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

Pull vfs updates from Al Viro:
 "All kinds of stuff this time around; some more notable parts:

   - RCU'd vfsmounts handling
   - new primitives for coredump handling
   - files_lock is gone
   - Bruce's delegations handling series
   - exportfs fixes

  plus misc stuff all over the place"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (101 commits)
  ecryptfs: ->f_op is never NULL
  locks: break delegations on any attribute modification
  locks: break delegations on link
  locks: break delegations on rename
  locks: helper functions for delegation breaking
  locks: break delegations on unlink
  namei: minor vfs_unlink cleanup
  locks: implement delegations
  locks: introduce new FL_DELEG lock flag
  vfs: take i_mutex on renamed file
  vfs: rename I_MUTEX_QUOTA now that it's not used for quotas
  vfs: don't use PARENT/CHILD lock classes for non-directories
  vfs: pull ext4's double-i_mutex-locking into common code
  exportfs: fix quadratic behavior in filehandle lookup
  exportfs: better variable name
  exportfs: move most of reconnect_path to helper function
  exportfs: eliminate unused "noprogress" counter
  exportfs: stop retrying once we race with rename/remove
  exportfs: clear DISCONNECTED on all parents sooner
  exportfs: more detailed comment for path_reconnect
  ...
diff --git a/CREDITS b/CREDITS
index 0640e16..b928516 100644
--- a/CREDITS
+++ b/CREDITS
@@ -3152,6 +3152,11 @@
 E: dipankar@in.ibm.com
 D: RCU
 
+N: Yoshinori Sato
+E: ysato@users.sourceforge.jp
+D: uClinux for Renesas H8/300 (H8300)
+D: http://uclinux-h8.sourceforge.jp/
+
 N: Hannu Savolainen
 E: hannu@opensound.com
 D: Maintainer of the sound drivers until 2.1.x days.
diff --git a/Documentation/ABI/stable/sysfs-bus-usb b/Documentation/ABI/stable/sysfs-bus-usb
index 2be603c..a6b6857 100644
--- a/Documentation/ABI/stable/sysfs-bus-usb
+++ b/Documentation/ABI/stable/sysfs-bus-usb
@@ -37,8 +37,8 @@
 		that the USB device has been connected to the machine.  This
 		file is read-only.
 Users:
-		PowerTOP <power@bughost.org>
-		http://www.lesswatts.org/projects/powertop/
+		PowerTOP <powertop@lists.01.org>
+		https://01.org/powertop/
 
 What:		/sys/bus/usb/device/.../power/active_duration
 Date:		January 2008
@@ -57,8 +57,8 @@
 		will give an integer percentage.  Note that this does not
 		account for counter wrap.
 Users:
-		PowerTOP <power@bughost.org>
-		http://www.lesswatts.org/projects/powertop/
+		PowerTOP <powertop@lists.01.org>
+		https://01.org/powertop/
 
 What:		/sys/bus/usb/devices/<busnum>-<port[.port]>...:<config num>-<interface num>/supports_autosuspend
 Date:		January 2008
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-mass-storage b/Documentation/ABI/testing/configfs-usb-gadget-mass-storage
new file mode 100644
index 0000000..ad72a37
--- /dev/null
+++ b/Documentation/ABI/testing/configfs-usb-gadget-mass-storage
@@ -0,0 +1,31 @@
+What:		/config/usb-gadget/gadget/functions/mass_storage.name
+Date:		Oct 2013
+KenelVersion:	3.13
+Description:
+		The attributes:
+
+		stall		- Set to permit function to halt bulk endpoints.
+				Disabled on some USB devices known not to work
+				correctly. You should set it to true.
+		num_buffers	- Number of pipeline buffers. Valid numbers
+				are 2..4. Available only if
+				CONFIG_USB_GADGET_DEBUG_FILES is set.
+
+What:		/config/usb-gadget/gadget/functions/mass_storage.name/lun.name
+Date:		Oct 2013
+KenelVersion:	3.13
+Description:
+		The attributes:
+
+		file		- The path to the backing file for the LUN.
+				Required if LUN is not marked as removable.
+		ro		- Flag specifying access to the LUN shall be
+				read-only. This is implied if CD-ROM emulation
+				is enabled as well as when it was impossible
+				to open "filename" in R/W mode.
+		removable	- Flag specifying that LUN shall be indicated as
+				being removable.
+		cdrom		- Flag specifying that LUN shall be reported as
+				being a CD-ROM.
+		nofua		- Flag specifying that FUA flag
+				in SCSI WRITE(10,12)
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index 39c8de0..b20e829 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -79,7 +79,7 @@
 		correspond to externally available input one of the named
 		versions may be used. The number must always be specified and
 		unique to allow association with event codes. Units after
-		application of scale and offset are microvolts.
+		application of scale and offset are millivolts.
 
 What:		/sys/bus/iio/devices/iio:deviceX/in_voltageY-voltageZ_raw
 KernelVersion:	2.6.35
@@ -90,7 +90,7 @@
 		physically equivalent inputs when non differential readings are
 		separately available. In differential only parts, then all that
 		is required is a consistent labeling.  Units after application
-		of scale and offset are microvolts.
+		of scale and offset are millivolts.
 
 What:		/sys/bus/iio/devices/iio:deviceX/in_capacitanceY_raw
 KernelVersion:	3.2
@@ -537,6 +537,62 @@
 		value is in raw device units or in processed units (as _raw
 		and _input do on sysfs direct channel read attributes).
 
+What:		/sys/.../events/in_accel_x_thresh_rising_hysteresis
+What:		/sys/.../events/in_accel_x_thresh_falling_hysteresis
+What:		/sys/.../events/in_accel_x_thresh_either_hysteresis
+What:		/sys/.../events/in_accel_y_thresh_rising_hysteresis
+What:		/sys/.../events/in_accel_y_thresh_falling_hysteresis
+What:		/sys/.../events/in_accel_y_thresh_either_hysteresis
+What:		/sys/.../events/in_accel_z_thresh_rising_hysteresis
+What:		/sys/.../events/in_accel_z_thresh_falling_hysteresis
+What:		/sys/.../events/in_accel_z_thresh_either_hysteresis
+What:		/sys/.../events/in_anglvel_x_thresh_rising_hysteresis
+What:		/sys/.../events/in_anglvel_x_thresh_falling_hysteresis
+What:		/sys/.../events/in_anglvel_x_thresh_either_hysteresis
+What:		/sys/.../events/in_anglvel_y_thresh_rising_hysteresis
+What:		/sys/.../events/in_anglvel_y_thresh_falling_hysteresis
+What:		/sys/.../events/in_anglvel_y_thresh_either_hysteresis
+What:		/sys/.../events/in_anglvel_z_thresh_rising_hysteresis
+What:		/sys/.../events/in_anglvel_z_thresh_falling_hysteresis
+What:		/sys/.../events/in_anglvel_z_thresh_either_hysteresis
+What:		/sys/.../events/in_magn_x_thresh_rising_hysteresis
+What:		/sys/.../events/in_magn_x_thresh_falling_hysteresis
+What:		/sys/.../events/in_magn_x_thresh_either_hysteresis
+What:		/sys/.../events/in_magn_y_thresh_rising_hysteresis
+What:		/sys/.../events/in_magn_y_thresh_falling_hysteresis
+What:		/sys/.../events/in_magn_y_thresh_either_hysteresis
+What:		/sys/.../events/in_magn_z_thresh_rising_hysteresis
+What:		/sys/.../events/in_magn_z_thresh_falling_hysteresis
+What:		/sys/.../events/in_magn_z_thresh_either_hysteresis
+What:		/sys/.../events/in_voltageY_thresh_rising_hysteresis
+What:		/sys/.../events/in_voltageY_thresh_falling_hysteresis
+What:		/sys/.../events/in_voltageY_thresh_either_hysteresis
+What:		/sys/.../events/in_tempY_thresh_rising_hysteresis
+What:		/sys/.../events/in_tempY_thresh_falling_hysteresis
+What:		/sys/.../events/in_tempY_thresh_either_hysteresis
+What:		/sys/.../events/in_illuminance0_thresh_falling_hysteresis
+what:		/sys/.../events/in_illuminance0_thresh_rising_hysteresis
+what:		/sys/.../events/in_illuminance0_thresh_either_hysteresis
+what:		/sys/.../events/in_proximity0_thresh_falling_hysteresis
+what:		/sys/.../events/in_proximity0_thresh_rising_hysteresis
+what:		/sys/.../events/in_proximity0_thresh_either_hysteresis
+KernelVersion:	3.13
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Specifies the hysteresis of threshold that the device is comparing
+		against for the events enabled by
+		<type>Y[_name]_thresh[_(rising|falling)]_hysteresis.
+		If separate attributes exist for the two directions, but
+		direction is not specified for this attribute, then a single
+		hysteresis value applies to both directions.
+		For falling events the hysteresis is added to the _value attribute for
+		this event to get the upper threshold for when the event goes back to
+		normal, for rising events the hysteresis is subtracted from the _value
+		attribute. E.g. if in_voltage0_raw_thresh_rising_value is set to 1200
+		and in_voltage0_raw_thresh_rising_hysteresis is set to 50. The event
+		will get activated once in_voltage0_raw goes above 1200 and will become
+		deactived again once the value falls below 1150.
+
 What:		/sys/.../events/in_accel_x_raw_roc_rising_value
 What:		/sys/.../events/in_accel_x_raw_roc_falling_value
 What:		/sys/.../events/in_accel_y_raw_roc_rising_value
@@ -811,3 +867,14 @@
 		Writing '1' stores the current device configuration into
 		on-chip EEPROM. After power-up or chip reset the device will
 		automatically load the saved configuration.
+
+What:		/sys/.../iio:deviceX/in_intensity_red_integration_time
+What:		/sys/.../iio:deviceX/in_intensity_green_integration_time
+What:		/sys/.../iio:deviceX/in_intensity_blue_integration_time
+What:		/sys/.../iio:deviceX/in_intensity_clear_integration_time
+What:		/sys/.../iio:deviceX/in_illuminance_integration_time
+KernelVersion:	3.12
+Contact:	linux-iio@vger.kernel.org
+Description:
+		This attribute is used to get/set the integration time in
+		seconds.
diff --git a/Documentation/ABI/testing/sysfs-class-mic.txt b/Documentation/ABI/testing/sysfs-class-mic.txt
new file mode 100644
index 0000000..13f48af
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-mic.txt
@@ -0,0 +1,157 @@
+What:		/sys/class/mic/
+Date:		October 2013
+KernelVersion:	3.13
+Contact:	Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+		The mic class directory belongs to Intel MIC devices and
+		provides information per MIC device. An Intel MIC device is a
+		PCIe form factor add-in Coprocessor card based on the Intel Many
+		Integrated Core (MIC) architecture that runs a Linux OS.
+
+What:		/sys/class/mic/mic(x)
+Date:		October 2013
+KernelVersion:	3.13
+Contact:	Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+		The directories /sys/class/mic/mic0, /sys/class/mic/mic1 etc.,
+		represent MIC devices (0,1,..etc). Each directory has
+		information specific to that MIC device.
+
+What:		/sys/class/mic/mic(x)/family
+Date:		October 2013
+KernelVersion:	3.13
+Contact:	Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+		Provides information about the Coprocessor family for an Intel
+		MIC device. For example - "x100"
+
+What:		/sys/class/mic/mic(x)/stepping
+Date:		October 2013
+KernelVersion:	3.13
+Contact:	Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+		Provides information about the silicon stepping for an Intel
+		MIC device. For example - "A0" or "B0"
+
+What:		/sys/class/mic/mic(x)/state
+Date:		October 2013
+KernelVersion:	3.13
+Contact:	Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+		When read, this entry provides the current state of an Intel
+		MIC device in the context of the card OS. Possible values that
+		will be read are:
+		"offline" - The MIC device is ready to boot the card OS. On
+		reading this entry after an OSPM resume, a "boot" has to be
+		written to this entry if the card was previously shutdown
+		during OSPM suspend.
+		"online" - The MIC device has initiated booting a card OS.
+		"shutting_down" - The card OS is shutting down.
+		"reset_failed" - The MIC device has failed to reset.
+		"suspending" - The MIC device is currently being prepared for
+		suspend. On reading this entry, a "suspend" has to be written
+		to the state sysfs entry to ensure the card is shutdown during
+		OSPM suspend.
+		"suspended" - The MIC device has been suspended.
+
+		When written, this sysfs entry triggers different state change
+		operations depending upon the current state of the card OS.
+		Acceptable values are:
+		"boot" - Boot the card OS image specified by the combination
+			 of firmware, ramdisk, cmdline and bootmode
+			sysfs entries.
+		"reset" - Initiates device reset.
+		"shutdown" - Initiates card OS shutdown.
+		"suspend" - Initiates card OS shutdown and also marks the card
+		as suspended.
+
+What:		/sys/class/mic/mic(x)/shutdown_status
+Date:		October 2013
+KernelVersion:	3.13
+Contact:	Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+		An Intel MIC device runs a Linux OS during its operation. This
+		OS can shutdown because of various reasons. When read, this
+		entry provides the status on why the card OS was shutdown.
+		Possible values are:
+		"nop" -  shutdown status is not applicable, when the card OS is
+			"online"
+		"crashed" - Shutdown because of a HW or SW crash.
+		"halted" - Shutdown because of a halt command.
+		"poweroff" - Shutdown because of a poweroff command.
+		"restart" - Shutdown because of a restart command.
+
+What:		/sys/class/mic/mic(x)/cmdline
+Date:		October 2013
+KernelVersion:	3.13
+Contact:	Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+		An Intel MIC device runs a Linux OS during its operation. Before
+		booting this card OS, it is possible to pass kernel command line
+		options to configure various features in it, similar to
+		self-bootable machines. When read, this entry provides
+		information about the current kernel command line options set to
+		boot the card OS. This entry can be written to change the
+		existing kernel command line options. Typically, the user would
+		want to read the current command line options, append new ones
+		or modify existing ones and then write the whole kernel command
+		line back to this entry.
+
+What:		/sys/class/mic/mic(x)/firmware
+Date:		October 2013
+KernelVersion:	3.13
+Contact:	Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+		When read, this sysfs entry provides the path name under
+		/lib/firmware/ where the firmware image to be booted on the
+		card can be found. The entry can be written to change the
+		firmware image location under /lib/firmware/.
+
+What:		/sys/class/mic/mic(x)/ramdisk
+Date:		October 2013
+KernelVersion:	3.13
+Contact:	Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+		When read, this sysfs entry provides the path name under
+		/lib/firmware/ where the ramdisk image to be used during card
+		OS boot can be found. The entry can be written to change
+		the ramdisk image location under /lib/firmware/.
+
+What:		/sys/class/mic/mic(x)/bootmode
+Date:		October 2013
+KernelVersion:	3.13
+Contact:	Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+		When read, this sysfs entry provides the current bootmode for
+		the card. This sysfs entry can be written with the following
+		valid strings:
+		a) linux - Boot a Linux image.
+		b) elf - Boot an elf image for flash updates.
+
+What:		/sys/class/mic/mic(x)/log_buf_addr
+Date:		October 2013
+KernelVersion:	3.13
+Contact:	Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+		An Intel MIC device runs a Linux OS during its operation. For
+		debugging purpose and early kernel boot messages, the user can
+		access the card OS log buffer via debugfs. When read, this entry
+		provides the kernel virtual address of the buffer where the card
+		OS log buffer can be read. This entry is written by the host
+		configuration daemon to set the log buffer address. The correct
+		log buffer address to be written can be found in the System.map
+		file of the card OS.
+
+What:		/sys/class/mic/mic(x)/log_buf_len
+Date:		October 2013
+KernelVersion:	3.13
+Contact:	Sudeep Dutt <sudeep.dutt@intel.com>
+Description:
+		An Intel MIC device runs a Linux OS during its operation. For
+		debugging purpose and early kernel boot messages, the user can
+		access the card OS log buffer via debugfs. When read, this entry
+		provides the kernel virtual address where the card OS log buffer
+		length can be read. This entry is written by host configuration
+		daemon to set the log buffer length address. The correct log
+		buffer length address to be written can be found in the
+		System.map file of the card OS.
diff --git a/Documentation/ABI/testing/sysfs-devices-power b/Documentation/ABI/testing/sysfs-devices-power
index 9d43e76..efe449b 100644
--- a/Documentation/ABI/testing/sysfs-devices-power
+++ b/Documentation/ABI/testing/sysfs-devices-power
@@ -1,6 +1,6 @@
 What:		/sys/devices/.../power/
 Date:		January 2009
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/devices/.../power directory contains attributes
 		allowing the user space to check and modify some power
@@ -8,7 +8,7 @@
 
 What:		/sys/devices/.../power/wakeup
 Date:		January 2009
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/devices/.../power/wakeup attribute allows the user
 		space to check if the device is enabled to wake up the system
@@ -34,7 +34,7 @@
 
 What:		/sys/devices/.../power/control
 Date:		January 2009
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/devices/.../power/control attribute allows the user
 		space to control the run-time power management of the device.
@@ -53,7 +53,7 @@
 
 What:		/sys/devices/.../power/async
 Date:		January 2009
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/devices/.../async attribute allows the user space to
 		enable or diasble the device's suspend and resume callbacks to
@@ -79,7 +79,7 @@
 
 What:		/sys/devices/.../power/wakeup_count
 Date:		September 2010
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/devices/.../wakeup_count attribute contains the number
 		of signaled wakeup events associated with the device.  This
@@ -88,7 +88,7 @@
 
 What:		/sys/devices/.../power/wakeup_active_count
 Date:		September 2010
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/devices/.../wakeup_active_count attribute contains the
 		number of times the processing of wakeup events associated with
@@ -98,7 +98,7 @@
 
 What:		/sys/devices/.../power/wakeup_abort_count
 Date:		February 2012
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/devices/.../wakeup_abort_count attribute contains the
 		number of times the processing of a wakeup event associated with
@@ -109,7 +109,7 @@
 
 What:		/sys/devices/.../power/wakeup_expire_count
 Date:		February 2012
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/devices/.../wakeup_expire_count attribute contains the
 		number of times a wakeup event associated with the device has
@@ -119,7 +119,7 @@
 
 What:		/sys/devices/.../power/wakeup_active
 Date:		September 2010
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/devices/.../wakeup_active attribute contains either 1,
 		or 0, depending on whether or not a wakeup event associated with
@@ -129,7 +129,7 @@
 
 What:		/sys/devices/.../power/wakeup_total_time_ms
 Date:		September 2010
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/devices/.../wakeup_total_time_ms attribute contains
 		the total time of processing wakeup events associated with the
@@ -139,7 +139,7 @@
 
 What:		/sys/devices/.../power/wakeup_max_time_ms
 Date:		September 2010
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/devices/.../wakeup_max_time_ms attribute contains
 		the maximum time of processing a single wakeup event associated
@@ -149,7 +149,7 @@
 
 What:		/sys/devices/.../power/wakeup_last_time_ms
 Date:		September 2010
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/devices/.../wakeup_last_time_ms attribute contains
 		the value of the monotonic clock corresponding to the time of
@@ -160,7 +160,7 @@
 
 What:		/sys/devices/.../power/wakeup_prevent_sleep_time_ms
 Date:		February 2012
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/devices/.../wakeup_prevent_sleep_time_ms attribute
 		contains the total time the device has been preventing
@@ -189,7 +189,7 @@
 
 What:		/sys/devices/.../power/pm_qos_latency_us
 Date:		March 2012
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/devices/.../power/pm_qos_resume_latency_us attribute
 		contains the PM QoS resume latency limit for the given device,
@@ -207,7 +207,7 @@
 
 What:		/sys/devices/.../power/pm_qos_no_power_off
 Date:		September 2012
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/devices/.../power/pm_qos_no_power_off attribute
 		is used for manipulating the PM QoS "no power off" flag.  If
@@ -222,7 +222,7 @@
 
 What:		/sys/devices/.../power/pm_qos_remote_wakeup
 Date:		September 2012
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/devices/.../power/pm_qos_remote_wakeup attribute
 		is used for manipulating the PM QoS "remote wakeup required"
diff --git a/Documentation/ABI/testing/sysfs-driver-sunxi-sid b/Documentation/ABI/testing/sysfs-driver-sunxi-sid
new file mode 100644
index 0000000..ffb9536
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-sunxi-sid
@@ -0,0 +1,22 @@
+What:		/sys/devices/*/<our-device>/eeprom
+Date:		August 2013
+Contact:	Oliver Schinagl <oliver@schinagl.nl>
+Description:	read-only access to the SID (Security-ID) on current
+		A-series SoC's from Allwinner. Currently supports A10, A10s, A13
+		and A20 CPU's. The earlier A1x series of SoCs exports 16 bytes,
+		whereas the newer A20 SoC exposes 512 bytes split into sections.
+		Besides the 16 bytes of SID, there's also an SJTAG area,
+		HDMI-HDCP key and some custom keys. Below a quick overview, for
+		details see the user manual:
+		0x000  128 bit root-key (sun[457]i)
+		0x010  128 bit boot-key (sun7i)
+		0x020   64 bit security-jtag-key (sun7i)
+		0x028   16 bit key configuration (sun7i)
+		0x02b   16 bit custom-vendor-key (sun7i)
+		0x02c  320 bit low general key (sun7i)
+		0x040   32 bit read-control access (sun7i)
+		0x064  224 bit low general key (sun7i)
+		0x080 2304 bit HDCP-key (sun7i)
+		0x1a0  768 bit high general key (sun7i)
+Users:		any user space application which wants to read the SID on
+		Allwinner's A-series of CPU's.
diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power
index 2177726..205a738 100644
--- a/Documentation/ABI/testing/sysfs-power
+++ b/Documentation/ABI/testing/sysfs-power
@@ -1,6 +1,6 @@
 What:		/sys/power/
 Date:		August 2006
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/power directory will contain files that will
 		provide a unified interface to the power management
@@ -8,7 +8,7 @@
 
 What:		/sys/power/state
 Date:		August 2006
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/power/state file controls the system power state.
 		Reading from this file returns what states are supported,
@@ -22,7 +22,7 @@
 
 What:		/sys/power/disk
 Date:		September 2006
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/power/disk file controls the operating mode of the
 		suspend-to-disk mechanism.  Reading from this file returns
@@ -67,7 +67,7 @@
 
 What:		/sys/power/image_size
 Date:		August 2006
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/power/image_size file controls the size of the image
 		created by the suspend-to-disk mechanism.  It can be written a
@@ -84,7 +84,7 @@
 
 What:		/sys/power/pm_trace
 Date:		August 2006
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/power/pm_trace file controls the code which saves the
 		last PM event point in the RTC across reboots, so that you can
@@ -133,7 +133,7 @@
 
 What:		/sys/power/pm_async
 Date:		January 2009
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/power/pm_async file controls the switch allowing the
 		user space to enable or disable asynchronous suspend and resume
@@ -146,7 +146,7 @@
 
 What:		/sys/power/wakeup_count
 Date:		July 2010
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/power/wakeup_count file allows user space to put the
 		system into a sleep state while taking into account the
@@ -161,7 +161,7 @@
 
 What:		/sys/power/reserved_size
 Date:		May 2011
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/power/reserved_size file allows user space to control
 		the amount of memory reserved for allocations made by device
@@ -175,7 +175,7 @@
 
 What:		/sys/power/autosleep
 Date:		April 2012
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/power/autosleep file can be written one of the strings
 		returned by reads from /sys/power/state.  If that happens, a
@@ -192,7 +192,7 @@
 
 What:		/sys/power/wake_lock
 Date:		February 2012
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/power/wake_lock file allows user space to create
 		wakeup source objects and activate them on demand (if one of
@@ -219,7 +219,7 @@
 
 What:		/sys/power/wake_unlock
 Date:		February 2012
-Contact:	Rafael J. Wysocki <rjw@sisk.pl>
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/power/wake_unlock file allows user space to deactivate
 		wakeup sources created with the help of /sys/power/wake_lock.
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
index fe397f9..6c9d9d3 100644
--- a/Documentation/DocBook/device-drivers.tmpl
+++ b/Documentation/DocBook/device-drivers.tmpl
@@ -87,7 +87,10 @@
 !Ekernel/printk/printk.c
 !Ekernel/panic.c
 !Ekernel/sys.c
-!Ekernel/rcupdate.c
+!Ekernel/rcu/srcu.c
+!Ekernel/rcu/tree.c
+!Ekernel/rcu/tree_plugin.h
+!Ekernel/rcu/update.c
      </sect1>
 
      <sect1><title>Device Resource Management</title>
diff --git a/Documentation/DocBook/filesystems.tmpl b/Documentation/DocBook/filesystems.tmpl
index 25b58ef..4f67683 100644
--- a/Documentation/DocBook/filesystems.tmpl
+++ b/Documentation/DocBook/filesystems.tmpl
@@ -91,7 +91,6 @@
      <title>The Filesystem for Exporting Kernel Objects</title>
 !Efs/sysfs/file.c
 !Efs/sysfs/symlink.c
-!Efs/sysfs/bin.c
   </chapter>
 
   <chapter id="debugfs">
diff --git a/Documentation/DocBook/genericirq.tmpl b/Documentation/DocBook/genericirq.tmpl
index d16d21b..46347f6 100644
--- a/Documentation/DocBook/genericirq.tmpl
+++ b/Documentation/DocBook/genericirq.tmpl
@@ -87,7 +87,7 @@
   <chapter id="rationale">
     <title>Rationale</title>
 	<para>
-	The original implementation of interrupt handling in Linux is using
+	The original implementation of interrupt handling in Linux uses
 	the __do_IRQ() super-handler, which is able to deal with every
 	type of interrupt logic.
 	</para>
@@ -111,19 +111,19 @@
 	</itemizedlist>
 	</para>
 	<para>
-	This split implementation of highlevel IRQ handlers allows us to
+	This split implementation of high-level IRQ handlers allows us to
 	optimize the flow of the interrupt handling for each specific
-	interrupt type. This reduces complexity in that particular codepath
+	interrupt type. This reduces complexity in that particular code path
 	and allows the optimized handling of a given type.
 	</para>
 	<para>
 	The original general IRQ implementation used hw_interrupt_type
 	structures and their ->ack(), ->end() [etc.] callbacks to
 	differentiate the flow control in the super-handler. This leads to
-	a mix of flow logic and lowlevel hardware logic, and it also leads
-	to unnecessary code duplication: for example in i386, there is a
-	ioapic_level_irq and a ioapic_edge_irq irq-type which share many
-	of the lowlevel details but have different flow handling.
+	a mix of flow logic and low-level hardware logic, and it also leads
+	to unnecessary code duplication: for example in i386, there is an
+	ioapic_level_irq and an ioapic_edge_irq IRQ-type which share many
+	of the low-level details but have different flow handling.
 	</para>
 	<para>
 	A more natural abstraction is the clean separation of the
@@ -132,23 +132,23 @@
 	<para>
 	Analysing a couple of architecture's IRQ subsystem implementations
 	reveals that most of them can use a generic set of 'irq flow'
-	methods and only need to add the chip level specific code.
+	methods and only need to add the chip-level specific code.
 	The separation is also valuable for (sub)architectures
-	which need specific quirks in the irq flow itself but not in the
-	chip-details - and thus provides a more transparent IRQ subsystem
+	which need specific quirks in the IRQ flow itself but not in the
+	chip details - and thus provides a more transparent IRQ subsystem
 	design.
 	</para>
 	<para>
-	Each interrupt descriptor is assigned its own highlevel flow
+	Each interrupt descriptor is assigned its own high-level flow
 	handler, which is normally one of the generic
-	implementations. (This highlevel flow handler implementation also
+	implementations. (This high-level flow handler implementation also
 	makes it simple to provide demultiplexing handlers which can be
 	found in embedded platforms on various architectures.)
 	</para>
 	<para>
 	The separation makes the generic interrupt handling layer more
 	flexible and extensible. For example, an (sub)architecture can
-	use a generic irq-flow implementation for 'level type' interrupts
+	use a generic IRQ-flow implementation for 'level type' interrupts
 	and add a (sub)architecture specific 'edge type' implementation.
 	</para>
 	<para>
@@ -172,9 +172,9 @@
     <para>
 	There are three main levels of abstraction in the interrupt code:
 	<orderedlist>
-	  <listitem><para>Highlevel driver API</para></listitem>
-	  <listitem><para>Highlevel IRQ flow handlers</para></listitem>
-	  <listitem><para>Chiplevel hardware encapsulation</para></listitem>
+	  <listitem><para>High-level driver API</para></listitem>
+	  <listitem><para>High-level IRQ flow handlers</para></listitem>
+	  <listitem><para>Chip-level hardware encapsulation</para></listitem>
 	</orderedlist>
     </para>
     <sect1 id="Interrupt_control_flow">
@@ -189,16 +189,16 @@
 	which are assigned to this interrupt.
 	</para>
 	<para>
-	Whenever an interrupt triggers, the lowlevel arch code calls into
-	the generic interrupt code by calling desc->handle_irq().
-	This highlevel IRQ handling function only uses desc->irq_data.chip
+	Whenever an interrupt triggers, the low-level architecture code calls
+	into the generic interrupt code by calling desc->handle_irq().
+	This high-level IRQ handling function only uses desc->irq_data.chip
 	primitives referenced by the assigned chip descriptor structure.
 	</para>
     </sect1>
     <sect1 id="Highlevel_Driver_API">
-	<title>Highlevel Driver API</title>
+	<title>High-level Driver API</title>
 	<para>
-	  The highlevel Driver API consists of following functions:
+	  The high-level Driver API consists of following functions:
 	  <itemizedlist>
 	  <listitem><para>request_irq()</para></listitem>
 	  <listitem><para>free_irq()</para></listitem>
@@ -216,7 +216,7 @@
 	</para>
     </sect1>
     <sect1 id="Highlevel_IRQ_flow_handlers">
-	<title>Highlevel IRQ flow handlers</title>
+	<title>High-level IRQ flow handlers</title>
 	<para>
 	  The generic layer provides a set of pre-defined irq-flow methods:
 	  <itemizedlist>
@@ -228,7 +228,7 @@
 	  <listitem><para>handle_edge_eoi_irq</para></listitem>
 	  <listitem><para>handle_bad_irq</para></listitem>
 	  </itemizedlist>
-	  The interrupt flow handlers (either predefined or architecture
+	  The interrupt flow handlers (either pre-defined or architecture
 	  specific) are assigned to specific interrupts by the architecture
 	  either during bootup or during device initialization.
 	</para>
@@ -297,7 +297,7 @@
 		<para>
 		handle_fasteoi_irq provides a generic implementation
 		for interrupts, which only need an EOI at the end of
-		the handler
+		the handler.
 		</para>
 		<para>
 		The following control flow is implemented (simplified excerpt):
@@ -394,7 +394,7 @@
 	The generic functions are intended for 'clean' architectures and chips,
 	which have no platform-specific IRQ handling quirks. If an architecture
 	needs to implement quirks on the 'flow' level then it can do so by
-	overriding the highlevel irq-flow handler.
+	overriding the high-level irq-flow handler.
 	</para>
 	</sect2>
 	<sect2 id="Delayed_interrupt_disable">
@@ -419,9 +419,9 @@
 	</sect2>
     </sect1>
     <sect1 id="Chiplevel_hardware_encapsulation">
-	<title>Chiplevel hardware encapsulation</title>
+	<title>Chip-level hardware encapsulation</title>
 	<para>
-	The chip level hardware descriptor structure irq_chip
+	The chip-level hardware descriptor structure irq_chip
 	contains all the direct chip relevant functions, which
 	can be utilized by the irq flow implementations.
 	  <itemizedlist>
@@ -429,14 +429,14 @@
 	  <listitem><para>irq_mask_ack() - Optional, recommended for performance</para></listitem>
 	  <listitem><para>irq_mask()</para></listitem>
 	  <listitem><para>irq_unmask()</para></listitem>
-	  <listitem><para>irq_eoi() - Optional, required for eoi flow handlers</para></listitem>
+	  <listitem><para>irq_eoi() - Optional, required for EOI flow handlers</para></listitem>
 	  <listitem><para>irq_retrigger() - Optional</para></listitem>
 	  <listitem><para>irq_set_type() - Optional</para></listitem>
 	  <listitem><para>irq_set_wake() - Optional</para></listitem>
 	  </itemizedlist>
 	These primitives are strictly intended to mean what they say: ack means
 	ACK, masking means masking of an IRQ line, etc. It is up to the flow
-	handler(s) to use these basic units of lowlevel functionality.
+	handler(s) to use these basic units of low-level functionality.
 	</para>
     </sect1>
   </chapter>
@@ -445,7 +445,7 @@
      <title>__do_IRQ entry point</title>
      <para>
 	The original implementation __do_IRQ() was an alternative entry
-	point for all types of interrupts. It not longer exists.
+	point for all types of interrupts. It no longer exists.
      </para>
      <para>
 	This handler turned out to be not suitable for all
@@ -468,11 +468,11 @@
   <chapter id="genericchip">
      <title>Generic interrupt chip</title>
      <para>
-       To avoid copies of identical implementations of irq chips the
+       To avoid copies of identical implementations of IRQ chips the
        core provides a configurable generic interrupt chip
        implementation. Developers should check carefuly whether the
        generic chip fits their needs before implementing the same
-       functionality slightly different themself.
+       functionality slightly differently themselves.
      </para>
 !Ekernel/irq/generic-chip.c
   </chapter>
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
index 7703ec7..9126619 100644
--- a/Documentation/RCU/checklist.txt
+++ b/Documentation/RCU/checklist.txt
@@ -202,8 +202,8 @@
 	updater uses call_rcu_sched() or synchronize_sched(), then
 	the corresponding readers must disable preemption, possibly
 	by calling rcu_read_lock_sched() and rcu_read_unlock_sched().
-	If the updater uses synchronize_srcu() or call_srcu(),
-	the the corresponding readers must use srcu_read_lock() and
+	If the updater uses synchronize_srcu() or call_srcu(), then
+	the corresponding readers must use srcu_read_lock() and
 	srcu_read_unlock(), and with the same srcu_struct.  The rules for
 	the expedited primitives are the same as for their non-expedited
 	counterparts.  Mixing things up will result in confusion and
diff --git a/Documentation/RCU/stallwarn.txt b/Documentation/RCU/stallwarn.txt
index 8e9359d..6f3a005 100644
--- a/Documentation/RCU/stallwarn.txt
+++ b/Documentation/RCU/stallwarn.txt
@@ -12,12 +12,12 @@
 	This kernel configuration parameter defines the period of time
 	that RCU will wait from the beginning of a grace period until it
 	issues an RCU CPU stall warning.  This time period is normally
-	sixty seconds.
+	21 seconds.
 
 	This configuration parameter may be changed at runtime via the
 	/sys/module/rcutree/parameters/rcu_cpu_stall_timeout, however
 	this parameter is checked only at the beginning of a cycle.
-	So if you are 30 seconds into a 70-second stall, setting this
+	So if you are 10 seconds into a 40-second stall, setting this
 	sysfs parameter to (say) five will shorten the timeout for the
 	-next- stall, or the following warning for the current stall
 	(assuming the stall lasts long enough).  It will not affect the
@@ -32,7 +32,7 @@
 	also dump the stacks of any tasks that are blocking the current
 	RCU-preempt grace period.
 
-RCU_CPU_STALL_INFO
+CONFIG_RCU_CPU_STALL_INFO
 
 	This kernel configuration parameter causes the stall warning to
 	print out additional per-CPU diagnostic information, including
@@ -43,7 +43,8 @@
 	Although the lockdep facility is extremely useful, it does add
 	some overhead.  Therefore, under CONFIG_PROVE_RCU, the
 	RCU_STALL_DELAY_DELTA macro allows five extra seconds before
-	giving an RCU CPU stall warning message.
+	giving an RCU CPU stall warning message.  (This is a cpp
+	macro, not a kernel configuration parameter.)
 
 RCU_STALL_RAT_DELAY
 
@@ -52,7 +53,8 @@
 	However, if the offending CPU does not detect its own stall in
 	the number of jiffies specified by RCU_STALL_RAT_DELAY, then
 	some other CPU will complain.  This delay is normally set to
-	two jiffies.
+	two jiffies.  (This is a cpp macro, not a kernel configuration
+	parameter.)
 
 When a CPU detects that it is stalling, it will print a message similar
 to the following:
@@ -86,7 +88,12 @@
 
 INFO: rcu_bh_state detected stalls on CPUs/tasks: { } (detected by 4, 2502 jiffies)
 
-This is rare, but does happen from time to time in real life.
+This is rare, but does happen from time to time in real life.  It is also
+possible for a zero-jiffy stall to be flagged in this case, depending
+on how the stall warning and the grace-period initialization happen to
+interact.  Please note that it is not possible to entirely eliminate this
+sort of false positive without resorting to things like stop_machine(),
+which is overkill for this sort of problem.
 
 If the CONFIG_RCU_CPU_STALL_INFO kernel configuration parameter is set,
 more information is printed with the stall-warning message, for example:
@@ -216,4 +223,5 @@
 If you can reliably trigger the stall, ftrace can be quite helpful.
 
 RCU bugs can often be debugged with the help of CONFIG_RCU_TRACE
-and with RCU's event tracing.
+and with RCU's event tracing.  For information on RCU's event tracing,
+see include/trace/events/rcu.h.
diff --git a/Documentation/acpi/dsdt-override.txt b/Documentation/acpi/dsdt-override.txt
index febbb1b..784841c 100644
--- a/Documentation/acpi/dsdt-override.txt
+++ b/Documentation/acpi/dsdt-override.txt
@@ -4,4 +4,4 @@
 
 When to use this method is described in detail on the
 Linux/ACPI home page:
-http://www.lesswatts.org/projects/acpi/overridingDSDT.php
+https://01.org/linux-acpi/documentation/overriding-dsdt
diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt
index aca4e69..b994bcb 100644
--- a/Documentation/acpi/enumeration.txt
+++ b/Documentation/acpi/enumeration.txt
@@ -295,10 +295,6 @@
 specifies the path to the controller. In order to use these GPIOs in Linux
 we need to translate them to the Linux GPIO numbers.
 
-The driver can do this by including <linux/acpi_gpio.h> and then calling
-acpi_get_gpio(path, gpio). This will return the Linux GPIO number or
-negative errno if there was no translation found.
-
 In a simple case of just getting the Linux GPIO number from device
 resources one can use acpi_get_gpio_by_index() helper function. It takes
 pointer to the device and index of the GpioIo/GpioInt descriptor in the
@@ -322,3 +318,25 @@
 
 In case of GpioInt resource an additional call to gpio_to_irq() must be
 done before calling request_irq().
+
+Note that the above API is ACPI specific and not recommended for drivers
+that need to support non-ACPI systems. The recommended way is to use
+the descriptor based GPIO interfaces. The above example looks like this
+when converted to the GPIO desc:
+
+	#include <linux/gpio/consumer.h>
+	...
+
+	struct gpio_desc *irq_desc, *power_desc;
+
+	irq_desc = gpiod_get_index(dev, NULL, 1);
+	if (IS_ERR(irq_desc))
+		/* handle error */
+
+	power_desc = gpiod_get_index(dev, NULL, 0);
+	if (IS_ERR(power_desc))
+		/* handle error */
+
+	/* Now we can use the GPIO descriptors */
+
+See also Documentation/gpio.txt.
diff --git a/Documentation/arm/Marvell/README b/Documentation/arm/Marvell/README
index 8f08a86e0..da0151d 100644
--- a/Documentation/arm/Marvell/README
+++ b/Documentation/arm/Marvell/README
@@ -88,6 +88,7 @@
         MV78230
         MV78260
         MV78460
+    NOTE: not to be confused with the non-SMP 78xx0 SoCs
 
   Product Brief: http://www.marvell.com/embedded-processors/armada-xp/assets/Marvell-ArmadaXP-SoC-product%20brief.pdf
   No public datasheet available.
diff --git a/Documentation/arm/sunxi/README b/Documentation/arm/sunxi/README
index e3f93fb..7945238 100644
--- a/Documentation/arm/sunxi/README
+++ b/Documentation/arm/sunxi/README
@@ -10,6 +10,10 @@
   Linux kernel mach directory: arch/arm/mach-sunxi
 
   Flavors:
+    * ARM926 based SoCs
+      - Allwinner F20 (sun3i)
+        + Not Supported
+
     * ARM Cortex-A8 based SoCs
       - Allwinner A10 (sun4i)
         + Datasheet
@@ -25,4 +29,24 @@
         + Datasheet
 	  http://dl.linux-sunxi.org/A13/A13%20Datasheet%20-%20v1.12%20%282012-03-29%29.pdf
         + User Manual
-	  http://dl.linux-sunxi.org/A13/A13%20User%20Manual%20-%20v1.2%20%282013-08-08%29.pdf
+          http://dl.linux-sunxi.org/A13/A13%20User%20Manual%20-%20v1.2%20%282013-01-08%29.pdf
+
+    * Dual ARM Cortex-A7 based SoCs
+      - Allwinner A20 (sun7i)
+        + User Manual
+          http://dl.linux-sunxi.org/A20/A20%20User%20Manual%202013-03-22.pdf
+
+      - Allwinner A23
+        + Not Supported
+
+    * Quad ARM Cortex-A7 based SoCs
+      - Allwinner A31 (sun6i)
+        + Datasheet
+          http://dl.linux-sunxi.org/A31/A31%20Datasheet%20-%20v1.00%20(2012-12-24).pdf
+
+      - Allwinner A31s (sun6i)
+        + Not Supported
+
+    * Quad ARM Cortex-A15, Quad ARM Cortex-A7 based SoCs
+      - Allwinner A80
+        + Not Supported
\ No newline at end of file
diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt
index 98df4a0..a9691cc 100644
--- a/Documentation/arm64/booting.txt
+++ b/Documentation/arm64/booting.txt
@@ -115,9 +115,10 @@
   External caches (if present) must be configured and disabled.
 
 - Architected timers
-  CNTFRQ must be programmed with the timer frequency.
-  If entering the kernel at EL1, CNTHCTL_EL2 must have EL1PCTEN (bit 0)
-  set where available.
+  CNTFRQ must be programmed with the timer frequency and CNTVOFF must
+  be programmed with a consistent value on all CPUs.  If entering the
+  kernel at EL1, CNTHCTL_EL2 must have EL1PCTEN (bit 0) set where
+  available.
 
 - Coherency
   All CPUs to be booted by the kernel must be part of the same coherency
@@ -130,30 +131,46 @@
   the kernel image will be entered must be initialised by software at a
   higher exception level to prevent execution in an UNKNOWN state.
 
+The requirements described above for CPU mode, caches, MMUs, architected
+timers, coherency and system registers apply to all CPUs.  All CPUs must
+enter the kernel in the same exception level.
+
 The boot loader is expected to enter the kernel on each CPU in the
 following manner:
 
 - The primary CPU must jump directly to the first instruction of the
   kernel image.  The device tree blob passed by this CPU must contain
-  for each CPU node:
-
-    1. An 'enable-method' property. Currently, the only supported value
-       for this field is the string "spin-table".
-
-    2. A 'cpu-release-addr' property identifying a 64-bit,
-       zero-initialised memory location.
+  an 'enable-method' property for each cpu node.  The supported
+  enable-methods are described below.
 
   It is expected that the bootloader will generate these device tree
   properties and insert them into the blob prior to kernel entry.
 
-- Any secondary CPUs must spin outside of the kernel in a reserved area
-  of memory (communicated to the kernel by a /memreserve/ region in the
+- CPUs with a "spin-table" enable-method must have a 'cpu-release-addr'
+  property in their cpu node.  This property identifies a
+  naturally-aligned 64-bit zero-initalised memory location.
+
+  These CPUs should spin outside of the kernel in a reserved area of
+  memory (communicated to the kernel by a /memreserve/ region in the
   device tree) polling their cpu-release-addr location, which must be
   contained in the reserved region.  A wfe instruction may be inserted
   to reduce the overhead of the busy-loop and a sev will be issued by
   the primary CPU.  When a read of the location pointed to by the
-  cpu-release-addr returns a non-zero value, the CPU must jump directly
-  to this value.
+  cpu-release-addr returns a non-zero value, the CPU must jump to this
+  value.  The value will be written as a single 64-bit little-endian
+  value, so CPUs must convert the read value to their native endianness
+  before jumping to it.
+
+- CPUs with a "psci" enable method should remain outside of
+  the kernel (i.e. outside of the regions of memory described to the
+  kernel in the memory node, or in a reserved area of memory described
+  to the kernel by a /memreserve/ region in the device tree).  The
+  kernel will issue CPU_ON calls as described in ARM document number ARM
+  DEN 0022A ("Power State Coordination Interface System Software on ARM
+  processors") to bring CPUs into the kernel.
+
+  The device tree should contain a 'psci' node, as described in
+  Documentation/devicetree/bindings/arm/psci.txt.
 
 - Secondary CPU general-purpose register settings
   x0 = 0 (reserved for future use)
diff --git a/Documentation/arm64/memory.txt b/Documentation/arm64/memory.txt
index 78a37712..5e054bf 100644
--- a/Documentation/arm64/memory.txt
+++ b/Documentation/arm64/memory.txt
@@ -21,7 +21,7 @@
 TTBR0.
 
 
-AArch64 Linux memory layout:
+AArch64 Linux memory layout with 4KB pages:
 
 Start			End			Size		Use
 -----------------------------------------------------------------------
@@ -39,13 +39,38 @@
 
 ffffffbffbe00000	ffffffbffbe0ffff	  64KB		PCI I/O space
 
-ffffffbbffff0000	ffffffbcffffffff	  ~2MB		[guard]
+ffffffbffbe10000	ffffffbcffffffff	  ~2MB		[guard]
 
 ffffffbffc000000	ffffffbfffffffff	  64MB		modules
 
 ffffffc000000000	ffffffffffffffff	 256GB		kernel logical memory map
 
 
+AArch64 Linux memory layout with 64KB pages:
+
+Start			End			Size		Use
+-----------------------------------------------------------------------
+0000000000000000	000003ffffffffff	   4TB		user
+
+fffffc0000000000	fffffdfbfffeffff	  ~2TB		vmalloc
+
+fffffdfbffff0000	fffffdfbffffffff	  64KB		[guard page]
+
+fffffdfc00000000	fffffdfdffffffff	   8GB		vmemmap
+
+fffffdfe00000000	fffffdfffbbfffff	  ~8GB		[guard, future vmmemap]
+
+fffffdfffbc00000	fffffdfffbdfffff	   2MB		earlyprintk device
+
+fffffdfffbe00000	fffffdfffbe0ffff	  64KB		PCI I/O space
+
+fffffdfffbe10000	fffffdfffbffffff	  ~2MB		[guard]
+
+fffffdfffc000000	fffffdffffffffff	  64MB		modules
+
+fffffe0000000000	ffffffffffffffff	   2TB		kernel logical memory map
+
+
 Translation table lookup with 4KB pages:
 
 +--------+--------+--------+--------+--------+--------+--------+--------+
diff --git a/Documentation/connector/ucon.c b/Documentation/connector/ucon.c
index 4848db8..8a4da64 100644
--- a/Documentation/connector/ucon.c
+++ b/Documentation/connector/ucon.c
@@ -71,7 +71,7 @@
 	nlh->nlmsg_seq = seq++;
 	nlh->nlmsg_pid = getpid();
 	nlh->nlmsg_type = NLMSG_DONE;
-	nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh));
+	nlh->nlmsg_len = size;
 	nlh->nlmsg_flags = 0;
 
 	m = NLMSG_DATA(nlh);
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index 23721d3..80b7241 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -414,6 +414,7 @@
 		200 = /dev/net/tun	TAP/TUN network device
 		201 = /dev/button/gulpb	Transmeta GULP-B buttons
 		202 = /dev/emd/ctl	Enhanced Metadisk RAID (EMD) control
+		203 = /dev/cuse		Cuse (character device in user-space)
 		204 = /dev/video/em8300		EM8300 DVD decoder control
 		205 = /dev/video/em8300_mv	EM8300 DVD decoder video
 		206 = /dev/video/em8300_ma	EM8300 DVD decoder audio
diff --git a/Documentation/devicetree/bindings/arm/arm-boards b/Documentation/devicetree/bindings/arm/arm-boards
index db5858e..5fac246 100644
--- a/Documentation/devicetree/bindings/arm/arm-boards
+++ b/Documentation/devicetree/bindings/arm/arm-boards
@@ -9,9 +9,53 @@
 
 FPGA type interrupt controllers, see the versatile-fpga-irq binding doc.
 
-In the root node the Integrator/CP must have a /cpcon node pointing
-to the CP control registers, and the Integrator/AP must have a
-/syscon node pointing to the Integrator/AP system controller.
+Required nodes:
+
+- core-module: the root node to the Integrator platforms must have
+  a core-module with regs and the compatible string
+  "arm,core-module-integrator"
+
+  Required properties for the core module:
+  - regs: the location and size of the core module registers, one
+    range of 0x200 bytes.
+
+- syscon: the root node of the Integrator platforms must have a
+  system controller node pointong to the control registers,
+  with the compatible string
+  "arm,integrator-ap-syscon"
+  "arm,integrator-cp-syscon"
+  respectively.
+
+  Required properties for the system controller:
+  - regs: the location and size of the system controller registers,
+    one range of 0x100 bytes.
+
+  Required properties for the AP system controller:
+  - interrupts: the AP syscon node must include the logical module
+    interrupts, stated in order of module instance <module 0>,
+    <module 1>, <module 2> ... for the CP system controller this
+    is not required not of any use.
+
+/dts-v1/;
+/include/ "integrator.dtsi"
+
+/ {
+	model = "ARM Integrator/AP";
+	compatible = "arm,integrator-ap";
+
+	core-module@10000000 {
+		compatible = "arm,core-module-integrator";
+		reg = <0x10000000 0x200>;
+	};
+
+	syscon {
+		compatible = "arm,integrator-ap-syscon";
+		reg = <0x11000000 0x100>;
+		interrupt-parent = <&pic>;
+		/* These are the logic module IRQs */
+		interrupts = <9>, <10>, <11>, <12>;
+	};
+};
 
 
 ARM Versatile Application and Platform Baseboards
diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
index 61df564..d74091a 100644
--- a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
+++ b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
@@ -4,6 +4,8 @@
 Required properties:
 - compatible: Should be "marvell,mpic"
 - interrupt-controller: Identifies the node as an interrupt controller.
+- msi-controller: Identifies the node as an PCI Message Signaled
+  Interrupt controller.
 - #interrupt-cells: The number of cells to define the interrupts. Should be 1.
   The cell is the IRQ number
 
@@ -24,6 +26,7 @@
               #address-cells = <1>;
               #size-cells = <1>;
               interrupt-controller;
+              msi-controller;
               reg = <0xd0020a00 0x1d0>,
                     <0xd0021070 0x58>;
         };
diff --git a/Documentation/devicetree/bindings/arm/atmel-adc.txt b/Documentation/devicetree/bindings/arm/atmel-adc.txt
index 723c205..d106146 100644
--- a/Documentation/devicetree/bindings/arm/atmel-adc.txt
+++ b/Documentation/devicetree/bindings/arm/atmel-adc.txt
@@ -7,7 +7,6 @@
   - interrupts: Should contain the IRQ line for the ADC
   - atmel,adc-channels-used: Bitmask of the channels muxed and enable for this
     device
-  - atmel,adc-num-channels: Number of channels available in the ADC
   - atmel,adc-startup-time: Startup Time of the ADC in microseconds as
     defined in the datasheet
   - atmel,adc-vref: Reference voltage in millivolts for the conversions
@@ -24,6 +23,13 @@
 		       resolution will be used.
   - atmel,adc-sleep-mode: Boolean to enable sleep mode when no conversion
   - atmel,adc-sample-hold-time: Sample and Hold Time in microseconds
+  - atmel,adc-ts-wires: Number of touch screen wires. Should be 4 or 5. If this
+                        value is set, then adc driver will enable touch screen
+                        support.
+    NOTE: when adc touch screen enabled, the adc hardware trigger will be
+          disabled. Since touch screen will occupied the trigger register.
+  - atmel,adc-ts-pressure-threshold: a pressure threshold for touchscreen. It
+                                     make touch detect more precision.
  
 Optional trigger Nodes:
   - Required properties:
diff --git a/Documentation/devicetree/bindings/arm/cci.txt b/Documentation/devicetree/bindings/arm/cci.txt
index 92d36e2..f28d82b 100644
--- a/Documentation/devicetree/bindings/arm/cci.txt
+++ b/Documentation/devicetree/bindings/arm/cci.txt
@@ -36,14 +36,18 @@
 
 	- reg
 		Usage: required
-		Value type: <prop-encoded-array>
+		Value type: Integer cells. A register entry, expressed as a pair
+			    of cells, containing base and size.
 		Definition: A standard property. Specifies base physical
 			    address of CCI control registers common to all
 			    interfaces.
 
 	- ranges:
 		Usage: required
-		Value type: <prop-encoded-array>
+		Value type: Integer cells. An array of range entries, expressed
+			    as a tuple of cells, containing child address,
+			    parent address and the size of the region in the
+			    child address space.
 		Definition: A standard property. Follow rules in the ePAPR for
 			    hierarchical bus addressing. CCI interfaces
 			    addresses refer to the parent node addressing
@@ -74,11 +78,49 @@
 
 		- reg:
 			Usage: required
-			Value type: <prop-encoded-array>
+			Value type: Integer cells. A register entry, expressed
+				    as a pair of cells, containing base and
+				    size.
 			Definition: the base address and size of the
 				    corresponding interface programming
 				    registers.
 
+	- CCI PMU node
+
+		Parent node must be CCI interconnect node.
+
+		A CCI pmu node must contain the following properties:
+
+		- compatible
+			Usage: required
+			Value type: <string>
+			Definition: must be "arm,cci-400-pmu"
+
+		- reg:
+			Usage: required
+			Value type: Integer cells. A register entry, expressed
+				    as a pair of cells, containing base and
+				    size.
+			Definition: the base address and size of the
+				    corresponding interface programming
+				    registers.
+
+		- interrupts:
+			Usage: required
+			Value type: Integer cells. Array of interrupt specifier
+				    entries, as defined in
+				    ../interrupt-controller/interrupts.txt.
+			Definition: list of counter overflow interrupts, one per
+				    counter. The interrupts must be specified
+				    starting with the cycle counter overflow
+				    interrupt, followed by counter0 overflow
+				    interrupt, counter1 overflow interrupt,...
+				    ,counterN overflow interrupt.
+
+				    The CCI PMU has an interrupt signal for each
+				    counter. The number of interrupts must be
+				    equal to the number of counters.
+
 * CCI interconnect bus masters
 
 	Description: masters in the device tree connected to a CCI port
@@ -144,7 +186,7 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		reg = <0x0 0x2c090000 0 0x1000>;
-		ranges = <0x0 0x0 0x2c090000 0x6000>;
+		ranges = <0x0 0x0 0x2c090000 0x10000>;
 
 		cci_control0: slave-if@1000 {
 			compatible = "arm,cci-400-ctrl-if";
@@ -163,6 +205,16 @@
 			interface-type = "ace";
 			reg = <0x5000 0x1000>;
 		};
+
+		pmu@9000 {
+			 compatible = "arm,cci-400-pmu";
+			 reg = <0x9000 0x5000>;
+			 interrupts = <0 101 4>,
+				      <0 102 4>,
+				      <0 103 4>,
+				      <0 104 4>,
+				      <0 105 4>;
+		};
 	};
 
 This CCI node corresponds to a CCI component whose control registers sits
diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
index f32494d..9130435 100644
--- a/Documentation/devicetree/bindings/arm/cpus.txt
+++ b/Documentation/devicetree/bindings/arm/cpus.txt
@@ -1,77 +1,384 @@
-* ARM CPUs binding description
+=================
+ARM CPUs bindings
+=================
 
 The device tree allows to describe the layout of CPUs in a system through
 the "cpus" node, which in turn contains a number of subnodes (ie "cpu")
 defining properties for every cpu.
 
-Bindings for CPU nodes follow the ePAPR standard, available from:
+Bindings for CPU nodes follow the ePAPR v1.1 standard, available from:
 
-http://devicetree.org
+https://www.power.org/documentation/epapr-version-1-1/
 
-For the ARM architecture every CPU node must contain the following properties:
+with updates for 32-bit and 64-bit ARM systems provided in this document.
 
-- device_type:	must be "cpu"
-- reg:		property matching the CPU MPIDR[23:0] register bits
-		reg[31:24] bits must be set to 0
-- compatible:	should be one of:
-		"arm,arm1020"
-		"arm,arm1020e"
-		"arm,arm1022"
-		"arm,arm1026"
-		"arm,arm720"
-		"arm,arm740"
-		"arm,arm7tdmi"
-		"arm,arm920"
-		"arm,arm922"
-		"arm,arm925"
-		"arm,arm926"
-		"arm,arm940"
-		"arm,arm946"
-		"arm,arm9tdmi"
-		"arm,cortex-a5"
-		"arm,cortex-a7"
-		"arm,cortex-a8"
-		"arm,cortex-a9"
-		"arm,cortex-a15"
-		"arm,arm1136"
-		"arm,arm1156"
-		"arm,arm1176"
-		"arm,arm11mpcore"
-		"faraday,fa526"
-		"intel,sa110"
-		"intel,sa1100"
-		"marvell,feroceon"
-		"marvell,mohawk"
-		"marvell,xsc3"
-		"marvell,xscale"
+================================
+Convention used in this document
+================================
 
-Example:
+This document follows the conventions described in the ePAPR v1.1, with
+the addition:
+
+- square brackets define bitfields, eg reg[7:0] value of the bitfield in
+  the reg property contained in bits 7 down to 0
+
+=====================================
+cpus and cpu node bindings definition
+=====================================
+
+The ARM architecture, in accordance with the ePAPR, requires the cpus and cpu
+nodes to be present and contain the properties described below.
+
+- cpus node
+
+	Description: Container of cpu nodes
+
+	The node name must be "cpus".
+
+	A cpus node must define the following properties:
+
+	- #address-cells
+		Usage: required
+		Value type: <u32>
+
+		Definition depends on ARM architecture version and
+		configuration:
+
+			# On uniprocessor ARM architectures previous to v7
+			  value must be 1, to enable a simple enumeration
+			  scheme for processors that do not have a HW CPU
+			  identification register.
+			# On 32-bit ARM 11 MPcore, ARM v7 or later systems
+			  value must be 1, that corresponds to CPUID/MPIDR
+			  registers sizes.
+			# On ARM v8 64-bit systems value should be set to 2,
+			  that corresponds to the MPIDR_EL1 register size.
+			  If MPIDR_EL1[63:32] value is equal to 0 on all CPUs
+			  in the system, #address-cells can be set to 1, since
+			  MPIDR_EL1[63:32] bits are not used for CPUs
+			  identification.
+	- #size-cells
+		Usage: required
+		Value type: <u32>
+		Definition: must be set to 0
+
+- cpu node
+
+	Description: Describes a CPU in an ARM based system
+
+	PROPERTIES
+
+	- device_type
+		Usage: required
+		Value type: <string>
+		Definition: must be "cpu"
+	- reg
+		Usage and definition depend on ARM architecture version and
+		configuration:
+
+			# On uniprocessor ARM architectures previous to v7
+			  this property is required and must be set to 0.
+
+			# On ARM 11 MPcore based systems this property is
+			  required and matches the CPUID[11:0] register bits.
+
+			  Bits [11:0] in the reg cell must be set to
+			  bits [11:0] in CPU ID register.
+
+			  All other bits in the reg cell must be set to 0.
+
+			# On 32-bit ARM v7 or later systems this property is
+			  required and matches the CPU MPIDR[23:0] register
+			  bits.
+
+			  Bits [23:0] in the reg cell must be set to
+			  bits [23:0] in MPIDR.
+
+			  All other bits in the reg cell must be set to 0.
+
+			# On ARM v8 64-bit systems this property is required
+			  and matches the MPIDR_EL1 register affinity bits.
+
+			  * If cpus node's #address-cells property is set to 2
+
+			    The first reg cell bits [7:0] must be set to
+			    bits [39:32] of MPIDR_EL1.
+
+			    The second reg cell bits [23:0] must be set to
+			    bits [23:0] of MPIDR_EL1.
+
+			  * If cpus node's #address-cells property is set to 1
+
+			    The reg cell bits [23:0] must be set to bits [23:0]
+			    of MPIDR_EL1.
+
+			  All other bits in the reg cells must be set to 0.
+
+	- compatible:
+		Usage: required
+		Value type: <string>
+		Definition: should be one of:
+			    "arm,arm710t"
+			    "arm,arm720t"
+			    "arm,arm740t"
+			    "arm,arm7ej-s"
+			    "arm,arm7tdmi"
+			    "arm,arm7tdmi-s"
+			    "arm,arm9es"
+			    "arm,arm9ej-s"
+			    "arm,arm920t"
+			    "arm,arm922t"
+			    "arm,arm925"
+			    "arm,arm926e-s"
+			    "arm,arm926ej-s"
+			    "arm,arm940t"
+			    "arm,arm946e-s"
+			    "arm,arm966e-s"
+			    "arm,arm968e-s"
+			    "arm,arm9tdmi"
+			    "arm,arm1020e"
+			    "arm,arm1020t"
+			    "arm,arm1022e"
+			    "arm,arm1026ej-s"
+			    "arm,arm1136j-s"
+			    "arm,arm1136jf-s"
+			    "arm,arm1156t2-s"
+			    "arm,arm1156t2f-s"
+			    "arm,arm1176jzf"
+			    "arm,arm1176jz-s"
+			    "arm,arm1176jzf-s"
+			    "arm,arm11mpcore"
+			    "arm,cortex-a5"
+			    "arm,cortex-a7"
+			    "arm,cortex-a8"
+			    "arm,cortex-a9"
+			    "arm,cortex-a15"
+			    "arm,cortex-a53"
+			    "arm,cortex-a57"
+			    "arm,cortex-m0"
+			    "arm,cortex-m0+"
+			    "arm,cortex-m1"
+			    "arm,cortex-m3"
+			    "arm,cortex-m4"
+			    "arm,cortex-r4"
+			    "arm,cortex-r5"
+			    "arm,cortex-r7"
+			    "faraday,fa526"
+			    "intel,sa110"
+			    "intel,sa1100"
+			    "marvell,feroceon"
+			    "marvell,mohawk"
+			    "marvell,pj4a"
+			    "marvell,pj4b"
+			    "marvell,sheeva-v5"
+			    "qcom,krait"
+			    "qcom,scorpion"
+	- enable-method
+		Value type: <stringlist>
+		Usage and definition depend on ARM architecture version.
+			# On ARM v8 64-bit this property is required and must
+			  be one of:
+			     "spin-table"
+			     "psci"
+			# On ARM 32-bit systems this property is optional.
+
+	- cpu-release-addr
+		Usage: required for systems that have an "enable-method"
+		       property value of "spin-table".
+		Value type: <prop-encoded-array>
+		Definition:
+			# On ARM v8 64-bit systems must be a two cell
+			  property identifying a 64-bit zero-initialised
+			  memory location.
+
+Example 1 (dual-cluster big.LITTLE system 32-bit):
 
 	cpus {
 		#size-cells = <0>;
 		#address-cells = <1>;
 
-		CPU0: cpu@0 {
+		cpu@0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x0>;
 		};
 
-		CPU1: cpu@1 {
+		cpu@1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x1>;
 		};
 
-		CPU2: cpu@100 {
+		cpu@100 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a7";
 			reg = <0x100>;
 		};
 
-		CPU3: cpu@101 {
+		cpu@101 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a7";
 			reg = <0x101>;
 		};
 	};
+
+Example 2 (Cortex-A8 uniprocessor 32-bit system):
+
+	cpus {
+		#size-cells = <0>;
+		#address-cells = <1>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a8";
+			reg = <0x0>;
+		};
+	};
+
+Example 3 (ARM 926EJ-S uniprocessor 32-bit system):
+
+	cpus {
+		#size-cells = <0>;
+		#address-cells = <1>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,arm926ej-s";
+			reg = <0x0>;
+		};
+	};
+
+Example 4 (ARM Cortex-A57 64-bit system):
+
+cpus {
+	#size-cells = <0>;
+	#address-cells = <2>;
+
+	cpu@0 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x0 0x0>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	cpu@1 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x0 0x1>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	cpu@100 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x0 0x100>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	cpu@101 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x0 0x101>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	cpu@10000 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x0 0x10000>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	cpu@10001 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x0 0x10001>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	cpu@10100 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x0 0x10100>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	cpu@10101 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x0 0x10101>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	cpu@100000000 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x1 0x0>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	cpu@100000001 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x1 0x1>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	cpu@100000100 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x1 0x100>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	cpu@100000101 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x1 0x101>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	cpu@100010000 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x1 0x10000>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	cpu@100010001 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x1 0x10001>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	cpu@100010100 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x1 0x10100>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	cpu@100010101 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x1 0x10101>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
index 91b7049..808c154 100644
--- a/Documentation/devicetree/bindings/arm/omap/omap.txt
+++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
@@ -21,7 +21,8 @@
 Optional properties:
 - ti,no_idle_on_suspend: When present, it prevents the PM to idle the module
   during suspend.
-
+- ti,no-reset-on-init: When present, the module should not be reset at init
+- ti,no-idle-on-init: When present, the module should not be idled at init
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/arm/topology.txt b/Documentation/devicetree/bindings/arm/topology.txt
new file mode 100644
index 0000000..4aa20e7
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/topology.txt
@@ -0,0 +1,474 @@
+===========================================
+ARM topology binding description
+===========================================
+
+===========================================
+1 - Introduction
+===========================================
+
+In an ARM system, the hierarchy of CPUs is defined through three entities that
+are used to describe the layout of physical CPUs in the system:
+
+- cluster
+- core
+- thread
+
+The cpu nodes (bindings defined in [1]) represent the devices that
+correspond to physical CPUs and are to be mapped to the hierarchy levels.
+
+The bottom hierarchy level sits at core or thread level depending on whether
+symmetric multi-threading (SMT) is supported or not.
+
+For instance in a system where CPUs support SMT, "cpu" nodes represent all
+threads existing in the system and map to the hierarchy level "thread" above.
+In systems where SMT is not supported "cpu" nodes represent all cores present
+in the system and map to the hierarchy level "core" above.
+
+ARM topology bindings allow one to associate cpu nodes with hierarchical groups
+corresponding to the system hierarchy; syntactically they are defined as device
+tree nodes.
+
+The remainder of this document provides the topology bindings for ARM, based
+on the ePAPR standard, available from:
+
+http://www.power.org/documentation/epapr-version-1-1/
+
+If not stated otherwise, whenever a reference to a cpu node phandle is made its
+value must point to a cpu node compliant with the cpu node bindings as
+documented in [1].
+A topology description containing phandles to cpu nodes that are not compliant
+with bindings standardized in [1] is therefore considered invalid.
+
+===========================================
+2 - cpu-map node
+===========================================
+
+The ARM CPU topology is defined within the cpu-map node, which is a direct
+child of the cpus node and provides a container where the actual topology
+nodes are listed.
+
+- cpu-map node
+
+	Usage: Optional - On ARM SMP systems provide CPUs topology to the OS.
+			  ARM uniprocessor systems do not require a topology
+			  description and therefore should not define a
+			  cpu-map node.
+
+	Description: The cpu-map node is just a container node where its
+		     subnodes describe the CPU topology.
+
+	Node name must be "cpu-map".
+
+	The cpu-map node's parent node must be the cpus node.
+
+	The cpu-map node's child nodes can be:
+
+	- one or more cluster nodes
+
+	Any other configuration is considered invalid.
+
+The cpu-map node can only contain three types of child nodes:
+
+- cluster node
+- core node
+- thread node
+
+whose bindings are described in paragraph 3.
+
+The nodes describing the CPU topology (cluster/core/thread) can only be
+defined within the cpu-map node.
+Any other configuration is consider invalid and therefore must be ignored.
+
+===========================================
+2.1 - cpu-map child nodes naming convention
+===========================================
+
+cpu-map child nodes must follow a naming convention where the node name
+must be "clusterN", "coreN", "threadN" depending on the node type (ie
+cluster/core/thread) (where N = {0, 1, ...} is the node number; nodes which
+are siblings within a single common parent node must be given a unique and
+sequential N value, starting from 0).
+cpu-map child nodes which do not share a common parent node can have the same
+name (ie same number N as other cpu-map child nodes at different device tree
+levels) since name uniqueness will be guaranteed by the device tree hierarchy.
+
+===========================================
+3 - cluster/core/thread node bindings
+===========================================
+
+Bindings for cluster/cpu/thread nodes are defined as follows:
+
+- cluster node
+
+	 Description: must be declared within a cpu-map node, one node
+		      per cluster. A system can contain several layers of
+		      clustering and cluster nodes can be contained in parent
+		      cluster nodes.
+
+	The cluster node name must be "clusterN" as described in 2.1 above.
+	A cluster node can not be a leaf node.
+
+	A cluster node's child nodes must be:
+
+	- one or more cluster nodes; or
+	- one or more core nodes
+
+	Any other configuration is considered invalid.
+
+- core node
+
+	Description: must be declared in a cluster node, one node per core in
+		     the cluster. If the system does not support SMT, core
+		     nodes are leaf nodes, otherwise they become containers of
+		     thread nodes.
+
+	The core node name must be "coreN" as described in 2.1 above.
+
+	A core node must be a leaf node if SMT is not supported.
+
+	Properties for core nodes that are leaf nodes:
+
+	- cpu
+		Usage: required
+		Value type: <phandle>
+		Definition: a phandle to the cpu node that corresponds to the
+			    core node.
+
+	If a core node is not a leaf node (CPUs supporting SMT) a core node's
+	child nodes can be:
+
+	- one or more thread nodes
+
+	Any other configuration is considered invalid.
+
+- thread node
+
+	Description: must be declared in a core node, one node per thread
+		     in the core if the system supports SMT. Thread nodes are
+		     always leaf nodes in the device tree.
+
+	The thread node name must be "threadN" as described in 2.1 above.
+
+	A thread node must be a leaf node.
+
+	A thread node must contain the following property:
+
+	- cpu
+		Usage: required
+		Value type: <phandle>
+		Definition: a phandle to the cpu node that corresponds to
+			    the thread node.
+
+===========================================
+4 - Example dts
+===========================================
+
+Example 1 (ARM 64-bit, 16-cpu system, two clusters of clusters):
+
+cpus {
+	#size-cells = <0>;
+	#address-cells = <2>;
+
+	cpu-map {
+		cluster0 {
+			cluster0 {
+				core0 {
+					thread0 {
+						cpu = <&CPU0>;
+					};
+					thread1 {
+						cpu = <&CPU1>;
+					};
+				};
+
+				core1 {
+					thread0 {
+						cpu = <&CPU2>;
+					};
+					thread1 {
+						cpu = <&CPU3>;
+					};
+				};
+			};
+
+			cluster1 {
+				core0 {
+					thread0 {
+						cpu = <&CPU4>;
+					};
+					thread1 {
+						cpu = <&CPU5>;
+					};
+				};
+
+				core1 {
+					thread0 {
+						cpu = <&CPU6>;
+					};
+					thread1 {
+						cpu = <&CPU7>;
+					};
+				};
+			};
+		};
+
+		cluster1 {
+			cluster0 {
+				core0 {
+					thread0 {
+						cpu = <&CPU8>;
+					};
+					thread1 {
+						cpu = <&CPU9>;
+					};
+				};
+				core1 {
+					thread0 {
+						cpu = <&CPU10>;
+					};
+					thread1 {
+						cpu = <&CPU11>;
+					};
+				};
+			};
+
+			cluster1 {
+				core0 {
+					thread0 {
+						cpu = <&CPU12>;
+					};
+					thread1 {
+						cpu = <&CPU13>;
+					};
+				};
+				core1 {
+					thread0 {
+						cpu = <&CPU14>;
+					};
+					thread1 {
+						cpu = <&CPU15>;
+					};
+				};
+			};
+		};
+	};
+
+	CPU0: cpu@0 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x0 0x0>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	CPU1: cpu@1 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x0 0x1>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	CPU2: cpu@100 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x0 0x100>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	CPU3: cpu@101 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x0 0x101>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	CPU4: cpu@10000 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x0 0x10000>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	CPU5: cpu@10001 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x0 0x10001>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	CPU6: cpu@10100 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x0 0x10100>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	CPU7: cpu@10101 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x0 0x10101>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	CPU8: cpu@100000000 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x1 0x0>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	CPU9: cpu@100000001 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x1 0x1>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	CPU10: cpu@100000100 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x1 0x100>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	CPU11: cpu@100000101 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x1 0x101>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	CPU12: cpu@100010000 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x1 0x10000>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	CPU13: cpu@100010001 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x1 0x10001>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	CPU14: cpu@100010100 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x1 0x10100>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+
+	CPU15: cpu@100010101 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a57";
+		reg = <0x1 0x10101>;
+		enable-method = "spin-table";
+		cpu-release-addr = <0 0x20000000>;
+	};
+};
+
+Example 2 (ARM 32-bit, dual-cluster, 8-cpu system, no SMT):
+
+cpus {
+	#size-cells = <0>;
+	#address-cells = <1>;
+
+	cpu-map {
+		cluster0 {
+			core0 {
+				cpu = <&CPU0>;
+			};
+			core1 {
+				cpu = <&CPU1>;
+			};
+			core2 {
+				cpu = <&CPU2>;
+			};
+			core3 {
+				cpu = <&CPU3>;
+			};
+		};
+
+		cluster1 {
+			core0 {
+				cpu = <&CPU4>;
+			};
+			core1 {
+				cpu = <&CPU5>;
+			};
+			core2 {
+				cpu = <&CPU6>;
+			};
+			core3 {
+				cpu = <&CPU7>;
+			};
+		};
+	};
+
+	CPU0: cpu@0 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a15";
+		reg = <0x0>;
+	};
+
+	CPU1: cpu@1 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a15";
+		reg = <0x1>;
+	};
+
+	CPU2: cpu@2 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a15";
+		reg = <0x2>;
+	};
+
+	CPU3: cpu@3 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a15";
+		reg = <0x3>;
+	};
+
+	CPU4: cpu@100 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a7";
+		reg = <0x100>;
+	};
+
+	CPU5: cpu@101 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a7";
+		reg = <0x101>;
+	};
+
+	CPU6: cpu@102 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a7";
+		reg = <0x102>;
+	};
+
+	CPU7: cpu@103 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a7";
+		reg = <0x103>;
+	};
+};
+
+===============================================================================
+[1] ARM Linux kernel documentation
+    Documentation/devicetree/bindings/arm/cpus.txt
diff --git a/Documentation/devicetree/bindings/arm/vic.txt b/Documentation/devicetree/bindings/arm/vic.txt
index 266716b..dd52721 100644
--- a/Documentation/devicetree/bindings/arm/vic.txt
+++ b/Documentation/devicetree/bindings/arm/vic.txt
@@ -18,6 +18,15 @@
 Optional properties:
 
 - interrupts : Interrupt source for parent controllers if the VIC is nested.
+- valid-mask : A one cell big bit mask of valid interrupt sources. Each bit
+  represents single interrupt source, starting from source 0 at LSb and ending
+  at source 31 at MSb. A bit that is set means that the source is wired and
+  clear means otherwise. If unspecified, defaults to all valid.
+- valid-wakeup-mask : A one cell big bit mask of interrupt sources that can be
+  configured as wake up source for the system. Order of bits is the same as for
+  valid-mask property. A set bit means that this interrupt source can be
+  configured as a wake up source for the system. If unspecied, defaults to all
+  interrupt sources configurable as wake up sources.
 
 Example:
 
@@ -26,4 +35,7 @@
 		interrupt-controller;
 		#interrupt-cells = <1>;
 		reg = <0x60000 0x1000>;
+
+		valid-mask = <0xffffff7f>;
+		valid-wakeup-mask = <0x0000ff7f>;
 	};
diff --git a/Documentation/devicetree/bindings/clock/efm32-clock.txt b/Documentation/devicetree/bindings/clock/efm32-clock.txt
new file mode 100644
index 0000000..263d293
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/efm32-clock.txt
@@ -0,0 +1,11 @@
+* Clock bindings for Energy Micro efm32 Giant Gecko's Clock Management Unit
+
+Required properties:
+- compatible: Should be "efm32gg,cmu"
+- reg: Base address and length of the register set
+- interrupts: Interrupt used by the CMU
+- #clock-cells: Should be <1>
+
+The clock consumer should specify the desired clock by having the clock ID in
+its "clocks" phandle cell. The header efm32-clk.h contains a list of available
+IDs.
diff --git a/Documentation/devicetree/bindings/clock/imx6q-clock.txt b/Documentation/devicetree/bindings/clock/imx6q-clock.txt
index 5a90a72..6aab72b 100644
--- a/Documentation/devicetree/bindings/clock/imx6q-clock.txt
+++ b/Documentation/devicetree/bindings/clock/imx6q-clock.txt
@@ -215,6 +215,11 @@
 	cko2      		200
 	cko      		201
 	vdoa      		202
+	pll4_audio_div		203
+	lvds1_sel		204
+	lvds2_sel		205
+	lvds1_gate		206
+	lvds2_gate		207
 
 Examples:
 
diff --git a/Documentation/devicetree/bindings/clock/keystone-gate.txt b/Documentation/devicetree/bindings/clock/keystone-gate.txt
new file mode 100644
index 0000000..c5aa187
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/keystone-gate.txt
@@ -0,0 +1,29 @@
+Status: Unstable - ABI compatibility may be broken in the future
+
+Binding for Keystone gate control driver which uses PSC controller IP.
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be "ti,keystone,psc-clock".
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : parent clock phandle
+- reg :	psc control and domain address address space
+- reg-names : psc control and domain registers
+- domain-id : psc domain id needed to check the transition state register
+
+Optional properties:
+- clock-output-names : From common clock binding to override the
+			default output clock name
+Example:
+	clkusb: clkusb {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk16>;
+		clock-output-names = "usb";
+		reg = <0x02350008 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
diff --git a/Documentation/devicetree/bindings/clock/keystone-pll.txt b/Documentation/devicetree/bindings/clock/keystone-pll.txt
new file mode 100644
index 0000000..12bd726
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/keystone-pll.txt
@@ -0,0 +1,84 @@
+Status: Unstable - ABI compatibility may be broken in the future
+
+Binding for keystone PLLs. The main PLL IP typically has a multiplier,
+a divider and a post divider. The additional PLL IPs like ARMPLL, DDRPLL
+and PAPLL are controlled by the memory mapped register where as the Main
+PLL is controlled by a PLL controller registers along with memory mapped
+registers.
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- #clock-cells : from common clock binding; shall be set to 0.
+- compatible : shall be "ti,keystone,main-pll-clock" or "ti,keystone,pll-clock"
+- clocks : parent clock phandle
+- reg - pll control0 and pll multipler registers
+- reg-names : control and multiplier. The multiplier is applicable only for
+		main pll clock
+- fixed-postdiv : fixed post divider value
+
+Example:
+	mainpllclk: mainpllclk@2310110 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,main-pll-clock";
+		clocks = <&refclkmain>;
+		reg = <0x02620350 4>, <0x02310110 4>;
+		reg-names = "control", "multiplier";
+		fixed-postdiv = <2>;
+	};
+
+	papllclk: papllclk@2620358 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclkmain>;
+		clock-output-names = "pa-pll-clk";
+		reg = <0x02620358 4>;
+		reg-names = "control";
+		fixed-postdiv = <6>;
+	};
+
+Required properties:
+- #clock-cells : from common clock binding; shall be set to 0.
+- compatible : shall be "ti,keystone,pll-mux-clock"
+- clocks : link phandles of parent clocks
+- reg - pll mux register
+- bit-shift : number of bits to shift the bit-mask
+- bit-mask : arbitrary bitmask for programming the mux
+
+Optional properties:
+- clock-output-names : From common clock binding.
+
+Example:
+	mainmuxclk: mainmuxclk@2310108 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-mux-clock";
+		clocks = <&mainpllclk>, <&refclkmain>;
+		reg = <0x02310108 4>;
+		bit-shift = <23>;
+		bit-mask = <1>;
+		clock-output-names = "mainmuxclk";
+	};
+
+Required properties:
+- #clock-cells : from common clock binding; shall be set to 0.
+- compatible : shall be "ti,keystone,pll-divider-clock"
+- clocks : parent clock phandle
+- reg - pll mux register
+- bit-shift : number of bits to shift the bit-mask
+- bit-mask : arbitrary bitmask for programming the divider
+
+Optional properties:
+- clock-output-names : From common clock binding.
+
+Example:
+	gemtraceclk: gemtraceclk@2310120 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-divider-clock";
+		clocks = <&mainmuxclk>;
+		reg = <0x02310120 4>;
+		bit-shift = <0>;
+		bit-mask = <8>;
+		clock-output-names = "gemtraceclk";
+	};
diff --git a/Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt
new file mode 100644
index 0000000..c62391f
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mvebu-corediv-clock.txt
@@ -0,0 +1,19 @@
+* Core Divider Clock bindings for Marvell MVEBU SoCs
+
+The following is a list of provided IDs and clock names on Armada 370/XP:
+ 0 = nand (NAND clock)
+
+Required properties:
+- compatible : must be "marvell,armada-370-corediv-clock"
+- reg : must be the register address of Core Divider control register
+- #clock-cells : from common clock binding; shall be set to 1
+- clocks : must be set to the parent's phandle
+
+Example:
+
+corediv_clk: corediv-clocks@18740 {
+	compatible = "marvell,armada-370-corediv-clock";
+	reg = <0x18740 0xc>;
+	#clock-cells = <1>;
+	clocks = <&pll>;
+};
diff --git a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
index cffc93d..fc2910f 100644
--- a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
+++ b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
@@ -1,10 +1,10 @@
-* Gated Clock bindings for Marvell Orion SoCs
+* Gated Clock bindings for Marvell EBU SoCs
 
-Marvell Dove and Kirkwood allow some peripheral clocks to be gated to save
-some power. The clock consumer should specify the desired clock by having
-the clock ID in its "clocks" phandle cell. The clock ID is directly mapped to
-the corresponding clock gating control bit in HW to ease manual clock lookup
-in datasheet.
+Marvell Armada 370/XP, Dove and Kirkwood allow some peripheral clocks to be
+gated to save some power. The clock consumer should specify the desired clock
+by having the clock ID in its "clocks" phandle cell. The clock ID is directly
+mapped to the corresponding clock gating control bit in HW to ease manual clock
+lookup in datasheet.
 
 The following is a list of provided IDs for Armada 370:
 ID	Clock	Peripheral
@@ -94,6 +94,8 @@
 
 Required properties:
 - compatible : shall be one of the following:
+	"marvell,armada-370-gating-clock" - for Armada 370 SoC clock gating
+	"marvell,armada-xp-gating-clock" - for Armada XP SoC clock gating
 	"marvell,dove-gating-clock" - for Dove SoC clock gating
 	"marvell,kirkwood-gating-clock" - for Kirkwood SoC clock gating
 - reg : shall be the register address of the Clock Gating Control register
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index 00a5c264..91a748f 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -45,8 +45,8 @@
 
 Clock consumers should specify the desired clocks they use with a
 "clocks" phandle cell. Consumers that are using a gated clock should
-provide an additional ID in their clock property. The values of this
-ID are documented in sunxi/<soc>-gates.txt.
+provide an additional ID in their clock property. This ID is the
+offset of the bit controlling this particular gate in the register.
 
 For example:
 
diff --git a/Documentation/devicetree/bindings/clock/sunxi/sun4i-a10-gates.txt b/Documentation/devicetree/bindings/clock/sunxi/sun4i-a10-gates.txt
deleted file mode 100644
index 6a03475..0000000
--- a/Documentation/devicetree/bindings/clock/sunxi/sun4i-a10-gates.txt
+++ /dev/null
@@ -1,93 +0,0 @@
-Gate clock outputs
-------------------
-
-  * AXI gates ("allwinner,sun4i-axi-gates-clk")
-
-    DRAM					0
-
-  * AHB gates ("allwinner,sun4i-ahb-gates-clk")
-
-    USB0					0
-    EHCI0					1
-    OHCI0					2*
-    EHCI1					3
-    OHCI1					4*
-    SS						5
-    DMA						6
-    BIST					7
-    MMC0					8
-    MMC1					9
-    MMC2					10
-    MMC3					11
-    MS						12**
-    NAND					13
-    SDRAM					14
-
-    ACE						16
-    EMAC					17
-    TS						18
-
-    SPI0					20
-    SPI1					21
-    SPI2					22
-    SPI3					23
-    PATA					24
-    SATA					25**
-    GPS						26*
-
-    VE						32
-    TVD						33
-    TVE0					34
-    TVE1					35
-    LCD0					36
-    LCD1					37
-
-    CSI0					40
-    CSI1					41
-
-    HDMI					43
-    DE_BE0					44
-    DE_BE1					45
-    DE_FE1					46
-    DE_FE1					47
-
-    MP						50
-
-    MALI400					52
-
-  * APB0 gates ("allwinner,sun4i-apb0-gates-clk")
-
-    CODEC					0
-    SPDIF					1*
-    AC97					2
-    IIS						3
-
-    PIO						5
-    IR0						6
-    IR1						7
-
-    KEYPAD					10
-
-  * APB1 gates ("allwinner,sun4i-apb1-gates-clk")
-
-    I2C0					0
-    I2C1					1
-    I2C2					2
-
-    CAN						4
-    SCR						5
-    PS20					6
-    PS21					7
-
-    UART0					16
-    UART1					17
-    UART2					18
-    UART3					19
-    UART4					20
-    UART5					21
-    UART6					22
-    UART7					23
-
-Notation:
- [*]:  The datasheet didn't mention these, but they are present on AW code
- [**]: The datasheet had this marked as "NC" but they are used on AW code
diff --git a/Documentation/devicetree/bindings/clock/sunxi/sun5i-a10s-gates.txt b/Documentation/devicetree/bindings/clock/sunxi/sun5i-a10s-gates.txt
deleted file mode 100644
index d24279f..0000000
--- a/Documentation/devicetree/bindings/clock/sunxi/sun5i-a10s-gates.txt
+++ /dev/null
@@ -1,75 +0,0 @@
-Gate clock outputs
-------------------
-
-  * AXI gates ("allwinner,sun4i-axi-gates-clk")
-
-    DRAM					0
-
-  * AHB gates ("allwinner,sun5i-a10s-ahb-gates-clk")
-
-    USB0					0
-    EHCI0					1
-    OHCI0					2
-
-    SS						5
-    DMA						6
-    BIST					7
-    MMC0					8
-    MMC1					9
-    MMC2					10
-
-    NAND					13
-    SDRAM					14
-
-    EMAC					17
-    TS						18
-
-    SPI0					20
-    SPI1					21
-    SPI2					22
-
-    GPS						26
-
-    HSTIMER					28
-
-    VE						32
-
-    TVE						34
-
-    LCD						36
-
-    CSI						40
-
-    HDMI					43
-    DE_BE					44
-
-    DE_FE					46
-
-    IEP						51
-    MALI400					52
-
-  * APB0 gates ("allwinner,sun5i-a10s-apb0-gates-clk")
-
-    CODEC					0
-
-    IIS						3
-
-    PIO						5
-    IR						6
-
-    KEYPAD					10
-
-  * APB1 gates ("allwinner,sun5i-a10s-apb1-gates-clk")
-
-    I2C0					0
-    I2C1					1
-    I2C2					2
-
-    UART0					16
-    UART1					17
-    UART2					18
-    UART3					19
-
-Notation:
- [*]:  The datasheet didn't mention these, but they are present on AW code
- [**]: The datasheet had this marked as "NC" but they are used on AW code
diff --git a/Documentation/devicetree/bindings/clock/sunxi/sun5i-a13-gates.txt b/Documentation/devicetree/bindings/clock/sunxi/sun5i-a13-gates.txt
deleted file mode 100644
index 006b6df..0000000
--- a/Documentation/devicetree/bindings/clock/sunxi/sun5i-a13-gates.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-Gate clock outputs
-------------------
-
-  * AXI gates ("allwinner,sun4i-axi-gates-clk")
-
-    DRAM					0
-
-  * AHB gates ("allwinner,sun5i-a13-ahb-gates-clk")
-
-    USBOTG					0
-    EHCI					1
-    OHCI					2
-
-    SS						5
-    DMA						6
-    BIST					7
-    MMC0					8
-    MMC1					9
-    MMC2					10
-
-    NAND					13
-    SDRAM					14
-
-    SPI0					20
-    SPI1					21
-    SPI2					22
-
-    STIMER					28
-
-    VE						32
-
-    LCD						36
-
-    CSI						40
-
-    DE_BE					44
-
-    DE_FE					46
-
-    IEP						51
-    MALI400					52
-
-  * APB0 gates ("allwinner,sun5i-a13-apb0-gates-clk")
-
-    CODEC					0
-
-    PIO						5
-    IR						6
-
-  * APB1 gates ("allwinner,sun5i-a13-apb1-gates-clk")
-
-    I2C0					0
-    I2C1					1
-    I2C2					2
-
-    UART1					17
-
-    UART3					19
diff --git a/Documentation/devicetree/bindings/clock/sunxi/sun6i-a31-gates.txt b/Documentation/devicetree/bindings/clock/sunxi/sun6i-a31-gates.txt
deleted file mode 100644
index fe44932..0000000
--- a/Documentation/devicetree/bindings/clock/sunxi/sun6i-a31-gates.txt
+++ /dev/null
@@ -1,83 +0,0 @@
-Gate clock outputs
-------------------
-
-  * AHB1 gates ("allwinner,sun6i-a31-ahb1-gates-clk")
-
-    MIPI DSI					1
-
-    SS						5
-    DMA						6
-
-    MMC0					8
-    MMC1					9
-    MMC2					10
-    MMC3					11
-
-    NAND1					12
-    NAND0					13
-    SDRAM					14
-
-    GMAC					17
-    TS						18
-    HSTIMER					19
-    SPI0					20
-    SPI1					21
-    SPI2					22
-    SPI3					23
-    USB_OTG					24
-
-    EHCI0					26
-    EHCI1					27
-
-    OHCI0					29
-    OHCI1					30
-    OHCI2					31
-    VE						32
-
-    LCD0					36
-    LCD1					37
-
-    CSI						40
-
-    HDMI					43
-    DE_BE0					44
-    DE_BE1					45
-    DE_FE1					46
-    DE_FE1					47
-
-    MP						50
-
-    GPU						52
-
-    DEU0					55
-    DEU1					56
-    DRC0					57
-    DRC1					58
-
-  * APB1 gates ("allwinner,sun6i-a31-apb1-gates-clk")
-
-    CODEC					0
-
-    DIGITAL MIC					4
-    PIO						5
-
-    DAUDIO0					12
-    DAUDIO1					13
-
-  * APB2 gates ("allwinner,sun6i-a31-apb2-gates-clk")
-
-    I2C0					0
-    I2C1					1
-    I2C2					2
-    I2C3					3
-
-    UART0					16
-    UART1					17
-    UART2					18
-    UART3					19
-    UART4					20
-    UART5					21
-
-Notation:
- [*]:  The datasheet didn't mention these, but they are present on AW code
- [**]: The datasheet had this marked as "NC" but they are used on AW code
diff --git a/Documentation/devicetree/bindings/clock/sunxi/sun7i-a20-gates.txt b/Documentation/devicetree/bindings/clock/sunxi/sun7i-a20-gates.txt
deleted file mode 100644
index 357f4fd..0000000
--- a/Documentation/devicetree/bindings/clock/sunxi/sun7i-a20-gates.txt
+++ /dev/null
@@ -1,98 +0,0 @@
-Gate clock outputs
-------------------
-
-  * AXI gates ("allwinner,sun4i-axi-gates-clk")
-
-    DRAM					0
-
-  * AHB gates ("allwinner,sun7i-a20-ahb-gates-clk")
-
-    USB0					0
-    EHCI0					1
-    OHCI0					2
-    EHCI1					3
-    OHCI1					4
-    SS						5
-    DMA						6
-    BIST					7
-    MMC0					8
-    MMC1					9
-    MMC2					10
-    MMC3					11
-    MS						12
-    NAND					13
-    SDRAM					14
-
-    ACE						16
-    EMAC					17
-    TS						18
-
-    SPI0					20
-    SPI1					21
-    SPI2					22
-    SPI3					23
-
-    SATA					25
-
-    HSTIMER					28
-
-    VE						32
-    TVD						33
-    TVE0					34
-    TVE1					35
-    LCD0					36
-    LCD1					37
-
-    CSI0					40
-    CSI1					41
-
-    HDMI1					42
-    HDMI0					43
-    DE_BE0					44
-    DE_BE1					45
-    DE_FE1					46
-    DE_FE1					47
-
-    GMAC					49
-    MP						50
-
-    MALI400					52
-
-  * APB0 gates ("allwinner,sun7i-a20-apb0-gates-clk")
-
-    CODEC					0
-    SPDIF					1
-    AC97					2
-    IIS0					3
-    IIS1					4
-    PIO						5
-    IR0						6
-    IR1						7
-    IIS2					8
-
-    KEYPAD					10
-
-  * APB1 gates ("allwinner,sun7i-a20-apb1-gates-clk")
-
-    I2C0					0
-    I2C1					1
-    I2C2					2
-    I2C3					3
-    CAN						4
-    SCR						5
-    PS20					6
-    PS21					7
-
-    I2C4					15
-    UART0					16
-    UART1					17
-    UART2					18
-    UART3					19
-    UART4					20
-    UART5					21
-    UART6					22
-    UART7					23
-
-Notation:
- [*]:  The datasheet didn't mention these, but they are present on AW code
- [**]: The datasheet had this marked as "NC" but they are used on AW code
diff --git a/Documentation/devicetree/bindings/clock/xgene.txt b/Documentation/devicetree/bindings/clock/xgene.txt
new file mode 100644
index 0000000..1c4ef77
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/xgene.txt
@@ -0,0 +1,111 @@
+Device Tree Clock bindings for APM X-Gene
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be one of the following:
+	"apm,xgene-socpll-clock" - for a X-Gene SoC PLL clock
+	"apm,xgene-pcppll-clock" - for a X-Gene PCP PLL clock
+	"apm,xgene-device-clock" - for a X-Gene device clock
+
+Required properties for SoC or PCP PLL clocks:
+- reg : shall be the physical PLL register address for the pll clock.
+- clocks : shall be the input parent clock phandle for the clock. This should
+	be the reference clock.
+- #clock-cells : shall be set to 1.
+- clock-output-names : shall be the name of the PLL referenced by derive
+  clock.
+Optional properties for PLL clocks:
+- clock-names : shall be the name of the PLL. If missing, use the device name.
+
+Required properties for device clocks:
+- reg : shall be a list of address and length pairs describing the CSR
+         reset and/or the divider. Either may be omitted, but at least
+         one must be present.
+ - reg-names : shall be a string list describing the reg resource. This
+               may include "csr-reg" and/or "div-reg". If this property
+               is not present, the reg property is assumed to describe
+               only "csr-reg".
+- clocks : shall be the input parent clock phandle for the clock.
+- #clock-cells : shall be set to 1.
+- clock-output-names : shall be the name of the device referenced.
+Optional properties for device clocks:
+- clock-names : shall be the name of the device clock. If missing, use the
+                device name.
+- csr-offset : Offset to the CSR reset register from the reset address base.
+               Default is 0.
+- csr-mask : CSR reset mask bit. Default is 0xF.
+- enable-offset : Offset to the enable register from the reset address base.
+                  Default is 0x8.
+- enable-mask : CSR enable mask bit. Default is 0xF.
+- divider-offset : Offset to the divider CSR register from the divider base.
+                   Default is 0x0.
+- divider-width : Width of the divider register. Default is 0.
+- divider-shift : Bit shift of the divider register. Default is 0.
+
+For example:
+
+	pcppll: pcppll@17000100 {
+		compatible = "apm,xgene-pcppll-clock";
+		#clock-cells = <1>;
+		clocks = <&refclk 0>;
+		clock-names = "pcppll";
+		reg = <0x0 0x17000100 0x0 0x1000>;
+		clock-output-names = "pcppll";
+		type = <0>;
+	};
+
+	socpll: socpll@17000120 {
+		compatible = "apm,xgene-socpll-clock";
+		#clock-cells = <1>;
+		clocks = <&refclk 0>;
+		clock-names = "socpll";
+		reg = <0x0 0x17000120 0x0 0x1000>;
+		clock-output-names = "socpll";
+		type = <1>;
+	};
+
+	qmlclk: qmlclk {
+		compatible = "apm,xgene-device-clock";
+		#clock-cells = <1>;
+		clocks = <&socplldiv2 0>;
+		clock-names = "qmlclk";
+		reg = <0x0 0x1703C000 0x0 0x1000>;
+		reg-name = "csr-reg";
+		clock-output-names = "qmlclk";
+	};
+
+	ethclk: ethclk {
+		compatible = "apm,xgene-device-clock";
+		#clock-cells = <1>;
+		clocks = <&socplldiv2 0>;
+		clock-names = "ethclk";
+		reg = <0x0 0x17000000 0x0 0x1000>;
+		reg-names = "div-reg";
+		divider-offset = <0x238>;
+		divider-width = <0x9>;
+		divider-shift = <0x0>;
+		clock-output-names = "ethclk";
+	};
+
+	apbclk: apbclk {
+		compatible = "apm,xgene-device-clock";
+		#clock-cells = <1>;
+		clocks = <&ahbclk 0>;
+		clock-names = "apbclk";
+		reg = <0x0 0x1F2AC000 0x0 0x1000
+			0x0 0x1F2AC000 0x0 0x1000>;
+		reg-names = "csr-reg", "div-reg";
+		csr-offset = <0x0>;
+		csr-mask = <0x200>;
+		enable-offset = <0x8>;
+		enable-mask = <0x200>;
+		divider-offset = <0x10>;
+		divider-width = <0x2>;
+		divider-shift = <0x0>;
+		flags = <0x8>;
+		clock-output-names = "apbclk";
+	};
+
diff --git a/Documentation/devicetree/bindings/crypto/omap-aes.txt b/Documentation/devicetree/bindings/crypto/omap-aes.txt
new file mode 100644
index 0000000..fd97176
--- /dev/null
+++ b/Documentation/devicetree/bindings/crypto/omap-aes.txt
@@ -0,0 +1,31 @@
+OMAP SoC AES crypto Module
+
+Required properties:
+
+- compatible : Should contain entries for this and backward compatible
+  AES versions:
+  - "ti,omap2-aes" for OMAP2.
+  - "ti,omap3-aes" for OMAP3.
+  - "ti,omap4-aes" for OMAP4 and AM33XX.
+  Note that the OMAP2 and 3 versions are compatible (OMAP3 supports
+  more algorithms) but they are incompatible with OMAP4.
+- ti,hwmods: Name of the hwmod associated with the AES module
+- reg : Offset and length of the register set for the module
+- interrupts : the interrupt-specifier for the AES module.
+
+Optional properties:
+- dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
+	Documentation/devicetree/bindings/dma/dma.txt
+- dma-names: DMA request names should include "tx" and "rx" if present.
+
+Example:
+	/* AM335x */
+	aes: aes@53500000 {
+		compatible = "ti,omap4-aes";
+		ti,hwmods = "aes";
+		reg = <0x53500000 0xa0>;
+		interrupts = <102>;
+		dmas = <&edma 6>,
+		       <&edma 5>;
+		dma-names = "tx", "rx";
+	};
diff --git a/Documentation/devicetree/bindings/crypto/omap-sham.txt b/Documentation/devicetree/bindings/crypto/omap-sham.txt
new file mode 100644
index 0000000..f839acd
--- /dev/null
+++ b/Documentation/devicetree/bindings/crypto/omap-sham.txt
@@ -0,0 +1,28 @@
+OMAP SoC SHA crypto Module
+
+Required properties:
+
+- compatible : Should contain entries for this and backward compatible
+  SHAM versions:
+  - "ti,omap2-sham" for OMAP2 & OMAP3.
+  - "ti,omap4-sham" for OMAP4 and AM33XX.
+  Note that these two versions are incompatible.
+- ti,hwmods: Name of the hwmod associated with the SHAM module
+- reg : Offset and length of the register set for the module
+- interrupts : the interrupt-specifier for the SHAM module.
+
+Optional properties:
+- dmas: DMA specifiers for the rx dma. See the DMA client binding,
+	Documentation/devicetree/bindings/dma/dma.txt
+- dma-names: DMA request name. Should be "rx" if a dma is present.
+
+Example:
+	/* AM335x */
+	sham: sham@53100000 {
+		compatible = "ti,omap4-sham";
+		ti,hwmods = "sham";
+		reg = <0x53100000 0x200>;
+		interrupts = <109>;
+		dmas = <&edma 36>;
+		dma-names = "rx";
+	};
diff --git a/Documentation/devicetree/bindings/gpio/abilis,tb10x-gpio.txt b/Documentation/devicetree/bindings/gpio/abilis,tb10x-gpio.txt
new file mode 100644
index 0000000..00611ac
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/abilis,tb10x-gpio.txt
@@ -0,0 +1,36 @@
+* Abilis TB10x GPIO controller
+
+Required Properties:
+- compatible: Should be "abilis,tb10x-gpio"
+- reg: Address and length of the register set for the device
+- gpio-controller: Marks the device node as a gpio controller.
+- #gpio-cells: Should be <2>. The first cell is the pin number and the
+  second cell is used to specify optional parameters:
+   - bit 0 specifies polarity (0 for normal, 1 for inverted).
+- abilis,ngpio: the number of GPIO pins this driver controls.
+
+Optional Properties:
+- interrupt-controller: Marks the device node as an interrupt controller.
+- #interrupt-cells: Should be <1>. Interrupts are triggered on both edges.
+- interrupts: Defines the interrupt line connecting this GPIO controller to
+  its parent interrupt controller.
+- interrupt-parent: Defines the parent interrupt controller.
+
+GPIO ranges are specified as described in
+Documentation/devicetree/bindings/gpio/gpio.txt
+
+Example:
+
+	gpioa: gpio@FF140000 {
+		compatible = "abilis,tb10x-gpio";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		interrupt-parent = <&tb10x_ictl>;
+		interrupts = <27 2>;
+		reg = <0xFF140000 0x1000>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		abilis,ngpio = <3>;
+		gpio-ranges = <&iomux 0 0 0>;
+		gpio-ranges-group-names = "gpioa_pins";
+	};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt b/Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt
new file mode 100644
index 0000000..4a63bc9
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt
@@ -0,0 +1,52 @@
+Broadcom Kona Family GPIO
+=========================
+
+This GPIO driver is used in the following Broadcom SoCs:
+  BCM11130, BCM11140, BCM11351, BCM28145, BCM28155
+
+The Broadcom GPIO Controller IP can be configured prior to synthesis to
+support up to 8 banks of 32 GPIOs where each bank has its own IRQ. The
+GPIO controller only supports edge, not level, triggering of interrupts.
+
+Required properties
+-------------------
+
+- compatible: "brcm,bcm11351-gpio", "brcm,kona-gpio"
+- reg: Physical base address and length of the controller's registers.
+- interrupts: The interrupt outputs from the controller. There is one GPIO
+  interrupt per GPIO bank. The number of interrupts listed depends on the
+  number of GPIO banks on the SoC. The interrupts must be ordered by bank,
+  starting with bank 0. There is always a 1:1 mapping between banks and
+  IRQs.
+- #gpio-cells: Should be <2>. The first cell is the pin number, the second
+  cell is used to specify optional parameters:
+  - bit 0 specifies polarity (0 for normal, 1 for inverted)
+  See also "gpio-specifier" in .../devicetree/bindings/gpio/gpio.txt.
+- #interrupt-cells: Should be <2>. The first cell is the GPIO number. The
+  second cell is used to specify flags. The following subset of flags is
+  supported:
+  - trigger type (bits[1:0]):
+      1 = low-to-high edge triggered.
+      2 = high-to-low edge triggered.
+      3 = low-to-high or high-to-low edge triggered
+      Valid values are 1, 2, 3
+  See also .../devicetree/bindings/interrupt-controller/interrupts.txt.
+- gpio-controller: Marks the device node as a GPIO controller.
+- interrupt-controller: Marks the device node as an interrupt controller.
+
+Example:
+	gpio: gpio@35003000 {
+		compatible = "brcm,bcm11351-gpio", "brcm,kona-gpio";
+		reg = <0x35003000 0x800>;
+		interrupts =
+		       <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH
+			GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH
+			GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH
+			GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH
+			GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH
+			GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+		#gpio-cells = <2>;
+		#interrupt-cells = <2>;
+		gpio-controller;
+		interrupt-controller;
+	};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt b/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt
new file mode 100644
index 0000000..d63194a
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt
@@ -0,0 +1,71 @@
+* PCF857x-compatible I/O expanders
+
+The PCF857x-compatible chips have "quasi-bidirectional" I/O lines that can be
+driven high by a pull-up current source or driven low to ground. This combines
+the direction and output level into a single bit per line, which can't be read
+back. We can't actually know at initialization time whether a line is configured
+(a) as output and driving the signal low/high, or (b) as input and reporting a
+low/high value, without knowing the last value written since the chip came out
+of reset (if any). The only reliable solution for setting up line direction is
+thus to do it explicitly.
+
+Required Properties:
+
+  - compatible: should be one of the following.
+    - "maxim,max7328": For the Maxim MAX7378
+    - "maxim,max7329": For the Maxim MAX7329
+    - "nxp,pca8574": For the NXP PCA8574
+    - "nxp,pca8575": For the NXP PCA8575
+    - "nxp,pca9670": For the NXP PCA9670
+    - "nxp,pca9671": For the NXP PCA9671
+    - "nxp,pca9672": For the NXP PCA9672
+    - "nxp,pca9673": For the NXP PCA9673
+    - "nxp,pca9674": For the NXP PCA9674
+    - "nxp,pca9675": For the NXP PCA9675
+    - "nxp,pcf8574": For the NXP PCF8574
+    - "nxp,pcf8574a": For the NXP PCF8574A
+    - "nxp,pcf8575": For the NXP PCF8575
+    - "ti,tca9554": For the TI TCA9554
+
+  - reg: I2C slave address.
+
+  - gpio-controller: Marks the device node as a gpio controller.
+  - #gpio-cells: Should be 2. The first cell is the GPIO number and the second
+    cell specifies GPIO flags, as defined in <dt-bindings/gpio/gpio.h>. Only the
+    GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported.
+
+Optional Properties:
+
+  - lines-initial-states: Bitmask that specifies the initial state of each
+  line. When a bit is set to zero, the corresponding line will be initialized to
+  the input (pulled-up) state. When the  bit is set to one, the line will be
+  initialized the the low-level output state. If the property is not specified
+  all lines will be initialized to the input state.
+
+  The I/O expander can detect input state changes, and thus optionally act as
+  an interrupt controller. When the expander interrupt line is connected all the
+  following properties must be set. For more information please see the
+  interrupt controller device tree bindings documentation available at
+  Documentation/devicetree/bindings/interrupt-controller/interrupts.txt.
+
+  - interrupt-controller: Identifies the node as an interrupt controller.
+  - #interrupt-cells: Number of cells to encode an interrupt source, shall be 2.
+  - interrupt-parent: phandle of the parent interrupt controller.
+  - interrupts: Interrupt specifier for the controllers interrupt.
+
+
+Please refer to gpio.txt in this directory for details of the common GPIO
+bindings used by client devices.
+
+Example: PCF8575 I/O expander node
+
+	pcf8575: gpio@20 {
+		compatible = "nxp,pcf8575";
+		reg = <0x20>;
+		interrupt-parent = <&irqpin2>;
+		interrupts = <3 0>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt
index 6cec6ff..0c85bb6 100644
--- a/Documentation/devicetree/bindings/gpio/gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio.txt
@@ -87,8 +87,10 @@
 contains information structures as follows:
 
 	gpio-range-list ::= <single-gpio-range> [gpio-range-list]
-	single-gpio-range ::=
+	single-gpio-range ::= <numeric-gpio-range> | <named-gpio-range>
+	numeric-gpio-range ::=
 			<pinctrl-phandle> <gpio-base> <pinctrl-base> <count>
+	named-gpio-range ::= <pinctrl-phandle> <gpio-base> '<0 0>'
 	gpio-phandle : phandle to pin controller node.
 	gpio-base : Base GPIO ID in the GPIO controller
 	pinctrl-base : Base pinctrl pin ID in the pin controller
@@ -97,6 +99,19 @@
 The "pin controller node" mentioned above must conform to the bindings
 described in ../pinctrl/pinctrl-bindings.txt.
 
+In case named gpio ranges are used (ranges with both <pinctrl-base> and
+<count> set to 0), the property gpio-ranges-group-names contains one string
+for every single-gpio-range in gpio-ranges:
+	gpiorange-names-list ::= <gpiorange-name> [gpiorange-names-list]
+	gpiorange-name : Name of the pingroup associated to the GPIO range in
+			the respective pin controller.
+
+Elements of gpiorange-names-list corresponding to numeric ranges contain
+the empty string. Elements of gpiorange-names-list corresponding to named
+ranges contain the name of a pin group defined in the respective pin
+controller. The number of pins/GPIOs in the range is the number of pins in
+that pin group.
+
 Previous versions of this binding required all pin controller nodes that
 were referenced by any gpio-ranges property to contain a property named
 #gpio-range-cells with value <3>. This requirement is now deprecated.
@@ -104,7 +119,7 @@
 compatibility reasons, and would still be required even in new device
 trees that need to be compatible with older software.
 
-Example:
+Example 1:
 
 	qe_pio_e: gpio-controller@1460 {
 		#gpio-cells = <2>;
@@ -117,3 +132,24 @@
 Here, a single GPIO controller has GPIOs 0..9 routed to pin controller
 pinctrl1's pins 20..29, and GPIOs 10..19 routed to pin controller pinctrl2's
 pins 50..59.
+
+Example 2:
+
+	gpio_pio_i: gpio-controller@14B0 {
+		#gpio-cells = <2>;
+		compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
+		reg = <0x1480 0x18>;
+		gpio-controller;
+		gpio-ranges =			<&pinctrl1 0 20 10>,
+						<&pinctrl2 10 0 0>,
+						<&pinctrl1 15 0 10>,
+						<&pinctrl2 25 0 0>;
+		gpio-ranges-group-names =	"",
+						"foo",
+						"",
+						"bar";
+	};
+
+Here, three GPIO ranges are defined wrt. two pin controllers. pinctrl1 GPIO
+ranges are defined using pin numbers whereas the GPIO ranges wrt. pinctrl2
+are named "foo" and "bar".
diff --git a/Documentation/devicetree/bindings/hwrng/omap_rng.txt b/Documentation/devicetree/bindings/hwrng/omap_rng.txt
new file mode 100644
index 0000000..6a62acd
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwrng/omap_rng.txt
@@ -0,0 +1,22 @@
+OMAP SoC HWRNG Module
+
+Required properties:
+
+- compatible : Should contain entries for this and backward compatible
+  RNG versions:
+  - "ti,omap2-rng" for OMAP2.
+  - "ti,omap4-rng" for OMAP4, OMAP5 and AM33XX.
+  Note that these two versions are incompatible.
+- ti,hwmods: Name of the hwmod associated with the RNG module
+- reg : Offset and length of the register set for the module
+- interrupts : the interrupt number for the RNG module.
+		Only used for "ti,omap4-rng".
+
+Example:
+/* AM335x */
+rng: rng@48310000 {
+	compatible = "ti,omap4-rng";
+	ti,hwmods = "rng";
+	reg = <0x48310000 0x2000>;
+	interrupts = <111>;
+};
diff --git a/Documentation/devicetree/bindings/iio/light/cm36651.txt b/Documentation/devicetree/bindings/iio/light/cm36651.txt
new file mode 100644
index 0000000..c03e19d
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/light/cm36651.txt
@@ -0,0 +1,26 @@
+* Capella CM36651 I2C Proximity and Color Light sensor
+
+Required properties:
+- compatible: must be "capella,cm36651"
+- reg: the I2C address of the device
+- interrupts: interrupt-specifier for the sole interrupt
+	      generated by the device
+- vled-supply: regulator for the IR LED. IR_LED is a part
+	      of the cm36651 for proximity detection.
+	      As covered in ../../regulator/regulator.txt
+
+Example:
+
+	i2c_cm36651: i2c-gpio {
+		/* ... */
+
+		cm36651@18 {
+			compatible = "capella,cm36651";
+			reg = <0x18>;
+			interrupt-parent = <&gpx0>;
+			interrupts = <2 0>;
+			vled-supply = <&ps_als_reg>;
+		};
+
+		/* ... */
+	};
diff --git a/Documentation/devicetree/bindings/iio/light/gp2ap020a00f.txt b/Documentation/devicetree/bindings/iio/light/gp2ap020a00f.txt
new file mode 100644
index 0000000..9231c82
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/light/gp2ap020a00f.txt
@@ -0,0 +1,21 @@
+* Sharp GP2AP020A00F I2C Proximity/ALS sensor
+
+The proximity detector sensor requires power supply
+for its built-in led. It is also defined by this binding.
+
+Required properties:
+
+  - compatible : should be "sharp,gp2ap020a00f"
+  - reg : the I2C slave address of the light sensor
+  - interrupts : interrupt specifier for the sole interrupt generated
+		 by the device
+  - vled-supply : VLED power supply, as covered in ../regulator/regulator.txt
+
+Example:
+
+gp2ap020a00f@39 {
+	compatible = "sharp,gp2ap020a00f";
+	reg = <0x39>;
+	interrupts = <2 0>;
+	vled-supply = <...>;
+};
diff --git a/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun4i-ic.txt b/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun4i-ic.txt
index 57edb30..3d3b2b9 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun4i-ic.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun4i-ic.txt
@@ -8,9 +8,6 @@
 - #interrupt-cells : Specifies the number of cells needed to encode an
   interrupt source. The value shall be 1.
 
-For the valid interrupt sources for your SoC, see the documentation in
-sunxi/<soc>.txt
-
 Example:
 
 intc: interrupt-controller {
diff --git a/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt b/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
index 72a06c0..1486497 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
@@ -4,16 +4,33 @@
 1) Interrupt client nodes
 -------------------------
 
-Nodes that describe devices which generate interrupts must contain an
-"interrupts" property. This property must contain a list of interrupt
-specifiers, one per output interrupt. The format of the interrupt specifier is
-determined by the interrupt controller to which the interrupts are routed; see
-section 2 below for details.
+Nodes that describe devices which generate interrupts must contain an either an
+"interrupts" property or an "interrupts-extended" property. These properties
+contain a list of interrupt specifiers, one per output interrupt. The format of
+the interrupt specifier is determined by the interrupt controller to which the
+interrupts are routed; see section 2 below for details.
+
+  Example:
+	interrupt-parent = <&intc1>;
+	interrupts = <5 0>, <6 0>;
 
 The "interrupt-parent" property is used to specify the controller to which
 interrupts are routed and contains a single phandle referring to the interrupt
 controller node. This property is inherited, so it may be specified in an
-interrupt client node or in any of its parent nodes.
+interrupt client node or in any of its parent nodes. Interrupts listed in the
+"interrupts" property are always in reference to the node's interrupt parent.
+
+The "interrupts-extended" property is a special form for use when a node needs
+to reference multiple interrupt parents. Each entry in this property contains
+both the parent phandle and the interrupt specifier. "interrupts-extended"
+should only be used when a device has multiple interrupt parents.
+
+  Example:
+	interrupts-extended = <&intc1 5 1>, <&intc2 1 0>;
+
+A device node may contain either "interrupts" or "interrupts-extended", but not
+both. If both properties are present, then the operating system should log an
+error and use only the data in "interrupts".
 
 2) Interrupt controller nodes
 -----------------------------
diff --git a/Documentation/devicetree/bindings/interrupt-controller/sunxi/sun4i-a10.txt b/Documentation/devicetree/bindings/interrupt-controller/sunxi/sun4i-a10.txt
deleted file mode 100644
index 76b98c8..0000000
--- a/Documentation/devicetree/bindings/interrupt-controller/sunxi/sun4i-a10.txt
+++ /dev/null
@@ -1,89 +0,0 @@
-Allwinner A10 (sun4i) interrupt sources
----------------------------------------
-
-The interrupt sources available for the Allwinner A10 SoC are the
-following one:
-
-0: ENMI
-1: UART0
-2: UART1
-3: UART2
-4: UART3
-5: IR0
-6: IR1
-7: I2C0
-8: I2C1
-9: I2C2
-10: SPI0
-11: SPI1
-12: SPI2
-13: SPDIF
-14: AC97
-15: TS
-16: I2S
-17: UART4
-18: UART5
-19: UART6
-20: UART7
-21: KEYPAD
-22: TIMER0
-23: TIMER1
-24: TIMER2
-25: TIMER3
-26: CAN
-27: DMA
-28: PIO
-29: TOUCH_PANEL
-30: AUDIO_CODEC
-31: LRADC
-32: MMC0
-33: MMC1
-34: MMC2
-35: MMC3
-36: MEMSTICK
-37: NAND
-38: USB0
-39: USB1
-40: USB2
-41: SCR
-42: CSI0
-43: CSI1
-44: LCDCTRL0
-45: LCDCTRL1
-46: MP
-47: DEFEBE0
-48: DEFEBE1
-49: PMU
-50: SPI3
-51: TZASC
-52: PATA
-53: VE
-54: SS
-55: EMAC
-56: SATA
-57: GPS
-58: HDMI
-59: TVE
-60: ACE
-61: TVD
-62: PS2_0
-63: PS2_1
-64: USB3
-65: USB4
-66: PLE_PFM
-67: TIMER4
-68: TIMER5
-69: GPU_GP
-70: GPU_GPMMU
-71: GPU_PP0
-72: GPU_PPMMU0
-73: GPU_PMU
-74: GPU_RSV0
-75: GPU_RSV1
-76: GPU_RSV2
-77: GPU_RSV3
-78: GPU_RSV4
-79: GPU_RSV5
-80: GPU_RSV6
-82: SYNC_TIMER0
-83: SYNC_TIMER1
diff --git a/Documentation/devicetree/bindings/interrupt-controller/sunxi/sun5i-a13.txt b/Documentation/devicetree/bindings/interrupt-controller/sunxi/sun5i-a13.txt
deleted file mode 100644
index 2ec3b5c..0000000
--- a/Documentation/devicetree/bindings/interrupt-controller/sunxi/sun5i-a13.txt
+++ /dev/null
@@ -1,55 +0,0 @@
-Allwinner A13 (sun5i) interrupt sources
----------------------------------------
-
-The interrupt sources available for the Allwinner A13 SoC are the
-following one:
-
-0: ENMI
-2: UART1
-4: UART3
-5: IR
-7: I2C0
-8: I2C1
-9: I2C2
-10: SPI0
-11: SPI1
-12: SPI2
-22: TIMER0
-23: TIMER1
-24: TIMER2
-25: TIMER3
-27: DMA
-28: PIO
-29: TOUCH_PANEL
-30: AUDIO_CODEC
-31: LRADC
-32: MMC0
-33: MMC1
-34: MMC2
-37: NAND
-38: USB OTG
-39: USB EHCI
-40: USB OHCI
-42: CSI
-44: LCDCTRL
-47: DEFEBE
-49: PMU
-53: VE
-54: SS
-66: PLE_PFM
-67: TIMER4
-68: TIMER5
-69: GPU_GP
-70: GPU_GPMMU
-71: GPU_PP0
-72: GPU_PPMMU0
-73: GPU_PMU
-74: GPU_RSV0
-75: GPU_RSV1
-76: GPU_RSV2
-77: GPU_RSV3
-78: GPU_RSV4
-79: GPU_RSV5
-80: GPU_RSV6
-82: SYNC_TIMER0
-83: SYNC_TIMER1
diff --git a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt
index a61727f..c55b8c0 100644
--- a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt
+++ b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt
@@ -10,6 +10,7 @@
 - max-cur: Maximun current at each led channel.
 
 Optional properties:
+- enable-gpio: GPIO attached to the chip's enable pin
 - label: Used for naming LEDs
 - pwr-sel: LP8501 specific property. Power selection for output channels.
          0: D1~9 are connected to VDD
@@ -17,12 +18,15 @@
          2: D1~6 with VOUT, D7~9 with VDD
          3: D1~9 are connected to VOUT
 
-Alternatively, each child can have specific channel name
-- chan-name: Name of each channel name
+Alternatively, each child can have a specific channel name and trigger:
+- chan-name (optional): name of channel
+- linux,default-trigger (optional): see
+  Documentation/devicetree/bindings/leds/common.txt
 
 example 1) LP5521
 3 LED channels, external clock used. Channel names are 'lp5521_pri:channel0',
-'lp5521_pri:channel1' and 'lp5521_pri:channel2'
+'lp5521_pri:channel1' and 'lp5521_pri:channel2', with a heartbeat trigger
+on channel 0.
 
 lp5521@32 {
 	compatible = "national,lp5521";
@@ -33,6 +37,7 @@
 	chan0 {
 		led-cur = /bits/ 8 <0x2f>;
 		max-cur = /bits/ 8 <0x5f>;
+		linux,default-trigger = "heartbeat";
 	};
 
 	chan1 {
diff --git a/Documentation/devicetree/bindings/memory.txt b/Documentation/devicetree/bindings/memory.txt
deleted file mode 100644
index eb24693..0000000
--- a/Documentation/devicetree/bindings/memory.txt
+++ /dev/null
@@ -1,168 +0,0 @@
-*** Memory binding ***
-
-The /memory node provides basic information about the address and size
-of the physical memory. This node is usually filled or updated by the
-bootloader, depending on the actual memory configuration of the given
-hardware.
-
-The memory layout is described by the following node:
-
-/ {
-	#address-cells = <(n)>;
-	#size-cells = <(m)>;
-	memory {
-		device_type = "memory";
-		reg =  <(baseaddr1) (size1)
-			(baseaddr2) (size2)
-			...
-			(baseaddrN) (sizeN)>;
-	};
-	...
-};
-
-A memory node follows the typical device tree rules for "reg" property:
-n:		number of cells used to store base address value
-m:		number of cells used to store size value
-baseaddrX:	defines a base address of the defined memory bank
-sizeX:		the size of the defined memory bank
-
-
-More than one memory bank can be defined.
-
-
-*** Reserved memory regions ***
-
-In /memory/reserved-memory node one can create child nodes describing
-particular reserved (excluded from normal use) memory regions. Such
-memory regions are usually designed for the special usage by various
-device drivers. A good example are contiguous memory allocations or
-memory sharing with other operating system on the same hardware board.
-Those special memory regions might depend on the board configuration and
-devices used on the target system.
-
-Parameters for each memory region can be encoded into the device tree
-with the following convention:
-
-[(label):] (name) {
-	compatible = "linux,contiguous-memory-region", "reserved-memory-region";
-	reg = <(address) (size)>;
-	(linux,default-contiguous-region);
-};
-
-compatible:	one or more of:
-	- "linux,contiguous-memory-region" - enables binding of this
-	  region to Contiguous Memory Allocator (special region for
-	  contiguous memory allocations, shared with movable system
-	  memory, Linux kernel-specific).
-	- "reserved-memory-region" - compatibility is defined, given
-	  region is assigned for exclusive usage for by the respective
-	  devices.
-
-reg:	standard property defining the base address and size of
-	the memory region
-
-linux,default-contiguous-region: property indicating that the region
-	is the default region for all contiguous memory
-	allocations, Linux specific (optional)
-
-It is optional to specify the base address, so if one wants to use
-autoconfiguration of the base address, '0' can be specified as a base
-address in the 'reg' property.
-
-The /memory/reserved-memory node must contain the same #address-cells
-and #size-cells value as the root node.
-
-
-*** Device node's properties ***
-
-Once regions in the /memory/reserved-memory node have been defined, they
-may be referenced by other device nodes. Bindings that wish to reference
-memory regions should explicitly document their use of the following
-property:
-
-memory-region = <&phandle_to_defined_region>;
-
-This property indicates that the device driver should use the memory
-region pointed by the given phandle.
-
-
-*** Example ***
-
-This example defines a memory consisting of 4 memory banks. 3 contiguous
-regions are defined for Linux kernel, one default of all device drivers
-(named contig_mem, placed at 0x72000000, 64MiB), one dedicated to the
-framebuffer device (labelled display_mem, placed at 0x78000000, 8MiB)
-and one for multimedia processing (labelled multimedia_mem, placed at
-0x77000000, 64MiB). 'display_mem' region is then assigned to fb@12300000
-device for DMA memory allocations (Linux kernel drivers will use CMA is
-available or dma-exclusive usage otherwise). 'multimedia_mem' is
-assigned to scaler@12500000 and codec@12600000 devices for contiguous
-memory allocations when CMA driver is enabled.
-
-The reason for creating a separate region for framebuffer device is to
-match the framebuffer base address to the one configured by bootloader,
-so once Linux kernel drivers starts no glitches on the displayed boot
-logo appears. Scaller and codec drivers should share the memory
-allocations.
-
-/ {
-	#address-cells = <1>;
-	#size-cells = <1>;
-
-	/* ... */
-
-	memory {
-		reg =  <0x40000000 0x10000000
-			0x50000000 0x10000000
-			0x60000000 0x10000000
-			0x70000000 0x10000000>;
-
-		reserved-memory {
-			#address-cells = <1>;
-			#size-cells = <1>;
-
-			/*
-			 * global autoconfigured region for contiguous allocations
-			 * (used only with Contiguous Memory Allocator)
-			 */
-			contig_region@0 {
-				compatible = "linux,contiguous-memory-region";
-				reg = <0x0 0x4000000>;
-				linux,default-contiguous-region;
-			};
-
-			/*
-			 * special region for framebuffer
-			 */
-			display_region: region@78000000 {
-				compatible = "linux,contiguous-memory-region", "reserved-memory-region";
-				reg = <0x78000000 0x800000>;
-			};
-
-			/*
-			 * special region for multimedia processing devices
-			 */
-			multimedia_region: region@77000000 {
-				compatible = "linux,contiguous-memory-region";
-				reg = <0x77000000 0x4000000>;
-			};
-		};
-	};
-
-	/* ... */
-
-	fb0: fb@12300000 {
-		status = "okay";
-		memory-region = <&display_region>;
-	};
-
-	scaler: scaler@12500000 {
-		status = "okay";
-		memory-region = <&multimedia_region>;
-	};
-
-	codec: codec@12600000 {
-		status = "okay";
-		memory-region = <&multimedia_region>;
-	};
-};
diff --git a/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
new file mode 100644
index 0000000..68ba372
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
@@ -0,0 +1,17 @@
+Allwinner sunxi-sid
+
+Required properties:
+- compatible: "allwinner,sun4i-sid" or "allwinner,sun7i-a20-sid".
+- reg: Should contain registers location and length
+
+Example for sun4i:
+	sid@01c23800 {
+		compatible = "allwinner,sun4i-sid";
+		reg = <0x01c23800 0x10>
+	};
+
+Example for sun7i:
+	sid@01c23800 {
+		compatible = "allwinner,sun7i-a20-sid";
+		reg = <0x01c23800 0x200>
+	};
diff --git a/Documentation/devicetree/bindings/misc/ti,dac7512.txt b/Documentation/devicetree/bindings/misc/ti,dac7512.txt
new file mode 100644
index 0000000..1db4593
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/ti,dac7512.txt
@@ -0,0 +1,20 @@
+TI DAC7512 DEVICETREE BINDINGS
+
+Required properties:
+
+	- "compatible"		Must be set to "ti,dac7512"
+
+Property rules described in Documentation/devicetree/bindings/spi/spi-bus.txt
+apply. In particular, "reg" and "spi-max-frequency" properties must be given.
+
+
+Example:
+
+	spi_master {
+		dac7512: dac7512@0 {
+			compatible = "ti,dac7512";
+			reg = <0>; /* CS0 */
+			spi-max-frequency = <1000000>;
+		};
+	};
+
diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
index ed271fc..8c8908a 100644
--- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
+++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
@@ -20,8 +20,17 @@
 ti,non-removable: non-removable slot (like eMMC)
 ti,needs-special-reset: Requires a special softreset sequence
 ti,needs-special-hs-handling: HSMMC IP needs special setting for handling High Speed
+dmas: List of DMA specifiers with the controller specific format
+as described in the generic DMA client binding. A tx and rx
+specifier is required.
+dma-names: List of DMA request names. These strings correspond
+1:1 with the DMA specifiers listed in dmas. The string naming is
+to be "rx" and "tx" for RX and TX DMA requests, respectively.
 
-Example:
+Examples:
+
+[hwmod populated DMA resources]
+
 	mmc1: mmc@0x4809c000 {
 		compatible = "ti,omap4-hsmmc";
 		reg = <0x4809c000 0x400>;
@@ -31,3 +40,18 @@
 		vmmc-supply = <&vmmc>; /* phandle to regulator node */
 		ti,non-removable;
 	};
+
+[generic DMA request binding]
+
+	mmc1: mmc@0x4809c000 {
+		compatible = "ti,omap4-hsmmc";
+		reg = <0x4809c000 0x400>;
+		ti,hwmods = "mmc1";
+		ti,dual-volt;
+		bus-width = <4>;
+		vmmc-supply = <&vmmc>; /* phandle to regulator node */
+		ti,non-removable;
+		dmas = <&edma 24
+			&edma 25>;
+		dma-names = "tx", "rx";
+	};
diff --git a/Documentation/devicetree/bindings/pci/mvebu-pci.txt b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
index 9556e2f..08c716b 100644
--- a/Documentation/devicetree/bindings/pci/mvebu-pci.txt
+++ b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
@@ -5,6 +5,7 @@
 - compatible: one of the following values:
     marvell,armada-370-pcie
     marvell,armada-xp-pcie
+    marvell,dove-pcie
     marvell,kirkwood-pcie
 - #address-cells, set to <3>
 - #size-cells, set to <2>
@@ -14,6 +15,8 @@
 - ranges: ranges describing the MMIO registers to control the PCIe
   interfaces, and ranges describing the MBus windows needed to access
   the memory and I/O regions of each PCIe interface.
+- msi-parent: Link to the hardware entity that serves as the Message
+  Signaled Interrupt controller for this PCI controller.
 
 The ranges describing the MMIO registers have the following layout:
 
@@ -74,6 +77,8 @@
 - marvell,pcie-lane: the physical PCIe lane number, for ports having
   multiple lanes. If this property is not found, we assume that the
   value is 0.
+- reset-gpios: optional gpio to PERST#
+- reset-delay-us: delay in us to wait after reset de-assertion
 
 Example:
 
@@ -86,6 +91,7 @@
 	#size-cells = <2>;
 
 	bus-range = <0x00 0xff>;
+	msi-parent = <&mpic>;
 
 	ranges =
 	       <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000	/* Port 0.0 registers */
@@ -135,6 +141,10 @@
 		interrupt-map = <0 0 0 0 &mpic 58>;
 		marvell,pcie-port = <0>;
 		marvell,pcie-lane = <0>;
+		/* low-active PERST# reset on GPIO 25 */
+		reset-gpios = <&gpio0 25 1>;
+		/* wait 20ms for device settle after reset deassertion */
+		reset-delay-us = <20000>;
 		clocks = <&gateclk 5>;
 		status = "disabled";
 	};
diff --git a/Documentation/devicetree/bindings/phy/phy-bindings.txt b/Documentation/devicetree/bindings/phy/phy-bindings.txt
new file mode 100644
index 0000000..8ae844f
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/phy-bindings.txt
@@ -0,0 +1,66 @@
+This document explains only the device tree data binding. For general
+information about PHY subsystem refer to Documentation/phy.txt
+
+PHY device node
+===============
+
+Required Properties:
+#phy-cells:	Number of cells in a PHY specifier;  The meaning of all those
+		cells is defined by the binding for the phy node. The PHY
+		provider can use the values in cells to find the appropriate
+		PHY.
+
+For example:
+
+phys: phy {
+    compatible = "xxx";
+    reg = <...>;
+    .
+    .
+    #phy-cells = <1>;
+    .
+    .
+};
+
+That node describes an IP block (PHY provider) that implements 2 different PHYs.
+In order to differentiate between these 2 PHYs, an additonal specifier should be
+given while trying to get a reference to it.
+
+PHY user node
+=============
+
+Required Properties:
+phys : the phandle for the PHY device (used by the PHY subsystem)
+phy-names : the names of the PHY corresponding to the PHYs present in the
+	    *phys* phandle
+
+Example 1:
+usb1: usb_otg_ss@xxx {
+    compatible = "xxx";
+    reg = <xxx>;
+    .
+    .
+    phys = <&usb2_phy>, <&usb3_phy>;
+    phy-names = "usb2phy", "usb3phy";
+    .
+    .
+};
+
+This node represents a controller that uses two PHYs, one for usb2 and one for
+usb3.
+
+Example 2:
+usb2: usb_otg_ss@xxx {
+    compatible = "xxx";
+    reg = <xxx>;
+    .
+    .
+    phys = <&phys 1>;
+    phy-names = "usbphy";
+    .
+    .
+};
+
+This node represents a controller that uses one of the PHYs of the PHY provider
+device defined previously. Note that the phy handle has an additional specifier
+"1" to differentiate between the two PHYs.
diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt b/Documentation/devicetree/bindings/phy/samsung-phy.txt
new file mode 100644
index 0000000..c0fccaa
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt
@@ -0,0 +1,22 @@
+Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY
+-------------------------------------------------
+
+Required properties:
+- compatible : should be "samsung,s5pv210-mipi-video-phy";
+- reg : offset and length of the MIPI DPHY register set;
+- #phy-cells : from the generic phy bindings, must be 1;
+
+For "samsung,s5pv210-mipi-video-phy" compatible PHYs the second cell in
+the PHY specifier identifies the PHY and its meaning is as follows:
+  0 - MIPI CSIS 0,
+  1 - MIPI DSIM 0,
+  2 - MIPI CSIS 1,
+  3 - MIPI DSIM 1.
+
+Samsung EXYNOS SoC series Display Port PHY
+-------------------------------------------------
+
+Required properties:
+- compatible : should be "samsung,exynos5250-dp-video-phy";
+- reg : offset and length of the Display Port PHY register set;
+- #phy-cells : from the generic PHY bindings, must be 0;
diff --git a/Documentation/devicetree/bindings/pinctrl/abilis,tb10x-iomux.txt b/Documentation/devicetree/bindings/pinctrl/abilis,tb10x-iomux.txt
new file mode 100644
index 0000000..2c11866
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/abilis,tb10x-iomux.txt
@@ -0,0 +1,80 @@
+Abilis Systems TB10x pin controller
+===================================
+
+Required properties
+-------------------
+
+- compatible: should be "abilis,tb10x-iomux";
+- reg: should contain the physical address and size of the pin controller's
+  register range.
+
+
+Function definitions
+--------------------
+
+Functions are defined (and referenced) by sub-nodes of the pin controller.
+Every sub-node defines exactly one function (implying a set of pins).
+Every function is associated to one named pin group inside the pin controller
+driver and these names are used to associate pin group predefinitions to pin
+controller sub-nodes.
+
+Required function definition subnode properties:
+  - abilis,function: should be set to the name of the function's pin group.
+
+The following pin groups are available:
+  - GPIO ports: gpioa, gpiob, gpioc, gpiod, gpioe, gpiof, gpiog,
+                gpioh, gpioi, gpioj, gpiok, gpiol, gpiom, gpion
+  - Serial TS input ports: mis0, mis1, mis2, mis3, mis4, mis5, mis6, mis7
+  - Parallel TS input ports: mip1, mip3, mip5, mip7
+  - Serial TS output ports: mos0, mos1, mos2, mos3
+  - Parallel TS output port: mop
+  - CI+ port: ciplus
+  - CableCard (Mcard) port: mcard
+  - Smart card ports: stc0, stc1
+  - UART ports: uart0, uart1
+  - SPI ports: spi1, spi3
+  - JTAG: jtag
+
+All other ports of the chip are not multiplexed and thus not managed by this
+driver.
+
+
+GPIO ranges definition
+----------------------
+
+The named pin groups of GPIO ports can be used to define GPIO ranges as
+explained in Documentation/devicetree/bindings/gpio/gpio.txt.
+
+
+Example
+-------
+
+iomux: iomux@FF10601c {
+	compatible = "abilis,tb10x-iomux";
+	reg = <0xFF10601c 0x4>;
+	pctl_gpio_a: pctl-gpio-a {
+		abilis,function = "gpioa";
+	};
+	pctl_uart0: pctl-uart0 {
+		abilis,function = "uart0";
+	};
+};
+uart@FF100000 {
+	compatible = "snps,dw-apb-uart";
+	reg = <0xFF100000 0x100>;
+	clock-frequency = <166666666>;
+	interrupts = <25 1>;
+	reg-shift = <2>;
+	reg-io-width = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pctl_uart0>;
+};
+gpioa: gpio@FF140000 {
+	compatible = "abilis,tb10x-gpio";
+	reg = <0xFF140000 0x1000>;
+	gpio-controller;
+	#gpio-cells = <2>;
+	ngpio = <3>;
+	gpio-ranges = <&iomux 0 0>;
+	gpio-ranges-group-names = "gpioa";
+};
diff --git a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
index 7ccae49..02ab5ab 100644
--- a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
@@ -18,7 +18,7 @@
 such as pull-up, multi drive, etc.
 
 Required properties for iomux controller:
-- compatible: "atmel,at91rm9200-pinctrl"
+- compatible: "atmel,at91rm9200-pinctrl" or "atmel,at91sam9x5-pinctrl"
 - atmel,mux-mask: array of mask (periph per bank) to describe if a pin can be
   configured in this periph mode. All the periph and bank need to be describe.
 
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt
index 3a7caf7..9fde25f 100644
--- a/Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt
@@ -22,11 +22,12 @@
   Please refer to each fsl,<soc>-pinctrl.txt binding doc for supported SoCs.
 
 Required properties for pin configuration node:
-- fsl,pins: two integers array, represents a group of pins mux and config
-  setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is a
-  pin working on a specific function, which consists of a tuple of
-  <mux_reg conf_reg input_reg mux_val input_val>.  CONFIG is the pad setting
-  value like pull-up on this pin.
+- fsl,pins: each entry consists of 6 integers and represents the mux and config
+  setting for one pin. The first 5 integers <mux_reg conf_reg input_reg mux_val
+  input_val> are specified using a PIN_FUNC_ID macro, which can be found in
+  imx*-pinfunc.h under device tree source folder. The last integer CONFIG is
+  the pad setting value like pull-up on this pin. And that's why fsl,pins entry
+  looks like <PIN_FUNC_ID CONFIG> in the example below.
 
 Bits used for CONFIG:
 NO_PAD_CTL(1 << 31): indicate this pin does not need config.
@@ -72,17 +73,18 @@
 	/* shared pinctrl settings */
 	usdhc4 {
 		pinctrl_usdhc4_1: usdhc4grp-1 {
-			fsl,pins = <1386 0x17059	/* MX6Q_PAD_SD4_CMD__USDHC4_CMD */
-				    1392 0x10059	/* MX6Q_PAD_SD4_CLK__USDHC4_CLK	*/
-				    1462 0x17059	/* MX6Q_PAD_SD4_DAT0__USDHC4_DAT0 */
-				    1470 0x17059	/* MX6Q_PAD_SD4_DAT1__USDHC4_DAT1 */
-				    1478 0x17059	/* MX6Q_PAD_SD4_DAT2__USDHC4_DAT2 */
-				    1486 0x17059	/* MX6Q_PAD_SD4_DAT3__USDHC4_DAT3 */
-				    1493 0x17059	/* MX6Q_PAD_SD4_DAT4__USDHC4_DAT4 */
-				    1501 0x17059	/* MX6Q_PAD_SD4_DAT5__USDHC4_DAT5 */
-				    1509 0x17059	/* MX6Q_PAD_SD4_DAT6__USDHC4_DAT6 */
-				    1517 0x17059>;	/* MX6Q_PAD_SD4_DAT7__USDHC4_DAT7 */
-		};
+			fsl,pins = <
+				MX6QDL_PAD_SD4_CMD__SD4_CMD    0x17059
+				MX6QDL_PAD_SD4_CLK__SD4_CLK    0x10059
+				MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
+				MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
+				MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
+				MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
+				MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
+				MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
+				MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
+				MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
+			>;
 	};
 	....
 };
@@ -90,6 +92,3 @@
 0x17059 means enable hysteresis, 47KOhm Pull Up, 50Mhz speed,
 80Ohm driver strength and Fast Slew Rate.
 User should refer to each SoC spec to set the correct value.
-
-TODO: when dtc macro support is available, we can change above raw data
-to dt macro which can get better readability in dts file.
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx27-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx27-pinctrl.txt
new file mode 100644
index 0000000..353eca0
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx27-pinctrl.txt
@@ -0,0 +1,99 @@
+* Freescale IMX27 IOMUX Controller
+
+Required properties:
+- compatible: "fsl,imx27-iomuxc"
+
+The iomuxc driver node should define subnodes containing of pinctrl configuration subnodes.
+
+Required properties for pin configuration node:
+- fsl,pins: three integers array, represents a group of pins mux and config
+  setting. The format is fsl,pins = <PIN MUX_ID CONFIG>.
+
+  PIN is an integer between 0 and 0xbf. imx27 has 6 ports with 32 configurable
+  configurable pins each. PIN is PORT * 32 + PORT_PIN, PORT_PIN is the pin
+  number on the specific port (between 0 and 31).
+
+  MUX_ID is
+    function + (direction << 2) + (gpio_oconf << 4) + (gpio_iconfa << 8) + (gpio_iconfb << 10)
+
+      function value is used to select the pin function.
+      Possible values:
+          0 - Primary function
+          1 - Alternate function
+          2 - GPIO
+      Registers: GIUS (GPIO In Use), GPR (General Purpose Register)
+
+      direction defines the data direction of the pin.
+      Possible values:
+          0 - Input
+          1 - Output
+      Register: DDIR
+
+      gpio_oconf configures the gpio submodule output signal. This does not
+      have any effect unless GPIO function is selected. A/B/C_IN are output
+      signals of function blocks A,B and C. Specific function blocks are
+      described in the reference manual.
+      Possible values:
+          0 - A_IN
+          1 - B_IN
+          2 - C_IN
+          3 - Data Register
+      Registers: OCR1, OCR2
+
+      gpio_iconfa/b configures the gpio submodule input to functionblocks A and
+      B. GPIO function should be selected if this is configured.
+      Possible values:
+          0 - GPIO_IN
+          1 - Interrupt Status Register
+          2 - Pulldown
+          3 - Pullup
+      Registers ICONFA1, ICONFA2, ICONFB1 and ICONFB2
+
+  CONFIG can be 0 or 1, meaning Pullup disable/enable.
+
+
+
+Example:
+
+iomuxc: iomuxc@10015000 {
+	compatible = "fsl,imx27-iomuxc";
+	reg = <0x10015000 0x600>;
+
+	uart {
+		pinctrl_uart1: uart-1 {
+			fsl,pins = <
+				0x8c 0x004 0x0 /* UART1_TXD__UART1_TXD */
+				0x8d 0x000 0x0 /* UART1_RXD__UART1_RXD */
+				0x8e 0x004 0x0 /* UART1_CTS__UART1_CTS */
+				0x8f 0x000 0x0 /* UART1_RTS__UART1_RTS */
+			>;
+		};
+
+		...
+	};
+};
+
+
+For convenience there are macros defined in imx27-pinfunc.h which provide PIN
+and MUX_ID. They are structured as MX27_PAD_<Pad name>__<Signal name>. The names
+are defined in the i.MX27 reference manual.
+
+The above example using macros:
+
+iomuxc: iomuxc@10015000 {
+	compatible = "fsl,imx27-iomuxc";
+	reg = <0x10015000 0x600>;
+
+	uart {
+		pinctrl_uart1: uart-1 {
+			fsl,pins = <
+				MX27_PAD_UART1_TXD__UART1_TXD 0x0
+				MX27_PAD_UART1_RXD__UART1_RXD 0x0
+				MX27_PAD_UART1_CTS__UART1_CTS 0x0
+				MX27_PAD_UART1_RTS__UART1_RTS 0x0
+			>;
+		};
+
+		...
+	};
+};
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
index 3077370..1e70a8a 100644
--- a/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,mxs-pinctrl.txt
@@ -59,16 +59,16 @@
 
 Optional subnode-properties:
 - fsl,drive-strength: Integer.
-    0: 4 mA
-    1: 8 mA
-    2: 12 mA
-    3: 16 mA
+    0: MXS_DRIVE_4mA
+    1: MXS_DRIVE_8mA
+    2: MXS_DRIVE_12mA
+    3: MXS_DRIVE_16mA
 - fsl,voltage: Integer.
-    0: 1.8 V
-    1: 3.3 V
+    0: MXS_VOLTAGE_LOW  - 1.8 V
+    1: MXS_VOLTAGE_HIGH - 3.3 V
 - fsl,pull-up: Integer.
-    0: Disable the internal pull-up
-    1: Enable the internal pull-up
+    0: MXS_PULL_DISABLE - Disable the internal pull-up
+    1: MXS_PULL_ENABLE  - Enable the internal pull-up
 
 Note that when enabling the pull-up, the internal pad keeper gets disabled.
 Also, some pins doesn't have a pull up, in that case, setting the fsl,pull-up
@@ -85,23 +85,32 @@
 	mmc0_8bit_pins_a: mmc0-8bit@0 {
 		reg = <0>;
 		fsl,pinmux-ids = <
-			0x2000 0x2010 0x2020 0x2030
-			0x2040 0x2050 0x2060 0x2070
-			0x2080 0x2090 0x20a0>;
-		fsl,drive-strength = <1>;
-		fsl,voltage = <1>;
-		fsl,pull-up = <1>;
+			MX28_PAD_SSP0_DATA0__SSP0_D0
+			MX28_PAD_SSP0_DATA1__SSP0_D1
+			MX28_PAD_SSP0_DATA2__SSP0_D2
+			MX28_PAD_SSP0_DATA3__SSP0_D3
+			MX28_PAD_SSP0_DATA4__SSP0_D4
+			MX28_PAD_SSP0_DATA5__SSP0_D5
+			MX28_PAD_SSP0_DATA6__SSP0_D6
+			MX28_PAD_SSP0_DATA7__SSP0_D7
+			MX28_PAD_SSP0_CMD__SSP0_CMD
+			MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT
+			MX28_PAD_SSP0_SCK__SSP0_SCK
+		>;
+		fsl,drive-strength = <MXS_DRIVE_4mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_ENABLE>;
 	};
 
 	mmc_cd_cfg: mmc-cd-cfg {
-		fsl,pinmux-ids = <0x2090>;
-		fsl,pull-up = <0>;
+		fsl,pinmux-ids = <MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
 	};
 
 	mmc_sck_cfg: mmc-sck-cfg {
-		fsl,pinmux-ids = <0x20a0>;
-		fsl,drive-strength = <2>;
-		fsl,pull-up = <0>;
+		fsl,pinmux-ids = <MX28_PAD_SSP0_SCK__SSP0_SCK>;
+		fsl,drive-strength = <MXS_DRIVE_12mA>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
 	};
 };
 
@@ -112,811 +121,7 @@
 node mmc0-8bit defines.  Only the configuration properties to be adjusted need
 to be listed in the config nodes.
 
-Valid values for i.MX28 pinmux-id:
-
-pinmux						id
-------						--
-MX28_PAD_GPMI_D00__GPMI_D0			0x0000
-MX28_PAD_GPMI_D01__GPMI_D1			0x0010
-MX28_PAD_GPMI_D02__GPMI_D2			0x0020
-MX28_PAD_GPMI_D03__GPMI_D3			0x0030
-MX28_PAD_GPMI_D04__GPMI_D4			0x0040
-MX28_PAD_GPMI_D05__GPMI_D5			0x0050
-MX28_PAD_GPMI_D06__GPMI_D6			0x0060
-MX28_PAD_GPMI_D07__GPMI_D7			0x0070
-MX28_PAD_GPMI_CE0N__GPMI_CE0N			0x0100
-MX28_PAD_GPMI_CE1N__GPMI_CE1N			0x0110
-MX28_PAD_GPMI_CE2N__GPMI_CE2N			0x0120
-MX28_PAD_GPMI_CE3N__GPMI_CE3N			0x0130
-MX28_PAD_GPMI_RDY0__GPMI_READY0			0x0140
-MX28_PAD_GPMI_RDY1__GPMI_READY1			0x0150
-MX28_PAD_GPMI_RDY2__GPMI_READY2			0x0160
-MX28_PAD_GPMI_RDY3__GPMI_READY3			0x0170
-MX28_PAD_GPMI_RDN__GPMI_RDN			0x0180
-MX28_PAD_GPMI_WRN__GPMI_WRN			0x0190
-MX28_PAD_GPMI_ALE__GPMI_ALE			0x01a0
-MX28_PAD_GPMI_CLE__GPMI_CLE			0x01b0
-MX28_PAD_GPMI_RESETN__GPMI_RESETN		0x01c0
-MX28_PAD_LCD_D00__LCD_D0			0x1000
-MX28_PAD_LCD_D01__LCD_D1			0x1010
-MX28_PAD_LCD_D02__LCD_D2			0x1020
-MX28_PAD_LCD_D03__LCD_D3			0x1030
-MX28_PAD_LCD_D04__LCD_D4			0x1040
-MX28_PAD_LCD_D05__LCD_D5			0x1050
-MX28_PAD_LCD_D06__LCD_D6			0x1060
-MX28_PAD_LCD_D07__LCD_D7			0x1070
-MX28_PAD_LCD_D08__LCD_D8			0x1080
-MX28_PAD_LCD_D09__LCD_D9			0x1090
-MX28_PAD_LCD_D10__LCD_D10			0x10a0
-MX28_PAD_LCD_D11__LCD_D11			0x10b0
-MX28_PAD_LCD_D12__LCD_D12			0x10c0
-MX28_PAD_LCD_D13__LCD_D13			0x10d0
-MX28_PAD_LCD_D14__LCD_D14			0x10e0
-MX28_PAD_LCD_D15__LCD_D15			0x10f0
-MX28_PAD_LCD_D16__LCD_D16			0x1100
-MX28_PAD_LCD_D17__LCD_D17			0x1110
-MX28_PAD_LCD_D18__LCD_D18			0x1120
-MX28_PAD_LCD_D19__LCD_D19			0x1130
-MX28_PAD_LCD_D20__LCD_D20			0x1140
-MX28_PAD_LCD_D21__LCD_D21			0x1150
-MX28_PAD_LCD_D22__LCD_D22			0x1160
-MX28_PAD_LCD_D23__LCD_D23			0x1170
-MX28_PAD_LCD_RD_E__LCD_RD_E			0x1180
-MX28_PAD_LCD_WR_RWN__LCD_WR_RWN			0x1190
-MX28_PAD_LCD_RS__LCD_RS				0x11a0
-MX28_PAD_LCD_CS__LCD_CS				0x11b0
-MX28_PAD_LCD_VSYNC__LCD_VSYNC			0x11c0
-MX28_PAD_LCD_HSYNC__LCD_HSYNC			0x11d0
-MX28_PAD_LCD_DOTCLK__LCD_DOTCLK			0x11e0
-MX28_PAD_LCD_ENABLE__LCD_ENABLE			0x11f0
-MX28_PAD_SSP0_DATA0__SSP0_D0			0x2000
-MX28_PAD_SSP0_DATA1__SSP0_D1			0x2010
-MX28_PAD_SSP0_DATA2__SSP0_D2			0x2020
-MX28_PAD_SSP0_DATA3__SSP0_D3			0x2030
-MX28_PAD_SSP0_DATA4__SSP0_D4			0x2040
-MX28_PAD_SSP0_DATA5__SSP0_D5			0x2050
-MX28_PAD_SSP0_DATA6__SSP0_D6			0x2060
-MX28_PAD_SSP0_DATA7__SSP0_D7			0x2070
-MX28_PAD_SSP0_CMD__SSP0_CMD			0x2080
-MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT		0x2090
-MX28_PAD_SSP0_SCK__SSP0_SCK			0x20a0
-MX28_PAD_SSP1_SCK__SSP1_SCK			0x20c0
-MX28_PAD_SSP1_CMD__SSP1_CMD			0x20d0
-MX28_PAD_SSP1_DATA0__SSP1_D0			0x20e0
-MX28_PAD_SSP1_DATA3__SSP1_D3			0x20f0
-MX28_PAD_SSP2_SCK__SSP2_SCK			0x2100
-MX28_PAD_SSP2_MOSI__SSP2_CMD			0x2110
-MX28_PAD_SSP2_MISO__SSP2_D0			0x2120
-MX28_PAD_SSP2_SS0__SSP2_D3			0x2130
-MX28_PAD_SSP2_SS1__SSP2_D4			0x2140
-MX28_PAD_SSP2_SS2__SSP2_D5			0x2150
-MX28_PAD_SSP3_SCK__SSP3_SCK			0x2180
-MX28_PAD_SSP3_MOSI__SSP3_CMD			0x2190
-MX28_PAD_SSP3_MISO__SSP3_D0			0x21a0
-MX28_PAD_SSP3_SS0__SSP3_D3			0x21b0
-MX28_PAD_AUART0_RX__AUART0_RX			0x3000
-MX28_PAD_AUART0_TX__AUART0_TX			0x3010
-MX28_PAD_AUART0_CTS__AUART0_CTS			0x3020
-MX28_PAD_AUART0_RTS__AUART0_RTS			0x3030
-MX28_PAD_AUART1_RX__AUART1_RX			0x3040
-MX28_PAD_AUART1_TX__AUART1_TX			0x3050
-MX28_PAD_AUART1_CTS__AUART1_CTS			0x3060
-MX28_PAD_AUART1_RTS__AUART1_RTS			0x3070
-MX28_PAD_AUART2_RX__AUART2_RX			0x3080
-MX28_PAD_AUART2_TX__AUART2_TX			0x3090
-MX28_PAD_AUART2_CTS__AUART2_CTS			0x30a0
-MX28_PAD_AUART2_RTS__AUART2_RTS			0x30b0
-MX28_PAD_AUART3_RX__AUART3_RX			0x30c0
-MX28_PAD_AUART3_TX__AUART3_TX			0x30d0
-MX28_PAD_AUART3_CTS__AUART3_CTS			0x30e0
-MX28_PAD_AUART3_RTS__AUART3_RTS			0x30f0
-MX28_PAD_PWM0__PWM_0				0x3100
-MX28_PAD_PWM1__PWM_1				0x3110
-MX28_PAD_PWM2__PWM_2				0x3120
-MX28_PAD_SAIF0_MCLK__SAIF0_MCLK			0x3140
-MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK		0x3150
-MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK		0x3160
-MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0		0x3170
-MX28_PAD_I2C0_SCL__I2C0_SCL			0x3180
-MX28_PAD_I2C0_SDA__I2C0_SDA			0x3190
-MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0		0x31a0
-MX28_PAD_SPDIF__SPDIF_TX			0x31b0
-MX28_PAD_PWM3__PWM_3				0x31c0
-MX28_PAD_PWM4__PWM_4				0x31d0
-MX28_PAD_LCD_RESET__LCD_RESET			0x31e0
-MX28_PAD_ENET0_MDC__ENET0_MDC			0x4000
-MX28_PAD_ENET0_MDIO__ENET0_MDIO			0x4010
-MX28_PAD_ENET0_RX_EN__ENET0_RX_EN		0x4020
-MX28_PAD_ENET0_RXD0__ENET0_RXD0			0x4030
-MX28_PAD_ENET0_RXD1__ENET0_RXD1			0x4040
-MX28_PAD_ENET0_TX_CLK__ENET0_TX_CLK		0x4050
-MX28_PAD_ENET0_TX_EN__ENET0_TX_EN		0x4060
-MX28_PAD_ENET0_TXD0__ENET0_TXD0			0x4070
-MX28_PAD_ENET0_TXD1__ENET0_TXD1			0x4080
-MX28_PAD_ENET0_RXD2__ENET0_RXD2			0x4090
-MX28_PAD_ENET0_RXD3__ENET0_RXD3			0x40a0
-MX28_PAD_ENET0_TXD2__ENET0_TXD2			0x40b0
-MX28_PAD_ENET0_TXD3__ENET0_TXD3			0x40c0
-MX28_PAD_ENET0_RX_CLK__ENET0_RX_CLK		0x40d0
-MX28_PAD_ENET0_COL__ENET0_COL			0x40e0
-MX28_PAD_ENET0_CRS__ENET0_CRS			0x40f0
-MX28_PAD_ENET_CLK__CLKCTRL_ENET			0x4100
-MX28_PAD_JTAG_RTCK__JTAG_RTCK			0x4140
-MX28_PAD_EMI_D00__EMI_DATA0			0x5000
-MX28_PAD_EMI_D01__EMI_DATA1			0x5010
-MX28_PAD_EMI_D02__EMI_DATA2			0x5020
-MX28_PAD_EMI_D03__EMI_DATA3			0x5030
-MX28_PAD_EMI_D04__EMI_DATA4			0x5040
-MX28_PAD_EMI_D05__EMI_DATA5			0x5050
-MX28_PAD_EMI_D06__EMI_DATA6			0x5060
-MX28_PAD_EMI_D07__EMI_DATA7			0x5070
-MX28_PAD_EMI_D08__EMI_DATA8			0x5080
-MX28_PAD_EMI_D09__EMI_DATA9			0x5090
-MX28_PAD_EMI_D10__EMI_DATA10			0x50a0
-MX28_PAD_EMI_D11__EMI_DATA11			0x50b0
-MX28_PAD_EMI_D12__EMI_DATA12			0x50c0
-MX28_PAD_EMI_D13__EMI_DATA13			0x50d0
-MX28_PAD_EMI_D14__EMI_DATA14			0x50e0
-MX28_PAD_EMI_D15__EMI_DATA15			0x50f0
-MX28_PAD_EMI_ODT0__EMI_ODT0			0x5100
-MX28_PAD_EMI_DQM0__EMI_DQM0			0x5110
-MX28_PAD_EMI_ODT1__EMI_ODT1			0x5120
-MX28_PAD_EMI_DQM1__EMI_DQM1			0x5130
-MX28_PAD_EMI_DDR_OPEN_FB__EMI_DDR_OPEN_FEEDBACK	0x5140
-MX28_PAD_EMI_CLK__EMI_CLK			0x5150
-MX28_PAD_EMI_DQS0__EMI_DQS0			0x5160
-MX28_PAD_EMI_DQS1__EMI_DQS1			0x5170
-MX28_PAD_EMI_DDR_OPEN__EMI_DDR_OPEN		0x51a0
-MX28_PAD_EMI_A00__EMI_ADDR0			0x6000
-MX28_PAD_EMI_A01__EMI_ADDR1			0x6010
-MX28_PAD_EMI_A02__EMI_ADDR2			0x6020
-MX28_PAD_EMI_A03__EMI_ADDR3			0x6030
-MX28_PAD_EMI_A04__EMI_ADDR4			0x6040
-MX28_PAD_EMI_A05__EMI_ADDR5			0x6050
-MX28_PAD_EMI_A06__EMI_ADDR6			0x6060
-MX28_PAD_EMI_A07__EMI_ADDR7			0x6070
-MX28_PAD_EMI_A08__EMI_ADDR8			0x6080
-MX28_PAD_EMI_A09__EMI_ADDR9			0x6090
-MX28_PAD_EMI_A10__EMI_ADDR10			0x60a0
-MX28_PAD_EMI_A11__EMI_ADDR11			0x60b0
-MX28_PAD_EMI_A12__EMI_ADDR12			0x60c0
-MX28_PAD_EMI_A13__EMI_ADDR13			0x60d0
-MX28_PAD_EMI_A14__EMI_ADDR14			0x60e0
-MX28_PAD_EMI_BA0__EMI_BA0			0x6100
-MX28_PAD_EMI_BA1__EMI_BA1			0x6110
-MX28_PAD_EMI_BA2__EMI_BA2			0x6120
-MX28_PAD_EMI_CASN__EMI_CASN			0x6130
-MX28_PAD_EMI_RASN__EMI_RASN			0x6140
-MX28_PAD_EMI_WEN__EMI_WEN			0x6150
-MX28_PAD_EMI_CE0N__EMI_CE0N			0x6160
-MX28_PAD_EMI_CE1N__EMI_CE1N			0x6170
-MX28_PAD_EMI_CKE__EMI_CKE			0x6180
-MX28_PAD_GPMI_D00__SSP1_D0			0x0001
-MX28_PAD_GPMI_D01__SSP1_D1			0x0011
-MX28_PAD_GPMI_D02__SSP1_D2			0x0021
-MX28_PAD_GPMI_D03__SSP1_D3			0x0031
-MX28_PAD_GPMI_D04__SSP1_D4			0x0041
-MX28_PAD_GPMI_D05__SSP1_D5			0x0051
-MX28_PAD_GPMI_D06__SSP1_D6			0x0061
-MX28_PAD_GPMI_D07__SSP1_D7			0x0071
-MX28_PAD_GPMI_CE0N__SSP3_D0			0x0101
-MX28_PAD_GPMI_CE1N__SSP3_D3			0x0111
-MX28_PAD_GPMI_CE2N__CAN1_TX			0x0121
-MX28_PAD_GPMI_CE3N__CAN1_RX			0x0131
-MX28_PAD_GPMI_RDY0__SSP1_CARD_DETECT		0x0141
-MX28_PAD_GPMI_RDY1__SSP1_CMD			0x0151
-MX28_PAD_GPMI_RDY2__CAN0_TX			0x0161
-MX28_PAD_GPMI_RDY3__CAN0_RX			0x0171
-MX28_PAD_GPMI_RDN__SSP3_SCK			0x0181
-MX28_PAD_GPMI_WRN__SSP1_SCK			0x0191
-MX28_PAD_GPMI_ALE__SSP3_D1			0x01a1
-MX28_PAD_GPMI_CLE__SSP3_D2			0x01b1
-MX28_PAD_GPMI_RESETN__SSP3_CMD			0x01c1
-MX28_PAD_LCD_D03__ETM_DA8			0x1031
-MX28_PAD_LCD_D04__ETM_DA9			0x1041
-MX28_PAD_LCD_D08__ETM_DA3			0x1081
-MX28_PAD_LCD_D09__ETM_DA4			0x1091
-MX28_PAD_LCD_D20__ENET1_1588_EVENT2_OUT		0x1141
-MX28_PAD_LCD_D21__ENET1_1588_EVENT2_IN		0x1151
-MX28_PAD_LCD_D22__ENET1_1588_EVENT3_OUT		0x1161
-MX28_PAD_LCD_D23__ENET1_1588_EVENT3_IN		0x1171
-MX28_PAD_LCD_RD_E__LCD_VSYNC			0x1181
-MX28_PAD_LCD_WR_RWN__LCD_HSYNC			0x1191
-MX28_PAD_LCD_RS__LCD_DOTCLK			0x11a1
-MX28_PAD_LCD_CS__LCD_ENABLE			0x11b1
-MX28_PAD_LCD_VSYNC__SAIF1_SDATA0		0x11c1
-MX28_PAD_LCD_HSYNC__SAIF1_SDATA1		0x11d1
-MX28_PAD_LCD_DOTCLK__SAIF1_MCLK			0x11e1
-MX28_PAD_SSP0_DATA4__SSP2_D0			0x2041
-MX28_PAD_SSP0_DATA5__SSP2_D3			0x2051
-MX28_PAD_SSP0_DATA6__SSP2_CMD			0x2061
-MX28_PAD_SSP0_DATA7__SSP2_SCK			0x2071
-MX28_PAD_SSP1_SCK__SSP2_D1			0x20c1
-MX28_PAD_SSP1_CMD__SSP2_D2			0x20d1
-MX28_PAD_SSP1_DATA0__SSP2_D6			0x20e1
-MX28_PAD_SSP1_DATA3__SSP2_D7			0x20f1
-MX28_PAD_SSP2_SCK__AUART2_RX			0x2101
-MX28_PAD_SSP2_MOSI__AUART2_TX			0x2111
-MX28_PAD_SSP2_MISO__AUART3_RX			0x2121
-MX28_PAD_SSP2_SS0__AUART3_TX			0x2131
-MX28_PAD_SSP2_SS1__SSP2_D1			0x2141
-MX28_PAD_SSP2_SS2__SSP2_D2			0x2151
-MX28_PAD_SSP3_SCK__AUART4_TX			0x2181
-MX28_PAD_SSP3_MOSI__AUART4_RX			0x2191
-MX28_PAD_SSP3_MISO__AUART4_RTS			0x21a1
-MX28_PAD_SSP3_SS0__AUART4_CTS			0x21b1
-MX28_PAD_AUART0_RX__I2C0_SCL			0x3001
-MX28_PAD_AUART0_TX__I2C0_SDA			0x3011
-MX28_PAD_AUART0_CTS__AUART4_RX			0x3021
-MX28_PAD_AUART0_RTS__AUART4_TX			0x3031
-MX28_PAD_AUART1_RX__SSP2_CARD_DETECT		0x3041
-MX28_PAD_AUART1_TX__SSP3_CARD_DETECT		0x3051
-MX28_PAD_AUART1_CTS__USB0_OVERCURRENT		0x3061
-MX28_PAD_AUART1_RTS__USB0_ID			0x3071
-MX28_PAD_AUART2_RX__SSP3_D1			0x3081
-MX28_PAD_AUART2_TX__SSP3_D2			0x3091
-MX28_PAD_AUART2_CTS__I2C1_SCL			0x30a1
-MX28_PAD_AUART2_RTS__I2C1_SDA			0x30b1
-MX28_PAD_AUART3_RX__CAN0_TX			0x30c1
-MX28_PAD_AUART3_TX__CAN0_RX			0x30d1
-MX28_PAD_AUART3_CTS__CAN1_TX			0x30e1
-MX28_PAD_AUART3_RTS__CAN1_RX			0x30f1
-MX28_PAD_PWM0__I2C1_SCL				0x3101
-MX28_PAD_PWM1__I2C1_SDA				0x3111
-MX28_PAD_PWM2__USB0_ID				0x3121
-MX28_PAD_SAIF0_MCLK__PWM_3			0x3141
-MX28_PAD_SAIF0_LRCLK__PWM_4			0x3151
-MX28_PAD_SAIF0_BITCLK__PWM_5			0x3161
-MX28_PAD_SAIF0_SDATA0__PWM_6			0x3171
-MX28_PAD_I2C0_SCL__TIMROT_ROTARYA		0x3181
-MX28_PAD_I2C0_SDA__TIMROT_ROTARYB		0x3191
-MX28_PAD_SAIF1_SDATA0__PWM_7			0x31a1
-MX28_PAD_LCD_RESET__LCD_VSYNC			0x31e1
-MX28_PAD_ENET0_MDC__GPMI_CE4N			0x4001
-MX28_PAD_ENET0_MDIO__GPMI_CE5N			0x4011
-MX28_PAD_ENET0_RX_EN__GPMI_CE6N			0x4021
-MX28_PAD_ENET0_RXD0__GPMI_CE7N			0x4031
-MX28_PAD_ENET0_RXD1__GPMI_READY4		0x4041
-MX28_PAD_ENET0_TX_CLK__HSADC_TRIGGER		0x4051
-MX28_PAD_ENET0_TX_EN__GPMI_READY5		0x4061
-MX28_PAD_ENET0_TXD0__GPMI_READY6		0x4071
-MX28_PAD_ENET0_TXD1__GPMI_READY7		0x4081
-MX28_PAD_ENET0_RXD2__ENET1_RXD0			0x4091
-MX28_PAD_ENET0_RXD3__ENET1_RXD1			0x40a1
-MX28_PAD_ENET0_TXD2__ENET1_TXD0			0x40b1
-MX28_PAD_ENET0_TXD3__ENET1_TXD1			0x40c1
-MX28_PAD_ENET0_RX_CLK__ENET0_RX_ER		0x40d1
-MX28_PAD_ENET0_COL__ENET1_TX_EN			0x40e1
-MX28_PAD_ENET0_CRS__ENET1_RX_EN			0x40f1
-MX28_PAD_GPMI_CE2N__ENET0_RX_ER			0x0122
-MX28_PAD_GPMI_CE3N__SAIF1_MCLK			0x0132
-MX28_PAD_GPMI_RDY0__USB0_ID			0x0142
-MX28_PAD_GPMI_RDY2__ENET0_TX_ER			0x0162
-MX28_PAD_GPMI_RDY3__HSADC_TRIGGER		0x0172
-MX28_PAD_GPMI_ALE__SSP3_D4			0x01a2
-MX28_PAD_GPMI_CLE__SSP3_D5			0x01b2
-MX28_PAD_LCD_D00__ETM_DA0			0x1002
-MX28_PAD_LCD_D01__ETM_DA1			0x1012
-MX28_PAD_LCD_D02__ETM_DA2			0x1022
-MX28_PAD_LCD_D03__ETM_DA3			0x1032
-MX28_PAD_LCD_D04__ETM_DA4			0x1042
-MX28_PAD_LCD_D05__ETM_DA5			0x1052
-MX28_PAD_LCD_D06__ETM_DA6			0x1062
-MX28_PAD_LCD_D07__ETM_DA7			0x1072
-MX28_PAD_LCD_D08__ETM_DA8			0x1082
-MX28_PAD_LCD_D09__ETM_DA9			0x1092
-MX28_PAD_LCD_D10__ETM_DA10			0x10a2
-MX28_PAD_LCD_D11__ETM_DA11			0x10b2
-MX28_PAD_LCD_D12__ETM_DA12			0x10c2
-MX28_PAD_LCD_D13__ETM_DA13			0x10d2
-MX28_PAD_LCD_D14__ETM_DA14			0x10e2
-MX28_PAD_LCD_D15__ETM_DA15			0x10f2
-MX28_PAD_LCD_D16__ETM_DA7			0x1102
-MX28_PAD_LCD_D17__ETM_DA6			0x1112
-MX28_PAD_LCD_D18__ETM_DA5			0x1122
-MX28_PAD_LCD_D19__ETM_DA4			0x1132
-MX28_PAD_LCD_D20__ETM_DA3			0x1142
-MX28_PAD_LCD_D21__ETM_DA2			0x1152
-MX28_PAD_LCD_D22__ETM_DA1			0x1162
-MX28_PAD_LCD_D23__ETM_DA0			0x1172
-MX28_PAD_LCD_RD_E__ETM_TCTL			0x1182
-MX28_PAD_LCD_WR_RWN__ETM_TCLK			0x1192
-MX28_PAD_LCD_HSYNC__ETM_TCTL			0x11d2
-MX28_PAD_LCD_DOTCLK__ETM_TCLK			0x11e2
-MX28_PAD_SSP1_SCK__ENET0_1588_EVENT2_OUT	0x20c2
-MX28_PAD_SSP1_CMD__ENET0_1588_EVENT2_IN		0x20d2
-MX28_PAD_SSP1_DATA0__ENET0_1588_EVENT3_OUT	0x20e2
-MX28_PAD_SSP1_DATA3__ENET0_1588_EVENT3_IN	0x20f2
-MX28_PAD_SSP2_SCK__SAIF0_SDATA1			0x2102
-MX28_PAD_SSP2_MOSI__SAIF0_SDATA2		0x2112
-MX28_PAD_SSP2_MISO__SAIF1_SDATA1		0x2122
-MX28_PAD_SSP2_SS0__SAIF1_SDATA2			0x2132
-MX28_PAD_SSP2_SS1__USB1_OVERCURRENT		0x2142
-MX28_PAD_SSP2_SS2__USB0_OVERCURRENT		0x2152
-MX28_PAD_SSP3_SCK__ENET1_1588_EVENT0_OUT	0x2182
-MX28_PAD_SSP3_MOSI__ENET1_1588_EVENT0_IN	0x2192
-MX28_PAD_SSP3_MISO__ENET1_1588_EVENT1_OUT	0x21a2
-MX28_PAD_SSP3_SS0__ENET1_1588_EVENT1_IN		0x21b2
-MX28_PAD_AUART0_RX__DUART_CTS			0x3002
-MX28_PAD_AUART0_TX__DUART_RTS			0x3012
-MX28_PAD_AUART0_CTS__DUART_RX			0x3022
-MX28_PAD_AUART0_RTS__DUART_TX			0x3032
-MX28_PAD_AUART1_RX__PWM_0			0x3042
-MX28_PAD_AUART1_TX__PWM_1			0x3052
-MX28_PAD_AUART1_CTS__TIMROT_ROTARYA		0x3062
-MX28_PAD_AUART1_RTS__TIMROT_ROTARYB		0x3072
-MX28_PAD_AUART2_RX__SSP3_D4			0x3082
-MX28_PAD_AUART2_TX__SSP3_D5			0x3092
-MX28_PAD_AUART2_CTS__SAIF1_BITCLK		0x30a2
-MX28_PAD_AUART2_RTS__SAIF1_LRCLK		0x30b2
-MX28_PAD_AUART3_RX__ENET0_1588_EVENT0_OUT	0x30c2
-MX28_PAD_AUART3_TX__ENET0_1588_EVENT0_IN	0x30d2
-MX28_PAD_AUART3_CTS__ENET0_1588_EVENT1_OUT	0x30e2
-MX28_PAD_AUART3_RTS__ENET0_1588_EVENT1_IN	0x30f2
-MX28_PAD_PWM0__DUART_RX				0x3102
-MX28_PAD_PWM1__DUART_TX				0x3112
-MX28_PAD_PWM2__USB1_OVERCURRENT			0x3122
-MX28_PAD_SAIF0_MCLK__AUART4_CTS			0x3142
-MX28_PAD_SAIF0_LRCLK__AUART4_RTS		0x3152
-MX28_PAD_SAIF0_BITCLK__AUART4_RX		0x3162
-MX28_PAD_SAIF0_SDATA0__AUART4_TX		0x3172
-MX28_PAD_I2C0_SCL__DUART_RX			0x3182
-MX28_PAD_I2C0_SDA__DUART_TX			0x3192
-MX28_PAD_SAIF1_SDATA0__SAIF0_SDATA1		0x31a2
-MX28_PAD_SPDIF__ENET1_RX_ER			0x31b2
-MX28_PAD_ENET0_MDC__SAIF0_SDATA1		0x4002
-MX28_PAD_ENET0_MDIO__SAIF0_SDATA2		0x4012
-MX28_PAD_ENET0_RX_EN__SAIF1_SDATA1		0x4022
-MX28_PAD_ENET0_RXD0__SAIF1_SDATA2		0x4032
-MX28_PAD_ENET0_TX_CLK__ENET0_1588_EVENT2_OUT	0x4052
-MX28_PAD_ENET0_RXD2__ENET0_1588_EVENT0_OUT	0x4092
-MX28_PAD_ENET0_RXD3__ENET0_1588_EVENT0_IN	0x40a2
-MX28_PAD_ENET0_TXD2__ENET0_1588_EVENT1_OUT	0x40b2
-MX28_PAD_ENET0_TXD3__ENET0_1588_EVENT1_IN	0x40c2
-MX28_PAD_ENET0_RX_CLK__ENET0_1588_EVENT2_IN	0x40d2
-MX28_PAD_ENET0_COL__ENET0_1588_EVENT3_OUT	0x40e2
-MX28_PAD_ENET0_CRS__ENET0_1588_EVENT3_IN	0x40f2
-MX28_PAD_GPMI_D00__GPIO_0_0			0x0003
-MX28_PAD_GPMI_D01__GPIO_0_1			0x0013
-MX28_PAD_GPMI_D02__GPIO_0_2			0x0023
-MX28_PAD_GPMI_D03__GPIO_0_3			0x0033
-MX28_PAD_GPMI_D04__GPIO_0_4			0x0043
-MX28_PAD_GPMI_D05__GPIO_0_5			0x0053
-MX28_PAD_GPMI_D06__GPIO_0_6			0x0063
-MX28_PAD_GPMI_D07__GPIO_0_7			0x0073
-MX28_PAD_GPMI_CE0N__GPIO_0_16			0x0103
-MX28_PAD_GPMI_CE1N__GPIO_0_17			0x0113
-MX28_PAD_GPMI_CE2N__GPIO_0_18			0x0123
-MX28_PAD_GPMI_CE3N__GPIO_0_19			0x0133
-MX28_PAD_GPMI_RDY0__GPIO_0_20			0x0143
-MX28_PAD_GPMI_RDY1__GPIO_0_21			0x0153
-MX28_PAD_GPMI_RDY2__GPIO_0_22			0x0163
-MX28_PAD_GPMI_RDY3__GPIO_0_23			0x0173
-MX28_PAD_GPMI_RDN__GPIO_0_24			0x0183
-MX28_PAD_GPMI_WRN__GPIO_0_25			0x0193
-MX28_PAD_GPMI_ALE__GPIO_0_26			0x01a3
-MX28_PAD_GPMI_CLE__GPIO_0_27			0x01b3
-MX28_PAD_GPMI_RESETN__GPIO_0_28			0x01c3
-MX28_PAD_LCD_D00__GPIO_1_0			0x1003
-MX28_PAD_LCD_D01__GPIO_1_1			0x1013
-MX28_PAD_LCD_D02__GPIO_1_2			0x1023
-MX28_PAD_LCD_D03__GPIO_1_3			0x1033
-MX28_PAD_LCD_D04__GPIO_1_4			0x1043
-MX28_PAD_LCD_D05__GPIO_1_5			0x1053
-MX28_PAD_LCD_D06__GPIO_1_6			0x1063
-MX28_PAD_LCD_D07__GPIO_1_7			0x1073
-MX28_PAD_LCD_D08__GPIO_1_8			0x1083
-MX28_PAD_LCD_D09__GPIO_1_9			0x1093
-MX28_PAD_LCD_D10__GPIO_1_10			0x10a3
-MX28_PAD_LCD_D11__GPIO_1_11			0x10b3
-MX28_PAD_LCD_D12__GPIO_1_12			0x10c3
-MX28_PAD_LCD_D13__GPIO_1_13			0x10d3
-MX28_PAD_LCD_D14__GPIO_1_14			0x10e3
-MX28_PAD_LCD_D15__GPIO_1_15			0x10f3
-MX28_PAD_LCD_D16__GPIO_1_16			0x1103
-MX28_PAD_LCD_D17__GPIO_1_17			0x1113
-MX28_PAD_LCD_D18__GPIO_1_18			0x1123
-MX28_PAD_LCD_D19__GPIO_1_19			0x1133
-MX28_PAD_LCD_D20__GPIO_1_20			0x1143
-MX28_PAD_LCD_D21__GPIO_1_21			0x1153
-MX28_PAD_LCD_D22__GPIO_1_22			0x1163
-MX28_PAD_LCD_D23__GPIO_1_23			0x1173
-MX28_PAD_LCD_RD_E__GPIO_1_24			0x1183
-MX28_PAD_LCD_WR_RWN__GPIO_1_25			0x1193
-MX28_PAD_LCD_RS__GPIO_1_26			0x11a3
-MX28_PAD_LCD_CS__GPIO_1_27			0x11b3
-MX28_PAD_LCD_VSYNC__GPIO_1_28			0x11c3
-MX28_PAD_LCD_HSYNC__GPIO_1_29			0x11d3
-MX28_PAD_LCD_DOTCLK__GPIO_1_30			0x11e3
-MX28_PAD_LCD_ENABLE__GPIO_1_31			0x11f3
-MX28_PAD_SSP0_DATA0__GPIO_2_0			0x2003
-MX28_PAD_SSP0_DATA1__GPIO_2_1			0x2013
-MX28_PAD_SSP0_DATA2__GPIO_2_2			0x2023
-MX28_PAD_SSP0_DATA3__GPIO_2_3			0x2033
-MX28_PAD_SSP0_DATA4__GPIO_2_4			0x2043
-MX28_PAD_SSP0_DATA5__GPIO_2_5			0x2053
-MX28_PAD_SSP0_DATA6__GPIO_2_6			0x2063
-MX28_PAD_SSP0_DATA7__GPIO_2_7			0x2073
-MX28_PAD_SSP0_CMD__GPIO_2_8			0x2083
-MX28_PAD_SSP0_DETECT__GPIO_2_9			0x2093
-MX28_PAD_SSP0_SCK__GPIO_2_10			0x20a3
-MX28_PAD_SSP1_SCK__GPIO_2_12			0x20c3
-MX28_PAD_SSP1_CMD__GPIO_2_13			0x20d3
-MX28_PAD_SSP1_DATA0__GPIO_2_14			0x20e3
-MX28_PAD_SSP1_DATA3__GPIO_2_15			0x20f3
-MX28_PAD_SSP2_SCK__GPIO_2_16			0x2103
-MX28_PAD_SSP2_MOSI__GPIO_2_17			0x2113
-MX28_PAD_SSP2_MISO__GPIO_2_18			0x2123
-MX28_PAD_SSP2_SS0__GPIO_2_19			0x2133
-MX28_PAD_SSP2_SS1__GPIO_2_20			0x2143
-MX28_PAD_SSP2_SS2__GPIO_2_21			0x2153
-MX28_PAD_SSP3_SCK__GPIO_2_24			0x2183
-MX28_PAD_SSP3_MOSI__GPIO_2_25			0x2193
-MX28_PAD_SSP3_MISO__GPIO_2_26			0x21a3
-MX28_PAD_SSP3_SS0__GPIO_2_27			0x21b3
-MX28_PAD_AUART0_RX__GPIO_3_0			0x3003
-MX28_PAD_AUART0_TX__GPIO_3_1			0x3013
-MX28_PAD_AUART0_CTS__GPIO_3_2			0x3023
-MX28_PAD_AUART0_RTS__GPIO_3_3			0x3033
-MX28_PAD_AUART1_RX__GPIO_3_4			0x3043
-MX28_PAD_AUART1_TX__GPIO_3_5			0x3053
-MX28_PAD_AUART1_CTS__GPIO_3_6			0x3063
-MX28_PAD_AUART1_RTS__GPIO_3_7			0x3073
-MX28_PAD_AUART2_RX__GPIO_3_8			0x3083
-MX28_PAD_AUART2_TX__GPIO_3_9			0x3093
-MX28_PAD_AUART2_CTS__GPIO_3_10			0x30a3
-MX28_PAD_AUART2_RTS__GPIO_3_11			0x30b3
-MX28_PAD_AUART3_RX__GPIO_3_12			0x30c3
-MX28_PAD_AUART3_TX__GPIO_3_13			0x30d3
-MX28_PAD_AUART3_CTS__GPIO_3_14			0x30e3
-MX28_PAD_AUART3_RTS__GPIO_3_15			0x30f3
-MX28_PAD_PWM0__GPIO_3_16			0x3103
-MX28_PAD_PWM1__GPIO_3_17			0x3113
-MX28_PAD_PWM2__GPIO_3_18			0x3123
-MX28_PAD_SAIF0_MCLK__GPIO_3_20			0x3143
-MX28_PAD_SAIF0_LRCLK__GPIO_3_21			0x3153
-MX28_PAD_SAIF0_BITCLK__GPIO_3_22		0x3163
-MX28_PAD_SAIF0_SDATA0__GPIO_3_23		0x3173
-MX28_PAD_I2C0_SCL__GPIO_3_24			0x3183
-MX28_PAD_I2C0_SDA__GPIO_3_25			0x3193
-MX28_PAD_SAIF1_SDATA0__GPIO_3_26		0x31a3
-MX28_PAD_SPDIF__GPIO_3_27			0x31b3
-MX28_PAD_PWM3__GPIO_3_28			0x31c3
-MX28_PAD_PWM4__GPIO_3_29			0x31d3
-MX28_PAD_LCD_RESET__GPIO_3_30			0x31e3
-MX28_PAD_ENET0_MDC__GPIO_4_0			0x4003
-MX28_PAD_ENET0_MDIO__GPIO_4_1			0x4013
-MX28_PAD_ENET0_RX_EN__GPIO_4_2			0x4023
-MX28_PAD_ENET0_RXD0__GPIO_4_3			0x4033
-MX28_PAD_ENET0_RXD1__GPIO_4_4			0x4043
-MX28_PAD_ENET0_TX_CLK__GPIO_4_5			0x4053
-MX28_PAD_ENET0_TX_EN__GPIO_4_6			0x4063
-MX28_PAD_ENET0_TXD0__GPIO_4_7			0x4073
-MX28_PAD_ENET0_TXD1__GPIO_4_8			0x4083
-MX28_PAD_ENET0_RXD2__GPIO_4_9			0x4093
-MX28_PAD_ENET0_RXD3__GPIO_4_10			0x40a3
-MX28_PAD_ENET0_TXD2__GPIO_4_11			0x40b3
-MX28_PAD_ENET0_TXD3__GPIO_4_12			0x40c3
-MX28_PAD_ENET0_RX_CLK__GPIO_4_13		0x40d3
-MX28_PAD_ENET0_COL__GPIO_4_14			0x40e3
-MX28_PAD_ENET0_CRS__GPIO_4_15			0x40f3
-MX28_PAD_ENET_CLK__GPIO_4_16			0x4103
-MX28_PAD_JTAG_RTCK__GPIO_4_20			0x4143
-
-Valid values for i.MX23 pinmux-id:
-
-pinmux						id
-------						--
-MX23_PAD_GPMI_D00__GPMI_D00			0x0000
-MX23_PAD_GPMI_D01__GPMI_D01			0x0010
-MX23_PAD_GPMI_D02__GPMI_D02			0x0020
-MX23_PAD_GPMI_D03__GPMI_D03			0x0030
-MX23_PAD_GPMI_D04__GPMI_D04			0x0040
-MX23_PAD_GPMI_D05__GPMI_D05			0x0050
-MX23_PAD_GPMI_D06__GPMI_D06			0x0060
-MX23_PAD_GPMI_D07__GPMI_D07			0x0070
-MX23_PAD_GPMI_D08__GPMI_D08			0x0080
-MX23_PAD_GPMI_D09__GPMI_D09			0x0090
-MX23_PAD_GPMI_D10__GPMI_D10			0x00a0
-MX23_PAD_GPMI_D11__GPMI_D11			0x00b0
-MX23_PAD_GPMI_D12__GPMI_D12			0x00c0
-MX23_PAD_GPMI_D13__GPMI_D13			0x00d0
-MX23_PAD_GPMI_D14__GPMI_D14			0x00e0
-MX23_PAD_GPMI_D15__GPMI_D15			0x00f0
-MX23_PAD_GPMI_CLE__GPMI_CLE			0x0100
-MX23_PAD_GPMI_ALE__GPMI_ALE			0x0110
-MX23_PAD_GPMI_CE2N__GPMI_CE2N			0x0120
-MX23_PAD_GPMI_RDY0__GPMI_RDY0			0x0130
-MX23_PAD_GPMI_RDY1__GPMI_RDY1			0x0140
-MX23_PAD_GPMI_RDY2__GPMI_RDY2			0x0150
-MX23_PAD_GPMI_RDY3__GPMI_RDY3			0x0160
-MX23_PAD_GPMI_WPN__GPMI_WPN			0x0170
-MX23_PAD_GPMI_WRN__GPMI_WRN			0x0180
-MX23_PAD_GPMI_RDN__GPMI_RDN			0x0190
-MX23_PAD_AUART1_CTS__AUART1_CTS			0x01a0
-MX23_PAD_AUART1_RTS__AUART1_RTS			0x01b0
-MX23_PAD_AUART1_RX__AUART1_RX			0x01c0
-MX23_PAD_AUART1_TX__AUART1_TX			0x01d0
-MX23_PAD_I2C_SCL__I2C_SCL			0x01e0
-MX23_PAD_I2C_SDA__I2C_SDA			0x01f0
-MX23_PAD_LCD_D00__LCD_D00			0x1000
-MX23_PAD_LCD_D01__LCD_D01			0x1010
-MX23_PAD_LCD_D02__LCD_D02			0x1020
-MX23_PAD_LCD_D03__LCD_D03			0x1030
-MX23_PAD_LCD_D04__LCD_D04			0x1040
-MX23_PAD_LCD_D05__LCD_D05			0x1050
-MX23_PAD_LCD_D06__LCD_D06			0x1060
-MX23_PAD_LCD_D07__LCD_D07			0x1070
-MX23_PAD_LCD_D08__LCD_D08			0x1080
-MX23_PAD_LCD_D09__LCD_D09			0x1090
-MX23_PAD_LCD_D10__LCD_D10			0x10a0
-MX23_PAD_LCD_D11__LCD_D11			0x10b0
-MX23_PAD_LCD_D12__LCD_D12			0x10c0
-MX23_PAD_LCD_D13__LCD_D13			0x10d0
-MX23_PAD_LCD_D14__LCD_D14			0x10e0
-MX23_PAD_LCD_D15__LCD_D15			0x10f0
-MX23_PAD_LCD_D16__LCD_D16			0x1100
-MX23_PAD_LCD_D17__LCD_D17			0x1110
-MX23_PAD_LCD_RESET__LCD_RESET			0x1120
-MX23_PAD_LCD_RS__LCD_RS				0x1130
-MX23_PAD_LCD_WR__LCD_WR				0x1140
-MX23_PAD_LCD_CS__LCD_CS				0x1150
-MX23_PAD_LCD_DOTCK__LCD_DOTCK			0x1160
-MX23_PAD_LCD_ENABLE__LCD_ENABLE			0x1170
-MX23_PAD_LCD_HSYNC__LCD_HSYNC			0x1180
-MX23_PAD_LCD_VSYNC__LCD_VSYNC			0x1190
-MX23_PAD_PWM0__PWM0				0x11a0
-MX23_PAD_PWM1__PWM1				0x11b0
-MX23_PAD_PWM2__PWM2				0x11c0
-MX23_PAD_PWM3__PWM3				0x11d0
-MX23_PAD_PWM4__PWM4				0x11e0
-MX23_PAD_SSP1_CMD__SSP1_CMD			0x2000
-MX23_PAD_SSP1_DETECT__SSP1_DETECT		0x2010
-MX23_PAD_SSP1_DATA0__SSP1_DATA0			0x2020
-MX23_PAD_SSP1_DATA1__SSP1_DATA1			0x2030
-MX23_PAD_SSP1_DATA2__SSP1_DATA2			0x2040
-MX23_PAD_SSP1_DATA3__SSP1_DATA3			0x2050
-MX23_PAD_SSP1_SCK__SSP1_SCK			0x2060
-MX23_PAD_ROTARYA__ROTARYA			0x2070
-MX23_PAD_ROTARYB__ROTARYB			0x2080
-MX23_PAD_EMI_A00__EMI_A00			0x2090
-MX23_PAD_EMI_A01__EMI_A01			0x20a0
-MX23_PAD_EMI_A02__EMI_A02			0x20b0
-MX23_PAD_EMI_A03__EMI_A03			0x20c0
-MX23_PAD_EMI_A04__EMI_A04			0x20d0
-MX23_PAD_EMI_A05__EMI_A05			0x20e0
-MX23_PAD_EMI_A06__EMI_A06			0x20f0
-MX23_PAD_EMI_A07__EMI_A07			0x2100
-MX23_PAD_EMI_A08__EMI_A08			0x2110
-MX23_PAD_EMI_A09__EMI_A09			0x2120
-MX23_PAD_EMI_A10__EMI_A10			0x2130
-MX23_PAD_EMI_A11__EMI_A11			0x2140
-MX23_PAD_EMI_A12__EMI_A12			0x2150
-MX23_PAD_EMI_BA0__EMI_BA0			0x2160
-MX23_PAD_EMI_BA1__EMI_BA1			0x2170
-MX23_PAD_EMI_CASN__EMI_CASN			0x2180
-MX23_PAD_EMI_CE0N__EMI_CE0N			0x2190
-MX23_PAD_EMI_CE1N__EMI_CE1N			0x21a0
-MX23_PAD_GPMI_CE1N__GPMI_CE1N			0x21b0
-MX23_PAD_GPMI_CE0N__GPMI_CE0N			0x21c0
-MX23_PAD_EMI_CKE__EMI_CKE			0x21d0
-MX23_PAD_EMI_RASN__EMI_RASN			0x21e0
-MX23_PAD_EMI_WEN__EMI_WEN			0x21f0
-MX23_PAD_EMI_D00__EMI_D00			0x3000
-MX23_PAD_EMI_D01__EMI_D01			0x3010
-MX23_PAD_EMI_D02__EMI_D02			0x3020
-MX23_PAD_EMI_D03__EMI_D03			0x3030
-MX23_PAD_EMI_D04__EMI_D04			0x3040
-MX23_PAD_EMI_D05__EMI_D05			0x3050
-MX23_PAD_EMI_D06__EMI_D06			0x3060
-MX23_PAD_EMI_D07__EMI_D07			0x3070
-MX23_PAD_EMI_D08__EMI_D08			0x3080
-MX23_PAD_EMI_D09__EMI_D09			0x3090
-MX23_PAD_EMI_D10__EMI_D10			0x30a0
-MX23_PAD_EMI_D11__EMI_D11			0x30b0
-MX23_PAD_EMI_D12__EMI_D12			0x30c0
-MX23_PAD_EMI_D13__EMI_D13			0x30d0
-MX23_PAD_EMI_D14__EMI_D14			0x30e0
-MX23_PAD_EMI_D15__EMI_D15			0x30f0
-MX23_PAD_EMI_DQM0__EMI_DQM0			0x3100
-MX23_PAD_EMI_DQM1__EMI_DQM1			0x3110
-MX23_PAD_EMI_DQS0__EMI_DQS0			0x3120
-MX23_PAD_EMI_DQS1__EMI_DQS1			0x3130
-MX23_PAD_EMI_CLK__EMI_CLK			0x3140
-MX23_PAD_EMI_CLKN__EMI_CLKN			0x3150
-MX23_PAD_GPMI_D00__LCD_D8			0x0001
-MX23_PAD_GPMI_D01__LCD_D9			0x0011
-MX23_PAD_GPMI_D02__LCD_D10			0x0021
-MX23_PAD_GPMI_D03__LCD_D11			0x0031
-MX23_PAD_GPMI_D04__LCD_D12			0x0041
-MX23_PAD_GPMI_D05__LCD_D13			0x0051
-MX23_PAD_GPMI_D06__LCD_D14			0x0061
-MX23_PAD_GPMI_D07__LCD_D15			0x0071
-MX23_PAD_GPMI_D08__LCD_D18			0x0081
-MX23_PAD_GPMI_D09__LCD_D19			0x0091
-MX23_PAD_GPMI_D10__LCD_D20			0x00a1
-MX23_PAD_GPMI_D11__LCD_D21			0x00b1
-MX23_PAD_GPMI_D12__LCD_D22			0x00c1
-MX23_PAD_GPMI_D13__LCD_D23			0x00d1
-MX23_PAD_GPMI_D14__AUART2_RX			0x00e1
-MX23_PAD_GPMI_D15__AUART2_TX			0x00f1
-MX23_PAD_GPMI_CLE__LCD_D16			0x0101
-MX23_PAD_GPMI_ALE__LCD_D17			0x0111
-MX23_PAD_GPMI_CE2N__ATA_A2			0x0121
-MX23_PAD_AUART1_RTS__IR_CLK			0x01b1
-MX23_PAD_AUART1_RX__IR_RX			0x01c1
-MX23_PAD_AUART1_TX__IR_TX			0x01d1
-MX23_PAD_I2C_SCL__GPMI_RDY2			0x01e1
-MX23_PAD_I2C_SDA__GPMI_CE2N			0x01f1
-MX23_PAD_LCD_D00__ETM_DA8			0x1001
-MX23_PAD_LCD_D01__ETM_DA9			0x1011
-MX23_PAD_LCD_D02__ETM_DA10			0x1021
-MX23_PAD_LCD_D03__ETM_DA11			0x1031
-MX23_PAD_LCD_D04__ETM_DA12			0x1041
-MX23_PAD_LCD_D05__ETM_DA13			0x1051
-MX23_PAD_LCD_D06__ETM_DA14			0x1061
-MX23_PAD_LCD_D07__ETM_DA15			0x1071
-MX23_PAD_LCD_D08__ETM_DA0			0x1081
-MX23_PAD_LCD_D09__ETM_DA1			0x1091
-MX23_PAD_LCD_D10__ETM_DA2			0x10a1
-MX23_PAD_LCD_D11__ETM_DA3			0x10b1
-MX23_PAD_LCD_D12__ETM_DA4			0x10c1
-MX23_PAD_LCD_D13__ETM_DA5			0x10d1
-MX23_PAD_LCD_D14__ETM_DA6			0x10e1
-MX23_PAD_LCD_D15__ETM_DA7			0x10f1
-MX23_PAD_LCD_RESET__ETM_TCTL			0x1121
-MX23_PAD_LCD_RS__ETM_TCLK			0x1131
-MX23_PAD_LCD_DOTCK__GPMI_RDY3			0x1161
-MX23_PAD_LCD_ENABLE__I2C_SCL			0x1171
-MX23_PAD_LCD_HSYNC__I2C_SDA			0x1181
-MX23_PAD_LCD_VSYNC__LCD_BUSY			0x1191
-MX23_PAD_PWM0__ROTARYA				0x11a1
-MX23_PAD_PWM1__ROTARYB				0x11b1
-MX23_PAD_PWM2__GPMI_RDY3			0x11c1
-MX23_PAD_PWM3__ETM_TCTL				0x11d1
-MX23_PAD_PWM4__ETM_TCLK				0x11e1
-MX23_PAD_SSP1_DETECT__GPMI_CE3N			0x2011
-MX23_PAD_SSP1_DATA1__I2C_SCL			0x2031
-MX23_PAD_SSP1_DATA2__I2C_SDA			0x2041
-MX23_PAD_ROTARYA__AUART2_RTS			0x2071
-MX23_PAD_ROTARYB__AUART2_CTS			0x2081
-MX23_PAD_GPMI_D00__SSP2_DATA0			0x0002
-MX23_PAD_GPMI_D01__SSP2_DATA1			0x0012
-MX23_PAD_GPMI_D02__SSP2_DATA2			0x0022
-MX23_PAD_GPMI_D03__SSP2_DATA3			0x0032
-MX23_PAD_GPMI_D04__SSP2_DATA4			0x0042
-MX23_PAD_GPMI_D05__SSP2_DATA5			0x0052
-MX23_PAD_GPMI_D06__SSP2_DATA6			0x0062
-MX23_PAD_GPMI_D07__SSP2_DATA7			0x0072
-MX23_PAD_GPMI_D08__SSP1_DATA4			0x0082
-MX23_PAD_GPMI_D09__SSP1_DATA5			0x0092
-MX23_PAD_GPMI_D10__SSP1_DATA6			0x00a2
-MX23_PAD_GPMI_D11__SSP1_DATA7			0x00b2
-MX23_PAD_GPMI_D15__GPMI_CE3N			0x00f2
-MX23_PAD_GPMI_RDY0__SSP2_DETECT			0x0132
-MX23_PAD_GPMI_RDY1__SSP2_CMD			0x0142
-MX23_PAD_GPMI_WRN__SSP2_SCK			0x0182
-MX23_PAD_AUART1_CTS__SSP1_DATA4			0x01a2
-MX23_PAD_AUART1_RTS__SSP1_DATA5			0x01b2
-MX23_PAD_AUART1_RX__SSP1_DATA6			0x01c2
-MX23_PAD_AUART1_TX__SSP1_DATA7			0x01d2
-MX23_PAD_I2C_SCL__AUART1_TX			0x01e2
-MX23_PAD_I2C_SDA__AUART1_RX			0x01f2
-MX23_PAD_LCD_D08__SAIF2_SDATA0			0x1082
-MX23_PAD_LCD_D09__SAIF1_SDATA0			0x1092
-MX23_PAD_LCD_D10__SAIF_MCLK_BITCLK		0x10a2
-MX23_PAD_LCD_D11__SAIF_LRCLK			0x10b2
-MX23_PAD_LCD_D12__SAIF2_SDATA1			0x10c2
-MX23_PAD_LCD_D13__SAIF2_SDATA2			0x10d2
-MX23_PAD_LCD_D14__SAIF1_SDATA2			0x10e2
-MX23_PAD_LCD_D15__SAIF1_SDATA1			0x10f2
-MX23_PAD_LCD_D16__SAIF_ALT_BITCLK		0x1102
-MX23_PAD_LCD_RESET__GPMI_CE3N			0x1122
-MX23_PAD_PWM0__DUART_RX				0x11a2
-MX23_PAD_PWM1__DUART_TX				0x11b2
-MX23_PAD_PWM3__AUART1_CTS			0x11d2
-MX23_PAD_PWM4__AUART1_RTS			0x11e2
-MX23_PAD_SSP1_CMD__JTAG_TDO			0x2002
-MX23_PAD_SSP1_DETECT__USB_OTG_ID		0x2012
-MX23_PAD_SSP1_DATA0__JTAG_TDI			0x2022
-MX23_PAD_SSP1_DATA1__JTAG_TCLK			0x2032
-MX23_PAD_SSP1_DATA2__JTAG_RTCK			0x2042
-MX23_PAD_SSP1_DATA3__JTAG_TMS			0x2052
-MX23_PAD_SSP1_SCK__JTAG_TRST			0x2062
-MX23_PAD_ROTARYA__SPDIF				0x2072
-MX23_PAD_ROTARYB__GPMI_CE3N			0x2082
-MX23_PAD_GPMI_D00__GPIO_0_0			0x0003
-MX23_PAD_GPMI_D01__GPIO_0_1			0x0013
-MX23_PAD_GPMI_D02__GPIO_0_2			0x0023
-MX23_PAD_GPMI_D03__GPIO_0_3			0x0033
-MX23_PAD_GPMI_D04__GPIO_0_4			0x0043
-MX23_PAD_GPMI_D05__GPIO_0_5			0x0053
-MX23_PAD_GPMI_D06__GPIO_0_6			0x0063
-MX23_PAD_GPMI_D07__GPIO_0_7			0x0073
-MX23_PAD_GPMI_D08__GPIO_0_8			0x0083
-MX23_PAD_GPMI_D09__GPIO_0_9			0x0093
-MX23_PAD_GPMI_D10__GPIO_0_10			0x00a3
-MX23_PAD_GPMI_D11__GPIO_0_11			0x00b3
-MX23_PAD_GPMI_D12__GPIO_0_12			0x00c3
-MX23_PAD_GPMI_D13__GPIO_0_13			0x00d3
-MX23_PAD_GPMI_D14__GPIO_0_14			0x00e3
-MX23_PAD_GPMI_D15__GPIO_0_15			0x00f3
-MX23_PAD_GPMI_CLE__GPIO_0_16			0x0103
-MX23_PAD_GPMI_ALE__GPIO_0_17			0x0113
-MX23_PAD_GPMI_CE2N__GPIO_0_18			0x0123
-MX23_PAD_GPMI_RDY0__GPIO_0_19			0x0133
-MX23_PAD_GPMI_RDY1__GPIO_0_20			0x0143
-MX23_PAD_GPMI_RDY2__GPIO_0_21			0x0153
-MX23_PAD_GPMI_RDY3__GPIO_0_22			0x0163
-MX23_PAD_GPMI_WPN__GPIO_0_23			0x0173
-MX23_PAD_GPMI_WRN__GPIO_0_24			0x0183
-MX23_PAD_GPMI_RDN__GPIO_0_25			0x0193
-MX23_PAD_AUART1_CTS__GPIO_0_26			0x01a3
-MX23_PAD_AUART1_RTS__GPIO_0_27			0x01b3
-MX23_PAD_AUART1_RX__GPIO_0_28			0x01c3
-MX23_PAD_AUART1_TX__GPIO_0_29			0x01d3
-MX23_PAD_I2C_SCL__GPIO_0_30			0x01e3
-MX23_PAD_I2C_SDA__GPIO_0_31			0x01f3
-MX23_PAD_LCD_D00__GPIO_1_0			0x1003
-MX23_PAD_LCD_D01__GPIO_1_1			0x1013
-MX23_PAD_LCD_D02__GPIO_1_2			0x1023
-MX23_PAD_LCD_D03__GPIO_1_3			0x1033
-MX23_PAD_LCD_D04__GPIO_1_4			0x1043
-MX23_PAD_LCD_D05__GPIO_1_5			0x1053
-MX23_PAD_LCD_D06__GPIO_1_6			0x1063
-MX23_PAD_LCD_D07__GPIO_1_7			0x1073
-MX23_PAD_LCD_D08__GPIO_1_8			0x1083
-MX23_PAD_LCD_D09__GPIO_1_9			0x1093
-MX23_PAD_LCD_D10__GPIO_1_10			0x10a3
-MX23_PAD_LCD_D11__GPIO_1_11			0x10b3
-MX23_PAD_LCD_D12__GPIO_1_12			0x10c3
-MX23_PAD_LCD_D13__GPIO_1_13			0x10d3
-MX23_PAD_LCD_D14__GPIO_1_14			0x10e3
-MX23_PAD_LCD_D15__GPIO_1_15			0x10f3
-MX23_PAD_LCD_D16__GPIO_1_16			0x1103
-MX23_PAD_LCD_D17__GPIO_1_17			0x1113
-MX23_PAD_LCD_RESET__GPIO_1_18			0x1123
-MX23_PAD_LCD_RS__GPIO_1_19			0x1133
-MX23_PAD_LCD_WR__GPIO_1_20			0x1143
-MX23_PAD_LCD_CS__GPIO_1_21			0x1153
-MX23_PAD_LCD_DOTCK__GPIO_1_22			0x1163
-MX23_PAD_LCD_ENABLE__GPIO_1_23			0x1173
-MX23_PAD_LCD_HSYNC__GPIO_1_24			0x1183
-MX23_PAD_LCD_VSYNC__GPIO_1_25			0x1193
-MX23_PAD_PWM0__GPIO_1_26			0x11a3
-MX23_PAD_PWM1__GPIO_1_27			0x11b3
-MX23_PAD_PWM2__GPIO_1_28			0x11c3
-MX23_PAD_PWM3__GPIO_1_29			0x11d3
-MX23_PAD_PWM4__GPIO_1_30			0x11e3
-MX23_PAD_SSP1_CMD__GPIO_2_0			0x2003
-MX23_PAD_SSP1_DETECT__GPIO_2_1			0x2013
-MX23_PAD_SSP1_DATA0__GPIO_2_2			0x2023
-MX23_PAD_SSP1_DATA1__GPIO_2_3			0x2033
-MX23_PAD_SSP1_DATA2__GPIO_2_4			0x2043
-MX23_PAD_SSP1_DATA3__GPIO_2_5			0x2053
-MX23_PAD_SSP1_SCK__GPIO_2_6			0x2063
-MX23_PAD_ROTARYA__GPIO_2_7			0x2073
-MX23_PAD_ROTARYB__GPIO_2_8			0x2083
-MX23_PAD_EMI_A00__GPIO_2_9			0x2093
-MX23_PAD_EMI_A01__GPIO_2_10			0x20a3
-MX23_PAD_EMI_A02__GPIO_2_11			0x20b3
-MX23_PAD_EMI_A03__GPIO_2_12			0x20c3
-MX23_PAD_EMI_A04__GPIO_2_13			0x20d3
-MX23_PAD_EMI_A05__GPIO_2_14			0x20e3
-MX23_PAD_EMI_A06__GPIO_2_15			0x20f3
-MX23_PAD_EMI_A07__GPIO_2_16			0x2103
-MX23_PAD_EMI_A08__GPIO_2_17			0x2113
-MX23_PAD_EMI_A09__GPIO_2_18			0x2123
-MX23_PAD_EMI_A10__GPIO_2_19			0x2133
-MX23_PAD_EMI_A11__GPIO_2_20			0x2143
-MX23_PAD_EMI_A12__GPIO_2_21			0x2153
-MX23_PAD_EMI_BA0__GPIO_2_22			0x2163
-MX23_PAD_EMI_BA1__GPIO_2_23			0x2173
-MX23_PAD_EMI_CASN__GPIO_2_24			0x2183
-MX23_PAD_EMI_CE0N__GPIO_2_25			0x2193
-MX23_PAD_EMI_CE1N__GPIO_2_26			0x21a3
-MX23_PAD_GPMI_CE1N__GPIO_2_27			0x21b3
-MX23_PAD_GPMI_CE0N__GPIO_2_28			0x21c3
-MX23_PAD_EMI_CKE__GPIO_2_29			0x21d3
-MX23_PAD_EMI_RASN__GPIO_2_30			0x21e3
-MX23_PAD_EMI_WEN__GPIO_2_31			0x21f3
+Valid values for i.MX28/i.MX23 pinmux-id are defined in
+arch/arm/boot/dts/imx28-pinfunc.h and arch/arm/boot/dts/imx23-pinfunc.h.
+The definitions for the padconfig properties can be found in
+arch/arm/boot/dts/mxs-pinfunc.h.
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-palmas.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-palmas.txt
index 734d9b0..caf297b 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-palmas.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-palmas.txt
@@ -41,7 +41,7 @@
 
 Required: pins
 Options: function, bias-disable, bias-pull-up, bias-pull-down,
-	 bias-pin-default, drive-open-drain.
+	 drive-open-drain.
 
 Note that many of these properties are only valid for certain specific pins.
 See the Palmas device datasheet for complete details regarding which pins
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
index 5a02e30..7069a0b 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
@@ -72,6 +72,13 @@
 		/* pin base, nr pins & gpio function */
 		pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1>;
 
+- interrupt-controller : standard interrupt controller binding if using
+  interrupts for wake-up events for example. In this case pinctrl-single
+  is set up as a chained interrupt controller and the wake-up interrupts
+  can be requested by the drivers using request_irq().
+
+- #interrupt-cells : standard interrupt binding if using interrupts
+
 This driver assumes that there is only one register for each pin (unless the
 pinctrl-single,bit-per-mux is set), and uses the common pinctrl bindings as
 specified in the pinctrl-bindings.txt document in this directory.
@@ -121,6 +128,8 @@
 	reg = <0x4a100040 0x0196>;
 	#address-cells = <1>;
 	#size-cells = <0>;
+	#interrupt-cells = <1>;
+	interrupt-controller;
 	pinctrl-single,register-width = <16>;
 	pinctrl-single,function-mask = <0xffff>;
 };
@@ -131,6 +140,8 @@
 	reg = <0x4a31e040 0x0038>;
 	#address-cells = <1>;
 	#size-cells = <0>;
+	#interrupt-cells = <1>;
+	interrupt-controller;
 	pinctrl-single,register-width = <16>;
 	pinctrl-single,function-mask = <0xffff>;
 };
diff --git a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
index b0fb101..f378d34 100644
--- a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
@@ -21,10 +21,13 @@
 Required properties for iomux controller:
   - compatible: one of "rockchip,rk2928-pinctrl", "rockchip,rk3066a-pinctrl"
 		       "rockchip,rk3066b-pinctrl", "rockchip,rk3188-pinctrl"
+  - reg: first element is the general register space of the iomux controller
+	 second element is the separate pull register space of the rk3188
 
 Required properties for gpio sub nodes:
-  - compatible: "rockchip,gpio-bank"
+  - compatible: "rockchip,gpio-bank", "rockchip,rk3188-gpio-bank0"
   - reg: register of the gpio bank (different than the iomux registerset)
+         second element: separate pull register for rk3188 bank0
   - interrupts: base interrupt of the gpio bank in the interrupt controller
   - clocks: clock that drives this bank
   - gpio-controller: identifies the node as a gpio controller and pin bank.
@@ -95,3 +98,44 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart2_xfer>;
 };
+
+Example for rk3188:
+
+	pinctrl@20008000 {
+		compatible = "rockchip,rk3188-pinctrl";
+		reg = <0x20008000 0xa0>,
+		      <0x20008164 0x1a0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		gpio0: gpio0@0x2000a000 {
+			compatible = "rockchip,rk3188-gpio-bank0";
+			reg = <0x2000a000 0x100>,
+			      <0x20004064 0x8>;
+			interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_gates8 9>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio1: gpio1@0x2003c000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x2003c000 0x100>;
+			interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_gates8 10>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		...
+
+	};
diff --git a/Documentation/devicetree/bindings/regulator/as3722-regulator.txt b/Documentation/devicetree/bindings/regulator/as3722-regulator.txt
new file mode 100644
index 0000000..caad0c8
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/as3722-regulator.txt
@@ -0,0 +1,91 @@
+Regulator of AMS AS3722 PMIC.
+Name of the regulator subnode must be "regulators".
+
+Optional properties:
+--------------------
+The input supply of regulators are the optional properties on the
+regulator node. The AS3722 is having 7 DCDC step-down regulators as
+sd[0-6], 10 LDOs as ldo[0-7], ldo[9-11]. The input supply of these
+regulators are provided through following properties:
+vsup-sd2-supply: Input supply for SD2.
+vsup-sd3-supply: Input supply for SD3.
+vsup-sd4-supply: Input supply for SD4.
+vsup-sd5-supply: Input supply for SD5.
+vin-ldo0-supply: Input supply for LDO0.
+vin-ldo1-6-supply: Input supply for LDO1 and LDO6.
+vin-ldo2-5-7-supply: Input supply for LDO2, LDO5 and LDO7.
+vin-ldo3-4-supply: Input supply for LDO3 and LDO4.
+vin-ldo9-10-supply: Input supply for LDO9 and LDO10.
+vin-ldo11-supply: Input supply for LDO11.
+
+Optional nodes:
+--------------
+- regulators : Must contain a sub-node per regulator from the list below.
+	       Each sub-node should contain the constraints and initialization
+	       information for that regulator. See regulator.txt for a
+	       description of standard properties for these sub-nodes.
+	       Additional custom properties  are listed below.
+	       sd[0-6], ldo[0-7], ldo[9-11].
+
+	       Optional sub-node properties:
+	       ----------------------------
+		ams,ext-control: External control of the rail. The option of
+			this properties will tell which external input is
+			controlling this rail. Valid values are 0, 1, 2 ad 3.
+			0: There is no external control of this rail.
+			1: Rail is controlled by ENABLE1 input pin.
+			2: Rail is controlled by ENABLE2 input pin.
+			3: Rail is controlled by ENABLE3 input pin.
+		ams,enable-tracking: Enable tracking with SD1, only supported
+			by LDO3.
+
+Example:
+-------
+	ams3722: ams3722 {
+		compatible = "ams,as3722";
+		reg = <0x40>;
+		...
+
+		regulators {
+			vsup-sd2-supply = <...>;
+			...
+
+			sd0 {
+				regulator-name = "vdd_cpu";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-always-on;
+				ams,ext-control = <2>;
+			};
+
+			sd1 {
+				regulator-name = "vdd_core";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-always-on;
+				ams,ext-control = <1>;
+			};
+
+			sd2 {
+				regulator-name = "vddio_ddr";
+				regulator-min-microvolt = <1350000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+			};
+
+			sd4 {
+				regulator-name = "avdd-hdmi-pex";
+				regulator-min-microvolt = <1050000>;
+				regulator-max-microvolt = <1050000>;
+				regulator-always-on;
+			};
+
+			sd5 {
+				regulator-name = "vdd-1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+			....
+		};
+	};
diff --git a/Documentation/devicetree/bindings/regulator/da9210.txt b/Documentation/devicetree/bindings/regulator/da9210.txt
new file mode 100644
index 0000000..f120f22
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/da9210.txt
@@ -0,0 +1,21 @@
+* Dialog Semiconductor DA9210 Voltage Regulator
+
+Required properties:
+
+- compatible:	must be "diasemi,da9210"
+- reg:		the i2c slave address of the regulator. It should be 0x68.
+
+Any standard regulator properties can be used to configure the single da9210
+DCDC.
+
+Example:
+
+	da9210@68 {
+		compatible = "diasemi,da9210";
+		reg = <0x68>;
+
+		regulator-min-microvolt = <900000>;
+		regulator-max-microvolt = <1000000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
diff --git a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt
index 875639a..42e6b6b 100644
--- a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt
+++ b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt
@@ -26,11 +26,17 @@
 
 	       For ti,palmas-pmic - smps12, smps123, smps3 depending on OTP,
 	       smps45, smps457, smps7 depending on variant, smps6, smps[8-9],
-	       smps10_out2, smps10_out1, do[1-9], ldoln, ldousb.
+	       smps10_out2, smps10_out1, ldo[1-9], ldoln, ldousb.
 
 	       Optional sub-node properties:
 	       ti,warm-reset - maintain voltage during warm reset(boolean)
-	       ti,roof-floor - control voltage selection by pin(boolean)
+	       ti,roof-floor - This takes as optional argument on platform supporting
+	       the rail from desired external control. If there is no argument then
+	       it will be assume that it is controlled by NSLEEP pin.
+	       The valid value for external pins are:
+			ENABLE1 then 1,
+			ENABLE2 then 2 or
+			NSLEEP then 3.
 	       ti,mode-sleep - mode to adopt in pmic sleep 0 - off, 1 - auto,
 	       2 - eco, 3 - forced pwm
 	       ti,smps-range - OTP has the wrong range set for the hardware so override
@@ -61,7 +67,7 @@
 			regulator-always-on;
 			regulator-boot-on;
 			ti,warm-reset;
-			ti,roof-floor;
+			ti,roof-floor = <1>; /* ENABLE1 control */
 			ti,mode-sleep = <0>;
 			ti,smps-range = <1>;
 		};
diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt
index 2bd8f09..e2c7f1e 100644
--- a/Documentation/devicetree/bindings/regulator/regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/regulator.txt
@@ -14,6 +14,11 @@
 - regulator-ramp-delay: ramp delay for regulator(in uV/uS)
   For hardwares which support disabling ramp rate, it should be explicitly
   intialised to zero (regulator-ramp-delay = <0>) for disabling ramp delay.
+- regulator-enable-ramp-delay: The time taken, in microseconds, for the supply
+  rail to reach the target voltage, plus/minus whatever tolerance the board
+  design requires. This property describes the total system ramp time
+  required due to the combination of internal ramping of the regulator itself,
+  and board design issues such as trace capacitance and load on the supply.
 
 Deprecated properties:
 - regulator-compatible: If a regulator chip contains multiple
diff --git a/Documentation/devicetree/bindings/sound/cs42l73.txt b/Documentation/devicetree/bindings/sound/cs42l73.txt
new file mode 100644
index 0000000..80ae910
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/cs42l73.txt
@@ -0,0 +1,22 @@
+CS42L73 audio CODEC
+
+Required properties:
+
+  - compatible : "cirrus,cs42l73"
+
+  - reg : the I2C address of the device for I2C
+
+Optional properties:
+
+  - reset_gpio : a GPIO spec for the reset pin.
+  - chgfreq    : Charge Pump Frequency values 0x00-0x0F
+
+
+Example:
+
+codec: cs42l73@4a {
+	compatible = "cirrus,cs42l73";
+	reg = <0x4a>;
+	reset_gpio = <&gpio 10 0>;
+	chgfreq = <0x05>;
+};
\ No newline at end of file
diff --git a/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt
new file mode 100644
index 0000000..865178d
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt
@@ -0,0 +1,42 @@
+* Texas Instruments SoC audio setups with TLV320AIC3X Codec
+
+Required properties:
+- compatible : "ti,da830-evm-audio" : forDM365/DA8xx/OMAPL1x/AM33xx
+- ti,model : The user-visible name of this sound complex.
+- ti,audio-codec : The phandle of the TLV320AIC3x audio codec
+- ti,mcasp-controller : The phandle of the McASP controller
+- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec
+- ti,audio-routing : A list of the connections between audio components.
+  Each entry is a pair of strings, the first being the connection's sink,
+  the second being the connection's source. Valid names for sources and
+  sinks are the codec's pins, and the jacks on the board:
+
+  Board connectors:
+
+  * Headphone Jack
+  * Line Out
+  * Mic Jack
+  * Line In
+
+
+Example:
+
+sound {
+	compatible = "ti,da830-evm-audio";
+	ti,model = "DA830 EVM";
+	ti,audio-codec = <&tlv320aic3x>;
+	ti,mcasp-controller = <&mcasp1>;
+	ti,codec-clock-rate = <12000000>;
+	ti,audio-routing =
+		"Headphone Jack",       "HPLOUT",
+		"Headphone Jack",       "HPROUT",
+		"Line Out",             "LLOUT",
+		"Line Out",             "RLOUT",
+		"MIC3L",                "Mic Bias 2V",
+		"MIC3R",                "Mic Bias 2V",
+		"Mic Bias 2V",          "Mic Jack",
+		"LINE1L",               "Line In",
+		"LINE2L",               "Line In",
+		"LINE1R",               "Line In",
+		"LINE2R",               "Line In";
+};
diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
index 374e145..ed785b3 100644
--- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
+++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
@@ -4,17 +4,25 @@
 - compatible :
 	"ti,dm646x-mcasp-audio"	: for DM646x platforms
 	"ti,da830-mcasp-audio"	: for both DA830 & DA850 platforms
-	"ti,omap2-mcasp-audio"	: for OMAP2 platforms (TI81xx, AM33xx)
+	"ti,am33xx-mcasp-audio"	: for AM33xx platforms (AM33xx, TI81xx)
 
-- reg : Should contain McASP registers offset and length
-- interrupts : Interrupt number for McASP
-- op-mode : I2S/DIT ops mode.
-- tdm-slots : Slots for TDM operation.
-- num-serializer : Serializers used by McASP.
-- serial-dir : A list of serializer pin mode. The list number should be equal
-		to "num-serializer" parameter. Each entry is a number indication
-		serializer pin direction. (0 - INACTIVE, 1 - TX, 2 - RX)
-
+- reg : Should contain reg specifiers for the entries in the reg-names property.
+- reg-names : Should contain:
+         * "mpu" for the main registers (required). For compatibility with
+           existing software, it is recommended this is the first entry.
+         * "dat" for separate data port register access (optional).
+- op-mode : I2S/DIT ops mode. 0 for I2S mode. 1 for DIT mode used for S/PDIF,
+  	    IEC60958-1, and AES-3 formats.
+- tdm-slots : Slots for TDM operation. Indicates number of channels transmitted
+  	      or received over one serializer.
+- serial-dir : A list of serializer configuration. Each entry is a number
+               indication for serializer pin direction.
+               (0 - INACTIVE, 1 - TX, 2 - RX)
+- dmas: two element list of DMA controller phandles and DMA request line
+        ordered pairs.
+- dma-names: identifier string for each DMA request line in the dmas property.
+	     These strings correspond 1:1 with the ordered pairs in dmas. The dma
+	     identifiers must be "rx" and "tx".
 
 Optional properties:
 
@@ -23,18 +31,23 @@
 - rx-num-evt : FIFO levels.
 - sram-size-playback : size of sram to be allocated during playback
 - sram-size-capture  : size of sram to be allocated during capture
+- interrupts : Interrupt numbers for McASP, currently not used by the driver
+- interrupt-names : Known interrupt names are "tx" and "rx"
+- pinctrl-0: Should specify pin control group used for this controller.
+- pinctrl-names: Should contain only one value - "default", for more details
+  		 please refer to pinctrl-bindings.txt
+  
 
 Example:
 
 mcasp0: mcasp0@1d00000 {
 	compatible = "ti,da830-mcasp-audio";
-	#address-cells = <1>;
-	#size-cells = <0>;
 	reg = <0x100000 0x3000>;
-	interrupts = <82 83>;
+	reg-names "mpu";
+	interrupts = <82>, <83>;
+	interrupts-names = "tx", "rx";
 	op-mode = <0>;		/* MCASP_IIS_MODE */
 	tdm-slots = <2>;
-	num-serializer = <16>;
 	serial-dir = <
 			0 0 0 0	/* 0: INACTIVE, 1: TX, 2: RX */
 			0 0 0 0
diff --git a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
index 705a6b1..5e6040c 100644
--- a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
+++ b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
@@ -24,10 +24,36 @@
 	3 - MICBIAS output is connected to AVDD,
 	If this node is not mentioned or if the value is incorrect, then MicBias
 	is powered down.
+- AVDD-supply, IOVDD-supply, DRVDD-supply, DVDD-supply : power supplies for the
+  device as covered in Documentation/devicetree/bindings/regulator/regulator.txt
+
+CODEC output pins:
+  * LLOUT
+  * RLOUT
+  * MONO_LOUT
+  * HPLOUT
+  * HPROUT
+  * HPLCOM
+  * HPRCOM
+
+CODEC input pins:
+  * MIC3L
+  * MIC3R
+  * LINE1L
+  * LINE2L
+  * LINE1R
+  * LINE2R
+
+The pins can be used in referring sound node's audio-routing property.
 
 Example:
 
 tlv320aic3x: tlv320aic3x@1b {
 	compatible = "ti,tlv320aic3x";
 	reg = <0x1b>;
+
+	AVDD-supply = <&regulator>;
+	IOVDD-supply = <&regulator>;
+	DRVDD-supply = <&regulator>;
+	DVDD-supply = <&regulator>;
 };
diff --git a/Documentation/devicetree/bindings/sound/tpa6130a2.txt b/Documentation/devicetree/bindings/sound/tpa6130a2.txt
new file mode 100644
index 0000000..6dfa740
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tpa6130a2.txt
@@ -0,0 +1,27 @@
+Texas Instruments - tpa6130a2 Codec module
+
+The tpa6130a2 serial control bus communicates through I2C protocols
+
+Required properties:
+
+- compatible - "string" - One of:
+    "ti,tpa6130a2" - TPA6130A2
+    "ti,tpa6140a2" - TPA6140A2
+
+
+- reg - <int> -  I2C slave address
+
+- Vdd-supply - <phandle> - power supply regulator
+
+Optional properties:
+
+- power-gpio - gpio pin to power the device
+
+Example:
+
+tpa6130a2: tpa6130a2@60 {
+	compatible = "ti,tpa6130a2";
+	reg = <0x60>;
+	Vdd-supply = <&vmmc2>;
+	power-gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
+};
diff --git a/Documentation/devicetree/bindings/spi/sh-hspi.txt b/Documentation/devicetree/bindings/spi/sh-hspi.txt
new file mode 100644
index 0000000..30b57b1
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/sh-hspi.txt
@@ -0,0 +1,7 @@
+Renesas HSPI.
+
+Required properties:
+- compatible : 	"renesas,hspi"
+- reg : Offset and length of the register set for the device
+- interrupts : interrupt line used by HSPI
+
diff --git a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
index 4688205..ee05dc3 100644
--- a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
+++ b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
@@ -1,7 +1,8 @@
 * Freescale i.MX28 LRADC device driver
 
 Required properties:
-- compatible: Should be "fsl,imx28-lradc"
+- compatible: Should be "fsl,imx23-lradc" for i.MX23 SoC and "fsl,imx28-lradc"
+              for i.MX28 SoC
 - reg: Address and length of the register set for the device
 - interrupts: Should contain the LRADC interrupts
 
@@ -9,13 +10,38 @@
 - fsl,lradc-touchscreen-wires: Number of wires used to connect the touchscreen
                                to LRADC. Valid value is either 4 or 5. If this
                                property is not present, then the touchscreen is
-                               disabled.
+                               disabled. 5 wires is valid for i.MX28 SoC only.
+- fsl,ave-ctrl: number of samples per direction to calculate an average value.
+                Allowed value is 1 ... 31, default is 4
+- fsl,ave-delay: delay between consecutive samples. Allowed value is
+                 1 ... 2047. It is used if 'fsl,ave-ctrl' > 1, counts at
+                 2 kHz and its default is 2 (= 1 ms)
+- fsl,settling: delay between plate switch to next sample. Allowed value is
+                1 ... 2047. It counts at 2 kHz and its default is
+                10 (= 5 ms)
 
-Examples:
+Example for i.MX23 SoC:
+
+	lradc@80050000 {
+		compatible = "fsl,imx23-lradc";
+		reg = <0x80050000 0x2000>;
+		interrupts = <36 37 38 39 40 41 42 43 44>;
+		status = "okay";
+		fsl,lradc-touchscreen-wires = <4>;
+		fsl,ave-ctrl = <4>;
+		fsl,ave-delay = <2>;
+		fsl,settling = <10>;
+	};
+
+Example for i.MX28 SoC:
 
 	lradc@80050000 {
 		compatible = "fsl,imx28-lradc";
 		reg = <0x80050000 0x2000>;
-		interrupts = <10 14 15 16 17 18 19
-				20 21 22 23 24 25>;
+		interrupts = <10 14 15 16 17 18 19 20 21 22 23 24 25>;
+		status = "okay";
+		fsl,lradc-touchscreen-wires = <5>;
+		fsl,ave-ctrl = <4>;
+		fsl,ave-delay = <2>;
+		fsl,settling = <10>;
 	};
diff --git a/Documentation/devicetree/bindings/timer/efm32,timer.txt b/Documentation/devicetree/bindings/timer/efm32,timer.txt
new file mode 100644
index 0000000..97a568f
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/efm32,timer.txt
@@ -0,0 +1,23 @@
+* EFM32 timer hardware
+
+The efm32 Giant Gecko SoCs come with four 16 bit timers. Two counters can be
+connected to form a 32 bit counter. Each timer has three Compare/Capture
+channels and can be used as PWM or Quadrature Decoder. Available clock sources
+are the cpu's HFPERCLK (with a 10-bit prescaler) or an external pin.
+
+Required properties:
+- compatible : Should be efm32,timer
+- reg : Address and length of the register set
+- clocks : Should contain a reference to the HFPERCLK
+
+Optional properties:
+- interrupts : Reference to the timer interrupt
+
+Example:
+
+timer@40010c00 {
+	compatible = "efm32,timer";
+	reg = <0x40010c00 0x400>;
+	interrupts = <14>;
+	clocks = <&cmu clk_HFPERCLKTIMER3>;
+};
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
new file mode 100644
index 0000000..5ea26c6
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -0,0 +1,17 @@
+MSM SoC HSUSB controllers
+
+EHCI
+
+Required properties:
+- compatible:	Should contain "qcom,ehci-host"
+- regs:			offset and length of the register set in the memory map
+- usb-phy:		phandle for the PHY device
+
+Example EHCI controller device node:
+
+	ehci: ehci@f9a55000 {
+		compatible = "qcom,ehci-host";
+		reg = <0xf9a55000 0x400>;
+		usb-phy = <&usb_otg>;
+	};
+
diff --git a/Documentation/devicetree/bindings/usb/omap-usb.txt b/Documentation/devicetree/bindings/usb/omap-usb.txt
index 9088ab0..090e5e2 100644
--- a/Documentation/devicetree/bindings/usb/omap-usb.txt
+++ b/Documentation/devicetree/bindings/usb/omap-usb.txt
@@ -3,9 +3,6 @@
 OMAP MUSB GLUE
  - compatible : Should be "ti,omap4-musb" or "ti,omap3-musb"
  - ti,hwmods : must be "usb_otg_hs"
- - ti,has-mailbox : to specify that omap uses an external mailbox
-   (in control module) to communicate with the musb core during device connect
-   and disconnect.
  - multipoint : Should be "1" indicating the musb controller supports
    multipoint. This is a MUSB configuration-specific setting.
  - num-eps : Specifies the number of endpoints. This is also a
@@ -19,6 +16,9 @@
  - power : Should be "50". This signifies the controller can supply up to
    100mA when operating in host mode.
  - usb-phy : the phandle for the PHY device
+ - phys : the phandle for the PHY device (used by generic PHY framework)
+ - phy-names : the names of the PHY corresponding to the PHYs present in the
+   *phy* phandle.
 
 Optional properties:
  - ctrl-module : phandle of the control module this glue uses to write to
@@ -28,11 +28,12 @@
 usb_otg_hs: usb_otg_hs@4a0ab000 {
 	compatible = "ti,omap4-musb";
 	ti,hwmods = "usb_otg_hs";
-	ti,has-mailbox;
 	multipoint = <1>;
 	num-eps = <16>;
 	ram-bits = <12>;
 	ctrl-module = <&omap_control_usb>;
+	phys = <&usb2_phy>;
+	phy-names = "usb2-phy";
 };
 
 Board specific device node entry
@@ -78,22 +79,22 @@
 OMAP CONTROL USB
 
 Required properties:
- - compatible: Should be "ti,omap-control-usb"
+ - compatible: Should be one of
+ "ti,control-phy-otghs" - if it has otghs_control mailbox register as on OMAP4.
+ "ti,control-phy-usb2" - if it has Power down bit in control_dev_conf register
+			e.g. USB2_PHY on OMAP5.
+ "ti,control-phy-pipe3" - if it has DPLL and individual Rx & Tx power control
+			e.g. USB3 PHY and SATA PHY on OMAP5.
+ "ti,control-phy-dra7usb2" - if it has power down register like USB2 PHY on
+			DRA7 platform.
  - reg : Address and length of the register set for the device. It contains
-   the address of "control_dev_conf" and "otghs_control" or "phy_power_usb"
-   depending upon omap4 or omap5.
- - reg-names: The names of the register addresses corresponding to the registers
-   filled in "reg".
- - ti,type: This is used to differentiate whether the control module has
-   usb mailbox or usb3 phy power. omap4 has usb mailbox in control module to
-   notify events to the musb core and omap5 has usb3 phy power register to
-   power on usb3 phy. Should be "1" if it has mailbox and "2" if it has usb3
-   phy power.
+   the address of "otghs_control" for control-phy-otghs or "power" register
+   for other types.
+ - reg-names: should be "otghs_control" control-phy-otghs and "power" for
+   other types.
 
 omap_control_usb: omap-control-usb@4a002300 {
-	compatible = "ti,omap-control-usb";
-	reg = <0x4a002300 0x4>,
-	      <0x4a00233c 0x4>;
-	reg-names = "control_dev_conf", "otghs_control";
-	ti,type = <1>;
+	compatible = "ti,control-phy-otghs";
+	reg = <0x4a00233c 0x4>;
+	reg-names = "otghs_control";
 };
diff --git a/Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt b/Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt
index d7e2726..1bd37fa 100644
--- a/Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt
+++ b/Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt
@@ -15,7 +15,7 @@
 
 - vcc-supply: phandle to the regulator that provides RESET to the PHY.
 
-- reset-supply: phandle to the regulator that provides power to the PHY.
+- reset-gpios: Should specify the GPIO for reset.
 
 Example:
 
@@ -25,10 +25,9 @@
 		clocks = <&osc 0>;
 		clock-names = "main_clk";
 		vcc-supply = <&hsusb1_vcc_regulator>;
-		reset-supply = <&hsusb1_reset_regulator>;
+		reset-gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
 	};
 
 hsusb1_phy is a NOP USB PHY device that gets its clock from an oscillator
 and expects that clock to be configured to 19.2MHz by the NOP PHY driver.
-hsusb1_vcc_regulator provides power to the PHY and hsusb1_reset_regulator
-controls RESET.
+hsusb1_vcc_regulator provides power to the PHY and GPIO 7 controls RESET.
diff --git a/Documentation/devicetree/bindings/usb/usb-phy.txt b/Documentation/devicetree/bindings/usb/usb-phy.txt
index 61496f5..c0245c8 100644
--- a/Documentation/devicetree/bindings/usb/usb-phy.txt
+++ b/Documentation/devicetree/bindings/usb/usb-phy.txt
@@ -5,6 +5,8 @@
 Required properties:
  - compatible: Should be "ti,omap-usb2"
  - reg : Address and length of the register set for the device.
+ - #phy-cells: determine the number of cells that should be given in the
+   phandle while referencing this phy.
 
 Optional properties:
  - ctrl-module : phandle of the control module used by PHY driver to power on
@@ -16,6 +18,7 @@
 	compatible = "ti,omap-usb2";
 	reg = <0x4a0ad080 0x58>;
 	ctrl-module = <&omap_control_usb>;
+	#phy-cells = <0>;
 };
 
 OMAP USB3 PHY
@@ -25,6 +28,8 @@
  - reg : Address and length of the register set for the device.
  - reg-names: The names of the register addresses corresponding to the registers
    filled in "reg".
+ - #phy-cells: determine the number of cells that should be given in the
+   phandle while referencing this phy.
 
 Optional properties:
  - ctrl-module : phandle of the control module used by PHY driver to power on
@@ -39,4 +44,5 @@
 	      <0x4a084c00 0x40>;
 	reg-names = "phy_rx", "phy_tx", "pll_ctrl";
 	ctrl-module = <&omap_control_usb>;
+	#phy-cells = <0>;
 };
diff --git a/Documentation/devicetree/bindings/usb/ux500-usb.txt b/Documentation/devicetree/bindings/usb/ux500-usb.txt
index 330d6ec..439a41c 100644
--- a/Documentation/devicetree/bindings/usb/ux500-usb.txt
+++ b/Documentation/devicetree/bindings/usb/ux500-usb.txt
@@ -15,7 +15,7 @@
 Example:
 
 usb_per5@a03e0000 {
-	compatible = "stericsson,db8500-musb", "mentor,musb";
+	compatible = "stericsson,db8500-musb";
 	reg = <0xa03e0000 0x10000>;
 	interrupts = <0 23 0x4>;
 	interrupt-names = "mc";
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 2956800..ce95ed1 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -12,11 +12,15 @@
 apm	Applied Micro Circuits Corporation (APM)
 arm	ARM Ltd.
 atmel	Atmel Corporation
+auo	AU Optronics Corporation
 avago	Avago Technologies
 bosch	Bosch Sensortec GmbH
 brcm	Broadcom Corporation
+capella	Capella Microsystems, Inc
 cavium	Cavium, Inc.
+cdns	Cadence Design Systems Inc.
 chrp	Common Hardware Reference Platform
+chunghwa	Chunghwa Picture Tubes Ltd.
 cirrus	Cirrus Logic, Inc.
 cortina	Cortina Systems, Inc.
 dallas	Maxim Integrated Products (formerly Dallas Semiconductor)
@@ -45,6 +49,8 @@
 nvidia	NVIDIA
 nxp	NXP Semiconductors
 onnn	ON Semiconductor Corp.
+panasonic	Panasonic Corporation
+phytec	PHYTEC Messtechnik GmbH
 picochip	Picochip Ltd
 powervr	PowerVR (deprecated, use img)
 qca	Qualcomm Atheros, Inc.
@@ -64,12 +70,12 @@
 st	STMicroelectronics
 ste	ST-Ericsson
 stericsson	ST-Ericsson
-toumaz	Toumaz
 ti	Texas Instruments
 toshiba	Toshiba Corporation
+toumaz	Toumaz
 v3	V3 Semiconductor
 via	VIA Technologies, Inc.
+winbond Winbond Electronics corp.
 wlf	Wolfson Microelectronics
 wm	Wondermedia Technologies, Inc.
-winbond Winbond Electronics corp.
 xlnx	Xilinx
diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt
index 84f10c1..3289d76 100644
--- a/Documentation/devicetree/bindings/video/exynos_dp.txt
+++ b/Documentation/devicetree/bindings/video/exynos_dp.txt
@@ -6,10 +6,10 @@
 	-dptx-phy node(defined inside dp-controller node)
 
 For the DP-PHY initialization, we use the dptx-phy node.
-Required properties for dptx-phy:
-	-reg:
+Required properties for dptx-phy: deprecated, use phys and phy-names
+	-reg: deprecated
 		Base address of DP PHY register.
-	-samsung,enable-mask:
+	-samsung,enable-mask: deprecated
 		The bit-mask used to enable/disable DP PHY.
 
 For the Panel initialization, we read data from dp-controller node.
@@ -27,6 +27,10 @@
 		from common clock binding: Shall be "dp".
 	-interrupt-parent:
 		phandle to Interrupt combiner node.
+	-phys:
+		from general PHY binding: the phandle for the PHY device.
+	-phy-names:
+		from general PHY binding: Should be "dp".
 	-samsung,color-space:
 		input video data format.
 			COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
@@ -68,11 +72,8 @@
 		clocks = <&clock 342>;
 		clock-names = "dp";
 
-		dptx-phy {
-			reg = <0x10040720>;
-			samsung,enable-mask = <1>;
-		};
-
+		phys = <&dp_phy>;
+		phy-names = "dp";
 	};
 
 Board Specific portion:
diff --git a/Documentation/devicetree/bindings/video/exynos_hdmi.txt b/Documentation/devicetree/bindings/video/exynos_hdmi.txt
index 323983b..50decf8 100644
--- a/Documentation/devicetree/bindings/video/exynos_hdmi.txt
+++ b/Documentation/devicetree/bindings/video/exynos_hdmi.txt
@@ -12,7 +12,19 @@
 	a) phandle of the gpio controller node.
 	b) pin number within the gpio controller.
 	c) optional flags and pull up/down.
-
+- clocks: list of clock IDs from SoC clock driver.
+	a) hdmi: Gate of HDMI IP bus clock.
+	b) sclk_hdmi: Gate of HDMI special clock.
+	c) sclk_pixel: Pixel special clock, one of the two possible inputs of
+		HDMI clock mux.
+	d) sclk_hdmiphy: HDMI PHY clock output, one of two possible inputs of
+		HDMI clock mux.
+	e) mout_hdmi: It is required by the driver to switch between the 2
+		parents i.e. sclk_pixel and sclk_hdmiphy. If hdmiphy is stable
+		after configuration, parent is set to sclk_hdmiphy else
+		sclk_pixel.
+- clock-names: aliases as per driver requirements for above clock IDs:
+	"hdmi", "sclk_hdmi", "sclk_pixel", "sclk_hdmiphy" and "mout_hdmi".
 Example:
 
 	hdmi {
diff --git a/Documentation/devicetree/bindings/video/exynos_mixer.txt b/Documentation/devicetree/bindings/video/exynos_mixer.txt
index 3334b0a..7bfde9c 100644
--- a/Documentation/devicetree/bindings/video/exynos_mixer.txt
+++ b/Documentation/devicetree/bindings/video/exynos_mixer.txt
@@ -10,6 +10,10 @@
 - reg: physical base address of the mixer and length of memory mapped
 	region.
 - interrupts: interrupt number to the cpu.
+- clocks: list of clock IDs from SoC clock driver.
+	a) mixer: Gate of Mixer IP bus clock.
+	b) sclk_hdmi: HDMI Special clock, one of the two possible inputs of
+               mixer mux.
 
 Example:
 
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index fcb34a5..5bdc8cb 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -283,6 +283,7 @@
   devm_regulator_get()
   devm_regulator_put()
   devm_regulator_bulk_get()
+  devm_regulator_register()
 
 CLOCK
   devm_clk_get()
@@ -302,3 +303,6 @@
 
 SLAVE DMA ENGINE
   devm_acpi_dma_controller_register()
+
+SPI
+  devm_spi_register_master()
diff --git a/Documentation/x86/efi-stub.txt b/Documentation/efi-stub.txt
similarity index 100%
rename from Documentation/x86/efi-stub.txt
rename to Documentation/efi-stub.txt
diff --git a/Documentation/extcon/porting-android-switch-class b/Documentation/extcon/porting-android-switch-class
index eb0fa5f..5377f63 100644
--- a/Documentation/extcon/porting-android-switch-class
+++ b/Documentation/extcon/porting-android-switch-class
@@ -25,8 +25,10 @@
     @print_state: no change but type change (switch_dev->extcon_dev)
 
 - switch_dev_register(sdev, dev)
-	=> extcon_dev_register(edev, dev)
-	: no change but type change (sdev->edev)
+	=> extcon_dev_register(edev)
+	: type change (sdev->edev)
+	: remove second param('dev'). if edev has parent device, should store
+	  'dev' to 'edev.dev.parent' before registering extcon device
 - switch_dev_unregister(sdev)
 	=> extcon_dev_unregister(edev)
 	: no change but type change (sdev->edev)
diff --git a/Documentation/filesystems/caching/netfs-api.txt b/Documentation/filesystems/caching/netfs-api.txt
index 11a0a40..aed6b94 100644
--- a/Documentation/filesystems/caching/netfs-api.txt
+++ b/Documentation/filesystems/caching/netfs-api.txt
@@ -29,15 +29,16 @@
 	 (6) Index registration
 	 (7) Data file registration
 	 (8) Miscellaneous object registration
-	 (9) Setting the data file size
+ 	 (9) Setting the data file size
 	(10) Page alloc/read/write
 	(11) Page uncaching
 	(12) Index and data file consistency
-	(13) Miscellaneous cookie operations
-	(14) Cookie unregistration
-	(15) Index invalidation
-	(16) Data file invalidation
-	(17) FS-Cache specific page flags.
+	(13) Cookie enablement
+	(14) Miscellaneous cookie operations
+	(15) Cookie unregistration
+	(16) Index invalidation
+	(17) Data file invalidation
+	(18) FS-Cache specific page flags.
 
 
 =============================
@@ -334,7 +335,8 @@
 	struct fscache_cookie *
 	fscache_acquire_cookie(struct fscache_cookie *parent,
 			       const struct fscache_object_def *def,
-			       void *netfs_data);
+			       void *netfs_data,
+			       bool enable);
 
 This function creates an index entry in the index represented by parent,
 filling in the index entry by calling the operations pointed to by def.
@@ -350,6 +352,10 @@
 may be created in several different caches independently at different times.
 This is all handled transparently, and the netfs doesn't see any of it.
 
+A cookie will be created in the disabled state if enabled is false.  A cookie
+must be enabled to do anything with it.  A disabled cookie can be enabled by
+calling fscache_enable_cookie() (see below).
+
 For example, with AFS, a cell would be added to the primary index.  This index
 entry would have a dependent inode containing a volume location index for the
 volume mappings within this cell:
@@ -357,7 +363,7 @@
 	cell->cache =
 		fscache_acquire_cookie(afs_cache_netfs.primary_index,
 				       &afs_cell_cache_index_def,
-				       cell);
+				       cell, true);
 
 Then when a volume location was accessed, it would be entered into the cell's
 index and an inode would be allocated that acts as a volume type and hash chain
@@ -366,7 +372,7 @@
 	vlocation->cache =
 		fscache_acquire_cookie(cell->cache,
 				       &afs_vlocation_cache_index_def,
-				       vlocation);
+				       vlocation, true);
 
 And then a particular flavour of volume (R/O for example) could be added to
 that index, creating another index for vnodes (AFS inode equivalents):
@@ -374,7 +380,7 @@
 	volume->cache =
 		fscache_acquire_cookie(vlocation->cache,
 				       &afs_volume_cache_index_def,
-				       volume);
+				       volume, true);
 
 
 ======================
@@ -388,7 +394,7 @@
 	vnode->cache =
 		fscache_acquire_cookie(volume->cache,
 				       &afs_vnode_cache_object_def,
-				       vnode);
+				       vnode, true);
 
 
 =================================
@@ -404,7 +410,7 @@
 	xattr->cache =
 		fscache_acquire_cookie(vnode->cache,
 				       &afs_xattr_cache_object_def,
-				       xattr);
+				       xattr, true);
 
 Miscellaneous objects might be used to store extended attributes or directory
 entries for example.
@@ -733,6 +739,47 @@
 data blocks are added to a data file object.
 
 
+=================
+COOKIE ENABLEMENT
+=================
+
+Cookies exist in one of two states: enabled and disabled.  If a cookie is
+disabled, it ignores all attempts to acquire child cookies; check, update or
+invalidate its state; allocate, read or write backing pages - though it is
+still possible to uncache pages and relinquish the cookie.
+
+The initial enablement state is set by fscache_acquire_cookie(), but the cookie
+can be enabled or disabled later.  To disable a cookie, call:
+    
+	void fscache_disable_cookie(struct fscache_cookie *cookie,
+    				    bool invalidate);
+    
+If the cookie is not already disabled, this locks the cookie against other
+enable and disable ops, marks the cookie as being disabled, discards or
+invalidates any backing objects and waits for cessation of activity on any
+associated object before unlocking the cookie.
+
+All possible failures are handled internally.  The caller should consider
+calling fscache_uncache_all_inode_pages() afterwards to make sure all page
+markings are cleared up.
+    
+Cookies can be enabled or reenabled with:
+    
+    	void fscache_enable_cookie(struct fscache_cookie *cookie,
+    				   bool (*can_enable)(void *data),
+    				   void *data)
+    
+If the cookie is not already enabled, this locks the cookie against other
+enable and disable ops, invokes can_enable() and, if the cookie is not an index
+cookie, will begin the procedure of acquiring backing objects.
+
+The optional can_enable() function is passed the data argument and returns a
+ruling as to whether or not enablement should actually be permitted to begin.
+
+All possible failures are handled internally.  The cookie will only be marked
+as enabled if provisional backing objects are allocated.
+
+
 ===============================
 MISCELLANEOUS COOKIE OPERATIONS
 ===============================
@@ -778,7 +825,7 @@
 To get rid of a cookie, this function should be called.
 
 	void fscache_relinquish_cookie(struct fscache_cookie *cookie,
-				       int retire);
+				       bool retire);
 
 If retire is non-zero, then the object will be marked for recycling, and all
 copies of it will be removed from all active caches in which it is present.
diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt
index 3cd27be..a3fe811 100644
--- a/Documentation/filesystems/f2fs.txt
+++ b/Documentation/filesystems/f2fs.txt
@@ -119,6 +119,7 @@
                        Default number is 6.
 disable_ext_identify   Disable the extension list configured by mkfs, so f2fs
                        does not aware of cold files such as media files.
+inline_xattr           Enable the inline xattrs feature.
 
 ================================================================================
 DEBUGFS ENTRIES
@@ -164,6 +165,12 @@
                               gc_idle = 1 will select the Cost Benefit approach
                               & setting gc_idle = 2 will select the greedy aproach.
 
+ reclaim_segments             This parameter controls the number of prefree
+                              segments to be reclaimed. If the number of prefree
+			      segments is larger than this number, f2fs tries to
+			      conduct checkpoint to reclaim the prefree segments
+			      to free segments. By default, 100 segments, 200MB.
+
 ================================================================================
 USAGE
 ================================================================================
diff --git a/Documentation/hwmon/lm25066 b/Documentation/hwmon/lm25066
index c1b57d7..b34c3de 100644
--- a/Documentation/hwmon/lm25066
+++ b/Documentation/hwmon/lm25066
@@ -8,6 +8,11 @@
     Datasheets:
 	http://www.ti.com/lit/gpn/lm25056
 	http://www.ti.com/lit/gpn/lm25056a
+  * TI LM25063
+    Prefix: 'lm25063'
+    Addresses scanned: -
+    Datasheet:
+	To be announced
   * National Semiconductor LM25066
     Prefix: 'lm25066'
     Addresses scanned: -
@@ -32,7 +37,7 @@
 -----------
 
 This driver supports hardware montoring for National Semiconductor / TI LM25056,
-LM25066, LM5064, and LM5064 Power Management, Monitoring, Control, and
+LM25063, LM25066, LM5064, and LM5066 Power Management, Monitoring, Control, and
 Protection ICs.
 
 The driver is a client driver to the core PMBus driver. Please see
@@ -64,8 +69,12 @@
 in1_average		Average measured input voltage.
 in1_min			Minimum input voltage.
 in1_max			Maximum input voltage.
+in1_crit		Critical high input voltage (LM25063 only).
+in1_lcrit		Critical low input voltage (LM25063 only).
 in1_min_alarm		Input voltage low alarm.
 in1_max_alarm		Input voltage high alarm.
+in1_lcrit_alarm		Input voltage critical low alarm (LM25063 only).
+in1_crit_alarm		Input voltage critical high alarm. (LM25063 only).
 
 in2_label		"vmon"
 in2_input		Measured voltage on VAUX pin
@@ -80,12 +89,16 @@
 in3_average		Average measured output voltage.
 in3_min			Minimum output voltage.
 in3_min_alarm		Output voltage low alarm.
+in3_highest		Historical minimum output voltage (LM25063 only).
+in3_lowest		Historical maximum output voltage (LM25063 only).
 
 curr1_label		"iin"
 curr1_input		Measured input current.
 curr1_average		Average measured input current.
 curr1_max		Maximum input current.
+curr1_crit		Critical input current (LM25063 only).
 curr1_max_alarm		Input current high alarm.
+curr1_crit_alarm	Input current critical high alarm (LM25063 only).
 
 power1_label		"pin"
 power1_input		Measured input power.
@@ -95,6 +108,11 @@
 power1_input_highest	Historical maximum power.
 power1_reset_history	Write any value to reset maximum power history.
 
+power2_label		"pout". LM25063 only.
+power2_input		Measured output power.
+power2_max		Maximum output power limit.
+power2_crit		Critical output power limit.
+
 temp1_input		Measured temperature.
 temp1_max		Maximum temperature.
 temp1_crit		Critical high temperature.
diff --git a/Documentation/hwmon/ltc2978 b/Documentation/hwmon/ltc2978
index dc0d08c..a0546fc 100644
--- a/Documentation/hwmon/ltc2978
+++ b/Documentation/hwmon/ltc2978
@@ -6,10 +6,15 @@
     Prefix: 'ltc2974'
     Addresses scanned: -
     Datasheet: http://www.linear.com/product/ltc2974
-  * Linear Technology LTC2978
+  * Linear Technology LTC2977
+    Prefix: 'ltc2977'
+    Addresses scanned: -
+    Datasheet: http://www.linear.com/product/ltc2977
+  * Linear Technology LTC2978, LTC2978A
     Prefix: 'ltc2978'
     Addresses scanned: -
     Datasheet: http://www.linear.com/product/ltc2978
+    	       http://www.linear.com/product/ltc2978a
   * Linear Technology LTC3880
     Prefix: 'ltc3880'
     Addresses scanned: -
@@ -26,8 +31,9 @@
 -----------
 
 LTC2974 is a quad digital power supply manager. LTC2978 is an octal power supply
-monitor. LTC3880 is a dual output poly-phase step-down DC/DC controller. LTC3883
-is a single phase step-down DC/DC controller.
+monitor. LTC2977 is a pin compatible replacement for LTC2978. LTC3880 is a dual
+output poly-phase step-down DC/DC controller. LTC3883 is a single phase
+step-down DC/DC controller.
 
 
 Usage Notes
@@ -49,21 +55,25 @@
 in1_label		"vin"
 in1_input		Measured input voltage.
 in1_min			Minimum input voltage.
-in1_max			Maximum input voltage. LTC2974 and LTC2978 only.
-in1_lcrit		Critical minimum input voltage. LTC2974 and LTC2978
-			only.
+in1_max			Maximum input voltage.
+			LTC2974, LTC2977, and LTC2978 only.
+in1_lcrit		Critical minimum input voltage.
+			LTC2974, LTC2977, and LTC2978 only.
 in1_crit		Critical maximum input voltage.
 in1_min_alarm		Input voltage low alarm.
-in1_max_alarm		Input voltage high alarm. LTC2974 and LTC2978 only.
-in1_lcrit_alarm		Input voltage critical low alarm. LTC2974 and LTC2978
-			only.
+in1_max_alarm		Input voltage high alarm.
+			LTC2974, LTC2977, and LTC2978 only.
+in1_lcrit_alarm		Input voltage critical low alarm.
+			LTC2974, LTC2977, and LTC2978 only.
 in1_crit_alarm		Input voltage critical high alarm.
-in1_lowest		Lowest input voltage. LTC2974 and LTC2978 only.
+in1_lowest		Lowest input voltage.
+			LTC2974, LTC2977, and LTC2978 only.
 in1_highest		Highest input voltage.
 in1_reset_history	Reset input voltage history.
 
 in[N]_label		"vout[1-8]".
 			LTC2974: N=2-5
+			LTC2977: N=2-9
 			LTC2978: N=2-9
 			LTC3880: N=2-3
 			LTC3883: N=2
@@ -83,21 +93,23 @@
 temp[N]_input		Measured temperature.
 			On LTC2974, temp[1-4] report external temperatures,
 			and temp5 reports the chip temperature.
-			On LTC2978, only one temperature measurement is
-			supported and reports the chip temperature.
+			On LTC2977 and LTC2978, only one temperature measurement
+			is supported and reports the chip temperature.
 			On LTC3880, temp1 and temp2 report external
 			temperatures, and temp3 reports the chip temperature.
 			On LTC3883, temp1 reports an external temperature,
 			and temp2 reports the chip temperature.
-temp[N]_min		Mimimum temperature. LTC2974 and LTC2978 only.
+temp[N]_min		Mimimum temperature. LTC2974, LCT2977, and LTC2978 only.
 temp[N]_max		Maximum temperature.
 temp[N]_lcrit		Critical low temperature.
 temp[N]_crit		Critical high temperature.
-temp[N]_min_alarm	Temperature low alarm. LTC2974 and LTC2978 only.
+temp[N]_min_alarm	Temperature low alarm.
+			LTC2974, LTC2977, and LTC2978 only.
 temp[N]_max_alarm	Temperature high alarm.
 temp[N]_lcrit_alarm	Temperature critical low alarm.
 temp[N]_crit_alarm	Temperature critical high alarm.
-temp[N]_lowest		Lowest measured temperature. LTC2974 and LTC2978 only.
+temp[N]_lowest		Lowest measured temperature.
+			LTC2974, LTC2977, and LTC2978 only.
 			Not supported for chip temperature sensor on LTC2974.
 temp[N]_highest		Highest measured temperature. Not supported for chip
 			temperature sensor on LTC2974.
@@ -109,6 +121,7 @@
 
 power[N]_label		"pout[1-4]".
 			LTC2974: N=1-4
+			LTC2977: Not supported
 			LTC2978: Not supported
 			LTC3880: N=1-2
 			LTC3883: N=2
@@ -123,6 +136,7 @@
 
 curr[N]_label		"iout[1-4]".
 			LTC2974: N=1-4
+			LTC2977: not supported
 			LTC2978: not supported
 			LTC3880: N=2-3
 			LTC3883: N=2
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index 2a5f0e1..7cbfa3c 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -138,6 +138,7 @@
 'H'	C0-DF	net/bluetooth/cmtp/cmtp.h	conflict!
 'H'	C0-DF	net/bluetooth/bnep/bnep.h	conflict!
 'H'	F1	linux/hid-roccat.h	<mailto:erazor_de@users.sourceforge.net>
+'H'	F8-FA	sound/firewire.h
 'I'	all	linux/isdn.h		conflict!
 'I'	00-0F	drivers/isdn/divert/isdn_divert.h	conflict!
 'I'	40-4F	linux/mISDNif.h		conflict!
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index fcbb736..fd3eced 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -847,6 +847,7 @@
 
 	earlyprintk=	[X86,SH,BLACKFIN,ARM]
 			earlyprintk=vga
+			earlyprintk=efi
 			earlyprintk=xen
 			earlyprintk=serial[,ttySn[,baudrate]]
 			earlyprintk=serial[,0x...[,baudrate]]
@@ -860,7 +861,8 @@
 			Append ",keep" to not disable it when the real console
 			takes over.
 
-			Only vga or serial or usb debug port at a time.
+			Only one of vga, efi, serial, or usb debug port can
+			be used at a time.
 
 			Currently only ttyS0 and ttyS1 may be specified by
 			name.  Other I/O ports may be explicitly specified
@@ -874,8 +876,8 @@
 			Interaction with the standard serial driver is not
 			very good.
 
-			The VGA output is eventually overwritten by the real
-			console.
+			The VGA and EFI output is eventually overwritten by
+			the real console.
 
 			The xen output can only be used by Xen PV guests.
 
@@ -2599,7 +2601,7 @@
 	ramdisk_size=	[RAM] Sizes of RAM disks in kilobytes
 			See Documentation/blockdev/ramdisk.txt.
 
-	rcu_nocbs=	[KNL,BOOT]
+	rcu_nocbs=	[KNL]
 			In kernels built with CONFIG_RCU_NOCB_CPU=y, set
 			the specified list of CPUs to be no-callback CPUs.
 			Invocation of these CPUs' RCU callbacks will
@@ -2612,7 +2614,7 @@
 			real-time workloads.  It can also improve energy
 			efficiency for asymmetric multiprocessors.
 
-	rcu_nocb_poll	[KNL,BOOT]
+	rcu_nocb_poll	[KNL]
 			Rather than requiring that offloaded CPUs
 			(specified by rcu_nocbs= above) explicitly
 			awaken the corresponding "rcuoN" kthreads,
@@ -2623,126 +2625,145 @@
 			energy efficiency by requiring that the kthreads
 			periodically wake up to do the polling.
 
-	rcutree.blimit=	[KNL,BOOT]
+	rcutree.blimit=	[KNL]
 			Set maximum number of finished RCU callbacks to process
 			in one batch.
 
-	rcutree.fanout_leaf=	[KNL,BOOT]
+	rcutree.rcu_fanout_leaf= [KNL]
 			Increase the number of CPUs assigned to each
 			leaf rcu_node structure.  Useful for very large
 			systems.
 
-	rcutree.jiffies_till_first_fqs= [KNL,BOOT]
+	rcutree.jiffies_till_first_fqs= [KNL]
 			Set delay from grace-period initialization to
 			first attempt to force quiescent states.
 			Units are jiffies, minimum value is zero,
 			and maximum value is HZ.
 
-	rcutree.jiffies_till_next_fqs= [KNL,BOOT]
+	rcutree.jiffies_till_next_fqs= [KNL]
 			Set delay between subsequent attempts to force
 			quiescent states.  Units are jiffies, minimum
 			value is one, and maximum value is HZ.
 
-	rcutree.qhimark=	[KNL,BOOT]
+	rcutree.qhimark= [KNL]
 			Set threshold of queued
 			RCU callbacks over which batch limiting is disabled.
 
-	rcutree.qlowmark=	[KNL,BOOT]
+	rcutree.qlowmark= [KNL]
 			Set threshold of queued RCU callbacks below which
 			batch limiting is re-enabled.
 
-	rcutree.rcu_cpu_stall_suppress=	[KNL,BOOT]
-			Suppress RCU CPU stall warning messages.
-
-	rcutree.rcu_cpu_stall_timeout= [KNL,BOOT]
-			Set timeout for RCU CPU stall warning messages.
-
-	rcutree.rcu_idle_gp_delay=	[KNL,BOOT]
+	rcutree.rcu_idle_gp_delay= [KNL]
 			Set wakeup interval for idle CPUs that have
 			RCU callbacks (RCU_FAST_NO_HZ=y).
 
-	rcutree.rcu_idle_lazy_gp_delay=	[KNL,BOOT]
+	rcutree.rcu_idle_lazy_gp_delay= [KNL]
 			Set wakeup interval for idle CPUs that have
 			only "lazy" RCU callbacks (RCU_FAST_NO_HZ=y).
 			Lazy RCU callbacks are those which RCU can
 			prove do nothing more than free memory.
 
-	rcutorture.fqs_duration= [KNL,BOOT]
+	rcutorture.fqs_duration= [KNL]
 			Set duration of force_quiescent_state bursts.
 
-	rcutorture.fqs_holdoff= [KNL,BOOT]
+	rcutorture.fqs_holdoff= [KNL]
 			Set holdoff time within force_quiescent_state bursts.
 
-	rcutorture.fqs_stutter= [KNL,BOOT]
+	rcutorture.fqs_stutter= [KNL]
 			Set wait time between force_quiescent_state bursts.
 
-	rcutorture.irqreader= [KNL,BOOT]
-			Test RCU readers from irq handlers.
+	rcutorture.gp_exp= [KNL]
+			Use expedited update-side primitives.
 
-	rcutorture.n_barrier_cbs= [KNL,BOOT]
+	rcutorture.gp_normal= [KNL]
+			Use normal (non-expedited) update-side primitives.
+			If both gp_exp and gp_normal are set, do both.
+			If neither gp_exp nor gp_normal are set, still
+			do both.
+
+	rcutorture.n_barrier_cbs= [KNL]
 			Set callbacks/threads for rcu_barrier() testing.
 
-	rcutorture.nfakewriters= [KNL,BOOT]
+	rcutorture.nfakewriters= [KNL]
 			Set number of concurrent RCU writers.  These just
 			stress RCU, they don't participate in the actual
 			test, hence the "fake".
 
-	rcutorture.nreaders= [KNL,BOOT]
+	rcutorture.nreaders= [KNL]
 			Set number of RCU readers.
 
-	rcutorture.onoff_holdoff= [KNL,BOOT]
+	rcutorture.object_debug= [KNL]
+			Enable debug-object double-call_rcu() testing.
+
+	rcutorture.onoff_holdoff= [KNL]
 			Set time (s) after boot for CPU-hotplug testing.
 
-	rcutorture.onoff_interval= [KNL,BOOT]
+	rcutorture.onoff_interval= [KNL]
 			Set time (s) between CPU-hotplug operations, or
 			zero to disable CPU-hotplug testing.
 
-	rcutorture.shuffle_interval= [KNL,BOOT]
+	rcutorture.rcutorture_runnable= [BOOT]
+			Start rcutorture running at boot time.
+
+	rcutorture.shuffle_interval= [KNL]
 			Set task-shuffle interval (s).  Shuffling tasks
 			allows some CPUs to go into dyntick-idle mode
 			during the rcutorture test.
 
-	rcutorture.shutdown_secs= [KNL,BOOT]
+	rcutorture.shutdown_secs= [KNL]
 			Set time (s) after boot system shutdown.  This
 			is useful for hands-off automated testing.
 
-	rcutorture.stall_cpu= [KNL,BOOT]
+	rcutorture.stall_cpu= [KNL]
 			Duration of CPU stall (s) to test RCU CPU stall
 			warnings, zero to disable.
 
-	rcutorture.stall_cpu_holdoff= [KNL,BOOT]
+	rcutorture.stall_cpu_holdoff= [KNL]
 			Time to wait (s) after boot before inducing stall.
 
-	rcutorture.stat_interval= [KNL,BOOT]
+	rcutorture.stat_interval= [KNL]
 			Time (s) between statistics printk()s.
 
-	rcutorture.stutter= [KNL,BOOT]
+	rcutorture.stutter= [KNL]
 			Time (s) to stutter testing, for example, specifying
 			five seconds causes the test to run for five seconds,
 			wait for five seconds, and so on.  This tests RCU's
 			ability to transition abruptly to and from idle.
 
-	rcutorture.test_boost= [KNL,BOOT]
+	rcutorture.test_boost= [KNL]
 			Test RCU priority boosting?  0=no, 1=maybe, 2=yes.
 			"Maybe" means test if the RCU implementation
 			under test support RCU priority boosting.
 
-	rcutorture.test_boost_duration= [KNL,BOOT]
+	rcutorture.test_boost_duration= [KNL]
 			Duration (s) of each individual boost test.
 
-	rcutorture.test_boost_interval= [KNL,BOOT]
+	rcutorture.test_boost_interval= [KNL]
 			Interval (s) between each boost test.
 
-	rcutorture.test_no_idle_hz= [KNL,BOOT]
+	rcutorture.test_no_idle_hz= [KNL]
 			Test RCU's dyntick-idle handling.  See also the
 			rcutorture.shuffle_interval parameter.
 
-	rcutorture.torture_type= [KNL,BOOT]
+	rcutorture.torture_type= [KNL]
 			Specify the RCU implementation to test.
 
-	rcutorture.verbose= [KNL,BOOT]
+	rcutorture.verbose= [KNL]
 			Enable additional printk() statements.
 
+	rcupdate.rcu_expedited= [KNL]
+			Use expedited grace-period primitives, for
+			example, synchronize_rcu_expedited() instead
+			of synchronize_rcu().  This reduces latency,
+			but can increase CPU utilization, degrade
+			real-time latency, and degrade energy efficiency.
+
+	rcupdate.rcu_cpu_stall_suppress= [KNL]
+			Suppress RCU CPU stall warning messages.
+
+	rcupdate.rcu_cpu_stall_timeout= [KNL]
+			Set timeout for RCU CPU stall warning messages.
+
 	rdinit=		[KNL]
 			Format: <full_path>
 			Run specified binary instead of /init from the ramdisk,
@@ -3471,11 +3492,11 @@
 			default x2apic cluster mode on platforms
 			supporting x2apic.
 
-	x86_mrst_timer= [X86-32,APBT]
-			Choose timer option for x86 Moorestown MID platform.
+	x86_intel_mid_timer= [X86-32,APBT]
+			Choose timer option for x86 Intel MID platform.
 			Two valid options are apbt timer only and lapic timer
 			plus one apbt timer for broadcast timer.
-			x86_mrst_timer=apbt_only | lapic_and_apbt
+			x86_intel_mid_timer=apbt_only | lapic_and_apbt
 
 	xen_emul_unplug=		[HW,X86,XEN]
 			Unplug Xen emulated devices
diff --git a/Documentation/kernel-per-CPU-kthreads.txt b/Documentation/kernel-per-CPU-kthreads.txt
index 32351bf..827104f 100644
--- a/Documentation/kernel-per-CPU-kthreads.txt
+++ b/Documentation/kernel-per-CPU-kthreads.txt
@@ -181,12 +181,17 @@
 		make sure that this is safe on your particular system.
 	d.	It is not possible to entirely get rid of OS jitter
 		from vmstat_update() on CONFIG_SMP=y systems, but you
-		can decrease its frequency by writing a large value to
-		/proc/sys/vm/stat_interval.  The default value is HZ,
-		for an interval of one second.  Of course, larger values
-		will make your virtual-memory statistics update more
-		slowly.  Of course, you can also run your workload at
-		a real-time priority, thus preempting vmstat_update().
+		can decrease its frequency by writing a large value
+		to /proc/sys/vm/stat_interval.	The default value is
+		HZ, for an interval of one second.  Of course, larger
+		values will make your virtual-memory statistics update
+		more slowly.  Of course, you can also run your workload
+		at a real-time priority, thus preempting vmstat_update(),
+		but if your workload is CPU-bound, this is a bad idea.
+		However, there is an RFC patch from Christoph Lameter
+		(based on an earlier one from Gilad Ben-Yossef) that
+		reduces or even eliminates vmstat overhead for some
+		workloads at https://lkml.org/lkml/2013/9/4/379.
 	e.	If running on high-end powerpc servers, build with
 		CONFIG_PPC_RTAS_DAEMON=n.  This prevents the RTAS
 		daemon from running on each CPU every second or so.
diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
index 86c5236..fc04c14 100644
--- a/Documentation/laptops/thinkpad-acpi.txt
+++ b/Documentation/laptops/thinkpad-acpi.txt
@@ -1,7 +1,7 @@
 		     ThinkPad ACPI Extras Driver
 
-                            Version 0.24
-                        December 11th,  2009
+                            Version 0.25
+                        October 16th,  2013
 
                Borislav Deianov <borislav@users.sf.net>
              Henrique de Moraes Holschuh <hmh@hmh.eng.br>
@@ -741,6 +741,9 @@
 Distributions must never enable this option.  Individual users that
 are aware of the consequences are welcome to enabling it.
 
+Audio mute and microphone mute LEDs are supported, but currently not
+visible to userspace. They are used by the snd-hda-intel audio driver.
+
 procfs notes:
 
 The available commands are:
diff --git a/Documentation/mic/mic_overview.txt b/Documentation/mic/mic_overview.txt
new file mode 100644
index 0000000..b419292
--- /dev/null
+++ b/Documentation/mic/mic_overview.txt
@@ -0,0 +1,51 @@
+An Intel MIC X100 device is a PCIe form factor add-in coprocessor
+card based on the Intel Many Integrated Core (MIC) architecture
+that runs a Linux OS. It is a PCIe endpoint in a platform and therefore
+implements the three required standard address spaces i.e. configuration,
+memory and I/O. The host OS loads a device driver as is typical for
+PCIe devices. The card itself runs a bootstrap after reset that
+transfers control to the card OS downloaded from the host driver. The
+host driver supports OSPM suspend and resume operations. It shuts down
+the card during suspend and reboots the card OS during resume.
+The card OS as shipped by Intel is a Linux kernel with modifications
+for the X100 devices.
+
+Since it is a PCIe card, it does not have the ability to host hardware
+devices for networking, storage and console. We provide these devices
+on X100 coprocessors thus enabling a self-bootable equivalent environment
+for applications. A key benefit of our solution is that it leverages
+the standard virtio framework for network, disk and console devices,
+though in our case the virtio framework is used across a PCIe bus.
+
+Here is a block diagram of the various components described above. The
+virtio backends are situated on the host rather than the card given better
+single threaded performance for the host compared to MIC, the ability of
+the host to initiate DMA's to/from the card using the MIC DMA engine and
+the fact that the virtio block storage backend can only be on the host.
+
+                              |
+       +----------+           |             +----------+
+       | Card OS  |           |             | Host OS  |
+       +----------+           |             +----------+
+                              |
++-------+ +--------+ +------+ | +---------+  +--------+ +--------+
+| Virtio| |Virtio  | |Virtio| | |Virtio   |  |Virtio  | |Virtio  |
+| Net   | |Console | |Block | | |Net      |  |Console | |Block   |
+| Driver| |Driver  | |Driver| | |backend  |  |backend | |backend |
++-------+ +--------+ +------+ | +---------+  +--------+ +--------+
+    |         |         |     |      |            |         |
+    |         |         |     |User  |            |         |
+    |         |         |     |------|------------|---------|-------
+    +-------------------+     |Kernel +--------------------------+
+              |               |       | Virtio over PCIe IOCTLs  |
+              |               |       +--------------------------+
+      +--------------+        |                   |
+      |Intel MIC     |        |            +---------------+
+      |Card Driver   |        |            |Intel MIC      |
+      +--------------+        |            |Host Driver    |
+              |               |            +---------------+
+              |               |                   |
+     +-------------------------------------------------------------+
+     |                                                             |
+     |                    PCIe Bus                                 |
+     +-------------------------------------------------------------+
diff --git a/Documentation/mic/mpssd/.gitignore b/Documentation/mic/mpssd/.gitignore
new file mode 100644
index 0000000..8b7c72f
--- /dev/null
+++ b/Documentation/mic/mpssd/.gitignore
@@ -0,0 +1 @@
+mpssd
diff --git a/Documentation/mic/mpssd/Makefile b/Documentation/mic/mpssd/Makefile
new file mode 100644
index 0000000..eb860a7
--- /dev/null
+++ b/Documentation/mic/mpssd/Makefile
@@ -0,0 +1,19 @@
+#
+# Makefile - Intel MIC User Space Tools.
+# Copyright(c) 2013, Intel Corporation.
+#
+ifdef DEBUG
+CFLAGS += $(USERWARNFLAGS) -I. -g -Wall -DDEBUG=$(DEBUG)
+else
+CFLAGS += $(USERWARNFLAGS) -I. -g -Wall
+endif
+
+mpssd: mpssd.o sysfs.o
+	$(CC) $(CFLAGS) -o $@ $^ -lpthread
+
+install:
+	install mpssd /usr/sbin/mpssd
+	install micctrl /usr/sbin/micctrl
+
+clean:
+	rm -f mpssd *.o
diff --git a/Documentation/mic/mpssd/micctrl b/Documentation/mic/mpssd/micctrl
new file mode 100755
index 0000000..8f2629b
--- /dev/null
+++ b/Documentation/mic/mpssd/micctrl
@@ -0,0 +1,173 @@
+#!/bin/bash
+# Intel MIC Platform Software Stack (MPSS)
+#
+# Copyright(c) 2013 Intel Corporation.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License, version 2, as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# The full GNU General Public License is included in this distribution in
+# the file called "COPYING".
+#
+# Intel MIC User Space Tools.
+#
+# micctrl - Controls MIC boot/start/stop.
+#
+# chkconfig: 2345 95 05
+# description: start MPSS stack processing.
+#
+### BEGIN INIT INFO
+# Provides: micctrl
+### END INIT INFO
+
+# Source function library.
+. /etc/init.d/functions
+
+sysfs="/sys/class/mic"
+
+_status()
+{
+	f=$sysfs/$1
+	echo -e $1 state: "`cat $f/state`" shutdown_status: "`cat $f/shutdown_status`"
+}
+
+status()
+{
+	if [ "`echo $1 | head -c3`" == "mic" ]; then
+		_status $1
+		return $?
+	fi
+	for f in $sysfs/*
+	do
+		_status `basename $f`
+		RETVAL=$?
+		[ $RETVAL -ne 0 ] && return $RETVAL
+	done
+	return 0
+}
+
+_reset()
+{
+	f=$sysfs/$1
+	echo reset > $f/state
+}
+
+reset()
+{
+	if [ "`echo $1 | head -c3`" == "mic" ]; then
+		_reset $1
+		return $?
+	fi
+	for f in $sysfs/*
+	do
+		_reset `basename $f`
+		RETVAL=$?
+		[ $RETVAL -ne 0 ] && return $RETVAL
+	done
+	return 0
+}
+
+_boot()
+{
+	f=$sysfs/$1
+	echo "linux" > $f/bootmode
+	echo "mic/uos.img" > $f/firmware
+	echo "mic/$1.image" > $f/ramdisk
+	echo "boot" > $f/state
+}
+
+boot()
+{
+	if [ "`echo $1 | head -c3`" == "mic" ]; then
+		_boot $1
+		return $?
+	fi
+	for f in $sysfs/*
+	do
+		_boot `basename $f`
+		RETVAL=$?
+		[ $RETVAL -ne 0 ] && return $RETVAL
+	done
+	return 0
+}
+
+_shutdown()
+{
+	f=$sysfs/$1
+	echo shutdown > $f/state
+}
+
+shutdown()
+{
+	if [ "`echo $1 | head -c3`" == "mic" ]; then
+		_shutdown $1
+		return $?
+	fi
+	for f in $sysfs/*
+	do
+		_shutdown `basename $f`
+		RETVAL=$?
+		[ $RETVAL -ne 0 ] && return $RETVAL
+	done
+	return 0
+}
+
+_wait()
+{
+	f=$sysfs/$1
+	while [ "`cat $f/state`" != "offline" -a "`cat $f/state`" != "online" ]
+	do
+		sleep 1
+		echo -e "Waiting for $1 to go offline"
+	done
+}
+
+wait()
+{
+	if [ "`echo $1 | head -c3`" == "mic" ]; then
+		_wait $1
+		return $?
+	fi
+	# Wait for the cards to go offline
+	for f in $sysfs/*
+	do
+		_wait `basename $f`
+		RETVAL=$?
+		[ $RETVAL -ne 0 ] && return $RETVAL
+	done
+	return 0
+}
+
+if [ ! -d "$sysfs" ]; then
+	echo -e $"Module unloaded "
+	exit 3
+fi
+
+case $1 in
+	-s)
+		status $2
+		;;
+	-r)
+		reset $2
+		;;
+	-b)
+		boot $2
+		;;
+	-S)
+		shutdown $2
+		;;
+	-w)
+		wait $2
+		;;
+	*)
+		echo $"Usage: $0 {-s (status) |-r (reset) |-b (boot) |-S (shutdown) |-w (wait)}"
+		exit 2
+esac
+
+exit $?
diff --git a/Documentation/mic/mpssd/mpss b/Documentation/mic/mpssd/mpss
new file mode 100755
index 0000000..3136c68
--- /dev/null
+++ b/Documentation/mic/mpssd/mpss
@@ -0,0 +1,202 @@
+#!/bin/bash
+# Intel MIC Platform Software Stack (MPSS)
+#
+# Copyright(c) 2013 Intel Corporation.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License, version 2, as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# The full GNU General Public License is included in this distribution in
+# the file called "COPYING".
+#
+# Intel MIC User Space Tools.
+#
+# mpss	Start mpssd.
+#
+# chkconfig: 2345 95 05
+# description: start MPSS stack processing.
+#
+### BEGIN INIT INFO
+# Provides: mpss
+# Required-Start:
+# Required-Stop:
+# Short-Description: MPSS stack control
+# Description: MPSS stack control
+### END INIT INFO
+
+# Source function library.
+. /etc/init.d/functions
+
+exec=/usr/sbin/mpssd
+sysfs="/sys/class/mic"
+
+start()
+{
+	[ -x $exec ] || exit 5
+
+	if [ "`ps -e | awk '{print $4}' | grep mpssd | head -1`" = "mpssd" ]; then
+		echo -e $"MPSSD already running! "
+		success
+		echo
+		return 0
+	fi
+
+	echo -e $"Starting MPSS Stack"
+	echo -e $"Loading MIC_HOST Module"
+
+	# Ensure the driver is loaded
+	if [ ! -d "$sysfs" ]; then
+		modprobe mic_host
+		RETVAL=$?
+		if [ $RETVAL -ne 0 ]; then
+			failure
+			echo
+			return $RETVAL
+		fi
+	fi
+
+	# Start the daemon
+	echo -n $"Starting MPSSD "
+	$exec
+	RETVAL=$?
+	if [ $RETVAL -ne 0 ]; then
+		failure
+		echo
+		return $RETVAL
+	fi
+	success
+	echo
+
+	sleep 5
+
+	# Boot the cards
+	micctrl -b
+
+	# Wait till ping works
+	for f in $sysfs/*
+	do
+		count=100
+		ipaddr=`cat $f/cmdline`
+		ipaddr=${ipaddr#*address,}
+		ipaddr=`echo $ipaddr | cut -d, -f1 | cut -d\; -f1`
+		while [ $count -ge 0 ]
+		do
+			echo -e "Pinging "`basename $f`" "
+			ping -c 1 $ipaddr &> /dev/null
+			RETVAL=$?
+			if [ $RETVAL -eq 0 ]; then
+				success
+				break
+			fi
+			sleep 1
+			count=`expr $count - 1`
+		done
+		[ $RETVAL -ne 0 ] && failure || success
+		echo
+	done
+	return $RETVAL
+}
+
+stop()
+{
+	echo -e $"Shutting down MPSS Stack: "
+
+	# Bail out if module is unloaded
+	if [ ! -d "$sysfs" ]; then
+		echo -n $"Module unloaded "
+		success
+		echo
+		return 0
+	fi
+
+	# Shut down the cards.
+	micctrl -S
+
+	# Wait for the cards to go offline
+	for f in $sysfs/*
+	do
+		while [ "`cat $f/state`" != "offline" ]
+		do
+			sleep 1
+			echo -e "Waiting for "`basename $f`" to go offline"
+		done
+	done
+
+	# Display the status of the cards
+	micctrl -s
+
+	# Kill MPSSD now
+	echo -n $"Killing MPSSD"
+	killall -9 mpssd 2>/dev/null
+	RETVAL=$?
+	[ $RETVAL -ne 0 ] && failure || success
+	echo
+	return $RETVAL
+}
+
+restart()
+{
+	stop
+	sleep 5
+	start
+}
+
+status()
+{
+	micctrl -s
+	if [ "`ps -e | awk '{print $4}' | grep mpssd | head -n 1`" = "mpssd" ]; then
+		echo "mpssd is running"
+	else
+		echo "mpssd is stopped"
+	fi
+	return 0
+}
+
+unload()
+{
+	if [ ! -d "$sysfs" ]; then
+		echo -n $"No MIC_HOST Module: "
+		success
+		echo
+		return
+	fi
+
+	stop
+
+	sleep 5
+	echo -n $"Removing MIC_HOST Module: "
+	modprobe -r mic_host
+	RETVAL=$?
+	[ $RETVAL -ne 0 ] && failure || success
+	echo
+	return $RETVAL
+}
+
+case $1 in
+	start)
+		start
+		;;
+	stop)
+		stop
+		;;
+	restart)
+		restart
+		;;
+	status)
+		status
+		;;
+	unload)
+		unload
+		;;
+	*)
+		echo $"Usage: $0 {start|stop|restart|status|unload}"
+		exit 2
+esac
+
+exit $?
diff --git a/Documentation/mic/mpssd/mpssd.c b/Documentation/mic/mpssd/mpssd.c
new file mode 100644
index 0000000..0c980ad
--- /dev/null
+++ b/Documentation/mic/mpssd/mpssd.c
@@ -0,0 +1,1721 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC User Space Tools.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <assert.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <signal.h>
+#include <poll.h>
+#include <features.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <linux/virtio_ring.h>
+#include <linux/virtio_net.h>
+#include <linux/virtio_console.h>
+#include <linux/virtio_blk.h>
+#include <linux/version.h>
+#include "mpssd.h"
+#include <linux/mic_ioctl.h>
+#include <linux/mic_common.h>
+
+static void init_mic(struct mic_info *mic);
+
+static FILE *logfp;
+static struct mic_info mic_list;
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define min_t(type, x, y) ({				\
+		type __min1 = (x);                      \
+		type __min2 = (y);                      \
+		__min1 < __min2 ? __min1 : __min2; })
+
+/* align addr on a size boundary - adjust address up/down if needed */
+#define _ALIGN_DOWN(addr, size)  ((addr)&(~((size)-1)))
+#define _ALIGN_UP(addr, size)    _ALIGN_DOWN(addr + size - 1, size)
+
+/* align addr on a size boundary - adjust address up if needed */
+#define _ALIGN(addr, size)     _ALIGN_UP(addr, size)
+
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr)        _ALIGN(addr, PAGE_SIZE)
+
+#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
+
+#define GSO_ENABLED		1
+#define MAX_GSO_SIZE		(64 * 1024)
+#define ETH_H_LEN		14
+#define MAX_NET_PKT_SIZE	(_ALIGN_UP(MAX_GSO_SIZE + ETH_H_LEN, 64))
+#define MIC_DEVICE_PAGE_END	0x1000
+
+#ifndef VIRTIO_NET_HDR_F_DATA_VALID
+#define VIRTIO_NET_HDR_F_DATA_VALID	2	/* Csum is valid */
+#endif
+
+static struct {
+	struct mic_device_desc dd;
+	struct mic_vqconfig vqconfig[2];
+	__u32 host_features, guest_acknowledgements;
+	struct virtio_console_config cons_config;
+} virtcons_dev_page = {
+	.dd = {
+		.type = VIRTIO_ID_CONSOLE,
+		.num_vq = ARRAY_SIZE(virtcons_dev_page.vqconfig),
+		.feature_len = sizeof(virtcons_dev_page.host_features),
+		.config_len = sizeof(virtcons_dev_page.cons_config),
+	},
+	.vqconfig[0] = {
+		.num = htole16(MIC_VRING_ENTRIES),
+	},
+	.vqconfig[1] = {
+		.num = htole16(MIC_VRING_ENTRIES),
+	},
+};
+
+static struct {
+	struct mic_device_desc dd;
+	struct mic_vqconfig vqconfig[2];
+	__u32 host_features, guest_acknowledgements;
+	struct virtio_net_config net_config;
+} virtnet_dev_page = {
+	.dd = {
+		.type = VIRTIO_ID_NET,
+		.num_vq = ARRAY_SIZE(virtnet_dev_page.vqconfig),
+		.feature_len = sizeof(virtnet_dev_page.host_features),
+		.config_len = sizeof(virtnet_dev_page.net_config),
+	},
+	.vqconfig[0] = {
+		.num = htole16(MIC_VRING_ENTRIES),
+	},
+	.vqconfig[1] = {
+		.num = htole16(MIC_VRING_ENTRIES),
+	},
+#if GSO_ENABLED
+		.host_features = htole32(
+		1 << VIRTIO_NET_F_CSUM |
+		1 << VIRTIO_NET_F_GSO |
+		1 << VIRTIO_NET_F_GUEST_TSO4 |
+		1 << VIRTIO_NET_F_GUEST_TSO6 |
+		1 << VIRTIO_NET_F_GUEST_ECN |
+		1 << VIRTIO_NET_F_GUEST_UFO),
+#else
+		.host_features = 0,
+#endif
+};
+
+static const char *mic_config_dir = "/etc/sysconfig/mic";
+static const char *virtblk_backend = "VIRTBLK_BACKEND";
+static struct {
+	struct mic_device_desc dd;
+	struct mic_vqconfig vqconfig[1];
+	__u32 host_features, guest_acknowledgements;
+	struct virtio_blk_config blk_config;
+} virtblk_dev_page = {
+	.dd = {
+		.type = VIRTIO_ID_BLOCK,
+		.num_vq = ARRAY_SIZE(virtblk_dev_page.vqconfig),
+		.feature_len = sizeof(virtblk_dev_page.host_features),
+		.config_len = sizeof(virtblk_dev_page.blk_config),
+	},
+	.vqconfig[0] = {
+		.num = htole16(MIC_VRING_ENTRIES),
+	},
+	.host_features =
+		htole32(1<<VIRTIO_BLK_F_SEG_MAX),
+	.blk_config = {
+		.seg_max = htole32(MIC_VRING_ENTRIES - 2),
+		.capacity = htole64(0),
+	 }
+};
+
+static char *myname;
+
+static int
+tap_configure(struct mic_info *mic, char *dev)
+{
+	pid_t pid;
+	char *ifargv[7];
+	char ipaddr[IFNAMSIZ];
+	int ret = 0;
+
+	pid = fork();
+	if (pid == 0) {
+		ifargv[0] = "ip";
+		ifargv[1] = "link";
+		ifargv[2] = "set";
+		ifargv[3] = dev;
+		ifargv[4] = "up";
+		ifargv[5] = NULL;
+		mpsslog("Configuring %s\n", dev);
+		ret = execvp("ip", ifargv);
+		if (ret < 0) {
+			mpsslog("%s execvp failed errno %s\n",
+				mic->name, strerror(errno));
+			return ret;
+		}
+	}
+	if (pid < 0) {
+		mpsslog("%s fork failed errno %s\n",
+			mic->name, strerror(errno));
+		return ret;
+	}
+
+	ret = waitpid(pid, NULL, 0);
+	if (ret < 0) {
+		mpsslog("%s waitpid failed errno %s\n",
+			mic->name, strerror(errno));
+		return ret;
+	}
+
+	snprintf(ipaddr, IFNAMSIZ, "172.31.%d.254/24", mic->id);
+
+	pid = fork();
+	if (pid == 0) {
+		ifargv[0] = "ip";
+		ifargv[1] = "addr";
+		ifargv[2] = "add";
+		ifargv[3] = ipaddr;
+		ifargv[4] = "dev";
+		ifargv[5] = dev;
+		ifargv[6] = NULL;
+		mpsslog("Configuring %s ipaddr %s\n", dev, ipaddr);
+		ret = execvp("ip", ifargv);
+		if (ret < 0) {
+			mpsslog("%s execvp failed errno %s\n",
+				mic->name, strerror(errno));
+			return ret;
+		}
+	}
+	if (pid < 0) {
+		mpsslog("%s fork failed errno %s\n",
+			mic->name, strerror(errno));
+		return ret;
+	}
+
+	ret = waitpid(pid, NULL, 0);
+	if (ret < 0) {
+		mpsslog("%s waitpid failed errno %s\n",
+			mic->name, strerror(errno));
+		return ret;
+	}
+	mpsslog("MIC name %s %s %d DONE!\n",
+		mic->name, __func__, __LINE__);
+	return 0;
+}
+
+static int tun_alloc(struct mic_info *mic, char *dev)
+{
+	struct ifreq ifr;
+	int fd, err;
+#if GSO_ENABLED
+	unsigned offload;
+#endif
+	fd = open("/dev/net/tun", O_RDWR);
+	if (fd < 0) {
+		mpsslog("Could not open /dev/net/tun %s\n", strerror(errno));
+		goto done;
+	}
+
+	memset(&ifr, 0, sizeof(ifr));
+
+	ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
+	if (*dev)
+		strncpy(ifr.ifr_name, dev, IFNAMSIZ);
+
+	err = ioctl(fd, TUNSETIFF, (void *)&ifr);
+	if (err < 0) {
+		mpsslog("%s %s %d TUNSETIFF failed %s\n",
+			mic->name, __func__, __LINE__, strerror(errno));
+		close(fd);
+		return err;
+	}
+#if GSO_ENABLED
+	offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 |
+		TUN_F_TSO_ECN | TUN_F_UFO;
+
+	err = ioctl(fd, TUNSETOFFLOAD, offload);
+	if (err < 0) {
+		mpsslog("%s %s %d TUNSETOFFLOAD failed %s\n",
+			mic->name, __func__, __LINE__, strerror(errno));
+		close(fd);
+		return err;
+	}
+#endif
+	strcpy(dev, ifr.ifr_name);
+	mpsslog("Created TAP %s\n", dev);
+done:
+	return fd;
+}
+
+#define NET_FD_VIRTIO_NET 0
+#define NET_FD_TUN 1
+#define MAX_NET_FD 2
+
+static void set_dp(struct mic_info *mic, int type, void *dp)
+{
+	switch (type) {
+	case VIRTIO_ID_CONSOLE:
+		mic->mic_console.console_dp = dp;
+		return;
+	case VIRTIO_ID_NET:
+		mic->mic_net.net_dp = dp;
+		return;
+	case VIRTIO_ID_BLOCK:
+		mic->mic_virtblk.block_dp = dp;
+		return;
+	}
+	mpsslog("%s %s %d not found\n", mic->name, __func__, type);
+	assert(0);
+}
+
+static void *get_dp(struct mic_info *mic, int type)
+{
+	switch (type) {
+	case VIRTIO_ID_CONSOLE:
+		return mic->mic_console.console_dp;
+	case VIRTIO_ID_NET:
+		return mic->mic_net.net_dp;
+	case VIRTIO_ID_BLOCK:
+		return mic->mic_virtblk.block_dp;
+	}
+	mpsslog("%s %s %d not found\n", mic->name, __func__, type);
+	assert(0);
+	return NULL;
+}
+
+static struct mic_device_desc *get_device_desc(struct mic_info *mic, int type)
+{
+	struct mic_device_desc *d;
+	int i;
+	void *dp = get_dp(mic, type);
+
+	for (i = mic_aligned_size(struct mic_bootparam); i < PAGE_SIZE;
+		i += mic_total_desc_size(d)) {
+		d = dp + i;
+
+		/* End of list */
+		if (d->type == 0)
+			break;
+
+		if (d->type == -1)
+			continue;
+
+		mpsslog("%s %s d-> type %d d %p\n",
+			mic->name, __func__, d->type, d);
+
+		if (d->type == (__u8)type)
+			return d;
+	}
+	mpsslog("%s %s %d not found\n", mic->name, __func__, type);
+	assert(0);
+	return NULL;
+}
+
+/* See comments in vhost.c for explanation of next_desc() */
+static unsigned next_desc(struct vring_desc *desc)
+{
+	unsigned int next;
+
+	if (!(le16toh(desc->flags) & VRING_DESC_F_NEXT))
+		return -1U;
+	next = le16toh(desc->next);
+	return next;
+}
+
+/* Sum up all the IOVEC length */
+static ssize_t
+sum_iovec_len(struct mic_copy_desc *copy)
+{
+	ssize_t sum = 0;
+	int i;
+
+	for (i = 0; i < copy->iovcnt; i++)
+		sum += copy->iov[i].iov_len;
+	return sum;
+}
+
+static inline void verify_out_len(struct mic_info *mic,
+	struct mic_copy_desc *copy)
+{
+	if (copy->out_len != sum_iovec_len(copy)) {
+		mpsslog("%s %s %d BUG copy->out_len 0x%x len 0x%zx\n",
+			mic->name, __func__, __LINE__,
+			copy->out_len, sum_iovec_len(copy));
+		assert(copy->out_len == sum_iovec_len(copy));
+	}
+}
+
+/* Display an iovec */
+static void
+disp_iovec(struct mic_info *mic, struct mic_copy_desc *copy,
+	   const char *s, int line)
+{
+	int i;
+
+	for (i = 0; i < copy->iovcnt; i++)
+		mpsslog("%s %s %d copy->iov[%d] addr %p len 0x%zx\n",
+			mic->name, s, line, i,
+			copy->iov[i].iov_base, copy->iov[i].iov_len);
+}
+
+static inline __u16 read_avail_idx(struct mic_vring *vr)
+{
+	return ACCESS_ONCE(vr->info->avail_idx);
+}
+
+static inline void txrx_prepare(int type, bool tx, struct mic_vring *vr,
+				struct mic_copy_desc *copy, ssize_t len)
+{
+	copy->vr_idx = tx ? 0 : 1;
+	copy->update_used = true;
+	if (type == VIRTIO_ID_NET)
+		copy->iov[1].iov_len = len - sizeof(struct virtio_net_hdr);
+	else
+		copy->iov[0].iov_len = len;
+}
+
+/* Central API which triggers the copies */
+static int
+mic_virtio_copy(struct mic_info *mic, int fd,
+		struct mic_vring *vr, struct mic_copy_desc *copy)
+{
+	int ret;
+
+	ret = ioctl(fd, MIC_VIRTIO_COPY_DESC, copy);
+	if (ret) {
+		mpsslog("%s %s %d errno %s ret %d\n",
+			mic->name, __func__, __LINE__,
+			strerror(errno), ret);
+	}
+	return ret;
+}
+
+/*
+ * This initialization routine requires at least one
+ * vring i.e. vr0. vr1 is optional.
+ */
+static void *
+init_vr(struct mic_info *mic, int fd, int type,
+	struct mic_vring *vr0, struct mic_vring *vr1, int num_vq)
+{
+	int vr_size;
+	char *va;
+
+	vr_size = PAGE_ALIGN(vring_size(MIC_VRING_ENTRIES,
+		MIC_VIRTIO_RING_ALIGN) + sizeof(struct _mic_vring_info));
+	va = mmap(NULL, MIC_DEVICE_PAGE_END + vr_size * num_vq,
+		PROT_READ, MAP_SHARED, fd, 0);
+	if (MAP_FAILED == va) {
+		mpsslog("%s %s %d mmap failed errno %s\n",
+			mic->name, __func__, __LINE__,
+			strerror(errno));
+		goto done;
+	}
+	set_dp(mic, type, va);
+	vr0->va = (struct mic_vring *)&va[MIC_DEVICE_PAGE_END];
+	vr0->info = vr0->va +
+		vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN);
+	vring_init(&vr0->vr,
+		   MIC_VRING_ENTRIES, vr0->va, MIC_VIRTIO_RING_ALIGN);
+	mpsslog("%s %s vr0 %p vr0->info %p vr_size 0x%x vring 0x%x ",
+		__func__, mic->name, vr0->va, vr0->info, vr_size,
+		vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
+	mpsslog("magic 0x%x expected 0x%x\n",
+		vr0->info->magic, MIC_MAGIC + type);
+	assert(vr0->info->magic == MIC_MAGIC + type);
+	if (vr1) {
+		vr1->va = (struct mic_vring *)
+			&va[MIC_DEVICE_PAGE_END + vr_size];
+		vr1->info = vr1->va + vring_size(MIC_VRING_ENTRIES,
+			MIC_VIRTIO_RING_ALIGN);
+		vring_init(&vr1->vr,
+			   MIC_VRING_ENTRIES, vr1->va, MIC_VIRTIO_RING_ALIGN);
+		mpsslog("%s %s vr1 %p vr1->info %p vr_size 0x%x vring 0x%x ",
+			__func__, mic->name, vr1->va, vr1->info, vr_size,
+			vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
+		mpsslog("magic 0x%x expected 0x%x\n",
+			vr1->info->magic, MIC_MAGIC + type + 1);
+		assert(vr1->info->magic == MIC_MAGIC + type + 1);
+	}
+done:
+	return va;
+}
+
+static void
+wait_for_card_driver(struct mic_info *mic, int fd, int type)
+{
+	struct pollfd pollfd;
+	int err;
+	struct mic_device_desc *desc = get_device_desc(mic, type);
+
+	pollfd.fd = fd;
+	mpsslog("%s %s Waiting .... desc-> type %d status 0x%x\n",
+		mic->name, __func__, type, desc->status);
+	while (1) {
+		pollfd.events = POLLIN;
+		pollfd.revents = 0;
+		err = poll(&pollfd, 1, -1);
+		if (err < 0) {
+			mpsslog("%s %s poll failed %s\n",
+				mic->name, __func__, strerror(errno));
+			continue;
+		}
+
+		if (pollfd.revents) {
+			mpsslog("%s %s Waiting... desc-> type %d status 0x%x\n",
+				mic->name, __func__, type, desc->status);
+			if (desc->status & VIRTIO_CONFIG_S_DRIVER_OK) {
+				mpsslog("%s %s poll.revents %d\n",
+					mic->name, __func__, pollfd.revents);
+				mpsslog("%s %s desc-> type %d status 0x%x\n",
+					mic->name, __func__, type,
+					desc->status);
+				break;
+			}
+		}
+	}
+}
+
+/* Spin till we have some descriptors */
+static void
+spin_for_descriptors(struct mic_info *mic, struct mic_vring *vr)
+{
+	__u16 avail_idx = read_avail_idx(vr);
+
+	while (avail_idx == le16toh(ACCESS_ONCE(vr->vr.avail->idx))) {
+#ifdef DEBUG
+		mpsslog("%s %s waiting for desc avail %d info_avail %d\n",
+			mic->name, __func__,
+			le16toh(vr->vr.avail->idx), vr->info->avail_idx);
+#endif
+		sched_yield();
+	}
+}
+
+static void *
+virtio_net(void *arg)
+{
+	static __u8 vnet_hdr[2][sizeof(struct virtio_net_hdr)];
+	static __u8 vnet_buf[2][MAX_NET_PKT_SIZE] __aligned(64);
+	struct iovec vnet_iov[2][2] = {
+		{ { .iov_base = vnet_hdr[0], .iov_len = sizeof(vnet_hdr[0]) },
+		  { .iov_base = vnet_buf[0], .iov_len = sizeof(vnet_buf[0]) } },
+		{ { .iov_base = vnet_hdr[1], .iov_len = sizeof(vnet_hdr[1]) },
+		  { .iov_base = vnet_buf[1], .iov_len = sizeof(vnet_buf[1]) } },
+	};
+	struct iovec *iov0 = vnet_iov[0], *iov1 = vnet_iov[1];
+	struct mic_info *mic = (struct mic_info *)arg;
+	char if_name[IFNAMSIZ];
+	struct pollfd net_poll[MAX_NET_FD];
+	struct mic_vring tx_vr, rx_vr;
+	struct mic_copy_desc copy;
+	struct mic_device_desc *desc;
+	int err;
+
+	snprintf(if_name, IFNAMSIZ, "mic%d", mic->id);
+	mic->mic_net.tap_fd = tun_alloc(mic, if_name);
+	if (mic->mic_net.tap_fd < 0)
+		goto done;
+
+	if (tap_configure(mic, if_name))
+		goto done;
+	mpsslog("MIC name %s id %d\n", mic->name, mic->id);
+
+	net_poll[NET_FD_VIRTIO_NET].fd = mic->mic_net.virtio_net_fd;
+	net_poll[NET_FD_VIRTIO_NET].events = POLLIN;
+	net_poll[NET_FD_TUN].fd = mic->mic_net.tap_fd;
+	net_poll[NET_FD_TUN].events = POLLIN;
+
+	if (MAP_FAILED == init_vr(mic, mic->mic_net.virtio_net_fd,
+				  VIRTIO_ID_NET, &tx_vr, &rx_vr,
+		virtnet_dev_page.dd.num_vq)) {
+		mpsslog("%s init_vr failed %s\n",
+			mic->name, strerror(errno));
+		goto done;
+	}
+
+	copy.iovcnt = 2;
+	desc = get_device_desc(mic, VIRTIO_ID_NET);
+
+	while (1) {
+		ssize_t len;
+
+		net_poll[NET_FD_VIRTIO_NET].revents = 0;
+		net_poll[NET_FD_TUN].revents = 0;
+
+		/* Start polling for data from tap and virtio net */
+		err = poll(net_poll, 2, -1);
+		if (err < 0) {
+			mpsslog("%s poll failed %s\n",
+				__func__, strerror(errno));
+			continue;
+		}
+		if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK))
+			wait_for_card_driver(mic, mic->mic_net.virtio_net_fd,
+					     VIRTIO_ID_NET);
+		/*
+		 * Check if there is data to be read from TUN and write to
+		 * virtio net fd if there is.
+		 */
+		if (net_poll[NET_FD_TUN].revents & POLLIN) {
+			copy.iov = iov0;
+			len = readv(net_poll[NET_FD_TUN].fd,
+				copy.iov, copy.iovcnt);
+			if (len > 0) {
+				struct virtio_net_hdr *hdr
+					= (struct virtio_net_hdr *)vnet_hdr[0];
+
+				/* Disable checksums on the card since we are on
+				   a reliable PCIe link */
+				hdr->flags |= VIRTIO_NET_HDR_F_DATA_VALID;
+#ifdef DEBUG
+				mpsslog("%s %s %d hdr->flags 0x%x ", mic->name,
+					__func__, __LINE__, hdr->flags);
+				mpsslog("copy.out_len %d hdr->gso_type 0x%x\n",
+					copy.out_len, hdr->gso_type);
+#endif
+#ifdef DEBUG
+				disp_iovec(mic, copy, __func__, __LINE__);
+				mpsslog("%s %s %d read from tap 0x%lx\n",
+					mic->name, __func__, __LINE__,
+					len);
+#endif
+				spin_for_descriptors(mic, &tx_vr);
+				txrx_prepare(VIRTIO_ID_NET, 1, &tx_vr, &copy,
+					     len);
+
+				err = mic_virtio_copy(mic,
+					mic->mic_net.virtio_net_fd, &tx_vr,
+					&copy);
+				if (err < 0) {
+					mpsslog("%s %s %d mic_virtio_copy %s\n",
+						mic->name, __func__, __LINE__,
+						strerror(errno));
+				}
+				if (!err)
+					verify_out_len(mic, &copy);
+#ifdef DEBUG
+				disp_iovec(mic, copy, __func__, __LINE__);
+				mpsslog("%s %s %d wrote to net 0x%lx\n",
+					mic->name, __func__, __LINE__,
+					sum_iovec_len(&copy));
+#endif
+				/* Reinitialize IOV for next run */
+				iov0[1].iov_len = MAX_NET_PKT_SIZE;
+			} else if (len < 0) {
+				disp_iovec(mic, &copy, __func__, __LINE__);
+				mpsslog("%s %s %d read failed %s ", mic->name,
+					__func__, __LINE__, strerror(errno));
+				mpsslog("cnt %d sum %zd\n",
+					copy.iovcnt, sum_iovec_len(&copy));
+			}
+		}
+
+		/*
+		 * Check if there is data to be read from virtio net and
+		 * write to TUN if there is.
+		 */
+		if (net_poll[NET_FD_VIRTIO_NET].revents & POLLIN) {
+			while (rx_vr.info->avail_idx !=
+				le16toh(rx_vr.vr.avail->idx)) {
+				copy.iov = iov1;
+				txrx_prepare(VIRTIO_ID_NET, 0, &rx_vr, &copy,
+					     MAX_NET_PKT_SIZE
+					+ sizeof(struct virtio_net_hdr));
+
+				err = mic_virtio_copy(mic,
+					mic->mic_net.virtio_net_fd, &rx_vr,
+					&copy);
+				if (!err) {
+#ifdef DEBUG
+					struct virtio_net_hdr *hdr
+						= (struct virtio_net_hdr *)
+							vnet_hdr[1];
+
+					mpsslog("%s %s %d hdr->flags 0x%x, ",
+						mic->name, __func__, __LINE__,
+						hdr->flags);
+					mpsslog("out_len %d gso_type 0x%x\n",
+						copy.out_len,
+						hdr->gso_type);
+#endif
+					/* Set the correct output iov_len */
+					iov1[1].iov_len = copy.out_len -
+						sizeof(struct virtio_net_hdr);
+					verify_out_len(mic, &copy);
+#ifdef DEBUG
+					disp_iovec(mic, copy, __func__,
+						   __LINE__);
+					mpsslog("%s %s %d ",
+						mic->name, __func__, __LINE__);
+					mpsslog("read from net 0x%lx\n",
+						sum_iovec_len(copy));
+#endif
+					len = writev(net_poll[NET_FD_TUN].fd,
+						copy.iov, copy.iovcnt);
+					if (len != sum_iovec_len(&copy)) {
+						mpsslog("Tun write failed %s ",
+							strerror(errno));
+						mpsslog("len 0x%zx ", len);
+						mpsslog("read_len 0x%zx\n",
+							sum_iovec_len(&copy));
+					} else {
+#ifdef DEBUG
+						disp_iovec(mic, &copy, __func__,
+							   __LINE__);
+						mpsslog("%s %s %d ",
+							mic->name, __func__,
+							__LINE__);
+						mpsslog("wrote to tap 0x%lx\n",
+							len);
+#endif
+					}
+				} else {
+					mpsslog("%s %s %d mic_virtio_copy %s\n",
+						mic->name, __func__, __LINE__,
+						strerror(errno));
+					break;
+				}
+			}
+		}
+		if (net_poll[NET_FD_VIRTIO_NET].revents & POLLERR)
+			mpsslog("%s: %s: POLLERR\n", __func__, mic->name);
+	}
+done:
+	pthread_exit(NULL);
+}
+
+/* virtio_console */
+#define VIRTIO_CONSOLE_FD 0
+#define MONITOR_FD (VIRTIO_CONSOLE_FD + 1)
+#define MAX_CONSOLE_FD (MONITOR_FD + 1)  /* must be the last one + 1 */
+#define MAX_BUFFER_SIZE PAGE_SIZE
+
+static void *
+virtio_console(void *arg)
+{
+	static __u8 vcons_buf[2][PAGE_SIZE];
+	struct iovec vcons_iov[2] = {
+		{ .iov_base = vcons_buf[0], .iov_len = sizeof(vcons_buf[0]) },
+		{ .iov_base = vcons_buf[1], .iov_len = sizeof(vcons_buf[1]) },
+	};
+	struct iovec *iov0 = &vcons_iov[0], *iov1 = &vcons_iov[1];
+	struct mic_info *mic = (struct mic_info *)arg;
+	int err;
+	struct pollfd console_poll[MAX_CONSOLE_FD];
+	int pty_fd;
+	char *pts_name;
+	ssize_t len;
+	struct mic_vring tx_vr, rx_vr;
+	struct mic_copy_desc copy;
+	struct mic_device_desc *desc;
+
+	pty_fd = posix_openpt(O_RDWR);
+	if (pty_fd < 0) {
+		mpsslog("can't open a pseudoterminal master device: %s\n",
+			strerror(errno));
+		goto _return;
+	}
+	pts_name = ptsname(pty_fd);
+	if (pts_name == NULL) {
+		mpsslog("can't get pts name\n");
+		goto _close_pty;
+	}
+	printf("%s console message goes to %s\n", mic->name, pts_name);
+	mpsslog("%s console message goes to %s\n", mic->name, pts_name);
+	err = grantpt(pty_fd);
+	if (err < 0) {
+		mpsslog("can't grant access: %s %s\n",
+			pts_name, strerror(errno));
+		goto _close_pty;
+	}
+	err = unlockpt(pty_fd);
+	if (err < 0) {
+		mpsslog("can't unlock a pseudoterminal: %s %s\n",
+			pts_name, strerror(errno));
+		goto _close_pty;
+	}
+	console_poll[MONITOR_FD].fd = pty_fd;
+	console_poll[MONITOR_FD].events = POLLIN;
+
+	console_poll[VIRTIO_CONSOLE_FD].fd = mic->mic_console.virtio_console_fd;
+	console_poll[VIRTIO_CONSOLE_FD].events = POLLIN;
+
+	if (MAP_FAILED == init_vr(mic, mic->mic_console.virtio_console_fd,
+				  VIRTIO_ID_CONSOLE, &tx_vr, &rx_vr,
+		virtcons_dev_page.dd.num_vq)) {
+		mpsslog("%s init_vr failed %s\n",
+			mic->name, strerror(errno));
+		goto _close_pty;
+	}
+
+	copy.iovcnt = 1;
+	desc = get_device_desc(mic, VIRTIO_ID_CONSOLE);
+
+	for (;;) {
+		console_poll[MONITOR_FD].revents = 0;
+		console_poll[VIRTIO_CONSOLE_FD].revents = 0;
+		err = poll(console_poll, MAX_CONSOLE_FD, -1);
+		if (err < 0) {
+			mpsslog("%s %d: poll failed: %s\n", __func__, __LINE__,
+				strerror(errno));
+			continue;
+		}
+		if (!(desc->status & VIRTIO_CONFIG_S_DRIVER_OK))
+			wait_for_card_driver(mic,
+					     mic->mic_console.virtio_console_fd,
+				VIRTIO_ID_CONSOLE);
+
+		if (console_poll[MONITOR_FD].revents & POLLIN) {
+			copy.iov = iov0;
+			len = readv(pty_fd, copy.iov, copy.iovcnt);
+			if (len > 0) {
+#ifdef DEBUG
+				disp_iovec(mic, copy, __func__, __LINE__);
+				mpsslog("%s %s %d read from tap 0x%lx\n",
+					mic->name, __func__, __LINE__,
+					len);
+#endif
+				spin_for_descriptors(mic, &tx_vr);
+				txrx_prepare(VIRTIO_ID_CONSOLE, 1, &tx_vr,
+					     &copy, len);
+
+				err = mic_virtio_copy(mic,
+					mic->mic_console.virtio_console_fd,
+					&tx_vr, &copy);
+				if (err < 0) {
+					mpsslog("%s %s %d mic_virtio_copy %s\n",
+						mic->name, __func__, __LINE__,
+						strerror(errno));
+				}
+				if (!err)
+					verify_out_len(mic, &copy);
+#ifdef DEBUG
+				disp_iovec(mic, copy, __func__, __LINE__);
+				mpsslog("%s %s %d wrote to net 0x%lx\n",
+					mic->name, __func__, __LINE__,
+					sum_iovec_len(copy));
+#endif
+				/* Reinitialize IOV for next run */
+				iov0->iov_len = PAGE_SIZE;
+			} else if (len < 0) {
+				disp_iovec(mic, &copy, __func__, __LINE__);
+				mpsslog("%s %s %d read failed %s ",
+					mic->name, __func__, __LINE__,
+					strerror(errno));
+				mpsslog("cnt %d sum %zd\n",
+					copy.iovcnt, sum_iovec_len(&copy));
+			}
+		}
+
+		if (console_poll[VIRTIO_CONSOLE_FD].revents & POLLIN) {
+			while (rx_vr.info->avail_idx !=
+				le16toh(rx_vr.vr.avail->idx)) {
+				copy.iov = iov1;
+				txrx_prepare(VIRTIO_ID_CONSOLE, 0, &rx_vr,
+					     &copy, PAGE_SIZE);
+
+				err = mic_virtio_copy(mic,
+					mic->mic_console.virtio_console_fd,
+					&rx_vr, &copy);
+				if (!err) {
+					/* Set the correct output iov_len */
+					iov1->iov_len = copy.out_len;
+					verify_out_len(mic, &copy);
+#ifdef DEBUG
+					disp_iovec(mic, copy, __func__,
+						   __LINE__);
+					mpsslog("%s %s %d ",
+						mic->name, __func__, __LINE__);
+					mpsslog("read from net 0x%lx\n",
+						sum_iovec_len(copy));
+#endif
+					len = writev(pty_fd,
+						copy.iov, copy.iovcnt);
+					if (len != sum_iovec_len(&copy)) {
+						mpsslog("Tun write failed %s ",
+							strerror(errno));
+						mpsslog("len 0x%zx ", len);
+						mpsslog("read_len 0x%zx\n",
+							sum_iovec_len(&copy));
+					} else {
+#ifdef DEBUG
+						disp_iovec(mic, copy, __func__,
+							   __LINE__);
+						mpsslog("%s %s %d ",
+							mic->name, __func__,
+							__LINE__);
+						mpsslog("wrote to tap 0x%lx\n",
+							len);
+#endif
+					}
+				} else {
+					mpsslog("%s %s %d mic_virtio_copy %s\n",
+						mic->name, __func__, __LINE__,
+						strerror(errno));
+					break;
+				}
+			}
+		}
+		if (console_poll[NET_FD_VIRTIO_NET].revents & POLLERR)
+			mpsslog("%s: %s: POLLERR\n", __func__, mic->name);
+	}
+_close_pty:
+	close(pty_fd);
+_return:
+	pthread_exit(NULL);
+}
+
+static void
+add_virtio_device(struct mic_info *mic, struct mic_device_desc *dd)
+{
+	char path[PATH_MAX];
+	int fd, err;
+
+	snprintf(path, PATH_MAX, "/dev/mic%d", mic->id);
+	fd = open(path, O_RDWR);
+	if (fd < 0) {
+		mpsslog("Could not open %s %s\n", path, strerror(errno));
+		return;
+	}
+
+	err = ioctl(fd, MIC_VIRTIO_ADD_DEVICE, dd);
+	if (err < 0) {
+		mpsslog("Could not add %d %s\n", dd->type, strerror(errno));
+		close(fd);
+		return;
+	}
+	switch (dd->type) {
+	case VIRTIO_ID_NET:
+		mic->mic_net.virtio_net_fd = fd;
+		mpsslog("Added VIRTIO_ID_NET for %s\n", mic->name);
+		break;
+	case VIRTIO_ID_CONSOLE:
+		mic->mic_console.virtio_console_fd = fd;
+		mpsslog("Added VIRTIO_ID_CONSOLE for %s\n", mic->name);
+		break;
+	case VIRTIO_ID_BLOCK:
+		mic->mic_virtblk.virtio_block_fd = fd;
+		mpsslog("Added VIRTIO_ID_BLOCK for %s\n", mic->name);
+		break;
+	}
+}
+
+static bool
+set_backend_file(struct mic_info *mic)
+{
+	FILE *config;
+	char buff[PATH_MAX], *line, *evv, *p;
+
+	snprintf(buff, PATH_MAX, "%s/mpssd%03d.conf", mic_config_dir, mic->id);
+	config = fopen(buff, "r");
+	if (config == NULL)
+		return false;
+	do {  /* look for "virtblk_backend=XXXX" */
+		line = fgets(buff, PATH_MAX, config);
+		if (line == NULL)
+			break;
+		if (*line == '#')
+			continue;
+		p = strchr(line, '\n');
+		if (p)
+			*p = '\0';
+	} while (strncmp(line, virtblk_backend, strlen(virtblk_backend)) != 0);
+	fclose(config);
+	if (line == NULL)
+		return false;
+	evv = strchr(line, '=');
+	if (evv == NULL)
+		return false;
+	mic->mic_virtblk.backend_file = malloc(strlen(evv) + 1);
+	if (mic->mic_virtblk.backend_file == NULL) {
+		mpsslog("%s %d can't allocate memory\n", mic->name, mic->id);
+		return false;
+	}
+	strcpy(mic->mic_virtblk.backend_file, evv + 1);
+	return true;
+}
+
+#define SECTOR_SIZE 512
+static bool
+set_backend_size(struct mic_info *mic)
+{
+	mic->mic_virtblk.backend_size = lseek(mic->mic_virtblk.backend, 0,
+		SEEK_END);
+	if (mic->mic_virtblk.backend_size < 0) {
+		mpsslog("%s: can't seek: %s\n",
+			mic->name, mic->mic_virtblk.backend_file);
+		return false;
+	}
+	virtblk_dev_page.blk_config.capacity =
+		mic->mic_virtblk.backend_size / SECTOR_SIZE;
+	if ((mic->mic_virtblk.backend_size % SECTOR_SIZE) != 0)
+		virtblk_dev_page.blk_config.capacity++;
+
+	virtblk_dev_page.blk_config.capacity =
+		htole64(virtblk_dev_page.blk_config.capacity);
+
+	return true;
+}
+
+static bool
+open_backend(struct mic_info *mic)
+{
+	if (!set_backend_file(mic))
+		goto _error_exit;
+	mic->mic_virtblk.backend = open(mic->mic_virtblk.backend_file, O_RDWR);
+	if (mic->mic_virtblk.backend < 0) {
+		mpsslog("%s: can't open: %s\n", mic->name,
+			mic->mic_virtblk.backend_file);
+		goto _error_free;
+	}
+	if (!set_backend_size(mic))
+		goto _error_close;
+	mic->mic_virtblk.backend_addr = mmap(NULL,
+		mic->mic_virtblk.backend_size,
+		PROT_READ|PROT_WRITE, MAP_SHARED,
+		mic->mic_virtblk.backend, 0L);
+	if (mic->mic_virtblk.backend_addr == MAP_FAILED) {
+		mpsslog("%s: can't map: %s %s\n",
+			mic->name, mic->mic_virtblk.backend_file,
+			strerror(errno));
+		goto _error_close;
+	}
+	return true;
+
+ _error_close:
+	close(mic->mic_virtblk.backend);
+ _error_free:
+	free(mic->mic_virtblk.backend_file);
+ _error_exit:
+	return false;
+}
+
+static void
+close_backend(struct mic_info *mic)
+{
+	munmap(mic->mic_virtblk.backend_addr, mic->mic_virtblk.backend_size);
+	close(mic->mic_virtblk.backend);
+	free(mic->mic_virtblk.backend_file);
+}
+
+static bool
+start_virtblk(struct mic_info *mic, struct mic_vring *vring)
+{
+	if (((unsigned long)&virtblk_dev_page.blk_config % 8) != 0) {
+		mpsslog("%s: blk_config is not 8 byte aligned.\n",
+			mic->name);
+		return false;
+	}
+	add_virtio_device(mic, &virtblk_dev_page.dd);
+	if (MAP_FAILED == init_vr(mic, mic->mic_virtblk.virtio_block_fd,
+				  VIRTIO_ID_BLOCK, vring, NULL,
+				  virtblk_dev_page.dd.num_vq)) {
+		mpsslog("%s init_vr failed %s\n",
+			mic->name, strerror(errno));
+		return false;
+	}
+	return true;
+}
+
+static void
+stop_virtblk(struct mic_info *mic)
+{
+	int vr_size, ret;
+
+	vr_size = PAGE_ALIGN(vring_size(MIC_VRING_ENTRIES,
+		MIC_VIRTIO_RING_ALIGN) + sizeof(struct _mic_vring_info));
+	ret = munmap(mic->mic_virtblk.block_dp,
+		MIC_DEVICE_PAGE_END + vr_size * virtblk_dev_page.dd.num_vq);
+	if (ret < 0)
+		mpsslog("%s munmap errno %d\n", mic->name, errno);
+	close(mic->mic_virtblk.virtio_block_fd);
+}
+
+static __u8
+header_error_check(struct vring_desc *desc)
+{
+	if (le32toh(desc->len) != sizeof(struct virtio_blk_outhdr)) {
+		mpsslog("%s() %d: length is not sizeof(virtio_blk_outhd)\n",
+			__func__, __LINE__);
+		return -EIO;
+	}
+	if (!(le16toh(desc->flags) & VRING_DESC_F_NEXT)) {
+		mpsslog("%s() %d: alone\n",
+			__func__, __LINE__);
+		return -EIO;
+	}
+	if (le16toh(desc->flags) & VRING_DESC_F_WRITE) {
+		mpsslog("%s() %d: not read\n",
+			__func__, __LINE__);
+		return -EIO;
+	}
+	return 0;
+}
+
+static int
+read_header(int fd, struct virtio_blk_outhdr *hdr, __u32 desc_idx)
+{
+	struct iovec iovec;
+	struct mic_copy_desc copy;
+
+	iovec.iov_len = sizeof(*hdr);
+	iovec.iov_base = hdr;
+	copy.iov = &iovec;
+	copy.iovcnt = 1;
+	copy.vr_idx = 0;  /* only one vring on virtio_block */
+	copy.update_used = false;  /* do not update used index */
+	return ioctl(fd, MIC_VIRTIO_COPY_DESC, &copy);
+}
+
+static int
+transfer_blocks(int fd, struct iovec *iovec, __u32 iovcnt)
+{
+	struct mic_copy_desc copy;
+
+	copy.iov = iovec;
+	copy.iovcnt = iovcnt;
+	copy.vr_idx = 0;  /* only one vring on virtio_block */
+	copy.update_used = false;  /* do not update used index */
+	return ioctl(fd, MIC_VIRTIO_COPY_DESC, &copy);
+}
+
+static __u8
+status_error_check(struct vring_desc *desc)
+{
+	if (le32toh(desc->len) != sizeof(__u8)) {
+		mpsslog("%s() %d: length is not sizeof(status)\n",
+			__func__, __LINE__);
+		return -EIO;
+	}
+	return 0;
+}
+
+static int
+write_status(int fd, __u8 *status)
+{
+	struct iovec iovec;
+	struct mic_copy_desc copy;
+
+	iovec.iov_base = status;
+	iovec.iov_len = sizeof(*status);
+	copy.iov = &iovec;
+	copy.iovcnt = 1;
+	copy.vr_idx = 0;  /* only one vring on virtio_block */
+	copy.update_used = true; /* Update used index */
+	return ioctl(fd, MIC_VIRTIO_COPY_DESC, &copy);
+}
+
+static void *
+virtio_block(void *arg)
+{
+	struct mic_info *mic = (struct mic_info *)arg;
+	int ret;
+	struct pollfd block_poll;
+	struct mic_vring vring;
+	__u16 avail_idx;
+	__u32 desc_idx;
+	struct vring_desc *desc;
+	struct iovec *iovec, *piov;
+	__u8 status;
+	__u32 buffer_desc_idx;
+	struct virtio_blk_outhdr hdr;
+	void *fos;
+
+	for (;;) {  /* forever */
+		if (!open_backend(mic)) { /* No virtblk */
+			for (mic->mic_virtblk.signaled = 0;
+				!mic->mic_virtblk.signaled;)
+				sleep(1);
+			continue;
+		}
+
+		/* backend file is specified. */
+		if (!start_virtblk(mic, &vring))
+			goto _close_backend;
+		iovec = malloc(sizeof(*iovec) *
+			le32toh(virtblk_dev_page.blk_config.seg_max));
+		if (!iovec) {
+			mpsslog("%s: can't alloc iovec: %s\n",
+				mic->name, strerror(ENOMEM));
+			goto _stop_virtblk;
+		}
+
+		block_poll.fd = mic->mic_virtblk.virtio_block_fd;
+		block_poll.events = POLLIN;
+		for (mic->mic_virtblk.signaled = 0;
+		     !mic->mic_virtblk.signaled;) {
+			block_poll.revents = 0;
+					/* timeout in 1 sec to see signaled */
+			ret = poll(&block_poll, 1, 1000);
+			if (ret < 0) {
+				mpsslog("%s %d: poll failed: %s\n",
+					__func__, __LINE__,
+					strerror(errno));
+				continue;
+			}
+
+			if (!(block_poll.revents & POLLIN)) {
+#ifdef DEBUG
+				mpsslog("%s %d: block_poll.revents=0x%x\n",
+					__func__, __LINE__, block_poll.revents);
+#endif
+				continue;
+			}
+
+			/* POLLIN */
+			while (vring.info->avail_idx !=
+				le16toh(vring.vr.avail->idx)) {
+				/* read header element */
+				avail_idx =
+					vring.info->avail_idx &
+					(vring.vr.num - 1);
+				desc_idx = le16toh(
+					vring.vr.avail->ring[avail_idx]);
+				desc = &vring.vr.desc[desc_idx];
+#ifdef DEBUG
+				mpsslog("%s() %d: avail_idx=%d ",
+					__func__, __LINE__,
+					vring.info->avail_idx);
+				mpsslog("vring.vr.num=%d desc=%p\n",
+					vring.vr.num, desc);
+#endif
+				status = header_error_check(desc);
+				ret = read_header(
+					mic->mic_virtblk.virtio_block_fd,
+					&hdr, desc_idx);
+				if (ret < 0) {
+					mpsslog("%s() %d %s: ret=%d %s\n",
+						__func__, __LINE__,
+						mic->name, ret,
+						strerror(errno));
+					break;
+				}
+				/* buffer element */
+				piov = iovec;
+				status = 0;
+				fos = mic->mic_virtblk.backend_addr +
+					(hdr.sector * SECTOR_SIZE);
+				buffer_desc_idx = next_desc(desc);
+				desc_idx = buffer_desc_idx;
+				for (desc = &vring.vr.desc[buffer_desc_idx];
+				     desc->flags & VRING_DESC_F_NEXT;
+				     desc_idx = next_desc(desc),
+					     desc = &vring.vr.desc[desc_idx]) {
+					piov->iov_len = desc->len;
+					piov->iov_base = fos;
+					piov++;
+					fos += desc->len;
+				}
+				/* Returning NULLs for VIRTIO_BLK_T_GET_ID. */
+				if (hdr.type & ~(VIRTIO_BLK_T_OUT |
+					VIRTIO_BLK_T_GET_ID)) {
+					/*
+					  VIRTIO_BLK_T_IN - does not do
+					  anything. Probably for documenting.
+					  VIRTIO_BLK_T_SCSI_CMD - for
+					  virtio_scsi.
+					  VIRTIO_BLK_T_FLUSH - turned off in
+					  config space.
+					  VIRTIO_BLK_T_BARRIER - defined but not
+					  used in anywhere.
+					*/
+					mpsslog("%s() %d: type %x ",
+						__func__, __LINE__,
+						hdr.type);
+					mpsslog("is not supported\n");
+					status = -ENOTSUP;
+
+				} else {
+					ret = transfer_blocks(
+					mic->mic_virtblk.virtio_block_fd,
+						iovec,
+						piov - iovec);
+					if (ret < 0 &&
+					    status != 0)
+						status = ret;
+				}
+				/* write status and update used pointer */
+				if (status != 0)
+					status = status_error_check(desc);
+				ret = write_status(
+					mic->mic_virtblk.virtio_block_fd,
+					&status);
+#ifdef DEBUG
+				mpsslog("%s() %d: write status=%d on desc=%p\n",
+					__func__, __LINE__,
+					status, desc);
+#endif
+			}
+		}
+		free(iovec);
+_stop_virtblk:
+		stop_virtblk(mic);
+_close_backend:
+		close_backend(mic);
+	}  /* forever */
+
+	pthread_exit(NULL);
+}
+
+static void
+reset(struct mic_info *mic)
+{
+#define RESET_TIMEOUT 120
+	int i = RESET_TIMEOUT;
+	setsysfs(mic->name, "state", "reset");
+	while (i) {
+		char *state;
+		state = readsysfs(mic->name, "state");
+		if (!state)
+			goto retry;
+		mpsslog("%s: %s %d state %s\n",
+			mic->name, __func__, __LINE__, state);
+
+		/*
+		 * If the shutdown was initiated by OSPM, the state stays
+		 * in "suspended" which is also a valid condition for reset.
+		 */
+		if ((!strcmp(state, "offline")) ||
+		    (!strcmp(state, "suspended"))) {
+			free(state);
+			break;
+		}
+		free(state);
+retry:
+		sleep(1);
+		i--;
+	}
+}
+
+static int
+get_mic_shutdown_status(struct mic_info *mic, char *shutdown_status)
+{
+	if (!strcmp(shutdown_status, "nop"))
+		return MIC_NOP;
+	if (!strcmp(shutdown_status, "crashed"))
+		return MIC_CRASHED;
+	if (!strcmp(shutdown_status, "halted"))
+		return MIC_HALTED;
+	if (!strcmp(shutdown_status, "poweroff"))
+		return MIC_POWER_OFF;
+	if (!strcmp(shutdown_status, "restart"))
+		return MIC_RESTART;
+	mpsslog("%s: BUG invalid status %s\n", mic->name, shutdown_status);
+	/* Invalid state */
+	assert(0);
+};
+
+static int get_mic_state(struct mic_info *mic, char *state)
+{
+	if (!strcmp(state, "offline"))
+		return MIC_OFFLINE;
+	if (!strcmp(state, "online"))
+		return MIC_ONLINE;
+	if (!strcmp(state, "shutting_down"))
+		return MIC_SHUTTING_DOWN;
+	if (!strcmp(state, "reset_failed"))
+		return MIC_RESET_FAILED;
+	if (!strcmp(state, "suspending"))
+		return MIC_SUSPENDING;
+	if (!strcmp(state, "suspended"))
+		return MIC_SUSPENDED;
+	mpsslog("%s: BUG invalid state %s\n", mic->name, state);
+	/* Invalid state */
+	assert(0);
+};
+
+static void mic_handle_shutdown(struct mic_info *mic)
+{
+#define SHUTDOWN_TIMEOUT 60
+	int i = SHUTDOWN_TIMEOUT, ret, stat = 0;
+	char *shutdown_status;
+	while (i) {
+		shutdown_status = readsysfs(mic->name, "shutdown_status");
+		if (!shutdown_status)
+			continue;
+		mpsslog("%s: %s %d shutdown_status %s\n",
+			mic->name, __func__, __LINE__, shutdown_status);
+		switch (get_mic_shutdown_status(mic, shutdown_status)) {
+		case MIC_RESTART:
+			mic->restart = 1;
+		case MIC_HALTED:
+		case MIC_POWER_OFF:
+		case MIC_CRASHED:
+			free(shutdown_status);
+			goto reset;
+		default:
+			break;
+		}
+		free(shutdown_status);
+		sleep(1);
+		i--;
+	}
+reset:
+	ret = kill(mic->pid, SIGTERM);
+	mpsslog("%s: %s %d kill pid %d ret %d\n",
+		mic->name, __func__, __LINE__,
+		mic->pid, ret);
+	if (!ret) {
+		ret = waitpid(mic->pid, &stat,
+			WIFSIGNALED(stat));
+		mpsslog("%s: %s %d waitpid ret %d pid %d\n",
+			mic->name, __func__, __LINE__,
+			ret, mic->pid);
+	}
+	if (ret == mic->pid)
+		reset(mic);
+}
+
+static void *
+mic_config(void *arg)
+{
+	struct mic_info *mic = (struct mic_info *)arg;
+	char *state = NULL;
+	char pathname[PATH_MAX];
+	int fd, ret;
+	struct pollfd ufds[1];
+	char value[4096];
+
+	snprintf(pathname, PATH_MAX - 1, "%s/%s/%s",
+		 MICSYSFSDIR, mic->name, "state");
+
+	fd = open(pathname, O_RDONLY);
+	if (fd < 0) {
+		mpsslog("%s: opening file %s failed %s\n",
+			mic->name, pathname, strerror(errno));
+		goto error;
+	}
+
+	do {
+		ret = read(fd, value, sizeof(value));
+		if (ret < 0) {
+			mpsslog("%s: Failed to read sysfs entry '%s': %s\n",
+				mic->name, pathname, strerror(errno));
+			goto close_error1;
+		}
+retry:
+		state = readsysfs(mic->name, "state");
+		if (!state)
+			goto retry;
+		mpsslog("%s: %s %d state %s\n",
+			mic->name, __func__, __LINE__, state);
+		switch (get_mic_state(mic, state)) {
+		case MIC_SHUTTING_DOWN:
+			mic_handle_shutdown(mic);
+			goto close_error;
+		case MIC_SUSPENDING:
+			mic->boot_on_resume = 1;
+			setsysfs(mic->name, "state", "suspend");
+			mic_handle_shutdown(mic);
+			goto close_error;
+		case MIC_OFFLINE:
+			if (mic->boot_on_resume) {
+				setsysfs(mic->name, "state", "boot");
+				mic->boot_on_resume = 0;
+			}
+			break;
+		default:
+			break;
+		}
+		free(state);
+
+		ufds[0].fd = fd;
+		ufds[0].events = POLLERR | POLLPRI;
+		ret = poll(ufds, 1, -1);
+		if (ret < 0) {
+			mpsslog("%s: poll failed %s\n",
+				mic->name, strerror(errno));
+			goto close_error1;
+		}
+	} while (1);
+close_error:
+	free(state);
+close_error1:
+	close(fd);
+error:
+	init_mic(mic);
+	pthread_exit(NULL);
+}
+
+static void
+set_cmdline(struct mic_info *mic)
+{
+	char buffer[PATH_MAX];
+	int len;
+
+	len = snprintf(buffer, PATH_MAX,
+		"clocksource=tsc highres=off nohz=off ");
+	len += snprintf(buffer + len, PATH_MAX,
+		"cpufreq_on;corec6_off;pc3_off;pc6_off ");
+	len += snprintf(buffer + len, PATH_MAX,
+		"ifcfg=static;address,172.31.%d.1;netmask,255.255.255.0",
+		mic->id);
+
+	setsysfs(mic->name, "cmdline", buffer);
+	mpsslog("%s: Command line: \"%s\"\n", mic->name, buffer);
+	snprintf(buffer, PATH_MAX, "172.31.%d.1", mic->id);
+	mpsslog("%s: IPADDR: \"%s\"\n", mic->name, buffer);
+}
+
+static void
+set_log_buf_info(struct mic_info *mic)
+{
+	int fd;
+	off_t len;
+	char system_map[] = "/lib/firmware/mic/System.map";
+	char *map, *temp, log_buf[17] = {'\0'};
+
+	fd = open(system_map, O_RDONLY);
+	if (fd < 0) {
+		mpsslog("%s: Opening System.map failed: %d\n",
+			mic->name, errno);
+		return;
+	}
+	len = lseek(fd, 0, SEEK_END);
+	if (len < 0) {
+		mpsslog("%s: Reading System.map size failed: %d\n",
+			mic->name, errno);
+		close(fd);
+		return;
+	}
+	map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
+	if (map == MAP_FAILED) {
+		mpsslog("%s: mmap of System.map failed: %d\n",
+			mic->name, errno);
+		close(fd);
+		return;
+	}
+	temp = strstr(map, "__log_buf");
+	if (!temp) {
+		mpsslog("%s: __log_buf not found: %d\n", mic->name, errno);
+		munmap(map, len);
+		close(fd);
+		return;
+	}
+	strncpy(log_buf, temp - 19, 16);
+	setsysfs(mic->name, "log_buf_addr", log_buf);
+	mpsslog("%s: log_buf_addr: %s\n", mic->name, log_buf);
+	temp = strstr(map, "log_buf_len");
+	if (!temp) {
+		mpsslog("%s: log_buf_len not found: %d\n", mic->name, errno);
+		munmap(map, len);
+		close(fd);
+		return;
+	}
+	strncpy(log_buf, temp - 19, 16);
+	setsysfs(mic->name, "log_buf_len", log_buf);
+	mpsslog("%s: log_buf_len: %s\n", mic->name, log_buf);
+	munmap(map, len);
+	close(fd);
+}
+
+static void init_mic(struct mic_info *mic);
+
+static void
+change_virtblk_backend(int x, siginfo_t *siginfo, void *p)
+{
+	struct mic_info *mic;
+
+	for (mic = mic_list.next; mic != NULL; mic = mic->next)
+		mic->mic_virtblk.signaled = 1/* true */;
+}
+
+static void
+init_mic(struct mic_info *mic)
+{
+	struct sigaction ignore = {
+		.sa_flags = 0,
+		.sa_handler = SIG_IGN
+	};
+	struct sigaction act = {
+		.sa_flags = SA_SIGINFO,
+		.sa_sigaction = change_virtblk_backend,
+	};
+	char buffer[PATH_MAX];
+	int err;
+
+	/*
+	 * Currently, one virtio block device is supported for each MIC card
+	 * at a time. Any user (or test) can send a SIGUSR1 to the MIC daemon.
+	 * The signal informs the virtio block backend about a change in the
+	 * configuration file which specifies the virtio backend file name on
+	 * the host. Virtio block backend then re-reads the configuration file
+	 * and switches to the new block device. This signalling mechanism may
+	 * not be required once multiple virtio block devices are supported by
+	 * the MIC daemon.
+	 */
+	sigaction(SIGUSR1, &ignore, NULL);
+
+	mic->pid = fork();
+	switch (mic->pid) {
+	case 0:
+		set_log_buf_info(mic);
+		set_cmdline(mic);
+		add_virtio_device(mic, &virtcons_dev_page.dd);
+		add_virtio_device(mic, &virtnet_dev_page.dd);
+		err = pthread_create(&mic->mic_console.console_thread, NULL,
+			virtio_console, mic);
+		if (err)
+			mpsslog("%s virtcons pthread_create failed %s\n",
+				mic->name, strerror(err));
+		err = pthread_create(&mic->mic_net.net_thread, NULL,
+			virtio_net, mic);
+		if (err)
+			mpsslog("%s virtnet pthread_create failed %s\n",
+				mic->name, strerror(err));
+		err = pthread_create(&mic->mic_virtblk.block_thread, NULL,
+			virtio_block, mic);
+		if (err)
+			mpsslog("%s virtblk pthread_create failed %s\n",
+				mic->name, strerror(err));
+		sigemptyset(&act.sa_mask);
+		err = sigaction(SIGUSR1, &act, NULL);
+		if (err)
+			mpsslog("%s sigaction SIGUSR1 failed %s\n",
+				mic->name, strerror(errno));
+		while (1)
+			sleep(60);
+	case -1:
+		mpsslog("fork failed MIC name %s id %d errno %d\n",
+			mic->name, mic->id, errno);
+		break;
+	default:
+		if (mic->restart) {
+			snprintf(buffer, PATH_MAX, "boot");
+			setsysfs(mic->name, "state", buffer);
+			mpsslog("%s restarting mic %d\n",
+				mic->name, mic->restart);
+			mic->restart = 0;
+		}
+		pthread_create(&mic->config_thread, NULL, mic_config, mic);
+	}
+}
+
+static void
+start_daemon(void)
+{
+	struct mic_info *mic;
+
+	for (mic = mic_list.next; mic != NULL; mic = mic->next)
+		init_mic(mic);
+
+	while (1)
+		sleep(60);
+}
+
+static int
+init_mic_list(void)
+{
+	struct mic_info *mic = &mic_list;
+	struct dirent *file;
+	DIR *dp;
+	int cnt = 0;
+
+	dp = opendir(MICSYSFSDIR);
+	if (!dp)
+		return 0;
+
+	while ((file = readdir(dp)) != NULL) {
+		if (!strncmp(file->d_name, "mic", 3)) {
+			mic->next = calloc(1, sizeof(struct mic_info));
+			if (mic->next) {
+				mic = mic->next;
+				mic->id = atoi(&file->d_name[3]);
+				mic->name = malloc(strlen(file->d_name) + 16);
+				if (mic->name)
+					strcpy(mic->name, file->d_name);
+				mpsslog("MIC name %s id %d\n", mic->name,
+					mic->id);
+				cnt++;
+			}
+		}
+	}
+
+	closedir(dp);
+	return cnt;
+}
+
+void
+mpsslog(char *format, ...)
+{
+	va_list args;
+	char buffer[4096];
+	char ts[52], *ts1;
+	time_t t;
+
+	if (logfp == NULL)
+		return;
+
+	va_start(args, format);
+	vsprintf(buffer, format, args);
+	va_end(args);
+
+	time(&t);
+	ts1 = ctime_r(&t, ts);
+	ts1[strlen(ts1) - 1] = '\0';
+	fprintf(logfp, "%s: %s", ts1, buffer);
+
+	fflush(logfp);
+}
+
+int
+main(int argc, char *argv[])
+{
+	int cnt;
+	pid_t pid;
+
+	myname = argv[0];
+
+	logfp = fopen(LOGFILE_NAME, "a+");
+	if (!logfp) {
+		fprintf(stderr, "cannot open logfile '%s'\n", LOGFILE_NAME);
+		exit(1);
+	}
+	pid = fork();
+	switch (pid) {
+	case 0:
+		break;
+	case -1:
+		exit(2);
+	default:
+		exit(0);
+	}
+
+	mpsslog("MIC Daemon start\n");
+
+	cnt = init_mic_list();
+	if (cnt == 0) {
+		mpsslog("MIC module not loaded\n");
+		exit(3);
+	}
+	mpsslog("MIC found %d devices\n", cnt);
+
+	start_daemon();
+
+	exit(0);
+}
diff --git a/Documentation/mic/mpssd/mpssd.h b/Documentation/mic/mpssd/mpssd.h
new file mode 100644
index 0000000..f5f18b1
--- /dev/null
+++ b/Documentation/mic/mpssd/mpssd.h
@@ -0,0 +1,102 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC User Space Tools.
+ */
+#ifndef _MPSSD_H_
+#define _MPSSD_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <libgen.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/dir.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/utsname.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <pthread.h>
+#include <signal.h>
+#include <limits.h>
+#include <syslog.h>
+#include <getopt.h>
+#include <net/if.h>
+#include <linux/if_tun.h>
+#include <linux/if_tun.h>
+#include <linux/virtio_ids.h>
+
+#define MICSYSFSDIR "/sys/class/mic"
+#define LOGFILE_NAME "/var/log/mpssd"
+#define PAGE_SIZE 4096
+
+struct mic_console_info {
+	pthread_t       console_thread;
+	int		virtio_console_fd;
+	void		*console_dp;
+};
+
+struct mic_net_info {
+	pthread_t       net_thread;
+	int		virtio_net_fd;
+	int		tap_fd;
+	void		*net_dp;
+};
+
+struct mic_virtblk_info {
+	pthread_t       block_thread;
+	int		virtio_block_fd;
+	void		*block_dp;
+	volatile sig_atomic_t	signaled;
+	char		*backend_file;
+	int		backend;
+	void		*backend_addr;
+	long		backend_size;
+};
+
+struct mic_info {
+	int		id;
+	char		*name;
+	pthread_t       config_thread;
+	pid_t		pid;
+	struct mic_console_info	mic_console;
+	struct mic_net_info	mic_net;
+	struct mic_virtblk_info	mic_virtblk;
+	int		restart;
+	int		boot_on_resume;
+	struct mic_info *next;
+};
+
+__attribute__((format(printf, 1, 2)))
+void mpsslog(char *format, ...);
+char *readsysfs(char *dir, char *entry);
+int setsysfs(char *dir, char *entry, char *value);
+#endif
diff --git a/Documentation/mic/mpssd/sysfs.c b/Documentation/mic/mpssd/sysfs.c
new file mode 100644
index 0000000..8dd3269
--- /dev/null
+++ b/Documentation/mic/mpssd/sysfs.c
@@ -0,0 +1,102 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC User Space Tools.
+ */
+
+#include "mpssd.h"
+
+#define PAGE_SIZE 4096
+
+char *
+readsysfs(char *dir, char *entry)
+{
+	char filename[PATH_MAX];
+	char value[PAGE_SIZE];
+	char *string = NULL;
+	int fd;
+	int len;
+
+	if (dir == NULL)
+		snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry);
+	else
+		snprintf(filename, PATH_MAX,
+			 "%s/%s/%s", MICSYSFSDIR, dir, entry);
+
+	fd = open(filename, O_RDONLY);
+	if (fd < 0) {
+		mpsslog("Failed to open sysfs entry '%s': %s\n",
+			filename, strerror(errno));
+		return NULL;
+	}
+
+	len = read(fd, value, sizeof(value));
+	if (len < 0) {
+		mpsslog("Failed to read sysfs entry '%s': %s\n",
+			filename, strerror(errno));
+		goto readsys_ret;
+	}
+	if (len == 0)
+		goto readsys_ret;
+
+	value[len - 1] = '\0';
+
+	string = malloc(strlen(value) + 1);
+	if (string)
+		strcpy(string, value);
+
+readsys_ret:
+	close(fd);
+	return string;
+}
+
+int
+setsysfs(char *dir, char *entry, char *value)
+{
+	char filename[PATH_MAX];
+	char *oldvalue;
+	int fd, ret = 0;
+
+	if (dir == NULL)
+		snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry);
+	else
+		snprintf(filename, PATH_MAX, "%s/%s/%s",
+			 MICSYSFSDIR, dir, entry);
+
+	oldvalue = readsysfs(dir, entry);
+
+	fd = open(filename, O_RDWR);
+	if (fd < 0) {
+		ret = errno;
+		mpsslog("Failed to open sysfs entry '%s': %s\n",
+			filename, strerror(errno));
+		goto done;
+	}
+
+	if (!oldvalue || strcmp(value, oldvalue)) {
+		if (write(fd, value, strlen(value)) < 0) {
+			ret = errno;
+			mpsslog("Failed to write new sysfs entry '%s': %s\n",
+				filename, strerror(errno));
+		}
+	}
+	close(fd);
+done:
+	if (oldvalue)
+		free(oldvalue);
+	return ret;
+}
diff --git a/Documentation/networking/dccp.txt b/Documentation/networking/dccp.txt
index d718bc2..bf5dbe3 100644
--- a/Documentation/networking/dccp.txt
+++ b/Documentation/networking/dccp.txt
@@ -18,8 +18,8 @@
 Datagram Congestion Control Protocol (DCCP) is an unreliable, connection
 oriented protocol designed to solve issues present in UDP and TCP, particularly
 for real-time and multimedia (streaming) traffic.
-It divides into a base protocol (RFC 4340) and plugable congestion control
-modules called CCIDs. Like plugable TCP congestion control, at least one CCID
+It divides into a base protocol (RFC 4340) and pluggable congestion control
+modules called CCIDs. Like pluggable TCP congestion control, at least one CCID
 needs to be enabled in order for the protocol to function properly. In the Linux
 implementation, this is the TCP-like CCID2 (RFC 4341). Additional CCIDs, such as
 the TCP-friendly CCID3 (RFC 4342), are optional.
diff --git a/Documentation/networking/e100.txt b/Documentation/networking/e100.txt
index 13a3212..f862cf3 100644
--- a/Documentation/networking/e100.txt
+++ b/Documentation/networking/e100.txt
@@ -103,7 +103,7 @@
   PRO/100 Family of Adapters is e100.
 
   As an example, if you install the e100 driver for two PRO/100 adapters
-  (eth0 and eth1), add the following to a configuraton file in /etc/modprobe.d/
+  (eth0 and eth1), add the following to a configuration file in /etc/modprobe.d/
 
        alias eth0 e100
        alias eth1 e100
diff --git a/Documentation/networking/ieee802154.txt b/Documentation/networking/ieee802154.txt
index 09eb573..22bbc72 100644
--- a/Documentation/networking/ieee802154.txt
+++ b/Documentation/networking/ieee802154.txt
@@ -4,7 +4,7 @@
 
 Introduction
 ============
-The IEEE 802.15.4 working group focuses on standartization of bottom
+The IEEE 802.15.4 working group focuses on standardization of bottom
 two layers: Medium Access Control (MAC) and Physical (PHY). And there
 are mainly two options available for upper layers:
  - ZigBee - proprietary protocol from ZigBee Alliance
@@ -66,7 +66,7 @@
 code via plain sk_buffs. On skb reception skb->cb must contain additional
 info as described in the struct ieee802154_mac_cb. During packet transmission
 the skb->cb is used to provide additional data to device's header_ops->create
-function. Be aware, that this data can be overriden later (when socket code
+function. Be aware that this data can be overridden later (when socket code
 submits skb to qdisc), so if you need something from that cb later, you should
 store info in the skb->data on your own.
 
diff --git a/Documentation/networking/l2tp.txt b/Documentation/networking/l2tp.txt
index e63fc1f..c74434d 100644
--- a/Documentation/networking/l2tp.txt
+++ b/Documentation/networking/l2tp.txt
@@ -197,7 +197,7 @@
 implemented to provide extra debug information to help diagnose
 problems.) Users should use the netlink API.
 
-/proc/net/pppol2tp is also provided for backwards compaibility with
+/proc/net/pppol2tp is also provided for backwards compatibility with
 the original pppol2tp driver. It lists information about L2TPv2
 tunnels and sessions only. Its use is discouraged.
 
diff --git a/Documentation/networking/netdev-FAQ.txt b/Documentation/networking/netdev-FAQ.txt
index d9112f0..0fe1c6e 100644
--- a/Documentation/networking/netdev-FAQ.txt
+++ b/Documentation/networking/netdev-FAQ.txt
@@ -4,23 +4,23 @@
 
 Q: What is netdev?
 
-A: It is a mailing list for all network related linux stuff.  This includes
+A: It is a mailing list for all network-related Linux stuff.  This includes
    anything found under net/  (i.e. core code like IPv6) and drivers/net
-   (i.e. hardware specific drivers) in the linux source tree.
+   (i.e. hardware specific drivers) in the Linux source tree.
 
    Note that some subsystems (e.g. wireless drivers) which have a high volume
    of traffic have their own specific mailing lists.
 
-   The netdev list is managed (like many other linux mailing lists) through
+   The netdev list is managed (like many other Linux mailing lists) through
    VGER ( http://vger.kernel.org/ ) and archives can be found below:
 
 	http://marc.info/?l=linux-netdev
 	http://www.spinics.net/lists/netdev/
 
-   Aside from subsystems like that mentioned above, all network related linux
-   development (i.e. RFC, review, comments, etc) takes place on netdev.
+   Aside from subsystems like that mentioned above, all network-related Linux
+   development (i.e. RFC, review, comments, etc.) takes place on netdev.
 
-Q: How do the changes posted to netdev make their way into linux?
+Q: How do the changes posted to netdev make their way into Linux?
 
 A: There are always two trees (git repositories) in play.  Both are driven
    by David Miller, the main network maintainer.  There is the "net" tree,
@@ -35,7 +35,7 @@
 Q: How often do changes from these trees make it to the mainline Linus tree?
 
 A: To understand this, you need to know a bit of background information
-   on the cadence of linux development.  Each new release starts off with
+   on the cadence of Linux development.  Each new release starts off with
    a two week "merge window" where the main maintainers feed their new
    stuff to Linus for merging into the mainline tree.  After the two weeks,
    the merge window is closed, and it is called/tagged "-rc1".  No new
@@ -46,7 +46,7 @@
    things are in a state of churn), and a week after the last vX.Y-rcN
    was done, the official "vX.Y" is released.
 
-   Relating that to netdev:  At the beginning of the 2 week merge window,
+   Relating that to netdev:  At the beginning of the 2-week merge window,
    the net-next tree will be closed - no new changes/features.  The
    accumulated new content of the past ~10 weeks will be passed onto
    mainline/Linus via a pull request for vX.Y -- at the same time,
@@ -59,16 +59,16 @@
    IMPORTANT:  Do not send new net-next content to netdev during the
    period during which net-next tree is closed.
 
-   Shortly after the two weeks have passed, (and vX.Y-rc1 is released) the
+   Shortly after the two weeks have passed (and vX.Y-rc1 is released), the
    tree for net-next reopens to collect content for the next (vX.Y+1) release.
 
    If you aren't subscribed to netdev and/or are simply unsure if net-next
    has re-opened yet, simply check the net-next git repository link above for
-   any new networking related commits.
+   any new networking-related commits.
 
    The "net" tree continues to collect fixes for the vX.Y content, and
    is fed back to Linus at regular (~weekly) intervals.  Meaning that the
-   focus for "net" is on stablilization and bugfixes.
+   focus for "net" is on stabilization and bugfixes.
 
    Finally, the vX.Y gets released, and the whole cycle starts over.
 
@@ -217,7 +217,7 @@
    to why it happens, and then if necessary, explain why the fix proposed
    is the best way to get things done.   Don't mangle whitespace, and as
    is common, don't mis-indent function arguments that span multiple lines.
-   If it is your 1st patch, mail it to yourself so you can test apply
+   If it is your first patch, mail it to yourself so you can test apply
    it to an unpatched tree to confirm infrastructure didn't mangle it.
 
    Finally, go back and read Documentation/SubmittingPatches to be
diff --git a/Documentation/networking/netlink_mmap.txt b/Documentation/networking/netlink_mmap.txt
index 5333788..b261229 100644
--- a/Documentation/networking/netlink_mmap.txt
+++ b/Documentation/networking/netlink_mmap.txt
@@ -45,7 +45,7 @@
 
 Conversion of the reception path involves calling poll() on the file
 descriptor, once the socket is readable the frames from the ring are
-processsed in order until no more messages are available, as indicated by
+processed in order until no more messages are available, as indicated by
 a status word in the frame header.
 
 On kernel side, in order to make use of memory mapped I/O on receive, the
@@ -56,7 +56,7 @@
 
 Conversion of the transmit path involves changing message construction to
 use memory from the TX ring instead of (usually) a buffer declared on the
-stack and setting up the frame header approriately. Optionally poll() can
+stack and setting up the frame header appropriately. Optionally poll() can
 be used to wait for free frames in the TX ring.
 
 Structured and definitions for using memory mapped I/O are contained in
@@ -231,7 +231,7 @@
 	if (setsockopt(fd, NETLINK_TX_RING, &req, sizeof(req)) < 0)
 		exit(1)
 
-	/* Calculate size of each invididual ring */
+	/* Calculate size of each individual ring */
 	ring_size = req.nm_block_nr * req.nm_block_size;
 
 	/* Map RX/TX rings. The TX ring is located after the RX ring */
diff --git a/Documentation/networking/operstates.txt b/Documentation/networking/operstates.txt
index 9769457..355c6d8 100644
--- a/Documentation/networking/operstates.txt
+++ b/Documentation/networking/operstates.txt
@@ -89,8 +89,8 @@
 it as lower layer.
 
 Note that for certain kind of soft-devices, which are not managing any
-real hardware, there is possible to set this bit from userpsace.
-One should use TVL IFLA_CARRIER to do so.
+real hardware, it is possible to set this bit from userspace.  One
+should use TVL IFLA_CARRIER to do so.
 
 netif_carrier_ok() can be used to query that bit.
 
diff --git a/Documentation/networking/rxrpc.txt b/Documentation/networking/rxrpc.txt
index 60d05eb..b89bc82e 100644
--- a/Documentation/networking/rxrpc.txt
+++ b/Documentation/networking/rxrpc.txt
@@ -144,7 +144,7 @@
  (*) Calls use ACK packets to handle reliability.  Data packets are also
      explicitly sequenced per call.
 
- (*) There are two types of positive acknowledgement: hard-ACKs and soft-ACKs.
+ (*) There are two types of positive acknowledgment: hard-ACKs and soft-ACKs.
      A hard-ACK indicates to the far side that all the data received to a point
      has been received and processed; a soft-ACK indicates that the data has
      been received but may yet be discarded and re-requested.  The sender may
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index 457b8bb..cdd916d 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -160,7 +160,7 @@
  o pmt: core has the embedded power module (optional).
  o force_sf_dma_mode: force DMA to use the Store and Forward mode
 		     instead of the Threshold.
- o force_thresh_dma_mode: force DMA to use the Shreshold mode other than
+ o force_thresh_dma_mode: force DMA to use the Threshold mode other than
 		     the Store and Forward mode.
  o riwt_off: force to disable the RX watchdog feature and switch to NAPI mode.
  o fix_mac_speed: this callback is used for modifying some syscfg registers
@@ -175,7 +175,7 @@
 	     registers.
  o custom_cfg/custom_data: this is a custom configuration that can be passed
 			   while initializing the resources.
- o bsp_priv: another private poiter.
+ o bsp_priv: another private pointer.
 
 For MDIO bus The we have:
 
@@ -271,7 +271,7 @@
  o dwmac1000_dma.c:  dma functions for the GMAC chip;
  o dwmac1000.h: specific header file for the GMAC;
  o dwmac100_core: MAC 100 core and dma code;
- o dwmac100_dma.c: dma funtions for the MAC chip;
+ o dwmac100_dma.c: dma functions for the MAC chip;
  o dwmac1000.h: specific header file for the MAC;
  o dwmac_lib.c: generic DMA functions shared among chips;
  o enh_desc.c: functions for handling enhanced descriptors;
@@ -364,4 +364,4 @@
 10) TODO:
  o XGMAC is not supported.
  o Complete the TBI & RTBI support.
- o extened VLAN support for 3.70a SYNP GMAC.
+ o extend VLAN support for 3.70a SYNP GMAC.
diff --git a/Documentation/networking/vortex.txt b/Documentation/networking/vortex.txt
index 9a8041d..97282da 100644
--- a/Documentation/networking/vortex.txt
+++ b/Documentation/networking/vortex.txt
@@ -68,7 +68,7 @@
 
 There are several parameters which may be provided to the driver when
 its module is loaded.  These are usually placed in /etc/modprobe.d/*.conf
-configuretion files.  Example:
+configuration files.  Example:
 
 options 3c59x debug=3 rx_copybreak=300
 
@@ -178,7 +178,7 @@
 
   The driver's interrupt service routine can handle many receive and
   transmit packets in a single invocation.  It does this in a loop. 
-  The value of max_interrupt_work governs how mnay times the interrupt
+  The value of max_interrupt_work governs how many times the interrupt
   service routine will loop.  The default value is 32 loops.  If this
   is exceeded the interrupt service routine gives up and generates a
   warning message "eth0: Too much work in interrupt".
diff --git a/Documentation/networking/x25-iface.txt b/Documentation/networking/x25-iface.txt
index 78f662e..7f213b5 100644
--- a/Documentation/networking/x25-iface.txt
+++ b/Documentation/networking/x25-iface.txt
@@ -105,7 +105,7 @@
     later.
     The lapb module interface was modified to support this. Its
     data_indication() method should now transparently pass the
-    netif_rx() return value to the (lapb mopdule) caller.
+    netif_rx() return value to the (lapb module) caller.
 (2) Drivers for kernel versions 2.2.x should always check the global
     variable netdev_dropping when a new frame is received. The driver
     should only call netif_rx() if netdev_dropping is zero. Otherwise
diff --git a/Documentation/phy.txt b/Documentation/phy.txt
new file mode 100644
index 0000000..0103e4b
--- /dev/null
+++ b/Documentation/phy.txt
@@ -0,0 +1,166 @@
+			    PHY SUBSYSTEM
+		  Kishon Vijay Abraham I <kishon@ti.com>
+
+This document explains the Generic PHY Framework along with the APIs provided,
+and how-to-use.
+
+1. Introduction
+
+*PHY* is the abbreviation for physical layer. It is used to connect a device
+to the physical medium e.g., the USB controller has a PHY to provide functions
+such as serialization, de-serialization, encoding, decoding and is responsible
+for obtaining the required data transmission rate. Note that some USB
+controllers have PHY functionality embedded into it and others use an external
+PHY. Other peripherals that use PHY include Wireless LAN, Ethernet,
+SATA etc.
+
+The intention of creating this framework is to bring the PHY drivers spread
+all over the Linux kernel to drivers/phy to increase code re-use and for
+better code maintainability.
+
+This framework will be of use only to devices that use external PHY (PHY
+functionality is not embedded within the controller).
+
+2. Registering/Unregistering the PHY provider
+
+PHY provider refers to an entity that implements one or more PHY instances.
+For the simple case where the PHY provider implements only a single instance of
+the PHY, the framework provides its own implementation of of_xlate in
+of_phy_simple_xlate. If the PHY provider implements multiple instances, it
+should provide its own implementation of of_xlate. of_xlate is used only for
+dt boot case.
+
+#define of_phy_provider_register(dev, xlate)    \
+        __of_phy_provider_register((dev), THIS_MODULE, (xlate))
+
+#define devm_of_phy_provider_register(dev, xlate)       \
+        __devm_of_phy_provider_register((dev), THIS_MODULE, (xlate))
+
+of_phy_provider_register and devm_of_phy_provider_register macros can be used to
+register the phy_provider and it takes device and of_xlate as
+arguments. For the dt boot case, all PHY providers should use one of the above
+2 macros to register the PHY provider.
+
+void devm_of_phy_provider_unregister(struct device *dev,
+	struct phy_provider *phy_provider);
+void of_phy_provider_unregister(struct phy_provider *phy_provider);
+
+devm_of_phy_provider_unregister and of_phy_provider_unregister can be used to
+unregister the PHY.
+
+3. Creating the PHY
+
+The PHY driver should create the PHY in order for other peripheral controllers
+to make use of it. The PHY framework provides 2 APIs to create the PHY.
+
+struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
+        struct phy_init_data *init_data);
+struct phy *devm_phy_create(struct device *dev, const struct phy_ops *ops,
+	struct phy_init_data *init_data);
+
+The PHY drivers can use one of the above 2 APIs to create the PHY by passing
+the device pointer, phy ops and init_data.
+phy_ops is a set of function pointers for performing PHY operations such as
+init, exit, power_on and power_off. *init_data* is mandatory to get a reference
+to the PHY in the case of non-dt boot. See section *Board File Initialization*
+on how init_data should be used.
+
+Inorder to dereference the private data (in phy_ops), the phy provider driver
+can use phy_set_drvdata() after creating the PHY and use phy_get_drvdata() in
+phy_ops to get back the private data.
+
+4. Getting a reference to the PHY
+
+Before the controller can make use of the PHY, it has to get a reference to
+it. This framework provides the following APIs to get a reference to the PHY.
+
+struct phy *phy_get(struct device *dev, const char *string);
+struct phy *devm_phy_get(struct device *dev, const char *string);
+
+phy_get and devm_phy_get can be used to get the PHY. In the case of dt boot,
+the string arguments should contain the phy name as given in the dt data and
+in the case of non-dt boot, it should contain the label of the PHY.
+The only difference between the two APIs is that devm_phy_get associates the
+device with the PHY using devres on successful PHY get. On driver detach,
+release function is invoked on the the devres data and devres data is freed.
+
+5. Releasing a reference to the PHY
+
+When the controller no longer needs the PHY, it has to release the reference
+to the PHY it has obtained using the APIs mentioned in the above section. The
+PHY framework provides 2 APIs to release a reference to the PHY.
+
+void phy_put(struct phy *phy);
+void devm_phy_put(struct device *dev, struct phy *phy);
+
+Both these APIs are used to release a reference to the PHY and devm_phy_put
+destroys the devres associated with this PHY.
+
+6. Destroying the PHY
+
+When the driver that created the PHY is unloaded, it should destroy the PHY it
+created using one of the following 2 APIs.
+
+void phy_destroy(struct phy *phy);
+void devm_phy_destroy(struct device *dev, struct phy *phy);
+
+Both these APIs destroy the PHY and devm_phy_destroy destroys the devres
+associated with this PHY.
+
+7. PM Runtime
+
+This subsystem is pm runtime enabled. So while creating the PHY,
+pm_runtime_enable of the phy device created by this subsystem is called and
+while destroying the PHY, pm_runtime_disable is called. Note that the phy
+device created by this subsystem will be a child of the device that calls
+phy_create (PHY provider device).
+
+So pm_runtime_get_sync of the phy_device created by this subsystem will invoke
+pm_runtime_get_sync of PHY provider device because of parent-child relationship.
+It should also be noted that phy_power_on and phy_power_off performs
+phy_pm_runtime_get_sync and phy_pm_runtime_put respectively.
+There are exported APIs like phy_pm_runtime_get, phy_pm_runtime_get_sync,
+phy_pm_runtime_put, phy_pm_runtime_put_sync, phy_pm_runtime_allow and
+phy_pm_runtime_forbid for performing PM operations.
+
+8. Board File Initialization
+
+Certain board file initialization is necessary in order to get a reference
+to the PHY in the case of non-dt boot.
+Say we have a single device that implements 3 PHYs that of USB, SATA and PCIe,
+then in the board file the following initialization should be done.
+
+struct phy_consumer consumers[] = {
+	PHY_CONSUMER("dwc3.0", "usb"),
+	PHY_CONSUMER("pcie.0", "pcie"),
+	PHY_CONSUMER("sata.0", "sata"),
+};
+PHY_CONSUMER takes 2 parameters, first is the device name of the controller
+(PHY consumer) and second is the port name.
+
+struct phy_init_data init_data = {
+	.consumers = consumers,
+	.num_consumers = ARRAY_SIZE(consumers),
+};
+
+static const struct platform_device pipe3_phy_dev = {
+	.name = "pipe3-phy",
+	.id = -1,
+	.dev = {
+		.platform_data = {
+			.init_data = &init_data,
+		},
+	},
+};
+
+then, while doing phy_create, the PHY driver should pass this init_data
+	phy_create(dev, ops, pdata->init_data);
+
+and the controller driver (phy consumer) should pass the port name along with
+the device to get a reference to the PHY
+	phy_get(dev, "pcie");
+
+9. DeviceTree Binding
+
+The documentation for PHY dt binding can be found @
+Documentation/devicetree/bindings/phy/phy-bindings.txt
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
index c0ffd30..a7929cb 100644
--- a/Documentation/pinctrl.txt
+++ b/Documentation/pinctrl.txt
@@ -358,7 +358,12 @@
 	.gc = &chip;
 };
 
-In this case the pin_base property will be ignored.
+In this case the pin_base property will be ignored. If the name of a pin
+group is known, the pins and npins elements of the above structure can be
+initialised using the function pinctrl_get_group_pins(), e.g. for pin
+group "foo":
+
+pinctrl_get_group_pins(pctl, "foo", &gpio_range.pins, &gpio_range.npins);
 
 When GPIO-specific functions in the pin control subsystem are called, these
 ranges will be used to look up the appropriate pin controller by inspecting
diff --git a/Documentation/pps/pps.txt b/Documentation/pps/pps.txt
index d35dcdd..c03b1be 100644
--- a/Documentation/pps/pps.txt
+++ b/Documentation/pps/pps.txt
@@ -66,6 +66,21 @@
 into files /dev/pps0, /dev/pps1, etc..
 
 
+PPS with USB to serial devices
+------------------------------
+
+It is possible to grab the PPS from an USB to serial device. However,
+you should take into account the latencies and jitter introduced by
+the USB stack. Users has reported clock instability around +-1ms when
+synchronized with PPS through USB. This isn't suited for time server
+synchronization.
+
+If your device doesn't report PPS, you can check that the feature is
+supported by its driver. Most of the time, you only need to add a call
+to usb_serial_handle_dcd_change after checking the DCD status (see
+ch341 and pl2303 examples).
+
+
 Coding example
 --------------
 
diff --git a/Documentation/s390/s390dbf.txt b/Documentation/s390/s390dbf.txt
index fcaf0b4..3da1633 100644
--- a/Documentation/s390/s390dbf.txt
+++ b/Documentation/s390/s390dbf.txt
@@ -158,6 +158,16 @@
 Description:   Sets new actual debug level if new_level is valid. 
 
 ---------------------------------------------------------------------------
+bool debug_level_enabled (debug_info_t * id, int level);
+
+Parameter:    id:	  handle for debug log
+	      level:	  debug level
+
+Return Value: True if level is less or equal to the current debug level.
+
+Description:  Returns true if debug events for the specified level would be
+	      logged. Otherwise returns false.
+---------------------------------------------------------------------------
 void debug_stop_all(void);
 
 Parameter:     none
diff --git a/Documentation/scheduler/sched-arch.txt b/Documentation/scheduler/sched-arch.txt
index b1b8587..9290de7 100644
--- a/Documentation/scheduler/sched-arch.txt
+++ b/Documentation/scheduler/sched-arch.txt
@@ -65,11 +65,6 @@
 
 Possible arch problems I found (and either tried to fix or didn't):
 
-h8300 - Is such sleeping racy vs interrupts? (See #4a).
-        The H8/300 manual I found indicates yes, however disabling IRQs
-        over the sleep mean only NMIs can wake it up, so can't fix easily
-        without doing spin waiting.
-
 ia64 - is safe_halt call racy vs interrupts? (does it sleep?) (See #4a)
 
 sh64 - Is sleeping racy vs interrupts? (See #4a)
diff --git a/Documentation/serial/driver b/Documentation/serial/driver
index 067c47d..c3a7689 100644
--- a/Documentation/serial/driver
+++ b/Documentation/serial/driver
@@ -264,10 +264,6 @@
 	Locking: none.
 	Interrupts: caller dependent.
 
-  set_wake(port,state)
-	Enable/disable power management wakeup on serial activity.  Not
-	currently implemented.
-
   type(port)
 	Return a pointer to a string constant describing the specified
 	port, or return NULL, in which case the string 'unknown' is
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 95731a0..b8dd0df 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -616,7 +616,7 @@
 
     As default, snd-dummy drivers doesn't allocate the real buffers
     but either ignores read/write or mmap a single dummy page to all
-    buffer pages, in order to save the resouces.  If your apps need
+    buffer pages, in order to save the resources.  If your apps need
     the read/ written buffer data to be consistent, pass fake_buffer=0
     option.
 
diff --git a/Documentation/sound/alsa/Audiophile-Usb.txt b/Documentation/sound/alsa/Audiophile-Usb.txt
index 654dd3b..e7a5ed4 100644
--- a/Documentation/sound/alsa/Audiophile-Usb.txt
+++ b/Documentation/sound/alsa/Audiophile-Usb.txt
@@ -232,7 +232,7 @@
    # modprobe snd-usb-audio index=1 device_setup=0x09
 
  * Or while configuring the modules options in your modules configuration file
-   (tipically a .conf file in /etc/modprobe.d/ directory:
+   (typically a .conf file in /etc/modprobe.d/ directory:
        alias snd-card-1 snd-usb-audio
        options snd-usb-audio index=1 device_setup=0x09
 
diff --git a/Documentation/sound/alsa/CMIPCI.txt b/Documentation/sound/alsa/CMIPCI.txt
index 16935c8..4e36e6e 100644
--- a/Documentation/sound/alsa/CMIPCI.txt
+++ b/Documentation/sound/alsa/CMIPCI.txt
@@ -87,7 +87,7 @@
 
 and use the interleaved 4 channel data.
 
-There are some control switchs affecting to the speaker connections:
+There are some control switches affecting to the speaker connections:
 
 "Line-In Mode"	- an enum control to change the behavior of line-in
 	jack.  Either "Line-In", "Rear Output" or "Bass Output" can
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index f911e36..85c362d 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -28,6 +28,7 @@
   alc269-dmic		Enable ALC269(VA) digital mic workaround
   alc271-dmic		Enable ALC271X digital mic workaround
   inv-dmic		Inverted internal mic workaround
+  headset-mic		Indicates a combined headset (headphone+mic) jack
   lenovo-dock   	Enables docking station I/O for some Lenovos
   dell-headset-multi	Headset jack, which can also be used as mic-in
   dell-headset-dock	Headset jack (without mic-in), and also dock I/O
diff --git a/Documentation/sound/alsa/compress_offload.txt b/Documentation/sound/alsa/compress_offload.txt
index fd74ff2..630c492 100644
--- a/Documentation/sound/alsa/compress_offload.txt
+++ b/Documentation/sound/alsa/compress_offload.txt
@@ -217,12 +217,12 @@
   would be enabled with ALSA kcontrols.
 
 - Audio policy/resource management. This API does not provide any
-  hooks to query the utilization of the audio DSP, nor any premption
+  hooks to query the utilization of the audio DSP, nor any preemption
   mechanisms.
 
-- No notion of underun/overrun. Since the bytes written are compressed
+- No notion of underrun/overrun. Since the bytes written are compressed
   in nature and data written/read doesn't translate directly to
-  rendered output in time, this does not deal with underrun/overun and
+  rendered output in time, this does not deal with underrun/overrun and
   maybe dealt in user-library
 
 Credits:
diff --git a/Documentation/sound/alsa/soc/DPCM.txt b/Documentation/sound/alsa/soc/DPCM.txt
new file mode 100644
index 0000000..0110180
--- /dev/null
+++ b/Documentation/sound/alsa/soc/DPCM.txt
@@ -0,0 +1,380 @@
+Dynamic PCM
+===========
+
+1. Description
+==============
+
+Dynamic PCM allows an ALSA PCM device to digitally route its PCM audio to
+various digital endpoints during the PCM stream runtime. e.g. PCM0 can route
+digital audio to I2S DAI0, I2S DAI1 or PDM DAI2. This is useful for on SoC DSP
+drivers that expose several ALSA PCMs and can route to multiple DAIs.
+
+The DPCM runtime routing is determined by the ALSA mixer settings in the same
+way as the analog signal is routed in an ASoC codec driver. DPCM uses a DAPM
+graph representing the DSP internal audio paths and uses the mixer settings to
+determine the patch used by each ALSA PCM.
+
+DPCM re-uses all the existing component codec, platform and DAI drivers without
+any modifications.
+
+
+Phone Audio System with SoC based DSP
+-------------------------------------
+
+Consider the following phone audio subsystem. This will be used in this
+document for all examples :-
+
+| Front End PCMs    |  SoC DSP  | Back End DAIs | Audio devices |
+
+                    *************
+PCM0 <------------> *           * <----DAI0-----> Codec Headset
+                    *           *
+PCM1 <------------> *           * <----DAI1-----> Codec Speakers
+                    *   DSP     *
+PCM2 <------------> *           * <----DAI2-----> MODEM
+                    *           *
+PCM3 <------------> *           * <----DAI3-----> BT
+                    *           *
+                    *           * <----DAI4-----> DMIC
+                    *           *
+                    *           * <----DAI5-----> FM
+                    *************
+
+This diagram shows a simple smart phone audio subsystem. It supports Bluetooth,
+FM digital radio, Speakers, Headset Jack, digital microphones and cellular
+modem. This sound card exposes 4 DSP front end (FE) ALSA PCM devices and
+supports 6 back end (BE) DAIs. Each FE PCM can digitally route audio data to any
+of the BE DAIs. The FE PCM devices can also route audio to more than 1 BE DAI.
+
+
+
+Example - DPCM Switching playback from DAI0 to DAI1
+---------------------------------------------------
+
+Audio is being played to the Headset. After a while the user removes the headset
+and audio continues playing on the speakers.
+
+Playback on PCM0 to Headset would look like :-
+
+                    *************
+PCM0 <============> *           * <====DAI0=====> Codec Headset
+                    *           *
+PCM1 <------------> *           * <----DAI1-----> Codec Speakers
+                    *   DSP     *
+PCM2 <------------> *           * <----DAI2-----> MODEM
+                    *           *
+PCM3 <------------> *           * <----DAI3-----> BT
+                    *           *
+                    *           * <----DAI4-----> DMIC
+                    *           *
+                    *           * <----DAI5-----> FM
+                    *************
+
+The headset is removed from the jack by user so the speakers must now be used :-
+
+                    *************
+PCM0 <============> *           * <----DAI0-----> Codec Headset
+                    *           *
+PCM1 <------------> *           * <====DAI1=====> Codec Speakers
+                    *   DSP     *
+PCM2 <------------> *           * <----DAI2-----> MODEM
+                    *           *
+PCM3 <------------> *           * <----DAI3-----> BT
+                    *           *
+                    *           * <----DAI4-----> DMIC
+                    *           *
+                    *           * <----DAI5-----> FM
+                    *************
+
+The audio driver processes this as follows :-
+
+ 1) Machine driver receives Jack removal event.
+
+ 2) Machine driver OR audio HAL disables the Headset path.
+
+ 3) DPCM runs the PCM trigger(stop), hw_free(), shutdown() operations on DAI0
+    for headset since the path is now disabled.
+
+ 4) Machine driver or audio HAL enables the speaker path.
+
+ 5) DPCM runs the PCM ops for startup(), hw_params(), prepapre() and
+    trigger(start) for DAI1 Speakers since the path is enabled.
+
+In this example, the machine driver or userspace audio HAL can alter the routing
+and then DPCM will take care of managing the DAI PCM operations to either bring
+the link up or down. Audio playback does not stop during this transition.
+
+
+
+DPCM machine driver
+===================
+
+The DPCM enabled ASoC machine driver is similar to normal machine drivers
+except that we also have to :-
+
+ 1) Define the FE and BE DAI links.
+
+ 2) Define any FE/BE PCM operations.
+
+ 3) Define widget graph connections.
+
+
+1 FE and BE DAI links
+---------------------
+
+| Front End PCMs    |  SoC DSP  | Back End DAIs | Audio devices |
+
+                    *************
+PCM0 <------------> *           * <----DAI0-----> Codec Headset
+                    *           *
+PCM1 <------------> *           * <----DAI1-----> Codec Speakers
+                    *   DSP     *
+PCM2 <------------> *           * <----DAI2-----> MODEM
+                    *           *
+PCM3 <------------> *           * <----DAI3-----> BT
+                    *           *
+                    *           * <----DAI4-----> DMIC
+                    *           *
+                    *           * <----DAI5-----> FM
+                    *************
+
+For the example above we have to define 4 FE DAI links and 6 BE DAI links. The
+FE DAI links are defined as follows :-
+
+static struct snd_soc_dai_link machine_dais[] = {
+	{
+		.name = "PCM0 System",
+		.stream_name = "System Playback",
+		.cpu_dai_name = "System Pin",
+		.platform_name = "dsp-audio",
+		.codec_name = "snd-soc-dummy",
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+		.dpcm_playback = 1,
+	},
+	.....< other FE and BE DAI links here >
+};
+
+This FE DAI link is pretty similar to a regular DAI link except that we also
+set the DAI link to a DPCM FE with the "dynamic = 1". The supported FE stream
+directions should also be set with the "dpcm_playback" and "dpcm_capture"
+flags. There is also an option to specify the ordering of the trigger call for
+each FE. This allows the ASoC core to trigger the DSP before or after the other
+components (as some DSPs have strong requirements for the ordering DAI/DSP
+start and stop sequences).
+
+The FE DAI above sets the codec and code DAIs to dummy devices since the BE is
+dynamic and will change depending on runtime config.
+
+The BE DAIs are configured as follows :-
+
+static struct snd_soc_dai_link machine_dais[] = {
+	.....< FE DAI links here >
+	{
+		.name = "Codec Headset",
+		.cpu_dai_name = "ssp-dai.0",
+		.platform_name = "snd-soc-dummy",
+		.no_pcm = 1,
+		.codec_name = "rt5640.0-001c",
+		.codec_dai_name = "rt5640-aif1",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.be_hw_params_fixup = hswult_ssp0_fixup,
+		.ops = &haswell_ops,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+	},
+	.....< other BE DAI links here >
+};
+
+This BE DAI link connects DAI0 to the codec (in this case RT5460 AIF1). It sets
+the "no_pcm" flag to mark it has a BE and sets flags for supported stream
+directions using "dpcm_playback" and "dpcm_capture" above.
+
+The BE has also flags set for ignoring suspend and PM down time. This allows
+the BE to work in a hostless mode where the host CPU is not transferring data
+like a BT phone call :-
+
+                    *************
+PCM0 <------------> *           * <----DAI0-----> Codec Headset
+                    *           *
+PCM1 <------------> *           * <----DAI1-----> Codec Speakers
+                    *   DSP     *
+PCM2 <------------> *           * <====DAI2=====> MODEM
+                    *           *
+PCM3 <------------> *           * <====DAI3=====> BT
+                    *           *
+                    *           * <----DAI4-----> DMIC
+                    *           *
+                    *           * <----DAI5-----> FM
+                    *************
+
+This allows the host CPU to sleep whilst the DSP, MODEM DAI and the BT DAI are
+still in operation.
+
+A BE DAI link can also set the codec to a dummy device if the code is a device
+that is managed externally.
+
+Likewise a BE DAI can also set a dummy cpu DAI if the CPU DAI is managed by the
+DSP firmware.
+
+
+2 FE/BE PCM operations
+----------------------
+
+The BE above also exports some PCM operations and a "fixup" callback. The fixup
+callback is used by the machine driver to (re)configure the DAI based upon the
+FE hw params. i.e. the DSP may perform SRC or ASRC from the FE to BE.
+
+e.g. DSP converts all FE hw params to run at fixed rate of 48k, 16bit, stereo for
+DAI0. This means all FE hw_params have to be fixed in the machine driver for
+DAI0 so that the DAI is running at desired configuration regardless of the FE
+configuration.
+
+static int dai0_fixup(struct snd_soc_pcm_runtime *rtd,
+			struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+			SNDRV_PCM_HW_PARAM_RATE);
+	struct snd_interval *channels = hw_param_interval(params,
+						SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	/* The DSP will covert the FE rate to 48k, stereo */
+	rate->min = rate->max = 48000;
+	channels->min = channels->max = 2;
+
+	/* set DAI0 to 16 bit */
+	snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
+				    SNDRV_PCM_HW_PARAM_FIRST_MASK],
+				    SNDRV_PCM_FORMAT_S16_LE);
+	return 0;
+}
+
+The other PCM operation are the same as for regular DAI links. Use as necessary.
+
+
+3 Widget graph connections
+--------------------------
+
+The BE DAI links will normally be connected to the graph at initialisation time
+by the ASoC DAPM core. However, if the BE codec or BE DAI is a dummy then this
+has to be set explicitly in the driver :-
+
+/* BE for codec Headset -  DAI0 is dummy and managed by DSP FW */
+{"DAI0 CODEC IN", NULL, "AIF1 Capture"},
+{"AIF1 Playback", NULL, "DAI0 CODEC OUT"},
+
+
+Writing a DPCM DSP driver
+=========================
+
+The DPCM DSP driver looks much like a standard platform class ASoC driver
+combined with elements from a codec class driver. A DSP platform driver must
+implement :-
+
+ 1) Front End PCM DAIs - i.e. struct snd_soc_dai_driver.
+
+ 2) DAPM graph showing DSP audio routing from FE DAIs to BEs.
+
+ 3) DAPM widgets from DSP graph.
+
+ 4) Mixers for gains, routing, etc.
+
+ 5) DMA configuration.
+
+ 6) BE AIF widgets.
+
+Items 6 is important for routing the audio outside of the DSP. AIF need to be
+defined for each BE and each stream direction. e.g for BE DAI0 above we would
+have :-
+
+SND_SOC_DAPM_AIF_IN("DAI0 RX", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("DAI0 TX", NULL, 0, SND_SOC_NOPM, 0, 0),
+
+The BE AIF are used to connect the DSP graph to the graphs for the other
+component drivers (e.g. codec graph).
+
+
+Hostless PCM streams
+====================
+
+A hostless PCM stream is a stream that is not routed through the host CPU. An
+example of this would be a phone call from handset to modem.
+
+
+                    *************
+PCM0 <------------> *           * <----DAI0-----> Codec Headset
+                    *           *
+PCM1 <------------> *           * <====DAI1=====> Codec Speakers/Mic
+                    *   DSP     *
+PCM2 <------------> *           * <====DAI2=====> MODEM
+                    *           *
+PCM3 <------------> *           * <----DAI3-----> BT
+                    *           *
+                    *           * <----DAI4-----> DMIC
+                    *           *
+                    *           * <----DAI5-----> FM
+                    *************
+
+In this case the PCM data is routed via the DSP. The host CPU in this use case
+is only used for control and can sleep during the runtime of the stream.
+
+The host can control the hostless link either by :-
+
+ 1) Configuring the link as a CODEC <-> CODEC style link. In this case the link
+    is enabled or disabled by the state of the DAPM graph. This usually means
+    there is a mixer control that can be used to connect or disconnect the path
+    between both DAIs.
+
+ 2) Hostless FE. This FE has a virtual connection to the BE DAI links on the DAPM
+    graph. Control is then carried out by the FE as regular PCM operations.
+    This method gives more control over the DAI links, but requires much more
+    userspace code to control the link. Its recommended to use CODEC<->CODEC
+    unless your HW needs more fine grained sequencing of the PCM ops.
+
+
+CODEC <-> CODEC link
+--------------------
+
+This DAI link is enabled when DAPM detects a valid path within the DAPM graph.
+The machine driver sets some additional parameters to the DAI link i.e.
+
+static const struct snd_soc_pcm_stream dai_params = {
+	.formats = SNDRV_PCM_FMTBIT_S32_LE,
+	.rate_min = 8000,
+	.rate_max = 8000,
+	.channels_min = 2,
+	.channels_max = 2,
+};
+
+static struct snd_soc_dai_link dais[] = {
+	< ... more DAI links above ... >
+	{
+		.name = "MODEM",
+		.stream_name = "MODEM",
+		.cpu_dai_name = "dai2",
+		.codec_dai_name = "modem-aif1",
+		.codec_name = "modem",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+				| SND_SOC_DAIFMT_CBM_CFM,
+		.params = &dai_params,
+	}
+	< ... more DAI links here ... >
+
+These parameters are used to configure the DAI hw_params() when DAPM detects a
+valid path and then calls the PCM operations to start the link. DAPM will also
+call the appropriate PCM operations to disable the DAI when the path is no
+longer valid.
+
+
+Hostless FE
+-----------
+
+The DAI link(s) are enabled by a FE that does not read or write any PCM data.
+This means creating a new FE that is connected with a virtual path to both
+DAI links. The DAI links will be started when the FE PCM is started and stopped
+when the FE PCM is stopped. Note that the FE PCM cannot read or write data in
+this configuration.
+
+
diff --git a/Documentation/sound/alsa/soc/codec.txt b/Documentation/sound/alsa/soc/codec.txt
index bce23a4..db5f9c9 100644
--- a/Documentation/sound/alsa/soc/codec.txt
+++ b/Documentation/sound/alsa/soc/codec.txt
@@ -1,22 +1,23 @@
-ASoC Codec Driver
-=================
+ASoC Codec Class Driver
+=======================
 
-The codec driver is generic and hardware independent code that configures the
-codec to provide audio capture and playback. It should contain no code that is
-specific to the target platform or machine. All platform and machine specific
-code should be added to the platform and machine drivers respectively.
+The codec class driver is generic and hardware independent code that configures
+the codec, FM, MODEM, BT or external DSP to provide audio capture and playback.
+It should contain no code that is specific to the target platform or machine.
+All platform and machine specific code should be added to the platform and
+machine drivers respectively.
 
-Each codec driver *must* provide the following features:-
+Each codec class driver *must* provide the following features:-
 
  1) Codec DAI and PCM configuration
- 2) Codec control IO - using I2C, 3 Wire(SPI) or both APIs
+ 2) Codec control IO - using RegMap API
  3) Mixers and audio controls
  4) Codec audio operations
+ 5) DAPM description.
+ 6) DAPM event handler.
 
 Optionally, codec drivers can also provide:-
 
- 5) DAPM description.
- 6) DAPM event handler.
  7) DAC Digital mute control.
 
 Its probably best to use this guide in conjunction with the existing codec
@@ -64,26 +65,9 @@
 2 - Codec control IO
 --------------------
 The codec can usually be controlled via an I2C or SPI style interface
-(AC97 combines control with data in the DAI). The codec drivers provide
-functions to read and write the codec registers along with supplying a
-register cache:-
-
-	/* IO control data and register cache */
-	void *control_data; /* codec control (i2c/3wire) data */
-	void *reg_cache;
-
-Codec read/write should do any data formatting and call the hardware
-read write below to perform the IO. These functions are called by the
-core and ALSA when performing DAPM or changing the mixer:-
-
-    unsigned int (*read)(struct snd_soc_codec *, unsigned int);
-    int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
-
-Codec hardware IO functions - usually points to either the I2C, SPI or AC97
-read/write:-
-
-	hw_write_t hw_write;
-	hw_read_t hw_read;
+(AC97 combines control with data in the DAI). The codec driver should use the
+Regmap API for all codec IO. Please see include/linux/regmap.h and existing
+codec drivers for example regmap usage.
 
 
 3 - Mixers and audio controls
@@ -127,7 +111,7 @@
 
 4 - Codec Audio Operations
 --------------------------
-The codec driver also supports the following ALSA operations:-
+The codec driver also supports the following ALSA PCM operations:-
 
 /* SoC audio ops */
 struct snd_soc_ops {
diff --git a/Documentation/sound/alsa/soc/dapm.txt b/Documentation/sound/alsa/soc/dapm.txt
index 05bf5a0..6faab48 100644
--- a/Documentation/sound/alsa/soc/dapm.txt
+++ b/Documentation/sound/alsa/soc/dapm.txt
@@ -21,7 +21,7 @@
 
 There are 4 power domains within DAPM
 
-   1. Codec domain - VREF, VMID (core codec and audio power)
+   1. Codec bias domain - VREF, VMID (core codec and audio power)
       Usually controlled at codec probe/remove and suspend/resume, although
       can be set at stream time if power is not needed for sidetone, etc.
 
@@ -30,7 +30,7 @@
       machine driver and responds to asynchronous events e.g when HP
       are inserted
 
-   3. Path domain - audio susbsystem signal paths
+   3. Path domain - audio subsystem signal paths
       Automatically set when mixer and mux settings are changed by the user.
       e.g. alsamixer, amixer.
 
@@ -63,14 +63,22 @@
  o Line       - Line Input/Output (and optional Jack)
  o Speaker    - Speaker
  o Supply     - Power or clock supply widget used by other widgets.
+ o Regulator  - External regulator that supplies power to audio components.
+ o Clock      -	External clock that supplies clock to audio components.
+ o AIF IN     - Audio Interface Input (with TDM slot mask).
+ o AIF OUT    - Audio Interface Output (with TDM slot mask).
+ o Siggen     - Signal Generator.
+ o DAI IN     - Digital Audio Interface Input.
+ o DAI OUT    - Digital Audio Interface Output.
+ o DAI Link   - DAI Link between two DAI structures */
  o Pre        - Special PRE widget (exec before all others)
  o Post       - Special POST widget (exec after all others)
 
 (Widgets are defined in include/sound/soc-dapm.h)
 
-Widgets are usually added in the codec driver and the machine driver. There are
-convenience macros defined in soc-dapm.h that can be used to quickly build a
-list of widgets of the codecs and machines DAPM widgets.
+Widgets can be added to the sound card by any of the component driver types.
+There are convenience macros defined in soc-dapm.h that can be used to quickly
+build a list of widgets of the codecs and machines DAPM widgets.
 
 Most widgets have a name, register, shift and invert. Some widgets have extra
 parameters for stream name and kcontrols.
@@ -80,11 +88,13 @@
 -------------------------
 
 Stream Widgets relate to the stream power domain and only consist of ADCs
-(analog to digital converters) and DACs (digital to analog converters).
+(analog to digital converters), DACs (digital to analog converters),
+AIF IN and AIF OUT.
 
 Stream widgets have the following format:-
 
 SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert),
+SND_SOC_DAPM_AIF_IN(name, stream, slot, reg, shift, invert)
 
 NOTE: the stream name must match the corresponding stream name in your codec
 snd_soc_codec_dai.
@@ -94,6 +104,11 @@
 SND_SOC_DAPM_DAC("HiFi DAC", "HiFi Playback", REG, 3, 1),
 SND_SOC_DAPM_ADC("HiFi ADC", "HiFi Capture", REG, 2, 1),
 
+e.g. stream widgets for AIF
+
+SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
+
 
 2.2 Path Domain Widgets
 -----------------------
@@ -121,12 +136,14 @@
 you can use SND_SOC_DAPM_MIXER_NAMED_CTL instead. the parameters are the same
 as for SND_SOC_DAPM_MIXER.
 
-2.3 Platform/Machine domain Widgets
------------------------------------
+
+2.3 Machine domain Widgets
+--------------------------
 
 Machine widgets are different from codec widgets in that they don't have a
 codec register bit associated with them. A machine widget is assigned to each
-machine audio component (non codec) that can be independently powered. e.g.
+machine audio component (non codec or DSP) that can be independently
+powered. e.g.
 
  o Speaker Amp
  o Microphone Bias
@@ -146,12 +163,12 @@
 SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),
 
 
-2.4 Codec Domain
-----------------
+2.4 Codec (BIAS) Domain
+-----------------------
 
-The codec power domain has no widgets and is handled by the codecs DAPM event
-handler. This handler is called when the codec powerstate is changed wrt to any
-stream event or by kernel PM events.
+The codec bias power domain has no widgets and is handled by the codecs DAPM
+event handler. This handler is called when the codec powerstate is changed wrt
+to any stream event or by kernel PM events.
 
 
 2.5 Virtual Widgets
@@ -169,15 +186,16 @@
 subsystem individually with a call to snd_soc_dapm_new_control().
 
 
-3. Codec Widget Interconnections
-================================
+3. Codec/DSP Widget Interconnections
+====================================
 
-Widgets are connected to each other within the codec and machine by audio paths
-(called interconnections). Each interconnection must be defined in order to
-create a map of all audio paths between widgets.
+Widgets are connected to each other within the codec, platform and machine by
+audio paths (called interconnections). Each interconnection must be defined in
+order to create a map of all audio paths between widgets.
 
-This is easiest with a diagram of the codec (and schematic of the machine audio
-system), as it requires joining widgets together via their audio signal paths.
+This is easiest with a diagram of the codec or DSP (and schematic of the machine
+audio system), as it requires joining widgets together via their audio signal
+paths.
 
 e.g., from the WM8731 output mixer (wm8731.c)
 
@@ -247,16 +265,9 @@
  o Mic Jack
  o Codec Pins
 
-When a codec pin is NC it can be marked as not used with a call to
-
-snd_soc_dapm_set_endpoint(codec, "Widget Name", 0);
-
-The last argument is 0 for inactive and 1 for active. This way the pin and its
-input widget will never be powered up and consume power.
-
-This also applies to machine widgets. e.g. if a headphone is connected to a
-jack then the jack can be marked active. If the headphone is removed, then
-the headphone jack can be marked inactive.
+Endpoints are added to the DAPM graph so that their usage can be determined in
+order to save power. e.g. NC codecs pins will be switched OFF, unconnected
+jacks can also be switched OFF.
 
 
 5 DAPM Widget Events
diff --git a/Documentation/sound/alsa/soc/machine.txt b/Documentation/sound/alsa/soc/machine.txt
index d50c14d..74056db 100644
--- a/Documentation/sound/alsa/soc/machine.txt
+++ b/Documentation/sound/alsa/soc/machine.txt
@@ -1,8 +1,10 @@
 ASoC Machine Driver
 ===================
 
-The ASoC machine (or board) driver is the code that glues together the platform
-and codec drivers.
+The ASoC machine (or board) driver is the code that glues together all the
+component drivers (e.g. codecs, platforms and DAIs). It also describes the
+relationships between each componnent which include audio paths, GPIOs,
+interrupts, clocking, jacks and voltage regulators.
 
 The machine driver can contain codec and platform specific code. It registers
 the audio subsystem with the kernel as a platform device and is represented by
diff --git a/Documentation/sound/alsa/soc/platform.txt b/Documentation/sound/alsa/soc/platform.txt
index d57efad..3a08a2c 100644
--- a/Documentation/sound/alsa/soc/platform.txt
+++ b/Documentation/sound/alsa/soc/platform.txt
@@ -1,9 +1,9 @@
 ASoC Platform Driver
 ====================
 
-An ASoC platform driver can be divided into audio DMA and SoC DAI configuration
-and control. The platform drivers only target the SoC CPU and must have no board
-specific code.
+An ASoC platform driver class can be divided into audio DMA drivers, SoC DAI
+drivers and DSP drivers. The platform drivers only target the SoC CPU and must
+have no board specific code.
 
 Audio DMA
 =========
@@ -64,3 +64,16 @@
  5) Suspend and resume (optional)
 
 Please see codec.txt for a description of items 1 - 4.
+
+
+SoC DSP Drivers
+===============
+
+Each SoC DSP driver usually supplies the following features :-
+
+ 1) DAPM graph
+ 2) Mixer controls
+ 3) DMA IO to/from DSP buffers (if applicable)
+ 4) Definition of DSP front end (FE) PCM devices.
+
+Please see DPCM.txt for a description of item 4.
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 9d4c1d1..4273b2d 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -355,6 +355,82 @@
 
 ==============================================================
 
+numa_balancing
+
+Enables/disables automatic page fault based NUMA memory
+balancing. Memory is moved automatically to nodes
+that access it often.
+
+Enables/disables automatic NUMA memory balancing. On NUMA machines, there
+is a performance penalty if remote memory is accessed by a CPU. When this
+feature is enabled the kernel samples what task thread is accessing memory
+by periodically unmapping pages and later trapping a page fault. At the
+time of the page fault, it is determined if the data being accessed should
+be migrated to a local memory node.
+
+The unmapping of pages and trapping faults incur additional overhead that
+ideally is offset by improved memory locality but there is no universal
+guarantee. If the target workload is already bound to NUMA nodes then this
+feature should be disabled. Otherwise, if the system overhead from the
+feature is too high then the rate the kernel samples for NUMA hinting
+faults may be controlled by the numa_balancing_scan_period_min_ms,
+numa_balancing_scan_delay_ms, numa_balancing_scan_period_max_ms,
+numa_balancing_scan_size_mb, numa_balancing_settle_count sysctls and
+numa_balancing_migrate_deferred.
+
+==============================================================
+
+numa_balancing_scan_period_min_ms, numa_balancing_scan_delay_ms,
+numa_balancing_scan_period_max_ms, numa_balancing_scan_size_mb
+
+Automatic NUMA balancing scans tasks address space and unmaps pages to
+detect if pages are properly placed or if the data should be migrated to a
+memory node local to where the task is running.  Every "scan delay" the task
+scans the next "scan size" number of pages in its address space. When the
+end of the address space is reached the scanner restarts from the beginning.
+
+In combination, the "scan delay" and "scan size" determine the scan rate.
+When "scan delay" decreases, the scan rate increases.  The scan delay and
+hence the scan rate of every task is adaptive and depends on historical
+behaviour. If pages are properly placed then the scan delay increases,
+otherwise the scan delay decreases.  The "scan size" is not adaptive but
+the higher the "scan size", the higher the scan rate.
+
+Higher scan rates incur higher system overhead as page faults must be
+trapped and potentially data must be migrated. However, the higher the scan
+rate, the more quickly a tasks memory is migrated to a local node if the
+workload pattern changes and minimises performance impact due to remote
+memory accesses. These sysctls control the thresholds for scan delays and
+the number of pages scanned.
+
+numa_balancing_scan_period_min_ms is the minimum time in milliseconds to
+scan a tasks virtual memory. It effectively controls the maximum scanning
+rate for each task.
+
+numa_balancing_scan_delay_ms is the starting "scan delay" used for a task
+when it initially forks.
+
+numa_balancing_scan_period_max_ms is the maximum time in milliseconds to
+scan a tasks virtual memory. It effectively controls the minimum scanning
+rate for each task.
+
+numa_balancing_scan_size_mb is how many megabytes worth of pages are
+scanned for a given scan.
+
+numa_balancing_settle_count is how many scan periods must complete before
+the schedule balancer stops pushing the task towards a preferred node. This
+gives the scheduler a chance to place the task on an alternative node if the
+preferred node is overloaded.
+
+numa_balancing_migrate_deferred is how many page migrations get skipped
+unconditionally, after a page migration is skipped because a page is shared
+with other tasks. This reduces page migration overhead, and determines
+how much stronger the "move task near its memory" policy scheduler becomes,
+versus the "move memory near its task" memory management policy, for workloads
+with shared memory.
+
+==============================================================
+
 osrelease, ostype & version:
 
 # cat osrelease
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
index 8cb4d78..0e307c9 100644
--- a/Documentation/sysrq.txt
+++ b/Documentation/sysrq.txt
@@ -11,27 +11,29 @@
 You need to say "yes" to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when
 configuring the kernel. When running a kernel with SysRq compiled in,
 /proc/sys/kernel/sysrq controls the functions allowed to be invoked via
-the SysRq key. By default the file contains 1 which means that every
-possible SysRq request is allowed (in older versions SysRq was disabled
-by default, and you were required to specifically enable it at run-time
-but this is not the case any more). Here is the list of possible values
-in /proc/sys/kernel/sysrq:
+the SysRq key. The default value in this file is set by the
+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE config symbol, which itself defaults
+to 1. Here is the list of possible values in /proc/sys/kernel/sysrq:
    0 - disable sysrq completely
    1 - enable all functions of sysrq
   >1 - bitmask of allowed sysrq functions (see below for detailed function
        description):
-          2 - enable control of console logging level
-          4 - enable control of keyboard (SAK, unraw)
-          8 - enable debugging dumps of processes etc.
-         16 - enable sync command
-         32 - enable remount read-only
-         64 - enable signalling of processes (term, kill, oom-kill)
-        128 - allow reboot/poweroff
-        256 - allow nicing of all RT tasks
+          2 =   0x2 - enable control of console logging level
+          4 =   0x4 - enable control of keyboard (SAK, unraw)
+          8 =   0x8 - enable debugging dumps of processes etc.
+         16 =  0x10 - enable sync command
+         32 =  0x20 - enable remount read-only
+         64 =  0x40 - enable signalling of processes (term, kill, oom-kill)
+        128 =  0x80 - allow reboot/poweroff
+        256 = 0x100 - allow nicing of all RT tasks
 
 You can set the value in the file by the following command:
     echo "number" >/proc/sys/kernel/sysrq
 
+The number may be written here either as decimal or as hexadecimal
+with the 0x prefix. CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE must always be
+written in hexadecimal.
+
 Note that the value of /proc/sys/kernel/sysrq influences only the invocation
 via a keyboard. Invocation of any operation via /proc/sysrq-trigger is always
 allowed (by a user with admin privileges).
diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt
index ea2d35d..bd36598 100644
--- a/Documentation/trace/ftrace.txt
+++ b/Documentation/trace/ftrace.txt
@@ -655,7 +655,11 @@
 		  read the irq flags variable, an 'X' will always
 		  be printed here.
 
-  need-resched: 'N' task need_resched is set, '.' otherwise.
+  need-resched:
+	'N' both TIF_NEED_RESCHED and PREEMPT_NEED_RESCHED is set,
+	'n' only TIF_NEED_RESCHED is set,
+	'p' only PREEMPT_NEED_RESCHED is set,
+	'.' otherwise.
 
   hardirq/softirq:
 	'H' - hard irq occurred inside a softirq.
diff --git a/MAINTAINERS b/MAINTAINERS
index 8a0cbf3..051e4dc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -237,11 +237,11 @@
 
 ACPI
 M:	Len Brown <lenb@kernel.org>
-M:	Rafael J. Wysocki <rjw@sisk.pl>
+M:	Rafael J. Wysocki <rjw@rjwysocki.net>
 L:	linux-acpi@vger.kernel.org
-W:	http://www.lesswatts.org/projects/acpi/
-Q:	http://patchwork.kernel.org/project/linux-acpi/list/
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux
+W:	https://01.org/linux-acpi
+Q:	https://patchwork.kernel.org/project/linux-acpi/list/
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
 S:	Supported
 F:	drivers/acpi/
 F:	drivers/pnp/pnpacpi/
@@ -256,21 +256,21 @@
 ACPI FAN DRIVER
 M:	Zhang Rui <rui.zhang@intel.com>
 L:	linux-acpi@vger.kernel.org
-W:	http://www.lesswatts.org/projects/acpi/
+W:	https://01.org/linux-acpi
 S:	Supported
 F:	drivers/acpi/fan.c
 
 ACPI THERMAL DRIVER
 M:	Zhang Rui <rui.zhang@intel.com>
 L:	linux-acpi@vger.kernel.org
-W:	http://www.lesswatts.org/projects/acpi/
+W:	https://01.org/linux-acpi
 S:	Supported
 F:	drivers/acpi/*thermal*
 
 ACPI VIDEO DRIVER
 M:	Zhang Rui <rui.zhang@intel.com>
 L:	linux-acpi@vger.kernel.org
-W:	http://www.lesswatts.org/projects/acpi/
+W:	https://01.org/linux-acpi
 S:	Supported
 F:	drivers/acpi/video.c
 
@@ -763,6 +763,10 @@
 W:	http://www.linux4sam.org
 S:	Supported
 F:	arch/arm/mach-at91/
+F:	arch/arm/boot/dts/at91*.dts
+F:	arch/arm/boot/dts/at91*.dtsi
+F:	arch/arm/boot/dts/sama*.dts
+F:	arch/arm/boot/dts/sama*.dtsi
 
 ARM/CALXEDA HIGHBANK ARCHITECTURE
 M:	Rob Herring <rob.herring@calxeda.com>
@@ -929,7 +933,7 @@
 L:	linux-omap@vger.kernel.org
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
-F:	arch/arm/mach-omap2/board-igep0020.c
+F:	arch/arm/boot/dts/omap3-igep*
 
 ARM/INCOME PXA270 SUPPORT
 M:	Marek Vasut <marek.vasut@gmail.com>
@@ -1009,6 +1013,7 @@
 M:	Jason Cooper <jason@lakedaemon.net>
 M:	Andrew Lunn <andrew@lunn.ch>
 M:	Gregory Clement <gregory.clement@free-electrons.com>
+M:	Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	arch/arm/mach-mvebu/
@@ -1016,6 +1021,7 @@
 ARM/Marvell Dove/Kirkwood/MV78xx0/Orion SOC support
 M:	Jason Cooper <jason@lakedaemon.net>
 M:	Andrew Lunn <andrew@lunn.ch>
+M:	Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	arch/arm/mach-dove/
@@ -1148,10 +1154,12 @@
 F:	drivers/net/ethernet/seeq/ether3*
 F:	drivers/scsi/arm/
 
-ARM/SHARK MACHINE SUPPORT
-M:	Alexander Schulz <alex@shark-linux.de>
-W:	http://www.shark-linux.de/shark.html
+ARM/Rockchip SoC support
+M:	Heiko Stuebner <heiko@sntech.de>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
+F:	arch/arm/mach-rockchip/
+F:	drivers/*/*rockchip*
 
 ARM/SAMSUNG ARM ARCHITECTURES
 M:	Ben Dooks <ben-linux@fluff.org>
@@ -1160,6 +1168,8 @@
 L:	linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
 W:	http://www.fluff.org/ben/linux/
 S:	Maintained
+F:	arch/arm/boot/dts/s3c*
+F:	arch/arm/boot/dts/exynos*
 F:	arch/arm/plat-samsung/
 F:	arch/arm/mach-s3c24*/
 F:	arch/arm/mach-s3c64xx/
@@ -1791,6 +1801,7 @@
 
 BONDING DRIVER
 M:	Jay Vosburgh <fubar@us.ibm.com>
+M:	Veaceslav Falico <vfalico@redhat.com>
 M:	Andy Gospodarek <andy@greyhouse.net>
 L:	netdev@vger.kernel.org
 W:	http://sourceforge.net/projects/bonding/
@@ -2300,7 +2311,7 @@
 F:	drivers/net/ethernet/ti/cpmac.c
 
 CPU FREQUENCY DRIVERS
-M:	Rafael J. Wysocki <rjw@sisk.pl>
+M:	Rafael J. Wysocki <rjw@rjwysocki.net>
 M:	Viresh Kumar <viresh.kumar@linaro.org>
 L:	cpufreq@vger.kernel.org
 L:	linux-pm@vger.kernel.org
@@ -2331,7 +2342,7 @@
 F:      drivers/cpuidle/cpuidle-big_little.c
 
 CPUIDLE DRIVERS
-M:	Rafael J. Wysocki <rjw@sisk.pl>
+M:	Rafael J. Wysocki <rjw@rjwysocki.net>
 M:	Daniel Lezcano <daniel.lezcano@linaro.org>
 L:	linux-pm@vger.kernel.org
 S:	Maintained
@@ -2718,6 +2729,8 @@
 DMA GENERIC OFFLOAD ENGINE SUBSYSTEM
 M:	Vinod Koul <vinod.koul@intel.com>
 M:	Dan Williams <dan.j.williams@intel.com>
+L:	dmaengine@vger.kernel.org
+Q:	https://patchwork.kernel.org/project/linux-dmaengine/list/
 S:	Supported
 F:	drivers/dma/
 F:	include/linux/dma*
@@ -2821,7 +2834,7 @@
 L:	dri-devel@lists.freedesktop.org
 L:	linux-tegra@vger.kernel.org
 T:	git git://anongit.freedesktop.org/tegra/linux.git
-S:	Maintained
+S:	Supported
 F:	drivers/gpu/host1x/
 F:	include/uapi/drm/tegra_drm.h
 F:	Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
@@ -3553,7 +3566,7 @@
 
 FREEZER
 M:	Pavel Machek <pavel@ucw.cz>
-M:	"Rafael J. Wysocki" <rjw@sisk.pl>
+M:	"Rafael J. Wysocki" <rjw@rjwysocki.net>
 L:	linux-pm@vger.kernel.org
 S:	Supported
 F:	Documentation/power/freezing-of-tasks.txt
@@ -3624,6 +3637,12 @@
 S:	Odd Fixes (e.g., new signatures)
 F:	drivers/scsi/fdomain.*
 
+GCOV BASED KERNEL PROFILING
+M:	Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
+S:	Maintained
+F:	kernel/gcov/
+F:	Documentation/gcov.txt
+
 GDT SCSI DISK ARRAY CONTROLLER DRIVER
 M:	Achim Leubner <achim_leubner@adaptec.com>
 L:	linux-scsi@vger.kernel.org
@@ -3673,6 +3692,14 @@
 F:	include/asm-generic/
 F:	include/uapi/asm-generic/
 
+GENERIC PHY FRAMEWORK
+M:	Kishon Vijay Abraham I <kishon@ti.com>
+L:	linux-kernel@vger.kernel.org
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy.git
+S:	Supported
+F:	drivers/phy/
+F:	include/linux/phy/
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
@@ -3889,7 +3916,7 @@
 
 HIBERNATION (aka Software Suspend, aka swsusp)
 M:	Pavel Machek <pavel@ucw.cz>
-M:	"Rafael J. Wysocki" <rjw@sisk.pl>
+M:	"Rafael J. Wysocki" <rjw@rjwysocki.net>
 L:	linux-pm@vger.kernel.org
 S:	Supported
 F:	arch/x86/power/
@@ -4214,7 +4241,7 @@
 F:	drivers/media/rc/iguanair.c
 
 IIO SUBSYSTEM AND DRIVERS
-M:	Jonathan Cameron <jic23@cam.ac.uk>
+M:	Jonathan Cameron <jic23@kernel.org>
 L:	linux-iio@vger.kernel.org
 S:	Maintained
 F:	drivers/iio/
@@ -4339,7 +4366,7 @@
 INTEL MENLOW THERMAL DRIVER
 M:	Sujith Thomas <sujith.thomas@intel.com>
 L:	platform-driver-x86@vger.kernel.org
-W:	http://www.lesswatts.org/projects/acpi/
+W:	https://01.org/linux-acpi
 S:	Supported
 F:	drivers/platform/x86/intel_menlow.c
 
@@ -4351,7 +4378,10 @@
 
 INTEL I/OAT DMA DRIVER
 M:	Dan Williams <dan.j.williams@intel.com>
-S:	Maintained
+M:	Dave Jiang <dave.jiang@intel.com>
+L:	dmaengine@vger.kernel.org
+Q:	https://patchwork.kernel.org/project/linux-dmaengine/list/
+S:	Supported
 F:	drivers/dma/ioat*
 
 INTEL IOMMU (VT-d)
@@ -4410,6 +4440,12 @@
 F:	Documentation/networking/i40e.txt
 F:	drivers/net/ethernet/intel/
 
+INTEL-MID GPIO DRIVER
+M:	David Cohen <david.a.cohen@linux.intel.com>
+L:	linux-gpio@vger.kernel.org
+S:	Maintained
+F:	drivers/gpio/gpio-intel-mid.c
+
 INTEL PRO/WIRELESS 2100, 2200BG, 2915ABG NETWORK CONNECTION SUPPORT
 M:	Stanislav Yakovlev <stas.yakovlev@gmail.com>
 L:	linux-wireless@vger.kernel.org
@@ -4748,6 +4784,13 @@
 F:	Documentation/hwmon/k8temp
 F:	drivers/hwmon/k8temp.c
 
+KTAP
+M:	Jovi Zhangwei <jovi.zhangwei@gmail.com>
+W:	http://www.ktap.org
+L:	ktap@freelists.org
+S:	Maintained
+F:	drivers/staging/ktap/
+
 KCONFIG
 M:	Michal Marek <mmarek@suse.cz>
 L:	linux-kbuild@vger.kernel.org
@@ -6088,6 +6131,12 @@
 S:	Maintained
 F:	drivers/gpio/gpio-omap.c
 
+OMAP/NEWFLOW NANOBONE MACHINE SUPPORT
+M:	Mark Jackson <mpfj@newflow.co.uk>
+L:	linux-omap@vger.kernel.org
+S:	Maintained
+F:	arch/arm/boot/dts/am335x-nano.dts
+
 OMFS FILESYSTEM
 M:	Bob Copeland <me@bobcopeland.com>
 L:	linux-karma-devel@lists.sourceforge.net
@@ -6929,7 +6978,7 @@
 S:	Supported
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git
 F:	Documentation/RCU/torture.txt
-F:	kernel/rcutorture.c
+F:	kernel/rcu/torture.c
 
 RDC R-321X SoC
 M:	Florian Fainelli <florian@openwrt.org>
@@ -6956,8 +7005,9 @@
 F:	Documentation/RCU/
 X:	Documentation/RCU/torture.txt
 F:	include/linux/rcu*
-F:	kernel/rcu*
-X:	kernel/rcutorture.c
+X:	include/linux/srcu.h
+F:	kernel/rcu/
+X:	kernel/rcu/torture.c
 
 REAL TIME CLOCK (RTC) SUBSYSTEM
 M:	Alessandro Zummo <a.zummo@towertech.it>
@@ -7282,6 +7332,8 @@
 F:	kernel/sched/
 F:	include/linux/sched.h
 F:	include/uapi/linux/sched.h
+F:	kernel/wait.c
+F:	include/linux/wait.h
 
 SCORE ARCHITECTURE
 M:	Chen Liqin <liqin.linux@gmail.com>
@@ -7644,8 +7696,8 @@
 W:	http://www.rdrop.com/users/paulmck/RCU/
 S:	Supported
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git
-F:	include/linux/srcu*
-F:	kernel/srcu*
+F:	include/linux/srcu.h
+F:	kernel/rcu/srcu.c
 
 SMACK SECURITY MODULE
 M:	Casey Schaufler <casey@schaufler-ca.com>
@@ -7816,6 +7868,13 @@
 F:	sound/soc/
 F:	include/sound/soc*
 
+SOUND - DMAENGINE HELPERS
+M:	Lars-Peter Clausen <lars@metafoo.de>
+S:	Supported
+F:	include/sound/dmaengine_pcm.h
+F:	sound/core/pcm_dmaengine.c
+F:	sound/soc/soc-generic-dmaengine-pcm.c
+
 SPARC + UltraSPARC (sparc/sparc64)
 M:	"David S. Miller" <davem@davemloft.net>
 L:	sparclinux@vger.kernel.org
@@ -7973,7 +8032,7 @@
 F:	drivers/staging/media/go7007/
 
 STAGING - INDUSTRIAL IO
-M:	Jonathan Cameron <jic23@cam.ac.uk>
+M:	Jonathan Cameron <jic23@kernel.org>
 L:	linux-iio@vger.kernel.org
 S:	Odd Fixes
 F:	drivers/staging/iio/
@@ -8095,7 +8154,7 @@
 SUSPEND TO RAM
 M:	Len Brown <len.brown@intel.com>
 M:	Pavel Machek <pavel@ucw.cz>
-M:	"Rafael J. Wysocki" <rjw@sisk.pl>
+M:	"Rafael J. Wysocki" <rjw@rjwysocki.net>
 L:	linux-pm@vger.kernel.org
 S:	Supported
 F:	Documentation/power/
@@ -8288,14 +8347,72 @@
 S:	Maintained
 F:	drivers/media/rc/ttusbir.c
 
-TEGRA SUPPORT
+TEGRA ARCHITECTURE SUPPORT
 M:	Stephen Warren <swarren@wwwdotorg.org>
+M:	Thierry Reding <thierry.reding@gmail.com>
 L:	linux-tegra@vger.kernel.org
 Q:	http://patchwork.ozlabs.org/project/linux-tegra/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git
 S:	Supported
 N:	[^a-z]tegra
 
+TEGRA ASOC DRIVER
+M:	Stephen Warren <swarren@wwwdotorg.org>
+S:	Supported
+F:	sound/soc/tegra/
+
+TEGRA CLOCK DRIVER
+M:	Peter De Schrijver <pdeschrijver@nvidia.com>
+M:	Prashant Gaikwad <pgaikwad@nvidia.com>
+S:	Supported
+F:	drivers/clk/tegra/
+
+TEGRA DMA DRIVER
+M:	Laxman Dewangan <ldewangan@nvidia.com>
+S:	Supported
+F:	drivers/dma/tegra20-apb-dma.c
+
+TEGRA GPIO DRIVER
+M:	Stephen Warren <swarren@wwwdotorg.org>
+S:	Supported
+F:	drivers/gpio/gpio-tegra.c
+
+TEGRA I2C DRIVER
+M:	Laxman Dewangan <ldewangan@nvidia.com>
+S:	Supported
+F:	drivers/i2c/busses/i2c-tegra.c
+
+TEGRA IOMMU DRIVERS
+M:	Hiroshi Doyu <hdoyu@nvidia.com>
+S:	Supported
+F:	drivers/iommu/tegra*
+
+TEGRA KBC DRIVER
+M:	Rakesh Iyer <riyer@nvidia.com>
+M:	Laxman Dewangan <ldewangan@nvidia.com>
+S:	Supported
+F:	drivers/input/keyboard/tegra-kbc.c
+
+TEGRA PINCTRL DRIVER
+M:	Stephen Warren <swarren@wwwdotorg.org>
+S:	Supported
+F:	drivers/pinctrl/pinctrl-tegra*
+
+TEGRA PWM DRIVER
+M:	Thierry Reding <thierry.reding@gmail.com>
+S:	Supported
+F:	drivers/pwm/pwm-tegra.c
+
+TEGRA SERIAL DRIVER
+M:	Laxman Dewangan <ldewangan@nvidia.com>
+S:	Supported
+F:	drivers/tty/serial/serial-tegra.c
+
+TEGRA SPI DRIVER
+M:	Laxman Dewangan <ldewangan@nvidia.com>
+S:	Supported
+F:	drivers/spi/spi-tegra*
+
 TEHUTI ETHERNET DRIVER
 M:	Andy Gospodarek <andy@greyhouse.net>
 L:	netdev@vger.kernel.org
@@ -8596,14 +8713,6 @@
 F:	arch/m68k/*/*_no.*
 F:	arch/m68k/include/asm/*_no.*
 
-UCLINUX FOR RENESAS H8/300 (H8300)
-M:	Yoshinori Sato <ysato@users.sourceforge.jp>
-W:	http://uclinux-h8.sourceforge.jp/
-S:	Supported
-F:	arch/h8300/
-F:	drivers/ide/ide-h8300.c
-F:	drivers/net/ethernet/8390/ne-h8300.c
-
 UDF FILESYSTEM
 M:	Jan Kara <jack@suse.cz>
 S:	Maintained
@@ -8831,61 +8940,14 @@
 S:	Maintained
 F:	drivers/net/usb/rtl8150.c
 
-USB SERIAL BELKIN F5U103 DRIVER
-M:	William Greathouse <wgreathouse@smva.com>
+USB SERIAL SUBSYSTEM
+M:	Johan Hovold <jhovold@gmail.com>
 L:	linux-usb@vger.kernel.org
 S:	Maintained
-F:	drivers/usb/serial/belkin_sa.*
-
-USB SERIAL CYPRESS M8 DRIVER
-M:	Lonnie Mendez <dignome@gmail.com>
-L:	linux-usb@vger.kernel.org
-S:	Maintained
-W:	http://geocities.com/i0xox0i
-W:	http://firstlight.net/cvs
-F:	drivers/usb/serial/cypress_m8.*
-
-USB SERIAL CYBERJACK DRIVER
-M:	Matthias Bruestle and Harald Welte <support@reiner-sct.com>
-W:	http://www.reiner-sct.de/support/treiber_cyberjack.php
-S:	Maintained
-F:	drivers/usb/serial/cyberjack.c
-
-USB SERIAL DIGI ACCELEPORT DRIVER
-M:	Peter Berger <pberger@brimson.com>
-M:	Al Borchers <alborchers@steinerpoint.com>
-L:	linux-usb@vger.kernel.org
-S:	Maintained
-F:	drivers/usb/serial/digi_acceleport.c
-
-USB SERIAL DRIVER
-M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-L:	linux-usb@vger.kernel.org
-S:	Supported
 F:	Documentation/usb/usb-serial.txt
-F:	drivers/usb/serial/generic.c
-F:	drivers/usb/serial/usb-serial.c
+F:	drivers/usb/serial/
 F:	include/linux/usb/serial.h
 
-USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER
-M:	Gary Brubaker <xavyer@ix.netcom.com>
-L:	linux-usb@vger.kernel.org
-S:	Maintained
-F:	drivers/usb/serial/empeg.c
-
-USB SERIAL KEYSPAN DRIVER
-M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-L:	linux-usb@vger.kernel.org
-S:	Maintained
-F:	drivers/usb/serial/*keyspan*
-
-USB SERIAL WHITEHEAT DRIVER
-M:	Support Department <support@connecttech.com>
-L:	linux-usb@vger.kernel.org
-W:	http://www.connecttech.com
-S:	Supported
-F:	drivers/usb/serial/whiteheat*
-
 USB SMSC75XX ETHERNET DRIVER
 M:	Steve Glendinning <steve.glendinning@shawell.net>
 L:	netdev@vger.kernel.org
diff --git a/Makefile b/Makefile
index 9de9aba..67077ad 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 12
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION =
 NAME = One Giant Leap for Frogkind
 
 # *DOCUMENTATION*
diff --git a/arch/Kconfig b/arch/Kconfig
index af2cc6e..ded747c 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -353,6 +353,18 @@
 config HAVE_VIRT_CPU_ACCOUNTING
 	bool
 
+config HAVE_VIRT_CPU_ACCOUNTING_GEN
+	bool
+	default y if 64BIT
+	help
+	  With VIRT_CPU_ACCOUNTING_GEN, cputime_t becomes 64-bit.
+	  Before enabling this option, arch code must be audited
+	  to ensure there are no races in concurrent read/write of
+	  cputime_t. For example, reading/writing 64-bit cputime_t on
+	  some 32-bit arches may require multiple accesses, so proper
+	  locking is needed to protect against concurrent accesses.
+
+
 config HAVE_IRQ_TIME_ACCOUNTING
 	bool
 	help
@@ -390,6 +402,16 @@
 	  Some architectures generate an _ in front of C symbols; things like
 	  module loading and assembly files need to know about this.
 
+config HAVE_IRQ_EXIT_ON_IRQ_STACK
+	bool
+	help
+	  Architecture doesn't only execute the irq handler on the irq stack
+	  but also irq_exit(). This way we can process softirqs on this irq
+	  stack instead of switching to a new one when we call __do_softirq()
+	  in the end of an hardirq.
+	  This spares a stack switch and improves cache usage on softirq
+	  processing.
+
 #
 # ABI hall of shame
 #
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index a6e85f44..f01fb50 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -3,3 +3,4 @@
 
 generic-y += exec.h
 generic-y += trace_clock.h
+generic-y += preempt.h
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 91dbb27..5ede546 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -35,6 +35,12 @@
 	select PERF_USE_VMALLOC
 	select HAVE_DEBUG_STACKOVERFLOW
 
+config TRACE_IRQFLAGS_SUPPORT
+	def_bool y
+
+config LOCKDEP_SUPPORT
+	def_bool y
+
 config SCHED_OMIT_FRAME_POINTER
 	def_bool y
 
@@ -130,17 +136,14 @@
 config ARC_HAS_COH_CACHES
 	def_bool n
 
-config ARC_HAS_COH_RTSC
-	def_bool n
-
 config ARC_HAS_REENTRANT_IRQ_LV2
 	def_bool n
 
 endif
 
 config NR_CPUS
-	int "Maximum number of CPUs (2-32)"
-	range 2 32
+	int "Maximum number of CPUs (2-4096)"
+	range 2 4096
 	depends on SMP
 	default "2"
 
@@ -326,8 +329,7 @@
 	bool "Insn: RTSC (64-bit r/o cycle counter)"
 	default y
 	depends on ARC_CPU_REL_4_10
-	# if SMP, enable RTSC only if counter is coherent across cores
-	depends on !SMP || ARC_HAS_COH_RTSC
+	depends on !SMP
 
 endmenu   # "ARC CPU Configuration"
 
diff --git a/arch/arc/configs/fpga_defconfig b/arch/arc/configs/fpga_defconfig
index 4ca50f1..e283aa5 100644
--- a/arch/arc/configs/fpga_defconfig
+++ b/arch/arc/configs/fpga_defconfig
@@ -2,6 +2,8 @@
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
@@ -62,4 +64,5 @@
 CONFIG_NFS_FS=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_DEBUG_PREEMPT is not set
 CONFIG_XZ_DEC=y
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index d8dd660..5943f7f 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -46,3 +46,4 @@
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h
index e4abdaa..2fd3162 100644
--- a/arch/arc/include/asm/cache.h
+++ b/arch/arc/include/asm/cache.h
@@ -17,13 +17,7 @@
 #endif
 
 #define L1_CACHE_BYTES		(1 << L1_CACHE_SHIFT)
-
-/* For a rare case where customers have differently config I/D */
-#define ARC_ICACHE_LINE_LEN	L1_CACHE_BYTES
-#define ARC_DCACHE_LINE_LEN	L1_CACHE_BYTES
-
-#define ICACHE_LINE_MASK	(~(ARC_ICACHE_LINE_LEN - 1))
-#define DCACHE_LINE_MASK	(~(ARC_DCACHE_LINE_LEN - 1))
+#define CACHE_LINE_MASK		(~(L1_CACHE_BYTES - 1))
 
 /*
  * ARC700 doesn't cache any access in top 256M.
diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index c0a7210..291a70d 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -18,8 +18,8 @@
 
 #include <asm-generic/irq.h>
 
-extern void __init arc_init_IRQ(void);
-extern int __init get_hw_config_num_irq(void);
+extern void arc_init_IRQ(void);
+extern int get_hw_config_num_irq(void);
 
 void arc_local_timer_setup(unsigned int cpu);
 
diff --git a/arch/arc/include/asm/irqflags.h b/arch/arc/include/asm/irqflags.h
index b68b53f..cb7efc2 100644
--- a/arch/arc/include/asm/irqflags.h
+++ b/arch/arc/include/asm/irqflags.h
@@ -151,16 +151,38 @@
 
 #else
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+
+.macro TRACE_ASM_IRQ_DISABLE
+	bl	trace_hardirqs_off
+.endm
+
+.macro TRACE_ASM_IRQ_ENABLE
+	bl	trace_hardirqs_on
+.endm
+
+#else
+
+.macro TRACE_ASM_IRQ_DISABLE
+.endm
+
+.macro TRACE_ASM_IRQ_ENABLE
+.endm
+
+#endif
+
 .macro IRQ_DISABLE  scratch
 	lr	\scratch, [status32]
 	bic	\scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK)
 	flag	\scratch
+	TRACE_ASM_IRQ_DISABLE
 .endm
 
 .macro IRQ_ENABLE  scratch
 	lr	\scratch, [status32]
 	or	\scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK)
 	flag	\scratch
+	TRACE_ASM_IRQ_ENABLE
 .endm
 
 #endif	/* __ASSEMBLY__ */
diff --git a/arch/arc/include/asm/mach_desc.h b/arch/arc/include/asm/mach_desc.h
index 9998dc8..e8993a2 100644
--- a/arch/arc/include/asm/mach_desc.h
+++ b/arch/arc/include/asm/mach_desc.h
@@ -51,22 +51,12 @@
 /*
  * Current machine - only accessible during boot.
  */
-extern struct machine_desc *machine_desc;
+extern const struct machine_desc *machine_desc;
 
 /*
  * Machine type table - also only accessible during boot
  */
-extern struct machine_desc __arch_info_begin[], __arch_info_end[];
-#define for_each_machine_desc(p)			\
-	for (p = __arch_info_begin; p < __arch_info_end; p++)
-
-static inline struct machine_desc *default_machine_desc(void)
-{
-	/* the default machine is the last one linked in */
-	if (__arch_info_end - 1 < __arch_info_begin)
-		return NULL;
-	return __arch_info_end - 1;
-}
+extern const struct machine_desc __arch_info_begin[], __arch_info_end[];
 
 /*
  * Set of macros to define architecture features.
@@ -81,7 +71,6 @@
 #define MACHINE_END				\
 };
 
-extern struct machine_desc *setup_machine_fdt(void *dt);
-extern void __init copy_devtree(void);
+extern const struct machine_desc *setup_machine_fdt(void *dt);
 
 #endif
diff --git a/arch/arc/include/asm/mmu.h b/arch/arc/include/asm/mmu.h
index c2663b3..8c84ae9 100644
--- a/arch/arc/include/asm/mmu.h
+++ b/arch/arc/include/asm/mmu.h
@@ -48,7 +48,7 @@
 #ifndef __ASSEMBLY__
 
 typedef struct {
-	unsigned long asid;	/* 8 bit MMU PID + Generation cycle */
+	unsigned long asid[NR_CPUS];	/* 8 bit MMU PID + Generation cycle */
 } mm_context_t;
 
 #ifdef CONFIG_ARC_DBG_TLB_PARANOIA
diff --git a/arch/arc/include/asm/mmu_context.h b/arch/arc/include/asm/mmu_context.h
index 43a1b51..1fd467e 100644
--- a/arch/arc/include/asm/mmu_context.h
+++ b/arch/arc/include/asm/mmu_context.h
@@ -30,13 +30,13 @@
  * "Fast Context Switch" i.e. no TLB flush on ctxt-switch
  *
  * Linux assigns each task a unique ASID. A simple round-robin allocation
- * of H/w ASID is done using software tracker @asid_cache.
+ * of H/w ASID is done using software tracker @asid_cpu.
  * When it reaches max 255, the allocation cycle starts afresh by flushing
  * the entire TLB and wrapping ASID back to zero.
  *
  * A new allocation cycle, post rollover, could potentially reassign an ASID
  * to a different task. Thus the rule is to refresh the ASID in a new cycle.
- * The 32 bit @asid_cache (and mm->asid) have 8 bits MMU PID and rest 24 bits
+ * The 32 bit @asid_cpu (and mm->asid) have 8 bits MMU PID and rest 24 bits
  * serve as cycle/generation indicator and natural 32 bit unsigned math
  * automagically increments the generation when lower 8 bits rollover.
  */
@@ -47,9 +47,11 @@
 #define MM_CTXT_FIRST_CYCLE	(MM_CTXT_ASID_MASK + 1)
 #define MM_CTXT_NO_ASID		0UL
 
-#define hw_pid(mm)		(mm->context.asid & MM_CTXT_ASID_MASK)
+#define asid_mm(mm, cpu)	mm->context.asid[cpu]
+#define hw_pid(mm, cpu)		(asid_mm(mm, cpu) & MM_CTXT_ASID_MASK)
 
-extern unsigned int asid_cache;
+DECLARE_PER_CPU(unsigned int, asid_cache);
+#define asid_cpu(cpu)		per_cpu(asid_cache, cpu)
 
 /*
  * Get a new ASID if task doesn't have a valid one (unalloc or from prev cycle)
@@ -57,6 +59,7 @@
  */
 static inline void get_new_mmu_context(struct mm_struct *mm)
 {
+	const unsigned int cpu = smp_processor_id();
 	unsigned long flags;
 
 	local_irq_save(flags);
@@ -71,28 +74,28 @@
 	 * 	 first need to destroy the context, setting it to invalid
 	 * 	 value.
 	 */
-	if (!((mm->context.asid ^ asid_cache) & MM_CTXT_CYCLE_MASK))
+	if (!((asid_mm(mm, cpu) ^ asid_cpu(cpu)) & MM_CTXT_CYCLE_MASK))
 		goto set_hw;
 
 	/* move to new ASID and handle rollover */
-	if (unlikely(!(++asid_cache & MM_CTXT_ASID_MASK))) {
+	if (unlikely(!(++asid_cpu(cpu) & MM_CTXT_ASID_MASK))) {
 
-		flush_tlb_all();
+		local_flush_tlb_all();
 
 		/*
 		 * Above checke for rollover of 8 bit ASID in 32 bit container.
 		 * If the container itself wrapped around, set it to a non zero
 		 * "generation" to distinguish from no context
 		 */
-		if (!asid_cache)
-			asid_cache = MM_CTXT_FIRST_CYCLE;
+		if (!asid_cpu(cpu))
+			asid_cpu(cpu) = MM_CTXT_FIRST_CYCLE;
 	}
 
 	/* Assign new ASID to tsk */
-	mm->context.asid = asid_cache;
+	asid_mm(mm, cpu) = asid_cpu(cpu);
 
 set_hw:
-	write_aux_reg(ARC_REG_PID, hw_pid(mm) | MMU_ENABLE);
+	write_aux_reg(ARC_REG_PID, hw_pid(mm, cpu) | MMU_ENABLE);
 
 	local_irq_restore(flags);
 }
@@ -104,16 +107,45 @@
 static inline int
 init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
-	mm->context.asid = MM_CTXT_NO_ASID;
+	int i;
+
+	for_each_possible_cpu(i)
+		asid_mm(mm, i) = MM_CTXT_NO_ASID;
+
 	return 0;
 }
 
+static inline void destroy_context(struct mm_struct *mm)
+{
+	unsigned long flags;
+
+	/* Needed to elide CONFIG_DEBUG_PREEMPT warning */
+	local_irq_save(flags);
+	asid_mm(mm, smp_processor_id()) = MM_CTXT_NO_ASID;
+	local_irq_restore(flags);
+}
+
 /* Prepare the MMU for task: setup PID reg with allocated ASID
     If task doesn't have an ASID (never alloc or stolen, get a new ASID)
 */
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 			     struct task_struct *tsk)
 {
+	const int cpu = smp_processor_id();
+
+	/*
+	 * Note that the mm_cpumask is "aggregating" only, we don't clear it
+	 * for the switched-out task, unlike some other arches.
+	 * It is used to enlist cpus for sending TLB flush IPIs and not sending
+	 * it to CPUs where a task once ran-on, could cause stale TLB entry
+	 * re-use, specially for a multi-threaded task.
+	 * e.g. T1 runs on C1, migrates to C3. T2 running on C2 munmaps.
+	 *      For a non-aggregating mm_cpumask, IPI not sent C1, and if T1
+	 *      were to re-migrate to C1, it could access the unmapped region
+	 *      via any existing stale TLB entries.
+	 */
+	cpumask_set_cpu(cpu, mm_cpumask(next));
+
 #ifndef CONFIG_SMP
 	/* PGD cached in MMU reg to avoid 3 mem lookups: task->mm->pgd */
 	write_aux_reg(ARC_REG_SCRATCH_DATA0, next->pgd);
@@ -131,11 +163,6 @@
  */
 #define activate_mm(prev, next)		switch_mm(prev, next, NULL)
 
-static inline void destroy_context(struct mm_struct *mm)
-{
-	mm->context.asid = MM_CTXT_NO_ASID;
-}
-
 /* it seemed that deactivate_mm( ) is a reasonable place to do book-keeping
  * for retiring-mm. However destroy_context( ) still needs to do that because
  * between mm_release( ) = >deactive_mm( ) and
diff --git a/arch/arc/include/asm/prom.h b/arch/arc/include/asm/prom.h
deleted file mode 100644
index 692d0d0..0000000
--- a/arch/arc/include/asm/prom.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _ASM_ARC_PROM_H_
-#define _ASM_ARC_PROM_H_
-
-#define HAVE_ARCH_DEVTREE_FIXUPS
-
-#endif
diff --git a/arch/arc/include/asm/setup.h b/arch/arc/include/asm/setup.h
index 229e506..e10f8ce 100644
--- a/arch/arc/include/asm/setup.h
+++ b/arch/arc/include/asm/setup.h
@@ -31,7 +31,7 @@
 extern int root_mountflags, end_mem;
 extern int running_on_hw;
 
-void __init setup_processor(void);
+void setup_processor(void);
 void __init setup_arch_memory(void);
 
 #endif /* __ASMARC_SETUP_H */
diff --git a/arch/arc/include/asm/smp.h b/arch/arc/include/asm/smp.h
index c4fb211..eefc29f 100644
--- a/arch/arc/include/asm/smp.h
+++ b/arch/arc/include/asm/smp.h
@@ -30,7 +30,7 @@
  * APIs provided by arch SMP code to rest of arch code
  */
 extern void __init smp_init_cpus(void);
-extern void __init first_lines_of_secondary(void);
+extern void first_lines_of_secondary(void);
 extern const char *arc_platform_smp_cpuinfo(void);
 
 /*
diff --git a/arch/arc/include/asm/tlbflush.h b/arch/arc/include/asm/tlbflush.h
index b2f9bc7..71c7b2e 100644
--- a/arch/arc/include/asm/tlbflush.h
+++ b/arch/arc/include/asm/tlbflush.h
@@ -18,11 +18,18 @@
 void local_flush_tlb_range(struct vm_area_struct *vma,
 			   unsigned long start, unsigned long end);
 
-/* XXX: Revisit for SMP */
+#ifndef CONFIG_SMP
 #define flush_tlb_range(vma, s, e)	local_flush_tlb_range(vma, s, e)
 #define flush_tlb_page(vma, page)	local_flush_tlb_page(vma, page)
 #define flush_tlb_kernel_range(s, e)	local_flush_tlb_kernel_range(s, e)
 #define flush_tlb_all()			local_flush_tlb_all()
 #define flush_tlb_mm(mm)		local_flush_tlb_mm(mm)
-
+#else
+extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+							 unsigned long end);
+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
+extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+extern void flush_tlb_all(void);
+extern void flush_tlb_mm(struct mm_struct *mm);
+#endif /* CONFIG_SMP */
 #endif
diff --git a/arch/arc/include/asm/unaligned.h b/arch/arc/include/asm/unaligned.h
index 60702f3..3e5f071 100644
--- a/arch/arc/include/asm/unaligned.h
+++ b/arch/arc/include/asm/unaligned.h
@@ -22,7 +22,8 @@
 misaligned_fixup(unsigned long address, struct pt_regs *regs,
 		 struct callee_regs *cregs)
 {
-	return 0;
+	/* Not fixed */
+	return 1;
 }
 #endif
 
diff --git a/arch/arc/kernel/ctx_sw.c b/arch/arc/kernel/ctx_sw.c
index 34410eb..c14a5be 100644
--- a/arch/arc/kernel/ctx_sw.c
+++ b/arch/arc/kernel/ctx_sw.c
@@ -17,6 +17,8 @@
 #include <asm/asm-offsets.h>
 #include <linux/sched.h>
 
+#define KSP_WORD_OFF 	((TASK_THREAD + THREAD_KSP) / 4)
+
 struct task_struct *__sched
 __switch_to(struct task_struct *prev_task, struct task_struct *next_task)
 {
@@ -45,7 +47,16 @@
 #endif
 
 		/* set ksp of outgoing task in tsk->thread.ksp */
+#if KSP_WORD_OFF <= 255
 		"st.as   sp, [%3, %1]    \n\t"
+#else
+		/*
+		 * Workaround for NR_CPUS=4k
+		 * %1 is bigger than 255 (S9 offset for st.as)
+		 */
+		"add2    r24, %3, %1     \n\t"
+		"st      sp, [r24]       \n\t"
+#endif
 
 		"sync   \n\t"
 
@@ -97,7 +108,7 @@
 		/* FP/BLINK restore generated by gcc (standard func epilogue */
 
 		: "=r"(tmp)
-		: "n"((TASK_THREAD + THREAD_KSP) / 4), "r"(next), "r"(prev)
+		: "n"(KSP_WORD_OFF), "r"(next), "r"(prev)
 		: "blink"
 	);
 
diff --git a/arch/arc/kernel/ctx_sw_asm.S b/arch/arc/kernel/ctx_sw_asm.S
index d897234..65690e7 100644
--- a/arch/arc/kernel/ctx_sw_asm.S
+++ b/arch/arc/kernel/ctx_sw_asm.S
@@ -14,6 +14,8 @@
 #include <asm/asm-offsets.h>
 #include <asm/linkage.h>
 
+#define KSP_WORD_OFF 	((TASK_THREAD + THREAD_KSP) / 4)
+
 ;################### Low Level Context Switch ##########################
 
 	.section .sched.text,"ax",@progbits
@@ -28,8 +30,13 @@
 	SAVE_CALLEE_SAVED_KERNEL
 
 	/* Save the now KSP in task->thread.ksp */
-	st.as  sp, [r0, (TASK_THREAD + THREAD_KSP)/4]
-
+#if KSP_WORD_OFF  <= 255
+	st.as  sp, [r0, KSP_WORD_OFF]
+#else
+	/* Workaround for NR_CPUS=4k as ST.as can only take s9 offset */
+	add2	r24, r0, KSP_WORD_OFF
+	st	sp, [r24]
+#endif
 	/*
 	* Return last task in r0 (return reg)
 	* On ARC, Return reg = First Arg reg = r0.
diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c
index 2340af0..b6dc4e2 100644
--- a/arch/arc/kernel/devtree.c
+++ b/arch/arc/kernel/devtree.c
@@ -14,10 +14,22 @@
 #include <linux/memblock.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
-#include <asm/prom.h>
 #include <asm/clk.h>
 #include <asm/mach_desc.h>
 
+static const void * __init arch_get_next_mach(const char *const **match)
+{
+	static const struct machine_desc *mdesc = __arch_info_begin;
+	const struct machine_desc *m = mdesc;
+
+	if (m >= __arch_info_end)
+		return NULL;
+
+	mdesc++;
+	*match = m->dt_compat;
+	return m;
+}
+
 /**
  * setup_machine_fdt - Machine setup when an dtb was passed to the kernel
  * @dt:		virtual address pointer to dt blob
@@ -25,93 +37,24 @@
  * If a dtb was passed to the kernel, then use it to choose the correct
  * machine_desc and to setup the system.
  */
-struct machine_desc * __init setup_machine_fdt(void *dt)
+const struct machine_desc * __init setup_machine_fdt(void *dt)
 {
-	struct boot_param_header *devtree = dt;
-	struct machine_desc *mdesc = NULL, *mdesc_best = NULL;
-	unsigned int score, mdesc_score = ~1;
+	const struct machine_desc *mdesc;
 	unsigned long dt_root;
-	const char *model, *compat;
 	void *clk;
-	char manufacturer[16];
 	unsigned long len;
 
-	/* check device tree validity */
-	if (be32_to_cpu(devtree->magic) != OF_DT_HEADER)
+	if (!early_init_dt_scan(dt))
 		return NULL;
 
-	initial_boot_params = devtree;
-	dt_root = of_get_flat_dt_root();
-
-	/*
-	 * The kernel could be multi-platform enabled, thus could have many
-	 * "baked-in" machine descriptors. Search thru all for the best
-	 * "compatible" string match.
-	 */
-	for_each_machine_desc(mdesc) {
-		score = of_flat_dt_match(dt_root, mdesc->dt_compat);
-		if (score > 0 && score < mdesc_score) {
-			mdesc_best = mdesc;
-			mdesc_score = score;
-		}
-	}
-	if (!mdesc_best) {
-		const char *prop;
-		long size;
-
-		pr_err("\n unrecognized device tree list:\n[ ");
-
-		prop = of_get_flat_dt_prop(dt_root, "compatible", &size);
-		if (prop) {
-			while (size > 0) {
-				printk("'%s' ", prop);
-				size -= strlen(prop) + 1;
-				prop += strlen(prop) + 1;
-			}
-		}
-		printk("]\n\n");
-
+	mdesc = of_flat_dt_match_machine(NULL, arch_get_next_mach);
+	if (!mdesc)
 		machine_halt();
-	}
 
-	/* compat = "<manufacturer>,<model>" */
-	compat =  mdesc_best->dt_compat[0];
-
-	model = strchr(compat, ',');
-	if (model)
-		model++;
-
-	strlcpy(manufacturer, compat, model ? model - compat : strlen(compat));
-
-	pr_info("Board \"%s\" from %s (Manufacturer)\n", model, manufacturer);
-
-	/* Retrieve various information from the /chosen node */
-	of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
-
-	/* Initialize {size,address}-cells info */
-	of_scan_flat_dt(early_init_dt_scan_root, NULL);
-
-	/* Setup memory, calling early_init_dt_add_memory_arch */
-	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
-
+	dt_root = of_get_flat_dt_root();
 	clk = of_get_flat_dt_prop(dt_root, "clock-frequency", &len);
 	if (clk)
 		arc_set_core_freq(of_read_ulong(clk, len/4));
 
-	return mdesc_best;
-}
-
-/*
- * Copy the flattened DT out of .init since unflattening doesn't copy strings
- * and the normal DT APIs refs them from orig flat DT
- */
-void __init copy_devtree(void)
-{
-	void *alloc = early_init_dt_alloc_memory_arch(
-			be32_to_cpu(initial_boot_params->totalsize), 64);
-	if (alloc) {
-		memcpy(alloc, initial_boot_params,
-				be32_to_cpu(initial_boot_params->totalsize));
-		initial_boot_params = alloc;
-	}
+	return mdesc;
 }
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index b908dde..47d09d0 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -250,6 +250,14 @@
 	lr  r0, [icause1]
 	and r0, r0, 0x1f
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+	; icause1 needs to be read early, before calling tracing, which
+	; can clobber scratch regs, hence use of stack to stash it
+	push r0
+	TRACE_ASM_IRQ_DISABLE
+	pop  r0
+#endif
+
 	bl.d  @arch_do_IRQ
 	mov r1, sp
 
@@ -337,9 +345,9 @@
 	;  vineetg: Mar 6th: Random Seg Fault issue #1
 	;  ecr and efa were not saved in case an Intr sneaks in
 	;  after fake rtie
-	;
+
 	lr  r2, [ecr]
-	lr  r1, [efa]	; Faulting Data address
+	lr  r0, [efa]	; Faulting Data address
 
 	; --------(4) Return from CPU Exception Mode ---------
 	;  Fake a rtie, but rtie to next label
@@ -348,6 +356,8 @@
 
 	FAKE_RET_FROM_EXCPN r9
 
+	mov   r1, sp
+
 	;------ (5) Type of Protection Violation? ----------
 	;
 	; ProtV Hardware Exception is triggered for Access Faults of 2 types
@@ -358,16 +368,12 @@
 	bbit1 r2, ECR_C_BIT_PROTV_MISALIG_DATA, 4f
 
 	;========= (6a) Access Violation Processing ========
-	mov r0, sp              ; pt_regs
 	bl  do_page_fault
 	b   ret_from_exception
 
 	;========== (6b) Non aligned access ============
 4:
-	mov r0, r1
-	mov r1, sp              ; pt_regs
 
-#ifdef  CONFIG_ARC_MISALIGN_ACCESS
 	SAVE_CALLEE_SAVED_USER
 	mov r2, sp              ; callee_regs
 
@@ -376,9 +382,6 @@
 	; TBD: optimize - do this only if a callee reg was involved
 	; either a dst of emulated LD/ST or src with address-writeback
 	RESTORE_CALLEE_SAVED_USER
-#else
-	bl  do_misaligned_error
-#endif
 
 	b   ret_from_exception
 
@@ -575,6 +578,7 @@
 	; --- (Slow Path #2) pending signal  ---
 	mov r0, sp	; pt_regs for arg to do_signal()/do_notify_resume()
 
+	GET_CURR_THR_INFO_FLAGS   r9
 	bbit0  r9, TIF_SIGPENDING, .Lchk_notify_resume
 
 	; Normal Trap/IRQ entry only saves Scratch (caller-saved) regs
@@ -640,6 +644,8 @@
 
 restore_regs :
 
+	TRACE_ASM_IRQ_ENABLE
+
 	lr	r10, [status32]
 
 	; Restore REG File. In case multiple Events outstanding,
diff --git a/arch/arc/kernel/head.S b/arch/arc/kernel/head.S
index 0f944f0..2c878e9 100644
--- a/arch/arc/kernel/head.S
+++ b/arch/arc/kernel/head.S
@@ -95,7 +95,7 @@
 ;----------------------------------------------------------------
 ;     First lines of code run by secondary before jumping to 'C'
 ;----------------------------------------------------------------
-	.section .init.text, "ax",@progbits
+	.section .text, "ax",@progbits
 	.type first_lines_of_secondary, @function
 	.globl first_lines_of_secondary
 
diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
index 5fc9245..a4b141e 100644
--- a/arch/arc/kernel/irq.c
+++ b/arch/arc/kernel/irq.c
@@ -39,10 +39,14 @@
 	level_mask |= IS_ENABLED(CONFIG_ARC_IRQ5_LV2) << 5;
 	level_mask |= IS_ENABLED(CONFIG_ARC_IRQ6_LV2) << 6;
 
-	if (level_mask) {
+	/*
+	 * Write to register, even if no LV2 IRQs configured to reset it
+	 * in case bootloader had mucked with it
+	 */
+	write_aux_reg(AUX_IRQ_LEV, level_mask);
+
+	if (level_mask)
 		pr_info("Level-2 interrupts bitset %x\n", level_mask);
-		write_aux_reg(AUX_IRQ_LEV, level_mask);
-	}
 }
 
 /*
@@ -146,7 +150,7 @@
 	set_irq_regs(old_regs);
 }
 
-int __init get_hw_config_num_irq(void)
+int get_hw_config_num_irq(void)
 {
 	uint32_t val = read_aux_reg(ARC_REG_VECBASE_BCR);
 
diff --git a/arch/arc/kernel/kgdb.c b/arch/arc/kernel/kgdb.c
index a7698fb..a2ff5c5 100644
--- a/arch/arc/kernel/kgdb.c
+++ b/arch/arc/kernel/kgdb.c
@@ -196,6 +196,18 @@
 	instruction_pointer(regs) = ip;
 }
 
+static void kgdb_call_nmi_hook(void *ignored)
+{
+	kgdb_nmicallback(raw_smp_processor_id(), NULL);
+}
+
+void kgdb_roundup_cpus(unsigned long flags)
+{
+	local_irq_enable();
+	smp_call_function(kgdb_call_nmi_hook, NULL, 0);
+	local_irq_disable();
+}
+
 struct kgdb_arch arch_kgdb_ops = {
 	/* breakpoint instruction: TRAP_S 0x3 */
 #ifdef CONFIG_CPU_BIG_ENDIAN
diff --git a/arch/arc/kernel/kprobes.c b/arch/arc/kernel/kprobes.c
index 72f97822..eb1c2ee 100644
--- a/arch/arc/kernel/kprobes.c
+++ b/arch/arc/kernel/kprobes.c
@@ -87,13 +87,13 @@
 
 static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
-	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
+	__this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
 	kcb->kprobe_status = kcb->prev_kprobe.status;
 }
 
 static inline void __kprobes set_current_kprobe(struct kprobe *p)
 {
-	__get_cpu_var(current_kprobe) = p;
+	__this_cpu_write(current_kprobe, p);
 }
 
 static void __kprobes resume_execution(struct kprobe *p, unsigned long addr,
@@ -237,7 +237,7 @@
 
 		return 1;
 	} else if (kprobe_running()) {
-		p = __get_cpu_var(current_kprobe);
+		p = __this_cpu_read(current_kprobe);
 		if (p->break_handler && p->break_handler(p, regs)) {
 			setup_singlestep(p, regs);
 			kcb->kprobe_status = KPROBE_HIT_SS;
diff --git a/arch/arc/kernel/ptrace.c b/arch/arc/kernel/ptrace.c
index 3332385..5d76706 100644
--- a/arch/arc/kernel/ptrace.c
+++ b/arch/arc/kernel/ptrace.c
@@ -102,7 +102,7 @@
 	REG_IGNORE_ONE(pad2);
 	REG_IN_CHUNK(callee, efa, cregs);	/* callee_regs[r25..r13] */
 	REG_IGNORE_ONE(efa);			/* efa update invalid */
-	REG_IN_ONE(stop_pc, &ptregs->ret);	/* stop_pc: PC update */
+	REG_IGNORE_ONE(stop_pc);			/* PC updated via @ret */
 
 	return ret;
 }
diff --git a/arch/arc/kernel/reset.c b/arch/arc/kernel/reset.c
index e227a2b..2768fa1 100644
--- a/arch/arc/kernel/reset.c
+++ b/arch/arc/kernel/reset.c
@@ -31,3 +31,4 @@
 }
 
 void (*pm_power_off) (void) = NULL;
+EXPORT_SYMBOL(pm_power_off);
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index 2c68bc7e..643eae4 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -21,7 +21,6 @@
 #include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/irq.h>
-#include <asm/prom.h>
 #include <asm/unwind.h>
 #include <asm/clk.h>
 #include <asm/mach_desc.h>
@@ -31,14 +30,13 @@
 int running_on_hw = 1;	/* vs. on ISS */
 
 char __initdata command_line[COMMAND_LINE_SIZE];
-struct machine_desc *machine_desc;
+const struct machine_desc *machine_desc;
 
 struct task_struct *_current_task[NR_CPUS];	/* For stack switching */
 
 struct cpuinfo_arc cpuinfo_arc700[NR_CPUS];
 
-
-void read_arc_build_cfg_regs(void)
+static void read_arc_build_cfg_regs(void)
 {
 	struct bcr_perip uncached_space;
 	struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
@@ -106,7 +104,7 @@
 	{ {0x00, NULL		} }
 };
 
-char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
+static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
 {
 	int n = 0;
 	struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id];
@@ -171,7 +169,7 @@
 	{0x6, "Dual 16x16 and 32x16"}
 };
 
-char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
+static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
 {
 	int n = 0;
 	struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id];
@@ -234,7 +232,7 @@
 	return buf;
 }
 
-void arc_chk_ccms(void)
+static void arc_chk_ccms(void)
 {
 #if defined(CONFIG_ARC_HAS_DCCM) || defined(CONFIG_ARC_HAS_ICCM)
 	struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
@@ -269,7 +267,7 @@
  * hardware has dedicated regs which need to be saved/restored on ctx-sw
  * (Single Precision uses core regs), thus kernel is kind of oblivious to it
  */
-void arc_chk_fpu(void)
+static void arc_chk_fpu(void)
 {
 	struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
 
@@ -346,8 +344,7 @@
 	setup_arch_memory();
 
 	/* copy flat DT out of .init and then unflatten it */
-	copy_devtree();
-	unflatten_device_tree();
+	unflatten_and_copy_device_tree();
 
 	/* Can be issue if someone passes cmd line arg "ro"
 	 * But that is unlikely so keeping it as it is
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index bca3052..c2f9ebb 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -95,7 +95,7 @@
  *        If it turns out to be elaborate, it's better to code it in assembly
  *
  */
-void __attribute__((weak)) arc_platform_smp_wait_to_boot(int cpu)
+void __weak arc_platform_smp_wait_to_boot(int cpu)
 {
 	/*
 	 * As a hack for debugging - since debugger will single-step over the
@@ -128,6 +128,7 @@
 	atomic_inc(&mm->mm_users);
 	atomic_inc(&mm->mm_count);
 	current->active_mm = mm;
+	cpumask_set_cpu(cpu, mm_cpumask(mm));
 
 	notify_cpu_starting(cpu);
 	set_cpu_online(cpu, true);
@@ -210,7 +211,6 @@
 	IPI_NOP = 0,
 	IPI_RESCHEDULE = 1,
 	IPI_CALL_FUNC,
-	IPI_CALL_FUNC_SINGLE,
 	IPI_CPU_STOP
 };
 
@@ -254,7 +254,7 @@
 
 void arch_send_call_function_single_ipi(int cpu)
 {
-	ipi_send_msg(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+	ipi_send_msg(cpumask_of(cpu), IPI_CALL_FUNC);
 }
 
 void arch_send_call_function_ipi_mask(const struct cpumask *mask)
@@ -286,10 +286,6 @@
 			generic_smp_call_function_interrupt();
 			break;
 
-		case IPI_CALL_FUNC_SINGLE:
-			generic_smp_call_function_single_interrupt();
-			break;
-
 		case IPI_CPU_STOP:
 			ipi_cpu_stop(cpu);
 			break;
diff --git a/arch/arc/kernel/stacktrace.c b/arch/arc/kernel/stacktrace.c
index f8b7d88..9ce47cf 100644
--- a/arch/arc/kernel/stacktrace.c
+++ b/arch/arc/kernel/stacktrace.c
@@ -237,11 +237,14 @@
  */
 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 {
+	/* Assumes @tsk is sleeping so unwinds from __switch_to */
 	arc_unwind_core(tsk, NULL, __collect_all_but_sched, trace);
 }
 
 void save_stack_trace(struct stack_trace *trace)
 {
-	arc_unwind_core(current, NULL, __collect_all, trace);
+	/* Pass NULL for task so it unwinds the current call frame */
+	arc_unwind_core(NULL, NULL, __collect_all, trace);
 }
+EXPORT_SYMBOL_GPL(save_stack_trace);
 #endif
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index 3fde7de..e5f3a83 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -63,9 +63,10 @@
 
 int arc_counter_setup(void)
 {
-	/* RTSC insn taps into cpu clk, needs no setup */
-
-	/* For SMP, only allowed if cross-core-sync, hence usable as cs */
+	/*
+	 * For SMP this needs to be 0. However Kconfig glue doesn't
+	 * enable this option for SMP configs
+	 */
 	return 1;
 }
 
@@ -206,7 +207,7 @@
 
 static irqreturn_t timer_irq_handler(int irq, void *dev_id)
 {
-	struct clock_event_device *clk = &__get_cpu_var(arc_clockevent_device);
+	struct clock_event_device *clk = this_cpu_ptr(&arc_clockevent_device);
 
 	arc_timer_event_ack(clk->mode == CLOCK_EVT_MODE_PERIODIC);
 	clk->event_handler(clk);
@@ -223,7 +224,7 @@
  * Setup the local event timer for @cpu
  * N.B. weak so that some exotic ARC SoCs can completely override it
  */
-void __attribute__((weak)) arc_local_timer_setup(unsigned int cpu)
+void __weak arc_local_timer_setup(unsigned int cpu)
 {
 	struct clock_event_device *clk = &per_cpu(arc_clockevent_device, cpu);
 
diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c
index e21692d..3eadfda 100644
--- a/arch/arc/kernel/traps.c
+++ b/arch/arc/kernel/traps.c
@@ -84,19 +84,18 @@
 DO_ERROR_INFO(SIGTRAP, "Breakpoint Set", trap_is_brkpt, TRAP_BRKPT)
 DO_ERROR_INFO(SIGBUS, "Misaligned Access", do_misaligned_error, BUS_ADRALN)
 
-#ifdef CONFIG_ARC_MISALIGN_ACCESS
 /*
  * Entry Point for Misaligned Data access Exception, for emulating in software
  */
 int do_misaligned_access(unsigned long address, struct pt_regs *regs,
 			 struct callee_regs *cregs)
 {
+	/* If emulation not enabled, or failed, kill the task */
 	if (misaligned_fixup(address, regs, cregs) != 0)
 		return do_misaligned_error(address, regs);
 
 	return 0;
 }
-#endif
 
 /*
  * Entry point for miscll errors such as Nested Exceptions
diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c
index 5a1259c..6b58c1d 100644
--- a/arch/arc/mm/cache_arc700.c
+++ b/arch/arc/mm/cache_arc700.c
@@ -182,7 +182,7 @@
 
 #ifdef CONFIG_ARC_HAS_ICACHE
 	/* 1. Confirm some of I-cache params which Linux assumes */
-	if (ic->line_len != ARC_ICACHE_LINE_LEN)
+	if (ic->line_len != L1_CACHE_BYTES)
 		panic("Cache H/W doesn't match kernel Config");
 
 	if (ic->ver != CONFIG_ARC_MMU_VER)
@@ -205,7 +205,7 @@
 		return;
 
 #ifdef CONFIG_ARC_HAS_DCACHE
-	if (dc->line_len != ARC_DCACHE_LINE_LEN)
+	if (dc->line_len != L1_CACHE_BYTES)
 		panic("Cache H/W doesn't match kernel Config");
 
 	/* check for D-Cache aliasing */
@@ -240,6 +240,67 @@
 #define OP_INV		0x1
 #define OP_FLUSH	0x2
 #define OP_FLUSH_N_INV	0x3
+#define OP_INV_IC	0x4
+
+/*
+ * Common Helper for Line Operations on {I,D}-Cache
+ */
+static inline void __cache_line_loop(unsigned long paddr, unsigned long vaddr,
+				     unsigned long sz, const int cacheop)
+{
+	unsigned int aux_cmd, aux_tag;
+	int num_lines;
+	const int full_page_op = __builtin_constant_p(sz) && sz == PAGE_SIZE;
+
+	if (cacheop == OP_INV_IC) {
+		aux_cmd = ARC_REG_IC_IVIL;
+		aux_tag = ARC_REG_IC_PTAG;
+	}
+	else {
+		/* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */
+		aux_cmd = cacheop & OP_INV ? ARC_REG_DC_IVDL : ARC_REG_DC_FLDL;
+		aux_tag = ARC_REG_DC_PTAG;
+	}
+
+	/* Ensure we properly floor/ceil the non-line aligned/sized requests
+	 * and have @paddr - aligned to cache line and integral @num_lines.
+	 * This however can be avoided for page sized since:
+	 *  -@paddr will be cache-line aligned already (being page aligned)
+	 *  -@sz will be integral multiple of line size (being page sized).
+	 */
+	if (!full_page_op) {
+		sz += paddr & ~CACHE_LINE_MASK;
+		paddr &= CACHE_LINE_MASK;
+		vaddr &= CACHE_LINE_MASK;
+	}
+
+	num_lines = DIV_ROUND_UP(sz, L1_CACHE_BYTES);
+
+#if (CONFIG_ARC_MMU_VER <= 2)
+	/* MMUv2 and before: paddr contains stuffed vaddrs bits */
+	paddr |= (vaddr >> PAGE_SHIFT) & 0x1F;
+#else
+	/* if V-P const for loop, PTAG can be written once outside loop */
+	if (full_page_op)
+		write_aux_reg(ARC_REG_DC_PTAG, paddr);
+#endif
+
+	while (num_lines-- > 0) {
+#if (CONFIG_ARC_MMU_VER > 2)
+		/* MMUv3, cache ops require paddr seperately */
+		if (!full_page_op) {
+			write_aux_reg(aux_tag, paddr);
+			paddr += L1_CACHE_BYTES;
+		}
+
+		write_aux_reg(aux_cmd, vaddr);
+		vaddr += L1_CACHE_BYTES;
+#else
+		write_aux_reg(aux, paddr);
+		paddr += L1_CACHE_BYTES;
+#endif
+	}
+}
 
 #ifdef CONFIG_ARC_HAS_DCACHE
 
@@ -289,53 +350,6 @@
 		write_aux_reg(ARC_REG_DC_CTRL, tmp & ~DC_CTRL_INV_MODE_FLUSH);
 }
 
-/*
- * Per Line Operation on D-Cache
- * Doesn't deal with type-of-op/IRQ-disabling/waiting-for-flush-to-complete
- * It's sole purpose is to help gcc generate ZOL
- * (aliasing VIPT dcache flushing needs both vaddr and paddr)
- */
-static inline void __dc_line_loop(unsigned long paddr, unsigned long vaddr,
-				  unsigned long sz, const int aux_reg)
-{
-	int num_lines;
-
-	/* Ensure we properly floor/ceil the non-line aligned/sized requests
-	 * and have @paddr - aligned to cache line and integral @num_lines.
-	 * This however can be avoided for page sized since:
-	 *  -@paddr will be cache-line aligned already (being page aligned)
-	 *  -@sz will be integral multiple of line size (being page sized).
-	 */
-	if (!(__builtin_constant_p(sz) && sz == PAGE_SIZE)) {
-		sz += paddr & ~DCACHE_LINE_MASK;
-		paddr &= DCACHE_LINE_MASK;
-		vaddr &= DCACHE_LINE_MASK;
-	}
-
-	num_lines = DIV_ROUND_UP(sz, ARC_DCACHE_LINE_LEN);
-
-#if (CONFIG_ARC_MMU_VER <= 2)
-	paddr |= (vaddr >> PAGE_SHIFT) & 0x1F;
-#endif
-
-	while (num_lines-- > 0) {
-#if (CONFIG_ARC_MMU_VER > 2)
-		/*
-		 * Just as for I$, in MMU v3, D$ ops also require
-		 * "tag" bits in DC_PTAG, "index" bits in FLDL,IVDL ops
-		 */
-		write_aux_reg(ARC_REG_DC_PTAG, paddr);
-
-		write_aux_reg(aux_reg, vaddr);
-		vaddr += ARC_DCACHE_LINE_LEN;
-#else
-		/* paddr contains stuffed vaddrs bits */
-		write_aux_reg(aux_reg, paddr);
-#endif
-		paddr += ARC_DCACHE_LINE_LEN;
-	}
-}
-
 /* For kernel mappings cache operation: index is same as paddr */
 #define __dc_line_op_k(p, sz, op)	__dc_line_op(p, p, sz, op)
 
@@ -346,7 +360,6 @@
 				unsigned long sz, const int cacheop)
 {
 	unsigned long flags, tmp = tmp;
-	int aux;
 
 	local_irq_save(flags);
 
@@ -361,12 +374,7 @@
 		write_aux_reg(ARC_REG_DC_CTRL, tmp | DC_CTRL_INV_MODE_FLUSH);
 	}
 
-	if (cacheop & OP_INV)	/* Inv / flush-n-inv use same cmd reg */
-		aux = ARC_REG_DC_IVDL;
-	else
-		aux = ARC_REG_DC_FLDL;
-
-	__dc_line_loop(paddr, vaddr, sz, aux);
+	__cache_line_loop(paddr, vaddr, sz, cacheop);
 
 	if (cacheop & OP_FLUSH)	/* flush / flush-n-inv both wait */
 		wait_for_flush();
@@ -438,42 +446,9 @@
 				unsigned long sz)
 {
 	unsigned long flags;
-	int num_lines;
-
-	/*
-	 * Ensure we properly floor/ceil the non-line aligned/sized requests:
-	 * However page sized flushes can be compile time optimised.
-	 *  -@paddr will be cache-line aligned already (being page aligned)
-	 *  -@sz will be integral multiple of line size (being page sized).
-	 */
-	if (!(__builtin_constant_p(sz) && sz == PAGE_SIZE)) {
-		sz += paddr & ~ICACHE_LINE_MASK;
-		paddr &= ICACHE_LINE_MASK;
-		vaddr &= ICACHE_LINE_MASK;
-	}
-
-	num_lines = DIV_ROUND_UP(sz, ARC_ICACHE_LINE_LEN);
-
-#if (CONFIG_ARC_MMU_VER <= 2)
-	/* bits 17:13 of vaddr go as bits 4:0 of paddr */
-	paddr |= (vaddr >> PAGE_SHIFT) & 0x1F;
-#endif
 
 	local_irq_save(flags);
-	while (num_lines-- > 0) {
-#if (CONFIG_ARC_MMU_VER > 2)
-		/* tag comes from phy addr */
-		write_aux_reg(ARC_REG_IC_PTAG, paddr);
-
-		/* index bits come from vaddr */
-		write_aux_reg(ARC_REG_IC_IVIL, vaddr);
-		vaddr += ARC_ICACHE_LINE_LEN;
-#else
-		/* paddr contains stuffed vaddrs bits */
-		write_aux_reg(ARC_REG_IC_IVIL, paddr);
-#endif
-		paddr += ARC_ICACHE_LINE_LEN;
-	}
+	__cache_line_loop(paddr, vaddr, sz, OP_INV_IC);
 	local_irq_restore(flags);
 }
 
diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c
index d63f3de..9c69552 100644
--- a/arch/arc/mm/fault.c
+++ b/arch/arc/mm/fault.c
@@ -17,7 +17,7 @@
 #include <asm/pgalloc.h>
 #include <asm/mmu.h>
 
-static int handle_vmalloc_fault(struct mm_struct *mm, unsigned long address)
+static int handle_vmalloc_fault(unsigned long address)
 {
 	/*
 	 * Synchronize this task's top level page-table
@@ -27,7 +27,7 @@
 	pud_t *pud, *pud_k;
 	pmd_t *pmd, *pmd_k;
 
-	pgd = pgd_offset_fast(mm, address);
+	pgd = pgd_offset_fast(current->active_mm, address);
 	pgd_k = pgd_offset_k(address);
 
 	if (!pgd_present(*pgd_k))
@@ -52,7 +52,7 @@
 	return 1;
 }
 
-void do_page_fault(struct pt_regs *regs, unsigned long address)
+void do_page_fault(unsigned long address, struct pt_regs *regs)
 {
 	struct vm_area_struct *vma = NULL;
 	struct task_struct *tsk = current;
@@ -72,7 +72,7 @@
 	 * nothing more.
 	 */
 	if (address >= VMALLOC_START && address <= VMALLOC_END) {
-		ret = handle_vmalloc_fault(mm, address);
+		ret = handle_vmalloc_fault(address);
 		if (unlikely(ret))
 			goto bad_area_nosemaphore;
 		else
diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c
index 81279ec..55e0a85 100644
--- a/arch/arc/mm/init.c
+++ b/arch/arc/mm/init.c
@@ -125,10 +125,3 @@
 	free_reserved_area((void *)start, (void *)end, -1, "initrd");
 }
 #endif
-
-#ifdef CONFIG_OF_FLATTREE
-void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
-{
-	pr_err("%s(%llx, %llx)\n", __func__, start, end);
-}
-#endif /* CONFIG_OF_FLATTREE */
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c
index 71cb26d..e1acf0c 100644
--- a/arch/arc/mm/tlb.c
+++ b/arch/arc/mm/tlb.c
@@ -100,7 +100,7 @@
 
 
 /* A copy of the ASID from the PID reg is kept in asid_cache */
-unsigned int asid_cache = MM_CTXT_FIRST_CYCLE;
+DEFINE_PER_CPU(unsigned int, asid_cache) = MM_CTXT_FIRST_CYCLE;
 
 /*
  * Utility Routine to erase a J-TLB entry
@@ -274,6 +274,7 @@
 void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 			   unsigned long end)
 {
+	const unsigned int cpu = smp_processor_id();
 	unsigned long flags;
 
 	/* If range @start to @end is more than 32 TLB entries deep,
@@ -297,9 +298,9 @@
 
 	local_irq_save(flags);
 
-	if (vma->vm_mm->context.asid != MM_CTXT_NO_ASID) {
+	if (asid_mm(vma->vm_mm, cpu) != MM_CTXT_NO_ASID) {
 		while (start < end) {
-			tlb_entry_erase(start | hw_pid(vma->vm_mm));
+			tlb_entry_erase(start | hw_pid(vma->vm_mm, cpu));
 			start += PAGE_SIZE;
 		}
 	}
@@ -346,6 +347,7 @@
 
 void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
+	const unsigned int cpu = smp_processor_id();
 	unsigned long flags;
 
 	/* Note that it is critical that interrupts are DISABLED between
@@ -353,14 +355,87 @@
 	 */
 	local_irq_save(flags);
 
-	if (vma->vm_mm->context.asid != MM_CTXT_NO_ASID) {
-		tlb_entry_erase((page & PAGE_MASK) | hw_pid(vma->vm_mm));
+	if (asid_mm(vma->vm_mm, cpu) != MM_CTXT_NO_ASID) {
+		tlb_entry_erase((page & PAGE_MASK) | hw_pid(vma->vm_mm, cpu));
 		utlb_invalidate();
 	}
 
 	local_irq_restore(flags);
 }
 
+#ifdef CONFIG_SMP
+
+struct tlb_args {
+	struct vm_area_struct *ta_vma;
+	unsigned long ta_start;
+	unsigned long ta_end;
+};
+
+static inline void ipi_flush_tlb_page(void *arg)
+{
+	struct tlb_args *ta = arg;
+
+	local_flush_tlb_page(ta->ta_vma, ta->ta_start);
+}
+
+static inline void ipi_flush_tlb_range(void *arg)
+{
+	struct tlb_args *ta = arg;
+
+	local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end);
+}
+
+static inline void ipi_flush_tlb_kernel_range(void *arg)
+{
+	struct tlb_args *ta = (struct tlb_args *)arg;
+
+	local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end);
+}
+
+void flush_tlb_all(void)
+{
+	on_each_cpu((smp_call_func_t)local_flush_tlb_all, NULL, 1);
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+	on_each_cpu_mask(mm_cpumask(mm), (smp_call_func_t)local_flush_tlb_mm,
+			 mm, 1);
+}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
+{
+	struct tlb_args ta = {
+		.ta_vma = vma,
+		.ta_start = uaddr
+	};
+
+	on_each_cpu_mask(mm_cpumask(vma->vm_mm), ipi_flush_tlb_page, &ta, 1);
+}
+
+void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+		     unsigned long end)
+{
+	struct tlb_args ta = {
+		.ta_vma = vma,
+		.ta_start = start,
+		.ta_end = end
+	};
+
+	on_each_cpu_mask(mm_cpumask(vma->vm_mm), ipi_flush_tlb_range, &ta, 1);
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+	struct tlb_args ta = {
+		.ta_start = start,
+		.ta_end = end
+	};
+
+	on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
+}
+#endif
+
 /*
  * Routine to create a TLB entry
  */
@@ -400,7 +475,7 @@
 
 	local_irq_save(flags);
 
-	tlb_paranoid_check(vma->vm_mm->context.asid, address);
+	tlb_paranoid_check(asid_mm(vma->vm_mm, smp_processor_id()), address);
 
 	address &= PAGE_MASK;
 
@@ -610,9 +685,9 @@
 			  struct pt_regs *regs)
 {
 	int set, way, n;
-	unsigned int pd0[4], pd1[4];	/* assume max 4 ways */
 	unsigned long flags, is_valid;
 	struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu;
+	unsigned int pd0[mmu->ways], pd1[mmu->ways];
 
 	local_irq_save(flags);
 
@@ -637,7 +712,7 @@
 			continue;
 
 		/* Scan the set for duplicate ways: needs a nested loop */
-		for (way = 0; way < mmu->ways; way++) {
+		for (way = 0; way < mmu->ways - 1; way++) {
 			if (!pd0[way])
 				continue;
 
diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S
index cf7d7d9..3fcfdb3 100644
--- a/arch/arc/mm/tlbex.S
+++ b/arch/arc/mm/tlbex.S
@@ -369,8 +369,8 @@
 	EXCEPTION_PROLOGUE
 
 	; ------- setup args for Linux Page fault Hanlder ---------
-	mov_s r0, sp
-	lr  r1, [efa]
+	mov_s r1, sp
+	lr    r0, [efa]
 
 	; We don't want exceptions to be disabled while the fault is handled.
 	; Now that we have saved the context we return from exception hence
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 1ad6fb6..acb8070 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -54,6 +54,7 @@
 	select HAVE_REGS_AND_STACK_ACCESS_API
 	select HAVE_SYSCALL_TRACEPOINTS
 	select HAVE_UID16
+	select HAVE_VIRT_CPU_ACCOUNTING_GEN
 	select IRQ_FORCED_THREADING
 	select KTIME_SCALAR
 	select MODULES_USE_ELF_REL
@@ -317,6 +318,7 @@
 	select NEED_MACH_MEMORY_H
 	select PLAT_VERSATILE
 	select SPARSE_IRQ
+	select USE_OF
 	select VERSATILE_FPGA_IRQ
 	help
 	  Support for ARM's Integrator platform.
@@ -358,7 +360,6 @@
 	bool "Atmel AT91"
 	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
-	select HAVE_CLK
 	select IRQ_DOMAIN
 	select NEED_MACH_GPIO_H
 	select NEED_MACH_IO_H if PCCARD
@@ -372,7 +373,6 @@
 	bool "Cirrus Logic CLPS711x/EP721x/EP731x-based"
 	select ARCH_REQUIRE_GPIOLIB
 	select AUTO_ZRELADDR
-	select CLKDEV_LOOKUP
 	select CLKSRC_MMIO
 	select COMMON_CLK
 	select CPU_ARM720T
@@ -386,9 +386,9 @@
 config ARCH_GEMINI
 	bool "Cortina Systems Gemini"
 	select ARCH_REQUIRE_GPIOLIB
-	select ARCH_USES_GETTIMEOFFSET
+	select CLKSRC_MMIO
 	select CPU_FA526
-	select NEED_MACH_GPIO_H
+	select GENERIC_CLOCKEVENTS
 	help
 	  Support for the Cortina Systems Gemini family SoCs
 
@@ -457,7 +457,7 @@
 	depends on MMU
 	select ARCH_REQUIRE_GPIOLIB
 	select CPU_XSCALE
-	select NEED_MACH_GPIO_H
+	select GPIO_IOP
 	select NEED_RET_TO_USER
 	select PCI
 	select PLAT_IOP
@@ -470,7 +470,7 @@
 	depends on MMU
 	select ARCH_REQUIRE_GPIOLIB
 	select CPU_XSCALE
-	select NEED_MACH_GPIO_H
+	select GPIO_IOP
 	select NEED_RET_TO_USER
 	select PCI
 	select PLAT_IOP
@@ -559,7 +559,6 @@
 	select GPIO_PXA
 	select IRQ_DOMAIN
 	select MULTI_IRQ_HANDLER
-	select NEED_MACH_GPIO_H
 	select PINCTRL
 	select PLAT_PXA
 	select SPARSE_IRQ
@@ -622,7 +621,6 @@
 	select GPIO_PXA
 	select HAVE_IDE
 	select MULTI_IRQ_HANDLER
-	select NEED_MACH_GPIO_H
 	select PLAT_PXA
 	select SPARSE_IRQ
 	help
@@ -631,7 +629,6 @@
 config ARCH_MSM
 	bool "Qualcomm MSM"
 	select ARCH_REQUIRE_GPIOLIB
-	select CLKDEV_LOOKUP
 	select CLKSRC_OF if OF
 	select COMMON_CLK
 	select GENERIC_CLOCKEVENTS
@@ -649,7 +646,6 @@
 	select GENERIC_CLOCKEVENTS
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
-	select HAVE_CLK
 	select HAVE_MACH_CLKDEV
 	select HAVE_SMP
 	select MIGHT_HAVE_CACHE_L2X0
@@ -706,7 +702,6 @@
 	select CLKSRC_SAMSUNG_PWM
 	select GENERIC_CLOCKEVENTS
 	select GPIO_SAMSUNG
-	select HAVE_CLK
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	select HAVE_S3C_RTC if RTC_CLASS
@@ -727,21 +722,22 @@
 	select ARM_VIC
 	select CLKDEV_LOOKUP
 	select CLKSRC_SAMSUNG_PWM
+	select COMMON_CLK
 	select CPU_V6
 	select GENERIC_CLOCKEVENTS
 	select GPIO_SAMSUNG
-	select HAVE_CLK
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	select HAVE_TCM
 	select NEED_MACH_GPIO_H
 	select NO_IOPORT
 	select PLAT_SAMSUNG
+	select PM_GENERIC_DOMAINS
 	select S3C_DEV_NAND
 	select S3C_GPIO_TRACK
 	select SAMSUNG_ATAGS
-	select SAMSUNG_CLKSRC
 	select SAMSUNG_GPIOLIB_4BIT
+	select SAMSUNG_WAKEMASK
 	select SAMSUNG_WDT_RESET
 	select USB_ARCH_HAS_OHCI
 	help
@@ -754,7 +750,6 @@
 	select CPU_V6
 	select GENERIC_CLOCKEVENTS
 	select GPIO_SAMSUNG
-	select HAVE_CLK
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	select HAVE_S3C_RTC if RTC_CLASS
@@ -773,7 +768,6 @@
 	select CPU_V7
 	select GENERIC_CLOCKEVENTS
 	select GPIO_SAMSUNG
-	select HAVE_CLK
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	select HAVE_S3C_RTC if RTC_CLASS
@@ -793,7 +787,6 @@
 	select CPU_V7
 	select GENERIC_CLOCKEVENTS
 	select GPIO_SAMSUNG
-	select HAVE_CLK
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	select HAVE_S3C_RTC if RTC_CLASS
@@ -810,11 +803,9 @@
 	select ARCH_REQUIRE_GPIOLIB
 	select ARCH_SPARSEMEM_ENABLE
 	select ARM_GIC
-	select CLKDEV_LOOKUP
 	select COMMON_CLK
 	select CPU_V7
 	select GENERIC_CLOCKEVENTS
-	select HAVE_CLK
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	select HAVE_S3C_RTC if RTC_CLASS
@@ -824,20 +815,6 @@
 	help
 	  Support for SAMSUNG's EXYNOS SoCs (EXYNOS4/5)
 
-config ARCH_SHARK
-	bool "Shark"
-	select ARCH_USES_GETTIMEOFFSET
-	select CPU_SA110
-	select ISA
-	select ISA_DMA
-	select NEED_MACH_MEMORY_H
-	select PCI
-	select VIRT_TO_BUS
-	select ZONE_DMA
-	help
-	  Support for the StrongARM based Digital DNARD machine, also known
-	  as "Shark" (<http://www.shark-linux.de/shark.html>).
-
 config ARCH_DAVINCI
 	bool "TI DaVinci"
 	select ARCH_HAS_HOLES_MEMORYMODEL
@@ -847,7 +824,6 @@
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_IRQ_CHIP
 	select HAVE_IDE
-	select NEED_MACH_GPIO_H
 	select TI_PRIV_EDMA
 	select USE_OF
 	select ZONE_DMA
@@ -865,7 +841,6 @@
 	select CLKSRC_MMIO
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_IRQ_CHIP
-	select HAVE_CLK
 	select HAVE_IDE
 	select IRQ_DOMAIN
 	select NEED_MACH_IO_H if PCCARD
@@ -1009,9 +984,7 @@
 
 source "arch/arm/mach-s3c24xx/Kconfig"
 
-if ARCH_S3C64XX
 source "arch/arm/mach-s3c64xx/Kconfig"
-endif
 
 source "arch/arm/mach-s5p64x0/Kconfig"
 
@@ -1431,12 +1404,6 @@
 config PCI_SYSCALL
 	def_bool PCI
 
-# Select the host bridge type
-config PCI_HOST_VIA82C505
-	bool
-	depends on PCI && ARCH_SHARK
-	default y
-
 config PCI_HOST_ITE8152
 	bool
 	depends on PCI && MACH_ARMCORE
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 9762c84..d597c6b 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -386,6 +386,13 @@
 		  when u-boot hands over to the kernel, the system
 		  silently crashes, with no serial output at all.
 
+	config DEBUG_VF_UART
+		bool "Vybrid UART"
+		depends on SOC_VF610
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Vybrid based platforms.
+
 	config DEBUG_NOMADIK_UART
 		bool "Kernel low-level debugging messages via NOMADIK UART"
 		depends on ARCH_NOMADIK
@@ -906,6 +913,7 @@
 	default "debug/tegra.S" if DEBUG_TEGRA_UART
 	default "debug/ux500.S" if DEBUG_UX500_UART
 	default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT
+	default "debug/vf.S" if DEBUG_VF_UART
 	default "debug/vt8500.S" if DEBUG_VT8500_UART0
 	default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
 	default "mach/debug-macro.S"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index a37a50f..8b66713 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -188,7 +188,6 @@
 machine-$(CONFIG_ARCH_S5PC100)		+= s5pc100
 machine-$(CONFIG_ARCH_S5PV210)		+= s5pv210
 machine-$(CONFIG_ARCH_SA1100)		+= sa1100
-machine-$(CONFIG_ARCH_SHARK)		+= shark
 machine-$(CONFIG_ARCH_SHMOBILE) 	+= shmobile
 machine-$(CONFIG_ARCH_SHMOBILE_MULTI) 	+= shmobile
 machine-$(CONFIG_ARCH_SIRF)		+= prima2
@@ -296,10 +295,15 @@
 # Convert bzImage to zImage
 bzImage: zImage
 
-zImage Image xipImage bootpImage uImage: vmlinux
+BOOT_TARGETS	= zImage Image xipImage bootpImage uImage
+INSTALL_TARGETS	= zinstall uinstall install
+
+PHONY += bzImage $(BOOT_TARGETS) $(INSTALL_TARGETS)
+
+$(BOOT_TARGETS): vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
 
-zinstall uinstall install: vmlinux
+$(INSTALL_TARGETS):
 	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
 
 %.dtb: | scripts
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index 84aa2ca..ec2f806 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -95,24 +95,24 @@
 	@test "$(INITRD)" != "" || \
 	(echo You must specify INITRD; exit -1)
 
-install: $(obj)/Image
-	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
+install:
+	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" \
 	$(obj)/Image System.map "$(INSTALL_PATH)"
 
-zinstall: $(obj)/zImage
-	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
+zinstall:
+	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" \
 	$(obj)/zImage System.map "$(INSTALL_PATH)"
 
-uinstall: $(obj)/uImage
-	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
+uinstall:
+	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" \
 	$(obj)/uImage System.map "$(INSTALL_PATH)"
 
 zi:
-	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
+	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" \
 	$(obj)/zImage System.map "$(INSTALL_PATH)"
 
 i:
-	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
+	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" \
 	$(obj)/Image System.map "$(INSTALL_PATH)"
 
 subdir-	    := bootp compressed dts
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 7ac1610..e7190bb 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -44,10 +44,6 @@
 OBJS		+= ll_char_wr.o font.o
 endif
 
-ifeq ($(CONFIG_ARCH_SHARK),y)
-OBJS		+= head-shark.o ofw-shark.o
-endif
-
 ifeq ($(CONFIG_ARCH_SA1100),y)
 OBJS		+= head-sa1100.o
 endif
diff --git a/arch/arm/boot/compressed/head-shark.S b/arch/arm/boot/compressed/head-shark.S
deleted file mode 100644
index 92b5689..0000000
--- a/arch/arm/boot/compressed/head-shark.S
+++ /dev/null
@@ -1,140 +0,0 @@
-/* The head-file for the Shark
- * by Alexander Schulz
- *
- * Does the following:
- * - get the memory layout from firmware. This can only be done as long as the mmu
- *   is still on.
- * - switch the mmu off, so we have physical addresses
- * - copy the kernel to 0x08508000. This is done to have a fixed address where the
- *   C-parts (misc.c) are executed. This address must be known at compile-time,
- *   but the load-address of the kernel depends on how much memory is installed.
- * - Jump to this location.
- * - Set r8 with 0, r7 with the architecture ID for head.S
- */
-
-#include <linux/linkage.h>
-
-#include <asm/assembler.h>
-	
-		.section	".start", "ax"
-
-		.arch armv4
-		b	__beginning
-	
-__ofw_data:	.long	0				@ the number of memory blocks
-		.space  128				@ (startaddr,size) ...
-		.space  128				@ bootargs
-		.align
-
-__beginning:	mov	r4, r0				@ save the entry to the firmware
-
-		mov	r0, #0xC0			@ disable irq and fiq
-		mov	r1, r0
-		mrs	r3, cpsr
-		bic	r2, r3, r0
-		eor	r2, r2, r1
-		msr	cpsr_c, r2
-
-		mov	r0, r4				@ get the Memory layout from firmware
-		adr	r1, __ofw_data
-		add	r2, r1, #4
-		mov	lr, pc
-		b	ofw_init
-		mov	r1, #0
-
-		adr	r2, __mmu_off			@ calculate physical address
-		sub	r2, r2, #0xf0000000		@ openprom maps us at f000 virt, 0e50 phys
-		adr	r0, __ofw_data
-		ldr	r0, [r0, #4]
-		add	r2, r2, r0
-		add	r2, r2, #0x00500000
-
-		mrc	p15, 0, r3, c1, c0
-		bic	r3, r3, #0xC			@ Write Buffer and DCache
-		bic	r3, r3, #0x1000			@ ICache
-		mcr	p15, 0, r3, c1, c0		@ disabled
-
-		mov	r0, #0
-		mcr	p15, 0, r0, c7, c7		@ flush I,D caches on v4
-		mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer on v4
-		mcr	p15, 0, r0, c8, c7		@ flush I,D TLBs on v4
-
-		bic	r3, r3, #0x1			@ MMU
-		mcr	p15, 0, r3, c1, c0		@ disabled
-
-		mov	pc, r2
-
-__copy_target:	.long	0x08507FFC
-__copy_end:	.long	0x08607FFC
-		
-		.word	_start
-		.word	__bss_start
-
-		.align
-__temp_stack:	.space 128
-
-__mmu_off:
-		adr	r0, __ofw_data			@ read the 1. entry of the memory map
-		ldr	r0, [r0, #4]
-		orr	r0, r0, #0x00600000
-		sub	r0, r0, #4
-	
-		ldr	r1, __copy_end
-		ldr	r3, __copy_target
-
-/* r0 = 0x0e600000 (current end of kernelcode)
- * r3 = 0x08508000 (where it should begin)
- * r1 = 0x08608000 (end of copying area, 1MB)
- * The kernel is compressed, so 1 MB should be enough.
- * copy the kernel to the beginning of physical memory
- * We start from the highest address, so we can copy
- * from 0x08500000 to 0x08508000 if we have only 8MB
- */
-
-/* As we get more 2.6-kernels it gets more and more
- * uncomfortable to be bound to kernel images of 1MB only.
- * So we add a loop here, to be able to copy some more.
- * Alexander Schulz 2005-07-17
- */
-
-		mov	r4, #3				@ How many megabytes to copy
-
-
-__MoveCode:	sub	r4, r4, #1
-	
-__Copy:		ldr	r2, [r0], #-4
-		str	r2, [r1], #-4
-		teq	r1, r3
-		bne	__Copy
-
-		/* The firmware maps us in blocks of 1 MB, the next block is
-		   _below_ the last one. So our decrementing source pointer
-		   ist right here, but the destination pointer must be increased
-		   by 2 MB */
-		add	r1, r1, #0x00200000
-		add	r3, r3, #0x00100000
-
-		teq	r4, #0
-		bne	__MoveCode
-
-
-		/* and jump to it */
-		adr	r2, __go_on			@ where we want to jump
-		adr	r0, __ofw_data			@ read the 1. entry of the memory map
-		ldr	r0, [r0, #4]
-		sub	r2, r2, r0			@ we are mapped add 0e50 now, sub that (-0e00)
-		sub	r2, r2, #0x00500000		@ -0050
-		ldr	r0, __copy_target		@ and add 0850 8000 instead
-		add	r0, r0, #4
-		add	r2, r2, r0
-		mov	pc, r2				@ and jump there
-
-__go_on:
-		adr	sp, __temp_stack
-		add	sp, sp, #128
-		adr	r0, __ofw_data
-		mov	lr, pc
-		b	create_params
-	
-		mov	r8, #0
-		mov	r7, #15
diff --git a/arch/arm/boot/compressed/ofw-shark.c b/arch/arm/boot/compressed/ofw-shark.c
deleted file mode 100644
index 465c54b..0000000
--- a/arch/arm/boot/compressed/ofw-shark.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * linux/arch/arm/boot/compressed/ofw-shark.c
- *
- * by Alexander Schulz
- *
- * This file is used to get some basic information
- * about the memory layout of the shark we are running
- * on. Memory is usually divided in blocks a 8 MB.
- * And bootargs are copied from OpenFirmware.
- */
-
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <asm/setup.h>
-#include <asm/page.h>
-
-
-asmlinkage void
-create_params (unsigned long *buffer)
-{
-	/* Is there a better address? Also change in mach-shark/core.c */
-	struct tag *tag = (struct tag *) 0x08003000;
-	int j,i,m,k,nr_banks,size;
-	unsigned char *c;
-
-	k = 0;
-
-	/* Head of the taglist */
-	tag->hdr.tag  = ATAG_CORE;
-	tag->hdr.size = tag_size(tag_core);
-	tag->u.core.flags = 1;
-	tag->u.core.pagesize = PAGE_SIZE;
-	tag->u.core.rootdev = 0;
-
-	/* Build up one tagged block for each memory region */
-	size=0;
-	nr_banks=(unsigned int) buffer[0];
-	for (j=0;j<nr_banks;j++){
-		/* search the lowest address and put it into the next entry   */
-		/* not a fast sort algorithm, but there are at most 8 entries */
-		/* and this is used only once anyway                          */
-		m=0xffffffff;
-		for (i=0;i<(unsigned int) buffer[0];i++){
-			if (buffer[2*i+1]<m) {
-				m=buffer[2*i+1];
-				k=i;
-			}
-		}
-	  
-		tag = tag_next(tag);
-		tag->hdr.tag = ATAG_MEM;
-		tag->hdr.size = tag_size(tag_mem32);
-		tag->u.mem.size = buffer[2*k+2];
-		tag->u.mem.start = buffer[2*k+1];
-
-		size += buffer[2*k+2];
-
-		buffer[2*k+1]=0xffffffff;                    /* mark as copied */
-	}
-	
-	/* The command line */
-	tag = tag_next(tag);
-	tag->hdr.tag = ATAG_CMDLINE;
-	
-	c=(unsigned char *)(&buffer[34]);
-	j=0;
-	while (*c) tag->u.cmdline.cmdline[j++]=*c++;
-
-	tag->u.cmdline.cmdline[j]=0;
-	tag->hdr.size = (j + 7 + sizeof(struct tag_header)) >> 2;
-
-	/* Hardware revision */
-	tag = tag_next(tag);
-	tag->hdr.tag = ATAG_REVISION;
-	tag->hdr.size = tag_size(tag_revision);
-	tag->u.revision.rev = ((unsigned char) buffer[33])-'0';
-
-	/* End of the taglist */
-	tag = tag_next(tag);
-	tag->hdr.tag = 0;
-	tag->hdr.size = 0;
-}
-
-
-typedef int (*ofw_handle_t)(void *);
-
-/* Everything below is called with a wrong MMU setting.
- * This means: no string constants, no initialization of
- * arrays, no global variables! This is ugly but I didn't
- * want to write this in assembler :-)
- */
-
-int
-of_decode_int(const unsigned char *p)
-{
-	unsigned int i = *p++ << 8;
-	i = (i + *p++) << 8;
-	i = (i + *p++) << 8;
-	return (i + *p);
-}
-  
-int
-OF_finddevice(ofw_handle_t openfirmware, char *name)
-{
-	unsigned int args[8];
-	char service[12];
-
-	service[0]='f';
-	service[1]='i';
-	service[2]='n';
-	service[3]='d';
-	service[4]='d';
-	service[5]='e';
-	service[6]='v';
-	service[7]='i';
-	service[8]='c';
-	service[9]='e';
-	service[10]='\0';
-
-	args[0]=(unsigned int)service;
-	args[1]=1;
-	args[2]=1;
-	args[3]=(unsigned int)name;
-
-	if (openfirmware(args) == -1)
-		return -1;
-	return args[4];
-}
-
-int
-OF_getproplen(ofw_handle_t openfirmware, int handle, char *prop)
-{
-	unsigned int args[8];
-	char service[12];
-
-	service[0]='g';
-	service[1]='e';
-	service[2]='t';
-	service[3]='p';
-	service[4]='r';
-	service[5]='o';
-	service[6]='p';
-	service[7]='l';
-	service[8]='e';
-	service[9]='n';
-	service[10]='\0';
-
-	args[0] = (unsigned int)service;
-	args[1] = 2;
-	args[2] = 1;
-	args[3] = (unsigned int)handle;
-	args[4] = (unsigned int)prop;
-
-	if (openfirmware(args) == -1)
-		return -1;
-	return args[5];
-}
-  
-int
-OF_getprop(ofw_handle_t openfirmware, int handle, char *prop, void *buf, unsigned int buflen)
-{
-	unsigned int args[8];
-	char service[8];
-
-	service[0]='g';
-	service[1]='e';
-	service[2]='t';
-	service[3]='p';
-	service[4]='r';
-	service[5]='o';
-	service[6]='p';
-	service[7]='\0';
-
-	args[0] = (unsigned int)service;
-	args[1] = 4;
-	args[2] = 1;
-	args[3] = (unsigned int)handle;
-	args[4] = (unsigned int)prop;
-	args[5] = (unsigned int)buf;
-	args[6] = buflen;
-
-	if (openfirmware(args) == -1)
-		return -1;
-	return args[7];
-}
-  
-asmlinkage void ofw_init(ofw_handle_t o, int *nomr, int *pointer)
-{
-	int phandle,i,mem_len,buffer[32];
-	char temp[15];
-  
-	temp[0]='/';
-	temp[1]='m';
-	temp[2]='e';
-	temp[3]='m';
-	temp[4]='o';
-	temp[5]='r';
-	temp[6]='y';
-	temp[7]='\0';
-
-	phandle=OF_finddevice(o,temp);
-
-	temp[0]='r';
-	temp[1]='e';
-	temp[2]='g';
-	temp[3]='\0';
-
-	mem_len = OF_getproplen(o,phandle, temp);
-	OF_getprop(o,phandle, temp, buffer, mem_len);
-	*nomr=mem_len >> 3;
-
-	for (i=0; i<=mem_len/4; i++) pointer[i]=of_decode_int((const unsigned char *)&buffer[i]);
-
-	temp[0]='/';
-	temp[1]='c';
-	temp[2]='h';
-	temp[3]='o';
-	temp[4]='s';
-	temp[5]='e';
-	temp[6]='n';
-	temp[7]='\0';
-
-	phandle=OF_finddevice(o,temp);
-
-	temp[0]='b';
-	temp[1]='o';
-	temp[2]='o';
-	temp[3]='t';
-	temp[4]='a';
-	temp[5]='r';
-	temp[6]='g';
-	temp[7]='s';
-	temp[8]='\0';
-
-	mem_len = OF_getproplen(o,phandle, temp);
-	OF_getprop(o,phandle, temp, buffer, mem_len);
-	if (mem_len > 128) mem_len=128;
-	for (i=0; i<=mem_len/4; i++) pointer[i+33]=buffer[i];
-	pointer[i+33]=0;
-
-	temp[0]='/';
-	temp[1]='\0';
-	phandle=OF_finddevice(o,temp);
-	temp[0]='b';
-	temp[1]='a';
-	temp[2]='n';
-	temp[3]='n';
-	temp[4]='e';
-	temp[5]='r';
-	temp[6]='-';
-	temp[7]='n';
-	temp[8]='a';
-	temp[9]='m';
-	temp[10]='e';
-	temp[11]='\0';
-	mem_len = OF_getproplen(o,phandle, temp);
-	OF_getprop(o,phandle, temp, buffer, mem_len);
-	* ((unsigned char *) &pointer[32]) = ((unsigned char *) buffer)[mem_len-2];
-}
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 802720e..d57c1a6 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -40,17 +40,17 @@
 dtb-$(CONFIG_ARCH_AT91)	+= sama5d33ek.dtb
 dtb-$(CONFIG_ARCH_AT91)	+= sama5d34ek.dtb
 dtb-$(CONFIG_ARCH_AT91)	+= sama5d35ek.dtb
-
 dtb-$(CONFIG_ARCH_ATLAS6) += atlas6-evb.dtb
-
 dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb
-dtb-$(CONFIG_ARCH_BCM) += bcm11351-brt.dtb \
+dtb-$(CONFIG_ARCH_BCM_MOBILE) += bcm11351-brt.dtb \
 	bcm28155-ap.dtb
+dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb
 dtb-$(CONFIG_ARCH_DAVINCI) += da850-enbw-cmc.dtb \
 	da850-evm.dtb
 dtb-$(CONFIG_ARCH_DOVE) += dove-cm-a510.dtb \
 	dove-cubox.dtb \
 	dove-d2plug.dtb \
+	dove-d3plug.dtb \
 	dove-dove-db.dtb
 dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
 	exynos4210-smdkv310.dtb \
@@ -96,22 +96,25 @@
 	kirkwood-ns2mini.dtb \
 	kirkwood-nsa310.dtb \
 	kirkwood-nsa310a.dtb \
+	kirkwood-openblocks_a6.dtb \
+	kirkwood-openblocks_a7.dtb \
 	kirkwood-sheevaplug.dtb \
 	kirkwood-sheevaplug-esata.dtb \
 	kirkwood-topkick.dtb \
 	kirkwood-ts219-6281.dtb \
-	kirkwood-ts219-6282.dtb \
-	kirkwood-openblocks_a6.dtb
+	kirkwood-ts219-6282.dtb
 dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb
-dtb-$(CONFIG_ARCH_MSM) += msm8660-surf.dtb \
-	msm8960-cdp.dtb
+dtb-$(CONFIG_ARCH_MSM) += qcom-msm8660-surf.dtb \
+	qcom-msm8960-cdp.dtb
 dtb-$(CONFIG_ARCH_MVEBU) += armada-370-db.dtb \
 	armada-370-mirabox.dtb \
 	armada-370-netgear-rn102.dtb \
+	armada-370-netgear-rn104.dtb \
 	armada-370-rd.dtb \
 	armada-xp-axpwifiap.dtb \
 	armada-xp-db.dtb \
 	armada-xp-gp.dtb \
+	armada-xp-matrix.dtb \
 	armada-xp-openblocks-ax3-4.dtb
 dtb-$(CONFIG_ARCH_MXC) += \
 	imx25-karo-tx25.dtb \
@@ -142,8 +145,10 @@
 	imx6q-sabrelite.dtb \
 	imx6q-sabresd.dtb \
 	imx6q-sbc6x.dtb \
+	imx6q-udoo.dtb \
 	imx6q-wandboard.dtb \
 	imx6sl-evk.dtb \
+	vf610-cosmic.dtb \
 	vf610-twr.dtb
 dtb-$(CONFIG_ARCH_MXS) += imx23-evk.dtb \
 	imx23-olinuxino.dtb \
@@ -159,6 +164,7 @@
 	imx28-cfa10057.dtb \
 	imx28-cfa10058.dtb \
 	imx28-evk.dtb \
+	imx28-m28cu3.dtb \
 	imx28-m28evk.dtb \
 	imx28-sps1.dtb \
 	imx28-tx28.dtb
@@ -172,9 +178,15 @@
 	omap3-devkit8000.dtb \
 	omap3-beagle-xm.dtb \
 	omap3-evm.dtb \
+	omap3-evm-37xx.dtb \
+	omap3-n900.dtb \
+	omap3-n9.dtb \
+	omap3-n950.dtb \
 	omap3-tobi.dtb \
+	omap3-gta04.dtb \
 	omap3-igep0020.dtb \
 	omap3-igep0030.dtb \
+	omap3-zoom3.dtb \
 	omap4-panda.dtb \
 	omap4-panda-a4.dtb \
 	omap4-panda-es.dtb \
@@ -186,25 +198,33 @@
 	am335x-evmsk.dtb \
 	am335x-bone.dtb \
 	am335x-boneblack.dtb \
+	am335x-nano.dtb \
+	am335x-base0033.dtb \
 	am3517-evm.dtb \
 	am3517_mt_ventoux.dtb \
-	am43x-epos-evm.dtb
+	am43x-epos-evm.dtb \
+	dra7-evm.dtb
 dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
 dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \
-	ste-hrefprev60.dtb \
-	ste-hrefv60plus.dtb \
+	ste-hrefprev60-stuib.dtb \
+	ste-hrefprev60-tvk.dtb \
+	ste-hrefv60plus-stuib.dtb \
+	ste-hrefv60plus-tvk.dtb \
 	ste-ccu8540.dtb \
 	ste-ccu9540.dtb
 dtb-$(CONFIG_ARCH_S3C24XX) += s3c2416-smdk2416.dtb
+dtb-$(CONFIG_ARCH_S3C64XX) += s3c6410-mini6410.dtb \
+	s3c6410-smdk6410.dtb
 dtb-$(CONFIG_ARCH_SHMOBILE) += emev2-kzm9d.dtb \
-	emev2-kzm9d-reference.dtb \
+	r7s72100-genmai.dtb \
 	r8a7740-armadillo800eva.dtb \
 	r8a7778-bockw.dtb \
 	r8a7778-bockw-reference.dtb \
 	r8a7740-armadillo800eva-reference.dtb \
 	r8a7779-marzen.dtb \
 	r8a7779-marzen-reference.dtb \
+	r8a7791-koelsch.dtb \
 	r8a7790-lager.dtb \
 	r8a7790-lager-reference.dtb \
 	sh73a0-kzm9g.dtb \
@@ -212,8 +232,10 @@
 	r8a73a4-ape6evm.dtb \
 	r8a73a4-ape6evm-reference.dtb \
 	sh7372-mackerel.dtb
-dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += emev2-kzm9d-reference.dtb
-dtb-$(CONFIG_ARCH_SOCFPGA) += socfpga_cyclone5.dtb \
+dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += emev2-kzm9d.dtb
+dtb-$(CONFIG_ARCH_SOCFPGA) += socfpga_arria5_socdk.dtb \
+	socfpga_cyclone5_socdk.dtb \
+	socfpga_cyclone5_sockit.dtb \
 	socfpga_vt.dtb
 dtb-$(CONFIG_ARCH_SPEAR13XX) += spear1310-evb.dtb \
 	spear1340-evb.dtb
@@ -235,6 +257,7 @@
 	sun5i-a13-olinuxino.dtb \
 	sun6i-a31-colombus.dtb \
 	sun7i-a20-cubieboard2.dtb \
+	sun7i-a20-cubietruck.dtb \
 	sun7i-a20-olinuxino-micro.dtb
 dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \
 	tegra20-iris-512.dtb \
@@ -249,7 +272,8 @@
 	tegra30-beaver.dtb \
 	tegra30-cardhu-a02.dtb \
 	tegra30-cardhu-a04.dtb \
-	tegra114-dalmore.dtb
+	tegra114-dalmore.dtb \
+	tegra124-venice2.dtb
 dtb-$(CONFIG_ARCH_VERSATILE) += versatile-ab.dtb \
 	versatile-pb.dtb
 dtb-$(CONFIG_ARCH_U300) += ste-u300.dtb
diff --git a/arch/arm/boot/dts/am335x-base0033.dts b/arch/arm/boot/dts/am335x-base0033.dts
new file mode 100644
index 0000000..b4f95c2
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-base0033.dts
@@ -0,0 +1,16 @@
+/*
+ * am335x-base0033.dts - Device Tree file for IGEP AQUILA EXPANSION
+ *
+ * Copyright (C) 2013 ISEE 2007 SL - http://www.isee.biz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "am335x-igep0033.dtsi"
+
+/ {
+	model = "IGEP COM AM335x on AQUILA Expansion";
+	compatible = "isee,am335x-base0033", "isee,am335x-igep0033", "ti,am33xx";
+};
diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
index 2f66ded..e3f27ec 100644
--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
@@ -21,145 +21,6 @@
 		reg = <0x80000000 0x10000000>; /* 256 MB */
 	};
 
-	am33xx_pinmux: pinmux@44e10800 {
-		pinctrl-names = "default";
-		pinctrl-0 = <&clkout2_pin>;
-
-		user_leds_s0: user_leds_s0 {
-			pinctrl-single,pins = <
-				0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a5.gpio1_21 */
-				0x58 (PIN_OUTPUT_PULLUP | MUX_MODE7)	/* gpmc_a6.gpio1_22 */
-				0x5c (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a7.gpio1_23 */
-				0x60 (PIN_OUTPUT_PULLUP | MUX_MODE7)	/* gpmc_a8.gpio1_24 */
-			>;
-		};
-
-		i2c0_pins: pinmux_i2c0_pins {
-			pinctrl-single,pins = <
-				0x188 (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
-				0x18c (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
-			>;
-		};
-
-		uart0_pins: pinmux_uart0_pins {
-			pinctrl-single,pins = <
-				0x170 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
-				0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
-			>;
-		};
-
-		clkout2_pin: pinmux_clkout2_pin {
-			pinctrl-single,pins = <
-				0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3)	/* xdma_event_intr1.clkout2 */
-			>;
-		};
-
-		cpsw_default: cpsw_default {
-			pinctrl-single,pins = <
-				/* Slave 1 */
-				0x110 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxerr.mii1_rxerr */
-				0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txen.mii1_txen */
-				0x118 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxdv.mii1_rxdv */
-				0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd3.mii1_txd3 */
-				0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd2.mii1_txd2 */
-				0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd1.mii1_txd1 */
-				0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd0.mii1_txd0 */
-				0x12c (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_txclk.mii1_txclk */
-				0x130 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxclk.mii1_rxclk */
-				0x134 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd3.mii1_rxd3 */
-				0x138 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd2.mii1_rxd2 */
-				0x13c (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd1.mii1_rxd1 */
-				0x140 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd0.mii1_rxd0 */
-			>;
-		};
-
-		cpsw_sleep: cpsw_sleep {
-			pinctrl-single,pins = <
-				/* Slave 1 reset value */
-				0x110 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-			>;
-		};
-
-		davinci_mdio_default: davinci_mdio_default {
-			pinctrl-single,pins = <
-				/* MDIO */
-				0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
-				0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
-			>;
-		};
-
-		davinci_mdio_sleep: davinci_mdio_sleep {
-			pinctrl-single,pins = <
-				/* MDIO reset value */
-				0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-			>;
-		};
-	};
-
-	ocp {
-		uart0: serial@44e09000 {
-			pinctrl-names = "default";
-			pinctrl-0 = <&uart0_pins>;
-
-			status = "okay";
-		};
-
-		musb: usb@47400000 {
-			status = "okay";
-
-			control@44e10000 {
-				status = "okay";
-			};
-
-			usb-phy@47401300 {
-				status = "okay";
-			};
-
-			usb-phy@47401b00 {
-				status = "okay";
-			};
-
-			usb@47401000 {
-				status = "okay";
-			};
-
-			usb@47401800 {
-				status = "okay";
-				dr_mode = "host";
-			};
-
-			dma-controller@07402000  {
-				status = "okay";
-			};
-		};
-
-		i2c0: i2c@44e0b000 {
-			pinctrl-names = "default";
-			pinctrl-0 = <&i2c0_pins>;
-
-			status = "okay";
-			clock-frequency = <400000>;
-
-			tps: tps@24 {
-				reg = <0x24>;
-			};
-
-		};
-	};
-
 	leds {
 		pinctrl-names = "default";
 		pinctrl-0 = <&user_leds_s0>;
@@ -183,15 +44,182 @@
 		led@4 {
 			label = "beaglebone:green:usr2";
 			gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "cpu0";
 			default-state = "off";
 		};
 
 		led@5 {
 			label = "beaglebone:green:usr3";
 			gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc1";
 			default-state = "off";
 		};
 	};
+
+	vmmcsd_fixed: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmcsd_fixed";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+};
+
+&am33xx_pinmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&clkout2_pin>;
+
+	user_leds_s0: user_leds_s0 {
+		pinctrl-single,pins = <
+			0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a5.gpio1_21 */
+			0x58 (PIN_OUTPUT_PULLUP | MUX_MODE7)	/* gpmc_a6.gpio1_22 */
+			0x5c (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a7.gpio1_23 */
+			0x60 (PIN_OUTPUT_PULLUP | MUX_MODE7)	/* gpmc_a8.gpio1_24 */
+		>;
+	};
+
+	i2c0_pins: pinmux_i2c0_pins {
+		pinctrl-single,pins = <
+			0x188 (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+			0x18c (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			0x170 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
+		>;
+	};
+
+	clkout2_pin: pinmux_clkout2_pin {
+		pinctrl-single,pins = <
+			0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3)	/* xdma_event_intr1.clkout2 */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 1 */
+			0x110 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxerr.mii1_rxerr */
+			0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txen.mii1_txen */
+			0x118 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxdv.mii1_rxdv */
+			0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd3.mii1_txd3 */
+			0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd2.mii1_txd2 */
+			0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd1.mii1_txd1 */
+			0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mii1_txd0.mii1_txd0 */
+			0x12c (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_txclk.mii1_txclk */
+			0x130 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxclk.mii1_rxclk */
+			0x134 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd3.mii1_rxd3 */
+			0x138 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd2.mii1_rxd2 */
+			0x13c (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd1.mii1_rxd1 */
+			0x140 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mii1_rxd0.mii1_rxd0 */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 reset value */
+			0x110 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			0x160 (PIN_INPUT | MUX_MODE7) /* GPIO0_6 */
+		>;
+	};
+
+	emmc_pins: pinmux_emmc_pins {
+		pinctrl-single,pins = <
+			0x80 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
+			0x84 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
+			0x00 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
+			0x04 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
+			0x08 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
+			0x0c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
+			0x10 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
+			0x14 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
+			0x18 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
+			0x1c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
+		>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+
+	control@44e10000 {
+		status = "okay";
+	};
+
+	usb-phy@47401300 {
+		status = "okay";
+	};
+
+	usb-phy@47401b00 {
+		status = "okay";
+	};
+
+	usb@47401000 {
+		status = "okay";
+	};
+
+	usb@47401800 {
+		status = "okay";
+		dr_mode = "host";
+	};
+
+	dma-controller@07402000  {
+		status = "okay";
+	};
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tps: tps@24 {
+		reg = <0x24>;
+	};
+
 };
 
 /include/ "tps65217.dtsi"
@@ -260,3 +288,12 @@
 	pinctrl-0 = <&davinci_mdio_default>;
 	pinctrl-1 = <&davinci_mdio_sleep>;
 };
+
+&mmc1 {
+	status = "okay";
+	bus-width = <0x4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+};
diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
index 7993c48..94ee427 100644
--- a/arch/arm/boot/dts/am335x-bone.dts
+++ b/arch/arm/boot/dts/am335x-bone.dts
@@ -9,3 +9,21 @@
 
 #include "am33xx.dtsi"
 #include "am335x-bone-common.dtsi"
+
+&ldo3_reg {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-always-on;
+};
+
+&mmc1 {
+	vmmc-supply = <&ldo3_reg>;
+};
+
+&sham {
+	status = "okay";
+};
+
+&aes {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
index 197cadf..6b71ad9 100644
--- a/arch/arm/boot/dts/am335x-boneblack.dts
+++ b/arch/arm/boot/dts/am335x-boneblack.dts
@@ -15,3 +15,64 @@
 	regulator-max-microvolt = <1800000>;
 	regulator-always-on;
 };
+
+&mmc1 {
+	vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&mmc2 {
+	vmmc-supply = <&vmmcsd_fixed>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_pins>;
+	bus-width = <8>;
+	status = "okay";
+	ti,vcc-aux-disable-is-sleep;
+};
+
+&am33xx_pinmux {
+	nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
+		pinctrl-single,pins = <
+			0x1b0 0x03      /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
+			0xa0 0x08       /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xa4 0x08       /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xa8 0x08       /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xac 0x08       /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xb0 0x08       /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xb4 0x08       /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xb8 0x08       /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xbc 0x08       /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xc0 0x08       /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xc4 0x08       /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xc8 0x08       /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xcc 0x08       /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xd0 0x08       /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xd4 0x08       /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xd8 0x08       /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xdc 0x08       /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */
+			0xe0 0x00       /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+			0xe4 0x00       /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+			0xe8 0x00       /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+			0xec 0x00       /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */
+		>;
+	};
+	nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
+		pinctrl-single,pins = <
+			0x1b0 0x03      /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */
+		>;
+	};
+};
+
+&lcdc {
+	status = "okay";
+};
+
+/ {
+	hdmi {
+		compatible = "ti,tilcdc,slave";
+		i2c = <&i2c0>;
+		pinctrl-names = "default", "off";
+		pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
+		pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
+		status = "okay";
+	};
+};
diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
index e8ec875..9874294 100644
--- a/arch/arm/boot/dts/am335x-evm.dts
+++ b/arch/arm/boot/dts/am335x-evm.dts
@@ -24,324 +24,6 @@
 		reg = <0x80000000 0x10000000>; /* 256 MB */
 	};
 
-	am33xx_pinmux: pinmux@44e10800 {
-		pinctrl-names = "default";
-		pinctrl-0 = <&matrix_keypad_s0 &volume_keys_s0 &clkout2_pin>;
-
-		matrix_keypad_s0: matrix_keypad_s0 {
-			pinctrl-single,pins = <
-				0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a5.gpio1_21 */
-				0x58 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a6.gpio1_22 */
-				0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a9.gpio1_25 */
-				0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a10.gpio1_26 */
-				0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a11.gpio1_27 */
-			>;
-		};
-
-		volume_keys_s0: volume_keys_s0 {
-			pinctrl-single,pins = <
-				0x150 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* spi0_sclk.gpio0_2 */
-				0x154 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* spi0_d0.gpio0_3 */
-			>;
-		};
-
-		i2c0_pins: pinmux_i2c0_pins {
-			pinctrl-single,pins = <
-				0x188 (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
-				0x18c (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
-			>;
-		};
-
-		i2c1_pins: pinmux_i2c1_pins {
-			pinctrl-single,pins = <
-				0x158 (PIN_INPUT_PULLUP | MUX_MODE2)	/* spi0_d1.i2c1_sda */
-				0x15c (PIN_INPUT_PULLUP | MUX_MODE2)	/* spi0_cs0.i2c1_scl */
-			>;
-		};
-
-		uart0_pins: pinmux_uart0_pins {
-			pinctrl-single,pins = <
-				0x170 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
-				0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
-			>;
-		};
-
-		clkout2_pin: pinmux_clkout2_pin {
-			pinctrl-single,pins = <
-				0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3)	/* xdma_event_intr1.clkout2 */
-			>;
-		};
-
-		nandflash_pins_s0: nandflash_pins_s0 {
-			pinctrl-single,pins = <
-				0x0 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad0.gpmc_ad0 */
-				0x4 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad1.gpmc_ad1 */
-				0x8 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad2.gpmc_ad2 */
-				0xc (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad3.gpmc_ad3 */
-				0x10 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad4.gpmc_ad4 */
-				0x14 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad5.gpmc_ad5 */
-				0x18 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad6.gpmc_ad6 */
-				0x1c (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad7.gpmc_ad7 */
-				0x70 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_wait0.gpmc_wait0 */
-				0x74 (PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_wpn.gpio0_30 */
-				0x7c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_csn0.gpmc_csn0  */
-				0x90 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_advn_ale.gpmc_advn_ale */
-				0x94 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_oen_ren.gpmc_oen_ren */
-				0x98 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_wen.gpmc_wen */
-				0x9c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_be0n_cle.gpmc_be0n_cle */
-			>;
-		};
-
-		ecap0_pins: backlight_pins {
-			pinctrl-single,pins = <
-				0x164 0x0	/* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 */
-			>;
-		};
-
-		cpsw_default: cpsw_default {
-			pinctrl-single,pins = <
-				/* Slave 1 */
-				0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txen.rgmii1_tctl */
-				0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxdv.rgmii1_rctl */
-				0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd3.rgmii1_td3 */
-				0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd2.rgmii1_td2 */
-				0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd1.rgmii1_td1 */
-				0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd0.rgmii1_td0 */
-				0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txclk.rgmii1_tclk */
-				0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxclk.rgmii1_rclk */
-				0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd3.rgmii1_rd3 */
-				0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd2.rgmii1_rd2 */
-				0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd1.rgmii1_rd1 */
-				0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd0.rgmii1_rd0 */
-			>;
-		};
-
-		cpsw_sleep: cpsw_sleep {
-			pinctrl-single,pins = <
-				/* Slave 1 reset value */
-				0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-			>;
-		};
-
-		davinci_mdio_default: davinci_mdio_default {
-			pinctrl-single,pins = <
-				/* MDIO */
-				0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
-				0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
-			>;
-		};
-
-		davinci_mdio_sleep: davinci_mdio_sleep {
-			pinctrl-single,pins = <
-				/* MDIO reset value */
-				0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-			>;
-		};
-	};
-
-	ocp {
-		uart0: serial@44e09000 {
-			pinctrl-names = "default";
-			pinctrl-0 = <&uart0_pins>;
-
-			status = "okay";
-		};
-
-		i2c0: i2c@44e0b000 {
-			pinctrl-names = "default";
-			pinctrl-0 = <&i2c0_pins>;
-
-			status = "okay";
-			clock-frequency = <400000>;
-
-			tps: tps@2d {
-				reg = <0x2d>;
-			};
-		};
-
-		musb: usb@47400000 {
-			status = "okay";
-
-			control@44e10000 {
-				status = "okay";
-			};
-
-			usb-phy@47401300 {
-				status = "okay";
-			};
-
-			usb-phy@47401b00 {
-				status = "okay";
-			};
-
-			usb@47401000 {
-				status = "okay";
-			};
-
-			usb@47401800 {
-				status = "okay";
-				dr_mode = "host";
-			};
-
-			dma-controller@07402000  {
-				status = "okay";
-			};
-		};
-
-		i2c1: i2c@4802a000 {
-			pinctrl-names = "default";
-			pinctrl-0 = <&i2c1_pins>;
-
-			status = "okay";
-			clock-frequency = <100000>;
-
-			lis331dlh: lis331dlh@18 {
-				compatible = "st,lis331dlh", "st,lis3lv02d";
-				reg = <0x18>;
-				Vdd-supply = <&lis3_reg>;
-				Vdd_IO-supply = <&lis3_reg>;
-
-				st,click-single-x;
-				st,click-single-y;
-				st,click-single-z;
-				st,click-thresh-x = <10>;
-				st,click-thresh-y = <10>;
-				st,click-thresh-z = <10>;
-				st,irq1-click;
-				st,irq2-click;
-				st,wakeup-x-lo;
-				st,wakeup-x-hi;
-				st,wakeup-y-lo;
-				st,wakeup-y-hi;
-				st,wakeup-z-lo;
-				st,wakeup-z-hi;
-				st,min-limit-x = <120>;
-				st,min-limit-y = <120>;
-				st,min-limit-z = <140>;
-				st,max-limit-x = <550>;
-				st,max-limit-y = <550>;
-				st,max-limit-z = <750>;
-			};
-
-			tsl2550: tsl2550@39 {
-				compatible = "taos,tsl2550";
-				reg = <0x39>;
-			};
-
-			tmp275: tmp275@48 {
-				compatible = "ti,tmp275";
-				reg = <0x48>;
-			};
-		};
-
-		elm: elm@48080000 {
-			status = "okay";
-		};
-
-		epwmss0: epwmss@48300000 {
-			status = "okay";
-
-			ecap0: ecap@48300100 {
-				status = "okay";
-				pinctrl-names = "default";
-				pinctrl-0 = <&ecap0_pins>;
-			};
-		};
-
-		gpmc: gpmc@50000000 {
-			status = "okay";
-			pinctrl-names = "default";
-			pinctrl-0 = <&nandflash_pins_s0>;
-			ranges = <0 0 0x08000000 0x10000000>;	/* CS0: NAND */
-			nand@0,0 {
-				reg = <0 0 0>; /* CS0, offset 0 */
-				nand-bus-width = <8>;
-				ti,nand-ecc-opt = "bch8";
-				gpmc,device-nand = "true";
-				gpmc,device-width = <1>;
-				gpmc,sync-clk-ps = <0>;
-				gpmc,cs-on-ns = <0>;
-				gpmc,cs-rd-off-ns = <44>;
-				gpmc,cs-wr-off-ns = <44>;
-				gpmc,adv-on-ns = <6>;
-				gpmc,adv-rd-off-ns = <34>;
-				gpmc,adv-wr-off-ns = <44>;
-				gpmc,we-on-ns = <0>;
-				gpmc,we-off-ns = <40>;
-				gpmc,oe-on-ns = <0>;
-				gpmc,oe-off-ns = <54>;
-				gpmc,access-ns = <64>;
-				gpmc,rd-cycle-ns = <82>;
-				gpmc,wr-cycle-ns = <82>;
-				gpmc,wait-on-read = "true";
-				gpmc,wait-on-write = "true";
-				gpmc,bus-turnaround-ns = <0>;
-				gpmc,cycle2cycle-delay-ns = <0>;
-				gpmc,clk-activation-ns = <0>;
-				gpmc,wait-monitoring-ns = <0>;
-				gpmc,wr-access-ns = <40>;
-				gpmc,wr-data-mux-bus-ns = <0>;
-
-				#address-cells = <1>;
-				#size-cells = <1>;
-				elm_id = <&elm>;
-
-				/* MTD partition table */
-				partition@0 {
-					label = "SPL1";
-					reg = <0x00000000 0x000020000>;
-				};
-
-				partition@1 {
-					label = "SPL2";
-					reg = <0x00020000 0x00020000>;
-				};
-
-				partition@2 {
-					label = "SPL3";
-					reg = <0x00040000 0x00020000>;
-				};
-
-				partition@3 {
-					label = "SPL4";
-					reg = <0x00060000 0x00020000>;
-				};
-
-				partition@4 {
-					label = "U-boot";
-					reg = <0x00080000 0x001e0000>;
-				};
-
-				partition@5 {
-					label = "environment";
-					reg = <0x00260000 0x00020000>;
-				};
-
-				partition@6 {
-					label = "Kernel";
-					reg = <0x00280000 0x00500000>;
-				};
-
-				partition@7 {
-					label = "File-System";
-					reg = <0x00780000 0x0F880000>;
-				};
-			};
-		};
-	};
-
 	vbat: fixedregulator@0 {
 		compatible = "regulator-fixed";
 		regulator-name = "vbat";
@@ -403,10 +85,447 @@
 		brightness-levels = <0 51 53 56 62 75 101 152 255>;
 		default-brightness-level = <8>;
 	};
+
+	panel {
+		compatible = "ti,tilcdc,panel";
+		status = "okay";
+		pinctrl-names = "default";
+		pinctrl-0 = <&lcd_pins_s0>;
+		panel-info {
+			ac-bias           = <255>;
+			ac-bias-intrpt    = <0>;
+			dma-burst-sz      = <16>;
+			bpp               = <32>;
+			fdd               = <0x80>;
+			sync-edge         = <0>;
+			sync-ctrl         = <1>;
+			raster-order      = <0>;
+			fifo-th           = <0>;
+		};
+
+		display-timings {
+			800x480p62 {
+				clock-frequency = <30000000>;
+				hactive = <800>;
+				vactive = <480>;
+				hfront-porch = <39>;
+				hback-porch = <39>;
+				hsync-len = <47>;
+				vback-porch = <29>;
+				vfront-porch = <13>;
+				vsync-len = <2>;
+				hsync-active = <1>;
+				vsync-active = <1>;
+			};
+		};
+	};
+
+	sound {
+		compatible = "ti,da830-evm-audio";
+		ti,model = "AM335x-EVM";
+		ti,audio-codec = <&tlv320aic3106>;
+		ti,mcasp-controller = <&mcasp1>;
+		ti,codec-clock-rate = <12000000>;
+		ti,audio-routing =
+			"Headphone Jack",       "HPLOUT",
+			"Headphone Jack",       "HPROUT",
+			"LINE1L",               "Line In",
+			"LINE1R",               "Line In";
+	};
+};
+
+&am33xx_pinmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&matrix_keypad_s0 &volume_keys_s0 &clkout2_pin>;
+
+	matrix_keypad_s0: matrix_keypad_s0 {
+		pinctrl-single,pins = <
+			0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a5.gpio1_21 */
+			0x58 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a6.gpio1_22 */
+			0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a9.gpio1_25 */
+			0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a10.gpio1_26 */
+			0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a11.gpio1_27 */
+		>;
+	};
+
+	volume_keys_s0: volume_keys_s0 {
+		pinctrl-single,pins = <
+			0x150 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* spi0_sclk.gpio0_2 */
+			0x154 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* spi0_d0.gpio0_3 */
+		>;
+	};
+
+	i2c0_pins: pinmux_i2c0_pins {
+		pinctrl-single,pins = <
+			0x188 (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+			0x18c (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	i2c1_pins: pinmux_i2c1_pins {
+		pinctrl-single,pins = <
+			0x158 (PIN_INPUT_PULLUP | MUX_MODE2)	/* spi0_d1.i2c1_sda */
+			0x15c (PIN_INPUT_PULLUP | MUX_MODE2)	/* spi0_cs0.i2c1_scl */
+		>;
+	};
+
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			0x170 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
+		>;
+	};
+
+	clkout2_pin: pinmux_clkout2_pin {
+		pinctrl-single,pins = <
+			0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3)	/* xdma_event_intr1.clkout2 */
+		>;
+	};
+
+	nandflash_pins_s0: nandflash_pins_s0 {
+		pinctrl-single,pins = <
+			0x0 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad0.gpmc_ad0 */
+			0x4 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad1.gpmc_ad1 */
+			0x8 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad2.gpmc_ad2 */
+			0xc (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad3.gpmc_ad3 */
+			0x10 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad4.gpmc_ad4 */
+			0x14 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad5.gpmc_ad5 */
+			0x18 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad6.gpmc_ad6 */
+			0x1c (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad7.gpmc_ad7 */
+			0x70 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_wait0.gpmc_wait0 */
+			0x74 (PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_wpn.gpio0_30 */
+			0x7c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_csn0.gpmc_csn0  */
+			0x90 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_advn_ale.gpmc_advn_ale */
+			0x94 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_oen_ren.gpmc_oen_ren */
+			0x98 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_wen.gpmc_wen */
+			0x9c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_be0n_cle.gpmc_be0n_cle */
+		>;
+	};
+
+	ecap0_pins: backlight_pins {
+		pinctrl-single,pins = <
+			0x164 0x0	/* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 1 */
+			0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txen.rgmii1_tctl */
+			0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxdv.rgmii1_rctl */
+			0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd3.rgmii1_td3 */
+			0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd2.rgmii1_td2 */
+			0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd1.rgmii1_td1 */
+			0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd0.rgmii1_td0 */
+			0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txclk.rgmii1_tclk */
+			0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxclk.rgmii1_rclk */
+			0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd3.rgmii1_rd3 */
+			0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd2.rgmii1_rd2 */
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd1.rgmii1_rd1 */
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd0.rgmii1_rd0 */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 reset value */
+			0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	lcd_pins_s0: lcd_pins_s0 {
+		pinctrl-single,pins = <
+			0x20 0x01	/* gpmc_ad8.lcd_data16, OUTPUT | MODE1 */
+			0x24 0x01	/* gpmc_ad9.lcd_data17, OUTPUT | MODE1 */
+			0x28 0x01	/* gpmc_ad10.lcd_data18, OUTPUT | MODE1 */
+			0x2c 0x01	/* gpmc_ad11.lcd_data19, OUTPUT | MODE1 */
+			0x30 0x01	/* gpmc_ad12.lcd_data20, OUTPUT | MODE1 */
+			0x34 0x01	/* gpmc_ad13.lcd_data21, OUTPUT | MODE1 */
+			0x38 0x01	/* gpmc_ad14.lcd_data22, OUTPUT | MODE1 */
+			0x3c 0x01	/* gpmc_ad15.lcd_data23, OUTPUT | MODE1 */
+			0xa0 0x00	/* lcd_data0.lcd_data0, OUTPUT | MODE0 */
+			0xa4 0x00	/* lcd_data1.lcd_data1, OUTPUT | MODE0 */
+			0xa8 0x00	/* lcd_data2.lcd_data2, OUTPUT | MODE0 */
+			0xac 0x00	/* lcd_data3.lcd_data3, OUTPUT | MODE0 */
+			0xb0 0x00	/* lcd_data4.lcd_data4, OUTPUT | MODE0 */
+			0xb4 0x00	/* lcd_data5.lcd_data5, OUTPUT | MODE0 */
+			0xb8 0x00	/* lcd_data6.lcd_data6, OUTPUT | MODE0 */
+			0xbc 0x00	/* lcd_data7.lcd_data7, OUTPUT | MODE0 */
+			0xc0 0x00	/* lcd_data8.lcd_data8, OUTPUT | MODE0 */
+			0xc4 0x00	/* lcd_data9.lcd_data9, OUTPUT | MODE0 */
+			0xc8 0x00	/* lcd_data10.lcd_data10, OUTPUT | MODE0 */
+			0xcc 0x00	/* lcd_data11.lcd_data11, OUTPUT | MODE0 */
+			0xd0 0x00	/* lcd_data12.lcd_data12, OUTPUT | MODE0 */
+			0xd4 0x00	/* lcd_data13.lcd_data13, OUTPUT | MODE0 */
+			0xd8 0x00	/* lcd_data14.lcd_data14, OUTPUT | MODE0 */
+			0xdc 0x00	/* lcd_data15.lcd_data15, OUTPUT | MODE0 */
+			0xe0 0x00	/* lcd_vsync.lcd_vsync, OUTPUT | MODE0 */
+			0xe4 0x00	/* lcd_hsync.lcd_hsync, OUTPUT | MODE0 */
+			0xe8 0x00	/* lcd_pclk.lcd_pclk, OUTPUT | MODE0 */
+			0xec 0x00	/* lcd_ac_bias_en.lcd_ac_bias_en, OUTPUT | MODE0 */
+		>;
+	};
+
+	am335x_evm_audio_pins: am335x_evm_audio_pins {
+		pinctrl-single,pins = <
+			0x10c (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_rx_dv.mcasp1_aclkx */
+			0x110 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_txd3.mcasp1_fsx */
+			0x108 (PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* mii1_col.mcasp1_axr2 */
+			0x144 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */
+		>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tps: tps@2d {
+		reg = <0x2d>;
+	};
+};
+
+&usb {
+	status = "okay";
+
+	control@44e10000 {
+		status = "okay";
+	};
+
+	usb-phy@47401300 {
+		status = "okay";
+	};
+
+	usb-phy@47401b00 {
+		status = "okay";
+	};
+
+	usb@47401000 {
+		status = "okay";
+	};
+
+	usb@47401800 {
+		status = "okay";
+		dr_mode = "host";
+	};
+
+	dma-controller@07402000  {
+		status = "okay";
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+
+	status = "okay";
+	clock-frequency = <100000>;
+
+	lis331dlh: lis331dlh@18 {
+		compatible = "st,lis331dlh", "st,lis3lv02d";
+		reg = <0x18>;
+		Vdd-supply = <&lis3_reg>;
+		Vdd_IO-supply = <&lis3_reg>;
+
+		st,click-single-x;
+		st,click-single-y;
+		st,click-single-z;
+		st,click-thresh-x = <10>;
+		st,click-thresh-y = <10>;
+		st,click-thresh-z = <10>;
+		st,irq1-click;
+		st,irq2-click;
+		st,wakeup-x-lo;
+		st,wakeup-x-hi;
+		st,wakeup-y-lo;
+		st,wakeup-y-hi;
+		st,wakeup-z-lo;
+		st,wakeup-z-hi;
+		st,min-limit-x = <120>;
+		st,min-limit-y = <120>;
+		st,min-limit-z = <140>;
+		st,max-limit-x = <550>;
+		st,max-limit-y = <550>;
+		st,max-limit-z = <750>;
+	};
+
+	tsl2550: tsl2550@39 {
+		compatible = "taos,tsl2550";
+		reg = <0x39>;
+	};
+
+	tmp275: tmp275@48 {
+		compatible = "ti,tmp275";
+		reg = <0x48>;
+	};
+
+	tlv320aic3106: tlv320aic3106@1b {
+		compatible = "ti,tlv320aic3106";
+		reg = <0x1b>;
+		status = "okay";
+
+		/* Regulators */
+		AVDD-supply = <&vaux2_reg>;
+		IOVDD-supply = <&vaux2_reg>;
+		DRVDD-supply = <&vaux2_reg>;
+		DVDD-supply = <&vbat>;
+	};
+};
+
+&lcdc {
+	status = "okay";
+};
+
+&elm {
+	status = "okay";
+};
+
+&epwmss0 {
+	status = "okay";
+
+	ecap0: ecap@48300100 {
+		status = "okay";
+		pinctrl-names = "default";
+		pinctrl-0 = <&ecap0_pins>;
+	};
+};
+
+&gpmc {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&nandflash_pins_s0>;
+	ranges = <0 0 0x08000000 0x10000000>;	/* CS0: NAND */
+	nand@0,0 {
+		reg = <0 0 0>; /* CS0, offset 0 */
+		nand-bus-width = <8>;
+		ti,nand-ecc-opt = "bch8";
+		gpmc,device-nand = "true";
+		gpmc,device-width = <1>;
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <44>;
+		gpmc,cs-wr-off-ns = <44>;
+		gpmc,adv-on-ns = <6>;
+		gpmc,adv-rd-off-ns = <34>;
+		gpmc,adv-wr-off-ns = <44>;
+		gpmc,we-on-ns = <0>;
+		gpmc,we-off-ns = <40>;
+		gpmc,oe-on-ns = <0>;
+		gpmc,oe-off-ns = <54>;
+		gpmc,access-ns = <64>;
+		gpmc,rd-cycle-ns = <82>;
+		gpmc,wr-cycle-ns = <82>;
+		gpmc,wait-on-read = "true";
+		gpmc,wait-on-write = "true";
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,clk-activation-ns = <0>;
+		gpmc,wait-monitoring-ns = <0>;
+		gpmc,wr-access-ns = <40>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		elm_id = <&elm>;
+
+		/* MTD partition table */
+		partition@0 {
+			label = "SPL1";
+			reg = <0x00000000 0x000020000>;
+		};
+
+		partition@1 {
+			label = "SPL2";
+			reg = <0x00020000 0x00020000>;
+		};
+
+		partition@2 {
+			label = "SPL3";
+			reg = <0x00040000 0x00020000>;
+		};
+
+		partition@3 {
+			label = "SPL4";
+			reg = <0x00060000 0x00020000>;
+		};
+
+		partition@4 {
+			label = "U-boot";
+			reg = <0x00080000 0x001e0000>;
+		};
+
+		partition@5 {
+			label = "environment";
+			reg = <0x00260000 0x00020000>;
+		};
+
+		partition@6 {
+			label = "Kernel";
+			reg = <0x00280000 0x00500000>;
+		};
+
+		partition@7 {
+			label = "File-System";
+			reg = <0x00780000 0x0F880000>;
+		};
+	};
 };
 
 #include "tps65910.dtsi"
 
+&mcasp1 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&am335x_evm_audio_pins>;
+
+		status = "okay";
+
+		op-mode = <0>;          /* MCASP_IIS_MODE */
+		tdm-slots = <2>;
+		/* 4 serializers */
+		serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
+			0 0 1 2
+		>;
+		tx-num-evt = <1>;
+		rx-num-evt = <1>;
+};
+
 &tps {
 	vcc1-supply = <&vbat>;
 	vcc2-supply = <&vbat>;
@@ -477,6 +596,8 @@
 		};
 
 		vmmc_reg: regulator@12 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3300000>;
 			regulator-always-on;
 		};
 	};
@@ -517,3 +638,17 @@
 		ti,adc-channels = <4 5 6 7>;
 	};
 };
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&vmmc_reg>;
+	bus-width = <4>;
+};
+
+&sham {
+	status = "okay";
+};
+
+&aes {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
index 4f339fa..03febf8 100644
--- a/arch/arm/boot/dts/am335x-evmsk.dts
+++ b/arch/arm/boot/dts/am335x-evmsk.dts
@@ -31,210 +31,6 @@
 		reg = <0x80000000 0x10000000>; /* 256 MB */
 	};
 
-	am33xx_pinmux: pinmux@44e10800 {
-		pinctrl-names = "default";
-		pinctrl-0 = <&gpio_keys_s0 &clkout2_pin>;
-
-		user_leds_s0: user_leds_s0 {
-			pinctrl-single,pins = <
-				0x10 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad4.gpio1_4 */
-				0x14 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad5.gpio1_5 */
-				0x18 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad6.gpio1_6 */
-				0x1c (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad7.gpio1_7 */
-			>;
-		};
-
-		gpio_keys_s0: gpio_keys_s0 {
-			pinctrl-single,pins = <
-				0x94 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_oen_ren.gpio2_3 */
-				0x90 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_advn_ale.gpio2_2 */
-				0x70 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_wait0.gpio0_30 */
-				0x9c (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ben0_cle.gpio2_5 */
-			>;
-		};
-
-		i2c0_pins: pinmux_i2c0_pins {
-			pinctrl-single,pins = <
-				0x188 (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
-				0x18c (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
-			>;
-		};
-
-		uart0_pins: pinmux_uart0_pins {
-			pinctrl-single,pins = <
-				0x170 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
-				0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)		/* uart0_txd.uart0_txd */
-			>;
-		};
-
-		clkout2_pin: pinmux_clkout2_pin {
-			pinctrl-single,pins = <
-				0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3)		/* xdma_event_intr1.clkout2 */
-			>;
-		};
-
-		ecap2_pins: backlight_pins {
-			pinctrl-single,pins = <
-				0x19c 0x4	/* mcasp0_ahclkr.ecap2_in_pwm2_out MODE4 */
-			>;
-		};
-
-		cpsw_default: cpsw_default {
-			pinctrl-single,pins = <
-				/* Slave 1 */
-				0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txen.rgmii1_tctl */
-				0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxdv.rgmii1_rctl */
-				0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd3.rgmii1_td3 */
-				0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd2.rgmii1_td2 */
-				0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd1.rgmii1_td1 */
-				0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd0.rgmii1_td0 */
-				0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txclk.rgmii1_tclk */
-				0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxclk.rgmii1_rclk */
-				0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd3.rgmii1_rd3 */
-				0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd2.rgmii1_rd2 */
-				0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd1.rgmii1_rd1 */
-				0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd0.rgmii1_rd0 */
-
-				/* Slave 2 */
-				0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a0.rgmii2_tctl */
-				0x44 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a1.rgmii2_rctl */
-				0x48 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a2.rgmii2_td3 */
-				0x4c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a3.rgmii2_td2 */
-				0x50 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a4.rgmii2_td1 */
-				0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a5.rgmii2_td0 */
-				0x58 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a6.rgmii2_tclk */
-				0x5c (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a7.rgmii2_rclk */
-				0x60 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a8.rgmii2_rd3 */
-				0x64 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a9.rgmii2_rd2 */
-				0x68 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a10.rgmii2_rd1 */
-				0x6c (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a11.rgmii2_rd0 */
-			>;
-		};
-
-		cpsw_sleep: cpsw_sleep {
-			pinctrl-single,pins = <
-				/* Slave 1 reset value */
-				0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-
-				/* Slave 2 reset value*/
-				0x40 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x44 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x48 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x4c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x50 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x54 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x58 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x5c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x60 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-			>;
-		};
-
-		davinci_mdio_default: davinci_mdio_default {
-			pinctrl-single,pins = <
-				/* MDIO */
-				0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
-				0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
-			>;
-		};
-
-		davinci_mdio_sleep: davinci_mdio_sleep {
-			pinctrl-single,pins = <
-				/* MDIO reset value */
-				0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
-				0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
-			>;
-		};
-	};
-
-	ocp {
-		uart0: serial@44e09000 {
-			pinctrl-names = "default";
-			pinctrl-0 = <&uart0_pins>;
-
-			status = "okay";
-		};
-
-		i2c0: i2c@44e0b000 {
-			pinctrl-names = "default";
-			pinctrl-0 = <&i2c0_pins>;
-
-			status = "okay";
-			clock-frequency = <400000>;
-
-			tps: tps@2d {
-				reg = <0x2d>;
-			};
-
-			lis331dlh: lis331dlh@18 {
-				compatible = "st,lis331dlh", "st,lis3lv02d";
-				reg = <0x18>;
-				Vdd-supply = <&lis3_reg>;
-				Vdd_IO-supply = <&lis3_reg>;
-
-				st,click-single-x;
-				st,click-single-y;
-				st,click-single-z;
-				st,click-thresh-x = <10>;
-				st,click-thresh-y = <10>;
-				st,click-thresh-z = <10>;
-				st,irq1-click;
-				st,irq2-click;
-				st,wakeup-x-lo;
-				st,wakeup-x-hi;
-				st,wakeup-y-lo;
-				st,wakeup-y-hi;
-				st,wakeup-z-lo;
-				st,wakeup-z-hi;
-				st,min-limit-x = <120>;
-				st,min-limit-y = <120>;
-				st,min-limit-z = <140>;
-				st,max-limit-x = <550>;
-				st,max-limit-y = <550>;
-				st,max-limit-z = <750>;
-			};
-		};
-
-		musb: usb@47400000 {
-			status = "okay";
-
-			control@44e10000 {
-				status = "okay";
-			};
-
-			usb-phy@47401300 {
-				status = "okay";
-			};
-
-			usb@47401000 {
-				status = "okay";
-			};
-		};
-
-		epwmss2: epwmss@48304000 {
-			status = "okay";
-
-			ecap2: ecap@48304100 {
-				status = "okay";
-				pinctrl-names = "default";
-				pinctrl-0 = <&ecap2_pins>;
-			};
-		};
-	};
-
 	vbat: fixedregulator@0 {
 		compatible = "regulator-fixed";
 		regulator-name = "vbat";
@@ -319,6 +115,240 @@
 		brightness-levels = <0 58 61 66 75 90 125 170 255>;
 		default-brightness-level = <8>;
 	};
+
+	sound {
+		compatible = "ti,da830-evm-audio";
+		ti,model = "AM335x-EVMSK";
+		ti,audio-codec = <&tlv320aic3106>;
+		ti,mcasp-controller = <&mcasp1>;
+		ti,codec-clock-rate = <24576000>;
+		ti,audio-routing =
+			"Headphone Jack",       "HPLOUT",
+			"Headphone Jack",       "HPROUT";
+	};
+};
+
+&am33xx_pinmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&gpio_keys_s0 &clkout2_pin>;
+
+	user_leds_s0: user_leds_s0 {
+		pinctrl-single,pins = <
+			0x10 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad4.gpio1_4 */
+			0x14 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad5.gpio1_5 */
+			0x18 (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad6.gpio1_6 */
+			0x1c (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ad7.gpio1_7 */
+		>;
+	};
+
+	gpio_keys_s0: gpio_keys_s0 {
+		pinctrl-single,pins = <
+			0x94 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_oen_ren.gpio2_3 */
+			0x90 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_advn_ale.gpio2_2 */
+			0x70 (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_wait0.gpio0_30 */
+			0x9c (PIN_INPUT_PULLDOWN | MUX_MODE7)	/* gpmc_ben0_cle.gpio2_5 */
+		>;
+	};
+
+	i2c0_pins: pinmux_i2c0_pins {
+		pinctrl-single,pins = <
+			0x188 (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+			0x18c (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			0x170 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)		/* uart0_txd.uart0_txd */
+		>;
+	};
+
+	clkout2_pin: pinmux_clkout2_pin {
+		pinctrl-single,pins = <
+			0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3)		/* xdma_event_intr1.clkout2 */
+		>;
+	};
+
+	ecap2_pins: backlight_pins {
+		pinctrl-single,pins = <
+			0x19c 0x4	/* mcasp0_ahclkr.ecap2_in_pwm2_out MODE4 */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 1 */
+			0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txen.rgmii1_tctl */
+			0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxdv.rgmii1_rctl */
+			0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd3.rgmii1_td3 */
+			0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd2.rgmii1_td2 */
+			0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd1.rgmii1_td1 */
+			0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd0.rgmii1_td0 */
+			0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txclk.rgmii1_tclk */
+			0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxclk.rgmii1_rclk */
+			0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd3.rgmii1_rd3 */
+			0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd2.rgmii1_rd2 */
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd1.rgmii1_rd1 */
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd0.rgmii1_rd0 */
+
+			/* Slave 2 */
+			0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a0.rgmii2_tctl */
+			0x44 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a1.rgmii2_rctl */
+			0x48 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a2.rgmii2_td3 */
+			0x4c (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a3.rgmii2_td2 */
+			0x50 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a4.rgmii2_td1 */
+			0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a5.rgmii2_td0 */
+			0x58 (PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a6.rgmii2_tclk */
+			0x5c (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a7.rgmii2_rclk */
+			0x60 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a8.rgmii2_rd3 */
+			0x64 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a9.rgmii2_rd2 */
+			0x68 (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a10.rgmii2_rd1 */
+			0x6c (PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a11.rgmii2_rd0 */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 reset value */
+			0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+
+			/* Slave 2 reset value*/
+			0x40 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x44 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x48 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x4c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x50 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x54 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x58 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x5c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x60 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	mcasp1_pins: mcasp1_pins {
+		pinctrl-single,pins = <
+			0x10c (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */
+			0x110 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_rxerr.mcasp1_fsx */
+			0x108 (PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* mii1_col.mcasp1_axr2 */
+			0x144 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */
+		>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tps: tps@2d {
+		reg = <0x2d>;
+	};
+
+	lis331dlh: lis331dlh@18 {
+		compatible = "st,lis331dlh", "st,lis3lv02d";
+		reg = <0x18>;
+		Vdd-supply = <&lis3_reg>;
+		Vdd_IO-supply = <&lis3_reg>;
+
+		st,click-single-x;
+		st,click-single-y;
+		st,click-single-z;
+		st,click-thresh-x = <10>;
+		st,click-thresh-y = <10>;
+		st,click-thresh-z = <10>;
+		st,irq1-click;
+		st,irq2-click;
+		st,wakeup-x-lo;
+		st,wakeup-x-hi;
+		st,wakeup-y-lo;
+		st,wakeup-y-hi;
+		st,wakeup-z-lo;
+		st,wakeup-z-hi;
+		st,min-limit-x = <120>;
+		st,min-limit-y = <120>;
+		st,min-limit-z = <140>;
+		st,max-limit-x = <550>;
+		st,max-limit-y = <550>;
+		st,max-limit-z = <750>;
+	};
+
+	tlv320aic3106: tlv320aic3106@1b {
+		compatible = "ti,tlv320aic3106";
+		reg = <0x1b>;
+		status = "okay";
+
+		/* Regulators */
+		AVDD-supply = <&vaux2_reg>;
+		IOVDD-supply = <&vaux2_reg>;
+		DRVDD-supply = <&vaux2_reg>;
+		DVDD-supply = <&vbat>;
+	};
+};
+
+&usb {
+	status = "okay";
+
+	control@44e10000 {
+		status = "okay";
+	};
+
+	usb-phy@47401300 {
+		status = "okay";
+	};
+
+	usb@47401000 {
+		status = "okay";
+	};
+};
+
+&epwmss2 {
+	status = "okay";
+
+	ecap2: ecap@48304100 {
+		status = "okay";
+		pinctrl-names = "default";
+		pinctrl-0 = <&ecap2_pins>;
+	};
 };
 
 #include "tps65910.dtsi"
@@ -393,6 +423,8 @@
 		};
 
 		vmmc_reg: regulator@12 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3300000>;
 			regulator-always-on;
 		};
 	};
@@ -419,3 +451,37 @@
 	phy_id = <&davinci_mdio>, <1>;
 	phy-mode = "rgmii-txid";
 };
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&vmmc_reg>;
+	bus-width = <4>;
+};
+
+&sham {
+	status = "okay";
+};
+
+&aes {
+	status = "okay";
+};
+
+&gpio0 {
+	ti,no-reset-on-init;
+};
+
+&mcasp1 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&mcasp1_pins>;
+
+		status = "okay";
+
+		op-mode = <0>;          /* MCASP_IIS_MODE */
+		tdm-slots = <2>;
+		/* 4 serializers */
+		serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
+			0 0 1 2
+		>;
+		tx-num-evt = <1>;
+		rx-num-evt = <1>;
+};
diff --git a/arch/arm/boot/dts/am335x-igep0033.dtsi b/arch/arm/boot/dts/am335x-igep0033.dtsi
new file mode 100644
index 0000000..6196244
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-igep0033.dtsi
@@ -0,0 +1,278 @@
+/*
+ * am335x-igep0033.dtsi - Device Tree file for IGEP COM AQUILA AM335x
+ *
+ * Copyright (C) 2013 ISEE 2007 SL - http://www.isee.biz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+#include "am33xx.dtsi"
+
+/ {
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&vdd1_reg>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	leds {
+		pinctrl-names = "default";
+		pinctrl-0 = <&leds_pins>;
+
+		compatible = "gpio-leds";
+
+		led@0 {
+			label = "com:green:user";
+			gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
+			default-state = "on";
+		};
+	};
+
+	vbat: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+	};
+
+	vmmc: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+};
+
+&am33xx_pinmux {
+	i2c0_pins: pinmux_i2c0_pins {
+		pinctrl-single,pins = <
+			0x188 (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+			0x18c (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	nandflash_pins: pinmux_nandflash_pins {
+		pinctrl-single,pins = <
+			0x0 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad0.gpmc_ad0 */
+			0x4 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad1.gpmc_ad1 */
+			0x8 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad2.gpmc_ad2 */
+			0xc (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad3.gpmc_ad3 */
+			0x10 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad4.gpmc_ad4 */
+			0x14 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad5.gpmc_ad5 */
+			0x18 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad6.gpmc_ad6 */
+			0x1c (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad7.gpmc_ad7 */
+			0x70 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_wait0.gpmc_wait0 */
+			0x74 (PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_wpn.gpio0_30 */
+			0x7c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_csn0.gpmc_csn0 */
+			0x90 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_advn_ale.gpmc_advn_ale */
+			0x94 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_oen_ren.gpmc_oen_ren */
+			0x98 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_wen.gpmc_wen */
+			0x9c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_be0n_cle.gpmc_be0n_cle */
+		>;
+	};
+
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			0x170 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
+		>;
+	};
+
+	leds_pins: pinmux_leds_pins {
+		pinctrl-single,pins = <
+			0x5c (PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* gpmc_a7.gpio1_23 */
+		>;
+	};
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <1>;
+};
+
+&elm {
+	status = "okay";
+};
+
+&gpmc {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&nandflash_pins>;
+
+	ranges = <0 0 0x08000000 0x10000000>;	/* CS0: NAND */
+
+	nand@0,0 {
+		reg = <0 0 0>; /* CS0, offset 0 */
+		nand-bus-width = <8>;
+		ti,nand-ecc-opt = "bch8";
+		gpmc,device-nand = "true";
+		gpmc,device-width = <1>;
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <44>;
+		gpmc,cs-wr-off-ns = <44>;
+		gpmc,adv-on-ns = <6>;
+		gpmc,adv-rd-off-ns = <34>;
+		gpmc,adv-wr-off-ns = <44>;
+		gpmc,we-on-ns = <0>;
+		gpmc,we-off-ns = <40>;
+		gpmc,oe-on-ns = <0>;
+		gpmc,oe-off-ns = <54>;
+		gpmc,access-ns = <64>;
+		gpmc,rd-cycle-ns = <82>;
+		gpmc,wr-cycle-ns = <82>;
+		gpmc,wait-on-read = "true";
+		gpmc,wait-on-write = "true";
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,clk-activation-ns = <0>;
+		gpmc,wait-monitoring-ns = <0>;
+		gpmc,wr-access-ns = <40>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		elm_id = <&elm>;
+
+		/* MTD partition table */
+		partition@0 {
+			label = "SPL";
+			reg = <0x00000000 0x000080000>;
+		};
+
+		partition@1 {
+			label = "U-boot";
+			reg = <0x00080000 0x001e0000>;
+		};
+
+		partition@2 {
+			label = "U-Boot Env";
+			reg = <0x00260000 0x00020000>;
+		};
+
+		partition@3 {
+			label = "Kernel";
+			reg = <0x00280000 0x00500000>;
+		};
+
+		partition@4 {
+			label = "File System";
+			reg = <0x00780000 0x007880000>;
+		};
+	};
+};
+
+&i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+
+	clock-frequency = <400000>;
+
+	tps: tps@2d {
+		reg = <0x2d>;
+	};
+};
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&vmmc>;
+	bus-width = <4>;
+};
+
+&uart0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+};
+
+#include "tps65910.dtsi"
+
+&tps {
+	vcc1-supply = <&vbat>;
+	vcc2-supply = <&vbat>;
+	vcc3-supply = <&vbat>;
+	vcc4-supply = <&vbat>;
+	vcc5-supply = <&vbat>;
+	vcc6-supply = <&vbat>;
+	vcc7-supply = <&vbat>;
+	vccio-supply = <&vbat>;
+
+	regulators {
+		vrtc_reg: regulator@0 {
+			regulator-always-on;
+		};
+
+		vio_reg: regulator@1 {
+			regulator-always-on;
+		};
+
+		vdd1_reg: regulator@2 {
+			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1312500>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd2_reg: regulator@3 {
+			/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1150000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd3_reg: regulator@4 {
+			regulator-always-on;
+		};
+
+		vdig1_reg: regulator@5 {
+			regulator-always-on;
+		};
+
+		vdig2_reg: regulator@6 {
+			regulator-always-on;
+		};
+
+		vpll_reg: regulator@7 {
+			regulator-always-on;
+		};
+
+		vdac_reg: regulator@8 {
+			regulator-always-on;
+		};
+
+		vaux1_reg: regulator@9 {
+			regulator-always-on;
+		};
+
+		vaux2_reg: regulator@10 {
+			regulator-always-on;
+		};
+
+		vaux33_reg: regulator@11 {
+			regulator-always-on;
+		};
+
+		vmmc_reg: regulator@12 {
+			regulator-always-on;
+		};
+	};
+};
+
diff --git a/arch/arm/boot/dts/am335x-nano.dts b/arch/arm/boot/dts/am335x-nano.dts
new file mode 100644
index 0000000..9907b49
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-nano.dts
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) 2013 Newflow Ltd - http://www.newflow.co.uk/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+
+/ {
+	model = "Newflow AM335x NanoBone";
+	compatible = "ti,am33xx";
+
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&dcdc2_reg>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led@0 {
+			label = "nanobone:green:usr1";
+			gpios = <&gpio1 5 0>;
+			default-state = "off";
+		};
+	};
+};
+
+&am33xx_pinmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&misc_pins>;
+
+	misc_pins: misc_pins {
+		pinctrl-single,pins = <
+			0x15c (PIN_OUTPUT | MUX_MODE7)	/* spi0_cs0.gpio0_5 */
+		>;
+	};
+
+	gpmc_pins: gpmc_pins {
+		pinctrl-single,pins = <
+			0x0 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad0.gpmc_ad0 */
+			0x4 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad1.gpmc_ad1 */
+			0x8 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad2.gpmc_ad2 */
+			0xc (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad3.gpmc_ad3 */
+			0x10 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad4.gpmc_ad4 */
+			0x14 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad5.gpmc_ad5 */
+			0x18 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad6.gpmc_ad6 */
+			0x1c (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad7.gpmc_ad7 */
+			0x20 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad8.gpmc_ad8 */
+			0x24 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad9.gpmc_ad9 */
+			0x28 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad10.gpmc_ad10 */
+			0x2c (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad11.gpmc_ad11 */
+			0x30 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad12.gpmc_ad12 */
+			0x34 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad13.gpmc_ad13 */
+			0x38 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad14.gpmc_ad14 */
+			0x3c (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad15.gpmc_ad15 */
+
+			0x70 (PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_wait0.gpmc_wait0 */
+			0x7c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_csn0.gpmc_csn0 */
+			0x80 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_csn1.gpmc_csn1 */
+			0x84 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_csn2.gpmc_csn2 */
+			0x88 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_csn3.gpmc_csn3 */
+
+			0x90 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_advn_ale.gpmc_advn_ale */
+			0x94 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_oen_ren.gpmc_oen_ren */
+			0x98 (PIN_OUTPUT | MUX_MODE0)		/* gpmc_wen.gpmc_wen */
+			0x9c (PIN_OUTPUT | MUX_MODE0)		/* gpmc_ben0_cle.gpmc_ben0_cle */
+
+			0xa4 (PIN_OUTPUT | MUX_MODE1)		/* lcd_data1.gpmc_a1 */
+			0xa8 (PIN_OUTPUT | MUX_MODE1)		/* lcd_data2.gpmc_a2 */
+			0xac (PIN_OUTPUT | MUX_MODE1)		/* lcd_data3.gpmc_a3 */
+			0xb0 (PIN_OUTPUT | MUX_MODE1)		/* lcd_data4.gpmc_a4 */
+			0xb4 (PIN_OUTPUT | MUX_MODE1)		/* lcd_data5.gpmc_a5 */
+			0xb8 (PIN_OUTPUT | MUX_MODE1)		/* lcd_data6.gpmc_a6 */
+			0xbc (PIN_OUTPUT | MUX_MODE1)		/* lcd_data7.gpmc_a7 */
+
+			0xe0 (PIN_OUTPUT | MUX_MODE1)		/* lcd_vsync.gpmc_a8 */
+			0xe4 (PIN_OUTPUT | MUX_MODE1)		/* lcd_hsync.gpmc_a9 */
+			0xe8 (PIN_OUTPUT | MUX_MODE1)		/* lcd_pclk.gpmc_a10 */
+		>;
+	};
+
+	i2c0_pins: i2c0_pins {
+		pinctrl-single,pins = <
+			0x188 (PIN_INPUT_PULLDOWN | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+			0x18c (PIN_INPUT_PULLDOWN | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+		>;
+	};
+
+	uart0_pins: uart0_pins {
+		pinctrl-single,pins = <
+			0x170 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			0x174 (PIN_OUTPUT | MUX_MODE0)		/* uart0_txd.uart0_txd */
+		>;
+	};
+
+	uart1_pins: uart1_pins {
+		pinctrl-single,pins = <
+			0x178 (PIN_OUTPUT | MUX_MODE7)		/* uart1_ctsn.uart1_ctsn */
+			0x17c (PIN_OUTPUT | MUX_MODE7)		/* uart1_rtsn.uart1_rtsn */
+			0x180 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart1_rxd.uart1_rxd */
+			0x184 (PIN_OUTPUT | MUX_MODE0)		/* uart1_txd.uart1_txd */
+		>;
+	};
+
+	uart2_pins: uart2_pins {
+		pinctrl-single,pins = <
+			0xc0 (PIN_INPUT_PULLUP | MUX_MODE7)	/* lcd_data8.gpio2[14] */
+			0xc4 (PIN_OUTPUT | MUX_MODE7)		/* lcd_data9.gpio2[15] */
+			0x150 (PIN_INPUT | MUX_MODE1)		/* spi0_sclk.uart2_rxd */
+			0x154 (PIN_OUTPUT | MUX_MODE1)		/* spi0_d0.uart2_txd */
+		>;
+	};
+
+	uart3_pins: uart3_pins {
+		pinctrl-single,pins = <
+			0xc8 (PIN_INPUT_PULLUP | MUX_MODE6)	/* lcd_data10.uart3_ctsn */
+			0xcc (PIN_OUTPUT | MUX_MODE6)		/* lcd_data11.uart3_rtsn */
+			0x160 (PIN_INPUT | MUX_MODE1)		/* spi0_cs1.uart3_rxd */
+			0x164 (PIN_OUTPUT | MUX_MODE1)		/* ecap0_in_pwm0_out.uart3_txd */
+		>;
+	};
+
+	uart4_pins: uart4_pins {
+		pinctrl-single,pins = <
+			0xd0 (PIN_INPUT_PULLUP | MUX_MODE6)	/* lcd_data12.uart4_ctsn */
+			0xd4 (PIN_OUTPUT | MUX_MODE6)		/* lcd_data13.uart4_rtsn */
+			0x168 (PIN_INPUT | MUX_MODE1)		/* uart0_ctsn.uart4_rxd */
+			0x16c (PIN_OUTPUT | MUX_MODE1)		/* uart0_rtsn.uart4_txd */
+		>;
+	};
+
+	uart5_pins: uart5_pins {
+		pinctrl-single,pins = <
+			0xd8 (PIN_INPUT | MUX_MODE4)		/* lcd_data14.uart5_rxd */
+			0x144 (PIN_OUTPUT | MUX_MODE3)		/* rmiii1_refclk.uart5_txd */
+		>;
+	};
+
+	mmc1_pins: mmc1_pins {
+		pinctrl-single,pins = <
+			0xf0 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat0.mmc0_dat0 */
+			0xf4 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat1.mmc0_dat1 */
+			0xf8 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat2.mmc0_dat2 */
+			0xfc (PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_dat3.mmc0_dat3 */
+			0x100 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_clk.mmc0_clk */
+			0x104 (PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc0_cmd.mmc0_cmd */
+			0x1e8 (PIN_INPUT_PULLUP | MUX_MODE7)	/* emu1.gpio3[8] */
+			0x1a0 (PIN_INPUT_PULLUP | MUX_MODE7)	/* mcasp0_aclkr.gpio3[18] */
+		>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	status = "okay";
+	rts-gpio = <&gpio0 13 GPIO_ACTIVE_HIGH>;
+	rs485-rts-active-high;
+	rs485-rx-during-tx;
+	rs485-rts-delay = <1 1>;
+	linux,rs485-enabled-at-boot-time;
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_pins>;
+	status = "okay";
+	rts-gpio = <&gpio2 15 GPIO_ACTIVE_HIGH>;
+	rs485-rts-active-high;
+	rs485-rts-delay = <1 1>;
+	linux,rs485-enabled-at-boot-time;
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins>;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart4_pins>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart5_pins>;
+	status = "okay";
+};
+
+&i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	clock-frequency = <400000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+
+	gpio@20 {
+		compatible = "mcp,mcp23017";
+		reg = <0x20>;
+	};
+
+	tps: tps@24 {
+		reg = <0x24>;
+	};
+
+	eeprom@53 {
+		compatible = "mcp,24c02";
+		reg = <0x53>;
+		pagesize = <8>;
+	};
+
+	rtc@68 {
+		compatible = "dallas,ds1307";
+		reg = <0x68>;
+	};
+};
+
+&elm {
+	status = "okay";
+};
+
+&gpmc {
+	compatible = "ti,am3352-gpmc";
+	ti,hwmods = "gpmc";
+	status = "okay";
+	gpmc,num-waitpins = <2>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&gpmc_pins>;
+
+	#address-cells = <2>;
+	#size-cells = <1>;
+	ranges = <0 0 0x08000000 0x08000000>;	/* CS0: NOR 128M */
+
+	nor@0,0 {
+		reg = <0 0x00000000 0x08000000>;
+		compatible = "cfi-flash";
+		linux,mtd-name = "spansion,s29gl010p11t";
+		bank-width = <2>;
+
+		gpmc,mux-add-data = <2>;
+
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <160>;
+		gpmc,cs-wr-off-ns = <160>;
+		gpmc,adv-on-ns = <10>;
+		gpmc,adv-rd-off-ns = <30>;
+		gpmc,adv-wr-off-ns = <30>;
+		gpmc,oe-on-ns = <40>;
+		gpmc,oe-off-ns = <160>;
+		gpmc,we-on-ns = <40>;
+		gpmc,we-off-ns = <160>;
+		gpmc,rd-cycle-ns = <160>;
+		gpmc,wr-cycle-ns = <160>;
+		gpmc,access-ns = <150>;
+		gpmc,page-burst-access-ns = <10>;
+		gpmc,cycle2cycle-samecsen;
+		gpmc,cycle2cycle-delay-ns = <20>;
+		gpmc,wr-data-mux-bus-ns = <70>;
+		gpmc,wr-access-ns = <80>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		/*
+		MTD partition table
+		===================
+		+------------+-->0x00000000-> U-Boot start
+		|            |
+		|            |-->0x000BFFFF-> U-Boot end
+		|            |-->0x000C0000-> ENV1 start
+		|            |
+		|            |-->0x000DFFFF-> ENV1 end
+		|            |-->0x000E0000-> ENV2 start
+		|            |
+		|            |-->0x000FFFFF-> ENV2 end
+		|            |-->0x00100000-> Kernel start
+		|            |
+		|            |-->0x004FFFFF-> Kernel end
+		|            |-->0x00500000-> File system start
+		|            |
+		|            |-->0x014FFFFF-> File system end
+		|            |-->0x01500000-> User data start
+		|            |
+		|            |-->0x03FFFFFF-> User data end
+		|            |-->0x04000000-> Data storage start
+		|            |
+		+------------+-->0x08000000-> NOR end (Free end)
+		*/
+		partition@0 {
+			label = "boot";
+			reg = <0x00000000 0x000c0000>; /* 768KB */
+		};
+
+		partition@1 {
+			label = "env1";
+			reg = <0x000c0000 0x00020000>; /* 128KB */
+		};
+
+		partition@2 {
+			label = "env2";
+			reg = <0x000e0000 0x00020000>; /* 128KB */
+		};
+
+		partition@3 {
+			label = "kernel";
+			reg = <0x00100000 0x00400000>; /* 4MB */
+		};
+
+		partition@4 {
+			label = "rootfs";
+			reg = <0x00500000 0x01000000>; /* 16MB */
+		};
+
+		partition@5 {
+			label = "user";
+			reg = <0x01500000 0x02b00000>; /* 43MB */
+		};
+
+		partition@6 {
+			label = "data";
+			reg = <0x04000000 0x04000000>; /* 64MB */
+		};
+	};
+};
+
+&mac {
+	dual_emac = <1>;
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+	dual_emac_res_vlan = <1>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <1>;
+	dual_emac_res_vlan = <2>;
+};
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&ldo4_reg>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	bus-width = <4>;
+	cd-gpios = <&gpio3 8 0>;
+	wp-gpios = <&gpio3 18 0>;
+};
+
+#include "tps65217.dtsi"
+
+&tps {
+	regulators {
+		dcdc1_reg: regulator@0 {
+			/* +1.5V voltage with ±4% tolerance */
+			regulator-min-microvolt = <1450000>;
+			regulator-max-microvolt = <1550000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc2_reg: regulator@1 {
+			/* VDD_MPU voltage limits 0.95V - 1.1V with ±4% tolerance */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <915000>;
+			regulator-max-microvolt = <1140000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc3_reg: regulator@2 {
+			/* VDD_CORE voltage limits 0.95V - 1.1V with ±4% tolerance */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <915000>;
+			regulator-max-microvolt = <1140000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		ldo1_reg: regulator@3 {
+			/* +1.8V voltage with ±4% tolerance */
+			regulator-min-microvolt = <1750000>;
+			regulator-max-microvolt = <1870000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		ldo2_reg: regulator@4 {
+			/* +3.3V voltage with ±4% tolerance */
+			regulator-min-microvolt = <3175000>;
+			regulator-max-microvolt = <3430000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		ldo3_reg: regulator@5 {
+			/* +1.8V voltage with ±4% tolerance */
+			regulator-min-microvolt = <1750000>;
+			regulator-max-microvolt = <1870000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		ldo4_reg: regulator@6 {
+			/* +3.3V voltage with ±4% tolerance */
+			regulator-min-microvolt = <3175000>;
+			regulator-max-microvolt = <3430000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index f9c5da9..fcb9c8e 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -18,6 +18,9 @@
 	interrupt-parent = <&intc>;
 
 	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
 		serial0 = &uart0;
 		serial1 = &uart1;
 		serial2 = &uart2;
@@ -30,6 +33,8 @@
 		usb1 = &usb1;
 		phy0 = &usb0_phy;
 		phy1 = &usb1_phy;
+		ethernet0 = &cpsw_emac0;
+		ethernet1 = &cpsw_emac1;
 	};
 
 	cpus {
@@ -57,6 +62,11 @@
 		};
 	};
 
+	pmu {
+		compatible = "arm,cortex-a8-pmu";
+		interrupts = <3>;
+	};
+
 	/*
 	 * The soc node represents the soc top level view. It is uses for IPs
 	 * that are not memory mapped in the MPU view or for the MPU itself.
@@ -100,13 +110,25 @@
 			reg = <0x48200000 0x1000>;
 		};
 
+		edma: edma@49000000 {
+			compatible = "ti,edma3";
+			ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2";
+			reg =	<0x49000000 0x10000>,
+				<0x44e10f90 0x10>;
+			interrupts = <12 13 14>;
+			#dma-cells = <1>;
+			dma-channels = <64>;
+			ti,edma-regions = <4>;
+			ti,edma-slots = <256>;
+		};
+
 		gpio0: gpio@44e07000 {
 			compatible = "ti,omap4-gpio";
 			ti,hwmods = "gpio1";
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
-			#interrupt-cells = <1>;
+			#interrupt-cells = <2>;
 			reg = <0x44e07000 0x1000>;
 			interrupts = <96>;
 		};
@@ -117,7 +139,7 @@
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
-			#interrupt-cells = <1>;
+			#interrupt-cells = <2>;
 			reg = <0x4804c000 0x1000>;
 			interrupts = <98>;
 		};
@@ -128,7 +150,7 @@
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
-			#interrupt-cells = <1>;
+			#interrupt-cells = <2>;
 			reg = <0x481ac000 0x1000>;
 			interrupts = <32>;
 		};
@@ -139,7 +161,7 @@
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
-			#interrupt-cells = <1>;
+			#interrupt-cells = <2>;
 			reg = <0x481ae000 0x1000>;
 			interrupts = <62>;
 		};
@@ -228,6 +250,50 @@
 			status = "disabled";
 		};
 
+		mmc1: mmc@48060000 {
+			compatible = "ti,omap4-hsmmc";
+			ti,hwmods = "mmc1";
+			ti,dual-volt;
+			ti,needs-special-reset;
+			ti,needs-special-hs-handling;
+			dmas = <&edma 24
+				&edma 25>;
+			dma-names = "tx", "rx";
+			interrupts = <64>;
+			interrupt-parent = <&intc>;
+			reg = <0x48060000 0x1000>;
+			status = "disabled";
+		};
+
+		mmc2: mmc@481d8000 {
+			compatible = "ti,omap4-hsmmc";
+			ti,hwmods = "mmc2";
+			ti,needs-special-reset;
+			dmas = <&edma 2
+				&edma 3>;
+			dma-names = "tx", "rx";
+			interrupts = <28>;
+			interrupt-parent = <&intc>;
+			reg = <0x481d8000 0x1000>;
+			status = "disabled";
+		};
+
+		mmc3: mmc@47810000 {
+			compatible = "ti,omap4-hsmmc";
+			ti,hwmods = "mmc3";
+			ti,needs-special-reset;
+			interrupts = <29>;
+			interrupt-parent = <&intc>;
+			reg = <0x47810000 0x1000>;
+			status = "disabled";
+		};
+
+		hwspinlock: spinlock@480ca000 {
+			compatible = "ti,omap4-hwspinlock";
+			reg = <0x480ca000 0x1000>;
+			ti,hwmods = "spinlock";
+		};
+
 		wdt2: wdt@44e35000 {
 			compatible = "ti,omap3-wdt";
 			ti,hwmods = "wd_timer2";
@@ -323,6 +389,11 @@
 			interrupts = <65>;
 			ti,spi-num-cs = <2>;
 			ti,hwmods = "spi0";
+			dmas = <&edma 16
+				&edma 17
+				&edma 18
+				&edma 19>;
+			dma-names = "tx0", "rx0", "tx1", "rx1";
 			status = "disabled";
 		};
 
@@ -334,6 +405,11 @@
 			interrupts = <125>;
 			ti,spi-num-cs = <2>;
 			ti,hwmods = "spi1";
+			dmas = <&edma 42
+				&edma 43
+				&edma 44
+				&edma 45>;
+			dma-names = "tx0", "rx0", "tx1", "rx1";
 			status = "disabled";
 		};
 
@@ -346,7 +422,7 @@
 			ti,hwmods = "usb_otg_hs";
 			status = "disabled";
 
-			ctrl_mod: control@44e10000 {
+			usb_ctrl_mod: control@44e10000 {
 				compatible = "ti,am335x-usb-ctrl-module";
 				reg = <0x44e10620 0x10
 					0x44e10648 0x4>;
@@ -359,7 +435,7 @@
 				reg = <0x47401300 0x100>;
 				reg-names = "phy";
 				status = "disabled";
-				ti,ctrl_mod = <&ctrl_mod>;
+				ti,ctrl_mod = <&usb_ctrl_mod>;
 			};
 
 			usb0: usb@47401000 {
@@ -407,7 +483,7 @@
 				reg = <0x47401b00 0x100>;
 				reg-names = "phy";
 				status = "disabled";
-				ti,ctrl_mod = <&ctrl_mod>;
+				ti,ctrl_mod = <&usb_ctrl_mod>;
 			};
 
 			usb1: usb@47401800 {
@@ -607,6 +683,7 @@
 			reg = <0x44d00000 0x4000	/* M3 UMEM */
 			       0x44d80000 0x2000>;	/* M3 DMEM */
 			ti,hwmods = "wkup_m3";
+			ti,no-reset-on-init;
 		};
 
 		elm: elm@48080000 {
@@ -617,6 +694,15 @@
 			status = "disabled";
 		};
 
+		lcdc: lcdc@4830e000 {
+			compatible = "ti,am33xx-tilcdc";
+			reg = <0x4830e000 0x1000>;
+			interrupt-parent = <&intc>;
+			interrupts = <36>;
+			ti,hwmods = "lcdc";
+			status = "disabled";
+		};
+
 		tscadc: tscadc@44e0d000 {
 			compatible = "ti,am3359-tscadc";
 			reg = <0x44e0d000 0x1000>;
@@ -637,6 +723,7 @@
 		gpmc: gpmc@50000000 {
 			compatible = "ti,am3352-gpmc";
 			ti,hwmods = "gpmc";
+			ti,no-idle-on-init;
 			reg = <0x50000000 0x2000>;
 			interrupts = <100>;
 			gpmc,num-cs = <7>;
@@ -645,5 +732,59 @@
 			#size-cells = <1>;
 			status = "disabled";
 		};
+
+		sham: sham@53100000 {
+			compatible = "ti,omap4-sham";
+			ti,hwmods = "sham";
+			reg = <0x53100000 0x200>;
+			interrupts = <109>;
+			dmas = <&edma 36>;
+			dma-names = "rx";
+		};
+
+		aes: aes@53500000 {
+			compatible = "ti,omap4-aes";
+			ti,hwmods = "aes";
+			reg = <0x53500000 0xa0>;
+			interrupts = <103>;
+			dmas = <&edma 6>,
+			       <&edma 5>;
+			dma-names = "tx", "rx";
+		};
+
+		mcasp0: mcasp@48038000 {
+			compatible = "ti,am33xx-mcasp-audio";
+			ti,hwmods = "mcasp0";
+			reg = <0x48038000 0x2000>,
+			      <0x46000000 0x400000>;
+			reg-names = "mpu", "dat";
+			interrupts = <80>, <81>;
+			interrupts-names = "tx", "rx";
+			status = "disabled";
+			dmas = <&edma 8>,
+				<&edma 9>;
+			dma-names = "tx", "rx";
+		};
+
+		mcasp1: mcasp@4803C000 {
+			compatible = "ti,am33xx-mcasp-audio";
+			ti,hwmods = "mcasp1";
+			reg = <0x4803C000 0x2000>,
+			      <0x46400000 0x400000>;
+			reg-names = "mpu", "dat";
+			interrupts = <82>, <83>;
+			interrupts-names = "tx", "rx";
+			status = "disabled";
+			dmas = <&edma 10>,
+				<&edma 11>;
+			dma-names = "tx", "rx";
+		};
+
+		rng: rng@48310000 {
+			compatible = "ti,omap4-rng";
+			ti,hwmods = "rng";
+			reg = <0x48310000 0x2000>;
+			interrupts = <111>;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi
index ddc1df7..974d103 100644
--- a/arch/arm/boot/dts/am4372.dtsi
+++ b/arch/arm/boot/dts/am4372.dtsi
@@ -18,12 +18,21 @@
 
 
 	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
 		serial0 = &uart0;
+		ethernet0 = &cpsw_emac0;
+		ethernet1 = &cpsw_emac1;
 	};
 
 	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
 		cpu@0 {
 			compatible = "arm,cortex-a9";
+			device_type = "cpu";
+			reg = <0>;
 		};
 	};
 
@@ -35,16 +44,100 @@
 		      <0x48240100 0x0100>;
 	};
 
+	l2-cache-controller@48242000 {
+		compatible = "arm,pl310-cache";
+		reg = <0x48242000 0x1000>;
+		cache-unified;
+		cache-level = <2>;
+	};
+
+	am43xx_pinmux: pinmux@44e10800 {
+		compatible = "pinctrl-single";
+		reg = <0x44e10800 0x31c>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0xffffffff>;
+	};
+
 	ocp {
 		compatible = "simple-bus";
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
+		ti,hwmods = "l3_main";
+
+		edma: edma@49000000 {
+			compatible = "ti,edma3";
+			ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2";
+			reg =	<0x49000000 0x10000>,
+				<0x44e10f90 0x10>;
+			interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+			#dma-cells = <1>;
+			dma-channels = <64>;
+			ti,edma-regions = <4>;
+			ti,edma-slots = <256>;
+		};
 
 		uart0: serial@44e09000 {
 			compatible = "ti,am4372-uart","ti,omap2-uart";
 			reg = <0x44e09000 0x2000>;
 			interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "uart1";
+		};
+
+		uart1: serial@48022000 {
+			compatible = "ti,am4372-uart","ti,omap2-uart";
+			reg = <0x48022000 0x2000>;
+			interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "uart2";
+			status = "disabled";
+		};
+
+		uart2: serial@48024000 {
+			compatible = "ti,am4372-uart","ti,omap2-uart";
+			reg = <0x48024000 0x2000>;
+			interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "uart3";
+			status = "disabled";
+		};
+
+		uart3: serial@481a6000 {
+			compatible = "ti,am4372-uart","ti,omap2-uart";
+			reg = <0x481a6000 0x2000>;
+			interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "uart4";
+			status = "disabled";
+		};
+
+		uart4: serial@481a8000 {
+			compatible = "ti,am4372-uart","ti,omap2-uart";
+			reg = <0x481a8000 0x2000>;
+			interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "uart5";
+			status = "disabled";
+		};
+
+		uart5: serial@481aa000 {
+			compatible = "ti,am4372-uart","ti,omap2-uart";
+			reg = <0x481aa000 0x2000>;
+			interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "uart6";
+			status = "disabled";
+		};
+
+		mailbox: mailbox@480C8000 {
+			compatible = "ti,omap4-mailbox";
+			reg = <0x480C8000 0x200>;
+			interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "mailbox";
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <8>;
+			ti,mbox-names = "wkup_m3";
+			ti,mbox-data = <0 0 0 0>;
+			status = "disabled";
 		};
 
 		timer1: timer@44e31000 {
@@ -52,17 +145,523 @@
 			reg = <0x44e31000 0x400>;
 			interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
 			ti,timer-alwon;
+			ti,hwmods = "timer1";
 		};
 
 		timer2: timer@48040000  {
 			compatible = "ti,am4372-timer","ti,am335x-timer";
 			reg = <0x48040000  0x400>;
 			interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer2";
+		};
+
+		timer3: timer@48042000 {
+			compatible = "ti,am4372-timer","ti,am335x-timer";
+			reg = <0x48042000 0x400>;
+			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer3";
+			status = "disabled";
+		};
+
+		timer4: timer@48044000 {
+			compatible = "ti,am4372-timer","ti,am335x-timer";
+			reg = <0x48044000 0x400>;
+			interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
+			ti,timer-pwm;
+			ti,hwmods = "timer4";
+			status = "disabled";
+		};
+
+		timer5: timer@48046000 {
+			compatible = "ti,am4372-timer","ti,am335x-timer";
+			reg = <0x48046000 0x400>;
+			interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
+			ti,timer-pwm;
+			ti,hwmods = "timer5";
+			status = "disabled";
+		};
+
+		timer6: timer@48048000 {
+			compatible = "ti,am4372-timer","ti,am335x-timer";
+			reg = <0x48048000 0x400>;
+			interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+			ti,timer-pwm;
+			ti,hwmods = "timer6";
+			status = "disabled";
+		};
+
+		timer7: timer@4804a000 {
+			compatible = "ti,am4372-timer","ti,am335x-timer";
+			reg = <0x4804a000 0x400>;
+			interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
+			ti,timer-pwm;
+			ti,hwmods = "timer7";
+			status = "disabled";
+		};
+
+		timer8: timer@481c1000 {
+			compatible = "ti,am4372-timer","ti,am335x-timer";
+			reg = <0x481c1000 0x400>;
+			interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer8";
+			status = "disabled";
+		};
+
+		timer9: timer@4833d000 {
+			compatible = "ti,am4372-timer","ti,am335x-timer";
+			reg = <0x4833d000 0x400>;
+			interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer9";
+			status = "disabled";
+		};
+
+		timer10: timer@4833f000 {
+			compatible = "ti,am4372-timer","ti,am335x-timer";
+			reg = <0x4833f000 0x400>;
+			interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer10";
+			status = "disabled";
+		};
+
+		timer11: timer@48341000 {
+			compatible = "ti,am4372-timer","ti,am335x-timer";
+			reg = <0x48341000 0x400>;
+			interrupts = <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer11";
+			status = "disabled";
 		};
 
 		counter32k: counter@44e86000 {
 			compatible = "ti,am4372-counter32k","ti,omap-counter32k";
 			reg = <0x44e86000 0x40>;
+			ti,hwmods = "counter_32k";
+		};
+
+		rtc@44e3e000 {
+			compatible = "ti,am4372-rtc","ti,da830-rtc";
+			reg = <0x44e3e000 0x1000>;
+			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "rtc";
+			status = "disabled";
+		};
+
+		wdt@44e35000 {
+			compatible = "ti,am4372-wdt","ti,omap3-wdt";
+			reg = <0x44e35000 0x1000>;
+			interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "wd_timer2";
+		};
+
+		gpio0: gpio@44e07000 {
+			compatible = "ti,am4372-gpio","ti,omap4-gpio";
+			reg = <0x44e07000 0x1000>;
+			interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			ti,hwmods = "gpio1";
+			status = "disabled";
+		};
+
+		gpio1: gpio@4804c000 {
+			compatible = "ti,am4372-gpio","ti,omap4-gpio";
+			reg = <0x4804c000 0x1000>;
+			interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			ti,hwmods = "gpio2";
+			status = "disabled";
+		};
+
+		gpio2: gpio@481ac000 {
+			compatible = "ti,am4372-gpio","ti,omap4-gpio";
+			reg = <0x481ac000 0x1000>;
+			interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			ti,hwmods = "gpio3";
+			status = "disabled";
+		};
+
+		gpio3: gpio@481ae000 {
+			compatible = "ti,am4372-gpio","ti,omap4-gpio";
+			reg = <0x481ae000 0x1000>;
+			interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			ti,hwmods = "gpio4";
+			status = "disabled";
+		};
+
+		gpio4: gpio@48320000 {
+			compatible = "ti,am4372-gpio","ti,omap4-gpio";
+			reg = <0x48320000 0x1000>;
+			interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			ti,hwmods = "gpio5";
+			status = "disabled";
+		};
+
+		gpio5: gpio@48322000 {
+			compatible = "ti,am4372-gpio","ti,omap4-gpio";
+			reg = <0x48322000 0x1000>;
+			interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			ti,hwmods = "gpio6";
+			status = "disabled";
+		};
+
+		i2c0: i2c@44e0b000 {
+			compatible = "ti,am4372-i2c","ti,omap4-i2c";
+			reg = <0x44e0b000 0x1000>;
+			interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "i2c1";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c1: i2c@4802a000 {
+			compatible = "ti,am4372-i2c","ti,omap4-i2c";
+			reg = <0x4802a000 0x1000>;
+			interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "i2c2";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c2: i2c@4819c000 {
+			compatible = "ti,am4372-i2c","ti,omap4-i2c";
+			reg = <0x4819c000 0x1000>;
+			interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "i2c3";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		spi0: spi@48030000 {
+			compatible = "ti,am4372-mcspi","ti,omap4-mcspi";
+			reg = <0x48030000 0x400>;
+			interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "spi0";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		mmc1: mmc@48060000 {
+			compatible = "ti,omap4-hsmmc";
+			reg = <0x48060000 0x1000>;
+			ti,hwmods = "mmc1";
+			ti,dual-volt;
+			ti,needs-special-reset;
+			dmas = <&edma 24
+				&edma 25>;
+			dma-names = "tx", "rx";
+			interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		mmc2: mmc@481d8000 {
+			compatible = "ti,omap4-hsmmc";
+			reg = <0x481d8000 0x1000>;
+			ti,hwmods = "mmc2";
+			ti,needs-special-reset;
+			dmas = <&edma 2
+				&edma 3>;
+			dma-names = "tx", "rx";
+			interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		mmc3: mmc@47810000 {
+			compatible = "ti,omap4-hsmmc";
+			reg = <0x47810000 0x1000>;
+			ti,hwmods = "mmc3";
+			ti,needs-special-reset;
+			interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		spi1: spi@481a0000 {
+			compatible = "ti,am4372-mcspi","ti,omap4-mcspi";
+			reg = <0x481a0000 0x400>;
+			interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "spi1";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		spi2: spi@481a2000 {
+			compatible = "ti,am4372-mcspi","ti,omap4-mcspi";
+			reg = <0x481a2000 0x400>;
+			interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "spi2";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		spi3: spi@481a4000 {
+			compatible = "ti,am4372-mcspi","ti,omap4-mcspi";
+			reg = <0x481a4000 0x400>;
+			interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "spi3";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		spi4: spi@48345000 {
+			compatible = "ti,am4372-mcspi","ti,omap4-mcspi";
+			reg = <0x48345000 0x400>;
+			interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "spi4";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		mac: ethernet@4a100000 {
+			compatible = "ti,am4372-cpsw","ti,cpsw";
+			reg = <0x4a100000 0x800
+			       0x4a101200 0x100>;
+			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ti,hwmods = "cpgmac0";
+			status = "disabled";
+			cpdma_channels = <8>;
+			ale_entries = <1024>;
+			bd_ram_size = <0x2000>;
+			no_bd_ram = <0>;
+			rx_descs = <64>;
+			mac_control = <0x20>;
+			slaves = <2>;
+			active_slave = <0>;
+			cpts_clock_mult = <0x80000000>;
+			cpts_clock_shift = <29>;
+			ranges;
+
+			davinci_mdio: mdio@4a101000 {
+				compatible = "ti,am4372-mdio","ti,davinci_mdio";
+				reg = <0x4a101000 0x100>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				ti,hwmods = "davinci_mdio";
+				bus_freq = <1000000>;
+				status = "disabled";
+			};
+
+			cpsw_emac0: slave@4a100200 {
+				/* Filled in by U-Boot */
+				mac-address = [ 00 00 00 00 00 00 ];
+			};
+
+			cpsw_emac1: slave@4a100300 {
+				/* Filled in by U-Boot */
+				mac-address = [ 00 00 00 00 00 00 ];
+			};
+		};
+
+		epwmss0: epwmss@48300000 {
+			compatible = "ti,am4372-pwmss","ti,am33xx-pwmss";
+			reg = <0x48300000 0x10>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			ti,hwmods = "epwmss0";
+			status = "disabled";
+
+			ecap0: ecap@48300100 {
+				compatible = "ti,am4372-ecap","ti,am33xx-ecap";
+				reg = <0x48300100 0x80>;
+				ti,hwmods = "ecap0";
+				status = "disabled";
+			};
+
+			ehrpwm0: ehrpwm@48300200 {
+				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
+				reg = <0x48300200 0x80>;
+				ti,hwmods = "ehrpwm0";
+				status = "disabled";
+			};
+		};
+
+		epwmss1: epwmss@48302000 {
+			compatible = "ti,am4372-pwmss","ti,am33xx-pwmss";
+			reg = <0x48302000 0x10>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			ti,hwmods = "epwmss1";
+			status = "disabled";
+
+			ecap1: ecap@48302100 {
+				compatible = "ti,am4372-ecap","ti,am33xx-ecap";
+				reg = <0x48302100 0x80>;
+				ti,hwmods = "ecap1";
+				status = "disabled";
+			};
+
+			ehrpwm1: ehrpwm@48302200 {
+				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
+				reg = <0x48302200 0x80>;
+				ti,hwmods = "ehrpwm1";
+				status = "disabled";
+			};
+		};
+
+		epwmss2: epwmss@48304000 {
+			compatible = "ti,am4372-pwmss","ti,am33xx-pwmss";
+			reg = <0x48304000 0x10>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			ti,hwmods = "epwmss2";
+			status = "disabled";
+
+			ecap2: ecap@48304100 {
+				compatible = "ti,am4372-ecap","ti,am33xx-ecap";
+				reg = <0x48304100 0x80>;
+				ti,hwmods = "ecap2";
+				status = "disabled";
+			};
+
+			ehrpwm2: ehrpwm@48304200 {
+				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
+				reg = <0x48304200 0x80>;
+				ti,hwmods = "ehrpwm2";
+				status = "disabled";
+			};
+		};
+
+		epwmss3: epwmss@48306000 {
+			compatible = "ti,am4372-pwmss","ti,am33xx-pwmss";
+			reg = <0x48306000 0x10>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			ti,hwmods = "epwmss3";
+			status = "disabled";
+
+			ehrpwm3: ehrpwm@48306200 {
+				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
+				reg = <0x48306200 0x80>;
+				ti,hwmods = "ehrpwm3";
+				status = "disabled";
+			};
+		};
+
+		epwmss4: epwmss@48308000 {
+			compatible = "ti,am4372-pwmss","ti,am33xx-pwmss";
+			reg = <0x48308000 0x10>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			ti,hwmods = "epwmss4";
+			status = "disabled";
+
+			ehrpwm4: ehrpwm@48308200 {
+				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
+				reg = <0x48308200 0x80>;
+				ti,hwmods = "ehrpwm4";
+				status = "disabled";
+			};
+		};
+
+		epwmss5: epwmss@4830a000 {
+			compatible = "ti,am4372-pwmss","ti,am33xx-pwmss";
+			reg = <0x4830a000 0x10>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			ti,hwmods = "epwmss5";
+			status = "disabled";
+
+			ehrpwm5: ehrpwm@4830a200 {
+				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
+				reg = <0x4830a200 0x80>;
+				ti,hwmods = "ehrpwm5";
+				status = "disabled";
+			};
+		};
+
+		sham: sham@53100000 {
+			compatible = "ti,omap5-sham";
+			ti,hwmods = "sham";
+			reg = <0x53100000 0x300>;
+			dmas = <&edma 36>;
+			dma-names = "rx";
+			interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		aes: aes@53501000 {
+			compatible = "ti,omap4-aes";
+			ti,hwmods = "aes";
+			reg = <0x53501000 0xa0>;
+			interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&edma 6
+				&edma 5>;
+			dma-names = "tx", "rx";
+		};
+
+		des: des@53701000 {
+			compatible = "ti,omap4-des";
+			ti,hwmods = "des";
+			reg = <0x53701000 0xa0>;
+			interrupts = <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&edma 34
+				&edma 33>;
+			dma-names = "tx", "rx";
+		};
+
+		mcasp0: mcasp@48038000 {
+			compatible = "ti,am33xx-mcasp-audio";
+			ti,hwmods = "mcasp0";
+			reg = <0x48038000 0x2000>,
+			      <0x46000000 0x400000>;
+			reg-names = "mpu", "dat";
+			interrupts = <80>, <81>;
+			interrupts-names = "tx", "rx";
+			status = "disabled";
+			dmas = <&edma 8>,
+			       <&edma 9>;
+			dma-names = "tx", "rx";
+		};
+
+		mcasp1: mcasp@4803C000 {
+			compatible = "ti,am33xx-mcasp-audio";
+			ti,hwmods = "mcasp1";
+			reg = <0x4803C000 0x2000>,
+			      <0x46400000 0x400000>;
+			reg-names = "mpu", "dat";
+			interrupts = <82>, <83>;
+			interrupts-names = "tx", "rx";
+			status = "disabled";
+			dmas = <&edma 10>,
+			       <&edma 11>;
+			dma-names = "tx", "rx";
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts
index 74174d4..fbf9c4c 100644
--- a/arch/arm/boot/dts/am43x-epos-evm.dts
+++ b/arch/arm/boot/dts/am43x-epos-evm.dts
@@ -11,8 +11,176 @@
 /dts-v1/;
 
 #include "am4372.dtsi"
+#include <dt-bindings/pinctrl/am43xx.h>
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	model = "TI AM43x EPOS EVM";
 	compatible = "ti,am43x-epos-evm","ti,am4372","ti,am43";
+
+	vmmcsd_fixed: fixedregulator-sd {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmcsd_fixed";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		enable-active-high;
+	};
+
+	am43xx_pinmux: pinmux@44e10800 {
+		cpsw_default: cpsw_default {
+			pinctrl-single,pins = <
+				/* Slave 1 */
+				0x10c (PIN_INPUT_PULLDOWN | MUX_MODE1)	/* mii1_crs.rmii1_crs */
+				0x110 (PIN_INPUT_PULLDOWN | MUX_MODE1)	/* mii1_rxerr.rmii1_rxerr */
+				0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* mii1_txen.rmii1_txen */
+				0x118 (PIN_INPUT_PULLDOWN | MUX_MODE1)	/* mii1_rxdv.rmii1_rxdv */
+				0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* mii1_txd1.rmii1_txd1 */
+				0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* mii1_txd0.rmii1_txd0 */
+				0x13c (PIN_INPUT_PULLDOWN | MUX_MODE1)	/* mii1_rxd1.rmii1_rxd1 */
+				0x140 (PIN_INPUT_PULLDOWN | MUX_MODE1)	/* mii1_rxd0.rmii1_rxd0 */
+				0x144 (PIN_INPUT_PULLDOWN | MUX_MODE0)	/* rmii1_refclk.rmii1_refclk */
+			>;
+		};
+
+		cpsw_sleep: cpsw_sleep {
+			pinctrl-single,pins = <
+				/* Slave 1 reset value */
+				0x10c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+				0x110 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+				0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+				0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+				0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+				0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+				0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+				0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+				0x144 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			>;
+		};
+
+		davinci_mdio_default: davinci_mdio_default {
+			pinctrl-single,pins = <
+				/* MDIO */
+				0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+				0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+			>;
+		};
+
+		davinci_mdio_sleep: davinci_mdio_sleep {
+			pinctrl-single,pins = <
+				/* MDIO reset value */
+				0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7)
+				0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7)
+			>;
+		};
+
+		i2c0_pins: pinmux_i2c0_pins {
+			pinctrl-single,pins = <
+				0x188 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* i2c0_sda.i2c0_sda */
+				0x18c (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* i2c0_scl.i2c0_scl */
+			>;
+		};
+	};
+
+	matrix_keypad: matrix_keypad@0 {
+			compatible = "gpio-matrix-keypad";
+			debounce-delay-ms = <5>;
+			col-scan-delay-us = <2>;
+
+			row-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH		/* Bank0, pin12 */
+				     &gpio0 13 GPIO_ACTIVE_HIGH		/* Bank0, pin13 */
+				     &gpio0 14 GPIO_ACTIVE_HIGH		/* Bank0, pin14 */
+				     &gpio0 15 GPIO_ACTIVE_HIGH>;	/* Bank0, pin15 */
+
+			col-gpios = <&gpio3 9 GPIO_ACTIVE_HIGH		/* Bank3, pin9 */
+				     &gpio3 10 GPIO_ACTIVE_HIGH		/* Bank3, pin10 */
+				     &gpio2 18 GPIO_ACTIVE_HIGH		/* Bank2, pin18 */
+				     &gpio2 19 GPIO_ACTIVE_HIGH>;	/* Bank2, pin19 */
+
+			linux,keymap = <0x00000201	/* P1 */
+				0x01000204	/* P4 */
+				0x02000207	/* P7 */
+				0x0300020a	/* NUMERIC_STAR */
+				0x00010202	/* P2 */
+				0x01010205	/* P5 */
+				0x02010208	/* P8 */
+				0x03010200	/* P0 */
+				0x00020203	/* P3 */
+				0x01020206	/* P6 */
+				0x02020209	/* P9 */
+				0x0302020b	/* NUMERIC_POUND */
+				0x00030067	/* UP */
+				0x0103006a	/* RIGHT */
+				0x0203006c	/* DOWN */
+				0x03030069>;	/* LEFT */
+		};
+};
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&vmmcsd_fixed>;
+	bus-width = <4>;
+};
+
+&mac {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+	status = "okay";
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+	status = "okay";
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <16>;
+	phy-mode = "rmii";
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <1>;
+	phy-mode = "rmii";
+};
+
+&i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+
+	at24@50 {
+		compatible = "at24,24c256";
+		pagesize = <64>;
+		reg = <0x50>;
+	};
+
+	pixcir_ts@5c {
+		compatible = "pixcir,pixcir_ts";
+		reg = <0x5c>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <17 0>;
+
+		attb-gpio = <&gpio1 17 GPIO_ACTIVE_HIGH>;
+
+		x-size = <1024>;
+		y-size = <768>;
+	};
+};
+
+&gpio0 {
+	status = "okay";
+};
+
+&gpio1 {
+	status = "okay";
+};
+
+&gpio2 {
+	status = "okay";
+};
+
+&gpio3 {
+	status = "okay";
 };
diff --git a/arch/arm/boot/dts/armada-370-netgear-rn104.dts b/arch/arm/boot/dts/armada-370-netgear-rn104.dts
new file mode 100644
index 0000000..b0b32f5
--- /dev/null
+++ b/arch/arm/boot/dts/armada-370-netgear-rn104.dts
@@ -0,0 +1,193 @@
+/*
+ * Device Tree file for NETGEAR ReadyNAS 104
+ *
+ * Copyright (C) 2013, Arnaud EBALARD <arno@natisbad.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/dts-v1/;
+
+#include "armada-370.dtsi"
+
+/ {
+	model = "NETGEAR ReadyNAS 104";
+	compatible = "netgear,readynas-104", "marvell,armada370", "marvell,armada-370-xp";
+
+	chosen {
+		bootargs = "console=ttyS0,115200 earlyprintk";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x20000000>; /* 512 MB */
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xd0000000 0x100000
+			  MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000>;
+
+		pcie-controller {
+			status = "okay";
+
+			/* Connected to FL1009 USB 3.0 controller */
+			pcie@1,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+
+			/* Connected to Marvell 88SE9215 SATA controller */
+			pcie@2,0 {
+				/* Port 1, Lane 0 */
+				status = "okay";
+			};
+		};
+
+		internal-regs {
+			serial@12000 {
+				clock-frequency = <200000000>;
+				status = "okay";
+			};
+
+			pinctrl {
+				poweroff: poweroff {
+					marvell,pins = "mpp60";
+					marvell,function = "gpio";
+				};
+
+				backup_key_pin: backup-key-pin {
+					marvell,pins = "mpp52";
+					marvell,function = "gpio";
+				};
+
+				power_key_pin: power-key-pin {
+					marvell,pins = "mpp62";
+					marvell,function = "gpio";
+				};
+
+				backup_led_pin: backup-led-pin {
+					marvell,pins = "mpp63";
+					marvell,function = "gpo";
+				};
+
+				power_led_pin: power-led-pin {
+					marvell,pins = "mpp64";
+					marvell,function = "gpio";
+				};
+
+				reset_key_pin: reset-key-pin {
+					marvell,pins = "mpp65";
+					marvell,function = "gpio";
+				};
+			};
+
+			mdio {
+				phy0: ethernet-phy@0 {
+					reg = <0>;
+				};
+
+				phy1: ethernet-phy@1 {
+					reg = <1>;
+				};
+			};
+
+			ethernet@70000 {
+				status = "okay";
+				phy = <&phy0>;
+				phy-mode = "rgmii-id";
+			};
+
+			ethernet@74000 {
+				status = "okay";
+				phy = <&phy1>;
+				phy-mode = "rgmii-id";
+			};
+
+			usb@50000 {
+				status = "okay";
+			};
+
+			i2c@11000 {
+				compatible = "marvell,mv64xxx-i2c";
+				clock-frequency = <100000>;
+				status = "okay";
+
+				g762: g762@3e {
+					compatible = "gmt,g762";
+					reg = <0x3e>;
+					clocks = <&g762_clk>; /* input clock */
+					fan_gear_mode = <0>;
+					fan_startv = <1>;
+					pwm_polarity = <0>;
+				};
+			};
+		};
+	};
+
+	clocks {
+	       #address-cells = <1>;
+	       #size-cells = <0>;
+
+	       g762_clk: fixedclk {
+			 compatible = "fixed-clock";
+			 #clock-cells = <0>;
+			 clock-frequency = <8192>;
+	       };
+	};
+
+	gpio_leds {
+		compatible = "gpio-leds";
+		pinctrl-0 = <&backup_led_pin &power_led_pin>;
+		pinctrl-names = "default";
+
+		blue_backup_led {
+			label = "rn104:blue:backup";
+			gpios = <&gpio1 31 0>;   /* GPIO 63 Active High */
+			default-state = "off";
+		};
+
+		blue_power_led {
+			label = "rn104:blue:pwr";
+			gpios = <&gpio2 0 1>;    /* GPIO 64 Active Low */
+			linux,default-trigger = "keep";
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = <&backup_key_pin
+			     &power_key_pin
+			     &reset_key_pin>;
+		pinctrl-names = "default";
+
+		button@1 {
+			label = "Backup Button";
+			linux,code = <133>;     /* KEY_COPY */
+			gpios = <&gpio1 20 1>;
+		};
+
+		button@2 {
+			label = "Power Button";
+			linux,code = <116>;     /* KEY_POWER */
+			gpios = <&gpio1 30 0>;
+		};
+
+		button@3 {
+			label = "Reset Button";
+			linux,code = <0x198>;   /* KEY_RESTART */
+			gpios = <&gpio2 1 1>;
+		};
+	};
+
+	gpio_poweroff {
+		compatible = "gpio-poweroff";
+		pinctrl-0 = <&poweroff>;
+		pinctrl-names = "default";
+		gpios = <&gpio1 28 1>;
+	};
+};
diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
index 1de2dae..00d6a79 100644
--- a/arch/arm/boot/dts/armada-370-xp.dtsi
+++ b/arch/arm/boot/dts/armada-370-xp.dtsi
@@ -113,6 +113,7 @@
 				#interrupt-cells = <1>;
 				#size-cells = <1>;
 				interrupt-controller;
+				msi-controller;
 			};
 
 			coherency-fabric@20200 {
@@ -137,6 +138,14 @@
 				status = "disabled";
 			};
 
+			coredivclk: corediv-clock@18740 {
+				compatible = "marvell,armada-370-corediv-clock";
+				reg = <0x18740 0xc>;
+				#clock-cells = <1>;
+				clocks = <&mainpll>;
+				clock-output-names = "nand";
+			};
+
 			timer@20300 {
 				reg = <0x20300 0x30>, <0x21040 0x30>;
 				interrupts = <37>, <38>, <39>, <40>, <5>, <6>;
@@ -176,7 +185,6 @@
 
 			i2c0: i2c@11000 {
 				compatible = "marvell,mv64xxx-i2c";
-				reg = <0x11000 0x20>;
 				#address-cells = <1>;
 				#size-cells = <0>;
 				interrupts = <31>;
@@ -187,7 +195,6 @@
 
 			i2c1: i2c@11100 {
 				compatible = "marvell,mv64xxx-i2c";
-				reg = <0x11100 0x20>;
 				#address-cells = <1>;
 				#size-cells = <0>;
 				interrupts = <32>;
@@ -252,4 +259,13 @@
 
 		};
 	};
+
+	clocks {
+		/* 2 GHz fixed main PLL */
+		mainpll: mainpll {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <2000000000>;
+		};
+	};
  };
diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi
index e134d7a..7a4b82e 100644
--- a/arch/arm/boot/dts/armada-370.dtsi
+++ b/arch/arm/boot/dts/armada-370.dtsi
@@ -44,6 +44,7 @@
 			#address-cells = <3>;
 			#size-cells = <2>;
 
+			msi-parent = <&mpic>;
 			bus-range = <0x00 0xff>;
 
 			ranges =
@@ -218,6 +219,14 @@
 				};
 			};
 
+			i2c0: i2c@11000 {
+				reg = <0x11000 0x20>;
+			};
+
+			i2c1: i2c@11100 {
+				reg = <0x11100 0x20>;
+			};
+
 			usb@50000 {
 				clocks = <&coreclk 0>;
 			};
diff --git a/arch/arm/boot/dts/armada-xp-matrix.dts b/arch/arm/boot/dts/armada-xp-matrix.dts
new file mode 100644
index 0000000..e47c49e
--- /dev/null
+++ b/arch/arm/boot/dts/armada-xp-matrix.dts
@@ -0,0 +1,75 @@
+/*
+ * Device Tree file for Marvell Armada XP Matrix board
+ *
+ * Copyright (C) 2013 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+/dts-v1/;
+#include "armada-xp-mv78460.dtsi"
+
+/ {
+	model = "Marvell Armada XP Matrix Board";
+	compatible = "marvell,axp-matrix", "marvell,armadaxp-mv78460", "marvell,armadaxp", "marvell,armada-370-xp";
+
+	chosen {
+		bootargs = "console=ttyS0,115200 earlyprintk";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x00000000 0 0x80000000>; /* 2 GB */
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000>;
+
+		internal-regs {
+			serial@12000 {
+				clock-frequency = <250000000>;
+				status = "okay";
+			};
+			serial@12100 {
+				clock-frequency = <250000000>;
+				status = "okay";
+			};
+			serial@12200 {
+				clock-frequency = <250000000>;
+				status = "okay";
+			};
+			serial@12300 {
+				clock-frequency = <250000000>;
+				status = "okay";
+			};
+
+			sata@a0000 {
+				nr-ports = <2>;
+				status = "okay";
+			};
+
+			ethernet@30000 {
+				status = "okay";
+				phy-mode = "sgmii";
+			};
+
+			pcie-controller {
+				status = "okay";
+
+				pcie@1,0 {
+					/* Port 0, Lane 0 */
+					status = "okay";
+				};
+			};
+
+			usb@50000 {
+				status = "okay";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
index 0358a33..3f5e612 100644
--- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
@@ -57,6 +57,7 @@
 			#address-cells = <3>;
 			#size-cells = <2>;
 
+			msi-parent = <&mpic>;
 			bus-range = <0x00 0xff>;
 
 			ranges =
diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
index 0e82c50..3e9fd13 100644
--- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
@@ -58,6 +58,7 @@
 			#address-cells = <3>;
 			#size-cells = <2>;
 
+			msi-parent = <&mpic>;
 			bus-range = <0x00 0xff>;
 
 			ranges =
diff --git a/arch/arm/boot/dts/armada-xp-mv78460.dtsi b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
index e82c1b8..31ba6d8 100644
--- a/arch/arm/boot/dts/armada-xp-mv78460.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
@@ -74,6 +74,7 @@
 			#address-cells = <3>;
 			#size-cells = <2>;
 
+			msi-parent = <&mpic>;
 			bus-range = <0x00 0xff>;
 
 			ranges =
diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi
index 3058522..281c644 100644
--- a/arch/arm/boot/dts/armada-xp.dtsi
+++ b/arch/arm/boot/dts/armada-xp.dtsi
@@ -147,6 +147,16 @@
 				};
 			};
 
+			i2c0: i2c@11000 {
+				compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
+				reg = <0x11000 0x100>;
+			};
+
+			i2c1: i2c@11100 {
+				compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
+				reg = <0x11100 0x100>;
+			};
+
 			usb@50000 {
 				clocks = <&gateclk 18>;
 			};
diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
index 1373546..cb2c010 100644
--- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
+++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
@@ -96,7 +96,6 @@
 			};
 
 			spi0: spi@fffc8000 {
-				status = "okay";
 				cs-gpios = <0>, <&pioC 11 0>, <0>, <0>;
 				mtd_dataflash@0 {
 					compatible = "atmel,at45", "atmel,dataflash";
diff --git a/arch/arm/boot/dts/at91sam9g25.dtsi b/arch/arm/boot/dts/at91sam9g25.dtsi
index b4ec6fe..17b8799 100644
--- a/arch/arm/boot/dts/at91sam9g25.dtsi
+++ b/arch/arm/boot/dts/at91sam9g25.dtsi
@@ -7,6 +7,8 @@
  */
 
 #include "at91sam9x5.dtsi"
+#include "at91sam9x5_usart3.dtsi"
+#include "at91sam9x5_macb0.dtsi"
 
 / {
 	model = "Atmel AT91SAM9G25 SoC";
diff --git a/arch/arm/boot/dts/at91sam9g35.dtsi b/arch/arm/boot/dts/at91sam9g35.dtsi
index bebf9f5..e35c2fc 100644
--- a/arch/arm/boot/dts/at91sam9g35.dtsi
+++ b/arch/arm/boot/dts/at91sam9g35.dtsi
@@ -7,6 +7,7 @@
  */
 
 #include "at91sam9x5.dtsi"
+#include "at91sam9x5_macb0.dtsi"
 
 / {
 	model = "Atmel AT91SAM9G35 SoC";
diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
index 9fb7ffd..6224f9f 100644
--- a/arch/arm/boot/dts/at91sam9n12.dtsi
+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
@@ -437,6 +437,9 @@
 				compatible = "atmel,at91sam9g45-ssc";
 				reg = <0xf0010000 0x4000>;
 				interrupts = <28 IRQ_TYPE_LEVEL_HIGH 5>;
+				dmas = <&dma 0 AT91_DMA_CFG_PER_ID(21)>,
+				       <&dma 0 AT91_DMA_CFG_PER_ID(22)>;
+				dma-names = "tx", "rx";
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
 				status = "disabled";
diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/at91sam9n12ek.dts
index 27a9352..e9487f6 100644
--- a/arch/arm/boot/dts/at91sam9n12ek.dts
+++ b/arch/arm/boot/dts/at91sam9n12ek.dts
@@ -38,9 +38,18 @@
 				status = "okay";
 			};
 
+			ssc0: ssc@f0010000 {
+				status = "okay";
+			};
+
 			i2c0: i2c@f8010000 {
 				status = "okay";
 
+				wm8904: codec@1a {
+					compatible = "wm8904";
+					reg = <0x1a>;
+				};
+
 				qt1070: keyboard@1b {
 					compatible = "qt1070";
 					reg = <0x1b>;
@@ -82,6 +91,13 @@
 							<AT91_PIOA 2 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
 					};
 				};
+
+				sound {
+					pinctrl_pck0_as_audio_mck: pck0_as_audio_mck {
+						atmel,pins =
+							<AT91_PIOB 10 AT91_PERIPH_B AT91_PINCTRL_NONE>;
+					};
+				};
 			};
 
 			spi0: spi@f0000000 {
@@ -142,4 +158,22 @@
 			gpio-key,wakeup;
 		};
 	};
+
+	sound {
+		compatible = "atmel,asoc-wm8904";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pck0_as_audio_mck>;
+
+		atmel,model = "wm8904 @ AT91SAM9N12";
+		atmel,audio-routing =
+			"Headphone Jack", "HPOUTL",
+			"Headphone Jack", "HPOUTR",
+			"IN2L", "Line In Jack",
+			"IN2R", "Line In Jack",
+			"Mic", "MICBIAS",
+			"IN1L", "Mic";
+
+		atmel,ssc-controller = <&ssc0>;
+		atmel,audio-codec = <&wm8904>;
+	};
 };
diff --git a/arch/arm/boot/dts/at91sam9x25.dtsi b/arch/arm/boot/dts/at91sam9x25.dtsi
index 49e94ab..c255421 100644
--- a/arch/arm/boot/dts/at91sam9x25.dtsi
+++ b/arch/arm/boot/dts/at91sam9x25.dtsi
@@ -7,6 +7,9 @@
  */
 
 #include "at91sam9x5.dtsi"
+#include "at91sam9x5_usart3.dtsi"
+#include "at91sam9x5_macb0.dtsi"
+#include "at91sam9x5_macb1.dtsi"
 
 / {
 	model = "Atmel AT91SAM9X25 SoC";
@@ -22,27 +25,6 @@
 				       0x80000000 0xfffd0000 0xb83fffff  /* pioC */
 				       0x003fffff 0x003f8000 0x00000000  /* pioD */
 				      >;
-
-				macb1 {
-					pinctrl_macb1_rmii: macb1_rmii-0 {
-						atmel,pins =
-							<AT91_PIOC 16 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PC16 periph B */
-							 AT91_PIOC 18 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PC18 periph B */
-							 AT91_PIOC 19 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PC19 periph B */
-							 AT91_PIOC 20 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PC20 periph B */
-							 AT91_PIOC 21 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PC21 periph B */
-							 AT91_PIOC 27 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PC27 periph B */
-							 AT91_PIOC 28 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PC28 periph B */
-							 AT91_PIOC 29 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PC29 periph B */
-							 AT91_PIOC 30 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PC30 periph B */
-							 AT91_PIOC 31 AT91_PERIPH_B AT91_PINCTRL_NONE>;	/* PC31 periph B */
-					};
-				};
-			};
-
-			macb1: ethernet@f8030000 {
-				pinctrl-names = "default";
-				pinctrl-0 = <&pinctrl_macb1_rmii>;
 			};
 		};
 	};
diff --git a/arch/arm/boot/dts/at91sam9x35.dtsi b/arch/arm/boot/dts/at91sam9x35.dtsi
index 1a3d525..8eac66c 100644
--- a/arch/arm/boot/dts/at91sam9x35.dtsi
+++ b/arch/arm/boot/dts/at91sam9x35.dtsi
@@ -7,6 +7,7 @@
  */
 
 #include "at91sam9x5.dtsi"
+#include "at91sam9x5_macb0.dtsi"
 
 / {
 	model = "Atmel AT91SAM9X35 SoC";
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index e74dc15..40267a1 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -206,29 +206,6 @@
 					};
 				};
 
-				usart3 {
-					pinctrl_usart3: usart3-0 {
-						atmel,pins =
-							<AT91_PIOC 22 AT91_PERIPH_B AT91_PINCTRL_PULL_UP	/* PC22 periph B with pullup */
-							 AT91_PIOC 23 AT91_PERIPH_B AT91_PINCTRL_NONE>;	/* PC23 periph B */
-					};
-
-					pinctrl_usart3_rts: usart3_rts-0 {
-						atmel,pins =
-							<AT91_PIOC 24 AT91_PERIPH_B AT91_PINCTRL_NONE>;	/* PC24 periph B */
-					};
-
-					pinctrl_usart3_cts: usart3_cts-0 {
-						atmel,pins =
-							<AT91_PIOC 25 AT91_PERIPH_B AT91_PINCTRL_NONE>;	/* PC25 periph B */
-					};
-
-					pinctrl_usart3_sck: usart3_sck-0 {
-						atmel,pins =
-							<AT91_PIOC 26 AT91_PERIPH_B AT91_PINCTRL_NONE>;	/* PC26 periph B */
-					};
-				};
-
 				uart0 {
 					pinctrl_uart0: uart0-0 {
 						atmel,pins =
@@ -277,34 +254,6 @@
 					};
 				};
 
-				macb0 {
-					pinctrl_macb0_rmii: macb0_rmii-0 {
-						atmel,pins =
-							<AT91_PIOB 0 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB0 periph A */
-							 AT91_PIOB 1 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB1 periph A */
-							 AT91_PIOB 2 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB2 periph A */
-							 AT91_PIOB 3 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB3 periph A */
-							 AT91_PIOB 4 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB4 periph A */
-							 AT91_PIOB 5 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB5 periph A */
-							 AT91_PIOB 6 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB6 periph A */
-							 AT91_PIOB 7 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB7 periph A */
-							 AT91_PIOB 9 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB9 periph A */
-							 AT91_PIOB 10 AT91_PERIPH_A AT91_PINCTRL_NONE>;	/* PB10 periph A */
-					};
-
-					pinctrl_macb0_rmii_mii: macb0_rmii_mii-0 {
-						atmel,pins =
-							<AT91_PIOB 8 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB8 periph A */
-							 AT91_PIOB 11 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB11 periph A */
-							 AT91_PIOB 12 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB12 periph A */
-							 AT91_PIOB 13 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB13 periph A */
-							 AT91_PIOB 14 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB14 periph A */
-							 AT91_PIOB 15 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB15 periph A */
-							 AT91_PIOB 16 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB16 periph A */
-							 AT91_PIOB 17 AT91_PERIPH_A AT91_PINCTRL_NONE>;	/* PB17 periph A */
-					};
-				};
-
 				mmc0 {
 					pinctrl_mmc0_slot0_clk_cmd_dat0: mmc0_slot0_clk_cmd_dat0-0 {
 						atmel,pins =
@@ -610,22 +559,6 @@
 				status = "disabled";
 			};
 
-			macb0: ethernet@f802c000 {
-				compatible = "cdns,at32ap7000-macb", "cdns,macb";
-				reg = <0xf802c000 0x100>;
-				interrupts = <24 IRQ_TYPE_LEVEL_HIGH 3>;
-				pinctrl-names = "default";
-				pinctrl-0 = <&pinctrl_macb0_rmii>;
-				status = "disabled";
-			};
-
-			macb1: ethernet@f8030000 {
-				compatible = "cdns,at32ap7000-macb", "cdns,macb";
-				reg = <0xf8030000 0x100>;
-				interrupts = <27 IRQ_TYPE_LEVEL_HIGH 3>;
-				status = "disabled";
-			};
-
 			i2c0: i2c@f8010000 {
 				compatible = "atmel,at91sam9x5-i2c";
 				reg = <0xf8010000 0x100>;
diff --git a/arch/arm/boot/dts/at91sam9x5_macb0.dtsi b/arch/arm/boot/dts/at91sam9x5_macb0.dtsi
new file mode 100644
index 0000000..55731ff
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9x5_macb0.dtsi
@@ -0,0 +1,56 @@
+/*
+ * at91sam9x5_macb0.dtsi - Device Tree Include file for AT91SAM9x5 SoC with 1
+ * Ethernet interface.
+ *
+ * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+#include <dt-bindings/pinctrl/at91.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	ahb {
+		apb {
+			pinctrl@fffff400 {
+				macb0 {
+					pinctrl_macb0_rmii: macb0_rmii-0 {
+						atmel,pins =
+							<AT91_PIOB 0 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB0 periph A */
+							 AT91_PIOB 1 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB1 periph A */
+							 AT91_PIOB 2 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB2 periph A */
+							 AT91_PIOB 3 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB3 periph A */
+							 AT91_PIOB 4 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB4 periph A */
+							 AT91_PIOB 5 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB5 periph A */
+							 AT91_PIOB 6 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB6 periph A */
+							 AT91_PIOB 7 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB7 periph A */
+							 AT91_PIOB 9 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB9 periph A */
+							 AT91_PIOB 10 AT91_PERIPH_A AT91_PINCTRL_NONE>;	/* PB10 periph A */
+					};
+
+					pinctrl_macb0_rmii_mii: macb0_rmii_mii-0 {
+						atmel,pins =
+							<AT91_PIOB 8 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB8 periph A */
+							 AT91_PIOB 11 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB11 periph A */
+							 AT91_PIOB 12 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB12 periph A */
+							 AT91_PIOB 13 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB13 periph A */
+							 AT91_PIOB 14 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB14 periph A */
+							 AT91_PIOB 15 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB15 periph A */
+							 AT91_PIOB 16 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB16 periph A */
+							 AT91_PIOB 17 AT91_PERIPH_A AT91_PINCTRL_NONE>;	/* PB17 periph A */
+					};
+				};
+			};
+
+			macb0: ethernet@f802c000 {
+				compatible = "cdns,at32ap7000-macb", "cdns,macb";
+				reg = <0xf802c000 0x100>;
+				interrupts = <24 IRQ_TYPE_LEVEL_HIGH 3>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_macb0_rmii>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/at91sam9x5_macb1.dtsi b/arch/arm/boot/dts/at91sam9x5_macb1.dtsi
new file mode 100644
index 0000000..77425a6
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9x5_macb1.dtsi
@@ -0,0 +1,44 @@
+/*
+ * at91sam9x5_macb1.dtsi - Device Tree Include file for AT91SAM9x5 SoC with 2
+ * Ethernet interfaces.
+ *
+ * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+#include <dt-bindings/pinctrl/at91.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	ahb {
+		apb {
+			pinctrl@fffff400 {
+				macb1 {
+					pinctrl_macb1_rmii: macb1_rmii-0 {
+						atmel,pins =
+							<AT91_PIOC 16 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PC16 periph B */
+							 AT91_PIOC 18 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PC18 periph B */
+							 AT91_PIOC 19 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PC19 periph B */
+							 AT91_PIOC 20 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PC20 periph B */
+							 AT91_PIOC 21 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PC21 periph B */
+							 AT91_PIOC 27 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PC27 periph B */
+							 AT91_PIOC 28 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PC28 periph B */
+							 AT91_PIOC 29 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PC29 periph B */
+							 AT91_PIOC 30 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PC30 periph B */
+							 AT91_PIOC 31 AT91_PERIPH_B AT91_PINCTRL_NONE>;	/* PC31 periph B */
+					};
+				};
+			};
+
+			macb1: ethernet@f8030000 {
+				compatible = "cdns,at32ap7000-macb", "cdns,macb";
+				reg = <0xf8030000 0x100>;
+				interrupts = <27 IRQ_TYPE_LEVEL_HIGH 3>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_macb1_rmii>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/at91sam9x5_usart3.dtsi b/arch/arm/boot/dts/at91sam9x5_usart3.dtsi
new file mode 100644
index 0000000..2347e95
--- /dev/null
+++ b/arch/arm/boot/dts/at91sam9x5_usart3.dtsi
@@ -0,0 +1,51 @@
+/*
+ * at91sam9x5_usart3.dtsi - Device Tree Include file for AT91SAM9x5 SoC with
+ * 4 USART.
+ *
+ * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+#include <dt-bindings/pinctrl/at91.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	ahb {
+		apb {
+			pinctrl@fffff400 {
+				usart3 {
+					pinctrl_usart3: usart3-0 {
+						atmel,pins =
+							<AT91_PIOC 22 AT91_PERIPH_B AT91_PINCTRL_PULL_UP	/* PC22 periph B with pullup */
+							 AT91_PIOC 23 AT91_PERIPH_B AT91_PINCTRL_NONE>;		/* PC23 periph B */
+					};
+
+					pinctrl_usart3_rts: usart3_rts-0 {
+						atmel,pins =
+							<AT91_PIOC 24 AT91_PERIPH_B AT91_PINCTRL_NONE>;		/* PC24 periph B */
+					};
+
+					pinctrl_usart3_cts: usart3_cts-0 {
+						atmel,pins =
+							<AT91_PIOC 25 AT91_PERIPH_B AT91_PINCTRL_NONE>;		/* PC25 periph B */
+					};
+
+					pinctrl_usart3_sck: usart3_sck-0 {
+						atmel,pins =
+							<AT91_PIOC 26 AT91_PERIPH_B AT91_PINCTRL_NONE>;		/* PC26 periph B */
+					};
+				};
+			};
+
+			usart3: serial@f8028000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xf8028000 0x200>;
+				interrupts = <8 IRQ_TYPE_LEVEL_HIGH 5>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usart3>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/atlas6.dtsi b/arch/arm/boot/dts/atlas6.dtsi
index 6db4f81..978bab4 100644
--- a/arch/arm/boot/dts/atlas6.dtsi
+++ b/arch/arm/boot/dts/atlas6.dtsi
@@ -65,6 +65,11 @@
 				compatible = "sirf,prima2-rsc";
 				reg = <0x88020000 0x1000>;
 			};
+
+			cphifbg@88030000 {
+				compatible = "sirf,prima2-cphifbg";
+				reg = <0x88030000 0x1000>;
+			};
 		};
 
 		mem-iobg {
@@ -75,10 +80,17 @@
 
 			memory-controller@90000000 {
 				compatible = "sirf,prima2-memc";
-				reg = <0x90000000 0x10000>;
+				reg = <0x90000000 0x2000>;
 				interrupts = <27>;
 				clocks = <&clks 5>;
 			};
+
+			memc-monitor {
+				compatible = "sirf,prima2-memcmon";
+				reg = <0x90002000 0x200>;
+				interrupts = <4>;
+				clocks = <&clks 32>;
+			};
 		};
 
 		disp-iobg {
@@ -120,6 +132,20 @@
 			};
 		};
 
+		graphics2d-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xa0000000 0xa0000000 0x8000000>;
+
+			ble@a0000000 {
+				compatible = "sirf,atlas6-ble";
+				reg = <0xa0000000 0x2000>;
+				interrupts = <5>;
+				clocks = <&clks 33>;
+			};
+		};
+
 		dsp-iobg {
 			compatible = "simple-bus";
 			#address-cells = <1>;
@@ -271,6 +297,11 @@
 				compatible = "sirf,prima2-spi";
 				reg = <0xb0170000 0x10000>;
 				interrupts = <16>;
+				sirf,spi-num-chipselects = <1>;
+				sirf,spi-dma-rx-channel = <12>;
+				sirf,spi-dma-tx-channel = <13>;
+				#address-cells = <1>;
+				#size-cells = <0>;
 				clocks = <&clks 20>;
 				status = "disabled";
 			};
@@ -527,6 +558,18 @@
                                                 sirf,function = "usb1_utmi_drvbus";
                                         };
                                 };
+                                usb1_dp_dn_pins_a: usb1_dp_dn@0 {
+                                        usb1_dp_dn {
+                                                sirf,pins = "usb1_dp_dngrp";
+                                                sirf,function = "usb1_dp_dn";
+                                        };
+                                };
+                                uart1_route_io_usb1_pins_a: uart1_route_io_usb1@0 {
+                                        uart1_route_io_usb1 {
+                                                sirf,pins = "uart1_route_io_usb1grp";
+                                                sirf,function = "uart1_route_io_usb1";
+                                        };
+                                };
                                 warm_rst_pins_a: warm_rst@0 {
                                         warm_rst {
                                                 sirf,pins = "warm_rstgrp";
diff --git a/arch/arm/boot/dts/bcm11351-brt.dts b/arch/arm/boot/dts/bcm11351-brt.dts
index 9d36eb4..23cd16d 100644
--- a/arch/arm/boot/dts/bcm11351-brt.dts
+++ b/arch/arm/boot/dts/bcm11351-brt.dts
@@ -40,6 +40,7 @@
 
 	sdio4: sdio@3f1b0000 {
 		max-frequency = <48000000>;
+		cd-gpios = <&gpio 14 0>;
 		status = "okay";
 	};
 
diff --git a/arch/arm/boot/dts/bcm11351.dtsi b/arch/arm/boot/dts/bcm11351.dtsi
index 05a5aab..b0c0610 100644
--- a/arch/arm/boot/dts/bcm11351.dtsi
+++ b/arch/arm/boot/dts/bcm11351.dtsi
@@ -49,6 +49,36 @@
 		reg-io-width = <4>;
 	};
 
+	uart@3e001000 {
+		compatible = "brcm,bcm11351-dw-apb-uart", "snps,dw-apb-uart";
+		status = "disabled";
+		reg = <0x3e001000 0x1000>;
+		clock-frequency = <13000000>;
+		interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+	};
+
+	uart@3e002000 {
+		compatible = "brcm,bcm11351-dw-apb-uart", "snps,dw-apb-uart";
+		status = "disabled";
+		reg = <0x3e002000 0x1000>;
+		clock-frequency = <13000000>;
+		interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+	};
+
+	uart@3e003000 {
+		compatible = "brcm,bcm11351-dw-apb-uart", "snps,dw-apb-uart";
+		status = "disabled";
+		reg = <0x3e003000 0x1000>;
+		clock-frequency = <13000000>;
+		interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+	};
+
 	L2: l2-cache {
 		compatible = "brcm,bcm11351-a2-pl310-cache";
 		reg = <0x3ff20000 0x1000>;
@@ -68,31 +98,47 @@
 		clock-frequency = <32768>;
 	};
 
+	gpio: gpio@35003000 {
+		compatible = "brcm,bcm11351-gpio", "brcm,kona-gpio";
+		reg = <0x35003000 0x800>;
+		interrupts =
+		       <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH
+			GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH
+			GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH
+			GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH
+			GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH
+			GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+		#gpio-cells = <2>;
+		#interrupt-cells = <2>;
+		gpio-controller;
+		interrupt-controller;
+	};
+
 	sdio1: sdio@3f180000 {
 		compatible = "brcm,kona-sdhci";
 		reg = <0x3f180000 0x10000>;
-		interrupts = <0x0 77 0x4>;
+		interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
 		status = "disabled";
 	};
 
 	sdio2: sdio@3f190000 {
 		compatible = "brcm,kona-sdhci";
 		reg = <0x3f190000 0x10000>;
-		interrupts = <0x0 76 0x4>;
+		interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
 		status = "disabled";
 	};
 
 	sdio3: sdio@3f1a0000 {
 		compatible = "brcm,kona-sdhci";
 		reg = <0x3f1a0000 0x10000>;
-		interrupts = <0x0 74 0x4>;
+		interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
 		status = "disabled";
 	};
 
 	sdio4: sdio@3f1b0000 {
 		compatible = "brcm,kona-sdhci";
 		reg = <0x3f1b0000 0x10000>;
-		interrupts = <0x0 73 0x4>;
+		interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
 		status = "disabled";
 	};
 
diff --git a/arch/arm/boot/dts/bcm28155-ap.dts b/arch/arm/boot/dts/bcm28155-ap.dts
index 96ae67a..08e47c2 100644
--- a/arch/arm/boot/dts/bcm28155-ap.dts
+++ b/arch/arm/boot/dts/bcm28155-ap.dts
@@ -40,6 +40,7 @@
 
 	sdio4: sdio@3f1b0000 {
 		max-frequency = <48000000>;
+		cd-gpios = <&gpio 14 0>;
 		status = "okay";
 	};
 };
diff --git a/arch/arm/boot/dts/dove-cm-a510.dts b/arch/arm/boot/dts/dove-cm-a510.dts
index 61a8062..50c0d69 100644
--- a/arch/arm/boot/dts/dove-cm-a510.dts
+++ b/arch/arm/boot/dts/dove-cm-a510.dts
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-/include/ "dove.dtsi"
+#include "dove.dtsi"
 
 / {
 	model = "Compulab CM-A510";
diff --git a/arch/arm/boot/dts/dove-cubox.dts b/arch/arm/boot/dts/dove-cubox.dts
index 022646e..8349a24 100644
--- a/arch/arm/boot/dts/dove-cubox.dts
+++ b/arch/arm/boot/dts/dove-cubox.dts
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-/include/ "dove.dtsi"
+#include "dove.dtsi"
 
 / {
 	model = "SolidRun CuBox";
@@ -99,19 +99,13 @@
 			silabs,pll-master;
 		};
 
-		clkout1 {
-			reg = <1>;
+		clkout2 {
+			reg = <2>;
 			silabs,drive-strength = <8>;
 			silabs,multisynth-source = <1>;
 			silabs,clock-source = <0>;
 			silabs,pll-master;
 		};
-
-		clkout2 {
-			reg = <2>;
-			silabs,multisynth-source = <1>;
-			silabs,clock-source = <0>;
-		};
 	};
 };
 
@@ -132,3 +126,11 @@
 		reg = <0>;
 	};
 };
+
+&audio1 {
+	status = "okay";
+	clocks = <&gate_clk 13>, <&si5351 2>;
+	clock-names = "internal", "extclk";
+	pinctrl-0 = <&pmx_audio1_i2s1_spdifo &pmx_audio1_extclk>;
+	pinctrl-names = "default";
+};
diff --git a/arch/arm/boot/dts/dove-d2plug.dts b/arch/arm/boot/dts/dove-d2plug.dts
index e2222ce..c11d363 100644
--- a/arch/arm/boot/dts/dove-d2plug.dts
+++ b/arch/arm/boot/dts/dove-d2plug.dts
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-/include/ "dove.dtsi"
+#include "dove.dtsi"
 
 / {
 	model = "Globalscale D2Plug";
diff --git a/arch/arm/boot/dts/dove-d3plug.dts b/arch/arm/boot/dts/dove-d3plug.dts
new file mode 100644
index 0000000..f5f59bb
--- /dev/null
+++ b/arch/arm/boot/dts/dove-d3plug.dts
@@ -0,0 +1,103 @@
+/dts-v1/;
+
+#include "dove.dtsi"
+
+/ {
+	model = "Globalscale D3Plug";
+	compatible = "globalscale,d3plug", "marvell,dove";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x40000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8 earlyprintk root=/dev/mmcblk0p2 rw rootwait";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-0 = <&pmx_gpio_0 &pmx_gpio_1 &pmx_gpio_2>;
+		pinctrl-names = "default";
+
+		wlan-act {
+			label = "wlan-act";
+			gpios = <&gpio0 0 1>;
+		};
+
+		wlan-ap {
+			label = "wlan-ap";
+			gpios = <&gpio0 1 1>;
+		};
+
+		status {
+			label = "status";
+			gpios = <&gpio0 2 1>;
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		usb_power: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "USB Power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&gpio0 8 0>;
+			pinctrl-0 = <&pmx_gpio_8>;
+			pinctrl-names = "default";
+		};
+	};
+};
+
+&uart0 { status = "okay"; };
+&sata0 { status = "okay"; };
+&i2c0 { status = "okay"; };
+
+/* Samsung M8G2F eMMC */
+&sdio0 {
+	status = "okay";
+	non-removable;
+	bus-width = <4>;
+};
+
+/* Marvell SD8787 WLAN/BT */
+&sdio1 {
+	status = "okay";
+	non-removable;
+};
+
+&spi0 {
+	status = "okay";
+
+	/* spi0.0: 2M Flash Macronix MX25L1605D */
+	spi-flash@0 {
+		compatible = "st,m25l1605d";
+		spi-max-frequency = <86000000>;
+		reg = <0>;
+	};
+};
+
+&pcie {
+	status = "okay";
+	/* Fresco Logic USB3.0 xHCI controller */
+	pcie-port@0 {
+		status = "okay";
+		reset-gpios = <&gpio0 26 1>;
+		reset-delay-us = <20000>;
+		pinctrl-0 = <&pmx_camera_gpio>;
+		pinctrl-names = "default";
+	};
+	/* Mini-PCIe slot */
+	pcie-port@1 {
+		status = "okay";
+		reset-gpios = <&gpio0 25 1>;
+	};
+};
diff --git a/arch/arm/boot/dts/dove-dove-db.dts b/arch/arm/boot/dts/dove-dove-db.dts
index e5a920b..bb725dc 100644
--- a/arch/arm/boot/dts/dove-dove-db.dts
+++ b/arch/arm/boot/dts/dove-dove-db.dts
@@ -1,6 +1,6 @@
 /dts-v1/;
 
-/include/ "dove.dtsi"
+#include "dove.dtsi"
 
 / {
 	model = "Marvell DB-MV88AP510-BP Development Board";
diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi
index cc27916..113a8bc 100644
--- a/arch/arm/boot/dts/dove.dtsi
+++ b/arch/arm/boot/dts/dove.dtsi
@@ -1,8 +1,11 @@
 /include/ "skeleton.dtsi"
 
+#define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
+
 / {
 	compatible = "marvell,dove";
 	model = "Marvell Armada 88AP510 SoC";
+	interrupt-parent = <&intc>;
 
 	aliases {
 		gpio0 = &gpio0;
@@ -27,482 +30,576 @@
 		marvell,tauros2-cache-features = <0>;
 	};
 
-	soc@f1000000 {
-		compatible = "simple-bus";
-		#address-cells = <1>;
+	mbus {
+		compatible = "marvell,dove-mbus", "marvell,mbus", "simple-bus";
+		#address-cells = <2>;
 		#size-cells = <1>;
-		interrupt-parent = <&intc>;
+		controller = <&mbusc>;
+		pcie-mem-aperture = <0xe0000000 0x10000000>; /* 256M MEM space */
+		pcie-io-aperture  = <0xf2000000 0x00200000>; /*   2M I/O space */
 
-		ranges = <0xc8000000 0xc8000000 0x0100000   /* CESA SRAM   1M */
-		          0xe0000000 0xe0000000 0x8000000   /* PCIe0 Mem 128M */
-		          0xe8000000 0xe8000000 0x8000000   /* PCIe1 Mem 128M */
-		          0xf0000000 0xf0000000 0x0100000   /* ScratchPad  1M */
-		          0x00000000 0xf1000000 0x1000000   /* SB/NB regs 16M */
-		          0xf2000000 0xf2000000 0x0100000   /* PCIe0 I/O   1M */
-		          0xf2100000 0xf2100000 0x0100000   /* PCIe0 I/O   1M */
-		          0xf8000000 0xf8000000 0x8000000>; /* BootROM   128M */
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x0100000   /* MBUS regs  1M */
+			  MBUS_ID(0xf0, 0x02) 0 0xf1800000 0x1000000   /* AXI  regs 16M */
+			  MBUS_ID(0x01, 0xfd) 0 0xf8000000 0x8000000   /* BootROM  128M */
+			  MBUS_ID(0x03, 0x01) 0 0xc8000000 0x0100000   /* CESA SRAM  1M */
+			  MBUS_ID(0x0d, 0x00) 0 0xf0000000 0x0100000>; /* PMU  SRAM  1M */
 
-		timer: timer@20300 {
-			compatible = "marvell,orion-timer";
-			reg = <0x20300 0x20>;
-			interrupt-parent = <&bridge_intc>;
-			interrupts = <1>, <2>;
-			clocks = <&core_clk 0>;
-		};
-
-		intc: main-interrupt-ctrl@20200 {
-			compatible = "marvell,orion-intc";
-			interrupt-controller;
-			#interrupt-cells = <1>;
-			reg = <0x20200 0x10>, <0x20210 0x10>;
-		};
-
-		bridge_intc: bridge-interrupt-ctrl@20110 {
-			compatible = "marvell,orion-bridge-intc";
-			interrupt-controller;
-			#interrupt-cells = <1>;
-			reg = <0x20110 0x8>;
-			interrupts = <0>;
-			marvell,#interrupts = <5>;
-		};
-
-		core_clk: core-clocks@d0214 {
-			compatible = "marvell,dove-core-clock";
-			reg = <0xd0214 0x4>;
-			#clock-cells = <1>;
-		};
-
-		gate_clk: clock-gating-ctrl@d0038 {
-			compatible = "marvell,dove-gating-clock";
-			reg = <0xd0038 0x4>;
-			clocks = <&core_clk 0>;
-			#clock-cells = <1>;
-		};
-
-		thermal: thermal-diode@d001c {
-			compatible = "marvell,dove-thermal";
-			reg = <0xd001c 0x0c>, <0xd005c 0x08>;
-		};
-
-		uart0: serial@12000 {
-			compatible = "ns16550a";
-			reg = <0x12000 0x100>;
-			reg-shift = <2>;
-			interrupts = <7>;
-			clocks = <&core_clk 0>;
+		pcie: pcie-controller {
+			compatible = "marvell,dove-pcie";
 			status = "disabled";
-		};
+			device_type = "pci";
+			#address-cells = <3>;
+			#size-cells = <2>;
 
-		uart1: serial@12100 {
-			compatible = "ns16550a";
-			reg = <0x12100 0x100>;
-			reg-shift = <2>;
-			interrupts = <8>;
-			clocks = <&core_clk 0>;
-			pinctrl-0 = <&pmx_uart1>;
-			pinctrl-names = "default";
-			status = "disabled";
-		};
+			msi-parent = <&intc>;
+			bus-range = <0x00 0xff>;
 
-		uart2: serial@12200 {
-			compatible = "ns16550a";
-			reg = <0x12000 0x100>;
-			reg-shift = <2>;
-			interrupts = <9>;
-			clocks = <&core_clk 0>;
-			status = "disabled";
-		};
+			ranges = <0x82000000 0x0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x2000
+			          0x82000000 0x0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x2000
+				  0x82000000 0x1 0x0 MBUS_ID(0x04, 0xe8) 0 1 0   /* Port 0.0 Mem */
+				  0x81000000 0x1 0x0 MBUS_ID(0x04, 0xe0) 0 1 0   /* Port 0.0 I/O */
+				  0x82000000 0x2 0x0 MBUS_ID(0x08, 0xe8) 0 1 0   /* Port 1.0 Mem */
+				  0x81000000 0x2 0x0 MBUS_ID(0x08, 0xe0) 0 1 0>; /* Port 1.0 I/O */
 
-		uart3: serial@12300 {
-			compatible = "ns16550a";
-			reg = <0x12100 0x100>;
-			reg-shift = <2>;
-			interrupts = <10>;
-			clocks = <&core_clk 0>;
-			status = "disabled";
-		};
+			pcie-port@0 {
+				device_type = "pci";
+				status = "disabled";
+				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+				reg = <0x0800 0 0 0 0>;
+				clocks = <&gate_clk 4>;
+				marvell,pcie-port = <0>;
 
-		gpio0: gpio-ctrl@d0400 {
-			compatible = "marvell,orion-gpio";
-			#gpio-cells = <2>;
-			gpio-controller;
-			reg = <0xd0400 0x20>;
-			ngpios = <32>;
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			interrupts = <12>, <13>, <14>, <60>;
-		};
+				#address-cells = <3>;
+				#size-cells = <2>;
+				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
+				          0x81000000 0 0 0x81000000 0x1 0 1 0>;
 
-		gpio1: gpio-ctrl@d0420 {
-			compatible = "marvell,orion-gpio";
-			#gpio-cells = <2>;
-			gpio-controller;
-			reg = <0xd0420 0x20>;
-			ngpios = <32>;
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			interrupts = <61>;
-		};
-
-		gpio2: gpio-ctrl@e8400 {
-			compatible = "marvell,orion-gpio";
-			#gpio-cells = <2>;
-			gpio-controller;
-			reg = <0xe8400 0x0c>;
-			ngpios = <8>;
-		};
-
-		pinctrl: pin-ctrl@d0200 {
-			compatible = "marvell,dove-pinctrl";
-			reg = <0xd0200 0x10>;
-			clocks = <&gate_clk 22>;
-
-			pmx_gpio_0: pmx-gpio-0 {
-				marvell,pins = "mpp0";
-				marvell,function = "gpio";
+				#interrupt-cells = <1>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &intc 16>;
 			};
 
-			pmx_gpio_1: pmx-gpio-1 {
-				marvell,pins = "mpp1";
-				marvell,function = "gpio";
-			};
+			pcie-port@1 {
+				device_type = "pci";
+				status = "disabled";
+				assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
+				reg = <0x1000 0 0 0 0>;
+				clocks = <&gate_clk 5>;
+				marvell,pcie-port = <1>;
 
-			pmx_gpio_2: pmx-gpio-2 {
-				marvell,pins = "mpp2";
-				marvell,function = "gpio";
-			};
+				#address-cells = <3>;
+				#size-cells = <2>;
+				ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+				          0x81000000 0 0 0x81000000 0x2 0 1 0>;
 
-			pmx_gpio_3: pmx-gpio-3 {
-				marvell,pins = "mpp3";
-				marvell,function = "gpio";
-			};
-
-			pmx_gpio_4: pmx-gpio-4 {
-				marvell,pins = "mpp4";
-				marvell,function = "gpio";
-			};
-
-			pmx_gpio_5: pmx-gpio-5 {
-				marvell,pins = "mpp5";
-				marvell,function = "gpio";
-			};
-
-			pmx_gpio_6: pmx-gpio-6 {
-				marvell,pins = "mpp6";
-				marvell,function = "gpio";
-			};
-
-			pmx_gpio_7: pmx-gpio-7 {
-				marvell,pins = "mpp7";
-				marvell,function = "gpio";
-			};
-
-			pmx_gpio_8: pmx-gpio-8 {
-				marvell,pins = "mpp8";
-				marvell,function = "gpio";
-			};
-
-			pmx_gpio_9: pmx-gpio-9 {
-				marvell,pins = "mpp9";
-				marvell,function = "gpio";
-			};
-
-			pmx_gpio_10: pmx-gpio-10 {
-				marvell,pins = "mpp10";
-				marvell,function = "gpio";
-			};
-
-			pmx_gpio_11: pmx-gpio-11 {
-				marvell,pins = "mpp11";
-				marvell,function = "gpio";
-			};
-
-			pmx_gpio_12: pmx-gpio-12 {
-				marvell,pins = "mpp12";
-				marvell,function = "gpio";
-			};
-
-			pmx_gpio_13: pmx-gpio-13 {
-				marvell,pins = "mpp13";
-				marvell,function = "gpio";
-			};
-
-			pmx_gpio_14: pmx-gpio-14 {
-				marvell,pins = "mpp14";
-				marvell,function = "gpio";
-			};
-
-			pmx_gpio_15: pmx-gpio-15 {
-				marvell,pins = "mpp15";
-				marvell,function = "gpio";
-			};
-
-			pmx_gpio_16: pmx-gpio-16 {
-				marvell,pins = "mpp16";
-				marvell,function = "gpio";
-			};
-
-			pmx_gpio_17: pmx-gpio-17 {
-				marvell,pins = "mpp17";
-				marvell,function = "gpio";
-			};
-
-			pmx_gpio_18: pmx-gpio-18 {
-				marvell,pins = "mpp18";
-				marvell,function = "gpio";
-			};
-
-			pmx_gpio_19: pmx-gpio-19 {
-				marvell,pins = "mpp19";
-				marvell,function = "gpio";
-			};
-
-			pmx_gpio_20: pmx-gpio-20 {
-				marvell,pins = "mpp20";
-				marvell,function = "gpio";
-			};
-
-			pmx_gpio_21: pmx-gpio-21 {
-				marvell,pins = "mpp21";
-				marvell,function = "gpio";
-			};
-
-			pmx_camera: pmx-camera {
-				marvell,pins = "mpp_camera";
-				marvell,function = "camera";
-			};
-
-			pmx_camera_gpio: pmx-camera-gpio {
-				marvell,pins = "mpp_camera";
-				marvell,function = "gpio";
-			};
-
-			pmx_sdio0: pmx-sdio0 {
-				marvell,pins = "mpp_sdio0";
-				marvell,function = "sdio0";
-			};
-
-			pmx_sdio0_gpio: pmx-sdio0-gpio {
-				marvell,pins = "mpp_sdio0";
-				marvell,function = "gpio";
-			};
-
-			pmx_sdio1: pmx-sdio1 {
-				marvell,pins = "mpp_sdio1";
-				marvell,function = "sdio1";
-			};
-
-			pmx_sdio1_gpio: pmx-sdio1-gpio {
-				marvell,pins = "mpp_sdio1";
-				marvell,function = "gpio";
-			};
-
-			pmx_audio1_gpio: pmx-audio1-gpio {
-				marvell,pins = "mpp_audio1";
-				marvell,function = "gpio";
-			};
-
-			pmx_spi0: pmx-spi0 {
-				marvell,pins = "mpp_spi0";
-				marvell,function = "spi0";
-			};
-
-			pmx_spi0_gpio: pmx-spi0-gpio {
-				marvell,pins = "mpp_spi0";
-				marvell,function = "gpio";
-			};
-
-			pmx_uart1: pmx-uart1 {
-				marvell,pins = "mpp_uart1";
-				marvell,function = "uart1";
-			};
-
-			pmx_uart1_gpio: pmx-uart1-gpio {
-				marvell,pins = "mpp_uart1";
-				marvell,function = "gpio";
-			};
-
-			pmx_nand: pmx-nand {
-				marvell,pins = "mpp_nand";
-				marvell,function = "nand";
-			};
-
-			pmx_nand_gpo: pmx-nand-gpo {
-				marvell,pins = "mpp_nand";
-				marvell,function = "gpo";
+				#interrupt-cells = <1>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &intc 18>;
 			};
 		};
 
-		spi0: spi-ctrl@10600 {
-			compatible = "marvell,orion-spi";
+		internal-regs {
+			compatible = "simple-bus";
 			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <0>;
-			interrupts = <6>;
-			reg = <0x10600 0x28>;
-			clocks = <&core_clk 0>;
-			pinctrl-0 = <&pmx_spi0>;
-			pinctrl-names = "default";
-			status = "disabled";
-		};
+			#size-cells = <1>;
+			ranges = <0x00000000 MBUS_ID(0xf0, 0x01) 0 0x0100000   /* MBUS regs  1M */
+				  0x00800000 MBUS_ID(0xf0, 0x02) 0 0x1000000   /* AXI  regs 16M */
+				  0xffffe000 MBUS_ID(0x03, 0x01) 0 0x0000800   /* CESA SRAM  2k */
+				  0xfffff000 MBUS_ID(0x0d, 0x00) 0 0x0000800>; /* PMU  SRAM  2k */
 
-		spi1: spi-ctrl@14600 {
-			compatible = "marvell,orion-spi";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			cell-index = <1>;
-			interrupts = <5>;
-			reg = <0x14600 0x28>;
-			clocks = <&core_clk 0>;
-			status = "disabled";
-		};
-
-		i2c0: i2c-ctrl@11000 {
-			compatible = "marvell,mv64xxx-i2c";
-			reg = <0x11000 0x20>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			interrupts = <11>;
-			clock-frequency = <400000>;
-			timeout-ms = <1000>;
-			clocks = <&core_clk 0>;
-			status = "disabled";
-		};
-
-		ehci0: usb-host@50000 {
-			compatible = "marvell,orion-ehci";
-			reg = <0x50000 0x1000>;
-			interrupts = <24>;
-			clocks = <&gate_clk 0>;
-			status = "okay";
-		};
-
-		ehci1: usb-host@51000 {
-			compatible = "marvell,orion-ehci";
-			reg = <0x51000 0x1000>;
-			interrupts = <25>;
-			clocks = <&gate_clk 1>;
-			status = "okay";
-		};
-
-		sdio0: sdio-host@92000 {
-			compatible = "marvell,dove-sdhci";
-			reg = <0x92000 0x100>;
-			interrupts = <35>, <37>;
-			clocks = <&gate_clk 8>;
-			pinctrl-0 = <&pmx_sdio0>;
-			pinctrl-names = "default";
-			status = "disabled";
-		};
-
-		sdio1: sdio-host@90000 {
-			compatible = "marvell,dove-sdhci";
-			reg = <0x90000 0x100>;
-			interrupts = <36>, <38>;
-			clocks = <&gate_clk 9>;
-			pinctrl-0 = <&pmx_sdio1>;
-			pinctrl-names = "default";
-			status = "disabled";
-		};
-
-		sata0: sata-host@a0000 {
-			compatible = "marvell,orion-sata";
-			reg = <0xa0000 0x2400>;
-			interrupts = <62>;
-			clocks = <&gate_clk 3>;
-			nr-ports = <1>;
-			status = "disabled";
-		};
-
-		rtc: real-time-clock@d8500 {
-			compatible = "marvell,orion-rtc";
-			reg = <0xd8500 0x20>;
-		};
-
-		crypto: crypto-engine@30000 {
-			compatible = "marvell,orion-crypto";
-			reg = <0x30000 0x10000>,
-			      <0xc8000000 0x800>;
-			reg-names = "regs", "sram";
-			interrupts = <31>;
-			clocks = <&gate_clk 15>;
-			status = "okay";
-		};
-
-		xor0: dma-engine@60800 {
-			compatible = "marvell,orion-xor";
-			reg = <0x60800 0x100
-			       0x60a00 0x100>;
-			clocks = <&gate_clk 23>;
-			status = "okay";
-
-			channel0 {
-				interrupts = <39>;
-				dmacap,memcpy;
-				dmacap,xor;
+			mbusc: mbus-ctrl@20000 {
+				compatible = "marvell,mbus-controller";
+				reg = <0x20000 0x80>, <0x800100 0x8>;
 			};
 
-			channel1 {
-				interrupts = <40>;
-				dmacap,memset;
-				dmacap,memcpy;
-				dmacap,xor;
-			};
-		};
-
-		xor1: dma-engine@60900 {
-			compatible = "marvell,orion-xor";
-			reg = <0x60900 0x100
-			       0x60b00 0x100>;
-			clocks = <&gate_clk 24>;
-			status = "okay";
-
-			channel0 {
-				interrupts = <42>;
-				dmacap,memcpy;
-				dmacap,xor;
+			timer: timer@20300 {
+				compatible = "marvell,orion-timer";
+				reg = <0x20300 0x20>;
+				interrupt-parent = <&bridge_intc>;
+				interrupts = <1>, <2>;
+				clocks = <&core_clk 0>;
 			};
 
-			channel1 {
-				interrupts = <43>;
-				dmacap,memset;
-				dmacap,memcpy;
-				dmacap,xor;
+			intc: main-interrupt-ctrl@20200 {
+				compatible = "marvell,orion-intc";
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				reg = <0x20200 0x10>, <0x20210 0x10>;
 			};
-		};
 
-		mdio: mdio-bus@72004 {
-			compatible = "marvell,orion-mdio";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			reg = <0x72004 0x84>;
-			interrupts = <30>;
-			clocks = <&gate_clk 2>;
-			status = "disabled";
-
-			ethphy: ethernet-phy {
-				device-type = "ethernet-phy";
-				/* set phy address in board file */
+			bridge_intc: bridge-interrupt-ctrl@20110 {
+				compatible = "marvell,orion-bridge-intc";
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				reg = <0x20110 0x8>;
+				interrupts = <0>;
+				marvell,#interrupts = <5>;
 			};
-		};
 
-		eth: ethernet-controller@72000 {
-			compatible = "marvell,orion-eth";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			reg = <0x72000 0x4000>;
-			clocks = <&gate_clk 2>;
-			marvell,tx-checksum-limit = <1600>;
-			status = "disabled";
+			core_clk: core-clocks@d0214 {
+				compatible = "marvell,dove-core-clock";
+				reg = <0xd0214 0x4>;
+				#clock-cells = <1>;
+			};
 
-			ethernet-port@0 {
-				device_type = "network";
-				compatible = "marvell,orion-eth-port";
-				reg = <0>;
-				interrupts = <29>;
-				/* overwrite MAC address in bootloader */
-				local-mac-address = [00 00 00 00 00 00];
-				phy-handle = <&ethphy>;
+			gate_clk: clock-gating-ctrl@d0038 {
+				compatible = "marvell,dove-gating-clock";
+				reg = <0xd0038 0x4>;
+				clocks = <&core_clk 0>;
+				#clock-cells = <1>;
+			};
+
+			thermal: thermal-diode@d001c {
+				compatible = "marvell,dove-thermal";
+				reg = <0xd001c 0x0c>, <0xd005c 0x08>;
+			};
+
+			uart0: serial@12000 {
+				compatible = "ns16550a";
+				reg = <0x12000 0x100>;
+				reg-shift = <2>;
+				interrupts = <7>;
+				clocks = <&core_clk 0>;
+				status = "disabled";
+			};
+
+			uart1: serial@12100 {
+				compatible = "ns16550a";
+				reg = <0x12100 0x100>;
+				reg-shift = <2>;
+				interrupts = <8>;
+				clocks = <&core_clk 0>;
+				pinctrl-0 = <&pmx_uart1>;
+				pinctrl-names = "default";
+				status = "disabled";
+			};
+
+			uart2: serial@12200 {
+				compatible = "ns16550a";
+				reg = <0x12000 0x100>;
+				reg-shift = <2>;
+				interrupts = <9>;
+				clocks = <&core_clk 0>;
+				status = "disabled";
+			};
+
+			uart3: serial@12300 {
+				compatible = "ns16550a";
+				reg = <0x12100 0x100>;
+				reg-shift = <2>;
+				interrupts = <10>;
+				clocks = <&core_clk 0>;
+				status = "disabled";
+			};
+
+			gpio0: gpio-ctrl@d0400 {
+				compatible = "marvell,orion-gpio";
+				#gpio-cells = <2>;
+				gpio-controller;
+				reg = <0xd0400 0x20>;
+				ngpios = <32>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				interrupts = <12>, <13>, <14>, <60>;
+			};
+
+			gpio1: gpio-ctrl@d0420 {
+				compatible = "marvell,orion-gpio";
+				#gpio-cells = <2>;
+				gpio-controller;
+				reg = <0xd0420 0x20>;
+				ngpios = <32>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				interrupts = <61>;
+			};
+
+			gpio2: gpio-ctrl@e8400 {
+				compatible = "marvell,orion-gpio";
+				#gpio-cells = <2>;
+				gpio-controller;
+				reg = <0xe8400 0x0c>;
+				ngpios = <8>;
+			};
+
+			pinctrl: pin-ctrl@d0200 {
+				compatible = "marvell,dove-pinctrl";
+				reg = <0xd0200 0x10>;
+				clocks = <&gate_clk 22>;
+
+				pmx_gpio_0: pmx-gpio-0 {
+					marvell,pins = "mpp0";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_1: pmx-gpio-1 {
+					marvell,pins = "mpp1";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_2: pmx-gpio-2 {
+					marvell,pins = "mpp2";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_3: pmx-gpio-3 {
+					marvell,pins = "mpp3";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_4: pmx-gpio-4 {
+					marvell,pins = "mpp4";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_5: pmx-gpio-5 {
+					marvell,pins = "mpp5";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_6: pmx-gpio-6 {
+					marvell,pins = "mpp6";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_7: pmx-gpio-7 {
+					marvell,pins = "mpp7";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_8: pmx-gpio-8 {
+					marvell,pins = "mpp8";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_9: pmx-gpio-9 {
+					marvell,pins = "mpp9";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_10: pmx-gpio-10 {
+					marvell,pins = "mpp10";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_11: pmx-gpio-11 {
+					marvell,pins = "mpp11";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_12: pmx-gpio-12 {
+					marvell,pins = "mpp12";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_13: pmx-gpio-13 {
+					marvell,pins = "mpp13";
+					marvell,function = "gpio";
+				};
+
+				pmx_audio1_extclk: pmx-audio1-extclk {
+					marvell,pins = "mpp13";
+					marvell,function = "audio1";
+				};
+
+				pmx_gpio_14: pmx-gpio-14 {
+					marvell,pins = "mpp14";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_15: pmx-gpio-15 {
+					marvell,pins = "mpp15";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_16: pmx-gpio-16 {
+					marvell,pins = "mpp16";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_17: pmx-gpio-17 {
+					marvell,pins = "mpp17";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_18: pmx-gpio-18 {
+					marvell,pins = "mpp18";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_19: pmx-gpio-19 {
+					marvell,pins = "mpp19";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_20: pmx-gpio-20 {
+					marvell,pins = "mpp20";
+					marvell,function = "gpio";
+				};
+
+				pmx_gpio_21: pmx-gpio-21 {
+					marvell,pins = "mpp21";
+					marvell,function = "gpio";
+				};
+
+				pmx_camera: pmx-camera {
+					marvell,pins = "mpp_camera";
+					marvell,function = "camera";
+				};
+
+				pmx_camera_gpio: pmx-camera-gpio {
+					marvell,pins = "mpp_camera";
+					marvell,function = "gpio";
+				};
+
+				pmx_sdio0: pmx-sdio0 {
+					marvell,pins = "mpp_sdio0";
+					marvell,function = "sdio0";
+				};
+
+				pmx_sdio0_gpio: pmx-sdio0-gpio {
+					marvell,pins = "mpp_sdio0";
+					marvell,function = "gpio";
+				};
+
+				pmx_sdio1: pmx-sdio1 {
+					marvell,pins = "mpp_sdio1";
+					marvell,function = "sdio1";
+				};
+
+				pmx_sdio1_gpio: pmx-sdio1-gpio {
+					marvell,pins = "mpp_sdio1";
+					marvell,function = "gpio";
+				};
+
+				pmx_audio1_gpio: pmx-audio1-gpio {
+					marvell,pins = "mpp_audio1";
+					marvell,function = "gpio";
+				};
+
+				pmx_audio1_i2s1_spdifo: pmx-audio1-i2s1-spdifo {
+					marvell,pins = "mpp_audio1";
+					marvell,function = "i2s1/spdifo";
+				};
+
+				pmx_spi0: pmx-spi0 {
+					marvell,pins = "mpp_spi0";
+					marvell,function = "spi0";
+				};
+
+				pmx_spi0_gpio: pmx-spi0-gpio {
+					marvell,pins = "mpp_spi0";
+					marvell,function = "gpio";
+				};
+
+				pmx_uart1: pmx-uart1 {
+					marvell,pins = "mpp_uart1";
+					marvell,function = "uart1";
+				};
+
+				pmx_uart1_gpio: pmx-uart1-gpio {
+					marvell,pins = "mpp_uart1";
+					marvell,function = "gpio";
+				};
+
+				pmx_nand: pmx-nand {
+					marvell,pins = "mpp_nand";
+					marvell,function = "nand";
+				};
+
+				pmx_nand_gpo: pmx-nand-gpo {
+					marvell,pins = "mpp_nand";
+					marvell,function = "gpo";
+				};
+			};
+
+			spi0: spi-ctrl@10600 {
+				compatible = "marvell,orion-spi";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <0>;
+				interrupts = <6>;
+				reg = <0x10600 0x28>;
+				clocks = <&core_clk 0>;
+				pinctrl-0 = <&pmx_spi0>;
+				pinctrl-names = "default";
+				status = "disabled";
+			};
+
+			spi1: spi-ctrl@14600 {
+				compatible = "marvell,orion-spi";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <1>;
+				interrupts = <5>;
+				reg = <0x14600 0x28>;
+				clocks = <&core_clk 0>;
+				status = "disabled";
+			};
+
+			i2c0: i2c-ctrl@11000 {
+				compatible = "marvell,mv64xxx-i2c";
+				reg = <0x11000 0x20>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				interrupts = <11>;
+				clock-frequency = <400000>;
+				timeout-ms = <1000>;
+				clocks = <&core_clk 0>;
+				status = "disabled";
+			};
+
+			ehci0: usb-host@50000 {
+				compatible = "marvell,orion-ehci";
+				reg = <0x50000 0x1000>;
+				interrupts = <24>;
+				clocks = <&gate_clk 0>;
+				status = "okay";
+			};
+
+			ehci1: usb-host@51000 {
+				compatible = "marvell,orion-ehci";
+				reg = <0x51000 0x1000>;
+				interrupts = <25>;
+				clocks = <&gate_clk 1>;
+				status = "okay";
+			};
+
+			sdio0: sdio-host@92000 {
+				compatible = "marvell,dove-sdhci";
+				reg = <0x92000 0x100>;
+				interrupts = <35>, <37>;
+				clocks = <&gate_clk 8>;
+				pinctrl-0 = <&pmx_sdio0>;
+				pinctrl-names = "default";
+				status = "disabled";
+			};
+
+			sdio1: sdio-host@90000 {
+				compatible = "marvell,dove-sdhci";
+				reg = <0x90000 0x100>;
+				interrupts = <36>, <38>;
+				clocks = <&gate_clk 9>;
+				pinctrl-0 = <&pmx_sdio1>;
+				pinctrl-names = "default";
+				status = "disabled";
+			};
+
+			sata0: sata-host@a0000 {
+				compatible = "marvell,orion-sata";
+				reg = <0xa0000 0x2400>;
+				interrupts = <62>;
+				clocks = <&gate_clk 3>;
+				nr-ports = <1>;
+				status = "disabled";
+			};
+
+			rtc: real-time-clock@d8500 {
+				compatible = "marvell,orion-rtc";
+				reg = <0xd8500 0x20>;
+			};
+
+			crypto: crypto-engine@30000 {
+				compatible = "marvell,orion-crypto";
+				reg = <0x30000 0x10000>,
+				      <0xffffe000 0x800>;
+				reg-names = "regs", "sram";
+				interrupts = <31>;
+				clocks = <&gate_clk 15>;
+				status = "okay";
+			};
+
+			xor0: dma-engine@60800 {
+				compatible = "marvell,orion-xor";
+				reg = <0x60800 0x100
+				       0x60a00 0x100>;
+				clocks = <&gate_clk 23>;
+				status = "okay";
+
+				channel0 {
+					interrupts = <39>;
+					dmacap,memcpy;
+					dmacap,xor;
+				};
+
+				channel1 {
+					interrupts = <40>;
+					dmacap,memcpy;
+					dmacap,xor;
+				};
+			};
+
+			xor1: dma-engine@60900 {
+				compatible = "marvell,orion-xor";
+				reg = <0x60900 0x100
+				       0x60b00 0x100>;
+				clocks = <&gate_clk 24>;
+				status = "okay";
+
+				channel0 {
+					interrupts = <42>;
+					dmacap,memcpy;
+					dmacap,xor;
+				};
+
+				channel1 {
+					interrupts = <43>;
+					dmacap,memcpy;
+					dmacap,xor;
+				};
+			};
+
+			mdio: mdio-bus@72004 {
+				compatible = "marvell,orion-mdio";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x72004 0x84>;
+				interrupts = <30>;
+				clocks = <&gate_clk 2>;
+				status = "disabled";
+
+				ethphy: ethernet-phy {
+					device-type = "ethernet-phy";
+					/* set phy address in board file */
+				};
+			};
+
+			eth: ethernet-ctrl@72000 {
+				compatible = "marvell,orion-eth";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x72000 0x4000>;
+				clocks = <&gate_clk 2>;
+				marvell,tx-checksum-limit = <1600>;
+				status = "disabled";
+
+				ethernet-port@0 {
+					device_type = "network";
+					compatible = "marvell,orion-eth-port";
+					reg = <0>;
+					interrupts = <29>;
+					/* overwrite MAC address in bootloader */
+					local-mac-address = [00 00 00 00 00 00];
+					phy-handle = <&ethphy>;
+				};
+			};
+
+			audio0: audio-controller@b0000 {
+				compatible = "marvell,dove-audio";
+				reg = <0xb0000 0x2210>;
+				interrupts = <19>, <20>;
+				clocks = <&gate_clk 12>;
+				clock-names = "internal";
+				status = "disabled";
+			};
+
+			audio1: audio-controller@b4000 {
+				compatible = "marvell,dove-audio";
+				reg = <0xb4000 0x2210>;
+				interrupts = <21>, <22>;
+				clocks = <&gate_clk 13>;
+				clock-names = "internal";
+				status = "disabled";
 			};
 		};
 	};
diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts
new file mode 100644
index 0000000..5babba0
--- /dev/null
+++ b/arch/arm/boot/dts/dra7-evm.dts
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "dra7.dtsi"
+
+/ {
+	model = "TI DRA7";
+	compatible = "ti,dra7-evm", "ti,dra752", "ti,dra7";
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x60000000>; /* 1536 MB */
+	};
+
+	mmc2_3v3: fixedregulator-mmc2 {
+		compatible = "regulator-fixed";
+		regulator-name = "mmc2_3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+};
+
+&dra7_pmx_core {
+	i2c1_pins: pinmux_i2c1_pins {
+		pinctrl-single,pins = <
+			0x400 (PIN_INPUT | MUX_MODE0) /* i2c1_sda */
+			0x404 (PIN_INPUT | MUX_MODE0) /* i2c1_scl */
+		>;
+	};
+
+	i2c2_pins: pinmux_i2c2_pins {
+		pinctrl-single,pins = <
+			0x408 (PIN_INPUT | MUX_MODE0) /* i2c2_sda */
+			0x40c (PIN_INPUT | MUX_MODE0) /* i2c2_scl */
+		>;
+	};
+
+	i2c3_pins: pinmux_i2c3_pins {
+		pinctrl-single,pins = <
+			0x410 (PIN_INPUT | MUX_MODE0) /* i2c3_sda */
+			0x414 (PIN_INPUT | MUX_MODE0) /* i2c3_scl */
+		>;
+	};
+
+	mcspi1_pins: pinmux_mcspi1_pins {
+		pinctrl-single,pins = <
+			0x3a4 (PIN_INPUT | MUX_MODE0) /* spi2_clk */
+			0x3a8 (PIN_INPUT | MUX_MODE0) /* spi2_d1 */
+			0x3ac (PIN_INPUT | MUX_MODE0) /* spi2_d0 */
+			0x3b0 (PIN_INPUT_SLEW | MUX_MODE0) /* spi2_cs0 */
+			0x3b4 (PIN_INPUT_SLEW | MUX_MODE0) /* spi2_cs1 */
+			0x3b8 (PIN_INPUT_SLEW | MUX_MODE6) /* spi2_cs2 */
+			0x3bc (PIN_INPUT_SLEW | MUX_MODE6) /* spi2_cs3 */
+		>;
+	};
+
+	mcspi2_pins: pinmux_mcspi2_pins {
+		pinctrl-single,pins = <
+			0x3c0 (PIN_INPUT | MUX_MODE0) /* spi2_sclk */
+			0x3c4 (PIN_INPUT_SLEW | MUX_MODE0) /* spi2_d1 */
+			0x3c8 (PIN_INPUT_SLEW | MUX_MODE0) /* spi2_d1 */
+			0x3cc (PIN_INPUT_SLEW | MUX_MODE0) /* spi2_cs0 */
+		>;
+	};
+
+	uart1_pins: pinmux_uart1_pins {
+		pinctrl-single,pins = <
+			0x3e0 (PIN_INPUT_SLEW | MUX_MODE0) /* uart1_rxd */
+			0x3e4 (PIN_INPUT_SLEW | MUX_MODE0) /* uart1_txd */
+			0x3e8 (PIN_INPUT | MUX_MODE3) /* uart1_ctsn */
+			0x3ec (PIN_INPUT | MUX_MODE3) /* uart1_rtsn */
+		>;
+	};
+
+	uart2_pins: pinmux_uart2_pins {
+		pinctrl-single,pins = <
+			0x3f0 (PIN_INPUT | MUX_MODE0) /* uart2_rxd */
+			0x3f4 (PIN_INPUT | MUX_MODE0) /* uart2_txd */
+			0x3f8 (PIN_INPUT | MUX_MODE0) /* uart2_ctsn */
+			0x3fc (PIN_INPUT | MUX_MODE0) /* uart2_rtsn */
+		>;
+	};
+
+	uart3_pins: pinmux_uart3_pins {
+		pinctrl-single,pins = <
+			0x248 (PIN_INPUT_SLEW | MUX_MODE0) /* uart3_rxd */
+			0x24c (PIN_INPUT_SLEW | MUX_MODE0) /* uart3_txd */
+		>;
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	clock-frequency = <400000>;
+
+	tps659038: tps659038@58 {
+		compatible = "ti,tps659038";
+		reg = <0x58>;
+
+		tps659038_pmic {
+			compatible = "ti,tps659038-pmic";
+
+			regulators {
+				smps123_reg: smps123 {
+					/* VDD_MPU */
+					regulator-name = "smps123";
+					regulator-min-microvolt = < 850000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps45_reg: smps45 {
+					/* VDD_DSPEVE */
+					regulator-name = "smps45";
+					regulator-min-microvolt = < 850000>;
+					regulator-max-microvolt = <1150000>;
+					regulator-boot-on;
+				};
+
+				smps6_reg: smps6 {
+					/* VDD_GPU - over VDD_SMPS6 */
+					regulator-name = "smps6";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <12500000>;
+					regulator-boot-on;
+				};
+
+				smps7_reg: smps7 {
+					/* CORE_VDD */
+					regulator-name = "smps7";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1030000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps8_reg: smps8 {
+					/* VDD_IVAHD */
+					regulator-name = "smps8";
+					regulator-min-microvolt = < 850000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-boot-on;
+				};
+
+				smps9_reg: smps9 {
+					/* VDDS1V8 */
+					regulator-name = "smps9";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo1_reg: ldo1 {
+					/* LDO1_OUT --> SDIO  */
+					regulator-name = "ldo1";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-boot-on;
+				};
+
+				ldo2_reg: ldo2 {
+					/* VDD_RTCIO */
+					/* LDO2 -> VDDSHV5, LDO2 also goes to CAN_PHY_3V3 */
+					regulator-name = "ldo2";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-boot-on;
+				};
+
+				ldo3_reg: ldo3 {
+					/* VDDA_1V8_PHY */
+					regulator-name = "ldo3";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-boot-on;
+				};
+
+				ldo9_reg: ldo9 {
+					/* VDD_RTC */
+					regulator-name = "ldo9";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+					regulator-boot-on;
+				};
+
+				ldoln_reg: ldoln {
+					/* VDDA_1V8_PLL */
+					regulator-name = "ldoln";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldousb_reg: ldousb {
+					/* VDDA_3V_USB: VDDA_USBHS33 */
+					regulator-name = "ldousb";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-boot-on;
+				};
+			};
+		};
+	};
+};
+
+&i2c2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_pins>;
+	clock-frequency = <400000>;
+};
+
+&i2c3 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_pins>;
+	clock-frequency = <3400000>;
+};
+
+&mcspi1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcspi1_pins>;
+};
+
+&mcspi2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcspi2_pins>;
+};
+
+&uart1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+};
+
+&uart2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_pins>;
+};
+
+&uart3 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins>;
+};
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&ldo1_reg>;
+	bus-width = <4>;
+};
+
+&mmc2 {
+	status = "okay";
+	vmmc-supply = <&mmc2_3v3>;
+	bus-width = <8>;
+};
+
+&cpu0 {
+	cpu0-supply = <&smps123_reg>;
+};
diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
new file mode 100644
index 0000000..d0df4c4
--- /dev/null
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -0,0 +1,586 @@
+/*
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ * Based on "omap4.dtsi"
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/pinctrl/dra.h>
+
+#include "skeleton.dtsi"
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	compatible = "ti,dra7xx";
+	interrupt-parent = <&gic>;
+
+	aliases {
+		i2c0 = &i2c1;
+		i2c1 = &i2c2;
+		i2c2 = &i2c3;
+		i2c3 = &i2c4;
+		i2c4 = &i2c5;
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		serial3 = &uart4;
+		serial4 = &uart5;
+		serial5 = &uart6;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0>;
+
+			operating-points = <
+				/* kHz    uV */
+				1000000	1060000
+				1176000	1160000
+				>;
+		};
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <1>;
+		};
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	gic: interrupt-controller@48211000 {
+		compatible = "arm,cortex-a15-gic";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0x48211000 0x1000>,
+		      <0x48212000 0x1000>,
+		      <0x48214000 0x2000>,
+		      <0x48216000 0x2000>;
+		interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	/*
+	 * The soc node represents the soc top level view. It is uses for IPs
+	 * that are not memory mapped in the MPU view or for the MPU itself.
+	 */
+	soc {
+		compatible = "ti,omap-infra";
+		mpu {
+			compatible = "ti,omap5-mpu";
+			ti,hwmods = "mpu";
+		};
+	};
+
+	/*
+	 * XXX: Use a flat representation of the SOC interconnect.
+	 * The real OMAP interconnect network is quite complex.
+	 * Since that will not bring real advantage to represent that in DT for
+	 * the moment, just use a fake OCP bus entry to represent the whole bus
+	 * hierarchy.
+	 */
+	ocp {
+		compatible = "ti,omap4-l3-noc", "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		ti,hwmods = "l3_main_1", "l3_main_2";
+		reg = <0x44000000 0x2000>,
+		      <0x44800000 0x3000>;
+		interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+
+		counter32k: counter@4ae04000 {
+			compatible = "ti,omap-counter32k";
+			reg = <0x4ae04000 0x40>;
+			ti,hwmods = "counter_32k";
+		};
+
+		dra7_pmx_core: pinmux@4a003400 {
+			compatible = "pinctrl-single";
+			reg = <0x4a003400 0x0464>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-single,register-width = <32>;
+			pinctrl-single,function-mask = <0x3fffffff>;
+		};
+
+		sdma: dma-controller@4a056000 {
+			compatible = "ti,omap4430-sdma";
+			reg = <0x4a056000 0x1000>;
+			interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+			#dma-cells = <1>;
+			#dma-channels = <32>;
+			#dma-requests = <127>;
+		};
+
+		gpio1: gpio@4ae10000 {
+			compatible = "ti,omap4-gpio";
+			reg = <0x4ae10000 0x200>;
+			interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "gpio1";
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <1>;
+		};
+
+		gpio2: gpio@48055000 {
+			compatible = "ti,omap4-gpio";
+			reg = <0x48055000 0x200>;
+			interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "gpio2";
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <1>;
+		};
+
+		gpio3: gpio@48057000 {
+			compatible = "ti,omap4-gpio";
+			reg = <0x48057000 0x200>;
+			interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "gpio3";
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <1>;
+		};
+
+		gpio4: gpio@48059000 {
+			compatible = "ti,omap4-gpio";
+			reg = <0x48059000 0x200>;
+			interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "gpio4";
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <1>;
+		};
+
+		gpio5: gpio@4805b000 {
+			compatible = "ti,omap4-gpio";
+			reg = <0x4805b000 0x200>;
+			interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "gpio5";
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <1>;
+		};
+
+		gpio6: gpio@4805d000 {
+			compatible = "ti,omap4-gpio";
+			reg = <0x4805d000 0x200>;
+			interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "gpio6";
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <1>;
+		};
+
+		gpio7: gpio@48051000 {
+			compatible = "ti,omap4-gpio";
+			reg = <0x48051000 0x200>;
+			interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "gpio7";
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <1>;
+		};
+
+		gpio8: gpio@48053000 {
+			compatible = "ti,omap4-gpio";
+			reg = <0x48053000 0x200>;
+			interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "gpio8";
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <1>;
+		};
+
+		uart1: serial@4806a000 {
+			compatible = "ti,omap4-uart";
+			reg = <0x4806a000 0x100>;
+			interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "uart1";
+			clock-frequency = <48000000>;
+			status = "disabled";
+		};
+
+		uart2: serial@4806c000 {
+			compatible = "ti,omap4-uart";
+			reg = <0x4806c000 0x100>;
+			interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "uart2";
+			clock-frequency = <48000000>;
+			status = "disabled";
+		};
+
+		uart3: serial@48020000 {
+			compatible = "ti,omap4-uart";
+			reg = <0x48020000 0x100>;
+			interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "uart3";
+			clock-frequency = <48000000>;
+			status = "disabled";
+		};
+
+		uart4: serial@4806e000 {
+			compatible = "ti,omap4-uart";
+			reg = <0x4806e000 0x100>;
+			interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "uart4";
+			clock-frequency = <48000000>;
+                        status = "disabled";
+		};
+
+		uart5: serial@48066000 {
+			compatible = "ti,omap4-uart";
+			reg = <0x48066000 0x100>;
+			interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "uart5";
+			clock-frequency = <48000000>;
+			status = "disabled";
+		};
+
+		uart6: serial@48068000 {
+			compatible = "ti,omap4-uart";
+			reg = <0x48068000 0x100>;
+			interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "uart6";
+			clock-frequency = <48000000>;
+			status = "disabled";
+		};
+
+		uart7: serial@48420000 {
+			compatible = "ti,omap4-uart";
+			reg = <0x48420000 0x100>;
+			ti,hwmods = "uart7";
+			clock-frequency = <48000000>;
+			status = "disabled";
+		};
+
+		uart8: serial@48422000 {
+			compatible = "ti,omap4-uart";
+			reg = <0x48422000 0x100>;
+			ti,hwmods = "uart8";
+			clock-frequency = <48000000>;
+			status = "disabled";
+		};
+
+		uart9: serial@48424000 {
+			compatible = "ti,omap4-uart";
+			reg = <0x48424000 0x100>;
+			ti,hwmods = "uart9";
+			clock-frequency = <48000000>;
+			status = "disabled";
+		};
+
+		uart10: serial@4ae2b000 {
+			compatible = "ti,omap4-uart";
+			reg = <0x4ae2b000 0x100>;
+			ti,hwmods = "uart10";
+			clock-frequency = <48000000>;
+			status = "disabled";
+		};
+
+		timer1: timer@4ae18000 {
+			compatible = "ti,omap5430-timer";
+			reg = <0x4ae18000 0x80>;
+			interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer1";
+			ti,timer-alwon;
+		};
+
+		timer2: timer@48032000 {
+			compatible = "ti,omap5430-timer";
+			reg = <0x48032000 0x80>;
+			interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer2";
+		};
+
+		timer3: timer@48034000 {
+			compatible = "ti,omap5430-timer";
+			reg = <0x48034000 0x80>;
+			interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer3";
+		};
+
+		timer4: timer@48036000 {
+			compatible = "ti,omap5430-timer";
+			reg = <0x48036000 0x80>;
+			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer4";
+		};
+
+		timer5: timer@48820000 {
+			compatible = "ti,omap5430-timer";
+			reg = <0x48820000 0x80>;
+			interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer5";
+			ti,timer-dsp;
+		};
+
+		timer6: timer@48822000 {
+			compatible = "ti,omap5430-timer";
+			reg = <0x48822000 0x80>;
+			interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer6";
+			ti,timer-dsp;
+			ti,timer-pwm;
+		};
+
+		timer7: timer@48824000 {
+			compatible = "ti,omap5430-timer";
+			reg = <0x48824000 0x80>;
+			interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer7";
+			ti,timer-dsp;
+		};
+
+		timer8: timer@48826000 {
+			compatible = "ti,omap5430-timer";
+			reg = <0x48826000 0x80>;
+			interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer8";
+			ti,timer-dsp;
+			ti,timer-pwm;
+		};
+
+		timer9: timer@4803e000 {
+			compatible = "ti,omap5430-timer";
+			reg = <0x4803e000 0x80>;
+			interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer9";
+		};
+
+		timer10: timer@48086000 {
+			compatible = "ti,omap5430-timer";
+			reg = <0x48086000 0x80>;
+			interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer10";
+		};
+
+		timer11: timer@48088000 {
+			compatible = "ti,omap5430-timer";
+			reg = <0x48088000 0x80>;
+			interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer11";
+			ti,timer-pwm;
+		};
+
+		timer13: timer@48828000 {
+			compatible = "ti,omap5430-timer";
+			reg = <0x48828000 0x80>;
+			ti,hwmods = "timer13";
+			status = "disabled";
+		};
+
+		timer14: timer@4882a000 {
+			compatible = "ti,omap5430-timer";
+			reg = <0x4882a000 0x80>;
+			ti,hwmods = "timer14";
+			status = "disabled";
+		};
+
+		timer15: timer@4882c000 {
+			compatible = "ti,omap5430-timer";
+			reg = <0x4882c000 0x80>;
+			ti,hwmods = "timer15";
+			status = "disabled";
+		};
+
+		timer16: timer@4882e000 {
+			compatible = "ti,omap5430-timer";
+			reg = <0x4882e000 0x80>;
+			ti,hwmods = "timer16";
+			status = "disabled";
+		};
+
+		wdt2: wdt@4ae14000 {
+			compatible = "ti,omap4-wdt";
+			reg = <0x4ae14000 0x80>;
+			interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "wd_timer2";
+		};
+
+		i2c1: i2c@48070000 {
+			compatible = "ti,omap4-i2c";
+			reg = <0x48070000 0x100>;
+			interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "i2c1";
+			status = "disabled";
+		};
+
+		i2c2: i2c@48072000 {
+			compatible = "ti,omap4-i2c";
+			reg = <0x48072000 0x100>;
+			interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "i2c2";
+			status = "disabled";
+		};
+
+		i2c3: i2c@48060000 {
+			compatible = "ti,omap4-i2c";
+			reg = <0x48060000 0x100>;
+			interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "i2c3";
+			status = "disabled";
+		};
+
+		i2c4: i2c@4807a000 {
+			compatible = "ti,omap4-i2c";
+			reg = <0x4807a000 0x100>;
+			interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "i2c4";
+			status = "disabled";
+		};
+
+		i2c5: i2c@4807c000 {
+			compatible = "ti,omap4-i2c";
+			reg = <0x4807c000 0x100>;
+			interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "i2c5";
+			status = "disabled";
+		};
+
+		mmc1: mmc@4809c000 {
+			compatible = "ti,omap4-hsmmc";
+			reg = <0x4809c000 0x400>;
+			interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "mmc1";
+			ti,dual-volt;
+			ti,needs-special-reset;
+			dmas = <&sdma 61>, <&sdma 62>;
+			dma-names = "tx", "rx";
+			status = "disabled";
+		};
+
+		mmc2: mmc@480b4000 {
+			compatible = "ti,omap4-hsmmc";
+			reg = <0x480b4000 0x400>;
+			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "mmc2";
+			ti,needs-special-reset;
+			dmas = <&sdma 47>, <&sdma 48>;
+			dma-names = "tx", "rx";
+			status = "disabled";
+		};
+
+		mmc3: mmc@480ad000 {
+			compatible = "ti,omap4-hsmmc";
+			reg = <0x480ad000 0x400>;
+			interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "mmc3";
+			ti,needs-special-reset;
+			dmas = <&sdma 77>, <&sdma 78>;
+			dma-names = "tx", "rx";
+			status = "disabled";
+		};
+
+		mmc4: mmc@480d1000 {
+			compatible = "ti,omap4-hsmmc";
+			reg = <0x480d1000 0x400>;
+			interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "mmc4";
+			ti,needs-special-reset;
+			dmas = <&sdma 57>, <&sdma 58>;
+			dma-names = "tx", "rx";
+			status = "disabled";
+		};
+
+		mcspi1: spi@48098000 {
+			compatible = "ti,omap4-mcspi";
+			reg = <0x48098000 0x200>;
+			interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "mcspi1";
+			ti,spi-num-cs = <4>;
+			dmas = <&sdma 35>,
+			       <&sdma 36>,
+			       <&sdma 37>,
+			       <&sdma 38>,
+			       <&sdma 39>,
+			       <&sdma 40>,
+			       <&sdma 41>,
+			       <&sdma 42>;
+			dma-names = "tx0", "rx0", "tx1", "rx1",
+				    "tx2", "rx2", "tx3", "rx3";
+			status = "disabled";
+		};
+
+		mcspi2: spi@4809a000 {
+			compatible = "ti,omap4-mcspi";
+			reg = <0x4809a000 0x200>;
+			interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "mcspi2";
+			ti,spi-num-cs = <2>;
+			dmas = <&sdma 43>,
+			       <&sdma 44>,
+			       <&sdma 45>,
+			       <&sdma 46>;
+			dma-names = "tx0", "rx0", "tx1", "rx1";
+			status = "disabled";
+		};
+
+		mcspi3: spi@480b8000 {
+			compatible = "ti,omap4-mcspi";
+			reg = <0x480b8000 0x200>;
+			interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "mcspi3";
+			ti,spi-num-cs = <2>;
+			dmas = <&sdma 15>, <&sdma 16>;
+			dma-names = "tx0", "rx0";
+			status = "disabled";
+		};
+
+		mcspi4: spi@480ba000 {
+			compatible = "ti,omap4-mcspi";
+			reg = <0x480ba000 0x200>;
+			interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "mcspi4";
+			ti,spi-num-cs = <1>;
+			dmas = <&sdma 70>, <&sdma 71>;
+			dma-names = "tx0", "rx0";
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/ecx-common.dtsi b/arch/arm/boot/dts/ecx-common.dtsi
index e8559b7..bc22557 100644
--- a/arch/arm/boot/dts/ecx-common.dtsi
+++ b/arch/arm/boot/dts/ecx-common.dtsi
@@ -19,6 +19,14 @@
 		bootargs = "console=ttyAMA0";
 	};
 
+	psci {
+		compatible	= "arm,psci";
+		method		= "smc";
+		cpu_suspend	= <0x84000002>;
+		cpu_off		= <0x84000004>;
+		cpu_on		= <0x84000006>;
+	};
+
 	soc {
 		#address-cells = <1>;
 		#size-cells = <1>;
diff --git a/arch/arm/boot/dts/emev2-kzm9d-reference.dts b/arch/arm/boot/dts/emev2-kzm9d-reference.dts
deleted file mode 100644
index cceefda..0000000
--- a/arch/arm/boot/dts/emev2-kzm9d-reference.dts
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Device Tree Source for the KZM9D board
- *
- * Copyright (C) 2013 Renesas Solutions Corp.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-/dts-v1/;
-
-/include/ "emev2.dtsi"
-
-/ {
-	model = "EMEV2 KZM9D Board";
-	compatible = "renesas,kzm9d-reference", "renesas,emev2";
-
-	memory {
-		device_type = "memory";
-		reg = <0x40000000 0x8000000>;
-	};
-
-	chosen {
-		bootargs = "console=ttyS1,115200n81 ignore_loglevel root=/dev/nfs ip=dhcp";
-	};
-
-	reg_1p8v: regulator@0 {
-		compatible = "regulator-fixed";
-		regulator-name = "fixed-1.8V";
-		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <1800000>;
-		regulator-always-on;
-		regulator-boot-on;
-	};
-
-	reg_3p3v: regulator@1 {
-		compatible = "regulator-fixed";
-		regulator-name = "fixed-3.3V";
-		regulator-min-microvolt = <3300000>;
-		regulator-max-microvolt = <3300000>;
-		regulator-always-on;
-		regulator-boot-on;
-	};
-
-	lan9220@20000000 {
-		compatible = "smsc,lan9220", "smsc,lan9115";
-		reg = <0x20000000 0x10000>;
-		phy-mode = "mii";
-		interrupt-parent = <&gpio0>;
-		interrupts = <1 1>;	/* active high */
-		reg-io-width = <4>;
-		smsc,irq-active-high;
-		smsc,irq-push-pull;
-		vddvario-supply = <&reg_1p8v>;
-		vdd33a-supply = <&reg_3p3v>;
-	};
-};
diff --git a/arch/arm/boot/dts/emev2-kzm9d.dts b/arch/arm/boot/dts/emev2-kzm9d.dts
index f92e812..861aa7d 100644
--- a/arch/arm/boot/dts/emev2-kzm9d.dts
+++ b/arch/arm/boot/dts/emev2-kzm9d.dts
@@ -1,7 +1,7 @@
 /*
  * Device Tree Source for the KZM9D board
  *
- * Copyright (C) 2012 Renesas Solutions Corp.
+ * Copyright (C) 2013 Renesas Solutions Corp.
  *
  * This file is licensed under the terms of the GNU General Public License
  * version 2.  This program is licensed "as is" without any warranty of any
@@ -23,4 +23,35 @@
 	chosen {
 		bootargs = "console=ttyS1,115200n81 ignore_loglevel root=/dev/nfs ip=dhcp";
 	};
+
+	reg_1p8v: regulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-1.8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	reg_3p3v: regulator@1 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	lan9220@20000000 {
+		compatible = "smsc,lan9220", "smsc,lan9115";
+		reg = <0x20000000 0x10000>;
+		phy-mode = "mii";
+		interrupt-parent = <&gpio0>;
+		interrupts = <1 1>;	/* active high */
+		reg-io-width = <4>;
+		smsc,irq-active-high;
+		smsc,irq-push-pull;
+		vddvario-supply = <&reg_1p8v>;
+		vdd33a-supply = <&reg_3p3v>;
+	};
 };
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index caadc02..a73eeb5 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -49,6 +49,12 @@
 		reg = <0x10000000 0x100>;
 	};
 
+	mipi_phy: video-phy@10020710 {
+		compatible = "samsung,s5pv210-mipi-video-phy";
+		reg = <0x10020710 8>;
+		#phy-cells = <1>;
+	};
+
 	pd_mfc: mfc-power-domain@10023C40 {
 		compatible = "samsung,exynos4210-pd";
 		reg = <0x10023C40 0x20>;
@@ -161,6 +167,8 @@
 			clock-names = "csis", "sclk_csis";
 			bus-width = <4>;
 			samsung,power-domain = <&pd_cam>;
+			phys = <&mipi_phy 0>;
+			phy-names = "csis";
 			status = "disabled";
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -174,6 +182,8 @@
 			clock-names = "csis", "sclk_csis";
 			bus-width = <2>;
 			samsung,power-domain = <&pd_cam>;
+			phys = <&mipi_phy 2>;
+			phy-names = "csis";
 			status = "disabled";
 			#address-cells = <1>;
 			#size-cells = <0>;
diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/exynos4210-origen.dts
index 382d8c7..1a12fb2 100644
--- a/arch/arm/boot/dts/exynos4210-origen.dts
+++ b/arch/arm/boot/dts/exynos4210-origen.dts
@@ -32,13 +32,20 @@
 		bootargs ="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc";
 	};
 
-	mmc_reg: voltage-regulator {
-	        compatible = "regulator-fixed";
-		regulator-name = "VMEM_VDD_2.8V";
-		regulator-min-microvolt = <2800000>;
-		regulator-max-microvolt = <2800000>;
-		gpio = <&gpx1 1 0>;
-		enable-active-high;
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		mmc_reg: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "VMEM_VDD_2.8V";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			gpio = <&gpx1 1 0>;
+			enable-active-high;
+		};
 	};
 
 	tmu@100C0000 {
@@ -192,7 +199,12 @@
 				};
 
 				buck1_reg: BUCK1 {
-					regulator-name = "VDD_ARM_1.2V";
+					/*
+					* HACK: The real name is VDD_ARM_1.2V,
+					* but exynos-cpufreq does not support
+					* DT-based regulator lookup yet.
+					*/
+					regulator-name = "vdd_arm";
 					regulator-min-microvolt = <950000>;
 					regulator-max-microvolt	= <1350000>;
 					regulator-always-on;
diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts
index 1c164f2..63cc571 100644
--- a/arch/arm/boot/dts/exynos4210-trats.dts
+++ b/arch/arm/boot/dts/exynos4210-trats.dts
@@ -290,7 +290,12 @@
 				};
 
 				varm_breg: BUCK1 {
-				     regulator-name = "VARM_1.2V_C210";
+				     /*
+				      * HACK: The real name is VARM_1.2V_C210,
+				      * but exynos-cpufreq does not support
+				      * DT-based regulator lookup yet.
+				      */
+				     regulator-name = "vdd_arm";
 				     regulator-min-microvolt = <900000>;
 				     regulator-max-microvolt = <1350000>;
 				     regulator-always-on;
diff --git a/arch/arm/boot/dts/exynos4210-universal_c210.dts b/arch/arm/boot/dts/exynos4210-universal_c210.dts
index 889cdad..d2e3f5f 100644
--- a/arch/arm/boot/dts/exynos4210-universal_c210.dts
+++ b/arch/arm/boot/dts/exynos4210-universal_c210.dts
@@ -350,3 +350,7 @@
 		status = "okay";
 	};
 };
+
+&mdma1 {
+	reg = <0x12840000 0x1000>;
+};
diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/exynos4412-origen.dts
index 8768b03..d65984c 100644
--- a/arch/arm/boot/dts/exynos4412-origen.dts
+++ b/arch/arm/boot/dts/exynos4412-origen.dts
@@ -32,13 +32,20 @@
 		reg = <0x0203F000 0x1000>;
 	};
 
-	mmc_reg: voltage-regulator {
-		compatible = "regulator-fixed";
-		regulator-name = "VMEM_VDD_2.8V";
-		regulator-min-microvolt = <2800000>;
-		regulator-max-microvolt = <2800000>;
-		gpio = <&gpx1 1 0>;
-		enable-active-high;
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		mmc_reg: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "VMEM_VDD_2.8V";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			gpio = <&gpx1 1 0>;
+			enable-active-high;
+		};
 	};
 
 	pinctrl@11000000 {
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts
index cee55fa..6845270 100644
--- a/arch/arm/boot/dts/exynos5250-arndale.dts
+++ b/arch/arm/boot/dts/exynos5250-arndale.dts
@@ -324,7 +324,14 @@
 	};
 
 	i2c@12C80000 {
-		status = "disabled";
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <66000>;
+		samsung,i2c-slave-addr = <0x50>;
+
+		hdmiddc@50 {
+			compatible = "samsung,exynos4210-hdmiddc";
+			reg = <0x50>;
+		};
 	};
 
 	i2c@12C90000 {
@@ -362,6 +369,17 @@
 		status = "disabled";
 	};
 
+	i2c@12CE0000 {
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <66000>;
+		samsung,i2c-slave-addr = <0x38>;
+
+		hdmiphy@38 {
+			compatible = "samsung,exynos4212-hdmiphy";
+			reg = <0x38>;
+		};
+	};
+
 	i2c@121D0000 {
 		status = "disabled";
 	};
@@ -412,6 +430,10 @@
 		status = "disabled";
 	};
 
+	i2s0: i2s@03830000 {
+		status = "okay";
+	};
+
 	spi_0: spi@12d20000 {
 		status = "disabled";
 	};
@@ -482,13 +504,15 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		main_dc_reg: fixedregulator@1 {
+		main_dc_reg: regulator@0 {
 			compatible = "regulator-fixed";
+			reg = <0>;
 			regulator-name = "MAIN_DC";
 		};
 
-		mmc_reg: voltage-regulator {
+		mmc_reg: regulator@1 {
 			compatible = "regulator-fixed";
+			reg = <1>;
 			regulator-name = "VDD_33ON_2.8V";
 			regulator-min-microvolt = <2800000>;
 			regulator-max-microvolt = <2800000>;
@@ -496,8 +520,9 @@
 			enable-active-high;
 		};
 
-		reg_hdmi_en: fixedregulator@0 {
+		reg_hdmi_en: regulator@2 {
 			compatible = "regulator-fixed";
+			reg = <2>;
 			regulator-name = "hdmi-en";
 		};
 	};
diff --git a/arch/arm/boot/dts/exynos5250-pinctrl.dtsi b/arch/arm/boot/dts/exynos5250-pinctrl.dtsi
index 724a22f..9a49e68 100644
--- a/arch/arm/boot/dts/exynos5250-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos5250-pinctrl.dtsi
@@ -210,21 +210,21 @@
 			samsung,pins = "gpa0-2", "gpa0-3";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <0>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 
 		i2c2_bus: i2c2-bus {
 			samsung,pins = "gpa0-6", "gpa0-7";
 			samsung,pin-function = <3>;
 			samsung,pin-pud = <3>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 
 		i2c2_hs_bus: i2c2-hs-bus {
 			samsung,pins = "gpa0-6", "gpa0-7";
 			samsung,pin-function = <4>;
 			samsung,pin-pud = <3>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 
 		uart2_data: uart2-data {
@@ -238,21 +238,21 @@
 			samsung,pins = "gpa1-2", "gpa1-3";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <0>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 
 		i2c3_bus: i2c3-bus {
 			samsung,pins = "gpa1-2", "gpa1-3";
 			samsung,pin-function = <3>;
 			samsung,pin-pud = <3>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 
 		i2c3_hs_bus: i2c3-hs-bus {
 			samsung,pins = "gpa1-2", "gpa1-3";
 			samsung,pin-function = <4>;
 			samsung,pin-pud = <3>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 
 		uart3_data: uart3-data {
@@ -273,14 +273,14 @@
 			samsung,pins = "gpa2-0", "gpa2-1";
 			samsung,pin-function = <3>;
 			samsung,pin-pud = <3>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 
 		i2c5_bus: i2c5-bus {
 			samsung,pins = "gpa2-2", "gpa2-3";
 			samsung,pin-function = <3>;
 			samsung,pin-pud = <3>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 
 		spi1_bus: spi1-bus {
@@ -376,14 +376,14 @@
 			samsung,pins = "gpb3-0", "gpb3-1";
 			samsung,pin-function = <4>;
 			samsung,pin-pud = <3>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 
 		i2c1_hs_bus: i2c1-hs-bus {
 			samsung,pins = "gpb3-2", "gpb3-3";
 			samsung,pin-function = <4>;
 			samsung,pin-pud = <3>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 
 		sd0_clk: sd0-clk {
@@ -551,14 +551,14 @@
 			samsung,pins = "gpd0-2", "gpd0-3";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <0>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 
 		dp_hpd: dp_hpd {
 			samsung,pins = "gpx0-7";
 			samsung,pin-function = <3>;
 			samsung,pin-pud = <0>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 	};
 
@@ -649,42 +649,42 @@
 				       "gpf1-0", "gpf1-1", "gpf1-2", "gpf1-3";
 			samsung,pin-function = <3>;
 			samsung,pin-pud = <0>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 
 		cam_i2c2_bus: cam-i2c2-bus {
 			samsung,pins = "gpe0-6", "gpe1-0";
 			samsung,pin-function = <4>;
 			samsung,pin-pud = <3>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 
 		cam_spi1_bus: cam-spi1-bus {
 			samsung,pins = "gpe0-4", "gpe0-5", "gpf0-2", "gpf0-3";
 			samsung,pin-function = <4>;
 			samsung,pin-pud = <0>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 
 		cam_i2c1_bus: cam-i2c1-bus {
 			samsung,pins = "gpf0-2", "gpf0-3";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <3>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 
 		cam_i2c0_bus: cam-i2c0-bus {
 			samsung,pins = "gpf0-0", "gpf0-1";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <3>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 
 		cam_spi0_bus: cam-spi0-bus {
 			samsung,pins = "gpf1-0", "gpf1-1", "gpf1-2", "gpf1-3";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <0>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 
 		cam_bayrgb_bus: cam-bayrgb-bus {
@@ -695,7 +695,7 @@
 				       "gpg2-0", "gpg2-1";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <0>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 
 		cam_port_a: cam-port-a {
@@ -704,7 +704,7 @@
 				       "gph1-4", "gph1-5", "gph1-6", "gph1-7";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <0>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 	};
 
@@ -756,7 +756,7 @@
 				       "gpv1-4", "gpv1-5", "gpv1-6", "gpv1-7";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <0>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 
 		c2c_txd: c2c-txd {
@@ -766,7 +766,7 @@
 				       "gpv3-4", "gpv3-5", "gpv3-6", "gpv3-7";
 			samsung,pin-function = <2>;
 			samsung,pin-pud = <0>;
-			samaung,pin-drv = <0>;
+			samsung,pin-drv = <0>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts
index 2538b32..f86d567 100644
--- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts
@@ -231,14 +231,6 @@
 		status = "okay";
 	};
 
-	i2s1: i2s@12D60000 {
-		status = "disabled";
-	};
-
-	i2s2: i2s@12D70000 {
-		status = "disabled";
-	};
-
 	sound {
 		compatible = "samsung,smdk-wm8994";
 
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index 7d7cc77..9db5047 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -96,6 +96,11 @@
 			     <1 14 0xf08>,
 			     <1 11 0xf08>,
 			     <1 10 0xf08>;
+		/* Unfortunately we need this since some versions of U-Boot
+		 * on Exynos don't set the CNTFRQ register, so we need the
+		 * value from DT.
+		 */
+		clock-frequency = <24000000>;
 	};
 
 	mct@101C0000 {
@@ -417,6 +422,7 @@
 
 	i2s0: i2s@03830000 {
 		compatible = "samsung,s5pv210-i2s";
+		status = "disabled";
 		reg = <0x03830000 0x100>;
 		dmas = <&pdma0 10
 			&pdma0 9
@@ -433,6 +439,7 @@
 
 	i2s1: i2s@12D60000 {
 		compatible = "samsung,s3c6410-i2s";
+		status = "disabled";
 		reg = <0x12D60000 0x100>;
 		dmas = <&pdma1 12
 			&pdma1 11>;
@@ -445,6 +452,7 @@
 
 	i2s2: i2s@12D70000 {
 		compatible = "samsung,s3c6410-i2s";
+		status = "disabled";
 		reg = <0x12D70000 0x100>;
 		dmas = <&pdma0 12
 			&pdma0 11>;
@@ -610,16 +618,18 @@
 		compatible = "samsung,exynos4212-hdmi";
 		reg = <0x14530000 0x70000>;
 		interrupts = <0 95 0>;
-		clocks = <&clock 333>, <&clock 136>, <&clock 137>,
-				<&clock 333>, <&clock 333>;
+		clocks = <&clock 344>, <&clock 136>, <&clock 137>,
+				<&clock 159>, <&clock 1024>;
 		clock-names = "hdmi", "sclk_hdmi", "sclk_pixel",
-				"sclk_hdmiphy", "hdmiphy";
+				"sclk_hdmiphy", "mout_hdmi";
 	};
 
 	mixer {
 		compatible = "samsung,exynos5250-mixer";
 		reg = <0x14450000 0x10000>;
 		interrupts = <0 94 0>;
+		clocks = <&clock 343>, <&clock 136>;
+		clock-names = "mixer", "sclk_hdmi";
 	};
 
 	dp_phy: video-phy@10040720 {
diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts
index bafba25..79524c7 100644
--- a/arch/arm/boot/dts/exynos5420-smdk5420.dts
+++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts
@@ -61,4 +61,30 @@
 		};
 	};
 
+	pinctrl@13400000 {
+		hdmi_hpd_irq: hdmi-hpd-irq {
+			samsung,pins = "gpx3-7";
+			samsung,pin-function = <0>;
+			samsung,pin-pud = <1>;
+			samsung,pin-drv = <0>;
+		};
+	};
+
+	hdmi@14530000 {
+		status = "okay";
+		hpd-gpio = <&gpx3 7 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&hdmi_hpd_irq>;
+	};
+
+	i2c_2: i2c@12C80000 {
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-max-bus-freq = <66000>;
+		status = "okay";
+
+		hdmiddc@50 {
+			compatible = "samsung,exynos4210-hdmiddc";
+			reg = <0x50>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index d537cd7..09aa06c 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -27,6 +27,10 @@
 		pinctrl2 = &pinctrl_2;
 		pinctrl3 = &pinctrl_3;
 		pinctrl4 = &pinctrl_4;
+		i2c0 = &i2c_0;
+		i2c1 = &i2c_1;
+		i2c2 = &i2c_2;
+		i2c3 = &i2c_3;
 	};
 
 	cpus {
@@ -235,4 +239,75 @@
 		io-channel-ranges;
 		status = "disabled";
 	};
+
+	i2c_0: i2c@12C60000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x12C60000 0x100>;
+		interrupts = <0 56 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&clock 261>;
+		clock-names = "i2c";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c0_bus>;
+		status = "disabled";
+	};
+
+	i2c_1: i2c@12C70000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x12C70000 0x100>;
+		interrupts = <0 57 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&clock 262>;
+		clock-names = "i2c";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c1_bus>;
+		status = "disabled";
+	};
+
+	i2c_2: i2c@12C80000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x12C80000 0x100>;
+		interrupts = <0 58 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&clock 263>;
+		clock-names = "i2c";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c2_bus>;
+		status = "disabled";
+	};
+
+	i2c_3: i2c@12C90000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x12C90000 0x100>;
+		interrupts = <0 59 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&clock 264>;
+		clock-names = "i2c";
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c3_bus>;
+		status = "disabled";
+	};
+
+	hdmi@14530000 {
+		compatible = "samsung,exynos4212-hdmi";
+		reg = <0x14530000 0x70000>;
+		interrupts = <0 95 0>;
+		clocks = <&clock 413>, <&clock 143>, <&clock 768>,
+			<&clock 158>, <&clock 640>;
+		clock-names = "hdmi", "sclk_hdmi", "sclk_pixel",
+			"sclk_hdmiphy", "mout_hdmi";
+		status = "disabled";
+	};
+
+	mixer@14450000 {
+		compatible = "samsung,exynos5420-mixer";
+		reg = <0x14450000 0x10000>;
+		interrupts = <0 94 0>;
+		clocks = <&clock 431>, <&clock 143>;
+		clock-names = "mixer", "sclk_hdmi";
+	};
 };
diff --git a/arch/arm/boot/dts/exynos5440-sd5v1.dts b/arch/arm/boot/dts/exynos5440-sd5v1.dts
index 5b22508..777fb1c 100644
--- a/arch/arm/boot/dts/exynos5440-sd5v1.dts
+++ b/arch/arm/boot/dts/exynos5440-sd5v1.dts
@@ -17,7 +17,7 @@
 	compatible = "samsung,sd5v1", "samsung,exynos5440";
 
 	chosen {
-		bootargs = "root=/dev/sda2 rw rootwait ignore_loglevel early_printk no_console_suspend mem=2048M@0x80000000 mem=6144M@0x100000000 console=ttySAC0,115200";
+		bootargs = "root=/dev/sda2 rw rootwait ignore_loglevel earlyprintk no_console_suspend mem=2048M@0x80000000 mem=6144M@0x100000000 console=ttySAC0,115200";
 	};
 
 	fixed-rate-clocks {
diff --git a/arch/arm/boot/dts/exynos5440-ssdk5440.dts b/arch/arm/boot/dts/exynos5440-ssdk5440.dts
index ede7727..d58cb78 100644
--- a/arch/arm/boot/dts/exynos5440-ssdk5440.dts
+++ b/arch/arm/boot/dts/exynos5440-ssdk5440.dts
@@ -17,7 +17,7 @@
 	compatible = "samsung,ssdk5440", "samsung,exynos5440";
 
 	chosen {
-		bootargs = "root=/dev/sda2 rw rootwait ignore_loglevel early_printk no_console_suspend mem=2048M@0x80000000 mem=6144M@0x100000000 console=ttySAC0,115200";
+		bootargs = "root=/dev/sda2 rw rootwait ignore_loglevel earlyprintk no_console_suspend mem=2048M@0x80000000 mem=6144M@0x100000000 console=ttySAC0,115200";
 	};
 
 	spi_0: spi@D0000 {
@@ -68,9 +68,11 @@
 
 	pcie@290000 {
 		reset-gpio = <&pin_ctrl 5 0>;
+		status = "okay";
 	};
 
 	pcie@2a0000 {
 		reset-gpio = <&pin_ctrl 22 0>;
+		status = "okay";
 	};
 };
diff --git a/arch/arm/boot/dts/exynos5440.dtsi b/arch/arm/boot/dts/exynos5440.dtsi
index 5d6cf49..8da1070 100644
--- a/arch/arm/boot/dts/exynos5440.dtsi
+++ b/arch/arm/boot/dts/exynos5440.dtsi
@@ -276,6 +276,7 @@
 		interrupt-map-mask = <0 0 0 0>;
 		interrupt-map = <0x0 0 &gic 53>;
 		num-lanes = <4>;
+		status = "disabled";
 	};
 
 	pcie@2a0000 {
@@ -296,5 +297,6 @@
 		interrupt-map-mask = <0 0 0 0>;
 		interrupt-map = <0x0 0 &gic 56>;
 		num-lanes = <4>;
+		status = "disabled";
 	};
 };
diff --git a/arch/arm/boot/dts/imx23-evk.dts b/arch/arm/boot/dts/imx23-evk.dts
index 185c7c0..1f026ad 100644
--- a/arch/arm/boot/dts/imx23-evk.dts
+++ b/arch/arm/boot/dts/imx23-evk.dts
@@ -10,7 +10,7 @@
  */
 
 /dts-v1/;
-/include/ "imx23.dtsi"
+#include "imx23.dtsi"
 
 / {
 	model = "Freescale i.MX23 Evaluation Kit";
@@ -45,14 +45,14 @@
 				hog_pins_a: hog@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x1123 /* MX23_PAD_LCD_RESET__GPIO_1_18 */
-						0x11d3 /* MX23_PAD_PWM3__GPIO_1_29 */
-						0x11e3 /* MX23_PAD_PWM4__GPIO_1_30 */
-						0x2010 /* MX23_PAD_SSP1_DETECT__SSP1_DETECT */
+						MX23_PAD_LCD_RESET__GPIO_1_18
+						MX23_PAD_PWM3__GPIO_1_29
+						MX23_PAD_PWM4__GPIO_1_30
+						MX23_PAD_SSP1_DETECT__SSP1_DETECT
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 			};
 
diff --git a/arch/arm/boot/dts/imx23-olinuxino.dts b/arch/arm/boot/dts/imx23-olinuxino.dts
index fc766ae..526bfdb 100644
--- a/arch/arm/boot/dts/imx23-olinuxino.dts
+++ b/arch/arm/boot/dts/imx23-olinuxino.dts
@@ -12,7 +12,7 @@
  */
 
 /dts-v1/;
-/include/ "imx23.dtsi"
+#include "imx23.dtsi"
 
 / {
 	model = "i.MX23 Olinuxino Low Cost Board";
@@ -40,21 +40,21 @@
 				hog_pins_a: hog@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x0113 /* MX23_PAD_GPMI_ALE__GPIO_0_17 */
+						MX23_PAD_GPMI_ALE__GPIO_0_17
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				led_pin_gpio2_1: led_gpio2_1@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x2013 /* MX23_PAD_SSP1_DETECT__GPIO_2_1 */
+						MX23_PAD_SSP1_DETECT__GPIO_2_1
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 			};
 
diff --git a/arch/arm/boot/dts/imx23-pinfunc.h b/arch/arm/boot/dts/imx23-pinfunc.h
new file mode 100644
index 0000000..5c0f32ca
--- /dev/null
+++ b/arch/arm/boot/dts/imx23-pinfunc.h
@@ -0,0 +1,333 @@
+/*
+ * Header providing constants for i.MX23 pinctrl bindings.
+ *
+ * Copyright (C) 2013 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __DT_BINDINGS_MX23_PINCTRL_H__
+#define __DT_BINDINGS_MX23_PINCTRL_H__
+
+#include "mxs-pinfunc.h"
+
+#define MX23_PAD_GPMI_D00__GPMI_D00			0x0000
+#define MX23_PAD_GPMI_D01__GPMI_D01			0x0010
+#define MX23_PAD_GPMI_D02__GPMI_D02			0x0020
+#define MX23_PAD_GPMI_D03__GPMI_D03			0x0030
+#define MX23_PAD_GPMI_D04__GPMI_D04			0x0040
+#define MX23_PAD_GPMI_D05__GPMI_D05			0x0050
+#define MX23_PAD_GPMI_D06__GPMI_D06			0x0060
+#define MX23_PAD_GPMI_D07__GPMI_D07			0x0070
+#define MX23_PAD_GPMI_D08__GPMI_D08			0x0080
+#define MX23_PAD_GPMI_D09__GPMI_D09			0x0090
+#define MX23_PAD_GPMI_D10__GPMI_D10			0x00a0
+#define MX23_PAD_GPMI_D11__GPMI_D11			0x00b0
+#define MX23_PAD_GPMI_D12__GPMI_D12			0x00c0
+#define MX23_PAD_GPMI_D13__GPMI_D13			0x00d0
+#define MX23_PAD_GPMI_D14__GPMI_D14			0x00e0
+#define MX23_PAD_GPMI_D15__GPMI_D15			0x00f0
+#define MX23_PAD_GPMI_CLE__GPMI_CLE			0x0100
+#define MX23_PAD_GPMI_ALE__GPMI_ALE			0x0110
+#define MX23_PAD_GPMI_CE2N__GPMI_CE2N			0x0120
+#define MX23_PAD_GPMI_RDY0__GPMI_RDY0			0x0130
+#define MX23_PAD_GPMI_RDY1__GPMI_RDY1			0x0140
+#define MX23_PAD_GPMI_RDY2__GPMI_RDY2			0x0150
+#define MX23_PAD_GPMI_RDY3__GPMI_RDY3			0x0160
+#define MX23_PAD_GPMI_WPN__GPMI_WPN			0x0170
+#define MX23_PAD_GPMI_WRN__GPMI_WRN			0x0180
+#define MX23_PAD_GPMI_RDN__GPMI_RDN			0x0190
+#define MX23_PAD_AUART1_CTS__AUART1_CTS			0x01a0
+#define MX23_PAD_AUART1_RTS__AUART1_RTS			0x01b0
+#define MX23_PAD_AUART1_RX__AUART1_RX			0x01c0
+#define MX23_PAD_AUART1_TX__AUART1_TX			0x01d0
+#define MX23_PAD_I2C_SCL__I2C_SCL			0x01e0
+#define MX23_PAD_I2C_SDA__I2C_SDA			0x01f0
+#define MX23_PAD_LCD_D00__LCD_D00			0x1000
+#define MX23_PAD_LCD_D01__LCD_D01			0x1010
+#define MX23_PAD_LCD_D02__LCD_D02			0x1020
+#define MX23_PAD_LCD_D03__LCD_D03			0x1030
+#define MX23_PAD_LCD_D04__LCD_D04			0x1040
+#define MX23_PAD_LCD_D05__LCD_D05			0x1050
+#define MX23_PAD_LCD_D06__LCD_D06			0x1060
+#define MX23_PAD_LCD_D07__LCD_D07			0x1070
+#define MX23_PAD_LCD_D08__LCD_D08			0x1080
+#define MX23_PAD_LCD_D09__LCD_D09			0x1090
+#define MX23_PAD_LCD_D10__LCD_D10			0x10a0
+#define MX23_PAD_LCD_D11__LCD_D11			0x10b0
+#define MX23_PAD_LCD_D12__LCD_D12			0x10c0
+#define MX23_PAD_LCD_D13__LCD_D13			0x10d0
+#define MX23_PAD_LCD_D14__LCD_D14			0x10e0
+#define MX23_PAD_LCD_D15__LCD_D15			0x10f0
+#define MX23_PAD_LCD_D16__LCD_D16			0x1100
+#define MX23_PAD_LCD_D17__LCD_D17			0x1110
+#define MX23_PAD_LCD_RESET__LCD_RESET			0x1120
+#define MX23_PAD_LCD_RS__LCD_RS				0x1130
+#define MX23_PAD_LCD_WR__LCD_WR				0x1140
+#define MX23_PAD_LCD_CS__LCD_CS				0x1150
+#define MX23_PAD_LCD_DOTCK__LCD_DOTCK			0x1160
+#define MX23_PAD_LCD_ENABLE__LCD_ENABLE			0x1170
+#define MX23_PAD_LCD_HSYNC__LCD_HSYNC			0x1180
+#define MX23_PAD_LCD_VSYNC__LCD_VSYNC			0x1190
+#define MX23_PAD_PWM0__PWM0				0x11a0
+#define MX23_PAD_PWM1__PWM1				0x11b0
+#define MX23_PAD_PWM2__PWM2				0x11c0
+#define MX23_PAD_PWM3__PWM3				0x11d0
+#define MX23_PAD_PWM4__PWM4				0x11e0
+#define MX23_PAD_SSP1_CMD__SSP1_CMD			0x2000
+#define MX23_PAD_SSP1_DETECT__SSP1_DETECT		0x2010
+#define MX23_PAD_SSP1_DATA0__SSP1_DATA0			0x2020
+#define MX23_PAD_SSP1_DATA1__SSP1_DATA1			0x2030
+#define MX23_PAD_SSP1_DATA2__SSP1_DATA2			0x2040
+#define MX23_PAD_SSP1_DATA3__SSP1_DATA3			0x2050
+#define MX23_PAD_SSP1_SCK__SSP1_SCK			0x2060
+#define MX23_PAD_ROTARYA__ROTARYA			0x2070
+#define MX23_PAD_ROTARYB__ROTARYB			0x2080
+#define MX23_PAD_EMI_A00__EMI_A00			0x2090
+#define MX23_PAD_EMI_A01__EMI_A01			0x20a0
+#define MX23_PAD_EMI_A02__EMI_A02			0x20b0
+#define MX23_PAD_EMI_A03__EMI_A03			0x20c0
+#define MX23_PAD_EMI_A04__EMI_A04			0x20d0
+#define MX23_PAD_EMI_A05__EMI_A05			0x20e0
+#define MX23_PAD_EMI_A06__EMI_A06			0x20f0
+#define MX23_PAD_EMI_A07__EMI_A07			0x2100
+#define MX23_PAD_EMI_A08__EMI_A08			0x2110
+#define MX23_PAD_EMI_A09__EMI_A09			0x2120
+#define MX23_PAD_EMI_A10__EMI_A10			0x2130
+#define MX23_PAD_EMI_A11__EMI_A11			0x2140
+#define MX23_PAD_EMI_A12__EMI_A12			0x2150
+#define MX23_PAD_EMI_BA0__EMI_BA0			0x2160
+#define MX23_PAD_EMI_BA1__EMI_BA1			0x2170
+#define MX23_PAD_EMI_CASN__EMI_CASN			0x2180
+#define MX23_PAD_EMI_CE0N__EMI_CE0N			0x2190
+#define MX23_PAD_EMI_CE1N__EMI_CE1N			0x21a0
+#define MX23_PAD_GPMI_CE1N__GPMI_CE1N			0x21b0
+#define MX23_PAD_GPMI_CE0N__GPMI_CE0N			0x21c0
+#define MX23_PAD_EMI_CKE__EMI_CKE			0x21d0
+#define MX23_PAD_EMI_RASN__EMI_RASN			0x21e0
+#define MX23_PAD_EMI_WEN__EMI_WEN			0x21f0
+#define MX23_PAD_EMI_D00__EMI_D00			0x3000
+#define MX23_PAD_EMI_D01__EMI_D01			0x3010
+#define MX23_PAD_EMI_D02__EMI_D02			0x3020
+#define MX23_PAD_EMI_D03__EMI_D03			0x3030
+#define MX23_PAD_EMI_D04__EMI_D04			0x3040
+#define MX23_PAD_EMI_D05__EMI_D05			0x3050
+#define MX23_PAD_EMI_D06__EMI_D06			0x3060
+#define MX23_PAD_EMI_D07__EMI_D07			0x3070
+#define MX23_PAD_EMI_D08__EMI_D08			0x3080
+#define MX23_PAD_EMI_D09__EMI_D09			0x3090
+#define MX23_PAD_EMI_D10__EMI_D10			0x30a0
+#define MX23_PAD_EMI_D11__EMI_D11			0x30b0
+#define MX23_PAD_EMI_D12__EMI_D12			0x30c0
+#define MX23_PAD_EMI_D13__EMI_D13			0x30d0
+#define MX23_PAD_EMI_D14__EMI_D14			0x30e0
+#define MX23_PAD_EMI_D15__EMI_D15			0x30f0
+#define MX23_PAD_EMI_DQM0__EMI_DQM0			0x3100
+#define MX23_PAD_EMI_DQM1__EMI_DQM1			0x3110
+#define MX23_PAD_EMI_DQS0__EMI_DQS0			0x3120
+#define MX23_PAD_EMI_DQS1__EMI_DQS1			0x3130
+#define MX23_PAD_EMI_CLK__EMI_CLK			0x3140
+#define MX23_PAD_EMI_CLKN__EMI_CLKN			0x3150
+#define MX23_PAD_GPMI_D00__LCD_D8			0x0001
+#define MX23_PAD_GPMI_D01__LCD_D9			0x0011
+#define MX23_PAD_GPMI_D02__LCD_D10			0x0021
+#define MX23_PAD_GPMI_D03__LCD_D11			0x0031
+#define MX23_PAD_GPMI_D04__LCD_D12			0x0041
+#define MX23_PAD_GPMI_D05__LCD_D13			0x0051
+#define MX23_PAD_GPMI_D06__LCD_D14			0x0061
+#define MX23_PAD_GPMI_D07__LCD_D15			0x0071
+#define MX23_PAD_GPMI_D08__LCD_D18			0x0081
+#define MX23_PAD_GPMI_D09__LCD_D19			0x0091
+#define MX23_PAD_GPMI_D10__LCD_D20			0x00a1
+#define MX23_PAD_GPMI_D11__LCD_D21			0x00b1
+#define MX23_PAD_GPMI_D12__LCD_D22			0x00c1
+#define MX23_PAD_GPMI_D13__LCD_D23			0x00d1
+#define MX23_PAD_GPMI_D14__AUART2_RX			0x00e1
+#define MX23_PAD_GPMI_D15__AUART2_TX			0x00f1
+#define MX23_PAD_GPMI_CLE__LCD_D16			0x0101
+#define MX23_PAD_GPMI_ALE__LCD_D17			0x0111
+#define MX23_PAD_GPMI_CE2N__ATA_A2			0x0121
+#define MX23_PAD_AUART1_RTS__IR_CLK			0x01b1
+#define MX23_PAD_AUART1_RX__IR_RX			0x01c1
+#define MX23_PAD_AUART1_TX__IR_TX			0x01d1
+#define MX23_PAD_I2C_SCL__GPMI_RDY2			0x01e1
+#define MX23_PAD_I2C_SDA__GPMI_CE2N			0x01f1
+#define MX23_PAD_LCD_D00__ETM_DA8			0x1001
+#define MX23_PAD_LCD_D01__ETM_DA9			0x1011
+#define MX23_PAD_LCD_D02__ETM_DA10			0x1021
+#define MX23_PAD_LCD_D03__ETM_DA11			0x1031
+#define MX23_PAD_LCD_D04__ETM_DA12			0x1041
+#define MX23_PAD_LCD_D05__ETM_DA13			0x1051
+#define MX23_PAD_LCD_D06__ETM_DA14			0x1061
+#define MX23_PAD_LCD_D07__ETM_DA15			0x1071
+#define MX23_PAD_LCD_D08__ETM_DA0			0x1081
+#define MX23_PAD_LCD_D09__ETM_DA1			0x1091
+#define MX23_PAD_LCD_D10__ETM_DA2			0x10a1
+#define MX23_PAD_LCD_D11__ETM_DA3			0x10b1
+#define MX23_PAD_LCD_D12__ETM_DA4			0x10c1
+#define MX23_PAD_LCD_D13__ETM_DA5			0x10d1
+#define MX23_PAD_LCD_D14__ETM_DA6			0x10e1
+#define MX23_PAD_LCD_D15__ETM_DA7			0x10f1
+#define MX23_PAD_LCD_RESET__ETM_TCTL			0x1121
+#define MX23_PAD_LCD_RS__ETM_TCLK			0x1131
+#define MX23_PAD_LCD_DOTCK__GPMI_RDY3			0x1161
+#define MX23_PAD_LCD_ENABLE__I2C_SCL			0x1171
+#define MX23_PAD_LCD_HSYNC__I2C_SDA			0x1181
+#define MX23_PAD_LCD_VSYNC__LCD_BUSY			0x1191
+#define MX23_PAD_PWM0__ROTARYA				0x11a1
+#define MX23_PAD_PWM1__ROTARYB				0x11b1
+#define MX23_PAD_PWM2__GPMI_RDY3			0x11c1
+#define MX23_PAD_PWM3__ETM_TCTL				0x11d1
+#define MX23_PAD_PWM4__ETM_TCLK				0x11e1
+#define MX23_PAD_SSP1_DETECT__GPMI_CE3N			0x2011
+#define MX23_PAD_SSP1_DATA1__I2C_SCL			0x2031
+#define MX23_PAD_SSP1_DATA2__I2C_SDA			0x2041
+#define MX23_PAD_ROTARYA__AUART2_RTS			0x2071
+#define MX23_PAD_ROTARYB__AUART2_CTS			0x2081
+#define MX23_PAD_GPMI_D00__SSP2_DATA0			0x0002
+#define MX23_PAD_GPMI_D01__SSP2_DATA1			0x0012
+#define MX23_PAD_GPMI_D02__SSP2_DATA2			0x0022
+#define MX23_PAD_GPMI_D03__SSP2_DATA3			0x0032
+#define MX23_PAD_GPMI_D04__SSP2_DATA4			0x0042
+#define MX23_PAD_GPMI_D05__SSP2_DATA5			0x0052
+#define MX23_PAD_GPMI_D06__SSP2_DATA6			0x0062
+#define MX23_PAD_GPMI_D07__SSP2_DATA7			0x0072
+#define MX23_PAD_GPMI_D08__SSP1_DATA4			0x0082
+#define MX23_PAD_GPMI_D09__SSP1_DATA5			0x0092
+#define MX23_PAD_GPMI_D10__SSP1_DATA6			0x00a2
+#define MX23_PAD_GPMI_D11__SSP1_DATA7			0x00b2
+#define MX23_PAD_GPMI_D15__GPMI_CE3N			0x00f2
+#define MX23_PAD_GPMI_RDY0__SSP2_DETECT			0x0132
+#define MX23_PAD_GPMI_RDY1__SSP2_CMD			0x0142
+#define MX23_PAD_GPMI_WRN__SSP2_SCK			0x0182
+#define MX23_PAD_AUART1_CTS__SSP1_DATA4			0x01a2
+#define MX23_PAD_AUART1_RTS__SSP1_DATA5			0x01b2
+#define MX23_PAD_AUART1_RX__SSP1_DATA6			0x01c2
+#define MX23_PAD_AUART1_TX__SSP1_DATA7			0x01d2
+#define MX23_PAD_I2C_SCL__AUART1_TX			0x01e2
+#define MX23_PAD_I2C_SDA__AUART1_RX			0x01f2
+#define MX23_PAD_LCD_D08__SAIF2_SDATA0			0x1082
+#define MX23_PAD_LCD_D09__SAIF1_SDATA0			0x1092
+#define MX23_PAD_LCD_D10__SAIF_MCLK_BITCLK		0x10a2
+#define MX23_PAD_LCD_D11__SAIF_LRCLK			0x10b2
+#define MX23_PAD_LCD_D12__SAIF2_SDATA1			0x10c2
+#define MX23_PAD_LCD_D13__SAIF2_SDATA2			0x10d2
+#define MX23_PAD_LCD_D14__SAIF1_SDATA2			0x10e2
+#define MX23_PAD_LCD_D15__SAIF1_SDATA1			0x10f2
+#define MX23_PAD_LCD_D16__SAIF_ALT_BITCLK		0x1102
+#define MX23_PAD_LCD_RESET__GPMI_CE3N			0x1122
+#define MX23_PAD_PWM0__DUART_RX				0x11a2
+#define MX23_PAD_PWM1__DUART_TX				0x11b2
+#define MX23_PAD_PWM3__AUART1_CTS			0x11d2
+#define MX23_PAD_PWM4__AUART1_RTS			0x11e2
+#define MX23_PAD_SSP1_CMD__JTAG_TDO			0x2002
+#define MX23_PAD_SSP1_DETECT__USB_OTG_ID		0x2012
+#define MX23_PAD_SSP1_DATA0__JTAG_TDI			0x2022
+#define MX23_PAD_SSP1_DATA1__JTAG_TCLK			0x2032
+#define MX23_PAD_SSP1_DATA2__JTAG_RTCK			0x2042
+#define MX23_PAD_SSP1_DATA3__JTAG_TMS			0x2052
+#define MX23_PAD_SSP1_SCK__JTAG_TRST			0x2062
+#define MX23_PAD_ROTARYA__SPDIF				0x2072
+#define MX23_PAD_ROTARYB__GPMI_CE3N			0x2082
+#define MX23_PAD_GPMI_D00__GPIO_0_0			0x0003
+#define MX23_PAD_GPMI_D01__GPIO_0_1			0x0013
+#define MX23_PAD_GPMI_D02__GPIO_0_2			0x0023
+#define MX23_PAD_GPMI_D03__GPIO_0_3			0x0033
+#define MX23_PAD_GPMI_D04__GPIO_0_4			0x0043
+#define MX23_PAD_GPMI_D05__GPIO_0_5			0x0053
+#define MX23_PAD_GPMI_D06__GPIO_0_6			0x0063
+#define MX23_PAD_GPMI_D07__GPIO_0_7			0x0073
+#define MX23_PAD_GPMI_D08__GPIO_0_8			0x0083
+#define MX23_PAD_GPMI_D09__GPIO_0_9			0x0093
+#define MX23_PAD_GPMI_D10__GPIO_0_10			0x00a3
+#define MX23_PAD_GPMI_D11__GPIO_0_11			0x00b3
+#define MX23_PAD_GPMI_D12__GPIO_0_12			0x00c3
+#define MX23_PAD_GPMI_D13__GPIO_0_13			0x00d3
+#define MX23_PAD_GPMI_D14__GPIO_0_14			0x00e3
+#define MX23_PAD_GPMI_D15__GPIO_0_15			0x00f3
+#define MX23_PAD_GPMI_CLE__GPIO_0_16			0x0103
+#define MX23_PAD_GPMI_ALE__GPIO_0_17			0x0113
+#define MX23_PAD_GPMI_CE2N__GPIO_0_18			0x0123
+#define MX23_PAD_GPMI_RDY0__GPIO_0_19			0x0133
+#define MX23_PAD_GPMI_RDY1__GPIO_0_20			0x0143
+#define MX23_PAD_GPMI_RDY2__GPIO_0_21			0x0153
+#define MX23_PAD_GPMI_RDY3__GPIO_0_22			0x0163
+#define MX23_PAD_GPMI_WPN__GPIO_0_23			0x0173
+#define MX23_PAD_GPMI_WRN__GPIO_0_24			0x0183
+#define MX23_PAD_GPMI_RDN__GPIO_0_25			0x0193
+#define MX23_PAD_AUART1_CTS__GPIO_0_26			0x01a3
+#define MX23_PAD_AUART1_RTS__GPIO_0_27			0x01b3
+#define MX23_PAD_AUART1_RX__GPIO_0_28			0x01c3
+#define MX23_PAD_AUART1_TX__GPIO_0_29			0x01d3
+#define MX23_PAD_I2C_SCL__GPIO_0_30			0x01e3
+#define MX23_PAD_I2C_SDA__GPIO_0_31			0x01f3
+#define MX23_PAD_LCD_D00__GPIO_1_0			0x1003
+#define MX23_PAD_LCD_D01__GPIO_1_1			0x1013
+#define MX23_PAD_LCD_D02__GPIO_1_2			0x1023
+#define MX23_PAD_LCD_D03__GPIO_1_3			0x1033
+#define MX23_PAD_LCD_D04__GPIO_1_4			0x1043
+#define MX23_PAD_LCD_D05__GPIO_1_5			0x1053
+#define MX23_PAD_LCD_D06__GPIO_1_6			0x1063
+#define MX23_PAD_LCD_D07__GPIO_1_7			0x1073
+#define MX23_PAD_LCD_D08__GPIO_1_8			0x1083
+#define MX23_PAD_LCD_D09__GPIO_1_9			0x1093
+#define MX23_PAD_LCD_D10__GPIO_1_10			0x10a3
+#define MX23_PAD_LCD_D11__GPIO_1_11			0x10b3
+#define MX23_PAD_LCD_D12__GPIO_1_12			0x10c3
+#define MX23_PAD_LCD_D13__GPIO_1_13			0x10d3
+#define MX23_PAD_LCD_D14__GPIO_1_14			0x10e3
+#define MX23_PAD_LCD_D15__GPIO_1_15			0x10f3
+#define MX23_PAD_LCD_D16__GPIO_1_16			0x1103
+#define MX23_PAD_LCD_D17__GPIO_1_17			0x1113
+#define MX23_PAD_LCD_RESET__GPIO_1_18			0x1123
+#define MX23_PAD_LCD_RS__GPIO_1_19			0x1133
+#define MX23_PAD_LCD_WR__GPIO_1_20			0x1143
+#define MX23_PAD_LCD_CS__GPIO_1_21			0x1153
+#define MX23_PAD_LCD_DOTCK__GPIO_1_22			0x1163
+#define MX23_PAD_LCD_ENABLE__GPIO_1_23			0x1173
+#define MX23_PAD_LCD_HSYNC__GPIO_1_24			0x1183
+#define MX23_PAD_LCD_VSYNC__GPIO_1_25			0x1193
+#define MX23_PAD_PWM0__GPIO_1_26			0x11a3
+#define MX23_PAD_PWM1__GPIO_1_27			0x11b3
+#define MX23_PAD_PWM2__GPIO_1_28			0x11c3
+#define MX23_PAD_PWM3__GPIO_1_29			0x11d3
+#define MX23_PAD_PWM4__GPIO_1_30			0x11e3
+#define MX23_PAD_SSP1_CMD__GPIO_2_0			0x2003
+#define MX23_PAD_SSP1_DETECT__GPIO_2_1			0x2013
+#define MX23_PAD_SSP1_DATA0__GPIO_2_2			0x2023
+#define MX23_PAD_SSP1_DATA1__GPIO_2_3			0x2033
+#define MX23_PAD_SSP1_DATA2__GPIO_2_4			0x2043
+#define MX23_PAD_SSP1_DATA3__GPIO_2_5			0x2053
+#define MX23_PAD_SSP1_SCK__GPIO_2_6			0x2063
+#define MX23_PAD_ROTARYA__GPIO_2_7			0x2073
+#define MX23_PAD_ROTARYB__GPIO_2_8			0x2083
+#define MX23_PAD_EMI_A00__GPIO_2_9			0x2093
+#define MX23_PAD_EMI_A01__GPIO_2_10			0x20a3
+#define MX23_PAD_EMI_A02__GPIO_2_11			0x20b3
+#define MX23_PAD_EMI_A03__GPIO_2_12			0x20c3
+#define MX23_PAD_EMI_A04__GPIO_2_13			0x20d3
+#define MX23_PAD_EMI_A05__GPIO_2_14			0x20e3
+#define MX23_PAD_EMI_A06__GPIO_2_15			0x20f3
+#define MX23_PAD_EMI_A07__GPIO_2_16			0x2103
+#define MX23_PAD_EMI_A08__GPIO_2_17			0x2113
+#define MX23_PAD_EMI_A09__GPIO_2_18			0x2123
+#define MX23_PAD_EMI_A10__GPIO_2_19			0x2133
+#define MX23_PAD_EMI_A11__GPIO_2_20			0x2143
+#define MX23_PAD_EMI_A12__GPIO_2_21			0x2153
+#define MX23_PAD_EMI_BA0__GPIO_2_22			0x2163
+#define MX23_PAD_EMI_BA1__GPIO_2_23			0x2173
+#define MX23_PAD_EMI_CASN__GPIO_2_24			0x2183
+#define MX23_PAD_EMI_CE0N__GPIO_2_25			0x2193
+#define MX23_PAD_EMI_CE1N__GPIO_2_26			0x21a3
+#define MX23_PAD_GPMI_CE1N__GPIO_2_27			0x21b3
+#define MX23_PAD_GPMI_CE0N__GPIO_2_28			0x21c3
+#define MX23_PAD_EMI_CKE__GPIO_2_29			0x21d3
+#define MX23_PAD_EMI_RASN__GPIO_2_30			0x21e3
+#define MX23_PAD_EMI_WEN__GPIO_2_31			0x21f3
+
+#endif /* __DT_BINDINGS_MX23_PINCTRL_H__ */
diff --git a/arch/arm/boot/dts/imx23-stmp378x_devb.dts b/arch/arm/boot/dts/imx23-stmp378x_devb.dts
index 85c3864..cb64e2b 100644
--- a/arch/arm/boot/dts/imx23-stmp378x_devb.dts
+++ b/arch/arm/boot/dts/imx23-stmp378x_devb.dts
@@ -10,7 +10,7 @@
  */
 
 /dts-v1/;
-/include/ "imx23.dtsi"
+#include "imx23.dtsi"
 
 / {
 	model = "Freescale STMP378x Development Board";
@@ -39,12 +39,12 @@
 				hog_pins_a: hog@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x11d3 /* MX23_PAD_PWM3__GPIO_1_29 */
-						0x11e3 /* MX23_PAD_PWM4__GPIO_1_30 */
+						MX23_PAD_PWM3__GPIO_1_29
+						MX23_PAD_PWM4__GPIO_1_30
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 			};
 		};
diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi
index 28b5ce2..c96ceae 100644
--- a/arch/arm/boot/dts/imx23.dtsi
+++ b/arch/arm/boot/dts/imx23.dtsi
@@ -9,7 +9,8 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-/include/ "skeleton.dtsi"
+#include "skeleton.dtsi"
+#include "imx23-pinfunc.h"
 
 / {
 	interrupt-parent = <&icoll>;
@@ -137,174 +138,174 @@
 				duart_pins_a: duart@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x11a2 /* MX23_PAD_PWM0__DUART_RX */
-						0x11b2 /* MX23_PAD_PWM1__DUART_TX */
+						MX23_PAD_PWM0__DUART_RX
+						MX23_PAD_PWM1__DUART_TX
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				auart0_pins_a: auart0@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x01c0 /* MX23_PAD_AUART1_RX__AUART1_RX */
-						0x01d0 /* MX23_PAD_AUART1_TX__AUART1_TX */
-						0x01a0 /* MX23_PAD_AUART1_CTS__AUART1_CTS */
-						0x01b0 /* MX23_PAD_AUART1_RTS__AUART1_RTS */
+						MX23_PAD_AUART1_RX__AUART1_RX
+						MX23_PAD_AUART1_TX__AUART1_TX
+						MX23_PAD_AUART1_CTS__AUART1_CTS
+						MX23_PAD_AUART1_RTS__AUART1_RTS
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				auart0_2pins_a: auart0-2pins@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x01e2 /* MX23_PAD_I2C_SCL__AUART1_TX */
-						0x01f2 /* MX23_PAD_I2C_SDA__AUART1_RX */
+						MX23_PAD_I2C_SCL__AUART1_TX
+						MX23_PAD_I2C_SDA__AUART1_RX
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				gpmi_pins_a: gpmi-nand@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x0000 /* MX23_PAD_GPMI_D00__GPMI_D00 */
-						0x0010 /* MX23_PAD_GPMI_D01__GPMI_D01 */
-						0x0020 /* MX23_PAD_GPMI_D02__GPMI_D02 */
-						0x0030 /* MX23_PAD_GPMI_D03__GPMI_D03 */
-						0x0040 /* MX23_PAD_GPMI_D04__GPMI_D04 */
-						0x0050 /* MX23_PAD_GPMI_D05__GPMI_D05 */
-						0x0060 /* MX23_PAD_GPMI_D06__GPMI_D06 */
-						0x0070 /* MX23_PAD_GPMI_D07__GPMI_D07 */
-						0x0100 /* MX23_PAD_GPMI_CLE__GPMI_CLE */
-						0x0110 /* MX23_PAD_GPMI_ALE__GPMI_ALE */
-						0x0130 /* MX23_PAD_GPMI_RDY0__GPMI_RDY0 */
-						0x0140 /* MX23_PAD_GPMI_RDY1__GPMI_RDY1 */
-						0x0170 /* MX23_PAD_GPMI_WPN__GPMI_WPN */
-						0x0180 /* MX23_PAD_GPMI_WRN__GPMI_WRN */
-						0x0190 /* MX23_PAD_GPMI_RDN__GPMI_RDN */
-						0x21b0 /* MX23_PAD_GPMI_CE1N__GPMI_CE1N */
-						0x21c0 /* MX23_PAD_GPMI_CE0N__GPMI_CE0N	*/
+						MX23_PAD_GPMI_D00__GPMI_D00
+						MX23_PAD_GPMI_D01__GPMI_D01
+						MX23_PAD_GPMI_D02__GPMI_D02
+						MX23_PAD_GPMI_D03__GPMI_D03
+						MX23_PAD_GPMI_D04__GPMI_D04
+						MX23_PAD_GPMI_D05__GPMI_D05
+						MX23_PAD_GPMI_D06__GPMI_D06
+						MX23_PAD_GPMI_D07__GPMI_D07
+						MX23_PAD_GPMI_CLE__GPMI_CLE
+						MX23_PAD_GPMI_ALE__GPMI_ALE
+						MX23_PAD_GPMI_RDY0__GPMI_RDY0
+						MX23_PAD_GPMI_RDY1__GPMI_RDY1
+						MX23_PAD_GPMI_WPN__GPMI_WPN
+						MX23_PAD_GPMI_WRN__GPMI_WRN
+						MX23_PAD_GPMI_RDN__GPMI_RDN
+						MX23_PAD_GPMI_CE1N__GPMI_CE1N
+						MX23_PAD_GPMI_CE0N__GPMI_CE0N
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				gpmi_pins_fixup: gpmi-pins-fixup {
 					fsl,pinmux-ids = <
-						0x0170 /* MX23_PAD_GPMI_WPN__GPMI_WPN */
-						0x0180 /* MX23_PAD_GPMI_WRN__GPMI_WRN */
-						0x0190 /* MX23_PAD_GPMI_RDN__GPMI_RDN */
+						MX23_PAD_GPMI_WPN__GPMI_WPN
+						MX23_PAD_GPMI_WRN__GPMI_WRN
+						MX23_PAD_GPMI_RDN__GPMI_RDN
 					>;
-					fsl,drive-strength = <2>;
+					fsl,drive-strength = <MXS_DRIVE_12mA>;
 				};
 
 				mmc0_4bit_pins_a: mmc0-4bit@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x2020 /* MX23_PAD_SSP1_DATA0__SSP1_DATA0 */
-						0x2030 /* MX23_PAD_SSP1_DATA1__SSP1_DATA1 */
-						0x2040 /* MX23_PAD_SSP1_DATA2__SSP1_DATA2 */
-						0x2050 /* MX23_PAD_SSP1_DATA3__SSP1_DATA3 */
-						0x2000 /* MX23_PAD_SSP1_CMD__SSP1_CMD */
-						0x2060 /* MX23_PAD_SSP1_SCK__SSP1_SCK */
+						MX23_PAD_SSP1_DATA0__SSP1_DATA0
+						MX23_PAD_SSP1_DATA1__SSP1_DATA1
+						MX23_PAD_SSP1_DATA2__SSP1_DATA2
+						MX23_PAD_SSP1_DATA3__SSP1_DATA3
+						MX23_PAD_SSP1_CMD__SSP1_CMD
+						MX23_PAD_SSP1_SCK__SSP1_SCK
 					>;
-					fsl,drive-strength = <1>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				mmc0_8bit_pins_a: mmc0-8bit@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x2020 /* MX23_PAD_SSP1_DATA0__SSP1_DATA0 */
-						0x2030 /* MX23_PAD_SSP1_DATA1__SSP1_DATA1 */
-						0x2040 /* MX23_PAD_SSP1_DATA2__SSP1_DATA2 */
-						0x2050 /* MX23_PAD_SSP1_DATA3__SSP1_DATA3 */
-						0x0082 /* MX23_PAD_GPMI_D08__SSP1_DATA4 */
-						0x0092 /* MX23_PAD_GPMI_D09__SSP1_DATA5 */
-						0x00a2 /* MX23_PAD_GPMI_D10__SSP1_DATA6 */
-						0x00b2 /* MX23_PAD_GPMI_D11__SSP1_DATA7 */
-						0x2000 /* MX23_PAD_SSP1_CMD__SSP1_CMD */
-						0x2010 /* MX23_PAD_SSP1_DETECT__SSP1_DETECT */
-						0x2060 /* MX23_PAD_SSP1_SCK__SSP1_SCK */
+						MX23_PAD_SSP1_DATA0__SSP1_DATA0
+						MX23_PAD_SSP1_DATA1__SSP1_DATA1
+						MX23_PAD_SSP1_DATA2__SSP1_DATA2
+						MX23_PAD_SSP1_DATA3__SSP1_DATA3
+						MX23_PAD_GPMI_D08__SSP1_DATA4
+						MX23_PAD_GPMI_D09__SSP1_DATA5
+						MX23_PAD_GPMI_D10__SSP1_DATA6
+						MX23_PAD_GPMI_D11__SSP1_DATA7
+						MX23_PAD_SSP1_CMD__SSP1_CMD
+						MX23_PAD_SSP1_DETECT__SSP1_DETECT
+						MX23_PAD_SSP1_SCK__SSP1_SCK
 					>;
-					fsl,drive-strength = <1>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				mmc0_pins_fixup: mmc0-pins-fixup {
 					fsl,pinmux-ids = <
-						0x2010 /* MX23_PAD_SSP1_DETECT__SSP1_DETECT */
-						0x2060 /* MX23_PAD_SSP1_SCK__SSP1_SCK */
+						MX23_PAD_SSP1_DETECT__SSP1_DETECT
+						MX23_PAD_SSP1_SCK__SSP1_SCK
 					>;
-					fsl,pull-up = <0>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				pwm2_pins_a: pwm2@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x11c0 /* MX23_PAD_PWM2__PWM2 */
+						MX23_PAD_PWM2__PWM2
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				lcdif_24bit_pins_a: lcdif-24bit@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x1000 /* MX23_PAD_LCD_D00__LCD_D0 */
-						0x1010 /* MX23_PAD_LCD_D01__LCD_D1 */
-						0x1020 /* MX23_PAD_LCD_D02__LCD_D2 */
-						0x1030 /* MX23_PAD_LCD_D03__LCD_D3 */
-						0x1040 /* MX23_PAD_LCD_D04__LCD_D4 */
-						0x1050 /* MX23_PAD_LCD_D05__LCD_D5 */
-						0x1060 /* MX23_PAD_LCD_D06__LCD_D6 */
-						0x1070 /* MX23_PAD_LCD_D07__LCD_D7 */
-						0x1080 /* MX23_PAD_LCD_D08__LCD_D8 */
-						0x1090 /* MX23_PAD_LCD_D09__LCD_D9 */
-						0x10a0 /* MX23_PAD_LCD_D10__LCD_D10 */
-						0x10b0 /* MX23_PAD_LCD_D11__LCD_D11 */
-						0x10c0 /* MX23_PAD_LCD_D12__LCD_D12 */
-						0x10d0 /* MX23_PAD_LCD_D13__LCD_D13 */
-						0x10e0 /* MX23_PAD_LCD_D14__LCD_D14 */
-						0x10f0 /* MX23_PAD_LCD_D15__LCD_D15 */
-						0x1100 /* MX23_PAD_LCD_D16__LCD_D16 */
-						0x1110 /* MX23_PAD_LCD_D17__LCD_D17 */
-						0x0081 /* MX23_PAD_GPMI_D08__LCD_D18 */
-						0x0091 /* MX23_PAD_GPMI_D09__LCD_D19 */
-						0x00a1 /* MX23_PAD_GPMI_D10__LCD_D20 */
-						0x00b1 /* MX23_PAD_GPMI_D11__LCD_D21 */
-						0x00c1 /* MX23_PAD_GPMI_D12__LCD_D22 */
-						0x00d1 /* MX23_PAD_GPMI_D13__LCD_D23 */
-						0x1160 /* MX23_PAD_LCD_DOTCK__LCD_DOTCK */
-						0x1170 /* MX23_PAD_LCD_ENABLE__LCD_ENABLE */
-						0x1180 /* MX23_PAD_LCD_HSYNC__LCD_HSYNC */
-						0x1190 /* MX23_PAD_LCD_VSYNC__LCD_VSYNC */
+						MX23_PAD_LCD_D00__LCD_D00
+						MX23_PAD_LCD_D01__LCD_D01
+						MX23_PAD_LCD_D02__LCD_D02
+						MX23_PAD_LCD_D03__LCD_D03
+						MX23_PAD_LCD_D04__LCD_D04
+						MX23_PAD_LCD_D05__LCD_D05
+						MX23_PAD_LCD_D06__LCD_D06
+						MX23_PAD_LCD_D07__LCD_D07
+						MX23_PAD_LCD_D08__LCD_D08
+						MX23_PAD_LCD_D09__LCD_D09
+						MX23_PAD_LCD_D10__LCD_D10
+						MX23_PAD_LCD_D11__LCD_D11
+						MX23_PAD_LCD_D12__LCD_D12
+						MX23_PAD_LCD_D13__LCD_D13
+						MX23_PAD_LCD_D14__LCD_D14
+						MX23_PAD_LCD_D15__LCD_D15
+						MX23_PAD_LCD_D16__LCD_D16
+						MX23_PAD_LCD_D17__LCD_D17
+						MX23_PAD_GPMI_D08__LCD_D18
+						MX23_PAD_GPMI_D09__LCD_D19
+						MX23_PAD_GPMI_D10__LCD_D20
+						MX23_PAD_GPMI_D11__LCD_D21
+						MX23_PAD_GPMI_D12__LCD_D22
+						MX23_PAD_GPMI_D13__LCD_D23
+						MX23_PAD_LCD_DOTCK__LCD_DOTCK
+						MX23_PAD_LCD_ENABLE__LCD_ENABLE
+						MX23_PAD_LCD_HSYNC__LCD_HSYNC
+						MX23_PAD_LCD_VSYNC__LCD_VSYNC
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				spi2_pins_a: spi2@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x0182 /* MX23_PAD_GPMI_WRN__SSP2_SCK */
-						0x0142 /* MX23_PAD_GPMI_RDY1__SSP2_CMD */
-						0x0002 /* MX23_PAD_GPMI_D00__SSP2_DATA0 */
-						0x0032 /* MX23_PAD_GPMI_D03__SSP2_DATA3 */
+						MX23_PAD_GPMI_WRN__SSP2_SCK
+						MX23_PAD_GPMI_RDY1__SSP2_CMD
+						MX23_PAD_GPMI_D00__SSP2_DATA0
+						MX23_PAD_GPMI_D03__SSP2_DATA3
 					>;
-					fsl,drive-strength = <1>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 			};
 
@@ -430,6 +431,7 @@
 				reg = <0x80050000 0x2000>;
 				interrupts = <36 37 38 39 40 41 42 43 44>;
 				status = "disabled";
+				clocks = <&clks 26>;
 			};
 
 			spdif@80054000 {
diff --git a/arch/arm/boot/dts/imx27-apf27dev.dts b/arch/arm/boot/dts/imx27-apf27dev.dts
index 2a377ca..47c8c26 100644
--- a/arch/arm/boot/dts/imx27-apf27dev.dts
+++ b/arch/arm/boot/dts/imx27-apf27dev.dts
@@ -16,6 +16,26 @@
 	model = "Armadeus Systems APF27Dev docking/development board";
 	compatible = "armadeus,imx27-apf27dev", "armadeus,imx27-apf27", "fsl,imx27";
 
+	display: display {
+		model = "Chimei-LW700AT9003";
+		native-mode = <&timing0>;
+		bits-per-pixel = <16>;  /* non-standard but required */
+		fsl,pcr = <0xfae80083>;	/* non-standard but required */
+		display-timings {
+			timing0: 640x480 {
+				clock-frequency = <33000033>;
+				hactive = <800>;
+				vactive = <640>;
+				hback-porch = <96>;
+				hfront-porch = <96>;
+				vback-porch = <20>;
+				vfront-porch = <21>;
+				hsync-len = <64>;
+				vsync-len = <4>;
+			};
+		};
+	};
+
 	gpio-keys {
 		compatible = "gpio-keys";
 
@@ -50,6 +70,12 @@
 	status = "okay";
 };
 
+&fb {
+	display = <&display>;
+	fsl,dmacr = <0x00020010>;
+	status = "okay";
+};
+
 &i2c1 {
 	clock-frequency = <400000>;
 	status = "okay";
diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi
index b7a1c6d..826231e 100644
--- a/arch/arm/boot/dts/imx27.dtsi
+++ b/arch/arm/boot/dts/imx27.dtsi
@@ -123,6 +123,7 @@
 			};
 
 			pwm: pwm@10006000 {
+				#pwm-cells = <2>;
 				compatible = "fsl,imx27-pwm";
 				reg = <0x10006000 0x1000>;
 				interrupts = <23>;
diff --git a/arch/arm/boot/dts/imx28-apf28.dts b/arch/arm/boot/dts/imx28-apf28.dts
index 7eb0758..7198fe3 100644
--- a/arch/arm/boot/dts/imx28-apf28.dts
+++ b/arch/arm/boot/dts/imx28-apf28.dts
@@ -10,7 +10,7 @@
  */
 
 /dts-v1/;
-/include/ "imx28.dtsi"
+#include "imx28.dtsi"
 
 / {
 	model = "Armadeus Systems APF28 module";
diff --git a/arch/arm/boot/dts/imx28-apf28dev.dts b/arch/arm/boot/dts/imx28-apf28dev.dts
index b602494..e2efd8d 100644
--- a/arch/arm/boot/dts/imx28-apf28dev.dts
+++ b/arch/arm/boot/dts/imx28-apf28dev.dts
@@ -10,7 +10,7 @@
  */
 
 /* APF28Dev is a docking board for the APF28 SOM */
-/include/ "imx28-apf28.dts"
+#include "imx28-apf28.dts"
 
 / {
 	model = "Armadeus Systems APF28Dev docking/development board";
@@ -41,30 +41,30 @@
 				hog_pins_apf28dev: hog@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x1103 /* MX28_PAD_LCD_D16__GPIO_1_16 */
-						0x1113 /* MX28_PAD_LCD_D17__GPIO_1_17 */
-						0x1123 /* MX28_PAD_LCD_D18__GPIO_1_18 */
-						0x1133 /* MX28_PAD_LCD_D19__GPIO_1_19 */
-						0x1143 /* MX28_PAD_LCD_D20__GPIO_1_20 */
-						0x1153 /* MX28_PAD_LCD_D21__GPIO_1_21 */
-						0x1163 /* MX28_PAD_LCD_D22__GPIO_1_22 */
+						MX28_PAD_LCD_D16__GPIO_1_16
+						MX28_PAD_LCD_D17__GPIO_1_17
+						MX28_PAD_LCD_D18__GPIO_1_18
+						MX28_PAD_LCD_D19__GPIO_1_19
+						MX28_PAD_LCD_D20__GPIO_1_20
+						MX28_PAD_LCD_D21__GPIO_1_21
+						MX28_PAD_LCD_D22__GPIO_1_22
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				lcdif_pins_apf28dev: lcdif-apf28dev@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
-						0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
-						0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
-						0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+						MX28_PAD_LCD_RD_E__LCD_VSYNC
+						MX28_PAD_LCD_WR_RWN__LCD_HSYNC
+						MX28_PAD_LCD_RS__LCD_DOTCLK
+						MX28_PAD_LCD_CS__LCD_ENABLE
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 			};
 
diff --git a/arch/arm/boot/dts/imx28-apx4devkit.dts b/arch/arm/boot/dts/imx28-apx4devkit.dts
index 0e7fed4..6f254ca 100644
--- a/arch/arm/boot/dts/imx28-apx4devkit.dts
+++ b/arch/arm/boot/dts/imx28-apx4devkit.dts
@@ -1,5 +1,5 @@
 /dts-v1/;
-/include/ "imx28.dtsi"
+#include "imx28.dtsi"
 
 / {
 	model = "Bluegiga APX4 Development Kit";
@@ -40,53 +40,53 @@
 				hog_pins_a: hog@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x0113 /* MX28_PAD_GPMI_CE1N__GPIO_0_17 */
-						0x0153 /* MX28_PAD_GPMI_RDY1__GPIO_0_21 */
-						0x2123 /* MX28_PAD_SSP2_MISO__GPIO_2_18 */
-						0x2131 /* MX28_PAD_SSP2_SS0__GPIO_2_19 */
-						0x31c3 /* MX28_PAD_PWM3__GPIO_3_28 */
-						0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
-						0x4143 /* MX28_PAD_JTAG_RTCK__GPIO_4_20 */
+						MX28_PAD_GPMI_CE1N__GPIO_0_17
+						MX28_PAD_GPMI_RDY1__GPIO_0_21
+						MX28_PAD_SSP2_MISO__GPIO_2_18
+						MX28_PAD_SSP2_SS0__AUART3_TX /* was: 0x2131 - MX28_PAD_SSP2_SS0__GPIO_2_19 */
+						MX28_PAD_PWM3__GPIO_3_28
+						MX28_PAD_LCD_RESET__GPIO_3_30
+						MX28_PAD_JTAG_RTCK__GPIO_4_20
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				lcdif_pins_apx4: lcdif-apx4@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
-						0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
-						0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
-						0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+						MX28_PAD_LCD_RD_E__LCD_VSYNC
+						MX28_PAD_LCD_WR_RWN__LCD_HSYNC
+						MX28_PAD_LCD_RS__LCD_DOTCLK
+						MX28_PAD_LCD_CS__LCD_ENABLE
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				mmc2_4bit_pins_apx4: mmc2-4bit-apx4@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x2041 /* MX28_PAD_SSP0_DATA4__SSP2_D0 */
-						0x2051 /* MX28_PAD_SSP0_DATA5__SSP2_D3 */
-						0x2061 /* MX28_PAD_SSP0_DATA6__SSP2_CMD */
-						0x2071 /* MX28_PAD_SSP0_DATA7__SSP2_SCK */
-						0x2141 /* MX28_PAD_SSP2_SS1__SSP2_D1 */
-						0x2151 /* MX28_PAD_SSP2_SS2__SSP2_D2 */
+						MX28_PAD_SSP0_DATA4__SSP2_D0
+						MX28_PAD_SSP0_DATA5__SSP2_D3
+						MX28_PAD_SSP0_DATA6__SSP2_CMD
+						MX28_PAD_SSP0_DATA7__SSP2_SCK
+						MX28_PAD_SSP2_SS1__SSP2_D1
+						MX28_PAD_SSP2_SS2__SSP2_D2
 					>;
-					fsl,drive-strength = <1>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				mmc2_sck_cfg_apx4: mmc2-sck-cfg-apx4 {
 					fsl,pinmux-ids = <
-						0x2071 /* MX28_PAD_SSP0_DATA7__SSP2_SCK */
+						MX28_PAD_SSP0_DATA7__SSP2_SCK
 					>;
-					fsl,drive-strength = <2>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_12mA>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 			};
 
diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts
index 1ec8c94..cabb617 100644
--- a/arch/arm/boot/dts/imx28-cfa10036.dts
+++ b/arch/arm/boot/dts/imx28-cfa10036.dts
@@ -10,7 +10,7 @@
  */
 
 /dts-v1/;
-/include/ "imx28.dtsi"
+#include "imx28.dtsi"
 
 / {
 	model = "Crystalfontz CFA-10036 Board";
@@ -26,31 +26,31 @@
 				ssd1306_cfa10036: ssd1306-10036@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x2073 /* MX28_PAD_SSP0_D7__GPIO_2_7 */
+						MX28_PAD_SSP0_DATA7__GPIO_2_7
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				led_pins_cfa10036: leds-10036@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x3043 /* MX28_PAD_AUART1_RX__GPIO_3_4 */
+						MX28_PAD_AUART1_RX__GPIO_3_4
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				usb0_otg_cfa10036: otg-10036@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x0142 /* MX28_PAD_GPMI_READY0__USB0_ID */
+						MX28_PAD_GPMI_RDY0__USB0_ID
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 			};
diff --git a/arch/arm/boot/dts/imx28-cfa10037.dts b/arch/arm/boot/dts/imx28-cfa10037.dts
index 182b99f..f93e9a7 100644
--- a/arch/arm/boot/dts/imx28-cfa10037.dts
+++ b/arch/arm/boot/dts/imx28-cfa10037.dts
@@ -13,7 +13,7 @@
  * The CFA-10049 is an expansion board for the CFA-10036 module, thus we
  * need to include the CFA-10036 DTS.
  */
-/include/ "imx28-cfa10036.dts"
+#include "imx28-cfa10036.dts"
 
 / {
 	model = "Crystalfontz CFA-10037 Board";
@@ -25,21 +25,21 @@
 				usb_pins_cfa10037: usb-10037@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x0073 /* MX28_PAD_GPMI_D7__GPIO_0_7 */
+						MX28_PAD_GPMI_D07__GPIO_0_7
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				mac0_pins_cfa10037: mac0-10037@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x2153 /* MX28_PAD_SSP2_D5__GPIO_2_21 */
+						MX28_PAD_SSP2_SS2__GPIO_2_21
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 			};
 		};
diff --git a/arch/arm/boot/dts/imx28-cfa10049.dts b/arch/arm/boot/dts/imx28-cfa10049.dts
index 06e4cfa..7087b4b 100644
--- a/arch/arm/boot/dts/imx28-cfa10049.dts
+++ b/arch/arm/boot/dts/imx28-cfa10049.dts
@@ -13,7 +13,7 @@
  * The CFA-10049 is an expansion board for the CFA-10036 module, thus we
  * need to include the CFA-10036 DTS.
  */
-/include/ "imx28-cfa10036.dts"
+#include "imx28-cfa10036.dts"
 
 / {
 	model = "Crystalfontz CFA-10049 Board";
@@ -25,150 +25,150 @@
 				usb_pins_cfa10049: usb-10049@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x0073 /* MX28_PAD_GPMI_D7__GPIO_0_7 */
+						MX28_PAD_GPMI_D07__GPIO_0_7
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				i2cmux_pins_cfa10049: i2cmux-10049@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x1163 /* MX28_PAD_LCD_D22__GPIO_1_22 */
-						0x1173 /* MX28_PAD_LCD_D22__GPIO_1_23 */
+						MX28_PAD_LCD_D22__GPIO_1_22
+						MX28_PAD_LCD_D23__GPIO_1_23
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				mac0_pins_cfa10049: mac0-10049@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x2153 /* MX28_PAD_SSP2_D5__GPIO_2_21 */
+						MX28_PAD_SSP2_SS2__GPIO_2_21
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				pca_pins_cfa10049: pca-10049@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x2133 /* MX28_PAD_SSP2_D3__GPIO_2_19 */
+						MX28_PAD_SSP2_SS0__GPIO_2_19
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				rotary_pins_cfa10049: rotary-10049@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x3183 /* MX28_PAD_I2C0_SCL__GPIO_3_24 */
-						0x3193 /* MX28_PAD_I2C0_SDA__GPIO_3_25 */
+						MX28_PAD_I2C0_SCL__GPIO_3_24
+						MX28_PAD_I2C0_SDA__GPIO_3_25
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				rotary_btn_pins_cfa10049: rotary-btn-10049@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x31a3 /* MX28_PAD_SAIF_SDATA0__GPIO_3_26 */
+						MX28_PAD_SAIF1_SDATA0__GPIO_3_26
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				spi2_pins_cfa10049: spi2-cfa10049@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x2103 /* MX28_PAD_SSP2_SCK__GPIO_2_16 */
-						0x2113 /* MX28_PAD_SSP2_CMD__GPIO_2_17 */
-						0x2123 /* MX28_PAD_SSP2_D0__GPIO_2_18 */
-						0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
+						MX28_PAD_SSP2_SCK__GPIO_2_16
+						MX28_PAD_SSP2_MOSI__GPIO_2_17
+						MX28_PAD_SSP2_MISO__GPIO_2_18
+						MX28_PAD_AUART1_TX__GPIO_3_5
 					>;
-					fsl,drive-strength = <1>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				spi3_pins_cfa10049: spi3-cfa10049@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x0183 /* MX28_PAD_GPMI_RDN__GPIO_0_24 */
-						0x01c3 /* MX28_PAD_GPMI_RESETN__GPIO_0_28 */
-						0x0113 /* MX28_PAD_GPMI_CE1N__GPIO_0_17 */
-						0x01a3 /* MX28_PAD_GPMI_ALE__GPIO_0_26 */
-						0x01b3 /* MX28_PAD_GPMI_CLE__GPIO_0_27 */
+						MX28_PAD_GPMI_RDN__GPIO_0_24
+						MX28_PAD_GPMI_RESETN__GPIO_0_28
+						MX28_PAD_GPMI_CE1N__GPIO_0_17
+						MX28_PAD_GPMI_ALE__GPIO_0_26
+						MX28_PAD_GPMI_CLE__GPIO_0_27
 					>;
-					fsl,drive-strength = <1>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				lcdif_18bit_pins_cfa10049: lcdif-18bit@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x1000 /* MX28_PAD_LCD_D00__LCD_D0 */
-						0x1010 /* MX28_PAD_LCD_D01__LCD_D1 */
-						0x1020 /* MX28_PAD_LCD_D02__LCD_D2 */
-						0x1030 /* MX28_PAD_LCD_D03__LCD_D3 */
-						0x1040 /* MX28_PAD_LCD_D04__LCD_D4 */
-						0x1050 /* MX28_PAD_LCD_D05__LCD_D5 */
-						0x1060 /* MX28_PAD_LCD_D06__LCD_D6 */
-						0x1070 /* MX28_PAD_LCD_D07__LCD_D7 */
-						0x1080 /* MX28_PAD_LCD_D08__LCD_D8 */
-						0x1090 /* MX28_PAD_LCD_D09__LCD_D9 */
-						0x10a0 /* MX28_PAD_LCD_D10__LCD_D10 */
-						0x10b0 /* MX28_PAD_LCD_D11__LCD_D11 */
-						0x10c0 /* MX28_PAD_LCD_D12__LCD_D12 */
-						0x10d0 /* MX28_PAD_LCD_D13__LCD_D13 */
-						0x10e0 /* MX28_PAD_LCD_D14__LCD_D14 */
-						0x10f0 /* MX28_PAD_LCD_D15__LCD_D15 */
-						0x1100 /* MX28_PAD_LCD_D16__LCD_D16 */
-						0x1110 /* MX28_PAD_LCD_D17__LCD_D17 */
+						MX28_PAD_LCD_D00__LCD_D0
+						MX28_PAD_LCD_D01__LCD_D1
+						MX28_PAD_LCD_D02__LCD_D2
+						MX28_PAD_LCD_D03__LCD_D3
+						MX28_PAD_LCD_D04__LCD_D4
+						MX28_PAD_LCD_D05__LCD_D5
+						MX28_PAD_LCD_D06__LCD_D6
+						MX28_PAD_LCD_D07__LCD_D7
+						MX28_PAD_LCD_D08__LCD_D8
+						MX28_PAD_LCD_D09__LCD_D9
+						MX28_PAD_LCD_D10__LCD_D10
+						MX28_PAD_LCD_D11__LCD_D11
+						MX28_PAD_LCD_D12__LCD_D12
+						MX28_PAD_LCD_D13__LCD_D13
+						MX28_PAD_LCD_D14__LCD_D14
+						MX28_PAD_LCD_D15__LCD_D15
+						MX28_PAD_LCD_D16__LCD_D16
+						MX28_PAD_LCD_D17__LCD_D17
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				lcdif_pins_cfa10049: lcdif-evk@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
-						0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
-						0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
-						0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+						MX28_PAD_LCD_RD_E__LCD_VSYNC
+						MX28_PAD_LCD_WR_RWN__LCD_HSYNC
+						MX28_PAD_LCD_RS__LCD_DOTCLK
+						MX28_PAD_LCD_CS__LCD_ENABLE
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				lcdif_pins_cfa10049_pullup: lcdif-10049-pullup@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
+						MX28_PAD_LCD_RESET__GPIO_3_30
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				w1_gpio_pins: w1-gpio@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x1153 /* MX28_PAD_LCD_D21__GPIO_1_21 */
+						MX28_PAD_LCD_D21__GPIO_1_21
 					>;
-					fsl,drive-strength = <1>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>; /* 0 will enable the keeper */
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>; /* 0 will enable the keeper */
 				};
 			};
 
diff --git a/arch/arm/boot/dts/imx28-cfa10055.dts b/arch/arm/boot/dts/imx28-cfa10055.dts
index 171bcbe..c3900e7 100644
--- a/arch/arm/boot/dts/imx28-cfa10055.dts
+++ b/arch/arm/boot/dts/imx28-cfa10055.dts
@@ -14,7 +14,7 @@
  * The CFA-10055 is an expansion board for the CFA-10036 module and
  * CFA-10037, thus we need to include the CFA-10037 DTS.
  */
-/include/ "imx28-cfa10037.dts"
+#include "imx28-cfa10037.dts"
 
 / {
 	model = "Crystalfontz CFA-10055 Board";
@@ -26,64 +26,64 @@
 				spi2_pins_cfa10055: spi2-cfa10055@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x2103 /* MX28_PAD_SSP2_SCK__GPIO_2_16 */
-						0x2113 /* MX28_PAD_SSP2_CMD__GPIO_2_17 */
-						0x2123 /* MX28_PAD_SSP2_D0__GPIO_2_18 */
-						0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
+						MX28_PAD_SSP2_SCK__GPIO_2_16
+						MX28_PAD_SSP2_MOSI__GPIO_2_17
+						MX28_PAD_SSP2_MISO__GPIO_2_18
+						MX28_PAD_AUART1_TX__GPIO_3_5
 					>;
-					fsl,drive-strength = <1>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				lcdif_18bit_pins_cfa10055: lcdif-18bit@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x1000 /* MX28_PAD_LCD_D00__LCD_D0 */
-						0x1010 /* MX28_PAD_LCD_D01__LCD_D1 */
-						0x1020 /* MX28_PAD_LCD_D02__LCD_D2 */
-						0x1030 /* MX28_PAD_LCD_D03__LCD_D3 */
-						0x1040 /* MX28_PAD_LCD_D04__LCD_D4 */
-						0x1050 /* MX28_PAD_LCD_D05__LCD_D5 */
-						0x1060 /* MX28_PAD_LCD_D06__LCD_D6 */
-						0x1070 /* MX28_PAD_LCD_D07__LCD_D7 */
-						0x1080 /* MX28_PAD_LCD_D08__LCD_D8 */
-						0x1090 /* MX28_PAD_LCD_D09__LCD_D9 */
-						0x10a0 /* MX28_PAD_LCD_D10__LCD_D10 */
-						0x10b0 /* MX28_PAD_LCD_D11__LCD_D11 */
-						0x10c0 /* MX28_PAD_LCD_D12__LCD_D12 */
-						0x10d0 /* MX28_PAD_LCD_D13__LCD_D13 */
-						0x10e0 /* MX28_PAD_LCD_D14__LCD_D14 */
-						0x10f0 /* MX28_PAD_LCD_D15__LCD_D15 */
-						0x1100 /* MX28_PAD_LCD_D16__LCD_D16 */
-						0x1110 /* MX28_PAD_LCD_D17__LCD_D17 */
+						MX28_PAD_LCD_D00__LCD_D0
+						MX28_PAD_LCD_D01__LCD_D1
+						MX28_PAD_LCD_D02__LCD_D2
+						MX28_PAD_LCD_D03__LCD_D3
+						MX28_PAD_LCD_D04__LCD_D4
+						MX28_PAD_LCD_D05__LCD_D5
+						MX28_PAD_LCD_D06__LCD_D6
+						MX28_PAD_LCD_D07__LCD_D7
+						MX28_PAD_LCD_D08__LCD_D8
+						MX28_PAD_LCD_D09__LCD_D9
+						MX28_PAD_LCD_D10__LCD_D10
+						MX28_PAD_LCD_D11__LCD_D11
+						MX28_PAD_LCD_D12__LCD_D12
+						MX28_PAD_LCD_D13__LCD_D13
+						MX28_PAD_LCD_D14__LCD_D14
+						MX28_PAD_LCD_D15__LCD_D15
+						MX28_PAD_LCD_D16__LCD_D16
+						MX28_PAD_LCD_D17__LCD_D17
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				lcdif_pins_cfa10055: lcdif-evk@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
-						0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
-						0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
-						0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+						MX28_PAD_LCD_RD_E__LCD_VSYNC
+						MX28_PAD_LCD_WR_RWN__LCD_HSYNC
+						MX28_PAD_LCD_RS__LCD_DOTCLK
+						MX28_PAD_LCD_CS__LCD_ENABLE
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				lcdif_pins_cfa10055_pullup: lcdif-10055-pullup@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
+						MX28_PAD_LCD_RESET__GPIO_3_30
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 			};
 
diff --git a/arch/arm/boot/dts/imx28-cfa10056.dts b/arch/arm/boot/dts/imx28-cfa10056.dts
index b45dd0e..cef959a 100644
--- a/arch/arm/boot/dts/imx28-cfa10056.dts
+++ b/arch/arm/boot/dts/imx28-cfa10056.dts
@@ -13,7 +13,7 @@
  * The CFA-10055 is an expansion board for the CFA-10036 module and
  * CFA-10037, thus we need to include the CFA-10037 DTS.
  */
-/include/ "imx28-cfa10037.dts"
+#include "imx28-cfa10037.dts"
 
 / {
 	model = "Crystalfontz CFA-10056 Board";
@@ -25,37 +25,37 @@
 				spi2_pins_cfa10056: spi2-cfa10056@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x2103 /* MX28_PAD_SSP2_SCK__GPIO_2_16 */
-						0x2113 /* MX28_PAD_SSP2_CMD__GPIO_2_17 */
-						0x2123 /* MX28_PAD_SSP2_D0__GPIO_2_18 */
-						0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
+						MX28_PAD_SSP2_SCK__GPIO_2_16
+						MX28_PAD_SSP2_MOSI__GPIO_2_17
+						MX28_PAD_SSP2_MISO__GPIO_2_18
+						MX28_PAD_AUART1_TX__GPIO_3_5
 					>;
-					fsl,drive-strength = <1>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				lcdif_pins_cfa10056: lcdif-10056@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
-						0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
-						0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
-						0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+						MX28_PAD_LCD_RD_E__LCD_VSYNC
+						MX28_PAD_LCD_WR_RWN__LCD_HSYNC
+						MX28_PAD_LCD_RS__LCD_DOTCLK
+						MX28_PAD_LCD_CS__LCD_ENABLE
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				lcdif_pins_cfa10056_pullup: lcdif-10056-pullup@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
+						MX28_PAD_LCD_RESET__GPIO_3_30
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 			};
 
diff --git a/arch/arm/boot/dts/imx28-cfa10057.dts b/arch/arm/boot/dts/imx28-cfa10057.dts
index 0333c05..3c13128 100644
--- a/arch/arm/boot/dts/imx28-cfa10057.dts
+++ b/arch/arm/boot/dts/imx28-cfa10057.dts
@@ -14,7 +14,7 @@
  * The CFA-10057 is an expansion board for the CFA-10036 module, thus we
  * need to include the CFA-10036 DTS.
  */
-/include/ "imx28-cfa10036.dts"
+#include "imx28-cfa10036.dts"
 
 / {
 	model = "Crystalfontz CFA-10057 Board";
@@ -26,51 +26,51 @@
 				usb_pins_cfa10057: usb-10057@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x0073 /* MX28_PAD_GPMI_D7__GPIO_0_7 */
+						MX28_PAD_GPMI_D07__GPIO_0_7
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				lcdif_18bit_pins_cfa10057: lcdif-18bit@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x1000 /* MX28_PAD_LCD_D00__LCD_D0 */
-						0x1010 /* MX28_PAD_LCD_D01__LCD_D1 */
-						0x1020 /* MX28_PAD_LCD_D02__LCD_D2 */
-						0x1030 /* MX28_PAD_LCD_D03__LCD_D3 */
-						0x1040 /* MX28_PAD_LCD_D04__LCD_D4 */
-						0x1050 /* MX28_PAD_LCD_D05__LCD_D5 */
-						0x1060 /* MX28_PAD_LCD_D06__LCD_D6 */
-						0x1070 /* MX28_PAD_LCD_D07__LCD_D7 */
-						0x1080 /* MX28_PAD_LCD_D08__LCD_D8 */
-						0x1090 /* MX28_PAD_LCD_D09__LCD_D9 */
-						0x10a0 /* MX28_PAD_LCD_D10__LCD_D10 */
-						0x10b0 /* MX28_PAD_LCD_D11__LCD_D11 */
-						0x10c0 /* MX28_PAD_LCD_D12__LCD_D12 */
-						0x10d0 /* MX28_PAD_LCD_D13__LCD_D13 */
-						0x10e0 /* MX28_PAD_LCD_D14__LCD_D14 */
-						0x10f0 /* MX28_PAD_LCD_D15__LCD_D15 */
-						0x1100 /* MX28_PAD_LCD_D16__LCD_D16 */
-						0x1110 /* MX28_PAD_LCD_D17__LCD_D17 */
+						MX28_PAD_LCD_D00__LCD_D0
+						MX28_PAD_LCD_D01__LCD_D1
+						MX28_PAD_LCD_D02__LCD_D2
+						MX28_PAD_LCD_D03__LCD_D3
+						MX28_PAD_LCD_D04__LCD_D4
+						MX28_PAD_LCD_D05__LCD_D5
+						MX28_PAD_LCD_D06__LCD_D6
+						MX28_PAD_LCD_D07__LCD_D7
+						MX28_PAD_LCD_D08__LCD_D8
+						MX28_PAD_LCD_D09__LCD_D9
+						MX28_PAD_LCD_D10__LCD_D10
+						MX28_PAD_LCD_D11__LCD_D11
+						MX28_PAD_LCD_D12__LCD_D12
+						MX28_PAD_LCD_D13__LCD_D13
+						MX28_PAD_LCD_D14__LCD_D14
+						MX28_PAD_LCD_D15__LCD_D15
+						MX28_PAD_LCD_D16__LCD_D16
+						MX28_PAD_LCD_D17__LCD_D17
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				lcdif_pins_cfa10057: lcdif-evk@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
-						0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
-						0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
-						0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+						MX28_PAD_LCD_RD_E__LCD_VSYNC
+						MX28_PAD_LCD_WR_RWN__LCD_HSYNC
+						MX28_PAD_LCD_RS__LCD_DOTCLK
+						MX28_PAD_LCD_CS__LCD_ENABLE
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 			};
 
diff --git a/arch/arm/boot/dts/imx28-cfa10058.dts b/arch/arm/boot/dts/imx28-cfa10058.dts
index 64c64c5..2469d34 100644
--- a/arch/arm/boot/dts/imx28-cfa10058.dts
+++ b/arch/arm/boot/dts/imx28-cfa10058.dts
@@ -14,7 +14,7 @@
  * The CFA-10058 is an expansion board for the CFA-10036 module, thus we
  * need to include the CFA-10036 DTS.
  */
-/include/ "imx28-cfa10036.dts"
+#include "imx28-cfa10036.dts"
 
 / {
 	model = "Crystalfontz CFA-10058 Board";
@@ -26,24 +26,24 @@
 				usb_pins_cfa10058: usb-10058@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x0073 /* MX28_PAD_GPMI_D7__GPIO_0_7 */
+						MX28_PAD_GPMI_D07__GPIO_0_7
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				lcdif_pins_cfa10058: lcdif-10058@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
-						0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
-						0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
-						0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+						MX28_PAD_LCD_RD_E__LCD_VSYNC
+						MX28_PAD_LCD_WR_RWN__LCD_HSYNC
+						MX28_PAD_LCD_RS__LCD_DOTCLK
+						MX28_PAD_LCD_CS__LCD_ENABLE
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 			};
 
diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts
index 15715d9..4267c2b 100644
--- a/arch/arm/boot/dts/imx28-evk.dts
+++ b/arch/arm/boot/dts/imx28-evk.dts
@@ -10,7 +10,7 @@
  */
 
 /dts-v1/;
-/include/ "imx28.dtsi"
+#include "imx28.dtsi"
 
 / {
 	model = "Freescale i.MX28 Evaluation Kit";
@@ -70,52 +70,52 @@
 				hog_pins_a: hog@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x20d3 /* MX28_PAD_SSP1_CMD__GPIO_2_13 */
-						0x20f3 /* MX28_PAD_SSP1_DATA3__GPIO_2_15 */
-						0x40d3 /* MX28_PAD_ENET0_RX_CLK__GPIO_4_13 */
-						0x20c3 /* MX28_PAD_SSP1_SCK__GPIO_2_12 */
-						0x31c3 /* MX28_PAD_PWM3__GPIO_3_28 */
-						0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
-						0x3083 /* MX28_PAD_AUART2_RX__GPIO_3_8 */
-						0x3093 /* MX28_PAD_AUART2_TX__GPIO_3_9 */
+						MX28_PAD_SSP1_CMD__GPIO_2_13
+						MX28_PAD_SSP1_DATA3__GPIO_2_15
+						MX28_PAD_ENET0_RX_CLK__GPIO_4_13
+						MX28_PAD_SSP1_SCK__GPIO_2_12
+						MX28_PAD_PWM3__GPIO_3_28
+						MX28_PAD_LCD_RESET__GPIO_3_30
+						MX28_PAD_AUART2_RX__GPIO_3_8
+						MX28_PAD_AUART2_TX__GPIO_3_9
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				led_pin_gpio3_5: led_gpio3_5@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
+						MX28_PAD_AUART1_TX__GPIO_3_5
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				gpmi_pins_evk: gpmi-nand-evk@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x0110 /* MX28_PAD_GPMI_CE1N__GPMI_CE1N */
-						0x0150 /* MX28_PAD_GPMI_RDY1__GPMI_READY1 */
+						MX28_PAD_GPMI_CE1N__GPMI_CE1N
+						MX28_PAD_GPMI_RDY1__GPMI_READY1
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				lcdif_pins_evk: lcdif-evk@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
-						0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
-						0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
-						0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+						MX28_PAD_LCD_RD_E__LCD_VSYNC
+						MX28_PAD_LCD_WR_RWN__LCD_HSYNC
+						MX28_PAD_LCD_RS__LCD_DOTCLK
+						MX28_PAD_LCD_CS__LCD_ENABLE
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 			};
 
@@ -182,7 +182,12 @@
 			};
 
 			lradc@80050000 {
+				fsl,lradc-touchscreen-wires = <4>;
 				status = "okay";
+				fsl,lradc-touchscreen-wires = <4>;
+				fsl,ave-ctrl = <4>;
+				fsl,ave-delay = <2>;
+				fsl,settling = <10>;
 			};
 
 			i2c0: i2c@80058000 {
@@ -242,6 +247,8 @@
 
 	ahb@80080000 {
 		usb0: usb@80080000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&usb0_id_pins_a>;
 			vbus-supply = <&reg_usb0_vbus>;
 			status = "okay";
 		};
diff --git a/arch/arm/boot/dts/imx28-m28cu3.dts b/arch/arm/boot/dts/imx28-m28cu3.dts
new file mode 100644
index 0000000..d3958da
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-m28cu3.dts
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2013 Marek Vasut <marex@denx.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx28.dtsi"
+
+/ {
+	model = "MSR M28CU3";
+	compatible = "msr,m28cu3", "fsl,imx28";
+
+	memory {
+		reg = <0x40000000 0x08000000>;
+	};
+
+	apb@80000000 {
+		apbh@80000000 {
+			gpmi-nand@8000c000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg>;
+				status = "okay";
+
+				partition@0 {
+					label = "gpmi-nfc-0-boot";
+					reg = <0x00000000 0x01400000>;
+					read-only;
+				};
+
+				partition@1 {
+					label = "gpmi-nfc-general-use";
+					reg = <0x01400000 0x0ec00000>;
+				};
+			};
+
+			ssp0: ssp@80010000 {
+				compatible = "fsl,imx28-mmc";
+				pinctrl-names = "default";
+				pinctrl-0 = <&mmc0_4bit_pins_a
+					     &mmc0_cd_cfg
+					     &mmc0_sck_cfg>;
+				bus-width = <4>;
+				vmmc-supply = <&reg_vddio_sd0>;
+				status = "okay";
+			};
+
+			ssp2: ssp@80014000 {
+				compatible = "fsl,imx28-mmc";
+				pinctrl-names = "default";
+				pinctrl-0 = <&mmc2_4bit_pins_a
+					     &mmc2_cd_cfg
+					     &mmc2_sck_cfg>;
+				bus-width = <4>;
+				vmmc-supply = <&reg_vddio_sd1>;
+				status = "okay";
+			};
+
+			pinctrl@80018000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&hog_pins_a>;
+
+				hog_pins_a: hog@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX28_PAD_SSP2_SS0__GPIO_2_19
+						MX28_PAD_PWM4__GPIO_3_29
+						MX28_PAD_AUART2_RX__GPIO_3_8
+						MX28_PAD_ENET0_RX_CLK__GPIO_4_13
+					>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
+				};
+
+				lcdif_pins_m28: lcdif-m28@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX28_PAD_LCD_VSYNC__LCD_VSYNC
+						MX28_PAD_LCD_HSYNC__LCD_HSYNC
+						MX28_PAD_LCD_DOTCLK__LCD_DOTCLK
+						MX28_PAD_LCD_RESET__LCD_RESET
+						MX28_PAD_LCD_CS__LCD_ENABLE
+						MX28_PAD_AUART1_TX__GPIO_3_5
+					>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
+				};
+
+				led_pins_gpio: leds-m28@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX28_PAD_SSP3_MISO__GPIO_2_26
+						MX28_PAD_SSP3_SCK__GPIO_2_24
+					>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
+				};
+			};
+
+			ocotp@8002c000 {
+				status = "okay";
+			};
+
+			lcdif@80030000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&lcdif_24bit_pins_a
+					     &lcdif_pins_m28>;
+				display = <&display>;
+				reset-active-high;
+				status = "okay";
+
+				display: display0 {
+					bits-per-pixel = <32>;
+					bus-width = <24>;
+
+					display-timings {
+						native-mode = <&timing0>;
+						timing0: timing0 {
+							clock-frequency = <6410256>;
+							hactive = <320>;
+							vactive = <240>;
+							hback-porch = <38>;
+							hfront-porch = <20>;
+							vback-porch = <15>;
+							vfront-porch = <5>;
+							hsync-len = <30>;
+							vsync-len = <3>;
+							hsync-active = <0>;
+							vsync-active = <0>;
+							de-active = <1>;
+							pixelclk-active = <1>;
+						};
+					};
+				};
+			};
+		};
+
+		apbx@80040000 {
+			duart: serial@80074000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&duart_pins_b>;
+				status = "okay";
+			};
+
+			usbphy1: usbphy@8007e000 {
+				status = "okay";
+			};
+
+			auart0: serial@8006a000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&auart0_2pins_a>;
+				status = "okay";
+			};
+
+			auart3: serial@80070000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&auart3_2pins_b>;
+				status = "okay";
+			};
+
+			pwm: pwm@80064000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pwm3_pins_a>;
+				status = "okay";
+			};
+		};
+	};
+
+	ahb@80080000 {
+		usb1: usb@80090000 {
+			vbus-supply = <&reg_usb1_vbus>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&usbphy1_pins_a>;
+			disable-over-current;
+			status = "okay";
+		};
+
+		mac0: ethernet@800f0000 {
+			phy-mode = "rmii";
+			pinctrl-names = "default";
+			pinctrl-0 = <&mac0_pins_a>;
+			phy-reset-gpios = <&gpio4 13 0>;
+			phy-reset-duration = <100>;
+			status = "okay";
+		};
+
+		mac1: ethernet@800f4000 {
+			phy-mode = "rmii";
+			pinctrl-names = "default";
+			pinctrl-0 = <&mac1_pins_a>;
+			status = "okay";
+		};
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm 3 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pins_gpio>;
+
+		user1 {
+			label = "sd0-led";
+			gpios = <&gpio2 26 0>;
+			linux,default-trigger = "mmc0";
+		};
+
+		user2 {
+			label = "sd1-led";
+			gpios = <&gpio2 24 0>;
+			linux,default-trigger = "mmc2";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_3p3v: 3p3v {
+			compatible = "regulator-fixed";
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+		reg_vddio_sd0: vddio-sd0 {
+			compatible = "regulator-fixed";
+			regulator-name = "vddio-sd0";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio3 29 0>;
+		};
+
+		reg_vddio_sd1: vddio-sd1 {
+			compatible = "regulator-fixed";
+			regulator-name = "vddio-sd1";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio2 19 0>;
+		};
+
+		reg_usb1_vbus: usb1_vbus {
+			compatible = "regulator-fixed";
+			regulator-name = "usb1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 8 0>;
+			enable-active-high;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx28-m28evk.dts b/arch/arm/boot/dts/imx28-m28evk.dts
index 0d322a2..8e2477f 100644
--- a/arch/arm/boot/dts/imx28-m28evk.dts
+++ b/arch/arm/boot/dts/imx28-m28evk.dts
@@ -10,7 +10,7 @@
  */
 
 /dts-v1/;
-/include/ "imx28.dtsi"
+#include "imx28.dtsi"
 
 / {
 	model = "DENX M28EVK";
@@ -92,26 +92,26 @@
 				hog_pins_a: hog@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x31c3 /* MX28_PAD_PWM3__GPIO_3_28 */
-						0x30a3 /* MX28_PAD_AUART2_CTS__GPIO_3_10 */
-						0x30b3 /* MX28_PAD_AUART2_RTS__GPIO_3_11 */
-						0x30c3 /* MX28_PAD_AUART3_RX__GPIO_3_12 */
-						0x30d3 /* MX28_PAD_AUART3_TX__GPIO_3_13 */
+						MX28_PAD_PWM3__GPIO_3_28
+						MX28_PAD_AUART2_CTS__GPIO_3_10
+						MX28_PAD_AUART2_RTS__GPIO_3_11
+						MX28_PAD_AUART3_RX__GPIO_3_12
+						MX28_PAD_AUART3_TX__GPIO_3_13
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				lcdif_pins_m28: lcdif-m28@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x11e0 /* MX28_PAD_LCD_DOTCLK__LCD_DOTCLK */
-						0x11f0 /* MX28_PAD_LCD_ENABLE__LCD_ENABLE */
+						MX28_PAD_LCD_DOTCLK__LCD_DOTCLK
+						MX28_PAD_LCD_ENABLE__LCD_ENABLE
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 			};
 
diff --git a/arch/arm/boot/dts/imx28-pinfunc.h b/arch/arm/boot/dts/imx28-pinfunc.h
new file mode 100644
index 0000000..e11f69b
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-pinfunc.h
@@ -0,0 +1,506 @@
+/*
+ * Header providing constants for i.MX28 pinctrl bindings.
+ *
+ * Copyright (C) 2013 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __DT_BINDINGS_MX28_PINCTRL_H__
+#define __DT_BINDINGS_MX28_PINCTRL_H__
+
+#include "mxs-pinfunc.h"
+
+#define MX28_PAD_GPMI_D00__GPMI_D0			0x0000
+#define MX28_PAD_GPMI_D01__GPMI_D1			0x0010
+#define MX28_PAD_GPMI_D02__GPMI_D2			0x0020
+#define MX28_PAD_GPMI_D03__GPMI_D3			0x0030
+#define MX28_PAD_GPMI_D04__GPMI_D4			0x0040
+#define MX28_PAD_GPMI_D05__GPMI_D5			0x0050
+#define MX28_PAD_GPMI_D06__GPMI_D6			0x0060
+#define MX28_PAD_GPMI_D07__GPMI_D7			0x0070
+#define MX28_PAD_GPMI_CE0N__GPMI_CE0N			0x0100
+#define MX28_PAD_GPMI_CE1N__GPMI_CE1N			0x0110
+#define MX28_PAD_GPMI_CE2N__GPMI_CE2N			0x0120
+#define MX28_PAD_GPMI_CE3N__GPMI_CE3N			0x0130
+#define MX28_PAD_GPMI_RDY0__GPMI_READY0			0x0140
+#define MX28_PAD_GPMI_RDY1__GPMI_READY1			0x0150
+#define MX28_PAD_GPMI_RDY2__GPMI_READY2			0x0160
+#define MX28_PAD_GPMI_RDY3__GPMI_READY3			0x0170
+#define MX28_PAD_GPMI_RDN__GPMI_RDN			0x0180
+#define MX28_PAD_GPMI_WRN__GPMI_WRN			0x0190
+#define MX28_PAD_GPMI_ALE__GPMI_ALE			0x01a0
+#define MX28_PAD_GPMI_CLE__GPMI_CLE			0x01b0
+#define MX28_PAD_GPMI_RESETN__GPMI_RESETN		0x01c0
+#define MX28_PAD_LCD_D00__LCD_D0			0x1000
+#define MX28_PAD_LCD_D01__LCD_D1			0x1010
+#define MX28_PAD_LCD_D02__LCD_D2			0x1020
+#define MX28_PAD_LCD_D03__LCD_D3			0x1030
+#define MX28_PAD_LCD_D04__LCD_D4			0x1040
+#define MX28_PAD_LCD_D05__LCD_D5			0x1050
+#define MX28_PAD_LCD_D06__LCD_D6			0x1060
+#define MX28_PAD_LCD_D07__LCD_D7			0x1070
+#define MX28_PAD_LCD_D08__LCD_D8			0x1080
+#define MX28_PAD_LCD_D09__LCD_D9			0x1090
+#define MX28_PAD_LCD_D10__LCD_D10			0x10a0
+#define MX28_PAD_LCD_D11__LCD_D11			0x10b0
+#define MX28_PAD_LCD_D12__LCD_D12			0x10c0
+#define MX28_PAD_LCD_D13__LCD_D13			0x10d0
+#define MX28_PAD_LCD_D14__LCD_D14			0x10e0
+#define MX28_PAD_LCD_D15__LCD_D15			0x10f0
+#define MX28_PAD_LCD_D16__LCD_D16			0x1100
+#define MX28_PAD_LCD_D17__LCD_D17			0x1110
+#define MX28_PAD_LCD_D18__LCD_D18			0x1120
+#define MX28_PAD_LCD_D19__LCD_D19			0x1130
+#define MX28_PAD_LCD_D20__LCD_D20			0x1140
+#define MX28_PAD_LCD_D21__LCD_D21			0x1150
+#define MX28_PAD_LCD_D22__LCD_D22			0x1160
+#define MX28_PAD_LCD_D23__LCD_D23			0x1170
+#define MX28_PAD_LCD_RD_E__LCD_RD_E			0x1180
+#define MX28_PAD_LCD_WR_RWN__LCD_WR_RWN			0x1190
+#define MX28_PAD_LCD_RS__LCD_RS				0x11a0
+#define MX28_PAD_LCD_CS__LCD_CS				0x11b0
+#define MX28_PAD_LCD_VSYNC__LCD_VSYNC			0x11c0
+#define MX28_PAD_LCD_HSYNC__LCD_HSYNC			0x11d0
+#define MX28_PAD_LCD_DOTCLK__LCD_DOTCLK			0x11e0
+#define MX28_PAD_LCD_ENABLE__LCD_ENABLE			0x11f0
+#define MX28_PAD_SSP0_DATA0__SSP0_D0			0x2000
+#define MX28_PAD_SSP0_DATA1__SSP0_D1			0x2010
+#define MX28_PAD_SSP0_DATA2__SSP0_D2			0x2020
+#define MX28_PAD_SSP0_DATA3__SSP0_D3			0x2030
+#define MX28_PAD_SSP0_DATA4__SSP0_D4			0x2040
+#define MX28_PAD_SSP0_DATA5__SSP0_D5			0x2050
+#define MX28_PAD_SSP0_DATA6__SSP0_D6			0x2060
+#define MX28_PAD_SSP0_DATA7__SSP0_D7			0x2070
+#define MX28_PAD_SSP0_CMD__SSP0_CMD			0x2080
+#define MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT		0x2090
+#define MX28_PAD_SSP0_SCK__SSP0_SCK			0x20a0
+#define MX28_PAD_SSP1_SCK__SSP1_SCK			0x20c0
+#define MX28_PAD_SSP1_CMD__SSP1_CMD			0x20d0
+#define MX28_PAD_SSP1_DATA0__SSP1_D0			0x20e0
+#define MX28_PAD_SSP1_DATA3__SSP1_D3			0x20f0
+#define MX28_PAD_SSP2_SCK__SSP2_SCK			0x2100
+#define MX28_PAD_SSP2_MOSI__SSP2_CMD			0x2110
+#define MX28_PAD_SSP2_MISO__SSP2_D0			0x2120
+#define MX28_PAD_SSP2_SS0__SSP2_D3			0x2130
+#define MX28_PAD_SSP2_SS1__SSP2_D4			0x2140
+#define MX28_PAD_SSP2_SS2__SSP2_D5			0x2150
+#define MX28_PAD_SSP3_SCK__SSP3_SCK			0x2180
+#define MX28_PAD_SSP3_MOSI__SSP3_CMD			0x2190
+#define MX28_PAD_SSP3_MISO__SSP3_D0			0x21a0
+#define MX28_PAD_SSP3_SS0__SSP3_D3			0x21b0
+#define MX28_PAD_AUART0_RX__AUART0_RX			0x3000
+#define MX28_PAD_AUART0_TX__AUART0_TX			0x3010
+#define MX28_PAD_AUART0_CTS__AUART0_CTS			0x3020
+#define MX28_PAD_AUART0_RTS__AUART0_RTS			0x3030
+#define MX28_PAD_AUART1_RX__AUART1_RX			0x3040
+#define MX28_PAD_AUART1_TX__AUART1_TX			0x3050
+#define MX28_PAD_AUART1_CTS__AUART1_CTS			0x3060
+#define MX28_PAD_AUART1_RTS__AUART1_RTS			0x3070
+#define MX28_PAD_AUART2_RX__AUART2_RX			0x3080
+#define MX28_PAD_AUART2_TX__AUART2_TX			0x3090
+#define MX28_PAD_AUART2_CTS__AUART2_CTS			0x30a0
+#define MX28_PAD_AUART2_RTS__AUART2_RTS			0x30b0
+#define MX28_PAD_AUART3_RX__AUART3_RX			0x30c0
+#define MX28_PAD_AUART3_TX__AUART3_TX			0x30d0
+#define MX28_PAD_AUART3_CTS__AUART3_CTS			0x30e0
+#define MX28_PAD_AUART3_RTS__AUART3_RTS			0x30f0
+#define MX28_PAD_PWM0__PWM_0				0x3100
+#define MX28_PAD_PWM1__PWM_1				0x3110
+#define MX28_PAD_PWM2__PWM_2				0x3120
+#define MX28_PAD_SAIF0_MCLK__SAIF0_MCLK			0x3140
+#define MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK		0x3150
+#define MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK		0x3160
+#define MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0		0x3170
+#define MX28_PAD_I2C0_SCL__I2C0_SCL			0x3180
+#define MX28_PAD_I2C0_SDA__I2C0_SDA			0x3190
+#define MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0		0x31a0
+#define MX28_PAD_SPDIF__SPDIF_TX			0x31b0
+#define MX28_PAD_PWM3__PWM_3				0x31c0
+#define MX28_PAD_PWM4__PWM_4				0x31d0
+#define MX28_PAD_LCD_RESET__LCD_RESET			0x31e0
+#define MX28_PAD_ENET0_MDC__ENET0_MDC			0x4000
+#define MX28_PAD_ENET0_MDIO__ENET0_MDIO			0x4010
+#define MX28_PAD_ENET0_RX_EN__ENET0_RX_EN		0x4020
+#define MX28_PAD_ENET0_RXD0__ENET0_RXD0			0x4030
+#define MX28_PAD_ENET0_RXD1__ENET0_RXD1			0x4040
+#define MX28_PAD_ENET0_TX_CLK__ENET0_TX_CLK		0x4050
+#define MX28_PAD_ENET0_TX_EN__ENET0_TX_EN		0x4060
+#define MX28_PAD_ENET0_TXD0__ENET0_TXD0			0x4070
+#define MX28_PAD_ENET0_TXD1__ENET0_TXD1			0x4080
+#define MX28_PAD_ENET0_RXD2__ENET0_RXD2			0x4090
+#define MX28_PAD_ENET0_RXD3__ENET0_RXD3			0x40a0
+#define MX28_PAD_ENET0_TXD2__ENET0_TXD2			0x40b0
+#define MX28_PAD_ENET0_TXD3__ENET0_TXD3			0x40c0
+#define MX28_PAD_ENET0_RX_CLK__ENET0_RX_CLK		0x40d0
+#define MX28_PAD_ENET0_COL__ENET0_COL			0x40e0
+#define MX28_PAD_ENET0_CRS__ENET0_CRS			0x40f0
+#define MX28_PAD_ENET_CLK__CLKCTRL_ENET			0x4100
+#define MX28_PAD_JTAG_RTCK__JTAG_RTCK			0x4140
+#define MX28_PAD_EMI_D00__EMI_DATA0			0x5000
+#define MX28_PAD_EMI_D01__EMI_DATA1			0x5010
+#define MX28_PAD_EMI_D02__EMI_DATA2			0x5020
+#define MX28_PAD_EMI_D03__EMI_DATA3			0x5030
+#define MX28_PAD_EMI_D04__EMI_DATA4			0x5040
+#define MX28_PAD_EMI_D05__EMI_DATA5			0x5050
+#define MX28_PAD_EMI_D06__EMI_DATA6			0x5060
+#define MX28_PAD_EMI_D07__EMI_DATA7			0x5070
+#define MX28_PAD_EMI_D08__EMI_DATA8			0x5080
+#define MX28_PAD_EMI_D09__EMI_DATA9			0x5090
+#define MX28_PAD_EMI_D10__EMI_DATA10			0x50a0
+#define MX28_PAD_EMI_D11__EMI_DATA11			0x50b0
+#define MX28_PAD_EMI_D12__EMI_DATA12			0x50c0
+#define MX28_PAD_EMI_D13__EMI_DATA13			0x50d0
+#define MX28_PAD_EMI_D14__EMI_DATA14			0x50e0
+#define MX28_PAD_EMI_D15__EMI_DATA15			0x50f0
+#define MX28_PAD_EMI_ODT0__EMI_ODT0			0x5100
+#define MX28_PAD_EMI_DQM0__EMI_DQM0			0x5110
+#define MX28_PAD_EMI_ODT1__EMI_ODT1			0x5120
+#define MX28_PAD_EMI_DQM1__EMI_DQM1			0x5130
+#define MX28_PAD_EMI_DDR_OPEN_FB__EMI_DDR_OPEN_FEEDBACK	0x5140
+#define MX28_PAD_EMI_CLK__EMI_CLK			0x5150
+#define MX28_PAD_EMI_DQS0__EMI_DQS0			0x5160
+#define MX28_PAD_EMI_DQS1__EMI_DQS1			0x5170
+#define MX28_PAD_EMI_DDR_OPEN__EMI_DDR_OPEN		0x51a0
+#define MX28_PAD_EMI_A00__EMI_ADDR0			0x6000
+#define MX28_PAD_EMI_A01__EMI_ADDR1			0x6010
+#define MX28_PAD_EMI_A02__EMI_ADDR2			0x6020
+#define MX28_PAD_EMI_A03__EMI_ADDR3			0x6030
+#define MX28_PAD_EMI_A04__EMI_ADDR4			0x6040
+#define MX28_PAD_EMI_A05__EMI_ADDR5			0x6050
+#define MX28_PAD_EMI_A06__EMI_ADDR6			0x6060
+#define MX28_PAD_EMI_A07__EMI_ADDR7			0x6070
+#define MX28_PAD_EMI_A08__EMI_ADDR8			0x6080
+#define MX28_PAD_EMI_A09__EMI_ADDR9			0x6090
+#define MX28_PAD_EMI_A10__EMI_ADDR10			0x60a0
+#define MX28_PAD_EMI_A11__EMI_ADDR11			0x60b0
+#define MX28_PAD_EMI_A12__EMI_ADDR12			0x60c0
+#define MX28_PAD_EMI_A13__EMI_ADDR13			0x60d0
+#define MX28_PAD_EMI_A14__EMI_ADDR14			0x60e0
+#define MX28_PAD_EMI_BA0__EMI_BA0			0x6100
+#define MX28_PAD_EMI_BA1__EMI_BA1			0x6110
+#define MX28_PAD_EMI_BA2__EMI_BA2			0x6120
+#define MX28_PAD_EMI_CASN__EMI_CASN			0x6130
+#define MX28_PAD_EMI_RASN__EMI_RASN			0x6140
+#define MX28_PAD_EMI_WEN__EMI_WEN			0x6150
+#define MX28_PAD_EMI_CE0N__EMI_CE0N			0x6160
+#define MX28_PAD_EMI_CE1N__EMI_CE1N			0x6170
+#define MX28_PAD_EMI_CKE__EMI_CKE			0x6180
+#define MX28_PAD_GPMI_D00__SSP1_D0			0x0001
+#define MX28_PAD_GPMI_D01__SSP1_D1			0x0011
+#define MX28_PAD_GPMI_D02__SSP1_D2			0x0021
+#define MX28_PAD_GPMI_D03__SSP1_D3			0x0031
+#define MX28_PAD_GPMI_D04__SSP1_D4			0x0041
+#define MX28_PAD_GPMI_D05__SSP1_D5			0x0051
+#define MX28_PAD_GPMI_D06__SSP1_D6			0x0061
+#define MX28_PAD_GPMI_D07__SSP1_D7			0x0071
+#define MX28_PAD_GPMI_CE0N__SSP3_D0			0x0101
+#define MX28_PAD_GPMI_CE1N__SSP3_D3			0x0111
+#define MX28_PAD_GPMI_CE2N__CAN1_TX			0x0121
+#define MX28_PAD_GPMI_CE3N__CAN1_RX			0x0131
+#define MX28_PAD_GPMI_RDY0__SSP1_CARD_DETECT		0x0141
+#define MX28_PAD_GPMI_RDY1__SSP1_CMD			0x0151
+#define MX28_PAD_GPMI_RDY2__CAN0_TX			0x0161
+#define MX28_PAD_GPMI_RDY3__CAN0_RX			0x0171
+#define MX28_PAD_GPMI_RDN__SSP3_SCK			0x0181
+#define MX28_PAD_GPMI_WRN__SSP1_SCK			0x0191
+#define MX28_PAD_GPMI_ALE__SSP3_D1			0x01a1
+#define MX28_PAD_GPMI_CLE__SSP3_D2			0x01b1
+#define MX28_PAD_GPMI_RESETN__SSP3_CMD			0x01c1
+#define MX28_PAD_LCD_D03__ETM_DA8			0x1031
+#define MX28_PAD_LCD_D04__ETM_DA9			0x1041
+#define MX28_PAD_LCD_D08__ETM_DA3			0x1081
+#define MX28_PAD_LCD_D09__ETM_DA4			0x1091
+#define MX28_PAD_LCD_D20__ENET1_1588_EVENT2_OUT		0x1141
+#define MX28_PAD_LCD_D21__ENET1_1588_EVENT2_IN		0x1151
+#define MX28_PAD_LCD_D22__ENET1_1588_EVENT3_OUT		0x1161
+#define MX28_PAD_LCD_D23__ENET1_1588_EVENT3_IN		0x1171
+#define MX28_PAD_LCD_RD_E__LCD_VSYNC			0x1181
+#define MX28_PAD_LCD_WR_RWN__LCD_HSYNC			0x1191
+#define MX28_PAD_LCD_RS__LCD_DOTCLK			0x11a1
+#define MX28_PAD_LCD_CS__LCD_ENABLE			0x11b1
+#define MX28_PAD_LCD_VSYNC__SAIF1_SDATA0		0x11c1
+#define MX28_PAD_LCD_HSYNC__SAIF1_SDATA1		0x11d1
+#define MX28_PAD_LCD_DOTCLK__SAIF1_MCLK			0x11e1
+#define MX28_PAD_SSP0_DATA4__SSP2_D0			0x2041
+#define MX28_PAD_SSP0_DATA5__SSP2_D3			0x2051
+#define MX28_PAD_SSP0_DATA6__SSP2_CMD			0x2061
+#define MX28_PAD_SSP0_DATA7__SSP2_SCK			0x2071
+#define MX28_PAD_SSP1_SCK__SSP2_D1			0x20c1
+#define MX28_PAD_SSP1_CMD__SSP2_D2			0x20d1
+#define MX28_PAD_SSP1_DATA0__SSP2_D6			0x20e1
+#define MX28_PAD_SSP1_DATA3__SSP2_D7			0x20f1
+#define MX28_PAD_SSP2_SCK__AUART2_RX			0x2101
+#define MX28_PAD_SSP2_MOSI__AUART2_TX			0x2111
+#define MX28_PAD_SSP2_MISO__AUART3_RX			0x2121
+#define MX28_PAD_SSP2_SS0__AUART3_TX			0x2131
+#define MX28_PAD_SSP2_SS1__SSP2_D1			0x2141
+#define MX28_PAD_SSP2_SS2__SSP2_D2			0x2151
+#define MX28_PAD_SSP3_SCK__AUART4_TX			0x2181
+#define MX28_PAD_SSP3_MOSI__AUART4_RX			0x2191
+#define MX28_PAD_SSP3_MISO__AUART4_RTS			0x21a1
+#define MX28_PAD_SSP3_SS0__AUART4_CTS			0x21b1
+#define MX28_PAD_AUART0_RX__I2C0_SCL			0x3001
+#define MX28_PAD_AUART0_TX__I2C0_SDA			0x3011
+#define MX28_PAD_AUART0_CTS__AUART4_RX			0x3021
+#define MX28_PAD_AUART0_RTS__AUART4_TX			0x3031
+#define MX28_PAD_AUART1_RX__SSP2_CARD_DETECT		0x3041
+#define MX28_PAD_AUART1_TX__SSP3_CARD_DETECT		0x3051
+#define MX28_PAD_AUART1_CTS__USB0_OVERCURRENT		0x3061
+#define MX28_PAD_AUART1_RTS__USB0_ID			0x3071
+#define MX28_PAD_AUART2_RX__SSP3_D1			0x3081
+#define MX28_PAD_AUART2_TX__SSP3_D2			0x3091
+#define MX28_PAD_AUART2_CTS__I2C1_SCL			0x30a1
+#define MX28_PAD_AUART2_RTS__I2C1_SDA			0x30b1
+#define MX28_PAD_AUART3_RX__CAN0_TX			0x30c1
+#define MX28_PAD_AUART3_TX__CAN0_RX			0x30d1
+#define MX28_PAD_AUART3_CTS__CAN1_TX			0x30e1
+#define MX28_PAD_AUART3_RTS__CAN1_RX			0x30f1
+#define MX28_PAD_PWM0__I2C1_SCL				0x3101
+#define MX28_PAD_PWM1__I2C1_SDA				0x3111
+#define MX28_PAD_PWM2__USB0_ID				0x3121
+#define MX28_PAD_SAIF0_MCLK__PWM_3			0x3141
+#define MX28_PAD_SAIF0_LRCLK__PWM_4			0x3151
+#define MX28_PAD_SAIF0_BITCLK__PWM_5			0x3161
+#define MX28_PAD_SAIF0_SDATA0__PWM_6			0x3171
+#define MX28_PAD_I2C0_SCL__TIMROT_ROTARYA		0x3181
+#define MX28_PAD_I2C0_SDA__TIMROT_ROTARYB		0x3191
+#define MX28_PAD_SAIF1_SDATA0__PWM_7			0x31a1
+#define MX28_PAD_LCD_RESET__LCD_VSYNC			0x31e1
+#define MX28_PAD_ENET0_MDC__GPMI_CE4N			0x4001
+#define MX28_PAD_ENET0_MDIO__GPMI_CE5N			0x4011
+#define MX28_PAD_ENET0_RX_EN__GPMI_CE6N			0x4021
+#define MX28_PAD_ENET0_RXD0__GPMI_CE7N			0x4031
+#define MX28_PAD_ENET0_RXD1__GPMI_READY4		0x4041
+#define MX28_PAD_ENET0_TX_CLK__HSADC_TRIGGER		0x4051
+#define MX28_PAD_ENET0_TX_EN__GPMI_READY5		0x4061
+#define MX28_PAD_ENET0_TXD0__GPMI_READY6		0x4071
+#define MX28_PAD_ENET0_TXD1__GPMI_READY7		0x4081
+#define MX28_PAD_ENET0_RXD2__ENET1_RXD0			0x4091
+#define MX28_PAD_ENET0_RXD3__ENET1_RXD1			0x40a1
+#define MX28_PAD_ENET0_TXD2__ENET1_TXD0			0x40b1
+#define MX28_PAD_ENET0_TXD3__ENET1_TXD1			0x40c1
+#define MX28_PAD_ENET0_RX_CLK__ENET0_RX_ER		0x40d1
+#define MX28_PAD_ENET0_COL__ENET1_TX_EN			0x40e1
+#define MX28_PAD_ENET0_CRS__ENET1_RX_EN			0x40f1
+#define MX28_PAD_GPMI_CE2N__ENET0_RX_ER			0x0122
+#define MX28_PAD_GPMI_CE3N__SAIF1_MCLK			0x0132
+#define MX28_PAD_GPMI_RDY0__USB0_ID			0x0142
+#define MX28_PAD_GPMI_RDY2__ENET0_TX_ER			0x0162
+#define MX28_PAD_GPMI_RDY3__HSADC_TRIGGER		0x0172
+#define MX28_PAD_GPMI_ALE__SSP3_D4			0x01a2
+#define MX28_PAD_GPMI_CLE__SSP3_D5			0x01b2
+#define MX28_PAD_LCD_D00__ETM_DA0			0x1002
+#define MX28_PAD_LCD_D01__ETM_DA1			0x1012
+#define MX28_PAD_LCD_D02__ETM_DA2			0x1022
+#define MX28_PAD_LCD_D03__ETM_DA3			0x1032
+#define MX28_PAD_LCD_D04__ETM_DA4			0x1042
+#define MX28_PAD_LCD_D05__ETM_DA5			0x1052
+#define MX28_PAD_LCD_D06__ETM_DA6			0x1062
+#define MX28_PAD_LCD_D07__ETM_DA7			0x1072
+#define MX28_PAD_LCD_D08__ETM_DA8			0x1082
+#define MX28_PAD_LCD_D09__ETM_DA9			0x1092
+#define MX28_PAD_LCD_D10__ETM_DA10			0x10a2
+#define MX28_PAD_LCD_D11__ETM_DA11			0x10b2
+#define MX28_PAD_LCD_D12__ETM_DA12			0x10c2
+#define MX28_PAD_LCD_D13__ETM_DA13			0x10d2
+#define MX28_PAD_LCD_D14__ETM_DA14			0x10e2
+#define MX28_PAD_LCD_D15__ETM_DA15			0x10f2
+#define MX28_PAD_LCD_D16__ETM_DA7			0x1102
+#define MX28_PAD_LCD_D17__ETM_DA6			0x1112
+#define MX28_PAD_LCD_D18__ETM_DA5			0x1122
+#define MX28_PAD_LCD_D19__ETM_DA4			0x1132
+#define MX28_PAD_LCD_D20__ETM_DA3			0x1142
+#define MX28_PAD_LCD_D21__ETM_DA2			0x1152
+#define MX28_PAD_LCD_D22__ETM_DA1			0x1162
+#define MX28_PAD_LCD_D23__ETM_DA0			0x1172
+#define MX28_PAD_LCD_RD_E__ETM_TCTL			0x1182
+#define MX28_PAD_LCD_WR_RWN__ETM_TCLK			0x1192
+#define MX28_PAD_LCD_HSYNC__ETM_TCTL			0x11d2
+#define MX28_PAD_LCD_DOTCLK__ETM_TCLK			0x11e2
+#define MX28_PAD_SSP1_SCK__ENET0_1588_EVENT2_OUT	0x20c2
+#define MX28_PAD_SSP1_CMD__ENET0_1588_EVENT2_IN		0x20d2
+#define MX28_PAD_SSP1_DATA0__ENET0_1588_EVENT3_OUT	0x20e2
+#define MX28_PAD_SSP1_DATA3__ENET0_1588_EVENT3_IN	0x20f2
+#define MX28_PAD_SSP2_SCK__SAIF0_SDATA1			0x2102
+#define MX28_PAD_SSP2_MOSI__SAIF0_SDATA2		0x2112
+#define MX28_PAD_SSP2_MISO__SAIF1_SDATA1		0x2122
+#define MX28_PAD_SSP2_SS0__SAIF1_SDATA2			0x2132
+#define MX28_PAD_SSP2_SS1__USB1_OVERCURRENT		0x2142
+#define MX28_PAD_SSP2_SS2__USB0_OVERCURRENT		0x2152
+#define MX28_PAD_SSP3_SCK__ENET1_1588_EVENT0_OUT	0x2182
+#define MX28_PAD_SSP3_MOSI__ENET1_1588_EVENT0_IN	0x2192
+#define MX28_PAD_SSP3_MISO__ENET1_1588_EVENT1_OUT	0x21a2
+#define MX28_PAD_SSP3_SS0__ENET1_1588_EVENT1_IN		0x21b2
+#define MX28_PAD_AUART0_RX__DUART_CTS			0x3002
+#define MX28_PAD_AUART0_TX__DUART_RTS			0x3012
+#define MX28_PAD_AUART0_CTS__DUART_RX			0x3022
+#define MX28_PAD_AUART0_RTS__DUART_TX			0x3032
+#define MX28_PAD_AUART1_RX__PWM_0			0x3042
+#define MX28_PAD_AUART1_TX__PWM_1			0x3052
+#define MX28_PAD_AUART1_CTS__TIMROT_ROTARYA		0x3062
+#define MX28_PAD_AUART1_RTS__TIMROT_ROTARYB		0x3072
+#define MX28_PAD_AUART2_RX__SSP3_D4			0x3082
+#define MX28_PAD_AUART2_TX__SSP3_D5			0x3092
+#define MX28_PAD_AUART2_CTS__SAIF1_BITCLK		0x30a2
+#define MX28_PAD_AUART2_RTS__SAIF1_LRCLK		0x30b2
+#define MX28_PAD_AUART3_RX__ENET0_1588_EVENT0_OUT	0x30c2
+#define MX28_PAD_AUART3_TX__ENET0_1588_EVENT0_IN	0x30d2
+#define MX28_PAD_AUART3_CTS__ENET0_1588_EVENT1_OUT	0x30e2
+#define MX28_PAD_AUART3_RTS__ENET0_1588_EVENT1_IN	0x30f2
+#define MX28_PAD_PWM0__DUART_RX				0x3102
+#define MX28_PAD_PWM1__DUART_TX				0x3112
+#define MX28_PAD_PWM2__USB1_OVERCURRENT			0x3122
+#define MX28_PAD_SAIF0_MCLK__AUART4_CTS			0x3142
+#define MX28_PAD_SAIF0_LRCLK__AUART4_RTS		0x3152
+#define MX28_PAD_SAIF0_BITCLK__AUART4_RX		0x3162
+#define MX28_PAD_SAIF0_SDATA0__AUART4_TX		0x3172
+#define MX28_PAD_I2C0_SCL__DUART_RX			0x3182
+#define MX28_PAD_I2C0_SDA__DUART_TX			0x3192
+#define MX28_PAD_SAIF1_SDATA0__SAIF0_SDATA1		0x31a2
+#define MX28_PAD_SPDIF__ENET1_RX_ER			0x31b2
+#define MX28_PAD_ENET0_MDC__SAIF0_SDATA1		0x4002
+#define MX28_PAD_ENET0_MDIO__SAIF0_SDATA2		0x4012
+#define MX28_PAD_ENET0_RX_EN__SAIF1_SDATA1		0x4022
+#define MX28_PAD_ENET0_RXD0__SAIF1_SDATA2		0x4032
+#define MX28_PAD_ENET0_TX_CLK__ENET0_1588_EVENT2_OUT	0x4052
+#define MX28_PAD_ENET0_RXD2__ENET0_1588_EVENT0_OUT	0x4092
+#define MX28_PAD_ENET0_RXD3__ENET0_1588_EVENT0_IN	0x40a2
+#define MX28_PAD_ENET0_TXD2__ENET0_1588_EVENT1_OUT	0x40b2
+#define MX28_PAD_ENET0_TXD3__ENET0_1588_EVENT1_IN	0x40c2
+#define MX28_PAD_ENET0_RX_CLK__ENET0_1588_EVENT2_IN	0x40d2
+#define MX28_PAD_ENET0_COL__ENET0_1588_EVENT3_OUT	0x40e2
+#define MX28_PAD_ENET0_CRS__ENET0_1588_EVENT3_IN	0x40f2
+#define MX28_PAD_GPMI_D00__GPIO_0_0			0x0003
+#define MX28_PAD_GPMI_D01__GPIO_0_1			0x0013
+#define MX28_PAD_GPMI_D02__GPIO_0_2			0x0023
+#define MX28_PAD_GPMI_D03__GPIO_0_3			0x0033
+#define MX28_PAD_GPMI_D04__GPIO_0_4			0x0043
+#define MX28_PAD_GPMI_D05__GPIO_0_5			0x0053
+#define MX28_PAD_GPMI_D06__GPIO_0_6			0x0063
+#define MX28_PAD_GPMI_D07__GPIO_0_7			0x0073
+#define MX28_PAD_GPMI_CE0N__GPIO_0_16			0x0103
+#define MX28_PAD_GPMI_CE1N__GPIO_0_17			0x0113
+#define MX28_PAD_GPMI_CE2N__GPIO_0_18			0x0123
+#define MX28_PAD_GPMI_CE3N__GPIO_0_19			0x0133
+#define MX28_PAD_GPMI_RDY0__GPIO_0_20			0x0143
+#define MX28_PAD_GPMI_RDY1__GPIO_0_21			0x0153
+#define MX28_PAD_GPMI_RDY2__GPIO_0_22			0x0163
+#define MX28_PAD_GPMI_RDY3__GPIO_0_23			0x0173
+#define MX28_PAD_GPMI_RDN__GPIO_0_24			0x0183
+#define MX28_PAD_GPMI_WRN__GPIO_0_25			0x0193
+#define MX28_PAD_GPMI_ALE__GPIO_0_26			0x01a3
+#define MX28_PAD_GPMI_CLE__GPIO_0_27			0x01b3
+#define MX28_PAD_GPMI_RESETN__GPIO_0_28			0x01c3
+#define MX28_PAD_LCD_D00__GPIO_1_0			0x1003
+#define MX28_PAD_LCD_D01__GPIO_1_1			0x1013
+#define MX28_PAD_LCD_D02__GPIO_1_2			0x1023
+#define MX28_PAD_LCD_D03__GPIO_1_3			0x1033
+#define MX28_PAD_LCD_D04__GPIO_1_4			0x1043
+#define MX28_PAD_LCD_D05__GPIO_1_5			0x1053
+#define MX28_PAD_LCD_D06__GPIO_1_6			0x1063
+#define MX28_PAD_LCD_D07__GPIO_1_7			0x1073
+#define MX28_PAD_LCD_D08__GPIO_1_8			0x1083
+#define MX28_PAD_LCD_D09__GPIO_1_9			0x1093
+#define MX28_PAD_LCD_D10__GPIO_1_10			0x10a3
+#define MX28_PAD_LCD_D11__GPIO_1_11			0x10b3
+#define MX28_PAD_LCD_D12__GPIO_1_12			0x10c3
+#define MX28_PAD_LCD_D13__GPIO_1_13			0x10d3
+#define MX28_PAD_LCD_D14__GPIO_1_14			0x10e3
+#define MX28_PAD_LCD_D15__GPIO_1_15			0x10f3
+#define MX28_PAD_LCD_D16__GPIO_1_16			0x1103
+#define MX28_PAD_LCD_D17__GPIO_1_17			0x1113
+#define MX28_PAD_LCD_D18__GPIO_1_18			0x1123
+#define MX28_PAD_LCD_D19__GPIO_1_19			0x1133
+#define MX28_PAD_LCD_D20__GPIO_1_20			0x1143
+#define MX28_PAD_LCD_D21__GPIO_1_21			0x1153
+#define MX28_PAD_LCD_D22__GPIO_1_22			0x1163
+#define MX28_PAD_LCD_D23__GPIO_1_23			0x1173
+#define MX28_PAD_LCD_RD_E__GPIO_1_24			0x1183
+#define MX28_PAD_LCD_WR_RWN__GPIO_1_25			0x1193
+#define MX28_PAD_LCD_RS__GPIO_1_26			0x11a3
+#define MX28_PAD_LCD_CS__GPIO_1_27			0x11b3
+#define MX28_PAD_LCD_VSYNC__GPIO_1_28			0x11c3
+#define MX28_PAD_LCD_HSYNC__GPIO_1_29			0x11d3
+#define MX28_PAD_LCD_DOTCLK__GPIO_1_30			0x11e3
+#define MX28_PAD_LCD_ENABLE__GPIO_1_31			0x11f3
+#define MX28_PAD_SSP0_DATA0__GPIO_2_0			0x2003
+#define MX28_PAD_SSP0_DATA1__GPIO_2_1			0x2013
+#define MX28_PAD_SSP0_DATA2__GPIO_2_2			0x2023
+#define MX28_PAD_SSP0_DATA3__GPIO_2_3			0x2033
+#define MX28_PAD_SSP0_DATA4__GPIO_2_4			0x2043
+#define MX28_PAD_SSP0_DATA5__GPIO_2_5			0x2053
+#define MX28_PAD_SSP0_DATA6__GPIO_2_6			0x2063
+#define MX28_PAD_SSP0_DATA7__GPIO_2_7			0x2073
+#define MX28_PAD_SSP0_CMD__GPIO_2_8			0x2083
+#define MX28_PAD_SSP0_DETECT__GPIO_2_9			0x2093
+#define MX28_PAD_SSP0_SCK__GPIO_2_10			0x20a3
+#define MX28_PAD_SSP1_SCK__GPIO_2_12			0x20c3
+#define MX28_PAD_SSP1_CMD__GPIO_2_13			0x20d3
+#define MX28_PAD_SSP1_DATA0__GPIO_2_14			0x20e3
+#define MX28_PAD_SSP1_DATA3__GPIO_2_15			0x20f3
+#define MX28_PAD_SSP2_SCK__GPIO_2_16			0x2103
+#define MX28_PAD_SSP2_MOSI__GPIO_2_17			0x2113
+#define MX28_PAD_SSP2_MISO__GPIO_2_18			0x2123
+#define MX28_PAD_SSP2_SS0__GPIO_2_19			0x2133
+#define MX28_PAD_SSP2_SS1__GPIO_2_20			0x2143
+#define MX28_PAD_SSP2_SS2__GPIO_2_21			0x2153
+#define MX28_PAD_SSP3_SCK__GPIO_2_24			0x2183
+#define MX28_PAD_SSP3_MOSI__GPIO_2_25			0x2193
+#define MX28_PAD_SSP3_MISO__GPIO_2_26			0x21a3
+#define MX28_PAD_SSP3_SS0__GPIO_2_27			0x21b3
+#define MX28_PAD_AUART0_RX__GPIO_3_0			0x3003
+#define MX28_PAD_AUART0_TX__GPIO_3_1			0x3013
+#define MX28_PAD_AUART0_CTS__GPIO_3_2			0x3023
+#define MX28_PAD_AUART0_RTS__GPIO_3_3			0x3033
+#define MX28_PAD_AUART1_RX__GPIO_3_4			0x3043
+#define MX28_PAD_AUART1_TX__GPIO_3_5			0x3053
+#define MX28_PAD_AUART1_CTS__GPIO_3_6			0x3063
+#define MX28_PAD_AUART1_RTS__GPIO_3_7			0x3073
+#define MX28_PAD_AUART2_RX__GPIO_3_8			0x3083
+#define MX28_PAD_AUART2_TX__GPIO_3_9			0x3093
+#define MX28_PAD_AUART2_CTS__GPIO_3_10			0x30a3
+#define MX28_PAD_AUART2_RTS__GPIO_3_11			0x30b3
+#define MX28_PAD_AUART3_RX__GPIO_3_12			0x30c3
+#define MX28_PAD_AUART3_TX__GPIO_3_13			0x30d3
+#define MX28_PAD_AUART3_CTS__GPIO_3_14			0x30e3
+#define MX28_PAD_AUART3_RTS__GPIO_3_15			0x30f3
+#define MX28_PAD_PWM0__GPIO_3_16			0x3103
+#define MX28_PAD_PWM1__GPIO_3_17			0x3113
+#define MX28_PAD_PWM2__GPIO_3_18			0x3123
+#define MX28_PAD_SAIF0_MCLK__GPIO_3_20			0x3143
+#define MX28_PAD_SAIF0_LRCLK__GPIO_3_21			0x3153
+#define MX28_PAD_SAIF0_BITCLK__GPIO_3_22		0x3163
+#define MX28_PAD_SAIF0_SDATA0__GPIO_3_23		0x3173
+#define MX28_PAD_I2C0_SCL__GPIO_3_24			0x3183
+#define MX28_PAD_I2C0_SDA__GPIO_3_25			0x3193
+#define MX28_PAD_SAIF1_SDATA0__GPIO_3_26		0x31a3
+#define MX28_PAD_SPDIF__GPIO_3_27			0x31b3
+#define MX28_PAD_PWM3__GPIO_3_28			0x31c3
+#define MX28_PAD_PWM4__GPIO_3_29			0x31d3
+#define MX28_PAD_LCD_RESET__GPIO_3_30			0x31e3
+#define MX28_PAD_ENET0_MDC__GPIO_4_0			0x4003
+#define MX28_PAD_ENET0_MDIO__GPIO_4_1			0x4013
+#define MX28_PAD_ENET0_RX_EN__GPIO_4_2			0x4023
+#define MX28_PAD_ENET0_RXD0__GPIO_4_3			0x4033
+#define MX28_PAD_ENET0_RXD1__GPIO_4_4			0x4043
+#define MX28_PAD_ENET0_TX_CLK__GPIO_4_5			0x4053
+#define MX28_PAD_ENET0_TX_EN__GPIO_4_6			0x4063
+#define MX28_PAD_ENET0_TXD0__GPIO_4_7			0x4073
+#define MX28_PAD_ENET0_TXD1__GPIO_4_8			0x4083
+#define MX28_PAD_ENET0_RXD2__GPIO_4_9			0x4093
+#define MX28_PAD_ENET0_RXD3__GPIO_4_10			0x40a3
+#define MX28_PAD_ENET0_TXD2__GPIO_4_11			0x40b3
+#define MX28_PAD_ENET0_TXD3__GPIO_4_12			0x40c3
+#define MX28_PAD_ENET0_RX_CLK__GPIO_4_13		0x40d3
+#define MX28_PAD_ENET0_COL__GPIO_4_14			0x40e3
+#define MX28_PAD_ENET0_CRS__GPIO_4_15			0x40f3
+#define MX28_PAD_ENET_CLK__GPIO_4_16			0x4103
+#define MX28_PAD_JTAG_RTCK__GPIO_4_20			0x4143
+
+#endif /* __DT_BINDINGS_MX28_PINCTRL_H__ */
diff --git a/arch/arm/boot/dts/imx28-sps1.dts b/arch/arm/boot/dts/imx28-sps1.dts
index 6c6a544..4870f07 100644
--- a/arch/arm/boot/dts/imx28-sps1.dts
+++ b/arch/arm/boot/dts/imx28-sps1.dts
@@ -10,7 +10,7 @@
  */
 
 /dts-v1/;
-/include/ "imx28.dtsi"
+#include "imx28.dtsi"
 
 / {
 	model = "SchulerControl GmbH, SC SPS 1";
@@ -29,13 +29,13 @@
 				hog_pins_a: hog-gpios@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x0003 /* MX28_PAD_GPMI_D00__GPIO_0_0 */
-						0x0033 /* MX28_PAD_GPMI_D03__GPIO_0_3 */
-						0x0063 /* MX28_PAD_GPMI_D06__GPIO_0_6 */
+						MX28_PAD_GPMI_D00__GPIO_0_0
+						MX28_PAD_GPMI_D03__GPIO_0_3
+						MX28_PAD_GPMI_D06__GPIO_0_6
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 			};
diff --git a/arch/arm/boot/dts/imx28-tx28.dts b/arch/arm/boot/dts/imx28-tx28.dts
index 37be532..be5a055 100644
--- a/arch/arm/boot/dts/imx28-tx28.dts
+++ b/arch/arm/boot/dts/imx28-tx28.dts
@@ -1,106 +1,139 @@
+/*
+ * Copyright 2012 Shawn Guo <shawn.guo@linaro.org>
+ * Copyright 2013 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
 /dts-v1/;
-/include/ "imx28.dtsi"
+#include "imx28.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	model = "Ka-Ro electronics TX28 module";
 	compatible = "karo,tx28", "fsl,imx28";
 
+	aliases {
+		can0 = &can0;
+		can1 = &can1;
+		display = &display;
+		ds1339 = &ds1339;
+		gpio5 = &gpio5;
+		lcdif = &lcdif;
+		lcdif_23bit_pins = &tx28_lcdif_23bit_pins;
+		lcdif_24bit_pins = &lcdif_24bit_pins_a;
+		stk5led = &user_led;
+		usbotg = &usb0;
+	};
+
 	memory {
-		reg = <0x40000000 0x08000000>;
+		reg = <0 0>; /* will be filled in by U-Boot */
 	};
 
-	apb@80000000 {
-		apbh@80000000 {
-			ssp0: ssp@80010000 {
-				compatible = "fsl,imx28-mmc";
-				pinctrl-names = "default";
-				pinctrl-0 = <&mmc0_4bit_pins_a
-					     &mmc0_cd_cfg
-					     &mmc0_sck_cfg>;
-				bus-width = <4>;
-				status = "okay";
-			};
+	onewire {
+		compatible = "w1-gpio";
+		gpios = <&gpio2 7 0>;
+		status = "disabled";
+	};
 
-			pinctrl@80018000 {
-				pinctrl-names = "default";
-				pinctrl-0 = <&hog_pins_a>;
+	regulators {
+		compatible = "simple-bus";
 
-				hog_pins_a: hog@0 {
-					reg = <0>;
-					fsl,pinmux-ids = <
-						0x40a3 /* MX28_PAD_ENET0_RXD3__GPIO_4_10 */
-					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
-				};
-
-				mac0_pins_gpio: mac0-gpio-mode@0 {
-					reg = <0>;
-					fsl,pinmux-ids = <
-						0x4003 /* MX28_PAD_ENET0_MDC__GPIO_4_0 */
-						0x4013 /* MX28_PAD_ENET0_MDIO__GPIO_4_1 */
-						0x4023 /* MX28_PAD_ENET0_RX_EN__GPIO_4_2 */
-						0x4033 /* MX28_PAD_ENET0_RXD0__GPIO_4_3 */
-						0x4043 /* MX28_PAD_ENET0_RXD1__GPIO_4_4 */
-						0x4063 /* MX28_PAD_ENET0_TX_EN__GPIO_4_6 */
-						0x4073 /* MX28_PAD_ENET0_TXD0__GPIO_4_7 */
-						0x4083 /* MX28_PAD_ENET0_TXD1__GPIO_4_8 */
-						0x4103 /* MX28_PAD_ENET_CLK__GPIO_4_16 */
-					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
-				};
-			};
+		reg_usb0_vbus: usb0_vbus {
+			compatible = "regulator-fixed";
+			regulator-name = "usb0_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio0 18 0>;
+			enable-active-high;
 		};
 
-		apbx@80040000 {
-			i2c0: i2c@80058000 {
-				pinctrl-names = "default";
-				pinctrl-0 = <&i2c0_pins_a>;
-				status = "okay";
+		reg_usb1_vbus: usb1_vbus {
+			compatible = "regulator-fixed";
+			regulator-name = "usb1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 27 0>;
+			enable-active-high;
+		};
 
-				ds1339: rtc@68 {
-					compatible = "mxim,ds1339";
-					reg = <0x68>;
-				};
-			};
+		reg_2p5v: 2p5v {
+			compatible = "regulator-fixed";
+			regulator-name = "2P5V";
+			regulator-min-microvolt = <2500000>;
+			regulator-max-microvolt = <2500000>;
+			regulator-always-on;
+		};
 
-			pwm: pwm@80064000 {
-				pinctrl-names = "default";
-				pinctrl-0 = <&pwm0_pins_a>;
-				status = "okay";
-			};
+		reg_3p3v: 3p3v {
+			compatible = "regulator-fixed";
+			regulator-name = "3P3V";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
 
-			duart: serial@80074000 {
-				pinctrl-names = "default";
-				pinctrl-0 = <&duart_4pins_a>;
-				status = "okay";
-			};
+		reg_can_xcvr: can-xcvr {
+			compatible = "regulator-fixed";
+			regulator-name = "CAN XCVR";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio1 0 0>;
+			enable-active-low;
+			pinctrl-names = "default";
+			pinctrl-0 = <&tx28_flexcan_xcvr_pins>;
+		};
 
-			auart1: serial@8006c000 {
-				pinctrl-names = "default";
-				pinctrl-0 = <&auart1_pins_a>;
-				status = "okay";
-			};
+		reg_lcd: lcd-power {
+			compatible = "regulator-fixed";
+			regulator-name = "LCD POWER";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio1 31 0>;
+			enable-active-high;
+		};
+
+		reg_lcd_reset: lcd-reset {
+			compatible = "regulator-fixed";
+			regulator-name = "LCD RESET";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio3 30 0>;
+			startup-delay-us = <300000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
 		};
 	};
 
-	ahb@80080000 {
-		mac0: ethernet@800f0000 {
-			phy-mode = "rmii";
-			pinctrl-names = "default", "gpio_mode";
-			pinctrl-0 = <&mac0_pins_a>;
-			pinctrl-1 = <&mac0_pins_gpio>;
-			status = "okay";
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		mclk: clock@0 {
+			compatible = "fixed-clock";
+			reg = <0>;
+			#clock-cells = <0>;
+			clock-frequency = <27000000>;
 		};
 	};
 
+	sound {
+		compatible = "fsl,imx28-tx28-sgtl5000",
+			     "fsl,mxs-audio-sgtl5000";
+		model = "imx28-tx28-sgtl5000";
+		saif-controllers = <&saif0 &saif1>;
+		audio-codec = <&sgtl5000>;
+	};
+
 	leds {
 		compatible = "gpio-leds";
 
-		user {
+		user_led: user {
 			label = "Heartbeat";
 			gpios = <&gpio4 10 0>;
 			linux,default-trigger = "heartbeat";
@@ -109,8 +142,512 @@
 
 	backlight {
 		compatible = "pwm-backlight";
-		pwms = <&pwm 0 5000000>;
-		brightness-levels = <0 4 8 16 32 64 128 255>;
-		default-brightness-level = <6>;
+		pwms = <&pwm 0 500000>;
+		/*
+		 * a silly way to create a 1:1 relationship between the
+		 * PWM value and the actual duty cycle
+		 */
+		brightness-levels = < 0  1  2  3  4  5  6  7  8  9
+				     10 11 12 13 14 15 16 17 18 19
+				     20 21 22 23 24 25 26 27 28 29
+				     30 31 32 33 34 35 36 37 38 39
+				     40 41 42 43 44 45 46 47 48 49
+				     50 51 52 53 54 55 56 57 58 59
+				     60 61 62 63 64 65 66 67 68 69
+				     70 71 72 73 74 75 76 77 78 79
+				     80 81 82 83 84 85 86 87 88 89
+				     90 91 92 93 94 95 96 97 98 99
+				    100>;
+		default-brightness-level = <50>;
 	};
+
+	matrix_keypad: matrix-keypad@0 {
+		compatible = "gpio-matrix-keypad";
+		col-gpios = <
+			&gpio5 0 0
+			&gpio5 1 0
+			&gpio5 2 0
+			&gpio5 3 0
+		>;
+		row-gpios = <
+			&gpio5 4 0
+			&gpio5 5 0
+			&gpio5 6 0
+			&gpio5 7 0
+		>;
+		/* sample keymap */
+		linux,keymap = <
+			0x00000074 /* row 0, col 0, KEY_POWER */
+			0x00010052 /* row 0, col 1, KEY_KP0 */
+			0x0002004f /* row 0, col 2, KEY_KP1 */
+			0x00030050 /* row 0, col 3, KEY_KP2 */
+			0x01000051 /* row 1, col 0, KEY_KP3 */
+			0x0101004b /* row 1, col 1, KEY_KP4 */
+			0x0102004c /* row 1, col 2, KEY_KP5 */
+			0x0103004d /* row 1, col 3, KEY_KP6 */
+			0x02000047 /* row 2, col 0, KEY_KP7 */
+			0x02010048 /* row 2, col 1, KEY_KP8 */
+			0x02020049 /* row 2, col 2, KEY_KP9 */
+		>;
+		gpio-activelow;
+		linux,wakeup;
+		debounce-delay-ms = <100>;
+		col-scan-delay-us = <5000>;
+		linux,no-autorepeat;
+	};
+};
+
+/* 2nd TX-Std UART - (A)UART1  */
+&auart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&auart1_pins_a>;
+	status = "okay";
+};
+
+/* 3rd TX-Std UART - (A)UART3  */
+&auart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&auart3_pins_a>;
+	status = "okay";
+};
+
+&can0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&can0_pins_a>;
+	xceiver-supply = <&reg_can_xcvr>;
+	status = "okay";
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&can1_pins_a>;
+	xceiver-supply = <&reg_can_xcvr>;
+	status = "okay";
+};
+
+&digctl {
+	status = "okay";
+};
+
+/* 1st TX-Std UART - (D)UART */
+&duart {
+	pinctrl-names = "default";
+	pinctrl-0 = <&duart_4pins_a>;
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg>;
+	nand-on-flash-bbt;
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins_a>;
+	clock-frequency = <400000>;
+	status = "okay";
+
+	sgtl5000: sgtl5000@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		VDDA-supply = <&reg_2p5v>;
+		VDDIO-supply = <&reg_3p3v>;
+		clocks = <&mclk>;
+	};
+
+	gpio5: pca953x@20 {
+		compatible = "nxp,pca9554";
+		reg = <0x20>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&tx28_pca9554_pins>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <28 0>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	polytouch: edt-ft5x06@38 {
+		compatible = "edt,edt-ft5x06";
+		reg = <0x38>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&tx28_edt_ft5x06_pins>;
+		interrupt-parent = <&gpio2>;
+		interrupts = <5 0>;
+		reset-gpios = <&gpio2 6 1>;
+		wake-gpios = <&gpio4 9 0>;
+	};
+
+	touchscreen: tsc2007@48 {
+		compatible = "ti,tsc2007";
+		reg = <0x48>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&tx28_tsc2007_pins>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <20 0>;
+		pendown-gpio = <&gpio3 20 1>;
+		ti,x-plate-ohms = /bits/ 16 <660>;
+	};
+
+	ds1339: rtc@68 {
+		compatible = "mxim,ds1339";
+		reg = <0x68>;
+	};
+};
+
+&lcdif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&lcdif_24bit_pins_a &lcdif_sync_pins_a &tx28_lcdif_ctrl_pins>;
+	lcd-supply = <&reg_lcd>;
+	display = <&display>;
+	status = "okay";
+
+	display: display@0 {
+		bits-per-pixel = <32>;
+		bus-width = <24>;
+		display-timings {
+			native-mode = <&timing5>;
+			timing0: timing0 {
+				panel-name = "VGA";
+				clock-frequency = <25175000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <48>;
+				hsync-len = <96>;
+				hfront-porch = <16>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			timing1: timing1 {
+				panel-name = "ETV570";
+				clock-frequency = <25175000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <114>;
+				hsync-len = <30>;
+				hfront-porch = <16>;
+				vback-porch = <32>;
+				vsync-len = <3>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			timing2: timing2 {
+				panel-name = "ET0350";
+				clock-frequency = <6500000>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <34>;
+				hsync-len = <34>;
+				hfront-porch = <20>;
+				vback-porch = <15>;
+				vsync-len = <3>;
+				vfront-porch = <4>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			timing3: timing3 {
+				panel-name = "ET0430";
+				clock-frequency = <9000000>;
+				hactive = <480>;
+				vactive = <272>;
+				hback-porch = <2>;
+				hsync-len = <41>;
+				hfront-porch = <2>;
+				vback-porch = <2>;
+				vsync-len = <10>;
+				vfront-porch = <2>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			timing4: timing4 {
+				panel-name = "ET0500", "ET0700";
+				clock-frequency = <33260000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			timing5: timing5 {
+				panel-name = "ETQ570";
+				clock-frequency = <6400000>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <38>;
+				hsync-len = <30>;
+				hfront-porch = <30>;
+				vback-porch = <16>;
+				vsync-len = <3>;
+				vfront-porch = <4>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+		};
+	};
+};
+
+&lradc {
+	fsl,lradc-touchscreen-wires = <4>;
+	status = "okay";
+};
+
+&mac0 {
+	phy-mode = "rmii";
+	pinctrl-names = "default", "gpio_mode";
+	pinctrl-0 = <&mac0_pins_a>;
+	pinctrl-1 = <&tx28_mac0_pins_gpio>;
+	status = "okay";
+};
+
+&mac1 {
+	phy-mode = "rmii";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mac1_pins_a>;
+	/* not enabled by default */
+};
+
+&mxs_rtc {
+	status = "okay";
+};
+
+&ocotp {
+	status = "okay";
+};
+
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm0_pins_a>;
+	status = "okay";
+};
+
+&pinctrl {
+	pinctrl-names = "default";
+	pinctrl-0 = <&hog_pins_a>;
+
+	hog_pins_a: hog@0 {
+		reg = <0>;
+		fsl,pinmux-ids = <
+			MX28_PAD_ENET0_RXD3__GPIO_4_10 /* module LED */
+		>;
+		fsl,drive-strength = <MXS_DRIVE_4mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
+	};
+
+	tx28_edt_ft5x06_pins: tx28-edt-ft5x06-pins {
+		fsl,pinmux-ids = <
+			MX28_PAD_SSP0_DATA6__GPIO_2_6 /* RESET */
+			MX28_PAD_SSP0_DATA5__GPIO_2_5 /* IRQ */
+			MX28_PAD_ENET0_RXD2__GPIO_4_9 /* WAKE */
+		>;
+		fsl,drive-strength = <MXS_DRIVE_4mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
+	};
+
+	tx28_flexcan_xcvr_pins: tx28-flexcan-xcvr-pins {
+		fsl,pinmux-ids = <
+			MX28_PAD_LCD_D00__GPIO_1_0
+		>;
+		fsl,drive-strength = <MXS_DRIVE_4mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
+	};
+
+	tx28_lcdif_23bit_pins: tx28-lcdif-23bit {
+		fsl,pinmux-ids = <
+			/* LCD_D00 may be used as Flexcan Transceiver Enable on STK5-V5 */
+			MX28_PAD_LCD_D01__LCD_D1
+			MX28_PAD_LCD_D02__LCD_D2
+			MX28_PAD_LCD_D03__LCD_D3
+			MX28_PAD_LCD_D04__LCD_D4
+			MX28_PAD_LCD_D05__LCD_D5
+			MX28_PAD_LCD_D06__LCD_D6
+			MX28_PAD_LCD_D07__LCD_D7
+			MX28_PAD_LCD_D08__LCD_D8
+			MX28_PAD_LCD_D09__LCD_D9
+			MX28_PAD_LCD_D10__LCD_D10
+			MX28_PAD_LCD_D11__LCD_D11
+			MX28_PAD_LCD_D12__LCD_D12
+			MX28_PAD_LCD_D13__LCD_D13
+			MX28_PAD_LCD_D14__LCD_D14
+			MX28_PAD_LCD_D15__LCD_D15
+			MX28_PAD_LCD_D16__LCD_D16
+			MX28_PAD_LCD_D17__LCD_D17
+			MX28_PAD_LCD_D18__LCD_D18
+			MX28_PAD_LCD_D19__LCD_D19
+			MX28_PAD_LCD_D20__LCD_D20
+			MX28_PAD_LCD_D21__LCD_D21
+			MX28_PAD_LCD_D22__LCD_D22
+			MX28_PAD_LCD_D23__LCD_D23
+		>;
+		fsl,drive-strength = <MXS_DRIVE_4mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
+	};
+
+	tx28_lcdif_ctrl_pins: tx28-lcdif-ctrl {
+		fsl,pinmux-ids = <
+			MX28_PAD_LCD_ENABLE__GPIO_1_31 /* Enable */
+			MX28_PAD_LCD_RESET__GPIO_3_30  /* Reset */
+		>;
+		fsl,drive-strength = <MXS_DRIVE_4mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
+	};
+
+	tx28_mac0_pins_gpio: tx28-mac0-gpio-pins {
+		fsl,pinmux-ids = <
+			MX28_PAD_ENET0_MDC__GPIO_4_0
+			MX28_PAD_ENET0_MDIO__GPIO_4_1
+			MX28_PAD_ENET0_RX_EN__GPIO_4_2
+			MX28_PAD_ENET0_RXD0__GPIO_4_3
+			MX28_PAD_ENET0_RXD1__GPIO_4_4
+			MX28_PAD_ENET0_TX_EN__GPIO_4_6
+			MX28_PAD_ENET0_TXD0__GPIO_4_7
+			MX28_PAD_ENET0_TXD1__GPIO_4_8
+			MX28_PAD_ENET_CLK__GPIO_4_16
+		>;
+		fsl,drive-strength = <MXS_DRIVE_4mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
+	};
+
+	tx28_pca9554_pins: tx28-pca9554-pins {
+		fsl,pinmux-ids = <
+			MX28_PAD_PWM3__GPIO_3_28
+		>;
+		fsl,drive-strength = <MXS_DRIVE_4mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
+	};
+
+	tx28_tsc2007_pins: tx28-tsc2007-pins {
+		fsl,pinmux-ids = <
+			MX28_PAD_SAIF0_MCLK__GPIO_3_20 /* TSC2007 IRQ */
+		>;
+		fsl,drive-strength = <MXS_DRIVE_4mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
+	};
+
+
+	tx28_usbphy0_pins: tx28-usbphy0-pins {
+		fsl,pinmux-ids = <
+			MX28_PAD_GPMI_CE2N__GPIO_0_18 /* USBOTG_VBUSEN */
+			MX28_PAD_GPMI_CE3N__GPIO_0_19 /* USBOTH_OC */
+		>;
+		fsl,drive-strength = <MXS_DRIVE_12mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
+	};
+
+	tx28_usbphy1_pins: tx28-usbphy1-pins {
+		fsl,pinmux-ids = <
+			MX28_PAD_SPDIF__GPIO_3_27 /* USBH_VBUSEN */
+			MX28_PAD_JTAG_RTCK__GPIO_4_20 /* USBH_OC */
+		>;
+		fsl,drive-strength = <MXS_DRIVE_12mA>;
+		fsl,voltage = <MXS_VOLTAGE_HIGH>;
+		fsl,pull-up = <MXS_PULL_DISABLE>;
+	};
+};
+
+&saif0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&saif0_pins_b>;
+	fsl,saif-master;
+	status = "okay";
+};
+
+&saif1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&saif1_pins_a>;
+	status = "okay";
+};
+
+&ssp0 {
+	compatible = "fsl,imx28-mmc";
+	pinctrl-names = "default", "special";
+	pinctrl-0 = <&mmc0_4bit_pins_a
+		     &mmc0_cd_cfg
+		     &mmc0_sck_cfg>;
+	bus-width = <4>;
+	status = "okay";
+};
+
+&ssp3 {
+	compatible = "fsl,imx28-spi";
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi3_pins_a>;
+	clock-frequency = <57600000>;
+	status = "okay";
+
+	spidev0: spi@0 {
+		compatible = "spidev";
+		reg = <0>;
+		spi-max-frequency = <57600000>;
+	};
+
+	spidev1: spi@1 {
+		compatible = "spidev";
+		reg = <1>;
+		spi-max-frequency = <57600000>;
+	};
+};
+
+&usb0 {
+	vbus-supply = <&reg_usb0_vbus>;
+	disable-over-current;
+	dr_mode = "peripheral";
+	status = "okay";
+};
+
+&usb1 {
+	vbus-supply = <&reg_usb1_vbus>;
+	disable-over-current;
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usbphy0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&tx28_usbphy0_pins>;
+	phy_type = "utmi";
+	status = "okay";
+};
+
+&usbphy1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&tx28_usbphy1_pins>;
+	phy_type = "utmi";
+	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index 7363fde..cda19c8 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -9,7 +9,8 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-/include/ "skeleton.dtsi"
+#include "skeleton.dtsi"
+#include "imx28-pinfunc.h"
 
 / {
 	interrupt-parent = <&icoll>;
@@ -207,538 +208,579 @@
 				duart_pins_a: duart@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x3102 /* MX28_PAD_PWM0__DUART_RX */
-						0x3112 /* MX28_PAD_PWM1__DUART_TX */
+						MX28_PAD_PWM0__DUART_RX
+						MX28_PAD_PWM1__DUART_TX
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				duart_pins_b: duart@1 {
 					reg = <1>;
 					fsl,pinmux-ids = <
-						0x3022 /* MX28_PAD_AUART0_CTS__DUART_RX */
-						0x3032 /* MX28_PAD_AUART0_RTS__DUART_TX */
+						MX28_PAD_AUART0_CTS__DUART_RX
+						MX28_PAD_AUART0_RTS__DUART_TX
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				duart_4pins_a: duart-4pins@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x3022 /* MX28_PAD_AUART0_CTS__DUART_RX */
-						0x3032 /* MX28_PAD_AUART0_RTS__DUART_TX */
-						0x3002 /* MX28_PAD_AUART0_RX__DUART_CTS */
-						0x3012 /* MX28_PAD_AUART0_TX__DUART_RTS */
+						MX28_PAD_AUART0_CTS__DUART_RX
+						MX28_PAD_AUART0_RTS__DUART_TX
+						MX28_PAD_AUART0_RX__DUART_CTS
+						MX28_PAD_AUART0_TX__DUART_RTS
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				gpmi_pins_a: gpmi-nand@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x0000 /* MX28_PAD_GPMI_D00__GPMI_D0 */
-						0x0010 /* MX28_PAD_GPMI_D01__GPMI_D1 */
-						0x0020 /* MX28_PAD_GPMI_D02__GPMI_D2 */
-						0x0030 /* MX28_PAD_GPMI_D03__GPMI_D3 */
-						0x0040 /* MX28_PAD_GPMI_D04__GPMI_D4 */
-						0x0050 /* MX28_PAD_GPMI_D05__GPMI_D5 */
-						0x0060 /* MX28_PAD_GPMI_D06__GPMI_D6 */
-						0x0070 /* MX28_PAD_GPMI_D07__GPMI_D7 */
-						0x0100 /* MX28_PAD_GPMI_CE0N__GPMI_CE0N */
-						0x0140 /* MX28_PAD_GPMI_RDY0__GPMI_READY0 */
-						0x0180 /* MX28_PAD_GPMI_RDN__GPMI_RDN */
-						0x0190 /* MX28_PAD_GPMI_WRN__GPMI_WRN */
-						0x01a0 /* MX28_PAD_GPMI_ALE__GPMI_ALE */
-						0x01b0 /* MX28_PAD_GPMI_CLE__GPMI_CLE */
-						0x01c0 /* MX28_PAD_GPMI_RESETN__GPMI_RESETN */
+						MX28_PAD_GPMI_D00__GPMI_D0
+						MX28_PAD_GPMI_D01__GPMI_D1
+						MX28_PAD_GPMI_D02__GPMI_D2
+						MX28_PAD_GPMI_D03__GPMI_D3
+						MX28_PAD_GPMI_D04__GPMI_D4
+						MX28_PAD_GPMI_D05__GPMI_D5
+						MX28_PAD_GPMI_D06__GPMI_D6
+						MX28_PAD_GPMI_D07__GPMI_D7
+						MX28_PAD_GPMI_CE0N__GPMI_CE0N
+						MX28_PAD_GPMI_RDY0__GPMI_READY0
+						MX28_PAD_GPMI_RDN__GPMI_RDN
+						MX28_PAD_GPMI_WRN__GPMI_WRN
+						MX28_PAD_GPMI_ALE__GPMI_ALE
+						MX28_PAD_GPMI_CLE__GPMI_CLE
+						MX28_PAD_GPMI_RESETN__GPMI_RESETN
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				gpmi_status_cfg: gpmi-status-cfg {
 					fsl,pinmux-ids = <
-						0x0180 /* MX28_PAD_GPMI_RDN__GPMI_RDN */
-						0x0190 /* MX28_PAD_GPMI_WRN__GPMI_WRN */
-						0x01c0 /* MX28_PAD_GPMI_RESETN__GPMI_RESETN */
+						MX28_PAD_GPMI_RDN__GPMI_RDN
+						MX28_PAD_GPMI_WRN__GPMI_WRN
+						MX28_PAD_GPMI_RESETN__GPMI_RESETN
 					>;
-					fsl,drive-strength = <2>;
+					fsl,drive-strength = <MXS_DRIVE_12mA>;
 				};
 
 				auart0_pins_a: auart0@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x3000 /* MX28_PAD_AUART0_RX__AUART0_RX */
-						0x3010 /* MX28_PAD_AUART0_TX__AUART0_TX */
-						0x3020 /* MX28_PAD_AUART0_CTS__AUART0_CTS */
-						0x3030 /* MX28_PAD_AUART0_RTS__AUART0_RTS */
+						MX28_PAD_AUART0_RX__AUART0_RX
+						MX28_PAD_AUART0_TX__AUART0_TX
+						MX28_PAD_AUART0_CTS__AUART0_CTS
+						MX28_PAD_AUART0_RTS__AUART0_RTS
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				auart0_2pins_a: auart0-2pins@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x3000 /* MX28_PAD_AUART0_RX__AUART0_RX */
-						0x3010 /* MX28_PAD_AUART0_TX__AUART0_TX */
+						MX28_PAD_AUART0_RX__AUART0_RX
+						MX28_PAD_AUART0_TX__AUART0_TX
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				auart1_pins_a: auart1@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x3040 /* MX28_PAD_AUART1_RX__AUART1_RX */
-						0x3050 /* MX28_PAD_AUART1_TX__AUART1_TX */
-						0x3060 /* MX28_PAD_AUART1_CTS__AUART1_CTS */
-						0x3070 /* MX28_PAD_AUART1_RTS__AUART1_RTS */
+						MX28_PAD_AUART1_RX__AUART1_RX
+						MX28_PAD_AUART1_TX__AUART1_TX
+						MX28_PAD_AUART1_CTS__AUART1_CTS
+						MX28_PAD_AUART1_RTS__AUART1_RTS
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				auart1_2pins_a: auart1-2pins@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x3040 /* MX28_PAD_AUART1_RX__AUART1_RX */
-						0x3050 /* MX28_PAD_AUART1_TX__AUART1_TX */
+						MX28_PAD_AUART1_RX__AUART1_RX
+						MX28_PAD_AUART1_TX__AUART1_TX
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				auart2_2pins_a: auart2-2pins@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x2101 /* MX28_PAD_SSP2_SCK__AUART2_RX */
-						0x2111 /* MX28_PAD_SSP2_MOSI__AUART2_TX */
+						MX28_PAD_SSP2_SCK__AUART2_RX
+						MX28_PAD_SSP2_MOSI__AUART2_TX
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				auart2_2pins_b: auart2-2pins@1 {
 					reg = <1>;
 					fsl,pinmux-ids = <
-						0x3080 /* MX28_PAD_AUART2_RX__AUART2_RX */
-						0x3090 /* MX28_PAD_AUART2_TX__AUART2_TX */
+						MX28_PAD_AUART2_RX__AUART2_RX
+						MX28_PAD_AUART2_TX__AUART2_TX
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				auart3_pins_a: auart3@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x30c0 /* MX28_PAD_AUART3_RX__AUART3_RX */
-						0x30d0 /* MX28_PAD_AUART3_TX__AUART3_TX */
-						0x30e0 /* MX28_PAD_AUART3_CTS__AUART3_CTS */
-						0x30f0 /* MX28_PAD_AUART3_RTS__AUART3_RTS */
+						MX28_PAD_AUART3_RX__AUART3_RX
+						MX28_PAD_AUART3_TX__AUART3_TX
+						MX28_PAD_AUART3_CTS__AUART3_CTS
+						MX28_PAD_AUART3_RTS__AUART3_RTS
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				auart3_2pins_a: auart3-2pins@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x2121 /* MX28_PAD_SSP2_MISO__AUART3_RX */
-						0x2131 /* MX28_PAD_SSP2_SS0__AUART3_TX */
+						MX28_PAD_SSP2_MISO__AUART3_RX
+						MX28_PAD_SSP2_SS0__AUART3_TX
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				auart3_2pins_b: auart3-2pins@1 {
 					reg = <1>;
 					fsl,pinmux-ids = <
-						0x30c0 /* MX28_PAD_AUART3_RX__AUART3_RX */
-						0x30d0 /* MX28_PAD_AUART3_TX__AUART3_TX */
+						MX28_PAD_AUART3_RX__AUART3_RX
+						MX28_PAD_AUART3_TX__AUART3_TX
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				auart4_2pins_a: auart4@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x2181 /* MX28_PAD_SSP3_SCK__AUART4_TX */
-						0x2191 /* MX28_PAD_SSP3_MOSI__AUART4_RX */
+						MX28_PAD_SSP3_SCK__AUART4_TX
+						MX28_PAD_SSP3_MOSI__AUART4_RX
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				mac0_pins_a: mac0@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x4000 /* MX28_PAD_ENET0_MDC__ENET0_MDC */
-						0x4010 /* MX28_PAD_ENET0_MDIO__ENET0_MDIO */
-						0x4020 /* MX28_PAD_ENET0_RX_EN__ENET0_RX_EN */
-						0x4030 /* MX28_PAD_ENET0_RXD0__ENET0_RXD0 */
-						0x4040 /* MX28_PAD_ENET0_RXD1__ENET0_RXD1 */
-						0x4060 /* MX28_PAD_ENET0_TX_EN__ENET0_TX_EN */
-						0x4070 /* MX28_PAD_ENET0_TXD0__ENET0_TXD0 */
-						0x4080 /* MX28_PAD_ENET0_TXD1__ENET0_TXD1 */
-						0x4100 /* MX28_PAD_ENET_CLK__CLKCTRL_ENET */
+						MX28_PAD_ENET0_MDC__ENET0_MDC
+						MX28_PAD_ENET0_MDIO__ENET0_MDIO
+						MX28_PAD_ENET0_RX_EN__ENET0_RX_EN
+						MX28_PAD_ENET0_RXD0__ENET0_RXD0
+						MX28_PAD_ENET0_RXD1__ENET0_RXD1
+						MX28_PAD_ENET0_TX_EN__ENET0_TX_EN
+						MX28_PAD_ENET0_TXD0__ENET0_TXD0
+						MX28_PAD_ENET0_TXD1__ENET0_TXD1
+						MX28_PAD_ENET_CLK__CLKCTRL_ENET
 					>;
-					fsl,drive-strength = <1>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				mac1_pins_a: mac1@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x40f1 /* MX28_PAD_ENET0_CRS__ENET1_RX_EN */
-						0x4091 /* MX28_PAD_ENET0_RXD2__ENET1_RXD0 */
-						0x40a1 /* MX28_PAD_ENET0_RXD3__ENET1_RXD1 */
-						0x40e1 /* MX28_PAD_ENET0_COL__ENET1_TX_EN */
-						0x40b1 /* MX28_PAD_ENET0_TXD2__ENET1_TXD0 */
-						0x40c1 /* MX28_PAD_ENET0_TXD3__ENET1_TXD1 */
+						MX28_PAD_ENET0_CRS__ENET1_RX_EN
+						MX28_PAD_ENET0_RXD2__ENET1_RXD0
+						MX28_PAD_ENET0_RXD3__ENET1_RXD1
+						MX28_PAD_ENET0_COL__ENET1_TX_EN
+						MX28_PAD_ENET0_TXD2__ENET1_TXD0
+						MX28_PAD_ENET0_TXD3__ENET1_TXD1
 					>;
-					fsl,drive-strength = <1>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				mmc0_8bit_pins_a: mmc0-8bit@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x2000 /* MX28_PAD_SSP0_DATA0__SSP0_D0 */
-						0x2010 /* MX28_PAD_SSP0_DATA1__SSP0_D1 */
-						0x2020 /* MX28_PAD_SSP0_DATA2__SSP0_D2 */
-						0x2030 /* MX28_PAD_SSP0_DATA3__SSP0_D3 */
-						0x2040 /* MX28_PAD_SSP0_DATA4__SSP0_D4 */
-						0x2050 /* MX28_PAD_SSP0_DATA5__SSP0_D5 */
-						0x2060 /* MX28_PAD_SSP0_DATA6__SSP0_D6 */
-						0x2070 /* MX28_PAD_SSP0_DATA7__SSP0_D7 */
-						0x2080 /* MX28_PAD_SSP0_CMD__SSP0_CMD */
-						0x2090 /* MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT */
-						0x20a0 /* MX28_PAD_SSP0_SCK__SSP0_SCK */
+						MX28_PAD_SSP0_DATA0__SSP0_D0
+						MX28_PAD_SSP0_DATA1__SSP0_D1
+						MX28_PAD_SSP0_DATA2__SSP0_D2
+						MX28_PAD_SSP0_DATA3__SSP0_D3
+						MX28_PAD_SSP0_DATA4__SSP0_D4
+						MX28_PAD_SSP0_DATA5__SSP0_D5
+						MX28_PAD_SSP0_DATA6__SSP0_D6
+						MX28_PAD_SSP0_DATA7__SSP0_D7
+						MX28_PAD_SSP0_CMD__SSP0_CMD
+						MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT
+						MX28_PAD_SSP0_SCK__SSP0_SCK
 					>;
-					fsl,drive-strength = <1>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				mmc0_4bit_pins_a: mmc0-4bit@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x2000 /* MX28_PAD_SSP0_DATA0__SSP0_D0 */
-						0x2010 /* MX28_PAD_SSP0_DATA1__SSP0_D1 */
-						0x2020 /* MX28_PAD_SSP0_DATA2__SSP0_D2 */
-						0x2030 /* MX28_PAD_SSP0_DATA3__SSP0_D3 */
-						0x2080 /* MX28_PAD_SSP0_CMD__SSP0_CMD */
-						0x2090 /* MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT */
-						0x20a0 /* MX28_PAD_SSP0_SCK__SSP0_SCK */
+						MX28_PAD_SSP0_DATA0__SSP0_D0
+						MX28_PAD_SSP0_DATA1__SSP0_D1
+						MX28_PAD_SSP0_DATA2__SSP0_D2
+						MX28_PAD_SSP0_DATA3__SSP0_D3
+						MX28_PAD_SSP0_CMD__SSP0_CMD
+						MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT
+						MX28_PAD_SSP0_SCK__SSP0_SCK
 					>;
-					fsl,drive-strength = <1>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				mmc0_cd_cfg: mmc0-cd-cfg {
 					fsl,pinmux-ids = <
-						0x2090 /* MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT */
+						MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT
 					>;
-					fsl,pull-up = <0>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				mmc0_sck_cfg: mmc0-sck-cfg {
 					fsl,pinmux-ids = <
-						0x20a0 /* MX28_PAD_SSP0_SCK__SSP0_SCK */
+						MX28_PAD_SSP0_SCK__SSP0_SCK
 					>;
-					fsl,drive-strength = <2>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_12mA>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
+				};
+
+				mmc2_4bit_pins_a: mmc2-4bit@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX28_PAD_SSP0_DATA4__SSP2_D0
+						MX28_PAD_SSP1_SCK__SSP2_D1
+						MX28_PAD_SSP1_CMD__SSP2_D2
+						MX28_PAD_SSP0_DATA5__SSP2_D3
+						MX28_PAD_SSP0_DATA6__SSP2_CMD
+						MX28_PAD_AUART1_RX__SSP2_CARD_DETECT
+						MX28_PAD_SSP0_DATA7__SSP2_SCK
+					>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
+				};
+
+				mmc2_cd_cfg: mmc2-cd-cfg {
+					fsl,pinmux-ids = <
+						MX28_PAD_AUART1_RX__SSP2_CARD_DETECT
+					>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
+				};
+
+				mmc2_sck_cfg: mmc2-sck-cfg {
+					fsl,pinmux-ids = <
+						MX28_PAD_SSP0_DATA7__SSP2_SCK
+					>;
+					fsl,drive-strength = <MXS_DRIVE_12mA>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				i2c0_pins_a: i2c0@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x3180 /* MX28_PAD_I2C0_SCL__I2C0_SCL */
-						0x3190 /* MX28_PAD_I2C0_SDA__I2C0_SDA */
+						MX28_PAD_I2C0_SCL__I2C0_SCL
+						MX28_PAD_I2C0_SDA__I2C0_SDA
 					>;
-					fsl,drive-strength = <1>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				i2c0_pins_b: i2c0@1 {
 					reg = <1>;
 					fsl,pinmux-ids = <
-						0x3001 /* MX28_PAD_AUART0_RX__I2C0_SCL */
-						0x3011 /* MX28_PAD_AUART0_TX__I2C0_SDA */
+						MX28_PAD_AUART0_RX__I2C0_SCL
+						MX28_PAD_AUART0_TX__I2C0_SDA
 					>;
-					fsl,drive-strength = <1>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				i2c1_pins_a: i2c1@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x3101 /* MX28_PAD_PWM0__I2C1_SCL */
-						0x3111 /* MX28_PAD_PWM1__I2C1_SDA */
+						MX28_PAD_PWM0__I2C1_SCL
+						MX28_PAD_PWM1__I2C1_SDA
 					>;
-					fsl,drive-strength = <1>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				saif0_pins_a: saif0@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x3140 /* MX28_PAD_SAIF0_MCLK__SAIF0_MCLK */
-						0x3150 /* MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK */
-						0x3160 /* MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK */
-						0x3170 /* MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0 */
+						MX28_PAD_SAIF0_MCLK__SAIF0_MCLK
+						MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK
+						MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK
+						MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0
 					>;
-					fsl,drive-strength = <2>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_12mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				saif0_pins_b: saif0@1 {
 					reg = <1>;
 					fsl,pinmux-ids = <
-						0x3150 /* MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK */
-						0x3160 /* MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK */
-						0x3170 /* MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0 */
+						MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK
+						MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK
+						MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0
 					>;
-					fsl,drive-strength = <2>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_12mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				saif1_pins_a: saif1@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x31a0 /* MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0 */
+						MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0
 					>;
-					fsl,drive-strength = <2>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_12mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				pwm0_pins_a: pwm0@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x3100 /* MX28_PAD_PWM0__PWM_0 */
+						MX28_PAD_PWM0__PWM_0
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				pwm2_pins_a: pwm2@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x3120 /* MX28_PAD_PWM2__PWM_2 */
+						MX28_PAD_PWM2__PWM_2
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				pwm3_pins_a: pwm3@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x31c0 /* MX28_PAD_PWM3__PWM_3 */
+						MX28_PAD_PWM3__PWM_3
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				pwm3_pins_b: pwm3@1 {
 					reg = <1>;
 					fsl,pinmux-ids = <
-						0x3141 /* MX28_PAD_SAIF0_MCLK__PWM3 */
+						MX28_PAD_SAIF0_MCLK__PWM_3
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				pwm4_pins_a: pwm4@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x31d0 /* MX28_PAD_PWM4__PWM_4 */
+						MX28_PAD_PWM4__PWM_4
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				lcdif_24bit_pins_a: lcdif-24bit@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x1000 /* MX28_PAD_LCD_D00__LCD_D0 */
-						0x1010 /* MX28_PAD_LCD_D01__LCD_D1 */
-						0x1020 /* MX28_PAD_LCD_D02__LCD_D2 */
-						0x1030 /* MX28_PAD_LCD_D03__LCD_D3 */
-						0x1040 /* MX28_PAD_LCD_D04__LCD_D4 */
-						0x1050 /* MX28_PAD_LCD_D05__LCD_D5 */
-						0x1060 /* MX28_PAD_LCD_D06__LCD_D6 */
-						0x1070 /* MX28_PAD_LCD_D07__LCD_D7 */
-						0x1080 /* MX28_PAD_LCD_D08__LCD_D8 */
-						0x1090 /* MX28_PAD_LCD_D09__LCD_D9 */
-						0x10a0 /* MX28_PAD_LCD_D10__LCD_D10 */
-						0x10b0 /* MX28_PAD_LCD_D11__LCD_D11 */
-						0x10c0 /* MX28_PAD_LCD_D12__LCD_D12 */
-						0x10d0 /* MX28_PAD_LCD_D13__LCD_D13 */
-						0x10e0 /* MX28_PAD_LCD_D14__LCD_D14 */
-						0x10f0 /* MX28_PAD_LCD_D15__LCD_D15 */
-						0x1100 /* MX28_PAD_LCD_D16__LCD_D16 */
-						0x1110 /* MX28_PAD_LCD_D17__LCD_D17 */
-						0x1120 /* MX28_PAD_LCD_D18__LCD_D18 */
-						0x1130 /* MX28_PAD_LCD_D19__LCD_D19 */
-						0x1140 /* MX28_PAD_LCD_D20__LCD_D20 */
-						0x1150 /* MX28_PAD_LCD_D21__LCD_D21 */
-						0x1160 /* MX28_PAD_LCD_D22__LCD_D22 */
-						0x1170 /* MX28_PAD_LCD_D23__LCD_D23 */
+						MX28_PAD_LCD_D00__LCD_D0
+						MX28_PAD_LCD_D01__LCD_D1
+						MX28_PAD_LCD_D02__LCD_D2
+						MX28_PAD_LCD_D03__LCD_D3
+						MX28_PAD_LCD_D04__LCD_D4
+						MX28_PAD_LCD_D05__LCD_D5
+						MX28_PAD_LCD_D06__LCD_D6
+						MX28_PAD_LCD_D07__LCD_D7
+						MX28_PAD_LCD_D08__LCD_D8
+						MX28_PAD_LCD_D09__LCD_D9
+						MX28_PAD_LCD_D10__LCD_D10
+						MX28_PAD_LCD_D11__LCD_D11
+						MX28_PAD_LCD_D12__LCD_D12
+						MX28_PAD_LCD_D13__LCD_D13
+						MX28_PAD_LCD_D14__LCD_D14
+						MX28_PAD_LCD_D15__LCD_D15
+						MX28_PAD_LCD_D16__LCD_D16
+						MX28_PAD_LCD_D17__LCD_D17
+						MX28_PAD_LCD_D18__LCD_D18
+						MX28_PAD_LCD_D19__LCD_D19
+						MX28_PAD_LCD_D20__LCD_D20
+						MX28_PAD_LCD_D21__LCD_D21
+						MX28_PAD_LCD_D22__LCD_D22
+						MX28_PAD_LCD_D23__LCD_D23
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				lcdif_16bit_pins_a: lcdif-16bit@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x1000 /* MX28_PAD_LCD_D00__LCD_D0 */
-						0x1010 /* MX28_PAD_LCD_D01__LCD_D1 */
-						0x1020 /* MX28_PAD_LCD_D02__LCD_D2 */
-						0x1030 /* MX28_PAD_LCD_D03__LCD_D3 */
-						0x1040 /* MX28_PAD_LCD_D04__LCD_D4 */
-						0x1050 /* MX28_PAD_LCD_D05__LCD_D5 */
-						0x1060 /* MX28_PAD_LCD_D06__LCD_D6 */
-						0x1070 /* MX28_PAD_LCD_D07__LCD_D7 */
-						0x1080 /* MX28_PAD_LCD_D08__LCD_D8 */
-						0x1090 /* MX28_PAD_LCD_D09__LCD_D9 */
-						0x10a0 /* MX28_PAD_LCD_D10__LCD_D10 */
-						0x10b0 /* MX28_PAD_LCD_D11__LCD_D11 */
-						0x10c0 /* MX28_PAD_LCD_D12__LCD_D12 */
-						0x10d0 /* MX28_PAD_LCD_D13__LCD_D13 */
-						0x10e0 /* MX28_PAD_LCD_D14__LCD_D14 */
-						0x10f0 /* MX28_PAD_LCD_D15__LCD_D15 */
+						MX28_PAD_LCD_D00__LCD_D0
+						MX28_PAD_LCD_D01__LCD_D1
+						MX28_PAD_LCD_D02__LCD_D2
+						MX28_PAD_LCD_D03__LCD_D3
+						MX28_PAD_LCD_D04__LCD_D4
+						MX28_PAD_LCD_D05__LCD_D5
+						MX28_PAD_LCD_D06__LCD_D6
+						MX28_PAD_LCD_D07__LCD_D7
+						MX28_PAD_LCD_D08__LCD_D8
+						MX28_PAD_LCD_D09__LCD_D9
+						MX28_PAD_LCD_D10__LCD_D10
+						MX28_PAD_LCD_D11__LCD_D11
+						MX28_PAD_LCD_D12__LCD_D12
+						MX28_PAD_LCD_D13__LCD_D13
+						MX28_PAD_LCD_D14__LCD_D14
+						MX28_PAD_LCD_D15__LCD_D15
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				lcdif_sync_pins_a: lcdif-sync@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
-						0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
-						0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
-						0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
+						MX28_PAD_LCD_RS__LCD_DOTCLK
+						MX28_PAD_LCD_CS__LCD_ENABLE
+						MX28_PAD_LCD_RD_E__LCD_VSYNC
+						MX28_PAD_LCD_WR_RWN__LCD_HSYNC
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				can0_pins_a: can0@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x0161 /* MX28_PAD_GPMI_RDY2__CAN0_TX */
-						0x0171 /* MX28_PAD_GPMI_RDY3__CAN0_RX */
+						MX28_PAD_GPMI_RDY2__CAN0_TX
+						MX28_PAD_GPMI_RDY3__CAN0_RX
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				can1_pins_a: can1@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x0121 /* MX28_PAD_GPMI_CE2N__CAN1_TX */
-						0x0131 /* MX28_PAD_GPMI_CE3N__CAN1_RX */
+						MX28_PAD_GPMI_CE2N__CAN1_TX
+						MX28_PAD_GPMI_CE3N__CAN1_RX
 					>;
-					fsl,drive-strength = <0>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_4mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				spi2_pins_a: spi2@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x2100 /* MX28_PAD_SSP2_SCK__SSP2_SCK */
-						0x2110 /* MX28_PAD_SSP2_MOSI__SSP2_CMD */
-						0x2120 /* MX28_PAD_SSP2_MISO__SSP2_D0 */
-						0x2130 /* MX28_PAD_SSP2_SS0__SSP2_D3 */
+						MX28_PAD_SSP2_SCK__SSP2_SCK
+						MX28_PAD_SSP2_MOSI__SSP2_CMD
+						MX28_PAD_SSP2_MISO__SSP2_D0
+						MX28_PAD_SSP2_SS0__SSP2_D3
 					>;
-					fsl,drive-strength = <1>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <1>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
 				spi3_pins_a: spi3@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x3082 /* MX28_PAD_AUART2_RX__SSP3_D4 */
-						0x3092 /* MX28_PAD_AUART2_TX__SSP3_D5 */
-						0x2180 /* MX28_PAD_SSP3_SCK__SSP3_SCK */
-						0x2190 /* MX28_PAD_SSP3_MOSI__SSP3_CMD */
-						0x21A0 /* MX28_PAD_SSP3_MISO__SSP3_D0 */
-						0x21B0 /* MX28_PAD_SSP3_SS0__SSP3_D3 */
+						MX28_PAD_AUART2_RX__SSP3_D4
+						MX28_PAD_AUART2_TX__SSP3_D5
+						MX28_PAD_SSP3_SCK__SSP3_SCK
+						MX28_PAD_SSP3_MOSI__SSP3_CMD
+						MX28_PAD_SSP3_MISO__SSP3_D0
+						MX28_PAD_SSP3_SS0__SSP3_D3
 					>;
-					fsl,drive-strength = <1>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				usbphy0_pins_a: usbphy0@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x2152 /* MX28_PAD_SSP2_SS2__USB0_OVERCURRENT */
+						MX28_PAD_SSP2_SS2__USB0_OVERCURRENT
 					>;
-					fsl,drive-strength = <2>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_12mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				usbphy0_pins_b: usbphy0@1 {
 					reg = <1>;
 					fsl,pinmux-ids = <
-						0x3061 /* MX28_PAD_AUART1_CTS__USB0_OVERCURRENT */
+						MX28_PAD_AUART1_CTS__USB0_OVERCURRENT
 					>;
-					fsl,drive-strength = <2>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_12mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
 				};
 
 				usbphy1_pins_a: usbphy1@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-						0x2142 /* MX28_PAD_SSP2_SS1__USB1_OVERCURRENT */
+						MX28_PAD_SSP2_SS1__USB1_OVERCURRENT
 					>;
-					fsl,drive-strength = <2>;
-					fsl,voltage = <1>;
-					fsl,pull-up = <0>;
+					fsl,drive-strength = <MXS_DRIVE_12mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_DISABLE>;
+				};
+
+				usb0_id_pins_a: usb0id@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						MX28_PAD_AUART1_RTS__USB0_ID
+					>;
+					fsl,drive-strength = <MXS_DRIVE_12mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 			};
 
@@ -902,6 +944,7 @@
 				interrupts = <10 14 15 16 17 18 19
 						20 21 22 23 24 25>;
 				status = "disabled";
+				clocks = <&clks 41>;
 			};
 
 			spdif: spdif@80054000 {
diff --git a/arch/arm/boot/dts/imx51-apf51dev.dts b/arch/arm/boot/dts/imx51-apf51dev.dts
index 123fe84..5a7f552 100644
--- a/arch/arm/boot/dts/imx51-apf51dev.dts
+++ b/arch/arm/boot/dts/imx51-apf51dev.dts
@@ -16,6 +16,33 @@
 	model = "Armadeus Systems APF51Dev docking/development board";
 	compatible = "armadeus,imx51-apf51dev", "armadeus,imx51-apf51", "fsl,imx51";
 
+	display@di1 {
+		compatible = "fsl,imx-parallel-display";
+		crtcs = <&ipu 0>;
+		interface-pix-fmt = "bgr666";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_ipu_disp1_1>;
+
+		display-timings {
+			lw700 {
+				native-mode;
+				clock-frequency = <33000033>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <96>;
+				hfront-porch = <96>;
+				vback-porch = <20>;
+				vfront-porch = <21>;
+				hsync-len = <64>;
+				vsync-len = <4>;
+				hsync-active = <1>;
+				vsync-active = <1>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+	};
+
 	gpio-keys {
 		compatible = "gpio-keys";
 
diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
index 1d337d9..be1407c 100644
--- a/arch/arm/boot/dts/imx51-babbage.dts
+++ b/arch/arm/boot/dts/imx51-babbage.dts
@@ -27,6 +27,20 @@
 		interface-pix-fmt = "rgb24";
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_ipu_disp1_1>;
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: dvi {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+			};
+		};
 	};
 
 	display@di1 {
@@ -35,6 +49,25 @@
 		interface-pix-fmt = "rgb565";
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_ipu_disp2_1>;
+		status = "disabled";
+		display-timings {
+			native-mode = <&timing1>;
+			timing1: claawvga {
+				clock-frequency = <27000000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <40>;
+				hfront-porch = <60>;
+				vback-porch = <10>;
+				vfront-porch = <10>;
+				hsync-len = <20>;
+				vsync-len = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
 	};
 
 	gpio-keys {
@@ -95,7 +128,7 @@
 
 &uart3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart3_1>;
+	pinctrl-0 = <&pinctrl_uart3_1 &pinctrl_uart3_rtscts_1>;
 	fsl,uart-has-rtscts;
 	status = "okay";
 };
@@ -252,7 +285,7 @@
 
 &uart1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_1>;
+	pinctrl-0 = <&pinctrl_uart1_1 &pinctrl_uart1_rtscts_1>;
 	fsl,uart-has-rtscts;
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
index 54cee65..f4dcff3 100644
--- a/arch/arm/boot/dts/imx51.dtsi
+++ b/arch/arm/boot/dts/imx51.dtsi
@@ -86,6 +86,11 @@
 		interrupt-parent = <&tzic>;
 		ranges;
 
+		iram: iram@1ffe0000 {
+			compatible = "mmio-sram";
+			reg = <0x1ffe0000 0x20000>;
+		};
+
 		ipu: ipu@40000000 {
 			#crtc-cells = <1>;
 			compatible = "fsl,imx51-ipu";
@@ -374,6 +379,14 @@
 				clocks = <&clks 107>;
 			};
 
+			owire: owire@83fa4000 {
+				compatible = "fsl,imx51-owire", "fsl,imx21-owire";
+				reg = <0x83fa4000 0x4000>;
+				interrupts = <88>;
+				clocks = <&clks 159>;
+				status = "disabled";
+			};
+
 			ecspi2: ecspi@83fac000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
@@ -747,6 +760,11 @@
 			fsl,pins = <
 				MX51_PAD_UART1_RXD__UART1_RXD 0x1c5
 				MX51_PAD_UART1_TXD__UART1_TXD 0x1c5
+			>;
+		};
+
+		pinctrl_uart1_rtscts_1: uart1rtscts-1 {
+			fsl,pins = <
 				MX51_PAD_UART1_RTS__UART1_RTS 0x1c5
 				MX51_PAD_UART1_CTS__UART1_CTS 0x1c5
 			>;
@@ -767,6 +785,11 @@
 			fsl,pins = <
 				MX51_PAD_EIM_D25__UART3_RXD 0x1c5
 				MX51_PAD_EIM_D26__UART3_TXD 0x1c5
+			>;
+		};
+
+		pinctrl_uart3_rtscts_1: uart3rtscts-1 {
+			fsl,pins = <
 				MX51_PAD_EIM_D27__UART3_RTS 0x1c5
 				MX51_PAD_EIM_D24__UART3_CTS 0x1c5
 			>;
diff --git a/arch/arm/boot/dts/imx53-qsb.dts b/arch/arm/boot/dts/imx53-qsb.dts
index e97ddae..91a5935 100644
--- a/arch/arm/boot/dts/imx53-qsb.dts
+++ b/arch/arm/boot/dts/imx53-qsb.dts
@@ -55,19 +55,20 @@
 			label = "Power Button";
 			gpios = <&gpio1 8 0>;
 			linux,code = <116>; /* KEY_POWER */
-			gpio-key,wakeup;
 		};
 
 		volume-up {
 			label = "Volume Up";
 			gpios = <&gpio2 14 0>;
 			linux,code = <115>; /* KEY_VOLUMEUP */
+			gpio-key,wakeup;
 		};
 
 		volume-down {
 			label = "Volume Down";
 			gpios = <&gpio2 15 0>;
 			linux,code = <114>; /* KEY_VOLUMEDOWN */
+			gpio-key,wakeup;
 		};
 	};
 
@@ -122,7 +123,6 @@
 &esdhc1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_esdhc1_1>;
-	cd-gpios = <&gpio3 13 0>;
 	status = "okay";
 };
 
@@ -136,6 +136,7 @@
 	pinctrl-0 = <&pinctrl_esdhc3_1>;
 	cd-gpios = <&gpio3 11 0>;
 	wp-gpios = <&gpio3 12 0>;
+	bus-width = <8>;
 	status = "okay";
 };
 
@@ -152,7 +153,6 @@
 				MX53_PAD_PATA_DATA15__GPIO2_15    0x80000000
 				MX53_PAD_EIM_DA11__GPIO3_11       0x80000000
 				MX53_PAD_EIM_DA12__GPIO3_12       0x80000000
-				MX53_PAD_EIM_DA13__GPIO3_13       0x80000000
 				MX53_PAD_PATA_DA_0__GPIO7_6       0x80000000
 				MX53_PAD_PATA_DA_2__GPIO7_8	  0x80000000
 				MX53_PAD_GPIO_16__GPIO7_11        0x80000000
@@ -318,5 +318,6 @@
 };
 
 &usbotg {
-       status = "okay";
+	dr_mode = "peripheral";
+	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6q-pinfunc.h b/arch/arm/boot/dts/imx6q-pinfunc.h
index 9bbe82b..97ed081 100644
--- a/arch/arm/boot/dts/imx6q-pinfunc.h
+++ b/arch/arm/boot/dts/imx6q-pinfunc.h
@@ -536,7 +536,7 @@
 #define MX6QDL_PAD_ENET_REF_CLK__ESAI_RX_FS         0x1d4 0x4e8 0x85c 0x2 0x0
 #define MX6QDL_PAD_ENET_REF_CLK__GPIO1_IO23         0x1d4 0x4e8 0x000 0x5 0x0
 #define MX6QDL_PAD_ENET_REF_CLK__SPDIF_SR_CLK       0x1d4 0x4e8 0x000 0x6 0x0
-#define MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID           0x1d8 0x4ec 0x000 0x0 0x0
+#define MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID           0x1d8 0x4ec 0x004 0x0 0xff0d0100
 #define MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER           0x1d8 0x4ec 0x000 0x1 0x0
 #define MX6QDL_PAD_ENET_RX_ER__ESAI_RX_HF_CLK       0x1d8 0x4ec 0x864 0x2 0x0
 #define MX6QDL_PAD_ENET_RX_ER__SPDIF_IN             0x1d8 0x4ec 0x914 0x3 0x1
@@ -654,7 +654,7 @@
 #define MX6QDL_PAD_GPIO_1__ESAI_RX_CLK              0x224 0x5f4 0x86c 0x0 0x1
 #define MX6QDL_PAD_GPIO_1__WDOG2_B                  0x224 0x5f4 0x000 0x1 0x0
 #define MX6QDL_PAD_GPIO_1__KEY_ROW5                 0x224 0x5f4 0x8f4 0x2 0x0
-#define MX6QDL_PAD_GPIO_1__USB_OTG_ID               0x224 0x5f4 0x000 0x3 0x0
+#define MX6QDL_PAD_GPIO_1__USB_OTG_ID               0x224 0x5f4 0x004 0x3 0xff0d0101
 #define MX6QDL_PAD_GPIO_1__PWM2_OUT                 0x224 0x5f4 0x000 0x4 0x0
 #define MX6QDL_PAD_GPIO_1__GPIO1_IO01               0x224 0x5f4 0x000 0x5 0x0
 #define MX6QDL_PAD_GPIO_1__SD1_CD_B                 0x224 0x5f4 0x000 0x6 0x0
diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts
index 3530280..f004913 100644
--- a/arch/arm/boot/dts/imx6q-sabrelite.dts
+++ b/arch/arm/boot/dts/imx6q-sabrelite.dts
@@ -65,8 +65,10 @@
 	};
 };
 
-&sata {
+&audmux {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux_1>;
 };
 
 &ecspi1 {
@@ -83,11 +85,29 @@
 	};
 };
 
-&ssi1 {
-	fsl,mode = "i2s-slave";
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet_1>;
+	phy-mode = "rgmii";
+	phy-reset-gpios = <&gpio3 23 0>;
 	status = "okay";
 };
 
+&i2c1 {
+	status = "okay";
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1_1>;
+
+	codec: sgtl5000@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks 201>;
+		VDDA-supply = <&reg_2p5v>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+};
+
 &iomuxc {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
@@ -103,11 +123,56 @@
 				MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x80000000
 				MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1f0b0
 				MX6QDL_PAD_GPIO_0__CCM_CLKO1    0x80000000
+				MX6QDL_PAD_EIM_D23__GPIO3_IO23	0x80000000
 			>;
 		};
 	};
 };
 
+&ldb {
+	status = "okay";
+
+	lvds-channel@0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+			};
+		};
+	};
+};
+
+&sata {
+	status = "okay";
+};
+
+&ssi1 {
+	fsl,mode = "i2s-slave";
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2_1>;
+};
+
+&usbh1 {
+	status = "okay";
+};
+
 &usbotg {
 	vbus-supply = <&reg_usb_otg_vbus>;
 	pinctrl-names = "default";
@@ -116,18 +181,6 @@
 	status = "okay";
 };
 
-&usbh1 {
-	status = "okay";
-};
-
-&fec {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet_1>;
-	phy-mode = "rgmii";
-	phy-reset-gpios = <&gpio3 23 0>;
-	status = "okay";
-};
-
 &usdhc3 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usdhc3_2>;
@@ -145,30 +198,3 @@
 	vmmc-supply = <&reg_3p3v>;
 	status = "okay";
 };
-
-&audmux {
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_audmux_1>;
-};
-
-&uart2 {
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2_1>;
-};
-
-&i2c1 {
-	status = "okay";
-	clock-frequency = <100000>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c1_1>;
-
-	codec: sgtl5000@0a {
-		compatible = "fsl,sgtl5000";
-		reg = <0x0a>;
-		clocks = <&clks 201>;
-		VDDA-supply = <&reg_2p5v>;
-		VDDIO-supply = <&reg_3p3v>;
-	};
-};
diff --git a/arch/arm/boot/dts/imx6q-udoo.dts b/arch/arm/boot/dts/imx6q-udoo.dts
new file mode 100644
index 0000000..6e1ccdc
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-udoo.dts
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+
+/ {
+	model = "Udoo i.MX6 Quad Board";
+	compatible = "udoo,imx6q-udoo", "fsl,imx6q";
+
+	memory {
+		reg = <0x10000000 0x40000000>;
+	};
+};
+
+&sata {
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2_1>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3_2>;
+	non-removable;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index 1cbbc51..ff6f1e8 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -54,6 +54,7 @@
 			fsl,pins = <
 				MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x80000000
 				MX6QDL_PAD_SD2_DAT2__GPIO1_IO13  0x80000000
+				MX6QDL_PAD_GPIO_18__SD3_VSELECT 0x17059
 			>;
 		};
 	};
@@ -74,8 +75,10 @@
 };
 
 &usdhc3 {
-	pinctrl-names = "default";
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
 	pinctrl-0 = <&pinctrl_usdhc3_1>;
+	pinctrl-1 = <&pinctrl_usdhc3_1_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc3_1_200mhz>;
 	cd-gpios = <&gpio6 15 0>;
 	wp-gpios = <&gpio1 13 0>;
 	status = "okay";
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index 39eafc2..e75e11b 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -80,6 +80,14 @@
 		mux-int-port = <2>;
 		mux-ext-port = <3>;
 	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm1 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <7>;
+		status = "okay";
+	};
 };
 
 &audmux {
@@ -108,6 +116,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet_1>;
 	phy-mode = "rgmii";
+	phy-reset-gpios = <&gpio1 25 0>;
 	status = "okay";
 };
 
@@ -172,6 +181,7 @@
 				MX6QDL_PAD_NANDF_CLE__GPIO6_IO07 0x80000000
 				MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
 				MX6QDL_PAD_EIM_D22__GPIO3_IO22  0x80000000
+				MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x80000000
 			>;
 		};
 	};
@@ -202,6 +212,12 @@
 	};
 };
 
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm0_1>;
+	status = "okay";
+};
+
 &ssi2 {
 	fsl,mode = "i2s-slave";
 	status = "okay";
@@ -229,6 +245,7 @@
 &usdhc2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usdhc2_1>;
+	bus-width = <8>;
 	cd-gpios = <&gpio2 2 0>;
 	wp-gpios = <&gpio2 3 0>;
 	status = "okay";
@@ -237,6 +254,7 @@
 &usdhc3 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usdhc3_1>;
+	bus-width = <8>;
 	cd-gpios = <&gpio2 0 0>;
 	wp-gpios = <&gpio2 1 0>;
 	status = "okay";
diff --git a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
index a55113e..35f5479 100644
--- a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
@@ -43,6 +43,13 @@
 		mux-int-port = <1>;
 		mux-ext-port = <3>;
 	};
+
+	sound-spdif {
+		compatible = "fsl,imx-audio-spdif";
+		model = "imx-spdif";
+		spdif-controller = <&spdif>;
+		spdif-out;
+	};
 };
 
 &audmux {
@@ -81,6 +88,7 @@
 				MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000 /* WL_REG_ON */
 				MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* WL_HOST_WAKE */
 				MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* WL_WAKE */
+				MX6QDL_PAD_EIM_D29__GPIO3_IO29   0x80000000
 			>;
 		};
 	};
@@ -90,6 +98,13 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet_1>;
 	phy-mode = "rgmii";
+	phy-reset-gpios = <&gpio3 29 0>;
+	status = "okay";
+};
+
+&spdif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_spdif_3>;
 	status = "okay";
 };
 
@@ -115,6 +130,14 @@
 	status = "okay";
 };
 
+&usbotg {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg_1>;
+	disable-over-current;
+	dr_mode = "peripheral";
+	status = "okay";
+};
+
 &usdhc1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usdhc1_2>;
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index ccd55c2..59154dc 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -116,6 +116,22 @@
 			arm,data-latency = <4 2 3>;
 		};
 
+		pcie: pcie@0x01000000 {
+			compatible = "fsl,imx6q-pcie", "snps,dw-pcie";
+			reg = <0x01ffc000 0x4000>; /* DBI */
+			#address-cells = <3>;
+			#size-cells = <2>;
+			device_type = "pci";
+			ranges = <0x00000800 0 0x01f00000 0x01f00000 0 0x00080000 /* configuration space */
+				  0x81000000 0 0          0x01f80000 0 0x00010000 /* downstream I/O */
+				  0x82000000 0 0x01000000 0x01000000 0 0x00f00000>; /* non-prefetchable memory */
+			num-lanes = <1>;
+			interrupts = <0 123 0x04>;
+			clocks = <&clks 189>, <&clks 187>, <&clks 206>, <&clks 144>;
+			clock-names = "pcie_ref_125m", "sata_ref_100m", "lvds_gate", "pcie_axi";
+			status = "disabled";
+		};
+
 		pmu {
 			compatible = "arm,cortex-a9-pmu";
 			interrupts = <0 94 0x04>;
@@ -136,8 +152,23 @@
 				ranges;
 
 				spdif: spdif@02004000 {
+					compatible = "fsl,imx35-spdif";
 					reg = <0x02004000 0x4000>;
 					interrupts = <0 52 0x04>;
+					dmas = <&sdma 14 18 0>,
+					       <&sdma 15 18 0>;
+					dma-names = "rx", "tx";
+					clocks = <&clks 197>, <&clks 3>,
+						 <&clks 197>, <&clks 107>,
+						 <&clks 0>,   <&clks 118>,
+						 <&clks 62>,  <&clks 139>,
+						 <&clks 0>;
+					clock-names = "core",  "rxtx0",
+						      "rxtx1", "rxtx2",
+						      "rxtx3", "rxtx4",
+						      "rxtx5", "rxtx6",
+						      "rxtx7";
+					status = "disabled";
 				};
 
 				ecspi1: ecspi@02008000 {
@@ -1010,6 +1041,12 @@
 							MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x1b0b0
 						>;
 					};
+
+					pinctrl_spdif_3: spdifgrp-3 {
+						fsl,pins = <
+							MX6QDL_PAD_ENET_RXD0__SPDIF_OUT 0x1b0b0
+						>;
+					};
 				};
 
 				uart1 {
@@ -1184,6 +1221,36 @@
 						>;
 					};
 
+					pinctrl_usdhc3_1_100mhz: usdhc3grp-1-100mhz { /* 100Mhz */
+						fsl,pins = <
+							MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9
+							MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100b9
+							MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170b9
+							MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170b9
+							MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170b9
+							MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170b9
+							MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170b9
+							MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170b9
+							MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170b9
+							MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170b9
+						>;
+					};
+
+					pinctrl_usdhc3_1_200mhz: usdhc3grp-1-200mhz { /* 200Mhz */
+						fsl,pins = <
+							MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9
+							MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9
+							MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170f9
+							MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170f9
+							MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170f9
+							MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170f9
+							MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170f9
+							MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170f9
+							MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170f9
+							MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170f9
+						>;
+					};
+
 					pinctrl_usdhc3_2: usdhc3grp-2 {
 						fsl,pins = <
 							MX6QDL_PAD_SD3_CMD__SD3_CMD    0x17059
diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts
index 2886a59..cc68e19 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -17,6 +17,44 @@
 	memory {
 		reg = <0x80000000 0x40000000>;
 	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_usb_otg1_vbus: usb_otg1_vbus {
+			compatible = "regulator-fixed";
+			regulator-name = "usb_otg1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio4 0 0>;
+			enable-active-high;
+		};
+
+		reg_usb_otg2_vbus: usb_otg2_vbus {
+			compatible = "regulator-fixed";
+			regulator-name = "usb_otg2_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio4 2 0>;
+			enable-active-high;
+		};
+	};
+};
+
+&ecspi1 {
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio4 11 0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1_1>;
+	status = "okay";
+
+	flash: m25p80@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "st,m25p32";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
 };
 
 &fec {
@@ -38,6 +76,8 @@
 				MX6SL_PAD_SD2_DAT7__GPIO5_IO00    0x17059
 				MX6SL_PAD_SD2_DAT6__GPIO4_IO29    0x17059
 				MX6SL_PAD_REF_CLK_32K__GPIO3_IO22 0x17059
+				MX6SL_PAD_KEY_COL4__GPIO4_IO00	0x80000000
+				MX6SL_PAD_KEY_COL5__GPIO4_IO02	0x80000000
 			>;
 		};
 	};
@@ -49,9 +89,26 @@
 	status = "okay";
 };
 
-&usdhc1 {
+&usbotg1 {
+	vbus-supply = <&reg_usb_otg1_vbus>;
 	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg1_1>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usbotg2 {
+	vbus-supply = <&reg_usb_otg2_vbus>;
+	dr_mode = "host";
+	disable-over-current;
+	status = "okay";
+};
+
+&usdhc1 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
 	pinctrl-0 = <&pinctrl_usdhc1_1>;
+	pinctrl-1 = <&pinctrl_usdhc1_1_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc1_1_200mhz>;
 	bus-width = <8>;
 	cd-gpios = <&gpio4 7 0>;
 	wp-gpios = <&gpio4 6 0>;
@@ -59,16 +116,20 @@
 };
 
 &usdhc2 {
-	pinctrl-names = "default";
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
 	pinctrl-0 = <&pinctrl_usdhc2_1>;
+	pinctrl-1 = <&pinctrl_usdhc2_1_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc2_1_200mhz>;
 	cd-gpios = <&gpio5 0 0>;
 	wp-gpios = <&gpio4 29 0>;
 	status = "okay";
 };
 
 &usdhc3 {
-	pinctrl-names = "default";
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
 	pinctrl-0 = <&pinctrl_usdhc3_1>;
+	pinctrl-1 = <&pinctrl_usdhc3_1_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc3_1_200mhz>;
 	cd-gpios = <&gpio3 22 0>;
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index c46651e..28558f1 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -13,16 +13,20 @@
 
 / {
 	aliases {
-		serial0 = &uart1;
-		serial1 = &uart2;
-		serial2 = &uart3;
-		serial3 = &uart4;
-		serial4 = &uart5;
 		gpio0 = &gpio1;
 		gpio1 = &gpio2;
 		gpio2 = &gpio3;
 		gpio3 = &gpio4;
 		gpio4 = &gpio5;
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+		serial3 = &uart4;
+		serial4 = &uart5;
+		spi0 = &ecspi1;
+		spi1 = &ecspi2;
+		spi2 = &ecspi3;
+		spi3 = &ecspi4;
 	};
 
 	cpus {
@@ -380,7 +384,9 @@
 			};
 
 			anatop: anatop@020c8000 {
-				compatible = "fsl,imx6sl-anatop", "syscon", "simple-bus";
+				compatible = "fsl,imx6sl-anatop",
+					     "fsl,imx6q-anatop",
+					     "syscon", "simple-bus";
 				reg = <0x020c8000 0x1000>;
 				interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
 
@@ -528,10 +534,26 @@
 				interrupts = <0 89 0x04>;
 			};
 
+			gpr: iomuxc-gpr@020e0000 {
+				compatible = "fsl,imx6sl-iomuxc-gpr",
+					     "fsl,imx6q-iomuxc-gpr", "syscon";
+				reg = <0x020e0000 0x38>;
+			};
+
 			iomuxc: iomuxc@020e0000 {
 				compatible = "fsl,imx6sl-iomuxc";
 				reg = <0x020e0000 0x4000>;
 
+				ecspi1 {
+					pinctrl_ecspi1_1: ecspi1grp-1 {
+						fsl,pins = <
+							MX6SL_PAD_ECSPI1_MISO__ECSPI1_MISO 0x100b1
+							MX6SL_PAD_ECSPI1_MOSI__ECSPI1_MOSI 0x100b1
+							MX6SL_PAD_ECSPI1_SCLK__ECSPI1_SCLK 0x100b1
+						>;
+					};
+				};
+
 				fec {
 					pinctrl_fec_1: fecgrp-1 {
 						fsl,pins = <
@@ -557,6 +579,64 @@
 					};
 				};
 
+				usbotg1 {
+					pinctrl_usbotg1_1: usbotg1grp-1 {
+						fsl,pins = <
+							MX6SL_PAD_EPDC_PWRCOM__USB_OTG1_ID 0x17059
+						>;
+					};
+
+					pinctrl_usbotg1_2: usbotg1grp-2 {
+						fsl,pins = <
+							MX6SL_PAD_FEC_RXD0__USB_OTG1_ID 0x17059
+						>;
+					};
+
+					pinctrl_usbotg1_3: usbotg1grp-3 {
+						fsl,pins = <
+							MX6SL_PAD_LCD_DAT1__USB_OTG1_ID 0x17059
+						>;
+					};
+
+					pinctrl_usbotg1_4: usbotg1grp-4 {
+						fsl,pins = <
+							MX6SL_PAD_REF_CLK_32K__USB_OTG1_ID 0x17059
+						>;
+					};
+
+					pinctrl_usbotg1_5: usbotg1grp-5 {
+						fsl,pins = <
+							MX6SL_PAD_SD3_DAT0__USB_OTG1_ID 0x17059
+						>;
+					};
+				};
+
+				usbotg2 {
+					pinctrl_usbotg2_1: usbotg2grp-1 {
+						fsl,pins = <
+							MX6SL_PAD_ECSPI1_SCLK__USB_OTG2_OC 0x17059
+						>;
+					};
+
+					pinctrl_usbotg2_2: usbotg2grp-2 {
+						fsl,pins = <
+							MX6SL_PAD_ECSPI2_SCLK__USB_OTG2_OC 0x17059
+						>;
+					};
+
+					pinctrl_usbotg2_3: usbotg2grp-3 {
+						fsl,pins = <
+							MX6SL_PAD_KEY_ROW5__USB_OTG2_OC 0x17059
+						>;
+					};
+
+					pinctrl_usbotg2_4: usbotg2grp-4 {
+						fsl,pins = <
+							MX6SL_PAD_SD3_DAT2__USB_OTG2_OC 0x17059
+						>;
+					};
+				};
+
 				usdhc1 {
 					pinctrl_usdhc1_1: usdhc1grp-1 {
 						fsl,pins = <
@@ -572,6 +652,38 @@
 							MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x17059
 						>;
 					};
+
+					pinctrl_usdhc1_1_100mhz: usdhc1grp-1-100mhz {
+						fsl,pins = <
+							MX6SL_PAD_SD1_CMD__SD1_CMD 0x170b9
+							MX6SL_PAD_SD1_CLK__SD1_CLK 0x100b9
+							MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x170b9
+							MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x170b9
+							MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x170b9
+							MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x170b9
+							MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x170b9
+							MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x170b9
+							MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x170b9
+							MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x170b9
+						>;
+					};
+
+					pinctrl_usdhc1_1_200mhz: usdhc1grp-1-200mhz {
+						fsl,pins = <
+							MX6SL_PAD_SD1_CMD__SD1_CMD 0x170f9
+							MX6SL_PAD_SD1_CLK__SD1_CLK 0x100f9
+							MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x170f9
+							MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x170f9
+							MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x170f9
+							MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x170f9
+							MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x170f9
+							MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x170f9
+							MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x170f9
+							MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x170f9
+						>;
+					};
+
+
 				};
 
 				usdhc2 {
@@ -585,6 +697,29 @@
 							MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x17059
 						>;
 					};
+
+					pinctrl_usdhc2_1_100mhz: usdhc2grp-1-100mhz {
+						fsl,pins = <
+							MX6SL_PAD_SD2_CMD__SD2_CMD    0x170b9
+							MX6SL_PAD_SD2_CLK__SD2_CLK    0x100b9
+							MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x170b9
+							MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x170b9
+							MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x170b9
+							MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x170b9
+						>;
+					};
+
+					pinctrl_usdhc2_1_200mhz: usdhc2grp-1-200mhz {
+						fsl,pins = <
+							MX6SL_PAD_SD2_CMD__SD2_CMD    0x170f9
+							MX6SL_PAD_SD2_CLK__SD2_CLK    0x100f9
+							MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x170f9
+							MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x170f9
+							MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x170f9
+							MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x170f9
+						>;
+					};
+
 				};
 
 				usdhc3 {
@@ -598,6 +733,28 @@
 							MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x17059
 						>;
 					};
+
+					pinctrl_usdhc3_1_100mhz: usdhc3grp-1-100mhz {
+						fsl,pins = <
+							MX6SL_PAD_SD3_CMD__SD3_CMD    0x170b9
+							MX6SL_PAD_SD3_CLK__SD3_CLK    0x100b9
+							MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x170b9
+							MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x170b9
+							MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x170b9
+							MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x170b9
+						>;
+					};
+
+					pinctrl_usdhc3_1_200mhz: usdhc3grp-1-200mhz {
+						fsl,pins = <
+							MX6SL_PAD_SD3_CMD__SD3_CMD    0x170f9
+							MX6SL_PAD_SD3_CLK__SD3_CLK    0x100f9
+							MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x170f9
+							MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x170f9
+							MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x170f9
+							MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x170f9
+						>;
+					};
 				};
 			};
 
@@ -619,7 +776,8 @@
 					 <&clks IMX6SL_CLK_SDMA>;
 				clock-names = "ipg", "ahb";
 				#dma-cells = <3>;
-				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6sl.bin";
+				/* imx6sl reuses imx6q sdma firmware */
+				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q.bin";
 			};
 
 			pxp: pxp@020f0000 {
@@ -663,7 +821,7 @@
 			usbotg2: usb@02184200 {
 				compatible = "fsl,imx6sl-usb", "fsl,imx27-usb";
 				reg = <0x02184200 0x200>;
-				interrupts = <0 40 0x04>;
+				interrupts = <0 42 0x04>;
 				clocks = <&clks IMX6SL_CLK_USBOH3>;
 				fsl,usbphy = <&usbphy2>;
 				fsl,usbmisc = <&usbmisc 1>;
@@ -673,7 +831,7 @@
 			usbh: usb@02184400 {
 				compatible = "fsl,imx6sl-usb", "fsl,imx27-usb";
 				reg = <0x02184400 0x200>;
-				interrupts = <0 42 0x04>;
+				interrupts = <0 40 0x04>;
 				clocks = <&clks IMX6SL_CLK_USBOH3>;
 				fsl,usbmisc = <&usbmisc 2>;
 				status = "disabled";
diff --git a/arch/arm/boot/dts/integrator.dtsi b/arch/arm/boot/dts/integrator.dtsi
index 813b91d..0f06f86 100644
--- a/arch/arm/boot/dts/integrator.dtsi
+++ b/arch/arm/boot/dts/integrator.dtsi
@@ -5,6 +5,11 @@
 /include/ "skeleton.dtsi"
 
 / {
+	core-module@10000000 {
+		compatible = "arm,core-module-integrator";
+		reg = <0x10000000 0x200>;
+	};
+
 	timer@13000000 {
 		reg = <0x13000000 0x100>;
 		interrupt-parent = <&pic>;
diff --git a/arch/arm/boot/dts/integratorap.dts b/arch/arm/boot/dts/integratorap.dts
index b6b82ec..e6be931 100644
--- a/arch/arm/boot/dts/integratorap.dts
+++ b/arch/arm/boot/dts/integratorap.dts
@@ -19,8 +19,11 @@
 	};
 
 	syscon {
-		/* AP system controller registers */
+		compatible = "arm,integrator-ap-syscon";
 		reg = <0x11000000 0x100>;
+		interrupt-parent = <&pic>;
+		/* These are the logical module IRQs */
+		interrupts = <9>, <10>, <11>, <12>;
 	};
 
 	timer0: timer@13000000 {
diff --git a/arch/arm/boot/dts/integratorcp.dts b/arch/arm/boot/dts/integratorcp.dts
index ff1aea0..7deb3a3 100644
--- a/arch/arm/boot/dts/integratorcp.dts
+++ b/arch/arm/boot/dts/integratorcp.dts
@@ -9,29 +9,28 @@
 	model = "ARM Integrator/CP";
 	compatible = "arm,integrator-cp";
 
-	aliases {
-		arm,timer-primary = &timer2;
-		arm,timer-secondary = &timer1;
-	};
-
 	chosen {
 		bootargs = "root=/dev/ram0 console=ttyAMA0,38400n8 earlyprintk";
 	};
 
-	cpcon {
-		/* CP controller registers */
+	syscon {
+		compatible = "arm,integrator-cp-syscon";
 		reg = <0xcb000000 0x100>;
 	};
 
 	timer0: timer@13000000 {
+		/* TIMER0 runs @ 25MHz */
 		compatible = "arm,integrator-cp-timer";
+		status = "disabled";
 	};
 
 	timer1: timer@13000100 {
+		/* TIMER1 runs @ 1MHz */
 		compatible = "arm,integrator-cp-timer";
 	};
 
 	timer2: timer@13000200 {
+		/* TIMER2 runs @ 1MHz */
 		compatible = "arm,integrator-cp-timer";
 	};
 
diff --git a/arch/arm/boot/dts/keystone-clocks.dtsi b/arch/arm/boot/dts/keystone-clocks.dtsi
new file mode 100644
index 0000000..d6713b1
--- /dev/null
+++ b/arch/arm/boot/dts/keystone-clocks.dtsi
@@ -0,0 +1,821 @@
+/*
+ * Device Tree Source for Keystone 2 clock tree
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+clocks {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+
+	refclkmain: refclkmain {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <122880000>;
+		clock-output-names = "refclk-main";
+	};
+
+	mainpllclk: mainpllclk@2310110 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,main-pll-clock";
+		clocks = <&refclkmain>;
+		reg = <0x02620350 4>, <0x02310110 4>;
+		reg-names = "control", "multiplier";
+		fixed-postdiv = <2>;
+	};
+
+	papllclk: papllclk@2620358 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclkmain>;
+		clock-output-names = "pa-pll-clk";
+		reg = <0x02620358 4>;
+		reg-names = "control";
+		fixed-postdiv = <6>;
+	};
+
+	ddr3allclk: ddr3apllclk@2620360 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclkmain>;
+		clock-output-names = "ddr-3a-pll-clk";
+		reg = <0x02620360 4>;
+		reg-names = "control";
+		fixed-postdiv = <6>;
+	};
+
+	ddr3bllclk: ddr3bpllclk@2620368 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclkmain>;
+		clock-output-names = "ddr-3b-pll-clk";
+		reg = <0x02620368 4>;
+		reg-names = "control";
+		fixed-postdiv = <6>;
+	};
+
+	armpllclk: armpllclk@2620370 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclkmain>;
+		clock-output-names = "arm-pll-clk";
+		reg = <0x02620370 4>;
+		reg-names = "control";
+		fixed-postdiv = <6>;
+	};
+
+	mainmuxclk: mainmuxclk@2310108 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-mux-clock";
+		clocks = <&mainpllclk>, <&refclkmain>;
+		reg = <0x02310108 4>;
+		bit-shift = <23>;
+		bit-mask = <1>;
+		clock-output-names = "mainmuxclk";
+	};
+
+	chipclk1: chipclk1 {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&mainmuxclk>;
+		clock-div = <1>;
+		clock-mult = <1>;
+		clock-output-names = "chipclk1";
+	};
+
+	chipclk1rstiso: chipclk1rstiso {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&mainmuxclk>;
+		clock-div = <1>;
+		clock-mult = <1>;
+		clock-output-names = "chipclk1rstiso";
+	};
+
+	gemtraceclk: gemtraceclk@2310120 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-divider-clock";
+		clocks = <&mainmuxclk>;
+		reg = <0x02310120 4>;
+		bit-shift = <0>;
+		bit-mask = <8>;
+		clock-output-names = "gemtraceclk";
+	};
+
+	chipstmxptclk: chipstmxptclk {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-divider-clock";
+		clocks = <&mainmuxclk>;
+		reg = <0x02310164 4>;
+		bit-shift = <0>;
+		bit-mask = <8>;
+		clock-output-names = "chipstmxptclk";
+	};
+
+	chipclk12: chipclk12 {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&chipclk1>;
+		clock-div = <2>;
+		clock-mult = <1>;
+		clock-output-names = "chipclk12";
+	};
+
+	chipclk13: chipclk13 {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&chipclk1>;
+		clock-div = <3>;
+		clock-mult = <1>;
+		clock-output-names = "chipclk13";
+	};
+
+	chipclk14: chipclk14 {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&chipclk1>;
+		clock-div = <4>;
+		clock-mult = <1>;
+		clock-output-names = "chipclk14";
+	};
+
+	chipclk16: chipclk16 {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&chipclk1>;
+		clock-div = <6>;
+		clock-mult = <1>;
+		clock-output-names = "chipclk16";
+	};
+
+	chipclk112: chipclk112 {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&chipclk1>;
+		clock-div = <12>;
+		clock-mult = <1>;
+		clock-output-names = "chipclk112";
+	};
+
+	chipclk124: chipclk124 {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&chipclk1>;
+		clock-div = <24>;
+		clock-mult = <1>;
+		clock-output-names = "chipclk114";
+	};
+
+	chipclk1rstiso13: chipclk1rstiso13 {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&chipclk1rstiso>;
+		clock-div = <3>;
+		clock-mult = <1>;
+		clock-output-names = "chipclk1rstiso13";
+	};
+
+	chipclk1rstiso14: chipclk1rstiso14 {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&chipclk1rstiso>;
+		clock-div = <4>;
+		clock-mult = <1>;
+		clock-output-names = "chipclk1rstiso14";
+	};
+
+	chipclk1rstiso16: chipclk1rstiso16 {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&chipclk1rstiso>;
+		clock-div = <6>;
+		clock-mult = <1>;
+		clock-output-names = "chipclk1rstiso16";
+	};
+
+	chipclk1rstiso112: chipclk1rstiso112 {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&chipclk1rstiso>;
+		clock-div = <12>;
+		clock-mult = <1>;
+		clock-output-names = "chipclk1rstiso112";
+	};
+
+	clkmodrst0: clkmodrst0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk16>;
+		clock-output-names = "modrst0";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+
+	clkusb: clkusb {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk16>;
+		clock-output-names = "usb";
+		reg = <0x02350008 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+	clkaemifspi: clkaemifspi {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk16>;
+		clock-output-names = "aemif-spi";
+		reg = <0x0235000c 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+
+	clkdebugsstrc: clkdebugsstrc {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "debugss-trc";
+		reg = <0x02350014 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+	clktetbtrc: clktetbtrc {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tetb-trc";
+		reg = <0x02350018 0xb00>, <0x02350004 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <1>;
+	};
+
+	clkpa: clkpa {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk16>;
+		clock-output-names = "pa";
+		reg = <0x0235001c 0xb00>, <0x02350008 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <2>;
+	};
+
+	clkcpgmac: clkcpgmac {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkpa>;
+		clock-output-names = "cpgmac";
+		reg = <0x02350020 0xb00>, <0x02350008 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <2>;
+	};
+
+	clksa: clksa {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkpa>;
+		clock-output-names = "sa";
+		reg = <0x02350024 0xb00>, <0x02350008 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <2>;
+	};
+
+	clkpcie: clkpcie {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk12>;
+		clock-output-names = "pcie";
+		reg = <0x02350028 0xb00>, <0x0235000c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <3>;
+	};
+
+	clksrio: clksrio {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1rstiso13>;
+		clock-output-names = "srio";
+		reg = <0x0235002c 0xb00>, <0x02350010 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <4>;
+	};
+
+	clkhyperlink0: clkhyperlink0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk12>;
+		clock-output-names = "hyperlink-0";
+		reg = <0x02350030 0xb00>, <0x02350014 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <5>;
+	};
+
+	clksr: clksr {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1rstiso112>;
+		clock-output-names = "sr";
+		reg = <0x02350034 0xb00>, <0x02350018 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <6>;
+	};
+
+	clkmsmcsram: clkmsmcsram {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "msmcsram";
+		reg = <0x02350038 0xb00>, <0x0235001c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <7>;
+	};
+
+	clkgem0: clkgem0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem0";
+		reg = <0x0235003c 0xb00>, <0x02350020 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <8>;
+	};
+
+	clkgem1: clkgem1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem1";
+		reg = <0x02350040 0xb00>, <0x02350024 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <9>;
+	};
+
+	clkgem2: clkgem2 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem2";
+		reg = <0x02350044 0xb00>, <0x02350028 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <10>;
+	};
+
+	clkgem3: clkgem3 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem3";
+		reg = <0x02350048 0xb00>, <0x0235002c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <11>;
+	};
+
+	clkgem4: clkgem4 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem4";
+		reg = <0x0235004c 0xb00>, <0x02350030 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <12>;
+	};
+
+	clkgem5: clkgem5 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem5";
+		reg = <0x02350050 0xb00>, <0x02350034 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <13>;
+	};
+
+	clkgem6: clkgem6 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem6";
+		reg = <0x02350054 0xb00>, <0x02350038 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <14>;
+	};
+
+	clkgem7: clkgem7 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem7";
+		reg = <0x02350058 0xb00>, <0x0235003c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <15>;
+	};
+
+	clkddr30: clkddr30 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk12>;
+		clock-output-names = "ddr3-0";
+		reg = <0x0235005c 0xb00>, <0x02350040 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <16>;
+	};
+
+	clkddr31: clkddr31 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "ddr3-1";
+		reg = <0x02350060 0xb00>, <0x02350040 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <16>;
+	};
+
+	clktac: clktac {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tac";
+		reg = <0x02350064 0xb00>, <0x02350044 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <17>;
+	};
+
+	clkrac01: clktac01 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "rac-01";
+		reg = <0x02350068 0xb00>, <0x02350044 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <17>;
+	};
+
+	clkrac23: clktac23 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "rac-23";
+		reg = <0x0235006c 0xb00>, <0x02350048 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <18>;
+	};
+
+	clkfftc0: clkfftc0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-0";
+		reg = <0x02350070 0xb00>, <0x0235004c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <19>;
+	};
+
+	clkfftc1: clkfftc1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-1";
+		reg = <0x02350074 0xb00>, <0x023504c0 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <19>;
+	};
+
+	clkfftc2: clkfftc2 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-2";
+		reg = <0x02350078 0xb00>, <0x02350050 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <20>;
+	};
+
+	clkfftc3: clkfftc3 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-3";
+		reg = <0x0235007c 0xb00>, <0x02350050 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <20>;
+	};
+
+	clkfftc4: clkfftc4 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-4";
+		reg = <0x02350080 0xb00>, <0x02350050 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <20>;
+	};
+
+	clkfftc5: clkfftc5 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-5";
+		reg = <0x02350084 0xb00>, <0x02350050 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <20>;
+	};
+
+	clkaif: clkaif {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "aif";
+		reg = <0x02350088 0xb00>, <0x02350054 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <21>;
+	};
+
+	clktcp3d0: clktcp3d0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tcp3d-0";
+		reg = <0x0235008c 0xb00>, <0x02350058 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <22>;
+	};
+
+	clktcp3d1: clktcp3d1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tcp3d-1";
+		reg = <0x02350090 0xb00>, <0x02350058 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <22>;
+	};
+
+	clktcp3d2: clktcp3d2 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tcp3d-2";
+		reg = <0x02350094 0xb00>, <0x0235005c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <23>;
+	};
+
+	clktcp3d3: clktcp3d3 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tcp3d-3";
+		reg = <0x02350098 0xb00>, <0x0235005c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <23>;
+	};
+
+	clkvcp0: clkvcp0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-0";
+		reg = <0x0235009c 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkvcp1: clkvcp1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-1";
+		reg = <0x023500a0 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkvcp2: clkvcp2 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-2";
+		reg = <0x023500a4 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkvcp3: clkvcp3 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-3";
+		reg = <0x0235000a8 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkvcp4: clkvcp4 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-4";
+		reg = <0x023500ac 0xb00>, <0x02350064 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <25>;
+	};
+
+	clkvcp5: clkvcp5 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-5";
+		reg = <0x023500b0 0xb00>, <0x02350064 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <25>;
+	};
+
+	clkvcp6: clkvcp6 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-6";
+		reg = <0x023500b4 0xb00>, <0x02350064 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <25>;
+	};
+
+	clkvcp7: clkvcp7 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-7";
+		reg = <0x023500b8 0xb00>, <0x02350064 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <25>;
+	};
+
+	clkbcp: clkbcp {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "bcp";
+		reg = <0x023500bc 0xb00>, <0x02350068 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <26>;
+	};
+
+	clkdxb: clkdxb {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "dxb";
+		reg = <0x023500c0 0xb00>, <0x0235006c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <27>;
+	};
+
+	clkhyperlink1: clkhyperlink1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk12>;
+		clock-output-names = "hyperlink-1";
+		reg = <0x023500c4 0xb00>, <0x02350070 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <28>;
+	};
+
+	clkxge: clkxge {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "xge";
+		reg = <0x023500c8 0xb00>, <0x02350074 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <29>;
+	};
+
+	clkwdtimer0: clkwdtimer0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkmodrst0>;
+		clock-output-names = "timer0";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+	clkwdtimer1: clkwdtimer1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkmodrst0>;
+		clock-output-names = "timer1";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+	clkwdtimer2: clkwdtimer2 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkmodrst0>;
+		clock-output-names = "timer2";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+	clkwdtimer3: clkwdtimer3 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkmodrst0>;
+		clock-output-names = "timer3";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+	clkuart0: clkuart0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkmodrst0>;
+		clock-output-names = "uart0";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+	clkuart1: clkuart1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkmodrst0>;
+		clock-output-names = "uart1";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+	clkaemif: clkaemif {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkaemifspi>;
+		clock-output-names = "aemif";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+	clkusim: clkusim {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkmodrst0>;
+		clock-output-names = "usim";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+	clki2c: clki2c {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkmodrst0>;
+		clock-output-names = "i2c";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+	clkspi: clkspi {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkaemifspi>;
+		clock-output-names = "spi";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+	clkgpio: clkgpio {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkmodrst0>;
+		clock-output-names = "gpio";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+	clkkeymgr: clkkeymgr {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkmodrst0>;
+		clock-output-names = "keymgr";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+};
diff --git a/arch/arm/boot/dts/keystone.dts b/arch/arm/boot/dts/keystone.dts
index a68e34b..100bdf5 100644
--- a/arch/arm/boot/dts/keystone.dts
+++ b/arch/arm/boot/dts/keystone.dts
@@ -100,13 +100,15 @@
 			reg = <0x023100e8 4>;	/* pll reset control reg */
 		};
 
+		/include/ "keystone-clocks.dtsi"
+
 		uart0: serial@02530c00 {
 			compatible = "ns16550a";
 			current-speed = <115200>;
 			reg-shift = <2>;
 			reg-io-width = <4>;
 			reg = <0x02530c00 0x100>;
-			clock-frequency = <133120000>;
+			clocks	= <&clkuart0>;
 			interrupts = <GIC_SPI 277 IRQ_TYPE_EDGE_RISING>;
 		};
 
@@ -116,9 +118,66 @@
 			reg-shift = <2>;
 			reg-io-width = <4>;
 			reg = <0x02531000 0x100>;
-			clock-frequency = <133120000>;
+			clocks	= <&clkuart1>;
 			interrupts = <GIC_SPI 280 IRQ_TYPE_EDGE_RISING>;
 		};
 
+		i2c0: i2c@2530000 {
+			compatible = "ti,davinci-i2c";
+			reg = <0x02530000 0x400>;
+			clock-frequency = <100000>;
+			clocks = <&clki2c>;
+			interrupts = <GIC_SPI 283 IRQ_TYPE_EDGE_RISING>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			dtt@50 {
+				compatible = "at,24c1024";
+				reg = <0x50>;
+			};
+		};
+
+		i2c1: i2c@2530400 {
+			compatible = "ti,davinci-i2c";
+			reg = <0x02530400 0x400>;
+			clock-frequency = <100000>;
+			clocks = <&clki2c>;
+			interrupts = <GIC_SPI 286 IRQ_TYPE_EDGE_RISING>;
+		};
+
+		i2c2: i2c@2530800 {
+			compatible = "ti,davinci-i2c";
+			reg = <0x02530800 0x400>;
+			clock-frequency = <100000>;
+			clocks = <&clki2c>;
+			interrupts = <GIC_SPI 289 IRQ_TYPE_EDGE_RISING>;
+		};
+
+		spi0: spi@21000400 {
+			compatible = "ti,dm6441-spi";
+			reg = <0x21000400 0x200>;
+			num-cs = <4>;
+			ti,davinci-spi-intr-line = <0>;
+			interrupts = <GIC_SPI 292 IRQ_TYPE_EDGE_RISING>;
+			clocks = <&clkspi>;
+		};
+
+		spi1: spi@21000600 {
+			compatible = "ti,dm6441-spi";
+			reg = <0x21000600 0x200>;
+			num-cs = <4>;
+			ti,davinci-spi-intr-line = <0>;
+			interrupts = <GIC_SPI 296 IRQ_TYPE_EDGE_RISING>;
+			clocks = <&clkspi>;
+		};
+
+		spi2: spi@21000800 {
+			compatible = "ti,dm6441-spi";
+			reg = <0x21000800 0x200>;
+			num-cs = <4>;
+			ti,davinci-spi-intr-line = <0>;
+			interrupts = <GIC_SPI 300 IRQ_TYPE_EDGE_RISING>;
+			clocks = <&clkspi>;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/kirkwood-db-88f6281.dts b/arch/arm/boot/dts/kirkwood-db-88f6281.dts
index 72c4b0a..c39dd76 100644
--- a/arch/arm/boot/dts/kirkwood-db-88f6281.dts
+++ b/arch/arm/boot/dts/kirkwood-db-88f6281.dts
@@ -19,7 +19,6 @@
 	compatible = "marvell,db-88f6281-bp", "marvell,kirkwood-88f6281", "marvell,kirkwood";
 
 	mbus {
-		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000>;
 		pcie-controller {
 			status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood-db-88f6282.dts b/arch/arm/boot/dts/kirkwood-db-88f6282.dts
index 36c411d..701c6b6 100644
--- a/arch/arm/boot/dts/kirkwood-db-88f6282.dts
+++ b/arch/arm/boot/dts/kirkwood-db-88f6282.dts
@@ -19,7 +19,6 @@
 	compatible = "marvell,db-88f6282-bp", "marvell,kirkwood-88f6282", "marvell,kirkwood";
 
 	mbus {
-		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000>;
 		pcie-controller {
 			status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood-db.dtsi b/arch/arm/boot/dts/kirkwood-db.dtsi
index c0e2a58..053aa20 100644
--- a/arch/arm/boot/dts/kirkwood-db.dtsi
+++ b/arch/arm/boot/dts/kirkwood-db.dtsi
@@ -39,28 +39,6 @@
 			status = "ok";
 		};
 
-		nand@3000000 {
-			pinctrl-0 = <&pmx_nand>;
-			pinctrl-names = "default";
-			chip-delay = <25>;
-			status = "okay";
-
-			partition@0 {
-				label = "uboot";
-				reg = <0x0 0x100000>;
-			};
-
-			partition@100000 {
-				label = "uImage";
-				reg = <0x100000 0x400000>;
-			};
-
-			partition@500000 {
-				label = "root";
-				reg = <0x500000 0x1fb00000>;
-			};
-		};
-
 		sata@80000 {
 			nr-ports = <2>;
 			status = "okay";
@@ -80,6 +58,28 @@
 	};
 };
 
+&nand {
+	pinctrl-0 = <&pmx_nand>;
+	pinctrl-names = "default";
+	chip-delay = <25>;
+	status = "okay";
+
+	partition@0 {
+		label = "uboot";
+		reg = <0x0 0x100000>;
+	};
+
+	partition@100000 {
+		label = "uImage";
+		reg = <0x100000 0x400000>;
+	};
+
+	partition@500000 {
+		label = "root";
+		reg = <0x500000 0x1fb00000>;
+	};
+};
+
 &mdio {
 	status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood-dnskw.dtsi b/arch/arm/boot/dts/kirkwood-dnskw.dtsi
index d544f77..aefa375 100644
--- a/arch/arm/boot/dts/kirkwood-dnskw.dtsi
+++ b/arch/arm/boot/dts/kirkwood-dnskw.dtsi
@@ -148,44 +148,6 @@
 			status = "okay";
 			nr-ports = <2>;
 		};
-
-		nand@3000000 {
-			pinctrl-0 = <&pmx_nand>;
-			pinctrl-names = "default";
-			status = "okay";
-			chip-delay = <35>;
-
-			partition@0 {
-				label = "u-boot";
-				reg = <0x0000000 0x100000>;
-				read-only;
-			};
-
-			partition@100000 {
-				label = "uImage";
-				reg = <0x0100000 0x500000>;
-			};
-
-			partition@600000 {
-				label = "ramdisk";
-				reg = <0x0600000 0x500000>;
-			};
-
-			partition@b00000 {
-				label = "image";
-				reg = <0x0b00000 0x6600000>;
-			};
-
-			partition@7100000 {
-				label = "mini firmware";
-				reg = <0x7100000 0xa00000>;
-			};
-
-			partition@7b00000 {
-				label = "config";
-				reg = <0x7b00000 0x500000>;
-			};
-		};
 	};
 
 	regulators {
@@ -220,6 +182,44 @@
 	};
 };
 
+&nand {
+	pinctrl-0 = <&pmx_nand>;
+	pinctrl-names = "default";
+	status = "okay";
+	chip-delay = <35>;
+
+	partition@0 {
+		label = "u-boot";
+		reg = <0x0000000 0x100000>;
+		read-only;
+	};
+
+	partition@100000 {
+		label = "uImage";
+		reg = <0x0100000 0x500000>;
+	};
+
+	partition@600000 {
+		label = "ramdisk";
+		reg = <0x0600000 0x500000>;
+	};
+
+	partition@b00000 {
+		label = "image";
+		reg = <0x0b00000 0x6600000>;
+	};
+
+	partition@7100000 {
+		label = "mini firmware";
+		reg = <0x7100000 0xa00000>;
+	};
+
+	partition@7b00000 {
+		label = "config";
+		reg = <0x7b00000 0x500000>;
+	};
+};
+
 &mdio {
 	status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood-dockstar.dts b/arch/arm/boot/dts/kirkwood-dockstar.dts
index 59a2117..33ff368 100644
--- a/arch/arm/boot/dts/kirkwood-dockstar.dts
+++ b/arch/arm/boot/dts/kirkwood-dockstar.dts
@@ -34,26 +34,6 @@
 		serial@12000 {
 			status = "ok";
 		};
-
-		nand@3000000 {
-			status = "okay";
-
-			partition@0 {
-				label = "u-boot";
-				reg = <0x0000000 0x100000>;
-				read-only;
-			};
-
-			partition@100000 {
-				label = "uImage";
-				reg = <0x0100000 0x400000>;
-			};
-
-			partition@500000 {
-				label = "data";
-				reg = <0x0500000 0xfb00000>;
-			};
-		};
 	};
 	gpio-leds {
 		compatible = "gpio-leds";
@@ -91,6 +71,26 @@
 	};
 };
 
+&nand {
+	status = "okay";
+
+	partition@0 {
+		label = "u-boot";
+		reg = <0x0000000 0x100000>;
+		read-only;
+	};
+
+	partition@100000 {
+		label = "uImage";
+		reg = <0x0100000 0x400000>;
+	};
+
+	partition@500000 {
+		label = "data";
+		reg = <0x0500000 0xfb00000>;
+	};
+};
+
 &mdio {
 	status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood-goflexnet.dts b/arch/arm/boot/dts/kirkwood-goflexnet.dts
index 6f7c7d7..a43bebb 100644
--- a/arch/arm/boot/dts/kirkwood-goflexnet.dts
+++ b/arch/arm/boot/dts/kirkwood-goflexnet.dts
@@ -67,31 +67,6 @@
 			status = "ok";
 		};
 
-		nand@3000000 {
-			chip-delay = <40>;
-			status = "okay";
-
-			partition@0 {
-				label = "u-boot";
-				reg = <0x0000000 0x100000>;
-				read-only;
-			};
-
-			partition@100000 {
-				label = "uImage";
-				reg = <0x0100000 0x400000>;
-			};
-
-			partition@500000 {
-				label = "pogoplug";
-				reg = <0x0500000 0x2000000>;
-			};
-
-			partition@2500000 {
-				label = "root";
-				reg = <0x02500000 0xd800000>;
-			};
-		};
 		sata@80000 {
 			status = "okay";
 			nr-ports = <2>;
@@ -171,6 +146,32 @@
 	};
 };
 
+&nand {
+	chip-delay = <40>;
+	status = "okay";
+
+	partition@0 {
+		label = "u-boot";
+		reg = <0x0000000 0x100000>;
+		read-only;
+	};
+
+	partition@100000 {
+		label = "uImage";
+		reg = <0x0100000 0x400000>;
+	};
+
+	partition@500000 {
+		label = "pogoplug";
+		reg = <0x0500000 0x2000000>;
+	};
+
+	partition@2500000 {
+		label = "root";
+		reg = <0x02500000 0xd800000>;
+	};
+};
+
 &mdio {
 	status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood-guruplug-server-plus.dts b/arch/arm/boot/dts/kirkwood-guruplug-server-plus.dts
index 6548b9d..d30a91a 100644
--- a/arch/arm/boot/dts/kirkwood-guruplug-server-plus.dts
+++ b/arch/arm/boot/dts/kirkwood-guruplug-server-plus.dts
@@ -40,26 +40,6 @@
 			status = "ok";
 		};
 
-		nand@3000000 {
-			status = "okay";
-
-			partition@0 {
-				label = "u-boot";
-				reg = <0x00000000 0x00100000>;
-				read-only;
-			};
-
-			partition@100000 {
-				label = "uImage";
-				reg = <0x00100000 0x00400000>;
-			};
-
-			partition@500000 {
-				label = "data";
-				reg = <0x00500000 0x1fb00000>;
-			};
-		};
-
 		sata@80000 {
 			status = "okay";
 			nr-ports = <1>;
@@ -97,6 +77,26 @@
 	};
 };
 
+&nand {
+	status = "okay";
+
+	partition@0 {
+		label = "u-boot";
+		reg = <0x00000000 0x00100000>;
+		read-only;
+	};
+
+	partition@100000 {
+		label = "uImage";
+		reg = <0x00100000 0x00400000>;
+	};
+
+	partition@500000 {
+		label = "data";
+		reg = <0x00500000 0x1fb00000>;
+	};
+};
+
 &mdio {
 	status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood-ib62x0.dts b/arch/arm/boot/dts/kirkwood-ib62x0.dts
index cb711a3..c5fb02f 100644
--- a/arch/arm/boot/dts/kirkwood-ib62x0.dts
+++ b/arch/arm/boot/dts/kirkwood-ib62x0.dts
@@ -5,7 +5,7 @@
 
 / {
 	model = "RaidSonic ICY BOX IB-NAS62x0 (Rev B)";
-	compatible = "raidsonic,ib-nas6210-b", "raidsonic,ib-nas6220-b", "raidsonic,ib-nas6210", "raidsonic,ib-nas6220", "raidsonic,ib-nas62x0",  "marvell,kirkwood-88f6281", "marvell,kirkwood";
+	compatible = "raidsonic,ib-nas6210-b", "raidsonic,ib-nas6220-b", "raidsonic,ib-nas6210", "raidsonic,ib-nas6220", "raidsonic,ib-nas62x0", "marvell,kirkwood-88f6281", "marvell,kirkwood";
 
 	memory {
 		device_type = "memory";
@@ -43,6 +43,7 @@
 				marvell,function = "gpio";
 			};
 		};
+
 		serial@12000 {
 			status = "okay";
 		};
@@ -51,28 +52,6 @@
 			status = "okay";
 			nr-ports = <2>;
 		};
-
-		nand@3000000 {
-			status = "okay";
-			pinctrl-0 = <&pmx_nand>;
-			pinctrl-names = "default";
-
-			partition@0 {
-				label = "u-boot";
-				reg = <0x0000000 0x100000>;
-			};
-
-			partition@100000 {
-				label = "uImage";
-				reg = <0x0100000 0x600000>;
-			};
-
-			partition@700000 {
-				label = "root";
-				reg = <0x0700000 0xf900000>;
-			};
-
-		};
 	};
 
 	gpio_keys {
@@ -93,6 +72,7 @@
 			gpios = <&gpio0 28 1>;
 		};
 	};
+
 	gpio-leds {
 		compatible = "gpio-leds";
 		pinctrl-0 = <&pmx_led_os_red &pmx_led_os_green
@@ -113,13 +93,39 @@
 			gpios = <&gpio0 27 0>;
 		};
 	};
+
 	gpio_poweroff {
 		compatible = "gpio-poweroff";
 		pinctrl-0 = <&pmx_power_off>;
 		pinctrl-names = "default";
 		gpios = <&gpio0 24 0>;
 	};
+};
 
+&nand {
+	status = "okay";
+	pinctrl-0 = <&pmx_nand>;
+	pinctrl-names = "default";
+
+	partition@0 {
+		label = "u-boot";
+		reg = <0x0000000 0xe0000>;
+	};
+
+	partition@e0000 {
+		label = "u-boot environment";
+		reg = <0xe0000 0x100000>;
+	};
+
+	partition@100000 {
+		label = "uImage";
+		reg = <0x0100000 0x600000>;
+	};
+
+	partition@700000 {
+		label = "root";
+		reg = <0x0700000 0xf900000>;
+	};
 
 };
 
@@ -134,6 +140,7 @@
 
 &eth0 {
 	status = "okay";
+
 	ethernet0-port@0 {
 		phy-handle = <&ethphy0>;
 	};
diff --git a/arch/arm/boot/dts/kirkwood-iconnect.dts b/arch/arm/boot/dts/kirkwood-iconnect.dts
index 0323f01..4a62b20 100644
--- a/arch/arm/boot/dts/kirkwood-iconnect.dts
+++ b/arch/arm/boot/dts/kirkwood-iconnect.dts
@@ -19,7 +19,6 @@
 	};
 
 	mbus {
-		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000>;
 		pcie-controller {
 			status = "okay";
 
@@ -83,35 +82,6 @@
 		serial@12000 {
 			status = "ok";
 		};
-
-		nand@3000000 {
-			status = "okay";
-
-			partition@0 {
-				label = "uboot";
-				reg = <0x0000000 0xc0000>;
-			};
-
-			partition@a0000 {
-				label = "env";
-				reg = <0xa0000 0x20000>;
-			};
-
-			partition@100000 {
-				label = "zImage";
-				reg = <0x100000 0x300000>;
-			};
-
-			partition@540000 {
-				label = "initrd";
-				reg = <0x540000 0x300000>;
-			};
-
-			partition@980000 {
-				label = "boot";
-				reg = <0x980000 0x1f400000>;
-			};
-		};
 	};
 
 	gpio-leds {
@@ -180,6 +150,35 @@
 	};
 };
 
+&nand {
+	status = "okay";
+
+	partition@0 {
+		label = "uboot";
+		reg = <0x0000000 0xc0000>;
+	};
+
+	partition@a0000 {
+		label = "env";
+		reg = <0xa0000 0x20000>;
+	};
+
+	partition@100000 {
+		label = "zImage";
+		reg = <0x100000 0x300000>;
+	};
+
+	partition@540000 {
+		label = "initrd";
+		reg = <0x540000 0x300000>;
+	};
+
+	partition@980000 {
+		label = "boot";
+		reg = <0x980000 0x1f400000>;
+	};
+};
+
 &mdio {
 	status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
index df84474..d15395d 100644
--- a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
+++ b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
@@ -113,31 +113,6 @@
 			status = "ok";
 		};
 
-		nand@3000000 {
-			status = "okay";
-
-			partition@0 {
-				label = "u-boot";
-				reg = <0x0000000 0x100000>;
-				read-only;
-			};
-
-			partition@a0000 {
-				label = "env";
-				reg = <0xa0000 0x20000>;
-				read-only;
-			};
-
-			partition@100000 {
-				label = "uImage";
-				reg = <0x100000 0x300000>;
-			};
-
-			partition@400000 {
-				label = "uInitrd";
-				reg = <0x540000 0x1000000>;
-			};
-		};
 		sata@80000 {
 			status = "okay";
 			nr-ports = <2>;
@@ -195,6 +170,32 @@
 	};
 };
 
+&nand {
+	status = "okay";
+
+	partition@0 {
+		label = "u-boot";
+		reg = <0x0000000 0x100000>;
+		read-only;
+	};
+
+	partition@a0000 {
+		label = "env";
+		reg = <0xa0000 0x20000>;
+		read-only;
+	};
+
+	partition@100000 {
+		label = "uImage";
+		reg = <0x100000 0x300000>;
+	};
+
+	partition@400000 {
+		label = "uInitrd";
+		reg = <0x540000 0x1000000>;
+	};
+};
+
 &mdio {
 	status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood-km_kirkwood.dts b/arch/arm/boot/dts/kirkwood-km_kirkwood.dts
index 6899408..cd44f37 100644
--- a/arch/arm/boot/dts/kirkwood-km_kirkwood.dts
+++ b/arch/arm/boot/dts/kirkwood-km_kirkwood.dts
@@ -34,13 +34,6 @@
 		serial@12000 {
 			status = "ok";
 		};
-
-		nand@3000000 {
-			pinctrl-0 = <&pmx_nand>;
-			pinctrl-names = "default";
-			status = "ok";
-			chip-delay = <25>;
-		};
 	};
 
 	i2c@0 {
@@ -51,6 +44,13 @@
 	};
 };
 
+&nand {
+	pinctrl-0 = <&pmx_nand>;
+	pinctrl-names = "default";
+	status = "ok";
+	chip-delay = <25>;
+};
+
 &mdio {
 	status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood-mplcec4.dts b/arch/arm/boot/dts/kirkwood-mplcec4.dts
index ce2b94b..6c1ec27 100644
--- a/arch/arm/boot/dts/kirkwood-mplcec4.dts
+++ b/arch/arm/boot/dts/kirkwood-mplcec4.dts
@@ -17,7 +17,6 @@
         };
 
 	mbus {
-		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000>;
 		pcie-controller {
 			status = "okay";
 
@@ -96,37 +95,6 @@
                         pinctrl-names = "default";
                 };
 
-                nand@3000000 {
-                        pinctrl-0 = <&pmx_nand>;
-                        pinctrl-names = "default";
-                        status = "okay";
-
-                        partition@0 {
-                                label = "uboot";
-                                reg = <0x0000000 0x100000>;
-                        };
-
-                        partition@100000 {
-                                label = "env";
-                                reg = <0x100000 0x80000>;
-                        };
-
-                        partition@180000 {
-                                label = "fdt";
-                                reg = <0x180000 0x80000>;
-                        };
-
-                        partition@200000 {
-                                label = "kernel";
-                                reg = <0x200000 0x400000>;
-                        };
-
-                        partition@600000 {
-                                label = "rootfs";
-                                reg = <0x600000 0x1fa00000>;
-                        };
-                };
-
 		rtc@10300 {
 			status = "disabled";
 		};
@@ -194,6 +162,37 @@
 	};
 };
 
+&nand {
+	pinctrl-0 = <&pmx_nand>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	partition@0 {
+		label = "uboot";
+		reg = <0x0000000 0x100000>;
+	};
+
+	partition@100000 {
+		label = "env";
+		reg = <0x100000 0x80000>;
+	};
+
+	partition@180000 {
+		label = "fdt";
+		reg = <0x180000 0x80000>;
+	};
+
+	partition@200000 {
+		label = "kernel";
+		reg = <0x200000 0x400000>;
+	};
+
+	partition@600000 {
+		label = "rootfs";
+		reg = <0x600000 0x1fa00000>;
+	};
+};
+
 &mdio {
 	status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts b/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts
index 874857e..e6a102c 100644
--- a/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts
+++ b/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts
@@ -17,7 +17,6 @@
 	};
 
 	mbus {
-		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000>;
 		pcie-controller {
 			status = "okay";
 
@@ -98,36 +97,6 @@
 			status = "okay";
 		};
 
-		nand@3000000 {
-			status = "okay";
-
-			partition@0 {
-				label = "u-boot";
-				reg = <0x0000000 0x180000>;
-				read-only;
-			};
-
-			partition@180000 {
-				label = "u-boot-env";
-				reg = <0x180000 0x20000>;
-			};
-
-			partition@200000 {
-				label = "uImage";
-				reg = <0x0200000 0x600000>;
-			};
-
-			partition@800000 {
-				label = "minirootfs";
-				reg = <0x0800000 0x1000000>;
-			};
-
-			partition@1800000 {
-				label = "jffs2";
-				reg = <0x1800000 0x6800000>;
-			};
-		};
-
 		sata@80000 {
 			status = "okay";
 			nr-ports = <2>;
@@ -208,6 +177,36 @@
         };
 };
 
+&nand {
+	status = "okay";
+
+	partition@0 {
+		label = "u-boot";
+		reg = <0x0000000 0x180000>;
+		read-only;
+	};
+
+	partition@180000 {
+		label = "u-boot-env";
+		reg = <0x180000 0x20000>;
+	};
+
+	partition@200000 {
+		label = "uImage";
+		reg = <0x0200000 0x600000>;
+	};
+
+	partition@800000 {
+		label = "minirootfs";
+		reg = <0x0800000 0x1000000>;
+	};
+
+	partition@1800000 {
+		label = "jffs2";
+		reg = <0x1800000 0x6800000>;
+	};
+};
+
 &mdio {
 	status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood-nsa310-common.dtsi b/arch/arm/boot/dts/kirkwood-nsa310-common.dtsi
index 06267a9..e3f915d 100644
--- a/arch/arm/boot/dts/kirkwood-nsa310-common.dtsi
+++ b/arch/arm/boot/dts/kirkwood-nsa310-common.dtsi
@@ -27,49 +27,6 @@
 			nr-ports = <2>;
 		};
 
-		nand@3000000 {
-			status = "okay";
-			chip-delay = <35>;
-
-			partition@0 {
-				label = "uboot";
-				reg = <0x0000000 0x0100000>;
-				read-only;
-			};
-			partition@100000 {
-				label = "uboot_env";
-				reg = <0x0100000 0x0080000>;
-			};
-			partition@180000 {
-				label = "key_store";
-				reg = <0x0180000 0x0080000>;
-			};
-			partition@200000 {
-				label = "info";
-				reg = <0x0200000 0x0080000>;
-			};
-			partition@280000 {
-				label = "etc";
-				reg = <0x0280000 0x0a00000>;
-			};
-			partition@c80000 {
-				label = "kernel_1";
-				reg = <0x0c80000 0x0a00000>;
-			};
-			partition@1680000 {
-				label = "rootfs1";
-				reg = <0x1680000 0x2fc0000>;
-			};
-			partition@4640000 {
-				label = "kernel_2";
-				reg = <0x4640000 0x0a00000>;
-			};
-			partition@5040000 {
-				label = "rootfs2";
-				reg = <0x5040000 0x2fc0000>;
-			};
-		};
-
 		pcie-controller {
 			status = "okay";
 
@@ -105,3 +62,46 @@
 		};
 	};
 };
+
+&nand {
+	status = "okay";
+	chip-delay = <35>;
+
+	partition@0 {
+		label = "uboot";
+		reg = <0x0000000 0x0100000>;
+		read-only;
+	};
+	partition@100000 {
+		label = "uboot_env";
+		reg = <0x0100000 0x0080000>;
+	};
+	partition@180000 {
+		label = "key_store";
+		reg = <0x0180000 0x0080000>;
+	};
+	partition@200000 {
+		label = "info";
+		reg = <0x0200000 0x0080000>;
+	};
+	partition@280000 {
+		label = "etc";
+		reg = <0x0280000 0x0a00000>;
+	};
+	partition@c80000 {
+		label = "kernel_1";
+		reg = <0x0c80000 0x0a00000>;
+	};
+	partition@1680000 {
+		label = "rootfs1";
+		reg = <0x1680000 0x2fc0000>;
+	};
+	partition@4640000 {
+		label = "kernel_2";
+		reg = <0x4640000 0x0a00000>;
+	};
+	partition@5040000 {
+		label = "rootfs2";
+		reg = <0x5040000 0x2fc0000>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-nsa310.dts b/arch/arm/boot/dts/kirkwood-nsa310.dts
index 7aeae0c..b5418bc 100644
--- a/arch/arm/boot/dts/kirkwood-nsa310.dts
+++ b/arch/arm/boot/dts/kirkwood-nsa310.dts
@@ -15,7 +15,6 @@
 	};
 
 	mbus {
-		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000>;
 		pcie-controller {
 			status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood-openblocks_a6.dts b/arch/arm/boot/dts/kirkwood-openblocks_a6.dts
index 85ccf8d..f0e3d21 100644
--- a/arch/arm/boot/dts/kirkwood-openblocks_a6.dts
+++ b/arch/arm/boot/dts/kirkwood-openblocks_a6.dts
@@ -29,43 +29,6 @@
 			pinctrl-names = "default";
 		};
 
-		nand@3000000 {
-			chip-delay = <25>;
-			status = "okay";
-			pinctrl-0 = <&pmx_nand>;
-			pinctrl-names = "default";
-
-			partition@0 {
-				label = "uboot";
-				reg = <0x0 0x90000>;
-			};
-
-			partition@90000 {
-				label = "env";
-				reg = <0x90000 0x44000>;
-			};
-
-			partition@d4000 {
-				label = "test";
-				reg = <0xd4000 0x24000>;
-			};
-
-			partition@f4000 {
-				label = "conf";
-				reg = <0xf4000 0x400000>;
-			};
-
-			partition@4f4000 {
-				label = "linux";
-				reg = <0x4f4000 0x1d20000>;
-			};
-
-			partition@2214000 {
-				label = "user";
-				reg = <0x2214000 0x1dec000>;
-			};
-		};
-
 		sata@80000 {
 			nr-ports = <1>;
 			status = "okay";
@@ -167,6 +130,43 @@
 	};
 };
 
+&nand {
+	chip-delay = <25>;
+	status = "okay";
+	pinctrl-0 = <&pmx_nand>;
+	pinctrl-names = "default";
+
+	partition@0 {
+		label = "uboot";
+		reg = <0x0 0x90000>;
+	};
+
+	partition@90000 {
+		label = "env";
+		reg = <0x90000 0x44000>;
+	};
+
+	partition@d4000 {
+		label = "test";
+		reg = <0xd4000 0x24000>;
+	};
+
+	partition@f4000 {
+		label = "conf";
+		reg = <0xf4000 0x400000>;
+	};
+
+	partition@4f4000 {
+		label = "linux";
+		reg = <0x4f4000 0x1d20000>;
+	};
+
+	partition@2214000 {
+		label = "user";
+		reg = <0x2214000 0x1dec000>;
+	};
+};
+
 &mdio {
 	status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood-openblocks_a7.dts b/arch/arm/boot/dts/kirkwood-openblocks_a7.dts
new file mode 100644
index 0000000..851fb2a
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-openblocks_a7.dts
@@ -0,0 +1,223 @@
+/*
+ * Device Tree file for OpenBlocks A7 board
+ *
+ * Copyright (C) 2013 Free Electrons
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+/dts-v1/;
+
+#include "kirkwood.dtsi"
+#include "kirkwood-6282.dtsi"
+
+/ {
+	model = "Plat'Home OpenBlocksA7";
+	compatible = "plathome,openblocks-a7", "marvell,kirkwood-88f6283", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x40000000>; /* 1 GB */
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8 earlyprintk";
+	};
+
+	ocp@f1000000 {
+		serial@12000 {
+			status = "ok";
+			pinctrl-0 = <&pmx_uart0>;
+			pinctrl-names = "default";
+		};
+
+		serial@12100 {
+			status = "ok";
+			pinctrl-0 = <&pmx_uart1>;
+			pinctrl-names = "default";
+		};
+
+		sata@80000 {
+			nr-ports = <1>;
+			status = "okay";
+		};
+
+		i2c@11100 {
+			status = "okay";
+			pinctrl-0 = <&pmx_twsi1>;
+			pinctrl-names = "default";
+
+			s24c02: s24c02@50 {
+				compatible = "24c02";
+				reg = <0x50>;
+			};
+		};
+
+		pinctrl: pinctrl@10000 {
+			pinctrl-0 = <&pmx_dip_switches &pmx_gpio_header>;
+			pinctrl-names = "default";
+
+			pmx_uart0: pmx-uart0 {
+				marvell,pins = "mpp10", "mpp11", "mpp15",
+					"mpp16";
+				marvell,function = "uart0";
+			};
+
+			pmx_uart1: pmx-uart1 {
+				marvell,pins = "mpp13", "mpp14", "mpp8",
+					"mpp9";
+				marvell,function = "uart1";
+			};
+
+			pmx_sysrst: pmx-sysrst {
+				marvell,pins = "mpp6";
+				marvell,function = "sysrst";
+			};
+
+			pmx_dip_switches: pmx-dip-switches {
+				marvell,pins = "mpp44", "mpp45", "mpp46", "mpp47";
+				marvell,function = "gpio";
+			};
+
+			/*
+			 * Accessible on connector J202. The MPP
+			 * listed below are pin 1-7, pin 8 is unused,
+			 * pin 9 is external reset input and pin 10 is
+			 * ground.
+			 */
+			pmx_gpio_header: pmx-gpio-header {
+				marvell,pins = "mpp17", "mpp7", "mpp29", "mpp28",
+					       "mpp35", "mpp34", "mpp40";
+				marvell,function = "gpio";
+			};
+
+			pmx_gpio_init: pmx-init {
+				marvell,pins = "mpp38";
+				marvell,function = "gpio";
+			};
+
+			pmx_usb_oc: pmx-usb-oc {
+				marvell,pins = "mpp39";
+				marvell,function = "gpio";
+			};
+
+			pmx_leds: pmx-leds {
+				marvell,pins = "mpp41", "mpp42", "mpp43";
+				marvell,function = "gpio";
+			};
+
+			pmx_ge1: pmx-ge1 {
+				marvell,pins = "mpp20", "mpp21", "mpp22", "mpp23",
+					       "mpp24", "mpp25", "mpp26", "mpp27",
+					       "mpp30", "mpp31", "mpp32", "mpp33";
+				marvell,function = "ge1";
+			};
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+		pinctrl-0 = <&pmx_leds>;
+		pinctrl-names = "default";
+
+		led-red {
+			label = "obsa7:red:stat";
+			gpios = <&gpio1 9 1>;
+		};
+
+		led-green {
+			label = "obsa7:green:stat";
+			gpios = <&gpio1 10 1>;
+		};
+
+		led-yellow {
+			label = "obsa7:yellow:stat";
+			gpios = <&gpio1 11 1>;
+		};
+        };
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		pinctrl-0 = <&pmx_gpio_init>;
+		pinctrl-names = "default";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		button@1 {
+			label = "Init Button";
+			linux,code = <116>;
+			gpios = <&gpio1 6 0>;
+		};
+	};
+};
+
+&nand {
+	chip-delay = <25>;
+	status = "okay";
+	pinctrl-0 = <&pmx_nand>;
+	pinctrl-names = "default";
+
+	partition@0 {
+		label = "uboot";
+		reg = <0x0 0x1c0000>;
+	};
+
+	partition@1c0000 {
+		label = "env";
+		reg = <0x1c0000 0x2c0000>;
+	};
+
+	partition@480000 {
+		label = "test";
+		reg = <0x480000 0x160000>;
+	};
+
+	partition@5e0000 {
+		label = "conf";
+		reg = <0x5e0000 0x540000>;
+	};
+
+	partition@b20000 {
+		label = "linux";
+		reg = <0xb20000 0x3d40000>;
+	};
+
+	partition@4860000 {
+		label = "user";
+		reg = <0x4860000 0xb7a0000>;
+	};
+};
+
+&mdio {
+	status = "okay";
+
+	ethphy0: ethernet-phy@0 {
+		device_type = "ethernet-phy";
+		reg = <0>;
+	};
+
+	ethphy1: ethernet-phy@1 {
+		device_type = "ethernet-phy";
+		reg = <1>;
+	};
+};
+
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		phy-handle = <&ethphy0>;
+	};
+};
+
+&eth1 {
+	status = "okay";
+	pinctrl-0 = <&pmx_ge1>;
+	pinctrl-names = "default";
+	ethernet1-port@0 {
+		phy-handle = <&ethphy1>;
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-sheevaplug-common.dtsi b/arch/arm/boot/dts/kirkwood-sheevaplug-common.dtsi
index 5696b63..1173d7f 100644
--- a/arch/arm/boot/dts/kirkwood-sheevaplug-common.dtsi
+++ b/arch/arm/boot/dts/kirkwood-sheevaplug-common.dtsi
@@ -48,27 +48,6 @@
 			pinctrl-names = "default";
 			status = "okay";
 		};
-
-		nand@3000000 {
-			pinctrl-0 = <&pmx_nand>;
-			pinctrl-names = "default";
-			status = "okay";
-
-			partition@0 {
-				label = "u-boot";
-				reg = <0x0000000 0x100000>;
-			};
-
-			partition@100000 {
-				label = "uImage";
-				reg = <0x0100000 0x400000>;
-			};
-
-			partition@500000 {
-				label = "root";
-				reg = <0x0500000 0x1fb00000>;
-			};
-		};
 	};
 
 	regulators {
@@ -92,6 +71,27 @@
 	};
 };
 
+&nand {
+	pinctrl-0 = <&pmx_nand>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	partition@0 {
+		label = "u-boot";
+		reg = <0x0000000 0x100000>;
+	};
+
+	partition@100000 {
+		label = "uImage";
+		reg = <0x0100000 0x400000>;
+	};
+
+	partition@500000 {
+		label = "root";
+		reg = <0x0500000 0x1fb00000>;
+	};
+};
+
 &mdio {
 	status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood-topkick.dts b/arch/arm/boot/dts/kirkwood-topkick.dts
index 30842b4..320da67 100644
--- a/arch/arm/boot/dts/kirkwood-topkick.dts
+++ b/arch/arm/boot/dts/kirkwood-topkick.dts
@@ -90,37 +90,6 @@
 			pinctrl-names = "default";
 		};
 
-		nand@3000000 {
-			status = "okay";
-			pinctrl-0 = <&pmx_nand>;
-			pinctrl-names = "default";
-
-			partition@0 {
-				label = "u-boot";
-				reg = <0x0000000 0x180000>;
-			};
-
-			partition@180000 {
-				label = "u-boot env";
-				reg = <0x0180000 0x20000>;
-			};
-
-			partition@200000 {
-				label = "uImage";
-				reg = <0x0200000 0x600000>;
-			};
-
-			partition@800000 {
-				label = "uInitrd";
-				reg = <0x0800000 0x1000000>;
-			};
-
-			partition@1800000 {
-				label = "rootfs";
-				reg = <0x1800000 0xe800000>;
-			};
-		};
-
 		sata@80000 {
 			status = "okay";
 			nr-ports = <1>;
@@ -204,6 +173,37 @@
 	};
 };
 
+&nand {
+	status = "okay";
+	pinctrl-0 = <&pmx_nand>;
+	pinctrl-names = "default";
+
+	partition@0 {
+		label = "u-boot";
+		reg = <0x0000000 0x180000>;
+	};
+
+	partition@180000 {
+		label = "u-boot env";
+		reg = <0x0180000 0x20000>;
+	};
+
+	partition@200000 {
+		label = "uImage";
+		reg = <0x0200000 0x600000>;
+	};
+
+	partition@800000 {
+		label = "uInitrd";
+		reg = <0x0800000 0x1000000>;
+	};
+
+	partition@1800000 {
+		label = "rootfs";
+		reg = <0x1800000 0xe800000>;
+	};
+};
+
 &mdio {
 	status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood-ts219-6282.dts b/arch/arm/boot/dts/kirkwood-ts219-6282.dts
index 9efcd2d..345562f 100644
--- a/arch/arm/boot/dts/kirkwood-ts219-6282.dts
+++ b/arch/arm/boot/dts/kirkwood-ts219-6282.dts
@@ -6,7 +6,6 @@
 
 / {
 	mbus {
-		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000>;
 		pcie-controller {
 			status = "okay";
 
diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/kirkwood.dtsi
index 1335b2e..8b73c80 100644
--- a/arch/arm/boot/dts/kirkwood.dtsi
+++ b/arch/arm/boot/dts/kirkwood.dtsi
@@ -28,16 +28,43 @@
 		compatible = "marvell,kirkwood-mbus", "simple-bus";
 		#address-cells = <2>;
 		#size-cells = <1>;
+		/* If a board file needs to change this ranges it must replace it completely */
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000	/* internal-regs */
+			  MBUS_ID(0x01, 0x2f) 0 0xf4000000 0x10000	/* nand flash */
+			  MBUS_ID(0x03, 0x01) 0 0xf5000000 0x10000	/* crypto sram */
+			  >;
 		controller = <&mbusc>;
 		pcie-mem-aperture = <0xe0000000 0x10000000>; /* 256 MiB memory space */
 		pcie-io-aperture  = <0xf2000000 0x100000>;   /*   1 MiB    I/O space */
+
+		crypto@0301 {
+			compatible = "marvell,orion-crypto";
+			reg = <MBUS_ID(0xf0, 0x01) 0x30000 0x10000>,
+			      <MBUS_ID(0x03, 0x01) 0 0x800>;
+			reg-names = "regs", "sram";
+			interrupts = <22>;
+			clocks = <&gate_clk 17>;
+			status = "okay";
+		};
+
+		nand: nand@012f {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			cle = <0>;
+			ale = <1>;
+			bank-width = <1>;
+			compatible = "marvell,orion-nand";
+			reg = <MBUS_ID(0x01, 0x2f) 0 0x400>;
+			chip-delay = <25>;
+			/* set partition map and/or chip-delay in board dts */
+			clocks = <&gate_clk 7>;
+			status = "disabled";
+		};
 	};
 
 	ocp@f1000000 {
 		compatible = "simple-bus";
-		ranges = <0x00000000 0xf1000000 0x0100000
-		          0xf4000000 0xf4000000 0x0000400
-		          0xf5000000 0xf5000000 0x0000400>;
+		ranges = <0x00000000 0xf1000000 0x0100000>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 
@@ -193,20 +220,6 @@
 			status = "okay";
 		};
 
-		nand@3000000 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			cle = <0>;
-			ale = <1>;
-			bank-width = <1>;
-			compatible = "marvell,orion-nand";
-			reg = <0xf4000000 0x400>;
-			chip-delay = <25>;
-			/* set partition map and/or chip-delay in board dts */
-			clocks = <&gate_clk 7>;
-			status = "disabled";
-		};
-
 		i2c@11000 {
 			compatible = "marvell,mv64xxx-i2c";
 			reg = <0x11000 0x20>;
@@ -218,16 +231,6 @@
 			status = "disabled";
 		};
 
-		crypto@30000 {
-			compatible = "marvell,orion-crypto";
-			reg = <0x30000 0x10000>,
-			      <0xf5000000 0x800>;
-			reg-names = "regs", "sram";
-			interrupts = <22>;
-			clocks = <&gate_clk 17>;
-			status = "okay";
-		};
-
 		mdio: mdio-bus@72004 {
 			compatible = "marvell,orion-mdio";
 			#address-cells = <1>;
diff --git a/arch/arm/boot/dts/mxs-pinfunc.h b/arch/arm/boot/dts/mxs-pinfunc.h
new file mode 100644
index 0000000..c6da987
--- /dev/null
+++ b/arch/arm/boot/dts/mxs-pinfunc.h
@@ -0,0 +1,31 @@
+/*
+ * Header providing constants for i.MX28 pinctrl bindings.
+ *
+ * Copyright (C) 2013 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __DT_BINDINGS_MXS_PINCTRL_H__
+#define __DT_BINDINGS_MXS_PINCTRL_H__
+
+/* fsl,drive-strength property */
+#define MXS_DRIVE_4mA		0
+#define MXS_DRIVE_8mA		1
+#define MXS_DRIVE_12mA		2
+#define MXS_DRIVE_16mA		3
+
+/* fsl,voltage property */
+#define MXS_VOLTAGE_LOW		0
+#define MXS_VOLTAGE_HIGH	1
+
+/* fsl,pull-up property */
+#define MXS_PULL_DISABLE	0
+#define MXS_PULL_ENABLE		1
+
+#endif /* __DT_BINDINGS_MXS_PINCTRL_H__ */
diff --git a/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi b/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi
new file mode 100644
index 0000000..9c18adf
--- /dev/null
+++ b/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi
@@ -0,0 +1,52 @@
+/*
+ * Common file for GPMC connected smsc911x on omaps
+ *
+ * Note that the board specifc DTS file needs to specify
+ * ranges, pinctrl, reg, interrupt parent and interrupts.
+ */
+
+/ {
+	vddvario: regulator-vddvario {
+		  compatible = "regulator-fixed";
+		  regulator-name = "vddvario";
+		  regulator-always-on;
+	};
+
+	vdd33a: regulator-vdd33a {
+		compatible = "regulator-fixed";
+		regulator-name = "vdd33a";
+		regulator-always-on;
+	};
+};
+
+&gpmc {
+	ethernet@gpmc {
+		compatible = "smsc,lan9221", "smsc,lan9115";
+		bank-width = <2>;
+		gpmc,mux-add-data;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <186>;
+		gpmc,cs-wr-off-ns = <186>;
+		gpmc,adv-on-ns = <12>;
+		gpmc,adv-rd-off-ns = <48>;
+		gpmc,adv-wr-off-ns = <48>;
+		gpmc,oe-on-ns = <54>;
+		gpmc,oe-off-ns = <168>;
+		gpmc,we-on-ns = <54>;
+		gpmc,we-off-ns = <168>;
+		gpmc,rd-cycle-ns = <186>;
+		gpmc,wr-cycle-ns = <186>;
+		gpmc,access-ns = <114>;
+		gpmc,page-burst-access-ns = <6>;
+		gpmc,bus-turnaround-ns = <12>;
+		gpmc,cycle2cycle-delay-ns = <18>;
+		gpmc,wr-data-mux-bus-ns = <90>;
+		gpmc,wr-access-ns = <186>;
+		gpmc,cycle2cycle-samecsen;
+		gpmc,cycle2cycle-diffcsen;
+		vmmc-supply = <&vddvario>;
+		vmmc_aux-supply = <&vdd33a>;
+		reg-io-width = <4>;
+		smsc,save-mac-address;
+	};
+};
diff --git a/arch/arm/boot/dts/omap-zoom-common.dtsi b/arch/arm/boot/dts/omap-zoom-common.dtsi
new file mode 100644
index 0000000..b0ee342
--- /dev/null
+++ b/arch/arm/boot/dts/omap-zoom-common.dtsi
@@ -0,0 +1,33 @@
+/*
+ * Common features on the Zoom debug board
+ */
+
+#include "omap-gpmc-smsc911x.dtsi"
+
+&gpmc {
+	ranges = <3 0 0x10000000 0x00000400>,
+		 <7 0 0x2c000000 0x01000000>;
+
+	/*
+	 * Four port TL16CP754C serial port on GPMC,
+	 * they probably share the same GPIO IRQ
+	 * REVISIT: Add timing support from slls644g.pdf
+	 */
+	8250@3,0 {
+		compatible = "ns16550a";
+		reg = <3 0 0x100>;
+		bank-width = <2>;
+		reg-shift = <1>;
+		reg-io-width = <1>;
+		interrupt-parent = <&gpio4>;
+		interrupts = <6 IRQ_TYPE_EDGE_RISING>;	/* gpio102 */
+		clock-frequency = <1843200>;
+		current-speed = <115200>;
+	};
+
+	ethernet@gpmc {
+		reg = <7 0 0xff>;
+		interrupt-parent = <&gpio5>;
+		interrupts = <30 IRQ_TYPE_LEVEL_LOW>;	/* gpio158 */
+	};
+};
diff --git a/arch/arm/boot/dts/omap2420-h4.dts b/arch/arm/boot/dts/omap2420-h4.dts
index 224c08f..34cdecb 100644
--- a/arch/arm/boot/dts/omap2420-h4.dts
+++ b/arch/arm/boot/dts/omap2420-h4.dts
@@ -50,15 +50,15 @@
 			label = "bootloader";
 			reg = <0 0x20000>;
 		};
-		partition@0x20000 {
+		partition@20000 {
 			label = "params";
 			reg = <0x20000 0x20000>;
 		};
-		partition@0x40000 {
+		partition@40000 {
 			label = "kernel";
 			reg = <0x40000 0x200000>;
 		};
-		partition@0x240000 {
+		partition@240000 {
 			label = "file-system";
 			reg = <0x240000 0x3dc0000>;
 		};
diff --git a/arch/arm/boot/dts/omap3-beagle-xm.dts b/arch/arm/boot/dts/omap3-beagle-xm.dts
index 0c514dc..31a632f 100644
--- a/arch/arm/boot/dts/omap3-beagle-xm.dts
+++ b/arch/arm/boot/dts/omap3-beagle-xm.dts
@@ -11,7 +11,7 @@
 
 / {
 	model = "TI OMAP3 BeagleBoard xM";
-	compatible = "ti,omap3-beagle-xm", "ti,omap3-beagle", "ti,omap3";
+	compatible = "ti,omap3-beagle-xm", "ti,omap36xx", "ti,omap3";
 
 	cpus {
 		cpu@0 {
@@ -69,6 +69,23 @@
 		};
 
 	};
+
+	/* HS USB Port 2 Power */
+	hsusb2_power: hsusb2_power_reg {
+		compatible = "regulator-fixed";
+		regulator-name = "hsusb2_vbus";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&twl_gpio 18 0>;	/* GPIO LEDA */
+		startup-delay-us = <70000>;
+	};
+
+	/* HS USB Host PHY on PORT 2 */
+	hsusb2_phy: hsusb2_phy {
+		compatible = "usb-nop-xceiv";
+		reset-gpios = <&gpio5 19 GPIO_ACTIVE_LOW>; /* gpio_147 */
+		vcc-supply = <&hsusb2_power>;
+	};
 };
 
 &omap3_pmx_wkup {
@@ -79,6 +96,37 @@
 	};
 };
 
+&omap3_pmx_core {
+	pinctrl-names = "default";
+	pinctrl-0 = <
+			&hsusbb2_pins
+	>;
+
+	uart3_pins: pinmux_uart3_pins {
+		pinctrl-single,pins = <
+			0x16e (PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */
+			0x170 (PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx OUTPUT | MODE0 */
+		>;
+	};
+
+	hsusbb2_pins: pinmux_hsusbb2_pins {
+		pinctrl-single,pins = <
+			0x5c0 (PIN_OUTPUT | MUX_MODE3)		/* etk_d10.hsusb2_clk */
+			0x5c2 (PIN_OUTPUT | MUX_MODE3)		/* etk_d11.hsusb2_stp */
+			0x5c4 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d12.hsusb2_dir */
+			0x5c6 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d13.hsusb2_nxt */
+			0x5c8 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d14.hsusb2_data0 */
+			0x5cA (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d15.hsusb2_data1 */
+			0x1a4 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcspi1_cs3.hsusb2_data2 */
+			0x1a6 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcspi2_clk.hsusb2_data7 */
+			0x1a8 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcspi2_simo.hsusb2_data4 */
+			0x1aa (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcspi2_somi.hsusb2_data5 */
+			0x1ac (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcspi2_cs0.hsusb2_data6 */
+			0x1ae (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcspi2_cs1.hsusb2_data3 */
+		>;
+	};
+};
+
 &i2c1 {
 	clock-frequency = <2600000>;
 
@@ -144,19 +192,12 @@
 &usb_otg_hs {
 	interface-type = <0>;
 	usb-phy = <&usb2_phy>;
+	phys = <&usb2_phy>;
+	phy-names = "usb2-phy";
 	mode = <3>;
 	power = <50>;
 };
 
-&omap3_pmx_core {
-	uart3_pins: pinmux_uart3_pins {
-		pinctrl-single,pins = <
-			0x16e (PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */
-			0x170 (PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx OUTPUT | MODE0 */
-		>;
-	};
-};
-
 &uart3 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart3_pins>;
@@ -166,3 +207,11 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&gpio1_pins>;
 };
+
+&usbhshost {
+	port2-mode = "ehci-phy";
+};
+
+&usbhsehci {
+	phys = <0 &hsusb2_phy>;
+};
diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts
index dfd8310..fa532aa 100644
--- a/arch/arm/boot/dts/omap3-beagle.dts
+++ b/arch/arm/boot/dts/omap3-beagle.dts
@@ -44,17 +44,6 @@
 		};
 	};
 
-	/* HS USB Port 2 RESET */
-	hsusb2_reset: hsusb2_reset_reg {
-		compatible = "regulator-fixed";
-		regulator-name = "hsusb2_reset";
-		regulator-min-microvolt = <3300000>;
-		regulator-max-microvolt = <3300000>;
-		gpio = <&gpio5 19 0>;	/* gpio_147 */
-		startup-delay-us = <70000>;
-		enable-active-high;
-	};
-
 	/* HS USB Port 2 Power */
 	hsusb2_power: hsusb2_power_reg {
 		compatible = "regulator-fixed";
@@ -68,7 +57,7 @@
 	/* HS USB Host PHY on PORT 2 */
 	hsusb2_phy: hsusb2_phy {
 		compatible = "usb-nop-xceiv";
-		reset-supply = <&hsusb2_reset>;
+		reset-gpios = <&gpio5 19 GPIO_ACTIVE_LOW>;	/* gpio_147 */
 		vcc-supply = <&hsusb2_power>;
 	};
 
@@ -101,18 +90,18 @@
 
 	hsusbb2_pins: pinmux_hsusbb2_pins {
 		pinctrl-single,pins = <
-			0x5c0 (PIN_OUTPUT | MUX_MODE3)		/* usbb2_ulpitll_clk.usbb1_ulpiphy_clk */
-			0x5c2 (PIN_OUTPUT | MUX_MODE3)		/* usbb2_ulpitll_clk.usbb1_ulpiphy_stp */
-			0x5c4 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* usbb2_ulpitll_clk.usbb1_ulpiphy_dir */
-			0x5c6 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* usbb2_ulpitll_clk.usbb1_ulpiphy_nxt */
-			0x5c8 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* usbb2_ulpitll_clk.usbb1_ulpiphy_dat0 */
-			0x5cA (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* usbb2_ulpitll_clk.usbb1_ulpiphy_dat1 */
-			0x1a4 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* usbb2_ulpitll_clk.usbb1_ulpiphy_dat2 */
-			0x1a6 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* usbb2_ulpitll_clk.usbb1_ulpiphy_dat3 */
-			0x1a8 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* usbb2_ulpitll_clk.usbb1_ulpiphy_dat4 */
-			0x1aa (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* usbb2_ulpitll_clk.usbb1_ulpiphy_dat5 */
-			0x1ac (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* usbb2_ulpitll_clk.usbb1_ulpiphy_dat6 */
-			0x1ae (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* usbb2_ulpitll_clk.usbb1_ulpiphy_dat7 */
+			0x5c0 (PIN_OUTPUT | MUX_MODE3)		/* etk_d10.hsusb2_clk */
+			0x5c2 (PIN_OUTPUT | MUX_MODE3)		/* etk_d11.hsusb2_stp */
+			0x5c4 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d12.hsusb2_dir */
+			0x5c6 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d13.hsusb2_nxt */
+			0x5c8 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d14.hsusb2_data0 */
+			0x5cA (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d15.hsusb2_data1 */
+			0x1a4 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcspi1_cs3.hsusb2_data2 */
+			0x1a6 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcspi2_clk.hsusb2_data7 */
+			0x1a8 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcspi2_simo.hsusb2_data4 */
+			0x1aa (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcspi2_somi.hsusb2_data5 */
+			0x1ac (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcspi2_cs0.hsusb2_data6 */
+			0x1ae (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcspi2_cs1.hsusb2_data3 */
 		>;
 	};
 
@@ -180,3 +169,12 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&gpio1_pins>;
 };
+
+&usb_otg_hs {
+	interface-type = <0>;
+	usb-phy = <&usb2_phy>;
+	phys = <&usb2_phy>;
+	phy-names = "usb2-phy";
+	mode = <3>;
+	power = <50>;
+};
diff --git a/arch/arm/boot/dts/omap3-devkit8000.dts b/arch/arm/boot/dts/omap3-devkit8000.dts
index 7ef2827..4665421 100644
--- a/arch/arm/boot/dts/omap3-devkit8000.dts
+++ b/arch/arm/boot/dts/omap3-devkit8000.dts
@@ -125,7 +125,7 @@
 		nand-bus-width = <16>;
 
 		gpmc,device-nand;
-		gpmc,sync-clki-ps = <0>;
+		gpmc,sync-clk-ps = <0>;
 		gpmc,cs-on-ns = <0>;
 		gpmc,cs-rd-off-ns = <44>;
 		gpmc,cs-wr-off-ns = <44>;
diff --git a/arch/arm/boot/dts/omap3-evm-37xx.dts b/arch/arm/boot/dts/omap3-evm-37xx.dts
new file mode 100644
index 0000000..4df68ad
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-evm-37xx.dts
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "omap36xx.dtsi"
+#include "omap3-evm-common.dtsi"
+
+
+/ {
+	model = "TI OMAP37XX EVM (TMDSEVM3730)";
+	compatible = "ti,omap3-evm-37xx", "ti,omap36xx";
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	wl12xx_vmmc: wl12xx_vmmc {
+		pinctrl-names = "default";
+		pinctrl-0 = <&wl12xx_gpio>;
+	};
+};
+
+&omap3_pmx_core {
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			0x114 (PIN_OUTPUT_PULLUP | MUX_MODE0)	/* sdmmc1_clk.sdmmc1_clk */
+			0x116 (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_cmd.sdmmc1_cmd */
+			0x118 (PIN_INPUT_PULLUP | MUX_MODE0) 	/* sdmmc1_dat0.sdmmc1_dat0 */
+			0x11a (PIN_INPUT_PULLUP | MUX_MODE0) 	/* sdmmc1_dat1.sdmmc1_dat1 */
+			0x11c (PIN_INPUT_PULLUP | MUX_MODE0) 	/* sdmmc1_dat2.sdmmc1_dat2 */
+			0x11e (PIN_INPUT_PULLUP | MUX_MODE0) 	/* sdmmc1_dat3.sdmmc1_dat3 */
+			0x120 (PIN_INPUT_PULLUP | MUX_MODE0) 	/* sdmmc1_dat4.sdmmc1_dat4 */
+			0x122 (PIN_INPUT_PULLUP | MUX_MODE0) 	/* sdmmc1_dat5.sdmmc1_dat5 */
+			0x124 (PIN_INPUT_PULLUP | MUX_MODE0) 	/* sdmmc1_dat6.sdmmc1_dat6 */
+			0x126 (PIN_INPUT_PULLUP | MUX_MODE0) 	/* sdmmc1_dat7.sdmmc1_dat7 */
+		>;
+	};
+
+	/* NOTE: Clocked externally, needs INPUT also for sdmmc2_clk.sdmmc2_clk */
+	mmc2_pins: pinmux_mmc2_pins {
+		pinctrl-single,pins = <
+			0x128 (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_clk.sdmmc2_clk */
+			0x12a (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_cmd.sdmmc2_cmd */
+			0x12c (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_dat0.sdmmc2_dat0 */
+			0x12e (WAKEUP_EN | PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat1.sdmmc2_dat1 */
+			0x130 (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_dat2.sdmmc2_dat2 */
+			0x132 (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_dat3.sdmmc2_dat3 */
+		>;
+	};
+
+	uart3_pins: pinmux_uart3_pins {
+		pinctrl-single,pins = <
+			0x16e (WAKEUP_EN | PIN_INPUT | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */
+			0x170 (PIN_OUTPUT | MUX_MODE0)		/* uart3_tx_irtx.uart3_tx_irtx */
+		>;
+	};
+
+	wl12xx_gpio: pinmux_wl12xx_gpio {
+		pinctrl-single,pins = <
+			0x150 (PIN_OUTPUT | MUX_MODE4)		/* uart1_cts.gpio_150 */
+			0x14e (PIN_INPUT | MUX_MODE4)		/* uart1_rts.gpio_149 */
+		>;
+	};
+
+	smsc911x_pins: pinmux_smsc911x_pins {
+		pinctrl-single,pins = <
+			0x1a2 (PIN_INPUT | MUX_MODE4)		/* mcspi1_cs2.gpio_176 */
+		>;
+	};
+};
+
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+};
+
+&mmc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins>;
+};
+
+&mmc3 {
+	status = "disabled";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins>;
+};
+
+&gpmc {
+	ranges = <0 0 0x00000000 0x20000000>,
+		 <5 0 0x2c000000 0x01000000>;
+
+	nand@0,0 {
+		linux,mtd-name= "hynix,h8kds0un0mer-4em";
+		reg = <0 0 0>;
+		nand-bus-width = <16>;
+		ti,nand-ecc-opt = "bch8";
+
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <44>;
+		gpmc,cs-wr-off-ns = <44>;
+		gpmc,adv-on-ns = <6>;
+		gpmc,adv-rd-off-ns = <34>;
+		gpmc,adv-wr-off-ns = <44>;
+		gpmc,we-off-ns = <40>;
+		gpmc,oe-off-ns = <54>;
+		gpmc,access-ns = <64>;
+		gpmc,rd-cycle-ns = <82>;
+		gpmc,wr-cycle-ns = <82>;
+		gpmc,wr-access-ns = <40>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		partition@0 {
+			label = "X-Loader";
+			reg = <0 0x80000>;
+		};
+		partition@0x80000 {
+			label = "U-Boot";
+			reg = <0x80000 0x1c0000>;
+		};
+		partition@0x1c0000 {
+			label = "Environment";
+			reg = <0x240000 0x40000>;
+		};
+		partition@0x280000 {
+			label = "Kernel";
+			reg = <0x280000 0x500000>;
+		};
+		partition@0x780000 {
+			label = "Filesystem";
+			reg = <0x780000 0x1f880000>;
+		};
+	};
+
+	ethernet@gpmc {
+		pinctrl-names = "default";
+		pinctrl-0 = <&smsc911x_pins>;
+	};
+};
diff --git a/arch/arm/boot/dts/omap3-evm-common.dtsi b/arch/arm/boot/dts/omap3-evm-common.dtsi
new file mode 100644
index 0000000..3007e79
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-evm-common.dtsi
@@ -0,0 +1,96 @@
+/*
+ * Common support for omap3 EVM boards
+ */
+
+#include "omap-gpmc-smsc911x.dtsi"
+
+/ {
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&vcc>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		ledb {
+			label = "omap3evm::ledb";
+			gpios = <&twl_gpio 19 GPIO_ACTIVE_HIGH>; /* LEDB */
+			linux,default-trigger = "default-on";
+		};
+	};
+
+	wl12xx_vmmc: wl12xx_vmmc {
+		compatible = "regulator-fixed";
+		regulator-name = "vwl1271";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		gpio = <&gpio5 22 0>;	/* gpio150 */
+		startup-delay-us = <70000>;
+		enable-active-high;
+		vin-supply = <&vmmc2>;
+	};
+};
+
+&i2c1 {
+	clock-frequency = <2600000>;
+
+	twl: twl@48 {
+		reg = <0x48>;
+		interrupts = <7>; /* SYS_NIRQ cascaded to intc */
+		interrupt-parent = <&intc>;
+	};
+};
+
+#include "twl4030.dtsi"
+#include "twl4030_omap3.dtsi"
+
+&i2c2 {
+	clock-frequency = <400000>;
+};
+
+&i2c3 {
+	clock-frequency = <400000>;
+
+	/*
+	 * TVP5146 Video decoder-in for analog input support.
+	 */
+	tvp5146@5c {
+		compatible = "ti,tvp5146m2";
+		reg = <0x5c>;
+	};
+};
+
+&mmc1 {
+	vmmc-supply = <&vmmc1>;
+	vmmc_aux-supply = <&vsim>;
+	bus-width = <8>;
+};
+
+&mmc2 {
+	vmmc-supply = <&wl12xx_vmmc>;
+	non-removable;
+	bus-width = <4>;
+	cap-power-off-card;
+};
+
+&twl_gpio {
+	ti,use-leds;
+};
+
+&usb_otg_hs {
+	interface-type = <0>;
+	usb-phy = <&usb2_phy>;
+	phys = <&usb2_phy>;
+	phy-names = "usb2-phy";
+	mode = <3>;
+	power = <50>;
+};
+
+&gpmc {
+	ethernet@gpmc {
+		interrupt-parent = <&gpio6>;
+		interrupts = <16 8>;
+		reg = <5 0 0xff>;
+	};
+};
diff --git a/arch/arm/boot/dts/omap3-evm.dts b/arch/arm/boot/dts/omap3-evm.dts
index 7d4329d..e10dcd0 100644
--- a/arch/arm/boot/dts/omap3-evm.dts
+++ b/arch/arm/boot/dts/omap3-evm.dts
@@ -8,68 +8,14 @@
 /dts-v1/;
 
 #include "omap34xx.dtsi"
+#include "omap3-evm-common.dtsi"
 
 / {
-	model = "TI OMAP3 EVM (OMAP3530, AM/DM37x)";
+	model = "TI OMAP35XX EVM (TMDSEVM3530)";
 	compatible = "ti,omap3-evm", "ti,omap3";
 
-	cpus {
-		cpu@0 {
-			cpu0-supply = <&vcc>;
-		};
-	};
-
 	memory {
 		device_type = "memory";
 		reg = <0x80000000 0x10000000>; /* 256 MB */
 	};
-
-	leds {
-		compatible = "gpio-leds";
-		ledb {
-			label = "omap3evm::ledb";
-			gpios = <&twl_gpio 19 GPIO_ACTIVE_HIGH>; /* LEDB */
-			linux,default-trigger = "default-on";
-		};
-	};
-};
-
-&i2c1 {
-	clock-frequency = <2600000>;
-
-	twl: twl@48 {
-		reg = <0x48>;
-		interrupts = <7>; /* SYS_NIRQ cascaded to intc */
-		interrupt-parent = <&intc>;
-	};
-};
-
-#include "twl4030.dtsi"
-#include "twl4030_omap3.dtsi"
-
-&i2c2 {
-	clock-frequency = <400000>;
-};
-
-&i2c3 {
-	clock-frequency = <400000>;
-
-	/*
-	 * TVP5146 Video decoder-in for analog input support.
-	 */
-	tvp5146@5c {
-		compatible = "ti,tvp5146m2";
-		reg = <0x5c>;
-	};
-};
-
-&twl_gpio {
-	ti,use-leds;
-};
-
-&usb_otg_hs {
-	interface-type = <0>;
-	usb-phy = <&usb2_phy>;
-	mode = <3>;
-	power = <50>;
 };
diff --git a/arch/arm/boot/dts/omap3-gta04.dts b/arch/arm/boot/dts/omap3-gta04.dts
new file mode 100644
index 0000000..b9b55c9
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-gta04.dts
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2013 Marek Belisko <marek@goldelico.com>
+ *
+ * Based on omap3-beagle-xm.dts
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "omap36xx.dtsi"
+
+/ {
+	model = "OMAP3 GTA04";
+	compatible = "ti,omap3-gta04", "ti,omap3";
+
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&vcc>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>; /* 512 MB */
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		aux-button {
+			label = "aux";
+			linux,code = <169>;
+			gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
+			gpio-key,wakeup;
+		};
+	};
+};
+
+&omap3_pmx_core {
+	uart1_pins: pinmux_uart1_pins {
+		pinctrl-single,pins = <
+			0x152 (PIN_INPUT | MUX_MODE0)		/* uart1_rx.uart1_rx */
+			0x14c (PIN_OUTPUT |MUX_MODE0)		/* uart1_tx.uart1_tx */
+		>;
+	};
+
+	uart2_pins: pinmux_uart2_pins {
+		pinctrl-single,pins = <
+			0x14a (PIN_INPUT | MUX_MODE0)		/* uart2_rx.uart2_rx */
+			0x148 (PIN_OUTPUT | MUX_MODE0)		/* uart2_tx.uart2_tx */
+		>;
+	};
+
+	uart3_pins: pinmux_uart3_pins {
+		pinctrl-single,pins = <
+			0x16e (PIN_INPUT | MUX_MODE0)		/* uart3_rx.uart3_rx */
+			0x170 (PIN_OUTPUT | MUX_MODE0)		/* uart3_tx.uart3_tx */
+		>;
+	};
+
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			0x114 (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_clk.sdmmc1_clk */
+			0x116 (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_cmd.sdmmc1_cmd */
+			0x118 (PIN_INPUT_PULLUP | MUX_MODE0) 	/* sdmmc1_dat0.sdmmc1_dat0 */
+			0x11a (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_dat1.sdmmc1_dat1 */
+			0x11c (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_dat2.sdmmc1_dat2 */
+			0x11e (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_dat3.sdmmc1_dat3 */
+		>;
+	};
+};
+
+&i2c1 {
+	clock-frequency = <2600000>;
+
+	twl: twl@48 {
+		reg = <0x48>;
+		interrupts = <7>; /* SYS_NIRQ cascaded to intc */
+		interrupt-parent = <&intc>;
+	};
+};
+
+#include "twl4030.dtsi"
+#include "twl4030_omap3.dtsi"
+
+&i2c2 {
+	clock-frequency = <400000>;
+
+	/* pressure sensor */
+	bmp085@77 {
+		compatible = "bosch,bmp085";
+		reg = <0x77>;
+	};
+
+	/* leds */
+	tca6507@45 {
+		compatible = "ti,tca6507";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x45>;
+
+		gta04_led0: red_aux@0 {
+			label = "gta04:red:aux";
+			reg = <0x0>;
+		};
+
+		gta04_led1: green_aux@1 {
+			label = "gta04:green:aux";
+			reg = <0x1>;
+		};
+
+		gta04_led3: red_power@3 {
+			label = "gta04:red:power";
+			reg = <0x3>;
+			linux,default-trigger = "default-on";
+		};
+
+		gta04_led4: green_power@4 {
+			label = "gta04:green:power";
+			reg = <0x4>;
+		};
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+};
+
+&usb_otg_hs {
+	interface-type = <0>;
+	usb-phy = <&usb2_phy>;
+	phys = <&usb2_phy>;
+	phy-names = "usb2-phy";
+	mode = <3>;
+	power = <50>;
+};
+
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	vmmc-supply = <&vmmc1>;
+	vmmc_aux-supply = <&vsim>;
+	bus-width = <4>;
+};
+
+&mmc2 {
+	status = "disabled";
+};
+
+&mmc3 {
+	status = "disabled";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_pins>;
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins>;
+};
+
diff --git a/arch/arm/boot/dts/omap3-igep.dtsi b/arch/arm/boot/dts/omap3-igep.dtsi
index 2326d11..ba1e58b 100644
--- a/arch/arm/boot/dts/omap3-igep.dtsi
+++ b/arch/arm/boot/dts/omap3-igep.dtsi
@@ -77,6 +77,8 @@
 			0x1a2 (PIN_INPUT | MUX_MODE4)		/* mcspi1_cs2.gpio_176 */
 		>;
 	};
+
+	leds_pins: pinmux_leds_pins { };
 };
 
 &i2c1 {
@@ -141,3 +143,12 @@
 &twl_gpio {
 	ti,use-leds;
 };
+
+&usb_otg_hs {
+	interface-type = <0>;
+	usb-phy = <&usb2_phy>;
+	phys = <&usb2_phy>;
+	phy-names = "usb2-phy";
+	mode = <3>;
+	power = <50>;
+};
diff --git a/arch/arm/boot/dts/omap3-igep0020.dts b/arch/arm/boot/dts/omap3-igep0020.dts
index e8c4828..d5cc792 100644
--- a/arch/arm/boot/dts/omap3-igep0020.dts
+++ b/arch/arm/boot/dts/omap3-igep0020.dts
@@ -10,13 +10,17 @@
  */
 
 #include "omap3-igep.dtsi"
+#include "omap-gpmc-smsc911x.dtsi"
 
 / {
 	model = "IGEPv2";
 	compatible = "isee,omap3-igep0020", "ti,omap3";
 
 	leds {
+		pinctrl-names = "default";
+		pinctrl-0 = <&leds_pins>;
 		compatible = "gpio-leds";
+
 		boot {
 			 label = "omap3:green:boot";
 			 gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>;
@@ -41,19 +45,56 @@
 		};
 	};
 
-	vddvario: regulator-vddvario {
-		  compatible = "regulator-fixed";
-		  regulator-name = "vddvario";
-		  regulator-always-on;
-	};
+       /* HS USB Port 1 Power */
+       hsusb1_power: hsusb1_power_reg {
+               compatible = "regulator-fixed";
+               regulator-name = "hsusb1_vbus";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&twl_gpio 18 GPIO_ACTIVE_LOW>;	/* GPIO LEDA */
+               startup-delay-us = <70000>;
+       };
 
-	vdd33a: regulator-vdd33a {
-		compatible = "regulator-fixed";
-		regulator-name = "vdd33a";
-		regulator-always-on;
+	/* HS USB Host PHY on PORT 1 */
+	hsusb1_phy: hsusb1_phy {
+		compatible = "usb-nop-xceiv";
+		reset-gpios = <&gpio1 24 GPIO_ACTIVE_LOW>; /* gpio_24 */
+		vcc-supply = <&hsusb1_power>;
 	};
 };
 
+&omap3_pmx_core {
+	pinctrl-names = "default";
+	pinctrl-0 = <
+		&hsusbb1_pins
+	>;
+
+	hsusbb1_pins: pinmux_hsusbb1_pins {
+		pinctrl-single,pins = <
+			0x5aa (PIN_OUTPUT | MUX_MODE3)		/* etk_ctl.hsusb1_clk */
+			0x5a8 (PIN_OUTPUT | MUX_MODE3)		/* etk_clk.hsusb1_stp */
+			0x5bc (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d8.hsusb1_dir */
+			0x5be (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d9.hsusb1_nxt */
+			0x5ac (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d0.hsusb1_data0 */
+			0x5ae (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d1.hsusb1_data1 */
+			0x5b0 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d2.hsusb1_data2 */
+			0x5b2 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d3.hsusb1_data7 */
+			0x5b4 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d4.hsusb1_data4 */
+			0x5b6 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d5.hsusb1_data5 */
+			0x5b8 (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d6.hsusb1_data6 */
+			0x5ba (PIN_INPUT_PULLDOWN | MUX_MODE3)	/* etk_d7.hsusb1_data3 */
+		>;
+	};
+};
+
+&leds_pins {
+	pinctrl-single,pins = <
+		0x5c4 (PIN_OUTPUT | MUX_MODE4) /* etk_d12.gpio_26 */
+		0x5c6 (PIN_OUTPUT | MUX_MODE4) /* etk_d13.gpio_27 */
+		0x5c8 (PIN_OUTPUT | MUX_MODE4) /* etk_d14.gpio_28 */
+	>;
+};
+
 &i2c3 {
 	clock-frequency = <100000>;
 
@@ -99,59 +140,37 @@
 			label = "SPL";
 			reg = <0 0x100000>;
 		};
-		partition@0x80000 {
+		partition@80000 {
 			label = "U-Boot";
 			reg = <0x100000 0x180000>;
 		};
-		partition@0x1c0000 {
+		partition@1c0000 {
 			label = "Environment";
 			reg = <0x280000 0x100000>;
 		};
-		partition@0x280000 {
+		partition@280000 {
 			label = "Kernel";
 			reg = <0x380000 0x300000>;
 		};
-		partition@0x780000 {
+		partition@780000 {
 			label = "Filesystem";
 			reg = <0x680000 0x1f980000>;
 		};
 	};
 
-	ethernet@5,0 {
+	ethernet@gpmc {
 		pinctrl-names = "default";
 		pinctrl-0 = <&smsc911x_pins>;
-		compatible = "smsc,lan9221", "smsc,lan9115";
 		reg = <5 0 0xff>;
-		bank-width = <2>;
-
-		gpmc,mux-add-data;
-		gpmc,cs-on-ns = <0>;
-		gpmc,cs-rd-off-ns = <186>;
-		gpmc,cs-wr-off-ns = <186>;
-		gpmc,adv-on-ns = <12>;
-		gpmc,adv-rd-off-ns = <48>;
-		gpmc,adv-wr-off-ns = <48>;
-		gpmc,oe-on-ns = <54>;
-		gpmc,oe-off-ns = <168>;
-		gpmc,we-on-ns = <54>;
-		gpmc,we-off-ns = <168>;
-		gpmc,rd-cycle-ns = <186>;
-		gpmc,wr-cycle-ns = <186>;
-		gpmc,access-ns = <114>;
-		gpmc,page-burst-access-ns = <6>;
-		gpmc,bus-turnaround-ns = <12>;
-		gpmc,cycle2cycle-delay-ns = <18>;
-		gpmc,wr-data-mux-bus-ns = <90>;
-		gpmc,wr-access-ns = <186>;
-		gpmc,cycle2cycle-samecsen;
-		gpmc,cycle2cycle-diffcsen;
-
 		interrupt-parent = <&gpio6>;
-		interrupts = <16 8>;
-		vmmc-supply = <&vddvario>;
-		vmmc_aux-supply = <&vdd33a>;
-		reg-io-width = <4>;
-
-		smsc,save-mac-address;
+		interrupts = <16 IRQ_TYPE_LEVEL_LOW>;
 	};
 };
+
+&usbhshost {
+	port1-mode = "ehci-phy";
+};
+
+&usbhsehci {
+	phys = <&hsusb1_phy>;
+};
diff --git a/arch/arm/boot/dts/omap3-igep0030.dts b/arch/arm/boot/dts/omap3-igep0030.dts
index 644d053..525e6d9 100644
--- a/arch/arm/boot/dts/omap3-igep0030.dts
+++ b/arch/arm/boot/dts/omap3-igep0030.dts
@@ -16,7 +16,10 @@
 	compatible = "isee,omap3-igep0030", "ti,omap3";
 
 	leds {
+		pinctrl-names = "default";
+		pinctrl-0 = <&leds_pins>;
 		compatible = "gpio-leds";
+
 		boot {
 			 label = "omap3:green:boot";
 			 gpios = <&twl_gpio 13 GPIO_ACTIVE_LOW>;
@@ -43,6 +46,12 @@
 	};
 };
 
+&leds_pins {
+	pinctrl-single,pins = <
+		0x5b0 (PIN_OUTPUT | MUX_MODE4) /* etk_d2.gpio_16 */
+	>;
+};
+
 &gpmc {
 	ranges = <0 0 0x00000000 0x20000000>;
 
@@ -74,19 +83,19 @@
 			label = "SPL";
 			reg = <0 0x100000>;
 		};
-		partition@0x80000 {
+		partition@80000 {
 			label = "U-Boot";
 			reg = <0x100000 0x180000>;
 		};
-		partition@0x1c0000 {
+		partition@1c0000 {
 			label = "Environment";
 			reg = <0x280000 0x100000>;
 		};
-		partition@0x280000 {
+		partition@280000 {
 			label = "Kernel";
 			reg = <0x380000 0x300000>;
 		};
-		partition@0x780000 {
+		partition@780000 {
 			label = "Filesystem";
 			reg = <0x680000 0x1f980000>;
 		};
diff --git a/arch/arm/boot/dts/omap3-n9.dts b/arch/arm/boot/dts/omap3-n9.dts
new file mode 100644
index 0000000..39828ce
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-n9.dts
@@ -0,0 +1,18 @@
+/*
+ * omap3-n9.dts - Device Tree file for Nokia N9
+ *
+ * Written by: Aaro Koskinen <aaro.koskinen@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+#include "omap3-n950-n9.dtsi"
+
+/ {
+	model = "Nokia N9";
+	compatible = "nokia,omap3-n9", "ti,omap3";
+};
diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts
new file mode 100644
index 0000000..c4f20bf
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-n900.dts
@@ -0,0 +1,484 @@
+/*
+ * Copyright (C) 2013 Pavel Machek <pavel@ucw.cz>
+ * Copyright 2013 Aaro Koskinen <aaro.koskinen@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 (or later) as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+#include "omap34xx.dtsi"
+
+/ {
+	model = "Nokia N900";
+	compatible = "nokia,omap3-n900", "ti,omap3";
+
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&vcc>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+
+		camera_lens_cover {
+			label = "Camera Lens Cover";
+			gpios = <&gpio4 14 GPIO_ACTIVE_LOW>; /* 110 */
+			linux,input-type = <5>; /* EV_SW */
+			linux,code = <0x09>; /* SW_CAMERA_LENS_COVER */
+			gpio-key,wakeup;
+		};
+
+		camera_focus {
+			label = "Camera Focus";
+			gpios = <&gpio3 4 GPIO_ACTIVE_LOW>; /* 68 */
+			linux,code = <0x210>; /* KEY_CAMERA_FOCUS */
+			gpio-key,wakeup;
+		};
+
+		camera_capture {
+			label = "Camera Capture";
+			gpios = <&gpio3 5 GPIO_ACTIVE_LOW>; /* 69 */
+			linux,code = <0xd4>; /* KEY_CAMERA */
+			gpio-key,wakeup;
+		};
+
+		lock_button {
+			label = "Lock Button";
+			gpios = <&gpio4 17 GPIO_ACTIVE_LOW>; /* 113 */
+			linux,code = <0x98>; /* KEY_SCREENLOCK */
+			gpio-key,wakeup;
+		};
+
+		keypad_slide {
+			label = "Keypad Slide";
+			gpios = <&gpio3 7 GPIO_ACTIVE_LOW>; /* 71 */
+			linux,input-type = <5>; /* EV_SW */
+			linux,code = <0x0a>; /* SW_KEYPAD_SLIDE */
+			gpio-key,wakeup;
+		};
+
+		proximity_sensor {
+			label = "Proximity Sensor";
+			gpios = <&gpio3 25 GPIO_ACTIVE_HIGH>; /* 89 */
+			linux,input-type = <5>; /* EV_SW */
+			linux,code = <0x0b>; /* SW_FRONT_PROXIMITY */
+		};
+	};
+
+};
+
+&omap3_pmx_core {
+	pinctrl-names = "default";
+
+	uart2_pins: pinmux_uart2_pins {
+		pinctrl-single,pins = <
+			0x14a (PIN_INPUT | MUX_MODE0)		/* uart2_rx */
+			0x148 (PIN_OUTPUT | MUX_MODE0)		/* uart2_tx */
+		>;
+	};
+
+	uart3_pins: pinmux_uart3_pins {
+		pinctrl-single,pins = <
+			0x16e (PIN_INPUT | MUX_MODE0)		/* uart3_rx */
+			0x170 (PIN_OUTPUT | MUX_MODE0)		/* uart3_tx */
+		>;
+	};
+
+	i2c1_pins: pinmux_i2c1_pins {
+		pinctrl-single,pins = <
+			0x18a (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c1_scl */
+			0x18c (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c1_sda */
+		>;
+	};
+
+	i2c2_pins: pinmux_i2c2_pins {
+		pinctrl-single,pins = <
+			0x18e (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c2_scl */
+			0x190 (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c2_sda */
+		>;
+	};
+
+	i2c3_pins: pinmux_i2c3_pins {
+		pinctrl-single,pins = <
+			0x192 (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c3_scl */
+			0x194 (PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c3_sda */
+		>;
+	};
+
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			0x114 (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_clk */
+			0x116 (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_cmd */
+			0x118 (PIN_INPUT_PULLUP | MUX_MODE0) 	/* sdmmc1_dat0 */
+			0x11a (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_dat1 */
+			0x11c (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_dat2 */
+			0x11e (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_dat3 */
+		>;
+	};
+
+	display_pins: pinmux_display_pins {
+		pinctrl-single,pins = <
+			0x0d4 (PIN_OUTPUT | MUX_MODE4)		/* RX51_LCD_RESET_GPIO */
+		>;
+	};
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+
+	clock-frequency = <2200000>;
+
+	twl: twl@48 {
+		reg = <0x48>;
+		interrupts = <7>; /* SYS_NIRQ cascaded to intc */
+		interrupt-parent = <&intc>;
+	};
+};
+
+#include "twl4030.dtsi"
+#include "twl4030_omap3.dtsi"
+
+&vaux1 {
+	regulator-name = "V28";
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <2800000>;
+	regulator-always-on; /* due battery cover sensor */
+};
+
+&vaux2 {
+	regulator-name = "VCSI";
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+};
+
+&vaux3 {
+	regulator-name = "VMMC2_30";
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <3000000>;
+};
+
+&vaux4 {
+	regulator-name = "VCAM_ANA_28";
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <2800000>;
+};
+
+&vmmc1 {
+	regulator-name = "VMMC1";
+	regulator-min-microvolt = <1850000>;
+	regulator-max-microvolt = <3150000>;
+};
+
+&vmmc2 {
+	regulator-name = "V28_A";
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <3000000>;
+	regulator-always-on; /* due VIO leak to AIC34 VDDs */
+};
+
+&vpll1 {
+	regulator-name = "VPLL";
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-always-on;
+};
+
+&vpll2 {
+	regulator-name = "VSDI_CSI";
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-always-on;
+};
+
+&vsim {
+	regulator-name = "VMMC2_IO_18";
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+};
+
+&vio {
+	regulator-name = "VIO";
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+
+};
+
+&vintana1 {
+	regulator-name = "VINTANA1";
+	/* fixed to 1500000 */
+	regulator-always-on;
+};
+
+&vintana2 {
+	regulator-name = "VINTANA2";
+	regulator-min-microvolt = <2750000>;
+	regulator-max-microvolt = <2750000>;
+	regulator-always-on;
+};
+
+&vintdig {
+	regulator-name = "VINTDIG";
+	/* fixed to 1500000 */
+	regulator-always-on;
+};
+
+&twl {
+	twl_audio: audio {
+		compatible = "ti,twl4030-audio";
+		ti,enable-vibra = <1>;
+	};
+};
+
+&twl_gpio {
+	ti,pullups	= <0x0>;
+	ti,pulldowns	= <0x03ff3f>; /* BIT(0..5) | BIT(8..17) */
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_pins>;
+
+	clock-frequency = <100000>;
+
+	tlv320aic3x: tlv320aic3x@18 {
+		compatible = "ti,tlv320aic3x";
+		reg = <0x18>;
+		gpio-reset = <&gpio2 28 GPIO_ACTIVE_HIGH>; /* 60 */
+		ai3x-gpio-func = <
+			0 /* AIC3X_GPIO1_FUNC_DISABLED */
+			5 /* AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT */
+		>;
+
+		AVDD-supply = <&vmmc2>;
+		DRVDD-supply = <&vmmc2>;
+		IOVDD-supply = <&vio>;
+		DVDD-supply = <&vio>;
+	};
+
+	tlv320aic3x_aux: tlv320aic3x@19 {
+		compatible = "ti,tlv320aic3x";
+		reg = <0x19>;
+		gpio-reset = <&gpio2 28 GPIO_ACTIVE_HIGH>; /* 60 */
+
+		AVDD-supply = <&vmmc2>;
+		DRVDD-supply = <&vmmc2>;
+		IOVDD-supply = <&vio>;
+		DVDD-supply = <&vio>;
+	};
+
+	lp5523: lp5523@32 {
+		compatible = "national,lp5523";
+		reg = <0x32>;
+		clock-mode = /bits/ 8 <0>; /* LP55XX_CLOCK_AUTO */
+		enable-gpio = <&gpio2 9 GPIO_ACTIVE_HIGH>; /* 41 */
+
+		chan0 {
+			chan-name = "lp5523:kb1";
+			led-cur = /bits/ 8 <50>;
+			max-cur = /bits/ 8 <100>;
+		};
+
+		chan1 {
+			chan-name = "lp5523:kb2";
+			led-cur = /bits/ 8 <50>;
+			max-cur = /bits/ 8 <100>;
+		};
+
+		chan2 {
+			chan-name = "lp5523:kb3";
+			led-cur = /bits/ 8 <50>;
+			max-cur = /bits/ 8 <100>;
+		};
+
+		chan3 {
+			chan-name = "lp5523:kb4";
+			led-cur = /bits/ 8 <50>;
+			max-cur = /bits/ 8 <100>;
+		};
+
+		chan4 {
+			chan-name = "lp5523:b";
+			led-cur = /bits/ 8 <50>;
+			max-cur = /bits/ 8 <100>;
+		};
+
+		chan5 {
+			chan-name = "lp5523:g";
+			led-cur = /bits/ 8 <50>;
+			max-cur = /bits/ 8 <100>;
+		};
+
+		chan6 {
+			chan-name = "lp5523:r";
+			led-cur = /bits/ 8 <50>;
+			max-cur = /bits/ 8 <100>;
+		};
+
+		chan7 {
+			chan-name = "lp5523:kb5";
+			led-cur = /bits/ 8 <50>;
+			max-cur = /bits/ 8 <100>;
+		};
+
+		chan8 {
+			chan-name = "lp5523:kb6";
+			led-cur = /bits/ 8 <50>;
+			max-cur = /bits/ 8 <100>;
+		};
+	};
+
+	bq27200: bq27200@55 {
+		compatible = "ti,bq27200";
+		reg = <0x55>;
+	};
+};
+
+&i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_pins>;
+
+	clock-frequency = <400000>;
+};
+
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	vmmc-supply = <&vmmc1>;
+	bus-width = <4>;
+	cd-gpios = <&gpio6 0 GPIO_ACTIVE_HIGH>; /* 160 */
+};
+
+&mmc2 {
+	status = "disabled";
+};
+
+&mmc3 {
+	status = "disabled";
+};
+
+&gpmc {
+	ranges = <0 0 0x04000000 0x10000000>; /* 256MB */
+
+	/* gpio-irq for dma: 65 */
+
+	onenand@0,0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0 0 0x10000000>;
+
+		gpmc,sync-read;
+		gpmc,sync-write;
+		gpmc,burst-length = <16>;
+		gpmc,burst-read;
+		gpmc,burst-wrap;
+		gpmc,burst-write;
+		gpmc,device-width = <2>; /* GPMC_DEVWIDTH_16BIT */
+		gpmc,mux-add-data = <2>; /* GPMC_MUX_AD */
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <87>;
+		gpmc,cs-wr-off-ns = <87>;
+		gpmc,adv-on-ns = <0>;
+		gpmc,adv-rd-off-ns = <10>;
+		gpmc,adv-wr-off-ns = <10>;
+		gpmc,oe-on-ns = <15>;
+		gpmc,oe-off-ns = <87>;
+		gpmc,we-on-ns = <0>;
+		gpmc,we-off-ns = <87>;
+		gpmc,rd-cycle-ns = <112>;
+		gpmc,wr-cycle-ns = <112>;
+		gpmc,access-ns = <81>;
+		gpmc,page-burst-access-ns = <15>;
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,wait-monitoring-ns = <0>;
+		gpmc,clk-activation-ns = <5>;
+		gpmc,wr-data-mux-bus-ns = <30>;
+		gpmc,wr-access-ns = <81>;
+		gpmc,sync-clk-ps = <15000>;
+
+		/*
+		 * MTD partition table corresponding to Nokia's
+		 * Maemo 5 (Fremantle) release.
+		 */
+		partition@0 {
+			label = "bootloader";
+			reg = <0x00000000 0x00020000>;
+			read-only;
+		};
+		partition@1 {
+			label = "config";
+			reg = <0x00020000 0x00060000>;
+		};
+		partition@2 {
+			label = "log";
+			reg = <0x00080000 0x00040000>;
+		};
+		partition@3 {
+			label = "kernel";
+			reg = <0x000c0000 0x00200000>;
+		};
+		partition@4 {
+			label = "initfs";
+			reg = <0x002c0000 0x00200000>;
+		};
+		partition@5 {
+			label = "rootfs";
+			reg = <0x004c0000 0x0fb40000>;
+		};
+	};
+};
+
+&mcspi1 {
+	/*
+	 * For some reason, touchscreen is necessary for screen to work at
+	 * all on real hw. It works well without it on emulator.
+	 *
+	 * Also... order in the device tree actually matters here.
+	 */
+	tsc2005@0 {
+		compatible = "tsc2005";
+		spi-max-frequency = <6000000>;
+		reg = <0>;
+	};
+	mipid@2 {
+		compatible = "acx565akm";
+		spi-max-frequency = <6000000>;
+		reg = <2>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&display_pins>;
+	};
+};
+
+&usb_otg_hs {
+	interface-type = <0>;
+	usb-phy = <&usb2_phy>;
+	phys = <&usb2_phy>;
+	phy-names = "usb2-phy";
+	mode = <2>;
+	power = <50>;
+};
+
+&uart1 {
+	status = "disabled";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_pins>;
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins>;
+};
diff --git a/arch/arm/boot/dts/omap3-n950-n9.dtsi b/arch/arm/boot/dts/omap3-n950-n9.dtsi
new file mode 100644
index 0000000..94eb77d
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-n950-n9.dtsi
@@ -0,0 +1,174 @@
+/*
+ * omap3-n950-n9.dtsi - Device Tree file for Nokia N950 & N9 (common stuff)
+ *
+ * Written by: Aaro Koskinen <aaro.koskinen@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "omap36xx.dtsi"
+
+/ {
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&vcc>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x40000000>; /* 1 GB */
+	};
+
+	vemmc: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "VEMMC";
+		regulator-min-microvolt = <2900000>;
+		regulator-max-microvolt = <2900000>;
+		gpio = <&gpio5 29 0>; /* gpio line 157 */
+		startup-delay-us = <150>;
+		enable-active-high;
+	};
+};
+
+&omap3_pmx_core {
+	mmc2_pins: pinmux_mmc2_pins {
+		pinctrl-single,pins = <
+			0x128 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk */
+			0x12a (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd */
+			0x12c (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat0 */
+			0x12e (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat1 */
+			0x130 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat2 */
+			0x132 (PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat3 */
+		>;
+	};
+};
+
+&i2c1 {
+	clock-frequency = <2900000>;
+
+	twl: twl@48 {
+		reg = <0x48>;
+		interrupts = <7>; /* SYS_NIRQ cascaded to intc */
+		interrupt-parent = <&intc>;
+	};
+};
+
+/include/ "twl4030.dtsi"
+
+&twl {
+	compatible = "ti,twl5031";
+};
+
+&twl_gpio {
+	ti,pullups	= <0x000001>; /* BIT(0) */
+	ti,pulldowns	= <0x008106>; /* BIT(1) | BIT(2) | BIT(8) | BIT(15) */
+};
+
+&i2c2 {
+	clock-frequency = <400000>;
+};
+
+&i2c3 {
+	clock-frequency = <400000>;
+};
+
+&mmc1 {
+	status = "disabled";
+};
+
+&mmc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins>;
+	vmmc-supply = <&vemmc>;
+	bus-width = <4>;
+	ti,non-removable;
+};
+
+&mmc3 {
+	status = "disabled";
+};
+
+&usb_otg_hs {
+	interface-type = <0>;
+	usb-phy = <&usb2_phy>;
+	phys = <&usb2_phy>;
+	phy-names = "usb2-phy";
+	mode = <3>;
+	power = <50>;
+};
+
+&gpmc {
+	ranges = <0 0 0x04000000 0x20000000>;
+
+	onenand@0,0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0 0 0x20000000>;
+
+		gpmc,sync-read;
+		gpmc,sync-write;
+		gpmc,burst-length = <16>;
+		gpmc,burst-read;
+		gpmc,burst-wrap;
+		gpmc,burst-write;
+		gpmc,device-width = <2>;
+		gpmc,mux-add-data = <2>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <87>;
+		gpmc,cs-wr-off-ns = <87>;
+		gpmc,adv-on-ns = <0>;
+		gpmc,adv-rd-off-ns = <10>;
+		gpmc,adv-wr-off-ns = <10>;
+		gpmc,oe-on-ns = <15>;
+		gpmc,oe-off-ns = <87>;
+		gpmc,we-on-ns = <0>;
+		gpmc,we-off-ns = <87>;
+		gpmc,rd-cycle-ns = <112>;
+		gpmc,wr-cycle-ns = <112>;
+		gpmc,access-ns = <81>;
+		gpmc,page-burst-access-ns = <15>;
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,wait-monitoring-ns = <0>;
+		gpmc,clk-activation-ns = <5>;
+		gpmc,wr-data-mux-bus-ns = <30>;
+		gpmc,wr-access-ns = <81>;
+		gpmc,sync-clk-ps = <15000>;
+
+		/*
+		 * MTD partition table corresponding to Nokia's MeeGo 1.2
+		 * Harmattan release.
+		 */
+		partition@0 {
+			label = "bootloader";
+			reg = <0x00000000 0x00100000>;
+		};
+		partition@1 {
+			label = "config";
+			reg = <0x00100000 0x002c0000>;
+		};
+		partition@2 {
+			label = "kernel";
+			reg = <0x003c0000 0x01000000>;
+		};
+		partition@3 {
+			label = "log";
+			reg = <0x013c0000 0x00200000>;
+		};
+		partition@4 {
+			label = "var";
+			reg = <0x015c0000 0x1ca40000>;
+		};
+		partition@5 {
+			label = "moslo";
+			reg = <0x1e000000 0x02000000>;
+		};
+		partition@6 {
+			label = "omap2-onenand";
+			reg = <0x00000000 0x20000000>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/omap3-n950.dts b/arch/arm/boot/dts/omap3-n950.dts
new file mode 100644
index 0000000..b076a52
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-n950.dts
@@ -0,0 +1,18 @@
+/*
+ * omap3-n950.dts - Device Tree file for Nokia N950
+ *
+ * Written by: Aaro Koskinen <aaro.koskinen@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+#include "omap3-n950-n9.dtsi"
+
+/ {
+	model = "Nokia N950";
+	compatible = "nokia,omap3-n950", "ti,omap3";
+};
diff --git a/arch/arm/boot/dts/omap3-overo.dtsi b/arch/arm/boot/dts/omap3-overo.dtsi
index 8f1abec..a461d2f 100644
--- a/arch/arm/boot/dts/omap3-overo.dtsi
+++ b/arch/arm/boot/dts/omap3-overo.dtsi
@@ -76,6 +76,8 @@
 &usb_otg_hs {
 	interface-type = <0>;
 	usb-phy = <&usb2_phy>;
+	phys = <&usb2_phy>;
+	phy-names = "usb2-phy";
 	mode = <3>;
 	power = <50>;
 };
diff --git a/arch/arm/boot/dts/omap3-zoom3.dts b/arch/arm/boot/dts/omap3-zoom3.dts
new file mode 100644
index 0000000..15eb9fe
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-zoom3.dts
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "omap36xx.dtsi"
+#include "omap-zoom-common.dtsi"
+
+/ {
+	model = "TI Zoom3";
+	compatible = "ti,omap3-zoom3", "ti,omap36xx", "ti,omap3";
+
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&vcc>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>; /* 512 MB */
+	};
+
+	vddvario: regulator-vddvario {
+		  compatible = "regulator-fixed";
+		  regulator-name = "vddvario";
+		  regulator-always-on;
+	};
+
+	vdd33a: regulator-vdd33a {
+		compatible = "regulator-fixed";
+		regulator-name = "vdd33a";
+		regulator-always-on;
+	};
+
+	wl12xx_vmmc: wl12xx_vmmc {
+		pinctrl-names = "default";
+		pinctrl-0 = <&wl12xx_gpio>;
+		compatible = "regulator-fixed";
+		regulator-name = "vwl1271";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		gpio = <&gpio4 5 0>;	/* gpio101 */
+		startup-delay-us = <70000>;
+		enable-active-high;
+	};
+};
+
+&omap3_pmx_core {
+	/* REVISIT: twl gpio0 is mmc0_cd */
+	mmc1_pins: pinmux_mmc1_pins {
+		pinctrl-single,pins = <
+			0x114 (PIN_OUTPUT_PULLUP | MUX_MODE0)	/* sdmmc1_clk.sdmmc1_clk */
+			0x116 (PIN_OUTPUT_PULLUP | MUX_MODE0)	/* sdmmc1_cmd.sdmmc1_cmd */
+			0x118 (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_dat0.sdmmc1_dat0 */
+			0x11a (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_dat1.sdmmc1_dat1 */
+			0x11c (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_dat2.sdmmc1_dat2 */
+			0x11e (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc1_dat3.sdmmc1_dat3 */
+		>;
+	};
+
+	mmc2_pins: pinmux_mmc2_pins {
+		pinctrl-single,pins = <
+			0x128 (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_clk.sdmmc2_clk */
+			0x12a (PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_cmd.sdmmc2_cmd */
+			0x12c (PIN_INPUT | MUX_MODE0)		/* sdmmc2_dat0.sdmmc2_dat0 */
+			0x12e (PIN_INPUT | MUX_MODE0)		/* sdmmc2_dat1.sdmmc2_dat1 */
+			0x130 (PIN_INPUT | MUX_MODE0)		/* sdmmc2_dat2.sdmmc2_dat2 */
+			0x132 (PIN_INPUT | MUX_MODE0)		/* sdmmc2_dat3.sdmmc2_dat3 */
+			0x134 (PIN_INPUT | MUX_MODE0)		/* sdmmc2_dat4.sdmmc2_dat4 */
+			0x136 (PIN_INPUT | MUX_MODE0)		/* sdmmc2_dat5.sdmmc2_dat5 */
+			0x138 (PIN_INPUT | MUX_MODE0)		/* sdmmc2_dat6.sdmmc2_dat6 */
+			0x13a (PIN_INPUT | MUX_MODE0)		/* sdmmc2_dat7.sdmmc2_dat7 */
+		>;
+	};
+
+	mmc3_pins: pinmux_mmc3_pins {
+		pinctrl-single,pins = <
+			0x168 (PIN_INPUT | MUX_MODE4)	/* mcbsp1_clkx.gpio_162 WLAN IRQ */
+			0x1a0 (PIN_INPUT_PULLUP | MUX_MODE3)	/* mcspi1_cs1.sdmmc3_cmd */
+			0x5a8 (PIN_INPUT_PULLUP | MUX_MODE2)	/* etk_clk.sdmmc3_clk */
+			0x5b4 (PIN_INPUT_PULLUP | MUX_MODE2)	/* etk_d4.sdmmc3_dat0 */
+			0x5b6 (WAKEUP_EN | PIN_INPUT_PULLUP | MUX_MODE2) /* etk_d5.sdmmc3_dat1 */
+			0x5b8 (PIN_INPUT_PULLUP | MUX_MODE2)	/* etk_d6.sdmmc3_dat2 */
+			0x5b2 (PIN_INPUT_PULLUP | MUX_MODE2)	/* etk_d3.sdmmc3_dat3 */
+		>;
+	};
+
+	uart1_pins: pinmux_uart1_pins {
+		pinctrl-single,pins = <
+                        0x150 (PIN_INPUT | MUX_MODE0)		/* uart1_cts.uart1_cts */
+                        0x14e (PIN_OUTPUT | MUX_MODE0)		/* uart1_rts.uart1_rts */
+                        0x152 (WAKEUP_EN | PIN_INPUT | MUX_MODE0) /* uart1_rx.uart1_rx */
+                        0x14c (PIN_OUTPUT | MUX_MODE0)		/* uart1_tx.uart1_tx */
+		>;
+	};
+
+	uart2_pins: pinmux_uart2_pins {
+		pinctrl-single,pins = <
+                        0x144 (PIN_INPUT_PULLUP | MUX_MODE0)	/* uart2_cts.uart2_cts */
+                        0x146 (PIN_OUTPUT | MUX_MODE0)		/* uart2_rts.uart2_rts */
+                        0x14a (WAKEUP_EN | PIN_INPUT | MUX_MODE0) /* uart2_rx.uart2_rx */
+                        0x148 (PIN_OUTPUT | MUX_MODE0)		/* uart2_tx.uart2_tx */
+		>;
+	};
+
+	uart3_pins: pinmux_uart3_pins {
+		pinctrl-single,pins = <
+                        0x16a (PIN_INPUT_PULLDOWN | MUX_MODE0)	/* uart3_cts_rctx.uart3_cts_rctx */
+                        0x16c (PIN_OUTPUT | MUX_MODE0)		/* uart3_rts_sd.uart3_rts_sd */
+                        0x16e (WAKEUP_EN | PIN_INPUT | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */
+                        0x170 (PIN_OUTPUT | MUX_MODE0)		/* uart3_tx_irtx.uart3_tx_irtx */
+		>;
+	};
+
+	/* wl12xx GPIO output for WLAN_EN */
+	wl12xx_gpio: pinmux_wl12xx_gpio {
+		pinctrl-single,pins = <
+			0xea (PIN_OUTPUT| MUX_MODE4)		/* cam_d2.gpio_101 */
+		>;
+	};
+};
+
+&omap3_pmx_wkup {
+	wlan_host_wkup: pinmux_wlan_host_wkup_pins {
+		pinctrl-single,pins = <
+			0x1a (PIN_INPUT_PULLUP | MUX_MODE4)	/* sys_clkout1.gpio_10 WLAN_HOST_WKUP */
+		>;
+	};
+};
+
+&i2c1 {
+	clock-frequency = <2600000>;
+
+	twl: twl@48 {
+		reg = <0x48>;
+		interrupts = <7>; /* SYS_NIRQ cascaded to intc */
+		interrupt-parent = <&intc>;
+	};
+};
+
+#include "twl4030.dtsi"
+
+&i2c2 {
+	clock-frequency = <400000>;
+};
+
+&i2c3 {
+	clock-frequency = <400000>;
+
+	/*
+	 * TVP5146 Video decoder-in for analog input support.
+	 */
+	tvp5146@5c {
+		compatible = "ti,tvp5146m2";
+		reg = <0x5c>;
+	};
+};
+
+&twl_gpio {
+	ti,use-leds;
+};
+
+&mmc1 {
+	vmmc-supply = <&vmmc1>;
+	vmmc_aux-supply = <&vsim>;
+	bus-width = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+};
+/*
+&mmc2 {
+	vmmc-supply = <&vmmc2>;
+	ti,non-removable;
+	bus-width = <8>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins>;
+};
+*/
+&mmc3 {
+	vmmc-supply = <&wl12xx_vmmc>;
+	non-removable;
+	bus-width = <4>;
+	cap-power-off-card;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc3_pins>;
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart1_pins>;
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart2_pins>;
+};
+
+&uart3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart3_pins>;
+};
+
+&uart4 {
+       status = "disabled";
+};
+
+&usb_otg_hs {
+	interface-type = <0>;
+	usb-phy = <&usb2_phy>;
+	mode = <3>;
+	power = <50>;
+};
diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index 7d95cda..f3a0c26 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -19,6 +19,9 @@
 	interrupt-parent = <&intc>;
 
 	aliases {
+		i2c0 = &i2c1;
+		i2c1 = &i2c2;
+		i2c2 = &i2c3;
 		serial0 = &uart1;
 		serial1 = &uart2;
 		serial2 = &uart3;
@@ -37,6 +40,7 @@
 
 	pmu {
 		compatible = "arm,cortex-a8-pmu";
+		reg = <0x54000000 0x800000>;
 		interrupts = <3>;
 		ti,hwmods = "debugss";
 	};
@@ -71,6 +75,8 @@
 	 */
 	ocp {
 		compatible = "simple-bus";
+		reg = <0x68000000 0x10000>;
+		interrupts = <9 10>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
@@ -107,17 +113,21 @@
 			reg = <0x48002030 0x05cc>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
 			pinctrl-single,register-width = <16>;
-			pinctrl-single,function-mask = <0x7f1f>;
+			pinctrl-single,function-mask = <0xff1f>;
 		};
 
-		omap3_pmx_wkup: pinmux@0x48002a00 {
+		omap3_pmx_wkup: pinmux@48002a00 {
 			compatible = "ti,omap3-padconf", "pinctrl-single";
 			reg = <0x48002a00 0x5c>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
 			pinctrl-single,register-width = <16>;
-			pinctrl-single,function-mask = <0x7f1f>;
+			pinctrl-single,function-mask = <0xff1f>;
 		};
 
 		gpio1: gpio@48310000 {
@@ -189,24 +199,40 @@
 
 		uart1: serial@4806a000 {
 			compatible = "ti,omap3-uart";
+			reg = <0x4806a000 0x2000>;
+			interrupts = <72>;
+			dmas = <&sdma 49 &sdma 50>;
+			dma-names = "tx", "rx";
 			ti,hwmods = "uart1";
 			clock-frequency = <48000000>;
 		};
 
 		uart2: serial@4806c000 {
 			compatible = "ti,omap3-uart";
+			reg = <0x4806c000 0x400>;
+			interrupts = <73>;
+			dmas = <&sdma 51 &sdma 52>;
+			dma-names = "tx", "rx";
 			ti,hwmods = "uart2";
 			clock-frequency = <48000000>;
 		};
 
 		uart3: serial@49020000 {
 			compatible = "ti,omap3-uart";
+			reg = <0x49020000 0x400>;
+			interrupts = <74>;
+			dmas = <&sdma 53 &sdma 54>;
+			dma-names = "tx", "rx";
 			ti,hwmods = "uart3";
 			clock-frequency = <48000000>;
 		};
 
 		i2c1: i2c@48070000 {
 			compatible = "ti,omap3-i2c";
+			reg = <0x48070000 0x80>;
+			interrupts = <56>;
+			dmas = <&sdma 27 &sdma 28>;
+			dma-names = "tx", "rx";
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c1";
@@ -214,6 +240,10 @@
 
 		i2c2: i2c@48072000 {
 			compatible = "ti,omap3-i2c";
+			reg = <0x48072000 0x80>;
+			interrupts = <57>;
+			dmas = <&sdma 29 &sdma 30>;
+			dma-names = "tx", "rx";
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c2";
@@ -221,6 +251,10 @@
 
 		i2c3: i2c@48060000 {
 			compatible = "ti,omap3-i2c";
+			reg = <0x48060000 0x80>;
+			interrupts = <61>;
+			dmas = <&sdma 25 &sdma 26>;
+			dma-names = "tx", "rx";
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c3";
@@ -228,6 +262,8 @@
 
 		mcspi1: spi@48098000 {
 			compatible = "ti,omap2-mcspi";
+			reg = <0x48098000 0x100>;
+			interrupts = <65>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "mcspi1";
@@ -246,6 +282,8 @@
 
 		mcspi2: spi@4809a000 {
 			compatible = "ti,omap2-mcspi";
+			reg = <0x4809a000 0x100>;
+			interrupts = <66>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "mcspi2";
@@ -259,6 +297,8 @@
 
 		mcspi3: spi@480b8000 {
 			compatible = "ti,omap2-mcspi";
+			reg = <0x480b8000 0x100>;
+			interrupts = <91>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "mcspi3";
@@ -272,6 +312,8 @@
 
 		mcspi4: spi@480ba000 {
 			compatible = "ti,omap2-mcspi";
+			reg = <0x480ba000 0x100>;
+			interrupts = <48>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "mcspi4";
@@ -280,8 +322,17 @@
 			dma-names = "tx0", "rx0";
 		};
 
+		hdqw1w: 1w@480b2000 {
+			compatible = "ti,omap3-1w";
+			reg = <0x480b2000 0x1000>;
+			interrupts = <58>;
+			ti,hwmods = "hdq1w";
+		};
+
 		mmc1: mmc@4809c000 {
 			compatible = "ti,omap3-hsmmc";
+			reg = <0x4809c000 0x200>;
+			interrupts = <83>;
 			ti,hwmods = "mmc1";
 			ti,dual-volt;
 			dmas = <&sdma 61>, <&sdma 62>;
@@ -290,6 +341,8 @@
 
 		mmc2: mmc@480b4000 {
 			compatible = "ti,omap3-hsmmc";
+			reg = <0x480b4000 0x200>;
+			interrupts = <86>;
 			ti,hwmods = "mmc2";
 			dmas = <&sdma 47>, <&sdma 48>;
 			dma-names = "tx", "rx";
@@ -297,6 +350,8 @@
 
 		mmc3: mmc@480ad000 {
 			compatible = "ti,omap3-hsmmc";
+			reg = <0x480ad000 0x200>;
+			interrupts = <94>;
 			ti,hwmods = "mmc3";
 			dmas = <&sdma 77>, <&sdma 78>;
 			dma-names = "tx", "rx";
@@ -304,6 +359,7 @@
 
 		wdt2: wdt@48314000 {
 			compatible = "ti,omap3-wdt";
+			reg = <0x48314000 0x80>;
 			ti,hwmods = "wd_timer2";
 		};
 
diff --git a/arch/arm/boot/dts/omap3430-sdp.dts b/arch/arm/boot/dts/omap3430-sdp.dts
index e2249bc..281914e 100644
--- a/arch/arm/boot/dts/omap3430-sdp.dts
+++ b/arch/arm/boot/dts/omap3430-sdp.dts
@@ -84,15 +84,15 @@
 			label = "bootloader-nor";
 			reg = <0 0x40000>;
 		};
-		partition@0x40000 {
+		partition@40000 {
 			label = "params-nor";
 			reg = <0x40000 0x40000>;
 		};
-		partition@0x80000 {
+		partition@80000 {
 			label = "kernel-nor";
 			reg = <0x80000 0x200000>;
 		};
-		partition@0x280000 {
+		partition@280000 {
 			label = "filesystem-nor";
 			reg = <0x240000 0x7d80000>;
 		};
@@ -125,19 +125,19 @@
 			label = "xloader-nand";
 			reg = <0 0x80000>;
 		};
-		partition@0x80000 {
+		partition@80000 {
 			label = "bootloader-nand";
 			reg = <0x80000 0x140000>;
 		};
-		partition@0x1c0000 {
+		partition@1c0000 {
 			label = "params-nand";
 			reg = <0x1c0000 0xc0000>;
 		};
-		partition@0x280000 {
+		partition@280000 {
 			label = "kernel-nand";
 			reg = <0x280000 0x500000>;
 		};
-		partition@0x780000 {
+		partition@780000 {
 			label = "filesystem-nand";
 			reg = <0x780000 0x7880000>;
 		};
@@ -170,19 +170,19 @@
 			label = "xloader-onenand";
 			reg = <0 0x80000>;
 		};
-		partition@0x80000 {
+		partition@80000 {
 			label = "bootloader-onenand";
 			reg = <0x80000 0x40000>;
 		};
-		partition@0xc0000 {
+		partition@c0000 {
 			label = "params-onenand";
 			reg = <0xc0000 0x20000>;
 		};
-		partition@0xe0000 {
+		partition@e0000 {
 			label = "kernel-onenand";
 			reg = <0xe0000 0x200000>;
 		};
-		partition@0x2e0000 {
+		partition@2e0000 {
 			label = "filesystem-onenand";
 			reg = <0x2e0000 0xfd20000>;
 		};
diff --git a/arch/arm/boot/dts/omap36xx.dtsi b/arch/arm/boot/dts/omap36xx.dtsi
index f8b3765..380c22e 100644
--- a/arch/arm/boot/dts/omap36xx.dtsi
+++ b/arch/arm/boot/dts/omap36xx.dtsi
@@ -31,6 +31,10 @@
 	ocp {
 		uart4: serial@49042000 {
 			compatible = "ti,omap3-uart";
+			reg = <0x49042000 0x400>;
+			interrupts = <80>;
+			dmas = <&sdma 81 &sdma 82>;
+			dma-names = "tx", "rx";
 			ti,hwmods = "uart4";
 			clock-frequency = <48000000>;
 		};
diff --git a/arch/arm/boot/dts/omap4-panda-common.dtsi b/arch/arm/boot/dts/omap4-panda-common.dtsi
index 814ab67..298e850 100644
--- a/arch/arm/boot/dts/omap4-panda-common.dtsi
+++ b/arch/arm/boot/dts/omap4-panda-common.dtsi
@@ -60,22 +60,6 @@
 			"AFMR", "Line In";
 	};
 
-	/*
-	 * Temp hack: Need to be replaced with the proper gpio-controlled
-	 * reset driver as soon it will be merged.
-	 * http://thread.gmane.org/gmane.linux.drivers.devicetree/36830
-	 */
-	/* HS USB Port 1 RESET */
-	hsusb1_reset: hsusb1_reset_reg {
-		compatible = "regulator-fixed";
-		regulator-name = "hsusb1_reset";
-		regulator-min-microvolt = <3300000>;
-		regulator-max-microvolt = <3300000>;
-		gpio = <&gpio2 30 0>;	/* gpio_62 */
-		startup-delay-us = <70000>;
-		enable-active-high;
-	};
-
 	/* HS USB Port 1 Power */
 	hsusb1_power: hsusb1_power_reg {
 		compatible = "regulator-fixed";
@@ -97,7 +81,7 @@
 	/* HS USB Host PHY on PORT 1 */
 	hsusb1_phy: hsusb1_phy {
 		compatible = "usb-nop-xceiv";
-		reset-supply = <&hsusb1_reset>;
+		reset-gpios = <&gpio2 30 GPIO_ACTIVE_LOW>;   /* gpio_62 */
 		vcc-supply = <&hsusb1_power>;
 	/**
 	 * FIXME:
@@ -122,37 +106,19 @@
 	};
 };
 
-&omap4_pmx_wkup {
-	pinctrl-names = "default";
-	pinctrl-0 = <
-			&twl6030_wkup_pins
-	>;
-
-	twl6030_wkup_pins: pinmux_twl6030_wkup_pins {
-		pinctrl-single,pins = <
-			0x14 (PIN_OUTPUT | MUX_MODE2)		/* fref_clk0_out.sys_drm_msecure */
-		>;
-	};
-};
-
 &omap4_pmx_core {
 	pinctrl-names = "default";
 	pinctrl-0 = <
-			&twl6030_pins
 			&twl6040_pins
 			&mcpdm_pins
 			&mcbsp1_pins
+			&dss_dpi_pins
+			&tfp410_pins
 			&dss_hdmi_pins
 			&tpd12s015_pins
 			&hsusbb1_pins
 	>;
 
-	twl6030_pins: pinmux_twl6030_pins {
-		pinctrl-single,pins = <
-			0x15e (WAKEUP_EN | PIN_INPUT_PULLUP | MUX_MODE0)	/* sys_nirq1.sys_nirq1 */
-		>;
-	};
-
 	twl6040_pins: pinmux_twl6040_pins {
 		pinctrl-single,pins = <
 			0xe0 (PIN_OUTPUT | MUX_MODE3)	/* hdq_sio.gpio_127 */
@@ -179,6 +145,47 @@
 		>;
 	};
 
+	dss_dpi_pins: pinmux_dss_dpi_pins {
+		pinctrl-single,pins = <
+			0x122 (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data23 */
+			0x124 (PIN_OUTPUT | MUX_MODE5) 	/* dispc2_data22 */
+			0x126 (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data21 */
+			0x128 (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data20 */
+			0x12a (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data19 */
+			0x12c (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data18 */
+			0x12e (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data15 */
+			0x130 (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data14 */
+			0x132 (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data13 */
+			0x134 (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data12 */
+			0x136 (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data11 */
+
+			0x174 (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data10 */
+			0x176 (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data9 */
+			0x178 (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data16 */
+			0x17a (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data17 */
+			0x17c (PIN_OUTPUT | MUX_MODE5)	/* dispc2_hsync */
+			0x17e (PIN_OUTPUT | MUX_MODE5)	/* dispc2_pclk */
+			0x180 (PIN_OUTPUT | MUX_MODE5)	/* dispc2_vsync */
+			0x182 (PIN_OUTPUT | MUX_MODE5)	/* dispc2_de */
+			0x184 (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data8 */
+			0x186 (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data7 */
+			0x188 (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data6 */
+			0x18a (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data5 */
+			0x18c (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data4 */
+			0x18e (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data3 */
+
+			0x190 (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data2 */
+			0x192 (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data1 */
+			0x194 (PIN_OUTPUT | MUX_MODE5)	/* dispc2_data0 */
+		>;
+	};
+
+	tfp410_pins: pinmux_tfp410_pins {
+		pinctrl-single,pins = <
+			0x144 (PIN_OUTPUT | MUX_MODE3)	/* gpio_0 */
+		>;
+	};
+
 	dss_hdmi_pins: pinmux_dss_hdmi_pins {
 		pinctrl-single,pins = <
 			0x5a (PIN_INPUT_PULLUP | MUX_MODE0)	/* hdmi_cec.hdmi_cec */
@@ -305,6 +312,7 @@
 };
 
 #include "twl6030.dtsi"
+#include "twl6030_omap4.dtsi"
 
 &i2c2 {
 	pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/omap4-panda-es.dts b/arch/arm/boot/dts/omap4-panda-es.dts
index 56c4354..816d1c9 100644
--- a/arch/arm/boot/dts/omap4-panda-es.dts
+++ b/arch/arm/boot/dts/omap4-panda-es.dts
@@ -62,3 +62,7 @@
 		gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
 	};
 };
+
+&gpio1 {
+	 ti,no-reset-on-init;
+};
diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts
index 4f78380..5fc3f43 100644
--- a/arch/arm/boot/dts/omap4-sdp.dts
+++ b/arch/arm/boot/dts/omap4-sdp.dts
@@ -155,23 +155,9 @@
 	};
 };
 
-&omap4_pmx_wkup {
-	pinctrl-names = "default";
-	pinctrl-0 = <
-			&twl6030_wkup_pins
-	>;
-
-	twl6030_wkup_pins: pinmux_twl6030_wkup_pins {
-		pinctrl-single,pins = <
-			0x14 (PIN_OUTPUT | MUX_MODE2)		/* fref_clk0_out.sys_drm_msecure */
-		>;
-	};
-};
-
 &omap4_pmx_core {
 	pinctrl-names = "default";
 	pinctrl-0 = <
-			&twl6030_pins
 			&twl6040_pins
 			&mcpdm_pins
 			&dmic_pins
@@ -206,12 +192,6 @@
 		>;
 	};
 
-	twl6030_pins: pinmux_twl6030_pins {
-		pinctrl-single,pins = <
-			0x15e (WAKEUP_EN | PIN_INPUT_PULLUP | MUX_MODE0)	/* sys_nirq1.sys_nirq1 */
-		>;
-	};
-
 	twl6040_pins: pinmux_twl6040_pins {
 		pinctrl-single,pins = <
 			0xe0 (PIN_OUTPUT | MUX_MODE3)		/* hdq_sio.gpio_127 */
@@ -370,6 +350,7 @@
 };
 
 #include "twl6030.dtsi"
+#include "twl6030_omap4.dtsi"
 
 &i2c2 {
 	pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 22d9f2b..a1e0585 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -17,6 +17,10 @@
 	interrupt-parent = <&gic>;
 
 	aliases {
+		i2c0 = &i2c1;
+		i2c1 = &i2c2;
+		i2c2 = &i2c3;
+		i2c3 = &i2c4;
 		serial0 = &uart1;
 		serial1 = &uart2;
 		serial2 = &uart3;
@@ -56,7 +60,7 @@
 		cache-level = <2>;
 	};
 
-	local-timer@0x48240600 {
+	local-timer@48240600 {
 		compatible = "arm,cortex-a9-twd-timer";
 		reg = <0x48240600 0x20>;
 		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_HIGH)>;
@@ -114,6 +118,8 @@
 			reg = <0x4a100040 0x0196>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
 			pinctrl-single,register-width = <16>;
 			pinctrl-single,function-mask = <0x7fff>;
 		};
@@ -122,6 +128,8 @@
 			reg = <0x4a31e040 0x0038>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
 			pinctrl-single,register-width = <16>;
 			pinctrl-single,function-mask = <0x7fff>;
 		};
@@ -214,6 +222,7 @@
 			gpmc,num-cs = <8>;
 			gpmc,num-waitpins = <4>;
 			ti,hwmods = "gpmc";
+			ti,no-idle-on-init;
 		};
 
 		uart1: serial@4806a000 {
@@ -248,6 +257,12 @@
 			clock-frequency = <48000000>;
 		};
 
+		hwspinlock: spinlock@4a0f6000 {
+			compatible = "ti,omap4-hwspinlock";
+			reg = <0x4a0f6000 0x1000>;
+			ti,hwmods = "spinlock";
+		};
+
 		i2c1: i2c@48070000 {
 			compatible = "ti,omap4-i2c";
 			reg = <0x48070000 0x100>;
@@ -492,6 +507,7 @@
 			reg = <0x4c000000 0x100>;
 			interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "emif1";
+			ti,no-idle-on-init;
 			phy-type = <1>;
 			hw-caps-read-idle-ctrl;
 			hw-caps-ll-interface;
@@ -503,6 +519,7 @@
 			reg = <0x4d000000 0x100>;
 			interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "emif2";
+			ti,no-idle-on-init;
 			phy-type = <1>;
 			hw-caps-read-idle-ctrl;
 			hw-caps-ll-interface;
@@ -519,7 +536,8 @@
 			usb2_phy: usb2phy@4a0ad080 {
 				compatible = "ti,omap-usb2";
 				reg = <0x4a0ad080 0x58>;
-				ctrl-module = <&omap_control_usb>;
+				ctrl-module = <&omap_control_usb2phy>;
+				#phy-cells = <0>;
 			};
 		};
 
@@ -643,12 +661,16 @@
 			};
 		};
 
-		omap_control_usb: omap-control-usb@4a002300 {
-			compatible = "ti,omap-control-usb";
-			reg = <0x4a002300 0x4>,
-			      <0x4a00233c 0x4>;
-			reg-names = "control_dev_conf", "otghs_control";
-			ti,type = <1>;
+		omap_control_usb2phy: control-phy@4a002300 {
+			compatible = "ti,control-phy-usb2";
+			reg = <0x4a002300 0x4>;
+			reg-names = "power";
+		};
+
+		omap_control_usbotg: control-phy@4a00233c {
+			compatible = "ti,control-phy-otghs";
+			reg = <0x4a00233c 0x4>;
+			reg-names = "otghs_control";
 		};
 
 		usb_otg_hs: usb_otg_hs@4a0ab000 {
@@ -658,10 +680,30 @@
 			interrupt-names = "mc", "dma";
 			ti,hwmods = "usb_otg_hs";
 			usb-phy = <&usb2_phy>;
+			phys = <&usb2_phy>;
+			phy-names = "usb2-phy";
 			multipoint = <1>;
 			num-eps = <16>;
 			ram-bits = <12>;
-			ti,has-mailbox;
+			ctrl-module = <&omap_control_usbotg>;
+		};
+
+		aes: aes@4b501000 {
+			compatible = "ti,omap4-aes";
+			ti,hwmods = "aes";
+			reg = <0x4b501000 0xa0>;
+			interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&sdma 111>, <&sdma 110>;
+			dma-names = "tx", "rx";
+		};
+
+		des: des@480a5000 {
+			compatible = "ti,omap4-des";
+			ti,hwmods = "des";
+			reg = <0x480a5000 0xa0>;
+			interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&sdma 117>, <&sdma 116>;
+			dma-names = "tx", "rx";
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/omap5-uevm.dts b/arch/arm/boot/dts/omap5-uevm.dts
index 65d7b60..002fa70 100644
--- a/arch/arm/boot/dts/omap5-uevm.dts
+++ b/arch/arm/boot/dts/omap5-uevm.dts
@@ -27,21 +27,10 @@
 		regulator-max-microvolt = <3000000>;
 	};
 
-	/* HS USB Port 2 RESET */
-	hsusb2_reset: hsusb2_reset_reg {
-		compatible = "regulator-fixed";
-		regulator-name = "hsusb2_reset";
-		regulator-min-microvolt = <3300000>;
-		regulator-max-microvolt = <3300000>;
-		gpio = <&gpio3 16 GPIO_ACTIVE_HIGH>; /* gpio3_80 HUB_NRESET */
-		startup-delay-us = <70000>;
-		enable-active-high;
-	};
-
 	/* HS USB Host PHY on PORT 2 */
 	hsusb2_phy: hsusb2_phy {
 		compatible = "usb-nop-xceiv";
-		reset-supply = <&hsusb2_reset>;
+		reset-gpios = <&gpio3 16 GPIO_ACTIVE_LOW>; /* gpio3_80 HUB_NRESET */
 	/**
 	  * FIXME
 	  * Put the right clock phandle here when available
@@ -51,21 +40,10 @@
 		clock-frequency = <19200000>;
 	};
 
-	/* HS USB Port 3 RESET */
-	hsusb3_reset: hsusb3_reset_reg {
-		compatible = "regulator-fixed";
-		regulator-name = "hsusb3_reset";
-		regulator-min-microvolt = <3300000>;
-		regulator-max-microvolt = <3300000>;
-		gpio = <&gpio3 15 GPIO_ACTIVE_HIGH>; /* gpio3_79 ETH_NRESET */
-		startup-delay-us = <70000>;
-		enable-active-high;
-	};
-
 	/* HS USB Host PHY on PORT 3 */
 	hsusb3_phy: hsusb3_phy {
 		compatible = "usb-nop-xceiv";
-		reset-supply = <&hsusb3_reset>;
+		reset-gpios = <&gpio3 15 GPIO_ACTIVE_LOW>; /* gpio3_79 ETH_NRESET */
 	};
 
 	leds {
@@ -84,7 +62,6 @@
 	pinctrl-0 = <
 			&twl6040_pins
 			&mcpdm_pins
-			&dmic_pins
 			&mcbsp1_pins
 			&mcbsp2_pins
 			&usbhost_pins
@@ -93,7 +70,7 @@
 
 	twl6040_pins: pinmux_twl6040_pins {
 		pinctrl-single,pins = <
-			0x18a (PIN_OUTPUT | MUX_MODE6)	/* perslimbus2_clock.gpio5_145 */
+			0x17e (PIN_OUTPUT | MUX_MODE6)	/* mcspi1_somi.gpio5_141 */
 		>;
 	};
 
@@ -107,15 +84,6 @@
 		>;
 	};
 
-	dmic_pins: pinmux_dmic_pins {
-		pinctrl-single,pins = <
-			0x144 (PIN_INPUT | MUX_MODE0)		/* abedmic_din1.abedmic_din1 */
-			0x146 (PIN_INPUT | MUX_MODE0)		/* abedmic_din2.abedmic_din2 */
-			0x148 (PIN_INPUT | MUX_MODE0)		/* abedmic_din3.abedmic_din3 */
-			0x14a (PIN_OUTPUT | MUX_MODE0)		/* abedmic_clk1.abedmic_clk1 */
-		>;
-	};
-
 	mcbsp1_pins: pinmux_mcbsp1_pins {
 		pinctrl-single,pins = <
 			0x14c (PIN_INPUT | MUX_MODE1)		/* abedmic_clk2.abemcbsp1_fsx */
@@ -153,25 +121,25 @@
 			0xbc (PIN_INPUT | MUX_MODE0)		/*  mcspi2_clk */
 			0xbe (PIN_INPUT | MUX_MODE0)		/*  mcspi2_simo */
 			0xc0 (PIN_INPUT_PULLUP | MUX_MODE0)	/*  mcspi2_somi */
-			0xc2 (PIN_OUTPUT | MUX_MODE0)		/*  mcspi2_cs */
+			0xc2 (PIN_OUTPUT | MUX_MODE0)		/*  mcspi2_cs0 */
 		>;
 	};
 
 	mcspi3_pins: pinmux_mcspi3_pins {
 		pinctrl-single,pins = <
-			0x78 (PIN_INPUT | MUX_MODE1)		/*  mcspi2_somi */
-			0x7a (PIN_INPUT | MUX_MODE1)		/*  mcspi2_cs */
-			0x7c (PIN_INPUT | MUX_MODE1)		/*  mcspi2_simo */
-			0x7e (PIN_INPUT | MUX_MODE1)		/*  mcspi2_clk */
+			0x78 (PIN_INPUT | MUX_MODE1)		/*  mcspi3_somi */
+			0x7a (PIN_INPUT | MUX_MODE1)		/*  mcspi3_cs0 */
+			0x7c (PIN_INPUT | MUX_MODE1)		/*  mcspi3_simo */
+			0x7e (PIN_INPUT | MUX_MODE1)		/*  mcspi3_clk */
 		>;
 	};
 
 	mcspi4_pins: pinmux_mcspi4_pins {
 		pinctrl-single,pins = <
-			0x164 (PIN_INPUT | MUX_MODE1)		/*  mcspi2_clk */
-			0x168 (PIN_INPUT | MUX_MODE1)		/*  mcspi2_simo */
-			0x16a (PIN_INPUT | MUX_MODE1)		/*  mcspi2_somi */
-			0x16c (PIN_INPUT | MUX_MODE1)		/*  mcspi2_cs */
+			0x164 (PIN_INPUT | MUX_MODE1)		/*  mcspi4_clk */
+			0x168 (PIN_INPUT | MUX_MODE1)		/*  mcspi4_simo */
+			0x16a (PIN_INPUT | MUX_MODE1)		/*  mcspi4_somi */
+			0x16c (PIN_INPUT | MUX_MODE1)		/*  mcspi4_cs0 */
 		>;
 	};
 
@@ -271,6 +239,14 @@
 		reg = <0x48>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
+		ti,system-power-controller;
+
+		extcon_usb3: palmas_usb {
+			compatible = "ti,palmas-usb-vid";
+			ti,enable-vbus-detection;
+			ti,enable-id-detection;
+			ti,wakeup;
+		};
 
 		palmas_pmic {
 			compatible = "ti,palmas-pmic";
@@ -334,15 +310,22 @@
 					ti,smps-range = <0x80>;
 				};
 
-				smps10_reg: smps10 {
+				smps10_out2_reg: smps10_out2 {
 					/* VBUS_5V_OTG */
-					regulator-name = "smps10";
+					regulator-name = "smps10_out2";
 					regulator-min-microvolt = <5000000>;
 					regulator-max-microvolt = <5000000>;
 					regulator-always-on;
 					regulator-boot-on;
 				};
 
+				smps10_out1_reg: smps10_out1 {
+					/* VBUS_5V_OTG */
+					regulator-name = "smps10_out1";
+					regulator-min-microvolt = <5000000>;
+					regulator-max-microvolt = <5000000>;
+				};
+
 				ldo1_reg: ldo1 {
 					/* VDDAPHY_CAM: vdda_csiport */
 					regulator-name = "ldo1";
@@ -470,6 +453,11 @@
 	phys = <0 &hsusb2_phy &hsusb3_phy>;
 };
 
+&usb3 {
+	extcon = <&extcon_usb3>;
+	vbus-supply = <&smps10_out1_reg>;
+};
+
 &mcspi1 {
 
 };
@@ -503,3 +491,7 @@
         pinctrl-names = "default";
         pinctrl-0 = <&uart5_pins>;
 };
+
+&cpu0 {
+	cpu0-supply = <&smps123_reg>;
+};
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index 7cdea1b..fc3fad5 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -21,6 +21,11 @@
 	interrupt-parent = <&gic>;
 
 	aliases {
+		i2c0 = &i2c1;
+		i2c1 = &i2c2;
+		i2c2 = &i2c3;
+		i2c3 = &i2c4;
+		i2c4 = &i2c5;
 		serial0 = &uart1;
 		serial1 = &uart2;
 		serial2 = &uart3;
@@ -33,10 +38,17 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		cpu@0 {
+		cpu0: cpu@0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a15";
 			reg = <0x0>;
+
+			operating-points = <
+				/* kHz    uV */
+				500000  880000
+				1000000 1060000
+				1500000 1250000
+			>;
 		};
 		cpu@1 {
 			device_type = "cpu";
@@ -52,7 +64,6 @@
 			     <GIC_PPI 14 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>,
 			     <GIC_PPI 11 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>,
 			     <GIC_PPI 10 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>;
-		clock-frequency = <6144000>;
 	};
 
 	gic: interrupt-controller@48211000 {
@@ -276,6 +287,12 @@
 			ti,hwmods = "i2c5";
 		};
 
+		hwspinlock: spinlock@4a0f6000 {
+			compatible = "ti,omap4-hwspinlock";
+			reg = <0x4a0f6000 0x1000>;
+			ti,hwmods = "spinlock";
+		};
+
 		mcspi1: spi@48098000 {
 			compatible = "ti,omap4-mcspi";
 			reg = <0x48098000 0x200>;
@@ -604,9 +621,10 @@
 			ti,hwmods = "wd_timer2";
 		};
 
-		emif1: emif@0x4c000000 {
+		emif1: emif@4c000000 {
 			compatible	= "ti,emif-4d5";
 			ti,hwmods	= "emif1";
+			ti,no-idle-on-init;
 			phy-type	= <2>; /* DDR PHY type: Intelli PHY */
 			reg = <0x4c000000 0x400>;
 			interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
@@ -615,9 +633,10 @@
 			hw-caps-temp-alert;
 		};
 
-		emif2: emif@0x4d000000 {
+		emif2: emif@4d000000 {
 			compatible	= "ti,emif-4d5";
 			ti,hwmods	= "emif2";
+			ti,no-idle-on-init;
 			phy-type	= <2>; /* DDR PHY type: Intelli PHY */
 			reg = <0x4d000000 0x400>;
 			interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
@@ -626,15 +645,19 @@
 			hw-caps-temp-alert;
 		};
 
-		omap_control_usb: omap-control-usb@4a002300 {
-			compatible = "ti,omap-control-usb";
-			reg = <0x4a002300 0x4>,
-			      <0x4a002370 0x4>;
-			reg-names = "control_dev_conf", "phy_power_usb";
-			ti,type = <2>;
+		omap_control_usb2phy: control-phy@4a002300 {
+			compatible = "ti,control-phy-usb2";
+			reg = <0x4a002300 0x4>;
+			reg-names = "power";
 		};
 
-		omap_dwc3@4a020000 {
+		omap_control_usb3phy: control-phy@4a002370 {
+			compatible = "ti,control-phy-pipe3";
+			reg = <0x4a002370 0x4>;
+			reg-names = "power";
+		};
+
+		usb3: omap_dwc3@4a020000 {
 			compatible = "ti,dwc3";
 			ti,hwmods = "usb_otg_ss";
 			reg = <0x4a020000 0x10000>;
@@ -648,6 +671,7 @@
 				reg = <0x4a030000 0x10000>;
 				interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
 				usb-phy = <&usb2_phy>, <&usb3_phy>;
+				dr_mode = "peripheral";
 				tx-fifo-resize;
 			};
 		};
@@ -662,7 +686,7 @@
 			usb2_phy: usb2phy@4a084000 {
 				compatible = "ti,omap-usb2";
 				reg = <0x4a084000 0x7c>;
-				ctrl-module = <&omap_control_usb>;
+				ctrl-module = <&omap_control_usb2phy>;
 			};
 
 			usb3_phy: usb3phy@4a084400 {
@@ -671,7 +695,7 @@
 				      <0x4a084800 0x64>,
 				      <0x4a084c00 0x40>;
 				reg-names = "phy_rx", "phy_tx", "pll_ctrl";
-				ctrl-module = <&omap_control_usb>;
+				ctrl-module = <&omap_control_usb3phy>;
 			};
 		};
 
diff --git a/arch/arm/boot/dts/prima2.dtsi b/arch/arm/boot/dts/prima2.dtsi
index 27ed9f5..daee5894 100644
--- a/arch/arm/boot/dts/prima2.dtsi
+++ b/arch/arm/boot/dts/prima2.dtsi
@@ -76,6 +76,11 @@
 				compatible = "sirf,prima2-rsc";
 				reg = <0x88020000 0x1000>;
 			};
+
+			cphifbg@88030000 {
+				compatible = "sirf,prima2-cphifbg";
+				reg = <0x88030000 0x1000>;
+			};
 		};
 
 		mem-iobg {
@@ -86,10 +91,17 @@
 
 			memory-controller@90000000 {
 				compatible = "sirf,prima2-memc";
-				reg = <0x90000000 0x10000>;
+				reg = <0x90000000 0x2000>;
 				interrupts = <27>;
 				clocks = <&clks 5>;
 			};
+
+			memc-monitor {
+				compatible = "sirf,prima2-memcmon";
+				reg = <0x90002000 0x200>;
+				interrupts = <4>;
+				clocks = <&clks 32>;
+			};
 		};
 
 		disp-iobg {
@@ -287,7 +299,13 @@
 				compatible = "sirf,prima2-spi";
 				reg = <0xb00d0000 0x10000>;
 				interrupts = <15>;
+				sirf,spi-num-chipselects = <1>;
+				sirf,spi-dma-rx-channel = <25>;
+				sirf,spi-dma-tx-channel = <20>;
+				#address-cells = <1>;
+				#size-cells = <0>;
 				clocks = <&clks 19>;
+				status = "disabled";
 			};
 
 			spi1: spi@b0170000 {
@@ -295,7 +313,13 @@
 				compatible = "sirf,prima2-spi";
 				reg = <0xb0170000 0x10000>;
 				interrupts = <16>;
+				sirf,spi-num-chipselects = <1>;
+				sirf,spi-dma-rx-channel = <12>;
+				sirf,spi-dma-tx-channel = <13>;
+				#address-cells = <1>;
+				#size-cells = <0>;
 				clocks = <&clks 20>;
+				status = "disabled";
 			};
 
 			i2c0: i2c@b00e0000 {
@@ -304,6 +328,8 @@
 				reg = <0xb00e0000 0x10000>;
 				interrupts = <24>;
 				clocks = <&clks 17>;
+				#address-cells = <1>;
+				#size-cells = <0>;
 			};
 
 			i2c1: i2c@b00f0000 {
@@ -312,6 +338,8 @@
 				reg = <0xb00f0000 0x10000>;
 				interrupts = <25>;
 				clocks = <&clks 18>;
+				#address-cells = <1>;
+				#size-cells = <0>;
 			};
 
 			tsc@b0110000 {
@@ -360,6 +388,12 @@
 						sirf,function = "uart0";
 					};
 				};
+				uart0_noflow_pins_a: uart0@1 {
+					uart {
+						sirf,pins = "uart0_nostreamctrlgrp";
+						sirf,function = "uart0_nostreamctrl";
+					};
+				};
 				uart1_pins_a: uart1@0 {
 					uart {
 						sirf,pins = "uart1grp";
@@ -498,18 +532,42 @@
                                                 sirf,function = "usp0";
                                         };
                                 };
+				usp0_uart_nostreamctrl_pins_a: usp0@1 {
+                                        usp0 {
+                                                sirf,pins =
+							"usp0_uart_nostreamctrl_grp";
+                                                sirf,function =
+							"usp0_uart_nostreamctrl";
+                                        };
+                                };
                                 usp1_pins_a: usp1@0 {
                                         usp1 {
                                                 sirf,pins = "usp1grp";
                                                 sirf,function = "usp1";
                                         };
                                 };
+				usp1_uart_nostreamctrl_pins_a: usp1@1 {
+                                        usp1 {
+                                                sirf,pins =
+							"usp1_uart_nostreamctrl_grp";
+                                                sirf,function =
+							"usp1_uart_nostreamctrl";
+                                        };
+                                };
                                 usp2_pins_a: usp2@0 {
                                         usp2 {
                                                 sirf,pins = "usp2grp";
                                                 sirf,function = "usp2";
                                         };
                                 };
+				usp2_uart_nostreamctrl_pins_a: usp2@1 {
+                                        usp2 {
+                                                sirf,pins =
+							"usp2_uart_nostreamctrl_grp";
+                                                sirf,function =
+							"usp2_uart_nostreamctrl";
+                                        };
+                                };
                                 usb0_utmi_drvbus_pins_a: usb0_utmi_drvbus@0 {
                                         usb0_utmi_drvbus {
                                                 sirf,pins = "usb0_utmi_drvbusgrp";
@@ -522,6 +580,18 @@
                                                 sirf,function = "usb1_utmi_drvbus";
                                         };
                                 };
+                                usb1_dp_dn_pins_a: usb1_dp_dn@0 {
+                                        usb1_dp_dn {
+                                                sirf,pins = "usb1_dp_dngrp";
+                                                sirf,function = "usb1_dp_dn";
+                                        };
+                                };
+                                uart1_route_io_usb1_pins_a: uart1_route_io_usb1@0 {
+                                        uart1_route_io_usb1 {
+                                                sirf,pins = "uart1_route_io_usb1grp";
+                                                sirf,function = "uart1_route_io_usb1";
+                                        };
+                                };
                                 warm_rst_pins_a: warm_rst@0 {
                                         warm_rst {
                                                 sirf,pins = "warm_rstgrp";
diff --git a/arch/arm/boot/dts/msm8660-surf.dts b/arch/arm/boot/dts/qcom-msm8660-surf.dts
similarity index 100%
rename from arch/arm/boot/dts/msm8660-surf.dts
rename to arch/arm/boot/dts/qcom-msm8660-surf.dts
diff --git a/arch/arm/boot/dts/msm8960-cdp.dts b/arch/arm/boot/dts/qcom-msm8960-cdp.dts
similarity index 100%
rename from arch/arm/boot/dts/msm8960-cdp.dts
rename to arch/arm/boot/dts/qcom-msm8960-cdp.dts
diff --git a/arch/arm/boot/dts/r7s72100-genmai.dts b/arch/arm/boot/dts/r7s72100-genmai.dts
new file mode 100644
index 0000000..1fb20f2
--- /dev/null
+++ b/arch/arm/boot/dts/r7s72100-genmai.dts
@@ -0,0 +1,31 @@
+/*
+ * Device Tree Source for the Genmai board
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/dts-v1/;
+/include/ "r7s72100.dtsi"
+
+/ {
+	model = "Genmai";
+	compatible = "renesas,genmai", "renesas,r7s72100";
+
+	chosen {
+		bootargs = "console=ttySC2,115200 ignore_loglevel rw root=/dev/nfs ip=dhcp";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x08000000 0x08000000>;
+	};
+
+	lbsc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+};
diff --git a/arch/arm/boot/dts/r7s72100.dtsi b/arch/arm/boot/dts/r7s72100.dtsi
new file mode 100644
index 0000000..46b82aa
--- /dev/null
+++ b/arch/arm/boot/dts/r7s72100.dtsi
@@ -0,0 +1,36 @@
+/*
+ * Device Tree Source for the r7s72100 SoC
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/ {
+	compatible = "renesas,r7s72100";
+	interrupt-parent = <&gic>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+	};
+
+	gic: interrupt-controller@e8201000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+		interrupt-controller;
+		reg = <0xe8201000 0x1000>,
+			<0xe8202000 0x1000>;
+	};
+};
diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts b/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts
index f444624..9443e93 100644
--- a/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts
+++ b/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts
@@ -10,6 +10,7 @@
 
 /dts-v1/;
 /include/ "r8a73a4.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	model = "APE6EVM";
@@ -24,6 +25,34 @@
 		reg = <0 0x40000000 0 0x40000000>;
 	};
 
+	vcc_mmc0: regulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "MMC0 Vcc";
+		regulator-min-microvolt = <2800000>;
+		regulator-max-microvolt = <2800000>;
+		regulator-always-on;
+	};
+
+	vcc_sdhi0: regulator@1 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "SDHI0 Vcc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&pfc 76 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	/* Common 3.3V rail, used by several devices on APE6EVM */
+	ape6evm_fixed_3v3: regulator@2 {
+		compatible = "regulator-fixed";
+		regulator-name = "3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
 	lbsc {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -33,6 +62,7 @@
 };
 
 &i2c5 {
+	status = "okay";
 	vdd_dvfs: max8973@1b {
 		compatible = "maxim,max8973";
 		reg = <0x1b>;
@@ -62,4 +92,47 @@
 		renesas,groups = "scifa0_data";
 		renesas,function = "scifa0";
 	};
+
+	mmc0_pins: mmcif {
+		renesas,groups = "mmc0_data8", "mmc0_ctrl";
+		renesas,function = "mmc0";
+	};
+
+	sdhi0_pins: sdhi0 {
+		renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd";
+		renesas,function = "sdhi0";
+	};
+
+	sdhi1_pins: sdhi1 {
+		renesas,groups = "sdhi1_data4", "sdhi1_ctrl";
+		renesas,function = "sdhi1";
+	};
+};
+
+&mmcif0 {
+	vmmc-supply = <&vcc_mmc0>;
+	bus-width = <8>;
+	non-removable;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins>;
+	status = "okay";
+};
+
+&sdhi0 {
+	vmmc-supply = <&vcc_sdhi0>;
+	bus-width = <4>;
+	toshiba,mmc-wrprotect-disable;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdhi0_pins>;
+	status = "okay";
+};
+
+&sdhi1 {
+	vmmc-supply = <&ape6evm_fixed_3v3>;
+	bus-width = <4>;
+	broken-cd;
+	toshiba,mmc-wrprotect-disable;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdhi1_pins>;
+	status = "okay";
 };
diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/r8a73a4-ape6evm.dts
index 72f867e..91436b5 100644
--- a/arch/arm/boot/dts/r8a73a4-ape6evm.dts
+++ b/arch/arm/boot/dts/r8a73a4-ape6evm.dts
@@ -52,6 +52,7 @@
 };
 
 &i2c5 {
+	status = "okay";
 	vdd_dvfs: max8973@1b {
 		compatible = "maxim,max8973";
 		reg = <0x1b>;
diff --git a/arch/arm/boot/dts/r8a73a4.dtsi b/arch/arm/boot/dts/r8a73a4.dtsi
index 658fcc5..287e047 100644
--- a/arch/arm/boot/dts/r8a73a4.dtsi
+++ b/arch/arm/boot/dts/r8a73a4.dtsi
@@ -78,6 +78,49 @@
 				<0 56 4>, <0 57 4>;
 	};
 
+	dmac: dma-multiplexer@0 {
+		compatible = "renesas,shdma-mux";
+		#dma-cells = <1>;
+		dma-channels = <20>;
+		dma-requests = <256>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		dma0: dma-controller@e6700020 {
+			compatible = "renesas,shdma-r8a73a4";
+			reg = <0 0xe6700020 0 0x89e0>;
+			interrupt-parent = <&gic>;
+			interrupts = <0 220 4
+					0 200 4
+					0 201 4
+					0 202 4
+					0 203 4
+					0 204 4
+					0 205 4
+					0 206 4
+					0 207 4
+					0 208 4
+					0 209 4
+					0 210 4
+					0 211 4
+					0 212 4
+					0 213 4
+					0 214 4
+					0 215 4
+					0 216 4
+					0 217 4
+					0 218 4
+					0 219 4>;
+			interrupt-names = "error",
+					"ch0", "ch1", "ch2", "ch3",
+					"ch4", "ch5", "ch6", "ch7",
+					"ch8", "ch9", "ch10", "ch11",
+					"ch12", "ch13", "ch14", "ch15",
+					"ch16", "ch17", "ch18", "ch19";
+		};
+	};
+
 	thermal@e61f0000 {
 		compatible = "renesas,rcar-thermal";
 		reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>,
@@ -93,6 +136,7 @@
 		reg = <0 0xe6500000 0 0x428>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 174 0x4>;
+		status = "disabled";
 	};
 
 	i2c1: i2c@e6510000 {
@@ -102,6 +146,7 @@
 		reg = <0 0xe6510000 0 0x428>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 175 0x4>;
+		status = "disabled";
 	};
 
 	i2c2: i2c@e6520000 {
@@ -111,6 +156,7 @@
 		reg = <0 0xe6520000 0 0x428>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 176 0x4>;
+		status = "disabled";
 	};
 
 	i2c3: i2c@e6530000 {
@@ -120,6 +166,7 @@
 		reg = <0 0xe6530000 0 0x428>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 177 0x4>;
+		status = "disabled";
 	};
 
 	i2c4: i2c@e6540000 {
@@ -129,6 +176,7 @@
 		reg = <0 0xe6540000 0 0x428>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 178 0x4>;
+		status = "disabled";
 	};
 
 	i2c5: i2c@e60b0000 {
@@ -138,6 +186,7 @@
 		reg = <0 0xe60b0000 0 0x428>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 179 0x4>;
+		status = "disabled";
 	};
 
 	i2c6: i2c@e6550000 {
@@ -147,6 +196,7 @@
 		reg = <0 0xe6550000 0 0x428>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 184 0x4>;
+		status = "disabled";
 	};
 
 	i2c7: i2c@e6560000 {
@@ -156,6 +206,7 @@
 		reg = <0 0xe6560000 0 0x428>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 185 0x4>;
+		status = "disabled";
 	};
 
 	i2c8: i2c@e6570000 {
@@ -165,6 +216,7 @@
 		reg = <0 0xe6570000 0 0x428>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 173 0x4>;
+		status = "disabled";
 	};
 
 	mmcif0: mmcif@ee200000 {
diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts b/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts
index c638e4a..1c56c5e 100644
--- a/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts
+++ b/arch/arm/boot/dts/r8a7740-armadillo800eva-reference.dts
@@ -11,6 +11,7 @@
 /dts-v1/;
 /include/ "r8a7740.dtsi"
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pwm/pwm.h>
 
 / {
 	model = "armadillo 800 eva reference";
@@ -34,6 +35,33 @@
 		regulator-boot-on;
 	};
 
+	vcc_sdhi0: regulator@1 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "SDHI0 Vcc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&pfc 75 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	vccq_sdhi0: regulator@2 {
+		compatible = "regulator-gpio";
+
+		regulator-name = "SDHI0 VccQ";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&vcc_sdhi0>;
+
+		enable-gpio = <&pfc 74 GPIO_ACTIVE_HIGH>;
+		gpios = <&pfc 17 GPIO_ACTIVE_HIGH>;
+		states = <3300000 0
+			  1800000 1>;
+
+		enable-active-high;
+	};
+
 	leds {
 		compatible = "gpio-leds";
 		led1 {
@@ -49,9 +77,19 @@
 			gpios = <&pfc 177 GPIO_ACTIVE_HIGH>;
 		};
 	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&tpu 2 33333 PWM_POLARITY_INVERTED>;
+		brightness-levels = <0 1 2 4 8 16 32 64 128 255>;
+		default-brightness-level = <9>;
+		pinctrl-0 = <&backlight_pins>;
+		pinctrl-names = "default";
+	};
 };
 
 &i2c0 {
+	status = "okay";
 	touchscreen: st1232@55 {
 		compatible = "sitronix,st1232";
 		reg = <0x55>;
@@ -76,4 +114,44 @@
 		renesas,groups = "intc_irq10";
 		renesas,function = "intc";
 	};
+
+	backlight_pins: backlight {
+		renesas,groups = "tpu0_to2_1";
+		renesas,function = "tpu0";
+	};
+
+	mmc0_pins: mmc0 {
+		renesas,groups = "mmc0_data8_1", "mmc0_ctrl_1";
+		renesas,function = "mmc0";
+	};
+
+	sdhi0_pins: sdhi0 {
+		renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_wp";
+		renesas,function = "sdhi0";
+	};
+};
+
+&tpu {
+	status = "okay";
+};
+
+&mmcif0 {
+	pinctrl-0 = <&mmc0_pins>;
+	pinctrl-names = "default";
+
+	vmmc-supply = <&reg_3p3v>;
+	bus-width = <8>;
+	non-removable;
+	status = "okay";
+};
+
+&sdhi0 {
+	pinctrl-0 = <&sdhi0_pins>;
+	pinctrl-names = "default";
+
+	vmmc-supply = <&vcc_sdhi0>;
+	vqmmc-supply = <&vccq_sdhi0>;
+	bus-width = <4>;
+	cd-gpios = <&pfc 167 GPIO_ACTIVE_LOW>;
+	status = "okay";
 };
diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi
index 44d3d52..ae1e230 100644
--- a/arch/arm/boot/dts/r8a7740.dtsi
+++ b/arch/arm/boot/dts/r8a7740.dtsi
@@ -131,6 +131,7 @@
 			      0 202 0x4
 			      0 203 0x4
 			      0 204 0x4>;
+		status = "disabled";
 	};
 
 	i2c1: i2c@e6c20000 {
@@ -143,6 +144,7 @@
 			      0 71 0x4
 			      0 72 0x4
 			      0 73 0x4>;
+		status = "disabled";
 	};
 
 	pfc: pfc@e6050000 {
@@ -159,4 +161,37 @@
 		status = "disabled";
 		#pwm-cells = <3>;
 	};
+
+	mmcif0: mmcif@e6bd0000 {
+		compatible = "renesas,sh-mmcif";
+		reg = <0xe6bd0000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 56 4
+				0 57 4>;
+		status = "disabled";
+	};
+
+	sdhi0: sdhi@e6850000 {
+		compatible = "renesas,sdhi-r8a7740";
+		reg = <0xe6850000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 117 4
+				0 118 4
+				0 119 4>;
+		cap-sd-highspeed;
+		cap-sdio-irq;
+		status = "disabled";
+	};
+
+	sdhi1: sdhi@e6860000 {
+		compatible = "renesas,sdhi-r8a7740";
+		reg = <0xe6860000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 121 4
+				0 122 4
+				0 123 4>;
+		cap-sd-highspeed;
+		cap-sdio-irq;
+		status = "disabled";
+	};
 };
diff --git a/arch/arm/boot/dts/r8a7778-bockw-reference.dts b/arch/arm/boot/dts/r8a7778-bockw-reference.dts
index 9bb903a..969e386 100644
--- a/arch/arm/boot/dts/r8a7778-bockw-reference.dts
+++ b/arch/arm/boot/dts/r8a7778-bockw-reference.dts
@@ -22,11 +22,36 @@
 	compatible = "renesas,bockw-reference", "renesas,r8a7778";
 
 	chosen {
-		bootargs = "console=ttySC0,115200 ignore_loglevel rw";
+		bootargs = "console=ttySC0,115200 ignore_loglevel root=/dev/nfs ip=dhcp rw";
 	};
 
 	memory {
 		device_type = "memory";
 		reg = <0x60000000 0x10000000>;
 	};
+
+	fixedregulator3v3: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	ethernet@18300000 {
+		compatible = "smsc,lan9220", "smsc,lan9115";
+		reg = <0x18300000 0x1000>;
+
+		phy-mode = "mii";
+		interrupt-parent = <&irqpin>;
+		interrupts = <0 0>; /* IRQ0: hwirq 0 on irqpin */
+		reg-io-width = <4>;
+		vddvario-supply = <&fixedregulator3v3>;
+		vdd33a-supply = <&fixedregulator3v3>;
+	};
+};
+
+&irqpin {
+	status = "okay";
 };
diff --git a/arch/arm/boot/dts/r8a7778.dtsi b/arch/arm/boot/dts/r8a7778.dtsi
index 3577aba..a6308a3 100644
--- a/arch/arm/boot/dts/r8a7778.dtsi
+++ b/arch/arm/boot/dts/r8a7778.dtsi
@@ -33,6 +33,25 @@
 		      <0xfe430000 0x100>;
 	};
 
+	/* irqpin: IRQ0 - IRQ3 */
+	irqpin: irqpin@fe78001c {
+		compatible = "renesas,intc-irqpin";
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		status = "disabled"; /* default off */
+		reg =	<0xfe78001c 4>,
+			<0xfe780010 4>,
+			<0xfe780024 4>,
+			<0xfe780044 4>,
+			<0xfe780064 4>;
+		interrupt-parent = <&gic>;
+		interrupts =   <0 27 0x4
+				0 28 0x4
+				0 29 0x4
+				0 30 0x4>;
+		sense-bitfield-width = <2>;
+	};
+
 	gpio0: gpio@ffc40000 {
 		compatible = "renesas,gpio-r8a7778", "renesas,gpio-rcar";
 		reg = <0xffc40000 0x2c>;
diff --git a/arch/arm/boot/dts/r8a7779-marzen-reference.dts b/arch/arm/boot/dts/r8a7779-marzen-reference.dts
index 6d55083..ab4110a 100644
--- a/arch/arm/boot/dts/r8a7779-marzen-reference.dts
+++ b/arch/arm/boot/dts/r8a7779-marzen-reference.dts
@@ -42,8 +42,8 @@
 		pinctrl-names = "default";
 
 		phy-mode = "mii";
-		interrupt-parent = <&gic>;
-		interrupts = <0 28 0x4>;
+		interrupt-parent = <&irqpin0>;
+		interrupts = <1 0>; /* IRQ1: hwirq 1 on irqpin0 */
 		reg-io-width = <4>;
 		vddvario-supply = <&fixedregulator3v3>;
 		vdd33a-supply = <&fixedregulator3v3>;
@@ -63,6 +63,10 @@
 	};
 };
 
+&irqpin0 {
+	status = "okay";
+};
+
 &pfc {
 	pinctrl-0 = <&scif2_pins &scif4_pins &sdhi0_pins>;
 	pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi
index ebbe507..19faeac 100644
--- a/arch/arm/boot/dts/r8a7779.dtsi
+++ b/arch/arm/boot/dts/r8a7779.dtsi
@@ -135,6 +135,7 @@
 	irqpin0: irqpin@fe780010 {
 		compatible = "renesas,intc-irqpin";
 		#interrupt-cells = <2>;
+		status = "disabled";
 		interrupt-controller;
 		reg = <0xfe78001c 4>,
 			<0xfe780010 4>,
@@ -156,6 +157,7 @@
 		reg = <0xffc70000 0x1000>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 79 0x4>;
+		status = "disabled";
 	};
 
 	i2c1: i2c@ffc71000 {
@@ -165,6 +167,7 @@
 		reg = <0xffc71000 0x1000>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 82 0x4>;
+		status = "disabled";
 	};
 
 	i2c2: i2c@ffc72000 {
@@ -174,6 +177,7 @@
 		reg = <0xffc72000 0x1000>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 80 0x4>;
+		status = "disabled";
 	};
 
 	i2c3: i2c@ffc73000 {
@@ -183,6 +187,7 @@
 		reg = <0xffc73000 0x1000>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 81 0x4>;
+		status = "disabled";
 	};
 
 	pfc: pfc@fffc0000 {
diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 413b4c2..ee845fa 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -24,6 +24,55 @@
 			reg = <0>;
 			clock-frequency = <1300000000>;
 		};
+
+		cpu1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <1>;
+			clock-frequency = <1300000000>;
+		};
+
+		cpu2: cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <2>;
+			clock-frequency = <1300000000>;
+		};
+
+		cpu3: cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <3>;
+			clock-frequency = <1300000000>;
+		};
+
+		cpu4: cpu@4 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x100>;
+			clock-frequency = <780000000>;
+		};
+
+		cpu5: cpu@5 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x101>;
+			clock-frequency = <780000000>;
+		};
+
+		cpu6: cpu@6 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x102>;
+			clock-frequency = <780000000>;
+		};
+
+		cpu7: cpu@7 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x103>;
+			clock-frequency = <780000000>;
+		};
 	};
 
 	gic: interrupt-controller@f1001000 {
@@ -127,6 +176,46 @@
 		interrupts = <0 0 4>, <0 1 4>, <0 2 4>,	<0 3 4>;
 	};
 
+	i2c0: i2c@e6508000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,i2c-r8a7790";
+		reg = <0 0xe6508000 0 0x40>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 287 0x4>;
+		status = "disabled";
+	};
+
+	i2c1: i2c@e6518000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,i2c-r8a7790";
+		reg = <0 0xe6518000 0 0x40>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 288 0x4>;
+		status = "disabled";
+	};
+
+	i2c2: i2c@e6530000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,i2c-r8a7790";
+		reg = <0 0xe6530000 0 0x40>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 286 0x4>;
+		status = "disabled";
+	};
+
+	i2c3: i2c@e6540000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,i2c-r8a7790";
+		reg = <0 0xe6540000 0 0x40>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 290 0x4>;
+		status = "disabled";
+	};
+
 	mmcif0: mmcif@ee200000 {
 		compatible = "renesas,sh-mmcif";
 		reg = <0 0xee200000 0 0x80>;
diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts
new file mode 100644
index 0000000..1ce5250
--- /dev/null
+++ b/arch/arm/boot/dts/r8a7791-koelsch.dts
@@ -0,0 +1,32 @@
+/*
+ * Device Tree Source for the Koelsch board
+ *
+ * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/dts-v1/;
+/include/ "r8a7791.dtsi"
+
+/ {
+	model = "Koelsch";
+	compatible = "renesas,koelsch", "renesas,r8a7791";
+
+	chosen {
+		bootargs = "console=ttySC6,115200 ignore_loglevel rw root=/dev/nfs ip=dhcp";
+	};
+
+	memory@40000000 {
+		device_type = "memory";
+		reg = <0 0x40000000 0 0x80000000>;
+	};
+
+	lbsc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+};
diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
new file mode 100644
index 0000000..fea5cfe
--- /dev/null
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -0,0 +1,74 @@
+/*
+ * Device Tree Source for the r8a7791 SoC
+ *
+ * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/ {
+	compatible = "renesas,r8a7791";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0>;
+			clock-frequency = <1300000000>;
+		};
+
+		cpu1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <1>;
+			clock-frequency = <1300000000>;
+		};
+	};
+
+	gic: interrupt-controller@f1001000 {
+		compatible = "arm,cortex-a15-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+		interrupt-controller;
+		reg = <0 0xf1001000 0 0x1000>,
+			<0 0xf1002000 0 0x1000>,
+			<0 0xf1004000 0 0x2000>,
+			<0 0xf1006000 0 0x2000>;
+		interrupts = <1 9 0xf04>;
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupts = <1 13 0xf08>,
+				<1 14 0xf08>,
+				<1 11 0xf08>,
+				<1 10 0xf08>;
+	};
+
+	irqc0: interrupt-controller@e61c0000 {
+		compatible = "renesas,irqc";
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		reg = <0 0xe61c0000 0 0x200>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 0 4>,
+			      <0 1 4>,
+			      <0 2 4>,
+			      <0 3 4>,
+			      <0 12 4>,
+			      <0 13 4>,
+			      <0 14 4>,
+			      <0 15 4>,
+			      <0 16 4>,
+			      <0 17 4>;
+	};
+};
diff --git a/arch/arm/boot/dts/rk3066a-bqcurie2.dts b/arch/arm/boot/dts/rk3066a-bqcurie2.dts
new file mode 100644
index 0000000..035df40
--- /dev/null
+++ b/arch/arm/boot/dts/rk3066a-bqcurie2.dts
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+#include "rk3066a.dtsi"
+
+/ {
+	model = "bq Curie 2";
+
+	memory {
+		reg = <0x60000000 0x40000000>;
+	};
+
+	soc {
+		uart0: serial@10124000 {
+			status = "okay";
+		};
+
+		uart1: serial@10126000 {
+			status = "okay";
+		};
+
+		uart2: serial@20064000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart2_xfer>;
+			status = "okay";
+		};
+
+		uart3: serial@20068000 {
+			status = "okay";
+		};
+
+		vcc_sd0: fixed-regulator {
+			compatible = "regulator-fixed";
+			regulator-name = "sdmmc-supply";
+			regulator-min-microvolt = <3000000>;
+			regulator-max-microvolt = <3000000>;
+			gpio = <&gpio3 7 GPIO_ACTIVE_LOW>;
+			startup-delay-us = <100000>;
+		};
+
+		dwmmc@10214000 { /* sdmmc */
+			num-slots = <1>;
+			status = "okay";
+
+			pinctrl-names = "default";
+			pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_bus4>;
+			vmmc-supply = <&vcc_sd0>;
+
+			slot@0 {
+				reg = <0>;
+				bus-width = <4>;
+				disable-wp;
+			};
+		};
+
+		dwmmc@10218000 { /* wifi */
+			num-slots = <1>;
+			status = "okay";
+			non-removable;
+
+			pinctrl-names = "default";
+			pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_bus4>;
+
+			slot@0 {
+				reg = <0>;
+				bus-width = <4>;
+				disable-wp;
+			};
+		};
+
+		gpio-keys {
+			compatible = "gpio-keys";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			autorepeat;
+
+			button@0 {
+				gpios = <&gpio6 2 GPIO_ACTIVE_LOW>; /* GPIO6_A2 */
+				linux,code = <116>;
+				label = "GPIO Key Power";
+				linux,input-type = <1>;
+				gpio-key,wakeup = <1>;
+				debounce-interval = <100>;
+			};
+			button@1 {
+				gpios = <&gpio4 21 GPIO_ACTIVE_LOW>; /* GPIO4_C5 */
+				linux,code = <104>;
+				label = "GPIO Key Vol-";
+				linux,input-type = <1>;
+				gpio-key,wakeup = <0>;
+				debounce-interval = <100>;
+			};
+			/* VOL+ comes somehow thru the ADC */
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi
index 56bfac9..be5d2b0 100644
--- a/arch/arm/boot/dts/rk3066a.dtsi
+++ b/arch/arm/boot/dts/rk3066a.dtsi
@@ -14,15 +14,12 @@
  */
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/pinctrl/rockchip.h>
-#include "skeleton.dtsi"
+#include "rk3xxx.dtsi"
 #include "rk3066a-clocks.dtsi"
 
 / {
 	compatible = "rockchip,rk3066a";
-	interrupt-parent = <&gic>;
 
 	cpus {
 		#address-cells = <1>;
@@ -43,33 +40,6 @@
 	};
 
 	soc {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "simple-bus";
-		ranges;
-
-		gic: interrupt-controller@1013d000 {
-			compatible = "arm,cortex-a9-gic";
-			interrupt-controller;
-			#interrupt-cells = <3>;
-			reg = <0x1013d000 0x1000>,
-			      <0x1013c100 0x0100>;
-		};
-
-		L2: l2-cache-controller@10138000 {
-			compatible = "arm,pl310-cache";
-			reg = <0x10138000 0x1000>;
-			cache-unified;
-			cache-level = <2>;
-		};
-
-		local-timer@1013c600 {
-			compatible = "arm,cortex-a9-twd-timer";
-			reg = <0x1013c600 0x20>;
-			interrupts = <GIC_PPI 13 0x304>;
-			clocks = <&dummy150m>;
-		};
-
 		timer@20038000 {
 			compatible = "snps,dw-apb-timer-osc";
 			reg = <0x20038000 0x100>;
@@ -191,17 +161,14 @@
 				uart0_xfer: uart0-xfer {
 					rockchip,pins = <RK_GPIO1 0 RK_FUNC_1 &pcfg_pull_default>,
 							<RK_GPIO1 1 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 
 				uart0_cts: uart0-cts {
 					rockchip,pins = <RK_GPIO1 2 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 
 				uart0_rts: uart0-rts {
 					rockchip,pins = <RK_GPIO1 3 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 			};
 
@@ -209,17 +176,14 @@
 				uart1_xfer: uart1-xfer {
 					rockchip,pins = <RK_GPIO1 4 RK_FUNC_1 &pcfg_pull_default>,
 							<RK_GPIO1 5 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 
 				uart1_cts: uart1-cts {
 					rockchip,pins = <RK_GPIO1 6 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 
 				uart1_rts: uart1-rts {
 					rockchip,pins = <RK_GPIO1 7 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 			};
 
@@ -227,7 +191,6 @@
 				uart2_xfer: uart2-xfer {
 					rockchip,pins = <RK_GPIO1 8 RK_FUNC_1 &pcfg_pull_default>,
 							<RK_GPIO1 9 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 				/* no rts / cts for uart2 */
 			};
@@ -236,44 +199,36 @@
 				uart3_xfer: uart3-xfer {
 					rockchip,pins = <RK_GPIO3 27 RK_FUNC_1 &pcfg_pull_default>,
 							<RK_GPIO3 28 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 
 				uart3_cts: uart3-cts {
 					rockchip,pins = <RK_GPIO3 29 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 
 				uart3_rts: uart3-rts {
 					rockchip,pins = <RK_GPIO3 30 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 			};
 
 			sd0 {
 				sd0_clk: sd0-clk {
 					rockchip,pins = <RK_GPIO3 8 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 
 				sd0_cmd: sd0-cmd {
 					rockchip,pins = <RK_GPIO3 9 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 
 				sd0_cd: sd0-cd {
 					rockchip,pins = <RK_GPIO3 14 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 
 				sd0_wp: sd0-wp {
 					rockchip,pins = <RK_GPIO3 15 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 
 				sd0_bus1: sd0-bus-width1 {
 					rockchip,pins = <RK_GPIO3 10 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 
 				sd0_bus4: sd0-bus-width4 {
@@ -281,34 +236,28 @@
 							<RK_GPIO3 11 RK_FUNC_1 &pcfg_pull_default>,
 							<RK_GPIO3 12 RK_FUNC_1 &pcfg_pull_default>,
 							<RK_GPIO3 13 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 			};
 
 			sd1 {
 				sd1_clk: sd1-clk {
 					rockchip,pins = <RK_GPIO3 21 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 
 				sd1_cmd: sd1-cmd {
 					rockchip,pins = <RK_GPIO3 16 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 
 				sd1_cd: sd1-cd {
 					rockchip,pins = <RK_GPIO3 22 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 
 				sd1_wp: sd1-wp {
 					rockchip,pins = <RK_GPIO3 23 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 
 				sd1_bus1: sd1-bus-width1 {
 					rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 
 				sd1_bus4: sd1-bus-width4 {
@@ -316,75 +265,8 @@
 							<RK_GPIO3 18 RK_FUNC_1 &pcfg_pull_default>,
 							<RK_GPIO3 19 RK_FUNC_1 &pcfg_pull_default>,
 							<RK_GPIO3 20 RK_FUNC_1 &pcfg_pull_default>;
-					rockchip,config = <&pcfg_pull_default>;
 				};
 			};
 		};
-
-		uart0: serial@10124000 {
-			compatible = "snps,dw-apb-uart";
-			reg = <0x10124000 0x400>;
-			interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
-			reg-shift = <2>;
-			reg-io-width = <1>;
-			clocks = <&clk_gates1 8>;
-			status = "disabled";
-		};
-
-		uart1: serial@10126000 {
-			compatible = "snps,dw-apb-uart";
-			reg = <0x10126000 0x400>;
-			interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
-			reg-shift = <2>;
-			reg-io-width = <1>;
-			clocks = <&clk_gates1 10>;
-			status = "disabled";
-		};
-
-		uart2: serial@20064000 {
-			compatible = "snps,dw-apb-uart";
-			reg = <0x20064000 0x400>;
-			interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
-			reg-shift = <2>;
-			reg-io-width = <1>;
-			clocks = <&clk_gates1 12>;
-			status = "disabled";
-		};
-
-		uart3: serial@20068000 {
-			compatible = "snps,dw-apb-uart";
-			reg = <0x20068000 0x400>;
-			interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
-			reg-shift = <2>;
-			reg-io-width = <1>;
-			clocks = <&clk_gates1 14>;
-			status = "disabled";
-		};
-
-		dwmmc@10214000 {
-			compatible = "rockchip,rk2928-dw-mshc";
-			reg = <0x10214000 0x1000>;
-			interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			clocks = <&clk_gates5 10>, <&clk_gates2 11>;
-			clock-names = "biu", "ciu";
-
-			status = "disabled";
-		};
-
-		dwmmc@10218000 {
-			compatible = "rockchip,rk2928-dw-mshc";
-			reg = <0x10218000 0x1000>;
-			interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			clocks = <&clk_gates5 11>, <&clk_gates2 13>;
-			clock-names = "biu", "ciu";
-
-			status = "disabled";
-		};
 	};
 };
diff --git a/arch/arm/boot/dts/rk3188-clocks.dtsi b/arch/arm/boot/dts/rk3188-clocks.dtsi
new file mode 100644
index 0000000..b1b92dc
--- /dev/null
+++ b/arch/arm/boot/dts/rk3188-clocks.dtsi
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		/*
+		 * This is a dummy clock, to be used as placeholder on
+		 * other mux clocks when a specific parent clock is not
+		 * yet implemented. It should be dropped when the driver
+		 * is complete.
+		 */
+		dummy: dummy {
+			compatible = "fixed-clock";
+			clock-frequency = <0>;
+			#clock-cells = <0>;
+		};
+
+		xin24m: xin24m {
+			compatible = "fixed-clock";
+			clock-frequency = <24000000>;
+			#clock-cells = <0>;
+		};
+
+		dummy48m: dummy48m {
+			compatible = "fixed-clock";
+			clock-frequency = <48000000>;
+			#clock-cells = <0>;
+		};
+
+		dummy150m: dummy150m {
+			compatible = "fixed-clock";
+			clock-frequency = <150000000>;
+			#clock-cells = <0>;
+		};
+
+		clk_gates0: gate-clk@200000d0 {
+			compatible = "rockchip,rk2928-gate-clk";
+			reg = <0x200000d0 0x4>;
+			clocks = <&dummy150m>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>;
+
+			clock-output-names =
+				"gate_core_periph", "gate_cpu_gpll",
+				"gate_ddrphy", "gate_aclk_cpu",
+				"gate_hclk_cpu", "gate_pclk_cpu",
+				"gate_atclk_cpu", "gate_aclk_core",
+				"reserved", "gate_i2s0",
+				"gate_i2s0_frac", "reserved",
+				"reserved", "gate_spdif",
+				"gate_spdif_frac", "gate_testclk";
+
+			#clock-cells = <1>;
+		};
+
+		clk_gates1: gate-clk@200000d4 {
+			compatible = "rockchip,rk2928-gate-clk";
+			reg = <0x200000d4 0x4>;
+			clocks = <&xin24m>, <&xin24m>,
+				 <&xin24m>, <&dummy>,
+				 <&dummy>, <&xin24m>,
+				 <&xin24m>, <&dummy>,
+				 <&xin24m>, <&dummy>,
+				 <&xin24m>, <&dummy>,
+				 <&xin24m>, <&dummy>,
+				 <&xin24m>, <&dummy>;
+
+			clock-output-names =
+				"gate_timer0", "gate_timer1",
+				"gate_timer3", "gate_jtag",
+				"gate_aclk_lcdc1_src", "gate_otgphy0",
+				"gate_otgphy1", "gate_ddr_gpll",
+				"gate_uart0", "gate_frac_uart0",
+				"gate_uart1", "gate_frac_uart1",
+				"gate_uart2", "gate_frac_uart2",
+				"gate_uart3", "gate_frac_uart3";
+
+			#clock-cells = <1>;
+		};
+
+		clk_gates2: gate-clk@200000d8 {
+			compatible = "rockchip,rk2928-gate-clk";
+			reg = <0x200000d8 0x4>;
+			clocks = <&clk_gates2 1>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&clk_gates2 3>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy48m>,
+				 <&dummy>, <&dummy48m>,
+				 <&dummy>, <&dummy>;
+
+			clock-output-names =
+				"gate_periph_src", "gate_aclk_periph",
+				"gate_hclk_periph", "gate_pclk_periph",
+				"gate_smc", "gate_mac",
+				"gate_hsadc", "gate_hsadc_frac",
+				"gate_saradc", "gate_spi0",
+				"gate_spi1", "gate_mmc0",
+				"gate_mac_lbtest", "gate_mmc1",
+				"gate_emmc", "reserved";
+
+			#clock-cells = <1>;
+		};
+
+		clk_gates3: gate-clk@200000dc {
+			compatible = "rockchip,rk2928-gate-clk";
+			reg = <0x200000dc 0x4>;
+			clocks = <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&xin24m>, <&xin24m>,
+				 <&dummy>, <&dummy>,
+				 <&xin24m>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&xin24m>, <&dummy>;
+
+			clock-output-names =
+				"gate_aclk_lcdc0_src", "gate_dclk_lcdc0",
+				"gate_dclk_lcdc1", "gate_pclkin_cif0",
+				"gate_timer2", "gate_timer4",
+				"gate_hsicphy", "gate_cif0_out",
+				"gate_timer5", "gate_aclk_vepu",
+				"gate_hclk_vepu", "gate_aclk_vdpu",
+				"gate_hclk_vdpu", "reserved",
+				"gate_timer6", "gate_aclk_gpu_src";
+
+			#clock-cells = <1>;
+		};
+
+		clk_gates4: gate-clk@200000e0 {
+			compatible = "rockchip,rk2928-gate-clk";
+			reg = <0x200000e0 0x4>;
+			clocks = <&clk_gates2 2>, <&clk_gates2 3>,
+				 <&clk_gates2 1>, <&clk_gates2 1>,
+				 <&clk_gates2 1>, <&clk_gates2 2>,
+				 <&clk_gates2 2>, <&clk_gates2 2>,
+				 <&clk_gates0 4>, <&clk_gates0 4>,
+				 <&clk_gates0 3>, <&dummy>,
+				 <&clk_gates0 3>, <&dummy>,
+				 <&dummy>, <&dummy>;
+
+			clock-output-names =
+				"gate_hclk_peri_axi_matrix", "gate_pclk_peri_axi_matrix",
+				"gate_aclk_cpu_peri", "gate_aclk_peri_axi_matrix",
+				"gate_aclk_pei_niu", "gate_hclk_usb_peri",
+				"gate_hclk_peri_ahb_arbi", "gate_hclk_emem_peri",
+				"gate_hclk_cpubus", "gate_hclk_ahb2apb",
+				"gate_aclk_strc_sys", "reserved",
+				"gate_aclk_intmem", "reserved",
+				"gate_hclk_imem1", "gate_hclk_imem0";
+
+			#clock-cells = <1>;
+		};
+
+		clk_gates5: gate-clk@200000e4 {
+			compatible = "rockchip,rk2928-gate-clk";
+			reg = <0x200000e4 0x4>;
+			clocks = <&clk_gates0 3>, <&clk_gates2 1>,
+				 <&clk_gates0 5>, <&clk_gates0 5>,
+				 <&clk_gates0 5>, <&clk_gates0 5>,
+				 <&clk_gates0 4>, <&clk_gates0 5>,
+				 <&clk_gates2 1>, <&clk_gates2 2>,
+				 <&clk_gates2 2>, <&clk_gates2 2>,
+				 <&clk_gates2 2>, <&clk_gates4 5>;
+
+			clock-output-names =
+				"gate_aclk_dmac1", "gate_aclk_dmac2",
+				"gate_pclk_efuse", "gate_pclk_tzpc",
+				"gate_pclk_grf", "gate_pclk_pmu",
+				"gate_hclk_rom", "gate_pclk_ddrupctl",
+				"gate_aclk_smc", "gate_hclk_nandc",
+				"gate_hclk_mmc0", "gate_hclk_mmc1",
+				"gate_hclk_emmc", "gate_hclk_otg0";
+
+			#clock-cells = <1>;
+		};
+
+		clk_gates6: gate-clk@200000e8 {
+			compatible = "rockchip,rk2928-gate-clk";
+			reg = <0x200000e8 0x4>;
+			clocks = <&clk_gates3 0>, <&clk_gates0 4>,
+				 <&clk_gates0 4>, <&clk_gates1 4>,
+				 <&clk_gates0 4>, <&clk_gates3 0>,
+				 <&dummy>, <&dummy>,
+				 <&clk_gates3 0>, <&clk_gates0 4>,
+				 <&clk_gates0 4>, <&clk_gates1 4>,
+				 <&clk_gates0 4>, <&clk_gates3 0>;
+
+			clock-output-names =
+				"gate_aclk_lcdc0", "gate_hclk_lcdc0",
+				"gate_hclk_lcdc1", "gate_aclk_lcdc1",
+				"gate_hclk_cif0", "gate_aclk_cif0",
+				"reserved", "reserved",
+				"gate_aclk_ipp", "gate_hclk_ipp",
+				"gate_hclk_rga", "gate_aclk_rga",
+				"gate_hclk_vio_bus", "gate_aclk_vio0";
+
+			#clock-cells = <1>;
+		};
+
+		clk_gates7: gate-clk@200000ec {
+			compatible = "rockchip,rk2928-gate-clk";
+			reg = <0x200000ec 0x4>;
+			clocks = <&clk_gates2 2>, <&clk_gates0 4>,
+				 <&clk_gates0 4>, <&dummy>,
+				 <&dummy>, <&clk_gates2 2>,
+				 <&clk_gates2 2>, <&clk_gates0 5>,
+				 <&dummy>, <&clk_gates0 5>,
+				 <&clk_gates0 5>, <&clk_gates2 3>,
+				 <&clk_gates2 3>, <&clk_gates2 3>,
+				 <&clk_gates2 3>, <&clk_gates2 3>;
+
+			clock-output-names =
+				"gate_hclk_emac", "gate_hclk_spdif",
+				"gate_hclk_i2s0_2ch", "gate_hclk_otg1",
+				"gate_hclk_hsic", "gate_hclk_hsadc",
+				"gate_hclk_pidf", "gate_pclk_timer0",
+				"reserved", "gate_pclk_timer2",
+				"gate_pclk_pwm01", "gate_pclk_pwm23",
+				"gate_pclk_spi0", "gate_pclk_spi1",
+				"gate_pclk_saradc", "gate_pclk_wdt";
+
+			#clock-cells = <1>;
+		};
+
+		clk_gates8: gate-clk@200000f0 {
+			compatible = "rockchip,rk2928-gate-clk";
+			reg = <0x200000f0 0x4>;
+			clocks = <&clk_gates0 5>, <&clk_gates0 5>,
+				 <&clk_gates2 3>, <&clk_gates2 3>,
+				 <&clk_gates0 5>, <&clk_gates0 5>,
+				 <&clk_gates2 3>, <&clk_gates2 3>,
+				 <&clk_gates2 3>, <&clk_gates0 5>,
+				 <&clk_gates0 5>, <&clk_gates0 5>,
+				 <&clk_gates2 3>, <&dummy>;
+
+			clock-output-names =
+				"gate_pclk_uart0", "gate_pclk_uart1",
+				"gate_pclk_uart2", "gate_pclk_uart3",
+				"gate_pclk_i2c0", "gate_pclk_i2c1",
+				"gate_pclk_i2c2", "gate_pclk_i2c3",
+				"gate_pclk_i2c4", "gate_pclk_gpio0",
+				"gate_pclk_gpio1", "gate_pclk_gpio2",
+				"gate_pclk_gpio3", "gate_aclk_gps";
+
+			#clock-cells = <1>;
+		};
+
+		clk_gates9: gate-clk@200000f4 {
+			compatible = "rockchip,rk2928-gate-clk";
+			reg = <0x200000f4 0x4>;
+			clocks = <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>,
+				 <&dummy>, <&dummy>;
+
+			clock-output-names =
+				"gate_clk_core_dbg", "gate_pclk_dbg",
+				"gate_clk_trace", "gate_atclk",
+				"gate_clk_l2c", "gate_aclk_vio1",
+				"gate_pclk_publ", "gate_aclk_gpu";
+
+			#clock-cells = <1>;
+		};
+	};
+
+};
diff --git a/arch/arm/boot/dts/rk3188-radxarock.dts b/arch/arm/boot/dts/rk3188-radxarock.dts
new file mode 100644
index 0000000..3ba1968
--- /dev/null
+++ b/arch/arm/boot/dts/rk3188-radxarock.dts
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+#include "rk3188.dtsi"
+
+/ {
+	model = "Radxa Rock";
+
+	memory {
+		reg = <0x60000000 0x80000000>;
+	};
+
+	soc {
+		uart0: serial@10124000 {
+			status = "okay";
+		};
+
+		uart1: serial@10126000 {
+			status = "okay";
+		};
+
+		uart2: serial@20064000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart2_xfer>;
+			status = "okay";
+		};
+
+		uart3: serial@20068000 {
+			status = "okay";
+		};
+
+		gpio-keys {
+			compatible = "gpio-keys";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			autorepeat;
+
+			button@0 {
+				gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
+				linux,code = <116>;
+				label = "GPIO Key Power";
+				linux,input-type = <1>;
+				gpio-key,wakeup = <1>;
+				debounce-interval = <100>;
+			};
+		};
+
+		gpio-leds {
+			compatible = "gpio-leds";
+
+			green {
+				gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
+				default-state = "off";
+			};
+
+			yellow {
+				gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
+				default-state = "off";
+			};
+
+			sleep {
+				gpios = <&gpio0 15 0>;
+				default-state = "off";
+			};
+		};
+
+	};
+};
diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi
new file mode 100644
index 0000000..1a26b03
--- /dev/null
+++ b/arch/arm/boot/dts/rk3188.dtsi
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include "rk3xxx.dtsi"
+#include "rk3188-clocks.dtsi"
+
+/ {
+	compatible = "rockchip,rk3188";
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			next-level-cache = <&L2>;
+			reg = <0x0>;
+		};
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			next-level-cache = <&L2>;
+			reg = <0x1>;
+		};
+		cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			next-level-cache = <&L2>;
+			reg = <0x2>;
+		};
+		cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			next-level-cache = <&L2>;
+			reg = <0x3>;
+		};
+	};
+
+	soc {
+		global-timer@1013c200 {
+			interrupts = <GIC_PPI 11 0xf04>;
+		};
+
+		local-timer@1013c600 {
+			interrupts = <GIC_PPI 13 0xf04>;
+		};
+
+		pinctrl@20008000 {
+			compatible = "rockchip,rk3188-pinctrl";
+			reg = <0x20008000 0xa0>,
+			      <0x20008164 0x1a0>;
+			reg-names = "base", "pull";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			gpio0: gpio0@0x2000a000 {
+				compatible = "rockchip,rk3188-gpio-bank0";
+				reg = <0x2000a000 0x100>,
+				      <0x20004064 0x8>;
+				interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clk_gates8 9>;
+
+				gpio-controller;
+				#gpio-cells = <2>;
+
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio1: gpio1@0x2003c000 {
+				compatible = "rockchip,gpio-bank";
+				reg = <0x2003c000 0x100>;
+				interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clk_gates8 10>;
+
+				gpio-controller;
+				#gpio-cells = <2>;
+
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio2: gpio2@2003e000 {
+				compatible = "rockchip,gpio-bank";
+				reg = <0x2003e000 0x100>;
+				interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clk_gates8 11>;
+
+				gpio-controller;
+				#gpio-cells = <2>;
+
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			gpio3: gpio3@20080000 {
+				compatible = "rockchip,gpio-bank";
+				reg = <0x20080000 0x100>;
+				interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clk_gates8 12>;
+
+				gpio-controller;
+				#gpio-cells = <2>;
+
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			pcfg_pull_up: pcfg_pull_up {
+				bias-pull-up;
+			};
+
+			pcfg_pull_down: pcfg_pull_down {
+				bias-pull-down;
+			};
+
+			pcfg_pull_none: pcfg_pull_none {
+				bias-disable;
+			};
+
+			uart0 {
+				uart0_xfer: uart0-xfer {
+					rockchip,pins = <RK_GPIO1 0 RK_FUNC_1 &pcfg_pull_none>,
+							<RK_GPIO1 1 RK_FUNC_1 &pcfg_pull_none>;
+				};
+
+				uart0_cts: uart0-cts {
+					rockchip,pins = <RK_GPIO1 2 RK_FUNC_1 &pcfg_pull_none>;
+				};
+
+				uart0_rts: uart0-rts {
+					rockchip,pins = <RK_GPIO1 3 RK_FUNC_1 &pcfg_pull_none>;
+				};
+			};
+
+			uart1 {
+				uart1_xfer: uart1-xfer {
+					rockchip,pins = <RK_GPIO1 4 RK_FUNC_1 &pcfg_pull_none>,
+							<RK_GPIO1 5 RK_FUNC_1 &pcfg_pull_none>;
+				};
+
+				uart1_cts: uart1-cts {
+					rockchip,pins = <RK_GPIO1 6 RK_FUNC_1 &pcfg_pull_none>;
+				};
+
+				uart1_rts: uart1-rts {
+					rockchip,pins = <RK_GPIO1 7 RK_FUNC_1 &pcfg_pull_none>;
+				};
+			};
+
+			uart2 {
+				uart2_xfer: uart2-xfer {
+					rockchip,pins = <RK_GPIO1 8 RK_FUNC_1 &pcfg_pull_none>,
+							<RK_GPIO1 9 RK_FUNC_1 &pcfg_pull_none>;
+				};
+				/* no rts / cts for uart2 */
+			};
+
+			uart3 {
+				uart3_xfer: uart3-xfer {
+					rockchip,pins = <RK_GPIO1 10 RK_FUNC_1 &pcfg_pull_none>,
+							<RK_GPIO1 11 RK_FUNC_1 &pcfg_pull_none>;
+				};
+
+				uart3_cts: uart3-cts {
+					rockchip,pins = <RK_GPIO1 12 RK_FUNC_1 &pcfg_pull_none>;
+				};
+
+				uart3_rts: uart3-rts {
+					rockchip,pins = <RK_GPIO1 13 RK_FUNC_1 &pcfg_pull_none>;
+				};
+			};
+
+			sd0 {
+				sd0_clk: sd0-clk {
+					rockchip,pins = <RK_GPIO3 2 RK_FUNC_1 &pcfg_pull_none>;
+				};
+
+				sd0_cmd: sd0-cmd {
+					rockchip,pins = <RK_GPIO3 3 RK_FUNC_1 &pcfg_pull_none>;
+				};
+
+				sd0_cd: sd0-cd {
+					rockchip,pins = <RK_GPIO3 8 RK_FUNC_1 &pcfg_pull_none>;
+				};
+
+				sd0_wp: sd0-wp {
+					rockchip,pins = <RK_GPIO3 9 RK_FUNC_1 &pcfg_pull_none>;
+				};
+
+				sd0_pwr: sd0-pwr {
+					rockchip,pins = <RK_GPIO3 1 RK_FUNC_1 &pcfg_pull_none>;
+				};
+
+				sd0_bus1: sd0-bus-width1 {
+					rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>;
+				};
+
+				sd0_bus4: sd0-bus-width4 {
+					rockchip,pins = <RK_GPIO3 4 RK_FUNC_1 &pcfg_pull_none>,
+							<RK_GPIO3 5 RK_FUNC_1 &pcfg_pull_none>,
+							<RK_GPIO3 6 RK_FUNC_1 &pcfg_pull_none>,
+							<RK_GPIO3 7 RK_FUNC_1 &pcfg_pull_none>;
+				};
+			};
+
+			sd1 {
+				sd1_clk: sd1-clk {
+					rockchip,pins = <RK_GPIO3 21 RK_FUNC_1 &pcfg_pull_none>;
+				};
+
+				sd1_cmd: sd1-cmd {
+					rockchip,pins = <RK_GPIO3 16 RK_FUNC_1 &pcfg_pull_none>;
+				};
+
+				sd1_cd: sd1-cd {
+					rockchip,pins = <RK_GPIO3 22 RK_FUNC_1 &pcfg_pull_none>;
+				};
+
+				sd1_wp: sd1-wp {
+					rockchip,pins = <RK_GPIO3 23 RK_FUNC_1 &pcfg_pull_none>;
+				};
+
+				sd1_bus1: sd1-bus-width1 {
+					rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_none>;
+				};
+
+				sd1_bus4: sd1-bus-width4 {
+					rockchip,pins = <RK_GPIO3 17 RK_FUNC_1 &pcfg_pull_none>,
+							<RK_GPIO3 18 RK_FUNC_1 &pcfg_pull_none>,
+							<RK_GPIO3 19 RK_FUNC_1 &pcfg_pull_none>,
+							<RK_GPIO3 20 RK_FUNC_1 &pcfg_pull_none>;
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/rk3xxx.dtsi b/arch/arm/boot/dts/rk3xxx.dtsi
new file mode 100644
index 0000000..0fcbcfd
--- /dev/null
+++ b/arch/arm/boot/dts/rk3xxx.dtsi
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "skeleton.dtsi"
+
+/ {
+	interrupt-parent = <&gic>;
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+
+		gic: interrupt-controller@1013d000 {
+			compatible = "arm,cortex-a9-gic";
+			interrupt-controller;
+			#interrupt-cells = <3>;
+			reg = <0x1013d000 0x1000>,
+			      <0x1013c100 0x0100>;
+		};
+
+		L2: l2-cache-controller@10138000 {
+			compatible = "arm,pl310-cache";
+			reg = <0x10138000 0x1000>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		global-timer@1013c200 {
+			compatible = "arm,cortex-a9-global-timer";
+			reg = <0x1013c200 0x20>;
+			interrupts = <GIC_PPI 11 0x304>;
+			clocks = <&dummy150m>;
+		};
+
+		local-timer@1013c600 {
+			compatible = "arm,cortex-a9-twd-timer";
+			reg = <0x1013c600 0x20>;
+			interrupts = <GIC_PPI 13 0x304>;
+			clocks = <&dummy150m>;
+		};
+
+		uart0: serial@10124000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x10124000 0x400>;
+			interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <1>;
+			clocks = <&clk_gates1 8>;
+			status = "disabled";
+		};
+
+		uart1: serial@10126000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x10126000 0x400>;
+			interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <1>;
+			clocks = <&clk_gates1 10>;
+			status = "disabled";
+		};
+
+		uart2: serial@20064000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x20064000 0x400>;
+			interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <1>;
+			clocks = <&clk_gates1 12>;
+			status = "disabled";
+		};
+
+		uart3: serial@20068000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x20068000 0x400>;
+			interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <1>;
+			clocks = <&clk_gates1 14>;
+			status = "disabled";
+		};
+
+		dwmmc@10214000 {
+			compatible = "rockchip,rk2928-dw-mshc";
+			reg = <0x10214000 0x1000>;
+			interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			clocks = <&clk_gates5 10>, <&clk_gates2 11>;
+			clock-names = "biu", "ciu";
+
+			status = "disabled";
+		};
+
+		dwmmc@10218000 {
+			compatible = "rockchip,rk2928-dw-mshc";
+			reg = <0x10218000 0x1000>;
+			interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			clocks = <&clk_gates5 11>, <&clk_gates2 13>;
+			clock-names = "biu", "ciu";
+
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/s3c6400.dtsi b/arch/arm/boot/dts/s3c6400.dtsi
new file mode 100644
index 0000000..a7d1c8e
--- /dev/null
+++ b/arch/arm/boot/dts/s3c6400.dtsi
@@ -0,0 +1,41 @@
+/*
+ * Samsung's S3C6400 SoC device tree source
+ *
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * Samsung's S3C6400 SoC device nodes are listed in this file. S3C6400
+ * based board files can include this file and provide values for board specfic
+ * bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * S3C6400 SoC. As device tree coverage for S3C6400 increases, additional
+ * nodes can be added to this file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include "s3c64xx.dtsi"
+
+/ {
+	compatible = "samsung,s3c6400";
+};
+
+&vic0 {
+	valid-mask = <0xfffffe1f>;
+	valid-wakeup-mask = <0x00200004>;
+};
+
+&vic1 {
+	valid-mask = <0xffffffff>;
+	valid-wakeup-mask = <0x53020000>;
+};
+
+&soc {
+	clocks: clock-controller@7e00f000 {
+		compatible = "samsung,s3c6400-clock";
+		reg = <0x7e00f000 0x1000>;
+		#clock-cells = <1>;
+	};
+};
diff --git a/arch/arm/boot/dts/s3c6410-mini6410.dts b/arch/arm/boot/dts/s3c6410-mini6410.dts
new file mode 100644
index 0000000..57e00f9
--- /dev/null
+++ b/arch/arm/boot/dts/s3c6410-mini6410.dts
@@ -0,0 +1,228 @@
+/*
+ * Samsung's S3C6410 based Mini6410 board device tree source
+ *
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * Device tree source file for FriendlyARM Mini6410 board which is based on
+ * Samsung's S3C6410 SoC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#include "s3c6410.dtsi"
+
+/ {
+	model = "FriendlyARM Mini6410 board based on S3C6410";
+	compatible = "friendlyarm,mini6410", "samsung,s3c6410";
+
+	memory {
+		reg = <0x50000000 0x10000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttySAC0,115200n8 earlyprintk rootwait root=/dev/mmcblk0p1";
+	};
+
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		fin_pll: oscillator@0 {
+			compatible = "fixed-clock";
+			reg = <0>;
+			clock-frequency = <12000000>;
+			clock-output-names = "fin_pll";
+			#clock-cells = <0>;
+		};
+
+		xusbxti: oscillator@1 {
+			compatible = "fixed-clock";
+			reg = <1>;
+			clock-output-names = "xusbxti";
+			clock-frequency = <48000000>;
+			#clock-cells = <0>;
+		};
+	};
+
+	srom-cs1@18000000 {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x18000000 0x8000000>;
+		ranges;
+
+		ethernet@18000000 {
+			compatible = "davicom,dm9000";
+			reg = <0x18000000 0x2 0x18000004 0x2>;
+			interrupt-parent = <&gpn>;
+			interrupts = <7 IRQ_TYPE_LEVEL_HIGH>;
+			davicom,no-eeprom;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&gpio_keys>;
+		autorepeat;
+
+		button-k1 {
+			label = "K1";
+			gpios = <&gpn 0 GPIO_ACTIVE_LOW>;
+			linux,code = <2>;
+			debounce-interval = <20>;
+		};
+
+		button-k2 {
+			label = "K2";
+			gpios = <&gpn 1 GPIO_ACTIVE_LOW>;
+			linux,code = <3>;
+			debounce-interval = <20>;
+		};
+
+		button-k3 {
+			label = "K3";
+			gpios = <&gpn 2 GPIO_ACTIVE_LOW>;
+			linux,code = <4>;
+			debounce-interval = <20>;
+		};
+
+		button-k4 {
+			label = "K4";
+			gpios = <&gpn 3 GPIO_ACTIVE_LOW>;
+			linux,code = <5>;
+			debounce-interval = <20>;
+		};
+
+		button-k5 {
+			label = "K5";
+			gpios = <&gpn 4 GPIO_ACTIVE_LOW>;
+			linux,code = <6>;
+			debounce-interval = <20>;
+		};
+
+		button-k6 {
+			label = "K6";
+			gpios = <&gpn 5 GPIO_ACTIVE_LOW>;
+			linux,code = <7>;
+			debounce-interval = <20>;
+		};
+
+		button-k7 {
+			label = "K7";
+			gpios = <&gpl 11 GPIO_ACTIVE_LOW>;
+			linux,code = <8>;
+			debounce-interval = <20>;
+		};
+
+		button-k8 {
+			label = "K8";
+			gpios = <&gpl 12 GPIO_ACTIVE_LOW>;
+			linux,code = <9>;
+			debounce-interval = <20>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&gpio_leds>;
+
+		led-1 {
+			label = "LED1";
+			gpios = <&gpk 4 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "heartbeat";
+		};
+
+		led-2 {
+			label = "LED2";
+			gpios = <&gpk 5 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "mmc0";
+		};
+
+		led-3 {
+			label = "LED3";
+			gpios = <&gpk 6 GPIO_ACTIVE_LOW>;
+		};
+
+		led-4 {
+			label = "LED4";
+			gpios = <&gpk 7 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	buzzer {
+		compatible = "pwm-beeper";
+		pwms = <&pwm 0 1000000 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm0_out>;
+	};
+};
+
+&sdhci0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd0_clk>, <&sd0_cmd>, <&sd0_cd>, <&sd0_bus4>;
+	bus-width = <4>;
+	status = "okay";
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_data>;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_data>, <&uart1_fctl>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_data>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_data>;
+	status = "okay";
+};
+
+&pwm {
+	status = "okay";
+};
+
+&pinctrl0 {
+	gpio_leds: gpio-leds {
+		samsung,pins = "gpk-4", "gpk-5", "gpk-6", "gpk-7";
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	gpio_keys: gpio-keys {
+		samsung,pins = "gpn-0", "gpn-1", "gpn-2", "gpn-3",
+				"gpn-4", "gpn-5", "gpl-11", "gpl-12";
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_bus>;
+	status = "okay";
+
+	eeprom@50 {
+		compatible = "atmel,24c08";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+};
diff --git a/arch/arm/boot/dts/s3c6410-smdk6410.dts b/arch/arm/boot/dts/s3c6410-smdk6410.dts
new file mode 100644
index 0000000..ecf35ec
--- /dev/null
+++ b/arch/arm/boot/dts/s3c6410-smdk6410.dts
@@ -0,0 +1,103 @@
+/*
+ * Samsung S3C6410 based SMDK6410 board device tree source.
+ *
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * Device tree source file for SAMSUNG SMDK6410 board which is based on
+ * Samsung's S3C6410 SoC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#include "s3c6410.dtsi"
+
+/ {
+	model = "SAMSUNG SMDK6410 board based on S3C6410";
+	compatible = "samsung,mini6410", "samsung,s3c6410";
+
+	memory {
+		reg = <0x50000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttySAC0,115200n8 earlyprintk rootwait root=/dev/mmcblk0p1";
+	};
+
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		fin_pll: oscillator@0 {
+			compatible = "fixed-clock";
+			reg = <0>;
+			clock-frequency = <12000000>;
+			clock-output-names = "fin_pll";
+			#clock-cells = <0>;
+		};
+
+		xusbxti: oscillator@1 {
+			compatible = "fixed-clock";
+			reg = <1>;
+			clock-output-names = "xusbxti";
+			clock-frequency = <48000000>;
+			#clock-cells = <0>;
+		};
+	};
+
+	srom-cs1@18000000 {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x18000000 0x8000000>;
+		ranges;
+
+		ethernet@18000000 {
+			compatible = "smsc,lan9115";
+			reg = <0x18000000 0x10000>;
+			interrupt-parent = <&gpn>;
+			interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
+			phy-mode = "mii";
+			reg-io-width = <4>;
+			smsc,force-internal-phy;
+		};
+	};
+};
+
+&sdhci0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd0_clk>, <&sd0_cmd>, <&sd0_cd>, <&sd0_bus4>;
+	bus-width = <4>;
+	status = "okay";
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_data>, <&uart0_fctl>;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_data>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_data>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_data>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/s3c6410.dtsi b/arch/arm/boot/dts/s3c6410.dtsi
new file mode 100644
index 0000000..eb4226b
--- /dev/null
+++ b/arch/arm/boot/dts/s3c6410.dtsi
@@ -0,0 +1,57 @@
+/*
+ * Samsung's S3C6410 SoC device tree source
+ *
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * Samsung's S3C6410 SoC device nodes are listed in this file. S3C6410
+ * based board files can include this file and provide values for board specfic
+ * bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * S3C6410 SoC. As device tree coverage for S3C6410 increases, additional
+ * nodes can be added to this file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include "s3c64xx.dtsi"
+
+/ {
+	compatible = "samsung,s3c6410";
+
+	aliases {
+		i2c1 = &i2c1;
+	};
+};
+
+&vic0 {
+	valid-mask = <0xffffff7f>;
+	valid-wakeup-mask = <0x00200004>;
+};
+
+&vic1 {
+	valid-mask = <0xffffffff>;
+	valid-wakeup-mask = <0x53020000>;
+};
+
+&soc {
+	clocks: clock-controller@7e00f000 {
+		compatible = "samsung,s3c6410-clock";
+		reg = <0x7e00f000 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	i2c1: i2c@7f00f000 {
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x7f00f000 0x1000>;
+		interrupt-parent = <&vic0>;
+		interrupts = <5>;
+		clock-names = "i2c";
+		clocks = <&clocks PCLK_IIC1>;
+		status = "disabled";
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+};
diff --git a/arch/arm/boot/dts/s3c64xx-pinctrl.dtsi b/arch/arm/boot/dts/s3c64xx-pinctrl.dtsi
new file mode 100644
index 0000000..b1197d8
--- /dev/null
+++ b/arch/arm/boot/dts/s3c64xx-pinctrl.dtsi
@@ -0,0 +1,687 @@
+/*
+ * Samsung's S3C64xx SoC series common device tree source
+ * - pin control-related definitions
+ *
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * Samsung's S3C64xx SoCs pin banks, pin-mux and pin-config options are
+ * listed as device tree nodes in this file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define PIN_PULL_NONE	0
+#define PIN_PULL_DOWN	1
+#define PIN_PULL_UP	2
+
+&pinctrl0 {
+	/*
+	 * Pin banks
+	 */
+
+	gpa: gpa {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpb: gpb {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpc: gpc {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpd: gpd {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpe: gpe {
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	gpf: gpf {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpg: gpg {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gph: gph {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpi: gpi {
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	gpj: gpj {
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	gpk: gpk {
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	gpl: gpl {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpm: gpm {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpn: gpn {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpo: gpo {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpp: gpp {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpq: gpq {
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	/*
+	 * Pin groups
+	 */
+
+	uart0_data: uart0-data {
+		samsung,pins = "gpa-0", "gpa-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	uart0_fctl: uart0-fctl {
+		samsung,pins = "gpa-2", "gpa-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	uart1_data: uart1-data {
+		samsung,pins = "gpa-4", "gpa-5";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	uart1_fctl: uart1-fctl {
+		samsung,pins = "gpa-6", "gpa-7";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	uart2_data: uart2-data {
+		samsung,pins = "gpb-0", "gpb-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	uart3_data: uart3-data {
+		samsung,pins = "gpb-2", "gpb-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	ext_dma_0: ext-dma-0 {
+		samsung,pins = "gpb-0", "gpb-1";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	ext_dma_1: ext-dma-1 {
+		samsung,pins = "gpb-2", "gpb-3";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	irda_data_0: irda-data-0 {
+		samsung,pins = "gpb-0", "gpb-1";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	irda_data_1: irda-data-1 {
+		samsung,pins = "gpb-2", "gpb-3";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	irda_sdbw: irda-sdbw {
+		samsung,pins = "gpb-4";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	i2c0_bus: i2c0-bus {
+		samsung,pins = "gpb-5", "gpb-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_UP>;
+	};
+
+	i2c1_bus: i2c1-bus {
+		/* S3C6410-only */
+		samsung,pins = "gpb-2", "gpb-3";
+		samsung,pin-function = <6>;
+		samsung,pin-pud = <PIN_PULL_UP>;
+	};
+
+	spi0_bus: spi0-bus {
+		samsung,pins = "gpc-0", "gpc-1", "gpc-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_UP>;
+	};
+
+	spi0_cs: spi0-cs {
+		samsung,pins = "gpc-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	spi1_bus: spi1-bus {
+		samsung,pins = "gpc-4", "gpc-5", "gpc-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_UP>;
+	};
+
+	spi1_cs: spi1-cs {
+		samsung,pins = "gpc-7";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	sd0_cmd: sd0-cmd {
+		samsung,pins = "gpg-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	sd0_clk: sd0-clk {
+		samsung,pins = "gpg-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	sd0_bus1: sd0-bus1 {
+		samsung,pins = "gpg-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	sd0_bus4: sd0-bus4 {
+		samsung,pins = "gpg-2", "gpg-3", "gpg-4", "gpg-5";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	sd0_cd: sd0-cd {
+		samsung,pins = "gpg-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_UP>;
+	};
+
+	sd1_cmd: sd1-cmd {
+		samsung,pins = "gph-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	sd1_clk: sd1-clk {
+		samsung,pins = "gph-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	sd1_bus1: sd1-bus1 {
+		samsung,pins = "gph-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	sd1_bus4: sd1-bus4 {
+		samsung,pins = "gph-2", "gph-3", "gph-4", "gph-5";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	sd1_bus8: sd1-bus8 {
+		samsung,pins = "gph-2", "gph-3", "gph-4", "gph-5",
+				"gph-6", "gph-7", "gph-8", "gph-9";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	sd1_cd: sd1-cd {
+		samsung,pins = "gpg-6";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_UP>;
+	};
+
+	sd2_cmd: sd2-cmd {
+		samsung,pins = "gpc-4";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	sd2_clk: sd2-clk {
+		samsung,pins = "gpc-5";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	sd2_bus1: sd2-bus1 {
+		samsung,pins = "gph-6";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	sd2_bus4: sd2-bus4 {
+		samsung,pins = "gph-6", "gph-7", "gph-8", "gph-9";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	i2s0_bus: i2s0-bus {
+		samsung,pins = "gpd-0", "gpd-2", "gpd-3", "gpd-4";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	i2s0_cdclk: i2s0-cdclk {
+		samsung,pins = "gpd-1";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	i2s1_bus: i2s1-bus {
+		samsung,pins = "gpe-0", "gpe-2", "gpe-3", "gpe-4";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	i2s1_cdclk: i2s1-cdclk {
+		samsung,pins = "gpe-1";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	i2s2_bus: i2s2-bus {
+		/* S3C6410-only */
+		samsung,pins = "gpc-4", "gpc-5", "gpc-6", "gph-6",
+				"gph-8", "gph-9";
+		samsung,pin-function = <5>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	i2s2_cdclk: i2s2-cdclk {
+		/* S3C6410-only */
+		samsung,pins = "gph-7";
+		samsung,pin-function = <5>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	pcm0_bus: pcm0-bus {
+		samsung,pins = "gpd-0", "gpd-2", "gpd-3", "gpd-4";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	pcm0_extclk: pcm0-extclk {
+		samsung,pins = "gpd-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	pcm1_bus: pcm1-bus {
+		samsung,pins = "gpe-0", "gpe-2", "gpe-3", "gpe-4";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	pcm1_extclk: pcm1-extclk {
+		samsung,pins = "gpe-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	ac97_bus_0: ac97-bus-0 {
+		samsung,pins = "gpd-0", "gpd-1", "gpd-2", "gpd-3", "gpd-4";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	ac97_bus_1: ac97-bus-1 {
+		samsung,pins = "gpe-0", "gpe-1", "gpe-2", "gpe-3", "gpe-4";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	cam_port: cam-port {
+		samsung,pins = "gpf-0", "gpf-1", "gpf-2", "gpf-4",
+				"gpf-5", "gpf-6", "gpf-7", "gpf-8",
+				"gpf-9", "gpf-10", "gpf-11", "gpf-12";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	cam_rst: cam-rst {
+		samsung,pins = "gpf-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	cam_field: cam-field {
+		/* S3C6410-only */
+		samsung,pins = "gpb-4";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	pwm_extclk: pwm-extclk {
+		samsung,pins = "gpf-13";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	pwm0_out: pwm0-out {
+		samsung,pins = "gpf-14";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	pwm1_out: pwm1-out {
+		samsung,pins = "gpf-15";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	clkout0: clkout-0 {
+		samsung,pins = "gpf-14";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_col0_0: keypad-col0-0 {
+		samsung,pins = "gph-0";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_col1_0: keypad-col1-0 {
+		samsung,pins = "gph-1";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_col2_0: keypad-col2-0 {
+		samsung,pins = "gph-2";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_col3_0: keypad-col3-0 {
+		samsung,pins = "gph-3";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_col4_0: keypad-col4-0 {
+		samsung,pins = "gph-4";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_col5_0: keypad-col5-0 {
+		samsung,pins = "gph-5";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_col6_0: keypad-col6-0 {
+		samsung,pins = "gph-6";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_col7_0: keypad-col7-0 {
+		samsung,pins = "gph-7";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_col0_1: keypad-col0-1 {
+		samsung,pins = "gpl-0";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_col1_1: keypad-col1-1 {
+		samsung,pins = "gpl-1";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_col2_1: keypad-col2-1 {
+		samsung,pins = "gpl-2";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_col3_1: keypad-col3-1 {
+		samsung,pins = "gpl-3";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_col4_1: keypad-col4-1 {
+		samsung,pins = "gpl-4";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_col5_1: keypad-col5-1 {
+		samsung,pins = "gpl-5";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_col6_1: keypad-col6-1 {
+		samsung,pins = "gpl-6";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_col7_1: keypad-col7-1 {
+		samsung,pins = "gpl-7";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_row0_0: keypad-row0-0 {
+		samsung,pins = "gpk-8";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_row1_0: keypad-row1-0 {
+		samsung,pins = "gpk-9";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_row2_0: keypad-row2-0 {
+		samsung,pins = "gpk-10";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_row3_0: keypad-row3-0 {
+		samsung,pins = "gpk-11";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_row4_0: keypad-row4-0 {
+		samsung,pins = "gpk-12";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_row5_0: keypad-row5-0 {
+		samsung,pins = "gpk-13";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_row6_0: keypad-row6-0 {
+		samsung,pins = "gpk-14";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_row7_0: keypad-row7-0 {
+		samsung,pins = "gpk-15";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_row0_1: keypad-row0-1 {
+		samsung,pins = "gpn-0";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_row1_1: keypad-row1-1 {
+		samsung,pins = "gpn-1";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_row2_1: keypad-row2-1 {
+		samsung,pins = "gpn-2";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_row3_1: keypad-row3-1 {
+		samsung,pins = "gpn-3";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_row4_1: keypad-row4-1 {
+		samsung,pins = "gpn-4";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_row5_1: keypad-row5-1 {
+		samsung,pins = "gpn-5";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_row6_1: keypad-row6-1 {
+		samsung,pins = "gpn-6";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	keypad_row7_1: keypad-row7-1 {
+		samsung,pins = "gpn-7";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	lcd_ctrl: lcd-ctrl {
+		samsung,pins = "gpj-8", "gpj-9", "gpj-10", "gpj-11";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	lcd_data16: lcd-data-width16 {
+		samsung,pins = "gpi-3", "gpi-4", "gpi-5", "gpi-6",
+				"gpi-7", "gpi-10", "gpi-11", "gpi-12",
+				"gpi-13", "gpi-14", "gpi-15", "gpj-3",
+				"gpj-4", "gpj-5", "gpj-6", "gpj-7";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	lcd_data18: lcd-data-width18 {
+		samsung,pins = "gpi-2", "gpi-3", "gpi-4", "gpi-5",
+				"gpi-6", "gpi-7", "gpi-10", "gpi-11",
+				"gpi-12", "gpi-13", "gpi-14", "gpi-15",
+				"gpj-2", "gpj-3", "gpj-4", "gpj-5",
+				"gpj-6", "gpj-7";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	lcd_data24: lcd-data-width24 {
+		samsung,pins = "gpi-0", "gpi-1", "gpi-2", "gpi-3",
+				"gpi-4", "gpi-5", "gpi-6", "gpi-7",
+				"gpi-8", "gpi-9", "gpi-10", "gpi-11",
+				"gpi-12", "gpi-13", "gpi-14", "gpi-15",
+				"gpj-0", "gpj-1", "gpj-2", "gpj-3",
+				"gpj-4", "gpj-5", "gpj-6", "gpj-7";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+
+	hsi_bus: hsi-bus {
+		samsung,pins = "gpk-0", "gpk-1", "gpk-2", "gpk-3",
+				"gpk-4", "gpk-5", "gpk-6", "gpk-7";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <PIN_PULL_NONE>;
+	};
+};
diff --git a/arch/arm/boot/dts/s3c64xx.dtsi b/arch/arm/boot/dts/s3c64xx.dtsi
new file mode 100644
index 0000000..4e3be4d
--- /dev/null
+++ b/arch/arm/boot/dts/s3c64xx.dtsi
@@ -0,0 +1,199 @@
+/*
+ * Samsung's S3C64xx SoC series common device tree source
+ *
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * Samsung's S3C64xx SoC series device nodes are listed in this file.
+ * Particular SoCs from S3C64xx series can include this file and provide
+ * values for SoCs specfic bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * S3C64xx SoCs. As device tree coverage for S3C64xx increases, additional
+ * nodes can be added to this file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "skeleton.dtsi"
+#include <dt-bindings/clock/samsung,s3c64xx-clock.h>
+
+/ {
+	aliases {
+		i2c0 = &i2c0;
+		pinctrl0 = &pinctrl0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,arm1176jzf-s", "arm,arm1176";
+			reg = <0x0>;
+		};
+	};
+
+	soc: soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		vic0: interrupt-controller@71200000 {
+			compatible = "arm,pl192-vic";
+			interrupt-controller;
+			reg = <0x71200000 0x1000>;
+			#interrupt-cells = <1>;
+		};
+
+		vic1: interrupt-controller@71300000 {
+			compatible = "arm,pl192-vic";
+			interrupt-controller;
+			reg = <0x71300000 0x1000>;
+			#interrupt-cells = <1>;
+		};
+
+		sdhci0: sdhci@7c200000 {
+			compatible = "samsung,s3c6410-sdhci";
+			reg = <0x7c200000 0x100>;
+			interrupt-parent = <&vic1>;
+			interrupts = <24>;
+			clock-names = "hsmmc", "mmc_busclk.0", "mmc_busclk.2";
+			clocks = <&clocks HCLK_HSMMC0>, <&clocks HCLK_HSMMC0>,
+					<&clocks SCLK_MMC0>;
+			status = "disabled";
+		};
+
+		sdhci1: sdhci@7c300000 {
+			compatible = "samsung,s3c6410-sdhci";
+			reg = <0x7c300000 0x100>;
+			interrupt-parent = <&vic1>;
+			interrupts = <25>;
+			clock-names = "hsmmc", "mmc_busclk.0", "mmc_busclk.2";
+			clocks = <&clocks HCLK_HSMMC1>, <&clocks HCLK_HSMMC1>,
+					<&clocks SCLK_MMC1>;
+			status = "disabled";
+		};
+
+		sdhci2: sdhci@7c400000 {
+			compatible = "samsung,s3c6410-sdhci";
+			reg = <0x7c400000 0x100>;
+			interrupt-parent = <&vic1>;
+			interrupts = <17>;
+			clock-names = "hsmmc", "mmc_busclk.0", "mmc_busclk.2";
+			clocks = <&clocks HCLK_HSMMC2>, <&clocks HCLK_HSMMC2>,
+					<&clocks SCLK_MMC2>;
+			status = "disabled";
+		};
+
+		watchdog: watchdog@7e004000 {
+			compatible = "samsung,s3c2410-wdt";
+			reg = <0x7e004000 0x1000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <26>;
+			clock-names = "watchdog";
+			clocks = <&clocks PCLK_WDT>;
+			status = "disabled";
+		};
+
+		i2c0: i2c@7f004000 {
+			compatible = "samsung,s3c2440-i2c";
+			reg = <0x7f004000 0x1000>;
+			interrupt-parent = <&vic1>;
+			interrupts = <18>;
+			clock-names = "i2c";
+			clocks = <&clocks PCLK_IIC0>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		uart0: serial@7f005000 {
+			compatible = "samsung,s3c6400-uart";
+			reg = <0x7f005000 0x100>;
+			interrupt-parent = <&vic1>;
+			interrupts = <5>;
+			clock-names = "uart", "clk_uart_baud2",
+					"clk_uart_baud3";
+			clocks = <&clocks PCLK_UART0>, <&clocks PCLK_UART0>,
+					<&clocks SCLK_UART>;
+			status = "disabled";
+		};
+
+		uart1: serial@7f005400 {
+			compatible = "samsung,s3c6400-uart";
+			reg = <0x7f005400 0x100>;
+			interrupt-parent = <&vic1>;
+			interrupts = <6>;
+			clock-names = "uart", "clk_uart_baud2",
+					"clk_uart_baud3";
+			clocks = <&clocks PCLK_UART1>, <&clocks PCLK_UART1>,
+					<&clocks SCLK_UART>;
+			status = "disabled";
+		};
+
+		uart2: serial@7f005800 {
+			compatible = "samsung,s3c6400-uart";
+			reg = <0x7f005800 0x100>;
+			interrupt-parent = <&vic1>;
+			interrupts = <7>;
+			clock-names = "uart", "clk_uart_baud2",
+					"clk_uart_baud3";
+			clocks = <&clocks PCLK_UART2>, <&clocks PCLK_UART2>,
+					<&clocks SCLK_UART>;
+			status = "disabled";
+		};
+
+		uart3: serial@7f005c00 {
+			compatible = "samsung,s3c6400-uart";
+			reg = <0x7f005c00 0x100>;
+			interrupt-parent = <&vic1>;
+			interrupts = <8>;
+			clock-names = "uart", "clk_uart_baud2",
+					"clk_uart_baud3";
+			clocks = <&clocks PCLK_UART3>, <&clocks PCLK_UART3>,
+					<&clocks SCLK_UART>;
+			status = "disabled";
+		};
+
+		pwm: pwm@7f006000 {
+			compatible = "samsung,s3c6400-pwm";
+			reg = <0x7f006000 0x1000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <23>, <24>, <25>, <27>, <28>;
+			clock-names = "timers";
+			clocks = <&clocks PCLK_PWM>;
+			samsung,pwm-outputs = <0>, <1>;
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		pinctrl0: pinctrl@7f008000 {
+			compatible = "samsung,s3c64xx-pinctrl";
+			reg = <0x7f008000 0x1000>;
+			interrupt-parent = <&vic1>;
+			interrupts = <21>;
+
+			pctrl_int_map: pinctrl-interrupt-map {
+				interrupt-map = <0 &vic0 0>,
+						<1 &vic0 1>,
+						<2 &vic1 0>,
+						<3 &vic1 1>;
+				#address-cells = <0>;
+				#size-cells = <0>;
+				#interrupt-cells = <1>;
+			};
+
+			wakeup-interrupt-controller {
+				compatible = "samsung,s3c64xx-wakeup-eint";
+				interrupts = <0>, <1>, <2>, <3>;
+				interrupt-parent = <&pctrl_int_map>;
+			};
+		};
+	};
+};
+
+#include "s3c64xx-pinctrl.dtsi"
diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi
index b7f4961..5cdaba4 100644
--- a/arch/arm/boot/dts/sama5d3.dtsi
+++ b/arch/arm/boot/dts/sama5d3.dtsi
@@ -31,7 +31,6 @@
 		gpio3 = &pioD;
 		gpio4 = &pioE;
 		tcb0 = &tcb0;
-		tcb1 = &tcb1;
 		i2c0 = &i2c0;
 		i2c1 = &i2c1;
 		i2c2 = &i2c2;
@@ -105,15 +104,6 @@
 				status = "disabled";
 			};
 
-			can0: can@f000c000 {
-				compatible = "atmel,at91sam9x5-can";
-				reg = <0xf000c000 0x300>;
-				interrupts = <40 IRQ_TYPE_LEVEL_HIGH 3>;
-				pinctrl-names = "default";
-				pinctrl-0 = <&pinctrl_can0_rx_tx>;
-				status = "disabled";
-			};
-
 			tcb0: timer@f0010000 {
 				compatible = "atmel,at91sam9x5-tcb";
 				reg = <0xf0010000 0x100>;
@@ -166,15 +156,6 @@
 				status = "disabled";
 			};
 
-			macb0: ethernet@f0028000 {
-				compatible = "cdns,pc302-gem", "cdns,gem";
-				reg = <0xf0028000 0x100>;
-				interrupts = <34 IRQ_TYPE_LEVEL_HIGH 3>;
-				pinctrl-names = "default";
-				pinctrl-0 = <&pinctrl_macb0_data_rgmii &pinctrl_macb0_signal_rgmii>;
-				status = "disabled";
-			};
-
 			isi: isi@f0034000 {
 				compatible = "atmel,at91sam9g45-isi";
 				reg = <0xf0034000 0x4000>;
@@ -195,19 +176,6 @@
 				#size-cells = <0>;
 			};
 
-			mmc2: mmc@f8004000 {
-				compatible = "atmel,hsmci";
-				reg = <0xf8004000 0x600>;
-				interrupts = <23 IRQ_TYPE_LEVEL_HIGH 0>;
-				dmas = <&dma1 2 AT91_DMA_CFG_PER_ID(1)>;
-				dma-names = "rxtx";
-				pinctrl-names = "default";
-				pinctrl-0 = <&pinctrl_mmc2_clk_cmd_dat0 &pinctrl_mmc2_dat1_3>;
-				status = "disabled";
-				#address-cells = <1>;
-				#size-cells = <0>;
-			};
-
 			spi1: spi@f8008000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
@@ -231,20 +199,6 @@
 				status = "disabled";
 			};
 
-			can1: can@f8010000 {
-				compatible = "atmel,at91sam9x5-can";
-				reg = <0xf8010000 0x300>;
-				interrupts = <41 IRQ_TYPE_LEVEL_HIGH 3>;
-				pinctrl-names = "default";
-				pinctrl-0 = <&pinctrl_can1_rx_tx>;
-			};
-
-			tcb1: timer@f8014000 {
-				compatible = "atmel,at91sam9x5-tcb";
-				reg = <0xf8014000 0x100>;
-				interrupts = <27 IRQ_TYPE_LEVEL_HIGH 0>;
-			};
-
 			adc0: adc@f8018000 {
 				compatible = "atmel,at91sam9260-adc";
 				reg = <0xf8018000 0x100>;
@@ -341,15 +295,6 @@
 				status = "disabled";
 			};
 
-			macb1: ethernet@f802c000 {
-				compatible = "cdns,at32ap7000-macb", "cdns,macb";
-				reg = <0xf802c000 0x100>;
-				interrupts = <35 IRQ_TYPE_LEVEL_HIGH 3>;
-				pinctrl-names = "default";
-				pinctrl-0 = <&pinctrl_macb1_rmii>;
-				status = "disabled";
-			};
-
 			sha@f8034000 {
 				compatible = "atmel,sam9g46-sha";
 				reg = <0xf8034000 0x100>;
@@ -474,22 +419,6 @@
 					};
 				};
 
-				can0 {
-					pinctrl_can0_rx_tx: can0_rx_tx {
-						atmel,pins =
-							<AT91_PIOD 14 AT91_PERIPH_C AT91_PINCTRL_NONE	/* PD14 periph C RX, conflicts with SCK0, SPI0_NPCS1 */
-							 AT91_PIOD 15 AT91_PERIPH_C AT91_PINCTRL_NONE>;	/* PD15 periph C TX, conflicts with CTS0, SPI0_NPCS2 */
-					};
-				};
-
-				can1 {
-					pinctrl_can1_rx_tx: can1_rx_tx {
-						atmel,pins =
-							<AT91_PIOB 14 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PB14 periph B RX, conflicts with GCRS */
-							 AT91_PIOB 15 AT91_PERIPH_B AT91_PINCTRL_NONE>;	/* PB15 periph B TX, conflicts with GCOL */
-					};
-				};
-
 				dbgu {
 					pinctrl_dbgu: dbgu-0 {
 						atmel,pins =
@@ -537,107 +466,6 @@
 					};
 				};
 
-				lcd {
-					pinctrl_lcd: lcd-0 {
-						atmel,pins =
-							<AT91_PIOA 24 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA24 periph A LCDPWM */
-							 AT91_PIOA 26 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA26 periph A LCDVSYNC */
-							 AT91_PIOA 27 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA27 periph A LCDHSYNC */
-							 AT91_PIOA 25 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA25 periph A LCDDISP */
-							 AT91_PIOA 29 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA29 periph A LCDDEN */
-							 AT91_PIOA 28 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA28 periph A LCDPCK */
-							 AT91_PIOA 0 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA0 periph A LCDD0 pin */
-							 AT91_PIOA 1 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA1 periph A LCDD1 pin */
-							 AT91_PIOA 2 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA2 periph A LCDD2 pin */
-							 AT91_PIOA 3 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA3 periph A LCDD3 pin */
-							 AT91_PIOA 4 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA4 periph A LCDD4 pin */
-							 AT91_PIOA 5 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA5 periph A LCDD5 pin */
-							 AT91_PIOA 6 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA6 periph A LCDD6 pin */
-							 AT91_PIOA 7 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA7 periph A LCDD7 pin */
-							 AT91_PIOA 8 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA8 periph A LCDD8 pin */
-							 AT91_PIOA 9 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA9 periph A LCDD9 pin */
-							 AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA10 periph A LCDD10 pin */
-							 AT91_PIOA 11 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA11 periph A LCDD11 pin */
-							 AT91_PIOA 12 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA12 periph A LCDD12 pin */
-							 AT91_PIOA 13 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA13 periph A LCDD13 pin */
-							 AT91_PIOA 14 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA14 periph A LCDD14 pin */
-							 AT91_PIOA 15 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA15 periph A LCDD15 pin */
-							 AT91_PIOC 14 AT91_PERIPH_C AT91_PINCTRL_NONE	/* PC14 periph C LCDD16 pin */
-							 AT91_PIOC 13 AT91_PERIPH_C AT91_PINCTRL_NONE	/* PC13 periph C LCDD17 pin */
-							 AT91_PIOC 12 AT91_PERIPH_C AT91_PINCTRL_NONE	/* PC12 periph C LCDD18 pin */
-							 AT91_PIOC 11 AT91_PERIPH_C AT91_PINCTRL_NONE	/* PC11 periph C LCDD19 pin */
-							 AT91_PIOC 10 AT91_PERIPH_C AT91_PINCTRL_NONE	/* PC10 periph C LCDD20 pin */
-							 AT91_PIOC 15 AT91_PERIPH_C AT91_PINCTRL_NONE	/* PC15 periph C LCDD21 pin */
-							 AT91_PIOE 27 AT91_PERIPH_C AT91_PINCTRL_NONE	/* PE27 periph C LCDD22 pin */
-							 AT91_PIOE 28 AT91_PERIPH_C AT91_PINCTRL_NONE>;	/* PE28 periph C LCDD23 pin */
-					};
-				};
-
-				macb0 {
-					pinctrl_macb0_data_rgmii: macb0_data_rgmii {
-						atmel,pins =
-							<AT91_PIOB 0 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB0 periph A GTX0, conflicts with PWMH0 */
-							 AT91_PIOB 1 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB1 periph A GTX1, conflicts with PWML0 */
-							 AT91_PIOB 2 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB2 periph A GTX2, conflicts with TK1 */
-							 AT91_PIOB 3 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB3 periph A GTX3, conflicts with TF1 */
-							 AT91_PIOB 4 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB4 periph A GRX0, conflicts with PWMH1 */
-							 AT91_PIOB 5 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB5 periph A GRX1, conflicts with PWML1 */
-							 AT91_PIOB 6 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB6 periph A GRX2, conflicts with TD1 */
-							 AT91_PIOB 7 AT91_PERIPH_A AT91_PINCTRL_NONE>;	/* PB7 periph A GRX3, conflicts with RK1 */
-					};
-					pinctrl_macb0_data_gmii: macb0_data_gmii {
-						atmel,pins =
-							<AT91_PIOB 19 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PB19 periph B GTX4, conflicts with MCI1_CDA */
-							 AT91_PIOB 20 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PB20 periph B GTX5, conflicts with MCI1_DA0 */
-							 AT91_PIOB 21 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PB21 periph B GTX6, conflicts with MCI1_DA1 */
-							 AT91_PIOB 22 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PB22 periph B GTX7, conflicts with MCI1_DA2 */
-							 AT91_PIOB 23 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PB23 periph B GRX4, conflicts with MCI1_DA3 */
-							 AT91_PIOB 24 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PB24 periph B GRX5, conflicts with MCI1_CK */
-							 AT91_PIOB 25 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PB25 periph B GRX6, conflicts with SCK1 */
-							 AT91_PIOB 26 AT91_PERIPH_B AT91_PINCTRL_NONE>;	/* PB26 periph B GRX7, conflicts with CTS1 */
-					};
-					pinctrl_macb0_signal_rgmii: macb0_signal_rgmii {
-						atmel,pins =
-							<AT91_PIOB 8 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB8 periph A GTXCK, conflicts with PWMH2 */
-							 AT91_PIOB 9 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB9 periph A GTXEN, conflicts with PWML2 */
-							 AT91_PIOB 11 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB11 periph A GRXCK, conflicts with RD1 */
-							 AT91_PIOB 13 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB13 periph A GRXER, conflicts with PWML3 */
-							 AT91_PIOB 16 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB16 periph A GMDC */
-							 AT91_PIOB 17 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB17 periph A GMDIO */
-							 AT91_PIOB 18 AT91_PERIPH_A AT91_PINCTRL_NONE>;	/* PB18 periph A G125CK */
-					};
-					pinctrl_macb0_signal_gmii: macb0_signal_gmii {
-						atmel,pins =
-							<AT91_PIOB 9 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB9 periph A GTXEN, conflicts with PWML2 */
-							 AT91_PIOB 10 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB10 periph A GTXER, conflicts with RF1 */
-							 AT91_PIOB 11 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB11 periph A GRXCK, conflicts with RD1 */
-							 AT91_PIOB 12 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB12 periph A GRXDV, conflicts with PWMH3 */
-							 AT91_PIOB 13 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB13 periph A GRXER, conflicts with PWML3 */
-							 AT91_PIOB 14 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB14 periph A GCRS, conflicts with CANRX1 */
-							 AT91_PIOB 15 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB15 periph A GCOL, conflicts with CANTX1 */
-							 AT91_PIOB 16 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB16 periph A GMDC */
-							 AT91_PIOB 17 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB17 periph A GMDIO */
-							 AT91_PIOB 27 AT91_PERIPH_B AT91_PINCTRL_NONE>;	/* PB27 periph B G125CKO */
-					};
-
-				};
-
-				macb1 {
-					pinctrl_macb1_rmii: macb1_rmii-0 {
-						atmel,pins =
-							<AT91_PIOC 0 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC0 periph A ETX0, conflicts with TIOA3 */
-							 AT91_PIOC 1 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC1 periph A ETX1, conflicts with TIOB3 */
-							 AT91_PIOC 2 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC2 periph A ERX0, conflicts with TCLK3 */
-							 AT91_PIOC 3 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC3 periph A ERX1, conflicts with TIOA4 */
-							 AT91_PIOC 4 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC4 periph A ETXEN, conflicts with TIOB4 */
-							 AT91_PIOC 5 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC5 periph A ECRSDV,conflicts with TCLK4 */
-							 AT91_PIOC 6 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC6 periph A ERXER, conflicts with TIOA5 */
-							 AT91_PIOC 7 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC7 periph A EREFCK, conflicts with TIOB5 */
-							 AT91_PIOC 8 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC8 periph A EMDC, conflicts with TCLK5 */
-							 AT91_PIOC 9 AT91_PERIPH_A AT91_PINCTRL_NONE>;	/* PC9 periph A EMDIO  */
-					};
-				};
-
 				mmc0 {
 					pinctrl_mmc0_clk_cmd_dat0: mmc0_clk_cmd_dat0 {
 						atmel,pins =
@@ -675,21 +503,6 @@
 					};
 				};
 
-				mmc2 {
-					pinctrl_mmc2_clk_cmd_dat0: mmc2_clk_cmd_dat0 {
-						atmel,pins =
-							<AT91_PIOC 15 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC15 periph A MCI2_CK, conflicts with PCK2 */
-							 AT91_PIOC 10 AT91_PERIPH_A AT91_PINCTRL_PULL_UP	/* PC10 periph A MCI2_CDA with pullup */
-							 AT91_PIOC 11 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;	/* PC11 periph A MCI2_DA0 with pullup */
-					};
-					pinctrl_mmc2_dat1_3: mmc2_dat1_3 {
-						atmel,pins =
-							<AT91_PIOC 12 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC12 periph A MCI2_DA1 with pullup, conflicts with TIOA1 */
-							 AT91_PIOC 13 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC13 periph A MCI2_DA2 with pullup, conflicts with TIOB1 */
-							 AT91_PIOC 14 AT91_PERIPH_A AT91_PINCTRL_NONE>;	/* PC14 periph A MCI2_DA3 with pullup, conflicts with TCLK1 */
-					};
-				};
-
 				nand0 {
 					pinctrl_nand0_ale_cle: nand0_ale_cle-0 {
 						atmel,pins =
@@ -748,22 +561,6 @@
 					};
 				};
 
-				uart0 {
-					pinctrl_uart0: uart0-0 {
-						atmel,pins =
-							<AT91_PIOC 29 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC29 periph A, conflicts with PWMFI2, ISI_D8 */
-							 AT91_PIOC 30 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;	/* PC30 periph A with pullup, conflicts with ISI_PCK */
-					};
-				};
-
-				uart1 {
-					pinctrl_uart1: uart1-0 {
-						atmel,pins =
-							<AT91_PIOA 30 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PA30 periph B, conflicts with TWD0, ISI_VSYNC */
-							 AT91_PIOA 31 AT91_PERIPH_B AT91_PINCTRL_PULL_UP>;	/* PA31 periph B with pullup, conflicts with TWCK0, ISI_HSYNC */
-					};
-				};
-
 				usart0 {
 					pinctrl_usart0: usart0-0 {
 						atmel,pins =
diff --git a/arch/arm/boot/dts/sama5d31.dtsi b/arch/arm/boot/dts/sama5d31.dtsi
new file mode 100644
index 0000000..7997dc9
--- /dev/null
+++ b/arch/arm/boot/dts/sama5d31.dtsi
@@ -0,0 +1,16 @@
+/*
+ * sama5d31.dtsi - Device Tree Include file for SAMA5D31 SoC
+ *
+ *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+#include "sama5d3.dtsi"
+#include "sama5d3_lcd.dtsi"
+#include "sama5d3_emac.dtsi"
+#include "sama5d3_mci2.dtsi"
+#include "sama5d3_uart.dtsi"
+
+/ {
+	compatible = "atmel,samad31", "atmel,sama5d3", "atmel,sama5";
+};
diff --git a/arch/arm/boot/dts/sama5d31ek.dts b/arch/arm/boot/dts/sama5d31ek.dts
index 027bac7..04eec0d 100644
--- a/arch/arm/boot/dts/sama5d31ek.dts
+++ b/arch/arm/boot/dts/sama5d31ek.dts
@@ -7,12 +7,13 @@
  * Licensed under GPLv2 or later.
  */
 /dts-v1/;
+#include "sama5d31.dtsi"
 #include "sama5d3xmb.dtsi"
 #include "sama5d3xdm.dtsi"
 
 / {
 	model = "Atmel SAMA5D31-EK";
-	compatible = "atmel,sama5d31ek", "atmel,sama5d3xmb", "atmel,sama5d3xcm", "atmel,sama5d3", "atmel,sama5";
+	compatible = "atmel,sama5d31ek", "atmel,sama5d3xmb", "atmel,sama5d3xcm", "atmel,sama5d31", "atmel,sama5d3", "atmel,sama5";
 
 	ahb {
 		apb {
diff --git a/arch/arm/boot/dts/sama5d33.dtsi b/arch/arm/boot/dts/sama5d33.dtsi
new file mode 100644
index 0000000..39f8322
--- /dev/null
+++ b/arch/arm/boot/dts/sama5d33.dtsi
@@ -0,0 +1,14 @@
+/*
+ * sama5d33.dtsi - Device Tree Include file for SAMA5D33 SoC
+ *
+ *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+#include "sama5d3.dtsi"
+#include "sama5d3_lcd.dtsi"
+#include "sama5d3_gmac.dtsi"
+
+/ {
+	compatible = "atmel,samad33", "atmel,sama5d3", "atmel,sama5";
+};
diff --git a/arch/arm/boot/dts/sama5d33ek.dts b/arch/arm/boot/dts/sama5d33ek.dts
index 99bd0c8..cbd6a3f 100644
--- a/arch/arm/boot/dts/sama5d33ek.dts
+++ b/arch/arm/boot/dts/sama5d33ek.dts
@@ -7,12 +7,13 @@
  * Licensed under GPLv2 or later.
  */
 /dts-v1/;
+#include "sama5d33.dtsi"
 #include "sama5d3xmb.dtsi"
 #include "sama5d3xdm.dtsi"
 
 / {
 	model = "Atmel SAMA5D33-EK";
-	compatible = "atmel,sama5d33ek", "atmel,sama5d3xmb", "atmel,sama5d3xcm", "atmel,sama5d3", "atmel,sama5";
+	compatible = "atmel,sama5d33ek", "atmel,sama5d3xmb", "atmel,sama5d3xcm", "atmel,sama5d33", "atmel,sama5d3", "atmel,sama5";
 
 	ahb {
 		apb {
diff --git a/arch/arm/boot/dts/sama5d34.dtsi b/arch/arm/boot/dts/sama5d34.dtsi
new file mode 100644
index 0000000..89cda2c
--- /dev/null
+++ b/arch/arm/boot/dts/sama5d34.dtsi
@@ -0,0 +1,16 @@
+/*
+ * sama5d34.dtsi - Device Tree Include file for SAMA5D34 SoC
+ *
+ *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+#include "sama5d3.dtsi"
+#include "sama5d3_lcd.dtsi"
+#include "sama5d3_gmac.dtsi"
+#include "sama5d3_can.dtsi"
+#include "sama5d3_mci2.dtsi"
+
+/ {
+	compatible = "atmel,samad34", "atmel,sama5d3", "atmel,sama5";
+};
diff --git a/arch/arm/boot/dts/sama5d34ek.dts b/arch/arm/boot/dts/sama5d34ek.dts
index fb8ee11..878aa16 100644
--- a/arch/arm/boot/dts/sama5d34ek.dts
+++ b/arch/arm/boot/dts/sama5d34ek.dts
@@ -7,12 +7,13 @@
  * Licensed under GPLv2 or later.
  */
 /dts-v1/;
+#include "sama5d34.dtsi"
 #include "sama5d3xmb.dtsi"
 #include "sama5d3xdm.dtsi"
 
 / {
 	model = "Atmel SAMA5D34-EK";
-	compatible = "atmel,sama5d34ek", "atmel,sama5d3xmb", "atmel,sama5d3xcm", "atmel,sama5d3", "atmel,sama5";
+	compatible = "atmel,sama5d34ek", "atmel,sama5d3xmb", "atmel,sama5d3xcm", "atmel,sama5d34", "atmel,sama5d3", "atmel,sama5";
 
 	ahb {
 		apb {
diff --git a/arch/arm/boot/dts/sama5d35.dtsi b/arch/arm/boot/dts/sama5d35.dtsi
new file mode 100644
index 0000000..d20cd71
--- /dev/null
+++ b/arch/arm/boot/dts/sama5d35.dtsi
@@ -0,0 +1,18 @@
+/*
+ * sama5d35.dtsi - Device Tree Include file for SAMA5D35 SoC
+ *
+ *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+#include "sama5d3.dtsi"
+#include "sama5d3_gmac.dtsi"
+#include "sama5d3_emac.dtsi"
+#include "sama5d3_can.dtsi"
+#include "sama5d3_mci2.dtsi"
+#include "sama5d3_uart.dtsi"
+#include "sama5d3_tcb1.dtsi"
+
+/ {
+	compatible = "atmel,samad35", "atmel,sama5d3", "atmel,sama5";
+};
diff --git a/arch/arm/boot/dts/sama5d35ek.dts b/arch/arm/boot/dts/sama5d35ek.dts
index 509a53d..9089c7c 100644
--- a/arch/arm/boot/dts/sama5d35ek.dts
+++ b/arch/arm/boot/dts/sama5d35ek.dts
@@ -7,11 +7,12 @@
  * Licensed under GPLv2 or later.
  */
 /dts-v1/;
+#include "sama5d35.dtsi"
 #include "sama5d3xmb.dtsi"
 
 / {
 	model = "Atmel SAMA5D35-EK";
-	compatible = "atmel,sama5d35ek", "atmel,sama5d3xmb", "atmel,sama5d3xcm", "atmel,sama5d3", "atmel,sama5";
+	compatible = "atmel,sama5d35ek", "atmel,sama5d3xmb", "atmel,sama5d3xcm", "atmel,sama5d35", "atmel,sama5d3", "atmel,sama5";
 
 	ahb {
 		apb {
diff --git a/arch/arm/boot/dts/sama5d3_can.dtsi b/arch/arm/boot/dts/sama5d3_can.dtsi
new file mode 100644
index 0000000..8ed3260
--- /dev/null
+++ b/arch/arm/boot/dts/sama5d3_can.dtsi
@@ -0,0 +1,54 @@
+/*
+ * at91sama5d3_can.dtsi - Device Tree Include file for AT91SAM9x5 SoC with
+ * CAN support
+ *
+ * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+#include <dt-bindings/pinctrl/at91.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	ahb {
+		apb {
+			pinctrl@fffff200 {
+				can0 {
+					pinctrl_can0_rx_tx: can0_rx_tx {
+						atmel,pins =
+							<AT91_PIOD 14 AT91_PERIPH_C AT91_PINCTRL_NONE	/* PD14 periph C RX, conflicts with SCK0, SPI0_NPCS1 */
+							 AT91_PIOD 15 AT91_PERIPH_C AT91_PINCTRL_NONE>;	/* PD15 periph C TX, conflicts with CTS0, SPI0_NPCS2 */
+					};
+				};
+
+				can1 {
+					pinctrl_can1_rx_tx: can1_rx_tx {
+						atmel,pins =
+							<AT91_PIOB 14 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PB14 periph B RX, conflicts with GCRS */
+							 AT91_PIOB 15 AT91_PERIPH_B AT91_PINCTRL_NONE>;	/* PB15 periph B TX, conflicts with GCOL */
+					};
+				};
+
+			};
+
+			can0: can@f000c000 {
+				compatible = "atmel,at91sam9x5-can";
+				reg = <0xf000c000 0x300>;
+				interrupts = <40 IRQ_TYPE_LEVEL_HIGH 3>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_can0_rx_tx>;
+				status = "disabled";
+			};
+
+			can1: can@f8010000 {
+				compatible = "atmel,at91sam9x5-can";
+				reg = <0xf8010000 0x300>;
+				interrupts = <41 IRQ_TYPE_LEVEL_HIGH 3>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_can1_rx_tx>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/sama5d3_emac.dtsi b/arch/arm/boot/dts/sama5d3_emac.dtsi
new file mode 100644
index 0000000..4d4f351
--- /dev/null
+++ b/arch/arm/boot/dts/sama5d3_emac.dtsi
@@ -0,0 +1,44 @@
+/*
+ * at91sama5d3_emac.dtsi - Device Tree Include file for AT91SAM9x5 SoC with
+ * Ethernet.
+ *
+ * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+#include <dt-bindings/pinctrl/at91.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	ahb {
+		apb {
+			pinctrl@fffff200 {
+				macb1 {
+					pinctrl_macb1_rmii: macb1_rmii-0 {
+						atmel,pins =
+							<AT91_PIOC 0 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC0 periph A ETX0, conflicts with TIOA3 */
+							 AT91_PIOC 1 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC1 periph A ETX1, conflicts with TIOB3 */
+							 AT91_PIOC 2 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC2 periph A ERX0, conflicts with TCLK3 */
+							 AT91_PIOC 3 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC3 periph A ERX1, conflicts with TIOA4 */
+							 AT91_PIOC 4 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC4 periph A ETXEN, conflicts with TIOB4 */
+							 AT91_PIOC 5 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC5 periph A ECRSDV,conflicts with TCLK4 */
+							 AT91_PIOC 6 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC6 periph A ERXER, conflicts with TIOA5 */
+							 AT91_PIOC 7 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC7 periph A EREFCK, conflicts with TIOB5 */
+							 AT91_PIOC 8 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC8 periph A EMDC, conflicts with TCLK5 */
+							 AT91_PIOC 9 AT91_PERIPH_A AT91_PINCTRL_NONE>;	/* PC9 periph A EMDIO  */
+					};
+				};
+			};
+
+			macb1: ethernet@f802c000 {
+				compatible = "cdns,at32ap7000-macb", "cdns,macb";
+				reg = <0xf802c000 0x100>;
+				interrupts = <35 IRQ_TYPE_LEVEL_HIGH 3>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_macb1_rmii>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/sama5d3_gmac.dtsi b/arch/arm/boot/dts/sama5d3_gmac.dtsi
new file mode 100644
index 0000000..0ba8be3
--- /dev/null
+++ b/arch/arm/boot/dts/sama5d3_gmac.dtsi
@@ -0,0 +1,77 @@
+/*
+ * at91sama5d3_gmac.dtsi - Device Tree Include file for AT91SAM9x5 SoC with
+ * Gigabit Ethernet.
+ *
+ * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+#include <dt-bindings/pinctrl/at91.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	ahb {
+		apb {
+			pinctrl@fffff200 {
+				macb0 {
+					pinctrl_macb0_data_rgmii: macb0_data_rgmii {
+						atmel,pins =
+							<AT91_PIOB 0 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB0 periph A GTX0, conflicts with PWMH0 */
+							 AT91_PIOB 1 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB1 periph A GTX1, conflicts with PWML0 */
+							 AT91_PIOB 2 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB2 periph A GTX2, conflicts with TK1 */
+							 AT91_PIOB 3 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB3 periph A GTX3, conflicts with TF1 */
+							 AT91_PIOB 4 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB4 periph A GRX0, conflicts with PWMH1 */
+							 AT91_PIOB 5 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB5 periph A GRX1, conflicts with PWML1 */
+							 AT91_PIOB 6 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB6 periph A GRX2, conflicts with TD1 */
+							 AT91_PIOB 7 AT91_PERIPH_A AT91_PINCTRL_NONE>;	/* PB7 periph A GRX3, conflicts with RK1 */
+					};
+					pinctrl_macb0_data_gmii: macb0_data_gmii {
+						atmel,pins =
+							<AT91_PIOB 19 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PB19 periph B GTX4, conflicts with MCI1_CDA */
+							 AT91_PIOB 20 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PB20 periph B GTX5, conflicts with MCI1_DA0 */
+							 AT91_PIOB 21 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PB21 periph B GTX6, conflicts with MCI1_DA1 */
+							 AT91_PIOB 22 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PB22 periph B GTX7, conflicts with MCI1_DA2 */
+							 AT91_PIOB 23 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PB23 periph B GRX4, conflicts with MCI1_DA3 */
+							 AT91_PIOB 24 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PB24 periph B GRX5, conflicts with MCI1_CK */
+							 AT91_PIOB 25 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PB25 periph B GRX6, conflicts with SCK1 */
+							 AT91_PIOB 26 AT91_PERIPH_B AT91_PINCTRL_NONE>;	/* PB26 periph B GRX7, conflicts with CTS1 */
+					};
+					pinctrl_macb0_signal_rgmii: macb0_signal_rgmii {
+						atmel,pins =
+							<AT91_PIOB 8 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB8 periph A GTXCK, conflicts with PWMH2 */
+							 AT91_PIOB 9 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB9 periph A GTXEN, conflicts with PWML2 */
+							 AT91_PIOB 11 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB11 periph A GRXCK, conflicts with RD1 */
+							 AT91_PIOB 13 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB13 periph A GRXER, conflicts with PWML3 */
+							 AT91_PIOB 16 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB16 periph A GMDC */
+							 AT91_PIOB 17 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB17 periph A GMDIO */
+							 AT91_PIOB 18 AT91_PERIPH_A AT91_PINCTRL_NONE>;	/* PB18 periph A G125CK */
+					};
+					pinctrl_macb0_signal_gmii: macb0_signal_gmii {
+						atmel,pins =
+							<AT91_PIOB 9 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB9 periph A GTXEN, conflicts with PWML2 */
+							 AT91_PIOB 10 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB10 periph A GTXER, conflicts with RF1 */
+							 AT91_PIOB 11 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB11 periph A GRXCK, conflicts with RD1 */
+							 AT91_PIOB 12 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB12 periph A GRXDV, conflicts with PWMH3 */
+							 AT91_PIOB 13 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB13 periph A GRXER, conflicts with PWML3 */
+							 AT91_PIOB 14 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB14 periph A GCRS, conflicts with CANRX1 */
+							 AT91_PIOB 15 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB15 periph A GCOL, conflicts with CANTX1 */
+							 AT91_PIOB 16 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB16 periph A GMDC */
+							 AT91_PIOB 17 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB17 periph A GMDIO */
+							 AT91_PIOB 27 AT91_PERIPH_B AT91_PINCTRL_NONE>;	/* PB27 periph B G125CKO */
+					};
+
+				};
+			};
+
+			macb0: ethernet@f0028000 {
+				compatible = "cdns,pc302-gem", "cdns,gem";
+				reg = <0xf0028000 0x100>;
+				interrupts = <34 IRQ_TYPE_LEVEL_HIGH 3>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_macb0_data_rgmii &pinctrl_macb0_signal_rgmii>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/sama5d3_lcd.dtsi b/arch/arm/boot/dts/sama5d3_lcd.dtsi
new file mode 100644
index 0000000..01f52a7
--- /dev/null
+++ b/arch/arm/boot/dts/sama5d3_lcd.dtsi
@@ -0,0 +1,55 @@
+/*
+ * at91sama5d3_lcd.dtsi - Device Tree Include file for AT91SAM9x5 SoC with
+ * LCD support
+ *
+ * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+#include <dt-bindings/pinctrl/at91.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	ahb {
+		apb {
+			pinctrl@fffff200 {
+				lcd {
+					pinctrl_lcd: lcd-0 {
+						atmel,pins =
+							<AT91_PIOA 24 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA24 periph A LCDPWM */
+							 AT91_PIOA 26 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA26 periph A LCDVSYNC */
+							 AT91_PIOA 27 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA27 periph A LCDHSYNC */
+							 AT91_PIOA 25 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA25 periph A LCDDISP */
+							 AT91_PIOA 29 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA29 periph A LCDDEN */
+							 AT91_PIOA 28 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA28 periph A LCDPCK */
+							 AT91_PIOA 0 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA0 periph A LCDD0 pin */
+							 AT91_PIOA 1 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA1 periph A LCDD1 pin */
+							 AT91_PIOA 2 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA2 periph A LCDD2 pin */
+							 AT91_PIOA 3 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA3 periph A LCDD3 pin */
+							 AT91_PIOA 4 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA4 periph A LCDD4 pin */
+							 AT91_PIOA 5 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA5 periph A LCDD5 pin */
+							 AT91_PIOA 6 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA6 periph A LCDD6 pin */
+							 AT91_PIOA 7 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA7 periph A LCDD7 pin */
+							 AT91_PIOA 8 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA8 periph A LCDD8 pin */
+							 AT91_PIOA 9 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA9 periph A LCDD9 pin */
+							 AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA10 periph A LCDD10 pin */
+							 AT91_PIOA 11 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA11 periph A LCDD11 pin */
+							 AT91_PIOA 12 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA12 periph A LCDD12 pin */
+							 AT91_PIOA 13 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA13 periph A LCDD13 pin */
+							 AT91_PIOA 14 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA14 periph A LCDD14 pin */
+							 AT91_PIOA 15 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA15 periph A LCDD15 pin */
+							 AT91_PIOC 14 AT91_PERIPH_C AT91_PINCTRL_NONE	/* PC14 periph C LCDD16 pin */
+							 AT91_PIOC 13 AT91_PERIPH_C AT91_PINCTRL_NONE	/* PC13 periph C LCDD17 pin */
+							 AT91_PIOC 12 AT91_PERIPH_C AT91_PINCTRL_NONE	/* PC12 periph C LCDD18 pin */
+							 AT91_PIOC 11 AT91_PERIPH_C AT91_PINCTRL_NONE	/* PC11 periph C LCDD19 pin */
+							 AT91_PIOC 10 AT91_PERIPH_C AT91_PINCTRL_NONE	/* PC10 periph C LCDD20 pin */
+							 AT91_PIOC 15 AT91_PERIPH_C AT91_PINCTRL_NONE	/* PC15 periph C LCDD21 pin */
+							 AT91_PIOE 27 AT91_PERIPH_C AT91_PINCTRL_NONE	/* PE27 periph C LCDD22 pin */
+							 AT91_PIOE 28 AT91_PERIPH_C AT91_PINCTRL_NONE>;	/* PE28 periph C LCDD23 pin */
+					};
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/sama5d3_mci2.dtsi b/arch/arm/boot/dts/sama5d3_mci2.dtsi
new file mode 100644
index 0000000..38e88e3
--- /dev/null
+++ b/arch/arm/boot/dts/sama5d3_mci2.dtsi
@@ -0,0 +1,47 @@
+/*
+ * at91sama5d3_mci2.dtsi - Device Tree Include file for AT91SAM9x5 SoC with
+ * 3 MMC ports
+ *
+ * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+#include <dt-bindings/pinctrl/at91.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	ahb {
+		apb {
+			pinctrl@fffff200 {
+				mmc2 {
+					pinctrl_mmc2_clk_cmd_dat0: mmc2_clk_cmd_dat0 {
+						atmel,pins =
+							<AT91_PIOC 15 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC15 periph A MCI2_CK, conflicts with PCK2 */
+							 AT91_PIOC 10 AT91_PERIPH_A AT91_PINCTRL_PULL_UP	/* PC10 periph A MCI2_CDA with pullup */
+							 AT91_PIOC 11 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;	/* PC11 periph A MCI2_DA0 with pullup */
+					};
+					pinctrl_mmc2_dat1_3: mmc2_dat1_3 {
+						atmel,pins =
+							<AT91_PIOC 12 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC12 periph A MCI2_DA1 with pullup, conflicts with TIOA1 */
+							 AT91_PIOC 13 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC13 periph A MCI2_DA2 with pullup, conflicts with TIOB1 */
+							 AT91_PIOC 14 AT91_PERIPH_A AT91_PINCTRL_NONE>;	/* PC14 periph A MCI2_DA3 with pullup, conflicts with TCLK1 */
+					};
+				};
+			};
+
+			mmc2: mmc@f8004000 {
+				compatible = "atmel,hsmci";
+				reg = <0xf8004000 0x600>;
+				interrupts = <23 IRQ_TYPE_LEVEL_HIGH 0>;
+				dmas = <&dma1 2 AT91_DMA_CFG_PER_ID(1)>;
+				dma-names = "rxtx";
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_mmc2_clk_cmd_dat0 &pinctrl_mmc2_dat1_3>;
+				status = "disabled";
+				#address-cells = <1>;
+				#size-cells = <0>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/sama5d3_tcb1.dtsi b/arch/arm/boot/dts/sama5d3_tcb1.dtsi
new file mode 100644
index 0000000..5264bb4
--- /dev/null
+++ b/arch/arm/boot/dts/sama5d3_tcb1.dtsi
@@ -0,0 +1,27 @@
+/*
+ * at91sama5d3_tcb1.dtsi - Device Tree Include file for AT91SAM9x5 SoC with
+ * 2 TC blocks.
+ *
+ * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+#include <dt-bindings/pinctrl/at91.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	aliases {
+		tcb1 = &tcb1;
+	};
+
+	ahb {
+		apb {
+			tcb1: timer@f8014000 {
+				compatible = "atmel,at91sam9x5-tcb";
+				reg = <0xf8014000 0x100>;
+				interrupts = <27 IRQ_TYPE_LEVEL_HIGH 0>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/sama5d3_uart.dtsi b/arch/arm/boot/dts/sama5d3_uart.dtsi
new file mode 100644
index 0000000..98fcb2d
--- /dev/null
+++ b/arch/arm/boot/dts/sama5d3_uart.dtsi
@@ -0,0 +1,53 @@
+/*
+ * at91sama5d3_uart.dtsi - Device Tree Include file for AT91SAM9x5 SoC with
+ * UART support
+ *
+ * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
+ *
+ * Licensed under GPLv2.
+ */
+
+#include <dt-bindings/pinctrl/at91.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	ahb {
+		apb {
+			pinctrl@fffff200 {
+				uart0 {
+					pinctrl_uart0: uart0-0 {
+						atmel,pins =
+							<AT91_PIOC 29 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC29 periph A, conflicts with PWMFI2, ISI_D8 */
+							 AT91_PIOC 30 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;	/* PC30 periph A with pullup, conflicts with ISI_PCK */
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1: uart1-0 {
+						atmel,pins =
+							<AT91_PIOA 30 AT91_PERIPH_B AT91_PINCTRL_NONE	/* PA30 periph B, conflicts with TWD0, ISI_VSYNC */
+							 AT91_PIOA 31 AT91_PERIPH_B AT91_PINCTRL_PULL_UP>;	/* PA31 periph B with pullup, conflicts with TWCK0, ISI_HSYNC */
+					};
+				};
+			};
+
+			uart0: serial@f0024000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xf0024000 0x200>;
+				interrupts = <16 IRQ_TYPE_LEVEL_HIGH 5>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart0>;
+				status = "disabled";
+			};
+
+			uart1: serial@f8028000 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0xf8028000 0x200>;
+				interrupts = <17 IRQ_TYPE_LEVEL_HIGH 5>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart1>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/sama5d3xcm.dtsi b/arch/arm/boot/dts/sama5d3xcm.dtsi
index 31ed9e3..726a0f3 100644
--- a/arch/arm/boot/dts/sama5d3xcm.dtsi
+++ b/arch/arm/boot/dts/sama5d3xcm.dtsi
@@ -6,7 +6,6 @@
  *
  * Licensed under GPLv2 or later.
  */
-#include "sama5d3.dtsi"
 
 / {
 	compatible = "atmel,samad3xcm", "atmel,sama5d3", "atmel,sama5";
diff --git a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
index 2122306..8ee06dd 100644
--- a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
+++ b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts
@@ -108,6 +108,7 @@
 };
 
 &i2c0 {
+	status = "okay";
 	as3711@40 {
 		compatible = "ams,as3711";
 		reg = <0x40>;
@@ -183,6 +184,7 @@
 &i2c3 {
 	pinctrl-0 = <&i2c3_pins>;
 	pinctrl-names = "default";
+	status = "okay";
 };
 
 &mmcif {
diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi
index 3955c76..fcf2688 100644
--- a/arch/arm/boot/dts/sh73a0.dtsi
+++ b/arch/arm/boot/dts/sh73a0.dtsi
@@ -135,6 +135,7 @@
 			      0 168 0x4
 			      0 169 0x4
 			      0 170 0x4>;
+		status = "disabled";
 	};
 
 	i2c1: i2c@e6822000 {
@@ -147,6 +148,7 @@
 			      0 52 0x4
 			      0 53 0x4
 			      0 54 0x4>;
+		status = "disabled";
 	};
 
 	i2c2: i2c@e6824000 {
@@ -159,6 +161,7 @@
 			      0 172 0x4
 			      0 173 0x4
 			      0 174 0x4>;
+		status = "disabled";
 	};
 
 	i2c3: i2c@e6826000 {
@@ -171,6 +174,7 @@
 			      0 184 0x4
 			      0 185 0x4
 			      0 186 0x4>;
+		status = "disabled";
 	};
 
 	i2c4: i2c@e6828000 {
@@ -183,6 +187,7 @@
 			      0 188 0x4
 			      0 189 0x4
 			      0 190 0x4>;
+		status = "disabled";
 	};
 
 	mmcif: mmcif@e6bd0000 {
diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi
index e273fa9..6d09b8d 100644
--- a/arch/arm/boot/dts/socfpga.dtsi
+++ b/arch/arm/boot/dts/socfpga.dtsi
@@ -147,7 +147,7 @@
 							reg = <0x58>;
 						};
 
-						cfg_s2f_usr0_clk: cfg_s2f_usr0_clk {
+						cfg_h2f_usr0_clk: cfg_h2f_usr0_clk {
 							#clock-cells = <0>;
 							compatible = "altr,socfpga-perip-clk";
 							clocks = <&main_pll>;
@@ -198,7 +198,7 @@
 							reg = <0x98>;
 						};
 
-						s2f_usr1_clk: s2f_usr1_clk {
+						h2f_usr1_clk: h2f_usr1_clk {
 							#clock-cells = <0>;
 							compatible = "altr,socfpga-perip-clk";
 							clocks = <&periph_pll>;
@@ -235,7 +235,7 @@
 							reg = <0xD0>;
 						};
 
-						s2f_usr2_clk: s2f_usr2_clk {
+						h2f_usr2_clk: h2f_usr2_clk {
 							#clock-cells = <0>;
 							compatible = "altr,socfpga-perip-clk";
 							clocks = <&sdram_pll>;
@@ -243,197 +243,197 @@
 						};
 					};
 
-				mpu_periph_clk: mpu_periph_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&mpuclk>;
-					fixed-divider = <4>;
+					mpu_periph_clk: mpu_periph_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&mpuclk>;
+						fixed-divider = <4>;
 					};
 
-				mpu_l2_ram_clk: mpu_l2_ram_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&mpuclk>;
-					fixed-divider = <2>;
+					mpu_l2_ram_clk: mpu_l2_ram_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&mpuclk>;
+						fixed-divider = <2>;
 					};
 
-				l4_main_clk: l4_main_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&mainclk>;
-					clk-gate = <0x60 0>;
+					l4_main_clk: l4_main_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&mainclk>;
+						clk-gate = <0x60 0>;
 					};
 
-				l3_main_clk: l3_main_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&mainclk>;
+					l3_main_clk: l3_main_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&mainclk>;
 					};
 
-				l3_mp_clk: l3_mp_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&mainclk>;
-					div-reg = <0x64 0 2>;
-					clk-gate = <0x60 1>;
+					l3_mp_clk: l3_mp_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&mainclk>;
+						div-reg = <0x64 0 2>;
+						clk-gate = <0x60 1>;
 					};
 
-				l3_sp_clk: l3_sp_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&mainclk>;
-					div-reg = <0x64 2 2>;
-				};
-
-				l4_mp_clk: l4_mp_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&mainclk>, <&per_base_clk>;
-					div-reg = <0x64 4 3>;
-					clk-gate = <0x60 2>;
+					l3_sp_clk: l3_sp_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&mainclk>;
+						div-reg = <0x64 2 2>;
 					};
 
-				l4_sp_clk: l4_sp_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&mainclk>, <&per_base_clk>;
-					div-reg = <0x64 7 3>;
-					clk-gate = <0x60 3>;
+					l4_mp_clk: l4_mp_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&mainclk>, <&per_base_clk>;
+						div-reg = <0x64 4 3>;
+						clk-gate = <0x60 2>;
 					};
 
-				dbg_at_clk: dbg_at_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&dbg_base_clk>;
-					div-reg = <0x68 0 2>;
-					clk-gate = <0x60 4>;
+					l4_sp_clk: l4_sp_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&mainclk>, <&per_base_clk>;
+						div-reg = <0x64 7 3>;
+						clk-gate = <0x60 3>;
 					};
 
-				dbg_clk: dbg_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&dbg_base_clk>;
-					div-reg = <0x68 2 2>;
-					clk-gate = <0x60 5>;
+					dbg_at_clk: dbg_at_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&dbg_base_clk>;
+						div-reg = <0x68 0 2>;
+						clk-gate = <0x60 4>;
 					};
 
-				dbg_trace_clk: dbg_trace_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&dbg_base_clk>;
-					div-reg = <0x6C 0 3>;
-					clk-gate = <0x60 6>;
+					dbg_clk: dbg_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&dbg_base_clk>;
+						div-reg = <0x68 2 2>;
+						clk-gate = <0x60 5>;
 					};
 
-				dbg_timer_clk: dbg_timer_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&dbg_base_clk>;
-					clk-gate = <0x60 7>;
+					dbg_trace_clk: dbg_trace_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&dbg_base_clk>;
+						div-reg = <0x6C 0 3>;
+						clk-gate = <0x60 6>;
 					};
 
-				cfg_clk: cfg_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&cfg_s2f_usr0_clk>;
-					clk-gate = <0x60 8>;
+					dbg_timer_clk: dbg_timer_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&dbg_base_clk>;
+						clk-gate = <0x60 7>;
 					};
 
-				s2f_user0_clk: s2f_user0_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&cfg_s2f_usr0_clk>;
-					clk-gate = <0x60 9>;
+					cfg_clk: cfg_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&cfg_h2f_usr0_clk>;
+						clk-gate = <0x60 8>;
 					};
 
-				emac_0_clk: emac_0_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&emac0_clk>;
-					clk-gate = <0xa0 0>;
+					h2f_user0_clk: h2f_user0_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&cfg_h2f_usr0_clk>;
+						clk-gate = <0x60 9>;
 					};
 
-				emac_1_clk: emac_1_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&emac1_clk>;
-					clk-gate = <0xa0 1>;
+					emac_0_clk: emac_0_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&emac0_clk>;
+						clk-gate = <0xa0 0>;
 					};
 
-				usb_mp_clk: usb_mp_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&per_base_clk>;
-					clk-gate = <0xa0 2>;
-					div-reg = <0xa4 0 3>;
+					emac_1_clk: emac_1_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&emac1_clk>;
+						clk-gate = <0xa0 1>;
 					};
 
-				spi_m_clk: spi_m_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&per_base_clk>;
-					clk-gate = <0xa0 3>;
-					div-reg = <0xa4 3 3>;
+					usb_mp_clk: usb_mp_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&per_base_clk>;
+						clk-gate = <0xa0 2>;
+						div-reg = <0xa4 0 3>;
 					};
 
-				can0_clk: can0_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&per_base_clk>;
-					clk-gate = <0xa0 4>;
-					div-reg = <0xa4 6 3>;
+					spi_m_clk: spi_m_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&per_base_clk>;
+						clk-gate = <0xa0 3>;
+						div-reg = <0xa4 3 3>;
 					};
 
-				can1_clk: can1_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&per_base_clk>;
-					clk-gate = <0xa0 5>;
-					div-reg = <0xa4 9 3>;
+					can0_clk: can0_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&per_base_clk>;
+						clk-gate = <0xa0 4>;
+						div-reg = <0xa4 6 3>;
 					};
 
-				gpio_db_clk: gpio_db_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&per_base_clk>;
-					clk-gate = <0xa0 6>;
-					div-reg = <0xa8 0 24>;
+					can1_clk: can1_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&per_base_clk>;
+						clk-gate = <0xa0 5>;
+						div-reg = <0xa4 9 3>;
 					};
 
-				s2f_user1_clk: s2f_user1_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&s2f_usr1_clk>;
-					clk-gate = <0xa0 7>;
+					gpio_db_clk: gpio_db_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&per_base_clk>;
+						clk-gate = <0xa0 6>;
+						div-reg = <0xa8 0 24>;
 					};
 
-				sdmmc_clk: sdmmc_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&f2s_periph_ref_clk>, <&main_nand_sdmmc_clk>, <&per_nand_mmc_clk>;
-					clk-gate = <0xa0 8>;
+					h2f_user1_clk: h2f_user1_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&h2f_usr1_clk>;
+						clk-gate = <0xa0 7>;
 					};
 
-				nand_x_clk: nand_x_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&f2s_periph_ref_clk>, <&main_nand_sdmmc_clk>, <&per_nand_mmc_clk>;
-					clk-gate = <0xa0 9>;
+					sdmmc_clk: sdmmc_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&f2s_periph_ref_clk>, <&main_nand_sdmmc_clk>, <&per_nand_mmc_clk>;
+						clk-gate = <0xa0 8>;
 					};
 
-				nand_clk: nand_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&f2s_periph_ref_clk>, <&main_nand_sdmmc_clk>, <&per_nand_mmc_clk>;
-					clk-gate = <0xa0 10>;
-					fixed-divider = <4>;
+					nand_x_clk: nand_x_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&f2s_periph_ref_clk>, <&main_nand_sdmmc_clk>, <&per_nand_mmc_clk>;
+						clk-gate = <0xa0 9>;
 					};
 
-				qspi_clk: qspi_clk {
-					#clock-cells = <0>;
-					compatible = "altr,socfpga-gate-clk";
-					clocks = <&f2s_periph_ref_clk>, <&main_qspi_clk>, <&per_qspi_clk>;
-					clk-gate = <0xa0 11>;
+					nand_clk: nand_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&f2s_periph_ref_clk>, <&main_nand_sdmmc_clk>, <&per_nand_mmc_clk>;
+						clk-gate = <0xa0 10>;
+						fixed-divider = <4>;
+					};
+
+					qspi_clk: qspi_clk {
+						#clock-cells = <0>;
+						compatible = "altr,socfpga-gate-clk";
+						clocks = <&f2s_periph_ref_clk>, <&main_qspi_clk>, <&per_qspi_clk>;
+						clk-gate = <0xa0 11>;
 					};
 				};
 			};
@@ -473,6 +473,7 @@
 			compatible = "arm,cortex-a9-twd-timer";
 			reg = <0xfffec600 0x100>;
 			interrupts = <1 13 0xf04>;
+			clocks = <&mpu_periph_clk>;
 		};
 
 		timer0: timer0@ffc08000 {
@@ -516,9 +517,9 @@
 		};
 
 		rstmgr@ffd05000 {
-				compatible = "altr,rst-mgr";
-				reg = <0xffd05000 0x1000>;
-			};
+			compatible = "altr,rst-mgr";
+			reg = <0xffd05000 0x1000>;
+		};
 
 		sysmgr@ffd08000 {
 				compatible = "altr,sys-mgr";
diff --git a/arch/arm/boot/dts/socfpga_arria5.dtsi b/arch/arm/boot/dts/socfpga_arria5.dtsi
new file mode 100644
index 0000000..a85b404
--- /dev/null
+++ b/arch/arm/boot/dts/socfpga_arria5.dtsi
@@ -0,0 +1,58 @@
+/*
+ *  Copyright (C) 2013 Altera Corporation <www.altera.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/dts-v1/;
+/include/ "socfpga.dtsi"
+
+/ {
+	soc {
+		clkmgr@ffd04000 {
+			clocks {
+				osc1 {
+					clock-frequency = <25000000>;
+				};
+			};
+		};
+
+		serial0@ffc02000 {
+			clock-frequency = <100000000>;
+		};
+
+		serial1@ffc03000 {
+			clock-frequency = <100000000>;
+		};
+
+		sysmgr@ffd08000 {
+			cpu1-start-addr = <0xffd080c4>;
+		};
+
+		timer0@ffc08000 {
+			clock-frequency = <100000000>;
+		};
+
+		timer1@ffc09000 {
+			clock-frequency = <100000000>;
+		};
+
+		timer2@ffd00000 {
+			clock-frequency = <25000000>;
+		};
+
+		timer3@ffd01000 {
+			clock-frequency = <25000000>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/socfpga_arria5_socdk.dts b/arch/arm/boot/dts/socfpga_arria5_socdk.dts
new file mode 100644
index 0000000..5beffb2
--- /dev/null
+++ b/arch/arm/boot/dts/socfpga_arria5_socdk.dts
@@ -0,0 +1,40 @@
+/*
+ *  Copyright (C) 2013 Altera Corporation <www.altera.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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/ "socfpga_arria5.dtsi"
+
+/ {
+	model = "Altera SOCFPGA Arria V SoC Development Kit";
+	compatible = "altr,socfpga-arria5", "altr,socfpga";
+
+	chosen {
+		bootargs = "console=ttyS0,115200";
+	};
+
+	memory {
+		name = "memory";
+		device_type = "memory";
+		reg = <0x0 0x40000000>; /* 1GB */
+	};
+
+	aliases {
+		/* this allow the ethaddr uboot environmnet variable contents
+		* to be added to the gmac1 device tree blob.
+		*/
+		ethernet0 = &gmac1;
+	};
+};
diff --git a/arch/arm/boot/dts/socfpga_cyclone5.dts b/arch/arm/boot/dts/socfpga_cyclone5.dtsi
similarity index 77%
rename from arch/arm/boot/dts/socfpga_cyclone5.dts
rename to arch/arm/boot/dts/socfpga_cyclone5.dtsi
index 973999d..a8716f6 100644
--- a/arch/arm/boot/dts/socfpga_cyclone5.dts
+++ b/arch/arm/boot/dts/socfpga_cyclone5.dtsi
@@ -19,26 +19,6 @@
 /include/ "socfpga.dtsi"
 
 / {
-	model = "Altera SOCFPGA Cyclone V";
-	compatible = "altr,socfpga-cyclone5", "altr,socfpga";
-
-	chosen {
-		bootargs = "console=ttyS0,57600";
-	};
-
-	memory {
-		name = "memory";
-		device_type = "memory";
-		reg = <0x0 0x40000000>; /* 1GB */
-	};
-
-	aliases {
-		/* this allow the ethaddr uboot environmnet variable contents
-		 * to be added to the gmac1 device tree blob.
-		 */
-		ethernet0 = &gmac1;
-	};
-
 	soc {
 		clkmgr@ffd04000 {
 			clocks {
diff --git a/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts b/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
new file mode 100644
index 0000000..2ee52ab
--- /dev/null
+++ b/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
@@ -0,0 +1,40 @@
+/*
+ *  Copyright (C) 2012 Altera Corporation <www.altera.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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/ "socfpga_cyclone5.dtsi"
+
+/ {
+	model = "Altera SOCFPGA Cyclone V SoC Development Kit";
+	compatible = "altr,socfpga-cyclone5", "altr,socfpga";
+
+	chosen {
+		bootargs = "console=ttyS0,115200";
+	};
+
+	memory {
+		name = "memory";
+		device_type = "memory";
+		reg = <0x0 0x40000000>; /* 1GB */
+	};
+
+	aliases {
+		/* this allow the ethaddr uboot environmnet variable contents
+		 * to be added to the gmac1 device tree blob.
+		 */
+		ethernet0 = &gmac1;
+	};
+};
diff --git a/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts b/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
new file mode 100644
index 0000000..50b99a2
--- /dev/null
+++ b/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
@@ -0,0 +1,37 @@
+/*
+ *  Copyright (C) 2013 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/include/ "socfpga_cyclone5.dtsi"
+
+/ {
+	model = "Terasic SoCkit";
+	compatible = "altr,socfpga-cyclone5", "altr,socfpga";
+
+	chosen {
+		bootargs = "console=ttyS0,115200";
+	};
+
+	memory {
+		name = "memory";
+		device_type = "memory";
+		reg = <0x0 0x40000000>; /* 1GB */
+	};
+};
+
+&gmac1 {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi
index 1c1091e..7da99fe 100644
--- a/arch/arm/boot/dts/ste-dbx5x0.dtsi
+++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi
@@ -10,6 +10,7 @@
  */
 
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/mfd/dbx500-prcmu.h>
 #include "skeleton.dtsi"
 
 / {
@@ -42,16 +43,56 @@
 			interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
+
+		clocks {
+			compatible = "stericsson,u8500-clks";
+
+			prcmu_clk: prcmu-clock {
+				#clock-cells = <1>;
+			};
+
+			prcc_pclk: prcc-periph-clock {
+				#clock-cells = <2>;
+			};
+
+			prcc_kclk: prcc-kernel-clock {
+				#clock-cells = <2>;
+			};
+
+			rtc_clk: rtc32k-clock {
+				#clock-cells = <0>;
+			};
+
+			smp_twd_clk: smp-twd-clock {
+				#clock-cells = <0>;
+			};
+		};
+
+		mtu@a03c6000 {
+			/* Nomadik System Timer */
+			compatible = "st,nomadik-mtu";
+			reg = <0xa03c6000 0x1000>;
+			interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>;
+
+			clocks = <&prcmu_clk PRCMU_TIMCLK>, <&prcc_pclk 6 6>;
+			clock-names = "timclk", "apb_pclk";
+		};
+
 		timer@a0410600 {
 			compatible = "arm,cortex-a9-twd-timer";
 			reg = <0xa0410600 0x20>;
 			interrupts = <1 13 0x304>; /* IRQ level high per-CPU */
+
+			clocks = <&smp_twd_clk>;
 		};
 
 		rtc@80154000 {
 			compatible = "arm,rtc-pl031", "arm,primecell";
 			reg = <0x80154000 0x1000>;
 			interrupts = <0 18 IRQ_TYPE_LEVEL_HIGH>;
+
+			clocks = <&rtc_clk>;
+			clock-names = "apb_pclk";
 		};
 
 		gpio0: gpio@8012e000 {
@@ -65,6 +106,8 @@
 			gpio-controller;
 			#gpio-cells = <2>;
 			gpio-bank = <0>;
+
+			clocks = <&prcc_pclk 1 9>;
 		};
 
 		gpio1: gpio@8012e080 {
@@ -78,6 +121,8 @@
 			gpio-controller;
 			#gpio-cells = <2>;
 			gpio-bank = <1>;
+
+			clocks = <&prcc_pclk 1 9>;
 		};
 
 		gpio2: gpio@8000e000 {
@@ -91,6 +136,8 @@
 			gpio-controller;
 			#gpio-cells = <2>;
 			gpio-bank = <2>;
+
+			clocks = <&prcc_pclk 3 8>;
 		};
 
 		gpio3: gpio@8000e080 {
@@ -104,6 +151,8 @@
 			gpio-controller;
 			#gpio-cells = <2>;
 			gpio-bank = <3>;
+
+			clocks = <&prcc_pclk 3 8>;
 		};
 
 		gpio4: gpio@8000e100 {
@@ -117,6 +166,8 @@
 			gpio-controller;
 			#gpio-cells = <2>;
 			gpio-bank = <4>;
+
+			clocks = <&prcc_pclk 3 8>;
 		};
 
 		gpio5: gpio@8000e180 {
@@ -130,6 +181,8 @@
 			gpio-controller;
 			#gpio-cells = <2>;
 			gpio-bank = <5>;
+
+			clocks = <&prcc_pclk 3 8>;
 		};
 
 		gpio6: gpio@8011e000 {
@@ -143,6 +196,8 @@
 			gpio-controller;
 			#gpio-cells = <2>;
 			gpio-bank = <6>;
+
+			clocks = <&prcc_pclk 2 11>;
 		};
 
 		gpio7: gpio@8011e080 {
@@ -156,6 +211,8 @@
 			gpio-controller;
 			#gpio-cells = <2>;
 			gpio-bank = <7>;
+
+			clocks = <&prcc_pclk 2 11>;
 		};
 
 		gpio8: gpio@a03fe000 {
@@ -169,6 +226,8 @@
 			gpio-controller;
 			#gpio-cells = <2>;
 			gpio-bank = <8>;
+
+			clocks = <&prcc_pclk 5 1>;
 		};
 
 		pinctrl {
@@ -177,8 +236,7 @@
 		};
 
 		usb_per5@a03e0000 {
-			compatible = "stericsson,db8500-musb",
-				"mentor,musb";
+			compatible = "stericsson,db8500-musb";
 			reg = <0xa03e0000 0x10000>;
 			interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-names = "mc";
@@ -210,6 +268,8 @@
 				    "iep_6_14", "oep_6_14",
 				    "iep_7_15", "oep_7_15",
 				    "iep_8",    "oep_8";
+
+			clocks = <&prcc_pclk 5 0>;
 		};
 
 		dma: dma-controller@801C0000 {
@@ -220,6 +280,8 @@
 
 			#dma-cells = <3>;
 			memcpy-channels = <56 57 58 59 60>;
+
+			clocks = <&prcmu_clk PRCMU_DMACLK>;
 		};
 
 		prcmu: prcmu@80157000 {
@@ -238,6 +300,13 @@
 				reg = <0x80157450 0xC>;
 			};
 
+			cpufreq {
+				compatible = "stericsson,cpufreq-ux500";
+				clocks = <&prcmu_clk PRCMU_ARMSS>;
+				clock-names = "armss";
+				status = "disabled";
+			};
+
 			thermal@801573c0 {
 				compatible = "stericsson,db8500-thermal";
 				reg = <0x801573c0 0x40>;
@@ -559,65 +628,74 @@
 			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
 			reg = <0x80004000 0x1000>;
 			interrupts = <0 21 IRQ_TYPE_LEVEL_HIGH>;
-			arm,primecell-periphid = <0x180024>;
 
 			#address-cells = <1>;
 			#size-cells = <0>;
 			v-i2c-supply = <&db8500_vape_reg>;
 
 			clock-frequency = <400000>;
+			clocks = <&prcc_kclk 3 3>, <&prcc_pclk 3 3>;
+			clock-names = "i2cclk", "apb_pclk";
 		};
 
 		i2c@80122000 {
 			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
 			reg = <0x80122000 0x1000>;
 			interrupts = <0 22 IRQ_TYPE_LEVEL_HIGH>;
-			arm,primecell-periphid = <0x180024>;
 
 			#address-cells = <1>;
 			#size-cells = <0>;
 			v-i2c-supply = <&db8500_vape_reg>;
 
 			clock-frequency = <400000>;
+
+			clocks = <&prcc_kclk 1 2>, <&prcc_pclk 1 2>;
+			clock-names = "i2cclk", "apb_pclk";
 		};
 
 		i2c@80128000 {
 			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
 			reg = <0x80128000 0x1000>;
 			interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>;
-			arm,primecell-periphid = <0x180024>;
 
 			#address-cells = <1>;
 			#size-cells = <0>;
 			v-i2c-supply = <&db8500_vape_reg>;
 
 			clock-frequency = <400000>;
+
+			clocks = <&prcc_kclk 1 6>, <&prcc_pclk 1 6>;
+			clock-names = "i2cclk", "apb_pclk";
 		};
 
 		i2c@80110000 {
 			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
 			reg = <0x80110000 0x1000>;
 			interrupts = <0 12 IRQ_TYPE_LEVEL_HIGH>;
-			arm,primecell-periphid = <0x180024>;
 
 			#address-cells = <1>;
 			#size-cells = <0>;
 			v-i2c-supply = <&db8500_vape_reg>;
 
 			clock-frequency = <400000>;
+
+			clocks = <&prcc_kclk 2 0>, <&prcc_pclk 2 0>;
+			clock-names = "i2cclk", "apb_pclk";
 		};
 
 		i2c@8012a000 {
 			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
 			reg = <0x8012a000 0x1000>;
 			interrupts = <0 51 IRQ_TYPE_LEVEL_HIGH>;
-			arm,primecell-periphid = <0x180024>;
 
 			#address-cells = <1>;
 			#size-cells = <0>;
 			v-i2c-supply = <&db8500_vape_reg>;
 
 			clock-frequency = <400000>;
+
+			clocks = <&prcc_kclk 1 9>, <&prcc_pclk 1 10>;
+			clock-names = "i2cclk", "apb_pclk";
 		};
 
 		ssp@80002000 {
@@ -626,7 +704,80 @@
 			interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
-			status = "disabled";
+			clocks = <&prcc_kclk 3 1>, <&prcc_pclk 3 1>;
+			clock-names = "ssp0clk", "apb_pclk";
+			dmas = <&dma 8 0 0x2>, /* Logical - DevToMem */
+			       <&dma 8 0 0x0>; /* Logical - MemToDev */
+			dma-names = "rx", "tx";
+		};
+
+		ssp@80003000 {
+			compatible = "arm,pl022", "arm,primecell";
+			reg = <0x80003000 0x1000>;
+			interrupts = <0 52 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&prcc_kclk 3 2>, <&prcc_pclk 3 2>;
+			clock-names = "ssp1clk", "apb_pclk";
+			dmas = <&dma 9 0 0x2>, /* Logical - DevToMem */
+			       <&dma 9 0 0x0>; /* Logical - MemToDev */
+			dma-names = "rx", "tx";
+		};
+
+		spi@8011a000 {
+			compatible = "arm,pl022", "arm,primecell";
+			reg = <0x8011a000 0x1000>;
+			interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			/* Same clock wired to kernel and pclk */
+			clocks = <&prcc_pclk 2 8>, <&prcc_pclk 2 8>;
+			clock-names = "spi0clk", "apb_pclk";
+			dmas = <&dma 0 0 0x2>, /* Logical - DevToMem */
+			       <&dma 0 0 0x0>; /* Logical - MemToDev */
+			dma-names = "rx", "tx";
+		};
+
+		spi@80112000 {
+			compatible = "arm,pl022", "arm,primecell";
+			reg = <0x80112000 0x1000>;
+			interrupts = <0 96 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			/* Same clock wired to kernel and pclk */
+			clocks = <&prcc_pclk 2 2>, <&prcc_pclk 2 2>;
+			clock-names = "spi1clk", "apb_pclk";
+			dmas = <&dma 35 0 0x2>, /* Logical - DevToMem */
+			       <&dma 35 0 0x0>; /* Logical - MemToDev */
+			dma-names = "rx", "tx";
+		};
+
+		spi@80111000 {
+			compatible = "arm,pl022", "arm,primecell";
+			reg = <0x80111000 0x1000>;
+			interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			/* Same clock wired to kernel and pclk */
+			clocks = <&prcc_pclk 2 1>, <&prcc_pclk 2 1>;
+			clock-names = "spi2clk", "apb_pclk";
+			dmas = <&dma 33 0 0x2>, /* Logical - DevToMem */
+			       <&dma 33 0 0x0>; /* Logical - MemToDev */
+			dma-names = "rx", "tx";
+		};
+
+		spi@80129000 {
+			compatible = "arm,pl022", "arm,primecell";
+			reg = <0x80129000 0x1000>;
+			interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			/* Same clock wired to kernel and pclk */
+			clocks = <&prcc_pclk 1 7>, <&prcc_pclk 1 7>;
+			clock-names = "spi3clk", "apb_pclk";
+			dmas = <&dma 40 0 0x2>, /* Logical - DevToMem */
+			       <&dma 40 0 0x0>; /* Logical - MemToDev */
+			dma-names = "rx", "tx";
 		};
 
 		uart@80120000 {
@@ -638,6 +789,9 @@
 			       <&dma 13 0 0x0>; /* Logical - MemToDev */
 			dma-names = "rx", "tx";
 
+			clocks = <&prcc_kclk 1 0>, <&prcc_pclk 1 0>;
+			clock-names = "uart", "apb_pclk";
+
 			status = "disabled";
 		};
 
@@ -650,6 +804,9 @@
 			       <&dma 12 0 0x0>; /* Logical - MemToDev */
 			dma-names = "rx", "tx";
 
+			clocks = <&prcc_kclk 1 1>, <&prcc_pclk 1 1>;
+			clock-names = "uart", "apb_pclk";
+
 			status = "disabled";
 		};
 
@@ -662,6 +819,9 @@
 			       <&dma 11 0 0x0>; /* Logical - MemToDev */
 			dma-names = "rx", "tx";
 
+			clocks = <&prcc_kclk 3 6>, <&prcc_pclk 3 6>;
+			clock-names = "uart", "apb_pclk";
+
 			status = "disabled";
 		};
 
@@ -674,6 +834,9 @@
 			       <&dma 29 0 0x0>; /* Logical - MemToDev */
 			dma-names = "rx", "tx";
 
+			clocks = <&prcc_kclk 1 5>, <&prcc_pclk 1 5>;
+			clock-names = "sdi", "apb_pclk";
+
 			status = "disabled";
 		};
 
@@ -686,6 +849,9 @@
 			       <&dma 32 0 0x0>; /* Logical - MemToDev */
 			dma-names = "rx", "tx";
 
+			clocks = <&prcc_kclk 2 4>, <&prcc_pclk 2 6>;
+			clock-names = "sdi", "apb_pclk";
+
 			status = "disabled";
 		};
 
@@ -698,6 +864,9 @@
 			       <&dma 28 0 0x0>; /* Logical - MemToDev */
 			dma-names = "rx", "tx";
 
+			clocks = <&prcc_kclk 3 4>, <&prcc_pclk 3 4>;
+			clock-names = "sdi", "apb_pclk";
+
 			status = "disabled";
 		};
 
@@ -705,6 +874,10 @@
 			compatible = "arm,pl18x", "arm,primecell";
 			reg = <0x80119000 0x1000>;
 			interrupts = <0 59 IRQ_TYPE_LEVEL_HIGH>;
+
+			clocks = <&prcc_kclk 2 5>, <&prcc_pclk 2 7>;
+			clock-names = "sdi", "apb_pclk";
+
 			status = "disabled";
 		};
 
@@ -717,6 +890,9 @@
 			       <&dma 42 0 0x0>; /* Logical - MemToDev */
 			dma-names = "rx", "tx";
 
+			clocks = <&prcc_kclk 2 2>, <&prcc_pclk 2 4>;
+			clock-names = "sdi", "apb_pclk";
+
 			status = "disabled";
 		};
 
@@ -724,6 +900,10 @@
 			compatible = "arm,pl18x", "arm,primecell";
 			reg = <0x80008000 0x1000>;
 			interrupts = <0 100 IRQ_TYPE_LEVEL_HIGH>;
+
+			clocks = <&prcc_kclk 3 7>, <&prcc_pclk 3 7>;
+			clock-names = "sdi", "apb_pclk";
+
 			status = "disabled";
 		};
 
@@ -732,6 +912,10 @@
 			reg = <0x80123000 0x1000>;
 			interrupts = <0 31 IRQ_TYPE_LEVEL_HIGH>;
 			v-ape-supply = <&db8500_vape_reg>;
+
+			clocks = <&prcc_kclk 1 3>, <&prcc_pclk 1 3>;
+			clock-names = "msp", "apb_pclk";
+
 			status = "disabled";
 		};
 
@@ -740,6 +924,10 @@
 			reg = <0x80124000 0x1000>;
 			interrupts = <0 62 IRQ_TYPE_LEVEL_HIGH>;
 			v-ape-supply = <&db8500_vape_reg>;
+
+			clocks = <&prcc_kclk 1 4>, <&prcc_pclk 1 4>;
+			clock-names = "msp", "apb_pclk";
+
 			status = "disabled";
 		};
 
@@ -749,6 +937,10 @@
 			reg = <0x80117000 0x1000>;
 			interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>;
 			v-ape-supply = <&db8500_vape_reg>;
+
+			clocks = <&prcc_kclk 2 3>, <&prcc_pclk 2 5>;
+			clock-names = "msp", "apb_pclk";
+
 			status = "disabled";
 		};
 
@@ -757,6 +949,10 @@
 			reg = <0x80125000 0x1000>;
 			interrupts = <0 62 IRQ_TYPE_LEVEL_HIGH>;
 			v-ape-supply = <&db8500_vape_reg>;
+
+			clocks = <&prcc_kclk 1 10>, <&prcc_pclk 1 11>;
+			clock-names = "msp", "apb_pclk";
+
 			status = "disabled";
 		};
 
@@ -772,7 +968,7 @@
 		cpufreq-cooling {
 			compatible = "stericsson,db8500-cpufreq-cooling";
 			status = "disabled";
-		 };
+		};
 
 		vmmci: regulator-gpio {
 			compatible = "regulator-gpio";
@@ -797,6 +993,7 @@
 			interrupts = <0 15 IRQ_TYPE_LEVEL_HIGH>;
 
 			v-ape-supply = <&db8500_vape_reg>;
+			clocks = <&prcc_pclk 6 1>;
 		};
 
 		hash@a03c2000 {
@@ -804,6 +1001,7 @@
 			reg = <0xa03c2000 0x1000>;
 
 			v-ape-supply = <&db8500_vape_reg>;
+			clocks = <&prcc_pclk 6 2>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/ste-stuib.dtsi b/arch/arm/boot/dts/ste-href-stuib.dtsi
similarity index 95%
rename from arch/arm/boot/dts/ste-stuib.dtsi
rename to arch/arm/boot/dts/ste-href-stuib.dtsi
index 524e332..76704ec 100644
--- a/arch/arm/boot/dts/ste-stuib.dtsi
+++ b/arch/arm/boot/dts/ste-href-stuib.dtsi
@@ -57,7 +57,6 @@
 			bu21013_tp@5c {
 				compatible = "rohm,bu21013_tp";
 				reg = <0x5c>;
-				touch-gpio = <&gpio2 20 0x4>;
 				avdd-supply = <&ab8500_ldo_aux1_reg>;
 
 				rohm,touch-max-x = <384>;
@@ -68,7 +67,6 @@
 			bu21013_tp@5d {
 				compatible = "rohm,bu21013_tp";
 				reg = <0x5d>;
-				touch-gpio = <&gpio2 20 0x4>;
 				avdd-supply = <&ab8500_ldo_aux1_reg>;
 
 				rohm,touch-max-x = <384>;
diff --git a/arch/arm/boot/dts/ste-href-tvk1281618.dtsi b/arch/arm/boot/dts/ste-href-tvk1281618.dtsi
new file mode 100644
index 0000000..76d3ef1
--- /dev/null
+++ b/arch/arm/boot/dts/ste-href-tvk1281618.dtsi
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2012 ST-Ericsson AB
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Device Tree for the TVK1281618 UIB
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	soc {
+		/* Add Synaptics touch screen, TC35892 keypad etc here */
+		i2c@80004000 {
+			tc3589x@44 {
+				compatible = "tc3589x";
+				reg = <0x44>;
+				interrupt-parent = <&gpio6>;
+				interrupts = <26 IRQ_TYPE_EDGE_RISING>;
+
+				interrupt-controller;
+				#interrupt-cells = <2>;
+
+				tc3589x_gpio {
+					compatible = "tc3589x-gpio";
+					interrupts = <0 IRQ_TYPE_EDGE_RISING>;
+
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/ste-href.dtsi b/arch/arm/boot/dts/ste-href.dtsi
index 370e03f..aa3f020 100644
--- a/arch/arm/boot/dts/ste-href.dtsi
+++ b/arch/arm/boot/dts/ste-href.dtsi
@@ -41,28 +41,6 @@
 			status = "okay";
 		};
 
-		i2c@80004000 {
-			tc3589x@42 {
-				compatible = "tc3589x";
-				reg = <0x42>;
-				interrupt-parent = <&gpio6>;
-				interrupts = <25 IRQ_TYPE_EDGE_RISING>;
-
-				interrupt-controller;
-				#interrupt-cells = <2>;
-
-				tc3589x_gpio: tc3589x_gpio {
-					compatible = "tc3589x-gpio";
-					interrupts = <0 IRQ_TYPE_EDGE_RISING>;
-
-					interrupt-controller;
-					#interrupt-cells = <2>;
-					gpio-controller;
-					#gpio-cells = <2>;
-				};
-			};
-		};
-
 		i2c@80128000 {
 			lp5521@33 {
 				compatible = "national,lp5521";
@@ -72,6 +50,7 @@
 				chan0 {
 					led-cur = /bits/ 8 <0x2f>;
 					max-cur = /bits/ 8 <0x5f>;
+					linux,default-trigger = "heartbeat";
 				};
 				chan1 {
 					led-cur = /bits/ 8 <0x2f>;
@@ -102,7 +81,7 @@
 			};
 			bh1780@29 {
 				compatible = "rohm,bh1780gli";
-				reg = <0x33>;
+				reg = <0x29>;
 			};
 		};
 
@@ -167,89 +146,11 @@
 		};
 
 		prcmu@80157000 {
-			db8500-prcmu-regulators {
-				db8500_vape_reg: db8500_vape {
-					regulator-name = "db8500-vape";
-				};
-
-				db8500_varm_reg: db8500_varm {
-					regulator-name = "db8500-varm";
-				};
-
-				db8500_vmodem_reg: db8500_vmodem {
-					regulator-name = "db8500-vmodem";
-				};
-
-				db8500_vpll_reg: db8500_vpll {
-					regulator-name = "db8500-vpll";
-				};
-
-				db8500_vsmps1_reg: db8500_vsmps1 {
-					regulator-name = "db8500-vsmps1";
-				};
-
-				db8500_vsmps2_reg: db8500_vsmps2 {
-					regulator-name = "db8500-vsmps2";
-				};
-
-				db8500_vsmps3_reg: db8500_vsmps3 {
-					regulator-name = "db8500-vsmps3";
-				};
-
-				db8500_vrf1_reg: db8500_vrf1 {
-					regulator-name = "db8500-vrf1";
-				};
-
-				db8500_sva_mmdsp_reg: db8500_sva_mmdsp {
-					regulator-name = "db8500-sva-mmdsp";
-				};
-
-				db8500_sva_mmdsp_ret_reg: db8500_sva_mmdsp_ret {
-					regulator-name = "db8500-sva-mmdsp-ret";
-				};
-
-				db8500_sva_pipe_reg: db8500_sva_pipe {
-					regulator-name = "db8500_sva_pipe";
-				};
-
-				db8500_sia_mmdsp_reg: db8500_sia_mmdsp {
-					regulator-name = "db8500_sia_mmdsp";
-				};
-
-				db8500_sia_mmdsp_ret_reg: db8500_sia_mmdsp_ret {
-					regulator-name = "db8500-sia-mmdsp-ret";
-				};
-
-				db8500_sia_pipe_reg: db8500_sia_pipe {
-					regulator-name = "db8500-sia-pipe";
-				};
-
-				db8500_sga_reg: db8500_sga {
-					regulator-name = "db8500-sga";
-				};
-
-				db8500_b2r2_mcde_reg: db8500_b2r2_mcde {
-					regulator-name = "db8500-b2r2-mcde";
-				};
-
-				db8500_esram12_reg: db8500_esram12 {
-					regulator-name = "db8500-esram12";
-				};
-
-				db8500_esram12_ret_reg: db8500_esram12_ret {
-					regulator-name = "db8500-esram12-ret";
-				};
-
-				db8500_esram34_reg: db8500_esram34 {
-					regulator-name = "db8500-esram34";
-				};
-
-				db8500_esram34_ret_reg: db8500_esram34_ret {
-					regulator-name = "db8500-esram34-ret";
-				};
-			};
-
 			ab8500 {
+				ab8500-gpio {
+					compatible = "stericsson,ab8500-gpio";
+				};
+
 				ab8500-regulators {
 					ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
 						regulator-name = "V-DISPLAY";
diff --git a/arch/arm/boot/dts/ste-hrefprev60-stuib.dts b/arch/arm/boot/dts/ste-hrefprev60-stuib.dts
new file mode 100644
index 0000000..2b1cb5b
--- /dev/null
+++ b/arch/arm/boot/dts/ste-hrefprev60-stuib.dts
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012 ST-Ericsson AB
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "ste-hrefprev60.dtsi"
+#include "ste-href-stuib.dtsi"
+
+/ {
+	model = "ST-Ericsson HREF (pre-v60) and ST UIB";
+	compatible = "st-ericsson,mop500", "st-ericsson,u8500";
+
+	soc {
+		/* Reset line for the BU21013 touchscreen */
+		i2c@80110000 {
+			/* Only one of these will be used */
+			bu21013_tp@5c {
+				touch-gpio = <&gpio2 12 0x4>;
+				reset-gpio = <&tc3589x_gpio 13 0x4>;
+			};
+			bu21013_tp@5d {
+				touch-gpio = <&gpio2 12 0x4>;
+				reset-gpio = <&tc3589x_gpio 13 0x4>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/ste-hrefprev60-tvk.dts b/arch/arm/boot/dts/ste-hrefprev60-tvk.dts
new file mode 100644
index 0000000..59523f8
--- /dev/null
+++ b/arch/arm/boot/dts/ste-hrefprev60-tvk.dts
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2012 ST-Ericsson AB
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "ste-hrefprev60.dtsi"
+#include "ste-href-tvk1281618.dtsi"
+
+/ {
+	model = "ST-Ericsson HREF (pre-v60) and TVK1281618 UIB";
+	compatible = "st-ericsson,mop500", "st-ericsson,u8500";
+};
diff --git a/arch/arm/boot/dts/ste-hrefprev60.dts b/arch/arm/boot/dts/ste-hrefprev60.dtsi
similarity index 60%
rename from arch/arm/boot/dts/ste-hrefprev60.dts
rename to arch/arm/boot/dts/ste-hrefprev60.dtsi
index d8d3b99..b2cd7bc 100644
--- a/arch/arm/boot/dts/ste-hrefprev60.dts
+++ b/arch/arm/boot/dts/ste-hrefprev60.dtsi
@@ -7,17 +7,14 @@
  *
  * http://www.opensource.org/licenses/gpl-license.html
  * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Device Tree for the HREF+ prior to the v60 variant.
  */
 
-/dts-v1/;
 #include "ste-dbx5x0.dtsi"
 #include "ste-href.dtsi"
-#include "ste-stuib.dtsi"
 
 / {
-	model = "ST-Ericsson HREF (pre-v60) platform with Device Tree";
-	compatible = "st-ericsson,mop500", "st-ericsson,u8500";
-
 	gpio_keys {
 		button@1 {
 			gpios = <&tc3589x_gpio 7 0x4>;
@@ -25,24 +22,30 @@
 	};
 
 	soc {
-		prcmu@80157000 {
-			ab8500@5 {
-				ab8500-gpio {
-					compatible = "stericsson,ab8500-gpio";
-				};
-			};
-		};
-
 		i2c@80004000 {
 			tps61052@33 {
 				compatible = "tps61052";
 				reg = <0x33>;
 			};
-		};
 
-		i2c@80110000 {
-			bu21013_tp@5c {
-				reset-gpio = <&tc3589x_gpio 13 0x4>;
+			tc3589x@42 {
+				compatible = "tc3589x";
+				reg = <0x42>;
+				interrupt-parent = <&gpio6>;
+				interrupts = <25 IRQ_TYPE_EDGE_RISING>;
+
+				interrupt-controller;
+				#interrupt-cells = <2>;
+
+				tc3589x_gpio: tc3589x_gpio {
+					compatible = "tc3589x-gpio";
+					interrupts = <0 IRQ_TYPE_EDGE_RISING>;
+
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
 			};
 		};
 
diff --git a/arch/arm/boot/dts/ste-hrefv60plus-stuib.dts b/arch/arm/boot/dts/ste-hrefv60plus-stuib.dts
new file mode 100644
index 0000000..8c6a2de
--- /dev/null
+++ b/arch/arm/boot/dts/ste-hrefv60plus-stuib.dts
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012 ST-Ericsson AB
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Device Tree for the HREF version 60 or later with the ST UIB
+ */
+
+/dts-v1/;
+#include "ste-hrefv60plus.dtsi"
+#include "ste-href-stuib.dtsi"
+
+/ {
+	model = "ST-Ericsson HREF (v60+) and ST UIB";
+	compatible = "st-ericsson,hrefv60+", "st-ericsson,u8500";
+
+	soc {
+		/* Reset line for the BU21013 touchscreen */
+		i2c@80110000 {
+			/* Only one of these will be used */
+			bu21013_tp@5c {
+				touch-gpio = <&gpio2 20 0x4>;
+				reset-gpio = <&gpio4 17 0x4>;
+			};
+			bu21013_tp@5d {
+				touch-gpio = <&gpio2 20 0x4>;
+				reset-gpio = <&gpio4 17 0x4>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/ste-hrefv60plus-tvk.dts b/arch/arm/boot/dts/ste-hrefv60plus-tvk.dts
new file mode 100644
index 0000000..d53cccd
--- /dev/null
+++ b/arch/arm/boot/dts/ste-hrefv60plus-tvk.dts
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2012 ST-Ericsson AB
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Device Tree for the HREF version 60 or later with the TVK1281618 UIB
+ */
+
+/dts-v1/;
+#include "ste-hrefv60plus.dtsi"
+#include "ste-href-tvk1281618.dtsi"
+
+/ {
+	model = "ST-Ericsson HREF (v60+) and TVK1281618 UIB";
+	compatible = "st-ericsson,hrefv60+", "st-ericsson,u8500";
+};
diff --git a/arch/arm/boot/dts/ste-hrefv60plus.dts b/arch/arm/boot/dts/ste-hrefv60plus.dts
deleted file mode 100644
index 6e52ebb..0000000
--- a/arch/arm/boot/dts/ste-hrefv60plus.dts
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright 2012 ST-Ericsson AB
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-/dts-v1/;
-#include "ste-dbx5x0.dtsi"
-#include "ste-href.dtsi"
-#include "ste-stuib.dtsi"
-
-/ {
-	model = "ST-Ericsson HREF (v60+) platform with Device Tree";
-	compatible = "st-ericsson,hrefv60+", "st-ericsson,u8500";
-
-	gpio_keys {
-		button@1 {
-			gpios = <&gpio6 25 0x4>;
-		};
-	};
-
-	soc {
-		i2c@80110000 {
-			bu21013_tp@0x5c {
-				reset-gpio = <&gpio4 15 0x4>;
-			};
-		};
-
-		// External Micro SD slot
-		sdi0_per1@80126000 {
-			arm,primecell-periphid = <0x10480180>;
-			max-frequency = <100000000>;
-			bus-width = <4>;
-			mmc-cap-sd-highspeed;
-			mmc-cap-mmc-highspeed;
-			vmmc-supply = <&ab8500_ldo_aux3_reg>;
-
-			cd-gpios  = <&tc3589x_gpio 3 0x4>;
-
-			status = "okay";
-		};
-
-		// WLAN SDIO channel
-		sdi1_per2@80118000 {
-			arm,primecell-periphid = <0x10480180>;
-			max-frequency = <100000000>;
-			bus-width = <4>;
-
-			status = "okay";
-		};
-
-		// PoP:ed eMMC
-		sdi2_per3@80005000 {
-			arm,primecell-periphid = <0x10480180>;
-			max-frequency = <100000000>;
-			bus-width = <8>;
-			mmc-cap-mmc-highspeed;
-
-			status = "okay";
-		};
-
-		// On-board eMMC
-		sdi4_per2@80114000 {
-			arm,primecell-periphid = <0x10480180>;
-		        max-frequency = <100000000>;
-			bus-width = <8>;
-			mmc-cap-mmc-highspeed;
-			vmmc-supply = <&ab8500_ldo_aux2_reg>;
-
-			status = "okay";
-		};
-
-		prcmu@80157000 {
-			db8500-prcmu-regulators {
-				db8500_vape_reg: db8500_vape {
-					regulator-name = "db8500-vape";
-				};
-
-				db8500_varm_reg: db8500_varm {
-					regulator-name = "db8500-varm";
-				};
-
-				db8500_vmodem_reg: db8500_vmodem {
-					regulator-name = "db8500-vmodem";
-				};
-
-				db8500_vpll_reg: db8500_vpll {
-					regulator-name = "db8500-vpll";
-				};
-
-				db8500_vsmps1_reg: db8500_vsmps1 {
-					regulator-name = "db8500-vsmps1";
-				};
-
-				db8500_vsmps2_reg: db8500_vsmps2 {
-					regulator-name = "db8500-vsmps2";
-				};
-
-				db8500_vsmps3_reg: db8500_vsmps3 {
-					regulator-name = "db8500-vsmps3";
-				};
-
-				db8500_vrf1_reg: db8500_vrf1 {
-					regulator-name = "db8500-vrf1";
-				};
-
-				db8500_sva_mmdsp_reg: db8500_sva_mmdsp {
-					regulator-name = "db8500-sva-mmdsp";
-				};
-
-				db8500_sva_mmdsp_ret_reg: db8500_sva_mmdsp_ret {
-					regulator-name = "db8500-sva-mmdsp-ret";
-				};
-
-				db8500_sva_pipe_reg: db8500_sva_pipe {
-					regulator-name = "db8500_sva_pipe";
-				};
-
-				db8500_sia_mmdsp_reg: db8500_sia_mmdsp {
-					regulator-name = "db8500_sia_mmdsp";
-				};
-
-				db8500_sia_mmdsp_ret_reg: db8500_sia_mmdsp_ret {
-					regulator-name = "db8500-sia-mmdsp-ret";
-				};
-
-				db8500_sia_pipe_reg: db8500_sia_pipe {
-					regulator-name = "db8500-sia-pipe";
-				};
-
-				db8500_sga_reg: db8500_sga {
-					regulator-name = "db8500-sga";
-				};
-
-				db8500_b2r2_mcde_reg: db8500_b2r2_mcde {
-					regulator-name = "db8500-b2r2-mcde";
-				};
-
-				db8500_esram12_reg: db8500_esram12 {
-					regulator-name = "db8500-esram12";
-				};
-
-				db8500_esram12_ret_reg: db8500_esram12_ret {
-					regulator-name = "db8500-esram12-ret";
-				};
-
-				db8500_esram34_reg: db8500_esram34 {
-					regulator-name = "db8500-esram34";
-				};
-
-				db8500_esram34_ret_reg: db8500_esram34_ret {
-					regulator-name = "db8500-esram34-ret";
-				};
-			};
-
-			ab8500 {
-				ab8500-regulators {
-					ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
-						regulator-name = "V-DISPLAY";
-					};
-
-					ab8500_ldo_aux2_reg: ab8500_ldo_aux2 {
-						regulator-name = "V-eMMC1";
-					};
-
-					ab8500_ldo_aux3_reg: ab8500_ldo_aux3 {
-						regulator-name = "V-MMC-SD";
-					};
-
-					ab8500_ldo_intcore_reg: ab8500_ldo_intcore {
-						regulator-name = "V-INTCORE";
-					};
-
-					ab8500_ldo_tvout_reg: ab8500_ldo_tvout {
-						regulator-name = "V-TVOUT";
-					};
-
-					ab8500_ldo_usb_reg: ab8500_ldo_usb {
-						regulator-name = "dummy";
-					};
-
-					ab8500_ldo_audio_reg: ab8500_ldo_audio {
-						regulator-name = "V-AUD";
-					};
-
-					ab8500_ldo_anamic1_reg: ab8500_ldo_anamic1 {
-						regulator-name = "V-AMIC1";
-					};
-
-					ab8500_ldo_anamic2_reg: ab8500_ldo_anamic2 {
-						regulator-name = "V-AMIC2";
-					};
-
-					ab8500_ldo_dmic_reg: ab8500_ldo_dmic {
-						regulator-name = "V-DMIC";
-					};
-
-					ab8500_ldo_ana_reg: ab8500_ldo_ana {
-						regulator-name = "V-CSI/DSI";
-					};
-				};
-			};
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/ste-hrefv60plus.dtsi b/arch/arm/boot/dts/ste-hrefv60plus.dtsi
new file mode 100644
index 0000000..aed511b
--- /dev/null
+++ b/arch/arm/boot/dts/ste-hrefv60plus.dtsi
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2012 ST-Ericsson AB
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "ste-dbx5x0.dtsi"
+#include "ste-href.dtsi"
+
+/ {
+	model = "ST-Ericsson HREF (v60+) platform with Device Tree";
+	compatible = "st-ericsson,hrefv60+", "st-ericsson,u8500";
+
+	gpio_keys {
+		button@1 {
+			gpios = <&gpio5 25 0x4>;
+		};
+	};
+
+	soc {
+		// External Micro SD slot
+		sdi0_per1@80126000 {
+			arm,primecell-periphid = <0x10480180>;
+			max-frequency = <100000000>;
+			bus-width = <4>;
+			mmc-cap-sd-highspeed;
+			mmc-cap-mmc-highspeed;
+			vmmc-supply = <&ab8500_ldo_aux3_reg>;
+
+			cd-gpios  = <&gpio2 31 0x4>; // 95
+
+			status = "okay";
+		};
+
+		// WLAN SDIO channel
+		sdi1_per2@80118000 {
+			arm,primecell-periphid = <0x10480180>;
+			max-frequency = <100000000>;
+			bus-width = <4>;
+
+			status = "okay";
+		};
+
+		// PoP:ed eMMC
+		sdi2_per3@80005000 {
+			arm,primecell-periphid = <0x10480180>;
+			max-frequency = <100000000>;
+			bus-width = <8>;
+			mmc-cap-mmc-highspeed;
+
+			status = "okay";
+		};
+
+		// On-board eMMC
+		sdi4_per2@80114000 {
+			arm,primecell-periphid = <0x10480180>;
+		        max-frequency = <100000000>;
+			bus-width = <8>;
+			mmc-cap-mmc-highspeed;
+			vmmc-supply = <&ab8500_ldo_aux2_reg>;
+
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi b/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
index 9169d30..79425e3 100644
--- a/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
+++ b/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
@@ -653,6 +653,7 @@
 		reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
 		clocks = <&hclksmc>;
 		status = "okay";
+		timings = /bits/ 8 <0 0 0 0x10 0x0a 0>;
 
 		partition@0 {
 		label = "X-Loader(NAND)";
@@ -707,8 +708,14 @@
 		pinctrl-0 = <&i2c0_default_mux>, <&i2c0_default_mode>;
 
 		stw4811@2d {
-			   compatible = "st,stw4811";
-			   reg = <0x2d>;
+			compatible = "st,stw4811";
+			reg = <0x2d>;
+			vmmc_regulator: vmmc {
+				compatible = "st,stw481x-vmmc";
+				regulator-name = "VMMC";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+			};
 		};
 	};
 
@@ -839,6 +846,7 @@
 			cd-inverted;
 			pinctrl-names = "default";
 			pinctrl-0 = <&mmcsd_default_mux>, <&mmcsd_default_mode>;
+			vmmc-supply = <&vmmc_regulator>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts
index f1fc128..f0b39f8 100644
--- a/arch/arm/boot/dts/ste-snowball.dts
+++ b/arch/arm/boot/dts/ste-snowball.dts
@@ -111,12 +111,13 @@
 				vdd33a-supply = <&en_3v3_reg>;
 				vddvario-supply = <&db8500_vape_reg>;
 
-
 				reg-shift = <1>;
 				reg-io-width = <2>;
 				smsc,force-internal-phy;
 				smsc,irq-active-high;
 				smsc,irq-push-pull;
+
+				clocks = <&prcc_pclk 3 0>;
 			};
 		};
 
@@ -170,86 +171,8 @@
 		};
 
 		prcmu@80157000 {
-			db8500-prcmu-regulators {
-				db8500_vape_reg: db8500_vape {
-					regulator-name = "db8500-vape";
-				};
-
-				db8500_varm_reg: db8500_varm {
-					regulator-name = "db8500-varm";
-				};
-
-				db8500_vmodem_reg: db8500_vmodem {
-					regulator-name = "db8500-vmodem";
-				};
-
-				db8500_vpll_reg: db8500_vpll {
-					regulator-name = "db8500-vpll";
-				};
-
-				db8500_vsmps1_reg: db8500_vsmps1 {
-					regulator-name = "db8500-vsmps1";
-				};
-
-				db8500_vsmps2_reg: db8500_vsmps2 {
-					regulator-name = "db8500-vsmps2";
-				};
-
-				db8500_vsmps3_reg: db8500_vsmps3 {
-					regulator-name = "db8500-vsmps3";
-				};
-
-				db8500_vrf1_reg: db8500_vrf1 {
-					regulator-name = "db8500-vrf1";
-				};
-
-				db8500_sva_mmdsp_reg: db8500_sva_mmdsp {
-					regulator-name = "db8500-sva-mmdsp";
-				};
-
-				db8500_sva_mmdsp_ret_reg: db8500_sva_mmdsp_ret {
-					regulator-name = "db8500-sva-mmdsp-ret";
-				};
-
-				db8500_sva_pipe_reg: db8500_sva_pipe {
-					regulator-name = "db8500_sva_pipe";
-				};
-
-				db8500_sia_mmdsp_reg: db8500_sia_mmdsp {
-					regulator-name = "db8500_sia_mmdsp";
-				};
-
-				db8500_sia_mmdsp_ret_reg: db8500_sia_mmdsp_ret {
-					regulator-name = "db8500-sia-mmdsp-ret";
-				};
-
-				db8500_sia_pipe_reg: db8500_sia_pipe {
-					regulator-name = "db8500-sia-pipe";
-				};
-
-				db8500_sga_reg: db8500_sga {
-					regulator-name = "db8500-sga";
-				};
-
-				db8500_b2r2_mcde_reg: db8500_b2r2_mcde {
-					regulator-name = "db8500-b2r2-mcde";
-				};
-
-				db8500_esram12_reg: db8500_esram12 {
-					regulator-name = "db8500-esram12";
-				};
-
-				db8500_esram12_ret_reg: db8500_esram12_ret {
-					regulator-name = "db8500-esram12-ret";
-				};
-
-				db8500_esram34_reg: db8500_esram34 {
-					regulator-name = "db8500-esram34";
-				};
-
-				db8500_esram34_ret_reg: db8500_esram34_ret {
-					regulator-name = "db8500-esram34-ret";
-				};
+			cpufreq {
+				status = "okay";
 			};
 
 			thermal@801573c0 {
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index c32770a..319cc6b 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -266,6 +266,11 @@
 			reg = <0x01c20c90 0x10>;
 		};
 
+		sid: eeprom@01c23800 {
+			compatible = "allwinner,sun4i-sid";
+			reg = <0x01c23800 0x10>;
+		};
+
 		uart0: serial@01c28000 {
 			compatible = "snps,dw-apb-uart";
 			reg = <0x01c28000 0x400>;
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index 3b4a057..5247674 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -255,6 +255,11 @@
 			reg = <0x01c20c90 0x10>;
 		};
 
+		sid: eeprom@01c23800 {
+			compatible = "allwinner,sun4i-sid";
+			reg = <0x01c23800 0x10>;
+		};
+
 		uart0: serial@01c28000 {
 			compatible = "snps,dw-apb-uart";
 			reg = <0x01c28000 0x400>;
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index f6091dc..ce8ef2a 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -222,6 +222,11 @@
 			reg = <0x01c20c90 0x10>;
 		};
 
+		sid: eeprom@01c23800 {
+			compatible = "allwinner,sun4i-sid";
+			reg = <0x01c23800 0x10>;
+		};
+
 		uart1: serial@01c28400 {
 			compatible = "snps,dw-apb-uart";
 			reg = <0x01c28400 0x400>;
diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index f244f5f..c1751a6 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -175,7 +175,7 @@
 		apb2_gates: apb2_gates@01c2006c {
 			#clock-cells = <1>;
 			compatible = "allwinner,sun6i-a31-apb2-gates-clk";
-			reg = <0x01c2006c 0x8>;
+			reg = <0x01c2006c 0x4>;
 			clocks = <&apb2>;
 			clock-output-names = "apb2_i2c0", "apb2_i2c1",
 					"apb2_i2c2", "apb2_i2c3", "apb2_uart0",
diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
index 15e625e..5c51cb8 100644
--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
@@ -48,6 +48,18 @@
 			pinctrl-0 = <&uart0_pins_a>;
 			status = "okay";
 		};
+
+		i2c0: i2c@01c2ac00 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c0_pins_a>;
+			status = "okay";
+		};
+
+		i2c1: i2c@01c2b000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c1_pins_a>;
+			status = "okay";
+		};
 	};
 
 	leds {
diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
new file mode 100644
index 0000000..8a1009d
--- /dev/null
+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 Oliver Schinagl
+ *
+ * Oliver Schinagl <oliver@schinagl.nl>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "sun7i-a20.dtsi"
+
+/ {
+	model = "Cubietech Cubietruck";
+	compatible = "cubietech,cubietruck", "allwinner,sun7i-a20";
+
+	soc@01c00000 {
+		pinctrl@01c20800 {
+			led_pins_cubietruck: led_pins@0 {
+				allwinner,pins = "PH7", "PH11", "PH20", "PH21";
+				allwinner,function = "gpio_out";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
+		};
+
+		uart0: serial@01c28000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart0_pins_a>;
+			status = "okay";
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pins_cubietruck>;
+
+		blue {
+			label = "cubietruck:blue:usr";
+			gpios = <&pio 7 21 0>;
+		};
+
+		orange {
+			label = "cubietruck:orange:usr";
+			gpios = <&pio 7 20 0>;
+		};
+
+		white {
+			label = "cubietruck:white:usr";
+			gpios = <&pio 7 11 0>;
+		};
+
+		green {
+			label = "cubietruck:green:usr";
+			gpios = <&pio 7 7 0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
index 9e77855..ead3013 100644
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
@@ -60,6 +60,24 @@
 			pinctrl-0 = <&uart7_pins_a>;
 			status = "okay";
 		};
+
+		i2c0: i2c@01c2ac00 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c0_pins_a>;
+			status = "okay";
+		};
+
+		i2c1: i2c@01c2b000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c1_pins_a>;
+			status = "okay";
+		};
+
+		i2c2: i2c@01c2b400 {
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c2_pins_a>;
+			status = "okay";
+		};
 	};
 
 	leds {
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 80559cb..e46cfed 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -215,6 +215,27 @@
 				allwinner,pull = <0>;
 			};
 
+			i2c0_pins_a: i2c0@0 {
+				allwinner,pins = "PB0", "PB1";
+				allwinner,function = "i2c0";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
+
+			i2c1_pins_a: i2c1@0 {
+				allwinner,pins = "PB18", "PB19";
+				allwinner,function = "i2c1";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
+
+			i2c2_pins_a: i2c2@0 {
+				allwinner,pins = "PB20", "PB21";
+				allwinner,function = "i2c2";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
+
 			emac_pins_a: emac0@0 {
 				allwinner,pins = "PA0", "PA1", "PA2",
 						"PA3", "PA4", "PA5", "PA6",
@@ -244,6 +265,11 @@
 			reg = <0x01c20c90 0x10>;
 		};
 
+		sid: eeprom@01c23800 {
+			compatible = "allwinner,sun7i-a20-sid";
+			reg = <0x01c23800 0x200>;
+		};
+
 		uart0: serial@01c28000 {
 			compatible = "snps,dw-apb-uart";
 			reg = <0x01c28000 0x400>;
@@ -324,6 +350,51 @@
 			status = "disabled";
 		};
 
+		i2c0: i2c@01c2ac00 {
+			compatible = "allwinner,sun4i-i2c";
+			reg = <0x01c2ac00 0x400>;
+			interrupts = <0 7 1>;
+			clocks = <&apb1_gates 0>;
+			clock-frequency = <100000>;
+			status = "disabled";
+		};
+
+		i2c1: i2c@01c2b000 {
+			compatible = "allwinner,sun4i-i2c";
+			reg = <0x01c2b000 0x400>;
+			interrupts = <0 8 1>;
+			clocks = <&apb1_gates 1>;
+			clock-frequency = <100000>;
+			status = "disabled";
+		};
+
+		i2c2: i2c@01c2b400 {
+			compatible = "allwinner,sun4i-i2c";
+			reg = <0x01c2b400 0x400>;
+			interrupts = <0 9 1>;
+			clocks = <&apb1_gates 2>;
+			clock-frequency = <100000>;
+			status = "disabled";
+		};
+
+		i2c3: i2c@01c2b800 {
+			compatible = "allwinner,sun4i-i2c";
+			reg = <0x01c2b800 0x400>;
+			interrupts = <0 88 1>;
+			clocks = <&apb1_gates 3>;
+			clock-frequency = <100000>;
+			status = "disabled";
+		};
+
+		i2c4: i2c@01c2bc00 {
+			compatible = "allwinner,sun4i-i2c";
+			reg = <0x01c2bc00 0x400>;
+			interrupts = <0 89 1>;
+			clocks = <&apb1_gates 15>;
+			clock-frequency = <100000>;
+			status = "disabled";
+		};
+
 		gic: interrupt-controller@01c81000 {
 			compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
 			reg = <0x01c81000 0x1000>,
diff --git a/arch/arm/boot/dts/tegra114-dalmore.dts b/arch/arm/boot/dts/tegra114-dalmore.dts
index 6023028..cb5ec23 100644
--- a/arch/arm/boot/dts/tegra114-dalmore.dts
+++ b/arch/arm/boot/dts/tegra114-dalmore.dts
@@ -1,5 +1,6 @@
 /dts-v1/;
 
+#include <dt-bindings/input/input.h>
 #include "tegra114.dtsi"
 
 / {
@@ -738,6 +739,14 @@
 			realtek,ldo1-en-gpios =
 				<&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>;
 		};
+
+		temperature-sensor@4c {
+			compatible = "onnn,nct1008";
+			reg = <0x4c>;
+			vcc-supply = <&palmas_ldo6_reg>;
+			interrupt-parent = <&gpio>;
+			interrupts = <TEGRA_GPIO(O, 4) IRQ_TYPE_LEVEL_LOW>;
+		};
 	};
 
 	i2c@7000d000 {
@@ -947,7 +956,7 @@
 						regulator-max-microvolt = <1800000>;
 					};
 
-					ldo6 {
+					palmas_ldo6_reg: ldo6 {
 						regulator-name = "vdd-sensor-2v85";
 						regulator-min-microvolt = <2850000>;
 						regulator-max-microvolt = <2850000>;
@@ -1011,6 +1020,19 @@
 				interrupt-parent = <&palmas>;
 				interrupts = <8 0>;
 			};
+
+			pinmux {
+				compatible = "ti,tps65913-pinctrl";
+				pinctrl-names = "default";
+				pinctrl-0 = <&palmas_default>;
+
+				palmas_default: pinmux {
+					pin_gpio6 {
+						pins = "gpio6";
+						function = "gpio";
+					};
+				};
+			};
 		};
 	};
 
@@ -1081,26 +1103,26 @@
 		home {
 			label = "Home";
 			gpios = <&gpio TEGRA_GPIO(I, 5) GPIO_ACTIVE_LOW>;
-			linux,code = <102>; /* KEY_HOME */
+			linux,code = <KEY_HOME>;
 		};
 
 		power {
 			label = "Power";
 			gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>;
-			linux,code = <116>; /* KEY_POWER */
+			linux,code = <KEY_POWER>;
 			gpio-key,wakeup;
 		};
 
 		volume_down {
 			label = "Volume Down";
 			gpios = <&gpio TEGRA_GPIO(R, 1) GPIO_ACTIVE_LOW>;
-			linux,code = <114>; /* KEY_VOLUMEDOWN */
+			linux,code = <KEY_VOLUMEDOWN>;
 		};
 
 		volume_up {
 			label = "Volume Up";
 			gpios = <&gpio TEGRA_GPIO(R, 2) GPIO_ACTIVE_LOW>;
-			linux,code = <115>; /* KEY_VOLUMEUP */
+			linux,code = <KEY_VOLUMEUP>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index 2905145..8d42787 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -318,9 +318,9 @@
 
 	iommu {
 		compatible = "nvidia,tegra114-smmu", "nvidia,tegra30-smmu";
-		reg = <0x7000f010 0x02c
-		       0x7000f1f0 0x010
-		       0x7000f228 0x074>;
+		reg = <0x70019010 0x02c
+		       0x700191f0 0x010
+		       0x70019228 0x074>;
 		nvidia,#asids = <4>;
 		dma-window = <0 0x40000000>;
 		nvidia,swgroups = <0x18659fe>;
diff --git a/arch/arm/boot/dts/tegra124-venice2.dts b/arch/arm/boot/dts/tegra124-venice2.dts
new file mode 100644
index 0000000..431d67a
--- /dev/null
+++ b/arch/arm/boot/dts/tegra124-venice2.dts
@@ -0,0 +1,27 @@
+/dts-v1/;
+
+#include "tegra124.dtsi"
+
+/ {
+	model = "NVIDIA Tegra124 Venice2";
+	compatible = "nvidia,venice2", "nvidia,tegra124";
+
+	memory {
+		reg = <0x80000000 0x80000000>;
+	};
+
+	serial@70006000 {
+		status = "okay";
+	};
+
+	pmc@7000e400 {
+		nvidia,invert-interrupt;
+		nvidia,suspend-mode = <1>;
+		nvidia,cpu-pwr-good-time = <500>;
+		nvidia,cpu-pwr-off-time = <300>;
+		nvidia,core-pwr-good-time = <641 3845>;
+		nvidia,core-pwr-off-time = <61036>;
+		nvidia,core-power-req-active-high;
+		nvidia,sys-clock-req-active-high;
+	};
+};
diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
new file mode 100644
index 0000000..b741300
--- /dev/null
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -0,0 +1,149 @@
+#include <dt-bindings/gpio/tegra-gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "skeleton.dtsi"
+
+/ {
+	compatible = "nvidia,tegra124";
+	interrupt-parent = <&gic>;
+
+	gic: interrupt-controller@50041000 {
+		compatible = "arm,cortex-a15-gic";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0x50041000 0x1000>,
+		      <0x50042000 0x1000>,
+		      <0x50044000 0x2000>,
+		      <0x50046000 0x2000>;
+		interrupts = <GIC_PPI 9
+			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	timer@60005000 {
+		compatible = "nvidia,tegra124-timer", "nvidia,tegra20-timer";
+		reg = <0x60005000 0x400>;
+		interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	gpio: gpio@6000d000 {
+		compatible = "nvidia,tegra124-gpio", "nvidia,tegra30-gpio";
+		reg = <0x6000d000 0x1000>;
+		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	/*
+	 * There are two serial driver i.e. 8250 based simple serial
+	 * driver and APB DMA based serial driver for higher baudrate
+	 * and performace. To enable the 8250 based driver, the compatible
+	 * is "nvidia,tegra124-uart", "nvidia,tegra20-uart" and to enable
+	 * the APB DMA based serial driver, the comptible is
+	 * "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart".
+	 */
+	serial@70006000 {
+		compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
+		reg = <0x70006000 0x40>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	serial@70006040 {
+		compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
+		reg = <0x70006040 0x40>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	serial@70006200 {
+		compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
+		reg = <0x70006200 0x40>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	serial@70006300 {
+		compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
+		reg = <0x70006300 0x40>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	serial@70006400 {
+		compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
+		reg = <0x70006400 0x40>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	rtc@7000e000 {
+		compatible = "nvidia,tegra124-rtc", "nvidia,tegra20-rtc";
+		reg = <0x7000e000 0x100>;
+		interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	pmc@7000e400 {
+		compatible = "nvidia,tegra124-pmc";
+		reg = <0x7000e400 0x400>;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0>;
+		};
+
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <1>;
+		};
+
+		cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <2>;
+		};
+
+		cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <3>;
+		};
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupts = <GIC_PPI 13
+				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14
+				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11
+				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10
+				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+	};
+};
diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi
index e19dbf2..5ea7dfa 100644
--- a/arch/arm/boot/dts/tegra30-cardhu.dtsi
+++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi
@@ -294,9 +294,10 @@
 			};
 		};
 
-		nct1008 {
+		temperature-sensor@4c {
 			compatible = "onnn,nct1008";
 			reg = <0x4c>;
+			vcc-supply = <&sys_3v3_reg>;
 			interrupt-parent = <&gpio>;
 			interrupts = <TEGRA_GPIO(CC, 2) IRQ_TYPE_LEVEL_LOW>;
 		};
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index 0022c12..2bd55cf 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -136,12 +136,13 @@
 		gr3d {
 			compatible = "nvidia,tegra30-gr3d";
 			reg = <0x54180000 0x00040000>;
-			clocks = <&tegra_car 24 &tegra_car 98>;
+			clocks = <&tegra_car TEGRA30_CLK_GR3D
+				  &tegra_car TEGRA30_CLK_GR3D2>;
 			clock-names = "3d", "3d2";
 		};
 
 		dc@54200000 {
-			compatible = "nvidia,tegra30-dc";
+			compatible = "nvidia,tegra30-dc", "nvidia,tegra20-dc";
 			reg = <0x54200000 0x00040000>;
 			interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&tegra_car TEGRA30_CLK_DISP1>,
diff --git a/arch/arm/boot/dts/testcases/tests-interrupts.dtsi b/arch/arm/boot/dts/testcases/tests-interrupts.dtsi
new file mode 100644
index 0000000..c843720
--- /dev/null
+++ b/arch/arm/boot/dts/testcases/tests-interrupts.dtsi
@@ -0,0 +1,58 @@
+
+/ {
+	testcase-data {
+		interrupts {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			test_intc0: intc0 {
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			test_intc1: intc1 {
+				interrupt-controller;
+				#interrupt-cells = <3>;
+			};
+
+			test_intc2: intc2 {
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			test_intmap0: intmap0 {
+				#interrupt-cells = <1>;
+				#address-cells = <0>;
+				interrupt-map = <1 &test_intc0 9>,
+						<2 &test_intc1 10 11 12>,
+						<3 &test_intc2 13 14>,
+						<4 &test_intc2 15 16>;
+			};
+
+			test_intmap1: intmap1 {
+				#interrupt-cells = <2>;
+				interrupt-map = <0x5000 1 2 &test_intc0 15>;
+			};
+
+			interrupts0 {
+				interrupt-parent = <&test_intc0>;
+				interrupts = <1>, <2>, <3>, <4>;
+			};
+
+			interrupts1 {
+				interrupt-parent = <&test_intmap0>;
+				interrupts = <1>, <2>, <3>, <4>;
+			};
+
+			interrupts-extended0 {
+				reg = <0x5000 0x100>;
+				interrupts-extended = <&test_intc0 1>,
+						      <&test_intc1 2 3 4>,
+						      <&test_intc2 5 6>,
+						      <&test_intmap0 1>,
+						      <&test_intmap0 2>,
+						      <&test_intmap0 3>,
+						      <&test_intmap1 1 2>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/testcases/tests.dtsi b/arch/arm/boot/dts/testcases/tests.dtsi
index a7c5067..3f123ec 100644
--- a/arch/arm/boot/dts/testcases/tests.dtsi
+++ b/arch/arm/boot/dts/testcases/tests.dtsi
@@ -1 +1,2 @@
 /include/ "tests-phandle.dtsi"
+/include/ "tests-interrupts.dtsi"
diff --git a/arch/arm/boot/dts/twl4030.dtsi b/arch/arm/boot/dts/twl4030.dtsi
index ae6a17a..fb1b2ec 100644
--- a/arch/arm/boot/dts/twl4030.dtsi
+++ b/arch/arm/boot/dts/twl4030.dtsi
@@ -23,6 +23,22 @@
 		compatible = "ti,twl4030-wdt";
 	};
 
+	vaux1: regulator-vaux1 {
+		compatible = "ti,twl4030-vaux1";
+	};
+
+	vaux2: regulator-vaux2 {
+		compatible = "ti,twl4030-vaux2";
+	};
+
+	vaux3: regulator-vaux3 {
+		compatible = "ti,twl4030-vaux3";
+	};
+
+	vaux4: regulator-vaux4 {
+		compatible = "ti,twl4030-vaux4";
+	};
+
 	vcc: regulator-vdd1 {
 		compatible = "ti,twl4030-vdd1";
 		regulator-min-microvolt = <600000>;
@@ -35,10 +51,20 @@
 		regulator-max-microvolt = <1800000>;
 	};
 
-	vpll2: regulator-vpll2 {
-		compatible = "ti,twl4030-vpll2";
-		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <1800000>;
+	vio: regulator-vio {
+		compatible = "ti,twl4030-vio";
+	};
+
+	vintana1: regulator-vintana1 {
+		compatible = "ti,twl4030-vintana1";
+	};
+
+	vintana2: regulator-vintana2 {
+		compatible = "ti,twl4030-vintana2";
+	};
+
+	vintdig: regulator-vintdig {
+		compatible = "ti,twl4030-vintdig";
 	};
 
 	vmmc1: regulator-vmmc1 {
@@ -65,6 +91,16 @@
 		compatible = "ti,twl4030-vusb3v1";
 	};
 
+	vpll1: regulator-vpll1 {
+		compatible = "ti,twl4030-vpll1";
+	};
+
+	vpll2: regulator-vpll2 {
+		compatible = "ti,twl4030-vpll2";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
 	vsim: regulator-vsim {
 		compatible = "ti,twl4030-vsim";
 		regulator-min-microvolt = <1800000>;
@@ -86,6 +122,7 @@
 		usb1v8-supply = <&vusb1v8>;
 		usb3v1-supply = <&vusb3v1>;
 		usb_mode = <1>;
+		#phy-cells = <0>;
 	};
 
 	twl_pwm: pwm {
@@ -97,4 +134,9 @@
 		compatible = "ti,twl4030-pwmled";
 		#pwm-cells = <2>;
 	};
+
+	twl_pwrbutton: pwrbutton {
+		compatible = "ti,twl4030-pwrbutton";
+		interrupts = <8>;
+	};
 };
diff --git a/arch/arm/boot/dts/twl6030_omap4.dtsi b/arch/arm/boot/dts/twl6030_omap4.dtsi
new file mode 100644
index 0000000..a4fa570
--- /dev/null
+++ b/arch/arm/boot/dts/twl6030_omap4.dtsi
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&twl {
+	/*
+	 * On most OMAP4 platforms, the twl6030 IRQ line is connected
+	 * to the SYS_NIRQ1 line on OMAP and the twl6030 MSECURE line is
+	 * connected to the fref_clk0_out.sys_drm_msecure line.
+	 * Therefore, configure the defaults for the SYS_NIRQ1 and
+	 * fref_clk0_out.sys_drm_msecure pins here.
+	 */
+	pinctrl-names = "default";
+	pinctrl-0 = <
+		&twl6030_pins
+		&twl6030_wkup_pins
+	>;
+};
+
+&omap4_pmx_wkup {
+	twl6030_wkup_pins: pinmux_twl6030_wkup_pins {
+		pinctrl-single,pins = <
+			0x14 (PIN_OUTPUT | MUX_MODE2)		/* fref_clk0_out.sys_drm_msecure */
+		>;
+	};
+};
+
+&omap4_pmx_core {
+	twl6030_pins: pinmux_twl6030_pins {
+		pinctrl-single,pins = <
+			0x15e (WAKEUP_EN | PIN_INPUT_PULLUP | MUX_MODE0)	/* sys_nirq1.sys_nirq1 */
+		>;
+	};
+};
diff --git a/arch/arm/boot/dts/versatile-ab.dts b/arch/arm/boot/dts/versatile-ab.dts
index dde75ae..e01e5a0 100644
--- a/arch/arm/boot/dts/versatile-ab.dts
+++ b/arch/arm/boot/dts/versatile-ab.dts
@@ -185,7 +185,7 @@
 			mmc@5000 {
 				compatible = "arm,primecell";
 				reg = < 0x5000 0x1000>;
-				interrupts = <22 34>;
+				interrupts-extended = <&vic 22 &sic 2>;
 			};
 			kmi@6000 {
 				compatible = "arm,pl050", "arm,primecell";
diff --git a/arch/arm/boot/dts/versatile-pb.dts b/arch/arm/boot/dts/versatile-pb.dts
index 7e81752..f43907c 100644
--- a/arch/arm/boot/dts/versatile-pb.dts
+++ b/arch/arm/boot/dts/versatile-pb.dts
@@ -41,7 +41,7 @@
 			mmc@b000 {
 				compatible = "arm,primecell";
 				reg = <0xb000 0x1000>;
-				interrupts = <23 34>;
+				interrupts-extended = <&vic 23 &sic 2>;
 			};
 		};
 	};
diff --git a/arch/arm/boot/dts/vf610-cosmic.dts b/arch/arm/boot/dts/vf610-cosmic.dts
new file mode 100644
index 0000000..c42e4f9
--- /dev/null
+++ b/arch/arm/boot/dts/vf610-cosmic.dts
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ * Copyright 2013 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+/dts-v1/;
+#include "vf610.dtsi"
+
+/ {
+	model = "PHYTEC Cosmic/Cosmic+ Board";
+	compatible = "phytec,vf610-cosmic", "fsl,vf610";
+
+	chosen {
+		bootargs = "console=ttyLP1,115200";
+	};
+
+	memory {
+		reg = <0x80000000 0x10000000>;
+	};
+
+	clocks {
+		enet_ext {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <50000000>;
+		};
+	};
+
+};
+
+&fec1 {
+	phy-mode = "rmii";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec1_1>;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_1>;
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/vf610-twr.dts b/arch/arm/boot/dts/vf610-twr.dts
index 1a58678..c8047ca 100644
--- a/arch/arm/boot/dts/vf610-twr.dts
+++ b/arch/arm/boot/dts/vf610-twr.dts
@@ -36,6 +36,23 @@
 
 };
 
+&dspi0 {
+	bus-num = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_dspi0_1>;
+	status = "okay";
+
+	sflash: at26df081a@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "atmel,at26df081a";
+		spi-max-frequency = <16000000>;
+		spi-cpol;
+		spi-cpha;
+		reg = <0>;
+	};
+};
+
 &fec0 {
 	phy-mode = "rmii";
 	pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi
index 67d929c..d31ce1b 100644
--- a/arch/arm/boot/dts/vf610.dtsi
+++ b/arch/arm/boot/dts/vf610.dtsi
@@ -123,6 +123,18 @@
 				status = "disabled";
 			};
 
+			dspi0: dspi0@4002c000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,vf610-dspi";
+				reg = <0x4002c000 0x1000>;
+				interrupts = <0 67 0x04>;
+				clocks = <&clks VF610_CLK_DSPI0>;
+				clock-names = "dspi";
+				spi-num-chipselects = <5>;
+				status = "disabled";
+			};
+
 			sai2: sai@40031000 {
 				compatible = "fsl,vf610-sai";
 				reg = <0x40031000 0x1000>;
diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi
index e32b92b..e7f73b2 100644
--- a/arch/arm/boot/dts/zynq-7000.dtsi
+++ b/arch/arm/boot/dts/zynq-7000.dtsi
@@ -92,6 +92,14 @@
 			};
 		};
 
+		global_timer: timer@f8f00200 {
+			compatible = "arm,cortex-a9-global-timer";
+			reg = <0xf8f00200 0x20>;
+			interrupts = <1 11 0x301>;
+			interrupt-parent = <&intc>;
+			clocks = <&clkc 4>;
+		};
+
 		ttc0: ttc0@f8001000 {
 			interrupt-parent = <&intc>;
 			interrupts = < 0 10 4 0 11 4 0 12 4 >;
diff --git a/arch/arm/boot/install.sh b/arch/arm/boot/install.sh
index 06ea7d4..2a45092 100644
--- a/arch/arm/boot/install.sh
+++ b/arch/arm/boot/install.sh
@@ -20,6 +20,20 @@
 #   $4 - default install path (blank if root directory)
 #
 
+verify () {
+	if [ ! -f "$1" ]; then
+		echo ""                                                   1>&2
+		echo " *** Missing file: $1"                              1>&2
+		echo ' *** You need to run "make" before "make install".' 1>&2
+		echo ""                                                   1>&2
+		exit 1
+	fi
+}
+
+# Make sure the files actually exist
+verify "$2"
+verify "$3"
+
 # User may have a custom install script
 if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi
 if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 8c60f47..eaa9cf4 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -6,7 +6,6 @@
 
 obj-$(CONFIG_ICST)		+= icst.o
 obj-$(CONFIG_SA1111)		+= sa1111.o
-obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o
 obj-$(CONFIG_DMABOUNCE)		+= dmabounce.o
 obj-$(CONFIG_SHARP_LOCOMO)	+= locomo.o
 obj-$(CONFIG_SHARP_PARAM)	+= sharpsl_param.o
diff --git a/arch/arm/common/mcpm_entry.c b/arch/arm/common/mcpm_entry.c
index 370236d..9902509 100644
--- a/arch/arm/common/mcpm_entry.c
+++ b/arch/arm/common/mcpm_entry.c
@@ -51,7 +51,8 @@
 {
 	phys_reset_t phys_reset;
 
-	BUG_ON(!platform_ops);
+	if (WARN_ON_ONCE(!platform_ops || !platform_ops->power_down))
+		return;
 	BUG_ON(!irqs_disabled());
 
 	/*
@@ -93,7 +94,8 @@
 {
 	phys_reset_t phys_reset;
 
-	BUG_ON(!platform_ops);
+	if (WARN_ON_ONCE(!platform_ops || !platform_ops->suspend))
+		return;
 	BUG_ON(!irqs_disabled());
 
 	/* Very similar to mcpm_cpu_power_down() */
diff --git a/arch/arm/common/sharpsl_param.c b/arch/arm/common/sharpsl_param.c
index d56c932..025f6ce 100644
--- a/arch/arm/common/sharpsl_param.c
+++ b/arch/arm/common/sharpsl_param.c
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <asm/mach/sharpsl_param.h>
+#include <asm/memory.h>
 
 /*
  * Certain hardware parameters determined at the time of device manufacture,
@@ -25,8 +26,10 @@
  */
 #ifdef CONFIG_ARCH_SA1100
 #define PARAM_BASE	0xe8ffc000
+#define param_start(x)	(void *)(x)
 #else
 #define PARAM_BASE	0xa0000a00
+#define param_start(x)	__va(x)
 #endif
 #define MAGIC_CHG(a,b,c,d) ( ( d << 24 ) | ( c << 16 )  | ( b << 8 ) | a )
 
@@ -41,7 +44,7 @@
 
 void sharpsl_save_param(void)
 {
-	memcpy(&sharpsl_param, (void *)PARAM_BASE, sizeof(struct sharpsl_param_info));
+	memcpy(&sharpsl_param, param_start(PARAM_BASE), sizeof(struct sharpsl_param_info));
 
 	if (sharpsl_param.comadj_keyword != COMADJ_MAGIC)
 		sharpsl_param.comadj=-1;
diff --git a/arch/arm/common/via82c505.c b/arch/arm/common/via82c505.c
deleted file mode 100644
index 6cb362e..0000000
--- a/arch/arm/common/via82c505.c
+++ /dev/null
@@ -1,83 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-
-
-#include <asm/mach/pci.h>
-
-#define MAX_SLOTS		7
-
-#define CONFIG_CMD(bus, devfn, where)   (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
-
-static int
-via82c505_read_config(struct pci_bus *bus, unsigned int devfn, int where,
-		      int size, u32 *value)
-{
-	outl(CONFIG_CMD(bus,devfn,where),0xCF8);
-	switch (size) {
-	case 1:
-		*value=inb(0xCFC + (where&3));
-		break;
-	case 2:
-		*value=inw(0xCFC + (where&2));
-		break;
-	case 4:
-		*value=inl(0xCFC);
-		break;
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-via82c505_write_config(struct pci_bus *bus, unsigned int devfn, int where,
-		       int size, u32 value)
-{
-	outl(CONFIG_CMD(bus,devfn,where),0xCF8);
-	switch (size) {
-	case 1:
-		outb(value, 0xCFC + (where&3));
-		break;
-	case 2:
-		outw(value, 0xCFC + (where&2));
-		break;
-	case 4:
-		outl(value, 0xCFC);
-		break;
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops via82c505_ops = {
-	.read	= via82c505_read_config,
-	.write	= via82c505_write_config,
-};
-
-void __init via82c505_preinit(void)
-{
-	printk(KERN_DEBUG "PCI: VIA 82c505\n");
-	if (!request_region(0xA8,2,"via config")) {
-		printk(KERN_WARNING"VIA 82c505: Unable to request region 0xA8\n");
-		return;
-	}
-	if (!request_region(0xCF8,8,"pci config")) {
-		printk(KERN_WARNING"VIA 82c505: Unable to request region 0xCF8\n");
-		release_region(0xA8, 2);
-		return;
-	}
-
-	/* Enable compatible Mode */
-	outb(0x96,0xA8);
-	outb(0x18,0xA9);
-	outb(0x93,0xA8);
-	outb(0xd0,0xA9);
-
-}
-
-int __init via82c505_setup(int nr, struct pci_sys_data *sys)
-{
-	return (nr == 0);
-}
diff --git a/arch/arm/configs/bcm_defconfig b/arch/arm/configs/bcm_defconfig
index 6e49310..287ac1d 100644
--- a/arch/arm/configs/bcm_defconfig
+++ b/arch/arm/configs/bcm_defconfig
@@ -1,4 +1,3 @@
-CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
@@ -25,10 +24,9 @@
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_PARTITION_ADVANCED=y
-CONFIG_EFI_PARTITION=y
 CONFIG_ARCH_BCM=y
+CONFIG_ARCH_BCM_MOBILE=y
 CONFIG_ARM_THUMBEE=y
-CONFIG_ARM_ERRATA_743622=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 # CONFIG_OABI_COMPAT is not set
@@ -50,7 +48,6 @@
 CONFIG_NET_KEY=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
-CONFIG_ARPD=y
 CONFIG_SYN_COOKIES=y
 CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6=y
@@ -95,7 +92,6 @@
 CONFIG_MMC_BLOCK_MINORS=32
 CONFIG_MMC_TEST=y
 CONFIG_MMC_SDHCI=y
-CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_BCM_KONA=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
@@ -117,12 +113,12 @@
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
-CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=110
 CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
-CONFIG_DEBUG_INFO=y
 # CONFIG_FTRACE is not set
 CONFIG_CRC_CCITT=y
 CONFIG_CRC_T10DIF=y
diff --git a/arch/arm/configs/bockw_defconfig b/arch/arm/configs/bockw_defconfig
index e7e9494..b38cd10 100644
--- a/arch/arm/configs/bockw_defconfig
+++ b/arch/arm/configs/bockw_defconfig
@@ -91,6 +91,10 @@
 CONFIG_VIDEO_ML86V7667=y
 CONFIG_SPI=y
 CONFIG_SPI_SH_HSPI=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_RCAR=y
 CONFIG_USB=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_EHCI_HCD=y
diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig
index 806005a..6ac5ea7 100644
--- a/arch/arm/configs/ep93xx_defconfig
+++ b/arch/arm/configs/ep93xx_defconfig
@@ -1,15 +1,14 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARCH_EP93XX=y
 CONFIG_CRUNCH=y
@@ -47,11 +46,8 @@
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_REDBOOT_PARTS=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_ADV_OPTIONS=y
@@ -67,15 +63,14 @@
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
 CONFIG_EP93XX_ETH=y
 CONFIG_USB_RTL8150=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_AMBA_PL010=y
 CONFIG_SERIAL_AMBA_PL010_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -86,9 +81,9 @@
 CONFIG_EP93XX_WATCHDOG=y
 CONFIG_USB=y
 CONFIG_USB_DEBUG=y
-CONFIG_USB_DEVICEFS=y
 CONFIG_USB_DYNAMIC_MINORS=y
 CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_SERIAL=y
 CONFIG_USB_SERIAL_CONSOLE=y
@@ -100,24 +95,18 @@
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
-CONFIG_INOTIFY=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_SLAB=y
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_LIBCRC32C=y
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index 5d488c2..8d0c5a0 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -132,7 +132,6 @@
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_MMA8450=y
 CONFIG_SERIO_SERPORT=m
-CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_IMX=y
@@ -188,22 +187,33 @@
 CONFIG_SND_SOC_EUKREA_TLV320=y
 CONFIG_SND_SOC_IMX_WM8962=y
 CONFIG_SND_SOC_IMX_SGTL5000=y
+CONFIG_SND_SOC_IMX_SPDIF=y
 CONFIG_SND_SOC_IMX_MC13783=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MXC=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_UDC=y
 CONFIG_USB_CHIPIDEA_HOST=y
-CONFIG_USB_PHY=y
 CONFIG_NOP_USB_XCEIV=y
 CONFIG_USB_MXS_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ETH=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_ESDHC_IMX=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_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_INTF_DEV_UIE_EMUL=y
 CONFIG_RTC_DRV_MC13XXX=y
@@ -246,7 +256,6 @@
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
-CONFIG_CONFIGFS_FS=m
 CONFIG_JFFS2_FS=y
 CONFIG_UBIFS_FS=y
 CONFIG_NFS_FS=y
@@ -261,6 +270,7 @@
 CONFIG_NLS_UTF8=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_SCHED_DEBUG is not set
+CONFIG_PROVE_LOCKING=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FTRACE is not set
 # CONFIG_ARM_UNWIND is not set
diff --git a/arch/arm/configs/integrator_defconfig b/arch/arm/configs/integrator_defconfig
index a8314c3..5bae195 100644
--- a/arch/arm/configs/integrator_defconfig
+++ b/arch/arm/configs/integrator_defconfig
@@ -1,15 +1,17 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
-CONFIG_TINY_RCU=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
 CONFIG_ARCH_INTEGRATOR=y
 CONFIG_ARCH_INTEGRATOR_AP=y
 CONFIG_ARCH_INTEGRATOR_CP=y
+CONFIG_INTEGRATOR_IMPD1=y
 CONFIG_CPU_ARM720T=y
 CONFIG_CPU_ARM920T=y
 CONFIG_CPU_ARM922T=y
@@ -18,12 +20,9 @@
 CONFIG_CPU_ARM1022=y
 CONFIG_CPU_ARM1026=y
 CONFIG_PCI=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
-CONFIG_LEDS=y
-CONFIG_LEDS_CPU=y
+# CONFIG_ATAGS is not set
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_CMDLINE="console=ttyAM0,38400n8 root=/dev/nfs ip=bootp"
@@ -44,24 +43,20 @@
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_AFS_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_ADV_OPTIONS=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_PHYSMAP=y
+CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_NET_PCI=y
 CONFIG_E100=y
 CONFIG_SMC91X=y
 # CONFIG_KEYBOARD_ATKBD is not set
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_AMBA_PL010=y
-CONFIG_SERIAL_AMBA_PL010_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_ARMCLCD=y
@@ -71,19 +66,23 @@
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_MMC=y
 CONFIG_MMC_ARMMMCI=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_CPU=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_PL030=y
+CONFIG_COMMON_CLK_DEBUG=y
 CONFIG_EXT2_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_CRAMFS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
-CONFIG_PARTITION_ADVANCED=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/arm/configs/keystone_defconfig b/arch/arm/configs/keystone_defconfig
index 1f36b82..9943e5d 100644
--- a/arch/arm/configs/keystone_defconfig
+++ b/arch/arm/configs/keystone_defconfig
@@ -123,7 +123,9 @@
 CONFIG_I2C=y
 # CONFIG_I2C_COMPAT is not set
 CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_DAVINCI=y
 CONFIG_SPI=y
+CONFIG_SPI_DAVINCI=y
 CONFIG_SPI_SPIDEV=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
diff --git a/arch/arm/configs/koelsch_defconfig b/arch/arm/configs/koelsch_defconfig
new file mode 100644
index 0000000..825c16d
--- /dev/null
+++ b/arch/arm/configs/koelsch_defconfig
@@ -0,0 +1,54 @@
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+CONFIG_SLAB=y
+# CONFIG_BLOCK is not set
+CONFIG_ARCH_SHMOBILE=y
+CONFIG_ARCH_R8A7791=y
+CONFIG_MACH_KOELSCH=y
+# CONFIG_SWP_EMULATE is not set
+CONFIG_CPU_BPREDICT_DISABLE=y
+CONFIG_PL310_ERRATA_588369=y
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_NR_CPUS=8
+CONFIG_AEABI=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_KEXEC=y
+CONFIG_AUTO_ZRELADDR=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=20
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+# CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_RCAR_THERMAL=y
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+CONFIG_TMPFS=y
+CONFIG_CONFIGFS_FS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_ARM_UNWIND is not set
diff --git a/arch/arm/configs/lager_defconfig b/arch/arm/configs/lager_defconfig
index e777ef2..35bff5e 100644
--- a/arch/arm/configs/lager_defconfig
+++ b/arch/arm/configs/lager_defconfig
@@ -89,6 +89,8 @@
 CONFIG_RCAR_THERMAL=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_DRM=y
+CONFIG_DRM_RCAR_DU=y
 # CONFIG_USB_SUPPORT is not set
 CONFIG_MMC=y
 CONFIG_MMC_SDHI=y
diff --git a/arch/arm/configs/marzen_defconfig b/arch/arm/configs/marzen_defconfig
index 000e920..5cc6360 100644
--- a/arch/arm/configs/marzen_defconfig
+++ b/arch/arm/configs/marzen_defconfig
@@ -92,6 +92,8 @@
 CONFIG_VIDEO_RCAR_VIN=y
 # CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
 CONFIG_VIDEO_ADV7180=y
+CONFIG_DRM=y
+CONFIG_DRM_RCAR_DU=y
 CONFIG_USB=y
 CONFIG_USB_RCAR_PHY=y
 CONFIG_MMC=y
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 119fc37..4a5903e 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -6,6 +6,7 @@
 CONFIG_MACH_ARMADA_370=y
 CONFIG_MACH_ARMADA_XP=y
 CONFIG_ARCH_BCM=y
+CONFIG_ARCH_BCM_MOBILE=y
 CONFIG_GPIO_PCA953X=y
 CONFIG_ARCH_HIGHBANK=y
 CONFIG_ARCH_KEYSTONE=y
diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig
index 4555c02..6150108 100644
--- a/arch/arm/configs/mxs_defconfig
+++ b/arch/arm/configs/mxs_defconfig
@@ -76,7 +76,6 @@
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_TSC2007=m
 # CONFIG_SERIO is not set
-CONFIG_VT_HW_CONSOLE_BINDING=y
 CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
@@ -91,7 +90,6 @@
 CONFIG_SPI=y
 CONFIG_SPI_GPIO=m
 CONFIG_SPI_MXS=y
-CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
@@ -115,9 +113,12 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_UDC=y
 CONFIG_USB_CHIPIDEA_HOST=y
-CONFIG_USB_PHY=y
 CONFIG_USB_MXS_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ETH=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_MMC=y
 CONFIG_MMC_UNSAFE_RESUME=y
 CONFIG_MMC_MXS=y
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index 254cf05..98a50c3 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -1,14 +1,13 @@
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_EXPERT=y
-# CONFIG_SYSCTL_SYSCALL is not set
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_SLAB=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
@@ -20,22 +19,21 @@
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
 CONFIG_ARCH_MULTI_V6=y
-CONFIG_ARCH_OMAP2PLUS=y
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_MUX_DEBUG=y
 CONFIG_ARCH_OMAP2=y
 CONFIG_ARCH_OMAP3=y
 CONFIG_ARCH_OMAP4=y
+CONFIG_SOC_OMAP5=y
 CONFIG_SOC_AM33XX=y
-CONFIG_OMAP_RESET_CLOCKS=y
-CONFIG_OMAP_MUX_DEBUG=y
-CONFIG_ARCH_VEXPRESS_CA9X4=y
+CONFIG_SOC_DRA7XX=y
 CONFIG_ARM_THUMBEE=y
 CONFIG_ARM_ERRATA_411920=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
-CONFIG_LEDS=y
+CONFIG_CMA=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
@@ -61,8 +59,6 @@
 # CONFIG_IPV6 is not set
 CONFIG_NETFILTER=y
 CONFIG_CAN=m
-CONFIG_CAN_RAW=m
-CONFIG_CAN_BCM=m
 CONFIG_CAN_C_CAN=m
 CONFIG_CAN_C_CAN_PLATFORM=m
 CONFIG_BT=m
@@ -77,14 +73,13 @@
 CONFIG_MAC80211_RC_PID=y
 CONFIG_MAC80211_RC_DEFAULT_PID=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_CMA=y
-CONFIG_DMA_CMA=y
-CONFIG_CONNECTOR=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_DMA_CMA=y
+CONFIG_OMAP_OCP2SCP=y
+CONFIG_CONNECTOR=y
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_OOPS=y
 CONFIG_MTD_CFI=y
@@ -98,32 +93,40 @@
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=16384
-CONFIG_SENSORS_LIS3LV02D=m
 CONFIG_SENSORS_TSL2550=m
-CONFIG_SENSORS_LIS3_I2C=m
 CONFIG_BMP085_I2C=m
+CONFIG_SENSORS_LIS3_I2C=m
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_MD=y
 CONFIG_NETDEVICES=y
-CONFIG_SMSC_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMC91X=y
-CONFIG_SMSC911X=y
 CONFIG_KS8851=y
 CONFIG_KS8851_MLL=y
-CONFIG_LIBERTAS=m
-CONFIG_LIBERTAS_USB=m
-CONFIG_LIBERTAS_SDIO=m
-CONFIG_LIBERTAS_DEBUG=y
+CONFIG_SMC91X=y
+CONFIG_SMSC911X=y
+CONFIG_TI_CPSW=y
+CONFIG_AT803X_PHY=y
+CONFIG_SMSC_PHY=y
 CONFIG_USB_USBNET=y
 CONFIG_USB_NET_SMSC95XX=y
 CONFIG_USB_ALI_M5632=y
 CONFIG_USB_AN2720=y
 CONFIG_USB_EPSON2888=y
 CONFIG_USB_KC2190=y
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_LIBERTAS_DEBUG=y
+CONFIG_WL_TI=y
+CONFIG_WL12XX=m
+CONFIG_WL18XX=m
+CONFIG_WLCORE_SPI=m
+CONFIG_WLCORE_SDIO=m
+CONFIG_MWIFIEX=m
+CONFIG_MWIFIEX_SDIO=m
+CONFIG_MWIFIEX_USB=m
 CONFIG_INPUT_JOYDEV=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
@@ -133,7 +136,6 @@
 CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_TWL4030_PWRBUTTON=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
@@ -143,8 +145,7 @@
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_8250_DETECT_IRQ=y
 CONFIG_SERIAL_8250_RSA=y
-CONFIG_SERIAL_AMBA_PL011=y
-CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_OMAP=y
 CONFIG_SERIAL_OMAP_CONSOLE=y
 CONFIG_HW_RANDOM=y
@@ -158,31 +159,31 @@
 CONFIG_W1=y
 CONFIG_POWER_SUPPLY=y
 CONFIG_SENSORS_LM75=m
-CONFIG_WATCHDOG=y
 CONFIG_THERMAL=y
-CONFIG_THERMAL_HWMON=y
-CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
 CONFIG_THERMAL_GOV_FAIR_SHARE=y
-CONFIG_THERMAL_GOV_STEP_WISE=y
 CONFIG_THERMAL_GOV_USER_SPACE=y
-CONFIG_CPU_THERMAL=y
+CONFIG_TI_SOC_THERMAL=y
+CONFIG_OMAP4_THERMAL=y
+CONFIG_OMAP5_THERMAL=y
+CONFIG_DRA752_THERMAL=y
+CONFIG_WATCHDOG=y
 CONFIG_OMAP_WATCHDOG=y
 CONFIG_TWL4030_WATCHDOG=y
+CONFIG_MFD_PALMAS=y
 CONFIG_MFD_TPS65217=y
 CONFIG_MFD_TPS65910=y
 CONFIG_TWL6040_CORE=y
-CONFIG_REGULATOR_TWL4030=y
+CONFIG_REGULATOR_PALMAS=y
 CONFIG_REGULATOR_TPS65023=y
 CONFIG_REGULATOR_TPS6507X=y
 CONFIG_REGULATOR_TPS65217=y
 CONFIG_REGULATOR_TPS65910=y
+CONFIG_REGULATOR_TWL4030=y
 CONFIG_FB=y
 CONFIG_FIRMWARE_EDID=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
-CONFIG_FB_OMAP_LCD_VGA=y
 CONFIG_OMAP2_DSS=m
-CONFIG_OMAP2_DSS_RFBI=y
 CONFIG_OMAP2_DSS_SDI=y
 CONFIG_OMAP2_DSS_DSI=y
 CONFIG_FB_OMAP2=m
@@ -194,12 +195,8 @@
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_LCD_PLATFORM=y
-CONFIG_DISPLAY_SUPPORT=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
 CONFIG_LOGO=y
 CONFIG_SOUND=m
 CONFIG_SND=m
@@ -216,14 +213,14 @@
 CONFIG_USB=y
 CONFIG_USB_DEBUG=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
 CONFIG_USB_MON=y
 CONFIG_USB_WDM=y
 CONFIG_USB_STORAGE=y
-CONFIG_USB_LIBUSUAL=y
+CONFIG_USB_DWC3=m
 CONFIG_USB_TEST=y
-CONFIG_USB_PHY=y
 CONFIG_NOP_USB_XCEIV=y
+CONFIG_OMAP_USB2=y
+CONFIG_OMAP_USB3=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
@@ -232,7 +229,6 @@
 CONFIG_MMC=y
 CONFIG_MMC_UNSAFE_RESUME=y
 CONFIG_SDIO_UART=y
-CONFIG_MMC_ARMMMCI=y
 CONFIG_MMC_OMAP=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_NEW_LEDS=y
@@ -252,11 +248,8 @@
 CONFIG_DMADEVICES=y
 CONFIG_TI_EDMA=y
 CONFIG_DMA_OMAP=y
-CONFIG_TI_SOC_THERMAL=y
-CONFIG_TI_THERMAL=y
-CONFIG_OMAP4_THERMAL=y
-CONFIG_OMAP5_THERMAL=y
-CONFIG_DRA752_THERMAL=y
+CONFIG_EXTCON=y
+CONFIG_EXTCON_PALMAS=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
@@ -275,23 +268,18 @@
 CONFIG_UBIFS_FS=y
 CONFIG_CRAMFS=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_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
 CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
 CONFIG_PROVE_LOCKING=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SECURITY=y
 CONFIG_CRYPTO_MICHAEL_MIC=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
@@ -300,9 +288,6 @@
 CONFIG_CRC_ITU_T=y
 CONFIG_CRC7=y
 CONFIG_LIBCRC32C=y
-CONFIG_SOC_OMAP5=y
-CONFIG_TI_DAVINCI_MDIO=y
-CONFIG_TI_DAVINCI_CPDMA=y
-CONFIG_TI_CPSW=y
-CONFIG_AT803X_PHY=y
-CONFIG_SOC_DRA7XX=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
diff --git a/arch/arm/configs/shark_defconfig b/arch/arm/configs/shark_defconfig
deleted file mode 100644
index e319b2c..0000000
--- a/arch/arm/configs/shark_defconfig
+++ /dev/null
@@ -1,80 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_SHARK=y
-CONFIG_LEDS=y
-CONFIG_LEDS_TIMER=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_STANDALONE is not set
-# CONFIG_FIRMWARE_IN_KERNEL is not set
-CONFIG_PARPORT=m
-CONFIG_PARPORT_PC=m
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECD=m
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
-CONFIG_CHR_DEV_ST=m
-CONFIG_BLK_DEV_SR=m
-CONFIG_CHR_DEV_SG=m
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_NET_PCI=y
-CONFIG_CS89x0=y
-# CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_PRINTER=m
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_FB_CYBER2000=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-CONFIG_SOUND=m
-CONFIG_SOUND_PRIME=m
-CONFIG_SOUND_OSS=m
-CONFIG_SOUND_SB=m
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_CMOS=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFSD=m
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_ISO8859_1=m
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig
new file mode 100644
index 0000000..d57a85b
--- /dev/null
+++ b/arch/arm/configs/sunxi_defconfig
@@ -0,0 +1,61 @@
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_SMP=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_HIGHPTE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_NETDEVICES=y
+CONFIG_SUN4I_EMAC=y
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_WLAN is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=8
+CONFIG_SERIAL_8250_RUNTIME_UARTS=8
+CONFIG_SERIAL_8250_DW=y
+CONFIG_I2C=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MV64XXX=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SUNXI_WATCHDOG=y
+# CONFIG_USB_SUPPORT is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_COMMON_CLK_DEBUG=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_NLS=y
diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index ea042e8..4934295 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -27,6 +27,7 @@
 CONFIG_ARCH_TEGRA_2x_SOC=y
 CONFIG_ARCH_TEGRA_3x_SOC=y
 CONFIG_ARCH_TEGRA_114_SOC=y
+CONFIG_ARCH_TEGRA_124_SOC=y
 CONFIG_TEGRA_EMC_SCALING_ENABLE=y
 CONFIG_PCI=y
 CONFIG_PCI_MSI=y
@@ -41,9 +42,11 @@
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_KEXEC=y
 CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_CPU_IDLE=y
 CONFIG_VFP=y
+CONFIG_NEON=y
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -129,6 +132,7 @@
 CONFIG_SPI_TEGRA114=y
 CONFIG_SPI_TEGRA20_SFLASH=y
 CONFIG_SPI_TEGRA20_SLINK=y
+CONFIG_PINCTRL_PALMAS=y
 CONFIG_GPIO_PCA953X_IRQ=y
 CONFIG_GPIO_PALMAS=y
 CONFIG_GPIO_TPS6586X=y
@@ -223,6 +227,7 @@
 CONFIG_SERIO_NVEC_PS2=y
 CONFIG_NVEC_POWER=y
 CONFIG_NVEC_PAZ00=y
+CONFIG_COMMON_CLK_DEBUG=y
 CONFIG_TEGRA_IOMMU_GART=y
 CONFIG_TEGRA_IOMMU_SMMU=y
 CONFIG_MEMORY=y
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig
index a0025dc..ac632cc 100644
--- a/arch/arm/configs/u8500_defconfig
+++ b/arch/arm/configs/u8500_defconfig
@@ -1,4 +1,3 @@
-CONFIG_HIGHMEM=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 CONFIG_NO_HZ=y
@@ -16,6 +15,9 @@
 CONFIG_NR_CPUS=2
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
 CONFIG_CMDLINE="root=/dev/ram0 console=ttyAMA2,115200n8"
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
@@ -68,8 +70,8 @@
 CONFIG_WATCHDOG=y
 CONFIG_MFD_STMPE=y
 CONFIG_MFD_TC3589X=y
-CONFIG_REGULATOR_GPIO=y
 CONFIG_REGULATOR_AB8500=y
+CONFIG_REGULATOR_GPIO=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
@@ -78,10 +80,8 @@
 CONFIG_USB=y
 CONFIG_USB_MUSB_HDRC=y
 CONFIG_USB_MUSB_UX500=y
-CONFIG_USB_PHY=y
 CONFIG_AB8500_USB=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_MUSB_HDRC=y
 CONFIG_USB_ETH=m
 CONFIG_MMC=y
 CONFIG_MMC_UNSAFE_RESUME=y
@@ -116,12 +116,12 @@
 CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
-CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
-CONFIG_DEBUG_INFO=y
 # CONFIG_FTRACE is not set
 CONFIG_DEBUG_USER=y
 CONFIG_CRYPTO_DEV_UX500=y
diff --git a/arch/arm/configs/vexpress_defconfig b/arch/arm/configs/vexpress_defconfig
index f2de51f..f489fda 100644
--- a/arch/arm/configs/vexpress_defconfig
+++ b/arch/arm/configs/vexpress_defconfig
@@ -1,4 +1,3 @@
-CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
@@ -8,11 +7,9 @@
 CONFIG_CPUSETS=y
 # CONFIG_UTS_NS is not set
 # CONFIG_IPC_NS is not set
-# CONFIG_USER_NS is not set
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
 CONFIG_MODULES=y
@@ -23,14 +20,22 @@
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARCH_VEXPRESS=y
 CONFIG_ARCH_VEXPRESS_CA9X4=y
+CONFIG_ARCH_VEXPRESS_DCSCB=y
+CONFIG_ARCH_VEXPRESS_TC2_PM=y
 # CONFIG_SWP_EMULATE is not set
 CONFIG_SMP=y
+CONFIG_HAVE_ARM_ARCH_TIMER=y
+CONFIG_MCPM=y
 CONFIG_VMSPLIT_2G=y
-CONFIG_HOTPLUG_CPU=y
+CONFIG_NR_CPUS=8
+CONFIG_ARM_PSCI=y
 CONFIG_AEABI=y
+CONFIG_CMA=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="root=/dev/nfs nfsroot=10.1.69.3:/work/nfsroot ip=dhcp console=ttyAMA0 mem=128M"
+CONFIG_CMDLINE="console=ttyAMA0"
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y
 CONFIG_VFP=y
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
@@ -44,37 +49,46 @@
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
 # CONFIG_WIRELESS is not set
+CONFIG_NET_9P=y
+CONFIG_NET_9P_VIRTIO=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_ARM_INTEGRATOR=y
-CONFIG_MISC_DEVICES=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_PLATRAM=y
+CONFIG_MTD_UBI=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_VIRTIO_BLK=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
-# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_SCSI_VIRTIO=y
 CONFIG_ATA=y
 # CONFIG_SATA_PMP is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
+CONFIG_VIRTIO_NET=y
+CONFIG_SMC91X=y
 CONFIG_SMSC911X=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
 # CONFIG_WLAN is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIO_AMBAKMI=y
+CONFIG_LEGACY_PTY_COUNT=16
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-CONFIG_LEGACY_PTY_COUNT=16
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
+CONFIG_VIRTIO_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_VIRTIO=y
+CONFIG_I2C=y
+CONFIG_I2C_VERSATILE=y
+CONFIG_SENSORS_VEXPRESS=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_VEXPRESS=y
 CONFIG_FB=y
 CONFIG_FB_ARMCLCD=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
@@ -103,38 +117,45 @@
 CONFIG_HID_ZEROPLUS=y
 CONFIG_USB=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-# CONFIG_USB_DEVICE_CLASS is not set
 CONFIG_USB_MON=y
 CONFIG_USB_ISP1760_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_ARMMMCI=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_CPU=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_PL031=y
+CONFIG_VIRTIO_BALLOON=y
+CONFIG_VIRTIO_MMIO=y
+CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
+CONFIG_UBIFS_FS=y
 CONFIG_CRAMFS=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_LZO=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
+CONFIG_9P_FS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
-CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 # CONFIG_SCHED_DEBUG is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_LL=y
-CONFIG_EARLY_PRINTK=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index d3db398..1a7024b 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -31,5 +31,5 @@
 generic-y += termios.h
 generic-y += timex.h
 generic-y += trace_clock.h
-generic-y += types.h
 generic-y += unaligned.h
+generic-y += preempt.h
diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
index 5665134..0704e0c 100644
--- a/arch/arm/include/asm/arch_timer.h
+++ b/arch/arm/include/asm/arch_timer.h
@@ -87,17 +87,43 @@
 	return cval;
 }
 
-static inline void arch_counter_set_user_access(void)
+static inline u32 arch_timer_get_cntkctl(void)
 {
 	u32 cntkctl;
-
 	asm volatile("mrc p15, 0, %0, c14, c1, 0" : "=r" (cntkctl));
+	return cntkctl;
+}
 
-	/* disable user access to everything */
-	cntkctl &= ~((3 << 8) | (7 << 0));
-
+static inline void arch_timer_set_cntkctl(u32 cntkctl)
+{
 	asm volatile("mcr p15, 0, %0, c14, c1, 0" : : "r" (cntkctl));
 }
+
+static inline void arch_counter_set_user_access(void)
+{
+	u32 cntkctl = arch_timer_get_cntkctl();
+
+	/* Disable user access to both physical/virtual counters/timers */
+	/* Also disable virtual event stream */
+	cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN
+			| ARCH_TIMER_USR_VT_ACCESS_EN
+			| ARCH_TIMER_VIRT_EVT_EN
+			| ARCH_TIMER_USR_VCT_ACCESS_EN
+			| ARCH_TIMER_USR_PCT_ACCESS_EN);
+	arch_timer_set_cntkctl(cntkctl);
+}
+
+static inline void arch_timer_evtstrm_enable(int divider)
+{
+	u32 cntkctl = arch_timer_get_cntkctl();
+	cntkctl &= ~ARCH_TIMER_EVT_TRIGGER_MASK;
+	/* Set the divider and enable virtual event stream */
+	cntkctl |= (divider << ARCH_TIMER_EVT_TRIGGER_SHIFT)
+			| ARCH_TIMER_VIRT_EVT_EN;
+	arch_timer_set_cntkctl(cntkctl);
+	elf_hwcap |= HWCAP_EVTSTRM;
+}
+
 #endif
 
 #endif
diff --git a/arch/arm/include/asm/hardware/iop3xx-gpio.h b/arch/arm/include/asm/hardware/iop3xx-gpio.h
deleted file mode 100644
index 9eda7dc..0000000
--- a/arch/arm/include/asm/hardware/iop3xx-gpio.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * arch/arm/include/asm/hardware/iop3xx-gpio.h
- *
- * IOP3xx GPIO wrappers
- *
- * Copyright (c) 2008 Arnaud Patard <arnaud.patard@rtp-net.org>
- * Based on IXP4XX gpio.h file
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#ifndef __ASM_ARM_HARDWARE_IOP3XX_GPIO_H
-#define __ASM_ARM_HARDWARE_IOP3XX_GPIO_H
-
-#include <mach/hardware.h>
-#include <asm-generic/gpio.h>
-
-#define __ARM_GPIOLIB_COMPLEX
-
-#define IOP3XX_N_GPIOS	8
-
-static inline int gpio_get_value(unsigned gpio)
-{
-	if (gpio > IOP3XX_N_GPIOS)
-		return __gpio_get_value(gpio);
-
-	return gpio_line_get(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-	if (gpio > IOP3XX_N_GPIOS) {
-		__gpio_set_value(gpio, value);
-		return;
-	}
-	gpio_line_set(gpio, value);
-}
-
-static inline int gpio_cansleep(unsigned gpio)
-{
-	if (gpio < IOP3XX_N_GPIOS)
-		return 0;
-	else
-		return __gpio_cansleep(gpio);
-}
-
-/*
- * The GPIOs are not generating any interrupt
- * Note : manuals are not clear about this
- */
-static inline int gpio_to_irq(int gpio)
-{
-	return -EINVAL;
-}
-
-static inline int irq_to_gpio(int gpio)
-{
-	return -EINVAL;
-}
-
-#endif
-
diff --git a/arch/arm/include/asm/hardware/iop3xx.h b/arch/arm/include/asm/hardware/iop3xx.h
index 423744b..2594a95 100644
--- a/arch/arm/include/asm/hardware/iop3xx.h
+++ b/arch/arm/include/asm/hardware/iop3xx.h
@@ -18,16 +18,9 @@
 /*
  * IOP3XX GPIO handling
  */
-#define GPIO_IN			0
-#define GPIO_OUT		1
-#define GPIO_LOW		0
-#define GPIO_HIGH		1
 #define IOP3XX_GPIO_LINE(x)	(x)
 
 #ifndef __ASSEMBLY__
-extern void gpio_line_config(int line, int direction);
-extern int  gpio_line_get(int line);
-extern void gpio_line_set(int line, int value);
 extern int init_atu;
 extern int iop3xx_get_init_atu(void);
 #endif
@@ -168,11 +161,6 @@
 /* PERCR0 DOESN'T EXIST - index from 1! */
 #define IOP3XX_PERCR0		(volatile u32 *)IOP3XX_REG_ADDR(0x0710)
 
-/* General Purpose I/O  */
-#define IOP3XX_GPOE		(volatile u32 *)IOP3XX_GPIO_REG(0x0000)
-#define IOP3XX_GPID		(volatile u32 *)IOP3XX_GPIO_REG(0x0004)
-#define IOP3XX_GPOD		(volatile u32 *)IOP3XX_GPIO_REG(0x0008)
-
 /* Timers  */
 #define IOP3XX_TU_TMR0		(volatile u32 *)IOP3XX_TIMER_REG(0x0000)
 #define IOP3XX_TU_TMR1		(volatile u32 *)IOP3XX_TIMER_REG(0x0004)
diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h
index bfc198c..863c892 100644
--- a/arch/arm/include/asm/jump_label.h
+++ b/arch/arm/include/asm/jump_label.h
@@ -16,7 +16,7 @@
 
 static __always_inline bool arch_static_branch(struct static_key *key)
 {
-	asm goto("1:\n\t"
+	asm_volatile_goto("1:\n\t"
 		 JUMP_LABEL_NOP "\n\t"
 		 ".pushsection __jump_table,  \"aw\"\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h
index 454d642..7fc4278 100644
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -106,8 +106,4 @@
 extern void dc21285_preinit(void);
 extern void dc21285_postinit(void);
 
-extern struct pci_ops via82c505_ops;
-extern int via82c505_setup(int nr, struct pci_sys_data *);
-extern void via82c505_init(void *sysdata);
-
 #endif /* __ASM_MACH_PCI_H */
diff --git a/arch/arm/include/asm/mcpm.h b/arch/arm/include/asm/mcpm.h
index 0f7b762..fc82a88 100644
--- a/arch/arm/include/asm/mcpm.h
+++ b/arch/arm/include/asm/mcpm.h
@@ -76,8 +76,11 @@
  *
  * This must be called with interrupts disabled.
  *
- * This does not return.  Re-entry in the kernel is expected via
- * mcpm_entry_point.
+ * On success this does not return.  Re-entry in the kernel is expected
+ * via mcpm_entry_point.
+ *
+ * This will return if mcpm_platform_register() has not been called
+ * previously in which case the caller should take appropriate action.
  */
 void mcpm_cpu_power_down(void);
 
@@ -98,8 +101,11 @@
  *
  * This must be called with interrupts disabled.
  *
- * This does not return.  Re-entry in the kernel is expected via
- * mcpm_entry_point.
+ * On success this does not return.  Re-entry in the kernel is expected
+ * via mcpm_entry_point.
+ *
+ * This will return if mcpm_platform_register() has not been called
+ * previously in which case the caller should take appropriate action.
  */
 void mcpm_cpu_suspend(u64 expected_residency);
 
diff --git a/arch/arm/include/asm/prom.h b/arch/arm/include/asm/prom.h
index 4a2985e..b681575 100644
--- a/arch/arm/include/asm/prom.h
+++ b/arch/arm/include/asm/prom.h
@@ -11,8 +11,6 @@
 #ifndef __ASMARM_PROM_H
 #define __ASMARM_PROM_H
 
-#define HAVE_ARCH_DEVTREE_FIXUPS
-
 #ifdef CONFIG_OF
 
 extern const struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
diff --git a/arch/arm/include/asm/sched_clock.h b/arch/arm/include/asm/sched_clock.h
deleted file mode 100644
index 2389b71..0000000
--- a/arch/arm/include/asm/sched_clock.h
+++ /dev/null
@@ -1,4 +0,0 @@
-/* You shouldn't include this file. Use linux/sched_clock.h instead.
- * Temporary file until all asm/sched_clock.h users are gone
- */
-#include <linux/sched_clock.h>
diff --git a/arch/arm/include/asm/syscall.h b/arch/arm/include/asm/syscall.h
index f1d96d4..73ddd72 100644
--- a/arch/arm/include/asm/syscall.h
+++ b/arch/arm/include/asm/syscall.h
@@ -57,6 +57,9 @@
 					 unsigned int i, unsigned int n,
 					 unsigned long *args)
 {
+	if (n == 0)
+		return;
+
 	if (i + n > SYSCALL_MAX_ARGS) {
 		unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i;
 		unsigned int n_bad = n + i - SYSCALL_MAX_ARGS;
@@ -81,6 +84,9 @@
 					 unsigned int i, unsigned int n,
 					 const unsigned long *args)
 {
+	if (n == 0)
+		return;
+
 	if (i + n > SYSCALL_MAX_ARGS) {
 		pr_warning("%s called with max args %d, handling only %d\n",
 			   __func__, i + n, SYSCALL_MAX_ARGS);
diff --git a/arch/arm/include/debug/vf.S b/arch/arm/include/debug/vf.S
new file mode 100644
index 0000000..ba12cc4
--- /dev/null
+++ b/arch/arm/include/debug/vf.S
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+	.macro	addruart, rp, rv, tmp
+	ldr	\rp, =0x40028000	@ physical
+	ldr	\rv, =0xfe028000	@ virtual
+	.endm
+
+	.macro	senduart, rd, rx
+	strb	\rd, [\rx, #0x7]	@ Data Register
+	.endm
+
+	.macro	busyuart, rd, rx
+1001:	ldrb	\rd, [\rx, #0x4]	@ Status Register 1
+	tst	\rd, #1 << 6		@ TC
+	beq	1001b			@ wait until transmit done
+	.endm
+
+	.macro	waituart,rd,rx
+	.endm
diff --git a/arch/arm/include/uapi/asm/hwcap.h b/arch/arm/include/uapi/asm/hwcap.h
index 6d34d08..7dcc10d 100644
--- a/arch/arm/include/uapi/asm/hwcap.h
+++ b/arch/arm/include/uapi/asm/hwcap.h
@@ -26,5 +26,6 @@
 #define HWCAP_VFPD32	(1 << 19)	/* set if VFP has 32 regs (not 16) */
 #define HWCAP_IDIV	(HWCAP_IDIVA | HWCAP_IDIVT)
 #define HWCAP_LPAE	(1 << 20)
+#define HWCAP_EVTSTRM	(1 << 21)
 
 #endif /* _UAPI__ASMARM_HWCAP_H */
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index 221f07b..1791f12 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/sched_clock.h>
 
 #include <asm/delay.h>
 
@@ -22,13 +21,6 @@
 	return arch_timer_read_counter();
 }
 
-static u32 sched_clock_mult __read_mostly;
-
-static unsigned long long notrace arch_timer_sched_clock(void)
-{
-	return arch_timer_read_counter() * sched_clock_mult;
-}
-
 static struct delay_timer arch_delay_timer;
 
 static void __init arch_timer_delay_timer_register(void)
@@ -48,11 +40,5 @@
 
 	arch_timer_delay_timer_register();
 
-	/* Cache the sched_clock multiplier to save a divide in the hot path. */
-	sched_clock_mult = NSEC_PER_SEC / arch_timer_rate;
-	sched_clock_func = arch_timer_sched_clock;
-	pr_info("sched_clock: ARM arch timer >56 bits at %ukHz, resolution %uns\n",
-		arch_timer_rate / 1000, sched_clock_mult);
-
 	return 0;
 }
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
index f35906b..739c3df 100644
--- a/arch/arm/kernel/devtree.c
+++ b/arch/arm/kernel/devtree.c
@@ -174,6 +174,19 @@
 	return (phys_id & MPIDR_HWID_BITMASK) == cpu_logical_map(cpu);
 }
 
+static const void * __init arch_get_next_mach(const char *const **match)
+{
+	static const struct machine_desc *mdesc = __arch_info_begin;
+	const struct machine_desc *m = mdesc;
+
+	if (m >= __arch_info_end)
+		return NULL;
+
+	mdesc++;
+	*match = m->dt_compat;
+	return m;
+}
+
 /**
  * setup_machine_fdt - Machine setup when an dtb was passed to the kernel
  * @dt_phys: physical address of dt blob
@@ -183,11 +196,7 @@
  */
 const struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
 {
-	struct boot_param_header *devtree;
 	const struct machine_desc *mdesc, *mdesc_best = NULL;
-	unsigned int score, mdesc_score = ~1;
-	unsigned long dt_root;
-	const char *model;
 
 #ifdef CONFIG_ARCH_MULTIPLATFORM
 	DT_MACHINE_START(GENERIC_DT, "Generic DT based system")
@@ -196,32 +205,20 @@
 	mdesc_best = &__mach_desc_GENERIC_DT;
 #endif
 
-	if (!dt_phys)
+	if (!dt_phys || !early_init_dt_scan(phys_to_virt(dt_phys)))
 		return NULL;
 
-	devtree = phys_to_virt(dt_phys);
+	mdesc = of_flat_dt_match_machine(mdesc_best, arch_get_next_mach);
 
-	/* check device tree validity */
-	if (be32_to_cpu(devtree->magic) != OF_DT_HEADER)
-		return NULL;
-
-	/* Search the mdescs for the 'best' compatible value match */
-	initial_boot_params = devtree;
-	dt_root = of_get_flat_dt_root();
-	for_each_machine_desc(mdesc) {
-		score = of_flat_dt_match(dt_root, mdesc->dt_compat);
-		if (score > 0 && score < mdesc_score) {
-			mdesc_best = mdesc;
-			mdesc_score = score;
-		}
-	}
-	if (!mdesc_best) {
+	if (!mdesc) {
 		const char *prop;
 		long size;
+		unsigned long dt_root;
 
 		early_print("\nError: unrecognized/unsupported "
 			    "device tree compatible list:\n[ ");
 
+		dt_root = of_get_flat_dt_root();
 		prop = of_get_flat_dt_prop(dt_root, "compatible", &size);
 		while (size > 0) {
 			early_print("'%s' ", prop);
@@ -233,22 +230,8 @@
 		dump_machine_table(); /* does not return */
 	}
 
-	model = of_get_flat_dt_prop(dt_root, "model", NULL);
-	if (!model)
-		model = of_get_flat_dt_prop(dt_root, "compatible", NULL);
-	if (!model)
-		model = "<unknown>";
-	pr_info("Machine: %s, model: %s\n", mdesc_best->name, model);
-
-	/* Retrieve various information from the /chosen node */
-	of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
-	/* Initialize {size,address}-cells info */
-	of_scan_flat_dt(early_init_dt_scan_root, NULL);
-	/* Setup memory, calling early_init_dt_add_memory_arch */
-	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
-
 	/* Change machine number to match the mdesc we're using */
-	__machine_arch_type = mdesc_best->nr;
+	__machine_arch_type = mdesc->nr;
 
-	return mdesc_best;
+	return mdesc;
 }
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 2c7cc1e..476de57 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -487,7 +487,26 @@
 	mrc	p15, 0, r0, c0, c0, 5	@ read MPIDR
 	and	r0, r0, #0xc0000000	@ multiprocessing extensions and
 	teq	r0, #0x80000000		@ not part of a uniprocessor system?
-	moveq	pc, lr			@ yes, assume SMP
+	bne    __fixup_smp_on_up	@ no, assume UP
+
+	@ Core indicates it is SMP. Check for Aegis SOC where a single
+	@ Cortex-A9 CPU is present but SMP operations fault.
+	mov	r4, #0x41000000
+	orr	r4, r4, #0x0000c000
+	orr	r4, r4, #0x00000090
+	teq	r3, r4			@ Check for ARM Cortex-A9
+	movne	pc, lr			@ Not ARM Cortex-A9,
+
+	@ If a future SoC *does* use 0x0 as the PERIPH_BASE, then the
+	@ below address check will need to be #ifdef'd or equivalent
+	@ for the Aegis platform.
+	mrc	p15, 4, r0, c15, c0	@ get SCU base address
+	teq	r0, #0x0		@ '0' on actual UP A9 hardware
+	beq	__fixup_smp_on_up	@ So its an A9 UP
+	ldr	r0, [r0, #4]		@ read SCU Config
+	and	r0, r0, #0x3		@ number of CPUs
+	teq	r0, #0x0		@ is 1?
+	movne	pc, lr
 
 __fixup_smp_on_up:
 	adr	r0, 1f
diff --git a/arch/arm/kernel/psci_smp.c b/arch/arm/kernel/psci_smp.c
index 70ded3f..570a48c 100644
--- a/arch/arm/kernel/psci_smp.c
+++ b/arch/arm/kernel/psci_smp.c
@@ -14,7 +14,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/irqchip/arm-gic.h>
 #include <linux/smp.h>
 #include <linux/of.h>
 
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 0e1e2b3..5d65438 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -975,6 +975,7 @@
 	"idivt",
 	"vfpd32",
 	"lpae",
+	"evtstrm",
 	NULL
 };
 
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 98aee32..829a96d 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -11,25 +11,26 @@
  *  This file contains the ARM-specific time handling details:
  *  reading the RTC at bootup, etc...
  */
-#include <linux/export.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/timex.h>
-#include <linux/errno.h>
-#include <linux/profile.h>
-#include <linux/timer.h>
+#include <linux/clk-provider.h>
 #include <linux/clocksource.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/profile.h>
+#include <linux/sched.h>
 #include <linux/sched_clock.h>
+#include <linux/smp.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/timer.h>
 
-#include <asm/thread_info.h>
-#include <asm/stacktrace.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
+#include <asm/stacktrace.h>
+#include <asm/thread_info.h>
 
 #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \
     defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE)
@@ -116,8 +117,12 @@
 
 void __init time_init(void)
 {
-	if (machine_desc->init_time)
+	if (machine_desc->init_time) {
 		machine_desc->init_time();
-	else
+	} else {
+#ifdef CONFIG_COMMON_CLK
+		of_clk_init(NULL);
+#endif
 		clocksource_of_init();
+	}
 }
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index bd454b0..47d7338 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -41,7 +41,6 @@
 endif
 
 lib-$(CONFIG_ARCH_RPC)		+= ecard.o io-acorn.o floppydma.o
-lib-$(CONFIG_ARCH_SHARK)	+= io-shark.o
 
 $(obj)/csumpartialcopy.o:	$(obj)/csumpartialcopygeneric.S
 $(obj)/csumpartialcopyuser.o:	$(obj)/csumpartialcopygeneric.S
diff --git a/arch/arm/lib/io-shark.c b/arch/arm/lib/io-shark.c
deleted file mode 100644
index 8242539..0000000
--- a/arch/arm/lib/io-shark.c
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- *  linux/arch/arm/lib/io-shark.c
- *
- *  by Alexander Schulz
- *
- * derived from:
- * linux/arch/arm/lib/io-ebsa.S
- * Copyright (C) 1995, 1996 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c
index c7d670d..2d895a2 100644
--- a/arch/arm/mach-at91/at91sam9n12.c
+++ b/arch/arm/mach-at91/at91sam9n12.c
@@ -169,6 +169,7 @@
 	CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb_clk),
 	CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb_clk),
 	CLKDEV_CON_DEV_ID("mci_clk", "f0008000.mmc", &mmc_clk),
+	CLKDEV_CON_DEV_ID(NULL, "f0010000.ssc", &ssc_clk),
 	CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma_clk),
 	CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
 	CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
index ade948b..112e867 100644
--- a/arch/arm/mach-at91/board-cam60.c
+++ b/arch/arm/mach-at91/board-cam60.c
@@ -112,7 +112,7 @@
 /*
  * MACB Ethernet device
  */
-static struct __initdata macb_platform_data cam60_macb_data = {
+static struct macb_platform_data cam60_macb_data __initdata = {
 	.phy_irq_pin	= AT91_PIN_PB5,
 	.is_rmii	= 0,
 };
diff --git a/arch/arm/mach-at91/board-dt-rm9200.c b/arch/arm/mach-at91/board-dt-rm9200.c
index 3fcb662..3a185fa 100644
--- a/arch/arm/mach-at91/board-dt-rm9200.c
+++ b/arch/arm/mach-at91/board-dt-rm9200.c
@@ -14,7 +14,6 @@
 #include <linux/gpio.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
-#include <linux/of_platform.h>
 
 #include <asm/setup.h>
 #include <asm/irq.h>
@@ -36,11 +35,6 @@
 	of_irq_init(irq_of_match);
 }
 
-static void __init at91rm9200_dt_device_init(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
 static const char *at91rm9200_dt_board_compat[] __initdata = {
 	"atmel,at91rm9200",
 	NULL
@@ -52,6 +46,5 @@
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= at91rm9200_dt_initialize,
 	.init_irq	= at91rm9200_dt_init_irq,
-	.init_machine	= at91rm9200_dt_device_init,
 	.dt_compat	= at91rm9200_dt_board_compat,
 MACHINE_END
diff --git a/arch/arm/mach-at91/board-dt-sam9.c b/arch/arm/mach-at91/board-dt-sam9.c
index 8db3013..3dab868 100644
--- a/arch/arm/mach-at91/board-dt-sam9.c
+++ b/arch/arm/mach-at91/board-dt-sam9.c
@@ -13,7 +13,6 @@
 #include <linux/gpio.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
-#include <linux/of_platform.h>
 
 #include <asm/setup.h>
 #include <asm/irq.h>
@@ -37,11 +36,6 @@
 	of_irq_init(irq_of_match);
 }
 
-static void __init at91_dt_device_init(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
 static const char *at91_dt_board_compat[] __initdata = {
 	"atmel,at91sam9",
 	NULL
@@ -54,6 +48,5 @@
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= at91_dt_initialize,
 	.init_irq	= at91_dt_init_irq,
-	.init_machine	= at91_dt_device_init,
 	.dt_compat	= at91_dt_board_compat,
 MACHINE_END
diff --git a/arch/arm/mach-at91/include/mach/at91_adc.h b/arch/arm/mach-at91/include/mach/at91_adc.h
index 048a57f..c287307 100644
--- a/arch/arm/mach-at91/include/mach/at91_adc.h
+++ b/arch/arm/mach-at91/include/mach/at91_adc.h
@@ -60,14 +60,48 @@
 #define AT91_ADC_IER		0x24		/* Interrupt Enable Register */
 #define AT91_ADC_IDR		0x28		/* Interrupt Disable Register */
 #define AT91_ADC_IMR		0x2C		/* Interrupt Mask Register */
+#define		AT91_ADC_IER_PEN	(1 << 29)
+#define		AT91_ADC_IER_NOPEN	(1 << 30)
+#define		AT91_ADC_IER_XRDY	(1 << 20)
+#define		AT91_ADC_IER_YRDY	(1 << 21)
+#define		AT91_ADC_IER_PRDY	(1 << 22)
+#define		AT91_ADC_ISR_PENS	(1 << 31)
 
 #define AT91_ADC_CHR(n)		(0x30 + ((n) * 4))	/* Channel Data Register N */
 #define		AT91_ADC_DATA		(0x3ff)
 
 #define AT91_ADC_CDR0_9X5	(0x50)			/* Channel Data Register 0 for 9X5 */
 
+#define AT91_ADC_ACR		0x94	/* Analog Control Register */
+#define		AT91_ADC_ACR_PENDETSENS	(0x3 << 0)	/* pull-up resistor */
+
+#define AT91_ADC_TSMR		0xB0
+#define		AT91_ADC_TSMR_TSMODE	(3 << 0)	/* Touch Screen Mode */
+#define			AT91_ADC_TSMR_TSMODE_NONE		(0 << 0)
+#define			AT91_ADC_TSMR_TSMODE_4WIRE_NO_PRESS	(1 << 0)
+#define			AT91_ADC_TSMR_TSMODE_4WIRE_PRESS	(2 << 0)
+#define			AT91_ADC_TSMR_TSMODE_5WIRE		(3 << 0)
+#define		AT91_ADC_TSMR_TSAV	(3 << 4)	/* Averages samples */
+#define			AT91_ADC_TSMR_TSAV_(x)		((x) << 4)
+#define		AT91_ADC_TSMR_SCTIM	(0x0f << 16)	/* Switch closure time */
+#define		AT91_ADC_TSMR_PENDBC	(0x0f << 28)	/* Pen Debounce time */
+#define			AT91_ADC_TSMR_PENDBC_(x)	((x) << 28)
+#define		AT91_ADC_TSMR_NOTSDMA	(1 << 22)	/* No Touchscreen DMA */
+#define		AT91_ADC_TSMR_PENDET_DIS	(0 << 24)	/* Pen contact detection disable */
+#define		AT91_ADC_TSMR_PENDET_ENA	(1 << 24)	/* Pen contact detection enable */
+
+#define AT91_ADC_TSXPOSR	0xB4
+#define AT91_ADC_TSYPOSR	0xB8
+#define AT91_ADC_TSPRESSR	0xBC
+
 #define AT91_ADC_TRGR_9260	AT91_ADC_MR
 #define AT91_ADC_TRGR_9G45	0x08
 #define AT91_ADC_TRGR_9X5	0xC0
 
+/* Trigger Register bit field */
+#define		AT91_ADC_TRGR_TRGPER	(0xffff << 16)
+#define			AT91_ADC_TRGR_TRGPER_(x)	((x) << 16)
+#define		AT91_ADC_TRGR_TRGMOD	(0x7 << 0)
+#define			AT91_ADC_TRGR_MOD_PERIOD_TRIG	(5 << 0)
+
 #endif
diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig
index 69d67f7..9fe6d88 100644
--- a/arch/arm/mach-bcm/Kconfig
+++ b/arch/arm/mach-bcm/Kconfig
@@ -1,5 +1,16 @@
 config ARCH_BCM
-	bool "Broadcom SoC" if ARCH_MULTI_V7
+	bool "Broadcom SoC Support"
+	depends on ARCH_MULTIPLATFORM
+	help
+	  This enables support for Broadcom ARM based SoC
+          chips
+
+if ARCH_BCM
+
+menu "Broadcom SoC Selection"
+
+config ARCH_BCM_MOBILE
+	bool "Broadcom Mobile SoC" if ARCH_MULTI_V7
 	depends on MMU
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_ERRATA_754322
@@ -9,12 +20,17 @@
 	select CLKSRC_OF
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_TIME
-	select GPIO_BCM
+	select GPIO_BCM_KONA
 	select SPARSE_IRQ
 	select TICK_ONESHOT
 	select CACHE_L2X0
+	select HAVE_ARM_ARCH_TIMER
 	help
-	  This enables support for system based on Broadcom SoCs.
+	  This enables support for systems based on Broadcom mobile SoCs.
 	  It currently supports the 'BCM281XX' family, which includes
 	  BCM11130, BCM11140, BCM11351, BCM28145 and
 	  BCM28155 variants.
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile
index e3d0303..c2ccd5a 100644
--- a/arch/arm/mach-bcm/Makefile
+++ b/arch/arm/mach-bcm/Makefile
@@ -10,6 +10,6 @@
 # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 
-obj-$(CONFIG_ARCH_BCM)		:= board_bcm281xx.o bcm_kona_smc.o bcm_kona_smc_asm.o kona.o
+obj-$(CONFIG_ARCH_BCM_MOBILE)	:= board_bcm281xx.o bcm_kona_smc.o bcm_kona_smc_asm.o kona.o
 plus_sec := $(call as-instr,.arch_extension sec,+sec)
 AFLAGS_bcm_kona_smc_asm.o	:=-Wa,-march=armv7-a$(plus_sec)
diff --git a/arch/arm/mach-bcm/board_bcm281xx.c b/arch/arm/mach-bcm/board_bcm281xx.c
index 8d9f931..cb3dc36 100644
--- a/arch/arm/mach-bcm/board_bcm281xx.c
+++ b/arch/arm/mach-bcm/board_bcm281xx.c
@@ -67,8 +67,7 @@
 
 static const char * const bcm11351_dt_compat[] = { "brcm,bcm11351", NULL, };
 
-DT_MACHINE_START(BCM11351_DT, "Broadcom Application Processor")
-	.init_time = clocksource_of_init,
+DT_MACHINE_START(BCM11351_DT, "BCM281xx Broadcom Application Processor")
 	.init_machine = board_init,
 	.restart = bcm_kona_restart,
 	.dt_compat = bcm11351_dt_compat,
diff --git a/arch/arm/mach-bcm2835/bcm2835.c b/arch/arm/mach-bcm2835/bcm2835.c
index 40686d7..70f2f39 100644
--- a/arch/arm/mach-bcm2835/bcm2835.c
+++ b/arch/arm/mach-bcm2835/bcm2835.c
@@ -14,11 +14,10 @@
 
 #include <linux/delay.h>
 #include <linux/init.h>
-#include <linux/irqchip/bcm2835.h>
+#include <linux/irqchip.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/clk/bcm2835.h>
-#include <linux/clocksource.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -131,10 +130,8 @@
 
 DT_MACHINE_START(BCM2835, "BCM2835")
 	.map_io = bcm2835_map_io,
-	.init_irq = bcm2835_init_irq,
-	.handle_irq = bcm2835_handle_irq,
+	.init_irq = irqchip_init,
 	.init_machine = bcm2835_init,
-	.init_time = clocksource_of_init,
 	.restart = bcm2835_restart,
 	.dt_compat = bcm2835_compat
 MACHINE_END
diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c
index 4ca2f3c..134641d 100644
--- a/arch/arm/mach-clps711x/common.c
+++ b/arch/arm/mach-clps711x/common.c
@@ -29,12 +29,12 @@
 #include <linux/clockchips.h>
 #include <linux/clocksource.h>
 #include <linux/clk-provider.h>
+#include <linux/sched_clock.h>
 
 #include <asm/exception.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
-#include <asm/sched_clock.h>
 #include <asm/system_misc.h>
 
 #include <mach/hardware.h>
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index c4bdc0a..40f15f1 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -22,17 +22,19 @@
 #include <linux/mtd/partitions.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
+#include <linux/platform_data/gpio-davinci.h>
+#include <linux/platform_data/mtd-davinci.h>
+#include <linux/platform_data/mtd-davinci-aemif.h>
+#include <linux/platform_data/spi-davinci.h>
+#include <linux/platform_data/usb-davinci.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+#include <mach/common.h>
 #include <mach/cp_intc.h>
 #include <mach/mux.h>
-#include <linux/platform_data/mtd-davinci.h>
 #include <mach/da8xx.h>
-#include <linux/platform_data/usb-davinci.h>
-#include <linux/platform_data/mtd-davinci-aemif.h>
-#include <linux/platform_data/spi-davinci.h>
 
 #define DA830_EVM_PHY_ID		""
 /*
@@ -74,7 +76,7 @@
 	if (handler != NULL) {
 		da830_evm_usb_ocic_handler = handler;
 
-		error = request_irq(irq, da830_evm_usb_ocic_irq, IRQF_DISABLED |
+		error = request_irq(irq, da830_evm_usb_ocic_irq,
 				    IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 				    "OHCI over-current indicator", NULL);
 		if (error)
@@ -591,6 +593,10 @@
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
 	int ret;
 
+	ret = da830_register_gpio();
+	if (ret)
+		pr_warn("da830_evm_init: GPIO init failed: %d\n", ret);
+
 	ret = da830_register_edma(da830_edma_rsv);
 	if (ret)
 		pr_warning("da830_evm_init: edma registration failed: %d\n",
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index dd1fb24..df16cb8 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -28,6 +28,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/platform_device.h>
+#include <linux/platform_data/gpio-davinci.h>
 #include <linux/platform_data/mtd-davinci.h>
 #include <linux/platform_data/mtd-davinci-aemif.h>
 #include <linux/platform_data/spi-davinci.h>
@@ -38,6 +39,7 @@
 #include <linux/spi/flash.h>
 #include <linux/wl12xx.h>
 
+#include <mach/common.h>
 #include <mach/cp_intc.h>
 #include <mach/da8xx.h>
 #include <mach/mux.h>
@@ -1437,6 +1439,10 @@
 {
 	int ret;
 
+	ret = da850_register_gpio();
+	if (ret)
+		pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
+
 	ret = pmic_tps65070_init();
 	if (ret)
 		pr_warn("%s: TPS65070 PMIC init failed: %d\n", __func__, ret);
diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c
index 42b23a3..ecdc7d4 100644
--- a/arch/arm/mach-davinci/board-dm355-evm.c
+++ b/arch/arm/mach-davinci/board-dm355-evm.c
@@ -22,15 +22,17 @@
 #include <media/tvp514x.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/eeprom.h>
+#include <linux/platform_data/gpio-davinci.h>
+#include <linux/platform_data/i2c-davinci.h>
+#include <linux/platform_data/mtd-davinci.h>
+#include <linux/platform_data/mmc-davinci.h>
+#include <linux/platform_data/usb-davinci.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#include <linux/platform_data/i2c-davinci.h>
 #include <mach/serial.h>
-#include <linux/platform_data/mtd-davinci.h>
-#include <linux/platform_data/mmc-davinci.h>
-#include <linux/platform_data/usb-davinci.h>
+#include <mach/common.h>
 
 #include "davinci.h"
 
@@ -375,6 +377,11 @@
 static __init void dm355_evm_init(void)
 {
 	struct clk *aemif;
+	int ret;
+
+	ret = dm355_gpio_register();
+	if (ret)
+		pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
 
 	gpio_request(1, "dm9000");
 	gpio_direction_input(1);
diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c
index 65a984c..43bacbf 100644
--- a/arch/arm/mach-davinci/board-dm355-leopard.c
+++ b/arch/arm/mach-davinci/board-dm355-leopard.c
@@ -19,15 +19,16 @@
 #include <linux/clk.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/eeprom.h>
+#include <linux/platform_data/i2c-davinci.h>
+#include <linux/platform_data/mmc-davinci.h>
+#include <linux/platform_data/mtd-davinci.h>
+#include <linux/platform_data/usb-davinci.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#include <linux/platform_data/i2c-davinci.h>
+#include <mach/common.h>
 #include <mach/serial.h>
-#include <linux/platform_data/mtd-davinci.h>
-#include <linux/platform_data/mmc-davinci.h>
-#include <linux/platform_data/usb-davinci.h>
 
 #include "davinci.h"
 
@@ -234,6 +235,11 @@
 static __init void dm355_leopard_init(void)
 {
 	struct clk *aemif;
+	int ret;
+
+	ret = dm355_gpio_register();
+	if (ret)
+		pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
 
 	gpio_request(9, "dm9000");
 	gpio_direction_input(9);
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index 4078ba9..f4a6c18 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -743,6 +743,12 @@
 
 static __init void dm365_evm_init(void)
 {
+	int ret;
+
+	ret = dm365_gpio_register();
+	if (ret)
+		pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
+
 	evm_init_i2c();
 	davinci_serial_init(dm365_serial_device);
 
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index 40bb9b5..9cc32c2 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -754,9 +754,14 @@
 
 static __init void davinci_evm_init(void)
 {
+	int ret;
 	struct clk *aemif_clk;
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
 
+	ret = dm644x_gpio_register();
+	if (ret)
+		pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
+
 	aemif_clk = clk_get(NULL, "aemif");
 	clk_prepare_enable(aemif_clk);
 
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 2bc3651..44b2019 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -33,17 +33,19 @@
 #include <linux/mtd/partitions.h>
 #include <linux/clk.h>
 #include <linux/export.h>
+#include <linux/platform_data/gpio-davinci.h>
+#include <linux/platform_data/i2c-davinci.h>
+#include <linux/platform_data/mtd-davinci.h>
+#include <linux/platform_data/mtd-davinci-aemif.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
 #include <mach/common.h>
+#include <mach/irqs.h>
 #include <mach/serial.h>
-#include <linux/platform_data/i2c-davinci.h>
-#include <linux/platform_data/mtd-davinci.h>
 #include <mach/clock.h>
 #include <mach/cdce949.h>
-#include <linux/platform_data/mtd-davinci-aemif.h>
 
 #include "davinci.h"
 #include "clock.h"
@@ -786,8 +788,13 @@
 
 static __init void evm_init(void)
 {
+	int ret;
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
 
+	ret = dm646x_gpio_register();
+	if (ret)
+		pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
+
 	evm_init_i2c();
 	davinci_serial_init(dm646x_serial_device);
 	dm646x_init_mcasp0(&dm646x_evm_snd_data[0]);
diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c
index 46f336f..bb680af 100644
--- a/arch/arm/mach-davinci/board-neuros-osd2.c
+++ b/arch/arm/mach-davinci/board-neuros-osd2.c
@@ -26,17 +26,18 @@
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/mtd/partitions.h>
+#include <linux/platform_data/gpio-davinci.h>
+#include <linux/platform_data/i2c-davinci.h>
+#include <linux/platform_data/mmc-davinci.h>
+#include <linux/platform_data/mtd-davinci.h>
+#include <linux/platform_data/usb-davinci.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
 #include <mach/common.h>
-#include <linux/platform_data/i2c-davinci.h>
 #include <mach/serial.h>
 #include <mach/mux.h>
-#include <linux/platform_data/mtd-davinci.h>
-#include <linux/platform_data/mmc-davinci.h>
-#include <linux/platform_data/usb-davinci.h>
 
 #include "davinci.h"
 
@@ -169,9 +170,14 @@
 
 static __init void davinci_ntosd2_init(void)
 {
+	int ret;
 	struct clk *aemif_clk;
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
 
+	ret = dm644x_gpio_register();
+	if (ret)
+		pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
+
 	aemif_clk = clk_get(NULL, "aemif");
 	clk_prepare_enable(aemif_clk);
 
diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
index ab98c75..2aac51d 100644
--- a/arch/arm/mach-davinci/board-omapl138-hawk.c
+++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
@@ -13,10 +13,12 @@
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/gpio.h>
+#include <linux/platform_data/gpio-davinci.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+#include <mach/common.h>
 #include <mach/cp_intc.h>
 #include <mach/da8xx.h>
 #include <mach/mux.h>
@@ -211,7 +213,7 @@
 		hawk_usb_ocic_handler = handler;
 
 		error = request_irq(irq, omapl138_hawk_usb_ocic_irq,
-					IRQF_DISABLED | IRQF_TRIGGER_RISING |
+					IRQF_TRIGGER_RISING |
 					IRQF_TRIGGER_FALLING,
 					"OHCI over-current indicator", NULL);
 		if (error)
@@ -290,6 +292,10 @@
 {
 	int ret;
 
+	ret = da850_register_gpio();
+	if (ret)
+		pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
+
 	davinci_serial_init(da8xx_serial_device);
 
 	omapl138_hawk_config_emac();
diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c
index d6c746e..0813b51 100644
--- a/arch/arm/mach-davinci/da830.c
+++ b/arch/arm/mach-davinci/da830.c
@@ -11,6 +11,7 @@
 #include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/clk.h>
+#include <linux/platform_data/gpio-davinci.h>
 
 #include <asm/mach/map.h>
 
@@ -20,7 +21,6 @@
 #include <mach/common.h>
 #include <mach/time.h>
 #include <mach/da8xx.h>
-#include <mach/gpio-davinci.h>
 
 #include "clock.h"
 #include "mux.h"
@@ -1151,6 +1151,16 @@
 	},
 };
 
+static struct davinci_gpio_platform_data da830_gpio_platform_data = {
+	.ngpio = 128,
+	.intc_irq_num = DA830_N_CP_INTC_IRQ,
+};
+
+int __init da830_register_gpio(void)
+{
+	return da8xx_register_gpio(&da830_gpio_platform_data);
+}
+
 static struct davinci_timer_instance da830_timer_instance[2] = {
 	{
 		.base		= DA8XX_TIMER64P0_BASE,
@@ -1196,10 +1206,6 @@
 	.intc_irq_prios		= da830_default_priorities,
 	.intc_irq_num		= DA830_N_CP_INTC_IRQ,
 	.timer_info		= &da830_timer_info,
-	.gpio_type		= GPIO_TYPE_DAVINCI,
-	.gpio_base		= DA8XX_GPIO_BASE,
-	.gpio_num		= 128,
-	.gpio_irq		= IRQ_DA8XX_GPIO0,
 	.emac_pdata		= &da8xx_emac_pdata,
 };
 
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index f56e5fb..352984e 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -17,6 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/cpufreq.h>
 #include <linux/regulator/consumer.h>
+#include <linux/platform_data/gpio-davinci.h>
 
 #include <asm/mach/map.h>
 
@@ -28,7 +29,6 @@
 #include <mach/da8xx.h>
 #include <mach/cpufreq.h>
 #include <mach/pm.h>
-#include <mach/gpio-davinci.h>
 
 #include "clock.h"
 #include "mux.h"
@@ -1281,6 +1281,16 @@
 	return platform_device_register(&da850_vpif_capture_dev);
 }
 
+static struct davinci_gpio_platform_data da850_gpio_platform_data = {
+	.ngpio = 144,
+	.intc_irq_num = DA850_N_CP_INTC_IRQ,
+};
+
+int __init da850_register_gpio(void)
+{
+	return da8xx_register_gpio(&da850_gpio_platform_data);
+}
+
 static struct davinci_soc_info davinci_soc_info_da850 = {
 	.io_desc		= da850_io_desc,
 	.io_desc_num		= ARRAY_SIZE(da850_io_desc),
@@ -1298,10 +1308,6 @@
 	.intc_irq_prios		= da850_default_priorities,
 	.intc_irq_num		= DA850_N_CP_INTC_IRQ,
 	.timer_info		= &da850_timer_info,
-	.gpio_type		= GPIO_TYPE_DAVINCI,
-	.gpio_base		= DA8XX_GPIO_BASE,
-	.gpio_num		= 144,
-	.gpio_irq		= IRQ_DA8XX_GPIO0,
 	.emac_pdata		= &da8xx_emac_pdata,
 	.sram_dma		= DA8XX_SHARED_RAM_BASE,
 	.sram_len		= SZ_128K,
diff --git a/arch/arm/mach-davinci/davinci.h b/arch/arm/mach-davinci/davinci.h
index 2ab5d57..2eebc43 100644
--- a/arch/arm/mach-davinci/davinci.h
+++ b/arch/arm/mach-davinci/davinci.h
@@ -53,6 +53,9 @@
 #define DAVINCI_SYSMOD_VIRT(x)	(davinci_sysmod_base + (x))
 void davinci_map_sysmod(void);
 
+#define DAVINCI_GPIO_BASE 0x01C67000
+int davinci_gpio_register(struct resource *res, int size, void *pdata);
+
 /* DM355 base addresses */
 #define DM355_ASYNC_EMIF_CONTROL_BASE	0x01e10000
 #define DM355_ASYNC_EMIF_DATA_CE0_BASE	0x02000000
@@ -82,6 +85,7 @@
 		const struct spi_board_info *info, unsigned len);
 void dm355_init_asp1(u32 evt_enable, struct snd_platform_data *pdata);
 int dm355_init_video(struct vpfe_config *, struct vpbe_config *);
+int dm355_gpio_register(void);
 
 /* DM365 function declarations */
 void dm365_init(void);
@@ -92,11 +96,13 @@
 void dm365_init_spi0(unsigned chipselect_mask,
 			const struct spi_board_info *info, unsigned len);
 int dm365_init_video(struct vpfe_config *, struct vpbe_config *);
+int dm365_gpio_register(void);
 
 /* DM644x function declarations */
 void dm644x_init(void);
 void dm644x_init_asp(struct snd_platform_data *pdata);
 int dm644x_init_video(struct vpfe_config *, struct vpbe_config *);
+int dm644x_gpio_register(void);
 
 /* DM646x function declarations */
 void dm646x_init(void);
@@ -106,6 +112,7 @@
 void dm646x_video_init(void);
 void dm646x_setup_vpif(struct vpif_display_config *,
 		       struct vpif_capture_config *);
+int dm646x_gpio_register(void);
 
 extern struct platform_device dm365_serial_device[];
 extern struct platform_device dm355_serial_device[];
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index 2e473fe..c46eccb 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -665,6 +665,32 @@
 	return platform_device_register(&da8xx_lcdc_device);
 }
 
+static struct resource da8xx_gpio_resources[] = {
+	{ /* registers */
+		.start	= DA8XX_GPIO_BASE,
+		.end	= DA8XX_GPIO_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{ /* interrupt */
+		.start	= IRQ_DA8XX_GPIO0,
+		.end	= IRQ_DA8XX_GPIO8,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device da8xx_gpio_device = {
+	.name		= "davinci_gpio",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(da8xx_gpio_resources),
+	.resource	= da8xx_gpio_resources,
+};
+
+int __init da8xx_register_gpio(void *pdata)
+{
+	da8xx_gpio_device.dev.platform_data = pdata;
+	return platform_device_register(&da8xx_gpio_device);
+}
+
 static struct resource da8xx_mmcsd0_resources[] = {
 	{		/* registers */
 		.start	= DA8XX_MMCSD0_BASE,
diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c
index 111573c0..3996e98 100644
--- a/arch/arm/mach-davinci/devices.c
+++ b/arch/arm/mach-davinci/devices.c
@@ -318,6 +318,19 @@
 	platform_device_register(&davinci_wdt_device);
 }
 
+static struct platform_device davinci_gpio_device = {
+	.name	= "davinci_gpio",
+	.id	= -1,
+};
+
+int davinci_gpio_register(struct resource *res, int size, void *pdata)
+{
+	davinci_gpio_device.resource = res;
+	davinci_gpio_device.num_resources = size;
+	davinci_gpio_device.dev.platform_data = pdata;
+	return platform_device_register(&davinci_gpio_device);
+}
+
 /*-------------------------------------------------------------------------*/
 
 /*-------------------------------------------------------------------------*/
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index 3eaa5f6..ef9ff1f 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -13,8 +13,10 @@
 #include <linux/serial_8250.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
-
 #include <linux/spi/spi.h>
+#include <linux/platform_data/edma.h>
+#include <linux/platform_data/gpio-davinci.h>
+#include <linux/platform_data/spi-davinci.h>
 
 #include <asm/mach/map.h>
 
@@ -25,9 +27,6 @@
 #include <mach/time.h>
 #include <mach/serial.h>
 #include <mach/common.h>
-#include <linux/platform_data/spi-davinci.h>
-#include <mach/gpio-davinci.h>
-#include <linux/platform_data/edma.h>
 
 #include "davinci.h"
 #include "clock.h"
@@ -886,6 +885,30 @@
 	},
 };
 
+static struct resource dm355_gpio_resources[] = {
+	{	/* registers */
+		.start	= DAVINCI_GPIO_BASE,
+		.end	= DAVINCI_GPIO_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{	/* interrupt */
+		.start	= IRQ_DM355_GPIOBNK0,
+		.end	= IRQ_DM355_GPIOBNK6,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct davinci_gpio_platform_data dm355_gpio_platform_data = {
+	.ngpio		= 104,
+	.intc_irq_num	= DAVINCI_N_AINTC_IRQ,
+};
+
+int __init dm355_gpio_register(void)
+{
+	return davinci_gpio_register(dm355_gpio_resources,
+				     sizeof(dm355_gpio_resources),
+				     &dm355_gpio_platform_data);
+}
 /*----------------------------------------------------------------------*/
 
 static struct map_desc dm355_io_desc[] = {
@@ -1005,10 +1028,6 @@
 	.intc_irq_prios		= dm355_default_priorities,
 	.intc_irq_num		= DAVINCI_N_AINTC_IRQ,
 	.timer_info		= &dm355_timer_info,
-	.gpio_type		= GPIO_TYPE_DAVINCI,
-	.gpio_base		= DAVINCI_GPIO_BASE,
-	.gpio_num		= 104,
-	.gpio_irq		= IRQ_DM355_GPIOBNK0,
 	.sram_dma		= 0x00010000,
 	.sram_len		= SZ_32K,
 };
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index c29e324..1511a06 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -19,6 +19,9 @@
 #include <linux/dma-mapping.h>
 #include <linux/spi/spi.h>
 #include <linux/platform_data/edma.h>
+#include <linux/platform_data/gpio-davinci.h>
+#include <linux/platform_data/keyscan-davinci.h>
+#include <linux/platform_data/spi-davinci.h>
 
 #include <asm/mach/map.h>
 
@@ -29,9 +32,6 @@
 #include <mach/time.h>
 #include <mach/serial.h>
 #include <mach/common.h>
-#include <linux/platform_data/keyscan-davinci.h>
-#include <linux/platform_data/spi-davinci.h>
-#include <mach/gpio-davinci.h>
 
 #include "davinci.h"
 #include "clock.h"
@@ -698,6 +698,32 @@
 	platform_device_register(&dm365_spi0_device);
 }
 
+static struct resource dm365_gpio_resources[] = {
+	{	/* registers */
+		.start	= DAVINCI_GPIO_BASE,
+		.end	= DAVINCI_GPIO_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{	/* interrupt */
+		.start	= IRQ_DM365_GPIO0,
+		.end	= IRQ_DM365_GPIO7,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct davinci_gpio_platform_data dm365_gpio_platform_data = {
+	.ngpio		= 104,
+	.intc_irq_num	= DAVINCI_N_AINTC_IRQ,
+	.gpio_unbanked	= 8,
+};
+
+int __init dm365_gpio_register(void)
+{
+	return davinci_gpio_register(dm365_gpio_resources,
+				     sizeof(dm365_gpio_resources),
+				     &dm365_gpio_platform_data);
+}
+
 static struct emac_platform_data dm365_emac_pdata = {
 	.ctrl_reg_offset	= DM365_EMAC_CNTRL_OFFSET,
 	.ctrl_mod_reg_offset	= DM365_EMAC_CNTRL_MOD_OFFSET,
@@ -1105,11 +1131,6 @@
 	.intc_irq_prios		= dm365_default_priorities,
 	.intc_irq_num		= DAVINCI_N_AINTC_IRQ,
 	.timer_info		= &dm365_timer_info,
-	.gpio_type		= GPIO_TYPE_DAVINCI,
-	.gpio_base		= DAVINCI_GPIO_BASE,
-	.gpio_num		= 104,
-	.gpio_irq		= IRQ_DM365_GPIO0,
-	.gpio_unbanked		= 8,	/* really 16 ... skip muxed GPIOs */
 	.emac_pdata		= &dm365_emac_pdata,
 	.sram_dma		= 0x00010000,
 	.sram_len		= SZ_32K,
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index 4f74682..143a321 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -13,6 +13,7 @@
 #include <linux/serial_8250.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/edma.h>
+#include <linux/platform_data/gpio-davinci.h>
 
 #include <asm/mach/map.h>
 
@@ -23,7 +24,6 @@
 #include <mach/time.h>
 #include <mach/serial.h>
 #include <mach/common.h>
-#include <mach/gpio-davinci.h>
 
 #include "davinci.h"
 #include "clock.h"
@@ -771,6 +771,30 @@
 	},
 };
 
+static struct resource dm644_gpio_resources[] = {
+	{	/* registers */
+		.start	= DAVINCI_GPIO_BASE,
+		.end	= DAVINCI_GPIO_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{	/* interrupt */
+		.start	= IRQ_GPIOBNK0,
+		.end	= IRQ_GPIOBNK4,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct davinci_gpio_platform_data dm644_gpio_platform_data = {
+	.ngpio		= 71,
+	.intc_irq_num	= DAVINCI_N_AINTC_IRQ,
+};
+
+int __init dm644x_gpio_register(void)
+{
+	return davinci_gpio_register(dm644_gpio_resources,
+				     sizeof(dm644_gpio_resources),
+				     &dm644_gpio_platform_data);
+}
 /*----------------------------------------------------------------------*/
 
 static struct map_desc dm644x_io_desc[] = {
@@ -897,10 +921,6 @@
 	.intc_irq_prios 	= dm644x_default_priorities,
 	.intc_irq_num		= DAVINCI_N_AINTC_IRQ,
 	.timer_info		= &dm644x_timer_info,
-	.gpio_type		= GPIO_TYPE_DAVINCI,
-	.gpio_base		= DAVINCI_GPIO_BASE,
-	.gpio_num		= 71,
-	.gpio_irq		= IRQ_GPIOBNK0,
 	.emac_pdata		= &dm644x_emac_pdata,
 	.sram_dma		= 0x00008000,
 	.sram_len		= SZ_16K,
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index 68f8d1f..2a73f29 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -14,6 +14,7 @@
 #include <linux/serial_8250.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/edma.h>
+#include <linux/platform_data/gpio-davinci.h>
 
 #include <asm/mach/map.h>
 
@@ -24,7 +25,6 @@
 #include <mach/time.h>
 #include <mach/serial.h>
 #include <mach/common.h>
-#include <mach/gpio-davinci.h>
 
 #include "davinci.h"
 #include "clock.h"
@@ -748,6 +748,30 @@
 	.num_resources	= ARRAY_SIZE(vpif_capture_resource),
 };
 
+static struct resource dm646x_gpio_resources[] = {
+	{	/* registers */
+		.start	= DAVINCI_GPIO_BASE,
+		.end	= DAVINCI_GPIO_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{	/* interrupt */
+		.start	= IRQ_DM646X_GPIOBNK0,
+		.end	= IRQ_DM646X_GPIOBNK2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct davinci_gpio_platform_data dm646x_gpio_platform_data = {
+	.ngpio		= 43,
+	.intc_irq_num	= DAVINCI_N_AINTC_IRQ,
+};
+
+int __init dm646x_gpio_register(void)
+{
+	return davinci_gpio_register(dm646x_gpio_resources,
+				     sizeof(dm646x_gpio_resources),
+				     &dm646x_gpio_platform_data);
+}
 /*----------------------------------------------------------------------*/
 
 static struct map_desc dm646x_io_desc[] = {
@@ -874,10 +898,6 @@
 	.intc_irq_prios		= dm646x_default_priorities,
 	.intc_irq_num		= DAVINCI_N_AINTC_IRQ,
 	.timer_info		= &dm646x_timer_info,
-	.gpio_type		= GPIO_TYPE_DAVINCI,
-	.gpio_base		= DAVINCI_GPIO_BASE,
-	.gpio_num		= 43, /* Only 33 usable */
-	.gpio_irq		= IRQ_DM646X_GPIOBNK0,
 	.emac_pdata		= &dm646x_emac_pdata,
 	.sram_dma		= 0x10010000,
 	.sram_len		= SZ_32K,
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index aae5307..39e58b4 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -97,6 +97,7 @@
 int da850_register_mmcsd1(struct davinci_mmc_config *config);
 void da8xx_register_mcasp(int id, struct snd_platform_data *pdata);
 int da8xx_register_rtc(void);
+int da8xx_register_gpio(void *pdata);
 int da850_register_cpufreq(char *async_clk);
 int da8xx_register_cpuidle(void);
 void __iomem *da8xx_get_mem_ctlr(void);
@@ -110,6 +111,8 @@
 void da8xx_restart(enum reboot_mode mode, const char *cmd);
 void da8xx_rproc_reserve_cma(void);
 int da8xx_register_rproc(void);
+int da850_register_gpio(void);
+int da830_register_gpio(void);
 
 extern struct platform_device da8xx_serial_device[];
 extern struct emac_platform_data da8xx_emac_pdata;
diff --git a/arch/arm/mach-davinci/include/mach/gpio-davinci.h b/arch/arm/mach-davinci/include/mach/gpio-davinci.h
deleted file mode 100644
index 1fdd1fd..0000000
--- a/arch/arm/mach-davinci/include/mach/gpio-davinci.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * TI DaVinci GPIO Support
- *
- * Copyright (c) 2006 David Brownell
- * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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	__DAVINCI_DAVINCI_GPIO_H
-#define	__DAVINCI_DAVINCI_GPIO_H
-
-#include <linux/io.h>
-#include <linux/spinlock.h>
-
-#include <asm-generic/gpio.h>
-
-#include <mach/irqs.h>
-#include <mach/common.h>
-
-#define DAVINCI_GPIO_BASE 0x01C67000
-
-enum davinci_gpio_type {
-	GPIO_TYPE_DAVINCI = 0,
-	GPIO_TYPE_TNETV107X,
-};
-
-/*
- * basic gpio routines
- *
- * board-specific init should be done by arch/.../.../board-XXX.c (maybe
- * initializing banks together) rather than boot loaders; kexec() won't
- * go through boot loaders.
- *
- * the gpio clock will be turned on when gpios are used, and you may also
- * need to pay attention to PINMUX registers to be sure those pins are
- * used as gpios, not with other peripherals.
- *
- * On-chip GPIOs are numbered 0..(DAVINCI_N_GPIO-1).  For documentation,
- * and maybe for later updates, code may write GPIO(N).  These may be
- * all 1.8V signals, all 3.3V ones, or a mix of the two.  A given chip
- * may not support all the GPIOs in that range.
- *
- * GPIOs can also be on external chips, numbered after the ones built-in
- * to the DaVinci chip.  For now, they won't be usable as IRQ sources.
- */
-#define	GPIO(X)		(X)		/* 0 <= X <= (DAVINCI_N_GPIO - 1) */
-
-/* Convert GPIO signal to GPIO pin number */
-#define GPIO_TO_PIN(bank, gpio)	(16 * (bank) + (gpio))
-
-struct davinci_gpio_controller {
-	struct gpio_chip	chip;
-	int			irq_base;
-	spinlock_t		lock;
-	void __iomem		*regs;
-	void __iomem		*set_data;
-	void __iomem		*clr_data;
-	void __iomem		*in_data;
-};
-
-/* The __gpio_to_controller() and __gpio_mask() functions inline to constants
- * with constant parameters; or in outlined code they execute at runtime.
- *
- * You'd access the controller directly when reading or writing more than
- * one gpio value at a time, and to support wired logic where the value
- * being driven by the cpu need not match the value read back.
- *
- * These are NOT part of the cross-platform GPIO interface
- */
-static inline struct davinci_gpio_controller *
-__gpio_to_controller(unsigned gpio)
-{
-	struct davinci_gpio_controller *ctlrs = davinci_soc_info.gpio_ctlrs;
-	int index = gpio / 32;
-
-	if (!ctlrs || index >= davinci_soc_info.gpio_ctlrs_num)
-		return NULL;
-
-	return ctlrs + index;
-}
-
-static inline u32 __gpio_mask(unsigned gpio)
-{
-	return 1 << (gpio % 32);
-}
-
-#endif	/* __DAVINCI_DAVINCI_GPIO_H */
diff --git a/arch/arm/mach-davinci/include/mach/gpio.h b/arch/arm/mach-davinci/include/mach/gpio.h
deleted file mode 100644
index 960e9de..0000000
--- a/arch/arm/mach-davinci/include/mach/gpio.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * TI DaVinci GPIO Support
- *
- * Copyright (c) 2006 David Brownell
- * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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	__DAVINCI_GPIO_H
-#define	__DAVINCI_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-#define __ARM_GPIOLIB_COMPLEX
-
-/* The inline versions use the static inlines in the driver header */
-#include "gpio-davinci.h"
-
-/*
- * The get/set/clear functions will inline when called with constant
- * parameters referencing built-in GPIOs, for low-overhead bitbanging.
- *
- * gpio_set_value() will inline only on traditional Davinci style controllers
- * with distinct set/clear registers.
- *
- * Otherwise, calls with variable parameters or referencing external
- * GPIOs (e.g. on GPIO expander chips) use outlined functions.
- */
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-	if (__builtin_constant_p(value) && gpio < davinci_soc_info.gpio_num) {
-		struct davinci_gpio_controller *ctlr;
-		u32				mask;
-
-		ctlr = __gpio_to_controller(gpio);
-
-		if (ctlr->set_data != ctlr->clr_data) {
-			mask = __gpio_mask(gpio);
-			if (value)
-				__raw_writel(mask, ctlr->set_data);
-			else
-				__raw_writel(mask, ctlr->clr_data);
-			return;
-		}
-	}
-
-	__gpio_set_value(gpio, value);
-}
-
-/* Returns zero or nonzero; works for gpios configured as inputs OR
- * as outputs, at least for built-in GPIOs.
- *
- * NOTE: for built-in GPIOs, changes in reported values are synchronized
- * to the GPIO clock.  This is easily seen after calling gpio_set_value()
- * and then immediately gpio_get_value(), where the gpio_get_value() will
- * return the old value until the GPIO clock ticks and the new value gets
- * latched.
- */
-static inline int gpio_get_value(unsigned gpio)
-{
-	struct davinci_gpio_controller *ctlr;
-
-	if (!__builtin_constant_p(gpio) || gpio >= davinci_soc_info.gpio_num)
-		return __gpio_get_value(gpio);
-
-	ctlr = __gpio_to_controller(gpio);
-	return __gpio_mask(gpio) & __raw_readl(ctlr->in_data);
-}
-
-static inline int gpio_cansleep(unsigned gpio)
-{
-	if (__builtin_constant_p(gpio) && gpio < davinci_soc_info.gpio_num)
-		return 0;
-	else
-		return __gpio_cansleep(gpio);
-}
-
-static inline int irq_to_gpio(unsigned irq)
-{
-	/* don't support the reverse mapping */
-	return -ENOSYS;
-}
-
-#endif				/* __DAVINCI_GPIO_H */
diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c
index 7a55b5c..56c6eb5 100644
--- a/arch/arm/mach-davinci/time.c
+++ b/arch/arm/mach-davinci/time.c
@@ -181,7 +181,7 @@
 		.name      = "clockevent",
 		.opts      = TIMER_OPTS_DISABLED,
 		.irqaction = {
-			.flags   = IRQF_DISABLED | IRQF_TIMER,
+			.flags   = IRQF_TIMER,
 			.handler = timer_interrupt,
 		}
 	},
@@ -190,7 +190,7 @@
 		.period     = ~0,
 		.opts       = TIMER_OPTS_PERIODIC,
 		.irqaction = {
-			.flags   = IRQF_DISABLED | IRQF_TIMER,
+			.flags   = IRQF_TIMER,
 			.handler = freerun_interrupt,
 		}
 	},
@@ -331,7 +331,6 @@
 
 static struct clock_event_device clockevent_davinci = {
 	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.shift		= 32,
 	.set_next_event	= davinci_set_next_event,
 	.set_mode	= davinci_set_mode,
 };
@@ -397,14 +396,10 @@
 
 	/* setup clockevent */
 	clockevent_davinci.name = id_to_name[timers[TID_CLOCKEVENT].id];
-	clockevent_davinci.mult = div_sc(davinci_clock_tick_rate, NSEC_PER_SEC,
-					 clockevent_davinci.shift);
-	clockevent_davinci.max_delta_ns =
-		clockevent_delta2ns(0xfffffffe, &clockevent_davinci);
-	clockevent_davinci.min_delta_ns = 50000; /* 50 usec */
 
 	clockevent_davinci.cpumask = cpumask_of(0);
-	clockevents_register_device(&clockevent_davinci);
+	clockevents_config_and_register(&clockevent_davinci,
+					davinci_clock_tick_rate, 1, 0xfffffffe);
 
 	for (i=0; i< ARRAY_SIZE(timers); i++)
 		timer32_config(&timers[i]);
diff --git a/arch/arm/mach-dove/board-dt.c b/arch/arm/mach-dove/board-dt.c
index 49f72a8..49fa9ab 100644
--- a/arch/arm/mach-dove/board-dt.c
+++ b/arch/arm/mach-dove/board-dt.c
@@ -10,54 +10,15 @@
 
 #include <linux/init.h>
 #include <linux/clk-provider.h>
-#include <linux/clocksource.h>
-#include <linux/irqchip.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
-#include <linux/platform_data/usb-ehci-orion.h>
 #include <asm/hardware/cache-tauros2.h>
 #include <asm/mach/arch.h>
 #include <mach/dove.h>
 #include <mach/pm.h>
 #include <plat/common.h>
-#include <plat/irq.h>
 #include "common.h"
 
-/*
- * There are still devices that doesn't even know about DT,
- * get clock gates here and add a clock lookup.
- */
-static void __init dove_legacy_clk_init(void)
-{
-	struct device_node *np = of_find_compatible_node(NULL, NULL,
-					 "marvell,dove-gating-clock");
-	struct of_phandle_args clkspec;
-
-	clkspec.np = np;
-	clkspec.args_count = 1;
-
-	clkspec.args[0] = CLOCK_GATING_BIT_PCIE0;
-	orion_clkdev_add("0", "pcie",
-			 of_clk_get_from_provider(&clkspec));
-
-	clkspec.args[0] = CLOCK_GATING_BIT_PCIE1;
-	orion_clkdev_add("1", "pcie",
-			 of_clk_get_from_provider(&clkspec));
-}
-
-static void __init dove_dt_time_init(void)
-{
-	of_clk_init(NULL);
-	clocksource_of_init();
-}
-
-static void __init dove_dt_init_early(void)
-{
-	mvebu_mbus_init("marvell,dove-mbus",
-			BRIDGE_WINS_BASE, BRIDGE_WINS_SZ,
-			DOVE_MC_WINS_BASE, DOVE_MC_WINS_SZ);
-}
-
 static void __init dove_dt_init(void)
 {
 	pr_info("Dove 88AP510 SoC\n");
@@ -65,14 +26,7 @@
 #ifdef CONFIG_CACHE_TAUROS2
 	tauros2_init(0);
 #endif
-	dove_setup_cpu_wins();
-
-	/* Setup clocks for legacy devices */
-	dove_legacy_clk_init();
-
-	/* Internal devices not ported to DT yet */
-	dove_pcie_init(1, 1);
-
+	BUG_ON(mvebu_mbus_dt_init());
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
@@ -83,8 +37,6 @@
 
 DT_MACHINE_START(DOVE_DT, "Marvell Dove (Flattened Device Tree)")
 	.map_io		= dove_map_io,
-	.init_early	= dove_dt_init_early,
-	.init_time	= dove_dt_time_init,
 	.init_machine	= dove_dt_init,
 	.restart	= dove_restart,
 	.dt_compat	= dove_dt_board_compat,
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
index c95dbce..39ef3b6 100644
--- a/arch/arm/mach-ep93xx/clock.c
+++ b/arch/arm/mach-ep93xx/clock.c
@@ -212,7 +212,7 @@
 	INIT_CK(NULL,			"hclk",		&clk_h),
 	INIT_CK(NULL,			"apb_pclk",	&clk_p),
 	INIT_CK(NULL,			"pll2",		&clk_pll2),
-	INIT_CK("ep93xx-ohci",		NULL,		&clk_usb_host),
+	INIT_CK("ohci-platform",	NULL,		&clk_usb_host),
 	INIT_CK("ep93xx-keypad",	NULL,		&clk_keypad),
 	INIT_CK("ep93xx-fb",		NULL,		&clk_video),
 	INIT_CK("ep93xx-spi.0",		NULL,		&clk_spi),
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 3f12b88..d95ee28a 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -36,6 +36,7 @@
 #include <linux/export.h>
 #include <linux/irqchip/arm-vic.h>
 #include <linux/reboot.h>
+#include <linux/usb/ohci_pdriver.h>
 
 #include <mach/hardware.h>
 #include <linux/platform_data/video-ep93xx.h>
@@ -297,25 +298,53 @@
 	.resource	= ep93xx_rtc_resource,
 };
 
+/*************************************************************************
+ * EP93xx OHCI USB Host
+ *************************************************************************/
+
+static struct clk *ep93xx_ohci_host_clock;
+
+static int ep93xx_ohci_power_on(struct platform_device *pdev)
+{
+	if (!ep93xx_ohci_host_clock) {
+		ep93xx_ohci_host_clock = devm_clk_get(&pdev->dev, NULL);
+		if (IS_ERR(ep93xx_ohci_host_clock))
+			return PTR_ERR(ep93xx_ohci_host_clock);
+	}
+
+	return clk_enable(ep93xx_ohci_host_clock);
+}
+
+static void ep93xx_ohci_power_off(struct platform_device *pdev)
+{
+	clk_disable(ep93xx_ohci_host_clock);
+}
+
+static struct usb_ohci_pdata ep93xx_ohci_pdata = {
+	.power_on	= ep93xx_ohci_power_on,
+	.power_off	= ep93xx_ohci_power_off,
+	.power_suspend	= ep93xx_ohci_power_off,
+};
 
 static struct resource ep93xx_ohci_resources[] = {
 	DEFINE_RES_MEM(EP93XX_USB_PHYS_BASE, 0x1000),
 	DEFINE_RES_IRQ(IRQ_EP93XX_USB),
 };
 
+static u64 ep93xx_ohci_dma_mask = DMA_BIT_MASK(32);
 
 static struct platform_device ep93xx_ohci_device = {
-	.name		= "ep93xx-ohci",
+	.name		= "ohci-platform",
 	.id		= -1,
-	.dev		= {
-		.dma_mask		= &ep93xx_ohci_device.dev.coherent_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
 	.num_resources	= ARRAY_SIZE(ep93xx_ohci_resources),
 	.resource	= ep93xx_ohci_resources,
+	.dev		= {
+		.dma_mask		= &ep93xx_ohci_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+		.platform_data		= &ep93xx_ohci_pdata,
+	},
 };
 
-
 /*************************************************************************
  * EP93xx physmap'ed flash
  *************************************************************************/
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 56fe819..f9d67a0 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -14,19 +14,28 @@
 config ARCH_EXYNOS4
 	bool "SAMSUNG EXYNOS4"
 	default y
+	select ARM_AMBA
+	select CLKSRC_OF
+	select CLKSRC_SAMSUNG_PWM if CPU_EXYNOS4210
+	select CPU_EXYNOS4210
 	select GIC_NON_BANKED
+	select KEYBOARD_SAMSUNG if INPUT_KEYBOARD
 	select HAVE_ARM_SCU if SMP
 	select HAVE_SMP
 	select MIGHT_HAVE_CACHE_L2X0
 	select PINCTRL
+	select S5P_DEV_MFC
 	help
 	  Samsung EXYNOS4 SoCs based systems
 
 config ARCH_EXYNOS5
 	bool "SAMSUNG EXYNOS5"
+	select ARM_AMBA
+	select CLKSRC_OF
 	select HAVE_ARM_SCU if SMP
 	select HAVE_SMP
 	select PINCTRL
+	select USB_ARCH_HAS_XHCI
 	help
 	  Samsung EXYNOS5 (Cortex-A15) SoC based systems
 
@@ -110,35 +119,6 @@
 	help
 	  Enable EXYNOS5440 SoC support
 
-comment "Flattened Device Tree based board for EXYNOS SoCs"
-
-config MACH_EXYNOS4_DT
-	bool "Samsung Exynos4 Machine using device tree"
-	default y
-	depends on ARCH_EXYNOS4
-	select ARM_AMBA
-	select CLKSRC_OF
-	select CLKSRC_SAMSUNG_PWM if CPU_EXYNOS4210
-	select CPU_EXYNOS4210
-	select KEYBOARD_SAMSUNG if INPUT_KEYBOARD
-	select S5P_DEV_MFC
-	help
-	  Machine support for Samsung Exynos4 machine with device tree enabled.
-	  Select this if a fdt blob is available for the Exynos4 SoC based board.
-	  Note: This is under development and not all peripherals can be supported
-	  with this machine file.
-
-config MACH_EXYNOS5_DT
-	bool "SAMSUNG EXYNOS5 Machine using device tree"
-	default y
-	depends on ARCH_EXYNOS5
-	select ARM_AMBA
-	select CLKSRC_OF
-	select USB_ARCH_HAS_XHCI
-	help
-	  Machine support for Samsung EXYNOS5 machine with device tree enabled.
-	  Select this if a fdt blob is available for the EXYNOS5 SoC based board.
-
 endmenu
 
 endif
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index 5369615..8930b66 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -32,5 +32,5 @@
 
 # machine support
 
-obj-$(CONFIG_MACH_EXYNOS4_DT)		+= mach-exynos4-dt.o
-obj-$(CONFIG_MACH_EXYNOS5_DT)		+= mach-exynos5-dt.o
+obj-$(CONFIG_ARCH_EXYNOS4)	+= mach-exynos4-dt.o
+obj-$(CONFIG_ARCH_EXYNOS5)	+= mach-exynos5-dt.o
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index ba95e5d..a4e7ba8 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -26,8 +26,6 @@
 #include <linux/export.h>
 #include <linux/irqdomain.h>
 #include <linux/of_address.h>
-#include <linux/clocksource.h>
-#include <linux/clk-provider.h>
 #include <linux/irqchip/arm-gic.h>
 #include <linux/irqchip/chained_irq.h>
 
@@ -367,12 +365,6 @@
 		iotable_init(exynos5250_iodesc, ARRAY_SIZE(exynos5250_iodesc));
 }
 
-void __init exynos_init_time(void)
-{
-	of_clk_init(NULL);
-	clocksource_of_init();
-}
-
 struct bus_type exynos_subsys = {
 	.name		= "exynos-core",
 	.dev_name	= "exynos-core",
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 8646a14..f0fa205 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -16,7 +16,6 @@
 #include <linux/of.h>
 
 void mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1);
-void exynos_init_time(void);
 
 struct map_desc;
 void exynos_init_io(void);
diff --git a/arch/arm/mach-exynos/include/mach/regs-pmu.h b/arch/arm/mach-exynos/include/mach/regs-pmu.h
index 57344b7..2cdb63e 100644
--- a/arch/arm/mach-exynos/include/mach/regs-pmu.h
+++ b/arch/arm/mach-exynos/include/mach/regs-pmu.h
@@ -44,11 +44,6 @@
 #define S5P_DAC_PHY_CONTROL			S5P_PMUREG(0x070C)
 #define S5P_DAC_PHY_ENABLE			(1 << 0)
 
-#define S5P_MIPI_DPHY_CONTROL(n)		S5P_PMUREG(0x0710 + (n) * 4)
-#define S5P_MIPI_DPHY_ENABLE			(1 << 0)
-#define S5P_MIPI_DPHY_SRESETN			(1 << 1)
-#define S5P_MIPI_DPHY_MRESETN			(1 << 2)
-
 #define S5P_INFORM0				S5P_PMUREG(0x0800)
 #define S5P_INFORM1				S5P_PMUREG(0x0804)
 #define S5P_INFORM2				S5P_PMUREG(0x0808)
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c
index 0099c6c..4b8f6e2 100644
--- a/arch/arm/mach-exynos/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -11,12 +11,8 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/kernel.h>
 #include <linux/of_platform.h>
 #include <linux/of_fdt.h>
-#include <linux/serial_core.h>
-#include <linux/memblock.h>
-#include <linux/clocksource.h>
 
 #include <asm/mach/arch.h>
 #include <plat/mfc.h>
@@ -54,7 +50,6 @@
 	.init_early	= exynos_firmware_init,
 	.init_machine	= exynos4_dt_machine_init,
 	.init_late	= exynos_init_late,
-	.init_time	= exynos_init_time,
 	.dt_compat	= exynos4_dt_compat,
 	.restart        = exynos4_restart,
 	.reserve	= exynos4_reserve,
diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c
index f874b77..7976ab3 100644
--- a/arch/arm/mach-exynos/mach-exynos5-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos5-dt.c
@@ -11,14 +11,10 @@
 
 #include <linux/of_platform.h>
 #include <linux/of_fdt.h>
-#include <linux/memblock.h>
 #include <linux/io.h>
-#include <linux/clocksource.h>
 
 #include <asm/mach/arch.h>
 #include <mach/regs-pmu.h>
-
-#include <plat/cpu.h>
 #include <plat/mfc.h>
 
 #include "common.h"
@@ -76,7 +72,6 @@
 	.map_io		= exynos_init_io,
 	.init_machine	= exynos5_dt_machine_init,
 	.init_late	= exynos_init_late,
-	.init_time	= exynos_init_time,
 	.dt_compat	= exynos5_dt_compat,
 	.restart        = exynos5_restart,
 	.reserve	= exynos5_reserve,
diff --git a/arch/arm/mach-gemini/gpio.c b/arch/arm/mach-gemini/gpio.c
index 70bfa57..f8cb571 100644
--- a/arch/arm/mach-gemini/gpio.c
+++ b/arch/arm/mach-gemini/gpio.c
@@ -21,9 +21,9 @@
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
-#include <mach/gpio.h>
 
 #define GPIO_BASE(x)		IO_ADDRESS(GEMINI_GPIO_BASE(x))
+#define irq_to_gpio(x)		((x) - GPIO_IRQ_BASE)
 
 /* GPIO registers definition */
 #define GPIO_DATA_OUT		0x0
diff --git a/arch/arm/mach-gemini/include/mach/gpio.h b/arch/arm/mach-gemini/include/mach/gpio.h
deleted file mode 100644
index 40a0527..0000000
--- a/arch/arm/mach-gemini/include/mach/gpio.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Gemini gpiolib specific defines
- *
- * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __MACH_GPIO_H__
-#define __MACH_GPIO_H__
-
-#include <mach/irqs.h>
-
-#define gpio_to_irq(x)	((x) + GPIO_IRQ_BASE)
-#define irq_to_gpio(x)	((x) - GPIO_IRQ_BASE)
-
-#endif /* __MACH_GPIO_H__ */
diff --git a/arch/arm/mach-gemini/time.c b/arch/arm/mach-gemini/time.c
index 21dc5a8..0a63c4d2 100644
--- a/arch/arm/mach-gemini/time.c
+++ b/arch/arm/mach-gemini/time.c
@@ -13,6 +13,8 @@
 #include <mach/hardware.h>
 #include <mach/global_reg.h>
 #include <asm/mach/time.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
 
 /*
  * Register definitions for the timers
@@ -33,19 +35,89 @@
 #define TIMER_3_CR_CLOCK		(1 << 7)
 #define TIMER_3_CR_INT			(1 << 8)
 
+static unsigned int tick_rate;
+
+static int gemini_timer_set_next_event(unsigned long cycles,
+				       struct clock_event_device *evt)
+{
+	u32 cr;
+
+	cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+
+	/* This may be overdoing it, feel free to test without this */
+	cr &= ~TIMER_2_CR_ENABLE;
+	cr &= ~TIMER_2_CR_INT;
+	writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+
+	/* Set next event */
+	writel(cycles, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE)));
+	writel(cycles, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE)));
+	cr |= TIMER_2_CR_ENABLE;
+	cr |= TIMER_2_CR_INT;
+	writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+
+	return 0;
+}
+
+static void gemini_timer_set_mode(enum clock_event_mode mode,
+				  struct clock_event_device *evt)
+{
+	u32 period = DIV_ROUND_CLOSEST(tick_rate, HZ);
+	u32 cr;
+
+	switch (mode) {
+        case CLOCK_EVT_MODE_PERIODIC:
+		/* Start the timer */
+		writel(period,
+		       TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE)));
+		writel(period,
+		       TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE)));
+		cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+		cr |= TIMER_2_CR_ENABLE;
+		cr |= TIMER_2_CR_INT;
+		writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_UNUSED:
+        case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_RESUME:
+		/*
+		 * Disable also for oneshot: the set_next() call will
+		 * arm the timer instead.
+		 */
+		cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+		cr &= ~TIMER_2_CR_ENABLE;
+		cr &= ~TIMER_2_CR_INT;
+		writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+		break;
+	default:
+                break;
+	}
+}
+
+/* Use TIMER2 as clock event */
+static struct clock_event_device gemini_clockevent = {
+	.name		= "TIMER2",
+	.rating		= 300, /* Reasonably fast and accurate clock event */
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.set_next_event	= gemini_timer_set_next_event,
+	.set_mode	= gemini_timer_set_mode,
+};
+
 /*
  * IRQ handler for the timer
  */
 static irqreturn_t gemini_timer_interrupt(int irq, void *dev_id)
 {
-	timer_tick();
+	struct clock_event_device *evt = &gemini_clockevent;
 
+	evt->event_handler(evt);
 	return IRQ_HANDLED;
 }
 
 static struct irqaction gemini_timer_irq = {
 	.name		= "Gemini Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER,
+	.flags		= IRQF_TIMER,
 	.handler	= gemini_timer_interrupt,
 };
 
@@ -54,9 +126,9 @@
  */
 void __init gemini_timer_init(void)
 {
-	unsigned int tick_rate, reg_v;
+	u32 reg_v;
 
-	reg_v = __raw_readl(IO_ADDRESS(GEMINI_GLOBAL_BASE + GLOBAL_STATUS));
+	reg_v = readl(IO_ADDRESS(GEMINI_GLOBAL_BASE + GLOBAL_STATUS));
 	tick_rate = REG_TO_AHB_SPEED(reg_v) * 1000000;
 
 	printk(KERN_INFO "Bus: %dMHz", tick_rate / 1000000);
@@ -82,8 +154,17 @@
 	 * Make irqs happen for the system timer
 	 */
 	setup_irq(IRQ_TIMER2, &gemini_timer_irq);
-	/* Start the timer */
-	__raw_writel(tick_rate / HZ, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE)));
-	__raw_writel(tick_rate / HZ, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE)));
-	__raw_writel(TIMER_2_CR_ENABLE | TIMER_2_CR_INT, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+
+	/* Enable and use TIMER1 as clock source */
+	writel(0xffffffff, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER1_BASE)));
+	writel(0xffffffff, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER1_BASE)));
+	writel(TIMER_1_CR_ENABLE, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+	if (clocksource_mmio_init(TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER1_BASE)),
+				  "TIMER1", tick_rate, 300, 32,
+				  clocksource_mmio_readl_up))
+		pr_err("timer: failed to initialize gemini clock source\n");
+
+	/* Configure and register the clockevent */
+	clockevents_config_and_register(&gemini_clockevent, tick_rate,
+					1, 0xffffffff);
 }
diff --git a/arch/arm/mach-highbank/Kconfig b/arch/arm/mach-highbank/Kconfig
index 8e8437d..fe98df4 100644
--- a/arch/arm/mach-highbank/Kconfig
+++ b/arch/arm/mach-highbank/Kconfig
@@ -10,9 +10,9 @@
 	select ARM_ERRATA_775420
 	select ARM_ERRATA_798181
 	select ARM_GIC
+	select ARM_PSCI
 	select ARM_TIMER_SP804
 	select CACHE_L2X0
-	select CLKDEV_LOOKUP
 	select COMMON_CLK
 	select CPU_V7
 	select GENERIC_CLOCKEVENTS
diff --git a/arch/arm/mach-highbank/Makefile b/arch/arm/mach-highbank/Makefile
index 8a1ef57..55840f4 100644
--- a/arch/arm/mach-highbank/Makefile
+++ b/arch/arm/mach-highbank/Makefile
@@ -3,6 +3,4 @@
 plus_sec := $(call as-instr,.arch_extension sec,+sec)
 AFLAGS_smc.o				:=-Wa,-march=armv7-a$(plus_sec)
 
-obj-$(CONFIG_SMP)			+= platsmp.o
-obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o
 obj-$(CONFIG_PM_SLEEP)			+= pm.o
diff --git a/arch/arm/mach-highbank/core.h b/arch/arm/mach-highbank/core.h
index aea1ec5..7ec5edc 100644
--- a/arch/arm/mach-highbank/core.h
+++ b/arch/arm/mach-highbank/core.h
@@ -3,7 +3,6 @@
 
 #include <linux/reboot.h>
 
-extern void highbank_set_cpu_jump(int cpu, void *jump_addr);
 extern void highbank_restart(enum reboot_mode, const char *);
 extern void __iomem *scu_base_addr;
 
@@ -14,8 +13,5 @@
 #endif
 
 extern void highbank_smc1(int fn, int arg);
-extern void highbank_cpu_die(unsigned int cpu);
-
-extern struct smp_operations highbank_smp_ops;
 
 #endif
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
index 8e63ccd..b3d7e56 100644
--- a/arch/arm/mach-highbank/highbank.c
+++ b/arch/arm/mach-highbank/highbank.c
@@ -24,11 +24,9 @@
 #include <linux/of_platform.h>
 #include <linux/of_address.h>
 #include <linux/amba/bus.h>
-#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
 
-#include <asm/cacheflush.h>
-#include <asm/cputype.h>
-#include <asm/smp_plat.h>
+#include <asm/psci.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -49,17 +47,6 @@
 	scu_base_addr = ioremap(base, SZ_4K);
 }
 
-#define HB_JUMP_TABLE_PHYS(cpu)		(0x40 + (0x10 * (cpu)))
-#define HB_JUMP_TABLE_VIRT(cpu)		phys_to_virt(HB_JUMP_TABLE_PHYS(cpu))
-
-void highbank_set_cpu_jump(int cpu, void *jump_addr)
-{
-	cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(cpu), 0);
-	writel(virt_to_phys(jump_addr), HB_JUMP_TABLE_VIRT(cpu));
-	__cpuc_flush_dcache_area(HB_JUMP_TABLE_VIRT(cpu), 16);
-	outer_clean_range(HB_JUMP_TABLE_PHYS(cpu),
-			  HB_JUMP_TABLE_PHYS(cpu) + 15);
-}
 
 static void highbank_l2x0_disable(void)
 {
@@ -83,20 +70,6 @@
 	}
 }
 
-static void __init highbank_timer_init(void)
-{
-	struct device_node *np;
-
-	/* Map system registers */
-	np = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs");
-	sregs_base = of_iomap(np, 0);
-	WARN_ON(!sregs_base);
-
-	of_clk_init(NULL);
-
-	clocksource_of_init();
-}
-
 static void highbank_power_off(void)
 {
 	highbank_set_pwr_shutdown();
@@ -153,8 +126,19 @@
 	.notifier_call = highbank_platform_notifier,
 };
 
+static struct platform_device highbank_cpuidle_device = {
+	.name = "cpuidle-calxeda",
+};
+
 static void __init highbank_init(void)
 {
+	struct device_node *np;
+
+	/* Map system registers */
+	np = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs");
+	sregs_base = of_iomap(np, 0);
+	WARN_ON(!sregs_base);
+
 	pm_power_off = highbank_power_off;
 	highbank_pm_init();
 
@@ -162,6 +146,9 @@
 	bus_register_notifier(&amba_bustype, &highbank_amba_nb);
 
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+	if (psci_ops.cpu_suspend)
+		platform_device_register(&highbank_cpuidle_device);
 }
 
 static const char *highbank_match[] __initconst = {
@@ -174,9 +161,7 @@
 #if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
 	.dma_zone_size	= (4ULL * SZ_1G),
 #endif
-	.smp		= smp_ops(highbank_smp_ops),
 	.init_irq	= highbank_init_irq,
-	.init_time	= highbank_timer_init,
 	.init_machine	= highbank_init,
 	.dt_compat	= highbank_match,
 	.restart	= highbank_restart,
diff --git a/arch/arm/mach-highbank/hotplug.c b/arch/arm/mach-highbank/hotplug.c
deleted file mode 100644
index a019e4e..0000000
--- a/arch/arm/mach-highbank/hotplug.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2011 Calxeda, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-#include <linux/kernel.h>
-#include <asm/cacheflush.h>
-
-#include "core.h"
-#include "sysregs.h"
-
-extern void secondary_startup(void);
-
-/*
- * platform-specific code to shutdown a CPU
- *
- */
-void __ref highbank_cpu_die(unsigned int cpu)
-{
-	highbank_set_cpu_jump(cpu, phys_to_virt(0));
-
-	flush_cache_louis();
-	highbank_set_core_pwr();
-
-	while (1)
-		cpu_do_idle();
-}
diff --git a/arch/arm/mach-highbank/platsmp.c b/arch/arm/mach-highbank/platsmp.c
deleted file mode 100644
index 32d75cf5..0000000
--- a/arch/arm/mach-highbank/platsmp.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2010-2011 Calxeda, Inc.
- * Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/io.h>
-
-#include <asm/smp_scu.h>
-
-#include "core.h"
-
-extern void secondary_startup(void);
-
-static int highbank_boot_secondary(unsigned int cpu, struct task_struct *idle)
-{
-	highbank_set_cpu_jump(cpu, secondary_startup);
-	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
-	return 0;
-}
-
-/*
- * Initialise the CPU possible map early - this describes the CPUs
- * which may be present or become present in the system.
- */
-static void __init highbank_smp_init_cpus(void)
-{
-	unsigned int i, ncores = 4;
-
-	/* sanity check */
-	if (ncores > NR_CPUS) {
-		printk(KERN_WARNING
-		       "highbank: no. of cores (%d) greater than configured "
-		       "maximum of %d - clipping\n",
-		       ncores, NR_CPUS);
-		ncores = NR_CPUS;
-	}
-
-	for (i = 0; i < ncores; i++)
-		set_cpu_possible(i, true);
-}
-
-static void __init highbank_smp_prepare_cpus(unsigned int max_cpus)
-{
-	if (scu_base_addr)
-		scu_enable(scu_base_addr);
-}
-
-struct smp_operations highbank_smp_ops __initdata = {
-	.smp_init_cpus		= highbank_smp_init_cpus,
-	.smp_prepare_cpus	= highbank_smp_prepare_cpus,
-	.smp_boot_secondary	= highbank_boot_secondary,
-#ifdef CONFIG_HOTPLUG_CPU
-	.cpu_die		= highbank_cpu_die,
-#endif
-};
diff --git a/arch/arm/mach-highbank/pm.c b/arch/arm/mach-highbank/pm.c
index 04eddb4..7f2bd85 100644
--- a/arch/arm/mach-highbank/pm.c
+++ b/arch/arm/mach-highbank/pm.c
@@ -16,27 +16,19 @@
 
 #include <linux/cpu_pm.h>
 #include <linux/init.h>
-#include <linux/io.h>
 #include <linux/suspend.h>
 
-#include <asm/cacheflush.h>
-#include <asm/proc-fns.h>
 #include <asm/suspend.h>
-
-#include "core.h"
-#include "sysregs.h"
+#include <asm/psci.h>
 
 static int highbank_suspend_finish(unsigned long val)
 {
-	outer_flush_all();
-	outer_disable();
+	const struct psci_power_state ps = {
+		.type = PSCI_POWER_STATE_TYPE_POWER_DOWN,
+		.affinity_level = 1,
+	};
 
-	highbank_set_pwr_suspend();
-
-	cpu_do_idle();
-
-	highbank_clear_pwr_request();
-	return 0;
+	return psci_ops.cpu_suspend(ps, __pa(cpu_resume));
 }
 
 static int highbank_pm_enter(suspend_state_t state)
@@ -44,15 +36,11 @@
 	cpu_pm_enter();
 	cpu_cluster_pm_enter();
 
-	highbank_set_cpu_jump(0, cpu_resume);
 	cpu_suspend(0, highbank_suspend_finish);
 
 	cpu_cluster_pm_exit();
 	cpu_pm_exit();
 
-	highbank_smc1(0x102, 0x1);
-	if (scu_base_addr)
-		scu_enable(scu_base_addr);
 	return 0;
 }
 
@@ -63,5 +51,8 @@
 
 void __init highbank_pm_init(void)
 {
+	if (!psci_ops.cpu_suspend)
+		return;
+
 	suspend_set_ops(&highbank_pm_ops);
 }
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 29a8af6..7a6e6f7 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -4,13 +4,14 @@
 	select ARM_CPU_SUSPEND if PM
 	select ARM_PATCH_PHYS_VIRT
 	select AUTO_ZRELADDR if !ZBOOT_ROM
-	select CLKDEV_LOOKUP
 	select CLKSRC_MMIO
+	select COMMON_CLK
 	select GENERIC_ALLOCATOR
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_IRQ_CHIP
 	select MIGHT_HAVE_CACHE_L2X0 if ARCH_MULTI_V6_V7
 	select MULTI_IRQ_HANDLER
+	select SOC_BUS
 	select SPARSE_IRQ
 	select USE_OF
 	help
@@ -24,7 +25,7 @@
 	help
 	  Select this if you want to use prioritized IRQ handling.
 	  This feature prevents higher priority ISR to be interrupted
-	  by lower priority IRQ even IRQF_DISABLED flag is not set.
+	  by lower priority IRQ.
 	  This may be useful in embedded applications, where are strong
 	  requirements for timing.
 	  Say N here, unless you have a specialized requirement.
@@ -92,14 +93,12 @@
 config SOC_IMX1
 	bool
 	select ARCH_MX1
-	select COMMON_CLK
 	select CPU_ARM920T
 	select IMX_HAVE_IOMUX_V1
 	select MXC_AVIC
 
 config SOC_IMX21
 	bool
-	select COMMON_CLK
 	select CPU_ARM926T
 	select IMX_HAVE_IOMUX_V1
 	select MXC_AVIC
@@ -108,7 +107,6 @@
 	bool
 	select ARCH_MX25
 	select ARCH_MXC_IOMUX_V3
-	select COMMON_CLK
 	select CPU_ARM926T
 	select MXC_AVIC
 
@@ -116,7 +114,6 @@
 	bool
 	select ARCH_HAS_CPUFREQ
 	select ARCH_HAS_OPP
-	select COMMON_CLK
 	select CPU_ARM926T
 	select IMX_HAVE_IOMUX_V1
 	select MACH_MX27
@@ -124,7 +121,6 @@
 
 config SOC_IMX31
 	bool
-	select COMMON_CLK
 	select CPU_V6
 	select IMX_HAVE_PLATFORM_MXC_RNGA
 	select MXC_AVIC
@@ -133,7 +129,6 @@
 config SOC_IMX35
 	bool
 	select ARCH_MXC_IOMUX_V3
-	select COMMON_CLK
 	select CPU_V6K
 	select HAVE_EPIT
 	select MXC_AVIC
@@ -144,7 +139,6 @@
 	select ARCH_HAS_CPUFREQ
 	select ARCH_HAS_OPP
 	select ARCH_MXC_IOMUX_V3
-	select COMMON_CLK
 	select CPU_V7
 	select MXC_TZIC
 
@@ -791,7 +785,6 @@
 	select ARM_ERRATA_764369 if SMP
 	select ARM_ERRATA_775420
 	select ARM_GIC
-	select COMMON_CLK
 	select CPU_V7
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
@@ -801,6 +794,8 @@
 	select HAVE_IMX_SRC
 	select HAVE_SMP
 	select MFD_SYSCON
+	select MIGHT_HAVE_PCI
+	select PCI_DOMAINS if PCI
 	select PINCTRL
 	select PINCTRL_IMX6Q
 	select PL310_ERRATA_588369 if CACHE_PL310
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 5383c58..bbe1f5b 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -102,6 +102,8 @@
 
 ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o
+# i.MX6SL reuses pm-imx6q.c
+obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o
 endif
 
 # i.MX5 based machines
diff --git a/arch/arm/mach-imx/anatop.c b/arch/arm/mach-imx/anatop.c
index ad3b755..4a40bbb4 100644
--- a/arch/arm/mach-imx/anatop.c
+++ b/arch/arm/mach-imx/anatop.c
@@ -16,6 +16,7 @@
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
 #include "common.h"
+#include "hardware.h"
 
 #define REG_SET		0x4
 #define REG_CLR		0x8
@@ -26,6 +27,7 @@
 #define ANADIG_USB1_CHRG_DETECT	0x1b0
 #define ANADIG_USB2_CHRG_DETECT	0x210
 #define ANADIG_DIGPROG		0x260
+#define ANADIG_DIGPROG_IMX6SL	0x280
 
 #define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG	0x40000
 #define BM_ANADIG_REG_CORE_FET_ODRIVE		0x20000000
@@ -76,21 +78,38 @@
 		BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B);
 }
 
-u32 imx_anatop_get_digprog(void)
+void __init imx_init_revision_from_anatop(void)
 {
 	struct device_node *np;
 	void __iomem *anatop_base;
-	static u32 digprog;
-
-	if (digprog)
-		return digprog;
+	unsigned int revision;
+	u32 digprog;
+	u16 offset = ANADIG_DIGPROG;
 
 	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
 	anatop_base = of_iomap(np, 0);
 	WARN_ON(!anatop_base);
-	digprog = readl_relaxed(anatop_base + ANADIG_DIGPROG);
+	if (of_device_is_compatible(np, "fsl,imx6sl-anatop"))
+		offset = ANADIG_DIGPROG_IMX6SL;
+	digprog = readl_relaxed(anatop_base + offset);
+	iounmap(anatop_base);
 
-	return digprog;
+	switch (digprog & 0xff) {
+	case 0:
+		revision = IMX_CHIP_REVISION_1_0;
+		break;
+	case 1:
+		revision = IMX_CHIP_REVISION_1_1;
+		break;
+	case 2:
+		revision = IMX_CHIP_REVISION_1_2;
+		break;
+	default:
+		revision = IMX_CHIP_REVISION_UNKNOWN;
+	}
+
+	mxc_set_cpu_type(digprog >> 16 & 0xff);
+	imx_set_soc_revision(revision);
 }
 
 void __init imx_anatop_init(void)
diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c
index 7c0dc45..ce37af2 100644
--- a/arch/arm/mach-imx/clk-imx51-imx53.c
+++ b/arch/arm/mach-imx/clk-imx51-imx53.c
@@ -11,8 +11,12 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/clkdev.h>
+#include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include "crm-regs-imx5.h"
 #include "clk.h"
@@ -131,8 +135,6 @@
 {
 	int i;
 
-	of_clk_init(NULL);
-
 	clk[dummy] = imx_clk_fixed("dummy", 0);
 	clk[ckil] = imx_obtain_fixed_clock("ckil", rate_ckil);
 	clk[osc] = imx_obtain_fixed_clock("osc", rate_osc);
@@ -465,12 +467,17 @@
 	return 0;
 }
 
-int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
-			unsigned long rate_ckih1, unsigned long rate_ckih2)
+static void __init mx51_clocks_init_dt(struct device_node *np)
 {
-	int i;
+	mx51_clocks_init(0, 0, 0, 0);
+}
+CLK_OF_DECLARE(imx51_ccm, "fsl,imx51-ccm", mx51_clocks_init_dt);
+
+static void __init mx53_clocks_init(struct device_node *np)
+{
+	int i, irq;
 	unsigned long r;
-	struct device_node *np;
+	void __iomem *base;
 
 	clk[pll1_sw] = imx_clk_pllv2("pll1_sw", "osc", MX53_DPLL1_BASE);
 	clk[pll2_sw] = imx_clk_pllv2("pll2_sw", "osc", MX53_DPLL2_BASE);
@@ -529,12 +536,11 @@
 			pr_err("i.MX53 clk %d: register failed with %ld\n",
 				i, PTR_ERR(clk[i]));
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx53-ccm");
 	clk_data.clks = clk;
 	clk_data.clk_num = ARRAY_SIZE(clk);
 	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
-	mx5_clocks_common_init(rate_ckil, rate_osc, rate_ckih1, rate_ckih2);
+	mx5_clocks_common_init(0, 0, 0, 0);
 
 	clk_register_clkdev(clk[vpu_gate], NULL, "imx53-vpu.0");
 	clk_register_clkdev(clk[i2c3_gate], NULL, "imx21-i2c.2");
@@ -557,9 +563,6 @@
 	clk_set_rate(clk[esdhc_a_podf], 200000000);
 	clk_set_rate(clk[esdhc_b_podf], 200000000);
 
-	/* System timer */
-	mxc_timer_init(MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR), MX53_INT_GPT);
-
 	clk_prepare_enable(clk[iim_gate]);
 	imx_print_silicon_rev("i.MX53", mx53_revision());
 	clk_disable_unprepare(clk[iim_gate]);
@@ -567,15 +570,10 @@
 	r = clk_round_rate(clk[usboh3_per_gate], 54000000);
 	clk_set_rate(clk[usboh3_per_gate], r);
 
-	return 0;
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx53-gpt");
+	base = of_iomap(np, 0);
+	WARN_ON(!base);
+	irq = irq_of_parse_and_map(np, 0);
+	mxc_timer_init(base, irq);
 }
-
-int __init mx51_clocks_init_dt(void)
-{
-	return mx51_clocks_init(0, 0, 0, 0);
-}
-
-int __init mx53_clocks_init_dt(void)
-{
-	return mx53_clocks_init(0, 0, 0, 0);
-}
+CLK_OF_DECLARE(imx53_ccm, "fsl,imx53-ccm", mx53_clocks_init);
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 9181a24..d756d91 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -14,7 +14,6 @@
 #include <linux/types.h>
 #include <linux/clk.h>
 #include <linux/clkdev.h>
-#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -25,155 +24,6 @@
 #include "common.h"
 #include "hardware.h"
 
-#define CCR				0x0
-#define BM_CCR_WB_COUNT			(0x7 << 16)
-#define BM_CCR_RBC_BYPASS_COUNT		(0x3f << 21)
-#define BM_CCR_RBC_EN			(0x1 << 27)
-
-#define CCGR0				0x68
-#define CCGR1				0x6c
-#define CCGR2				0x70
-#define CCGR3				0x74
-#define CCGR4				0x78
-#define CCGR5				0x7c
-#define CCGR6				0x80
-#define CCGR7				0x84
-
-#define CLPCR				0x54
-#define BP_CLPCR_LPM			0
-#define BM_CLPCR_LPM			(0x3 << 0)
-#define BM_CLPCR_BYPASS_PMIC_READY	(0x1 << 2)
-#define BM_CLPCR_ARM_CLK_DIS_ON_LPM	(0x1 << 5)
-#define BM_CLPCR_SBYOS			(0x1 << 6)
-#define BM_CLPCR_DIS_REF_OSC		(0x1 << 7)
-#define BM_CLPCR_VSTBY			(0x1 << 8)
-#define BP_CLPCR_STBY_COUNT		9
-#define BM_CLPCR_STBY_COUNT		(0x3 << 9)
-#define BM_CLPCR_COSC_PWRDOWN		(0x1 << 11)
-#define BM_CLPCR_WB_PER_AT_LPM		(0x1 << 16)
-#define BM_CLPCR_WB_CORE_AT_LPM		(0x1 << 17)
-#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS	(0x1 << 19)
-#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS	(0x1 << 21)
-#define BM_CLPCR_MASK_CORE0_WFI		(0x1 << 22)
-#define BM_CLPCR_MASK_CORE1_WFI		(0x1 << 23)
-#define BM_CLPCR_MASK_CORE2_WFI		(0x1 << 24)
-#define BM_CLPCR_MASK_CORE3_WFI		(0x1 << 25)
-#define BM_CLPCR_MASK_SCU_IDLE		(0x1 << 26)
-#define BM_CLPCR_MASK_L2CC_IDLE		(0x1 << 27)
-
-#define CGPR				0x64
-#define BM_CGPR_CHICKEN_BIT		(0x1 << 17)
-
-static void __iomem *ccm_base;
-
-void imx6q_set_chicken_bit(void)
-{
-	u32 val = readl_relaxed(ccm_base + CGPR);
-
-	val |= BM_CGPR_CHICKEN_BIT;
-	writel_relaxed(val, ccm_base + CGPR);
-}
-
-static void imx6q_enable_rbc(bool enable)
-{
-	u32 val;
-	static bool last_rbc_mode;
-
-	if (last_rbc_mode == enable)
-		return;
-	/*
-	 * need to mask all interrupts in GPC before
-	 * operating RBC configurations
-	 */
-	imx_gpc_mask_all();
-
-	/* configure RBC enable bit */
-	val = readl_relaxed(ccm_base + CCR);
-	val &= ~BM_CCR_RBC_EN;
-	val |= enable ? BM_CCR_RBC_EN : 0;
-	writel_relaxed(val, ccm_base + CCR);
-
-	/* configure RBC count */
-	val = readl_relaxed(ccm_base + CCR);
-	val &= ~BM_CCR_RBC_BYPASS_COUNT;
-	val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0;
-	writel(val, ccm_base + CCR);
-
-	/*
-	 * need to delay at least 2 cycles of CKIL(32K)
-	 * due to hardware design requirement, which is
-	 * ~61us, here we use 65us for safe
-	 */
-	udelay(65);
-
-	/* restore GPC interrupt mask settings */
-	imx_gpc_restore_all();
-
-	last_rbc_mode = enable;
-}
-
-static void imx6q_enable_wb(bool enable)
-{
-	u32 val;
-	static bool last_wb_mode;
-
-	if (last_wb_mode == enable)
-		return;
-
-	/* configure well bias enable bit */
-	val = readl_relaxed(ccm_base + CLPCR);
-	val &= ~BM_CLPCR_WB_PER_AT_LPM;
-	val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0;
-	writel_relaxed(val, ccm_base + CLPCR);
-
-	/* configure well bias count */
-	val = readl_relaxed(ccm_base + CCR);
-	val &= ~BM_CCR_WB_COUNT;
-	val |= enable ? BM_CCR_WB_COUNT : 0;
-	writel_relaxed(val, ccm_base + CCR);
-
-	last_wb_mode = enable;
-}
-
-int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
-{
-	u32 val = readl_relaxed(ccm_base + CLPCR);
-
-	val &= ~BM_CLPCR_LPM;
-	switch (mode) {
-	case WAIT_CLOCKED:
-		imx6q_enable_wb(false);
-		imx6q_enable_rbc(false);
-		break;
-	case WAIT_UNCLOCKED:
-		val |= 0x1 << BP_CLPCR_LPM;
-		val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM;
-		break;
-	case STOP_POWER_ON:
-		val |= 0x2 << BP_CLPCR_LPM;
-		break;
-	case WAIT_UNCLOCKED_POWER_OFF:
-		val |= 0x1 << BP_CLPCR_LPM;
-		val &= ~BM_CLPCR_VSTBY;
-		val &= ~BM_CLPCR_SBYOS;
-		break;
-	case STOP_POWER_OFF:
-		val |= 0x2 << BP_CLPCR_LPM;
-		val |= 0x3 << BP_CLPCR_STBY_COUNT;
-		val |= BM_CLPCR_VSTBY;
-		val |= BM_CLPCR_SBYOS;
-		imx6q_enable_wb(true);
-		imx6q_enable_rbc(true);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	writel_relaxed(val, ccm_base + CLPCR);
-
-	return 0;
-}
-
 static const char *step_sels[]	= { "osc", "pll2_pfd2_396m", };
 static const char *pll1_sw_sels[]	= { "pll1_sys", "step", };
 static const char *periph_pre_sels[]	= { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", };
@@ -182,7 +32,7 @@
 static const char *periph_sels[]	= { "periph_pre", "periph_clk2", };
 static const char *periph2_sels[]	= { "periph2_pre", "periph2_clk2", };
 static const char *axi_sels[]		= { "periph", "pll2_pfd2_396m", "periph", "pll3_pfd1_540m", };
-static const char *audio_sels[]	= { "pll4_post_div", "pll3_pfd2_508m", "pll3_pfd3_454m", "pll3_usb_otg", };
+static const char *audio_sels[]	= { "pll4_audio_div", "pll3_pfd2_508m", "pll3_pfd3_454m", "pll3_usb_otg", };
 static const char *gpu_axi_sels[]	= { "axi", "ahb", };
 static const char *gpu2d_core_sels[]	= { "axi", "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", };
 static const char *gpu3d_core_sels[]	= { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd2_396m", };
@@ -196,7 +46,7 @@
 static const char *ipu2_di1_sels[]	= { "ipu2_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
 static const char *hsi_tx_sels[]	= { "pll3_120m", "pll2_pfd2_396m", };
 static const char *pcie_axi_sels[]	= { "axi", "ahb", };
-static const char *ssi_sels[]		= { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_post_div", };
+static const char *ssi_sels[]		= { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_audio_div", };
 static const char *usdhc_sels[]	= { "pll2_pfd2_396m", "pll2_pfd0_352m", };
 static const char *enfc_sels[]	= { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", };
 static const char *emi_sels[]		= { "pll2_pfd2_396m", "pll3_usb_otg", "axi", "pll2_pfd0_352m", };
@@ -205,7 +55,7 @@
 static const char *vpu_axi_sels[]	= { "axi", "pll2_pfd2_396m", "pll2_pfd0_352m", };
 static const char *cko1_sels[]	= { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div",
 				    "dummy", "axi", "enfc", "ipu1_di0", "ipu1_di1", "ipu2_di0",
-				    "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_post_div", };
+				    "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_audio_div", };
 static const char *cko2_sels[] = {
 	"mmdc_ch0_axi", "mmdc_ch1_axi", "usdhc4", "usdhc1",
 	"gpu2d_axi", "dummy", "ecspi_root", "gpu3d_axi",
@@ -217,6 +67,11 @@
 	"uart_serial", "spdif", "asrc", "hsi_tx",
 };
 static const char *cko_sels[] = { "cko1", "cko2", };
+static const char *lvds_sels[] = {
+	"dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
+	"pll4_audio", "pll5_video", "pll8_mlb", "enet_ref",
+	"pcie_ref", "sata_ref",
+};
 
 enum mx6q_clks {
 	dummy, ckil, ckih, osc, pll2_pfd0_352m, pll2_pfd1_594m, pll2_pfd2_396m,
@@ -251,7 +106,8 @@
 	ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5,
 	sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate,
 	usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow,
-	spdif, cko2_sel, cko2_podf, cko2, cko, vdoa, clk_max
+	spdif, cko2_sel, cko2_podf, cko2, cko, vdoa, pll4_audio_div,
+	lvds1_sel, lvds2_sel, lvds1_gate, lvds2_gate, clk_max
 };
 
 static struct clk *clk[clk_max];
@@ -300,7 +156,7 @@
 	WARN_ON(!base);
 
 	/* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */
-	if (cpu_is_imx6q() && imx6q_revision() == IMX_CHIP_REVISION_1_0) {
+	if (cpu_is_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_1_0) {
 		post_div_table[1].div = 1;
 		post_div_table[2].div = 1;
 		video_div_table[1].div = 1;
@@ -342,6 +198,18 @@
 			base + 0xe0, 0, 2, 0, clk_enet_ref_table,
 			&imx_ccm_lock);
 
+	clk[lvds1_sel] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
+	clk[lvds2_sel] = imx_clk_mux("lvds2_sel", base + 0x160, 5, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
+
+	/*
+	 * lvds1_gate and lvds2_gate are pseudo-gates.  Both can be
+	 * independently configured as clock inputs or outputs.  We treat
+	 * the "output_enable" bit as a gate, even though it's really just
+	 * enabling clock output.
+	 */
+	clk[lvds1_gate] = imx_clk_gate("lvds1_gate", "dummy", base + 0x160, 10);
+	clk[lvds2_gate] = imx_clk_gate("lvds2_gate", "dummy", base + 0x160, 11);
+
 	/*                                name              parent_name        reg       idx */
 	clk[pll2_pfd0_352m] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus",     base + 0x100, 0);
 	clk[pll2_pfd1_594m] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus",     base + 0x100, 1);
@@ -359,13 +227,15 @@
 	clk[twd]       = imx_clk_fixed_factor("twd",       "arm",            1, 2);
 
 	clk[pll4_post_div] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
+	clk[pll4_audio_div] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock);
 	clk[pll5_post_div] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
 	clk[pll5_video_div] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
 
 	np = ccm_node;
 	base = of_iomap(np, 0);
 	WARN_ON(!base);
-	ccm_base = base;
+
+	imx6q_pm_set_ccm_base(base);
 
 	/*                                  name                reg       shift width parent_names     num_parents */
 	clk[step]             = imx_clk_mux("step",	        base + 0xc,  8,  1, step_sels,	       ARRAY_SIZE(step_sels));
@@ -573,7 +443,8 @@
 	clk_register_clkdev(clk[pll4_post_div], "pll4_post_div", NULL);
 	clk_register_clkdev(clk[pll4_audio], "pll4_audio", NULL);
 
-	if ((imx6q_revision() != IMX_CHIP_REVISION_1_0) || cpu_is_imx6dl()) {
+	if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) ||
+	    cpu_is_imx6dl()) {
 		clk_set_parent(clk[ldb_di0_sel], clk[pll5_video_div]);
 		clk_set_parent(clk[ldb_di1_sel], clk[pll5_video_div]);
 	}
@@ -603,8 +474,9 @@
 	if (ret)
 		pr_warn("failed to set up CLKO: %d\n", ret);
 
-	/* Set initial power mode */
-	imx6q_set_lpm(WAIT_CLOCKED);
+	/* All existing boards with PCIe use LVDS1 */
+	if (IS_ENABLED(CONFIG_PCI_IMX6))
+		clk_set_parent(clk[lvds1_sel], clk[sata_ref]);
 
 	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
 	base = of_iomap(np, 0);
diff --git a/arch/arm/mach-imx/clk-imx6sl.c b/arch/arm/mach-imx/clk-imx6sl.c
index a5c3c5d..c0c4ef5 100644
--- a/arch/arm/mach-imx/clk-imx6sl.c
+++ b/arch/arm/mach-imx/clk-imx6sl.c
@@ -127,6 +127,9 @@
 	base = of_iomap(np, 0);
 	WARN_ON(!base);
 
+	/* Reuse imx6q pm code */
+	imx6q_pm_set_ccm_base(base);
+
 	/*                                              name                reg       shift width parent_names     num_parents */
 	clks[IMX6SL_CLK_STEP]             = imx_clk_mux("step",             base + 0xc,  8,  1, step_sels,         ARRAY_SIZE(step_sels));
 	clks[IMX6SL_CLK_PLL1_SW]          = imx_clk_mux("pll1_sw",          base + 0xc,  2,  1, pll1_sw_sels,      ARRAY_SIZE(pll1_sw_sels));
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 4517fd7..7cbe22d 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -13,74 +13,73 @@
 
 #include <linux/reboot.h>
 
+struct irq_data;
 struct platform_device;
 struct pt_regs;
 struct clk;
 enum mxc_cpu_pwr_mode;
 
-extern void mx1_map_io(void);
-extern void mx21_map_io(void);
-extern void mx25_map_io(void);
-extern void mx27_map_io(void);
-extern void mx31_map_io(void);
-extern void mx35_map_io(void);
-extern void mx51_map_io(void);
-extern void mx53_map_io(void);
-extern void imx1_init_early(void);
-extern void imx21_init_early(void);
-extern void imx25_init_early(void);
-extern void imx27_init_early(void);
-extern void imx31_init_early(void);
-extern void imx35_init_early(void);
-extern void imx51_init_early(void);
-extern void imx53_init_early(void);
-extern void mxc_init_irq(void __iomem *);
-extern void tzic_init_irq(void __iomem *);
-extern void mx1_init_irq(void);
-extern void mx21_init_irq(void);
-extern void mx25_init_irq(void);
-extern void mx27_init_irq(void);
-extern void mx31_init_irq(void);
-extern void mx35_init_irq(void);
-extern void mx51_init_irq(void);
-extern void mx53_init_irq(void);
-extern void imx1_soc_init(void);
-extern void imx21_soc_init(void);
-extern void imx25_soc_init(void);
-extern void imx27_soc_init(void);
-extern void imx31_soc_init(void);
-extern void imx35_soc_init(void);
-extern void imx51_soc_init(void);
-extern void imx51_init_late(void);
-extern void imx53_init_late(void);
-extern void epit_timer_init(void __iomem *base, int irq);
-extern void mxc_timer_init(void __iomem *, int);
-extern int mx1_clocks_init(unsigned long fref);
-extern int mx21_clocks_init(unsigned long lref, unsigned long fref);
-extern int mx25_clocks_init(void);
-extern int mx27_clocks_init(unsigned long fref);
-extern int mx31_clocks_init(unsigned long fref);
-extern int mx35_clocks_init(void);
-extern int mx51_clocks_init(unsigned long ckil, unsigned long osc,
+void mx1_map_io(void);
+void mx21_map_io(void);
+void mx25_map_io(void);
+void mx27_map_io(void);
+void mx31_map_io(void);
+void mx35_map_io(void);
+void mx51_map_io(void);
+void mx53_map_io(void);
+void imx1_init_early(void);
+void imx21_init_early(void);
+void imx25_init_early(void);
+void imx27_init_early(void);
+void imx31_init_early(void);
+void imx35_init_early(void);
+void imx51_init_early(void);
+void imx53_init_early(void);
+void mxc_init_irq(void __iomem *);
+void tzic_init_irq(void __iomem *);
+void mx1_init_irq(void);
+void mx21_init_irq(void);
+void mx25_init_irq(void);
+void mx27_init_irq(void);
+void mx31_init_irq(void);
+void mx35_init_irq(void);
+void mx51_init_irq(void);
+void mx53_init_irq(void);
+void imx1_soc_init(void);
+void imx21_soc_init(void);
+void imx25_soc_init(void);
+void imx27_soc_init(void);
+void imx31_soc_init(void);
+void imx35_soc_init(void);
+void imx51_soc_init(void);
+void imx51_init_late(void);
+void imx53_init_late(void);
+void epit_timer_init(void __iomem *base, int irq);
+void mxc_timer_init(void __iomem *, int);
+int mx1_clocks_init(unsigned long fref);
+int mx21_clocks_init(unsigned long lref, unsigned long fref);
+int mx25_clocks_init(void);
+int mx27_clocks_init(unsigned long fref);
+int mx31_clocks_init(unsigned long fref);
+int mx35_clocks_init(void);
+int mx51_clocks_init(unsigned long ckil, unsigned long osc,
 			unsigned long ckih1, unsigned long ckih2);
-extern int mx53_clocks_init(unsigned long ckil, unsigned long osc,
-			unsigned long ckih1, unsigned long ckih2);
-extern int mx25_clocks_init_dt(void);
-extern int mx27_clocks_init_dt(void);
-extern int mx31_clocks_init_dt(void);
-extern int mx51_clocks_init_dt(void);
-extern int mx53_clocks_init_dt(void);
-extern struct platform_device *mxc_register_gpio(char *name, int id,
+int mx25_clocks_init_dt(void);
+int mx27_clocks_init_dt(void);
+int mx31_clocks_init_dt(void);
+struct platform_device *mxc_register_gpio(char *name, int id,
 	resource_size_t iobase, resource_size_t iosize, int irq, int irq_high);
-extern void mxc_set_cpu_type(unsigned int type);
-extern void mxc_restart(enum reboot_mode, const char *);
-extern void mxc_arch_reset_init(void __iomem *);
-extern void mxc_arch_reset_init_dt(void);
-extern int mx53_revision(void);
-extern int imx6q_revision(void);
-extern int mx53_display_revision(void);
-extern void imx_set_aips(void __iomem *);
-extern int mxc_device_init(void);
+void mxc_set_cpu_type(unsigned int type);
+void mxc_restart(enum reboot_mode, const char *);
+void mxc_arch_reset_init(void __iomem *);
+void mxc_arch_reset_init_dt(void);
+int mx53_revision(void);
+void imx_set_aips(void __iomem *);
+int mxc_device_init(void);
+void imx_set_soc_revision(unsigned int rev);
+unsigned int imx_get_soc_revision(void);
+void imx_init_revision_from_anatop(void);
+struct device *imx_soc_device_init(void);
 
 enum mxc_cpu_pwr_mode {
 	WAIT_CLOCKED,		/* wfi only */
@@ -97,8 +96,8 @@
 	MX3_SLEEP,
 };
 
-extern void mx3_cpu_lp_set(enum mx3_cpu_pwr_mode mode);
-extern void imx_print_silicon_rev(const char *cpu, int srev);
+void mx3_cpu_lp_set(enum mx3_cpu_pwr_mode mode);
+void imx_print_silicon_rev(const char *cpu, int srev);
 
 void avic_handle_irq(struct pt_regs *);
 void tzic_handle_irq(struct pt_regs *);
@@ -112,54 +111,61 @@
 #define imx51_handle_irq tzic_handle_irq
 #define imx53_handle_irq tzic_handle_irq
 
-extern void imx_enable_cpu(int cpu, bool enable);
-extern void imx_set_cpu_jump(int cpu, void *jump_addr);
-extern u32 imx_get_cpu_arg(int cpu);
-extern void imx_set_cpu_arg(int cpu, u32 arg);
-extern void v7_cpu_resume(void);
+void imx_enable_cpu(int cpu, bool enable);
+void imx_set_cpu_jump(int cpu, void *jump_addr);
+u32 imx_get_cpu_arg(int cpu);
+void imx_set_cpu_arg(int cpu, u32 arg);
+void v7_cpu_resume(void);
 #ifdef CONFIG_SMP
-extern void v7_secondary_startup(void);
-extern void imx_scu_map_io(void);
-extern void imx_smp_prepare(void);
-extern void imx_scu_standby_enable(void);
+void v7_secondary_startup(void);
+void imx_scu_map_io(void);
+void imx_smp_prepare(void);
+void imx_scu_standby_enable(void);
 #else
 static inline void imx_scu_map_io(void) {}
 static inline void imx_smp_prepare(void) {}
 static inline void imx_scu_standby_enable(void) {}
 #endif
-extern void imx_src_init(void);
-extern void imx_src_prepare_restart(void);
-extern void imx_gpc_init(void);
-extern void imx_gpc_pre_suspend(void);
-extern void imx_gpc_post_resume(void);
-extern void imx_gpc_mask_all(void);
-extern void imx_gpc_restore_all(void);
-extern void imx_anatop_init(void);
-extern void imx_anatop_pre_suspend(void);
-extern void imx_anatop_post_resume(void);
-extern u32 imx_anatop_get_digprog(void);
-extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
-extern void imx6q_set_chicken_bit(void);
+void imx_src_init(void);
+#ifdef CONFIG_HAVE_IMX_SRC
+void imx_src_prepare_restart(void);
+#else
+static inline void imx_src_prepare_restart(void) {}
+#endif
+void imx_gpc_init(void);
+void imx_gpc_pre_suspend(void);
+void imx_gpc_post_resume(void);
+void imx_gpc_mask_all(void);
+void imx_gpc_restore_all(void);
+void imx_gpc_irq_mask(struct irq_data *d);
+void imx_gpc_irq_unmask(struct irq_data *d);
+void imx_anatop_init(void);
+void imx_anatop_pre_suspend(void);
+void imx_anatop_post_resume(void);
+int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
+void imx6q_set_chicken_bit(void);
 
-extern void imx_cpu_die(unsigned int cpu);
-extern int imx_cpu_kill(unsigned int cpu);
+void imx_cpu_die(unsigned int cpu);
+int imx_cpu_kill(unsigned int cpu);
 
 #ifdef CONFIG_PM
-extern void imx6q_pm_init(void);
-extern void imx5_pm_init(void);
+void imx6q_pm_init(void);
+void imx6q_pm_set_ccm_base(void __iomem *base);
+void imx5_pm_init(void);
 #else
 static inline void imx6q_pm_init(void) {}
+static inline void imx6q_pm_set_ccm_base(void __iomem *base) {}
 static inline void imx5_pm_init(void) {}
 #endif
 
 #ifdef CONFIG_NEON
-extern int mx51_neon_fixup(void);
+int mx51_neon_fixup(void);
 #else
 static inline int mx51_neon_fixup(void) { return 0; }
 #endif
 
 #ifdef CONFIG_CACHE_L2X0
-extern void imx_init_l2cache(void);
+void imx_init_l2cache(void);
 #else
 static inline void imx_init_l2cache(void) {}
 #endif
diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c
index e70e3ac..ba3b498 100644
--- a/arch/arm/mach-imx/cpu.c
+++ b/arch/arm/mach-imx/cpu.c
@@ -1,6 +1,9 @@
-
+#include <linux/err.h>
 #include <linux/module.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
 
 #include "hardware.h"
 #include "common.h"
@@ -8,11 +11,23 @@
 unsigned int __mxc_cpu_type;
 EXPORT_SYMBOL(__mxc_cpu_type);
 
+static unsigned int imx_soc_revision;
+
 void mxc_set_cpu_type(unsigned int type)
 {
 	__mxc_cpu_type = type;
 }
 
+void imx_set_soc_revision(unsigned int rev)
+{
+	imx_soc_revision = rev;
+}
+
+unsigned int imx_get_soc_revision(void)
+{
+	return imx_soc_revision;
+}
+
 void imx_print_silicon_rev(const char *cpu, int srev)
 {
 	if (srev == IMX_CHIP_REVISION_UNKNOWN)
@@ -44,3 +59,81 @@
 	reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
 	__raw_writel(reg, base + 0x50);
 }
+
+struct device * __init imx_soc_device_init(void)
+{
+	struct soc_device_attribute *soc_dev_attr;
+	struct soc_device *soc_dev;
+	struct device_node *root;
+	const char *soc_id;
+	int ret;
+
+	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+	if (!soc_dev_attr)
+		return NULL;
+
+	soc_dev_attr->family = "Freescale i.MX";
+
+	root = of_find_node_by_path("/");
+	ret = of_property_read_string(root, "model", &soc_dev_attr->machine);
+	of_node_put(root);
+	if (ret)
+		goto free_soc;
+
+	switch (__mxc_cpu_type) {
+	case MXC_CPU_MX1:
+		soc_id = "i.MX1";
+		break;
+	case MXC_CPU_MX21:
+		soc_id = "i.MX21";
+		break;
+	case MXC_CPU_MX25:
+		soc_id = "i.MX25";
+		break;
+	case MXC_CPU_MX27:
+		soc_id = "i.MX27";
+		break;
+	case MXC_CPU_MX31:
+		soc_id = "i.MX31";
+		break;
+	case MXC_CPU_MX35:
+		soc_id = "i.MX35";
+		break;
+	case MXC_CPU_MX51:
+		soc_id = "i.MX51";
+		break;
+	case MXC_CPU_MX53:
+		soc_id = "i.MX53";
+		break;
+	case MXC_CPU_IMX6SL:
+		soc_id = "i.MX6SL";
+		break;
+	case MXC_CPU_IMX6DL:
+		soc_id = "i.MX6DL";
+		break;
+	case MXC_CPU_IMX6Q:
+		soc_id = "i.MX6Q";
+		break;
+	default:
+		soc_id = "Unknown";
+	}
+	soc_dev_attr->soc_id = soc_id;
+
+	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d.%d",
+					   (imx_soc_revision >> 4) & 0xf,
+					   imx_soc_revision & 0xf);
+	if (!soc_dev_attr->revision)
+		goto free_soc;
+
+	soc_dev = soc_device_register(soc_dev_attr);
+	if (IS_ERR(soc_dev))
+		goto free_rev;
+
+	return soc_device_to_device(soc_dev);
+
+free_rev:
+	kfree(soc_dev_attr->revision);
+free_soc:
+	kfree(soc_dev_attr);
+	return NULL;
+}
diff --git a/arch/arm/mach-imx/epit.c b/arch/arm/mach-imx/epit.c
index e02de18..074b1a8 100644
--- a/arch/arm/mach-imx/epit.c
+++ b/arch/arm/mach-imx/epit.c
@@ -171,7 +171,7 @@
 
 static struct irqaction epit_timer_irq = {
 	.name		= "i.MX EPIT Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
 	.handler	= epit_timer_interrupt,
 };
 
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 44a65e9..586e017 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -90,7 +90,7 @@
 		writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
 }
 
-static void imx_gpc_irq_unmask(struct irq_data *d)
+void imx_gpc_irq_unmask(struct irq_data *d)
 {
 	void __iomem *reg;
 	u32 val;
@@ -105,7 +105,7 @@
 	writel_relaxed(val, reg);
 }
 
-static void imx_gpc_irq_mask(struct irq_data *d)
+void imx_gpc_irq_mask(struct irq_data *d)
 {
 	void __iomem *reg;
 	u32 val;
diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c
index 3daf1ed..b35e99c 100644
--- a/arch/arm/mach-imx/hotplug.c
+++ b/arch/arm/mach-imx/hotplug.c
@@ -52,7 +52,9 @@
 	 * the register being cleared to kill the cpu.
 	 */
 	imx_set_cpu_arg(cpu, ~0);
-	cpu_do_idle();
+
+	while (1)
+		cpu_do_idle();
 }
 
 int imx_cpu_kill(unsigned int cpu)
diff --git a/arch/arm/mach-imx/imx51-dt.c b/arch/arm/mach-imx/imx51-dt.c
index 53e43e5..bece8a6 100644
--- a/arch/arm/mach-imx/imx51-dt.c
+++ b/arch/arm/mach-imx/imx51-dt.c
@@ -34,17 +34,11 @@
 	NULL
 };
 
-static void __init imx51_timer_init(void)
-{
-	mx51_clocks_init_dt();
-}
-
 DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
 	.map_io		= mx51_map_io,
 	.init_early	= imx51_init_early,
 	.init_irq	= mx51_init_irq,
 	.handle_irq	= imx51_handle_irq,
-	.init_time	= imx51_timer_init,
 	.init_machine	= imx51_dt_init,
 	.init_late	= imx51_init_late,
 	.dt_compat	= imx51_dt_board_compat,
diff --git a/arch/arm/mach-imx/mach-armadillo5x0.c b/arch/arm/mach-imx/mach-armadillo5x0.c
index 368a6e3..58b864a 100644
--- a/arch/arm/mach-imx/mach-armadillo5x0.c
+++ b/arch/arm/mach-imx/mach-armadillo5x0.c
@@ -404,8 +404,7 @@
 
 	/* When supported the trigger type have to be BOTH */
 	ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK)),
-			  detect_irq,
-			  IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+			  detect_irq, IRQF_TRIGGER_FALLING,
 			  "sdhc-detect", data);
 
 	if (ret)
diff --git a/arch/arm/mach-imx/mach-imx53.c b/arch/arm/mach-imx/mach-imx53.c
index 98c5894..c9c4d8d 100644
--- a/arch/arm/mach-imx/mach-imx53.c
+++ b/arch/arm/mach-imx/mach-imx53.c
@@ -36,17 +36,11 @@
 	NULL
 };
 
-static void __init imx53_timer_init(void)
-{
-	mx53_clocks_init_dt();
-}
-
 DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
 	.map_io		= mx53_map_io,
 	.init_early	= imx53_init_early,
 	.init_irq	= mx53_init_irq,
 	.handle_irq	= imx53_handle_irq,
-	.init_time	= imx53_timer_init,
 	.init_machine	= imx53_dt_init,
 	.init_late	= imx53_init_late,
 	.dt_compat	= imx53_dt_board_compat,
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 90372a2..0f9f241 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -11,11 +11,8 @@
  */
 
 #include <linux/clk.h>
-#include <linux/clk-provider.h>
 #include <linux/clkdev.h>
-#include <linux/clocksource.h>
 #include <linux/cpu.h>
-#include <linux/delay.h>
 #include <linux/export.h>
 #include <linux/init.h>
 #include <linux/io.h>
@@ -40,64 +37,6 @@
 #include "cpuidle.h"
 #include "hardware.h"
 
-static u32 chip_revision;
-
-int imx6q_revision(void)
-{
-	return chip_revision;
-}
-
-static void __init imx6q_init_revision(void)
-{
-	u32 rev = imx_anatop_get_digprog();
-
-	switch (rev & 0xff) {
-	case 0:
-		chip_revision = IMX_CHIP_REVISION_1_0;
-		break;
-	case 1:
-		chip_revision = IMX_CHIP_REVISION_1_1;
-		break;
-	case 2:
-		chip_revision = IMX_CHIP_REVISION_1_2;
-		break;
-	default:
-		chip_revision = IMX_CHIP_REVISION_UNKNOWN;
-	}
-
-	mxc_set_cpu_type(rev >> 16 & 0xff);
-}
-
-static void imx6q_restart(enum reboot_mode mode, const char *cmd)
-{
-	struct device_node *np;
-	void __iomem *wdog_base;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-wdt");
-	wdog_base = of_iomap(np, 0);
-	if (!wdog_base)
-		goto soft;
-
-	imx_src_prepare_restart();
-
-	/* enable wdog */
-	writew_relaxed(1 << 2, wdog_base);
-	/* write twice to ensure the request will not get ignored */
-	writew_relaxed(1 << 2, wdog_base);
-
-	/* wait for reset to assert ... */
-	mdelay(500);
-
-	pr_err("Watchdog reset failed to assert reset\n");
-
-	/* delay to allow the serial port to show the message */
-	mdelay(50);
-
-soft:
-	/* we'll take a jump through zero as a poor second */
-	soft_restart(0);
-}
-
 /* For imx6q sabrelite board: set KSZ9021RN RGMII pad skew */
 static int ksz9021rn_phy_fixup(struct phy_device *phydev)
 {
@@ -192,9 +131,20 @@
 
 static void __init imx6q_init_machine(void)
 {
+	struct device *parent;
+
+	imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q",
+			      imx_get_soc_revision());
+
+	mxc_arch_reset_init_dt();
+
+	parent = imx_soc_device_init();
+	if (parent == NULL)
+		pr_warn("failed to initialize soc device\n");
+
 	imx6q_enet_phy_init();
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
 
 	imx_anatop_init();
 	imx6q_pm_init();
@@ -269,7 +219,7 @@
 	 * WAIT mode is broken on TO 1.0 and 1.1, so there is no point
 	 * to run cpuidle on them.
 	 */
-	if (imx6q_revision() > IMX_CHIP_REVISION_1_1)
+	if (imx_get_soc_revision() > IMX_CHIP_REVISION_1_1)
 		imx6q_cpuidle_init();
 
 	if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) {
@@ -286,21 +236,13 @@
 
 static void __init imx6q_init_irq(void)
 {
-	imx6q_init_revision();
+	imx_init_revision_from_anatop();
 	imx_init_l2cache();
 	imx_src_init();
 	imx_gpc_init();
 	irqchip_init();
 }
 
-static void __init imx6q_timer_init(void)
-{
-	of_clk_init(NULL);
-	clocksource_of_init();
-	imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q",
-			      imx6q_revision());
-}
-
 static const char *imx6q_dt_compat[] __initdata = {
 	"fsl,imx6dl",
 	"fsl,imx6q",
@@ -311,9 +253,8 @@
 	.smp		= smp_ops(imx_smp_ops),
 	.map_io		= imx6q_map_io,
 	.init_irq	= imx6q_init_irq,
-	.init_time	= imx6q_timer_init,
 	.init_machine	= imx6q_init_machine,
 	.init_late      = imx6q_init_late,
 	.dt_compat	= imx6q_dt_compat,
-	.restart	= imx6q_restart,
+	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c
index 0d75dc5..2f952e3 100644
--- a/arch/arm/mach-imx/mach-imx6sl.c
+++ b/arch/arm/mach-imx/mach-imx6sl.c
@@ -7,35 +7,60 @@
  *
  */
 
-#include <linux/clk-provider.h>
 #include <linux/irqchip.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/regmap.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
 #include "common.h"
 
+static void __init imx6sl_fec_init(void)
+{
+	struct regmap *gpr;
+
+	/* set FEC clock from internal PLL clock source */
+	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6sl-iomuxc-gpr");
+	if (!IS_ERR(gpr)) {
+		regmap_update_bits(gpr, IOMUXC_GPR1,
+			IMX6SL_GPR1_FEC_CLOCK_MUX2_SEL_MASK, 0);
+		regmap_update_bits(gpr, IOMUXC_GPR1,
+			IMX6SL_GPR1_FEC_CLOCK_MUX1_SEL_MASK, 0);
+	} else {
+		pr_err("failed to find fsl,imx6sl-iomux-gpr regmap\n");
+	}
+}
+
 static void __init imx6sl_init_machine(void)
 {
+	struct device *parent;
+
 	mxc_arch_reset_init_dt();
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+	parent = imx_soc_device_init();
+	if (parent == NULL)
+		pr_warn("failed to initialize soc device\n");
+
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
+
+	imx6sl_fec_init();
+	imx_anatop_init();
+	/* Reuse imx6q pm code */
+	imx6q_pm_init();
 }
 
 static void __init imx6sl_init_irq(void)
 {
+	imx_init_revision_from_anatop();
 	imx_init_l2cache();
 	imx_src_init();
 	imx_gpc_init();
 	irqchip_init();
 }
 
-static void __init imx6sl_timer_init(void)
-{
-	of_clk_init(NULL);
-}
-
 static const char *imx6sl_dt_compat[] __initdata = {
 	"fsl,imx6sl",
 	NULL,
@@ -44,7 +69,6 @@
 DT_MACHINE_START(IMX6SL, "Freescale i.MX6 SoloLite (Device Tree)")
 	.map_io		= debug_ll_io_init,
 	.init_irq	= imx6sl_init_irq,
-	.init_time	= imx6sl_timer_init,
 	.init_machine	= imx6sl_init_machine,
 	.dt_compat	= imx6sl_dt_compat,
 	.restart	= mxc_restart,
diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c
index 1ed9161..50044a2 100644
--- a/arch/arm/mach-imx/mach-mx31_3ds.c
+++ b/arch/arm/mach-imx/mach-mx31_3ds.c
@@ -311,7 +311,7 @@
 	}
 
 	ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)),
-			  detect_irq, IRQF_DISABLED |
+			  detect_irq,
 			  IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
 			  "sdhc1-detect", data);
 	if (ret) {
diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c
index bc0261e..45303bd6 100644
--- a/arch/arm/mach-imx/mach-pcm037.c
+++ b/arch/arm/mach-imx/mach-pcm037.c
@@ -371,8 +371,7 @@
 #endif
 
 	ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_SCK6)), detect_irq,
-			IRQF_DISABLED | IRQF_TRIGGER_FALLING,
-				"sdhc-detect", data);
+			IRQF_TRIGGER_FALLING, "sdhc-detect", data);
 	if (ret)
 		goto err_gpio_free_2;
 
diff --git a/arch/arm/mach-imx/mach-vf610.c b/arch/arm/mach-imx/mach-vf610.c
index 816991d..af0cb8a 100644
--- a/arch/arm/mach-imx/mach-vf610.c
+++ b/arch/arm/mach-imx/mach-vf610.c
@@ -8,9 +8,7 @@
  */
 
 #include <linux/of_platform.h>
-#include <linux/clocksource.h>
 #include <linux/irqchip.h>
-#include <linux/clk-provider.h>
 #include <asm/mach/arch.h>
 #include <asm/hardware/cache-l2x0.h>
 
@@ -28,12 +26,6 @@
 	irqchip_init();
 }
 
-static void __init vf610_init_time(void)
-{
-	of_clk_init(NULL);
-	clocksource_of_init();
-}
-
 static const char *vf610_dt_compat[] __initdata = {
 	"fsl,vf610",
 	NULL,
@@ -41,7 +33,6 @@
 
 DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF610 (Device Tree)")
 	.init_irq	= vf610_init_irq,
-	.init_time	= vf610_init_time,
 	.init_machine   = vf610_init_machine,
 	.dt_compat	= vf610_dt_compat,
 	.restart	= mxc_restart,
diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c
index eb3cce3..d1d5260 100644
--- a/arch/arm/mach-imx/mm-imx5.c
+++ b/arch/arm/mach-imx/mm-imx5.c
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/of_address.h>
 
 #include <asm/mach/map.h>
 
@@ -88,8 +89,15 @@
 
 void __init imx53_init_early(void)
 {
+	struct device_node *np;
+	void __iomem *base;
+
 	mxc_set_cpu_type(MXC_CPU_MX53);
-	mxc_iomux_v3_init(MX53_IO_ADDRESS(MX53_IOMUXC_BASE_ADDR));
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx53-iomuxc");
+	base = of_iomap(np, 0);
+	WARN_ON(!base);
+	mxc_iomux_v3_init(base);
 	imx_src_init();
 }
 
@@ -100,7 +108,14 @@
 
 void __init mx53_init_irq(void)
 {
-	tzic_init_irq(MX53_IO_ADDRESS(MX53_TZIC_BASE_ADDR));
+	struct device_node *np;
+	void __iomem *base;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx53-tzic");
+	base = of_iomap(np, 0);
+	WARN_ON(!base);
+
+	tzic_init_irq(base);
 }
 
 static struct sdma_platform_data imx51_sdma_pdata __initdata = {
diff --git a/arch/arm/mach-imx/mx31lilly-db.c b/arch/arm/mach-imx/mx31lilly-db.c
index d4361b8..649fe49 100644
--- a/arch/arm/mach-imx/mx31lilly-db.c
+++ b/arch/arm/mach-imx/mx31lilly-db.c
@@ -130,8 +130,7 @@
 	gpio_direction_input(gpio_wp);
 
 	ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1)),
-			  detect_irq,
-			  IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+			  detect_irq, IRQF_TRIGGER_FALLING,
 			  "MMC detect", data);
 	if (ret)
 		goto exit_free_wp;
diff --git a/arch/arm/mach-imx/mxc.h b/arch/arm/mach-imx/mxc.h
index 8629e5b..b08ab3a 100644
--- a/arch/arm/mach-imx/mxc.h
+++ b/arch/arm/mach-imx/mxc.h
@@ -34,6 +34,7 @@
 #define MXC_CPU_MX35		35
 #define MXC_CPU_MX51		51
 #define MXC_CPU_MX53		53
+#define MXC_CPU_IMX6SL		0x60
 #define MXC_CPU_IMX6DL		0x61
 #define MXC_CPU_IMX6Q		0x63
 
@@ -152,6 +153,11 @@
 #endif
 
 #ifndef __ASSEMBLY__
+static inline bool cpu_is_imx6sl(void)
+{
+	return __mxc_cpu_type == MXC_CPU_IMX6SL;
+}
+
 static inline bool cpu_is_imx6dl(void)
 {
 	return __mxc_cpu_type == MXC_CPU_IMX6DL;
diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c
index 2049427..aecd9f8 100644
--- a/arch/arm/mach-imx/pm-imx6q.c
+++ b/arch/arm/mach-imx/pm-imx6q.c
@@ -10,9 +10,15 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/regmap.h>
 #include <linux/suspend.h>
 #include <asm/cacheflush.h>
 #include <asm/proc-fns.h>
@@ -22,6 +28,147 @@
 #include "common.h"
 #include "hardware.h"
 
+#define CCR				0x0
+#define BM_CCR_WB_COUNT			(0x7 << 16)
+#define BM_CCR_RBC_BYPASS_COUNT		(0x3f << 21)
+#define BM_CCR_RBC_EN			(0x1 << 27)
+
+#define CLPCR				0x54
+#define BP_CLPCR_LPM			0
+#define BM_CLPCR_LPM			(0x3 << 0)
+#define BM_CLPCR_BYPASS_PMIC_READY	(0x1 << 2)
+#define BM_CLPCR_ARM_CLK_DIS_ON_LPM	(0x1 << 5)
+#define BM_CLPCR_SBYOS			(0x1 << 6)
+#define BM_CLPCR_DIS_REF_OSC		(0x1 << 7)
+#define BM_CLPCR_VSTBY			(0x1 << 8)
+#define BP_CLPCR_STBY_COUNT		9
+#define BM_CLPCR_STBY_COUNT		(0x3 << 9)
+#define BM_CLPCR_COSC_PWRDOWN		(0x1 << 11)
+#define BM_CLPCR_WB_PER_AT_LPM		(0x1 << 16)
+#define BM_CLPCR_WB_CORE_AT_LPM		(0x1 << 17)
+#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS	(0x1 << 19)
+#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS	(0x1 << 21)
+#define BM_CLPCR_MASK_CORE0_WFI		(0x1 << 22)
+#define BM_CLPCR_MASK_CORE1_WFI		(0x1 << 23)
+#define BM_CLPCR_MASK_CORE2_WFI		(0x1 << 24)
+#define BM_CLPCR_MASK_CORE3_WFI		(0x1 << 25)
+#define BM_CLPCR_MASK_SCU_IDLE		(0x1 << 26)
+#define BM_CLPCR_MASK_L2CC_IDLE		(0x1 << 27)
+
+#define CGPR				0x64
+#define BM_CGPR_CHICKEN_BIT		(0x1 << 17)
+
+static void __iomem *ccm_base;
+
+void imx6q_set_chicken_bit(void)
+{
+	u32 val = readl_relaxed(ccm_base + CGPR);
+
+	val |= BM_CGPR_CHICKEN_BIT;
+	writel_relaxed(val, ccm_base + CGPR);
+}
+
+static void imx6q_enable_rbc(bool enable)
+{
+	u32 val;
+
+	/*
+	 * need to mask all interrupts in GPC before
+	 * operating RBC configurations
+	 */
+	imx_gpc_mask_all();
+
+	/* configure RBC enable bit */
+	val = readl_relaxed(ccm_base + CCR);
+	val &= ~BM_CCR_RBC_EN;
+	val |= enable ? BM_CCR_RBC_EN : 0;
+	writel_relaxed(val, ccm_base + CCR);
+
+	/* configure RBC count */
+	val = readl_relaxed(ccm_base + CCR);
+	val &= ~BM_CCR_RBC_BYPASS_COUNT;
+	val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0;
+	writel(val, ccm_base + CCR);
+
+	/*
+	 * need to delay at least 2 cycles of CKIL(32K)
+	 * due to hardware design requirement, which is
+	 * ~61us, here we use 65us for safe
+	 */
+	udelay(65);
+
+	/* restore GPC interrupt mask settings */
+	imx_gpc_restore_all();
+}
+
+static void imx6q_enable_wb(bool enable)
+{
+	u32 val;
+
+	/* configure well bias enable bit */
+	val = readl_relaxed(ccm_base + CLPCR);
+	val &= ~BM_CLPCR_WB_PER_AT_LPM;
+	val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0;
+	writel_relaxed(val, ccm_base + CLPCR);
+
+	/* configure well bias count */
+	val = readl_relaxed(ccm_base + CCR);
+	val &= ~BM_CCR_WB_COUNT;
+	val |= enable ? BM_CCR_WB_COUNT : 0;
+	writel_relaxed(val, ccm_base + CCR);
+}
+
+int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
+{
+	struct irq_desc *iomuxc_irq_desc;
+	u32 val = readl_relaxed(ccm_base + CLPCR);
+
+	val &= ~BM_CLPCR_LPM;
+	switch (mode) {
+	case WAIT_CLOCKED:
+		break;
+	case WAIT_UNCLOCKED:
+		val |= 0x1 << BP_CLPCR_LPM;
+		val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM;
+		break;
+	case STOP_POWER_ON:
+		val |= 0x2 << BP_CLPCR_LPM;
+		break;
+	case WAIT_UNCLOCKED_POWER_OFF:
+		val |= 0x1 << BP_CLPCR_LPM;
+		val &= ~BM_CLPCR_VSTBY;
+		val &= ~BM_CLPCR_SBYOS;
+		break;
+	case STOP_POWER_OFF:
+		val |= 0x2 << BP_CLPCR_LPM;
+		val |= 0x3 << BP_CLPCR_STBY_COUNT;
+		val |= BM_CLPCR_VSTBY;
+		val |= BM_CLPCR_SBYOS;
+		if (cpu_is_imx6sl()) {
+			val |= BM_CLPCR_BYPASS_PMIC_READY;
+			val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
+		} else {
+			val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * Unmask the always pending IOMUXC interrupt #32 as wakeup source to
+	 * deassert dsm_request signal, so that we can ensure dsm_request
+	 * is not asserted when we're going to write CLPCR register to set LPM.
+	 * After setting up LPM bits, we need to mask this wakeup source.
+	 */
+	iomuxc_irq_desc = irq_to_desc(32);
+	imx_gpc_irq_unmask(&iomuxc_irq_desc->irq_data);
+	writel_relaxed(val, ccm_base + CLPCR);
+	imx_gpc_irq_mask(&iomuxc_irq_desc->irq_data);
+
+	return 0;
+}
+
 static int imx6q_suspend_finish(unsigned long val)
 {
 	cpu_do_idle();
@@ -33,14 +180,19 @@
 	switch (state) {
 	case PM_SUSPEND_MEM:
 		imx6q_set_lpm(STOP_POWER_OFF);
+		imx6q_enable_wb(true);
+		imx6q_enable_rbc(true);
 		imx_gpc_pre_suspend();
 		imx_anatop_pre_suspend();
 		imx_set_cpu_jump(0, v7_cpu_resume);
 		/* Zzz ... */
 		cpu_suspend(0, imx6q_suspend_finish);
-		imx_smp_prepare();
+		if (cpu_is_imx6q() || cpu_is_imx6dl())
+			imx_smp_prepare();
 		imx_anatop_post_resume();
 		imx_gpc_post_resume();
+		imx6q_enable_rbc(false);
+		imx6q_enable_wb(false);
 		imx6q_set_lpm(WAIT_CLOCKED);
 		break;
 	default:
@@ -55,7 +207,29 @@
 	.valid = suspend_valid_only_mem,
 };
 
+void __init imx6q_pm_set_ccm_base(void __iomem *base)
+{
+	ccm_base = base;
+}
+
 void __init imx6q_pm_init(void)
 {
+	struct regmap *gpr;
+
+	WARN_ON(!ccm_base);
+
+	/*
+	 * Force IOMUXC irq pending, so that the interrupt to GPC can be
+	 * used to deassert dsm_request signal when the signal gets
+	 * asserted unexpectedly.
+	 */
+	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+	if (!IS_ERR(gpr))
+		regmap_update_bits(gpr, IOMUXC_GPR1, IMX6Q_GPR1_GINT,
+				   IMX6Q_GPR1_GINT);
+
+	/* Set initial power mode */
+	imx6q_set_lpm(WAIT_CLOCKED);
+
 	suspend_set_ops(&imx6q_pm_ops);
 }
diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c
index 10a6b1a..4754373 100644
--- a/arch/arm/mach-imx/src.c
+++ b/arch/arm/mach-imx/src.c
@@ -91,6 +91,7 @@
 	spin_lock(&scr_lock);
 	val = readl_relaxed(src_base + SRC_SCR);
 	val = enable ? val | mask : val & ~mask;
+	val |= 1 << (BP_SRC_SCR_CORE1_RST + cpu - 1);
 	writel_relaxed(val, src_base + SRC_SCR);
 	spin_unlock(&scr_lock);
 }
diff --git a/arch/arm/mach-imx/system.c b/arch/arm/mach-imx/system.c
index 80c177c..e6edcd3 100644
--- a/arch/arm/mach-imx/system.c
+++ b/arch/arm/mach-imx/system.c
@@ -42,6 +42,9 @@
 {
 	unsigned int wcr_enable;
 
+	if (cpu_is_imx6q() || cpu_is_imx6dl())
+		imx_src_prepare_restart();
+
 	if (wdog_clk)
 		clk_enable(wdog_clk);
 
@@ -52,6 +55,8 @@
 
 	/* Assert SRS signal */
 	__raw_writew(wcr_enable, wdog_base);
+	/* write twice to ensure the request will not get ignored */
+	__raw_writew(wcr_enable, wdog_base);
 
 	/* wait for reset to assert... */
 	mdelay(500);
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index cd46529..9b6638a 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -250,7 +250,7 @@
 
 static struct irqaction mxc_timer_irq = {
 	.name		= "i.MX Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
 	.handler	= mxc_timer_interrupt,
 };
 
diff --git a/arch/arm/mach-integrator/include/mach/cm.h b/arch/arm/mach-integrator/cm.h
similarity index 88%
rename from arch/arm/mach-integrator/include/mach/cm.h
rename to arch/arm/mach-integrator/cm.h
index 202e6a5..4ecff7b 100644
--- a/arch/arm/mach-integrator/include/mach/cm.h
+++ b/arch/arm/mach-integrator/cm.h
@@ -1,9 +1,12 @@
 /*
- * update the core module control register.
+ * access the core module control register.
  */
+u32 cm_get(void);
 void cm_control(u32, u32);
 
-#define CM_CTRL	__io_address(INTEGRATOR_HDR_CTRL)
+struct device_node;
+void cm_init(void);
+void cm_clear_irqs(void);
 
 #define CM_CTRL_LED			(1 << 0)
 #define CM_CTRL_nMBDET			(1 << 1)
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index 4cdfd73..00ddf20 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -22,76 +22,29 @@
 #include <linux/amba/serial.h>
 #include <linux/io.h>
 #include <linux/stat.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <mach/cm.h>
-#include <mach/irqs.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/time.h>
 #include <asm/pgtable.h>
 
+#include "cm.h"
 #include "common.h"
 
-#ifdef CONFIG_ATAGS
-
-#define INTEGRATOR_RTC_IRQ	{ IRQ_RTCINT }
-#define INTEGRATOR_UART0_IRQ	{ IRQ_UARTINT0 }
-#define INTEGRATOR_UART1_IRQ	{ IRQ_UARTINT1 }
-#define KMI0_IRQ		{ IRQ_KMIINT0 }
-#define KMI1_IRQ		{ IRQ_KMIINT1 }
-
-static AMBA_APB_DEVICE(rtc, "rtc", 0,
-	INTEGRATOR_RTC_BASE, INTEGRATOR_RTC_IRQ, NULL);
-
-static AMBA_APB_DEVICE(uart0, "uart0", 0,
-	INTEGRATOR_UART0_BASE, INTEGRATOR_UART0_IRQ, NULL);
-
-static AMBA_APB_DEVICE(uart1, "uart1", 0,
-	INTEGRATOR_UART1_BASE, INTEGRATOR_UART1_IRQ, NULL);
-
-static AMBA_APB_DEVICE(kmi0, "kmi0", 0, KMI0_BASE, KMI0_IRQ, NULL);
-static AMBA_APB_DEVICE(kmi1, "kmi1", 0, KMI1_BASE, KMI1_IRQ, NULL);
-
-static struct amba_device *amba_devs[] __initdata = {
-	&rtc_device,
-	&uart0_device,
-	&uart1_device,
-	&kmi0_device,
-	&kmi1_device,
-};
-
-int __init integrator_init(bool is_cp)
-{
-	int i;
-
-	/*
-	 * The Integrator/AP lacks necessary AMBA PrimeCell IDs, so we need to
-	 * hard-code them. The Integator/CP and forward have proper cell IDs.
-	 * Else we leave them undefined to the bus driver can autoprobe them.
-	 */
-	if (!is_cp && IS_ENABLED(CONFIG_ARCH_INTEGRATOR_AP)) {
-		rtc_device.periphid	= 0x00041030;
-		uart0_device.periphid	= 0x00041010;
-		uart1_device.periphid	= 0x00041010;
-		kmi0_device.periphid	= 0x00041050;
-		kmi1_device.periphid	= 0x00041050;
-		uart0_device.dev.platform_data = &ap_uart_data;
-		uart1_device.dev.platform_data = &ap_uart_data;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
-		struct amba_device *d = amba_devs[i];
-		amba_device_register(d, &iomem_resource);
-	}
-
-	return 0;
-}
-
-#endif
-
 static DEFINE_RAW_SPINLOCK(cm_lock);
+static void __iomem *cm_base;
+
+/**
+ * cm_get - get the value from the CM_CTRL register
+ */
+u32 cm_get(void)
+{
+	return readl(cm_base + INTEGRATOR_HDR_CTRL_OFFSET);
+}
 
 /**
  * cm_control - update the CM_CTRL register.
@@ -104,12 +57,80 @@
 	u32 val;
 
 	raw_spin_lock_irqsave(&cm_lock, flags);
-	val = readl(CM_CTRL) & ~mask;
-	writel(val | set, CM_CTRL);
+	val = readl(cm_base + INTEGRATOR_HDR_CTRL_OFFSET) & ~mask;
+	writel(val | set, cm_base + INTEGRATOR_HDR_CTRL_OFFSET);
 	raw_spin_unlock_irqrestore(&cm_lock, flags);
 }
 
-EXPORT_SYMBOL(cm_control);
+static const char *integrator_arch_str(u32 id)
+{
+	switch ((id >> 16) & 0xff) {
+	case 0x00:
+		return "ASB little-endian";
+	case 0x01:
+		return "AHB little-endian";
+	case 0x03:
+		return "AHB-Lite system bus, bi-endian";
+	case 0x04:
+		return "AHB";
+	case 0x08:
+		return "AHB system bus, ASB processor bus";
+	default:
+		return "Unknown";
+	}
+}
+
+static const char *integrator_fpga_str(u32 id)
+{
+	switch ((id >> 12) & 0xf) {
+	case 0x01:
+		return "XC4062";
+	case 0x02:
+		return "XC4085";
+	case 0x03:
+		return "XVC600";
+	case 0x04:
+		return "EPM7256AE (Altera PLD)";
+	default:
+		return "Unknown";
+	}
+}
+
+void cm_clear_irqs(void)
+{
+	/* disable core module IRQs */
+	writel(0xffffffffU, cm_base + INTEGRATOR_HDR_IC_OFFSET +
+		IRQ_ENABLE_CLEAR);
+}
+
+static const struct of_device_id cm_match[] = {
+	{ .compatible = "arm,core-module-integrator"},
+	{ },
+};
+
+void cm_init(void)
+{
+	struct device_node *cm = of_find_matching_node(NULL, cm_match);
+	u32 val;
+
+	if (!cm) {
+		pr_crit("no core module node found in device tree\n");
+		return;
+	}
+	cm_base = of_iomap(cm, 0);
+	if (!cm_base) {
+		pr_crit("could not remap core module\n");
+		return;
+	}
+	cm_clear_irqs();
+	val = readl(cm_base + INTEGRATOR_HDR_ID_OFFSET);
+	pr_info("Detected ARM core module:\n");
+	pr_info("    Manufacturer: %02x\n", (val >> 24));
+	pr_info("    Architecture: %s\n", integrator_arch_str(val));
+	pr_info("    FPGA: %s\n", integrator_fpga_str(val));
+	pr_info("    Build: %02x\n", (val >> 4) & 0xFF);
+	pr_info("    Rev: %c\n", ('A' + (val & 0x03)));
+}
 
 /*
  * We need to stop things allocating the low memory; ideally we need a
@@ -145,27 +166,7 @@
 			      struct device_attribute *attr,
 			      char *buf)
 {
-	const char *arch;
-
-	switch ((integrator_id >> 16) & 0xff) {
-	case 0x00:
-		arch = "ASB little-endian";
-		break;
-	case 0x01:
-		arch = "AHB little-endian";
-		break;
-	case 0x03:
-		arch = "AHB-Lite system bus, bi-endian";
-		break;
-	case 0x04:
-		arch = "AHB";
-		break;
-	default:
-		arch = "Unknown";
-		break;
-	}
-
-	return sprintf(buf, "%s\n", arch);
+	return sprintf(buf, "%s\n", integrator_arch_str(integrator_id));
 }
 
 static struct device_attribute intcp_arch_attr =
@@ -175,24 +176,7 @@
 			      struct device_attribute *attr,
 			      char *buf)
 {
-	const char *fpga;
-
-	switch ((integrator_id >> 12) & 0xf) {
-	case 0x01:
-		fpga = "XC4062";
-		break;
-	case 0x02:
-		fpga = "XC4085";
-		break;
-	case 0x04:
-		fpga = "EPM7256AE (Altera PLD)";
-		break;
-	default:
-		fpga = "Unknown";
-		break;
-	}
-
-	return sprintf(buf, "%s\n", fpga);
+	return sprintf(buf, "%s\n", integrator_fpga_str(integrator_id));
 }
 
 static struct device_attribute intcp_fpga_attr =
diff --git a/arch/arm/mach-integrator/include/mach/irqs.h b/arch/arm/mach-integrator/include/mach/irqs.h
deleted file mode 100644
index eff0ada..0000000
--- a/arch/arm/mach-integrator/include/mach/irqs.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- *  arch/arm/mach-integrator/include/mach/irqs.h
- *
- *  Copyright (C) 1999 ARM Limited
- *  Copyright (C) 2000 Deep Blue Solutions Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- * Interrupt numbers, all of the above are just static reservations
- * used so they can be encoded into device resources. They will finally
- * be done away with when switching to device tree.
- */
-#define IRQ_PIC_START			64
-#define IRQ_SOFTINT			(IRQ_PIC_START+0)
-#define IRQ_UARTINT0			(IRQ_PIC_START+1)
-#define IRQ_UARTINT1			(IRQ_PIC_START+2)
-#define IRQ_KMIINT0			(IRQ_PIC_START+3)
-#define IRQ_KMIINT1			(IRQ_PIC_START+4)
-#define IRQ_TIMERINT0			(IRQ_PIC_START+5)
-#define IRQ_TIMERINT1			(IRQ_PIC_START+6)
-#define IRQ_TIMERINT2			(IRQ_PIC_START+7)
-#define IRQ_RTCINT			(IRQ_PIC_START+8)
-#define IRQ_AP_EXPINT0			(IRQ_PIC_START+9)
-#define IRQ_AP_EXPINT1			(IRQ_PIC_START+10)
-#define IRQ_AP_EXPINT2			(IRQ_PIC_START+11)
-#define IRQ_AP_EXPINT3			(IRQ_PIC_START+12)
-#define IRQ_AP_PCIINT0			(IRQ_PIC_START+13)
-#define IRQ_AP_PCIINT1			(IRQ_PIC_START+14)
-#define IRQ_AP_PCIINT2			(IRQ_PIC_START+15)
-#define IRQ_AP_PCIINT3			(IRQ_PIC_START+16)
-#define IRQ_AP_V3INT			(IRQ_PIC_START+17)
-#define IRQ_AP_CPINT0			(IRQ_PIC_START+18)
-#define IRQ_AP_CPINT1			(IRQ_PIC_START+19)
-#define IRQ_AP_LBUSTIMEOUT 		(IRQ_PIC_START+20)
-#define IRQ_AP_APCINT			(IRQ_PIC_START+21)
-#define IRQ_CP_CLCDCINT			(IRQ_PIC_START+22)
-#define IRQ_CP_MMCIINT0			(IRQ_PIC_START+23)
-#define IRQ_CP_MMCIINT1			(IRQ_PIC_START+24)
-#define IRQ_CP_AACIINT			(IRQ_PIC_START+25)
-#define IRQ_CP_CPPLDINT			(IRQ_PIC_START+26)
-#define IRQ_CP_ETHINT			(IRQ_PIC_START+27)
-#define IRQ_CP_TSPENINT			(IRQ_PIC_START+28)
-#define IRQ_PIC_END			(IRQ_PIC_START+28)
-
-#define IRQ_CIC_START			(IRQ_PIC_END+1)
-#define IRQ_CM_SOFTINT			(IRQ_CIC_START+0)
-#define IRQ_CM_COMMRX			(IRQ_CIC_START+1)
-#define IRQ_CM_COMMTX			(IRQ_CIC_START+2)
-#define IRQ_CIC_END			(IRQ_CIC_START+2)
-
-/*
- * IntegratorCP only
- */
-#define IRQ_SIC_START			(IRQ_CIC_END+1)
-#define IRQ_SIC_CP_SOFTINT		(IRQ_SIC_START+0)
-#define IRQ_SIC_CP_RI0			(IRQ_SIC_START+1)
-#define IRQ_SIC_CP_RI1			(IRQ_SIC_START+2)
-#define IRQ_SIC_CP_CARDIN		(IRQ_SIC_START+3)
-#define IRQ_SIC_CP_LMINT0		(IRQ_SIC_START+4)
-#define IRQ_SIC_CP_LMINT1		(IRQ_SIC_START+5)
-#define IRQ_SIC_CP_LMINT2		(IRQ_SIC_START+6)
-#define IRQ_SIC_CP_LMINT3		(IRQ_SIC_START+7)
-#define IRQ_SIC_CP_LMINT4		(IRQ_SIC_START+8)
-#define IRQ_SIC_CP_LMINT5		(IRQ_SIC_START+9)
-#define IRQ_SIC_CP_LMINT6		(IRQ_SIC_START+10)
-#define IRQ_SIC_CP_LMINT7		(IRQ_SIC_START+11)
-#define IRQ_SIC_END			(IRQ_SIC_START+11)
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index d9e95e6..d50dc2d 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -51,13 +51,13 @@
 #include <asm/mach-types.h>
 
 #include <mach/lm.h>
-#include <mach/irqs.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 
+#include "cm.h"
 #include "common.h"
 #include "pci_v3.h"
 
@@ -146,7 +146,7 @@
 static void irq_resume(void)
 {
 	/* disable all irq sources */
-	writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
+	cm_clear_irqs();
 	writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
 	writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
 
@@ -402,8 +402,6 @@
 {
 }
 
-#ifdef CONFIG_OF
-
 static void __init ap_of_timer_init(void)
 {
 	struct device_node *node;
@@ -450,8 +448,7 @@
 
 static void __init ap_init_irq_of(void)
 {
-	/* disable core module IRQs */
-	writel(0xffffffffU, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
+	cm_init();
 	of_irq_init(fpga_irq_of_match);
 	integrator_clk_init(false);
 }
@@ -473,6 +470,11 @@
 	{ /* sentinel */ },
 };
 
+static const struct of_device_id ap_syscon_match[] = {
+	{ .compatible = "arm,integrator-ap-syscon"},
+	{ },
+};
+
 static void __init ap_init_of(void)
 {
 	unsigned long sc_dec;
@@ -489,7 +491,8 @@
 	root = of_find_node_by_path("/");
 	if (!root)
 		return;
-	syscon = of_find_node_by_path("/syscon");
+
+	syscon = of_find_matching_node(root, ap_syscon_match);
 	if (!syscon)
 		return;
 
@@ -541,7 +544,7 @@
 		lmdev->resource.start = 0xc0000000 + 0x10000000 * i;
 		lmdev->resource.end = lmdev->resource.start + 0x0fffffff;
 		lmdev->resource.flags = IORESOURCE_MEM;
-		lmdev->irq = IRQ_AP_EXPINT0 + i;
+		lmdev->irq = irq_of_parse_and_map(syscon, i);
 		lmdev->id = i;
 
 		lm_device_register(lmdev);
@@ -564,136 +567,3 @@
 	.restart	= integrator_restart,
 	.dt_compat      = ap_dt_board_compat,
 MACHINE_END
-
-#endif
-
-#ifdef CONFIG_ATAGS
-
-/*
- * For the ATAG boot some static mappings are needed. This will
- * go away with the ATAG support down the road.
- */
-
-static struct map_desc ap_io_desc_atag[] __initdata = {
-	{
-		.virtual	= IO_ADDRESS(INTEGRATOR_SC_BASE),
-		.pfn		= __phys_to_pfn(INTEGRATOR_SC_BASE),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE
-	},
-};
-
-static void __init ap_map_io_atag(void)
-{
-	iotable_init(ap_io_desc_atag, ARRAY_SIZE(ap_io_desc_atag));
-	ap_map_io();
-}
-
-/*
- * This is where non-devicetree initialization code is collected and stashed
- * for eventual deletion.
- */
-
-static struct platform_device pci_v3_device = {
-	.name		= "pci-v3",
-	.id		= 0,
-};
-
-static struct resource cfi_flash_resource = {
-	.start		= INTEGRATOR_FLASH_BASE,
-	.end		= INTEGRATOR_FLASH_BASE + INTEGRATOR_FLASH_SIZE - 1,
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device cfi_flash_device = {
-	.name		= "physmap-flash",
-	.id		= 0,
-	.dev		= {
-		.platform_data	= &ap_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &cfi_flash_resource,
-};
-
-static void __init ap_timer_init(void)
-{
-	struct clk *clk;
-	unsigned long rate;
-
-	clk = clk_get_sys("ap_timer", NULL);
-	BUG_ON(IS_ERR(clk));
-	clk_prepare_enable(clk);
-	rate = clk_get_rate(clk);
-
-	writel(0, TIMER0_VA_BASE + TIMER_CTRL);
-	writel(0, TIMER1_VA_BASE + TIMER_CTRL);
-	writel(0, TIMER2_VA_BASE + TIMER_CTRL);
-
-	integrator_clocksource_init(rate, (void __iomem *)TIMER2_VA_BASE);
-	integrator_clockevent_init(rate, (void __iomem *)TIMER1_VA_BASE,
-				IRQ_TIMERINT1);
-}
-
-#define INTEGRATOR_SC_VALID_INT	0x003fffff
-
-static void __init ap_init_irq(void)
-{
-	/* Disable all interrupts initially. */
-	/* Do the core module ones */
-	writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
-
-	/* do the header card stuff next */
-	writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
-	writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
-
-	fpga_irq_init(VA_IC_BASE, "SC", IRQ_PIC_START,
-		-1, INTEGRATOR_SC_VALID_INT, NULL);
-	integrator_clk_init(false);
-}
-
-static void __init ap_init(void)
-{
-	unsigned long sc_dec;
-	int i;
-
-	platform_device_register(&pci_v3_device);
-	platform_device_register(&cfi_flash_device);
-
-	ap_syscon_base = __io_address(INTEGRATOR_SC_BASE);
-	sc_dec = readl(ap_syscon_base + INTEGRATOR_SC_DEC_OFFSET);
-	for (i = 0; i < 4; i++) {
-		struct lm_device *lmdev;
-
-		if ((sc_dec & (16 << i)) == 0)
-			continue;
-
-		lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL);
-		if (!lmdev)
-			continue;
-
-		lmdev->resource.start = 0xc0000000 + 0x10000000 * i;
-		lmdev->resource.end = lmdev->resource.start + 0x0fffffff;
-		lmdev->resource.flags = IORESOURCE_MEM;
-		lmdev->irq = IRQ_AP_EXPINT0 + i;
-		lmdev->id = i;
-
-		lm_device_register(lmdev);
-	}
-
-	integrator_init(false);
-}
-
-MACHINE_START(INTEGRATOR, "ARM-Integrator")
-	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.atag_offset	= 0x100,
-	.reserve	= integrator_reserve,
-	.map_io		= ap_map_io_atag,
-	.init_early	= ap_init_early,
-	.init_irq	= ap_init_irq,
-	.handle_irq	= fpga_handle_irq,
-	.init_time	= ap_timer_init,
-	.init_machine	= ap_init,
-	.restart	= integrator_restart,
-MACHINE_END
-
-#endif
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 8c60fcb..1df6e76 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -36,9 +36,7 @@
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/icst.h>
 
-#include <mach/cm.h>
 #include <mach/lm.h>
-#include <mach/irqs.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
@@ -50,6 +48,7 @@
 #include <plat/clcd.h>
 #include <plat/sched_clock.h>
 
+#include "cm.h"
 #include "common.h"
 
 /* Base address to the CP controller */
@@ -249,7 +248,6 @@
 #endif
 }
 
-#ifdef CONFIG_OF
 static const struct of_device_id fpga_irq_of_match[] __initconst = {
 	{ .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
 	{ /* Sentinel */ }
@@ -257,6 +255,7 @@
 
 static void __init intcp_init_irq_of(void)
 {
+	cm_init();
 	of_irq_init(fpga_irq_of_match);
 	integrator_clk_init(true);
 }
@@ -287,6 +286,11 @@
 	{ /* sentinel */ },
 };
 
+static const struct of_device_id intcp_syscon_match[] = {
+	{ .compatible = "arm,integrator-cp-syscon"},
+	{ },
+};
+
 static void __init intcp_init_of(void)
 {
 	struct device_node *root;
@@ -301,7 +305,8 @@
 	root = of_find_node_by_path("/");
 	if (!root)
 		return;
-	cpcon = of_find_node_by_path("/cpcon");
+
+	cpcon = of_find_matching_node(root, intcp_syscon_match);
 	if (!cpcon)
 		return;
 
@@ -354,175 +359,3 @@
 	.restart	= integrator_restart,
 	.dt_compat      = intcp_dt_board_compat,
 MACHINE_END
-
-#endif
-
-#ifdef CONFIG_ATAGS
-
-/*
- * For the ATAG boot some static mappings are needed. This will
- * go away with the ATAG support down the road.
- */
-
-static struct map_desc intcp_io_desc_atag[] __initdata = {
-	{
-		.virtual	= IO_ADDRESS(INTEGRATOR_CP_CTL_BASE),
-		.pfn		= __phys_to_pfn(INTEGRATOR_CP_CTL_BASE),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE
-	},
-};
-
-static void __init intcp_map_io_atag(void)
-{
-	iotable_init(intcp_io_desc_atag, ARRAY_SIZE(intcp_io_desc_atag));
-	intcp_con_base = __io_address(INTEGRATOR_CP_CTL_BASE);
-	intcp_map_io();
-}
-
-
-/*
- * This is where non-devicetree initialization code is collected and stashed
- * for eventual deletion.
- */
-
-#define INTCP_FLASH_SIZE		SZ_32M
-
-static struct resource intcp_flash_resource = {
-	.start		= INTCP_PA_FLASH_BASE,
-	.end		= INTCP_PA_FLASH_BASE + INTCP_FLASH_SIZE - 1,
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device intcp_flash_device = {
-	.name		= "physmap-flash",
-	.id		= 0,
-	.dev		= {
-		.platform_data	= &intcp_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &intcp_flash_resource,
-};
-
-#define INTCP_ETH_SIZE			0x10
-
-static struct resource smc91x_resources[] = {
-	[0] = {
-		.start	= INTEGRATOR_CP_ETH_BASE,
-		.end	= INTEGRATOR_CP_ETH_BASE + INTCP_ETH_SIZE - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_CP_ETHINT,
-		.end	= IRQ_CP_ETHINT,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device smc91x_device = {
-	.name		= "smc91x",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(smc91x_resources),
-	.resource	= smc91x_resources,
-};
-
-static struct platform_device *intcp_devs[] __initdata = {
-	&intcp_flash_device,
-	&smc91x_device,
-};
-
-#define INTCP_VA_CIC_BASE		__io_address(INTEGRATOR_HDR_BASE + 0x40)
-#define INTCP_VA_PIC_BASE		__io_address(INTEGRATOR_IC_BASE)
-#define INTCP_VA_SIC_BASE		__io_address(INTEGRATOR_CP_SIC_BASE)
-
-static void __init intcp_init_irq(void)
-{
-	u32 pic_mask, cic_mask, sic_mask;
-
-	/* These masks are for the HW IRQ registers */
-	pic_mask = ~((~0u) << (11 - 0));
-	pic_mask |= (~((~0u) << (29 - 22))) << 22;
-	cic_mask = ~((~0u) << (1 + IRQ_CIC_END - IRQ_CIC_START));
-	sic_mask = ~((~0u) << (1 + IRQ_SIC_END - IRQ_SIC_START));
-
-	/*
-	 * Disable all interrupt sources
-	 */
-	writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR);
-	writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR);
-	writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);
-	writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR);
-	writel(sic_mask, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);
-	writel(sic_mask, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR);
-
-	fpga_irq_init(INTCP_VA_PIC_BASE, "PIC", IRQ_PIC_START,
-		      -1, pic_mask, NULL);
-
-	fpga_irq_init(INTCP_VA_CIC_BASE, "CIC", IRQ_CIC_START,
-		      -1, cic_mask, NULL);
-
-	fpga_irq_init(INTCP_VA_SIC_BASE, "SIC", IRQ_SIC_START,
-		      IRQ_CP_CPPLDINT, sic_mask, NULL);
-
-	integrator_clk_init(true);
-}
-
-#define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE)
-#define TIMER1_VA_BASE __io_address(INTEGRATOR_TIMER1_BASE)
-#define TIMER2_VA_BASE __io_address(INTEGRATOR_TIMER2_BASE)
-
-static void __init cp_timer_init(void)
-{
-	writel(0, TIMER0_VA_BASE + TIMER_CTRL);
-	writel(0, TIMER1_VA_BASE + TIMER_CTRL);
-	writel(0, TIMER2_VA_BASE + TIMER_CTRL);
-
-	sp804_clocksource_init(TIMER2_VA_BASE, "timer2");
-	sp804_clockevents_init(TIMER1_VA_BASE, IRQ_TIMERINT1, "timer1");
-}
-
-#define INTEGRATOR_CP_MMC_IRQS	{ IRQ_CP_MMCIINT0, IRQ_CP_MMCIINT1 }
-#define INTEGRATOR_CP_AACI_IRQS	{ IRQ_CP_AACIINT }
-
-static AMBA_APB_DEVICE(mmc, "mmci", 0, INTEGRATOR_CP_MMC_BASE,
-	INTEGRATOR_CP_MMC_IRQS, &mmc_data);
-
-static AMBA_APB_DEVICE(aaci, "aaci", 0, INTEGRATOR_CP_AACI_BASE,
-	INTEGRATOR_CP_AACI_IRQS, NULL);
-
-static AMBA_AHB_DEVICE(clcd, "clcd", 0, INTCP_PA_CLCD_BASE,
-	{ IRQ_CP_CLCDCINT }, &clcd_data);
-
-static struct amba_device *amba_devs[] __initdata = {
-	&mmc_device,
-	&aaci_device,
-	&clcd_device,
-};
-
-static void __init intcp_init(void)
-{
-	int i;
-
-	platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs));
-
-	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
-		struct amba_device *d = amba_devs[i];
-		amba_device_register(d, &iomem_resource);
-	}
-	integrator_init(true);
-}
-
-MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
-	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.atag_offset	= 0x100,
-	.reserve	= integrator_reserve,
-	.map_io		= intcp_map_io_atag,
-	.init_early	= intcp_init_early,
-	.init_irq	= intcp_init_irq,
-	.handle_irq	= fpga_handle_irq,
-	.init_time	= cp_timer_init,
-	.init_machine	= intcp_init,
-	.restart	= integrator_restart,
-MACHINE_END
-
-#endif
diff --git a/arch/arm/mach-integrator/leds.c b/arch/arm/mach-integrator/leds.c
index 7a7f6d3..cb6ac58 100644
--- a/arch/arm/mach-integrator/leds.c
+++ b/arch/arm/mach-integrator/leds.c
@@ -11,10 +11,11 @@
 #include <linux/slab.h>
 #include <linux/leds.h>
 
-#include <mach/cm.h>
 #include <mach/hardware.h>
 #include <mach/platform.h>
 
+#include "cm.h"
+
 #if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
 
 #define ALPHA_REG __io_address(INTEGRATOR_DBG_BASE)
@@ -78,7 +79,7 @@
 
 static enum led_brightness cm_led_get(struct led_classdev *cdev)
 {
-	u32 reg = readl(CM_CTRL);
+	u32 reg = cm_get();
 
 	return (reg & CM_CTRL_LED) ? LED_FULL : LED_OFF;
 }
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index bef1005..c5e01b2 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -36,7 +36,6 @@
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <mach/irqs.h>
 
 #include <asm/mach/map.h>
 #include <asm/signal.h>
@@ -605,7 +604,7 @@
 	return 1;
 }
 
-static irqreturn_t v3_irq(int dummy, void *devid)
+static irqreturn_t v3_irq(int irq, void *devid)
 {
 #ifdef CONFIG_DEBUG_LL
 	struct pt_regs *regs = get_irq_regs();
@@ -615,7 +614,7 @@
 	extern void printascii(const char *);
 
 	sprintf(buf, "V3 int %d: pc=0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x "
-		"ISTAT=%02x\n", IRQ_AP_V3INT, pc, instr,
+		"ISTAT=%02x\n", irq, pc, instr,
 		__raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFADDR_OFFSET),
 		__raw_readl(ap_syscon_base + INTEGRATOR_SC_LBFCODE_OFFSET) & 255,
 		v3_readb(V3_LB_ISTAT));
@@ -809,21 +808,6 @@
 	return pci_common_swizzle(dev, pinp);
 }
 
-static int irq_tab[4] __initdata = {
-	IRQ_AP_PCIINT0,	IRQ_AP_PCIINT1,	IRQ_AP_PCIINT2,	IRQ_AP_PCIINT3
-};
-
-/*
- * map the specified device/slot/pin to an IRQ.  This works out such
- * that slot 9 pin 1 is INT0, pin 2 is INT1, and slot 10 pin 1 is INT1.
- */
-static int __init pci_v3_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	int intnr = ((slot - 9) + (pin - 1)) & 3;
-
-	return irq_tab[intnr];
-}
-
 static struct hw_pci pci_v3 __initdata = {
 	.swizzle		= pci_v3_swizzle,
 	.setup			= pci_v3_setup,
@@ -833,32 +817,27 @@
 	.postinit		= pci_v3_postinit,
 };
 
-#ifdef CONFIG_OF
-
-static int __init pci_v3_map_irq_dt(const struct pci_dev *dev, u8 slot, u8 pin)
+static int __init pci_v3_probe(struct platform_device *pdev)
 {
-	struct of_irq oirq;
-	int ret;
-
-	ret = of_irq_map_pci(dev, &oirq);
-	if (ret) {
-		dev_err(&dev->dev, "of_irq_map_pci() %d\n", ret);
-		/* Proper return code 0 == NO_IRQ */
-		return 0;
-	}
-
-	return irq_create_of_mapping(oirq.controller, oirq.specifier,
-				     oirq.size);
-}
-
-static int __init pci_v3_dtprobe(struct platform_device *pdev,
-				struct device_node *np)
-{
+	struct device_node *np = pdev->dev.of_node;
 	struct of_pci_range_parser parser;
 	struct of_pci_range range;
 	struct resource *res;
 	int irq, ret;
 
+	/* Remap the Integrator system controller */
+	ap_syscon_base = devm_ioremap(&pdev->dev, INTEGRATOR_SC_BASE, 0x100);
+	if (!ap_syscon_base) {
+		dev_err(&pdev->dev, "unable to remap the AP syscon for PCIv3\n");
+		return -ENODEV;
+	}
+
+	/* Device tree probe path */
+	if (!np) {
+		dev_err(&pdev->dev, "no device tree node for PCIv3\n");
+		return -ENODEV;
+	}
+
 	if (of_pci_range_parser_init(&parser, np))
 		return -EINVAL;
 
@@ -919,77 +898,7 @@
 		return -EINVAL;
 	}
 
-	pci_v3.map_irq = pci_v3_map_irq_dt;
-	pci_common_init_dev(&pdev->dev, &pci_v3);
-
-	return 0;
-}
-
-#else
-
-static inline int pci_v3_dtprobe(struct platform_device *pdev,
-				  struct device_node *np)
-{
-	return -EINVAL;
-}
-
-#endif
-
-static int __init pci_v3_probe(struct platform_device *pdev)
-{
-	struct device_node *np = pdev->dev.of_node;
-	int ret;
-
-	/* Remap the Integrator system controller */
-	ap_syscon_base = ioremap(INTEGRATOR_SC_BASE, 0x100);
-	if (!ap_syscon_base) {
-		dev_err(&pdev->dev, "unable to remap the AP syscon for PCIv3\n");
-		return -ENODEV;
-	}
-
-	/* Device tree probe path */
-	if (np)
-		return pci_v3_dtprobe(pdev, np);
-
-	pci_v3_base = devm_ioremap(&pdev->dev, PHYS_PCI_V3_BASE, SZ_64K);
-	if (!pci_v3_base) {
-		dev_err(&pdev->dev, "unable to remap PCIv3 base\n");
-		return -ENODEV;
-	}
-
-	ret = devm_request_irq(&pdev->dev, IRQ_AP_V3INT, v3_irq, 0, "V3", NULL);
-	if (ret) {
-		dev_err(&pdev->dev, "unable to grab PCI error interrupt: %d\n",
-			ret);
-		return -ENODEV;
-	}
-
-	conf_mem.name = "PCIv3 config";
-	conf_mem.start = PHYS_PCI_CONFIG_BASE;
-	conf_mem.end = PHYS_PCI_CONFIG_BASE + SZ_16M - 1;
-	conf_mem.flags = IORESOURCE_MEM;
-
-	io_mem.name = "PCIv3 I/O";
-	io_mem.start = PHYS_PCI_IO_BASE;
-	io_mem.end = PHYS_PCI_IO_BASE + SZ_16M - 1;
-	io_mem.flags = IORESOURCE_MEM;
-
-	non_mem_pci = 0x00000000;
-	non_mem_pci_sz = SZ_256M;
-	non_mem.name = "PCIv3 non-prefetched mem";
-	non_mem.start = PHYS_PCI_MEM_BASE;
-	non_mem.end = PHYS_PCI_MEM_BASE + SZ_256M - 1;
-	non_mem.flags = IORESOURCE_MEM;
-
-	pre_mem_pci = 0x10000000;
-	pre_mem_pci_sz = SZ_256M;
-	pre_mem.name = "PCIv3 prefetched mem";
-	pre_mem.start = PHYS_PCI_PRE_BASE + SZ_256M;
-	pre_mem.end = PHYS_PCI_PRE_BASE + SZ_256M - 1;
-	pre_mem.flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
-
-	pci_v3.map_irq = pci_v3_map_irq;
-
+	pci_v3.map_irq = of_irq_parse_and_map_pci;
 	pci_common_init_dev(&pdev->dev, &pci_v3);
 
 	return 0;
diff --git a/arch/arm/mach-iop32x/em7210.c b/arch/arm/mach-iop32x/em7210.c
index 31fbb6c..177cd07 100644
--- a/arch/arm/mach-iop32x/em7210.c
+++ b/arch/arm/mach-iop32x/em7210.c
@@ -32,6 +32,7 @@
 #include <asm/mach/time.h>
 #include <asm/mach-types.h>
 #include <mach/time.h>
+#include "gpio-iop32x.h"
 
 static void __init em7210_timer_init(void)
 {
@@ -183,6 +184,7 @@
 
 static void __init em7210_init_machine(void)
 {
+	register_iop32x_gpio();
 	platform_device_register(&em7210_serial_device);
 	platform_device_register(&iop3xx_i2c0_device);
 	platform_device_register(&iop3xx_i2c1_device);
diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c
index ac30470..547b234 100644
--- a/arch/arm/mach-iop32x/glantank.c
+++ b/arch/arm/mach-iop32x/glantank.c
@@ -34,6 +34,7 @@
 #include <asm/mach-types.h>
 #include <asm/page.h>
 #include <mach/time.h>
+#include "gpio-iop32x.h"
 
 /*
  * GLAN Tank timer tick configuration.
@@ -187,6 +188,7 @@
 
 static void __init glantank_init_machine(void)
 {
+	register_iop32x_gpio();
 	platform_device_register(&iop3xx_i2c0_device);
 	platform_device_register(&iop3xx_i2c1_device);
 	platform_device_register(&glantank_flash_device);
diff --git a/arch/arm/mach-iop32x/gpio-iop32x.h b/arch/arm/mach-iop32x/gpio-iop32x.h
new file mode 100644
index 0000000..3c7309c
--- /dev/null
+++ b/arch/arm/mach-iop32x/gpio-iop32x.h
@@ -0,0 +1,10 @@
+static struct resource iop32x_gpio_res[] = {
+	DEFINE_RES_MEM((IOP3XX_PERIPHERAL_PHYS_BASE + 0x07c4), 0x10),
+};
+
+static inline void register_iop32x_gpio(void)
+{
+	platform_device_register_simple("gpio-iop", 0,
+					iop32x_gpio_res,
+					ARRAY_SIZE(iop32x_gpio_res));
+}
diff --git a/arch/arm/mach-iop32x/include/mach/gpio.h b/arch/arm/mach-iop32x/include/mach/gpio.h
deleted file mode 100644
index 708f4ec..0000000
--- a/arch/arm/mach-iop32x/include/mach/gpio.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_ARCH_IOP32X_GPIO_H
-#define __ASM_ARCH_IOP32X_GPIO_H
-
-#include <asm/hardware/iop3xx-gpio.h>
-
-#endif
diff --git a/arch/arm/mach-iop32x/include/mach/iop32x.h b/arch/arm/mach-iop32x/include/mach/iop32x.h
index 941f363..56ec864 100644
--- a/arch/arm/mach-iop32x/include/mach/iop32x.h
+++ b/arch/arm/mach-iop32x/include/mach/iop32x.h
@@ -19,7 +19,6 @@
  * Peripherals that are shared between the iop32x and iop33x but
  * located at different addresses.
  */
-#define IOP3XX_GPIO_REG(reg)	(IOP3XX_PERIPHERAL_VIRT_BASE + 0x07c4 + (reg))
 #define IOP3XX_TIMER_REG(reg)	(IOP3XX_PERIPHERAL_VIRT_BASE + 0x07e0 + (reg))
 
 #include <asm/hardware/iop3xx.h>
diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c
index f2cd296..0e1392b 100644
--- a/arch/arm/mach-iop32x/iq31244.c
+++ b/arch/arm/mach-iop32x/iq31244.c
@@ -37,6 +37,7 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <mach/time.h>
+#include "gpio-iop32x.h"
 
 /*
  * Until March of 2007 iq31244 platforms and ep80219 platforms shared the
@@ -283,6 +284,7 @@
 
 static void __init iq31244_init_machine(void)
 {
+	register_iop32x_gpio();
 	platform_device_register(&iop3xx_i2c0_device);
 	platform_device_register(&iop3xx_i2c1_device);
 	platform_device_register(&iq31244_flash_device);
diff --git a/arch/arm/mach-iop32x/iq80321.c b/arch/arm/mach-iop32x/iq80321.c
index 015435d..66782ff 100644
--- a/arch/arm/mach-iop32x/iq80321.c
+++ b/arch/arm/mach-iop32x/iq80321.c
@@ -33,6 +33,7 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <mach/time.h>
+#include "gpio-iop32x.h"
 
 /*
  * IQ80321 timer tick configuration.
@@ -170,6 +171,7 @@
 
 static void __init iq80321_init_machine(void)
 {
+	register_iop32x_gpio();
 	platform_device_register(&iop3xx_i2c0_device);
 	platform_device_register(&iop3xx_i2c1_device);
 	platform_device_register(&iq80321_flash_device);
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index 0691443..c1cd80e 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -30,6 +30,7 @@
 #include <linux/platform_device.h>
 #include <linux/reboot.h>
 #include <linux/io.h>
+#include <linux/gpio.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
@@ -40,6 +41,7 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <mach/time.h>
+#include "gpio-iop32x.h"
 
 /*
  * N2100 timer tick configuration.
@@ -288,8 +290,14 @@
 
 static void n2100_restart(enum reboot_mode mode, const char *cmd)
 {
-	gpio_line_set(N2100_HARDWARE_RESET, GPIO_LOW);
-	gpio_line_config(N2100_HARDWARE_RESET, GPIO_OUT);
+	int ret;
+
+	ret = gpio_direction_output(N2100_HARDWARE_RESET, 0);
+	if (ret) {
+		pr_crit("could not drive reset GPIO low\n");
+		return;
+	}
+	/* Wait for reset to happen */
 	while (1)
 		;
 }
@@ -299,7 +307,7 @@
 
 static void power_button_poll(unsigned long dummy)
 {
-	if (gpio_line_get(N2100_POWER_BUTTON) == 0) {
+	if (gpio_get_value(N2100_POWER_BUTTON) == 0) {
 		ctrl_alt_del();
 		return;
 	}
@@ -308,9 +316,37 @@
 	add_timer(&power_button_poll_timer);
 }
 
+static int __init n2100_request_gpios(void)
+{
+	int ret;
+
+	if (!machine_is_n2100())
+		return 0;
+
+	ret = gpio_request(N2100_HARDWARE_RESET, "reset");
+	if (ret)
+		pr_err("could not request reset GPIO\n");
+
+	ret = gpio_request(N2100_POWER_BUTTON, "power");
+	if (ret)
+		pr_err("could not request power GPIO\n");
+	else {
+		ret = gpio_direction_input(N2100_POWER_BUTTON);
+		if (ret)
+			pr_err("could not set power GPIO as input\n");
+	}
+	/* Set up power button poll timer */
+	init_timer(&power_button_poll_timer);
+	power_button_poll_timer.function = power_button_poll;
+	power_button_poll_timer.expires = jiffies + (HZ / 10);
+	add_timer(&power_button_poll_timer);
+	return 0;
+}
+device_initcall(n2100_request_gpios);
 
 static void __init n2100_init_machine(void)
 {
+	register_iop32x_gpio();
 	platform_device_register(&iop3xx_i2c0_device);
 	platform_device_register(&n2100_flash_device);
 	platform_device_register(&n2100_serial_device);
@@ -321,11 +357,6 @@
 		ARRAY_SIZE(n2100_i2c_devices));
 
 	pm_power_off = n2100_power_off;
-
-	init_timer(&power_button_poll_timer);
-	power_button_poll_timer.function = power_button_poll;
-	power_button_poll_timer.expires = jiffies + (HZ / 10);
-	add_timer(&power_button_poll_timer);
 }
 
 MACHINE_START(N2100, "Thecus N2100")
diff --git a/arch/arm/mach-iop33x/include/mach/gpio.h b/arch/arm/mach-iop33x/include/mach/gpio.h
deleted file mode 100644
index ddd55bb..0000000
--- a/arch/arm/mach-iop33x/include/mach/gpio.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_ARCH_IOP33X_GPIO_H
-#define __ASM_ARCH_IOP33X_GPIO_H
-
-#include <asm/hardware/iop3xx-gpio.h>
-
-#endif
diff --git a/arch/arm/mach-iop33x/include/mach/iop33x.h b/arch/arm/mach-iop33x/include/mach/iop33x.h
index a89c0a2..c951226 100644
--- a/arch/arm/mach-iop33x/include/mach/iop33x.h
+++ b/arch/arm/mach-iop33x/include/mach/iop33x.h
@@ -18,7 +18,6 @@
  * Peripherals that are shared between the iop32x and iop33x but
  * located at different addresses.
  */
-#define IOP3XX_GPIO_REG(reg)	(IOP3XX_PERIPHERAL_VIRT_BASE + 0x1780 + (reg))
 #define IOP3XX_TIMER_REG(reg)	(IOP3XX_PERIPHERAL_VIRT_BASE + 0x07d0 + (reg))
 
 #include <asm/hardware/iop3xx.h>
diff --git a/arch/arm/mach-iop33x/iq80331.c b/arch/arm/mach-iop33x/iq80331.c
index c43304a..e2cb65c 100644
--- a/arch/arm/mach-iop33x/iq80331.c
+++ b/arch/arm/mach-iop33x/iq80331.c
@@ -122,8 +122,15 @@
 	.resource	= &iq80331_flash_resource,
 };
 
+static struct resource iq80331_gpio_res[] = {
+	DEFINE_RES_MEM((IOP3XX_PERIPHERAL_PHYS_BASE + 0x1780), 0x10),
+};
+
 static void __init iq80331_init_machine(void)
 {
+	platform_device_register_simple("gpio-iop", 0,
+					iq80331_gpio_res,
+					ARRAY_SIZE(iq80331_gpio_res));
 	platform_device_register(&iop3xx_i2c0_device);
 	platform_device_register(&iop3xx_i2c1_device);
 	platform_device_register(&iop33x_uart0_device);
diff --git a/arch/arm/mach-iop33x/iq80332.c b/arch/arm/mach-iop33x/iq80332.c
index 8192987..0b6269d 100644
--- a/arch/arm/mach-iop33x/iq80332.c
+++ b/arch/arm/mach-iop33x/iq80332.c
@@ -122,8 +122,15 @@
 	.resource	= &iq80332_flash_resource,
 };
 
+static struct resource iq80332_gpio_res[] = {
+	DEFINE_RES_MEM((IOP3XX_PERIPHERAL_PHYS_BASE + 0x1780), 0x10),
+};
+
 static void __init iq80332_init_machine(void)
 {
+	platform_device_register_simple("gpio-iop", 0,
+					iq80332_gpio_res,
+					ARRAY_SIZE(iq80332_gpio_res));
 	platform_device_register(&iop3xx_i2c0_device);
 	platform_device_register(&iop3xx_i2c1_device);
 	platform_device_register(&iop33x_uart0_device);
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 5327dec..9edaf47 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -81,6 +81,44 @@
   	iotable_init(ixp4xx_io_desc, ARRAY_SIZE(ixp4xx_io_desc));
 }
 
+/*
+ * GPIO-functions
+ */
+/*
+ * The following converted to the real HW bits the gpio_line_config
+ */
+/* GPIO pin types */
+#define IXP4XX_GPIO_OUT 		0x1
+#define IXP4XX_GPIO_IN  		0x2
+
+/* GPIO signal types */
+#define IXP4XX_GPIO_LOW			0
+#define IXP4XX_GPIO_HIGH		1
+
+/* GPIO Clocks */
+#define IXP4XX_GPIO_CLK_0		14
+#define IXP4XX_GPIO_CLK_1		15
+
+static void gpio_line_config(u8 line, u32 direction)
+{
+	if (direction == IXP4XX_GPIO_IN)
+		*IXP4XX_GPIO_GPOER |= (1 << line);
+	else
+		*IXP4XX_GPIO_GPOER &= ~(1 << line);
+}
+
+static void gpio_line_get(u8 line, int *value)
+{
+	*value = (*IXP4XX_GPIO_GPINR >> line) & 0x1;
+}
+
+static void gpio_line_set(u8 line, int value)
+{
+	if (value == IXP4XX_GPIO_HIGH)
+	    *IXP4XX_GPIO_GPOUTR |= (1 << line);
+	else if (value == IXP4XX_GPIO_LOW)
+	    *IXP4XX_GPIO_GPOUTR &= ~(1 << line);
+}
 
 /*************************************************************************
  * IXP4xx chipset IRQ handling
@@ -117,17 +155,6 @@
 	return -EINVAL;
 }
 
-int irq_to_gpio(unsigned int irq)
-{
-	int gpio = (irq < 32) ? irq2gpio[irq] : -EINVAL;
-
-	if (gpio == -1)
-		return -EINVAL;
-
-	return gpio;
-}
-EXPORT_SYMBOL(irq_to_gpio);
-
 static int ixp4xx_set_irq_type(struct irq_data *d, unsigned int type)
 {
 	int line = irq2gpio[d->irq];
diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
index 63de1b3..736dc69 100644
--- a/arch/arm/mach-ixp4xx/dsmg600-setup.c
+++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c
@@ -26,6 +26,7 @@
 #include <linux/reboot.h>
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
+#include <linux/gpio.h>
 
 #include <mach/hardware.h>
 
@@ -161,11 +162,8 @@
 
 static void dsmg600_power_off(void)
 {
-	/* enable the pwr cntl gpio */
-	gpio_line_config(DSMG600_PO_GPIO, IXP4XX_GPIO_OUT);
-
-	/* poweroff */
-	gpio_line_set(DSMG600_PO_GPIO, IXP4XX_GPIO_HIGH);
+	/* enable the pwr cntl and drive it high */
+	gpio_direction_output(DSMG600_PO_GPIO, 1);
 }
 
 /* This is used to make sure the power-button pusher is serious.  The button
@@ -202,7 +200,7 @@
 			ctrl_alt_del();
 
 			/* Change the state of the power LED to "blink" */
-			gpio_line_set(DSMG600_LED_PWR_GPIO, IXP4XX_GPIO_LOW);
+			gpio_set_value(DSMG600_LED_PWR_GPIO, 0);
 		} else {
 			power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
 		}
@@ -228,6 +226,40 @@
     ixp4xx_timer_init();
 }
 
+static int __init dsmg600_gpio_init(void)
+{
+	if (!machine_is_dsmg600())
+		return 0;
+
+	gpio_request(DSMG600_RB_GPIO, "reset button");
+	if (request_irq(gpio_to_irq(DSMG600_RB_GPIO), &dsmg600_reset_handler,
+		IRQF_DISABLED | IRQF_TRIGGER_LOW,
+		"DSM-G600 reset button", NULL) < 0) {
+
+		printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
+			gpio_to_irq(DSMG600_RB_GPIO));
+	}
+
+	/*
+	 * The power button on the D-Link DSM-G600 is on GPIO 15, but
+	 * it cannot handle interrupts on that GPIO line.  So we'll
+	 * have to poll it with a kernel timer.
+	 */
+
+	/* Make sure that the power button GPIO is set up as an input */
+	gpio_request(DSMG600_PB_GPIO, "power button");
+	gpio_direction_input(DSMG600_PB_GPIO);
+	/* Request poweroff GPIO line */
+	gpio_request(DSMG600_PO_GPIO, "power off button");
+
+	/* Set the initial value for the power button IRQ handler */
+	power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
+
+	mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
+	return 0;
+}
+device_initcall(dsmg600_gpio_init);
+
 static void __init dsmg600_init(void)
 {
 	ixp4xx_sys_init();
@@ -251,27 +283,6 @@
 	platform_add_devices(dsmg600_devices, ARRAY_SIZE(dsmg600_devices));
 
 	pm_power_off = dsmg600_power_off;
-
-	if (request_irq(gpio_to_irq(DSMG600_RB_GPIO), &dsmg600_reset_handler,
-		IRQF_DISABLED | IRQF_TRIGGER_LOW,
-		"DSM-G600 reset button", NULL) < 0) {
-
-		printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
-			gpio_to_irq(DSMG600_RB_GPIO));
-	}
-
-	/* The power button on the D-Link DSM-G600 is on GPIO 15, but
-	 * it cannot handle interrupts on that GPIO line.  So we'll
-	 * have to poll it with a kernel timer.
-	 */
-
-	/* Make sure that the power button GPIO is set up as an input */
-	gpio_line_config(DSMG600_PB_GPIO, IXP4XX_GPIO_IN);
-
-	/* Set the initial value for the power button IRQ handler */
-	power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
-
-	mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
 }
 
 MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
diff --git a/arch/arm/mach-ixp4xx/include/mach/platform.h b/arch/arm/mach-ixp4xx/include/mach/platform.h
index 4c4c6a6..75c4c65 100644
--- a/arch/arm/mach-ixp4xx/include/mach/platform.h
+++ b/arch/arm/mach-ixp4xx/include/mach/platform.h
@@ -131,44 +131,5 @@
 extern int ixp4xx_setup(int nr, struct pci_sys_data *sys);
 extern struct pci_ops ixp4xx_ops;
 
-/*
- * GPIO-functions
- */
-/*
- * The following converted to the real HW bits the gpio_line_config
- */
-/* GPIO pin types */
-#define IXP4XX_GPIO_OUT 		0x1
-#define IXP4XX_GPIO_IN  		0x2
-
-/* GPIO signal types */
-#define IXP4XX_GPIO_LOW			0
-#define IXP4XX_GPIO_HIGH		1
-
-/* GPIO Clocks */
-#define IXP4XX_GPIO_CLK_0		14
-#define IXP4XX_GPIO_CLK_1		15
-
-static inline void gpio_line_config(u8 line, u32 direction)
-{
-	if (direction == IXP4XX_GPIO_IN)
-		*IXP4XX_GPIO_GPOER |= (1 << line);
-	else
-		*IXP4XX_GPIO_GPOER &= ~(1 << line);
-}
-
-static inline void gpio_line_get(u8 line, int *value)
-{
-	*value = (*IXP4XX_GPIO_GPINR >> line) & 0x1;
-}
-
-static inline void gpio_line_set(u8 line, int value)
-{
-	if (value == IXP4XX_GPIO_HIGH)
-	    *IXP4XX_GPIO_GPOUTR |= (1 << line);
-	else if (value == IXP4XX_GPIO_LOW)
-	    *IXP4XX_GPIO_GPOUTR &= ~(1 << line);
-}
-
 #endif // __ASSEMBLY__
 
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index 22d688b..e7b8bef 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -20,6 +20,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <asm/types.h>
 #include <asm/setup.h>
 #include <asm/memory.h>
@@ -80,10 +81,10 @@
 
 	if (ctrl & NAND_CTRL_CHANGE) {
 		if (ctrl & NAND_NCE) {
-			gpio_line_set(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_LOW);
+			gpio_set_value(IXDP425_NAND_NCE_PIN, 0);
 			udelay(5);
 		} else
-			gpio_line_set(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_HIGH);
+			gpio_set_value(IXDP425_NAND_NCE_PIN, 1);
 
 		offset = (ctrl & NAND_CLE) ? IXDP425_NAND_CMD_BYTE : 0;
 		offset |= (ctrl & NAND_ALE) ? IXDP425_NAND_ADDR_BYTE : 0;
@@ -227,7 +228,8 @@
 	ixdp425_flash_nand_resource.start = IXP4XX_EXP_BUS_BASE(3),
 	ixdp425_flash_nand_resource.end   = IXP4XX_EXP_BUS_BASE(3) + 0x10 - 1;
 
-	gpio_line_config(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_OUT);
+	gpio_request(IXDP425_NAND_NCE_PIN, "NAND NCE pin");
+	gpio_direction_output(IXDP425_NAND_NCE_PIN, 0);
 
 	/* Configure expansion bus for NAND Flash */
 	*IXP4XX_EXP_CS3 = IXP4XX_EXP_BUS_CS_EN |
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index ed667ce..507cb52 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -184,11 +184,8 @@
 {
 	/* This causes the box to drop the power and go dead. */
 
-	/* enable the pwr cntl gpio */
-	gpio_line_config(NAS100D_PO_GPIO, IXP4XX_GPIO_OUT);
-
-	/* do the deed */
-	gpio_line_set(NAS100D_PO_GPIO, IXP4XX_GPIO_HIGH);
+	/* enable the pwr cntl gpio and assert power off */
+	gpio_direction_output(NAS100D_PO_GPIO, 1);
 }
 
 /* This is used to make sure the power-button pusher is serious.  The button
@@ -225,7 +222,7 @@
 			ctrl_alt_del();
 
 			/* Change the state of the power LED to "blink" */
-			gpio_line_set(NAS100D_LED_PWR_GPIO, IXP4XX_GPIO_LOW);
+			gpio_set_value(NAS100D_LED_PWR_GPIO, 0);
 		} else {
 			power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
 		}
@@ -242,6 +239,33 @@
 	return IRQ_HANDLED;
 }
 
+static int __init nas100d_gpio_init(void)
+{
+	if (!machine_is_nas100d())
+		return 0;
+
+	/*
+	 * The power button on the Iomega NAS100d is on GPIO 14, but
+	 * it cannot handle interrupts on that GPIO line.  So we'll
+	 * have to poll it with a kernel timer.
+	 */
+
+	/* Request the power off GPIO */
+	gpio_request(NAS100D_PO_GPIO, "power off");
+
+	/* Make sure that the power button GPIO is set up as an input */
+	gpio_request(NAS100D_PB_GPIO, "power button");
+	gpio_direction_input(NAS100D_PB_GPIO);
+
+	/* Set the initial value for the power button IRQ handler */
+	power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
+
+	mod_timer(&nas100d_power_timer, jiffies + msecs_to_jiffies(500));
+
+	return 0;
+}
+device_initcall(nas100d_gpio_init);
+
 static void __init nas100d_init(void)
 {
 	uint8_t __iomem *f;
@@ -278,19 +302,6 @@
 			gpio_to_irq(NAS100D_RB_GPIO));
 	}
 
-	/* The power button on the Iomega NAS100d is on GPIO 14, but
-	 * it cannot handle interrupts on that GPIO line.  So we'll
-	 * have to poll it with a kernel timer.
-	 */
-
-	/* Make sure that the power button GPIO is set up as an input */
-	gpio_line_config(NAS100D_PB_GPIO, IXP4XX_GPIO_IN);
-
-	/* Set the initial value for the power button IRQ handler */
-	power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
-
-	mod_timer(&nas100d_power_timer, jiffies + msecs_to_jiffies(500));
-
 	/*
 	 * Map in a portion of the flash and read the MAC address.
 	 * Since it is stored in BE in the flash itself, we need to
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index 7e55236..ba5f1cd 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -197,11 +197,8 @@
 {
 	/* This causes the box to drop the power and go dead. */
 
-	/* enable the pwr cntl gpio */
-	gpio_line_config(NSLU2_PO_GPIO, IXP4XX_GPIO_OUT);
-
-	/* do the deed */
-	gpio_line_set(NSLU2_PO_GPIO, IXP4XX_GPIO_HIGH);
+	/* enable the pwr cntl gpio and assert power off */
+	gpio_direction_output(NSLU2_PO_GPIO, 1);
 }
 
 static irqreturn_t nslu2_power_handler(int irq, void *dev_id)
@@ -223,6 +220,16 @@
 	return IRQ_HANDLED;
 }
 
+static int __init nslu2_gpio_init(void)
+{
+	if (!machine_is_nslu2())
+		return 0;
+
+	/* Request the power off GPIO */
+	return gpio_request(NSLU2_PO_GPIO, "power off");
+}
+device_initcall(nslu2_gpio_init);
+
 static void __init nslu2_timer_init(void)
 {
     /* The xtal on this machine is non-standard. */
diff --git a/arch/arm/mach-keystone/Kconfig b/arch/arm/mach-keystone/Kconfig
index 366d1a3..f20c53e 100644
--- a/arch/arm/mach-keystone/Kconfig
+++ b/arch/arm/mach-keystone/Kconfig
@@ -9,6 +9,8 @@
 	select GENERIC_CLOCKEVENTS
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARM_ERRATA_798181 if SMP
+	select COMMON_CLK_KEYSTONE
+	select TI_EDMA
 	help
 	  Support for boards based on the Texas Instruments Keystone family of
 	  SoCs.
diff --git a/arch/arm/mach-keystone/Makefile b/arch/arm/mach-keystone/Makefile
index ddc52b0..25d9239 100644
--- a/arch/arm/mach-keystone/Makefile
+++ b/arch/arm/mach-keystone/Makefile
@@ -4,3 +4,6 @@
 AFLAGS_smc.o				:=-Wa,-march=armv7-a$(plus_sec)
 
 obj-$(CONFIG_SMP)			+= platsmp.o
+
+# PM domain driver for Keystone SOCs
+obj-$(CONFIG_ARCH_KEYSTONE)		+= pm_domain.o
diff --git a/arch/arm/mach-keystone/platsmp.c b/arch/arm/mach-keystone/platsmp.c
index c1229615..5cf0683 100644
--- a/arch/arm/mach-keystone/platsmp.c
+++ b/arch/arm/mach-keystone/platsmp.c
@@ -17,7 +17,6 @@
 #include <linux/io.h>
 
 #include <asm/smp_plat.h>
-#include <asm/prom.h>
 
 #include "keystone.h"
 
diff --git a/arch/arm/mach-keystone/pm_domain.c b/arch/arm/mach-keystone/pm_domain.c
new file mode 100644
index 0000000..2962523
--- /dev/null
+++ b/arch/arm/mach-keystone/pm_domain.c
@@ -0,0 +1,82 @@
+/*
+ * PM domain driver for Keystone2 devices
+ *
+ * Copyright 2013 Texas Instruments, Inc.
+ *	Santosh Shilimkar <santosh.shillimkar@ti.com>
+ *
+ * Based on Kevins work on DAVINCI SOCs
+ *	Kevin Hilman <khilman@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_clock.h>
+#include <linux/platform_device.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+
+#ifdef CONFIG_PM_RUNTIME
+static int keystone_pm_runtime_suspend(struct device *dev)
+{
+	int ret;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	ret = pm_generic_runtime_suspend(dev);
+	if (ret)
+		return ret;
+
+	ret = pm_clk_suspend(dev);
+	if (ret) {
+		pm_generic_runtime_resume(dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int keystone_pm_runtime_resume(struct device *dev)
+{
+	dev_dbg(dev, "%s\n", __func__);
+
+	pm_clk_resume(dev);
+
+	return pm_generic_runtime_resume(dev);
+}
+#endif
+
+static struct dev_pm_domain keystone_pm_domain = {
+	.ops = {
+		SET_RUNTIME_PM_OPS(keystone_pm_runtime_suspend,
+				   keystone_pm_runtime_resume, NULL)
+		USE_PLATFORM_PM_SLEEP_OPS
+	},
+};
+
+static struct pm_clk_notifier_block platform_domain_notifier = {
+	.pm_domain = &keystone_pm_domain,
+};
+
+static struct of_device_id of_keystone_table[] = {
+	{.compatible = "ti,keystone"},
+	{ /* end of list */ },
+};
+
+int __init keystone_pm_runtime_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_matching_node(NULL, of_keystone_table);
+	if (!np)
+		return 0;
+
+	of_clk_init(NULL);
+	pm_clk_add_notifier(&platform_bus_type, &platform_domain_notifier);
+
+	return 0;
+}
+subsys_initcall(keystone_pm_runtime_init);
diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
index d1f8e3d..144b511 100644
--- a/arch/arm/mach-kirkwood/Makefile
+++ b/arch/arm/mach-kirkwood/Makefile
@@ -1,5 +1,7 @@
 obj-y				+= common.o pcie.o
 obj-$(CONFIG_KIRKWOOD_LEGACY)	+= irq.o mpp.o
+obj-$(CONFIG_PM)		+= pm.o
+
 obj-$(CONFIG_MACH_D2NET_V2)		+= d2net_v2-setup.o lacie_v2-common.o
 obj-$(CONFIG_MACH_NET2BIG_V2)		+= netxbig_v2-setup.o lacie_v2-common.o
 obj-$(CONFIG_MACH_NET5BIG_V2)		+= netxbig_v2-setup.o lacie_v2-common.o
diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c
index 82d3ad8..9caa4fe 100644
--- a/arch/arm/mach-kirkwood/board-dt.c
+++ b/arch/arm/mach-kirkwood/board-dt.c
@@ -13,9 +13,10 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_net.h>
 #include <linux/of_platform.h>
 #include <linux/clk-provider.h>
-#include <linux/clocksource.h>
 #include <linux/dma-mapping.h>
 #include <linux/irqchip.h>
 #include <linux/kexec.h>
@@ -44,14 +45,6 @@
 	clkspec.np = np;
 	clkspec.args_count = 1;
 
-	clkspec.args[0] = CGC_BIT_PEX0;
-	orion_clkdev_add("0", "pcie",
-			 of_clk_get_from_provider(&clkspec));
-
-	clkspec.args[0] = CGC_BIT_PEX1;
-	orion_clkdev_add("1", "pcie",
-			 of_clk_get_from_provider(&clkspec));
-
 	/*
 	 * The ethernet interfaces forget the MAC address assigned by
 	 * u-boot if the clocks are turned off. Until proper DT support
@@ -66,17 +59,83 @@
 	clk_prepare_enable(clk);
 }
 
-static void __init kirkwood_dt_time_init(void)
-{
-	of_clk_init(NULL);
-	clocksource_of_init();
-}
+#define MV643XX_ETH_MAC_ADDR_LOW	0x0414
+#define MV643XX_ETH_MAC_ADDR_HIGH	0x0418
 
-static void __init kirkwood_dt_init_early(void)
+static void __init kirkwood_dt_eth_fixup(void)
 {
-	mvebu_mbus_init("marvell,kirkwood-mbus",
-			BRIDGE_WINS_BASE, BRIDGE_WINS_SZ,
-			DDR_WINDOW_CPU_BASE, DDR_WINDOW_CPU_SZ);
+	struct device_node *np;
+
+	/*
+	 * The ethernet interfaces forget the MAC address assigned by u-boot
+	 * if the clocks are turned off. Usually, u-boot on kirkwood boards
+	 * has no DT support to properly set local-mac-address property.
+	 * As a workaround, we get the MAC address from mv643xx_eth registers
+	 * and update the port device node if no valid MAC address is set.
+	 */
+	for_each_compatible_node(np, NULL, "marvell,kirkwood-eth-port") {
+		struct device_node *pnp = of_get_parent(np);
+		struct clk *clk;
+		struct property *pmac;
+		void __iomem *io;
+		u8 *macaddr;
+		u32 reg;
+
+		if (!pnp)
+			continue;
+
+		/* skip disabled nodes or nodes with valid MAC address*/
+		if (!of_device_is_available(pnp) || of_get_mac_address(np))
+			goto eth_fixup_skip;
+
+		clk = of_clk_get(pnp, 0);
+		if (IS_ERR(clk))
+			goto eth_fixup_skip;
+
+		io = of_iomap(pnp, 0);
+		if (!io)
+			goto eth_fixup_no_map;
+
+		/* ensure port clock is not gated to not hang CPU */
+		clk_prepare_enable(clk);
+
+		/* store MAC address register contents in local-mac-address */
+		pr_err(FW_INFO "%s: local-mac-address is not set\n",
+		       np->full_name);
+
+		pmac = kzalloc(sizeof(*pmac) + 6, GFP_KERNEL);
+		if (!pmac)
+			goto eth_fixup_no_mem;
+
+		pmac->value = pmac + 1;
+		pmac->length = 6;
+		pmac->name = kstrdup("local-mac-address", GFP_KERNEL);
+		if (!pmac->name) {
+			kfree(pmac);
+			goto eth_fixup_no_mem;
+		}
+
+		macaddr = pmac->value;
+		reg = readl(io + MV643XX_ETH_MAC_ADDR_HIGH);
+		macaddr[0] = (reg >> 24) & 0xff;
+		macaddr[1] = (reg >> 16) & 0xff;
+		macaddr[2] = (reg >> 8) & 0xff;
+		macaddr[3] = reg & 0xff;
+
+		reg = readl(io + MV643XX_ETH_MAC_ADDR_LOW);
+		macaddr[4] = (reg >> 8) & 0xff;
+		macaddr[5] = reg & 0xff;
+
+		of_update_property(np, pmac);
+
+eth_fixup_no_mem:
+		iounmap(io);
+		clk_disable_unprepare(clk);
+eth_fixup_no_map:
+		clk_put(clk);
+eth_fixup_skip:
+		of_node_put(pnp);
+	}
 }
 
 static void __init kirkwood_dt_init(void)
@@ -92,16 +151,16 @@
 	writel(readl(CPU_CONFIG) & ~CPU_CONFIG_ERROR_PROP, CPU_CONFIG);
 
 	BUG_ON(mvebu_mbus_dt_init());
-	kirkwood_setup_wins();
 
 	kirkwood_l2_init();
 
 	kirkwood_cpufreq_init();
-
+	kirkwood_cpuidle_init();
 	/* Setup clocks for legacy devices */
 	kirkwood_legacy_clk_init();
 
-	kirkwood_cpuidle_init();
+	kirkwood_pm_init();
+	kirkwood_dt_eth_fixup();
 
 #ifdef CONFIG_KEXEC
 	kexec_reinit = kirkwood_enable_pcie;
@@ -121,8 +180,6 @@
 DT_MACHINE_START(KIRKWOOD_DT, "Marvell Kirkwood (Flattened Device Tree)")
 	/* Maintainer: Jason Cooper <jason@lakedaemon.net> */
 	.map_io		= kirkwood_map_io,
-	.init_early	= kirkwood_dt_init_early,
-	.init_time	= kirkwood_dt_time_init,
 	.init_machine	= kirkwood_dt_init,
 	.restart	= kirkwood_restart,
 	.dt_compat	= kirkwood_dt_board_compat,
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index 1767611..f3407a5 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -721,6 +721,7 @@
 	kirkwood_xor1_init();
 	kirkwood_crypto_init();
 
+	kirkwood_pm_init();
 	kirkwood_cpuidle_init();
 #ifdef CONFIG_KEXEC
 	kexec_reinit = kirkwood_enable_pcie;
diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h
index 1296de9..05fd648 100644
--- a/arch/arm/mach-kirkwood/common.h
+++ b/arch/arm/mach-kirkwood/common.h
@@ -58,6 +58,12 @@
 void kirkwood_restart(enum reboot_mode, const char *);
 void kirkwood_clk_init(void);
 
+#ifdef CONFIG_PM
+void kirkwood_pm_init(void);
+#else
+static inline void kirkwood_pm_init(void) {};
+#endif
+
 /* board init functions for boards not fully converted to fdt */
 #ifdef CONFIG_MACH_MV88F6281GTW_GE_DT
 void mv88f6281gtw_ge_init(void);
diff --git a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
index 91242c9..8b9d1c9 100644
--- a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
+++ b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
@@ -78,4 +78,6 @@
 #define CGC_TDM			(1 << 20)
 #define CGC_RESERVED		(0x6 << 21)
 
+#define MEMORY_PM_CTRL		(BRIDGE_VIRT_BASE + 0x118)
+
 #endif
diff --git a/arch/arm/mach-kirkwood/pm.c b/arch/arm/mach-kirkwood/pm.c
new file mode 100644
index 0000000..8783a71
--- /dev/null
+++ b/arch/arm/mach-kirkwood/pm.c
@@ -0,0 +1,73 @@
+/*
+ * Power Management driver for Marvell Kirkwood SoCs
+ *
+ * Copyright (C) 2013 Ezequiel Garcia <ezequiel@free-electrons.com>
+ * Copyright (C) 2010 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,
+ * version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/suspend.h>
+#include <linux/io.h>
+#include <mach/bridge-regs.h>
+
+static void __iomem *ddr_operation_base;
+
+static void kirkwood_low_power(void)
+{
+	u32 mem_pm_ctrl;
+
+	mem_pm_ctrl = readl(MEMORY_PM_CTRL);
+
+	/* Set peripherals to low-power mode */
+	writel_relaxed(~0, MEMORY_PM_CTRL);
+
+	/* Set DDR in self-refresh */
+	writel_relaxed(0x7, ddr_operation_base);
+
+	/*
+	 * Set CPU in wait-for-interrupt state.
+	 * This disables the CPU core clocks,
+	 * the array clocks, and also the L2 controller.
+	 */
+	cpu_do_idle();
+
+	writel_relaxed(mem_pm_ctrl, MEMORY_PM_CTRL);
+}
+
+static int kirkwood_suspend_enter(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+		kirkwood_low_power();
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int kirkwood_pm_valid_standby(suspend_state_t state)
+{
+	return state == PM_SUSPEND_STANDBY;
+}
+
+static const struct platform_suspend_ops kirkwood_suspend_ops = {
+	.enter = kirkwood_suspend_enter,
+	.valid = kirkwood_pm_valid_standby,
+};
+
+int __init kirkwood_pm_init(void)
+{
+	ddr_operation_base = ioremap(DDR_OPERATION_BASE, 4);
+	suspend_set_ops(&kirkwood_suspend_ops);
+	return 0;
+}
diff --git a/arch/arm/mach-mmp/include/mach/gpio.h b/arch/arm/mach-mmp/include/mach/gpio.h
deleted file mode 100644
index 13219eb..0000000
--- a/arch/arm/mach-mmp/include/mach/gpio.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __ASM_MACH_GPIO_H
-#define __ASM_MACH_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-#include <mach/cputype.h>
-
-#endif /* __ASM_MACH_GPIO_H */
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 905efc8..2586c28 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1,12 +1,12 @@
 if ARCH_MSM
 
 comment "Qualcomm MSM SoC Type"
-	depends on (ARCH_MSM8X60 || ARCH_MSM8960)
+	depends on ARCH_MSM_DT
 
 choice
 	prompt "Qualcomm MSM SoC Type"
 	default ARCH_MSM7X00A
-	depends on !(ARCH_MSM8X60 || ARCH_MSM8960)
+	depends on !ARCH_MSM_DT
 
 config ARCH_MSM7X00A
 	bool "MSM7x00A / MSM7x01A"
@@ -49,7 +49,6 @@
 	select GPIO_MSM_V2
 	select HAVE_SMP
 	select MSM_SCM if SMP
-	select USE_OF
 
 config ARCH_MSM8960
 	bool "MSM8960"
@@ -58,6 +57,11 @@
 	select HAVE_SMP
 	select GPIO_MSM_V2
 	select MSM_SCM if SMP
+
+config ARCH_MSM_DT
+	def_bool y
+	depends on (ARCH_MSM8X60 || ARCH_MSM8960)
+	select SPARSE_IRQ
 	select USE_OF
 
 config MSM_HAS_DEBUG_UART_HS
@@ -68,6 +72,7 @@
 
 config  ARCH_MSM_ARM11
 	bool
+
 config  ARCH_MSM_SCORPION
 	bool
 
@@ -75,6 +80,7 @@
 	bool
 
 menu "Qualcomm MSM Board Type"
+	depends on !ARCH_MSM_DT
 
 config MACH_HALIBUT
 	depends on ARCH_MSM
@@ -122,6 +128,7 @@
 
 config MSM_GPIOMUX
 	bool
+	depends on !ARCH_MSM_DT
 	help
 	  Support for MSM V1 TLMM GPIOMUX architecture.
 
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index d872634..7ed4c1b 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -26,7 +26,6 @@
 obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o
 obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o
 obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o
-obj-$(CONFIG_ARCH_MSM8X60) += board-dt-8660.o
-obj-$(CONFIG_ARCH_MSM8960) += board-dt-8960.o
+obj-$(CONFIG_ARCH_MSM_DT) += board-dt.o
 obj-$(CONFIG_MSM_GPIOMUX) += gpiomux.o
 obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o
diff --git a/arch/arm/mach-msm/board-dt-8660.c b/arch/arm/mach-msm/board-dt-8660.c
deleted file mode 100644
index c294689..0000000
--- a/arch/arm/mach-msm/board-dt-8660.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/init.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include "common.h"
-
-static void __init msm8x60_init_late(void)
-{
-	smd_debugfs_init();
-}
-
-static struct of_dev_auxdata msm_auxdata_lookup[] __initdata = {
-	{}
-};
-
-static void __init msm8x60_dt_init(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table,
-			msm_auxdata_lookup, NULL);
-}
-
-static const char *msm8x60_fluid_match[] __initdata = {
-	"qcom,msm8660-fluid",
-	"qcom,msm8660-surf",
-	NULL
-};
-
-DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
-	.smp = smp_ops(msm_smp_ops),
-	.init_machine = msm8x60_dt_init,
-	.init_late = msm8x60_init_late,
-	.dt_compat = msm8x60_fluid_match,
-MACHINE_END
diff --git a/arch/arm/mach-msm/board-dt-8960.c b/arch/arm/mach-msm/board-dt.c
similarity index 64%
rename from arch/arm/mach-msm/board-dt-8960.c
rename to arch/arm/mach-msm/board-dt.c
index d4ca52c..16e6183 100644
--- a/arch/arm/mach-msm/board-dt-8960.c
+++ b/arch/arm/mach-msm/board-dt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2012,2013 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,6 +11,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/of.h>
 #include <linux/of_platform.h>
 
 #include <asm/mach/arch.h>
@@ -18,18 +19,14 @@
 
 #include "common.h"
 
-static void __init msm_dt_init(void)
-{
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
-static const char * const msm8960_dt_match[] __initconst = {
+static const char * const msm_dt_match[] __initconst = {
+	"qcom,msm8660-fluid",
+	"qcom,msm8660-surf",
 	"qcom,msm8960-cdp",
 	NULL
 };
 
-DT_MACHINE_START(MSM8960_DT, "Qualcomm MSM (Flattened Device Tree)")
+DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
 	.smp = smp_ops(msm_smp_ops),
-	.init_machine = msm_dt_init,
-	.dt_compat = msm8960_dt_match,
+	.dt_compat = msm_dt_match,
 MACHINE_END
diff --git a/arch/arm/mach-msm/include/mach/irqs-8960.h b/arch/arm/mach-msm/include/mach/irqs-8960.h
deleted file mode 100644
index 81ab2a6..0000000
--- a/arch/arm/mach-msm/include/mach/irqs-8960.h
+++ /dev/null
@@ -1,277 +0,0 @@
-/* Copyright (c) 2011 Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ASM_ARCH_MSM_IRQS_8960_H
-#define __ASM_ARCH_MSM_IRQS_8960_H
-
-/* MSM ACPU Interrupt Numbers */
-
-/* 0-15:  STI/SGI (software triggered/generated interrupts)
-   16-31: PPI (private peripheral interrupts)
-   32+:   SPI (shared peripheral interrupts) */
-
-#define GIC_PPI_START 16
-#define GIC_SPI_START 32
-
-#define INT_VGIC				(GIC_PPI_START + 0)
-#define INT_DEBUG_TIMER_EXP			(GIC_PPI_START + 1)
-#define INT_GP_TIMER_EXP			(GIC_PPI_START + 2)
-#define INT_GP_TIMER2_EXP			(GIC_PPI_START + 3)
-#define WDT0_ACCSCSSNBARK_INT			(GIC_PPI_START + 4)
-#define WDT1_ACCSCSSNBARK_INT			(GIC_PPI_START + 5)
-#define AVS_SVICINT				(GIC_PPI_START + 6)
-#define AVS_SVICINTSWDONE			(GIC_PPI_START + 7)
-#define CPU_DBGCPUXCOMMRXFULL			(GIC_PPI_START + 8)
-#define CPU_DBGCPUXCOMMTXEMPTY			(GIC_PPI_START + 9)
-#define CPU_SICCPUXPERFMONIRPTREQ		(GIC_PPI_START + 10)
-#define SC_AVSCPUXDOWN				(GIC_PPI_START + 11)
-#define SC_AVSCPUXUP				(GIC_PPI_START + 12)
-#define SC_SICCPUXACGIRPTREQ			(GIC_PPI_START + 13)
-#define SC_SICCPUXEXTFAULTIRPTREQ		(GIC_PPI_START + 14)
-/* PPI 15 is unused */
-
-#define SC_SICMPUIRPTREQ			(GIC_SPI_START + 0)
-#define SC_SICL2IRPTREQ				(GIC_SPI_START + 1)
-#define SC_SICL2PERFMONIRPTREQ			(GIC_SPI_START + 2)
-#define SC_SICAGCIRPTREQ			(GIC_SPI_START + 3)
-#define TLMM_APCC_DIR_CONN_IRQ_0		(GIC_SPI_START + 4)
-#define TLMM_APCC_DIR_CONN_IRQ_1		(GIC_SPI_START + 5)
-#define TLMM_APCC_DIR_CONN_IRQ_2		(GIC_SPI_START + 6)
-#define TLMM_APCC_DIR_CONN_IRQ_3		(GIC_SPI_START + 7)
-#define TLMM_APCC_DIR_CONN_IRQ_4		(GIC_SPI_START + 8)
-#define TLMM_APCC_DIR_CONN_IRQ_5		(GIC_SPI_START + 9)
-#define TLMM_APCC_DIR_CONN_IRQ_6		(GIC_SPI_START + 10)
-#define TLMM_APCC_DIR_CONN_IRQ_7		(GIC_SPI_START + 11)
-#define TLMM_APCC_DIR_CONN_IRQ_8		(GIC_SPI_START + 12)
-#define TLMM_APCC_DIR_CONN_IRQ_9		(GIC_SPI_START + 13)
-#define PM8921_SEC_IRQ_103			(GIC_SPI_START + 14)
-#define PM8018_SEC_IRQ_106			(GIC_SPI_START + 15)
-#define TLMM_APCC_SUMMARY_IRQ			(GIC_SPI_START + 16)
-#define SPDM_RT_1_IRQ				(GIC_SPI_START + 17)
-#define SPDM_DIAG_IRQ				(GIC_SPI_START + 18)
-#define RPM_APCC_CPU0_GP_HIGH_IRQ		(GIC_SPI_START + 19)
-#define RPM_APCC_CPU0_GP_MEDIUM_IRQ		(GIC_SPI_START + 20)
-#define RPM_APCC_CPU0_GP_LOW_IRQ		(GIC_SPI_START + 21)
-#define RPM_APCC_CPU0_WAKE_UP_IRQ		(GIC_SPI_START + 22)
-#define RPM_APCC_CPU1_GP_HIGH_IRQ		(GIC_SPI_START + 23)
-#define RPM_APCC_CPU1_GP_MEDIUM_IRQ		(GIC_SPI_START + 24)
-#define RPM_APCC_CPU1_GP_LOW_IRQ		(GIC_SPI_START + 25)
-#define RPM_APCC_CPU1_WAKE_UP_IRQ		(GIC_SPI_START + 26)
-#define SSBI2_2_SC_CPU0_SECURE_IRQ		(GIC_SPI_START + 27)
-#define SSBI2_2_SC_CPU0_NON_SECURE_IRQ		(GIC_SPI_START + 28)
-#define SSBI2_1_SC_CPU0_SECURE_IRQ		(GIC_SPI_START + 29)
-#define SSBI2_1_SC_CPU0_NON_SECURE_IRQ		(GIC_SPI_START + 30)
-#define MSMC_SC_SEC_CE_IRQ			(GIC_SPI_START + 31)
-#define MSMC_SC_PRI_CE_IRQ			(GIC_SPI_START + 32)
-#define SLIMBUS0_CORE_EE1_IRQ			(GIC_SPI_START + 33)
-#define SLIMBUS0_BAM_EE1_IRQ			(GIC_SPI_START + 34)
-#define Q6FW_WDOG_EXPIRED_IRQ			(GIC_SPI_START + 35)
-#define Q6SW_WDOG_EXPIRED_IRQ			(GIC_SPI_START + 36)
-#define MSS_TO_APPS_IRQ_0			(GIC_SPI_START + 37)
-#define MSS_TO_APPS_IRQ_1			(GIC_SPI_START + 38)
-#define MSS_TO_APPS_IRQ_2			(GIC_SPI_START + 39)
-#define MSS_TO_APPS_IRQ_3			(GIC_SPI_START + 40)
-#define MSS_TO_APPS_IRQ_4			(GIC_SPI_START + 41)
-#define MSS_TO_APPS_IRQ_5			(GIC_SPI_START + 42)
-#define MSS_TO_APPS_IRQ_6			(GIC_SPI_START + 43)
-#define MSS_TO_APPS_IRQ_7			(GIC_SPI_START + 44)
-#define MSS_TO_APPS_IRQ_8			(GIC_SPI_START + 45)
-#define MSS_TO_APPS_IRQ_9			(GIC_SPI_START + 46)
-#define VPE_IRQ					(GIC_SPI_START + 47)
-#define VFE_IRQ					(GIC_SPI_START + 48)
-#define VCODEC_IRQ				(GIC_SPI_START + 49)
-#define TV_ENC_IRQ				(GIC_SPI_START + 50)
-#define SMMU_VPE_CB_SC_SECURE_IRQ		(GIC_SPI_START + 51)
-#define SMMU_VPE_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 52)
-#define SMMU_VFE_CB_SC_SECURE_IRQ		(GIC_SPI_START + 53)
-#define SMMU_VFE_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 54)
-#define SMMU_VCODEC_B_CB_SC_SECURE_IRQ		(GIC_SPI_START + 55)
-#define SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ	(GIC_SPI_START + 56)
-#define SMMU_VCODEC_A_CB_SC_SECURE_IRQ		(GIC_SPI_START + 57)
-#define SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ	(GIC_SPI_START + 58)
-#define SMMU_ROT_CB_SC_SECURE_IRQ		(GIC_SPI_START + 59)
-#define SMMU_ROT_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 60)
-#define SMMU_MDP1_CB_SC_SECURE_IRQ		(GIC_SPI_START + 61)
-#define SMMU_MDP1_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 62)
-#define SMMU_MDP0_CB_SC_SECURE_IRQ		(GIC_SPI_START + 63)
-#define SMMU_MDP0_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 64)
-#define SMMU_JPEGD_CB_SC_SECURE_IRQ		(GIC_SPI_START + 65)
-#define SMMU_JPEGD_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 66)
-#define SMMU_IJPEG_CB_SC_SECURE_IRQ		(GIC_SPI_START + 67)
-#define SMMU_IJPEG_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 68)
-#define SMMU_GFX3D_CB_SC_SECURE_IRQ		(GIC_SPI_START + 69)
-#define SMMU_GFX3D_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 70)
-#define SMMU_GFX2D0_CB_SC_SECURE_IRQ		(GIC_SPI_START + 71)
-#define SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ	(GIC_SPI_START + 72)
-#define ROT_IRQ					(GIC_SPI_START + 73)
-#define MMSS_FABRIC_IRQ				(GIC_SPI_START + 74)
-#define MDP_IRQ					(GIC_SPI_START + 75)
-#define JPEGD_IRQ				(GIC_SPI_START + 76)
-#define JPEG_IRQ				(GIC_SPI_START + 77)
-#define MMSS_IMEM_IRQ				(GIC_SPI_START + 78)
-#define HDMI_IRQ				(GIC_SPI_START + 79)
-#define GFX3D_IRQ				(GIC_SPI_START + 80)
-#define GFX2D0_IRQ				(GIC_SPI_START + 81)
-#define DSI1_IRQ				(GIC_SPI_START + 82)
-#define CSI_1_IRQ				(GIC_SPI_START + 83)
-#define CSI_0_IRQ				(GIC_SPI_START + 84)
-#define LPASS_SCSS_AUDIO_IF_OUT0_IRQ		(GIC_SPI_START + 85)
-#define LPASS_SCSS_MIDI_IRQ			(GIC_SPI_START + 86)
-#define LPASS_Q6SS_WDOG_EXPIRED			(GIC_SPI_START + 87)
-#define LPASS_SCSS_GP_LOW_IRQ			(GIC_SPI_START + 88)
-#define LPASS_SCSS_GP_MEDIUM_IRQ		(GIC_SPI_START + 89)
-#define LPASS_SCSS_GP_HIGH_IRQ			(GIC_SPI_START + 90)
-#define TOP_IMEM_IRQ				(GIC_SPI_START + 91)
-#define FABRIC_SYS_IRQ				(GIC_SPI_START + 92)
-#define FABRIC_APPS_IRQ				(GIC_SPI_START + 93)
-#define USB1_HS_BAM_IRQ				(GIC_SPI_START + 94)
-#define SDC4_BAM_IRQ				(GIC_SPI_START + 95)
-#define SDC3_BAM_IRQ				(GIC_SPI_START + 96)
-#define SDC2_BAM_IRQ				(GIC_SPI_START + 97)
-#define SDC1_BAM_IRQ				(GIC_SPI_START + 98)
-#define FABRIC_SPS_IRQ				(GIC_SPI_START + 99)
-#define USB1_HS_IRQ				(GIC_SPI_START + 100)
-#define SDC4_IRQ_0				(GIC_SPI_START + 101)
-#define SDC3_IRQ_0				(GIC_SPI_START + 102)
-#define SDC2_IRQ_0				(GIC_SPI_START + 103)
-#define SDC1_IRQ_0				(GIC_SPI_START + 104)
-#define SPS_BAM_DMA_IRQ				(GIC_SPI_START + 105)
-#define SPS_SEC_VIOL_IRQ			(GIC_SPI_START + 106)
-#define SPS_MTI_0				(GIC_SPI_START + 107)
-#define SPS_MTI_1				(GIC_SPI_START + 108)
-#define SPS_MTI_2				(GIC_SPI_START + 109)
-#define SPS_MTI_3				(GIC_SPI_START + 110)
-#define SPS_MTI_4				(GIC_SPI_START + 111)
-#define SPS_MTI_5				(GIC_SPI_START + 112)
-#define SPS_MTI_6				(GIC_SPI_START + 113)
-#define SPS_MTI_7				(GIC_SPI_START + 114)
-#define SPS_MTI_8				(GIC_SPI_START + 115)
-#define SPS_MTI_9				(GIC_SPI_START + 116)
-#define SPS_MTI_10				(GIC_SPI_START + 117)
-#define SPS_MTI_11				(GIC_SPI_START + 118)
-#define SPS_MTI_12				(GIC_SPI_START + 119)
-#define SPS_MTI_13				(GIC_SPI_START + 120)
-#define SPS_MTI_14				(GIC_SPI_START + 121)
-#define SPS_MTI_15				(GIC_SPI_START + 122)
-#define SPS_MTI_16				(GIC_SPI_START + 123)
-#define SPS_MTI_17				(GIC_SPI_START + 124)
-#define SPS_MTI_18				(GIC_SPI_START + 125)
-#define SPS_MTI_19				(GIC_SPI_START + 126)
-#define SPS_MTI_20				(GIC_SPI_START + 127)
-#define SPS_MTI_21				(GIC_SPI_START + 128)
-#define SPS_MTI_22				(GIC_SPI_START + 129)
-#define SPS_MTI_23				(GIC_SPI_START + 130)
-#define SPS_MTI_24				(GIC_SPI_START + 131)
-#define SPS_MTI_25				(GIC_SPI_START + 132)
-#define SPS_MTI_26				(GIC_SPI_START + 133)
-#define SPS_MTI_27				(GIC_SPI_START + 134)
-#define SPS_MTI_28				(GIC_SPI_START + 135)
-#define SPS_MTI_29				(GIC_SPI_START + 136)
-#define SPS_MTI_30				(GIC_SPI_START + 137)
-#define SPS_MTI_31				(GIC_SPI_START + 138)
-#define CSIPHY_4LN_IRQ				(GIC_SPI_START + 139)
-#define CSIPHY_2LN_IRQ				(GIC_SPI_START + 140)
-#define USB2_IRQ				(GIC_SPI_START + 141)
-#define USB1_IRQ				(GIC_SPI_START + 142)
-#define TSSC_SSBI_IRQ				(GIC_SPI_START + 143)
-#define TSSC_SAMPLE_IRQ				(GIC_SPI_START + 144)
-#define TSSC_PENUP_IRQ				(GIC_SPI_START + 145)
-#define GSBI1_UARTDM_IRQ			(GIC_SPI_START + 146)
-#define GSBI1_QUP_IRQ				(GIC_SPI_START + 147)
-#define GSBI2_UARTDM_IRQ			(GIC_SPI_START + 148)
-#define GSBI2_QUP_IRQ			        (GIC_SPI_START + 149)
-#define GSBI3_UARTDM_IRQ			(GIC_SPI_START + 150)
-#define GSBI3_QUP_IRQ				(GIC_SPI_START + 151)
-#define GSBI4_UARTDM_IRQ			(GIC_SPI_START + 152)
-#define GSBI4_QUP_IRQ				(GIC_SPI_START + 153)
-#define GSBI5_UARTDM_IRQ			(GIC_SPI_START + 154)
-#define GSBI5_QUP_IRQ				(GIC_SPI_START + 155)
-#define GSBI6_UARTDM_IRQ			(GIC_SPI_START + 156)
-#define GSBI6_QUP_IRQ				(GIC_SPI_START + 157)
-#define GSBI7_UARTDM_IRQ			(GIC_SPI_START + 158)
-#define GSBI7_QUP_IRQ				(GIC_SPI_START + 159)
-#define GSBI8_UARTDM_IRQ			(GIC_SPI_START + 160)
-#define GSBI8_QUP_IRQ				(GIC_SPI_START + 161)
-#define TSIF_TSPP_IRQ				(GIC_SPI_START + 162)
-#define TSIF_BAM_IRQ				(GIC_SPI_START + 163)
-#define TSIF2_IRQ				(GIC_SPI_START + 164)
-#define TSIF1_IRQ				(GIC_SPI_START + 165)
-#define DSI2_IRQ				(GIC_SPI_START + 166)
-#define ISPIF_IRQ				(GIC_SPI_START + 167)
-#define MSMC_SC_SEC_TMR_IRQ			(GIC_SPI_START + 168)
-#define MSMC_SC_SEC_WDOG_BARK_IRQ		(GIC_SPI_START + 169)
-#define INT_ADM0_SCSS_0_IRQ			(GIC_SPI_START + 170)
-#define INT_ADM0_SCSS_1_IRQ			(GIC_SPI_START + 171)
-#define INT_ADM0_SCSS_2_IRQ			(GIC_SPI_START + 172)
-#define INT_ADM0_SCSS_3_IRQ			(GIC_SPI_START + 173)
-#define CC_SCSS_WDT1CPU1BITEEXPIRED		(GIC_SPI_START + 174)
-#define CC_SCSS_WDT1CPU0BITEEXPIRED		(GIC_SPI_START + 175)
-#define CC_SCSS_WDT0CPU1BITEEXPIRED		(GIC_SPI_START + 176)
-#define CC_SCSS_WDT0CPU0BITEEXPIRED		(GIC_SPI_START + 177)
-#define TSENS_UPPER_LOWER_INT			(GIC_SPI_START + 178)
-#define SSBI2_2_SC_CPU1_SECURE_INT		(GIC_SPI_START + 179)
-#define SSBI2_2_SC_CPU1_NON_SECURE_INT		(GIC_SPI_START + 180)
-#define SSBI2_1_SC_CPU1_SECURE_INT		(GIC_SPI_START + 181)
-#define SSBI2_1_SC_CPU1_NON_SECURE_INT		(GIC_SPI_START + 182)
-#define XPU_SUMMARY_IRQ				(GIC_SPI_START + 183)
-#define BUS_EXCEPTION_SUMMARY_IRQ		(GIC_SPI_START + 184)
-#define HSDDRX_EBI1CH0_IRQ			(GIC_SPI_START + 185)
-#define HSDDRX_EBI1CH1_IRQ			(GIC_SPI_START + 186)
-#define SDC5_BAM_IRQ				(GIC_SPI_START + 187)
-#define SDC5_IRQ_0				(GIC_SPI_START + 188)
-#define GSBI9_UARTDM_IRQ			(GIC_SPI_START + 189)
-#define GSBI9_QUP_IRQ				(GIC_SPI_START + 190)
-#define GSBI10_UARTDM_IRQ			(GIC_SPI_START + 191)
-#define GSBI10_QUP_IRQ				(GIC_SPI_START + 192)
-#define GSBI11_UARTDM_IRQ			(GIC_SPI_START + 193)
-#define GSBI11_QUP_IRQ				(GIC_SPI_START + 194)
-#define GSBI12_UARTDM_IRQ			(GIC_SPI_START + 195)
-#define GSBI12_QUP_IRQ				(GIC_SPI_START + 196)
-#define RIVA_APSS_LTECOEX_IRQ			(GIC_SPI_START + 197)
-#define RIVA_APSS_SPARE_IRQ			(GIC_SPI_START + 198)
-#define RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ	(GIC_SPI_START + 199)
-#define RIVA_ASS_RESET_DONE_IRQ			(GIC_SPI_START + 200)
-#define RIVA_APSS_ASIC_IRQ			(GIC_SPI_START + 201)
-#define RIVA_APPS_WLAN_RX_DATA_AVAIL_IRQ	(GIC_SPI_START + 202)
-#define RIVA_APPS_WLAN_DATA_XFER_DONE_IRQ	(GIC_SPI_START + 203)
-#define RIVA_APPS_WLAM_SMSM_IRQ			(GIC_SPI_START + 204)
-#define RIVA_APPS_LOG_CTRL_IRQ			(GIC_SPI_START + 205)
-#define RIVA_APPS_FM_CTRL_IRQ			(GIC_SPI_START + 206)
-#define RIVA_APPS_HCI_IRQ			(GIC_SPI_START + 207)
-#define RIVA_APPS_WLAN_CTRL_IRQ			(GIC_SPI_START + 208)
-#define A2_BAM_IRQ				(GIC_SPI_START + 209)
-#define SMMU_GFX2D1_CB_SC_SECURE_IRQ		(GIC_SPI_START + 210)
-#define SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ	(GIC_SPI_START + 211)
-#define GFX2D1_IRQ				(GIC_SPI_START + 212)
-#define PPSS_WDOG_TIMER_IRQ			(GIC_SPI_START + 213)
-#define SPS_SLIMBUS_CORE_EE0_IRQ		(GIC_SPI_START + 214)
-#define SPS_SLIMBUS_BAM_EE0_IRQ			(GIC_SPI_START + 215)
-#define QDSS_ETB_IRQ				(GIC_SPI_START + 216)
-#define QDSS_CTI2KPSS_CPU1_IRQ			(GIC_SPI_START + 217)
-#define QDSS_CTI2KPSS_CPU0_IRQ			(GIC_SPI_START + 218)
-#define TLMM_APCC_DIR_CONN_IRQ_16		(GIC_SPI_START + 219)
-#define TLMM_APCC_DIR_CONN_IRQ_17		(GIC_SPI_START + 220)
-#define TLMM_APCC_DIR_CONN_IRQ_18		(GIC_SPI_START + 221)
-#define TLMM_APCC_DIR_CONN_IRQ_19		(GIC_SPI_START + 222)
-#define TLMM_APCC_DIR_CONN_IRQ_20		(GIC_SPI_START + 223)
-#define TLMM_APCC_DIR_CONN_IRQ_21		(GIC_SPI_START + 224)
-#define PM8921_SEC_IRQ_104			(GIC_SPI_START + 225)
-#define PM8018_SEC_IRQ_107			(GIC_SPI_START + 226)
-
-/* For now, use the maximum number of interrupts until a pending GIC issue
- * is sorted out */
-#define NR_MSM_IRQS 1020
-#define NR_BOARD_IRQS 0
-#define NR_GPIO_IRQS 0
-
-#endif
-
diff --git a/arch/arm/mach-msm/include/mach/irqs-8x60.h b/arch/arm/mach-msm/include/mach/irqs-8x60.h
deleted file mode 100644
index f65841c..0000000
--- a/arch/arm/mach-msm/include/mach/irqs-8x60.h
+++ /dev/null
@@ -1,258 +0,0 @@
-/* Copyright (c) 2010 Code Aurora Forum. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __ASM_ARCH_MSM_IRQS_8X60_H
-#define __ASM_ARCH_MSM_IRQS_8X60_H
-
-/* MSM ACPU Interrupt Numbers */
-
-/* 0-15:  STI/SGI (software triggered/generated interrupts)
- * 16-31: PPI (private peripheral interrupts)
- * 32+:   SPI (shared peripheral interrupts)
- */
-
-#define GIC_PPI_START 16
-#define GIC_SPI_START 32
-
-#define INT_DEBUG_TIMER_EXP			(GIC_PPI_START + 0)
-#define INT_GP_TIMER_EXP			(GIC_PPI_START + 1)
-#define INT_GP_TIMER2_EXP			(GIC_PPI_START + 2)
-#define WDT0_ACCSCSSNBARK_INT			(GIC_PPI_START + 3)
-#define WDT1_ACCSCSSNBARK_INT			(GIC_PPI_START + 4)
-#define AVS_SVICINT				(GIC_PPI_START + 5)
-#define AVS_SVICINTSWDONE			(GIC_PPI_START + 6)
-#define CPU_DBGCPUXCOMMRXFULL			(GIC_PPI_START + 7)
-#define CPU_DBGCPUXCOMMTXEMPTY			(GIC_PPI_START + 8)
-#define CPU_SICCPUXPERFMONIRPTREQ		(GIC_PPI_START + 9)
-#define SC_AVSCPUXDOWN				(GIC_PPI_START + 10)
-#define SC_AVSCPUXUP				(GIC_PPI_START + 11)
-#define SC_SICCPUXACGIRPTREQ			(GIC_PPI_START + 12)
-/* PPI 13 to 15 are unused */
-
-
-#define SC_SICMPUIRPTREQ			(GIC_SPI_START + 0)
-#define SC_SICL2IRPTREQ				(GIC_SPI_START + 1)
-#define SC_SICL2ACGIRPTREQ			(GIC_SPI_START + 2)
-#define NC					(GIC_SPI_START + 3)
-#define TLMM_SCSS_DIR_CONN_IRQ_0		(GIC_SPI_START + 4)
-#define TLMM_SCSS_DIR_CONN_IRQ_1		(GIC_SPI_START + 5)
-#define TLMM_SCSS_DIR_CONN_IRQ_2		(GIC_SPI_START + 6)
-#define TLMM_SCSS_DIR_CONN_IRQ_3		(GIC_SPI_START + 7)
-#define TLMM_SCSS_DIR_CONN_IRQ_4		(GIC_SPI_START + 8)
-#define TLMM_SCSS_DIR_CONN_IRQ_5		(GIC_SPI_START + 9)
-#define TLMM_SCSS_DIR_CONN_IRQ_6		(GIC_SPI_START + 10)
-#define TLMM_SCSS_DIR_CONN_IRQ_7		(GIC_SPI_START + 11)
-#define TLMM_SCSS_DIR_CONN_IRQ_8		(GIC_SPI_START + 12)
-#define TLMM_SCSS_DIR_CONN_IRQ_9		(GIC_SPI_START + 13)
-#define PM8058_SEC_IRQ_N			(GIC_SPI_START + 14)
-#define PM8901_SEC_IRQ_N			(GIC_SPI_START + 15)
-#define TLMM_SCSS_SUMMARY_IRQ			(GIC_SPI_START + 16)
-#define SPDM_RT_1_IRQ				(GIC_SPI_START + 17)
-#define SPDM_DIAG_IRQ				(GIC_SPI_START + 18)
-#define RPM_SCSS_CPU0_GP_HIGH_IRQ		(GIC_SPI_START + 19)
-#define RPM_SCSS_CPU0_GP_MEDIUM_IRQ		(GIC_SPI_START + 20)
-#define RPM_SCSS_CPU0_GP_LOW_IRQ		(GIC_SPI_START + 21)
-#define RPM_SCSS_CPU0_WAKE_UP_IRQ		(GIC_SPI_START + 22)
-#define RPM_SCSS_CPU1_GP_HIGH_IRQ		(GIC_SPI_START + 23)
-#define RPM_SCSS_CPU1_GP_MEDIUM_IRQ		(GIC_SPI_START + 24)
-#define RPM_SCSS_CPU1_GP_LOW_IRQ		(GIC_SPI_START + 25)
-#define RPM_SCSS_CPU1_WAKE_UP_IRQ		(GIC_SPI_START + 26)
-#define SSBI2_2_SC_CPU0_SECURE_INT		(GIC_SPI_START + 27)
-#define SSBI2_2_SC_CPU0_NON_SECURE_INT		(GIC_SPI_START + 28)
-#define SSBI2_1_SC_CPU0_SECURE_INT		(GIC_SPI_START + 29)
-#define SSBI2_1_SC_CPU0_NON_SECURE_INT		(GIC_SPI_START + 30)
-#define MSMC_SC_SEC_CE_IRQ			(GIC_SPI_START + 31)
-#define MSMC_SC_PRI_CE_IRQ			(GIC_SPI_START + 32)
-#define MARM_FIQ				(GIC_SPI_START + 33)
-#define MARM_IRQ				(GIC_SPI_START + 34)
-#define MARM_L2CC_IRQ				(GIC_SPI_START + 35)
-#define MARM_WDOG_EXPIRED			(GIC_SPI_START + 36)
-#define MARM_SCSS_GP_IRQ_0			(GIC_SPI_START + 37)
-#define MARM_SCSS_GP_IRQ_1			(GIC_SPI_START + 38)
-#define MARM_SCSS_GP_IRQ_2			(GIC_SPI_START + 39)
-#define MARM_SCSS_GP_IRQ_3			(GIC_SPI_START + 40)
-#define MARM_SCSS_GP_IRQ_4			(GIC_SPI_START + 41)
-#define MARM_SCSS_GP_IRQ_5			(GIC_SPI_START + 42)
-#define MARM_SCSS_GP_IRQ_6			(GIC_SPI_START + 43)
-#define MARM_SCSS_GP_IRQ_7			(GIC_SPI_START + 44)
-#define MARM_SCSS_GP_IRQ_8			(GIC_SPI_START + 45)
-#define MARM_SCSS_GP_IRQ_9			(GIC_SPI_START + 46)
-#define VPE_IRQ					(GIC_SPI_START + 47)
-#define VFE_IRQ					(GIC_SPI_START + 48)
-#define VCODEC_IRQ				(GIC_SPI_START + 49)
-#define TV_ENC_IRQ				(GIC_SPI_START + 50)
-#define SMMU_VPE_CB_SC_SECURE_IRQ		(GIC_SPI_START + 51)
-#define SMMU_VPE_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 52)
-#define SMMU_VFE_CB_SC_SECURE_IRQ		(GIC_SPI_START + 53)
-#define SMMU_VFE_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 54)
-#define SMMU_VCODEC_B_CB_SC_SECURE_IRQ		(GIC_SPI_START + 55)
-#define SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ	(GIC_SPI_START + 56)
-#define SMMU_VCODEC_A_CB_SC_SECURE_IRQ		(GIC_SPI_START + 57)
-#define SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ	(GIC_SPI_START + 58)
-#define SMMU_ROT_CB_SC_SECURE_IRQ		(GIC_SPI_START + 59)
-#define SMMU_ROT_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 60)
-#define SMMU_MDP1_CB_SC_SECURE_IRQ		(GIC_SPI_START + 61)
-#define SMMU_MDP1_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 62)
-#define SMMU_MDP0_CB_SC_SECURE_IRQ		(GIC_SPI_START + 63)
-#define SMMU_MDP0_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 64)
-#define SMMU_JPEGD_CB_SC_SECURE_IRQ		(GIC_SPI_START + 65)
-#define SMMU_JPEGD_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 66)
-#define SMMU_IJPEG_CB_SC_SECURE_IRQ		(GIC_SPI_START + 67)
-#define SMMU_IJPEG_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 68)
-#define SMMU_GFX3D_CB_SC_SECURE_IRQ		(GIC_SPI_START + 69)
-#define SMMU_GFX3D_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 70)
-#define SMMU_GFX2D0_CB_SC_SECURE_IRQ		(GIC_SPI_START + 71)
-#define SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ	(GIC_SPI_START + 72)
-#define ROT_IRQ					(GIC_SPI_START + 73)
-#define MMSS_FABRIC_IRQ				(GIC_SPI_START + 74)
-#define MDP_IRQ					(GIC_SPI_START + 75)
-#define JPEGD_IRQ				(GIC_SPI_START + 76)
-#define JPEG_IRQ				(GIC_SPI_START + 77)
-#define MMSS_IMEM_IRQ				(GIC_SPI_START + 78)
-#define HDMI_IRQ				(GIC_SPI_START + 79)
-#define GFX3D_IRQ				(GIC_SPI_START + 80)
-#define GFX2D0_IRQ				(GIC_SPI_START + 81)
-#define DSI_IRQ					(GIC_SPI_START + 82)
-#define CSI_1_IRQ				(GIC_SPI_START + 83)
-#define CSI_0_IRQ				(GIC_SPI_START + 84)
-#define LPASS_SCSS_AUDIO_IF_OUT0_IRQ		(GIC_SPI_START + 85)
-#define LPASS_SCSS_MIDI_IRQ			(GIC_SPI_START + 86)
-#define LPASS_Q6SS_WDOG_EXPIRED			(GIC_SPI_START + 87)
-#define LPASS_SCSS_GP_LOW_IRQ			(GIC_SPI_START + 88)
-#define LPASS_SCSS_GP_MEDIUM_IRQ		(GIC_SPI_START + 89)
-#define LPASS_SCSS_GP_HIGH_IRQ			(GIC_SPI_START + 90)
-#define TOP_IMEM_IRQ				(GIC_SPI_START + 91)
-#define FABRIC_SYS_IRQ				(GIC_SPI_START + 92)
-#define FABRIC_APPS_IRQ				(GIC_SPI_START + 93)
-#define USB1_HS_BAM_IRQ				(GIC_SPI_START + 94)
-#define SDC4_BAM_IRQ				(GIC_SPI_START + 95)
-#define SDC3_BAM_IRQ				(GIC_SPI_START + 96)
-#define SDC2_BAM_IRQ				(GIC_SPI_START + 97)
-#define SDC1_BAM_IRQ				(GIC_SPI_START + 98)
-#define FABRIC_SPS_IRQ				(GIC_SPI_START + 99)
-#define USB1_HS_IRQ				(GIC_SPI_START + 100)
-#define SDC4_IRQ_0				(GIC_SPI_START + 101)
-#define SDC3_IRQ_0				(GIC_SPI_START + 102)
-#define SDC2_IRQ_0				(GIC_SPI_START + 103)
-#define SDC1_IRQ_0				(GIC_SPI_START + 104)
-#define SPS_BAM_DMA_IRQ				(GIC_SPI_START + 105)
-#define SPS_SEC_VIOL_IRQ			(GIC_SPI_START + 106)
-#define SPS_MTI_0				(GIC_SPI_START + 107)
-#define SPS_MTI_1				(GIC_SPI_START + 108)
-#define SPS_MTI_2				(GIC_SPI_START + 109)
-#define SPS_MTI_3				(GIC_SPI_START + 110)
-#define SPS_MTI_4				(GIC_SPI_START + 111)
-#define SPS_MTI_5				(GIC_SPI_START + 112)
-#define SPS_MTI_6				(GIC_SPI_START + 113)
-#define SPS_MTI_7				(GIC_SPI_START + 114)
-#define SPS_MTI_8				(GIC_SPI_START + 115)
-#define SPS_MTI_9				(GIC_SPI_START + 116)
-#define SPS_MTI_10				(GIC_SPI_START + 117)
-#define SPS_MTI_11				(GIC_SPI_START + 118)
-#define SPS_MTI_12				(GIC_SPI_START + 119)
-#define SPS_MTI_13				(GIC_SPI_START + 120)
-#define SPS_MTI_14				(GIC_SPI_START + 121)
-#define SPS_MTI_15				(GIC_SPI_START + 122)
-#define SPS_MTI_16				(GIC_SPI_START + 123)
-#define SPS_MTI_17				(GIC_SPI_START + 124)
-#define SPS_MTI_18				(GIC_SPI_START + 125)
-#define SPS_MTI_19				(GIC_SPI_START + 126)
-#define SPS_MTI_20				(GIC_SPI_START + 127)
-#define SPS_MTI_21				(GIC_SPI_START + 128)
-#define SPS_MTI_22				(GIC_SPI_START + 129)
-#define SPS_MTI_23				(GIC_SPI_START + 130)
-#define SPS_MTI_24				(GIC_SPI_START + 131)
-#define SPS_MTI_25				(GIC_SPI_START + 132)
-#define SPS_MTI_26				(GIC_SPI_START + 133)
-#define SPS_MTI_27				(GIC_SPI_START + 134)
-#define SPS_MTI_28				(GIC_SPI_START + 135)
-#define SPS_MTI_29				(GIC_SPI_START + 136)
-#define SPS_MTI_30				(GIC_SPI_START + 137)
-#define SPS_MTI_31				(GIC_SPI_START + 138)
-#define UXMC_EBI2_WR_ER_DONE_IRQ		(GIC_SPI_START + 139)
-#define UXMC_EBI2_OP_DONE_IRQ			(GIC_SPI_START + 140)
-#define USB2_IRQ				(GIC_SPI_START + 141)
-#define USB1_IRQ				(GIC_SPI_START + 142)
-#define TSSC_SSBI_IRQ				(GIC_SPI_START + 143)
-#define TSSC_SAMPLE_IRQ				(GIC_SPI_START + 144)
-#define TSSC_PENUP_IRQ				(GIC_SPI_START + 145)
-#define INT_UART1DM_IRQ				(GIC_SPI_START + 146)
-#define GSBI1_QUP_IRQ				(GIC_SPI_START + 147)
-#define INT_UART2DM_IRQ				(GIC_SPI_START + 148)
-#define GSBI2_QUP_IRQ				(GIC_SPI_START + 149)
-#define INT_UART3DM_IRQ				(GIC_SPI_START + 150)
-#define GSBI3_QUP_IRQ				(GIC_SPI_START + 151)
-#define INT_UART4DM_IRQ				(GIC_SPI_START + 152)
-#define GSBI4_QUP_IRQ				(GIC_SPI_START + 153)
-#define INT_UART5DM_IRQ				(GIC_SPI_START + 154)
-#define GSBI5_QUP_IRQ				(GIC_SPI_START + 155)
-#define INT_UART6DM_IRQ				(GIC_SPI_START + 156)
-#define GSBI6_QUP_IRQ				(GIC_SPI_START + 157)
-#define INT_UART7DM_IRQ				(GIC_SPI_START + 158)
-#define GSBI7_QUP_IRQ				(GIC_SPI_START + 159)
-#define INT_UART8DM_IRQ				(GIC_SPI_START + 160)
-#define GSBI8_QUP_IRQ				(GIC_SPI_START + 161)
-#define TSIF_TSPP_IRQ				(GIC_SPI_START + 162)
-#define TSIF_BAM_IRQ				(GIC_SPI_START + 163)
-#define TSIF2_IRQ				(GIC_SPI_START + 164)
-#define TSIF1_IRQ				(GIC_SPI_START + 165)
-#define INT_ADM1_MASTER				(GIC_SPI_START + 166)
-#define INT_ADM1_AARM				(GIC_SPI_START + 167)
-#define INT_ADM1_SD2				(GIC_SPI_START + 168)
-#define INT_ADM1_SD3				(GIC_SPI_START + 169)
-#define INT_ADM0_MASTER				(GIC_SPI_START + 170)
-#define INT_ADM0_AARM				(GIC_SPI_START + 171)
-#define INT_ADM0_SD2				(GIC_SPI_START + 172)
-#define INT_ADM0_SD3				(GIC_SPI_START + 173)
-#define CC_SCSS_WDT1CPU1BITEEXPIRED		(GIC_SPI_START + 174)
-#define CC_SCSS_WDT1CPU0BITEEXPIRED		(GIC_SPI_START + 175)
-#define CC_SCSS_WDT0CPU1BITEEXPIRED		(GIC_SPI_START + 176)
-#define CC_SCSS_WDT0CPU0BITEEXPIRED		(GIC_SPI_START + 177)
-#define TSENS_UPPER_LOWER_INT			(GIC_SPI_START + 178)
-#define SSBI2_2_SC_CPU1_SECURE_INT		(GIC_SPI_START + 179)
-#define SSBI2_2_SC_CPU1_NON_SECURE_INT		(GIC_SPI_START + 180)
-#define SSBI2_1_SC_CPU1_SECURE_INT		(GIC_SPI_START + 181)
-#define SSBI2_1_SC_CPU1_NON_SECURE_INT		(GIC_SPI_START + 182)
-#define XPU_SUMMARY_IRQ				(GIC_SPI_START + 183)
-#define BUS_EXCEPTION_SUMMARY_IRQ		(GIC_SPI_START + 184)
-#define HSDDRX_SMICH0_IRQ			(GIC_SPI_START + 185)
-#define HSDDRX_EBI1_IRQ				(GIC_SPI_START + 186)
-#define SDC5_BAM_IRQ				(GIC_SPI_START + 187)
-#define SDC5_IRQ_0				(GIC_SPI_START + 188)
-#define INT_UART9DM_IRQ				(GIC_SPI_START + 189)
-#define GSBI9_QUP_IRQ				(GIC_SPI_START + 190)
-#define INT_UART10DM_IRQ			(GIC_SPI_START + 191)
-#define GSBI10_QUP_IRQ				(GIC_SPI_START + 192)
-#define INT_UART11DM_IRQ			(GIC_SPI_START + 193)
-#define GSBI11_QUP_IRQ				(GIC_SPI_START + 194)
-#define INT_UART12DM_IRQ			(GIC_SPI_START + 195)
-#define GSBI12_QUP_IRQ				(GIC_SPI_START + 196)
-
-/*SPI 197 to 209 arent used in 8x60*/
-#define SMMU_GFX2D1_CB_SC_SECURE_IRQ            (GIC_SPI_START + 210)
-#define SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ        (GIC_SPI_START + 211)
-
-/*SPI 212 to 216 arent used in 8x60*/
-#define SMPSS_SPARE_1				(GIC_SPI_START + 217)
-#define SMPSS_SPARE_2				(GIC_SPI_START + 218)
-#define SMPSS_SPARE_3				(GIC_SPI_START + 219)
-#define SMPSS_SPARE_4				(GIC_SPI_START + 220)
-#define SMPSS_SPARE_5				(GIC_SPI_START + 221)
-#define SMPSS_SPARE_6				(GIC_SPI_START + 222)
-#define SMPSS_SPARE_7				(GIC_SPI_START + 223)
-
-#define NR_GPIO_IRQS 173
-#define NR_MSM_IRQS 256
-#define NR_BOARD_IRQS 0
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/irqs.h b/arch/arm/mach-msm/include/mach/irqs.h
index 3cd78b1..164d355 100644
--- a/arch/arm/mach-msm/include/mach/irqs.h
+++ b/arch/arm/mach-msm/include/mach/irqs.h
@@ -24,11 +24,6 @@
 #elif defined(CONFIG_ARCH_QSD8X50)
 #include "irqs-8x50.h"
 #include "sirc.h"
-#elif defined(CONFIG_ARCH_MSM8X60)
-#include "irqs-8x60.h"
-#elif defined(CONFIG_ARCH_MSM8960)
-/* TODO: Make these not generic. */
-#include "irqs-8960.h"
 #elif defined(CONFIG_ARCH_MSM_ARM11)
 #include "irqs-7x00.h"
 #else
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 696fb73..1e9c338 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -274,7 +274,6 @@
 		pr_err("Unknown frequency\n");
 		return;
 	}
-	of_node_put(np);
 
 	event_base = base + 0x4;
 	sts_base = base + 0x88;
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c
index 98f6e2a..1dc5acd 100644
--- a/arch/arm/mach-mxs/mach-mxs.c
+++ b/arch/arm/mach-mxs/mach-mxs.c
@@ -13,8 +13,6 @@
 #include <linux/clk.h>
 #include <linux/clk/mxs.h>
 #include <linux/clkdev.h>
-#include <linux/clocksource.h>
-#include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
@@ -332,6 +330,11 @@
 	update_fec_mac_prop(OUI_CRYSTALFONTZ);
 }
 
+static void __init m28cu3_init(void)
+{
+	update_fec_mac_prop(OUI_DENX);
+}
+
 static const char __init *mxs_get_soc_id(void)
 {
 	struct device_node *np;
@@ -459,6 +462,8 @@
 		apx4devkit_init();
 	else if (of_machine_is_compatible("crystalfontz,cfa10036"))
 		crystalfontz_init();
+	else if (of_machine_is_compatible("msr,m28cu3"))
+		m28cu3_init();
 
 	of_platform_populate(NULL, of_default_bus_match_table,
 			     NULL, parent);
@@ -490,16 +495,6 @@
 	soft_restart(0);
 }
 
-static void __init mxs_timer_init(void)
-{
-	if (of_machine_is_compatible("fsl,imx23"))
-		mx23_clocks_init();
-	else
-		mx28_clocks_init();
-	of_clk_init(NULL);
-	clocksource_of_init();
-}
-
 static const char *mxs_dt_compat[] __initdata = {
 	"fsl,imx28",
 	"fsl,imx23",
@@ -508,7 +503,6 @@
 
 DT_MACHINE_START(MXS, "Freescale MXS (Device Tree)")
 	.handle_irq	= icoll_handle_irq,
-	.init_time	= mxs_timer_init,
 	.init_machine	= mxs_machine_init,
 	.init_late      = mxs_pm_init,
 	.dt_compat	= mxs_dt_compat,
diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c
index 13e0df9..cce2c9d 100644
--- a/arch/arm/mach-nomadik/cpu-8815.c
+++ b/arch/arm/mach-nomadik/cpu-8815.c
@@ -25,15 +25,11 @@
 #include <linux/slab.h>
 #include <linux/irq.h>
 #include <linux/dma-mapping.h>
-#include <linux/platform_data/clk-nomadik.h>
-#include <linux/clocksource.h>
 #include <linux/of_irq.h>
 #include <linux/of_gpio.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
-#include <linux/mtd/fsmc.h>
 #include <linux/gpio.h>
-#include <linux/amba/mmci.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -113,50 +109,6 @@
 	writel(1, srcbase + 0x18);
 }
 
-/* Initial value for SRC control register: all timers use MXTAL/8 source */
-#define SRC_CR_INIT_MASK	0x00007fff
-#define SRC_CR_INIT_VAL		0x2aaa8000
-
-static void __init cpu8815_timer_init_of(void)
-{
-	struct device_node *mtu;
-	void __iomem *base;
-	int irq;
-	u32 src_cr;
-
-	/* We need this to be up now */
-	nomadik_clk_init();
-
-	mtu = of_find_node_by_path("/mtu@101e2000");
-	if (!mtu)
-		return;
-	base = of_iomap(mtu, 0);
-	if (WARN_ON(!base))
-		return;
-	irq = irq_of_parse_and_map(mtu, 0);
-
-	pr_info("Remapped MTU @ %p, irq: %d\n", base, irq);
-
-	/* Configure timer sources in "system reset controller" ctrl reg */
-	src_cr = readl(base);
-	src_cr &= SRC_CR_INIT_MASK;
-	src_cr |= SRC_CR_INIT_VAL;
-	writel(src_cr, base);
-
-	clocksource_of_init();
-}
-
-static struct fsmc_nand_timings cpu8815_nand_timings = {
-	.thiz	= 0,
-	.thold	= 0x10,
-	.twait	= 0x0A,
-	.tset	= 0,
-};
-
-static struct fsmc_nand_platform_data cpu8815_nand_data = {
-	.nand_timings = &cpu8815_nand_timings,
-};
-
 /*
  * The SMSC911x IRQ is connected to a GPIO pin, but the driver expects
  * to simply request an IRQ passed as a resource. So the GPIO pin needs
@@ -190,15 +142,6 @@
 device_initcall(cpu8815_eth_init);
 
 /*
- * TODO:
- * cannot be set from device tree, convert to a proper DT
- * binding.
- */
-static struct mmci_platform_data mmcsd_plat_data = {
-	.ocr_mask = MMC_VDD_29_30,
-};
-
-/*
  * This GPIO pin turns on a line that is used to detect card insertion
  * on this board.
  */
@@ -232,24 +175,13 @@
 }
 device_initcall(cpu8815_mmcsd_init);
 
-
-/* These are mostly to get the right device names for the clock lookups */
-static struct of_dev_auxdata cpu8815_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("stericsson,fsmc-nand", NOMADIK_FSMC_BASE,
-		NULL, &cpu8815_nand_data),
-	OF_DEV_AUXDATA("arm,primecell", NOMADIK_SDI_BASE,
-		NULL, &mmcsd_plat_data),
-	{ /* sentinel */ },
-};
-
 static void __init cpu8815_init_of(void)
 {
 #ifdef CONFIG_CACHE_L2X0
 	/* At full speed latency must be >=2, so 0x249 in low bits */
 	l2x0_of_init(0x00730249, 0xfe000fff);
 #endif
-	of_platform_populate(NULL, of_default_bus_match_table,
-			cpu8815_auxdata_lookup, NULL);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static const char * cpu8815_board_compat[] = {
@@ -259,7 +191,6 @@
 
 DT_MACHINE_START(NOMADIK_DT, "Nomadik STn8815")
 	.map_io		= cpu8815_map_io,
-	.init_time	= cpu8815_timer_init_of,
 	.init_machine	= cpu8815_init_of,
 	.restart	= cpu8815_restart,
 	.dt_compat      = cpu8815_board_compat,
diff --git a/arch/arm/mach-nspire/nspire.c b/arch/arm/mach-nspire/nspire.c
index 99e2609..4b2ed2e 100644
--- a/arch/arm/mach-nspire/nspire.c
+++ b/arch/arm/mach-nspire/nspire.c
@@ -14,11 +14,9 @@
 #include <linux/of_platform.h>
 #include <linux/irqchip.h>
 #include <linux/irqchip/arm-vic.h>
-#include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
-#include <linux/clocksource.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -65,12 +63,6 @@
 			nspire_auxdata, NULL);
 }
 
-static void __init nspire_init_time(void)
-{
-	of_clk_init(NULL);
-	clocksource_of_init();
-}
-
 static void nspire_restart(char mode, const char *cmd)
 {
 	void __iomem *base = ioremap(NSPIRE_MISC_PHYS_BASE, SZ_4K);
@@ -83,7 +75,6 @@
 DT_MACHINE_START(NSPIRE, "TI-NSPIRE")
 	.dt_compat	= nspire_dt_match,
 	.map_io		= nspire_map_io,
-	.init_time	= nspire_init_time,
 	.init_machine	= nspire_init,
 	.restart	= nspire_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/common.h b/arch/arm/mach-omap1/common.h
index abec019..732f8ee 100644
--- a/arch/arm/mach-omap1/common.h
+++ b/arch/arm/mach-omap1/common.h
@@ -46,6 +46,9 @@
 void omap1510_fpga_init_irq(void);
 void omap15xx_map_io(void);
 #else
+static inline void omap1510_fpga_init_irq(void)
+{
+}
 static inline void omap15xx_map_io(void)
 {
 }
diff --git a/arch/arm/mach-omap1/fpga.c b/arch/arm/mach-omap1/fpga.c
index 8bd71b2..3c0e422 100644
--- a/arch/arm/mach-omap1/fpga.c
+++ b/arch/arm/mach-omap1/fpga.c
@@ -135,8 +135,7 @@
  * mask_ack routine for all of the FPGA interrupts has been changed from
  * fpga_mask_ack_irq() to fpga_ack_irq() so that the specific FPGA interrupt
  * being serviced is left unmasked.  We can do this because the FPGA cascade
- * interrupt is installed with the IRQF_DISABLED flag, which leaves all
- * interrupts masked at the CPU while an FPGA interrupt handler executes.
+ * interrupt is run with all interrupts masked.
  *
  * Limited testing indicates that this workaround appears to be effective
  * for the smc9194 Ethernet driver used on the Innovator.  It should work
diff --git a/arch/arm/mach-omap1/gpio15xx.c b/arch/arm/mach-omap1/gpio15xx.c
index 02b3eb2..312a092 100644
--- a/arch/arm/mach-omap1/gpio15xx.c
+++ b/arch/arm/mach-omap1/gpio15xx.c
@@ -25,7 +25,7 @@
 #define OMAP1510_GPIO_BASE		0xFFFCE000
 
 /* gpio1 */
-static struct __initdata resource omap15xx_mpu_gpio_resources[] = {
+static struct resource omap15xx_mpu_gpio_resources[] = {
 	{
 		.start	= OMAP1_MPUIO_VBASE,
 		.end	= OMAP1_MPUIO_VBASE + SZ_2K - 1,
@@ -48,7 +48,7 @@
 	.irqctrl	= OMAP_MPUIO_GPIO_INT_EDGE,
 };
 
-static struct __initdata omap_gpio_platform_data omap15xx_mpu_gpio_config = {
+static struct omap_gpio_platform_data omap15xx_mpu_gpio_config = {
 	.is_mpuio		= true,
 	.bank_width		= 16,
 	.bank_stride		= 1,
@@ -66,7 +66,7 @@
 };
 
 /* gpio2 */
-static struct __initdata resource omap15xx_gpio_resources[] = {
+static struct resource omap15xx_gpio_resources[] = {
 	{
 		.start	= OMAP1510_GPIO_BASE,
 		.end	= OMAP1510_GPIO_BASE + SZ_2K - 1,
@@ -90,7 +90,7 @@
 	.pinctrl	= OMAP1510_GPIO_PIN_CONTROL,
 };
 
-static struct __initdata omap_gpio_platform_data omap15xx_gpio_config = {
+static struct omap_gpio_platform_data omap15xx_gpio_config = {
 	.bank_width		= 16,
 	.regs                   = &omap15xx_gpio_regs,
 };
diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c
index b9952a2..6e6ec93 100644
--- a/arch/arm/mach-omap1/gpio16xx.c
+++ b/arch/arm/mach-omap1/gpio16xx.c
@@ -31,7 +31,7 @@
 #define SYSCONFIG_WORD			0x14
 
 /* mpu gpio */
-static struct __initdata resource omap16xx_mpu_gpio_resources[] = {
+static struct resource omap16xx_mpu_gpio_resources[] = {
 	{
 		.start	= OMAP1_MPUIO_VBASE,
 		.end	= OMAP1_MPUIO_VBASE + SZ_2K - 1,
@@ -54,7 +54,7 @@
 	.irqctrl	= OMAP_MPUIO_GPIO_INT_EDGE,
 };
 
-static struct __initdata omap_gpio_platform_data omap16xx_mpu_gpio_config = {
+static struct omap_gpio_platform_data omap16xx_mpu_gpio_config = {
 	.is_mpuio		= true,
 	.bank_width		= 16,
 	.bank_stride		= 1,
@@ -72,7 +72,7 @@
 };
 
 /* gpio1 */
-static struct __initdata resource omap16xx_gpio1_resources[] = {
+static struct resource omap16xx_gpio1_resources[] = {
 	{
 		.start	= OMAP1610_GPIO1_BASE,
 		.end	= OMAP1610_GPIO1_BASE + SZ_2K - 1,
@@ -100,7 +100,7 @@
 	.edgectrl2	= OMAP1610_GPIO_EDGE_CTRL2,
 };
 
-static struct __initdata omap_gpio_platform_data omap16xx_gpio1_config = {
+static struct omap_gpio_platform_data omap16xx_gpio1_config = {
 	.bank_width		= 16,
 	.regs                   = &omap16xx_gpio_regs,
 };
@@ -116,7 +116,7 @@
 };
 
 /* gpio2 */
-static struct __initdata resource omap16xx_gpio2_resources[] = {
+static struct resource omap16xx_gpio2_resources[] = {
 	{
 		.start	= OMAP1610_GPIO2_BASE,
 		.end	= OMAP1610_GPIO2_BASE + SZ_2K - 1,
@@ -128,7 +128,7 @@
 	},
 };
 
-static struct __initdata omap_gpio_platform_data omap16xx_gpio2_config = {
+static struct omap_gpio_platform_data omap16xx_gpio2_config = {
 	.bank_width		= 16,
 	.regs                   = &omap16xx_gpio_regs,
 };
@@ -144,7 +144,7 @@
 };
 
 /* gpio3 */
-static struct __initdata resource omap16xx_gpio3_resources[] = {
+static struct resource omap16xx_gpio3_resources[] = {
 	{
 		.start	= OMAP1610_GPIO3_BASE,
 		.end	= OMAP1610_GPIO3_BASE + SZ_2K - 1,
@@ -156,7 +156,7 @@
 	},
 };
 
-static struct __initdata omap_gpio_platform_data omap16xx_gpio3_config = {
+static struct omap_gpio_platform_data omap16xx_gpio3_config = {
 	.bank_width		= 16,
 	.regs                   = &omap16xx_gpio_regs,
 };
@@ -172,7 +172,7 @@
 };
 
 /* gpio4 */
-static struct __initdata resource omap16xx_gpio4_resources[] = {
+static struct resource omap16xx_gpio4_resources[] = {
 	{
 		.start	= OMAP1610_GPIO4_BASE,
 		.end	= OMAP1610_GPIO4_BASE + SZ_2K - 1,
@@ -184,7 +184,7 @@
 	},
 };
 
-static struct __initdata omap_gpio_platform_data omap16xx_gpio4_config = {
+static struct omap_gpio_platform_data omap16xx_gpio4_config = {
 	.bank_width		= 16,
 	.regs                   = &omap16xx_gpio_regs,
 };
@@ -199,7 +199,7 @@
 	.resource = omap16xx_gpio4_resources,
 };
 
-static struct __initdata platform_device * omap16xx_gpio_dev[] = {
+static struct platform_device *omap16xx_gpio_dev[] __initdata = {
 	&omap16xx_mpu_gpio,
 	&omap16xx_gpio1,
 	&omap16xx_gpio2,
diff --git a/arch/arm/mach-omap1/gpio7xx.c b/arch/arm/mach-omap1/gpio7xx.c
index f5819b2..4612d25 100644
--- a/arch/arm/mach-omap1/gpio7xx.c
+++ b/arch/arm/mach-omap1/gpio7xx.c
@@ -30,7 +30,7 @@
 #define OMAP1_MPUIO_VBASE		OMAP1_MPUIO_BASE
 
 /* mpu gpio */
-static struct __initdata resource omap7xx_mpu_gpio_resources[] = {
+static struct resource omap7xx_mpu_gpio_resources[] = {
 	{
 		.start	= OMAP1_MPUIO_VBASE,
 		.end	= OMAP1_MPUIO_VBASE + SZ_2K - 1,
@@ -53,7 +53,7 @@
 	.irqctrl	= OMAP_MPUIO_GPIO_INT_EDGE >> 1,
 };
 
-static struct __initdata omap_gpio_platform_data omap7xx_mpu_gpio_config = {
+static struct omap_gpio_platform_data omap7xx_mpu_gpio_config = {
 	.is_mpuio		= true,
 	.bank_width		= 16,
 	.bank_stride		= 2,
@@ -71,7 +71,7 @@
 };
 
 /* gpio1 */
-static struct __initdata resource omap7xx_gpio1_resources[] = {
+static struct resource omap7xx_gpio1_resources[] = {
 	{
 		.start	= OMAP7XX_GPIO1_BASE,
 		.end	= OMAP7XX_GPIO1_BASE + SZ_2K - 1,
@@ -94,7 +94,7 @@
 	.irqctrl	= OMAP7XX_GPIO_INT_CONTROL,
 };
 
-static struct __initdata omap_gpio_platform_data omap7xx_gpio1_config = {
+static struct omap_gpio_platform_data omap7xx_gpio1_config = {
 	.bank_width		= 32,
 	.regs			= &omap7xx_gpio_regs,
 };
@@ -110,7 +110,7 @@
 };
 
 /* gpio2 */
-static struct __initdata resource omap7xx_gpio2_resources[] = {
+static struct resource omap7xx_gpio2_resources[] = {
 	{
 		.start	= OMAP7XX_GPIO2_BASE,
 		.end	= OMAP7XX_GPIO2_BASE + SZ_2K - 1,
@@ -122,7 +122,7 @@
 	},
 };
 
-static struct __initdata omap_gpio_platform_data omap7xx_gpio2_config = {
+static struct omap_gpio_platform_data omap7xx_gpio2_config = {
 	.bank_width		= 32,
 	.regs			= &omap7xx_gpio_regs,
 };
@@ -138,7 +138,7 @@
 };
 
 /* gpio3 */
-static struct __initdata resource omap7xx_gpio3_resources[] = {
+static struct resource omap7xx_gpio3_resources[] = {
 	{
 		.start	= OMAP7XX_GPIO3_BASE,
 		.end	= OMAP7XX_GPIO3_BASE + SZ_2K - 1,
@@ -150,7 +150,7 @@
 	},
 };
 
-static struct __initdata omap_gpio_platform_data omap7xx_gpio3_config = {
+static struct omap_gpio_platform_data omap7xx_gpio3_config = {
 	.bank_width		= 32,
 	.regs			= &omap7xx_gpio_regs,
 };
@@ -166,7 +166,7 @@
 };
 
 /* gpio4 */
-static struct __initdata resource omap7xx_gpio4_resources[] = {
+static struct resource omap7xx_gpio4_resources[] = {
 	{
 		.start	= OMAP7XX_GPIO4_BASE,
 		.end	= OMAP7XX_GPIO4_BASE + SZ_2K - 1,
@@ -178,7 +178,7 @@
 	},
 };
 
-static struct __initdata omap_gpio_platform_data omap7xx_gpio4_config = {
+static struct omap_gpio_platform_data omap7xx_gpio4_config = {
 	.bank_width		= 32,
 	.regs			= &omap7xx_gpio_regs,
 };
@@ -194,7 +194,7 @@
 };
 
 /* gpio5 */
-static struct __initdata resource omap7xx_gpio5_resources[] = {
+static struct resource omap7xx_gpio5_resources[] = {
 	{
 		.start	= OMAP7XX_GPIO5_BASE,
 		.end	= OMAP7XX_GPIO5_BASE + SZ_2K - 1,
@@ -206,7 +206,7 @@
 	},
 };
 
-static struct __initdata omap_gpio_platform_data omap7xx_gpio5_config = {
+static struct omap_gpio_platform_data omap7xx_gpio5_config = {
 	.bank_width		= 32,
 	.regs			= &omap7xx_gpio_regs,
 };
@@ -222,7 +222,7 @@
 };
 
 /* gpio6 */
-static struct __initdata resource omap7xx_gpio6_resources[] = {
+static struct resource omap7xx_gpio6_resources[] = {
 	{
 		.start	= OMAP7XX_GPIO6_BASE,
 		.end	= OMAP7XX_GPIO6_BASE + SZ_2K - 1,
@@ -234,7 +234,7 @@
 	},
 };
 
-static struct __initdata omap_gpio_platform_data omap7xx_gpio6_config = {
+static struct omap_gpio_platform_data omap7xx_gpio6_config = {
 	.bank_width		= 32,
 	.regs			= &omap7xx_gpio_regs,
 };
@@ -249,7 +249,7 @@
 	.resource = omap7xx_gpio6_resources,
 };
 
-static struct __initdata platform_device * omap7xx_gpio_dev[] = {
+static struct platform_device *omap7xx_gpio_dev[] __initdata = {
 	&omap7xx_mpu_gpio,
 	&omap7xx_gpio1,
 	&omap7xx_gpio2,
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
index 358b82c..40a1ae3 100644
--- a/arch/arm/mach-omap1/pm.c
+++ b/arch/arm/mach-omap1/pm.c
@@ -628,7 +628,6 @@
 
 static struct irqaction omap_wakeup_irq = {
 	.name		= "peripheral wakeup",
-	.flags		= IRQF_DISABLED,
 	.handler	= omap_wakeup_interrupt
 };
 
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
index 80603d2..6b5f298 100644
--- a/arch/arm/mach-omap1/time.c
+++ b/arch/arm/mach-omap1/time.c
@@ -160,7 +160,7 @@
 
 static struct irqaction omap_mpu_timer1_irq = {
 	.name		= "mpu_timer1",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
 	.handler	= omap_mpu_timer1_interrupt,
 };
 
diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c
index 0b74246..107e7ab 100644
--- a/arch/arm/mach-omap1/timer32k.c
+++ b/arch/arm/mach-omap1/timer32k.c
@@ -156,7 +156,7 @@
 
 static struct irqaction omap_32k_timer_irq = {
 	.name		= "32KHz timer",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
 	.handler	= omap_32k_timer_interrupt,
 };
 
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index b5fb5f7..dc21df1 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -8,7 +8,6 @@
 	select CPU_V6
 	select MULTI_IRQ_HANDLER
 	select SOC_HAS_OMAP2_SDRC
-	select COMMON_CLK
 
 config ARCH_OMAP3
 	bool "TI OMAP3"
@@ -22,7 +21,6 @@
 	select PM_OPP if PM
 	select PM_RUNTIME if CPU_IDLE
 	select SOC_HAS_OMAP2_SDRC
-	select COMMON_CLK
 	select USB_ARCH_HAS_EHCI if USB_SUPPORT
 
 config ARCH_OMAP4
@@ -45,7 +43,6 @@
 	select PM_OPP if PM
 	select PM_RUNTIME if CPU_IDLE
 	select USB_ARCH_HAS_EHCI if USB_SUPPORT
-	select COMMON_CLK
 	select ARM_ERRATA_754322
 	select ARM_ERRATA_775420
 
@@ -59,7 +56,6 @@
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if LOCAL_TIMERS
 	select HAVE_SMP
-	select COMMON_CLK
 	select HAVE_ARM_ARCH_TIMER
 	select ARM_ERRATA_798181 if SMP
 
@@ -70,7 +66,6 @@
 	select ARM_CPU_SUSPEND if PM
 	select CPU_V7
 	select MULTI_IRQ_HANDLER
-	select COMMON_CLK
 
 config SOC_AM43XX
 	bool "TI AM43x"
@@ -79,7 +74,6 @@
 	select ARCH_OMAP2PLUS
 	select MULTI_IRQ_HANDLER
 	select ARM_GIC
-	select COMMON_CLK
 	select MACH_OMAP_GENERIC
 
 config ARCH_OMAP2PLUS
@@ -89,11 +83,11 @@
 	select ARCH_HAS_HOLES_MEMORYMODEL
 	select ARCH_OMAP
 	select ARCH_REQUIRE_GPIOLIB
-	select CLKDEV_LOOKUP
 	select CLKSRC_MMIO
+	select COMMON_CLK
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_IRQ_CHIP
-	select HAVE_CLK
+	select MACH_OMAP_GENERIC
 	select OMAP_DM_TIMER
 	select PINCTRL
 	select PROC_DEVICETREE if PROC_FS
@@ -187,16 +181,11 @@
 config OMAP_PACKAGE_CBP
        bool
 
-comment "OMAP Board Type"
+comment "OMAP Legacy Platform Data Board Type"
 	depends on ARCH_OMAP2PLUS
 
 config MACH_OMAP_GENERIC
-	bool "Generic OMAP2+ board"
-	depends on ARCH_OMAP2PLUS
-	default y
-	help
-	  Support for generic TI OMAP2+ boards using Flattened Device Tree.
-	  More information at Documentation/devicetree
+	bool
 
 config MACH_OMAP2_TUSB6010
 	bool
@@ -260,12 +249,6 @@
 	default y
 	select OMAP_PACKAGE_CBB
 
-config MACH_OMAP3EVM
-	bool "OMAP 3530 EVM board"
-	depends on ARCH_OMAP3
-	default y
-	select OMAP_PACKAGE_CBB
-
 config MACH_OMAP3517EVM
 	bool "OMAP3517/ AM3517 EVM board"
 	depends on ARCH_OMAP3
@@ -314,33 +297,12 @@
 	select MACH_NOKIA_N810_WIMAX
 	select OMAP_PACKAGE_ZAC
 
-config MACH_NOKIA_RM680
-	bool "Nokia N950 (RM-680) / N9 (RM-696) phones"
-	depends on ARCH_OMAP3
-	default y
-	select MACH_NOKIA_RM696
-	select OMAP_PACKAGE_CBB
-
 config MACH_NOKIA_RX51
 	bool "Nokia N900 (RX-51) phone"
 	depends on ARCH_OMAP3
 	default y
 	select OMAP_PACKAGE_CBB
 
-config MACH_OMAP_ZOOM2
-	bool "OMAP3 Zoom2 board"
-	depends on ARCH_OMAP3
-	default y
-	select OMAP_PACKAGE_CBB
-	select REGULATOR_FIXED_VOLTAGE if REGULATOR
-
-config MACH_OMAP_ZOOM3
-	bool "OMAP3630 Zoom3 board"
-	depends on ARCH_OMAP3
-	default y
-	select OMAP_PACKAGE_CBP
-	select REGULATOR_FIXED_VOLTAGE if REGULATOR
-
 config MACH_CM_T35
 	bool "CompuLab CM-T35/CM-T3730 modules"
 	depends on ARCH_OMAP3
@@ -357,31 +319,12 @@
 config MACH_CM_T3730
        bool
 
-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 MACH_IGEP0020
-	select OMAP_PACKAGE_CBB
-
 config MACH_SBC3530
 	bool "OMAP3 SBC STALKER board"
 	depends on ARCH_OMAP3
 	default y
 	select OMAP_PACKAGE_CUS
 
-config MACH_OMAP_3630SDP
-	bool "OMAP3630 SDP board"
-	depends on ARCH_OMAP3
-	default y
-	select OMAP_PACKAGE_CBP
-
 config MACH_TI8168EVM
 	bool "TI8168 Evaluation Module"
 	depends on SOC_TI81XX
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index afb457c..e15ac00 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -8,7 +8,7 @@
 # Common support
 obj-y := id.o io.o control.o mux.o devices.o fb.o serial.o gpmc.o timer.o pm.o \
 	 common.o gpio.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o \
-	 omap_device.o sram.o
+	 omap_device.o sram.o drm.o
 
 omap-2-3-common				= irq.o
 hwmod-common				= omap_hwmod.o omap_hwmod_reset.o \
@@ -112,13 +112,13 @@
 obj-$(CONFIG_ARCH_OMAP3)		+= prm2xxx_3xxx.o prm3xxx.o cm3xxx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= vc3xxx_data.o vp3xxx_data.o
 obj-$(CONFIG_SOC_AM33XX)		+= prm33xx.o cm33xx.o
-obj-$(CONFIG_SOC_AM43XX)		+= prm33xx.o cm33xx.o
 omap-prcm-4-5-common			=  cminst44xx.o cm44xx.o prm44xx.o \
 					   prcm_mpu44xx.o prminst44xx.o \
 					   vc44xx_data.o vp44xx_data.o
 obj-$(CONFIG_ARCH_OMAP4)		+= $(omap-prcm-4-5-common)
 obj-$(CONFIG_SOC_OMAP5)			+= $(omap-prcm-4-5-common)
 obj-$(CONFIG_SOC_DRA7XX)		+= $(omap-prcm-4-5-common)
+obj-$(CONFIG_SOC_AM43XX)		+= $(omap-prcm-4-5-common)
 
 # OMAP voltage domains
 voltagedomain-common			:= voltage.o vc.o vp.o
@@ -146,6 +146,7 @@
 obj-$(CONFIG_SOC_AM33XX)		+= $(powerdomain-common)
 obj-$(CONFIG_SOC_AM33XX)		+= powerdomains33xx_data.o
 obj-$(CONFIG_SOC_AM43XX)		+= $(powerdomain-common)
+obj-$(CONFIG_SOC_AM43XX)		+= powerdomains43xx_data.o
 obj-$(CONFIG_SOC_OMAP5)			+= $(powerdomain-common)
 obj-$(CONFIG_SOC_OMAP5)			+= powerdomains54xx_data.o
 obj-$(CONFIG_SOC_DRA7XX)		+= $(powerdomain-common)
@@ -165,6 +166,7 @@
 obj-$(CONFIG_SOC_AM33XX)		+= $(clockdomain-common)
 obj-$(CONFIG_SOC_AM33XX)		+= clockdomains33xx_data.o
 obj-$(CONFIG_SOC_AM43XX)		+= $(clockdomain-common)
+obj-$(CONFIG_SOC_AM43XX)		+= clockdomains43xx_data.o
 obj-$(CONFIG_SOC_OMAP5)			+= $(clockdomain-common)
 obj-$(CONFIG_SOC_OMAP5)			+= clockdomains54xx_data.o
 obj-$(CONFIG_SOC_DRA7XX)		+= $(clockdomain-common)
@@ -210,6 +212,11 @@
 obj-$(CONFIG_ARCH_OMAP3)		+= omap_hwmod_2xxx_3xxx_interconnect_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= omap_hwmod_3xxx_data.o
 obj-$(CONFIG_SOC_AM33XX)		+= omap_hwmod_33xx_data.o
+obj-$(CONFIG_SOC_AM33XX)		+= omap_hwmod_33xx_43xx_interconnect_data.o
+obj-$(CONFIG_SOC_AM33XX)		+= omap_hwmod_33xx_43xx_ipblock_data.o
+obj-$(CONFIG_SOC_AM43XX)		+= omap_hwmod_43xx_data.o
+obj-$(CONFIG_SOC_AM43XX)		+= omap_hwmod_33xx_43xx_interconnect_data.o
+obj-$(CONFIG_SOC_AM43XX)		+= omap_hwmod_33xx_43xx_ipblock_data.o
 obj-$(CONFIG_ARCH_OMAP4)		+= omap_hwmod_44xx_data.o
 obj-$(CONFIG_SOC_OMAP5)			+= omap_hwmod_54xx_data.o
 obj-$(CONFIG_SOC_DRA7XX)		+= omap_hwmod_7xx_data.o
@@ -228,12 +235,8 @@
 # OMAP2420 MSDI controller integration support ("MMC")
 obj-$(CONFIG_SOC_OMAP2420)		+= msdi.o
 
-ifneq ($(CONFIG_DRM_OMAP),)
-obj-y					+= drm.o
-endif
-
 # Specific board support
-obj-$(CONFIG_MACH_OMAP_GENERIC)		+= board-generic.o
+obj-$(CONFIG_MACH_OMAP_GENERIC)		+= board-generic.o pdata-quirks.o
 obj-$(CONFIG_MACH_OMAP_H4)		+= board-h4.o
 obj-$(CONFIG_MACH_OMAP_2430SDP)		+= board-2430sdp.o
 obj-$(CONFIG_MACH_OMAP3_BEAGLE)		+= board-omap3beagle.o
@@ -242,26 +245,14 @@
 obj-$(CONFIG_MACH_OMAP3530_LV_SOM)      += board-omap3logic.o
 obj-$(CONFIG_MACH_OMAP3_TORPEDO)        += board-omap3logic.o
 obj-$(CONFIG_MACH_OVERO)		+= board-overo.o
-obj-$(CONFIG_MACH_OMAP3EVM)		+= board-omap3evm.o
 obj-$(CONFIG_MACH_OMAP3_PANDORA)	+= board-omap3pandora.o
 obj-$(CONFIG_MACH_OMAP_3430SDP)		+= board-3430sdp.o
 obj-$(CONFIG_MACH_NOKIA_N8X0)		+= board-n8x0.o
-obj-$(CONFIG_MACH_NOKIA_RM680)		+= board-rm680.o sdram-nokia.o
 obj-$(CONFIG_MACH_NOKIA_RX51)		+= board-rx51.o sdram-nokia.o
 obj-$(CONFIG_MACH_NOKIA_RX51)		+= board-rx51-peripherals.o
 obj-$(CONFIG_MACH_NOKIA_RX51)		+= board-rx51-video.o
-obj-$(CONFIG_MACH_OMAP_ZOOM2)		+= board-zoom.o board-zoom-peripherals.o
-obj-$(CONFIG_MACH_OMAP_ZOOM2)		+= board-zoom-display.o
-obj-$(CONFIG_MACH_OMAP_ZOOM2)		+= board-zoom-debugboard.o
-obj-$(CONFIG_MACH_OMAP_ZOOM3)		+= board-zoom.o board-zoom-peripherals.o
-obj-$(CONFIG_MACH_OMAP_ZOOM3)		+= board-zoom-display.o
-obj-$(CONFIG_MACH_OMAP_ZOOM3)		+= board-zoom-debugboard.o
-obj-$(CONFIG_MACH_OMAP_3630SDP)		+= board-3630sdp.o
-obj-$(CONFIG_MACH_OMAP_3630SDP)		+= board-zoom-peripherals.o
-obj-$(CONFIG_MACH_OMAP_3630SDP)		+= board-zoom-display.o
 obj-$(CONFIG_MACH_CM_T35)		+= board-cm-t35.o
 obj-$(CONFIG_MACH_CM_T3517)		+= board-cm-t3517.o
-obj-$(CONFIG_MACH_IGEP0020)		+= board-igep0020.o
 obj-$(CONFIG_MACH_TOUCHBOOK)		+= board-omap3touchbook.o
 
 obj-$(CONFIG_MACH_OMAP3517EVM)		+= board-am3517evm.o
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
deleted file mode 100644
index 20d6d81..0000000
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2009 Texas Instruments Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/input.h>
-#include <linux/gpio.h>
-#include <linux/mtd/nand.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#include "common.h"
-#include "gpmc-smc91x.h"
-
-#include "board-zoom.h"
-
-#include "board-flash.h"
-#include "mux.h"
-#include "sdram-hynix-h8mbx00u0mer-0em.h"
-
-#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
-
-static struct omap_smc91x_platform_data board_smc91x_data = {
-	.cs             = 3,
-	.flags          = GPMC_MUX_ADD_DATA | IORESOURCE_IRQ_LOWLEVEL,
-};
-
-static void __init board_smc91x_init(void)
-{
-	board_smc91x_data.gpio_irq = 158;
-	gpmc_smc91x_init(&board_smc91x_data);
-}
-
-#else
-
-static inline void board_smc91x_init(void)
-{
-}
-
-#endif /* defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE) */
-
-static void enable_board_wakeup_source(void)
-{
-	/* T2 interrupt line (keypad) */
-	omap_mux_init_signal("sys_nirq",
-		OMAP_WAKEUP_EN | OMAP_PIN_INPUT_PULLUP);
-}
-
-static struct usbhs_phy_data phy_data[] __initdata = {
-	{
-		.port = 1,
-		.reset_gpio = 126,
-		.vcc_gpio = -EINVAL,
-	},
-	{
-		.port = 2,
-		.reset_gpio = 61,
-		.vcc_gpio = -EINVAL,
-	},
-};
-
-static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
-
-	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
-	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
-};
-
-#ifdef CONFIG_OMAP_MUX
-static struct omap_board_mux board_mux[] __initdata = {
-	{ .reg_offset = OMAP_MUX_TERMINATOR },
-};
-#endif
-
-/*
- * SDP3630 CS organization
- * See also the Switch S8 settings in the comments.
- */
-static char chip_sel_sdp[][GPMC_CS_NUM] = {
-	{PDC_NOR, PDC_NAND, PDC_ONENAND, DBG_MPDB, 0, 0, 0, 0}, /* S8:1111 */
-	{PDC_ONENAND, PDC_NAND, PDC_NOR, DBG_MPDB, 0, 0, 0, 0}, /* S8:1110 */
-	{PDC_NAND, PDC_ONENAND, PDC_NOR, DBG_MPDB, 0, 0, 0, 0}, /* S8:1101 */
-};
-
-static struct mtd_partition sdp_nor_partitions[] = {
-	/* bootloader (U-Boot, etc) in first sector */
-	{
-		.name		= "Bootloader-NOR",
-		.offset		= 0,
-		.size		= SZ_256K,
-		.mask_flags	= MTD_WRITEABLE, /* force read-only */
-	},
-	/* bootloader params in the next sector */
-	{
-		.name		= "Params-NOR",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= SZ_256K,
-		.mask_flags	= 0,
-	},
-	/* kernel */
-	{
-		.name		= "Kernel-NOR",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= SZ_2M,
-		.mask_flags	= 0
-	},
-	/* file system */
-	{
-		.name		= "Filesystem-NOR",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= MTDPART_SIZ_FULL,
-		.mask_flags	= 0
-	}
-};
-
-static struct mtd_partition sdp_onenand_partitions[] = {
-	{
-		.name		= "X-Loader-OneNAND",
-		.offset		= 0,
-		.size		= 4 * (64 * 2048),
-		.mask_flags	= MTD_WRITEABLE  /* force read-only */
-	},
-	{
-		.name		= "U-Boot-OneNAND",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= 2 * (64 * 2048),
-		.mask_flags	= MTD_WRITEABLE  /* force read-only */
-	},
-	{
-		.name		= "U-Boot Environment-OneNAND",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= 1 * (64 * 2048),
-	},
-	{
-		.name		= "Kernel-OneNAND",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= 16 * (64 * 2048),
-	},
-	{
-		.name		= "File System-OneNAND",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= MTDPART_SIZ_FULL,
-	},
-};
-
-static struct mtd_partition sdp_nand_partitions[] = {
-	/* All the partition sizes are listed in terms of NAND block size */
-	{
-		.name		= "X-Loader-NAND",
-		.offset		= 0,
-		.size		= 4 * (64 * 2048),
-		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
-	},
-	{
-		.name		= "U-Boot-NAND",
-		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x80000 */
-		.size		= 10 * (64 * 2048),
-		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
-	},
-	{
-		.name		= "Boot Env-NAND",
-
-		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x1c0000 */
-		.size		= 6 * (64 * 2048),
-	},
-	{
-		.name		= "Kernel-NAND",
-		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x280000 */
-		.size		= 40 * (64 * 2048),
-	},
-	{
-		.name		= "File System - NAND",
-		.size		= MTDPART_SIZ_FULL,
-		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x780000 */
-	},
-};
-
-static struct flash_partitions sdp_flash_partitions[] = {
-	{
-		.parts = sdp_nor_partitions,
-		.nr_parts = ARRAY_SIZE(sdp_nor_partitions),
-	},
-	{
-		.parts = sdp_onenand_partitions,
-		.nr_parts = ARRAY_SIZE(sdp_onenand_partitions),
-	},
-	{
-		.parts = sdp_nand_partitions,
-		.nr_parts = ARRAY_SIZE(sdp_nand_partitions),
-	},
-};
-
-static void __init omap_sdp_init(void)
-{
-	omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
-	zoom_peripherals_init();
-	omap_sdrc_init(h8mbx00u0mer0em_sdrc_params,
-				  h8mbx00u0mer0em_sdrc_params);
-	zoom_display_init();
-	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_sdp, NAND_BUSWIDTH_16);
-	enable_board_wakeup_source();
-
-	usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
-	usbhs_init(&usbhs_bdata);
-}
-
-MACHINE_START(OMAP_3630SDP, "OMAP 3630SDP board")
-	.atag_offset	= 0x100,
-	.reserve	= omap_reserve,
-	.map_io		= omap3_map_io,
-	.init_early	= omap3630_init_early,
-	.init_irq	= omap3_init_irq,
-	.handle_irq	= omap3_intc_handle_irq,
-	.init_machine	= omap_sdp_init,
-	.init_late	= omap3630_init_late,
-	.init_time	= omap3_sync32k_timer_init,
-	.restart	= omap3xxx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 39c7838..19f1652 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -15,13 +15,10 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/irqdomain.h>
-#include <linux/clk.h>
 
 #include <asm/mach/arch.h>
 
 #include "common.h"
-#include "common-board-devices.h"
-#include "dss-common.h"
 
 #if !(defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3))
 #define intc_of_init	NULL
@@ -36,40 +33,9 @@
 	{ }
 };
 
-/*
- * Create alias for USB host PHY clock.
- * Remove this when clock phandle can be provided via DT
- */
-static void __init legacy_init_ehci_clk(char *clkname)
-{
-	int ret;
-
-	ret = clk_add_alias("main_clk", NULL, clkname, NULL);
-	if (ret) {
-		pr_err("%s:Failed to add main_clk alias to %s :%d\n",
-						__func__, clkname, ret);
-	}
-}
-
 static void __init omap_generic_init(void)
 {
-	omap_sdrc_init(NULL, NULL);
-
-	of_platform_populate(NULL, omap_dt_match_table, NULL, NULL);
-
-	/*
-	 * HACK: call display setup code for selected boards to enable omapdss.
-	 * This will be removed when omapdss supports DT.
-	 */
-	if (of_machine_is_compatible("ti,omap4-panda")) {
-		omap4_panda_display_init_of();
-		legacy_init_ehci_clk("auxclk3_ck");
-
-	}
-	else if (of_machine_is_compatible("ti,omap4-sdp"))
-		omap_4430sdp_display_init_of();
-	else if (of_machine_is_compatible("ti,omap5-uevm"))
-		legacy_init_ehci_clk("auxclk1_ck");
+	pdata_quirks_init(omap_dt_match_table);
 }
 
 #ifdef CONFIG_SOC_OMAP2420
@@ -129,6 +95,24 @@
 	.restart	= omap3xxx_restart,
 MACHINE_END
 
+static const char *omap36xx_boards_compat[] __initdata = {
+	"ti,omap36xx",
+	NULL,
+};
+
+DT_MACHINE_START(OMAP36XX_DT, "Generic OMAP36xx (Flattened Device Tree)")
+	.reserve	= omap_reserve,
+	.map_io		= omap3_map_io,
+	.init_early	= omap3630_init_early,
+	.init_irq	= omap_intc_of_init,
+	.handle_irq	= omap3_intc_handle_irq,
+	.init_machine	= omap_generic_init,
+	.init_late	= omap3_init_late,
+	.init_time	= omap3_sync32k_timer_init,
+	.dt_compat	= omap36xx_boards_compat,
+	.restart	= omap3xxx_restart,
+MACHINE_END
+
 static const char *omap3_gp_boards_compat[] __initdata = {
 	"ti,omap3-beagle",
 	"timll,omap3-devkit8000",
@@ -162,6 +146,7 @@
 	.init_irq	= omap_intc_of_init,
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= omap_generic_init,
+	.init_late	= am33xx_init_late,
 	.init_time	= omap3_gptimer_timer_init,
 	.dt_compat	= am33xx_boards_compat,
 	.restart	= am33xx_restart,
@@ -201,6 +186,7 @@
 	.init_early	= omap5_init_early,
 	.init_irq	= omap_gic_of_init,
 	.init_machine	= omap_generic_init,
+	.init_late	= omap5_init_late,
 	.init_time	= omap5_realtime_timer_init,
 	.dt_compat	= omap5_boards_compat,
 	.restart	= omap44xx_restart,
@@ -216,6 +202,7 @@
 DT_MACHINE_START(AM43_DT, "Generic AM43 (Flattened Device Tree)")
 	.map_io		= am33xx_map_io,
 	.init_early	= am43xx_init_early,
+	.init_late	= am43xx_init_late,
 	.init_irq	= omap_gic_of_init,
 	.init_machine	= omap_generic_init,
 	.init_time	= omap3_sync32k_timer_init,
@@ -234,6 +221,7 @@
 	.smp		= smp_ops(omap4_smp_ops),
 	.map_io		= omap5_map_io,
 	.init_early	= dra7xx_init_early,
+	.init_late	= dra7xx_init_late,
 	.init_irq	= omap_gic_of_init,
 	.init_machine	= omap_generic_init,
 	.init_time	= omap5_realtime_timer_init,
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
deleted file mode 100644
index 06dbb2d..0000000
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ /dev/null
@@ -1,718 +0,0 @@
-/*
- * Copyright (C) 2009 Integration Software and Electronic Engineering.
- *
- * 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/input.h>
-#include <linux/usb/phy.h>
-
-#include <linux/regulator/machine.h>
-#include <linux/regulator/fixed.h>
-#include <linux/i2c/twl.h>
-#include <linux/mmc/host.h>
-
-#include <linux/mtd/nand.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-#include <linux/platform_data/mtd-onenand-omap2.h>
-
-#include "common.h"
-#include "gpmc.h"
-#include "mux.h"
-#include "hsmmc.h"
-#include "sdram-numonyx-m65kxxxxam.h"
-#include "common-board-devices.h"
-#include "board-flash.h"
-#include "control.h"
-#include "gpmc-onenand.h"
-
-#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_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
-
-#define IGEP3_GPIO_LED0_GREEN	54
-#define IGEP3_GPIO_LED0_RED	53
-#define IGEP3_GPIO_LED1_RED	16
-#define IGEP3_GPIO_USBH_NRESET  183
-
-#define IGEP_SYSBOOT_MASK           0x1f
-#define IGEP_SYSBOOT_NAND           0x0f
-#define IGEP_SYSBOOT_ONENAND        0x10
-
-/*
- * 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
-#define IGEP3_BOARD_HWREV	2
-
-static u8 hwrev;
-
-static void __init igep2_get_revision(void)
-{
-	u8 ret;
-
-	if (machine_is_igep0030()) {
-		hwrev = IGEP3_BOARD_HWREV;
-		return;
-	}
-
-	omap_mux_init_gpio(IGEP2_GPIO_LED1_RED, OMAP_PIN_INPUT);
-
-	if (gpio_request_one(IGEP2_GPIO_LED1_RED, GPIOF_IN, "GPIO_HW0_REV")) {
-		pr_warning("IGEP2: Could not obtain gpio GPIO_HW0_REV\n");
-		pr_err("IGEP2: Unknown Hardware Revision\n");
-		return;
-	}
-
-	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;
-	}
-
-	gpio_free(IGEP2_GPIO_LED1_RED);
-}
-
-#if defined(CONFIG_MTD_ONENAND_OMAP2) ||		\
-	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE) ||	\
-	defined(CONFIG_MTD_NAND_OMAP2) ||		\
-	defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-
-#define ONENAND_MAP             0x20000000
-
-/* NAND04GR4E1A ( 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 igep_flash_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 inline u32 igep_get_sysboot_value(void)
-{
-	return omap_ctrl_readl(OMAP343X_CONTROL_STATUS) & IGEP_SYSBOOT_MASK;
-}
-
-static void __init igep_flash_init(void)
-{
-	u32 mux;
-	mux = igep_get_sysboot_value();
-
-	if (mux == IGEP_SYSBOOT_NAND) {
-		pr_info("IGEP: initializing NAND memory device\n");
-		board_nand_init(igep_flash_partitions,
-				ARRAY_SIZE(igep_flash_partitions),
-				0, NAND_BUSWIDTH_16, nand_default_timings);
-	} else if (mux == IGEP_SYSBOOT_ONENAND) {
-		pr_info("IGEP: initializing OneNAND memory device\n");
-		board_onenand_init(igep_flash_partitions,
-				   ARRAY_SIZE(igep_flash_partitions), 0);
-	} else {
-		pr_err("IGEP: Flash: unsupported sysboot sequence found\n");
-	}
-}
-
-#else
-static void __init igep_flash_init(void) {}
-#endif
-
-#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
-
-#include <linux/smsc911x.h>
-#include "gpmc-smsc911x.h"
-
-static struct omap_smsc911x_platform_data smsc911x_cfg = {
-	.cs             = IGEP2_SMSC911X_CS,
-	.gpio_irq       = IGEP2_SMSC911X_GPIO,
-	.gpio_reset     = -EINVAL,
-	.flags		= SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS,
-};
-
-static inline void __init igep2_init_smsc911x(void)
-{
-	gpmc_smsc911x_init(&smsc911x_cfg);
-}
-
-#else
-static inline void __init igep2_init_smsc911x(void) { }
-#endif
-
-static struct regulator_consumer_supply igep_vmmc1_supply[] = {
-	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
-};
-
-/* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
-static struct regulator_init_data igep_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  = ARRAY_SIZE(igep_vmmc1_supply),
-	.consumer_supplies      = igep_vmmc1_supply,
-};
-
-static struct regulator_consumer_supply igep_vio_supply[] = {
-	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.1"),
-};
-
-static struct regulator_init_data igep_vio = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.apply_uV		= 1,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
-					| REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies  = ARRAY_SIZE(igep_vio_supply),
-	.consumer_supplies      = igep_vio_supply,
-};
-
-static struct regulator_consumer_supply igep_vmmc2_supply[] = {
-	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
-};
-
-static struct regulator_init_data igep_vmmc2 = {
-	.constraints		= {
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL,
-		.always_on		= 1,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(igep_vmmc2_supply),
-	.consumer_supplies	= igep_vmmc2_supply,
-};
-
-static struct fixed_voltage_config igep_vwlan = {
-	.supply_name		= "vwlan",
-	.microvolts		= 3300000,
-	.gpio			= -EINVAL,
-	.enabled_at_boot	= 1,
-	.init_data		= &igep_vmmc2,
-};
-
-static struct platform_device igep_vwlan_device = {
-	.name		= "reg-fixed-voltage",
-	.id		= 0,
-	.dev = {
-		.platform_data	= &igep_vwlan,
-	},
-};
-
-static struct omap2_hsmmc_info mmc[] = {
-	{
-		.mmc		= 1,
-		.caps		= MMC_CAP_4_BIT_DATA,
-		.gpio_cd	= -EINVAL,
-		.gpio_wp	= -EINVAL,
-		.deferred	= true,
-	},
-#if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
-	{
-		.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 igep_gpio_leds[] = {
-	[0] = {
-		.name			= "omap3:red:user0",
-		.default_state		= 0,
-	},
-	[1] = {
-		.name			= "omap3:green:boot",
-		.default_state		= 1,
-	},
-	[2] = {
-		.name			= "omap3:red:user1",
-		.default_state		= 0,
-	},
-	[3] = {
-		.name			= "omap3:green:user1",
-		.default_state		= 0,
-		.gpio			= -EINVAL, /* gets replaced */
-		.active_low		= 1,
-	},
-};
-
-static struct gpio_led_platform_data igep_led_pdata = {
-	.leds           = igep_gpio_leds,
-	.num_leds       = ARRAY_SIZE(igep_gpio_leds),
-};
-
-static struct platform_device igep_led_device = {
-	 .name   = "leds-gpio",
-	 .id     = -1,
-	 .dev    = {
-		 .platform_data  =  &igep_led_pdata,
-	},
-};
-
-static void __init igep_leds_init(void)
-{
-	if (machine_is_igep0020()) {
-		igep_gpio_leds[0].gpio = IGEP2_GPIO_LED0_RED;
-		igep_gpio_leds[1].gpio = IGEP2_GPIO_LED0_GREEN;
-		igep_gpio_leds[2].gpio = IGEP2_GPIO_LED1_RED;
-	} else {
-		igep_gpio_leds[0].gpio = IGEP3_GPIO_LED0_RED;
-		igep_gpio_leds[1].gpio = IGEP3_GPIO_LED0_GREEN;
-		igep_gpio_leds[2].gpio = IGEP3_GPIO_LED1_RED;
-	}
-
-	platform_device_register(&igep_led_device);
-}
-
-#else
-static struct gpio igep_gpio_leds[] __initdata = {
-	{ -EINVAL,	GPIOF_OUT_INIT_LOW, "gpio-led:red:d0"   },
-	{ -EINVAL,	GPIOF_OUT_INIT_LOW, "gpio-led:green:d0" },
-	{ -EINVAL,	GPIOF_OUT_INIT_LOW, "gpio-led:red:d1"   },
-};
-
-static inline void igep_leds_init(void)
-{
-	int i;
-
-	if (machine_is_igep0020()) {
-		igep_gpio_leds[0].gpio = IGEP2_GPIO_LED0_RED;
-		igep_gpio_leds[1].gpio = IGEP2_GPIO_LED0_GREEN;
-		igep_gpio_leds[2].gpio = IGEP2_GPIO_LED1_RED;
-	} else {
-		igep_gpio_leds[0].gpio = IGEP3_GPIO_LED0_RED;
-		igep_gpio_leds[1].gpio = IGEP3_GPIO_LED0_GREEN;
-		igep_gpio_leds[2].gpio = IGEP3_GPIO_LED1_RED;
-	}
-
-	if (gpio_request_array(igep_gpio_leds, ARRAY_SIZE(igep_gpio_leds))) {
-		pr_warning("IGEP v2: Could not obtain leds gpios\n");
-		return;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(igep_gpio_leds); i++)
-		gpio_export(igep_gpio_leds[i].gpio, 0);
-}
-#endif
-
-static struct gpio igep2_twl_gpios[] = {
-	{ -EINVAL, GPIOF_IN,		"GPIO_EHCI_NOC"  },
-	{ -EINVAL, GPIOF_OUT_INIT_LOW,	"GPIO_USBH_CPEN" },
-};
-
-static int igep_twl_gpio_setup(struct device *dev,
-		unsigned gpio, unsigned ngpio)
-{
-	int ret;
-
-	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
-	mmc[0].gpio_cd = gpio + 0;
-	omap_hsmmc_late_init(mmc);
-
-	/* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
-#if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
-	ret = gpio_request_one(gpio + TWL4030_GPIO_MAX + 1, GPIOF_OUT_INIT_HIGH,
-			       "gpio-led:green:d1");
-	if (ret == 0)
-		gpio_export(gpio + TWL4030_GPIO_MAX + 1, 0);
-	else
-		pr_warning("IGEP: Could not obtain gpio GPIO_LED1_GREEN\n");
-#else
-	igep_gpio_leds[3].gpio = gpio + TWL4030_GPIO_MAX + 1;
-#endif
-
-	if (machine_is_igep0030())
-		return 0;
-
-	/*
-	 * REVISIT: need ehci-omap hooks for external VBUS
-	 * power switch and overcurrent detect
-	 */
-	igep2_twl_gpios[0].gpio = gpio + 1;
-
-	/* TWL4030_GPIO_MAX + 0 == ledA, GPIO_USBH_CPEN (out, active low) */
-	igep2_twl_gpios[1].gpio = gpio + TWL4030_GPIO_MAX;
-
-	ret = gpio_request_array(igep2_twl_gpios, ARRAY_SIZE(igep2_twl_gpios));
-	if (ret < 0)
-		pr_err("IGEP2: Could not obtain gpio for USBH_CPEN");
-
-	return 0;
-};
-
-static struct twl4030_gpio_platform_data igep_twl4030_gpio_pdata = {
-	.use_leds	= true,
-	.setup		= igep_twl_gpio_setup,
-};
-
-static struct connector_dvi_platform_data omap3stalker_dvi_connector_pdata = {
-	.name                   = "dvi",
-	.source                 = "tfp410.0",
-	.i2c_bus_num            = 3,
-};
-
-static struct platform_device omap3stalker_dvi_connector_device = {
-	.name                   = "connector-dvi",
-	.id                     = 0,
-	.dev.platform_data      = &omap3stalker_dvi_connector_pdata,
-};
-
-static struct encoder_tfp410_platform_data omap3stalker_tfp410_pdata = {
-	.name                   = "tfp410.0",
-	.source                 = "dpi.0",
-	.data_lines             = 24,
-	.power_down_gpio        = IGEP2_GPIO_DVI_PUP,
-};
-
-static struct platform_device omap3stalker_tfp410_device = {
-	.name                   = "tfp410",
-	.id                     = 0,
-	.dev.platform_data      = &omap3stalker_tfp410_pdata,
-};
-
-static struct omap_dss_board_info igep2_dss_data = {
-	.default_display_name = "dvi",
-};
-
-static struct platform_device *igep_devices[] __initdata = {
-	&igep_vwlan_device,
-	&omap3stalker_tfp410_device,
-	&omap3stalker_dvi_connector_device,
-};
-
-static int igep2_keymap[] = {
-	KEY(0, 0, KEY_LEFT),
-	KEY(0, 1, KEY_RIGHT),
-	KEY(0, 2, KEY_A),
-	KEY(0, 3, KEY_B),
-	KEY(1, 0, KEY_DOWN),
-	KEY(1, 1, KEY_UP),
-	KEY(1, 2, KEY_E),
-	KEY(1, 3, KEY_F),
-	KEY(2, 0, KEY_ENTER),
-	KEY(2, 1, KEY_I),
-	KEY(2, 2, KEY_J),
-	KEY(2, 3, KEY_K),
-	KEY(3, 0, KEY_M),
-	KEY(3, 1, KEY_N),
-	KEY(3, 2, KEY_O),
-	KEY(3, 3, KEY_P)
-};
-
-static struct matrix_keymap_data igep2_keymap_data = {
-	.keymap			= igep2_keymap,
-	.keymap_size		= ARRAY_SIZE(igep2_keymap),
-};
-
-static struct twl4030_keypad_data igep2_keypad_pdata = {
-	.keymap_data	= &igep2_keymap_data,
-	.rows		= 4,
-	.cols		= 4,
-	.rep		= 1,
-};
-
-static struct twl4030_platform_data igep_twldata = {
-	/* platform_data for children goes here */
-	.gpio		= &igep_twl4030_gpio_pdata,
-	.vmmc1          = &igep_vmmc1,
-	.vio		= &igep_vio,
-};
-
-static struct i2c_board_info __initdata igep2_i2c3_boardinfo[] = {
-	{
-		I2C_BOARD_INFO("eeprom", 0x50),
-	},
-};
-
-static void __init igep_i2c_init(void)
-{
-	int ret;
-
-	omap3_pmic_get_config(&igep_twldata, TWL_COMMON_PDATA_USB,
-			      TWL_COMMON_REGULATOR_VPLL2);
-	igep_twldata.vpll2->constraints.apply_uV = true;
-	igep_twldata.vpll2->constraints.name = "VDVI";
-
-	if (machine_is_igep0020()) {
-		/*
-		 * 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);
-
-		igep_twldata.keypad	= &igep2_keypad_pdata;
-		/* Get common pmic data */
-		omap3_pmic_get_config(&igep_twldata, TWL_COMMON_PDATA_AUDIO, 0);
-	}
-
-	omap3_pmic_init("twl4030", &igep_twldata);
-}
-
-static struct usbhs_phy_data igep2_phy_data[] __initdata = {
-	{
-		.port = 1,
-		.reset_gpio = IGEP2_GPIO_USBH_NRESET,
-		.vcc_gpio = -EINVAL,
-	},
-};
-
-static struct usbhs_phy_data igep3_phy_data[] __initdata = {
-	{
-		.port = 2,
-		.reset_gpio = IGEP3_GPIO_USBH_NRESET,
-		.vcc_gpio = -EINVAL,
-	},
-};
-
-static struct usbhs_omap_platform_data igep2_usbhs_bdata __initdata = {
-	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
-};
-
-static struct usbhs_omap_platform_data igep3_usbhs_bdata __initdata = {
-	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
-};
-
-#ifdef CONFIG_OMAP_MUX
-static struct omap_board_mux board_mux[] __initdata = {
-	/* Display Sub System */
-	OMAP3_MUX(DSS_PCLK, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_HSYNC, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_VSYNC, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_ACBIAS, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA0, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA1, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA2, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA3, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA4, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA5, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA6, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA7, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA8, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA9, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA10, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA11, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA12, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA13, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA14, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA15, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA16, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA17, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA18, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA19, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA20, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA21, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA22, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	OMAP3_MUX(DSS_DATA23, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
-	/* TFP410 PanelBus DVI Transmitte (GPIO_170) */
-	OMAP3_MUX(HDQ_SIO, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
-	/* SMSC9221 LAN Controller ETH IRQ (GPIO_176) */
-	OMAP3_MUX(MCSPI1_CS2, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
-	{ .reg_offset = OMAP_MUX_TERMINATOR },
-};
-#endif
-
-#if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
-static struct gpio igep_wlan_bt_gpios[] __initdata = {
-	{ -EINVAL, GPIOF_OUT_INIT_HIGH, "GPIO_WIFI_NPD"	   },
-	{ -EINVAL, GPIOF_OUT_INIT_HIGH, "GPIO_WIFI_NRESET" },
-	{ -EINVAL, GPIOF_OUT_INIT_HIGH, "GPIO_BT_NRESET"   },
-};
-
-static void __init igep_wlan_bt_init(void)
-{
-	int err;
-
-	/* GPIO's for WLAN-BT combo depends on hardware revision */
-	if (hwrev == IGEP2_BOARD_HWREV_B) {
-		igep_wlan_bt_gpios[0].gpio = IGEP2_RB_GPIO_WIFI_NPD;
-		igep_wlan_bt_gpios[1].gpio = IGEP2_RB_GPIO_WIFI_NRESET;
-		igep_wlan_bt_gpios[2].gpio = IGEP2_RB_GPIO_BT_NRESET;
-	} else if (hwrev == IGEP2_BOARD_HWREV_C || machine_is_igep0030()) {
-		igep_wlan_bt_gpios[0].gpio = IGEP2_RC_GPIO_WIFI_NPD;
-		igep_wlan_bt_gpios[1].gpio = IGEP2_RC_GPIO_WIFI_NRESET;
-		igep_wlan_bt_gpios[2].gpio = IGEP2_RC_GPIO_BT_NRESET;
-	} else
-		return;
-
-	/* Make sure that the GPIO pins are muxed correctly */
-	omap_mux_init_gpio(igep_wlan_bt_gpios[0].gpio, OMAP_PIN_OUTPUT);
-	omap_mux_init_gpio(igep_wlan_bt_gpios[1].gpio, OMAP_PIN_OUTPUT);
-	omap_mux_init_gpio(igep_wlan_bt_gpios[2].gpio, OMAP_PIN_OUTPUT);
-
-	err = gpio_request_array(igep_wlan_bt_gpios,
-				 ARRAY_SIZE(igep_wlan_bt_gpios));
-	if (err) {
-		pr_warning("IGEP2: Could not obtain WIFI/BT gpios\n");
-		return;
-	}
-
-	gpio_export(igep_wlan_bt_gpios[0].gpio, 0);
-	gpio_export(igep_wlan_bt_gpios[1].gpio, 0);
-	gpio_export(igep_wlan_bt_gpios[2].gpio, 0);
-
-	gpio_set_value(igep_wlan_bt_gpios[1].gpio, 0);
-	udelay(10);
-	gpio_set_value(igep_wlan_bt_gpios[1].gpio, 1);
-
-}
-#else
-static inline void __init igep_wlan_bt_init(void) { }
-#endif
-
-static struct regulator_consumer_supply dummy_supplies[] = {
-	REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
-	REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
-};
-
-static void __init igep_init(void)
-{
-	regulator_register_fixed(1, dummy_supplies, ARRAY_SIZE(dummy_supplies));
-	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
-
-	/* Get IGEP2 hardware revision */
-	igep2_get_revision();
-
-	omap_hsmmc_init(mmc);
-
-	/* Register I2C busses and drivers */
-	igep_i2c_init();
-	platform_add_devices(igep_devices, ARRAY_SIZE(igep_devices));
-	omap_serial_init();
-	omap_sdrc_init(m65kxxxxam_sdrc_params,
-				  m65kxxxxam_sdrc_params);
-	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
-	usb_musb_init(NULL);
-
-	igep_flash_init();
-	igep_leds_init();
-	omap_twl4030_audio_init("igep2", NULL);
-
-	/*
-	 * WLAN-BT combo module from MuRata which has a Marvell WLAN
-	 * (88W8686) + CSR Bluetooth chipset. Uses SDIO interface.
-	 */
-	igep_wlan_bt_init();
-
-	if (machine_is_igep0020()) {
-		omap_display_init(&igep2_dss_data);
-		igep2_init_smsc911x();
-		usbhs_init_phys(igep2_phy_data, ARRAY_SIZE(igep2_phy_data));
-		usbhs_init(&igep2_usbhs_bdata);
-	} else {
-		usbhs_init_phys(igep3_phy_data, ARRAY_SIZE(igep3_phy_data));
-		usbhs_init(&igep3_usbhs_bdata);
-	}
-}
-
-MACHINE_START(IGEP0020, "IGEP v2 board")
-	.atag_offset	= 0x100,
-	.reserve	= omap_reserve,
-	.map_io		= omap3_map_io,
-	.init_early	= omap35xx_init_early,
-	.init_irq	= omap3_init_irq,
-	.handle_irq	= omap3_intc_handle_irq,
-	.init_machine	= igep_init,
-	.init_late	= omap35xx_init_late,
-	.init_time	= omap3_sync32k_timer_init,
-	.restart	= omap3xxx_restart,
-MACHINE_END
-
-MACHINE_START(IGEP0030, "IGEP OMAP3 module")
-	.atag_offset	= 0x100,
-	.reserve	= omap_reserve,
-	.map_io		= omap3_map_io,
-	.init_early	= omap35xx_init_early,
-	.init_irq	= omap3_init_irq,
-	.handle_irq	= omap3_intc_handle_irq,
-	.init_machine	= igep_init,
-	.init_late	= omap35xx_init_late,
-	.init_time	= omap3_sync32k_timer_init,
-	.restart	= omap3xxx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index dd8da2c..4ec8d82 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -36,7 +36,6 @@
 #include <asm/mach/map.h>
 
 #include "common.h"
-#include "board-zoom.h"
 #include "gpmc.h"
 #include "gpmc-smsc911x.h"
 
@@ -406,7 +405,7 @@
 	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
 	usb_musb_init(NULL);
 	board_nand_init(ldp_nand_partitions, ARRAY_SIZE(ldp_nand_partitions),
-			ZOOM_NAND_CS, 0, nand_default_timings);
+			0, 0, nand_default_timings);
 
 	omap_hsmmc_init(mmc);
 	ldp_display_init();
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index f269184..8b9cd06 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -289,18 +289,12 @@
 
 static struct gpio_led gpio_leds[];
 
-/* PHY's VCC regulator might be added later, so flag that we need it */
-static struct usb_phy_gen_xceiv_platform_data hsusb2_phy_data = {
-	.needs_vcc = true,
-};
-
 static struct usbhs_phy_data phy_data[] = {
 	{
 		.port = 2,
 		.reset_gpio = 147,
 		.vcc_gpio = -1,		/* updated in beagle_twl_gpio_setup */
 		.vcc_polarity = 1,	/* updated in beagle_twl_gpio_setup */
-		.platform_data = &hsusb2_phy_data,
 	},
 };
 
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
deleted file mode 100644
index 1814387..0000000
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ /dev/null
@@ -1,756 +0,0 @@
-/*
- * linux/arch/arm/mach-omap2/board-omap3evm.c
- *
- * Copyright (C) 2008 Texas Instruments
- *
- * Modified from mach-omap2/board-3430sdp.c
- *
- * Initial code: Syed Mohammed Khasim
- *
- * This program is free software; you can redistribute it 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/gpio.h>
-#include <linux/input.h>
-#include <linux/input/matrix_keypad.h>
-#include <linux/leds.h>
-#include <linux/interrupt.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/nand.h>
-
-#include <linux/spi/spi.h>
-#include <linux/spi/ads7846.h>
-#include <linux/i2c/twl.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/musb.h>
-#include <linux/usb/usb_phy_gen_xceiv.h>
-#include <linux/smsc911x.h>
-
-#include <linux/wl12xx.h>
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/machine.h>
-#include <linux/mmc/host.h>
-#include <linux/export.h>
-#include <linux/usb/phy.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include <linux/platform_data/mtd-nand-omap2.h>
-#include "common.h"
-#include <linux/platform_data/spi-omap2-mcspi.h>
-#include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-
-#include "soc.h"
-#include "mux.h"
-#include "sdram-micron-mt46h32m32lf-6.h"
-#include "hsmmc.h"
-#include "common-board-devices.h"
-#include "board-flash.h"
-
-#define	NAND_CS			0
-
-#define OMAP3_EVM_TS_GPIO	175
-#define OMAP3_EVM_EHCI_VBUS	22
-#define OMAP3_EVM_EHCI_SELECT	61
-
-#define OMAP3EVM_ETHR_START	0x2c000000
-#define OMAP3EVM_ETHR_SIZE	1024
-#define OMAP3EVM_ETHR_ID_REV	0x50
-#define OMAP3EVM_ETHR_GPIO_IRQ	176
-#define OMAP3EVM_SMSC911X_CS	5
-/*
- * Eth Reset signal
- *	64 = Generation 1 (<=RevD)
- *	7 = Generation 2 (>=RevE)
- */
-#define OMAP3EVM_GEN1_ETHR_GPIO_RST	64
-#define OMAP3EVM_GEN2_ETHR_GPIO_RST	7
-
-/*
- * OMAP35x EVM revision
- * Run time detection of EVM revision is done by reading Ethernet
- * PHY ID -
- *	GEN_1	= 0x01150000
- *	GEN_2	= 0x92200000
- */
-enum {
-	OMAP3EVM_BOARD_GEN_1 = 0,	/* EVM Rev between  A - D */
-	OMAP3EVM_BOARD_GEN_2,		/* EVM Rev >= Rev E */
-};
-
-static u8 omap3_evm_version;
-
-static u8 get_omap3_evm_rev(void)
-{
-	return omap3_evm_version;
-}
-
-static void __init omap3_evm_get_revision(void)
-{
-	void __iomem *ioaddr;
-	unsigned int smsc_id;
-
-	/* Ethernet PHY ID is stored at ID_REV register */
-	ioaddr = ioremap_nocache(OMAP3EVM_ETHR_START, SZ_1K);
-	if (!ioaddr)
-		return;
-	smsc_id = readl(ioaddr + OMAP3EVM_ETHR_ID_REV) & 0xFFFF0000;
-	iounmap(ioaddr);
-
-	switch (smsc_id) {
-	/*SMSC9115 chipset*/
-	case 0x01150000:
-		omap3_evm_version = OMAP3EVM_BOARD_GEN_1;
-		break;
-	/*SMSC 9220 chipset*/
-	case 0x92200000:
-	default:
-		omap3_evm_version = OMAP3EVM_BOARD_GEN_2;
-	}
-}
-
-#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
-#include "gpmc-smsc911x.h"
-
-static struct omap_smsc911x_platform_data smsc911x_cfg = {
-	.cs             = OMAP3EVM_SMSC911X_CS,
-	.gpio_irq       = OMAP3EVM_ETHR_GPIO_IRQ,
-	.gpio_reset     = -EINVAL,
-	.flags		= SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS,
-};
-
-static inline void __init omap3evm_init_smsc911x(void)
-{
-	/* Configure ethernet controller reset gpio */
-	if (cpu_is_omap3430()) {
-		if (get_omap3_evm_rev() == OMAP3EVM_BOARD_GEN_1)
-			smsc911x_cfg.gpio_reset = OMAP3EVM_GEN1_ETHR_GPIO_RST;
-		else
-			smsc911x_cfg.gpio_reset = OMAP3EVM_GEN2_ETHR_GPIO_RST;
-	}
-
-	gpmc_smsc911x_init(&smsc911x_cfg);
-}
-
-#else
-static inline void __init omap3evm_init_smsc911x(void) { return; }
-#endif
-
-/*
- * OMAP3EVM LCD Panel control signals
- */
-#define OMAP3EVM_LCD_PANEL_LR		2
-#define OMAP3EVM_LCD_PANEL_UD		3
-#define OMAP3EVM_LCD_PANEL_INI		152
-#define OMAP3EVM_LCD_PANEL_QVGA		154
-#define OMAP3EVM_LCD_PANEL_RESB		155
-
-#define OMAP3EVM_LCD_PANEL_ENVDD	153
-#define OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO	210
-
-/*
- * OMAP3EVM DVI control signals
- */
-#define OMAP3EVM_DVI_PANEL_EN_GPIO	199
-
-#ifdef CONFIG_BROKEN
-static void __init omap3_evm_display_init(void)
-{
-	int r;
-
-	r = gpio_request_one(OMAP3EVM_LCD_PANEL_ENVDD, GPIOF_OUT_INIT_LOW,
-				"lcd_panel_envdd");
-	if (r)
-		pr_err("failed to get lcd_panel_envdd GPIO\n");
-
-	r = gpio_request_one(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO,
-				GPIOF_OUT_INIT_LOW, "lcd_panel_bklight");
-	if (r)
-		pr_err("failed to get lcd_panel_bklight GPIO\n");
-
-	if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2)
-		gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0);
-	else
-		gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1);
-}
-#endif
-
-static struct panel_sharp_ls037v7dw01_platform_data omap3_evm_lcd_pdata = {
-	.name                   = "lcd",
-	.source                 = "dpi.0",
-
-	.data_lines		= 18,
-
-	.resb_gpio		= OMAP3EVM_LCD_PANEL_RESB,
-	.ini_gpio		= OMAP3EVM_LCD_PANEL_INI,
-	.mo_gpio		= OMAP3EVM_LCD_PANEL_QVGA,
-	.lr_gpio		= OMAP3EVM_LCD_PANEL_LR,
-	.ud_gpio		= OMAP3EVM_LCD_PANEL_UD,
-};
-
-static struct platform_device omap3_evm_lcd_device = {
-	.name                   = "panel-sharp-ls037v7dw01",
-	.id                     = 0,
-	.dev.platform_data      = &omap3_evm_lcd_pdata,
-};
-
-static struct connector_dvi_platform_data omap3_evm_dvi_connector_pdata = {
-	.name                   = "dvi",
-	.source                 = "tfp410.0",
-	.i2c_bus_num            = -1,
-};
-
-static struct platform_device omap3_evm_dvi_connector_device = {
-	.name                   = "connector-dvi",
-	.id                     = 0,
-	.dev.platform_data      = &omap3_evm_dvi_connector_pdata,
-};
-
-static struct encoder_tfp410_platform_data omap3_evm_tfp410_pdata = {
-	.name                   = "tfp410.0",
-	.source                 = "dpi.0",
-	.data_lines             = 24,
-	.power_down_gpio        = OMAP3EVM_DVI_PANEL_EN_GPIO,
-};
-
-static struct platform_device omap3_evm_tfp410_device = {
-	.name                   = "tfp410",
-	.id                     = 0,
-	.dev.platform_data      = &omap3_evm_tfp410_pdata,
-};
-
-static struct connector_atv_platform_data omap3_evm_tv_pdata = {
-	.name = "tv",
-	.source = "venc.0",
-	.connector_type = OMAP_DSS_VENC_TYPE_SVIDEO,
-	.invert_polarity = false,
-};
-
-static struct platform_device omap3_evm_tv_connector_device = {
-	.name                   = "connector-analog-tv",
-	.id                     = 0,
-	.dev.platform_data      = &omap3_evm_tv_pdata,
-};
-
-static struct omap_dss_board_info omap3_evm_dss_data = {
-	.default_display_name = "lcd",
-};
-
-static struct regulator_consumer_supply omap3evm_vmmc1_supply[] = {
-	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
-};
-
-static struct regulator_consumer_supply omap3evm_vsim_supply[] = {
-	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
-};
-
-/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
-static struct regulator_init_data omap3evm_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	= ARRAY_SIZE(omap3evm_vmmc1_supply),
-	.consumer_supplies	= omap3evm_vmmc1_supply,
-};
-
-/* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
-static struct regulator_init_data omap3evm_vsim = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 3000000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
-					| REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(omap3evm_vsim_supply),
-	.consumer_supplies	= omap3evm_vsim_supply,
-};
-
-static struct omap2_hsmmc_info mmc[] = {
-	{
-		.mmc		= 1,
-		.caps		= MMC_CAP_4_BIT_DATA,
-		.gpio_cd	= -EINVAL,
-		.gpio_wp	= 63,
-		.deferred	= true,
-	},
-#ifdef CONFIG_WILINK_PLATFORM_DATA
-	{
-		.name		= "wl1271",
-		.mmc		= 2,
-		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
-		.gpio_wp	= -EINVAL,
-		.gpio_cd	= -EINVAL,
-		.nonremovable	= true,
-	},
-#endif
-	{}	/* Terminator */
-};
-
-static struct gpio_led gpio_leds[] = {
-	{
-		.name			= "omap3evm::ledb",
-		/* normally not visible (board underside) */
-		.default_trigger	= "default-on",
-		.gpio			= -EINVAL,	/* gets replaced */
-		.active_low		= true,
-	},
-};
-
-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 int omap3evm_twl_gpio_setup(struct device *dev,
-		unsigned gpio, unsigned ngpio)
-{
-	int r, lcd_bl_en;
-
-	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
-	mmc[0].gpio_cd = gpio + 0;
-	omap_hsmmc_late_init(mmc);
-
-	/*
-	 * Most GPIOs are for USB OTG.  Some are mostly sent to
-	 * the P2 connector; notably LEDA for the LCD backlight.
-	 */
-
-	/* TWL4030_GPIO_MAX + 0 == ledA, LCD Backlight control */
-	lcd_bl_en = get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2 ?
-		GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
-	r = gpio_request_one(gpio + TWL4030_GPIO_MAX, lcd_bl_en, "EN_LCD_BKL");
-	if (r)
-		printk(KERN_ERR "failed to get/set lcd_bkl gpio\n");
-
-	/* gpio + 7 == DVI Enable */
-	gpio_request_one(gpio + 7, GPIOF_OUT_INIT_LOW, "EN_DVI");
-
-	/* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
-	gpio_leds[0].gpio = gpio + TWL4030_GPIO_MAX + 1;
-
-	platform_device_register(&leds_gpio);
-
-	/* Enable VBUS switch by setting TWL4030.GPIO2DIR as output
-	 * for starting USB tranceiver
-	 */
-#ifdef CONFIG_TWL4030_CORE
-	if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2) {
-		u8 val;
-
-		twl_i2c_read_u8(TWL4030_MODULE_GPIO, &val, REG_GPIODATADIR1);
-		val |= 0x04; /* TWL4030.GPIO2DIR BIT at GPIODATADIR1(0x9B) */
-		twl_i2c_write_u8(TWL4030_MODULE_GPIO, val, REG_GPIODATADIR1);
-	}
-#endif
-
-	return 0;
-}
-
-static struct twl4030_gpio_platform_data omap3evm_gpio_data = {
-	.use_leds	= true,
-	.setup		= omap3evm_twl_gpio_setup,
-};
-
-static uint32_t board_keymap[] = {
-	KEY(0, 0, KEY_LEFT),
-	KEY(0, 1, KEY_DOWN),
-	KEY(0, 2, KEY_ENTER),
-	KEY(0, 3, KEY_M),
-
-	KEY(1, 0, KEY_RIGHT),
-	KEY(1, 1, KEY_UP),
-	KEY(1, 2, KEY_I),
-	KEY(1, 3, KEY_N),
-
-	KEY(2, 0, KEY_A),
-	KEY(2, 1, KEY_E),
-	KEY(2, 2, KEY_J),
-	KEY(2, 3, KEY_O),
-
-	KEY(3, 0, KEY_B),
-	KEY(3, 1, KEY_F),
-	KEY(3, 2, KEY_K),
-	KEY(3, 3, KEY_P)
-};
-
-static struct matrix_keymap_data board_map_data = {
-	.keymap			= board_keymap,
-	.keymap_size		= ARRAY_SIZE(board_keymap),
-};
-
-static struct twl4030_keypad_data omap3evm_kp_data = {
-	.keymap_data	= &board_map_data,
-	.rows		= 4,
-	.cols		= 4,
-	.rep		= 1,
-};
-
-/* ads7846 on SPI */
-static struct regulator_consumer_supply omap3evm_vio_supply[] = {
-	REGULATOR_SUPPLY("vcc", "spi1.0"),
-};
-
-/* VIO for ads7846 */
-static struct regulator_init_data omap3evm_vio = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(omap3evm_vio_supply),
-	.consumer_supplies	= omap3evm_vio_supply,
-};
-
-#ifdef CONFIG_WILINK_PLATFORM_DATA
-
-#define OMAP3EVM_WLAN_PMENA_GPIO	(150)
-#define OMAP3EVM_WLAN_IRQ_GPIO		(149)
-
-static struct regulator_consumer_supply omap3evm_vmmc2_supply[] = {
-	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
-};
-
-/* VMMC2 for driving the WL12xx module */
-static struct regulator_init_data omap3evm_vmmc2 = {
-	.constraints = {
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(omap3evm_vmmc2_supply),
-	.consumer_supplies	= omap3evm_vmmc2_supply,
-};
-
-static struct fixed_voltage_config omap3evm_vwlan = {
-	.supply_name		= "vwl1271",
-	.microvolts		= 1800000, /* 1.80V */
-	.gpio			= OMAP3EVM_WLAN_PMENA_GPIO,
-	.startup_delay		= 70000, /* 70ms */
-	.enable_high		= 1,
-	.enabled_at_boot	= 0,
-	.init_data		= &omap3evm_vmmc2,
-};
-
-static struct platform_device omap3evm_wlan_regulator = {
-	.name		= "reg-fixed-voltage",
-	.id		= 1,
-	.dev = {
-		.platform_data	= &omap3evm_vwlan,
-	},
-};
-
-struct wl12xx_platform_data omap3evm_wlan_data __initdata = {
-	.board_ref_clock = WL12XX_REFCLOCK_38, /* 38.4 MHz */
-};
-#endif
-
-/* VAUX2 for USB */
-static struct regulator_consumer_supply omap3evm_vaux2_supplies[] = {
-	REGULATOR_SUPPLY("VDD_CSIPHY1", "omap3isp"),	/* OMAP ISP */
-	REGULATOR_SUPPLY("VDD_CSIPHY2", "omap3isp"),	/* OMAP ISP */
-	REGULATOR_SUPPLY("vcc", "usb_phy_gen_xceiv.2"),	/* hsusb port 2 */
-	REGULATOR_SUPPLY("vaux2", NULL),
-};
-
-static struct regulator_init_data omap3evm_vaux2 = {
-	.constraints = {
-		.min_uV		= 2800000,
-		.max_uV		= 2800000,
-		.apply_uV	= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies		= ARRAY_SIZE(omap3evm_vaux2_supplies),
-	.consumer_supplies		= omap3evm_vaux2_supplies,
-};
-
-static struct twl4030_platform_data omap3evm_twldata = {
-	/* platform_data for children goes here */
-	.keypad		= &omap3evm_kp_data,
-	.gpio		= &omap3evm_gpio_data,
-	.vio		= &omap3evm_vio,
-	.vmmc1		= &omap3evm_vmmc1,
-	.vsim		= &omap3evm_vsim,
-};
-
-static int __init omap3_evm_i2c_init(void)
-{
-	omap3_pmic_get_config(&omap3evm_twldata,
-			TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_MADC |
-			TWL_COMMON_PDATA_AUDIO,
-			TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
-
-	omap3evm_twldata.vdac->constraints.apply_uV = true;
-	omap3evm_twldata.vpll2->constraints.apply_uV = true;
-
-	omap3_pmic_init("twl4030", &omap3evm_twldata);
-	omap_register_i2c_bus(2, 400, NULL, 0);
-	omap_register_i2c_bus(3, 400, NULL, 0);
-	return 0;
-}
-
-static struct usbhs_phy_data phy_data[] __initdata = {
-	{
-		.port = 2,
-		.reset_gpio = -1,	/* set at runtime */
-		.vcc_gpio = -EINVAL,
-	},
-};
-
-static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
-	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
-};
-
-#ifdef CONFIG_OMAP_MUX
-static struct omap_board_mux omap35x_board_mux[] __initdata = {
-	OMAP3_MUX(SYS_NIRQ, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP |
-				OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW |
-				OMAP_PIN_OFF_WAKEUPENABLE),
-	OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
-				OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW |
-				OMAP_PIN_OFF_WAKEUPENABLE),
-	OMAP3_MUX(SYS_BOOT5, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
-				OMAP_PIN_OFF_NONE),
-	OMAP3_MUX(GPMC_WAIT2, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
-				OMAP_PIN_OFF_NONE),
-#ifdef CONFIG_WILINK_PLATFORM_DATA
-	/* WLAN IRQ - GPIO 149 */
-	OMAP3_MUX(UART1_RTS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
-
-	/* WLAN POWER ENABLE - GPIO 150 */
-	OMAP3_MUX(UART1_CTS, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
-
-	/* MMC2 SDIO pin muxes for WL12xx */
-	OMAP3_MUX(SDMMC2_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
-	OMAP3_MUX(SDMMC2_CMD, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
-	OMAP3_MUX(SDMMC2_DAT0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
-	OMAP3_MUX(SDMMC2_DAT1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
-	OMAP3_MUX(SDMMC2_DAT2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
-	OMAP3_MUX(SDMMC2_DAT3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
-#endif
-	{ .reg_offset = OMAP_MUX_TERMINATOR },
-};
-
-static struct omap_board_mux omap36x_board_mux[] __initdata = {
-	OMAP3_MUX(SYS_NIRQ, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP |
-				OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW |
-				OMAP_PIN_OFF_WAKEUPENABLE),
-	OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
-				OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW |
-				OMAP_PIN_OFF_WAKEUPENABLE),
-	/* AM/DM37x EVM: DSS data bus muxed with sys_boot */
-	OMAP3_MUX(DSS_DATA18, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
-	OMAP3_MUX(DSS_DATA19, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
-	OMAP3_MUX(DSS_DATA22, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
-	OMAP3_MUX(DSS_DATA21, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
-	OMAP3_MUX(DSS_DATA22, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
-	OMAP3_MUX(DSS_DATA23, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
-	OMAP3_MUX(SYS_BOOT0, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
-	OMAP3_MUX(SYS_BOOT1, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
-	OMAP3_MUX(SYS_BOOT3, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
-	OMAP3_MUX(SYS_BOOT4, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
-	OMAP3_MUX(SYS_BOOT5, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
-	OMAP3_MUX(SYS_BOOT6, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
-#ifdef CONFIG_WILINK_PLATFORM_DATA
-	/* WLAN IRQ - GPIO 149 */
-	OMAP3_MUX(UART1_RTS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
-
-	/* WLAN POWER ENABLE - GPIO 150 */
-	OMAP3_MUX(UART1_CTS, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
-
-	/* MMC2 SDIO pin muxes for WL12xx */
-	OMAP3_MUX(SDMMC2_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
-	OMAP3_MUX(SDMMC2_CMD, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
-	OMAP3_MUX(SDMMC2_DAT0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
-	OMAP3_MUX(SDMMC2_DAT1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
-	OMAP3_MUX(SDMMC2_DAT2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
-	OMAP3_MUX(SDMMC2_DAT3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
-#endif
-
-	{ .reg_offset = OMAP_MUX_TERMINATOR },
-};
-#else
-#define omap35x_board_mux	NULL
-#define omap36x_board_mux	NULL
-#endif
-
-static struct omap_musb_board_data musb_board_data = {
-	.interface_type		= MUSB_INTERFACE_ULPI,
-	.mode			= MUSB_OTG,
-	.power			= 100,
-};
-
-static struct gpio omap3_evm_ehci_gpios[] __initdata = {
-	{ OMAP3_EVM_EHCI_VBUS,	 GPIOF_OUT_INIT_HIGH,  "enable EHCI VBUS" },
-	{ OMAP3_EVM_EHCI_SELECT, GPIOF_OUT_INIT_LOW,   "select EHCI port" },
-};
-
-static void __init omap3_evm_wl12xx_init(void)
-{
-#ifdef CONFIG_WILINK_PLATFORM_DATA
-	int ret;
-
-	/* WL12xx WLAN Init */
-	omap3evm_wlan_data.irq = gpio_to_irq(OMAP3EVM_WLAN_IRQ_GPIO);
-	ret = wl12xx_set_platform_data(&omap3evm_wlan_data);
-	if (ret)
-		pr_err("error setting wl12xx data: %d\n", ret);
-	ret = platform_device_register(&omap3evm_wlan_regulator);
-	if (ret)
-		pr_err("error registering wl12xx device: %d\n", ret);
-#endif
-}
-
-static struct regulator_consumer_supply dummy_supplies[] = {
-	REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
-	REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
-};
-
-static struct mtd_partition omap3evm_nand_partitions[] = {
-	/* All the partition sizes are listed in terms of NAND block size */
-	{
-		.name           = "X-Loader",
-		.offset         = 0,
-		.size           = 4*(SZ_128K),
-		.mask_flags     = MTD_WRITEABLE
-	},
-	{
-		.name           = "U-Boot",
-		.offset         = MTDPART_OFS_APPEND,
-		.size           = 14*(SZ_128K),
-		.mask_flags     = MTD_WRITEABLE
-	},
-	{
-		.name           = "U-Boot Env",
-		.offset         = MTDPART_OFS_APPEND,
-		.size           = 2*(SZ_128K)
-	},
-	{
-		.name           = "Kernel",
-		.offset         = MTDPART_OFS_APPEND,
-		.size           = 40*(SZ_128K)
-	},
-	{
-		.name           = "File system",
-		.size           = MTDPART_SIZ_FULL,
-		.offset         = MTDPART_OFS_APPEND,
-	},
-};
-
-static void __init omap3_evm_init(void)
-{
-	struct omap_board_mux *obm;
-
-	omap3_evm_get_revision();
-	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
-
-	obm = (cpu_is_omap3630()) ? omap36x_board_mux : omap35x_board_mux;
-	omap3_mux_init(obm, OMAP_PACKAGE_CBB);
-
-	omap_mux_init_gpio(63, OMAP_PIN_INPUT);
-	omap_hsmmc_init(mmc);
-
-	if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2)
-		omap3evm_twldata.vaux2 = &omap3evm_vaux2;
-
-	omap3_evm_i2c_init();
-
-	omap_display_init(&omap3_evm_dss_data);
-	platform_device_register(&omap3_evm_lcd_device);
-	platform_device_register(&omap3_evm_tfp410_device);
-	platform_device_register(&omap3_evm_dvi_connector_device);
-	platform_device_register(&omap3_evm_tv_connector_device);
-
-	omap_serial_init();
-	omap_sdrc_init(mt46h32m32lf6_sdrc_params, NULL);
-
-	/* OMAP3EVM uses ISP1504 phy and so register nop transceiver */
-	usb_nop_xceiv_register();
-
-	if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2) {
-		/* enable EHCI VBUS using GPIO22 */
-		omap_mux_init_gpio(OMAP3_EVM_EHCI_VBUS, OMAP_PIN_INPUT_PULLUP);
-		/* Select EHCI port on main board */
-		omap_mux_init_gpio(OMAP3_EVM_EHCI_SELECT,
-				   OMAP_PIN_INPUT_PULLUP);
-		gpio_request_array(omap3_evm_ehci_gpios,
-				   ARRAY_SIZE(omap3_evm_ehci_gpios));
-
-		/* setup EHCI phy reset config */
-		omap_mux_init_gpio(21, OMAP_PIN_INPUT_PULLUP);
-		phy_data[0].reset_gpio = 21;
-
-		/* EVM REV >= E can supply 500mA with EXTVBUS programming */
-		musb_board_data.power = 500;
-		musb_board_data.extvbus = 1;
-	} else {
-		/* setup EHCI phy reset on MDC */
-		omap_mux_init_gpio(135, OMAP_PIN_OUTPUT);
-		phy_data[0].reset_gpio = 135;
-	}
-	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
-	usb_musb_init(&musb_board_data);
-
-	usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
-	usbhs_init(&usbhs_bdata);
-	board_nand_init(omap3evm_nand_partitions,
-			ARRAY_SIZE(omap3evm_nand_partitions), NAND_CS,
-			NAND_BUSWIDTH_16, NULL);
-
-	omap_ads7846_init(1, OMAP3_EVM_TS_GPIO, 310, NULL);
-	omap3evm_init_smsc911x();
-#ifdef CONFIG_BROKEN
-	omap3_evm_display_init();
-#endif
-	omap3_evm_wl12xx_init();
-	omap_twl4030_audio_init("omap3evm", NULL);
-}
-
-MACHINE_START(OMAP3EVM, "OMAP3 EVM")
-	/* Maintainer: Syed Mohammed Khasim - Texas Instruments */
-	.atag_offset	= 0x100,
-	.reserve	= omap_reserve,
-	.map_io		= omap3_map_io,
-	.init_early	= omap35xx_init_early,
-	.init_irq	= omap3_init_irq,
-	.handle_irq	= omap3_intc_handle_irq,
-	.init_machine	= omap3_evm_init,
-	.init_late	= omap35xx_init_late,
-	.init_time	= omap3_sync32k_timer_init,
-	.restart	= omap3xxx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
deleted file mode 100644
index 345e8c4..0000000
--- a/arch/arm/mach-omap2/board-rm680.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Board support file for Nokia N950 (RM-680) / N9 (RM-696).
- *
- * Copyright (C) 2010 Nokia
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/i2c/twl.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/consumer.h>
-#include <linux/platform_data/mtd-onenand-omap2.h>
-#include <linux/usb/phy.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-
-#include "common.h"
-#include "mux.h"
-#include "gpmc.h"
-#include "mmc.h"
-#include "hsmmc.h"
-#include "sdram-nokia.h"
-#include "common-board-devices.h"
-#include "gpmc-onenand.h"
-
-static struct regulator_consumer_supply rm680_vemmc_consumers[] = {
-	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
-};
-
-/* Fixed regulator for internal eMMC */
-static struct regulator_init_data rm680_vemmc = {
-	.constraints =	{
-		.name			= "rm680_vemmc",
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_STATUS
-					| REGULATOR_CHANGE_MODE,
-	},
-	.num_consumer_supplies		= ARRAY_SIZE(rm680_vemmc_consumers),
-	.consumer_supplies		= rm680_vemmc_consumers,
-};
-
-static struct fixed_voltage_config rm680_vemmc_config = {
-	.supply_name		= "VEMMC",
-	.microvolts		= 2900000,
-	.gpio			= 157,
-	.startup_delay		= 150,
-	.enable_high		= 1,
-	.init_data		= &rm680_vemmc,
-};
-
-static struct platform_device rm680_vemmc_device = {
-	.name			= "reg-fixed-voltage",
-	.dev			= {
-		.platform_data	= &rm680_vemmc_config,
-	},
-};
-
-static struct platform_device *rm680_peripherals_devices[] __initdata = {
-	&rm680_vemmc_device,
-};
-
-/* TWL */
-static struct twl4030_gpio_platform_data rm680_gpio_data = {
-	.pullups		= BIT(0),
-	.pulldowns		= BIT(1) | BIT(2) | BIT(8) | BIT(15),
-};
-
-static struct twl4030_platform_data rm680_twl_data = {
-	.gpio			= &rm680_gpio_data,
-	/* add rest of the children here */
-};
-
-static void __init rm680_i2c_init(void)
-{
-	omap3_pmic_get_config(&rm680_twl_data, TWL_COMMON_PDATA_USB, 0);
-	omap_pmic_init(1, 2900, "twl5031", 7 + OMAP_INTC_START, &rm680_twl_data);
-	omap_register_i2c_bus(2, 400, NULL, 0);
-	omap_register_i2c_bus(3, 400, NULL, 0);
-}
-
-#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
-	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
-static struct omap_onenand_platform_data board_onenand_data[] = {
-	{
-		.gpio_irq	= 65,
-		.flags		= ONENAND_SYNC_READWRITE,
-	}
-};
-#endif
-
-/* eMMC */
-static struct omap2_hsmmc_info mmc[] __initdata = {
-	{
-		.name		= "internal",
-		.mmc		= 2,
-		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED,
-		.gpio_cd	= -EINVAL,
-		.gpio_wp	= -EINVAL,
-	},
-	{ /* Terminator */ }
-};
-
-static void __init rm680_peripherals_init(void)
-{
-	platform_add_devices(rm680_peripherals_devices,
-				ARRAY_SIZE(rm680_peripherals_devices));
-	rm680_i2c_init();
-	gpmc_onenand_init(board_onenand_data);
-	omap_hsmmc_init(mmc);
-}
-
-#ifdef CONFIG_OMAP_MUX
-static struct omap_board_mux board_mux[] __initdata = {
-	{ .reg_offset = OMAP_MUX_TERMINATOR },
-};
-#endif
-
-static void __init rm680_init(void)
-{
-	struct omap_sdrc_params *sdrc_params;
-
-	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
-	omap_serial_init();
-
-	sdrc_params = nokia_get_sdram_timings();
-	omap_sdrc_init(sdrc_params, sdrc_params);
-
-	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
-	usb_musb_init(NULL);
-	rm680_peripherals_init();
-}
-
-MACHINE_START(NOKIA_RM680, "Nokia RM-680 board")
-	.atag_offset	= 0x100,
-	.reserve	= omap_reserve,
-	.map_io		= omap3_map_io,
-	.init_early	= omap3630_init_early,
-	.init_irq	= omap3_init_irq,
-	.handle_irq	= omap3_intc_handle_irq,
-	.init_machine	= rm680_init,
-	.init_late	= omap3630_init_late,
-	.init_time	= omap3_sync32k_timer_init,
-	.restart	= omap3xxx_restart,
-MACHINE_END
-
-MACHINE_START(NOKIA_RM696, "Nokia RM-696 board")
-	.atag_offset	= 0x100,
-	.reserve	= omap_reserve,
-	.map_io		= omap3_map_io,
-	.init_early	= omap3630_init_early,
-	.init_irq	= omap3_init_irq,
-	.handle_irq	= omap3_intc_handle_irq,
-	.init_machine	= rm680_init,
-	.init_late	= omap3630_init_late,
-	.init_time	= omap3_sync32k_timer_init,
-	.restart	= omap3xxx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index c3270c0..f093af17 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -57,6 +57,8 @@
 #include "common-board-devices.h"
 #include "gpmc.h"
 #include "gpmc-onenand.h"
+#include "soc.h"
+#include "omap-secure.h"
 
 #define SYSTEM_REV_B_USES_VAUX3	0x1699
 #define SYSTEM_REV_S_USES_VAUX3 0x8
@@ -167,64 +169,55 @@
 		.name		= "lp5523:kb1",
 		.chan_nr	= 0,
 		.led_current	= 50,
+		.max_current	= 100,
 	}, {
 		.name		= "lp5523:kb2",
 		.chan_nr	= 1,
 		.led_current	= 50,
+		.max_current	= 100,
 	}, {
 		.name		= "lp5523:kb3",
 		.chan_nr	= 2,
 		.led_current	= 50,
+		.max_current	= 100,
 	}, {
 		.name		= "lp5523:kb4",
 		.chan_nr	= 3,
 		.led_current	= 50,
+		.max_current	= 100,
 	}, {
 		.name		= "lp5523:b",
 		.chan_nr	= 4,
 		.led_current	= 50,
+		.max_current	= 100,
 	}, {
 		.name		= "lp5523:g",
 		.chan_nr	= 5,
 		.led_current	= 50,
+		.max_current	= 100,
 	}, {
 		.name		= "lp5523:r",
 		.chan_nr	= 6,
 		.led_current	= 50,
+		.max_current	= 100,
 	}, {
 		.name		= "lp5523:kb5",
 		.chan_nr	= 7,
 		.led_current	= 50,
+		.max_current	= 100,
 	}, {
 		.name		= "lp5523:kb6",
 		.chan_nr	= 8,
 		.led_current	= 50,
+		.max_current	= 100,
 	}
 };
 
-static int rx51_lp5523_setup(void)
-{
-	return gpio_request_one(RX51_LP5523_CHIP_EN_GPIO, GPIOF_DIR_OUT,
-			"lp5523_enable");
-}
-
-static void rx51_lp5523_release(void)
-{
-	gpio_free(RX51_LP5523_CHIP_EN_GPIO);
-}
-
-static void rx51_lp5523_enable(bool state)
-{
-	gpio_set_value(RX51_LP5523_CHIP_EN_GPIO, !!state);
-}
-
 static struct lp55xx_platform_data rx51_lp5523_platform_data = {
 	.led_config		= rx51_lp5523_led_config,
 	.num_channels		= ARRAY_SIZE(rx51_lp5523_led_config),
 	.clock_mode		= LP55XX_CLOCK_AUTO,
-	.setup_resources	= rx51_lp5523_setup,
-	.release_resources	= rx51_lp5523_release,
-	.enable			= rx51_lp5523_enable,
+	.enable_gpio		= RX51_LP5523_CHIP_EN_GPIO,
 };
 #endif
 
@@ -1289,6 +1282,22 @@
 	platform_device_register(&madc_hwmon);
 }
 
+static struct platform_device omap3_rom_rng_device = {
+	.name		= "omap3-rom-rng",
+	.id		= -1,
+	.dev	= {
+		.platform_data	= rx51_secure_rng_call,
+	},
+};
+
+static void __init rx51_init_omap3_rom_rng(void)
+{
+	if (omap_type() == OMAP2_DEVICE_TYPE_SEC) {
+		pr_info("RX-51: Registring OMAP3 HWRNG device\n");
+		platform_device_register(&omap3_rom_rng_device);
+	}
+}
+
 void __init rx51_peripherals_init(void)
 {
 	rx51_i2c_init();
@@ -1309,5 +1318,6 @@
 
 	rx51_charger_init();
 	rx51_init_twl4030_hwmon();
+	rx51_init_omap3_rom_rng();
 }
 
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index 773510556..db168c9 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -2,6 +2,8 @@
  * Board support file for Nokia N900 (aka RX-51).
  *
  * Copyright (C) 2007, 2008 Nokia
+ * Copyright (C) 2012 Ivaylo Dimitrov <freemangordon@abv.bg>
+ * Copyright (C) 2013 Pali Rohár <pali.rohar@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -31,7 +33,9 @@
 #include "mux.h"
 #include "gpmc.h"
 #include "pm.h"
+#include "soc.h"
 #include "sdram-nokia.h"
+#include "omap-secure.h"
 
 #define RX51_GPIO_SLEEP_IND 162
 
@@ -103,6 +107,14 @@
 	usb_musb_init(&musb_board_data);
 	rx51_peripherals_init();
 
+	if (omap_type() == OMAP2_DEVICE_TYPE_SEC) {
+#ifdef CONFIG_ARM_ERRATA_430973
+		pr_info("RX-51: Enabling ARM errata 430973 workaround\n");
+		/* set IBE to 1 */
+		rx51_secure_update_aux_cr(BIT(6), 0);
+#endif
+	}
+
 	/* 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);
diff --git a/arch/arm/mach-omap2/board-zoom-debugboard.c b/arch/arm/mach-omap2/board-zoom-debugboard.c
deleted file mode 100644
index 42e5f23..0000000
--- a/arch/arm/mach-omap2/board-zoom-debugboard.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2009 Texas Instruments Inc.
- * Mikkel Christensen <mlc@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/gpio.h>
-#include <linux/serial_8250.h>
-#include <linux/smsc911x.h>
-#include <linux/interrupt.h>
-
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/machine.h>
-
-#include "gpmc.h"
-#include "gpmc-smsc911x.h"
-
-#include "board-zoom.h"
-
-#include "soc.h"
-#include "common.h"
-
-#define ZOOM_SMSC911X_CS	7
-#define ZOOM_SMSC911X_GPIO	158
-#define ZOOM_QUADUART_CS	3
-#define ZOOM_QUADUART_GPIO	102
-#define ZOOM_QUADUART_RST_GPIO	152
-#define QUART_CLK		1843200
-#define DEBUG_BASE		0x08000000
-#define ZOOM_ETHR_START	DEBUG_BASE
-
-static struct omap_smsc911x_platform_data zoom_smsc911x_cfg = {
-	.cs             = ZOOM_SMSC911X_CS,
-	.gpio_irq       = ZOOM_SMSC911X_GPIO,
-	.gpio_reset     = -EINVAL,
-	.flags		= SMSC911X_USE_32BIT,
-};
-
-static inline void __init zoom_init_smsc911x(void)
-{
-	gpmc_smsc911x_init(&zoom_smsc911x_cfg);
-}
-
-static struct plat_serial8250_port serial_platform_data[] = {
-	{
-		.mapbase	= ZOOM_UART_BASE,
-		.flags		= UPF_BOOT_AUTOCONF|UPF_IOREMAP|UPF_SHARE_IRQ,
-		.irqflags	= IRQF_SHARED | IRQF_TRIGGER_RISING,
-		.iotype		= UPIO_MEM,
-		.regshift	= 1,
-		.uartclk	= QUART_CLK,
-	}, {
-		.flags		= 0
-	}
-};
-
-static struct platform_device zoom_debugboard_serial_device = {
-	.name			= "serial8250",
-	.id			= PLAT8250_DEV_PLATFORM,
-	.dev			= {
-		.platform_data	= serial_platform_data,
-	},
-};
-
-static inline void __init zoom_init_quaduart(void)
-{
-	int quart_cs;
-	unsigned long cs_mem_base;
-	int quart_gpio = 0;
-
-	if (gpio_request_one(ZOOM_QUADUART_RST_GPIO,
-				GPIOF_OUT_INIT_LOW,
-				"TL16CP754C GPIO") < 0) {
-		pr_err("Failed to request GPIO%d for TL16CP754C\n",
-			ZOOM_QUADUART_RST_GPIO);
-		return;
-	}
-
-	quart_cs = ZOOM_QUADUART_CS;
-
-	if (gpmc_cs_request(quart_cs, SZ_1M, &cs_mem_base) < 0) {
-		pr_err("Failed to request GPMC mem for Quad UART(TL16CP754C)\n");
-		return;
-	}
-
-	quart_gpio = ZOOM_QUADUART_GPIO;
-
-	if (gpio_request_one(quart_gpio, GPIOF_IN, "TL16CP754C GPIO") < 0)
-		printk(KERN_ERR "Failed to request GPIO%d for TL16CP754C\n",
-								quart_gpio);
-
-	serial_platform_data[0].irq = gpio_to_irq(102);
-}
-
-static inline int omap_zoom_debugboard_detect(void)
-{
-	int debug_board_detect = 0;
-	int ret = 1;
-
-	debug_board_detect = ZOOM_SMSC911X_GPIO;
-
-	if (gpio_request_one(debug_board_detect, GPIOF_IN,
-			     "Zoom debug board detect") < 0) {
-		pr_err("Failed to request GPIO%d for Zoom debug board detect\n",
-		       debug_board_detect);
-		return 0;
-	}
-
-	if (!gpio_get_value(debug_board_detect)) {
-		ret = 0;
-	}
-	gpio_free(debug_board_detect);
-	return ret;
-}
-
-static struct platform_device *zoom_devices[] __initdata = {
-	&zoom_debugboard_serial_device,
-};
-
-static struct regulator_consumer_supply dummy_supplies[] = {
-	REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
-	REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
-};
-
-int __init zoom_debugboard_init(void)
-{
-	if (!omap_zoom_debugboard_detect())
-		return 0;
-
-	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
-	zoom_init_smsc911x();
-	zoom_init_quaduart();
-	return platform_add_devices(zoom_devices, ARRAY_SIZE(zoom_devices));
-}
diff --git a/arch/arm/mach-omap2/board-zoom-display.c b/arch/arm/mach-omap2/board-zoom-display.c
deleted file mode 100644
index 3d8ecc1e..0000000
--- a/arch/arm/mach-omap2/board-zoom-display.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2010 Texas Instruments Inc.
- *
- * Modified from mach-omap2/board-zoom-peripherals.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/spi/spi.h>
-#include <linux/platform_data/spi-omap2-mcspi.h>
-#include <video/omapdss.h>
-#include <video/omap-panel-data.h>
-
-#include "board-zoom.h"
-#include "soc.h"
-#include "common.h"
-
-#define LCD_PANEL_RESET_GPIO_PROD	96
-#define LCD_PANEL_RESET_GPIO_PILOT	55
-#define LCD_PANEL_QVGA_GPIO		56
-
-static struct panel_nec_nl8048hl11_platform_data zoom_lcd_pdata = {
-	.name                   = "lcd",
-	.source                 = "dpi.0",
-
-	.data_lines		= 24,
-
-	.res_gpio		= -1,	/* filled in code */
-	.qvga_gpio		= LCD_PANEL_QVGA_GPIO,
-};
-
-static struct omap_dss_board_info zoom_dss_data = {
-	.default_display_name = "lcd",
-};
-
-static void __init zoom_lcd_panel_init(void)
-{
-	zoom_lcd_pdata.res_gpio = (omap_rev() > OMAP3430_REV_ES3_0) ?
-			LCD_PANEL_RESET_GPIO_PROD :
-			LCD_PANEL_RESET_GPIO_PILOT;
-}
-
-static struct omap2_mcspi_device_config dss_lcd_mcspi_config = {
-	.turbo_mode		= 1,
-};
-
-static struct spi_board_info nec_8048_spi_board_info[] __initdata = {
-	[0] = {
-		.modalias		= "panel-nec-nl8048hl11",
-		.bus_num		= 1,
-		.chip_select		= 2,
-		.max_speed_hz		= 375000,
-		.controller_data	= &dss_lcd_mcspi_config,
-		.platform_data		= &zoom_lcd_pdata,
-	},
-};
-
-void __init zoom_display_init(void)
-{
-	omap_display_init(&zoom_dss_data);
-	zoom_lcd_panel_init();
-	spi_register_board_info(nec_8048_spi_board_info,
-				ARRAY_SIZE(nec_8048_spi_board_info));
-}
-
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
deleted file mode 100644
index a90375d..0000000
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * Copyright (C) 2009 Texas Instruments Inc.
- *
- * Modified from mach-omap2/board-zoom2.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/input.h>
-#include <linux/input/matrix_keypad.h>
-#include <linux/gpio.h>
-#include <linux/i2c/twl.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/fixed.h>
-#include <linux/wl12xx.h>
-#include <linux/mmc/host.h>
-#include <linux/platform_data/gpio-omap.h>
-#include <linux/platform_data/omap-twl4030.h>
-#include <linux/usb/phy.h>
-#include <linux/pwm.h>
-#include <linux/leds_pwm.h>
-#include <linux/pwm_backlight.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-#include "common.h"
-
-#include "board-zoom.h"
-
-#include "mux.h"
-#include "hsmmc.h"
-#include "common-board-devices.h"
-
-#define OMAP_ZOOM_WLAN_PMENA_GPIO	(101)
-#define OMAP_ZOOM_TSC2004_IRQ_GPIO	(153)
-#define OMAP_ZOOM_WLAN_IRQ_GPIO		(162)
-
-/* Zoom2 has Qwerty keyboard*/
-static uint32_t board_keymap[] = {
-	KEY(0, 0, KEY_E),
-	KEY(0, 1, KEY_R),
-	KEY(0, 2, KEY_T),
-	KEY(0, 3, KEY_HOME),
-	KEY(0, 6, KEY_I),
-	KEY(0, 7, KEY_LEFTSHIFT),
-	KEY(1, 0, KEY_D),
-	KEY(1, 1, KEY_F),
-	KEY(1, 2, KEY_G),
-	KEY(1, 3, KEY_SEND),
-	KEY(1, 6, KEY_K),
-	KEY(1, 7, KEY_ENTER),
-	KEY(2, 0, KEY_X),
-	KEY(2, 1, KEY_C),
-	KEY(2, 2, KEY_V),
-	KEY(2, 3, KEY_END),
-	KEY(2, 6, KEY_DOT),
-	KEY(2, 7, KEY_CAPSLOCK),
-	KEY(3, 0, KEY_Z),
-	KEY(3, 1, KEY_KPPLUS),
-	KEY(3, 2, KEY_B),
-	KEY(3, 3, KEY_F1),
-	KEY(3, 6, KEY_O),
-	KEY(3, 7, KEY_SPACE),
-	KEY(4, 0, KEY_W),
-	KEY(4, 1, KEY_Y),
-	KEY(4, 2, KEY_U),
-	KEY(4, 3, KEY_F2),
-	KEY(4, 4, KEY_VOLUMEUP),
-	KEY(4, 6, KEY_L),
-	KEY(4, 7, KEY_LEFT),
-	KEY(5, 0, KEY_S),
-	KEY(5, 1, KEY_H),
-	KEY(5, 2, KEY_J),
-	KEY(5, 3, KEY_F3),
-	KEY(5, 4, KEY_UNKNOWN),
-	KEY(5, 5, KEY_VOLUMEDOWN),
-	KEY(5, 6, KEY_M),
-	KEY(5, 7, KEY_RIGHT),
-	KEY(6, 0, KEY_Q),
-	KEY(6, 1, KEY_A),
-	KEY(6, 2, KEY_N),
-	KEY(6, 3, KEY_BACKSPACE),
-	KEY(6, 6, KEY_P),
-	KEY(6, 7, KEY_UP),
-	KEY(7, 0, KEY_PROG1),	/*MACRO 1 <User defined> */
-	KEY(7, 1, KEY_PROG2),	/*MACRO 2 <User defined> */
-	KEY(7, 2, KEY_PROG3),	/*MACRO 3 <User defined> */
-	KEY(7, 3, KEY_PROG4),	/*MACRO 4 <User defined> */
-	KEY(7, 6, KEY_SELECT),
-	KEY(7, 7, KEY_DOWN)
-};
-
-static struct matrix_keymap_data board_map_data = {
-	.keymap			= board_keymap,
-	.keymap_size		= ARRAY_SIZE(board_keymap),
-};
-
-static struct twl4030_keypad_data zoom_kp_twl4030_data = {
-	.keymap_data	= &board_map_data,
-	.rows		= 8,
-	.cols		= 8,
-	.rep		= 1,
-};
-
-static struct regulator_consumer_supply zoom_vmmc1_supply[] = {
-	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
-};
-
-static struct regulator_consumer_supply zoom_vsim_supply[] = {
-	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
-};
-
-static struct regulator_consumer_supply zoom_vmmc2_supply[] = {
-	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
-};
-
-static struct regulator_consumer_supply zoom_vmmc3_supply[] = {
-	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.2"),
-};
-
-/* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
-static struct regulator_init_data zoom_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  = ARRAY_SIZE(zoom_vmmc1_supply),
-	.consumer_supplies      = zoom_vmmc1_supply,
-};
-
-/* VMMC2 for MMC2 card */
-static struct regulator_init_data zoom_vmmc2 = {
-	.constraints = {
-		.min_uV			= 1850000,
-		.max_uV			= 1850000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies  = ARRAY_SIZE(zoom_vmmc2_supply),
-	.consumer_supplies      = zoom_vmmc2_supply,
-};
-
-/* VSIM for OMAP VDD_MMC1A (i/o for DAT4..DAT7) */
-static struct regulator_init_data zoom_vsim = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 3000000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
-					| REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies  = ARRAY_SIZE(zoom_vsim_supply),
-	.consumer_supplies      = zoom_vsim_supply,
-};
-
-static struct regulator_init_data zoom_vmmc3 = {
-	.constraints = {
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(zoom_vmmc3_supply),
-	.consumer_supplies	= zoom_vmmc3_supply,
-};
-
-static struct fixed_voltage_config zoom_vwlan = {
-	.supply_name		= "vwl1271",
-	.microvolts		= 1800000, /* 1.8V */
-	.gpio			= OMAP_ZOOM_WLAN_PMENA_GPIO,
-	.startup_delay		= 70000, /* 70msec */
-	.enable_high		= 1,
-	.enabled_at_boot	= 0,
-	.init_data		= &zoom_vmmc3,
-};
-
-static struct platform_device omap_vwlan_device = {
-	.name		= "reg-fixed-voltage",
-	.id		= 1,
-	.dev = {
-		.platform_data	= &zoom_vwlan,
-	},
-};
-
-static struct pwm_lookup zoom_pwm_lookup[] = {
-	PWM_LOOKUP("twl-pwm", 0, "leds_pwm", "zoom::keypad"),
-	PWM_LOOKUP("twl-pwm", 1, "pwm-backlight", "backlight"),
-};
-
-static struct led_pwm zoom_pwm_leds[] = {
-	{
-		.name		= "zoom::keypad",
-		.max_brightness	= 127,
-		.pwm_period_ns	= 7812500,
-	},
-};
-
-static struct led_pwm_platform_data zoom_pwm_data = {
-	.num_leds	= ARRAY_SIZE(zoom_pwm_leds),
-	.leds		= zoom_pwm_leds,
-};
-
-static struct platform_device zoom_leds_pwm = {
-	.name	= "leds_pwm",
-	.id	= -1,
-	.dev	= {
-		.platform_data = &zoom_pwm_data,
-	},
-};
-
-static struct platform_pwm_backlight_data zoom_backlight_data = {
-	.pwm_id = 1,
-	.max_brightness = 127,
-	.dft_brightness = 127,
-	.pwm_period_ns = 7812500,
-};
-
-static struct platform_device zoom_backlight_pwm = {
-	.name   = "pwm-backlight",
-	.id     = -1,
-	.dev    = {
-		.platform_data = &zoom_backlight_data,
-	},
-};
-
-static struct platform_device *zoom_devices[] __initdata = {
-	&omap_vwlan_device,
-	&zoom_leds_pwm,
-	&zoom_backlight_pwm,
-};
-
-static struct wl12xx_platform_data omap_zoom_wlan_data __initdata = {
-	.board_ref_clock = WL12XX_REFCLOCK_26, /* 26 MHz */
-};
-
-static struct omap2_hsmmc_info mmc[] = {
-	{
-		.name		= "external",
-		.mmc		= 1,
-		.caps		= MMC_CAP_4_BIT_DATA,
-		.gpio_wp	= -EINVAL,
-		.power_saving	= true,
-		.deferred	= true,
-	},
-	{
-		.name		= "internal",
-		.mmc		= 2,
-		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
-		.gpio_cd	= -EINVAL,
-		.gpio_wp	= -EINVAL,
-		.nonremovable	= true,
-		.power_saving	= true,
-	},
-	{
-		.name		= "wl1271",
-		.mmc		= 3,
-		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
-		.gpio_wp	= -EINVAL,
-		.gpio_cd	= -EINVAL,
-		.nonremovable	= true,
-	},
-	{}      /* Terminator */
-};
-
-static struct omap_tw4030_pdata omap_twl4030_audio_data = {
-	.voice_connected = true,
-	.custom_routing	= true,
-
-	.has_hs		= OMAP_TWL4030_LEFT | OMAP_TWL4030_RIGHT,
-	.has_hf		= OMAP_TWL4030_LEFT | OMAP_TWL4030_RIGHT,
-
-	.has_mainmic	= true,
-	.has_submic	= true,
-	.has_hsmic	= true,
-	.has_linein	= OMAP_TWL4030_LEFT | OMAP_TWL4030_RIGHT,
-};
-
-static int zoom_twl_gpio_setup(struct device *dev,
-		unsigned gpio, unsigned ngpio)
-{
-	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
-	mmc[0].gpio_cd = gpio + 0;
-	omap_hsmmc_late_init(mmc);
-
-	/* Audio setup */
-	omap_twl4030_audio_data.jack_detect = gpio + 2;
-	omap_twl4030_audio_init("Zoom2", &omap_twl4030_audio_data);
-
-	return 0;
-}
-
-static struct twl4030_gpio_platform_data zoom_gpio_data = {
-	.setup		= zoom_twl_gpio_setup,
-};
-
-static struct twl4030_platform_data zoom_twldata = {
-	/* platform_data for children goes here */
-	.gpio		= &zoom_gpio_data,
-	.keypad		= &zoom_kp_twl4030_data,
-	.vmmc1          = &zoom_vmmc1,
-	.vmmc2          = &zoom_vmmc2,
-	.vsim           = &zoom_vsim,
-};
-
-static int __init omap_i2c_init(void)
-{
-	omap3_pmic_get_config(&zoom_twldata,
-			TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_BCI |
-			TWL_COMMON_PDATA_MADC | TWL_COMMON_PDATA_AUDIO,
-			TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
-
-	if (machine_is_omap_zoom2())
-		zoom_twldata.audio->codec->ramp_delay_value = 3; /* 161 ms */
-
-	omap_pmic_init(1, 2400, "twl5030", 7 + OMAP_INTC_START, &zoom_twldata);
-	omap_register_i2c_bus(2, 400, NULL, 0);
-	omap_register_i2c_bus(3, 400, NULL, 0);
-	return 0;
-}
-
-static void enable_board_wakeup_source(void)
-{
-	/* T2 interrupt line (keypad) */
-	omap_mux_init_signal("sys_nirq",
-		OMAP_WAKEUP_EN | OMAP_PIN_INPUT_PULLUP);
-}
-
-void __init zoom_peripherals_init(void)
-{
-	int ret;
-
-	omap_zoom_wlan_data.irq = gpio_to_irq(OMAP_ZOOM_WLAN_IRQ_GPIO);
-	ret = wl12xx_set_platform_data(&omap_zoom_wlan_data);
-
-	if (ret)
-		pr_err("error setting wl12xx data: %d\n", ret);
-
-	omap_hsmmc_init(mmc);
-	omap_i2c_init();
-	pwm_add_table(zoom_pwm_lookup, ARRAY_SIZE(zoom_pwm_lookup));
-	platform_add_devices(zoom_devices, ARRAY_SIZE(zoom_devices));
-	usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
-	usb_musb_init(NULL);
-	enable_board_wakeup_source();
-	omap_serial_init();
-}
diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c
deleted file mode 100644
index 1a3dd86..0000000
--- a/arch/arm/mach-omap2/board-zoom.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Texas Instruments Inc.
- * Mikkel Christensen <mlc@ti.com>
- * Felipe Balbi <balbi@ti.com>
- *
- * Modified from mach-omap2/board-ldp.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/input.h>
-#include <linux/gpio.h>
-#include <linux/i2c/twl.h>
-#include <linux/mtd/nand.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-
-#include "common.h"
-
-#include "board-zoom.h"
-
-#include "board-flash.h"
-#include "mux.h"
-#include "sdram-micron-mt46h32m32lf-6.h"
-#include "sdram-hynix-h8mbx00u0mer-0em.h"
-
-#define ZOOM3_EHCI_RESET_GPIO		64
-
-#ifdef CONFIG_OMAP_MUX
-static struct omap_board_mux board_mux[] __initdata = {
-	/* WLAN IRQ - GPIO 162 */
-	OMAP3_MUX(MCBSP1_CLKX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
-	/* WLAN POWER ENABLE - GPIO 101 */
-	OMAP3_MUX(CAM_D2, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
-	/* WLAN SDIO: MMC3 CMD */
-	OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLUP),
-	/* WLAN SDIO: MMC3 CLK */
-	OMAP3_MUX(ETK_CLK, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
-	/* WLAN SDIO: MMC3 DAT[0-3] */
-	OMAP3_MUX(ETK_D3, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
-	OMAP3_MUX(ETK_D4, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
-	OMAP3_MUX(ETK_D5, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
-	OMAP3_MUX(ETK_D6, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
-	{ .reg_offset = OMAP_MUX_TERMINATOR },
-};
-#endif
-
-static struct mtd_partition zoom_nand_partitions[] = {
-	/* All the partition sizes are listed in terms of NAND block size */
-	{
-		.name		= "X-Loader-NAND",
-		.offset		= 0,
-		.size		= 4 * (64 * 2048),	/* 512KB, 0x80000 */
-		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
-	},
-	{
-		.name		= "U-Boot-NAND",
-		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x80000 */
-		.size		= 10 * (64 * 2048),	/* 1.25MB, 0x140000 */
-		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
-	},
-	{
-		.name		= "Boot Env-NAND",
-		.offset		= MTDPART_OFS_APPEND,   /* Offset = 0x1c0000 */
-		.size		= 2 * (64 * 2048),	/* 256KB, 0x40000 */
-	},
-	{
-		.name		= "Kernel-NAND",
-		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x0200000*/
-		.size		= 240 * (64 * 2048),	/* 30M, 0x1E00000 */
-	},
-	{
-		.name		= "system",
-		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x2000000 */
-		.size		= 3328 * (64 * 2048),	/* 416M, 0x1A000000 */
-	},
-	{
-		.name		= "userdata",
-		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x1C000000*/
-		.size		= 256 * (64 * 2048),	/* 32M, 0x2000000 */
-	},
-	{
-		.name		= "cache",
-		.offset		= MTDPART_OFS_APPEND,	/* Offset = 0x1E000000*/
-		.size		= 256 * (64 * 2048),	/* 32M, 0x2000000 */
-	},
-};
-
-static struct usbhs_phy_data phy_data[] __initdata = {
-	{
-		.port = 2,
-		.reset_gpio = ZOOM3_EHCI_RESET_GPIO,
-		.vcc_gpio = -EINVAL,
-	},
-};
-
-static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
-	.port_mode[1]		= OMAP_EHCI_PORT_MODE_PHY,
-};
-
-static void __init omap_zoom_init(void)
-{
-	if (machine_is_omap_zoom2()) {
-		omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
-	} else if (machine_is_omap_zoom3()) {
-		omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
-		omap_mux_init_gpio(ZOOM3_EHCI_RESET_GPIO, OMAP_PIN_OUTPUT);
-
-		usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
-		usbhs_init(&usbhs_bdata);
-	}
-
-	board_nand_init(zoom_nand_partitions,
-			ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS,
-			NAND_BUSWIDTH_16, nand_default_timings);
-	zoom_debugboard_init();
-	zoom_peripherals_init();
-
-	if (machine_is_omap_zoom2())
-		omap_sdrc_init(mt46h32m32lf6_sdrc_params,
-					  mt46h32m32lf6_sdrc_params);
-	else if (machine_is_omap_zoom3())
-		omap_sdrc_init(h8mbx00u0mer0em_sdrc_params,
-					  h8mbx00u0mer0em_sdrc_params);
-
-	zoom_display_init();
-}
-
-MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
-	.atag_offset	= 0x100,
-	.reserve	= omap_reserve,
-	.map_io		= omap3_map_io,
-	.init_early	= omap3430_init_early,
-	.init_irq	= omap3_init_irq,
-	.handle_irq	= omap3_intc_handle_irq,
-	.init_machine	= omap_zoom_init,
-	.init_late	= omap3430_init_late,
-	.init_time	= omap3_sync32k_timer_init,
-	.restart	= omap3xxx_restart,
-MACHINE_END
-
-MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
-	.atag_offset	= 0x100,
-	.reserve	= omap_reserve,
-	.map_io		= omap3_map_io,
-	.init_early	= omap3630_init_early,
-	.init_irq	= omap3_init_irq,
-	.handle_irq	= omap3_intc_handle_irq,
-	.init_machine	= omap_zoom_init,
-	.init_late	= omap3630_init_late,
-	.init_time	= omap3_sync32k_timer_init,
-	.restart	= omap3xxx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-omap2/board-zoom.h b/arch/arm/mach-omap2/board-zoom.h
deleted file mode 100644
index 2e94869..0000000
--- a/arch/arm/mach-omap2/board-zoom.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Defines for zoom boards
- */
-#include <video/omapdss.h>
-
-#define ZOOM_NAND_CS    0
-
-extern int __init zoom_debugboard_init(void);
-extern void __init zoom_peripherals_init(void);
-extern void __init zoom_display_init(void);
diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c
index 334b767..03a2829 100644
--- a/arch/arm/mach-omap2/cclock3xxx_data.c
+++ b/arch/arm/mach-omap2/cclock3xxx_data.c
@@ -3275,6 +3275,7 @@
 static struct omap_clk omap34xx_omap36xx_clks[] = {
 	CLK(NULL,	"aes1_ick",	&aes1_ick),
 	CLK("omap_rng",	"ick",		&rng_ick),
+	CLK("omap3-rom-rng",	"ick",	&rng_ick),
 	CLK(NULL,	"sha11_ick",	&sha11_ick),
 	CLK(NULL,	"des1_ick",	&des1_ick),
 	CLK(NULL,	"cam_mclk",	&cam_mclk),
diff --git a/arch/arm/mach-omap2/clkt2xxx_apll.c b/arch/arm/mach-omap2/clkt2xxx_apll.c
index 25b1fee..c78e893 100644
--- a/arch/arm/mach-omap2/clkt2xxx_apll.c
+++ b/arch/arm/mach-omap2/clkt2xxx_apll.c
@@ -52,7 +52,7 @@
 
 	apll_mask = EN_APLL_LOCKED << clk->enable_bit;
 
-	r = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
+	r = omap2xxx_cm_get_pll_status();
 
 	return ((r & apll_mask) == apll_mask) ? true : false;
 }
@@ -126,7 +126,7 @@
 {
 	u32 aplls, srate = 0;
 
-	aplls = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
+	aplls = omap2xxx_cm_get_pll_config();
 	aplls &= OMAP24XX_APLLS_CLKIN_MASK;
 	aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT;
 
diff --git a/arch/arm/mach-omap2/clkt2xxx_dpllcore.c b/arch/arm/mach-omap2/clkt2xxx_dpllcore.c
index d862010..3ff3254 100644
--- a/arch/arm/mach-omap2/clkt2xxx_dpllcore.c
+++ b/arch/arm/mach-omap2/clkt2xxx_dpllcore.c
@@ -60,8 +60,7 @@
 
 	core_clk = omap2_get_dpll_rate(dpll_core_ck);
 
-	v = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
-	v &= OMAP24XX_CORE_CLK_SRC_MASK;
+	v = omap2xxx_cm_get_core_clk_src();
 
 	if (v == CORE_CLK_SRC_32K)
 		core_clk = 32768;
@@ -79,8 +78,7 @@
 {
 	u32 high, low, core_clk_src;
 
-	core_clk_src = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
-	core_clk_src &= OMAP24XX_CORE_CLK_SRC_MASK;
+	core_clk_src = omap2xxx_cm_get_core_clk_src();
 
 	if (core_clk_src == CORE_CLK_SRC_DPLL) {	/* DPLL clockout */
 		high = curr_prcm_set->dpll_speed * 2;
@@ -120,8 +118,7 @@
 	const struct dpll_data *dd;
 
 	cur_rate = omap2xxx_clk_get_core_rate();
-	mult = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
-	mult &= OMAP24XX_CORE_CLK_SRC_MASK;
+	mult = omap2xxx_cm_get_core_clk_src();
 
 	if ((rate == (cur_rate / 2)) && (mult == 2)) {
 		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
@@ -145,7 +142,7 @@
 		tmpset.cm_clksel1_pll &= ~(dd->mult_mask |
 					   dd->div1_mask);
 		div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
-		tmpset.cm_clksel2_pll = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
+		tmpset.cm_clksel2_pll = omap2xxx_cm_get_core_pll_config();
 		tmpset.cm_clksel2_pll &= ~OMAP24XX_CORE_CLK_SRC_MASK;
 		if (rate > low) {
 			tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL_X2;
diff --git a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
index ae2b35e..b935ed2 100644
--- a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
+++ b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
@@ -98,7 +98,7 @@
 int omap2_select_table_rate(struct clk_hw *hw, unsigned long rate,
 			    unsigned long parent_rate)
 {
-	u32 cur_rate, done_rate, bypass = 0, tmp;
+	u32 cur_rate, done_rate, bypass = 0;
 	const struct prcm_config *prcm;
 	unsigned long found_speed = 0;
 	unsigned long flags;
@@ -141,23 +141,11 @@
 		else
 			done_rate = CORE_CLK_SRC_DPLL;
 
-		/* MPU divider */
-		omap2_cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL);
-
-		/* dsp + iva1 div(2420), iva2.1(2430) */
-		omap2_cm_write_mod_reg(prcm->cm_clksel_dsp,
-				 OMAP24XX_DSP_MOD, CM_CLKSEL);
-
-		omap2_cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL);
-
-		/* Major subsystem dividers */
-		tmp = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK;
-		omap2_cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD,
-				 CM_CLKSEL1);
-
-		if (cpu_is_omap2430())
-			omap2_cm_write_mod_reg(prcm->cm_clksel_mdm,
-					 OMAP2430_MDM_MOD, CM_CLKSEL);
+		omap2xxx_cm_set_mod_dividers(prcm->cm_clksel_mpu,
+					     prcm->cm_clksel_dsp,
+					     prcm->cm_clksel_gfx,
+					     prcm->cm_clksel1_core,
+					     prcm->cm_clksel_mdm);
 
 		/* x2 to enter omap2xxx_sdrc_init_params() */
 		omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 0c38ca9..c7c5d31 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -543,6 +543,44 @@
 }
 
 /**
+ * omap2_clk_deny_idle - disable autoidle on an OMAP clock
+ * @clk: struct clk * to disable autoidle for
+ *
+ * Disable autoidle on an OMAP clock.
+ */
+int omap2_clk_deny_idle(struct clk *clk)
+{
+	struct clk_hw_omap *c;
+
+	if (__clk_get_flags(clk) & CLK_IS_BASIC)
+		return -EINVAL;
+
+	c = to_clk_hw_omap(__clk_get_hw(clk));
+	if (c->ops && c->ops->deny_idle)
+		c->ops->deny_idle(c);
+	return 0;
+}
+
+/**
+ * omap2_clk_allow_idle - enable autoidle on an OMAP clock
+ * @clk: struct clk * to enable autoidle for
+ *
+ * Enable autoidle on an OMAP clock.
+ */
+int omap2_clk_allow_idle(struct clk *clk)
+{
+	struct clk_hw_omap *c;
+
+	if (__clk_get_flags(clk) & CLK_IS_BASIC)
+		return -EINVAL;
+
+	c = to_clk_hw_omap(__clk_get_hw(clk));
+	if (c->ops && c->ops->allow_idle)
+		c->ops->allow_idle(c);
+	return 0;
+}
+
+/**
  * omap2_clk_enable_init_clocks - prepare & enable a list of clocks
  * @clk_names: ptr to an array of strings of clock names to enable
  * @num_clocks: number of clock names in @clk_names
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 7aa32cd..82916cc 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -411,6 +411,8 @@
 void omap2_init_clk_hw_omap_clocks(struct clk *clk);
 int omap2_clk_enable_autoidle_all(void);
 int omap2_clk_disable_autoidle_all(void);
+int omap2_clk_allow_idle(struct clk *clk);
+int omap2_clk_deny_idle(struct clk *clk);
 void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks);
 int omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name);
 void omap2_clk_print_new_rates(const char *hfclkin_ck_name,
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
index 4b03394..f17f006 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -132,7 +132,7 @@
 	u8 _flags;
 	const u8 dep_bit;
 	const u8 prcm_partition;
-	const s16 cm_inst;
+	const u16 cm_inst;
 	const u16 clkdm_offs;
 	struct clkdm_dep *wkdep_srcs;
 	struct clkdm_dep *sleepdep_srcs;
@@ -218,6 +218,7 @@
 extern void __init omap44xx_clockdomains_init(void);
 extern void __init omap54xx_clockdomains_init(void);
 extern void __init dra7xx_clockdomains_init(void);
+void am43xx_clockdomains_init(void);
 
 extern void clkdm_add_autodeps(struct clockdomain *clkdm);
 extern void clkdm_del_autodeps(struct clockdomain *clkdm);
@@ -226,6 +227,7 @@
 extern struct clkdm_ops omap3_clkdm_operations;
 extern struct clkdm_ops omap4_clkdm_operations;
 extern struct clkdm_ops am33xx_clkdm_operations;
+extern struct clkdm_ops am43xx_clkdm_operations;
 
 extern struct clkdm_dep gfx_24xx_wkdeps[];
 extern struct clkdm_dep dsp_24xx_wkdeps[];
diff --git a/arch/arm/mach-omap2/clockdomains43xx_data.c b/arch/arm/mach-omap2/clockdomains43xx_data.c
new file mode 100644
index 0000000..6d71c60
--- /dev/null
+++ b/arch/arm/mach-omap2/clockdomains43xx_data.c
@@ -0,0 +1,196 @@
+/*
+ * AM43xx Clock domains framework
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include "clockdomain.h"
+#include "prcm44xx.h"
+#include "prcm43xx.h"
+
+static struct clockdomain l4_cefuse_43xx_clkdm = {
+	.name		  = "l4_cefuse_clkdm",
+	.pwrdm		  = { .name = "cefuse_pwrdm" },
+	.prcm_partition	  = AM43XX_CM_PARTITION,
+	.cm_inst	  = AM43XX_CM_CEFUSE_INST,
+	.clkdm_offs	  = AM43XX_CM_CEFUSE_CEFUSE_CDOFFS,
+	.flags		  = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain mpu_43xx_clkdm = {
+	.name		  = "mpu_clkdm",
+	.pwrdm		  = { .name = "mpu_pwrdm" },
+	.prcm_partition	  = AM43XX_CM_PARTITION,
+	.cm_inst	  = AM43XX_CM_MPU_INST,
+	.clkdm_offs	  = AM43XX_CM_MPU_MPU_CDOFFS,
+	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
+};
+
+static struct clockdomain l4ls_43xx_clkdm = {
+	.name		  = "l4ls_clkdm",
+	.pwrdm		  = { .name = "per_pwrdm" },
+	.prcm_partition	  = AM43XX_CM_PARTITION,
+	.cm_inst	  = AM43XX_CM_PER_INST,
+	.clkdm_offs	  = AM43XX_CM_PER_L4LS_CDOFFS,
+	.flags		  = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain tamper_43xx_clkdm = {
+	.name		  = "tamper_clkdm",
+	.pwrdm		  = { .name = "tamper_pwrdm" },
+	.prcm_partition	  = AM43XX_CM_PARTITION,
+	.cm_inst	  = AM43XX_CM_TAMPER_INST,
+	.clkdm_offs	  = AM43XX_CM_TAMPER_TAMPER_CDOFFS,
+	.flags		  = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain l4_rtc_43xx_clkdm = {
+	.name		  = "l4_rtc_clkdm",
+	.pwrdm		  = { .name = "rtc_pwrdm" },
+	.prcm_partition	  = AM43XX_CM_PARTITION,
+	.cm_inst	  = AM43XX_CM_RTC_INST,
+	.clkdm_offs	  = AM43XX_CM_RTC_RTC_CDOFFS,
+	.flags		  = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain pruss_ocp_43xx_clkdm = {
+	.name		  = "pruss_ocp_clkdm",
+	.pwrdm		  = { .name = "per_pwrdm" },
+	.prcm_partition	  = AM43XX_CM_PARTITION,
+	.cm_inst	  = AM43XX_CM_PER_INST,
+	.clkdm_offs	  = AM43XX_CM_PER_ICSS_CDOFFS,
+	.flags		  = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain ocpwp_l3_43xx_clkdm = {
+	.name		  = "ocpwp_l3_clkdm",
+	.pwrdm		  = { .name = "per_pwrdm" },
+	.prcm_partition	  = AM43XX_CM_PARTITION,
+	.cm_inst	  = AM43XX_CM_PER_INST,
+	.clkdm_offs	  = AM43XX_CM_PER_OCPWP_L3_CDOFFS,
+	.flags		  = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain l3s_tsc_43xx_clkdm = {
+	.name		  = "l3s_tsc_clkdm",
+	.pwrdm		  = { .name = "wkup_pwrdm" },
+	.prcm_partition	  = AM43XX_CM_PARTITION,
+	.cm_inst	  = AM43XX_CM_WKUP_INST,
+	.clkdm_offs	  = AM43XX_CM_WKUP_L3S_TSC_CDOFFS,
+	.flags		  = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain dss_43xx_clkdm = {
+	.name		  = "dss_clkdm",
+	.pwrdm		  = { .name = "per_pwrdm" },
+	.prcm_partition	  = AM43XX_CM_PARTITION,
+	.cm_inst	  = AM43XX_CM_PER_INST,
+	.clkdm_offs	  = AM43XX_CM_PER_DSS_CDOFFS,
+	.flags		  = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain l3_aon_43xx_clkdm = {
+	.name		  = "l3_aon_clkdm",
+	.pwrdm		  = { .name = "wkup_pwrdm" },
+	.prcm_partition	  = AM43XX_CM_PARTITION,
+	.cm_inst	  = AM43XX_CM_WKUP_INST,
+	.clkdm_offs	  = AM43XX_CM_WKUP_L3_AON_CDOFFS,
+	.flags		  = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain emif_43xx_clkdm = {
+	.name		  = "emif_clkdm",
+	.pwrdm		  = { .name = "per_pwrdm" },
+	.prcm_partition	  = AM43XX_CM_PARTITION,
+	.cm_inst	  = AM43XX_CM_PER_INST,
+	.clkdm_offs	  = AM43XX_CM_PER_EMIF_CDOFFS,
+	.flags		  = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain l4_wkup_aon_43xx_clkdm = {
+	.name		  = "l4_wkup_aon_clkdm",
+	.pwrdm		  = { .name = "wkup_pwrdm" },
+	.prcm_partition	  = AM43XX_CM_PARTITION,
+	.cm_inst	  = AM43XX_CM_WKUP_INST,
+	.clkdm_offs	  = AM43XX_CM_WKUP_L4_WKUP_AON_CDOFFS,
+};
+
+static struct clockdomain l3_43xx_clkdm = {
+	.name		  = "l3_clkdm",
+	.pwrdm		  = { .name = "per_pwrdm" },
+	.prcm_partition	  = AM43XX_CM_PARTITION,
+	.cm_inst	  = AM43XX_CM_PER_INST,
+	.clkdm_offs	  = AM43XX_CM_PER_L3_CDOFFS,
+	.flags		  = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain l4_wkup_43xx_clkdm = {
+	.name		  = "l4_wkup_clkdm",
+	.pwrdm		  = { .name = "wkup_pwrdm" },
+	.prcm_partition	  = AM43XX_CM_PARTITION,
+	.cm_inst	  = AM43XX_CM_WKUP_INST,
+	.clkdm_offs	  = AM43XX_CM_WKUP_WKUP_CDOFFS,
+	.flags		  = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain cpsw_125mhz_43xx_clkdm = {
+	.name		  = "cpsw_125mhz_clkdm",
+	.pwrdm		  = { .name = "per_pwrdm" },
+	.prcm_partition	  = AM43XX_CM_PARTITION,
+	.cm_inst	  = AM43XX_CM_PER_INST,
+	.clkdm_offs	  = AM43XX_CM_PER_CPSW_CDOFFS,
+	.flags		  = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain gfx_l3_43xx_clkdm = {
+	.name		  = "gfx_l3_clkdm",
+	.pwrdm		  = { .name = "gfx_pwrdm" },
+	.prcm_partition	  = AM43XX_CM_PARTITION,
+	.cm_inst	  = AM43XX_CM_GFX_INST,
+	.clkdm_offs	  = AM43XX_CM_GFX_GFX_L3_CDOFFS,
+	.flags		  = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain l3s_43xx_clkdm = {
+	.name		  = "l3s_clkdm",
+	.pwrdm		  = { .name = "per_pwrdm" },
+	.prcm_partition	  = AM43XX_CM_PARTITION,
+	.cm_inst	  = AM43XX_CM_PER_INST,
+	.clkdm_offs	  = AM43XX_CM_PER_L3S_CDOFFS,
+	.flags		  = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain *clockdomains_am43xx[] __initdata = {
+	&l4_cefuse_43xx_clkdm,
+	&mpu_43xx_clkdm,
+	&l4ls_43xx_clkdm,
+	&tamper_43xx_clkdm,
+	&l4_rtc_43xx_clkdm,
+	&pruss_ocp_43xx_clkdm,
+	&ocpwp_l3_43xx_clkdm,
+	&l3s_tsc_43xx_clkdm,
+	&dss_43xx_clkdm,
+	&l3_aon_43xx_clkdm,
+	&emif_43xx_clkdm,
+	&l4_wkup_aon_43xx_clkdm,
+	&l3_43xx_clkdm,
+	&l4_wkup_43xx_clkdm,
+	&cpsw_125mhz_43xx_clkdm,
+	&gfx_l3_43xx_clkdm,
+	&l3s_43xx_clkdm,
+	NULL
+};
+
+void __init am43xx_clockdomains_init(void)
+{
+	clkdm_register_platform_funcs(&am43xx_clkdm_operations);
+	clkdm_register_clkdms(clockdomains_am43xx);
+	clkdm_complete_init();
+}
diff --git a/arch/arm/mach-omap2/cm2xxx.c b/arch/arm/mach-omap2/cm2xxx.c
index 6774a53..ce25abb 100644
--- a/arch/arm/mach-omap2/cm2xxx.c
+++ b/arch/arm/mach-omap2/cm2xxx.c
@@ -327,6 +327,73 @@
 	.clkdm_clk_disable	= omap2xxx_clkdm_clk_disable,
 };
 
+int omap2xxx_cm_fclks_active(void)
+{
+	u32 f1, f2;
+
+	f1 = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
+	f2 = omap2_cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
+
+	return (f1 | f2) ? 1 : 0;
+}
+
+int omap2xxx_cm_mpu_retention_allowed(void)
+{
+	u32 l;
+
+	/* Check for MMC, UART2, UART1, McSPI2, McSPI1 and DSS1. */
+	l = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
+	if (l & (OMAP2420_EN_MMC_MASK | OMAP24XX_EN_UART2_MASK |
+		 OMAP24XX_EN_UART1_MASK | OMAP24XX_EN_MCSPI2_MASK |
+		 OMAP24XX_EN_MCSPI1_MASK | OMAP24XX_EN_DSS1_MASK))
+		return 0;
+	/* Check for UART3. */
+	l = omap2_cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
+	if (l & OMAP24XX_EN_UART3_MASK)
+		return 0;
+
+	return 1;
+}
+
+u32 omap2xxx_cm_get_core_clk_src(void)
+{
+	u32 v;
+
+	v = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
+	v &= OMAP24XX_CORE_CLK_SRC_MASK;
+
+	return v;
+}
+
+u32 omap2xxx_cm_get_core_pll_config(void)
+{
+	return omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
+}
+
+u32 omap2xxx_cm_get_pll_config(void)
+{
+	return omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
+}
+
+u32 omap2xxx_cm_get_pll_status(void)
+{
+	return omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
+}
+
+void omap2xxx_cm_set_mod_dividers(u32 mpu, u32 dsp, u32 gfx, u32 core, u32 mdm)
+{
+	u32 tmp;
+
+	omap2_cm_write_mod_reg(mpu, MPU_MOD, CM_CLKSEL);
+	omap2_cm_write_mod_reg(dsp, OMAP24XX_DSP_MOD, CM_CLKSEL);
+	omap2_cm_write_mod_reg(gfx, GFX_MOD, CM_CLKSEL);
+	tmp = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) &
+		OMAP24XX_CLKSEL_DSS2_MASK;
+	omap2_cm_write_mod_reg(core | tmp, CORE_MOD, CM_CLKSEL1);
+	if (cpu_is_omap2430())
+		omap2_cm_write_mod_reg(mdm, OMAP2430_MDM_MOD, CM_CLKSEL);
+}
+
 /*
  *
  */
diff --git a/arch/arm/mach-omap2/cm2xxx.h b/arch/arm/mach-omap2/cm2xxx.h
index 4cbb39b..891d81c 100644
--- a/arch/arm/mach-omap2/cm2xxx.h
+++ b/arch/arm/mach-omap2/cm2xxx.h
@@ -62,6 +62,14 @@
 					 u8 idlest_shift);
 extern int omap2xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
 					s16 *prcm_inst, u8 *idlest_reg_id);
+extern int omap2xxx_cm_fclks_active(void);
+extern int omap2xxx_cm_mpu_retention_allowed(void);
+extern u32 omap2xxx_cm_get_core_clk_src(void);
+extern u32 omap2xxx_cm_get_core_pll_config(void);
+extern u32 omap2xxx_cm_get_pll_config(void);
+extern u32 omap2xxx_cm_get_pll_status(void);
+extern void omap2xxx_cm_set_mod_dividers(u32 mpu, u32 dsp, u32 gfx, u32 core,
+					 u32 mdm);
 
 extern int __init omap2xxx_cm_init(void);
 
diff --git a/arch/arm/mach-omap2/cm33xx.c b/arch/arm/mach-omap2/cm33xx.c
index 325a515..40a22e5 100644
--- a/arch/arm/mach-omap2/cm33xx.c
+++ b/arch/arm/mach-omap2/cm33xx.c
@@ -48,13 +48,13 @@
 /* Private functions */
 
 /* Read a register in a CM instance */
-static inline u32 am33xx_cm_read_reg(s16 inst, u16 idx)
+static inline u32 am33xx_cm_read_reg(u16 inst, u16 idx)
 {
 	return __raw_readl(cm_base + inst + idx);
 }
 
 /* Write into a register in a CM */
-static inline void am33xx_cm_write_reg(u32 val, s16 inst, u16 idx)
+static inline void am33xx_cm_write_reg(u32 val, u16 inst, u16 idx)
 {
 	__raw_writel(val, cm_base + inst + idx);
 }
@@ -138,7 +138,7 @@
  * @c must be the unshifted value for CLKTRCTRL - i.e., this function
  * will handle the shift itself.
  */
-static void _clktrctrl_write(u8 c, s16 inst, u16 cdoffs)
+static void _clktrctrl_write(u8 c, u16 inst, u16 cdoffs)
 {
 	u32 v;
 
@@ -158,7 +158,7 @@
  * Returns true if the clockdomain referred to by (@inst, @cdoffs)
  * is in hardware-supervised idle mode, or 0 otherwise.
  */
-bool am33xx_cm_is_clkdm_in_hwsup(s16 inst, u16 cdoffs)
+bool am33xx_cm_is_clkdm_in_hwsup(u16 inst, u16 cdoffs)
 {
 	u32 v;
 
@@ -177,7 +177,7 @@
  * Put a clockdomain referred to by (@inst, @cdoffs) into
  * hardware-supervised idle mode.  No return value.
  */
-void am33xx_cm_clkdm_enable_hwsup(s16 inst, u16 cdoffs)
+void am33xx_cm_clkdm_enable_hwsup(u16 inst, u16 cdoffs)
 {
 	_clktrctrl_write(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, inst, cdoffs);
 }
@@ -191,7 +191,7 @@
  * software-supervised idle mode, i.e., controlled manually by the
  * Linux OMAP clockdomain code.  No return value.
  */
-void am33xx_cm_clkdm_disable_hwsup(s16 inst, u16 cdoffs)
+void am33xx_cm_clkdm_disable_hwsup(u16 inst, u16 cdoffs)
 {
 	_clktrctrl_write(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, inst, cdoffs);
 }
@@ -204,7 +204,7 @@
  * Put a clockdomain referred to by (@inst, @cdoffs) into idle
  * No return value.
  */
-void am33xx_cm_clkdm_force_sleep(s16 inst, u16 cdoffs)
+void am33xx_cm_clkdm_force_sleep(u16 inst, u16 cdoffs)
 {
 	_clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, inst, cdoffs);
 }
@@ -217,7 +217,7 @@
  * Take a clockdomain referred to by (@inst, @cdoffs) out of idle,
  * waking it up.  No return value.
  */
-void am33xx_cm_clkdm_force_wakeup(s16 inst, u16 cdoffs)
+void am33xx_cm_clkdm_force_wakeup(u16 inst, u16 cdoffs)
 {
 	_clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, inst, cdoffs);
 }
diff --git a/arch/arm/mach-omap2/cm33xx.h b/arch/arm/mach-omap2/cm33xx.h
index 9d1f4fc..cfb8891 100644
--- a/arch/arm/mach-omap2/cm33xx.h
+++ b/arch/arm/mach-omap2/cm33xx.h
@@ -377,13 +377,13 @@
 
 
 #ifndef __ASSEMBLER__
-extern bool am33xx_cm_is_clkdm_in_hwsup(s16 inst, u16 cdoffs);
-extern void am33xx_cm_clkdm_enable_hwsup(s16 inst, u16 cdoffs);
-extern void am33xx_cm_clkdm_disable_hwsup(s16 inst, u16 cdoffs);
-extern void am33xx_cm_clkdm_force_sleep(s16 inst, u16 cdoffs);
-extern void am33xx_cm_clkdm_force_wakeup(s16 inst, u16 cdoffs);
+bool am33xx_cm_is_clkdm_in_hwsup(u16 inst, u16 cdoffs);
+void am33xx_cm_clkdm_enable_hwsup(u16 inst, u16 cdoffs);
+void am33xx_cm_clkdm_disable_hwsup(u16 inst, u16 cdoffs);
+void am33xx_cm_clkdm_force_sleep(u16 inst, u16 cdoffs);
+void am33xx_cm_clkdm_force_wakeup(u16 inst, u16 cdoffs);
 
-#if defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_AM43XX)
+#ifdef CONFIG_SOC_AM33XX
 extern int am33xx_cm_wait_module_idle(u16 inst, s16 cdoffs,
 					u16 clkctrl_offs);
 extern void am33xx_cm_module_enable(u8 mode, u16 inst, s16 cdoffs,
diff --git a/arch/arm/mach-omap2/cm3xxx.c b/arch/arm/mach-omap2/cm3xxx.c
index 9061c30..f6f0288 100644
--- a/arch/arm/mach-omap2/cm3xxx.c
+++ b/arch/arm/mach-omap2/cm3xxx.c
@@ -636,6 +636,28 @@
 			       OMAP3_CM_CLKOUT_CTRL_OFFSET);
 }
 
+void omap3_cm_save_scratchpad_contents(u32 *ptr)
+{
+	*ptr++ = omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL);
+	*ptr++ = omap2_cm_read_mod_reg(WKUP_MOD, CM_CLKSEL);
+	*ptr++ = omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
+
+	/*
+	 * As per erratum i671, ROM code does not respect the PER DPLL
+	 * programming scheme if CM_AUTOIDLE_PLL..AUTO_PERIPH_DPLL == 1.
+	 * Then,  in anycase, clear these bits to avoid extra latencies.
+	 */
+	*ptr++ = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE) &
+		~OMAP3430_AUTO_PERIPH_DPLL_MASK;
+	*ptr++ = omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL);
+	*ptr++ = omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL2_PLL);
+	*ptr++ = omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL3);
+	*ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKEN_PLL);
+	*ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL);
+	*ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL);
+	*ptr++ = omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL);
+}
+
 /*
  *
  */
diff --git a/arch/arm/mach-omap2/cm3xxx.h b/arch/arm/mach-omap2/cm3xxx.h
index e8e146f..8224c91 100644
--- a/arch/arm/mach-omap2/cm3xxx.h
+++ b/arch/arm/mach-omap2/cm3xxx.h
@@ -83,6 +83,7 @@
 
 extern void omap3_cm_save_context(void);
 extern void omap3_cm_restore_context(void);
+extern void omap3_cm_save_scratchpad_contents(u32 *ptr);
 
 extern int __init omap3xxx_cm_init(void);
 
diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c
index f0290f5..731ca13 100644
--- a/arch/arm/mach-omap2/cminst44xx.c
+++ b/arch/arm/mach-omap2/cminst44xx.c
@@ -111,7 +111,7 @@
 /* Public functions */
 
 /* Read a register in a CM instance */
-u32 omap4_cminst_read_inst_reg(u8 part, s16 inst, u16 idx)
+u32 omap4_cminst_read_inst_reg(u8 part, u16 inst, u16 idx)
 {
 	BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
 	       part == OMAP4430_INVALID_PRCM_PARTITION ||
@@ -120,7 +120,7 @@
 }
 
 /* Write into a register in a CM instance */
-void omap4_cminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx)
+void omap4_cminst_write_inst_reg(u32 val, u8 part, u16 inst, u16 idx)
 {
 	BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS ||
 	       part == OMAP4430_INVALID_PRCM_PARTITION ||
@@ -129,7 +129,7 @@
 }
 
 /* Read-modify-write a register in CM1. Caller must lock */
-u32 omap4_cminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, s16 inst,
+u32 omap4_cminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, u16 inst,
 				   s16 idx)
 {
 	u32 v;
@@ -142,12 +142,12 @@
 	return v;
 }
 
-u32 omap4_cminst_set_inst_reg_bits(u32 bits, u8 part, s16 inst, s16 idx)
+u32 omap4_cminst_set_inst_reg_bits(u32 bits, u8 part, u16 inst, s16 idx)
 {
 	return omap4_cminst_rmw_inst_reg_bits(bits, bits, part, inst, idx);
 }
 
-u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, s16 inst, s16 idx)
+u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, u16 inst, s16 idx)
 {
 	return omap4_cminst_rmw_inst_reg_bits(bits, 0x0, part, inst, idx);
 }
@@ -177,7 +177,7 @@
  * @c must be the unshifted value for CLKTRCTRL - i.e., this function
  * will handle the shift itself.
  */
-static void _clktrctrl_write(u8 c, u8 part, s16 inst, u16 cdoffs)
+static void _clktrctrl_write(u8 c, u8 part, u16 inst, u16 cdoffs)
 {
 	u32 v;
 
@@ -196,7 +196,7 @@
  * Returns true if the clockdomain referred to by (@part, @inst, @cdoffs)
  * is in hardware-supervised idle mode, or 0 otherwise.
  */
-bool omap4_cminst_is_clkdm_in_hwsup(u8 part, s16 inst, u16 cdoffs)
+bool omap4_cminst_is_clkdm_in_hwsup(u8 part, u16 inst, u16 cdoffs)
 {
 	u32 v;
 
@@ -216,7 +216,7 @@
  * Put a clockdomain referred to by (@part, @inst, @cdoffs) into
  * hardware-supervised idle mode.  No return value.
  */
-void omap4_cminst_clkdm_enable_hwsup(u8 part, s16 inst, u16 cdoffs)
+void omap4_cminst_clkdm_enable_hwsup(u8 part, u16 inst, u16 cdoffs)
 {
 	_clktrctrl_write(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, part, inst, cdoffs);
 }
@@ -231,7 +231,7 @@
  * software-supervised idle mode, i.e., controlled manually by the
  * Linux OMAP clockdomain code.  No return value.
  */
-void omap4_cminst_clkdm_disable_hwsup(u8 part, s16 inst, u16 cdoffs)
+void omap4_cminst_clkdm_disable_hwsup(u8 part, u16 inst, u16 cdoffs)
 {
 	_clktrctrl_write(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, part, inst, cdoffs);
 }
@@ -245,7 +245,7 @@
  * Take a clockdomain referred to by (@part, @inst, @cdoffs) out of idle,
  * waking it up.  No return value.
  */
-void omap4_cminst_clkdm_force_wakeup(u8 part, s16 inst, u16 cdoffs)
+void omap4_cminst_clkdm_force_wakeup(u8 part, u16 inst, u16 cdoffs)
 {
 	_clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, part, inst, cdoffs);
 }
@@ -483,3 +483,12 @@
 	.clkdm_clk_enable	= omap4_clkdm_clk_enable,
 	.clkdm_clk_disable	= omap4_clkdm_clk_disable,
 };
+
+struct clkdm_ops am43xx_clkdm_operations = {
+	.clkdm_sleep		= omap4_clkdm_sleep,
+	.clkdm_wakeup		= omap4_clkdm_wakeup,
+	.clkdm_allow_idle	= omap4_clkdm_allow_idle,
+	.clkdm_deny_idle	= omap4_clkdm_deny_idle,
+	.clkdm_clk_enable	= omap4_clkdm_clk_enable,
+	.clkdm_clk_disable	= omap4_clkdm_clk_disable,
+};
diff --git a/arch/arm/mach-omap2/cminst44xx.h b/arch/arm/mach-omap2/cminst44xx.h
index bd7bab8..7f56ea4 100644
--- a/arch/arm/mach-omap2/cminst44xx.h
+++ b/arch/arm/mach-omap2/cminst44xx.h
@@ -11,11 +11,11 @@
 #ifndef __ARCH_ASM_MACH_OMAP2_CMINST44XX_H
 #define __ARCH_ASM_MACH_OMAP2_CMINST44XX_H
 
-extern bool omap4_cminst_is_clkdm_in_hwsup(u8 part, s16 inst, u16 cdoffs);
-extern void omap4_cminst_clkdm_enable_hwsup(u8 part, s16 inst, u16 cdoffs);
-extern void omap4_cminst_clkdm_disable_hwsup(u8 part, s16 inst, u16 cdoffs);
-extern void omap4_cminst_clkdm_force_sleep(u8 part, s16 inst, u16 cdoffs);
-extern void omap4_cminst_clkdm_force_wakeup(u8 part, s16 inst, u16 cdoffs);
+bool omap4_cminst_is_clkdm_in_hwsup(u8 part, u16 inst, u16 cdoffs);
+void omap4_cminst_clkdm_enable_hwsup(u8 part, u16 inst, u16 cdoffs);
+void omap4_cminst_clkdm_disable_hwsup(u8 part, u16 inst, u16 cdoffs);
+void omap4_cminst_clkdm_force_sleep(u8 part, u16 inst, u16 cdoffs);
+void omap4_cminst_clkdm_force_wakeup(u8 part, u16 inst, u16 cdoffs);
 extern int omap4_cminst_wait_module_ready(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs);
 extern int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs,
 					 u16 clkctrl_offs);
@@ -27,14 +27,14 @@
  * In an ideal world, we would not export these low-level functions,
  * but this will probably take some time to fix properly
  */
-extern u32 omap4_cminst_read_inst_reg(u8 part, s16 inst, u16 idx);
-extern void omap4_cminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx);
-extern u32 omap4_cminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part,
-					   s16 inst, s16 idx);
-extern u32 omap4_cminst_set_inst_reg_bits(u32 bits, u8 part, s16 inst,
-					   s16 idx);
-extern u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, s16 inst,
-					   s16 idx);
+u32 omap4_cminst_read_inst_reg(u8 part, u16 inst, u16 idx);
+void omap4_cminst_write_inst_reg(u32 val, u8 part, u16 inst, u16 idx);
+u32 omap4_cminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part,
+				   u16 inst, s16 idx);
+u32 omap4_cminst_set_inst_reg_bits(u32 bits, u8 part, u16 inst,
+				   s16 idx);
+u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, u16 inst,
+				     s16 idx);
 extern u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx,
 					   u32 mask);
 
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 4a5684b..f7644fe 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -98,6 +98,7 @@
 void ti81xx_init_early(void);
 void am33xx_init_early(void);
 void am43xx_init_early(void);
+void am43xx_init_late(void);
 void omap4430_init_early(void);
 void omap5_init_early(void);
 void omap3_init_late(void);	/* Do not use this one */
@@ -109,8 +110,11 @@
 void omap3630_init_late(void);
 void am35xx_init_late(void);
 void ti81xx_init_late(void);
+void am33xx_init_late(void);
+void omap5_init_late(void);
 int omap2_common_pm_late_init(void);
 void dra7xx_init_early(void);
+void dra7xx_init_late(void);
 
 #ifdef CONFIG_SOC_BUS
 void omap_soc_device_init(void);
@@ -288,6 +292,9 @@
 
 #endif
 
+void pdata_quirks_init(struct of_device_id *);
+void omap_pcs_legacy_init(int irq, void (*rearm)(void));
+
 struct omap_sdrc_params;
 extern void omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
 				      struct omap_sdrc_params *sdrc_cs1);
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index 31e0dfe..44bb4d5 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -46,17 +46,7 @@
 struct omap3_scratchpad_prcm_block {
 	u32 prm_clksrc_ctrl;
 	u32 prm_clksel;
-	u32 cm_clksel_core;
-	u32 cm_clksel_wkup;
-	u32 cm_clken_pll;
-	u32 cm_autoidle_pll;
-	u32 cm_clksel1_pll;
-	u32 cm_clksel2_pll;
-	u32 cm_clksel3_pll;
-	u32 cm_clken_pll_mpu;
-	u32 cm_autoidle_pll_mpu;
-	u32 cm_clksel1_pll_mpu;
-	u32 cm_clksel2_pll_mpu;
+	u32 cm_contents[11];
 	u32 prcm_block_size;
 };
 
@@ -347,34 +337,9 @@
 	prcm_block_contents.prm_clksel =
 		omap2_prm_read_mod_reg(OMAP3430_CCR_MOD,
 				       OMAP3_PRM_CLKSEL_OFFSET);
-	prcm_block_contents.cm_clksel_core =
-			omap2_cm_read_mod_reg(CORE_MOD, CM_CLKSEL);
-	prcm_block_contents.cm_clksel_wkup =
-			omap2_cm_read_mod_reg(WKUP_MOD, CM_CLKSEL);
-	prcm_block_contents.cm_clken_pll =
-			omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
-	/*
-	 * As per erratum i671, ROM code does not respect the PER DPLL
-	 * programming scheme if CM_AUTOIDLE_PLL..AUTO_PERIPH_DPLL == 1.
-	 * Then,  in anycase, clear these bits to avoid extra latencies.
-	 */
-	prcm_block_contents.cm_autoidle_pll =
-			omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE) &
-			~OMAP3430_AUTO_PERIPH_DPLL_MASK;
-	prcm_block_contents.cm_clksel1_pll =
-			omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL);
-	prcm_block_contents.cm_clksel2_pll =
-			omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL2_PLL);
-	prcm_block_contents.cm_clksel3_pll =
-			omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL3);
-	prcm_block_contents.cm_clken_pll_mpu =
-			omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKEN_PLL);
-	prcm_block_contents.cm_autoidle_pll_mpu =
-			omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL);
-	prcm_block_contents.cm_clksel1_pll_mpu =
-			omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL);
-	prcm_block_contents.cm_clksel2_pll_mpu =
-			omap2_cm_read_mod_reg(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL);
+
+	omap3_cm_save_scratchpad_contents(prcm_block_contents.cm_contents);
+
 	prcm_block_contents.prcm_block_size = 0x0;
 
 	/* Populate the SDRC block contents */
@@ -604,4 +569,15 @@
 	return 0;
 }
 
+/**
+ * omap3_ctrl_set_iva_bootmode_idle - sets the IVA2 bootmode to idle
+ *
+ * Sets the bootmode for IVA2 to idle. This is needed by the PM code to
+ * force disable IVA2 so that it does not prevent any low-power states.
+ */
+void omap3_ctrl_set_iva_bootmode_idle(void)
+{
+	omap_ctrl_writel(OMAP3_IVA2_BOOTMOD_IDLE,
+			 OMAP343X_CONTROL_IVA2_BOOTMOD);
+}
 #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index f7d7c2e..da05480 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -427,6 +427,7 @@
 extern void omap_ctrl_write_dsp_boot_mode(u8 bootmode);
 extern void omap3630_ctrl_disable_rta(void);
 extern int omap3_ctrl_save_padconf(void);
+extern void omap3_ctrl_set_iva_bootmode_idle(void);
 extern void omap2_set_globals_control(void __iomem *ctrl,
 				      void __iomem *ctrl_pad);
 #else
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 5c5315b..0dd6398 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -19,7 +19,6 @@
 #include <linux/of.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_data/omap4-keypad.h>
-#include <linux/wl12xx.h>
 #include <linux/platform_data/mailbox-omap.h>
 
 #include <asm/mach-types.h>
@@ -37,6 +36,7 @@
 #include "mux.h"
 #include "control.h"
 #include "devices.h"
+#include "display.h"
 
 #define L3_MODULES_MAX_LEN 12
 #define L3_MODULES 3
@@ -466,47 +466,13 @@
 	.resource 	= &omap_vout_resource[0],
 	.id		= -1,
 };
-static void omap_init_vout(void)
+
+int __init omap_init_vout(void)
 {
-	if (platform_device_register(&omap_vout_device) < 0)
-		printk(KERN_ERR "Unable to register OMAP-VOUT device\n");
+	return platform_device_register(&omap_vout_device);
 }
 #else
-static inline void omap_init_vout(void) {}
-#endif
-
-#if IS_ENABLED(CONFIG_WL12XX)
-
-static struct wl12xx_platform_data wl12xx __initdata;
-
-void __init omap_init_wl12xx_of(void)
-{
-	int ret;
-
-	if (!of_have_populated_dt())
-		return;
-
-	if (of_machine_is_compatible("ti,omap4-sdp")) {
-		wl12xx.board_ref_clock = WL12XX_REFCLOCK_26;
-		wl12xx.board_tcxo_clock = WL12XX_TCXOCLOCK_26;
-		wl12xx.irq = gpio_to_irq(53);
-	} else if (of_machine_is_compatible("ti,omap4-panda")) {
-		wl12xx.board_ref_clock = WL12XX_REFCLOCK_38;
-		wl12xx.irq = gpio_to_irq(53);
-	} else {
-		return;
-	}
-
-	ret = wl12xx_set_platform_data(&wl12xx);
-	if (ret) {
-		pr_err("error setting wl12xx data: %d\n", ret);
-		return;
-	}
-}
-#else
-static inline void omap_init_wl12xx_of(void)
-{
-}
+int __init omap_init_vout(void) { return 0; }
 #endif
 
 /*-------------------------------------------------------------------------*/
@@ -531,12 +497,8 @@
 		omap_init_sham();
 		omap_init_aes();
 		omap_init_rng();
-	} else {
-		/* These can be removed when bindings are done */
-		omap_init_wl12xx_of();
 	}
 	omap_init_sti();
-	omap_init_vout();
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 03a0516..a4e536b 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -416,6 +416,34 @@
 		}
 	}
 
+	/* create DRM device */
+	r = omap_init_drm();
+	if (r < 0) {
+		pr_err("Unable to register omapdrm device\n");
+		return r;
+	}
+
+	/* create vrfb device */
+	r = omap_init_vrfb();
+	if (r < 0) {
+		pr_err("Unable to register omapvrfb device\n");
+		return r;
+	}
+
+	/* create FB device */
+	r = omap_init_fb();
+	if (r < 0) {
+		pr_err("Unable to register omapfb device\n");
+		return r;
+	}
+
+	/* create V4L2 display device */
+	r = omap_init_vout();
+	if (r < 0) {
+		pr_err("Unable to register omap_vout device\n");
+		return r;
+	}
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-omap2/display.h b/arch/arm/mach-omap2/display.h
index b871b017..f3d2ce4 100644
--- a/arch/arm/mach-omap2/display.h
+++ b/arch/arm/mach-omap2/display.h
@@ -26,4 +26,8 @@
 	bool	has_framedonetv_irq;
 };
 
+int omap_init_drm(void);
+int omap_init_vrfb(void);
+int omap_init_fb(void);
+int omap_init_vout(void);
 #endif
diff --git a/arch/arm/mach-omap2/drm.c b/arch/arm/mach-omap2/drm.c
index 59a4af7..facd740 100644
--- a/arch/arm/mach-omap2/drm.c
+++ b/arch/arm/mach-omap2/drm.c
@@ -26,10 +26,9 @@
 #include <linux/platform_data/omap_drm.h>
 
 #include "soc.h"
-#include "omap_device.h"
-#include "omap_hwmod.h"
+#include "display.h"
 
-#if defined(CONFIG_DRM_OMAP) || (CONFIG_DRM_OMAP_MODULE)
+#if defined(CONFIG_DRM_OMAP) || defined(CONFIG_DRM_OMAP_MODULE)
 
 static struct omap_drm_platform_data platform_data;
 
@@ -42,26 +41,13 @@
 	.id = 0,
 };
 
-static int __init omap_init_drm(void)
+int __init omap_init_drm(void)
 {
-	struct omap_hwmod *oh = NULL;
-	struct platform_device *pdev;
-
-	/* lookup and populate the DMM information, if present - OMAP4+ */
-	oh = omap_hwmod_lookup("dmm");
-
-	if (oh) {
-		pdev = omap_device_build(oh->name, -1, oh, NULL, 0);
-		WARN(IS_ERR(pdev), "Could not build omap_device for %s\n",
-			oh->name);
-	}
-
 	platform_data.omaprev = GET_OMAP_TYPE;
 
 	return platform_device_register(&omap_drm_device);
 
 }
-
-omap_arch_initcall(omap_init_drm);
-
+#else
+int __init omap_init_drm(void) { return 0; }
 #endif
diff --git a/arch/arm/mach-omap2/dss-common.c b/arch/arm/mach-omap2/dss-common.c
index bf89eff..365bfd3 100644
--- a/arch/arm/mach-omap2/dss-common.c
+++ b/arch/arm/mach-omap2/dss-common.c
@@ -213,3 +213,47 @@
 	platform_device_register(&sdp4430_tpd_device);
 	platform_device_register(&sdp4430_hdmi_connector_device);
 }
+
+
+/* OMAP3 IGEPv2 data */
+
+#define IGEP2_DVI_TFP410_POWER_DOWN_GPIO	170
+
+/* DVI Connector */
+static struct connector_dvi_platform_data omap3_igep2_dvi_connector_pdata = {
+	.name                   = "dvi",
+	.source                 = "tfp410.0",
+	.i2c_bus_num            = 3,
+};
+
+static struct platform_device omap3_igep2_dvi_connector_device = {
+	.name                   = "connector-dvi",
+	.id                     = 0,
+	.dev.platform_data      = &omap3_igep2_dvi_connector_pdata,
+};
+
+/* TFP410 DPI-to-DVI chip */
+static struct encoder_tfp410_platform_data omap3_igep2_tfp410_pdata = {
+	.name                   = "tfp410.0",
+	.source                 = "dpi.0",
+	.data_lines             = 24,
+	.power_down_gpio        = IGEP2_DVI_TFP410_POWER_DOWN_GPIO,
+};
+
+static struct platform_device omap3_igep2_tfp410_device = {
+	.name                   = "tfp410",
+	.id                     = 0,
+	.dev.platform_data      = &omap3_igep2_tfp410_pdata,
+};
+
+static struct omap_dss_board_info igep2_dss_data = {
+	.default_display_name = "dvi",
+};
+
+void __init omap3_igep2_display_init_of(void)
+{
+	omap_display_init(&igep2_dss_data);
+
+	platform_device_register(&omap3_igep2_tfp410_device);
+	platform_device_register(&omap3_igep2_dvi_connector_device);
+}
diff --git a/arch/arm/mach-omap2/dss-common.h b/arch/arm/mach-omap2/dss-common.h
index c28fe3c..a9becf0 100644
--- a/arch/arm/mach-omap2/dss-common.h
+++ b/arch/arm/mach-omap2/dss-common.h
@@ -8,5 +8,6 @@
 
 void __init omap4_panda_display_init_of(void);
 void __init omap_4430sdp_display_init_of(void);
+void __init omap3_igep2_display_init_of(void);
 
 #endif
diff --git a/arch/arm/mach-omap2/fb.c b/arch/arm/mach-omap2/fb.c
index 2ca33cc..26e28e9 100644
--- a/arch/arm/mach-omap2/fb.c
+++ b/arch/arm/mach-omap2/fb.c
@@ -32,6 +32,7 @@
 #include <asm/mach/map.h>
 
 #include "soc.h"
+#include "display.h"
 
 #ifdef CONFIG_OMAP2_VRFB
 
@@ -64,7 +65,7 @@
 	DEFINE_RES_MEM_NAMED(0xfc000000u, 0x4000000, "vrfb-area-11"),
 };
 
-static int __init omap_init_vrfb(void)
+int __init omap_init_vrfb(void)
 {
 	struct platform_device *pdev;
 	const struct resource *res;
@@ -85,8 +86,8 @@
 
 	return PTR_RET(pdev);
 }
-
-omap_arch_initcall(omap_init_vrfb);
+#else
+int __init omap_init_vrfb(void) { return 0; }
 #endif
 
 #if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
@@ -105,11 +106,10 @@
 	.num_resources = 0,
 };
 
-static int __init omap_init_fb(void)
+int __init omap_init_fb(void)
 {
 	return platform_device_register(&omap_fb_device);
 }
-
-omap_arch_initcall(omap_init_fb);
-
+#else
+int __init omap_init_fb(void) { return 0; }
 #endif
diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index 64b5a83..8b6876c 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -272,9 +272,19 @@
 	struct gpmc_timings t;
 	int ret;
 
-	if (gpmc_onenand_data->of_node)
+	if (gpmc_onenand_data->of_node) {
 		gpmc_read_settings_dt(gpmc_onenand_data->of_node,
 				      &onenand_async);
+		if (onenand_async.sync_read || onenand_async.sync_write) {
+			if (onenand_async.sync_write)
+				gpmc_onenand_data->flags |=
+					ONENAND_SYNC_READWRITE;
+			else
+				gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
+			onenand_async.sync_read = false;
+			onenand_async.sync_write = false;
+		}
+	}
 
 	omap2_onenand_set_async_mode(onenand_base);
 
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 579697a..51525fa 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -1521,6 +1521,42 @@
 	return ret;
 }
 
+/*
+ * REVISIT: Add timing support from slls644g.pdf
+ */
+static int gpmc_probe_8250(struct platform_device *pdev,
+				struct device_node *child)
+{
+	struct resource res;
+	unsigned long base;
+	int ret, cs;
+
+	if (of_property_read_u32(child, "reg", &cs) < 0) {
+		dev_err(&pdev->dev, "%s has no 'reg' property\n",
+			child->full_name);
+		return -ENODEV;
+	}
+
+	if (of_address_to_resource(child, 0, &res) < 0) {
+		dev_err(&pdev->dev, "%s has malformed 'reg' property\n",
+			child->full_name);
+		return -ENODEV;
+	}
+
+	ret = gpmc_cs_request(cs, resource_size(&res), &base);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs);
+		return ret;
+	}
+
+	if (of_platform_device_create(child, NULL, &pdev->dev))
+		return 0;
+
+	dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name);
+
+	return -ENODEV;
+}
+
 static int gpmc_probe_dt(struct platform_device *pdev)
 {
 	int ret;
@@ -1564,6 +1600,8 @@
 		else if (of_node_cmp(child->name, "ethernet") == 0 ||
 			 of_node_cmp(child->name, "nor") == 0)
 			ret = gpmc_probe_generic_child(pdev, child);
+		else if (of_node_cmp(child->name, "8250") == 0)
+			ret = gpmc_probe_8250(pdev, child);
 
 		if (WARN(ret < 0, "%s: probing gpmc child %s failed\n",
 			 __func__, child->full_name))
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index 0289adc..9428c5f 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/random.h>
 #include <linux/slab.h>
 
 #ifdef CONFIG_SOC_BUS
@@ -130,6 +131,17 @@
 	odi->id_3 = read_tap_reg(OMAP_TAP_DIE_ID_3);
 }
 
+static int __init omap_feed_randpool(void)
+{
+	struct omap_die_id odi;
+
+	/* Throw the die ID into the entropy pool at boot */
+	omap_get_die_id(&odi);
+	add_device_randomness(&odi, sizeof(odi));
+	return 0;
+}
+omap_device_initcall(omap_feed_randpool);
+
 void __init omap2xxx_check_revision(void)
 {
 	int i, j;
@@ -576,8 +588,8 @@
 	case 0xb942:
 		switch (rev) {
 		case 0:
-			omap_revision = OMAP5430_REV_ES1_0;
-			break;
+			/* No support for ES1.0 Test chip */
+			BUG();
 		case 1:
 		default:
 			omap_revision = OMAP5430_REV_ES2_0;
@@ -587,8 +599,8 @@
 	case 0xb998:
 		switch (rev) {
 		case 0:
-			omap_revision = OMAP5432_REV_ES1_0;
-			break;
+			/* No support for ES1.0 Test chip */
+			BUG();
 		case 1:
 		default:
 			omap_revision = OMAP5432_REV_ES2_0;
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index ff2113c..cd22262 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -583,6 +583,11 @@
 	omap_hwmod_init_postsetup();
 	omap_clk_init = am33xx_clk_init;
 }
+
+void __init am33xx_init_late(void)
+{
+	omap_common_late_init();
+}
 #endif
 
 #ifdef CONFIG_SOC_AM43XX
@@ -594,7 +599,18 @@
 				  NULL);
 	omap2_set_globals_prm(AM33XX_L4_WK_IO_ADDRESS(AM43XX_PRCM_BASE));
 	omap2_set_globals_cm(AM33XX_L4_WK_IO_ADDRESS(AM43XX_PRCM_BASE), NULL);
+	omap_prm_base_init();
+	omap_cm_base_init();
 	omap3xxx_check_revision();
+	am43xx_powerdomains_init();
+	am43xx_clockdomains_init();
+	am43xx_hwmod_init();
+	omap_hwmod_init_postsetup();
+}
+
+void __init am43xx_init_late(void)
+{
+	omap_common_late_init();
 }
 #endif
 
@@ -651,6 +667,11 @@
 	omap54xx_hwmod_init();
 	omap_hwmod_init_postsetup();
 }
+
+void __init omap5_init_late(void)
+{
+	omap_common_late_init();
+}
 #endif
 
 #ifdef CONFIG_SOC_DRA7XX
@@ -671,6 +692,11 @@
 	dra7xx_hwmod_init();
 	omap_hwmod_init_postsetup();
 }
+
+void __init dra7xx_init_late(void)
+{
+	omap_common_late_init();
+}
 #endif
 
 
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 3926f37..e022a86 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -233,7 +233,7 @@
 			goto out;
 
 		irqnr = readl_relaxed(base_addr + 0xd8);
-#ifdef CONFIG_SOC_TI81XX
+#if IS_ENABLED(CONFIG_SOC_TI81XX) || IS_ENABLED(CONFIG_SOC_AM33XX)
 		if (irqnr)
 			goto out;
 		irqnr = readl_relaxed(base_addr + 0xf8);
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index 5d87680..b4ac3af 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -25,6 +25,7 @@
 
 #include "soc.h"
 #include "omap_device.h"
+#include "clock.h"
 
 /*
  * FIXME: Find a mechanism to enable/disable runtime the McBSP ICLK autoidle.
@@ -33,22 +34,18 @@
 #include "cm3xxx.h"
 #include "cm-regbits-34xx.h"
 
+static struct clk *mcbsp_iclks[5];
+
 static int omap3_enable_st_clock(unsigned int id, bool enable)
 {
-	unsigned int w;
-
 	/*
 	 * Sidetone uses McBSP ICLK - which must not idle when sidetones
 	 * are enabled or sidetones start sounding ugly.
 	 */
-	w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE);
 	if (enable)
-		w &= ~(1 << (id - 2));
+		return omap2_clk_deny_idle(mcbsp_iclks[id]);
 	else
-		w |= 1 << (id - 2);
-	omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE);
-
-	return 0;
+		return omap2_clk_allow_idle(mcbsp_iclks[id]);
 }
 
 static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
@@ -58,6 +55,7 @@
 	struct omap_hwmod *oh_device[2];
 	struct omap_mcbsp_platform_data *pdata = NULL;
 	struct platform_device *pdev;
+	char clk_name[11];
 
 	sscanf(oh->name, "mcbsp%d", &id);
 
@@ -99,6 +97,8 @@
 		oh_device[1] = omap_hwmod_lookup((
 		(struct omap_mcbsp_dev_attr *)(oh->dev_attr))->sidetone);
 		pdata->enable_st_clock = omap3_enable_st_clock;
+		sprintf(clk_name, "mcbsp%d_ick", id);
+		mcbsp_iclks[id] = clk_get(NULL, clk_name);
 		count++;
 	}
 	pdev = omap_device_build_ss(name, id, oh_device, count, pdata,
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index f82cf87..48094b5 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -811,6 +811,12 @@
 		}
 	}
 
+	omap_mux_dbg_init();
+
+	/* see pinctrl-single-omap for the wake-up interrupt handling */
+	if (of_have_populated_dt())
+		return 0;
+
 	ret = request_irq(omap_prcm_event_to_irq("io"),
 		omap_hwmod_mux_handle_irq, IRQF_SHARED | IRQF_NO_SUSPEND,
 			"hwmod_io", omap_mux_late_init);
@@ -818,8 +824,6 @@
 	if (ret)
 		pr_warning("mux: Failed to setup hwmod io irq %d\n", ret);
 
-	omap_mux_dbg_init();
-
 	return 0;
 }
 
diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h
index 5d2080e..16f78a9 100644
--- a/arch/arm/mach-omap2/mux.h
+++ b/arch/arm/mach-omap2/mux.h
@@ -28,7 +28,7 @@
 #define OMAP_PULL_UP			(1 << 4)
 #define OMAP_ALTELECTRICALSEL		(1 << 5)
 
-/* 34xx specific mux bit defines */
+/* omap3/4/5 specific mux bit defines */
 #define OMAP_INPUT_EN			(1 << 8)
 #define OMAP_OFF_EN			(1 << 9)
 #define OMAP_OFFOUT_EN			(1 << 10)
@@ -36,8 +36,6 @@
 #define OMAP_OFF_PULL_EN		(1 << 12)
 #define OMAP_OFF_PULL_UP		(1 << 13)
 #define OMAP_WAKEUP_EN			(1 << 14)
-
-/* 44xx specific mux bit defines */
 #define OMAP_WAKEUP_EVENT		(1 << 15)
 
 /* Active pin states */
diff --git a/arch/arm/mach-omap2/omap-secure.c b/arch/arm/mach-omap2/omap-secure.c
index b970440..5ac122e 100644
--- a/arch/arm/mach-omap2/omap-secure.c
+++ b/arch/arm/mach-omap2/omap-secure.c
@@ -3,6 +3,8 @@
  *
  * Copyright (C) 2011 Texas Instruments, Inc.
  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+ * Copyright (C) 2012 Ivaylo Dimitrov <freemangordon@abv.bg>
+ * Copyright (C) 2013 Pali Rohár <pali.rohar@gmail.com>
  *
  *
  * This program is free software,you can redistribute it and/or modify
@@ -70,3 +72,77 @@
 {
 	return omap_secure_memblock_base;
 }
+
+/**
+ * rx51_secure_dispatcher: Routine to dispatch secure PPA API calls
+ * @idx: The PPA API index
+ * @process: Process ID
+ * @flag: The flag indicating criticality of operation
+ * @nargs: Number of valid arguments out of four.
+ * @arg1, arg2, arg3 args4: Parameters passed to secure API
+ *
+ * Return the non-zero error value on failure.
+ *
+ * NOTE: rx51_secure_dispatcher differs from omap_secure_dispatcher because
+ *       it calling omap_smc3() instead omap_smc2() and param[0] is nargs+1
+ */
+u32 rx51_secure_dispatcher(u32 idx, u32 process, u32 flag, u32 nargs,
+			   u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+{
+	u32 ret;
+	u32 param[5];
+
+	param[0] = nargs+1; /* RX-51 needs number of arguments + 1 */
+	param[1] = arg1;
+	param[2] = arg2;
+	param[3] = arg3;
+	param[4] = arg4;
+
+	/*
+	 * Secure API needs physical address
+	 * pointer for the parameters
+	 */
+	local_irq_disable();
+	local_fiq_disable();
+	flush_cache_all();
+	outer_clean_range(__pa(param), __pa(param + 5));
+	ret = omap_smc3(idx, process, flag, __pa(param));
+	flush_cache_all();
+	local_fiq_enable();
+	local_irq_enable();
+
+	return ret;
+}
+
+/**
+ * rx51_secure_update_aux_cr: Routine to modify the contents of Auxiliary Control Register
+ *  @set_bits: bits to set in ACR
+ *  @clr_bits: bits to clear in ACR
+ *
+ * Return the non-zero error value on failure.
+*/
+u32 rx51_secure_update_aux_cr(u32 set_bits, u32 clear_bits)
+{
+	u32 acr;
+
+	/* Read ACR */
+	asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr));
+	acr &= ~clear_bits;
+	acr |= set_bits;
+
+	return rx51_secure_dispatcher(RX51_PPA_WRITE_ACR,
+				      0,
+				      FLAG_START_CRITICAL,
+				      1, acr, 0, 0, 0);
+}
+
+/**
+ * rx51_secure_rng_call: Routine for HW random generator
+ */
+u32 rx51_secure_rng_call(u32 ptr, u32 count, u32 flag)
+{
+	return rx51_secure_dispatcher(RX51_PPA_HWRNG,
+				      0,
+				      NO_FLAG,
+				      3, ptr, count, flag, 0);
+}
diff --git a/arch/arm/mach-omap2/omap-secure.h b/arch/arm/mach-omap2/omap-secure.h
index 0e72917..8cc7d33 100644
--- a/arch/arm/mach-omap2/omap-secure.h
+++ b/arch/arm/mach-omap2/omap-secure.h
@@ -3,6 +3,8 @@
  *
  * Copyright (C) 2011 Texas Instruments, Inc.
  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+ * Copyright (C) 2012 Ivaylo Dimitrov <freemangordon@abv.bg>
+ * Copyright (C) 2013 Pali Rohár <pali.rohar@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -42,23 +44,38 @@
 #define OMAP4_MON_L2X0_AUXCTRL_INDEX	0x109
 #define OMAP4_MON_L2X0_PREFETCH_INDEX	0x113
 
+#define OMAP5_DRA7_MON_SET_CNTFRQ_INDEX	0x109
+
 /* Secure PPA(Primary Protected Application) APIs */
 #define OMAP4_PPA_L2_POR_INDEX		0x23
 #define OMAP4_PPA_CPU_ACTRL_SMP_INDEX	0x25
 
+/* Secure RX-51 PPA (Primary Protected Application) APIs */
+#define RX51_PPA_HWRNG			29
+#define RX51_PPA_L2_INVAL		40
+#define RX51_PPA_WRITE_ACR		42
+
 #ifndef __ASSEMBLER__
 
 extern u32 omap_secure_dispatcher(u32 idx, u32 flag, u32 nargs,
 				u32 arg1, u32 arg2, u32 arg3, u32 arg4);
 extern u32 omap_smc2(u32 id, u32 falg, u32 pargs);
+extern u32 omap_smc3(u32 id, u32 process, u32 flag, u32 pargs);
 extern phys_addr_t omap_secure_ram_mempool_base(void);
 extern int omap_secure_ram_reserve_memblock(void);
 
+extern u32 rx51_secure_dispatcher(u32 idx, u32 process, u32 flag, u32 nargs,
+				  u32 arg1, u32 arg2, u32 arg3, u32 arg4);
+extern u32 rx51_secure_update_aux_cr(u32 set_bits, u32 clear_bits);
+extern u32 rx51_secure_rng_call(u32 ptr, u32 count, u32 flag);
+
 #ifdef CONFIG_OMAP4_ERRATA_I688
 extern int omap_barrier_reserve_memblock(void);
 #else
 static inline void omap_barrier_reserve_memblock(void)
 { }
 #endif
+
+void set_cntfreq(void);
 #endif /* __ASSEMBLER__ */
 #endif /* OMAP_ARCH_OMAP_SECURE_H */
diff --git a/arch/arm/mach-omap2/omap-smc.S b/arch/arm/mach-omap2/omap-smc.S
index f6441c1..fd90125 100644
--- a/arch/arm/mach-omap2/omap-smc.S
+++ b/arch/arm/mach-omap2/omap-smc.S
@@ -1,9 +1,11 @@
 /*
- * OMAP44xx secure APIs file.
+ * OMAP34xx and OMAP44xx secure APIs file.
  *
  * Copyright (C) 2010 Texas Instruments, Inc.
  * Written by Santosh Shilimkar <santosh.shilimkar@ti.com>
  *
+ * Copyright (C) 2012 Ivaylo Dimitrov <freemangordon@abv.bg>
+ * Copyright (C) 2013 Pali Rohár <pali.rohar@gmail.com>
  *
  * This program is free software,you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -54,6 +56,23 @@
 	ldmfd   sp!, {r4-r12, pc}
 ENDPROC(omap_smc2)
 
+/**
+ * u32 omap_smc3(u32 service_id, u32 process_id, u32 flag, u32 pargs)
+ * Low level common routine for secure HAL and PPA APIs via smc #1
+ * r0 - @service_id: Secure Service ID
+ * r1 - @process_id: Process ID
+ * r2 - @flag: Flag to indicate the criticality of operation
+ * r3 - @pargs: Physical address of parameter list
+ */
+ENTRY(omap_smc3)
+	stmfd	sp!, {r4-r11, lr}
+	mov	r12, r0		@ Copy the secure service ID
+	mov	r6, #0xff	@ Indicate new Task call
+	dsb			@ Memory Barrier (not sure if needed, copied from omap_smc2)
+	smc	#1		@ Call PPA service
+	ldmfd	sp!, {r4-r11, pc}
+ENDPROC(omap_smc3)
+
 ENTRY(omap_modify_auxcoreboot0)
 	stmfd   sp!, {r1-r12, lr}
 	ldr	r12, =0x104
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index 8912110..75e95d4 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -66,6 +66,13 @@
 							4, 0, 0, 0, 0, 0);
 
 	/*
+	 * Configure the CNTFRQ register for the secondary cpu's which
+	 * indicates the frequency of the cpu local timers.
+	 */
+	if (soc_is_omap54xx() || soc_is_dra7xx())
+		set_cntfreq();
+
+	/*
 	 * Synchronise with the boot thread.
 	 */
 	spin_lock(&boot_lock);
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
index 813c615..3664562 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -33,8 +33,12 @@
 #include "omap4-sar-layout.h"
 #include "common.h"
 
-#define MAX_NR_REG_BANKS	5
-#define MAX_IRQS		160
+#define AM43XX_NR_REG_BANKS	7
+#define AM43XX_IRQS		224
+#define MAX_NR_REG_BANKS	AM43XX_NR_REG_BANKS
+#define MAX_IRQS		AM43XX_IRQS
+#define DEFAULT_NR_REG_BANKS	5
+#define DEFAULT_IRQS		160
 #define WKG_MASK_ALL		0x00000000
 #define WKG_UNMASK_ALL		0xffffffff
 #define CPU_ENA_OFFSET		0x400
@@ -47,8 +51,8 @@
 static void __iomem *sar_base;
 static DEFINE_RAW_SPINLOCK(wakeupgen_lock);
 static unsigned int irq_target_cpu[MAX_IRQS];
-static unsigned int irq_banks = MAX_NR_REG_BANKS;
-static unsigned int max_irqs = MAX_IRQS;
+static unsigned int irq_banks = DEFAULT_NR_REG_BANKS;
+static unsigned int max_irqs = DEFAULT_IRQS;
 static unsigned int omap_secure_apis;
 
 /*
@@ -418,12 +422,16 @@
 		irq_banks = OMAP4_NR_BANKS;
 		max_irqs = OMAP4_NR_IRQS;
 		omap_secure_apis = 1;
+	} else if (soc_is_am43xx()) {
+		irq_banks = AM43XX_NR_REG_BANKS;
+		max_irqs = AM43XX_IRQS;
 	}
 
 	/* Clear all IRQ bitmasks at wakeupGen level */
 	for (i = 0; i < irq_banks; i++) {
 		wakeupgen_writel(0, i, CPU0_ID);
-		wakeupgen_writel(0, i, CPU1_ID);
+		if (!soc_is_am43xx())
+			wakeupgen_writel(0, i, CPU1_ID);
 	}
 
 	/*
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index d9ee0ff..e3f0eca 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2357,25 +2357,29 @@
 /**
  * _init_mpu_rt_base - populate the virtual address for a hwmod
  * @oh: struct omap_hwmod * to locate the virtual address
+ * @data: (unused, caller should pass NULL)
+ * @np: struct device_node * of the IP block's device node in the DT data
  *
  * Cache the virtual address used by the MPU to access this IP block's
  * registers.  This address is needed early so the OCP registers that
  * are part of the device's address space can be ioremapped properly.
- * No return value.
+ *
+ * Returns 0 on success, -EINVAL if an invalid hwmod is passed, and
+ * -ENXIO on absent or invalid register target address space.
  */
-static void __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data)
+static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data,
+				    struct device_node *np)
 {
 	struct omap_hwmod_addr_space *mem;
 	void __iomem *va_start = NULL;
-	struct device_node *np;
 
 	if (!oh)
-		return;
+		return -EINVAL;
 
 	_save_mpu_port_index(oh);
 
 	if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
-		return;
+		return -ENXIO;
 
 	mem = _find_mpu_rt_addr_space(oh);
 	if (!mem) {
@@ -2383,25 +2387,24 @@
 			 oh->name);
 
 		/* Extract the IO space from device tree blob */
-		if (!of_have_populated_dt())
-			return;
+		if (!np)
+			return -ENXIO;
 
-		np = of_dev_hwmod_lookup(of_find_node_by_name(NULL, "ocp"), oh);
-		if (np)
-			va_start = of_iomap(np, oh->mpu_rt_idx);
+		va_start = of_iomap(np, oh->mpu_rt_idx);
 	} else {
 		va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start);
 	}
 
 	if (!va_start) {
 		pr_err("omap_hwmod: %s: Could not ioremap\n", oh->name);
-		return;
+		return -ENXIO;
 	}
 
 	pr_debug("omap_hwmod: %s: MPU register target at va %p\n",
 		 oh->name, va_start);
 
 	oh->_mpu_rt_va = va_start;
+	return 0;
 }
 
 /**
@@ -2414,18 +2417,28 @@
  * registered at this point.  This is the first of two phases for
  * hwmod initialization.  Code called here does not touch any hardware
  * registers, it simply prepares internal data structures.  Returns 0
- * upon success or if the hwmod isn't registered, or -EINVAL upon
- * failure.
+ * upon success or if the hwmod isn't registered or if the hwmod's
+ * address space is not defined, or -EINVAL upon failure.
  */
 static int __init _init(struct omap_hwmod *oh, void *data)
 {
 	int r;
+	struct device_node *np = NULL;
 
 	if (oh->_state != _HWMOD_STATE_REGISTERED)
 		return 0;
 
-	if (oh->class->sysc)
-		_init_mpu_rt_base(oh, NULL);
+	if (of_have_populated_dt())
+		np = of_dev_hwmod_lookup(of_find_node_by_name(NULL, "ocp"), oh);
+
+	if (oh->class->sysc) {
+		r = _init_mpu_rt_base(oh, NULL, np);
+		if (r < 0) {
+			WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n",
+			     oh->name);
+			return 0;
+		}
+	}
 
 	r = _init_clocks(oh, NULL);
 	if (r < 0) {
@@ -2433,6 +2446,12 @@
 		return -EINVAL;
 	}
 
+	if (np)
+		if (of_find_property(np, "ti,no-reset-on-init", NULL))
+			oh->flags |= HWMOD_INIT_NO_RESET;
+		if (of_find_property(np, "ti,no-idle-on-init", NULL))
+			oh->flags |= HWMOD_INIT_NO_IDLE;
+
 	oh->_state = _HWMOD_STATE_INITIALIZED;
 
 	return 0;
@@ -4125,6 +4144,14 @@
 		soc_ops.init_clkdm = _init_clkdm;
 		soc_ops.update_context_lost = _omap4_update_context_lost;
 		soc_ops.get_context_lost = _omap4_get_context_lost;
+	} else if (soc_is_am43xx()) {
+		soc_ops.enable_module = _omap4_enable_module;
+		soc_ops.disable_module = _omap4_disable_module;
+		soc_ops.wait_target_ready = _omap4_wait_target_ready;
+		soc_ops.assert_hardreset = _omap4_assert_hardreset;
+		soc_ops.deassert_hardreset = _omap4_deassert_hardreset;
+		soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted;
+		soc_ops.init_clkdm = _init_clkdm;
 	} else if (soc_is_am33xx()) {
 		soc_ops.enable_module = _am33xx_enable_module;
 		soc_ops.disable_module = _am33xx_disable_module;
diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h
index d02acf9..0f97d63 100644
--- a/arch/arm/mach-omap2/omap_hwmod.h
+++ b/arch/arm/mach-omap2/omap_hwmod.h
@@ -752,6 +752,7 @@
 extern int omap54xx_hwmod_init(void);
 extern int am33xx_hwmod_init(void);
 extern int dra7xx_hwmod_init(void);
+int am43xx_hwmod_init(void);
 
 extern int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois);
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h
new file mode 100644
index 0000000..130332c
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h
@@ -0,0 +1,163 @@
+/*
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated
+ *
+ * Data common for AM335x and AM43x
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_OMAP_HWMOD_33XX_43XX_COMMON_DATA_H
+#define __ARCH_ARM_MACH_OMAP2_OMAP_HWMOD_33XX_43XX_COMMON_DATA_H
+
+extern struct omap_hwmod_ocp_if am33xx_mpu__l3_main;
+extern struct omap_hwmod_ocp_if am33xx_l3_main__l3_s;
+extern struct omap_hwmod_ocp_if am33xx_l3_s__l4_ls;
+extern struct omap_hwmod_ocp_if am33xx_l3_s__l4_wkup;
+extern struct omap_hwmod_ocp_if am33xx_l3_main__l3_instr;
+extern struct omap_hwmod_ocp_if am33xx_mpu__prcm;
+extern struct omap_hwmod_ocp_if am33xx_l3_s__l3_main;
+extern struct omap_hwmod_ocp_if am33xx_pruss__l3_main;
+extern struct omap_hwmod_ocp_if am33xx_gfx__l3_main;
+extern struct omap_hwmod_ocp_if am33xx_l3_main__gfx;
+extern struct omap_hwmod_ocp_if am33xx_l4_wkup__rtc;
+extern struct omap_hwmod_ocp_if am33xx_l4_per__dcan0;
+extern struct omap_hwmod_ocp_if am33xx_l4_per__dcan1;
+extern struct omap_hwmod_ocp_if am33xx_l4_per__gpio1;
+extern struct omap_hwmod_ocp_if am33xx_l4_per__gpio2;
+extern struct omap_hwmod_ocp_if am33xx_l4_per__gpio3;
+extern struct omap_hwmod_ocp_if am33xx_cpgmac0__mdio;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__elm;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss0;
+extern struct omap_hwmod_ocp_if am33xx_epwmss0__ecap0;
+extern struct omap_hwmod_ocp_if am33xx_epwmss0__eqep0;
+extern struct omap_hwmod_ocp_if am33xx_epwmss0__ehrpwm0;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss1;
+extern struct omap_hwmod_ocp_if am33xx_epwmss1__ecap1;
+extern struct omap_hwmod_ocp_if am33xx_epwmss1__eqep1;
+extern struct omap_hwmod_ocp_if am33xx_epwmss1__ehrpwm1;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss2;
+extern struct omap_hwmod_ocp_if am33xx_epwmss2__ecap2;
+extern struct omap_hwmod_ocp_if am33xx_epwmss2__eqep2;
+extern struct omap_hwmod_ocp_if am33xx_epwmss2__ehrpwm2;
+extern struct omap_hwmod_ocp_if am33xx_l3_s__gpmc;
+extern struct omap_hwmod_ocp_if am33xx_l4_per__i2c2;
+extern struct omap_hwmod_ocp_if am33xx_l4_per__i2c3;
+extern struct omap_hwmod_ocp_if am33xx_l4_per__mailbox;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__spinlock;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__mcasp0;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__mcasp1;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__mmc0;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__mmc1;
+extern struct omap_hwmod_ocp_if am33xx_l3_s__mmc2;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__mcspi0;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__mcspi1;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__timer2;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__timer3;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__timer4;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__timer5;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__timer6;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__timer7;
+extern struct omap_hwmod_ocp_if am33xx_l3_main__tpcc;
+extern struct omap_hwmod_ocp_if am33xx_l3_main__tptc0;
+extern struct omap_hwmod_ocp_if am33xx_l3_main__tptc1;
+extern struct omap_hwmod_ocp_if am33xx_l3_main__tptc2;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__uart2;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__uart3;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__uart4;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__uart5;
+extern struct omap_hwmod_ocp_if am33xx_l4_ls__uart6;
+extern struct omap_hwmod_ocp_if am33xx_l3_main__ocmc;
+extern struct omap_hwmod_ocp_if am33xx_l3_main__sha0;
+extern struct omap_hwmod_ocp_if am33xx_l3_main__aes0;
+
+extern struct omap_hwmod am33xx_l3_main_hwmod;
+extern struct omap_hwmod am33xx_l3_s_hwmod;
+extern struct omap_hwmod am33xx_l3_instr_hwmod;
+extern struct omap_hwmod am33xx_l4_ls_hwmod;
+extern struct omap_hwmod am33xx_l4_wkup_hwmod;
+extern struct omap_hwmod am33xx_mpu_hwmod;
+extern struct omap_hwmod am33xx_pruss_hwmod;
+extern struct omap_hwmod am33xx_gfx_hwmod;
+extern struct omap_hwmod am33xx_prcm_hwmod;
+extern struct omap_hwmod am33xx_aes0_hwmod;
+extern struct omap_hwmod am33xx_sha0_hwmod;
+extern struct omap_hwmod am33xx_ocmcram_hwmod;
+extern struct omap_hwmod am33xx_smartreflex0_hwmod;
+extern struct omap_hwmod am33xx_smartreflex1_hwmod;
+extern struct omap_hwmod am33xx_cpgmac0_hwmod;
+extern struct omap_hwmod am33xx_mdio_hwmod;
+extern struct omap_hwmod am33xx_dcan0_hwmod;
+extern struct omap_hwmod am33xx_dcan1_hwmod;
+extern struct omap_hwmod am33xx_elm_hwmod;
+extern struct omap_hwmod am33xx_epwmss0_hwmod;
+extern struct omap_hwmod am33xx_ecap0_hwmod;
+extern struct omap_hwmod am33xx_eqep0_hwmod;
+extern struct omap_hwmod am33xx_ehrpwm0_hwmod;
+extern struct omap_hwmod am33xx_epwmss1_hwmod;
+extern struct omap_hwmod am33xx_ecap1_hwmod;
+extern struct omap_hwmod am33xx_eqep1_hwmod;
+extern struct omap_hwmod am33xx_ehrpwm1_hwmod;
+extern struct omap_hwmod am33xx_epwmss2_hwmod;
+extern struct omap_hwmod am33xx_ecap2_hwmod;
+extern struct omap_hwmod am33xx_eqep2_hwmod;
+extern struct omap_hwmod am33xx_ehrpwm2_hwmod;
+extern struct omap_hwmod am33xx_gpio1_hwmod;
+extern struct omap_hwmod am33xx_gpio2_hwmod;
+extern struct omap_hwmod am33xx_gpio3_hwmod;
+extern struct omap_hwmod am33xx_gpmc_hwmod;
+extern struct omap_hwmod am33xx_i2c1_hwmod;
+extern struct omap_hwmod am33xx_i2c2_hwmod;
+extern struct omap_hwmod am33xx_i2c3_hwmod;
+extern struct omap_hwmod am33xx_mailbox_hwmod;
+extern struct omap_hwmod am33xx_mcasp0_hwmod;
+extern struct omap_hwmod am33xx_mcasp1_hwmod;
+extern struct omap_hwmod am33xx_mmc0_hwmod;
+extern struct omap_hwmod am33xx_mmc1_hwmod;
+extern struct omap_hwmod am33xx_mmc2_hwmod;
+extern struct omap_hwmod am33xx_rtc_hwmod;
+extern struct omap_hwmod am33xx_spi0_hwmod;
+extern struct omap_hwmod am33xx_spi1_hwmod;
+extern struct omap_hwmod am33xx_spinlock_hwmod;
+extern struct omap_hwmod am33xx_timer1_hwmod;
+extern struct omap_hwmod am33xx_timer2_hwmod;
+extern struct omap_hwmod am33xx_timer3_hwmod;
+extern struct omap_hwmod am33xx_timer4_hwmod;
+extern struct omap_hwmod am33xx_timer5_hwmod;
+extern struct omap_hwmod am33xx_timer6_hwmod;
+extern struct omap_hwmod am33xx_timer7_hwmod;
+extern struct omap_hwmod am33xx_tpcc_hwmod;
+extern struct omap_hwmod am33xx_tptc0_hwmod;
+extern struct omap_hwmod am33xx_tptc1_hwmod;
+extern struct omap_hwmod am33xx_tptc2_hwmod;
+extern struct omap_hwmod am33xx_uart1_hwmod;
+extern struct omap_hwmod am33xx_uart2_hwmod;
+extern struct omap_hwmod am33xx_uart3_hwmod;
+extern struct omap_hwmod am33xx_uart4_hwmod;
+extern struct omap_hwmod am33xx_uart5_hwmod;
+extern struct omap_hwmod am33xx_uart6_hwmod;
+extern struct omap_hwmod am33xx_wd_timer1_hwmod;
+
+extern struct omap_hwmod_class am33xx_l4_hwmod_class;
+extern struct omap_hwmod_class am33xx_wkup_m3_hwmod_class;
+extern struct omap_hwmod_class am33xx_control_hwmod_class;
+extern struct omap_hwmod_class am33xx_gpio_hwmod_class;
+extern struct omap_hwmod_class am33xx_timer_hwmod_class;
+extern struct omap_hwmod_class am33xx_epwmss_hwmod_class;
+extern struct omap_hwmod_class am33xx_ehrpwm_hwmod_class;
+extern struct omap_hwmod_class am33xx_spi_hwmod_class;
+
+extern struct omap_gpio_dev_attr gpio_dev_attr;
+extern struct omap2_mcspi_dev_attr mcspi_attrib;
+
+void omap_hwmod_am33xx_reg(void);
+void omap_hwmod_am43xx_reg(void);
+
+#endif
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c
new file mode 100644
index 0000000..e2db378
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c
@@ -0,0 +1,643 @@
+/*
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated
+ *
+ * Interconnects common for AM335x and AM43x
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/sizes.h>
+#include "omap_hwmod.h"
+#include "omap_hwmod_33xx_43xx_common_data.h"
+
+/* mpu -> l3 main */
+struct omap_hwmod_ocp_if am33xx_mpu__l3_main = {
+	.master		= &am33xx_mpu_hwmod,
+	.slave		= &am33xx_l3_main_hwmod,
+	.clk		= "dpll_mpu_m2_ck",
+	.user		= OCP_USER_MPU,
+};
+
+/* l3 main -> l3 s */
+struct omap_hwmod_ocp_if am33xx_l3_main__l3_s = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_l3_s_hwmod,
+	.clk		= "l3s_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3 s -> l4 per/ls */
+struct omap_hwmod_ocp_if am33xx_l3_s__l4_ls = {
+	.master		= &am33xx_l3_s_hwmod,
+	.slave		= &am33xx_l4_ls_hwmod,
+	.clk		= "l3s_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3 s -> l4 wkup */
+struct omap_hwmod_ocp_if am33xx_l3_s__l4_wkup = {
+	.master		= &am33xx_l3_s_hwmod,
+	.slave		= &am33xx_l4_wkup_hwmod,
+	.clk		= "l3s_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3 main -> l3 instr */
+struct omap_hwmod_ocp_if am33xx_l3_main__l3_instr = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_l3_instr_hwmod,
+	.clk		= "l3s_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu -> prcm */
+struct omap_hwmod_ocp_if am33xx_mpu__prcm = {
+	.master		= &am33xx_mpu_hwmod,
+	.slave		= &am33xx_prcm_hwmod,
+	.clk		= "dpll_mpu_m2_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3 s -> l3 main*/
+struct omap_hwmod_ocp_if am33xx_l3_s__l3_main = {
+	.master		= &am33xx_l3_s_hwmod,
+	.slave		= &am33xx_l3_main_hwmod,
+	.clk		= "l3s_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* pru-icss -> l3 main */
+struct omap_hwmod_ocp_if am33xx_pruss__l3_main = {
+	.master		= &am33xx_pruss_hwmod,
+	.slave		= &am33xx_l3_main_hwmod,
+	.clk		= "l3_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* gfx -> l3 main */
+struct omap_hwmod_ocp_if am33xx_gfx__l3_main = {
+	.master		= &am33xx_gfx_hwmod,
+	.slave		= &am33xx_l3_main_hwmod,
+	.clk		= "dpll_core_m4_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3 main -> gfx */
+struct omap_hwmod_ocp_if am33xx_l3_main__gfx = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_gfx_hwmod,
+	.clk		= "dpll_core_m4_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 wkup -> rtc */
+struct omap_hwmod_ocp_if am33xx_l4_wkup__rtc = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am33xx_rtc_hwmod,
+	.clk		= "clkdiv32k_ick",
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 per/ls -> DCAN0 */
+struct omap_hwmod_ocp_if am33xx_l4_per__dcan0 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_dcan0_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 per/ls -> DCAN1 */
+struct omap_hwmod_ocp_if am33xx_l4_per__dcan1 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_dcan1_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 per/ls -> GPIO2 */
+struct omap_hwmod_ocp_if am33xx_l4_per__gpio1 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_gpio1_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 per/ls -> gpio3 */
+struct omap_hwmod_ocp_if am33xx_l4_per__gpio2 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_gpio2_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 per/ls -> gpio4 */
+struct omap_hwmod_ocp_if am33xx_l4_per__gpio3 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_gpio3_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+struct omap_hwmod_ocp_if am33xx_cpgmac0__mdio = {
+	.master		= &am33xx_cpgmac0_hwmod,
+	.slave		= &am33xx_mdio_hwmod,
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am33xx_elm_addr_space[] = {
+	{
+		.pa_start	= 0x48080000,
+		.pa_end		= 0x48080000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_ocp_if am33xx_l4_ls__elm = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_elm_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_elm_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am33xx_epwmss0_addr_space[] = {
+	{
+		.pa_start	= 0x48300000,
+		.pa_end		= 0x48300000 + SZ_16 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss0 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_epwmss0_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_epwmss0_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+struct omap_hwmod_ocp_if am33xx_epwmss0__ecap0 = {
+	.master		= &am33xx_epwmss0_hwmod,
+	.slave		= &am33xx_ecap0_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+struct omap_hwmod_ocp_if am33xx_epwmss0__eqep0 = {
+	.master		= &am33xx_epwmss0_hwmod,
+	.slave		= &am33xx_eqep0_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+struct omap_hwmod_ocp_if am33xx_epwmss0__ehrpwm0 = {
+	.master		= &am33xx_epwmss0_hwmod,
+	.slave		= &am33xx_ehrpwm0_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+
+static struct omap_hwmod_addr_space am33xx_epwmss1_addr_space[] = {
+	{
+		.pa_start	= 0x48302000,
+		.pa_end		= 0x48302000 + SZ_16 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss1 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_epwmss1_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_epwmss1_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+struct omap_hwmod_ocp_if am33xx_epwmss1__ecap1 = {
+	.master		= &am33xx_epwmss1_hwmod,
+	.slave		= &am33xx_ecap1_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+struct omap_hwmod_ocp_if am33xx_epwmss1__eqep1 = {
+	.master		= &am33xx_epwmss1_hwmod,
+	.slave		= &am33xx_eqep1_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+struct omap_hwmod_ocp_if am33xx_epwmss1__ehrpwm1 = {
+	.master		= &am33xx_epwmss1_hwmod,
+	.slave		= &am33xx_ehrpwm1_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am33xx_epwmss2_addr_space[] = {
+	{
+		.pa_start	= 0x48304000,
+		.pa_end		= 0x48304000 + SZ_16 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss2 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_epwmss2_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_epwmss2_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+struct omap_hwmod_ocp_if am33xx_epwmss2__ecap2 = {
+	.master		= &am33xx_epwmss2_hwmod,
+	.slave		= &am33xx_ecap2_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+struct omap_hwmod_ocp_if am33xx_epwmss2__eqep2 = {
+	.master		= &am33xx_epwmss2_hwmod,
+	.slave		= &am33xx_eqep2_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+struct omap_hwmod_ocp_if am33xx_epwmss2__ehrpwm2 = {
+	.master		= &am33xx_epwmss2_hwmod,
+	.slave		= &am33xx_ehrpwm2_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+/* l3s cfg -> gpmc */
+static struct omap_hwmod_addr_space am33xx_gpmc_addr_space[] = {
+	{
+		.pa_start	= 0x50000000,
+		.pa_end		= 0x50000000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+struct omap_hwmod_ocp_if am33xx_l3_s__gpmc = {
+	.master		= &am33xx_l3_s_hwmod,
+	.slave		= &am33xx_gpmc_hwmod,
+	.clk		= "l3s_gclk",
+	.addr		= am33xx_gpmc_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* i2c2 */
+struct omap_hwmod_ocp_if am33xx_l4_per__i2c2 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_i2c2_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+struct omap_hwmod_ocp_if am33xx_l4_per__i2c3 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_i2c3_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am33xx_mailbox_addrs[] = {
+	{
+		.pa_start	= 0x480C8000,
+		.pa_end		= 0x480C8000 + (SZ_4K - 1),
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+/* l4 ls -> mailbox */
+struct omap_hwmod_ocp_if am33xx_l4_per__mailbox = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_mailbox_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_mailbox_addrs,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> spinlock */
+struct omap_hwmod_ocp_if am33xx_l4_ls__spinlock = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_spinlock_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> mcasp0 */
+static struct omap_hwmod_addr_space am33xx_mcasp0_addr_space[] = {
+	{
+		.pa_start	= 0x48038000,
+		.pa_end		= 0x48038000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_ocp_if am33xx_l4_ls__mcasp0 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_mcasp0_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_mcasp0_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> mcasp1 */
+static struct omap_hwmod_addr_space am33xx_mcasp1_addr_space[] = {
+	{
+		.pa_start	= 0x4803C000,
+		.pa_end		= 0x4803C000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_ocp_if am33xx_l4_ls__mcasp1 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_mcasp1_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_mcasp1_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> mmc0 */
+static struct omap_hwmod_addr_space am33xx_mmc0_addr_space[] = {
+	{
+		.pa_start	= 0x48060100,
+		.pa_end		= 0x48060100 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+struct omap_hwmod_ocp_if am33xx_l4_ls__mmc0 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_mmc0_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_mmc0_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> mmc1 */
+static struct omap_hwmod_addr_space am33xx_mmc1_addr_space[] = {
+	{
+		.pa_start	= 0x481d8100,
+		.pa_end		= 0x481d8100 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+struct omap_hwmod_ocp_if am33xx_l4_ls__mmc1 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_mmc1_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_mmc1_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l3 s -> mmc2 */
+static struct omap_hwmod_addr_space am33xx_mmc2_addr_space[] = {
+	{
+		.pa_start	= 0x47810100,
+		.pa_end		= 0x47810100 + SZ_64K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+struct omap_hwmod_ocp_if am33xx_l3_s__mmc2 = {
+	.master		= &am33xx_l3_s_hwmod,
+	.slave		= &am33xx_mmc2_hwmod,
+	.clk		= "l3s_gclk",
+	.addr		= am33xx_mmc2_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> mcspi0 */
+struct omap_hwmod_ocp_if am33xx_l4_ls__mcspi0 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_spi0_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> mcspi1 */
+struct omap_hwmod_ocp_if am33xx_l4_ls__mcspi1 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_spi1_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 per -> timer2 */
+struct omap_hwmod_ocp_if am33xx_l4_ls__timer2 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_timer2_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 per -> timer3 */
+struct omap_hwmod_ocp_if am33xx_l4_ls__timer3 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_timer3_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 per -> timer4 */
+struct omap_hwmod_ocp_if am33xx_l4_ls__timer4 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_timer4_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 per -> timer5 */
+struct omap_hwmod_ocp_if am33xx_l4_ls__timer5 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_timer5_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 per -> timer6 */
+struct omap_hwmod_ocp_if am33xx_l4_ls__timer6 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_timer6_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 per -> timer7 */
+struct omap_hwmod_ocp_if am33xx_l4_ls__timer7 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_timer7_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+/* l3 main -> tpcc */
+struct omap_hwmod_ocp_if am33xx_l3_main__tpcc = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_tpcc_hwmod,
+	.clk		= "l3_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+/* l3 main -> tpcc0 */
+static struct omap_hwmod_addr_space am33xx_tptc0_addr_space[] = {
+	{
+		.pa_start	= 0x49800000,
+		.pa_end		= 0x49800000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+struct omap_hwmod_ocp_if am33xx_l3_main__tptc0 = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_tptc0_hwmod,
+	.clk		= "l3_gclk",
+	.addr		= am33xx_tptc0_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l3 main -> tpcc1 */
+static struct omap_hwmod_addr_space am33xx_tptc1_addr_space[] = {
+	{
+		.pa_start	= 0x49900000,
+		.pa_end		= 0x49900000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+struct omap_hwmod_ocp_if am33xx_l3_main__tptc1 = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_tptc1_hwmod,
+	.clk		= "l3_gclk",
+	.addr		= am33xx_tptc1_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l3 main -> tpcc2 */
+static struct omap_hwmod_addr_space am33xx_tptc2_addr_space[] = {
+	{
+		.pa_start	= 0x49a00000,
+		.pa_end		= 0x49a00000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+struct omap_hwmod_ocp_if am33xx_l3_main__tptc2 = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_tptc2_hwmod,
+	.clk		= "l3_gclk",
+	.addr		= am33xx_tptc2_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> uart2 */
+struct omap_hwmod_ocp_if am33xx_l4_ls__uart2 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_uart2_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> uart3 */
+struct omap_hwmod_ocp_if am33xx_l4_ls__uart3 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_uart3_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> uart4 */
+struct omap_hwmod_ocp_if am33xx_l4_ls__uart4 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_uart4_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> uart5 */
+struct omap_hwmod_ocp_if am33xx_l4_ls__uart5 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_uart5_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> uart6 */
+struct omap_hwmod_ocp_if am33xx_l4_ls__uart6 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_uart6_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+/* l3 main -> ocmc */
+struct omap_hwmod_ocp_if am33xx_l3_main__ocmc = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_ocmcram_hwmod,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3 main -> sha0 HIB2 */
+static struct omap_hwmod_addr_space am33xx_sha0_addrs[] = {
+	{
+		.pa_start	= 0x53100000,
+		.pa_end		= 0x53100000 + SZ_512 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_ocp_if am33xx_l3_main__sha0 = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_sha0_hwmod,
+	.clk		= "sha0_fck",
+	.addr		= am33xx_sha0_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3 main -> AES0 HIB2 */
+static struct omap_hwmod_addr_space am33xx_aes0_addrs[] = {
+	{
+		.pa_start	= 0x53500000,
+		.pa_end		= 0x53500000 + SZ_1M - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+struct omap_hwmod_ocp_if am33xx_l3_main__aes0 = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_aes0_hwmod,
+	.clk		= "aes0_fck",
+	.addr		= am33xx_aes0_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
new file mode 100644
index 0000000..0f17862
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
@@ -0,0 +1,1469 @@
+/*
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated
+ *
+ * Hwmod common for AM335x and AM43x
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/platform_data/gpio-omap.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
+#include "omap_hwmod.h"
+#include "i2c.h"
+#include "mmc.h"
+#include "wd_timer.h"
+#include "cm33xx.h"
+#include "prm33xx.h"
+#include "omap_hwmod_33xx_43xx_common_data.h"
+#include "prcm43xx.h"
+
+#define CLKCTRL(oh, clkctrl) ((oh).prcm.omap4.clkctrl_offs = (clkctrl))
+#define RSTCTRL(oh, rstctrl) ((oh).prcm.omap4.rstctrl_offs = (rstctrl))
+#define RSTST(oh, rstst) ((oh).prcm.omap4.rstst_offs = (rstst))
+
+/*
+ * 'l3' class
+ * instance(s): l3_main, l3_s, l3_instr
+ */
+static struct omap_hwmod_class am33xx_l3_hwmod_class = {
+	.name		= "l3",
+};
+
+struct omap_hwmod am33xx_l3_main_hwmod = {
+	.name		= "l3_main",
+	.class		= &am33xx_l3_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.flags		= HWMOD_INIT_NO_IDLE,
+	.main_clk	= "l3_gclk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* l3_s */
+struct omap_hwmod am33xx_l3_s_hwmod = {
+	.name		= "l3_s",
+	.class		= &am33xx_l3_hwmod_class,
+	.clkdm_name	= "l3s_clkdm",
+};
+
+/* l3_instr */
+struct omap_hwmod am33xx_l3_instr_hwmod = {
+	.name		= "l3_instr",
+	.class		= &am33xx_l3_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.flags		= HWMOD_INIT_NO_IDLE,
+	.main_clk	= "l3_gclk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'l4' class
+ * instance(s): l4_ls, l4_hs, l4_wkup, l4_fw
+ */
+struct omap_hwmod_class am33xx_l4_hwmod_class = {
+	.name		= "l4",
+};
+
+/* l4_ls */
+struct omap_hwmod am33xx_l4_ls_hwmod = {
+	.name		= "l4_ls",
+	.class		= &am33xx_l4_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.flags		= HWMOD_INIT_NO_IDLE,
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* l4_wkup */
+struct omap_hwmod am33xx_l4_wkup_hwmod = {
+	.name		= "l4_wkup",
+	.class		= &am33xx_l4_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= HWMOD_INIT_NO_IDLE,
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'mpu' class
+ */
+static struct omap_hwmod_class am33xx_mpu_hwmod_class = {
+	.name	= "mpu",
+};
+
+struct omap_hwmod am33xx_mpu_hwmod = {
+	.name		= "mpu",
+	.class		= &am33xx_mpu_hwmod_class,
+	.clkdm_name	= "mpu_clkdm",
+	.flags		= HWMOD_INIT_NO_IDLE,
+	.main_clk	= "dpll_mpu_m2_ck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'wakeup m3' class
+ * Wakeup controller sub-system under wakeup domain
+ */
+struct omap_hwmod_class am33xx_wkup_m3_hwmod_class = {
+	.name		= "wkup_m3",
+};
+
+/*
+ * 'pru-icss' class
+ * Programmable Real-Time Unit and Industrial Communication Subsystem
+ */
+static struct omap_hwmod_class am33xx_pruss_hwmod_class = {
+	.name	= "pruss",
+};
+
+static struct omap_hwmod_rst_info am33xx_pruss_resets[] = {
+	{ .name = "pruss", .rst_shift = 1 },
+};
+
+/* pru-icss */
+/* Pseudo hwmod for reset control purpose only */
+struct omap_hwmod am33xx_pruss_hwmod = {
+	.name		= "pruss",
+	.class		= &am33xx_pruss_hwmod_class,
+	.clkdm_name	= "pruss_ocp_clkdm",
+	.main_clk	= "pruss_ocp_gclk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.rst_lines	= am33xx_pruss_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(am33xx_pruss_resets),
+};
+
+/* gfx */
+/* Pseudo hwmod for reset control purpose only */
+static struct omap_hwmod_class am33xx_gfx_hwmod_class = {
+	.name	= "gfx",
+};
+
+static struct omap_hwmod_rst_info am33xx_gfx_resets[] = {
+	{ .name = "gfx", .rst_shift = 0, .st_shift = 0},
+};
+
+struct omap_hwmod am33xx_gfx_hwmod = {
+	.name		= "gfx",
+	.class		= &am33xx_gfx_hwmod_class,
+	.clkdm_name	= "gfx_l3_clkdm",
+	.main_clk	= "gfx_fck_div_ck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.rst_lines	= am33xx_gfx_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(am33xx_gfx_resets),
+};
+
+/*
+ * 'prcm' class
+ * power and reset manager (whole prcm infrastructure)
+ */
+static struct omap_hwmod_class am33xx_prcm_hwmod_class = {
+	.name	= "prcm",
+};
+
+/* prcm */
+struct omap_hwmod am33xx_prcm_hwmod = {
+	.name		= "prcm",
+	.class		= &am33xx_prcm_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+};
+
+/*
+ * 'aes0' class
+ */
+static struct omap_hwmod_class_sysconfig am33xx_aes0_sysc = {
+	.rev_offs	= 0x80,
+	.sysc_offs	= 0x84,
+	.syss_offs	= 0x88,
+	.sysc_flags	= SYSS_HAS_RESET_STATUS,
+};
+
+static struct omap_hwmod_class am33xx_aes0_hwmod_class = {
+	.name		= "aes0",
+	.sysc		= &am33xx_aes0_sysc,
+};
+
+struct omap_hwmod am33xx_aes0_hwmod = {
+	.name		= "aes",
+	.class		= &am33xx_aes0_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.main_clk	= "aes0_fck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* sha0 HIB2 (the 'P' (public) device) */
+static struct omap_hwmod_class_sysconfig am33xx_sha0_sysc = {
+	.rev_offs	= 0x100,
+	.sysc_offs	= 0x110,
+	.syss_offs	= 0x114,
+	.sysc_flags	= SYSS_HAS_RESET_STATUS,
+};
+
+static struct omap_hwmod_class am33xx_sha0_hwmod_class = {
+	.name		= "sha0",
+	.sysc		= &am33xx_sha0_sysc,
+};
+
+struct omap_hwmod am33xx_sha0_hwmod = {
+	.name		= "sham",
+	.class		= &am33xx_sha0_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.main_clk	= "l3_gclk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* ocmcram */
+static struct omap_hwmod_class am33xx_ocmcram_hwmod_class = {
+	.name = "ocmcram",
+};
+
+struct omap_hwmod am33xx_ocmcram_hwmod = {
+	.name		= "ocmcram",
+	.class		= &am33xx_ocmcram_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.flags		= HWMOD_INIT_NO_IDLE,
+	.main_clk	= "l3_gclk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* 'smartreflex' class */
+static struct omap_hwmod_class am33xx_smartreflex_hwmod_class = {
+	.name		= "smartreflex",
+};
+
+/* smartreflex0 */
+struct omap_hwmod am33xx_smartreflex0_hwmod = {
+	.name		= "smartreflex0",
+	.class		= &am33xx_smartreflex_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.main_clk	= "smartreflex0_fck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* smartreflex1 */
+struct omap_hwmod am33xx_smartreflex1_hwmod = {
+	.name		= "smartreflex1",
+	.class		= &am33xx_smartreflex_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.main_clk	= "smartreflex1_fck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'control' module class
+ */
+struct omap_hwmod_class am33xx_control_hwmod_class = {
+	.name		= "control",
+};
+
+/*
+ * 'cpgmac' class
+ * cpsw/cpgmac sub system
+ */
+static struct omap_hwmod_class_sysconfig am33xx_cpgmac_sysc = {
+	.rev_offs	= 0x0,
+	.sysc_offs	= 0x8,
+	.syss_offs	= 0x4,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+			   SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | MSTANDBY_FORCE |
+			   MSTANDBY_NO),
+	.sysc_fields	= &omap_hwmod_sysc_type3,
+};
+
+static struct omap_hwmod_class am33xx_cpgmac0_hwmod_class = {
+	.name		= "cpgmac0",
+	.sysc		= &am33xx_cpgmac_sysc,
+};
+
+struct omap_hwmod am33xx_cpgmac0_hwmod = {
+	.name		= "cpgmac0",
+	.class		= &am33xx_cpgmac0_hwmod_class,
+	.clkdm_name	= "cpsw_125mhz_clkdm",
+	.flags		= (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY),
+	.main_clk	= "cpsw_125mhz_gclk",
+	.mpu_rt_idx	= 1,
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * mdio class
+ */
+static struct omap_hwmod_class am33xx_mdio_hwmod_class = {
+	.name		= "davinci_mdio",
+};
+
+struct omap_hwmod am33xx_mdio_hwmod = {
+	.name		= "davinci_mdio",
+	.class		= &am33xx_mdio_hwmod_class,
+	.clkdm_name	= "cpsw_125mhz_clkdm",
+	.main_clk	= "cpsw_125mhz_gclk",
+};
+
+/*
+ * dcan class
+ */
+static struct omap_hwmod_class am33xx_dcan_hwmod_class = {
+	.name = "d_can",
+};
+
+/* dcan0 */
+struct omap_hwmod am33xx_dcan0_hwmod = {
+	.name		= "d_can0",
+	.class		= &am33xx_dcan_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "dcan0_fck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* dcan1 */
+struct omap_hwmod am33xx_dcan1_hwmod = {
+	.name		= "d_can1",
+	.class		= &am33xx_dcan_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "dcan1_fck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* elm */
+static struct omap_hwmod_class_sysconfig am33xx_elm_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+			SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class am33xx_elm_hwmod_class = {
+	.name		= "elm",
+	.sysc		= &am33xx_elm_sysc,
+};
+
+struct omap_hwmod am33xx_elm_hwmod = {
+	.name		= "elm",
+	.class		= &am33xx_elm_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* pwmss  */
+static struct omap_hwmod_class_sysconfig am33xx_epwmss_sysc = {
+	.rev_offs	= 0x0,
+	.sysc_offs	= 0x4,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
+			MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+struct omap_hwmod_class am33xx_epwmss_hwmod_class = {
+	.name		= "epwmss",
+	.sysc		= &am33xx_epwmss_sysc,
+};
+
+static struct omap_hwmod_class am33xx_ecap_hwmod_class = {
+	.name		= "ecap",
+};
+
+static struct omap_hwmod_class am33xx_eqep_hwmod_class = {
+	.name		= "eqep",
+};
+
+struct omap_hwmod_class am33xx_ehrpwm_hwmod_class = {
+	.name		= "ehrpwm",
+};
+
+/* epwmss0 */
+struct omap_hwmod am33xx_epwmss0_hwmod = {
+	.name		= "epwmss0",
+	.class		= &am33xx_epwmss_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* ecap0 */
+struct omap_hwmod am33xx_ecap0_hwmod = {
+	.name		= "ecap0",
+	.class		= &am33xx_ecap_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+};
+
+/* eqep0 */
+struct omap_hwmod am33xx_eqep0_hwmod = {
+	.name		= "eqep0",
+	.class		= &am33xx_eqep_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+};
+
+/* ehrpwm0 */
+struct omap_hwmod am33xx_ehrpwm0_hwmod = {
+	.name		= "ehrpwm0",
+	.class		= &am33xx_ehrpwm_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+};
+
+/* epwmss1 */
+struct omap_hwmod am33xx_epwmss1_hwmod = {
+	.name		= "epwmss1",
+	.class		= &am33xx_epwmss_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* ecap1 */
+struct omap_hwmod am33xx_ecap1_hwmod = {
+	.name		= "ecap1",
+	.class		= &am33xx_ecap_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+};
+
+/* eqep1 */
+struct omap_hwmod am33xx_eqep1_hwmod = {
+	.name		= "eqep1",
+	.class		= &am33xx_eqep_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+};
+
+/* ehrpwm1 */
+struct omap_hwmod am33xx_ehrpwm1_hwmod = {
+	.name		= "ehrpwm1",
+	.class		= &am33xx_ehrpwm_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+};
+
+/* epwmss2 */
+struct omap_hwmod am33xx_epwmss2_hwmod = {
+	.name		= "epwmss2",
+	.class		= &am33xx_epwmss_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* ecap2 */
+struct omap_hwmod am33xx_ecap2_hwmod = {
+	.name		= "ecap2",
+	.class		= &am33xx_ecap_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+};
+
+/* eqep2 */
+struct omap_hwmod am33xx_eqep2_hwmod = {
+	.name		= "eqep2",
+	.class		= &am33xx_eqep_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+};
+
+/* ehrpwm2 */
+struct omap_hwmod am33xx_ehrpwm2_hwmod = {
+	.name		= "ehrpwm2",
+	.class		= &am33xx_ehrpwm_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+};
+
+/*
+ * 'gpio' class: for gpio 0,1,2,3
+ */
+static struct omap_hwmod_class_sysconfig am33xx_gpio_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0114,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP |
+			  SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			  SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			  SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class am33xx_gpio_hwmod_class = {
+	.name		= "gpio",
+	.sysc		= &am33xx_gpio_sysc,
+	.rev		= 2,
+};
+
+struct omap_gpio_dev_attr gpio_dev_attr = {
+	.bank_width	= 32,
+	.dbck_flag	= true,
+};
+
+/* gpio1 */
+static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio1_dbclk" },
+};
+
+struct omap_hwmod am33xx_gpio1_hwmod = {
+	.name		= "gpio2",
+	.class		= &am33xx_gpio_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.opt_clks	= gpio1_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio1_opt_clks),
+	.dev_attr	= &gpio_dev_attr,
+};
+
+/* gpio2 */
+static struct omap_hwmod_opt_clk gpio2_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio2_dbclk" },
+};
+
+struct omap_hwmod am33xx_gpio2_hwmod = {
+	.name		= "gpio3",
+	.class		= &am33xx_gpio_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.opt_clks	= gpio2_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio2_opt_clks),
+	.dev_attr	= &gpio_dev_attr,
+};
+
+/* gpio3 */
+static struct omap_hwmod_opt_clk gpio3_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio3_dbclk" },
+};
+
+struct omap_hwmod am33xx_gpio3_hwmod = {
+	.name		= "gpio4",
+	.class		= &am33xx_gpio_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.opt_clks	= gpio3_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio3_opt_clks),
+	.dev_attr	= &gpio_dev_attr,
+};
+
+/* gpmc */
+static struct omap_hwmod_class_sysconfig gpmc_sysc = {
+	.rev_offs	= 0x0,
+	.sysc_offs	= 0x10,
+	.syss_offs	= 0x14,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
+			SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class am33xx_gpmc_hwmod_class = {
+	.name		= "gpmc",
+	.sysc		= &gpmc_sysc,
+};
+
+struct omap_hwmod am33xx_gpmc_hwmod = {
+	.name		= "gpmc",
+	.class		= &am33xx_gpmc_hwmod_class,
+	.clkdm_name	= "l3s_clkdm",
+	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.main_clk	= "l3s_gclk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* 'i2c' class */
+static struct omap_hwmod_class_sysconfig am33xx_i2c_sysc = {
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0090,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			  SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			  SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			  SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class i2c_class = {
+	.name		= "i2c",
+	.sysc		= &am33xx_i2c_sysc,
+	.rev		= OMAP_I2C_IP_VERSION_2,
+	.reset		= &omap_i2c_reset,
+};
+
+static struct omap_i2c_dev_attr i2c_dev_attr = {
+	.flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE,
+};
+
+/* i2c1 */
+struct omap_hwmod am33xx_i2c1_hwmod = {
+	.name		= "i2c1",
+	.class		= &i2c_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
+	.main_clk	= "dpll_per_m2_div4_wkupdm_ck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.dev_attr	= &i2c_dev_attr,
+};
+
+/* i2c1 */
+struct omap_hwmod am33xx_i2c2_hwmod = {
+	.name		= "i2c2",
+	.class		= &i2c_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4 = {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.dev_attr	= &i2c_dev_attr,
+};
+
+/* i2c3 */
+struct omap_hwmod am33xx_i2c3_hwmod = {
+	.name		= "i2c3",
+	.class		= &i2c_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.dev_attr	= &i2c_dev_attr,
+};
+
+/*
+ * 'mailbox' class
+ * mailbox module allowing communication between the on-chip processors using a
+ * queued mailbox-interrupt mechanism.
+ */
+static struct omap_hwmod_class_sysconfig am33xx_mailbox_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE |
+			  SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class am33xx_mailbox_hwmod_class = {
+	.name	= "mailbox",
+	.sysc	= &am33xx_mailbox_sysc,
+};
+
+struct omap_hwmod am33xx_mailbox_hwmod = {
+	.name		= "mailbox",
+	.class		= &am33xx_mailbox_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+	.prcm = {
+		.omap4 = {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'mcasp' class
+ */
+static struct omap_hwmod_class_sysconfig am33xx_mcasp_sysc = {
+	.rev_offs	= 0x0,
+	.sysc_offs	= 0x4,
+	.sysc_flags	= SYSC_HAS_SIDLEMODE,
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type3,
+};
+
+static struct omap_hwmod_class am33xx_mcasp_hwmod_class = {
+	.name		= "mcasp",
+	.sysc		= &am33xx_mcasp_sysc,
+};
+
+/* mcasp0 */
+struct omap_hwmod am33xx_mcasp0_hwmod = {
+	.name		= "mcasp0",
+	.class		= &am33xx_mcasp_hwmod_class,
+	.clkdm_name	= "l3s_clkdm",
+	.main_clk	= "mcasp0_fck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* mcasp1 */
+struct omap_hwmod am33xx_mcasp1_hwmod = {
+	.name		= "mcasp1",
+	.class		= &am33xx_mcasp_hwmod_class,
+	.clkdm_name	= "l3s_clkdm",
+	.main_clk	= "mcasp1_fck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* 'mmc' class */
+static struct omap_hwmod_class_sysconfig am33xx_mmc_sysc = {
+	.rev_offs	= 0x1fc,
+	.sysc_offs	= 0x10,
+	.syss_offs	= 0x14,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+			  SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			  SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class am33xx_mmc_hwmod_class = {
+	.name		= "mmc",
+	.sysc		= &am33xx_mmc_sysc,
+};
+
+/* mmc0 */
+static struct omap_mmc_dev_attr am33xx_mmc0_dev_attr = {
+	.flags		= OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
+};
+
+struct omap_hwmod am33xx_mmc0_hwmod = {
+	.name		= "mmc1",
+	.class		= &am33xx_mmc_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "mmc_clk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.dev_attr	= &am33xx_mmc0_dev_attr,
+};
+
+/* mmc1 */
+static struct omap_mmc_dev_attr am33xx_mmc1_dev_attr = {
+	.flags		= OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
+};
+
+struct omap_hwmod am33xx_mmc1_hwmod = {
+	.name		= "mmc2",
+	.class		= &am33xx_mmc_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "mmc_clk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.dev_attr	= &am33xx_mmc1_dev_attr,
+};
+
+/* mmc2 */
+static struct omap_mmc_dev_attr am33xx_mmc2_dev_attr = {
+	.flags		= OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
+};
+struct omap_hwmod am33xx_mmc2_hwmod = {
+	.name		= "mmc3",
+	.class		= &am33xx_mmc_hwmod_class,
+	.clkdm_name	= "l3s_clkdm",
+	.main_clk	= "mmc_clk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.dev_attr	= &am33xx_mmc2_dev_attr,
+};
+
+/*
+ * 'rtc' class
+ * rtc subsystem
+ */
+static struct omap_hwmod_class_sysconfig am33xx_rtc_sysc = {
+	.rev_offs	= 0x0074,
+	.sysc_offs	= 0x0078,
+	.sysc_flags	= SYSC_HAS_SIDLEMODE,
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO |
+			  SIDLE_SMART | SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type3,
+};
+
+static struct omap_hwmod_class am33xx_rtc_hwmod_class = {
+	.name		= "rtc",
+	.sysc		= &am33xx_rtc_sysc,
+};
+
+struct omap_hwmod am33xx_rtc_hwmod = {
+	.name		= "rtc",
+	.class		= &am33xx_rtc_hwmod_class,
+	.clkdm_name	= "l4_rtc_clkdm",
+	.main_clk	= "clk_32768_ck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* 'spi' class */
+static struct omap_hwmod_class_sysconfig am33xx_mcspi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0110,
+	.syss_offs	= 0x0114,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+			  SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			  SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class am33xx_spi_hwmod_class = {
+	.name		= "mcspi",
+	.sysc		= &am33xx_mcspi_sysc,
+	.rev		= OMAP4_MCSPI_REV,
+};
+
+/* spi0 */
+struct omap2_mcspi_dev_attr mcspi_attrib = {
+	.num_chipselect	= 2,
+};
+struct omap_hwmod am33xx_spi0_hwmod = {
+	.name		= "spi0",
+	.class		= &am33xx_spi_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.dev_attr	= &mcspi_attrib,
+};
+
+/* spi1 */
+struct omap_hwmod am33xx_spi1_hwmod = {
+	.name		= "spi1",
+	.class		= &am33xx_spi_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.dev_attr	= &mcspi_attrib,
+};
+
+/*
+ * 'spinlock' class
+ * spinlock provides hardware assistance for synchronizing the
+ * processes running on multiple processors
+ */
+
+static struct omap_hwmod_class_sysconfig am33xx_spinlock_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class am33xx_spinlock_hwmod_class = {
+	.name		= "spinlock",
+	.sysc		= &am33xx_spinlock_sysc,
+};
+
+struct omap_hwmod am33xx_spinlock_hwmod = {
+	.name		= "spinlock",
+	.class		= &am33xx_spinlock_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* 'timer 2-7' class */
+static struct omap_hwmod_class_sysconfig am33xx_timer_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			  SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+struct omap_hwmod_class am33xx_timer_hwmod_class = {
+	.name		= "timer",
+	.sysc		= &am33xx_timer_sysc,
+};
+
+/* timer1 1ms */
+static struct omap_hwmod_class_sysconfig am33xx_timer1ms_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+			SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class am33xx_timer1ms_hwmod_class = {
+	.name		= "timer",
+	.sysc		= &am33xx_timer1ms_sysc,
+};
+
+struct omap_hwmod am33xx_timer1_hwmod = {
+	.name		= "timer1",
+	.class		= &am33xx_timer1ms_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.main_clk	= "timer1_fck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+struct omap_hwmod am33xx_timer2_hwmod = {
+	.name		= "timer2",
+	.class		= &am33xx_timer_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "timer2_fck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+struct omap_hwmod am33xx_timer3_hwmod = {
+	.name		= "timer3",
+	.class		= &am33xx_timer_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "timer3_fck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+struct omap_hwmod am33xx_timer4_hwmod = {
+	.name		= "timer4",
+	.class		= &am33xx_timer_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "timer4_fck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+struct omap_hwmod am33xx_timer5_hwmod = {
+	.name		= "timer5",
+	.class		= &am33xx_timer_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "timer5_fck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+struct omap_hwmod am33xx_timer6_hwmod = {
+	.name		= "timer6",
+	.class		= &am33xx_timer_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "timer6_fck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+struct omap_hwmod am33xx_timer7_hwmod = {
+	.name		= "timer7",
+	.class		= &am33xx_timer_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "timer7_fck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* tpcc */
+static struct omap_hwmod_class am33xx_tpcc_hwmod_class = {
+	.name		= "tpcc",
+};
+
+struct omap_hwmod am33xx_tpcc_hwmod = {
+	.name		= "tpcc",
+	.class		= &am33xx_tpcc_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.main_clk	= "l3_gclk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod_class_sysconfig am33xx_tptc_sysc = {
+	.rev_offs	= 0x0,
+	.sysc_offs	= 0x10,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			  SYSC_HAS_MIDLEMODE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_SMART | MSTANDBY_FORCE),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+/* 'tptc' class */
+static struct omap_hwmod_class am33xx_tptc_hwmod_class = {
+	.name		= "tptc",
+	.sysc		= &am33xx_tptc_sysc,
+};
+
+/* tptc0 */
+struct omap_hwmod am33xx_tptc0_hwmod = {
+	.name		= "tptc0",
+	.class		= &am33xx_tptc_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.flags		= HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
+	.main_clk	= "l3_gclk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* tptc1 */
+struct omap_hwmod am33xx_tptc1_hwmod = {
+	.name		= "tptc1",
+	.class		= &am33xx_tptc_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.flags		= (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY),
+	.main_clk	= "l3_gclk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* tptc2 */
+struct omap_hwmod am33xx_tptc2_hwmod = {
+	.name		= "tptc2",
+	.class		= &am33xx_tptc_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.flags		= (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY),
+	.main_clk	= "l3_gclk",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* 'uart' class */
+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 |
+			  SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class uart_class = {
+	.name		= "uart",
+	.sysc		= &uart_sysc,
+};
+
+struct omap_hwmod am33xx_uart1_hwmod = {
+	.name		= "uart1",
+	.class		= &uart_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= DEBUG_AM33XXUART1_FLAGS | HWMOD_SWSUP_SIDLE_ACT,
+	.main_clk	= "dpll_per_m2_div4_wkupdm_ck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+struct omap_hwmod am33xx_uart2_hwmod = {
+	.name		= "uart2",
+	.class		= &uart_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.flags		= HWMOD_SWSUP_SIDLE_ACT,
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* uart3 */
+struct omap_hwmod am33xx_uart3_hwmod = {
+	.name		= "uart3",
+	.class		= &uart_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.flags		= HWMOD_SWSUP_SIDLE_ACT,
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+struct omap_hwmod am33xx_uart4_hwmod = {
+	.name		= "uart4",
+	.class		= &uart_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.flags		= HWMOD_SWSUP_SIDLE_ACT,
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+struct omap_hwmod am33xx_uart5_hwmod = {
+	.name		= "uart5",
+	.class		= &uart_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.flags		= HWMOD_SWSUP_SIDLE_ACT,
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+struct omap_hwmod am33xx_uart6_hwmod = {
+	.name		= "uart6",
+	.class		= &uart_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.flags		= HWMOD_SWSUP_SIDLE_ACT,
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* 'wd_timer' class */
+static struct omap_hwmod_class_sysconfig wdt_sysc = {
+	.rev_offs	= 0x0,
+	.sysc_offs	= 0x10,
+	.syss_offs	= 0x14,
+	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_SIDLEMODE |
+			SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class am33xx_wd_timer_hwmod_class = {
+	.name		= "wd_timer",
+	.sysc		= &wdt_sysc,
+	.pre_shutdown	= &omap2_wd_timer_disable,
+};
+
+/*
+ * XXX: device.c file uses hardcoded name for watchdog timer
+ * driver "wd_timer2, so we are also using same name as of now...
+ */
+struct omap_hwmod am33xx_wd_timer1_hwmod = {
+	.name		= "wd_timer2",
+	.class		= &am33xx_wd_timer_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= HWMOD_SWSUP_SIDLE,
+	.main_clk	= "wdt1_fck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static void omap_hwmod_am33xx_clkctrl(void)
+{
+	CLKCTRL(am33xx_uart2_hwmod, AM33XX_CM_PER_UART1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_uart3_hwmod, AM33XX_CM_PER_UART2_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_uart4_hwmod, AM33XX_CM_PER_UART3_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_uart5_hwmod, AM33XX_CM_PER_UART4_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_uart6_hwmod, AM33XX_CM_PER_UART5_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_dcan0_hwmod, AM33XX_CM_PER_DCAN0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_dcan1_hwmod, AM33XX_CM_PER_DCAN1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_elm_hwmod, AM33XX_CM_PER_ELM_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_epwmss0_hwmod, AM33XX_CM_PER_EPWMSS0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_epwmss1_hwmod, AM33XX_CM_PER_EPWMSS1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_epwmss2_hwmod, AM33XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_gpio1_hwmod, AM33XX_CM_PER_GPIO1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_gpio2_hwmod, AM33XX_CM_PER_GPIO2_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_gpio3_hwmod, AM33XX_CM_PER_GPIO3_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_i2c2_hwmod, AM33XX_CM_PER_I2C1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_i2c3_hwmod, AM33XX_CM_PER_I2C2_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_mailbox_hwmod, AM33XX_CM_PER_MAILBOX0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_mcasp0_hwmod, AM33XX_CM_PER_MCASP0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_mcasp1_hwmod, AM33XX_CM_PER_MCASP1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_mmc0_hwmod, AM33XX_CM_PER_MMC0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_mmc1_hwmod, AM33XX_CM_PER_MMC1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_spi0_hwmod, AM33XX_CM_PER_SPI0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_spi1_hwmod, AM33XX_CM_PER_SPI1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_spinlock_hwmod, AM33XX_CM_PER_SPINLOCK_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_timer2_hwmod, AM33XX_CM_PER_TIMER2_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_timer3_hwmod, AM33XX_CM_PER_TIMER3_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_timer4_hwmod, AM33XX_CM_PER_TIMER4_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_timer5_hwmod, AM33XX_CM_PER_TIMER5_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_timer6_hwmod, AM33XX_CM_PER_TIMER6_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_timer7_hwmod, AM33XX_CM_PER_TIMER7_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_smartreflex0_hwmod,
+		AM33XX_CM_WKUP_SMARTREFLEX0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_smartreflex1_hwmod,
+		AM33XX_CM_WKUP_SMARTREFLEX1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_uart1_hwmod, AM33XX_CM_WKUP_UART0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_timer1_hwmod, AM33XX_CM_WKUP_TIMER1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_i2c1_hwmod, AM33XX_CM_WKUP_I2C0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_wd_timer1_hwmod, AM33XX_CM_WKUP_WDT1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_rtc_hwmod, AM33XX_CM_RTC_RTC_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_mmc2_hwmod, AM33XX_CM_PER_MMC2_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_gpmc_hwmod, AM33XX_CM_PER_GPMC_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_l4_ls_hwmod, AM33XX_CM_PER_L4LS_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_l4_wkup_hwmod, AM33XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_l3_main_hwmod, AM33XX_CM_PER_L3_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_tpcc_hwmod, AM33XX_CM_PER_TPCC_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_tptc0_hwmod, AM33XX_CM_PER_TPTC0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_tptc1_hwmod, AM33XX_CM_PER_TPTC1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_tptc2_hwmod, AM33XX_CM_PER_TPTC2_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_gfx_hwmod, AM33XX_CM_GFX_GFX_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_cpgmac0_hwmod, AM33XX_CM_PER_CPGMAC0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_pruss_hwmod, AM33XX_CM_PER_PRUSS_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_mpu_hwmod , AM33XX_CM_MPU_MPU_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_l3_instr_hwmod , AM33XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_ocmcram_hwmod , AM33XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_sha0_hwmod , AM33XX_CM_PER_SHA0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_aes0_hwmod , AM33XX_CM_PER_AES0_CLKCTRL_OFFSET);
+}
+
+static void omap_hwmod_am33xx_rst(void)
+{
+	RSTCTRL(am33xx_pruss_hwmod, AM33XX_RM_PER_RSTCTRL_OFFSET);
+	RSTCTRL(am33xx_gfx_hwmod, AM33XX_RM_GFX_RSTCTRL_OFFSET);
+	RSTST(am33xx_gfx_hwmod, AM33XX_RM_GFX_RSTST_OFFSET);
+}
+
+void omap_hwmod_am33xx_reg(void)
+{
+	omap_hwmod_am33xx_clkctrl();
+	omap_hwmod_am33xx_rst();
+}
+
+static void omap_hwmod_am43xx_clkctrl(void)
+{
+	CLKCTRL(am33xx_uart2_hwmod, AM43XX_CM_PER_UART1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_uart3_hwmod, AM43XX_CM_PER_UART2_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_uart4_hwmod, AM43XX_CM_PER_UART3_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_uart5_hwmod, AM43XX_CM_PER_UART4_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_uart6_hwmod, AM43XX_CM_PER_UART5_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_dcan0_hwmod, AM43XX_CM_PER_DCAN0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_dcan1_hwmod, AM43XX_CM_PER_DCAN1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_elm_hwmod, AM43XX_CM_PER_ELM_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_epwmss0_hwmod, AM43XX_CM_PER_EPWMSS0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_epwmss1_hwmod, AM43XX_CM_PER_EPWMSS1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_epwmss2_hwmod, AM43XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_gpio1_hwmod, AM43XX_CM_PER_GPIO1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_gpio2_hwmod, AM43XX_CM_PER_GPIO2_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_gpio3_hwmod, AM43XX_CM_PER_GPIO3_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_i2c2_hwmod, AM43XX_CM_PER_I2C1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_i2c3_hwmod, AM43XX_CM_PER_I2C2_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_mailbox_hwmod, AM43XX_CM_PER_MAILBOX0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_mcasp0_hwmod, AM43XX_CM_PER_MCASP0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_mcasp1_hwmod, AM43XX_CM_PER_MCASP1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_mmc0_hwmod, AM43XX_CM_PER_MMC0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_mmc1_hwmod, AM43XX_CM_PER_MMC1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_spi0_hwmod, AM43XX_CM_PER_SPI0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_spi1_hwmod, AM43XX_CM_PER_SPI1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_spinlock_hwmod, AM43XX_CM_PER_SPINLOCK_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_timer2_hwmod, AM43XX_CM_PER_TIMER2_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_timer3_hwmod, AM43XX_CM_PER_TIMER3_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_timer4_hwmod, AM43XX_CM_PER_TIMER4_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_timer5_hwmod, AM43XX_CM_PER_TIMER5_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_timer6_hwmod, AM43XX_CM_PER_TIMER6_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_timer7_hwmod, AM43XX_CM_PER_TIMER7_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_smartreflex0_hwmod,
+		AM43XX_CM_WKUP_SMARTREFLEX0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_smartreflex1_hwmod,
+		AM43XX_CM_WKUP_SMARTREFLEX1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_uart1_hwmod, AM43XX_CM_WKUP_UART0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_timer1_hwmod, AM43XX_CM_WKUP_TIMER1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_i2c1_hwmod, AM43XX_CM_WKUP_I2C0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_wd_timer1_hwmod, AM43XX_CM_WKUP_WDT1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_rtc_hwmod, AM43XX_CM_RTC_RTC_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_mmc2_hwmod, AM43XX_CM_PER_MMC2_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_gpmc_hwmod, AM43XX_CM_PER_GPMC_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_l4_ls_hwmod, AM43XX_CM_PER_L4LS_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_l4_wkup_hwmod, AM43XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_l3_main_hwmod, AM43XX_CM_PER_L3_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_tpcc_hwmod, AM43XX_CM_PER_TPCC_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_tptc0_hwmod, AM43XX_CM_PER_TPTC0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_tptc1_hwmod, AM43XX_CM_PER_TPTC1_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_tptc2_hwmod, AM43XX_CM_PER_TPTC2_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_gfx_hwmod, AM43XX_CM_GFX_GFX_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_cpgmac0_hwmod, AM43XX_CM_PER_CPGMAC0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_pruss_hwmod, AM43XX_CM_PER_PRUSS_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_mpu_hwmod , AM43XX_CM_MPU_MPU_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_l3_instr_hwmod , AM43XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_ocmcram_hwmod , AM43XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_sha0_hwmod , AM43XX_CM_PER_SHA0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_aes0_hwmod , AM43XX_CM_PER_AES0_CLKCTRL_OFFSET);
+}
+
+static void omap_hwmod_am43xx_rst(void)
+{
+	RSTCTRL(am33xx_pruss_hwmod, AM43XX_RM_PER_RSTCTRL_OFFSET);
+	RSTCTRL(am33xx_gfx_hwmod, AM43XX_RM_GFX_RSTCTRL_OFFSET);
+	RSTST(am33xx_gfx_hwmod, AM43XX_RM_GFX_RSTST_OFFSET);
+}
+
+void omap_hwmod_am43xx_reg(void)
+{
+	omap_hwmod_am43xx_clkctrl();
+	omap_hwmod_am43xx_rst();
+}
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
index 215894f..6b406ca 100644
--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
@@ -29,6 +29,7 @@
 #include "i2c.h"
 #include "mmc.h"
 #include "wd_timer.h"
+#include "omap_hwmod_33xx_43xx_common_data.h"
 
 /*
  * IP blocks
@@ -52,7 +53,7 @@
 	.name		= "emif",
 	.class		= &am33xx_emif_hwmod_class,
 	.clkdm_name	= "l3_clkdm",
-	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.flags		= HWMOD_INIT_NO_IDLE,
 	.main_clk	= "dpll_ddr_m2_div2_ck",
 	.prcm		= {
 		.omap4	= {
@@ -62,79 +63,12 @@
 	},
 };
 
-/*
- * 'l3' class
- * instance(s): l3_main, l3_s, l3_instr
- */
-static struct omap_hwmod_class am33xx_l3_hwmod_class = {
-	.name		= "l3",
-};
-
-static struct omap_hwmod am33xx_l3_main_hwmod = {
-	.name		= "l3_main",
-	.class		= &am33xx_l3_hwmod_class,
-	.clkdm_name	= "l3_clkdm",
-	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
-	.main_clk	= "l3_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_L3_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* l3_s */
-static struct omap_hwmod am33xx_l3_s_hwmod = {
-	.name		= "l3_s",
-	.class		= &am33xx_l3_hwmod_class,
-	.clkdm_name	= "l3s_clkdm",
-};
-
-/* l3_instr */
-static struct omap_hwmod am33xx_l3_instr_hwmod = {
-	.name		= "l3_instr",
-	.class		= &am33xx_l3_hwmod_class,
-	.clkdm_name	= "l3_clkdm",
-	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
-	.main_clk	= "l3_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/*
- * 'l4' class
- * instance(s): l4_ls, l4_hs, l4_wkup, l4_fw
- */
-static struct omap_hwmod_class am33xx_l4_hwmod_class = {
-	.name		= "l4",
-};
-
-/* l4_ls */
-static struct omap_hwmod am33xx_l4_ls_hwmod = {
-	.name		= "l4_ls",
-	.class		= &am33xx_l4_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
-	.main_clk	= "l4ls_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_L4LS_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
 /* l4_hs */
 static struct omap_hwmod am33xx_l4_hs_hwmod = {
 	.name		= "l4_hs",
 	.class		= &am33xx_l4_hwmod_class,
 	.clkdm_name	= "l4hs_clkdm",
-	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.flags		= HWMOD_INIT_NO_IDLE,
 	.main_clk	= "l4hs_gclk",
 	.prcm		= {
 		.omap4	= {
@@ -144,50 +78,6 @@
 	},
 };
 
-
-/* l4_wkup */
-static struct omap_hwmod am33xx_l4_wkup_hwmod = {
-	.name		= "l4_wkup",
-	.class		= &am33xx_l4_hwmod_class,
-	.clkdm_name	= "l4_wkup_clkdm",
-	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/*
- * 'mpu' class
- */
-static struct omap_hwmod_class am33xx_mpu_hwmod_class = {
-	.name	= "mpu",
-};
-
-static struct omap_hwmod am33xx_mpu_hwmod = {
-	.name		= "mpu",
-	.class		= &am33xx_mpu_hwmod_class,
-	.clkdm_name	= "mpu_clkdm",
-	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
-	.main_clk	= "dpll_mpu_m2_ck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_MPU_MPU_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/*
- * 'wakeup m3' class
- * Wakeup controller sub-system under wakeup domain
- */
-static struct omap_hwmod_class am33xx_wkup_m3_hwmod_class = {
-	.name		= "wkup_m3",
-};
-
 static struct omap_hwmod_rst_info am33xx_wkup_m3_resets[] = {
 	{ .name = "wkup_m3", .rst_shift = 3, .st_shift = 5 },
 };
@@ -213,78 +103,6 @@
 };
 
 /*
- * 'pru-icss' class
- * Programmable Real-Time Unit and Industrial Communication Subsystem
- */
-static struct omap_hwmod_class am33xx_pruss_hwmod_class = {
-	.name	= "pruss",
-};
-
-static struct omap_hwmod_rst_info am33xx_pruss_resets[] = {
-	{ .name = "pruss", .rst_shift = 1 },
-};
-
-/* pru-icss */
-/* Pseudo hwmod for reset control purpose only */
-static struct omap_hwmod am33xx_pruss_hwmod = {
-	.name		= "pruss",
-	.class		= &am33xx_pruss_hwmod_class,
-	.clkdm_name	= "pruss_ocp_clkdm",
-	.main_clk	= "pruss_ocp_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_PRUSS_CLKCTRL_OFFSET,
-			.rstctrl_offs	= AM33XX_RM_PER_RSTCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-	.rst_lines	= am33xx_pruss_resets,
-	.rst_lines_cnt	= ARRAY_SIZE(am33xx_pruss_resets),
-};
-
-/* gfx */
-/* Pseudo hwmod for reset control purpose only */
-static struct omap_hwmod_class am33xx_gfx_hwmod_class = {
-	.name	= "gfx",
-};
-
-static struct omap_hwmod_rst_info am33xx_gfx_resets[] = {
-	{ .name = "gfx", .rst_shift = 0, .st_shift = 0},
-};
-
-static struct omap_hwmod am33xx_gfx_hwmod = {
-	.name		= "gfx",
-	.class		= &am33xx_gfx_hwmod_class,
-	.clkdm_name	= "gfx_l3_clkdm",
-	.main_clk	= "gfx_fck_div_ck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_GFX_GFX_CLKCTRL_OFFSET,
-			.rstctrl_offs	= AM33XX_RM_GFX_RSTCTRL_OFFSET,
-			.rstst_offs	= AM33XX_RM_GFX_RSTST_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-	.rst_lines	= am33xx_gfx_resets,
-	.rst_lines_cnt	= ARRAY_SIZE(am33xx_gfx_resets),
-};
-
-/*
- * 'prcm' class
- * power and reset manager (whole prcm infrastructure)
- */
-static struct omap_hwmod_class am33xx_prcm_hwmod_class = {
-	.name	= "prcm",
-};
-
-/* prcm */
-static struct omap_hwmod am33xx_prcm_hwmod = {
-	.name		= "prcm",
-	.class		= &am33xx_prcm_hwmod_class,
-	.clkdm_name	= "l4_wkup_clkdm",
-};
-
-/*
  * 'adc/tsc' class
  * TouchScreen Controller (Anolog-To-Digital Converter)
  */
@@ -388,79 +206,6 @@
 #endif
 
 /*
- * 'aes0' class
- */
-static struct omap_hwmod_class_sysconfig am33xx_aes0_sysc = {
-	.rev_offs	= 0x80,
-	.sysc_offs	= 0x84,
-	.syss_offs	= 0x88,
-	.sysc_flags	= SYSS_HAS_RESET_STATUS,
-};
-
-static struct omap_hwmod_class am33xx_aes0_hwmod_class = {
-	.name		= "aes0",
-	.sysc		= &am33xx_aes0_sysc,
-};
-
-static struct omap_hwmod am33xx_aes0_hwmod = {
-	.name		= "aes",
-	.class		= &am33xx_aes0_hwmod_class,
-	.clkdm_name	= "l3_clkdm",
-	.main_clk	= "aes0_fck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_AES0_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* sha0 HIB2 (the 'P' (public) device) */
-static struct omap_hwmod_class_sysconfig am33xx_sha0_sysc = {
-	.rev_offs	= 0x100,
-	.sysc_offs	= 0x110,
-	.syss_offs	= 0x114,
-	.sysc_flags	= SYSS_HAS_RESET_STATUS,
-};
-
-static struct omap_hwmod_class am33xx_sha0_hwmod_class = {
-	.name		= "sha0",
-	.sysc		= &am33xx_sha0_sysc,
-};
-
-static struct omap_hwmod am33xx_sha0_hwmod = {
-	.name		= "sham",
-	.class		= &am33xx_sha0_hwmod_class,
-	.clkdm_name	= "l3_clkdm",
-	.main_clk	= "l3_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_SHA0_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* ocmcram */
-static struct omap_hwmod_class am33xx_ocmcram_hwmod_class = {
-	.name = "ocmcram",
-};
-
-static struct omap_hwmod am33xx_ocmcram_hwmod = {
-	.name		= "ocmcram",
-	.class		= &am33xx_ocmcram_hwmod_class,
-	.clkdm_name	= "l3_clkdm",
-	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
-	.main_clk	= "l3_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/*
  * 'debugss' class
  * debug sub system
  */
@@ -488,51 +233,11 @@
 	.opt_clks_cnt	= ARRAY_SIZE(debugss_opt_clks),
 };
 
-/* 'smartreflex' class */
-static struct omap_hwmod_class am33xx_smartreflex_hwmod_class = {
-	.name		= "smartreflex",
-};
-
-/* smartreflex0 */
-static struct omap_hwmod am33xx_smartreflex0_hwmod = {
-	.name		= "smartreflex0",
-	.class		= &am33xx_smartreflex_hwmod_class,
-	.clkdm_name	= "l4_wkup_clkdm",
-	.main_clk	= "smartreflex0_fck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_WKUP_SMARTREFLEX0_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* smartreflex1 */
-static struct omap_hwmod am33xx_smartreflex1_hwmod = {
-	.name		= "smartreflex1",
-	.class		= &am33xx_smartreflex_hwmod_class,
-	.clkdm_name	= "l4_wkup_clkdm",
-	.main_clk	= "smartreflex1_fck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_WKUP_SMARTREFLEX1_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/*
- * 'control' module class
- */
-static struct omap_hwmod_class am33xx_control_hwmod_class = {
-	.name		= "control",
-};
-
 static struct omap_hwmod am33xx_control_hwmod = {
 	.name		= "control",
 	.class		= &am33xx_control_hwmod_class,
 	.clkdm_name	= "l4_wkup_clkdm",
-	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.flags		= HWMOD_INIT_NO_IDLE,
 	.main_clk	= "dpll_core_m4_div2_ck",
 	.prcm		= {
 		.omap4	= {
@@ -542,288 +247,6 @@
 	},
 };
 
-/*
- * 'cpgmac' class
- * cpsw/cpgmac sub system
- */
-static struct omap_hwmod_class_sysconfig am33xx_cpgmac_sysc = {
-	.rev_offs	= 0x0,
-	.sysc_offs	= 0x8,
-	.syss_offs	= 0x4,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
-			   SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | MSTANDBY_FORCE |
-			   MSTANDBY_NO),
-	.sysc_fields	= &omap_hwmod_sysc_type3,
-};
-
-static struct omap_hwmod_class am33xx_cpgmac0_hwmod_class = {
-	.name		= "cpgmac0",
-	.sysc		= &am33xx_cpgmac_sysc,
-};
-
-static struct omap_hwmod am33xx_cpgmac0_hwmod = {
-	.name		= "cpgmac0",
-	.class		= &am33xx_cpgmac0_hwmod_class,
-	.clkdm_name	= "cpsw_125mhz_clkdm",
-	.flags		= (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY),
-	.main_clk	= "cpsw_125mhz_gclk",
-	.mpu_rt_idx	= 1,
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_CPGMAC0_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/*
- * mdio class
- */
-static struct omap_hwmod_class am33xx_mdio_hwmod_class = {
-	.name		= "davinci_mdio",
-};
-
-static struct omap_hwmod am33xx_mdio_hwmod = {
-	.name		= "davinci_mdio",
-	.class		= &am33xx_mdio_hwmod_class,
-	.clkdm_name	= "cpsw_125mhz_clkdm",
-	.main_clk	= "cpsw_125mhz_gclk",
-};
-
-/*
- * dcan class
- */
-static struct omap_hwmod_class am33xx_dcan_hwmod_class = {
-	.name = "d_can",
-};
-
-/* dcan0 */
-static struct omap_hwmod am33xx_dcan0_hwmod = {
-	.name		= "d_can0",
-	.class		= &am33xx_dcan_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "dcan0_fck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_DCAN0_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* dcan1 */
-static struct omap_hwmod am33xx_dcan1_hwmod = {
-	.name		= "d_can1",
-	.class		= &am33xx_dcan_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "dcan1_fck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_DCAN1_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* elm */
-static struct omap_hwmod_class_sysconfig am33xx_elm_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
-			SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
-			SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class am33xx_elm_hwmod_class = {
-	.name		= "elm",
-	.sysc		= &am33xx_elm_sysc,
-};
-
-static struct omap_hwmod am33xx_elm_hwmod = {
-	.name		= "elm",
-	.class		= &am33xx_elm_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_ELM_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* pwmss  */
-static struct omap_hwmod_class_sysconfig am33xx_epwmss_sysc = {
-	.rev_offs	= 0x0,
-	.sysc_offs	= 0x4,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-			SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
-			MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
-	.sysc_fields	= &omap_hwmod_sysc_type2,
-};
-
-static struct omap_hwmod_class am33xx_epwmss_hwmod_class = {
-	.name		= "epwmss",
-	.sysc		= &am33xx_epwmss_sysc,
-};
-
-static struct omap_hwmod_class am33xx_ecap_hwmod_class = {
-	.name		= "ecap",
-};
-
-static struct omap_hwmod_class am33xx_eqep_hwmod_class = {
-	.name		= "eqep",
-};
-
-static struct omap_hwmod_class am33xx_ehrpwm_hwmod_class = {
-	.name		= "ehrpwm",
-};
-
-/* epwmss0 */
-static struct omap_hwmod am33xx_epwmss0_hwmod = {
-	.name		= "epwmss0",
-	.class		= &am33xx_epwmss_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_EPWMSS0_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* ecap0 */
-static struct omap_hwmod am33xx_ecap0_hwmod = {
-	.name		= "ecap0",
-	.class		= &am33xx_ecap_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
-/* eqep0 */
-static struct omap_hwmod am33xx_eqep0_hwmod = {
-	.name		= "eqep0",
-	.class		= &am33xx_eqep_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
-/* ehrpwm0 */
-static struct omap_hwmod am33xx_ehrpwm0_hwmod = {
-	.name		= "ehrpwm0",
-	.class		= &am33xx_ehrpwm_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
-/* epwmss1 */
-static struct omap_hwmod am33xx_epwmss1_hwmod = {
-	.name		= "epwmss1",
-	.class		= &am33xx_epwmss_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_EPWMSS1_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* ecap1 */
-static struct omap_hwmod am33xx_ecap1_hwmod = {
-	.name		= "ecap1",
-	.class		= &am33xx_ecap_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
-/* eqep1 */
-static struct omap_hwmod am33xx_eqep1_hwmod = {
-	.name		= "eqep1",
-	.class		= &am33xx_eqep_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
-/* ehrpwm1 */
-static struct omap_hwmod am33xx_ehrpwm1_hwmod = {
-	.name		= "ehrpwm1",
-	.class		= &am33xx_ehrpwm_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
-/* epwmss2 */
-static struct omap_hwmod am33xx_epwmss2_hwmod = {
-	.name		= "epwmss2",
-	.class		= &am33xx_epwmss_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* ecap2 */
-static struct omap_hwmod am33xx_ecap2_hwmod = {
-	.name		= "ecap2",
-	.class		= &am33xx_ecap_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
-/* eqep2 */
-static struct omap_hwmod am33xx_eqep2_hwmod = {
-	.name		= "eqep2",
-	.class		= &am33xx_eqep_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
-/* ehrpwm2 */
-static struct omap_hwmod am33xx_ehrpwm2_hwmod = {
-	.name		= "ehrpwm2",
-	.class		= &am33xx_ehrpwm_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-};
-
-/*
- * 'gpio' class: for gpio 0,1,2,3
- */
-static struct omap_hwmod_class_sysconfig am33xx_gpio_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0114,
-	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP |
-			  SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
-			  SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-			  SIDLE_SMART_WKUP),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class am33xx_gpio_hwmod_class = {
-	.name		= "gpio",
-	.sysc		= &am33xx_gpio_sysc,
-	.rev		= 2,
-};
-
-static struct omap_gpio_dev_attr gpio_dev_attr = {
-	.bank_width	= 32,
-	.dbck_flag	= true,
-};
-
 /* gpio0 */
 static struct omap_hwmod_opt_clk gpio0_opt_clks[] = {
 	{ .role = "dbclk", .clk = "gpio0_dbclk" },
@@ -846,174 +269,6 @@
 	.dev_attr	= &gpio_dev_attr,
 };
 
-/* gpio1 */
-static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
-	{ .role = "dbclk", .clk = "gpio1_dbclk" },
-};
-
-static struct omap_hwmod am33xx_gpio1_hwmod = {
-	.name		= "gpio2",
-	.class		= &am33xx_gpio_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.main_clk	= "l4ls_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_GPIO1_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-	.opt_clks	= gpio1_opt_clks,
-	.opt_clks_cnt	= ARRAY_SIZE(gpio1_opt_clks),
-	.dev_attr	= &gpio_dev_attr,
-};
-
-/* gpio2 */
-static struct omap_hwmod_opt_clk gpio2_opt_clks[] = {
-	{ .role = "dbclk", .clk = "gpio2_dbclk" },
-};
-
-static struct omap_hwmod am33xx_gpio2_hwmod = {
-	.name		= "gpio3",
-	.class		= &am33xx_gpio_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.main_clk	= "l4ls_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_GPIO2_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-	.opt_clks	= gpio2_opt_clks,
-	.opt_clks_cnt	= ARRAY_SIZE(gpio2_opt_clks),
-	.dev_attr	= &gpio_dev_attr,
-};
-
-/* gpio3 */
-static struct omap_hwmod_opt_clk gpio3_opt_clks[] = {
-	{ .role = "dbclk", .clk = "gpio3_dbclk" },
-};
-
-static struct omap_hwmod am33xx_gpio3_hwmod = {
-	.name		= "gpio4",
-	.class		= &am33xx_gpio_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.main_clk	= "l4ls_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_GPIO3_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-	.opt_clks	= gpio3_opt_clks,
-	.opt_clks_cnt	= ARRAY_SIZE(gpio3_opt_clks),
-	.dev_attr	= &gpio_dev_attr,
-};
-
-/* gpmc */
-static struct omap_hwmod_class_sysconfig gpmc_sysc = {
-	.rev_offs	= 0x0,
-	.sysc_offs	= 0x10,
-	.syss_offs	= 0x14,
-	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
-			SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class am33xx_gpmc_hwmod_class = {
-	.name		= "gpmc",
-	.sysc		= &gpmc_sysc,
-};
-
-static struct omap_hwmod am33xx_gpmc_hwmod = {
-	.name		= "gpmc",
-	.class		= &am33xx_gpmc_hwmod_class,
-	.clkdm_name	= "l3s_clkdm",
-	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
-	.main_clk	= "l3s_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_GPMC_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* 'i2c' class */
-static struct omap_hwmod_class_sysconfig am33xx_i2c_sysc = {
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0090,
-	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
-			  SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
-			  SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-			  SIDLE_SMART_WKUP),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class i2c_class = {
-	.name		= "i2c",
-	.sysc		= &am33xx_i2c_sysc,
-	.rev		= OMAP_I2C_IP_VERSION_2,
-	.reset		= &omap_i2c_reset,
-};
-
-static struct omap_i2c_dev_attr i2c_dev_attr = {
-	.flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE,
-};
-
-/* i2c1 */
-static struct omap_hwmod am33xx_i2c1_hwmod = {
-	.name		= "i2c1",
-	.class		= &i2c_class,
-	.clkdm_name	= "l4_wkup_clkdm",
-	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-	.main_clk	= "dpll_per_m2_div4_wkupdm_ck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_WKUP_I2C0_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-	.dev_attr	= &i2c_dev_attr,
-};
-
-/* i2c1 */
-static struct omap_hwmod am33xx_i2c2_hwmod = {
-	.name		= "i2c2",
-	.class		= &i2c_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-	.main_clk	= "dpll_per_m2_div4_ck",
-	.prcm		= {
-		.omap4 = {
-			.clkctrl_offs	= AM33XX_CM_PER_I2C1_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-	.dev_attr	= &i2c_dev_attr,
-};
-
-/* i2c3 */
-static struct omap_hwmod am33xx_i2c3_hwmod = {
-	.name		= "i2c3",
-	.class		= &i2c_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-	.main_clk	= "dpll_per_m2_div4_ck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_I2C2_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-	.dev_attr	= &i2c_dev_attr,
-};
-
-
 /* lcdc */
 static struct omap_hwmod_class_sysconfig lcdc_sysc = {
 	.rev_offs	= 0x0,
@@ -1043,600 +298,6 @@
 };
 
 /*
- * 'mailbox' class
- * mailbox module allowing communication between the on-chip processors using a
- * queued mailbox-interrupt mechanism.
- */
-static struct omap_hwmod_class_sysconfig am33xx_mailbox_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.sysc_flags	= (SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE |
-			  SYSC_HAS_SOFTRESET),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type2,
-};
-
-static struct omap_hwmod_class am33xx_mailbox_hwmod_class = {
-	.name	= "mailbox",
-	.sysc	= &am33xx_mailbox_sysc,
-};
-
-static struct omap_hwmod am33xx_mailbox_hwmod = {
-	.name		= "mailbox",
-	.class		= &am33xx_mailbox_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-	.prcm = {
-		.omap4 = {
-			.clkctrl_offs	= AM33XX_CM_PER_MAILBOX0_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/*
- * 'mcasp' class
- */
-static struct omap_hwmod_class_sysconfig am33xx_mcasp_sysc = {
-	.rev_offs	= 0x0,
-	.sysc_offs	= 0x4,
-	.sysc_flags	= SYSC_HAS_SIDLEMODE,
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type3,
-};
-
-static struct omap_hwmod_class am33xx_mcasp_hwmod_class = {
-	.name		= "mcasp",
-	.sysc		= &am33xx_mcasp_sysc,
-};
-
-/* mcasp0 */
-static struct omap_hwmod am33xx_mcasp0_hwmod = {
-	.name		= "mcasp0",
-	.class		= &am33xx_mcasp_hwmod_class,
-	.clkdm_name	= "l3s_clkdm",
-	.main_clk	= "mcasp0_fck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_MCASP0_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* mcasp1 */
-static struct omap_hwmod am33xx_mcasp1_hwmod = {
-	.name		= "mcasp1",
-	.class		= &am33xx_mcasp_hwmod_class,
-	.clkdm_name	= "l3s_clkdm",
-	.main_clk	= "mcasp1_fck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_MCASP1_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* 'mmc' class */
-static struct omap_hwmod_class_sysconfig am33xx_mmc_sysc = {
-	.rev_offs	= 0x1fc,
-	.sysc_offs	= 0x10,
-	.syss_offs	= 0x14,
-	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
-			  SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-			  SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class am33xx_mmc_hwmod_class = {
-	.name		= "mmc",
-	.sysc		= &am33xx_mmc_sysc,
-};
-
-/* mmc0 */
-static struct omap_mmc_dev_attr am33xx_mmc0_dev_attr = {
-	.flags		= OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
-};
-
-static struct omap_hwmod am33xx_mmc0_hwmod = {
-	.name		= "mmc1",
-	.class		= &am33xx_mmc_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "mmc_clk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_MMC0_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-	.dev_attr	= &am33xx_mmc0_dev_attr,
-};
-
-/* mmc1 */
-static struct omap_mmc_dev_attr am33xx_mmc1_dev_attr = {
-	.flags		= OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
-};
-
-static struct omap_hwmod am33xx_mmc1_hwmod = {
-	.name		= "mmc2",
-	.class		= &am33xx_mmc_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "mmc_clk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_MMC1_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-	.dev_attr	= &am33xx_mmc1_dev_attr,
-};
-
-/* mmc2 */
-static struct omap_mmc_dev_attr am33xx_mmc2_dev_attr = {
-	.flags		= OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
-};
-static struct omap_hwmod am33xx_mmc2_hwmod = {
-	.name		= "mmc3",
-	.class		= &am33xx_mmc_hwmod_class,
-	.clkdm_name	= "l3s_clkdm",
-	.main_clk	= "mmc_clk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_MMC2_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-	.dev_attr	= &am33xx_mmc2_dev_attr,
-};
-
-/*
- * 'rtc' class
- * rtc subsystem
- */
-static struct omap_hwmod_class_sysconfig am33xx_rtc_sysc = {
-	.rev_offs	= 0x0074,
-	.sysc_offs	= 0x0078,
-	.sysc_flags	= SYSC_HAS_SIDLEMODE,
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO |
-			  SIDLE_SMART | SIDLE_SMART_WKUP),
-	.sysc_fields	= &omap_hwmod_sysc_type3,
-};
-
-static struct omap_hwmod_class am33xx_rtc_hwmod_class = {
-	.name		= "rtc",
-	.sysc		= &am33xx_rtc_sysc,
-};
-
-static struct omap_hwmod am33xx_rtc_hwmod = {
-	.name		= "rtc",
-	.class		= &am33xx_rtc_hwmod_class,
-	.clkdm_name	= "l4_rtc_clkdm",
-	.main_clk	= "clk_32768_ck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_RTC_RTC_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* 'spi' class */
-static struct omap_hwmod_class_sysconfig am33xx_mcspi_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0110,
-	.syss_offs	= 0x0114,
-	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
-			  SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
-			  SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class am33xx_spi_hwmod_class = {
-	.name		= "mcspi",
-	.sysc		= &am33xx_mcspi_sysc,
-	.rev		= OMAP4_MCSPI_REV,
-};
-
-/* spi0 */
-static struct omap2_mcspi_dev_attr mcspi_attrib = {
-	.num_chipselect	= 2,
-};
-static struct omap_hwmod am33xx_spi0_hwmod = {
-	.name		= "spi0",
-	.class		= &am33xx_spi_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "dpll_per_m2_div4_ck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_SPI0_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-	.dev_attr	= &mcspi_attrib,
-};
-
-/* spi1 */
-static struct omap_hwmod am33xx_spi1_hwmod = {
-	.name		= "spi1",
-	.class		= &am33xx_spi_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "dpll_per_m2_div4_ck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_SPI1_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-	.dev_attr	= &mcspi_attrib,
-};
-
-/*
- * 'spinlock' class
- * spinlock provides hardware assistance for synchronizing the
- * processes running on multiple processors
- */
-static struct omap_hwmod_class am33xx_spinlock_hwmod_class = {
-	.name		= "spinlock",
-};
-
-static struct omap_hwmod am33xx_spinlock_hwmod = {
-	.name		= "spinlock",
-	.class		= &am33xx_spinlock_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "l4ls_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_SPINLOCK_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* 'timer 2-7' class */
-static struct omap_hwmod_class_sysconfig am33xx_timer_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-			  SIDLE_SMART_WKUP),
-	.sysc_fields	= &omap_hwmod_sysc_type2,
-};
-
-static struct omap_hwmod_class am33xx_timer_hwmod_class = {
-	.name		= "timer",
-	.sysc		= &am33xx_timer_sysc,
-};
-
-/* timer1 1ms */
-static struct omap_hwmod_class_sysconfig am33xx_timer1ms_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
-			SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
-			SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class am33xx_timer1ms_hwmod_class = {
-	.name		= "timer",
-	.sysc		= &am33xx_timer1ms_sysc,
-};
-
-static struct omap_hwmod am33xx_timer1_hwmod = {
-	.name		= "timer1",
-	.class		= &am33xx_timer1ms_hwmod_class,
-	.clkdm_name	= "l4_wkup_clkdm",
-	.main_clk	= "timer1_fck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_WKUP_TIMER1_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-static struct omap_hwmod am33xx_timer2_hwmod = {
-	.name		= "timer2",
-	.class		= &am33xx_timer_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "timer2_fck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_TIMER2_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-static struct omap_hwmod am33xx_timer3_hwmod = {
-	.name		= "timer3",
-	.class		= &am33xx_timer_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "timer3_fck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_TIMER3_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-static struct omap_hwmod am33xx_timer4_hwmod = {
-	.name		= "timer4",
-	.class		= &am33xx_timer_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "timer4_fck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_TIMER4_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-static struct omap_hwmod am33xx_timer5_hwmod = {
-	.name		= "timer5",
-	.class		= &am33xx_timer_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "timer5_fck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_TIMER5_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-static struct omap_hwmod am33xx_timer6_hwmod = {
-	.name		= "timer6",
-	.class		= &am33xx_timer_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "timer6_fck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_TIMER6_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-static struct omap_hwmod am33xx_timer7_hwmod = {
-	.name		= "timer7",
-	.class		= &am33xx_timer_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.main_clk	= "timer7_fck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_TIMER7_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* tpcc */
-static struct omap_hwmod_class am33xx_tpcc_hwmod_class = {
-	.name		= "tpcc",
-};
-
-static struct omap_hwmod am33xx_tpcc_hwmod = {
-	.name		= "tpcc",
-	.class		= &am33xx_tpcc_hwmod_class,
-	.clkdm_name	= "l3_clkdm",
-	.main_clk	= "l3_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_TPCC_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-static struct omap_hwmod_class_sysconfig am33xx_tptc_sysc = {
-	.rev_offs	= 0x0,
-	.sysc_offs	= 0x10,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
-			  SYSC_HAS_MIDLEMODE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_SMART | MSTANDBY_FORCE),
-	.sysc_fields	= &omap_hwmod_sysc_type2,
-};
-
-/* 'tptc' class */
-static struct omap_hwmod_class am33xx_tptc_hwmod_class = {
-	.name		= "tptc",
-	.sysc		= &am33xx_tptc_sysc,
-};
-
-/* tptc0 */
-static struct omap_hwmod am33xx_tptc0_hwmod = {
-	.name		= "tptc0",
-	.class		= &am33xx_tptc_hwmod_class,
-	.clkdm_name	= "l3_clkdm",
-	.flags		= HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
-	.main_clk	= "l3_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_TPTC0_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* tptc1 */
-static struct omap_hwmod am33xx_tptc1_hwmod = {
-	.name		= "tptc1",
-	.class		= &am33xx_tptc_hwmod_class,
-	.clkdm_name	= "l3_clkdm",
-	.flags		= (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY),
-	.main_clk	= "l3_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_TPTC1_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* tptc2 */
-static struct omap_hwmod am33xx_tptc2_hwmod = {
-	.name		= "tptc2",
-	.class		= &am33xx_tptc_hwmod_class,
-	.clkdm_name	= "l3_clkdm",
-	.flags		= (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY),
-	.main_clk	= "l3_gclk",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_TPTC2_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* 'uart' class */
-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 |
-			  SIDLE_SMART_WKUP),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class uart_class = {
-	.name		= "uart",
-	.sysc		= &uart_sysc,
-};
-
-/* uart1 */
-static struct omap_hwmod am33xx_uart1_hwmod = {
-	.name		= "uart1",
-	.class		= &uart_class,
-	.clkdm_name	= "l4_wkup_clkdm",
-	.flags		= DEBUG_AM33XXUART1_FLAGS | HWMOD_SWSUP_SIDLE_ACT,
-	.main_clk	= "dpll_per_m2_div4_wkupdm_ck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_WKUP_UART0_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-static struct omap_hwmod am33xx_uart2_hwmod = {
-	.name		= "uart2",
-	.class		= &uart_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.flags		= HWMOD_SWSUP_SIDLE_ACT,
-	.main_clk	= "dpll_per_m2_div4_ck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_UART1_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* uart3 */
-static struct omap_hwmod am33xx_uart3_hwmod = {
-	.name		= "uart3",
-	.class		= &uart_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.flags		= HWMOD_SWSUP_SIDLE_ACT,
-	.main_clk	= "dpll_per_m2_div4_ck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_UART2_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-static struct omap_hwmod am33xx_uart4_hwmod = {
-	.name		= "uart4",
-	.class		= &uart_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.flags		= HWMOD_SWSUP_SIDLE_ACT,
-	.main_clk	= "dpll_per_m2_div4_ck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_UART3_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-static struct omap_hwmod am33xx_uart5_hwmod = {
-	.name		= "uart5",
-	.class		= &uart_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.flags		= HWMOD_SWSUP_SIDLE_ACT,
-	.main_clk	= "dpll_per_m2_div4_ck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_UART4_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-static struct omap_hwmod am33xx_uart6_hwmod = {
-	.name		= "uart6",
-	.class		= &uart_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.flags		= HWMOD_SWSUP_SIDLE_ACT,
-	.main_clk	= "dpll_per_m2_div4_ck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_UART5_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/* 'wd_timer' class */
-static struct omap_hwmod_class_sysconfig wdt_sysc = {
-	.rev_offs	= 0x0,
-	.sysc_offs	= 0x10,
-	.syss_offs	= 0x14,
-	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_SIDLEMODE |
-			SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-			SIDLE_SMART_WKUP),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class am33xx_wd_timer_hwmod_class = {
-	.name		= "wd_timer",
-	.sysc		= &wdt_sysc,
-	.pre_shutdown	= &omap2_wd_timer_disable,
-};
-
-/*
- * XXX: device.c file uses hardcoded name for watchdog timer
- * driver "wd_timer2, so we are also using same name as of now...
- */
-static struct omap_hwmod am33xx_wd_timer1_hwmod = {
-	.name		= "wd_timer2",
-	.class		= &am33xx_wd_timer_hwmod_class,
-	.clkdm_name	= "l4_wkup_clkdm",
-	.flags		= HWMOD_SWSUP_SIDLE,
-	.main_clk	= "wdt1_fck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_WKUP_WDT1_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-/*
  * 'usb_otg' class
  * high-speed on-the-go universal serial bus (usb_otg) controller
  */
@@ -1690,14 +351,6 @@
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* mpu -> l3 main */
-static struct omap_hwmod_ocp_if am33xx_mpu__l3_main = {
-	.master		= &am33xx_mpu_hwmod,
-	.slave		= &am33xx_l3_main_hwmod,
-	.clk		= "dpll_mpu_m2_ck",
-	.user		= OCP_USER_MPU,
-};
-
 /* l3 main -> l4 hs */
 static struct omap_hwmod_ocp_if am33xx_l3_main__l4_hs = {
 	.master		= &am33xx_l3_main_hwmod,
@@ -1706,62 +359,6 @@
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l3 main -> l3 s */
-static struct omap_hwmod_ocp_if am33xx_l3_main__l3_s = {
-	.master		= &am33xx_l3_main_hwmod,
-	.slave		= &am33xx_l3_s_hwmod,
-	.clk		= "l3s_gclk",
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l3 s -> l4 per/ls */
-static struct omap_hwmod_ocp_if am33xx_l3_s__l4_ls = {
-	.master		= &am33xx_l3_s_hwmod,
-	.slave		= &am33xx_l4_ls_hwmod,
-	.clk		= "l3s_gclk",
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l3 s -> l4 wkup */
-static struct omap_hwmod_ocp_if am33xx_l3_s__l4_wkup = {
-	.master		= &am33xx_l3_s_hwmod,
-	.slave		= &am33xx_l4_wkup_hwmod,
-	.clk		= "l3s_gclk",
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l3 main -> l3 instr */
-static struct omap_hwmod_ocp_if am33xx_l3_main__l3_instr = {
-	.master		= &am33xx_l3_main_hwmod,
-	.slave		= &am33xx_l3_instr_hwmod,
-	.clk		= "l3s_gclk",
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* mpu -> prcm */
-static struct omap_hwmod_ocp_if am33xx_mpu__prcm = {
-	.master		= &am33xx_mpu_hwmod,
-	.slave		= &am33xx_prcm_hwmod,
-	.clk		= "dpll_mpu_m2_ck",
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l3 s -> l3 main*/
-static struct omap_hwmod_ocp_if am33xx_l3_s__l3_main = {
-	.master		= &am33xx_l3_s_hwmod,
-	.slave		= &am33xx_l3_main_hwmod,
-	.clk		= "l3s_gclk",
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* pru-icss -> l3 main */
-static struct omap_hwmod_ocp_if am33xx_pruss__l3_main = {
-	.master		= &am33xx_pruss_hwmod,
-	.slave		= &am33xx_l3_main_hwmod,
-	.clk		= "l3_gclk",
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 /* wkup m3 -> l4 wkup */
 static struct omap_hwmod_ocp_if am33xx_wkup_m3__l4_wkup = {
 	.master		= &am33xx_wkup_m3_hwmod,
@@ -1770,14 +367,6 @@
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* gfx -> l3 main */
-static struct omap_hwmod_ocp_if am33xx_gfx__l3_main = {
-	.master		= &am33xx_gfx_hwmod,
-	.slave		= &am33xx_l3_main_hwmod,
-	.clk		= "dpll_core_m4_ck",
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 /* l4 wkup -> wkup m3 */
 static struct omap_hwmod_ocp_if am33xx_l4_wkup__wkup_m3 = {
 	.master		= &am33xx_l4_wkup_hwmod,
@@ -1794,14 +383,6 @@
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l3 main -> gfx */
-static struct omap_hwmod_ocp_if am33xx_l3_main__gfx = {
-	.master		= &am33xx_l3_main_hwmod,
-	.slave		= &am33xx_gfx_hwmod,
-	.clk		= "dpll_core_m4_ck",
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 /* l3_main -> debugss */
 static struct omap_hwmod_addr_space am33xx_debugss_addrs[] = {
 	{
@@ -1844,54 +425,6 @@
 	.user		= OCP_USER_MPU,
 };
 
-/* l4 wkup -> rtc */
-static struct omap_hwmod_ocp_if am33xx_l4_wkup__rtc = {
-	.master		= &am33xx_l4_wkup_hwmod,
-	.slave		= &am33xx_rtc_hwmod,
-	.clk		= "clkdiv32k_ick",
-	.user		= OCP_USER_MPU,
-};
-
-/* l4 per/ls -> DCAN0 */
-static struct omap_hwmod_ocp_if am33xx_l4_per__dcan0 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_dcan0_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4 per/ls -> DCAN1 */
-static struct omap_hwmod_ocp_if am33xx_l4_per__dcan1 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_dcan1_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4 per/ls -> GPIO2 */
-static struct omap_hwmod_ocp_if am33xx_l4_per__gpio1 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_gpio1_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4 per/ls -> gpio3 */
-static struct omap_hwmod_ocp_if am33xx_l4_per__gpio2 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_gpio2_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l4 per/ls -> gpio4 */
-static struct omap_hwmod_ocp_if am33xx_l4_per__gpio3 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_gpio3_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-};
-
 /* L4 WKUP -> I2C1 */
 static struct omap_hwmod_ocp_if am33xx_l4_wkup__i2c1 = {
 	.master		= &am33xx_l4_wkup_hwmod,
@@ -1933,177 +466,6 @@
 	.user		= OCP_USER_MPU,
 };
 
-static struct omap_hwmod_ocp_if am33xx_cpgmac0__mdio = {
-	.master		= &am33xx_cpgmac0_hwmod,
-	.slave		= &am33xx_mdio_hwmod,
-	.user		= OCP_USER_MPU,
-};
-
-static struct omap_hwmod_addr_space am33xx_elm_addr_space[] = {
-	{
-		.pa_start	= 0x48080000,
-		.pa_end		= 0x48080000 + SZ_8K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
-static struct omap_hwmod_ocp_if am33xx_l4_ls__elm = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_elm_hwmod,
-	.clk		= "l4ls_gclk",
-	.addr		= am33xx_elm_addr_space,
-	.user		= OCP_USER_MPU,
-};
-
-static struct omap_hwmod_addr_space am33xx_epwmss0_addr_space[] = {
-	{
-		.pa_start	= 0x48300000,
-		.pa_end		= 0x48300000 + SZ_16 - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
-static struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss0 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_epwmss0_hwmod,
-	.clk		= "l4ls_gclk",
-	.addr		= am33xx_epwmss0_addr_space,
-	.user		= OCP_USER_MPU,
-};
-
-static struct omap_hwmod_ocp_if am33xx_epwmss0__ecap0 = {
-	.master		= &am33xx_epwmss0_hwmod,
-	.slave		= &am33xx_ecap0_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-static struct omap_hwmod_ocp_if am33xx_epwmss0__eqep0 = {
-	.master		= &am33xx_epwmss0_hwmod,
-	.slave		= &am33xx_eqep0_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-static struct omap_hwmod_ocp_if am33xx_epwmss0__ehrpwm0 = {
-	.master		= &am33xx_epwmss0_hwmod,
-	.slave		= &am33xx_ehrpwm0_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-
-static struct omap_hwmod_addr_space am33xx_epwmss1_addr_space[] = {
-	{
-		.pa_start	= 0x48302000,
-		.pa_end		= 0x48302000 + SZ_16 - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
-static struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss1 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_epwmss1_hwmod,
-	.clk		= "l4ls_gclk",
-	.addr		= am33xx_epwmss1_addr_space,
-	.user		= OCP_USER_MPU,
-};
-
-static struct omap_hwmod_ocp_if am33xx_epwmss1__ecap1 = {
-	.master		= &am33xx_epwmss1_hwmod,
-	.slave		= &am33xx_ecap1_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-static struct omap_hwmod_ocp_if am33xx_epwmss1__eqep1 = {
-	.master		= &am33xx_epwmss1_hwmod,
-	.slave		= &am33xx_eqep1_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-static struct omap_hwmod_ocp_if am33xx_epwmss1__ehrpwm1 = {
-	.master		= &am33xx_epwmss1_hwmod,
-	.slave		= &am33xx_ehrpwm1_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-static struct omap_hwmod_addr_space am33xx_epwmss2_addr_space[] = {
-	{
-		.pa_start	= 0x48304000,
-		.pa_end		= 0x48304000 + SZ_16 - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
-static struct omap_hwmod_ocp_if am33xx_l4_ls__epwmss2 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_epwmss2_hwmod,
-	.clk		= "l4ls_gclk",
-	.addr		= am33xx_epwmss2_addr_space,
-	.user		= OCP_USER_MPU,
-};
-
-static struct omap_hwmod_ocp_if am33xx_epwmss2__ecap2 = {
-	.master		= &am33xx_epwmss2_hwmod,
-	.slave		= &am33xx_ecap2_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-static struct omap_hwmod_ocp_if am33xx_epwmss2__eqep2 = {
-	.master		= &am33xx_epwmss2_hwmod,
-	.slave		= &am33xx_eqep2_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-static struct omap_hwmod_ocp_if am33xx_epwmss2__ehrpwm2 = {
-	.master		= &am33xx_epwmss2_hwmod,
-	.slave		= &am33xx_ehrpwm2_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-/* l3s cfg -> gpmc */
-static struct omap_hwmod_addr_space am33xx_gpmc_addr_space[] = {
-	{
-		.pa_start	= 0x50000000,
-		.pa_end		= 0x50000000 + SZ_8K - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
-
-static struct omap_hwmod_ocp_if am33xx_l3_s__gpmc = {
-	.master		= &am33xx_l3_s_hwmod,
-	.slave		= &am33xx_gpmc_hwmod,
-	.clk		= "l3s_gclk",
-	.addr		= am33xx_gpmc_addr_space,
-	.user		= OCP_USER_MPU,
-};
-
-/* i2c2 */
-static struct omap_hwmod_ocp_if am33xx_l4_per__i2c2 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_i2c2_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-static struct omap_hwmod_ocp_if am33xx_l4_per__i2c3 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_i2c3_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
 static struct omap_hwmod_addr_space am33xx_lcdc_addr_space[] = {
 	{
 		.pa_start	= 0x4830E000,
@@ -2121,138 +483,6 @@
 	.user		= OCP_USER_MPU,
 };
 
-static struct omap_hwmod_addr_space am33xx_mailbox_addrs[] = {
-	{
-		.pa_start	= 0x480C8000,
-		.pa_end		= 0x480C8000 + (SZ_4K - 1),
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
-/* l4 ls -> mailbox */
-static struct omap_hwmod_ocp_if am33xx_l4_per__mailbox = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_mailbox_hwmod,
-	.clk		= "l4ls_gclk",
-	.addr		= am33xx_mailbox_addrs,
-	.user		= OCP_USER_MPU,
-};
-
-/* l4 ls -> spinlock */
-static struct omap_hwmod_ocp_if am33xx_l4_ls__spinlock = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_spinlock_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-/* l4 ls -> mcasp0 */
-static struct omap_hwmod_addr_space am33xx_mcasp0_addr_space[] = {
-	{
-		.pa_start	= 0x48038000,
-		.pa_end		= 0x48038000 + SZ_8K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
-static struct omap_hwmod_ocp_if am33xx_l4_ls__mcasp0 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_mcasp0_hwmod,
-	.clk		= "l4ls_gclk",
-	.addr		= am33xx_mcasp0_addr_space,
-	.user		= OCP_USER_MPU,
-};
-
-/* l4 ls -> mcasp1 */
-static struct omap_hwmod_addr_space am33xx_mcasp1_addr_space[] = {
-	{
-		.pa_start	= 0x4803C000,
-		.pa_end		= 0x4803C000 + SZ_8K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
-static struct omap_hwmod_ocp_if am33xx_l4_ls__mcasp1 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_mcasp1_hwmod,
-	.clk		= "l4ls_gclk",
-	.addr		= am33xx_mcasp1_addr_space,
-	.user		= OCP_USER_MPU,
-};
-
-/* l4 ls -> mmc0 */
-static struct omap_hwmod_addr_space am33xx_mmc0_addr_space[] = {
-	{
-		.pa_start	= 0x48060100,
-		.pa_end		= 0x48060100 + SZ_4K - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
-
-static struct omap_hwmod_ocp_if am33xx_l4_ls__mmc0 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_mmc0_hwmod,
-	.clk		= "l4ls_gclk",
-	.addr		= am33xx_mmc0_addr_space,
-	.user		= OCP_USER_MPU,
-};
-
-/* l4 ls -> mmc1 */
-static struct omap_hwmod_addr_space am33xx_mmc1_addr_space[] = {
-	{
-		.pa_start	= 0x481d8100,
-		.pa_end		= 0x481d8100 + SZ_4K - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
-
-static struct omap_hwmod_ocp_if am33xx_l4_ls__mmc1 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_mmc1_hwmod,
-	.clk		= "l4ls_gclk",
-	.addr		= am33xx_mmc1_addr_space,
-	.user		= OCP_USER_MPU,
-};
-
-/* l3 s -> mmc2 */
-static struct omap_hwmod_addr_space am33xx_mmc2_addr_space[] = {
-	{
-		.pa_start	= 0x47810100,
-		.pa_end		= 0x47810100 + SZ_64K - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
-
-static struct omap_hwmod_ocp_if am33xx_l3_s__mmc2 = {
-	.master		= &am33xx_l3_s_hwmod,
-	.slave		= &am33xx_mmc2_hwmod,
-	.clk		= "l3s_gclk",
-	.addr		= am33xx_mmc2_addr_space,
-	.user		= OCP_USER_MPU,
-};
-
-/* l4 ls -> mcspi0 */
-static struct omap_hwmod_ocp_if am33xx_l4_ls__mcspi0 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_spi0_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-/* l4 ls -> mcspi1 */
-static struct omap_hwmod_ocp_if am33xx_l4_ls__mcspi1 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_spi1_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
 /* l4 wkup -> timer1 */
 static struct omap_hwmod_ocp_if am33xx_l4_wkup__timer1 = {
 	.master		= &am33xx_l4_wkup_hwmod,
@@ -2261,116 +491,6 @@
 	.user		= OCP_USER_MPU,
 };
 
-/* l4 per -> timer2 */
-static struct omap_hwmod_ocp_if am33xx_l4_ls__timer2 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_timer2_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-/* l4 per -> timer3 */
-static struct omap_hwmod_ocp_if am33xx_l4_ls__timer3 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_timer3_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-/* l4 per -> timer4 */
-static struct omap_hwmod_ocp_if am33xx_l4_ls__timer4 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_timer4_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-/* l4 per -> timer5 */
-static struct omap_hwmod_ocp_if am33xx_l4_ls__timer5 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_timer5_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-/* l4 per -> timer6 */
-static struct omap_hwmod_ocp_if am33xx_l4_ls__timer6 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_timer6_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-/* l4 per -> timer7 */
-static struct omap_hwmod_ocp_if am33xx_l4_ls__timer7 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_timer7_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-/* l3 main -> tpcc */
-static struct omap_hwmod_ocp_if am33xx_l3_main__tpcc = {
-	.master		= &am33xx_l3_main_hwmod,
-	.slave		= &am33xx_tpcc_hwmod,
-	.clk		= "l3_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-/* l3 main -> tpcc0 */
-static struct omap_hwmod_addr_space am33xx_tptc0_addr_space[] = {
-	{
-		.pa_start	= 0x49800000,
-		.pa_end		= 0x49800000 + SZ_8K - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
-
-static struct omap_hwmod_ocp_if am33xx_l3_main__tptc0 = {
-	.master		= &am33xx_l3_main_hwmod,
-	.slave		= &am33xx_tptc0_hwmod,
-	.clk		= "l3_gclk",
-	.addr		= am33xx_tptc0_addr_space,
-	.user		= OCP_USER_MPU,
-};
-
-/* l3 main -> tpcc1 */
-static struct omap_hwmod_addr_space am33xx_tptc1_addr_space[] = {
-	{
-		.pa_start	= 0x49900000,
-		.pa_end		= 0x49900000 + SZ_8K - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
-
-static struct omap_hwmod_ocp_if am33xx_l3_main__tptc1 = {
-	.master		= &am33xx_l3_main_hwmod,
-	.slave		= &am33xx_tptc1_hwmod,
-	.clk		= "l3_gclk",
-	.addr		= am33xx_tptc1_addr_space,
-	.user		= OCP_USER_MPU,
-};
-
-/* l3 main -> tpcc2 */
-static struct omap_hwmod_addr_space am33xx_tptc2_addr_space[] = {
-	{
-		.pa_start	= 0x49a00000,
-		.pa_end		= 0x49a00000 + SZ_8K - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
-
-static struct omap_hwmod_ocp_if am33xx_l3_main__tptc2 = {
-	.master		= &am33xx_l3_main_hwmod,
-	.slave		= &am33xx_tptc2_hwmod,
-	.clk		= "l3_gclk",
-	.addr		= am33xx_tptc2_addr_space,
-	.user		= OCP_USER_MPU,
-};
-
 /* l4 wkup -> uart1 */
 static struct omap_hwmod_ocp_if am33xx_l4_wkup__uart1 = {
 	.master		= &am33xx_l4_wkup_hwmod,
@@ -2379,46 +499,6 @@
 	.user		= OCP_USER_MPU,
 };
 
-/* l4 ls -> uart2 */
-static struct omap_hwmod_ocp_if am33xx_l4_ls__uart2 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_uart2_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-/* l4 ls -> uart3 */
-static struct omap_hwmod_ocp_if am33xx_l4_ls__uart3 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_uart3_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-/* l4 ls -> uart4 */
-static struct omap_hwmod_ocp_if am33xx_l4_ls__uart4 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_uart4_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-/* l4 ls -> uart5 */
-static struct omap_hwmod_ocp_if am33xx_l4_ls__uart5 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_uart5_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
-/* l4 ls -> uart6 */
-static struct omap_hwmod_ocp_if am33xx_l4_ls__uart6 = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_uart6_hwmod,
-	.clk		= "l4ls_gclk",
-	.user		= OCP_USER_MPU,
-};
-
 /* l4 wkup -> wd_timer1 */
 static struct omap_hwmod_ocp_if am33xx_l4_wkup__wd_timer1 = {
 	.master		= &am33xx_l4_wkup_hwmod,
@@ -2437,47 +517,39 @@
 	.flags		= OCPIF_SWSUP_IDLE,
 };
 
-/* l3 main -> ocmc */
-static struct omap_hwmod_ocp_if am33xx_l3_main__ocmc = {
-	.master		= &am33xx_l3_main_hwmod,
-	.slave		= &am33xx_ocmcram_hwmod,
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+/* rng */
+static struct omap_hwmod_class_sysconfig am33xx_rng_sysc = {
+	.rev_offs	= 0x1fe0,
+	.sysc_offs	= 0x1fe4,
+	.sysc_flags	= SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE,
+	.idlemodes	= SIDLE_FORCE | SIDLE_NO,
+	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
 
-/* l3 main -> sha0 HIB2 */
-static struct omap_hwmod_addr_space am33xx_sha0_addrs[] = {
-	{
-		.pa_start	= 0x53100000,
-		.pa_end		= 0x53100000 + SZ_512 - 1,
-		.flags		= ADDR_TYPE_RT
+static struct omap_hwmod_class am33xx_rng_hwmod_class = {
+	.name		= "rng",
+	.sysc		= &am33xx_rng_sysc,
+};
+
+static struct omap_hwmod am33xx_rng_hwmod = {
+	.name		= "rng",
+	.class		= &am33xx_rng_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.flags		= HWMOD_SWSUP_SIDLE,
+	.main_clk	= "rng_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_RNG_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
 	},
-	{ }
 };
 
-static struct omap_hwmod_ocp_if am33xx_l3_main__sha0 = {
-	.master		= &am33xx_l3_main_hwmod,
-	.slave		= &am33xx_sha0_hwmod,
-	.clk		= "sha0_fck",
-	.addr		= am33xx_sha0_addrs,
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* l3 main -> AES0 HIB2 */
-static struct omap_hwmod_addr_space am33xx_aes0_addrs[] = {
-	{
-		.pa_start	= 0x53500000,
-		.pa_end		= 0x53500000 + SZ_1M - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
-static struct omap_hwmod_ocp_if am33xx_l3_main__aes0 = {
-	.master		= &am33xx_l3_main_hwmod,
-	.slave		= &am33xx_aes0_hwmod,
-	.clk		= "aes0_fck",
-	.addr		= am33xx_aes0_addrs,
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+static struct omap_hwmod_ocp_if am33xx_l4_per__rng = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_rng_hwmod,
+	.clk		= "rng_fck",
+	.user		= OCP_USER_MPU,
 };
 
 static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
@@ -2559,11 +631,13 @@
 	&am33xx_cpgmac0__mdio,
 	&am33xx_l3_main__sha0,
 	&am33xx_l3_main__aes0,
+	&am33xx_l4_per__rng,
 	NULL,
 };
 
 int __init am33xx_hwmod_init(void)
 {
+	omap_hwmod_am33xx_reg();
 	omap_hwmod_init();
 	return omap_hwmod_register_links(am33xx_hwmod_ocp_ifs);
 }
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 0c3a427..9e56fab 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -3693,6 +3693,53 @@
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/*
+ * 'ssi' class
+ * synchronous serial interface (multichannel and full-duplex serial if)
+ */
+
+static struct omap_hwmod_class_sysconfig omap34xx_ssi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_EMUFREE |
+			   SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
+			   MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap34xx_ssi_hwmod_class = {
+	.name	= "ssi",
+	.sysc	= &omap34xx_ssi_sysc,
+};
+
+static struct omap_hwmod omap34xx_ssi_hwmod = {
+	.name		= "ssi",
+	.class		= &omap34xx_ssi_hwmod_class,
+	.clkdm_name	= "core_l4_clkdm",
+	.main_clk	= "ssi_ssr_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id		= 1,
+			.module_bit		= OMAP3430_EN_SSI_SHIFT,
+			.module_offs		= CORE_MOD,
+			.idlest_reg_id		= 1,
+			.idlest_idle_bit	= OMAP3430ES2_ST_SSI_IDLE_SHIFT,
+		},
+	},
+};
+
+/* L4 CORE -> SSI */
+static struct omap_hwmod_ocp_if omap34xx_l4_core__ssi = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap34xx_ssi_hwmod,
+	.clk		= "ssi_ick",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
 	&omap3xxx_l3_main__l4_core,
 	&omap3xxx_l3_main__l4_per,
@@ -3818,6 +3865,7 @@
 #ifdef CONFIG_OMAP_IOMMU_IVA2
 	&omap3xxx_l3_main__mmu_iva,
 #endif
+	&omap34xx_l4_core__ssi,
 	NULL
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c
new file mode 100644
index 0000000..9002fca
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c
@@ -0,0 +1,758 @@
+/*
+ * Copyright (C) 2013 Texas Instruments Incorporated
+ *
+ * Hwmod present only in AM43x and those that differ other than register
+ * offsets as compared to AM335x.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/platform_data/gpio-omap.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
+#include "omap_hwmod.h"
+#include "omap_hwmod_33xx_43xx_common_data.h"
+#include "prcm43xx.h"
+
+/* IP blocks */
+static struct omap_hwmod am43xx_l4_hs_hwmod = {
+	.name		= "l4_hs",
+	.class		= &am33xx_l4_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.flags		= HWMOD_INIT_NO_IDLE,
+	.main_clk	= "l4hs_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM43XX_CM_PER_L4HS_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod_rst_info am33xx_wkup_m3_resets[] = {
+	{ .name = "wkup_m3", .rst_shift = 3, .st_shift = 5 },
+};
+
+static struct omap_hwmod am43xx_wkup_m3_hwmod = {
+	.name		= "wkup_m3",
+	.class		= &am33xx_wkup_m3_hwmod_class,
+	.clkdm_name	= "l4_wkup_aon_clkdm",
+	/* Keep hardreset asserted */
+	.flags		= HWMOD_INIT_NO_RESET | HWMOD_NO_IDLEST,
+	.main_clk	= "sys_clkin_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM43XX_CM_WKUP_WKUP_M3_CLKCTRL_OFFSET,
+			.rstctrl_offs	= AM43XX_RM_WKUP_RSTCTRL_OFFSET,
+			.rstst_offs	= AM43XX_RM_WKUP_RSTST_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.rst_lines	= am33xx_wkup_m3_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(am33xx_wkup_m3_resets),
+};
+
+static struct omap_hwmod am43xx_control_hwmod = {
+	.name		= "control",
+	.class		= &am33xx_control_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= HWMOD_INIT_NO_IDLE,
+	.main_clk	= "sys_clkin_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM43XX_CM_WKUP_CONTROL_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod_opt_clk gpio0_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio0_dbclk" },
+};
+
+static struct omap_hwmod am43xx_gpio0_hwmod = {
+	.name		= "gpio1",
+	.class		= &am33xx_gpio_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.main_clk	= "sys_clkin_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM43XX_CM_WKUP_GPIO0_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.opt_clks	= gpio0_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio0_opt_clks),
+	.dev_attr	= &gpio_dev_attr,
+};
+
+static struct omap_hwmod_class_sysconfig am43xx_synctimer_sysc = {
+	.rev_offs	= 0x0,
+	.sysc_offs	= 0x4,
+	.sysc_flags	= SYSC_HAS_SIDLEMODE,
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class am43xx_synctimer_hwmod_class = {
+	.name	= "synctimer",
+	.sysc	= &am43xx_synctimer_sysc,
+};
+
+static struct omap_hwmod am43xx_synctimer_hwmod = {
+	.name		= "counter_32k",
+	.class		= &am43xx_synctimer_hwmod_class,
+	.clkdm_name	= "l4_wkup_aon_clkdm",
+	.flags		= HWMOD_SWSUP_SIDLE,
+	.main_clk	= "synctimer_32kclk",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = AM43XX_CM_WKUP_SYNCTIMER_CLKCTRL_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod am43xx_timer8_hwmod = {
+	.name		= "timer8",
+	.class		= &am33xx_timer_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "timer8_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM43XX_CM_PER_TIMER8_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod am43xx_timer9_hwmod = {
+	.name		= "timer9",
+	.class		= &am33xx_timer_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "timer9_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM43XX_CM_PER_TIMER9_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod am43xx_timer10_hwmod = {
+	.name		= "timer10",
+	.class		= &am33xx_timer_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "timer10_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM43XX_CM_PER_TIMER10_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod am43xx_timer11_hwmod = {
+	.name		= "timer11",
+	.class		= &am33xx_timer_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "timer11_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM43XX_CM_PER_TIMER11_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod am43xx_epwmss3_hwmod = {
+	.name		= "epwmss3",
+	.class		= &am33xx_epwmss_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs = AM43XX_CM_PER_EPWMSS3_CLKCTRL_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod am43xx_ehrpwm3_hwmod = {
+	.name		= "ehrpwm3",
+	.class		= &am33xx_ehrpwm_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+};
+
+static struct omap_hwmod am43xx_epwmss4_hwmod = {
+	.name		= "epwmss4",
+	.class		= &am33xx_epwmss_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs = AM43XX_CM_PER_EPWMSS4_CLKCTRL_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod am43xx_ehrpwm4_hwmod = {
+	.name		= "ehrpwm4",
+	.class		= &am33xx_ehrpwm_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+};
+
+static struct omap_hwmod am43xx_epwmss5_hwmod = {
+	.name		= "epwmss5",
+	.class		= &am33xx_epwmss_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs = AM43XX_CM_PER_EPWMSS5_CLKCTRL_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod am43xx_ehrpwm5_hwmod = {
+	.name		= "ehrpwm5",
+	.class		= &am33xx_ehrpwm_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+};
+
+static struct omap_hwmod am43xx_spi2_hwmod = {
+	.name		= "spi2",
+	.class		= &am33xx_spi_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs = AM43XX_CM_PER_SPI2_CLKCTRL_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+	.dev_attr	= &mcspi_attrib,
+};
+
+static struct omap_hwmod am43xx_spi3_hwmod = {
+	.name		= "spi3",
+	.class		= &am33xx_spi_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs = AM43XX_CM_PER_SPI3_CLKCTRL_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+	.dev_attr	= &mcspi_attrib,
+};
+
+static struct omap_hwmod am43xx_spi4_hwmod = {
+	.name		= "spi4",
+	.class		= &am33xx_spi_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs = AM43XX_CM_PER_SPI4_CLKCTRL_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+	.dev_attr	= &mcspi_attrib,
+};
+
+static struct omap_hwmod_opt_clk gpio4_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio4_dbclk" },
+};
+
+static struct omap_hwmod am43xx_gpio4_hwmod = {
+	.name		= "gpio5",
+	.class		= &am33xx_gpio_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs = AM43XX_CM_PER_GPIO4_CLKCTRL_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+	.opt_clks	= gpio4_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio4_opt_clks),
+	.dev_attr	= &gpio_dev_attr,
+};
+
+static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio5_dbclk" },
+};
+
+static struct omap_hwmod am43xx_gpio5_hwmod = {
+	.name		= "gpio6",
+	.class		= &am33xx_gpio_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs = AM43XX_CM_PER_GPIO5_CLKCTRL_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+	.opt_clks	= gpio5_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio5_opt_clks),
+	.dev_attr	= &gpio_dev_attr,
+};
+
+static struct omap_hwmod_class am43xx_ocp2scp_hwmod_class = {
+	.name	= "ocp2scp",
+};
+
+static struct omap_hwmod am43xx_ocp2scp0_hwmod = {
+	.name		= "ocp2scp0",
+	.class		= &am43xx_ocp2scp_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = AM43XX_CM_PER_USBPHYOCP2SCP0_CLKCTRL_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod am43xx_ocp2scp1_hwmod = {
+	.name		= "ocp2scp1",
+	.class		= &am43xx_ocp2scp_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs	= AM43XX_CM_PER_USBPHYOCP2SCP1_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod_class_sysconfig am43xx_usb_otg_ss_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_DMADISABLE | SYSC_HAS_MIDLEMODE |
+				SYSC_HAS_SIDLEMODE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+				SIDLE_SMART_WKUP | MSTANDBY_FORCE |
+				MSTANDBY_NO | MSTANDBY_SMART |
+				MSTANDBY_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class am43xx_usb_otg_ss_hwmod_class = {
+	.name	= "usb_otg_ss",
+	.sysc	= &am43xx_usb_otg_ss_sysc,
+};
+
+static struct omap_hwmod am43xx_usb_otg_ss0_hwmod = {
+	.name		= "usb_otg_ss0",
+	.class		= &am43xx_usb_otg_ss_hwmod_class,
+	.clkdm_name	= "l3s_clkdm",
+	.main_clk	= "l3s_gclk",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs	= AM43XX_CM_PER_USB_OTG_SS0_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod am43xx_usb_otg_ss1_hwmod = {
+	.name		= "usb_otg_ss1",
+	.class		= &am43xx_usb_otg_ss_hwmod_class,
+	.clkdm_name	= "l3s_clkdm",
+	.main_clk	= "l3s_gclk",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs	= AM43XX_CM_PER_USB_OTG_SS1_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod_class_sysconfig am43xx_qspi_sysc = {
+	.sysc_offs      = 0x0010,
+	.sysc_flags     = SYSC_HAS_SIDLEMODE,
+	.idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+				SIDLE_SMART_WKUP),
+	.sysc_fields    = &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class am43xx_qspi_hwmod_class = {
+	.name   = "qspi",
+	.sysc   = &am43xx_qspi_sysc,
+};
+
+static struct omap_hwmod am43xx_qspi_hwmod = {
+	.name           = "qspi",
+	.class          = &am43xx_qspi_hwmod_class,
+	.clkdm_name     = "l3s_clkdm",
+	.main_clk       = "l3s_gclk",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = AM43XX_CM_PER_QSPI_CLKCTRL_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* Interfaces */
+static struct omap_hwmod_ocp_if am43xx_l3_main__l4_hs = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am43xx_l4_hs_hwmod,
+	.clk		= "l3s_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if am43xx_wkup_m3__l4_wkup = {
+	.master		= &am43xx_wkup_m3_hwmod,
+	.slave		= &am33xx_l4_wkup_hwmod,
+	.clk		= "sys_clkin_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_wkup__wkup_m3 = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am43xx_wkup_m3_hwmod,
+	.clk		= "sys_clkin_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l3_main__pruss = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_pruss_hwmod,
+	.clk		= "dpll_core_m4_ck",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_wkup__smartreflex0 = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am33xx_smartreflex0_hwmod,
+	.clk		= "sys_clkin_ck",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_wkup__smartreflex1 = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am33xx_smartreflex1_hwmod,
+	.clk		= "sys_clkin_ck",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_wkup__control = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am43xx_control_hwmod,
+	.clk		= "sys_clkin_ck",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_wkup__i2c1 = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am33xx_i2c1_hwmod,
+	.clk		= "sys_clkin_ck",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_wkup__gpio0 = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am43xx_gpio0_hwmod,
+	.clk		= "sys_clkin_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_hs__cpgmac0 = {
+	.master		= &am43xx_l4_hs_hwmod,
+	.slave		= &am33xx_cpgmac0_hwmod,
+	.clk		= "cpsw_125mhz_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_wkup__timer1 = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am33xx_timer1_hwmod,
+	.clk		= "sys_clkin_ck",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_wkup__uart1 = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am33xx_uart1_hwmod,
+	.clk		= "sys_clkin_ck",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_wkup__wd_timer1 = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am33xx_wd_timer1_hwmod,
+	.clk		= "sys_clkin_ck",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_wkup__synctimer = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am43xx_synctimer_hwmod,
+	.clk		= "sys_clkin_ck",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__timer8 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am43xx_timer8_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__timer9 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am43xx_timer9_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__timer10 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am43xx_timer10_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__timer11 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am43xx_timer11_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__epwmss3 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am43xx_epwmss3_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_epwmss3__ehrpwm3 = {
+	.master		= &am43xx_epwmss3_hwmod,
+	.slave		= &am43xx_ehrpwm3_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__epwmss4 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am43xx_epwmss4_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_epwmss4__ehrpwm4 = {
+	.master		= &am43xx_epwmss4_hwmod,
+	.slave		= &am43xx_ehrpwm4_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__epwmss5 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am43xx_epwmss5_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_epwmss5__ehrpwm5 = {
+	.master		= &am43xx_epwmss5_hwmod,
+	.slave		= &am43xx_ehrpwm5_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__mcspi2 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am43xx_spi2_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__mcspi3 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am43xx_spi3_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__mcspi4 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am43xx_spi4_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__gpio4 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am43xx_gpio4_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__gpio5 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am43xx_gpio5_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__ocp2scp0 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am43xx_ocp2scp0_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__ocp2scp1 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am43xx_ocp2scp1_hwmod,
+	.clk		= "l4ls_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l3_s__usbotgss0 = {
+	.master         = &am33xx_l3_s_hwmod,
+	.slave          = &am43xx_usb_otg_ss0_hwmod,
+	.clk            = "l3s_gclk",
+	.user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l3_s__usbotgss1 = {
+	.master         = &am33xx_l3_s_hwmod,
+	.slave          = &am43xx_usb_otg_ss1_hwmod,
+	.clk            = "l3s_gclk",
+	.user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l3_s__qspi = {
+	.master         = &am33xx_l3_s_hwmod,
+	.slave          = &am43xx_qspi_hwmod,
+	.clk            = "l3s_gclk",
+	.user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = {
+	&am33xx_l4_wkup__synctimer,
+	&am43xx_l4_ls__timer8,
+	&am43xx_l4_ls__timer9,
+	&am43xx_l4_ls__timer10,
+	&am43xx_l4_ls__timer11,
+	&am43xx_l4_ls__epwmss3,
+	&am43xx_epwmss3__ehrpwm3,
+	&am43xx_l4_ls__epwmss4,
+	&am43xx_epwmss4__ehrpwm4,
+	&am43xx_l4_ls__epwmss5,
+	&am43xx_epwmss5__ehrpwm5,
+	&am43xx_l4_ls__mcspi2,
+	&am43xx_l4_ls__mcspi3,
+	&am43xx_l4_ls__mcspi4,
+	&am43xx_l4_ls__gpio4,
+	&am43xx_l4_ls__gpio5,
+	&am43xx_l3_main__pruss,
+	&am33xx_mpu__l3_main,
+	&am33xx_mpu__prcm,
+	&am33xx_l3_s__l4_ls,
+	&am33xx_l3_s__l4_wkup,
+	&am43xx_l3_main__l4_hs,
+	&am33xx_l3_main__l3_s,
+	&am33xx_l3_main__l3_instr,
+	&am33xx_l3_main__gfx,
+	&am33xx_l3_s__l3_main,
+	&am33xx_pruss__l3_main,
+	&am43xx_wkup_m3__l4_wkup,
+	&am33xx_gfx__l3_main,
+	&am43xx_l4_wkup__wkup_m3,
+	&am43xx_l4_wkup__control,
+	&am43xx_l4_wkup__smartreflex0,
+	&am43xx_l4_wkup__smartreflex1,
+	&am43xx_l4_wkup__uart1,
+	&am43xx_l4_wkup__timer1,
+	&am43xx_l4_wkup__i2c1,
+	&am43xx_l4_wkup__gpio0,
+	&am43xx_l4_wkup__wd_timer1,
+	&am43xx_l3_s__qspi,
+	&am33xx_l4_per__dcan0,
+	&am33xx_l4_per__dcan1,
+	&am33xx_l4_per__gpio1,
+	&am33xx_l4_per__gpio2,
+	&am33xx_l4_per__gpio3,
+	&am33xx_l4_per__i2c2,
+	&am33xx_l4_per__i2c3,
+	&am33xx_l4_per__mailbox,
+	&am33xx_l4_ls__mcasp0,
+	&am33xx_l4_ls__mcasp1,
+	&am33xx_l4_ls__mmc0,
+	&am33xx_l4_ls__mmc1,
+	&am33xx_l3_s__mmc2,
+	&am33xx_l4_ls__timer2,
+	&am33xx_l4_ls__timer3,
+	&am33xx_l4_ls__timer4,
+	&am33xx_l4_ls__timer5,
+	&am33xx_l4_ls__timer6,
+	&am33xx_l4_ls__timer7,
+	&am33xx_l3_main__tpcc,
+	&am33xx_l4_ls__uart2,
+	&am33xx_l4_ls__uart3,
+	&am33xx_l4_ls__uart4,
+	&am33xx_l4_ls__uart5,
+	&am33xx_l4_ls__uart6,
+	&am33xx_l4_ls__elm,
+	&am33xx_l4_ls__epwmss0,
+	&am33xx_epwmss0__ecap0,
+	&am33xx_epwmss0__eqep0,
+	&am33xx_epwmss0__ehrpwm0,
+	&am33xx_l4_ls__epwmss1,
+	&am33xx_epwmss1__ecap1,
+	&am33xx_epwmss1__eqep1,
+	&am33xx_epwmss1__ehrpwm1,
+	&am33xx_l4_ls__epwmss2,
+	&am33xx_epwmss2__ecap2,
+	&am33xx_epwmss2__eqep2,
+	&am33xx_epwmss2__ehrpwm2,
+	&am33xx_l3_s__gpmc,
+	&am33xx_l4_ls__mcspi0,
+	&am33xx_l4_ls__mcspi1,
+	&am33xx_l3_main__tptc0,
+	&am33xx_l3_main__tptc1,
+	&am33xx_l3_main__tptc2,
+	&am33xx_l3_main__ocmc,
+	&am43xx_l4_hs__cpgmac0,
+	&am33xx_cpgmac0__mdio,
+	&am33xx_l3_main__sha0,
+	&am33xx_l3_main__aes0,
+	&am43xx_l4_ls__ocp2scp0,
+	&am43xx_l4_ls__ocp2scp1,
+	&am43xx_l3_s__usbotgss0,
+	&am43xx_l3_s__usbotgss1,
+	NULL,
+};
+
+int __init am43xx_hwmod_init(void)
+{
+	omap_hwmod_am43xx_reg();
+	omap_hwmod_init();
+	return omap_hwmod_register_links(am43xx_hwmod_ocp_ifs);
+}
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 9c3b504..1e5b12c 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -914,7 +914,7 @@
 	.name		= "emif1",
 	.class		= &omap44xx_emif_hwmod_class,
 	.clkdm_name	= "l3_emif_clkdm",
-	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+	.flags		= HWMOD_INIT_NO_IDLE,
 	.main_clk	= "ddrphy_ck",
 	.prcm = {
 		.omap4 = {
@@ -930,7 +930,7 @@
 	.name		= "emif2",
 	.class		= &omap44xx_emif_hwmod_class,
 	.clkdm_name	= "l3_emif_clkdm",
-	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+	.flags		= HWMOD_INIT_NO_IDLE,
 	.main_clk	= "ddrphy_ck",
 	.prcm = {
 		.omap4 = {
@@ -2193,7 +2193,7 @@
 	.name		= "mpu",
 	.class		= &omap44xx_mpu_hwmod_class,
 	.clkdm_name	= "mpuss_clkdm",
-	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+	.flags		= HWMOD_INIT_NO_IDLE,
 	.main_clk	= "dpll_mpu_m2_ck",
 	.prcm = {
 		.omap4 = {
diff --git a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c
index cde4155..9e08d69 100644
--- a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c
@@ -352,7 +352,7 @@
 	.name		= "emif1",
 	.class		= &omap54xx_emif_hwmod_class,
 	.clkdm_name	= "emif_clkdm",
-	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+	.flags		= HWMOD_INIT_NO_IDLE,
 	.main_clk	= "dpll_core_h11x2_ck",
 	.prcm = {
 		.omap4 = {
@@ -368,7 +368,7 @@
 	.name		= "emif2",
 	.class		= &omap54xx_emif_hwmod_class,
 	.clkdm_name	= "emif_clkdm",
-	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+	.flags		= HWMOD_INIT_NO_IDLE,
 	.main_clk	= "dpll_core_h11x2_ck",
 	.prcm = {
 		.omap4 = {
@@ -1135,7 +1135,7 @@
 	.name		= "mpu",
 	.class		= &omap54xx_mpu_hwmod_class,
 	.clkdm_name	= "mpu_clkdm",
-	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+	.flags		= HWMOD_INIT_NO_IDLE,
 	.main_clk	= "dpll_mpu_m2_ck",
 	.prcm = {
 		.omap4 = {
@@ -1146,6 +1146,77 @@
 };
 
 /*
+ * 'spinlock' class
+ * spinlock provides hardware assistance for synchronizing the processes
+ * running on multiple processors
+ */
+
+static struct omap_hwmod_class_sysconfig omap54xx_spinlock_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap54xx_spinlock_hwmod_class = {
+	.name	= "spinlock",
+	.sysc	= &omap54xx_spinlock_sysc,
+};
+
+/* spinlock */
+static struct omap_hwmod omap54xx_spinlock_hwmod = {
+	.name		= "spinlock",
+	.class		= &omap54xx_spinlock_hwmod_class,
+	.clkdm_name	= "l4cfg_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = OMAP54XX_CM_L4CFG_SPINLOCK_CLKCTRL_OFFSET,
+			.context_offs = OMAP54XX_RM_L4CFG_SPINLOCK_CONTEXT_OFFSET,
+		},
+	},
+};
+
+/*
+ * 'ocp2scp' class
+ * bridge to transform ocp interface protocol to scp (serial control port)
+ * protocol
+ */
+
+static struct omap_hwmod_class_sysconfig omap54xx_ocp2scp_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
+			SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap54xx_ocp2scp_hwmod_class = {
+	.name	= "ocp2scp",
+	.sysc	= &omap54xx_ocp2scp_sysc,
+};
+
+/* ocp2scp1 */
+static struct omap_hwmod omap54xx_ocp2scp1_hwmod = {
+	.name		= "ocp2scp1",
+	.class		= &omap54xx_ocp2scp_hwmod_class,
+	.clkdm_name	= "l3init_clkdm",
+	.main_clk	= "l4_root_clk_div",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = OMAP54XX_CM_L3INIT_OCP2SCP1_CLKCTRL_OFFSET,
+			.context_offs = OMAP54XX_RM_L3INIT_OCP2SCP1_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
+		},
+	},
+};
+
+/*
  * 'timer' class
  * general purpose timer module with accurate 1ms tick
  * This class contains several variants: ['timer_1ms', 'timer']
@@ -1465,6 +1536,123 @@
 };
 
 /*
+ * 'usb_host_hs' class
+ * high-speed multi-port usb host controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap54xx_usb_host_hs_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_MIDLEMODE | SYSC_HAS_RESET_STATUS |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
+			   MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap54xx_usb_host_hs_hwmod_class = {
+	.name	= "usb_host_hs",
+	.sysc	= &omap54xx_usb_host_hs_sysc,
+};
+
+static struct omap_hwmod omap54xx_usb_host_hs_hwmod = {
+	.name		= "usb_host_hs",
+	.class		= &omap54xx_usb_host_hs_hwmod_class,
+	.clkdm_name	= "l3init_clkdm",
+	/*
+	 * Errata: USBHOST Configured In Smart-Idle Can Lead To a Deadlock
+	 * id: i660
+	 *
+	 * Description:
+	 * In the following configuration :
+	 * - USBHOST module is set to smart-idle mode
+	 * - PRCM asserts idle_req to the USBHOST module ( This typically
+	 *   happens when the system is going to a low power mode : all ports
+	 *   have been suspended, the master part of the USBHOST module has
+	 *   entered the standby state, and SW has cut the functional clocks)
+	 * - an USBHOST interrupt occurs before the module is able to answer
+	 *   idle_ack, typically a remote wakeup IRQ.
+	 * Then the USB HOST module will enter a deadlock situation where it
+	 * is no more accessible nor functional.
+	 *
+	 * Workaround:
+	 * Don't use smart idle; use only force idle, hence HWMOD_SWSUP_SIDLE
+	 */
+
+	/*
+	 * Errata: USB host EHCI may stall when entering smart-standby mode
+	 * Id: i571
+	 *
+	 * Description:
+	 * When the USBHOST module is set to smart-standby mode, and when it is
+	 * ready to enter the standby state (i.e. all ports are suspended and
+	 * all attached devices are in suspend mode), then it can wrongly assert
+	 * the Mstandby signal too early while there are still some residual OCP
+	 * transactions ongoing. If this condition occurs, the internal state
+	 * machine may go to an undefined state and the USB link may be stuck
+	 * upon the next resume.
+	 *
+	 * Workaround:
+	 * Don't use smart standby; use only force standby,
+	 * hence HWMOD_SWSUP_MSTANDBY
+	 */
+
+	/*
+	 * During system boot; If the hwmod framework resets the module
+	 * the module will have smart idle settings; which can lead to deadlock
+	 * (above Errata Id:i660); so, dont reset the module during boot;
+	 * Use HWMOD_INIT_NO_RESET.
+	 */
+
+	.flags		= HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY |
+			  HWMOD_INIT_NO_RESET,
+	.main_clk	= "l3init_60m_fclk",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = OMAP54XX_CM_L3INIT_USB_HOST_HS_CLKCTRL_OFFSET,
+			.context_offs = OMAP54XX_RM_L3INIT_USB_HOST_HS_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'usb_tll_hs' class
+ * usb_tll_hs module is the adapter on the usb_host_hs ports
+ */
+
+static struct omap_hwmod_class_sysconfig omap54xx_usb_tll_hs_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap54xx_usb_tll_hs_hwmod_class = {
+	.name	= "usb_tll_hs",
+	.sysc	= &omap54xx_usb_tll_hs_sysc,
+};
+
+static struct omap_hwmod omap54xx_usb_tll_hs_hwmod = {
+	.name		= "usb_tll_hs",
+	.class		= &omap54xx_usb_tll_hs_hwmod_class,
+	.clkdm_name	= "l3init_clkdm",
+	.main_clk	= "l4_root_clk_div",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = OMAP54XX_CM_L3INIT_USB_TLL_HS_CLKCTRL_OFFSET,
+			.context_offs = OMAP54XX_RM_L3INIT_USB_TLL_HS_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
+		},
+	},
+};
+
+/*
  * 'usb_otg_ss' class
  * 2.0 super speed (usb_otg_ss) controller
  */
@@ -1960,6 +2148,22 @@
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l4_cfg -> spinlock */
+static struct omap_hwmod_ocp_if omap54xx_l4_cfg__spinlock = {
+	.master		= &omap54xx_l4_cfg_hwmod,
+	.slave		= &omap54xx_spinlock_hwmod,
+	.clk		= "l4_root_clk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> ocp2scp1 */
+static struct omap_hwmod_ocp_if omap54xx_l4_cfg__ocp2scp1 = {
+	.master		= &omap54xx_l4_cfg_hwmod,
+	.slave		= &omap54xx_ocp2scp1_hwmod,
+	.clk		= "l4_root_clk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l4_wkup -> timer1 */
 static struct omap_hwmod_ocp_if omap54xx_l4_wkup__timer1 = {
 	.master		= &omap54xx_l4_wkup_hwmod,
@@ -2096,6 +2300,22 @@
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l4_cfg -> usb_host_hs */
+static struct omap_hwmod_ocp_if omap54xx_l4_cfg__usb_host_hs = {
+	.master		= &omap54xx_l4_cfg_hwmod,
+	.slave		= &omap54xx_usb_host_hs_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> usb_tll_hs */
+static struct omap_hwmod_ocp_if omap54xx_l4_cfg__usb_tll_hs = {
+	.master		= &omap54xx_l4_cfg_hwmod,
+	.slave		= &omap54xx_usb_tll_hs_hwmod,
+	.clk		= "l4_root_clk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l4_cfg -> usb_otg_ss */
 static struct omap_hwmod_ocp_if omap54xx_l4_cfg__usb_otg_ss = {
 	.master		= &omap54xx_l4_cfg_hwmod,
@@ -2163,6 +2383,8 @@
 	&omap54xx_l4_per__mmc4,
 	&omap54xx_l4_per__mmc5,
 	&omap54xx_l4_cfg__mpu,
+	&omap54xx_l4_cfg__spinlock,
+	&omap54xx_l4_cfg__ocp2scp1,
 	&omap54xx_l4_wkup__timer1,
 	&omap54xx_l4_per__timer2,
 	&omap54xx_l4_per__timer3,
@@ -2180,6 +2402,8 @@
 	&omap54xx_l4_per__uart4,
 	&omap54xx_l4_per__uart5,
 	&omap54xx_l4_per__uart6,
+	&omap54xx_l4_cfg__usb_host_hs,
+	&omap54xx_l4_cfg__usb_tll_hs,
 	&omap54xx_l4_cfg__usb_otg_ss,
 	&omap54xx_l4_wkup__wd_timer2,
 	NULL,
diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c
index bd41d59..82fd8c7 100644
--- a/arch/arm/mach-omap2/opp.c
+++ b/arch/arm/mach-omap2/opp.c
@@ -17,6 +17,7 @@
  * GNU General Public License for more details.
  */
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/opp.h>
 #include <linux/cpu.h>
 
@@ -40,6 +41,9 @@
 {
 	int i, r;
 
+	if (of_have_populated_dt())
+		return -EINVAL;
+
 	if (!opp_def || !opp_def_size) {
 		pr_err("%s: invalid params!\n", __func__);
 		return -EINVAL;
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
new file mode 100644
index 0000000..10c7145
--- /dev/null
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -0,0 +1,174 @@
+/*
+ * Legacy platform_data quirks
+ *
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+#include <linux/wl12xx.h>
+
+#include <linux/platform_data/pinctrl-single.h>
+
+#include "common.h"
+#include "common-board-devices.h"
+#include "dss-common.h"
+#include "control.h"
+
+struct pdata_init {
+	const char *compatible;
+	void (*fn)(void);
+};
+
+/*
+ * Create alias for USB host PHY clock.
+ * Remove this when clock phandle can be provided via DT
+ */
+static void __init __used legacy_init_ehci_clk(char *clkname)
+{
+	int ret;
+
+	ret = clk_add_alias("main_clk", NULL, clkname, NULL);
+	if (ret)
+		pr_err("%s:Failed to add main_clk alias to %s :%d\n",
+		       __func__, clkname, ret);
+}
+
+#if IS_ENABLED(CONFIG_WL12XX)
+
+static struct wl12xx_platform_data wl12xx __initdata;
+
+static void __init __used legacy_init_wl12xx(unsigned ref_clock,
+					     unsigned tcxo_clock,
+					     int gpio)
+{
+	int res;
+
+	wl12xx.board_ref_clock = ref_clock;
+	wl12xx.board_tcxo_clock = tcxo_clock;
+	wl12xx.irq = gpio_to_irq(gpio);
+
+	res = wl12xx_set_platform_data(&wl12xx);
+	if (res) {
+		pr_err("error setting wl12xx data: %d\n", res);
+		return;
+	}
+}
+#else
+static inline void legacy_init_wl12xx(unsigned ref_clock,
+				      unsigned tcxo_clock,
+				      int gpio)
+{
+}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+static void __init hsmmc2_internal_input_clk(void)
+{
+	u32 reg;
+
+	reg = omap_ctrl_readl(OMAP343X_CONTROL_DEVCONF1);
+	reg |= OMAP2_MMCSDIO2ADPCLKISEL;
+	omap_ctrl_writel(reg, OMAP343X_CONTROL_DEVCONF1);
+}
+
+static void __init omap3_igep0020_legacy_init(void)
+{
+	omap3_igep2_display_init_of();
+}
+
+static void __init omap3_evm_legacy_init(void)
+{
+	legacy_init_wl12xx(WL12XX_REFCLOCK_38, 0, 149);
+}
+
+static void __init omap3_zoom_legacy_init(void)
+{
+	legacy_init_wl12xx(WL12XX_REFCLOCK_26, 0, 162);
+}
+#endif /* CONFIG_ARCH_OMAP3 */
+
+#ifdef CONFIG_ARCH_OMAP4
+static void __init omap4_sdp_legacy_init(void)
+{
+	omap_4430sdp_display_init_of();
+	legacy_init_wl12xx(WL12XX_REFCLOCK_26,
+			   WL12XX_TCXOCLOCK_26, 53);
+}
+
+static void __init omap4_panda_legacy_init(void)
+{
+	omap4_panda_display_init_of();
+	legacy_init_ehci_clk("auxclk3_ck");
+	legacy_init_wl12xx(WL12XX_REFCLOCK_38, 0, 53);
+}
+#endif
+
+#ifdef CONFIG_SOC_OMAP5
+static void __init omap5_uevm_legacy_init(void)
+{
+	legacy_init_ehci_clk("auxclk1_ck");
+}
+#endif
+
+static struct pcs_pdata pcs_pdata;
+
+void omap_pcs_legacy_init(int irq, void (*rearm)(void))
+{
+	pcs_pdata.irq = irq;
+	pcs_pdata.rearm = rearm;
+}
+
+struct of_dev_auxdata omap_auxdata_lookup[] __initdata = {
+#ifdef CONFIG_ARCH_OMAP3
+	OF_DEV_AUXDATA("ti,omap3-padconf", 0x48002030, "48002030.pinmux", &pcs_pdata),
+	OF_DEV_AUXDATA("ti,omap3-padconf", 0x48002a00, "48002a00.pinmux", &pcs_pdata),
+#endif
+#ifdef CONFIG_ARCH_OMAP4
+	OF_DEV_AUXDATA("ti,omap4-padconf", 0x4a100040, "4a100040.pinmux", &pcs_pdata),
+	OF_DEV_AUXDATA("ti,omap4-padconf", 0x4a31e040, "4a31e040.pinmux", &pcs_pdata),
+#endif
+	{ /* sentinel */ },
+};
+
+static struct pdata_init pdata_quirks[] __initdata = {
+#ifdef CONFIG_ARCH_OMAP3
+	{ "nokia,omap3-n9", hsmmc2_internal_input_clk, },
+	{ "nokia,omap3-n950", hsmmc2_internal_input_clk, },
+	{ "isee,omap3-igep0020", omap3_igep0020_legacy_init, },
+	{ "ti,omap3-evm-37xx", omap3_evm_legacy_init, },
+	{ "ti,omap3-zoom3", omap3_zoom_legacy_init, },
+#endif
+#ifdef CONFIG_ARCH_OMAP4
+	{ "ti,omap4-sdp", omap4_sdp_legacy_init, },
+	{ "ti,omap4-panda", omap4_panda_legacy_init, },
+#endif
+#ifdef CONFIG_SOC_OMAP5
+	{ "ti,omap5-uevm", omap5_uevm_legacy_init, },
+#endif
+	{ /* sentinel */ },
+};
+
+void __init pdata_quirks_init(struct of_device_id *omap_dt_match_table)
+{
+	struct pdata_init *quirks = pdata_quirks;
+
+	omap_sdrc_init(NULL, NULL);
+	of_platform_populate(NULL, omap_dt_match_table,
+			     omap_auxdata_lookup, NULL);
+
+	while (quirks->compatible) {
+		if (of_machine_is_compatible(quirks->compatible)) {
+			if (quirks->fn)
+				quirks->fn();
+			break;
+		}
+		quirks++;
+	}
+}
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index e742118..360b2da 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -266,7 +266,12 @@
 
 static inline void omap_init_cpufreq(void)
 {
-	struct platform_device_info devinfo = { .name = "omap-cpufreq", };
+	struct platform_device_info devinfo = { };
+
+	if (!of_have_populated_dt())
+		devinfo.name = "omap-cpufreq";
+	else
+		devinfo.name = "cpufreq-cpu0";
 	platform_device_register_full(&devinfo);
 }
 
@@ -300,10 +305,11 @@
 		/* Smartreflex device init */
 		omap_devinit_smartreflex();
 
-		/* cpufreq dummy device instantiation */
-		omap_init_cpufreq();
 	}
 
+	/* cpufreq dummy device instantiation */
+	omap_init_cpufreq();
+
 #ifdef CONFIG_SUSPEND
 	suspend_set_ops(&omap_pm_ops);
 #endif
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index ce956b0..8c07594 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -62,16 +62,6 @@
 
 static struct clk *osc_ck, *emul_ck;
 
-static int omap2_fclks_active(void)
-{
-	u32 f1, f2;
-
-	f1 = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
-	f2 = omap2_cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
-
-	return (f1 | f2) ? 1 : 0;
-}
-
 static int omap2_enter_full_retention(void)
 {
 	u32 l;
@@ -142,17 +132,7 @@
 
 static int omap2_allow_mpu_retention(void)
 {
-	u32 l;
-
-	/* Check for MMC, UART2, UART1, McSPI2, McSPI1 and DSS1. */
-	l = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
-	if (l & (OMAP2420_EN_MMC_MASK | OMAP24XX_EN_UART2_MASK |
-		 OMAP24XX_EN_UART1_MASK | OMAP24XX_EN_MCSPI2_MASK |
-		 OMAP24XX_EN_MCSPI1_MASK | OMAP24XX_EN_DSS1_MASK))
-		return 0;
-	/* Check for UART3. */
-	l = omap2_cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2);
-	if (l & OMAP24XX_EN_UART3_MASK)
+	if (!omap2xxx_cm_mpu_retention_allowed())
 		return 0;
 	if (sti_console_enabled)
 		return 0;
@@ -188,7 +168,7 @@
 
 static int omap2_can_sleep(void)
 {
-	if (omap2_fclks_active())
+	if (omap2xxx_cm_fclks_active())
 		return 0;
 	if (__clk_is_enabled(osc_ck))
 		return 0;
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 5a2d803..93b80e5 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -430,8 +430,7 @@
 			 OMAP3430_IVA2_MOD, CM_FCLKEN);
 
 	/* Set IVA2 boot mode to 'idle' */
-	omap_ctrl_writel(OMAP3_IVA2_BOOTMOD_IDLE,
-			 OMAP343X_CONTROL_IVA2_BOOTMOD);
+	omap3_ctrl_set_iva_bootmode_idle();
 
 	/* Un-reset IVA2 */
 	omap2_prm_write_mod_reg(0, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index baf3d8b..da5a59a 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -257,6 +257,7 @@
 extern void omap44xx_powerdomains_init(void);
 extern void omap54xx_powerdomains_init(void);
 extern void dra7xx_powerdomains_init(void);
+void am43xx_powerdomains_init(void);
 
 extern struct pwrdm_ops omap2_pwrdm_operations;
 extern struct pwrdm_ops omap3_pwrdm_operations;
diff --git a/arch/arm/mach-omap2/powerdomains43xx_data.c b/arch/arm/mach-omap2/powerdomains43xx_data.c
new file mode 100644
index 0000000..95fee54
--- /dev/null
+++ b/arch/arm/mach-omap2/powerdomains43xx_data.c
@@ -0,0 +1,136 @@
+/*
+ * AM43xx Power domains framework
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include "powerdomain.h"
+
+#include "prcm-common.h"
+#include "prcm44xx.h"
+#include "prcm43xx.h"
+
+static struct powerdomain gfx_43xx_pwrdm = {
+	.name		  = "gfx_pwrdm",
+	.voltdm		  = { .name = "core" },
+	.prcm_offs	  = AM43XX_PRM_GFX_INST,
+	.prcm_partition	  = AM43XX_PRM_PARTITION,
+	.pwrsts		  = PWRSTS_OFF_ON,
+	.banks		  = 1,
+	.pwrsts_mem_on	= {
+		[0] = PWRSTS_ON,	/* gfx_mem */
+	},
+	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
+};
+
+static struct powerdomain mpu_43xx_pwrdm = {
+	.name		  = "mpu_pwrdm",
+	.voltdm		  = { .name = "mpu" },
+	.prcm_offs	  = AM43XX_PRM_MPU_INST,
+	.prcm_partition	  = AM43XX_PRM_PARTITION,
+	.pwrsts		  = PWRSTS_OFF_RET_ON,
+	.pwrsts_logic_ret = PWRSTS_OFF_RET,
+	.banks		  = 3,
+	.pwrsts_mem_ret	= {
+		[0] = PWRSTS_OFF_RET,	/* mpu_l1 */
+		[1] = PWRSTS_OFF_RET,	/* mpu_l2 */
+		[2] = PWRSTS_OFF_RET,	/* mpu_ram */
+	},
+	.pwrsts_mem_on	= {
+		[0] = PWRSTS_ON,	/* mpu_l1 */
+		[1] = PWRSTS_ON,	/* mpu_l2 */
+		[2] = PWRSTS_ON,	/* mpu_ram */
+	},
+	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
+};
+
+static struct powerdomain rtc_43xx_pwrdm = {
+	.name		  = "rtc_pwrdm",
+	.voltdm		  = { .name = "rtc" },
+	.prcm_offs	  = AM43XX_PRM_RTC_INST,
+	.prcm_partition	  = AM43XX_PRM_PARTITION,
+	.pwrsts		  = PWRSTS_ON,
+};
+
+static struct powerdomain wkup_43xx_pwrdm = {
+	.name		  = "wkup_pwrdm",
+	.voltdm		  = { .name = "core" },
+	.prcm_offs	  = AM43XX_PRM_WKUP_INST,
+	.prcm_partition	  = AM43XX_PRM_PARTITION,
+	.pwrsts		  = PWRSTS_ON,
+	.banks		  = 1,
+	.pwrsts_mem_on	= {
+		[0] = PWRSTS_ON,	/* debugss_mem */
+	},
+};
+
+static struct powerdomain tamper_43xx_pwrdm = {
+	.name		  = "tamper_pwrdm",
+	.voltdm		  = { .name = "tamper" },
+	.prcm_offs	  = AM43XX_PRM_TAMPER_INST,
+	.prcm_partition	  = AM43XX_PRM_PARTITION,
+	.pwrsts		  = PWRSTS_ON,
+};
+
+static struct powerdomain cefuse_43xx_pwrdm = {
+	.name		  = "cefuse_pwrdm",
+	.voltdm		  = { .name = "core" },
+	.prcm_offs	  = AM43XX_PRM_CEFUSE_INST,
+	.prcm_partition	  = AM43XX_PRM_PARTITION,
+	.pwrsts		  = PWRSTS_OFF_ON,
+	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
+};
+
+static struct powerdomain per_43xx_pwrdm = {
+	.name		  = "per_pwrdm",
+	.voltdm		  = { .name = "core" },
+	.prcm_offs	  = AM43XX_PRM_PER_INST,
+	.prcm_partition	  = AM43XX_PRM_PARTITION,
+	.pwrsts		  = PWRSTS_OFF_RET_ON,
+	.pwrsts_logic_ret = PWRSTS_OFF_RET,
+	.banks		  = 4,
+	.pwrsts_mem_ret	= {
+		[0] = PWRSTS_OFF_RET,	/* icss_mem */
+		[1] = PWRSTS_OFF_RET,	/* per_mem */
+		[2] = PWRSTS_OFF_RET,	/* ram1_mem */
+		[3] = PWRSTS_OFF_RET,	/* ram2_mem */
+	},
+	.pwrsts_mem_on	= {
+		[0] = PWRSTS_ON,	/* icss_mem */
+		[1] = PWRSTS_ON,	/* per_mem */
+		[2] = PWRSTS_ON,	/* ram1_mem */
+		[3] = PWRSTS_ON,	/* ram2_mem */
+	},
+	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
+};
+
+static struct powerdomain *powerdomains_am43xx[] __initdata = {
+	&gfx_43xx_pwrdm,
+	&mpu_43xx_pwrdm,
+	&rtc_43xx_pwrdm,
+	&wkup_43xx_pwrdm,
+	&tamper_43xx_pwrdm,
+	&cefuse_43xx_pwrdm,
+	&per_43xx_pwrdm,
+	NULL
+};
+
+static int am43xx_check_vcvp(void)
+{
+	return 0;
+}
+
+void __init am43xx_powerdomains_init(void)
+{
+	omap4_pwrdm_operations.pwrdm_has_voltdm = am43xx_check_vcvp;
+	pwrdm_register_platform_funcs(&omap4_pwrdm_operations);
+	pwrdm_register_pwrdms(powerdomains_am43xx);
+	pwrdm_complete_init();
+}
diff --git a/arch/arm/mach-omap2/prcm43xx.h b/arch/arm/mach-omap2/prcm43xx.h
new file mode 100644
index 0000000..7785be9
--- /dev/null
+++ b/arch/arm/mach-omap2/prcm43xx.h
@@ -0,0 +1,146 @@
+/*
+ * AM43x PRCM defines
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_PRCM_43XX_H
+#define __ARCH_ARM_MACH_OMAP2_PRCM_43XX_H
+
+#define AM43XX_PRM_PARTITION				1
+#define AM43XX_CM_PARTITION				1
+
+/* PRM instances */
+#define AM43XX_PRM_OCP_SOCKET_INST			0x0000
+#define AM43XX_PRM_MPU_INST				0x0300
+#define AM43XX_PRM_GFX_INST				0x0400
+#define AM43XX_PRM_RTC_INST				0x0500
+#define AM43XX_PRM_TAMPER_INST				0x0600
+#define AM43XX_PRM_CEFUSE_INST				0x0700
+#define AM43XX_PRM_PER_INST				0x0800
+#define AM43XX_PRM_WKUP_INST				0x2000
+#define AM43XX_PRM_DEVICE_INST				0x4000
+
+/* RM RSTCTRL offsets */
+#define AM43XX_RM_PER_RSTCTRL_OFFSET			0x0010
+#define AM43XX_RM_GFX_RSTCTRL_OFFSET			0x0010
+#define AM43XX_RM_WKUP_RSTCTRL_OFFSET			0x0010
+
+/* RM RSTST offsets */
+#define AM43XX_RM_GFX_RSTST_OFFSET			0x0014
+#define AM43XX_RM_WKUP_RSTST_OFFSET			0x0014
+
+/* CM instances */
+#define AM43XX_CM_WKUP_INST				0x2800
+#define AM43XX_CM_DEVICE_INST				0x4100
+#define AM43XX_CM_DPLL_INST				0x4200
+#define AM43XX_CM_MPU_INST				0x8300
+#define AM43XX_CM_GFX_INST				0x8400
+#define AM43XX_CM_RTC_INST				0x8500
+#define AM43XX_CM_TAMPER_INST				0x8600
+#define AM43XX_CM_CEFUSE_INST				0x8700
+#define AM43XX_CM_PER_INST				0x8800
+
+/* CD offsets */
+#define AM43XX_CM_WKUP_L3_AON_CDOFFS			0x0000
+#define AM43XX_CM_WKUP_L3S_TSC_CDOFFS			0x0100
+#define AM43XX_CM_WKUP_L4_WKUP_AON_CDOFFS		0x0200
+#define AM43XX_CM_WKUP_WKUP_CDOFFS			0x0300
+#define AM43XX_CM_MPU_MPU_CDOFFS			0x0000
+#define AM43XX_CM_GFX_GFX_L3_CDOFFS			0x0000
+#define AM43XX_CM_RTC_RTC_CDOFFS			0x0000
+#define AM43XX_CM_TAMPER_TAMPER_CDOFFS			0x0000
+#define AM43XX_CM_CEFUSE_CEFUSE_CDOFFS			0x0000
+#define AM43XX_CM_PER_L3_CDOFFS				0x0000
+#define AM43XX_CM_PER_L3S_CDOFFS			0x0200
+#define AM43XX_CM_PER_ICSS_CDOFFS			0x0300
+#define AM43XX_CM_PER_L4LS_CDOFFS			0x0400
+#define AM43XX_CM_PER_EMIF_CDOFFS			0x0700
+#define AM43XX_CM_PER_DSS_CDOFFS			0x0a00
+#define AM43XX_CM_PER_CPSW_CDOFFS			0x0b00
+#define AM43XX_CM_PER_OCPWP_L3_CDOFFS			0x0c00
+
+/* CLK CTRL offsets */
+#define AM43XX_CM_PER_UART1_CLKCTRL_OFFSET		0x0580
+#define AM43XX_CM_PER_UART2_CLKCTRL_OFFSET		0x0588
+#define AM43XX_CM_PER_UART3_CLKCTRL_OFFSET		0x0590
+#define AM43XX_CM_PER_UART4_CLKCTRL_OFFSET		0x0598
+#define AM43XX_CM_PER_UART5_CLKCTRL_OFFSET		0x05a0
+#define AM43XX_CM_PER_DCAN0_CLKCTRL_OFFSET		0x0428
+#define AM43XX_CM_PER_DCAN1_CLKCTRL_OFFSET		0x0430
+#define AM43XX_CM_PER_ELM_CLKCTRL_OFFSET		0x0468
+#define AM43XX_CM_PER_EPWMSS0_CLKCTRL_OFFSET		0x0438
+#define AM43XX_CM_PER_EPWMSS1_CLKCTRL_OFFSET		0x0440
+#define AM43XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET		0x0448
+#define AM43XX_CM_PER_GPIO1_CLKCTRL_OFFSET		0x0478
+#define AM43XX_CM_PER_GPIO2_CLKCTRL_OFFSET		0x0480
+#define AM43XX_CM_PER_GPIO3_CLKCTRL_OFFSET		0x0488
+#define AM43XX_CM_PER_I2C1_CLKCTRL_OFFSET		0x04a8
+#define AM43XX_CM_PER_I2C2_CLKCTRL_OFFSET		0x04b0
+#define AM43XX_CM_PER_MAILBOX0_CLKCTRL_OFFSET		0x04b8
+#define AM43XX_CM_PER_MMC0_CLKCTRL_OFFSET		0x04c0
+#define AM43XX_CM_PER_MMC1_CLKCTRL_OFFSET		0x04c8
+#define AM43XX_CM_PER_SPI0_CLKCTRL_OFFSET		0x0500
+#define AM43XX_CM_PER_SPI1_CLKCTRL_OFFSET		0x0508
+#define AM43XX_CM_PER_SPINLOCK_CLKCTRL_OFFSET		0x0528
+#define AM43XX_CM_PER_TIMER2_CLKCTRL_OFFSET		0x0530
+#define AM43XX_CM_PER_TIMER3_CLKCTRL_OFFSET		0x0538
+#define AM43XX_CM_PER_TIMER4_CLKCTRL_OFFSET		0x0540
+#define AM43XX_CM_PER_TIMER5_CLKCTRL_OFFSET		0x0548
+#define AM43XX_CM_PER_TIMER6_CLKCTRL_OFFSET		0x0550
+#define AM43XX_CM_PER_TIMER7_CLKCTRL_OFFSET		0x0558
+#define AM43XX_CM_WKUP_WKUP_M3_CLKCTRL_OFFSET		0x0228
+#define AM43XX_CM_WKUP_CONTROL_CLKCTRL_OFFSET		0x0360
+#define AM43XX_CM_WKUP_SMARTREFLEX0_CLKCTRL_OFFSET	0x0350
+#define AM43XX_CM_WKUP_SMARTREFLEX1_CLKCTRL_OFFSET	0x0358
+#define AM43XX_CM_WKUP_UART0_CLKCTRL_OFFSET		0x0348
+#define AM43XX_CM_WKUP_TIMER1_CLKCTRL_OFFSET		0x0328
+#define AM43XX_CM_WKUP_I2C0_CLKCTRL_OFFSET		0x0340
+#define AM43XX_CM_WKUP_GPIO0_CLKCTRL_OFFSET		0x0368
+#define AM43XX_CM_WKUP_ADC_TSC_CLKCTRL_OFFSET		0x0120
+#define AM43XX_CM_WKUP_WDT1_CLKCTRL_OFFSET		0x0338
+#define AM43XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET		0x0220
+#define AM43XX_CM_RTC_RTC_CLKCTRL_OFFSET		0x0020
+#define AM43XX_CM_PER_MMC2_CLKCTRL_OFFSET		0x0248
+#define AM43XX_CM_PER_QSPI_CLKCTRL_OFFSET               0x0258
+#define AM43XX_CM_PER_GPMC_CLKCTRL_OFFSET		0x0220
+#define AM43XX_CM_PER_MCASP0_CLKCTRL_OFFSET		0x0238
+#define AM43XX_CM_PER_MCASP1_CLKCTRL_OFFSET		0x0240
+#define AM43XX_CM_PER_L4LS_CLKCTRL_OFFSET		0x0420
+#define AM43XX_CM_PER_L3_CLKCTRL_OFFSET			0x0020
+#define AM43XX_CM_PER_TPCC_CLKCTRL_OFFSET		0x0078
+#define AM43XX_CM_PER_TPTC0_CLKCTRL_OFFSET		0x0080
+#define AM43XX_CM_PER_TPTC1_CLKCTRL_OFFSET		0x0088
+#define AM43XX_CM_PER_TPTC2_CLKCTRL_OFFSET		0x0090
+#define AM43XX_CM_PER_CPGMAC0_CLKCTRL_OFFSET		0x0b20
+#define AM43XX_CM_PER_PRUSS_CLKCTRL_OFFSET		0x0320
+#define AM43XX_CM_GFX_GFX_CLKCTRL_OFFSET		0x0020
+#define AM43XX_CM_PER_L4HS_CLKCTRL_OFFSET		0x00a0
+#define AM43XX_CM_MPU_MPU_CLKCTRL_OFFSET		0x0020
+#define AM43XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET		0x0040
+#define AM43XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET		0x0050
+#define AM43XX_CM_PER_SHA0_CLKCTRL_OFFSET		0x0058
+#define AM43XX_CM_PER_AES0_CLKCTRL_OFFSET		0x0028
+#define AM43XX_CM_PER_TIMER8_CLKCTRL_OFFSET		0x0560
+#define AM43XX_CM_PER_TIMER9_CLKCTRL_OFFSET		0x0568
+#define AM43XX_CM_PER_TIMER10_CLKCTRL_OFFSET		0x0570
+#define AM43XX_CM_PER_TIMER11_CLKCTRL_OFFSET		0x0578
+#define AM43XX_CM_WKUP_SYNCTIMER_CLKCTRL_OFFSET		0x0230
+#define AM43XX_CM_PER_EPWMSS3_CLKCTRL_OFFSET		0x0450
+#define AM43XX_CM_PER_EPWMSS4_CLKCTRL_OFFSET		0x0458
+#define AM43XX_CM_PER_EPWMSS5_CLKCTRL_OFFSET		0x0460
+#define AM43XX_CM_PER_SPI2_CLKCTRL_OFFSET		0x0510
+#define AM43XX_CM_PER_SPI3_CLKCTRL_OFFSET		0x0518
+#define AM43XX_CM_PER_SPI4_CLKCTRL_OFFSET		0x0520
+#define AM43XX_CM_PER_GPIO4_CLKCTRL_OFFSET		0x0490
+#define AM43XX_CM_PER_GPIO5_CLKCTRL_OFFSET		0x0498
+#define AM43XX_CM_PER_USB_OTG_SS0_CLKCTRL_OFFSET	0x0260
+#define AM43XX_CM_PER_USBPHYOCP2SCP0_CLKCTRL_OFFSET	0x05B8
+#define AM43XX_CM_PER_USB_OTG_SS1_CLKCTRL_OFFSET        0x0268
+#define AM43XX_CM_PER_USBPHYOCP2SCP1_CLKCTRL_OFFSET	0x05C0
+
+#endif
diff --git a/arch/arm/mach-omap2/prm3xxx.h b/arch/arm/mach-omap2/prm3xxx.h
index 277f717..f8eb833 100644
--- a/arch/arm/mach-omap2/prm3xxx.h
+++ b/arch/arm/mach-omap2/prm3xxx.h
@@ -144,7 +144,13 @@
 extern void omap3_prm_vcvp_write(u32 val, u8 offset);
 extern u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
 
-extern void omap3xxx_prm_reconfigure_io_chain(void);
+#ifdef CONFIG_ARCH_OMAP3
+void omap3xxx_prm_reconfigure_io_chain(void);
+#else
+static inline void omap3xxx_prm_reconfigure_io_chain(void)
+{
+}
+#endif
 
 /* PRM interrupt-related functions */
 extern void omap3xxx_prm_read_pending_irqs(unsigned long *events);
diff --git a/arch/arm/mach-omap2/prm44xx_54xx.h b/arch/arm/mach-omap2/prm44xx_54xx.h
index 7cd22ab..a085d9c 100644
--- a/arch/arm/mach-omap2/prm44xx_54xx.h
+++ b/arch/arm/mach-omap2/prm44xx_54xx.h
@@ -42,7 +42,13 @@
 extern void omap4_prm_vcvp_write(u32 val, u8 offset);
 extern u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
 
-extern void omap44xx_prm_reconfigure_io_chain(void);
+#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)
+void omap44xx_prm_reconfigure_io_chain(void);
+#else
+static inline void omap44xx_prm_reconfigure_io_chain(void)
+{
+}
+#endif
 
 /* PRM interrupt-related functions */
 extern void omap44xx_prm_read_pending_irqs(unsigned long *events);
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 228b850..a2e1174 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -24,6 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 
+#include "soc.h"
 #include "prm2xxx_3xxx.h"
 #include "prm2xxx.h"
 #include "prm3xxx.h"
@@ -322,6 +323,16 @@
 		prcm_irq_chips[i] = gc;
 	}
 
+	if (of_have_populated_dt()) {
+		int irq = omap_prcm_event_to_irq("io");
+		if (cpu_is_omap34xx())
+			omap_pcs_legacy_init(irq,
+				omap3xxx_prm_reconfigure_io_chain);
+		else
+			omap_pcs_legacy_init(irq,
+				omap44xx_prm_reconfigure_io_chain);
+	}
+
 	return 0;
 
 err:
diff --git a/arch/arm/mach-omap2/soc.h b/arch/arm/mach-omap2/soc.h
index 4588df1..076bd90 100644
--- a/arch/arm/mach-omap2/soc.h
+++ b/arch/arm/mach-omap2/soc.h
@@ -455,9 +455,7 @@
 #define OMAP4470_REV_ES1_0	(OMAP447X_CLASS | (0x10 << 8))
 
 #define OMAP54XX_CLASS		0x54000054
-#define OMAP5430_REV_ES1_0	(OMAP54XX_CLASS | (0x30 << 16) | (0x10 << 8))
 #define OMAP5430_REV_ES2_0	(OMAP54XX_CLASS | (0x30 << 16) | (0x20 << 8))
-#define OMAP5432_REV_ES1_0	(OMAP54XX_CLASS | (0x32 << 16) | (0x10 << 8))
 #define OMAP5432_REV_ES2_0	(OMAP54XX_CLASS | (0x32 << 16) | (0x20 << 8))
 
 void omap2xxx_check_revision(void);
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index fa74a06..3ca81e0 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -55,6 +55,7 @@
 #include "soc.h"
 #include "common.h"
 #include "powerdomain.h"
+#include "omap-secure.h"
 
 #define REALTIME_COUNTER_BASE				0x48243200
 #define INCREMENTER_NUMERATOR_OFFSET			0x10
@@ -66,6 +67,15 @@
 static struct omap_dm_timer clkev;
 static struct clock_event_device clockevent_gpt;
 
+#ifdef CONFIG_SOC_HAS_REALTIME_COUNTER
+static unsigned long arch_timer_freq;
+
+void set_cntfreq(void)
+{
+	omap_smc1(OMAP5_DRA7_MON_SET_CNTFRQ_INDEX, arch_timer_freq);
+}
+#endif
+
 static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
 {
 	struct clock_event_device *evt = &clockevent_gpt;
@@ -78,7 +88,7 @@
 
 static struct irqaction omap2_gp_timer_irq = {
 	.name		= "gp_timer",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
 	.handler	= omap2_gp_timer_interrupt,
 };
 
@@ -515,6 +525,10 @@
 		num = 8;
 		den = 25;
 		break;
+	case 20000000:
+		num = 192;
+		den = 625;
+		break;
 	case 2600000:
 		num = 384;
 		den = 1625;
@@ -542,6 +556,9 @@
 	reg |= den;
 	__raw_writel(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET);
 
+	arch_timer_freq = (rate / den) * num;
+	set_cntfreq();
+
 	iounmap(base);
 }
 #else
@@ -628,7 +645,7 @@
 #endif /* CONFIG_HAVE_ARM_TWD */
 #endif /* CONFIG_ARCH_OMAP4 */
 
-#ifdef CONFIG_SOC_OMAP5
+#if defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX)
 void __init omap5_realtime_timer_init(void)
 {
 	omap4_sync32k_timer_init();
@@ -636,7 +653,7 @@
 
 	clocksource_of_init();
 }
-#endif /* CONFIG_SOC_OMAP5 */
+#endif /* CONFIG_SOC_OMAP5 || CONFIG_SOC_DRA7XX */
 
 /**
  * omap_timer_init - build and register timer device with an
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
index c05898f..b0d54da 100644
--- a/arch/arm/mach-omap2/twl-common.c
+++ b/arch/arm/mach-omap2/twl-common.c
@@ -24,6 +24,7 @@
 #include <linux/i2c/twl.h>
 #include <linux/gpio.h>
 #include <linux/string.h>
+#include <linux/phy/phy.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
 
@@ -90,8 +91,18 @@
 }
 
 #if defined(CONFIG_ARCH_OMAP3)
+struct phy_consumer consumers[] = {
+	PHY_CONSUMER("musb-hdrc.0", "usb"),
+};
+
+struct phy_init_data init_data = {
+	.consumers = consumers,
+	.num_consumers = ARRAY_SIZE(consumers),
+};
+
 static struct twl4030_usb_data omap3_usb_pdata = {
 	.usb_mode	= T2_USB_MODE_ULPI,
+	.init_data	= &init_data,
 };
 
 static int omap3_batt_table[] = {
diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c
index e83a6a4..10855eb 100644
--- a/arch/arm/mach-omap2/usb-host.c
+++ b/arch/arm/mach-omap2/usb-host.c
@@ -435,6 +435,7 @@
 	struct platform_device *pdev;
 	char *phy_id;
 	struct platform_device_info pdevinfo;
+	struct usb_phy_gen_xceiv_platform_data nop_pdata;
 
 	for (i = 0; i < num_phys; i++) {
 
@@ -455,11 +456,18 @@
 			return -ENOMEM;
 		}
 
+		/* set platform data */
+		memset(&nop_pdata, 0, sizeof(nop_pdata));
+		if (gpio_is_valid(phy->vcc_gpio))
+			nop_pdata.needs_vcc = true;
+		nop_pdata.gpio_reset = phy->reset_gpio;
+		nop_pdata.type = USB_PHY_TYPE_USB2;
+
 		/* create a NOP PHY device */
 		memset(&pdevinfo, 0, sizeof(pdevinfo));
 		pdevinfo.name = nop_name;
 		pdevinfo.id = phy->port;
-		pdevinfo.data = phy->platform_data;
+		pdevinfo.data = &nop_pdata;
 		pdevinfo.size_data =
 			sizeof(struct usb_phy_gen_xceiv_platform_data);
 		scnprintf(phy_id, MAX_STR, "usb_phy_gen_xceiv.%d",
@@ -474,14 +482,6 @@
 
 		usb_bind_phy("ehci-omap.0", phy->port - 1, phy_id);
 
-		/* Do we need RESET regulator ? */
-		if (gpio_is_valid(phy->reset_gpio)) {
-			scnprintf(rail_name, MAX_STR,
-					"hsusb%d_reset", phy->port);
-			usbhs_add_regulator(rail_name, phy_id, "reset",
-						phy->reset_gpio, 1);
-		}
-
 		/* Do we need VCC regulator ? */
 		if (gpio_is_valid(phy->vcc_gpio)) {
 			scnprintf(rail_name, MAX_STR, "hsusb%d_vcc", phy->port);
diff --git a/arch/arm/mach-omap2/usb.h b/arch/arm/mach-omap2/usb.h
index e7261eb..4ba2ae7 100644
--- a/arch/arm/mach-omap2/usb.h
+++ b/arch/arm/mach-omap2/usb.h
@@ -58,7 +58,6 @@
 	int reset_gpio;
 	int vcc_gpio;
 	bool vcc_polarity;	/* 1 active high, 0 active low */
-	void *platform_data;
 };
 
 extern void usb_musb_init(struct omap_musb_board_data *board_data);
diff --git a/arch/arm/mach-prima2/common.c b/arch/arm/mach-prima2/common.c
index e110b6d..d49aff7 100644
--- a/arch/arm/mach-prima2/common.c
+++ b/arch/arm/mach-prima2/common.c
@@ -6,7 +6,6 @@
  * Licensed under GPLv2 or later.
  */
 
-#include <linux/clocksource.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <asm/sizes.h>
@@ -21,13 +20,6 @@
 	sirfsoc_pm_init();
 }
 
-static __init void sirfsoc_init_time(void)
-{
-	/* initialize clocking early, we want to set the OS timer */
-	sirfsoc_of_clk_init();
-	clocksource_of_init();
-}
-
 static __init void sirfsoc_map_io(void)
 {
 	sirfsoc_map_lluart();
@@ -43,7 +35,6 @@
 DT_MACHINE_START(ATLAS6_DT, "Generic ATLAS6 (Flattened Device Tree)")
 	/* Maintainer: Barry Song <baohua.song@csr.com> */
 	.map_io         = sirfsoc_map_io,
-	.init_time	= sirfsoc_init_time,
 	.init_late	= sirfsoc_init_late,
 	.dt_compat      = atlas6_dt_match,
 	.restart	= sirfsoc_restart,
@@ -59,7 +50,6 @@
 DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)")
 	/* Maintainer: Barry Song <baohua.song@csr.com> */
 	.map_io         = sirfsoc_map_io,
-	.init_time	= sirfsoc_init_time,
 	.dma_zone_size	= SZ_256M,
 	.init_late	= sirfsoc_init_late,
 	.dt_compat      = prima2_dt_match,
@@ -77,7 +67,6 @@
 	/* Maintainer: Barry Song <baohua.song@csr.com> */
 	.smp            = smp_ops(sirfsoc_smp_ops),
 	.map_io         = sirfsoc_map_io,
-	.init_time	= sirfsoc_init_time,
 	.init_late	= sirfsoc_init_late,
 	.dt_compat      = marco_dt_match,
 	.restart	= sirfsoc_restart,
diff --git a/arch/arm/mach-prima2/common.h b/arch/arm/mach-prima2/common.h
index a630485..4b76806 100644
--- a/arch/arm/mach-prima2/common.h
+++ b/arch/arm/mach-prima2/common.h
@@ -23,7 +23,6 @@
 extern void sirfsoc_cpu_die(unsigned int cpu);
 
 extern void __init sirfsoc_of_irq_init(void);
-extern void __init sirfsoc_of_clk_init(void);
 extern void sirfsoc_restart(enum reboot_mode, const char *);
 extern asmlinkage void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs);
 
diff --git a/arch/arm/mach-pxa/include/mach/gpio.h b/arch/arm/mach-pxa/include/mach/gpio.h
deleted file mode 100644
index 0248e43..0000000
--- a/arch/arm/mach-pxa/include/mach/gpio.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * arch/arm/mach-pxa/include/mach/gpio.h
- *
- * PXA GPIO wrappers for arch-neutral GPIO calls
- *
- * Written by Philipp Zabel <philipp.zabel@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#ifndef __ASM_ARCH_PXA_GPIO_H
-#define __ASM_ARCH_PXA_GPIO_H
-
-#include <asm-generic/gpio.h>
-
-#include <mach/irqs.h>
-#include <mach/hardware.h>
-
-#endif
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 25ee12b..cf073de 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -5,12 +5,13 @@
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_GIC
 	select CACHE_L2X0
-	select HAVE_ARM_TWD if LOCAL_TIMERS
+	select HAVE_ARM_TWD if SMP
 	select HAVE_SMP
-	select LOCAL_TIMERS if SMP
 	select COMMON_CLK
 	select GENERIC_CLOCKEVENTS
 	select DW_APB_TIMER_OF
+	select ARM_GLOBAL_TIMER
+	select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
 	help
 	  Support for Rockchip's Cortex-A9 Single-to-Quad-Core-SoCs
 	  containing the RK2928, RK30xx and RK31xx series.
diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c
index 724d2d8..82c0b07 100644
--- a/arch/arm/mach-rockchip/rockchip.c
+++ b/arch/arm/mach-rockchip/rockchip.c
@@ -19,18 +19,10 @@
 #include <linux/init.h>
 #include <linux/of_platform.h>
 #include <linux/irqchip.h>
-#include <linux/dw_apb_timer.h>
-#include <linux/clk-provider.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/hardware/cache-l2x0.h>
 
-static void __init rockchip_timer_init(void)
-{
-	of_clk_init(NULL);
-	clocksource_of_init();
-}
-
 static void __init rockchip_dt_init(void)
 {
 	l2x0_of_init(0, ~0UL);
@@ -47,6 +39,5 @@
 
 DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)")
 	.init_machine	= rockchip_dt_init,
-	.init_time	= rockchip_timer_init,
 	.dt_compat	= rockchip_board_dt_compat,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig
index dba2173..8f1d327 100644
--- a/arch/arm/mach-s3c24xx/Kconfig
+++ b/arch/arm/mach-s3c24xx/Kconfig
@@ -28,6 +28,7 @@
 	select CPU_ARM920T
 	select CPU_LLSERIAL_S3C2410
 	select S3C2410_CLOCK
+	select S3C2410_DMA if S3C24XX_DMA
 	select ARM_S3C2410_CPUFREQ if ARM_S3C24XX_CPUFREQ
 	select S3C2410_PM if PM
 	select SAMSUNG_WDT_RESET
@@ -70,6 +71,7 @@
 	select CPU_ARM920T
 	select CPU_LLSERIAL_S3C2440
 	select S3C2410_CLOCK
+	select S3C2410_DMA if S3C24XX_DMA
 	select S3C2410_PM if PM
 	help
 	  Support for S3C2442 Samsung Mobile CPU based systems.
@@ -148,7 +150,6 @@
 config S3C2410_DMA
 	bool
 	depends on S3C24XX_DMA && (CPU_S3C2410 || CPU_S3C2442)
-	default y if CPU_S3C2410 || CPU_S3C2442
 	help
 	  DMA device selection for S3C2410 and compatible CPUs
 
diff --git a/arch/arm/mach-s3c24xx/clock-s3c2412.c b/arch/arm/mach-s3c24xx/clock-s3c2412.c
index d8f253f..11b3b28 100644
--- a/arch/arm/mach-s3c24xx/clock-s3c2412.c
+++ b/arch/arm/mach-s3c24xx/clock-s3c2412.c
@@ -484,22 +484,22 @@
 
 static struct clk init_clocks[] = {
 	{
-		.name		= "dma",
+		.name		= "dma.0",
 		.parent		= &clk_h,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_DMA0,
 	}, {
-		.name		= "dma",
+		.name		= "dma.1",
 		.parent		= &clk_h,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_DMA1,
 	}, {
-		.name		= "dma",
+		.name		= "dma.2",
 		.parent		= &clk_h,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_DMA2,
 	}, {
-		.name		= "dma",
+		.name		= "dma.3",
 		.parent		= &clk_h,
 		.enable		= s3c2412_clkcon_enable,
 		.ctrlbit	= S3C2412_CLKCON_DMA3,
diff --git a/arch/arm/mach-s3c24xx/common-s3c2443.c b/arch/arm/mach-s3c24xx/common-s3c2443.c
index f6b9f2e..65d3eef 100644
--- a/arch/arm/mach-s3c24xx/common-s3c2443.c
+++ b/arch/arm/mach-s3c24xx/common-s3c2443.c
@@ -438,32 +438,32 @@
 
 static struct clk init_clocks[] = {
 	{
-		.name		= "dma",
+		.name		= "dma.0",
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_DMA0,
 	}, {
-		.name		= "dma",
+		.name		= "dma.1",
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_DMA1,
 	}, {
-		.name		= "dma",
+		.name		= "dma.2",
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_DMA2,
 	}, {
-		.name		= "dma",
+		.name		= "dma.3",
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_DMA3,
 	}, {
-		.name		= "dma",
+		.name		= "dma.4",
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_DMA4,
 	}, {
-		.name		= "dma",
+		.name		= "dma.5",
 		.parent		= &clk_h,
 		.enable		= s3c2443_clkcon_enable_h,
 		.ctrlbit	= S3C2443_HCLKCON_DMA5,
diff --git a/arch/arm/mach-s3c24xx/common.c b/arch/arm/mach-s3c24xx/common.c
index 457261c..4adaa4b 100644
--- a/arch/arm/mach-s3c24xx/common.c
+++ b/arch/arm/mach-s3c24xx/common.c
@@ -31,6 +31,7 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/platform_data/dma-s3c24xx.h>
 
 #include <mach/hardware.h>
 #include <mach/regs-clock.h>
@@ -44,6 +45,7 @@
 
 #include <mach/regs-gpio.h>
 #include <plat/regs-serial.h>
+#include <mach/dma.h>
 
 #include <plat/cpu.h>
 #include <plat/devs.h>
@@ -329,3 +331,207 @@
 	clk_p.rate = pclk;
 	clk_f.rate = fclk;
 }
+
+#if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2412) || \
+	defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
+static struct resource s3c2410_dma_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_DMA, S3C24XX_SZ_DMA),
+	[1] = DEFINE_RES_IRQ(IRQ_DMA0),
+	[2] = DEFINE_RES_IRQ(IRQ_DMA1),
+	[3] = DEFINE_RES_IRQ(IRQ_DMA2),
+	[4] = DEFINE_RES_IRQ(IRQ_DMA3),
+};
+#endif
+
+#if defined(CONFIG_CPU_S3C2410) || defined(CONFIG_CPU_S3C2442)
+static struct s3c24xx_dma_channel s3c2410_dma_channels[DMACH_MAX] = {
+	[DMACH_XD0] = { S3C24XX_DMA_AHB, true, S3C24XX_DMA_CHANREQ(0, 0), },
+	[DMACH_XD1] = { S3C24XX_DMA_AHB, true, S3C24XX_DMA_CHANREQ(0, 1), },
+	[DMACH_SDI] = { S3C24XX_DMA_APB, false, S3C24XX_DMA_CHANREQ(2, 0) |
+						S3C24XX_DMA_CHANREQ(2, 2) |
+						S3C24XX_DMA_CHANREQ(1, 3),
+	},
+	[DMACH_SPI0] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(3, 1), },
+	[DMACH_SPI1] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(2, 3), },
+	[DMACH_UART0] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(1, 0), },
+	[DMACH_UART1] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(1, 1), },
+	[DMACH_UART2] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(0, 3), },
+	[DMACH_TIMER] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(3, 0) |
+						 S3C24XX_DMA_CHANREQ(3, 2) |
+						 S3C24XX_DMA_CHANREQ(3, 3),
+	},
+	[DMACH_I2S_IN] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(2, 1) |
+						  S3C24XX_DMA_CHANREQ(1, 2),
+	},
+	[DMACH_I2S_OUT] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(0, 2), },
+	[DMACH_USB_EP1] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(4, 0), },
+	[DMACH_USB_EP2] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(4, 1), },
+	[DMACH_USB_EP3] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(4, 2), },
+	[DMACH_USB_EP4] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(4, 3), },
+};
+
+static struct s3c24xx_dma_platdata s3c2410_dma_platdata = {
+	.num_phy_channels = 4,
+	.channels = s3c2410_dma_channels,
+	.num_channels = DMACH_MAX,
+};
+
+struct platform_device s3c2410_device_dma = {
+	.name		= "s3c2410-dma",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s3c2410_dma_resource),
+	.resource	= s3c2410_dma_resource,
+	.dev	= {
+		.platform_data	= &s3c2410_dma_platdata,
+	},
+};
+#endif
+
+#ifdef CONFIG_CPU_S3C2412
+static struct s3c24xx_dma_channel s3c2412_dma_channels[DMACH_MAX] = {
+	[DMACH_XD0] = { S3C24XX_DMA_AHB, true, 17 },
+	[DMACH_XD1] = { S3C24XX_DMA_AHB, true, 18 },
+	[DMACH_SDI] = { S3C24XX_DMA_APB, false, 10 },
+	[DMACH_SPI0_RX] = { S3C24XX_DMA_APB, true, 1 },
+	[DMACH_SPI0_TX] = { S3C24XX_DMA_APB, true, 0 },
+	[DMACH_SPI1_RX] = { S3C24XX_DMA_APB, true, 3 },
+	[DMACH_SPI1_TX] = { S3C24XX_DMA_APB, true, 2 },
+	[DMACH_UART0] = { S3C24XX_DMA_APB, true, 19 },
+	[DMACH_UART1] = { S3C24XX_DMA_APB, true, 21 },
+	[DMACH_UART2] = { S3C24XX_DMA_APB, true, 23 },
+	[DMACH_UART0_SRC2] = { S3C24XX_DMA_APB, true, 20 },
+	[DMACH_UART1_SRC2] = { S3C24XX_DMA_APB, true, 22 },
+	[DMACH_UART2_SRC2] = { S3C24XX_DMA_APB, true, 24 },
+	[DMACH_TIMER] = { S3C24XX_DMA_APB, true, 9 },
+	[DMACH_I2S_IN] = { S3C24XX_DMA_APB, true, 5 },
+	[DMACH_I2S_OUT] = { S3C24XX_DMA_APB, true, 4 },
+	[DMACH_USB_EP1] = { S3C24XX_DMA_APB, true, 13 },
+	[DMACH_USB_EP2] = { S3C24XX_DMA_APB, true, 14 },
+	[DMACH_USB_EP3] = { S3C24XX_DMA_APB, true, 15 },
+	[DMACH_USB_EP4] = { S3C24XX_DMA_APB, true, 16 },
+};
+
+static struct s3c24xx_dma_platdata s3c2412_dma_platdata = {
+	.num_phy_channels = 4,
+	.channels = s3c2412_dma_channels,
+	.num_channels = DMACH_MAX,
+};
+
+struct platform_device s3c2412_device_dma = {
+	.name		= "s3c2412-dma",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s3c2410_dma_resource),
+	.resource	= s3c2410_dma_resource,
+	.dev	= {
+		.platform_data	= &s3c2412_dma_platdata,
+	},
+};
+#endif
+
+#if defined(CONFIG_CPU_S3C2440)
+static struct s3c24xx_dma_channel s3c2440_dma_channels[DMACH_MAX] = {
+	[DMACH_XD0] = { S3C24XX_DMA_AHB, true, S3C24XX_DMA_CHANREQ(0, 0), },
+	[DMACH_XD1] = { S3C24XX_DMA_AHB, true, S3C24XX_DMA_CHANREQ(0, 1), },
+	[DMACH_SDI] = { S3C24XX_DMA_APB, false, S3C24XX_DMA_CHANREQ(2, 0) |
+						S3C24XX_DMA_CHANREQ(6, 1) |
+						S3C24XX_DMA_CHANREQ(2, 2) |
+						S3C24XX_DMA_CHANREQ(1, 3),
+	},
+	[DMACH_SPI0] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(3, 1), },
+	[DMACH_SPI1] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(2, 3), },
+	[DMACH_UART0] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(1, 0), },
+	[DMACH_UART1] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(1, 1), },
+	[DMACH_UART2] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(0, 3), },
+	[DMACH_TIMER] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(3, 0) |
+						 S3C24XX_DMA_CHANREQ(3, 2) |
+						 S3C24XX_DMA_CHANREQ(3, 3),
+	},
+	[DMACH_I2S_IN] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(2, 1) |
+						  S3C24XX_DMA_CHANREQ(1, 2),
+	},
+	[DMACH_I2S_OUT] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(5, 0) |
+						   S3C24XX_DMA_CHANREQ(0, 2),
+	},
+	[DMACH_PCM_IN] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(6, 0) |
+						  S3C24XX_DMA_CHANREQ(5, 2),
+	},
+	[DMACH_PCM_OUT] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(5, 1) |
+						  S3C24XX_DMA_CHANREQ(6, 3),
+	},
+	[DMACH_MIC_IN] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(6, 2) |
+						  S3C24XX_DMA_CHANREQ(5, 3),
+	},
+	[DMACH_USB_EP1] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(4, 0), },
+	[DMACH_USB_EP2] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(4, 1), },
+	[DMACH_USB_EP3] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(4, 2), },
+	[DMACH_USB_EP4] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(4, 3), },
+};
+
+static struct s3c24xx_dma_platdata s3c2440_dma_platdata = {
+	.num_phy_channels = 4,
+	.channels = s3c2440_dma_channels,
+	.num_channels = DMACH_MAX,
+};
+
+struct platform_device s3c2440_device_dma = {
+	.name		= "s3c2410-dma",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s3c2410_dma_resource),
+	.resource	= s3c2410_dma_resource,
+	.dev	= {
+		.platform_data	= &s3c2440_dma_platdata,
+	},
+};
+#endif
+
+#if defined(CONFIG_CPUS_3C2443) || defined(CONFIG_CPU_S3C2416)
+static struct resource s3c2443_dma_resource[] = {
+	[0] = DEFINE_RES_MEM(S3C24XX_PA_DMA, S3C24XX_SZ_DMA),
+	[1] = DEFINE_RES_IRQ(IRQ_S3C2443_DMA0),
+	[2] = DEFINE_RES_IRQ(IRQ_S3C2443_DMA1),
+	[3] = DEFINE_RES_IRQ(IRQ_S3C2443_DMA2),
+	[4] = DEFINE_RES_IRQ(IRQ_S3C2443_DMA3),
+	[5] = DEFINE_RES_IRQ(IRQ_S3C2443_DMA4),
+	[6] = DEFINE_RES_IRQ(IRQ_S3C2443_DMA5),
+};
+
+static struct s3c24xx_dma_channel s3c2443_dma_channels[DMACH_MAX] = {
+	[DMACH_XD0] = { S3C24XX_DMA_AHB, true, 17 },
+	[DMACH_XD1] = { S3C24XX_DMA_AHB, true, 18 },
+	[DMACH_SDI] = { S3C24XX_DMA_APB, false, 10 },
+	[DMACH_SPI0_RX] = { S3C24XX_DMA_APB, true, 1 },
+	[DMACH_SPI0_TX] = { S3C24XX_DMA_APB, true, 0 },
+	[DMACH_SPI1_RX] = { S3C24XX_DMA_APB, true, 3 },
+	[DMACH_SPI1_TX] = { S3C24XX_DMA_APB, true, 2 },
+	[DMACH_UART0] = { S3C24XX_DMA_APB, true, 19 },
+	[DMACH_UART1] = { S3C24XX_DMA_APB, true, 21 },
+	[DMACH_UART2] = { S3C24XX_DMA_APB, true, 23 },
+	[DMACH_UART3] = { S3C24XX_DMA_APB, true, 25 },
+	[DMACH_UART0_SRC2] = { S3C24XX_DMA_APB, true, 20 },
+	[DMACH_UART1_SRC2] = { S3C24XX_DMA_APB, true, 22 },
+	[DMACH_UART2_SRC2] = { S3C24XX_DMA_APB, true, 24 },
+	[DMACH_UART3_SRC2] = { S3C24XX_DMA_APB, true, 26 },
+	[DMACH_TIMER] = { S3C24XX_DMA_APB, true, 9 },
+	[DMACH_I2S_IN] = { S3C24XX_DMA_APB, true, 5 },
+	[DMACH_I2S_OUT] = { S3C24XX_DMA_APB, true, 4 },
+	[DMACH_PCM_IN] = { S3C24XX_DMA_APB, true, 28 },
+	[DMACH_PCM_OUT] = { S3C24XX_DMA_APB, true, 27 },
+	[DMACH_MIC_IN] = { S3C24XX_DMA_APB, true, 29 },
+};
+
+static struct s3c24xx_dma_platdata s3c2443_dma_platdata = {
+	.num_phy_channels = 6,
+	.channels = s3c2443_dma_channels,
+	.num_channels = DMACH_MAX,
+};
+
+struct platform_device s3c2443_device_dma = {
+	.name		= "s3c2443-dma",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s3c2443_dma_resource),
+	.resource	= s3c2443_dma_resource,
+	.dev	= {
+		.platform_data	= &s3c2443_dma_platdata,
+	},
+};
+#endif
diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h
index 84b2806..e46c1041 100644
--- a/arch/arm/mach-s3c24xx/common.h
+++ b/arch/arm/mach-s3c24xx/common.h
@@ -109,4 +109,9 @@
 
 extern struct syscore_ops s3c24xx_irq_syscore_ops;
 
+extern struct platform_device s3c2410_device_dma;
+extern struct platform_device s3c2412_device_dma;
+extern struct platform_device s3c2440_device_dma;
+extern struct platform_device s3c2443_device_dma;
+
 #endif /* __ARCH_ARM_MACH_S3C24XX_COMMON_H */
diff --git a/arch/arm/mach-s3c24xx/mach-jive.c b/arch/arm/mach-s3c24xx/mach-jive.c
index a45fcd8..43c23e2 100644
--- a/arch/arm/mach-s3c24xx/mach-jive.c
+++ b/arch/arm/mach-s3c24xx/mach-jive.c
@@ -466,6 +466,7 @@
 	&jive_device_wm8750,
 	&s3c_device_nand,
 	&s3c_device_usbgadget,
+	&s3c2412_device_dma,
 };
 
 static struct s3c2410_udc_mach_info jive_udc_cfg __initdata = {
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2413.c b/arch/arm/mach-s3c24xx/mach-smdk2413.c
index 8146e92..c9d31ef 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2413.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2413.c
@@ -89,6 +89,7 @@
 	&s3c_device_i2c0,
 	&s3c_device_iis,
 	&s3c_device_usbgadget,
+	&s3c2412_device_dma,
 };
 
 static void __init smdk2413_fixup(struct tag *tags, char **cmdline,
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2416.c b/arch/arm/mach-s3c24xx/mach-smdk2416.c
index cb46847..f88e672 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2416.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2416.c
@@ -215,6 +215,7 @@
 	&s3c_device_hsmmc0,
 	&s3c_device_hsmmc1,
 	&s3c_device_usb_hsudc,
+	&s3c2443_device_dma,
 };
 
 static void __init smdk2416_map_io(void)
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2443.c b/arch/arm/mach-s3c24xx/mach-smdk2443.c
index 9435c3b..d9933fc 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2443.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2443.c
@@ -115,6 +115,7 @@
 #ifdef CONFIG_SND_SOC_SMDK2443_WM9710
 	&s3c_device_ac97,
 #endif
+	&s3c2443_device_dma,
 };
 
 static void __init smdk2443_map_io(void)
diff --git a/arch/arm/mach-s3c24xx/mach-vstms.c b/arch/arm/mach-s3c24xx/mach-vstms.c
index b665884..f7ec9c5 100644
--- a/arch/arm/mach-s3c24xx/mach-vstms.c
+++ b/arch/arm/mach-s3c24xx/mach-vstms.c
@@ -126,6 +126,7 @@
 	&s3c_device_iis,
 	&s3c_device_rtc,
 	&s3c_device_nand,
+	&s3c2412_device_dma,
 };
 
 static void __init vstms_fixup(struct tag *tags, char **cmdline,
diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
index 041da51..2cb8dc5 100644
--- a/arch/arm/mach-s3c64xx/Kconfig
+++ b/arch/arm/mach-s3c64xx/Kconfig
@@ -3,16 +3,7 @@
 #
 # Licensed under GPLv2
 
-# temporary until we can eliminate all drivers using it.
-config PLAT_S3C64XX
-	bool
-	depends on ARCH_S3C64XX
-	default y
-	select PM_GENERIC_DOMAINS
-	select SAMSUNG_WAKEMASK
-	help
-	  Base platform code for any Samsung S3C64XX device
-
+if ARCH_S3C64XX
 
 # Configuration options for the S3C6410 CPU
 
@@ -306,3 +297,21 @@
 	select SAMSUNG_GPIO_EXTRA128
 	help
 	  Machine support for the Wolfson Cragganmore S3C6410 variant.
+
+config MACH_S3C64XX_DT
+	bool "Samsung S3C6400/S3C6410 machine using Device Tree"
+	select CLKSRC_OF
+	select CPU_S3C6400
+	select CPU_S3C6410
+	select PINCTRL
+	select PINCTRL_S3C64XX
+	select USE_OF
+	help
+	  Machine support for Samsung S3C6400/S3C6410 machines with Device Tree
+	  enabled.
+	  Select this if a fdt blob is available for your S3C64XX SoC based
+	  board.
+	  Note: This is under development and not all peripherals can be
+	  supported with this machine file.
+
+endif
diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile
index 31d0c91..6faedcf 100644
--- a/arch/arm/mach-s3c64xx/Makefile
+++ b/arch/arm/mach-s3c64xx/Makefile
@@ -12,7 +12,7 @@
 
 # Core
 
-obj-y				+= common.o clock.o
+obj-y				+= common.o
 
 # Core support
 
@@ -57,3 +57,4 @@
 obj-$(CONFIG_MACH_SMDK6400)		+= mach-smdk6400.o
 obj-$(CONFIG_MACH_SMDK6410)		+= mach-smdk6410.o
 obj-$(CONFIG_MACH_WLF_CRAGG_6410)	+= mach-crag6410.o mach-crag6410-module.o
+obj-$(CONFIG_MACH_S3C64XX_DT)		+= mach-s3c64xx-dt.o
diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c
deleted file mode 100644
index c1bcc4a6..0000000
--- a/arch/arm/mach-s3c64xx/clock.c
+++ /dev/null
@@ -1,1007 +0,0 @@
-/* linux/arch/arm/plat-s3c64xx/clock.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C64XX Base clock support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-
-#include <mach/regs-clock.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/pll.h>
-
-#include "regs-sys.h"
-
-/* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
- * ext_xtal_mux for want of an actual name from the manual.
-*/
-
-static struct clk clk_ext_xtal_mux = {
-	.name		= "ext_xtal",
-};
-
-#define clk_fin_apll clk_ext_xtal_mux
-#define clk_fin_mpll clk_ext_xtal_mux
-#define clk_fin_epll clk_ext_xtal_mux
-
-#define clk_fout_mpll	clk_mpll
-#define clk_fout_epll	clk_epll
-
-struct clk clk_h2 = {
-	.name		= "hclk2",
-	.rate		= 0,
-};
-
-struct clk clk_27m = {
-	.name		= "clk_27m",
-	.rate		= 27000000,
-};
-
-static int clk_48m_ctrl(struct clk *clk, int enable)
-{
-	unsigned long flags;
-	u32 val;
-
-	/* can't rely on clock lock, this register has other usages */
-	local_irq_save(flags);
-
-	val = __raw_readl(S3C64XX_OTHERS);
-	if (enable)
-		val |= S3C64XX_OTHERS_USBMASK;
-	else
-		val &= ~S3C64XX_OTHERS_USBMASK;
-
-	__raw_writel(val, S3C64XX_OTHERS);
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-struct clk clk_48m = {
-	.name		= "clk_48m",
-	.rate		= 48000000,
-	.enable		= clk_48m_ctrl,
-};
-
-struct clk clk_xusbxti = {
-	.name		= "xusbxti",
-	.rate		= 48000000,
-};
-
-static int inline s3c64xx_gate(void __iomem *reg,
-				struct clk *clk,
-				int enable)
-{
-	unsigned int ctrlbit = clk->ctrlbit;
-	u32 con;
-
-	con = __raw_readl(reg);
-
-	if (enable)
-		con |= ctrlbit;
-	else
-		con &= ~ctrlbit;
-
-	__raw_writel(con, reg);
-	return 0;
-}
-
-static int s3c64xx_pclk_ctrl(struct clk *clk, int enable)
-{
-	return s3c64xx_gate(S3C_PCLK_GATE, clk, enable);
-}
-
-static int s3c64xx_hclk_ctrl(struct clk *clk, int enable)
-{
-	return s3c64xx_gate(S3C_HCLK_GATE, clk, enable);
-}
-
-int s3c64xx_sclk_ctrl(struct clk *clk, int enable)
-{
-	return s3c64xx_gate(S3C_SCLK_GATE, clk, enable);
-}
-
-static struct clk init_clocks_off[] = {
-	{
-		.name		= "nand",
-		.parent		= &clk_h,
-	}, {
-		.name		= "rtc",
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_RTC,
-	}, {
-		.name		= "adc",
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_TSADC,
-	}, {
-		.name		= "i2c",
-		.devname        = "s3c2440-i2c.0",
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_IIC,
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.1",
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C6410_CLKCON_PCLK_I2C1,
-	}, {
-		.name		= "keypad",
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_KEYPAD,
-	}, {
-		.name		= "spi",
-		.devname	= "s3c6410-spi.0",
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_SPI0,
-	}, {
-		.name		= "spi",
-		.devname	= "s3c6410-spi.1",
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_SPI1,
-	}, {
-		.name		= "48m",
-		.devname	= "s3c-sdhci.0",
-		.parent		= &clk_48m,
-		.enable		= s3c64xx_sclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_SCLK_MMC0_48,
-	}, {
-		.name		= "48m",
-		.devname	= "s3c-sdhci.1",
-		.parent		= &clk_48m,
-		.enable		= s3c64xx_sclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_SCLK_MMC1_48,
-	}, {
-		.name		= "48m",
-		.devname	= "s3c-sdhci.2",
-		.parent		= &clk_48m,
-		.enable		= s3c64xx_sclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_SCLK_MMC2_48,
-	}, {
-		.name		= "ac97",
-		.parent		= &clk_p,
-		.ctrlbit	= S3C_CLKCON_PCLK_AC97,
-	}, {
-		.name		= "cfcon",
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_IHOST,
-	}, {
-		.name		= "dma0",
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_DMA0,
-	}, {
-		.name		= "dma1",
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_DMA1,
-	}, {
-		.name		= "3dse",
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_3DSE,
-	}, {
-		.name		= "hclk_secur",
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_SECUR,
-	}, {
-		.name		= "sdma1",
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_SDMA1,
-	}, {
-		.name		= "sdma0",
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_SDMA0,
-	}, {
-		.name		= "hclk_jpeg",
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_JPEG,
-	}, {
-		.name		= "camif",
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_CAMIF,
-	}, {
-		.name		= "hclk_scaler",
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_SCALER,
-	}, {
-		.name		= "2d",
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_2D,
-	}, {
-		.name		= "tv",
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_TV,
-	}, {
-		.name		= "post0",
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_POST0,
-	}, {
-		.name		= "rot",
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_ROT,
-	}, {
-		.name		= "hclk_mfc",
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_MFC,
-	}, {
-		.name		= "pclk_mfc",
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_MFC,
-	}, {
-		.name		= "dac27",
-		.enable		= s3c64xx_sclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_SCLK_DAC27,
-	}, {
-		.name		= "tv27",
-		.enable		= s3c64xx_sclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_SCLK_TV27,
-	}, {
-		.name		= "scaler27",
-		.enable		= s3c64xx_sclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_SCLK_SCALER27,
-	}, {
-		.name		= "sclk_scaler",
-		.enable		= s3c64xx_sclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_SCLK_SCALER,
-	}, {
-		.name		= "post0_27",
-		.enable		= s3c64xx_sclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_SCLK_POST0_27,
-	}, {
-		.name		= "secur",
-		.enable		= s3c64xx_sclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_SCLK_SECUR,
-	}, {
-		.name		= "sclk_mfc",
-		.enable		= s3c64xx_sclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_SCLK_MFC,
-	}, {
-		.name		= "sclk_jpeg",
-		.enable		= s3c64xx_sclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_SCLK_JPEG,
-	},
-};
-
-static struct clk clk_48m_spi0 = {
-	.name		= "spi_48m",
-	.devname	= "s3c6410-spi.0",
-	.parent		= &clk_48m,
-	.enable		= s3c64xx_sclk_ctrl,
-	.ctrlbit	= S3C_CLKCON_SCLK_SPI0_48,
-};
-
-static struct clk clk_48m_spi1 = {
-	.name		= "spi_48m",
-	.devname	= "s3c6410-spi.1",
-	.parent		= &clk_48m,
-	.enable		= s3c64xx_sclk_ctrl,
-	.ctrlbit	= S3C_CLKCON_SCLK_SPI1_48,
-};
-
-static struct clk clk_i2s0 = {
-	.name		= "iis",
-	.devname	= "samsung-i2s.0",
-	.parent		= &clk_p,
-	.enable		= s3c64xx_pclk_ctrl,
-	.ctrlbit	= S3C_CLKCON_PCLK_IIS0,
-};
-
-static struct clk clk_i2s1 = {
-	.name		= "iis",
-	.devname	= "samsung-i2s.1",
-	.parent		= &clk_p,
-	.enable		= s3c64xx_pclk_ctrl,
-	.ctrlbit	= S3C_CLKCON_PCLK_IIS1,
-};
-
-#ifdef CONFIG_CPU_S3C6410
-static struct clk clk_i2s2 = {
-	.name		= "iis",
-	.devname	= "samsung-i2s.2",
-	.parent		= &clk_p,
-	.enable		= s3c64xx_pclk_ctrl,
-	.ctrlbit	= S3C6410_CLKCON_PCLK_IIS2,
-};
-#endif
-
-static struct clk init_clocks[] = {
-	{
-		.name		= "lcd",
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_LCD,
-	}, {
-		.name		= "gpio",
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_GPIO,
-	}, {
-		.name		= "usb-host",
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_UHOST,
-	}, {
-		.name		= "otg",
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_USB,
-	}, {
-		.name		= "timers",
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_PWM,
-	}, {
-		.name		= "uart",
-		.devname	= "s3c6400-uart.0",
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_UART0,
-	}, {
-		.name		= "uart",
-		.devname	= "s3c6400-uart.1",
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_UART1,
-	}, {
-		.name		= "uart",
-		.devname	= "s3c6400-uart.2",
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_UART2,
-	}, {
-		.name		= "uart",
-		.devname	= "s3c6400-uart.3",
-		.parent		= &clk_p,
-		.enable		= s3c64xx_pclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_PCLK_UART3,
-	}, {
-		.name		= "watchdog",
-		.parent		= &clk_p,
-		.ctrlbit	= S3C_CLKCON_PCLK_WDT,
-	},
-};
-
-static struct clk clk_hsmmc0 = {
-	.name		= "hsmmc",
-	.devname	= "s3c-sdhci.0",
-	.parent		= &clk_h,
-	.enable		= s3c64xx_hclk_ctrl,
-	.ctrlbit	= S3C_CLKCON_HCLK_HSMMC0,
-};
-
-static struct clk clk_hsmmc1 = {
-	.name		= "hsmmc",
-	.devname	= "s3c-sdhci.1",
-	.parent		= &clk_h,
-	.enable		= s3c64xx_hclk_ctrl,
-	.ctrlbit	= S3C_CLKCON_HCLK_HSMMC1,
-};
-
-static struct clk clk_hsmmc2 = {
-	.name		= "hsmmc",
-	.devname	= "s3c-sdhci.2",
-	.parent		= &clk_h,
-	.enable		= s3c64xx_hclk_ctrl,
-	.ctrlbit	= S3C_CLKCON_HCLK_HSMMC2,
-};
-
-static struct clk clk_fout_apll = {
-	.name		= "fout_apll",
-};
-
-static struct clk *clk_src_apll_list[] = {
-	[0] = &clk_fin_apll,
-	[1] = &clk_fout_apll,
-};
-
-static struct clksrc_sources clk_src_apll = {
-	.sources	= clk_src_apll_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_apll_list),
-};
-
-static struct clksrc_clk clk_mout_apll = {
-	.clk	= {
-		.name		= "mout_apll",
-	},
-	.reg_src	= { .reg = S3C_CLK_SRC, .shift = 0, .size = 1  },
-	.sources	= &clk_src_apll,
-};
-
-static struct clk *clk_src_epll_list[] = {
-	[0] = &clk_fin_epll,
-	[1] = &clk_fout_epll,
-};
-
-static struct clksrc_sources clk_src_epll = {
-	.sources	= clk_src_epll_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_epll_list),
-};
-
-static struct clksrc_clk clk_mout_epll = {
-	.clk	= {
-		.name		= "mout_epll",
-	},
-	.reg_src	= { .reg = S3C_CLK_SRC, .shift = 2, .size = 1  },
-	.sources	= &clk_src_epll,
-};
-
-static struct clk *clk_src_mpll_list[] = {
-	[0] = &clk_fin_mpll,
-	[1] = &clk_fout_mpll,
-};
-
-static struct clksrc_sources clk_src_mpll = {
-	.sources	= clk_src_mpll_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_mpll_list),
-};
-
-static struct clksrc_clk clk_mout_mpll = {
-	.clk = {
-		.name		= "mout_mpll",
-	},
-	.reg_src	= { .reg = S3C_CLK_SRC, .shift = 1, .size = 1  },
-	.sources	= &clk_src_mpll,
-};
-
-static unsigned int armclk_mask;
-
-static unsigned long s3c64xx_clk_arm_get_rate(struct clk *clk)
-{
-	unsigned long rate = clk_get_rate(clk->parent);
-	u32 clkdiv;
-
-	/* divisor mask starts at bit0, so no need to shift */
-	clkdiv = __raw_readl(S3C_CLK_DIV0) & armclk_mask;
-
-	return rate / (clkdiv + 1);
-}
-
-static unsigned long s3c64xx_clk_arm_round_rate(struct clk *clk,
-						unsigned long rate)
-{
-	unsigned long parent = clk_get_rate(clk->parent);
-	u32 div;
-
-	if (parent < rate)
-		return parent;
-
-	div = (parent / rate) - 1;
-	if (div > armclk_mask)
-		div = armclk_mask;
-
-	return parent / (div + 1);
-}
-
-static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent = clk_get_rate(clk->parent);
-	u32 div;
-	u32 val;
-
-	if (rate < parent / (armclk_mask + 1))
-		return -EINVAL;
-
-	rate = clk_round_rate(clk, rate);
-	div = clk_get_rate(clk->parent) / rate;
-
-	val = __raw_readl(S3C_CLK_DIV0);
-	val &= ~armclk_mask;
-	val |= (div - 1);
-	__raw_writel(val, S3C_CLK_DIV0);
-
-	return 0;
-
-}
-
-static struct clk clk_arm = {
-	.name		= "armclk",
-	.parent		= &clk_mout_apll.clk,
-	.ops		= &(struct clk_ops) {
-		.get_rate	= s3c64xx_clk_arm_get_rate,
-		.set_rate	= s3c64xx_clk_arm_set_rate,
-		.round_rate	= s3c64xx_clk_arm_round_rate,
-	},
-};
-
-static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk)
-{
-	unsigned long rate = clk_get_rate(clk->parent);
-
-	printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
-
-	if (__raw_readl(S3C_CLK_DIV0) & S3C6400_CLKDIV0_MPLL_MASK)
-		rate /= 2;
-
-	return rate;
-}
-
-static struct clk_ops clk_dout_ops = {
-	.get_rate	= s3c64xx_clk_doutmpll_get_rate,
-};
-
-static struct clk clk_dout_mpll = {
-	.name		= "dout_mpll",
-	.parent		= &clk_mout_mpll.clk,
-	.ops		= &clk_dout_ops,
-};
-
-static struct clk *clkset_spi_mmc_list[] = {
-	&clk_mout_epll.clk,
-	&clk_dout_mpll,
-	&clk_fin_epll,
-	&clk_27m,
-};
-
-static struct clksrc_sources clkset_spi_mmc = {
-	.sources	= clkset_spi_mmc_list,
-	.nr_sources	= ARRAY_SIZE(clkset_spi_mmc_list),
-};
-
-static struct clk *clkset_irda_list[] = {
-	&clk_mout_epll.clk,
-	&clk_dout_mpll,
-	NULL,
-	&clk_27m,
-};
-
-static struct clksrc_sources clkset_irda = {
-	.sources	= clkset_irda_list,
-	.nr_sources	= ARRAY_SIZE(clkset_irda_list),
-};
-
-static struct clk *clkset_uart_list[] = {
-	&clk_mout_epll.clk,
-	&clk_dout_mpll,
-	NULL,
-	NULL
-};
-
-static struct clksrc_sources clkset_uart = {
-	.sources	= clkset_uart_list,
-	.nr_sources	= ARRAY_SIZE(clkset_uart_list),
-};
-
-static struct clk *clkset_uhost_list[] = {
-	&clk_48m,
-	&clk_mout_epll.clk,
-	&clk_dout_mpll,
-	&clk_fin_epll,
-};
-
-static struct clksrc_sources clkset_uhost = {
-	.sources	= clkset_uhost_list,
-	.nr_sources	= ARRAY_SIZE(clkset_uhost_list),
-};
-
-/* The peripheral clocks are all controlled via clocksource followed
- * by an optional divider and gate stage. We currently roll this into
- * one clock which hides the intermediate clock from the mux.
- *
- * Note, the JPEG clock can only be an even divider...
- *
- * The scaler and LCD clocks depend on the S3C64XX version, and also
- * have a common parent divisor so are not included here.
- */
-
-/* clocks that feed other parts of the clock source tree */
-
-static struct clk clk_iis_cd0 = {
-	.name		= "iis_cdclk0",
-};
-
-static struct clk clk_iis_cd1 = {
-	.name		= "iis_cdclk1",
-};
-
-static struct clk clk_iisv4_cd = {
-	.name		= "iis_cdclk_v4",
-};
-
-static struct clk clk_pcm_cd = {
-	.name		= "pcm_cdclk",
-};
-
-static struct clk *clkset_audio0_list[] = {
-	[0] = &clk_mout_epll.clk,
-	[1] = &clk_dout_mpll,
-	[2] = &clk_fin_epll,
-	[3] = &clk_iis_cd0,
-	[4] = &clk_pcm_cd,
-};
-
-static struct clksrc_sources clkset_audio0 = {
-	.sources	= clkset_audio0_list,
-	.nr_sources	= ARRAY_SIZE(clkset_audio0_list),
-};
-
-static struct clk *clkset_audio1_list[] = {
-	[0] = &clk_mout_epll.clk,
-	[1] = &clk_dout_mpll,
-	[2] = &clk_fin_epll,
-	[3] = &clk_iis_cd1,
-	[4] = &clk_pcm_cd,
-};
-
-static struct clksrc_sources clkset_audio1 = {
-	.sources	= clkset_audio1_list,
-	.nr_sources	= ARRAY_SIZE(clkset_audio1_list),
-};
-
-#ifdef CONFIG_CPU_S3C6410
-static struct clk *clkset_audio2_list[] = {
-	[0] = &clk_mout_epll.clk,
-	[1] = &clk_dout_mpll,
-	[2] = &clk_fin_epll,
-	[3] = &clk_iisv4_cd,
-	[4] = &clk_pcm_cd,
-};
-
-static struct clksrc_sources clkset_audio2 = {
-	.sources	= clkset_audio2_list,
-	.nr_sources	= ARRAY_SIZE(clkset_audio2_list),
-};
-#endif
-
-static struct clksrc_clk clksrcs[] = {
-	{
-		.clk	= {
-			.name		= "usb-bus-host",
-			.ctrlbit        = S3C_CLKCON_SCLK_UHOST,
-			.enable		= s3c64xx_sclk_ctrl,
-		},
-		.reg_src 	= { .reg = S3C_CLK_SRC, .shift = 5, .size = 2  },
-		.reg_div	= { .reg = S3C_CLK_DIV1, .shift = 20, .size = 4  },
-		.sources	= &clkset_uhost,
-	}, {
-		.clk	= {
-			.name		= "irda-bus",
-			.ctrlbit        = S3C_CLKCON_SCLK_IRDA,
-			.enable		= s3c64xx_sclk_ctrl,
-		},
-		.reg_src	= { .reg = S3C_CLK_SRC, .shift = 24, .size = 2  },
-		.reg_div	= { .reg = S3C_CLK_DIV2, .shift = 20, .size = 4  },
-		.sources	= &clkset_irda,
-	}, {
-		.clk	= {
-			.name		= "camera",
-			.ctrlbit        = S3C_CLKCON_SCLK_CAM,
-			.enable		= s3c64xx_sclk_ctrl,
-			.parent		= &clk_h2,
-		},
-		.reg_div	= { .reg = S3C_CLK_DIV0, .shift = 20, .size = 4  },
-	},
-};
-
-/* Where does UCLK0 come from? */
-static struct clksrc_clk clk_sclk_uclk = {
-	.clk	= {
-		.name		= "uclk1",
-		.ctrlbit        = S3C_CLKCON_SCLK_UART,
-		.enable		= s3c64xx_sclk_ctrl,
-	},
-	.reg_src	= { .reg = S3C_CLK_SRC, .shift = 13, .size = 1  },
-	.reg_div	= { .reg = S3C_CLK_DIV2, .shift = 16, .size = 4  },
-	.sources	= &clkset_uart,
-};
-
-static struct clksrc_clk clk_sclk_mmc0 = {
-	.clk	= {
-		.name		= "mmc_bus",
-		.devname	= "s3c-sdhci.0",
-		.ctrlbit        = S3C_CLKCON_SCLK_MMC0,
-		.enable		= s3c64xx_sclk_ctrl,
-	},
-	.reg_src	= { .reg = S3C_CLK_SRC, .shift = 18, .size = 2  },
-	.reg_div	= { .reg = S3C_CLK_DIV1, .shift = 0, .size = 4  },
-	.sources	= &clkset_spi_mmc,
-};
-
-static struct clksrc_clk clk_sclk_mmc1 = {
-	.clk	= {
-		.name		= "mmc_bus",
-		.devname	= "s3c-sdhci.1",
-		.ctrlbit        = S3C_CLKCON_SCLK_MMC1,
-		.enable		= s3c64xx_sclk_ctrl,
-	},
-	.reg_src	= { .reg = S3C_CLK_SRC, .shift = 20, .size = 2  },
-	.reg_div	= { .reg = S3C_CLK_DIV1, .shift = 4, .size = 4  },
-	.sources	= &clkset_spi_mmc,
-};
-
-static struct clksrc_clk clk_sclk_mmc2 = {
-	.clk	= {
-		.name		= "mmc_bus",
-		.devname	= "s3c-sdhci.2",
-		.ctrlbit        = S3C_CLKCON_SCLK_MMC2,
-		.enable		= s3c64xx_sclk_ctrl,
-	},
-	.reg_src	= { .reg = S3C_CLK_SRC, .shift = 22, .size = 2  },
-	.reg_div	= { .reg = S3C_CLK_DIV1, .shift = 8, .size = 4  },
-	.sources	= &clkset_spi_mmc,
-};
-
-static struct clksrc_clk clk_sclk_spi0 = {
-	.clk	= {
-		.name		= "spi-bus",
-		.devname	= "s3c6410-spi.0",
-		.ctrlbit	= S3C_CLKCON_SCLK_SPI0,
-		.enable		= s3c64xx_sclk_ctrl,
-	},
-	.reg_src = { .reg = S3C_CLK_SRC, .shift = 14, .size = 2 },
-	.reg_div = { .reg = S3C_CLK_DIV2, .shift = 0, .size = 4 },
-	.sources = &clkset_spi_mmc,
-};
-
-static struct clksrc_clk clk_sclk_spi1 = {
-	.clk	= {
-		.name		= "spi-bus",
-		.devname	= "s3c6410-spi.1",
-		.ctrlbit	= S3C_CLKCON_SCLK_SPI1,
-		.enable		= s3c64xx_sclk_ctrl,
-	},
-	.reg_src = { .reg = S3C_CLK_SRC, .shift = 16, .size = 2 },
-	.reg_div = { .reg = S3C_CLK_DIV2, .shift = 4, .size = 4 },
-	.sources = &clkset_spi_mmc,
-};
-
-static struct clksrc_clk clk_audio_bus0 = {
-	.clk	= {
-		.name		= "audio-bus",
-		.devname	= "samsung-i2s.0",
-		.ctrlbit	= S3C_CLKCON_SCLK_AUDIO0,
-		.enable		= s3c64xx_sclk_ctrl,
-	},
-	.reg_src	= { .reg = S3C_CLK_SRC, .shift = 7, .size = 3  },
-	.reg_div	= { .reg = S3C_CLK_DIV2, .shift = 8, .size = 4  },
-	.sources	= &clkset_audio0,
-};
-
-static struct clksrc_clk clk_audio_bus1 = {
-	.clk	= {
-		.name		= "audio-bus",
-		.devname	= "samsung-i2s.1",
-		.ctrlbit	= S3C_CLKCON_SCLK_AUDIO1,
-		.enable		= s3c64xx_sclk_ctrl,
-	},
-	.reg_src	= { .reg = S3C_CLK_SRC, .shift = 10, .size = 3  },
-	.reg_div	= { .reg = S3C_CLK_DIV2, .shift = 12, .size = 4  },
-	.sources	= &clkset_audio1,
-};
-
-#ifdef CONFIG_CPU_S3C6410
-static struct clksrc_clk clk_audio_bus2 = {
-	.clk	= {
-		.name		= "audio-bus",
-		.devname	= "samsung-i2s.2",
-		.ctrlbit	= S3C6410_CLKCON_SCLK_AUDIO2,
-		.enable		= s3c64xx_sclk_ctrl,
-	},
-	.reg_src	= { .reg = S3C6410_CLK_SRC2, .shift = 0, .size = 3  },
-	.reg_div	= { .reg = S3C_CLK_DIV2, .shift = 24, .size = 4  },
-	.sources	= &clkset_audio2,
-};
-#endif
-/* Clock initialisation code */
-
-static struct clksrc_clk *init_parents[] = {
-	&clk_mout_apll,
-	&clk_mout_epll,
-	&clk_mout_mpll,
-};
-
-static struct clksrc_clk *clksrc_cdev[] = {
-	&clk_sclk_uclk,
-	&clk_sclk_mmc0,
-	&clk_sclk_mmc1,
-	&clk_sclk_mmc2,
-	&clk_sclk_spi0,
-	&clk_sclk_spi1,
-	&clk_audio_bus0,
-	&clk_audio_bus1,
-};
-
-static struct clk *clk_cdev[] = {
-	&clk_hsmmc0,
-	&clk_hsmmc1,
-	&clk_hsmmc2,
-	&clk_48m_spi0,
-	&clk_48m_spi1,
-	&clk_i2s0,
-	&clk_i2s1,
-};
-
-static struct clk_lookup s3c64xx_clk_lookup[] = {
-	CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
-	CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk),
-	CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &clk_hsmmc0),
-	CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &clk_hsmmc1),
-	CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.0", &clk_hsmmc2),
-	CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
-	CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
-	CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
-	CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
-	CLKDEV_INIT("s3c6410-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
-	CLKDEV_INIT("s3c6410-spi.0", "spi_busclk2", &clk_48m_spi0),
-	CLKDEV_INIT("s3c6410-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
-	CLKDEV_INIT("s3c6410-spi.1", "spi_busclk2", &clk_48m_spi1),
-	CLKDEV_INIT("samsung-i2s.0", "i2s_opclk0", &clk_i2s0),
-	CLKDEV_INIT("samsung-i2s.0", "i2s_opclk1", &clk_audio_bus0.clk),
-	CLKDEV_INIT("samsung-i2s.1", "i2s_opclk0", &clk_i2s1),
-	CLKDEV_INIT("samsung-i2s.1", "i2s_opclk1", &clk_audio_bus1.clk),
-#ifdef CONFIG_CPU_S3C6410
-	CLKDEV_INIT("samsung-i2s.2", "i2s_opclk0", &clk_i2s2),
-	CLKDEV_INIT("samsung-i2s.2", "i2s_opclk1", &clk_audio_bus2.clk),
-#endif
-};
-
-#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
-
-void __init_or_cpufreq s3c64xx_setup_clocks(void)
-{
-	struct clk *xtal_clk;
-	unsigned long xtal;
-	unsigned long fclk;
-	unsigned long hclk;
-	unsigned long hclk2;
-	unsigned long pclk;
-	unsigned long epll;
-	unsigned long apll;
-	unsigned long mpll;
-	unsigned int ptr;
-	u32 clkdiv0;
-
-	printk(KERN_DEBUG "%s: registering clocks\n", __func__);
-
-	clkdiv0 = __raw_readl(S3C_CLK_DIV0);
-	printk(KERN_DEBUG "%s: clkdiv0 = %08x\n", __func__, clkdiv0);
-
-	xtal_clk = clk_get(NULL, "xtal");
-	BUG_ON(IS_ERR(xtal_clk));
-
-	xtal = clk_get_rate(xtal_clk);
-	clk_put(xtal_clk);
-
-	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
-
-	/* For now assume the mux always selects the crystal */
-	clk_ext_xtal_mux.parent = xtal_clk;
-
-	epll = s3c_get_pll6553x(xtal, __raw_readl(S3C_EPLL_CON0),
-				__raw_readl(S3C_EPLL_CON1));
-	mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON));
-	apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON));
-
-	fclk = mpll;
-
-	printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n",
-	       apll, mpll, epll);
-
-	if(__raw_readl(S3C64XX_OTHERS) & S3C64XX_OTHERS_SYNCMUXSEL)
-		/* Synchronous mode */
-		hclk2 = apll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
-	else
-		/* Asynchronous mode */
-		hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2);
-
-	hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK);
-	pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK);
-
-	printk(KERN_INFO "S3C64XX: HCLK2=%ld, HCLK=%ld, PCLK=%ld\n",
-	       hclk2, hclk, pclk);
-
-	clk_fout_mpll.rate = mpll;
-	clk_fout_epll.rate = epll;
-	clk_fout_apll.rate = apll;
-
-	clk_h2.rate = hclk2;
-	clk_h.rate = hclk;
-	clk_p.rate = pclk;
-	clk_f.rate = fclk;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
-		s3c_set_clksrc(init_parents[ptr], true);
-
-	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
-		s3c_set_clksrc(&clksrcs[ptr], true);
-}
-
-static struct clk *clks1[] __initdata = {
-	&clk_ext_xtal_mux,
-	&clk_iis_cd0,
-	&clk_iis_cd1,
-	&clk_iisv4_cd,
-	&clk_pcm_cd,
-	&clk_mout_epll.clk,
-	&clk_mout_mpll.clk,
-	&clk_dout_mpll,
-	&clk_arm,
-};
-
-static struct clk *clks[] __initdata = {
-	&clk_ext,
-	&clk_epll,
-	&clk_27m,
-	&clk_48m,
-	&clk_h2,
-	&clk_xusbxti,
-};
-
-/**
- * s3c64xx_register_clocks - register clocks for s3c6400 and s3c6410
- * @xtal: The rate for the clock crystal feeding the PLLs.
- * @armclk_divlimit: Divisor mask for ARMCLK.
- *
- * Register the clocks for the S3C6400 and S3C6410 SoC range, such
- * as ARMCLK as well as the necessary parent clocks.
- *
- * This call does not setup the clocks, which is left to the
- * s3c64xx_setup_clocks() call which may be needed by the cpufreq
- * or resume code to re-set the clocks if the bootloader has changed
- * them.
- */
-void __init s3c64xx_register_clocks(unsigned long xtal, 
-				    unsigned armclk_divlimit)
-{
-	unsigned int cnt;
-
-	armclk_mask = armclk_divlimit;
-
-	s3c24xx_register_baseclocks(xtal);
-	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
-
-	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
-
-	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-
-	s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
-	for (cnt = 0; cnt < ARRAY_SIZE(clk_cdev); cnt++)
-		s3c_disable_clocks(clk_cdev[cnt], 1);
-
-	s3c24xx_register_clocks(clks1, ARRAY_SIZE(clks1));
-	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-	for (cnt = 0; cnt < ARRAY_SIZE(clksrc_cdev); cnt++)
-		s3c_register_clksrc(clksrc_cdev[cnt], 1);
-	clkdev_add_table(s3c64xx_clk_lookup, ARRAY_SIZE(s3c64xx_clk_lookup));
-}
diff --git a/arch/arm/mach-s3c64xx/common.c b/arch/arm/mach-s3c64xx/common.c
index 73d79cf..7a3ce4c 100644
--- a/arch/arm/mach-s3c64xx/common.c
+++ b/arch/arm/mach-s3c64xx/common.c
@@ -14,9 +14,14 @@
  * published by the Free Software Foundation.
  */
 
+/*
+ * NOTE: Code in this file is not used when booting with Device Tree support.
+ */
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/clk-provider.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/serial_core.h>
@@ -38,7 +43,6 @@
 #include <mach/regs-gpio.h>
 
 #include <plat/cpu.h>
-#include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/pm.h>
 #include <plat/gpio-cfg.h>
@@ -50,6 +54,19 @@
 
 #include "common.h"
 
+/* External clock frequency */
+static unsigned long xtal_f = 12000000, xusbxti_f = 48000000;
+
+void __init s3c64xx_set_xtal_freq(unsigned long freq)
+{
+	xtal_f = freq;
+}
+
+void __init s3c64xx_set_xusbxti_freq(unsigned long freq)
+{
+	xusbxti_f = freq;
+}
+
 /* uart registration process */
 
 static void __init s3c64xx_init_uarts(struct s3c2410_uartcfg *cfg, int no)
@@ -67,7 +84,6 @@
 		.idcode		= S3C6400_CPU_ID,
 		.idmask		= S3C64XX_CPU_MASK,
 		.map_io		= s3c6400_map_io,
-		.init_clocks	= s3c6400_init_clocks,
 		.init_uarts	= s3c64xx_init_uarts,
 		.init		= s3c6400_init,
 		.name		= name_s3c6400,
@@ -75,7 +91,6 @@
 		.idcode		= S3C6410_CPU_ID,
 		.idmask		= S3C64XX_CPU_MASK,
 		.map_io		= s3c6410_map_io,
-		.init_clocks	= s3c6410_init_clocks,
 		.init_uarts	= s3c64xx_init_uarts,
 		.init		= s3c6410_init,
 		.name		= name_s3c6410,
@@ -192,6 +207,10 @@
 
 static __init int s3c64xx_dev_init(void)
 {
+	/* Not applicable when using DT. */
+	if (of_have_populated_dt())
+		return 0;
+
 	subsys_system_register(&s3c64xx_subsys, NULL);
 	return device_register(&s3c64xx_dev);
 }
@@ -213,8 +232,10 @@
 {
 	/*
 	 * FIXME: there is no better place to put this at the moment
-	 * (samsung_wdt_reset_init needs clocks)
+	 * (s3c64xx_clk_init needs ioremap and must happen before init_time
+	 * samsung_wdt_reset_init needs clocks)
 	 */
+	s3c64xx_clk_init(NULL, xtal_f, xusbxti_f, soc_is_s3c6400(), S3C_VA_SYS);
 	samsung_wdt_reset_init(S3C_VA_WATCHDOG);
 
 	printk(KERN_DEBUG "%s: initialising interrupts\n", __func__);
@@ -391,6 +412,10 @@
 {
 	int irq;
 
+	/* On DT-enabled systems EINTs are handled by pinctrl-s3c64xx driver. */
+	if (of_have_populated_dt())
+		return -ENODEV;
+
 	for (irq = IRQ_EINT(0); irq <= IRQ_EINT(27); irq++) {
 		irq_set_chip_and_handler(irq, &s3c_irq_eint, handle_level_irq);
 		irq_set_chip_data(irq, (void *)eint_irq_to_bit(irq));
diff --git a/arch/arm/mach-s3c64xx/common.h b/arch/arm/mach-s3c64xx/common.h
index e8f990b..bd3bd56 100644
--- a/arch/arm/mach-s3c64xx/common.h
+++ b/arch/arm/mach-s3c64xx/common.h
@@ -22,21 +22,21 @@
 void s3c64xx_init_irq(u32 vic0, u32 vic1);
 void s3c64xx_init_io(struct map_desc *mach_desc, int size);
 
-void s3c64xx_register_clocks(unsigned long xtal, unsigned armclk_limit);
-void s3c64xx_setup_clocks(void);
-
 void s3c64xx_restart(enum reboot_mode mode, const char *cmd);
 void s3c64xx_init_late(void);
 
+void s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f,
+	unsigned long xusbxti_f, bool is_s3c6400, void __iomem *reg_base);
+void s3c64xx_set_xtal_freq(unsigned long freq);
+void s3c64xx_set_xusbxti_freq(unsigned long freq);
+
 #ifdef CONFIG_CPU_S3C6400
 
 extern  int s3c6400_init(void);
 extern void s3c6400_init_irq(void);
 extern void s3c6400_map_io(void);
-extern void s3c6400_init_clocks(int xtal);
 
 #else
-#define s3c6400_init_clocks NULL
 #define s3c6400_map_io NULL
 #define s3c6400_init NULL
 #endif
@@ -46,10 +46,8 @@
 extern  int s3c6410_init(void);
 extern void s3c6410_init_irq(void);
 extern void s3c6410_map_io(void);
-extern void s3c6410_init_clocks(int xtal);
 
 #else
-#define s3c6410_init_clocks NULL
 #define s3c6410_map_io NULL
 #define s3c6410_init NULL
 #endif
diff --git a/arch/arm/mach-s3c64xx/dma.c b/arch/arm/mach-s3c64xx/dma.c
index 759846c..7e22c21 100644
--- a/arch/arm/mach-s3c64xx/dma.c
+++ b/arch/arm/mach-s3c64xx/dma.c
@@ -12,6 +12,10 @@
  * published by the Free Software Foundation.
 */
 
+/*
+ * NOTE: Code in this file is not used when booting with Device Tree support.
+ */
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
@@ -24,6 +28,7 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/amba/pl080.h>
+#include <linux/of.h>
 
 #include <mach/dma.h>
 #include <mach/map.h>
@@ -677,7 +682,7 @@
 		goto err_map;
 	}
 
-	clk_enable(dmac->clk);
+	clk_prepare_enable(dmac->clk);
 
 	dmac->regs = regs;
 	dmac->chanbase = chbase;
@@ -711,7 +716,7 @@
 	return 0;
 
 err_clk:
-	clk_disable(dmac->clk);
+	clk_disable_unprepare(dmac->clk);
 	clk_put(dmac->clk);
 err_map:
 	iounmap(regs);
@@ -726,6 +731,10 @@
 {
 	int ret;
 
+	/* This driver is not supported when booting with device tree. */
+	if (of_have_populated_dt())
+		return -ENODEV;
+
 	printk(KERN_INFO "%s: Registering DMA channels\n", __func__);
 
 	dma_pool = dma_pool_create("DMA-LLI", NULL, sizeof(struct pl080s_lli), 16, 0);
diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-clock.h b/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
index 05332b9..4f44aac 100644
--- a/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
+++ b/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
@@ -15,145 +15,21 @@
 #ifndef __PLAT_REGS_CLOCK_H
 #define __PLAT_REGS_CLOCK_H __FILE__
 
+/*
+ * FIXME: Remove remaining definitions
+ */
+
 #define S3C_CLKREG(x)		(S3C_VA_SYS + (x))
 
-#define S3C_APLL_LOCK		S3C_CLKREG(0x00)
-#define S3C_MPLL_LOCK		S3C_CLKREG(0x04)
-#define S3C_EPLL_LOCK		S3C_CLKREG(0x08)
-#define S3C_APLL_CON		S3C_CLKREG(0x0C)
-#define S3C_MPLL_CON		S3C_CLKREG(0x10)
-#define S3C_EPLL_CON0		S3C_CLKREG(0x14)
-#define S3C_EPLL_CON1		S3C_CLKREG(0x18)
-#define S3C_CLK_SRC		S3C_CLKREG(0x1C)
-#define S3C_CLK_DIV0		S3C_CLKREG(0x20)
-#define S3C_CLK_DIV1		S3C_CLKREG(0x24)
-#define S3C_CLK_DIV2		S3C_CLKREG(0x28)
-#define S3C_CLK_OUT		S3C_CLKREG(0x2C)
-#define S3C_HCLK_GATE		S3C_CLKREG(0x30)
 #define S3C_PCLK_GATE		S3C_CLKREG(0x34)
-#define S3C_SCLK_GATE		S3C_CLKREG(0x38)
-#define S3C_MEM0_GATE		S3C_CLKREG(0x3C)
 #define S3C6410_CLK_SRC2	S3C_CLKREG(0x10C)
 #define S3C_MEM_SYS_CFG		S3C_CLKREG(0x120)
 
-/* CLKDIV0 */
-#define S3C6400_CLKDIV0_PCLK_MASK	(0xf << 12)
-#define S3C6400_CLKDIV0_PCLK_SHIFT	(12)
-#define S3C6400_CLKDIV0_HCLK2_MASK	(0x7 << 9)
-#define S3C6400_CLKDIV0_HCLK2_SHIFT	(9)
-#define S3C6400_CLKDIV0_HCLK_MASK	(0x1 << 8)
-#define S3C6400_CLKDIV0_HCLK_SHIFT	(8)
-#define S3C6400_CLKDIV0_MPLL_MASK	(0x1 << 4)
-#define S3C6400_CLKDIV0_MPLL_SHIFT	(4)
-
-#define S3C6400_CLKDIV0_ARM_MASK	(0x7 << 0)
-#define S3C6410_CLKDIV0_ARM_MASK	(0xf << 0)
-#define S3C6400_CLKDIV0_ARM_SHIFT	(0)
-
-/* HCLK GATE Registers */
-#define S3C_CLKCON_HCLK_3DSE	(1<<31)
-#define S3C_CLKCON_HCLK_UHOST	(1<<29)
-#define S3C_CLKCON_HCLK_SECUR	(1<<28)
-#define S3C_CLKCON_HCLK_SDMA1	(1<<27)
-#define S3C_CLKCON_HCLK_SDMA0	(1<<26)
-#define S3C_CLKCON_HCLK_IROM	(1<<25)
-#define S3C_CLKCON_HCLK_DDR1	(1<<24)
-#define S3C_CLKCON_HCLK_DDR0	(1<<23)
-#define S3C_CLKCON_HCLK_MEM1	(1<<22)
-#define S3C_CLKCON_HCLK_MEM0	(1<<21)
-#define S3C_CLKCON_HCLK_USB	(1<<20)
-#define S3C_CLKCON_HCLK_HSMMC2	(1<<19)
-#define S3C_CLKCON_HCLK_HSMMC1	(1<<18)
-#define S3C_CLKCON_HCLK_HSMMC0	(1<<17)
-#define S3C_CLKCON_HCLK_MDP	(1<<16)
-#define S3C_CLKCON_HCLK_DHOST	(1<<15)
-#define S3C_CLKCON_HCLK_IHOST	(1<<14)
-#define S3C_CLKCON_HCLK_DMA1	(1<<13)
-#define S3C_CLKCON_HCLK_DMA0	(1<<12)
-#define S3C_CLKCON_HCLK_JPEG	(1<<11)
-#define S3C_CLKCON_HCLK_CAMIF	(1<<10)
-#define S3C_CLKCON_HCLK_SCALER	(1<<9)
-#define S3C_CLKCON_HCLK_2D	(1<<8)
-#define S3C_CLKCON_HCLK_TV	(1<<7)
-#define S3C_CLKCON_HCLK_POST0	(1<<5)
-#define S3C_CLKCON_HCLK_ROT	(1<<4)
-#define S3C_CLKCON_HCLK_LCD	(1<<3)
-#define S3C_CLKCON_HCLK_TZIC	(1<<2)
-#define S3C_CLKCON_HCLK_INTC	(1<<1)
-#define S3C_CLKCON_HCLK_MFC	(1<<0)
-
 /* PCLK GATE Registers */
-#define S3C6410_CLKCON_PCLK_I2C1	(1<<27)
-#define S3C6410_CLKCON_PCLK_IIS2	(1<<26)
-#define S3C_CLKCON_PCLK_SKEY		(1<<24)
-#define S3C_CLKCON_PCLK_CHIPID		(1<<23)
-#define S3C_CLKCON_PCLK_SPI1		(1<<22)
-#define S3C_CLKCON_PCLK_SPI0		(1<<21)
-#define S3C_CLKCON_PCLK_HSIRX		(1<<20)
-#define S3C_CLKCON_PCLK_HSITX		(1<<19)
-#define S3C_CLKCON_PCLK_GPIO		(1<<18)
-#define S3C_CLKCON_PCLK_IIC		(1<<17)
-#define S3C_CLKCON_PCLK_IIS1		(1<<16)
-#define S3C_CLKCON_PCLK_IIS0		(1<<15)
-#define S3C_CLKCON_PCLK_AC97		(1<<14)
-#define S3C_CLKCON_PCLK_TZPC		(1<<13)
-#define S3C_CLKCON_PCLK_TSADC		(1<<12)
-#define S3C_CLKCON_PCLK_KEYPAD		(1<<11)
-#define S3C_CLKCON_PCLK_IRDA		(1<<10)
-#define S3C_CLKCON_PCLK_PCM1		(1<<9)
-#define S3C_CLKCON_PCLK_PCM0		(1<<8)
-#define S3C_CLKCON_PCLK_PWM		(1<<7)
-#define S3C_CLKCON_PCLK_RTC		(1<<6)
-#define S3C_CLKCON_PCLK_WDT		(1<<5)
 #define S3C_CLKCON_PCLK_UART3		(1<<4)
 #define S3C_CLKCON_PCLK_UART2		(1<<3)
 #define S3C_CLKCON_PCLK_UART1		(1<<2)
 #define S3C_CLKCON_PCLK_UART0		(1<<1)
-#define S3C_CLKCON_PCLK_MFC		(1<<0)
-
-/* SCLK GATE Registers */
-#define S3C_CLKCON_SCLK_UHOST		(1<<30)
-#define S3C_CLKCON_SCLK_MMC2_48		(1<<29)
-#define S3C_CLKCON_SCLK_MMC1_48		(1<<28)
-#define S3C_CLKCON_SCLK_MMC0_48		(1<<27)
-#define S3C_CLKCON_SCLK_MMC2		(1<<26)
-#define S3C_CLKCON_SCLK_MMC1		(1<<25)
-#define S3C_CLKCON_SCLK_MMC0		(1<<24)
-#define S3C_CLKCON_SCLK_SPI1_48 	(1<<23)
-#define S3C_CLKCON_SCLK_SPI0_48 	(1<<22)
-#define S3C_CLKCON_SCLK_SPI1		(1<<21)
-#define S3C_CLKCON_SCLK_SPI0		(1<<20)
-#define S3C_CLKCON_SCLK_DAC27		(1<<19)
-#define S3C_CLKCON_SCLK_TV27		(1<<18)
-#define S3C_CLKCON_SCLK_SCALER27	(1<<17)
-#define S3C_CLKCON_SCLK_SCALER		(1<<16)
-#define S3C_CLKCON_SCLK_LCD27		(1<<15)
-#define S3C_CLKCON_SCLK_LCD		(1<<14)
-#define S3C6400_CLKCON_SCLK_POST1_27	(1<<13)
-#define S3C6410_CLKCON_FIMC		(1<<13)
-#define S3C_CLKCON_SCLK_POST0_27	(1<<12)
-#define S3C6400_CLKCON_SCLK_POST1	(1<<11)
-#define S3C6410_CLKCON_SCLK_AUDIO2	(1<<11)
-#define S3C_CLKCON_SCLK_POST0		(1<<10)
-#define S3C_CLKCON_SCLK_AUDIO1		(1<<9)
-#define S3C_CLKCON_SCLK_AUDIO0		(1<<8)
-#define S3C_CLKCON_SCLK_SECUR		(1<<7)
-#define S3C_CLKCON_SCLK_IRDA		(1<<6)
-#define S3C_CLKCON_SCLK_UART		(1<<5)
-#define S3C_CLKCON_SCLK_ONENAND 	(1<<4)
-#define S3C_CLKCON_SCLK_MFC		(1<<3)
-#define S3C_CLKCON_SCLK_CAM		(1<<2)
-#define S3C_CLKCON_SCLK_JPEG		(1<<1)
-
-/* CLKSRC */
-
-#define S3C6400_CLKSRC_APLL_MOUT	(1 << 0)
-#define S3C6400_CLKSRC_MPLL_MOUT	(1 << 1)
-#define S3C6400_CLKSRC_EPLL_MOUT	(1 << 2)
-#define S3C6400_CLKSRC_APLL_MOUT_SHIFT	(0)
-#define S3C6400_CLKSRC_MPLL_MOUT_SHIFT	(1)
-#define S3C6400_CLKSRC_EPLL_MOUT_SHIFT	(2)
-#define S3C6400_CLKSRC_MFC		(1 << 4)
 
 /* MEM_SYS_CFG */
 #define MEM_SYS_CFG_INDEP_CF		0x4000
diff --git a/arch/arm/mach-s3c64xx/irq-pm.c b/arch/arm/mach-s3c64xx/irq-pm.c
index c3da1b6..1649c0d 100644
--- a/arch/arm/mach-s3c64xx/irq-pm.c
+++ b/arch/arm/mach-s3c64xx/irq-pm.c
@@ -12,12 +12,17 @@
  * published by the Free Software Foundation.
  */
 
+/*
+ * NOTE: Code in this file is not used when booting with Device Tree support.
+ */
+
 #include <linux/kernel.h>
 #include <linux/syscore_ops.h>
 #include <linux/interrupt.h>
 #include <linux/serial_core.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/of.h>
 
 #include <mach/map.h>
 
@@ -101,6 +106,10 @@
 
 static __init int s3c64xx_syscore_init(void)
 {
+	/* Appropriate drivers (pinctrl, uart) handle this when using DT. */
+	if (of_have_populated_dt())
+		return 0;
+
 	register_syscore_ops(&s3c64xx_irq_syscore_ops);
 
 	return 0;
diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c
index 35e3f54..d266dd5 100644
--- a/arch/arm/mach-s3c64xx/mach-anw6410.c
+++ b/arch/arm/mach-s3c64xx/mach-anw6410.c
@@ -207,7 +207,7 @@
 static void __init anw6410_map_io(void)
 {
 	s3c64xx_init_io(anw6410_iodesc, ARRAY_SIZE(anw6410_iodesc));
-	s3c24xx_init_clocks(12000000);
+	s3c64xx_set_xtal_freq(12000000);
 	s3c24xx_init_uarts(anw6410_uartcfgs, ARRAY_SIZE(anw6410_uartcfgs));
 	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index eb8e5a1..aca7d16 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -310,10 +310,6 @@
 
 	REGULATOR_SUPPLY("SPKVDDL", "spi0.1"),
 	REGULATOR_SUPPLY("SPKVDDR", "spi0.1"),
-	REGULATOR_SUPPLY("SPKVDDL", "wm5102-codec"),
-	REGULATOR_SUPPLY("SPKVDDR", "wm5102-codec"),
-	REGULATOR_SUPPLY("SPKVDDL", "wm5110-codec"),
-	REGULATOR_SUPPLY("SPKVDDR", "wm5110-codec"),
 
 	REGULATOR_SUPPLY("DC1VDD", "0-0034"),
 	REGULATOR_SUPPLY("DC2VDD", "0-0034"),
@@ -653,14 +649,6 @@
 	REGULATOR_SUPPLY("DBVDD3", "spi0.1"),
 	REGULATOR_SUPPLY("LDOVDD", "spi0.1"),
 	REGULATOR_SUPPLY("CPVDD", "spi0.1"),
-
-	REGULATOR_SUPPLY("DBVDD2", "wm5102-codec"),
-	REGULATOR_SUPPLY("DBVDD3", "wm5102-codec"),
-	REGULATOR_SUPPLY("CPVDD", "wm5102-codec"),
-
-	REGULATOR_SUPPLY("DBVDD2", "wm5110-codec"),
-	REGULATOR_SUPPLY("DBVDD3", "wm5110-codec"),
-	REGULATOR_SUPPLY("CPVDD", "wm5110-codec"),
 };
 
 static struct regulator_init_data pvdd_1v8 = {
@@ -743,7 +731,7 @@
 static void __init crag6410_map_io(void)
 {
 	s3c64xx_init_io(NULL, 0);
-	s3c24xx_init_clocks(12000000);
+	s3c64xx_set_xtal_freq(12000000);
 	s3c24xx_init_uarts(crag6410_uartcfgs, ARRAY_SIZE(crag6410_uartcfgs));
 	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c
index f39569e..e806404 100644
--- a/arch/arm/mach-s3c64xx/mach-hmt.c
+++ b/arch/arm/mach-s3c64xx/mach-hmt.c
@@ -247,7 +247,7 @@
 static void __init hmt_map_io(void)
 {
 	s3c64xx_init_io(hmt_iodesc, ARRAY_SIZE(hmt_iodesc));
-	s3c24xx_init_clocks(12000000);
+	s3c64xx_set_xtal_freq(12000000);
 	s3c24xx_init_uarts(hmt_uartcfgs, ARRAY_SIZE(hmt_uartcfgs));
 	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c
index fc043e3..58d46a3 100644
--- a/arch/arm/mach-s3c64xx/mach-mini6410.c
+++ b/arch/arm/mach-s3c64xx/mach-mini6410.c
@@ -231,7 +231,7 @@
 	u32 tmp;
 
 	s3c64xx_init_io(NULL, 0);
-	s3c24xx_init_clocks(12000000);
+	s3c64xx_set_xtal_freq(12000000);
 	s3c24xx_init_uarts(mini6410_uartcfgs, ARRAY_SIZE(mini6410_uartcfgs));
 	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
diff --git a/arch/arm/mach-s3c64xx/mach-ncp.c b/arch/arm/mach-s3c64xx/mach-ncp.c
index 7e2c390..2067b0b 100644
--- a/arch/arm/mach-s3c64xx/mach-ncp.c
+++ b/arch/arm/mach-s3c64xx/mach-ncp.c
@@ -86,7 +86,7 @@
 static void __init ncp_map_io(void)
 {
 	s3c64xx_init_io(ncp_iodesc, ARRAY_SIZE(ncp_iodesc));
-	s3c24xx_init_clocks(12000000);
+	s3c64xx_set_xtal_freq(12000000);
 	s3c24xx_init_uarts(ncp_uartcfgs, ARRAY_SIZE(ncp_uartcfgs));
 	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
diff --git a/arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c b/arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c
new file mode 100644
index 0000000..7eb9a10
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/mach-s3c64xx-dt.c
@@ -0,0 +1,85 @@
+/*
+ * Samsung's S3C64XX flattened device tree enabled machine
+ *
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/clk-provider.h>
+#include <linux/irqchip.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/system_misc.h>
+
+#include <plat/cpu.h>
+#include <plat/watchdog-reset.h>
+
+#include <mach/map.h>
+
+#include "common.h"
+
+/*
+ * IO mapping for shared system controller IP.
+ *
+ * FIXME: Make remaining drivers use dynamic mapping.
+ */
+static struct map_desc s3c64xx_dt_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S3C_VA_SYS,
+		.pfn		= __phys_to_pfn(S3C64XX_PA_SYSCON),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static void __init s3c64xx_dt_map_io(void)
+{
+	debug_ll_io_init();
+	iotable_init(s3c64xx_dt_iodesc, ARRAY_SIZE(s3c64xx_dt_iodesc));
+
+	s3c64xx_init_cpu();
+
+	if (!soc_is_s3c64xx())
+		panic("SoC is not S3C64xx!");
+}
+
+static void __init s3c64xx_dt_init_irq(void)
+{
+	of_clk_init(NULL);
+	samsung_wdt_reset_of_init();
+	irqchip_init();
+};
+
+static void __init s3c64xx_dt_init_machine(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static void s3c64xx_dt_restart(enum reboot_mode mode, const char *cmd)
+{
+	if (mode != REBOOT_SOFT)
+		samsung_wdt_reset();
+
+	/* if all else fails, or mode was for soft, jump to 0 */
+	soft_restart(0);
+}
+
+static char const *s3c64xx_dt_compat[] __initdata = {
+	"samsung,s3c6400",
+	"samsung,s3c6410",
+	NULL
+};
+
+DT_MACHINE_START(S3C6400_DT, "Samsung S3C64xx (Flattened Device Tree)")
+	/* Maintainer: Tomasz Figa <tomasz.figa@gmail.com> */
+	.dt_compat	= s3c64xx_dt_compat,
+	.map_io		= s3c64xx_dt_map_io,
+	.init_irq	= s3c64xx_dt_init_irq,
+	.init_machine	= s3c64xx_dt_init_machine,
+	.restart        = s3c64xx_dt_restart,
+MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c
index 86d980b..0f47237 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq.c
@@ -337,13 +337,6 @@
 	return ret;
 }
 
-static int __init smartq_usb_otg_init(void)
-{
-	clk_xusbxti.rate = 12000000;
-
-	return 0;
-}
-
 static int __init smartq_wifi_init(void)
 {
 	int ret;
@@ -377,7 +370,8 @@
 void __init smartq_map_io(void)
 {
 	s3c64xx_init_io(smartq_iodesc, ARRAY_SIZE(smartq_iodesc));
-	s3c24xx_init_clocks(12000000);
+	s3c64xx_set_xtal_freq(12000000);
+	s3c64xx_set_xusbxti_freq(12000000);
 	s3c24xx_init_uarts(smartq_uartcfgs, ARRAY_SIZE(smartq_uartcfgs));
 	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
@@ -399,7 +393,6 @@
 	WARN_ON(smartq_lcd_setup_gpio());
 	WARN_ON(smartq_power_off_init());
 	WARN_ON(smartq_usb_host_init());
-	WARN_ON(smartq_usb_otg_init());
 	WARN_ON(smartq_wifi_init());
 
 	platform_add_devices(smartq_devices, ARRAY_SIZE(smartq_devices));
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6400.c b/arch/arm/mach-s3c64xx/mach-smdk6400.c
index d70c084..27381cf 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6400.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6400.c
@@ -65,7 +65,7 @@
 static void __init smdk6400_map_io(void)
 {
 	s3c64xx_init_io(smdk6400_iodesc, ARRAY_SIZE(smdk6400_iodesc));
-	s3c24xx_init_clocks(12000000);
+	s3c64xx_set_xtal_freq(12000000);
 	s3c24xx_init_uarts(smdk6400_uartcfgs, ARRAY_SIZE(smdk6400_uartcfgs));
 	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index d90b450..2a7b32c 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -634,7 +634,7 @@
 	u32 tmp;
 
 	s3c64xx_init_io(smdk6410_iodesc, ARRAY_SIZE(smdk6410_iodesc));
-	s3c24xx_init_clocks(12000000);
+	s3c64xx_set_xtal_freq(12000000);
 	s3c24xx_init_uarts(smdk6410_uartcfgs, ARRAY_SIZE(smdk6410_uartcfgs));
 	samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
diff --git a/arch/arm/mach-s3c64xx/pm.c b/arch/arm/mach-s3c64xx/pm.c
index 6a1f91f..8cdb824 100644
--- a/arch/arm/mach-s3c64xx/pm.c
+++ b/arch/arm/mach-s3c64xx/pm.c
@@ -194,29 +194,8 @@
 #endif
 
 static struct sleep_save core_save[] = {
-	SAVE_ITEM(S3C_APLL_LOCK),
-	SAVE_ITEM(S3C_MPLL_LOCK),
-	SAVE_ITEM(S3C_EPLL_LOCK),
-	SAVE_ITEM(S3C_CLK_SRC),
-	SAVE_ITEM(S3C_CLK_DIV0),
-	SAVE_ITEM(S3C_CLK_DIV1),
-	SAVE_ITEM(S3C_CLK_DIV2),
-	SAVE_ITEM(S3C_CLK_OUT),
-	SAVE_ITEM(S3C_HCLK_GATE),
-	SAVE_ITEM(S3C_PCLK_GATE),
-	SAVE_ITEM(S3C_SCLK_GATE),
-	SAVE_ITEM(S3C_MEM0_GATE),
-
-	SAVE_ITEM(S3C_EPLL_CON1),
-	SAVE_ITEM(S3C_EPLL_CON0),
-
 	SAVE_ITEM(S3C64XX_MEM0DRVCON),
 	SAVE_ITEM(S3C64XX_MEM1DRVCON),
-
-#ifndef CONFIG_CPU_FREQ
-	SAVE_ITEM(S3C_APLL_CON),
-	SAVE_ITEM(S3C_MPLL_CON),
-#endif
 };
 
 static struct sleep_save misc_save[] = {
diff --git a/arch/arm/mach-s3c64xx/s3c6400.c b/arch/arm/mach-s3c64xx/s3c6400.c
index 4869714..3db0c98 100644
--- a/arch/arm/mach-s3c64xx/s3c6400.c
+++ b/arch/arm/mach-s3c64xx/s3c6400.c
@@ -9,6 +9,10 @@
  * published by the Free Software Foundation.
 */
 
+/*
+ * NOTE: Code in this file is not used when booting with Device Tree support.
+ */
+
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
@@ -20,6 +24,7 @@
 #include <linux/device.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -58,12 +63,6 @@
 	s3c64xx_onenand1_setname("s3c6400-onenand");
 }
 
-void __init s3c6400_init_clocks(int xtal)
-{
-	s3c64xx_register_clocks(xtal, S3C6400_CLKDIV0_ARM_MASK);
-	s3c64xx_setup_clocks();
-}
-
 void __init s3c6400_init_irq(void)
 {
 	/* VIC0 does not have IRQS 5..7,
@@ -82,6 +81,10 @@
 
 static int __init s3c6400_core_init(void)
 {
+	/* Not applicable when using DT. */
+	if (of_have_populated_dt())
+		return 0;
+
 	return subsys_system_register(&s3c6400_subsys, NULL);
 }
 
diff --git a/arch/arm/mach-s3c64xx/s3c6410.c b/arch/arm/mach-s3c64xx/s3c6410.c
index 31c29fd..72b2278 100644
--- a/arch/arm/mach-s3c64xx/s3c6410.c
+++ b/arch/arm/mach-s3c64xx/s3c6410.c
@@ -10,6 +10,10 @@
  * published by the Free Software Foundation.
 */
 
+/*
+ * NOTE: Code in this file is not used when booting with Device Tree support.
+ */
+
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
@@ -21,6 +25,7 @@
 #include <linux/device.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -62,13 +67,6 @@
 	s3c_cfcon_setname("s3c64xx-pata");
 }
 
-void __init s3c6410_init_clocks(int xtal)
-{
-	printk(KERN_DEBUG "%s: initialising clocks\n", __func__);
-	s3c64xx_register_clocks(xtal, S3C6410_CLKDIV0_ARM_MASK);
-	s3c64xx_setup_clocks();
-}
-
 void __init s3c6410_init_irq(void)
 {
 	/* VIC0 is missing IRQ7, VIC1 is fully populated. */
@@ -86,6 +84,10 @@
 
 static int __init s3c6410_core_init(void)
 {
+	/* Not applicable when using DT. */
+	if (of_have_populated_dt())
+		return 0;
+
 	return subsys_system_register(&s3c6410_subsys, NULL);
 }
 
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-clock.h b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
index 032de66..e345584 100644
--- a/arch/arm/mach-s5pv210/include/mach/regs-clock.h
+++ b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
@@ -147,10 +147,6 @@
 #define S5P_HDMI_PHY_CONTROL	S5P_CLKREG(0xE804)
 #define S5P_USB_PHY_CONTROL	S5P_CLKREG(0xE80C)
 #define S5P_DAC_PHY_CONTROL	S5P_CLKREG(0xE810)
-#define S5P_MIPI_DPHY_CONTROL(x) S5P_CLKREG(0xE814)
-#define S5P_MIPI_DPHY_ENABLE	(1 << 0)
-#define S5P_MIPI_DPHY_SRESETN	(1 << 1)
-#define S5P_MIPI_DPHY_MRESETN	(1 << 2)
 
 #define S5P_INFORM0		S5P_CLKREG(0xF000)
 #define S5P_INFORM1		S5P_CLKREG(0xF004)
diff --git a/arch/arm/mach-shark/Makefile b/arch/arm/mach-shark/Makefile
deleted file mode 100644
index 2965718..0000000
--- a/arch/arm/mach-shark/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y			:= core.o dma.o irq.o pci.o leds.o
-obj-m			:=
-obj-n			:=
-obj-			:=
diff --git a/arch/arm/mach-shark/Makefile.boot b/arch/arm/mach-shark/Makefile.boot
deleted file mode 100644
index e40e24e..0000000
--- a/arch/arm/mach-shark/Makefile.boot
+++ /dev/null
@@ -1,2 +0,0 @@
-   zreladdr-y	+= 0x08008000
-
diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c
deleted file mode 100644
index 1d32c5e..0000000
--- a/arch/arm/mach-shark/core.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- *  linux/arch/arm/mach-shark/arch.c
- *
- *  Architecture specific stuff.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/sched.h>
-#include <linux/serial_8250.h>
-#include <linux/io.h>
-#include <linux/cpu.h>
-#include <linux/reboot.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/param.h>
-#include <asm/system_misc.h>
-
-#include <asm/mach/map.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#define ROMCARD_SIZE            0x08000000
-#define ROMCARD_START           0x10000000
-
-static void shark_restart(enum reboot_mode mode, const char *cmd)
-{
-        short temp;
-        /* Reset the Machine via pc[3] of the sequoia chipset */
-        outw(0x09,0x24);
-        temp=inw(0x26);
-        temp = temp | (1<<3) | (1<<10);
-        outw(0x09,0x24);
-        outw(temp,0x26);
-}
-
-static struct plat_serial8250_port serial_platform_data[] = {
-	{
-		.iobase		= 0x3f8,
-		.irq		= 4,
-		.uartclk	= 1843200,
-		.regshift	= 0,
-		.iotype		= UPIO_PORT,
-		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
-	},
-	{
-		.iobase		= 0x2f8,
-		.irq		= 3,
-		.uartclk	= 1843200,
-		.regshift	= 0,
-		.iotype		= UPIO_PORT,
-		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
-	},
-	{ },
-};
-
-static struct platform_device serial_device = {
-	.name			= "serial8250",
-	.id			= PLAT8250_DEV_PLATFORM,
-	.dev			= {
-		.platform_data	= serial_platform_data,
-	},
-};
-
-static struct resource rtc_resources[] = {
-	[0] = {
-		.start	= 0x70,
-		.end	= 0x73,
-		.flags	= IORESOURCE_IO,
-	},
-	[1] = {
-		.start	= IRQ_ISA_RTC_ALARM,
-		.end	= IRQ_ISA_RTC_ALARM,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-static struct platform_device rtc_device = {
-	.name		= "rtc_cmos",
-	.id		= -1,
-	.resource	= rtc_resources,
-	.num_resources	= ARRAY_SIZE(rtc_resources),
-};
-
-static int __init shark_init(void)
-{
-	int ret;
-
-	if (machine_is_shark())
-	{
-	        ret = platform_device_register(&rtc_device);
-		if (ret) printk(KERN_ERR "Unable to register RTC device: %d\n", ret);
-		ret = platform_device_register(&serial_device);
-		if (ret) printk(KERN_ERR "Unable to register Serial device: %d\n", ret);
-	}
-	return 0;
-}
-
-arch_initcall(shark_init);
-
-extern void shark_init_irq(void);
-
-#define IRQ_TIMER 0
-#define HZ_TIME ((1193180 + HZ/2) / HZ)
-
-static irqreturn_t
-shark_timer_interrupt(int irq, void *dev_id)
-{
-	timer_tick();
-	return IRQ_HANDLED;
-}
-
-static struct irqaction shark_timer_irq = {
-	.name		= "Shark Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= shark_timer_interrupt,
-};
-
-/*
- * Set up timer interrupt, and return the current time in seconds.
- */
-static void __init shark_timer_init(void)
-{
-	outb(0x34, 0x43);               /* binary, mode 0, LSB/MSB, Ch 0 */
-	outb(HZ_TIME & 0xff, 0x40);     /* LSB of count */
-	outb(HZ_TIME >> 8, 0x40);
-
-	setup_irq(IRQ_TIMER, &shark_timer_irq);
-}
-
-static void shark_init_early(void)
-{
-	cpu_idle_poll_ctrl(true);
-}
-
-MACHINE_START(SHARK, "Shark")
-	/* Maintainer: Alexander Schulz */
-	.atag_offset	= 0x3000,
-	.init_early	= shark_init_early,
-	.init_irq	= shark_init_irq,
-	.init_time	= shark_timer_init,
-	.dma_zone_size	= SZ_4M,
-	.restart	= shark_restart,
-MACHINE_END
diff --git a/arch/arm/mach-shark/dma.c b/arch/arm/mach-shark/dma.c
deleted file mode 100644
index 10b5b8b..0000000
--- a/arch/arm/mach-shark/dma.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- *  linux/arch/arm/mach-shark/dma.c
- *
- *  by Alexander Schulz
- *
- *  derived from:
- *  arch/arm/kernel/dma-ebsa285.c
- *  Copyright (C) 1998 Phil Blundell
- */
-
-#include <linux/init.h>
-
-#include <asm/dma.h>
-#include <asm/mach/dma.h>
-
-static int __init shark_dma_init(void)
-{
-#ifdef CONFIG_ISA_DMA
-	isa_init_dma();
-#endif
-	return 0;
-}
-core_initcall(shark_dma_init);
diff --git a/arch/arm/mach-shark/include/mach/debug-macro.S b/arch/arm/mach-shark/include/mach/debug-macro.S
deleted file mode 100644
index d129119..0000000
--- a/arch/arm/mach-shark/include/mach/debug-macro.S
+++ /dev/null
@@ -1,34 +0,0 @@
-/* arch/arm/mach-shark/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-		.macro	addruart, rp, rv, tmp
-		mov	\rp, #0x3f8
-		orr	\rv, \rp, #0xfe000000
-		orr	\rv, \rv, #0x00e00000
-		orr	\rp, \rp, #0x40000000
-		.endm
-
-		.macro	senduart,rd,rx
-		strb	\rd, [\rx]
-		.endm
-
-		.macro waituart,rd,rx
-		.endm
-
-		.macro	busyuart,rd,rx
-		mov	\rd, #0
-1001:		add	\rd, \rd, #1
-		teq	\rd, #0x10000
-		bne	1001b
-		.endm
-
diff --git a/arch/arm/mach-shark/include/mach/entry-macro.S b/arch/arm/mach-shark/include/mach/entry-macro.S
deleted file mode 100644
index c9e49f0..0000000
--- a/arch/arm/mach-shark/include/mach/entry-macro.S
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * arch/arm/mach-shark/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for Shark platform
- *
- * 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.
- */
-		.macro  get_irqnr_preamble, base, tmp
-		mov	\base, #0xfe000000
-		orr	\base, \base, #0x00e00000
-		.endm
-
-		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-		mov	\irqstat, #0x0C
-		strb	\irqstat, [\base, #0x20]	@outb(0x0C, 0x20) /* Poll command */
-		ldrb	\irqnr, [\base, #0x20]		@irq = inb(0x20) & 7
-		and	\irqstat, \irqnr, #0x80
-		teq	\irqstat, #0
-		beq	43f
-		and	\irqnr, \irqnr, #7
-		teq	\irqnr, #2
-		bne	44f
-43:		mov	\irqstat, #0x0C
-		strb	\irqstat, [\base, #0xa0]	@outb(0x0C, 0xA0) /* Poll command */
-		ldrb	\irqnr, [\base, #0xa0]		@irq = (inb(0xA0) & 7) + 8
-		and	\irqstat, \irqnr, #0x80
-		teq	\irqstat, #0
-		beq	44f
-		and	\irqnr, \irqnr, #7
-		add	\irqnr, \irqnr, #8
-44:		teq	\irqstat, #0
-		.endm
-
diff --git a/arch/arm/mach-shark/include/mach/framebuffer.h b/arch/arm/mach-shark/include/mach/framebuffer.h
deleted file mode 100644
index 84a5bf6..0000000
--- a/arch/arm/mach-shark/include/mach/framebuffer.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * arch/arm/mach-shark/include/mach/framebuffer.h
- *
- * by Alexander Schulz
- *
- */
-
-#ifndef __ASM_ARCH_FRAMEBUFFER_H
-#define __ASM_ARCH_FRAMEBUFFER_H
-
-/* defines for the Framebuffer */
-#define FB_START		0x06000000
-#define FB_SIZE			0x01000000
-
-#endif
-
diff --git a/arch/arm/mach-shark/include/mach/hardware.h b/arch/arm/mach-shark/include/mach/hardware.h
deleted file mode 100644
index 663f952..0000000
--- a/arch/arm/mach-shark/include/mach/hardware.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * arch/arm/mach-shark/include/mach/hardware.h
- *
- * by Alexander Schulz
- *
- * derived from:
- * arch/arm/mach-ebsa110/include/mach/hardware.h
- * Copyright (C) 1996-1999 Russell King.
- */
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#define UNCACHEABLE_ADDR        0xdf010000
-
-#endif
-
diff --git a/arch/arm/mach-shark/include/mach/irqs.h b/arch/arm/mach-shark/include/mach/irqs.h
deleted file mode 100644
index c8e8a4e..0000000
--- a/arch/arm/mach-shark/include/mach/irqs.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * arch/arm/mach-shark/include/mach/irqs.h
- *
- * by Alexander Schulz
- */
-
-#define NR_IRQS			16
-
-#define IRQ_ISA_KEYBOARD	 1
-#define IRQ_ISA_RTC_ALARM	 8
-#define I8042_KBD_IRQ		 1
-#define I8042_AUX_IRQ		12
-#define IRQ_HARDDISK            14
diff --git a/arch/arm/mach-shark/include/mach/isa-dma.h b/arch/arm/mach-shark/include/mach/isa-dma.h
deleted file mode 100644
index 96c43b8..0000000
--- a/arch/arm/mach-shark/include/mach/isa-dma.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * arch/arm/mach-shark/include/mach/isa-dma.h
- *
- * by Alexander Schulz
- */
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-#define MAX_DMA_CHANNELS	8
-#define DMA_ISA_CASCADE         4
-
-#endif /* _ASM_ARCH_DMA_H */
-
diff --git a/arch/arm/mach-shark/include/mach/memory.h b/arch/arm/mach-shark/include/mach/memory.h
deleted file mode 100644
index 1cf8d69..0000000
--- a/arch/arm/mach-shark/include/mach/memory.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * arch/arm/mach-shark/include/mach/memory.h
- *
- * by Alexander Schulz
- *
- * derived from:
- * arch/arm/mach-ebsa110/include/mach/memory.h
- * Copyright (c) 1996-1999 Russell King.
- */
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-#include <asm/sizes.h>
-
-/*
- * Physical DRAM offset.
- */
-#define PLAT_PHYS_OFFSET     UL(0x08000000)
-
-/*
- * Cache flushing area
- */
-#define FLUSH_BASE_PHYS		0x80000000
-#define FLUSH_BASE		0xdf000000
-
-#endif
diff --git a/arch/arm/mach-shark/include/mach/timex.h b/arch/arm/mach-shark/include/mach/timex.h
deleted file mode 100644
index bb6eeae..0000000
--- a/arch/arm/mach-shark/include/mach/timex.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * arch/arm/mach-shark/include/mach/timex.h
- *
- * by Alexander Schulz
- */
-
-#define CLOCK_TICK_RATE 1193180
diff --git a/arch/arm/mach-shark/include/mach/uncompress.h b/arch/arm/mach-shark/include/mach/uncompress.h
deleted file mode 100644
index a168435..0000000
--- a/arch/arm/mach-shark/include/mach/uncompress.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * arch/arm/mach-shark/include/mach/uncompress.h
- * by Alexander Schulz
- *
- * derived from:
- * arch/arm/mach-footbridge/include/mach/uncompress.h
- * Copyright (C) 1996,1997,1998 Russell King
- */
-
-#define SERIAL_BASE ((volatile unsigned char *)0x400003f8)
-
-static inline void putc(int c)
-{
-	volatile int t;
-
-	SERIAL_BASE[0] = c;
-	t=0x10000;
-	while (t--);
-}
-
-static inline void flush(void)
-{
-}
-
-#ifdef DEBUG
-static void putn(unsigned long z)
-{
-	int i;
-	char x;
-
-	putc('0');
-	putc('x');
-	for (i=0;i<8;i++) {
-		x='0'+((z>>((7-i)*4))&0xf);
-		if (x>'9') x=x-'0'+'A'-10;
-		putc(x);
-	}
-}
-
-static void putr()
-{
-	putc('\n');
-	putc('\r');
-}
-#endif
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
diff --git a/arch/arm/mach-shark/irq.c b/arch/arm/mach-shark/irq.c
deleted file mode 100644
index 5dce13e..0000000
--- a/arch/arm/mach-shark/irq.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- *  linux/arch/arm/mach-shark/irq.c
- *
- * by Alexander Schulz
- *
- * derived from linux/arch/ppc/kernel/i8259.c and:
- * arch/arm/mach-ebsa110/include/mach/irq.h
- * Copyright (C) 1996-1998 Russell King
- */
-
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-
-/*
- * 8259A PIC functions to handle ISA devices:
- */
-
-/*
- * This contains the irq mask for both 8259A irq controllers,
- * Let through the cascade-interrupt no. 2 (ff-(1<<2)==fb)
- */
-static unsigned char cached_irq_mask[2] = { 0xfb, 0xff };
-
-/*
- * These have to be protected by the irq controller spinlock
- * before being called.
- */
-static void shark_disable_8259A_irq(struct irq_data *d)
-{
-	unsigned int mask;
-	if (d->irq<8) {
-	  mask = 1 << d->irq;
-	  cached_irq_mask[0] |= mask;
-	  outb(cached_irq_mask[1],0xA1);
-	} else {
-	  mask = 1 << (d->irq-8);
-	  cached_irq_mask[1] |= mask;
-	  outb(cached_irq_mask[0],0x21);
-	}
-}
-
-static void shark_enable_8259A_irq(struct irq_data *d)
-{
-	unsigned int mask;
-	if (d->irq<8) {
-	  mask = ~(1 << d->irq);
-	  cached_irq_mask[0] &= mask;
-	  outb(cached_irq_mask[0],0x21);
-	} else {
-	  mask = ~(1 << (d->irq-8));
-	  cached_irq_mask[1] &= mask;
-	  outb(cached_irq_mask[1],0xA1);
-	}
-}
-
-static void shark_ack_8259A_irq(struct irq_data *d){}
-
-static irqreturn_t bogus_int(int irq, void *dev_id)
-{
-	printk("Got interrupt %i!\n",irq);
-	return IRQ_NONE;
-}
-
-static struct irqaction cascade;
-
-static struct irq_chip fb_chip = {
-	.name		= "XT-PIC",
-	.irq_ack	= shark_ack_8259A_irq,
-	.irq_mask	= shark_disable_8259A_irq,
-	.irq_unmask	= shark_enable_8259A_irq,
-};
-
-void __init shark_init_irq(void)
-{
-	int irq;
-
-	for (irq = 0; irq < NR_IRQS; irq++) {
-		irq_set_chip_and_handler(irq, &fb_chip, handle_edge_irq);
-		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-	}
-
-	/* init master interrupt controller */
-	outb(0x11, 0x20); /* Start init sequence, edge triggered (level: 0x19)*/
-	outb(0x00, 0x21); /* Vector base */
-	outb(0x04, 0x21); /* Cascade (slave) on IRQ2 */
-	outb(0x03, 0x21); /* Select 8086 mode , auto eoi*/
-	outb(0x0A, 0x20);
-	/* init slave interrupt controller */
-	outb(0x11, 0xA0); /* Start init sequence, edge triggered */
-	outb(0x08, 0xA1); /* Vector base */
-	outb(0x02, 0xA1); /* Cascade (slave) on IRQ2 */
-	outb(0x03, 0xA1); /* Select 8086 mode, auto eoi */
-	outb(0x0A, 0xA0);
-	outb(cached_irq_mask[1],0xA1);
-	outb(cached_irq_mask[0],0x21);
-	//request_region(0x20,0x2,"pic1");
-	//request_region(0xA0,0x2,"pic2");
-
-	cascade.handler = bogus_int;
-	cascade.name = "cascade";
-	setup_irq(2,&cascade);
-}
-
diff --git a/arch/arm/mach-shark/leds.c b/arch/arm/mach-shark/leds.c
deleted file mode 100644
index 081c778..0000000
--- a/arch/arm/mach-shark/leds.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * DIGITAL Shark LED control routines.
- *
- * Driver for the 3 user LEDs found on the Shark
- * Based on Versatile and RealView machine LED code
- *
- * License terms: GNU General Public License (GPL) version 2
- * Author: Bryan Wu <bryan.wu@canonical.com>
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/leds.h>
-
-#include <asm/mach-types.h>
-
-#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
-struct shark_led {
-	struct led_classdev cdev;
-	u8 mask;
-};
-
-/*
- * The triggers lines up below will only be used if the
- * LED triggers are compiled in.
- */
-static const struct {
-	const char *name;
-	const char *trigger;
-} shark_leds[] = {
-	{ "shark:amber0", "default-on", },	/* Bit 5 */
-	{ "shark:green", "heartbeat", },	/* Bit 6 */
-	{ "shark:amber1", "cpu0" },		/* Bit 7 */
-};
-
-static u16 led_reg_read(void)
-{
-	outw(0x09, 0x24);
-	return inw(0x26);
-}
-
-static void led_reg_write(u16 value)
-{
-	outw(0x09, 0x24);
-	outw(value, 0x26);
-}
-
-static void shark_led_set(struct led_classdev *cdev,
-			      enum led_brightness b)
-{
-	struct shark_led *led = container_of(cdev,
-						 struct shark_led, cdev);
-	u16 reg = led_reg_read();
-
-	if (b != LED_OFF)
-		reg |= led->mask;
-	else
-		reg &= ~led->mask;
-
-	led_reg_write(reg);
-}
-
-static enum led_brightness shark_led_get(struct led_classdev *cdev)
-{
-	struct shark_led *led = container_of(cdev,
-						 struct shark_led, cdev);
-	u16 reg = led_reg_read();
-
-	return (reg & led->mask) ? LED_FULL : LED_OFF;
-}
-
-static int __init shark_leds_init(void)
-{
-	int i;
-	u16 reg;
-
-	if (!machine_is_shark())
-		return -ENODEV;
-
-	for (i = 0; i < ARRAY_SIZE(shark_leds); i++) {
-		struct shark_led *led;
-
-		led = kzalloc(sizeof(*led), GFP_KERNEL);
-		if (!led)
-			break;
-
-		led->cdev.name = shark_leds[i].name;
-		led->cdev.brightness_set = shark_led_set;
-		led->cdev.brightness_get = shark_led_get;
-		led->cdev.default_trigger = shark_leds[i].trigger;
-
-		/* Count in 5 bits offset */
-		led->mask = BIT(i + 5);
-
-		if (led_classdev_register(NULL, &led->cdev) < 0) {
-			kfree(led);
-			break;
-		}
-	}
-
-	/* Make LEDs independent of power-state */
-	request_region(0x24, 4, "led_reg");
-	reg = led_reg_read();
-	reg |= 1 << 10;
-	led_reg_write(reg);
-
-	return 0;
-}
-
-/*
- * Since we may have triggers on any subsystem, defer registration
- * until after subsystem_init.
- */
-fs_initcall(shark_leds_init);
-#endif
diff --git a/arch/arm/mach-shark/pci.c b/arch/arm/mach-shark/pci.c
deleted file mode 100644
index 6d91a91..0000000
--- a/arch/arm/mach-shark/pci.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *  linux/arch/arm/mach-shark/pci.c
- *
- *  PCI bios-type initialisation for PCI machines
- *
- *  Bits taken from various places.
- */
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <video/vga.h>
-
-#include <asm/irq.h>
-#include <asm/mach/pci.h>
-#include <asm/mach-types.h>
-
-#define IO_START	0x40000000
-
-static int __init shark_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	if (dev->bus->number == 0)
-		if (dev->devfn == 0)
-			return 255;
-		else
-			return 11;
-	else
-		return 255;
-}
-
-extern void __init via82c505_preinit(void);
-
-static struct hw_pci shark_pci __initdata = {
-	.setup		= via82c505_setup,
-	.map_irq	= shark_map_irq,
-	.nr_controllers = 1,
-	.ops		= &via82c505_ops,
-	.preinit	= via82c505_preinit,
-};
-
-static int __init shark_pci_init(void)
-{
-	if (!machine_is_shark())
-		return -ENODEV;
-
-	pcibios_min_io = 0x6000;
-	pcibios_min_mem = 0x50000000;
-	vga_base = 0xe8000000;
-
-	pci_ioremap_io(0, IO_START);
-
-	pci_common_init(&shark_pci);
-
-	return 0;
-}
-
-subsys_initcall(shark_pci_init);
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index 1f94c31..a4a4b75 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -22,16 +22,10 @@
 
 comment "SH-Mobile Board Type"
 
-config MACH_KZM9D_REFERENCE
-	bool "KZM9D board - Reference Device Tree Implementation"
+config MACH_KZM9D
+	bool "KZM9D board"
 	depends on ARCH_EMEV2
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
-	---help---
-	   Use reference implementation of KZM9D board support
-	   which makes a greater use of device tree at the expense
-	   of not supporting a number of devices.
-
-	   This is intended to aid developers
 
 comment "SH-Mobile System Configuration"
 endif
@@ -101,12 +95,24 @@
 	select SH_CLK_CPG
 	select RENESAS_IRQC
 
+config ARCH_R8A7791
+	bool "R-Car M2 (R8A77910)"
+	select ARM_GIC
+	select CPU_V7
+	select SH_CLK_CPG
+
 config ARCH_EMEV2
 	bool "Emma Mobile EV2"
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARM_GIC
 	select CPU_V7
 
+config ARCH_R7S72100
+	bool "RZ/A1H (R7S72100)"
+	select ARM_GIC
+	select CPU_V7
+	select SH_CLK_CPG
+
 comment "SH-Mobile Board Type"
 
 config MACH_APE6EVM
@@ -162,6 +168,8 @@
 	select RENESAS_INTC_IRQPIN
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
 	select USE_OF
+	select SND_SOC_AK4554 if SND_SIMPLE_CARD
+	select SND_SOC_AK4642 if SND_SIMPLE_CARD
 
 config MACH_BOCKW_REFERENCE
 	bool "BOCK-W  - Reference Device Tree Implementation"
@@ -177,6 +185,11 @@
 
 	   This is intended to aid developers
 
+config MACH_GENMAI
+	bool "Genmai board"
+	depends on ARCH_R7S72100
+	select USE_OF
+
 config MACH_MARZEN
 	bool "MARZEN board"
 	depends on ARCH_R8A7779
@@ -213,24 +226,17 @@
 
 	   This is intended to aid developers
 
+config MACH_KOELSCH
+	bool "Koelsch board"
+	depends on ARCH_R8A7791
+	select USE_OF
+
 config MACH_KZM9D
 	bool "KZM9D board"
 	depends on ARCH_EMEV2
 	select REGULATOR_FIXED_VOLTAGE if REGULATOR
 	select USE_OF
 
-config MACH_KZM9D_REFERENCE
-	bool "KZM9D board - Reference Device Tree Implementation"
-	depends on ARCH_EMEV2
-	select REGULATOR_FIXED_VOLTAGE if REGULATOR
-	select USE_OF
-	---help---
-	   Use reference implementation of KZM9D board support
-	   which makes a greater use of device tree at the expense
-	   of not supporting a number of devices.
-
-	   This is intended to aid developers
-
 config MACH_KZM9G
 	bool "KZM-A9-GT board"
 	depends on ARCH_SH73A0
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index 2705bfa..51db2bc 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -15,7 +15,10 @@
 obj-$(CONFIG_ARCH_R8A7778)	+= setup-r8a7778.o
 obj-$(CONFIG_ARCH_R8A7779)	+= setup-r8a7779.o
 obj-$(CONFIG_ARCH_R8A7790)	+= setup-r8a7790.o
+obj-$(CONFIG_ARCH_R8A7790)	+= setup-r8a7790.o setup-rcar-gen2.o
+obj-$(CONFIG_ARCH_R8A7791)	+= setup-r8a7791.o setup-rcar-gen2.o
 obj-$(CONFIG_ARCH_EMEV2)	+= setup-emev2.o
+obj-$(CONFIG_ARCH_R7S72100)	+= setup-r7s72100.o
 
 # Clock objects
 ifndef CONFIG_COMMON_CLK
@@ -27,13 +30,17 @@
 obj-$(CONFIG_ARCH_R8A7778)	+= clock-r8a7778.o
 obj-$(CONFIG_ARCH_R8A7779)	+= clock-r8a7779.o
 obj-$(CONFIG_ARCH_R8A7790)	+= clock-r8a7790.o
+obj-$(CONFIG_ARCH_R8A7791)	+= clock-r8a7791.o
 obj-$(CONFIG_ARCH_EMEV2)	+= clock-emev2.o
+obj-$(CONFIG_ARCH_R7S72100)	+= clock-r7s72100.o
 endif
 
 # SMP objects
 smp-y				:= platsmp.o headsmp.o
 smp-$(CONFIG_ARCH_SH73A0)	+= smp-sh73a0.o headsmp-scu.o platsmp-scu.o
 smp-$(CONFIG_ARCH_R8A7779)	+= smp-r8a7779.o headsmp-scu.o platsmp-scu.o
+smp-$(CONFIG_ARCH_R8A7790)	+= smp-r8a7790.o platsmp-apmu.o
+smp-$(CONFIG_ARCH_R8A7791)	+= smp-r8a7791.o platsmp-apmu.o
 smp-$(CONFIG_ARCH_EMEV2)	+= smp-emev2.o headsmp-scu.o platsmp-scu.o
 
 # IRQ objects
@@ -48,21 +55,26 @@
 obj-$(CONFIG_ARCH_R8A7779)	+= pm-r8a7779.o
 
 # Board objects
+ifdef CONFIG_ARCH_SHMOBILE_MULTI
+obj-$(CONFIG_MACH_KZM9D)	+= board-kzm9d-reference.o
+else
 obj-$(CONFIG_MACH_APE6EVM)	+= board-ape6evm.o
 obj-$(CONFIG_MACH_APE6EVM_REFERENCE)	+= board-ape6evm-reference.o
 obj-$(CONFIG_MACH_MACKEREL)	+= board-mackerel.o
 obj-$(CONFIG_MACH_BOCKW)	+= board-bockw.o
 obj-$(CONFIG_MACH_BOCKW_REFERENCE)	+= board-bockw-reference.o
+obj-$(CONFIG_MACH_GENMAI)	+= board-genmai.o
 obj-$(CONFIG_MACH_MARZEN)	+= board-marzen.o
 obj-$(CONFIG_MACH_MARZEN_REFERENCE)	+= board-marzen-reference.o
 obj-$(CONFIG_MACH_LAGER)	+= board-lager.o
 obj-$(CONFIG_MACH_LAGER_REFERENCE)	+= board-lager-reference.o
 obj-$(CONFIG_MACH_ARMADILLO800EVA)	+= board-armadillo800eva.o
 obj-$(CONFIG_MACH_ARMADILLO800EVA_REFERENCE)	+= board-armadillo800eva-reference.o
+obj-$(CONFIG_MACH_KOELSCH)	+= board-koelsch.o
 obj-$(CONFIG_MACH_KZM9D)	+= board-kzm9d.o
-obj-$(CONFIG_MACH_KZM9D_REFERENCE)	+= board-kzm9d-reference.o
 obj-$(CONFIG_MACH_KZM9G)	+= board-kzm9g.o
 obj-$(CONFIG_MACH_KZM9G_REFERENCE)	+= board-kzm9g-reference.o
+endif
 
 # Framework support
 obj-$(CONFIG_SMP)		+= $(smp-y)
diff --git a/arch/arm/mach-shmobile/Makefile.boot b/arch/arm/mach-shmobile/Makefile.boot
index 6a504fe..391d72a 100644
--- a/arch/arm/mach-shmobile/Makefile.boot
+++ b/arch/arm/mach-shmobile/Makefile.boot
@@ -6,8 +6,9 @@
 loadaddr-$(CONFIG_MACH_ARMADILLO800EVA_REFERENCE) += 0x40008000
 loadaddr-$(CONFIG_MACH_BOCKW) += 0x60008000
 loadaddr-$(CONFIG_MACH_BOCKW_REFERENCE) += 0x60008000
+loadaddr-$(CONFIG_MACH_GENMAI) += 0x8008000
+loadaddr-$(CONFIG_MACH_KOELSCH) += 0x40008000
 loadaddr-$(CONFIG_MACH_KZM9D) += 0x40008000
-loadaddr-$(CONFIG_MACH_KZM9D_REFERENCE) += 0x40008000
 loadaddr-$(CONFIG_MACH_KZM9G) += 0x41008000
 loadaddr-$(CONFIG_MACH_KZM9G_REFERENCE) += 0x41008000
 loadaddr-$(CONFIG_MACH_LAGER) += 0x40008000
diff --git a/arch/arm/mach-shmobile/board-ape6evm-reference.c b/arch/arm/mach-shmobile/board-ape6evm-reference.c
index a23fa71..3276afc 100644
--- a/arch/arm/mach-shmobile/board-ape6evm-reference.c
+++ b/arch/arm/mach-shmobile/board-ape6evm-reference.c
@@ -57,7 +57,7 @@
 };
 
 DT_MACHINE_START(APE6EVM_DT, "ape6evm")
-	.init_early	= r8a73a4_init_delay,
+	.init_early	= r8a73a4_init_early,
 	.init_machine	= ape6evm_add_standard_devices,
 	.dt_compat	= ape6evm_boards_compat_dt,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-ape6evm.c b/arch/arm/mach-shmobile/board-ape6evm.c
index 24b87eea..0fa068e 100644
--- a/arch/arm/mach-shmobile/board-ape6evm.c
+++ b/arch/arm/mach-shmobile/board-ape6evm.c
@@ -86,7 +86,7 @@
 	GPIO_KEY(KEY_VOLUMEDOWN,	329,	"S21"),
 };
 
-static struct __initdata gpio_keys_platform_data ape6evm_keys_pdata = {
+static struct gpio_keys_platform_data ape6evm_keys_pdata __initdata = {
 	.buttons	= gpio_buttons,
 	.nbuttons	= ARRAY_SIZE(gpio_buttons),
 };
@@ -113,22 +113,58 @@
 };
 
 /*
- * On APE6EVM power is supplied to MMCIF by a tps80032 regulator. For now we
- * model a VDD supply to MMCIF, using a fixed 3.3V regulator. Also use the
- * static power supply for SDHI0 and SDHI1, whereas SDHI0's VccQ is also
- * supplied by the same tps80032 regulator and thus can also be adjusted
- * dynamically.
+ * MMC0 power supplies:
+ * Both Vcc and VccQ to eMMC on APE6EVM are supplied by a tps80032 voltage
+ * regulator. Until support for it is added to this file we simulate the
+ * Vcc supply by a fixed always-on regulator
  */
-static struct regulator_consumer_supply fixed3v3_power_consumers[] =
+static struct regulator_consumer_supply vcc_mmc0_consumers[] =
 {
 	REGULATOR_SUPPLY("vmmc", "sh_mmcif.0"),
+};
+
+/*
+ * SDHI0 power supplies:
+ * Vcc to SDHI0 on APE6EVM is supplied by a GPIO-switchable regulator. VccQ is
+ * provided by the same tps80032 regulator as both MMC0 voltages - see comment
+ * above
+ */
+static struct regulator_consumer_supply vcc_sdhi0_consumers[] =
+{
 	REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
+};
+
+static struct regulator_init_data vcc_sdhi0_init_data = {
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies  = ARRAY_SIZE(vcc_sdhi0_consumers),
+	.consumer_supplies      = vcc_sdhi0_consumers,
+};
+
+static const struct fixed_voltage_config vcc_sdhi0_info __initconst = {
+	.supply_name = "SDHI0 Vcc",
+	.microvolts = 3300000,
+	.gpio = 76,
+	.enable_high = 1,
+	.init_data = &vcc_sdhi0_init_data,
+};
+
+/*
+ * SDHI1 power supplies:
+ * Vcc and VccQ to SDHI1 on APE6EVM are both fixed at 3.3V
+ */
+static struct regulator_consumer_supply vcc_sdhi1_consumers[] =
+{
 	REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.1"),
 };
 
 /* MMCIF */
 static const struct sh_mmcif_plat_data mmcif0_pdata __initconst = {
 	.caps		= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
+	.slave_id_tx	= SHDMA_SLAVE_MMCIF0_TX,
+	.slave_id_rx	= SHDMA_SLAVE_MMCIF0_RX,
+	.ccs_unsupported = true,
 };
 
 static const struct resource mmcif0_resources[] __initconst = {
@@ -215,14 +251,19 @@
 	platform_device_register_resndata(&platform_bus, "smsc911x", -1,
 					  lan9220_res, ARRAY_SIZE(lan9220_res),
 					  &lan9220_data, sizeof(lan9220_data));
-	regulator_register_always_on(1, "fixed-3.3V", fixed3v3_power_consumers,
-				     ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
+
+	regulator_register_always_on(1, "MMC0 Vcc", vcc_mmc0_consumers,
+				     ARRAY_SIZE(vcc_mmc0_consumers), 2800000);
 	platform_device_register_resndata(&platform_bus, "sh_mmcif", 0,
 					  mmcif0_resources, ARRAY_SIZE(mmcif0_resources),
 					  &mmcif0_pdata, sizeof(mmcif0_pdata));
+	platform_device_register_data(&platform_bus, "reg-fixed-voltage", 2,
+				      &vcc_sdhi0_info, sizeof(vcc_sdhi0_info));
 	platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 0,
 					  sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
 					  &sdhi0_pdata, sizeof(sdhi0_pdata));
+	regulator_register_always_on(3, "SDHI1 Vcc", vcc_sdhi1_consumers,
+				     ARRAY_SIZE(vcc_sdhi1_consumers), 3300000);
 	platform_device_register_resndata(&platform_bus, "sh_mobile_sdhi", 1,
 					  sdhi1_resources, ARRAY_SIZE(sdhi1_resources),
 					  &sdhi1_pdata, sizeof(sdhi1_pdata));
@@ -240,7 +281,7 @@
 };
 
 DT_MACHINE_START(APE6EVM_DT, "ape6evm")
-	.init_early	= r8a73a4_init_delay,
+	.init_early	= r8a73a4_init_early,
 	.init_machine	= ape6evm_add_standard_devices,
 	.dt_compat	= ape6evm_boards_compat_dt,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
index 7f8f607..8bc8e4c 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -823,6 +823,7 @@
 	.caps		= MMC_CAP_4_BIT_DATA |
 			  MMC_CAP_8_BIT_DATA |
 			  MMC_CAP_NONREMOVABLE,
+	.ccs_unsupported = true,
 	.slave_id_tx	= SHDMA_SLAVE_MMCIF_TX,
 	.slave_id_rx	= SHDMA_SLAVE_MMCIF_RX,
 };
diff --git a/arch/arm/mach-shmobile/board-bockw-reference.c b/arch/arm/mach-shmobile/board-bockw-reference.c
index 1a7c893..ae88fda 100644
--- a/arch/arm/mach-shmobile/board-bockw-reference.c
+++ b/arch/arm/mach-shmobile/board-bockw-reference.c
@@ -36,15 +36,35 @@
 				  "scif0_ctrl", "scif0"),
 };
 
+#define FPGA	0x18200000
+#define IRQ0MR	0x30
+#define COMCTLR	0x101c
 static void __init bockw_init(void)
 {
+	static void __iomem *fpga;
+
 	r8a7778_clock_init();
+	r8a7778_init_irq_extpin_dt(1);
 
 	pinctrl_register_mappings(bockw_pinctrl_map,
 				  ARRAY_SIZE(bockw_pinctrl_map));
 	r8a7778_pinmux_init();
 	r8a7778_add_dt_devices();
 
+	fpga = ioremap_nocache(FPGA, SZ_1M);
+	if (fpga) {
+		/*
+		 * CAUTION
+		 *
+		 * IRQ0/1 is cascaded interrupt from FPGA.
+		 * it should be cared in the future
+		 * Now, it is assuming IRQ0 was used only from SMSC.
+		 */
+		u16 val = ioread16(fpga + IRQ0MR);
+		val &= ~(1 << 4); /* enable SMSC911x */
+		iowrite16(val, fpga + IRQ0MR);
+	}
+
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c
index 6b9faf3..3861152 100644
--- a/arch/arm/mach-shmobile/board-bockw.c
+++ b/arch/arm/mach-shmobile/board-bockw.c
@@ -32,11 +32,19 @@
 #include <linux/smsc911x.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
+#include <linux/usb/renesas_usbhs.h>
 #include <media/soc_camera.h>
 #include <mach/common.h>
 #include <mach/irqs.h>
 #include <mach/r8a7778.h>
 #include <asm/mach/arch.h>
+#include <sound/rcar_snd.h>
+#include <sound/simple_card.h>
+
+#define FPGA	0x18200000
+#define IRQ0MR	0x30
+#define COMCTLR	0x101c
+static void __iomem *fpga;
 
 /*
  *	CN9(Upper side) SCIF/RCAN selection
@@ -63,6 +71,45 @@
  * SW19	(MMC)	1 pin
  */
 
+/*
+ *	SSI settings
+ *
+ * SW45: 1-4 side	(SSI5 out, ROUT/LOUT CN19 Mid)
+ * SW46: 1101		(SSI6 Recorde)
+ * SW47: 1110		(SSI5 Playback)
+ * SW48: 11		(Recorde power)
+ * SW49: 1		(SSI slave mode)
+ * SW50: 1111		(SSI7, SSI8)
+ * SW51: 1111		(SSI3, SSI4)
+ * SW54: 1pin		(ak4554 FPGA control)
+ * SW55: 1		(CLKB is 24.5760MHz)
+ * SW60: 1pin		(ak4554 FPGA control)
+ * SW61: 3pin		(use X11 clock)
+ * SW78: 3-6		(ak4642 connects I2C0)
+ *
+ * You can use sound as
+ *
+ * hw0: CN19: SSI56-AK4643
+ * hw1: CN21: SSI3-AK4554(playback)
+ * hw2: CN21: SSI4-AK4554(capture)
+ * hw3: CN20: SSI7-AK4554(playback)
+ * hw4: CN20: SSI8-AK4554(capture)
+ *
+ * this command is required when playback on hw0.
+ *
+ * # amixer set "LINEOUT Mixer DACL" on
+ */
+
+/*
+ * USB
+ *
+ * USB1 (CN29) can be Host/Function
+ *
+ *		Host	Func
+ * SW98		1	2
+ * SW99		1	3
+ */
+
 /* Dummy supplies, where voltage doesn't matter */
 static struct regulator_consumer_supply dummy_supplies[] = {
 	REGULATOR_SUPPLY("vddvario", "smsc911x"),
@@ -81,16 +128,76 @@
 	DEFINE_RES_IRQ(irq_pin(0)), /* IRQ 0 */
 };
 
+#if IS_ENABLED(CONFIG_USB_RENESAS_USBHS_UDC)
+/*
+ * When USB1 is Func
+ */
+static int usbhsf_get_id(struct platform_device *pdev)
+{
+	return USBHS_GADGET;
+}
+
+#define SUSPMODE	0x102
+static int usbhsf_power_ctrl(struct platform_device *pdev,
+			     void __iomem *base, int enable)
+{
+	enable = !!enable;
+
+	r8a7778_usb_phy_power(enable);
+
+	iowrite16(enable << 14, base + SUSPMODE);
+
+	return 0;
+}
+
+static struct resource usbhsf_resources[] __initdata = {
+	DEFINE_RES_MEM(0xffe60000, 0x110),
+	DEFINE_RES_IRQ(gic_iid(0x4f)),
+};
+
+static struct renesas_usbhs_platform_info usbhs_info __initdata = {
+	.platform_callback = {
+		.get_id		= usbhsf_get_id,
+		.power_ctrl	= usbhsf_power_ctrl,
+	},
+	.driver_param = {
+		.buswait_bwait	= 4,
+	},
+};
+
+#define USB_PHY_SETTING {.port1_func = 1, .ovc_pin[1].active_high = 1,}
+#define USB1_DEVICE	"renesas_usbhs"
+#define ADD_USB_FUNC_DEVICE_IF_POSSIBLE()			\
+	platform_device_register_resndata(			\
+		&platform_bus, "renesas_usbhs", -1,		\
+		usbhsf_resources,				\
+		ARRAY_SIZE(usbhsf_resources),			\
+		&usbhs_info, sizeof(struct renesas_usbhs_platform_info))
+
+#else
+/*
+ * When USB1 is Host
+ */
+#define USB_PHY_SETTING { }
+#define USB1_DEVICE	"ehci-platform"
+#define ADD_USB_FUNC_DEVICE_IF_POSSIBLE()
+
+#endif
+
 /* USB */
 static struct resource usb_phy_resources[] __initdata = {
 	DEFINE_RES_MEM(0xffe70800, 0x100),
 	DEFINE_RES_MEM(0xffe76000, 0x100),
 };
 
-static struct rcar_phy_platform_data usb_phy_platform_data __initdata;
+static struct rcar_phy_platform_data usb_phy_platform_data __initdata =
+	USB_PHY_SETTING;
+
 
 /* SDHI */
 static struct sh_mobile_sdhi_info sdhi0_info __initdata = {
+	.dma_slave_tx	= HPBDMA_SLAVE_SDHI0_TX,
+	.dma_slave_rx	= HPBDMA_SLAVE_SDHI0_RX,
 	.tmio_caps	= MMC_CAP_SD_HIGHSPEED,
 	.tmio_ocr_mask	= MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
 	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT,
@@ -101,6 +208,12 @@
 	DEFINE_RES_IRQ(gic_iid(0x77)),
 };
 
+/* Ether */
+static struct resource ether_resources[] __initdata = {
+	DEFINE_RES_MEM(0xfde00000, 0x400),
+	DEFINE_RES_IRQ(gic_iid(0x89)),
+};
+
 static struct sh_eth_plat_data ether_platform_data __initdata = {
 	.phy		= 0x01,
 	.edmac_endian	= EDMAC_LITTLE_ENDIAN,
@@ -118,7 +231,9 @@
 static struct i2c_board_info i2c0_devices[] = {
 	{
 		I2C_BOARD_INFO("rx8581", 0x51),
-	},
+	}, {
+		I2C_BOARD_INFO("ak4643", 0x12),
+	}
 };
 
 /* HSPI*/
@@ -162,10 +277,6 @@
 			  MMC_CAP_NEEDS_POLL,
 };
 
-static struct rcar_vin_platform_data vin_platform_data __initdata = {
-	.flags	= RCAR_VIN_BT656,
-};
-
 /* In the default configuration both decoders reside on I2C bus 0 */
 #define BOCKW_CAMERA(idx)						\
 static struct i2c_board_info camera##idx##_info = {			\
@@ -181,7 +292,237 @@
 BOCKW_CAMERA(0);
 BOCKW_CAMERA(1);
 
+/* VIN */
+static struct rcar_vin_platform_data vin_platform_data __initdata = {
+	.flags	= RCAR_VIN_BT656,
+};
+
+#define R8A7778_VIN(idx)						\
+static struct resource vin##idx##_resources[] __initdata = {		\
+	DEFINE_RES_MEM(0xffc50000 + 0x1000 * (idx), 0x1000),		\
+	DEFINE_RES_IRQ(gic_iid(0x5a)),					\
+};									\
+									\
+static struct platform_device_info vin##idx##_info __initdata = {	\
+	.parent		= &platform_bus,				\
+	.name		= "r8a7778-vin",				\
+	.id		= idx,						\
+	.res		= vin##idx##_resources,				\
+	.num_res	= ARRAY_SIZE(vin##idx##_resources),		\
+	.dma_mask	= DMA_BIT_MASK(32),				\
+	.data		= &vin_platform_data,				\
+	.size_data	= sizeof(vin_platform_data),			\
+}
+R8A7778_VIN(0);
+R8A7778_VIN(1);
+
+/* Sound */
+static struct resource rsnd_resources[] __initdata = {
+	[RSND_GEN1_SRU] = DEFINE_RES_MEM(0xffd90000, 0x1000),
+	[RSND_GEN1_SSI] = DEFINE_RES_MEM(0xffd91000, 0x1240),
+	[RSND_GEN1_ADG] = DEFINE_RES_MEM(0xfffe0000, 0x24),
+};
+
+static struct rsnd_ssi_platform_info rsnd_ssi[] = {
+	RSND_SSI_UNUSED, /* SSI 0 */
+	RSND_SSI_UNUSED, /* SSI 1 */
+	RSND_SSI_UNUSED, /* SSI 2 */
+	RSND_SSI_SET(1, 0, gic_iid(0x85), RSND_SSI_PLAY),
+	RSND_SSI_SET(2, 0, gic_iid(0x85), RSND_SSI_CLK_PIN_SHARE | RSND_SSI_CLK_FROM_ADG),
+	RSND_SSI_SET(0, 0, gic_iid(0x86), RSND_SSI_PLAY),
+	RSND_SSI_SET(0, 0, gic_iid(0x86), 0),
+	RSND_SSI_SET(3, 0, gic_iid(0x86), RSND_SSI_PLAY),
+	RSND_SSI_SET(4, 0, gic_iid(0x86), RSND_SSI_CLK_PIN_SHARE | RSND_SSI_CLK_FROM_ADG),
+};
+
+static struct rsnd_scu_platform_info rsnd_scu[9] = {
+	/* no member at this point */
+};
+
+enum {
+	AK4554_34 = 0,
+	AK4643_56,
+	AK4554_78,
+	SOUND_MAX,
+};
+
+static int rsnd_codec_power(int id, int enable)
+{
+	static int sound_user[SOUND_MAX] = {0, 0, 0};
+	int *usr = NULL;
+	u32 bit;
+
+	switch (id) {
+	case 3:
+	case 4:
+		usr = sound_user + AK4554_34;
+		bit = (1 << 10);
+		break;
+	case 5:
+	case 6:
+		usr = sound_user + AK4643_56;
+		bit = (1 << 6);
+		break;
+	case 7:
+	case 8:
+		usr = sound_user + AK4554_78;
+		bit = (1 << 7);
+		break;
+	}
+
+	if (!usr)
+		return -EIO;
+
+	if (enable) {
+		if (*usr == 0) {
+			u32 val = ioread16(fpga + COMCTLR);
+			val &= ~bit;
+			iowrite16(val, fpga + COMCTLR);
+		}
+
+		(*usr)++;
+	} else {
+		if (*usr == 0)
+			return 0;
+
+		(*usr)--;
+
+		if (*usr == 0) {
+			u32 val = ioread16(fpga + COMCTLR);
+			val |= bit;
+			iowrite16(val, fpga + COMCTLR);
+		}
+	}
+
+	return 0;
+}
+
+static int rsnd_start(int id)
+{
+	return rsnd_codec_power(id, 1);
+}
+
+static int rsnd_stop(int id)
+{
+	return rsnd_codec_power(id, 0);
+}
+
+static struct rcar_snd_info rsnd_info = {
+	.flags		= RSND_GEN1,
+	.ssi_info	= rsnd_ssi,
+	.ssi_info_nr	= ARRAY_SIZE(rsnd_ssi),
+	.scu_info	= rsnd_scu,
+	.scu_info_nr	= ARRAY_SIZE(rsnd_scu),
+	.start		= rsnd_start,
+	.stop		= rsnd_stop,
+};
+
+static struct asoc_simple_card_info rsnd_card_info[] = {
+	/* SSI5, SSI6 */
+	{
+		.name		= "AK4643",
+		.card		= "SSI56-AK4643",
+		.codec		= "ak4642-codec.0-0012",
+		.platform	= "rcar_sound",
+		.daifmt		= SND_SOC_DAIFMT_LEFT_J,
+		.cpu_dai = {
+			.name	= "rsnd-dai.0",
+			.fmt	= SND_SOC_DAIFMT_CBS_CFS,
+		},
+		.codec_dai = {
+			.name	= "ak4642-hifi",
+			.fmt	= SND_SOC_DAIFMT_CBM_CFM,
+			.sysclk	= 11289600,
+		},
+	},
+	/* SSI3 */
+	{
+		.name		= "AK4554",
+		.card		= "SSI3-AK4554(playback)",
+		.codec		= "ak4554-adc-dac.0",
+		.platform	= "rcar_sound",
+		.cpu_dai = {
+			.name	= "rsnd-dai.1",
+			.fmt	= SND_SOC_DAIFMT_CBM_CFM |
+				  SND_SOC_DAIFMT_RIGHT_J,
+		},
+		.codec_dai = {
+			.name	= "ak4554-hifi",
+		},
+	},
+	/* SSI4 */
+	{
+		.name		= "AK4554",
+		.card		= "SSI4-AK4554(capture)",
+		.codec		= "ak4554-adc-dac.0",
+		.platform	= "rcar_sound",
+		.cpu_dai = {
+			.name	= "rsnd-dai.2",
+			.fmt	= SND_SOC_DAIFMT_CBM_CFM |
+				  SND_SOC_DAIFMT_LEFT_J,
+		},
+		.codec_dai = {
+			.name	= "ak4554-hifi",
+		},
+	},
+	/* SSI7 */
+	{
+		.name		= "AK4554",
+		.card		= "SSI7-AK4554(playback)",
+		.codec		= "ak4554-adc-dac.1",
+		.platform	= "rcar_sound",
+		.cpu_dai = {
+			.name	= "rsnd-dai.3",
+			.fmt	= SND_SOC_DAIFMT_CBM_CFM |
+				  SND_SOC_DAIFMT_RIGHT_J,
+		},
+		.codec_dai = {
+			.name	= "ak4554-hifi",
+		},
+	},
+	/* SSI8 */
+	{
+		.name		= "AK4554",
+		.card		= "SSI8-AK4554(capture)",
+		.codec		= "ak4554-adc-dac.1",
+		.platform	= "rcar_sound",
+		.cpu_dai = {
+			.name	= "rsnd-dai.4",
+			.fmt	= SND_SOC_DAIFMT_CBM_CFM |
+				  SND_SOC_DAIFMT_LEFT_J,
+		},
+		.codec_dai = {
+			.name	= "ak4554-hifi",
+		},
+	}
+};
+
 static const struct pinctrl_map bockw_pinctrl_map[] = {
+	/* AUDIO */
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+				  "audio_clk_a", "audio_clk"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+				  "audio_clk_b", "audio_clk"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+				  "ssi34_ctrl", "ssi"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+				  "ssi3_data", "ssi"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+				  "ssi4_data", "ssi"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+				  "ssi5_ctrl", "ssi"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+				  "ssi5_data", "ssi"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+				  "ssi6_ctrl", "ssi"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+				  "ssi6_data", "ssi"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+				  "ssi78_ctrl", "ssi"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+				  "ssi7_data", "ssi"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7778",
+				  "ssi8_data", "ssi"),
 	/* Ether */
 	PIN_MAP_MUX_GROUP_DEFAULT("r8a777x-ether", "pfc-r8a7778",
 				  "ether_rmii", "ether"),
@@ -201,7 +542,7 @@
 	/* USB */
 	PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform", "pfc-r8a7778",
 				  "usb0", "usb0"),
-	PIN_MAP_MUX_GROUP_DEFAULT("ehci-platform", "pfc-r8a7778",
+	PIN_MAP_MUX_GROUP_DEFAULT(USB1_DEVICE, "pfc-r8a7778",
 				  "usb1", "usb1"),
 	/* SDHI0 */
 	PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778",
@@ -224,22 +565,28 @@
 				  "vin1_data8", "vin1"),
 };
 
-#define FPGA	0x18200000
-#define IRQ0MR	0x30
 #define PFC	0xfffc0000
 #define PUPR4	0x110
 static void __init bockw_init(void)
 {
 	void __iomem *base;
+	struct clk *clk;
+	int i;
 
 	r8a7778_clock_init();
 	r8a7778_init_irq_extpin(1);
 	r8a7778_add_standard_devices();
-	r8a7778_add_ether_device(&ether_platform_data);
-	r8a7778_add_vin_device(0, &vin_platform_data);
+
+	platform_device_register_resndata(&platform_bus, "r8a777x-ether", -1,
+					  ether_resources,
+					  ARRAY_SIZE(ether_resources),
+					  &ether_platform_data,
+					  sizeof(ether_platform_data));
+
+	platform_device_register_full(&vin0_info);
 	/* VIN1 has a pin conflict with Ether */
 	if (!IS_ENABLED(CONFIG_SH_ETH))
-		r8a7778_add_vin_device(1, &vin_platform_data);
+		platform_device_register_full(&vin1_info);
 	platform_device_register_data(&platform_bus, "soc-camera-pdrv", 0,
 				      &iclink0_ml86v7667,
 				      sizeof(iclink0_ml86v7667));
@@ -269,8 +616,8 @@
 
 
 	/* for SMSC */
-	base = ioremap_nocache(FPGA, SZ_1M);
-	if (base) {
+	fpga = ioremap_nocache(FPGA, SZ_1M);
+	if (fpga) {
 		/*
 		 * CAUTION
 		 *
@@ -278,10 +625,9 @@
 		 * it should be cared in the future
 		 * Now, it is assuming IRQ0 was used only from SMSC.
 		 */
-		u16 val = ioread16(base + IRQ0MR);
+		u16 val = ioread16(fpga + IRQ0MR);
 		val &= ~(1 << 4); /* enable SMSC911x */
-		iowrite16(val, base + IRQ0MR);
-		iounmap(base);
+		iowrite16(val, fpga + IRQ0MR);
 
 		regulator_register_fixed(0, dummy_supplies,
 					 ARRAY_SIZE(dummy_supplies));
@@ -308,6 +654,42 @@
 			sdhi0_resources, ARRAY_SIZE(sdhi0_resources),
 			&sdhi0_info, sizeof(struct sh_mobile_sdhi_info));
 	}
+
+	/* for Audio */
+	clk = clk_get(NULL, "audio_clk_b");
+	clk_set_rate(clk, 24576000);
+	clk_put(clk);
+	rsnd_codec_power(5, 1); /* enable ak4642 */
+
+	platform_device_register_simple(
+		"ak4554-adc-dac", 0, NULL, 0);
+
+	platform_device_register_simple(
+		"ak4554-adc-dac", 1, NULL, 0);
+
+	platform_device_register_resndata(
+		&platform_bus, "rcar_sound", -1,
+		rsnd_resources, ARRAY_SIZE(rsnd_resources),
+		&rsnd_info, sizeof(rsnd_info));
+
+	for (i = 0; i < ARRAY_SIZE(rsnd_card_info); i++) {
+		struct platform_device_info cardinfo = {
+			.parent         = &platform_bus,
+			.name           = "asoc-simple-card",
+			.id             = i,
+			.data           = &rsnd_card_info[i],
+			.size_data      = sizeof(struct asoc_simple_card_info),
+			.dma_mask       = ~0,
+		};
+
+		platform_device_register_full(&cardinfo);
+	}
+}
+
+static void __init bockw_init_late(void)
+{
+	r8a7778_init_late();
+	ADD_USB_FUNC_DEVICE_IF_POSSIBLE();
 }
 
 static const char *bockw_boards_compat_dt[] __initdata = {
@@ -320,5 +702,5 @@
 	.init_irq	= r8a7778_init_irq_dt,
 	.init_machine	= bockw_init,
 	.dt_compat	= bockw_boards_compat_dt,
-	.init_late      = r8a7778_init_late,
+	.init_late      = bockw_init_late,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-genmai.c b/arch/arm/mach-shmobile/board-genmai.c
new file mode 100644
index 0000000..3e92e3c
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-genmai.c
@@ -0,0 +1,43 @@
+/*
+ * Genmai board support
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <mach/common.h>
+#include <mach/r7s72100.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static void __init genmai_add_standard_devices(void)
+{
+	r7s72100_clock_init();
+	r7s72100_add_dt_devices();
+}
+
+static const char * const genmai_boards_compat_dt[] __initconst = {
+	"renesas,genmai",
+	NULL,
+};
+
+DT_MACHINE_START(GENMAI_DT, "genmai")
+	.init_early	= r7s72100_init_early,
+	.init_machine	= genmai_add_standard_devices,
+	.dt_compat	= genmai_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-koelsch.c b/arch/arm/mach-shmobile/board-koelsch.c
new file mode 100644
index 0000000..ace1711
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-koelsch.c
@@ -0,0 +1,47 @@
+/*
+ * Koelsch board support
+ *
+ * Copyright (C) 2013  Renesas Electronics Corporation
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <mach/common.h>
+#include <mach/r8a7791.h>
+#include <mach/rcar-gen2.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+static void __init koelsch_add_standard_devices(void)
+{
+	r8a7791_clock_init();
+	r8a7791_add_standard_devices();
+}
+
+static const char * const koelsch_boards_compat_dt[] __initconst = {
+	"renesas,koelsch",
+	NULL,
+};
+
+DT_MACHINE_START(KOELSCH_DT, "koelsch")
+	.smp		= smp_ops(r8a7791_smp_ops),
+	.init_early	= r8a7791_init_early,
+	.init_machine	= koelsch_add_standard_devices,
+	.init_time	= rcar_gen2_timer_init,
+	.dt_compat	= koelsch_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-kzm9d-reference.c b/arch/arm/mach-shmobile/board-kzm9d-reference.c
index 8f8bb2f..054d8d5 100644
--- a/arch/arm/mach-shmobile/board-kzm9d-reference.c
+++ b/arch/arm/mach-shmobile/board-kzm9d-reference.c
@@ -33,6 +33,7 @@
 }
 
 static const char *kzm9d_boards_compat_dt[] __initdata = {
+	"renesas,kzm9d",
 	"renesas,kzm9d-reference",
 	NULL,
 };
diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
index f199496..fe689b7 100644
--- a/arch/arm/mach-shmobile/board-kzm9g.c
+++ b/arch/arm/mach-shmobile/board-kzm9g.c
@@ -366,6 +366,7 @@
 static struct sh_mmcif_plat_data sh_mmcif_platdata = {
 	.ocr		= MMC_VDD_165_195,
 	.caps		= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
+	.ccs_unsupported = true,
 	.slave_id_tx	= SHDMA_SLAVE_MMCIF_TX,
 	.slave_id_rx	= SHDMA_SLAVE_MMCIF_RX,
 };
diff --git a/arch/arm/mach-shmobile/board-lager-reference.c b/arch/arm/mach-shmobile/board-lager-reference.c
index 9c316a1..1a1a4a8 100644
--- a/arch/arm/mach-shmobile/board-lager-reference.c
+++ b/arch/arm/mach-shmobile/board-lager-reference.c
@@ -38,8 +38,9 @@
 };
 
 DT_MACHINE_START(LAGER_DT, "lager")
-	.init_early	= r8a7790_init_delay,
+	.smp		= smp_ops(r8a7790_smp_ops),
+	.init_early	= r8a7790_init_early,
+	.init_time	= rcar_gen2_timer_init,
 	.init_machine	= lager_add_standard_devices,
-	.init_time	= r8a7790_timer_init,
 	.dt_compat	= lager_boards_compat_dt,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c
index 5930af8..a8d3ce6 100644
--- a/arch/arm/mach-shmobile/board-lager.c
+++ b/arch/arm/mach-shmobile/board-lager.c
@@ -28,6 +28,7 @@
 #include <linux/mmc/sh_mmcif.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_data/gpio-rcar.h>
+#include <linux/platform_data/rcar-du.h>
 #include <linux/platform_device.h>
 #include <linux/phy.h>
 #include <linux/regulator/fixed.h>
@@ -39,6 +40,62 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+/* DU */
+static struct rcar_du_encoder_data lager_du_encoders[] = {
+	{
+		.type = RCAR_DU_ENCODER_VGA,
+		.output = RCAR_DU_OUTPUT_DPAD0,
+	}, {
+		.type = RCAR_DU_ENCODER_NONE,
+		.output = RCAR_DU_OUTPUT_LVDS1,
+		.connector.lvds.panel = {
+			.width_mm = 210,
+			.height_mm = 158,
+			.mode = {
+				.clock = 65000,
+				.hdisplay = 1024,
+				.hsync_start = 1048,
+				.hsync_end = 1184,
+				.htotal = 1344,
+				.vdisplay = 768,
+				.vsync_start = 771,
+				.vsync_end = 777,
+				.vtotal = 806,
+				.flags = 0,
+			},
+		},
+	},
+};
+
+static const struct rcar_du_platform_data lager_du_pdata __initconst = {
+	.encoders = lager_du_encoders,
+	.num_encoders = ARRAY_SIZE(lager_du_encoders),
+};
+
+static const struct resource du_resources[] __initconst = {
+	DEFINE_RES_MEM(0xfeb00000, 0x70000),
+	DEFINE_RES_MEM_NAMED(0xfeb90000, 0x1c, "lvds.0"),
+	DEFINE_RES_MEM_NAMED(0xfeb94000, 0x1c, "lvds.1"),
+	DEFINE_RES_IRQ(gic_spi(256)),
+	DEFINE_RES_IRQ(gic_spi(268)),
+	DEFINE_RES_IRQ(gic_spi(269)),
+};
+
+static void __init lager_add_du_device(void)
+{
+	struct platform_device_info info = {
+		.name = "rcar-du-r8a7790",
+		.id = -1,
+		.res = du_resources,
+		.num_res = ARRAY_SIZE(du_resources),
+		.data = &lager_du_pdata,
+		.size_data = sizeof(lager_du_pdata),
+		.dma_mask = DMA_BIT_MASK(32),
+	};
+
+	platform_device_register_full(&info);
+}
+
 /* LEDS */
 static struct gpio_led lager_leds[] = {
 	{
@@ -56,7 +113,7 @@
 	},
 };
 
-static __initdata struct gpio_led_platform_data lager_leds_pdata = {
+static const struct gpio_led_platform_data lager_leds_pdata __initconst = {
 	.leds		= lager_leds,
 	.num_leds	= ARRAY_SIZE(lager_leds),
 };
@@ -72,7 +129,7 @@
 	GPIO_KEY(KEY_1,		RCAR_GP_PIN(1, 14),	"SW2-pin1"),
 };
 
-static __initdata struct gpio_keys_platform_data lager_keys_pdata = {
+static const struct gpio_keys_platform_data lager_keys_pdata __initconst = {
 	.buttons	= gpio_buttons,
 	.nbuttons	= ARRAY_SIZE(gpio_buttons),
 };
@@ -84,29 +141,38 @@
 };
 
 /* MMCIF */
-static struct sh_mmcif_plat_data mmcif1_pdata __initdata = {
+static const struct sh_mmcif_plat_data mmcif1_pdata __initconst = {
 	.caps		= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
+	.clk_ctrl2_present = true,
+	.ccs_unsupported = true,
 };
 
-static struct resource mmcif1_resources[] __initdata = {
+static const struct resource mmcif1_resources[] __initconst = {
 	DEFINE_RES_MEM_NAMED(0xee220000, 0x80, "MMCIF1"),
 	DEFINE_RES_IRQ(gic_spi(170)),
 };
 
 /* Ether */
-static struct sh_eth_plat_data ether_pdata __initdata = {
+static const struct sh_eth_plat_data ether_pdata __initconst = {
 	.phy			= 0x1,
 	.edmac_endian		= EDMAC_LITTLE_ENDIAN,
 	.phy_interface		= PHY_INTERFACE_MODE_RMII,
 	.ether_link_active_low	= 1,
 };
 
-static struct resource ether_resources[] __initdata = {
+static const struct resource ether_resources[] __initconst = {
 	DEFINE_RES_MEM(0xee700000, 0x400),
 	DEFINE_RES_IRQ(gic_spi(162)),
 };
 
 static const struct pinctrl_map lager_pinctrl_map[] = {
+	/* DU (CN10: ARGB0, CN13: LVDS) */
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7790", "pfc-r8a7790",
+				  "du_rgb666", "du"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7790", "pfc-r8a7790",
+				  "du_sync_1", "du"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7790", "pfc-r8a7790",
+				  "du_clk_out_0", "du"),
 	/* SCIF0 (CN19: DEBUG SERIAL0) */
 	PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.6", "pfc-r8a7790",
 				  "scif0_data", "scif0"),
@@ -154,6 +220,8 @@
 					  ether_resources,
 					  ARRAY_SIZE(ether_resources),
 					  &ether_pdata, sizeof(ether_pdata));
+
+	lager_add_du_device();
 }
 
 /*
@@ -180,14 +248,15 @@
 	phy_register_fixup_for_id("r8a7790-ether-ff:01", lager_ksz8041_fixup);
 }
 
-static const char *lager_boards_compat_dt[] __initdata = {
+static const char * const lager_boards_compat_dt[] __initconst = {
 	"renesas,lager",
 	NULL,
 };
 
 DT_MACHINE_START(LAGER_DT, "lager")
-	.init_early	= r8a7790_init_delay,
-	.init_time	= r8a7790_timer_init,
+	.smp		= smp_ops(r8a7790_smp_ops),
+	.init_early	= r8a7790_init_early,
+	.init_time	= rcar_gen2_timer_init,
 	.init_machine	= lager_init,
 	.dt_compat	= lager_boards_compat_dt,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-marzen-reference.c b/arch/arm/mach-shmobile/board-marzen-reference.c
index 3f4250a..2773936 100644
--- a/arch/arm/mach-shmobile/board-marzen-reference.c
+++ b/arch/arm/mach-shmobile/board-marzen-reference.c
@@ -28,6 +28,7 @@
 static void __init marzen_init(void)
 {
 	r8a7779_add_standard_devices_dt();
+	r8a7779_init_irq_extpin_dt(1); /* IRQ1 as individual interrupt */
 }
 
 static const char *marzen_boards_compat_dt[] __initdata = {
diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c
index 3f5044f..da1352f 100644
--- a/arch/arm/mach-shmobile/board-marzen.c
+++ b/arch/arm/mach-shmobile/board-marzen.c
@@ -30,6 +30,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_data/gpio-rcar.h>
+#include <linux/platform_data/rcar-du.h>
 #include <linux/platform_data/usb-rcar-phy.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
@@ -124,6 +125,8 @@
 };
 
 static struct sh_mobile_sdhi_info sdhi0_platform_data = {
+	.dma_slave_tx = HPBDMA_SLAVE_SDHI0_TX,
+	.dma_slave_rx = HPBDMA_SLAVE_SDHI0_RX,
 	.tmio_flags = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
 	.tmio_caps = MMC_CAP_SD_HIGHSPEED,
 };
@@ -169,6 +172,63 @@
 	.num_resources	= ARRAY_SIZE(hspi_resources),
 };
 
+/*
+ * DU
+ *
+ * The panel only specifies the [hv]display and [hv]total values. The position
+ * and width of the sync pulses don't matter, they're copied from VESA timings.
+ */
+static struct rcar_du_encoder_data du_encoders[] = {
+	{
+		.type = RCAR_DU_ENCODER_VGA,
+		.output = RCAR_DU_OUTPUT_DPAD0,
+	}, {
+		.type = RCAR_DU_ENCODER_LVDS,
+		.output = RCAR_DU_OUTPUT_DPAD1,
+		.connector.lvds.panel = {
+			.width_mm = 210,
+			.height_mm = 158,
+			.mode = {
+				.clock = 65000,
+				.hdisplay = 1024,
+				.hsync_start = 1048,
+				.hsync_end = 1184,
+				.htotal = 1344,
+				.vdisplay = 768,
+				.vsync_start = 771,
+				.vsync_end = 777,
+				.vtotal = 806,
+				.flags = 0,
+			},
+		},
+	},
+};
+
+static const struct rcar_du_platform_data du_pdata __initconst = {
+	.encoders = du_encoders,
+	.num_encoders = ARRAY_SIZE(du_encoders),
+};
+
+static const struct resource du_resources[] __initconst = {
+	DEFINE_RES_MEM(0xfff80000, 0x40000),
+	DEFINE_RES_IRQ(gic_iid(0x3f)),
+};
+
+static void __init marzen_add_du_device(void)
+{
+	struct platform_device_info info = {
+		.name = "rcar-du-r8a7779",
+		.id = -1,
+		.res = du_resources,
+		.num_res = ARRAY_SIZE(du_resources),
+		.data = &du_pdata,
+		.size_data = sizeof(du_pdata),
+		.dma_mask = DMA_BIT_MASK(32),
+	};
+
+	platform_device_register_full(&info);
+}
+
 /* LEDS */
 static struct gpio_led marzen_leds[] = {
 	{
@@ -237,6 +297,19 @@
 };
 
 static const struct pinctrl_map marzen_pinctrl_map[] = {
+	/* DU (CN10: ARGB0, CN13: LVDS) */
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779",
+				  "du0_rgb888", "du0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779",
+				  "du0_sync_1", "du0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779",
+				  "du0_clk_out_0", "du0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779",
+				  "du1_rgb666", "du1"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779",
+				  "du1_sync_1", "du1"),
+	PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7779", "pfc-r8a7779",
+				  "du1_clk_out", "du1"),
 	/* HSPI0 */
 	PIN_MAP_MUX_GROUP_DEFAULT("sh-hspi.0", "pfc-r8a7779",
 				  "hspi0", "hspi0"),
@@ -297,6 +370,7 @@
 	r8a7779_add_vin_device(1, &vin_platform_data);
 	r8a7779_add_vin_device(3, &vin_platform_data);
 	platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices));
+	marzen_add_du_device();
 }
 
 static const char *marzen_boards_compat_dt[] __initdata = {
diff --git a/arch/arm/mach-shmobile/clock-r7s72100.c b/arch/arm/mach-shmobile/clock-r7s72100.c
new file mode 100644
index 0000000..4aba20c
--- /dev/null
+++ b/arch/arm/mach-shmobile/clock-r7s72100.c
@@ -0,0 +1,202 @@
+/*
+ * r7a72100 clock framework support
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2012  Phil Edworthy
+ * Copyright (C) 2011  Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/sh_clk.h>
+#include <linux/clkdev.h>
+#include <mach/common.h>
+#include <mach/r7s72100.h>
+
+/* registers */
+#define FRQCR		0xfcfe0010
+#define FRQCR2		0xfcfe0014
+#define STBCR3		0xfcfe0420
+#define STBCR4		0xfcfe0424
+
+#define PLL_RATE 30
+
+static struct clk_mapping cpg_mapping = {
+	.phys	= 0xfcfe0000,
+	.len	= 0x1000,
+};
+
+/* Fixed 32 KHz root clock for RTC */
+static struct clk r_clk = {
+	.rate           = 32768,
+};
+
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk extal_clk = {
+	.rate		= 13330000,
+	.mapping	= &cpg_mapping,
+};
+
+static unsigned long pll_recalc(struct clk *clk)
+{
+	return clk->parent->rate * PLL_RATE;
+}
+
+static struct sh_clk_ops pll_clk_ops = {
+	.recalc		= pll_recalc,
+};
+
+static struct clk pll_clk = {
+	.ops		= &pll_clk_ops,
+	.parent		= &extal_clk,
+	.flags		= CLK_ENABLE_ON_INIT,
+};
+
+static unsigned long bus_recalc(struct clk *clk)
+{
+	return clk->parent->rate * 2 / 3;
+}
+
+static struct sh_clk_ops bus_clk_ops = {
+	.recalc		= bus_recalc,
+};
+
+static struct clk bus_clk = {
+	.ops		= &bus_clk_ops,
+	.parent		= &pll_clk,
+	.flags		= CLK_ENABLE_ON_INIT,
+};
+
+static unsigned long peripheral0_recalc(struct clk *clk)
+{
+	return clk->parent->rate / 12;
+}
+
+static struct sh_clk_ops peripheral0_clk_ops = {
+	.recalc		= peripheral0_recalc,
+};
+
+static struct clk peripheral0_clk = {
+	.ops		= &peripheral0_clk_ops,
+	.parent		= &pll_clk,
+	.flags		= CLK_ENABLE_ON_INIT,
+};
+
+static unsigned long peripheral1_recalc(struct clk *clk)
+{
+	return clk->parent->rate / 6;
+}
+
+static struct sh_clk_ops peripheral1_clk_ops = {
+	.recalc		= peripheral1_recalc,
+};
+
+static struct clk peripheral1_clk = {
+	.ops		= &peripheral1_clk_ops,
+	.parent		= &pll_clk,
+	.flags		= CLK_ENABLE_ON_INIT,
+};
+
+struct clk *main_clks[] = {
+	&r_clk,
+	&extal_clk,
+	&pll_clk,
+	&bus_clk,
+	&peripheral0_clk,
+	&peripheral1_clk,
+};
+
+static int div2[] = { 1, 3, 0, 3 }; /* 1, 2/3, reserve, 1/3 */
+static int multipliers[] = { 1, 2, 1, 1 };
+
+static struct clk_div_mult_table div4_div_mult_table = {
+	.divisors = div2,
+	.nr_divisors = ARRAY_SIZE(div2),
+	.multipliers = multipliers,
+	.nr_multipliers = ARRAY_SIZE(multipliers),
+};
+
+static struct clk_div4_table div4_table = {
+	.div_mult_table = &div4_div_mult_table,
+};
+
+enum { DIV4_I,
+	DIV4_NR };
+
+#define DIV4(_reg, _bit, _mask, _flags) \
+	SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
+
+/* The mask field specifies the div2 entries that are valid */
+struct clk div4_clks[DIV4_NR] = {
+	[DIV4_I]  = DIV4(FRQCR, 8, 0xB, CLK_ENABLE_REG_16BIT
+					| CLK_ENABLE_ON_INIT),
+};
+
+enum { MSTP47, MSTP46, MSTP45, MSTP44, MSTP43, MSTP42, MSTP41, MSTP40,
+	MSTP33,	MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+	[MSTP47] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 7, 0), /* SCIF0 */
+	[MSTP46] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 6, 0), /* SCIF1 */
+	[MSTP45] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 5, 0), /* SCIF2 */
+	[MSTP44] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 4, 0), /* SCIF3 */
+	[MSTP43] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 3, 0), /* SCIF4 */
+	[MSTP42] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 2, 0), /* SCIF5 */
+	[MSTP41] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 1, 0), /* SCIF6 */
+	[MSTP40] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 0, 0), /* SCIF7 */
+	[MSTP33] = SH_CLK_MSTP8(&peripheral0_clk, STBCR3, 3, 0), /* MTU2 */
+};
+
+static struct clk_lookup lookups[] = {
+	/* main clocks */
+	CLKDEV_CON_ID("rclk", &r_clk),
+	CLKDEV_CON_ID("extal", &extal_clk),
+	CLKDEV_CON_ID("pll_clk", &pll_clk),
+	CLKDEV_CON_ID("peripheral_clk", &peripheral1_clk),
+
+	/* DIV4 clocks */
+	CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+
+	/* MSTP clocks */
+	CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP47]),
+	CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP46]),
+	CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP45]),
+	CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP44]),
+	CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP43]),
+	CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP42]),
+	CLKDEV_ICK_ID("sci_fck", "sh-sci.6", &mstp_clks[MSTP41]),
+	CLKDEV_ICK_ID("sci_fck", "sh-sci.7", &mstp_clks[MSTP40]),
+};
+
+void __init r7s72100_clock_init(void)
+{
+	int k, ret = 0;
+
+	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+		ret = clk_register(main_clks[k]);
+
+	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+	if (!ret)
+		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+
+	if (!ret)
+		ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+
+	if (!ret)
+		shmobile_clk_init();
+	else
+		panic("failed to setup rza1 clocks\n");
+}
diff --git a/arch/arm/mach-shmobile/clock-r8a73a4.c b/arch/arm/mach-shmobile/clock-r8a73a4.c
index 5bd2e85..571409b 100644
--- a/arch/arm/mach-shmobile/clock-r8a73a4.c
+++ b/arch/arm/mach-shmobile/clock-r8a73a4.c
@@ -504,7 +504,7 @@
 
 /* MSTP */
 enum {
-	MSTP217, MSTP216, MSTP207, MSTP206, MSTP204, MSTP203,
+	MSTP218, MSTP217, MSTP216, MSTP207, MSTP206, MSTP204, MSTP203,
 	MSTP329, MSTP323, MSTP318, MSTP317, MSTP316,
 	MSTP315, MSTP314, MSTP313, MSTP312, MSTP305, MSTP300,
 	MSTP411, MSTP410, MSTP409,
@@ -519,6 +519,7 @@
 	[MSTP207] = SH_CLK_MSTP32(&div6_clks[DIV6_MP],	SMSTPCR2, 7, 0), /* SCIFB1 */
 	[MSTP216] = SH_CLK_MSTP32(&div6_clks[DIV6_MP],	SMSTPCR2, 16, 0), /* SCIFB2 */
 	[MSTP217] = SH_CLK_MSTP32(&div6_clks[DIV6_MP],	SMSTPCR2, 17, 0), /* SCIFB3 */
+	[MSTP218] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR2, 18, 0), /* DMAC */
 	[MSTP300] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR3, 0, 0), /* IIC2 */
 	[MSTP305] = SH_CLK_MSTP32(&div6_clks[DIV6_MMC1],SMSTPCR3, 5, 0), /* MMCIF1 */
 	[MSTP312] = SH_CLK_MSTP32(&div6_clks[DIV6_SDHI2],SMSTPCR3, 12, 0), /* SDHI2 */
@@ -578,6 +579,8 @@
 	CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP207]),
 	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP216]),
 	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP217]),
+	CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]),
+	CLKDEV_DEV_ID("e6700020.dma-controller", &mstp_clks[MSTP218]),
 	CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
 	CLKDEV_DEV_ID("e6520000.i2c", &mstp_clks[MSTP300]),
 	CLKDEV_DEV_ID("sh_mmcif.1", &mstp_clks[MSTP305]),
diff --git a/arch/arm/mach-shmobile/clock-r8a7778.c b/arch/arm/mach-shmobile/clock-r8a7778.c
index c4bf2d8..fb6af83 100644
--- a/arch/arm/mach-shmobile/clock-r8a7778.c
+++ b/arch/arm/mach-shmobile/clock-r8a7778.c
@@ -69,6 +69,15 @@
 	.mapping = &cpg_mapping,
 };
 
+static struct clk audio_clk_a = {
+};
+
+static struct clk audio_clk_b = {
+};
+
+static struct clk audio_clk_c = {
+};
+
 /*
  * clock ratio of these clock will be updated
  * on r8a7778_clock_init()
@@ -100,18 +109,23 @@
 	&p_clk,
 	&g_clk,
 	&z_clk,
+	&audio_clk_a,
+	&audio_clk_b,
+	&audio_clk_c,
 };
 
 enum {
 	MSTP331,
 	MSTP323, MSTP322, MSTP321,
+	MSTP311, MSTP310,
+	MSTP309, MSTP308, MSTP307,
 	MSTP114,
 	MSTP110, MSTP109,
 	MSTP100,
 	MSTP030,
 	MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
-	MSTP016, MSTP015,
-	MSTP007,
+	MSTP016, MSTP015, MSTP012, MSTP011, MSTP010,
+	MSTP009, MSTP008, MSTP007,
 	MSTP_NR };
 
 static struct clk mstp_clks[MSTP_NR] = {
@@ -119,6 +133,11 @@
 	[MSTP323] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 23, 0), /* SDHI0 */
 	[MSTP322] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 22, 0), /* SDHI1 */
 	[MSTP321] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 21, 0), /* SDHI2 */
+	[MSTP311] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 11, 0), /* SSI4 */
+	[MSTP310] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 10, 0), /* SSI5 */
+	[MSTP309] = SH_CLK_MSTP32(&p_clk, MSTPCR3,  9, 0), /* SSI6 */
+	[MSTP308] = SH_CLK_MSTP32(&p_clk, MSTPCR3,  8, 0), /* SSI7 */
+	[MSTP307] = SH_CLK_MSTP32(&p_clk, MSTPCR3,  7, 0), /* SSI8 */
 	[MSTP114] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 14, 0), /* Ether */
 	[MSTP110] = SH_CLK_MSTP32(&s_clk, MSTPCR1, 10, 0), /* VIN0 */
 	[MSTP109] = SH_CLK_MSTP32(&s_clk, MSTPCR1,  9, 0), /* VIN1 */
@@ -135,11 +154,20 @@
 	[MSTP021] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 21, 0), /* SCIF5 */
 	[MSTP016] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 16, 0), /* TMU0 */
 	[MSTP015] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 15, 0), /* TMU1 */
+	[MSTP012] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 12, 0), /* SSI0 */
+	[MSTP011] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 11, 0), /* SSI1 */
+	[MSTP010] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 10, 0), /* SSI2 */
+	[MSTP009] = SH_CLK_MSTP32(&p_clk, MSTPCR0,  9, 0), /* SSI3 */
+	[MSTP008] = SH_CLK_MSTP32(&p_clk, MSTPCR0,  8, 0), /* SRU */
 	[MSTP007] = SH_CLK_MSTP32(&p_clk, MSTPCR0,  7, 0), /* HSPI */
 };
 
 static struct clk_lookup lookups[] = {
 	/* main */
+	CLKDEV_CON_ID("audio_clk_a",	&audio_clk_a),
+	CLKDEV_CON_ID("audio_clk_b",	&audio_clk_b),
+	CLKDEV_CON_ID("audio_clk_c",	&audio_clk_c),
+	CLKDEV_CON_ID("audio_clk_internal",	&s1_clk),
 	CLKDEV_CON_ID("shyway_clk",	&s_clk),
 	CLKDEV_CON_ID("peripheral_clk",	&p_clk),
 
@@ -153,6 +181,7 @@
 	CLKDEV_DEV_ID("r8a7778-vin.1", &mstp_clks[MSTP109]), /* VIN1 */
 	CLKDEV_DEV_ID("ehci-platform", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */
 	CLKDEV_DEV_ID("ohci-platform", &mstp_clks[MSTP100]), /* USB OHCI port0/1 */
+	CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP100]), /* USB FUNC */
 	CLKDEV_DEV_ID("i2c-rcar.0", &mstp_clks[MSTP030]), /* I2C0 */
 	CLKDEV_DEV_ID("i2c-rcar.1", &mstp_clks[MSTP029]), /* I2C1 */
 	CLKDEV_DEV_ID("i2c-rcar.2", &mstp_clks[MSTP028]), /* I2C2 */
@@ -168,6 +197,17 @@
 	CLKDEV_DEV_ID("sh-hspi.0", &mstp_clks[MSTP007]), /* HSPI0 */
 	CLKDEV_DEV_ID("sh-hspi.1", &mstp_clks[MSTP007]), /* HSPI1 */
 	CLKDEV_DEV_ID("sh-hspi.2", &mstp_clks[MSTP007]), /* HSPI2 */
+	CLKDEV_DEV_ID("rcar_sound", &mstp_clks[MSTP008]), /* SRU */
+
+	CLKDEV_ICK_ID("ssi.0", "rcar_sound", &mstp_clks[MSTP012]),
+	CLKDEV_ICK_ID("ssi.1", "rcar_sound", &mstp_clks[MSTP011]),
+	CLKDEV_ICK_ID("ssi.2", "rcar_sound", &mstp_clks[MSTP010]),
+	CLKDEV_ICK_ID("ssi.3", "rcar_sound", &mstp_clks[MSTP009]),
+	CLKDEV_ICK_ID("ssi.4", "rcar_sound", &mstp_clks[MSTP311]),
+	CLKDEV_ICK_ID("ssi.5", "rcar_sound", &mstp_clks[MSTP310]),
+	CLKDEV_ICK_ID("ssi.6", "rcar_sound", &mstp_clks[MSTP309]),
+	CLKDEV_ICK_ID("ssi.7", "rcar_sound", &mstp_clks[MSTP308]),
+	CLKDEV_ICK_ID("ssi.8", "rcar_sound", &mstp_clks[MSTP307]),
 };
 
 void __init r8a7778_clock_init(void)
diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c
index bd6ad92..1f7080f 100644
--- a/arch/arm/mach-shmobile/clock-r8a7779.c
+++ b/arch/arm/mach-shmobile/clock-r8a7779.c
@@ -200,7 +200,7 @@
 	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP320]), /* SDHI3 */
-	CLKDEV_DEV_ID("rcar-du.0", &mstp_clks[MSTP103]), /* DU */
+	CLKDEV_DEV_ID("rcar-du-r8a7779", &mstp_clks[MSTP103]), /* DU */
 };
 
 void __init r8a7779_clock_init(void)
diff --git a/arch/arm/mach-shmobile/clock-r8a7790.c b/arch/arm/mach-shmobile/clock-r8a7790.c
index fc36d3d..a64f965 100644
--- a/arch/arm/mach-shmobile/clock-r8a7790.c
+++ b/arch/arm/mach-shmobile/clock-r8a7790.c
@@ -52,6 +52,7 @@
 #define SMSTPCR5 0xe6150144
 #define SMSTPCR7 0xe615014c
 #define SMSTPCR8 0xe6150990
+#define SMSTPCR9 0xe6150994
 
 #define SDCKCR		0xE6150074
 #define SD2CKCR		0xE6150078
@@ -181,8 +182,9 @@
 
 /* MSTP */
 enum {
+	MSTP931, MSTP930, MSTP929, MSTP928,
 	MSTP813,
-	MSTP721, MSTP720,
+	MSTP726, MSTP725, MSTP724, MSTP723, MSTP722, MSTP721, MSTP720,
 	MSTP717, MSTP716,
 	MSTP522,
 	MSTP315, MSTP314, MSTP313, MSTP312, MSTP311, MSTP305, MSTP304,
@@ -192,7 +194,16 @@
 };
 
 static struct clk mstp_clks[MSTP_NR] = {
+	[MSTP931] = SH_CLK_MSTP32(&hp_clk, SMSTPCR9, 31, 0), /* I2C0 */
+	[MSTP930] = SH_CLK_MSTP32(&hp_clk, SMSTPCR9, 30, 0), /* I2C1 */
+	[MSTP929] = SH_CLK_MSTP32(&hp_clk, SMSTPCR9, 29, 0), /* I2C2 */
+	[MSTP928] = SH_CLK_MSTP32(&hp_clk, SMSTPCR9, 28, 0), /* I2C3 */
 	[MSTP813] = SH_CLK_MSTP32(&p_clk, SMSTPCR8, 13, 0), /* Ether */
+	[MSTP726] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 26, 0), /* LVDS0 */
+	[MSTP725] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 25, 0), /* LVDS1 */
+	[MSTP724] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 24, 0), /* DU0 */
+	[MSTP723] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 23, 0), /* DU1 */
+	[MSTP722] = SH_CLK_MSTP32(&zx_clk, SMSTPCR7, 22, 0), /* DU2 */
 	[MSTP721] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 21, 0), /* SCIF0 */
 	[MSTP720] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 20, 0), /* SCIF1 */
 	[MSTP717] = SH_CLK_MSTP32(&zs_clk, SMSTPCR7, 17, 0), /* HSCIF0 */
@@ -251,6 +262,11 @@
 	CLKDEV_CON_ID("ssprs",		&div6_clks[DIV6_SSPRS]),
 
 	/* MSTP */
+	CLKDEV_ICK_ID("lvds.0", "rcar-du-r8a7790", &mstp_clks[MSTP726]),
+	CLKDEV_ICK_ID("lvds.1", "rcar-du-r8a7790", &mstp_clks[MSTP725]),
+	CLKDEV_ICK_ID("du.0", "rcar-du-r8a7790", &mstp_clks[MSTP724]),
+	CLKDEV_ICK_ID("du.1", "rcar-du-r8a7790", &mstp_clks[MSTP723]),
+	CLKDEV_ICK_ID("du.2", "rcar-du-r8a7790", &mstp_clks[MSTP722]),
 	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]),
 	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]),
 	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP206]),
@@ -261,6 +277,10 @@
 	CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP720]),
 	CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP717]),
 	CLKDEV_DEV_ID("sh-sci.9", &mstp_clks[MSTP716]),
+	CLKDEV_DEV_ID("e6508000.i2c", &mstp_clks[MSTP931]),
+	CLKDEV_DEV_ID("e6518000.i2c", &mstp_clks[MSTP930]),
+	CLKDEV_DEV_ID("e6530000.i2c", &mstp_clks[MSTP929]),
+	CLKDEV_DEV_ID("e6540000.i2c", &mstp_clks[MSTP928]),
 	CLKDEV_DEV_ID("r8a7790-ether", &mstp_clks[MSTP813]),
 	CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]),
 	CLKDEV_DEV_ID("ee200000.mmcif", &mstp_clks[MSTP315]),
@@ -290,7 +310,7 @@
 
 void __init r8a7790_clock_init(void)
 {
-	u32 mode = r8a7790_read_mode_pins();
+	u32 mode = rcar_gen2_read_mode_pins();
 	int k, ret = 0;
 
 	switch (mode & (MD(14) | MD(13))) {
diff --git a/arch/arm/mach-shmobile/clock-r8a7791.c b/arch/arm/mach-shmobile/clock-r8a7791.c
new file mode 100644
index 0000000..c9a26f1
--- /dev/null
+++ b/arch/arm/mach-shmobile/clock-r8a7791.c
@@ -0,0 +1,237 @@
+/*
+ * r8a7791 clock framework support
+ *
+ * Copyright (C) 2013  Renesas Electronics Corporation
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/sh_clk.h>
+#include <linux/clkdev.h>
+#include <mach/clock.h>
+#include <mach/common.h>
+
+/*
+ *   MD		EXTAL		PLL0	PLL1	PLL3
+ * 14 13 19	(MHz)		*1	*1
+ *---------------------------------------------------
+ * 0  0  0	15 x 1		x172/2	x208/2	x106
+ * 0  0  1	15 x 1		x172/2	x208/2	x88
+ * 0  1  0	20 x 1		x130/2	x156/2	x80
+ * 0  1  1	20 x 1		x130/2	x156/2	x66
+ * 1  0  0	26 / 2		x200/2	x240/2	x122
+ * 1  0  1	26 / 2		x200/2	x240/2	x102
+ * 1  1  0	30 / 2		x172/2	x208/2	x106
+ * 1  1  1	30 / 2		x172/2	x208/2	x88
+ *
+ * *1 :	Table 7.6 indicates VCO ouput (PLLx = VCO/2)
+ *	see "p1 / 2" on R8A7791_CLOCK_ROOT() below
+ */
+
+#define MD(nr)	(1 << nr)
+
+#define CPG_BASE 0xe6150000
+#define CPG_LEN 0x1000
+
+#define SMSTPCR0	0xE6150130
+#define SMSTPCR1	0xE6150134
+#define SMSTPCR2	0xe6150138
+#define SMSTPCR3	0xE615013C
+#define SMSTPCR5	0xE6150144
+#define SMSTPCR7	0xe615014c
+#define SMSTPCR8	0xE6150990
+#define SMSTPCR9	0xE6150994
+#define SMSTPCR10	0xE6150998
+#define SMSTPCR11	0xE615099C
+
+#define MODEMR		0xE6160060
+#define SDCKCR		0xE6150074
+#define SD2CKCR		0xE6150078
+#define SD3CKCR		0xE615007C
+#define MMC0CKCR	0xE6150240
+#define MMC1CKCR	0xE6150244
+#define SSPCKCR		0xE6150248
+#define SSPRSCKCR	0xE615024C
+
+static struct clk_mapping cpg_mapping = {
+	.phys   = CPG_BASE,
+	.len    = CPG_LEN,
+};
+
+static struct clk extal_clk = {
+	/* .rate will be updated on r8a7791_clock_init() */
+	.mapping	= &cpg_mapping,
+};
+
+static struct sh_clk_ops followparent_clk_ops = {
+	.recalc	= followparent_recalc,
+};
+
+static struct clk main_clk = {
+	/* .parent will be set r8a73a4_clock_init */
+	.ops	= &followparent_clk_ops,
+};
+
+/*
+ * clock ratio of these clock will be updated
+ * on r8a7791_clock_init()
+ */
+SH_FIXED_RATIO_CLK_SET(pll1_clk,		main_clk,	1, 1);
+SH_FIXED_RATIO_CLK_SET(pll3_clk,		main_clk,	1, 1);
+
+/* fixed ratio clock */
+SH_FIXED_RATIO_CLK_SET(extal_div2_clk,		extal_clk,	1, 2);
+SH_FIXED_RATIO_CLK_SET(cp_clk,			extal_clk,	1, 2);
+
+SH_FIXED_RATIO_CLK_SET(pll1_div2_clk,		pll1_clk,	1, 2);
+SH_FIXED_RATIO_CLK_SET(hp_clk,			pll1_clk,	1, 12);
+SH_FIXED_RATIO_CLK_SET(p_clk,			pll1_clk,	1, 24);
+SH_FIXED_RATIO_CLK_SET(rclk_clk,		pll1_clk,	1, (48 * 1024));
+SH_FIXED_RATIO_CLK_SET(mp_clk,			pll1_div2_clk,	1, 15);
+
+static struct clk *main_clks[] = {
+	&extal_clk,
+	&extal_div2_clk,
+	&main_clk,
+	&pll1_clk,
+	&pll1_div2_clk,
+	&pll3_clk,
+	&hp_clk,
+	&p_clk,
+	&rclk_clk,
+	&mp_clk,
+	&cp_clk,
+};
+
+/* MSTP */
+enum {
+	MSTP721, MSTP720,
+	MSTP719, MSTP718, MSTP715, MSTP714,
+	MSTP216, MSTP207, MSTP206,
+	MSTP204, MSTP203, MSTP202, MSTP1105, MSTP1106, MSTP1107,
+	MSTP124,
+	MSTP_NR
+};
+
+static struct clk mstp_clks[MSTP_NR] = {
+	[MSTP721] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 21, 0), /* SCIF0 */
+	[MSTP720] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 20, 0), /* SCIF1 */
+	[MSTP719] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 19, 0), /* SCIF2 */
+	[MSTP718] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 18, 0), /* SCIF3 */
+	[MSTP715] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 15, 0), /* SCIF4 */
+	[MSTP714] = SH_CLK_MSTP32(&p_clk, SMSTPCR7, 14, 0), /* SCIF5 */
+	[MSTP216] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 16, 0), /* SCIFB2 */
+	[MSTP207] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 7, 0), /* SCIFB1 */
+	[MSTP206] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 6, 0), /* SCIFB0 */
+	[MSTP204] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 4, 0), /* SCIFA0 */
+	[MSTP203] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 3, 0), /* SCIFA1 */
+	[MSTP202] = SH_CLK_MSTP32(&mp_clk, SMSTPCR2, 2, 0), /* SCIFA2 */
+	[MSTP1105] = SH_CLK_MSTP32(&mp_clk, SMSTPCR11, 5, 0), /* SCIFA3 */
+	[MSTP1106] = SH_CLK_MSTP32(&mp_clk, SMSTPCR11, 6, 0), /* SCIFA4 */
+	[MSTP1107] = SH_CLK_MSTP32(&mp_clk, SMSTPCR11, 7, 0), /* SCIFA5 */
+	[MSTP124] = SH_CLK_MSTP32(&rclk_clk, SMSTPCR1, 24, 0), /* CMT0 */
+};
+
+static struct clk_lookup lookups[] = {
+
+	/* main clocks */
+	CLKDEV_CON_ID("extal",		&extal_clk),
+	CLKDEV_CON_ID("extal_div2",	&extal_div2_clk),
+	CLKDEV_CON_ID("main",		&main_clk),
+	CLKDEV_CON_ID("pll1",		&pll1_clk),
+	CLKDEV_CON_ID("pll1_div2",	&pll1_div2_clk),
+	CLKDEV_CON_ID("pll3",		&pll3_clk),
+	CLKDEV_CON_ID("hp",		&hp_clk),
+	CLKDEV_CON_ID("p",		&p_clk),
+	CLKDEV_CON_ID("rclk",		&rclk_clk),
+	CLKDEV_CON_ID("mp",		&mp_clk),
+	CLKDEV_CON_ID("cp",		&cp_clk),
+	CLKDEV_CON_ID("peripheral_clk", &hp_clk),
+
+	/* MSTP */
+	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */
+	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), /* SCIFA1 */
+	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP206]), /* SCIFB0 */
+	CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP207]), /* SCIFB1 */
+	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP216]), /* SCIFB2 */
+	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP202]), /* SCIFA2 */
+	CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP721]), /* SCIF0 */
+	CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP720]), /* SCIF1 */
+	CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP719]), /* SCIF2 */
+	CLKDEV_DEV_ID("sh-sci.9", &mstp_clks[MSTP718]), /* SCIF3 */
+	CLKDEV_DEV_ID("sh-sci.10", &mstp_clks[MSTP715]), /* SCIF4 */
+	CLKDEV_DEV_ID("sh-sci.11", &mstp_clks[MSTP714]), /* SCIF5 */
+	CLKDEV_DEV_ID("sh-sci.12", &mstp_clks[MSTP1105]), /* SCIFA3 */
+	CLKDEV_DEV_ID("sh-sci.13", &mstp_clks[MSTP1106]), /* SCIFA4 */
+	CLKDEV_DEV_ID("sh-sci.14", &mstp_clks[MSTP1107]), /* SCIFA5 */
+	CLKDEV_DEV_ID("sh_cmt.0", &mstp_clks[MSTP124]),
+};
+
+#define R8A7791_CLOCK_ROOT(e, m, p0, p1, p30, p31)		\
+	extal_clk.rate	= e * 1000 * 1000;			\
+	main_clk.parent	= m;					\
+	SH_CLK_SET_RATIO(&pll1_clk_ratio, p1 / 2, 1);		\
+	if (mode & MD(19))					\
+		SH_CLK_SET_RATIO(&pll3_clk_ratio, p31, 1);	\
+	else							\
+		SH_CLK_SET_RATIO(&pll3_clk_ratio, p30, 1)
+
+
+void __init r8a7791_clock_init(void)
+{
+	void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
+	u32 mode;
+	int k, ret = 0;
+
+	BUG_ON(!modemr);
+	mode = ioread32(modemr);
+	iounmap(modemr);
+
+	switch (mode & (MD(14) | MD(13))) {
+	case 0:
+		R8A7791_CLOCK_ROOT(15, &extal_clk, 172, 208, 106, 88);
+		break;
+	case MD(13):
+		R8A7791_CLOCK_ROOT(20, &extal_clk, 130, 156, 80, 66);
+		break;
+	case MD(14):
+		R8A7791_CLOCK_ROOT(26, &extal_div2_clk, 200, 240, 122, 102);
+		break;
+	case MD(13) | MD(14):
+		R8A7791_CLOCK_ROOT(30, &extal_div2_clk, 172, 208, 106, 88);
+		break;
+	}
+
+	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+		ret = clk_register(main_clks[k]);
+
+	if (!ret)
+		ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+
+	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+	if (!ret)
+		shmobile_clk_init();
+	else
+		goto epanic;
+
+	return;
+
+epanic:
+	panic("failed to setup r8a7791 clocks\n");
+}
diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S
index f93751c..e5be5c8 100644
--- a/arch/arm/mach-shmobile/headsmp.S
+++ b/arch/arm/mach-shmobile/headsmp.S
@@ -40,6 +40,9 @@
 	.globl	shmobile_boot_arg
 shmobile_boot_arg:
 2:	.space	4
+	.globl	shmobile_boot_size
+shmobile_boot_size:
+	.long	. - shmobile_boot_vector
 
 /*
  * Per-CPU SMP boot function/argument selection code based on MPIDR
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index 7b93868..e319805 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -9,16 +9,23 @@
 extern void shmobile_boot_vector(void);
 extern unsigned long shmobile_boot_fn;
 extern unsigned long shmobile_boot_arg;
+extern unsigned long shmobile_boot_size;
 extern void shmobile_smp_boot(void);
 extern void shmobile_smp_sleep(void);
 extern void shmobile_smp_hook(unsigned int cpu, unsigned long fn,
 			      unsigned long arg);
+extern int shmobile_smp_cpu_disable(unsigned int cpu);
+extern void shmobile_invalidate_start(void);
 extern void shmobile_boot_scu(void);
 extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus);
-extern int shmobile_smp_scu_boot_secondary(unsigned int cpu,
-					   struct task_struct *idle);
 extern void shmobile_smp_scu_cpu_die(unsigned int cpu);
 extern int shmobile_smp_scu_cpu_kill(unsigned int cpu);
+extern void shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus);
+extern int shmobile_smp_apmu_boot_secondary(unsigned int cpu,
+					    struct task_struct *idle);
+extern void shmobile_smp_apmu_cpu_die(unsigned int cpu);
+extern int shmobile_smp_apmu_cpu_kill(unsigned int cpu);
+extern void shmobile_invalidate_start(void);
 struct clk;
 extern int shmobile_clk_init(void);
 extern void shmobile_handle_irq_intc(struct pt_regs *);
@@ -39,7 +46,6 @@
 #endif
 
 extern void __iomem *shmobile_scu_base;
-extern void shmobile_smp_init_cpus(unsigned int ncores);
 
 static inline void __init shmobile_init_late(void)
 {
diff --git a/arch/arm/mach-shmobile/include/mach/r7s72100.h b/arch/arm/mach-shmobile/include/mach/r7s72100.h
new file mode 100644
index 0000000..5f34b20
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/r7s72100.h
@@ -0,0 +1,8 @@
+#ifndef __ASM_R7S72100_H__
+#define __ASM_R7S72100_H__
+
+void r7s72100_add_dt_devices(void);
+void r7s72100_clock_init(void);
+void r7s72100_init_early(void);
+
+#endif /* __ASM_R7S72100_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a73a4.h b/arch/arm/mach-shmobile/include/mach/r8a73a4.h
index f3a9b70..ce8bdd1 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a73a4.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a73a4.h
@@ -1,10 +1,19 @@
 #ifndef __ASM_R8A73A4_H__
 #define __ASM_R8A73A4_H__
 
+/* DMA slave IDs */
+enum {
+	SHDMA_SLAVE_INVALID,
+	SHDMA_SLAVE_MMCIF0_TX,
+	SHDMA_SLAVE_MMCIF0_RX,
+	SHDMA_SLAVE_MMCIF1_TX,
+	SHDMA_SLAVE_MMCIF1_RX,
+};
+
 void r8a73a4_add_standard_devices(void);
 void r8a73a4_add_dt_devices(void);
 void r8a73a4_clock_init(void);
 void r8a73a4_pinmux_init(void);
-void r8a73a4_init_delay(void);
+void r8a73a4_init_early(void);
 
 #endif /* __ASM_R8A73A4_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7778.h b/arch/arm/mach-shmobile/include/mach/r8a7778.h
index adfcf51..441886c 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7778.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7778.h
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2013  Renesas Solutions Corp.
  * Copyright (C) 2013  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ * Copyright (C) 2013  Cogent Embedded, 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
@@ -21,11 +22,15 @@
 #include <linux/sh_eth.h>
 #include <linux/platform_data/camera-rcar.h>
 
+/* HPB-DMA slave IDs */
+enum {
+	HPBDMA_SLAVE_DUMMY,
+	HPBDMA_SLAVE_SDHI0_TX,
+	HPBDMA_SLAVE_SDHI0_RX,
+};
+
 extern void r8a7778_add_standard_devices(void);
 extern void r8a7778_add_standard_devices_dt(void);
-extern void r8a7778_add_ether_device(struct sh_eth_plat_data *pdata);
-extern void r8a7778_add_vin_device(int id,
-				   struct rcar_vin_platform_data *pdata);
 extern void r8a7778_add_dt_devices(void);
 
 extern void r8a7778_init_late(void);
@@ -33,6 +38,9 @@
 extern void r8a7778_init_irq_dt(void);
 extern void r8a7778_clock_init(void);
 extern void r8a7778_init_irq_extpin(int irlm);
+extern void r8a7778_init_irq_extpin_dt(int irlm);
 extern void r8a7778_pinmux_init(void);
 
+extern int r8a7778_usb_phy_power(bool enable);
+
 #endif /* __ASM_R8A7778_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7779.h b/arch/arm/mach-shmobile/include/mach/r8a7779.h
index 11c7400..17af34e 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7779.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7779.h
@@ -6,6 +6,13 @@
 #include <linux/sh_eth.h>
 #include <linux/platform_data/camera-rcar.h>
 
+/* HPB-DMA slave IDs */
+enum {
+	HPBDMA_SLAVE_DUMMY,
+	HPBDMA_SLAVE_SDHI0_TX,
+	HPBDMA_SLAVE_SDHI0_RX,
+};
+
 struct platform_device;
 
 struct r8a7779_pm_ch {
@@ -26,6 +33,7 @@
 
 extern void r8a7779_init_delay(void);
 extern void r8a7779_init_irq_extpin(int irlm);
+extern void r8a7779_init_irq_extpin_dt(int irlm);
 extern void r8a7779_init_irq_dt(void);
 extern void r8a7779_map_io(void);
 extern void r8a7779_earlytimer_init(void);
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7790.h b/arch/arm/mach-shmobile/include/mach/r8a7790.h
index 788d559..5fbfa28 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7790.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7790.h
@@ -1,14 +1,13 @@
 #ifndef __ASM_R8A7790_H__
 #define __ASM_R8A7790_H__
 
+#include <mach/rcar-gen2.h>
+
 void r8a7790_add_standard_devices(void);
 void r8a7790_add_dt_devices(void);
 void r8a7790_clock_init(void);
 void r8a7790_pinmux_init(void);
-void r8a7790_init_delay(void);
-void r8a7790_timer_init(void);
-
-#define MD(nr) BIT(nr)
-u32 r8a7790_read_mode_pins(void);
+void r8a7790_init_early(void);
+extern struct smp_operations r8a7790_smp_ops;
 
 #endif /* __ASM_R8A7790_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7791.h b/arch/arm/mach-shmobile/include/mach/r8a7791.h
new file mode 100644
index 0000000..051ead3
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/r8a7791.h
@@ -0,0 +1,10 @@
+#ifndef __ASM_R8A7791_H__
+#define __ASM_R8A7791_H__
+
+void r8a7791_add_standard_devices(void);
+void r8a7791_add_dt_devices(void);
+void r8a7791_clock_init(void);
+void r8a7791_init_early(void);
+extern struct smp_operations r8a7791_smp_ops;
+
+#endif /* __ASM_R8A7791_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/rcar-gen2.h b/arch/arm/mach-shmobile/include/mach/rcar-gen2.h
new file mode 100644
index 0000000..43f606e
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/rcar-gen2.h
@@ -0,0 +1,8 @@
+#ifndef __ASM_RCAR_GEN2_H__
+#define __ASM_RCAR_GEN2_H__
+
+void rcar_gen2_timer_init(void);
+#define MD(nr) BIT(nr)
+u32 rcar_gen2_read_mode_pins(void);
+
+#endif /* __ASM_RCAR_GEN2_H__ */
diff --git a/arch/arm/mach-shmobile/platsmp-apmu.c b/arch/arm/mach-shmobile/platsmp-apmu.c
new file mode 100644
index 0000000..1da5a72
--- /dev/null
+++ b/arch/arm/mach-shmobile/platsmp-apmu.c
@@ -0,0 +1,195 @@
+/*
+ * SMP support for SoCs with APMU
+ *
+ * Copyright (C) 2013  Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/of_address.h>
+#include <linux/smp.h>
+#include <asm/cacheflush.h>
+#include <asm/cp15.h>
+#include <asm/smp_plat.h>
+#include <mach/common.h>
+
+static struct {
+	void __iomem *iomem;
+	int bit;
+} apmu_cpus[CONFIG_NR_CPUS];
+
+#define WUPCR_OFFS 0x10
+#define PSTR_OFFS 0x40
+#define CPUNCR_OFFS(n) (0x100 + (0x10 * (n)))
+
+static int apmu_power_on(void __iomem *p, int bit)
+{
+	/* request power on */
+	writel_relaxed(BIT(bit), p + WUPCR_OFFS);
+
+	/* wait for APMU to finish */
+	while (readl_relaxed(p + WUPCR_OFFS) != 0)
+		;
+
+	return 0;
+}
+
+static int apmu_power_off(void __iomem *p, int bit)
+{
+	/* request Core Standby for next WFI */
+	writel_relaxed(3, p + CPUNCR_OFFS(bit));
+	return 0;
+}
+
+static int apmu_power_off_poll(void __iomem *p, int bit)
+{
+	int k;
+
+	for (k = 0; k < 1000; k++) {
+		if (((readl_relaxed(p + PSTR_OFFS) >> (bit * 4)) & 0x03) == 3)
+			return 1;
+
+		mdelay(1);
+	}
+
+	return 0;
+}
+
+static int apmu_wrap(int cpu, int (*fn)(void __iomem *p, int cpu))
+{
+	void __iomem *p = apmu_cpus[cpu].iomem;
+
+	return p ? fn(p, apmu_cpus[cpu].bit) : -EINVAL;
+}
+
+static void apmu_init_cpu(struct resource *res, int cpu, int bit)
+{
+	if (apmu_cpus[cpu].iomem)
+		return;
+
+	apmu_cpus[cpu].iomem = ioremap_nocache(res->start, resource_size(res));
+	apmu_cpus[cpu].bit = bit;
+
+	pr_debug("apmu ioremap %d %d 0x%08x 0x%08x\n", cpu, bit,
+		 res->start, resource_size(res));
+}
+
+static struct {
+	struct resource iomem;
+	int cpus[4];
+} apmu_config[] = {
+	{
+		.iomem = DEFINE_RES_MEM(0xe6152000, 0x88),
+		.cpus = { 0, 1, 2, 3 },
+	},
+	{
+		.iomem = DEFINE_RES_MEM(0xe6151000, 0x88),
+		.cpus = { 0x100, 0x101, 0x102, 0x103 },
+	}
+};
+
+static void apmu_parse_cfg(void (*fn)(struct resource *res, int cpu, int bit))
+{
+	u32 id;
+	int k;
+	int bit, index;
+	bool is_allowed;
+
+	for (k = 0; k < ARRAY_SIZE(apmu_config); k++) {
+		/* only enable the cluster that includes the boot CPU */
+		is_allowed = false;
+		for (bit = 0; bit < ARRAY_SIZE(apmu_config[k].cpus); bit++) {
+			id = apmu_config[k].cpus[bit];
+			if (id >= 0) {
+				if (id == cpu_logical_map(0))
+					is_allowed = true;
+			}
+		}
+		if (!is_allowed)
+			continue;
+
+		for (bit = 0; bit < ARRAY_SIZE(apmu_config[k].cpus); bit++) {
+			id = apmu_config[k].cpus[bit];
+			if (id >= 0) {
+				index = get_logical_index(id);
+				if (index >= 0)
+					fn(&apmu_config[k].iomem, index, bit);
+			}
+		}
+	}
+}
+
+void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus)
+{
+	/* install boot code shared by all CPUs */
+	shmobile_boot_fn = virt_to_phys(shmobile_smp_boot);
+	shmobile_boot_arg = MPIDR_HWID_BITMASK;
+
+	/* perform per-cpu setup */
+	apmu_parse_cfg(apmu_init_cpu);
+}
+
+int shmobile_smp_apmu_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	/* For this particular CPU register boot vector */
+	shmobile_smp_hook(cpu, virt_to_phys(shmobile_invalidate_start), 0);
+
+	return apmu_wrap(cpu, apmu_power_on);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+/* nicked from arch/arm/mach-exynos/hotplug.c */
+static inline void cpu_enter_lowpower_a15(void)
+{
+	unsigned int v;
+
+	asm volatile(
+	"       mrc     p15, 0, %0, c1, c0, 0\n"
+	"       bic     %0, %0, %1\n"
+	"       mcr     p15, 0, %0, c1, c0, 0\n"
+		: "=&r" (v)
+		: "Ir" (CR_C)
+		: "cc");
+
+	flush_cache_louis();
+
+	asm volatile(
+	/*
+	 * Turn off coherency
+	 */
+	"       mrc     p15, 0, %0, c1, c0, 1\n"
+	"       bic     %0, %0, %1\n"
+	"       mcr     p15, 0, %0, c1, c0, 1\n"
+		: "=&r" (v)
+		: "Ir" (0x40)
+		: "cc");
+
+	isb();
+	dsb();
+}
+
+void shmobile_smp_apmu_cpu_die(unsigned int cpu)
+{
+	/* For this particular CPU deregister boot vector */
+	shmobile_smp_hook(cpu, 0, 0);
+
+	/* Select next sleep mode using the APMU */
+	apmu_wrap(cpu, apmu_power_off);
+
+	/* Do ARM specific CPU shutdown */
+	cpu_enter_lowpower_a15();
+
+	/* jump to shared mach-shmobile sleep / reset code */
+	shmobile_smp_sleep();
+}
+
+int shmobile_smp_apmu_cpu_kill(unsigned int cpu)
+{
+	return apmu_wrap(cpu, apmu_power_off_poll);
+}
+#endif
diff --git a/arch/arm/mach-shmobile/platsmp-scu.c b/arch/arm/mach-shmobile/platsmp-scu.c
index c96f501..673ad6e 100644
--- a/arch/arm/mach-shmobile/platsmp-scu.c
+++ b/arch/arm/mach-shmobile/platsmp-scu.c
@@ -7,6 +7,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/cpu.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/io.h>
@@ -16,6 +17,26 @@
 #include <asm/smp_scu.h>
 #include <mach/common.h>
 
+static int shmobile_smp_scu_notifier_call(struct notifier_block *nfb,
+					  unsigned long action, void *hcpu)
+{
+	unsigned int cpu = (long)hcpu;
+
+	switch (action) {
+	case CPU_UP_PREPARE:
+		/* For this particular CPU register SCU SMP boot vector */
+		shmobile_smp_hook(cpu, virt_to_phys(shmobile_boot_scu),
+				  (unsigned long)shmobile_scu_base);
+		break;
+	};
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block shmobile_smp_scu_notifier = {
+	.notifier_call = shmobile_smp_scu_notifier_call,
+};
+
 void __init shmobile_smp_scu_prepare_cpus(unsigned int max_cpus)
 {
 	/* install boot code shared by all CPUs */
@@ -25,14 +46,9 @@
 	/* enable SCU and cache coherency on booting CPU */
 	scu_enable(shmobile_scu_base);
 	scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
-}
 
-int shmobile_smp_scu_boot_secondary(unsigned int cpu, struct task_struct *idle)
-{
-	/* For this particular CPU register SCU boot vector */
-	shmobile_smp_hook(cpu, virt_to_phys(shmobile_boot_scu),
-			  (unsigned long)shmobile_scu_base);
-	return 0;
+	/* Use CPU notifier for reset vector control */
+	register_cpu_notifier(&shmobile_smp_scu_notifier);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
index d4ae616..9ebc246 100644
--- a/arch/arm/mach-shmobile/platsmp.c
+++ b/arch/arm/mach-shmobile/platsmp.c
@@ -11,25 +11,10 @@
  * published by the Free Software Foundation.
  */
 #include <linux/init.h>
-#include <linux/smp.h>
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 #include <mach/common.h>
 
-void __init shmobile_smp_init_cpus(unsigned int ncores)
-{
-	unsigned int i;
-
-	if (ncores > nr_cpu_ids) {
-		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
-			ncores, nr_cpu_ids);
-		ncores = nr_cpu_ids;
-	}
-
-	for (i = 0; i < ncores; i++)
-		set_cpu_possible(i, true);
-}
-
 extern unsigned long shmobile_smp_fn[];
 extern unsigned long shmobile_smp_arg[];
 extern unsigned long shmobile_smp_mpidr[];
@@ -44,3 +29,10 @@
 	shmobile_smp_arg[cpu] = arg;
 	flush_cache_all();
 }
+
+#ifdef CONFIG_HOTPLUG_CPU
+int shmobile_smp_cpu_disable(unsigned int cpu)
+{
+	return 0; /* Hotplug of any CPU is supported */
+}
+#endif
diff --git a/arch/arm/mach-shmobile/setup-r7s72100.c b/arch/arm/mach-shmobile/setup-r7s72100.c
new file mode 100644
index 0000000..d4eb509
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-r7s72100.c
@@ -0,0 +1,88 @@
+/*
+ * r7s72100 processor support
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+#include <linux/serial_sci.h>
+#include <mach/common.h>
+#include <mach/irqs.h>
+#include <mach/r7s72100.h>
+#include <asm/mach/arch.h>
+
+#define SCIF_DATA(index, baseaddr, irq)					\
+[index] = {								\
+	.type		= PORT_SCIF,					\
+	.regtype	= SCIx_SH2_SCIF_FIFODATA_REGTYPE,		\
+	.flags		= UPF_BOOT_AUTOCONF | UPF_IOREMAP,		\
+	.scbrr_algo_id	= SCBRR_ALGO_2,					\
+	.scscr		= SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |	\
+			  SCSCR_REIE,					\
+	.mapbase	= baseaddr,					\
+	.irqs		= { irq + 1, irq + 2, irq + 3, irq },		\
+}
+
+enum { SCIF0, SCIF1, SCIF2, SCIF3, SCIF4, SCIF5, SCIF6, SCIF7 };
+
+static const struct plat_sci_port scif[] __initconst = {
+	SCIF_DATA(SCIF0, 0xe8007000, gic_iid(221)), /* SCIF0 */
+	SCIF_DATA(SCIF1, 0xe8007800, gic_iid(225)), /* SCIF1 */
+	SCIF_DATA(SCIF2, 0xe8008000, gic_iid(229)), /* SCIF2 */
+	SCIF_DATA(SCIF3, 0xe8008800, gic_iid(233)), /* SCIF3 */
+	SCIF_DATA(SCIF4, 0xe8009000, gic_iid(237)), /* SCIF4 */
+	SCIF_DATA(SCIF5, 0xe8009800, gic_iid(241)), /* SCIF5 */
+	SCIF_DATA(SCIF6, 0xe800a000, gic_iid(245)), /* SCIF6 */
+	SCIF_DATA(SCIF7, 0xe800a800, gic_iid(249)), /* SCIF7 */
+};
+
+static inline void r7s72100_register_scif(int idx)
+{
+	platform_device_register_data(&platform_bus, "sh-sci", idx, &scif[idx],
+				      sizeof(struct plat_sci_port));
+}
+
+void __init r7s72100_add_dt_devices(void)
+{
+	r7s72100_register_scif(SCIF0);
+	r7s72100_register_scif(SCIF1);
+	r7s72100_register_scif(SCIF2);
+	r7s72100_register_scif(SCIF3);
+	r7s72100_register_scif(SCIF4);
+	r7s72100_register_scif(SCIF5);
+	r7s72100_register_scif(SCIF6);
+	r7s72100_register_scif(SCIF7);
+}
+
+void __init r7s72100_init_early(void)
+{
+	shmobile_setup_delay(400, 1, 3); /* Cortex-A9 @ 400MHz */
+}
+
+#ifdef CONFIG_USE_OF
+static const char *r7s72100_boards_compat_dt[] __initdata = {
+	"renesas,r7s72100",
+	NULL,
+};
+
+DT_MACHINE_START(R7S72100_DT, "Generic R7S72100 (Flattened Device Tree)")
+	.init_early	= r7s72100_init_early,
+	.dt_compat	= r7s72100_boards_compat_dt,
+MACHINE_END
+#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-r8a73a4.c b/arch/arm/mach-shmobile/setup-r8a73a4.c
index 8949170..b0f2749 100644
--- a/arch/arm/mach-shmobile/setup-r8a73a4.c
+++ b/arch/arm/mach-shmobile/setup-r8a73a4.c
@@ -22,8 +22,10 @@
 #include <linux/of_platform.h>
 #include <linux/platform_data/irq-renesas-irqc.h>
 #include <linux/serial_sci.h>
+#include <linux/sh_dma.h>
 #include <linux/sh_timer.h>
 #include <mach/common.h>
+#include <mach/dma-register.h>
 #include <mach/irqs.h>
 #include <mach/r8a73a4.h>
 #include <asm/mach/arch.h>
@@ -199,15 +201,104 @@
 	r8a7790_register_cmt(10);
 }
 
+/* DMA */
+static const struct sh_dmae_slave_config dma_slaves[] = {
+	{
+		.slave_id	= SHDMA_SLAVE_MMCIF0_TX,
+		.addr		= 0xee200034,
+		.chcr		= CHCR_TX(XMIT_SZ_32BIT),
+		.mid_rid	= 0xd1,
+	}, {
+		.slave_id	= SHDMA_SLAVE_MMCIF0_RX,
+		.addr		= 0xee200034,
+		.chcr		= CHCR_RX(XMIT_SZ_32BIT),
+		.mid_rid	= 0xd2,
+	}, {
+		.slave_id	= SHDMA_SLAVE_MMCIF1_TX,
+		.addr		= 0xee220034,
+		.chcr		= CHCR_TX(XMIT_SZ_32BIT),
+		.mid_rid	= 0xe1,
+	}, {
+		.slave_id	= SHDMA_SLAVE_MMCIF1_RX,
+		.addr		= 0xee220034,
+		.chcr		= CHCR_RX(XMIT_SZ_32BIT),
+		.mid_rid	= 0xe2,
+	},
+};
+
+#define DMAE_CHANNEL(a, b)				\
+	{						\
+		.offset         = (a) - 0x20,		\
+		.dmars          = (a) - 0x20 + 0x40,	\
+		.chclr_bit	= (b),			\
+		.chclr_offset	= 0x80 - 0x20,		\
+	}
+
+static const struct sh_dmae_channel dma_channels[] = {
+	DMAE_CHANNEL(0x8000, 0),
+	DMAE_CHANNEL(0x8080, 1),
+	DMAE_CHANNEL(0x8100, 2),
+	DMAE_CHANNEL(0x8180, 3),
+	DMAE_CHANNEL(0x8200, 4),
+	DMAE_CHANNEL(0x8280, 5),
+	DMAE_CHANNEL(0x8300, 6),
+	DMAE_CHANNEL(0x8380, 7),
+	DMAE_CHANNEL(0x8400, 8),
+	DMAE_CHANNEL(0x8480, 9),
+	DMAE_CHANNEL(0x8500, 10),
+	DMAE_CHANNEL(0x8580, 11),
+	DMAE_CHANNEL(0x8600, 12),
+	DMAE_CHANNEL(0x8680, 13),
+	DMAE_CHANNEL(0x8700, 14),
+	DMAE_CHANNEL(0x8780, 15),
+	DMAE_CHANNEL(0x8800, 16),
+	DMAE_CHANNEL(0x8880, 17),
+	DMAE_CHANNEL(0x8900, 18),
+	DMAE_CHANNEL(0x8980, 19),
+};
+
+static const struct sh_dmae_pdata dma_pdata = {
+	.slave		= dma_slaves,
+	.slave_num	= ARRAY_SIZE(dma_slaves),
+	.channel	= dma_channels,
+	.channel_num	= ARRAY_SIZE(dma_channels),
+	.ts_low_shift	= TS_LOW_SHIFT,
+	.ts_low_mask	= TS_LOW_BIT << TS_LOW_SHIFT,
+	.ts_high_shift	= TS_HI_SHIFT,
+	.ts_high_mask	= TS_HI_BIT << TS_HI_SHIFT,
+	.ts_shift	= dma_ts_shift,
+	.ts_shift_num	= ARRAY_SIZE(dma_ts_shift),
+	.dmaor_init     = DMAOR_DME,
+	.chclr_present	= 1,
+	.chclr_bitwise	= 1,
+};
+
+static struct resource dma_resources[] = {
+	DEFINE_RES_MEM(0xe6700020, 0x89e0),
+	DEFINE_RES_IRQ_NAMED(gic_spi(220), "error_irq"),
+	{
+		/* IRQ for channels 0-19 */
+		.start  = gic_spi(200),
+		.end    = gic_spi(219),
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+#define r8a73a4_register_dmac()							\
+	platform_device_register_resndata(&platform_bus, "sh-dma-engine", 0,	\
+				dma_resources, ARRAY_SIZE(dma_resources),	\
+				&dma_pdata, sizeof(dma_pdata))
+
 void __init r8a73a4_add_standard_devices(void)
 {
 	r8a73a4_add_dt_devices();
 	r8a73a4_register_irqc(0);
 	r8a73a4_register_irqc(1);
 	r8a73a4_register_thermal();
+	r8a73a4_register_dmac();
 }
 
-void __init r8a73a4_init_delay(void)
+void __init r8a73a4_init_early(void)
 {
 #ifndef CONFIG_ARM_ARCH_TIMER
 	shmobile_setup_delay(1500, 2, 4); /* Cortex-A15 @ 1500MHz */
@@ -222,7 +313,7 @@
 };
 
 DT_MACHINE_START(R8A73A4_DT, "Generic R8A73A4 (Flattened Device Tree)")
-	.init_early	= r8a73a4_init_delay,
+	.init_early	= r8a73a4_init_early,
 	.dt_compat	= r8a73a4_boards_compat_dt,
 MACHINE_END
 #endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-r8a7778.c b/arch/arm/mach-shmobile/setup-r8a7778.c
index 6a2657e..03fcc59 100644
--- a/arch/arm/mach-shmobile/setup-r8a7778.c
+++ b/arch/arm/mach-shmobile/setup-r8a7778.c
@@ -24,6 +24,7 @@
 #include <linux/irqchip/arm-gic.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/platform_data/dma-rcar-hpbdma.h>
 #include <linux/platform_data/gpio-rcar.h>
 #include <linux/platform_data/irq-renesas-intc-irqpin.h>
 #include <linux/platform_device.h>
@@ -95,29 +96,46 @@
 		&sh_tmu##idx##_platform_data,		\
 		sizeof(sh_tmu##idx##_platform_data))
 
-/* USB */
-static struct usb_phy *phy;
+int r8a7778_usb_phy_power(bool enable)
+{
+	static struct usb_phy *phy = NULL;
+	int ret = 0;
 
+	if (!phy)
+		phy = usb_get_phy(USB_PHY_TYPE_USB2);
+
+	if (IS_ERR(phy)) {
+		pr_err("kernel doesn't have usb phy driver\n");
+		return PTR_ERR(phy);
+	}
+
+	if (enable)
+		ret = usb_phy_init(phy);
+	else
+		usb_phy_shutdown(phy);
+
+	return ret;
+}
+
+/* USB */
 static int usb_power_on(struct platform_device *pdev)
 {
-	if (IS_ERR(phy))
-		return PTR_ERR(phy);
+	int ret = r8a7778_usb_phy_power(true);
+
+	if (ret)
+		return ret;
 
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_get_sync(&pdev->dev);
 
-	usb_phy_init(phy);
-
 	return 0;
 }
 
 static void usb_power_off(struct platform_device *pdev)
 {
-	if (IS_ERR(phy))
+	if (r8a7778_usb_phy_power(false))
 		return;
 
-	usb_phy_shutdown(phy);
-
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 }
@@ -174,20 +192,6 @@
 USB_PLATFORM_INFO(ehci);
 USB_PLATFORM_INFO(ohci);
 
-/* Ether */
-static struct resource ether_resources[] __initdata = {
-	DEFINE_RES_MEM(0xfde00000, 0x400),
-	DEFINE_RES_IRQ(gic_iid(0x89)),
-};
-
-void __init r8a7778_add_ether_device(struct sh_eth_plat_data *pdata)
-{
-	platform_device_register_resndata(&platform_bus, "r8a777x-ether", -1,
-					  ether_resources,
-					  ARRAY_SIZE(ether_resources),
-					  pdata, sizeof(*pdata));
-}
-
 /* PFC/GPIO */
 static struct resource pfc_resources[] __initdata = {
 	DEFINE_RES_MEM(0xfffc0000, 0x118),
@@ -272,7 +276,7 @@
 	DEFINE_RES_IRQ(gic_iid(0x75)),
 };
 
-void __init r8a7778_register_hspi(int id)
+static void __init r8a7778_register_hspi(int id)
 {
 	BUG_ON(id < 0 || id > 2);
 
@@ -281,40 +285,6 @@
 		hspi_resources + (2 * id), 2);
 }
 
-/* VIN */
-#define R8A7778_VIN(idx)						\
-static struct resource vin##idx##_resources[] __initdata = {		\
-	DEFINE_RES_MEM(0xffc50000 + 0x1000 * (idx), 0x1000),		\
-	DEFINE_RES_IRQ(gic_iid(0x5a)),					\
-};									\
-									\
-static struct platform_device_info vin##idx##_info __initdata = {	\
-	.parent		= &platform_bus,				\
-	.name		= "r8a7778-vin",				\
-	.id		= idx,						\
-	.res		= vin##idx##_resources,				\
-	.num_res	= ARRAY_SIZE(vin##idx##_resources),		\
-	.dma_mask	= DMA_BIT_MASK(32),				\
-}
-
-R8A7778_VIN(0);
-R8A7778_VIN(1);
-
-static struct platform_device_info *vin_info_table[] __initdata = {
-	&vin0_info,
-	&vin1_info,
-};
-
-void __init r8a7778_add_vin_device(int id, struct rcar_vin_platform_data *pdata)
-{
-	BUG_ON(id < 0 || id > 1);
-
-	vin_info_table[id]->data = pdata;
-	vin_info_table[id]->size_data = sizeof(*pdata);
-
-	platform_device_register_full(vin_info_table[id]);
-}
-
 void __init r8a7778_add_dt_devices(void)
 {
 	int i;
@@ -339,6 +309,88 @@
 	r8a7778_register_tmu(1);
 }
 
+/* HPB-DMA */
+
+/* Asynchronous mode register (ASYNCMDR) bits */
+#define HPB_DMAE_ASYNCMDR_ASMD22_MASK	BIT(2)	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD22_SINGLE	BIT(2)	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD22_MULTI	0	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD21_MASK	BIT(1)	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD21_SINGLE	BIT(1)	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD21_MULTI	0	/* SDHI0 */
+
+static const struct hpb_dmae_slave_config hpb_dmae_slaves[] = {
+	{
+		.id	= HPBDMA_SLAVE_SDHI0_TX,
+		.addr	= 0xffe4c000 + 0x30,
+		.dcr	= HPB_DMAE_DCR_SPDS_16BIT |
+			  HPB_DMAE_DCR_DMDL |
+			  HPB_DMAE_DCR_DPDS_16BIT,
+		.rstr	= HPB_DMAE_ASYNCRSTR_ASRST21 |
+			  HPB_DMAE_ASYNCRSTR_ASRST22 |
+			  HPB_DMAE_ASYNCRSTR_ASRST23,
+		.mdr	= HPB_DMAE_ASYNCMDR_ASMD21_MULTI,
+		.mdm	= HPB_DMAE_ASYNCMDR_ASMD21_MASK,
+		.port	= 0x0D0C,
+		.flags	= HPB_DMAE_SET_ASYNC_RESET | HPB_DMAE_SET_ASYNC_MODE,
+		.dma_ch	= 21,
+	}, {
+		.id	= HPBDMA_SLAVE_SDHI0_RX,
+		.addr	= 0xffe4c000 + 0x30,
+		.dcr	= HPB_DMAE_DCR_SMDL |
+			  HPB_DMAE_DCR_SPDS_16BIT |
+			  HPB_DMAE_DCR_DPDS_16BIT,
+		.rstr	= HPB_DMAE_ASYNCRSTR_ASRST21 |
+			  HPB_DMAE_ASYNCRSTR_ASRST22 |
+			  HPB_DMAE_ASYNCRSTR_ASRST23,
+		.mdr	= HPB_DMAE_ASYNCMDR_ASMD22_MULTI,
+		.mdm	= HPB_DMAE_ASYNCMDR_ASMD22_MASK,
+		.port	= 0x0D0C,
+		.flags	= HPB_DMAE_SET_ASYNC_RESET | HPB_DMAE_SET_ASYNC_MODE,
+		.dma_ch	= 22,
+	},
+};
+
+static const struct hpb_dmae_channel hpb_dmae_channels[] = {
+	HPB_DMAE_CHANNEL(0x7e, HPBDMA_SLAVE_SDHI0_TX), /* ch. 21 */
+	HPB_DMAE_CHANNEL(0x7e, HPBDMA_SLAVE_SDHI0_RX), /* ch. 22 */
+};
+
+static struct hpb_dmae_pdata dma_platform_data __initdata = {
+	.slaves			= hpb_dmae_slaves,
+	.num_slaves		= ARRAY_SIZE(hpb_dmae_slaves),
+	.channels		= hpb_dmae_channels,
+	.num_channels		= ARRAY_SIZE(hpb_dmae_channels),
+	.ts_shift		= {
+		[XMIT_SZ_8BIT]	= 0,
+		[XMIT_SZ_16BIT]	= 1,
+		[XMIT_SZ_32BIT]	= 2,
+	},
+	.num_hw_channels	= 39,
+};
+
+static struct resource hpb_dmae_resources[] __initdata = {
+	/* Channel registers */
+	DEFINE_RES_MEM(0xffc08000, 0x1000),
+	/* Common registers */
+	DEFINE_RES_MEM(0xffc09000, 0x170),
+	/* Asynchronous reset registers */
+	DEFINE_RES_MEM(0xffc00300, 4),
+	/* Asynchronous mode registers */
+	DEFINE_RES_MEM(0xffc00400, 4),
+	/* IRQ for DMA channels */
+	DEFINE_RES_NAMED(gic_iid(0x7b), 5, NULL, IORESOURCE_IRQ),
+};
+
+static void __init r8a7778_register_hpb_dmae(void)
+{
+	platform_device_register_resndata(&platform_bus, "hpb-dma-engine", -1,
+					  hpb_dmae_resources,
+					  ARRAY_SIZE(hpb_dmae_resources),
+					  &dma_platform_data,
+					  sizeof(dma_platform_data));
+}
+
 void __init r8a7778_add_standard_devices(void)
 {
 	r8a7778_add_dt_devices();
@@ -349,12 +401,12 @@
 	r8a7778_register_hspi(0);
 	r8a7778_register_hspi(1);
 	r8a7778_register_hspi(2);
+
+	r8a7778_register_hpb_dmae();
 }
 
 void __init r8a7778_init_late(void)
 {
-	phy = usb_get_phy(USB_PHY_TYPE_USB2);
-
 	platform_device_register_full(&ehci_info);
 	platform_device_register_full(&ohci_info);
 }
@@ -376,7 +428,7 @@
 	DEFINE_RES_IRQ(gic_iid(0x3e)), /* IRQ3 */
 };
 
-void __init r8a7778_init_irq_extpin(int irlm)
+void __init r8a7778_init_irq_extpin_dt(int irlm)
 {
 	void __iomem *icr0 = ioremap_nocache(0xfe780000, PAGE_SIZE);
 	unsigned long tmp;
@@ -394,7 +446,11 @@
 	tmp |= (1 << 21); /* LVLMODE = 1 */
 	iowrite32(tmp, icr0);
 	iounmap(icr0);
+}
 
+void __init r8a7778_init_irq_extpin(int irlm)
+{
+	r8a7778_init_irq_extpin_dt(irlm);
 	if (irlm)
 		platform_device_register_resndata(
 			&platform_bus, "renesas_intc_irqpin", -1,
diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c
index ecd0148..13049e9 100644
--- a/arch/arm/mach-shmobile/setup-r8a7779.c
+++ b/arch/arm/mach-shmobile/setup-r8a7779.c
@@ -25,6 +25,7 @@
 #include <linux/irqchip.h>
 #include <linux/irqchip/arm-gic.h>
 #include <linux/of_platform.h>
+#include <linux/platform_data/dma-rcar-hpbdma.h>
 #include <linux/platform_data/gpio-rcar.h>
 #include <linux/platform_data/irq-renesas-intc-irqpin.h>
 #include <linux/platform_device.h>
@@ -97,7 +98,7 @@
 	DEFINE_RES_IRQ(gic_spi(30)), /* IRQ3 */
 };
 
-void __init r8a7779_init_irq_extpin(int irlm)
+void __init r8a7779_init_irq_extpin_dt(int irlm)
 {
 	void __iomem *icr0 = ioremap_nocache(0xfe780000, PAGE_SIZE);
 	u32 tmp;
@@ -115,7 +116,11 @@
 	tmp |= (1 << 21); /* LVLMODE = 1 */
 	iowrite32(tmp, icr0);
 	iounmap(icr0);
+}
 
+void __init r8a7779_init_irq_extpin(int irlm)
+{
+	r8a7779_init_irq_extpin_dt(irlm);
 	if (irlm)
 		platform_device_register_resndata(
 			&platform_bus, "renesas_intc_irqpin", -1,
@@ -632,6 +637,158 @@
 	&vin3_info,
 };
 
+/* HPB-DMA */
+
+/* Asynchronous mode register bits */
+#define HPB_DMAE_ASYNCMDR_ASMD43_MASK		BIT(23)	/* MMC1 */
+#define HPB_DMAE_ASYNCMDR_ASMD43_SINGLE		BIT(23)	/* MMC1 */
+#define HPB_DMAE_ASYNCMDR_ASMD43_MULTI		0	/* MMC1 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD43_MASK		BIT(22)	/* MMC1 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD43_BURST	BIT(22)	/* MMC1 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD43_NBURST	0	/* MMC1 */
+#define HPB_DMAE_ASYNCMDR_ASMD24_MASK		BIT(21)	/* MMC0 */
+#define HPB_DMAE_ASYNCMDR_ASMD24_SINGLE		BIT(21)	/* MMC0 */
+#define HPB_DMAE_ASYNCMDR_ASMD24_MULTI		0	/* MMC0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD24_MASK		BIT(20)	/* MMC0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD24_BURST	BIT(20)	/* MMC0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD24_NBURST	0	/* MMC0 */
+#define HPB_DMAE_ASYNCMDR_ASMD41_MASK		BIT(19)	/* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD41_SINGLE		BIT(19)	/* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD41_MULTI		0	/* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD41_MASK		BIT(18)	/* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD41_BURST	BIT(18)	/* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD41_NBURST	0	/* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD40_MASK		BIT(17)	/* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD40_SINGLE		BIT(17)	/* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD40_MULTI		0	/* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD40_MASK		BIT(16)	/* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD40_BURST	BIT(16)	/* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD40_NBURST	0	/* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD39_MASK		BIT(15)	/* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD39_SINGLE		BIT(15)	/* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD39_MULTI		0	/* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD39_MASK		BIT(14)	/* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD39_BURST	BIT(14)	/* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD39_NBURST	0	/* SDHI3 */
+#define HPB_DMAE_ASYNCMDR_ASMD27_MASK		BIT(13)	/* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD27_SINGLE		BIT(13)	/* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD27_MULTI		0	/* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD27_MASK		BIT(12)	/* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD27_BURST	BIT(12)	/* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD27_NBURST	0	/* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD26_MASK		BIT(11)	/* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD26_SINGLE		BIT(11)	/* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD26_MULTI		0	/* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD26_MASK		BIT(10)	/* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD26_BURST	BIT(10)	/* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD26_NBURST	0	/* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD25_MASK		BIT(9)	/* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD25_SINGLE		BIT(9)	/* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD25_MULTI		0	/* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD25_MASK		BIT(8)	/* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD25_BURST	BIT(8)	/* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD25_NBURST	0	/* SDHI2 */
+#define HPB_DMAE_ASYNCMDR_ASMD23_MASK		BIT(7)	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD23_SINGLE		BIT(7)	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD23_MULTI		0	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD23_MASK		BIT(6)	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD23_BURST	BIT(6)	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD23_NBURST	0	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD22_MASK		BIT(5)	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD22_SINGLE		BIT(5)	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD22_MULTI		0	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD22_MASK		BIT(4)	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD22_BURST	BIT(4)	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD22_NBURST	0	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD21_MASK		BIT(3)	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD21_SINGLE		BIT(3)	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD21_MULTI		0	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD21_MASK		BIT(2)	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD21_BURST	BIT(2)	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD21_NBURST	0	/* SDHI0 */
+#define HPB_DMAE_ASYNCMDR_ASMD20_MASK		BIT(1)	/* SDHI1 */
+#define HPB_DMAE_ASYNCMDR_ASMD20_SINGLE		BIT(1)	/* SDHI1 */
+#define HPB_DMAE_ASYNCMDR_ASMD20_MULTI		0	/* SDHI1 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD20_MASK		BIT(0)	/* SDHI1 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD20_BURST	BIT(0)	/* SDHI1 */
+#define HPB_DMAE_ASYNCMDR_ASBTMD20_NBURST	0	/* SDHI1 */
+
+static const struct hpb_dmae_slave_config hpb_dmae_slaves[] = {
+	{
+		.id	= HPBDMA_SLAVE_SDHI0_TX,
+		.addr	= 0xffe4c000 + 0x30,
+		.dcr	= HPB_DMAE_DCR_SPDS_16BIT |
+			  HPB_DMAE_DCR_DMDL |
+			  HPB_DMAE_DCR_DPDS_16BIT,
+		.rstr	= HPB_DMAE_ASYNCRSTR_ASRST21 |
+			  HPB_DMAE_ASYNCRSTR_ASRST22 |
+			  HPB_DMAE_ASYNCRSTR_ASRST23,
+		.mdr	= HPB_DMAE_ASYNCMDR_ASMD21_SINGLE |
+			  HPB_DMAE_ASYNCMDR_ASBTMD21_NBURST,
+		.mdm	= HPB_DMAE_ASYNCMDR_ASMD21_MASK |
+			  HPB_DMAE_ASYNCMDR_ASBTMD21_MASK,
+		.port	= 0x0D0C,
+		.flags	= HPB_DMAE_SET_ASYNC_RESET | HPB_DMAE_SET_ASYNC_MODE,
+		.dma_ch	= 21,
+	}, {
+		.id	= HPBDMA_SLAVE_SDHI0_RX,
+		.addr	= 0xffe4c000 + 0x30,
+		.dcr	= HPB_DMAE_DCR_SMDL |
+			  HPB_DMAE_DCR_SPDS_16BIT |
+			  HPB_DMAE_DCR_DPDS_16BIT,
+		.rstr	= HPB_DMAE_ASYNCRSTR_ASRST21 |
+			  HPB_DMAE_ASYNCRSTR_ASRST22 |
+			  HPB_DMAE_ASYNCRSTR_ASRST23,
+		.mdr	= HPB_DMAE_ASYNCMDR_ASMD22_SINGLE |
+			  HPB_DMAE_ASYNCMDR_ASBTMD22_NBURST,
+		.mdm	= HPB_DMAE_ASYNCMDR_ASMD22_MASK |
+			  HPB_DMAE_ASYNCMDR_ASBTMD22_MASK,
+		.port	= 0x0D0C,
+		.flags	= HPB_DMAE_SET_ASYNC_RESET | HPB_DMAE_SET_ASYNC_MODE,
+		.dma_ch	= 22,
+	},
+};
+
+static const struct hpb_dmae_channel hpb_dmae_channels[] = {
+	HPB_DMAE_CHANNEL(0x93, HPBDMA_SLAVE_SDHI0_TX), /* ch. 21 */
+	HPB_DMAE_CHANNEL(0x93, HPBDMA_SLAVE_SDHI0_RX), /* ch. 22 */
+};
+
+static struct hpb_dmae_pdata dma_platform_data __initdata = {
+	.slaves			= hpb_dmae_slaves,
+	.num_slaves		= ARRAY_SIZE(hpb_dmae_slaves),
+	.channels		= hpb_dmae_channels,
+	.num_channels		= ARRAY_SIZE(hpb_dmae_channels),
+	.ts_shift		= {
+		[XMIT_SZ_8BIT]	= 0,
+		[XMIT_SZ_16BIT]	= 1,
+		[XMIT_SZ_32BIT]	= 2,
+	},
+	.num_hw_channels	= 44,
+};
+
+static struct resource hpb_dmae_resources[] __initdata = {
+	/* Channel registers */
+	DEFINE_RES_MEM(0xffc08000, 0x1000),
+	/* Common registers */
+	DEFINE_RES_MEM(0xffc09000, 0x170),
+	/* Asynchronous reset registers */
+	DEFINE_RES_MEM(0xffc00300, 4),
+	/* Asynchronous mode registers */
+	DEFINE_RES_MEM(0xffc00400, 4),
+	/* IRQ for DMA channels */
+	DEFINE_RES_NAMED(gic_iid(0x8e), 12, NULL, IORESOURCE_IRQ),
+};
+
+static void __init r8a7779_register_hpb_dmae(void)
+{
+	platform_device_register_resndata(&platform_bus, "hpb-dma-engine", -1,
+					  hpb_dmae_resources,
+					  ARRAY_SIZE(hpb_dmae_resources),
+					  &dma_platform_data,
+					  sizeof(dma_platform_data));
+}
+
 static struct platform_device *r8a7779_devices_dt[] __initdata = {
 	&scif0_device,
 	&scif1_device,
@@ -665,6 +822,7 @@
 			    ARRAY_SIZE(r8a7779_devices_dt));
 	platform_add_devices(r8a7779_standard_devices,
 			    ARRAY_SIZE(r8a7779_standard_devices));
+	r8a7779_register_hpb_dmae();
 }
 
 void __init r8a7779_add_ether_device(struct sh_eth_plat_data *pdata)
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c
index d0f5c9f..c47bcebb 100644
--- a/arch/arm/mach-shmobile/setup-r8a7790.c
+++ b/arch/arm/mach-shmobile/setup-r8a7790.c
@@ -18,7 +18,6 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <linux/clocksource.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/of_platform.h>
@@ -31,17 +30,18 @@
 #include <mach/r8a7790.h>
 #include <asm/mach/arch.h>
 
-static struct resource pfc_resources[] __initdata = {
+static const struct resource pfc_resources[] __initconst = {
 	DEFINE_RES_MEM(0xe6060000, 0x250),
 };
 
 #define R8A7790_GPIO(idx)						\
-static struct resource r8a7790_gpio##idx##_resources[] __initdata = {	\
+static const struct resource r8a7790_gpio##idx##_resources[] __initconst = { \
 	DEFINE_RES_MEM(0xe6050000 + 0x1000 * (idx), 0x50),		\
 	DEFINE_RES_IRQ(gic_spi(4 + (idx))),				\
 };									\
 									\
-static struct gpio_rcar_config r8a7790_gpio##idx##_platform_data __initdata = {	\
+static const struct gpio_rcar_config					\
+r8a7790_gpio##idx##_platform_data __initconst = {			\
 	.gpio_base	= 32 * (idx),					\
 	.irq_base	= 0,						\
 	.number_of_pins	= 32,						\
@@ -112,7 +112,7 @@
 enum { SCIFA0, SCIFA1, SCIFB0, SCIFB1, SCIFB2, SCIFA2, SCIF0, SCIF1,
        HSCIF0, HSCIF1 };
 
-static struct plat_sci_port scif[] __initdata = {
+static const struct plat_sci_port scif[] __initconst = {
 	SCIFA_DATA(SCIFA0, 0xe6c40000, gic_spi(144)), /* SCIFA0 */
 	SCIFA_DATA(SCIFA1, 0xe6c50000, gic_spi(145)), /* SCIFA1 */
 	SCIFB_DATA(SCIFB0, 0xe6c20000, gic_spi(148)), /* SCIFB0 */
@@ -131,11 +131,11 @@
 				      sizeof(struct plat_sci_port));
 }
 
-static struct renesas_irqc_config irqc0_data __initdata = {
+static const struct renesas_irqc_config irqc0_data __initconst = {
 	.irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
 };
 
-static struct resource irqc0_resources[] __initdata = {
+static const struct resource irqc0_resources[] __initconst = {
 	DEFINE_RES_MEM(0xe61c0000, 0x200), /* IRQC Event Detector Block_0 */
 	DEFINE_RES_IRQ(gic_spi(0)), /* IRQ0 */
 	DEFINE_RES_IRQ(gic_spi(1)), /* IRQ1 */
@@ -150,7 +150,7 @@
 					  &irqc##idx##_data,		\
 					  sizeof(struct renesas_irqc_config))
 
-static struct resource thermal_resources[] __initdata = {
+static const struct resource thermal_resources[] __initconst = {
 	DEFINE_RES_MEM(0xe61f0000, 0x14),
 	DEFINE_RES_MEM(0xe61f0100, 0x38),
 	DEFINE_RES_IRQ(gic_spi(69)),
@@ -161,13 +161,13 @@
 					thermal_resources,		\
 					ARRAY_SIZE(thermal_resources))
 
-static struct sh_timer_config cmt00_platform_data __initdata = {
+static const struct sh_timer_config cmt00_platform_data __initconst = {
 	.name = "CMT00",
 	.timer_bit = 0,
 	.clockevent_rating = 80,
 };
 
-static struct resource cmt00_resources[] __initdata = {
+static const struct resource cmt00_resources[] __initconst = {
 	DEFINE_RES_MEM(0xffca0510, 0x0c),
 	DEFINE_RES_MEM(0xffca0500, 0x04),
 	DEFINE_RES_IRQ(gic_spi(142)), /* CMT0_0 */
@@ -202,72 +202,7 @@
 	r8a7790_register_thermal();
 }
 
-#define MODEMR 0xe6160060
-
-u32 __init r8a7790_read_mode_pins(void)
-{
-	void __iomem *modemr = ioremap_nocache(MODEMR, 4);
-	u32 mode;
-
-	BUG_ON(!modemr);
-	mode = ioread32(modemr);
-	iounmap(modemr);
-
-	return mode;
-}
-
-#define CNTCR 0
-#define CNTFID0 0x20
-
-void __init r8a7790_timer_init(void)
-{
-#ifdef CONFIG_ARM_ARCH_TIMER
-	u32 mode = r8a7790_read_mode_pins();
-	void __iomem *base;
-	int extal_mhz = 0;
-	u32 freq;
-
-	/* At Linux boot time the r8a7790 arch timer comes up
-	 * with the counter disabled. Moreover, it may also report
-	 * a potentially incorrect fixed 13 MHz frequency. To be
-	 * correct these registers need to be updated to use the
-	 * frequency EXTAL / 2 which can be determined by the MD pins.
-	 */
-
-	switch (mode & (MD(14) | MD(13))) {
-	case 0:
-		extal_mhz = 15;
-		break;
-	case MD(13):
-		extal_mhz = 20;
-		break;
-	case MD(14):
-		extal_mhz = 26;
-		break;
-	case MD(13) | MD(14):
-		extal_mhz = 30;
-		break;
-	}
-
-	/* The arch timer frequency equals EXTAL / 2 */
-	freq = extal_mhz * (1000000 / 2);
-
-	/* Remap "armgcnt address map" space */
-	base = ioremap(0xe6080000, PAGE_SIZE);
-
-	/* Update registers with correct frequency */
-	iowrite32(freq, base + CNTFID0);
-	asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq));
-
-	/* make sure arch timer is started by setting bit 0 of CNTCR */
-	iowrite32(1, base + CNTCR);
-	iounmap(base);
-#endif /* CONFIG_ARM_ARCH_TIMER */
-
-	clocksource_of_init();
-}
-
-void __init r8a7790_init_delay(void)
+void __init r8a7790_init_early(void)
 {
 #ifndef CONFIG_ARM_ARCH_TIMER
 	shmobile_setup_delay(1300, 2, 4); /* Cortex-A15 @ 1300MHz */
@@ -276,14 +211,15 @@
 
 #ifdef CONFIG_USE_OF
 
-static const char *r8a7790_boards_compat_dt[] __initdata = {
+static const char * const r8a7790_boards_compat_dt[] __initconst = {
 	"renesas,r8a7790",
 	NULL,
 };
 
 DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)")
-	.init_early	= r8a7790_init_delay,
-	.init_time	= r8a7790_timer_init,
+	.smp		= smp_ops(r8a7790_smp_ops),
+	.init_early	= r8a7790_init_early,
+	.init_time	= rcar_gen2_timer_init,
 	.dt_compat	= r8a7790_boards_compat_dt,
 MACHINE_END
 #endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-r8a7791.c b/arch/arm/mach-shmobile/setup-r8a7791.c
new file mode 100644
index 0000000..d9393d6
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-r8a7791.c
@@ -0,0 +1,184 @@
+/*
+ * r8a7791 processor support
+ *
+ * Copyright (C) 2013  Renesas Electronics Corporation
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/of_platform.h>
+#include <linux/platform_data/irq-renesas-irqc.h>
+#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <mach/common.h>
+#include <mach/irqs.h>
+#include <mach/r8a7791.h>
+#include <mach/rcar-gen2.h>
+#include <asm/mach/arch.h>
+
+#define SCIF_COMMON(scif_type, baseaddr, irq)			\
+	.type		= scif_type,				\
+	.mapbase	= baseaddr,				\
+	.flags		= UPF_BOOT_AUTOCONF | UPF_IOREMAP,	\
+	.irqs		= SCIx_IRQ_MUXED(irq)
+
+#define SCIFA_DATA(index, baseaddr, irq)		\
+[index] = {						\
+	SCIF_COMMON(PORT_SCIFA, baseaddr, irq),		\
+	.scbrr_algo_id	= SCBRR_ALGO_4,			\
+	.scscr = SCSCR_RE | SCSCR_TE,	\
+}
+
+#define SCIFB_DATA(index, baseaddr, irq)	\
+[index] = {					\
+	SCIF_COMMON(PORT_SCIFB, baseaddr, irq),	\
+	.scbrr_algo_id	= SCBRR_ALGO_4,		\
+	.scscr = SCSCR_RE | SCSCR_TE,		\
+}
+
+#define SCIF_DATA(index, baseaddr, irq)		\
+[index] = {						\
+	SCIF_COMMON(PORT_SCIF, baseaddr, irq),		\
+	.scbrr_algo_id	= SCBRR_ALGO_2,			\
+	.scscr = SCSCR_RE | SCSCR_TE,	\
+}
+
+#define HSCIF_DATA(index, baseaddr, irq)		\
+[index] = {						\
+	SCIF_COMMON(PORT_HSCIF, baseaddr, irq),		\
+	.scbrr_algo_id	= SCBRR_ALGO_6,			\
+	.scscr = SCSCR_RE | SCSCR_TE,	\
+}
+
+enum { SCIFA0, SCIFA1, SCIFB0, SCIFB1, SCIFB2, SCIFA2, SCIF0, SCIF1,
+	SCIF2, SCIF3, SCIF4, SCIF5, SCIFA3, SCIFA4, SCIFA5 };
+
+static const struct plat_sci_port scif[] __initconst = {
+	SCIFA_DATA(SCIFA0, 0xe6c40000, gic_spi(144)), /* SCIFA0 */
+	SCIFA_DATA(SCIFA1, 0xe6c50000, gic_spi(145)), /* SCIFA1 */
+	SCIFB_DATA(SCIFB0, 0xe6c20000, gic_spi(148)), /* SCIFB0 */
+	SCIFB_DATA(SCIFB1, 0xe6c30000, gic_spi(149)), /* SCIFB1 */
+	SCIFB_DATA(SCIFB2, 0xe6ce0000, gic_spi(150)), /* SCIFB2 */
+	SCIFA_DATA(SCIFA2, 0xe6c60000, gic_spi(151)), /* SCIFA2 */
+	SCIF_DATA(SCIF0, 0xe6e60000, gic_spi(152)), /* SCIF0 */
+	SCIF_DATA(SCIF1, 0xe6e68000, gic_spi(153)), /* SCIF1 */
+	SCIF_DATA(SCIF2, 0xe6e58000, gic_spi(22)), /* SCIF2 */
+	SCIF_DATA(SCIF3, 0xe6ea8000, gic_spi(23)), /* SCIF3 */
+	SCIF_DATA(SCIF4, 0xe6ee0000, gic_spi(24)), /* SCIF4 */
+	SCIF_DATA(SCIF5, 0xe6ee8000, gic_spi(25)), /* SCIF5 */
+	SCIFA_DATA(SCIFA3, 0xe6c70000, gic_spi(29)), /* SCIFA3 */
+	SCIFA_DATA(SCIFA4, 0xe6c78000, gic_spi(30)), /* SCIFA4 */
+	SCIFA_DATA(SCIFA5, 0xe6c80000, gic_spi(31)), /* SCIFA5 */
+};
+
+static inline void r8a7791_register_scif(int idx)
+{
+	platform_device_register_data(&platform_bus, "sh-sci", idx, &scif[idx],
+				      sizeof(struct plat_sci_port));
+}
+
+static const struct sh_timer_config cmt00_platform_data __initconst = {
+	.name = "CMT00",
+	.timer_bit = 0,
+	.clockevent_rating = 80,
+};
+
+static const struct resource cmt00_resources[] __initconst = {
+	DEFINE_RES_MEM(0xffca0510, 0x0c),
+	DEFINE_RES_MEM(0xffca0500, 0x04),
+	DEFINE_RES_IRQ(gic_spi(142)), /* CMT0_0 */
+};
+
+#define r8a7791_register_cmt(idx)					\
+	platform_device_register_resndata(&platform_bus, "sh_cmt",	\
+					  idx, cmt##idx##_resources,	\
+					  ARRAY_SIZE(cmt##idx##_resources), \
+					  &cmt##idx##_platform_data,	\
+					  sizeof(struct sh_timer_config))
+
+static struct renesas_irqc_config irqc0_data = {
+	.irq_base = irq_pin(0), /* IRQ0 -> IRQ9 */
+};
+
+static struct resource irqc0_resources[] = {
+	DEFINE_RES_MEM(0xe61c0000, 0x200), /* IRQC Event Detector Block_0 */
+	DEFINE_RES_IRQ(gic_spi(0)), /* IRQ0 */
+	DEFINE_RES_IRQ(gic_spi(1)), /* IRQ1 */
+	DEFINE_RES_IRQ(gic_spi(2)), /* IRQ2 */
+	DEFINE_RES_IRQ(gic_spi(3)), /* IRQ3 */
+	DEFINE_RES_IRQ(gic_spi(12)), /* IRQ4 */
+	DEFINE_RES_IRQ(gic_spi(13)), /* IRQ5 */
+	DEFINE_RES_IRQ(gic_spi(14)), /* IRQ6 */
+	DEFINE_RES_IRQ(gic_spi(15)), /* IRQ7 */
+	DEFINE_RES_IRQ(gic_spi(16)), /* IRQ8 */
+	DEFINE_RES_IRQ(gic_spi(17)), /* IRQ9 */
+};
+
+#define r8a7791_register_irqc(idx)					\
+	platform_device_register_resndata(&platform_bus, "renesas_irqc", \
+					  idx, irqc##idx##_resources,	\
+					  ARRAY_SIZE(irqc##idx##_resources), \
+					  &irqc##idx##_data,		\
+					  sizeof(struct renesas_irqc_config))
+
+void __init r8a7791_add_dt_devices(void)
+{
+	r8a7791_register_scif(SCIFA0);
+	r8a7791_register_scif(SCIFA1);
+	r8a7791_register_scif(SCIFB0);
+	r8a7791_register_scif(SCIFB1);
+	r8a7791_register_scif(SCIFB2);
+	r8a7791_register_scif(SCIFA2);
+	r8a7791_register_scif(SCIF0);
+	r8a7791_register_scif(SCIF1);
+	r8a7791_register_scif(SCIF2);
+	r8a7791_register_scif(SCIF3);
+	r8a7791_register_scif(SCIF4);
+	r8a7791_register_scif(SCIF5);
+	r8a7791_register_scif(SCIFA3);
+	r8a7791_register_scif(SCIFA4);
+	r8a7791_register_scif(SCIFA5);
+	r8a7791_register_cmt(00);
+}
+
+void __init r8a7791_add_standard_devices(void)
+{
+	r8a7791_add_dt_devices();
+	r8a7791_register_irqc(0);
+}
+
+void __init r8a7791_init_early(void)
+{
+#ifndef CONFIG_ARM_ARCH_TIMER
+	shmobile_setup_delay(1300, 2, 4); /* Cortex-A15 @ 1300MHz */
+#endif
+}
+
+#ifdef CONFIG_USE_OF
+static const char *r8a7791_boards_compat_dt[] __initdata = {
+	"renesas,r8a7791",
+	NULL,
+};
+
+DT_MACHINE_START(R8A7791_DT, "Generic R8A7791 (Flattened Device Tree)")
+	.smp		= smp_ops(r8a7791_smp_ops),
+	.init_early	= r8a7791_init_early,
+	.init_time	= rcar_gen2_timer_init,
+	.dt_compat	= r8a7791_boards_compat_dt,
+MACHINE_END
+#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c
new file mode 100644
index 0000000..5734c24
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c
@@ -0,0 +1,91 @@
+/*
+ * R-Car Generation 2 support
+ *
+ * Copyright (C) 2013  Renesas Solutions Corp.
+ * Copyright (C) 2013  Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/clocksource.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <mach/common.h>
+#include <mach/rcar-gen2.h>
+#include <asm/mach/arch.h>
+
+#define MODEMR 0xe6160060
+
+u32 __init rcar_gen2_read_mode_pins(void)
+{
+	void __iomem *modemr = ioremap_nocache(MODEMR, 4);
+	u32 mode;
+
+	BUG_ON(!modemr);
+	mode = ioread32(modemr);
+	iounmap(modemr);
+
+	return mode;
+}
+
+#define CNTCR 0
+#define CNTFID0 0x20
+
+void __init rcar_gen2_timer_init(void)
+{
+#ifdef CONFIG_ARM_ARCH_TIMER
+	u32 mode = rcar_gen2_read_mode_pins();
+	void __iomem *base;
+	int extal_mhz = 0;
+	u32 freq;
+
+	/* At Linux boot time the r8a7790 arch timer comes up
+	 * with the counter disabled. Moreover, it may also report
+	 * a potentially incorrect fixed 13 MHz frequency. To be
+	 * correct these registers need to be updated to use the
+	 * frequency EXTAL / 2 which can be determined by the MD pins.
+	 */
+
+	switch (mode & (MD(14) | MD(13))) {
+	case 0:
+		extal_mhz = 15;
+		break;
+	case MD(13):
+		extal_mhz = 20;
+		break;
+	case MD(14):
+		extal_mhz = 26;
+		break;
+	case MD(13) | MD(14):
+		extal_mhz = 30;
+		break;
+	}
+
+	/* The arch timer frequency equals EXTAL / 2 */
+	freq = extal_mhz * (1000000 / 2);
+
+	/* Remap "armgcnt address map" space */
+	base = ioremap(0xe6080000, PAGE_SIZE);
+
+	/* Update registers with correct frequency */
+	iowrite32(freq, base + CNTFID0);
+	asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq));
+
+	/* make sure arch timer is started by setting bit 0 of CNTCR */
+	iowrite32(1, base + CNTCR);
+	iounmap(base);
+#endif /* CONFIG_ARM_ARCH_TIMER */
+
+	clocksource_of_init();
+}
diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c
index 522de5e..f2ca923 100644
--- a/arch/arm/mach-shmobile/smp-emev2.c
+++ b/arch/arm/mach-shmobile/smp-emev2.c
@@ -34,12 +34,6 @@
 
 static int emev2_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-	int ret;
-
-	ret = shmobile_smp_scu_boot_secondary(cpu, idle);
-	if (ret)
-		return ret;
-
 	arch_send_wakeup_ipi_mask(cpumask_of(cpu_logical_map(cpu)));
 	return 0;
 }
diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c
index 0f05e9f..627c1f0 100644
--- a/arch/arm/mach-shmobile/smp-r8a7779.c
+++ b/arch/arm/mach-shmobile/smp-r8a7779.c
@@ -87,10 +87,6 @@
 	unsigned int lcpu = cpu_logical_map(cpu);
 	int ret;
 
-	ret = shmobile_smp_scu_boot_secondary(cpu, idle);
-	if (ret)
-		return ret;
-
 	if (lcpu < ARRAY_SIZE(r8a7779_ch_cpu))
 		ch = r8a7779_ch_cpu[lcpu];
 
diff --git a/arch/arm/mach-shmobile/smp-r8a7790.c b/arch/arm/mach-shmobile/smp-r8a7790.c
new file mode 100644
index 0000000..015e275
--- /dev/null
+++ b/arch/arm/mach-shmobile/smp-r8a7790.c
@@ -0,0 +1,67 @@
+/*
+ * SMP support for r8a7790
+ *
+ * Copyright (C) 2012-2013 Renesas Solutions Corp.
+ * Copyright (C) 2012 Takashi Yoshii <takashi.yoshii.ze@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <asm/smp_plat.h>
+#include <mach/common.h>
+
+#define RST		0xe6160000
+#define CA15BAR		0x0020
+#define CA7BAR		0x0030
+#define CA15RESCNT	0x0040
+#define CA7RESCNT	0x0044
+#define MERAM		0xe8080000
+
+static void __init r8a7790_smp_prepare_cpus(unsigned int max_cpus)
+{
+	void __iomem *p;
+	u32 bar;
+
+	/* let APMU code install data related to shmobile_boot_vector */
+	shmobile_smp_apmu_prepare_cpus(max_cpus);
+
+	/* MERAM for jump stub, because BAR requires 256KB aligned address */
+	p = ioremap_nocache(MERAM, shmobile_boot_size);
+	memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
+	iounmap(p);
+
+	/* setup reset vectors */
+	p = ioremap_nocache(RST, 0x63);
+	bar = (MERAM >> 8) & 0xfffffc00;
+	writel_relaxed(bar, p + CA15BAR);
+	writel_relaxed(bar, p + CA7BAR);
+	writel_relaxed(bar | 0x10, p + CA15BAR);
+	writel_relaxed(bar | 0x10, p + CA7BAR);
+
+	/* enable clocks to all CPUs */
+	writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) | 0xa5a50000,
+		       p + CA15RESCNT);
+	writel_relaxed((readl_relaxed(p + CA7RESCNT) & ~0x0f) | 0x5a5a0000,
+		       p + CA7RESCNT);
+	iounmap(p);
+}
+
+struct smp_operations r8a7790_smp_ops __initdata = {
+	.smp_prepare_cpus	= r8a7790_smp_prepare_cpus,
+	.smp_boot_secondary	= shmobile_smp_apmu_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_disable		= shmobile_smp_cpu_disable,
+	.cpu_die		= shmobile_smp_apmu_cpu_die,
+	.cpu_kill		= shmobile_smp_apmu_cpu_kill,
+#endif
+};
diff --git a/arch/arm/mach-shmobile/smp-r8a7791.c b/arch/arm/mach-shmobile/smp-r8a7791.c
new file mode 100644
index 0000000..2df5bd1
--- /dev/null
+++ b/arch/arm/mach-shmobile/smp-r8a7791.c
@@ -0,0 +1,62 @@
+/*
+ * SMP support for r8a7791
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <asm/smp_plat.h>
+#include <mach/common.h>
+#include <mach/r8a7791.h>
+
+#define RST		0xe6160000
+#define CA15BAR		0x0020
+#define CA15RESCNT	0x0040
+#define RAM		0xe6300000
+
+static void __init r8a7791_smp_prepare_cpus(unsigned int max_cpus)
+{
+	void __iomem *p;
+	u32 bar;
+
+	/* let APMU code install data related to shmobile_boot_vector */
+	shmobile_smp_apmu_prepare_cpus(max_cpus);
+
+	/* RAM for jump stub, because BAR requires 256KB aligned address */
+	p = ioremap_nocache(RAM, shmobile_boot_size);
+	memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
+	iounmap(p);
+
+	/* setup reset vectors */
+	p = ioremap_nocache(RST, 0x63);
+	bar = (RAM >> 8) & 0xfffffc00;
+	writel_relaxed(bar, p + CA15BAR);
+	writel_relaxed(bar | 0x10, p + CA15BAR);
+
+	/* enable clocks to all CPUs */
+	writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) | 0xa5a50000,
+		       p + CA15RESCNT);
+	iounmap(p);
+}
+
+struct smp_operations r8a7791_smp_ops __initdata = {
+	.smp_prepare_cpus	= r8a7791_smp_prepare_cpus,
+	.smp_boot_secondary	= shmobile_smp_apmu_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_disable		= shmobile_smp_cpu_disable,
+	.cpu_die		= shmobile_smp_apmu_cpu_die,
+	.cpu_kill		= shmobile_smp_apmu_cpu_kill,
+#endif
+};
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
index 0baa244..13ba36a 100644
--- a/arch/arm/mach-shmobile/smp-sh73a0.c
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -46,11 +46,6 @@
 static int sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	unsigned int lcpu = cpu_logical_map(cpu);
-	int ret;
-
-	ret = shmobile_smp_scu_boot_secondary(cpu, idle);
-	if (ret)
-		return ret;
 
 	if (((__raw_readl(PSTR) >> (4 * lcpu)) & 3) == 3)
 		__raw_writel(1 << lcpu, WUPCR);	/* wake up */
@@ -71,18 +66,11 @@
 	shmobile_smp_scu_prepare_cpus(max_cpus);
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-static int sh73a0_cpu_disable(unsigned int cpu)
-{
-	return 0; /* CPU0 and CPU1 supported */
-}
-#endif /* CONFIG_HOTPLUG_CPU */
-
 struct smp_operations sh73a0_smp_ops __initdata = {
 	.smp_prepare_cpus	= sh73a0_smp_prepare_cpus,
 	.smp_boot_secondary	= sh73a0_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
-	.cpu_disable		= sh73a0_cpu_disable,
+	.cpu_disable		= shmobile_smp_cpu_disable,
 	.cpu_die		= shmobile_smp_scu_cpu_die,
 	.cpu_kill		= shmobile_smp_scu_cpu_kill,
 #endif
diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig
index dd86db4..037100a 100644
--- a/arch/arm/mach-socfpga/Kconfig
+++ b/arch/arm/mach-socfpga/Kconfig
@@ -4,7 +4,6 @@
 	select ARM_AMBA
 	select ARM_GIC
 	select CACHE_L2X0
-	select CLKDEV_LOOKUP
 	select COMMON_CLK
 	select CPU_V7
 	select DW_APB_TIMER_OF
diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c
index bfce964..dd0d49c 100644
--- a/arch/arm/mach-socfpga/socfpga.c
+++ b/arch/arm/mach-socfpga/socfpga.c
@@ -14,7 +14,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-#include <linux/clk-provider.h>
 #include <linux/irqchip.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -107,7 +106,6 @@
 {
 	l2x0_of_init(0, ~0UL);
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-	of_clk_init(NULL);
 	socfpga_init_clocks();
 }
 
diff --git a/arch/arm/mach-spear/Kconfig b/arch/arm/mach-spear/Kconfig
index df0d59a..ac1710e6 100644
--- a/arch/arm/mach-spear/Kconfig
+++ b/arch/arm/mach-spear/Kconfig
@@ -7,11 +7,9 @@
 	default PLAT_SPEAR_SINGLE
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_AMBA
-	select CLKDEV_LOOKUP
 	select CLKSRC_MMIO
 	select COMMON_CLK
 	select GENERIC_CLOCKEVENTS
-	select HAVE_CLK
 
 if PLAT_SPEAR
 
diff --git a/arch/arm/mach-sti/board-dt.c b/arch/arm/mach-sti/board-dt.c
index 8fe6f0c..1217fb5 100644
--- a/arch/arm/mach-sti/board-dt.c
+++ b/arch/arm/mach-sti/board-dt.c
@@ -7,9 +7,8 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/clk-provider.h>
-#include <linux/clocksource.h>
 #include <linux/irq.h>
+#include <linux/of_platform.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/arch.h>
 
@@ -28,11 +27,10 @@
 	l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK);
 }
 
-static void __init stih41x_timer_init(void)
+static void __init stih41x_machine_init(void)
 {
-	of_clk_init(NULL);
-	clocksource_of_init();
 	stih41x_l2x0_init();
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static const char *stih41x_dt_match[] __initdata = {
@@ -42,7 +40,7 @@
 };
 
 DT_MACHINE_START(STM, "STiH415/416 SoC with Flattened Device Tree")
-	.init_time	= stih41x_timer_init,
+	.init_machine	= stih41x_machine_init,
 	.smp		= smp_ops(sti_smp_ops),
 	.dt_compat	= stih41x_dt_match,
 MACHINE_END
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 3ab2f65..c9e72c8 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -1,14 +1,14 @@
 config ARCH_SUNXI
 	bool "Allwinner A1X SOCs" if ARCH_MULTI_V7
 	select ARCH_REQUIRE_GPIOLIB
+	select ARM_GIC
 	select CLKSRC_MMIO
 	select CLKSRC_OF
 	select COMMON_CLK
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_IRQ_CHIP
+	select HAVE_SMP
 	select PINCTRL
+	select PINCTRL_SUNXI
 	select SPARSE_IRQ
 	select SUN4I_TIMER
-	select PINCTRL_SUNXI
-	select ARM_GIC
-	select HAVE_SMP
diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c
index e79fb34..61d3a38 100644
--- a/arch/arm/mach-sunxi/sunxi.c
+++ b/arch/arm/mach-sunxi/sunxi.c
@@ -10,7 +10,6 @@
  * warranty of any kind, whether express or implied.
  */
 
-#include <linux/clocksource.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -20,8 +19,6 @@
 #include <linux/io.h>
 #include <linux/reboot.h>
 
-#include <linux/clk/sunxi.h>
-
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/system_misc.h>
@@ -93,14 +90,13 @@
 }
 
 static struct of_device_id sunxi_restart_ids[] = {
-	{ .compatible = "allwinner,sun4i-wdt", .data = sun4i_restart },
-	{ .compatible = "allwinner,sun6i-wdt", .data = sun6i_restart },
+	{ .compatible = "allwinner,sun4i-wdt" },
+	{ .compatible = "allwinner,sun6i-wdt" },
 	{ /*sentinel*/ }
 };
 
 static void sunxi_setup_restart(void)
 {
-	const struct of_device_id *of_id;
 	struct device_node *np;
 
 	np = of_find_matching_node(NULL, sunxi_restart_ids);
@@ -109,17 +105,6 @@
 
 	wdt_base = of_iomap(np, 0);
 	WARN(!wdt_base, "failed to map watchdog base address");
-
-	of_id = of_match_node(sunxi_restart_ids, np);
-	WARN(!of_id, "restart function not available");
-
-	arm_pm_restart = of_id->data;
-}
-
-static void __init sunxi_timer_init(void)
-{
-	sunxi_init_clocks();
-	clocksource_of_init();
 }
 
 static void __init sunxi_dt_init(void)
@@ -133,13 +118,33 @@
 	"allwinner,sun4i-a10",
 	"allwinner,sun5i-a10s",
 	"allwinner,sun5i-a13",
-	"allwinner,sun6i-a31",
-	"allwinner,sun7i-a20",
 	NULL,
 };
 
 DT_MACHINE_START(SUNXI_DT, "Allwinner A1X (Device Tree)")
 	.init_machine	= sunxi_dt_init,
-	.init_time	= sunxi_timer_init,
 	.dt_compat	= sunxi_board_dt_compat,
+	.restart	= sun4i_restart,
+MACHINE_END
+
+static const char * const sun6i_board_dt_compat[] = {
+	"allwinner,sun6i-a31",
+	NULL,
+};
+
+DT_MACHINE_START(SUN6I_DT, "Allwinner sun6i (A31) Family")
+	.init_machine	= sunxi_dt_init,
+	.dt_compat	= sun6i_board_dt_compat,
+	.restart	= sun6i_restart,
+MACHINE_END
+
+static const char * const sun7i_board_dt_compat[] = {
+	"allwinner,sun7i-a20",
+	NULL,
+};
+
+DT_MACHINE_START(SUN7I_DT, "Allwinner sun7i (A20) Family")
+	.init_machine	= sunxi_dt_init,
+	.dt_compat	= sun7i_board_dt_compat,
+	.restart	= sun4i_restart,
 MACHINE_END
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 67a76f2..0bf04a0 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -3,7 +3,6 @@
 	select ARCH_HAS_CPUFREQ
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_GIC
-	select CLKDEV_LOOKUP
 	select CLKSRC_MMIO
 	select CLKSRC_OF
 	select COMMON_CLK
@@ -11,7 +10,6 @@
 	select GENERIC_CLOCKEVENTS
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
-	select HAVE_CLK
 	select HAVE_SMP
 	select MIGHT_HAVE_CACHE_L2X0
 	select MIGHT_HAVE_PCI
@@ -53,14 +51,22 @@
 
 config ARCH_TEGRA_114_SOC
 	bool "Enable support for Tegra114 family"
-	select HAVE_ARM_ARCH_TIMER
 	select ARM_ERRATA_798181
 	select ARM_L1_CACHE_SHIFT_6
+	select HAVE_ARM_ARCH_TIMER
 	select PINCTRL_TEGRA114
 	help
 	  Support for NVIDIA Tegra T114 processor family, based on the
 	  ARM CortexA15MP CPU
 
+config ARCH_TEGRA_124_SOC
+	bool "Enable support for Tegra124 family"
+	select ARM_L1_CACHE_SHIFT_6
+	select HAVE_ARM_ARCH_TIMER
+	help
+	  Support for NVIDIA Tegra T124 processor family, based on the
+	  ARM CortexA15MP CPU
+
 config TEGRA_AHB
 	bool "Enable AHB driver for NVIDIA Tegra SoCs"
 	default y
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index e7e5f45..019bb17 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -1,6 +1,5 @@
 asflags-y				+= -march=armv7-a
 
-obj-y                                   += common.o
 obj-y                                   += io.o
 obj-y                                   += irq.o
 obj-y					+= fuse.o
@@ -36,5 +35,10 @@
 ifeq ($(CONFIG_CPU_IDLE),y)
 obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= cpuidle-tegra114.o
 endif
+obj-$(CONFIG_ARCH_TEGRA_124_SOC)	+= sleep-tegra30.o
+obj-$(CONFIG_ARCH_TEGRA_124_SOC)	+= pm-tegra30.o
+ifeq ($(CONFIG_CPU_IDLE),y)
+obj-$(CONFIG_ARCH_TEGRA_124_SOC)	+= cpuidle-tegra114.o
+endif
 
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= board-paz00.o
diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c
index 740e16f..06f0240 100644
--- a/arch/arm/mach-tegra/board-paz00.c
+++ b/arch/arm/mach-tegra/board-paz00.c
@@ -20,12 +20,11 @@
 #include <linux/platform_device.h>
 #include <linux/rfkill-gpio.h>
 #include "board.h"
-#include "board-paz00.h"
 
 static struct rfkill_gpio_platform_data wifi_rfkill_platform_data = {
 	.name		= "wifi_rfkill",
-	.reset_gpio	= TEGRA_WIFI_RST,
-	.shutdown_gpio	= TEGRA_WIFI_PWRN,
+	.reset_gpio	= 25, /* PD1 */
+	.shutdown_gpio	= 85, /* PK5 */
 	.type	= RFKILL_TYPE_WLAN,
 };
 
diff --git a/arch/arm/mach-tegra/board-paz00.h b/arch/arm/mach-tegra/board-paz00.h
deleted file mode 100644
index 25c08ec..0000000
--- a/arch/arm/mach-tegra/board-paz00.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * arch/arm/mach-tegra/board-paz00.h
- *
- * Copyright (C) 2010 Marc Dietrich <marvin24@gmx.de>
- *
- * 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_BOARD_PAZ00_H
-#define _MACH_TEGRA_BOARD_PAZ00_H
-
-#include "gpio-names.h"
-
-#define TEGRA_WIFI_PWRN			TEGRA_GPIO_PK5
-#define TEGRA_WIFI_RST			TEGRA_GPIO_PD1
-
-#endif
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h
index db6810d..bcf5dbf 100644
--- a/arch/arm/mach-tegra/board.h
+++ b/arch/arm/mach-tegra/board.h
@@ -25,20 +25,8 @@
 #include <linux/types.h>
 #include <linux/reboot.h>
 
-void tegra_assert_system_reset(enum reboot_mode mode, const char *cmd);
-
-void __init tegra_init_early(void);
 void __init tegra_map_common_io(void);
 void __init tegra_init_irq(void);
-void __init tegra_dt_init_irq(void);
-
-void tegra_init_late(void);
-
-#ifdef CONFIG_DEBUG_FS
-int tegra_clk_debugfs_init(void);
-#else
-static inline int tegra_clk_debugfs_init(void) { return 0; }
-#endif
 
 int __init tegra_powergate_init(void);
 #if defined(CONFIG_ARCH_TEGRA_2x_SOC) && defined(CONFIG_DEBUG_FS)
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
deleted file mode 100644
index 94a119a..0000000
--- a/arch/arm/mach-tegra/common.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * arch/arm/mach-tegra/common.c
- *
- * Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
- * 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/init.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/reboot.h>
-#include <linux/irqchip.h>
-#include <linux/clk-provider.h>
-
-#include <asm/hardware/cache-l2x0.h>
-
-#include "board.h"
-#include "common.h"
-#include "cpuidle.h"
-#include "fuse.h"
-#include "iomap.h"
-#include "irq.h"
-#include "pmc.h"
-#include "apbio.h"
-#include "sleep.h"
-#include "pm.h"
-#include "reset.h"
-
-/*
- * Storage for debug-macro.S's state.
- *
- * This must be in .data not .bss so that it gets initialized each time the
- * kernel is loaded. The data is declared here rather than debug-macro.S so
- * that multiple inclusions of debug-macro.S point at the same data.
- */
-u32 tegra_uart_config[4] = {
-	/* Debug UART initialization required */
-	1,
-	/* Debug UART physical address */
-	0,
-	/* Debug UART virtual address */
-	0,
-	/* Scratch space for debug macro */
-	0,
-};
-
-#ifdef CONFIG_OF
-void __init tegra_dt_init_irq(void)
-{
-	of_clk_init(NULL);
-	tegra_pmc_init();
-	tegra_init_irq();
-	irqchip_init();
-	tegra_legacy_irq_syscore_init();
-}
-#endif
-
-void tegra_assert_system_reset(enum reboot_mode mode, const char *cmd)
-{
-	void __iomem *reset = IO_ADDRESS(TEGRA_PMC_BASE + 0);
-	u32 reg;
-
-	reg = readl_relaxed(reset);
-	reg |= 0x10;
-	writel_relaxed(reg, reset);
-}
-
-static void __init tegra_init_cache(void)
-{
-#ifdef CONFIG_CACHE_L2X0
-	int ret;
-	void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
-	u32 aux_ctrl, cache_type;
-
-	cache_type = readl(p + L2X0_CACHE_TYPE);
-	aux_ctrl = (cache_type & 0x700) << (17-8);
-	aux_ctrl |= 0x7C400001;
-
-	ret = l2x0_of_init(aux_ctrl, 0x8200c3fe);
-	if (!ret)
-		l2x0_saved_regs_addr = virt_to_phys(&l2x0_saved_regs);
-#endif
-
-}
-
-void __init tegra_init_early(void)
-{
-	tegra_cpu_reset_handler_init();
-	tegra_apb_io_init();
-	tegra_init_fuse();
-	tegra_init_cache();
-	tegra_powergate_init();
-	tegra_hotplug_init();
-}
-
-void __init tegra_init_late(void)
-{
-	tegra_init_suspend();
-	tegra_cpuidle_init();
-	tegra_powergate_debugfs_init();
-}
diff --git a/arch/arm/mach-tegra/cpuidle.c b/arch/arm/mach-tegra/cpuidle.c
index 0961dfc..7bc5d8d 100644
--- a/arch/arm/mach-tegra/cpuidle.c
+++ b/arch/arm/mach-tegra/cpuidle.c
@@ -39,7 +39,9 @@
 			tegra30_cpuidle_init();
 		break;
 	case TEGRA114:
-		if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC))
+	case TEGRA124:
+		if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) ||
+		    IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC))
 			tegra114_cpuidle_init();
 		break;
 	}
diff --git a/arch/arm/mach-tegra/flowctrl.c b/arch/arm/mach-tegra/flowctrl.c
index 5348543..ce8ab8a 100644
--- a/arch/arm/mach-tegra/flowctrl.c
+++ b/arch/arm/mach-tegra/flowctrl.c
@@ -87,6 +87,7 @@
 		break;
 	case TEGRA30:
 	case TEGRA114:
+	case TEGRA124:
 		/* clear wfe bitmap */
 		reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;
 		/* clear wfi bitmap */
@@ -125,6 +126,7 @@
 		break;
 	case TEGRA30:
 	case TEGRA114:
+	case TEGRA124:
 		/* clear wfe bitmap */
 		reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;
 		/* clear wfi bitmap */
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
index e035cd2..d4639c5 100644
--- a/arch/arm/mach-tegra/fuse.c
+++ b/arch/arm/mach-tegra/fuse.c
@@ -21,14 +21,26 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/export.h>
+#include <linux/random.h>
 #include <linux/tegra-soc.h>
 
 #include "fuse.h"
 #include "iomap.h"
 #include "apbio.h"
 
+/* Tegra20 only */
 #define FUSE_UID_LOW		0x108
 #define FUSE_UID_HIGH		0x10c
+
+/* Tegra30 and later */
+#define FUSE_VENDOR_CODE	0x200
+#define FUSE_FAB_CODE		0x204
+#define FUSE_LOT_CODE_0		0x208
+#define FUSE_LOT_CODE_1		0x20c
+#define FUSE_WAFER_ID		0x210
+#define FUSE_X_COORDINATE	0x214
+#define FUSE_Y_COORDINATE	0x218
+
 #define FUSE_SKU_INFO		0x110
 
 #define TEGRA20_FUSE_SPARE_BIT		0x200
@@ -112,21 +124,51 @@
 	return readl_relaxed(IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804);
 }
 
-void tegra_init_fuse(void)
+static void __init tegra20_fuse_init_randomness(void)
+{
+	u32 randomness[2];
+
+	randomness[0] = tegra_fuse_readl(FUSE_UID_LOW);
+	randomness[1] = tegra_fuse_readl(FUSE_UID_HIGH);
+
+	add_device_randomness(randomness, sizeof(randomness));
+}
+
+/* Applies to Tegra30 or later */
+static void __init tegra30_fuse_init_randomness(void)
+{
+	u32 randomness[7];
+
+	randomness[0] = tegra_fuse_readl(FUSE_VENDOR_CODE);
+	randomness[1] = tegra_fuse_readl(FUSE_FAB_CODE);
+	randomness[2] = tegra_fuse_readl(FUSE_LOT_CODE_0);
+	randomness[3] = tegra_fuse_readl(FUSE_LOT_CODE_1);
+	randomness[4] = tegra_fuse_readl(FUSE_WAFER_ID);
+	randomness[5] = tegra_fuse_readl(FUSE_X_COORDINATE);
+	randomness[6] = tegra_fuse_readl(FUSE_Y_COORDINATE);
+
+	add_device_randomness(randomness, sizeof(randomness));
+}
+
+void __init tegra_init_fuse(void)
 {
 	u32 id;
+	u32 randomness[5];
 
 	u32 reg = readl(IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x48));
 	reg |= 1 << 28;
 	writel(reg, IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x48));
 
 	reg = tegra_fuse_readl(FUSE_SKU_INFO);
+	randomness[0] = reg;
 	tegra_sku_id = reg & 0xFF;
 
 	reg = tegra_apb_readl(TEGRA_APB_MISC_BASE + STRAP_OPT);
+	randomness[1] = reg;
 	tegra_bct_strapping = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT;
 
 	id = tegra_read_chipid();
+	randomness[2] = id;
 	tegra_chip_id = (id >> 8) & 0xff;
 
 	switch (tegra_chip_id) {
@@ -149,6 +191,18 @@
 
 	tegra_revision = tegra_get_revision(id);
 	tegra_init_speedo_data();
+	randomness[3] = (tegra_cpu_process_id << 16) | tegra_core_process_id;
+	randomness[4] = (tegra_cpu_speedo_id << 16) | tegra_soc_speedo_id;
+
+	add_device_randomness(randomness, sizeof(randomness));
+	switch (tegra_chip_id) {
+	case TEGRA20:
+		tegra20_fuse_init_randomness();
+	case TEGRA30:
+	case TEGRA114:
+	default:
+		tegra30_fuse_init_randomness();
+	}
 
 	pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n",
 		tegra_revision_name[tegra_revision],
diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h
index def7968..c01d047 100644
--- a/arch/arm/mach-tegra/fuse.h
+++ b/arch/arm/mach-tegra/fuse.h
@@ -29,6 +29,7 @@
 #define TEGRA20		0x20
 #define TEGRA30		0x30
 #define TEGRA114	0x35
+#define TEGRA124	0x40
 
 #ifndef __ASSEMBLY__
 enum tegra_revision {
diff --git a/arch/arm/mach-tegra/gpio-names.h b/arch/arm/mach-tegra/gpio-names.h
deleted file mode 100644
index f28220a..0000000
--- a/arch/arm/mach-tegra/gpio-names.h
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/gpio-names.h
- *
- * Copyright (c) 2010 Google, Inc
- *
- * Author:
- *	Erik Gilling <konkers@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __MACH_TEGRA_GPIO_NAMES_H
-#define __MACH_TEGRA_GPIO_NAMES_H
-
-#define TEGRA_GPIO_PA0		0
-#define TEGRA_GPIO_PA1		1
-#define TEGRA_GPIO_PA2		2
-#define TEGRA_GPIO_PA3		3
-#define TEGRA_GPIO_PA4		4
-#define TEGRA_GPIO_PA5		5
-#define TEGRA_GPIO_PA6		6
-#define TEGRA_GPIO_PA7		7
-#define TEGRA_GPIO_PB0		8
-#define TEGRA_GPIO_PB1		9
-#define TEGRA_GPIO_PB2		10
-#define TEGRA_GPIO_PB3		11
-#define TEGRA_GPIO_PB4		12
-#define TEGRA_GPIO_PB5		13
-#define TEGRA_GPIO_PB6		14
-#define TEGRA_GPIO_PB7		15
-#define TEGRA_GPIO_PC0		16
-#define TEGRA_GPIO_PC1		17
-#define TEGRA_GPIO_PC2		18
-#define TEGRA_GPIO_PC3		19
-#define TEGRA_GPIO_PC4		20
-#define TEGRA_GPIO_PC5		21
-#define TEGRA_GPIO_PC6		22
-#define TEGRA_GPIO_PC7		23
-#define TEGRA_GPIO_PD0		24
-#define TEGRA_GPIO_PD1		25
-#define TEGRA_GPIO_PD2		26
-#define TEGRA_GPIO_PD3		27
-#define TEGRA_GPIO_PD4		28
-#define TEGRA_GPIO_PD5		29
-#define TEGRA_GPIO_PD6		30
-#define TEGRA_GPIO_PD7		31
-#define TEGRA_GPIO_PE0		32
-#define TEGRA_GPIO_PE1		33
-#define TEGRA_GPIO_PE2		34
-#define TEGRA_GPIO_PE3		35
-#define TEGRA_GPIO_PE4		36
-#define TEGRA_GPIO_PE5		37
-#define TEGRA_GPIO_PE6		38
-#define TEGRA_GPIO_PE7		39
-#define TEGRA_GPIO_PF0		40
-#define TEGRA_GPIO_PF1		41
-#define TEGRA_GPIO_PF2		42
-#define TEGRA_GPIO_PF3		43
-#define TEGRA_GPIO_PF4		44
-#define TEGRA_GPIO_PF5		45
-#define TEGRA_GPIO_PF6		46
-#define TEGRA_GPIO_PF7		47
-#define TEGRA_GPIO_PG0		48
-#define TEGRA_GPIO_PG1		49
-#define TEGRA_GPIO_PG2		50
-#define TEGRA_GPIO_PG3		51
-#define TEGRA_GPIO_PG4		52
-#define TEGRA_GPIO_PG5		53
-#define TEGRA_GPIO_PG6		54
-#define TEGRA_GPIO_PG7		55
-#define TEGRA_GPIO_PH0		56
-#define TEGRA_GPIO_PH1		57
-#define TEGRA_GPIO_PH2		58
-#define TEGRA_GPIO_PH3		59
-#define TEGRA_GPIO_PH4		60
-#define TEGRA_GPIO_PH5		61
-#define TEGRA_GPIO_PH6		62
-#define TEGRA_GPIO_PH7		63
-#define TEGRA_GPIO_PI0		64
-#define TEGRA_GPIO_PI1		65
-#define TEGRA_GPIO_PI2		66
-#define TEGRA_GPIO_PI3		67
-#define TEGRA_GPIO_PI4		68
-#define TEGRA_GPIO_PI5		69
-#define TEGRA_GPIO_PI6		70
-#define TEGRA_GPIO_PI7		71
-#define TEGRA_GPIO_PJ0		72
-#define TEGRA_GPIO_PJ1		73
-#define TEGRA_GPIO_PJ2		74
-#define TEGRA_GPIO_PJ3		75
-#define TEGRA_GPIO_PJ4		76
-#define TEGRA_GPIO_PJ5		77
-#define TEGRA_GPIO_PJ6		78
-#define TEGRA_GPIO_PJ7		79
-#define TEGRA_GPIO_PK0		80
-#define TEGRA_GPIO_PK1		81
-#define TEGRA_GPIO_PK2		82
-#define TEGRA_GPIO_PK3		83
-#define TEGRA_GPIO_PK4		84
-#define TEGRA_GPIO_PK5		85
-#define TEGRA_GPIO_PK6		86
-#define TEGRA_GPIO_PK7		87
-#define TEGRA_GPIO_PL0		88
-#define TEGRA_GPIO_PL1		89
-#define TEGRA_GPIO_PL2		90
-#define TEGRA_GPIO_PL3		91
-#define TEGRA_GPIO_PL4		92
-#define TEGRA_GPIO_PL5		93
-#define TEGRA_GPIO_PL6		94
-#define TEGRA_GPIO_PL7		95
-#define TEGRA_GPIO_PM0		96
-#define TEGRA_GPIO_PM1		97
-#define TEGRA_GPIO_PM2		98
-#define TEGRA_GPIO_PM3		99
-#define TEGRA_GPIO_PM4		100
-#define TEGRA_GPIO_PM5		101
-#define TEGRA_GPIO_PM6		102
-#define TEGRA_GPIO_PM7		103
-#define TEGRA_GPIO_PN0		104
-#define TEGRA_GPIO_PN1		105
-#define TEGRA_GPIO_PN2		106
-#define TEGRA_GPIO_PN3		107
-#define TEGRA_GPIO_PN4		108
-#define TEGRA_GPIO_PN5		109
-#define TEGRA_GPIO_PN6		110
-#define TEGRA_GPIO_PN7		111
-#define TEGRA_GPIO_PO0		112
-#define TEGRA_GPIO_PO1		113
-#define TEGRA_GPIO_PO2		114
-#define TEGRA_GPIO_PO3		115
-#define TEGRA_GPIO_PO4		116
-#define TEGRA_GPIO_PO5		117
-#define TEGRA_GPIO_PO6		118
-#define TEGRA_GPIO_PO7		119
-#define TEGRA_GPIO_PP0		120
-#define TEGRA_GPIO_PP1		121
-#define TEGRA_GPIO_PP2		122
-#define TEGRA_GPIO_PP3		123
-#define TEGRA_GPIO_PP4		124
-#define TEGRA_GPIO_PP5		125
-#define TEGRA_GPIO_PP6		126
-#define TEGRA_GPIO_PP7		127
-#define TEGRA_GPIO_PQ0		128
-#define TEGRA_GPIO_PQ1		129
-#define TEGRA_GPIO_PQ2		130
-#define TEGRA_GPIO_PQ3		131
-#define TEGRA_GPIO_PQ4		132
-#define TEGRA_GPIO_PQ5		133
-#define TEGRA_GPIO_PQ6		134
-#define TEGRA_GPIO_PQ7		135
-#define TEGRA_GPIO_PR0		136
-#define TEGRA_GPIO_PR1		137
-#define TEGRA_GPIO_PR2		138
-#define TEGRA_GPIO_PR3		139
-#define TEGRA_GPIO_PR4		140
-#define TEGRA_GPIO_PR5		141
-#define TEGRA_GPIO_PR6		142
-#define TEGRA_GPIO_PR7		143
-#define TEGRA_GPIO_PS0		144
-#define TEGRA_GPIO_PS1		145
-#define TEGRA_GPIO_PS2		146
-#define TEGRA_GPIO_PS3		147
-#define TEGRA_GPIO_PS4		148
-#define TEGRA_GPIO_PS5		149
-#define TEGRA_GPIO_PS6		150
-#define TEGRA_GPIO_PS7		151
-#define TEGRA_GPIO_PT0		152
-#define TEGRA_GPIO_PT1		153
-#define TEGRA_GPIO_PT2		154
-#define TEGRA_GPIO_PT3		155
-#define TEGRA_GPIO_PT4		156
-#define TEGRA_GPIO_PT5		157
-#define TEGRA_GPIO_PT6		158
-#define TEGRA_GPIO_PT7		159
-#define TEGRA_GPIO_PU0		160
-#define TEGRA_GPIO_PU1		161
-#define TEGRA_GPIO_PU2		162
-#define TEGRA_GPIO_PU3		163
-#define TEGRA_GPIO_PU4		164
-#define TEGRA_GPIO_PU5		165
-#define TEGRA_GPIO_PU6		166
-#define TEGRA_GPIO_PU7		167
-#define TEGRA_GPIO_PV0		168
-#define TEGRA_GPIO_PV1		169
-#define TEGRA_GPIO_PV2		170
-#define TEGRA_GPIO_PV3		171
-#define TEGRA_GPIO_PV4		172
-#define TEGRA_GPIO_PV5		173
-#define TEGRA_GPIO_PV6		174
-#define TEGRA_GPIO_PV7		175
-#define TEGRA_GPIO_PW0		176
-#define TEGRA_GPIO_PW1		177
-#define TEGRA_GPIO_PW2		178
-#define TEGRA_GPIO_PW3		179
-#define TEGRA_GPIO_PW4		180
-#define TEGRA_GPIO_PW5		181
-#define TEGRA_GPIO_PW6		182
-#define TEGRA_GPIO_PW7		183
-#define TEGRA_GPIO_PX0		184
-#define TEGRA_GPIO_PX1		185
-#define TEGRA_GPIO_PX2		186
-#define TEGRA_GPIO_PX3		187
-#define TEGRA_GPIO_PX4		188
-#define TEGRA_GPIO_PX5		189
-#define TEGRA_GPIO_PX6		190
-#define TEGRA_GPIO_PX7		191
-#define TEGRA_GPIO_PY0		192
-#define TEGRA_GPIO_PY1		193
-#define TEGRA_GPIO_PY2		194
-#define TEGRA_GPIO_PY3		195
-#define TEGRA_GPIO_PY4		196
-#define TEGRA_GPIO_PY5		197
-#define TEGRA_GPIO_PY6		198
-#define TEGRA_GPIO_PY7		199
-#define TEGRA_GPIO_PZ0		200
-#define TEGRA_GPIO_PZ1		201
-#define TEGRA_GPIO_PZ2		202
-#define TEGRA_GPIO_PZ3		203
-#define TEGRA_GPIO_PZ4		204
-#define TEGRA_GPIO_PZ5		205
-#define TEGRA_GPIO_PZ6		206
-#define TEGRA_GPIO_PZ7		207
-#define TEGRA_GPIO_PAA0		208
-#define TEGRA_GPIO_PAA1		209
-#define TEGRA_GPIO_PAA2		210
-#define TEGRA_GPIO_PAA3		211
-#define TEGRA_GPIO_PAA4		212
-#define TEGRA_GPIO_PAA5		213
-#define TEGRA_GPIO_PAA6		214
-#define TEGRA_GPIO_PAA7		215
-#define TEGRA_GPIO_PBB0		216
-#define TEGRA_GPIO_PBB1		217
-#define TEGRA_GPIO_PBB2		218
-#define TEGRA_GPIO_PBB3		219
-#define TEGRA_GPIO_PBB4		220
-#define TEGRA_GPIO_PBB5		221
-#define TEGRA_GPIO_PBB6		222
-#define TEGRA_GPIO_PBB7		223
-
-#endif
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
index 04de2e8..ff26af2 100644
--- a/arch/arm/mach-tegra/hotplug.c
+++ b/arch/arm/mach-tegra/hotplug.c
@@ -57,4 +57,6 @@
 		tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
 	if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114)
 		tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
+	if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_chip_id == TEGRA124)
+		tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
 }
diff --git a/arch/arm/mach-tegra/iomap.h b/arch/arm/mach-tegra/iomap.h
index 3f5fa07..26b1c2a 100644
--- a/arch/arm/mach-tegra/iomap.h
+++ b/arch/arm/mach-tegra/iomap.h
@@ -24,44 +24,12 @@
 #define TEGRA_IRAM_BASE			0x40000000
 #define TEGRA_IRAM_SIZE			SZ_256K
 
-#define TEGRA_IRAM_CODE_AREA		(TEGRA_IRAM_BASE + SZ_4K)
-
-#define TEGRA_HOST1X_BASE		0x50000000
-#define TEGRA_HOST1X_SIZE		0x24000
-
 #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
 
-#define TEGRA_MPE_BASE			0x54040000
-#define TEGRA_MPE_SIZE			SZ_256K
-
-#define TEGRA_VI_BASE			0x54080000
-#define TEGRA_VI_SIZE			SZ_256K
-
-#define TEGRA_ISP_BASE			0x54100000
-#define TEGRA_ISP_SIZE			SZ_256K
-
-#define TEGRA_DISPLAY_BASE		0x54200000
-#define TEGRA_DISPLAY_SIZE		SZ_256K
-
-#define TEGRA_DISPLAY2_BASE		0x54240000
-#define TEGRA_DISPLAY2_SIZE		SZ_256K
-
-#define TEGRA_HDMI_BASE			0x54280000
-#define TEGRA_HDMI_SIZE			SZ_256K
-
-#define TEGRA_GART_BASE			0x58000000
-#define TEGRA_GART_SIZE			SZ_32M
-
-#define TEGRA_RES_SEMA_BASE		0x60001000
-#define TEGRA_RES_SEMA_SIZE		SZ_4K
-
 #define TEGRA_PRIMARY_ICTLR_BASE	0x60004000
 #define TEGRA_PRIMARY_ICTLR_SIZE	SZ_64
 
@@ -98,51 +66,15 @@
 #define TEGRA_FLOW_CTRL_BASE		0x60007000
 #define TEGRA_FLOW_CTRL_SIZE		20
 
-#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_SB_BASE			0x6000C200
 #define TEGRA_SB_SIZE			256
 
-#define TEGRA_STATMON_BASE		0x6000C400
-#define TEGRA_STATMON_SIZE		SZ_1K
-
-#define TEGRA_GPIO_BASE			0x6000D000
-#define TEGRA_GPIO_SIZE			SZ_4K
-
 #define TEGRA_EXCEPTION_VECTORS_BASE    0x6000F000
 #define TEGRA_EXCEPTION_VECTORS_SIZE    SZ_4K
 
 #define TEGRA_APB_MISC_BASE		0x70000000
 #define TEGRA_APB_MISC_SIZE		SZ_4K
 
-#define TEGRA_APB_MISC_DAS_BASE		0x70000c00
-#define TEGRA_APB_MISC_DAS_SIZE		SZ_128
-
-#define TEGRA_AC97_BASE			0x70002000
-#define TEGRA_AC97_SIZE			SZ_512
-
-#define TEGRA_SPDIF_BASE		0x70002400
-#define TEGRA_SPDIF_SIZE		SZ_512
-
-#define TEGRA_I2S1_BASE			0x70002800
-#define TEGRA_I2S1_SIZE			SZ_256
-
-#define TEGRA_I2S2_BASE			0x70002A00
-#define TEGRA_I2S2_SIZE			SZ_256
-
 #define TEGRA_UARTA_BASE		0x70006000
 #define TEGRA_UARTA_SIZE		SZ_64
 
@@ -158,108 +90,27 @@
 #define TEGRA_UARTE_BASE		0x70006400
 #define TEGRA_UARTE_SIZE		SZ_256
 
-#define TEGRA_NAND_BASE			0x70008000
-#define TEGRA_NAND_SIZE			SZ_256
-
-#define TEGRA_HSMMC_BASE		0x70008500
-#define TEGRA_HSMMC_SIZE		SZ_256
-
-#define TEGRA_SNOR_BASE			0x70009000
-#define TEGRA_SNOR_SIZE			SZ_4K
-
-#define TEGRA_PWFM_BASE			0x7000A000
-#define TEGRA_PWFM_SIZE			SZ_256
-
-#define TEGRA_PWFM0_BASE		0x7000A000
-#define TEGRA_PWFM0_SIZE		4
-
-#define TEGRA_PWFM1_BASE		0x7000A010
-#define TEGRA_PWFM1_SIZE		4
-
-#define TEGRA_PWFM2_BASE		0x7000A020
-#define TEGRA_PWFM2_SIZE		4
-
-#define TEGRA_PWFM3_BASE		0x7000A030
-#define TEGRA_PWFM3_SIZE		4
-
-#define TEGRA_MIPI_BASE			0x7000B000
-#define TEGRA_MIPI_SIZE			SZ_256
-
-#define TEGRA_I2C_BASE			0x7000C000
-#define TEGRA_I2C_SIZE			SZ_256
-
-#define TEGRA_TWC_BASE			0x7000C100
-#define TEGRA_TWC_SIZE			SZ_256
-
-#define TEGRA_SPI_BASE			0x7000C380
-#define TEGRA_SPI_SIZE			48
-
-#define TEGRA_I2C2_BASE			0x7000C400
-#define TEGRA_I2C2_SIZE			SZ_256
-
-#define TEGRA_I2C3_BASE			0x7000C500
-#define TEGRA_I2C3_SIZE			SZ_256
-
-#define TEGRA_OWR_BASE			0x7000C600
-#define TEGRA_OWR_SIZE			80
-
-#define TEGRA_DVC_BASE			0x7000D000
-#define TEGRA_DVC_SIZE			SZ_512
-
-#define TEGRA_SPI1_BASE			0x7000D400
-#define TEGRA_SPI1_SIZE			SZ_512
-
-#define TEGRA_SPI2_BASE			0x7000D600
-#define TEGRA_SPI2_SIZE			SZ_512
-
-#define TEGRA_SPI3_BASE			0x7000D800
-#define TEGRA_SPI3_SIZE			SZ_512
-
-#define TEGRA_SPI4_BASE			0x7000DA00
-#define TEGRA_SPI4_SIZE			SZ_512
-
-#define TEGRA_RTC_BASE			0x7000E000
-#define TEGRA_RTC_SIZE			SZ_256
-
-#define TEGRA_KBC_BASE			0x7000E200
-#define TEGRA_KBC_SIZE			SZ_256
-
 #define TEGRA_PMC_BASE			0x7000E400
 #define TEGRA_PMC_SIZE			SZ_256
 
-#define TEGRA_MC_BASE			0x7000F000
-#define TEGRA_MC_SIZE			SZ_1K
-
 #define TEGRA_EMC_BASE			0x7000F400
 #define TEGRA_EMC_SIZE			SZ_1K
 
 #define TEGRA_FUSE_BASE			0x7000F800
 #define TEGRA_FUSE_SIZE			SZ_1K
 
-#define TEGRA_KFUSE_BASE		0x7000FC00
-#define TEGRA_KFUSE_SIZE		SZ_1K
-
 #define TEGRA_EMC0_BASE			0x7001A000
 #define TEGRA_EMC0_SIZE			SZ_2K
 
 #define TEGRA_EMC1_BASE			0x7001A800
 #define TEGRA_EMC1_SIZE			SZ_2K
 
+#define TEGRA124_EMC_BASE		0x7001B000
+#define TEGRA124_EMC_SIZE		SZ_2K
+
 #define TEGRA_CSITE_BASE		0x70040000
 #define TEGRA_CSITE_SIZE		SZ_256K
 
-#define TEGRA_SDMMC1_BASE		0xC8000000
-#define TEGRA_SDMMC1_SIZE		SZ_512
-
-#define TEGRA_SDMMC2_BASE		0xC8000200
-#define TEGRA_SDMMC2_SIZE		SZ_512
-
-#define TEGRA_SDMMC3_BASE		0xC8000400
-#define TEGRA_SDMMC3_SIZE		SZ_512
-
-#define TEGRA_SDMMC4_BASE		0xC8000600
-#define TEGRA_SDMMC4_SIZE		SZ_512
-
 /* On TEGRA, many peripherals are very closely packed in
  * two 256MB io windows (that actually only use about 64KB
  * at the start of each).
diff --git a/arch/arm/mach-tegra/irammap.h b/arch/arm/mach-tegra/irammap.h
index 501952a..e32e174 100644
--- a/arch/arm/mach-tegra/irammap.h
+++ b/arch/arm/mach-tegra/irammap.h
@@ -23,4 +23,10 @@
 #define TEGRA_IRAM_RESET_HANDLER_OFFSET	0
 #define TEGRA_IRAM_RESET_HANDLER_SIZE	SZ_1K
 
+/*
+ * This area is used for LPx resume vector, only while LPx power state is
+ * active. At other times, the AVP may use this area for arbitrary purposes
+ */
+#define TEGRA_IRAM_LPx_RESUME_AREA	(TEGRA_IRAM_BASE + SZ_4K)
+
 #endif
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 2d02036..eb72ae7 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -176,6 +176,8 @@
 		return tegra30_boot_secondary(cpu, idle);
 	if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114)
 		return tegra114_boot_secondary(cpu, idle);
+	if (IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC) && tegra_chip_id == TEGRA124)
+		return tegra114_boot_secondary(cpu, idle);
 
 	return -EINVAL;
 }
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index ed294a0..4ae0286 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -59,8 +59,10 @@
 		break;
 	case TEGRA30:
 	case TEGRA114:
+	case TEGRA124:
 		if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) ||
-		    IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC))
+		    IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) ||
+		    IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC))
 			tegra_tear_down_cpu = tegra30_tear_down_cpu;
 		break;
 	}
@@ -216,8 +218,10 @@
 		break;
 	case TEGRA30:
 	case TEGRA114:
+	case TEGRA124:
 		if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) ||
-		    IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC))
+		    IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) ||
+		    IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC))
 			tegra30_lp1_iram_hook();
 		break;
 	default:
@@ -244,8 +248,10 @@
 		break;
 	case TEGRA30:
 	case TEGRA114:
+	case TEGRA124:
 		if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) ||
-		    IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC))
+		    IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) ||
+		    IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC))
 			tegra30_sleep_core_init();
 		break;
 	default:
@@ -263,10 +269,10 @@
 	tegra_pmc_suspend();
 
 	/* copy the reset vector & SDRAM shutdown code into IRAM */
-	memcpy(iram_save_addr, IO_ADDRESS(TEGRA_IRAM_CODE_AREA),
+	memcpy(iram_save_addr, IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA),
 		iram_save_size);
-	memcpy(IO_ADDRESS(TEGRA_IRAM_CODE_AREA), tegra_lp1_iram.start_addr,
-		iram_save_size);
+	memcpy(IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA),
+		tegra_lp1_iram.start_addr, iram_save_size);
 
 	*((u32 *)tegra_cpu_lp1_mask) = 1;
 }
@@ -276,7 +282,7 @@
 	tegra_pmc_resume();
 
 	/* restore IRAM */
-	memcpy(IO_ADDRESS(TEGRA_IRAM_CODE_AREA), iram_save_addr,
+	memcpy(IO_ADDRESS(TEGRA_IRAM_LPx_RESUME_AREA), iram_save_addr,
 		iram_save_size);
 
 	*(u32 *)tegra_cpu_lp1_mask = 0;
diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h
index fe204e5..6e92a7c 100644
--- a/arch/arm/mach-tegra/pm.h
+++ b/arch/arm/mach-tegra/pm.h
@@ -37,9 +37,6 @@
 
 extern unsigned long l2x0_saved_regs_addr;
 
-void save_cpu_arch_register(void);
-void restore_cpu_arch_register(void);
-
 void tegra_clear_cpu_in_lp2(void);
 bool tegra_set_cpu_in_lp2(void);
 
diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c
index 8acb881..fb79202 100644
--- a/arch/arm/mach-tegra/pmc.c
+++ b/arch/arm/mach-tegra/pmc.c
@@ -20,6 +20,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/tegra-powergate.h>
 
 #include "flowctrl.h"
 #include "fuse.h"
@@ -43,12 +44,6 @@
 #define PMC_CPUPWRGOOD_TIMER	0xc8
 #define PMC_CPUPWROFF_TIMER	0xcc
 
-#define TEGRA_POWERGATE_PCIE	3
-#define TEGRA_POWERGATE_VDEC	4
-#define TEGRA_POWERGATE_CPU1	9
-#define TEGRA_POWERGATE_CPU2	10
-#define TEGRA_POWERGATE_CPU3	11
-
 static u8 tegra_cpu_domains[] = {
 	0xFF,			/* not available for CPU0 */
 	TEGRA_POWERGATE_CPU1,
@@ -166,6 +161,15 @@
 	return tegra_pmc_powergate_remove_clamping(id);
 }
 
+void tegra_pmc_restart(enum reboot_mode mode, const char *cmd)
+{
+	u32 val;
+
+	val = tegra_pmc_readl(0);
+	val |= 0x10;
+	tegra_pmc_writel(val, 0);
+}
+
 #ifdef CONFIG_PM_SLEEP
 static void set_power_timers(u32 us_on, u32 us_off, unsigned long rate)
 {
@@ -279,13 +283,35 @@
 #endif
 
 static const struct of_device_id matches[] __initconst = {
+	{ .compatible = "nvidia,tegra124-pmc" },
 	{ .compatible = "nvidia,tegra114-pmc" },
 	{ .compatible = "nvidia,tegra30-pmc" },
 	{ .compatible = "nvidia,tegra20-pmc" },
 	{ }
 };
 
-static void __init tegra_pmc_parse_dt(void)
+void __init tegra_pmc_init_irq(void)
+{
+	struct device_node *np;
+	u32 val;
+
+	np = of_find_matching_node(NULL, matches);
+	BUG_ON(!np);
+
+	tegra_pmc_base = of_iomap(np, 0);
+
+	tegra_pmc_invert_interrupt = of_property_read_bool(np,
+				     "nvidia,invert-interrupt");
+
+	val = tegra_pmc_readl(PMC_CTRL);
+	if (tegra_pmc_invert_interrupt)
+		val |= PMC_CTRL_INTR_LOW;
+	else
+		val &= ~PMC_CTRL_INTR_LOW;
+	tegra_pmc_writel(val, PMC_CTRL);
+}
+
+void __init tegra_pmc_init(void)
 {
 	struct device_node *np;
 	u32 prop;
@@ -296,10 +322,6 @@
 	np = of_find_matching_node(NULL, matches);
 	BUG_ON(!np);
 
-	tegra_pmc_base = of_iomap(np, 0);
-
-	tegra_pmc_invert_interrupt = of_property_read_bool(np,
-				     "nvidia,invert-interrupt");
 	tegra_pclk = of_clk_get_by_name(np, "pclk");
 	WARN_ON(IS_ERR(tegra_pclk));
 
@@ -365,17 +387,3 @@
 
 	pmc_pm_data.suspend_mode = suspend_mode;
 }
-
-void __init tegra_pmc_init(void)
-{
-	u32 val;
-
-	tegra_pmc_parse_dt();
-
-	val = tegra_pmc_readl(PMC_CTRL);
-	if (tegra_pmc_invert_interrupt)
-		val |= PMC_CTRL_INTR_LOW;
-	else
-		val &= ~PMC_CTRL_INTR_LOW;
-	tegra_pmc_writel(val, PMC_CTRL);
-}
diff --git a/arch/arm/mach-tegra/pmc.h b/arch/arm/mach-tegra/pmc.h
index 549f8c7..59e19c34 100644
--- a/arch/arm/mach-tegra/pmc.h
+++ b/arch/arm/mach-tegra/pmc.h
@@ -18,6 +18,8 @@
 #ifndef __MACH_TEGRA_PMC_H
 #define __MACH_TEGRA_PMC_H
 
+#include <linux/reboot.h>
+
 enum tegra_suspend_mode {
 	TEGRA_SUSPEND_NONE = 0,
 	TEGRA_SUSPEND_LP2,	/* CPU voltage off */
@@ -39,6 +41,9 @@
 int tegra_pmc_cpu_power_on(int cpuid);
 int tegra_pmc_cpu_remove_clamping(int cpuid);
 
+void tegra_pmc_restart(enum reboot_mode mode, const char *cmd);
+
+void tegra_pmc_init_irq(void);
 void tegra_pmc_init(void);
 
 #endif
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c
index f076f0f..85d28e7 100644
--- a/arch/arm/mach-tegra/powergate.c
+++ b/arch/arm/mach-tegra/powergate.c
@@ -42,8 +42,16 @@
 
 static int tegra_num_powerdomains;
 static int tegra_num_cpu_domains;
-static u8 *tegra_cpu_domains;
-static u8 tegra30_cpu_domains[] = {
+static const u8 *tegra_cpu_domains;
+
+static const u8 tegra30_cpu_domains[] = {
+	TEGRA_POWERGATE_CPU,
+	TEGRA_POWERGATE_CPU1,
+	TEGRA_POWERGATE_CPU2,
+	TEGRA_POWERGATE_CPU3,
+};
+
+static const u8 tegra114_cpu_domains[] = {
 	TEGRA_POWERGATE_CPU0,
 	TEGRA_POWERGATE_CPU1,
 	TEGRA_POWERGATE_CPU2,
@@ -189,6 +197,11 @@
 		tegra_num_cpu_domains = 4;
 		tegra_cpu_domains = tegra30_cpu_domains;
 		break;
+	case TEGRA114:
+		tegra_num_powerdomains = 23;
+		tegra_num_cpu_domains = 4;
+		tegra_cpu_domains = tegra114_cpu_domains;
+		break;
 	default:
 		/* Unknown Tegra variant. Disable powergating */
 		tegra_num_powerdomains = 0;
@@ -229,6 +242,27 @@
 	[TEGRA_POWERGATE_3D1]	= "3d1",
 };
 
+static const char * const powergate_name_t114[] = {
+	[TEGRA_POWERGATE_CPU]	= "cpu0",
+	[TEGRA_POWERGATE_3D]	= "3d",
+	[TEGRA_POWERGATE_VENC]	= "venc",
+	[TEGRA_POWERGATE_VDEC]	= "vdec",
+	[TEGRA_POWERGATE_MPE]	= "mpe",
+	[TEGRA_POWERGATE_HEG]	= "heg",
+	[TEGRA_POWERGATE_CPU1]	= "cpu1",
+	[TEGRA_POWERGATE_CPU2]	= "cpu2",
+	[TEGRA_POWERGATE_CPU3]	= "cpu3",
+	[TEGRA_POWERGATE_CELP]	= "celp",
+	[TEGRA_POWERGATE_CPU0]	= "cpu0",
+	[TEGRA_POWERGATE_C0NC]	= "c0nc",
+	[TEGRA_POWERGATE_C1NC]	= "c1nc",
+	[TEGRA_POWERGATE_DIS]	= "dis",
+	[TEGRA_POWERGATE_DISB]	= "disb",
+	[TEGRA_POWERGATE_XUSBA]	= "xusba",
+	[TEGRA_POWERGATE_XUSBB]	= "xusbb",
+	[TEGRA_POWERGATE_XUSBC]	= "xusbc",
+};
+
 static int powergate_show(struct seq_file *s, void *data)
 {
 	int i;
@@ -236,9 +270,14 @@
 	seq_printf(s, " powergate powered\n");
 	seq_printf(s, "------------------\n");
 
-	for (i = 0; i < tegra_num_powerdomains; i++)
+	for (i = 0; i < tegra_num_powerdomains; i++) {
+		if (!powergate_name[i])
+			continue;
+
 		seq_printf(s, " %9s %7s\n", powergate_name[i],
 			tegra_powergate_is_powered(i) ? "yes" : "no");
+	}
+
 	return 0;
 }
 
@@ -265,6 +304,9 @@
 	case TEGRA30:
 		powergate_name = powergate_name_t30;
 		break;
+	case TEGRA114:
+		powergate_name = powergate_name_t114;
+		break;
 	}
 
 	if (powergate_name) {
diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
index f527b2c..8c1ba4f 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -45,17 +45,11 @@
 ENTRY(tegra_resume)
 	check_cpu_part_num 0xc09, r8, r9
 	bleq	v7_invalidate_l1
-	blne	tegra_init_l2_for_a15
 
 	cpu_id	r0
-	tegra_get_soc_id TEGRA_APB_MISC_BASE, r6
-	cmp	r6, #TEGRA114
-	beq	no_cpu0_chk
-
 	cmp	r0, #0				@ CPU0?
  THUMB(	it	ne )
 	bne	cpu_resume			@ no
-no_cpu0_chk:
 
 	/* Are we on Tegra20? */
 	cmp	r6, #TEGRA20
@@ -75,7 +69,7 @@
 
 	mov32	r9, 0xc09
 	cmp	r8, r9
-	bne	not_ca9
+	bne	end_ca9_scu_l2_resume
 #ifdef CONFIG_HAVE_ARM_SCU
 	/* enable SCU */
 	mov32	r0, TEGRA_ARM_PERIF_BASE
@@ -86,7 +80,10 @@
 
 	/* L2 cache resume & re-enable */
 	l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr
-not_ca9:
+end_ca9_scu_l2_resume:
+	mov32	r9, 0xc0f
+	cmp	r8, r9
+	bleq	tegra_init_l2_for_a15
 
 	b	cpu_resume
 ENDPROC(tegra_resume)
diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c
index fd0bbf8..568f5bb 100644
--- a/arch/arm/mach-tegra/reset.c
+++ b/arch/arm/mach-tegra/reset.c
@@ -82,7 +82,7 @@
 
 #ifdef CONFIG_PM_SLEEP
 	__tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP1] =
-		TEGRA_IRAM_CODE_AREA;
+		TEGRA_IRAM_LPx_RESUME_AREA;
 	__tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP2] =
 		virt_to_phys((void *)tegra_resume);
 #endif
diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S
index 5c3bd11..aaaf3ab 100644
--- a/arch/arm/mach-tegra/sleep-tegra20.S
+++ b/arch/arm/mach-tegra/sleep-tegra20.S
@@ -25,6 +25,7 @@
 #include <asm/cp15.h>
 #include <asm/cache.h>
 
+#include "irammap.h"
 #include "sleep.h"
 #include "flowctrl.h"
 
@@ -235,7 +236,7 @@
 	mov32	r0, tegra20_tear_down_core
 	mov32	r1, tegra20_iram_start
 	sub	r0, r0, r1
-	mov32	r1, TEGRA_IRAM_CODE_AREA
+	mov32	r1, TEGRA_IRAM_LPx_RESUME_AREA
 	add	r0, r0, r1
 
 	mov	pc, r3
@@ -328,7 +329,7 @@
  * The physical address of tegra_resume expected to be stored in
  * PMC_SCRATCH41.
  *
- * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_CODE_AREA.
+ * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA.
  */
 ENTRY(tegra20_lp1_reset)
 	/*
diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S
index 63fa91b..b16d4a57 100644
--- a/arch/arm/mach-tegra/sleep-tegra30.S
+++ b/arch/arm/mach-tegra/sleep-tegra30.S
@@ -20,6 +20,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/cache.h>
 
+#include "irammap.h"
 #include "fuse.h"
 #include "sleep.h"
 #include "flowctrl.h"
@@ -262,7 +263,7 @@
 	mov32	r0, tegra30_tear_down_core
 	mov32	r1, tegra30_iram_start
 	sub	r0, r0, r1
-	mov32	r1, TEGRA_IRAM_CODE_AREA
+	mov32	r1, TEGRA_IRAM_LPx_RESUME_AREA
 	add	r0, r0, r1
 
 	mov	pc, r3
@@ -314,7 +315,7 @@
  * The physical address of tegra_resume expected to be stored in
  * PMC_SCRATCH41.
  *
- * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_CODE_AREA.
+ * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA.
  */
 ENTRY(tegra30_lp1_reset)
 	/*
@@ -382,7 +383,7 @@
 	add	r1, r1, #LOCK_DELAY
 	wait_until r1, r7, r3
 
-	adr	r5, tegra30_sdram_pad_save
+	adr	r5, tegra_sdram_pad_save
 
 	ldr	r4, [r5, #0x18]		@ restore CLK_SOURCE_MSELECT
 	str	r4, [r0, #CLK_RESET_CLK_SOURCE_MSELECT]
@@ -407,8 +408,12 @@
 	cmp	r10, #TEGRA30
 	movweq	r0, #:lower16:TEGRA_EMC_BASE	@ r0 reserved for emc base
 	movteq	r0, #:upper16:TEGRA_EMC_BASE
-	movwne	r0, #:lower16:TEGRA_EMC0_BASE
-	movtne	r0, #:upper16:TEGRA_EMC0_BASE
+	cmp	r10, #TEGRA114
+	movweq	r0, #:lower16:TEGRA_EMC0_BASE
+	movteq	r0, #:upper16:TEGRA_EMC0_BASE
+	cmp	r10, #TEGRA124
+	movweq	r0, #:lower16:TEGRA124_EMC_BASE
+	movteq	r0, #:upper16:TEGRA124_EMC_BASE
 
 exit_self_refresh:
 	ldr	r1, [r5, #0xC]		@ restore EMC_XM2VTTGENPADCTRL
@@ -537,6 +542,7 @@
 	.word	TEGRA_PMC_BASE + PMC_IO_DPD_STATUS			@0x14
 	.word	TEGRA_CLK_RESET_BASE + CLK_RESET_CLK_SOURCE_MSELECT	@0x18
 	.word	TEGRA_CLK_RESET_BASE + CLK_RESET_SCLK_BURST		@0x1c
+tegra30_sdram_pad_address_end:
 
 tegra114_sdram_pad_address:
 	.word	TEGRA_EMC0_BASE + EMC_CFG				@0x0
@@ -552,16 +558,28 @@
 	.word	TEGRA_EMC1_BASE + EMC_AUTO_CAL_INTERVAL			@0x28
 	.word	TEGRA_EMC1_BASE + EMC_XM2VTTGENPADCTRL			@0x2c
 	.word	TEGRA_EMC1_BASE + EMC_XM2VTTGENPADCTRL2			@0x30
+tegra114_sdram_pad_adress_end:
+
+tegra124_sdram_pad_address:
+	.word	TEGRA124_EMC_BASE + EMC_CFG				@0x0
+	.word	TEGRA124_EMC_BASE + EMC_ZCAL_INTERVAL			@0x4
+	.word	TEGRA124_EMC_BASE + EMC_AUTO_CAL_INTERVAL		@0x8
+	.word	TEGRA124_EMC_BASE + EMC_XM2VTTGENPADCTRL		@0xc
+	.word	TEGRA124_EMC_BASE + EMC_XM2VTTGENPADCTRL2		@0x10
+	.word	TEGRA_PMC_BASE + PMC_IO_DPD_STATUS			@0x14
+	.word	TEGRA_CLK_RESET_BASE + CLK_RESET_CLK_SOURCE_MSELECT	@0x18
+	.word	TEGRA_CLK_RESET_BASE + CLK_RESET_SCLK_BURST		@0x1c
+tegra124_sdram_pad_address_end:
 
 tegra30_sdram_pad_size:
-	.word	tegra114_sdram_pad_address - tegra30_sdram_pad_address
+	.word	tegra30_sdram_pad_address_end - tegra30_sdram_pad_address
 
 tegra114_sdram_pad_size:
-	.word	tegra30_sdram_pad_size - tegra114_sdram_pad_address
+	.word	tegra114_sdram_pad_adress_end - tegra114_sdram_pad_address
 
-	.type	tegra30_sdram_pad_save, %object
-tegra30_sdram_pad_save:
-	.rept (tegra30_sdram_pad_size - tegra114_sdram_pad_address) / 4
+	.type	tegra_sdram_pad_save, %object
+tegra_sdram_pad_save:
+	.rept (tegra114_sdram_pad_adress_end - tegra114_sdram_pad_address) / 4
 	.long	0
 	.endr
 
@@ -692,13 +710,18 @@
  */
 tegra30_sdram_self_refresh:
 
-	adr	r8, tegra30_sdram_pad_save
+	adr	r8, tegra_sdram_pad_save
 	tegra_get_soc_id TEGRA_APB_MISC_BASE, r10
 	cmp	r10, #TEGRA30
 	adreq	r2, tegra30_sdram_pad_address
 	ldreq	r3, tegra30_sdram_pad_size
-	adrne	r2, tegra114_sdram_pad_address
-	ldrne	r3, tegra114_sdram_pad_size
+	cmp	r10, #TEGRA114
+	adreq	r2, tegra114_sdram_pad_address
+	ldreq	r3, tegra114_sdram_pad_size
+	cmp	r10, #TEGRA124
+	adreq	r2, tegra124_sdram_pad_address
+	ldreq	r3, tegra30_sdram_pad_size
+
 	mov	r9, #0
 
 padsave:
@@ -716,7 +739,10 @@
 
 	cmp	r10, #TEGRA30
 	ldreq	r0, =TEGRA_EMC_BASE	@ r0 reserved for emc base addr
-	ldrne	r0, =TEGRA_EMC0_BASE
+	cmp	r10, #TEGRA114
+	ldreq	r0, =TEGRA_EMC0_BASE
+	cmp	r10, #TEGRA124
+	ldreq	r0, =TEGRA124_EMC_BASE
 
 enter_self_refresh:
 	cmp	r10, #TEGRA30
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index 5b86055..ce553d5 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -16,7 +16,6 @@
  *
  */
 
-#include <linux/clocksource.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -34,16 +33,78 @@
 #include <linux/sys_soc.h>
 #include <linux/usb/tegra_usb_phy.h>
 #include <linux/clk/tegra.h>
+#include <linux/irqchip.h>
 
+#include <asm/hardware/cache-l2x0.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/setup.h>
 
+#include "apbio.h"
 #include "board.h"
 #include "common.h"
+#include "cpuidle.h"
 #include "fuse.h"
 #include "iomap.h"
+#include "irq.h"
+#include "pmc.h"
+#include "pm.h"
+#include "reset.h"
+#include "sleep.h"
+
+/*
+ * Storage for debug-macro.S's state.
+ *
+ * This must be in .data not .bss so that it gets initialized each time the
+ * kernel is loaded. The data is declared here rather than debug-macro.S so
+ * that multiple inclusions of debug-macro.S point at the same data.
+ */
+u32 tegra_uart_config[4] = {
+	/* Debug UART initialization required */
+	1,
+	/* Debug UART physical address */
+	0,
+	/* Debug UART virtual address */
+	0,
+	/* Scratch space for debug macro */
+	0,
+};
+
+static void __init tegra_init_cache(void)
+{
+#ifdef CONFIG_CACHE_L2X0
+	int ret;
+	void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
+	u32 aux_ctrl, cache_type;
+
+	cache_type = readl(p + L2X0_CACHE_TYPE);
+	aux_ctrl = (cache_type & 0x700) << (17-8);
+	aux_ctrl |= 0x7C400001;
+
+	ret = l2x0_of_init(aux_ctrl, 0x8200c3fe);
+	if (!ret)
+		l2x0_saved_regs_addr = virt_to_phys(&l2x0_saved_regs);
+#endif
+}
+
+static void __init tegra_init_early(void)
+{
+	tegra_cpu_reset_handler_init();
+	tegra_apb_io_init();
+	tegra_init_fuse();
+	tegra_init_cache();
+	tegra_powergate_init();
+	tegra_hotplug_init();
+}
+
+static void __init tegra_dt_init_irq(void)
+{
+	tegra_pmc_init_irq();
+	tegra_init_irq();
+	irqchip_init();
+	tegra_legacy_irq_syscore_init();
+}
 
 static void __init tegra_dt_init(void)
 {
@@ -51,6 +112,8 @@
 	struct soc_device *soc_dev;
 	struct device *parent = NULL;
 
+	tegra_pmc_init();
+
 	tegra_clocks_apply_init_table();
 
 	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
@@ -97,7 +160,9 @@
 {
 	int i;
 
-	tegra_init_late();
+	tegra_init_suspend();
+	tegra_cpuidle_init();
+	tegra_powergate_debugfs_init();
 
 	for (i = 0; i < ARRAY_SIZE(board_init_funcs); i++) {
 		if (of_machine_is_compatible(board_init_funcs[i].machine)) {
@@ -108,6 +173,7 @@
 }
 
 static const char * const tegra_dt_board_compat[] = {
+	"nvidia,tegra124",
 	"nvidia,tegra114",
 	"nvidia,tegra30",
 	"nvidia,tegra20",
@@ -119,9 +185,8 @@
 	.smp		= smp_ops(tegra_smp_ops),
 	.init_early	= tegra_init_early,
 	.init_irq	= tegra_dt_init_irq,
-	.init_time	= clocksource_of_init,
 	.init_machine	= tegra_dt_init,
 	.init_late	= tegra_dt_init_late,
-	.restart	= tegra_assert_system_reset,
+	.restart	= tegra_pmc_restart,
 	.dt_compat	= tegra_dt_board_compat,
 MACHINE_END
diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig
index a165986..8e23071 100644
--- a/arch/arm/mach-u300/Kconfig
+++ b/arch/arm/mach-u300/Kconfig
@@ -5,7 +5,6 @@
 	select ARM_AMBA
 	select ARM_PATCH_PHYS_VIRT
 	select ARM_VIC
-	select CLKDEV_LOOKUP
 	select CLKSRC_MMIO
 	select CLKSRC_OF
 	select COMMON_CLK
diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c
index b5db207..9a5f9fb 100644
--- a/arch/arm/mach-u300/timer.c
+++ b/arch/arm/mach-u300/timer.c
@@ -358,8 +358,7 @@
  */
 static void __init u300_timer_init_of(struct device_node *np)
 {
-	struct resource irq_res;
-	int irq;
+	unsigned int irq;
 	struct clk *clk;
 	unsigned long rate;
 
@@ -368,11 +367,11 @@
 		panic("could not ioremap system timer\n");
 
 	/* Get the IRQ for the GP1 timer */
-	irq = of_irq_to_resource(np, 2, &irq_res);
-	if (irq <= 0)
+	irq = irq_of_parse_and_map(np, 2);
+	if (!irq)
 		panic("no IRQ for system timer\n");
 
-	pr_info("U300 GP1 timer @ base: %p, IRQ: %d\n", u300_timer_base, irq);
+	pr_info("U300 GP1 timer @ base: %p, IRQ: %u\n", u300_timer_base, irq);
 
 	/* Clock the interrupt controller */
 	clk = of_clk_get(np, 0);
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index 99a28d6..c67f8ad 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -1,36 +1,31 @@
 config ARCH_U8500
 	bool "ST-Ericsson U8500 Series" if ARCH_MULTI_V7
 	depends on MMU
+	select AB8500_CORE
+	select ABX500_CORE
 	select ARCH_HAS_CPUFREQ
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_AMBA
-	select CLKDEV_LOOKUP
-	select CPU_V7
-	select GENERIC_CLOCKEVENTS
-	select HAVE_ARM_SCU if SMP
-	select HAVE_ARM_TWD if SMP
-	select HAVE_SMP
-	select MIGHT_HAVE_CACHE_L2X0
-	help
-	  Support for ST-Ericsson's Ux500 architecture
-
-if ARCH_U8500
-
-config UX500_SOC_COMMON
-	bool
-	default y
-	select ABX500_CORE
-	select AB8500_CORE
 	select ARM_ERRATA_754322
 	select ARM_ERRATA_764369 if SMP
 	select ARM_GIC
 	select CACHE_L2X0
 	select CLKSRC_NOMADIK_MTU
 	select COMMON_CLK
+	select CPU_V7
+	select GENERIC_CLOCKEVENTS
+	select HAVE_ARM_SCU if SMP
+	select HAVE_ARM_TWD if SMP
+	select HAVE_SMP
+	select MIGHT_HAVE_CACHE_L2X0
 	select PINCTRL
-	select PINCTRL_NOMADIK
 	select PINCTRL_ABX500
+	select PINCTRL_NOMADIK
 	select PL310_ERRATA_753970 if CACHE_PL310
+	help
+	  Support for ST-Ericsson's Ux500 architecture
+
+if ARCH_U8500
 
 config UX500_SOC_DB8500
 	bool
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index fe1f3e2..616b96e 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -2,14 +2,11 @@
 # Makefile for the linux kernel, U8500 machine.
 #
 
-obj-y				:= cpu.o devices.o devices-common.o \
-				   id.o usb.o timer.o pm.o
+obj-y				:= cpu.o devices.o id.o timer.o pm.o
 obj-$(CONFIG_CACHE_L2X0)	+= cache-l2x0.o
 obj-$(CONFIG_UX500_SOC_DB8500)	+= cpu-db8500.o devices-db8500.o
 obj-$(CONFIG_MACH_MOP500)	+= board-mop500.o board-mop500-sdi.o \
 				board-mop500-regulators.o \
-				board-mop500-uib.o board-mop500-stuib.o \
-				board-mop500-u8500uib.o \
 				board-mop500-pins.o \
 				board-mop500-audio.o
 obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
diff --git a/arch/arm/mach-ux500/board-mop500-audio.c b/arch/arm/mach-ux500/board-mop500-audio.c
index ec08072..154e15f 100644
--- a/arch/arm/mach-ux500/board-mop500-audio.c
+++ b/arch/arm/mach-ux500/board-mop500-audio.c
@@ -68,40 +68,6 @@
 	.phy_channel = 1,
 };
 
-static struct platform_device *db8500_add_msp_i2s(struct device *parent,
-			int id,
-			resource_size_t base, int irq,
-			struct msp_i2s_platform_data *pdata)
-{
-	struct platform_device *pdev;
-	struct resource res[] = {
-		DEFINE_RES_MEM(base, SZ_4K),
-		DEFINE_RES_IRQ(irq),
-	};
-
-	pr_info("Register platform-device 'ux500-msp-i2s', id %d, irq %d\n",
-		id, irq);
-	pdev = platform_device_register_resndata(parent, "ux500-msp-i2s", id,
-						res, ARRAY_SIZE(res),
-						pdata, sizeof(*pdata));
-	if (!pdev) {
-		pr_err("Failed to register platform-device 'ux500-msp-i2s.%d'!\n",
-			id);
-		return NULL;
-	}
-
-	return pdev;
-}
-
-/* Platform device for ASoC MOP500 machine */
-static struct platform_device snd_soc_mop500 = {
-	.name = "snd-soc-mop500",
-	.id = 0,
-	.dev = {
-		.platform_data = NULL,
-	},
-};
-
 struct msp_i2s_platform_data msp2_platform_data = {
 	.id = MSP_I2S_2,
 	.msp_i2s_dma_rx = &msp2_dma_rx,
@@ -113,19 +79,3 @@
 	.msp_i2s_dma_rx	= &msp1_dma_rx,
 	.msp_i2s_dma_tx	= NULL,
 };
-
-void mop500_audio_init(struct device *parent)
-{
-	pr_info("%s: Register platform-device 'snd-soc-mop500'.\n", __func__);
-	platform_device_register(&snd_soc_mop500);
-
-	pr_info("Initialize MSP I2S-devices.\n");
-	db8500_add_msp_i2s(parent, 0, U8500_MSP0_BASE, IRQ_DB8500_MSP0,
-			   &msp0_platform_data);
-	db8500_add_msp_i2s(parent, 1, U8500_MSP1_BASE, IRQ_DB8500_MSP1,
-			   &msp1_platform_data);
-	db8500_add_msp_i2s(parent, 2, U8500_MSP2_BASE, IRQ_DB8500_MSP2,
-			   &msp2_platform_data);
-	db8500_add_msp_i2s(parent, 3, U8500_MSP3_BASE, IRQ_DB8500_MSP1,
-			   &msp3_platform_data);
-}
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
index b3e61a3..26600a1 100644
--- a/arch/arm/mach-ux500/board-mop500-sdi.c
+++ b/arch/arm/mach-ux500/board-mop500-sdi.c
@@ -65,18 +65,6 @@
 #endif
 };
 
-static void sdi0_configure(struct device *parent)
-{
-	/* Add the device, force v2 to subrevision 1 */
-	db8500_add_sdi0(parent, &mop500_sdi0_data, U8500_SDI_V2_PERIPHID);
-}
-
-void mop500_sdi_tc35892_init(struct device *parent)
-{
-	mop500_sdi0_data.gpio_cd = GPIO_SDMMC_CD;
-	sdi0_configure(parent);
-}
-
 /*
  * SDI1 (SDIO WLAN)
  */
@@ -178,42 +166,3 @@
 	.dma_tx_param	= &mop500_sdi4_dma_cfg_tx,
 #endif
 };
-
-void __init mop500_sdi_init(struct device *parent)
-{
-	/* PoP:ed eMMC */
-	db8500_add_sdi2(parent, &mop500_sdi2_data, U8500_SDI_V2_PERIPHID);
-	/* On-board eMMC */
-	db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID);
-
-	/*
-	 * On boards with the TC35892 GPIO expander, sdi0 will finally
-	 * be added when the TC35892 initializes and calls
-	 * mop500_sdi_tc35892_init() above.
-	 */
-}
-
-void __init snowball_sdi_init(struct device *parent)
-{
-	/* On Snowball MMC_CAP_SD_HIGHSPEED isn't supported (Hardware issue?) */
-	mop500_sdi0_data.capabilities &= ~MMC_CAP_SD_HIGHSPEED;
-	/* On-board eMMC */
-	db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID);
-	/* External Micro SD slot */
-	mop500_sdi0_data.gpio_cd = SNOWBALL_SDMMC_CD_GPIO;
-	mop500_sdi0_data.cd_invert = true;
-	sdi0_configure(parent);
-}
-
-void __init hrefv60_sdi_init(struct device *parent)
-{
-	/* PoP:ed eMMC */
-	db8500_add_sdi2(parent, &mop500_sdi2_data, U8500_SDI_V2_PERIPHID);
-	/* On-board eMMC */
-	db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID);
-	/* External Micro SD slot */
-	mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
-	sdi0_configure(parent);
-	/* WLAN SDIO channel */
-	db8500_add_sdi1(parent, &mop500_sdi1_data, U8500_SDI_V2_PERIPHID);
-}
diff --git a/arch/arm/mach-ux500/board-mop500-stuib.c b/arch/arm/mach-ux500/board-mop500-stuib.c
deleted file mode 100644
index 7e1f294..0000000
--- a/arch/arm/mach-ux500/board-mop500-stuib.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License terms: GNU General Public License (GPL), version 2
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mfd/stmpe.h>
-#include <linux/input/bu21013.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/input/matrix_keypad.h>
-#include <asm/mach-types.h>
-
-#include "board-mop500.h"
-
-/* STMPE/SKE keypad use this key layout */
-static const unsigned int mop500_keymap[] = {
-	KEY(2, 5, KEY_END),
-	KEY(4, 1, KEY_POWER),
-	KEY(3, 5, KEY_VOLUMEDOWN),
-	KEY(1, 3, KEY_3),
-	KEY(5, 2, KEY_RIGHT),
-	KEY(5, 0, KEY_9),
-
-	KEY(0, 5, KEY_MENU),
-	KEY(7, 6, KEY_ENTER),
-	KEY(4, 5, KEY_0),
-	KEY(6, 7, KEY_2),
-	KEY(3, 4, KEY_UP),
-	KEY(3, 3, KEY_DOWN),
-
-	KEY(6, 4, KEY_SEND),
-	KEY(6, 2, KEY_BACK),
-	KEY(4, 2, KEY_VOLUMEUP),
-	KEY(5, 5, KEY_1),
-	KEY(4, 3, KEY_LEFT),
-	KEY(3, 2, KEY_7),
-};
-
-static const struct matrix_keymap_data mop500_keymap_data = {
-	.keymap		= mop500_keymap,
-	.keymap_size    = ARRAY_SIZE(mop500_keymap),
-};
-/*
- * STMPE1601
- */
-static struct stmpe_keypad_platform_data stmpe1601_keypad_data = {
-	.debounce_ms    = 64,
-	.scan_count     = 8,
-	.no_autorepeat  = true,
-	.keymap_data    = &mop500_keymap_data,
-};
-
-static struct stmpe_platform_data stmpe1601_data = {
-	.id		= 1,
-	.blocks		= STMPE_BLOCK_KEYPAD,
-	.irq_trigger    = IRQF_TRIGGER_FALLING,
-	.irq_base       = MOP500_STMPE1601_IRQ(0),
-	.keypad		= &stmpe1601_keypad_data,
-	.autosleep      = true,
-	.autosleep_timeout = 1024,
-};
-
-static struct i2c_board_info __initdata mop500_i2c0_devices_stuib[] = {
-	{
-		I2C_BOARD_INFO("stmpe1601", 0x40),
-		.irq = NOMADIK_GPIO_TO_IRQ(218),
-		.platform_data = &stmpe1601_data,
-		.flags = I2C_CLIENT_WAKE,
-	},
-};
-
-/*
- * BU21013 ROHM touchscreen interface on the STUIBs
- */
-
-#define TOUCH_GPIO_PIN  84
-
-#define TOUCH_XMAX	384
-#define TOUCH_YMAX	704
-
-#define PRCMU_CLOCK_OCR		0x1CC
-#define TSC_EXT_CLOCK_9_6MHZ	0x840000
-
-static struct bu21013_platform_device tsc_plat_device = {
-	.touch_pin = TOUCH_GPIO_PIN,
-	.touch_x_max = TOUCH_XMAX,
-	.touch_y_max = TOUCH_YMAX,
-	.ext_clk = false,
-	.x_flip = false,
-	.y_flip = true,
-};
-
-static struct i2c_board_info __initdata u8500_i2c3_devices_stuib[] = {
-	{
-		I2C_BOARD_INFO("bu21013_tp", 0x5C),
-		.platform_data = &tsc_plat_device,
-	},
-	{
-		I2C_BOARD_INFO("bu21013_tp", 0x5D),
-		.platform_data = &tsc_plat_device,
-	},
-};
-
-void __init mop500_stuib_init(void)
-{
-	if (machine_is_hrefv60())
-		tsc_plat_device.cs_pin = HREFV60_TOUCH_RST_GPIO;
-	else
-		tsc_plat_device.cs_pin = GPIO_BU21013_CS;
-
-	mop500_uib_i2c_add(0, mop500_i2c0_devices_stuib,
-			ARRAY_SIZE(mop500_i2c0_devices_stuib));
-
-	mop500_uib_i2c_add(3, u8500_i2c3_devices_stuib,
-			ARRAY_SIZE(u8500_i2c3_devices_stuib));
-}
diff --git a/arch/arm/mach-ux500/board-mop500-u8500uib.c b/arch/arm/mach-ux500/board-mop500-u8500uib.c
deleted file mode 100644
index d397c19..0000000
--- a/arch/arm/mach-ux500/board-mop500-u8500uib.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Board data for the U8500 UIB, also known as the New UIB
- * License terms: GNU General Public License (GPL), version 2
- */
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/interrupt.h>
-#include <linux/mfd/tc3589x.h>
-#include <linux/input/matrix_keypad.h>
-
-#include "irqs.h"
-
-#include "board-mop500.h"
-
-static struct i2c_board_info __initdata mop500_i2c3_devices_u8500[] = {
-	{
-		I2C_BOARD_INFO("synaptics_rmi4_i2c", 0x4B),
-		.irq = NOMADIK_GPIO_TO_IRQ(84),
-	},
-};
-
-/*
- * TC35893
- */
-static const unsigned int u8500_keymap[] = {
-	KEY(3, 1, KEY_END),
-	KEY(4, 1, KEY_POWER),
-	KEY(6, 4, KEY_VOLUMEDOWN),
-	KEY(4, 2, KEY_EMAIL),
-	KEY(3, 3, KEY_RIGHT),
-	KEY(2, 5, KEY_BACKSPACE),
-
-	KEY(6, 7, KEY_MENU),
-	KEY(5, 0, KEY_ENTER),
-	KEY(4, 3, KEY_0),
-	KEY(3, 4, KEY_DOT),
-	KEY(5, 2, KEY_UP),
-	KEY(3, 5, KEY_DOWN),
-
-	KEY(4, 5, KEY_SEND),
-	KEY(0, 5, KEY_BACK),
-	KEY(6, 2, KEY_VOLUMEUP),
-	KEY(1, 3, KEY_SPACE),
-	KEY(7, 6, KEY_LEFT),
-	KEY(5, 5, KEY_SEARCH),
-};
-
-static struct matrix_keymap_data u8500_keymap_data = {
-	.keymap		= u8500_keymap,
-	.keymap_size    = ARRAY_SIZE(u8500_keymap),
-};
-
-static struct tc3589x_keypad_platform_data tc35893_data = {
-	.krow = TC_KPD_ROWS,
-	.kcol = TC_KPD_COLUMNS,
-	.debounce_period = TC_KPD_DEBOUNCE_PERIOD,
-	.settle_time = TC_KPD_SETTLE_TIME,
-	.irqtype = IRQF_TRIGGER_FALLING,
-	.enable_wakeup = true,
-	.keymap_data    = &u8500_keymap_data,
-	.no_autorepeat  = true,
-};
-
-static struct tc3589x_platform_data tc3589x_keypad_data = {
-	.block = TC3589x_BLOCK_KEYPAD,
-	.keypad = &tc35893_data,
-	.irq_base = MOP500_EGPIO_IRQ_BASE,
-};
-
-static struct i2c_board_info __initdata mop500_i2c0_devices_u8500[] = {
-	{
-		I2C_BOARD_INFO("tc3589x", 0x44),
-		.platform_data = &tc3589x_keypad_data,
-		.irq = NOMADIK_GPIO_TO_IRQ(218),
-		.flags = I2C_CLIENT_WAKE,
-	},
-};
-
-
-void __init mop500_u8500uib_init(void)
-{
-	mop500_uib_i2c_add(3, mop500_i2c3_devices_u8500,
-			ARRAY_SIZE(mop500_i2c3_devices_u8500));
-
-	mop500_uib_i2c_add(0, mop500_i2c0_devices_u8500,
-			ARRAY_SIZE(mop500_i2c0_devices_u8500));
-
-}
diff --git a/arch/arm/mach-ux500/board-mop500-uib.c b/arch/arm/mach-ux500/board-mop500-uib.c
deleted file mode 100644
index bdaa422..0000000
--- a/arch/arm/mach-ux500/board-mop500-uib.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
- * License terms: GNU General Public License (GPL), version 2
- */
-
-#define pr_fmt(fmt)	"mop500-uib: " fmt
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-
-#include "board-mop500.h"
-#include "id.h"
-
-enum mop500_uib {
-	STUIB,
-	U8500UIB,
-};
-
-struct uib {
-	const char *name;
-	const char *option;
-	void (*init)(void);
-};
-
-static struct uib __initdata mop500_uibs[] = {
-	[STUIB] = {
-		.name	= "ST-UIB",
-		.option	= "stuib",
-		.init	= mop500_stuib_init,
-	},
-	[U8500UIB] = {
-		.name	= "U8500-UIB",
-		.option	= "u8500uib",
-		.init	= mop500_u8500uib_init,
-	},
-};
-
-static struct uib *mop500_uib;
-
-static int __init mop500_uib_setup(char *str)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(mop500_uibs); i++) {
-		struct uib *uib = &mop500_uibs[i];
-
-		if (!strcmp(str, uib->option)) {
-			mop500_uib = uib;
-			break;
-		}
-	}
-
-	if (i == ARRAY_SIZE(mop500_uibs))
-		pr_err("invalid uib= option (%s)\n", str);
-
-	return 1;
-}
-__setup("uib=", mop500_uib_setup);
-
-/*
- * The UIBs are detected after the I2C host controllers are registered, so
- * i2c_register_board_info() can't be used.
- */
-void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
-		unsigned n)
-{
-	struct i2c_adapter *adap;
-	struct i2c_client *client;
-	int i;
-
-	adap = i2c_get_adapter(busnum);
-	if (!adap) {
-		pr_err("failed to get adapter i2c%d\n", busnum);
-		return;
-	}
-
-	for (i = 0; i < n; i++) {
-		client = i2c_new_device(adap, &info[i]);
-		if (!client)
-			pr_err("failed to register %s to i2c%d\n",
-					info[i].type, busnum);
-	}
-
-	i2c_put_adapter(adap);
-}
-
-static void __init __mop500_uib_init(struct uib *uib, const char *why)
-{
-	pr_info("%s (%s)\n", uib->name, why);
-	uib->init();
-}
-
-/*
- * Detect the UIB attached based on the presence or absence of i2c devices.
- */
-int __init mop500_uib_init(void)
-{
-	struct uib *uib = mop500_uib;
-	struct i2c_adapter *i2c0;
-	int ret;
-
-	if (!cpu_is_u8500_family())
-		return -ENODEV;
-
-	if (uib) {
-		__mop500_uib_init(uib, "from uib= boot argument");
-		return 0;
-	}
-
-	i2c0 = i2c_get_adapter(0);
-	if (!i2c0) {
-		__mop500_uib_init(&mop500_uibs[STUIB],
-				"fallback, could not get i2c0");
-		return -ENODEV;
-	}
-
-	/* U8500-UIB has the TC35893 at 0x44 on I2C0, the ST-UIB doesn't. */
-	ret = i2c_smbus_xfer(i2c0, 0x44, 0, I2C_SMBUS_WRITE, 0,
-			I2C_SMBUS_QUICK, NULL);
-	i2c_put_adapter(i2c0);
-
-	if (ret == 0)
-		uib = &mop500_uibs[U8500UIB];
-	else
-		uib = &mop500_uibs[STUIB];
-
-	__mop500_uib_init(uib, "detected");
-
-	return 0;
-}
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index ad0806e..514d40b 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -14,27 +14,16 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-#include <linux/i2c.h>
-#include <linux/platform_data/i2c-nomadik.h>
 #include <linux/platform_data/db8500_thermal.h>
-#include <linux/gpio.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl022.h>
-#include <linux/amba/serial.h>
-#include <linux/spi/spi.h>
 #include <linux/mfd/abx500/ab8500.h>
 #include <linux/regulator/ab8500.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/driver.h>
-#include <linux/regulator/gpio-regulator.h>
-#include <linux/mfd/tc3589x.h>
 #include <linux/mfd/tps6105x.h>
-#include <linux/mfd/abx500/ab8500-gpio.h>
-#include <linux/mfd/abx500/ab8500-codec.h>
 #include <linux/platform_data/leds-lp55xx.h>
 #include <linux/input.h>
-#include <linux/smsc911x.h>
-#include <linux/gpio_keys.h>
 #include <linux/delay.h>
 #include <linux/leds.h>
 #include <linux/pinctrl/consumer.h>
@@ -46,7 +35,6 @@
 #include "setup.h"
 #include "devices.h"
 #include "irqs.h"
-#include <linux/platform_data/crypto-ux500.h>
 
 #include "ste-dma40-db8500.h"
 #include "db8500-regs.h"
@@ -54,401 +42,9 @@
 #include "board-mop500.h"
 #include "board-mop500-regulators.h"
 
-static struct gpio_led snowball_led_array[] = {
-	{
-		.name = "user_led",
-		.default_trigger = "heartbeat",
-		.gpio = 142,
-	},
-};
-
-static struct gpio_led_platform_data snowball_led_data = {
-	.leds = snowball_led_array,
-	.num_leds = ARRAY_SIZE(snowball_led_array),
-};
-
-static struct platform_device snowball_led_dev = {
-	.name = "leds-gpio",
-	.dev = {
-		.platform_data = &snowball_led_data,
-	},
-};
-
-static struct fixed_voltage_config snowball_gpio_en_3v3_data = {
-       .supply_name            = "EN-3V3",
-       .gpio                   = SNOWBALL_EN_3V3_ETH_GPIO,
-       .microvolts             = 3300000,
-       .enable_high            = 1,
-       .init_data              = &gpio_en_3v3_regulator,
-       .startup_delay          = 5000, /* 1200us */
-};
-
-static struct platform_device snowball_gpio_en_3v3_regulator_dev = {
-       .name   = "reg-fixed-voltage",
-       .id     = 1,
-       .dev    = {
-               .platform_data  = &snowball_gpio_en_3v3_data,
-       },
-};
-
-/* Dynamically populated. */
-static struct gpio sdi0_reg_gpios[] = {
-	{ 0, GPIOF_OUT_INIT_LOW, "mmci_vsel" },
-};
-
-static struct gpio_regulator_state sdi0_reg_states[] = {
-	{ .value = 2900000, .gpios = (0 << 0) },
-	{ .value = 1800000, .gpios = (1 << 0) },
-};
-
-static struct gpio_regulator_config sdi0_reg_info = {
-	.supply_name		= "ext-mmc-level-shifter",
-	.gpios			= sdi0_reg_gpios,
-	.nr_gpios		= ARRAY_SIZE(sdi0_reg_gpios),
-	.states			= sdi0_reg_states,
-	.nr_states		= ARRAY_SIZE(sdi0_reg_states),
-	.type			= REGULATOR_VOLTAGE,
-	.enable_high		= 1,
-	.enabled_at_boot	= 0,
-	.init_data		= &sdi0_reg_init_data,
-	.startup_delay		= 100,
-};
-
-static struct platform_device sdi0_regulator = {
-	.name = "gpio-regulator",
-	.id   = -1,
-	.dev  = {
-		.platform_data = &sdi0_reg_info,
-	},
-};
-
-static struct abx500_gpio_platform_data ab8500_gpio_pdata = {
-	.gpio_base		= MOP500_AB8500_PIN_GPIO(1),
-};
-
-/* ab8500-codec */
-static struct ab8500_codec_platform_data ab8500_codec_pdata = {
-	.amics =  {
-		.mic1_type = AMIC_TYPE_DIFFERENTIAL,
-		.mic2_type = AMIC_TYPE_DIFFERENTIAL,
-		.mic1a_micbias = AMIC_MICBIAS_VAMIC1,
-		.mic1b_micbias = AMIC_MICBIAS_VAMIC1,
-		.mic2_micbias = AMIC_MICBIAS_VAMIC2
-	},
-	.ear_cmv = EAR_CMV_0_95V
-};
-
-static struct gpio_keys_button snowball_key_array[] = {
-	{
-		.gpio           = 32,
-		.type           = EV_KEY,
-		.code           = KEY_1,
-		.desc           = "userpb",
-		.active_low     = 1,
-		.debounce_interval = 50,
-		.wakeup         = 1,
-	},
-	{
-		.gpio           = 151,
-		.type           = EV_KEY,
-		.code           = KEY_2,
-		.desc           = "extkb1",
-		.active_low     = 1,
-		.debounce_interval = 50,
-		.wakeup         = 1,
-	},
-	{
-		.gpio           = 152,
-		.type           = EV_KEY,
-		.code           = KEY_3,
-		.desc           = "extkb2",
-		.active_low     = 1,
-		.debounce_interval = 50,
-		.wakeup         = 1,
-	},
-	{
-		.gpio           = 161,
-		.type           = EV_KEY,
-		.code           = KEY_4,
-		.desc           = "extkb3",
-		.active_low     = 1,
-		.debounce_interval = 50,
-		.wakeup         = 1,
-	},
-	{
-		.gpio           = 162,
-		.type           = EV_KEY,
-		.code           = KEY_5,
-		.desc           = "extkb4",
-		.active_low     = 1,
-		.debounce_interval = 50,
-		.wakeup         = 1,
-	},
-};
-
-static struct gpio_keys_platform_data snowball_key_data = {
-	.buttons        = snowball_key_array,
-	.nbuttons       = ARRAY_SIZE(snowball_key_array),
-};
-
-static struct platform_device snowball_key_dev = {
-	.name           = "gpio-keys",
-	.id             = -1,
-	.dev            = {
-		.platform_data  = &snowball_key_data,
-	}
-};
-
-static struct smsc911x_platform_config snowball_sbnet_cfg = {
-	.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
-	.irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
-	.flags = SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
-	.shift = 1,
-};
-
-static struct resource sbnet_res[] = {
-	{
-		.name = "smsc911x-memory",
-		.start = (0x5000 << 16),
-		.end  =  (0x5000 << 16) + 0xffff,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = NOMADIK_GPIO_TO_IRQ(140),
-		.end = NOMADIK_GPIO_TO_IRQ(140),
-		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
-	},
-};
-
-static struct platform_device snowball_sbnet_dev = {
-	.name           = "smsc911x",
-	.num_resources  = ARRAY_SIZE(sbnet_res),
-	.resource       = sbnet_res,
-	.dev            = {
-		.platform_data = &snowball_sbnet_cfg,
-	},
-};
-
 struct ab8500_platform_data ab8500_platdata = {
 	.irq_base	= MOP500_AB8500_IRQ_BASE,
 	.regulator	= &ab8500_regulator_plat_data,
-	.gpio		= &ab8500_gpio_pdata,
-	.codec		= &ab8500_codec_pdata,
-};
-
-static struct platform_device u8500_cpufreq_cooling_device = {
-	.name           = "db8500-cpufreq-cooling",
-};
-
-/*
- * TPS61052
- */
-
-static struct tps6105x_platform_data mop500_tps61052_data = {
-	.mode = TPS6105X_MODE_VOLTAGE,
-	.regulator_data = &tps61052_regulator,
-};
-
-/*
- * TC35892
- */
-
-static void mop500_tc35892_init(struct tc3589x *tc3589x, unsigned int base)
-{
-	struct device *parent = NULL;
-#if 0
-	/* FIXME: Is the sdi actually part of tc3589x? */
-	parent = tc3589x->dev;
-#endif
-	mop500_sdi_tc35892_init(parent);
-}
-
-static struct tc3589x_gpio_platform_data mop500_tc35892_gpio_data = {
-	.gpio_base	= MOP500_EGPIO(0),
-	.setup		= mop500_tc35892_init,
-};
-
-static struct tc3589x_platform_data mop500_tc35892_data = {
-	.block		= TC3589x_BLOCK_GPIO,
-	.gpio		= &mop500_tc35892_gpio_data,
-	.irq_base	= MOP500_EGPIO_IRQ_BASE,
-};
-
-static struct lp55xx_led_config lp5521_pri_led[] = {
-       [0] = {
-	       .chan_nr = 0,
-	       .led_current = 0x2f,
-	       .max_current = 0x5f,
-       },
-       [1] = {
-	       .chan_nr = 1,
-	       .led_current = 0x2f,
-	       .max_current = 0x5f,
-       },
-       [2] = {
-	       .chan_nr = 2,
-	       .led_current = 0x2f,
-	       .max_current = 0x5f,
-       },
-};
-
-static struct lp55xx_platform_data __initdata lp5521_pri_data = {
-       .label = "lp5521_pri",
-       .led_config     = &lp5521_pri_led[0],
-       .num_channels   = 3,
-       .clock_mode     = LP55XX_CLOCK_EXT,
-};
-
-static struct lp55xx_led_config lp5521_sec_led[] = {
-       [0] = {
-	       .chan_nr = 0,
-	       .led_current = 0x2f,
-	       .max_current = 0x5f,
-       },
-       [1] = {
-	       .chan_nr = 1,
-	       .led_current = 0x2f,
-	       .max_current = 0x5f,
-       },
-       [2] = {
-	       .chan_nr = 2,
-	       .led_current = 0x2f,
-	       .max_current = 0x5f,
-       },
-};
-
-static struct lp55xx_platform_data __initdata lp5521_sec_data = {
-       .label = "lp5521_sec",
-       .led_config     = &lp5521_sec_led[0],
-       .num_channels   = 3,
-       .clock_mode     = LP55XX_CLOCK_EXT,
-};
-
-/* I2C0 devices only available on the first HREF/MOP500 */
-static struct i2c_board_info __initdata mop500_i2c0_devices[] = {
-	{
-		I2C_BOARD_INFO("tc3589x", 0x42),
-		.irq		= NOMADIK_GPIO_TO_IRQ(217),
-		.platform_data  = &mop500_tc35892_data,
-	},
-	{
-		I2C_BOARD_INFO("tps61052", 0x33),
-		.platform_data  = &mop500_tps61052_data,
-	},
-};
-
-static struct i2c_board_info __initdata mop500_i2c2_devices[] = {
-	{
-		/* lp5521 LED driver, 1st device */
-		I2C_BOARD_INFO("lp5521", 0x33),
-		.platform_data = &lp5521_pri_data,
-	},
-	{
-		/* lp5521 LED driver, 2st device */
-		I2C_BOARD_INFO("lp5521", 0x34),
-		.platform_data = &lp5521_sec_data,
-	},
-	{
-		/* Light sensor Rohm BH1780GLI */
-		I2C_BOARD_INFO("bh1780", 0x29),
-	},
-};
-
-static int __init mop500_i2c_board_init(void)
-{
-	if (machine_is_u8500())
-		mop500_uib_i2c_add(0, mop500_i2c0_devices,
-				   ARRAY_SIZE(mop500_i2c0_devices));
-	mop500_uib_i2c_add(2, mop500_i2c2_devices,
-			   ARRAY_SIZE(mop500_i2c2_devices));
-	return 0;
-}
-device_initcall(mop500_i2c_board_init);
-
-static void __init mop500_i2c_init(struct device *parent)
-{
-	db8500_add_i2c0(parent, NULL);
-	db8500_add_i2c1(parent, NULL);
-	db8500_add_i2c2(parent, NULL);
-	db8500_add_i2c3(parent, NULL);
-}
-
-static struct gpio_keys_button mop500_gpio_keys[] = {
-	{
-		.desc			= "SFH7741 Proximity Sensor",
-		.type			= EV_SW,
-		.code			= SW_FRONT_PROXIMITY,
-		.active_low		= 0,
-		.can_disable		= 1,
-	}
-};
-
-static struct regulator *prox_regulator;
-static int mop500_prox_activate(struct device *dev);
-static void mop500_prox_deactivate(struct device *dev);
-
-static struct gpio_keys_platform_data mop500_gpio_keys_data = {
-	.buttons	= mop500_gpio_keys,
-	.nbuttons	= ARRAY_SIZE(mop500_gpio_keys),
-	.enable		= mop500_prox_activate,
-	.disable	= mop500_prox_deactivate,
-};
-
-static struct platform_device mop500_gpio_keys_device = {
-	.name	= "gpio-keys",
-	.id	= 0,
-	.dev	= {
-		.platform_data	= &mop500_gpio_keys_data,
-	},
-};
-
-static int mop500_prox_activate(struct device *dev)
-{
-	prox_regulator = regulator_get(&mop500_gpio_keys_device.dev,
-						"vcc");
-	if (IS_ERR(prox_regulator)) {
-		dev_err(&mop500_gpio_keys_device.dev,
-			"no regulator\n");
-		return PTR_ERR(prox_regulator);
-	}
-
-	return regulator_enable(prox_regulator);
-}
-
-static void mop500_prox_deactivate(struct device *dev)
-{
-	regulator_disable(prox_regulator);
-	regulator_put(prox_regulator);
-}
-
-static struct cryp_platform_data u8500_cryp1_platform_data = {
-		.mem_to_engine = {
-				.dir = DMA_MEM_TO_DEV,
-				.dev_type = DB8500_DMA_DEV48_CAC1,
-				.mode = STEDMA40_MODE_LOGICAL,
-		},
-		.engine_to_mem = {
-				.dir = DMA_DEV_TO_MEM,
-				.dev_type = DB8500_DMA_DEV48_CAC1,
-				.mode = STEDMA40_MODE_LOGICAL,
-		}
-};
-
-static struct stedma40_chan_cfg u8500_hash_dma_cfg_tx = {
-		.dir = DMA_MEM_TO_DEV,
-		.dev_type = DB8500_DMA_DEV50_HAC1_TX,
-		.mode = STEDMA40_MODE_LOGICAL,
-};
-
-static struct hash_platform_data u8500_hash1_platform_data = {
-		.mem_to_engine = &u8500_hash_dma_cfg_tx,
-		.dma_filter = stedma40_filter,
-};
-
-/* add any platform devices here - TODO */
-static struct platform_device *mop500_platform_devs[] __initdata = {
-	&mop500_gpio_keys_device,
-	&sdi0_regulator,
 };
 
 #ifdef CONFIG_STE_DMA40
@@ -480,236 +76,3 @@
 	 */
 	.num_chipselect = 5,
 };
-
-static void __init mop500_spi_init(struct device *parent)
-{
-	db8500_add_ssp0(parent, &ssp0_plat);
-}
-
-#ifdef CONFIG_STE_DMA40
-static struct stedma40_chan_cfg uart0_dma_cfg_rx = {
-	.mode = STEDMA40_MODE_LOGICAL,
-	.dir = DMA_DEV_TO_MEM,
-	.dev_type = DB8500_DMA_DEV13_UART0,
-};
-
-static struct stedma40_chan_cfg uart0_dma_cfg_tx = {
-	.mode = STEDMA40_MODE_LOGICAL,
-	.dir = DMA_MEM_TO_DEV,
-	.dev_type = DB8500_DMA_DEV13_UART0,
-};
-
-static struct stedma40_chan_cfg uart1_dma_cfg_rx = {
-	.mode = STEDMA40_MODE_LOGICAL,
-	.dir = DMA_DEV_TO_MEM,
-	.dev_type = DB8500_DMA_DEV12_UART1,
-};
-
-static struct stedma40_chan_cfg uart1_dma_cfg_tx = {
-	.mode = STEDMA40_MODE_LOGICAL,
-	.dir = DMA_MEM_TO_DEV,
-	.dev_type = DB8500_DMA_DEV12_UART1,
-};
-
-static struct stedma40_chan_cfg uart2_dma_cfg_rx = {
-	.mode = STEDMA40_MODE_LOGICAL,
-	.dir = DMA_DEV_TO_MEM,
-	.dev_type = DB8500_DMA_DEV11_UART2,
-};
-
-static struct stedma40_chan_cfg uart2_dma_cfg_tx = {
-	.mode = STEDMA40_MODE_LOGICAL,
-	.dir = DMA_MEM_TO_DEV,
-	.dev_type = DB8500_DMA_DEV11_UART2,
-};
-#endif
-
-struct amba_pl011_data uart0_plat = {
-#ifdef CONFIG_STE_DMA40
-	.dma_filter = stedma40_filter,
-	.dma_rx_param = &uart0_dma_cfg_rx,
-	.dma_tx_param = &uart0_dma_cfg_tx,
-#endif
-};
-
-struct amba_pl011_data uart1_plat = {
-#ifdef CONFIG_STE_DMA40
-	.dma_filter = stedma40_filter,
-	.dma_rx_param = &uart1_dma_cfg_rx,
-	.dma_tx_param = &uart1_dma_cfg_tx,
-#endif
-};
-
-struct amba_pl011_data uart2_plat = {
-#ifdef CONFIG_STE_DMA40
-	.dma_filter = stedma40_filter,
-	.dma_rx_param = &uart2_dma_cfg_rx,
-	.dma_tx_param = &uart2_dma_cfg_tx,
-#endif
-};
-
-static void __init mop500_uart_init(struct device *parent)
-{
-	db8500_add_uart0(parent, &uart0_plat);
-	db8500_add_uart1(parent, &uart1_plat);
-	db8500_add_uart2(parent, &uart2_plat);
-}
-
-static void __init u8500_cryp1_hash1_init(struct device *parent)
-{
-	db8500_add_cryp1(parent, &u8500_cryp1_platform_data);
-	db8500_add_hash1(parent, &u8500_hash1_platform_data);
-}
-
-static struct platform_device *snowball_platform_devs[] __initdata = {
-	&snowball_led_dev,
-	&snowball_key_dev,
-	&snowball_sbnet_dev,
-	&snowball_gpio_en_3v3_regulator_dev,
-	&u8500_cpufreq_cooling_device,
-	&sdi0_regulator,
-};
-
-static void __init mop500_init_machine(void)
-{
-	struct device *parent = NULL;
-	int i;
-
-	platform_device_register(&db8500_prcmu_device);
-	mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
-
-	sdi0_reg_info.enable_gpio = GPIO_SDMMC_EN;
-	sdi0_reg_info.gpios[0].gpio = GPIO_SDMMC_1V8_3V_SEL;
-
-	mop500_pinmaps_init();
-	parent = u8500_init_devices();
-
-	for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
-		mop500_platform_devs[i]->dev.parent = parent;
-
-	platform_add_devices(mop500_platform_devs,
-			ARRAY_SIZE(mop500_platform_devs));
-
-	mop500_i2c_init(parent);
-	mop500_sdi_init(parent);
-	mop500_spi_init(parent);
-	mop500_audio_init(parent);
-	mop500_uart_init(parent);
-	u8500_cryp1_hash1_init(parent);
-
-	/* This board has full regulator constraints */
-	regulator_has_full_constraints();
-}
-
-
-static void __init snowball_init_machine(void)
-{
-	struct device *parent = NULL;
-	int i;
-
-	platform_device_register(&db8500_prcmu_device);
-
-	sdi0_reg_info.enable_gpio = SNOWBALL_SDMMC_EN_GPIO;
-	sdi0_reg_info.gpios[0].gpio = SNOWBALL_SDMMC_1V8_3V_GPIO;
-
-	snowball_pinmaps_init();
-	parent = u8500_init_devices();
-
-	for (i = 0; i < ARRAY_SIZE(snowball_platform_devs); i++)
-		snowball_platform_devs[i]->dev.parent = parent;
-
-	platform_add_devices(snowball_platform_devs,
-			ARRAY_SIZE(snowball_platform_devs));
-
-	mop500_i2c_init(parent);
-	snowball_sdi_init(parent);
-	mop500_spi_init(parent);
-	mop500_audio_init(parent);
-	mop500_uart_init(parent);
-
-	u8500_cryp1_hash1_init(parent);
-
-	/* This board has full regulator constraints */
-	regulator_has_full_constraints();
-}
-
-static void __init hrefv60_init_machine(void)
-{
-	struct device *parent = NULL;
-	int i;
-
-	platform_device_register(&db8500_prcmu_device);
-	/*
-	 * The HREFv60 board removed a GPIO expander and routed
-	 * all these GPIO pins to the internal GPIO controller
-	 * instead.
-	 */
-	mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
-
-	sdi0_reg_info.enable_gpio = HREFV60_SDMMC_EN_GPIO;
-	sdi0_reg_info.gpios[0].gpio = HREFV60_SDMMC_1V8_3V_GPIO;
-
-	hrefv60_pinmaps_init();
-	parent = u8500_init_devices();
-
-	for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
-		mop500_platform_devs[i]->dev.parent = parent;
-
-	platform_add_devices(mop500_platform_devs,
-			ARRAY_SIZE(mop500_platform_devs));
-
-	mop500_i2c_init(parent);
-	hrefv60_sdi_init(parent);
-	mop500_spi_init(parent);
-	mop500_audio_init(parent);
-	mop500_uart_init(parent);
-
-	/* This board has full regulator constraints */
-	regulator_has_full_constraints();
-}
-
-MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
-	/* Maintainer: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> */
-	.atag_offset	= 0x100,
-	.smp		= smp_ops(ux500_smp_ops),
-	.map_io		= u8500_map_io,
-	.init_irq	= ux500_init_irq,
-	/* we re-use nomadik timer here */
-	.init_time	= ux500_timer_init,
-	.init_machine	= mop500_init_machine,
-	.init_late	= ux500_init_late,
-	.restart        = ux500_restart,
-MACHINE_END
-
-MACHINE_START(U8520, "ST-Ericsson U8520 Platform HREFP520")
-	.atag_offset	= 0x100,
-	.map_io		= u8500_map_io,
-	.init_irq	= ux500_init_irq,
-	.init_time	= ux500_timer_init,
-	.init_machine	= mop500_init_machine,
-	.init_late	= ux500_init_late,
-	.restart        = ux500_restart,
-MACHINE_END
-
-MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+")
-	.atag_offset	= 0x100,
-	.smp		= smp_ops(ux500_smp_ops),
-	.map_io		= u8500_map_io,
-	.init_irq	= ux500_init_irq,
-	.init_time	= ux500_timer_init,
-	.init_machine	= hrefv60_init_machine,
-	.init_late	= ux500_init_late,
-	.restart        = ux500_restart,
-MACHINE_END
-
-MACHINE_START(SNOWBALL, "Calao Systems Snowball platform")
-	.atag_offset	= 0x100,
-	.smp		= smp_ops(ux500_smp_ops),
-	.map_io		= u8500_map_io,
-	.init_irq	= ux500_init_irq,
-	/* we re-use nomadik timer here */
-	.init_time	= ux500_timer_init,
-	.init_machine	= snowball_init_machine,
-	.init_late	= NULL,
-	.restart        = ux500_restart,
-MACHINE_END
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
index d6fab16..511d6fe 100644
--- a/arch/arm/mach-ux500/board-mop500.h
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -79,7 +79,6 @@
 #define SNOWBALL_EN_3V3_ETH_GPIO	MOP500_AB8500_PIN_GPIO(26)	/* GPIO26 */
 
 struct device;
-struct i2c_board_info;
 extern struct mmci_platform_data mop500_sdi0_data;
 extern struct mmci_platform_data mop500_sdi1_data;
 extern struct mmci_platform_data mop500_sdi2_data;
@@ -88,25 +87,10 @@
 extern struct msp_i2s_platform_data msp1_platform_data;
 extern struct msp_i2s_platform_data msp2_platform_data;
 extern struct msp_i2s_platform_data msp3_platform_data;
-extern struct arm_pmu_platdata db8500_pmu_platdata;
-extern struct amba_pl011_data uart0_plat;
-extern struct amba_pl011_data uart1_plat;
-extern struct amba_pl011_data uart2_plat;
 extern struct pl022_ssp_controller ssp0_plat;
-extern struct stedma40_platform_data dma40_plat_data;
 
-extern void mop500_sdi_init(struct device *parent);
-extern void snowball_sdi_init(struct device *parent);
-extern void hrefv60_sdi_init(struct device *parent);
-extern void mop500_sdi_tc35892_init(struct device *parent);
-void __init mop500_u8500uib_init(void);
-void __init mop500_stuib_init(void);
 void __init mop500_pinmaps_init(void);
 void __init snowball_pinmaps_init(void);
 void __init hrefv60_pinmaps_init(void);
-void mop500_audio_init(struct device *parent);
 
-int __init mop500_uib_init(void);
-void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
-		unsigned n);
 #endif
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index 301c346..2e85c1e 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -32,7 +32,6 @@
 #include "irqs.h"
 
 #include "devices-db8500.h"
-#include "ste-dma40-db8500.h"
 #include "db8500-regs.h"
 #include "board-mop500.h"
 #include "id.h"
@@ -93,14 +92,6 @@
 		iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc));
 }
 
-static struct resource db8500_pmu_resources[] = {
-	[0] = {
-		.start		= IRQ_DB8500_PMU,
-		.end		= IRQ_DB8500_PMU,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
 /*
  * The PMU IRQ lines of two cores are wired together into a single interrupt.
  * Bounce the interrupt to the other core if it's not ours.
@@ -125,54 +116,6 @@
 	.handle_irq		= db8500_pmu_handler,
 };
 
-static struct platform_device db8500_pmu_device = {
-	.name			= "arm-pmu",
-	.id			= -1,
-	.num_resources		= ARRAY_SIZE(db8500_pmu_resources),
-	.resource		= db8500_pmu_resources,
-	.dev.platform_data	= &db8500_pmu_platdata,
-};
-
-static struct platform_device *platform_devs[] __initdata = {
-	&u8500_dma40_device,
-	&db8500_pmu_device,
-};
-
-static resource_size_t __initdata db8500_gpio_base[] = {
-	U8500_GPIOBANK0_BASE,
-	U8500_GPIOBANK1_BASE,
-	U8500_GPIOBANK2_BASE,
-	U8500_GPIOBANK3_BASE,
-	U8500_GPIOBANK4_BASE,
-	U8500_GPIOBANK5_BASE,
-	U8500_GPIOBANK6_BASE,
-	U8500_GPIOBANK7_BASE,
-	U8500_GPIOBANK8_BASE,
-};
-
-static void __init db8500_add_gpios(struct device *parent)
-{
-	struct nmk_gpio_platform_data pdata = {
-		.supports_sleepmode = true,
-	};
-
-	dbx500_add_gpios(parent, db8500_gpio_base,
-			 ARRAY_SIZE(db8500_gpio_base),
-			 IRQ_DB8500_GPIO0, &pdata);
-	dbx500_add_pinctrl(parent, "pinctrl-db8500", U8500_PRCMU_BASE);
-}
-
-static int usb_db8500_dma_cfg[] = {
-	DB8500_DMA_DEV38_USB_OTG_IEP_AND_OEP_1_9,
-	DB8500_DMA_DEV37_USB_OTG_IEP_AND_OEP_2_10,
-	DB8500_DMA_DEV36_USB_OTG_IEP_AND_OEP_3_11,
-	DB8500_DMA_DEV19_USB_OTG_IEP_AND_OEP_4_12,
-	DB8500_DMA_DEV18_USB_OTG_IEP_AND_OEP_5_13,
-	DB8500_DMA_DEV17_USB_OTG_IEP_AND_OEP_6_14,
-	DB8500_DMA_DEV16_USB_OTG_IEP_AND_OEP_7_15,
-	DB8500_DMA_DEV39_USB_OTG_IEP_AND_OEP_8
-};
-
 static const char *db8500_read_soc_id(void)
 {
 	void __iomem *uid = __io_address(U8500_BB_UID_BASE);
@@ -192,60 +135,22 @@
 	return ux500_soc_device_init(soc_id);
 }
 
-/*
- * This function is called from the board init
- */
-struct device * __init u8500_init_devices(void)
-{
-	struct device *parent;
-	int i;
-
-	parent = db8500_soc_device_init();
-
-	db8500_add_rtc(parent);
-	db8500_add_gpios(parent);
-	db8500_add_usb(parent, usb_db8500_dma_cfg, usb_db8500_dma_cfg);
-
-	for (i = 0; i < ARRAY_SIZE(platform_devs); i++)
-		platform_devs[i]->dev.parent = parent;
-
-	platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
-
-	return parent;
-}
-
 #ifdef CONFIG_MACH_UX500_DT
 static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
 	/* Requires call-back bindings. */
 	OF_DEV_AUXDATA("arm,cortex-a9-pmu", 0, "arm-pmu", &db8500_pmu_platdata),
 	/* Requires DMA bindings. */
-	OF_DEV_AUXDATA("arm,pl011", 0x80120000, "uart0", NULL),
-	OF_DEV_AUXDATA("arm,pl011", 0x80121000, "uart1", NULL),
-	OF_DEV_AUXDATA("arm,pl011", 0x80007000, "uart2", NULL),
-	OF_DEV_AUXDATA("arm,pl022", 0x80002000, "ssp0",  &ssp0_plat),
-	OF_DEV_AUXDATA("arm,pl18x", 0x80126000, "sdi0",  NULL),
-	OF_DEV_AUXDATA("arm,pl18x", 0x80118000, "sdi1",  NULL),
-	OF_DEV_AUXDATA("arm,pl18x", 0x80005000, "sdi2",  NULL),
-	OF_DEV_AUXDATA("arm,pl18x", 0x80114000, "sdi4",  NULL),
-	/* Requires clock name bindings. */
-	OF_DEV_AUXDATA("st,nomadik-gpio", 0x8012e000, "gpio.0", NULL),
-	OF_DEV_AUXDATA("st,nomadik-gpio", 0x8012e080, "gpio.1", NULL),
-	OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e000, "gpio.2", NULL),
-	OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e080, "gpio.3", NULL),
-	OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e100, "gpio.4", NULL),
-	OF_DEV_AUXDATA("st,nomadik-gpio", 0x8000e180, "gpio.5", NULL),
-	OF_DEV_AUXDATA("st,nomadik-gpio", 0x8011e000, "gpio.6", NULL),
-	OF_DEV_AUXDATA("st,nomadik-gpio", 0x8011e080, "gpio.7", NULL),
-	OF_DEV_AUXDATA("st,nomadik-gpio", 0xa03fe000, "gpio.8", NULL),
-	OF_DEV_AUXDATA("st,nomadik-i2c", 0x80004000, "nmk-i2c.0", NULL),
-	OF_DEV_AUXDATA("st,nomadik-i2c", 0x80122000, "nmk-i2c.1", NULL),
-	OF_DEV_AUXDATA("st,nomadik-i2c", 0x80128000, "nmk-i2c.2", NULL),
-	OF_DEV_AUXDATA("st,nomadik-i2c", 0x80110000, "nmk-i2c.3", NULL),
-	OF_DEV_AUXDATA("st,nomadik-i2c", 0x8012a000, "nmk-i2c.4", NULL),
-	OF_DEV_AUXDATA("stericsson,db8500-musb", 0xa03e0000, "musb-ux500.0", NULL),
+	OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80123000,
+		       "ux500-msp-i2s.0", &msp0_platform_data),
+	OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80124000,
+		       "ux500-msp-i2s.1", &msp1_platform_data),
+	OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80117000,
+		       "ux500-msp-i2s.2", &msp2_platform_data),
+	OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80125000,
+		       "ux500-msp-i2s.3", &msp3_platform_data),
+	/* Requires non-DT:able platform data. */
 	OF_DEV_AUXDATA("stericsson,db8500-prcmu", 0x80157000, "db8500-prcmu",
 			&db8500_prcmu_pdata),
-	OF_DEV_AUXDATA("smsc,lan9115", 0x50000000, "smsc911x.0", NULL),
 	OF_DEV_AUXDATA("stericsson,ux500-cryp", 0xa03cb000, "cryp1", NULL),
 	OF_DEV_AUXDATA("stericsson,ux500-hash", 0xa03c2000, "hash1", NULL),
 	OF_DEV_AUXDATA("stericsson,snd-soc-mop500", 0, "snd-soc-mop500.0",
@@ -253,17 +158,6 @@
 	/* Requires device name bindings. */
 	OF_DEV_AUXDATA("stericsson,db8500-pinctrl", U8500_PRCMU_BASE,
 		"pinctrl-db8500", NULL),
-	/* Requires clock name and DMA bindings. */
-	OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80123000,
-		"ux500-msp-i2s.0", &msp0_platform_data),
-	OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80124000,
-		"ux500-msp-i2s.1", &msp1_platform_data),
-	OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80117000,
-		"ux500-msp-i2s.2", &msp2_platform_data),
-	OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80125000,
-		"ux500-msp-i2s.3", &msp3_platform_data),
-	/* Requires clock name bindings and channel address lookup table. */
-	OF_DEV_AUXDATA("stericsson,db8500-dma40", 0x801C0000, "dma40.0", NULL),
 	{},
 };
 
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index 5d7eebc..f84d439 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -78,9 +78,17 @@
 	if (cpu_is_u8500_family()) {
 		prcmu_early_init(U8500_PRCMU_BASE, SZ_8K - 1);
 		ux500_pm_init(U8500_PRCMU_BASE, SZ_8K - 1);
-		u8500_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE,
-			       U8500_CLKRST3_BASE, U8500_CLKRST5_BASE,
-			       U8500_CLKRST6_BASE);
+
+		if (of_have_populated_dt())
+			u8500_of_clk_init(U8500_CLKRST1_BASE,
+					  U8500_CLKRST2_BASE,
+					  U8500_CLKRST3_BASE,
+					  U8500_CLKRST5_BASE,
+					  U8500_CLKRST6_BASE);
+		else
+			u8500_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE,
+				       U8500_CLKRST3_BASE, U8500_CLKRST5_BASE,
+				       U8500_CLKRST6_BASE);
 	} else if (cpu_is_u9540()) {
 		prcmu_early_init(U8500_PRCMU_BASE, SZ_8K - 1);
 		ux500_pm_init(U8500_PRCMU_BASE, SZ_8K - 1);
@@ -96,11 +104,6 @@
 	}
 }
 
-void __init ux500_init_late(void)
-{
-	mop500_uib_init();
-}
-
 static const char * __init ux500_get_machine(void)
 {
 	return kasprintf(GFP_KERNEL, "DB%4x", dbx500_partnumber());
diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c
deleted file mode 100644
index f71b3d7..0000000
--- a/arch/arm/mach-ux500/devices-common.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
- * License terms: GNU General Public License (GPL), version 2.
- */
-
-#include <linux/kernel.h>
-#include <linux/dma-mapping.h>
-#include <linux/err.h>
-#include <linux/irq.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/platform_data/pinctrl-nomadik.h>
-
-#include "irqs.h"
-
-#include "devices-common.h"
-
-static struct platform_device *
-dbx500_add_gpio(struct device *parent, int id, resource_size_t addr, int irq,
-		struct nmk_gpio_platform_data *pdata)
-{
-	struct resource resources[] = {
-		{
-			.start	= addr,
-			.end	= addr + 127,
-			.flags	= IORESOURCE_MEM,
-		},
-		{
-			.start	= irq,
-			.end	= irq,
-			.flags	= IORESOURCE_IRQ,
-		}
-	};
-
-	return platform_device_register_resndata(
-		parent,
-		"gpio",
-		id,
-		resources,
-		ARRAY_SIZE(resources),
-		pdata,
-		sizeof(*pdata));
-}
-
-void dbx500_add_gpios(struct device *parent, resource_size_t *base, int num,
-		      int irq, struct nmk_gpio_platform_data *pdata)
-{
-	int first = 0;
-	int i;
-
-	for (i = 0; i < num; i++, first += 32, irq++) {
-		pdata->first_gpio = first;
-		pdata->first_irq = NOMADIK_GPIO_TO_IRQ(first);
-		pdata->num_gpio = 32;
-
-		dbx500_add_gpio(parent, i, base[i], irq, pdata);
-	}
-}
diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h
deleted file mode 100644
index 96fa4ac..0000000
--- a/arch/arm/mach-ux500/devices-common.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
- * License terms: GNU General Public License (GPL), version 2.
- */
-
-#ifndef __DEVICES_COMMON_H
-#define __DEVICES_COMMON_H
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/sys_soc.h>
-#include <linux/amba/bus.h>
-#include <linux/platform_data/i2c-nomadik.h>
-#include <linux/platform_data/crypto-ux500.h>
-
-struct spi_master_cntlr;
-
-static inline struct amba_device *
-dbx500_add_msp_spi(struct device *parent, const char *name,
-		   resource_size_t base, int irq,
-		   struct spi_master_cntlr *pdata)
-{
-	return amba_ahb_device_add(parent, name, base, SZ_4K, irq, 0,
-				   pdata, 0);
-}
-
-static inline struct amba_device *
-dbx500_add_spi(struct device *parent, const char *name, resource_size_t base,
-	       int irq, struct spi_master_cntlr *pdata,
-	       u32 periphid)
-{
-	return amba_ahb_device_add(parent, name, base, SZ_4K, irq, 0,
-				   pdata, periphid);
-}
-
-struct mmci_platform_data;
-
-static inline struct amba_device *
-dbx500_add_sdi(struct device *parent, const char *name, resource_size_t base,
-	       int irq, struct mmci_platform_data *pdata, u32 periphid)
-{
-	return amba_ahb_device_add(parent, name, base, SZ_4K, irq, 0,
-				   pdata, periphid);
-}
-
-struct amba_pl011_data;
-
-static inline struct amba_device *
-dbx500_add_uart(struct device *parent, const char *name, resource_size_t base,
-		int irq, struct amba_pl011_data *pdata)
-{
-	return amba_ahb_device_add(parent, name, base, SZ_4K, irq, 0, pdata, 0);
-}
-
-struct nmk_i2c_controller;
-
-static inline struct amba_device *
-dbx500_add_i2c(struct device *parent, int id, resource_size_t base, int irq,
-	       struct nmk_i2c_controller *data)
-{
-	/* Conjure a name similar to what the platform device used to have */
-	char name[16];
-
-	snprintf(name, sizeof(name), "nmk-i2c.%d", id);
-	return amba_apb_device_add(parent, name, base, SZ_4K, irq, 0, data, 0);
-}
-
-static inline struct amba_device *
-dbx500_add_rtc(struct device *parent, resource_size_t base, int irq)
-{
-	return amba_apb_device_add(parent, "rtc-pl031", base, SZ_4K, irq,
-				0, NULL, 0);
-}
-
-struct cryp_platform_data;
-
-static inline struct platform_device *
-dbx500_add_cryp1(struct device *parent, int id, resource_size_t base, int irq,
-		struct cryp_platform_data *pdata)
-{
-	struct resource res[] = {
-			DEFINE_RES_MEM(base, SZ_4K),
-			DEFINE_RES_IRQ(irq),
-	};
-
-	struct platform_device_info pdevinfo = {
-			.parent = parent,
-			.name = "cryp1",
-			.id = id,
-			.res = res,
-			.num_res = ARRAY_SIZE(res),
-			.data = pdata,
-			.size_data = sizeof(*pdata),
-			.dma_mask = DMA_BIT_MASK(32),
-	};
-
-	return platform_device_register_full(&pdevinfo);
-}
-
-struct hash_platform_data;
-
-static inline struct platform_device *
-dbx500_add_hash1(struct device *parent, int id, resource_size_t base,
-		struct hash_platform_data *pdata)
-{
-	struct resource res[] = {
-			DEFINE_RES_MEM(base, SZ_4K),
-	};
-
-	struct platform_device_info pdevinfo = {
-			.parent = parent,
-			.name = "hash1",
-			.id = id,
-			.res = res,
-			.num_res = ARRAY_SIZE(res),
-			.data = pdata,
-			.size_data = sizeof(*pdata),
-			.dma_mask = DMA_BIT_MASK(32),
-	};
-
-	return platform_device_register_full(&pdevinfo);
-}
-
-struct nmk_gpio_platform_data;
-
-void dbx500_add_gpios(struct device *parent, resource_size_t *base, int num,
-		      int irq, struct nmk_gpio_platform_data *pdata);
-
-static inline void
-dbx500_add_pinctrl(struct device *parent, const char *name,
-		   resource_size_t base)
-{
-	struct resource res[] = {
-		DEFINE_RES_MEM(base, SZ_8K),
-	};
-	struct platform_device_info pdevinfo = {
-		.parent = parent,
-		.name = name,
-		.id = -1,
-		.res = res,
-		.num_res = ARRAY_SIZE(res),
-	};
-
-	platform_device_register_full(&pdevinfo);
-}
-
-#endif
diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c
index bc31606..c59f89d 100644
--- a/arch/arm/mach-ux500/devices-db8500.c
+++ b/arch/arm/mach-ux500/devices-db8500.c
@@ -9,10 +9,8 @@
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
-#include <linux/gpio.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl022.h>
-#include <linux/platform_data/dma-ste-dma40.h>
 #include <linux/mfd/dbx500-prcmu.h>
 
 #include "setup.h"
@@ -20,62 +18,6 @@
 
 #include "db8500-regs.h"
 #include "devices-db8500.h"
-#include "ste-dma40-db8500.h"
-
-static struct resource dma40_resources[] = {
-	[0] = {
-		.start = U8500_DMA_BASE,
-		.end   = U8500_DMA_BASE + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-		.name  = "base",
-	},
-	[1] = {
-		.start = U8500_DMA_LCPA_BASE,
-		.end   = U8500_DMA_LCPA_BASE + 2 * SZ_1K - 1,
-		.flags = IORESOURCE_MEM,
-		.name  = "lcpa",
-	},
-	[2] = {
-		.start = IRQ_DB8500_DMA,
-		.end   = IRQ_DB8500_DMA,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-struct stedma40_platform_data dma40_plat_data = {
-	.disabled_channels = {-1},
-};
-
-struct platform_device u8500_dma40_device = {
-	.dev = {
-		.platform_data = &dma40_plat_data,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-	.name = "dma40",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(dma40_resources),
-	.resource = dma40_resources
-};
-
-struct resource keypad_resources[] = {
-	[0] = {
-		.start = U8500_SKE_BASE,
-		.end = U8500_SKE_BASE + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_DB8500_KB,
-		.end = IRQ_DB8500_KB,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device u8500_ske_keypad_device = {
-	.name = "nmk-ske-keypad",
-	.id = -1,
-	.num_resources = ARRAY_SIZE(keypad_resources),
-	.resource = keypad_resources,
-};
 
 struct prcmu_pdata db8500_prcmu_pdata = {
 	.ab_platdata	= &ab8500_platdata,
@@ -84,39 +26,3 @@
 	.version_offset	= DB8500_PRCMU_FW_VERSION_OFFSET,
 	.legacy_offset	= DB8500_PRCMU_LEGACY_OFFSET,
 };
-
-static struct resource db8500_prcmu_res[] = {
-	{
-		.name  = "prcmu",
-		.start = U8500_PRCMU_BASE,
-		.end   = U8500_PRCMU_BASE + SZ_8K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name  = "prcmu-tcdm",
-		.start = U8500_PRCMU_TCDM_BASE,
-		.end   = U8500_PRCMU_TCDM_BASE + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name  = "irq",
-		.start = IRQ_DB8500_PRCMU1,
-		.end   = IRQ_DB8500_PRCMU1,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name  = "prcmu-tcpm",
-		.start = U8500_PRCMU_TCPM_BASE,
-		.end   = U8500_PRCMU_TCPM_BASE + SZ_32K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-};
-
-struct platform_device db8500_prcmu_device = {
-	.name			= "db8500-prcmu",
-	.resource		= db8500_prcmu_res,
-	.num_resources		= ARRAY_SIZE(db8500_prcmu_res),
-	.dev = {
-		.platform_data = &db8500_prcmu_pdata,
-	},
-};
diff --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h
index 3219983..b8ffc99 100644
--- a/arch/arm/mach-ux500/devices-db8500.h
+++ b/arch/arm/mach-ux500/devices-db8500.h
@@ -8,122 +8,12 @@
 #ifndef __DEVICES_DB8500_H
 #define __DEVICES_DB8500_H
 
-#include <linux/platform_data/usb-musb-ux500.h>
 #include "irqs.h"
 #include "db8500-regs.h"
-#include "devices-common.h"
 
-struct ske_keypad_platform_data;
-struct pl022_ssp_controller;
 struct platform_device;
 
 extern struct ab8500_platform_data ab8500_platdata;
 extern struct prcmu_pdata db8500_prcmu_pdata;
-extern struct platform_device db8500_prcmu_device;
 
-static inline struct platform_device *
-db8500_add_ske_keypad(struct device *parent,
-		      struct ske_keypad_platform_data *pdata,
-		      size_t size)
-{
-	struct resource resources[] = {
-		DEFINE_RES_MEM(U8500_SKE_BASE, SZ_4K),
-		DEFINE_RES_IRQ(IRQ_DB8500_KB),
-	};
-
-	return platform_device_register_resndata(parent, "nmk-ske-keypad", -1,
-						 resources, 2, pdata, size);
-}
-
-static inline struct amba_device *
-db8500_add_ssp(struct device *parent, const char *name, resource_size_t base,
-	       int irq, struct pl022_ssp_controller *pdata)
-{
-	return amba_ahb_device_add(parent, name, base, SZ_4K, irq, 0, pdata, 0);
-}
-
-#define db8500_add_i2c0(parent, pdata) \
-	dbx500_add_i2c(parent, 0, U8500_I2C0_BASE, IRQ_DB8500_I2C0, pdata)
-#define db8500_add_i2c1(parent, pdata) \
-	dbx500_add_i2c(parent, 1, U8500_I2C1_BASE, IRQ_DB8500_I2C1, pdata)
-#define db8500_add_i2c2(parent, pdata) \
-	dbx500_add_i2c(parent, 2, U8500_I2C2_BASE, IRQ_DB8500_I2C2, pdata)
-#define db8500_add_i2c3(parent, pdata) \
-	dbx500_add_i2c(parent, 3, U8500_I2C3_BASE, IRQ_DB8500_I2C3, pdata)
-#define db8500_add_i2c4(parent, pdata) \
-	dbx500_add_i2c(parent, 4, U8500_I2C4_BASE, IRQ_DB8500_I2C4, pdata)
-
-#define db8500_add_msp0_spi(parent, pdata) \
-	dbx500_add_msp_spi(parent, "msp0", U8500_MSP0_BASE, \
-			   IRQ_DB8500_MSP0, pdata)
-#define db8500_add_msp1_spi(parent, pdata) \
-	dbx500_add_msp_spi(parent, "msp1", U8500_MSP1_BASE, \
-			   IRQ_DB8500_MSP1, pdata)
-#define db8500_add_msp2_spi(parent, pdata) \
-	dbx500_add_msp_spi(parent, "msp2", U8500_MSP2_BASE, \
-			   IRQ_DB8500_MSP2, pdata)
-#define db8500_add_msp3_spi(parent, pdata) \
-	dbx500_add_msp_spi(parent, "msp3", U8500_MSP3_BASE, \
-			   IRQ_DB8500_MSP1, pdata)
-
-#define db8500_add_rtc(parent) \
-	dbx500_add_rtc(parent, U8500_RTC_BASE, IRQ_DB8500_RTC);
-
-#define db8500_add_usb(parent, rx_cfg, tx_cfg) \
-	ux500_add_usb(parent, U8500_USBOTG_BASE, \
-		      IRQ_DB8500_USBOTG, rx_cfg, tx_cfg)
-
-#define db8500_add_sdi0(parent, pdata, pid) \
-	dbx500_add_sdi(parent, "sdi0", U8500_SDI0_BASE, \
-		       IRQ_DB8500_SDMMC0, pdata, pid)
-#define db8500_add_sdi1(parent, pdata, pid) \
-	dbx500_add_sdi(parent, "sdi1", U8500_SDI1_BASE, \
-		       IRQ_DB8500_SDMMC1, pdata, pid)
-#define db8500_add_sdi2(parent, pdata, pid) \
-	dbx500_add_sdi(parent, "sdi2", U8500_SDI2_BASE, \
-		       IRQ_DB8500_SDMMC2, pdata, pid)
-#define db8500_add_sdi3(parent, pdata, pid) \
-	dbx500_add_sdi(parent, "sdi3", U8500_SDI3_BASE, \
-		       IRQ_DB8500_SDMMC3, pdata, pid)
-#define db8500_add_sdi4(parent, pdata, pid) \
-	dbx500_add_sdi(parent, "sdi4", U8500_SDI4_BASE, \
-		       IRQ_DB8500_SDMMC4, pdata, pid)
-#define db8500_add_sdi5(parent, pdata, pid) \
-	dbx500_add_sdi(parent, "sdi5", U8500_SDI5_BASE, \
-		       IRQ_DB8500_SDMMC5, pdata, pid)
-
-#define db8500_add_ssp0(parent, pdata) \
-	db8500_add_ssp(parent, "ssp0", U8500_SSP0_BASE, \
-		       IRQ_DB8500_SSP0, pdata)
-#define db8500_add_ssp1(parent, pdata) \
-	db8500_add_ssp(parent, "ssp1", U8500_SSP1_BASE, \
-		       IRQ_DB8500_SSP1, pdata)
-
-#define db8500_add_spi0(parent, pdata) \
-	dbx500_add_spi(parent, "spi0", U8500_SPI0_BASE, \
-		       IRQ_DB8500_SPI0, pdata, 0)
-#define db8500_add_spi1(parent, pdata) \
-	dbx500_add_spi(parent, "spi1", U8500_SPI1_BASE, \
-		       IRQ_DB8500_SPI1, pdata, 0)
-#define db8500_add_spi2(parent, pdata) \
-	dbx500_add_spi(parent, "spi2", U8500_SPI2_BASE, \
-		       IRQ_DB8500_SPI2, pdata, 0)
-#define db8500_add_spi3(parent, pdata) \
-	dbx500_add_spi(parent, "spi3", U8500_SPI3_BASE, \
-		       IRQ_DB8500_SPI3, pdata, 0)
-
-#define db8500_add_uart0(parent, pdata) \
-	dbx500_add_uart(parent, "uart0", U8500_UART0_BASE, \
-			IRQ_DB8500_UART0, pdata)
-#define db8500_add_uart1(parent, pdata) \
-	dbx500_add_uart(parent, "uart1", U8500_UART1_BASE, \
-			IRQ_DB8500_UART1, pdata)
-#define db8500_add_uart2(parent, pdata) \
-	dbx500_add_uart(parent, "uart2", U8500_UART2_BASE, \
-			IRQ_DB8500_UART2, pdata)
-
-#define db8500_add_cryp1(parent, pdata) \
-	dbx500_add_cryp1(parent, -1, U8500_CRYP1_BASE, IRQ_DB8500_CRYP1, pdata)
-#define db8500_add_hash1(parent, pdata) \
-	dbx500_add_hash1(parent, -1, U8500_HASH1_BASE, pdata)
 #endif
diff --git a/arch/arm/mach-ux500/devices.h b/arch/arm/mach-ux500/devices.h
index cbc6f1e..5bca7c6 100644
--- a/arch/arm/mach-ux500/devices.h
+++ b/arch/arm/mach-ux500/devices.h
@@ -10,14 +10,6 @@
 struct platform_device;
 struct amba_device;
 
-extern struct platform_device u8500_gpio_devs[];
-
 extern struct amba_device ux500_pl031_device;
 
-extern struct platform_device ux500_hash1_device;
-extern struct platform_device ux500_cryp1_device;
-
-extern struct platform_device u8500_dma40_device;
-extern struct platform_device ux500_ske_keypad_device;
-
 #endif
diff --git a/arch/arm/mach-ux500/setup.h b/arch/arm/mach-ux500/setup.h
index 656324a..bdb3564 100644
--- a/arch/arm/mach-ux500/setup.h
+++ b/arch/arm/mach-ux500/setup.h
@@ -24,7 +24,6 @@
 extern struct device * __init u8500_init_devices(void);
 
 extern void __init ux500_init_irq(void);
-extern void __init ux500_init_late(void);
 
 extern struct device *ux500_soc_device_init(const char *soc_id);
 
diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c
index b6bd0ef..05a4ff7 100644
--- a/arch/arm/mach-ux500/timer.c
+++ b/arch/arm/mach-ux500/timer.c
@@ -97,8 +97,8 @@
 	 * sched_clock with higher rating then MTU since is always-on.
 	 *
 	 */
-
-	nmdk_timer_init(mtu_timer_base, IRQ_MTU0);
+	if (!of_have_populated_dt())
+		nmdk_timer_init(mtu_timer_base, IRQ_MTU0);
 	clksrc_dbx500_prcmu_init(prcmu_timer_base);
 	ux500_twd_init();
 }
diff --git a/arch/arm/mach-ux500/usb.c b/arch/arm/mach-ux500/usb.c
deleted file mode 100644
index b7bd8d3..0000000
--- a/arch/arm/mach-ux500/usb.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2011
- *
- * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
- * License terms: GNU General Public License (GPL) version 2
- */
-#include <linux/platform_device.h>
-#include <linux/usb/musb.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_data/usb-musb-ux500.h>
-#include <linux/platform_data/dma-ste-dma40.h>
-
-#include "db8500-regs.h"
-
-#define MUSB_DMA40_RX_CH { \
-		.mode = STEDMA40_MODE_LOGICAL, \
-		.dir = DMA_DEV_TO_MEM, \
-	}
-
-#define MUSB_DMA40_TX_CH { \
-		.mode = STEDMA40_MODE_LOGICAL, \
-		.dir = DMA_MEM_TO_DEV, \
-	}
-
-static struct stedma40_chan_cfg musb_dma_rx_ch[UX500_MUSB_DMA_NUM_RX_TX_CHANNELS]
-	= {
-	MUSB_DMA40_RX_CH,
-	MUSB_DMA40_RX_CH,
-	MUSB_DMA40_RX_CH,
-	MUSB_DMA40_RX_CH,
-	MUSB_DMA40_RX_CH,
-	MUSB_DMA40_RX_CH,
-	MUSB_DMA40_RX_CH,
-	MUSB_DMA40_RX_CH
-};
-
-static struct stedma40_chan_cfg musb_dma_tx_ch[UX500_MUSB_DMA_NUM_RX_TX_CHANNELS]
-	= {
-	MUSB_DMA40_TX_CH,
-	MUSB_DMA40_TX_CH,
-	MUSB_DMA40_TX_CH,
-	MUSB_DMA40_TX_CH,
-	MUSB_DMA40_TX_CH,
-	MUSB_DMA40_TX_CH,
-	MUSB_DMA40_TX_CH,
-	MUSB_DMA40_TX_CH,
-};
-
-static void *ux500_dma_rx_param_array[UX500_MUSB_DMA_NUM_RX_TX_CHANNELS] = {
-	&musb_dma_rx_ch[0],
-	&musb_dma_rx_ch[1],
-	&musb_dma_rx_ch[2],
-	&musb_dma_rx_ch[3],
-	&musb_dma_rx_ch[4],
-	&musb_dma_rx_ch[5],
-	&musb_dma_rx_ch[6],
-	&musb_dma_rx_ch[7]
-};
-
-static void *ux500_dma_tx_param_array[UX500_MUSB_DMA_NUM_RX_TX_CHANNELS] = {
-	&musb_dma_tx_ch[0],
-	&musb_dma_tx_ch[1],
-	&musb_dma_tx_ch[2],
-	&musb_dma_tx_ch[3],
-	&musb_dma_tx_ch[4],
-	&musb_dma_tx_ch[5],
-	&musb_dma_tx_ch[6],
-	&musb_dma_tx_ch[7]
-};
-
-static struct ux500_musb_board_data musb_board_data = {
-	.dma_rx_param_array = ux500_dma_rx_param_array,
-	.dma_tx_param_array = ux500_dma_tx_param_array,
-	.dma_filter = stedma40_filter,
-};
-
-static struct musb_hdrc_platform_data musb_platform_data = {
-	.mode = MUSB_OTG,
-	.board_data = &musb_board_data,
-};
-
-static struct resource usb_resources[] = {
-	[0] = {
-		.name	= "usb-mem",
-		.flags	=  IORESOURCE_MEM,
-	},
-
-	[1] = {
-		.name   = "mc", /* hard-coded in musb */
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device ux500_musb_device = {
-	.name = "musb-ux500",
-	.id = 0,
-	.dev = {
-		.platform_data = &musb_platform_data,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-	.num_resources = ARRAY_SIZE(usb_resources),
-	.resource = usb_resources,
-};
-
-static inline void ux500_usb_dma_update_rx_ch_config(int *dev_type)
-{
-	u32 idx;
-
-	for (idx = 0; idx < UX500_MUSB_DMA_NUM_RX_TX_CHANNELS; idx++)
-		musb_dma_rx_ch[idx].dev_type = dev_type[idx];
-}
-
-static inline void ux500_usb_dma_update_tx_ch_config(int *dev_type)
-{
-	u32 idx;
-
-	for (idx = 0; idx < UX500_MUSB_DMA_NUM_RX_TX_CHANNELS; idx++)
-		musb_dma_tx_ch[idx].dev_type = dev_type[idx];
-}
-
-void ux500_add_usb(struct device *parent, resource_size_t base, int irq,
-		   int *dma_rx_cfg, int *dma_tx_cfg)
-{
-	ux500_musb_device.resource[0].start = base;
-	ux500_musb_device.resource[0].end = base + SZ_64K - 1;
-	ux500_musb_device.resource[1].start = irq;
-	ux500_musb_device.resource[1].end = irq;
-
-	ux500_usb_dma_update_rx_ch_config(dma_rx_cfg);
-	ux500_usb_dma_update_tx_ch_config(dma_tx_cfg);
-
-	ux500_musb_device.dev.parent = parent;
-
-	platform_device_register(&ux500_musb_device);
-}
diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
index 3657954..d7e7422 100644
--- a/arch/arm/mach-vexpress/Kconfig
+++ b/arch/arm/mach-vexpress/Kconfig
@@ -4,14 +4,12 @@
 	select ARM_AMBA
 	select ARM_GIC
 	select ARM_TIMER_SP804
-	select CLKDEV_LOOKUP
 	select COMMON_CLK
 	select COMMON_CLK_VERSATILE
 	select CPU_V7
 	select GENERIC_CLOCKEVENTS
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
-	select HAVE_CLK
 	select HAVE_PATA_PLATFORM
 	select HAVE_SMP
 	select ICST
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 95a469e..4f8b8cb 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -1,12 +1,10 @@
 /*
  * Versatile Express V2M Motherboard Support
  */
-#include <linux/clocksource.h>
 #include <linux/device.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/mmci.h>
 #include <linux/io.h>
-#include <linux/clocksource.h>
 #include <linux/smp.h>
 #include <linux/init.h>
 #include <linux/of_address.h>
@@ -22,7 +20,6 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/vexpress.h>
-#include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 
 #include <asm/mach-types.h>
@@ -422,16 +419,8 @@
 			pr_warning("vexpress: DT HBI (%x) is not matching "
 					"hardware (%x)!\n", dt_hbi, hbi);
 	}
-}
 
-static void __init v2m_dt_timer_init(void)
-{
-	of_clk_init(NULL);
-
-	clocksource_of_init();
-
-	versatile_sched_clock_init(vexpress_get_24mhz_clock_base(),
-				24000000);
+	versatile_sched_clock_init(vexpress_get_24mhz_clock_base(), 24000000);
 }
 
 static const struct of_device_id v2m_dt_bus_match[] __initconst = {
@@ -458,6 +447,5 @@
 	.smp_init	= smp_init_ops(vexpress_smp_init_ops),
 	.map_io		= v2m_dt_map_io,
 	.init_early	= v2m_dt_init_early,
-	.init_time	= v2m_dt_timer_init,
 	.init_machine	= v2m_dt_init,
 MACHINE_END
diff --git a/arch/arm/mach-vt8500/Kconfig b/arch/arm/mach-vt8500/Kconfig
index 9b25293..927be93 100644
--- a/arch/arm/mach-vt8500/Kconfig
+++ b/arch/arm/mach-vt8500/Kconfig
@@ -5,7 +5,6 @@
 	select CLKDEV_LOOKUP
 	select CLKSRC_OF
 	select GENERIC_CLOCKEVENTS
-	select HAVE_CLK
 	select VT8500_TIMER
 	select PINCTRL
 	help
diff --git a/arch/arm/mach-vt8500/common.h b/arch/arm/mach-vt8500/common.h
deleted file mode 100644
index 087787a..0000000
--- a/arch/arm/mach-vt8500/common.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* linux/arch/arm/mach-vt8500/dt_common.h
- *
- * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
- *
- * 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_VT8500_DT_COMMON_H
-#define __ARCH_ARM_MACH_VT8500_DT_COMMON_H
-
-#include <linux/of.h>
-
-/* defined in drivers/clk/clk-vt8500.c */
-void __init vtwm_clk_init(void __iomem *pmc_base);
-
-#endif
diff --git a/arch/arm/mach-vt8500/vt8500.c b/arch/arm/mach-vt8500/vt8500.c
index eefaa60..4a73464 100644
--- a/arch/arm/mach-vt8500/vt8500.c
+++ b/arch/arm/mach-vt8500/vt8500.c
@@ -18,7 +18,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/clocksource.h>
 #include <linux/io.h>
 #include <linux/pm.h>
 #include <linux/reboot.h>
@@ -33,8 +32,6 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
-#include "common.h"
-
 #define LEGACY_GPIO_BASE	0xD8110000
 #define LEGACY_PMC_BASE		0xD8130000
 
@@ -162,8 +159,6 @@
 	else
 		pr_err("%s: PMC Hibernation register could not be remapped, not enabling power off!\n", __func__);
 
-	vtwm_clk_init(pmc_base);
-
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
@@ -180,7 +175,6 @@
 	.dt_compat	= vt8500_dt_compat,
 	.map_io		= vt8500_map_io,
 	.init_machine	= vt8500_init,
-	.init_time	= clocksource_of_init,
 	.restart	= vt8500_restart,
 MACHINE_END
 
diff --git a/arch/arm/mach-w90x900/include/mach/gpio.h b/arch/arm/mach-w90x900/include/mach/gpio.h
deleted file mode 100644
index 5385a42..0000000
--- a/arch/arm/mach-w90x900/include/mach/gpio.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * linux/arch/arm/mach-w90p910/include/mach/gpio.h
- *
- * Generic w90p910 GPIO handling
- *
- *  Wan ZongShun <mcuos.com@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_W90P910_GPIO_H
-#define __ASM_ARCH_W90P910_GPIO_H
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-static inline int gpio_to_irq(unsigned gpio)
-{
-	return gpio;
-}
-#define gpio_to_irq gpio_to_irq
-
-static inline int irq_to_gpio(unsigned irq)
-{
-	return irq;
-}
-
-#endif
diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig
index 04f8a4a..6b04260 100644
--- a/arch/arm/mach-zynq/Kconfig
+++ b/arch/arm/mach-zynq/Kconfig
@@ -13,5 +13,6 @@
 	select HAVE_SMP
 	select SPARSE_IRQ
 	select CADENCE_TTC_TIMER
+	select ARM_GLOBAL_TIMER
 	help
 	  Support for Xilinx Zynq ARM Cortex A9 Platform
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index f5e1a84..1272ed2 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1232,7 +1232,8 @@
 				break;
 
 		len = (j - i) << PAGE_SHIFT;
-		ret = iommu_map(mapping->domain, iova, phys, len, 0);
+		ret = iommu_map(mapping->domain, iova, phys, len,
+				IOMMU_READ|IOMMU_WRITE);
 		if (ret < 0)
 			goto fail;
 		iova += len;
@@ -1431,6 +1432,27 @@
 					 GFP_KERNEL);
 }
 
+static int __dma_direction_to_prot(enum dma_data_direction dir)
+{
+	int prot;
+
+	switch (dir) {
+	case DMA_BIDIRECTIONAL:
+		prot = IOMMU_READ | IOMMU_WRITE;
+		break;
+	case DMA_TO_DEVICE:
+		prot = IOMMU_READ;
+		break;
+	case DMA_FROM_DEVICE:
+		prot = IOMMU_WRITE;
+		break;
+	default:
+		prot = 0;
+	}
+
+	return prot;
+}
+
 /*
  * Map a part of the scatter-gather list into contiguous io address space
  */
@@ -1444,6 +1466,7 @@
 	int ret = 0;
 	unsigned int count;
 	struct scatterlist *s;
+	int prot;
 
 	size = PAGE_ALIGN(size);
 	*handle = DMA_ERROR_CODE;
@@ -1460,7 +1483,9 @@
 			!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
 			__dma_page_cpu_to_dev(sg_page(s), s->offset, s->length, dir);
 
-		ret = iommu_map(mapping->domain, iova, phys, len, 0);
+		prot = __dma_direction_to_prot(dir);
+
+		ret = iommu_map(mapping->domain, iova, phys, len, prot);
 		if (ret < 0)
 			goto fail;
 		count += len >> PAGE_SHIFT;
@@ -1665,19 +1690,7 @@
 	if (dma_addr == DMA_ERROR_CODE)
 		return dma_addr;
 
-	switch (dir) {
-	case DMA_BIDIRECTIONAL:
-		prot = IOMMU_READ | IOMMU_WRITE;
-		break;
-	case DMA_TO_DEVICE:
-		prot = IOMMU_READ;
-		break;
-	case DMA_FROM_DEVICE:
-		prot = IOMMU_WRITE;
-		break;
-	default:
-		prot = 0;
-	}
+	prot = __dma_direction_to_prot(dir);
 
 	ret = iommu_map(mapping->domain, dma_addr, page_to_phys(page), len, prot);
 	if (ret < 0)
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index febaee7..ca907f8 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -17,7 +17,6 @@
 #include <linux/nodemask.h>
 #include <linux/initrd.h>
 #include <linux/of_fdt.h>
-#include <linux/of_reserved_mem.h>
 #include <linux/highmem.h>
 #include <linux/gfp.h>
 #include <linux/memblock.h>
@@ -77,14 +76,6 @@
 
 __tagtable(ATAG_INITRD2, parse_tag_initrd2);
 
-#ifdef CONFIG_OF_FLATTREE
-void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
-{
-	phys_initrd_start = start;
-	phys_initrd_size = end - start;
-}
-#endif /* CONFIG_OF_FLATTREE */
-
 /*
  * This keeps memory configuration data used by a couple memory
  * initialization functions, as well as show_mem() for the skipping
@@ -351,6 +342,11 @@
 	memblock_reserve(__pa(_stext), _end - _stext);
 #endif
 #ifdef CONFIG_BLK_DEV_INITRD
+	/* FDT scan will populate initrd_start */
+	if (initrd_start) {
+		phys_initrd_start = __virt_to_phys(initrd_start);
+		phys_initrd_size = initrd_end - initrd_start;
+	}
 	if (phys_initrd_size &&
 	    !memblock_is_region_memory(phys_initrd_start, phys_initrd_size)) {
 		pr_err("INITRD: 0x%08llx+0x%08lx is not a memory region - disabling initrd\n",
@@ -379,8 +375,6 @@
 	if (mdesc->reserve)
 		mdesc->reserve();
 
-	early_init_dt_scan_reserved_mem();
-
 	/*
 	 * reserve memory for DMA contigouos allocations,
 	 * must come from DMA area inside low memory
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index f50d223..99b44e0 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -930,4 +930,5 @@
 {
 	if (fp->bpf_func != sk_run_filter)
 		module_free(NULL, fp->bpf_func);
+	kfree(fp);
 }
diff --git a/arch/arm/plat-iop/Makefile b/arch/arm/plat-iop/Makefile
index a99dc15..224e56c 100644
--- a/arch/arm/plat-iop/Makefile
+++ b/arch/arm/plat-iop/Makefile
@@ -5,7 +5,6 @@
 obj-y :=
 
 # IOP32X
-obj-$(CONFIG_ARCH_IOP32X) += gpio.o
 obj-$(CONFIG_ARCH_IOP32X) += i2c.o
 obj-$(CONFIG_ARCH_IOP32X) += pci.o
 obj-$(CONFIG_ARCH_IOP32X) += setup.o
@@ -16,7 +15,6 @@
 obj-$(CONFIG_ARCH_IOP32X) += restart.o
 
 # IOP33X
-obj-$(CONFIG_ARCH_IOP33X) += gpio.o
 obj-$(CONFIG_ARCH_IOP33X) += i2c.o
 obj-$(CONFIG_ARCH_IOP33X) += pci.o
 obj-$(CONFIG_ARCH_IOP33X) += setup.o
diff --git a/arch/arm/plat-iop/gpio.c b/arch/arm/plat-iop/gpio.c
deleted file mode 100644
index 697de6d..0000000
--- a/arch/arm/plat-iop/gpio.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * arch/arm/plat-iop/gpio.c
- * GPIO handling for Intel IOP3xx processors.
- *
- * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/gpio.h>
-#include <linux/export.h>
-#include <asm/hardware/iop3xx.h>
-#include <mach/gpio.h>
-
-void gpio_line_config(int line, int direction)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	if (direction == GPIO_IN) {
-		*IOP3XX_GPOE |= 1 << line;
-	} else if (direction == GPIO_OUT) {
-		*IOP3XX_GPOE &= ~(1 << line);
-	}
-	local_irq_restore(flags);
-}
-EXPORT_SYMBOL(gpio_line_config);
-
-int gpio_line_get(int line)
-{
-	return !!(*IOP3XX_GPID & (1 << line));
-}
-EXPORT_SYMBOL(gpio_line_get);
-
-void gpio_line_set(int line, int value)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	if (value == GPIO_LOW) {
-		*IOP3XX_GPOD &= ~(1 << line);
-	} else if (value == GPIO_HIGH) {
-		*IOP3XX_GPOD |= 1 << line;
-	}
-	local_irq_restore(flags);
-}
-EXPORT_SYMBOL(gpio_line_set);
-
-static int iop3xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
-{
-	gpio_line_config(gpio, GPIO_IN);
-	return 0;
-}
-
-static int iop3xx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int level)
-{
-	gpio_line_set(gpio, level);
-	gpio_line_config(gpio, GPIO_OUT);
-	return 0;
-}
-
-static int iop3xx_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
-{
-	return gpio_line_get(gpio);
-}
-
-static void iop3xx_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)
-{
-	gpio_line_set(gpio, value);
-}
-
-static struct gpio_chip iop3xx_chip = {
-	.label			= "iop3xx",
-	.direction_input	= iop3xx_gpio_direction_input,
-	.get			= iop3xx_gpio_get_value,
-	.direction_output	= iop3xx_gpio_direction_output,
-	.set			= iop3xx_gpio_set_value,
-	.base			= 0,
-	.ngpio			= IOP3XX_N_GPIOS,
-};
-
-static int __init iop3xx_gpio_setup(void)
-{
-	return gpiochip_add(&iop3xx_chip);
-}
-arch_initcall(iop3xx_gpio_setup);
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 0376606..01619c2 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -1965,7 +1965,6 @@
 static struct irqaction omap24xx_dma_irq = {
 	.name = "DMA",
 	.handler = omap2_dma_irq_handler,
-	.flags = IRQF_DISABLED
 };
 
 #else
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 7dfba93..6d95d60 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -382,11 +382,6 @@
 	help
 	  Compile in platform device definition for TV interface
 
-config S5P_DEV_USB_EHCI
-	bool
-	help
-	  Compile in platform device definition for USB EHCI
-
 config S3C24XX_PWM
 	bool "PWM device support"
 	select PWM
@@ -395,11 +390,6 @@
 	  Support for exporting the PWM timer blocks via the pwm device
 	  system
 
-config S5P_SETUP_MIPIPHY
-	bool
-	help
-	  Compile in common setup code for MIPI-CSIS and MIPI-DSIM devices
-
 config S3C_SETUP_CAMIF
 	bool
 	help
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 498c7c2..9267d29 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -38,7 +38,6 @@
 obj-$(CONFIG_SAMSUNG_DEV_BACKLIGHT)	+= dev-backlight.o
 
 obj-$(CONFIG_S3C_SETUP_CAMIF)	+= setup-camif.o
-obj-$(CONFIG_S5P_SETUP_MIPIPHY)	+= setup-mipiphy.o
 
 # DMA support
 
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index 8ce0ac0..99a3590 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -32,6 +32,7 @@
 #include <linux/ioport.h>
 #include <linux/platform_data/s3c-hsudc.h>
 #include <linux/platform_data/s3c-hsotg.h>
+#include <linux/platform_data/dma-s3c24xx.h>
 
 #include <media/s5p_hdmi.h>
 
@@ -49,7 +50,6 @@
 #include <plat/devs.h>
 #include <plat/adc.h>
 #include <linux/platform_data/ata-samsung_cf.h>
-#include <linux/platform_data/usb-ehci-s5p.h>
 #include <plat/fb.h>
 #include <plat/fb-s3c2410.h>
 #include <plat/hdmi.h>
@@ -1359,39 +1359,6 @@
 }
 #endif /* CONFIG_PLAT_S3C24XX */
 
-/* USB EHCI Host Controller */
-
-#ifdef CONFIG_S5P_DEV_USB_EHCI
-static struct resource s5p_ehci_resource[] = {
-	[0] = DEFINE_RES_MEM(S5P_PA_EHCI, SZ_256),
-	[1] = DEFINE_RES_IRQ(IRQ_USB_HOST),
-};
-
-struct platform_device s5p_device_ehci = {
-	.name		= "s5p-ehci",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(s5p_ehci_resource),
-	.resource	= s5p_ehci_resource,
-	.dev		= {
-		.dma_mask		= &samsung_device_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	}
-};
-
-void __init s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd)
-{
-	struct s5p_ehci_platdata *npd;
-
-	npd = s3c_set_platdata(pd, sizeof(struct s5p_ehci_platdata),
-			&s5p_device_ehci);
-
-	if (!npd->phy_init)
-		npd->phy_init = s5p_usb_phy_init;
-	if (!npd->phy_exit)
-		npd->phy_exit = s5p_usb_phy_exit;
-}
-#endif /* CONFIG_S5P_DEV_USB_EHCI */
-
 /* USB HSOTG */
 
 #ifdef CONFIG_S3C_DEV_USB_HSOTG
@@ -1499,8 +1466,10 @@
 	pd.num_cs = num_cs;
 	pd.src_clk_nr = src_clk_nr;
 	pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi0_cfg_gpio;
-#ifdef CONFIG_PL330_DMA
+#if defined(CONFIG_PL330_DMA)
 	pd.filter = pl330_filter;
+#elif defined(CONFIG_S3C24XX_DMAC)
+	pd.filter = s3c24xx_dma_filter;
 #endif
 
 	s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi0);
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
index 4fb1f03..335beb3 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -87,8 +87,12 @@
 #endif
 
 #if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
+# define soc_is_s3c6400()	is_samsung_s3c6400()
+# define soc_is_s3c6410()	is_samsung_s3c6410()
 # define soc_is_s3c64xx()	(is_samsung_s3c6400() || is_samsung_s3c6410())
 #else
+# define soc_is_s3c6400()	0
+# define soc_is_s3c6410()	0
 # define soc_is_s3c64xx()	0
 #endif
 
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index 0dc4ac4..eece188 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -75,7 +75,6 @@
 extern struct platform_device s3c_device_usb_hsudc;
 extern struct platform_device s3c_device_wdt;
 
-extern struct platform_device s5p_device_ehci;
 extern struct platform_device s5p_device_fimc0;
 extern struct platform_device s5p_device_fimc1;
 extern struct platform_device s5p_device_fimc2;
diff --git a/arch/arm/plat-samsung/init.c b/arch/arm/plat-samsung/init.c
index 50a3ea0..aa9511b 100644
--- a/arch/arm/plat-samsung/init.c
+++ b/arch/arm/plat-samsung/init.c
@@ -11,12 +11,18 @@
  * published by the Free Software Foundation.
 */
 
+/*
+ * NOTE: Code in this file is not used on S3C64xx when booting with
+ * Device Tree support.
+ */
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
 
 #include <mach/hardware.h>
 
@@ -148,8 +154,12 @@
 
 	// do the correct init for cpu
 
-	if (cpu == NULL)
+	if (cpu == NULL) {
+		/* Not needed when booting with device tree. */
+		if (of_have_populated_dt())
+			return 0;
 		panic("s3c_arch_init: NULL cpu\n");
+	}
 
 	ret = (cpu->init)();
 	if (ret != 0)
diff --git a/arch/arm/plat-samsung/setup-mipiphy.c b/arch/arm/plat-samsung/setup-mipiphy.c
deleted file mode 100644
index 66df315..0000000
--- a/arch/arm/plat-samsung/setup-mipiphy.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- *
- * S5P - Helper functions for MIPI-CSIS and MIPI-DSIM D-PHY control
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/export.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/spinlock.h>
-#include <mach/regs-clock.h>
-
-static int __s5p_mipi_phy_control(int id, bool on, u32 reset)
-{
-	static DEFINE_SPINLOCK(lock);
-	void __iomem *addr;
-	unsigned long flags;
-	u32 cfg;
-
-	id = max(0, id);
-	if (id > 1)
-		return -EINVAL;
-
-	addr = S5P_MIPI_DPHY_CONTROL(id);
-
-	spin_lock_irqsave(&lock, flags);
-
-	cfg = __raw_readl(addr);
-	cfg = on ? (cfg | reset) : (cfg & ~reset);
-	__raw_writel(cfg, addr);
-
-	if (on) {
-		cfg |= S5P_MIPI_DPHY_ENABLE;
-	} else if (!(cfg & (S5P_MIPI_DPHY_SRESETN |
-			    S5P_MIPI_DPHY_MRESETN) & ~reset)) {
-		cfg &= ~S5P_MIPI_DPHY_ENABLE;
-	}
-
-	__raw_writel(cfg, addr);
-	spin_unlock_irqrestore(&lock, flags);
-
-	return 0;
-}
-
-int s5p_csis_phy_enable(int id, bool on)
-{
-	return __s5p_mipi_phy_control(id, on, S5P_MIPI_DPHY_SRESETN);
-}
-EXPORT_SYMBOL(s5p_csis_phy_enable);
-
-int s5p_dsim_phy_enable(struct platform_device *pdev, bool on)
-{
-	return __s5p_mipi_phy_control(pdev->id, on, S5P_MIPI_DPHY_MRESETN);
-}
-EXPORT_SYMBOL(s5p_dsim_phy_enable);
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index c044548..bb0bf1b 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1,6 +1,7 @@
 config ARM64
 	def_bool y
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
+	select ARCH_USE_CMPXCHG_LOCKREF
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
 	select ARCH_WANT_FRAME_POINTERS
@@ -14,6 +15,7 @@
 	select GENERIC_IOMAP
 	select GENERIC_IRQ_PROBE
 	select GENERIC_IRQ_SHOW
+	select GENERIC_SCHED_CLOCK
 	select GENERIC_SMP_IDLE_THREAD
 	select GENERIC_TIME_VSYSCALL
 	select HARDIRQS_SW_RESEND
@@ -61,10 +63,6 @@
 config TRACE_IRQFLAGS_SUPPORT
 	def_bool y
 
-config GENERIC_LOCKBREAK
-	def_bool y
-	depends on SMP && PREEMPT
-
 config RWSEM_GENERIC_SPINLOCK
 	def_bool y
 
@@ -138,6 +136,11 @@
 	  look-up. AArch32 emulation is not available when this feature
 	  is enabled.
 
+config CPU_BIG_ENDIAN
+       bool "Build big-endian kernel"
+       help
+         Say Y if you plan on running a kernel in big-endian mode.
+
 config SMP
 	bool "Symmetric Multi-Processing"
 	select USE_GENERIC_SMP_HELPERS
@@ -160,6 +163,13 @@
 	default "8" if ARCH_XGENE
 	default "4"
 
+config HOTPLUG_CPU
+	bool "Support for hot-pluggable CPUs"
+	depends on SMP
+	help
+	  Say Y here to experiment with turning CPUs off and on.  CPUs
+	  can be controlled through /sys/devices/system/cpu.
+
 source kernel/Kconfig.preempt
 
 config HZ
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index d90cf79..2fceb71 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -20,9 +20,15 @@
 KBUILD_DEFCONFIG := defconfig
 
 KBUILD_CFLAGS	+= -mgeneral-regs-only
+ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)
+KBUILD_CPPFLAGS	+= -mbig-endian
+AS		+= -EB
+LD		+= -EB
+else
 KBUILD_CPPFLAGS	+= -mlittle-endian
 AS		+= -EL
 LD		+= -EL
+endif
 
 comma = ,
 
diff --git a/arch/arm64/boot/dts/apm-storm.dtsi b/arch/arm64/boot/dts/apm-storm.dtsi
index bfdc578..d37d736 100644
--- a/arch/arm64/boot/dts/apm-storm.dtsi
+++ b/arch/arm64/boot/dts/apm-storm.dtsi
@@ -103,6 +103,81 @@
 		#size-cells = <2>;
 		ranges;
 
+		clocks {
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges;
+			refclk: refclk {
+				compatible = "fixed-clock";
+				#clock-cells = <1>;
+				clock-frequency = <100000000>;
+				clock-output-names = "refclk";
+			};
+
+			pcppll: pcppll@17000100 {
+				compatible = "apm,xgene-pcppll-clock";
+				#clock-cells = <1>;
+				clocks = <&refclk 0>;
+				clock-names = "pcppll";
+				reg = <0x0 0x17000100 0x0 0x1000>;
+				clock-output-names = "pcppll";
+				type = <0>;
+			};
+
+			socpll: socpll@17000120 {
+				compatible = "apm,xgene-socpll-clock";
+				#clock-cells = <1>;
+				clocks = <&refclk 0>;
+				clock-names = "socpll";
+				reg = <0x0 0x17000120 0x0 0x1000>;
+				clock-output-names = "socpll";
+				type = <1>;
+			};
+
+			socplldiv2: socplldiv2  {
+				compatible = "fixed-factor-clock";
+				#clock-cells = <1>;
+				clocks = <&socpll 0>;
+				clock-names = "socplldiv2";
+				clock-mult = <1>;
+				clock-div = <2>;
+				clock-output-names = "socplldiv2";
+			};
+
+			qmlclk: qmlclk {
+				compatible = "apm,xgene-device-clock";
+				#clock-cells = <1>;
+				clocks = <&socplldiv2 0>;
+				clock-names = "qmlclk";
+				reg = <0x0 0x1703C000 0x0 0x1000>;
+				reg-names = "csr-reg";
+				clock-output-names = "qmlclk";
+			};
+
+			ethclk: ethclk {
+				compatible = "apm,xgene-device-clock";
+				#clock-cells = <1>;
+				clocks = <&socplldiv2 0>;
+				clock-names = "ethclk";
+				reg = <0x0 0x17000000 0x0 0x1000>;
+				reg-names = "div-reg";
+				divider-offset = <0x238>;
+				divider-width = <0x9>;
+				divider-shift = <0x0>;
+				clock-output-names = "ethclk";
+			};
+
+			eth8clk: eth8clk {
+				compatible = "apm,xgene-device-clock";
+				#clock-cells = <1>;
+				clocks = <&ethclk 0>;
+				clock-names = "eth8clk";
+				reg = <0x0 0x1702C000 0x0 0x1000>;
+				reg-names = "csr-reg";
+				clock-output-names = "eth8clk";
+			};
+		};
+
 		serial0: serial@1c020000 {
 			device_type = "serial";
 			compatible = "ns16550";
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 31c81e9..84139be 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -26,7 +26,7 @@
 CONFIG_ARCH_VEXPRESS=y
 CONFIG_ARCH_XGENE=y
 CONFIG_SMP=y
-CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_PREEMPT=y
 CONFIG_CMDLINE="console=ttyAMA0"
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_COMPAT=y
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 79a642d..519f89f 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -50,3 +50,4 @@
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
index c9f1d28..9400596 100644
--- a/arch/arm64/include/asm/arch_timer.h
+++ b/arch/arm64/include/asm/arch_timer.h
@@ -92,19 +92,49 @@
 	return val;
 }
 
-static inline void arch_counter_set_user_access(void)
+static inline u32 arch_timer_get_cntkctl(void)
 {
 	u32 cntkctl;
-
-	/* Disable user access to the timers and the physical counter. */
 	asm volatile("mrs	%0, cntkctl_el1" : "=r" (cntkctl));
-	cntkctl &= ~((3 << 8) | (1 << 0));
+	return cntkctl;
+}
 
-	/* Enable user access to the virtual counter and frequency. */
-	cntkctl |= (1 << 1);
+static inline void arch_timer_set_cntkctl(u32 cntkctl)
+{
 	asm volatile("msr	cntkctl_el1, %0" : : "r" (cntkctl));
 }
 
+static inline void arch_counter_set_user_access(void)
+{
+	u32 cntkctl = arch_timer_get_cntkctl();
+
+	/* Disable user access to the timers and the physical counter */
+	/* Also disable virtual event stream */
+	cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN
+			| ARCH_TIMER_USR_VT_ACCESS_EN
+			| ARCH_TIMER_VIRT_EVT_EN
+			| ARCH_TIMER_USR_PCT_ACCESS_EN);
+
+	/* Enable user access to the virtual counter */
+	cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN;
+
+	arch_timer_set_cntkctl(cntkctl);
+}
+
+static inline void arch_timer_evtstrm_enable(int divider)
+{
+	u32 cntkctl = arch_timer_get_cntkctl();
+	cntkctl &= ~ARCH_TIMER_EVT_TRIGGER_MASK;
+	/* Set the divider and enable virtual event stream */
+	cntkctl |= (divider << ARCH_TIMER_EVT_TRIGGER_SHIFT)
+			| ARCH_TIMER_VIRT_EVT_EN;
+	arch_timer_set_cntkctl(cntkctl);
+	elf_hwcap |= HWCAP_EVTSTRM;
+#ifdef CONFIG_COMPAT
+	compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
+#endif
+}
+
 static inline u64 arch_counter_get_cntvct(void)
 {
 	u64 cval;
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index 5aceb83..fd3e392 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -115,3 +115,34 @@
 	.align	7
 	b	\label
 	.endm
+
+/*
+ * Select code when configured for BE.
+ */
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define CPU_BE(code...) code
+#else
+#define CPU_BE(code...)
+#endif
+
+/*
+ * Select code when configured for LE.
+ */
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define CPU_LE(code...)
+#else
+#define CPU_LE(code...) code
+#endif
+
+/*
+ * Define a macro that constructs a 64-bit value by concatenating two
+ * 32-bit registers. Note that on big endian systems the order of the
+ * registers is swapped.
+ */
+#ifndef CONFIG_CPU_BIG_ENDIAN
+	.macro	regs_to_64, rd, lbits, hbits
+#else
+	.macro	regs_to_64, rd, hbits, lbits
+#endif
+	orr	\rd, \lbits, \hbits, lsl #32
+	.endm
diff --git a/arch/arm64/include/asm/cmpxchg.h b/arch/arm64/include/asm/cmpxchg.h
index 8a8ce0e..3914c0d 100644
--- a/arch/arm64/include/asm/cmpxchg.h
+++ b/arch/arm64/include/asm/cmpxchg.h
@@ -173,4 +173,6 @@
 #define cmpxchg64(ptr,o,n)		cmpxchg((ptr),(o),(n))
 #define cmpxchg64_local(ptr,o,n)	cmpxchg_local((ptr),(o),(n))
 
+#define cmpxchg64_relaxed(ptr,o,n)	cmpxchg_local((ptr),(o),(n))
+
 #endif	/* __ASM_CMPXCHG_H */
diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h
index 899af80..fda2704 100644
--- a/arch/arm64/include/asm/compat.h
+++ b/arch/arm64/include/asm/compat.h
@@ -26,7 +26,11 @@
 #include <linux/ptrace.h>
 
 #define COMPAT_USER_HZ		100
+#ifdef __AARCH64EB__
+#define COMPAT_UTS_MACHINE	"armv8b\0\0"
+#else
 #define COMPAT_UTS_MACHINE	"armv8l\0\0"
+#endif
 
 typedef u32		compat_size_t;
 typedef s32		compat_ssize_t;
@@ -73,13 +77,23 @@
 };
 
 struct compat_stat {
+#ifdef __AARCH64EB__
+	short		st_dev;
+	short		__pad1;
+#else
 	compat_dev_t	st_dev;
+#endif
 	compat_ino_t	st_ino;
 	compat_mode_t	st_mode;
 	compat_ushort_t	st_nlink;
 	__compat_uid16_t	st_uid;
 	__compat_gid16_t	st_gid;
+#ifdef __AARCH64EB__
+	short		st_rdev;
+	short		__pad2;
+#else
 	compat_dev_t	st_rdev;
+#endif
 	compat_off_t	st_size;
 	compat_off_t	st_blksize;
 	compat_off_t	st_blocks;
diff --git a/arch/arm64/include/asm/cpu_ops.h b/arch/arm64/include/asm/cpu_ops.h
new file mode 100644
index 0000000..c4cdb5e
--- /dev/null
+++ b/arch/arm64/include/asm/cpu_ops.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2013 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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 __ASM_CPU_OPS_H
+#define __ASM_CPU_OPS_H
+
+#include <linux/init.h>
+#include <linux/threads.h>
+
+struct device_node;
+
+/**
+ * struct cpu_operations - Callback operations for hotplugging CPUs.
+ *
+ * @name:	Name of the property as appears in a devicetree cpu node's
+ *		enable-method property.
+ * @cpu_init:	Reads any data necessary for a specific enable-method from the
+ *		devicetree, for a given cpu node and proposed logical id.
+ * @cpu_prepare: Early one-time preparation step for a cpu. If there is a
+ *		mechanism for doing so, tests whether it is possible to boot
+ *		the given CPU.
+ * @cpu_boot:	Boots a cpu into the kernel.
+ * @cpu_postboot: Optionally, perform any post-boot cleanup or necesary
+ *		synchronisation. Called from the cpu being booted.
+ * @cpu_disable: Prepares a cpu to die. May fail for some mechanism-specific
+ * 		reason, which will cause the hot unplug to be aborted. Called
+ * 		from the cpu to be killed.
+ * @cpu_die:	Makes a cpu leave the kernel. Must not fail. Called from the
+ *		cpu being killed.
+ */
+struct cpu_operations {
+	const char	*name;
+	int		(*cpu_init)(struct device_node *, unsigned int);
+	int		(*cpu_prepare)(unsigned int);
+	int		(*cpu_boot)(unsigned int);
+	void		(*cpu_postboot)(void);
+#ifdef CONFIG_HOTPLUG_CPU
+	int		(*cpu_disable)(unsigned int cpu);
+	void		(*cpu_die)(unsigned int cpu);
+#endif
+};
+
+extern const struct cpu_operations *cpu_ops[NR_CPUS];
+extern int __init cpu_read_ops(struct device_node *dn, int cpu);
+extern void __init cpu_read_bootcpu_ops(void);
+
+#endif /* ifndef __ASM_CPU_OPS_H */
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index e7fa87f..01d3aab 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -90,11 +90,24 @@
  * These are used to set parameters in the core dumps.
  */
 #define ELF_CLASS	ELFCLASS64
+#ifdef __AARCH64EB__
+#define ELF_DATA	ELFDATA2MSB
+#else
 #define ELF_DATA	ELFDATA2LSB
+#endif
 #define ELF_ARCH	EM_AARCH64
 
+/*
+ * This yields a string that ld.so will use to load implementation
+ * specific libraries for optimization.  This is more specific in
+ * intent than poking at uname or /proc/cpuinfo.
+ */
 #define ELF_PLATFORM_SIZE	16
+#ifdef __AARCH64EB__
+#define ELF_PLATFORM		("aarch64_be")
+#else
 #define ELF_PLATFORM		("aarch64")
+#endif
 
 /*
  * This is used to ensure we don't load something for the wrong architecture.
@@ -149,7 +162,12 @@
 #define arch_randomize_brk arch_randomize_brk
 
 #ifdef CONFIG_COMPAT
+
+#ifdef __AARCH64EB__
+#define COMPAT_ELF_PLATFORM		("v8b")
+#else
 #define COMPAT_ELF_PLATFORM		("v8l")
+#endif
 
 #define COMPAT_ELF_ET_DYN_BASE		(randomize_et_dyn(2 * TASK_SIZE_32 / 3))
 
diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h
index e2950b0..6cddbb0 100644
--- a/arch/arm64/include/asm/hwcap.h
+++ b/arch/arm64/include/asm/hwcap.h
@@ -30,6 +30,7 @@
 #define COMPAT_HWCAP_IDIVA	(1 << 17)
 #define COMPAT_HWCAP_IDIVT	(1 << 18)
 #define COMPAT_HWCAP_IDIV	(COMPAT_HWCAP_IDIVA|COMPAT_HWCAP_IDIVT)
+#define COMPAT_HWCAP_EVTSTRM	(1 << 21)
 
 #ifndef __ASSEMBLY__
 /*
@@ -37,11 +38,11 @@
  * instruction set this cpu supports.
  */
 #define ELF_HWCAP		(elf_hwcap)
-#define COMPAT_ELF_HWCAP	(COMPAT_HWCAP_HALF|COMPAT_HWCAP_THUMB|\
-				 COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\
-				 COMPAT_HWCAP_TLS|COMPAT_HWCAP_VFP|\
-				 COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\
-				 COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV)
+
+#ifdef CONFIG_COMPAT
+#define COMPAT_ELF_HWCAP	(compat_elf_hwcap)
+extern unsigned int compat_elf_hwcap;
+#endif
 
 extern unsigned long elf_hwcap;
 #endif
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 1d12f89..b56e5b5 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -224,6 +224,7 @@
  */
 extern void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot);
 extern void __iounmap(volatile void __iomem *addr);
+extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size);
 
 #define PROT_DEFAULT		(PTE_TYPE_PAGE | PTE_AF | PTE_DIRTY)
 #define PROT_DEVICE_nGnRE	(PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
@@ -233,7 +234,6 @@
 #define ioremap(addr, size)		__ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
 #define ioremap_nocache(addr, size)	__ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
 #define ioremap_wc(addr, size)		__ioremap((addr), (size), __pgprot(PROT_NORMAL_NC))
-#define ioremap_cached(addr, size)	__ioremap((addr), (size), __pgprot(PROT_NORMAL))
 #define iounmap				__iounmap
 
 #define PROT_SECT_DEFAULT	(PMD_TYPE_SECT | PMD_SECT_AF)
diff --git a/arch/arm64/include/asm/irq.h b/arch/arm64/include/asm/irq.h
index 0332fc0..e1f7ecd 100644
--- a/arch/arm64/include/asm/irq.h
+++ b/arch/arm64/include/asm/irq.h
@@ -4,6 +4,7 @@
 #include <asm-generic/irq.h>
 
 extern void (*handle_arch_irq)(struct pt_regs *);
+extern void migrate_irqs(void);
 extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
 
 #endif
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index 20925bc..3776217 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -33,18 +33,23 @@
 #define UL(x) _AC(x, UL)
 
 /*
- * PAGE_OFFSET - the virtual address of the start of the kernel image.
+ * PAGE_OFFSET - the virtual address of the start of the kernel image (top
+ *		 (VA_BITS - 1))
  * VA_BITS - the maximum number of bits for virtual addresses.
  * TASK_SIZE - the maximum size of a user space task.
  * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area.
  * The module space lives between the addresses given by TASK_SIZE
  * and PAGE_OFFSET - it must be within 128MB of the kernel text.
  */
-#define PAGE_OFFSET		UL(0xffffffc000000000)
+#ifdef CONFIG_ARM64_64K_PAGES
+#define VA_BITS			(42)
+#else
+#define VA_BITS			(39)
+#endif
+#define PAGE_OFFSET		(UL(0xffffffffffffffff) << (VA_BITS - 1))
 #define MODULES_END		(PAGE_OFFSET)
 #define MODULES_VADDR		(MODULES_END - SZ_64M)
 #define EARLYCON_IOBASE		(MODULES_VADDR - SZ_4M)
-#define VA_BITS			(39)
 #define TASK_SIZE_64		(UL(1) << VA_BITS)
 
 #ifdef CONFIG_COMPAT
diff --git a/arch/arm64/include/asm/pgtable-2level-hwdef.h b/arch/arm64/include/asm/pgtable-2level-hwdef.h
index 0a8ed3f..2593b49 100644
--- a/arch/arm64/include/asm/pgtable-2level-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-2level-hwdef.h
@@ -21,10 +21,10 @@
  * 8192 entries of 8 bytes each, occupying a 64KB page. Levels 0 and 1 are not
  * used. The 2nd level table (PGD for Linux) can cover a range of 4TB, each
  * entry representing 512MB. The user and kernel address spaces are limited to
- * 512GB and therefore we only use 1024 entries in the PGD.
+ * 4TB in the 64KB page configuration.
  */
 #define PTRS_PER_PTE		8192
-#define PTRS_PER_PGD		1024
+#define PTRS_PER_PGD		8192
 
 /*
  * PGDIR_SHIFT determines the size a top-level page table entry can map.
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index f0bebc5..17bd3af 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -33,7 +33,7 @@
 /*
  * VMALLOC and SPARSEMEM_VMEMMAP ranges.
  */
-#define VMALLOC_START		UL(0xffffff8000000000)
+#define VMALLOC_START		(UL(0xffffffffffffffff) << VA_BITS)
 #define VMALLOC_END		(PAGE_OFFSET - UL(0x400000000) - SZ_64K)
 
 #define vmemmap			((struct page *)(VMALLOC_END + SZ_64K))
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index ab239b2..45b20cd 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -107,6 +107,11 @@
 	regs->pstate = COMPAT_PSR_MODE_USR;
 	if (pc & 1)
 		regs->pstate |= COMPAT_PSR_T_BIT;
+
+#ifdef __AARCH64EB__
+	regs->pstate |= COMPAT_PSR_E_BIT;
+#endif
+
 	regs->compat_sp = sp;
 }
 #endif
diff --git a/arch/arm64/include/asm/prom.h b/arch/arm64/include/asm/prom.h
deleted file mode 100644
index 68b90e6..0000000
--- a/arch/arm64/include/asm/prom.h
+++ /dev/null
@@ -1 +0,0 @@
-/* Empty for now */
diff --git a/arch/arm64/include/asm/psci.h b/arch/arm64/include/asm/psci.h
index 0604237..e5312ea 100644
--- a/arch/arm64/include/asm/psci.h
+++ b/arch/arm64/include/asm/psci.h
@@ -14,25 +14,6 @@
 #ifndef __ASM_PSCI_H
 #define __ASM_PSCI_H
 
-#define PSCI_POWER_STATE_TYPE_STANDBY		0
-#define PSCI_POWER_STATE_TYPE_POWER_DOWN	1
-
-struct psci_power_state {
-	u16	id;
-	u8	type;
-	u8	affinity_level;
-};
-
-struct psci_operations {
-	int (*cpu_suspend)(struct psci_power_state state,
-			   unsigned long entry_point);
-	int (*cpu_off)(struct psci_power_state state);
-	int (*cpu_on)(unsigned long cpuid, unsigned long entry_point);
-	int (*migrate)(unsigned long cpuid);
-};
-
-extern struct psci_operations psci_ops;
-
 int psci_init(void);
 
 #endif /* __ASM_PSCI_H */
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index 0dacbbf..0e7fa49 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -42,6 +42,7 @@
 #define COMPAT_PSR_MODE_UND	0x0000001b
 #define COMPAT_PSR_MODE_SYS	0x0000001f
 #define COMPAT_PSR_T_BIT	0x00000020
+#define COMPAT_PSR_E_BIT	0x00000200
 #define COMPAT_PSR_F_BIT	0x00000040
 #define COMPAT_PSR_I_BIT	0x00000080
 #define COMPAT_PSR_A_BIT	0x00000100
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index 4b8023c..a498f2c 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -60,21 +60,14 @@
 	void *stack;
 };
 extern struct secondary_data secondary_data;
-extern void secondary_holding_pen(void);
-extern volatile unsigned long secondary_holding_pen_release;
+extern void secondary_entry(void);
 
 extern void arch_send_call_function_single_ipi(int cpu);
 extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
 
-struct device_node;
+extern int __cpu_disable(void);
 
-struct smp_enable_ops {
-	const char	*name;
-	int		(*init_cpu)(struct device_node *, int);
-	int		(*prepare_cpu)(int);
-};
-
-extern const struct smp_enable_ops smp_spin_table_ops;
-extern const struct smp_enable_ops smp_psci_ops;
+extern void __cpu_die(unsigned int cpu);
+extern void cpu_die(void);
 
 #endif /* ifndef __ASM_SMP_H */
diff --git a/arch/arm64/include/asm/spinlock.h b/arch/arm64/include/asm/spinlock.h
index 0defa07..3d5cf06 100644
--- a/arch/arm64/include/asm/spinlock.h
+++ b/arch/arm64/include/asm/spinlock.h
@@ -22,17 +22,10 @@
 /*
  * Spinlock implementation.
  *
- * The old value is read exclusively and the new one, if unlocked, is written
- * exclusively. In case of failure, the loop is restarted.
- *
  * The memory barriers are implicit with the load-acquire and store-release
  * instructions.
- *
- * Unlocked value: 0
- * Locked value: 1
  */
 
-#define arch_spin_is_locked(x)		((x)->lock != 0)
 #define arch_spin_unlock_wait(lock) \
 	do { while (arch_spin_is_locked(lock)) cpu_relax(); } while (0)
 
@@ -41,32 +34,51 @@
 static inline void arch_spin_lock(arch_spinlock_t *lock)
 {
 	unsigned int tmp;
+	arch_spinlock_t lockval, newval;
 
 	asm volatile(
-	"	sevl\n"
-	"1:	wfe\n"
-	"2:	ldaxr	%w0, %1\n"
-	"	cbnz	%w0, 1b\n"
-	"	stxr	%w0, %w2, %1\n"
-	"	cbnz	%w0, 2b\n"
-	: "=&r" (tmp), "+Q" (lock->lock)
-	: "r" (1)
-	: "cc", "memory");
+	/* Atomically increment the next ticket. */
+"	prfm	pstl1strm, %3\n"
+"1:	ldaxr	%w0, %3\n"
+"	add	%w1, %w0, %w5\n"
+"	stxr	%w2, %w1, %3\n"
+"	cbnz	%w2, 1b\n"
+	/* Did we get the lock? */
+"	eor	%w1, %w0, %w0, ror #16\n"
+"	cbz	%w1, 3f\n"
+	/*
+	 * No: spin on the owner. Send a local event to avoid missing an
+	 * unlock before the exclusive load.
+	 */
+"	sevl\n"
+"2:	wfe\n"
+"	ldaxrh	%w2, %4\n"
+"	eor	%w1, %w2, %w0, lsr #16\n"
+"	cbnz	%w1, 2b\n"
+	/* We got the lock. Critical section starts here. */
+"3:"
+	: "=&r" (lockval), "=&r" (newval), "=&r" (tmp), "+Q" (*lock)
+	: "Q" (lock->owner), "I" (1 << TICKET_SHIFT)
+	: "memory");
 }
 
 static inline int arch_spin_trylock(arch_spinlock_t *lock)
 {
 	unsigned int tmp;
+	arch_spinlock_t lockval;
 
 	asm volatile(
-	"2:	ldaxr	%w0, %1\n"
-	"	cbnz	%w0, 1f\n"
-	"	stxr	%w0, %w2, %1\n"
-	"	cbnz	%w0, 2b\n"
-	"1:\n"
-	: "=&r" (tmp), "+Q" (lock->lock)
-	: "r" (1)
-	: "cc", "memory");
+"	prfm	pstl1strm, %2\n"
+"1:	ldaxr	%w0, %2\n"
+"	eor	%w1, %w0, %w0, ror #16\n"
+"	cbnz	%w1, 2f\n"
+"	add	%w0, %w0, %3\n"
+"	stxr	%w1, %w0, %2\n"
+"	cbnz	%w1, 1b\n"
+"2:"
+	: "=&r" (lockval), "=&r" (tmp), "+Q" (*lock)
+	: "I" (1 << TICKET_SHIFT)
+	: "memory");
 
 	return !tmp;
 }
@@ -74,10 +86,29 @@
 static inline void arch_spin_unlock(arch_spinlock_t *lock)
 {
 	asm volatile(
-	"	stlr	%w1, %0\n"
-	: "=Q" (lock->lock) : "r" (0) : "memory");
+"	stlrh	%w1, %0\n"
+	: "=Q" (lock->owner)
+	: "r" (lock->owner + 1)
+	: "memory");
 }
 
+static inline int arch_spin_value_unlocked(arch_spinlock_t lock)
+{
+	return lock.owner == lock.next;
+}
+
+static inline int arch_spin_is_locked(arch_spinlock_t *lock)
+{
+	return !arch_spin_value_unlocked(ACCESS_ONCE(*lock));
+}
+
+static inline int arch_spin_is_contended(arch_spinlock_t *lock)
+{
+	arch_spinlock_t lockval = ACCESS_ONCE(*lock);
+	return (lockval.next - lockval.owner) > 1;
+}
+#define arch_spin_is_contended	arch_spin_is_contended
+
 /*
  * Write lock implementation.
  *
diff --git a/arch/arm64/include/asm/spinlock_types.h b/arch/arm64/include/asm/spinlock_types.h
index 9a49434..b8d3836 100644
--- a/arch/arm64/include/asm/spinlock_types.h
+++ b/arch/arm64/include/asm/spinlock_types.h
@@ -20,14 +20,19 @@
 # error "please don't include this file directly"
 #endif
 
-/* We only require natural alignment for exclusive accesses. */
-#define __lock_aligned
+#define TICKET_SHIFT	16
 
 typedef struct {
-	volatile unsigned int lock;
-} arch_spinlock_t;
+#ifdef __AARCH64EB__
+	u16 next;
+	u16 owner;
+#else
+	u16 owner;
+	u16 next;
+#endif
+} __aligned(4) arch_spinlock_t;
 
-#define __ARCH_SPIN_LOCK_UNLOCKED	{ 0 }
+#define __ARCH_SPIN_LOCK_UNLOCKED	{ 0 , 0 }
 
 typedef struct {
 	volatile unsigned int lock;
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 89c047f..70ba9d4 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -59,6 +59,9 @@
 					 unsigned int i, unsigned int n,
 					 unsigned long *args)
 {
+	if (n == 0)
+		return;
+
 	if (i + n > SYSCALL_MAX_ARGS) {
 		unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i;
 		unsigned int n_bad = n + i - SYSCALL_MAX_ARGS;
@@ -82,6 +85,9 @@
 					 unsigned int i, unsigned int n,
 					 const unsigned long *args)
 {
+	if (n == 0)
+		return;
+
 	if (i + n > SYSCALL_MAX_ARGS) {
 		pr_warning("%s called with max args %d, handling only %d\n",
 			   __func__, i + n, SYSCALL_MAX_ARGS);
diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
index 26e310c..130e2be 100644
--- a/arch/arm64/include/asm/virt.h
+++ b/arch/arm64/include/asm/virt.h
@@ -18,7 +18,8 @@
 #ifndef __ASM__VIRT_H
 #define __ASM__VIRT_H
 
-#define BOOT_CPU_MODE_EL2	(0x0e12b007)
+#define BOOT_CPU_MODE_EL1	(0xe11)
+#define BOOT_CPU_MODE_EL2	(0xe12)
 
 #ifndef __ASSEMBLY__
 #include <asm/cacheflush.h>
diff --git a/arch/arm64/include/uapi/asm/byteorder.h b/arch/arm64/include/uapi/asm/byteorder.h
index 2b92046..dc19e95 100644
--- a/arch/arm64/include/uapi/asm/byteorder.h
+++ b/arch/arm64/include/uapi/asm/byteorder.h
@@ -16,6 +16,10 @@
 #ifndef __ASM_BYTEORDER_H
 #define __ASM_BYTEORDER_H
 
+#ifdef __AARCH64EB__
+#include <linux/byteorder/big_endian.h>
+#else
 #include <linux/byteorder/little_endian.h>
+#endif
 
 #endif	/* __ASM_BYTEORDER_H */
diff --git a/arch/arm64/include/uapi/asm/hwcap.h b/arch/arm64/include/uapi/asm/hwcap.h
index eea4975..9b12476 100644
--- a/arch/arm64/include/uapi/asm/hwcap.h
+++ b/arch/arm64/include/uapi/asm/hwcap.h
@@ -21,6 +21,7 @@
  */
 #define HWCAP_FP		(1 << 0)
 #define HWCAP_ASIMD		(1 << 1)
+#define HWCAP_EVTSTRM		(1 << 2)
 
 
 #endif /* _UAPI__ASM_HWCAP_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 7b4b564..5ba2fd4 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -9,12 +9,12 @@
 arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
 			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
 			   sys.o stacktrace.o time.o traps.o io.o vdso.o	\
-			   hyp-stub.o psci.o
+			   hyp-stub.o psci.o cpu_ops.o
 
 arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
-arm64-obj-$(CONFIG_SMP)			+= smp.o smp_spin_table.o smp_psci.o
+arm64-obj-$(CONFIG_SMP)			+= smp.o smp_spin_table.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
 arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o
 arm64-obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
index 41b4f62..e7ee770 100644
--- a/arch/arm64/kernel/arm64ksyms.c
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -39,6 +39,7 @@
 EXPORT_SYMBOL(__copy_from_user);
 EXPORT_SYMBOL(__copy_to_user);
 EXPORT_SYMBOL(__clear_user);
+EXPORT_SYMBOL(__copy_in_user);
 
 	/* physical memory */
 EXPORT_SYMBOL(memstart_addr);
diff --git a/arch/arm64/kernel/cpu_ops.c b/arch/arm64/kernel/cpu_ops.c
new file mode 100644
index 0000000..d62d12f
--- /dev/null
+++ b/arch/arm64/kernel/cpu_ops.c
@@ -0,0 +1,87 @@
+/*
+ * CPU kernel entry/exit control
+ *
+ * Copyright (C) 2013 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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 <asm/cpu_ops.h>
+#include <asm/smp_plat.h>
+#include <linux/errno.h>
+#include <linux/of.h>
+#include <linux/string.h>
+
+extern const struct cpu_operations smp_spin_table_ops;
+extern const struct cpu_operations cpu_psci_ops;
+
+const struct cpu_operations *cpu_ops[NR_CPUS];
+
+static const struct cpu_operations *supported_cpu_ops[] __initconst = {
+#ifdef CONFIG_SMP
+	&smp_spin_table_ops,
+	&cpu_psci_ops,
+#endif
+	NULL,
+};
+
+static const struct cpu_operations * __init cpu_get_ops(const char *name)
+{
+	const struct cpu_operations **ops = supported_cpu_ops;
+
+	while (*ops) {
+		if (!strcmp(name, (*ops)->name))
+			return *ops;
+
+		ops++;
+	}
+
+	return NULL;
+}
+
+/*
+ * Read a cpu's enable method from the device tree and record it in cpu_ops.
+ */
+int __init cpu_read_ops(struct device_node *dn, int cpu)
+{
+	const char *enable_method = of_get_property(dn, "enable-method", NULL);
+	if (!enable_method) {
+		/*
+		 * The boot CPU may not have an enable method (e.g. when
+		 * spin-table is used for secondaries). Don't warn spuriously.
+		 */
+		if (cpu != 0)
+			pr_err("%s: missing enable-method property\n",
+				dn->full_name);
+		return -ENOENT;
+	}
+
+	cpu_ops[cpu] = cpu_get_ops(enable_method);
+	if (!cpu_ops[cpu]) {
+		pr_warn("%s: unsupported enable-method property: %s\n",
+			dn->full_name, enable_method);
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+void __init cpu_read_bootcpu_ops(void)
+{
+	struct device_node *dn = of_get_cpu_node(0, NULL);
+	if (!dn) {
+		pr_err("Failed to find device node for boot cpu\n");
+		return;
+	}
+	cpu_read_ops(dn, 0);
+}
diff --git a/arch/arm64/kernel/cputable.c b/arch/arm64/kernel/cputable.c
index 63cfc4a..fd3993c 100644
--- a/arch/arm64/kernel/cputable.c
+++ b/arch/arm64/kernel/cputable.c
@@ -22,7 +22,7 @@
 
 extern unsigned long __cpu_setup(void);
 
-struct cpu_info __initdata cpu_table[] = {
+struct cpu_info cpu_table[] = {
 	{
 		.cpu_id_val	= 0x000f0000,
 		.cpu_id_mask	= 0x000f0000,
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 3881fd1..e116614 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -311,14 +311,14 @@
 #endif
 #ifdef CONFIG_PREEMPT
 	get_thread_info tsk
-	ldr	x24, [tsk, #TI_PREEMPT]		// get preempt count
-	add	x0, x24, #1			// increment it
-	str	x0, [tsk, #TI_PREEMPT]
+	ldr	w24, [tsk, #TI_PREEMPT]		// get preempt count
+	add	w0, w24, #1			// increment it
+	str	w0, [tsk, #TI_PREEMPT]
 #endif
 	irq_handler
 #ifdef CONFIG_PREEMPT
-	str	x24, [tsk, #TI_PREEMPT]		// restore preempt count
-	cbnz	x24, 1f				// preempt count != 0
+	str	w24, [tsk, #TI_PREEMPT]		// restore preempt count
+	cbnz	w24, 1f				// preempt count != 0
 	ldr	x0, [tsk, #TI_FLAGS]		// get flags
 	tbz	x0, #TIF_NEED_RESCHED, 1f	// needs rescheduling?
 	bl	el1_preempt
@@ -509,15 +509,15 @@
 #endif
 	get_thread_info tsk
 #ifdef CONFIG_PREEMPT
-	ldr	x24, [tsk, #TI_PREEMPT]		// get preempt count
-	add	x23, x24, #1			// increment it
-	str	x23, [tsk, #TI_PREEMPT]
+	ldr	w24, [tsk, #TI_PREEMPT]		// get preempt count
+	add	w23, w24, #1			// increment it
+	str	w23, [tsk, #TI_PREEMPT]
 #endif
 	irq_handler
 #ifdef CONFIG_PREEMPT
-	ldr	x0, [tsk, #TI_PREEMPT]
-	str	x24, [tsk, #TI_PREEMPT]
-	cmp	x0, x23
+	ldr	w0, [tsk, #TI_PREEMPT]
+	str	w24, [tsk, #TI_PREEMPT]
+	cmp	w0, w23
 	b.eq	1f
 	mov	x1, #0
 	str	x1, [x1]			// BUG
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 7090c12..7009387 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -123,8 +123,9 @@
 
 ENTRY(stext)
 	mov	x21, x0				// x21=FDT
+	bl	el2_setup			// Drop to EL1, w20=cpu_boot_mode
 	bl	__calc_phys_offset		// x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET
-	bl	el2_setup			// Drop to EL1
+	bl	set_cpu_boot_mode_flag
 	mrs	x22, midr_el1			// x22=cpuid
 	mov	x0, x22
 	bl	lookup_processor_type
@@ -150,21 +151,30 @@
 /*
  * If we're fortunate enough to boot at EL2, ensure that the world is
  * sane before dropping to EL1.
+ *
+ * Returns either BOOT_CPU_MODE_EL1 or BOOT_CPU_MODE_EL2 in x20 if
+ * booted in EL1 or EL2 respectively.
  */
 ENTRY(el2_setup)
 	mrs	x0, CurrentEL
 	cmp	x0, #PSR_MODE_EL2t
 	ccmp	x0, #PSR_MODE_EL2h, #0x4, ne
-	ldr	x0, =__boot_cpu_mode		// Compute __boot_cpu_mode
-	add	x0, x0, x28
-	b.eq	1f
-	str	wzr, [x0]			// Remember we don't have EL2...
+	b.ne	1f
+	mrs	x0, sctlr_el2
+CPU_BE(	orr	x0, x0, #(1 << 25)	)	// Set the EE bit for EL2
+CPU_LE(	bic	x0, x0, #(1 << 25)	)	// Clear the EE bit for EL2
+	msr	sctlr_el2, x0
+	b	2f
+1:	mrs	x0, sctlr_el1
+CPU_BE(	orr	x0, x0, #(3 << 24)	)	// Set the EE and E0E bits for EL1
+CPU_LE(	bic	x0, x0, #(3 << 24)	)	// Clear the EE and E0E bits for EL1
+	msr	sctlr_el1, x0
+	mov	w20, #BOOT_CPU_MODE_EL1		// This cpu booted in EL1
+	isb
 	ret
 
 	/* Hyp configuration. */
-1:	ldr	w1, =BOOT_CPU_MODE_EL2
-	str	w1, [x0, #4]			// This CPU has EL2
-	mov	x0, #(1 << 31)			// 64-bit EL1
+2:	mov	x0, #(1 << 31)			// 64-bit EL1
 	msr	hcr_el2, x0
 
 	/* Generic timers. */
@@ -181,7 +191,8 @@
 
 	/* sctlr_el1 */
 	mov	x0, #0x0800			// Set/clear RES{1,0} bits
-	movk	x0, #0x30d0, lsl #16
+CPU_BE(	movk	x0, #0x33d0, lsl #16	)	// Set EE and E0E on BE systems
+CPU_LE(	movk	x0, #0x30d0, lsl #16	)	// Clear EE and E0E on LE systems
 	msr	sctlr_el1, x0
 
 	/* Coprocessor traps. */
@@ -204,10 +215,25 @@
 		      PSR_MODE_EL1h)
 	msr	spsr_el2, x0
 	msr	elr_el2, lr
+	mov	w20, #BOOT_CPU_MODE_EL2		// This CPU booted in EL2
 	eret
 ENDPROC(el2_setup)
 
 /*
+ * Sets the __boot_cpu_mode flag depending on the CPU boot mode passed
+ * in x20. See arch/arm64/include/asm/virt.h for more info.
+ */
+ENTRY(set_cpu_boot_mode_flag)
+	ldr	x1, =__boot_cpu_mode		// Compute __boot_cpu_mode
+	add	x1, x1, x28
+	cmp	w20, #BOOT_CPU_MODE_EL2
+	b.ne	1f
+	add	x1, x1, #4
+1:	str	w20, [x1]			// This CPU has booted in EL1
+	ret
+ENDPROC(set_cpu_boot_mode_flag)
+
+/*
  * We need to find out the CPU boot mode long after boot, so we need to
  * store it in a writable variable.
  *
@@ -225,7 +251,6 @@
 	.quad	PAGE_OFFSET
 
 #ifdef CONFIG_SMP
-	.pushsection    .smp.pen.text, "ax"
 	.align	3
 1:	.quad	.
 	.quad	secondary_holding_pen_release
@@ -235,8 +260,9 @@
 	 * cores are held until we're ready for them to initialise.
 	 */
 ENTRY(secondary_holding_pen)
-	bl	__calc_phys_offset		// x24=phys offset
-	bl	el2_setup			// Drop to EL1
+	bl	el2_setup			// Drop to EL1, w20=cpu_boot_mode
+	bl	__calc_phys_offset		// x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET
+	bl	set_cpu_boot_mode_flag
 	mrs	x0, mpidr_el1
 	ldr     x1, =MPIDR_HWID_BITMASK
 	and	x0, x0, x1
@@ -250,7 +276,16 @@
 	wfe
 	b	pen
 ENDPROC(secondary_holding_pen)
-	.popsection
+
+	/*
+	 * Secondary entry point that jumps straight into the kernel. Only to
+	 * be used where CPUs are brought online dynamically by the kernel.
+	 */
+ENTRY(secondary_entry)
+	bl	__calc_phys_offset		// x2=phys offset
+	bl	el2_setup			// Drop to EL1
+	b	secondary_startup
+ENDPROC(secondary_entry)
 
 ENTRY(secondary_startup)
 	/*
diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c
index ecb3354..473e5db 100644
--- a/arch/arm64/kernel/irq.c
+++ b/arch/arm64/kernel/irq.c
@@ -81,3 +81,64 @@
 	if (!handle_arch_irq)
 		panic("No interrupt controller found.");
 }
+
+#ifdef CONFIG_HOTPLUG_CPU
+static bool migrate_one_irq(struct irq_desc *desc)
+{
+	struct irq_data *d = irq_desc_get_irq_data(desc);
+	const struct cpumask *affinity = d->affinity;
+	struct irq_chip *c;
+	bool ret = false;
+
+	/*
+	 * If this is a per-CPU interrupt, or the affinity does not
+	 * include this CPU, then we have nothing to do.
+	 */
+	if (irqd_is_per_cpu(d) || !cpumask_test_cpu(smp_processor_id(), affinity))
+		return false;
+
+	if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
+		affinity = cpu_online_mask;
+		ret = true;
+	}
+
+	c = irq_data_get_irq_chip(d);
+	if (!c->irq_set_affinity)
+		pr_debug("IRQ%u: unable to set affinity\n", d->irq);
+	else if (c->irq_set_affinity(d, affinity, true) == IRQ_SET_MASK_OK && ret)
+		cpumask_copy(d->affinity, affinity);
+
+	return ret;
+}
+
+/*
+ * The current CPU has been marked offline.  Migrate IRQs off this CPU.
+ * If the affinity settings do not allow other CPUs, force them onto any
+ * available CPU.
+ *
+ * Note: we must iterate over all IRQs, whether they have an attached
+ * action structure or not, as we need to get chained interrupts too.
+ */
+void migrate_irqs(void)
+{
+	unsigned int i;
+	struct irq_desc *desc;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	for_each_irq_desc(i, desc) {
+		bool affinity_broken;
+
+		raw_spin_lock(&desc->lock);
+		affinity_broken = migrate_one_irq(desc);
+		raw_spin_unlock(&desc->lock);
+
+		if (affinity_broken)
+			pr_warn_ratelimited("IRQ%u no longer affine to CPU%u\n",
+					    i, smp_processor_id());
+	}
+
+	local_irq_restore(flags);
+}
+#endif /* CONFIG_HOTPLUG_CPU */
diff --git a/arch/arm64/kernel/kuser32.S b/arch/arm64/kernel/kuser32.S
index 8b69ecb..63c48ff 100644
--- a/arch/arm64/kernel/kuser32.S
+++ b/arch/arm64/kernel/kuser32.S
@@ -27,6 +27,9 @@
  *
  * See Documentation/arm/kernel_user_helpers.txt for formal definitions.
  */
+
+#include <asm/unistd32.h>
+
 	.align	5
 	.globl	__kuser_helper_start
 __kuser_helper_start:
@@ -35,33 +38,30 @@
 	.inst	0xe92d00f0		//	push		{r4, r5, r6, r7}
 	.inst	0xe1c040d0		//	ldrd		r4, r5, [r0]
 	.inst	0xe1c160d0		//	ldrd		r6, r7, [r1]
-	.inst	0xf57ff05f		//	dmb		sy
-	.inst	0xe1b20f9f		// 1:	ldrexd		r0, r1, [r2]
+	.inst	0xe1b20e9f		// 1:	ldaexd		r0, r1, [r2]
 	.inst	0xe0303004		//	eors		r3, r0, r4
 	.inst	0x00313005		//	eoreqs		r3, r1, r5
-	.inst	0x01a23f96		//	strexdeq	r3, r6, [r2]
+	.inst	0x01a23e96		//	stlexdeq	r3, r6, [r2]
 	.inst	0x03330001		//	teqeq		r3, #1
 	.inst	0x0afffff9		//	beq		1b
-	.inst	0xf57ff05f		//	dmb		sy
 	.inst	0xe2730000		//	rsbs		r0, r3, #0
 	.inst	0xe8bd00f0		//	pop		{r4, r5, r6, r7}
 	.inst	0xe12fff1e		//	bx		lr
 
 	.align	5
 __kuser_memory_barrier:			// 0xffff0fa0
-	.inst	0xf57ff05f		//	dmb		sy
+	.inst	0xf57ff05b		//	dmb		ish
 	.inst	0xe12fff1e		//	bx		lr
 
 	.align	5
 __kuser_cmpxchg:			// 0xffff0fc0
-	.inst	0xf57ff05f		//	dmb		sy
-	.inst	0xe1923f9f		// 1:	ldrex		r3, [r2]
+	.inst	0xe1923e9f		// 1:	ldaex		r3, [r2]
 	.inst	0xe0533000		//	subs		r3, r3, r0
-	.inst	0x01823f91		//	strexeq	r3, r1, [r2]
+	.inst	0x01823e91		//	stlexeq		r3, r1, [r2]
 	.inst	0x03330001		//	teqeq		r3, #1
 	.inst	0x0afffffa		//	beq		1b
 	.inst	0xe2730000		//	rsbs		r0, r3, #0
-	.inst	0xeaffffef		//	b		<__kuser_memory_barrier>
+	.inst	0xe12fff1e		//	bx		lr
 
 	.align	5
 __kuser_get_tls:			// 0xffff0fe0
@@ -75,3 +75,42 @@
 	.word	((__kuser_helper_end - __kuser_helper_start) >> 5)
 	.globl	__kuser_helper_end
 __kuser_helper_end:
+
+/*
+ * AArch32 sigreturn code
+ *
+ * For ARM syscalls, the syscall number has to be loaded into r7.
+ * We do not support an OABI userspace.
+ *
+ * For Thumb syscalls, we also pass the syscall number via r7. We therefore
+ * need two 16-bit instructions.
+ */
+	.globl __aarch32_sigret_code_start
+__aarch32_sigret_code_start:
+
+	/*
+	 * ARM Code
+	 */
+	.byte	__NR_compat_sigreturn, 0x70, 0xa0, 0xe3	// mov	r7, #__NR_compat_sigreturn
+	.byte	__NR_compat_sigreturn, 0x00, 0x00, 0xef	// svc	#__NR_compat_sigreturn
+
+	/*
+	 * Thumb code
+	 */
+	.byte	__NR_compat_sigreturn, 0x27			// svc	#__NR_compat_sigreturn
+	.byte	__NR_compat_sigreturn, 0xdf			// mov	r7, #__NR_compat_sigreturn
+
+	/*
+	 * ARM code
+	 */
+	.byte	__NR_compat_rt_sigreturn, 0x70, 0xa0, 0xe3	// mov	r7, #__NR_compat_rt_sigreturn
+	.byte	__NR_compat_rt_sigreturn, 0x00, 0x00, 0xef	// svc	#__NR_compat_rt_sigreturn
+
+	/*
+	 * Thumb code
+	 */
+	.byte	__NR_compat_rt_sigreturn, 0x27			// svc	#__NR_compat_rt_sigreturn
+	.byte	__NR_compat_rt_sigreturn, 0xdf			// mov	r7, #__NR_compat_rt_sigreturn
+
+        .globl __aarch32_sigret_code_end
+__aarch32_sigret_code_end:
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c
index ca0e3d5..2c28a6c 100644
--- a/arch/arm64/kernel/module.c
+++ b/arch/arm64/kernel/module.c
@@ -111,6 +111,9 @@
 	u32 immlo, immhi, lomask, himask, mask;
 	int shift;
 
+	/* The instruction stream is always little endian. */
+	insn = le32_to_cpu(insn);
+
 	switch (type) {
 	case INSN_IMM_MOVNZ:
 		/*
@@ -179,7 +182,7 @@
 	insn &= ~(mask << shift);
 	insn |= (imm & mask) << shift;
 
-	return insn;
+	return cpu_to_le32(insn);
 }
 
 static int reloc_insn_movw(enum aarch64_reloc_op op, void *place, u64 val,
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index cea1594..5d14470 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -784,8 +784,8 @@
 /*
  * PMXEVTYPER: Event selection reg
  */
-#define	ARMV8_EVTYPE_MASK	0xc80000ff	/* Mask for writable bits */
-#define	ARMV8_EVTYPE_EVENT	0xff		/* Mask for EVENT bits */
+#define	ARMV8_EVTYPE_MASK	0xc80003ff	/* Mask for writable bits */
+#define	ARMV8_EVTYPE_EVENT	0x3ff		/* Mask for EVENT bits */
 
 /*
  * Event filters for PMUv3
@@ -1175,7 +1175,8 @@
 static int armv8_pmuv3_map_event(struct perf_event *event)
 {
 	return map_cpu_event(event, &armv8_pmuv3_perf_map,
-				&armv8_pmuv3_perf_cache_map, 0xFF);
+				&armv8_pmuv3_perf_cache_map,
+				ARMV8_EVTYPE_EVENT);
 }
 
 static struct arm_pmu armv8pmu = {
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 7ae8a1f..de17c89 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -102,6 +102,13 @@
 	local_irq_enable();
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+void arch_cpu_idle_dead(void)
+{
+       cpu_die();
+}
+#endif
+
 void machine_shutdown(void)
 {
 #ifdef CONFIG_SMP
diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c
index 14f73c4..4f97db3 100644
--- a/arch/arm64/kernel/psci.c
+++ b/arch/arm64/kernel/psci.c
@@ -17,12 +17,32 @@
 
 #include <linux/init.h>
 #include <linux/of.h>
+#include <linux/smp.h>
 
 #include <asm/compiler.h>
+#include <asm/cpu_ops.h>
 #include <asm/errno.h>
 #include <asm/psci.h>
+#include <asm/smp_plat.h>
 
-struct psci_operations psci_ops;
+#define PSCI_POWER_STATE_TYPE_STANDBY		0
+#define PSCI_POWER_STATE_TYPE_POWER_DOWN	1
+
+struct psci_power_state {
+	u16	id;
+	u8	type;
+	u8	affinity_level;
+};
+
+struct psci_operations {
+	int (*cpu_suspend)(struct psci_power_state state,
+			   unsigned long entry_point);
+	int (*cpu_off)(struct psci_power_state state);
+	int (*cpu_on)(unsigned long cpuid, unsigned long entry_point);
+	int (*migrate)(unsigned long cpuid);
+};
+
+static struct psci_operations psci_ops;
 
 static int (*invoke_psci_fn)(u64, u64, u64, u64);
 
@@ -209,3 +229,68 @@
 	of_node_put(np);
 	return err;
 }
+
+#ifdef CONFIG_SMP
+
+static int __init cpu_psci_cpu_init(struct device_node *dn, unsigned int cpu)
+{
+	return 0;
+}
+
+static int __init cpu_psci_cpu_prepare(unsigned int cpu)
+{
+	if (!psci_ops.cpu_on) {
+		pr_err("no cpu_on method, not booting CPU%d\n", cpu);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int cpu_psci_cpu_boot(unsigned int cpu)
+{
+	int err = psci_ops.cpu_on(cpu_logical_map(cpu), __pa(secondary_entry));
+	if (err)
+		pr_err("psci: failed to boot CPU%d (%d)\n", cpu, err);
+
+	return err;
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static int cpu_psci_cpu_disable(unsigned int cpu)
+{
+	/* Fail early if we don't have CPU_OFF support */
+	if (!psci_ops.cpu_off)
+		return -EOPNOTSUPP;
+	return 0;
+}
+
+static void cpu_psci_cpu_die(unsigned int cpu)
+{
+	int ret;
+	/*
+	 * There are no known implementations of PSCI actually using the
+	 * power state field, pass a sensible default for now.
+	 */
+	struct psci_power_state state = {
+		.type = PSCI_POWER_STATE_TYPE_POWER_DOWN,
+	};
+
+	ret = psci_ops.cpu_off(state);
+
+	pr_crit("psci: unable to power off CPU%u (%d)\n", cpu, ret);
+}
+#endif
+
+const struct cpu_operations cpu_psci_ops = {
+	.name		= "psci",
+	.cpu_init	= cpu_psci_cpu_init,
+	.cpu_prepare	= cpu_psci_cpu_prepare,
+	.cpu_boot	= cpu_psci_cpu_boot,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_disable	= cpu_psci_cpu_disable,
+	.cpu_die	= cpu_psci_cpu_die,
+#endif
+};
+
+#endif
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 055cfb8..0bc5e4c 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -45,6 +45,7 @@
 #include <asm/cputype.h>
 #include <asm/elf.h>
 #include <asm/cputable.h>
+#include <asm/cpu_ops.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/smp_plat.h>
@@ -60,6 +61,16 @@
 unsigned long elf_hwcap __read_mostly;
 EXPORT_SYMBOL_GPL(elf_hwcap);
 
+#ifdef CONFIG_COMPAT
+#define COMPAT_ELF_HWCAP_DEFAULT	\
+				(COMPAT_HWCAP_HALF|COMPAT_HWCAP_THUMB|\
+				 COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\
+				 COMPAT_HWCAP_TLS|COMPAT_HWCAP_VFP|\
+				 COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\
+				 COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV)
+unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT;
+#endif
+
 static const char *cpu_name;
 static const char *machine_name;
 phys_addr_t __fdt_pointer __initdata;
@@ -97,6 +108,11 @@
 	printk("%s", buf);
 }
 
+bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
+{
+	return phys_id == cpu_logical_map(cpu);
+}
+
 static void __init setup_processor(void)
 {
 	struct cpu_info *cpu_info;
@@ -118,76 +134,24 @@
 	printk("CPU: %s [%08x] revision %d\n",
 	       cpu_name, read_cpuid_id(), read_cpuid_id() & 15);
 
-	sprintf(init_utsname()->machine, "aarch64");
+	sprintf(init_utsname()->machine, ELF_PLATFORM);
 	elf_hwcap = 0;
 }
 
 static void __init setup_machine_fdt(phys_addr_t dt_phys)
 {
-	struct boot_param_header *devtree;
-	unsigned long dt_root;
-
-	/* Check we have a non-NULL DT pointer */
-	if (!dt_phys) {
-		early_print("\n"
-			"Error: NULL or invalid device tree blob\n"
-			"The dtb must be 8-byte aligned and passed in the first 512MB of memory\n"
-			"\nPlease check your bootloader.\n");
-
-		while (true)
-			cpu_relax();
-
-	}
-
-	devtree = phys_to_virt(dt_phys);
-
-	/* Check device tree validity */
-	if (be32_to_cpu(devtree->magic) != OF_DT_HEADER) {
+	if (!dt_phys || !early_init_dt_scan(phys_to_virt(dt_phys))) {
 		early_print("\n"
 			"Error: invalid device tree blob at physical address 0x%p (virtual address 0x%p)\n"
-			"Expected 0x%x, found 0x%x\n"
+			"The dtb must be 8-byte aligned and passed in the first 512MB of memory\n"
 			"\nPlease check your bootloader.\n",
-			dt_phys, devtree, OF_DT_HEADER,
-			be32_to_cpu(devtree->magic));
+			dt_phys, phys_to_virt(dt_phys));
 
 		while (true)
 			cpu_relax();
 	}
 
-	initial_boot_params = devtree;
-	dt_root = of_get_flat_dt_root();
-
-	machine_name = of_get_flat_dt_prop(dt_root, "model", NULL);
-	if (!machine_name)
-		machine_name = of_get_flat_dt_prop(dt_root, "compatible", NULL);
-	if (!machine_name)
-		machine_name = "<unknown>";
-	pr_info("Machine: %s\n", machine_name);
-
-	/* Retrieve various information from the /chosen node */
-	of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
-	/* Initialize {size,address}-cells info */
-	of_scan_flat_dt(early_init_dt_scan_root, NULL);
-	/* Setup memory, calling early_init_dt_add_memory_arch */
-	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
-}
-
-void __init early_init_dt_add_memory_arch(u64 base, u64 size)
-{
-	base &= PAGE_MASK;
-	size &= PAGE_MASK;
-	if (base + size < PHYS_OFFSET) {
-		pr_warning("Ignoring memory block 0x%llx - 0x%llx\n",
-			   base, base + size);
-		return;
-	}
-	if (base < PHYS_OFFSET) {
-		pr_warning("Ignoring memory range 0x%llx - 0x%llx\n",
-			   base, PHYS_OFFSET);
-		size -= PHYS_OFFSET - base;
-		base = PHYS_OFFSET;
-	}
-	memblock_add(base, size);
+	machine_name = of_flat_dt_get_machine_name();
 }
 
 /*
@@ -264,6 +228,7 @@
 	psci_init();
 
 	cpu_logical_map(0) = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
+	cpu_read_bootcpu_ops();
 #ifdef CONFIG_SMP
 	smp_init_cpus();
 #endif
@@ -304,6 +269,7 @@
 static const char *hwcap_str[] = {
 	"fp",
 	"asimd",
+	"evtstrm",
 	NULL
 };
 
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index 07da8c0..b3fc9f5 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -100,34 +100,6 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-/*
- * For ARM syscalls, the syscall number has to be loaded into r7.
- * We do not support an OABI userspace.
- */
-#define MOV_R7_NR_SIGRETURN	(0xe3a07000 | __NR_compat_sigreturn)
-#define SVC_SYS_SIGRETURN	(0xef000000 | __NR_compat_sigreturn)
-#define MOV_R7_NR_RT_SIGRETURN	(0xe3a07000 | __NR_compat_rt_sigreturn)
-#define SVC_SYS_RT_SIGRETURN	(0xef000000 | __NR_compat_rt_sigreturn)
-
-/*
- * For Thumb syscalls, we also pass the syscall number via r7. We therefore
- * need two 16-bit instructions.
- */
-#define SVC_THUMB_SIGRETURN	(((0xdf00 | __NR_compat_sigreturn) << 16) | \
-				   0x2700 | __NR_compat_sigreturn)
-#define SVC_THUMB_RT_SIGRETURN	(((0xdf00 | __NR_compat_rt_sigreturn) << 16) | \
-				   0x2700 | __NR_compat_rt_sigreturn)
-
-const compat_ulong_t aarch32_sigret_code[6] = {
-	/*
-	 * AArch32 sigreturn code.
-	 * We don't construct an OABI SWI - instead we just set the imm24 field
-	 * to the EABI syscall number so that we create a sane disassembly.
-	 */
-	MOV_R7_NR_SIGRETURN,    SVC_SYS_SIGRETURN,    SVC_THUMB_SIGRETURN,
-	MOV_R7_NR_RT_SIGRETURN, SVC_SYS_RT_SIGRETURN, SVC_THUMB_RT_SIGRETURN,
-};
-
 static inline int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set)
 {
 	compat_sigset_t	cset;
@@ -474,12 +446,13 @@
 	/* Check if the handler is written for ARM or Thumb */
 	thumb = handler & 1;
 
-	if (thumb) {
+	if (thumb)
 		spsr |= COMPAT_PSR_T_BIT;
-		spsr &= ~COMPAT_PSR_IT_MASK;
-	} else {
+	else
 		spsr &= ~COMPAT_PSR_T_BIT;
-	}
+
+	/* The IT state must be cleared for both ARM and Thumb-2 */
+	spsr &= ~COMPAT_PSR_IT_MASK;
 
 	if (ka->sa.sa_flags & SA_RESTORER) {
 		retcode = ptr_to_compat(ka->sa.sa_restorer);
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 78db90d..a5aeefa 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -39,6 +39,7 @@
 #include <asm/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/cputype.h>
+#include <asm/cpu_ops.h>
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -54,7 +55,6 @@
  * where to place its SVC stack
  */
 struct secondary_data secondary_data;
-volatile unsigned long secondary_holding_pen_release = INVALID_HWID;
 
 enum ipi_msg_type {
 	IPI_RESCHEDULE,
@@ -63,61 +63,16 @@
 	IPI_CPU_STOP,
 };
 
-static DEFINE_RAW_SPINLOCK(boot_lock);
-
-/*
- * Write secondary_holding_pen_release in a way that is guaranteed to be
- * visible to all observers, irrespective of whether they're taking part
- * in coherency or not.  This is necessary for the hotplug code to work
- * reliably.
- */
-static void write_pen_release(u64 val)
-{
-	void *start = (void *)&secondary_holding_pen_release;
-	unsigned long size = sizeof(secondary_holding_pen_release);
-
-	secondary_holding_pen_release = val;
-	__flush_dcache_area(start, size);
-}
-
 /*
  * Boot a secondary CPU, and assign it the specified idle task.
  * This also gives us the initial stack to use for this CPU.
  */
 static int boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-	unsigned long timeout;
+	if (cpu_ops[cpu]->cpu_boot)
+		return cpu_ops[cpu]->cpu_boot(cpu);
 
-	/*
-	 * Set synchronisation state between this boot processor
-	 * and the secondary one
-	 */
-	raw_spin_lock(&boot_lock);
-
-	/*
-	 * Update the pen release flag.
-	 */
-	write_pen_release(cpu_logical_map(cpu));
-
-	/*
-	 * Send an event, causing the secondaries to read pen_release.
-	 */
-	sev();
-
-	timeout = jiffies + (1 * HZ);
-	while (time_before(jiffies, timeout)) {
-		if (secondary_holding_pen_release == INVALID_HWID)
-			break;
-		udelay(10);
-	}
-
-	/*
-	 * Now the secondary core is starting up let it run its
-	 * calibrations, then wait for it to finish
-	 */
-	raw_spin_unlock(&boot_lock);
-
-	return secondary_holding_pen_release != INVALID_HWID ? -ENOSYS : 0;
+	return -EOPNOTSUPP;
 }
 
 static DECLARE_COMPLETION(cpu_running);
@@ -187,17 +142,13 @@
 	preempt_disable();
 	trace_hardirqs_off();
 
-	/*
-	 * Let the primary processor know we're out of the
-	 * pen, then head off into the C entry point
-	 */
-	write_pen_release(INVALID_HWID);
+	if (cpu_ops[cpu]->cpu_postboot)
+		cpu_ops[cpu]->cpu_postboot();
 
 	/*
-	 * Synchronise with the boot thread.
+	 * Enable GIC and timers.
 	 */
-	raw_spin_lock(&boot_lock);
-	raw_spin_unlock(&boot_lock);
+	notify_cpu_starting(cpu);
 
 	/*
 	 * OK, now it's safe to let the boot CPU continue.  Wait for
@@ -207,11 +158,6 @@
 	set_cpu_online(cpu, true);
 	complete(&cpu_running);
 
-	/*
-	 * Enable GIC and timers.
-	 */
-	notify_cpu_starting(cpu);
-
 	local_irq_enable();
 	local_fiq_enable();
 
@@ -221,6 +167,102 @@
 	cpu_startup_entry(CPUHP_ONLINE);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+static int op_cpu_disable(unsigned int cpu)
+{
+	/*
+	 * If we don't have a cpu_die method, abort before we reach the point
+	 * of no return. CPU0 may not have an cpu_ops, so test for it.
+	 */
+	if (!cpu_ops[cpu] || !cpu_ops[cpu]->cpu_die)
+		return -EOPNOTSUPP;
+
+	/*
+	 * We may need to abort a hot unplug for some other mechanism-specific
+	 * reason.
+	 */
+	if (cpu_ops[cpu]->cpu_disable)
+		return cpu_ops[cpu]->cpu_disable(cpu);
+
+	return 0;
+}
+
+/*
+ * __cpu_disable runs on the processor to be shutdown.
+ */
+int __cpu_disable(void)
+{
+	unsigned int cpu = smp_processor_id();
+	int ret;
+
+	ret = op_cpu_disable(cpu);
+	if (ret)
+		return ret;
+
+	/*
+	 * Take this CPU offline.  Once we clear this, we can't return,
+	 * and we must not schedule until we're ready to give up the cpu.
+	 */
+	set_cpu_online(cpu, false);
+
+	/*
+	 * OK - migrate IRQs away from this CPU
+	 */
+	migrate_irqs();
+
+	/*
+	 * Remove this CPU from the vm mask set of all processes.
+	 */
+	clear_tasks_mm_cpumask(cpu);
+
+	return 0;
+}
+
+static DECLARE_COMPLETION(cpu_died);
+
+/*
+ * called on the thread which is asking for a CPU to be shutdown -
+ * waits until shutdown has completed, or it is timed out.
+ */
+void __cpu_die(unsigned int cpu)
+{
+	if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) {
+		pr_crit("CPU%u: cpu didn't die\n", cpu);
+		return;
+	}
+	pr_notice("CPU%u: shutdown\n", cpu);
+}
+
+/*
+ * Called from the idle thread for the CPU which has been shutdown.
+ *
+ * Note that we disable IRQs here, but do not re-enable them
+ * before returning to the caller. This is also the behaviour
+ * of the other hotplug-cpu capable cores, so presumably coming
+ * out of idle fixes this.
+ */
+void cpu_die(void)
+{
+	unsigned int cpu = smp_processor_id();
+
+	idle_task_exit();
+
+	local_irq_disable();
+
+	/* Tell __cpu_die() that this CPU is now safe to dispose of */
+	complete(&cpu_died);
+
+	/*
+	 * Actually shutdown the CPU. This must never fail. The specific hotplug
+	 * mechanism must perform all required cache maintenance to ensure that
+	 * no dirty lines are lost in the process of shutting down the CPU.
+	 */
+	cpu_ops[cpu]->cpu_die(cpu);
+
+	BUG();
+}
+#endif
+
 void __init smp_cpus_done(unsigned int max_cpus)
 {
 	pr_info("SMP: Total of %d processors activated.\n", num_online_cpus());
@@ -232,28 +274,6 @@
 
 static void (*smp_cross_call)(const struct cpumask *, unsigned int);
 
-static const struct smp_enable_ops *enable_ops[] __initconst = {
-	&smp_spin_table_ops,
-	&smp_psci_ops,
-	NULL,
-};
-
-static const struct smp_enable_ops *smp_enable_ops[NR_CPUS];
-
-static const struct smp_enable_ops * __init smp_get_enable_ops(const char *name)
-{
-	const struct smp_enable_ops **ops = enable_ops;
-
-	while (*ops) {
-		if (!strcmp(name, (*ops)->name))
-			return *ops;
-
-		ops++;
-	}
-
-	return NULL;
-}
-
 /*
  * Enumerate the possible CPU set from the device tree and build the
  * cpu logical map array containing MPIDR values related to logical
@@ -261,9 +281,8 @@
  */
 void __init smp_init_cpus(void)
 {
-	const char *enable_method;
 	struct device_node *dn = NULL;
-	int i, cpu = 1;
+	unsigned int i, cpu = 1;
 	bool bootcpu_valid = false;
 
 	while ((dn = of_find_node_by_type(dn, "cpu"))) {
@@ -332,25 +351,10 @@
 		if (cpu >= NR_CPUS)
 			goto next;
 
-		/*
-		 * We currently support only the "spin-table" enable-method.
-		 */
-		enable_method = of_get_property(dn, "enable-method", NULL);
-		if (!enable_method) {
-			pr_err("%s: missing enable-method property\n",
-				dn->full_name);
+		if (cpu_read_ops(dn, cpu) != 0)
 			goto next;
-		}
 
-		smp_enable_ops[cpu] = smp_get_enable_ops(enable_method);
-
-		if (!smp_enable_ops[cpu]) {
-			pr_err("%s: invalid enable-method property: %s\n",
-			       dn->full_name, enable_method);
-			goto next;
-		}
-
-		if (smp_enable_ops[cpu]->init_cpu(dn, cpu))
+		if (cpu_ops[cpu]->cpu_init(dn, cpu))
 			goto next;
 
 		pr_debug("cpu logical map 0x%llx\n", hwid);
@@ -380,8 +384,8 @@
 
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
-	int cpu, err;
-	unsigned int ncores = num_possible_cpus();
+	int err;
+	unsigned int cpu, ncores = num_possible_cpus();
 
 	/*
 	 * are we trying to boot more cores than exist?
@@ -408,10 +412,10 @@
 		if (cpu == smp_processor_id())
 			continue;
 
-		if (!smp_enable_ops[cpu])
+		if (!cpu_ops[cpu])
 			continue;
 
-		err = smp_enable_ops[cpu]->prepare_cpu(cpu);
+		err = cpu_ops[cpu]->cpu_prepare(cpu);
 		if (err)
 			continue;
 
@@ -451,7 +455,7 @@
 	for (i = 0; i < NR_IPI; i++) {
 		seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i + IPI_RESCHEDULE,
 			   prec >= 4 ? " " : "");
-		for_each_present_cpu(cpu)
+		for_each_online_cpu(cpu)
 			seq_printf(p, "%10u ",
 				   __get_irq_stat(cpu, ipi_irqs[i]));
 		seq_printf(p, "      %s\n", ipi_types[i]);
diff --git a/arch/arm64/kernel/smp_psci.c b/arch/arm64/kernel/smp_psci.c
deleted file mode 100644
index 0c53330..0000000
--- a/arch/arm64/kernel/smp_psci.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * PSCI SMP initialisation
- *
- * Copyright (C) 2013 ARM Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/init.h>
-#include <linux/of.h>
-#include <linux/smp.h>
-
-#include <asm/psci.h>
-#include <asm/smp_plat.h>
-
-static int __init smp_psci_init_cpu(struct device_node *dn, int cpu)
-{
-	return 0;
-}
-
-static int __init smp_psci_prepare_cpu(int cpu)
-{
-	int err;
-
-	if (!psci_ops.cpu_on) {
-		pr_err("psci: no cpu_on method, not booting CPU%d\n", cpu);
-		return -ENODEV;
-	}
-
-	err = psci_ops.cpu_on(cpu_logical_map(cpu), __pa(secondary_holding_pen));
-	if (err) {
-		pr_err("psci: failed to boot CPU%d (%d)\n", cpu, err);
-		return err;
-	}
-
-	return 0;
-}
-
-const struct smp_enable_ops smp_psci_ops __initconst = {
-	.name		= "psci",
-	.init_cpu	= smp_psci_init_cpu,
-	.prepare_cpu	= smp_psci_prepare_cpu,
-};
diff --git a/arch/arm64/kernel/smp_spin_table.c b/arch/arm64/kernel/smp_spin_table.c
index 7c35fa6..44c2280 100644
--- a/arch/arm64/kernel/smp_spin_table.c
+++ b/arch/arm64/kernel/smp_spin_table.c
@@ -16,15 +16,39 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/of.h>
 #include <linux/smp.h>
 
 #include <asm/cacheflush.h>
+#include <asm/cpu_ops.h>
+#include <asm/cputype.h>
+#include <asm/smp_plat.h>
+
+extern void secondary_holding_pen(void);
+volatile unsigned long secondary_holding_pen_release = INVALID_HWID;
 
 static phys_addr_t cpu_release_addr[NR_CPUS];
+static DEFINE_RAW_SPINLOCK(boot_lock);
 
-static int __init smp_spin_table_init_cpu(struct device_node *dn, int cpu)
+/*
+ * Write secondary_holding_pen_release in a way that is guaranteed to be
+ * visible to all observers, irrespective of whether they're taking part
+ * in coherency or not.  This is necessary for the hotplug code to work
+ * reliably.
+ */
+static void write_pen_release(u64 val)
+{
+	void *start = (void *)&secondary_holding_pen_release;
+	unsigned long size = sizeof(secondary_holding_pen_release);
+
+	secondary_holding_pen_release = val;
+	__flush_dcache_area(start, size);
+}
+
+
+static int smp_spin_table_cpu_init(struct device_node *dn, unsigned int cpu)
 {
 	/*
 	 * Determine the address from which the CPU is polling.
@@ -40,7 +64,7 @@
 	return 0;
 }
 
-static int __init smp_spin_table_prepare_cpu(int cpu)
+static int smp_spin_table_cpu_prepare(unsigned int cpu)
 {
 	void **release_addr;
 
@@ -48,7 +72,16 @@
 		return -ENODEV;
 
 	release_addr = __va(cpu_release_addr[cpu]);
-	release_addr[0] = (void *)__pa(secondary_holding_pen);
+
+	/*
+	 * We write the release address as LE regardless of the native
+	 * endianess of the kernel. Therefore, any boot-loaders that
+	 * read this address need to convert this address to the
+	 * boot-loader's endianess before jumping. This is mandated by
+	 * the boot protocol.
+	 */
+	release_addr[0] = (void *) cpu_to_le64(__pa(secondary_holding_pen));
+
 	__flush_dcache_area(release_addr, sizeof(release_addr[0]));
 
 	/*
@@ -59,8 +92,60 @@
 	return 0;
 }
 
-const struct smp_enable_ops smp_spin_table_ops __initconst = {
+static int smp_spin_table_cpu_boot(unsigned int cpu)
+{
+	unsigned long timeout;
+
+	/*
+	 * Set synchronisation state between this boot processor
+	 * and the secondary one
+	 */
+	raw_spin_lock(&boot_lock);
+
+	/*
+	 * Update the pen release flag.
+	 */
+	write_pen_release(cpu_logical_map(cpu));
+
+	/*
+	 * Send an event, causing the secondaries to read pen_release.
+	 */
+	sev();
+
+	timeout = jiffies + (1 * HZ);
+	while (time_before(jiffies, timeout)) {
+		if (secondary_holding_pen_release == INVALID_HWID)
+			break;
+		udelay(10);
+	}
+
+	/*
+	 * Now the secondary core is starting up let it run its
+	 * calibrations, then wait for it to finish
+	 */
+	raw_spin_unlock(&boot_lock);
+
+	return secondary_holding_pen_release != INVALID_HWID ? -ENOSYS : 0;
+}
+
+void smp_spin_table_cpu_postboot(void)
+{
+	/*
+	 * Let the primary processor know we're out of the pen.
+	 */
+	write_pen_release(INVALID_HWID);
+
+	/*
+	 * Synchronise with the boot thread.
+	 */
+	raw_spin_lock(&boot_lock);
+	raw_spin_unlock(&boot_lock);
+}
+
+const struct cpu_operations smp_spin_table_ops = {
 	.name		= "spin-table",
-	.init_cpu 	= smp_spin_table_init_cpu,
-	.prepare_cpu	= smp_spin_table_prepare_cpu,
+	.cpu_init	= smp_spin_table_cpu_init,
+	.cpu_prepare	= smp_spin_table_cpu_prepare,
+	.cpu_boot	= smp_spin_table_cpu_boot,
+	.cpu_postboot	= smp_spin_table_cpu_postboot,
 };
diff --git a/arch/arm64/kernel/sys32.S b/arch/arm64/kernel/sys32.S
index a1b19ed..423a5b3 100644
--- a/arch/arm64/kernel/sys32.S
+++ b/arch/arm64/kernel/sys32.S
@@ -59,48 +59,48 @@
  * extension.
  */
 compat_sys_pread64_wrapper:
-	orr	x3, x4, x5, lsl #32
+	regs_to_64	x3, x4, x5
 	b	sys_pread64
 ENDPROC(compat_sys_pread64_wrapper)
 
 compat_sys_pwrite64_wrapper:
-	orr	x3, x4, x5, lsl #32
+	regs_to_64	x3, x4, x5
 	b	sys_pwrite64
 ENDPROC(compat_sys_pwrite64_wrapper)
 
 compat_sys_truncate64_wrapper:
-	orr	x1, x2, x3, lsl #32
+	regs_to_64	x1, x2, x3
 	b	sys_truncate
 ENDPROC(compat_sys_truncate64_wrapper)
 
 compat_sys_ftruncate64_wrapper:
-	orr	x1, x2, x3, lsl #32
+	regs_to_64	x1, x2, x3
 	b	sys_ftruncate
 ENDPROC(compat_sys_ftruncate64_wrapper)
 
 compat_sys_readahead_wrapper:
-	orr	x1, x2, x3, lsl #32
+	regs_to_64	x1, x2, x3
 	mov	w2, w4
 	b	sys_readahead
 ENDPROC(compat_sys_readahead_wrapper)
 
 compat_sys_fadvise64_64_wrapper:
 	mov	w6, w1
-	orr	x1, x2, x3, lsl #32
-	orr	x2, x4, x5, lsl #32
+	regs_to_64	x1, x2, x3
+	regs_to_64	x2, x4, x5
 	mov	w3, w6
 	b	sys_fadvise64_64
 ENDPROC(compat_sys_fadvise64_64_wrapper)
 
 compat_sys_sync_file_range2_wrapper:
-	orr	x2, x2, x3, lsl #32
-	orr	x3, x4, x5, lsl #32
+	regs_to_64	x2, x2, x3
+	regs_to_64	x3, x4, x5
 	b	sys_sync_file_range2
 ENDPROC(compat_sys_sync_file_range2_wrapper)
 
 compat_sys_fallocate_wrapper:
-	orr	x2, x2, x3, lsl #32
-	orr	x3, x4, x5, lsl #32
+	regs_to_64	x2, x2, x3
+	regs_to_64	x3, x4, x5
 	b	sys_fallocate
 ENDPROC(compat_sys_fallocate_wrapper)
 
diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c
index 03dc371..29c39d5 100644
--- a/arch/arm64/kernel/time.c
+++ b/arch/arm64/kernel/time.c
@@ -61,13 +61,6 @@
 EXPORT_SYMBOL(profile_pc);
 #endif
 
-static u64 sched_clock_mult __read_mostly;
-
-unsigned long long notrace sched_clock(void)
-{
-	return arch_timer_read_counter() * sched_clock_mult;
-}
-
 void __init time_init(void)
 {
 	u32 arch_timer_rate;
@@ -78,9 +71,6 @@
 	if (!arch_timer_rate)
 		panic("Unable to initialise architected timer.\n");
 
-	/* Cache the sched_clock multiplier to save a divide in the hot path. */
-	sched_clock_mult = NSEC_PER_SEC / arch_timer_rate;
-
 	/* Calibrate the delay loop directly */
 	lpj_fine = arch_timer_rate / HZ;
 }
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 6a389dc..65d40cf 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -58,7 +58,10 @@
 static int alloc_vectors_page(void)
 {
 	extern char __kuser_helper_start[], __kuser_helper_end[];
+	extern char __aarch32_sigret_code_start[], __aarch32_sigret_code_end[];
+
 	int kuser_sz = __kuser_helper_end - __kuser_helper_start;
+	int sigret_sz = __aarch32_sigret_code_end - __aarch32_sigret_code_start;
 	unsigned long vpage;
 
 	vpage = get_zeroed_page(GFP_ATOMIC);
@@ -72,7 +75,7 @@
 
 	/* sigreturn code */
 	memcpy((void *)vpage + AARCH32_KERN_SIGRET_CODE_OFFSET,
-		aarch32_sigret_code, sizeof(aarch32_sigret_code));
+               __aarch32_sigret_code_start, sigret_sz);
 
 	flush_icache_range(vpage, vpage + PAGE_SIZE);
 	vectors_page[0] = virt_to_page(vpage);
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index f8ab9d8..5161ad9 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -54,7 +54,6 @@
 	}
 	.text : {			/* Real text segment		*/
 		_stext = .;		/* Text and read-only data	*/
-			*(.smp.pen.text)
 			__exception_text_start = .;
 			*(.exception.text)
 			__exception_text_end = .;
@@ -97,30 +96,13 @@
 	PERCPU_SECTION(64)
 
 	__init_end = .;
-	. = ALIGN(THREAD_SIZE);
-	__data_loc = .;
 
-	.data : AT(__data_loc) {
-		_data = .;		/* address in memory */
-		_sdata = .;
-
-		/*
-		 * first, the init task union, aligned
-		 * to an 8192 byte boundary.
-		 */
-		INIT_TASK_DATA(THREAD_SIZE)
-		NOSAVE_DATA
-		CACHELINE_ALIGNED_DATA(64)
-		READ_MOSTLY_DATA(64)
-
-		/*
-		 * and the usual data section
-		 */
-		DATA_DATA
-		CONSTRUCTORS
-
-		_edata = .;
-	}
+	. = ALIGN(PAGE_SIZE);
+	_data = .;
+	__data_loc = _data - LOAD_OFFSET;
+	_sdata = .;
+	RW_DATA_SECTION(64, PAGE_SIZE, THREAD_SIZE)
+	_edata = .;
 	_edata_loc = __data_loc + SIZEOF(.data);
 
 	BSS_SECTION(0, 0, 0)
diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S
index ba84e67..2b0244d 100644
--- a/arch/arm64/kvm/hyp-init.S
+++ b/arch/arm64/kvm/hyp-init.S
@@ -74,7 +74,10 @@
 	msr	mair_el2, x4
 	isb
 
-	mov	x4, #SCTLR_EL2_FLAGS
+	mrs	x4, sctlr_el2
+	and	x4, x4, #SCTLR_EL2_EE	// preserve endianness of EL2
+	ldr	x5, =SCTLR_EL2_FLAGS
+	orr	x4, x4, x5
 	msr	sctlr_el2, x4
 	isb
 
diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
index 1ac0bbb..3b47c36 100644
--- a/arch/arm64/kvm/hyp.S
+++ b/arch/arm64/kvm/hyp.S
@@ -403,6 +403,14 @@
 	ldr	w9, [x2, #GICH_ELRSR0]
 	ldr	w10, [x2, #GICH_ELRSR1]
 	ldr	w11, [x2, #GICH_APR]
+CPU_BE(	rev	w4,  w4  )
+CPU_BE(	rev	w5,  w5  )
+CPU_BE(	rev	w6,  w6  )
+CPU_BE(	rev	w7,  w7  )
+CPU_BE(	rev	w8,  w8  )
+CPU_BE(	rev	w9,  w9  )
+CPU_BE(	rev	w10, w10 )
+CPU_BE(	rev	w11, w11 )
 
 	str	w4, [x3, #VGIC_CPU_HCR]
 	str	w5, [x3, #VGIC_CPU_VMCR]
@@ -421,6 +429,7 @@
 	ldr	w4, [x3, #VGIC_CPU_NR_LR]
 	add	x3, x3, #VGIC_CPU_LR
 1:	ldr	w5, [x2], #4
+CPU_BE(	rev	w5, w5 )
 	str	w5, [x3], #4
 	sub	w4, w4, #1
 	cbnz	w4, 1b
@@ -446,6 +455,9 @@
 	ldr	w4, [x3, #VGIC_CPU_HCR]
 	ldr	w5, [x3, #VGIC_CPU_VMCR]
 	ldr	w6, [x3, #VGIC_CPU_APR]
+CPU_BE(	rev	w4, w4 )
+CPU_BE(	rev	w5, w5 )
+CPU_BE(	rev	w6, w6 )
 
 	str	w4, [x2, #GICH_HCR]
 	str	w5, [x2, #GICH_VMCR]
@@ -456,6 +468,7 @@
 	ldr	w4, [x3, #VGIC_CPU_NR_LR]
 	add	x3, x3, #VGIC_CPU_LR
 1:	ldr	w5, [x3], #4
+CPU_BE(	rev	w5, w5 )
 	str	w5, [x2], #4
 	sub	w4, w4, #1
 	cbnz	w4, 1b
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index de2de5d..0cb8742 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -31,7 +31,6 @@
 #include <linux/sort.h>
 #include <linux/of_fdt.h>
 
-#include <asm/prom.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/sizes.h>
@@ -39,17 +38,9 @@
 
 #include "mm.h"
 
-static unsigned long phys_initrd_start __initdata = 0;
-static unsigned long phys_initrd_size __initdata = 0;
-
 phys_addr_t memstart_addr __read_mostly = 0;
 
-void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
-{
-	phys_initrd_start = start;
-	phys_initrd_size = end - start;
-}
-
+#ifdef CONFIG_BLK_DEV_INITRD
 static int __init early_initrd(char *p)
 {
 	unsigned long start, size;
@@ -59,12 +50,13 @@
 	if (*endp == ',') {
 		size = memparse(endp + 1, NULL);
 
-		phys_initrd_start = start;
-		phys_initrd_size = size;
+		initrd_start = (unsigned long)__va(start);
+		initrd_end = (unsigned long)__va(start + size);
 	}
 	return 0;
 }
 early_param("initrd", early_initrd);
+#endif
 
 #define MAX_DMA32_PFN ((4UL * 1024 * 1024 * 1024) >> PAGE_SHIFT)
 
@@ -137,13 +129,8 @@
 	/* Register the kernel text, kernel data and initrd with memblock */
 	memblock_reserve(__pa(_text), _end - _text);
 #ifdef CONFIG_BLK_DEV_INITRD
-	if (phys_initrd_size) {
-		memblock_reserve(phys_initrd_start, phys_initrd_size);
-
-		/* Now convert initrd to virtual addresses */
-		initrd_start = __phys_to_virt(phys_initrd_start);
-		initrd_end = initrd_start + phys_initrd_size;
-	}
+	if (initrd_start)
+		memblock_reserve(__virt_to_phys(initrd_start), initrd_end - initrd_start);
 #endif
 
 	/*
diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c
index 1725cd6..2bb1d58 100644
--- a/arch/arm64/mm/ioremap.c
+++ b/arch/arm64/mm/ioremap.c
@@ -77,8 +77,24 @@
 
 void __iounmap(volatile void __iomem *io_addr)
 {
-	void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
+	unsigned long addr = (unsigned long)io_addr & PAGE_MASK;
 
-	vunmap(addr);
+	/*
+	 * We could get an address outside vmalloc range in case
+	 * of ioremap_cache() reusing a RAM mapping.
+	 */
+	if (VMALLOC_START <= addr && addr < VMALLOC_END)
+		vunmap((void *)addr);
 }
 EXPORT_SYMBOL(__iounmap);
+
+void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size)
+{
+	/* For normal memory we already have a cacheable mapping. */
+	if (pfn_valid(__phys_to_pfn(phys_addr)))
+		return (void __iomem *)__phys_to_virt(phys_addr);
+
+	return __ioremap_caller(phys_addr, size, __pgprot(PROT_NORMAL),
+				__builtin_return_address(0));
+}
+EXPORT_SYMBOL(ioremap_cache);
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index b1b31bb..421b99f 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -162,9 +162,9 @@
 	 *       CE0      XWHW CZ     ME TEEA S
 	 * .... .IEE .... NEAI TE.I ..AD DEN0 ACAM
 	 * 0011 0... 1101 ..0. ..0. 10.. .... .... < hardware reserved
-	 * .... .100 .... 01.1 11.1 ..01 0001 1101 < software settings
+	 * .... .1.. .... 01.1 11.1 ..01 0001 1101 < software settings
 	 */
 	.type	crval, #object
 crval:
-	.word	0x030802e2			// clear
+	.word	0x000802e2			// clear
 	.word	0x0405d11d			// set
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index fd79807..658001b 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -7,6 +7,7 @@
 generic-y       += emergency-restart.h
 generic-y	+= exec.h
 generic-y       += futex.h
+generic-y	+= preempt.h
 generic-y       += irq_regs.h
 generic-y	+= param.h
 generic-y       += local.h
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index f78c9a2..74314bd 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -52,6 +52,9 @@
 config ZONE_DMA
 	def_bool y
 
+config GENERIC_GPIO
+	def_bool y
+
 config FORCE_MAX_ZONEORDER
 	int
 	default "14"
@@ -317,6 +320,14 @@
 	depends on (BF531 || BF532 || BF533 || BF534 || BF536 || BF537)
 	default y
 
+config GPIO_ADI
+	def_bool y
+	depends on (BF51x || BF52x || BF53x || BF538 || BF539 || BF561)
+
+config PINCTRL
+	def_bool y
+	depends on BF54x || BF60x
+
 config MEM_MT48LC64M4A2FB_7E
 	bool
 	depends on (BFIN533_STAMP)
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 127826f..f2b4347 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -44,3 +44,4 @@
 generic-y += unaligned.h
 generic-y += user.h
 generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h
index 98d0133..99d338c 100644
--- a/arch/blackfin/include/asm/gpio.h
+++ b/arch/blackfin/include/asm/gpio.h
@@ -25,8 +25,12 @@
 
 #ifndef __ASSEMBLY__
 
+#ifndef CONFIG_PINCTRL
+
 #include <linux/compiler.h>
-#include <linux/gpio.h>
+#include <asm/blackfin.h>
+#include <asm/portmux.h>
+#include <asm/irq_handler.h>
 
 /***********************************************************
 *
@@ -45,7 +49,6 @@
 * MODIFICATION HISTORY :
 **************************************************************/
 
-#if !BFIN_GPIO_PINT
 void set_gpio_dir(unsigned, unsigned short);
 void set_gpio_inen(unsigned, unsigned short);
 void set_gpio_polar(unsigned, unsigned short);
@@ -115,7 +118,6 @@
 	unsigned short dummy16;
 	unsigned short inen;
 };
-#endif
 
 #ifdef BFIN_SPECIAL_GPIO_BANKS
 void bfin_special_gpio_free(unsigned gpio);
@@ -127,25 +129,21 @@
 #endif
 
 #ifdef CONFIG_PM
-int bfin_pm_standby_ctrl(unsigned ctrl);
+void bfin_gpio_pm_hibernate_restore(void);
+void bfin_gpio_pm_hibernate_suspend(void);
+int bfin_gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl);
+int bfin_gpio_pm_standby_ctrl(unsigned ctrl);
 
 static inline int bfin_pm_standby_setup(void)
 {
-	return bfin_pm_standby_ctrl(1);
+	return bfin_gpio_pm_standby_ctrl(1);
 }
 
 static inline void bfin_pm_standby_restore(void)
 {
-	bfin_pm_standby_ctrl(0);
+	bfin_gpio_pm_standby_ctrl(0);
 }
 
-void bfin_gpio_pm_hibernate_restore(void);
-void bfin_gpio_pm_hibernate_suspend(void);
-void bfin_pint_suspend(void);
-void bfin_pint_resume(void);
-
-# if !BFIN_GPIO_PINT
-int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl);
 
 struct gpio_port_s {
 	unsigned short data;
@@ -161,7 +159,6 @@
 	unsigned short reserved;
 	unsigned short mux;
 };
-# endif
 #endif /*CONFIG_PM*/
 
 /***********************************************************
@@ -178,36 +175,29 @@
 *************************************************************
 * MODIFICATION HISTORY :
 **************************************************************/
-
-int bfin_gpio_request(unsigned gpio, const char *label);
-void bfin_gpio_free(unsigned gpio);
 int bfin_gpio_irq_request(unsigned gpio, const char *label);
 void bfin_gpio_irq_free(unsigned gpio);
-int bfin_gpio_direction_input(unsigned gpio);
-int bfin_gpio_direction_output(unsigned gpio, int value);
-int bfin_gpio_get_value(unsigned gpio);
-void bfin_gpio_set_value(unsigned gpio, int value);
+void bfin_gpio_irq_prepare(unsigned gpio);
+
+static inline int irq_to_gpio(unsigned irq)
+{
+	return irq - GPIO_IRQ_BASE;
+}
+#endif /* CONFIG_PINCTRL */
 
 #include <asm/irq.h>
 #include <asm/errno.h>
 
-#ifdef CONFIG_GPIOLIB
 #include <asm-generic/gpio.h>		/* cansleep wrappers */
 
 static inline int gpio_get_value(unsigned int gpio)
 {
-	if (gpio < MAX_BLACKFIN_GPIOS)
-		return bfin_gpio_get_value(gpio);
-	else
-		return __gpio_get_value(gpio);
+	return __gpio_get_value(gpio);
 }
 
 static inline void gpio_set_value(unsigned int gpio, int value)
 {
-	if (gpio < MAX_BLACKFIN_GPIOS)
-		bfin_gpio_set_value(gpio, value);
-	else
-		__gpio_set_value(gpio, value);
+	__gpio_set_value(gpio, value);
 }
 
 static inline int gpio_cansleep(unsigned int gpio)
@@ -219,113 +209,6 @@
 {
 	return __gpio_to_irq(gpio);
 }
-
-#else /* !CONFIG_GPIOLIB */
-
-static inline int gpio_request(unsigned gpio, const char *label)
-{
-	return bfin_gpio_request(gpio, label);
-}
-
-static inline void gpio_free(unsigned gpio)
-{
-	return bfin_gpio_free(gpio);
-}
-
-static inline int gpio_direction_input(unsigned gpio)
-{
-	return bfin_gpio_direction_input(gpio);
-}
-
-static inline int gpio_direction_output(unsigned gpio, int value)
-{
-	return bfin_gpio_direction_output(gpio, value);
-}
-
-static inline int gpio_set_debounce(unsigned gpio, unsigned debounce)
-{
-	return -EINVAL;
-}
-
-static inline int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
-{
-	int err;
-
-	err = bfin_gpio_request(gpio, label);
-	if (err)
-		return err;
-
-	if (flags & GPIOF_DIR_IN)
-		err = bfin_gpio_direction_input(gpio);
-	else
-		err = bfin_gpio_direction_output(gpio,
-			(flags & GPIOF_INIT_HIGH) ? 1 : 0);
-
-	if (err)
-		bfin_gpio_free(gpio);
-
-	return err;
-}
-
-static inline int gpio_request_array(const struct gpio *array, size_t num)
-{
-	int i, err;
-
-	for (i = 0; i < num; i++, array++) {
-		err = gpio_request_one(array->gpio, array->flags, array->label);
-		if (err)
-			goto err_free;
-	}
-	return 0;
-
-err_free:
-	while (i--)
-		bfin_gpio_free((--array)->gpio);
-	return err;
-}
-
-static inline void gpio_free_array(const struct gpio *array, size_t num)
-{
-	while (num--)
-		bfin_gpio_free((array++)->gpio);
-}
-
-static inline int __gpio_get_value(unsigned gpio)
-{
-	return bfin_gpio_get_value(gpio);
-}
-
-static inline void __gpio_set_value(unsigned gpio, int value)
-{
-	return bfin_gpio_set_value(gpio, value);
-}
-
-static inline int gpio_get_value(unsigned gpio)
-{
-	return __gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-	return __gpio_set_value(gpio, value);
-}
-
-static inline int gpio_to_irq(unsigned gpio)
-{
-	if (likely(gpio < MAX_BLACKFIN_GPIOS))
-		return gpio + GPIO_IRQ_BASE;
-
-	return -EINVAL;
-}
-
-#include <asm-generic/gpio.h>		/* cansleep wrappers */
-#endif	/* !CONFIG_GPIOLIB */
-
-static inline int irq_to_gpio(unsigned irq)
-{
-	return (irq - GPIO_IRQ_BASE);
-}
-
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ARCH_BLACKFIN_GPIO_H__ */
diff --git a/arch/blackfin/include/asm/portmux.h b/arch/blackfin/include/asm/portmux.h
index 9b1e2c3..7aa2043 100644
--- a/arch/blackfin/include/asm/portmux.h
+++ b/arch/blackfin/include/asm/portmux.h
@@ -17,14 +17,29 @@
 #define P_MAYSHARE	0x2000
 #define P_DONTCARE	0x1000
 
+#ifdef CONFIG_PINCTRL
+#include <asm/irq_handler.h>
 
+#define gpio_pint_regs bfin_pint_regs
+#define adi_internal_set_wake bfin_internal_set_wake
+
+#define peripheral_request(per, label) 0
+#define peripheral_free(per)
+#define peripheral_request_list(per, label) \
+	(pdev ? (IS_ERR(devm_pinctrl_get_select_default(&pdev->dev)) \
+	? -EINVAL : 0) : 0)
+#define peripheral_free_list(per)
+#else
 int peripheral_request(unsigned short per, const char *label);
 void peripheral_free(unsigned short per);
 int peripheral_request_list(const unsigned short per[], const char *label);
 void peripheral_free_list(const unsigned short per[]);
+#endif
 
-#include <asm/gpio.h>
+#include <linux/err.h>
+#include <linux/pinctrl/pinctrl.h>
 #include <mach/portmux.h>
+#include <linux/gpio.h>
 
 #ifndef P_SPORT2_TFS
 #define P_SPORT2_TFS P_UNDEF
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index 735f24e..703dc7c 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -7,7 +7,7 @@
 obj-y := \
 	entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \
 	sys_bfin.o traps.o irqchip.o dma-mapping.o flat.o \
-	fixed_code.o reboot.o bfin_gpio.o bfin_dma.o \
+	fixed_code.o reboot.o bfin_dma.o \
 	exception.o dumpstack.o
 
 ifeq ($(CONFIG_GENERIC_CLOCKEVENTS),y)
@@ -16,6 +16,7 @@
     obj-y += time.o
 endif
 
+obj-$(CONFIG_GPIO_ADI)               += bfin_gpio.o
 obj-$(CONFIG_DYNAMIC_FTRACE)         += ftrace.o
 obj-$(CONFIG_FUNCTION_TRACER)        += ftrace-entry.o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER)  += ftrace.o
diff --git a/arch/blackfin/mach-bf548/include/mach/portmux.h b/arch/blackfin/mach-bf548/include/mach/portmux.h
index e222462..d9f8632 100644
--- a/arch/blackfin/mach-bf548/include/mach/portmux.h
+++ b/arch/blackfin/mach-bf548/include/mach/portmux.h
@@ -7,8 +7,6 @@
 #ifndef _MACH_PORTMUX_H_
 #define _MACH_PORTMUX_H_
 
-#define MAX_RESOURCES	MAX_BLACKFIN_GPIOS
-
 #define P_SPORT2_TFS	(P_DEFINED | P_IDENT(GPIO_PA0) | P_FUNCT(0))
 #define P_SPORT2_DTSEC	(P_DEFINED | P_IDENT(GPIO_PA1) | P_FUNCT(0))
 #define P_SPORT2_DTPRI	(P_DEFINED | P_IDENT(GPIO_PA2) | P_FUNCT(0))
diff --git a/arch/blackfin/mach-bf609/include/mach/portmux.h b/arch/blackfin/mach-bf609/include/mach/portmux.h
index 2e1a51c..fe34191 100644
--- a/arch/blackfin/mach-bf609/include/mach/portmux.h
+++ b/arch/blackfin/mach-bf609/include/mach/portmux.h
@@ -7,8 +7,6 @@
 #ifndef _MACH_PORTMUX_H_
 #define _MACH_PORTMUX_H_
 
-#define MAX_RESOURCES	MAX_BLACKFIN_GPIOS
-
 /* EMAC RMII Port Mux */
 #define P_MII0_MDC	(P_DEFINED | P_IDENT(GPIO_PC6) | P_FUNCT(0))
 #define P_MII0_MDIO	(P_DEFINED | P_IDENT(GPIO_PC7) | P_FUNCT(0))
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index e49f918..fc0b3c3 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -56,3 +56,4 @@
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/c6x/include/asm/prom.h b/arch/c6x/include/asm/prom.h
deleted file mode 100644
index b4ec95f..0000000
--- a/arch/c6x/include/asm/prom.h
+++ /dev/null
@@ -1 +0,0 @@
-/* dummy prom.h; here to make linux/of.h's #includes happy */
diff --git a/arch/c6x/include/asm/setup.h b/arch/c6x/include/asm/setup.h
index ecead15..6968044 100644
--- a/arch/c6x/include/asm/setup.h
+++ b/arch/c6x/include/asm/setup.h
@@ -14,8 +14,6 @@
 #include <uapi/asm/setup.h>
 
 #ifndef __ASSEMBLY__
-extern char c6x_command_line[COMMAND_LINE_SIZE];
-
 extern int c6x_add_memory(phys_addr_t start, unsigned long size);
 
 extern unsigned long ram_start;
diff --git a/arch/c6x/kernel/devicetree.c b/arch/c6x/kernel/devicetree.c
index 9e15ab9..fa3e574 100644
--- a/arch/c6x/kernel/devicetree.c
+++ b/arch/c6x/kernel/devicetree.c
@@ -10,37 +10,8 @@
  *
  */
 #include <linux/init.h>
-#include <linux/of.h>
-#include <linux/of_fdt.h>
-#include <linux/initrd.h>
 #include <linux/memblock.h>
 
-void __init early_init_devtree(void *params)
-{
-	/* Setup flat device-tree pointer */
-	initial_boot_params = params;
-
-	/* Retrieve various informations from the /chosen node of the
-	 * device-tree, including the platform type, initrd location and
-	 * size and more ...
-	 */
-	of_scan_flat_dt(early_init_dt_scan_chosen, c6x_command_line);
-
-	/* Scan memory nodes and rebuild MEMBLOCKs */
-	of_scan_flat_dt(early_init_dt_scan_root, NULL);
-	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
-}
-
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
-{
-	initrd_start = (unsigned long)__va(start);
-	initrd_end = (unsigned long)__va(end);
-	initrd_below_start_ok = 1;
-}
-#endif
-
 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
 {
 	c6x_add_memory(base, size);
diff --git a/arch/c6x/kernel/setup.c b/arch/c6x/kernel/setup.c
index f4e72bd..731db4b 100644
--- a/arch/c6x/kernel/setup.c
+++ b/arch/c6x/kernel/setup.c
@@ -68,13 +68,6 @@
 static unsigned long dma_start __initdata;
 static unsigned long dma_size __initdata;
 
-char c6x_command_line[COMMAND_LINE_SIZE];
-
-#if defined(CONFIG_CMDLINE_BOOL)
-static const char default_command_line[COMMAND_LINE_SIZE] __section(.cmdline) =
-	CONFIG_CMDLINE;
-#endif
-
 struct cpuinfo_c6x {
 	const char *cpu_name;
 	const char *cpu_voltage;
@@ -294,10 +287,8 @@
 		fdt = dtb;
 
 	/* Do some early initialization based on the flat device tree */
-	early_init_devtree(fdt);
+	early_init_dt_scan(fdt);
 
-	/* parse_early_param needs a boot_command_line */
-	strlcpy(boot_command_line, c6x_command_line, COMMAND_LINE_SIZE);
 	parse_early_param();
 }
 
@@ -309,7 +300,7 @@
 	printk(KERN_INFO "Initializing kernel\n");
 
 	/* Initialize command line */
-	*cmdline_p = c6x_command_line;
+	*cmdline_p = boot_command_line;
 
 	memory_end = ram_end;
 	memory_end &= ~(PAGE_SIZE - 1);
diff --git a/arch/c6x/kernel/vmlinux.lds.S b/arch/c6x/kernel/vmlinux.lds.S
index 279d807..5a6e141 100644
--- a/arch/c6x/kernel/vmlinux.lds.S
+++ b/arch/c6x/kernel/vmlinux.lds.S
@@ -37,12 +37,6 @@
 		_vectors_end = .;
 	}
 
-	. = ALIGN(0x1000);
-	.cmdline :
-	{
-		*(.cmdline)
-	}
-
 	/*
 	 * This section contains data which may be shared with other
 	 * cores. It needs to be a fixed offset from PAGE_OFFSET
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index c832545..b06caf6 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -11,3 +11,4 @@
 generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index c5d7670..74742dc 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -2,3 +2,4 @@
 generic-y += clkdev.h
 generic-y += exec.h
 generic-y += trace_clock.h
+generic-y += preempt.h
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
deleted file mode 100644
index 24b1dc2..0000000
--- a/arch/h8300/Kconfig
+++ /dev/null
@@ -1,108 +0,0 @@
-config H8300
-	bool
-	default y
-	select HAVE_IDE
-	select GENERIC_ATOMIC64
-	select HAVE_UID16
-	select VIRT_TO_BUS
-	select ARCH_WANT_IPC_PARSE_VERSION
-	select GENERIC_IRQ_SHOW
-	select GENERIC_CPU_DEVICES
-	select MODULES_USE_ELF_RELA
-	select OLD_SIGSUSPEND3
-	select OLD_SIGACTION
-	select HAVE_UNDERSCORE_SYMBOL_PREFIX
-
-config MMU
-	bool
-	default n
-
-config SWAP
-	bool
-	default n
-
-config ZONE_DMA
-	bool
-	default y
-
-config FPU
-	bool
-	default n
-
-config RWSEM_GENERIC_SPINLOCK
-	bool
-	default y
-
-config RWSEM_XCHGADD_ALGORITHM
-	bool
-	default n
-
-config ARCH_HAS_ILOG2_U32
-	bool
-	default n
-
-config ARCH_HAS_ILOG2_U64
-	bool
-	default n
-
-config GENERIC_HWEIGHT
-	bool
-	default y
-
-config GENERIC_CALIBRATE_DELAY
-	bool
-	default y
-
-config GENERIC_BUG
-        bool
-        depends on BUG
-
-config TIME_LOW_RES
-	bool
-	default y
-
-config NO_IOPORT
-	def_bool y
-
-config NO_DMA
-	def_bool y
-
-config ISA
-	bool
-	default y
-
-config PCI
-	bool
-	default n
-
-config HZ
-	int
-	default 100
-
-source "init/Kconfig"
-
-source "kernel/Kconfig.freezer"
-
-source "arch/h8300/Kconfig.cpu"
-
-menu "Executable file formats"
-
-source "fs/Kconfig.binfmt"
-
-endmenu
-
-source "net/Kconfig"
-
-source "drivers/Kconfig"
-
-source "arch/h8300/Kconfig.ide"
-
-source "fs/Kconfig"
-
-source "arch/h8300/Kconfig.debug"
-
-source "security/Kconfig"
-
-source "crypto/Kconfig"
-
-source "lib/Kconfig"
diff --git a/arch/h8300/Kconfig.cpu b/arch/h8300/Kconfig.cpu
deleted file mode 100644
index cdee771..0000000
--- a/arch/h8300/Kconfig.cpu
+++ /dev/null
@@ -1,171 +0,0 @@
-menu "Processor type and features"
-
-choice
-	prompt "H8/300 platform"
-	default H8300H_GENERIC
-
-config H8300H_GENERIC
-	bool "H8/300H Generic"
-	help
-	  H8/300H CPU Generic Hardware Support
-
-config H8300H_AKI3068NET
-	bool "AE-3068/69"
-	select H83068
-	help
-	  AKI-H8/3068F / AKI-H8/3069F Flashmicom LAN Board Support
-	  More Information. (Japanese Only)
-	  <http://akizukidenshi.com/catalog/default.aspx>
-	  AE-3068/69 Evaluation Board Support
-	  More Information.
-	  <http://www.microtronique.com/ae3069lan.htm>
-
-config H8300H_H8MAX
-	bool "H8MAX"
-	select H83068
-	help
-	  H8MAX Evaluation Board Support
-	  More Information. (Japanese Only)
-	  <http://strawberry-linux.com/h8/index.html>
-
-config H8300H_SIM
-	bool "H8/300H Simulator"
-	select H83007
-	help
-	  GDB Simulator Support
-	  More Information.
-	  <http://sourceware.org/sid/>
-
-config H8S_GENERIC
-	bool "H8S Generic"
-	help
-	  H8S CPU Generic Hardware Support
-
-config H8S_EDOSK2674
-	bool "EDOSK-2674"
-	select H8S2678
-	help
-	  Renesas EDOSK-2674 Evaluation Board Support
-	  More Information.
-	  <http://www.azpower.com/H8-uClinux/index.html>
- 	  <http://www.renesas.eu/products/tools/introductory_evaluation_tools/evaluation_development_os_kits/edosk2674r/edosk2674r_software_tools_root.jsp>
-
-config H8S_SIM
-	bool "H8S Simulator"
-	help
-	  GDB Simulator Support
-	  More Information.
-	  <http://sourceware.org/sid/>
-
-endchoice
-
-choice
-	prompt "CPU Selection"
-
-config H83002
-	bool "H8/3001,3002,3003"
-	depends on BROKEN
-	select CPU_H8300H
-
-config H83007
-	bool "H8/3006,3007"
-	select CPU_H8300H
-
-config H83048
-	bool "H8/3044,3045,3046,3047,3048,3052"
-	depends on BROKEN
-	select CPU_H8300H
-
-config H83068
-	bool "H8/3065,3066,3067,3068,3069"
-	select CPU_H8300H
-
-config H8S2678
-	bool "H8S/2670,2673,2674R,2675,2676"
-	select CPU_H8S
-
-endchoice
-
-config CPU_CLOCK
-	int "CPU Clock Frequency (/1KHz)"
-	default "20000"
-	help
-	  CPU Clock Frequency divide to 1000
-
-choice
-	prompt "Kernel executes from"
-	---help---
-	  Choose the memory type that the kernel will be running in.
-
-config RAMKERNEL
-	bool "RAM"
-	help
-	  The kernel will be resident in RAM when running.
-
-config ROMKERNEL
-	bool "ROM"
-	help
-	  The kernel will be resident in FLASH/ROM when running.
-endchoice
-
-
-config CPU_H8300H
-	bool
-	depends on (H83002 || H83007 || H83048 || H83068)
-	default y
-
-config CPU_H8S
-	bool
-	depends on H8S2678
-	default y
-
-choice
-	prompt "Timer"
-config H8300_TIMER8
-	bool "8bit timer (2ch cascade)"
-	depends on (H83007 || H83068 || H8S2678)
-
-config H8300_TIMER16
-	bool "16bit timer"
-	depends on (H83007 || H83068)
-
-config H8300_ITU
-	bool "ITU"
-	depends on (H83002 || H83048)
-
-config H8300_TPU
-	bool "TPU"
-	depends on H8S2678
-endchoice
-
-if H8300_TIMER8
-choice
-	prompt "Timer Channel"
-config H8300_TIMER8_CH0
-	bool "Channel 0"
-config H8300_TIMER8_CH2
-	bool "Channel 2"
-	depends on CPU_H8300H
-endchoice
-endif
-
-config H8300_TIMER16_CH
-	int "16bit timer channel (0 - 2)"
-	depends on H8300_TIMER16
-	range 0 2
-
-config H8300_ITU_CH
-	int "ITU channel"
-	depends on H8300_ITU
-	range 0 4
-
-config H8300_TPU_CH
-	int "TPU channel"
-	depends on H8300_TPU
-	range 0 4
-
-source "kernel/Kconfig.preempt"
-
-source "mm/Kconfig"
-
-endmenu
diff --git a/arch/h8300/Kconfig.debug b/arch/h8300/Kconfig.debug
deleted file mode 100644
index e8d1b23..0000000
--- a/arch/h8300/Kconfig.debug
+++ /dev/null
@@ -1,68 +0,0 @@
-menu "Kernel hacking"
-
-source "lib/Kconfig.debug"
-
-config FULLDEBUG
-	bool "Full Symbolic/Source Debugging support"
-	help
-	  Enable debugging symbols on kernel build.
-
-config HIGHPROFILE
-	bool "Use fast second timer for profiling"
-	help
-	  Use a fast secondary clock to produce profiling information.
-
-config NO_KERNEL_MSG
-	bool "Suppress Kernel BUG Messages"
-	help
-	  Do not output any debug BUG messages within the kernel.
-
-config GDB_MAGICPRINT
-	bool "Message Output for GDB MagicPrint service"
-	depends on (H8300H_SIM || H8S_SIM)
-	help
-	  kernel messages output using MagicPrint service from GDB
-
-config SYSCALL_PRINT
-	bool "SystemCall trace print"
-	help
-	  output history of systemcall
-
-config GDB_DEBUG
-   	bool "Use gdb stub"
-	depends on (!H8300H_SIM && !H8S_SIM)
-	help
-	  gdb stub exception support
-
-config SH_STANDARD_BIOS
-	bool "Use gdb protocol serial console"
-	depends on (!H8300H_SIM && !H8S_SIM)
-	help
-	  serial console output using GDB protocol.
-	  Require eCos/RedBoot
-
-config DEFAULT_CMDLINE
-	bool "Use builtin commandline"
-	default n
-	help
-	  builtin kernel commandline enabled.
-
-config KERNEL_COMMAND
-	string "Buildin command string"
-	depends on DEFAULT_CMDLINE
-	help
-	  builtin kernel commandline strings.
-
-config BLKDEV_RESERVE
-	bool "BLKDEV Reserved Memory"
-	default n
-	help
-	  Reserved BLKDEV area.
-
-config BLKDEV_RESERVE_ADDRESS
-	hex 'start address'
-	depends on BLKDEV_RESERVE
-	help
-	  BLKDEV start address.
-
-endmenu
diff --git a/arch/h8300/Kconfig.ide b/arch/h8300/Kconfig.ide
deleted file mode 100644
index a38a630..0000000
--- a/arch/h8300/Kconfig.ide
+++ /dev/null
@@ -1,44 +0,0 @@
-# uClinux H8/300 Target Board Selection Menu (IDE)
-
-if (H8300H_AKI3068NET)
-menu "IDE Extra configuration"
-
-config H8300_IDE_BASE
-	hex "IDE register base address"
-	depends on IDE
-	default 0
-	help
-	  IDE registers base address
-
-config H8300_IDE_ALT
-	hex "IDE register alternate address"
-	depends on IDE
-	default 0
-	help
-	  IDE alternate registers address
-
-config H8300_IDE_IRQ
-	int "IDE IRQ no"
-	depends on IDE
-	default 0
-	help
-	  IDE use IRQ no
-endmenu
-endif
-
-if (H8300H_H8MAX)
-config H8300_IDE_BASE
-	hex
-	depends on IDE
-	default 0x200000
-
-config H8300_IDE_ALT
-	hex
-	depends on IDE
-	default 0x60000c
-
-config H8300_IDE_IRQ
-	int
-	depends on IDE
-	default 5
-endif
diff --git a/arch/h8300/Makefile b/arch/h8300/Makefile
deleted file mode 100644
index a556447..0000000
--- a/arch/h8300/Makefile
+++ /dev/null
@@ -1,71 +0,0 @@
-#
-# arch/h8300/Makefile
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License.  See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# (C) Copyright 2002,2003 Yoshinori Sato <ysato@users.sourceforge.jp>
-#
-
-platform-$(CONFIG_CPU_H8300H)	:= h8300h
-platform-$(CONFIG_CPU_H8S)	:= h8s
-PLATFORM := $(platform-y)
-
-board-$(CONFIG_H8300H_GENERIC)		:= generic
-board-$(CONFIG_H8300H_AKI3068NET)	:= aki3068net
-board-$(CONFIG_H8300H_H8MAX)		:= h8max
-board-$(CONFIG_H8300H_SIM)		:= generic
-board-$(CONFIG_H8S_GENERIC)		:= generic
-board-$(CONFIG_H8S_EDOSK2674)		:= edosk2674
-board-$(CONFIG_H8S_SIM)			:= generic
-BOARD := $(board-y)
-
-model-$(CONFIG_RAMKERNEL)	:= ram
-model-$(CONFIG_ROMKERNEL)	:= rom
-MODEL := $(model-y)
-
-cflags-$(CONFIG_CPU_H8300H)	:= -mh
-ldflags-$(CONFIG_CPU_H8300H)	:= -mh8300helf
-cflags-$(CONFIG_CPU_H8S)	:= -ms
-ldflags-$(CONFIG_CPU_H8S)	:= -mh8300self
-
-KBUILD_CFLAGS += $(cflags-y)
-KBUILD_CFLAGS += -mint32 -fno-builtin
-KBUILD_CFLAGS += -g
-KBUILD_CFLAGS += -D__linux__
-KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
-KBUILD_AFLAGS += -DPLATFORM=$(PLATFORM) -DMODEL=$(MODEL) $(cflags-y)
-LDFLAGS += $(ldflags-y)
-
-CROSS_COMPILE = h8300-elf-
-LIBGCC := $(shell $(CROSS-COMPILE)$(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
-
-head-y := arch/$(ARCH)/platform/$(PLATFORM)/$(BOARD)/crt0_$(MODEL).o
-
-core-y	+= arch/$(ARCH)/kernel/ \
-	   arch/$(ARCH)/mm/
-ifdef PLATFORM
-core-y	+= arch/$(ARCH)/platform/$(PLATFORM)/ \
-	   arch/$(ARCH)/platform/$(PLATFORM)/$(BOARD)/
-endif
-
-libs-y	+= arch/$(ARCH)/lib/ $(LIBGCC)
-
-boot := arch/h8300/boot
-
-export MODEL PLATFORM BOARD
-
-archmrproper:
-
-archclean:
-	$(Q)$(MAKE) $(clean)=$(boot)
-
-vmlinux.srec vmlinux.bin zImage: vmlinux
-	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
-
-define archhelp
-  @echo  'vmlinux.bin  - Create raw binary'
-  @echo  'vmlinux.srec - Create srec binary'
-  @echo  'zImage       - Compressed kernel image'
-endef
diff --git a/arch/h8300/README b/arch/h8300/README
deleted file mode 100644
index efa805f..0000000
--- a/arch/h8300/README
+++ /dev/null
@@ -1,38 +0,0 @@
-linux-2.6 for H8/300 README
-Yoshinori Sato <ysato@users.sourceforge.jp>
-
-* Supported CPU
-H8/300H and H8S
-
-* Supported Target
-1.simulator of GDB
-  require patches.
-
-2.AE 3068/AE 3069
-  more information 
-  MICROTRONIQUE <http://www.microtronique.com/>
-  Akizuki Denshi Tsusho Ltd. <http://akizukidenshi.com/> (Japanese Only)
-
-3.H8MAX 
-  see http://ip-sol.jp/h8max/ (Japanese Only)
-
-4.EDOSK2674
-  see http://www.eu.renesas.com/products/mpumcu/tool/edk/support/edosk2674.html
-      http://www.uclinux.org/pub/uClinux/ports/h8/HITACHI-EDOSK2674-HOWTO
-      http://www.azpower.com/H8-uClinux/
-
-* Toolchain Version
-gcc-3.1 or higher and patch
-see arch/h8300/tools_patch/README
-binutils-2.12 or higher
-gdb-5.2 or higher
-The environment that can compile a h8300-elf binary is necessary.
-
-* Userland Develop environment
-used h8300-elf toolchains.
-see http://www.uclinux.org/pub/uClinux/ports/h8/
-
-* A few words of thanks
-Porting to H8/300 serieses is support of Information-technology Promotion Agency, Japan.
-I thank support.
-and All developer/user.
diff --git a/arch/h8300/boot/Makefile b/arch/h8300/boot/Makefile
deleted file mode 100644
index 0bb62e0..0000000
--- a/arch/h8300/boot/Makefile
+++ /dev/null
@@ -1,22 +0,0 @@
-# arch/h8300/boot/Makefile
-
-targets := vmlinux.srec vmlinux.bin zImage
-subdir- := compressed
-
-OBJCOPYFLAGS_vmlinux.srec := -Osrec
-OBJCOPYFLAGS_vmlinux.bin  := -Obinary
-OBJCOPYFLAGS_zImage := -O binary -R .note -R .comment -R .stab -R .stabstr -S
-
-$(obj)/vmlinux.srec $(obj)/vmlinux.bin:  vmlinux FORCE
-	$(call if_changed,objcopy)
-	@echo '  Kernel: $@ is ready'
-
-$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
-	$(call if_changed,objcopy)
-	@echo 'Kernel: $@ is ready'
-
-$(obj)/compressed/vmlinux: FORCE
-	$(Q)$(MAKE) $(build)=$(obj)/compressed $@
-
-CLEAN_FILES += arch/$(ARCH)/vmlinux.bin arch/$(ARCH)/vmlinux.srec
-
diff --git a/arch/h8300/boot/compressed/Makefile b/arch/h8300/boot/compressed/Makefile
deleted file mode 100644
index a6c98fe..0000000
--- a/arch/h8300/boot/compressed/Makefile
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# linux/arch/sh/boot/compressed/Makefile
-#
-# create a compressed vmlinux image from the original vmlinux
-#
-
-targets		:= vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
-asflags-y	:= -traditional
-
-OBJECTS = $(obj)/head.o $(obj)/misc.o
-
-#
-# IMAGE_OFFSET is the load offset of the compression loader
-# Assign dummy values if these 2 variables are not defined,
-# in order to suppress error message.
-#
-CONFIG_MEMORY_START     ?= 0x00400000
-CONFIG_BOOT_LINK_OFFSET ?= 0x00140000
-IMAGE_OFFSET := $(shell printf "0x%08x" $$(($(CONFIG_MEMORY_START)+$(CONFIG_BOOT_LINK_OFFSET))))
-
-LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -estartup $(obj)/vmlinux.lds
-
-$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
-	$(call if_changed,ld)
-	@:
-
-$(obj)/vmlinux.bin: vmlinux FORCE
-	$(call if_changed,objcopy)
-
-$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
-	$(call if_changed,gzip)
-
-LDFLAGS_piggy.o := -r --format binary --oformat elf32-h8300 -T
-OBJCOPYFLAGS := -O binary
-
-$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
-	$(call if_changed,ld)
diff --git a/arch/h8300/boot/compressed/head.S b/arch/h8300/boot/compressed/head.S
deleted file mode 100644
index 10e9a2d..0000000
--- a/arch/h8300/boot/compressed/head.S
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- *  linux/arch/h8300/boot/compressed/head.S
- *
- *  Copyright (C) 2006 Yoshinori Sato
- */
-
-	.h8300h
-#include <linux/linkage.h>
-
-#define SRAM_START 0xff4000
-
-	.section	.text..startup
-	.global	startup
-startup:
-	mov.l	#SRAM_START+0x8000, sp
-	mov.l	#__sbss, er0
-	mov.l	#__ebss, er1
-	sub.l	er0, er1
-	shlr	er1
-	shlr	er1
-	sub.l	er2, er2
-1:
-	mov.l	er2, @er0
-	adds	#4, er0
-	dec.l	#1, er1
-	bne	1b
-	jsr	@_decompress_kernel
-	jmp	@0x400000
-
-	.align	9
-fake_headers_as_bzImage:
-	.word	0
-	.ascii	"HdrS"		; header signature
-	.word	0x0202		; header version number (>= 0x0105)
-				; or else old loadlin-1.5 will fail)
-	.word	0		; default_switch
-	.word	0		; SETUPSEG
-	.word	0x1000
-	.word	0		; pointing to kernel version string
-	.byte	0		; = 0, old one (LILO, Loadlin,
-				; 0xTV: T=0 for LILO
-				;       V = version
-	.byte	1		; Load flags bzImage=1
-	.word	0x8000		; size to move, when setup is not
-	.long	0x100000	; 0x100000 = default for big kernel
-	.long	0		; address of loaded ramdisk image
-	.long	0		; its size in bytes
diff --git a/arch/h8300/boot/compressed/misc.c b/arch/h8300/boot/compressed/misc.c
deleted file mode 100644
index 4a1e3dd..0000000
--- a/arch/h8300/boot/compressed/misc.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * arch/h8300/boot/compressed/misc.c
- *
- * This is a collection of several routines from gzip-1.0.3
- * adapted for Linux.
- *
- * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
- *
- * Adapted for h8300 by Yoshinori Sato 2006
- */
-
-#include <asm/uaccess.h>
-
-/*
- * gzip declarations
- */
-
-#define OF(args)  args
-#define STATIC static
-
-#undef memset
-#undef memcpy
-#define memzero(s, n)     memset ((s), 0, (n))
-
-typedef unsigned char  uch;
-typedef unsigned short ush;
-typedef unsigned long  ulg;
-
-#define WSIZE 0x8000		/* Window size must be at least 32k, */
-				/* and a power of two */
-
-static uch *inbuf;	     /* input buffer */
-static uch window[WSIZE];    /* Sliding window buffer */
-
-static unsigned insize = 0;  /* valid bytes in inbuf */
-static unsigned inptr = 0;   /* index of next byte to be processed in inbuf */
-static unsigned outcnt = 0;  /* bytes in output buffer */
-
-/* gzip flag byte */
-#define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
-#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
-#define COMMENT      0x10 /* bit 4 set: file comment present */
-#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
-#define RESERVED     0xC0 /* bit 6,7:   reserved */
-
-#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
-
-/* Diagnostic functions */
-#ifdef DEBUG
-#  define Assert(cond,msg) {if(!(cond)) error(msg);}
-#  define Trace(x) fprintf x
-#  define Tracev(x) {if (verbose) fprintf x ;}
-#  define Tracevv(x) {if (verbose>1) fprintf x ;}
-#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
-#else
-#  define Assert(cond,msg)
-#  define Trace(x)
-#  define Tracev(x)
-#  define Tracevv(x)
-#  define Tracec(c,x)
-#  define Tracecv(c,x)
-#endif
-
-static int  fill_inbuf(void);
-static void flush_window(void);
-static void error(char *m);
-
-extern char input_data[];
-extern int input_len;
-
-static long bytes_out = 0;
-static uch *output_data;
-static unsigned long output_ptr = 0;
-
-static void error(char *m);
-
-int puts(const char *);
-
-extern int _end;
-static unsigned long free_mem_ptr;
-static unsigned long free_mem_end_ptr;
-
-#define HEAP_SIZE             0x10000
-
-#include "../../../../lib/inflate.c"
-
-#define SCR *((volatile unsigned char *)0xffff8a)
-#define TDR *((volatile unsigned char *)0xffff8b)
-#define SSR *((volatile unsigned char *)0xffff8c)
-
-int puts(const char *s)
-{
-	return 0;
-}
-
-void* memset(void* s, int c, size_t n)
-{
-	int i;
-	char *ss = (char*)s;
-
-	for (i=0;i<n;i++) ss[i] = c;
-	return s;
-}
-
-void* memcpy(void* __dest, __const void* __src,
-			    size_t __n)
-{
-	int i;
-	char *d = (char *)__dest, *s = (char *)__src;
-
-	for (i=0;i<__n;i++) d[i] = s[i];
-	return __dest;
-}
-
-/* ===========================================================================
- * Fill the input buffer. This is called only when the buffer is empty
- * and at least one byte is really needed.
- */
-static int fill_inbuf(void)
-{
-	if (insize != 0) {
-		error("ran out of input data");
-	}
-
-	inbuf = input_data;
-	insize = input_len;
-	inptr = 1;
-	return inbuf[0];
-}
-
-/* ===========================================================================
- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
- * (Used for the decompressed data only.)
- */
-static void flush_window(void)
-{
-    ulg c = crc;         /* temporary variable */
-    unsigned n;
-    uch *in, *out, ch;
-
-    in = window;
-    out = &output_data[output_ptr];
-    for (n = 0; n < outcnt; n++) {
-	    ch = *out++ = *in++;
-	    c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
-    }
-    crc = c;
-    bytes_out += (ulg)outcnt;
-    output_ptr += (ulg)outcnt;
-    outcnt = 0;
-}
-
-static void error(char *x)
-{
-	puts("\n\n");
-	puts(x);
-	puts("\n\n -- System halted");
-
-	while(1);	/* Halt */
-}
-
-#define STACK_SIZE (4096)
-long user_stack [STACK_SIZE];
-long* stack_start = &user_stack[STACK_SIZE];
-
-void decompress_kernel(void)
-{
-	output_data = 0;
-	output_ptr = (unsigned long)0x400000;
-	free_mem_ptr = (unsigned long)&_end;
-	free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
-
-	makecrc();
-	puts("Uncompressing Linux... ");
-	gunzip();
-	puts("Ok, booting the kernel.\n");
-}
diff --git a/arch/h8300/boot/compressed/vmlinux.lds b/arch/h8300/boot/compressed/vmlinux.lds
deleted file mode 100644
index a0a3a0e..0000000
--- a/arch/h8300/boot/compressed/vmlinux.lds
+++ /dev/null
@@ -1,32 +0,0 @@
-SECTIONS
-{
-        .text :
-        {
-        __stext = . ;
-	__text = .;
-	       *(.text..startup)
-	       *(.text)
-        __etext = . ;
-        }
-
-	.rodata :
-	{
-		*(.rodata)
-	}
-        .data :
-
-        {
-        __sdata = . ;
-        ___data_start = . ;
-                *(.data.*)
-	}
-        .bss :
-        {
-        . = ALIGN(0x4) ;
-        __sbss = . ;
-                *(.bss*)
-        . = ALIGN(0x4) ;
-        __ebss = . ;
-        __end = . ;
-        }
-}
diff --git a/arch/h8300/boot/compressed/vmlinux.scr b/arch/h8300/boot/compressed/vmlinux.scr
deleted file mode 100644
index a0f6962..0000000
--- a/arch/h8300/boot/compressed/vmlinux.scr
+++ /dev/null
@@ -1,9 +0,0 @@
-SECTIONS
-{
-  .data : {
-	_input_len = .;
-	LONG(_input_data_end - _input_data) _input_data = .;
-	*(.data)
-	_input_data_end = .;
-	}
-}
diff --git a/arch/h8300/defconfig b/arch/h8300/defconfig
deleted file mode 100644
index 042425a..0000000
--- a/arch/h8300/defconfig
+++ /dev/null
@@ -1,42 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EXPERT=y
-# CONFIG_UID16 is not set
-# CONFIG_SYSCTL_SYSCALL is not set
-# CONFIG_KALLSYMS is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_BASE_FULL is not set
-# CONFIG_FUTEX is not set
-# CONFIG_EPOLL is not set
-# CONFIG_SIGNALFD is not set
-# CONFIG_TIMERFD is not set
-# CONFIG_EVENTFD is not set
-# CONFIG_VM_EVENT_COUNTERS is not set
-# CONFIG_COMPAT_BRK is not set
-CONFIG_SLOB=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_H83007=y
-CONFIG_BINFMT_FLAT=y
-CONFIG_BINFMT_ZFLAT=y
-CONFIG_BINFMT_MISC=y
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_RAM=y
-CONFIG_MTD_ROM=y
-CONFIG_MTD_UCLINUX=y
-# CONFIG_BLK_DEV is not set
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_HWMON is not set
-# CONFIG_USB_SUPPORT is not set
-# CONFIG_DNOTIFY is not set
-CONFIG_ROMFS_FS=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-# CONFIG_CRC32 is not set
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
deleted file mode 100644
index 8ada3cf..0000000
--- a/arch/h8300/include/asm/Kbuild
+++ /dev/null
@@ -1,8 +0,0 @@
-
-generic-y += clkdev.h
-generic-y += exec.h
-generic-y += linkage.h
-generic-y += mmu.h
-generic-y += module.h
-generic-y += trace_clock.h
-generic-y += xor.h
diff --git a/arch/h8300/include/asm/asm-offsets.h b/arch/h8300/include/asm/asm-offsets.h
deleted file mode 100644
index d370ee3..0000000
--- a/arch/h8300/include/asm/asm-offsets.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <generated/asm-offsets.h>
diff --git a/arch/h8300/include/asm/atomic.h b/arch/h8300/include/asm/atomic.h
deleted file mode 100644
index 40901e3..0000000
--- a/arch/h8300/include/asm/atomic.h
+++ /dev/null
@@ -1,146 +0,0 @@
-#ifndef __ARCH_H8300_ATOMIC__
-#define __ARCH_H8300_ATOMIC__
-
-#include <linux/types.h>
-#include <asm/cmpxchg.h>
-
-/*
- * Atomic operations that C can't guarantee us.  Useful for
- * resource counting etc..
- */
-
-#define ATOMIC_INIT(i)	{ (i) }
-
-#define atomic_read(v)		(*(volatile int *)&(v)->counter)
-#define atomic_set(v, i)	(((v)->counter) = i)
-
-#include <linux/kernel.h>
-
-static __inline__ int atomic_add_return(int i, atomic_t *v)
-{
-	unsigned long flags;
-	int ret;
-	local_irq_save(flags);
-	ret = v->counter += i;
-	local_irq_restore(flags);
-	return ret;
-}
-
-#define atomic_add(i, v) atomic_add_return(i, v)
-#define atomic_add_negative(a, v)	(atomic_add_return((a), (v)) < 0)
-
-static __inline__ int atomic_sub_return(int i, atomic_t *v)
-{
-	unsigned long flags;
-	int ret;
-	local_irq_save(flags);
-	ret = v->counter -= i;
-	local_irq_restore(flags);
-	return ret;
-}
-
-#define atomic_sub(i, v) atomic_sub_return(i, v)
-#define atomic_sub_and_test(i,v) (atomic_sub_return(i, v) == 0)
-
-static __inline__ int atomic_inc_return(atomic_t *v)
-{
-	unsigned long flags;
-	int ret;
-	local_irq_save(flags);
-	v->counter++;
-	ret = v->counter;
-	local_irq_restore(flags);
-	return ret;
-}
-
-#define atomic_inc(v) atomic_inc_return(v)
-
-/*
- * atomic_inc_and_test - increment and test
- * @v: pointer of type atomic_t
- *
- * Atomically increments @v by 1
- * and returns true if the result is zero, or false for all
- * other cases.
- */
-#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
-
-static __inline__ int atomic_dec_return(atomic_t *v)
-{
-	unsigned long flags;
-	int ret;
-	local_irq_save(flags);
-	--v->counter;
-	ret = v->counter;
-	local_irq_restore(flags);
-	return ret;
-}
-
-#define atomic_dec(v) atomic_dec_return(v)
-
-static __inline__ int atomic_dec_and_test(atomic_t *v)
-{
-	unsigned long flags;
-	int ret;
-	local_irq_save(flags);
-	--v->counter;
-	ret = v->counter;
-	local_irq_restore(flags);
-	return ret == 0;
-}
-
-static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
-{
-	int ret;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	ret = v->counter;
-	if (likely(ret == old))
-		v->counter = new;
-	local_irq_restore(flags);
-	return ret;
-}
-
-static inline int __atomic_add_unless(atomic_t *v, int a, int u)
-{
-	int ret;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	ret = v->counter;
-	if (ret != u)
-		v->counter += a;
-	local_irq_restore(flags);
-	return ret;
-}
-
-static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *v)
-{
-	__asm__ __volatile__("stc ccr,r1l\n\t"
-	                     "orc #0x80,ccr\n\t"
-	                     "mov.l %0,er0\n\t"
-	                     "and.l %1,er0\n\t"
-	                     "mov.l er0,%0\n\t"
-	                     "ldc r1l,ccr" 
-                             : "=m" (*v) : "g" (~(mask)) :"er0","er1");
-}
-
-static __inline__ void atomic_set_mask(unsigned long mask, unsigned long *v)
-{
-	__asm__ __volatile__("stc ccr,r1l\n\t"
-	                     "orc #0x80,ccr\n\t"
-	                     "mov.l %0,er0\n\t"
-	                     "or.l %1,er0\n\t"
-	                     "mov.l er0,%0\n\t"
-	                     "ldc r1l,ccr" 
-                             : "=m" (*v) : "g" (mask) :"er0","er1");
-}
-
-/* Atomic operations are already serializing */
-#define smp_mb__before_atomic_dec()    barrier()
-#define smp_mb__after_atomic_dec() barrier()
-#define smp_mb__before_atomic_inc()    barrier()
-#define smp_mb__after_atomic_inc() barrier()
-
-#endif /* __ARCH_H8300_ATOMIC __ */
diff --git a/arch/h8300/include/asm/barrier.h b/arch/h8300/include/asm/barrier.h
deleted file mode 100644
index 9e0aa9f..0000000
--- a/arch/h8300/include/asm/barrier.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef _H8300_BARRIER_H
-#define _H8300_BARRIER_H
-
-#define nop()  asm volatile ("nop"::)
-
-/*
- * Force strict CPU ordering.
- * Not really required on H8...
- */
-#define mb()   asm volatile (""   : : :"memory")
-#define rmb()  asm volatile (""   : : :"memory")
-#define wmb()  asm volatile (""   : : :"memory")
-#define set_mb(var, value) do { xchg(&var, value); } while (0)
-
-#define read_barrier_depends()	do { } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb()	mb()
-#define smp_rmb()	rmb()
-#define smp_wmb()	wmb()
-#define smp_read_barrier_depends()	read_barrier_depends()
-#else
-#define smp_mb()	barrier()
-#define smp_rmb()	barrier()
-#define smp_wmb()	barrier()
-#define smp_read_barrier_depends()	do { } while(0)
-#endif
-
-#endif /* _H8300_BARRIER_H */
diff --git a/arch/h8300/include/asm/bitops.h b/arch/h8300/include/asm/bitops.h
deleted file mode 100644
index eb34e0c..0000000
--- a/arch/h8300/include/asm/bitops.h
+++ /dev/null
@@ -1,211 +0,0 @@
-#ifndef _H8300_BITOPS_H
-#define _H8300_BITOPS_H
-
-/*
- * Copyright 1992, Linus Torvalds.
- * Copyright 2002, Yoshinori Sato
- */
-
-#include <linux/compiler.h>
-
-#ifdef __KERNEL__
-
-#ifndef _LINUX_BITOPS_H
-#error only <linux/bitops.h> can be included directly
-#endif
-
-/*
- * Function prototypes to keep gcc -Wall happy
- */
-
-/*
- * ffz = Find First Zero in word. Undefined if no zero exists,
- * so code should check against ~0UL first..
- */
-static __inline__ unsigned long ffz(unsigned long word)
-{
-	unsigned long result;
-
-	result = -1;
-	__asm__("1:\n\t"
-		"shlr.l %2\n\t"
-		"adds #1,%0\n\t"
-		"bcs 1b"
-		: "=r" (result)
-		: "0"  (result),"r" (word));
-	return result;
-}
-
-#define H8300_GEN_BITOP_CONST(OP,BIT)			    \
-	case BIT:					    \
-	__asm__(OP " #" #BIT ",@%0"::"r"(b_addr):"memory"); \
-	break;
-
-#define H8300_GEN_BITOP(FNAME,OP)				      \
-static __inline__ void FNAME(int nr, volatile unsigned long* addr)    \
-{								      \
-	volatile unsigned char *b_addr;				      \
-	b_addr = (volatile unsigned char *)addr + ((nr >> 3) ^ 3);    \
-	if (__builtin_constant_p(nr)) {				      \
-		switch(nr & 7) {				      \
-			H8300_GEN_BITOP_CONST(OP,0)		      \
-			H8300_GEN_BITOP_CONST(OP,1)		      \
-			H8300_GEN_BITOP_CONST(OP,2)		      \
-			H8300_GEN_BITOP_CONST(OP,3)		      \
-			H8300_GEN_BITOP_CONST(OP,4)		      \
-			H8300_GEN_BITOP_CONST(OP,5)		      \
-			H8300_GEN_BITOP_CONST(OP,6)		      \
-			H8300_GEN_BITOP_CONST(OP,7)		      \
-		}						      \
-	} else {						      \
-		__asm__(OP " %w0,@%1"::"r"(nr),"r"(b_addr):"memory"); \
-	}							      \
-}
-
-/*
- * clear_bit() doesn't provide any barrier for the compiler.
- */
-#define smp_mb__before_clear_bit()	barrier()
-#define smp_mb__after_clear_bit()	barrier()
-
-H8300_GEN_BITOP(set_bit	  ,"bset")
-H8300_GEN_BITOP(clear_bit ,"bclr")
-H8300_GEN_BITOP(change_bit,"bnot")
-#define __set_bit(nr,addr)    set_bit((nr),(addr))
-#define __clear_bit(nr,addr)  clear_bit((nr),(addr))
-#define __change_bit(nr,addr) change_bit((nr),(addr))
-
-#undef H8300_GEN_BITOP
-#undef H8300_GEN_BITOP_CONST
-
-static __inline__ int test_bit(int nr, const unsigned long* addr)
-{
-	return (*((volatile unsigned char *)addr + 
-               ((nr >> 3) ^ 3)) & (1UL << (nr & 7))) != 0;
-}
-
-#define __test_bit(nr, addr) test_bit(nr, addr)
-
-#define H8300_GEN_TEST_BITOP_CONST_INT(OP,BIT)			     \
-	case BIT:						     \
-	__asm__("stc ccr,%w1\n\t"				     \
-		"orc #0x80,ccr\n\t"				     \
-		"bld #" #BIT ",@%4\n\t"				     \
-		OP " #" #BIT ",@%4\n\t"				     \
-		"rotxl.l %0\n\t"				     \
-		"ldc %w1,ccr"					     \
-		: "=r"(retval),"=&r"(ccrsave),"=m"(*b_addr)	     \
-		: "0" (retval),"r" (b_addr)			     \
-		: "memory");                                         \
-        break;
-
-#define H8300_GEN_TEST_BITOP_CONST(OP,BIT)			     \
-	case BIT:						     \
-	__asm__("bld #" #BIT ",@%3\n\t"				     \
-		OP " #" #BIT ",@%3\n\t"				     \
-		"rotxl.l %0\n\t"				     \
-		: "=r"(retval),"=m"(*b_addr)			     \
-		: "0" (retval),"r" (b_addr)			     \
-		: "memory");                                         \
-        break;
-
-#define H8300_GEN_TEST_BITOP(FNNAME,OP)				     \
-static __inline__ int FNNAME(int nr, volatile void * addr)	     \
-{								     \
-	int retval = 0;						     \
-	char ccrsave;						     \
-	volatile unsigned char *b_addr;				     \
-	b_addr = (volatile unsigned char *)addr + ((nr >> 3) ^ 3);   \
-	if (__builtin_constant_p(nr)) {				     \
-		switch(nr & 7) {				     \
-			H8300_GEN_TEST_BITOP_CONST_INT(OP,0)	     \
-			H8300_GEN_TEST_BITOP_CONST_INT(OP,1)	     \
-			H8300_GEN_TEST_BITOP_CONST_INT(OP,2)	     \
-			H8300_GEN_TEST_BITOP_CONST_INT(OP,3)	     \
-			H8300_GEN_TEST_BITOP_CONST_INT(OP,4)	     \
-			H8300_GEN_TEST_BITOP_CONST_INT(OP,5)	     \
-			H8300_GEN_TEST_BITOP_CONST_INT(OP,6)	     \
-			H8300_GEN_TEST_BITOP_CONST_INT(OP,7)	     \
-		}						     \
-	} else {						     \
-		__asm__("stc ccr,%w1\n\t"			     \
-			"orc #0x80,ccr\n\t"			     \
-			"btst %w5,@%4\n\t"			     \
-			OP " %w5,@%4\n\t"			     \
-			"beq 1f\n\t"				     \
-			"inc.l #1,%0\n"				     \
-			"1:\n\t"				     \
-			"ldc %w1,ccr"				     \
-			: "=r"(retval),"=&r"(ccrsave),"=m"(*b_addr)  \
-			: "0" (retval),"r" (b_addr),"r"(nr)	     \
-			: "memory");				     \
-	}							     \
-	return retval;						     \
-}								     \
-								     \
-static __inline__ int __ ## FNNAME(int nr, volatile void * addr)     \
-{								     \
-	int retval = 0;						     \
-	volatile unsigned char *b_addr;				     \
-	b_addr = (volatile unsigned char *)addr + ((nr >> 3) ^ 3);   \
-	if (__builtin_constant_p(nr)) {				     \
-		switch(nr & 7) {				     \
-			H8300_GEN_TEST_BITOP_CONST(OP,0) 	     \
-			H8300_GEN_TEST_BITOP_CONST(OP,1) 	     \
-			H8300_GEN_TEST_BITOP_CONST(OP,2) 	     \
-			H8300_GEN_TEST_BITOP_CONST(OP,3) 	     \
-			H8300_GEN_TEST_BITOP_CONST(OP,4) 	     \
-			H8300_GEN_TEST_BITOP_CONST(OP,5) 	     \
-			H8300_GEN_TEST_BITOP_CONST(OP,6) 	     \
-			H8300_GEN_TEST_BITOP_CONST(OP,7) 	     \
-		}						     \
-	} else {						     \
-		__asm__("btst %w4,@%3\n\t"			     \
-			OP " %w4,@%3\n\t"			     \
-			"beq 1f\n\t"				     \
-			"inc.l #1,%0\n"				     \
-			"1:"					     \
-			: "=r"(retval),"=m"(*b_addr)		     \
-			: "0" (retval),"r" (b_addr),"r"(nr)	     \
-			: "memory");				     \
-	}							     \
-	return retval;						     \
-}
-
-H8300_GEN_TEST_BITOP(test_and_set_bit,	 "bset")
-H8300_GEN_TEST_BITOP(test_and_clear_bit, "bclr")
-H8300_GEN_TEST_BITOP(test_and_change_bit,"bnot")
-#undef H8300_GEN_TEST_BITOP_CONST
-#undef H8300_GEN_TEST_BITOP_CONST_INT
-#undef H8300_GEN_TEST_BITOP
-
-#include <asm-generic/bitops/ffs.h>
-
-static __inline__ unsigned long __ffs(unsigned long word)
-{
-	unsigned long result;
-
-	result = -1;
-	__asm__("1:\n\t"
-		"shlr.l %2\n\t"
-		"adds #1,%0\n\t"
-		"bcc 1b"
-		: "=r" (result)
-		: "0"(result),"r"(word));
-	return result;
-}
-
-#include <asm-generic/bitops/find.h>
-#include <asm-generic/bitops/sched.h>
-#include <asm-generic/bitops/hweight.h>
-#include <asm-generic/bitops/lock.h>
-#include <asm-generic/bitops/le.h>
-#include <asm-generic/bitops/ext2-atomic.h>
-
-#endif /* __KERNEL__ */
-
-#include <asm-generic/bitops/fls.h>
-#include <asm-generic/bitops/__fls.h>
-#include <asm-generic/bitops/fls64.h>
-
-#endif /* _H8300_BITOPS_H */
diff --git a/arch/h8300/include/asm/bootinfo.h b/arch/h8300/include/asm/bootinfo.h
deleted file mode 100644
index 5bed7e7..0000000
--- a/arch/h8300/include/asm/bootinfo.h
+++ /dev/null
@@ -1,2 +0,0 @@
-
-/* Nothing for h8300 */
diff --git a/arch/h8300/include/asm/bug.h b/arch/h8300/include/asm/bug.h
deleted file mode 100644
index 1e1be81..0000000
--- a/arch/h8300/include/asm/bug.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _H8300_BUG_H
-#define _H8300_BUG_H
-
-/* always true */
-#define is_valid_bugaddr(addr) (1)
-
-#include <asm-generic/bug.h>
-
-struct pt_regs;
-extern void die(const char *str, struct pt_regs *fp, unsigned long err);
-
-#endif
diff --git a/arch/h8300/include/asm/bugs.h b/arch/h8300/include/asm/bugs.h
deleted file mode 100644
index 1cb4afb..0000000
--- a/arch/h8300/include/asm/bugs.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- *  include/asm-h8300/bugs.h
- *
- *  Copyright (C) 1994  Linus Torvalds
- */
-
-/*
- * This is included by init/main.c to check for architecture-dependent bugs.
- *
- * Needs:
- *	void check_bugs(void);
- */
-
-static void check_bugs(void)
-{
-}
diff --git a/arch/h8300/include/asm/cache.h b/arch/h8300/include/asm/cache.h
deleted file mode 100644
index 05887a1..0000000
--- a/arch/h8300/include/asm/cache.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ARCH_H8300_CACHE_H
-#define __ARCH_H8300_CACHE_H
-
-/* bytes per L1 cache line */
-#define        L1_CACHE_SHIFT  2
-#define        L1_CACHE_BYTES  (1 << L1_CACHE_SHIFT)
-
-/* m68k-elf-gcc  2.95.2 doesn't like these */
-
-#define __cacheline_aligned
-#define ____cacheline_aligned
-
-#endif
diff --git a/arch/h8300/include/asm/cachectl.h b/arch/h8300/include/asm/cachectl.h
deleted file mode 100644
index c464022..0000000
--- a/arch/h8300/include/asm/cachectl.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _H8300_CACHECTL_H
-#define _H8300_CACHECTL_H
-
-/* Definitions for the cacheflush system call.  */
-
-#define FLUSH_SCOPE_LINE    0	/* Flush a cache line */
-#define FLUSH_SCOPE_PAGE    0	/* Flush a page */
-#define FLUSH_SCOPE_ALL     0	/* Flush the whole cache -- superuser only */
-
-#define FLUSH_CACHE_DATA    0	/* Writeback and flush data cache */
-#define FLUSH_CACHE_INSN    0	/* Flush instruction cache */
-#define FLUSH_CACHE_BOTH    0	/* Flush both caches */
-
-#endif /* _H8300_CACHECTL_H */
diff --git a/arch/h8300/include/asm/cacheflush.h b/arch/h8300/include/asm/cacheflush.h
deleted file mode 100644
index 4cf2df2..0000000
--- a/arch/h8300/include/asm/cacheflush.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * (C) Copyright 2002, Yoshinori Sato <ysato@users.sourceforge.jp>
- */
-
-#ifndef _ASM_H8300_CACHEFLUSH_H
-#define _ASM_H8300_CACHEFLUSH_H
-
-/*
- * Cache handling functions
- * No Cache memory all dummy functions
- */
-
-#define flush_cache_all()
-#define	flush_cache_mm(mm)
-#define	flush_cache_dup_mm(mm)		do { } while (0)
-#define	flush_cache_range(vma,a,b)
-#define	flush_cache_page(vma,p,pfn)
-#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
-#define	flush_dcache_page(page)
-#define	flush_dcache_mmap_lock(mapping)
-#define	flush_dcache_mmap_unlock(mapping)
-#define	flush_icache()
-#define	flush_icache_page(vma,page)
-#define	flush_icache_range(start,len)
-#define flush_cache_vmap(start, end)
-#define flush_cache_vunmap(start, end)
-#define	cache_push_v(vaddr,len)
-#define	cache_push(paddr,len)
-#define	cache_clear(paddr,len)
-
-#define	flush_dcache_range(a,b)
-
-#define	flush_icache_user_range(vma,page,addr,len)
-
-#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
-#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
-
-#endif /* _ASM_H8300_CACHEFLUSH_H */
diff --git a/arch/h8300/include/asm/checksum.h b/arch/h8300/include/asm/checksum.h
deleted file mode 100644
index 98724e1..0000000
--- a/arch/h8300/include/asm/checksum.h
+++ /dev/null
@@ -1,102 +0,0 @@
-#ifndef _H8300_CHECKSUM_H
-#define _H8300_CHECKSUM_H
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-__wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- * the same as csum_partial, but copies from src while it
- * checksums
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum);
-
-
-/*
- * the same as csum_partial_copy, but copies from user space.
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
-						int len, __wsum sum, int *csum_err);
-
-__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
-
-
-/*
- *	Fold a partial checksum
- */
-
-static inline __sum16 csum_fold(__wsum sum)
-{
-	__asm__("mov.l %0,er0\n\t"
-		"add.w e0,r0\n\t"
-		"xor.w e0,e0\n\t"
-		"rotxl.w e0\n\t"
-		"add.w e0,r0\n\t"
-		"sub.w e0,e0\n\t"
-		"mov.l er0,%0"
-		: "=r"(sum)
-		: "0"(sum)
-		: "er0");
-	return (__force __sum16)~sum;
-}
-
-
-/*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-
-static inline __wsum
-csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
-		  unsigned short proto, __wsum sum)
-{
-	__asm__ ("sub.l er0,er0\n\t"
-		 "add.l %2,%0\n\t"
-		 "addx	#0,r0l\n\t"
-		 "add.l	%3,%0\n\t"
-		 "addx	#0,r0l\n\t"
-		 "add.l %4,%0\n\t"
-		 "addx	#0,r0l\n\t"
-		 "add.l	er0,%0\n\t"
-		 "bcc	1f\n\t"
-		 "inc.l	#1,%0\n"
-		 "1:"
-		 : "=&r" (sum)
-		 : "0" (sum), "r" (daddr), "r" (saddr), "r" (len + proto)
-		 :"er0");
-	return sum;
-}
-
-static inline __sum16
-csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
-		  unsigned short proto, __wsum sum)
-{
-	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
-}
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-
-extern __sum16 ip_compute_csum(const void *buff, int len);
-
-#endif /* _H8300_CHECKSUM_H */
diff --git a/arch/h8300/include/asm/cmpxchg.h b/arch/h8300/include/asm/cmpxchg.h
deleted file mode 100644
index cdb203e..0000000
--- a/arch/h8300/include/asm/cmpxchg.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef __ARCH_H8300_CMPXCHG__
-#define __ARCH_H8300_CMPXCHG__
-
-#include <linux/irqflags.h>
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-struct __xchg_dummy { unsigned long a[100]; };
-#define __xg(x) ((volatile struct __xchg_dummy *)(x))
-
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
-{
-  unsigned long tmp, flags;
-
-  local_irq_save(flags);
-
-  switch (size) {
-  case 1:
-    __asm__ __volatile__
-    ("mov.b %2,%0\n\t"
-     "mov.b %1,%2"
-    : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
-    break;
-  case 2:
-    __asm__ __volatile__
-    ("mov.w %2,%0\n\t"
-     "mov.w %1,%2"
-    : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
-    break;
-  case 4:
-    __asm__ __volatile__
-    ("mov.l %2,%0\n\t"
-     "mov.l %1,%2"
-    : "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)) : "memory");
-    break;
-  default:
-    tmp = 0;	  
-  }
-  local_irq_restore(flags);
-  return tmp;
-}
-
-#include <asm-generic/cmpxchg-local.h>
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)				  	       \
-	((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-			(unsigned long)(n), sizeof(*(ptr))))
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
-#ifndef CONFIG_SMP
-#include <asm-generic/cmpxchg.h>
-#endif
-
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
-#endif /* __ARCH_H8300_CMPXCHG__ */
diff --git a/arch/h8300/include/asm/cputime.h b/arch/h8300/include/asm/cputime.h
deleted file mode 100644
index 092e187..0000000
--- a/arch/h8300/include/asm/cputime.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __H8300_CPUTIME_H
-#define __H8300_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __H8300_CPUTIME_H */
diff --git a/arch/h8300/include/asm/current.h b/arch/h8300/include/asm/current.h
deleted file mode 100644
index 57d74ee..0000000
--- a/arch/h8300/include/asm/current.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef _H8300_CURRENT_H
-#define _H8300_CURRENT_H
-/*
- *	current.h
- *	(C) Copyright 2000, Lineo, David McCullough <davidm@lineo.com>
- *	(C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
- *
- *	rather than dedicate a register (as the m68k source does), we
- *	just keep a global,  we should probably just change it all to be
- *	current and lose _current_task.
- */
-
-#include <linux/thread_info.h>
-#include <asm/thread_info.h>
-
-struct task_struct;
-
-static inline struct task_struct *get_current(void)
-{
-	return(current_thread_info()->task);
-}
-
-#define	current	get_current()
-
-#endif /* _H8300_CURRENT_H */
diff --git a/arch/h8300/include/asm/dbg.h b/arch/h8300/include/asm/dbg.h
deleted file mode 100644
index 2c6d1cb..0000000
--- a/arch/h8300/include/asm/dbg.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#define DEBUG 1
-#define	BREAK asm volatile ("trap #3")
diff --git a/arch/h8300/include/asm/delay.h b/arch/h8300/include/asm/delay.h
deleted file mode 100644
index 743beba..0000000
--- a/arch/h8300/include/asm/delay.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef _H8300_DELAY_H
-#define _H8300_DELAY_H
-
-#include <asm/param.h>
-
-/*
- * Copyright (C) 2002 Yoshinori Sato <ysato@sourceforge.jp>
- *
- * Delay routines, using a pre-computed "loops_per_second" value.
- */
-
-static inline void __delay(unsigned long loops)
-{
-	__asm__ __volatile__ ("1:\n\t"
-			      "dec.l #1,%0\n\t"
-			      "bne 1b"
-			      :"=r" (loops):"0"(loops));
-}
-
-/*
- * Use only for very small delays ( < 1 msec).  Should probably use a
- * lookup table, really, as the multiplications take much too long with
- * short delays.  This is a "reasonable" implementation, though (and the
- * first constant multiplications gets optimized away if the delay is
- * a constant)  
- */
-
-extern unsigned long loops_per_jiffy;
-
-static inline void udelay(unsigned long usecs)
-{
-	usecs *= 4295;		/* 2**32 / 1000000 */
-	usecs /= (loops_per_jiffy*HZ);
-	if (usecs)
-		__delay(usecs);
-}
-
-#endif /* _H8300_DELAY_H */
diff --git a/arch/h8300/include/asm/device.h b/arch/h8300/include/asm/device.h
deleted file mode 100644
index d8f9872..0000000
--- a/arch/h8300/include/asm/device.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Arch specific extensions to struct device
- *
- * This file is released under the GPLv2
- */
-#include <asm-generic/device.h>
-
diff --git a/arch/h8300/include/asm/div64.h b/arch/h8300/include/asm/div64.h
deleted file mode 100644
index 6cd978c..0000000
--- a/arch/h8300/include/asm/div64.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/div64.h>
diff --git a/arch/h8300/include/asm/dma.h b/arch/h8300/include/asm/dma.h
deleted file mode 100644
index 3edbaaa..0000000
--- a/arch/h8300/include/asm/dma.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef _H8300_DMA_H
-#define _H8300_DMA_H 
- 
-
-/*
- * Set number of channels of DMA on ColdFire for different implementations.
- */
-#define MAX_DMA_CHANNELS 0
-#define MAX_DMA_ADDRESS PAGE_OFFSET
-
-/* These are in kernel/dma.c: */
-extern int request_dma(unsigned int dmanr, const char *device_id);	/* reserve a DMA channel */
-extern void free_dma(unsigned int dmanr);	/* release it again */
- 
-#endif /* _H8300_DMA_H */
diff --git a/arch/h8300/include/asm/elf.h b/arch/h8300/include/asm/elf.h
deleted file mode 100644
index 6db7124..0000000
--- a/arch/h8300/include/asm/elf.h
+++ /dev/null
@@ -1,101 +0,0 @@
-#ifndef __ASMH8300_ELF_H
-#define __ASMH8300_ELF_H
-
-/*
- * ELF register definitions..
- */
-
-#include <asm/ptrace.h>
-#include <asm/user.h>
-
-typedef unsigned long elf_greg_t;
-
-#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-typedef unsigned long elf_fpregset_t;
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x) ((x)->e_machine == EM_H8_300)
-
-/*
- * These are used to set parameters in the core dumps.
- */
-#define ELF_CLASS	ELFCLASS32
-#define ELF_DATA	ELFDATA2MSB
-#define ELF_ARCH	EM_H8_300
-#if defined(__H8300H__)
-#define ELF_CORE_EFLAGS 0x810000
-#endif
-#if defined(__H8300S__)
-#define ELF_CORE_EFLAGS 0x820000
-#endif
-
-#define ELF_PLAT_INIT(_r)	_r->er1 = 0
-
-#define ELF_EXEC_PAGESIZE	4096
-
-/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
-   use of this is to invoke "./ld.so someprog" to test out a new version of
-   the loader.  We need to make sure that it is out of the way of the program
-   that it will "exec", and that there is sufficient room for the brk.  */
-
-#define ELF_ET_DYN_BASE         0xD0000000UL
-
-/* This yields a mask that user programs can use to figure out what
-   instruction set this cpu supports.  */
-
-#define ELF_HWCAP	(0)
-
-/* This yields a string that ld.so will use to load implementation
-   specific libraries for optimization.  This is more specific in
-   intent than poking at uname or /proc/cpuinfo.  */
-
-#define ELF_PLATFORM  (NULL)
-
-#define R_H8_NONE       0
-#define R_H8_DIR32      1
-#define R_H8_DIR32_28   2
-#define R_H8_DIR32_24   3
-#define R_H8_DIR32_16   4
-#define R_H8_DIR32U     6
-#define R_H8_DIR32U_28  7
-#define R_H8_DIR32U_24  8
-#define R_H8_DIR32U_20  9
-#define R_H8_DIR32U_16 10
-#define R_H8_DIR24     11
-#define R_H8_DIR24_20  12
-#define R_H8_DIR24_16  13
-#define R_H8_DIR24U    14
-#define R_H8_DIR24U_20 15
-#define R_H8_DIR24U_16 16
-#define R_H8_DIR16     17
-#define R_H8_DIR16U    18
-#define R_H8_DIR16S_32 19
-#define R_H8_DIR16S_28 20
-#define R_H8_DIR16S_24 21
-#define R_H8_DIR16S_20 22
-#define R_H8_DIR16S    23
-#define R_H8_DIR8      24
-#define R_H8_DIR8U     25
-#define R_H8_DIR8Z_32  26
-#define R_H8_DIR8Z_28  27
-#define R_H8_DIR8Z_24  28
-#define R_H8_DIR8Z_20  29
-#define R_H8_DIR8Z_16  30
-#define R_H8_PCREL16   31
-#define R_H8_PCREL8    32
-#define R_H8_BPOS      33
-#define R_H8_PCREL32   34
-#define R_H8_GOT32O    35
-#define R_H8_GOT16O    36
-#define R_H8_DIR16A8   59
-#define R_H8_DIR16R8   60
-#define R_H8_DIR24A8   61
-#define R_H8_DIR24R8   62
-#define R_H8_DIR32A16  63
-#define R_H8_ABS32     65
-#define R_H8_ABS32A16 127
-
-#endif
diff --git a/arch/h8300/include/asm/emergency-restart.h b/arch/h8300/include/asm/emergency-restart.h
deleted file mode 100644
index 108d8c4..0000000
--- a/arch/h8300/include/asm/emergency-restart.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/arch/h8300/include/asm/fb.h b/arch/h8300/include/asm/fb.h
deleted file mode 100644
index c7df380..0000000
--- a/arch/h8300/include/asm/fb.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _ASM_FB_H_
-#define _ASM_FB_H_
-#include <linux/fb.h>
-
-#define fb_pgprotect(...) do {} while (0)
-
-static inline int fb_is_primary_device(struct fb_info *info)
-{
-	return 0;
-}
-
-#endif /* _ASM_FB_H_ */
diff --git a/arch/h8300/include/asm/flat.h b/arch/h8300/include/asm/flat.h
deleted file mode 100644
index bd12b31..0000000
--- a/arch/h8300/include/asm/flat.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * include/asm-h8300/flat.h -- uClinux flat-format executables
- */
-
-#ifndef __H8300_FLAT_H__
-#define __H8300_FLAT_H__
-
-#define	flat_argvp_envp_on_stack()		1
-#define	flat_old_ram_flag(flags)		1
-#define	flat_reloc_valid(reloc, size)		((reloc) <= (size))
-#define	flat_set_persistent(relval, p)		0
-
-/*
- * on the H8 a couple of the relocations have an instruction in the
- * top byte.  As there can only be 24bits of address space,  we just
- * always preserve that 8bits at the top,  when it isn't an instruction
- * is is 0 (davidm@snapgear.com)
- */
-
-#define	flat_get_relocate_addr(rel)		(rel)
-#define flat_get_addr_from_rp(rp, relval, flags, persistent) \
-        (get_unaligned(rp) & ((flags & FLAT_FLAG_GOTPIC) ? 0xffffffff: 0x00ffffff))
-#define flat_put_addr_at_rp(rp, addr, rel) \
-	put_unaligned (((*(char *)(rp)) << 24) | ((addr) & 0x00ffffff), rp)
-
-#endif /* __H8300_FLAT_H__ */
diff --git a/arch/h8300/include/asm/fpu.h b/arch/h8300/include/asm/fpu.h
deleted file mode 100644
index 4fc416e..0000000
--- a/arch/h8300/include/asm/fpu.h
+++ /dev/null
@@ -1 +0,0 @@
-/* Nothing do */
diff --git a/arch/h8300/include/asm/ftrace.h b/arch/h8300/include/asm/ftrace.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/h8300/include/asm/ftrace.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/h8300/include/asm/futex.h b/arch/h8300/include/asm/futex.h
deleted file mode 100644
index 6a332a9..0000000
--- a/arch/h8300/include/asm/futex.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
-
-#include <asm-generic/futex.h>
-
-#endif
diff --git a/arch/h8300/include/asm/gpio-internal.h b/arch/h8300/include/asm/gpio-internal.h
deleted file mode 100644
index a714f0c..0000000
--- a/arch/h8300/include/asm/gpio-internal.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef _H8300_GPIO_H
-#define _H8300_GPIO_H
-
-#define H8300_GPIO_P1 0
-#define H8300_GPIO_P2 1
-#define H8300_GPIO_P3 2
-#define H8300_GPIO_P4 3
-#define H8300_GPIO_P5 4
-#define H8300_GPIO_P6 5
-#define H8300_GPIO_P7 6
-#define H8300_GPIO_P8 7
-#define H8300_GPIO_P9 8
-#define H8300_GPIO_PA 9
-#define H8300_GPIO_PB 10
-#define H8300_GPIO_PC 11
-#define H8300_GPIO_PD 12
-#define H8300_GPIO_PE 13
-#define H8300_GPIO_PF 14
-#define H8300_GPIO_PG 15
-#define H8300_GPIO_PH 16
-
-#define H8300_GPIO_B7 0x80
-#define H8300_GPIO_B6 0x40
-#define H8300_GPIO_B5 0x20
-#define H8300_GPIO_B4 0x10
-#define H8300_GPIO_B3 0x08
-#define H8300_GPIO_B2 0x04
-#define H8300_GPIO_B1 0x02
-#define H8300_GPIO_B0 0x01
-
-#define H8300_GPIO_INPUT 0
-#define H8300_GPIO_OUTPUT 1
-
-#define H8300_GPIO_RESERVE(port, bits) \
-        h8300_reserved_gpio(port, bits)
-
-#define H8300_GPIO_FREE(port, bits) \
-        h8300_free_gpio(port, bits)
-
-#define H8300_GPIO_DDR(port, bit, dir) \
-        h8300_set_gpio_dir(((port) << 8) | (bit), dir)
-
-#define H8300_GPIO_GETDIR(port, bit) \
-        h8300_get_gpio_dir(((port) << 8) | (bit))
-
-extern int h8300_reserved_gpio(int port, int bits);
-extern int h8300_free_gpio(int port, int bits);
-extern int h8300_set_gpio_dir(int port_bit, int dir);
-extern int h8300_get_gpio_dir(int port_bit);
-extern int h8300_init_gpio(void);
-
-#endif
diff --git a/arch/h8300/include/asm/hardirq.h b/arch/h8300/include/asm/hardirq.h
deleted file mode 100644
index c2e1aa0..0000000
--- a/arch/h8300/include/asm/hardirq.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __H8300_HARDIRQ_H
-#define __H8300_HARDIRQ_H
-
-#include <asm/irq.h>
-
-#define HARDIRQ_BITS	8
-
-/*
- * The hardirq mask has to be large enough to have
- * space for potentially all IRQ sources in the system
- * nesting on a single CPU:
- */
-#if (1 << HARDIRQ_BITS) < NR_IRQS
-# error HARDIRQ_BITS is too low!
-#endif
-
-#include <asm-generic/hardirq.h>
-
-#endif
diff --git a/arch/h8300/include/asm/hw_irq.h b/arch/h8300/include/asm/hw_irq.h
deleted file mode 100644
index d75a5a1..0000000
--- a/arch/h8300/include/asm/hw_irq.h
+++ /dev/null
@@ -1 +0,0 @@
-/* Do Nothing */
diff --git a/arch/h8300/include/asm/io.h b/arch/h8300/include/asm/io.h
deleted file mode 100644
index c1a8df2..0000000
--- a/arch/h8300/include/asm/io.h
+++ /dev/null
@@ -1,358 +0,0 @@
-#ifndef _H8300_IO_H
-#define _H8300_IO_H
-
-#ifdef __KERNEL__
-
-#include <asm/virtconvert.h>
-
-#if defined(CONFIG_H83007) || defined(CONFIG_H83068)
-#include <asm/regs306x.h>
-#elif defined(CONFIG_H8S2678)
-#include <asm/regs267x.h>
-#else
-#error UNKNOWN CPU TYPE
-#endif
-
-
-/*
- * These are for ISA/PCI shared memory _only_ and should never be used
- * on any other type of memory, including Zorro memory. They are meant to
- * access the bus in the bus byte order which is little-endian!.
- *
- * readX/writeX() are used to access memory mapped devices. On some
- * architectures the memory mapped IO stuff needs to be accessed
- * differently. On the m68k architecture, we just read/write the
- * memory location directly.
- */
-/* ++roman: The assignments to temp. vars avoid that gcc sometimes generates
- * two accesses to memory, which may be undesirable for some devices.
- */
-
-/*
- * swap functions are sometimes needed to interface little-endian hardware
- */
-
-static inline unsigned short _swapw(volatile unsigned short v)
-{
-#ifndef H8300_IO_NOSWAP
-	unsigned short r;
-	__asm__("xor.b %w0,%x0\n\t"
-		"xor.b %x0,%w0\n\t"
-		"xor.b %w0,%x0"
-		:"=r"(r)
-		:"0"(v));
-	return r;
-#else
-	return v;
-#endif
-}
-
-static inline unsigned long _swapl(volatile unsigned long v)
-{
-#ifndef H8300_IO_NOSWAP
-	unsigned long r;
-	__asm__("xor.b %w0,%x0\n\t"
-		"xor.b %x0,%w0\n\t"
-		"xor.b %w0,%x0\n\t"
-		"xor.w %e0,%f0\n\t"
-		"xor.w %f0,%e0\n\t"
-		"xor.w %e0,%f0\n\t"
-		"xor.b %w0,%x0\n\t"
-		"xor.b %x0,%w0\n\t"
-		"xor.b %w0,%x0"
-		:"=r"(r)
-		:"0"(v));
-	return r;
-#else
-	return v;
-#endif
-}
-
-#define readb(addr) \
-    ({ unsigned char __v = \
-     *(volatile unsigned char *)((unsigned long)(addr) & 0x00ffffff); \
-     __v; })
-#define readw(addr) \
-    ({ unsigned short __v = \
-     *(volatile unsigned short *)((unsigned long)(addr) & 0x00ffffff); \
-     __v; })
-#define readl(addr) \
-    ({ unsigned long __v = \
-     *(volatile unsigned long *)((unsigned long)(addr) & 0x00ffffff); \
-     __v; })
-
-#define writeb(b,addr) (void)((*(volatile unsigned char *) \
-                             ((unsigned long)(addr) & 0x00ffffff)) = (b))
-#define writew(b,addr) (void)((*(volatile unsigned short *) \
-                             ((unsigned long)(addr) & 0x00ffffff)) = (b))
-#define writel(b,addr) (void)((*(volatile unsigned long *) \
-                             ((unsigned long)(addr) & 0x00ffffff)) = (b))
-#define readb_relaxed(addr) readb(addr)
-#define readw_relaxed(addr) readw(addr)
-#define readl_relaxed(addr) readl(addr)
-
-#define __raw_readb readb
-#define __raw_readw readw
-#define __raw_readl readl
-#define __raw_writeb writeb
-#define __raw_writew writew
-#define __raw_writel writel
-
-static inline int h8300_buswidth(unsigned int addr)
-{
-	return (*(volatile unsigned char *)ABWCR & (1 << ((addr >> 21) & 7))) == 0;
-}
-
-static inline void io_outsb(unsigned int addr, const void *buf, int len)
-{
-	volatile unsigned char  *ap_b = (volatile unsigned char *) addr;
-	volatile unsigned short *ap_w = (volatile unsigned short *) addr;
-	unsigned char *bp = (unsigned char *) buf;
-
-	if(h8300_buswidth(addr) && (addr & 1)) {
-		while (len--)
-			*ap_w = *bp++;
-	} else {
-		while (len--)
-			*ap_b = *bp++;
-	}
-}
-
-static inline void io_outsw(unsigned int addr, const void *buf, int len)
-{
-	volatile unsigned short *ap = (volatile unsigned short *) addr;
-	unsigned short *bp = (unsigned short *) buf;
-	while (len--)
-		*ap = _swapw(*bp++);
-}
-
-static inline void io_outsl(unsigned int addr, const void *buf, int len)
-{
-	volatile unsigned long *ap = (volatile unsigned long *) addr;
-	unsigned long *bp = (unsigned long *) buf;
-	while (len--)
-		*ap = _swapl(*bp++);
-}
-
-static inline void io_outsw_noswap(unsigned int addr, const void *buf, int len)
-{
-	volatile unsigned short *ap = (volatile unsigned short *) addr;
-	unsigned short *bp = (unsigned short *) buf;
-	while (len--)
-		*ap = *bp++;
-}
-
-static inline void io_outsl_noswap(unsigned int addr, const void *buf, int len)
-{
-	volatile unsigned long *ap = (volatile unsigned long *) addr;
-	unsigned long *bp = (unsigned long *) buf;
-	while (len--)
-		*ap = *bp++;
-}
-
-static inline void io_insb(unsigned int addr, void *buf, int len)
-{
-	volatile unsigned char  *ap_b;
-	volatile unsigned short *ap_w;
-	unsigned char *bp = (unsigned char *) buf;
-
-	if(h8300_buswidth(addr)) {
-		ap_w = (volatile unsigned short *)(addr & ~1);
-		while (len--)
-			*bp++ = *ap_w & 0xff;
-	} else {
-		ap_b = (volatile unsigned char *)addr;
-		while (len--)
-			*bp++ = *ap_b;
-	}
-}
-
-static inline void io_insw(unsigned int addr, void *buf, int len)
-{
-	volatile unsigned short *ap = (volatile unsigned short *) addr;
-	unsigned short *bp = (unsigned short *) buf;
-	while (len--)
-		*bp++ = _swapw(*ap);
-}
-
-static inline void io_insl(unsigned int addr, void *buf, int len)
-{
-	volatile unsigned long *ap = (volatile unsigned long *) addr;
-	unsigned long *bp = (unsigned long *) buf;
-	while (len--)
-		*bp++ = _swapl(*ap);
-}
-
-static inline void io_insw_noswap(unsigned int addr, void *buf, int len)
-{
-	volatile unsigned short *ap = (volatile unsigned short *) addr;
-	unsigned short *bp = (unsigned short *) buf;
-	while (len--)
-		*bp++ = *ap;
-}
-
-static inline void io_insl_noswap(unsigned int addr, void *buf, int len)
-{
-	volatile unsigned long *ap = (volatile unsigned long *) addr;
-	unsigned long *bp = (unsigned long *) buf;
-	while (len--)
-		*bp++ = *ap;
-}
-
-/*
- *	make the short names macros so specific devices
- *	can override them as required
- */
-
-#define memset_io(a,b,c)	memset((void *)(a),(b),(c))
-#define memcpy_fromio(a,b,c)	memcpy((a),(void *)(b),(c))
-#define memcpy_toio(a,b,c)	memcpy((void *)(a),(b),(c))
-
-#define mmiowb()
-
-#define inb(addr)    ((h8300_buswidth(addr))?readw((addr) & ~1) & 0xff:readb(addr))
-#define inw(addr)    _swapw(readw(addr))
-#define inl(addr)    _swapl(readl(addr))
-#define outb(x,addr) ((void)((h8300_buswidth(addr) && \
-                      ((addr) & 1))?writew(x,(addr) & ~1):writeb(x,addr)))
-#define outw(x,addr) ((void) writew(_swapw(x),addr))
-#define outl(x,addr) ((void) writel(_swapl(x),addr))
-
-#define inb_p(addr)    inb(addr)
-#define inw_p(addr)    inw(addr)
-#define inl_p(addr)    inl(addr)
-#define outb_p(x,addr) outb(x,addr)
-#define outw_p(x,addr) outw(x,addr)
-#define outl_p(x,addr) outl(x,addr)
-
-#define outsb(a,b,l) io_outsb(a,b,l)
-#define outsw(a,b,l) io_outsw(a,b,l)
-#define outsl(a,b,l) io_outsl(a,b,l)
-
-#define insb(a,b,l) io_insb(a,b,l)
-#define insw(a,b,l) io_insw(a,b,l)
-#define insl(a,b,l) io_insl(a,b,l)
-
-#define IO_SPACE_LIMIT 0xffffff
-
-
-/* Values for nocacheflag and cmode */
-#define IOMAP_FULL_CACHING		0
-#define IOMAP_NOCACHE_SER		1
-#define IOMAP_NOCACHE_NONSER		2
-#define IOMAP_WRITETHROUGH		3
-
-extern void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag);
-extern void __iounmap(void *addr, unsigned long size);
-
-static inline void *ioremap(unsigned long physaddr, unsigned long size)
-{
-	return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
-}
-static inline void *ioremap_nocache(unsigned long physaddr, unsigned long size)
-{
-	return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
-}
-static inline void *ioremap_writethrough(unsigned long physaddr, unsigned long size)
-{
-	return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
-}
-static inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size)
-{
-	return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
-}
-
-extern void iounmap(void *addr);
-
-/* H8/300 internal I/O functions */
-static __inline__ unsigned char ctrl_inb(unsigned long addr)
-{
-	return *(volatile unsigned char*)addr;
-}
-
-static __inline__ unsigned short ctrl_inw(unsigned long addr)
-{
-	return *(volatile unsigned short*)addr;
-}
-
-static __inline__ unsigned long ctrl_inl(unsigned long addr)
-{
-	return *(volatile unsigned long*)addr;
-}
-
-static __inline__ void ctrl_outb(unsigned char b, unsigned long addr)
-{
-	*(volatile unsigned char*)addr = b;
-}
-
-static __inline__ void ctrl_outw(unsigned short b, unsigned long addr)
-{
-	*(volatile unsigned short*)addr = b;
-}
-
-static __inline__ void ctrl_outl(unsigned long b, unsigned long addr)
-{
-        *(volatile unsigned long*)addr = b;
-}
-
-static __inline__ void ctrl_bclr(int b, unsigned long addr)
-{
-	if (__builtin_constant_p(b))
-		switch (b) {
-		case 0: __asm__("bclr #0,@%0"::"r"(addr)); break;
-		case 1: __asm__("bclr #1,@%0"::"r"(addr)); break;
-		case 2: __asm__("bclr #2,@%0"::"r"(addr)); break;
-		case 3: __asm__("bclr #3,@%0"::"r"(addr)); break;
-		case 4: __asm__("bclr #4,@%0"::"r"(addr)); break;
-		case 5: __asm__("bclr #5,@%0"::"r"(addr)); break;
-		case 6: __asm__("bclr #6,@%0"::"r"(addr)); break;
-		case 7: __asm__("bclr #7,@%0"::"r"(addr)); break;
-		}
-	else
-		__asm__("bclr %w0,@%1"::"r"(b), "r"(addr));
-}
-
-static __inline__ void ctrl_bset(int b, unsigned long addr)
-{
-	if (__builtin_constant_p(b))
-		switch (b) {
-		case 0: __asm__("bset #0,@%0"::"r"(addr)); break;
-		case 1: __asm__("bset #1,@%0"::"r"(addr)); break;
-		case 2: __asm__("bset #2,@%0"::"r"(addr)); break;
-		case 3: __asm__("bset #3,@%0"::"r"(addr)); break;
-		case 4: __asm__("bset #4,@%0"::"r"(addr)); break;
-		case 5: __asm__("bset #5,@%0"::"r"(addr)); break;
-		case 6: __asm__("bset #6,@%0"::"r"(addr)); break;
-		case 7: __asm__("bset #7,@%0"::"r"(addr)); break;
-		}
-	else
-		__asm__("bset %w0,@%1"::"r"(b), "r"(addr));
-}
-
-/* Pages to physical address... */
-#define page_to_phys(page)      ((page - mem_map) << PAGE_SHIFT)
-#define page_to_bus(page)       ((page - mem_map) << PAGE_SHIFT)
-
-/*
- * Macros used for converting between virtual and physical mappings.
- */
-#define phys_to_virt(vaddr)	((void *) (vaddr))
-#define virt_to_phys(vaddr)	((unsigned long) (vaddr))
-
-#define virt_to_bus virt_to_phys
-#define bus_to_virt phys_to_virt
-
-/*
- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- * access
- */
-#define xlate_dev_mem_ptr(p)	__va(p)
-
-/*
- * Convert a virtual cached pointer to an uncached pointer
- */
-#define xlate_dev_kmem_ptr(p)	p
-
-#endif /* __KERNEL__ */
-
-#endif /* _H8300_IO_H */
diff --git a/arch/h8300/include/asm/irq.h b/arch/h8300/include/asm/irq.h
deleted file mode 100644
index 13d7c60..0000000
--- a/arch/h8300/include/asm/irq.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef _H8300_IRQ_H_
-#define _H8300_IRQ_H_
-
-#include <asm/ptrace.h>
-
-#if defined(CONFIG_CPU_H8300H)
-#define NR_IRQS 64
-#define EXT_IRQ0 12
-#define EXT_IRQ1 13
-#define EXT_IRQ2 14
-#define EXT_IRQ3 15
-#define EXT_IRQ4 16
-#define EXT_IRQ5 17
-#define EXT_IRQ6 18
-#define EXT_IRQ7 19
-#define EXT_IRQS 5
-#define IER_REGS *(volatile unsigned char *)IER
-#endif
-#if defined(CONFIG_CPU_H8S)
-#define NR_IRQS 128
-#define EXT_IRQ0 16
-#define EXT_IRQ1 17
-#define EXT_IRQ2 18
-#define EXT_IRQ3 19
-#define EXT_IRQ4 20
-#define EXT_IRQ5 21
-#define EXT_IRQ6 22
-#define EXT_IRQ7 23
-#define EXT_IRQ8 24
-#define EXT_IRQ9 25
-#define EXT_IRQ10 26
-#define EXT_IRQ11 27
-#define EXT_IRQ12 28
-#define EXT_IRQ13 29
-#define EXT_IRQ14 30
-#define EXT_IRQ15 31
-#define EXT_IRQS 15
-
-#define IER_REGS *(volatile unsigned short *)IER
-#endif
-
-static __inline__ int irq_canonicalize(int irq)
-{
-	return irq;
-}
-
-typedef void (*h8300_vector)(void);
-
-#endif /* _H8300_IRQ_H_ */
diff --git a/arch/h8300/include/asm/irq_regs.h b/arch/h8300/include/asm/irq_regs.h
deleted file mode 100644
index 3dd9c0b..0000000
--- a/arch/h8300/include/asm/irq_regs.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
diff --git a/arch/h8300/include/asm/irqflags.h b/arch/h8300/include/asm/irqflags.h
deleted file mode 100644
index 9617cd5..0000000
--- a/arch/h8300/include/asm/irqflags.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef _H8300_IRQFLAGS_H
-#define _H8300_IRQFLAGS_H
-
-static inline unsigned long arch_local_save_flags(void)
-{
-	unsigned long flags;
-	asm volatile ("stc ccr,%w0" : "=r" (flags));
-	return flags;
-}
-
-static inline void arch_local_irq_disable(void)
-{
-	asm volatile ("orc  #0x80,ccr" : : : "memory");
-}
-
-static inline void arch_local_irq_enable(void)
-{
-	asm volatile ("andc #0x7f,ccr" : : : "memory");
-}
-
-static inline unsigned long arch_local_irq_save(void)
-{
-	unsigned long flags = arch_local_save_flags();
-	arch_local_irq_disable();
-	return flags;
-}
-
-static inline void arch_local_irq_restore(unsigned long flags)
-{
-	asm volatile ("ldc %w0,ccr" : : "r" (flags) : "memory");
-}
-
-static inline bool arch_irqs_disabled_flags(unsigned long flags)
-{
-	return (flags & 0x80) == 0x80;
-}
-
-static inline bool arch_irqs_disabled(void)
-{
-	return arch_irqs_disabled_flags(arch_local_save_flags());
-}
-
-#endif /* _H8300_IRQFLAGS_H */
diff --git a/arch/h8300/include/asm/kdebug.h b/arch/h8300/include/asm/kdebug.h
deleted file mode 100644
index 6ece1b0..0000000
--- a/arch/h8300/include/asm/kdebug.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kdebug.h>
diff --git a/arch/h8300/include/asm/kmap_types.h b/arch/h8300/include/asm/kmap_types.h
deleted file mode 100644
index be12a71..0000000
--- a/arch/h8300/include/asm/kmap_types.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_H8300_KMAP_TYPES_H
-#define _ASM_H8300_KMAP_TYPES_H
-
-#include <asm-generic/kmap_types.h>
-
-#endif
diff --git a/arch/h8300/include/asm/local.h b/arch/h8300/include/asm/local.h
deleted file mode 100644
index fdd4efe..0000000
--- a/arch/h8300/include/asm/local.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_LOCAL_H_
-#define _H8300_LOCAL_H_
-
-#include <asm-generic/local.h>
-
-#endif
diff --git a/arch/h8300/include/asm/local64.h b/arch/h8300/include/asm/local64.h
deleted file mode 100644
index 36c93b5..0000000
--- a/arch/h8300/include/asm/local64.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local64.h>
diff --git a/arch/h8300/include/asm/mc146818rtc.h b/arch/h8300/include/asm/mc146818rtc.h
deleted file mode 100644
index ab9d964..0000000
--- a/arch/h8300/include/asm/mc146818rtc.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Machine dependent access functions for RTC registers.
- */
-#ifndef _H8300_MC146818RTC_H
-#define _H8300_MC146818RTC_H
-
-/* empty include file to satisfy the include in genrtc.c/ide-geometry.c */
-
-#endif /* _H8300_MC146818RTC_H */
diff --git a/arch/h8300/include/asm/mmu_context.h b/arch/h8300/include/asm/mmu_context.h
deleted file mode 100644
index f44b730..0000000
--- a/arch/h8300/include/asm/mmu_context.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef __H8300_MMU_CONTEXT_H
-#define __H8300_MMU_CONTEXT_H
-
-#include <asm/setup.h>
-#include <asm/page.h>
-#include <asm/pgalloc.h>
-#include <asm-generic/mm_hooks.h>
-
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
-{
-}
-
-static inline int
-init_new_context(struct task_struct *tsk, struct mm_struct *mm)
-{
-	// mm->context = virt_to_phys(mm->pgd);
-	return(0);
-}
-
-#define destroy_context(mm)		do { } while(0)
-#define deactivate_mm(tsk,mm)           do { } while(0)
-
-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
-{
-}
-
-static inline void activate_mm(struct mm_struct *prev_mm,
-			       struct mm_struct *next_mm)
-{
-}
-
-#endif
diff --git a/arch/h8300/include/asm/mutex.h b/arch/h8300/include/asm/mutex.h
deleted file mode 100644
index 458c1f7..0000000
--- a/arch/h8300/include/asm/mutex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-
-#include <asm-generic/mutex-dec.h>
diff --git a/arch/h8300/include/asm/page.h b/arch/h8300/include/asm/page.h
deleted file mode 100644
index 837381a..0000000
--- a/arch/h8300/include/asm/page.h
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef _H8300_PAGE_H
-#define _H8300_PAGE_H
-
-/* PAGE_SHIFT determines the page size */
-
-#define PAGE_SHIFT	(12)
-#define PAGE_SIZE	(1UL << PAGE_SHIFT)
-#define PAGE_MASK	(~(PAGE_SIZE-1))
-
-#include <asm/setup.h>
-
-#ifndef __ASSEMBLY__
- 
-#define get_user_page(vaddr)		__get_free_page(GFP_KERNEL)
-#define free_user_page(page, addr)	free_page(addr)
-
-#define clear_page(page)	memset((page), 0, PAGE_SIZE)
-#define copy_page(to,from)	memcpy((to), (from), PAGE_SIZE)
-
-#define clear_user_page(page, vaddr, pg)	clear_page(page)
-#define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
-
-#define __alloc_zeroed_user_highpage(movableflags, vma, vaddr) \
-	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
-#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
-
-/*
- * These are used to make use of C type-checking..
- */
-typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long pmd[16]; } pmd_t;
-typedef struct { unsigned long pgd; } pgd_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
-typedef struct page *pgtable_t;
-
-#define pte_val(x)	((x).pte)
-#define pmd_val(x)	((&x)->pmd[0])
-#define pgd_val(x)	((x).pgd)
-#define pgprot_val(x)	((x).pgprot)
-
-#define __pte(x)	((pte_t) { (x) } )
-#define __pmd(x)	((pmd_t) { (x) } )
-#define __pgd(x)	((pgd_t) { (x) } )
-#define __pgprot(x)	((pgprot_t) { (x) } )
-
-extern unsigned long memory_start;
-extern unsigned long memory_end;
-
-#endif /* !__ASSEMBLY__ */
-
-#include <asm/page_offset.h>
-
-#define PAGE_OFFSET		(PAGE_OFFSET_RAW)
-
-#ifndef __ASSEMBLY__
-
-#define __pa(vaddr)		virt_to_phys(vaddr)
-#define __va(paddr)		phys_to_virt((unsigned long)paddr)
-
-#define virt_to_pfn(kaddr)	(__pa(kaddr) >> PAGE_SHIFT)
-#define pfn_to_virt(pfn)	__va((pfn) << PAGE_SHIFT)
-
-#define MAP_NR(addr)		(((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
-#define virt_to_page(addr)	(mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
-#define page_to_virt(page)	((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
-#define pfn_valid(page)	        (page < max_mapnr)
-
-#define ARCH_PFN_OFFSET		(PAGE_OFFSET >> PAGE_SHIFT)
-
-#define	virt_addr_valid(kaddr)	(((void *)(kaddr) >= (void *)PAGE_OFFSET) && \
-				((void *)(kaddr) < (void *)memory_end))
-
-#endif /* __ASSEMBLY__ */
-
-#include <asm-generic/memory_model.h>
-#include <asm-generic/getorder.h>
-
-#endif /* _H8300_PAGE_H */
diff --git a/arch/h8300/include/asm/page_offset.h b/arch/h8300/include/asm/page_offset.h
deleted file mode 100644
index f870646..0000000
--- a/arch/h8300/include/asm/page_offset.h
+++ /dev/null
@@ -1,3 +0,0 @@
-
-#define PAGE_OFFSET_RAW		0x00000000
-
diff --git a/arch/h8300/include/asm/param.h b/arch/h8300/include/asm/param.h
deleted file mode 100644
index c3909e7..0000000
--- a/arch/h8300/include/asm/param.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _H8300_PARAM_H
-#define _H8300_PARAM_H
-
-#include <uapi/asm/param.h>
-
-#define HZ		CONFIG_HZ
-#define	USER_HZ		HZ
-#define	CLOCKS_PER_SEC	(USER_HZ)
-#endif /* _H8300_PARAM_H */
diff --git a/arch/h8300/include/asm/pci.h b/arch/h8300/include/asm/pci.h
deleted file mode 100644
index 0b2acaa..0000000
--- a/arch/h8300/include/asm/pci.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _ASM_H8300_PCI_H
-#define _ASM_H8300_PCI_H
-
-/*
- * asm-h8300/pci.h - H8/300 specific PCI declarations.
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- */
-
-#define pcibios_assign_all_busses()	0
-
-static inline void pcibios_penalize_isa_irq(int irq, int active)
-{
-	/* We don't do dynamic PCI IRQ allocation */
-}
-
-#define PCI_DMA_BUS_IS_PHYS	(1)
-
-#endif /* _ASM_H8300_PCI_H */
diff --git a/arch/h8300/include/asm/percpu.h b/arch/h8300/include/asm/percpu.h
deleted file mode 100644
index 72c03e3..0000000
--- a/arch/h8300/include/asm/percpu.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ARCH_H8300_PERCPU__
-#define __ARCH_H8300_PERCPU__
-
-#include <asm-generic/percpu.h>
-
-#endif /* __ARCH_H8300_PERCPU__ */
diff --git a/arch/h8300/include/asm/pgalloc.h b/arch/h8300/include/asm/pgalloc.h
deleted file mode 100644
index c2e89a2..0000000
--- a/arch/h8300/include/asm/pgalloc.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _H8300_PGALLOC_H
-#define _H8300_PGALLOC_H
-
-#include <asm/setup.h>
-
-#define check_pgt_cache()	do { } while (0)
-
-#endif /* _H8300_PGALLOC_H */
diff --git a/arch/h8300/include/asm/pgtable.h b/arch/h8300/include/asm/pgtable.h
deleted file mode 100644
index 7ca20f8..0000000
--- a/arch/h8300/include/asm/pgtable.h
+++ /dev/null
@@ -1,73 +0,0 @@
-#ifndef _H8300_PGTABLE_H
-#define _H8300_PGTABLE_H
-
-#include <asm-generic/4level-fixup.h>
-
-#include <linux/slab.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/io.h>
-
-#define pgd_present(pgd)     (1)       /* pages are always present on NO_MM */
-#define pgd_none(pgd)		(0)
-#define pgd_bad(pgd)		(0)
-#define pgd_clear(pgdp)
-#define kern_addr_valid(addr)	(1)
-#define	pmd_offset(a, b)	((void *)0)
-#define pmd_none(pmd)           (1)
-#define pgd_offset_k(adrdress)  ((pgd_t *)0)
-#define pte_offset_kernel(dir, address) ((pte_t *)0)
-
-#define PAGE_NONE		__pgprot(0)    /* these mean nothing to NO_MM */
-#define PAGE_SHARED		__pgprot(0)    /* these mean nothing to NO_MM */
-#define PAGE_COPY		__pgprot(0)    /* these mean nothing to NO_MM */
-#define PAGE_READONLY	__pgprot(0)    /* these mean nothing to NO_MM */
-#define PAGE_KERNEL		__pgprot(0)    /* these mean nothing to NO_MM */
-
-extern void paging_init(void);
-#define swapper_pg_dir ((pgd_t *) 0)
-
-#define __swp_type(x)		(0)
-#define __swp_offset(x)		(0)
-#define __swp_entry(typ,off)	((swp_entry_t) { ((typ) | ((off) << 7)) })
-#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
-#define __swp_entry_to_pte(x)	((pte_t) { (x).val })
-
-static inline int pte_file(pte_t pte) { return 0; }
-
-/*
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-#define ZERO_PAGE(vaddr)	(virt_to_page(0))
-
-/*
- * These would be in other places but having them here reduces the diffs.
- */
-extern unsigned int kobjsize(const void *objp);
-extern int is_in_rom(unsigned long);
-
-/*
- * No page table caches to initialise
- */
-#define pgtable_cache_init()   do { } while (0)
-
-/*
- * All 32bit addresses are effectively valid for vmalloc...
- * Sort of meaningless for non-VM targets.
- */
-#define	VMALLOC_START	0
-#define	VMALLOC_END	0xffffffff
-
-/*
- * All 32bit addresses are effectively valid for vmalloc...
- * Sort of meaningless for non-VM targets.
- */
-#define	VMALLOC_START	0
-#define	VMALLOC_END	0xffffffff
-
-#define arch_enter_lazy_cpu_mode()    do {} while (0)
-
-#include <asm-generic/pgtable.h>
-
-#endif /* _H8300_PGTABLE_H */
diff --git a/arch/h8300/include/asm/processor.h b/arch/h8300/include/asm/processor.h
deleted file mode 100644
index 4b0ca49..0000000
--- a/arch/h8300/include/asm/processor.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * include/asm-h8300/processor.h
- *
- * Copyright (C) 2002 Yoshinori Sato
- *
- * Based on: linux/asm-m68nommu/processor.h
- *
- * Copyright (C) 1995 Hamish Macdonald
- */
-
-#ifndef __ASM_H8300_PROCESSOR_H
-#define __ASM_H8300_PROCESSOR_H
-
-/*
- * Default implementation of macro that returns current
- * instruction pointer ("program counter").
- */
-#define current_text_addr() ({ __label__ _l; _l: &&_l;})
-
-#include <linux/compiler.h>
-#include <asm/segment.h>
-#include <asm/fpu.h>
-#include <asm/ptrace.h>
-#include <asm/current.h>
-
-static inline unsigned long rdusp(void) {
-	extern unsigned int	sw_usp;
-	return(sw_usp);
-}
-
-static inline void wrusp(unsigned long usp) {
-	extern unsigned int	sw_usp;
-	sw_usp = usp;
-}
-
-/*
- * User space process size: 3.75GB. This is hardcoded into a few places,
- * so don't change it unless you know what you are doing.
- */
-#define TASK_SIZE	(0xFFFFFFFFUL)
-
-#ifdef __KERNEL__
-#define STACK_TOP	TASK_SIZE
-#define STACK_TOP_MAX	STACK_TOP
-#endif
-
-/*
- * This decides where the kernel will search for a free chunk of vm
- * space during mmap's. We won't be using it
- */
-#define TASK_UNMAPPED_BASE	0
-
-struct thread_struct {
-	unsigned long  ksp;		/* kernel stack pointer */
-	unsigned long  usp;		/* user stack pointer */
-	unsigned long  ccr;		/* saved status register */
-	unsigned long  esp0;            /* points to SR of stack frame */
-	struct {
-		unsigned short *addr;
-		unsigned short inst;
-	} breakinfo;
-};
-
-#define INIT_THREAD  {						\
-	.ksp  = sizeof(init_stack) + (unsigned long)init_stack, \
-	.usp  = 0,						\
-	.ccr  = PS_S,						\
-	.esp0 = 0,						\
-	.breakinfo = {						\
-		.addr = (unsigned short *)-1,			\
-		.inst = 0					\
-	}							\
-}
-
-/*
- * Do necessary setup to start up a newly executed thread.
- *
- * pass the data segment into user programs if it exists,
- * it can't hurt anything as far as I can tell
- */
-#if defined(__H8300H__)
-#define start_thread(_regs, _pc, _usp)			        \
-do {							        \
-  	(_regs)->pc = (_pc);				        \
-	(_regs)->ccr = 0x00;	   /* clear all flags */        \
-	(_regs)->er5 = current->mm->start_data;	/* GOT base */  \
-	wrusp((unsigned long)(_usp) - sizeof(unsigned long)*3);	\
-} while(0)
-#endif
-#if defined(__H8300S__)
-#define start_thread(_regs, _pc, _usp)			        \
-do {							        \
-	(_regs)->pc = (_pc);				        \
-	(_regs)->ccr = 0x00;	   /* clear kernel flag */      \
-	(_regs)->exr = 0x78;       /* enable all interrupts */  \
-	(_regs)->er5 = current->mm->start_data;	/* GOT base */  \
-	/* 14 = space for retaddr(4), vector(4), er0(4) and ext(2) on stack */ \
-	wrusp(((unsigned long)(_usp)) - 14);                    \
-} while(0)
-#endif
-
-/* Forward declaration, a strange C thing */
-struct task_struct;
-
-/* Free all resources held by a thread. */
-static inline void release_thread(struct task_struct *dead_task)
-{
-}
-
-/*
- * Free current thread data structures etc..
- */
-static inline void exit_thread(void)
-{
-}
-
-/*
- * Return saved PC of a blocked thread.
- */
-unsigned long thread_saved_pc(struct task_struct *tsk);
-unsigned long get_wchan(struct task_struct *p);
-
-#define	KSTK_EIP(tsk)	\
-    ({			\
-	unsigned long eip = 0;	 \
-	if ((tsk)->thread.esp0 > PAGE_SIZE && \
-	    MAP_NR((tsk)->thread.esp0) < max_mapnr) \
-	      eip = ((struct pt_regs *) (tsk)->thread.esp0)->pc; \
-	eip; })
-#define	KSTK_ESP(tsk)	((tsk) == current ? rdusp() : (tsk)->thread.usp)
-
-#define cpu_relax()    barrier()
-
-#define HARD_RESET_NOW() ({		\
-        local_irq_disable();		\
-        asm("jmp @@0");			\
-})
-
-#endif
diff --git a/arch/h8300/include/asm/ptrace.h b/arch/h8300/include/asm/ptrace.h
deleted file mode 100644
index c1826b9..0000000
--- a/arch/h8300/include/asm/ptrace.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef _H8300_PTRACE_H
-#define _H8300_PTRACE_H
-
-#include <uapi/asm/ptrace.h>
-
-#ifndef __ASSEMBLY__
-#if defined(CONFIG_CPU_H8S)
-#endif
-#ifndef PS_S
-#define PS_S  (0x10)
-#endif
-
-#if defined(__H8300H__)
-#define H8300_REGS_NO 11
-#endif
-#if defined(__H8300S__)
-#define H8300_REGS_NO 12
-#endif
-
-/* Find the stack offset for a register, relative to thread.esp0. */
-#define PT_REG(reg)	((long)&((struct pt_regs *)0)->reg)
-
-#define arch_has_single_step()	(1)
-
-#define user_mode(regs) (!((regs)->ccr & PS_S))
-#define instruction_pointer(regs) ((regs)->pc)
-#define profile_pc(regs) instruction_pointer(regs)
-#define current_pt_regs() ((struct pt_regs *) \
-	(THREAD_SIZE + (unsigned long)current_thread_info()) - 1)
-#define signal_pt_regs() ((struct pt_regs *)current->thread.esp0)
-#define current_user_stack_pointer() rdusp()
-#endif /* __ASSEMBLY__ */
-#endif /* _H8300_PTRACE_H */
diff --git a/arch/h8300/include/asm/regs267x.h b/arch/h8300/include/asm/regs267x.h
deleted file mode 100644
index 1bff731..0000000
--- a/arch/h8300/include/asm/regs267x.h
+++ /dev/null
@@ -1,336 +0,0 @@
-/* internal Peripherals Register address define */
-/* CPU: H8/306x                                 */
-
-#if !defined(__REGS_H8S267x__)
-#define __REGS_H8S267x__ 
-
-#if defined(__KERNEL__)
-
-#define DASTCR 0xFEE01A
-#define DADR0  0xFFFFA4
-#define DADR1  0xFFFFA5
-#define DACR01 0xFFFFA6
-#define DADR2  0xFFFFA8
-#define DADR3  0xFFFFA9
-#define DACR23 0xFFFFAA
-
-#define ADDRA  0xFFFF90
-#define ADDRAH 0xFFFF90
-#define ADDRAL 0xFFFF91
-#define ADDRB  0xFFFF92
-#define ADDRBH 0xFFFF92
-#define ADDRBL 0xFFFF93
-#define ADDRC  0xFFFF94
-#define ADDRCH 0xFFFF94
-#define ADDRCL 0xFFFF95
-#define ADDRD  0xFFFF96
-#define ADDRDH 0xFFFF96
-#define ADDRDL 0xFFFF97
-#define ADDRE  0xFFFF98
-#define ADDREH 0xFFFF98
-#define ADDREL 0xFFFF99
-#define ADDRF  0xFFFF9A
-#define ADDRFH 0xFFFF9A
-#define ADDRFL 0xFFFF9B
-#define ADDRG  0xFFFF9C
-#define ADDRGH 0xFFFF9C
-#define ADDRGL 0xFFFF9D
-#define ADDRH  0xFFFF9E
-#define ADDRHH 0xFFFF9E
-#define ADDRHL 0xFFFF9F
-
-#define ADCSR  0xFFFFA0
-#define ADCR   0xFFFFA1
-
-#define ABWCR  0xFFFEC0
-#define ASTCR  0xFFFEC1
-#define WTCRAH 0xFFFEC2
-#define WTCRAL 0xFFFEC3
-#define WTCRBH 0xFFFEC4
-#define WTCRBL 0xFFFEC5
-#define RDNCR  0xFFFEC6
-#define CSACRH 0xFFFEC8
-#define CSACRL 0xFFFEC9
-#define BROMCRH 0xFFFECA
-#define BROMCRL 0xFFFECB
-#define BCR    0xFFFECC
-#define DRAMCR 0xFFFED0
-#define DRACCR 0xFFFED2
-#define REFCR  0xFFFED4
-#define RTCNT  0xFFFED6
-#define RTCOR  0xFFFED7
-
-#define MAR0AH  0xFFFEE0
-#define MAR0AL  0xFFFEE2
-#define IOAR0A  0xFFFEE4
-#define ETCR0A  0xFFFEE6
-#define MAR0BH  0xFFFEE8
-#define MAR0BL  0xFFFEEA
-#define IOAR0B  0xFFFEEC
-#define ETCR0B  0xFFFEEE
-#define MAR1AH  0xFFFEF0
-#define MAR1AL  0xFFFEF2
-#define IOAR1A  0xFFFEF4
-#define ETCR1A  0xFFFEF6
-#define MAR1BH  0xFFFEF8
-#define MAR1BL  0xFFFEFA
-#define IOAR1B  0xFFFEFC
-#define ETCR1B  0xFFFEFE
-#define DMAWER  0xFFFF20
-#define DMATCR  0xFFFF21
-#define DMACR0A 0xFFFF22
-#define DMACR0B 0xFFFF23
-#define DMACR1A 0xFFFF24
-#define DMACR1B 0xFFFF25
-#define DMABCRH 0xFFFF26
-#define DMABCRL 0xFFFF27
-
-#define EDSAR0  0xFFFDC0
-#define EDDAR0  0xFFFDC4
-#define EDTCR0  0xFFFDC8
-#define EDMDR0  0xFFFDCC
-#define EDMDR0H 0xFFFDCC
-#define EDMDR0L 0xFFFDCD
-#define EDACR0  0xFFFDCE
-#define EDSAR1  0xFFFDD0
-#define EDDAR1  0xFFFDD4
-#define EDTCR1  0xFFFDD8
-#define EDMDR1  0xFFFDDC
-#define EDMDR1H 0xFFFDDC
-#define EDMDR1L 0xFFFDDD
-#define EDACR1  0xFFFDDE
-#define EDSAR2  0xFFFDE0
-#define EDDAR2  0xFFFDE4
-#define EDTCR2  0xFFFDE8
-#define EDMDR2  0xFFFDEC
-#define EDMDR2H 0xFFFDEC
-#define EDMDR2L 0xFFFDED
-#define EDACR2  0xFFFDEE
-#define EDSAR3  0xFFFDF0
-#define EDDAR3  0xFFFDF4
-#define EDTCR3  0xFFFDF8
-#define EDMDR3  0xFFFDFC
-#define EDMDR3H 0xFFFDFC
-#define EDMDR3L 0xFFFDFD
-#define EDACR3  0xFFFDFE
-
-#define IPRA  0xFFFE00
-#define IPRB  0xFFFE02
-#define IPRC  0xFFFE04
-#define IPRD  0xFFFE06
-#define IPRE  0xFFFE08
-#define IPRF  0xFFFE0A
-#define IPRG  0xFFFE0C
-#define IPRH  0xFFFE0E
-#define IPRI  0xFFFE10
-#define IPRJ  0xFFFE12
-#define IPRK  0xFFFE14
-#define ITSR  0xFFFE16
-#define SSIER 0xFFFE18
-#define ISCRH 0xFFFE1A
-#define ISCRL 0xFFFE1C
-
-#define INTCR 0xFFFF31
-#define IER   0xFFFF32
-#define IERH  0xFFFF32
-#define IERL  0xFFFF33
-#define ISR   0xFFFF34
-#define ISRH  0xFFFF34
-#define ISRL  0xFFFF35
-
-#define P1DDR 0xFFFE20
-#define P2DDR 0xFFFE21
-#define P3DDR 0xFFFE22
-#define P4DDR 0xFFFE23
-#define P5DDR 0xFFFE24
-#define P6DDR 0xFFFE25
-#define P7DDR 0xFFFE26
-#define P8DDR 0xFFFE27
-#define P9DDR 0xFFFE28
-#define PADDR 0xFFFE29
-#define PBDDR 0xFFFE2A
-#define PCDDR 0xFFFE2B
-#define PDDDR 0xFFFE2C
-#define PEDDR 0xFFFE2D
-#define PFDDR 0xFFFE2E
-#define PGDDR 0xFFFE2F
-#define PHDDR 0xFFFF74
-
-#define PFCR0 0xFFFE32
-#define PFCR1 0xFFFE33
-#define PFCR2 0xFFFE34
-
-#define PAPCR 0xFFFE36
-#define PBPCR 0xFFFE37
-#define PCPCR 0xFFFE38
-#define PDPCR 0xFFFE39
-#define PEPCR 0xFFFE3A
-
-#define P3ODR 0xFFFE3C
-#define PAODR 0xFFFE3D
-
-#define P1DR  0xFFFF60
-#define P2DR  0xFFFF61
-#define P3DR  0xFFFF62
-#define P4DR  0xFFFF63
-#define P5DR  0xFFFF64
-#define P6DR  0xFFFF65
-#define P7DR  0xFFFF66
-#define P8DR  0xFFFF67
-#define P9DR  0xFFFF68
-#define PADR  0xFFFF69
-#define PBDR  0xFFFF6A
-#define PCDR  0xFFFF6B
-#define PDDR  0xFFFF6C
-#define PEDR  0xFFFF6D
-#define PFDR  0xFFFF6E
-#define PGDR  0xFFFF6F
-#define PHDR  0xFFFF72
-
-#define PORT1 0xFFFF50
-#define PORT2 0xFFFF51
-#define PORT3 0xFFFF52
-#define PORT4 0xFFFF53
-#define PORT5 0xFFFF54
-#define PORT6 0xFFFF55
-#define PORT7 0xFFFF56
-#define PORT8 0xFFFF57
-#define PORT9 0xFFFF58
-#define PORTA 0xFFFF59
-#define PORTB 0xFFFF5A
-#define PORTC 0xFFFF5B
-#define PORTD 0xFFFF5C
-#define PORTE 0xFFFF5D
-#define PORTF 0xFFFF5E
-#define PORTG 0xFFFF5F
-#define PORTH 0xFFFF70
-
-#define PCR   0xFFFF46
-#define PMR   0xFFFF47
-#define NDERH 0xFFFF48
-#define NDERL 0xFFFF49
-#define PODRH 0xFFFF4A
-#define PODRL 0xFFFF4B
-#define NDRH1 0xFFFF4C
-#define NDRL1 0xFFFF4D
-#define NDRH2 0xFFFF4E
-#define NDRL2 0xFFFF4F
-
-#define SMR0  0xFFFF78
-#define BRR0  0xFFFF79
-#define SCR0  0xFFFF7A
-#define TDR0  0xFFFF7B
-#define SSR0  0xFFFF7C
-#define RDR0  0xFFFF7D
-#define SCMR0 0xFFFF7E
-#define SMR1  0xFFFF80
-#define BRR1  0xFFFF81
-#define SCR1  0xFFFF82
-#define TDR1  0xFFFF83
-#define SSR1  0xFFFF84
-#define RDR1  0xFFFF85
-#define SCMR1 0xFFFF86
-#define SMR2  0xFFFF88
-#define BRR2  0xFFFF89
-#define SCR2  0xFFFF8A
-#define TDR2  0xFFFF8B
-#define SSR2  0xFFFF8C
-#define RDR2  0xFFFF8D
-#define SCMR2 0xFFFF8E
-
-#define IRCR0 0xFFFE1E
-#define SEMR  0xFFFDA8
-
-#define MDCR    0xFFFF3E
-#define SYSCR   0xFFFF3D
-#define MSTPCRH 0xFFFF40
-#define MSTPCRL 0xFFFF41
-#define FLMCR1  0xFFFFC8
-#define FLMCR2  0xFFFFC9
-#define EBR1    0xFFFFCA
-#define EBR2    0xFFFFCB
-#define CTGARC_RAMCR   0xFFFECE
-#define SBYCR   0xFFFF3A
-#define SCKCR   0xFFFF3B
-#define PLLCR   0xFFFF45
-
-#define TSTR   0xFFFFC0
-#define TSNC   0XFFFFC1
-
-#define TCR0   0xFFFFD0
-#define TMDR0  0xFFFFD1
-#define TIORH0 0xFFFFD2
-#define TIORL0 0xFFFFD3
-#define TIER0  0xFFFFD4
-#define TSR0   0xFFFFD5
-#define TCNT0  0xFFFFD6
-#define GRA0   0xFFFFD8
-#define GRB0   0xFFFFDA
-#define GRC0   0xFFFFDC
-#define GRD0   0xFFFFDE
-#define TCR1   0xFFFFE0
-#define TMDR1  0xFFFFE1
-#define TIORH1 0xFFFFE2
-#define TIORL1 0xFFFFE3
-#define TIER1  0xFFFFE4
-#define TSR1   0xFFFFE5
-#define TCNT1  0xFFFFE6
-#define GRA1   0xFFFFE8
-#define GRB1   0xFFFFEA
-#define TCR2   0xFFFFF0
-#define TMDR2  0xFFFFF1
-#define TIORH2 0xFFFFF2
-#define TIORL2 0xFFFFF3
-#define TIER2  0xFFFFF4
-#define TSR2   0xFFFFF5
-#define TCNT2  0xFFFFF6
-#define GRA2   0xFFFFF8
-#define GRB2   0xFFFFFA
-#define TCR3   0xFFFE80
-#define TMDR3  0xFFFE81
-#define TIORH3 0xFFFE82
-#define TIORL3 0xFFFE83
-#define TIER3  0xFFFE84
-#define TSR3   0xFFFE85
-#define TCNT3  0xFFFE86
-#define GRA3   0xFFFE88
-#define GRB3   0xFFFE8A
-#define GRC3   0xFFFE8C
-#define GRD3   0xFFFE8E
-#define TCR4   0xFFFE90
-#define TMDR4  0xFFFE91
-#define TIORH4 0xFFFE92
-#define TIORL4 0xFFFE93
-#define TIER4  0xFFFE94
-#define TSR4   0xFFFE95
-#define TCNT4  0xFFFE96
-#define GRA4   0xFFFE98
-#define GRB4   0xFFFE9A
-#define TCR5   0xFFFEA0
-#define TMDR5  0xFFFEA1
-#define TIORH5 0xFFFEA2
-#define TIORL5 0xFFFEA3
-#define TIER5  0xFFFEA4
-#define TSR5   0xFFFEA5
-#define TCNT5  0xFFFEA6
-#define GRA5   0xFFFEA8
-#define GRB5   0xFFFEAA
-
-#define _8TCR0   0xFFFFB0
-#define _8TCR1   0xFFFFB1
-#define _8TCSR0  0xFFFFB2
-#define _8TCSR1  0xFFFFB3
-#define _8TCORA0 0xFFFFB4
-#define _8TCORA1 0xFFFFB5
-#define _8TCORB0 0xFFFFB6
-#define _8TCORB1 0xFFFFB7
-#define _8TCNT0  0xFFFFB8
-#define _8TCNT1  0xFFFFB9
-
-#define TCSR    0xFFFFBC
-#define TCNT    0xFFFFBD
-#define RSTCSRW 0xFFFFBE
-#define RSTCSRR 0xFFFFBF
-
-#endif /* __KERNEL__ */
-#endif /* __REGS_H8S267x__ */
diff --git a/arch/h8300/include/asm/regs306x.h b/arch/h8300/include/asm/regs306x.h
deleted file mode 100644
index 027dd63..0000000
--- a/arch/h8300/include/asm/regs306x.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/* internal Peripherals Register address define */
-/* CPU: H8/306x                                 */
-
-#if !defined(__REGS_H8306x__)
-#define __REGS_H8306x__ 
-
-#if defined(__KERNEL__)
-
-#define DASTCR 0xFEE01A
-#define DADR0  0xFEE09C
-#define DADR1  0xFEE09D
-#define DACR   0xFEE09E
-
-#define ADDRAH 0xFFFFE0
-#define ADDRAL 0xFFFFE1
-#define ADDRBH 0xFFFFE2
-#define ADDRBL 0xFFFFE3
-#define ADDRCH 0xFFFFE4
-#define ADDRCL 0xFFFFE5
-#define ADDRDH 0xFFFFE6
-#define ADDRDL 0xFFFFE7
-#define ADCSR  0xFFFFE8
-#define ADCR   0xFFFFE9
-
-#define BRCR   0xFEE013
-#define ADRCR  0xFEE01E
-#define CSCR   0xFEE01F
-#define ABWCR  0xFEE020
-#define ASTCR  0xFEE021
-#define WCRH   0xFEE022
-#define WCRL   0xFEE023
-#define BCR    0xFEE024
-#define DRCRA  0xFEE026
-#define DRCRB  0xFEE027
-#define RTMCSR 0xFEE028
-#define RTCNT  0xFEE029
-#define RTCOR  0xFEE02A
-
-#define MAR0AR  0xFFFF20
-#define MAR0AE  0xFFFF21
-#define MAR0AH  0xFFFF22
-#define MAR0AL  0xFFFF23
-#define ETCR0AL 0xFFFF24
-#define ETCR0AH 0xFFFF25
-#define IOAR0A  0xFFFF26
-#define DTCR0A  0xFFFF27
-#define MAR0BR  0xFFFF28
-#define MAR0BE  0xFFFF29
-#define MAR0BH  0xFFFF2A
-#define MAR0BL  0xFFFF2B
-#define ETCR0BL 0xFFFF2C
-#define ETCR0BH 0xFFFF2D
-#define IOAR0B  0xFFFF2E
-#define DTCR0B  0xFFFF2F
-#define MAR1AR  0xFFFF30
-#define MAR1AE  0xFFFF31
-#define MAR1AH  0xFFFF32
-#define MAR1AL  0xFFFF33
-#define ETCR1AL 0xFFFF34
-#define ETCR1AH 0xFFFF35
-#define IOAR1A  0xFFFF36
-#define DTCR1A  0xFFFF37
-#define MAR1BR  0xFFFF38
-#define MAR1BE  0xFFFF39
-#define MAR1BH  0xFFFF3A
-#define MAR1BL  0xFFFF3B
-#define ETCR1BL 0xFFFF3C
-#define ETCR1BH 0xFFFF3D
-#define IOAR1B  0xFFFF3E
-#define DTCR1B  0xFFFF3F
-
-#define ISCR 0xFEE014
-#define IER  0xFEE015
-#define ISR  0xFEE016
-#define IPRA 0xFEE018
-#define IPRB 0xFEE019
-
-#define P1DDR 0xFEE000
-#define P2DDR 0xFEE001
-#define P3DDR 0xFEE002
-#define P4DDR 0xFEE003
-#define P5DDR 0xFEE004
-#define P6DDR 0xFEE005
-/*#define P7DDR 0xFEE006*/
-#define P8DDR 0xFEE007
-#define P9DDR 0xFEE008
-#define PADDR 0xFEE009
-#define PBDDR 0xFEE00A
-
-#define P1DR  0xFFFFD0
-#define P2DR  0xFFFFD1
-#define P3DR  0xFFFFD2
-#define P4DR  0xFFFFD3
-#define P5DR  0xFFFFD4
-#define P6DR  0xFFFFD5
-/*#define P7DR  0xFFFFD6*/
-#define P8DR  0xFFFFD7
-#define P9DR  0xFFFFD8
-#define PADR  0xFFFFD9
-#define PBDR  0xFFFFDA
-
-#define P2CR  0xFEE03C
-#define P4CR  0xFEE03E
-#define P5CR  0xFEE03F
-
-#define SMR0  0xFFFFB0
-#define BRR0  0xFFFFB1
-#define SCR0  0xFFFFB2
-#define TDR0  0xFFFFB3
-#define SSR0  0xFFFFB4
-#define RDR0  0xFFFFB5
-#define SCMR0 0xFFFFB6
-#define SMR1  0xFFFFB8
-#define BRR1  0xFFFFB9
-#define SCR1  0xFFFFBA
-#define TDR1  0xFFFFBB
-#define SSR1  0xFFFFBC
-#define RDR1  0xFFFFBD
-#define SCMR1 0xFFFFBE
-#define SMR2  0xFFFFC0
-#define BRR2  0xFFFFC1
-#define SCR2  0xFFFFC2
-#define TDR2  0xFFFFC3
-#define SSR2  0xFFFFC4
-#define RDR2  0xFFFFC5
-#define SCMR2 0xFFFFC6
-
-#define MDCR   0xFEE011
-#define SYSCR  0xFEE012
-#define DIVCR  0xFEE01B
-#define MSTCRH 0xFEE01C
-#define MSTCRL 0xFEE01D
-#define FLMCR1 0xFEE030
-#define FLMCR2 0xFEE031
-#define EBR1   0xFEE032
-#define EBR2   0xFEE033
-#define RAMCR  0xFEE077
-
-#define TSTR   0xFFFF60
-#define TSNC   0XFFFF61
-#define TMDR   0xFFFF62
-#define TOLR   0xFFFF63
-#define TISRA  0xFFFF64
-#define TISRB  0xFFFF65
-#define TISRC  0xFFFF66
-#define TCR0   0xFFFF68
-#define TIOR0  0xFFFF69
-#define TCNT0H 0xFFFF6A
-#define TCNT0L 0xFFFF6B
-#define GRA0H  0xFFFF6C
-#define GRA0L  0xFFFF6D
-#define GRB0H  0xFFFF6E
-#define GRB0L  0xFFFF6F
-#define TCR1   0xFFFF70
-#define TIOR1  0xFFFF71
-#define TCNT1H 0xFFFF72
-#define TCNT1L 0xFFFF73
-#define GRA1H  0xFFFF74
-#define GRA1L  0xFFFF75
-#define GRB1H  0xFFFF76
-#define GRB1L  0xFFFF77
-#define TCR3   0xFFFF78
-#define TIOR3  0xFFFF79
-#define TCNT3H 0xFFFF7A
-#define TCNT3L 0xFFFF7B
-#define GRA3H  0xFFFF7C
-#define GRA3L  0xFFFF7D
-#define GRB3H  0xFFFF7E
-#define GRB3L  0xFFFF7F
-
-#define _8TCR0  0xFFFF80
-#define _8TCR1  0xFFFF81
-#define _8TCSR0 0xFFFF82
-#define _8TCSR1 0xFFFF83
-#define TCORA0 0xFFFF84
-#define TCORA1 0xFFFF85
-#define TCORB0 0xFFFF86
-#define TCORB1 0xFFFF87
-#define _8TCNT0 0xFFFF88
-#define _8TCNT1 0xFFFF89
-
-#define _8TCR2  0xFFFF90
-#define _8TCR3  0xFFFF91
-#define _8TCSR2 0xFFFF92
-#define _8TCSR3 0xFFFF93
-#define TCORA2 0xFFFF94
-#define TCORA3 0xFFFF95
-#define TCORB2 0xFFFF96
-#define TCORB3 0xFFFF97
-#define _8TCNT2 0xFFFF98
-#define _8TCNT3 0xFFFF99
-
-#define TCSR   0xFFFF8C
-#define TCNT   0xFFFF8D
-#define RSTCSR 0xFFFF8F
-
-#define TPMR  0xFFFFA0
-#define TPCR  0xFFFFA1
-#define NDERB 0xFFFFA2
-#define NDERA 0xFFFFA3
-#define NDRB1 0xFFFFA4
-#define NDRA1 0xFFFFA5
-#define NDRB2 0xFFFFA6
-#define NDRA2 0xFFFFA7
-
-#define TCSR    0xFFFF8C
-#define TCNT    0xFFFF8D
-#define RSTCSRW 0xFFFF8E
-#define RSTCSRR 0xFFFF8F
-
-#endif /* __KERNEL__ */
-#endif /* __REGS_H8306x__ */
diff --git a/arch/h8300/include/asm/scatterlist.h b/arch/h8300/include/asm/scatterlist.h
deleted file mode 100644
index 82130ed..0000000
--- a/arch/h8300/include/asm/scatterlist.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_SCATTERLIST_H
-#define _H8300_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* !(_H8300_SCATTERLIST_H) */
diff --git a/arch/h8300/include/asm/sections.h b/arch/h8300/include/asm/sections.h
deleted file mode 100644
index a81743e..0000000
--- a/arch/h8300/include/asm/sections.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_SECTIONS_H_
-#define _H8300_SECTIONS_H_
-
-#include <asm-generic/sections.h>
-
-#endif
diff --git a/arch/h8300/include/asm/segment.h b/arch/h8300/include/asm/segment.h
deleted file mode 100644
index b79a82d..0000000
--- a/arch/h8300/include/asm/segment.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef _H8300_SEGMENT_H
-#define _H8300_SEGMENT_H
-
-/* define constants */
-#define USER_DATA     (1)
-#ifndef __USER_DS
-#define __USER_DS     (USER_DATA)
-#endif
-#define USER_PROGRAM  (2)
-#define SUPER_DATA    (3)
-#ifndef __KERNEL_DS
-#define __KERNEL_DS   (SUPER_DATA)
-#endif
-#define SUPER_PROGRAM (4)
-
-#ifndef __ASSEMBLY__
-
-typedef struct {
-	unsigned long seg;
-} mm_segment_t;
-
-#define MAKE_MM_SEG(s)	((mm_segment_t) { (s) })
-#define USER_DS		MAKE_MM_SEG(__USER_DS)
-#define KERNEL_DS	MAKE_MM_SEG(__KERNEL_DS)
-
-/*
- * Get/set the SFC/DFC registers for MOVES instructions
- */
-
-static inline mm_segment_t get_fs(void)
-{
-    return USER_DS;
-}
-
-static inline mm_segment_t get_ds(void)
-{
-    /* return the supervisor data space code */
-    return KERNEL_DS;
-}
-
-static inline void set_fs(mm_segment_t val)
-{
-}
-
-#define segment_eq(a,b)	((a).seg == (b).seg)
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* _H8300_SEGMENT_H */
diff --git a/arch/h8300/include/asm/sh_bios.h b/arch/h8300/include/asm/sh_bios.h
deleted file mode 100644
index b6bb6e5..0000000
--- a/arch/h8300/include/asm/sh_bios.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* eCos HAL interface header */
-
-#ifndef SH_BIOS_H
-#define SH_BIOS_H
-
-#define HAL_IF_VECTOR_TABLE 0xfffe20
-#define CALL_IF_SET_CONSOLE_COMM  13
-#define QUERY_CURRENT -1
-#define MANGLER       -3
-
-/* Checking for GDB stub active */
-/* suggestion Jonathan Larmour */
-static int sh_bios_in_gdb_mode(void)
-{
-	static int gdb_active = -1;
-	if (gdb_active == -1) {
-		int (*set_console_comm)(int);
-		set_console_comm = ((void **)HAL_IF_VECTOR_TABLE)[CALL_IF_SET_CONSOLE_COMM];
-		gdb_active = (set_console_comm(QUERY_CURRENT) == MANGLER);
-	}
-	return gdb_active;
-}
-
-static void sh_bios_gdb_detach(void)
-{
-
-}
-
-#endif
diff --git a/arch/h8300/include/asm/shm.h b/arch/h8300/include/asm/shm.h
deleted file mode 100644
index ed6623c..0000000
--- a/arch/h8300/include/asm/shm.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef _H8300_SHM_H
-#define _H8300_SHM_H
-
-
-/* format of page table entries that correspond to shared memory pages
-   currently out in swap space (see also mm/swap.c):
-   bits 0-1 (PAGE_PRESENT) is  = 0
-   bits 8..2 (SWP_TYPE) are = SHM_SWP_TYPE
-   bits 31..9 are used like this:
-   bits 15..9 (SHM_ID) the id of the shared memory segment
-   bits 30..16 (SHM_IDX) the index of the page within the shared memory segment
-                    (actually only bits 25..16 get used since SHMMAX is so low)
-   bit 31 (SHM_READ_ONLY) flag whether the page belongs to a read-only attach
-*/
-/* on the m68k both bits 0 and 1 must be zero */
-/* format on the sun3 is similar, but bits 30, 31 are set to zero and all
-   others are reduced by 2. --m */
-
-#ifndef CONFIG_SUN3
-#define SHM_ID_SHIFT	9
-#else
-#define SHM_ID_SHIFT	7
-#endif
-#define _SHM_ID_BITS	7
-#define SHM_ID_MASK	((1<<_SHM_ID_BITS)-1)
-
-#define SHM_IDX_SHIFT	(SHM_ID_SHIFT+_SHM_ID_BITS)
-#define _SHM_IDX_BITS	15
-#define SHM_IDX_MASK	((1<<_SHM_IDX_BITS)-1)
-
-#endif /* _H8300_SHM_H */
diff --git a/arch/h8300/include/asm/shmparam.h b/arch/h8300/include/asm/shmparam.h
deleted file mode 100644
index d186395..0000000
--- a/arch/h8300/include/asm/shmparam.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_SHMPARAM_H
-#define _H8300_SHMPARAM_H
-
-#define	SHMLBA PAGE_SIZE		 /* attach addr a multiple of this */
-
-#endif /* _H8300_SHMPARAM_H */
diff --git a/arch/h8300/include/asm/signal.h b/arch/h8300/include/asm/signal.h
deleted file mode 100644
index 6341e36..0000000
--- a/arch/h8300/include/asm/signal.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef _H8300_SIGNAL_H
-#define _H8300_SIGNAL_H
-
-#include <uapi/asm/signal.h>
-
-/* Most things should be clean enough to redefine this at will, if care
-   is taken to make libc match.  */
-
-#define _NSIG		64
-#define _NSIG_BPW	32
-#define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
-
-typedef unsigned long old_sigset_t;		/* at least 32 bits */
-
-typedef struct {
-	unsigned long sig[_NSIG_WORDS];
-} sigset_t;
-
-#define __ARCH_HAS_SA_RESTORER
-
-#include <asm/sigcontext.h>
-#undef __HAVE_ARCH_SIG_BITOPS
-
-#endif /* _H8300_SIGNAL_H */
diff --git a/arch/h8300/include/asm/smp.h b/arch/h8300/include/asm/smp.h
deleted file mode 100644
index 9e9bd7e..0000000
--- a/arch/h8300/include/asm/smp.h
+++ /dev/null
@@ -1 +0,0 @@
-/* nothing required here yet */
diff --git a/arch/h8300/include/asm/spinlock.h b/arch/h8300/include/asm/spinlock.h
deleted file mode 100644
index d5407fa..0000000
--- a/arch/h8300/include/asm/spinlock.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __H8300_SPINLOCK_H
-#define __H8300_SPINLOCK_H
-
-#error "H8/300 doesn't do SMP yet"
-
-#endif
diff --git a/arch/h8300/include/asm/string.h b/arch/h8300/include/asm/string.h
deleted file mode 100644
index ca50348..0000000
--- a/arch/h8300/include/asm/string.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef _H8300_STRING_H_
-#define _H8300_STRING_H_
-
-#ifdef __KERNEL__ /* only set these up for kernel code */
-
-#include <asm/setup.h>
-#include <asm/page.h>
-
-#define __HAVE_ARCH_MEMSET
-extern void * memset(void * s, int c, size_t count);
-
-#define __HAVE_ARCH_MEMCPY
-extern void * memcpy(void *d, const void *s, size_t count);
-
-#else /* KERNEL */
-
-/*
- *	let user libraries deal with these,
- *	IMHO the kernel has no place defining these functions for user apps
- */
-
-#define __HAVE_ARCH_STRCPY 1
-#define __HAVE_ARCH_STRNCPY 1
-#define __HAVE_ARCH_STRCAT 1
-#define __HAVE_ARCH_STRNCAT 1
-#define __HAVE_ARCH_STRCMP 1
-#define __HAVE_ARCH_STRNCMP 1
-#define __HAVE_ARCH_STRNICMP 1
-#define __HAVE_ARCH_STRCHR 1
-#define __HAVE_ARCH_STRRCHR 1
-#define __HAVE_ARCH_STRSTR 1
-#define __HAVE_ARCH_STRLEN 1
-#define __HAVE_ARCH_STRNLEN 1
-#define __HAVE_ARCH_MEMSET 1
-#define __HAVE_ARCH_MEMCPY 1
-#define __HAVE_ARCH_MEMMOVE 1
-#define __HAVE_ARCH_MEMSCAN 1
-#define __HAVE_ARCH_MEMCMP 1
-#define __HAVE_ARCH_MEMCHR 1
-#define __HAVE_ARCH_STRTOK 1
-
-#endif /* KERNEL */
-
-#endif /* _M68K_STRING_H_ */
diff --git a/arch/h8300/include/asm/switch_to.h b/arch/h8300/include/asm/switch_to.h
deleted file mode 100644
index cdd8731..0000000
--- a/arch/h8300/include/asm/switch_to.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef _H8300_SWITCH_TO_H
-#define _H8300_SWITCH_TO_H
-
-/*
- * switch_to(n) should switch tasks to task ptr, first checking that
- * ptr isn't the current task, in which case it does nothing.  This
- * also clears the TS-flag if the task we switched to has used the
- * math co-processor latest.
- */
-/*
- * switch_to() saves the extra registers, that are not saved
- * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and
- * a0-a1. Some of these are used by schedule() and its predecessors
- * and so we might get see unexpected behaviors when a task returns
- * with unexpected register values.
- *
- * syscall stores these registers itself and none of them are used
- * by syscall after the function in the syscall has been called.
- *
- * Beware that resume now expects *next to be in d1 and the offset of
- * tss to be in a1. This saves a few instructions as we no longer have
- * to push them onto the stack and read them back right after.
- *
- * 02/17/96 - Jes Sorensen (jds@kom.auc.dk)
- *
- * Changed 96/09/19 by Andreas Schwab
- * pass prev in a0, next in a1, offset of tss in d1, and whether
- * the mm structures are shared in d2 (to avoid atc flushing).
- *
- * H8/300 Porting 2002/09/04 Yoshinori Sato
- */
-
-asmlinkage void resume(void);
-#define switch_to(prev,next,last) {                         \
-  void *_last;						    \
-  __asm__ __volatile__(					    \
-  			"mov.l	%1, er0\n\t"		    \
-			"mov.l	%2, er1\n\t"		    \
-                        "mov.l  %3, er2\n\t"                \
-			"jsr @_resume\n\t"                  \
-                        "mov.l  er2,%0\n\t"                 \
-		       : "=r" (_last)			    \
-		       : "r" (&(prev->thread)),		    \
-			 "r" (&(next->thread)),		    \
-                         "g" (prev)                         \
-		       : "cc", "er0", "er1", "er2", "er3"); \
-  (last) = _last; 					    \
-}
-
-#endif /* _H8300_SWITCH_TO_H */
diff --git a/arch/h8300/include/asm/target_time.h b/arch/h8300/include/asm/target_time.h
deleted file mode 100644
index 9f2a9aa..0000000
--- a/arch/h8300/include/asm/target_time.h
+++ /dev/null
@@ -1,4 +0,0 @@
-extern int platform_timer_setup(void (*timer_int)(int, void *, struct pt_regs *));
-extern void platform_timer_eoi(void);
-extern void platform_gettod(unsigned int *year, unsigned int *mon, unsigned int *day, 
-                            unsigned int *hour, unsigned int *min, unsigned int *sec);
diff --git a/arch/h8300/include/asm/termios.h b/arch/h8300/include/asm/termios.h
deleted file mode 100644
index 93a63df..0000000
--- a/arch/h8300/include/asm/termios.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef _H8300_TERMIOS_H
-#define _H8300_TERMIOS_H
-
-#include <uapi/asm/termios.h>
-
-/*	intr=^C		quit=^|		erase=del	kill=^U
-	eof=^D		vtime=\0	vmin=\1		sxtc=\0
-	start=^Q	stop=^S		susp=^Z		eol=\0
-	reprint=^R	discard=^U	werase=^W	lnext=^V
-	eol2=\0
-*/
-#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
-
-/*
- * Translate a "termio" structure into a "termios". Ugh.
- */
-#define user_termio_to_kernel_termios(termios, termio) \
-({ \
-	unsigned short tmp; \
-	get_user(tmp, &(termio)->c_iflag); \
-	(termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
-	get_user(tmp, &(termio)->c_oflag); \
-	(termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \
-	get_user(tmp, &(termio)->c_cflag); \
-	(termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \
-	get_user(tmp, &(termio)->c_lflag); \
-	(termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
-	get_user((termios)->c_line, &(termio)->c_line); \
-	copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
-})
-
-/*
- * Translate a "termios" structure into a "termio". Ugh.
- */
-#define kernel_termios_to_user_termio(termio, termios) \
-({ \
-	put_user((termios)->c_iflag, &(termio)->c_iflag); \
-	put_user((termios)->c_oflag, &(termio)->c_oflag); \
-	put_user((termios)->c_cflag, &(termio)->c_cflag); \
-	put_user((termios)->c_lflag, &(termio)->c_lflag); \
-	put_user((termios)->c_line,  &(termio)->c_line); \
-	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
-})
-
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
-#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
-
-#endif /* _H8300_TERMIOS_H */
diff --git a/arch/h8300/include/asm/thread_info.h b/arch/h8300/include/asm/thread_info.h
deleted file mode 100644
index ec2f777..0000000
--- a/arch/h8300/include/asm/thread_info.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* thread_info.h: h8300 low-level thread information
- * adapted from the i386 and PPC versions by Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * Copyright (C) 2002  David Howells (dhowells@redhat.com)
- * - Incorporating suggestions made by Linus Torvalds and Dave Miller
- */
-
-#ifndef _ASM_THREAD_INFO_H
-#define _ASM_THREAD_INFO_H
-
-#include <asm/page.h>
-
-#ifdef __KERNEL__
-
-#ifndef __ASSEMBLY__
-
-/*
- * low level task data.
- * If you change this, change the TI_* offsets below to match.
- */
-struct thread_info {
-	struct task_struct *task;		/* main task structure */
-	struct exec_domain *exec_domain;	/* execution domain */
-	unsigned long	   flags;		/* low level flags */
-	int		   cpu;			/* cpu we're on */
-	int		   preempt_count;	/* 0 => preemptable, <0 => BUG */
-	struct restart_block restart_block;
-};
-
-/*
- * macros/functions for gaining access to the thread information structure
- */
-#define INIT_THREAD_INFO(tsk)			\
-{						\
-	.task =		&tsk,			\
-	.exec_domain =	&default_exec_domain,	\
-	.flags =	0,			\
-	.cpu =		0,			\
-	.preempt_count = INIT_PREEMPT_COUNT,	\
-	.restart_block	= {			\
-		.fn = do_no_restart_syscall,	\
-	},					\
-}
-
-#define init_thread_info	(init_thread_union.thread_info)
-#define init_stack		(init_thread_union.stack)
-
-
-/*
- * Size of kernel stack for each process. This must be a power of 2...
- */
-#define THREAD_SIZE_ORDER	1
-#define THREAD_SIZE		8192	/* 2 pages */
-
-
-/* how to get the thread information struct from C */
-static inline struct thread_info *current_thread_info(void)
-{
-	struct thread_info *ti;
-	__asm__(
-		"mov.l	sp, %0 \n\t"
-		"and.l	%1, %0"
-		: "=&r"(ti)
-		: "i" (~(THREAD_SIZE-1))
-		);
-	return ti;
-}
-
-#endif /* __ASSEMBLY__ */
-
-/*
- * Offsets in thread_info structure, used in assembly code
- */
-#define TI_TASK		0
-#define TI_EXECDOMAIN	4
-#define TI_FLAGS	8
-#define TI_CPU		12
-#define TI_PRE_COUNT	16
-
-#define	PREEMPT_ACTIVE	0x4000000
-
-/*
- * thread information flag bit numbers
- */
-#define TIF_SYSCALL_TRACE	0	/* syscall trace active */
-#define TIF_SIGPENDING		1	/* signal pending */
-#define TIF_NEED_RESCHED	2	/* rescheduling necessary */
-#define TIF_MEMDIE		4	/* is terminating due to OOM killer */
-#define TIF_RESTORE_SIGMASK	5	/* restore signal mask in do_signal() */
-#define TIF_NOTIFY_RESUME	6	/* callback before returning to user */
-
-/* as above, but as bit values */
-#define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
-#define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
-#define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
-#define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
-
-#define _TIF_WORK_MASK		(_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
-				 _TIF_NOTIFY_RESUME)
-
-#endif /* __KERNEL__ */
-
-#endif /* _ASM_THREAD_INFO_H */
diff --git a/arch/h8300/include/asm/timer.h b/arch/h8300/include/asm/timer.h
deleted file mode 100644
index def8046..0000000
--- a/arch/h8300/include/asm/timer.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef __H8300_TIMER_H
-#define __H8300_TIMER_H
-
-void h8300_timer_tick(void);
-void h8300_timer_setup(void);
-void h8300_gettod(unsigned int *year, unsigned int *mon, unsigned int *day,
-		   unsigned int *hour, unsigned int *min, unsigned int *sec);
-
-#define TIMER_FREQ (CONFIG_CPU_CLOCK*10000) /* Timer input freq. */
-
-#define calc_param(cnt, div, rate, limit)			\
-do {								\
-	cnt = TIMER_FREQ / HZ;					\
-	for (div = 0; div < ARRAY_SIZE(divide_rate); div++) {	\
-		if (rate[div] == 0)				\
-			continue;				\
-		if ((cnt / rate[div]) > limit)			\
-			break;					\
-	}							\
-	if (div == ARRAY_SIZE(divide_rate))			\
-		panic("Timer counter overflow");		\
-	cnt /= divide_rate[div];				\
-} while(0)
-
-#endif
diff --git a/arch/h8300/include/asm/timex.h b/arch/h8300/include/asm/timex.h
deleted file mode 100644
index 23e6701..0000000
--- a/arch/h8300/include/asm/timex.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * linux/include/asm-h8300/timex.h
- *
- * H8/300 architecture timex specifications
- */
-#ifndef _ASM_H8300_TIMEX_H
-#define _ASM_H8300_TIMEX_H
-
-#define CLOCK_TICK_RATE (CONFIG_CPU_CLOCK*1000/8192) /* Timer input freq. */
-
-typedef unsigned long cycles_t;
-extern short h8300_timer_count;
-
-static inline cycles_t get_cycles(void)
-{
-	return 0;
-}
-
-#endif
diff --git a/arch/h8300/include/asm/tlb.h b/arch/h8300/include/asm/tlb.h
deleted file mode 100644
index 7f07430..0000000
--- a/arch/h8300/include/asm/tlb.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __H8300_TLB_H__
-#define __H8300_TLB_H__
-
-#define tlb_flush(tlb)	do { } while(0)
-
-#include <asm-generic/tlb.h>
-
-#endif
diff --git a/arch/h8300/include/asm/tlbflush.h b/arch/h8300/include/asm/tlbflush.h
deleted file mode 100644
index 41c148a..0000000
--- a/arch/h8300/include/asm/tlbflush.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef _H8300_TLBFLUSH_H
-#define _H8300_TLBFLUSH_H
-
-/*
- * Copyright (C) 2000 Lineo, David McCullough <davidm@uclinux.org>
- * Copyright (C) 2000-2002, Greg Ungerer <gerg@snapgear.com>
- */
-
-#include <asm/setup.h>
-
-/*
- * flush all user-space atc entries.
- */
-static inline void __flush_tlb(void)
-{
-	BUG();
-}
-
-static inline void __flush_tlb_one(unsigned long addr)
-{
-	BUG();
-}
-
-#define flush_tlb() __flush_tlb()
-
-/*
- * flush all atc entries (both kernel and user-space entries).
- */
-static inline void flush_tlb_all(void)
-{
-	BUG();
-}
-
-static inline void flush_tlb_mm(struct mm_struct *mm)
-{
-	BUG();
-}
-
-static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
-{
-	BUG();
-}
-
-static inline void flush_tlb_range(struct mm_struct *mm,
-				   unsigned long start, unsigned long end)
-{
-	BUG();
-}
-
-static inline void flush_tlb_kernel_page(unsigned long addr)
-{
-	BUG();
-}
-
-#endif /* _H8300_TLBFLUSH_H */
diff --git a/arch/h8300/include/asm/topology.h b/arch/h8300/include/asm/topology.h
deleted file mode 100644
index fdc1219..0000000
--- a/arch/h8300/include/asm/topology.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_H8300_TOPOLOGY_H
-#define _ASM_H8300_TOPOLOGY_H
-
-#include <asm-generic/topology.h>
-
-#endif /* _ASM_H8300_TOPOLOGY_H */
diff --git a/arch/h8300/include/asm/traps.h b/arch/h8300/include/asm/traps.h
deleted file mode 100644
index 41cf6be..0000000
--- a/arch/h8300/include/asm/traps.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  linux/include/asm-h8300/traps.h
- *
- *  Copyright (C) 2003 Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#ifndef _H8300_TRAPS_H
-#define _H8300_TRAPS_H
-
-extern void system_call(void);
-extern void interrupt_entry(void);
-extern void trace_break(void);
-
-#define JMP_OP 0x5a000000
-#define JSR_OP 0x5e000000
-#define VECTOR(address) ((JMP_OP)|((unsigned long)address))
-#define REDIRECT(address) ((JSR_OP)|((unsigned long)address))
-
-#define TRACE_VEC 5
-
-#define TRAP0_VEC 8
-#define TRAP1_VEC 9
-#define TRAP2_VEC 10
-#define TRAP3_VEC 11
-
-#if defined(__H8300H__)
-#define NR_TRAPS 12
-#endif
-#if defined(__H8300S__)
-#define NR_TRAPS 16
-#endif
-
-#endif /* _H8300_TRAPS_H */
diff --git a/arch/h8300/include/asm/types.h b/arch/h8300/include/asm/types.h
deleted file mode 100644
index c012707..0000000
--- a/arch/h8300/include/asm/types.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _H8300_TYPES_H
-#define _H8300_TYPES_H
-
-#include <uapi/asm/types.h>
-
-
-#define BITS_PER_LONG 32
-
-#endif /* _H8300_TYPES_H */
diff --git a/arch/h8300/include/asm/uaccess.h b/arch/h8300/include/asm/uaccess.h
deleted file mode 100644
index 8725d1a..0000000
--- a/arch/h8300/include/asm/uaccess.h
+++ /dev/null
@@ -1,163 +0,0 @@
-#ifndef __H8300_UACCESS_H
-#define __H8300_UACCESS_H
-
-/*
- * User space memory access functions
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-
-#include <asm/segment.h>
-
-#define VERIFY_READ	0
-#define VERIFY_WRITE	1
-
-/* We let the MMU do all checking */
-#define access_ok(type, addr, size) __access_ok((unsigned long)addr,size)
-static inline int __access_ok(unsigned long addr, unsigned long size)
-{
-#define	RANGE_CHECK_OK(addr, size, lower, upper) \
-	(((addr) >= (lower)) && (((addr) + (size)) < (upper)))
-
-	extern unsigned long _ramend;
-	return(RANGE_CHECK_OK(addr, size, 0L, (unsigned long)&_ramend));
-}
-
-/*
- * The exception table consists of pairs of addresses: the first is the
- * address of an instruction that is allowed to fault, and the second is
- * the address at which the program should continue.  No registers are
- * modified, so it is entirely up to the continuation code to figure out
- * what to do.
- *
- * All the routines below use bits of fixup code that are out of line
- * with the main instruction path.  This means when everything is well,
- * we don't even have to jump over them.  Further, they do not intrude
- * on our cache or tlb entries.
- */
-
-struct exception_table_entry
-{
-	unsigned long insn, fixup;
-};
-
-/* Returns 0 if exception not found and fixup otherwise.  */
-extern unsigned long search_exception_table(unsigned long);
-
-
-/*
- * These are the main single-value transfer routines.  They automatically
- * use the right size if we just have the right pointer type.
- */
-
-#define put_user(x, ptr)				\
-({							\
-    int __pu_err = 0;					\
-    typeof(*(ptr)) __pu_val = (x);			\
-    switch (sizeof (*(ptr))) {				\
-    case 1:						\
-    case 2:						\
-    case 4:						\
-	*(ptr) = (__pu_val);   	        		\
-	break;						\
-    case 8:						\
-	memcpy(ptr, &__pu_val, sizeof (*(ptr)));        \
-	break;						\
-    default:						\
-	__pu_err = __put_user_bad();			\
-	break;						\
-    }							\
-    __pu_err;						\
-})
-#define __put_user(x, ptr) put_user(x, ptr)
-
-extern int __put_user_bad(void);
-
-/*
- * Tell gcc we read from memory instead of writing: this is because
- * we do not write to any memory gcc knows about, so there are no
- * aliasing issues.
- */
-
-#define __ptr(x) ((unsigned long *)(x))
-
-/*
- * Tell gcc we read from memory instead of writing: this is because
- * we do not write to any memory gcc knows about, so there are no
- * aliasing issues.
- */
-
-#define get_user(x, ptr)					\
-({								\
-    int __gu_err = 0;						\
-    typeof(*(ptr)) __gu_val = *ptr;				\
-    switch (sizeof(*(ptr))) {					\
-    case 1:							\
-    case 2:							\
-    case 4:							\
-    case 8: 							\
-	break;							\
-    default:							\
-	__gu_err = __get_user_bad();				\
-	break;							\
-    }								\
-    (x) = __gu_val;						\
-    __gu_err;							\
-})
-#define __get_user(x, ptr) get_user(x, ptr)
-
-extern int __get_user_bad(void);
-
-#define copy_from_user(to, from, n)		(memcpy(to, from, n), 0)
-#define copy_to_user(to, from, n)		(memcpy(to, from, n), 0)
-
-#define __copy_from_user(to, from, n) copy_from_user(to, from, n)
-#define __copy_to_user(to, from, n) copy_to_user(to, from, n)
-#define __copy_to_user_inatomic __copy_to_user
-#define __copy_from_user_inatomic __copy_from_user
-
-#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; })
-
-#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; })
-
-/*
- * Copy a null terminated string from userspace.
- */
-
-static inline long
-strncpy_from_user(char *dst, const char *src, long count)
-{
-	char *tmp;
-	strncpy(dst, src, count);
-	for (tmp = dst; *tmp && count > 0; tmp++, count--)
-		;
-	return(tmp - dst); /* DAVIDM should we count a NUL ?  check getname */
-}
-
-/*
- * Return the size of a string (including the ending 0)
- *
- * Return 0 on exception, a value greater than N if too long
- */
-static inline long strnlen_user(const char *src, long n)
-{
-	return(strlen(src) + 1); /* DAVIDM make safer */
-}
-
-#define strlen_user(str) strnlen_user(str, 32767)
-
-/*
- * Zero Userspace
- */
-
-static inline unsigned long
-clear_user(void *to, unsigned long n)
-{
-	memset(to, 0, n);
-	return 0;
-}
-
-#define __clear_user	clear_user
-
-#endif /* _H8300_UACCESS_H */
diff --git a/arch/h8300/include/asm/ucontext.h b/arch/h8300/include/asm/ucontext.h
deleted file mode 100644
index 0bcf8f8..0000000
--- a/arch/h8300/include/asm/ucontext.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _H8300_UCONTEXT_H
-#define _H8300_UCONTEXT_H
-
-struct ucontext {
-	unsigned long	  uc_flags;
-	struct ucontext  *uc_link;
-	stack_t		  uc_stack;
-	struct sigcontext uc_mcontext;
-	sigset_t	  uc_sigmask;	/* mask last for extensibility */
-};
-
-#endif
diff --git a/arch/h8300/include/asm/unaligned.h b/arch/h8300/include/asm/unaligned.h
deleted file mode 100644
index b8d06c7..0000000
--- a/arch/h8300/include/asm/unaligned.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _ASM_H8300_UNALIGNED_H
-#define _ASM_H8300_UNALIGNED_H
-
-#include <linux/unaligned/be_memmove.h>
-#include <linux/unaligned/le_byteshift.h>
-#include <linux/unaligned/generic.h>
-
-#define get_unaligned	__get_unaligned_be
-#define put_unaligned	__put_unaligned_be
-
-#endif /* _ASM_H8300_UNALIGNED_H */
diff --git a/arch/h8300/include/asm/unistd.h b/arch/h8300/include/asm/unistd.h
deleted file mode 100644
index ab671ec..0000000
--- a/arch/h8300/include/asm/unistd.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef _ASM_H8300_UNISTD_H_
-#define _ASM_H8300_UNISTD_H_
-
-#include <uapi/asm/unistd.h>
-
-
-#define NR_syscalls 321
-
-#define __ARCH_WANT_OLD_READDIR
-#define __ARCH_WANT_OLD_STAT
-#define __ARCH_WANT_STAT64
-#define __ARCH_WANT_SYS_ALARM
-#define __ARCH_WANT_SYS_GETHOSTNAME
-#define __ARCH_WANT_SYS_IPC
-#define __ARCH_WANT_SYS_PAUSE
-#define __ARCH_WANT_SYS_SGETMASK
-#define __ARCH_WANT_SYS_SIGNAL
-#define __ARCH_WANT_SYS_TIME
-#define __ARCH_WANT_SYS_UTIME
-#define __ARCH_WANT_SYS_WAITPID
-#define __ARCH_WANT_SYS_SOCKETCALL
-#define __ARCH_WANT_SYS_FADVISE64
-#define __ARCH_WANT_SYS_GETPGRP
-#define __ARCH_WANT_SYS_LLSEEK
-#define __ARCH_WANT_SYS_NICE
-#define __ARCH_WANT_SYS_OLD_GETRLIMIT
-#define __ARCH_WANT_SYS_OLD_MMAP
-#define __ARCH_WANT_SYS_OLD_SELECT
-#define __ARCH_WANT_SYS_OLDUMOUNT
-#define __ARCH_WANT_SYS_SIGPENDING
-#define __ARCH_WANT_SYS_SIGPROCMASK
-#define __ARCH_WANT_SYS_FORK
-#define __ARCH_WANT_SYS_VFORK
-#define __ARCH_WANT_SYS_CLONE
-
-#endif /* _ASM_H8300_UNISTD_H_ */
diff --git a/arch/h8300/include/asm/user.h b/arch/h8300/include/asm/user.h
deleted file mode 100644
index 14a9e18..0000000
--- a/arch/h8300/include/asm/user.h
+++ /dev/null
@@ -1,75 +0,0 @@
-#ifndef _H8300_USER_H
-#define _H8300_USER_H
-
-#include <asm/page.h>
-
-/* Core file format: The core file is written in such a way that gdb
-   can understand it and provide useful information to the user (under
-   linux we use the 'trad-core' bfd).  There are quite a number of
-   obstacles to being able to view the contents of the floating point
-   registers, and until these are solved you will not be able to view the
-   contents of them.  Actually, you can read in the core file and look at
-   the contents of the user struct to find out what the floating point
-   registers contain.
-   The actual file contents are as follows:
-   UPAGE: 1 page consisting of a user struct that tells gdb what is present
-   in the file.  Directly after this is a copy of the task_struct, which
-   is currently not used by gdb, but it may come in useful at some point.
-   All of the registers are stored as part of the upage.  The upage should
-   always be only one page.
-   DATA: The data area is stored.  We use current->end_text to
-   current->brk to pick up all of the user variables, plus any memory
-   that may have been malloced.  No attempt is made to determine if a page
-   is demand-zero or if a page is totally unused, we just cover the entire
-   range.  All of the addresses are rounded in such a way that an integral
-   number of pages is written.
-   STACK: We need the stack information in order to get a meaningful
-   backtrace.  We need to write the data from (esp) to
-   current->start_stack, so we round each of these off in order to be able
-   to write an integer number of pages.
-   The minimum core file size is 3 pages, or 12288 bytes.
-*/
-
-/* This is the old layout of "struct pt_regs" as of Linux 1.x, and
-   is still the layout used by user (the new pt_regs doesn't have
-   all registers). */
-struct user_regs_struct {
-	long er1,er2,er3,er4,er5,er6;
-	long er0;
-	long usp;
-	long orig_er0;
-	short ccr;
-	long pc;
-};
-
-	
-/* When the kernel dumps core, it starts by dumping the user struct -
-   this will be used by gdb to figure out where the data and stack segments
-   are within the file, and what virtual addresses to use. */
-struct user{
-/* We start with the registers, to mimic the way that "memory" is returned
-   from the ptrace(3,...) function.  */
-  struct user_regs_struct regs;	/* Where the registers are actually stored */
-/* ptrace does not yet supply these.  Someday.... */
-/* The rest of this junk is to help gdb figure out what goes where */
-  unsigned long int u_tsize;	/* Text segment size (pages). */
-  unsigned long int u_dsize;	/* Data segment size (pages). */
-  unsigned long int u_ssize;	/* Stack segment size (pages). */
-  unsigned long start_code;     /* Starting virtual address of text. */
-  unsigned long start_stack;	/* Starting virtual address of stack area.
-				   This is actually the bottom of the stack,
-				   the top of the stack is always found in the
-				   esp register.  */
-  long int signal;     		/* Signal that caused the core dump. */
-  int reserved;			/* No longer used */
-  unsigned long u_ar0;		/* Used by gdb to help find the values for */
-				/* the registers. */
-  unsigned long magic;		/* To uniquely identify a core file */
-  char u_comm[32];		/* User command that was responsible */
-};
-#define NBPG PAGE_SIZE
-#define UPAGES 1
-#define HOST_TEXT_START_ADDR (u.start_code)
-#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
-
-#endif
diff --git a/arch/h8300/include/asm/virtconvert.h b/arch/h8300/include/asm/virtconvert.h
deleted file mode 100644
index 19cfd62..0000000
--- a/arch/h8300/include/asm/virtconvert.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __H8300_VIRT_CONVERT__
-#define __H8300_VIRT_CONVERT__
-
-/*
- * Macros used for converting between virtual and physical mappings.
- */
-
-#ifdef __KERNEL__
-
-#include <asm/setup.h>
-#include <asm/page.h>
-
-#define phys_to_virt(vaddr)	((void *) (vaddr))
-#define virt_to_phys(vaddr)	((unsigned long) (vaddr))
-
-#define virt_to_bus virt_to_phys
-#define bus_to_virt phys_to_virt
-
-#endif
-#endif
diff --git a/arch/h8300/include/uapi/asm/Kbuild b/arch/h8300/include/uapi/asm/Kbuild
deleted file mode 100644
index 040178c..0000000
--- a/arch/h8300/include/uapi/asm/Kbuild
+++ /dev/null
@@ -1,34 +0,0 @@
-# UAPI Header export list
-include include/uapi/asm-generic/Kbuild.asm
-
-header-y += auxvec.h
-header-y += bitsperlong.h
-header-y += byteorder.h
-header-y += errno.h
-header-y += fcntl.h
-header-y += ioctl.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += kvm_para.h
-header-y += mman.h
-header-y += msgbuf.h
-header-y += param.h
-header-y += poll.h
-header-y += posix_types.h
-header-y += ptrace.h
-header-y += resource.h
-header-y += sembuf.h
-header-y += setup.h
-header-y += shmbuf.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
-header-y += stat.h
-header-y += statfs.h
-header-y += swab.h
-header-y += termbits.h
-header-y += termios.h
-header-y += types.h
-header-y += unistd.h
diff --git a/arch/h8300/include/uapi/asm/auxvec.h b/arch/h8300/include/uapi/asm/auxvec.h
deleted file mode 100644
index 1d36fe38..0000000
--- a/arch/h8300/include/uapi/asm/auxvec.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __ASMH8300_AUXVEC_H
-#define __ASMH8300_AUXVEC_H
-
-#endif
diff --git a/arch/h8300/include/uapi/asm/bitsperlong.h b/arch/h8300/include/uapi/asm/bitsperlong.h
deleted file mode 100644
index 6dc0bb0..0000000
--- a/arch/h8300/include/uapi/asm/bitsperlong.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/bitsperlong.h>
diff --git a/arch/h8300/include/uapi/asm/byteorder.h b/arch/h8300/include/uapi/asm/byteorder.h
deleted file mode 100644
index 13539da..0000000
--- a/arch/h8300/include/uapi/asm/byteorder.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_BYTEORDER_H
-#define _H8300_BYTEORDER_H
-
-#include <linux/byteorder/big_endian.h>
-
-#endif /* _H8300_BYTEORDER_H */
diff --git a/arch/h8300/include/uapi/asm/errno.h b/arch/h8300/include/uapi/asm/errno.h
deleted file mode 100644
index 0c2f564..0000000
--- a/arch/h8300/include/uapi/asm/errno.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_ERRNO_H
-#define _H8300_ERRNO_H
-
-#include <asm-generic/errno.h>
-
-#endif /* _H8300_ERRNO_H */
diff --git a/arch/h8300/include/uapi/asm/fcntl.h b/arch/h8300/include/uapi/asm/fcntl.h
deleted file mode 100644
index 1952cb2e..0000000
--- a/arch/h8300/include/uapi/asm/fcntl.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _H8300_FCNTL_H
-#define _H8300_FCNTL_H
-
-#define O_DIRECTORY	040000	/* must be a directory */
-#define O_NOFOLLOW	0100000	/* don't follow links */
-#define O_DIRECT	0200000	/* direct disk access hint - currently ignored */
-#define O_LARGEFILE	0400000
-
-#include <asm-generic/fcntl.h>
-
-#endif /* _H8300_FCNTL_H */
diff --git a/arch/h8300/include/uapi/asm/ioctl.h b/arch/h8300/include/uapi/asm/ioctl.h
deleted file mode 100644
index b279fe0..0000000
--- a/arch/h8300/include/uapi/asm/ioctl.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctl.h>
diff --git a/arch/h8300/include/uapi/asm/ioctls.h b/arch/h8300/include/uapi/asm/ioctls.h
deleted file mode 100644
index 30eaed2..0000000
--- a/arch/h8300/include/uapi/asm/ioctls.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __ARCH_H8300_IOCTLS_H__
-#define __ARCH_H8300_IOCTLS_H__
-
-#define FIOQSIZE	0x545E
-
-#include <asm-generic/ioctls.h>
-
-#endif /* __ARCH_H8300_IOCTLS_H__ */
diff --git a/arch/h8300/include/uapi/asm/ipcbuf.h b/arch/h8300/include/uapi/asm/ipcbuf.h
deleted file mode 100644
index 84c7e51..0000000
--- a/arch/h8300/include/uapi/asm/ipcbuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipcbuf.h>
diff --git a/arch/h8300/include/uapi/asm/kvm_para.h b/arch/h8300/include/uapi/asm/kvm_para.h
deleted file mode 100644
index 14fab8f..0000000
--- a/arch/h8300/include/uapi/asm/kvm_para.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kvm_para.h>
diff --git a/arch/h8300/include/uapi/asm/mman.h b/arch/h8300/include/uapi/asm/mman.h
deleted file mode 100644
index 8eebf89..0000000
--- a/arch/h8300/include/uapi/asm/mman.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/mman.h>
diff --git a/arch/h8300/include/uapi/asm/msgbuf.h b/arch/h8300/include/uapi/asm/msgbuf.h
deleted file mode 100644
index 6b148cd..0000000
--- a/arch/h8300/include/uapi/asm/msgbuf.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef _H8300_MSGBUF_H
-#define _H8300_MSGBUF_H
-
-/* 
- * The msqid64_ds structure for H8/300 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct msqid64_ds {
-	struct ipc64_perm msg_perm;
-	__kernel_time_t msg_stime;	/* last msgsnd time */
-	unsigned long	__unused1;
-	__kernel_time_t msg_rtime;	/* last msgrcv time */
-	unsigned long	__unused2;
-	__kernel_time_t msg_ctime;	/* last change time */
-	unsigned long	__unused3;
-	unsigned long  msg_cbytes;	/* current number of bytes on queue */
-	unsigned long  msg_qnum;	/* number of messages in queue */
-	unsigned long  msg_qbytes;	/* max number of bytes on queue */
-	__kernel_pid_t msg_lspid;	/* pid of last msgsnd */
-	__kernel_pid_t msg_lrpid;	/* last receive pid */
-	unsigned long  __unused4;
-	unsigned long  __unused5;
-};
-
-#endif /* _H8300_MSGBUF_H */
diff --git a/arch/h8300/include/uapi/asm/param.h b/arch/h8300/include/uapi/asm/param.h
deleted file mode 100644
index 3dd18ae..0000000
--- a/arch/h8300/include/uapi/asm/param.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _UAPI_H8300_PARAM_H
-#define _UAPI_H8300_PARAM_H
-
-#ifndef __KERNEL__
-#define HZ		100
-#endif
-
-#define EXEC_PAGESIZE	4096
-
-#ifndef NOGROUP
-#define NOGROUP		(-1)
-#endif
-
-#define MAXHOSTNAMELEN	64	/* max length of hostname */
-
-#endif /* _UAPI_H8300_PARAM_H */
diff --git a/arch/h8300/include/uapi/asm/poll.h b/arch/h8300/include/uapi/asm/poll.h
deleted file mode 100644
index f61540c..0000000
--- a/arch/h8300/include/uapi/asm/poll.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __H8300_POLL_H
-#define __H8300_POLL_H
-
-#define POLLWRNORM	POLLOUT
-#define POLLWRBAND	256
-
-#include <asm-generic/poll.h>
-
-#undef POLLREMOVE
-
-#endif
diff --git a/arch/h8300/include/uapi/asm/posix_types.h b/arch/h8300/include/uapi/asm/posix_types.h
deleted file mode 100644
index 91e62ba..0000000
--- a/arch/h8300/include/uapi/asm/posix_types.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef __ARCH_H8300_POSIX_TYPES_H
-#define __ARCH_H8300_POSIX_TYPES_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc.  Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned short	__kernel_mode_t;
-#define __kernel_mode_t __kernel_mode_t
-
-typedef unsigned short	__kernel_ipc_pid_t;
-#define __kernel_ipc_pid_t __kernel_ipc_pid_t
-
-typedef unsigned short	__kernel_uid_t;
-typedef unsigned short	__kernel_gid_t;
-#define __kernel_uid_t __kernel_uid_t
-
-typedef unsigned short	__kernel_old_uid_t;
-typedef unsigned short	__kernel_old_gid_t;
-#define __kernel_old_uid_t __kernel_old_uid_t
-
-#include <asm-generic/posix_types.h>
-
-#endif
diff --git a/arch/h8300/include/uapi/asm/ptrace.h b/arch/h8300/include/uapi/asm/ptrace.h
deleted file mode 100644
index ef39ec5..0000000
--- a/arch/h8300/include/uapi/asm/ptrace.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef _UAPI_H8300_PTRACE_H
-#define _UAPI_H8300_PTRACE_H
-
-#ifndef __ASSEMBLY__
-
-#define PT_ER1	   0
-#define PT_ER2	   1
-#define PT_ER3	   2
-#define PT_ER4	   3
-#define PT_ER5	   4
-#define PT_ER6	   5
-#define PT_ER0	   6
-#define PT_ORIG_ER0	   7
-#define PT_CCR	   8
-#define PT_PC	   9
-#define PT_USP	   10
-#define PT_EXR     12
-
-/* this struct defines the way the registers are stored on the
-   stack during a system call. */
-
-struct pt_regs {
-	long     retpc;
-	long     er4;
-	long     er5;
-	long     er6;
-	long     er3;
-	long     er2;
-	long     er1;
-	long     orig_er0;
-	unsigned short ccr;
-	long     er0;
-	long     vector;
-#if defined(CONFIG_CPU_H8S)
-	unsigned short exr;
-#endif
-	unsigned long  pc;
-} __attribute__((aligned(2),packed));
-
-#define PTRACE_GETREGS            12
-#define PTRACE_SETREGS            13
-
-#endif /* __ASSEMBLY__ */
-#endif /* _UAPI_H8300_PTRACE_H */
diff --git a/arch/h8300/include/uapi/asm/resource.h b/arch/h8300/include/uapi/asm/resource.h
deleted file mode 100644
index 46c5f43..0000000
--- a/arch/h8300/include/uapi/asm/resource.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_RESOURCE_H
-#define _H8300_RESOURCE_H
-
-#include <asm-generic/resource.h>
-
-#endif /* _H8300_RESOURCE_H */
diff --git a/arch/h8300/include/uapi/asm/sembuf.h b/arch/h8300/include/uapi/asm/sembuf.h
deleted file mode 100644
index e04a3ec..0000000
--- a/arch/h8300/include/uapi/asm/sembuf.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef _H8300_SEMBUF_H
-#define _H8300_SEMBUF_H
-
-/* 
- * The semid64_ds structure for m68k architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct semid64_ds {
-	struct ipc64_perm sem_perm;		/* permissions .. see ipc.h */
-	__kernel_time_t	sem_otime;		/* last semop time */
-	unsigned long	__unused1;
-	__kernel_time_t	sem_ctime;		/* last change time */
-	unsigned long	__unused2;
-	unsigned long	sem_nsems;		/* no. of semaphores in array */
-	unsigned long	__unused3;
-	unsigned long	__unused4;
-};
-
-#endif /* _H8300_SEMBUF_H */
diff --git a/arch/h8300/include/uapi/asm/setup.h b/arch/h8300/include/uapi/asm/setup.h
deleted file mode 100644
index e2c600e..0000000
--- a/arch/h8300/include/uapi/asm/setup.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __H8300_SETUP_H
-#define __H8300_SETUP_H
-
-#define COMMAND_LINE_SIZE	512
-
-#endif
diff --git a/arch/h8300/include/uapi/asm/shmbuf.h b/arch/h8300/include/uapi/asm/shmbuf.h
deleted file mode 100644
index 64e7799..0000000
--- a/arch/h8300/include/uapi/asm/shmbuf.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef _H8300_SHMBUF_H
-#define _H8300_SHMBUF_H
-
-/* 
- * The shmid64_ds structure for m68k architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct shmid64_ds {
-	struct ipc64_perm	shm_perm;	/* operation perms */
-	size_t			shm_segsz;	/* size of segment (bytes) */
-	__kernel_time_t		shm_atime;	/* last attach time */
-	unsigned long		__unused1;
-	__kernel_time_t		shm_dtime;	/* last detach time */
-	unsigned long		__unused2;
-	__kernel_time_t		shm_ctime;	/* last change time */
-	unsigned long		__unused3;
-	__kernel_pid_t		shm_cpid;	/* pid of creator */
-	__kernel_pid_t		shm_lpid;	/* pid of last operator */
-	unsigned long		shm_nattch;	/* no. of current attaches */
-	unsigned long		__unused4;
-	unsigned long		__unused5;
-};
-
-struct shminfo64 {
-	unsigned long	shmmax;
-	unsigned long	shmmin;
-	unsigned long	shmmni;
-	unsigned long	shmseg;
-	unsigned long	shmall;
-	unsigned long	__unused1;
-	unsigned long	__unused2;
-	unsigned long	__unused3;
-	unsigned long	__unused4;
-};
-
-#endif /* _H8300_SHMBUF_H */
diff --git a/arch/h8300/include/uapi/asm/sigcontext.h b/arch/h8300/include/uapi/asm/sigcontext.h
deleted file mode 100644
index e4b8150..0000000
--- a/arch/h8300/include/uapi/asm/sigcontext.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef _ASM_H8300_SIGCONTEXT_H
-#define _ASM_H8300_SIGCONTEXT_H
-
-struct sigcontext {
-	unsigned long  sc_mask; 	/* old sigmask */
-	unsigned long  sc_usp;		/* old user stack pointer */
-	unsigned long  sc_er0;
-	unsigned long  sc_er1;
-	unsigned long  sc_er2;
-	unsigned long  sc_er3;
-	unsigned long  sc_er4;
-	unsigned long  sc_er5;
-	unsigned long  sc_er6;
-	unsigned short sc_ccr;
-	unsigned long  sc_pc;
-};
-
-#endif
diff --git a/arch/h8300/include/uapi/asm/siginfo.h b/arch/h8300/include/uapi/asm/siginfo.h
deleted file mode 100644
index bc8fbea..0000000
--- a/arch/h8300/include/uapi/asm/siginfo.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_SIGINFO_H
-#define _H8300_SIGINFO_H
-
-#include <asm-generic/siginfo.h>
-
-#endif
diff --git a/arch/h8300/include/uapi/asm/signal.h b/arch/h8300/include/uapi/asm/signal.h
deleted file mode 100644
index af3a6c3..0000000
--- a/arch/h8300/include/uapi/asm/signal.h
+++ /dev/null
@@ -1,115 +0,0 @@
-#ifndef _UAPI_H8300_SIGNAL_H
-#define _UAPI_H8300_SIGNAL_H
-
-#include <linux/types.h>
-
-/* Avoid too many header ordering problems.  */
-struct siginfo;
-
-#ifndef __KERNEL__
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-#define NSIG		32
-typedef unsigned long sigset_t;
-
-#endif /* __KERNEL__ */
-
-#define SIGHUP		 1
-#define SIGINT		 2
-#define SIGQUIT		 3
-#define SIGILL		 4
-#define SIGTRAP		 5
-#define SIGABRT		 6
-#define SIGIOT		 6
-#define SIGBUS		 7
-#define SIGFPE		 8
-#define SIGKILL		 9
-#define SIGUSR1		10
-#define SIGSEGV		11
-#define SIGUSR2		12
-#define SIGPIPE		13
-#define SIGALRM		14
-#define SIGTERM		15
-#define SIGSTKFLT	16
-#define SIGCHLD		17
-#define SIGCONT		18
-#define SIGSTOP		19
-#define SIGTSTP		20
-#define SIGTTIN		21
-#define SIGTTOU		22
-#define SIGURG		23
-#define SIGXCPU		24
-#define SIGXFSZ		25
-#define SIGVTALRM	26
-#define SIGPROF		27
-#define SIGWINCH	28
-#define SIGIO		29
-#define SIGPOLL		SIGIO
-/*
-#define SIGLOST		29
-*/
-#define SIGPWR		30
-#define SIGSYS		31
-#define	SIGUNUSED	31
-
-/* These should not be considered constants from userland.  */
-#define SIGRTMIN	32
-#define SIGRTMAX	_NSIG
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002 /* not supported yet */
-#define SA_SIGINFO	0x00000004
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
-#define SA_RESTORER	0x04000000
-
-#define MINSIGSTKSZ	2048
-#define SIGSTKSZ	8192
-
-#include <asm-generic/signal-defs.h>
-
-#ifndef __KERNEL__
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-struct sigaction {
-	union {
-	  __sighandler_t _sa_handler;
-	  void (*_sa_sigaction)(int, struct siginfo *, void *);
-	} _u;
-	sigset_t sa_mask;
-	unsigned long sa_flags;
-	void (*sa_restorer)(void);
-};
-
-#define sa_handler	_u._sa_handler
-#define sa_sigaction	_u._sa_sigaction
-
-#endif /* __KERNEL__ */
-
-typedef struct sigaltstack {
-	void *ss_sp;
-	int ss_flags;
-	size_t ss_size;
-} stack_t;
-
-
-#endif /* _UAPI_H8300_SIGNAL_H */
diff --git a/arch/h8300/include/uapi/asm/socket.h b/arch/h8300/include/uapi/asm/socket.h
deleted file mode 100644
index 9490758..0000000
--- a/arch/h8300/include/uapi/asm/socket.h
+++ /dev/null
@@ -1,79 +0,0 @@
-#ifndef _ASM_SOCKET_H
-#define _ASM_SOCKET_H
-
-#include <asm/sockios.h>
-
-/* For setsockoptions(2) */
-#define SOL_SOCKET	1
-
-#define SO_DEBUG	1
-#define SO_REUSEADDR	2
-#define SO_TYPE		3
-#define SO_ERROR	4
-#define SO_DONTROUTE	5
-#define SO_BROADCAST	6
-#define SO_SNDBUF	7
-#define SO_RCVBUF	8
-#define SO_SNDBUFFORCE	32
-#define SO_RCVBUFFORCE	33
-#define SO_KEEPALIVE	9
-#define SO_OOBINLINE	10
-#define SO_NO_CHECK	11
-#define SO_PRIORITY	12
-#define SO_LINGER	13
-#define SO_BSDCOMPAT	14
-#define SO_REUSEPORT	15
-#define SO_PASSCRED	16
-#define SO_PEERCRED	17
-#define SO_RCVLOWAT	18
-#define SO_SNDLOWAT	19
-#define SO_RCVTIMEO	20
-#define SO_SNDTIMEO	21
-
-/* Security levels - as per NRL IPv6 - don't actually do anything */
-#define SO_SECURITY_AUTHENTICATION		22
-#define SO_SECURITY_ENCRYPTION_TRANSPORT	23
-#define SO_SECURITY_ENCRYPTION_NETWORK		24
-
-#define SO_BINDTODEVICE	25
-
-/* Socket filtering */
-#define SO_ATTACH_FILTER        26
-#define SO_DETACH_FILTER        27
-#define SO_GET_FILTER		SO_ATTACH_FILTER
-
-#define SO_PEERNAME             28
-#define SO_TIMESTAMP		29
-#define SCM_TIMESTAMP		SO_TIMESTAMP
-
-#define SO_ACCEPTCONN		30
-
-#define SO_PEERSEC		31
-#define SO_PASSSEC		34
-#define SO_TIMESTAMPNS		35
-#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
-
-#define SO_MARK			36
-
-#define SO_TIMESTAMPING		37
-#define SCM_TIMESTAMPING	SO_TIMESTAMPING
-
-#define SO_PROTOCOL		38
-#define SO_DOMAIN		39
-
-#define SO_RXQ_OVFL             40
-
-#define SO_WIFI_STATUS		41
-#define SCM_WIFI_STATUS		SO_WIFI_STATUS
-#define SO_PEEK_OFF		42
-
-/* Instruct lower device to use last 4-bytes of skb data as FCS */
-#define SO_NOFCS		43
-
-#define SO_LOCK_FILTER		44
-
-#define SO_SELECT_ERR_QUEUE	45
-
-#define SO_BUSY_POLL		46
-
-#endif /* _ASM_SOCKET_H */
diff --git a/arch/h8300/include/uapi/asm/sockios.h b/arch/h8300/include/uapi/asm/sockios.h
deleted file mode 100644
index e9c7ec8..0000000
--- a/arch/h8300/include/uapi/asm/sockios.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ARCH_H8300_SOCKIOS__
-#define __ARCH_H8300_SOCKIOS__
-
-/* Socket-level I/O control calls. */
-#define FIOSETOWN 	0x8901
-#define SIOCSPGRP	0x8902
-#define FIOGETOWN	0x8903
-#define SIOCGPGRP	0x8904
-#define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
-#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
-
-#endif /* __ARCH_H8300_SOCKIOS__ */
diff --git a/arch/h8300/include/uapi/asm/stat.h b/arch/h8300/include/uapi/asm/stat.h
deleted file mode 100644
index 62c3cc2..0000000
--- a/arch/h8300/include/uapi/asm/stat.h
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef _H8300_STAT_H
-#define _H8300_STAT_H
-
-struct __old_kernel_stat {
-	unsigned short st_dev;
-	unsigned short st_ino;
-	unsigned short st_mode;
-	unsigned short st_nlink;
-	unsigned short st_uid;
-	unsigned short st_gid;
-	unsigned short st_rdev;
-	unsigned long  st_size;
-	unsigned long  st_atime;
-	unsigned long  st_mtime;
-	unsigned long  st_ctime;
-};
-
-struct stat {
-	unsigned short st_dev;
-	unsigned short __pad1;
-	unsigned long st_ino;
-	unsigned short st_mode;
-	unsigned short st_nlink;
-	unsigned short st_uid;
-	unsigned short st_gid;
-	unsigned short st_rdev;
-	unsigned short __pad2;
-	unsigned long  st_size;
-	unsigned long  st_blksize;
-	unsigned long  st_blocks;
-	unsigned long  st_atime;
-	unsigned long  __unused1;
-	unsigned long  st_mtime;
-	unsigned long  __unused2;
-	unsigned long  st_ctime;
-	unsigned long  __unused3;
-	unsigned long  __unused4;
-	unsigned long  __unused5;
-};
-
-/* This matches struct stat64 in glibc2.1, hence the absolutely
- * insane amounts of padding around dev_t's.
- */
-struct stat64 {
-	unsigned long long	st_dev;
-	unsigned char	__pad1[2];
-
-#define STAT64_HAS_BROKEN_ST_INO	1
-	unsigned long	__st_ino;
-
-	unsigned int	st_mode;
-	unsigned int	st_nlink;
-
-	unsigned long	st_uid;
-	unsigned long	st_gid;
-
-	unsigned long long	st_rdev;
-	unsigned char	__pad3[2];
-
-	long long	st_size;
-	unsigned long	st_blksize;
-
-	unsigned long	__pad4;		/* future possible st_blocks high bits */
-	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
-
-	unsigned long	st_atime;
-	unsigned long	st_atime_nsec;
-
-	unsigned long	st_mtime;
-	unsigned long	st_mtime_nsec;
-
-	unsigned long	st_ctime;
-	unsigned long	st_ctime_nsec;
-
-	unsigned long long	st_ino;
-};
-
-#endif /* _H8300_STAT_H */
diff --git a/arch/h8300/include/uapi/asm/statfs.h b/arch/h8300/include/uapi/asm/statfs.h
deleted file mode 100644
index b96efa7..0000000
--- a/arch/h8300/include/uapi/asm/statfs.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_STATFS_H
-#define _H8300_STATFS_H
-
-#include <asm-generic/statfs.h>
-
-#endif /* _H8300_STATFS_H */
diff --git a/arch/h8300/include/uapi/asm/swab.h b/arch/h8300/include/uapi/asm/swab.h
deleted file mode 100644
index 39abbf5..0000000
--- a/arch/h8300/include/uapi/asm/swab.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _H8300_SWAB_H
-#define _H8300_SWAB_H
-
-#include <linux/types.h>
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
-#  define __SWAB_64_THRU_32__
-#endif
-
-#endif /* _H8300_SWAB_H */
diff --git a/arch/h8300/include/uapi/asm/termbits.h b/arch/h8300/include/uapi/asm/termbits.h
deleted file mode 100644
index 3287a62..0000000
--- a/arch/h8300/include/uapi/asm/termbits.h
+++ /dev/null
@@ -1,201 +0,0 @@
-#ifndef __ARCH_H8300_TERMBITS_H__
-#define __ARCH_H8300_TERMBITS_H__
-
-#include <linux/posix_types.h>
-
-typedef unsigned char	cc_t;
-typedef unsigned int	speed_t;
-typedef unsigned int	tcflag_t;
-
-#define NCCS 19
-struct termios {
-	tcflag_t c_iflag;		/* input mode flags */
-	tcflag_t c_oflag;		/* output mode flags */
-	tcflag_t c_cflag;		/* control mode flags */
-	tcflag_t c_lflag;		/* local mode flags */
-	cc_t c_line;			/* line discipline */
-	cc_t c_cc[NCCS];		/* control characters */
-};
-
-struct termios2 {
-	tcflag_t c_iflag;		/* input mode flags */
-	tcflag_t c_oflag;		/* output mode flags */
-	tcflag_t c_cflag;		/* control mode flags */
-	tcflag_t c_lflag;		/* local mode flags */
-	cc_t c_line;			/* line discipline */
-	cc_t c_cc[NCCS];		/* control characters */
-	speed_t c_ispeed;		/* input speed */
-	speed_t c_ospeed;		/* output speed */
-};
-
-struct ktermios {
-	tcflag_t c_iflag;		/* input mode flags */
-	tcflag_t c_oflag;		/* output mode flags */
-	tcflag_t c_cflag;		/* control mode flags */
-	tcflag_t c_lflag;		/* local mode flags */
-	cc_t c_line;			/* line discipline */
-	cc_t c_cc[NCCS];		/* control characters */
-	speed_t c_ispeed;		/* input speed */
-	speed_t c_ospeed;		/* output speed */
-};
-
-/* c_cc characters */
-#define VINTR 0
-#define VQUIT 1
-#define VERASE 2
-#define VKILL 3
-#define VEOF 4
-#define VTIME 5
-#define VMIN 6
-#define VSWTC 7
-#define VSTART 8
-#define VSTOP 9
-#define VSUSP 10
-#define VEOL 11
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE 14
-#define VLNEXT 15
-#define VEOL2 16
-
-
-/* c_iflag bits */
-#define IGNBRK	0000001
-#define BRKINT	0000002
-#define IGNPAR	0000004
-#define PARMRK	0000010
-#define INPCK	0000020
-#define ISTRIP	0000040
-#define INLCR	0000100
-#define IGNCR	0000200
-#define ICRNL	0000400
-#define IUCLC	0001000
-#define IXON	0002000
-#define IXANY	0004000
-#define IXOFF	0010000
-#define IMAXBEL	0020000
-#define IUTF8	0040000
-
-/* c_oflag bits */
-#define OPOST	0000001
-#define OLCUC	0000002
-#define ONLCR	0000004
-#define OCRNL	0000010
-#define ONOCR	0000020
-#define ONLRET	0000040
-#define OFILL	0000100
-#define OFDEL	0000200
-#define NLDLY	0000400
-#define   NL0	0000000
-#define   NL1	0000400
-#define CRDLY	0003000
-#define   CR0	0000000
-#define   CR1	0001000
-#define   CR2	0002000
-#define   CR3	0003000
-#define TABDLY	0014000
-#define   TAB0	0000000
-#define   TAB1	0004000
-#define   TAB2	0010000
-#define   TAB3	0014000
-#define   XTABS	0014000
-#define BSDLY	0020000
-#define   BS0	0000000
-#define   BS1	0020000
-#define VTDLY	0040000
-#define   VT0	0000000
-#define   VT1	0040000
-#define FFDLY	0100000
-#define   FF0	0000000
-#define   FF1	0100000
-
-/* c_cflag bit meaning */
-#define CBAUD	0010017
-#define  B0	0000000		/* hang up */
-#define  B50	0000001
-#define  B75	0000002
-#define  B110	0000003
-#define  B134	0000004
-#define  B150	0000005
-#define  B200	0000006
-#define  B300	0000007
-#define  B600	0000010
-#define  B1200	0000011
-#define  B1800	0000012
-#define  B2400	0000013
-#define  B4800	0000014
-#define  B9600	0000015
-#define  B19200	0000016
-#define  B38400	0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE	0000060
-#define   CS5	0000000
-#define   CS6	0000020
-#define   CS7	0000040
-#define   CS8	0000060
-#define CSTOPB	0000100
-#define CREAD	0000200
-#define PARENB	0000400
-#define PARODD	0001000
-#define HUPCL	0002000
-#define CLOCAL	0004000
-#define CBAUDEX 0010000
-#define    BOTHER 0010000
-#define    B57600 0010001
-#define   B115200 0010002
-#define   B230400 0010003
-#define   B460800 0010004
-#define   B500000 0010005
-#define   B576000 0010006
-#define   B921600 0010007
-#define  B1000000 0010010
-#define  B1152000 0010011
-#define  B1500000 0010012
-#define  B2000000 0010013
-#define  B2500000 0010014
-#define  B3000000 0010015
-#define  B3500000 0010016
-#define  B4000000 0010017
-#define CIBAUD	  002003600000		/* input baud rate */
-#define CMSPAR	  010000000000		/* mark or space (stick) parity */
-#define CRTSCTS	  020000000000		/* flow control */
-
-#define IBSHIFT	  16			/* shift from CBAUD to CIBAUD */
-
-/* c_lflag bits */
-#define ISIG	0000001
-#define ICANON	0000002
-#define XCASE	0000004
-#define ECHO	0000010
-#define ECHOE	0000020
-#define ECHOK	0000040
-#define ECHONL	0000100
-#define NOFLSH	0000200
-#define TOSTOP	0000400
-#define ECHOCTL	0001000
-#define ECHOPRT	0002000
-#define ECHOKE	0004000
-#define FLUSHO	0010000
-#define PENDIN	0040000
-#define IEXTEN	0100000
-#define EXTPROC	0200000
-
-
-/* tcflow() and TCXONC use these */
-#define	TCOOFF		0
-#define	TCOON		1
-#define	TCIOFF		2
-#define	TCION		3
-
-/* tcflush() and TCFLSH use these */
-#define	TCIFLUSH	0
-#define	TCOFLUSH	1
-#define	TCIOFLUSH	2
-
-/* tcsetattr uses these */
-#define	TCSANOW		0
-#define	TCSADRAIN	1
-#define	TCSAFLUSH	2
-
-#endif /* __ARCH_H8300_TERMBITS_H__ */
diff --git a/arch/h8300/include/uapi/asm/termios.h b/arch/h8300/include/uapi/asm/termios.h
deleted file mode 100644
index 5a67d7e..0000000
--- a/arch/h8300/include/uapi/asm/termios.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef _UAPI_H8300_TERMIOS_H
-#define _UAPI_H8300_TERMIOS_H
-
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
- 
-struct winsize {
-	unsigned short ws_row;
-	unsigned short ws_col;
-	unsigned short ws_xpixel;
-	unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
-	unsigned short c_iflag;		/* input mode flags */
-	unsigned short c_oflag;		/* output mode flags */
-	unsigned short c_cflag;		/* control mode flags */
-	unsigned short c_lflag;		/* local mode flags */
-	unsigned char c_line;		/* line discipline */
-	unsigned char c_cc[NCC];	/* control characters */
-};
-
-
-/* modem lines */
-#define TIOCM_LE	0x001
-#define TIOCM_DTR	0x002
-#define TIOCM_RTS	0x004
-#define TIOCM_ST	0x008
-#define TIOCM_SR	0x010
-#define TIOCM_CTS	0x020
-#define TIOCM_CAR	0x040
-#define TIOCM_RNG	0x080
-#define TIOCM_DSR	0x100
-#define TIOCM_CD	TIOCM_CAR
-#define TIOCM_RI	TIOCM_RNG
-#define TIOCM_OUT1	0x2000
-#define TIOCM_OUT2	0x4000
-#define TIOCM_LOOP	0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-
-#endif /* _UAPI_H8300_TERMIOS_H */
diff --git a/arch/h8300/include/uapi/asm/types.h b/arch/h8300/include/uapi/asm/types.h
deleted file mode 100644
index 9ec9d4c..0000000
--- a/arch/h8300/include/uapi/asm/types.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/int-ll64.h>
diff --git a/arch/h8300/include/uapi/asm/unistd.h b/arch/h8300/include/uapi/asm/unistd.h
deleted file mode 100644
index 8cb5d42..0000000
--- a/arch/h8300/include/uapi/asm/unistd.h
+++ /dev/null
@@ -1,330 +0,0 @@
-#ifndef _UAPI_ASM_H8300_UNISTD_H_
-#define _UAPI_ASM_H8300_UNISTD_H_
-
-/*
- * This file contains the system call numbers.
- */
-
-#define __NR_restart_syscall      0
-#define __NR_exit		  1
-#define __NR_fork		  2
-#define __NR_read		  3
-#define __NR_write		  4
-#define __NR_open		  5
-#define __NR_close		  6
-#define __NR_waitpid		  7
-#define __NR_creat		  8
-#define __NR_link		  9
-#define __NR_unlink		 10
-#define __NR_execve		 11
-#define __NR_chdir		 12
-#define __NR_time		 13
-#define __NR_mknod		 14
-#define __NR_chmod		 15
-#define __NR_lchown		 16
-#define __NR_break		 17
-#define __NR_oldstat		 18
-#define __NR_lseek		 19
-#define __NR_getpid		 20
-#define __NR_mount		 21
-#define __NR_umount		 22
-#define __NR_setuid		 23
-#define __NR_getuid		 24
-#define __NR_stime		 25
-#define __NR_ptrace		 26
-#define __NR_alarm		 27
-#define __NR_oldfstat		 28
-#define __NR_pause		 29
-#define __NR_utime		 30
-#define __NR_stty		 31
-#define __NR_gtty		 32
-#define __NR_access		 33
-#define __NR_nice		 34
-#define __NR_ftime		 35
-#define __NR_sync		 36
-#define __NR_kill		 37
-#define __NR_rename		 38
-#define __NR_mkdir		 39
-#define __NR_rmdir		 40
-#define __NR_dup		 41
-#define __NR_pipe		 42
-#define __NR_times		 43
-#define __NR_prof		 44
-#define __NR_brk		 45
-#define __NR_setgid		 46
-#define __NR_getgid		 47
-#define __NR_signal		 48
-#define __NR_geteuid		 49
-#define __NR_getegid		 50
-#define __NR_acct		 51
-#define __NR_umount2		 52
-#define __NR_lock		 53
-#define __NR_ioctl		 54
-#define __NR_fcntl		 55
-#define __NR_mpx		 56
-#define __NR_setpgid		 57
-#define __NR_ulimit		 58
-#define __NR_oldolduname	 59
-#define __NR_umask		 60
-#define __NR_chroot		 61
-#define __NR_ustat		 62
-#define __NR_dup2		 63
-#define __NR_getppid		 64
-#define __NR_getpgrp		 65
-#define __NR_setsid		 66
-#define __NR_sigaction		 67
-#define __NR_sgetmask		 68
-#define __NR_ssetmask		 69
-#define __NR_setreuid		 70
-#define __NR_setregid		 71
-#define __NR_sigsuspend		 72
-#define __NR_sigpending		 73
-#define __NR_sethostname	 74
-#define __NR_setrlimit		 75
-#define __NR_getrlimit		 76
-#define __NR_getrusage		 77
-#define __NR_gettimeofday	 78
-#define __NR_settimeofday	 79
-#define __NR_getgroups		 80
-#define __NR_setgroups		 81
-#define __NR_select		 82
-#define __NR_symlink		 83
-#define __NR_oldlstat		 84
-#define __NR_readlink		 85
-#define __NR_uselib		 86
-#define __NR_swapon		 87
-#define __NR_reboot		 88
-#define __NR_readdir		 89
-#define __NR_mmap		 90
-#define __NR_munmap		 91
-#define __NR_truncate		 92
-#define __NR_ftruncate		 93
-#define __NR_fchmod		 94
-#define __NR_fchown		 95
-#define __NR_getpriority	 96
-#define __NR_setpriority	 97
-#define __NR_profil		 98
-#define __NR_statfs		 99
-#define __NR_fstatfs		100
-#define __NR_ioperm		101
-#define __NR_socketcall		102
-#define __NR_syslog		103
-#define __NR_setitimer		104
-#define __NR_getitimer		105
-#define __NR_stat		106
-#define __NR_lstat		107
-#define __NR_fstat		108
-#define __NR_olduname		109
-#define __NR_iopl		110
-#define __NR_vhangup		111
-#define __NR_idle		112
-#define __NR_vm86old		113
-#define __NR_wait4		114
-#define __NR_swapoff		115
-#define __NR_sysinfo		116
-#define __NR_ipc		117
-#define __NR_fsync		118
-#define __NR_sigreturn		119
-#define __NR_clone		120
-#define __NR_setdomainname	121
-#define __NR_uname		122
-#define __NR_modify_ldt		123
-#define __NR_adjtimex		124
-#define __NR_mprotect		125
-#define __NR_sigprocmask	126
-#define __NR_create_module	127
-#define __NR_init_module	128
-#define __NR_delete_module	129
-#define __NR_get_kernel_syms	130
-#define __NR_quotactl		131
-#define __NR_getpgid		132
-#define __NR_fchdir		133
-#define __NR_bdflush		134
-#define __NR_sysfs		135
-#define __NR_personality	136
-#define __NR_afs_syscall	137 /* Syscall for Andrew File System */
-#define __NR_setfsuid		138
-#define __NR_setfsgid		139
-#define __NR__llseek		140
-#define __NR_getdents		141
-#define __NR__newselect		142
-#define __NR_flock		143
-#define __NR_msync		144
-#define __NR_readv		145
-#define __NR_writev		146
-#define __NR_getsid		147
-#define __NR_fdatasync		148
-#define __NR__sysctl		149
-#define __NR_mlock		150
-#define __NR_munlock		151
-#define __NR_mlockall		152
-#define __NR_munlockall		153
-#define __NR_sched_setparam		154
-#define __NR_sched_getparam		155
-#define __NR_sched_setscheduler		156
-#define __NR_sched_getscheduler		157
-#define __NR_sched_yield		158
-#define __NR_sched_get_priority_max	159
-#define __NR_sched_get_priority_min	160
-#define __NR_sched_rr_get_interval	161
-#define __NR_nanosleep		162
-#define __NR_mremap		163
-#define __NR_setresuid		164
-#define __NR_getresuid		165
-#define __NR_vm86		166
-#define __NR_query_module	167
-#define __NR_poll		168
-#define __NR_nfsservctl		169
-#define __NR_setresgid		170
-#define __NR_getresgid		171
-#define __NR_prctl		172
-#define __NR_rt_sigreturn	173
-#define __NR_rt_sigaction	174
-#define __NR_rt_sigprocmask	175
-#define __NR_rt_sigpending	176
-#define __NR_rt_sigtimedwait	177
-#define __NR_rt_sigqueueinfo	178
-#define __NR_rt_sigsuspend	179
-#define __NR_pread64		180
-#define __NR_pwrite64		181
-#define __NR_chown		182
-#define __NR_getcwd		183
-#define __NR_capget		184
-#define __NR_capset		185
-#define __NR_sigaltstack	186
-#define __NR_sendfile		187
-#define __NR_getpmsg		188	/* some people actually want streams */
-#define __NR_putpmsg		189	/* some people actually want streams */
-#define __NR_vfork		190
-#define __NR_ugetrlimit		191
-#define __NR_mmap2		192
-#define __NR_truncate64		193
-#define __NR_ftruncate64	194
-#define __NR_stat64		195
-#define __NR_lstat64		196
-#define __NR_fstat64		197
-#define __NR_lchown32		198
-#define __NR_getuid32		199
-#define __NR_getgid32		200
-#define __NR_geteuid32		201
-#define __NR_getegid32		202
-#define __NR_setreuid32		203
-#define __NR_setregid32		204
-#define __NR_getgroups32	205
-#define __NR_setgroups32	206
-#define __NR_fchown32		207
-#define __NR_setresuid32	208
-#define __NR_getresuid32	209
-#define __NR_setresgid32	210
-#define __NR_getresgid32	211
-#define __NR_chown32		212
-#define __NR_setuid32		213
-#define __NR_setgid32		214
-#define __NR_setfsuid32		215
-#define __NR_setfsgid32		216
-#define __NR_pivot_root		217
-#define __NR_mincore		218
-#define __NR_madvise		219
-#define __NR_madvise1		219
-#define __NR_getdents64		220
-#define __NR_fcntl64		221
-/* 223 is unused */
-#define __NR_gettid		224
-#define __NR_readahead		225
-#define __NR_setxattr		226
-#define __NR_lsetxattr		227
-#define __NR_fsetxattr		228
-#define __NR_getxattr		229
-#define __NR_lgetxattr		230
-#define __NR_fgetxattr		231
-#define __NR_listxattr		232
-#define __NR_llistxattr		233
-#define __NR_flistxattr		234
-#define __NR_removexattr	235
-#define __NR_lremovexattr	236
-#define __NR_fremovexattr	237
-#define __NR_tkill		238
-#define __NR_sendfile64		239
-#define __NR_futex		240
-#define __NR_sched_setaffinity	241
-#define __NR_sched_getaffinity	242
-#define __NR_set_thread_area	243
-#define __NR_get_thread_area	244
-#define __NR_io_setup		245
-#define __NR_io_destroy		246
-#define __NR_io_getevents	247
-#define __NR_io_submit		248
-#define __NR_io_cancel		249
-#define __NR_fadvise64		250
-/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
-#define __NR_exit_group		252
-#define __NR_lookup_dcookie	253
-#define __NR_epoll_create	254
-#define __NR_epoll_ctl		255
-#define __NR_epoll_wait		256
-#define __NR_remap_file_pages	257
-#define __NR_set_tid_address	258
-#define __NR_timer_create	259
-#define __NR_timer_settime	(__NR_timer_create+1)
-#define __NR_timer_gettime	(__NR_timer_create+2)
-#define __NR_timer_getoverrun	(__NR_timer_create+3)
-#define __NR_timer_delete	(__NR_timer_create+4)
-#define __NR_clock_settime	(__NR_timer_create+5)
-#define __NR_clock_gettime	(__NR_timer_create+6)
-#define __NR_clock_getres	(__NR_timer_create+7)
-#define __NR_clock_nanosleep	(__NR_timer_create+8)
-#define __NR_statfs64		268
-#define __NR_fstatfs64		269
-#define __NR_tgkill		270
-#define __NR_utimes		271
-#define __NR_fadvise64_64	272
-#define __NR_vserver		273
-#define __NR_mbind		274
-#define __NR_get_mempolicy	275
-#define __NR_set_mempolicy	276
-#define __NR_mq_open 		277
-#define __NR_mq_unlink		(__NR_mq_open+1)
-#define __NR_mq_timedsend	(__NR_mq_open+2)
-#define __NR_mq_timedreceive	(__NR_mq_open+3)
-#define __NR_mq_notify		(__NR_mq_open+4)
-#define __NR_mq_getsetattr	(__NR_mq_open+5)
-#define __NR_kexec_load		283
-#define __NR_waitid		284
-/* #define __NR_sys_setaltroot	285 */
-#define __NR_add_key		286
-#define __NR_request_key	287
-#define __NR_keyctl		288
-#define __NR_ioprio_set		289
-#define __NR_ioprio_get		290
-#define __NR_inotify_init	291
-#define __NR_inotify_add_watch	292
-#define __NR_inotify_rm_watch	293
-#define __NR_migrate_pages	294
-#define __NR_openat		295
-#define __NR_mkdirat		296
-#define __NR_mknodat		297
-#define __NR_fchownat		298
-#define __NR_futimesat		299
-#define __NR_fstatat64		300
-#define __NR_unlinkat		301
-#define __NR_renameat		302
-#define __NR_linkat		303
-#define __NR_symlinkat		304
-#define __NR_readlinkat		305
-#define __NR_fchmodat		306
-#define __NR_faccessat		307
-#define __NR_pselect6		308
-#define __NR_ppoll		309
-#define __NR_unshare		310
-#define __NR_set_robust_list	311
-#define __NR_get_robust_list	312
-#define __NR_splice		313
-#define __NR_sync_file_range	314
-#define __NR_tee		315
-#define __NR_vmsplice		316
-#define __NR_move_pages		317
-#define __NR_getcpu		318
-#define __NR_epoll_pwait	319
-#define __NR_setns		320
-
-#endif /* _UAPI_ASM_H8300_UNISTD_H_ */
diff --git a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile
deleted file mode 100644
index 1cc57f8..0000000
--- a/arch/h8300/kernel/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-extra-y := vmlinux.lds
-
-obj-y := process.o traps.o ptrace.o irq.o \
-	 sys_h8300.o time.o signal.o \
-         setup.o gpio.o syscalls.o \
-	 entry.o timer/
-
-obj-$(CONFIG_MODULES) += module.o h8300_ksyms.o 
diff --git a/arch/h8300/kernel/asm-offsets.c b/arch/h8300/kernel/asm-offsets.c
deleted file mode 100644
index fd961e0..0000000
--- a/arch/h8300/kernel/asm-offsets.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * This program is used to generate definitions needed by
- * assembly language modules.
- *
- * We use the technique used in the OSF Mach kernel code:
- * generate asm statements containing #defines,
- * compile this file to assembler, and then extract the
- * #defines from the assembly-language output.
- */
-
-#include <linux/stddef.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <linux/ptrace.h>
-#include <linux/hardirq.h>
-#include <linux/kbuild.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/ptrace.h>
-
-int main(void)
-{
-	/* offsets into the task struct */
-	DEFINE(TASK_STATE, offsetof(struct task_struct, state));
-	DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
-	DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
-	DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
-	DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
-	DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack));
-	DEFINE(TASK_MM, offsetof(struct task_struct, mm));
-	DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
-
-	/* offsets into the irq_cpustat_t struct */
-	DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
-
-	/* offsets into the thread struct */
-	DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
-	DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
-	DEFINE(THREAD_CCR, offsetof(struct thread_struct, ccr));
-
-	/* offsets into the pt_regs struct */
-	DEFINE(LER0,  offsetof(struct pt_regs, er0)      - sizeof(long));
-	DEFINE(LER1,  offsetof(struct pt_regs, er1)      - sizeof(long));
-	DEFINE(LER2,  offsetof(struct pt_regs, er2)      - sizeof(long));
-	DEFINE(LER3,  offsetof(struct pt_regs, er3)      - sizeof(long));
-	DEFINE(LER4,  offsetof(struct pt_regs, er4)      - sizeof(long));
-	DEFINE(LER5,  offsetof(struct pt_regs, er5)      - sizeof(long));
-	DEFINE(LER6,  offsetof(struct pt_regs, er6)      - sizeof(long));
-	DEFINE(LORIG, offsetof(struct pt_regs, orig_er0) - sizeof(long));
-	DEFINE(LCCR,  offsetof(struct pt_regs, ccr)      - sizeof(long));
-	DEFINE(LVEC,  offsetof(struct pt_regs, vector)   - sizeof(long));
-#if defined(__H8300S__)
-	DEFINE(LEXR,  offsetof(struct pt_regs, exr)      - sizeof(long));
-#endif
-	DEFINE(LRET,  offsetof(struct pt_regs, pc)       - sizeof(long));
-
-	DEFINE(PT_PTRACED, PT_PTRACED);
-
-	return 0;
-}
diff --git a/arch/h8300/kernel/entry.S b/arch/h8300/kernel/entry.S
deleted file mode 100644
index 94bd30f..0000000
--- a/arch/h8300/kernel/entry.S
+++ /dev/null
@@ -1,402 +0,0 @@
-/* -*- mode: asm -*-
- *
- *  linux/arch/h8300/platform/h8300h/entry.S
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *  David McCullough <davidm@snapgear.com>
- *
- */
-
-/*
- *  entry.S
- *  include exception/interrupt gateway
- *          system call entry
- */
-
-#include <linux/sys.h>
-#include <asm/unistd.h>
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/linkage.h>
-#include <asm/asm-offsets.h>
-#include <asm/thread_info.h>
-#include <asm/errno.h>
-
-#if defined(CONFIG_CPU_H8300H)
-#define USERRET 8
-INTERRUPTS = 64
-	.h8300h
-	.macro	SHLL2 reg
-	shll.l	\reg
-	shll.l	\reg
-	.endm
-	.macro	SHLR2 reg
-	shlr.l	\reg
-	shlr.l	\reg
-	.endm
-	.macro	SAVEREGS
-	mov.l	er0,@-sp
-	mov.l	er1,@-sp
-	mov.l	er2,@-sp
-	mov.l	er3,@-sp
-	.endm
-	.macro	RESTOREREGS
-	mov.l	@sp+,er3
-	mov.l	@sp+,er2
-	.endm
-	.macro	SAVEEXR
-	.endm
-	.macro	RESTOREEXR
-	.endm
-#endif
-#if defined(CONFIG_CPU_H8S)
-#define USERRET 10
-#define USEREXR 8
-INTERRUPTS = 128
-	.h8300s
-	.macro	SHLL2 reg
-	shll.l	#2,\reg
-	.endm
-	.macro	SHLR2 reg
-	shlr.l	#2,\reg
-	.endm
-	.macro	SAVEREGS
-	stm.l	er0-er3,@-sp
-	.endm
-	.macro	RESTOREREGS
-	ldm.l	@sp+,er2-er3
-	.endm
-	.macro	SAVEEXR
-	mov.w	@(USEREXR:16,er0),r1
-	mov.w	r1,@(LEXR-LER3:16,sp)		/* copy EXR */
-	.endm
-	.macro	RESTOREEXR
-	mov.w	@(LEXR-LER1:16,sp),r1		/* restore EXR */
-	mov.b	r1l,r1h
-	mov.w	r1,@(USEREXR:16,er0)
-	.endm
-#endif
-
-
-/* CPU context save/restore macros. */
-
-	.macro	SAVE_ALL
-	mov.l	er0,@-sp
-	stc	ccr,r0l				/* check kernel mode */
-	btst	#4,r0l
-	bne	5f
-
-	/* user mode */
-	mov.l	sp,@_sw_usp
-	mov.l	@sp,er0				/* restore saved er0 */
-	orc	#0x10,ccr			/* switch kernel stack */
-	mov.l	@_sw_ksp,sp
-	sub.l	#(LRET-LORIG),sp		/* allocate LORIG - LRET */
-	SAVEREGS
-	mov.l   @_sw_usp,er0
-	mov.l   @(USERRET:16,er0),er1           /* copy the RET addr */
-	mov.l   er1,@(LRET-LER3:16,sp)
-	SAVEEXR
-
-	mov.l	@(LORIG-LER3:16,sp),er0
-	mov.l	er0,@(LER0-LER3:16,sp)		/* copy ER0 */
-	mov.w	e1,r1				/* e1 highbyte = ccr */
-	and	#0xef,r1h			/* mask mode? flag */
-	bra	6f
-5:
-	/* kernel mode */
-	mov.l	@sp,er0				/* restore saved er0 */
-	subs	#2,sp				/* set dummy ccr */
-	SAVEREGS
-	mov.w	@(LRET-LER3:16,sp),r1		/* copy old ccr */
-6:
-	mov.b	r1h,r1l
-	mov.b	#0,r1h
-	mov.w	r1,@(LCCR-LER3:16,sp)		/* set ccr */
-	mov.l	er6,@-sp			/* syscall arg #6 */
-	mov.l	er5,@-sp			/* syscall arg #5 */
-	mov.l	er4,@-sp			/* syscall arg #4 */
-	.endm					/* r1 = ccr */
-
-	.macro	RESTORE_ALL
-	mov.l	@sp+,er4
-	mov.l	@sp+,er5
-	mov.l	@sp+,er6
-	RESTOREREGS
-	mov.w	@(LCCR-LER1:16,sp),r0		/* check kernel mode */
-	btst	#4,r0l
-	bne	7f
-
-	orc	#0x80,ccr
-	mov.l	@_sw_usp,er0
-	mov.l	@(LER0-LER1:16,sp),er1		/* restore ER0 */
-	mov.l	er1,@er0
-	RESTOREEXR
-	mov.w	@(LCCR-LER1:16,sp),r1		/* restore the RET addr */
-	mov.b	r1l,r1h
-	mov.b	@(LRET+1-LER1:16,sp),r1l
-	mov.w	r1,e1
-	mov.w	@(LRET+2-LER1:16,sp),r1
-	mov.l	er1,@(USERRET:16,er0)
-
-	mov.l	@sp+,er1
-	add.l	#(LRET-LER1),sp			/* remove LORIG - LRET */
-	mov.l	sp,@_sw_ksp
-	andc	#0xef,ccr			/* switch to user mode */
-	mov.l	er0,sp
-	bra	8f
-7:
-	mov.l	@sp+,er1
-	adds	#4,sp
-	adds	#2,sp
-8:
-	mov.l	@sp+,er0
-	adds	#4,sp				/* remove the sw created LVEC */
-	rte
-	.endm
-
-.globl _system_call
-.globl _ret_from_exception
-.globl _ret_from_fork
-.globl _ret_from_kernel_thread
-.globl _ret_from_interrupt
-.globl _interrupt_redirect_table
-.globl _sw_ksp,_sw_usp
-.globl _resume
-.globl _interrupt_entry
-.globl _trace_break
-
-#if defined(CONFIG_ROMKERNEL)
-	.section .int_redirect,"ax"
-_interrupt_redirect_table:
-#if defined(CONFIG_CPU_H8300H)
-	.rept	7
-	.long	0
-	.endr
-#endif
-#if defined(CONFIG_CPU_H8S)
-	.rept	5
-	.long	0
-	.endr
-	jmp	@_trace_break
-	.long	0
-#endif
-
-	jsr	@_interrupt_entry		/* NMI */
-	jmp	@_system_call			/* TRAPA #0 (System call) */
-	.long	0
-	.long	0
-	jmp	@_trace_break			/* TRAPA #3 (breakpoint) */
-	.rept	INTERRUPTS-12
-	jsr	@_interrupt_entry
-	.endr
-#endif
-#if defined(CONFIG_RAMKERNEL)
-.globl _interrupt_redirect_table
-	.section .bss
-_interrupt_redirect_table:
-	.space	4
-#endif
-
-	.section .text
-	.align	2
-_interrupt_entry:
-	SAVE_ALL
-	mov.l	sp,er0
-	add.l	#LVEC,er0
-	btst	#4,r1l
-	bne	1f
-	/* user LVEC */
-	mov.l	@_sw_usp,er0
-	adds	#4,er0
-1:
-	mov.l	@er0,er0			/* LVEC address */
-#if defined(CONFIG_ROMKERNEL)
-	sub.l	#_interrupt_redirect_table,er0
-#endif
-#if defined(CONFIG_RAMKERNEL)
-	mov.l	@_interrupt_redirect_table,er1
-	sub.l	er1,er0
-#endif
-	SHLR2	er0
-	dec.l	#1,er0
-	mov.l	sp,er1
-	subs	#4,er1				/* adjust ret_pc */
-	jsr	@_do_IRQ
-	jmp	@_ret_from_interrupt
-
-_system_call:
-	subs	#4,sp				/* dummy LVEC */
-	SAVE_ALL
-	andc	#0x7f,ccr
-	mov.l	er0,er4
-
-	/* save top of frame */
-	mov.l	sp,er0
-	jsr	@_set_esp0
-	mov.l	sp,er2
-	and.w	#0xe000,r2
-	mov.b	@((TI_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
-	btst	#(TIF_SYSCALL_TRACE & 7),r2l
-	beq	1f
-	jsr	@_do_syscall_trace
-1:
-	cmp.l	#NR_syscalls,er4
-	bcc	badsys
-	SHLL2	er4
-	mov.l	#_sys_call_table,er0
-	add.l	er4,er0
-	mov.l	@er0,er4
-	beq	_ret_from_exception:16
-	mov.l	@(LER1:16,sp),er0
-	mov.l	@(LER2:16,sp),er1
-	mov.l	@(LER3:16,sp),er2
-	jsr	@er4
-	mov.l	er0,@(LER0:16,sp)		/* save the return value */
-	mov.l	sp,er2
-	and.w	#0xe000,r2
-	mov.b	@((TI_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
-	btst	#(TIF_SYSCALL_TRACE & 7),r2l
-	beq	2f
-	jsr	@_do_syscall_trace
-2:
-#if defined(CONFIG_SYSCALL_PRINT)
-	jsr	@_syscall_print
-#endif
-	orc	#0x80,ccr
-	bra	resume_userspace
-
-badsys:
-	mov.l	#-ENOSYS,er0
-	mov.l	er0,@(LER0:16,sp)
-	bra	resume_userspace
-
-#if !defined(CONFIG_PREEMPT)
-#define resume_kernel restore_all
-#endif
-
-_ret_from_exception:
-#if defined(CONFIG_PREEMPT)
-	orc	#0x80,ccr
-#endif
-_ret_from_interrupt:
-	mov.b	@(LCCR+1:16,sp),r0l
-	btst	#4,r0l
-	bne	resume_kernel:8		/* return from kernel */
-resume_userspace:
-	andc	#0x7f,ccr
-	mov.l	sp,er4
-	and.w	#0xe000,r4		/* er4 <- current thread info */
-	mov.l	@(TI_FLAGS:16,er4),er1
-	and.l	#_TIF_WORK_MASK,er1
-	beq	restore_all:8
-work_pending:
-	btst	#TIF_NEED_RESCHED,r1l
-	bne	work_resched:8
-	/* work notifysig */
-	mov.l	sp,er0
-	subs	#4,er0			/* er0: pt_regs */
-	jsr	@_do_notify_resume
-	bra	restore_all:8
-work_resched:
-	mov.l	sp,er0
-	jsr	@_set_esp0
-	jsr	@_schedule
-	bra	resume_userspace:8
-restore_all:
-	RESTORE_ALL			/* Does RTE */
-
-#if defined(CONFIG_PREEMPT)
-resume_kernel:
-	mov.l	@(TI_PRE_COUNT:16,er4),er0
-	bne	restore_all:8
-need_resched:
-	mov.l	@(TI_FLAGS:16,er4),er0
-	btst	#TIF_NEED_RESCHED,r0l
-	beq	restore_all:8
-	mov.b	@(LCCR+1:16,sp),r0l	/* Interrupt Enabled? */
-	bmi	restore_all:8
-	mov.l	#PREEMPT_ACTIVE,er0
-	mov.l	er0,@(TI_PRE_COUNT:16,er4)
-	andc	#0x7f,ccr
-	mov.l	sp,er0
-	jsr	@_set_esp0
-	jsr	@_schedule
-	orc	#0x80,ccr
-	bra	need_resched:8
-#endif
-
-_ret_from_fork:
-	mov.l	er2,er0
-	jsr	@_schedule_tail
-	jmp	@_ret_from_exception
-
-_ret_from_kernel_thread:
-	mov.l	er2,er0
-	jsr	@_schedule_tail
-	mov.l	@(LER4:16,sp),er0
-	mov.l	@(LER5:16,sp),er1
-	jsr	@er1
-	jmp	@_ret_from_exception
-
-_resume:
-	/*
-	 * Beware - when entering resume, offset of tss is in d1,
-	 * prev (the current task) is in a0, next (the new task)
-	 * is in a1 and d2.b is non-zero if the mm structure is
-	 * shared between the tasks, so don't change these
-	 * registers until their contents are no longer needed.
-	 */
-
-	/* save sr */
-	sub.w	r3,r3
-	stc	ccr,r3l
-	mov.w	r3,@(THREAD_CCR+2:16,er0)
-
-	/* disable interrupts */
-	orc	#0x80,ccr
-	mov.l	@_sw_usp,er3
-	mov.l	er3,@(THREAD_USP:16,er0)
-	mov.l	sp,@(THREAD_KSP:16,er0)
-
-	/* Skip address space switching if they are the same. */
-	/* FIXME: what did we hack out of here, this does nothing! */
-
-	mov.l	@(THREAD_USP:16,er1),er0
-	mov.l	er0,@_sw_usp
-	mov.l	@(THREAD_KSP:16,er1),sp
-
-	/* restore status register */
-	mov.w	@(THREAD_CCR+2:16,er1),r3
-
-	ldc	r3l,ccr
-	rts
-
-_trace_break:
-	subs	#4,sp
-	SAVE_ALL
-	sub.l	er1,er1
-	dec.l	#1,er1
-	mov.l	er1,@(LORIG,sp)
-	mov.l	sp,er0
-	jsr	@_set_esp0
-	mov.l	@_sw_usp,er0
-	mov.l	@er0,er1
-	mov.w	@(-2:16,er1),r2
-	cmp.w	#0x5730,r2
-	beq	1f
-	subs	#2,er1
-	mov.l	er1,@er0
-1:
-	and.w	#0xff,e1
-	mov.l	er1,er0
-	jsr	@_trace_trap
-	jmp	@_ret_from_exception
-
-	.section	.bss
-_sw_ksp:
-	.space	4
-_sw_usp:
-	.space	4
-
-	.end
diff --git a/arch/h8300/kernel/gpio.c b/arch/h8300/kernel/gpio.c
deleted file mode 100644
index 084bfd0..0000000
--- a/arch/h8300/kernel/gpio.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- *  linux/arch/h8300/kernel/gpio.c
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- */
-
-/*
- * Internal I/O Port Management
- */
-
-#include <linux/stddef.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-
-#define _(addr) (volatile unsigned char *)(addr)
-#if defined(CONFIG_H83007) || defined(CONFIG_H83068)
-#include <asm/regs306x.h>
-static volatile unsigned char *ddrs[] = {
-	_(P1DDR),_(P2DDR),_(P3DDR),_(P4DDR),_(P5DDR),_(P6DDR),
-	NULL,    _(P8DDR),_(P9DDR),_(PADDR),_(PBDDR),
-};
-#define MAX_PORT 11
-#endif
-
- #if defined(CONFIG_H83002) || defined(CONFIG_H8048)
-/* Fix me!! */
-#include <asm/regs306x.h>
-static volatile unsigned char *ddrs[] = {
-	_(P1DDR),_(P2DDR),_(P3DDR),_(P4DDR),_(P5DDR),_(P6DDR),
-	NULL,    _(P8DDR),_(P9DDR),_(PADDR),_(PBDDR),
-};
-#define MAX_PORT 11
-#endif
-
-#if defined(CONFIG_H8S2678)
-#include <asm/regs267x.h>
-static volatile unsigned char *ddrs[] = {
-	_(P1DDR),_(P2DDR),_(P3DDR),NULL    ,_(P5DDR),_(P6DDR),
-	_(P7DDR),_(P8DDR),NULL,    _(PADDR),_(PBDDR),_(PCDDR),
-	_(PDDDR),_(PEDDR),_(PFDDR),_(PGDDR),_(PHDDR),
-	_(PADDR),_(PBDDR),_(PCDDR),_(PDDDR),_(PEDDR),_(PFDDR),
-	_(PGDDR),_(PHDDR)
-};
-#define MAX_PORT 17
-#endif
-#undef _
- 
-#if !defined(P1DDR)
-#error Unsuppoted CPU Selection
-#endif
-
-static struct {
-	unsigned char used;
-	unsigned char ddr;
-} gpio_regs[MAX_PORT];
-
-extern char *_platform_gpio_table(int length);
-
-int h8300_reserved_gpio(int port, unsigned int bits)
-{
-	unsigned char *used;
-
-	if (port < 0 || port >= MAX_PORT)
-		return -1;
-	used = &(gpio_regs[port].used);
-	if ((*used & bits) != 0)
-		return 0;
-	*used |= bits;
-	return 1;
-}
-
-int h8300_free_gpio(int port, unsigned int bits)
-{
-	unsigned char *used;
-
-	if (port < 0 || port >= MAX_PORT)
-		return -1;
-	used = &(gpio_regs[port].used);
-	if ((*used & bits) != bits)
-		return 0;
-	*used &= (~bits);
-	return 1;
-}
-
-int h8300_set_gpio_dir(int port_bit,int dir)
-{
-	int port = (port_bit >> 8) & 0xff;
-	int bit  = port_bit & 0xff;
-
-	if (ddrs[port] == NULL)
-		return 0;
-	if (gpio_regs[port].used & bit) {
-		if (dir)
-			gpio_regs[port].ddr |= bit;
-		else
-			gpio_regs[port].ddr &= ~bit;
-		*ddrs[port] = gpio_regs[port].ddr;
-		return 1;
-	} else
-		return 0;
-}
-
-int h8300_get_gpio_dir(int port_bit)
-{
-	int port = (port_bit >> 8) & 0xff;
-	int bit  = port_bit & 0xff;
-
-	if (ddrs[port] == NULL)
-		return 0;
-	if (gpio_regs[port].used & bit) {
-		return (gpio_regs[port].ddr & bit) != 0;
-	} else
-		return -1;
-}
-
-#if defined(CONFIG_PROC_FS)
-static char *port_status(int portno)
-{
-	static char result[10];
-	static const char io[2]={'I','O'};
-	char *rp;
-	int c;
-	unsigned char used,ddr;
-	
-	used = gpio_regs[portno].used;
-	ddr  = gpio_regs[portno].ddr;
-	result[8]='\0';
-	rp = result + 7;
-	for (c = 8; c > 0; c--,rp--,used >>= 1, ddr >>= 1)
-		if (used & 0x01)
-			*rp = io[ ddr & 0x01];
-		else	
-			*rp = '-';
-	return result;
-}
-
-static int gpio_proc_show(struct seq_file *m, void *v)
-{
-	static const char port_name[]="123456789ABCDEFGH";
-	int c;
-
-	for (c = 0; c < MAX_PORT; c++) {
-		if (ddrs[c] == NULL)
-			continue;
-		seq_printf(m, "P%c: %s\n", port_name[c], port_status(c));
-	}
-	return 0;
-}
-
-static int gpio_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, gpio_proc_show, PDE_DATA(inode));
-}
-
-static const struct file_operations gpio_proc_fops = {
-	.open		= gpio_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static __init int register_proc(void)
-{
-	return proc_create("gpio", S_IRUGO, NULL, &gpio_proc_fops) != NULL;
-}
-
-__initcall(register_proc);
-#endif
-
-void __init h8300_gpio_init(void)
-{
-	memcpy(gpio_regs,_platform_gpio_table(sizeof(gpio_regs)),sizeof(gpio_regs));
-}
diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c
deleted file mode 100644
index 53d7c0e..0000000
--- a/arch/h8300/kernel/h8300_ksyms.c
+++ /dev/null
@@ -1,100 +0,0 @@
-#include <linux/module.h>
-#include <linux/linkage.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/user.h>
-#include <linux/elfcore.h>
-#include <linux/in6.h>
-#include <linux/interrupt.h>
-
-#include <asm/setup.h>
-#include <asm/pgalloc.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/checksum.h>
-#include <asm/current.h>
-#include <asm/gpio.h>
-
-//asmlinkage long long __ashrdi3 (long long, int);
-//asmlinkage long long __lshrdi3 (long long, int);
-extern char h8300_debug_device[];
-
-/* platform dependent support */
-
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strncmp);
-
-EXPORT_SYMBOL(ip_fast_csum);
-
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
-
-/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial_copy_nocheck);
-
-/* The following are special because they're not called
-   explicitly (the C compiler generates them).  Fortunately,
-   their interface isn't gonna change any time soon now, so
-   it's OK to leave it out of version control.  */
-//EXPORT_SYMBOL(__ashrdi3);
-//EXPORT_SYMBOL(__lshrdi3);
-EXPORT_SYMBOL(memcpy);
-EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
-EXPORT_SYMBOL(memmove);
-
-/*
- * 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 __gcc_bcmp(void);
-extern void __ashldi3(void);
-extern void __ashrdi3(void);
-extern void __cmpdi2(void);
-extern void __divdi3(void);
-extern void __divsi3(void);
-extern void __lshrdi3(void);
-extern void __moddi3(void);
-extern void __modsi3(void);
-extern void __muldi3(void);
-extern void __mulsi3(void);
-extern void __negdi2(void);
-extern void __ucmpdi2(void);
-extern void __udivdi3(void);
-extern void __udivmoddi4(void);
-extern void __udivsi3(void);
-extern void __umoddi3(void);
-extern void __umodsi3(void);
-
-        /* gcc lib functions */
-EXPORT_SYMBOL(__gcc_bcmp);
-EXPORT_SYMBOL(__ashldi3);
-EXPORT_SYMBOL(__ashrdi3);
-EXPORT_SYMBOL(__cmpdi2);
-EXPORT_SYMBOL(__divdi3);
-EXPORT_SYMBOL(__divsi3);
-EXPORT_SYMBOL(__lshrdi3);
-EXPORT_SYMBOL(__moddi3);
-EXPORT_SYMBOL(__modsi3);
-EXPORT_SYMBOL(__muldi3);
-EXPORT_SYMBOL(__mulsi3);
-EXPORT_SYMBOL(__negdi2);
-EXPORT_SYMBOL(__ucmpdi2);
-EXPORT_SYMBOL(__udivdi3);
-EXPORT_SYMBOL(__udivmoddi4);
-EXPORT_SYMBOL(__udivsi3);
-EXPORT_SYMBOL(__umoddi3);
-EXPORT_SYMBOL(__umodsi3);
-
-EXPORT_SYMBOL(h8300_reserved_gpio);
-EXPORT_SYMBOL(h8300_free_gpio);
-EXPORT_SYMBOL(h8300_set_gpio_dir);
diff --git a/arch/h8300/kernel/irq.c b/arch/h8300/kernel/irq.c
deleted file mode 100644
index 2fa8ac7..0000000
--- a/arch/h8300/kernel/irq.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * linux/arch/h8300/kernel/irq.c
- *
- * Copyright 2007 Yoshinori Sato <ysato@users.sourceforge.jp>
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <linux/seq_file.h>
-#include <linux/init.h>
-#include <linux/random.h>
-#include <linux/bootmem.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-
-#include <asm/traps.h>
-#include <asm/io.h>
-#include <asm/setup.h>
-#include <asm/errno.h>
-
-/*#define DEBUG*/
-
-extern unsigned long *interrupt_redirect_table;
-extern const int h8300_saved_vectors[];
-extern const h8300_vector h8300_trap_table[];
-int h8300_enable_irq_pin(unsigned int irq);
-void h8300_disable_irq_pin(unsigned int irq);
-
-#define CPU_VECTOR ((unsigned long *)0x000000)
-#define ADDR_MASK (0xffffff)
-
-static inline int is_ext_irq(unsigned int irq)
-{
-	return (irq >= EXT_IRQ0 && irq <= (EXT_IRQ0 + EXT_IRQS));
-}
-
-static void h8300_enable_irq(struct irq_data *data)
-{
-	if (is_ext_irq(data->irq))
-		IER_REGS |= 1 << (data->irq - EXT_IRQ0);
-}
-
-static void h8300_disable_irq(struct irq_data *data)
-{
-	if (is_ext_irq(data->irq))
-		IER_REGS &= ~(1 << (data->irq - EXT_IRQ0));
-}
-
-static unsigned int h8300_startup_irq(struct irq_data *data)
-{
-	if (is_ext_irq(data->irq))
-		return h8300_enable_irq_pin(data->irq);
-	else
-		return 0;
-}
-
-static void h8300_shutdown_irq(struct irq_data *data)
-{
-	if (is_ext_irq(data->irq))
-		h8300_disable_irq_pin(data->irq);
-}
-
-/*
- * h8300 interrupt controller implementation
- */
-struct irq_chip h8300irq_chip = {
-	.name		= "H8300-INTC",
-	.irq_startup	= h8300_startup_irq,
-	.irq_shutdown	= h8300_shutdown_irq,
-	.irq_enable	= h8300_enable_irq,
-	.irq_disable	= h8300_disable_irq,
-};
-
-#if defined(CONFIG_RAMKERNEL)
-static unsigned long __init *get_vector_address(void)
-{
-	unsigned long *rom_vector = CPU_VECTOR;
-	unsigned long base,tmp;
-	int vec_no;
-
-	base = rom_vector[EXT_IRQ0] & ADDR_MASK;
-
-	/* check romvector format */
-	for (vec_no = EXT_IRQ1; vec_no <= EXT_IRQ0+EXT_IRQS; vec_no++) {
-		if ((base+(vec_no - EXT_IRQ0)*4) != (rom_vector[vec_no] & ADDR_MASK))
-			return NULL;
-	}
-
-	/* ramvector base address */
-	base -= EXT_IRQ0*4;
-
-	/* writerble check */
-	tmp = ~(*(volatile unsigned long *)base);
-	(*(volatile unsigned long *)base) = tmp;
-	if ((*(volatile unsigned long *)base) != tmp)
-		return NULL;
-	return (unsigned long *)base;
-}
-
-static void __init setup_vector(void)
-{
-	int i;
-	unsigned long *ramvec,*ramvec_p;
-	const h8300_vector *trap_entry;
-	const int *saved_vector;
-
-	ramvec = get_vector_address();
-	if (ramvec == NULL)
-		panic("interrupt vector serup failed.");
-	else
-		printk(KERN_INFO "virtual vector at 0x%08lx\n",(unsigned long)ramvec);
-
-	/* create redirect table */
-	ramvec_p = ramvec;
-	trap_entry = h8300_trap_table;
-	saved_vector = h8300_saved_vectors;
-	for ( i = 0; i < NR_IRQS; i++) {
-		if (i == *saved_vector) {
-			ramvec_p++;
-			saved_vector++;
-		} else {
-			if ( i < NR_TRAPS ) {
-				if (*trap_entry)
-					*ramvec_p = VECTOR(*trap_entry);
-				ramvec_p++;
-				trap_entry++;
-			} else
-				*ramvec_p++ = REDIRECT(interrupt_entry);
-		}
-	}
-	interrupt_redirect_table = ramvec;
-#ifdef DEBUG
-	ramvec_p = ramvec;
-	for (i = 0; i < NR_IRQS; i++) {
-		if ((i % 8) == 0)
-			printk(KERN_DEBUG "\n%p: ",ramvec_p);
-		printk(KERN_DEBUG "%p ",*ramvec_p);
-		ramvec_p++;
-	}
-	printk(KERN_DEBUG "\n");
-#endif
-}
-#else
-#define setup_vector() do { } while(0)
-#endif
-
-void __init init_IRQ(void)
-{
-	int c;
-
-	setup_vector();
-
-	for (c = 0; c < NR_IRQS; c++)
-		irq_set_chip_and_handler(c, &h8300irq_chip, handle_simple_irq);
-}
-
-asmlinkage void do_IRQ(int irq)
-{
-	irq_enter();
-	generic_handle_irq(irq);
-	irq_exit();
-}
diff --git a/arch/h8300/kernel/module.c b/arch/h8300/kernel/module.c
deleted file mode 100644
index 1d526e0..0000000
--- a/arch/h8300/kernel/module.c
+++ /dev/null
@@ -1,75 +0,0 @@
-#include <linux/moduleloader.h>
-#include <linux/elf.h>
-#include <linux/vmalloc.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(fmt...)
-#endif
-
-int apply_relocate_add(Elf32_Shdr *sechdrs,
-		       const char *strtab,
-		       unsigned int symindex,
-		       unsigned int relsec,
-		       struct module *me)
-{
-	unsigned int i;
-	Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
-
-	DEBUGP("Applying relocate section %u to %u\n", relsec,
-	       sechdrs[relsec].sh_info);
-	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
-		/* This is where to make the change */
-		uint32_t *loc = (uint32_t *)(sechdrs[sechdrs[relsec].sh_info].sh_addr
-					     + rela[i].r_offset);
-		/* This is the symbol it is referring to.  Note that all
-		   undefined symbols have been resolved.  */
-		Elf32_Sym *sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
-			+ ELF32_R_SYM(rela[i].r_info);
-		uint32_t v = sym->st_value + rela[i].r_addend;
-
-		switch (ELF32_R_TYPE(rela[i].r_info)) {
-		case R_H8_DIR24R8:
-			loc = (uint32_t *)((uint32_t)loc - 1);
-			*loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
-			break;
-		case R_H8_DIR24A8:
-			if (ELF32_R_SYM(rela[i].r_info))
-				*loc += v;
-			break;
-		case R_H8_DIR32:
-		case R_H8_DIR32A16:
-			*loc += v;
-			break;
-		case R_H8_PCREL16:
-			v -= (unsigned long)loc + 2;
-			if ((Elf32_Sword)v > 0x7fff || 
-			    (Elf32_Sword)v < -(Elf32_Sword)0x8000)
-				goto overflow;
-			else 
-				*(unsigned short *)loc = v;
-			break;
-		case R_H8_PCREL8:
-			v -= (unsigned long)loc + 1;
-			if ((Elf32_Sword)v > 0x7f || 
-			    (Elf32_Sword)v < -(Elf32_Sword)0x80)
-				goto overflow;
-			else 
-				*(unsigned char *)loc = v;
-			break;
-		default:
-			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
-			       me->name, ELF32_R_TYPE(rela[i].r_info));
-			return -ENOEXEC;
-		}
-	}
-	return 0;
- overflow:
-	printk(KERN_ERR "module %s: relocation offset overflow: %08x\n",
-	       me->name, rela[i].r_offset);
-	return -ENOEXEC;
-}
diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c
deleted file mode 100644
index 1a744ab..0000000
--- a/arch/h8300/kernel/process.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- *  linux/arch/h8300/kernel/process.c
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- *  Based on:
- *
- *  linux/arch/m68knommu/kernel/process.c
- *
- *  Copyright (C) 1998  D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>,
- *                      Kenneth Albanowski <kjahds@kjahds.com>,
- *                      The Silver Hammer Group, Ltd.
- *
- *  linux/arch/m68k/kernel/process.c
- *
- *  Copyright (C) 1995  Hamish Macdonald
- *
- *  68060 fixes by Jesper Skov
- */
-
-/*
- * This file handles the architecture-dependent parts of process handling..
- */
-
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/user.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/rcupdate.h>
-
-#include <asm/uaccess.h>
-#include <asm/traps.h>
-#include <asm/setup.h>
-#include <asm/pgtable.h>
-
-void (*pm_power_off)(void) = NULL;
-EXPORT_SYMBOL(pm_power_off);
-
-asmlinkage void ret_from_fork(void);
-asmlinkage void ret_from_kernel_thread(void);
-
-/*
- * The idle loop on an H8/300..
- */
-#if !defined(CONFIG_H8300H_SIM) && !defined(CONFIG_H8S_SIM)
-void arch_cpu_idle(void)
-{
-	local_irq_enable();
-	/* XXX: race here! What if need_resched() gets set now? */
-	__asm__("sleep");
-}
-#endif
-
-void machine_restart(char * __unused)
-{
-	local_irq_disable();
-	__asm__("jmp @@0"); 
-}
-
-void machine_halt(void)
-{
-	local_irq_disable();
-	__asm__("sleep");
-	for (;;);
-}
-
-void machine_power_off(void)
-{
-	local_irq_disable();
-	__asm__("sleep");
-	for (;;);
-}
-
-void show_regs(struct pt_regs * regs)
-{
-	show_regs_print_info(KERN_DEFAULT);
-
-	printk("\nPC: %08lx  Status: %02x",
-	       regs->pc, regs->ccr);
-	printk("\nORIG_ER0: %08lx ER0: %08lx ER1: %08lx",
-	       regs->orig_er0, regs->er0, regs->er1);
-	printk("\nER2: %08lx ER3: %08lx ER4: %08lx ER5: %08lx",
-	       regs->er2, regs->er3, regs->er4, regs->er5);
-	printk("\nER6' %08lx ",regs->er6);
-	if (user_mode(regs))
-		printk("USP: %08lx\n", rdusp());
-	else
-		printk("\n");
-}
-
-void flush_thread(void)
-{
-}
-
-int copy_thread(unsigned long clone_flags,
-                unsigned long usp, unsigned long topstk,
-		 struct task_struct * p)
-{
-	struct pt_regs * childregs;
-
-	childregs = (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1;
-
-	if (unlikely(p->flags & PF_KTHREAD)) {
-		memset(childregs, 0, sizeof(struct pt_regs));
-		childregs->retpc = (unsigned long) ret_from_kernel_thread;
-		childregs->er4 = topstk; /* arg */
-		childregs->er5 = usp; /* fn */
-		p->thread.ksp = (unsigned long)childregs;
-	}
-	*childregs = *current_pt_regs();
-	childregs->retpc = (unsigned long) ret_from_fork;
-	childregs->er0 = 0;
-	p->thread.usp = usp ?: rdusp();
-	p->thread.ksp = (unsigned long)childregs;
-
-	return 0;
-}
-
-unsigned long thread_saved_pc(struct task_struct *tsk)
-{
-	return ((struct pt_regs *)tsk->thread.esp0)->pc;
-}
-
-unsigned long get_wchan(struct task_struct *p)
-{
-	unsigned long fp, pc;
-	unsigned long stack_page;
-	int count = 0;
-	if (!p || p == current || p->state == TASK_RUNNING)
-		return 0;
-
-	stack_page = (unsigned long)p;
-	fp = ((struct pt_regs *)p->thread.ksp)->er6;
-	do {
-		if (fp < stack_page+sizeof(struct thread_info) ||
-		    fp >= 8184+stack_page)
-			return 0;
-		pc = ((unsigned long *)fp)[1];
-		if (!in_sched_functions(pc))
-			return pc;
-		fp = *(unsigned long *) fp;
-	} while (count++ < 16);
-	return 0;
-}
diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c
deleted file mode 100644
index 748cf65..0000000
--- a/arch/h8300/kernel/ptrace.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- *  linux/arch/h8300/kernel/ptrace.c
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- *  Based on:
- *  linux/arch/m68k/kernel/ptrace.c
- *
- *  Copyright (C) 1994 by Hamish Macdonald
- *  Taken from linux/kernel/ptrace.c and modified for M680x0.
- *  linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of
- * this archive for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/errno.h>
-#include <linux/ptrace.h>
-#include <linux/user.h>
-#include <linux/signal.h>
-
-#include <asm/uaccess.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/signal.h>
-
-/* cpu depend functions */
-extern long h8300_get_reg(struct task_struct *task, int regno);
-extern int  h8300_put_reg(struct task_struct *task, int regno, unsigned long data);
-
-
-void user_disable_single_step(struct task_struct *child)
-{
-}
-
-/*
- * does not yet catch signals sent when the child dies.
- * in exit.c or in signal.c.
- */
-
-void ptrace_disable(struct task_struct *child)
-{
-	user_disable_single_step(child);
-}
-
-long arch_ptrace(struct task_struct *child, long request,
-		 unsigned long addr, unsigned long data)
-{
-	int ret;
-	int regno = addr >> 2;
-	unsigned long __user *datap = (unsigned long __user *) data;
-
-	switch (request) {
-	/* read the word at location addr in the USER area. */
-		case PTRACE_PEEKUSR: {
-			unsigned long tmp = 0;
-			
-			if ((addr & 3) || addr >= sizeof(struct user)) {
-				ret = -EIO;
-				break ;
-			}
-			
-		        ret = 0;  /* Default return condition */
-
-			if (regno < H8300_REGS_NO)
-				tmp = h8300_get_reg(child, regno);
-			else {
-				switch (regno) {
-				case 49:
-					tmp = child->mm->start_code;
-					break ;
-				case 50:
-					tmp = child->mm->start_data;
-					break ;
-				case 51:
-					tmp = child->mm->end_code;
-					break ;
-				case 52:
-					tmp = child->mm->end_data;
-					break ;
-				default:
-					ret = -EIO;
-				}
-			}
-			if (!ret)
-				ret = put_user(tmp, datap);
-			break ;
-		}
-
-      /* when I and D space are separate, this will have to be fixed. */
-		case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
-			if ((addr & 3) || addr >= sizeof(struct user)) {
-				ret = -EIO;
-				break ;
-			}
-			    
-			if (regno == PT_ORIG_ER0) {
-				ret = -EIO;
-				break ;
-			}
-			if (regno < H8300_REGS_NO) {
-				ret = h8300_put_reg(child, regno, data);
-				break ;
-			}
-			ret = -EIO;
-			break ;
-
-		case PTRACE_GETREGS: { /* Get all gp regs from the child. */
-		  	int i;
-			unsigned long tmp;
-			for (i = 0; i < H8300_REGS_NO; i++) {
-			    tmp = h8300_get_reg(child, i);
-			    if (put_user(tmp, datap)) {
-				ret = -EFAULT;
-				break;
-			    }
-			    datap++;
-			}
-			ret = 0;
-			break;
-		}
-
-		case PTRACE_SETREGS: { /* Set all gp regs in the child. */
-			int i;
-			unsigned long tmp;
-			for (i = 0; i < H8300_REGS_NO; i++) {
-			    if (get_user(tmp, datap)) {
-				ret = -EFAULT;
-				break;
-			    }
-			    h8300_put_reg(child, i, tmp);
-			    datap++;
-			}
-			ret = 0;
-			break;
-		}
-
-		default:
-			ret = ptrace_request(child, request, addr, data);
-			break;
-	}
-	return ret;
-}
-
-asmlinkage void do_syscall_trace(void)
-{
-	if (!test_thread_flag(TIF_SYSCALL_TRACE))
-		return;
-	if (!(current->ptrace & PT_PTRACED))
-		return;
-	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-				 ? 0x80 : 0));
-	/*
-	 * this isn't the same as continuing with a signal, but it will do
-	 * for normal use.  strace only continues with a signal if the
-	 * stopping signal is not SIGTRAP.  -brl
-	 */
-	if (current->exit_code) {
-		send_sig(current->exit_code, current, 1);
-		current->exit_code = 0;
-	}
-}
diff --git a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c
deleted file mode 100644
index d0b1607..0000000
--- a/arch/h8300/kernel/setup.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- *  linux/arch/h8300/kernel/setup.c
- *
- *  Copyleft  ()) 2000       James D. Schettine {james@telos-systems.com}
- *  Copyright (C) 1999,2000  Greg Ungerer (gerg@snapgear.com)
- *  Copyright (C) 1998,1999  D. Jeff Dionne <jeff@lineo.ca>
- *  Copyright (C) 1998       Kenneth Albanowski <kjahds@kjahds.com>
- *  Copyright (C) 1995       Hamish Macdonald
- *  Copyright (C) 2000       Lineo Inc. (www.lineo.com) 
- *  Copyright (C) 2001 	     Lineo, Inc. <www.lineo.com>
- *
- *  H8/300 porting Yoshinori Sato <ysato@users.sourceforge.jp>
- */
-
-/*
- * This file handles the architecture-dependent parts of system setup
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/fb.h>
-#include <linux/console.h>
-#include <linux/genhd.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/major.h>
-#include <linux/bootmem.h>
-#include <linux/seq_file.h>
-#include <linux/init.h>
-
-#include <asm/setup.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/sections.h>
-
-#if defined(__H8300H__)
-#define CPU "H8/300H"
-#include <asm/regs306x.h>
-#endif
-
-#if defined(__H8300S__)
-#define CPU "H8S"
-#include <asm/regs267x.h>
-#endif
-
-#define STUBSIZE 0xc000
-
-unsigned long rom_length;
-unsigned long memory_start;
-unsigned long memory_end;
-
-char __initdata command_line[COMMAND_LINE_SIZE];
-
-extern int _ramstart, _ramend;
-extern char _target_name[];
-extern void h8300_gpio_init(void);
-
-#if (defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM)) \
-    && defined(CONFIG_GDB_MAGICPRINT)
-/* printk with gdb service */
-static void gdb_console_output(struct console *c, const char *msg, unsigned len)
-{
-	for (; len > 0; len--) {
-		asm("mov.w %0,r2\n\t"
-                    "jsr @0xc4"::"r"(*msg++):"er2");
-	}
-}
-
-/*
- *	Setup initial baud/bits/parity. We do two things here:
- *	- construct a cflag setting for the first rs_open()
- *	- initialize the serial port
- *	Return non-zero if we didn't find a serial port.
- */
-static int __init gdb_console_setup(struct console *co, char *options)
-{
-	return 0;
-}
-
-static const struct console gdb_console = {
-	.name		= "gdb_con",
-	.write		= gdb_console_output,
-	.device		= NULL,
-	.setup		= gdb_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-};
-#endif
-
-void __init setup_arch(char **cmdline_p)
-{
-	int bootmap_size;
-
-	memory_start = (unsigned long) &_ramstart;
-
-	/* allow for ROMFS on the end of the kernel */
-	if (memcmp((void *)memory_start, "-rom1fs-", 8) == 0) {
-#if defined(CONFIG_BLK_DEV_INITRD)
-		initrd_start = memory_start;
-		initrd_end = memory_start += be32_to_cpu(((unsigned long *) (memory_start))[2]);
-#else
-		memory_start += be32_to_cpu(((unsigned long *) memory_start)[2]);
-#endif
-	}
-	memory_start = PAGE_ALIGN(memory_start);
-#if !defined(CONFIG_BLKDEV_RESERVE)
-	memory_end = (unsigned long) &_ramend; /* by now the stack is part of the init task */
-#if defined(CONFIG_GDB_DEBUG)
-	memory_end -= STUBSIZE;
-#endif
-#else
-	if ((memory_end < CONFIG_BLKDEV_RESERVE_ADDRESS) && 
-	    (memory_end > CONFIG_BLKDEV_RESERVE_ADDRESS))
-	    /* overlap userarea */
-	    memory_end = CONFIG_BLKDEV_RESERVE_ADDRESS; 
-#endif
-
-	init_mm.start_code = (unsigned long) _stext;
-	init_mm.end_code = (unsigned long) _etext;
-	init_mm.end_data = (unsigned long) _edata;
-	init_mm.brk = (unsigned long) 0; 
-
-#if (defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM)) && defined(CONFIG_GDB_MAGICPRINT)
-	register_console((struct console *)&gdb_console);
-#endif
-
-	printk(KERN_INFO "\r\n\nuClinux " CPU "\n");
-	printk(KERN_INFO "Target Hardware: %s\n",_target_name);
-	printk(KERN_INFO "Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n");
-	printk(KERN_INFO "H8/300 series support by Yoshinori Sato <ysato@users.sourceforge.jp>\n");
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "KERNEL -> TEXT=0x%p-0x%p DATA=0x%p-0x%p "
-		"BSS=0x%p-0x%p\n", _stext, _etext, _sdata, _edata, __bss_start,
-		__bss_stop);
-	printk(KERN_DEBUG "KERNEL -> ROMFS=0x%p-0x%06lx MEM=0x%06lx-0x%06lx "
-		"STACK=0x%06lx-0x%p\n", __bss_stop, memory_start, memory_start,
-		memory_end, memory_end, &_ramend);
-#endif
-
-#ifdef CONFIG_DEFAULT_CMDLINE
-	/* set from default command line */
-	if (*command_line == '\0')
-		strcpy(command_line,CONFIG_KERNEL_COMMAND);
-#endif
-	/* Keep a copy of command line */
-	*cmdline_p = &command_line[0];
-	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
-	boot_command_line[COMMAND_LINE_SIZE-1] = 0;
-
-#ifdef DEBUG
-	if (strlen(*cmdline_p)) 
-		printk(KERN_DEBUG "Command line: '%s'\n", *cmdline_p);
-#endif
-
-	/*
-	 * give all the memory to the bootmap allocator,  tell it to put the
-	 * boot mem_map at the start of memory
-	 */
-	bootmap_size = init_bootmem_node(
-			NODE_DATA(0),
-			memory_start >> PAGE_SHIFT, /* map goes here */
-			PAGE_OFFSET >> PAGE_SHIFT,	/* 0 on coldfire */
-			memory_end >> PAGE_SHIFT);
-	/*
-	 * free the usable memory,  we have to make sure we do not free
-	 * the bootmem bitmap so we then reserve it after freeing it :-)
-	 */
-	free_bootmem(memory_start, memory_end - memory_start);
-	reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT);
-	/*
-	 * get kmalloc into gear
-	 */
-	paging_init();
-	h8300_gpio_init();
-#if defined(CONFIG_H8300_AKI3068NET) && defined(CONFIG_IDE)
-	{
-#define AREABIT(addr) (1 << (((addr) >> 21) & 7))
-		/* setup BSC */
-		volatile unsigned char *abwcr = (volatile unsigned char *)ABWCR;
-		volatile unsigned char *cscr = (volatile unsigned char *)CSCR;
-		*abwcr &= ~(AREABIT(CONFIG_H8300_IDE_BASE) | AREABIT(CONFIG_H8300_IDE_ALT));
-		*cscr  |= (AREABIT(CONFIG_H8300_IDE_BASE) | AREABIT(CONFIG_H8300_IDE_ALT)) | 0x0f;
-	}
-#endif
-#ifdef DEBUG
-	printk(KERN_DEBUG "Done setup_arch\n");
-#endif
-}
-
-/*
- *	Get CPU information for use by the procfs.
- */
-
-static int show_cpuinfo(struct seq_file *m, void *v)
-{
-    char *cpu;
-    int mode;
-    u_long clockfreq;
-
-    cpu = CPU;
-    mode = *(volatile unsigned char *)MDCR & 0x07;
-
-    clockfreq = CONFIG_CPU_CLOCK;
-
-    seq_printf(m,  "CPU:\t\t%s (mode:%d)\n"
-		   "Clock:\t\t%lu.%1luMHz\n"
-		   "BogoMips:\t%lu.%02lu\n"
-		   "Calibration:\t%lu loops\n",
-	           cpu,mode,
-		   clockfreq/1000,clockfreq%1000,
-		   (loops_per_jiffy*HZ)/500000,((loops_per_jiffy*HZ)/5000)%100,
-		   (loops_per_jiffy*HZ));
-
-    return 0;
-}
-
-static void *c_start(struct seq_file *m, loff_t *pos)
-{
-	return *pos < NR_CPUS ? ((void *) 0x12345678) : NULL;
-}
-
-static void *c_next(struct seq_file *m, void *v, loff_t *pos)
-{
-	++*pos;
-	return c_start(m, pos);
-}
-
-static void c_stop(struct seq_file *m, void *v)
-{
-}
-
-const struct seq_operations cpuinfo_op = {
-	.start	= c_start,
-	.next	= c_next,
-	.stop	= c_stop,
-	.show	= show_cpuinfo,
-};
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
deleted file mode 100644
index a65ff3b..0000000
--- a/arch/h8300/kernel/signal.c
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- *  linux/arch/h8300/kernel/signal.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-/*
- * uClinux H8/300 support by Yoshinori Sato <ysato@users.sourceforge.jp>
- *                and David McCullough <davidm@snapgear.com>
- *
- * Based on
- * Linux/m68k by Hamish Macdonald
- */
-
-/*
- * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
- * Atari :-) Current limitation: Only one sigstack can be active at one time.
- * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
- * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
- * signal handlers!
- */
-
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/syscalls.h>
-#include <linux/errno.h>
-#include <linux/wait.h>
-#include <linux/ptrace.h>
-#include <linux/unistd.h>
-#include <linux/stddef.h>
-#include <linux/highuid.h>
-#include <linux/personality.h>
-#include <linux/tty.h>
-#include <linux/binfmts.h>
-#include <linux/tracehook.h>
-
-#include <asm/setup.h>
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/traps.h>
-#include <asm/ucontext.h>
-
-/*
- * Do a signal return; undo the signal stack.
- *
- * Keep the return code on the stack quadword aligned!
- * That makes the cache flush below easier.
- */
-
-struct sigframe
-{
-	long dummy_er0;
-	long dummy_vector;
-#if defined(CONFIG_CPU_H8S)
-	short dummy_exr;
-#endif
-	long dummy_pc;
-	char *pretcode;
-	unsigned char retcode[8];
-	unsigned long extramask[_NSIG_WORDS-1];
-	struct sigcontext sc;
-	int sig;
-} __attribute__((aligned(2),packed));
-
-struct rt_sigframe
-{
-	long dummy_er0;
-	long dummy_vector;
-#if defined(CONFIG_CPU_H8S)
-	short dummy_exr;
-#endif
-	long dummy_pc;
-	char *pretcode;
-	struct siginfo *pinfo;
-	void *puc;
-	unsigned char retcode[8];
-	struct siginfo info;
-	struct ucontext uc;
-	int sig;
-} __attribute__((aligned(2),packed));
-
-static inline int
-restore_sigcontext(struct sigcontext *usc, int *pd0)
-{
-	struct pt_regs *regs = current_pt_regs();
-	int err = 0;
-	unsigned int ccr;
-	unsigned int usp;
-	unsigned int er0;
-
-	/* Always make any pending restarted system calls return -EINTR */
-	current_thread_info()->restart_block.fn = do_no_restart_syscall;
-
-#define COPY(r) err |= __get_user(regs->r, &usc->sc_##r)    /* restore passed registers */
-	COPY(er1);
-	COPY(er2);
-	COPY(er3);
-	COPY(er5);
-	COPY(pc);
-	ccr = regs->ccr & 0x10;
-	COPY(ccr);
-#undef COPY
-	regs->ccr &= 0xef;
-	regs->ccr |= ccr;
-	regs->orig_er0 = -1;		/* disable syscall checks */
-	err |= __get_user(usp, &usc->sc_usp);
-	wrusp(usp);
-
-	err |= __get_user(er0, &usc->sc_er0);
-	*pd0 = er0;
-	return err;
-}
-
-asmlinkage int sys_sigreturn(void)
-{
-	unsigned long usp = rdusp();
-	struct sigframe *frame = (struct sigframe *)(usp - 4);
-	sigset_t set;
-	int er0;
-
-	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
-		goto badframe;
-	if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
-	    (_NSIG_WORDS > 1 &&
-	     __copy_from_user(&set.sig[1], &frame->extramask,
-			      sizeof(frame->extramask))))
-		goto badframe;
-
-	set_current_blocked(&set);
-	
-	if (restore_sigcontext(&frame->sc, &er0))
-		goto badframe;
-	return er0;
-
-badframe:
-	force_sig(SIGSEGV, current);
-	return 0;
-}
-
-asmlinkage int sys_rt_sigreturn(void)
-{
-	unsigned long usp = rdusp();
-	struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4);
-	sigset_t set;
-	int er0;
-
-	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
-		goto badframe;
-	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
-		goto badframe;
-
-	set_current_blocked(&set);
-	
-	if (restore_sigcontext(&frame->uc.uc_mcontext, &er0))
-		goto badframe;
-
-	if (restore_altstack(&frame->uc.uc_stack))
-		goto badframe;
-
-	return er0;
-
-badframe:
-	force_sig(SIGSEGV, current);
-	return 0;
-}
-
-static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
-			     unsigned long mask)
-{
-	int err = 0;
-
-	err |= __put_user(regs->er0, &sc->sc_er0);
-	err |= __put_user(regs->er1, &sc->sc_er1);
-	err |= __put_user(regs->er2, &sc->sc_er2);
-	err |= __put_user(regs->er3, &sc->sc_er3);
-	err |= __put_user(regs->er4, &sc->sc_er4);
-	err |= __put_user(regs->er5, &sc->sc_er5);
-	err |= __put_user(regs->er6, &sc->sc_er6);
-	err |= __put_user(rdusp(),   &sc->sc_usp);
-	err |= __put_user(regs->pc,  &sc->sc_pc);
-	err |= __put_user(regs->ccr, &sc->sc_ccr);
-	err |= __put_user(mask,      &sc->sc_mask);
-
-	return err;
-}
-
-static inline void *
-get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
-{
-	unsigned long usp;
-
-	/* Default to using normal stack.  */
-	usp = rdusp();
-
-	/* This is the X/Open sanctioned signal stack switching.  */
-	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (!sas_ss_flags(usp))
-			usp = current->sas_ss_sp + current->sas_ss_size;
-	}
-	return (void *)((usp - frame_size) & -8UL);
-}
-
-static int setup_frame (int sig, struct k_sigaction *ka,
-			 sigset_t *set, struct pt_regs *regs)
-{
-	struct sigframe *frame;
-	int err = 0;
-	int usig;
-	unsigned char *ret;
-
-	frame = get_sigframe(ka, regs, sizeof(*frame));
-
-	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
-
-	usig = current_thread_info()->exec_domain
-		&& current_thread_info()->exec_domain->signal_invmap
-		&& sig < 32
-		? current_thread_info()->exec_domain->signal_invmap[sig]
-		: sig;
-
-	err |= __put_user(usig, &frame->sig);
-	if (err)
-		goto give_sigsegv;
-
-	err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
-	if (err)
-		goto give_sigsegv;
-
-	if (_NSIG_WORDS > 1) {
-		err |= copy_to_user(frame->extramask, &set->sig[1],
-				    sizeof(frame->extramask));
-		if (err)
-			goto give_sigsegv;
-	}
-
-	ret = frame->retcode;
-	if (ka->sa.sa_flags & SA_RESTORER)
-		ret = (unsigned char *)(ka->sa.sa_restorer);
-	else {
-		/* sub.l er0,er0; mov.b #__NR_sigreturn,r0l; trapa #0 */
-		err |= __put_user(0x1a80f800 + (__NR_sigreturn & 0xff),
-				  (unsigned long *)(frame->retcode + 0));
-		err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4));
-	}
-
-	/* Set up to return from userspace.  */
-	err |= __put_user(ret, &frame->pretcode);
-
-	if (err)
-		goto give_sigsegv;
-
-	/* Set up registers for signal handler */
-	wrusp ((unsigned long) frame);
-	regs->pc = (unsigned long) ka->sa.sa_handler;
-	regs->er0 = (current_thread_info()->exec_domain
-			   && current_thread_info()->exec_domain->signal_invmap
-			   && sig < 32
-			   ? current_thread_info()->exec_domain->signal_invmap[sig]
-		          : sig);
-	regs->er1 = (unsigned long)&(frame->sc);
-	regs->er5 = current->mm->start_data;	/* GOT base */
-
-	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
-}
-
-static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
-			    sigset_t *set, struct pt_regs *regs)
-{
-	struct rt_sigframe *frame;
-	int err = 0;
-	int usig;
-	unsigned char *ret;
-
-	frame = get_sigframe(ka, regs, sizeof(*frame));
-
-	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
-
-	usig = current_thread_info()->exec_domain
-		&& current_thread_info()->exec_domain->signal_invmap
-		&& sig < 32
-		? current_thread_info()->exec_domain->signal_invmap[sig]
-		: sig;
-
-	err |= __put_user(usig, &frame->sig);
-	if (err)
-		goto give_sigsegv;
-
-	err |= __put_user(&frame->info, &frame->pinfo);
-	err |= __put_user(&frame->uc, &frame->puc);
-	err |= copy_siginfo_to_user(&frame->info, info);
-	if (err)
-		goto give_sigsegv;
-
-	/* Create the ucontext.  */
-	err |= __put_user(0, &frame->uc.uc_flags);
-	err |= __put_user(0, &frame->uc.uc_link);
-	err |= __save_altstack(&frame->uc.uc_stack, rdusp());
-	err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
-	err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
-	if (err)
-		goto give_sigsegv;
-
-	/* Set up to return from userspace.  */
-	ret = frame->retcode;
-	if (ka->sa.sa_flags & SA_RESTORER)
-		ret = (unsigned char *)(ka->sa.sa_restorer);
-	else {
-		/* sub.l er0,er0; mov.b #__NR_sigreturn,r0l; trapa #0 */
-		err |= __put_user(0x1a80f800 + (__NR_sigreturn & 0xff),
-				  (unsigned long *)(frame->retcode + 0));
-		err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4));
-	}
-	err |= __put_user(ret, &frame->pretcode);
-
-	if (err)
-		goto give_sigsegv;
-
-	/* Set up registers for signal handler */
-	wrusp ((unsigned long) frame);
-	regs->pc  = (unsigned long) ka->sa.sa_handler;
-	regs->er0 = (current_thread_info()->exec_domain
-		     && current_thread_info()->exec_domain->signal_invmap
-		     && sig < 32
-		     ? current_thread_info()->exec_domain->signal_invmap[sig]
-		     : sig);
-	regs->er1 = (unsigned long)&(frame->info);
-	regs->er2 = (unsigned long)&frame->uc;
-	regs->er5 = current->mm->start_data;	/* GOT base */
-
-	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
-}
-
-/*
- * OK, we're invoking a handler
- */
-static void
-handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
-	      struct pt_regs * regs)
-{
-	sigset_t *oldset = sigmask_to_save();
-	int ret;
-	/* are we from a system call? */
-	if (regs->orig_er0 >= 0) {
-		switch (regs->er0) {
-		        case -ERESTART_RESTARTBLOCK:
-			case -ERESTARTNOHAND:
-				regs->er0 = -EINTR;
-				break;
-
-			case -ERESTARTSYS:
-				if (!(ka->sa.sa_flags & SA_RESTART)) {
-					regs->er0 = -EINTR;
-					break;
-				}
-			/* fallthrough */
-			case -ERESTARTNOINTR:
-				regs->er0 = regs->orig_er0;
-				regs->pc -= 2;
-		}
-	}
-
-	/* set up the stack frame */
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		ret = setup_rt_frame(sig, ka, info, oldset, regs);
-	else
-		ret = setup_frame(sig, ka, oldset, regs);
-
-	if (!ret)
-		signal_delivered(sig, info, ka, regs, 0);
-}
-
-/*
- * Note that 'init' is a special process: it doesn't get signals it doesn't
- * want to handle. Thus you cannot kill init even with a SIGKILL even by
- * mistake.
- */
-static void do_signal(struct pt_regs *regs)
-{
-	siginfo_t info;
-	int signr;
-	struct k_sigaction ka;
-
-	/*
-	 * We want the common case to go fast, which
-	 * is why we may in certain cases get here from
-	 * kernel mode. Just return without doing anything
-	 * if so.
-	 */
-	if ((regs->ccr & 0x10))
-		return;
-
-	current->thread.esp0 = (unsigned long) regs;
-
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
-		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, &info, &ka, regs);
-		return;
-	}
-	/* Did we come from a system call? */
-	if (regs->orig_er0 >= 0) {
-		/* Restart the system call - no handlers present */
-		if (regs->er0 == -ERESTARTNOHAND ||
-		    regs->er0 == -ERESTARTSYS ||
-		    regs->er0 == -ERESTARTNOINTR) {
-			regs->er0 = regs->orig_er0;
-			regs->pc -= 2;
-		}
-		if (regs->er0 == -ERESTART_RESTARTBLOCK){
-			regs->er0 = __NR_restart_syscall;
-			regs->pc -= 2;
-		}
-	}
-
-	/* If there's no signal to deliver, we just restore the saved mask.  */
-	restore_saved_sigmask();
-}
-
-asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
-{
-	if (thread_info_flags & _TIF_SIGPENDING)
-		do_signal(regs);
-
-	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
-		clear_thread_flag(TIF_NOTIFY_RESUME);
-		tracehook_notify_resume(regs);
-	}
-}
diff --git a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c
deleted file mode 100644
index bf350cb..0000000
--- a/arch/h8300/kernel/sys_h8300.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * linux/arch/h8300/kernel/sys_h8300.c
- *
- * This file contains various random system calls that
- * have a non-standard calling sequence on the H8/300
- * platform.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/sem.h>
-#include <linux/msg.h>
-#include <linux/shm.h>
-#include <linux/stat.h>
-#include <linux/syscalls.h>
-#include <linux/mman.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/ipc.h>
-
-#include <asm/setup.h>
-#include <asm/uaccess.h>
-#include <asm/cachectl.h>
-#include <asm/traps.h>
-#include <asm/unistd.h>
-
-/* sys_cacheflush -- no support.  */
-asmlinkage int
-sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
-{
-	return -EINVAL;
-}
-
-asmlinkage int sys_getpagesize(void)
-{
-	return PAGE_SIZE;
-}
-
-#if defined(CONFIG_SYSCALL_PRINT)
-asmlinkage void syscall_print(void *dummy,...)
-{
-	struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4);
-	printk("call %06lx:%ld 1:%08lx,2:%08lx,3:%08lx,ret:%08lx\n",
-               ((regs->pc)&0xffffff)-2,regs->orig_er0,regs->er1,regs->er2,regs->er3,regs->er0);
-}
-#endif
diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S
deleted file mode 100644
index c55e0ed..0000000
--- a/arch/h8300/kernel/syscalls.S
+++ /dev/null
@@ -1,338 +0,0 @@
-/* Systemcall Entry Table */
-#include <linux/sys.h>
-#include <asm/linkage.h>
-#include <asm/unistd.h>
-
-#define CALL(x)	.long _ ## x
-
-.globl _sys_call_table
-
-#if defined(CONFIG_CPU_H8300H)
-	.h8300h
-#endif
-#if defined(CONFIG_CPU_H8S)
-	.h8300s
-#endif
-	.section .text
-	.align	2
-_sys_call_table:
-	CALL(sys_ni_syscall)		/* 0  -  old "setup()" system call*/
-	CALL(sys_exit)
-	CALL(sys_fork)
-	CALL(sys_read)
-	CALL(sys_write)
-	CALL(sys_open)			/* 5 */
-	CALL(sys_close)
-	CALL(sys_waitpid)
-	CALL(sys_creat)
-	CALL(sys_link)
-	CALL(sys_unlink)		/* 10 */
-	CALL(sys_execve)
-	CALL(sys_chdir)
-	CALL(sys_time)
-	CALL(sys_mknod)
-	CALL(sys_chmod)			/* 15 */
-	CALL(sys_chown16)
-	CALL(sys_ni_syscall)		/* old break syscall holder */
-	CALL(sys_stat)
-	CALL(sys_lseek)
-	CALL(sys_getpid)		/* 20 */
-	CALL(sys_mount)
-	CALL(sys_oldumount)
-	CALL(sys_setuid16)
-	CALL(sys_getuid16)
-	CALL(sys_stime)			/* 25 */
-	CALL(sys_ptrace)
-	CALL(sys_alarm)
-	CALL(sys_fstat)
-	CALL(sys_pause)
-	CALL(sys_utime)			/* 30 */
-	CALL(sys_ni_syscall)		/* old stty syscall holder */
-	CALL(sys_ni_syscall)		/* old gtty syscall holder */
-	CALL(sys_access)
-	CALL(sys_nice)
-	CALL(sys_ni_syscall)		/* 35 old ftime syscall holder */
-	CALL(sys_sync)
-	CALL(sys_kill)
-	CALL(sys_rename)
-	CALL(sys_mkdir)
-	CALL(sys_rmdir)			/* 40 */
-	CALL(sys_dup)
-	CALL(sys_pipe)
-	CALL(sys_times)
-	CALL(sys_ni_syscall)		/* old prof syscall holder */
-	CALL(sys_brk)			/* 45 */
-	CALL(sys_setgid16)
-	CALL(sys_getgid16)
-	CALL(sys_signal)
-	CALL(sys_geteuid16)
-	CALL(sys_getegid16)		/* 50 */
-	CALL(sys_acct)
-	CALL(sys_umount)		/* recycled never used phys() */
-	CALL(sys_ni_syscall)		/* old lock syscall holder */
-	CALL(sys_ioctl)
-	CALL(sys_fcntl)			/* 55 */
-	CALL(sys_ni_syscall)		/* old mpx syscall holder */
-	CALL(sys_setpgid)
-	CALL(sys_ni_syscall)		/* old ulimit syscall holder */
-	CALL(sys_ni_syscall)
-	CALL(sys_umask)			/* 60 */
-	CALL(sys_chroot)
-	CALL(sys_ustat)
-	CALL(sys_dup2)
-	CALL(sys_getppid)
-	CALL(sys_getpgrp)		/* 65 */
-	CALL(sys_setsid)
-	CALL(sys_sigaction)
-	CALL(sys_sgetmask)
-	CALL(sys_ssetmask)
-	CALL(sys_setreuid16)		/* 70 */
-	CALL(sys_setregid16)
-	CALL(sys_sigsuspend)
-	CALL(sys_sigpending)
-	CALL(sys_sethostname)
-	CALL(sys_setrlimit)		/* 75 */
-	CALL(sys_old_getrlimit)
-	CALL(sys_getrusage)
-	CALL(sys_gettimeofday)
-	CALL(sys_settimeofday)
-	CALL(sys_getgroups16)		/* 80 */
-	CALL(sys_setgroups16)
-	CALL(sys_old_select)
-	CALL(sys_symlink)
-	CALL(sys_lstat)
-	CALL(sys_readlink)		/* 85 */
-	CALL(sys_uselib)
-	CALL(sys_swapon)
-	CALL(sys_reboot)
-	CALL(sys_old_readdir)
-	CALL(sys_old_mmap)		/* 90 */
-	CALL(sys_munmap)
-	CALL(sys_truncate)
-	CALL(sys_ftruncate)
-	CALL(sys_fchmod)
-	CALL(sys_fchown16)		/* 95 */
-	CALL(sys_getpriority)
-	CALL(sys_setpriority)
-	CALL(sys_ni_syscall)		/* old profil syscall holder */
-	CALL(sys_statfs)
-	CALL(sys_fstatfs)		/* 100 */
-	CALL(sys_ni_syscall)		/* ioperm for i386 */
-	CALL(sys_socketcall)
-	CALL(sys_syslog)
-	CALL(sys_setitimer)
-	CALL(sys_getitimer)		/* 105 */
-	CALL(sys_newstat)
-	CALL(sys_newlstat)
-	CALL(sys_newfstat)
-	CALL(sys_ni_syscall)
-	CALL(sys_ni_syscall)		/* iopl for i386 */ /* 110 */
-	CALL(sys_vhangup)
-	CALL(sys_ni_syscall)		/* obsolete idle() syscall */
-	CALL(sys_ni_syscall)		/* vm86old for i386 */
-	CALL(sys_wait4)
-	CALL(sys_swapoff)		/* 115 */
-	CALL(sys_sysinfo)
-	CALL(sys_ipc)
-	CALL(sys_fsync)
-	CALL(sys_sigreturn)
-	CALL(sys_clone)			/* 120 */
-	CALL(sys_setdomainname)
-	CALL(sys_newuname)
-	CALL(sys_cacheflush)		/* modify_ldt for i386 */
-	CALL(sys_adjtimex)
-	CALL(sys_ni_syscall)		/* 125 sys_mprotect */
-	CALL(sys_sigprocmask)
-	CALL(sys_ni_syscall)		/* sys_create_module */
-	CALL(sys_init_module)
-	CALL(sys_delete_module)
-	CALL(sys_ni_syscall)		/* 130 sys_get_kernel_syms */
-	CALL(sys_quotactl)
-	CALL(sys_getpgid)
-	CALL(sys_fchdir)
-	CALL(sys_bdflush)
-	CALL(sys_sysfs)			/* 135 */
-	CALL(sys_personality)
-	CALL(sys_ni_syscall)		/* for afs_syscall */
-	CALL(sys_setfsuid16)
-	CALL(sys_setfsgid16)
-	CALL(sys_llseek)		/* 140 */
-	CALL(sys_getdents)
-	CALL(sys_select)
-	CALL(sys_flock)
-	CALL(sys_ni_syscall)		/* sys_msync */
-	CALL(sys_readv)			/* 145 */
-	CALL(sys_writev)
-	CALL(sys_getsid)
-	CALL(sys_fdatasync)
-	CALL(sys_sysctl)
-	CALL(sys_ni_syscall)		/* 150 sys_mlock */
-	CALL(sys_ni_syscall)		/* sys_munlock */
-	CALL(sys_ni_syscall)		/* sys_mlockall */
-	CALL(sys_ni_syscall)		/* sys_munlockall */
-	CALL(sys_sched_setparam)
-	CALL(sys_sched_getparam)	/* 155 */
-	CALL(sys_sched_setscheduler)
-	CALL(sys_sched_getscheduler)
-	CALL(sys_sched_yield)
-	CALL(sys_sched_get_priority_max)
-	CALL(sys_sched_get_priority_min)  /* 160 */
-	CALL(sys_sched_rr_get_interval)
-	CALL(sys_nanosleep)
-	CALL(sys_ni_syscall)		/* sys_mremap */
-	CALL(sys_setresuid16)
-	CALL(sys_getresuid16)		/* 165 */
-	CALL(sys_ni_syscall)		/* for vm86 */
-	CALL(sys_ni_syscall)		/* sys_query_module */
-	CALL(sys_poll)
-	CALL(sys_ni_syscall)		/* old nfsservctl */
-	CALL(sys_setresgid16)		/* 170 */
-	CALL(sys_getresgid16)
-	CALL(sys_prctl)
-	CALL(sys_rt_sigreturn)
-	CALL(sys_rt_sigaction)
-	CALL(sys_rt_sigprocmask)	/* 175 */
-	CALL(sys_rt_sigpending)
-	CALL(sys_rt_sigtimedwait)
-	CALL(sys_rt_sigqueueinfo)
-	CALL(sys_rt_sigsuspend)
-	CALL(sys_pread64)		/* 180 */
-	CALL(sys_pwrite64)
-	CALL(sys_lchown16);
-	CALL(sys_getcwd)
-	CALL(sys_capget)
-	CALL(sys_capset)		/* 185 */
-	CALL(sys_sigaltstack)
-	CALL(sys_sendfile)
-	CALL(sys_ni_syscall)		/* streams1 */
-	CALL(sys_ni_syscall)		/* streams2 */
-	CALL(sys_vfork)			/* 190 */
-	CALL(sys_getrlimit)
-	CALL(sys_mmap_pgoff)
-	CALL(sys_truncate64)
-	CALL(sys_ftruncate64)
-	CALL(sys_stat64)		/* 195 */
-	CALL(sys_lstat64)
-	CALL(sys_fstat64)
-	CALL(sys_chown)
-	CALL(sys_getuid)
-	CALL(sys_getgid)		/* 200 */
-	CALL(sys_geteuid)
-	CALL(sys_getegid)
-	CALL(sys_setreuid)
-	CALL(sys_setregid)
-	CALL(sys_getgroups)		/* 205 */
-	CALL(sys_setgroups)
-	CALL(sys_fchown)
-	CALL(sys_setresuid)
-	CALL(sys_getresuid)
-	CALL(sys_setresgid)		/* 210 */
-	CALL(sys_getresgid)
-	CALL(sys_lchown)
-	CALL(sys_setuid)
-	CALL(sys_setgid)
-	CALL(sys_setfsuid)		/* 215 */
-	CALL(sys_setfsgid)
-	CALL(sys_pivot_root)
-	CALL(sys_ni_syscall)
-	CALL(sys_ni_syscall)
-	CALL(sys_getdents64)		/* 220 */
-	CALL(sys_fcntl64)
-	CALL(sys_ni_syscall)		/* reserved TUX */
-	CALL(sys_ni_syscall)		/* reserved Security */
-	CALL(sys_gettid)
-	CALL(sys_readahead)		/* 225 */
-	CALL(sys_setxattr)
-	CALL(sys_lsetxattr)
-	CALL(sys_fsetxattr)
-	CALL(sys_getxattr)
-	CALL(sys_lgetxattr)		/* 230 */
-	CALL(sys_fgetxattr)
-	CALL(sys_listxattr)
-	CALL(sys_llistxattr)
-	CALL(sys_flistxattr)
-	CALL(sys_removexattr)		/* 235 */
-	CALL(sys_lremovexattr)
-	CALL(sys_fremovexattr)
-	CALL(sys_tkill)
-	CALL(sys_sendfile64)
-	CALL(sys_futex)			/* 240 */
-	CALL(sys_sched_setaffinity)
-	CALL(sys_sched_getaffinity)
-	CALL(sys_ni_syscall)
-	CALL(sys_ni_syscall)
-	CALL(sys_io_setup)		/* 245 */
-	CALL(sys_io_destroy)
-	CALL(sys_io_getevents)
-	CALL(sys_io_submit)
-	CALL(sys_io_cancel)
-	CALL(sys_fadvise64)		/* 250 */
-	CALL(sys_ni_syscall)
-	CALL(sys_exit_group)
-	CALL(sys_lookup_dcookie)
-	CALL(sys_epoll_create)
-	CALL(sys_epoll_ctl)		/* 255 */
-	CALL(sys_epoll_wait)
-	CALL(sys_ni_syscall)		/* sys_remap_file_pages */
-	CALL(sys_set_tid_address)
-	CALL(sys_timer_create)
-	CALL(sys_timer_settime)		/* 260 */
-	CALL(sys_timer_gettime)
-	CALL(sys_timer_getoverrun)
-	CALL(sys_timer_delete)
-	CALL(sys_clock_settime)
-	CALL(sys_clock_gettime)		/* 265 */
-	CALL(sys_clock_getres)
-	CALL(sys_clock_nanosleep)
-	CALL(sys_statfs64)
-	CALL(sys_fstatfs64)
-	CALL(sys_tgkill)		/* 270 */
-	CALL(sys_utimes)
-	CALL(sys_fadvise64_64)
-	CALL(sys_ni_syscall)		/* sys_vserver */
-	CALL(sys_ni_syscall)
-	CALL(sys_get_mempolicy)		/* 275 */
-	CALL(sys_set_mempolicy)
-	CALL(sys_mq_open)
-	CALL(sys_mq_unlink)
-	CALL(sys_mq_timedsend)
-	CALL(sys_mq_timedreceive)	/* 280 */
-	CALL(sys_mq_notify)
-	CALL(sys_mq_getsetattr)
-	CALL(sys_waitid)
-	CALL(sys_ni_syscall)		/* sys_kexec_load */
-	CALL(sys_add_key) 		/* 285 */
-	CALL(sys_request_key)
-	CALL(sys_keyctl)
-	CALL(sys_ioprio_set)
-	CALL(sys_ioprio_get)		/* 290 */
-	CALL(sys_inotify_init)
-	CALL(sys_inotify_add_watch)
-	CALL(sys_inotify_rm_watch)
-	CALL(sys_migrate_pages)
-	CALL(sys_openat)		/* 295 */
-	CALL(sys_mkdirat)
-	CALL(sys_mknodat)
-	CALL(sys_fchownat)
-	CALL(sys_futimesat)
-	CALL(sys_fstatat64)		/* 300 */
-	CALL(sys_unlinkat)
-	CALL(sys_renameat)
-	CALL(sys_linkat)
-	CALL(sys_symlinkat)
-	CALL(sys_readlinkat)		/* 305 */
-	CALL(sys_fchmodat)
-	CALL(sys_faccessat)
-	CALL(sys_ni_syscall)		/* sys_pselect6 */
-	CALL(sys_ni_syscall)		/* sys_ppoll */
-	CALL(sys_unshare)		/* 310 */
-	CALL(sys_set_robust_list)
-	CALL(sys_get_robust_list)
-	CALL(sys_splice)
-	CALL(sys_sync_file_range)
-	CALL(sys_tee)			/* 315 */
-	CALL(sys_vmsplice)
-	CALL(sys_ni_syscall)		/* sys_move_pages */
-	CALL(sys_getcpu)
-	CALL(sys_ni_syscall)		/* sys_epoll_pwait */
-	CALL(sys_setns)			/* 320 */
diff --git a/arch/h8300/kernel/time.c b/arch/h8300/kernel/time.c
deleted file mode 100644
index e0f7419..0000000
--- a/arch/h8300/kernel/time.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- *  linux/arch/h8300/kernel/time.c
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- *  Copied/hacked from:
- *
- *  linux/arch/m68k/kernel/time.c
- *
- *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
- *
- * This file contains the m68k-specific time handling details.
- * Most of the stuff is located in the machine specific files.
- *
- * 1997-09-10	Updated NTP code according to technical memorandum Jan '96
- *		"A Kernel Model for Precision Timekeeping" by Dave Mills
- */
-
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/timex.h>
-#include <linux/profile.h>
-
-#include <asm/io.h>
-#include <asm/irq_regs.h>
-#include <asm/timer.h>
-
-#define	TICK_SIZE (tick_nsec / 1000)
-
-void h8300_timer_tick(void)
-{
-	if (current->pid)
-		profile_tick(CPU_PROFILING);
-	xtime_update(1);
-	update_process_times(user_mode(get_irq_regs()));
-}
-
-void read_persistent_clock(struct timespec *ts)
-{
-	unsigned int year, mon, day, hour, min, sec;
-
-	/* FIX by dqg : Set to zero for platforms that don't have tod */
-	/* without this time is undefined and can overflow time_t, causing  */
-	/* very strange errors */
-	year = 1980;
-	mon = day = 1;
-	hour = min = sec = 0;
-#ifdef CONFIG_H8300_GETTOD
-	h8300_gettod (&year, &mon, &day, &hour, &min, &sec);
-#endif
-	if ((year += 1900) < 1970)
-		year += 100;
-	ts->tv_sec = mktime(year, mon, day, hour, min, sec);
-	ts->tv_nsec = 0;
-}
-
-void __init time_init(void)
-{
-
-	h8300_timer_setup();
-}
diff --git a/arch/h8300/kernel/timer/Makefile b/arch/h8300/kernel/timer/Makefile
deleted file mode 100644
index bef0510..0000000
--- a/arch/h8300/kernel/timer/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# h8300 internal timer handler
-
-obj-$(CONFIG_H8300_TIMER8)  := timer8.o
-obj-$(CONFIG_H8300_TIMER16) := timer16.o
-obj-$(CONFIG_H8300_ITU)     := itu.o
-obj-$(CONFIG_H8300_TPU)     := tpu.o
diff --git a/arch/h8300/kernel/timer/itu.c b/arch/h8300/kernel/timer/itu.c
deleted file mode 100644
index 0a8b5cd..0000000
--- a/arch/h8300/kernel/timer/itu.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- *  linux/arch/h8300/kernel/timer/itu.c
- *
- *  Yoshinori Sato <ysato@users.sourcefoge.jp>
- *
- *  ITU Timer Handler
- *
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/timex.h>
-
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/regs306x.h>
-
-#if CONFIG_H8300_ITU_CH == 0
-#define ITUBASE	0xffff64
-#define ITUIRQ	24
-#elif CONFIG_H8300_ITU_CH == 1
-#define ITUBASE	0xffff6e
-#define ITUIRQ	28
-#elif CONFIG_H8300_ITU_CH == 2
-#define ITUBASE	0xffff78
-#define ITUIRQ	32
-#elif CONFIG_H8300_ITU_CH == 3
-#define ITUBASE	0xffff82
-#define ITUIRQ	36
-#elif CONFIG_H8300_ITU_CH == 4
-#define ITUBASE	0xffff92
-#define ITUIRQ	40
-#else
-#error Unknown timer channel.
-#endif
-
-#define TCR	0
-#define TIOR	1
-#define TIER	2
-#define TSR	3
-#define TCNT	4
-#define GRA	6
-#define GRB	8
-
-static irqreturn_t timer_interrupt(int irq, void *dev_id)
-{
-	h8300_timer_tick();
-	ctrl_bclr(IMFA, ITUBASE + TSR);
-	return IRQ_HANDLED;
-}
-
-static struct irqaction itu_irq = {
-	.name		= "itu",
-	.handler	= timer_interrupt,
-	.flags		= IRQF_DISABLED | IRQF_TIMER,
-};
-
-static const int __initconst divide_rate[] = {1, 2, 4, 8};
-
-void __init h8300_timer_setup(void)
-{
-	unsigned int div;
-	unsigned int cnt;
-
-	calc_param(cnt, div, divide_rate, 0x10000);
-
-	setup_irq(ITUIRQ, &itu_irq);
-
-	/* initialize timer */
-	ctrl_outb(0, TSTR);
-	ctrl_outb(CCLR0 | div, ITUBASE + TCR);
-	ctrl_outb(0x01, ITUBASE + TIER);
-	ctrl_outw(cnt, ITUBASE + GRA);
-	ctrl_bset(CONFIG_H8300_ITU_CH, TSTR);
-}
diff --git a/arch/h8300/kernel/timer/timer16.c b/arch/h8300/kernel/timer/timer16.c
deleted file mode 100644
index 462d9f58..0000000
--- a/arch/h8300/kernel/timer/timer16.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- *  linux/arch/h8300/kernel/timer/timer16.c
- *
- *  Yoshinori Sato <ysato@users.sourcefoge.jp>
- *
- *  16bit Timer Handler
- *
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/timex.h>
-
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/regs306x.h>
-
-/* 16bit timer */
-#if CONFIG_H8300_TIMER16_CH == 0
-#define _16BASE	0xffff78
-#define _16IRQ	24
-#elif CONFIG_H8300_TIMER16_CH == 1
-#define _16BASE	0xffff80
-#define _16IRQ	28
-#elif CONFIG_H8300_TIMER16_CH == 2
-#define _16BASE	0xffff88
-#define _16IRQ	32
-#else
-#error Unknown timer channel.
-#endif
-
-#define TCR	0
-#define TIOR	1
-#define TCNT	2
-#define GRA	4
-#define GRB	6
-
-#define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*10000 /* Timer input freq. */
-
-static irqreturn_t timer_interrupt(int irq, void *dev_id)
-{
-	h8300_timer_tick();
-	ctrl_bclr(CONFIG_H8300_TIMER16_CH, TISRA);
-	return IRQ_HANDLED;
-}
-
-static struct irqaction timer16_irq = {
-	.name		= "timer-16",
-	.handler	= timer_interrupt,
-	.flags		= IRQF_DISABLED | IRQF_TIMER,
-};
-
-static const int __initconst divide_rate[] = {1, 2, 4, 8};
-
-void __init h8300_timer_setup(void)
-{
-	unsigned int div;
-	unsigned int cnt;
-
-	calc_param(cnt, div, divide_rate, 0x10000);
-
-	setup_irq(_16IRQ, &timer16_irq);
-
-	/* initialize timer */
-	ctrl_outb(0, TSTR);
-	ctrl_outb(CCLR0 | div, _16BASE + TCR);
-	ctrl_outw(cnt, _16BASE + GRA);
-	ctrl_bset(4 + CONFIG_H8300_TIMER16_CH, TISRA);
-	ctrl_bset(CONFIG_H8300_TIMER16_CH, TSTR);
-}
diff --git a/arch/h8300/kernel/timer/timer8.c b/arch/h8300/kernel/timer/timer8.c
deleted file mode 100644
index 505f341..0000000
--- a/arch/h8300/kernel/timer/timer8.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- *  linux/arch/h8300/kernel/cpu/timer/timer8.c
- *
- *  Yoshinori Sato <ysato@users.sourcefoge.jp>
- *
- *  8bit Timer Handler
- *
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/profile.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/timer.h>
-#if defined(CONFIG_CPU_H8300H)
-#include <asm/regs306x.h>
-#endif
-#if defined(CONFIG_CPU_H8S)
-#include <asm/regs267x.h>
-#endif
-
-/* 8bit timer x2 */
-#define CMFA	6
-
-#if defined(CONFIG_H8300_TIMER8_CH0)
-#define _8BASE	_8TCR0
-#ifdef CONFIG_CPU_H8300H
-#define _8IRQ	36
-#endif
-#ifdef CONFIG_CPU_H8S
-#define _8IRQ	72
-#endif
-#elif defined(CONFIG_H8300_TIMER8_CH2)
-#ifdef CONFIG_CPU_H8300H
-#define _8BASE	_8TCR2
-#define _8IRQ	40
-#endif
-#endif
-
-#ifndef _8BASE
-#error Unknown timer channel.
-#endif
-
-#define _8TCR	0
-#define _8TCSR	2
-#define TCORA	4
-#define TCORB	6
-#define _8TCNT	8
-
-#define CMIEA	0x40
-#define CCLR_CMA 0x08
-#define CKS2	0x04
-
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "xtime_update()" routine every clocktick
- */
-
-static irqreturn_t timer_interrupt(int irq, void *dev_id)
-{
-	h8300_timer_tick();
-	ctrl_bclr(CMFA, _8BASE + _8TCSR);
-	return IRQ_HANDLED;
-}
-
-static struct irqaction timer8_irq = {
-	.name		= "timer-8",
-	.handler	= timer_interrupt,
-	.flags		= IRQF_DISABLED | IRQF_TIMER,
-};
-
-static const int __initconst divide_rate[] = {8, 64, 8192};
-
-void __init h8300_timer_setup(void)
-{
-	unsigned int div;
-	unsigned int cnt;
-
-	calc_param(cnt, div, divide_rate, 0x10000);
-	div++;
-
-	setup_irq(_8IRQ, &timer8_irq);
-
-#if defined(CONFIG_CPU_H8S)
-	/* Timer module enable */
-	ctrl_bclr(0, MSTPCRL)
-#endif
-
-	/* initialize timer */
-	ctrl_outw(cnt, _8BASE + TCORA);
-	ctrl_outw(0x0000, _8BASE + _8TCSR);
-	ctrl_outw((CMIEA|CCLR_CMA|CKS2) << 8 | div,
-		  _8BASE + _8TCR);
-}
diff --git a/arch/h8300/kernel/timer/tpu.c b/arch/h8300/kernel/timer/tpu.c
deleted file mode 100644
index 0350f62..0000000
--- a/arch/h8300/kernel/timer/tpu.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- *  linux/arch/h8300/kernel/timer/tpu.c
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- *  TPU Timer Handler
- *
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/timex.h>
-
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/regs267x.h>
-
-/* TPU */
-#if CONFIG_H8300_TPU_CH == 0
-#define TPUBASE	0xffffd0
-#define TPUIRQ	40
-#elif CONFIG_H8300_TPU_CH == 1
-#define TPUBASE	0xffffe0
-#define TPUIRQ	48
-#elif CONFIG_H8300_TPU_CH == 2
-#define TPUBASE	0xfffff0
-#define TPUIRQ	52
-#elif CONFIG_H8300_TPU_CH == 3
-#define TPUBASE	0xfffe80
-#define TPUIRQ	56
-#elif CONFIG_H8300_TPU_CH == 4
-#define TPUBASE	0xfffe90
-#define TPUIRQ	64
-#else
-#error Unknown timer channel.
-#endif
-
-#define _TCR	0
-#define _TMDR	1
-#define _TIOR	2
-#define _TIER	4
-#define _TSR	5
-#define _TCNT	6
-#define _GRA	8
-#define _GRB	10
-
-#define CCLR0	0x20
-
-static irqreturn_t timer_interrupt(int irq, void *dev_id)
-{
-	h8300_timer_tick();
-	ctrl_bclr(0, TPUBASE + _TSR);
-	return IRQ_HANDLED;
-}
-
-static struct irqaction tpu_irq = {
-	.name		= "tpu",
-	.handler	= timer_interrupt,
-	.flags		= IRQF_DISABLED | IRQF_TIMER,
-};
-
-static const int __initconst divide_rate[] = {
-#if CONFIG_H8300_TPU_CH == 0
-	1,4,16,64,0,0,0,0,
-#elif (CONFIG_H8300_TPU_CH == 1) || (CONFIG_H8300_TPU_CH == 5)
-	1,4,16,64,0,0,256,0,
-#elif (CONFIG_H8300_TPU_CH == 2) || (CONFIG_H8300_TPU_CH == 4)
-	1,4,16,64,0,0,0,1024,
-#elif CONFIG_H8300_TPU_CH == 3
-	1,4,16,64,0,1024,256,4096,
-#endif
-};
-
-void __init h8300_timer_setup(void)
-{
-	unsigned int cnt;
-	unsigned int div;
-
-	calc_param(cnt, div, divide_rate, 0x10000);
-
-	setup_irq(TPUIRQ, &tpu_irq);
-
-	/* TPU module enabled */
-	ctrl_bclr(3, MSTPCRH);
-
-	ctrl_outb(0, TSTR);
-	ctrl_outb(CCLR0 | div, TPUBASE + _TCR);
-	ctrl_outb(0, TPUBASE + _TMDR);
-	ctrl_outw(0, TPUBASE + _TIOR);
-	ctrl_outb(0x01, TPUBASE + _TIER);
-	ctrl_outw(cnt, TPUBASE + _GRA);
-	ctrl_bset(CONFIG_H8300_TPU_CH, TSTR);
-}
diff --git a/arch/h8300/kernel/traps.c b/arch/h8300/kernel/traps.c
deleted file mode 100644
index cfe494d..0000000
--- a/arch/h8300/kernel/traps.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * linux/arch/h8300/boot/traps.c -- general exception handling code
- * H8/300 support Yoshinori Sato <ysato@users.sourceforge.jp>
- * 
- * Cloned from Linux/m68k.
- *
- * No original Copyright holder listed,
- * Probable original (C) Roman Zippel (assigned DJD, 1999)
- *
- * Copyright 1999-2000 D. Jeff Dionne, <jeff@rt-control.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/bug.h>
-
-#include <asm/irq.h>
-#include <asm/traps.h>
-#include <asm/page.h>
-
-static DEFINE_SPINLOCK(die_lock);
-
-/*
- * this must be called very early as the kernel might
- * use some instruction that are emulated on the 060
- */
-
-void __init base_trap_init(void)
-{
-}
-
-void __init trap_init (void)
-{
-}
-
-asmlinkage void set_esp0 (unsigned long ssp)
-{
-	current->thread.esp0 = ssp;
-}
-
-/*
- *	Generic dumping code. Used for panic and debug.
- */
-
-static void dump(struct pt_regs *fp)
-{
-	unsigned long	*sp;
-	unsigned char	*tp;
-	int		i;
-
-	printk("\nCURRENT PROCESS:\n\n");
-	printk("COMM=%s PID=%d\n", current->comm, current->pid);
-	if (current->mm) {
-		printk("TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n",
-			(int) current->mm->start_code,
-			(int) current->mm->end_code,
-			(int) current->mm->start_data,
-			(int) current->mm->end_data,
-			(int) current->mm->end_data,
-			(int) current->mm->brk);
-		printk("USER-STACK=%08x  KERNEL-STACK=%08lx\n\n",
-			(int) current->mm->start_stack,
-			(int) PAGE_SIZE+(unsigned long)current);
-	}
-
-	show_regs(fp);
-	printk("\nCODE:");
-	tp = ((unsigned char *) fp->pc) - 0x20;
-	for (sp = (unsigned long *) tp, i = 0; (i < 0x40);  i += 4) {
-		if ((i % 0x10) == 0)
-			printk("\n%08x: ", (int) (tp + i));
-		printk("%08x ", (int) *sp++);
-	}
-	printk("\n");
-
-	printk("\nKERNEL STACK:");
-	tp = ((unsigned char *) fp) - 0x40;
-	for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) {
-		if ((i % 0x10) == 0)
-			printk("\n%08x: ", (int) (tp + i));
-		printk("%08x ", (int) *sp++);
-	}
-	printk("\n");
-	if (STACK_MAGIC != *(unsigned long *)((unsigned long)current+PAGE_SIZE))
-                printk("(Possibly corrupted stack page??)\n");
-
-	printk("\n\n");
-}
-
-void die(const char *str, struct pt_regs *fp, unsigned long err)
-{
-	static int diecount;
-
-	oops_enter();
-
-	console_verbose();
-	spin_lock_irq(&die_lock);
-	report_bug(fp->pc, fp);
-	printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++diecount);
-	dump(fp);
-
-	spin_unlock_irq(&die_lock);
-	do_exit(SIGSEGV);
-}
-
-extern char _start, _etext;
-#define check_kernel_text(addr) \
-        ((addr >= (unsigned long)(&_start)) && \
-         (addr <  (unsigned long)(&_etext))) 
-
-static int kstack_depth_to_print = 24;
-
-void show_stack(struct task_struct *task, unsigned long *esp)
-{
-	unsigned long *stack,  addr;
-	int i;
-
-	if (esp == NULL)
-		esp = (unsigned long *) &esp;
-
-	stack = esp;
-
-	printk("Stack from %08lx:", (unsigned long)stack);
-	for (i = 0; i < kstack_depth_to_print; i++) {
-		if (((unsigned long)stack & (THREAD_SIZE - 1)) == 0)
-			break;
-		if (i % 8 == 0)
-			printk("\n       ");
-		printk(" %08lx", *stack++);
-	}
-
-	printk("\nCall Trace:");
-	i = 0;
-	stack = esp;
-	while (((unsigned long)stack & (THREAD_SIZE - 1)) != 0) {
-		addr = *stack++;
-		/*
-		 * If the address is either in the text segment of the
-		 * kernel, or in the region which contains vmalloc'ed
-		 * memory, it *may* be the address of a calling
-		 * routine; if so, print it so that someone tracing
-		 * down the cause of the crash will be able to figure
-		 * out the call path that was taken.
-		 */
-		if (check_kernel_text(addr)) {
-			if (i % 4 == 0)
-				printk("\n       ");
-			printk(" [<%08lx>]", addr);
-			i++;
-		}
-	}
-	printk("\n");
-}
-
-void show_trace_task(struct task_struct *tsk)
-{
-	show_stack(tsk,(unsigned long *)tsk->thread.esp0);
-}
diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S
deleted file mode 100644
index 3253fed..0000000
--- a/arch/h8300/kernel/vmlinux.lds.S
+++ /dev/null
@@ -1,157 +0,0 @@
-#include <asm-generic/vmlinux.lds.h>
-#include <asm/page.h>
-
-/* target memory map */
-#ifdef CONFIG_H8300H_GENERIC
-#define ROMTOP  0x000000
-#define ROMSIZE 0x400000
-#define RAMTOP  0x400000
-#define RAMSIZE 0x400000
-#endif
-
-#ifdef CONFIG_H8300H_AKI3068NET
-#define ROMTOP  0x000000
-#define ROMSIZE 0x080000
-#define RAMTOP  0x400000
-#define RAMSIZE 0x200000
-#endif
-
-#ifdef CONFIG_H8300H_H8MAX
-#define ROMTOP  0x000000
-#define ROMSIZE 0x080000
-#define RAMTOP  0x400000
-#define RAMSIZE 0x200000
-#endif
-
-#ifdef CONFIG_H8300H_SIM
-#define ROMTOP  0x000000
-#define ROMSIZE 0x400000
-#define RAMTOP  0x400000
-#define RAMSIZE 0x400000
-#endif
-
-#ifdef CONFIG_H8S_SIM
-#define ROMTOP  0x000000
-#define ROMSIZE 0x400000
-#define RAMTOP  0x400000
-#define RAMSIZE 0x800000
-#endif
-
-#ifdef CONFIG_H8S_EDOSK2674
-#define ROMTOP  0x000000
-#define ROMSIZE 0x400000
-#define RAMTOP  0x400000
-#define RAMSIZE 0x800000
-#endif
-
-#if defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM)
-INPUT(romfs.o)
-#endif
-
-_jiffies = _jiffies_64 + 4;
-
-ENTRY(__start)
-
-SECTIONS
-{
-#if defined(CONFIG_ROMKERNEL)
-	. = ROMTOP; 
-	.vectors :
-	{
-	__vector = . ;
-		*(.vectors*)
-	}
-#else
-	. = RAMTOP; 
-	.bootvec :	
-	{
-		*(.bootvec)
-	}
-#endif
-        .text :
-	{
-	_text = .;
-#if defined(CONFIG_ROMKERNEL)
-	*(.int_redirect)
-#endif
-	__stext = . ;
-	TEXT_TEXT
-	SCHED_TEXT
-	LOCK_TEXT
-	__etext = . ;
-	}
-	EXCEPTION_TABLE(16)
-
-	RODATA
-#if defined(CONFIG_ROMKERNEL)
-	SECURITY_INIT
-#endif
-	ROEND = .; 
-#if defined(CONFIG_ROMKERNEL)
-	. = RAMTOP;
-	.data :	AT(ROEND)
-#else
-	.data :	
-#endif
-	{
-	__sdata = . ;
-	___data_start = . ;
-
-	INIT_TASK_DATA(0x2000)
-	. = ALIGN(0x4) ;
-		DATA_DATA
-	. = ALIGN(0x4) ;
-		*(.data.*)	
-
-	. = ALIGN(0x4) ;
-	___init_begin = .;
-	__sinittext = .; 
-		INIT_TEXT
-	__einittext = .; 
-		INIT_DATA
-	. = ALIGN(0x4) ;
-	INIT_SETUP(0x4)
-	___setup_start = .;
-		*(.init.setup)
-	. = ALIGN(0x4) ;
-	___setup_end = .;
-	INIT_CALLS
-	CON_INITCALL
-		EXIT_TEXT
-		EXIT_DATA
-	INIT_RAM_FS
-	. = ALIGN(0x4) ;
-	___init_end = .;
-	__edata = . ;
-	}
-#if defined(CONFIG_RAMKERNEL)
-	SECURITY_INIT
-#endif
-	__begin_data = LOADADDR(.data);
-        .bss : 
-        {
-	. = ALIGN(0x4) ;
-	__sbss = . ;
-	___bss_start = . ;
-		*(.bss*)
-	. = ALIGN(0x4) ;
-		*(COMMON)
-	. = ALIGN(0x4) ;
-	___bss_stop = . ;
-	__ebss = . ;
-	__end = . ;
-	__ramstart = .;
-	}
-        .romfs :	
-	{
-		*(.romfs*)
-	}
-	. = RAMTOP+RAMSIZE;
-        .dummy :
-        {
-	COMMAND_START = . - 0x200 ;
-	__ramend = . ;
-	}
-
-	DISCARDS
-}
diff --git a/arch/h8300/lib/Makefile b/arch/h8300/lib/Makefile
deleted file mode 100644
index 1577f50..0000000
--- a/arch/h8300/lib/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for H8/300-specific library files..
-#
-
-lib-y  = ashrdi3.o checksum.o memcpy.o memset.o abs.o romfs.o
diff --git a/arch/h8300/lib/abs.S b/arch/h8300/lib/abs.S
deleted file mode 100644
index ddd1fb3..0000000
--- a/arch/h8300/lib/abs.S
+++ /dev/null
@@ -1,21 +0,0 @@
-;;; abs.S
-
-#include <asm/linkage.h>
-
-#if defined(__H8300H__) 
-	.h8300h
-#endif
-#if defined(__H8300S__) 
-	.h8300s
-#endif
-	.text
-.global _abs
-
-;;; int abs(int n)
-_abs:
-	mov.l	er0,er0
-	bpl	1f
-	neg.l	er0
-1:
-	rts
-	
diff --git a/arch/h8300/lib/ashrdi3.c b/arch/h8300/lib/ashrdi3.c
deleted file mode 100644
index 78efb65..0000000
--- a/arch/h8300/lib/ashrdi3.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
-/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-#define BITS_PER_UNIT 8
-
-typedef 	 int SItype	__attribute__ ((mode (SI)));
-typedef unsigned int USItype	__attribute__ ((mode (SI)));
-typedef		 int DItype	__attribute__ ((mode (DI)));
-typedef int word_type __attribute__ ((mode (__word__)));
-
-struct DIstruct {SItype high, low;};
-
-typedef union
-{
-  struct DIstruct s;
-  DItype ll;
-} DIunion;
-
-DItype
-__ashrdi3 (DItype u, word_type b)
-{
-  DIunion w;
-  word_type bm;
-  DIunion uu;
-
-  if (b == 0)
-    return u;
-
-  uu.ll = u;
-
-  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
-  if (bm <= 0)
-    {
-      /* w.s.high = 1..1 or 0..0 */
-      w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
-      w.s.low = uu.s.high >> -bm;
-    }
-  else
-    {
-      USItype carries = (USItype)uu.s.high << bm;
-      w.s.high = uu.s.high >> b;
-      w.s.low = ((USItype)uu.s.low >> b) | carries;
-    }
-
-  return w.ll;
-}
diff --git a/arch/h8300/lib/checksum.c b/arch/h8300/lib/checksum.c
deleted file mode 100644
index bdc5b03..0000000
--- a/arch/h8300/lib/checksum.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * INET		An implementation of the TCP/IP protocol suite for the LINUX
- *		operating system.  INET is implemented using the  BSD Socket
- *		interface as the means of communication with the user level.
- *
- *		IP/TCP/UDP checksumming routines
- *
- * Authors:	Jorge Cwik, <jorge@laser.satlink.net>
- *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
- *		Tom May, <ftom@netcom.com>
- *		Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
- *		Lots of code moved from tcp.c and ip.c; see those files
- *		for more names.
- *
- * 03/02/96	Jes Sorensen, Andreas Schwab, Roman Hodek:
- *		Fixed some nasty bugs, causing some horrible crashes.
- *		A: At some points, the sum (%0) was used as
- *		length-counter instead of the length counter
- *		(%1). Thanks to Roman Hodek for pointing this out.
- *		B: GCC seems to mess up if one uses too many
- *		data-registers to hold input values and one tries to
- *		specify d0 and d1 as scratch registers. Letting gcc choose these
- *      registers itself solves the problem.
- *
- *		This program is free software; you can redistribute it and/or
- *		modify it under the terms of the GNU General Public License
- *		as published by the Free Software Foundation; either version
- *		2 of the License, or (at your option) any later version.
- */
- 
-/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access kills, so most
-   of the assembly has to go. */
-
-#include <net/checksum.h>
-#include <linux/module.h>
-
-static inline unsigned short from32to16(unsigned long x)
-{
-	/* add up 16-bit and 16-bit for 16+c bit */
-	x = (x & 0xffff) + (x >> 16);
-	/* add up carry.. */
-	x = (x & 0xffff) + (x >> 16);
-	return x;
-}
-
-static unsigned long do_csum(const unsigned char * buff, int len)
-{
-	int odd, count;
-	unsigned long result = 0;
-
-	if (len <= 0)
-		goto out;
-	odd = 1 & (unsigned long) buff;
-	if (odd) {
-		result = *buff;
-		len--;
-		buff++;
-	}
-	count = len >> 1;		/* nr of 16-bit words.. */
-	if (count) {
-		if (2 & (unsigned long) buff) {
-			result += *(unsigned short *) buff;
-			count--;
-			len -= 2;
-			buff += 2;
-		}
-		count >>= 1;		/* nr of 32-bit words.. */
-		if (count) {
-		        unsigned long carry = 0;
-			do {
-				unsigned long w = *(unsigned long *) buff;
-				count--;
-				buff += 4;
-				result += carry;
-				result += w;
-				carry = (w > result);
-			} while (count);
-			result += carry;
-			result = (result & 0xffff) + (result >> 16);
-		}
-		if (len & 2) {
-			result += *(unsigned short *) buff;
-			buff += 2;
-		}
-	}
-	if (len & 1)
-		result += (*buff << 8);
-	result = from32to16(result);
-	if (odd)
-		result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
-out:
-	return result;
-}
-
-/*
- *	This is a version of ip_compute_csum() optimized for IP headers,
- *	which always checksum on 4 octet boundaries.
- */
-__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
-{
-	return (__force __sum16)~do_csum(iph,ihl*4);
-}
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-/*
- * Egads...  That thing apparently assumes that *all* checksums it ever sees will
- * be folded.  Very likely a bug.
- */
-__wsum csum_partial(const void *buff, int len, __wsum sum)
-{
-	unsigned int result = do_csum(buff, len);
-
-	/* add in old sum, and carry.. */
-	result += (__force u32)sum;
-	/* 16+c bits -> 16 bits */
-	result = (result & 0xffff) + (result >> 16);
-	return (__force __wsum)result;
-}
-
-EXPORT_SYMBOL(csum_partial);
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-__sum16 ip_compute_csum(const void *buff, int len)
-{
-	return (__force __sum16)~do_csum(buff,len);
-}
-
-/*
- * copy from fs while checksumming, otherwise like csum_partial
- */
-
-__wsum
-csum_partial_copy_from_user(const void __user *src, void *dst, int len,
-			    __wsum sum, int *csum_err)
-{
-	if (csum_err) *csum_err = 0;
-	memcpy(dst, (__force const void *)src, len);
-	return csum_partial(dst, len, sum);
-}
-
-/*
- * copy from ds while checksumming, otherwise like csum_partial
- */
-
-__wsum
-csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
-{
-	memcpy(dst, src, len);
-	return csum_partial(dst, len, sum);
-}
diff --git a/arch/h8300/lib/memcpy.S b/arch/h8300/lib/memcpy.S
deleted file mode 100644
index cad325e..0000000
--- a/arch/h8300/lib/memcpy.S
+++ /dev/null
@@ -1,84 +0,0 @@
-;;; memcpy.S
-
-#include <asm/linkage.h>
-
-#if defined(__H8300H__) 
-	.h8300h
-#endif
-#if defined(__H8300S__) 
-	.h8300s
-#endif
-
-	.text
-.global _memcpy
-
-;;; void *memcpy(void *to, void *from, size_t n)
-_memcpy:
-	mov.l	er2,er2
-	bne	1f
-	rts	
-1:	
-	;; address check
-	bld	#0,r0l
-	bxor	#0,r1l
-	bcs	4f
-	mov.l	er4,@-sp
-	mov.l	er0,@-sp
-	btst	#0,r0l
-	beq	1f
-	;; (aligned even) odd address
-	mov.b	@er1,r3l
-	mov.b	r3l,@er0
-	adds	#1,er1
-	adds	#1,er0
-	dec.l	#1,er2
-	beq	3f
-1:	
-	;; n < sizeof(unsigned long) check
-	sub.l	er4,er4
-	adds	#4,er4		; loop count check value
-	cmp.l	er4,er2
-	blo	2f
-	;; unsigned long copy
-1:	
-	mov.l	@er1,er3
-	mov.l	er3,@er0
-	adds	#4,er0
-	adds	#4,er1
-	subs	#4,er2
-	cmp.l	er4,er2
-	bcc	1b	
-	;; rest
-2:	
-	mov.l	er2,er2
-	beq	3f
-1:	
-	mov.b	@er1,r3l
-	mov.b	r3l,@er0
-	adds	#1,er1
-	adds	#1,er0
-	dec.l	#1,er2
-	bne	1b
-3:
-	mov.l	@sp+,er0
-	mov.l	@sp+,er4
-	rts
-
-	;; odd <- even / even <- odd
-4:	
-	mov.l	er4,er3
-	mov.l	er2,er4
-	mov.l	er5,er2
-	mov.l	er1,er5
-	mov.l	er6,er1
-	mov.l	er0,er6
-1:
-	eepmov.w
-	mov.w	r4,r4
-	bne	1b
-	dec.w	#1,e4
-	bpl	1b
-	mov.l	er1,er6
-	mov.l	er2,er5
-	mov.l	er3,er4
-	rts
diff --git a/arch/h8300/lib/memset.S b/arch/h8300/lib/memset.S
deleted file mode 100644
index 4549a64..0000000
--- a/arch/h8300/lib/memset.S
+++ /dev/null
@@ -1,61 +0,0 @@
-/* memset.S */
-
-#include <asm/linkage.h>
-
-#if defined(__H8300H__) 
-	.h8300h
-#endif
-#if defined(__H8300S__) 
-	.h8300s
-#endif
-	.text
-
-.global	_memset
-
-;;void *memset(*ptr, int c, size_t count)
-;; ptr = er0
-;; c   = er1(r1l)
-;; count = er2
-_memset:
-	btst	#0,r0l
-	beq	2f
-
-	;; odd address
-1:
-	mov.b	r1l,@er0
-	adds	#1,er0
-	dec.l	#1,er2
-	beq	6f
-
-	;; even address
-2:
-	mov.l	er2,er3
-	cmp.l	#4,er2
-	blo	4f
-	;; count>=4 -> count/4
-#if defined(__H8300H__)
-	shlr.l	er2
-	shlr.l	er2
-#endif
-#if defined(__H8300S__)
-	shlr.l	#2,er2
-#endif
-	;; byte -> long
-	mov.b	r1l,r1h
-	mov.w	r1,e1
-3:
-	mov.l	er1,@er0
-	adds	#4,er0
-	dec.l	#1,er2
-	bne	3b
-4:
-	;; count % 4
-	and.b	#3,r3l
-	beq	6f
-5:
-	mov.b	r1l,@er0
-	adds	#1,er0
-	dec.b	r3l
-	bne	5b
-6:
-	rts
diff --git a/arch/h8300/lib/romfs.S b/arch/h8300/lib/romfs.S
deleted file mode 100644
index 68910d8..0000000
--- a/arch/h8300/lib/romfs.S
+++ /dev/null
@@ -1,57 +0,0 @@
-/* romfs move to __ebss */
-
-#include <asm/linkage.h>
-
-#if defined(__H8300H__) 
-	.h8300h
-#endif
-#if defined(__H8300S__) 
-	.h8300s
-#endif
-
-#define BLKOFFSET 512
-
-	.text
-.globl	__move_romfs
-_romfs_sig_len = 8
-
-__move_romfs:	
-	mov.l	#__sbss,er0
-	mov.l	#_romfs_sig,er1
-	mov.b	#_romfs_sig_len,r3l
-1:					/* check romfs image */
-	mov.b	@er0+,r2l
-	mov.b	@er1+,r2h
-	cmp.b	r2l,r2h
-	bne	2f
-	dec.b	r3l
-	bne	1b
-
-	/* find romfs image */
-	mov.l	@__sbss+8,er0		/* romfs length(be) */
-	mov.l	#__sbss,er1
-	add.l	er0,er1			/* romfs image end */
-	mov.l	#__ebss,er2
-	add.l	er0,er2			/* distination address */
-#if defined(CONFIG_INTELFLASH)
-	add.l	#BLKOFFSET,er2
-#endif
-	adds	#2,er0
-	adds	#1,er0
-	shlr	er0
-	shlr	er0			/* transfer length */
-1:
-	mov.l	@er1,er3		/* copy image */
-	mov.l	er3,@er2
-	subs	#4,er1
-	subs	#4,er2
-	dec.l	#1,er0
-	bpl	1b
-2:
-	rts
-
-	.section	.rodata
-_romfs_sig:	
-	.ascii	"-rom1fs-"
-
-	.end
diff --git a/arch/h8300/mm/Makefile b/arch/h8300/mm/Makefile
deleted file mode 100644
index 5f4bc42..0000000
--- a/arch/h8300/mm/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the linux m68k-specific parts of the memory manager.
-#
-
-obj-y	 := init.o fault.o memory.o kmap.o
diff --git a/arch/h8300/mm/fault.c b/arch/h8300/mm/fault.c
deleted file mode 100644
index 4725359..0000000
--- a/arch/h8300/mm/fault.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *  linux/arch/h8300/mm/fault.c
- *
- *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
- *  Copyright (C) 2000  Lineo, Inc.  (www.lineo.com) 
- *
- *  Based on:
- *
- *  linux/arch/m68knommu/mm/fault.c
- *  linux/arch/m68k/mm/fault.c
- *
- *  Copyright (C) 1995  Hamish Macdonald
- */
-
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/ptrace.h>
-
-#include <asm/pgtable.h>
-
-/*
- * This routine handles page faults.  It determines the problem, and
- * then passes it off to one of the appropriate routines.
- *
- * error_code:
- *	bit 0 == 0 means no page found, 1 means protection fault
- *	bit 1 == 0 means read, 1 means write
- *
- * If this routine detects a bad access, it returns 1, otherwise it
- * returns 0.
- */
-asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
-			      unsigned long error_code)
-{
-#ifdef DEBUG
-	printk ("regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld\n",
-		regs->sr, regs->pc, address, error_code);
-#endif
-
-/*
- * Oops. The kernel tried to access some bad page. We'll have to
- * terminate things with extreme prejudice.
- */
-	if ((unsigned long) address < PAGE_SIZE) {
-		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
-	} else
-		printk(KERN_ALERT "Unable to handle kernel access");
-	printk(" at virtual address %08lx\n",address);
-	if (!user_mode(regs))
-		die("Oops", regs, error_code);
-	do_exit(SIGKILL);
-
-	return 1;
-}
-
diff --git a/arch/h8300/mm/init.c b/arch/h8300/mm/init.c
deleted file mode 100644
index 6c1251e..0000000
--- a/arch/h8300/mm/init.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- *  linux/arch/h8300/mm/init.c
- *
- *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
- *                      Kenneth Albanowski <kjahds@kjahds.com>,
- *  Copyright (C) 2000  Lineo, Inc.  (www.lineo.com) 
- *
- *  Based on:
- *
- *  linux/arch/m68knommu/mm/init.c
- *  linux/arch/m68k/mm/init.c
- *
- *  Copyright (C) 1995  Hamish Macdonald
- *
- *  JAN/1999 -- hacked to support ColdFire (gerg@snapgear.com)
- *  DEC/2000 -- linux 2.4 support <davidm@snapgear.com>
- */
-
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/init.h>
-#include <linux/highmem.h>
-#include <linux/pagemap.h>
-#include <linux/bootmem.h>
-#include <linux/gfp.h>
-
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/sections.h>
-
-#undef DEBUG
-
-/*
- * BAD_PAGE is the page that is used for page faults when linux
- * is out-of-memory. Older versions of linux just did a
- * do_exit(), but using this instead means there is less risk
- * for a process dying in kernel mode, possibly leaving a inode
- * unused etc..
- *
- * BAD_PAGETABLE is the accompanying page-table: it is initialized
- * to point to BAD_PAGE entries.
- *
- * ZERO_PAGE is a special page that is used for zero-initialized
- * data and COW.
- */
-static unsigned long empty_bad_page_table;
-
-static unsigned long empty_bad_page;
-
-unsigned long empty_zero_page;
-
-extern unsigned long rom_length;
-
-extern unsigned long memory_start;
-extern unsigned long memory_end;
-
-/*
- * paging_init() continues the virtual memory environment setup which
- * was begun by the code in arch/head.S.
- * The parameters are pointers to where to stick the starting and ending
- * addresses of available kernel virtual memory.
- */
-void __init paging_init(void)
-{
-	/*
-	 * Make sure start_mem is page aligned,  otherwise bootmem and
-	 * page_alloc get different views og the world.
-	 */
-#ifdef DEBUG
-	unsigned long start_mem = PAGE_ALIGN(memory_start);
-#endif
-	unsigned long end_mem   = memory_end & PAGE_MASK;
-
-#ifdef DEBUG
-	printk ("start_mem is %#lx\nvirtual_end is %#lx\n",
-		start_mem, end_mem);
-#endif
-
-	/*
-	 * Initialize the bad page table and bad page to point
-	 * to a couple of allocated pages.
-	 */
-	empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
-	empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
-	empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
-	memset((void *)empty_zero_page, 0, PAGE_SIZE);
-
-	/*
-	 * Set up SFC/DFC registers (user data space).
-	 */
-	set_fs (USER_DS);
-
-#ifdef DEBUG
-	printk ("before free_area_init\n");
-
-	printk ("free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n",
-		start_mem, end_mem);
-#endif
-
-	{
-		unsigned long zones_size[MAX_NR_ZONES] = {0, };
-
-		zones_size[ZONE_DMA]     = 0 >> PAGE_SHIFT;
-		zones_size[ZONE_NORMAL]  = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
-#ifdef CONFIG_HIGHMEM
-		zones_size[ZONE_HIGHMEM] = 0;
-#endif
-		free_area_init(zones_size);
-	}
-}
-
-void __init mem_init(void)
-{
-	unsigned long codesize = _etext - _stext;
-
-	pr_devel("Mem_init: start=%lx, end=%lx\n", memory_start, memory_end);
-
-	high_memory = (void *) (memory_end & PAGE_MASK);
-	max_mapnr = MAP_NR(high_memory);
-
-	/* this will put all low memory onto the freelists */
-	free_all_bootmem();
-
-	mem_init_print_info(NULL);
-	if (rom_length > 0 && rom_length > codesize)
-		pr_info("Memory available: %luK/%luK ROM\n",
-			(rom_length - codesize) >> 10, rom_length >> 10);
-}
-
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-	free_reserved_area((void *)start, (void *)end, -1, "initrd");
-}
-#endif
-
-void
-free_initmem(void)
-{
-#ifdef CONFIG_RAMKERNEL
-	free_initmem_default(-1);
-#endif
-}
-
diff --git a/arch/h8300/mm/kmap.c b/arch/h8300/mm/kmap.c
deleted file mode 100644
index f79edcd..0000000
--- a/arch/h8300/mm/kmap.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *  linux/arch/h8300/mm/kmap.c
- *  
- *  Based on
- *  linux/arch/m68knommu/mm/kmap.c
- *
- *  Copyright (C) 2000 Lineo, <davidm@snapgear.com>
- *  Copyright (C) 2000-2002 David McCullough <davidm@snapgear.com>
- */
-
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/vmalloc.h>
-
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/page.h>
-#include <asm/pgalloc.h>
-#include <asm/io.h>
-
-#undef DEBUG
-
-#define VIRT_OFFSET (0x01000000)
-
-/*
- * Map some physical address range into the kernel address space.
- */
-void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
-{
-	return (void *)(physaddr + VIRT_OFFSET);
-}
-
-/*
- * Unmap a ioremap()ed region again.
- */
-void iounmap(void *addr)
-{
-}
-
-/*
- * __iounmap unmaps nearly everything, so be careful
- * it doesn't free currently pointer/page tables anymore but it
- * wans't used anyway and might be added later.
- */
-void __iounmap(void *addr, unsigned long size)
-{
-}
-
-/*
- * Set new cache mode for some kernel address space.
- * The caller must push data for that range itself, if such data may already
- * be in the cache.
- */
-void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
-{
-}
diff --git a/arch/h8300/mm/memory.c b/arch/h8300/mm/memory.c
deleted file mode 100644
index 06e3646..0000000
--- a/arch/h8300/mm/memory.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *  linux/arch/h8300/mm/memory.c
- *
- *  Copyright (C) 2002  Yoshinori Sato <ysato@users.sourceforge.jp>,
- *
- *  Based on:
- *
- *  linux/arch/m68knommu/mm/memory.c
- *
- *  Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>,
- *  Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
- *
- *  Based on:
- *
- *  linux/arch/m68k/mm/memory.c
- *
- *  Copyright (C) 1995  Hamish Macdonald
- */
-
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/types.h>
-
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/traps.h>
-#include <asm/io.h>
-
-void cache_clear (unsigned long paddr, int len)
-{
-}
-
-
-void cache_push (unsigned long paddr, int len)
-{
-}
-
-void cache_push_v (unsigned long vaddr, int len)
-{
-}
-
-/*
- * Map some physical address range into the kernel address space.
- */
-
-unsigned long kernel_map(unsigned long paddr, unsigned long size,
-			 int nocacheflag, unsigned long *memavailp )
-{
-	return paddr;
-}
-
diff --git a/arch/h8300/platform/h8300h/Makefile b/arch/h8300/platform/h8300h/Makefile
deleted file mode 100644
index 420f73b..0000000
--- a/arch/h8300/platform/h8300h/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-# Reuse any files we can from the H8/300H
-#
-
-obj-y := irq.o ptrace_h8300h.o
diff --git a/arch/h8300/platform/h8300h/aki3068net/Makefile b/arch/h8300/platform/h8300h/aki3068net/Makefile
deleted file mode 100644
index b7ff780..0000000
--- a/arch/h8300/platform/h8300h/aki3068net/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-extra-y := crt0_ram.o
diff --git a/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S b/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S
deleted file mode 100644
index b2ad0f2..0000000
--- a/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- *  linux/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- *  Platform depend startup
- *  Target Archtecture:	AE-3068 (aka. aki3068net)
- *  Memory Layout     :	RAM
- */
-
-#define ASSEMBLY
-
-#include <asm/linkage.h>
-	
-#if !defined(CONFIG_BLKDEV_RESERVE)
-#if defined(CONFIG_GDB_DEBUG)
-#define RAMEND (__ramend - 0xc000)
-#else
-#define RAMEND __ramend
-#endif
-#else
-#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS
-#endif
-	
-	.global __start
-	.global _command_line
-	.global __platform_gpio_table
-	.global __target_name
-	
-	.h8300h
-
-	.section .text
-	.file	"crt0_ram.S"
-
-	/* CPU Reset entry */
-__start:
-	mov.l	#RAMEND,sp
-	ldc	#0x80,ccr
-
-	/* Peripheral Setup */
-	
-#if defined(CONFIG_MTD_UCLINUX)
-	/* move romfs image */
-	jsr	@__move_romfs	
-#endif
-	
-	/* .bss clear */
-	mov.l	#__sbss,er5
-	mov.l	#__ebss,er4
-	sub.l	er5,er4
-	shlr	er4
-	shlr	er4
-	sub.l	er0,er0
-1:	
-	mov.l	er0,@er5
-	adds	#4,er5
-	dec.l	#1,er4
-	bne	1b
-
-	/* copy kernel commandline */
-	mov.l	#COMMAND_START,er5
-	mov.l	#_command_line,er6
-	mov.w	#512,r4
-	eepmov.w
-
-	/* uClinux kernel start */
-	ldc	#0x90,ccr	/* running kernel */
-	mov.l	#_init_thread_union,sp
-	add.l	#0x2000,sp
-	jsr	@_start_kernel
-_exit:
-
-	jmp	_exit
-
-	rts
-
-	/* I/O port assign information */
-__platform_gpio_table:	
-	mov.l	#gpio_table,er0
-	rts
-
-gpio_table:
-	;; P1DDR
-	.byte	0xff,0xff
-	;; P2DDR
-	.byte	0xff,0xff
-	;; P3DDR
-	.byte	0xff,0x00
-	;; P4DDR
-	.byte	0x00,0x00
-	;; P5DDR
-	.byte	0x01,0x01
-	;; P6DDR
-	.byte	0x00,0x00
-	;; dummy
-	.byte	0x00,0x00
-	;; P8DDR
-	.byte	0x0c,0x0c
-	;; P9DDR
-	.byte	0x00,0x00
-	;; PADDR
-	.byte	0x00,0x00
-	;; PBDDR
-	.byte	0x30,0x30
-
-__target_name:	
-	.asciz	"AE-3068"
-	
-	.section .bootvec,"ax"
-	jmp	@__start
diff --git a/arch/h8300/platform/h8300h/generic/Makefile b/arch/h8300/platform/h8300h/generic/Makefile
deleted file mode 100644
index 2b12a17..0000000
--- a/arch/h8300/platform/h8300h/generic/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-extra-y :=  crt0_$(MODEL).o
diff --git a/arch/h8300/platform/h8300h/generic/crt0_ram.S b/arch/h8300/platform/h8300h/generic/crt0_ram.S
deleted file mode 100644
index 5ab7d9c..0000000
--- a/arch/h8300/platform/h8300h/generic/crt0_ram.S
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- *  linux/arch/h8300/platform/h8300h/generic/crt0_ram.S
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- *  Platform depend startup
- *  Target Archtecture:	AE-3068 (aka. aki3068net)
- *  Memory Layout     :	RAM
- */
-
-#define ASSEMBLY
-
-#include <asm/linkage.h>
-	
-#if !defined(CONFIG_BLKDEV_RESERVE)
-#if defined(CONFIG_GDB_DEBUG)
-#define RAMEND (__ramend - 0xc000)
-#else
-#define RAMEND __ramend
-#endif
-#else
-#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS
-#endif
-	
-	.global __start
-	.global _command_line
-	.global __platform_gpio_table
-	.global __target_name
-	
-	.h8300h
-
-	.section .text
-	.file	"crt0_ram.S"
-
-	/* CPU Reset entry */
-__start:
-	mov.l	#RAMEND,sp
-	ldc	#0x80,ccr
-
-	/* Peripheral Setup */
-	
-#if defined(CONFIG_BLK_DEV_BLKMEM)
-	/* move romfs image */
-	jsr	@__move_romfs	
-#endif
-	
-	/* .bss clear */
-	mov.l	#__sbss,er5
-	mov.l	#__ebss,er4
-	sub.l	er5,er4
-	shlr	er4
-	shlr	er4
-	sub.l	er0,er0
-1:	
-	mov.l	er0,@er5
-	adds	#4,er5
-	dec.l	#1,er4
-	bne	1b
-
-	/* copy kernel commandline */
-	mov.l	#COMMAND_START,er5
-	mov.l	#_command_line,er6
-	mov.w	#512,r4
-	eepmov.w
-
-	/* uClinux kernel start */
-	ldc	#0x90,ccr	/* running kernel */
-	mov.l	#_init_thread_union,sp
-	add.l	#0x2000,sp
-	jsr	@_start_kernel
-_exit:
-
-	jmp	_exit
-
-	rts
-
-	/* I/O port assign information */
-__platform_gpio_table:	
-	mov.l	#gpio_table,er0
-	rts
-
-gpio_table:
-	;; P1DDR
-	.byte	0x00,0x00
-	;; P2DDR
-	.byte	0x00,0x00
-	;; P3DDR
-	.byte	0x00,0x00
-	;; P4DDR
-	.byte	0x00,0x00
-	;; P5DDR
-	.byte	0x00,0x00
-	;; P6DDR
-	.byte	0x00,0x00
-	;; dummy
-	.byte	0x00,0x00
-	;; P8DDR
-	.byte	0x00,0x00
-	;; P9DDR
-	.byte	0x00,0x00
-	;; PADDR
-	.byte	0x00,0x00
-	;; PBDDR
-	.byte	0x00,0x00
-
-__target_name:	
-	.asciz	"generic"
diff --git a/arch/h8300/platform/h8300h/generic/crt0_rom.S b/arch/h8300/platform/h8300h/generic/crt0_rom.S
deleted file mode 100644
index dda1dfa..0000000
--- a/arch/h8300/platform/h8300h/generic/crt0_rom.S
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- *  linux/arch/h8300/platform/h8300h/generic/crt0_rom.S
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- *  Platform depend startup
- *  Target Archtecture:	generic
- *  Memory Layout     :	ROM
- */
-
-#define ASSEMBLY
-
-#include <asm/linkage.h>
-	
-	.global __start
-	.global __command_line
-	.global __platform_gpio_table
-	.global __target_name
-	
-	.h8300h
-	.section .text
-	.file	"crt0_rom.S"
-
-	/* CPU Reset entry */
-__start:
-	mov.l	#__ramend,sp
-	ldc	#0x80,ccr
-
-	/* Peripheral Setup */
-	
-	/* .bss clear */
-	mov.l	#__sbss,er5
-	mov.l	#__ebss,er4
-	sub.l	er5,er4
-	shlr	er4
-	shlr	er4
-	sub.l	er0,er0
-1:	
-	mov.l	er0,@er5
-	adds	#4,er5
-	dec.l	#1,er4
-	bne	1b
-
-	/* copy .data */
-#if !defined(CONFIG_H8300H_SIM)
-	/* copy .data */
-	mov.l	#__begin_data,er5
-	mov.l	#__sdata,er6
-	mov.l	#__edata,er4
-	sub.l	er6,er4
-	shlr.l	er4
-	shlr.l	er4
-1:	
-	mov.l	@er5+,er0
-	mov.l	er0,@er6
-	adds	#4,er6
-	dec.l	#1,er4
-	bne	1b	
-#endif
-
-	/* copy kernel commandline */
-	mov.l	#COMMAND_START,er5
-	mov.l	#__command_line,er6
-	mov.w	#512,r4
-	eepmov.w
-
-	/* linux kernel start */
-	ldc	#0x90,ccr	/* running kernel */
-	mov.l	#_init_thread_union,sp
-	add.l	#0x2000,sp
-	jsr	@_start_kernel
-_exit:
-
-	jmp	_exit
-
-	rts
-
-	/* I/O port assign information */
-__platform_gpio_table:	
-	mov.l	#gpio_table,er0
-	rts
-
-gpio_table:
-	;; P1DDR
-	.byte	0x00,0x00
-	;; P2DDR
-	.byte	0x00,0x00
-	;; P3DDR
-	.byte	0x00,0x00
-	;; P4DDR
-	.byte	0x00,0x00
-	;; P5DDR
-	.byte	0x00,0x00
-	;; P6DDR
-	.byte	0x00,0x00
-	;; dummy
-	.byte	0x00,0x00
-	;; P8DDR
-	.byte	0x00,0x00
-	;; P9DDR
-	.byte	0x00,0x00
-	;; PADDR
-	.byte	0x00,0x00
-	;; PBDDR
-	.byte	0x00,0x00
-
-	.section .rodata
-__target_name:	
-	.asciz	"generic"
-	
-	.section .bss
-__command_line:	
-	.space	512
-
-	/* interrupt vector */
-	.section .vectors,"ax"
-	.long	__start
-vector	=	1
-	.rept	64-1
-	.long	_interrupt_redirect_table+vector*4
-vector	=	vector + 1
-	.endr
diff --git a/arch/h8300/platform/h8300h/h8max/Makefile b/arch/h8300/platform/h8300h/h8max/Makefile
deleted file mode 100644
index b7ff780..0000000
--- a/arch/h8300/platform/h8300h/h8max/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-extra-y := crt0_ram.o
diff --git a/arch/h8300/platform/h8300h/h8max/crt0_ram.S b/arch/h8300/platform/h8300h/h8max/crt0_ram.S
deleted file mode 100644
index 6a0d4e2..0000000
--- a/arch/h8300/platform/h8300h/h8max/crt0_ram.S
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- *  linux/arch/h8300/platform/h8300h/h8max/crt0_ram.S
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- *  Platform depend startup
- *  Target Archtecture:	H8MAX
- *  Memory Layout     :	RAM
- */
-
-#define ASSEMBLY
-
-#include <asm/linkage.h>
-	
-#if !defined(CONFIG_BLKDEV_RESERVE)
-#if defined(CONFIG_GDB_DEBUG)
-#define RAMEND (__ramend - 0xc000)
-#else
-#define RAMEND __ramend
-#endif
-#else
-#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS
-#endif
-	
-	.global __start
-	.global _command_line
-	.global __platform_gpio_table
-	.global __target_name
-	
-	.h8300h
-
-	.section .text
-	.file	"crt0_ram.S"
-
-	/* CPU Reset entry */
-__start:
-	mov.l	#RAMEND,sp
-	ldc	#0x80,ccr
-
-	/* Peripheral Setup */
-	
-#if defined(CONFIG_MTD_UCLINUX)
-	/* move romfs image */
-	jsr	@__move_romfs	
-#endif
-	
-	/* .bss clear */
-	mov.l	#__sbss,er5
-	mov.l	#__ebss,er4
-	sub.l	er5,er4
-	shlr	er4
-	shlr	er4
-	sub.l	er0,er0
-1:	
-	mov.l	er0,@er5
-	adds	#4,er5
-	dec.l	#1,er4
-	bne	1b
-
-	/* copy kernel commandline */
-	mov.l	#COMMAND_START,er5
-	mov.l	#_command_line,er6
-	mov.w	#512,r4
-	eepmov.w
-
-	/* uClinux kernel start */
-	ldc	#0x90,ccr	/* running kernel */
-	mov.l	#_init_thread_union,sp
-	add.l	#0x2000,sp
-	jsr	@_start_kernel
-_exit:
-
-	jmp	_exit
-
-	rts
-
-	/* I/O port assign information */
-__platform_gpio_table:	
-	mov.l	#gpio_table,er0
-	rts
-
-gpio_table:
-	;; P1DDR
-	.byte	0xff,0xff
-	;; P2DDR
-	.byte	0xff,0xff
-	;; P3DDR
-	.byte	0x00,0x00
-	;; P4DDR
-	.byte	0x00,0x00
-	;; P5DDR
-	.byte	0x01,0x01
-	;; P6DDR
-	.byte	0xf6,0xf6
-	;; dummy
-	.byte	0x00,0x00
-	;; P8DDR
-	.byte	0xee,0xee
-	;; P9DDR
-	.byte	0x00,0x00
-	;; PADDR
-	.byte	0x00,0x00
-	;; PBDDR
-	.byte	0x30,0x30
-
-__target_name:	
-	.asciz	"H8MAX"
-	
-	.section .bootvec,"ax"
-	jmp	@__start
diff --git a/arch/h8300/platform/h8300h/irq.c b/arch/h8300/platform/h8300h/irq.c
deleted file mode 100644
index 0a50353..0000000
--- a/arch/h8300/platform/h8300h/irq.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Interrupt handling H8/300H depend.
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- */
-
-#include <linux/init.h>
-#include <linux/errno.h>
-
-#include <asm/ptrace.h>
-#include <asm/traps.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/gpio-internal.h>
-#include <asm/regs306x.h>
-
-const int __initconst h8300_saved_vectors[] = {
-#if defined(CONFIG_GDB_DEBUG)
-	TRAP3_VEC,	/* TRAPA #3 is GDB breakpoint */
-#endif
-	-1,
-};
-
-const h8300_vector __initconst h8300_trap_table[] = {
-	0, 0, 0, 0, 0, 0, 0, 0,
-	system_call,
-	0,
-	0,
-	trace_break,
-};
-
-int h8300_enable_irq_pin(unsigned int irq)
-{
-	int bitmask;
-	if (irq < EXT_IRQ0 || irq > EXT_IRQ5)
-		return 0;
-
-	/* initialize IRQ pin */
-	bitmask = 1 << (irq - EXT_IRQ0);
-	switch(irq) {
-	case EXT_IRQ0:
-	case EXT_IRQ1:
-	case EXT_IRQ2:
-	case EXT_IRQ3:
-		if (H8300_GPIO_RESERVE(H8300_GPIO_P8, bitmask) == 0)
-			return -EBUSY;
-		H8300_GPIO_DDR(H8300_GPIO_P8, bitmask, H8300_GPIO_INPUT);
-		break;
-	case EXT_IRQ4:
-	case EXT_IRQ5:
-		if (H8300_GPIO_RESERVE(H8300_GPIO_P9, bitmask) == 0)
-			return -EBUSY;
-		H8300_GPIO_DDR(H8300_GPIO_P9, bitmask, H8300_GPIO_INPUT);
-		break;
-	}
-
-	return 0;
-}
-
-void h8300_disable_irq_pin(unsigned int irq)
-{
-	int bitmask;
-	if (irq < EXT_IRQ0 || irq > EXT_IRQ5)
-		return;
-
-	/* disable interrupt & release IRQ pin */
-	bitmask = 1 << (irq - EXT_IRQ0);
-	switch(irq) {
-	case EXT_IRQ0:
-	case EXT_IRQ1:
-	case EXT_IRQ2:
-	case EXT_IRQ3:
-		*(volatile unsigned char *)IER &= ~bitmask;
-		H8300_GPIO_FREE(H8300_GPIO_P8, bitmask);
-		break ;
-	case EXT_IRQ4:
-	case EXT_IRQ5:
-		*(volatile unsigned char *)IER &= ~bitmask;
-		H8300_GPIO_FREE(H8300_GPIO_P9, bitmask);
-		break;
-	}
-}
diff --git a/arch/h8300/platform/h8300h/ptrace_h8300h.c b/arch/h8300/platform/h8300h/ptrace_h8300h.c
deleted file mode 100644
index 4f1ed02..0000000
--- a/arch/h8300/platform/h8300h/ptrace_h8300h.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- *  linux/arch/h8300/platform/h8300h/ptrace_h8300h.c
- *    ptrace cpu depend helper functions
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of
- * this archive for more details.
- */
-
-#include <linux/linkage.h>
-#include <linux/sched.h>
-#include <asm/ptrace.h>
-
-#define CCR_MASK 0x6f    /* mode/imask not set */
-#define BREAKINST 0x5730 /* trapa #3 */
-
-/* Mapping from PT_xxx to the stack offset at which the register is
-   saved.  Notice that usp has no stack-slot and needs to be treated
-   specially (see get_reg/put_reg below). */
-static const int h8300_register_offset[] = {
-	PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4),
-	PT_REG(er5), PT_REG(er6), PT_REG(er0), PT_REG(orig_er0),
-	PT_REG(ccr), PT_REG(pc)
-};
-
-/* read register */
-long h8300_get_reg(struct task_struct *task, int regno)
-{
-	switch (regno) {
-	case PT_USP:
-		return task->thread.usp + sizeof(long)*2;
-	case PT_CCR:
-	    return *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
-	default:
-	    return *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]);
-	}
-}
-
-/* write register */
-int h8300_put_reg(struct task_struct *task, int regno, unsigned long data)
-{
-	unsigned short oldccr;
-	switch (regno) {
-	case PT_USP:
-		task->thread.usp = data - sizeof(long)*2;
-	case PT_CCR:
-		oldccr = *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
-		oldccr &= ~CCR_MASK;
-		data &= CCR_MASK;
-		data |= oldccr;
-		*(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
-		break;
-	default:
-		*(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
-		break;
-	}
-	return 0;
-}
-
-/* disable singlestep */
-void user_disable_single_step(struct task_struct *child)
-{
-	if((long)child->thread.breakinfo.addr != -1L) {
-		*child->thread.breakinfo.addr = child->thread.breakinfo.inst;
-		child->thread.breakinfo.addr = (unsigned short *)-1L;
-	}
-}
-
-/* calculate next pc */
-enum jump_type {none,    /* normal instruction */
-		jabs,    /* absolute address jump */
-		ind,     /* indirect address jump */
-		ret,     /* return to subrutine */
-		reg,     /* register indexed jump */
-		relb,    /* pc relative jump (byte offset) */
-		relw,    /* pc relative jump (word offset) */
-               };
-
-/* opcode decode table define
-   ptn: opcode pattern
-   msk: opcode bitmask
-   len: instruction length (<0 next table index)
-   jmp: jump operation mode */
-struct optable {
-	unsigned char bitpattern;
-	unsigned char bitmask;
-	signed char length;
-	signed char type;
-} __attribute__((aligned(1),packed));
-
-#define OPTABLE(ptn,msk,len,jmp)   \
-        {                          \
-		.bitpattern = ptn, \
-		.bitmask    = msk, \
-		.length	    = len, \
-		.type       = jmp, \
-	}
-
-static const struct optable optable_0[] = {
-	OPTABLE(0x00,0xff, 1,none), /* 0x00 */
-	OPTABLE(0x01,0xff,-1,none), /* 0x01 */
-	OPTABLE(0x02,0xfe, 1,none), /* 0x02-0x03 */
-	OPTABLE(0x04,0xee, 1,none), /* 0x04-0x05/0x14-0x15 */
-	OPTABLE(0x06,0xfe, 1,none), /* 0x06-0x07 */
-	OPTABLE(0x08,0xea, 1,none), /* 0x08-0x09/0x0c-0x0d/0x18-0x19/0x1c-0x1d */
-	OPTABLE(0x0a,0xee, 1,none), /* 0x0a-0x0b/0x1a-0x1b */
-	OPTABLE(0x0e,0xee, 1,none), /* 0x0e-0x0f/0x1e-0x1f */
-	OPTABLE(0x10,0xfc, 1,none), /* 0x10-0x13 */
-	OPTABLE(0x16,0xfe, 1,none), /* 0x16-0x17 */
-	OPTABLE(0x20,0xe0, 1,none), /* 0x20-0x3f */
-	OPTABLE(0x40,0xf0, 1,relb), /* 0x40-0x4f */
-	OPTABLE(0x50,0xfc, 1,none), /* 0x50-0x53 */
-	OPTABLE(0x54,0xfd, 1,ret ), /* 0x54/0x56 */
-	OPTABLE(0x55,0xff, 1,relb), /* 0x55 */
-	OPTABLE(0x57,0xff, 1,none), /* 0x57 */
-	OPTABLE(0x58,0xfb, 2,relw), /* 0x58/0x5c */
-	OPTABLE(0x59,0xfb, 1,reg ), /* 0x59/0x5b */
-	OPTABLE(0x5a,0xfb, 2,jabs), /* 0x5a/0x5e */
-	OPTABLE(0x5b,0xfb, 2,ind ), /* 0x5b/0x5f */
-	OPTABLE(0x60,0xe8, 1,none), /* 0x60-0x67/0x70-0x77 */
-	OPTABLE(0x68,0xfa, 1,none), /* 0x68-0x69/0x6c-0x6d */
-	OPTABLE(0x6a,0xfe,-2,none), /* 0x6a-0x6b */
-	OPTABLE(0x6e,0xfe, 2,none), /* 0x6e-0x6f */
-	OPTABLE(0x78,0xff, 4,none), /* 0x78 */
-	OPTABLE(0x79,0xff, 2,none), /* 0x79 */
-	OPTABLE(0x7a,0xff, 3,none), /* 0x7a */
-	OPTABLE(0x7b,0xff, 2,none), /* 0x7b */
-	OPTABLE(0x7c,0xfc, 2,none), /* 0x7c-0x7f */
-	OPTABLE(0x80,0x80, 1,none), /* 0x80-0xff */
-};
-
-static const struct optable optable_1[] = {
-	OPTABLE(0x00,0xff,-3,none), /* 0x0100 */
-	OPTABLE(0x40,0xf0,-3,none), /* 0x0140-0x14f */
-	OPTABLE(0x80,0xf0, 1,none), /* 0x0180-0x018f */
-	OPTABLE(0xc0,0xc0, 2,none), /* 0x01c0-0x01ff */
-};
-
-static const struct optable optable_2[] = {
-	OPTABLE(0x00,0x20, 2,none), /* 0x6a0?/0x6a8?/0x6b0?/0x6b8? */
-	OPTABLE(0x20,0x20, 3,none), /* 0x6a2?/0x6aa?/0x6b2?/0x6ba? */
-};
-
-static const struct optable optable_3[] = {
-	OPTABLE(0x69,0xfb, 2,none), /* 0x010069/0x01006d/014069/0x01406d */
-	OPTABLE(0x6b,0xff,-4,none), /* 0x01006b/0x01406b */
-	OPTABLE(0x6f,0xff, 3,none), /* 0x01006f/0x01406f */
-	OPTABLE(0x78,0xff, 5,none), /* 0x010078/0x014078 */
-};
-
-static const struct optable optable_4[] = {
-	OPTABLE(0x00,0x78, 3,none), /* 0x0100690?/0x01006d0?/0140690/0x01406d0?/0x0100698?/0x01006d8?/0140698?/0x01406d8? */
-	OPTABLE(0x20,0x78, 4,none), /* 0x0100692?/0x01006d2?/0140692/0x01406d2?/0x010069a?/0x01006da?/014069a?/0x01406da? */
-};
-
-static const struct optables_list {
-	const struct optable *ptr;
-	int size;
-} optables[] = {
-#define OPTABLES(no)                                                   \
-        {                                                              \
-		.ptr  = optable_##no,                                  \
-		.size = sizeof(optable_##no) / sizeof(struct optable), \
-	}
-	OPTABLES(0),
-	OPTABLES(1),
-	OPTABLES(2),
-	OPTABLES(3),
-	OPTABLES(4),
-
-};
-
-const unsigned char condmask[] = {
-	0x00,0x40,0x01,0x04,0x02,0x08,0x10,0x20
-};
-
-static int isbranch(struct task_struct *task,int reson)
-{
-	unsigned char cond = h8300_get_reg(task, PT_CCR);
-	/* encode complex conditions */
-	/* B4: N^V
-	   B5: Z|(N^V)
-	   B6: C|Z */
-	__asm__("bld #3,%w0\n\t"
-		"bxor #1,%w0\n\t"
-		"bst #4,%w0\n\t"
-		"bor #2,%w0\n\t"
-		"bst #5,%w0\n\t"
-		"bld #2,%w0\n\t"
-		"bor #0,%w0\n\t"
-		"bst #6,%w0\n\t"
-		:"=&r"(cond)::"cc");
-	cond &= condmask[reson >> 1];
-	if (!(reson & 1))
-		return cond == 0;
-	else
-		return cond != 0;
-}
-
-static unsigned short *getnextpc(struct task_struct *child, unsigned short *pc)
-{
-	const struct optable *op;
-	unsigned char *fetch_p;
-	unsigned char inst;
-	unsigned long addr;
-	unsigned long *sp;
-	int op_len,regno;
-	op = optables[0].ptr;
-	op_len = optables[0].size;
-	fetch_p = (unsigned char *)pc;
-	inst = *fetch_p++;
-	do {
-		if ((inst & op->bitmask) == op->bitpattern) {
-			if (op->length < 0) {
-				op = optables[-op->length].ptr;
-				op_len = optables[-op->length].size + 1;
-				inst = *fetch_p++;
-			} else {
-				switch (op->type) {
-				case none:
-					return pc + op->length;
-				case jabs:
-					addr = *(unsigned long *)pc;
-					return (unsigned short *)(addr & 0x00ffffff);
-				case ind:
-					addr = *pc & 0xff;
-					return (unsigned short *)(*(unsigned long *)addr);
-				case ret:
-					sp = (unsigned long *)h8300_get_reg(child, PT_USP);
-					/* user stack frames
-					   |   er0  | temporary saved
-					   +--------+
-					   |   exp  | exception stack frames
-					   +--------+
-					   | ret pc | userspace return address
-					*/
-					return (unsigned short *)(*(sp+2) & 0x00ffffff);
-				case reg:
-					regno = (*pc >> 4) & 0x07;
-					if (regno == 0)
-						addr = h8300_get_reg(child, PT_ER0);
-					else
-						addr = h8300_get_reg(child, regno-1+PT_ER1);
-					return (unsigned short *)addr;
-				case relb:
-					if (inst == 0x55 || isbranch(child,inst & 0x0f))
-						pc = (unsigned short *)((unsigned long)pc +
-								       ((signed char)(*fetch_p)));
-					return pc+1; /* skip myself */
-				case relw:
-					if (inst == 0x5c || isbranch(child,(*fetch_p & 0xf0) >> 4))
-						pc = (unsigned short *)((unsigned long)pc +
-								       ((signed short)(*(pc+1))));
-					return pc+2; /* skip myself */
-				}
-			}
-		} else
-			op++;
-	} while(--op_len > 0);
-	return NULL;
-}
-
-/* Set breakpoint(s) to simulate a single step from the current PC.  */
-
-void user_enable_single_step(struct task_struct *child)
-{
-	unsigned short *nextpc;
-	nextpc = getnextpc(child,(unsigned short *)h8300_get_reg(child, PT_PC));
-	child->thread.breakinfo.addr = nextpc;
-	child->thread.breakinfo.inst = *nextpc;
-	*nextpc = BREAKINST;
-}
-
-asmlinkage void trace_trap(unsigned long bp)
-{
-	if ((unsigned long)current->thread.breakinfo.addr == bp) {
-		user_disable_single_step(current);
-		force_sig(SIGTRAP,current);
-	} else
-	        force_sig(SIGILL,current);
-}
-
diff --git a/arch/h8300/platform/h8s/Makefile b/arch/h8300/platform/h8s/Makefile
deleted file mode 100644
index bf12418..0000000
--- a/arch/h8300/platform/h8s/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-# Reuse any files we can from the H8S
-#
-
-obj-y := ints_h8s.o ptrace_h8s.o
diff --git a/arch/h8300/platform/h8s/edosk2674/Makefile b/arch/h8300/platform/h8s/edosk2674/Makefile
deleted file mode 100644
index 8e34972..0000000
--- a/arch/h8300/platform/h8s/edosk2674/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-extra-y := crt0_$(MODEL).o
diff --git a/arch/h8300/platform/h8s/edosk2674/crt0_ram.S b/arch/h8300/platform/h8s/edosk2674/crt0_ram.S
deleted file mode 100644
index 5ed191b..0000000
--- a/arch/h8300/platform/h8s/edosk2674/crt0_ram.S
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- *  linux/arch/h8300/platform/h8s/edosk2674/crt0_ram.S
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- *  Platform depend startup
- *  Target Archtecture:	EDOSK-2674
- *  Memory Layout     :	RAM
- */
-
-#define ASSEMBLY
-
-#include <asm/linkage.h>
-#include <asm/regs267x.h>
-			
-#if !defined(CONFIG_BLKDEV_RESERVE)
-#if defined(CONFIG_GDB_DEBUG)
-#define RAMEND (__ramend - 0xc000)
-#else
-#define RAMEND __ramend
-#endif
-#else
-#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS
-#endif
-	
-	.global __start
-	.global __command_line
-	.global __platform_gpio_table
-	.global __target_name
-	
-	.h8300s
-
-	.section .text
-	.file	"crt0_ram.S"
-
-	/* CPU Reset entry */
-__start:
-	mov.l	#RAMEND,sp
-	ldc	#0x80,ccr
-	ldc	#0x00,exr
-
-	/* Peripheral Setup */
-	bclr	#4,@INTCR:8	/* interrupt mode 2 */
-	bset	#5,@INTCR:8
-	bclr	#0,@IER+1:16
-	bset	#1,@ISCRL+1:16	/* IRQ0 Positive Edge */
-	bclr	#0,@ISCRL+1:16
-
-#if defined(CONFIG_MTD_UCLINUX)
-	/* move romfs image */
-	jsr	@__move_romfs	
-#endif
-	
-	/* .bss clear */
-	mov.l	#__sbss,er5
-	mov.l	er5,er6
-	mov.l	#__ebss,er4
-	sub.l	er5,er4
-	shlr	#2,er4
-	sub.l	er0,er0
-1:	
-	mov.l	er0,@er5
-	adds	#4,er5
-	dec.l	#1,er4
-	bne	1b
-
-	/* copy kernel commandline */
-	mov.l	#COMMAND_START,er5
-	mov.l	#_command_line,er6
-	mov.w	#512,r4
-	eepmov.w
-
-	/* uClinux kernel start */
-	ldc	#0x90,ccr	/* running kernel */
-	mov.l	#_init_thread_union,sp
-	add.l	#0x2000,sp
-	jsr	@_start_kernel
-_exit:
-
-	jmp	_exit
-
-	rts
-
-	/* I/O port assign information */
-__platform_gpio_table:	
-	mov.l	#gpio_table,er0
-	rts
-
-gpio_table:
-	;; P1DDR
-	;;      used,ddr
-	.byte	0x00,0x00
-	;; P2DDR
-	.byte	0x00,0x00
-	;; P3DDR
-	.byte	0x3f,0x3a
-	;; dummy
-	.byte	0x00,0x00
-	;; P5DDR
-	.byte	0x00,0x00
-	;; P6DDR
-	.byte	0x00,0x00
-	;; P7DDR
-	.byte	0x00,0x00
-	;; P8DDR
-	.byte	0x00,0x00
-	;; dummy
-	.byte	0x00,0x00
-	;; PADDR
-	.byte	0xff,0xff
-	;; PBDDR
-	.byte	0xff,0x00
-	;; PCDDR
-	.byte	0xff,0x00
-	;; PDDDR
-	.byte	0xff,0x00
-	;; PEDDR
-	.byte	0xff,0x00
-	;; PFDDR
-	.byte	0xff,0xff
-	;; PGDDR
-	.byte	0x0f,0x0f
-	;; PHDDR
-	.byte	0x0f,0x0f
-
-__target_name:	
-	.asciz	"EDOSK-2674"
-	
-	.section .bootvec,"ax"
-	jmp	@__start
diff --git a/arch/h8300/platform/h8s/edosk2674/crt0_rom.S b/arch/h8300/platform/h8s/edosk2674/crt0_rom.S
deleted file mode 100644
index 06d1d7f..0000000
--- a/arch/h8300/platform/h8s/edosk2674/crt0_rom.S
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- *  linux/arch/h8300/platform/h8s/edosk2674/crt0_rom.S
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- *  Platform depend startup
- *  Target Archtecture:	EDOSK-2674
- *  Memory Layout     :	ROM
- */
-
-#define ASSEMBLY
-
-#include <asm/linkage.h>
-#include <asm/regs267x.h>
-		
-	.global __start
-	.global __command_line
-	.global __platform_gpio_table
-	.global __target_name
-	
-	.h8300s
-	.section .text
-	.file	"crt0_rom.S"
-
-	/* CPU Reset entry */
-__start:
-	mov.l	#__ramend,sp
-	ldc	#0x80,ccr
-	ldc	#0,exr
-	
-	/* Peripheral Setup */
-;BSC/GPIO setup
-	mov.l	#init_regs,er0
-	mov.w	#0xffff,e2
-1:
-	mov.w	@er0+,r2
-	beq	2f
-	mov.w	@er0+,r1
-	mov.b	r1l,@er2
-	bra	1b
-
-2:
-;SDRAM setup
-#define SDRAM_SMR 0x400040
-
-	mov.b	#0,r0l
-	mov.b	r0l,@DRACCR:16
-	mov.w	#0x188,r0
-	mov.w	r0,@REFCR:16
-	mov.w	#0x85b4,r0
-	mov.w	r0,@DRAMCR:16
-	mov.b	#0,r1l
-	mov.b	r1l,@SDRAM_SMR
-	mov.w	#0x84b4,r0
-	mov.w	r0,@DRAMCR:16
-;special thanks to Arizona Cooperative Power
-	
-	/* copy .data */
-	mov.l	#__begin_data,er5
-	mov.l	#__sdata,er6
-	mov.l	#__edata,er4
-	sub.l	er6,er4
-	shlr.l	#2,er4
-1:	
-	mov.l	@er5+,er0
-	mov.l	er0,@er6
-	adds	#4,er6
-	dec.l	#1,er4
-	bne	1b	
-
-	/* .bss clear */
-	mov.l	#__sbss,er5
-	mov.l	#__ebss,er4
-	sub.l	er5,er4
-	shlr.l	#2,er4		
-	sub.l	er0,er0
-1:
-	mov.l	er0,@er5
-	adds	#4,er5
-	dec.l	#1,er4
-	bne	1b
-
-	/* copy kernel commandline */
-	mov.l	#COMMAND_START,er5
-	mov.l	#__command_line,er6
-	mov.w	#512,r4
-	eepmov.w
-
-	/* linux kernel start */
-	ldc	#0x90,ccr	/* running kernel */
-	mov.l	#_init_thread_union,sp
-	add.l	#0x2000,sp
-	jsr	@_start_kernel
-_exit:
-
-	jmp	_exit
-
-	rts
-
-	/* I/O port assign information */
-__platform_gpio_table:	
-	mov.l	#gpio_table,er0
-	rts
-
-#define INIT_REGS_DATA(REGS,DATA) \
-	.word	((REGS) & 0xffff),DATA
-
-init_regs:
-INIT_REGS_DATA(ASTCR,0xff)
-INIT_REGS_DATA(RDNCR,0x00)
-INIT_REGS_DATA(ABWCR,0x80)
-INIT_REGS_DATA(WTCRAH,0x27)
-INIT_REGS_DATA(WTCRAL,0x77)
-INIT_REGS_DATA(WTCRBH,0x71)
-INIT_REGS_DATA(WTCRBL,0x22)
-INIT_REGS_DATA(CSACRH,0x80)
-INIT_REGS_DATA(CSACRL,0x80)
-INIT_REGS_DATA(BROMCRH,0xa0)
-INIT_REGS_DATA(BROMCRL,0xa0)
-INIT_REGS_DATA(P3DDR,0x3a)
-INIT_REGS_DATA(P3ODR,0x06)
-INIT_REGS_DATA(PADDR,0xff)
-INIT_REGS_DATA(PFDDR,0xfe)
-INIT_REGS_DATA(PGDDR,0x0f)
-INIT_REGS_DATA(PHDDR,0x0f)
-INIT_REGS_DATA(PFCR0,0xff)
-INIT_REGS_DATA(PFCR2,0x0d)
-INIT_REGS_DATA(ITSR, 0x00)
-INIT_REGS_DATA(ITSR+1,0x3f)
-INIT_REGS_DATA(INTCR,0x20)
-		
-	.word	0
-
-gpio_table:
-	;; P1DDR
-	.byte	0x00,0x00
-	;; P2DDR
-	.byte	0x00,0x00
-	;; P3DDR
-	.byte	0x00,0x00
-	;; dummy
-	.byte	0x00,0x00
-	;; P5DDR
-	.byte	0x00,0x00
-	;; P6DDR
-	.byte	0x00,0x00
-	;; P7DDR
-	.byte	0x00,0x00
-	;; P8DDR
-	.byte	0x00,0x00
-	;; dummy
-	.byte	0x00,0x00
-	;; PADDR
-	.byte	0x00,0x00
-	;; PBDDR
-	.byte	0x00,0x00
-	;; PCDDR
-	.byte	0x00,0x00
-	;; PDDDR
-	.byte	0x00,0x00
-	;; PEDDR
-	.byte	0x00,0x00
-	;; PFDDR
-	.byte	0x00,0x00
-	;; PGDDR
-	.byte	0x00,0x00
-	;; PHDDR
-	.byte	0x00,0x00
-
-	.section .rodata
-__target_name:	
-	.asciz	"EDOSK-2674"
-	
-	.section .bss
-__command_line:	
-	.space	512
-
-	/* interrupt vector */
-	.section .vectors,"ax"
-	.long	__start
-	.long	__start
-vector	=	2
-	.rept	126
-	.long	_interrupt_redirect_table+vector*4
-vector	=	vector + 1
-	.endr
diff --git a/arch/h8300/platform/h8s/generic/Makefile b/arch/h8300/platform/h8s/generic/Makefile
deleted file mode 100644
index 44b4685..0000000
--- a/arch/h8300/platform/h8s/generic/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-extra-y =  crt0_$(MODEL).o
diff --git a/arch/h8300/platform/h8s/generic/crt0_ram.S b/arch/h8300/platform/h8s/generic/crt0_ram.S
deleted file mode 100644
index 7018915..0000000
--- a/arch/h8300/platform/h8s/generic/crt0_ram.S
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- *  linux/arch/h8300/platform/h8s/edosk2674/crt0_ram.S
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- *  Platform depend startup
- *  Target Archtecture:	generic
- *  Memory Layout     :	RAM
- */
-
-#define ASSEMBLY
-
-#include <asm/linkage.h>
-#include <asm/regs267x.h>
-			
-#if !defined(CONFIG_BLKDEV_RESERVE)
-#if defined(CONFIG_GDB_DEBUG)
-#define RAMEND (__ramend - 0xc000)
-#else
-#define RAMEND __ramend
-#endif
-#else
-#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS
-#endif
-	
-	.global __start
-	.global __command_line
-	.global __platform_gpio_table
-	.global __target_name
-	
-	.h8300s
-
-	.section .text
-	.file	"crt0_ram.S"
-
-	/* CPU Reset entry */
-__start:
-	mov.l	#RAMEND,sp
-	ldc	#0x80,ccr
-	ldc	#0x00,exr
-
-	/* Peripheral Setup */
-	bclr	#4,@INTCR:8	/* interrupt mode 2 */
-	bset	#5,@INTCR:8
-
-#if defined(CONFIG_MTD_UCLINUX)
-	/* move romfs image */
-	jsr	@__move_romfs	
-#endif
-	
-	/* .bss clear */
-	mov.l	#__sbss,er5
-	mov.l	er5,er6
-	mov.l	#__ebss,er4
-	sub.l	er5,er4
-	shlr	#2,er4
-	sub.l	er0,er0
-1:	
-	mov.l	er0,@er5
-	adds	#4,er5
-	dec.l	#1,er4
-	bne	1b
-
-	/* copy kernel commandline */
-	mov.l	#COMMAND_START,er5
-	mov.l	#_command_line,er6
-	mov.w	#512,r4
-	eepmov.w
-
-	/* uClinux kernel start */
-	ldc	#0x90,ccr	/* running kernel */
-	mov.l	#_init_thread_union,sp
-	add.l	#0x2000,sp
-	jsr	@_start_kernel
-_exit:
-
-	jmp	_exit
-
-	rts
-
-	/* I/O port assign information */
-__platform_gpio_table:	
-	mov.l	#gpio_table,er0
-	rts
-
-gpio_table:
-	;; P1DDR
-	;;      used,ddr
-	.byte	0x00,0x00
-	;; P2DDR
-	.byte	0x00,0x00
-	;; P3DDR
-	.byte	0x00,0x00
-	;; dummy
-	.byte	0x00,0x00
-	;; P5DDR
-	.byte	0x00,0x00
-	;; P6DDR
-	.byte	0x00,0x00
-	;; P7DDR
-	.byte	0x00,0x00
-	;; P8DDR
-	.byte	0x00,0x00
-	;; dummy
-	.byte	0x00,0x00
-	;; PADDR
-	.byte	0x00,0x00
-	;; PBDDR
-	.byte	0x00,0x00
-	;; PCDDR
-	.byte	0x00,0x00
-	;; PDDDR
-	.byte	0x00,0x00
-	;; PEDDR
-	.byte	0x00,0x00
-	;; PFDDR
-	.byte	0x00,0x00
-	;; PGDDR
-	.byte	0x00,0x00
-	;; PHDDR
-	.byte	0x00,0x00
-
-__target_name:	
-	.asciz	"generic"
-	
-	.section .bootvec,"ax"
-	jmp	@__start
diff --git a/arch/h8300/platform/h8s/generic/crt0_rom.S b/arch/h8300/platform/h8s/generic/crt0_rom.S
deleted file mode 100644
index 623ba78..0000000
--- a/arch/h8300/platform/h8s/generic/crt0_rom.S
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- *  linux/arch/h8300/platform/h8s/generic/crt0_rom.S
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- *  Platform depend startup 
- *  Target Archtecture:	generic
- *  Memory Layout     :	ROM
- */
-
-#define ASSEMBLY
-
-#include <asm/linkage.h>
-#include <asm/regs267x.h>
-	
-	.global __start
-	.global __command_line
-	.global __platform_gpio_table
-	.global __target_name
-	
-	.h8300s
-	.section .text
-	.file	"crt0_rom.S"
-
-	/* CPU Reset entry */
-__start:
-	mov.l	#__ramend,sp
-	ldc	#0x80,ccr
-	ldc	#0,exr
-	bclr	#4,@INTCR:8
-	bset	#5,@INTCR:8	/* Interrupt mode 2 */
-	
-	/* Peripheral Setup */
-	
-	/* copy .data */
-#if !defined(CONFIG_H8S_SIM)
-	mov.l	#__begin_data,er5
-	mov.l	#__sdata,er6
-	mov.l	#__edata,er4
-	sub.l	er6,er4
-	shlr.l	#2,er4
-1:	
-	mov.l	@er5+,er0
-	mov.l	er0,@er6
-	adds	#4,er6
-	dec.l	#1,er4
-	bne	1b	
-#endif
-
-	/* .bss clear */
-	mov.l	#__sbss,er5
-	mov.l	#__ebss,er4
-	sub.l	er5,er4
-	shlr.l	#2,er4		
-	sub.l	er0,er0
-1:
-	mov.l	er0,@er5
-	adds	#4,er5
-	dec.l	#1,er4
-	bne	1b
-
-	/* linux kernel start */
-	ldc	#0x90,ccr	/* running kernel */
-	mov.l	#_init_thread_union,sp
-	add.l	#0x2000,sp
-	jsr	@_start_kernel
-_exit:
-
-	jmp	_exit
-
-	rts
-
-	/* I/O port assign information */
-__platform_gpio_table:	
-	mov.l	#gpio_table,er0
-	rts
-
-gpio_table:
-	;; P1DDR
-	.byte	0x00,0x00
-	;; P2DDR
-	.byte	0x00,0x00
-	;; P3DDR
-	.byte	0x00,0x00
-	;; P4DDR
-	.byte	0x00,0x00
-	;; P5DDR
-	.byte	0x00,0x00
-	;; P6DDR
-	.byte	0x00,0x00
-	;; dummy
-	.byte	0x00,0x00
-	;; P8DDR
-	.byte	0x00,0x00
-	;; PADDR
-	.byte	0x00,0x00
-	;; PBDDR
-	.byte	0x00,0x00
-	;; PCDDR
-	.byte	0x00,0x00
-	;; PDDDR
-	.byte	0x00,0x00
-	;; PEDDR
-	.byte	0x00,0x00
-	;; PFDDR
-	.byte	0x00,0x00
-	;; PGDDR
-	.byte	0x00,0x00
-	;; PHDDR
-	.byte	0x00,0x00
-
-	.section .rodata
-__target_name:	
-	.asciz	"generic"
-	
-	.section .bss
-__command_line:	
-	.space	512
-
-	/* interrupt vector */
-	.section .vectors,"ax"
-	.long	__start
-	.long	__start
-vector	=	2
-	.rept	126-1
-	.long	_interrupt_redirect_table+vector*4
-vector	=	vector + 1
-	.endr
diff --git a/arch/h8300/platform/h8s/irq.c b/arch/h8300/platform/h8s/irq.c
deleted file mode 100644
index f3a5511..0000000
--- a/arch/h8300/platform/h8s/irq.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * linux/arch/h8300/platform/h8s/ints_h8s.c
- * Interrupt handling CPU variants
- *
- * Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- */
-
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-
-#include <asm/ptrace.h>
-#include <asm/traps.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/gpio-internal.h>
-#include <asm/regs267x.h>
-
-/* saved vector list */
-const int __initconst h8300_saved_vectors[] = {
-#if defined(CONFIG_GDB_DEBUG)
-	TRACE_VEC,
-	TRAP3_VEC,
-#endif
-	-1
-};
-
-/* trap entry table */
-const H8300_VECTOR __initconst h8300_trap_table[] = {
-	0,0,0,0,0,
-	trace_break,  /* TRACE */
-	0,0,
-	system_call,  /* TRAPA #0 */
-	0,0,0,0,0,0,0
-};
-
-/* IRQ pin assignment */
-struct irq_pins {
-	unsigned char port_no;
-	unsigned char bit_no;
-} __attribute__((aligned(1),packed));
-/* ISTR = 0 */
-static const struct irq_pins irq_assign_table0[16]={
-        {H8300_GPIO_P5,H8300_GPIO_B0},{H8300_GPIO_P5,H8300_GPIO_B1},
-	{H8300_GPIO_P5,H8300_GPIO_B2},{H8300_GPIO_P5,H8300_GPIO_B3},
-	{H8300_GPIO_P5,H8300_GPIO_B4},{H8300_GPIO_P5,H8300_GPIO_B5},
-	{H8300_GPIO_P5,H8300_GPIO_B6},{H8300_GPIO_P5,H8300_GPIO_B7},
-	{H8300_GPIO_P6,H8300_GPIO_B0},{H8300_GPIO_P6,H8300_GPIO_B1},
-	{H8300_GPIO_P6,H8300_GPIO_B2},{H8300_GPIO_P6,H8300_GPIO_B3},
-	{H8300_GPIO_P6,H8300_GPIO_B4},{H8300_GPIO_P6,H8300_GPIO_B5},
-	{H8300_GPIO_PF,H8300_GPIO_B1},{H8300_GPIO_PF,H8300_GPIO_B2},
-};
-/* ISTR = 1 */
-static const struct irq_pins irq_assign_table1[16]={
-	{H8300_GPIO_P8,H8300_GPIO_B0},{H8300_GPIO_P8,H8300_GPIO_B1},
-	{H8300_GPIO_P8,H8300_GPIO_B2},{H8300_GPIO_P8,H8300_GPIO_B3},
-	{H8300_GPIO_P8,H8300_GPIO_B4},{H8300_GPIO_P8,H8300_GPIO_B5},
-	{H8300_GPIO_PH,H8300_GPIO_B2},{H8300_GPIO_PH,H8300_GPIO_B3},
-	{H8300_GPIO_P2,H8300_GPIO_B0},{H8300_GPIO_P2,H8300_GPIO_B1},
-	{H8300_GPIO_P2,H8300_GPIO_B2},{H8300_GPIO_P2,H8300_GPIO_B3},
-	{H8300_GPIO_P2,H8300_GPIO_B4},{H8300_GPIO_P2,H8300_GPIO_B5},
-	{H8300_GPIO_P2,H8300_GPIO_B6},{H8300_GPIO_P2,H8300_GPIO_B7},
-};
-
-/* IRQ to GPIO pin translation */
-#define IRQ_GPIO_MAP(irqbit,irq,port,bit)			  \
-do {								  \
-	if (*(volatile unsigned short *)ITSR & irqbit) {	  \
-		port = irq_assign_table1[irq - EXT_IRQ0].port_no; \
-		bit  = irq_assign_table1[irq - EXT_IRQ0].bit_no;  \
-	} else {						  \
-		port = irq_assign_table0[irq - EXT_IRQ0].port_no; \
-		bit  = irq_assign_table0[irq - EXT_IRQ0].bit_no;  \
-	}							  \
-} while(0)
-
-int h8300_enable_irq_pin(unsigned int irq)
-{
-	if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) {
-		unsigned short ptn = 1 << (irq - EXT_IRQ0);
-		unsigned int port_no,bit_no;
-		IRQ_GPIO_MAP(ptn, irq, port_no, bit_no);
-		if (H8300_GPIO_RESERVE(port_no, bit_no) == 0)
-			return -EBUSY;                   /* pin already use */
-		H8300_GPIO_DDR(port_no, bit_no, H8300_GPIO_INPUT);
-		*(volatile unsigned short *)ISR &= ~ptn; /* ISR clear */
-	}
-
-	return 0;
-}
-
-void h8300_disable_irq_pin(unsigned int irq)
-{
-	if (irq >= EXT_IRQ0 && irq <= EXT_IRQ15) {
-		/* disable interrupt & release IRQ pin */
-		unsigned short ptn = 1 << (irq - EXT_IRQ0);
-		unsigned short port_no,bit_no;
-		*(volatile unsigned short *)ISR &= ~ptn;
-		*(volatile unsigned short *)IER &= ~ptn;
-		IRQ_GPIO_MAP(ptn, irq, port_no, bit_no);
-		H8300_GPIO_FREE(port_no, bit_no);
-	}
-}
diff --git a/arch/h8300/platform/h8s/ptrace_h8s.c b/arch/h8300/platform/h8s/ptrace_h8s.c
deleted file mode 100644
index c058ab1..0000000
--- a/arch/h8300/platform/h8s/ptrace_h8s.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- *  linux/arch/h8300/platform/h8s/ptrace_h8s.c
- *    ptrace cpu depend helper functions
- *
- *  Yoshinori Sato <ysato@users.sourceforge.jp>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file COPYING in the main directory of
- * this archive for more details.
- */
-
-#include <linux/linkage.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <asm/ptrace.h>
-
-#define CCR_MASK  0x6f
-#define EXR_TRACE 0x80
-
-/* Mapping from PT_xxx to the stack offset at which the register is
-   saved.  Notice that usp has no stack-slot and needs to be treated
-   specially (see get_reg/put_reg below). */
-static const int h8300_register_offset[] = {
-	PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4),
-	PT_REG(er5), PT_REG(er6), PT_REG(er0), PT_REG(orig_er0),
-	PT_REG(ccr), PT_REG(pc),  0,           PT_REG(exr)
-};
-
-/* read register */
-long h8300_get_reg(struct task_struct *task, int regno)
-{
-	switch (regno) {
-	case PT_USP:
-		return task->thread.usp + sizeof(long)*2 + 2;
-	case PT_CCR:
-	case PT_EXR:
-	    return *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
-	default:
-	    return *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]);
-	}
-}
-
-/* write register */
-int h8300_put_reg(struct task_struct *task, int regno, unsigned long data)
-{
-	unsigned short oldccr;
-	switch (regno) {
-	case PT_USP:
-		task->thread.usp = data - sizeof(long)*2 - 2;
-	case PT_CCR:
-		oldccr = *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
-		oldccr &= ~CCR_MASK;
-		data &= CCR_MASK;
-		data |= oldccr;
-		*(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
-		break;
-	case PT_EXR:
-		/* exr modify not support */
-		return -EIO;
-	default:
-		*(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
-		break;
-	}
-	return 0;
-}
-
-/* disable singlestep */
-void user_disable_single_step(struct task_struct *child)
-{
-	*(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) &= ~EXR_TRACE;
-}
-
-/* enable singlestep */
-void user_enable_single_step(struct task_struct *child)
-{
-	*(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) |= EXR_TRACE;
-}
-
-asmlinkage void trace_trap(unsigned long bp)
-{
-	(void)bp;
-	force_sig(SIGTRAP,current);
-}
-
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 1da17ca..67c3450 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -53,3 +53,4 @@
 generic-y += ucontext.h
 generic-y += unaligned.h
 generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/hexagon/kernel/setup.c b/arch/hexagon/kernel/setup.c
index 29d1f1b..0e7c1db 100644
--- a/arch/hexagon/kernel/setup.c
+++ b/arch/hexagon/kernel/setup.c
@@ -32,9 +32,6 @@
 #include <asm/hexagon_vm.h>
 #include <asm/vm_mmu.h>
 #include <asm/time.h>
-#ifdef CONFIG_OF
-#include <asm/prom.h>
-#endif
 
 char cmd_line[COMMAND_LINE_SIZE];
 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index a3456f3..f93ee08 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -3,4 +3,5 @@
 generic-y += exec.h
 generic-y += kvm_para.h
 generic-y += trace_clock.h
+generic-y += preempt.h
 generic-y += vtime.h
\ No newline at end of file
diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h
index 74a7cc3..0d2bcb3 100644
--- a/arch/ia64/include/asm/io.h
+++ b/arch/ia64/include/asm/io.h
@@ -424,6 +424,7 @@
 extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
 extern void iounmap (volatile void __iomem *addr);
 extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size);
+#define early_memremap(phys_addr, size)        early_ioremap(phys_addr, size)
 extern void early_iounmap (volatile void __iomem *addr, unsigned long size);
 static inline void __iomem * ioremap_cache (unsigned long phys_addr, unsigned long size)
 {
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 51bce59..da5b462 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -44,10 +44,15 @@
 
 #define EFI_DEBUG	0
 
+static __initdata unsigned long palo_phys;
+
+static __initdata efi_config_table_type_t arch_tables[] = {
+	{PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID, "PALO", &palo_phys},
+	{NULL_GUID, NULL, 0},
+};
+
 extern efi_status_t efi_call_phys (void *, ...);
 
-struct efi efi;
-EXPORT_SYMBOL(efi);
 static efi_runtime_services_t *runtime;
 static u64 mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL;
 
@@ -423,9 +428,9 @@
  * Parse and handle PALO table which is published at:
  * http://www.dig64.org/home/DIG64_PALO_R1_0.pdf
  */
-static void __init handle_palo(unsigned long palo_phys)
+static void __init handle_palo(unsigned long phys_addr)
 {
-	struct palo_table *palo = __va(palo_phys);
+	struct palo_table *palo = __va(phys_addr);
 	u8  checksum;
 
 	if (strncmp(palo->signature, PALO_SIG, sizeof(PALO_SIG) - 1)) {
@@ -467,12 +472,10 @@
 efi_init (void)
 {
 	void *efi_map_start, *efi_map_end;
-	efi_config_table_t *config_tables;
 	efi_char16_t *c16;
 	u64 efi_desc_size;
 	char *cp, vendor[100] = "unknown";
 	int i;
-	unsigned long palo_phys;
 
 	/*
 	 * It's too early to be able to use the standard kernel command line
@@ -514,8 +517,6 @@
 		       efi.systab->hdr.revision >> 16,
 		       efi.systab->hdr.revision & 0xffff);
 
-	config_tables = __va(efi.systab->tables);
-
 	/* Show what we know for posterity */
 	c16 = __va(efi.systab->fw_vendor);
 	if (c16) {
@@ -528,43 +529,10 @@
 	       efi.systab->hdr.revision >> 16,
 	       efi.systab->hdr.revision & 0xffff, vendor);
 
-	efi.mps        = EFI_INVALID_TABLE_ADDR;
-	efi.acpi       = EFI_INVALID_TABLE_ADDR;
-	efi.acpi20     = EFI_INVALID_TABLE_ADDR;
-	efi.smbios     = EFI_INVALID_TABLE_ADDR;
-	efi.sal_systab = EFI_INVALID_TABLE_ADDR;
-	efi.boot_info  = EFI_INVALID_TABLE_ADDR;
-	efi.hcdp       = EFI_INVALID_TABLE_ADDR;
-	efi.uga        = EFI_INVALID_TABLE_ADDR;
-
 	palo_phys      = EFI_INVALID_TABLE_ADDR;
 
-	for (i = 0; i < (int) efi.systab->nr_tables; i++) {
-		if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) {
-			efi.mps = config_tables[i].table;
-			printk(" MPS=0x%lx", config_tables[i].table);
-		} else if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) {
-			efi.acpi20 = config_tables[i].table;
-			printk(" ACPI 2.0=0x%lx", config_tables[i].table);
-		} else if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) {
-			efi.acpi = config_tables[i].table;
-			printk(" ACPI=0x%lx", config_tables[i].table);
-		} else if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) {
-			efi.smbios = config_tables[i].table;
-			printk(" SMBIOS=0x%lx", config_tables[i].table);
-		} else if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) {
-			efi.sal_systab = config_tables[i].table;
-			printk(" SALsystab=0x%lx", config_tables[i].table);
-		} else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
-			efi.hcdp = config_tables[i].table;
-			printk(" HCDP=0x%lx", config_tables[i].table);
-		} else if (efi_guidcmp(config_tables[i].guid,
-			 PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID) == 0) {
-			palo_phys = config_tables[i].table;
-			printk(" PALO=0x%lx", config_tables[i].table);
-		}
-	}
-	printk("\n");
+	if (efi_config_init(arch_tables) != 0)
+		return;
 
 	if (palo_phys != EFI_INVALID_TABLE_ADDR)
 		handle_palo(palo_phys);
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 4fc2e95..d86669b 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -1063,6 +1063,7 @@
 static int __init run_dmi_scan(void)
 {
 	dmi_scan_machine();
+	dmi_memdev_walk();
 	dmi_set_dump_stack_arch_desc();
 	return 0;
 }
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index bebdc36..2b58c5f 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -3,3 +3,4 @@
 generic-y += exec.h
 generic-y += module.h
 generic-y += trace_clock.h
+generic-y += preempt.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 09d77a8..a5d27f2 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -31,3 +31,4 @@
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/m68k/include/asm/floppy.h b/arch/m68k/include/asm/floppy.h
index 697d503..47365b1 100644
--- a/arch/m68k/include/asm/floppy.h
+++ b/arch/m68k/include/asm/floppy.h
@@ -85,7 +85,7 @@
 {
 	if(MACH_IS_Q40)
 		return request_irq(FLOPPY_IRQ, floppy_hardint,
-				   IRQF_DISABLED, "floppy", floppy_hardint);
+				   0, "floppy", floppy_hardint);
 	else if(MACH_IS_SUN3X)
 		return sun3xflop_request_irq();
 	return -ENXIO;
diff --git a/arch/m68k/include/asm/sun3xflop.h b/arch/m68k/include/asm/sun3xflop.h
index 95231e2..a02ea3a 100644
--- a/arch/m68k/include/asm/sun3xflop.h
+++ b/arch/m68k/include/asm/sun3xflop.h
@@ -207,7 +207,7 @@
 	if(!once) {
 		once = 1;
 		error = request_irq(FLOPPY_IRQ, sun3xflop_hardint,
-				    IRQF_DISABLED, "floppy", NULL);
+				    0, "floppy", NULL);
 		return ((error == 0) ? 0 : -1);
 	} else return 0;
 }
diff --git a/arch/m68k/include/asm/uaccess.h b/arch/m68k/include/asm/uaccess.h
index 639c731..3fadc4a 100644
--- a/arch/m68k/include/asm/uaccess.h
+++ b/arch/m68k/include/asm/uaccess.h
@@ -3,3 +3,10 @@
 #else
 #include <asm/uaccess_mm.h>
 #endif
+
+#ifdef CONFIG_CPU_HAS_NO_UNALIGNED
+#include <asm-generic/uaccess-unaligned.h>
+#else
+#define __get_user_unaligned(x, ptr)	__get_user((x), (ptr))
+#define __put_user_unaligned(x, ptr)	__put_user((x), (ptr))
+#endif
diff --git a/arch/m68k/platform/68000/timers.c b/arch/m68k/platform/68000/timers.c
index ec30acb..99a9869 100644
--- a/arch/m68k/platform/68000/timers.c
+++ b/arch/m68k/platform/68000/timers.c
@@ -70,7 +70,7 @@
 
 static struct irqaction m68328_timer_irq = {
 	.name	 = "timer",
-	.flags	 = IRQF_DISABLED | IRQF_TIMER,
+	.flags	 = IRQF_TIMER,
 	.handler = hw_tick,
 };
 
diff --git a/arch/m68k/platform/68360/config.c b/arch/m68k/platform/68360/config.c
index 0570741..d493ac4 100644
--- a/arch/m68k/platform/68360/config.c
+++ b/arch/m68k/platform/68360/config.c
@@ -59,7 +59,7 @@
 
 static struct irqaction m68360_timer_irq = {
 	.name	 = "timer",
-	.flags	 = IRQF_DISABLED | IRQF_TIMER,
+	.flags	 = IRQF_TIMER,
 	.handler = hw_tick,
 };
 
diff --git a/arch/m68k/platform/coldfire/pit.c b/arch/m68k/platform/coldfire/pit.c
index e8f3b97..493b311 100644
--- a/arch/m68k/platform/coldfire/pit.c
+++ b/arch/m68k/platform/coldfire/pit.c
@@ -118,7 +118,7 @@
 
 static struct irqaction pit_irq = {
 	.name	 = "timer",
-	.flags	 = IRQF_DISABLED | IRQF_TIMER,
+	.flags	 = IRQF_TIMER,
 	.handler = pit_tick,
 };
 
diff --git a/arch/m68k/platform/coldfire/sltimers.c b/arch/m68k/platform/coldfire/sltimers.c
index bb5a25a..831a08c 100644
--- a/arch/m68k/platform/coldfire/sltimers.c
+++ b/arch/m68k/platform/coldfire/sltimers.c
@@ -51,7 +51,7 @@
 
 static struct irqaction mcfslt_profile_irq = {
 	.name	 = "profile timer",
-	.flags	 = IRQF_DISABLED | IRQF_TIMER,
+	.flags	 = IRQF_TIMER,
 	.handler = mcfslt_profile_tick,
 };
 
@@ -93,7 +93,7 @@
 
 static struct irqaction mcfslt_timer_irq = {
 	.name	 = "timer",
-	.flags	 = IRQF_DISABLED | IRQF_TIMER,
+	.flags	 = IRQF_TIMER,
 	.handler = mcfslt_tick,
 };
 
diff --git a/arch/m68k/platform/coldfire/timers.c b/arch/m68k/platform/coldfire/timers.c
index d06068e..cd496a2 100644
--- a/arch/m68k/platform/coldfire/timers.c
+++ b/arch/m68k/platform/coldfire/timers.c
@@ -83,7 +83,7 @@
 
 static struct irqaction mcftmr_timer_irq = {
 	.name	 = "timer",
-	.flags	 = IRQF_DISABLED | IRQF_TIMER,
+	.flags	 = IRQF_TIMER,
 	.handler = mcftmr_tick,
 };
 
@@ -171,7 +171,7 @@
 
 static struct irqaction coldfire_profile_irq = {
 	.name	 = "profile timer",
-	.flags	 = IRQF_DISABLED | IRQF_TIMER,
+	.flags	 = IRQF_TIMER,
 	.handler = coldfire_profile_tick,
 };
 
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 6ae0ccb..84d0c1d 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -52,3 +52,4 @@
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/metag/include/asm/mach/arch.h b/arch/metag/include/asm/mach/arch.h
index 12c5664..433f946 100644
--- a/arch/metag/include/asm/mach/arch.h
+++ b/arch/metag/include/asm/mach/arch.h
@@ -53,7 +53,7 @@
 /*
  * Current machine - only accessible during boot.
  */
-extern struct machine_desc *machine_desc;
+extern const struct machine_desc *machine_desc;
 
 /*
  * Machine type table - also only accessible during boot
diff --git a/arch/metag/include/asm/prom.h b/arch/metag/include/asm/prom.h
deleted file mode 100644
index d2aa35d..0000000
--- a/arch/metag/include/asm/prom.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- *  arch/metag/include/asm/prom.h
- *
- *  Copyright (C) 2012 Imagination Technologies Ltd.
- *
- *  Based on ARM version:
- *  Copyright (C) 2009 Canonical Ltd. <jeremy.kerr@canonical.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-#ifndef __ASM_METAG_PROM_H
-#define __ASM_METAG_PROM_H
-
-#include <asm/setup.h>
-#define HAVE_ARCH_DEVTREE_FIXUPS
-
-extern struct machine_desc *setup_machine_fdt(void *dt);
-extern void copy_fdt(void);
-
-#endif /* __ASM_METAG_PROM_H */
diff --git a/arch/metag/include/asm/setup.h b/arch/metag/include/asm/setup.h
index e13083b..e9fdee9 100644
--- a/arch/metag/include/asm/setup.h
+++ b/arch/metag/include/asm/setup.h
@@ -3,6 +3,7 @@
 
 #include <uapi/asm/setup.h>
 
+extern const struct machine_desc *setup_machine_fdt(void *dt);
 void per_cpu_trap_init(unsigned long);
 extern void __init dump_machine_table(void);
 #endif /* _ASM_METAG_SETUP_H */
diff --git a/arch/metag/include/asm/tbx.h b/arch/metag/include/asm/tbx.h
index 287b36f..703b9cb 100644
--- a/arch/metag/include/asm/tbx.h
+++ b/arch/metag/include/asm/tbx.h
@@ -150,11 +150,9 @@
 #else
 /* Reserved 0x04-0x09 */
 #endif
-#define TBID_SIGNUM_SWS     0x0A /* KICK received with SigMask != 0 */
-#define TBID_SIGNUM_SWK     0x0B /* KICK received with SigMask == 0 */
-/* Reserved 0x0C-0x0F */
+/* Reserved 0x0A-0x0F */
 #define TBID_SIGNUM_TRT     0x10 /* Timer trigger */
-#define TBID_SIGNUM_LWK     0x11 /* Low level kick (handler provided by TBI) */
+#define TBID_SIGNUM_LWK     0x11 /* Low level kick */
 #define TBID_SIGNUM_XXF     0x12 /* Fault handler - receives ALL _xxF sigs */
 #ifdef TBI_1_4
 #define TBID_SIGNUM_DFR     0x13 /* Deferred Exception handler */
@@ -183,8 +181,7 @@
    each hardware signal, sometimes this is a many-to-one relationship. */
 #define TBI_TRIG_BIT(SigNum)                                      (\
     ((SigNum) >= TBID_SIGNUM_TRT) ? 1<<((SigNum)-TBID_SIGNUM_TRT) :\
-    ( ((SigNum) == TBID_SIGNUM_SWS) ||                             \
-      ((SigNum) == TBID_SIGNUM_SWK)    ) ?                         \
+    ((SigNum) == TBID_SIGNUM_LWK) ?                                \
                          TXSTAT_KICK_BIT : TXSTATI_BGNDHALT_BIT    )
 
 /* Return the hardware trigger vector number for entries in the
@@ -687,10 +684,8 @@
    Triggers will indicate the status of TXSTAT or TXSTATI sampled by the
           code that called the handler.
           
-   InstOrSWSId is defined firstly as 'Inst' if the SigNum is TBID_SIGNUM_SWx
-          and hold the actual SWITCH instruction detected, secondly if SigNum
-          is TBID_SIGNUM_SWS the 'SWSId' is defined to hold the Id of the
-          software signal detected, in other cases the value of this
+   Inst is defined as 'Inst' if the SigNum is TBID_SIGNUM_SWx and holds the
+          actual SWITCH instruction detected, in other cases the value of this
           parameter is undefined.
    
    pTBI   points at the PTBI structure related to the thread and processing
@@ -709,7 +704,7 @@
 
  */
 typedef TBIRES (*PTBIAPIFN)( TBIRES State, int SigNum,
-                             int Triggers, int InstOrSWSId,
+                             int Triggers, int Inst,
                              volatile struct _tbi_tag_ *pTBI );
 #endif /* ifndef __ASSEMBLY__ */
 
@@ -757,7 +752,7 @@
 #ifndef __ASSEMBLY__
 /* This handler should be used for TBID_SIGNUM_DFR */
 extern TBIRES __TBIHandleDFR ( TBIRES State, int SigNum,
-                               int Triggers, int InstOrSWSId,
+                               int Triggers, int Inst,
                                volatile struct _tbi_tag_ *pTBI );
 #endif
 #endif
diff --git a/arch/metag/include/asm/topology.h b/arch/metag/include/asm/topology.h
index 23f5118..8e9c0b3 100644
--- a/arch/metag/include/asm/topology.h
+++ b/arch/metag/include/asm/topology.h
@@ -26,6 +26,8 @@
 	.last_balance		= jiffies,		\
 	.balance_interval	= 1,			\
 	.nr_balance_failed	= 0,			\
+	.max_newidle_lb_cost	= 0,			\
+	.next_decay_max_lb_cost	= jiffies,		\
 }
 
 #define cpu_to_node(cpu)	((void)(cpu), 0)
diff --git a/arch/metag/kernel/devtree.c b/arch/metag/kernel/devtree.c
index 7cd0252..18dd7ae 100644
--- a/arch/metag/kernel/devtree.c
+++ b/arch/metag/kernel/devtree.c
@@ -34,6 +34,19 @@
 	return alloc_bootmem_align(size, align);
 }
 
+static const void * __init arch_get_next_mach(const char *const **match)
+{
+	static const struct machine_desc *mdesc = __arch_info_begin;
+	const struct machine_desc *m = mdesc;
+
+	if (m >= __arch_info_end)
+		return NULL;
+
+	mdesc++;
+	*match = m->dt_compat;
+	return m;
+}
+
 /**
  * setup_machine_fdt - Machine setup when an dtb was passed to the kernel
  * @dt:		virtual address pointer to dt blob
@@ -41,74 +54,18 @@
  * If a dtb was passed to the kernel, then use it to choose the correct
  * machine_desc and to setup the system.
  */
-struct machine_desc * __init setup_machine_fdt(void *dt)
+const struct machine_desc * __init setup_machine_fdt(void *dt)
 {
-	struct boot_param_header *devtree = dt;
-	struct machine_desc *mdesc, *mdesc_best = NULL;
-	unsigned int score, mdesc_score = ~1;
-	unsigned long dt_root;
-	const char *model;
+	const struct machine_desc *mdesc;
 
 	/* check device tree validity */
-	if (be32_to_cpu(devtree->magic) != OF_DT_HEADER)
+	if (!early_init_dt_scan(dt))
 		return NULL;
 
-	/* Search the mdescs for the 'best' compatible value match */
-	initial_boot_params = devtree;
-	dt_root = of_get_flat_dt_root();
-
-	for_each_machine_desc(mdesc) {
-		score = of_flat_dt_match(dt_root, mdesc->dt_compat);
-		if (score > 0 && score < mdesc_score) {
-			mdesc_best = mdesc;
-			mdesc_score = score;
-		}
-	}
-	if (!mdesc_best) {
-		const char *prop;
-		long size;
-
-		pr_err("\nError: unrecognized/unsupported device tree compatible list:\n[ ");
-
-		prop = of_get_flat_dt_prop(dt_root, "compatible", &size);
-		if (prop) {
-			while (size > 0) {
-				printk("'%s' ", prop);
-				size -= strlen(prop) + 1;
-				prop += strlen(prop) + 1;
-			}
-		}
-		printk("]\n\n");
-
+	mdesc = of_flat_dt_match_machine(NULL, arch_get_next_mach);
+	if (!mdesc)
 		dump_machine_table(); /* does not return */
-	}
+	pr_info("Machine name: %s\n", mdesc->name);
 
-	model = of_get_flat_dt_prop(dt_root, "model", NULL);
-	if (!model)
-		model = of_get_flat_dt_prop(dt_root, "compatible", NULL);
-	if (!model)
-		model = "<unknown>";
-	pr_info("Machine: %s, model: %s\n", mdesc_best->name, model);
-
-	/* Retrieve various information from the /chosen node */
-	of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
-
-	return mdesc_best;
-}
-
-/**
- * copy_fdt - Copy device tree into non-init memory.
- *
- * We must copy the flattened device tree blob into non-init memory because the
- * unflattened device tree will reference the strings in it directly.
- */
-void __init copy_fdt(void)
-{
-	void *alloc = early_init_dt_alloc_memory_arch(
-			be32_to_cpu(initial_boot_params->totalsize), 0x40);
-	if (alloc) {
-		memcpy(alloc, initial_boot_params,
-		       be32_to_cpu(initial_boot_params->totalsize));
-		initial_boot_params = alloc;
-	}
+	return mdesc;
 }
diff --git a/arch/metag/kernel/irq.c b/arch/metag/kernel/irq.c
index 2a2c9d5..3b4b7f6 100644
--- a/arch/metag/kernel/irq.c
+++ b/arch/metag/kernel/irq.c
@@ -159,44 +159,30 @@
 
 extern asmlinkage void __do_softirq(void);
 
-asmlinkage void do_softirq(void)
+void do_softirq_own_stack(void)
 {
-	unsigned long flags;
 	struct thread_info *curctx;
 	union irq_ctx *irqctx;
 	u32 *isp;
 
-	if (in_interrupt())
-		return;
+	curctx = current_thread_info();
+	irqctx = softirq_ctx[smp_processor_id()];
+	irqctx->tinfo.task = curctx->task;
 
-	local_irq_save(flags);
+	/* build the stack frame on the softirq stack */
+	isp = (u32 *) ((char *)irqctx + sizeof(struct thread_info));
 
-	if (local_softirq_pending()) {
-		curctx = current_thread_info();
-		irqctx = softirq_ctx[smp_processor_id()];
-		irqctx->tinfo.task = curctx->task;
-
-		/* build the stack frame on the softirq stack */
-		isp = (u32 *) ((char *)irqctx + sizeof(struct thread_info));
-
-		asm volatile (
-			"MOV   D0.5,%0\n"
-			"SWAP  A0StP,D0.5\n"
-			"CALLR D1RtP,___do_softirq\n"
-			"MOV   A0StP,D0.5\n"
-			:
-			: "r" (isp)
-			: "memory", "cc", "D1Ar1", "D0Ar2", "D1Ar3", "D0Ar4",
-			  "D1Ar5", "D0Ar6", "D0Re0", "D1Re0", "D0.4", "D1RtP",
-			  "D0.5"
-			);
-		/*
-		 * Shouldn't happen, we returned above if in_interrupt():
-		 */
-		WARN_ON_ONCE(softirq_count());
-	}
-
-	local_irq_restore(flags);
+	asm volatile (
+		"MOV   D0.5,%0\n"
+		"SWAP  A0StP,D0.5\n"
+		"CALLR D1RtP,___do_softirq\n"
+		"MOV   A0StP,D0.5\n"
+		:
+		: "r" (isp)
+		: "memory", "cc", "D1Ar1", "D0Ar2", "D1Ar3", "D0Ar4",
+		  "D1Ar5", "D0Ar6", "D0Re0", "D1Re0", "D0.4", "D1RtP",
+		  "D0.5"
+		);
 }
 #endif
 
diff --git a/arch/metag/kernel/setup.c b/arch/metag/kernel/setup.c
index c396cd0..129c7cd 100644
--- a/arch/metag/kernel/setup.c
+++ b/arch/metag/kernel/setup.c
@@ -42,7 +42,6 @@
 #include <asm/mmu.h>
 #include <asm/mmzone.h>
 #include <asm/processor.h>
-#include <asm/prom.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/traps.h>
@@ -115,7 +114,7 @@
 extern struct console dash_console;
 #endif
 
-struct machine_desc *machine_desc __initdata;
+const struct machine_desc *machine_desc __initdata;
 
 /*
  * Map a Linux CPU number to a hardware thread ID
@@ -302,13 +301,9 @@
 	 * rather than the version from the bootloader. This makes call
 	 * stacks easier to understand and may allow us to unmap the
 	 * bootloader at some point.
-	 *
-	 * We need to keep the LWK handler that TBI installed in order to
-	 * be able to do inter-thread comms.
 	 */
 	for (i = 0; i <= TBID_SIGNUM_MAX; i++)
-		if (i != TBID_SIGNUM_LWK)
-			_pTBI->fnSigs[i] = __TBIUnExpXXX;
+		_pTBI->fnSigs[i] = __TBIUnExpXXX;
 
 	/* A Meta requirement is that the kernel is loaded (virtually)
 	 * at the PAGE_OFFSET.
@@ -408,9 +403,7 @@
 	cpu_2_hwthread_id[smp_processor_id()] = hard_processor_id();
 	hwthread_id_2_cpu[hard_processor_id()] = smp_processor_id();
 
-	/* Copy device tree blob into non-init memory before unflattening */
-	copy_fdt();
-	unflatten_device_tree();
+	unflatten_and_copy_device_tree();
 
 #ifdef CONFIG_SMP
 	smp_init_cpus();
diff --git a/arch/metag/kernel/traps.c b/arch/metag/kernel/traps.c
index 25f9d1c..17b2e2e 100644
--- a/arch/metag/kernel/traps.c
+++ b/arch/metag/kernel/traps.c
@@ -819,8 +819,7 @@
 
 	set_trigger_mask(TBI_INTS_INIT(thread) | /* interrupts */
 			 TBI_TRIG_BIT(TBID_SIGNUM_LWK) | /* low level kick */
-			 TBI_TRIG_BIT(TBID_SIGNUM_SW1) |
-			 TBI_TRIG_BIT(TBID_SIGNUM_SWS));
+			 TBI_TRIG_BIT(TBID_SIGNUM_SW1));
 
 	/* non-priv - use current stack */
 	int_context.Sig.pCtx = NULL;
@@ -842,7 +841,7 @@
 	_pTBI->fnSigs[TBID_SIGNUM_SW1] = switch1_handler;
 	_pTBI->fnSigs[TBID_SIGNUM_SW2] = switchx_handler;
 	_pTBI->fnSigs[TBID_SIGNUM_SW3] = switchx_handler;
-	_pTBI->fnSigs[TBID_SIGNUM_SWK] = kick_handler;
+	_pTBI->fnSigs[TBID_SIGNUM_LWK] = kick_handler;
 
 #ifdef CONFIG_METAG_META21
 	_pTBI->fnSigs[TBID_SIGNUM_DFR] = __TBIHandleDFR;
diff --git a/arch/metag/mm/init.c b/arch/metag/mm/init.c
index 1239195..249fff6 100644
--- a/arch/metag/mm/init.c
+++ b/arch/metag/mm/init.c
@@ -12,7 +12,6 @@
 #include <linux/percpu.h>
 #include <linux/memblock.h>
 #include <linux/initrd.h>
-#include <linux/of_fdt.h>
 
 #include <asm/setup.h>
 #include <asm/page.h>
@@ -405,11 +404,3 @@
 			   "initrd");
 }
 #endif
-
-#ifdef CONFIG_OF_FLATTREE
-void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
-{
-	pr_err("%s(%llx, %llx)\n",
-	       __func__, start, end);
-}
-#endif /* CONFIG_OF_FLATTREE */
diff --git a/arch/metag/mm/numa.c b/arch/metag/mm/numa.c
index 9ae578c..b172aa4 100644
--- a/arch/metag/mm/numa.c
+++ b/arch/metag/mm/numa.c
@@ -34,7 +34,7 @@
 	unsigned long pgdat_paddr;
 
 	/* Don't allow bogus node assignment */
-	BUG_ON(nid > MAX_NUMNODES || nid <= 0);
+	BUG_ON(nid >= MAX_NUMNODES || nid <= 0);
 
 	start_pfn = start >> PAGE_SHIFT;
 	end_pfn = end >> PAGE_SHIFT;
diff --git a/arch/metag/tbx/tbidefr.S b/arch/metag/tbx/tbidefr.S
index 3eb165e..8f0902b 100644
--- a/arch/metag/tbx/tbidefr.S
+++ b/arch/metag/tbx/tbidefr.S
@@ -20,7 +20,7 @@
 /* D1Ar1:D0Ar2 -- State
  * D0Ar3       -- SigNum
  * D0Ar4       -- Triggers
- * D1Ar5       -- InstOrSWSId
+ * D1Ar5       -- Inst
  * D0Ar6       -- pTBI (volatile)
  */
 ___TBIHandleDFR:
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index b82f82b..655e1ca 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -82,11 +82,6 @@
 	bool "MMU support"
 	default n
 
-config NO_MMU
-	bool
-	depends on !MMU
-	default y
-
 comment "Boot options"
 
 config CMDLINE_BOOL
@@ -250,10 +245,6 @@
 
 endchoice
 
-config KERNEL_PAD
-	hex "Kernel PAD for unpacking" if ADVANCED_OPTIONS
-	default "0x80000" if MMU
-
 endmenu
 
 source "mm/Kconfig"
diff --git a/arch/microblaze/boot/dts/Makefile b/arch/microblaze/boot/dts/Makefile
index c3b3a5d..c4982d1 100644
--- a/arch/microblaze/boot/dts/Makefile
+++ b/arch/microblaze/boot/dts/Makefile
@@ -1,6 +1,4 @@
 #
-# arch/microblaze/boot/Makefile
-#
 
 obj-y += linked_dtb.o
 
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index d3c51a6..ce0bbf8 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -3,3 +3,4 @@
 generic-y += exec.h
 generic-y += trace_clock.h
 generic-y += syscalls.h
+generic-y += preempt.h
diff --git a/arch/microblaze/include/asm/pci.h b/arch/microblaze/include/asm/pci.h
index d52abb6..935f9be 100644
--- a/arch/microblaze/include/asm/pci.h
+++ b/arch/microblaze/include/asm/pci.h
@@ -127,8 +127,6 @@
 extern void of_scan_bus(struct device_node *node, struct pci_bus *bus);
 extern void of_rescan_bus(struct device_node *node, struct pci_bus *bus);
 
-extern int pci_read_irq_line(struct pci_dev *dev);
-
 extern int pci_bus_find_capability(struct pci_bus *bus,
 						unsigned int devfn, int cap);
 
diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h
index 9977816..2f03ac8 100644
--- a/arch/microblaze/include/asm/prom.h
+++ b/arch/microblaze/include/asm/prom.h
@@ -11,19 +11,10 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
-
-#include <linux/of.h>	/* linux/of.h gets to determine #include ordering */
-
 #ifndef _ASM_MICROBLAZE_PROM_H
 #define _ASM_MICROBLAZE_PROM_H
-#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
 
-#include <linux/types.h>
-#include <asm/irq.h>
-#include <linux/atomic.h>
-
-#define HAVE_ARCH_DEVTREE_FIXUPS
+#include <linux/of.h>
 
 /* Other Prototypes */
 enum early_consoles {
@@ -33,32 +24,4 @@
 
 extern int of_early_console(void *version);
 
-/*
- * OF address retreival & translation
- */
-
-#ifdef CONFIG_PCI
-extern unsigned long pci_address_to_pio(phys_addr_t address);
-#define pci_address_to_pio pci_address_to_pio
-#endif	/* CONFIG_PCI */
-
-/* Parse the ibm,dma-window property of an OF node into the busno, phys and
- * size parameters.
- */
-void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
-		unsigned long *busno, unsigned long *phys, unsigned long *size);
-
-extern void kdump_move_device_tree(void);
-
-#endif /* __ASSEMBLY__ */
-#endif /* __KERNEL__ */
-
-/* These includes are put at the bottom because they may contain things
- * that are overridden by this file.  Ideally they shouldn't be included
- * by this file, but there are a bunch of .c files that currently depend
- * on it.  Eventually they will be cleaned up. */
-#include <linux/of_fdt.h>
-#include <linux/of_irq.h>
-#include <linux/platform_device.h>
-
 #endif /* _ASM_MICROBLAZE_PROM_H */
diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S
index fcc797f..817b7ee 100644
--- a/arch/microblaze/kernel/head.S
+++ b/arch/microblaze/kernel/head.S
@@ -176,7 +176,7 @@
 	/* start to do TLB calculation */
 	addik	r12, r0, _end
 	rsub	r12, r3, r12
-	addik	r12, r12, CONFIG_KERNEL_PAD /* that's the pad */
+	addik	r12, r12, CONFIG_LOWMEM_SIZE >> PTE_SHIFT /* that's the pad */
 
 	or r9, r0, r0 /* TLB0 = 0 */
 	or r10, r0, r0 /* TLB1 = 0 */
diff --git a/arch/microblaze/kernel/hw_exception_handler.S b/arch/microblaze/kernel/hw_exception_handler.S
index 61b3a1f..fc6b89f 100644
--- a/arch/microblaze/kernel/hw_exception_handler.S
+++ b/arch/microblaze/kernel/hw_exception_handler.S
@@ -193,8 +193,8 @@
  *      -                            W   S   REG   EXC
  *
  *
- * STACK FRAME STRUCTURE (for NO_MMU)
- * ---------------------------------
+ * STACK FRAME STRUCTURE (for CONFIG_MMU=n)
+ * ----------------------------------------
  *
  *      +-------------+         + 0
  *      |     MSR     |
diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index 0c4453f..abdfb10 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -30,6 +30,7 @@
 #include <linux/debugfs.h>
 #include <linux/irq.h>
 #include <linux/memblock.h>
+#include <linux/of_fdt.h>
 
 #include <asm/prom.h>
 #include <asm/page.h>
@@ -41,11 +42,6 @@
 #include <asm/sections.h>
 #include <asm/pci-bridge.h>
 
-void __init early_init_dt_add_memory_arch(u64 base, u64 size)
-{
-	memblock_add(base, size);
-}
-
 #ifdef CONFIG_EARLY_PRINTK
 static char *stdout;
 
@@ -106,21 +102,10 @@
 {
 	pr_debug(" -> early_init_devtree(%p)\n", params);
 
-	/* Setup flat device-tree pointer */
-	initial_boot_params = params;
+	early_init_dt_scan(params);
+	if (!strlen(boot_command_line))
+		strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
 
-	/* Retrieve various informations from the /chosen node of the
-	 * device-tree, including the platform type, initrd location and
-	 * size, TCE reserve, and more ...
-	 */
-	of_scan_flat_dt(early_init_dt_scan_chosen, cmd_line);
-
-	/* Scan memory nodes and rebuild MEMBLOCKs */
-	of_scan_flat_dt(early_init_dt_scan_root, NULL);
-	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
-
-	/* Save command line for /proc/cmdline and then parse parameters */
-	strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
 	parse_early_param();
 
 	memblock_allow_resize();
@@ -130,15 +115,6 @@
 	pr_debug(" <- early_init_devtree()\n");
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
-{
-	initrd_start = (unsigned long)__va(start);
-	initrd_end = (unsigned long)__va(end);
-	initrd_below_start_ok = 1;
-}
-#endif
-
 /*******
  *
  * New implementation of the OF "find" APIs, return a refcounted
diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c
index 0775e03..8de8ebc 100644
--- a/arch/microblaze/kernel/setup.c
+++ b/arch/microblaze/kernel/setup.c
@@ -16,6 +16,7 @@
 #include <linux/initrd.h>
 #include <linux/console.h>
 #include <linux/debugfs.h>
+#include <linux/of_fdt.h>
 
 #include <asm/setup.h>
 #include <asm/sections.h>
@@ -50,7 +51,7 @@
 
 void __init setup_arch(char **cmdline_p)
 {
-	*cmdline_p = cmd_line;
+	*cmdline_p = boot_command_line;
 
 	console_verbose();
 
diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c
index f905b3a..f1e1f66 100644
--- a/arch/microblaze/kernel/sys_microblaze.c
+++ b/arch/microblaze/kernel/sys_microblaze.c
@@ -33,12 +33,23 @@
 #include <linux/slab.h>
 #include <asm/syscalls.h>
 
-asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
-			unsigned long prot, unsigned long flags,
-			unsigned long fd, off_t pgoff)
+SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
+		unsigned long, prot, unsigned long, flags, unsigned long, fd,
+		off_t, pgoff)
 {
 	if (pgoff & ~PAGE_MASK)
 		return -EINVAL;
 
 	return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT);
 }
+
+SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
+		unsigned long, prot, unsigned long, flags, unsigned long, fd,
+		unsigned long, pgoff)
+{
+	if (pgoff & (~PAGE_MASK >> 12))
+		return -EINVAL;
+
+	return sys_mmap_pgoff(addr, len, prot, flags, fd,
+			      pgoff >> (PAGE_SHIFT - 12));
+}
diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S
index 4fca56c..b882ad5 100644
--- a/arch/microblaze/kernel/syscall_table.S
+++ b/arch/microblaze/kernel/syscall_table.S
@@ -192,7 +192,7 @@
 	.long sys_ni_syscall		/* reserved for streams2 */
 	.long sys_vfork		/* 190 */
 	.long sys_getrlimit
-	.long sys_mmap_pgoff		/* mmap2 */
+	.long sys_mmap2
 	.long sys_truncate64
 	.long sys_ftruncate64
 	.long sys_stat64		/* 195 */
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c
index e4b3f33..3e39b10 100644
--- a/arch/microblaze/kernel/timer.c
+++ b/arch/microblaze/kernel/timer.c
@@ -15,6 +15,7 @@
 #include <linux/clk.h>
 #include <linux/clockchips.h>
 #include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <asm/cpuinfo.h>
 #include <linux/cnt32_to_63.h>
 
@@ -148,7 +149,7 @@
 
 static struct irqaction timer_irqaction = {
 	.handler = timer_interrupt,
-	.flags = IRQF_DISABLED | IRQF_TIMER,
+	.flags = IRQF_TIMER,
 	.name = "timer",
 	.dev_id = &clockevent_xilinx_timer,
 };
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index 1b93bf0..66804ad 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_pci.h>
 #include <linux/export.h>
 
@@ -193,76 +194,6 @@
 }
 
 /*
- * Reads the interrupt pin to determine if interrupt is use by card.
- * If the interrupt is used, then gets the interrupt line from the
- * openfirmware and sets it in the pci_dev and pci_config line.
- */
-int pci_read_irq_line(struct pci_dev *pci_dev)
-{
-	struct of_irq oirq;
-	unsigned int virq;
-
-	/* The current device-tree that iSeries generates from the HV
-	 * PCI informations doesn't contain proper interrupt routing,
-	 * and all the fallback would do is print out crap, so we
-	 * don't attempt to resolve the interrupts here at all, some
-	 * iSeries specific fixup does it.
-	 *
-	 * In the long run, we will hopefully fix the generated device-tree
-	 * instead.
-	 */
-	pr_debug("PCI: Try to map irq for %s...\n", pci_name(pci_dev));
-
-#ifdef DEBUG
-	memset(&oirq, 0xff, sizeof(oirq));
-#endif
-	/* Try to get a mapping from the device-tree */
-	if (of_irq_map_pci(pci_dev, &oirq)) {
-		u8 line, pin;
-
-		/* If that fails, lets fallback to what is in the config
-		 * space and map that through the default controller. We
-		 * also set the type to level low since that's what PCI
-		 * interrupts are. If your platform does differently, then
-		 * either provide a proper interrupt tree or don't use this
-		 * function.
-		 */
-		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
-			return -1;
-		if (pin == 0)
-			return -1;
-		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
-		    line == 0xff || line == 0) {
-			return -1;
-		}
-		pr_debug(" No map ! Using line %d (pin %d) from PCI config\n",
-			 line, pin);
-
-		virq = irq_create_mapping(NULL, line);
-		if (virq)
-			irq_set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
-	} else {
-		pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
-			 oirq.size, oirq.specifier[0], oirq.specifier[1],
-			 of_node_full_name(oirq.controller));
-
-		virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
-					     oirq.size);
-	}
-	if (!virq) {
-		pr_debug(" Failed to map !\n");
-		return -1;
-	}
-
-	pr_debug(" Mapped to linux irq %d\n", virq);
-
-	pci_dev->irq = virq;
-
-	return 0;
-}
-EXPORT_SYMBOL(pci_read_irq_line);
-
-/*
  * Platform support for /proc/bus/pci/X/Y mmap()s,
  * modelled on the sparc64 implementation by Dave Miller.
  *  -- paulus.
@@ -960,7 +891,7 @@
 		dev->dev.archdata.dma_data = (void *)PCI_DRAM_OFFSET;
 
 		/* Read default IRQs and fixup if necessary */
-		pci_read_irq_line(dev);
+		dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
 	}
 }
 
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index d9d81c2..6e23912 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -20,7 +20,6 @@
 platforms += netlogic
 platforms += pmcs-msp71xx
 platforms += pnx833x
-platforms += powertv
 platforms += ralink
 platforms += rb532
 platforms += sgi-ip22
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index f75ab4a..17cc7ff 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -8,6 +8,7 @@
 	select HAVE_PERF_EVENTS
 	select PERF_USE_VMALLOC
 	select HAVE_ARCH_KGDB
+	select HAVE_ARCH_TRACEHOOK
 	select ARCH_HAVE_CUSTOM_GPIO_H
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
@@ -18,6 +19,7 @@
 	select HAVE_KPROBES
 	select HAVE_KRETPROBES
 	select HAVE_DEBUG_KMEMLEAK
+	select HAVE_SYSCALL_TRACEPOINTS
 	select ARCH_BINFMT_ELF_RANDOMIZE_PIE
 	select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES && 64BIT
 	select RTC_LIB if !MACH_LOONGSON
@@ -146,6 +148,7 @@
 	select CSRC_R4K
 	select CEVT_GT641XX
 	select DMA_NONCOHERENT
+	select EARLY_PRINTK_8250 if EARLY_PRINTK
 	select HW_HAS_PCI
 	select I8253
 	select I8259
@@ -412,23 +415,6 @@
 	  of integrated peripherals, interfaces and DSPs in addition to
 	  a variety of MIPS cores.
 
-config POWERTV
-	bool "Cisco PowerTV"
-	select BOOT_ELF32
-	select CEVT_R4K
-	select CPU_MIPSR2_IRQ_VI
-	select CPU_MIPSR2_IRQ_EI
-	select CSRC_POWERTV
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select SYS_HAS_CPU_MIPS32_R2
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_BIG_ENDIAN
-	select SYS_SUPPORTS_HIGHMEM
-	select USB_OHCI_LITTLE_ENDIAN
-	help
-	  This enables support for the Cisco PowerTV Platform.
-
 config RALINK
 	bool "Ralink based machines"
 	select CEVT_R4K
@@ -811,7 +797,6 @@
 source "arch/mips/lantiq/Kconfig"
 source "arch/mips/lasat/Kconfig"
 source "arch/mips/pmcs-msp71xx/Kconfig"
-source "arch/mips/powertv/Kconfig"
 source "arch/mips/ralink/Kconfig"
 source "arch/mips/sgi-ip27/Kconfig"
 source "arch/mips/sibyte/Kconfig"
@@ -890,9 +875,6 @@
 config CSRC_IOASIC
 	bool
 
-config CSRC_POWERTV
-	bool
-
 config CSRC_R4K
 	bool
 
@@ -1489,8 +1471,10 @@
 	bool
 	select HAVE_KERNEL_GZIP
 	select HAVE_KERNEL_BZIP2
+	select HAVE_KERNEL_LZ4
 	select HAVE_KERNEL_LZMA
 	select HAVE_KERNEL_LZO
+	select HAVE_KERNEL_XZ
 
 config SYS_SUPPORTS_ZBOOT_UART16550
 	bool
@@ -1977,6 +1961,7 @@
 config MIPS_CMP
 	bool "MIPS CMP framework support"
 	depends on SYS_SUPPORTS_MIPS_CMP
+	select SMP
 	select SYNC_R4K
 	select SYS_SUPPORTS_SMP
 	select SYS_SUPPORTS_SCHED_SMT if SMP
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index 37871f0..b147e70 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -20,6 +20,14 @@
 	  doesn't cooperate with an X server. You should normally say N here,
 	  unless you want to debug such a crash.
 
+config EARLY_PRINTK_8250
+	bool "8250/16550 and compatible serial early printk driver"
+	depends on EARLY_PRINTK
+	default n
+	help
+	  If you say Y here, it will be possible to use a 8250/16550 serial
+	  port as the boot console.
+
 config CMDLINE_BOOL
 	bool "Built-in kernel command line"
 	default n
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index ca8f834..de300b9 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -285,15 +285,19 @@
 # Other need ECOFF, so we build a 32-bit ELF binary for them which we then
 # convert to ECOFF using elf2ecoff.
 #
+quiet_cmd_32 = OBJCOPY $@
+	cmd_32 = $(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@
 vmlinux.32: vmlinux
-	$(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@
+	$(call cmd,32)
 
 #
 # The 64-bit ELF tools are pretty broken so at this time we generate 64-bit
 # ELF files from 32-bit files by conversion.
 #
+quiet_cmd_64 = OBJCOPY $@
+	cmd_64 = $(OBJCOPY) -O $(64bit-bfd) $(OBJCOPYFLAGS) $< $@
 vmlinux.64: vmlinux
-	$(OBJCOPY) -O $(64bit-bfd) $(OBJCOPYFLAGS) $< $@
+	$(call cmd,64)
 
 all:	$(all-y)
 
@@ -302,10 +306,16 @@
 	$(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) \
 		$(bootvars-y) arch/mips/boot/$@
 
+ifdef CONFIG_SYS_SUPPORTS_ZBOOT
 # boot/compressed
 $(bootz-y): $(vmlinux-32) FORCE
 	$(Q)$(MAKE) $(build)=arch/mips/boot/compressed \
 		$(bootvars-y) 32bit-bfd=$(32bit-bfd) $@
+else
+vmlinuz: FORCE
+	@echo '   CONFIG_SYS_SUPPORTS_ZBOOT is not enabled'
+	/bin/false
+endif
 
 
 CLEAN_FILES += vmlinux.32 vmlinux.64
diff --git a/arch/mips/alchemy/devboards/db1235.c b/arch/mips/alchemy/devboards/db1235.c
index c76a90f..bac19dc 100644
--- a/arch/mips/alchemy/devboards/db1235.c
+++ b/arch/mips/alchemy/devboards/db1235.c
@@ -59,7 +59,7 @@
 		ret = -ENODEV;
 	}
 	if (ret)
-		panic("cannot initialize board support\n");
+		panic("cannot initialize board support");
 }
 
 int __init db1235_arch_init(void)
diff --git a/arch/mips/ath79/dev-common.c b/arch/mips/ath79/dev-common.c
index c3b04c9..516225d 100644
--- a/arch/mips/ath79/dev-common.c
+++ b/arch/mips/ath79/dev-common.c
@@ -20,7 +20,6 @@
 
 #include <asm/mach-ath79/ath79.h>
 #include <asm/mach-ath79/ar71xx_regs.h>
-#include <asm/mach-ath79/ar933x_uart_platform.h>
 #include "common.h"
 #include "dev-common.h"
 
@@ -68,15 +67,11 @@
 	},
 };
 
-static struct ar933x_uart_platform_data ar933x_uart_data;
 static struct platform_device ar933x_uart_device = {
 	.name		= "ar933x-uart",
 	.id		= -1,
 	.resource	= ar933x_uart_resources,
 	.num_resources	= ARRAY_SIZE(ar933x_uart_resources),
-	.dev = {
-		.platform_data	= &ar933x_uart_data,
-	},
 };
 
 void __init ath79_register_uart(void)
@@ -93,7 +88,6 @@
 		ath79_uart_data[0].uartclk = uart_clk_rate;
 		platform_device_register(&ath79_uart_device);
 	} else if (soc_is_ar933x()) {
-		ar933x_uart_data.uartclk = uart_clk_rate;
 		platform_device_register(&ar933x_uart_device);
 	} else {
 		BUG();
diff --git a/arch/mips/bcm47xx/Makefile b/arch/mips/bcm47xx/Makefile
index f3bf6d5..c52daf9 100644
--- a/arch/mips/bcm47xx/Makefile
+++ b/arch/mips/bcm47xx/Makefile
@@ -4,4 +4,5 @@
 #
 
 obj-y				+= irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
+obj-y				+= board.o
 obj-$(CONFIG_BCM47XX_SSB)	+= wgt634u.o
diff --git a/arch/mips/bcm47xx/board.c b/arch/mips/bcm47xx/board.c
new file mode 100644
index 0000000..f3f6bfe
--- /dev/null
+++ b/arch/mips/bcm47xx/board.c
@@ -0,0 +1,309 @@
+#include <linux/export.h>
+#include <linux/string.h>
+#include <bcm47xx_board.h>
+#include <bcm47xx_nvram.h>
+
+struct bcm47xx_board_type {
+	const enum bcm47xx_board board;
+	const char *name;
+};
+
+struct bcm47xx_board_type_list1 {
+	struct bcm47xx_board_type board;
+	const char *value1;
+};
+
+struct bcm47xx_board_type_list2 {
+	struct bcm47xx_board_type board;
+	const char *value1;
+	const char *value2;
+};
+
+struct bcm47xx_board_type_list3 {
+	struct bcm47xx_board_type board;
+	const char *value1;
+	const char *value2;
+	const char *value3;
+};
+
+struct bcm47xx_board_store {
+	enum bcm47xx_board board;
+	char name[BCM47XX_BOARD_MAX_NAME];
+};
+
+/* model_name */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_model_name[] __initconst = {
+	{{BCM47XX_BOARD_DLINK_DIR130, "D-Link DIR-130"}, "DIR-130"},
+	{{BCM47XX_BOARD_DLINK_DIR330, "D-Link DIR-330"}, "DIR-330"},
+	{ {0}, 0},
+};
+
+/* model_no */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_model_no[] __initconst = {
+	{{BCM47XX_BOARD_ASUS_WL700GE, "Asus WL700"}, "WL700"},
+	{ {0}, 0},
+};
+
+/* machine_name */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_machine_name[] __initconst = {
+	{{BCM47XX_BOARD_LINKSYS_WRTSL54GS, "Linksys WRTSL54GS"}, "WRTSL54GS"},
+	{ {0}, 0},
+};
+
+/* hardware_version */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_hardware_version[] __initconst = {
+	{{BCM47XX_BOARD_ASUS_RTN16, "Asus RT-N16"}, "RT-N16-"},
+	{{BCM47XX_BOARD_ASUS_WL320GE, "Asus WL320GE"}, "WL320G-"},
+	{{BCM47XX_BOARD_ASUS_WL330GE, "Asus WL330GE"}, "WL330GE-"},
+	{{BCM47XX_BOARD_ASUS_WL500GD, "Asus WL500GD"}, "WL500gd-"},
+	{{BCM47XX_BOARD_ASUS_WL500GPV1, "Asus WL500GP V1"}, "WL500gp-"},
+	{{BCM47XX_BOARD_ASUS_WL500GPV2, "Asus WL500GP V2"}, "WL500GPV2-"},
+	{{BCM47XX_BOARD_ASUS_WL500W, "Asus WL500W"}, "WL500gW-"},
+	{{BCM47XX_BOARD_ASUS_WL520GC, "Asus WL520GC"}, "WL520GC-"},
+	{{BCM47XX_BOARD_ASUS_WL520GU, "Asus WL520GU"}, "WL520GU-"},
+	{{BCM47XX_BOARD_BELKIN_F7D4301, "Belkin F7D4301"}, "F7D4301"},
+	{ {0}, 0},
+};
+
+/* productid */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_productid[] __initconst = {
+	{{BCM47XX_BOARD_ASUS_RTAC66U, "Asus RT-AC66U"}, "RT-AC66U"},
+	{{BCM47XX_BOARD_ASUS_RTN10, "Asus RT-N10"}, "RT-N10"},
+	{{BCM47XX_BOARD_ASUS_RTN10D, "Asus RT-N10D"}, "RT-N10D"},
+	{{BCM47XX_BOARD_ASUS_RTN10U, "Asus RT-N10U"}, "RT-N10U"},
+	{{BCM47XX_BOARD_ASUS_RTN12, "Asus RT-N12"}, "RT-N12"},
+	{{BCM47XX_BOARD_ASUS_RTN12B1, "Asus RT-N12B1"}, "RT-N12B1"},
+	{{BCM47XX_BOARD_ASUS_RTN12C1, "Asus RT-N12C1"}, "RT-N12C1"},
+	{{BCM47XX_BOARD_ASUS_RTN12D1, "Asus RT-N12D1"}, "RT-N12D1"},
+	{{BCM47XX_BOARD_ASUS_RTN12HP, "Asus RT-N12HP"}, "RT-N12HP"},
+	{{BCM47XX_BOARD_ASUS_RTN15U, "Asus RT-N15U"}, "RT-N15U"},
+	{{BCM47XX_BOARD_ASUS_RTN16, "Asus RT-N16"}, "RT-N16"},
+	{{BCM47XX_BOARD_ASUS_RTN53, "Asus RT-N53"}, "RT-N53"},
+	{{BCM47XX_BOARD_ASUS_RTN66U, "Asus RT-N66U"}, "RT-N66U"},
+	{{BCM47XX_BOARD_ASUS_WL300G, "Asus WL300G"}, "WL300g"},
+	{{BCM47XX_BOARD_ASUS_WLHDD, "Asus WLHDD"}, "WLHDD"},
+	{ {0}, 0},
+};
+
+/* ModelId */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_ModelId[] __initconst = {
+	{{BCM47XX_BOARD_DELL_TM2300, "Dell WX-5565"}, "WX-5565"},
+	{{BCM47XX_BOARD_MOTOROLA_WE800G, "Motorola WE800G"}, "WE800G"},
+	{{BCM47XX_BOARD_MOTOROLA_WR850GP, "Motorola WR850GP"}, "WR850GP"},
+	{{BCM47XX_BOARD_MOTOROLA_WR850GV2V3, "Motorola WR850G"}, "WR850G"},
+	{ {0}, 0},
+};
+
+/* melco_id or buf1falo_id */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_melco_id[] __initconst = {
+	{{BCM47XX_BOARD_BUFFALO_WBR2_G54, "Buffalo WBR2-G54"}, "29bb0332"},
+	{{BCM47XX_BOARD_BUFFALO_WHR2_A54G54, "Buffalo WHR2-A54G54"}, "290441dd"},
+	{{BCM47XX_BOARD_BUFFALO_WHR_G125, "Buffalo WHR-G125"}, "32093"},
+	{{BCM47XX_BOARD_BUFFALO_WHR_G54S, "Buffalo WHR-G54S"}, "30182"},
+	{{BCM47XX_BOARD_BUFFALO_WHR_HP_G54, "Buffalo WHR-HP-G54"}, "30189"},
+	{{BCM47XX_BOARD_BUFFALO_WLA2_G54L, "Buffalo WLA2-G54L"}, "29129"},
+	{{BCM47XX_BOARD_BUFFALO_WZR_G300N, "Buffalo WZR-G300N"}, "31120"},
+	{{BCM47XX_BOARD_BUFFALO_WZR_RS_G54, "Buffalo WZR-RS-G54"}, "30083"},
+	{{BCM47XX_BOARD_BUFFALO_WZR_RS_G54HP, "Buffalo WZR-RS-G54HP"}, "30103"},
+	{ {0}, 0},
+};
+
+/* boot_hw_model, boot_hw_ver */
+static const
+struct bcm47xx_board_type_list2 bcm47xx_board_list_boot_hw[] __initconst = {
+	/* like WRT160N v3.0 */
+	{{BCM47XX_BOARD_CISCO_M10V1, "Cisco M10"}, "M10", "1.0"},
+	/* like WRT310N v2.0 */
+	{{BCM47XX_BOARD_CISCO_M20V1, "Cisco M20"}, "M20", "1.0"},
+	{{BCM47XX_BOARD_LINKSYS_E900V1, "Linksys E900 V1"}, "E900", "1.0"},
+	/* like WRT160N v3.0 */
+	{{BCM47XX_BOARD_LINKSYS_E1000V1, "Linksys E1000 V1"}, "E100", "1.0"},
+	{{BCM47XX_BOARD_LINKSYS_E1000V2, "Linksys E1000 V2"}, "E1000", "2.0"},
+	{{BCM47XX_BOARD_LINKSYS_E1000V21, "Linksys E1000 V2.1"}, "E1000", "2.1"},
+	{{BCM47XX_BOARD_LINKSYS_E1200V2, "Linksys E1200 V2"}, "E1200", "2.0"},
+	{{BCM47XX_BOARD_LINKSYS_E2000V1, "Linksys E2000 V1"}, "Linksys E2000", "1.0"},
+	/* like WRT610N v2.0 */
+	{{BCM47XX_BOARD_LINKSYS_E3000V1, "Linksys E3000 V1"}, "E300", "1.0"},
+	{{BCM47XX_BOARD_LINKSYS_E3200V1, "Linksys E3200 V1"}, "E3200", "1.0"},
+	{{BCM47XX_BOARD_LINKSYS_E4200V1, "Linksys E4200 V1"}, "E4200", "1.0"},
+	{{BCM47XX_BOARD_LINKSYS_WRT150NV11, "Linksys WRT150N V1.1"}, "WRT150N", "1.1"},
+	{{BCM47XX_BOARD_LINKSYS_WRT150NV1, "Linksys WRT150N V1"}, "WRT150N", "1"},
+	{{BCM47XX_BOARD_LINKSYS_WRT160NV1, "Linksys WRT160N V1"}, "WRT160N", "1.0"},
+	{{BCM47XX_BOARD_LINKSYS_WRT160NV3, "Linksys WRT160N V3"}, "WRT160N", "3.0"},
+	{{BCM47XX_BOARD_LINKSYS_WRT300NV11, "Linksys WRT300N V1.1"}, "WRT300N", "1.1"},
+	{{BCM47XX_BOARD_LINKSYS_WRT310NV1, "Linksys WRT310N V1"}, "WRT310N", "1.0"},
+	{{BCM47XX_BOARD_LINKSYS_WRT310NV2, "Linksys WRT310N V2"}, "WRT310N", "2.0"},
+	{{BCM47XX_BOARD_LINKSYS_WRT54G3GV2, "Linksys WRT54G3GV2-VF"}, "WRT54G3GV2-VF", "1.0"},
+	{{BCM47XX_BOARD_LINKSYS_WRT610NV1, "Linksys WRT610N V1"}, "WRT610N", "1.0"},
+	{{BCM47XX_BOARD_LINKSYS_WRT610NV2, "Linksys WRT610N V2"}, "WRT610N", "2.0"},
+	{ {0}, 0},
+};
+
+/* board_id */
+static const
+struct bcm47xx_board_type_list1 bcm47xx_board_list_board_id[] __initconst = {
+	{{BCM47XX_BOARD_NETGEAR_WGR614V8, "Netgear WGR614 V8"}, "U12H072T00_NETGEAR"},
+	{{BCM47XX_BOARD_NETGEAR_WGR614V9, "Netgear WGR614 V9"}, "U12H094T00_NETGEAR"},
+	{{BCM47XX_BOARD_NETGEAR_WNDR3300, "Netgear WNDR3300"}, "U12H093T00_NETGEAR"},
+	{{BCM47XX_BOARD_NETGEAR_WNDR3400V1, "Netgear WNDR3400 V1"}, "U12H155T00_NETGEAR"},
+	{{BCM47XX_BOARD_NETGEAR_WNDR3400V2, "Netgear WNDR3400 V2"}, "U12H187T00_NETGEAR"},
+	{{BCM47XX_BOARD_NETGEAR_WNDR3400VCNA, "Netgear WNDR3400 Vcna"}, "U12H155T01_NETGEAR"},
+	{{BCM47XX_BOARD_NETGEAR_WNDR3700V3, "Netgear WNDR3700 V3"}, "U12H194T00_NETGEAR"},
+	{{BCM47XX_BOARD_NETGEAR_WNDR4000, "Netgear WNDR4000"}, "U12H181T00_NETGEAR"},
+	{{BCM47XX_BOARD_NETGEAR_WNDR4500V1, "Netgear WNDR4500 V1"}, "U12H189T00_NETGEAR"},
+	{{BCM47XX_BOARD_NETGEAR_WNDR4500V2, "Netgear WNDR4500 V2"}, "U12H224T00_NETGEAR"},
+	{{BCM47XX_BOARD_NETGEAR_WNR2000, "Netgear WNR2000"}, "U12H114T00_NETGEAR"},
+	{{BCM47XX_BOARD_NETGEAR_WNR3500L, "Netgear WNR3500L"}, "U12H136T99_NETGEAR"},
+	{{BCM47XX_BOARD_NETGEAR_WNR3500U, "Netgear WNR3500U"}, "U12H136T00_NETGEAR"},
+	{{BCM47XX_BOARD_NETGEAR_WNR3500V2, "Netgear WNR3500 V2"}, "U12H127T00_NETGEAR"},
+	{{BCM47XX_BOARD_NETGEAR_WNR3500V2VC, "Netgear WNR3500 V2vc"}, "U12H127T70_NETGEAR"},
+	{{BCM47XX_BOARD_NETGEAR_WNR834BV2, "Netgear WNR834B V2"}, "U12H081T00_NETGEAR"},
+	{ {0}, 0},
+};
+
+/* boardtype, boardnum, boardrev */
+static const
+struct bcm47xx_board_type_list3 bcm47xx_board_list_board[] __initconst = {
+	{{BCM47XX_BOARD_HUAWEI_E970, "Huawei E970"}, "0x048e", "0x5347", "0x11"},
+	{{BCM47XX_BOARD_PHICOMM_M1, "Phicomm M1"}, "0x0590", "80", "0x1104"},
+	{{BCM47XX_BOARD_ZTE_H218N, "ZTE H218N"}, "0x053d", "1234", "0x1305"},
+	{ {0}, 0},
+};
+
+static const
+struct bcm47xx_board_type bcm47xx_board_unknown[] __initconst = {
+	{BCM47XX_BOARD_UNKNOWN, "Unknown Board"},
+};
+
+static struct bcm47xx_board_store bcm47xx_board = {BCM47XX_BOARD_NO, "Unknown Board"};
+
+static __init const struct bcm47xx_board_type *bcm47xx_board_get_nvram(void)
+{
+	char buf1[30];
+	char buf2[30];
+	char buf3[30];
+	const struct bcm47xx_board_type_list1 *e1;
+	const struct bcm47xx_board_type_list2 *e2;
+	const struct bcm47xx_board_type_list3 *e3;
+
+	if (bcm47xx_nvram_getenv("model_name", buf1, sizeof(buf1)) >= 0) {
+		for (e1 = bcm47xx_board_list_model_name; e1->value1; e1++) {
+			if (!strcmp(buf1, e1->value1))
+				return &e1->board;
+		}
+	}
+
+	if (bcm47xx_nvram_getenv("model_no", buf1, sizeof(buf1)) >= 0) {
+		for (e1 = bcm47xx_board_list_model_no; e1->value1; e1++) {
+			if (strstarts(buf1, e1->value1))
+				return &e1->board;
+		}
+	}
+
+	if (bcm47xx_nvram_getenv("machine_name", buf1, sizeof(buf1)) >= 0) {
+		for (e1 = bcm47xx_board_list_machine_name; e1->value1; e1++) {
+			if (strstarts(buf1, e1->value1))
+				return &e1->board;
+		}
+	}
+
+	if (bcm47xx_nvram_getenv("hardware_version", buf1, sizeof(buf1)) >= 0) {
+		for (e1 = bcm47xx_board_list_hardware_version; e1->value1; e1++) {
+			if (strstarts(buf1, e1->value1))
+				return &e1->board;
+		}
+	}
+
+	if (bcm47xx_nvram_getenv("productid", buf1, sizeof(buf1)) >= 0) {
+		for (e1 = bcm47xx_board_list_productid; e1->value1; e1++) {
+			if (!strcmp(buf1, e1->value1))
+				return &e1->board;
+		}
+	}
+
+	if (bcm47xx_nvram_getenv("ModelId", buf1, sizeof(buf1)) >= 0) {
+		for (e1 = bcm47xx_board_list_ModelId; e1->value1; e1++) {
+			if (!strcmp(buf1, e1->value1))
+				return &e1->board;
+		}
+	}
+
+	if (bcm47xx_nvram_getenv("melco_id", buf1, sizeof(buf1)) >= 0 ||
+	    bcm47xx_nvram_getenv("buf1falo_id", buf1, sizeof(buf1)) >= 0) {
+		/* buffalo hardware, check id for specific hardware matches */
+		for (e1 = bcm47xx_board_list_melco_id; e1->value1; e1++) {
+			if (!strcmp(buf1, e1->value1))
+				return &e1->board;
+		}
+	}
+
+	if (bcm47xx_nvram_getenv("boot_hw_model", buf1, sizeof(buf1)) >= 0 &&
+	    bcm47xx_nvram_getenv("boot_hw_ver", buf2, sizeof(buf2)) >= 0) {
+		for (e2 = bcm47xx_board_list_boot_hw; e2->value1; e2++) {
+			if (!strcmp(buf1, e2->value1) &&
+			    !strcmp(buf2, e2->value2))
+				return &e2->board;
+		}
+	}
+
+	if (bcm47xx_nvram_getenv("board_id", buf1, sizeof(buf1)) >= 0) {
+		for (e1 = bcm47xx_board_list_board_id; e1->value1; e1++) {
+			if (!strcmp(buf1, e1->value1))
+				return &e1->board;
+		}
+	}
+
+	if (bcm47xx_nvram_getenv("boardtype", buf1, sizeof(buf1)) >= 0 &&
+	    bcm47xx_nvram_getenv("boardnum", buf2, sizeof(buf2)) >= 0 &&
+	    bcm47xx_nvram_getenv("boardrev", buf3, sizeof(buf3)) >= 0) {
+		for (e3 = bcm47xx_board_list_board; e3->value1; e3++) {
+			if (!strcmp(buf1, e3->value1) &&
+			    !strcmp(buf2, e3->value2) &&
+			    !strcmp(buf3, e3->value3))
+				return &e3->board;
+		}
+	}
+	return bcm47xx_board_unknown;
+}
+
+void __init bcm47xx_board_detect(void)
+{
+	int err;
+	char buf[10];
+	const struct bcm47xx_board_type *board_detected;
+
+	if (bcm47xx_board.board != BCM47XX_BOARD_NO)
+		return;
+
+	/* check if the nvram is available */
+	err = bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf));
+
+	/* init of nvram failed, probably too early now */
+	if (err == -ENXIO) {
+		return;
+	}
+
+	board_detected = bcm47xx_board_get_nvram();
+	bcm47xx_board.board = board_detected->board;
+	strlcpy(bcm47xx_board.name, board_detected->name,
+		BCM47XX_BOARD_MAX_NAME);
+}
+
+enum bcm47xx_board bcm47xx_board_get(void)
+{
+	return bcm47xx_board.board;
+}
+EXPORT_SYMBOL(bcm47xx_board_get);
+
+const char *bcm47xx_board_get_name(void)
+{
+	return bcm47xx_board.name;
+}
+EXPORT_SYMBOL(bcm47xx_board_get_name);
diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c
index cc40b74..b4c585b 100644
--- a/arch/mips/bcm47xx/nvram.c
+++ b/arch/mips/bcm47xx/nvram.c
@@ -190,3 +190,23 @@
 	return -ENOENT;
 }
 EXPORT_SYMBOL(bcm47xx_nvram_getenv);
+
+int bcm47xx_nvram_gpio_pin(const char *name)
+{
+	int i, err;
+	char nvram_var[10];
+	char buf[30];
+
+	for (i = 0; i < 16; i++) {
+		err = snprintf(nvram_var, sizeof(nvram_var), "gpio%i", i);
+		if (err <= 0)
+			continue;
+		err = bcm47xx_nvram_getenv(nvram_var, buf, sizeof(buf));
+		if (err <= 0)
+			continue;
+		if (!strcmp(name, buf))
+			return i;
+	}
+	return -ENOENT;
+}
+EXPORT_SYMBOL(bcm47xx_nvram_gpio_pin);
diff --git a/arch/mips/bcm47xx/prom.c b/arch/mips/bcm47xx/prom.c
index 8c155af..5cba318 100644
--- a/arch/mips/bcm47xx/prom.c
+++ b/arch/mips/bcm47xx/prom.c
@@ -32,12 +32,37 @@
 #include <asm/bootinfo.h>
 #include <asm/fw/cfe/cfe_api.h>
 #include <asm/fw/cfe/cfe_error.h>
+#include <bcm47xx.h>
+#include <bcm47xx_board.h>
 
 static int cfe_cons_handle;
 
+static u16 get_chip_id(void)
+{
+	switch (bcm47xx_bus_type) {
+#ifdef CONFIG_BCM47XX_SSB
+	case BCM47XX_BUS_TYPE_SSB:
+		return bcm47xx_bus.ssb.chip_id;
+#endif
+#ifdef CONFIG_BCM47XX_BCMA
+	case BCM47XX_BUS_TYPE_BCMA:
+		return bcm47xx_bus.bcma.bus.chipinfo.id;
+#endif
+	}
+	return 0;
+}
+
 const char *get_system_type(void)
 {
-	return "Broadcom BCM47XX";
+	static char buf[50];
+	u16 chip_id = get_chip_id();
+
+	snprintf(buf, sizeof(buf),
+		 (chip_id > 0x9999) ? "Broadcom BCM%d (%s)" :
+				      "Broadcom BCM%04X (%s)",
+		 chip_id, bcm47xx_board_get_name());
+
+	return buf;
 }
 
 void prom_putchar(char c)
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index b2246cd..1f30571 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -36,6 +36,7 @@
 #include <asm/time.h>
 #include <bcm47xx.h>
 #include <bcm47xx_nvram.h>
+#include <bcm47xx_board.h>
 
 union bcm47xx_bus bcm47xx_bus;
 EXPORT_SYMBOL(bcm47xx_bus);
@@ -221,6 +222,7 @@
 	_machine_restart = bcm47xx_machine_restart;
 	_machine_halt = bcm47xx_machine_halt;
 	pm_power_off = bcm47xx_machine_halt;
+	bcm47xx_board_detect();
 }
 
 static int __init bcm47xx_register_bus_complete(void)
diff --git a/arch/mips/bcm47xx/time.c b/arch/mips/bcm47xx/time.c
index 536374d..2c85d92 100644
--- a/arch/mips/bcm47xx/time.c
+++ b/arch/mips/bcm47xx/time.c
@@ -27,10 +27,16 @@
 #include <linux/ssb/ssb.h>
 #include <asm/time.h>
 #include <bcm47xx.h>
+#include <bcm47xx_nvram.h>
+#include <bcm47xx_board.h>
 
 void __init plat_time_init(void)
 {
 	unsigned long hz = 0;
+	u16 chip_id = 0;
+	char buf[10];
+	int len;
+	enum bcm47xx_board board = bcm47xx_board_get();
 
 	/*
 	 * Use deterministic values for initial counter interrupt
@@ -43,15 +49,32 @@
 #ifdef CONFIG_BCM47XX_SSB
 	case BCM47XX_BUS_TYPE_SSB:
 		hz = ssb_cpu_clock(&bcm47xx_bus.ssb.mipscore) / 2;
+		chip_id = bcm47xx_bus.ssb.chip_id;
 		break;
 #endif
 #ifdef CONFIG_BCM47XX_BCMA
 	case BCM47XX_BUS_TYPE_BCMA:
 		hz = bcma_cpu_clock(&bcm47xx_bus.bcma.bus.drv_mips) / 2;
+		chip_id = bcm47xx_bus.bcma.bus.chipinfo.id;
 		break;
 #endif
 	}
 
+	if (chip_id == 0x5354) {
+		len = bcm47xx_nvram_getenv("clkfreq", buf, sizeof(buf));
+		if (len >= 0 && !strncmp(buf, "200", 4))
+			hz = 100000000;
+	}
+
+	switch (board) {
+	case BCM47XX_BOARD_ASUS_WL520GC:
+	case BCM47XX_BOARD_ASUS_WL520GU:
+		hz = 100000000;
+		break;
+	default:
+		break;
+	}
+
 	if (!hz)
 		hz = 100000000;
 
diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
index 0048c08..ca0c343 100644
--- a/arch/mips/boot/compressed/Makefile
+++ b/arch/mips/boot/compressed/Makefile
@@ -37,6 +37,10 @@
 vmlinuzobjs-$(CONFIG_MIPS_ALCHEMY)		   += $(obj)/uart-alchemy.o
 endif
 
+ifdef CONFIG_KERNEL_XZ
+vmlinuzobjs-y += $(obj)/../../lib/ashldi3.o
+endif
+
 targets += vmlinux.bin
 OBJCOPYFLAGS_vmlinux.bin := $(OBJCOPYFLAGS) -O binary -R .comment -S
 $(obj)/vmlinux.bin: $(KBUILD_IMAGE) FORCE
@@ -44,8 +48,10 @@
 
 tool_$(CONFIG_KERNEL_GZIP)    = gzip
 tool_$(CONFIG_KERNEL_BZIP2)   = bzip2
+tool_$(CONFIG_KERNEL_LZ4)     = lz4
 tool_$(CONFIG_KERNEL_LZMA)    = lzma
 tool_$(CONFIG_KERNEL_LZO)     = lzo
+tool_$(CONFIG_KERNEL_XZ)      = xzkern
 
 targets += vmlinux.bin.z
 $(obj)/vmlinux.bin.z: $(obj)/vmlinux.bin FORCE
diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c
index 2c95730..a8c6fd6 100644
--- a/arch/mips/boot/compressed/decompress.c
+++ b/arch/mips/boot/compressed/decompress.c
@@ -43,7 +43,8 @@
 /* activate the code for pre-boot environment */
 #define STATIC static
 
-#ifdef CONFIG_KERNEL_GZIP
+#if defined(CONFIG_KERNEL_GZIP) || defined(CONFIG_KERNEL_XZ) || \
+	defined(CONFIG_KERNEL_LZ4)
 void *memcpy(void *dest, const void *src, size_t n)
 {
 	int i;
@@ -54,6 +55,8 @@
 		d[i] = s[i];
 	return dest;
 }
+#endif
+#ifdef CONFIG_KERNEL_GZIP
 #include "../../../../lib/decompress_inflate.c"
 #endif
 
@@ -70,6 +73,10 @@
 #include "../../../../lib/decompress_bunzip2.c"
 #endif
 
+#ifdef CONFIG_KERNEL_LZ4
+#include "../../../../lib/decompress_unlz4.c"
+#endif
+
 #ifdef CONFIG_KERNEL_LZMA
 #include "../../../../lib/decompress_unlzma.c"
 #endif
@@ -78,6 +85,10 @@
 #include "../../../../lib/decompress_unlzo.c"
 #endif
 
+#ifdef CONFIG_KERNEL_XZ
+#include "../../../../lib/decompress_unxz.c"
+#endif
+
 void decompress_kernel(unsigned long boot_heap_start)
 {
 	unsigned long zimage_start, zimage_size;
diff --git a/arch/mips/boot/compressed/ld.script b/arch/mips/boot/compressed/ld.script
index 8e6b07c..5a33409 100644
--- a/arch/mips/boot/compressed/ld.script
+++ b/arch/mips/boot/compressed/ld.script
@@ -8,6 +8,9 @@
 
 OUTPUT_ARCH(mips)
 ENTRY(start)
+PHDRS {
+	text PT_LOAD FLAGS(7); /* RWX */
+}
 SECTIONS
 {
 	/* Text and read-only data */
@@ -15,7 +18,7 @@
 	.text : {
 		*(.text)
 		*(.rodata)
-	}
+	}: text
 	/* End of text section */
 
 	/* Writable data */
diff --git a/arch/mips/boot/ecoff.h b/arch/mips/boot/ecoff.h
index 83e5c38..7a75ce2 100644
--- a/arch/mips/boot/ecoff.h
+++ b/arch/mips/boot/ecoff.h
@@ -12,7 +12,6 @@
 } FILHDR;
 #define FILHSZ	sizeof(FILHDR)
 
-#define OMAGIC		0407
 #define MIPSEBMAGIC	0x160
 #define MIPSELMAGIC	0x162
 
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index b212ae1..331b837 100644
--- a/arch/mips/cavium-octeon/setup.c
+++ b/arch/mips/cavium-octeon/setup.c
@@ -999,7 +999,7 @@
 
 	if (total == 0)
 		panic("Unable to allocate memory from "
-		      "cvmx_bootmem_phy_alloc\n");
+		      "cvmx_bootmem_phy_alloc");
 }
 
 /*
@@ -1081,7 +1081,7 @@
 	/* Copy the default tree from init memory. */
 	initial_boot_params = early_init_dt_alloc_memory_arch(dt_size, 8);
 	if (initial_boot_params == NULL)
-		panic("Could not allocate initial_boot_params\n");
+		panic("Could not allocate initial_boot_params");
 	memcpy(initial_boot_params, fdt, dt_size);
 
 	if (do_prune) {
diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
index 61a334a..558e949 100644
--- a/arch/mips/cobalt/Makefile
+++ b/arch/mips/cobalt/Makefile
@@ -5,5 +5,4 @@
 obj-y := buttons.o irq.o lcd.o led.o reset.o rtc.o serial.o setup.o time.o
 
 obj-$(CONFIG_PCI)		+= pci.o
-obj-$(CONFIG_EARLY_PRINTK)	+= console.o
 obj-$(CONFIG_MTD_PHYSMAP)	+= mtd.o
diff --git a/arch/mips/cobalt/console.c b/arch/mips/cobalt/console.c
deleted file mode 100644
index d1ba701..0000000
--- a/arch/mips/cobalt/console.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * (C) P. Horton 2006
- */
-#include <linux/io.h>
-#include <linux/serial_reg.h>
-
-#include <cobalt.h>
-
-#define UART_BASE	((void __iomem *)CKSEG1ADDR(0x1c800000))
-
-void prom_putchar(char c)
-{
-	if (cobalt_board_id <= COBALT_BRD_ID_QUBE1)
-		return;
-
-	while (!(readb(UART_BASE + UART_LSR) & UART_LSR_THRE))
-		;
-
-	writeb(c, UART_BASE + UART_TX);
-}
diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c
index ec3b2c4..9a8c2fe 100644
--- a/arch/mips/cobalt/setup.c
+++ b/arch/mips/cobalt/setup.c
@@ -17,6 +17,7 @@
 
 #include <asm/bootinfo.h>
 #include <asm/reboot.h>
+#include <asm/setup.h>
 #include <asm/gt64120.h>
 
 #include <cobalt.h>
@@ -112,6 +113,8 @@
 	}
 
 	add_memory_region(0x0, memsz, BOOT_MEM_RAM);
+
+	setup_8250_early_printk_port(CKSEG1ADDR(0x1c800000), 0, 0);
 }
 
 void __init prom_free_prom_memory(void)
diff --git a/arch/mips/configs/powertv_defconfig b/arch/mips/configs/powertv_defconfig
deleted file mode 100644
index 7fda0ce..0000000
--- a/arch/mips/configs/powertv_defconfig
+++ /dev/null
@@ -1,136 +0,0 @@
-CONFIG_POWERTV=y
-CONFIG_BOOTLOADER_FAMILY="R2"
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_HZ_1000=y
-CONFIG_PREEMPT=y
-# CONFIG_SECCOMP is not set
-CONFIG_EXPERIMENTAL=y
-CONFIG_CROSS_COMPILE=""
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_RELAY=y
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_RD_GZIP is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-# CONFIG_SYSCTL_SYSCALL is not set
-CONFIG_KALLSYMS_ALL=y
-# CONFIG_PCSPKR_PLATFORM is not set
-# CONFIG_EPOLL is not set
-# CONFIG_SIGNALFD is not set
-# CONFIG_EVENTFD is not set
-# CONFIG_VM_EVENT_COUNTERS is not set
-# CONFIG_SLUB_DEBUG 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_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_PCI=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_PNP=y
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
-CONFIG_INET6_AH=y
-CONFIG_INET6_ESP=y
-CONFIG_INET6_IPCOMP=y
-# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET6_XFRM_MODE_BEET is not set
-# CONFIG_IPV6_SIT is not set
-CONFIG_IPV6_TUNNEL=y
-CONFIG_NETFILTER=y
-# CONFIG_BRIDGE_NETFILTER is not set
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
-CONFIG_IP_NF_IPTABLES=y
-CONFIG_IP_NF_FILTER=y
-CONFIG_IP_NF_ARPTABLES=y
-CONFIG_IP_NF_ARPFILTER=y
-CONFIG_IP6_NF_IPTABLES=y
-CONFIG_IP6_NF_FILTER=y
-CONFIG_BRIDGE=y
-CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_TBF=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_NAND=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=32768
-# CONFIG_MISC_DEVICES is not set
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_ATA=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-# CONFIG_WLAN is not set
-CONFIG_USB_RTL8150=y
-# 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_VT is not set
-# CONFIG_DEVKMEM is not set
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-# CONFIG_MFD_SUPPORT is not set
-# CONFIG_VGA_ARB is not set
-CONFIG_USB_HIDDEV=y
-CONFIG_USB=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_DEVICE_CLASS is not set
-CONFIG_USB_EHCI_HCD=y
-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_SERIAL=y
-CONFIG_USB_SERIAL_CONSOLE=y
-CONFIG_USB_SERIAL_CP210X=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-# CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_DNOTIFY is not set
-CONFIG_FUSE_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_PRINTK_TIME=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DETECT_HUNG_TASK=y
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_DEBUG_PREEMPT is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_EARLY_PRINTK is not set
-CONFIG_CMDLINE_BOOL=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRYPTO_HW is not set
diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S
index 22afed1..41a2fa1 100644
--- a/arch/mips/dec/int-handler.S
+++ b/arch/mips/dec/int-handler.S
@@ -118,7 +118,7 @@
  *	       7	FPU/R4k timer
  *
  * We handle the IRQ according to _our_ priority (see setup.c),
- * then we just return.	 If multiple IRQs are pending then we will
+ * then we just return.  If multiple IRQs are pending then we will
  * just take another exception, big deal.
  */
 		.align	5
@@ -146,7 +146,7 @@
 		/*
 		 * Find irq with highest priority
 		 */
-		 PTR_LA t1,cpu_mask_nr_tbl
+		 PTR_LA	t1,cpu_mask_nr_tbl
 1:		lw	t2,(t1)
 		nop
 		and	t2,t0
@@ -195,7 +195,7 @@
 		/*
 		 * Find irq with highest priority
 		 */
-		 PTR_LA t1,asic_mask_nr_tbl
+		 PTR_LA	t1,asic_mask_nr_tbl
 2:		lw	t2,(t1)
 		nop
 		and	t2,t0
@@ -221,7 +221,7 @@
 		FEXPORT(cpu_all_int)		# HALT, timers, software junk
 		li	a0,DEC_CPU_IRQ_BASE
 		srl	t0,CAUSEB_IP
-		li	t1,CAUSEF_IP>>CAUSEB_IP # mask
+		li	t1,CAUSEF_IP>>CAUSEB_IP	# mask
 		b	1f
 		 li	t2,4			# nr of bits / 2
 
diff --git a/arch/mips/dec/ioasic-irq.c b/arch/mips/dec/ioasic-irq.c
index 4b3e3a4..e04d973 100644
--- a/arch/mips/dec/ioasic-irq.c
+++ b/arch/mips/dec/ioasic-irq.c
@@ -1,7 +1,7 @@
 /*
  *	DEC I/O ASIC interrupts.
  *
- *	Copyright (c) 2002, 2003  Maciej W. Rozycki
+ *	Copyright (c) 2002, 2003, 2013  Maciej W. Rozycki
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -51,22 +51,51 @@
 	.irq_unmask = unmask_ioasic_irq,
 };
 
-void clear_ioasic_dma_irq(unsigned int irq)
+static void clear_ioasic_dma_irq(struct irq_data *d)
 {
 	u32 sir;
 
-	sir = ~(1 << (irq - ioasic_irq_base));
+	sir = ~(1 << (d->irq - ioasic_irq_base));
 	ioasic_write(IO_REG_SIR, sir);
+	fast_iob();
 }
 
 static struct irq_chip ioasic_dma_irq_type = {
 	.name = "IO-ASIC-DMA",
-	.irq_ack = ack_ioasic_irq,
+	.irq_ack = clear_ioasic_dma_irq,
 	.irq_mask = mask_ioasic_irq,
-	.irq_mask_ack = ack_ioasic_irq,
 	.irq_unmask = unmask_ioasic_irq,
+	.irq_eoi = clear_ioasic_dma_irq,
 };
 
+/*
+ * I/O ASIC implements two kinds of DMA interrupts, informational and
+ * error interrupts.
+ *
+ * The formers do not stop DMA and should be cleared as soon as possible
+ * so that if they retrigger before the handler has completed, usually as
+ * a side effect of actions taken by the handler, then they are reissued.
+ * These use the `handle_edge_irq' handler that clears the request right
+ * away.
+ *
+ * The latters stop DMA and do not resume it until the interrupt has been
+ * cleared.  This cannot be done until after a corrective action has been
+ * taken and this also means they will not retrigger.  Therefore they use
+ * the `handle_fasteoi_irq' handler that only clears the request on the
+ * way out.  Because MIPS processor interrupt inputs, one of which the I/O
+ * ASIC is cascaded to, are level-triggered it is recommended that error
+ * DMA interrupt action handlers are registered with the IRQF_ONESHOT flag
+ * set so that they are run with the interrupt line masked.
+ *
+ * This mask has `1' bits in the positions of informational interrupts.
+ */
+#define IO_IRQ_DMA_INFO							\
+	(IO_IRQ_MASK(IO_INR_SCC0A_RXDMA) |				\
+	 IO_IRQ_MASK(IO_INR_SCC1A_RXDMA) |				\
+	 IO_IRQ_MASK(IO_INR_ISDN_TXDMA) |				\
+	 IO_IRQ_MASK(IO_INR_ISDN_RXDMA) |				\
+	 IO_IRQ_MASK(IO_INR_ASC_DMA))
+
 void __init init_ioasic_irqs(int base)
 {
 	int i;
@@ -79,7 +108,9 @@
 		irq_set_chip_and_handler(i, &ioasic_irq_type,
 					 handle_level_irq);
 	for (; i < base + IO_IRQ_LINES; i++)
-		irq_set_chip(i, &ioasic_dma_irq_type);
+		irq_set_chip_and_handler(i, &ioasic_dma_irq_type,
+					 1 << (i - base) & IO_IRQ_DMA_INFO ?
+					 handle_edge_irq : handle_fasteoi_irq);
 
 	ioasic_irq_base = base;
 }
diff --git a/arch/mips/dec/prom/call_o32.S b/arch/mips/dec/prom/call_o32.S
index c0d1522..8c84981 100644
--- a/arch/mips/dec/prom/call_o32.S
+++ b/arch/mips/dec/prom/call_o32.S
@@ -14,7 +14,7 @@
 
 /* Maximum number of arguments supported.  Must be even!  */
 #define O32_ARGC	32
-/* Number of static registers we save.	*/
+/* Number of static registers we save.  */
 #define O32_STATC	11
 /* Frame size for both of the above.  */
 #define O32_FRAMESZ	(4 * O32_ARGC + SZREG * O32_STATC)
diff --git a/arch/mips/dec/prom/init.c b/arch/mips/dec/prom/init.c
index 468f665..4e1761e 100644
--- a/arch/mips/dec/prom/init.c
+++ b/arch/mips/dec/prom/init.c
@@ -104,7 +104,7 @@
 	if (prom_is_rex(magic))
 		rex_clear_cache();
 
-	/* Register the early console.	*/
+	/* Register the early console.  */
 	register_prom_console();
 
 	/* Were we compiled with the right CPU option? */
diff --git a/arch/mips/dec/prom/memory.c b/arch/mips/dec/prom/memory.c
index 0aadac7..8c62316 100644
--- a/arch/mips/dec/prom/memory.c
+++ b/arch/mips/dec/prom/memory.c
@@ -22,7 +22,7 @@
 
 /*
  * Probe memory in 4MB chunks, waiting for an error to tell us we've fallen
- * off the end of real memory.	Only suitable for the 2100/3100's (PMAX).
+ * off the end of real memory.  Only suitable for the 2100/3100's (PMAX).
  */
 
 #define CHUNK_SIZE 0x400000
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index 741cb42..56e6e2c 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -65,7 +65,7 @@
 /*
  * IRQ routing and priority tables.  Priorites are set as follows:
  *
- *		KN01	KN230	KN02	KN02-BA KN02-CA KN03
+ *		KN01	KN230	KN02	KN02-BA	KN02-CA	KN03
  *
  * MEMORY	CPU	CPU	CPU	ASIC	CPU	CPU
  * RTC		CPU	CPU	CPU	ASIC	CPU	CPU
@@ -413,7 +413,7 @@
 
 /*
  * Machine-specific initialisation for KN02-BA, aka DS5000/1xx
- * (xx = 20, 25, 33), aka 3min.	 Also applies to KN04(-BA), aka
+ * (xx = 20, 25, 33), aka 3min.  Also applies to KN04(-BA), aka
  * DS5000/150, aka 4min.
  */
 static int kn02ba_interrupt[DEC_NR_INTS] __initdata = {
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 454ddf9..1acbb8b 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -11,5 +11,6 @@
 generic-y += segment.h
 generic-y += serial.h
 generic-y += trace_clock.h
+generic-y += preempt.h
 generic-y += ucontext.h
 generic-y += xor.h
diff --git a/arch/mips/include/asm/addrspace.h b/arch/mips/include/asm/addrspace.h
index 13d61c0..3f74545 100644
--- a/arch/mips/include/asm/addrspace.h
+++ b/arch/mips/include/asm/addrspace.h
@@ -58,7 +58,7 @@
 
 /*
  * Memory segments (64bit kernel mode addresses)
- * The compatibility segments use the full 64-bit sign extended value.	Note
+ * The compatibility segments use the full 64-bit sign extended value.  Note
  * the R8000 doesn't have them so don't reference these in generic MIPS code.
  */
 #define XKUSEG			_CONST64_(0x0000000000000000)
@@ -131,7 +131,7 @@
 
 /*
  * The ultimate limited of the 64-bit MIPS architecture:  2 bits for selecting
- * the region, 3 bits for the CCA mode.	 This leaves 59 bits of which the
+ * the region, 3 bits for the CCA mode.  This leaves 59 bits of which the
  * R8000 implements most with its 48-bit physical address space.
  */
 #define TO_PHYS_MASK	_CONST64_(0x07ffffffffffffff)	/* 2^^59 - 1 */
diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
index 08b6079..7eed2f2 100644
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h
@@ -1,5 +1,5 @@
 /*
- * Atomic operations that C can't guarantee us.	 Useful for
+ * Atomic operations that C can't guarantee us.  Useful for
  * resource counting etc..
  *
  * But use these as seldom as possible since they are much more slower
diff --git a/arch/mips/include/asm/barrier.h b/arch/mips/include/asm/barrier.h
index 314ab55..f26d8e1 100644
--- a/arch/mips/include/asm/barrier.h
+++ b/arch/mips/include/asm/barrier.h
@@ -18,7 +18,7 @@
  * over this barrier.  All reads preceding this primitive are guaranteed
  * to access memory (but not necessarily other CPUs' caches) before any
  * reads following this primitive that depend on the data return by
- * any of the preceding reads.	This primitive is much lighter weight than
+ * any of the preceding reads.  This primitive is much lighter weight than
  * rmb() on most CPUs, and is never heavier weight than is
  * rmb().
  *
@@ -43,7 +43,7 @@
  * </programlisting>
  *
  * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends().	 However,
+ * two reads are separated by a read_barrier_depends().  However,
  * the following code, with the same initial values for "a" and "b":
  *
  * <programlisting>
@@ -57,7 +57,7 @@
  * </programlisting>
  *
  * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b".	 Therefore, on some CPUs, such
+ * the read of "a" and the read of "b".  Therefore, on some CPUs, such
  * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
  * in cases like this where there are no data dependencies.
  */
diff --git a/arch/mips/include/asm/cacheops.h b/arch/mips/include/asm/cacheops.h
index 68f37e3..c75025f 100644
--- a/arch/mips/include/asm/cacheops.h
+++ b/arch/mips/include/asm/cacheops.h
@@ -14,56 +14,52 @@
 /*
  * Cache Operations available on all MIPS processors with R4000-style caches
  */
-#define Index_Invalidate_I	0x00
-#define Index_Writeback_Inv_D	0x01
-#define Index_Load_Tag_I	0x04
-#define Index_Load_Tag_D	0x05
-#define Index_Store_Tag_I	0x08
-#define Index_Store_Tag_D	0x09
-#if defined(CONFIG_CPU_LOONGSON2)
-#define Hit_Invalidate_I	0x00
-#else
-#define Hit_Invalidate_I	0x10
-#endif
-#define Hit_Invalidate_D	0x11
-#define Hit_Writeback_Inv_D	0x15
+#define Index_Invalidate_I		0x00
+#define Index_Writeback_Inv_D		0x01
+#define Index_Load_Tag_I		0x04
+#define Index_Load_Tag_D		0x05
+#define Index_Store_Tag_I		0x08
+#define Index_Store_Tag_D		0x09
+#define Hit_Invalidate_I		0x10
+#define Hit_Invalidate_D		0x11
+#define Hit_Writeback_Inv_D		0x15
 
 /*
  * R4000-specific cacheops
  */
-#define Create_Dirty_Excl_D	0x0d
-#define Fill			0x14
-#define Hit_Writeback_I		0x18
-#define Hit_Writeback_D		0x19
+#define Create_Dirty_Excl_D		0x0d
+#define Fill				0x14
+#define Hit_Writeback_I			0x18
+#define Hit_Writeback_D			0x19
 
 /*
  * R4000SC and R4400SC-specific cacheops
  */
-#define Index_Invalidate_SI	0x02
-#define Index_Writeback_Inv_SD	0x03
-#define Index_Load_Tag_SI	0x06
-#define Index_Load_Tag_SD	0x07
-#define Index_Store_Tag_SI	0x0A
-#define Index_Store_Tag_SD	0x0B
-#define Create_Dirty_Excl_SD	0x0f
-#define Hit_Invalidate_SI	0x12
-#define Hit_Invalidate_SD	0x13
-#define Hit_Writeback_Inv_SD	0x17
-#define Hit_Writeback_SD	0x1b
-#define Hit_Set_Virtual_SI	0x1e
-#define Hit_Set_Virtual_SD	0x1f
+#define Index_Invalidate_SI		0x02
+#define Index_Writeback_Inv_SD		0x03
+#define Index_Load_Tag_SI		0x06
+#define Index_Load_Tag_SD		0x07
+#define Index_Store_Tag_SI		0x0A
+#define Index_Store_Tag_SD		0x0B
+#define Create_Dirty_Excl_SD		0x0f
+#define Hit_Invalidate_SI		0x12
+#define Hit_Invalidate_SD		0x13
+#define Hit_Writeback_Inv_SD		0x17
+#define Hit_Writeback_SD		0x1b
+#define Hit_Set_Virtual_SI		0x1e
+#define Hit_Set_Virtual_SD		0x1f
 
 /*
  * R5000-specific cacheops
  */
-#define R5K_Page_Invalidate_S	0x17
+#define R5K_Page_Invalidate_S		0x17
 
 /*
  * RM7000-specific cacheops
  */
-#define Page_Invalidate_T	0x16
-#define Index_Store_Tag_T	0x0a
-#define Index_Load_Tag_T	0x06
+#define Page_Invalidate_T		0x16
+#define Index_Store_Tag_T		0x0a
+#define Index_Load_Tag_T		0x06
 
 /*
  * R10000-specific cacheops
@@ -71,17 +67,22 @@
  * Cacheops 0x02, 0x06, 0x0a, 0x0c-0x0e, 0x16, 0x1a and 0x1e are unused.
  * Most of the _S cacheops are identical to the R4000SC _SD cacheops.
  */
-#define Index_Writeback_Inv_S	0x03
-#define Index_Load_Tag_S	0x07
-#define Index_Store_Tag_S	0x0B
-#define Hit_Invalidate_S	0x13
-#define Cache_Barrier		0x14
-#define Hit_Writeback_Inv_S	0x17
-#define Index_Load_Data_I	0x18
-#define Index_Load_Data_D	0x19
-#define Index_Load_Data_S	0x1b
-#define Index_Store_Data_I	0x1c
-#define Index_Store_Data_D	0x1d
-#define Index_Store_Data_S	0x1f
+#define Index_Writeback_Inv_S		0x03
+#define Index_Load_Tag_S		0x07
+#define Index_Store_Tag_S		0x0B
+#define Hit_Invalidate_S		0x13
+#define Cache_Barrier			0x14
+#define Hit_Writeback_Inv_S		0x17
+#define Index_Load_Data_I		0x18
+#define Index_Load_Data_D		0x19
+#define Index_Load_Data_S		0x1b
+#define Index_Store_Data_I		0x1c
+#define Index_Store_Data_D		0x1d
+#define Index_Store_Data_S		0x1f
+
+/*
+ * Loongson2-specific cacheops
+ */
+#define Hit_Invalidate_I_Loongson23	0x00
 
 #endif	/* __ASM_CACHEOPS_H */
diff --git a/arch/mips/include/asm/dec/ioasic.h b/arch/mips/include/asm/dec/ioasic.h
index a6e505a..be4d62a 100644
--- a/arch/mips/include/asm/dec/ioasic.h
+++ b/arch/mips/include/asm/dec/ioasic.h
@@ -31,8 +31,6 @@
 	return ioasic_base[reg / 4];
 }
 
-extern void clear_ioasic_dma_irq(unsigned int irq);
-
 extern void init_ioasic_irqs(int base);
 
 extern int dec_ioasic_clocksource_init(void);
diff --git a/arch/mips/include/asm/dec/ioasic_addrs.h b/arch/mips/include/asm/dec/ioasic_addrs.h
index a8665a7..8bd9597 100644
--- a/arch/mips/include/asm/dec/ioasic_addrs.h
+++ b/arch/mips/include/asm/dec/ioasic_addrs.h
@@ -40,7 +40,7 @@
 #define IOASIC_FLOPPY	(11*IOASIC_SLOT_SIZE)	/* FDC (maxine) */
 #define IOASIC_SCSI	(12*IOASIC_SLOT_SIZE)	/* ASC SCSI */
 #define IOASIC_FDC_DMA	(13*IOASIC_SLOT_SIZE)	/* FDC DMA (maxine) */
-#define IOASIC_SCSI_DMA (14*IOASIC_SLOT_SIZE)	/* ??? */
+#define IOASIC_SCSI_DMA	(14*IOASIC_SLOT_SIZE)	/* ??? */
 #define IOASIC_RES_15	(15*IOASIC_SLOT_SIZE)	/* unused? */
 
 
diff --git a/arch/mips/include/asm/dec/kn01.h b/arch/mips/include/asm/dec/kn01.h
index 0eb3241..88d9ffd 100644
--- a/arch/mips/include/asm/dec/kn01.h
+++ b/arch/mips/include/asm/dec/kn01.h
@@ -57,12 +57,12 @@
 /*
  * System Control & Status Register bits.
  */
-#define KN01_CSR_MNFMOD		(1<<15) /* MNFMOD manufacturing jumper */
-#define KN01_CSR_STATUS		(1<<14) /* self-test result status output */
-#define KN01_CSR_PARDIS		(1<<13) /* parity error disable */
-#define KN01_CSR_CRSRTST	(1<<12) /* PCC test output */
-#define KN01_CSR_MONO		(1<<11) /* mono/color fb SIMM installed */
-#define KN01_CSR_MEMERR		(1<<10) /* write timeout error status & ack*/
+#define KN01_CSR_MNFMOD		(1<<15)	/* MNFMOD manufacturing jumper */
+#define KN01_CSR_STATUS		(1<<14)	/* self-test result status output */
+#define KN01_CSR_PARDIS		(1<<13)	/* parity error disable */
+#define KN01_CSR_CRSRTST	(1<<12)	/* PCC test output */
+#define KN01_CSR_MONO		(1<<11)	/* mono/color fb SIMM installed */
+#define KN01_CSR_MEMERR		(1<<10)	/* write timeout error status & ack*/
 #define KN01_CSR_VINT		(1<<9)	/* PCC area detect #2 status & ack */
 #define KN01_CSR_TXDIS		(1<<8)	/* DZ11 transmit disable */
 #define KN01_CSR_VBGTRG		(1<<2)	/* blue DAC voltage over green (r/o) */
diff --git a/arch/mips/include/asm/dec/kn02ca.h b/arch/mips/include/asm/dec/kn02ca.h
index 69dc2a9..92c0fe2 100644
--- a/arch/mips/include/asm/dec/kn02ca.h
+++ b/arch/mips/include/asm/dec/kn02ca.h
@@ -68,7 +68,7 @@
 #define KN03CA_IO_SSR_ISDN_RST	(1<<12)		/* ~ISDN (Am79C30A) reset */
 
 #define KN03CA_IO_SSR_FLOPPY_RST (1<<7)		/* ~FDC (82077) reset */
-#define KN03CA_IO_SSR_VIDEO_RST (1<<6)		/* ~framebuffer reset */
+#define KN03CA_IO_SSR_VIDEO_RST	(1<<6)		/* ~framebuffer reset */
 #define KN03CA_IO_SSR_AB_RST	(1<<5)		/* ACCESS.bus reset */
 #define KN03CA_IO_SSR_RES_4	(1<<4)		/* unused */
 #define KN03CA_IO_SSR_RES_3	(1<<4)		/* unused */
diff --git a/arch/mips/include/asm/dec/prom.h b/arch/mips/include/asm/dec/prom.h
index 4465777..c0ead63 100644
--- a/arch/mips/include/asm/dec/prom.h
+++ b/arch/mips/include/asm/dec/prom.h
@@ -49,7 +49,7 @@
 
 #ifdef CONFIG_64BIT
 
-#define prom_is_rex(magic)	1	/* KN04 and KN05 are REX PROMs.	 */
+#define prom_is_rex(magic)	1	/* KN04 and KN05 are REX PROMs.  */
 
 #else /* !CONFIG_64BIT */
 
diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
index cf3ae24..a66359e 100644
--- a/arch/mips/include/asm/elf.h
+++ b/arch/mips/include/asm/elf.h
@@ -331,6 +331,7 @@
 #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs)			\
 	dump_task_fpu(tsk, elf_fpregs)
 
+#define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
 /* This yields a mask that user programs can use to figure out what
diff --git a/arch/mips/include/asm/jump_label.h b/arch/mips/include/asm/jump_label.h
index 4d6d77e..e194f95 100644
--- a/arch/mips/include/asm/jump_label.h
+++ b/arch/mips/include/asm/jump_label.h
@@ -22,7 +22,7 @@
 
 static __always_inline bool arch_static_branch(struct static_key *key)
 {
-	asm goto("1:\tnop\n\t"
+	asm_volatile_goto("1:\tnop\n\t"
 		"nop\n\t"
 		".pushsection __jump_table,  \"aw\"\n\t"
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
diff --git a/arch/mips/include/asm/mach-ath79/ar933x_uart_platform.h b/arch/mips/include/asm/mach-ath79/ar933x_uart_platform.h
deleted file mode 100644
index 6cb30f2..0000000
--- a/arch/mips/include/asm/mach-ath79/ar933x_uart_platform.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- *  Platform data definition for Atheros AR933X UART
- *
- *  Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License version 2 as published
- *  by the Free Software Foundation.
- */
-
-#ifndef _AR933X_UART_PLATFORM_H
-#define _AR933X_UART_PLATFORM_H
-
-struct ar933x_uart_platform_data {
-	unsigned	uartclk;
-};
-
-#endif /* _AR933X_UART_PLATFORM_H */
diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
new file mode 100644
index 0000000..00867dd
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
@@ -0,0 +1,110 @@
+#ifndef __BCM47XX_BOARD_H
+#define __BCM47XX_BOARD_H
+
+enum bcm47xx_board {
+	BCM47XX_BOARD_ASUS_RTAC66U,
+	BCM47XX_BOARD_ASUS_RTN10,
+	BCM47XX_BOARD_ASUS_RTN10D,
+	BCM47XX_BOARD_ASUS_RTN10U,
+	BCM47XX_BOARD_ASUS_RTN12,
+	BCM47XX_BOARD_ASUS_RTN12B1,
+	BCM47XX_BOARD_ASUS_RTN12C1,
+	BCM47XX_BOARD_ASUS_RTN12D1,
+	BCM47XX_BOARD_ASUS_RTN12HP,
+	BCM47XX_BOARD_ASUS_RTN15U,
+	BCM47XX_BOARD_ASUS_RTN16,
+	BCM47XX_BOARD_ASUS_RTN53,
+	BCM47XX_BOARD_ASUS_RTN66U,
+	BCM47XX_BOARD_ASUS_WL300G,
+	BCM47XX_BOARD_ASUS_WL320GE,
+	BCM47XX_BOARD_ASUS_WL330GE,
+	BCM47XX_BOARD_ASUS_WL500GD,
+	BCM47XX_BOARD_ASUS_WL500GPV1,
+	BCM47XX_BOARD_ASUS_WL500GPV2,
+	BCM47XX_BOARD_ASUS_WL500W,
+	BCM47XX_BOARD_ASUS_WL520GC,
+	BCM47XX_BOARD_ASUS_WL520GU,
+	BCM47XX_BOARD_ASUS_WL700GE,
+	BCM47XX_BOARD_ASUS_WLHDD,
+
+	BCM47XX_BOARD_BELKIN_F7D4301,
+
+	BCM47XX_BOARD_BUFFALO_WBR2_G54,
+	BCM47XX_BOARD_BUFFALO_WHR2_A54G54,
+	BCM47XX_BOARD_BUFFALO_WHR_G125,
+	BCM47XX_BOARD_BUFFALO_WHR_G54S,
+	BCM47XX_BOARD_BUFFALO_WHR_HP_G54,
+	BCM47XX_BOARD_BUFFALO_WLA2_G54L,
+	BCM47XX_BOARD_BUFFALO_WZR_G300N,
+	BCM47XX_BOARD_BUFFALO_WZR_RS_G54,
+	BCM47XX_BOARD_BUFFALO_WZR_RS_G54HP,
+
+	BCM47XX_BOARD_CISCO_M10V1,
+	BCM47XX_BOARD_CISCO_M20V1,
+
+	BCM47XX_BOARD_DELL_TM2300,
+
+	BCM47XX_BOARD_DLINK_DIR130,
+	BCM47XX_BOARD_DLINK_DIR330,
+
+	BCM47XX_BOARD_HUAWEI_E970,
+
+	BCM47XX_BOARD_LINKSYS_E900V1,
+	BCM47XX_BOARD_LINKSYS_E1000V1,
+	BCM47XX_BOARD_LINKSYS_E1000V2,
+	BCM47XX_BOARD_LINKSYS_E1000V21,
+	BCM47XX_BOARD_LINKSYS_E1200V2,
+	BCM47XX_BOARD_LINKSYS_E2000V1,
+	BCM47XX_BOARD_LINKSYS_E3000V1,
+	BCM47XX_BOARD_LINKSYS_E3200V1,
+	BCM47XX_BOARD_LINKSYS_E4200V1,
+	BCM47XX_BOARD_LINKSYS_WRT150NV1,
+	BCM47XX_BOARD_LINKSYS_WRT150NV11,
+	BCM47XX_BOARD_LINKSYS_WRT160NV1,
+	BCM47XX_BOARD_LINKSYS_WRT160NV3,
+	BCM47XX_BOARD_LINKSYS_WRT300NV11,
+	BCM47XX_BOARD_LINKSYS_WRT310NV1,
+	BCM47XX_BOARD_LINKSYS_WRT310NV2,
+	BCM47XX_BOARD_LINKSYS_WRT54G3GV2,
+	BCM47XX_BOARD_LINKSYS_WRT610NV1,
+	BCM47XX_BOARD_LINKSYS_WRT610NV2,
+	BCM47XX_BOARD_LINKSYS_WRTSL54GS,
+
+	BCM47XX_BOARD_MOTOROLA_WE800G,
+	BCM47XX_BOARD_MOTOROLA_WR850GP,
+	BCM47XX_BOARD_MOTOROLA_WR850GV2V3,
+
+	BCM47XX_BOARD_NETGEAR_WGR614V8,
+	BCM47XX_BOARD_NETGEAR_WGR614V9,
+	BCM47XX_BOARD_NETGEAR_WNDR3300,
+	BCM47XX_BOARD_NETGEAR_WNDR3400V1,
+	BCM47XX_BOARD_NETGEAR_WNDR3400V2,
+	BCM47XX_BOARD_NETGEAR_WNDR3400VCNA,
+	BCM47XX_BOARD_NETGEAR_WNDR3700V3,
+	BCM47XX_BOARD_NETGEAR_WNDR4000,
+	BCM47XX_BOARD_NETGEAR_WNDR4500V1,
+	BCM47XX_BOARD_NETGEAR_WNDR4500V2,
+	BCM47XX_BOARD_NETGEAR_WNR2000,
+	BCM47XX_BOARD_NETGEAR_WNR3500L,
+	BCM47XX_BOARD_NETGEAR_WNR3500U,
+	BCM47XX_BOARD_NETGEAR_WNR3500V2,
+	BCM47XX_BOARD_NETGEAR_WNR3500V2VC,
+	BCM47XX_BOARD_NETGEAR_WNR834BV2,
+
+	BCM47XX_BOARD_PHICOMM_M1,
+
+	BCM47XX_BOARD_SIMPLETECH_SIMPLESHARE,
+
+	BCM47XX_BOARD_ZTE_H218N,
+
+	BCM47XX_BOARD_UNKNOWN,
+	BCM47XX_BOARD_NO,
+};
+
+#define BCM47XX_BOARD_MAX_NAME 30
+
+void bcm47xx_board_detect(void);
+enum bcm47xx_board bcm47xx_board_get(void);
+const char *bcm47xx_board_get_name(void);
+
+#endif /* __BCM47XX_BOARD_H */
diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h
index b8e7be8..36a3fc1 100644
--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_nvram.h
@@ -48,4 +48,6 @@
 		printk(KERN_WARNING "Can not parse mac address: %s\n", buf);
 }
 
+int bcm47xx_nvram_gpio_pin(const char *name);
+
 #endif /* __BCM47XX_NVRAM_H */
diff --git a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
index 47fb247..f9f4486 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
@@ -52,23 +52,11 @@
 	return 0;
 }
 
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
-	BUG();
-}
-
 static inline int plat_device_is_coherent(struct device *dev)
 {
 	return 1;
 }
 
-static inline int plat_dma_mapping_error(struct device *dev,
-					 dma_addr_t dma_addr)
-{
-	BUG();
-	return 0;
-}
-
 dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
 phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
 
diff --git a/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h b/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h
new file mode 100644
index 0000000..acce27f
--- /dev/null
+++ b/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h
@@ -0,0 +1,87 @@
+/*
+ *	CPU feature overrides for DECstation systems.  Two variations
+ *	are generally applicable.
+ *
+ *	Copyright (C) 2013  Maciej W. Rozycki
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ */
+#ifndef __ASM_MACH_DEC_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_DEC_CPU_FEATURE_OVERRIDES_H
+
+/* Generic ones first.  */
+#define cpu_has_tlb			1
+#define cpu_has_tx39_cache		0
+#define cpu_has_fpu			1
+#define cpu_has_divec			0
+#define cpu_has_prefetch		0
+#define cpu_has_mcheck			0
+#define cpu_has_ejtag			0
+#define cpu_has_mips16			0
+#define cpu_has_mdmx			0
+#define cpu_has_mips3d			0
+#define cpu_has_smartmips		0
+#define cpu_has_rixi			0
+#define cpu_has_vtag_icache		0
+#define cpu_has_ic_fills_f_dc		0
+#define cpu_has_pindexed_dcache		0
+#define cpu_has_local_ebase		0
+#define cpu_icache_snoops_remote_store	1
+#define cpu_has_mips_4			0
+#define cpu_has_mips_5			0
+#define cpu_has_mips32r1		0
+#define cpu_has_mips32r2		0
+#define cpu_has_mips64r1		0
+#define cpu_has_mips64r2		0
+#define cpu_has_dsp			0
+#define cpu_has_mipsmt			0
+#define cpu_has_userlocal		0
+
+/* R3k-specific ones.  */
+#ifdef CONFIG_CPU_R3000
+#define cpu_has_4kex			0
+#define cpu_has_3k_cache		1
+#define cpu_has_4k_cache		0
+#define cpu_has_32fpr			0
+#define cpu_has_counter			0
+#define cpu_has_watch			0
+#define cpu_has_vce			0
+#define cpu_has_cache_cdex_p		0
+#define cpu_has_cache_cdex_s		0
+#define cpu_has_llsc			0
+#define cpu_has_dc_aliases		0
+#define cpu_has_mips_2			0
+#define cpu_has_mips_3			0
+#define cpu_has_nofpuex			1
+#define cpu_has_inclusive_pcaches	0
+#define cpu_dcache_line_size()		4
+#define cpu_icache_line_size()		4
+#define cpu_scache_line_size()		0
+#endif /* CONFIG_CPU_R3000 */
+
+/* R4k-specific ones.  */
+#ifdef CONFIG_CPU_R4X00
+#define cpu_has_4kex			1
+#define cpu_has_3k_cache		0
+#define cpu_has_4k_cache		1
+#define cpu_has_32fpr			1
+#define cpu_has_counter			1
+#define cpu_has_watch			1
+#define cpu_has_vce			1
+#define cpu_has_cache_cdex_p		1
+#define cpu_has_cache_cdex_s		1
+#define cpu_has_llsc			1
+#define cpu_has_dc_aliases		(PAGE_SIZE < 0x4000)
+#define cpu_has_mips_2			1
+#define cpu_has_mips_3			1
+#define cpu_has_nofpuex			0
+#define cpu_has_inclusive_pcaches	1
+#define cpu_dcache_line_size()		16
+#define cpu_icache_line_size()		16
+#define cpu_scache_line_size()		32
+#endif /* CONFIG_CPU_R4X00 */
+
+#endif /* __ASM_MACH_DEC_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h
index 74cb992..a9e8f6b 100644
--- a/arch/mips/include/asm/mach-generic/dma-coherence.h
+++ b/arch/mips/include/asm/mach-generic/dma-coherence.h
@@ -47,16 +47,6 @@
 	return 1;
 }
 
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
-}
-
-static inline int plat_dma_mapping_error(struct device *dev,
-					 dma_addr_t dma_addr)
-{
-	return 0;
-}
-
 static inline int plat_device_is_coherent(struct device *dev)
 {
 #ifdef CONFIG_DMA_COHERENT
diff --git a/arch/mips/include/asm/mach-ip27/dma-coherence.h b/arch/mips/include/asm/mach-ip27/dma-coherence.h
index 06c4419..4ffddfd 100644
--- a/arch/mips/include/asm/mach-ip27/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ip27/dma-coherence.h
@@ -58,16 +58,6 @@
 	return 1;
 }
 
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
-}
-
-static inline int plat_dma_mapping_error(struct device *dev,
-					 dma_addr_t dma_addr)
-{
-	return 0;
-}
-
 static inline int plat_device_is_coherent(struct device *dev)
 {
 	return 1;		/* IP27 non-cohernet mode is unsupported */
diff --git a/arch/mips/include/asm/mach-ip32/dma-coherence.h b/arch/mips/include/asm/mach-ip32/dma-coherence.h
index 073f0c4..104cfbc 100644
--- a/arch/mips/include/asm/mach-ip32/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ip32/dma-coherence.h
@@ -80,17 +80,6 @@
 	return 1;
 }
 
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
-	return;
-}
-
-static inline int plat_dma_mapping_error(struct device *dev,
-					 dma_addr_t dma_addr)
-{
-	return 0;
-}
-
 static inline int plat_device_is_coherent(struct device *dev)
 {
 	return 0;		/* IP32 is non-cohernet */
diff --git a/arch/mips/include/asm/mach-jazz/dma-coherence.h b/arch/mips/include/asm/mach-jazz/dma-coherence.h
index 9fc1e9a..949003e 100644
--- a/arch/mips/include/asm/mach-jazz/dma-coherence.h
+++ b/arch/mips/include/asm/mach-jazz/dma-coherence.h
@@ -48,16 +48,6 @@
 	return 1;
 }
 
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
-}
-
-static inline int plat_dma_mapping_error(struct device *dev,
-					 dma_addr_t dma_addr)
-{
-	return 0;
-}
-
 static inline int plat_device_is_coherent(struct device *dev)
 {
 	return 0;
diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson/dma-coherence.h
index e143305..aeb2c05 100644
--- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
+++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
@@ -53,16 +53,6 @@
 	return 1;
 }
 
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
-}
-
-static inline int plat_dma_mapping_error(struct device *dev,
-					 dma_addr_t dma_addr)
-{
-	return 0;
-}
-
 static inline int plat_device_is_coherent(struct device *dev)
 {
 	return 0;
diff --git a/arch/mips/include/asm/mach-powertv/asic.h b/arch/mips/include/asm/mach-powertv/asic.h
deleted file mode 100644
index b341108..0000000
--- a/arch/mips/include/asm/mach-powertv/asic.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2009  Cisco Systems, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have 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 _ASM_MACH_POWERTV_ASIC_H
-#define _ASM_MACH_POWERTV_ASIC_H
-
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <asm/mach-powertv/asic_regs.h>
-
-#define DVR_CAPABLE	(1<<0)
-#define PCIE_CAPABLE	(1<<1)
-#define FFS_CAPABLE	(1<<2)
-#define DISPLAY_CAPABLE (1<<3)
-
-/* Platform Family types
- * For compitability, the new value must be added in the end */
-enum family_type {
-	FAMILY_8500,
-	FAMILY_8500RNG,
-	FAMILY_4500,
-	FAMILY_1500,
-	FAMILY_8600,
-	FAMILY_4600,
-	FAMILY_4600VZA,
-	FAMILY_8600VZB,
-	FAMILY_1500VZE,
-	FAMILY_1500VZF,
-	FAMILY_8700,
-	FAMILIES
-};
-
-/* Register maps for each ASIC */
-extern const struct register_map calliope_register_map;
-extern const struct register_map cronus_register_map;
-extern const struct register_map gaia_register_map;
-extern const struct register_map zeus_register_map;
-
-extern struct resource dvr_cronus_resources[];
-extern struct resource dvr_gaia_resources[];
-extern struct resource dvr_zeus_resources[];
-extern struct resource non_dvr_calliope_resources[];
-extern struct resource non_dvr_cronus_resources[];
-extern struct resource non_dvr_cronuslite_resources[];
-extern struct resource non_dvr_gaia_resources[];
-extern struct resource non_dvr_vz_calliope_resources[];
-extern struct resource non_dvr_vze_calliope_resources[];
-extern struct resource non_dvr_vzf_calliope_resources[];
-extern struct resource non_dvr_zeus_resources[];
-
-extern void powertv_platform_init(void);
-extern void platform_alloc_bootmem(void);
-extern enum asic_type platform_get_asic(void);
-extern enum family_type platform_get_family(void);
-extern int platform_supports_dvr(void);
-extern int platform_supports_ffs(void);
-extern int platform_supports_pcie(void);
-extern int platform_supports_display(void);
-extern void configure_platform(void);
-
-/* Platform Resources */
-#define ASIC_RESOURCE_GET_EXISTS 1
-extern struct resource *asic_resource_get(const char *name);
-extern void platform_release_memory(void *baddr, int size);
-
-/* USB configuration */
-struct usb_hcd;			/* Forward reference */
-extern void platform_configure_usb_ehci(void);
-extern void platform_unconfigure_usb_ehci(void);
-extern void platform_configure_usb_ohci(void);
-extern void platform_unconfigure_usb_ohci(void);
-
-/* Resource for ASIC registers */
-extern struct resource asic_resource;
-extern int platform_usb_devices_init(struct platform_device **echi_dev,
-	struct platform_device **ohci_dev);
-
-/* Reboot Cause */
-extern void set_reboot_cause(char code, unsigned int data, unsigned int data2);
-extern void set_locked_reboot_cause(char code, unsigned int data,
-	unsigned int data2);
-
-enum sys_reboot_type {
-	sys_unknown_reboot = 0x00,	/* Unknown reboot cause */
-	sys_davic_change = 0x01,	/* Reboot due to change in DAVIC
-					 * mode */
-	sys_user_reboot = 0x02,		/* Reboot initiated by user */
-	sys_system_reboot = 0x03,	/* Reboot initiated by OS */
-	sys_trap_reboot = 0x04,		/* Reboot due to a CPU trap */
-	sys_silent_reboot = 0x05,	/* Silent reboot */
-	sys_boot_ldr_reboot = 0x06,	/* Bootloader reboot */
-	sys_power_up_reboot = 0x07,	/* Power on bootup.  Older
-					 * drivers may report as
-					 * userReboot. */
-	sys_code_change = 0x08,		/* Reboot to take code change.
-					 * Older drivers may report as
-					 * userReboot. */
-	sys_hardware_reset = 0x09,	/* HW watchdog or front-panel
-					 * reset button reset.	Older
-					 * drivers may report as
-					 * userReboot. */
-	sys_watchdogInterrupt = 0x0A	/* Pre-watchdog interrupt */
-};
-
-#endif /* _ASM_MACH_POWERTV_ASIC_H */
diff --git a/arch/mips/include/asm/mach-powertv/asic_reg_map.h b/arch/mips/include/asm/mach-powertv/asic_reg_map.h
deleted file mode 100644
index 20348e8..0000000
--- a/arch/mips/include/asm/mach-powertv/asic_reg_map.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- *				asic_reg_map.h
- *
- * A macro-enclosed list of the elements for the register_map structure for
- * use in defining and manipulating the structure.
- *
- * Copyright (C) 2009  Cisco Systems, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have 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
- */
-
-REGISTER_MAP_ELEMENT(eic_slow0_strt_add)
-REGISTER_MAP_ELEMENT(eic_cfg_bits)
-REGISTER_MAP_ELEMENT(eic_ready_status)
-REGISTER_MAP_ELEMENT(chipver3)
-REGISTER_MAP_ELEMENT(chipver2)
-REGISTER_MAP_ELEMENT(chipver1)
-REGISTER_MAP_ELEMENT(chipver0)
-REGISTER_MAP_ELEMENT(uart1_intstat)
-REGISTER_MAP_ELEMENT(uart1_inten)
-REGISTER_MAP_ELEMENT(uart1_config1)
-REGISTER_MAP_ELEMENT(uart1_config2)
-REGISTER_MAP_ELEMENT(uart1_divisorhi)
-REGISTER_MAP_ELEMENT(uart1_divisorlo)
-REGISTER_MAP_ELEMENT(uart1_data)
-REGISTER_MAP_ELEMENT(uart1_status)
-REGISTER_MAP_ELEMENT(int_stat_3)
-REGISTER_MAP_ELEMENT(int_stat_2)
-REGISTER_MAP_ELEMENT(int_stat_1)
-REGISTER_MAP_ELEMENT(int_stat_0)
-REGISTER_MAP_ELEMENT(int_config)
-REGISTER_MAP_ELEMENT(int_int_scan)
-REGISTER_MAP_ELEMENT(ien_int_3)
-REGISTER_MAP_ELEMENT(ien_int_2)
-REGISTER_MAP_ELEMENT(ien_int_1)
-REGISTER_MAP_ELEMENT(ien_int_0)
-REGISTER_MAP_ELEMENT(int_level_3_3)
-REGISTER_MAP_ELEMENT(int_level_3_2)
-REGISTER_MAP_ELEMENT(int_level_3_1)
-REGISTER_MAP_ELEMENT(int_level_3_0)
-REGISTER_MAP_ELEMENT(int_level_2_3)
-REGISTER_MAP_ELEMENT(int_level_2_2)
-REGISTER_MAP_ELEMENT(int_level_2_1)
-REGISTER_MAP_ELEMENT(int_level_2_0)
-REGISTER_MAP_ELEMENT(int_level_1_3)
-REGISTER_MAP_ELEMENT(int_level_1_2)
-REGISTER_MAP_ELEMENT(int_level_1_1)
-REGISTER_MAP_ELEMENT(int_level_1_0)
-REGISTER_MAP_ELEMENT(int_level_0_3)
-REGISTER_MAP_ELEMENT(int_level_0_2)
-REGISTER_MAP_ELEMENT(int_level_0_1)
-REGISTER_MAP_ELEMENT(int_level_0_0)
-REGISTER_MAP_ELEMENT(int_docsis_en)
-REGISTER_MAP_ELEMENT(mips_pll_setup)
-REGISTER_MAP_ELEMENT(fs432x4b4_usb_ctl)
-REGISTER_MAP_ELEMENT(test_bus)
-REGISTER_MAP_ELEMENT(crt_spare)
-REGISTER_MAP_ELEMENT(usb2_ohci_int_mask)
-REGISTER_MAP_ELEMENT(usb2_strap)
-REGISTER_MAP_ELEMENT(ehci_hcapbase)
-REGISTER_MAP_ELEMENT(ohci_hc_revision)
-REGISTER_MAP_ELEMENT(bcm1_bs_lmi_steer)
-REGISTER_MAP_ELEMENT(usb2_control)
-REGISTER_MAP_ELEMENT(usb2_stbus_obc)
-REGISTER_MAP_ELEMENT(usb2_stbus_mess_size)
-REGISTER_MAP_ELEMENT(usb2_stbus_chunk_size)
-REGISTER_MAP_ELEMENT(pcie_regs)
-REGISTER_MAP_ELEMENT(tim_ch)
-REGISTER_MAP_ELEMENT(tim_cl)
-REGISTER_MAP_ELEMENT(gpio_dout)
-REGISTER_MAP_ELEMENT(gpio_din)
-REGISTER_MAP_ELEMENT(gpio_dir)
-REGISTER_MAP_ELEMENT(watchdog)
-REGISTER_MAP_ELEMENT(front_panel)
-REGISTER_MAP_ELEMENT(misc_clk_ctl1)
-REGISTER_MAP_ELEMENT(misc_clk_ctl2)
-REGISTER_MAP_ELEMENT(crt_ext_ctl)
-REGISTER_MAP_ELEMENT(register_maps)
diff --git a/arch/mips/include/asm/mach-powertv/asic_regs.h b/arch/mips/include/asm/mach-powertv/asic_regs.h
deleted file mode 100644
index 06712ab..0000000
--- a/arch/mips/include/asm/mach-powertv/asic_regs.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2009  Cisco Systems, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have 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 __ASM_MACH_POWERTV_ASIC_H_
-#define __ASM_MACH_POWERTV_ASIC_H_
-#include <linux/io.h>
-
-/* ASIC types */
-enum asic_type {
-	ASIC_UNKNOWN,
-	ASIC_ZEUS,
-	ASIC_CALLIOPE,
-	ASIC_CRONUS,
-	ASIC_CRONUSLITE,
-	ASIC_GAIA,
-	ASICS			/* Number of supported ASICs */
-};
-
-/* hardcoded values read from Chip Version registers */
-#define CRONUS_10	0x0B4C1C20
-#define CRONUS_11	0x0B4C1C21
-#define CRONUSLITE_10	0x0B4C1C40
-
-#define NAND_FLASH_BASE		0x03000000
-#define CALLIOPE_IO_BASE	0x08000000
-#define GAIA_IO_BASE		0x09000000
-#define CRONUS_IO_BASE		0x09000000
-#define ZEUS_IO_BASE		0x09000000
-
-#define ASIC_IO_SIZE		0x01000000
-
-/* Definitions for backward compatibility */
-#define UART1_INTSTAT	uart1_intstat
-#define UART1_INTEN	uart1_inten
-#define UART1_CONFIG1	uart1_config1
-#define UART1_CONFIG2	uart1_config2
-#define UART1_DIVISORHI uart1_divisorhi
-#define UART1_DIVISORLO uart1_divisorlo
-#define UART1_DATA	uart1_data
-#define UART1_STATUS	uart1_status
-
-/* ASIC register enumeration */
-union register_map_entry {
-	unsigned long phys;
-	u32 *virt;
-};
-
-#define REGISTER_MAP_ELEMENT(x) union register_map_entry x;
-struct register_map {
-#include <asm/mach-powertv/asic_reg_map.h>
-};
-#undef REGISTER_MAP_ELEMENT
-
-/**
- * register_map_offset_phys - add an offset to the physical address
- * @map:	Pointer to the &struct register_map
- * @offset:	Value to add
- *
- * Only adds the base to non-zero physical addresses
- */
-static inline void register_map_offset_phys(struct register_map *map,
-	unsigned long offset)
-{
-#define REGISTER_MAP_ELEMENT(x)		do {				\
-		if (map->x.phys != 0)					\
-			map->x.phys += offset;				\
-	} while (false);
-
-#include <asm/mach-powertv/asic_reg_map.h>
-#undef REGISTER_MAP_ELEMENT
-}
-
-/**
- * register_map_virtualize - Convert &register_map to virtual addresses
- * @map:	Pointer to &register_map to virtualize
- */
-static inline void register_map_virtualize(struct register_map *map)
-{
-#define REGISTER_MAP_ELEMENT(x)		do {				\
-		map->x.virt = (!map->x.phys) ? NULL :			\
-			UNCAC_ADDR(phys_to_virt(map->x.phys));		\
-	} while (false);
-
-#include <asm/mach-powertv/asic_reg_map.h>
-#undef REGISTER_MAP_ELEMENT
-}
-
-extern struct register_map _asic_register_map;
-extern unsigned long asic_phy_base;
-
-/*
- * Macros to interface to registers through their ioremapped address
- * asic_reg_phys_addr	Returns the physical address of the given register
- * asic_reg_addr	Returns the iomapped virtual address of the given
- *			register.
- */
-#define asic_reg_addr(x)	(_asic_register_map.x.virt)
-#define asic_reg_phys_addr(x)	(virt_to_phys((void *) CAC_ADDR(	\
-					(unsigned long) asic_reg_addr(x))))
-
-/*
- * The asic_reg macro is gone. It should be replaced by either asic_read or
- * asic_write, as appropriate.
- */
-
-#define asic_read(x)		readl(asic_reg_addr(x))
-#define asic_write(v, x)	writel(v, asic_reg_addr(x))
-
-extern void asic_irq_init(void);
-#endif
diff --git a/arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h b/arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h
deleted file mode 100644
index 58c76ec..0000000
--- a/arch/mips/include/asm/mach-powertv/cpu-feature-overrides.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2010  Cisco Systems, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have 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 _ASM_MACH_POWERTV_CPU_FEATURE_OVERRIDES_H_
-#define _ASM_MACH_POWERTV_CPU_FEATURE_OVERRIDES_H_
-#define cpu_has_tlb			1
-#define cpu_has_4kex			1
-#define cpu_has_3k_cache		0
-#define cpu_has_4k_cache		1
-#define cpu_has_tx39_cache		0
-#define cpu_has_fpu			0
-#define cpu_has_counter			1
-#define cpu_has_watch			1
-#define cpu_has_divec			1
-#define cpu_has_vce			0
-#define cpu_has_cache_cdex_p		0
-#define cpu_has_cache_cdex_s		0
-#define cpu_has_mcheck			1
-#define cpu_has_ejtag			1
-#define cpu_has_llsc			1
-#define cpu_has_mips16			0
-#define cpu_has_mdmx			0
-#define cpu_has_mips3d			0
-#define cpu_has_smartmips		0
-#define cpu_has_vtag_icache		0
-#define cpu_has_dc_aliases		0
-#define cpu_has_ic_fills_f_dc		0
-#define cpu_has_mips32r1		0
-#define cpu_has_mips32r2		1
-#define cpu_has_mips64r1		0
-#define cpu_has_mips64r2		0
-#define cpu_has_dsp			0
-#define cpu_has_dsp2			0
-#define cpu_has_mipsmt			0
-#define cpu_has_userlocal		0
-#define cpu_has_nofpuex			0
-#define cpu_has_64bits			0
-#define cpu_has_64bit_zero_reg		0
-#define cpu_has_vint			1
-#define cpu_has_veic			1
-#define cpu_has_inclusive_pcaches	0
-
-#define cpu_dcache_line_size()		32
-#define cpu_icache_line_size()		32
-#endif
diff --git a/arch/mips/include/asm/mach-powertv/dma-coherence.h b/arch/mips/include/asm/mach-powertv/dma-coherence.h
deleted file mode 100644
index f831672..0000000
--- a/arch/mips/include/asm/mach-powertv/dma-coherence.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Version from mach-generic modified to support PowerTV port
- * Portions Copyright (C) 2009	Cisco Systems, Inc.
- * Copyright (C) 2006  Ralf Baechle <ralf@linux-mips.org>
- *
- */
-
-#ifndef __ASM_MACH_POWERTV_DMA_COHERENCE_H
-#define __ASM_MACH_POWERTV_DMA_COHERENCE_H
-
-#include <linux/sched.h>
-#include <linux/device.h>
-#include <asm/mach-powertv/asic.h>
-
-static inline bool is_kseg2(void *addr)
-{
-	return (unsigned long)addr >= KSEG2;
-}
-
-static inline unsigned long virt_to_phys_from_pte(void *addr)
-{
-	pgd_t *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
-	pte_t *ptep, pte;
-
-	unsigned long virt_addr = (unsigned long)addr;
-	unsigned long phys_addr = 0UL;
-
-	/* get the page global directory. */
-	pgd = pgd_offset_k(virt_addr);
-
-	if (!pgd_none(*pgd)) {
-		/* get the page upper directory */
-		pud = pud_offset(pgd, virt_addr);
-		if (!pud_none(*pud)) {
-			/* get the page middle directory */
-			pmd = pmd_offset(pud, virt_addr);
-			if (!pmd_none(*pmd)) {
-				/* get a pointer to the page table entry */
-				ptep = pte_offset(pmd, virt_addr);
-				pte = *ptep;
-				/* check for a valid page */
-				if (pte_present(pte)) {
-					/* get the physical address the page is
-					 * referring to */
-					phys_addr = (unsigned long)
-						page_to_phys(pte_page(pte));
-					/* add the offset within the page */
-					phys_addr |= (virt_addr & ~PAGE_MASK);
-				}
-			}
-		}
-	}
-
-	return phys_addr;
-}
-
-static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
-	size_t size)
-{
-	if (is_kseg2(addr))
-		return phys_to_dma(virt_to_phys_from_pte(addr));
-	else
-		return phys_to_dma(virt_to_phys(addr));
-}
-
-static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
-	struct page *page)
-{
-	return phys_to_dma(page_to_phys(page));
-}
-
-static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
-	dma_addr_t dma_addr)
-{
-	return dma_to_phys(dma_addr);
-}
-
-static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
-	size_t size, enum dma_data_direction direction)
-{
-}
-
-static inline int plat_dma_supported(struct device *dev, u64 mask)
-{
-	/*
-	 * we fall back to GFP_DMA when the mask isn't all 1s,
-	 * so we can't guarantee allocations that must be
-	 * within a tighter range than GFP_DMA..
-	 */
-	if (mask < DMA_BIT_MASK(24))
-		return 0;
-
-	return 1;
-}
-
-static inline void plat_extra_sync_for_device(struct device *dev)
-{
-}
-
-static inline int plat_dma_mapping_error(struct device *dev,
-					 dma_addr_t dma_addr)
-{
-	return 0;
-}
-
-static inline int plat_device_is_coherent(struct device *dev)
-{
-	return 0;
-}
-
-#endif /* __ASM_MACH_POWERTV_DMA_COHERENCE_H */
diff --git a/arch/mips/include/asm/mach-powertv/interrupts.h b/arch/mips/include/asm/mach-powertv/interrupts.h
deleted file mode 100644
index 6c463be..0000000
--- a/arch/mips/include/asm/mach-powertv/interrupts.h
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright (C) 2009  Cisco Systems, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have 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 _ASM_MACH_POWERTV_INTERRUPTS_H_
-#define _ASM_MACH_POWERTV_INTERRUPTS_H_
-
-/*
- * Defines for all of the interrupt lines
- */
-
-/* Definitions for backward compatibility */
-#define kIrq_Uart1		irq_uart1
-
-#define ibase 0
-
-/*------------- Register: int_stat_3 */
-/* 126 unused (bit 31) */
-#define irq_asc2video		(ibase+126)	/* ASC 2 Video Interrupt */
-#define irq_asc1video		(ibase+125)	/* ASC 1 Video Interrupt */
-#define irq_comms_block_wd	(ibase+124)	/* ASC 1 Video Interrupt */
-#define irq_fdma_mailbox	(ibase+123)	/* FDMA Mailbox Output */
-#define irq_fdma_gp		(ibase+122)	/* FDMA GP Output */
-#define irq_mips_pic		(ibase+121)	/* MIPS Performance Counter
-						 * Interrupt */
-#define irq_mips_timer		(ibase+120)	/* MIPS Timer Interrupt */
-#define irq_memory_protect	(ibase+119)	/* Memory Protection Interrupt
-						 * -- Ored by glue logic inside
-						 *  SPARC ILC (see
-						 *  INT_MEM_PROT_STAT, below,
-						 *  for individual interrupts)
-						 */
-/* 118 unused (bit 22) */
-#define irq_sbag		(ibase+117)	/* SBAG Interrupt -- Ored by
-						 * glue logic inside SPARC ILC
-						 * (see INT_SBAG_STAT, below,
-						 * for individual interrupts) */
-#define irq_qam_b_fec		(ibase+116)	/* QAM	B FEC Interrupt */
-#define irq_qam_a_fec		(ibase+115)	/* QAM A FEC Interrupt */
-/* 114 unused	(bit 18) */
-#define irq_mailbox		(ibase+113)	/* Mailbox Debug Interrupt  --
-						 * Ored by glue logic inside
-						 * SPARC ILC (see
-						 * INT_MAILBOX_STAT, below, for
-						 * individual interrupts) */
-#define irq_fuse_stat1		(ibase+112)	/* Fuse Status 1 */
-#define irq_fuse_stat2		(ibase+111)	/* Fuse Status 2 */
-#define irq_fuse_stat3		(ibase+110)	/* Blitter Interrupt / Fuse
-						 * Status 3 */
-#define irq_blitter		(ibase+110)	/* Blitter Interrupt / Fuse
-						 * Status 3 */
-#define irq_avc1_pp0		(ibase+109)	/* AVC Decoder #1 PP0
-						 * Interrupt */
-#define irq_avc1_pp1		(ibase+108)	/* AVC Decoder #1 PP1
-						 * Interrupt */
-#define irq_avc1_mbe		(ibase+107)	/* AVC Decoder #1 MBE
-						 * Interrupt */
-#define irq_avc2_pp0		(ibase+106)	/* AVC Decoder #2 PP0
-						 * Interrupt */
-#define irq_avc2_pp1		(ibase+105)	/* AVC Decoder #2 PP1
-						 * Interrupt */
-#define irq_avc2_mbe		(ibase+104)	/* AVC Decoder #2 MBE
-						 * Interrupt */
-#define irq_zbug_spi		(ibase+103)	/* Zbug SPI Slave Interrupt */
-#define irq_qam_mod2		(ibase+102)	/* QAM Modulator 2 DMA
-						 * Interrupt */
-#define irq_ir_rx		(ibase+101)	/* IR RX 2 Interrupt */
-#define irq_aud_dsp2		(ibase+100)	/* Audio DSP #2 Interrupt */
-#define irq_aud_dsp1		(ibase+99)	/* Audio DSP #1 Interrupt */
-#define irq_docsis		(ibase+98)	/* DOCSIS Debug Interrupt */
-#define irq_sd_dvp1		(ibase+97)	/* SD DVP #1 Interrupt */
-#define irq_sd_dvp2		(ibase+96)	/* SD DVP #2 Interrupt */
-/*------------- Register: int_stat_2 */
-#define irq_hd_dvp		(ibase+95)	/* HD DVP Interrupt */
-#define kIrq_Prewatchdog	(ibase+94)	/* watchdog Pre-Interrupt */
-#define irq_timer2		(ibase+93)	/* Programmable Timer
-						 * Interrupt 2 */
-#define irq_1394		(ibase+92)	/* 1394 Firewire Interrupt */
-#define irq_usbohci		(ibase+91)	/* USB 2.0 OHCI Interrupt */
-#define irq_usbehci		(ibase+90)	/* USB 2.0 EHCI Interrupt */
-#define irq_pciexp		(ibase+89)	/* PCI Express 0 Interrupt */
-#define irq_pciexp0		(ibase+89)	/* PCI Express 0 Interrupt */
-#define irq_afe1		(ibase+88)	/* AFE 1 Interrupt */
-#define irq_sata		(ibase+87)	/* SATA 1 Interrupt */
-#define irq_sata1		(ibase+87)	/* SATA 1 Interrupt */
-#define irq_dtcp		(ibase+86)	/* DTCP Interrupt */
-#define irq_pciexp1		(ibase+85)	/* PCI Express 1 Interrupt */
-/* 84 unused	(bit 20) */
-/* 83 unused	(bit 19) */
-/* 82 unused	(bit 18) */
-#define irq_sata2		(ibase+81)	/* SATA2 Interrupt */
-#define irq_uart2		(ibase+80)	/* UART2 Interrupt */
-#define irq_legacy_usb		(ibase+79)	/* Legacy USB Host ISR (1.1
-						 * Host module) */
-#define irq_pod			(ibase+78)	/* POD Interrupt */
-#define irq_slave_usb		(ibase+77)	/* Slave USB */
-#define irq_denc1		(ibase+76)	/* DENC #1 VTG Interrupt */
-#define irq_vbi_vtg		(ibase+75)	/* VBI VTG Interrupt */
-#define irq_afe2		(ibase+74)	/* AFE 2 Interrupt */
-#define irq_denc2		(ibase+73)	/* DENC #2 VTG Interrupt */
-#define irq_asc2		(ibase+72)	/* ASC #2 Interrupt */
-#define irq_asc1		(ibase+71)	/* ASC #1 Interrupt */
-#define irq_mod_dma		(ibase+70)	/* Modulator DMA Interrupt */
-#define irq_byte_eng1		(ibase+69)	/* Byte Engine Interrupt [1] */
-#define irq_byte_eng0		(ibase+68)	/* Byte Engine Interrupt [0] */
-/* 67 unused	(bit 03) */
-/* 66 unused	(bit 02) */
-/* 65 unused	(bit 01) */
-/* 64 unused	(bit 00) */
-/*------------- Register: int_stat_1 */
-/* 63 unused	(bit 31) */
-/* 62 unused	(bit 30) */
-/* 61 unused	(bit 29) */
-/* 60 unused	(bit 28) */
-/* 59 unused	(bit 27) */
-/* 58 unused	(bit 26) */
-/* 57 unused	(bit 25) */
-/* 56 unused	(bit 24) */
-#define irq_buf_dma_mem2mem	(ibase+55)	/* BufDMA Memory to Memory
-						 * Interrupt */
-#define irq_buf_dma_usbtransmit (ibase+54)	/* BufDMA USB Transmit
-						 * Interrupt */
-#define irq_buf_dma_qpskpodtransmit (ibase+53)	/* BufDMA QPSK/POD Tramsit
-						 * Interrupt */
-#define irq_buf_dma_transmit_error (ibase+52)	/* BufDMA Transmit Error
-						 * Interrupt */
-#define irq_buf_dma_usbrecv	(ibase+51)	/* BufDMA USB Receive
-						 * Interrupt */
-#define irq_buf_dma_qpskpodrecv (ibase+50)	/* BufDMA QPSK/POD Receive
-						 * Interrupt */
-#define irq_buf_dma_recv_error	(ibase+49)	/* BufDMA Receive Error
-						 * Interrupt */
-#define irq_qamdma_transmit_play (ibase+48)	/* QAMDMA Transmit/Play
-						 * Interrupt */
-#define irq_qamdma_transmit_error (ibase+47)	/* QAMDMA Transmit Error
-						 * Interrupt */
-#define irq_qamdma_recv2high	(ibase+46)	/* QAMDMA Receive 2 High
-						 * (Chans 63-32) */
-#define irq_qamdma_recv2low	(ibase+45)	/* QAMDMA Receive 2 Low
-						 * (Chans 31-0) */
-#define irq_qamdma_recv1high	(ibase+44)	/* QAMDMA Receive 1 High
-						 * (Chans 63-32) */
-#define irq_qamdma_recv1low	(ibase+43)	/* QAMDMA Receive 1 Low
-						 * (Chans 31-0) */
-#define irq_qamdma_recv_error	(ibase+42)	/* QAMDMA Receive Error
-						 * Interrupt */
-#define irq_mpegsplice		(ibase+41)	/* MPEG Splice Interrupt */
-#define irq_deinterlace_rdy	(ibase+40)	/* Deinterlacer Frame Ready
-						 * Interrupt */
-#define irq_ext_in0		(ibase+39)	/* External Interrupt irq_in0 */
-#define irq_gpio3		(ibase+38)	/* GP I/O IRQ 3 - From GP I/O
-						 * Module */
-#define irq_gpio2		(ibase+37)	/* GP I/O IRQ 2 - From GP I/O
-						 * Module (ABE_intN) */
-#define irq_pcrcmplt1		(ibase+36)	/* PCR Capture Complete	 or
-						 * Discontinuity 1 */
-#define irq_pcrcmplt2		(ibase+35)	/* PCR Capture Complete or
-						 * Discontinuity 2 */
-#define irq_parse_peierr	(ibase+34)	/* PID Parser Error Detect
-						 * (PEI) */
-#define irq_parse_cont_err	(ibase+33)	/* PID Parser continuity error
-						 * detect */
-#define irq_ds1framer		(ibase+32)	/* DS1 Framer Interrupt */
-/*------------- Register: int_stat_0 */
-#define irq_gpio1		(ibase+31)	/* GP I/O IRQ 1 - From GP I/O
-						 * Module */
-#define irq_gpio0		(ibase+30)	/* GP I/O IRQ 0 - From GP I/O
-						 * Module */
-#define irq_qpsk_out_aloha	(ibase+29)	/* QPSK Output Slotted Aloha
-						 * (chan 3) Transmission
-						 * Completed OK */
-#define irq_qpsk_out_tdma	(ibase+28)	/* QPSK Output TDMA (chan 2)
-						 * Transmission Completed OK */
-#define irq_qpsk_out_reserve	(ibase+27)	/* QPSK Output Reservation
-						 * (chan 1) Transmission
-						 * Completed OK */
-#define irq_qpsk_out_aloha_err	(ibase+26)	/* QPSK Output Slotted Aloha
-						 * (chan 3)Transmission
-						 * completed with Errors. */
-#define irq_qpsk_out_tdma_err	(ibase+25)	/* QPSK Output TDMA (chan 2)
-						 * Transmission completed with
-						 * Errors. */
-#define irq_qpsk_out_rsrv_err	(ibase+24)	/* QPSK Output Reservation
-						 * (chan 1) Transmission
-						 * completed with Errors */
-#define irq_aloha_fail		(ibase+23)	/* Unsuccessful Resend of Aloha
-						 * for N times. Aloha retry
-						 * timeout for channel 3. */
-#define irq_timer1		(ibase+22)	/* Programmable Timer
-						 * Interrupt */
-#define irq_keyboard		(ibase+21)	/* Keyboard Module Interrupt */
-#define irq_i2c			(ibase+20)	/* I2C Module Interrupt */
-#define irq_spi			(ibase+19)	/* SPI Module Interrupt */
-#define irq_irblaster		(ibase+18)	/* IR Blaster Interrupt */
-#define irq_splice_detect	(ibase+17)	/* PID Key Change Interrupt or
-						 * Splice Detect Interrupt */
-#define irq_se_micro		(ibase+16)	/* Secure Micro I/F Module
-						 * Interrupt */
-#define irq_uart1		(ibase+15)	/* UART Interrupt */
-#define irq_irrecv		(ibase+14)	/* IR Receiver Interrupt */
-#define irq_host_int1		(ibase+13)	/* Host-to-Host Interrupt 1 */
-#define irq_host_int0		(ibase+12)	/* Host-to-Host Interrupt 0 */
-#define irq_qpsk_hecerr		(ibase+11)	/* QPSK HEC Error Interrupt */
-#define irq_qpsk_crcerr		(ibase+10)	/* QPSK AAL-5 CRC Error
-						 * Interrupt */
-/* 9 unused	(bit 09) */
-/* 8 unused	(bit 08) */
-#define irq_psicrcerr		(ibase+7)	/* QAM PSI CRC Error
-						 * Interrupt */
-#define irq_psilength_err	(ibase+6)	/* QAM PSI Length Error
-						 * Interrupt */
-#define irq_esfforward		(ibase+5)	/* ESF Interrupt Mark From
-						 * Forward Path Reference -
-						 * every 3ms when forward Mbits
-						 * and forward slot control
-						 * bytes are updated. */
-#define irq_esfreverse		(ibase+4)	/* ESF Interrupt Mark from
-						 * Reverse Path Reference -
-						 * delayed from forward mark by
-						 * the ranging delay plus a
-						 * fixed amount. When reverse
-						 * Mbits and reverse slot
-						 * control bytes are updated.
-						 * Occurs every 3ms for 3.0M and
-						 * 1.554 M upstream rates and
-						 * every 6 ms for 256K upstream
-						 * rate. */
-#define irq_aloha_timeout	(ibase+3)	/* Slotted-Aloha timeout on
-						 * Channel 1. */
-#define irq_reservation		(ibase+2)	/* Partial (or Incremental)
-						 * Reservation Message Completed
-						 * or Slotted aloha verify for
-						 * channel 1. */
-#define irq_aloha3		(ibase+1)	/* Slotted-Aloha Message Verify
-						 * Interrupt or Reservation
-						 * increment completed for
-						 * channel 3. */
-#define irq_mpeg_d		(ibase+0)	/* MPEG Decoder Interrupt */
-#endif	/* _ASM_MACH_POWERTV_INTERRUPTS_H_ */
diff --git a/arch/mips/include/asm/mach-powertv/ioremap.h b/arch/mips/include/asm/mach-powertv/ioremap.h
deleted file mode 100644
index c86ef09..0000000
--- a/arch/mips/include/asm/mach-powertv/ioremap.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License
- *	as published by the Free Software Foundation; either version
- *	2 of the License, or (at your option) any later version.
- *
- * Portions Copyright (C)  Cisco Systems, Inc.
- */
-#ifndef __ASM_MACH_POWERTV_IOREMAP_H
-#define __ASM_MACH_POWERTV_IOREMAP_H
-
-#include <linux/types.h>
-#include <linux/log2.h>
-#include <linux/compiler.h>
-
-#include <asm/pgtable-bits.h>
-#include <asm/addrspace.h>
-
-/* We're going to mess with bits, so get sizes */
-#define IOR_BPC			8			/* Bits per char */
-#define IOR_PHYS_BITS		(IOR_BPC * sizeof(phys_addr_t))
-#define IOR_DMA_BITS		(IOR_BPC * sizeof(dma_addr_t))
-
-/*
- * Define the granularity of physical/DMA mapping in terms of the number
- * of bits that defines the offset within a grain. These will be the
- * least significant bits of the address. The rest of a physical or DMA
- * address will be used to index into an appropriate table to find the
- * offset to add to the address to yield the corresponding DMA or physical
- * address, respectively.
- */
-#define IOR_LSBITS		22			/* Bits in a grain */
-
-/*
- * Compute the number of most significant address bits after removing those
- * used for the offset within a grain and then compute the number of table
- * entries for the conversion.
- */
-#define IOR_PHYS_MSBITS		(IOR_PHYS_BITS - IOR_LSBITS)
-#define IOR_NUM_PHYS_TO_DMA	((phys_addr_t) 1 << IOR_PHYS_MSBITS)
-
-#define IOR_DMA_MSBITS		(IOR_DMA_BITS - IOR_LSBITS)
-#define IOR_NUM_DMA_TO_PHYS	((dma_addr_t) 1 << IOR_DMA_MSBITS)
-
-/*
- * Define data structures used as elements in the arrays for the conversion
- * between physical and DMA addresses. We do some slightly fancy math to
- * compute the width of the offset element of the conversion tables so
- * that we can have the smallest conversion tables. Next, round up the
- * sizes to the next higher power of two, i.e. the offset element will have
- * 8, 16, 32, 64, etc. bits. This eliminates the need to mask off any
- * bits.  Finally, we compute a shift value that puts the most significant
- * bits of the offset into the most significant bits of the offset element.
- * This makes it more efficient on processors without barrel shifters and
- * easier to see the values if the conversion table is dumped in binary.
- */
-#define _IOR_OFFSET_WIDTH(n)	(1 << order_base_2(n))
-#define IOR_OFFSET_WIDTH(n) \
-	(_IOR_OFFSET_WIDTH(n) < 8 ? 8 : _IOR_OFFSET_WIDTH(n))
-
-#define IOR_PHYS_OFFSET_BITS	IOR_OFFSET_WIDTH(IOR_PHYS_MSBITS)
-#define IOR_PHYS_SHIFT		(IOR_PHYS_BITS - IOR_PHYS_OFFSET_BITS)
-
-#define IOR_DMA_OFFSET_BITS	IOR_OFFSET_WIDTH(IOR_DMA_MSBITS)
-#define IOR_DMA_SHIFT		(IOR_DMA_BITS - IOR_DMA_OFFSET_BITS)
-
-struct ior_phys_to_dma {
-	dma_addr_t offset:IOR_DMA_OFFSET_BITS __packed
-		__aligned((IOR_DMA_OFFSET_BITS / IOR_BPC));
-};
-
-struct ior_dma_to_phys {
-	dma_addr_t offset:IOR_PHYS_OFFSET_BITS __packed
-		__aligned((IOR_PHYS_OFFSET_BITS / IOR_BPC));
-};
-
-extern struct ior_phys_to_dma _ior_phys_to_dma[IOR_NUM_PHYS_TO_DMA];
-extern struct ior_dma_to_phys _ior_dma_to_phys[IOR_NUM_DMA_TO_PHYS];
-
-static inline dma_addr_t _phys_to_dma_offset_raw(phys_addr_t phys)
-{
-	return (dma_addr_t)_ior_phys_to_dma[phys >> IOR_LSBITS].offset;
-}
-
-static inline dma_addr_t _dma_to_phys_offset_raw(dma_addr_t dma)
-{
-	return (dma_addr_t)_ior_dma_to_phys[dma >> IOR_LSBITS].offset;
-}
-
-/* These are not portable and should not be used in drivers. Drivers should
- * be using ioremap() and friends to map physical addresses to virtual
- * addresses and dma_map*() and friends to map virtual addresses into DMA
- * addresses and back.
- */
-static inline dma_addr_t phys_to_dma(phys_addr_t phys)
-{
-	return phys + (_phys_to_dma_offset_raw(phys) << IOR_PHYS_SHIFT);
-}
-
-static inline phys_addr_t dma_to_phys(dma_addr_t dma)
-{
-	return dma + (_dma_to_phys_offset_raw(dma) << IOR_DMA_SHIFT);
-}
-
-extern void ioremap_add_map(dma_addr_t phys, phys_addr_t alias,
-	dma_addr_t size);
-
-/*
- * Allow physical addresses to be fixed up to help peripherals located
- * outside the low 32-bit range -- generic pass-through version.
- */
-static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
-{
-	return phys_addr;
-}
-
-/*
- * Handle the special case of addresses the area aliased into the first
- * 512 MiB of the processor's physical address space. These turn into either
- * kseg0 or kseg1 addresses, depending on flags.
- */
-static inline void __iomem *plat_ioremap(phys_t start, unsigned long size,
-	unsigned long flags)
-{
-	phys_addr_t start_offset;
-	void __iomem *result = NULL;
-
-	/* Start by checking to see whether this is an aliased address */
-	start_offset = _dma_to_phys_offset_raw(start);
-
-	/*
-	 * If:
-	 * o	the memory is aliased into the first 512 MiB, and
-	 * o	the start and end are in the same RAM bank, and
-	 * o	we don't have a zero size or wrap around, and
-	 * o	we are supposed to create an uncached mapping,
-	 *	handle this is a kseg0 or kseg1 address
-	 */
-	if (start_offset != 0) {
-		phys_addr_t last;
-		dma_addr_t dma_to_phys_offset;
-
-		last = start + size - 1;
-		dma_to_phys_offset =
-			_dma_to_phys_offset_raw(last) << IOR_DMA_SHIFT;
-
-		if (dma_to_phys_offset == start_offset &&
-			size != 0 && start <= last) {
-			phys_t adjusted_start;
-			adjusted_start = start + start_offset;
-			if (flags == _CACHE_UNCACHED)
-				result = (void __iomem *) (unsigned long)
-					CKSEG1ADDR(adjusted_start);
-			else
-				result = (void __iomem *) (unsigned long)
-					CKSEG0ADDR(adjusted_start);
-		}
-	}
-
-	return result;
-}
-
-static inline int plat_iounmap(const volatile void __iomem *addr)
-{
-	return 0;
-}
-#endif /* __ASM_MACH_POWERTV_IOREMAP_H */
diff --git a/arch/mips/include/asm/mach-powertv/irq.h b/arch/mips/include/asm/mach-powertv/irq.h
deleted file mode 100644
index 4bd5d0c..0000000
--- a/arch/mips/include/asm/mach-powertv/irq.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2009  Cisco Systems, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have 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 _ASM_MACH_POWERTV_IRQ_H
-#define _ASM_MACH_POWERTV_IRQ_H
-#include <asm/mach-powertv/interrupts.h>
-
-#define MIPS_CPU_IRQ_BASE	ibase
-#define NR_IRQS			127
-#endif
diff --git a/arch/mips/include/asm/mach-powertv/powertv-clock.h b/arch/mips/include/asm/mach-powertv/powertv-clock.h
deleted file mode 100644
index 6f3e9a0..0000000
--- a/arch/mips/include/asm/mach-powertv/powertv-clock.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2009  Cisco Systems, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have 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
- */
-/*
- * Local definitions for the powertv PCI code
- */
-
-#ifndef _POWERTV_PCI_POWERTV_PCI_H_
-#define _POWERTV_PCI_POWERTV_PCI_H_
-extern int asic_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
-extern int asic_pcie_init(void);
-extern int asic_pcie_init(void);
-
-extern int log_level;
-#endif
diff --git a/arch/mips/include/asm/mach-powertv/war.h b/arch/mips/include/asm/mach-powertv/war.h
deleted file mode 100644
index c5651c8..0000000
--- a/arch/mips/include/asm/mach-powertv/war.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * This version for the PowerTV platform copied from the Malta version.
- *
- * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- */
-#ifndef __ASM_MACH_POWERTV_WAR_H
-#define __ASM_MACH_POWERTV_WAR_H
-
-#define R4600_V1_INDEX_ICACHEOP_WAR	0
-#define R4600_V1_HIT_CACHEOP_WAR	0
-#define R4600_V2_HIT_CACHEOP_WAR	0
-#define R5432_CP0_INTERRUPT_WAR		0
-#define BCM1250_M3_WAR			0
-#define SIBYTE_1956_WAR			0
-#define MIPS4K_ICACHE_REFILL_WAR	1
-#define MIPS_CACHE_SYNC_WAR		1
-#define TX49XX_ICACHE_INDEX_INV_WAR	0
-#define ICACHE_REFILLS_WORKAROUND_WAR	1
-#define R10000_LLSC_WAR			0
-#define MIPS34K_MISSED_ITLB_WAR		0
-
-#endif /* __ASM_MACH_POWERTV_WAR_H */
diff --git a/arch/mips/include/asm/mips-boards/piix4.h b/arch/mips/include/asm/mips-boards/piix4.h
index a02596c..e332279 100644
--- a/arch/mips/include/asm/mips-boards/piix4.h
+++ b/arch/mips/include/asm/mips-boards/piix4.h
@@ -1,6 +1,7 @@
 /*
  * Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 2013 Imagination Technologies Ltd.
  *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
@@ -20,61 +21,26 @@
 #ifndef __ASM_MIPS_BOARDS_PIIX4_H
 #define __ASM_MIPS_BOARDS_PIIX4_H
 
-/************************************************************************
- *  IO register offsets
- ************************************************************************/
-#define PIIX4_ICTLR1_ICW1	0x20
-#define PIIX4_ICTLR1_ICW2	0x21
-#define PIIX4_ICTLR1_ICW3	0x21
-#define PIIX4_ICTLR1_ICW4	0x21
-#define PIIX4_ICTLR2_ICW1	0xa0
-#define PIIX4_ICTLR2_ICW2	0xa1
-#define PIIX4_ICTLR2_ICW3	0xa1
-#define PIIX4_ICTLR2_ICW4	0xa1
-#define PIIX4_ICTLR1_OCW1	0x21
-#define PIIX4_ICTLR1_OCW2	0x20
-#define PIIX4_ICTLR1_OCW3	0x20
-#define PIIX4_ICTLR1_OCW4	0x20
-#define PIIX4_ICTLR2_OCW1	0xa1
-#define PIIX4_ICTLR2_OCW2	0xa0
-#define PIIX4_ICTLR2_OCW3	0xa0
-#define PIIX4_ICTLR2_OCW4	0xa0
+/* PIRQX Route Control */
+#define PIIX4_FUNC0_PIRQRC			0x60
+#define   PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_DISABLE	(1 << 7)
+#define   PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_MASK		0xf
+#define   PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_MAX		16
+/* Top Of Memory */
+#define PIIX4_FUNC0_TOM				0x69
+#define   PIIX4_FUNC0_TOM_TOP_OF_MEMORY_MASK		0xf0
+/* Deterministic Latency Control */
+#define PIIX4_FUNC0_DLC				0x82
+#define   PIIX4_FUNC0_DLC_USBPR_EN			(1 << 2)
+#define   PIIX4_FUNC0_DLC_PASSIVE_RELEASE_EN		(1 << 1)
+#define   PIIX4_FUNC0_DLC_DELAYED_TRANSACTION_EN	(1 << 0)
 
-
-/************************************************************************
- *  Register encodings.
- ************************************************************************/
-#define PIIX4_OCW2_NSEOI	(0x1 << 5)
-#define PIIX4_OCW2_SEOI		(0x3 << 5)
-#define PIIX4_OCW2_RNSEOI	(0x5 << 5)
-#define PIIX4_OCW2_RAEOIS	(0x4 << 5)
-#define PIIX4_OCW2_RAEOIC	(0x0 << 5)
-#define PIIX4_OCW2_RSEOI	(0x7 << 5)
-#define PIIX4_OCW2_SP		(0x6 << 5)
-#define PIIX4_OCW2_NOP		(0x2 << 5)
-
-#define PIIX4_OCW2_SEL		(0x0 << 3)
-
-#define PIIX4_OCW2_ILS_0	0
-#define PIIX4_OCW2_ILS_1	1
-#define PIIX4_OCW2_ILS_2	2
-#define PIIX4_OCW2_ILS_3	3
-#define PIIX4_OCW2_ILS_4	4
-#define PIIX4_OCW2_ILS_5	5
-#define PIIX4_OCW2_ILS_6	6
-#define PIIX4_OCW2_ILS_7	7
-#define PIIX4_OCW2_ILS_8	0
-#define PIIX4_OCW2_ILS_9	1
-#define PIIX4_OCW2_ILS_10	2
-#define PIIX4_OCW2_ILS_11	3
-#define PIIX4_OCW2_ILS_12	4
-#define PIIX4_OCW2_ILS_13	5
-#define PIIX4_OCW2_ILS_14	6
-#define PIIX4_OCW2_ILS_15	7
-
-#define PIIX4_OCW3_SEL		(0x1 << 3)
-
-#define PIIX4_OCW3_IRR		0x2
-#define PIIX4_OCW3_ISR		0x3
+/* IDE Timing */
+#define PIIX4_FUNC1_IDETIM_PRIMARY_LO		0x40
+#define PIIX4_FUNC1_IDETIM_PRIMARY_HI		0x41
+#define   PIIX4_FUNC1_IDETIM_PRIMARY_HI_IDE_DECODE_EN	(1 << 7)
+#define PIIX4_FUNC1_IDETIM_SECONDARY_LO		0x42
+#define PIIX4_FUNC1_IDETIM_SECONDARY_HI		0x43
+#define   PIIX4_FUNC1_IDETIM_SECONDARY_HI_IDE_DECODE_EN	(1 << 7)
 
 #endif /* __ASM_MIPS_BOARDS_PIIX4_H */
diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index 3b29079..e277bba 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -24,21 +24,21 @@
 #endif /* SMTC */
 #include <asm-generic/mm_hooks.h>
 
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
-
 #define TLBMISS_HANDLER_SETUP_PGD(pgd)					\
 do {									\
 	extern void tlbmiss_handler_setup_pgd(unsigned long);		\
 	tlbmiss_handler_setup_pgd((unsigned long)(pgd));		\
 } while (0)
 
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 #define TLBMISS_HANDLER_SETUP()						\
 	do {								\
 		TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir);		\
-		write_c0_xcontext((unsigned long) smp_processor_id() << 51); \
+		write_c0_xcontext((unsigned long) smp_processor_id() <<	\
+						SMP_CPUID_REGSHIFT);	\
 	} while (0)
 
-#else /* CONFIG_MIPS_PGD_C0_CONTEXT: using  pgd_current*/
+#else /* !CONFIG_MIPS_PGD_C0_CONTEXT: using  pgd_current*/
 
 /*
  * For the fast tlb miss handlers, we keep a per cpu array of pointers
@@ -47,21 +47,11 @@
  */
 extern unsigned long pgd_current[];
 
-#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
-	pgd_current[smp_processor_id()] = (unsigned long)(pgd)
-
-#ifdef CONFIG_32BIT
 #define TLBMISS_HANDLER_SETUP()						\
-	write_c0_context((unsigned long) smp_processor_id() << 25);	\
+	write_c0_context((unsigned long) smp_processor_id() <<		\
+						SMP_CPUID_REGSHIFT);	\
 	back_to_back_c0_hazard();					\
 	TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
-#endif
-#ifdef CONFIG_64BIT
-#define TLBMISS_HANDLER_SETUP()						\
-	write_c0_context((unsigned long) smp_processor_id() << 26);	\
-	back_to_back_c0_hazard();					\
-	TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
-#endif
 #endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/
 #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
 
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
index 17daffb2..470f209 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
@@ -69,6 +69,7 @@
 int xlp_get_dram_map(int n, uint64_t *dram_map);
 
 /* Device tree related */
+void xlp_early_init_devtree(void);
 void *xlp_dt_init(void *fdtp);
 
 static inline int cpu_is_xlpii(void)
diff --git a/arch/mips/include/asm/prom.h b/arch/mips/include/asm/prom.h
index 1e7e096..ccd2b75 100644
--- a/arch/mips/include/asm/prom.h
+++ b/arch/mips/include/asm/prom.h
@@ -17,22 +17,8 @@
 #include <linux/types.h>
 #include <asm/bootinfo.h>
 
-extern int early_init_dt_scan_memory_arch(unsigned long node,
-	const char *uname, int depth, void *data);
-
 extern void device_tree_init(void);
 
-static inline unsigned long pci_address_to_pio(phys_addr_t address)
-{
-	/*
-	 * The ioport address can be directly used by inX() / outX()
-	 */
-	BUG_ON(address > IO_SPACE_LIMIT);
-
-	return (unsigned long) address;
-}
-#define pci_address_to_pio pci_address_to_pio
-
 struct boot_param_header;
 
 extern void __dt_setup_arch(struct boot_param_header *bph);
diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index 5e6cd09..7bba9da 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -81,7 +81,6 @@
 
 #define instruction_pointer(regs) ((regs)->cp0_epc)
 #define profile_pc(regs) instruction_pointer(regs)
-#define user_stack_pointer(r) ((r)->regs[29])
 
 extern asmlinkage void syscall_trace_enter(struct pt_regs *regs);
 extern asmlinkage void syscall_trace_leave(struct pt_regs *regs);
@@ -100,4 +99,17 @@
 	(struct pt_regs *)((sp | (THREAD_SIZE - 1)) + 1 - 32) - 1;	\
 })
 
+/* Helpers for working with the user stack pointer */
+
+static inline unsigned long user_stack_pointer(struct pt_regs *regs)
+{
+	return regs->regs[29];
+}
+
+static inline void user_stack_pointer_set(struct pt_regs *regs,
+	unsigned long val)
+{
+	regs->regs[29] = val;
+}
+
 #endif /* _ASM_PTRACE_H */
diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h
index a0b2650..34d1a19 100644
--- a/arch/mips/include/asm/r4kcache.h
+++ b/arch/mips/include/asm/r4kcache.h
@@ -15,6 +15,7 @@
 #include <asm/asm.h>
 #include <asm/cacheops.h>
 #include <asm/cpu-features.h>
+#include <asm/cpu-type.h>
 #include <asm/mipsmtregs.h>
 
 /*
@@ -162,7 +163,15 @@
 static inline void flush_icache_line(unsigned long addr)
 {
 	__iflush_prologue
-	cache_op(Hit_Invalidate_I, addr);
+	switch (boot_cpu_type()) {
+	case CPU_LOONGSON2:
+		cache_op(Hit_Invalidate_I_Loongson23, addr);
+		break;
+
+	default:
+		cache_op(Hit_Invalidate_I, addr);
+		break;
+	}
 	__iflush_epilogue
 }
 
@@ -208,7 +217,15 @@
  */
 static inline void protected_flush_icache_line(unsigned long addr)
 {
-	protected_cache_op(Hit_Invalidate_I, addr);
+	switch (boot_cpu_type()) {
+	case CPU_LOONGSON2:
+		protected_cache_op(Hit_Invalidate_I_Loongson23, addr);
+		break;
+
+	default:
+		protected_cache_op(Hit_Invalidate_I, addr);
+		break;
+	}
 }
 
 /*
@@ -412,8 +429,8 @@
 __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128)
 
 /* build blast_xxx_range, protected_blast_xxx_range */
-#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \
-static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
+#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra)	\
+static inline void prot##extra##blast_##pfx##cache##_range(unsigned long start, \
 						    unsigned long end)	\
 {									\
 	unsigned long lsize = cpu_##desc##_line_size();			\
@@ -432,13 +449,15 @@
 	__##pfx##flush_epilogue						\
 }
 
-__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
-__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_)
-__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_)
-__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, )
-__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, )
+__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, )
+__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, )
+__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, )
+__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson23, \
+	protected_, loongson23_)
+__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , )
+__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , )
 /* blast_inv_dcache_range */
-__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, )
-__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, )
+__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , )
+__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , )
 
 #endif /* _ASM_R4KCACHE_H */
diff --git a/arch/mips/include/asm/setup.h b/arch/mips/include/asm/setup.h
index e26589e..d7bfdeb 100644
--- a/arch/mips/include/asm/setup.h
+++ b/arch/mips/include/asm/setup.h
@@ -5,6 +5,14 @@
 
 extern void setup_early_printk(void);
 
+#ifdef CONFIG_EARLY_PRINTK_8250
+extern void setup_8250_early_printk_port(unsigned long base,
+	unsigned int reg_shift, unsigned int timeout);
+#else
+static inline void setup_8250_early_printk_port(unsigned long base,
+	unsigned int reg_shift, unsigned int timeout) {}
+#endif
+
 extern void set_handler(unsigned long offset, void *addr, unsigned long len);
 extern void set_uncached_handler(unsigned long offset, void *addr, unsigned long len);
 
diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index 23fc95e..4857e2c 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -17,6 +17,7 @@
 #include <asm/asmmacro.h>
 #include <asm/mipsregs.h>
 #include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
 
 /*
  * For SMTC kernel, global IE should be left set, and interrupts
@@ -93,21 +94,8 @@
 		.endm
 
 #ifdef CONFIG_SMP
-#ifdef CONFIG_MIPS_MT_SMTC
-#define PTEBASE_SHIFT	19	/* TCBIND */
-#define CPU_ID_REG CP0_TCBIND
-#define CPU_ID_MFC0 mfc0
-#elif defined(CONFIG_MIPS_PGD_C0_CONTEXT)
-#define PTEBASE_SHIFT	48	/* XCONTEXT */
-#define CPU_ID_REG CP0_XCONTEXT
-#define CPU_ID_MFC0 MFC0
-#else
-#define PTEBASE_SHIFT	23	/* CONTEXT */
-#define CPU_ID_REG CP0_CONTEXT
-#define CPU_ID_MFC0 MFC0
-#endif
 		.macro	get_saved_sp	/* SMP variation */
-		CPU_ID_MFC0	k0, CPU_ID_REG
+		ASM_CPUID_MFC0	k0, ASM_SMP_CPUID_REG
 #if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
 		lui	k1, %hi(kernelsp)
 #else
@@ -117,17 +105,17 @@
 		daddiu	k1, %hi(kernelsp)
 		dsll	k1, 16
 #endif
-		LONG_SRL	k0, PTEBASE_SHIFT
+		LONG_SRL	k0, SMP_CPUID_PTRSHIFT
 		LONG_ADDU	k1, k0
 		LONG_L	k1, %lo(kernelsp)(k1)
 		.endm
 
 		.macro	set_saved_sp stackp temp temp2
-		CPU_ID_MFC0	\temp, CPU_ID_REG
-		LONG_SRL	\temp, PTEBASE_SHIFT
+		ASM_CPUID_MFC0	\temp, ASM_SMP_CPUID_REG
+		LONG_SRL	\temp, SMP_CPUID_PTRSHIFT
 		LONG_S	\stackp, kernelsp(\temp)
 		.endm
-#else
+#else /* !CONFIG_SMP */
 		.macro	get_saved_sp	/* Uniprocessor variation */
 #ifdef CONFIG_CPU_JUMP_WORKAROUNDS
 		/*
diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h
new file mode 100644
index 0000000..81c8913
--- /dev/null
+++ b/arch/mips/include/asm/syscall.h
@@ -0,0 +1,116 @@
+/*
+ * Access to user system call parameters and results
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * See asm-generic/syscall.h for descriptions of what we must do here.
+ *
+ * Copyright (C) 2012 Ralf Baechle <ralf@linux-mips.org>
+ */
+
+#ifndef __ASM_MIPS_SYSCALL_H
+#define __ASM_MIPS_SYSCALL_H
+
+#include <linux/audit.h>
+#include <linux/elf-em.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <asm/ptrace.h>
+
+static inline long syscall_get_nr(struct task_struct *task,
+				  struct pt_regs *regs)
+{
+	return regs->regs[2];
+}
+
+static inline unsigned long mips_get_syscall_arg(unsigned long *arg,
+	struct task_struct *task, struct pt_regs *regs, unsigned int n)
+{
+	unsigned long usp = regs->regs[29];
+
+	switch (n) {
+	case 0: case 1: case 2: case 3:
+		*arg = regs->regs[4 + n];
+
+		return 0;
+
+#ifdef CONFIG_32BIT
+	case 4: case 5: case 6: case 7:
+		return get_user(*arg, (int *)usp + 4 * n);
+#endif
+
+#ifdef CONFIG_64BIT
+	case 4: case 5: case 6: case 7:
+#ifdef CONFIG_MIPS32_O32
+		if (test_thread_flag(TIF_32BIT_REGS))
+			return get_user(*arg, (int *)usp + 4 * n);
+		else
+#endif
+			*arg = regs->regs[4 + n];
+
+		return 0;
+#endif
+
+	default:
+		BUG();
+	}
+}
+
+static inline long syscall_get_return_value(struct task_struct *task,
+					    struct pt_regs *regs)
+{
+	return regs->regs[2];
+}
+
+static inline void syscall_set_return_value(struct task_struct *task,
+					    struct pt_regs *regs,
+					    int error, long val)
+{
+	if (error) {
+		regs->regs[2] = -error;
+		regs->regs[7] = -1;
+	} else {
+		regs->regs[2] = val;
+		regs->regs[7] = 0;
+	}
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+					 struct pt_regs *regs,
+					 unsigned int i, unsigned int n,
+					 unsigned long *args)
+{
+	unsigned long arg;
+	int ret;
+
+	while (n--)
+		ret |= mips_get_syscall_arg(&arg, task, regs, i++);
+
+	/*
+	 * No way to communicate an error because this is a void function.
+	 */
+#if 0
+	return ret;
+#endif
+}
+
+extern const unsigned long sys_call_table[];
+extern const unsigned long sys32_call_table[];
+extern const unsigned long sysn32_call_table[];
+
+static inline int __syscall_get_arch(void)
+{
+	int arch = EM_MIPS;
+#ifdef CONFIG_64BIT
+	arch |=  __AUDIT_ARCH_64BIT;
+#endif
+#if defined(__LITTLE_ENDIAN)
+	arch |=  __AUDIT_ARCH_LE;
+#endif
+	return arch;
+}
+
+#endif	/* __ASM_MIPS_SYSCALL_H */
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index 61215a3..f9b24bf 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -116,6 +116,7 @@
 #define TIF_32BIT_ADDR		23	/* 32-bit address space (o32/n32) */
 #define TIF_FPUBOUND		24	/* thread bound to FPU-full CPU set */
 #define TIF_LOAD_WATCH		25	/* If set, load watch registers */
+#define TIF_SYSCALL_TRACEPOINT	26	/* syscall tracepoint instrumentation */
 #define TIF_SYSCALL_TRACE	31	/* syscall trace active */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -132,21 +133,54 @@
 #define _TIF_32BIT_ADDR		(1<<TIF_32BIT_ADDR)
 #define _TIF_FPUBOUND		(1<<TIF_FPUBOUND)
 #define _TIF_LOAD_WATCH		(1<<TIF_LOAD_WATCH)
+#define _TIF_SYSCALL_TRACEPOINT	(1<<TIF_SYSCALL_TRACEPOINT)
 
 #define _TIF_WORK_SYSCALL_ENTRY	(_TIF_NOHZ | _TIF_SYSCALL_TRACE |	\
-				 _TIF_SYSCALL_AUDIT)
+				 _TIF_SYSCALL_AUDIT | _TIF_SYSCALL_TRACEPOINT)
 
 /* work to do in syscall_trace_leave() */
 #define _TIF_WORK_SYSCALL_EXIT	(_TIF_NOHZ | _TIF_SYSCALL_TRACE |	\
-				 _TIF_SYSCALL_AUDIT)
+				 _TIF_SYSCALL_AUDIT | _TIF_SYSCALL_TRACEPOINT)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK		\
 	(_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME)
 /* work to do on any return to u-space */
 #define _TIF_ALLWORK_MASK	(_TIF_NOHZ | _TIF_WORK_MASK |		\
-				 _TIF_WORK_SYSCALL_EXIT)
+				 _TIF_WORK_SYSCALL_EXIT |		\
+				 _TIF_SYSCALL_TRACEPOINT)
+
+/*
+ * We stash processor id into a COP0 register to retrieve it fast
+ * at kernel exception entry.
+ */
+#if defined(CONFIG_MIPS_MT_SMTC)
+#define SMP_CPUID_REG		2, 2	/* TCBIND */
+#define ASM_SMP_CPUID_REG	$2, 2
+#define SMP_CPUID_PTRSHIFT	19
+#elif defined(CONFIG_MIPS_PGD_C0_CONTEXT)
+#define SMP_CPUID_REG		20, 0	/* XCONTEXT */
+#define ASM_SMP_CPUID_REG	$20
+#define SMP_CPUID_PTRSHIFT	48
+#else
+#define SMP_CPUID_REG		4, 0	/* CONTEXT */
+#define ASM_SMP_CPUID_REG	$4
+#define SMP_CPUID_PTRSHIFT	23
+#endif
+
+#ifdef CONFIG_64BIT
+#define SMP_CPUID_REGSHIFT	(SMP_CPUID_PTRSHIFT + 3)
+#else
+#define SMP_CPUID_REGSHIFT	(SMP_CPUID_PTRSHIFT + 2)
+#endif
+
+#ifdef CONFIG_MIPS_MT_SMTC
+#define ASM_CPUID_MFC0		mfc0
+#define UASM_i_CPUID_MFC0	uasm_i_mfc0
+#else
+#define ASM_CPUID_MFC0		MFC0
+#define UASM_i_CPUID_MFC0	UASM_i_MFC0
+#endif
 
 #endif /* __KERNEL__ */
-
 #endif /* _ASM_THREAD_INFO_H */
diff --git a/arch/mips/include/asm/time.h b/arch/mips/include/asm/time.h
index 2d7b9df..24f534a 100644
--- a/arch/mips/include/asm/time.h
+++ b/arch/mips/include/asm/time.h
@@ -75,7 +75,7 @@
 
 static inline int init_mips_clocksource(void)
 {
-#if defined(CONFIG_CSRC_R4K) && !defined(CONFIG_CSRC_GIC)
+#ifdef CONFIG_CSRC_R4K
 	return init_r4k_clocksource();
 #else
 	return 0;
diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h
index 63c9c88..4d3b928 100644
--- a/arch/mips/include/asm/unistd.h
+++ b/arch/mips/include/asm/unistd.h
@@ -14,6 +14,13 @@
 
 #include <uapi/asm/unistd.h>
 
+#ifdef CONFIG_MIPS32_N32
+#define NR_syscalls  (__NR_N32_Linux + __NR_N32_Linux_syscalls)
+#elif defined(CONFIG_64BIT)
+#define NR_syscalls  (__NR_64_Linux + __NR_64_Linux_syscalls)
+#else
+#define NR_syscalls  (__NR_O32_Linux + __NR_O32_Linux_syscalls)
+#endif
 
 #ifndef __ASSEMBLY__
 
diff --git a/arch/mips/include/uapi/asm/siginfo.h b/arch/mips/include/uapi/asm/siginfo.h
index 88e292b..e811744 100644
--- a/arch/mips/include/uapi/asm/siginfo.h
+++ b/arch/mips/include/uapi/asm/siginfo.h
@@ -33,6 +33,8 @@
 #error _MIPS_SZLONG neither 32 nor 64
 #endif
 
+#define __ARCH_SIGSYS
+
 #include <asm-generic/siginfo.h>
 
 typedef struct siginfo {
@@ -97,6 +99,13 @@
 			__ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */
 			int _fd;
 		} _sigpoll;
+
+		/* SIGSYS */
+		struct {
+			void __user *_call_addr; /* calling user insn */
+			int _syscall;	/* triggering system call number */
+			unsigned int _arch;	/* AUDIT_ARCH_* of syscall */
+		} _sigsys;
 	} _sifields;
 } siginfo_t;
 
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 423d871..1c1b717 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -26,7 +26,6 @@
 obj-$(CONFIG_CSRC_BCM1480)	+= csrc-bcm1480.o
 obj-$(CONFIG_CSRC_GIC)		+= csrc-gic.o
 obj-$(CONFIG_CSRC_IOASIC)	+= csrc-ioasic.o
-obj-$(CONFIG_CSRC_POWERTV)	+= csrc-powertv.o
 obj-$(CONFIG_CSRC_R4K)		+= csrc-r4k.o
 obj-$(CONFIG_CSRC_SB1250)	+= csrc-sb1250.o
 obj-$(CONFIG_SYNC_R4K)		+= sync-r4k.o
@@ -35,6 +34,7 @@
 obj-$(CONFIG_MODULES)		+= mips_ksyms.o module.o
 obj-$(CONFIG_MODULES_USE_ELF_RELA) += module-rela.o
 
+obj-$(CONFIG_FTRACE_SYSCALLS)	+= ftrace.o
 obj-$(CONFIG_FUNCTION_TRACER)	+= mcount.o ftrace.o
 
 obj-$(CONFIG_CPU_R4K_FPU)	+= r4k_fpu.o r4k_switch.o
@@ -84,6 +84,7 @@
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o crash.o
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
+obj-$(CONFIG_EARLY_PRINTK_8250)	+= early_printk_8250.o
 obj-$(CONFIG_SPINLOCK_TEST)	+= spinlock_test.o
 obj-$(CONFIG_MIPS_MACHINE)	+= mips_machine.o
 
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 5465dc1..c814287 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -376,13 +376,33 @@
 				__cpu_name[cpu] = "R4000PC";
 			}
 		} else {
+			int cca = read_c0_config() & CONF_CM_CMASK;
+			int mc;
+
+			/*
+			 * SC and MC versions can't be reliably told apart,
+			 * but only the latter support coherent caching
+			 * modes so assume the firmware has set the KSEG0
+			 * coherency attribute reasonably (if uncached, we
+			 * assume SC).
+			 */
+			switch (cca) {
+			case CONF_CM_CACHABLE_CE:
+			case CONF_CM_CACHABLE_COW:
+			case CONF_CM_CACHABLE_CUW:
+				mc = 1;
+				break;
+			default:
+				mc = 0;
+				break;
+			}
 			if ((c->processor_id & PRID_REV_MASK) >=
 			    PRID_REV_R4400) {
-				c->cputype = CPU_R4400SC;
-				__cpu_name[cpu] = "R4400SC";
+				c->cputype = mc ? CPU_R4400MC : CPU_R4400SC;
+				__cpu_name[cpu] = mc ? "R4400MC" : "R4400SC";
 			} else {
-				c->cputype = CPU_R4000SC;
-				__cpu_name[cpu] = "R4000SC";
+				c->cputype = mc ? CPU_R4000MC : CPU_R4000SC;
+				__cpu_name[cpu] = mc ? "R4000MC" : "R4000SC";
 			}
 		}
 
@@ -1079,8 +1099,8 @@
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
 
-	printk(KERN_INFO "CPU revision is: %08x (%s)\n",
-	       c->processor_id, cpu_name_string());
+	pr_info("CPU%d revision is: %08x (%s)\n",
+		smp_processor_id(), c->processor_id, cpu_name_string());
 	if (c->options & MIPS_CPU_FPU)
 		printk(KERN_INFO "FPU revision is: %08x\n", c->fpu_id);
 }
diff --git a/arch/mips/kernel/csrc-powertv.c b/arch/mips/kernel/csrc-powertv.c
deleted file mode 100644
index abd99ea..0000000
--- a/arch/mips/kernel/csrc-powertv.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2008 Scientific-Atlanta, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-/*
- * The file comes from kernel/csrc-r4k.c
- */
-#include <linux/clocksource.h>
-#include <linux/init.h>
-
-#include <asm/time.h>			/* Not included in linux/time.h */
-
-#include <asm/mach-powertv/asic_regs.h>
-#include "powertv-clock.h"
-
-/* MIPS PLL Register Definitions */
-#define PLL_GET_M(x)		(((x) >> 8) & 0x000000FF)
-#define PLL_GET_N(x)		(((x) >> 16) & 0x000000FF)
-#define PLL_GET_P(x)		(((x) >> 24) & 0x00000007)
-
-/*
- * returns:  Clock frequency in kHz
- */
-unsigned int __init mips_get_pll_freq(void)
-{
-	unsigned int pll_reg, m, n, p;
-	unsigned int fin = 54000; /* Base frequency in kHz */
-	unsigned int fout;
-
-	/* Read PLL register setting */
-	pll_reg = asic_read(mips_pll_setup);
-	m = PLL_GET_M(pll_reg);
-	n = PLL_GET_N(pll_reg);
-	p = PLL_GET_P(pll_reg);
-	pr_info("MIPS PLL Register:0x%x	 M=%d  N=%d  P=%d\n", pll_reg, m, n, p);
-
-	/* Calculate clock frequency = (2 * N * 54MHz) / (M * (2**P)) */
-	fout = ((2 * n * fin) / (m * (0x01 << p)));
-
-	pr_info("MIPS Clock Freq=%d kHz\n", fout);
-
-	return fout;
-}
-
-static cycle_t c0_hpt_read(struct clocksource *cs)
-{
-	return read_c0_count();
-}
-
-static struct clocksource clocksource_mips = {
-	.name		= "powertv-counter",
-	.read		= c0_hpt_read,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static void __init powertv_c0_hpt_clocksource_init(void)
-{
-	unsigned int pll_freq = mips_get_pll_freq();
-
-	pr_info("CPU frequency %d.%02d MHz\n", pll_freq / 1000,
-		(pll_freq % 1000) * 100 / 1000);
-
-	mips_hpt_frequency = pll_freq / 2 * 1000;
-
-	clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
-
-	clocksource_register_hz(&clocksource_mips, mips_hpt_frequency);
-}
-
-/**
- * struct tim_c - free running counter
- * @hi: High 16 bits of the counter
- * @lo: Low 32 bits of the counter
- *
- * Lays out the structure of the free running counter in memory. This counter
- * increments at a rate of 27 MHz/8 on all platforms.
- */
-struct tim_c {
-	unsigned int hi;
-	unsigned int lo;
-};
-
-static struct tim_c *tim_c;
-
-static cycle_t tim_c_read(struct clocksource *cs)
-{
-	unsigned int hi;
-	unsigned int next_hi;
-	unsigned int lo;
-
-	hi = readl(&tim_c->hi);
-
-	for (;;) {
-		lo = readl(&tim_c->lo);
-		next_hi = readl(&tim_c->hi);
-		if (next_hi == hi)
-			break;
-		hi = next_hi;
-	}
-
-pr_crit("%s: read %llx\n", __func__, ((u64) hi << 32) | lo);
-	return ((u64) hi << 32) | lo;
-}
-
-#define TIM_C_SIZE		48		/* # bits in the timer */
-
-static struct clocksource clocksource_tim_c = {
-	.name		= "powertv-tim_c",
-	.read		= tim_c_read,
-	.mask		= CLOCKSOURCE_MASK(TIM_C_SIZE),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-/**
- * powertv_tim_c_clocksource_init - set up a clock source for the TIM_C clock
- *
- * We know that TIM_C counts at 27 MHz/8, so each cycle corresponds to
- * 1 / (27,000,000/8) seconds.
- */
-static void __init powertv_tim_c_clocksource_init(void)
-{
-	const unsigned long	counts_per_second = 27000000 / 8;
-
-	clocksource_tim_c.rating = 200;
-
-	clocksource_register_hz(&clocksource_tim_c, counts_per_second);
-	tim_c = (struct tim_c *) asic_reg_addr(tim_ch);
-}
-
-/**
- powertv_clocksource_init - initialize all clocksources
- */
-void __init powertv_clocksource_init(void)
-{
-	powertv_c0_hpt_clocksource_init();
-	powertv_tim_c_clocksource_init();
-}
diff --git a/arch/mips/kernel/early_printk_8250.c b/arch/mips/kernel/early_printk_8250.c
new file mode 100644
index 0000000..83cea37
--- /dev/null
+++ b/arch/mips/kernel/early_printk_8250.c
@@ -0,0 +1,66 @@
+/*
+ *  8250/16550-type serial ports prom_putchar()
+ *
+ *  Copyright (C) 2010  Yoichi Yuasa <yuasa@linux-mips.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/io.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+
+static void __iomem *serial8250_base;
+static unsigned int serial8250_reg_shift;
+static unsigned int serial8250_tx_timeout;
+
+void setup_8250_early_printk_port(unsigned long base, unsigned int reg_shift,
+				  unsigned int timeout)
+{
+	serial8250_base = (void __iomem *)base;
+	serial8250_reg_shift = reg_shift;
+	serial8250_tx_timeout = timeout;
+}
+
+static inline u8 serial_in(int offset)
+{
+	return readb(serial8250_base + (offset << serial8250_reg_shift));
+}
+
+static inline void serial_out(int offset, char value)
+{
+	writeb(value, serial8250_base + (offset << serial8250_reg_shift));
+}
+
+void prom_putchar(char c)
+{
+	unsigned int timeout;
+	int status, bits;
+
+	if (!serial8250_base)
+		return;
+
+	timeout = serial8250_tx_timeout;
+	bits = UART_LSR_TEMT | UART_LSR_THRE;
+
+	do {
+		status = serial_in(UART_LSR);
+
+		if (--timeout == 0)
+			break;
+	} while ((status & bits) != bits);
+
+	if (timeout)
+		serial_out(UART_TX, c);
+}
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index dba90ec..185ba25 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -11,11 +11,14 @@
 #include <linux/uaccess.h>
 #include <linux/init.h>
 #include <linux/ftrace.h>
+#include <linux/syscalls.h>
 
 #include <asm/asm.h>
 #include <asm/asm-offsets.h>
 #include <asm/cacheflush.h>
+#include <asm/syscall.h>
 #include <asm/uasm.h>
+#include <asm/unistd.h>
 
 #include <asm-generic/sections.h>
 
@@ -364,3 +367,33 @@
 	WARN_ON(1);
 }
 #endif	/* CONFIG_FUNCTION_GRAPH_TRACER */
+
+#ifdef CONFIG_FTRACE_SYSCALLS
+
+#ifdef CONFIG_32BIT
+unsigned long __init arch_syscall_addr(int nr)
+{
+	return (unsigned long)sys_call_table[nr - __NR_O32_Linux];
+}
+#endif
+
+#ifdef CONFIG_64BIT
+
+unsigned long __init arch_syscall_addr(int nr)
+{
+#ifdef CONFIG_MIPS32_N32
+	if (nr >= __NR_N32_Linux && nr <= __NR_N32_Linux + __NR_N32_Linux_syscalls)
+		return (unsigned long)sysn32_call_table[nr - __NR_N32_Linux];
+#endif
+	if (nr >= __NR_64_Linux  && nr <= __NR_64_Linux + __NR_64_Linux_syscalls)
+		return (unsigned long)sys_call_table[nr - __NR_64_Linux];
+#ifdef CONFIG_MIPS32_O32
+	if (nr >= __NR_O32_Linux && nr <= __NR_O32_Linux + __NR_O32_Linux_syscalls)
+		return (unsigned long)sys32_call_table[nr - __NR_O32_Linux];
+#endif
+
+	return (unsigned long) &sys_ni_syscall;
+}
+#endif
+
+#endif /* CONFIG_FTRACE_SYSCALLS */
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 31fa856..47d7583 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -374,12 +374,20 @@
 NESTED(nmi_handler, PT_SIZE, sp)
 	.set	push
 	.set	noat
+	/*
+	 * Clear ERL - restore segment mapping
+	 * Clear BEV - required for page fault exception handler to work
+	 */
+	mfc0	k0, CP0_STATUS
+	ori     k0, k0, ST0_EXL
+	li	k1, ~(ST0_BEV | ST0_ERL)
+	and     k0, k0, k1
+	mtc0    k0, CP0_STATUS
+	_ehb
 	SAVE_ALL
 	move	a0, sp
 	jal	nmi_exception_handler
-	RESTORE_ALL
-	.set	mips3
-	eret
+	/* nmi_exception_handler never returns */
 	.set	pop
 	END(nmi_handler)
 
diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index 72ef2d2..e498f2b 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -150,7 +150,7 @@
 	domain = irq_domain_add_legacy(of_node, 8, MIPS_CPU_IRQ_BASE, 0,
 				       &mips_cpu_intc_irq_domain_ops, NULL);
 	if (!domain)
-		panic("Failed to add irqdomain for MIPS CPU\n");
+		panic("Failed to add irqdomain for MIPS CPU");
 
 	return 0;
 }
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index 977a623..2a52568 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -23,6 +23,7 @@
 #include <linux/moduleloader.h>
 #include <linux/elf.h>
 #include <linux/mm.h>
+#include <linux/numa.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
@@ -46,7 +47,7 @@
 void *module_alloc(unsigned long size)
 {
 	return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END,
-				GFP_KERNEL, PAGE_KERNEL, -1,
+				GFP_KERNEL, PAGE_KERNEL, NUMA_NO_NODE,
 				__builtin_return_address(0));
 }
 #endif
diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S
index 4204d76..029e002 100644
--- a/arch/mips/kernel/octeon_switch.S
+++ b/arch/mips/kernel/octeon_switch.S
@@ -73,7 +73,7 @@
 3:
 
 #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
-	PTR_L	t8, __stack_chk_guard
+	PTR_LA	t8, __stack_chk_guard
 	LONG_L	t9, TASK_STACK_CANARY(a1)
 	LONG_S	t9, 0(t8)
 #endif
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index 45f1ffc..24cdf64 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -971,11 +971,11 @@
 [C(LL)] = {
 	[C(OP_READ)] = {
 		[C(RESULT_ACCESS)]	= { 0x1c, CNTR_ODD, P },
-		[C(RESULT_MISS)]	= { 0x1d, CNTR_EVEN | CNTR_ODD, P },
+		[C(RESULT_MISS)]	= { 0x1d, CNTR_EVEN, P },
 	},
 	[C(OP_WRITE)] = {
 		[C(RESULT_ACCESS)]	= { 0x1c, CNTR_ODD, P },
-		[C(RESULT_MISS)]	= { 0x1d, CNTR_EVEN | CNTR_ODD, P },
+		[C(RESULT_MISS)]	= { 0x1d, CNTR_EVEN, P },
 	},
 },
 [C(ITLB)] = {
diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c
index 0fa0b69..3c3b0df 100644
--- a/arch/mips/kernel/prom.c
+++ b/arch/mips/kernel/prom.c
@@ -13,12 +13,9 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/bootmem.h>
-#include <linux/initrd.h>
 #include <linux/debugfs.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
 
 #include <asm/page.h>
 #include <asm/prom.h>
@@ -40,13 +37,6 @@
 }
 
 #ifdef CONFIG_OF
-int __init early_init_dt_scan_memory_arch(unsigned long node,
-					  const char *uname, int depth,
-					  void *data)
-{
-	return early_init_dt_scan_memory(node, uname, depth, data);
-}
-
 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
 {
 	return add_memory_region(base, size, BOOT_MEM_RAM);
@@ -57,57 +47,11 @@
 	return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS));
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
-{
-	initrd_start = (unsigned long)__va(start);
-	initrd_end = (unsigned long)__va(end);
-	initrd_below_start_ok = 1;
-}
-#endif
-
-int __init early_init_dt_scan_model(unsigned long node,	const char *uname,
-				    int depth, void *data)
-{
-	if (!depth) {
-		char *model = of_get_flat_dt_prop(node, "model", NULL);
-
-		if (model)
-			mips_set_machine_name(model);
-	}
-	return 0;
-}
-
-void __init early_init_devtree(void *params)
-{
-	/* Setup flat device-tree pointer */
-	initial_boot_params = params;
-
-	/* Retrieve various informations from the /chosen node of the
-	 * device-tree, including the platform type, initrd location and
-	 * size, and more ...
-	 */
-	of_scan_flat_dt(early_init_dt_scan_chosen, arcs_cmdline);
-
-
-	/* Scan memory nodes */
-	of_scan_flat_dt(early_init_dt_scan_root, NULL);
-	of_scan_flat_dt(early_init_dt_scan_memory_arch, NULL);
-
-	/* try to load the mips machine name */
-	of_scan_flat_dt(early_init_dt_scan_model, NULL);
-}
-
 void __init __dt_setup_arch(struct boot_param_header *bph)
 {
-	if (be32_to_cpu(bph->magic) != OF_DT_HEADER) {
-		pr_err("DTB has bad magic, ignoring builtin OF DTB\n");
-
+	if (!early_init_dt_scan(bph))
 		return;
-	}
 
-	initial_boot_params = bph;
-
-	early_init_devtree(initial_boot_params);
+	mips_set_machine_name(of_flat_dt_get_machine_name());
 }
 #endif
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 8ae1ebe..b52e1d2 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -16,16 +16,20 @@
  */
 #include <linux/compiler.h>
 #include <linux/context_tracking.h>
+#include <linux/elf.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
+#include <linux/regset.h>
 #include <linux/smp.h>
 #include <linux/user.h>
 #include <linux/security.h>
+#include <linux/tracehook.h>
 #include <linux/audit.h>
 #include <linux/seccomp.h>
+#include <linux/ftrace.h>
 
 #include <asm/byteorder.h>
 #include <asm/cpu.h>
@@ -35,10 +39,14 @@
 #include <asm/mipsmtregs.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
+#include <asm/syscall.h>
 #include <asm/uaccess.h>
 #include <asm/bootinfo.h>
 #include <asm/reg.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
 /*
  * Called by kernel/ptrace.c when detaching..
  *
@@ -255,6 +263,133 @@
 	return 0;
 }
 
+/* regset get/set implementations */
+
+static int gpr_get(struct task_struct *target,
+		   const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	struct pt_regs *regs = task_pt_regs(target);
+
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				   regs, 0, sizeof(*regs));
+}
+
+static int gpr_set(struct task_struct *target,
+		   const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+	struct pt_regs newregs;
+	int ret;
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &newregs,
+				 0, sizeof(newregs));
+	if (ret)
+		return ret;
+
+	*task_pt_regs(target) = newregs;
+
+	return 0;
+}
+
+static int fpr_get(struct task_struct *target,
+		   const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				   &target->thread.fpu,
+				   0, sizeof(elf_fpregset_t));
+	/* XXX fcr31  */
+}
+
+static int fpr_set(struct task_struct *target,
+		   const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				  &target->thread.fpu,
+				  0, sizeof(elf_fpregset_t));
+	/* XXX fcr31  */
+}
+
+enum mips_regset {
+	REGSET_GPR,
+	REGSET_FPR,
+};
+
+static const struct user_regset mips_regsets[] = {
+	[REGSET_GPR] = {
+		.core_note_type	= NT_PRSTATUS,
+		.n		= ELF_NGREG,
+		.size		= sizeof(unsigned int),
+		.align		= sizeof(unsigned int),
+		.get		= gpr_get,
+		.set		= gpr_set,
+	},
+	[REGSET_FPR] = {
+		.core_note_type	= NT_PRFPREG,
+		.n		= ELF_NFPREG,
+		.size		= sizeof(elf_fpreg_t),
+		.align		= sizeof(elf_fpreg_t),
+		.get		= fpr_get,
+		.set		= fpr_set,
+	},
+};
+
+static const struct user_regset_view user_mips_view = {
+	.name		= "mips",
+	.e_machine	= ELF_ARCH,
+	.ei_osabi	= ELF_OSABI,
+	.regsets	= mips_regsets,
+	.n		= ARRAY_SIZE(mips_regsets),
+};
+
+static const struct user_regset mips64_regsets[] = {
+	[REGSET_GPR] = {
+		.core_note_type	= NT_PRSTATUS,
+		.n		= ELF_NGREG,
+		.size		= sizeof(unsigned long),
+		.align		= sizeof(unsigned long),
+		.get		= gpr_get,
+		.set		= gpr_set,
+	},
+	[REGSET_FPR] = {
+		.core_note_type	= NT_PRFPREG,
+		.n		= ELF_NFPREG,
+		.size		= sizeof(elf_fpreg_t),
+		.align		= sizeof(elf_fpreg_t),
+		.get		= fpr_get,
+		.set		= fpr_set,
+	},
+};
+
+static const struct user_regset_view user_mips64_view = {
+	.name		= "mips",
+	.e_machine	= ELF_ARCH,
+	.ei_osabi	= ELF_OSABI,
+	.regsets	= mips64_regsets,
+	.n		= ARRAY_SIZE(mips_regsets),
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+#ifdef CONFIG_32BIT
+	return &user_mips_view;
+#endif
+
+#ifdef CONFIG_MIPS32_O32
+		if (test_thread_flag(TIF_32BIT_REGS))
+			return &user_mips_view;
+#endif
+
+	return &user_mips64_view;
+}
+
 long arch_ptrace(struct task_struct *child, long request,
 		 unsigned long addr, unsigned long data)
 {
@@ -517,52 +652,27 @@
 	return ret;
 }
 
-static inline int audit_arch(void)
-{
-	int arch = EM_MIPS;
-#ifdef CONFIG_64BIT
-	arch |=	 __AUDIT_ARCH_64BIT;
-#endif
-#if defined(__LITTLE_ENDIAN)
-	arch |=	 __AUDIT_ARCH_LE;
-#endif
-	return arch;
-}
-
 /*
  * Notification of system call entry/exit
  * - triggered by current->work.syscall_trace
  */
 asmlinkage void syscall_trace_enter(struct pt_regs *regs)
 {
+	long ret = 0;
 	user_exit();
 
 	/* do the secure computing check first */
 	secure_computing_strict(regs->regs[2]);
 
-	if (!(current->ptrace & PT_PTRACED))
-		goto out;
+	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
+	    tracehook_report_syscall_entry(regs))
+		ret = -1;
 
-	if (!test_thread_flag(TIF_SYSCALL_TRACE))
-		goto out;
+	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
+		trace_sys_enter(regs, regs->regs[2]);
 
-	/* The 0x80 provides a way for the tracing parent to distinguish
-	   between a syscall stop and SIGTRAP delivery */
-	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ?
-				 0x80 : 0));
-
-	/*
-	 * this isn't the same as continuing with a signal, but it will do
-	 * for normal use.  strace only continues with a signal if the
-	 * stopping signal is not SIGTRAP.  -brl
-	 */
-	if (current->exit_code) {
-		send_sig(current->exit_code, current, 1);
-		current->exit_code = 0;
-	}
-
-out:
-	audit_syscall_entry(audit_arch(), regs->regs[2],
+	audit_syscall_entry(__syscall_get_arch(),
+			    regs->regs[2],
 			    regs->regs[4], regs->regs[5],
 			    regs->regs[6], regs->regs[7]);
 }
@@ -582,26 +692,11 @@
 
 	audit_syscall_exit(regs);
 
-	if (!(current->ptrace & PT_PTRACED))
-		return;
+	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
+		trace_sys_exit(regs, regs->regs[2]);
 
-	if (!test_thread_flag(TIF_SYSCALL_TRACE))
-		return;
-
-	/* The 0x80 provides a way for the tracing parent to distinguish
-	   between a syscall stop and SIGTRAP delivery */
-	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ?
-				 0x80 : 0));
-
-	/*
-	 * this isn't the same as continuing with a signal, but it will do
-	 * for normal use.  strace only continues with a signal if the
-	 * stopping signal is not SIGTRAP.  -brl
-	 */
-	if (current->exit_code) {
-		send_sig(current->exit_code, current, 1);
-		current->exit_code = 0;
-	}
+	if (test_thread_flag(TIF_SYSCALL_TRACE))
+		tracehook_report_syscall_exit(regs, 0);
 
 	user_enter();
 }
diff --git a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S
index 38af83f..20b7b04 100644
--- a/arch/mips/kernel/r2300_switch.S
+++ b/arch/mips/kernel/r2300_switch.S
@@ -67,7 +67,7 @@
 1:
 
 #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
-	PTR_L	t8, __stack_chk_guard
+	PTR_LA	t8, __stack_chk_guard
 	LONG_L	t9, TASK_STACK_CANARY(a1)
 	LONG_S	t9, 0(t8)
 #endif
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 921238a..078de5e 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -69,7 +69,7 @@
 1:
 
 #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
-	PTR_L	t8, __stack_chk_guard
+	PTR_LA	t8, __stack_chk_guard
 	LONG_L	t9, TASK_STACK_CANARY(a1)
 	LONG_S	t9, 0(t8)
 #endif
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index d763f11..2c12ea1 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -172,8 +172,9 @@
 	if (rtlx == NULL) {
 		if( (p = vpe_get_shared(tclimit)) == NULL) {
 		    if (can_sleep) {
-			__wait_event_interruptible(channel_wqs[index].lx_queue,
-				(p = vpe_get_shared(tclimit)), ret);
+			ret = __wait_event_interruptible(
+					channel_wqs[index].lx_queue,
+					(p = vpe_get_shared(tclimit)));
 			if (ret)
 				goto out_fail;
 		    } else {
@@ -263,11 +264,10 @@
 	/* data available to read? */
 	if (chan->lx_read == chan->lx_write) {
 		if (can_sleep) {
-			int ret = 0;
-
-			__wait_event_interruptible(channel_wqs[index].lx_queue,
+			int ret = __wait_event_interruptible(
+				channel_wqs[index].lx_queue,
 				(chan->lx_read != chan->lx_write) ||
-				sp_stopping, ret);
+				sp_stopping);
 			if (ret)
 				return ret;
 
@@ -440,14 +440,13 @@
 
 	/* any space left... */
 	if (!rtlx_write_poll(minor)) {
-		int ret = 0;
+		int ret;
 
 		if (file->f_flags & O_NONBLOCK)
 			return -EAGAIN;
 
-		__wait_event_interruptible(channel_wqs[minor].rt_queue,
-					   rtlx_write_poll(minor),
-					   ret);
+		ret = __wait_event_interruptible(channel_wqs[minor].rt_queue,
+					   rtlx_write_poll(minor));
 		if (ret)
 			return ret;
 	}
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index e774bb1..e8e541b 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -40,17 +40,58 @@
 	sw	t1, PT_EPC(sp)
 	beqz	t0, illegal_syscall
 
-	sll	t0, v0, 3
+	sll	t0, v0, 2
 	la	t1, sys_call_table
 	addu	t1, t0
 	lw	t2, (t1)		# syscall routine
-	lw	t3, 4(t1)		# >= 0 if we need stack arguments
 	beqz	t2, illegal_syscall
 
 	sw	a3, PT_R26(sp)		# save a3 for syscall restarting
-	bgez	t3, stackargs
 
-stack_done:
+	/*
+	 * More than four arguments.  Try to deal with it by copying the
+	 * stack arguments from the user stack to the kernel stack.
+	 * This Sucks (TM).
+	 */
+	lw	t0, PT_R29(sp)		# get old user stack pointer
+
+	/*
+	 * We intentionally keep the kernel stack a little below the top of
+	 * userspace so we don't have to do a slower byte accurate check here.
+	 */
+	lw	t5, TI_ADDR_LIMIT($28)
+	addu	t4, t0, 32
+	and	t5, t4
+	bltz	t5, bad_stack		# -> sp is bad
+
+	/*
+	 * Ok, copy the args from the luser stack to the kernel stack.
+	 * t3 is the precomputed number of instruction bytes needed to
+	 * load or store arguments 6-8.
+	 */
+
+	.set    push
+	.set    noreorder
+	.set	nomacro
+
+1:	lw	t5, 16(t0)		# argument #5 from usp
+4:	lw	t6, 20(t0)		# argument #6 from usp
+3:	lw	t7, 24(t0)		# argument #7 from usp
+2:	lw	t8, 28(t0)		# argument #8 from usp
+
+	sw	t5, 16(sp)		# argument #5 to ksp
+	sw	t6, 20(sp)		# argument #6 to ksp
+	sw	t7, 24(sp)		# argument #7 to ksp
+	sw	t8, 28(sp)		# argument #8 to ksp
+	.set	pop
+
+	.section __ex_table,"a"
+	PTR	1b,bad_stack
+	PTR	2b,bad_stack
+	PTR	3b,bad_stack
+	PTR	4b,bad_stack
+	.previous
+
 	lw	t0, TI_FLAGS($28)	# syscall tracing enabled?
 	li	t1, _TIF_WORK_SYSCALL_ENTRY
 	and	t0, t1
@@ -102,66 +143,6 @@
 /* ------------------------------------------------------------------------ */
 
 	/*
-	 * More than four arguments.  Try to deal with it by copying the
-	 * stack arguments from the user stack to the kernel stack.
-	 * This Sucks (TM).
-	 */
-stackargs:
-	lw	t0, PT_R29(sp)		# get old user stack pointer
-
-	/*
-	 * We intentionally keep the kernel stack a little below the top of
-	 * userspace so we don't have to do a slower byte accurate check here.
-	 */
-	lw	t5, TI_ADDR_LIMIT($28)
-	addu	t4, t0, 32
-	and	t5, t4
-	bltz	t5, bad_stack		# -> sp is bad
-
-	/* Ok, copy the args from the luser stack to the kernel stack.
-	 * t3 is the precomputed number of instruction bytes needed to
-	 * load or store arguments 6-8.
-	 */
-
-	la	t1, 5f			# load up to 3 arguments
-	subu	t1, t3
-1:	lw	t5, 16(t0)		# argument #5 from usp
-	.set	push
-	.set	noreorder
-	.set	nomacro
-	jr	t1
-	 addiu	t1, 6f - 5f
-
-2:	lw	t8, 28(t0)		# argument #8 from usp
-3:	lw	t7, 24(t0)		# argument #7 from usp
-4:	lw	t6, 20(t0)		# argument #6 from usp
-5:	jr	t1
-	 sw	t5, 16(sp)		# argument #5 to ksp
-
-#ifdef CONFIG_CPU_MICROMIPS
-	sw	t8, 28(sp)		# argument #8 to ksp
-	nop
-	sw	t7, 24(sp)		# argument #7 to ksp
-	nop
-	sw	t6, 20(sp)		# argument #6 to ksp
-	nop
-#else
-	sw	t8, 28(sp)		# argument #8 to ksp
-	sw	t7, 24(sp)		# argument #7 to ksp
-	sw	t6, 20(sp)		# argument #6 to ksp
-#endif
-6:	j	stack_done		# go back
-	 nop
-	.set	pop
-
-	.section __ex_table,"a"
-	PTR	1b,bad_stack
-	PTR	2b,bad_stack
-	PTR	3b,bad_stack
-	PTR	4b,bad_stack
-	.previous
-
-	/*
 	 * The stackpointer for a call with more than 4 arguments is bad.
 	 * We probably should handle this case a bit more drastic.
 	 */
@@ -187,7 +168,7 @@
 	subu	t0, a0, __NR_O32_Linux	# check syscall number
 	sltiu	v0, t0, __NR_O32_Linux_syscalls + 1
 	beqz	t0, einval		# do not recurse
-	sll	t1, t0, 3
+	sll	t1, t0, 2
 	beqz	v0, einval
 	lw	t2, sys_call_table(t1)		# syscall routine
 
@@ -218,260 +199,248 @@
 	jr	ra
 	END(sys_syscall)
 
-	.macro	fifty ptr, nargs, from=1, to=50
-	sys	\ptr		\nargs
-	.if	\to-\from
-	fifty	\ptr,\nargs,"(\from+1)",\to
-	.endif
-	.endm
-
-	.macro	mille ptr, nargs, from=1, to=20
-	fifty	\ptr,\nargs
-	.if	\to-\from
-	mille	\ptr,\nargs,"(\from+1)",\to
-	.endif
-	.endm
-
-	.macro	syscalltable
-	sys	sys_syscall		8	/* 4000 */
-	sys	sys_exit		1
-	sys	__sys_fork		0
-	sys	sys_read		3
-	sys	sys_write		3
-	sys	sys_open		3	/* 4005 */
-	sys	sys_close		1
-	sys	sys_waitpid		3
-	sys	sys_creat		2
-	sys	sys_link		2
-	sys	sys_unlink		1	/* 4010 */
-	sys	sys_execve		0
-	sys	sys_chdir		1
-	sys	sys_time		1
-	sys	sys_mknod		3
-	sys	sys_chmod		2	/* 4015 */
-	sys	sys_lchown		3
-	sys	sys_ni_syscall		0
-	sys	sys_ni_syscall		0	/* was sys_stat */
-	sys	sys_lseek		3
-	sys	sys_getpid		0	/* 4020 */
-	sys	sys_mount		5
-	sys	sys_oldumount		1
-	sys	sys_setuid		1
-	sys	sys_getuid		0
-	sys	sys_stime		1	/* 4025 */
-	sys	sys_ptrace		4
-	sys	sys_alarm		1
-	sys	sys_ni_syscall		0	/* was sys_fstat */
-	sys	sys_pause		0
-	sys	sys_utime		2	/* 4030 */
-	sys	sys_ni_syscall		0
-	sys	sys_ni_syscall		0
-	sys	sys_access		2
-	sys	sys_nice		1
-	sys	sys_ni_syscall		0	/* 4035 */
-	sys	sys_sync		0
-	sys	sys_kill		2
-	sys	sys_rename		2
-	sys	sys_mkdir		2
-	sys	sys_rmdir		1	/* 4040 */
-	sys	sys_dup			1
-	sys	sysm_pipe		0
-	sys	sys_times		1
-	sys	sys_ni_syscall		0
-	sys	sys_brk			1	/* 4045 */
-	sys	sys_setgid		1
-	sys	sys_getgid		0
-	sys	sys_ni_syscall		0	/* was signal(2) */
-	sys	sys_geteuid		0
-	sys	sys_getegid		0	/* 4050 */
-	sys	sys_acct		1
-	sys	sys_umount		2
-	sys	sys_ni_syscall		0
-	sys	sys_ioctl		3
-	sys	sys_fcntl		3	/* 4055 */
-	sys	sys_ni_syscall		2
-	sys	sys_setpgid		2
-	sys	sys_ni_syscall		0
-	sys	sys_olduname		1
-	sys	sys_umask		1	/* 4060 */
-	sys	sys_chroot		1
-	sys	sys_ustat		2
-	sys	sys_dup2		2
-	sys	sys_getppid		0
-	sys	sys_getpgrp		0	/* 4065 */
-	sys	sys_setsid		0
-	sys	sys_sigaction		3
-	sys	sys_sgetmask		0
-	sys	sys_ssetmask		1
-	sys	sys_setreuid		2	/* 4070 */
-	sys	sys_setregid		2
-	sys	sys_sigsuspend		0
-	sys	sys_sigpending		1
-	sys	sys_sethostname		2
-	sys	sys_setrlimit		2	/* 4075 */
-	sys	sys_getrlimit		2
-	sys	sys_getrusage		2
-	sys	sys_gettimeofday	2
-	sys	sys_settimeofday	2
-	sys	sys_getgroups		2	/* 4080 */
-	sys	sys_setgroups		2
-	sys	sys_ni_syscall		0	/* old_select */
-	sys	sys_symlink		2
-	sys	sys_ni_syscall		0	/* was sys_lstat */
-	sys	sys_readlink		3	/* 4085 */
-	sys	sys_uselib		1
-	sys	sys_swapon		2
-	sys	sys_reboot		3
-	sys	sys_old_readdir		3
-	sys	sys_mips_mmap		6	/* 4090 */
-	sys	sys_munmap		2
-	sys	sys_truncate		2
-	sys	sys_ftruncate		2
-	sys	sys_fchmod		2
-	sys	sys_fchown		3	/* 4095 */
-	sys	sys_getpriority		2
-	sys	sys_setpriority		3
-	sys	sys_ni_syscall		0
-	sys	sys_statfs		2
-	sys	sys_fstatfs		2	/* 4100 */
-	sys	sys_ni_syscall		0	/* was ioperm(2) */
-	sys	sys_socketcall		2
-	sys	sys_syslog		3
-	sys	sys_setitimer		3
-	sys	sys_getitimer		2	/* 4105 */
-	sys	sys_newstat		2
-	sys	sys_newlstat		2
-	sys	sys_newfstat		2
-	sys	sys_uname		1
-	sys	sys_ni_syscall		0	/* 4110 was iopl(2) */
-	sys	sys_vhangup		0
-	sys	sys_ni_syscall		0	/* was sys_idle() */
-	sys	sys_ni_syscall		0	/* was sys_vm86 */
-	sys	sys_wait4		4
-	sys	sys_swapoff		1	/* 4115 */
-	sys	sys_sysinfo		1
-	sys	sys_ipc			6
-	sys	sys_fsync		1
-	sys	sys_sigreturn		0
-	sys	__sys_clone		6	/* 4120 */
-	sys	sys_setdomainname	2
-	sys	sys_newuname		1
-	sys	sys_ni_syscall		0	/* sys_modify_ldt */
-	sys	sys_adjtimex		1
-	sys	sys_mprotect		3	/* 4125 */
-	sys	sys_sigprocmask		3
-	sys	sys_ni_syscall		0	/* was create_module */
-	sys	sys_init_module		5
-	sys	sys_delete_module	1
-	sys	sys_ni_syscall		0	/* 4130 was get_kernel_syms */
-	sys	sys_quotactl		4
-	sys	sys_getpgid		1
-	sys	sys_fchdir		1
-	sys	sys_bdflush		2
-	sys	sys_sysfs		3	/* 4135 */
-	sys	sys_personality		1
-	sys	sys_ni_syscall		0	/* for afs_syscall */
-	sys	sys_setfsuid		1
-	sys	sys_setfsgid		1
-	sys	sys_llseek		5	/* 4140 */
-	sys	sys_getdents		3
-	sys	sys_select		5
-	sys	sys_flock		2
-	sys	sys_msync		3
-	sys	sys_readv		3	/* 4145 */
-	sys	sys_writev		3
-	sys	sys_cacheflush		3
-	sys	sys_cachectl		3
-	sys	sys_sysmips		4
-	sys	sys_ni_syscall		0	/* 4150 */
-	sys	sys_getsid		1
-	sys	sys_fdatasync		1
-	sys	sys_sysctl		1
-	sys	sys_mlock		2
-	sys	sys_munlock		2	/* 4155 */
-	sys	sys_mlockall		1
-	sys	sys_munlockall		0
-	sys	sys_sched_setparam	2
-	sys	sys_sched_getparam	2
-	sys	sys_sched_setscheduler	3	/* 4160 */
-	sys	sys_sched_getscheduler	1
-	sys	sys_sched_yield		0
-	sys	sys_sched_get_priority_max 1
-	sys	sys_sched_get_priority_min 1
-	sys	sys_sched_rr_get_interval 2	/* 4165 */
-	sys	sys_nanosleep,		2
-	sys	sys_mremap,		5
-	sys	sys_accept		3
-	sys	sys_bind		3
-	sys	sys_connect		3	/* 4170 */
-	sys	sys_getpeername		3
-	sys	sys_getsockname		3
-	sys	sys_getsockopt		5
-	sys	sys_listen		2
-	sys	sys_recv		4	/* 4175 */
-	sys	sys_recvfrom		6
-	sys	sys_recvmsg		3
-	sys	sys_send		4
-	sys	sys_sendmsg		3
-	sys	sys_sendto		6	/* 4180 */
-	sys	sys_setsockopt		5
-	sys	sys_shutdown		2
-	sys	sys_socket		3
-	sys	sys_socketpair		4
-	sys	sys_setresuid		3	/* 4185 */
-	sys	sys_getresuid		3
-	sys	sys_ni_syscall		0	/* was sys_query_module */
-	sys	sys_poll		3
-	sys	sys_ni_syscall		0	/* was nfsservctl */
-	sys	sys_setresgid		3	/* 4190 */
-	sys	sys_getresgid		3
-	sys	sys_prctl		5
-	sys	sys_rt_sigreturn	0
-	sys	sys_rt_sigaction	4
-	sys	sys_rt_sigprocmask	4	/* 4195 */
-	sys	sys_rt_sigpending	2
-	sys	sys_rt_sigtimedwait	4
-	sys	sys_rt_sigqueueinfo	3
-	sys	sys_rt_sigsuspend	0
-	sys	sys_pread64		6	/* 4200 */
-	sys	sys_pwrite64		6
-	sys	sys_chown		3
-	sys	sys_getcwd		2
-	sys	sys_capget		2
-	sys	sys_capset		2	/* 4205 */
-	sys	sys_sigaltstack		0
-	sys	sys_sendfile		4
-	sys	sys_ni_syscall		0
-	sys	sys_ni_syscall		0
-	sys	sys_mips_mmap2		6	/* 4210 */
-	sys	sys_truncate64		4
-	sys	sys_ftruncate64		4
-	sys	sys_stat64		2
-	sys	sys_lstat64		2
-	sys	sys_fstat64		2	/* 4215 */
-	sys	sys_pivot_root		2
-	sys	sys_mincore		3
-	sys	sys_madvise		3
-	sys	sys_getdents64		3
-	sys	sys_fcntl64		3	/* 4220 */
-	sys	sys_ni_syscall		0
-	sys	sys_gettid		0
-	sys	sys_readahead		5
-	sys	sys_setxattr		5
-	sys	sys_lsetxattr		5	/* 4225 */
-	sys	sys_fsetxattr		5
-	sys	sys_getxattr		4
-	sys	sys_lgetxattr		4
-	sys	sys_fgetxattr		4
-	sys	sys_listxattr		3	/* 4230 */
-	sys	sys_llistxattr		3
-	sys	sys_flistxattr		3
-	sys	sys_removexattr		2
-	sys	sys_lremovexattr	2
-	sys	sys_fremovexattr	2	/* 4235 */
-	sys	sys_tkill		2
-	sys	sys_sendfile64		5
-	sys	sys_futex		6
+	.align	2
+	.type	sys_call_table, @object
+EXPORT(sys_call_table)
+	PTR	sys_syscall			/* 4000 */
+	PTR	sys_exit
+	PTR	__sys_fork
+	PTR	sys_read
+	PTR	sys_write
+	PTR	sys_open			/* 4005 */
+	PTR	sys_close
+	PTR	sys_waitpid
+	PTR	sys_creat
+	PTR	sys_link
+	PTR	sys_unlink			/* 4010 */
+	PTR	sys_execve
+	PTR	sys_chdir
+	PTR	sys_time
+	PTR	sys_mknod
+	PTR	sys_chmod			/* 4015 */
+	PTR	sys_lchown
+	PTR	sys_ni_syscall
+	PTR	sys_ni_syscall			/* was sys_stat */
+	PTR	sys_lseek
+	PTR	sys_getpid			/* 4020 */
+	PTR	sys_mount
+	PTR	sys_oldumount
+	PTR	sys_setuid
+	PTR	sys_getuid
+	PTR	sys_stime			/* 4025 */
+	PTR	sys_ptrace
+	PTR	sys_alarm
+	PTR	sys_ni_syscall			/* was sys_fstat */
+	PTR	sys_pause
+	PTR	sys_utime			/* 4030 */
+	PTR	sys_ni_syscall
+	PTR	sys_ni_syscall
+	PTR	sys_access
+	PTR	sys_nice
+	PTR	sys_ni_syscall			/* 4035 */
+	PTR	sys_sync
+	PTR	sys_kill
+	PTR	sys_rename
+	PTR	sys_mkdir
+	PTR	sys_rmdir			/* 4040 */
+	PTR	sys_dup
+	PTR	sysm_pipe
+	PTR	sys_times
+	PTR	sys_ni_syscall
+	PTR	sys_brk				/* 4045 */
+	PTR	sys_setgid
+	PTR	sys_getgid
+	PTR	sys_ni_syscall			/* was signal(2) */
+	PTR	sys_geteuid
+	PTR	sys_getegid			/* 4050 */
+	PTR	sys_acct
+	PTR	sys_umount
+	PTR	sys_ni_syscall
+	PTR	sys_ioctl
+	PTR	sys_fcntl			/* 4055 */
+	PTR	sys_ni_syscall
+	PTR	sys_setpgid
+	PTR	sys_ni_syscall
+	PTR	sys_olduname
+	PTR	sys_umask			/* 4060 */
+	PTR	sys_chroot
+	PTR	sys_ustat
+	PTR	sys_dup2
+	PTR	sys_getppid
+	PTR	sys_getpgrp			/* 4065 */
+	PTR	sys_setsid
+	PTR	sys_sigaction
+	PTR	sys_sgetmask
+	PTR	sys_ssetmask
+	PTR	sys_setreuid			/* 4070 */
+	PTR	sys_setregid
+	PTR	sys_sigsuspend
+	PTR	sys_sigpending
+	PTR	sys_sethostname
+	PTR	sys_setrlimit			/* 4075 */
+	PTR	sys_getrlimit
+	PTR	sys_getrusage
+	PTR	sys_gettimeofday
+	PTR	sys_settimeofday
+	PTR	sys_getgroups			/* 4080 */
+	PTR	sys_setgroups
+	PTR	sys_ni_syscall			/* old_select */
+	PTR	sys_symlink
+	PTR	sys_ni_syscall			/* was sys_lstat */
+	PTR	sys_readlink			/* 4085 */
+	PTR	sys_uselib
+	PTR	sys_swapon
+	PTR	sys_reboot
+	PTR	sys_old_readdir
+	PTR	sys_mips_mmap			/* 4090 */
+	PTR	sys_munmap
+	PTR	sys_truncate
+	PTR	sys_ftruncate
+	PTR	sys_fchmod
+	PTR	sys_fchown			/* 4095 */
+	PTR	sys_getpriority
+	PTR	sys_setpriority
+	PTR	sys_ni_syscall
+	PTR	sys_statfs
+	PTR	sys_fstatfs			/* 4100 */
+	PTR	sys_ni_syscall			/* was ioperm(2) */
+	PTR	sys_socketcall
+	PTR	sys_syslog
+	PTR	sys_setitimer
+	PTR	sys_getitimer			/* 4105 */
+	PTR	sys_newstat
+	PTR	sys_newlstat
+	PTR	sys_newfstat
+	PTR	sys_uname
+	PTR	sys_ni_syscall			/* 4110 was iopl(2) */
+	PTR	sys_vhangup
+	PTR	sys_ni_syscall			/* was sys_idle() */
+	PTR	sys_ni_syscall			/* was sys_vm86 */
+	PTR	sys_wait4
+	PTR	sys_swapoff			/* 4115 */
+	PTR	sys_sysinfo
+	PTR	sys_ipc
+	PTR	sys_fsync
+	PTR	sys_sigreturn
+	PTR	__sys_clone			/* 4120 */
+	PTR	sys_setdomainname
+	PTR	sys_newuname
+	PTR	sys_ni_syscall			/* sys_modify_ldt */
+	PTR	sys_adjtimex
+	PTR	sys_mprotect			/* 4125 */
+	PTR	sys_sigprocmask
+	PTR	sys_ni_syscall			/* was create_module */
+	PTR	sys_init_module
+	PTR	sys_delete_module
+	PTR	sys_ni_syscall			/* 4130 was get_kernel_syms */
+	PTR	sys_quotactl
+	PTR	sys_getpgid
+	PTR	sys_fchdir
+	PTR	sys_bdflush
+	PTR	sys_sysfs			/* 4135 */
+	PTR	sys_personality
+	PTR	sys_ni_syscall			/* for afs_syscall */
+	PTR	sys_setfsuid
+	PTR	sys_setfsgid
+	PTR	sys_llseek			/* 4140 */
+	PTR	sys_getdents
+	PTR	sys_select
+	PTR	sys_flock
+	PTR	sys_msync
+	PTR	sys_readv			/* 4145 */
+	PTR	sys_writev
+	PTR	sys_cacheflush
+	PTR	sys_cachectl
+	PTR	sys_sysmips
+	PTR	sys_ni_syscall			/* 4150 */
+	PTR	sys_getsid
+	PTR	sys_fdatasync
+	PTR	sys_sysctl
+	PTR	sys_mlock
+	PTR	sys_munlock			/* 4155 */
+	PTR	sys_mlockall
+	PTR	sys_munlockall
+	PTR	sys_sched_setparam
+	PTR	sys_sched_getparam
+	PTR	sys_sched_setscheduler		/* 4160 */
+	PTR	sys_sched_getscheduler
+	PTR	sys_sched_yield
+	PTR	sys_sched_get_priority_max
+	PTR	sys_sched_get_priority_min
+	PTR	sys_sched_rr_get_interval	/* 4165 */
+	PTR	sys_nanosleep
+	PTR	sys_mremap
+	PTR	sys_accept
+	PTR	sys_bind
+	PTR	sys_connect			/* 4170 */
+	PTR	sys_getpeername
+	PTR	sys_getsockname
+	PTR	sys_getsockopt
+	PTR	sys_listen
+	PTR	sys_recv			/* 4175 */
+	PTR	sys_recvfrom
+	PTR	sys_recvmsg
+	PTR	sys_send
+	PTR	sys_sendmsg
+	PTR	sys_sendto			/* 4180 */
+	PTR	sys_setsockopt
+	PTR	sys_shutdown
+	PTR	sys_socket
+	PTR	sys_socketpair
+	PTR	sys_setresuid			/* 4185 */
+	PTR	sys_getresuid
+	PTR	sys_ni_syscall			/* was sys_query_module */
+	PTR	sys_poll
+	PTR	sys_ni_syscall			/* was nfsservctl */
+	PTR	sys_setresgid			/* 4190 */
+	PTR	sys_getresgid
+	PTR	sys_prctl
+	PTR	sys_rt_sigreturn
+	PTR	sys_rt_sigaction
+	PTR	sys_rt_sigprocmask		/* 4195 */
+	PTR	sys_rt_sigpending
+	PTR	sys_rt_sigtimedwait
+	PTR	sys_rt_sigqueueinfo
+	PTR	sys_rt_sigsuspend
+	PTR	sys_pread64			/* 4200 */
+	PTR	sys_pwrite64
+	PTR	sys_chown
+	PTR	sys_getcwd
+	PTR	sys_capget
+	PTR	sys_capset			/* 4205 */
+	PTR	sys_sigaltstack
+	PTR	sys_sendfile
+	PTR	sys_ni_syscall
+	PTR	sys_ni_syscall
+	PTR	sys_mips_mmap2			/* 4210 */
+	PTR	sys_truncate64
+	PTR	sys_ftruncate64
+	PTR	sys_stat64
+	PTR	sys_lstat64
+	PTR	sys_fstat64			/* 4215 */
+	PTR	sys_pivot_root
+	PTR	sys_mincore
+	PTR	sys_madvise
+	PTR	sys_getdents64
+	PTR	sys_fcntl64			/* 4220 */
+	PTR	sys_ni_syscall
+	PTR	sys_gettid
+	PTR	sys_readahead
+	PTR	sys_setxattr
+	PTR	sys_lsetxattr			/* 4225 */
+	PTR	sys_fsetxattr
+	PTR	sys_getxattr
+	PTR	sys_lgetxattr
+	PTR	sys_fgetxattr
+	PTR	sys_listxattr			/* 4230 */
+	PTR	sys_llistxattr
+	PTR	sys_flistxattr
+	PTR	sys_removexattr
+	PTR	sys_lremovexattr
+	PTR	sys_fremovexattr		/* 4235 */
+	PTR	sys_tkill
+	PTR	sys_sendfile64
+	PTR	sys_futex
 #ifdef CONFIG_MIPS_MT_FPAFF
 	/*
 	 * For FPU affinity scheduling on MIPS MT processors, we need to
@@ -480,132 +449,117 @@
 	 * these hooks for the 32-bit kernel - there is no MIPS64 MT processor
 	 * atm.
 	 */
-	sys	mipsmt_sys_sched_setaffinity	3
-	sys	mipsmt_sys_sched_getaffinity	3
+	PTR	mipsmt_sys_sched_setaffinity
+	PTR	mipsmt_sys_sched_getaffinity
 #else
-	sys	sys_sched_setaffinity	3
-	sys	sys_sched_getaffinity	3	/* 4240 */
+	PTR	sys_sched_setaffinity
+	PTR	sys_sched_getaffinity		/* 4240 */
 #endif /* CONFIG_MIPS_MT_FPAFF */
-	sys	sys_io_setup		2
-	sys	sys_io_destroy		1
-	sys	sys_io_getevents	5
-	sys	sys_io_submit		3
-	sys	sys_io_cancel		3	/* 4245 */
-	sys	sys_exit_group		1
-	sys	sys_lookup_dcookie	4
-	sys	sys_epoll_create	1
-	sys	sys_epoll_ctl		4
-	sys	sys_epoll_wait		4	/* 4250 */
-	sys	sys_remap_file_pages	5
-	sys	sys_set_tid_address	1
-	sys	sys_restart_syscall	0
-	sys	sys_fadvise64_64	7
-	sys	sys_statfs64		3	/* 4255 */
-	sys	sys_fstatfs64		2
-	sys	sys_timer_create	3
-	sys	sys_timer_settime	4
-	sys	sys_timer_gettime	2
-	sys	sys_timer_getoverrun	1	/* 4260 */
-	sys	sys_timer_delete	1
-	sys	sys_clock_settime	2
-	sys	sys_clock_gettime	2
-	sys	sys_clock_getres	2
-	sys	sys_clock_nanosleep	4	/* 4265 */
-	sys	sys_tgkill		3
-	sys	sys_utimes		2
-	sys	sys_mbind		4
-	sys	sys_ni_syscall		0	/* sys_get_mempolicy */
-	sys	sys_ni_syscall		0	/* 4270 sys_set_mempolicy */
-	sys	sys_mq_open		4
-	sys	sys_mq_unlink		1
-	sys	sys_mq_timedsend	5
-	sys	sys_mq_timedreceive	5
-	sys	sys_mq_notify		2	/* 4275 */
-	sys	sys_mq_getsetattr	3
-	sys	sys_ni_syscall		0	/* sys_vserver */
-	sys	sys_waitid		5
-	sys	sys_ni_syscall		0	/* available, was setaltroot */
-	sys	sys_add_key		5	/* 4280 */
-	sys	sys_request_key		4
-	sys	sys_keyctl		5
-	sys	sys_set_thread_area	1
-	sys	sys_inotify_init	0
-	sys	sys_inotify_add_watch	3	/* 4285 */
-	sys	sys_inotify_rm_watch	2
-	sys	sys_migrate_pages	4
-	sys	sys_openat		4
-	sys	sys_mkdirat		3
-	sys	sys_mknodat		4	/* 4290 */
-	sys	sys_fchownat		5
-	sys	sys_futimesat		3
-	sys	sys_fstatat64		4
-	sys	sys_unlinkat		3
-	sys	sys_renameat		4	/* 4295 */
-	sys	sys_linkat		5
-	sys	sys_symlinkat		3
-	sys	sys_readlinkat		4
-	sys	sys_fchmodat		3
-	sys	sys_faccessat		3	/* 4300 */
-	sys	sys_pselect6		6
-	sys	sys_ppoll		5
-	sys	sys_unshare		1
-	sys	sys_splice		6
-	sys	sys_sync_file_range	7	/* 4305 */
-	sys	sys_tee			4
-	sys	sys_vmsplice		4
-	sys	sys_move_pages		6
-	sys	sys_set_robust_list	2
-	sys	sys_get_robust_list	3	/* 4310 */
-	sys	sys_kexec_load		4
-	sys	sys_getcpu		3
-	sys	sys_epoll_pwait		6
-	sys	sys_ioprio_set		3
-	sys	sys_ioprio_get		2	/* 4315 */
-	sys	sys_utimensat		4
-	sys	sys_signalfd		3
-	sys	sys_ni_syscall		0	/* was timerfd */
-	sys	sys_eventfd		1
-	sys	sys_fallocate		6	/* 4320 */
-	sys	sys_timerfd_create	2
-	sys	sys_timerfd_gettime	2
-	sys	sys_timerfd_settime	4
-	sys	sys_signalfd4		4
-	sys	sys_eventfd2		2	/* 4325 */
-	sys	sys_epoll_create1	1
-	sys	sys_dup3		3
-	sys	sys_pipe2		2
-	sys	sys_inotify_init1	1
-	sys	sys_preadv		6	/* 4330 */
-	sys	sys_pwritev		6
-	sys	sys_rt_tgsigqueueinfo	4
-	sys	sys_perf_event_open	5
-	sys	sys_accept4		4
-	sys	sys_recvmmsg		5	/* 4335 */
-	sys	sys_fanotify_init	2
-	sys	sys_fanotify_mark	6
-	sys	sys_prlimit64		4
-	sys	sys_name_to_handle_at	5
-	sys	sys_open_by_handle_at	3	/* 4340 */
-	sys	sys_clock_adjtime	2
-	sys	sys_syncfs		1
-	sys	sys_sendmmsg		4
-	sys	sys_setns		2
-	sys	sys_process_vm_readv	6	/* 4345 */
-	sys	sys_process_vm_writev	6
-	sys	sys_kcmp		5
-	sys	sys_finit_module	3
-	.endm
-
-	/* We pre-compute the number of _instruction_ bytes needed to
-	   load or store the arguments 6-8. Negative values are ignored. */
-
-	.macro	sys function, nargs
-	PTR	\function
-	LONG	(\nargs << 2) - (5 << 2)
-	.endm
-
-	.align	3
-	.type	sys_call_table,@object
-EXPORT(sys_call_table)
-	syscalltable
-	.size	sys_call_table, . - sys_call_table
+	PTR	sys_io_setup
+	PTR	sys_io_destroy
+	PTR	sys_io_getevents
+	PTR	sys_io_submit
+	PTR	sys_io_cancel			/* 4245 */
+	PTR	sys_exit_group
+	PTR	sys_lookup_dcookie
+	PTR	sys_epoll_create
+	PTR	sys_epoll_ctl
+	PTR	sys_epoll_wait			/* 4250 */
+	PTR	sys_remap_file_pages
+	PTR	sys_set_tid_address
+	PTR	sys_restart_syscall
+	PTR	sys_fadvise64_64
+	PTR	sys_statfs64			/* 4255 */
+	PTR	sys_fstatfs64
+	PTR	sys_timer_create
+	PTR	sys_timer_settime
+	PTR	sys_timer_gettime
+	PTR	sys_timer_getoverrun		/* 4260 */
+	PTR	sys_timer_delete
+	PTR	sys_clock_settime
+	PTR	sys_clock_gettime
+	PTR	sys_clock_getres
+	PTR	sys_clock_nanosleep		/* 4265 */
+	PTR	sys_tgkill
+	PTR	sys_utimes
+	PTR	sys_mbind
+	PTR	sys_ni_syscall			/* sys_get_mempolicy */
+	PTR	sys_ni_syscall			/* 4270 sys_set_mempolicy */
+	PTR	sys_mq_open
+	PTR	sys_mq_unlink
+	PTR	sys_mq_timedsend
+	PTR	sys_mq_timedreceive
+	PTR	sys_mq_notify			/* 4275 */
+	PTR	sys_mq_getsetattr
+	PTR	sys_ni_syscall			/* sys_vserver */
+	PTR	sys_waitid
+	PTR	sys_ni_syscall			/* available, was setaltroot */
+	PTR	sys_add_key			/* 4280 */
+	PTR	sys_request_key
+	PTR	sys_keyctl
+	PTR	sys_set_thread_area
+	PTR	sys_inotify_init
+	PTR	sys_inotify_add_watch		/* 4285 */
+	PTR	sys_inotify_rm_watch
+	PTR	sys_migrate_pages
+	PTR	sys_openat
+	PTR	sys_mkdirat
+	PTR	sys_mknodat			/* 4290 */
+	PTR	sys_fchownat
+	PTR	sys_futimesat
+	PTR	sys_fstatat64
+	PTR	sys_unlinkat
+	PTR	sys_renameat			/* 4295 */
+	PTR	sys_linkat
+	PTR	sys_symlinkat
+	PTR	sys_readlinkat
+	PTR	sys_fchmodat
+	PTR	sys_faccessat			/* 4300 */
+	PTR	sys_pselect6
+	PTR	sys_ppoll
+	PTR	sys_unshare
+	PTR	sys_splice
+	PTR	sys_sync_file_range		/* 4305 */
+	PTR	sys_tee
+	PTR	sys_vmsplice
+	PTR	sys_move_pages
+	PTR	sys_set_robust_list
+	PTR	sys_get_robust_list		/* 4310 */
+	PTR	sys_kexec_load
+	PTR	sys_getcpu
+	PTR	sys_epoll_pwait
+	PTR	sys_ioprio_set
+	PTR	sys_ioprio_get			/* 4315 */
+	PTR	sys_utimensat
+	PTR	sys_signalfd
+	PTR	sys_ni_syscall			/* was timerfd */
+	PTR	sys_eventfd
+	PTR	sys_fallocate			/* 4320 */
+	PTR	sys_timerfd_create
+	PTR	sys_timerfd_gettime
+	PTR	sys_timerfd_settime
+	PTR	sys_signalfd4
+	PTR	sys_eventfd2			/* 4325 */
+	PTR	sys_epoll_create1
+	PTR	sys_dup3
+	PTR	sys_pipe2
+	PTR	sys_inotify_init1
+	PTR	sys_preadv			/* 4330 */
+	PTR	sys_pwritev
+	PTR	sys_rt_tgsigqueueinfo
+	PTR	sys_perf_event_open
+	PTR	sys_accept4
+	PTR	sys_recvmmsg			/* 4335 */
+	PTR	sys_fanotify_init
+	PTR	sys_fanotify_mark
+	PTR	sys_prlimit64
+	PTR	sys_name_to_handle_at
+	PTR	sys_open_by_handle_at		/* 4340 */
+	PTR	sys_clock_adjtime
+	PTR	sys_syncfs
+	PTR	sys_sendmmsg
+	PTR	sys_setns
+	PTR	sys_process_vm_readv		/* 4345 */
+	PTR	sys_process_vm_writev
+	PTR	sys_kcmp
+	PTR	sys_finit_module
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index be6627e..57e3742 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -114,7 +114,8 @@
 	END(handle_sys64)
 
 	.align	3
-sys_call_table:
+	.type	sys_call_table, @object
+EXPORT(sys_call_table)
 	PTR	sys_read			/* 5000 */
 	PTR	sys_write
 	PTR	sys_open
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index cab1507..2f48f59 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -103,6 +103,7 @@
 
 	END(handle_sysn32)
 
+	.type	sysn32_call_table, @object
 EXPORT(sysn32_call_table)
 	PTR	sys_read			/* 6000 */
 	PTR	sys_write
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 37605dc..f1acdb4 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -53,7 +53,7 @@
 	sll	a3, a3, 0
 
 	dsll	t0, v0, 3		# offset into table
-	ld	t2, (sys_call_table - (__NR_O32_Linux * 8))(t0)
+	ld	t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
 
 	sd	a3, PT_R26(sp)		# save a3 for syscall restarting
 
@@ -168,7 +168,7 @@
 	beqz	t0, einval		# do not recurse
 	dsll	t1, t0, 3
 	beqz	v0, einval
-	ld	t2, sys_call_table(t1)		# syscall routine
+	ld	t2, sys32_call_table(t1)		# syscall routine
 
 	move	a0, a1			# shift argument registers
 	move	a1, a2
@@ -190,8 +190,8 @@
 	END(sys32_syscall)
 
 	.align	3
-	.type	sys_call_table,@object
-sys_call_table:
+	.type	sys32_call_table,@object
+EXPORT(sys32_call_table)
 	PTR	sys32_syscall			/* 4000 */
 	PTR	sys_exit
 	PTR	__sys_fork
@@ -541,4 +541,4 @@
 	PTR	compat_sys_process_vm_writev
 	PTR	sys_kcmp
 	PTR	sys_finit_module
-	.size	sys_call_table,.-sys_call_table
+	.size	sys32_call_table,.-sys32_call_table
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index c538d6e..a842154 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -300,12 +300,13 @@
 	int i;
 
 	/*
-	 * Init any data related to initrd. It's a nop if INITRD is
-	 * not selected. Once that done we can determine the low bound
-	 * of usable memory.
+	 * Sanity check any INITRD first. We don't take it into account
+	 * for bootmem setup initially, rely on the end-of-kernel-code
+	 * as our memory range starting point. Once bootmem is inited we
+	 * will reserve the area used for the initrd.
 	 */
-	reserved_end = max(init_initrd(),
-			   (unsigned long) PFN_UP(__pa_symbol(&_end)));
+	init_initrd();
+	reserved_end = (unsigned long) PFN_UP(__pa_symbol(&_end));
 
 	/*
 	 * max_low_pfn is not a number of pages. The number of pages
@@ -362,6 +363,14 @@
 		max_low_pfn = PFN_DOWN(HIGHMEM_START);
 	}
 
+#ifdef CONFIG_BLK_DEV_INITRD
+	/*
+	 * mapstart should be after initrd_end
+	 */
+	if (initrd_end)
+		mapstart = max(mapstart, (unsigned long)PFN_UP(__pa(initrd_end)));
+#endif
+
 	/*
 	 * Initialize the boot-time allocator with low memory only.
 	 */
diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c
index 126da74..2362665 100644
--- a/arch/mips/kernel/smp-bmips.c
+++ b/arch/mips/kernel/smp-bmips.c
@@ -136,10 +136,10 @@
 {
 	if (request_irq(IPI0_IRQ, bmips_ipi_interrupt, IRQF_PERCPU,
 			"smp_ipi0", NULL))
-		panic("Can't request IPI0 interrupt\n");
+		panic("Can't request IPI0 interrupt");
 	if (request_irq(IPI1_IRQ, bmips_ipi_interrupt, IRQF_PERCPU,
 			"smp_ipi1", NULL))
-		panic("Can't request IPI1 interrupt\n");
+		panic("Can't request IPI1 interrupt");
 }
 
 /*
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 5c208ed..0a022ee 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -150,7 +150,6 @@
 void __irq_entry smp_call_function_interrupt(void)
 {
 	irq_enter();
-	generic_smp_call_function_single_interrupt();
 	generic_smp_call_function_interrupt();
 	irq_exit();
 }
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 524841f..f9c8746 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -330,6 +330,7 @@
 void show_registers(struct pt_regs *regs)
 {
 	const int field = 2 * sizeof(unsigned long);
+	mm_segment_t old_fs = get_fs();
 
 	__show_regs(regs);
 	print_modules();
@@ -344,9 +345,13 @@
 			printk("*HwTLS: %0*lx\n", field, tls);
 	}
 
+	if (!user_mode(regs))
+		/* Necessary for getting the correct stack content */
+		set_fs(KERNEL_DS);
 	show_stacktrace(current, regs);
 	show_code((unsigned int __user *) regs->cp0_epc);
 	printk("\n");
+	set_fs(old_fs);
 }
 
 static int regs_to_trapnr(struct pt_regs *regs)
@@ -366,7 +371,8 @@
 
 	oops_enter();
 
-	if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV) == NOTIFY_STOP)
+	if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs),
+		       SIGSEGV) == NOTIFY_STOP)
 		sig = 0;
 
 	console_verbose();
@@ -457,8 +463,8 @@
 	printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n",
 	       data ? "Data" : "Instruction",
 	       field, regs->cp0_epc, field, regs->regs[31]);
-	if (notify_die(DIE_OOPS, "bus error", regs, 0, regs_to_trapnr(regs), SIGBUS)
-	    == NOTIFY_STOP)
+	if (notify_die(DIE_OOPS, "bus error", regs, 0, regs_to_trapnr(regs),
+		       SIGBUS) == NOTIFY_STOP)
 		goto out;
 
 	die_if_kernel("Oops", regs);
@@ -727,8 +733,8 @@
 	siginfo_t info = {0};
 
 	prev_state = exception_enter();
-	if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE)
-	    == NOTIFY_STOP)
+	if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs),
+		       SIGFPE) == NOTIFY_STOP)
 		goto out;
 	die_if_kernel("FP exception in kernel code", regs);
 
@@ -798,7 +804,8 @@
 		return;
 #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
 
-	if (notify_die(DIE_TRAP, str, regs, code, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
+	if (notify_die(DIE_TRAP, str, regs, code, regs_to_trapnr(regs),
+		       SIGTRAP) == NOTIFY_STOP)
 		return;
 
 	/*
@@ -892,12 +899,14 @@
 	 */
 	switch (bcode) {
 	case BRK_KPROBE_BP:
-		if (notify_die(DIE_BREAK, "debug", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
+		if (notify_die(DIE_BREAK, "debug", regs, bcode,
+			       regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
 			goto out;
 		else
 			break;
 	case BRK_KPROBE_SSTEPBP:
-		if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
+		if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode,
+			       regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
 			goto out;
 		else
 			break;
@@ -961,8 +970,8 @@
 	int status = -1;
 
 	prev_state = exception_enter();
-	if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs), SIGILL)
-	    == NOTIFY_STOP)
+	if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs),
+		       SIGILL) == NOTIFY_STOP)
 		goto out;
 
 	die_if_kernel("Reserved instruction in kernel code", regs);
@@ -1488,10 +1497,14 @@
 
 void __noreturn nmi_exception_handler(struct pt_regs *regs)
 {
+	char str[100];
+
 	raw_notifier_call_chain(&nmi_chain, 0, regs);
 	bust_spinlocks(1);
-	printk("NMI taken!!!!\n");
-	die("NMI", regs);
+	snprintf(str, 100, "CPU%d NMI taken, CP0_EPC=%lx\n",
+		 smp_processor_id(), regs->cp0_epc);
+	regs->cp0_epc = read_c0_errorepc();
+	die(str, regs);
 }
 
 #define VECTORSPACING 0x100	/* for EI/VI mode */
@@ -1554,7 +1567,6 @@
 	unsigned char *b;
 
 	BUG_ON(!cpu_has_veic && !cpu_has_vint);
-	BUG_ON((n < 0) && (n > 9));
 
 	if (addr == NULL) {
 		handler = (unsigned long) do_default_vi;
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index eb3e186..85685e1 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -390,7 +390,7 @@
 		ret = of_irq_to_resource_table(eiu_node,
 						ltq_eiu_irq, exin_avail);
 		if (ret != exin_avail)
-			panic("failed to load external irq resources\n");
+			panic("failed to load external irq resources");
 
 		if (request_mem_region(res.start, resource_size(&res),
 							res.name) < 0)
diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
index 49c4603..19686c5 100644
--- a/arch/mips/lantiq/prom.c
+++ b/arch/mips/lantiq/prom.c
@@ -14,6 +14,7 @@
 
 #include <asm/bootinfo.h>
 #include <asm/time.h>
+#include <asm/prom.h>
 
 #include <lantiq.h>
 
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
index c24924f..51804b1 100644
--- a/arch/mips/lantiq/xway/sysctrl.c
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -128,7 +128,7 @@
 	do {} while (--retry && (pmu_r32(PWDSR(clk->module)) & clk->bits));
 
 	if (!retry)
-		panic("activating PMU module failed!\n");
+		panic("activating PMU module failed!");
 
 	return 0;
 }
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index bc6f96f..62ffd20 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -346,14 +346,8 @@
 
 static inline void local_r4k___flush_cache_all(void * args)
 {
-#if defined(CONFIG_CPU_LOONGSON2)
-	r4k_blast_scache();
-	return;
-#endif
-	r4k_blast_dcache();
-	r4k_blast_icache();
-
 	switch (current_cpu_type()) {
+	case CPU_LOONGSON2:
 	case CPU_R4000SC:
 	case CPU_R4000MC:
 	case CPU_R4400SC:
@@ -361,7 +355,18 @@
 	case CPU_R10000:
 	case CPU_R12000:
 	case CPU_R14000:
+		/*
+		 * These caches are inclusive caches, that is, if something
+		 * is not cached in the S-cache, we know it also won't be
+		 * in one of the primary caches.
+		 */
 		r4k_blast_scache();
+		break;
+
+	default:
+		r4k_blast_dcache();
+		r4k_blast_icache();
+		break;
 	}
 }
 
@@ -572,8 +577,17 @@
 
 	if (end - start > icache_size)
 		r4k_blast_icache();
-	else
-		protected_blast_icache_range(start, end);
+	else {
+		switch (boot_cpu_type()) {
+		case CPU_LOONGSON2:
+			protected_blast_icache_range(start, end);
+			break;
+
+		default:
+			protected_loongson23_blast_icache_range(start, end);
+			break;
+		}
+	}
 }
 
 static inline void local_r4k_flush_icache_range_ipi(void *args)
@@ -1109,15 +1123,14 @@
 	case CPU_ALCHEMY:
 		c->icache.flags |= MIPS_CACHE_IC_F_DC;
 		break;
-	}
 
-#ifdef	CONFIG_CPU_LOONGSON2
-	/*
-	 * LOONGSON2 has 4 way icache, but when using indexed cache op,
-	 * one op will act on all 4 ways
-	 */
-	c->icache.ways = 1;
-#endif
+	case CPU_LOONGSON2:
+		/*
+		 * LOONGSON2 has 4 way icache, but when using indexed cache op,
+		 * one op will act on all 4 ways
+		 */
+		c->icache.ways = 1;
+	}
 
 	printk("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n",
 	       icache_size >> 10,
@@ -1193,7 +1206,6 @@
 	return 1;
 }
 
-#if defined(CONFIG_CPU_LOONGSON2)
 static void __init loongson2_sc_init(void)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
@@ -1209,7 +1221,6 @@
 
 	c->options |= MIPS_CPU_INCLUSIVE_CACHES;
 }
-#endif
 
 extern int r5k_sc_init(void);
 extern int rm7k_sc_init(void);
@@ -1259,11 +1270,10 @@
 #endif
 		return;
 
-#if defined(CONFIG_CPU_LOONGSON2)
 	case CPU_LOONGSON2:
 		loongson2_sc_init();
 		return;
-#endif
+
 	case CPU_XLP:
 		/* don't need to worry about L2, fully coherent */
 		return;
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 5f8b955..2e94185 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -297,7 +297,6 @@
 static void mips_dma_sync_single_for_device(struct device *dev,
 	dma_addr_t dma_handle, size_t size, enum dma_data_direction direction)
 {
-	plat_extra_sync_for_device(dev);
 	if (!plat_device_is_coherent(dev))
 		__dma_sync(dma_addr_to_page(dev, dma_handle),
 			   dma_handle & ~PAGE_MASK, size, direction);
@@ -327,7 +326,7 @@
 
 int mips_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
-	return plat_dma_mapping_error(dev, dma_addr);
+	return 0;
 }
 
 int mips_dma_supported(struct device *dev, u64 mask)
@@ -340,7 +339,6 @@
 {
 	BUG_ON(direction == DMA_NONE);
 
-	plat_extra_sync_for_device(dev);
 	if (!plat_device_is_coherent(dev))
 		__dma_sync_virtual(vaddr, size, direction);
 }
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index e205ef5..1215617 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -124,7 +124,7 @@
 
 	BUG_ON(Page_dcache_dirty(page));
 
-	inc_preempt_count();
+	pagefault_disable();
 	idx = (addr >> PAGE_SHIFT) & (FIX_N_COLOURS - 1);
 #ifdef CONFIG_MIPS_MT_SMTC
 	idx += FIX_N_COLOURS * smp_processor_id() +
@@ -193,8 +193,7 @@
 	write_c0_entryhi(old_ctx);
 	EXIT_CRITICAL(flags);
 #endif
-	dec_preempt_count();
-	preempt_check_resched();
+	pagefault_enable();
 }
 
 void copy_user_highpage(struct page *to, struct page *from,
diff --git a/arch/mips/mm/tlb-funcs.S b/arch/mips/mm/tlb-funcs.S
index 79bca31..30a494d 100644
--- a/arch/mips/mm/tlb-funcs.S
+++ b/arch/mips/mm/tlb-funcs.S
@@ -16,12 +16,10 @@
 
 #define FASTPATH_SIZE	128
 
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 LEAF(tlbmiss_handler_setup_pgd)
 	.space		16 * 4
 END(tlbmiss_handler_setup_pgd)
 EXPORT(tlbmiss_handler_setup_pgd_end)
-#endif
 
 LEAF(handle_tlbm)
 	.space		FASTPATH_SIZE * 4
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index bb3a5f64..da3b0b9 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -52,21 +52,26 @@
 
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-#if defined(CONFIG_CPU_LOONGSON2)
 /*
  * LOONGSON2 has a 4 entry itlb which is a subset of dtlb,
  * unfortrunately, itlb is not totally transparent to software.
  */
-#define FLUSH_ITLB write_c0_diag(4);
+static inline void flush_itlb(void)
+{
+	switch (current_cpu_type()) {
+	case CPU_LOONGSON2:
+		write_c0_diag(4);
+		break;
+	default:
+		break;
+	}
+}
 
-#define FLUSH_ITLB_VM(vma) { if ((vma)->vm_flags & VM_EXEC)  write_c0_diag(4); }
-
-#else
-
-#define FLUSH_ITLB
-#define FLUSH_ITLB_VM(vma)
-
-#endif
+static inline void flush_itlb_vm(struct vm_area_struct *vma)
+{
+	if (vma->vm_flags & VM_EXEC)
+		flush_itlb();
+}
 
 void local_flush_tlb_all(void)
 {
@@ -93,7 +98,7 @@
 	}
 	tlbw_use_hazard();
 	write_c0_entryhi(old_ctx);
-	FLUSH_ITLB;
+	flush_itlb();
 	EXIT_CRITICAL(flags);
 }
 EXPORT_SYMBOL(local_flush_tlb_all);
@@ -155,7 +160,7 @@
 		} else {
 			drop_mmu_context(mm, cpu);
 		}
-		FLUSH_ITLB;
+		flush_itlb();
 		EXIT_CRITICAL(flags);
 	}
 }
@@ -197,7 +202,7 @@
 	} else {
 		local_flush_tlb_all();
 	}
-	FLUSH_ITLB;
+	flush_itlb();
 	EXIT_CRITICAL(flags);
 }
 
@@ -230,7 +235,7 @@
 
 	finish:
 		write_c0_entryhi(oldpid);
-		FLUSH_ITLB_VM(vma);
+		flush_itlb_vm(vma);
 		EXIT_CRITICAL(flags);
 	}
 }
@@ -262,7 +267,7 @@
 		tlbw_use_hazard();
 	}
 	write_c0_entryhi(oldpid);
-	FLUSH_ITLB;
+	flush_itlb();
 	EXIT_CRITICAL(flags);
 }
 
@@ -335,7 +340,7 @@
 			tlb_write_indexed();
 	}
 	tlbw_use_hazard();
-	FLUSH_ITLB_VM(vma);
+	flush_itlb_vm(vma);
 	EXIT_CRITICAL(flags);
 }
 
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 9bb3a93..183f2b5 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -340,10 +340,6 @@
 {
 	struct work_registers r;
 
-	int smp_processor_id_reg;
-	int smp_processor_id_sel;
-	int smp_processor_id_shift;
-
 	if (scratch_reg >= 0) {
 		/* Save in CPU local C0_KScratch? */
 		UASM_i_MTC0(p, 1, c0_kscratch(), scratch_reg);
@@ -354,25 +350,9 @@
 	}
 
 	if (num_possible_cpus() > 1) {
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
-		smp_processor_id_shift = 51;
-		smp_processor_id_reg = 20; /* XContext */
-		smp_processor_id_sel = 0;
-#else
-# ifdef CONFIG_32BIT
-		smp_processor_id_shift = 25;
-		smp_processor_id_reg = 4; /* Context */
-		smp_processor_id_sel = 0;
-# endif
-# ifdef CONFIG_64BIT
-		smp_processor_id_shift = 26;
-		smp_processor_id_reg = 4; /* Context */
-		smp_processor_id_sel = 0;
-# endif
-#endif
 		/* Get smp_processor_id */
-		UASM_i_MFC0(p, K0, smp_processor_id_reg, smp_processor_id_sel);
-		UASM_i_SRL_SAFE(p, K0, K0, smp_processor_id_shift);
+		UASM_i_CPUID_MFC0(p, K0, SMP_CPUID_REG);
+		UASM_i_SRL_SAFE(p, K0, K0, SMP_CPUID_REGSHIFT);
 
 		/* handler_reg_save index in K0 */
 		UASM_i_SLL(p, K0, K0, ilog2(sizeof(struct tlb_reg_save)));
@@ -819,11 +799,11 @@
 	}
 	/* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */
 
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 	if (pgd_reg != -1) {
 		/* pgd is in pgd_reg */
 		UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg);
 	} else {
+#if defined(CONFIG_MIPS_PGD_C0_CONTEXT)
 		/*
 		 * &pgd << 11 stored in CONTEXT [23..63].
 		 */
@@ -835,30 +815,18 @@
 		/* 1 0	1 0 1  << 6  xkphys cached */
 		uasm_i_ori(p, ptr, ptr, 0x540);
 		uasm_i_drotr(p, ptr, ptr, 11);
-	}
 #elif defined(CONFIG_SMP)
-# ifdef	 CONFIG_MIPS_MT_SMTC
-	/*
-	 * SMTC uses TCBind value as "CPU" index
-	 */
-	uasm_i_mfc0(p, ptr, C0_TCBIND);
-	uasm_i_dsrl_safe(p, ptr, ptr, 19);
-# else
-	/*
-	 * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
-	 * stored in CONTEXT.
-	 */
-	uasm_i_dmfc0(p, ptr, C0_CONTEXT);
-	uasm_i_dsrl_safe(p, ptr, ptr, 23);
-# endif
-	UASM_i_LA_mostly(p, tmp, pgdc);
-	uasm_i_daddu(p, ptr, ptr, tmp);
-	uasm_i_dmfc0(p, tmp, C0_BADVADDR);
-	uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
+		UASM_i_CPUID_MFC0(p, ptr, SMP_CPUID_REG);
+		uasm_i_dsrl_safe(p, ptr, ptr, SMP_CPUID_PTRSHIFT);
+		UASM_i_LA_mostly(p, tmp, pgdc);
+		uasm_i_daddu(p, ptr, ptr, tmp);
+		uasm_i_dmfc0(p, tmp, C0_BADVADDR);
+		uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
 #else
-	UASM_i_LA_mostly(p, ptr, pgdc);
-	uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
+		UASM_i_LA_mostly(p, ptr, pgdc);
+		uasm_i_ld(p, ptr, uasm_rel_lo(pgdc), ptr);
 #endif
+	}
 
 	uasm_l_vmalloc_done(l, *p);
 
@@ -953,31 +921,25 @@
 static void __maybe_unused
 build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
 {
-	long pgdc = (long)pgd_current;
+	if (pgd_reg != -1) {
+		/* pgd is in pgd_reg */
+		uasm_i_mfc0(p, ptr, c0_kscratch(), pgd_reg);
+		uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
+	} else {
+		long pgdc = (long)pgd_current;
 
-	/* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
+		/* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
 #ifdef CONFIG_SMP
-#ifdef	CONFIG_MIPS_MT_SMTC
-	/*
-	 * SMTC uses TCBind value as "CPU" index
-	 */
-	uasm_i_mfc0(p, ptr, C0_TCBIND);
-	UASM_i_LA_mostly(p, tmp, pgdc);
-	uasm_i_srl(p, ptr, ptr, 19);
+		uasm_i_mfc0(p, ptr, SMP_CPUID_REG);
+		UASM_i_LA_mostly(p, tmp, pgdc);
+		uasm_i_srl(p, ptr, ptr, SMP_CPUID_PTRSHIFT);
+		uasm_i_addu(p, ptr, tmp, ptr);
 #else
-	/*
-	 * smp_processor_id() << 2 is stored in CONTEXT.
-	 */
-	uasm_i_mfc0(p, ptr, C0_CONTEXT);
-	UASM_i_LA_mostly(p, tmp, pgdc);
-	uasm_i_srl(p, ptr, ptr, 23);
+		UASM_i_LA_mostly(p, ptr, pgdc);
 #endif
-	uasm_i_addu(p, ptr, tmp, ptr);
-#else
-	UASM_i_LA_mostly(p, ptr, pgdc);
-#endif
-	uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
-	uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr);
+		uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
+		uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr);
+	}
 	uasm_i_srl(p, tmp, tmp, PGDIR_SHIFT); /* get pgd only bits */
 	uasm_i_sll(p, tmp, tmp, PGD_T_LOG2);
 	uasm_i_addu(p, ptr, ptr, tmp); /* add in pgd offset */
@@ -1349,95 +1311,100 @@
 	 * need three, with the second nop'ed and the third being
 	 * unused.
 	 */
-	/* Loongson2 ebase is different than r4k, we have more space */
-#if defined(CONFIG_32BIT) || defined(CONFIG_CPU_LOONGSON2)
-	if ((p - tlb_handler) > 64)
-		panic("TLB refill handler space exceeded");
-#else
-	if (((p - tlb_handler) > (MIPS64_REFILL_INSNS * 2) - 1)
-	    || (((p - tlb_handler) > (MIPS64_REFILL_INSNS * 2) - 3)
-		&& uasm_insn_has_bdelay(relocs,
-					tlb_handler + MIPS64_REFILL_INSNS - 3)))
-		panic("TLB refill handler space exceeded");
-#endif
-
-	/*
-	 * Now fold the handler in the TLB refill handler space.
-	 */
-#if defined(CONFIG_32BIT) || defined(CONFIG_CPU_LOONGSON2)
-	f = final_handler;
-	/* Simplest case, just copy the handler. */
-	uasm_copy_handler(relocs, labels, tlb_handler, p, f);
-	final_len = p - tlb_handler;
-#else /* CONFIG_64BIT */
-	f = final_handler + MIPS64_REFILL_INSNS;
-	if ((p - tlb_handler) <= MIPS64_REFILL_INSNS) {
-		/* Just copy the handler. */
-		uasm_copy_handler(relocs, labels, tlb_handler, p, f);
-		final_len = p - tlb_handler;
-	} else {
+	switch (boot_cpu_type()) {
+	default:
+		if (sizeof(long) == 4) {
+	case CPU_LOONGSON2:
+		/* Loongson2 ebase is different than r4k, we have more space */
+			if ((p - tlb_handler) > 64)
+				panic("TLB refill handler space exceeded");
+			/*
+			 * Now fold the handler in the TLB refill handler space.
+			 */
+			f = final_handler;
+			/* Simplest case, just copy the handler. */
+			uasm_copy_handler(relocs, labels, tlb_handler, p, f);
+			final_len = p - tlb_handler;
+			break;
+		} else {
+			if (((p - tlb_handler) > (MIPS64_REFILL_INSNS * 2) - 1)
+			    || (((p - tlb_handler) > (MIPS64_REFILL_INSNS * 2) - 3)
+				&& uasm_insn_has_bdelay(relocs,
+							tlb_handler + MIPS64_REFILL_INSNS - 3)))
+				panic("TLB refill handler space exceeded");
+			/*
+			 * Now fold the handler in the TLB refill handler space.
+			 */
+			f = final_handler + MIPS64_REFILL_INSNS;
+			if ((p - tlb_handler) <= MIPS64_REFILL_INSNS) {
+				/* Just copy the handler. */
+				uasm_copy_handler(relocs, labels, tlb_handler, p, f);
+				final_len = p - tlb_handler;
+			} else {
 #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
-		const enum label_id ls = label_tlb_huge_update;
+				const enum label_id ls = label_tlb_huge_update;
 #else
-		const enum label_id ls = label_vmalloc;
+				const enum label_id ls = label_vmalloc;
 #endif
-		u32 *split;
-		int ov = 0;
-		int i;
+				u32 *split;
+				int ov = 0;
+				int i;
 
-		for (i = 0; i < ARRAY_SIZE(labels) && labels[i].lab != ls; i++)
-			;
-		BUG_ON(i == ARRAY_SIZE(labels));
-		split = labels[i].addr;
+				for (i = 0; i < ARRAY_SIZE(labels) && labels[i].lab != ls; i++)
+					;
+				BUG_ON(i == ARRAY_SIZE(labels));
+				split = labels[i].addr;
 
-		/*
-		 * See if we have overflown one way or the other.
-		 */
-		if (split > tlb_handler + MIPS64_REFILL_INSNS ||
-		    split < p - MIPS64_REFILL_INSNS)
-			ov = 1;
+				/*
+				 * See if we have overflown one way or the other.
+				 */
+				if (split > tlb_handler + MIPS64_REFILL_INSNS ||
+				    split < p - MIPS64_REFILL_INSNS)
+					ov = 1;
 
-		if (ov) {
-			/*
-			 * Split two instructions before the end.  One
-			 * for the branch and one for the instruction
-			 * in the delay slot.
-			 */
-			split = tlb_handler + MIPS64_REFILL_INSNS - 2;
+				if (ov) {
+					/*
+					 * Split two instructions before the end.  One
+					 * for the branch and one for the instruction
+					 * in the delay slot.
+					 */
+					split = tlb_handler + MIPS64_REFILL_INSNS - 2;
 
-			/*
-			 * If the branch would fall in a delay slot,
-			 * we must back up an additional instruction
-			 * so that it is no longer in a delay slot.
-			 */
-			if (uasm_insn_has_bdelay(relocs, split - 1))
-				split--;
-		}
-		/* Copy first part of the handler. */
-		uasm_copy_handler(relocs, labels, tlb_handler, split, f);
-		f += split - tlb_handler;
+					/*
+					 * If the branch would fall in a delay slot,
+					 * we must back up an additional instruction
+					 * so that it is no longer in a delay slot.
+					 */
+					if (uasm_insn_has_bdelay(relocs, split - 1))
+						split--;
+				}
+				/* Copy first part of the handler. */
+				uasm_copy_handler(relocs, labels, tlb_handler, split, f);
+				f += split - tlb_handler;
 
-		if (ov) {
-			/* Insert branch. */
-			uasm_l_split(&l, final_handler);
-			uasm_il_b(&f, &r, label_split);
-			if (uasm_insn_has_bdelay(relocs, split))
-				uasm_i_nop(&f);
-			else {
-				uasm_copy_handler(relocs, labels,
-						  split, split + 1, f);
-				uasm_move_labels(labels, f, f + 1, -1);
-				f++;
-				split++;
+				if (ov) {
+					/* Insert branch. */
+					uasm_l_split(&l, final_handler);
+					uasm_il_b(&f, &r, label_split);
+					if (uasm_insn_has_bdelay(relocs, split))
+						uasm_i_nop(&f);
+					else {
+						uasm_copy_handler(relocs, labels,
+								  split, split + 1, f);
+						uasm_move_labels(labels, f, f + 1, -1);
+						f++;
+						split++;
+					}
+				}
+
+				/* Copy the rest of the handler. */
+				uasm_copy_handler(relocs, labels, split, p, final_handler);
+				final_len = (f - (final_handler + MIPS64_REFILL_INSNS)) +
+					    (p - split);
 			}
 		}
-
-		/* Copy the rest of the handler. */
-		uasm_copy_handler(relocs, labels, split, p, final_handler);
-		final_len = (f - (final_handler + MIPS64_REFILL_INSNS)) +
-			    (p - split);
+		break;
 	}
-#endif /* CONFIG_64BIT */
 
 	uasm_resolve_relocs(relocs, labels);
 	pr_debug("Wrote TLB refill handler (%u instructions).\n",
@@ -1451,28 +1418,30 @@
 extern u32 handle_tlbl[], handle_tlbl_end[];
 extern u32 handle_tlbs[], handle_tlbs_end[];
 extern u32 handle_tlbm[], handle_tlbm_end[];
-
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 extern u32 tlbmiss_handler_setup_pgd[], tlbmiss_handler_setup_pgd_end[];
 
-static void build_r4000_setup_pgd(void)
+static void build_setup_pgd(void)
 {
 	const int a0 = 4;
-	const int a1 = 5;
+	const int __maybe_unused a1 = 5;
+	const int __maybe_unused a2 = 6;
 	u32 *p = tlbmiss_handler_setup_pgd;
 	const int tlbmiss_handler_setup_pgd_size =
 		tlbmiss_handler_setup_pgd_end - tlbmiss_handler_setup_pgd;
-	struct uasm_label *l = labels;
-	struct uasm_reloc *r = relocs;
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
+	long pgdc = (long)pgd_current;
+#endif
 
 	memset(tlbmiss_handler_setup_pgd, 0, tlbmiss_handler_setup_pgd_size *
 					sizeof(tlbmiss_handler_setup_pgd[0]));
 	memset(labels, 0, sizeof(labels));
 	memset(relocs, 0, sizeof(relocs));
-
 	pgd_reg = allocate_kscratch();
-
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 	if (pgd_reg == -1) {
+		struct uasm_label *l = labels;
+		struct uasm_reloc *r = relocs;
+
 		/* PGD << 11 in c0_Context */
 		/*
 		 * If it is a ckseg0 address, convert to a physical
@@ -1494,6 +1463,26 @@
 		uasm_i_jr(&p, 31);
 		UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
 	}
+#else
+#ifdef CONFIG_SMP
+	/* Save PGD to pgd_current[smp_processor_id()] */
+	UASM_i_CPUID_MFC0(&p, a1, SMP_CPUID_REG);
+	UASM_i_SRL_SAFE(&p, a1, a1, SMP_CPUID_PTRSHIFT);
+	UASM_i_LA_mostly(&p, a2, pgdc);
+	UASM_i_ADDU(&p, a2, a2, a1);
+	UASM_i_SW(&p, a0, uasm_rel_lo(pgdc), a2);
+#else
+	UASM_i_LA_mostly(&p, a2, pgdc);
+	UASM_i_SW(&p, a0, uasm_rel_lo(pgdc), a2);
+#endif /* SMP */
+	uasm_i_jr(&p, 31);
+
+	/* if pgd_reg is allocated, save PGD also to scratch register */
+	if (pgd_reg != -1)
+		UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
+	else
+		uasm_i_nop(&p);
+#endif
 	if (p >= tlbmiss_handler_setup_pgd_end)
 		panic("tlbmiss_handler_setup_pgd space exceeded");
 
@@ -1504,7 +1493,6 @@
 	dump_handler("tlbmiss_handler", tlbmiss_handler_setup_pgd,
 					tlbmiss_handler_setup_pgd_size);
 }
-#endif
 
 static void
 iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr)
@@ -2197,10 +2185,8 @@
 			   (unsigned long)handle_tlbs_end);
 	local_flush_icache_range((unsigned long)handle_tlbm,
 			   (unsigned long)handle_tlbm_end);
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
 	local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd,
 			   (unsigned long)tlbmiss_handler_setup_pgd_end);
-#endif
 }
 
 void build_tlb_refill_handler(void)
@@ -2232,6 +2218,7 @@
 		if (!run_once) {
 			if (!cpu_has_local_ebase)
 				build_r3000_tlb_refill_handler();
+			build_setup_pgd();
 			build_r3000_tlb_load_handler();
 			build_r3000_tlb_store_handler();
 			build_r3000_tlb_modify_handler();
@@ -2255,9 +2242,7 @@
 	default:
 		if (!run_once) {
 			scratch_reg = allocate_kscratch();
-#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
-			build_r4000_setup_pgd();
-#endif
+			build_setup_pgd();
 			build_r4000_tlb_load_handler();
 			build_r4000_tlb_store_handler();
 			build_r4000_tlb_modify_handler();
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index c69da37..0892575 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -37,7 +37,6 @@
 #include <asm/irq_regs.h>
 #include <asm/mips-boards/malta.h>
 #include <asm/mips-boards/maltaint.h>
-#include <asm/mips-boards/piix4.h>
 #include <asm/gt64120.h>
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/msc01_pci.h>
@@ -473,7 +472,7 @@
 {
 	int cpu;
 
-	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+	for (cpu = 0; cpu < nr_cpu_ids; cpu++) {
 		fill_ipi_map1(gic_resched_int_base, cpu, GIC_CPU_INT1);
 		fill_ipi_map1(gic_call_int_base, cpu, GIC_CPU_INT2);
 	}
@@ -574,8 +573,9 @@
 		/* FIXME */
 		int i;
 #if defined(CONFIG_MIPS_MT_SMP)
-		gic_call_int_base = GIC_NUM_INTRS - NR_CPUS;
-		gic_resched_int_base = gic_call_int_base - NR_CPUS;
+		gic_call_int_base = GIC_NUM_INTRS -
+			(NR_CPUS - nr_cpu_ids) * 2 - nr_cpu_ids;
+		gic_resched_int_base = gic_call_int_base - nr_cpu_ids;
 		fill_ipi_map();
 #endif
 		gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map,
@@ -599,7 +599,7 @@
 		printk("CPU%d: status register now %08x\n", smp_processor_id(), read_c0_status());
 		write_c0_status(0x1100dc00);
 		printk("CPU%d: status register frc %08x\n", smp_processor_id(), read_c0_status());
-		for (i = 0; i < NR_CPUS; i++) {
+		for (i = 0; i < nr_cpu_ids; i++) {
 			arch_init_ipiirq(MIPS_GIC_IRQ_BASE +
 					 GIC_RESCHED_INT(i), &irq_resched);
 			arch_init_ipiirq(MIPS_GIC_IRQ_BASE +
diff --git a/arch/mips/mti-sead3/sead3-setup.c b/arch/mips/mti-sead3/sead3-setup.c
index b5059dc..928ba84 100644
--- a/arch/mips/mti-sead3/sead3-setup.c
+++ b/arch/mips/mti-sead3/sead3-setup.c
@@ -10,6 +10,8 @@
 #include <linux/of_fdt.h>
 #include <linux/bootmem.h>
 
+#include <asm/prom.h>
+
 #include <asm/mips-boards/generic.h>
 
 const char *get_system_type(void)
diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c
index 6f8feb9..c0eded0 100644
--- a/arch/mips/netlogic/common/smp.c
+++ b/arch/mips/netlogic/common/smp.c
@@ -245,7 +245,7 @@
 	return threadmode;
 
 unsupp:
-	panic("Unsupported CPU mask %lx\n",
+	panic("Unsupported CPU mask %lx",
 		(unsigned long)cpumask_bits(wakeup_mask)[0]);
 	return 0;
 }
diff --git a/arch/mips/netlogic/xlp/dt.c b/arch/mips/netlogic/xlp/dt.c
index 88df445..8316d54 100644
--- a/arch/mips/netlogic/xlp/dt.c
+++ b/arch/mips/netlogic/xlp/dt.c
@@ -39,8 +39,11 @@
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
 
+#include <asm/prom.h>
+
 extern u32 __dtb_xlp_evp_begin[], __dtb_xlp_svp_begin[],
 	__dtb_xlp_fvp_begin[], __dtb_start[];
+static void *xlp_fdt_blob;
 
 void __init *xlp_dt_init(void *fdtp)
 {
@@ -67,19 +70,26 @@
 			break;
 		}
 	}
-	initial_boot_params = fdtp;
+	xlp_fdt_blob = fdtp;
 	return fdtp;
 }
 
+void __init xlp_early_init_devtree(void)
+{
+	__dt_setup_arch(xlp_fdt_blob);
+	strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
+}
+
 void __init device_tree_init(void)
 {
 	unsigned long base, size;
+	struct boot_param_header *fdtp = xlp_fdt_blob;
 
-	if (!initial_boot_params)
+	if (!fdtp)
 		return;
 
-	base = virt_to_phys((void *)initial_boot_params);
-	size = be32_to_cpu(initial_boot_params->totalsize);
+	base = virt_to_phys(fdtp);
+	size = be32_to_cpu(fdtp->totalsize);
 
 	/* Before we do anything, lets reserve the dt blob */
 	reserve_bootmem(base, size, BOOTMEM_DEFAULT);
diff --git a/arch/mips/netlogic/xlp/setup.c b/arch/mips/netlogic/xlp/setup.c
index 76a7131..6d981bb 100644
--- a/arch/mips/netlogic/xlp/setup.c
+++ b/arch/mips/netlogic/xlp/setup.c
@@ -98,7 +98,7 @@
 	pm_power_off	= nlm_linux_exit;
 
 	/* memory and bootargs from DT */
-	early_init_devtree(initial_boot_params);
+	xlp_early_init_devtree();
 
 	if (boot_mem_map.nr_map == 0) {
 		pr_info("Using DRAM BARs for memory map.\n");
diff --git a/arch/mips/pci/fixup-lantiq.c b/arch/mips/pci/fixup-lantiq.c
index 6c829df..c2ce41e 100644
--- a/arch/mips/pci/fixup-lantiq.c
+++ b/arch/mips/pci/fixup-lantiq.c
@@ -25,16 +25,5 @@
 
 int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-	struct of_irq dev_irq;
-	int irq;
-
-	if (of_irq_map_pci(dev, &dev_irq)) {
-		dev_err(&dev->dev, "trying to map irq for unknown slot:%d pin:%d\n",
-			slot, pin);
-		return 0;
-	}
-	irq = irq_create_of_mapping(dev_irq.controller, dev_irq.specifier,
-					dev_irq.size);
-	dev_info(&dev->dev, "SLOT:%d PIN:%d IRQ:%d\n", slot, pin, irq);
-	return irq;
+	return of_irq_parse_and_map_pci(dev, slot, pin);
 }
diff --git a/arch/mips/pci/fixup-malta.c b/arch/mips/pci/fixup-malta.c
index 07ada7f..df36e23 100644
--- a/arch/mips/pci/fixup-malta.c
+++ b/arch/mips/pci/fixup-malta.c
@@ -1,5 +1,6 @@
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <asm/mips-boards/piix4.h>
 
 /* PCI interrupt pins */
 #define PCIA		1
@@ -53,7 +54,8 @@
 static void malta_piix_func0_fixup(struct pci_dev *pdev)
 {
 	unsigned char reg_val;
-	static int piixirqmap[16] = {  /* PIIX PIRQC[A:D] irq mappings */
+	/* PIIX PIRQC[A:D] irq mappings */
+	static int piixirqmap[PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_MAX] = {
 		0,  0,	0,  3,
 		4,  5,	6,  7,
 		0,  9, 10, 11,
@@ -63,11 +65,12 @@
 
 	/* Interrogate PIIX4 to get PCI IRQ mapping */
 	for (i = 0; i <= 3; i++) {
-		pci_read_config_byte(pdev, 0x60+i, &reg_val);
-		if (reg_val & 0x80)
+		pci_read_config_byte(pdev, PIIX4_FUNC0_PIRQRC+i, &reg_val);
+		if (reg_val & PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_DISABLE)
 			pci_irq[PCIA+i] = 0;	/* Disabled */
 		else
-			pci_irq[PCIA+i] = piixirqmap[reg_val & 15];
+			pci_irq[PCIA+i] = piixirqmap[reg_val &
+				PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_MASK];
 	}
 
 	/* Done by YAMON 2.00 onwards */
@@ -76,8 +79,9 @@
 		 * Set top of main memory accessible by ISA or DMA
 		 * devices to 16 Mb.
 		 */
-		pci_read_config_byte(pdev, 0x69, &reg_val);
-		pci_write_config_byte(pdev, 0x69, reg_val | 0xf0);
+		pci_read_config_byte(pdev, PIIX4_FUNC0_TOM, &reg_val);
+		pci_write_config_byte(pdev, PIIX4_FUNC0_TOM, reg_val |
+				PIIX4_FUNC0_TOM_TOP_OF_MEMORY_MASK);
 	}
 }
 
@@ -93,10 +97,14 @@
 		/*
 		 * IDE Decode enable.
 		 */
-		pci_read_config_byte(pdev, 0x41, &reg_val);
-		pci_write_config_byte(pdev, 0x41, reg_val|0x80);
-		pci_read_config_byte(pdev, 0x43, &reg_val);
-		pci_write_config_byte(pdev, 0x43, reg_val|0x80);
+		pci_read_config_byte(pdev, PIIX4_FUNC1_IDETIM_PRIMARY_HI,
+			&reg_val);
+		pci_write_config_byte(pdev, PIIX4_FUNC1_IDETIM_PRIMARY_HI,
+			reg_val|PIIX4_FUNC1_IDETIM_PRIMARY_HI_IDE_DECODE_EN);
+		pci_read_config_byte(pdev, PIIX4_FUNC1_IDETIM_SECONDARY_HI,
+			&reg_val);
+		pci_write_config_byte(pdev, PIIX4_FUNC1_IDETIM_SECONDARY_HI,
+			reg_val|PIIX4_FUNC1_IDETIM_SECONDARY_HI_IDE_DECODE_EN);
 	}
 }
 
@@ -108,10 +116,12 @@
 {
 	u8 odlc, ndlc;
 
-	(void) pci_read_config_byte(dev, 0x82, &odlc);
+	(void) pci_read_config_byte(dev, PIIX4_FUNC0_DLC, &odlc);
 	/* Enable passive releases and delayed transaction */
-	ndlc = odlc | 7;
-	(void) pci_write_config_byte(dev, 0x82, ndlc);
+	ndlc = odlc | PIIX4_FUNC0_DLC_USBPR_EN |
+		      PIIX4_FUNC0_DLC_PASSIVE_RELEASE_EN |
+		      PIIX4_FUNC0_DLC_DELAYED_TRANSACTION_EN;
+	(void) pci_write_config_byte(dev, PIIX4_FUNC0_DLC, ndlc);
 }
 
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
diff --git a/arch/mips/pci/pci-ar71xx.c b/arch/mips/pci/pci-ar71xx.c
index 18517dd..d471a26 100644
--- a/arch/mips/pci/pci-ar71xx.c
+++ b/arch/mips/pci/pci-ar71xx.c
@@ -363,9 +363,6 @@
 	spin_lock_init(&apc->lock);
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base");
-	if (!res)
-		return -EINVAL;
-
 	apc->cfg_base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(apc->cfg_base))
 		return PTR_ERR(apc->cfg_base);
diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
index 65ec032..785b265 100644
--- a/arch/mips/pci/pci-ar724x.c
+++ b/arch/mips/pci/pci-ar724x.c
@@ -362,25 +362,16 @@
 		return -ENOMEM;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl_base");
-	if (!res)
-		return -EINVAL;
-
 	apc->ctrl_base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(apc->ctrl_base))
 		return PTR_ERR(apc->ctrl_base);
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base");
-	if (!res)
-		return -EINVAL;
-
 	apc->devcfg_base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(apc->devcfg_base))
 		return PTR_ERR(apc->devcfg_base);
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "crp_base");
-	if (!res)
-		return -EINVAL;
-
 	apc->crp_base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(apc->crp_base))
 		return PTR_ERR(apc->crp_base);
diff --git a/arch/mips/pci/pci-rt3883.c b/arch/mips/pci/pci-rt3883.c
index 95c9d41..adeff2b 100644
--- a/arch/mips/pci/pci-rt3883.c
+++ b/arch/mips/pci/pci-rt3883.c
@@ -583,29 +583,7 @@
 
 int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-	struct of_irq dev_irq;
-	int err;
-	int irq;
-
-	err = of_irq_map_pci(dev, &dev_irq);
-	if (err) {
-		pr_err("pci %s: unable to get irq map, err=%d\n",
-		       pci_name((struct pci_dev *) dev), err);
-		return 0;
-	}
-
-	irq = irq_create_of_mapping(dev_irq.controller,
-				    dev_irq.specifier,
-				    dev_irq.size);
-
-	if (irq == 0)
-		pr_crit("pci %s: no irq found for pin %u\n",
-			pci_name((struct pci_dev *) dev), pin);
-	else
-		pr_info("pci %s: using irq %d for pin %u\n",
-			pci_name((struct pci_dev *) dev), irq, pin);
-
-	return irq;
+	return of_irq_parse_and_map_pci(dev, slot, pin);
 }
 
 int pcibios_plat_dev_init(struct pci_dev *dev)
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 33e7aa5..1bf60b1 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -120,51 +120,37 @@
 #ifdef CONFIG_OF
 void pci_load_of_ranges(struct pci_controller *hose, struct device_node *node)
 {
-	const __be32 *ranges;
-	int rlen;
-	int pna = of_n_addr_cells(node);
-	int np = pna + 5;
+	struct of_pci_range range;
+	struct of_pci_range_parser parser;
 
 	pr_info("PCI host bridge %s ranges:\n", node->full_name);
-	ranges = of_get_property(node, "ranges", &rlen);
-	if (ranges == NULL)
-		return;
 	hose->of_node = node;
 
-	while ((rlen -= np * 4) >= 0) {
-		u32 pci_space;
-		struct resource *res = NULL;
-		u64 addr, size;
+	if (of_pci_range_parser_init(&parser, node))
+		return;
 
-		pci_space = be32_to_cpup(&ranges[0]);
-		addr = of_translate_address(node, ranges + 3);
-		size = of_read_number(ranges + pna + 3, 2);
-		ranges += np;
-		switch ((pci_space >> 24) & 0x3) {
-		case 1:		/* PCI IO space */
+	for_each_of_pci_range(&parser, &range) {
+		struct resource *res = NULL;
+
+		switch (range.flags & IORESOURCE_TYPE_BITS) {
+		case IORESOURCE_IO:
 			pr_info("  IO 0x%016llx..0x%016llx\n",
-					addr, addr + size - 1);
+				range.cpu_addr,
+				range.cpu_addr + range.size - 1);
 			hose->io_map_base =
-				(unsigned long)ioremap(addr, size);
+				(unsigned long)ioremap(range.cpu_addr,
+						       range.size);
 			res = hose->io_resource;
-			res->flags = IORESOURCE_IO;
 			break;
-		case 2:		/* PCI Memory space */
-		case 3:		/* PCI 64 bits Memory space */
+		case IORESOURCE_MEM:
 			pr_info(" MEM 0x%016llx..0x%016llx\n",
-					addr, addr + size - 1);
+				range.cpu_addr,
+				range.cpu_addr + range.size - 1);
 			res = hose->mem_resource;
-			res->flags = IORESOURCE_MEM;
 			break;
 		}
-		if (res != NULL) {
-			res->start = addr;
-			res->name = node->full_name;
-			res->end = res->start + size - 1;
-			res->parent = NULL;
-			res->sibling = NULL;
-			res->child = NULL;
-		}
+		if (res != NULL)
+			of_pci_range_to_resource(&range, node, res);
 	}
 }
 
diff --git a/arch/mips/powertv/Kconfig b/arch/mips/powertv/Kconfig
deleted file mode 100644
index dd91fba..0000000
--- a/arch/mips/powertv/Kconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-config BOOTLOADER_FAMILY
-	string "POWERTV Bootloader Family string"
-	default "85"
-	depends on POWERTV
-	help
-	  This value should be specified when the bootloader driver is disabled
-	  and must be exactly two characters long. Families supported are:
-	    R1 - RNG-100  R2 - RNG-200
-	    A1 - Class A  B1 - Class B
-	    E1 - Class E  F1 - Class F
-	    44 - 45xx     46 - 46xx
-	    85 - 85xx     86 - 86xx
diff --git a/arch/mips/powertv/Makefile b/arch/mips/powertv/Makefile
deleted file mode 100644
index 39ca9f8..0000000
--- a/arch/mips/powertv/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Carsten Langgaard, carstenl@mips.com
-# Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
-#
-# Carsten Langgaard, carstenl@mips.com
-# Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
-# Portions copyright (C)  2009 Cisco Systems, Inc.
-#
-# This program is free software; you can distribute 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 it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# for more details.
-#
-# You 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.
-#
-# Makefile for the Cisco PowerTV-specific kernel interface routines
-# under Linux.
-#
-
-obj-y += init.o ioremap.o memory.o powertv_setup.o reset.o time.o \
-	asic/ pci/
-
-obj-$(CONFIG_USB) += powertv-usb.o
diff --git a/arch/mips/powertv/Platform b/arch/mips/powertv/Platform
deleted file mode 100644
index 4eb5af1..0000000
--- a/arch/mips/powertv/Platform
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Cisco PowerTV Platform
-#
-platform-$(CONFIG_POWERTV)	+= powertv/
-cflags-$(CONFIG_POWERTV)	+=					\
-		-I$(srctree)/arch/mips/include/asm/mach-powertv
-load-$(CONFIG_POWERTV)		+= 0xffffffff90800000
diff --git a/arch/mips/powertv/asic/Makefile b/arch/mips/powertv/asic/Makefile
deleted file mode 100644
index 35dcc53..0000000
--- a/arch/mips/powertv/asic/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Copyright (C) 2009  Scientific-Atlanta, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-#
-
-obj-y += asic-calliope.o asic-cronus.o asic-gaia.o asic-zeus.o \
-	asic_devices.o asic_int.o irq_asic.o prealloc-calliope.o \
-	prealloc-cronus.o prealloc-cronuslite.o prealloc-gaia.o prealloc-zeus.o
diff --git a/arch/mips/powertv/asic/asic-calliope.c b/arch/mips/powertv/asic/asic-calliope.c
deleted file mode 100644
index 2f539b4..0000000
--- a/arch/mips/powertv/asic/asic-calliope.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Locations of devices in the Calliope ASIC.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author:	 Ken Eppinett
- *		 David Schleef <ds@schleef.org>
- *
- * Description:	 Defines the platform resources for the SA settop.
- */
-
-#include <linux/init.h>
-#include <asm/mach-powertv/asic.h>
-
-#define CALLIOPE_ADDR(x)	(CALLIOPE_IO_BASE + (x))
-
-const struct register_map calliope_register_map __initconst = {
-	.eic_slow0_strt_add = {.phys = CALLIOPE_ADDR(0x800000)},
-	.eic_cfg_bits = {.phys = CALLIOPE_ADDR(0x800038)},
-	.eic_ready_status = {.phys = CALLIOPE_ADDR(0x80004c)},
-
-	.chipver3 = {.phys = CALLIOPE_ADDR(0xA00800)},
-	.chipver2 = {.phys = CALLIOPE_ADDR(0xA00804)},
-	.chipver1 = {.phys = CALLIOPE_ADDR(0xA00808)},
-	.chipver0 = {.phys = CALLIOPE_ADDR(0xA0080c)},
-
-	/* The registers of IRBlaster */
-	.uart1_intstat = {.phys = CALLIOPE_ADDR(0xA01800)},
-	.uart1_inten = {.phys = CALLIOPE_ADDR(0xA01804)},
-	.uart1_config1 = {.phys = CALLIOPE_ADDR(0xA01808)},
-	.uart1_config2 = {.phys = CALLIOPE_ADDR(0xA0180C)},
-	.uart1_divisorhi = {.phys = CALLIOPE_ADDR(0xA01810)},
-	.uart1_divisorlo = {.phys = CALLIOPE_ADDR(0xA01814)},
-	.uart1_data = {.phys = CALLIOPE_ADDR(0xA01818)},
-	.uart1_status = {.phys = CALLIOPE_ADDR(0xA0181C)},
-
-	.int_stat_3 = {.phys = CALLIOPE_ADDR(0xA02800)},
-	.int_stat_2 = {.phys = CALLIOPE_ADDR(0xA02804)},
-	.int_stat_1 = {.phys = CALLIOPE_ADDR(0xA02808)},
-	.int_stat_0 = {.phys = CALLIOPE_ADDR(0xA0280c)},
-	.int_config = {.phys = CALLIOPE_ADDR(0xA02810)},
-	.int_int_scan = {.phys = CALLIOPE_ADDR(0xA02818)},
-	.ien_int_3 = {.phys = CALLIOPE_ADDR(0xA02830)},
-	.ien_int_2 = {.phys = CALLIOPE_ADDR(0xA02834)},
-	.ien_int_1 = {.phys = CALLIOPE_ADDR(0xA02838)},
-	.ien_int_0 = {.phys = CALLIOPE_ADDR(0xA0283c)},
-	.int_level_3_3 = {.phys = CALLIOPE_ADDR(0xA02880)},
-	.int_level_3_2 = {.phys = CALLIOPE_ADDR(0xA02884)},
-	.int_level_3_1 = {.phys = CALLIOPE_ADDR(0xA02888)},
-	.int_level_3_0 = {.phys = CALLIOPE_ADDR(0xA0288c)},
-	.int_level_2_3 = {.phys = CALLIOPE_ADDR(0xA02890)},
-	.int_level_2_2 = {.phys = CALLIOPE_ADDR(0xA02894)},
-	.int_level_2_1 = {.phys = CALLIOPE_ADDR(0xA02898)},
-	.int_level_2_0 = {.phys = CALLIOPE_ADDR(0xA0289c)},
-	.int_level_1_3 = {.phys = CALLIOPE_ADDR(0xA028a0)},
-	.int_level_1_2 = {.phys = CALLIOPE_ADDR(0xA028a4)},
-	.int_level_1_1 = {.phys = CALLIOPE_ADDR(0xA028a8)},
-	.int_level_1_0 = {.phys = CALLIOPE_ADDR(0xA028ac)},
-	.int_level_0_3 = {.phys = CALLIOPE_ADDR(0xA028b0)},
-	.int_level_0_2 = {.phys = CALLIOPE_ADDR(0xA028b4)},
-	.int_level_0_1 = {.phys = CALLIOPE_ADDR(0xA028b8)},
-	.int_level_0_0 = {.phys = CALLIOPE_ADDR(0xA028bc)},
-	.int_docsis_en = {.phys = CALLIOPE_ADDR(0xA028F4)},
-
-	.mips_pll_setup = {.phys = CALLIOPE_ADDR(0x980000)},
-	.fs432x4b4_usb_ctl = {.phys = CALLIOPE_ADDR(0x980030)},
-	.test_bus = {.phys = CALLIOPE_ADDR(0x9800CC)},
-	.crt_spare = {.phys = CALLIOPE_ADDR(0x9800d4)},
-	.usb2_ohci_int_mask = {.phys = CALLIOPE_ADDR(0x9A000c)},
-	.usb2_strap = {.phys = CALLIOPE_ADDR(0x9A0014)},
-	.ehci_hcapbase = {.phys = CALLIOPE_ADDR(0x9BFE00)},
-	.ohci_hc_revision = {.phys = CALLIOPE_ADDR(0x9BFC00)},
-	.bcm1_bs_lmi_steer = {.phys = CALLIOPE_ADDR(0x9E0004)},
-	.usb2_control = {.phys = CALLIOPE_ADDR(0x9E0054)},
-	.usb2_stbus_obc = {.phys = CALLIOPE_ADDR(0x9BFF00)},
-	.usb2_stbus_mess_size = {.phys = CALLIOPE_ADDR(0x9BFF04)},
-	.usb2_stbus_chunk_size = {.phys = CALLIOPE_ADDR(0x9BFF08)},
-
-	.pcie_regs = {.phys = 0x000000},	/* -doesn't exist- */
-	.tim_ch = {.phys = CALLIOPE_ADDR(0xA02C10)},
-	.tim_cl = {.phys = CALLIOPE_ADDR(0xA02C14)},
-	.gpio_dout = {.phys = CALLIOPE_ADDR(0xA02c20)},
-	.gpio_din = {.phys = CALLIOPE_ADDR(0xA02c24)},
-	.gpio_dir = {.phys = CALLIOPE_ADDR(0xA02c2C)},
-	.watchdog = {.phys = CALLIOPE_ADDR(0xA02c30)},
-	.front_panel = {.phys = 0x000000},	/* -not used- */
-};
diff --git a/arch/mips/powertv/asic/asic-cronus.c b/arch/mips/powertv/asic/asic-cronus.c
deleted file mode 100644
index 7f8f342..0000000
--- a/arch/mips/powertv/asic/asic-cronus.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Locations of devices in the Cronus ASIC
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author:	 Ken Eppinett
- *		 David Schleef <ds@schleef.org>
- *
- * Description:	 Defines the platform resources for the SA settop.
- */
-
-#include <linux/init.h>
-#include <asm/mach-powertv/asic.h>
-
-#define CRONUS_ADDR(x)	(CRONUS_IO_BASE + (x))
-
-const struct register_map cronus_register_map __initconst = {
-	.eic_slow0_strt_add = {.phys = CRONUS_ADDR(0x000000)},
-	.eic_cfg_bits = {.phys = CRONUS_ADDR(0x000038)},
-	.eic_ready_status = {.phys = CRONUS_ADDR(0x00004C)},
-
-	.chipver3 = {.phys = CRONUS_ADDR(0x2A0800)},
-	.chipver2 = {.phys = CRONUS_ADDR(0x2A0804)},
-	.chipver1 = {.phys = CRONUS_ADDR(0x2A0808)},
-	.chipver0 = {.phys = CRONUS_ADDR(0x2A080C)},
-
-	/* The registers of IRBlaster */
-	.uart1_intstat = {.phys = CRONUS_ADDR(0x2A1800)},
-	.uart1_inten = {.phys = CRONUS_ADDR(0x2A1804)},
-	.uart1_config1 = {.phys = CRONUS_ADDR(0x2A1808)},
-	.uart1_config2 = {.phys = CRONUS_ADDR(0x2A180C)},
-	.uart1_divisorhi = {.phys = CRONUS_ADDR(0x2A1810)},
-	.uart1_divisorlo = {.phys = CRONUS_ADDR(0x2A1814)},
-	.uart1_data = {.phys = CRONUS_ADDR(0x2A1818)},
-	.uart1_status = {.phys = CRONUS_ADDR(0x2A181C)},
-
-	.int_stat_3 = {.phys = CRONUS_ADDR(0x2A2800)},
-	.int_stat_2 = {.phys = CRONUS_ADDR(0x2A2804)},
-	.int_stat_1 = {.phys = CRONUS_ADDR(0x2A2808)},
-	.int_stat_0 = {.phys = CRONUS_ADDR(0x2A280C)},
-	.int_config = {.phys = CRONUS_ADDR(0x2A2810)},
-	.int_int_scan = {.phys = CRONUS_ADDR(0x2A2818)},
-	.ien_int_3 = {.phys = CRONUS_ADDR(0x2A2830)},
-	.ien_int_2 = {.phys = CRONUS_ADDR(0x2A2834)},
-	.ien_int_1 = {.phys = CRONUS_ADDR(0x2A2838)},
-	.ien_int_0 = {.phys = CRONUS_ADDR(0x2A283C)},
-	.int_level_3_3 = {.phys = CRONUS_ADDR(0x2A2880)},
-	.int_level_3_2 = {.phys = CRONUS_ADDR(0x2A2884)},
-	.int_level_3_1 = {.phys = CRONUS_ADDR(0x2A2888)},
-	.int_level_3_0 = {.phys = CRONUS_ADDR(0x2A288C)},
-	.int_level_2_3 = {.phys = CRONUS_ADDR(0x2A2890)},
-	.int_level_2_2 = {.phys = CRONUS_ADDR(0x2A2894)},
-	.int_level_2_1 = {.phys = CRONUS_ADDR(0x2A2898)},
-	.int_level_2_0 = {.phys = CRONUS_ADDR(0x2A289C)},
-	.int_level_1_3 = {.phys = CRONUS_ADDR(0x2A28A0)},
-	.int_level_1_2 = {.phys = CRONUS_ADDR(0x2A28A4)},
-	.int_level_1_1 = {.phys = CRONUS_ADDR(0x2A28A8)},
-	.int_level_1_0 = {.phys = CRONUS_ADDR(0x2A28AC)},
-	.int_level_0_3 = {.phys = CRONUS_ADDR(0x2A28B0)},
-	.int_level_0_2 = {.phys = CRONUS_ADDR(0x2A28B4)},
-	.int_level_0_1 = {.phys = CRONUS_ADDR(0x2A28B8)},
-	.int_level_0_0 = {.phys = CRONUS_ADDR(0x2A28BC)},
-	.int_docsis_en = {.phys = CRONUS_ADDR(0x2A28F4)},
-
-	.mips_pll_setup = {.phys = CRONUS_ADDR(0x1C0000)},
-	.fs432x4b4_usb_ctl = {.phys = CRONUS_ADDR(0x1C0028)},
-	.test_bus = {.phys = CRONUS_ADDR(0x1C00CC)},
-	.crt_spare = {.phys = CRONUS_ADDR(0x1c00d4)},
-	.usb2_ohci_int_mask = {.phys = CRONUS_ADDR(0x20000C)},
-	.usb2_strap = {.phys = CRONUS_ADDR(0x200014)},
-	.ehci_hcapbase = {.phys = CRONUS_ADDR(0x21FE00)},
-	.ohci_hc_revision = {.phys = CRONUS_ADDR(0x21fc00)},
-	.bcm1_bs_lmi_steer = {.phys = CRONUS_ADDR(0x2E0008)},
-	.usb2_control = {.phys = CRONUS_ADDR(0x2E004C)},
-	.usb2_stbus_obc = {.phys = CRONUS_ADDR(0x21FF00)},
-	.usb2_stbus_mess_size = {.phys = CRONUS_ADDR(0x21FF04)},
-	.usb2_stbus_chunk_size = {.phys = CRONUS_ADDR(0x21FF08)},
-
-	.pcie_regs = {.phys = CRONUS_ADDR(0x220000)},
-	.tim_ch = {.phys = CRONUS_ADDR(0x2A2C10)},
-	.tim_cl = {.phys = CRONUS_ADDR(0x2A2C14)},
-	.gpio_dout = {.phys = CRONUS_ADDR(0x2A2C20)},
-	.gpio_din = {.phys = CRONUS_ADDR(0x2A2C24)},
-	.gpio_dir = {.phys = CRONUS_ADDR(0x2A2C2C)},
-	.watchdog = {.phys = CRONUS_ADDR(0x2A2C30)},
-	.front_panel = {.phys = CRONUS_ADDR(0x2A3800)},
-};
diff --git a/arch/mips/powertv/asic/asic-gaia.c b/arch/mips/powertv/asic/asic-gaia.c
deleted file mode 100644
index 1265b49..0000000
--- a/arch/mips/powertv/asic/asic-gaia.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Locations of devices in the Gaia ASIC
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author:	 David VomLehn
- */
-
-#include <linux/init.h>
-#include <asm/mach-powertv/asic.h>
-
-const struct register_map gaia_register_map __initconst = {
-	.eic_slow0_strt_add = {.phys = GAIA_IO_BASE + 0x000000},
-	.eic_cfg_bits = {.phys = GAIA_IO_BASE + 0x000038},
-	.eic_ready_status = {.phys = GAIA_IO_BASE + 0x00004C},
-
-	.chipver3 = {.phys = GAIA_IO_BASE + 0x2A0800},
-	.chipver2 = {.phys = GAIA_IO_BASE + 0x2A0804},
-	.chipver1 = {.phys = GAIA_IO_BASE + 0x2A0808},
-	.chipver0 = {.phys = GAIA_IO_BASE + 0x2A080C},
-
-	/* The registers of IRBlaster */
-	.uart1_intstat = {.phys = GAIA_IO_BASE + 0x2A1800},
-	.uart1_inten = {.phys = GAIA_IO_BASE + 0x2A1804},
-	.uart1_config1 = {.phys = GAIA_IO_BASE + 0x2A1808},
-	.uart1_config2 = {.phys = GAIA_IO_BASE + 0x2A180C},
-	.uart1_divisorhi = {.phys = GAIA_IO_BASE + 0x2A1810},
-	.uart1_divisorlo = {.phys = GAIA_IO_BASE + 0x2A1814},
-	.uart1_data = {.phys = GAIA_IO_BASE + 0x2A1818},
-	.uart1_status = {.phys = GAIA_IO_BASE + 0x2A181C},
-
-	.int_stat_3 = {.phys = GAIA_IO_BASE + 0x2A2800},
-	.int_stat_2 = {.phys = GAIA_IO_BASE + 0x2A2804},
-	.int_stat_1 = {.phys = GAIA_IO_BASE + 0x2A2808},
-	.int_stat_0 = {.phys = GAIA_IO_BASE + 0x2A280C},
-	.int_config = {.phys = GAIA_IO_BASE + 0x2A2810},
-	.int_int_scan = {.phys = GAIA_IO_BASE + 0x2A2818},
-	.ien_int_3 = {.phys = GAIA_IO_BASE + 0x2A2830},
-	.ien_int_2 = {.phys = GAIA_IO_BASE + 0x2A2834},
-	.ien_int_1 = {.phys = GAIA_IO_BASE + 0x2A2838},
-	.ien_int_0 = {.phys = GAIA_IO_BASE + 0x2A283C},
-	.int_level_3_3 = {.phys = GAIA_IO_BASE + 0x2A2880},
-	.int_level_3_2 = {.phys = GAIA_IO_BASE + 0x2A2884},
-	.int_level_3_1 = {.phys = GAIA_IO_BASE + 0x2A2888},
-	.int_level_3_0 = {.phys = GAIA_IO_BASE + 0x2A288C},
-	.int_level_2_3 = {.phys = GAIA_IO_BASE + 0x2A2890},
-	.int_level_2_2 = {.phys = GAIA_IO_BASE + 0x2A2894},
-	.int_level_2_1 = {.phys = GAIA_IO_BASE + 0x2A2898},
-	.int_level_2_0 = {.phys = GAIA_IO_BASE + 0x2A289C},
-	.int_level_1_3 = {.phys = GAIA_IO_BASE + 0x2A28A0},
-	.int_level_1_2 = {.phys = GAIA_IO_BASE + 0x2A28A4},
-	.int_level_1_1 = {.phys = GAIA_IO_BASE + 0x2A28A8},
-	.int_level_1_0 = {.phys = GAIA_IO_BASE + 0x2A28AC},
-	.int_level_0_3 = {.phys = GAIA_IO_BASE + 0x2A28B0},
-	.int_level_0_2 = {.phys = GAIA_IO_BASE + 0x2A28B4},
-	.int_level_0_1 = {.phys = GAIA_IO_BASE + 0x2A28B8},
-	.int_level_0_0 = {.phys = GAIA_IO_BASE + 0x2A28BC},
-	.int_docsis_en = {.phys = GAIA_IO_BASE + 0x2A28F4},
-
-	.mips_pll_setup = {.phys = GAIA_IO_BASE + 0x1C0000},
-	.fs432x4b4_usb_ctl = {.phys = GAIA_IO_BASE + 0x1C0024},
-	.test_bus = {.phys = GAIA_IO_BASE + 0x1C00CC},
-	.crt_spare = {.phys = GAIA_IO_BASE + 0x1c0108},
-	.usb2_ohci_int_mask = {.phys = GAIA_IO_BASE + 0x20000C},
-	.usb2_strap = {.phys = GAIA_IO_BASE + 0x200014},
-	.ehci_hcapbase = {.phys = GAIA_IO_BASE + 0x21FE00},
-	.ohci_hc_revision = {.phys = GAIA_IO_BASE + 0x21fc00},
-	.bcm1_bs_lmi_steer = {.phys = GAIA_IO_BASE + 0x2E0004},
-	.usb2_control = {.phys = GAIA_IO_BASE + 0x2E004C},
-	.usb2_stbus_obc = {.phys = GAIA_IO_BASE + 0x21FF00},
-	.usb2_stbus_mess_size = {.phys = GAIA_IO_BASE + 0x21FF04},
-	.usb2_stbus_chunk_size = {.phys = GAIA_IO_BASE + 0x21FF08},
-
-	.pcie_regs = {.phys = GAIA_IO_BASE + 0x220000},
-	.tim_ch = {.phys = GAIA_IO_BASE + 0x2A2C10},
-	.tim_cl = {.phys = GAIA_IO_BASE + 0x2A2C14},
-	.gpio_dout = {.phys = GAIA_IO_BASE + 0x2A2C20},
-	.gpio_din = {.phys = GAIA_IO_BASE + 0x2A2C24},
-	.gpio_dir = {.phys = GAIA_IO_BASE + 0x2A2C2C},
-	.watchdog = {.phys = GAIA_IO_BASE + 0x2A2C30},
-	.front_panel = {.phys = GAIA_IO_BASE + 0x2A3800},
-};
diff --git a/arch/mips/powertv/asic/asic-zeus.c b/arch/mips/powertv/asic/asic-zeus.c
deleted file mode 100644
index 14e7de1..0000000
--- a/arch/mips/powertv/asic/asic-zeus.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Locations of devices in the Zeus ASIC
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author:	 Ken Eppinett
- *		 David Schleef <ds@schleef.org>
- *
- * Description:	 Defines the platform resources for the SA settop.
- */
-
-#include <linux/init.h>
-#include <asm/mach-powertv/asic.h>
-
-#define ZEUS_ADDR(x)	(ZEUS_IO_BASE + (x))
-
-const struct register_map zeus_register_map __initconst = {
-	.eic_slow0_strt_add = {.phys = ZEUS_ADDR(0x000000)},
-	.eic_cfg_bits = {.phys = ZEUS_ADDR(0x000038)},
-	.eic_ready_status = {.phys = ZEUS_ADDR(0x00004c)},
-
-	.chipver3 = {.phys = ZEUS_ADDR(0x280800)},
-	.chipver2 = {.phys = ZEUS_ADDR(0x280804)},
-	.chipver1 = {.phys = ZEUS_ADDR(0x280808)},
-	.chipver0 = {.phys = ZEUS_ADDR(0x28080c)},
-
-	/* The registers of IRBlaster */
-	.uart1_intstat = {.phys = ZEUS_ADDR(0x281800)},
-	.uart1_inten = {.phys = ZEUS_ADDR(0x281804)},
-	.uart1_config1 = {.phys = ZEUS_ADDR(0x281808)},
-	.uart1_config2 = {.phys = ZEUS_ADDR(0x28180C)},
-	.uart1_divisorhi = {.phys = ZEUS_ADDR(0x281810)},
-	.uart1_divisorlo = {.phys = ZEUS_ADDR(0x281814)},
-	.uart1_data = {.phys = ZEUS_ADDR(0x281818)},
-	.uart1_status = {.phys = ZEUS_ADDR(0x28181C)},
-
-	.int_stat_3 = {.phys = ZEUS_ADDR(0x282800)},
-	.int_stat_2 = {.phys = ZEUS_ADDR(0x282804)},
-	.int_stat_1 = {.phys = ZEUS_ADDR(0x282808)},
-	.int_stat_0 = {.phys = ZEUS_ADDR(0x28280c)},
-	.int_config = {.phys = ZEUS_ADDR(0x282810)},
-	.int_int_scan = {.phys = ZEUS_ADDR(0x282818)},
-	.ien_int_3 = {.phys = ZEUS_ADDR(0x282830)},
-	.ien_int_2 = {.phys = ZEUS_ADDR(0x282834)},
-	.ien_int_1 = {.phys = ZEUS_ADDR(0x282838)},
-	.ien_int_0 = {.phys = ZEUS_ADDR(0x28283c)},
-	.int_level_3_3 = {.phys = ZEUS_ADDR(0x282880)},
-	.int_level_3_2 = {.phys = ZEUS_ADDR(0x282884)},
-	.int_level_3_1 = {.phys = ZEUS_ADDR(0x282888)},
-	.int_level_3_0 = {.phys = ZEUS_ADDR(0x28288c)},
-	.int_level_2_3 = {.phys = ZEUS_ADDR(0x282890)},
-	.int_level_2_2 = {.phys = ZEUS_ADDR(0x282894)},
-	.int_level_2_1 = {.phys = ZEUS_ADDR(0x282898)},
-	.int_level_2_0 = {.phys = ZEUS_ADDR(0x28289c)},
-	.int_level_1_3 = {.phys = ZEUS_ADDR(0x2828a0)},
-	.int_level_1_2 = {.phys = ZEUS_ADDR(0x2828a4)},
-	.int_level_1_1 = {.phys = ZEUS_ADDR(0x2828a8)},
-	.int_level_1_0 = {.phys = ZEUS_ADDR(0x2828ac)},
-	.int_level_0_3 = {.phys = ZEUS_ADDR(0x2828b0)},
-	.int_level_0_2 = {.phys = ZEUS_ADDR(0x2828b4)},
-	.int_level_0_1 = {.phys = ZEUS_ADDR(0x2828b8)},
-	.int_level_0_0 = {.phys = ZEUS_ADDR(0x2828bc)},
-	.int_docsis_en = {.phys = ZEUS_ADDR(0x2828F4)},
-
-	.mips_pll_setup = {.phys = ZEUS_ADDR(0x1a0000)},
-	.fs432x4b4_usb_ctl = {.phys = ZEUS_ADDR(0x1a0018)},
-	.test_bus = {.phys = ZEUS_ADDR(0x1a0238)},
-	.crt_spare = {.phys = ZEUS_ADDR(0x1a0090)},
-	.usb2_ohci_int_mask = {.phys = ZEUS_ADDR(0x1e000c)},
-	.usb2_strap = {.phys = ZEUS_ADDR(0x1e0014)},
-	.ehci_hcapbase = {.phys = ZEUS_ADDR(0x1FFE00)},
-	.ohci_hc_revision = {.phys = ZEUS_ADDR(0x1FFC00)},
-	.bcm1_bs_lmi_steer = {.phys = ZEUS_ADDR(0x2C0008)},
-	.usb2_control = {.phys = ZEUS_ADDR(0x2c01a0)},
-	.usb2_stbus_obc = {.phys = ZEUS_ADDR(0x1FFF00)},
-	.usb2_stbus_mess_size = {.phys = ZEUS_ADDR(0x1FFF04)},
-	.usb2_stbus_chunk_size = {.phys = ZEUS_ADDR(0x1FFF08)},
-
-	.pcie_regs = {.phys = ZEUS_ADDR(0x200000)},
-	.tim_ch = {.phys = ZEUS_ADDR(0x282C10)},
-	.tim_cl = {.phys = ZEUS_ADDR(0x282C14)},
-	.gpio_dout = {.phys = ZEUS_ADDR(0x282c20)},
-	.gpio_din = {.phys = ZEUS_ADDR(0x282c24)},
-	.gpio_dir = {.phys = ZEUS_ADDR(0x282c2C)},
-	.watchdog = {.phys = ZEUS_ADDR(0x282c30)},
-	.front_panel = {.phys = ZEUS_ADDR(0x283800)},
-};
diff --git a/arch/mips/powertv/asic/asic_devices.c b/arch/mips/powertv/asic/asic_devices.c
deleted file mode 100644
index 8380605..0000000
--- a/arch/mips/powertv/asic/asic_devices.c
+++ /dev/null
@@ -1,549 +0,0 @@
-/*
- *
- * Description:	 Defines the platform resources for Gaia-based settops.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * NOTE: The bootloader allocates persistent memory at an address which is
- * 16 MiB below the end of the highest address in KSEG0. All fixed
- * address memory reservations must avoid this region.
- */
-
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/resource.h>
-#include <linux/serial_reg.h>
-#include <linux/io.h>
-#include <linux/bootmem.h>
-#include <linux/mm.h>
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <asm/page.h>
-#include <linux/swap.h>
-#include <linux/highmem.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/mach-powertv/asic.h>
-#include <asm/mach-powertv/asic_regs.h>
-#include <asm/mach-powertv/interrupts.h>
-
-#ifdef CONFIG_BOOTLOADER_DRIVER
-#include <asm/mach-powertv/kbldr.h>
-#endif
-#include <asm/bootinfo.h>
-
-#define BOOTLDRFAMILY(byte1, byte0) (((byte1) << 8) | (byte0))
-
-/*
- * Forward Prototypes
- */
-static void pmem_setup_resource(void);
-
-/*
- * Global Variables
- */
-enum asic_type asic;
-
-unsigned int platform_features;
-unsigned int platform_family;
-struct register_map _asic_register_map;
-EXPORT_SYMBOL(_asic_register_map);		/* Exported for testing */
-unsigned long asic_phy_base;
-unsigned long asic_base;
-EXPORT_SYMBOL(asic_base);			/* Exported for testing */
-struct resource *gp_resources;
-
-/*
- * Don't recommend to use it directly, it is usually used by kernel internally.
- * Portable code should be using interfaces such as ioremp, dma_map_single, etc.
- */
-unsigned long phys_to_dma_offset;
-EXPORT_SYMBOL(phys_to_dma_offset);
-
-/*
- *
- * IO Resource Definition
- *
- */
-
-struct resource asic_resource = {
-	.name  = "ASIC Resource",
-	.start = 0,
-	.end   = ASIC_IO_SIZE,
-	.flags = IORESOURCE_MEM,
-};
-
-/*
- * Allow override of bootloader-specified model
- * Returns zero on success, a negative errno value on failure.	This parameter
- * allows overriding of the bootloader-specified model.
- */
-static char __initdata cmdline[COMMAND_LINE_SIZE];
-
-#define FORCEFAMILY_PARAM	"forcefamily"
-
-/*
- * check_forcefamily - check for, and parse, forcefamily command line parameter
- * @forced_family:	Pointer to two-character array in which to store the
- *			value of the forcedfamily parameter, if any.
- */
-static __init int check_forcefamily(unsigned char forced_family[2])
-{
-	const char *p;
-
-	forced_family[0] = '\0';
-	forced_family[1] = '\0';
-
-	/* Check the command line for a forcefamily directive */
-	strncpy(cmdline, arcs_cmdline, COMMAND_LINE_SIZE - 1);
-	p = strstr(cmdline, FORCEFAMILY_PARAM);
-	if (p && (p != cmdline) && (*(p - 1) != ' '))
-		p = strstr(p, " " FORCEFAMILY_PARAM "=");
-
-	if (p) {
-		p += strlen(FORCEFAMILY_PARAM "=");
-
-		if (*p == '\0' || *(p + 1) == '\0' ||
-			(*(p + 2) != '\0' && *(p + 2) != ' '))
-			pr_err(FORCEFAMILY_PARAM " must be exactly two "
-				"characters long, ignoring value\n");
-
-		else {
-			forced_family[0] = *p;
-			forced_family[1] = *(p + 1);
-		}
-	}
-
-	return 0;
-}
-
-/*
- * platform_set_family - determine major platform family type.
- *
- * Returns family type; -1 if none
- * Returns the family type; -1 if none
- *
- */
-static __init noinline void platform_set_family(void)
-{
-	unsigned char forced_family[2];
-	unsigned short bootldr_family;
-
-	if (check_forcefamily(forced_family) == 0)
-		bootldr_family = BOOTLDRFAMILY(forced_family[0],
-			forced_family[1]);
-	else
-		bootldr_family = (unsigned short) BOOTLDRFAMILY(
-			CONFIG_BOOTLOADER_FAMILY[0],
-			CONFIG_BOOTLOADER_FAMILY[1]);
-
-	pr_info("Bootloader Family = 0x%04X\n", bootldr_family);
-
-	switch (bootldr_family) {
-	case BOOTLDRFAMILY('R', '1'):
-		platform_family = FAMILY_1500;
-		break;
-	case BOOTLDRFAMILY('4', '4'):
-		platform_family = FAMILY_4500;
-		break;
-	case BOOTLDRFAMILY('4', '6'):
-		platform_family = FAMILY_4600;
-		break;
-	case BOOTLDRFAMILY('A', '1'):
-		platform_family = FAMILY_4600VZA;
-		break;
-	case BOOTLDRFAMILY('8', '5'):
-		platform_family = FAMILY_8500;
-		break;
-	case BOOTLDRFAMILY('R', '2'):
-		platform_family = FAMILY_8500RNG;
-		break;
-	case BOOTLDRFAMILY('8', '6'):
-		platform_family = FAMILY_8600;
-		break;
-	case BOOTLDRFAMILY('B', '1'):
-		platform_family = FAMILY_8600VZB;
-		break;
-	case BOOTLDRFAMILY('E', '1'):
-		platform_family = FAMILY_1500VZE;
-		break;
-	case BOOTLDRFAMILY('F', '1'):
-		platform_family = FAMILY_1500VZF;
-		break;
-	case BOOTLDRFAMILY('8', '7'):
-		platform_family = FAMILY_8700;
-		break;
-	default:
-		platform_family = -1;
-	}
-}
-
-unsigned int platform_get_family(void)
-{
-	return platform_family;
-}
-EXPORT_SYMBOL(platform_get_family);
-
-/*
- * platform_get_asic - determine the ASIC type.
- *
- * Returns the ASIC type, or ASIC_UNKNOWN if unknown
- *
- */
-enum asic_type platform_get_asic(void)
-{
-	return asic;
-}
-EXPORT_SYMBOL(platform_get_asic);
-
-/*
- * set_register_map - set ASIC register configuration
- * @phys_base:	Physical address of the base of the ASIC registers
- * @map:	Description of key ASIC registers
- */
-static void __init set_register_map(unsigned long phys_base,
-	const struct register_map *map)
-{
-	asic_phy_base = phys_base;
-	_asic_register_map = *map;
-	register_map_virtualize(&_asic_register_map);
-	asic_base = (unsigned long)ioremap_nocache(phys_base, ASIC_IO_SIZE);
-}
-
-/**
- * configure_platform - configuration based on platform type.
- */
-void __init configure_platform(void)
-{
-	platform_set_family();
-
-	switch (platform_family) {
-	case FAMILY_1500:
-	case FAMILY_1500VZE:
-	case FAMILY_1500VZF:
-		platform_features = FFS_CAPABLE;
-		asic = ASIC_CALLIOPE;
-		set_register_map(CALLIOPE_IO_BASE, &calliope_register_map);
-
-		if (platform_family == FAMILY_1500VZE) {
-			gp_resources = non_dvr_vze_calliope_resources;
-			pr_info("Platform: 1500/Vz Class E - "
-				"CALLIOPE, NON_DVR_CAPABLE\n");
-		} else if (platform_family == FAMILY_1500VZF) {
-			gp_resources = non_dvr_vzf_calliope_resources;
-			pr_info("Platform: 1500/Vz Class F - "
-				"CALLIOPE, NON_DVR_CAPABLE\n");
-		} else {
-			gp_resources = non_dvr_calliope_resources;
-			pr_info("Platform: 1500/RNG100 - CALLIOPE, "
-				"NON_DVR_CAPABLE\n");
-		}
-		break;
-
-	case FAMILY_4500:
-		platform_features = FFS_CAPABLE | PCIE_CAPABLE |
-			DISPLAY_CAPABLE;
-		asic = ASIC_ZEUS;
-		set_register_map(ZEUS_IO_BASE, &zeus_register_map);
-		gp_resources = non_dvr_zeus_resources;
-
-		pr_info("Platform: 4500 - ZEUS, NON_DVR_CAPABLE\n");
-		break;
-
-	case FAMILY_4600:
-	{
-		unsigned int chipversion = 0;
-
-		/* The settop has PCIE but it isn't used, so don't advertise
-		 * it*/
-		platform_features = FFS_CAPABLE | DISPLAY_CAPABLE;
-
-		/* Cronus and Cronus Lite have the same register map */
-		set_register_map(CRONUS_IO_BASE, &cronus_register_map);
-
-		/* ASIC version will determine if this is a real CronusLite or
-		 * Castrati(Cronus) */
-		chipversion  = asic_read(chipver3) << 24;
-		chipversion |= asic_read(chipver2) << 16;
-		chipversion |= asic_read(chipver1) << 8;
-		chipversion |= asic_read(chipver0);
-
-		if ((chipversion == CRONUS_10) || (chipversion == CRONUS_11))
-			asic = ASIC_CRONUS;
-		else
-			asic = ASIC_CRONUSLITE;
-
-		gp_resources = non_dvr_cronuslite_resources;
-		pr_info("Platform: 4600 - %s, NON_DVR_CAPABLE, "
-			"chipversion=0x%08X\n",
-			(asic == ASIC_CRONUS) ? "CRONUS" : "CRONUS LITE",
-			chipversion);
-		break;
-	}
-	case FAMILY_4600VZA:
-		platform_features = FFS_CAPABLE | DISPLAY_CAPABLE;
-		asic = ASIC_CRONUS;
-		set_register_map(CRONUS_IO_BASE, &cronus_register_map);
-		gp_resources = non_dvr_cronus_resources;
-
-		pr_info("Platform: Vz Class A - CRONUS, NON_DVR_CAPABLE\n");
-		break;
-
-	case FAMILY_8500:
-	case FAMILY_8500RNG:
-		platform_features = DVR_CAPABLE | PCIE_CAPABLE |
-			DISPLAY_CAPABLE;
-		asic = ASIC_ZEUS;
-		set_register_map(ZEUS_IO_BASE, &zeus_register_map);
-		gp_resources = dvr_zeus_resources;
-
-		pr_info("Platform: 8500/RNG200 - ZEUS, DVR_CAPABLE\n");
-		break;
-
-	case FAMILY_8600:
-	case FAMILY_8600VZB:
-		platform_features = DVR_CAPABLE | PCIE_CAPABLE |
-			DISPLAY_CAPABLE;
-		asic = ASIC_CRONUS;
-		set_register_map(CRONUS_IO_BASE, &cronus_register_map);
-		gp_resources = dvr_cronus_resources;
-
-		pr_info("Platform: 8600/Vz Class B - CRONUS, "
-			"DVR_CAPABLE\n");
-		break;
-
-	case FAMILY_8700:
-		platform_features = FFS_CAPABLE | PCIE_CAPABLE;
-		asic = ASIC_GAIA;
-		set_register_map(GAIA_IO_BASE, &gaia_register_map);
-		gp_resources = dvr_gaia_resources;
-
-		pr_info("Platform: 8700 - GAIA, DVR_CAPABLE\n");
-		break;
-
-	default:
-		pr_crit("Platform:  UNKNOWN PLATFORM\n");
-		break;
-	}
-
-	switch (asic) {
-	case ASIC_ZEUS:
-		phys_to_dma_offset = 0x30000000;
-		break;
-	case ASIC_CALLIOPE:
-		phys_to_dma_offset = 0x10000000;
-		break;
-	case ASIC_CRONUSLITE:
-		/* Fall through */
-	case ASIC_CRONUS:
-		/*
-		 * TODO: We suppose 0x10000000 aliases into 0x20000000-
-		 * 0x2XXXXXXX. If 0x10000000 aliases into 0x60000000-
-		 * 0x6XXXXXXX, the offset should be 0x50000000, not 0x10000000.
-		 */
-		phys_to_dma_offset = 0x10000000;
-		break;
-	default:
-		phys_to_dma_offset = 0x00000000;
-		break;
-	}
-}
-
-/*
- * RESOURCE ALLOCATION
- *
- */
-/*
- * Allocates/reserves the Platform memory resources early in the boot process.
- * This ignores any resources that are designated IORESOURCE_IO
- */
-void __init platform_alloc_bootmem(void)
-{
-	int i;
-	int total = 0;
-
-	/* Get persistent memory data from command line before allocating
-	 * resources. This need to happen before normal command line parsing
-	 * has been done */
-	pmem_setup_resource();
-
-	/* Loop through looking for resources that want a particular address */
-	for (i = 0; gp_resources[i].flags != 0; i++) {
-		int size = resource_size(&gp_resources[i]);
-		if ((gp_resources[i].start != 0) &&
-			((gp_resources[i].flags & IORESOURCE_MEM) != 0)) {
-			reserve_bootmem(dma_to_phys(gp_resources[i].start),
-				size, 0);
-			total += resource_size(&gp_resources[i]);
-			pr_info("reserve resource %s at %08x (%u bytes)\n",
-				gp_resources[i].name, gp_resources[i].start,
-				resource_size(&gp_resources[i]));
-		}
-	}
-
-	/* Loop through assigning addresses for those that are left */
-	for (i = 0; gp_resources[i].flags != 0; i++) {
-		int size = resource_size(&gp_resources[i]);
-		if ((gp_resources[i].start == 0) &&
-			((gp_resources[i].flags & IORESOURCE_MEM) != 0)) {
-			void *mem = alloc_bootmem_pages(size);
-
-			if (mem == NULL)
-				pr_err("Unable to allocate bootmem pages "
-					"for %s\n", gp_resources[i].name);
-
-			else {
-				gp_resources[i].start =
-					phys_to_dma(virt_to_phys(mem));
-				gp_resources[i].end =
-					gp_resources[i].start + size - 1;
-				total += size;
-				pr_info("allocate resource %s at %08x "
-						"(%u bytes)\n",
-					gp_resources[i].name,
-					gp_resources[i].start, size);
-			}
-		}
-	}
-
-	pr_info("Total Platform driver memory allocation: 0x%08x\n", total);
-
-	/* indicate resources that are platform I/O related */
-	for (i = 0; gp_resources[i].flags != 0; i++) {
-		if ((gp_resources[i].start != 0) &&
-			((gp_resources[i].flags & IORESOURCE_IO) != 0)) {
-			pr_info("reserved platform resource %s at %08x\n",
-				gp_resources[i].name, gp_resources[i].start);
-		}
-	}
-}
-
-/*
- *
- * PERSISTENT MEMORY (PMEM) CONFIGURATION
- *
- */
-static unsigned long pmemaddr __initdata;
-
-static int __init early_param_pmemaddr(char *p)
-{
-	pmemaddr = (unsigned long)simple_strtoul(p, NULL, 0);
-	return 0;
-}
-early_param("pmemaddr", early_param_pmemaddr);
-
-static long pmemlen __initdata;
-
-static int __init early_param_pmemlen(char *p)
-{
-/* TODO: we can use this code when and if the bootloader ever changes this */
-#if 0
-	pmemlen = (unsigned long)simple_strtoul(p, NULL, 0);
-#else
-	pmemlen = 0x20000;
-#endif
-	return 0;
-}
-early_param("pmemlen", early_param_pmemlen);
-
-/*
- * Set up persistent memory. If we were given values, we patch the array of
- * resources. Otherwise, persistent memory may be allocated anywhere at all.
- */
-static void __init pmem_setup_resource(void)
-{
-	struct resource *resource;
-	resource = asic_resource_get("DiagPersistentMemory");
-
-	if (resource && pmemaddr && pmemlen) {
-		/* The address provided by bootloader is in kseg0. Convert to
-		 * a bus address. */
-		resource->start = phys_to_dma(pmemaddr - 0x80000000);
-		resource->end = resource->start + pmemlen - 1;
-
-		pr_info("persistent memory: start=0x%x	end=0x%x\n",
-			resource->start, resource->end);
-	}
-}
-
-/*
- *
- * RESOURCE ACCESS FUNCTIONS
- *
- */
-
-/**
- * asic_resource_get - retrieves parameters for a platform resource.
- * @name:	string to match resource
- *
- * Returns a pointer to a struct resource corresponding to the given name.
- *
- * CANNOT BE NAMED platform_resource_get, which would be the obvious choice,
- * as this function name is already declared
- */
-struct resource *asic_resource_get(const char *name)
-{
-	int i;
-
-	for (i = 0; gp_resources[i].flags != 0; i++) {
-		if (strcmp(gp_resources[i].name, name) == 0)
-			return &gp_resources[i];
-	}
-
-	return NULL;
-}
-EXPORT_SYMBOL(asic_resource_get);
-
-/**
- * platform_release_memory - release pre-allocated memory
- * @ptr:	pointer to memory to release
- * @size:	size of resource
- *
- * This must only be called for memory allocated or reserved via the boot
- * memory allocator.
- */
-void platform_release_memory(void *ptr, int size)
-{
-	free_reserved_area(ptr, ptr + size, -1, NULL);
-}
-EXPORT_SYMBOL(platform_release_memory);
-
-/*
- *
- * FEATURE AVAILABILITY FUNCTIONS
- *
- */
-int platform_supports_dvr(void)
-{
-	return (platform_features & DVR_CAPABLE) != 0;
-}
-
-int platform_supports_ffs(void)
-{
-	return (platform_features & FFS_CAPABLE) != 0;
-}
-
-int platform_supports_pcie(void)
-{
-	return (platform_features & PCIE_CAPABLE) != 0;
-}
-
-int platform_supports_display(void)
-{
-	return (platform_features & DISPLAY_CAPABLE) != 0;
-}
diff --git a/arch/mips/powertv/asic/asic_int.c b/arch/mips/powertv/asic/asic_int.c
deleted file mode 100644
index f44cd92..0000000
--- a/arch/mips/powertv/asic/asic_int.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc.
- * Copyright (C) 2001 Ralf Baechle
- * Portions copyright (C) 2009	Cisco Systems, Inc.
- *
- *  This program is free software; you can distribute 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 it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You 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.
- *
- * Routines for generic manipulation of the interrupts found on the PowerTV
- * platform.
- *
- * The interrupt controller is located in the South Bridge a PIIX4 device
- * with two internal 82C95 interrupt controllers.
- */
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/kernel.h>
-#include <linux/random.h>
-
-#include <asm/irq_cpu.h>
-#include <linux/io.h>
-#include <asm/irq_regs.h>
-#include <asm/setup.h>
-#include <asm/mips-boards/generic.h>
-
-#include <asm/mach-powertv/asic_regs.h>
-
-static DEFINE_RAW_SPINLOCK(asic_irq_lock);
-
-static inline int get_int(void)
-{
-	unsigned long flags;
-	int irq;
-
-	raw_spin_lock_irqsave(&asic_irq_lock, flags);
-
-	irq = (asic_read(int_int_scan) >> 4) - 1;
-
-	if (irq == 0 || irq >= NR_IRQS)
-		irq = -1;
-
-	raw_spin_unlock_irqrestore(&asic_irq_lock, flags);
-
-	return irq;
-}
-
-static void asic_irqdispatch(void)
-{
-	int irq;
-
-	irq = get_int();
-	if (irq < 0)
-		return;	 /* interrupt has already been cleared */
-
-	do_IRQ(irq);
-}
-
-static inline int clz(unsigned long x)
-{
-	__asm__(
-	"	.set	push					\n"
-	"	.set	mips32					\n"
-	"	clz	%0, %1					\n"
-	"	.set	pop					\n"
-	: "=r" (x)
-	: "r" (x));
-
-	return x;
-}
-
-/*
- * Version of ffs that only looks at bits 12..15.
- */
-static inline unsigned int irq_ffs(unsigned int pending)
-{
-	return fls(pending) - 1 + CAUSEB_IP;
-}
-
-/*
- * TODO: check how it works under EIC mode.
- */
-asmlinkage void plat_irq_dispatch(void)
-{
-	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
-	int irq;
-
-	irq = irq_ffs(pending);
-
-	if (irq == CAUSEF_IP3)
-		asic_irqdispatch();
-	else if (irq >= 0)
-		do_IRQ(irq);
-	else
-		spurious_interrupt();
-}
-
-void __init arch_init_irq(void)
-{
-	int i;
-
-	asic_irq_init();
-
-	/*
-	 * Initialize interrupt exception vectors.
-	 */
-	if (cpu_has_veic || cpu_has_vint) {
-		int nvec = cpu_has_veic ? 64 : 8;
-		for (i = 0; i < nvec; i++)
-			set_vi_handler(i, asic_irqdispatch);
-	}
-}
diff --git a/arch/mips/powertv/asic/irq_asic.c b/arch/mips/powertv/asic/irq_asic.c
deleted file mode 100644
index 9344902..0000000
--- a/arch/mips/powertv/asic/irq_asic.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Portions copyright (C) 2005-2009 Scientific Atlanta
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- * Modified from arch/mips/kernel/irq-rm7000.c:
- * Copyright (C) 2003 Ralf Baechle
- *
- * This program is free software; you can redistribute	it and/or modify it
- * under  the terms of	the GNU 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/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/irq.h>
-
-#include <asm/irq_cpu.h>
-#include <asm/mipsregs.h>
-
-#include <asm/mach-powertv/asic_regs.h>
-
-static inline void unmask_asic_irq(struct irq_data *d)
-{
-	unsigned long enable_bit;
-	unsigned int irq = d->irq;
-
-	enable_bit = (1 << (irq & 0x1f));
-
-	switch (irq >> 5) {
-	case 0:
-		asic_write(asic_read(ien_int_0) | enable_bit, ien_int_0);
-		break;
-	case 1:
-		asic_write(asic_read(ien_int_1) | enable_bit, ien_int_1);
-		break;
-	case 2:
-		asic_write(asic_read(ien_int_2) | enable_bit, ien_int_2);
-		break;
-	case 3:
-		asic_write(asic_read(ien_int_3) | enable_bit, ien_int_3);
-		break;
-	default:
-		BUG();
-	}
-}
-
-static inline void mask_asic_irq(struct irq_data *d)
-{
-	unsigned long disable_mask;
-	unsigned int irq = d->irq;
-
-	disable_mask = ~(1 << (irq & 0x1f));
-
-	switch (irq >> 5) {
-	case 0:
-		asic_write(asic_read(ien_int_0) & disable_mask, ien_int_0);
-		break;
-	case 1:
-		asic_write(asic_read(ien_int_1) & disable_mask, ien_int_1);
-		break;
-	case 2:
-		asic_write(asic_read(ien_int_2) & disable_mask, ien_int_2);
-		break;
-	case 3:
-		asic_write(asic_read(ien_int_3) & disable_mask, ien_int_3);
-		break;
-	default:
-		BUG();
-	}
-}
-
-static struct irq_chip asic_irq_chip = {
-	.name = "ASIC Level",
-	.irq_mask = mask_asic_irq,
-	.irq_unmask = unmask_asic_irq,
-};
-
-void __init asic_irq_init(void)
-{
-	int i;
-
-	/* set priority to 0 */
-	write_c0_status(read_c0_status() & ~(0x0000fc00));
-
-	asic_write(0, ien_int_0);
-	asic_write(0, ien_int_1);
-	asic_write(0, ien_int_2);
-	asic_write(0, ien_int_3);
-
-	asic_write(0x0fffffff, int_level_3_3);
-	asic_write(0xffffffff, int_level_3_2);
-	asic_write(0xffffffff, int_level_3_1);
-	asic_write(0xffffffff, int_level_3_0);
-	asic_write(0xffffffff, int_level_2_3);
-	asic_write(0xffffffff, int_level_2_2);
-	asic_write(0xffffffff, int_level_2_1);
-	asic_write(0xffffffff, int_level_2_0);
-	asic_write(0xffffffff, int_level_1_3);
-	asic_write(0xffffffff, int_level_1_2);
-	asic_write(0xffffffff, int_level_1_1);
-	asic_write(0xffffffff, int_level_1_0);
-	asic_write(0xffffffff, int_level_0_3);
-	asic_write(0xffffffff, int_level_0_2);
-	asic_write(0xffffffff, int_level_0_1);
-	asic_write(0xffffffff, int_level_0_0);
-
-	asic_write(0xf, int_int_scan);
-
-	/*
-	 * Initialize interrupt handlers.
-	 */
-	for (i = 0; i < NR_IRQS; i++)
-		irq_set_chip_and_handler(i, &asic_irq_chip, handle_level_irq);
-}
diff --git a/arch/mips/powertv/asic/prealloc-calliope.c b/arch/mips/powertv/asic/prealloc-calliope.c
deleted file mode 100644
index 98dc516..0000000
--- a/arch/mips/powertv/asic/prealloc-calliope.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * Memory pre-allocations for Calliope boxes.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author:	 Ken Eppinett
- *		 David Schleef <ds@schleef.org>
- */
-
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <asm/mach-powertv/asic.h>
-#include "prealloc.h"
-
-/*
- * NON_DVR_CAPABLE CALLIOPE RESOURCES
- */
-struct resource non_dvr_calliope_resources[] __initdata =
-{
-	/*
-	 * VIDEO / LX1
-	 */
-	/* Delta-Mu 1 image (2MiB) */
-	PREALLOC_NORMAL("ST231aImage", 0x24000000, 0x24200000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 1 monitor (8KiB) */
-	PREALLOC_NORMAL("ST231aMonitor", 0x24200000, 0x24202000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 1 RAM (~36.9MiB (32MiB - (2MiB + 8KiB))) */
-	PREALLOC_NORMAL("MediaMemory1", 0x24202000, 0x26700000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * Sysaudio Driver
-	 */
-	/* DSP code and data images (1MiB) */
-	PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC CPU PCM buffer (40KiB) */
-	PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC AUX buffer (128KiB) */
-	PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00020000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC Main buffer (128KiB) */
-	PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00020000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * STAVEM driver/STAPI
-	 */
-	/* 6MiB */
-	PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00600000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * DOCSIS Subsystem
-	 */
-	/* 7MiB */
-	PREALLOC_DOCSIS("Docsis", 0x27500000, 0x27c00000-1, IORESOURCE_MEM)
-
-	/*
-	 * GHW HAL Driver
-	 */
-	/* PowerTV Graphics Heap (14MiB) */
-	PREALLOC_NORMAL("GraphicsHeap", 0x26700000, 0x26700000+(14*1048576)-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * multi com buffer area
-	 */
-	/* 128KiB */
-	PREALLOC_NORMAL("MulticomSHM", 0x23700000, 0x23720000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * DMA Ring buffer (don't need recording buffers)
-	 */
-	/* 680KiB */
-	PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x000AA000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Display bins buffer for unit0
-	 */
-	/* 4KiB */
-	PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * AVFS: player HAL memory
-	 */
-	/* 945K * 3 for playback */
-	PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x002c4c00-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * PMEM
-	 */
-	/* Persistent memory for diagnostics (64KiB) */
-	PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
-	     (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Smartcard
-	 */
-	/* Read and write buffers for Internal/External cards (10KiB) */
-	PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * NAND Flash
-	 */
-	/* 10KiB */
-	PREALLOC_NORMAL("NandFlash", NAND_FLASH_BASE, NAND_FLASH_BASE+0x400-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * Synopsys GMAC Memory Region
-	 */
-	/* 64KiB */
-	PREALLOC_NORMAL("GMAC", 0x00000000, 0x00010000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * TFTPBuffer
-	 *
-	 *  This buffer is used in some minimal configurations (e.g. two-way
-	 *  loader) for storing software images
-	 */
-	PREALLOC_TFTP("TFTPBuffer", 0x00000000, MEBIBYTE(80)-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Add other resources here
-	 */
-
-	/*
-	 * End of Resource marker
-	 */
-	{
-		.flags	= 0,
-	},
-};
-
-
-struct resource non_dvr_vze_calliope_resources[] __initdata =
-{
-	/*
-	 * VIDEO / LX1
-	 */
-	/* Delta-Mu 1 image (2MiB) */
-	PREALLOC_NORMAL("ST231aImage", 0x22000000, 0x22200000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 1 monitor (8KiB) */
-	PREALLOC_NORMAL("ST231aMonitor", 0x22200000, 0x22202000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 1 RAM (10.12MiB) */
-	PREALLOC_NORMAL("MediaMemory1", 0x22202000, 0x22C20B85-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * Sysaudio Driver
-	 */
-	/* DSP code and data images (1MiB) */
-	PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC CPU PCM buffer (40KiB) */
-	PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC AUX buffer (16KiB) */
-	PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00004000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC Main buffer (16KiB) */
-	PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00004000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * STAVEM driver/STAPI
-	 */
-	/* 3.125MiB */
-	PREALLOC_NORMAL("AVMEMPartition0", 0x20396000, 0x206B6000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * GHW HAL Driver
-	 */
-	/* PowerTV Graphics Heap (2.59MiB) */
-	PREALLOC_NORMAL("GraphicsHeap", 0x20100000, 0x20396000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * multi com buffer area
-	 */
-	/* 128KiB */
-	PREALLOC_NORMAL("MulticomSHM", 0x206B6000, 0x206D6000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * DMA Ring buffer (don't need recording buffers)
-	 */
-	/* 680KiB */
-	PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x000AA000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Display bins buffer for unit0
-	 */
-	/* 4KiB */
-	PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * PMEM
-	 */
-	/* Persistent memory for diagnostics (64KiB) */
-	PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
-	     (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Smartcard
-	 */
-	/* Read and write buffers for Internal/External cards (10KiB) */
-	PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * NAND Flash
-	 */
-	/* 10KiB */
-	PREALLOC_NORMAL("NandFlash", NAND_FLASH_BASE, NAND_FLASH_BASE+0x400-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * Synopsys GMAC Memory Region
-	 */
-	/* 64KiB */
-	PREALLOC_NORMAL("GMAC", 0x00000000, 0x00010000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Add other resources here
-	 */
-
-	/*
-	 * End of Resource marker
-	 */
-	{
-		.flags	= 0,
-	},
-};
-
-struct resource non_dvr_vzf_calliope_resources[] __initdata =
-{
-	/*
-	 * VIDEO / LX1
-	 */
-	/* Delta-Mu 1 image (2MiB) */
-	PREALLOC_NORMAL("ST231aImage", 0x24000000, 0x24200000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 1 monitor (8KiB) */
-	PREALLOC_NORMAL("ST231aMonitor", 0x24200000, 0x24202000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 1 RAM (~19.4 (21.5MiB - (2MiB + 8KiB))) */
-	PREALLOC_NORMAL("MediaMemory1", 0x24202000, 0x25580000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * Sysaudio Driver
-	 */
-	/* DSP code and data images (1MiB) */
-	PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC CPU PCM buffer (40KiB) */
-	PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC AUX buffer (128KiB) */
-	PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00020000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC Main buffer (128KiB) */
-	PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00020000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * STAVEM driver/STAPI
-	 */
-	/* 4.5MiB */
-	PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00480000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * GHW HAL Driver
-	 */
-	/* PowerTV Graphics Heap (14MiB) */
-	PREALLOC_NORMAL("GraphicsHeap", 0x25600000, 0x25600000+(14*1048576)-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * multi com buffer area
-	 */
-	/* 128KiB */
-	PREALLOC_NORMAL("MulticomSHM", 0x23700000, 0x23720000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * DMA Ring buffer (don't need recording buffers)
-	 */
-	/* 680KiB */
-	PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x000AA000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Display bins buffer for unit0
-	 */
-	/* 4KiB */
-	PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Display bins buffer for unit1
-	 */
-	/* 4KiB */
-	PREALLOC_NORMAL("DisplayBins1", 0x00000000, 0x00001000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * AVFS: player HAL memory
-	 */
-	/* 945K * 3 for playback */
-	PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x002c4c00-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * PMEM
-	 */
-	/* Persistent memory for diagnostics (64KiB) */
-	PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
-	     (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Smartcard
-	 */
-	/* Read and write buffers for Internal/External cards (10KiB) */
-	PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * NAND Flash
-	 */
-	/* 10KiB */
-	PREALLOC_NORMAL("NandFlash", NAND_FLASH_BASE, NAND_FLASH_BASE+0x400-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * Synopsys GMAC Memory Region
-	 */
-	/* 64KiB */
-	PREALLOC_NORMAL("GMAC", 0x00000000, 0x00010000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Add other resources here
-	 */
-
-	/*
-	 * End of Resource marker
-	 */
-	{
-		.flags	= 0,
-	},
-};
diff --git a/arch/mips/powertv/asic/prealloc-cronus.c b/arch/mips/powertv/asic/prealloc-cronus.c
deleted file mode 100644
index 7c6ce75..0000000
--- a/arch/mips/powertv/asic/prealloc-cronus.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Memory pre-allocations for Cronus boxes.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author:	 Ken Eppinett
- *		 David Schleef <ds@schleef.org>
- */
-
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <asm/mach-powertv/asic.h>
-#include "prealloc.h"
-
-/*
- * DVR_CAPABLE CRONUS RESOURCES
- */
-struct resource dvr_cronus_resources[] __initdata =
-{
-	/*
-	 * VIDEO1 / LX1
-	 */
-	/* Delta-Mu 1 image (2MiB) */
-	PREALLOC_NORMAL("ST231aImage", 0x24000000, 0x24200000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 1 monitor (8KiB) */
-	PREALLOC_NORMAL("ST231aMonitor", 0x24200000, 0x24202000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 1 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
-	PREALLOC_NORMAL("MediaMemory1", 0x24202000, 0x26000000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * VIDEO2 / LX2
-	 */
-	/* Delta-Mu 2 image (2MiB) */
-	PREALLOC_NORMAL("ST231bImage", 0x60000000, 0x60200000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 2 monitor (8KiB) */
-	PREALLOC_NORMAL("ST231bMonitor", 0x60200000, 0x60202000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 2 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
-	PREALLOC_NORMAL("MediaMemory2", 0x60202000, 0x62000000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * Sysaudio Driver
-	 */
-	/* DSP code and data images (1MiB) */
-	PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC CPU PCM buffer (40KiB) */
-	PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC AUX buffer (128KiB) */
-	PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00020000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC Main buffer (128KiB) */
-	PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00020000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * STAVEM driver/STAPI
-	 *
-	 *  This memory area is used for allocating buffers for Video decoding
-	 *  purposes.  Allocation/De-allocation within this buffer is managed
-	 *  by the STAVMEM driver of the STAPI.	 They could be Decimated
-	 *  Picture Buffers, Intermediate Buffers, as deemed necessary for
-	 *  video decoding purposes, for any video decoders on Zeus.
-	 */
-	/* 12MiB */
-	PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00c00000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * DOCSIS Subsystem
-	 */
-	/* 7MiB */
-	PREALLOC_DOCSIS("Docsis", 0x67500000, 0x67c00000-1, IORESOURCE_MEM)
-
-	/*
-	 * GHW HAL Driver
-	 */
-	/* PowerTV Graphics Heap (14MiB) */
-	PREALLOC_NORMAL("GraphicsHeap", 0x62700000, 0x63500000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * multi com buffer area
-	 */
-	/* 128KiB */
-	PREALLOC_NORMAL("MulticomSHM", 0x26000000, 0x26020000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * DMA Ring buffer
-	 */
-	PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x002EA000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Display bins buffer for unit0
-	 */
-	/* 4KiB */
-	PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Display bins buffer for unit1
-	 */
-	/* 4KiB */
-	PREALLOC_NORMAL("DisplayBins1", 0x00000000, 0x00001000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * ITFS
-	 */
-	/* 815,104 bytes each for 2 ITFS partitions. */
-	PREALLOC_NORMAL("ITFS", 0x00000000, 0x0018E000-1, IORESOURCE_MEM)
-
-	/*
-	 * AVFS
-	 */
-	/* (945K * 8) = (128K * 3) 5 playbacks / 3 server */
-	PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x007c2000-1,
-		IORESOURCE_MEM)
-
-	/* 4KiB */
-	PREALLOC_NORMAL("AvfsFileSys", 0x00000000, 0x00001000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * PMEM
-	 */
-	/* Persistent memory for diagnostics (64KiB) */
-	PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
-	     (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Smartcard
-	 */
-	/* Read and write buffers for Internal/External cards (10KiB) */
-	PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * KAVNET
-	 */
-	/* NP Reset Vector - must be of the form xxCxxxxx (4KiB) */
-	PREALLOC_NORMAL("NP_Reset_Vector", 0x27c00000, 0x27c01000-1,
-		IORESOURCE_MEM)
-	/* NP Image - must be video bank 1 (320KiB) */
-	PREALLOC_NORMAL("NP_Image", 0x27020000, 0x27070000-1, IORESOURCE_MEM)
-	/* NP IPC - must be video bank 2 (512KiB) */
-	PREALLOC_NORMAL("NP_IPC", 0x63500000, 0x63580000-1, IORESOURCE_MEM)
-
-	/*
-	 * TFTPBuffer
-	 *
-	 *  This buffer is used in some minimal configurations (e.g. two-way
-	 *  loader) for storing software images
-	 */
-	PREALLOC_TFTP("TFTPBuffer", 0x00000000, MEBIBYTE(80)-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Add other resources here
-	 */
-
-	/*
-	 * End of Resource marker
-	 */
-	{
-		.flags	= 0,
-	},
-};
-
-/*
- * NON_DVR_CAPABLE CRONUS RESOURCES
- */
-struct resource non_dvr_cronus_resources[] __initdata =
-{
-	/*
-	 * VIDEO1 / LX1
-	 */
-	/* Delta-Mu 1 image (2MiB) */
-	PREALLOC_NORMAL("ST231aImage", 0x24000000, 0x24200000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 1 monitor (8KiB) */
-	PREALLOC_NORMAL("ST231aMonitor", 0x24200000, 0x24202000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 1 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
-	PREALLOC_NORMAL("MediaMemory1", 0x24202000, 0x26000000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * VIDEO2 / LX2
-	 */
-	/* Delta-Mu 2 image (2MiB) */
-	PREALLOC_NORMAL("ST231bImage", 0x60000000, 0x60200000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 2 monitor (8KiB) */
-	PREALLOC_NORMAL("ST231bMonitor", 0x60200000, 0x60202000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 2 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
-	PREALLOC_NORMAL("MediaMemory2", 0x60202000, 0x62000000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * Sysaudio Driver
-	 */
-	/* DSP code and data images (1MiB) */
-	PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC CPU PCM buffer (40KiB) */
-	PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC AUX buffer (128KiB) */
-	PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00020000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC Main buffer (128KiB) */
-	PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00020000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * STAVEM driver/STAPI
-	 *
-	 *  This memory area is used for allocating buffers for Video decoding
-	 *  purposes.  Allocation/De-allocation within this buffer is managed
-	 *  by the STAVMEM driver of the STAPI.	 They could be Decimated
-	 *  Picture Buffers, Intermediate Buffers, as deemed necessary for
-	 *  video decoding purposes, for any video decoders on Zeus.
-	 */
-	/* 12MiB */
-	PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00c00000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * DOCSIS Subsystem
-	 */
-	/* 7MiB */
-	PREALLOC_DOCSIS("Docsis", 0x67500000, 0x67c00000-1, IORESOURCE_MEM)
-
-	/*
-	 * GHW HAL Driver
-	 */
-	/* PowerTV Graphics Heap (14MiB) */
-	PREALLOC_NORMAL("GraphicsHeap", 0x62700000, 0x63500000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * multi com buffer area
-	 */
-	/* 128KiB */
-	PREALLOC_NORMAL("MulticomSHM", 0x26000000, 0x26020000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * DMA Ring buffer (don't need recording buffers)
-	 */
-	/* 680KiB */
-	PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x000AA000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Display bins buffer for unit0
-	 */
-	/* 4KiB */
-	PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Display bins buffer for unit1
-	 */
-	/* 4KiB */
-	PREALLOC_NORMAL("DisplayBins1", 0x00000000, 0x00001000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * AVFS: player HAL memory
-	 */
-	/* 945K * 3 for playback */
-	PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x002c4c00-1, IORESOURCE_MEM)
-
-	/*
-	 * PMEM
-	 */
-	/* Persistent memory for diagnostics (64KiB) */
-	PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
-	     (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Smartcard
-	 */
-	/* Read and write buffers for Internal/External cards (10KiB) */
-	PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1, IORESOURCE_MEM)
-
-	/*
-	 * KAVNET
-	 */
-	/* NP Reset Vector - must be of the form xxCxxxxx (4KiB) */
-	PREALLOC_NORMAL("NP_Reset_Vector", 0x27c00000, 0x27c01000-1,
-		IORESOURCE_MEM)
-	/* NP Image - must be video bank 1 (320KiB) */
-	PREALLOC_NORMAL("NP_Image", 0x27020000, 0x27070000-1, IORESOURCE_MEM)
-	/* NP IPC - must be video bank 2 (512KiB) */
-	PREALLOC_NORMAL("NP_IPC", 0x63500000, 0x63580000-1, IORESOURCE_MEM)
-
-	/*
-	 * NAND Flash
-	 */
-	/* 10KiB */
-	PREALLOC_NORMAL("NandFlash", NAND_FLASH_BASE, NAND_FLASH_BASE+0x400-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * Add other resources here
-	 */
-
-	/*
-	 * End of Resource marker
-	 */
-	{
-		.flags	= 0,
-	},
-};
diff --git a/arch/mips/powertv/asic/prealloc-cronuslite.c b/arch/mips/powertv/asic/prealloc-cronuslite.c
deleted file mode 100644
index a7937ba..0000000
--- a/arch/mips/powertv/asic/prealloc-cronuslite.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Memory pre-allocations for Cronus Lite boxes.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author:	 Ken Eppinett
- *		 David Schleef <ds@schleef.org>
- */
-
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <asm/mach-powertv/asic.h>
-#include "prealloc.h"
-
-/*
- * NON_DVR_CAPABLE CRONUSLITE RESOURCES
- */
-struct resource non_dvr_cronuslite_resources[] __initdata =
-{
-	/*
-	 * VIDEO2 / LX2
-	 */
-	/* Delta-Mu 1 image (2MiB) */
-	PREALLOC_NORMAL("ST231aImage", 0x60000000, 0x60200000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 1 monitor (8KiB) */
-	PREALLOC_NORMAL("ST231aMonitor", 0x60200000, 0x60202000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 1 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
-	PREALLOC_NORMAL("MediaMemory1", 0x60202000, 0x62000000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * Sysaudio Driver
-	 */
-	/* DSP code and data images (1MiB) */
-	PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC CPU PCM buffer (40KiB) */
-	PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC AUX buffer (128KiB) */
-	PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00020000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC Main buffer (128KiB) */
-	PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00020000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * STAVEM driver/STAPI
-	 *
-	 *  This memory area is used for allocating buffers for Video decoding
-	 *  purposes.  Allocation/De-allocation within this buffer is managed
-	 *  by the STAVMEM driver of the STAPI.	 They could be Decimated
-	 *  Picture Buffers, Intermediate Buffers, as deemed necessary for
-	 *  video decoding purposes, for any video decoders on Zeus.
-	 */
-	/* 6MiB */
-	PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00600000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * DOCSIS Subsystem
-	 */
-	/* 7MiB */
-	PREALLOC_DOCSIS("Docsis", 0x67500000, 0x67c00000-1, IORESOURCE_MEM)
-
-	/*
-	 * GHW HAL Driver
-	 */
-	/* PowerTV Graphics Heap (14MiB) */
-	PREALLOC_NORMAL("GraphicsHeap", 0x62700000, 0x63500000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * multi com buffer area
-	 */
-	/* 128KiB */
-	PREALLOC_NORMAL("MulticomSHM", 0x26000000, 0x26020000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * DMA Ring buffer (don't need recording buffers)
-	 */
-	/* 680KiB */
-	PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x000AA000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Display bins buffer for unit0
-	 */
-	/* 4KiB */
-	PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Display bins buffer for unit1
-	 */
-	/* 4KiB */
-	PREALLOC_NORMAL("DisplayBins1", 0x00000000, 0x00001000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * AVFS: player HAL memory
-	 */
-	/* 945K * 3 for playback */
-	PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x002c4c00-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * PMEM
-	 */
-	/* Persistent memory for diagnostics (64KiB) */
-	PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
-	     (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Smartcard
-	 */
-	/* Read and write buffers for Internal/External cards (10KiB) */
-	PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1, IORESOURCE_MEM)
-
-	/*
-	 * KAVNET
-	 */
-	/* NP Reset Vector - must be of the form xxCxxxxx (4KiB) */
-	PREALLOC_NORMAL("NP_Reset_Vector", 0x27c00000, 0x27c01000-1,
-		IORESOURCE_MEM)
-	/* NP Image - must be video bank 1 (320KiB) */
-	PREALLOC_NORMAL("NP_Image", 0x27020000, 0x27070000-1, IORESOURCE_MEM)
-	/* NP IPC - must be video bank 2 (512KiB) */
-	PREALLOC_NORMAL("NP_IPC", 0x63500000, 0x63580000-1, IORESOURCE_MEM)
-
-	/*
-	 * NAND Flash
-	 */
-	/* 10KiB */
-	PREALLOC_NORMAL("NandFlash", NAND_FLASH_BASE, NAND_FLASH_BASE+0x400-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * TFTPBuffer
-	 *
-	 *  This buffer is used in some minimal configurations (e.g. two-way
-	 *  loader) for storing software images
-	 */
-	PREALLOC_TFTP("TFTPBuffer", 0x00000000, MEBIBYTE(80)-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Add other resources here
-	 */
-
-	/*
-	 * End of Resource marker
-	 */
-	{
-		.flags	= 0,
-	},
-};
diff --git a/arch/mips/powertv/asic/prealloc-gaia.c b/arch/mips/powertv/asic/prealloc-gaia.c
deleted file mode 100644
index 2303bbf..0000000
--- a/arch/mips/powertv/asic/prealloc-gaia.c
+++ /dev/null
@@ -1,589 +0,0 @@
-/*
- * Memory pre-allocations for Gaia boxes.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author:	 David VomLehn
- */
-
-#include <linux/init.h>
-#include <asm/mach-powertv/asic.h>
-
-/*
- * DVR_CAPABLE GAIA RESOURCES
- */
-struct resource dvr_gaia_resources[] __initdata = {
-	/*
-	 *
-	 * VIDEO1 / LX1
-	 *
-	 */
-	{
-		.name	= "ST231aImage",	/* Delta-Mu 1 image and ram */
-		.start	= 0x24000000,
-		.end	= 0x241FFFFF,		/* 2MiB */
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.name	= "ST231aMonitor",	/* 8KiB block ST231a monitor */
-		.start	= 0x24200000,
-		.end	= 0x24201FFF,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.name	= "MediaMemory1",
-		.start	= 0x24202000,
-		.end	= 0x25FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
-		.flags	= IORESOURCE_MEM,
-	},
-	/*
-	 *
-	 * VIDEO2 / LX2
-	 *
-	 */
-	{
-		.name	= "ST231bImage",	/* Delta-Mu 2 image and ram */
-		.start	= 0x60000000,
-		.end	= 0x601FFFFF,		/* 2MiB */
-		.flags	= IORESOURCE_IO,
-	},
-	{
-		.name	= "ST231bMonitor",	/* 8KiB block ST231b monitor */
-		.start	= 0x60200000,
-		.end	= 0x60201FFF,
-		.flags	= IORESOURCE_IO,
-	},
-	{
-		.name	= "MediaMemory2",
-		.start	= 0x60202000,
-		.end	= 0x61FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
-		.flags	= IORESOURCE_IO,
-	},
-	/*
-	 *
-	 * Sysaudio Driver
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  DSP_Image_Buff - DSP code and data images (1MB)
-	 *  ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB)
-	 *  ADSC_AUX_Buff - ADSC AUX buffer (16KB)
-	 *  ADSC_Main_Buff - ADSC Main buffer (16KB)
-	 *
-	 */
-	{
-		.name	= "DSP_Image_Buff",
-		.start	= 0x00000000,
-		.end	= 0x000FFFFF,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.name	= "ADSC_CPU_PCM_Buff",
-		.start	= 0x00000000,
-		.end	= 0x00009FFF,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.name	= "ADSC_AUX_Buff",
-		.start	= 0x00000000,
-		.end	= 0x00003FFF,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.name	= "ADSC_Main_Buff",
-		.start	= 0x00000000,
-		.end	= 0x00003FFF,
-		.flags	= IORESOURCE_MEM,
-	},
-	/*
-	 *
-	 * STAVEM driver/STAPI
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  This memory area is used for allocating buffers for Video decoding
-	 *  purposes.  Allocation/De-allocation within this buffer is managed
-	 *  by the STAVMEM driver of the STAPI.	 They could be Decimated
-	 *  Picture Buffers, Intermediate Buffers, as deemed necessary for
-	 *  video decoding purposes, for any video decoders on Zeus.
-	 *
-	 */
-	{
-		.name	= "AVMEMPartition0",
-		.start	= 0x63580000,
-		.end	= 0x64180000 - 1,  /* 12 MB total */
-		.flags	= IORESOURCE_IO,
-	},
-	/*
-	 *
-	 * DOCSIS Subsystem
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  Docsis -
-	 *
-	 */
-	{
-		.name	= "Docsis",
-		.start	= 0x62000000,
-		.end	= 0x62700000 - 1,	/* 7 MB total */
-		.flags	= IORESOURCE_IO,
-	},
-	/*
-	 *
-	 * GHW HAL Driver
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  GraphicsHeap - PowerTV Graphics Heap
-	 *
-	 */
-	{
-		.name	= "GraphicsHeap",
-		.start	= 0x62700000,
-		.end	= 0x63500000 - 1,	/* 14 MB total */
-		.flags	= IORESOURCE_IO,
-	},
-	/*
-	 *
-	 * multi com buffer area
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  Docsis -
-	 *
-	 */
-	{
-		.name	= "MulticomSHM",
-		.start	= 0x26000000,
-		.end	= 0x26020000 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	/*
-	 *
-	 * DMA Ring buffer
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  Docsis -
-	 *
-	 */
-	{
-		.name	= "BMM_Buffer",
-		.start	= 0x00000000,
-		.end	= 0x00280000 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	/*
-	 *
-	 * Display bins buffer for unit0
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  Display Bins for unit0
-	 *
-	 */
-	{
-		.name	= "DisplayBins0",
-		.start	= 0x00000000,
-		.end	= 0x00000FFF,		/* 4 KB total */
-		.flags	= IORESOURCE_MEM,
-	},
-	/*
-	 *
-	 * Display bins buffer
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  Display Bins for unit1
-	 *
-	 */
-	{
-		.name	= "DisplayBins1",
-		.start	= 0x64AD4000,
-		.end	= 0x64AD5000 - 1,  /* 4 KB total */
-		.flags	= IORESOURCE_IO,
-	},
-	/*
-	 *
-	 * ITFS
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  Docsis -
-	 *
-	 */
-	{
-		.name	= "ITFS",
-		.start	= 0x64180000,
-		/* 815,104 bytes each for 2 ITFS partitions. */
-		.end	= 0x6430DFFF,
-		.flags	= IORESOURCE_IO,
-	},
-	/*
-	 *
-	 * AVFS
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  Docsis -
-	 *
-	 */
-	{
-		.name	= "AvfsDmaMem",
-		.start	= 0x6430E000,
-		/* (945K * 8) = (128K *3) 5 playbacks / 3 server */
-		.end	= 0x64AD0000 - 1,
-		.flags	= IORESOURCE_IO,
-	},
-	{
-		.name	= "AvfsFileSys",
-		.start	= 0x64AD0000,
-		.end	= 0x64AD1000 - 1,  /* 4K */
-		.flags	= IORESOURCE_IO,
-	},
-	/*
-	 *
-	 * Smartcard
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  Read and write buffers for Internal/External cards
-	 *
-	 */
-	{
-		.name	= "SmartCardInfo",
-		.start	= 0x64AD1000,
-		.end	= 0x64AD3800 - 1,
-		.flags	= IORESOURCE_IO,
-	},
-	/*
-	 *
-	 * KAVNET
-	 *    NP Reset Vector - must be of the form xxCxxxxx
-	 *	   NP Image - must be video bank 1
-	 *	   NP IPC - must be video bank 2
-	 */
-	{
-		.name	= "NP_Reset_Vector",
-		.start	= 0x27c00000,
-		.end	= 0x27c01000 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.name	= "NP_Image",
-		.start	= 0x27020000,
-		.end	= 0x27060000 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.name	= "NP_IPC",
-		.start	= 0x63500000,
-		.end	= 0x63580000 - 1,
-		.flags	= IORESOURCE_IO,
-	},
-	/*
-	 * Add other resources here
-	 */
-	{ },
-};
-
-/*
- * NON_DVR_CAPABLE GAIA RESOURCES
- */
-struct resource non_dvr_gaia_resources[] __initdata = {
-	/*
-	 *
-	 * VIDEO1 / LX1
-	 *
-	 */
-	{
-		.name	= "ST231aImage",	/* Delta-Mu 1 image and ram */
-		.start	= 0x24000000,
-		.end	= 0x241FFFFF,		/* 2MiB */
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.name	= "ST231aMonitor",	/* 8KiB block ST231a monitor */
-		.start	= 0x24200000,
-		.end	= 0x24201FFF,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.name	= "MediaMemory1",
-		.start	= 0x24202000,
-		.end	= 0x25FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
-		.flags	= IORESOURCE_MEM,
-	},
-	/*
-	 *
-	 * VIDEO2 / LX2
-	 *
-	 */
-	{
-		.name	= "ST231bImage",	/* Delta-Mu 2 image and ram */
-		.start	= 0x60000000,
-		.end	= 0x601FFFFF,		/* 2MiB */
-		.flags	= IORESOURCE_IO,
-	},
-	{
-		.name	= "ST231bMonitor",	/* 8KiB block ST231b monitor */
-		.start	= 0x60200000,
-		.end	= 0x60201FFF,
-		.flags	= IORESOURCE_IO,
-	},
-	{
-		.name	= "MediaMemory2",
-		.start	= 0x60202000,
-		.end	= 0x61FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
-		.flags	= IORESOURCE_IO,
-	},
-	/*
-	 *
-	 * Sysaudio Driver
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  DSP_Image_Buff - DSP code and data images (1MB)
-	 *  ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB)
-	 *  ADSC_AUX_Buff - ADSC AUX buffer (16KB)
-	 *  ADSC_Main_Buff - ADSC Main buffer (16KB)
-	 *
-	 */
-	{
-		.name	= "DSP_Image_Buff",
-		.start	= 0x00000000,
-		.end	= 0x000FFFFF,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.name	= "ADSC_CPU_PCM_Buff",
-		.start	= 0x00000000,
-		.end	= 0x00009FFF,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.name	= "ADSC_AUX_Buff",
-		.start	= 0x00000000,
-		.end	= 0x00003FFF,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.name	= "ADSC_Main_Buff",
-		.start	= 0x00000000,
-		.end	= 0x00003FFF,
-		.flags	= IORESOURCE_MEM,
-	},
-	/*
-	 *
-	 * STAVEM driver/STAPI
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  This memory area is used for allocating buffers for Video decoding
-	 *  purposes.  Allocation/De-allocation within this buffer is managed
-	 *  by the STAVMEM driver of the STAPI.	 They could be Decimated
-	 *  Picture Buffers, Intermediate Buffers, as deemed necessary for
-	 *  video decoding purposes, for any video decoders on Zeus.
-	 *
-	 */
-	{
-		.name	= "AVMEMPartition0",
-		.start	= 0x63580000,
-		.end	= 0x64180000 - 1,  /* 12 MB total */
-		.flags	= IORESOURCE_IO,
-	},
-	/*
-	 *
-	 * DOCSIS Subsystem
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  Docsis -
-	 *
-	 */
-	{
-		.name	= "Docsis",
-		.start	= 0x62000000,
-		.end	= 0x62700000 - 1,	/* 7 MB total */
-		.flags	= IORESOURCE_IO,
-	},
-	/*
-	 *
-	 * GHW HAL Driver
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  GraphicsHeap - PowerTV Graphics Heap
-	 *
-	 */
-	{
-		.name	= "GraphicsHeap",
-		.start	= 0x62700000,
-		.end	= 0x63500000 - 1,	/* 14 MB total */
-		.flags	= IORESOURCE_IO,
-	},
-	/*
-	 *
-	 * multi com buffer area
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  Docsis -
-	 *
-	 */
-	{
-		.name	= "MulticomSHM",
-		.start	= 0x26000000,
-		.end	= 0x26020000 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	/*
-	 *
-	 * DMA Ring buffer
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  Docsis -
-	 *
-	 */
-	{
-		.name	= "BMM_Buffer",
-		.start	= 0x00000000,
-		.end	= 0x000AA000 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	/*
-	 *
-	 * Display bins buffer for unit0
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  Display Bins for unit0
-	 *
-	 */
-	{
-		.name	= "DisplayBins0",
-		.start	= 0x00000000,
-		.end	= 0x00000FFF,		/* 4 KB total */
-		.flags	= IORESOURCE_MEM,
-	},
-	/*
-	 *
-	 * Display bins buffer
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  Display Bins for unit1
-	 *
-	 */
-	{
-		.name	= "DisplayBins1",
-		.start	= 0x64AD4000,
-		.end	= 0x64AD5000 - 1,  /* 4 KB total */
-		.flags	= IORESOURCE_IO,
-	},
-	/*
-	 *
-	 * AVFS: player HAL memory
-	 *
-	 *
-	 */
-	{
-		.name	= "AvfsDmaMem",
-		.start	= 0x6430E000,
-		.end	= 0x645D2C00 - 1,  /* 945K * 3 for playback */
-		.flags	= IORESOURCE_IO,
-	},
-	/*
-	 *
-	 * PMEM
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  Persistent memory for diagnostics.
-	 *
-	 */
-	{
-		.name	= "DiagPersistentMemory",
-		.start	= 0x00000000,
-		.end	= 0x10000 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	/*
-	 *
-	 * Smartcard
-	 *
-	 * This driver requires:
-	 *
-	 * Arbitrary Based Buffers:
-	 *  Read and write buffers for Internal/External cards
-	 *
-	 */
-	{
-		.name	= "SmartCardInfo",
-		.start	= 0x64AD1000,
-		.end	= 0x64AD3800 - 1,
-		.flags	= IORESOURCE_IO,
-	},
-	/*
-	 *
-	 * KAVNET
-	 *    NP Reset Vector - must be of the form xxCxxxxx
-	 *	   NP Image - must be video bank 1
-	 *	   NP IPC - must be video bank 2
-	 */
-	{
-		.name	= "NP_Reset_Vector",
-		.start	= 0x27c00000,
-		.end	= 0x27c01000 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.name	= "NP_Image",
-		.start	= 0x27020000,
-		.end	= 0x27060000 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.name	= "NP_IPC",
-		.start	= 0x63500000,
-		.end	= 0x63580000 - 1,
-		.flags	= IORESOURCE_IO,
-	},
-	{ },
-};
diff --git a/arch/mips/powertv/asic/prealloc-zeus.c b/arch/mips/powertv/asic/prealloc-zeus.c
deleted file mode 100644
index 6e76f09..0000000
--- a/arch/mips/powertv/asic/prealloc-zeus.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Memory pre-allocations for Zeus boxes.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author:	 Ken Eppinett
- *		 David Schleef <ds@schleef.org>
- */
-
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <asm/mach-powertv/asic.h>
-#include "prealloc.h"
-
-/*
- * DVR_CAPABLE RESOURCES
- */
-struct resource dvr_zeus_resources[] __initdata =
-{
-	/*
-	 * VIDEO1 / LX1
-	 */
-	/* Delta-Mu 1 image (2MiB) */
-	PREALLOC_NORMAL("ST231aImage", 0x20000000, 0x20200000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 1 monitor (8KiB) */
-	PREALLOC_NORMAL("ST231aMonitor", 0x20200000, 0x20202000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 1 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
-	PREALLOC_NORMAL("MediaMemory1", 0x20202000, 0x22000000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * VIDEO2 / LX2
-	 */
-	/* Delta-Mu 2 image (2MiB) */
-	PREALLOC_NORMAL("ST231bImage", 0x30000000, 0x30200000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 2 monitor (8KiB) */
-	PREALLOC_NORMAL("ST231bMonitor", 0x30200000, 0x30202000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 2 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
-	PREALLOC_NORMAL("MediaMemory2", 0x30202000, 0x32000000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * Sysaudio Driver
-	 */
-	/* DSP code and data images (1MiB) */
-	PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC CPU PCM buffer (40KiB) */
-	PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC AUX buffer (16KiB) */
-	PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00004000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC Main buffer (16KiB) */
-	PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00004000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * STAVEM driver/STAPI
-	 *
-	 *  This memory area is used for allocating buffers for Video decoding
-	 *  purposes.  Allocation/De-allocation within this buffer is managed
-	 *  by the STAVMEM driver of the STAPI.	 They could be Decimated
-	 *  Picture Buffers, Intermediate Buffers, as deemed necessary for
-	 *  video decoding purposes, for any video decoders on Zeus.
-	 */
-	/* 12MiB */
-	PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00c00000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * DOCSIS Subsystem
-	 */
-	/* 7MiB */
-	PREALLOC_DOCSIS("Docsis", 0x40100000, 0x40800000-1, IORESOURCE_MEM)
-
-	/*
-	 * GHW HAL Driver
-	 */
-	/* PowerTV Graphics Heap (14MiB) */
-	PREALLOC_NORMAL("GraphicsHeap", 0x46900000, 0x47700000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * multi com buffer area
-	 */
-	/* 128KiB */
-	PREALLOC_NORMAL("MulticomSHM", 0x47900000, 0x47920000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * DMA Ring buffer
-	 */
-	/* 2.5MiB */
-	PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x00280000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Display bins buffer for unit0
-	 */
-	/* 4KiB */
-	PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Display bins buffer for unit1
-	 */
-	/* 4KiB */
-	PREALLOC_NORMAL("DisplayBins1", 0x00000000, 0x00001000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * ITFS
-	 */
-	/* 815,104 bytes each for 2 ITFS partitions. */
-	PREALLOC_NORMAL("ITFS", 0x00000000, 0x0018E000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * AVFS
-	 */
-	/* (945K * 8) = (128K * 3) 5 playbacks / 3 server */
-	PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x007c2000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* 4KiB */
-	PREALLOC_NORMAL("AvfsFileSys", 0x00000000, 0x00001000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * PMEM
-	 */
-	/* Persistent memory for diagnostics (64KiB) */
-	PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
-	     (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Smartcard
-	 */
-	/* Read and write buffers for Internal/External cards (10KiB) */
-	PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * TFTPBuffer
-	 *
-	 *  This buffer is used in some minimal configurations (e.g. two-way
-	 *  loader) for storing software images
-	 */
-	PREALLOC_TFTP("TFTPBuffer", 0x00000000, MEBIBYTE(80)-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Add other resources here
-	 */
-
-	/*
-	 * End of Resource marker
-	 */
-	{
-		.flags	= 0,
-	},
-};
-
-/*
- * NON_DVR_CAPABLE ZEUS RESOURCES
- */
-struct resource non_dvr_zeus_resources[] __initdata =
-{
-	/*
-	 * VIDEO1 / LX1
-	 */
-	/* Delta-Mu 1 image (2MiB) */
-	PREALLOC_NORMAL("ST231aImage", 0x20000000, 0x20200000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 1 monitor (8KiB) */
-	PREALLOC_NORMAL("ST231aMonitor", 0x20200000, 0x20202000-1,
-		IORESOURCE_MEM)
-	/* Delta-Mu 1 RAM (~29.9MiB (32MiB - (2MiB + 8KiB))) */
-	PREALLOC_NORMAL("MediaMemory1", 0x20202000, 0x22000000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * Sysaudio Driver
-	 */
-	/* DSP code and data images (1MiB) */
-	PREALLOC_NORMAL("DSP_Image_Buff", 0x00000000, 0x00100000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC CPU PCM buffer (40KiB) */
-	PREALLOC_NORMAL("ADSC_CPU_PCM_Buff", 0x00000000, 0x0000A000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC AUX buffer (16KiB) */
-	PREALLOC_NORMAL("ADSC_AUX_Buff", 0x00000000, 0x00004000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-	/* ADSC Main buffer (16KiB) */
-	PREALLOC_NORMAL("ADSC_Main_Buff", 0x00000000, 0x00004000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * STAVEM driver/STAPI
-	 */
-	/* 6MiB */
-	PREALLOC_NORMAL("AVMEMPartition0", 0x00000000, 0x00600000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * DOCSIS Subsystem
-	 */
-	/* 7MiB */
-	PREALLOC_DOCSIS("Docsis", 0x40100000, 0x40800000-1, IORESOURCE_MEM)
-
-	/*
-	 * GHW HAL Driver
-	 */
-	/* PowerTV Graphics Heap (14MiB) */
-	PREALLOC_NORMAL("GraphicsHeap", 0x46900000, 0x47700000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * multi com buffer area
-	 */
-	/* 128KiB */
-	PREALLOC_NORMAL("MulticomSHM", 0x47900000, 0x47920000-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * DMA Ring buffer
-	 */
-	/* 2.5MiB */
-	PREALLOC_NORMAL("BMM_Buffer", 0x00000000, 0x00280000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Display bins buffer for unit0
-	 */
-	/* 4KiB */
-	PREALLOC_NORMAL("DisplayBins0", 0x00000000, 0x00001000-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * AVFS: player HAL memory
-	 */
-	/* 945K * 3 for playback */
-	PREALLOC_NORMAL("AvfsDmaMem", 0x00000000, 0x002c4c00-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * PMEM
-	 */
-	/* Persistent memory for diagnostics (64KiB) */
-	PREALLOC_PMEM("DiagPersistentMemory", 0x00000000, 0x10000-1,
-	     (IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Smartcard
-	 */
-	/* Read and write buffers for Internal/External cards (10KiB) */
-	PREALLOC_NORMAL("SmartCardInfo", 0x00000000, 0x2800-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * NAND Flash
-	 */
-	/* 10KiB */
-	PREALLOC_NORMAL("NandFlash", NAND_FLASH_BASE, NAND_FLASH_BASE+0x400-1,
-		IORESOURCE_MEM)
-
-	/*
-	 * TFTPBuffer
-	 *
-	 *  This buffer is used in some minimal configurations (e.g. two-way
-	 *  loader) for storing software images
-	 */
-	PREALLOC_TFTP("TFTPBuffer", 0x00000000, MEBIBYTE(80)-1,
-		(IORESOURCE_MEM|IORESOURCE_PTV_RES_LOEXT))
-
-	/*
-	 * Add other resources here
-	 */
-
-	/*
-	 * End of Resource marker
-	 */
-	{
-		.flags	= 0,
-	},
-};
diff --git a/arch/mips/powertv/asic/prealloc.h b/arch/mips/powertv/asic/prealloc.h
deleted file mode 100644
index 8e682df..0000000
--- a/arch/mips/powertv/asic/prealloc.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Definitions for memory preallocations
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _ARCH_MIPS_POWERTV_ASIC_PREALLOC_H
-#define _ARCH_MIPS_POWERTV_ASIC_PREALLOC_H
-
-#define KIBIBYTE(n) ((n) * 1024)    /* Number of kibibytes */
-#define MEBIBYTE(n) ((n) * KIBIBYTE(1024)) /* Number of mebibytes */
-
-/* "struct resource" array element definition */
-#define PREALLOC(NAME, START, END, FLAGS) {	\
-		.name = (NAME),			\
-		.start = (START),		\
-		.end = (END),			\
-		.flags = (FLAGS)		\
-	},
-
-/* Individual resources in the preallocated resource arrays are defined using
- *  macros.  These macros are conditionally defined based on their
- *  corresponding kernel configuration flag:
- *    - CONFIG_PREALLOC_NORMAL: preallocate resources for a normal settop box
- *    - CONFIG_PREALLOC_TFTP: preallocate the TFTP download resource
- *    - CONFIG_PREALLOC_DOCSIS: preallocate the DOCSIS resource
- *    - CONFIG_PREALLOC_PMEM: reserve space for persistent memory
- */
-#ifdef CONFIG_PREALLOC_NORMAL
-#define PREALLOC_NORMAL(name, start, end, flags) \
-   PREALLOC(name, start, end, flags)
-#else
-#define PREALLOC_NORMAL(name, start, end, flags)
-#endif
-
-#ifdef CONFIG_PREALLOC_TFTP
-#define PREALLOC_TFTP(name, start, end, flags) \
-   PREALLOC(name, start, end, flags)
-#else
-#define PREALLOC_TFTP(name, start, end, flags)
-#endif
-
-#ifdef CONFIG_PREALLOC_DOCSIS
-#define PREALLOC_DOCSIS(name, start, end, flags) \
-   PREALLOC(name, start, end, flags)
-#else
-#define PREALLOC_DOCSIS(name, start, end, flags)
-#endif
-
-#ifdef CONFIG_PREALLOC_PMEM
-#define PREALLOC_PMEM(name, start, end, flags) \
-   PREALLOC(name, start, end, flags)
-#else
-#define PREALLOC_PMEM(name, start, end, flags)
-#endif
-#endif
diff --git a/arch/mips/powertv/init.c b/arch/mips/powertv/init.c
deleted file mode 100644
index 4989263..0000000
--- a/arch/mips/powertv/init.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 1999, 2000, 2004, 2005	 MIPS Technologies, Inc.
- *	All rights reserved.
- *	Authors: Carsten Langgaard <carstenl@mips.com>
- *		 Maciej W. Rozycki <macro@mips.com>
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- *  This program is free software; you can distribute 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 it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You 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.
- *
- * PROM library initialisation code.
- */
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-#include <asm/bootinfo.h>
-#include <linux/io.h>
-#include <asm/cacheflush.h>
-#include <asm/traps.h>
-
-#include <asm/mips-boards/generic.h>
-#include <asm/mach-powertv/asic.h>
-
-#include "init.h"
-
-static int *_prom_envp;
-unsigned long _prom_memsize;
-
-/*
- * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
- * This macro take care of sign extension, if running in 64-bit mode.
- */
-#define prom_envp(index) ((char *)(long)_prom_envp[(index)])
-
-char *prom_getenv(char *envname)
-{
-	char *result = NULL;
-
-	if (_prom_envp != NULL) {
-		/*
-		 * Return a pointer to the given environment variable.
-		 * In 64-bit mode: we're using 64-bit pointers, but all pointers
-		 * in the PROM structures are only 32-bit, so we need some
-		 * workarounds, if we are running in 64-bit mode.
-		 */
-		int i, index = 0;
-
-		i = strlen(envname);
-
-		while (prom_envp(index)) {
-			if (strncmp(envname, prom_envp(index), i) == 0) {
-				result = prom_envp(index + 1);
-				break;
-			}
-			index += 2;
-		}
-	}
-
-	return result;
-}
-
-void __init prom_init(void)
-{
-	int prom_argc;
-	char *prom_argv;
-
-	prom_argc = fw_arg0;
-	prom_argv = (char *) fw_arg1;
-	_prom_envp = (int *) fw_arg2;
-	_prom_memsize = (unsigned long) fw_arg3;
-
-	if (prom_argc == 1) {
-		strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE);
-		strlcat(arcs_cmdline, prom_argv, COMMAND_LINE_SIZE);
-	}
-
-	configure_platform();
-	prom_meminit();
-}
diff --git a/arch/mips/powertv/init.h b/arch/mips/powertv/init.h
deleted file mode 100644
index c1a8bd0..0000000
--- a/arch/mips/powertv/init.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Definitions from powertv init.c file
- *
- * Copyright (C) 2009  Cisco Systems, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have 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
- *
- * Author: David VomLehn
- */
-
-#ifndef _POWERTV_INIT_H
-#define _POWERTV_INIT_H
-extern unsigned long _prom_memsize;
-extern void prom_meminit(void);
-extern char *prom_getenv(char *name);
-#endif
diff --git a/arch/mips/powertv/ioremap.c b/arch/mips/powertv/ioremap.c
deleted file mode 100644
index d060478..0000000
--- a/arch/mips/powertv/ioremap.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- *			ioremap.c
- *
- * Support for mapping between dma_addr_t values a phys_addr_t values.
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author:	 David VomLehn <dvomlehn@cisco.com>
- *
- * Description:	 Defines the platform resources for the SA settop.
- *
- * NOTE: The bootloader allocates persistent memory at an address which is
- * 16 MiB below the end of the highest address in KSEG0. All fixed
- * address memory reservations must avoid this region.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include <asm/mach-powertv/ioremap.h>
-
-/*
- * Define the sizes of and masks for grains in physical and DMA space. The
- * values are the same but the types are not.
- */
-#define IOR_PHYS_GRAIN		((phys_addr_t) 1 << IOR_LSBITS)
-#define IOR_PHYS_GRAIN_MASK	(IOR_PHYS_GRAIN - 1)
-
-#define IOR_DMA_GRAIN		((dma_addr_t) 1 << IOR_LSBITS)
-#define IOR_DMA_GRAIN_MASK	(IOR_DMA_GRAIN - 1)
-
-/*
- * Values that, when accessed by an index derived from a phys_addr_t and
- * added to phys_addr_t value, yield a DMA address
- */
-struct ior_phys_to_dma _ior_phys_to_dma[IOR_NUM_PHYS_TO_DMA];
-EXPORT_SYMBOL(_ior_phys_to_dma);
-
-/*
- * Values that, when accessed by an index derived from a dma_addr_t and
- * added to that dma_addr_t value, yield a physical address
- */
-struct ior_dma_to_phys _ior_dma_to_phys[IOR_NUM_DMA_TO_PHYS];
-EXPORT_SYMBOL(_ior_dma_to_phys);
-
-/**
- * setup_dma_to_phys - set up conversion from DMA to physical addresses
- * @dma_idx:	Top IOR_LSBITS bits of the DMA address, i.e. an index
- *		into the array _dma_to_phys.
- * @delta:	Value that, when added to the DMA address, will yield the
- *		physical address
- * @s:		Number of bytes in the section of memory with the given delta
- *		between DMA and physical addresses.
- */
-static void setup_dma_to_phys(dma_addr_t dma, phys_addr_t delta, dma_addr_t s)
-{
-	int dma_idx, first_idx, last_idx;
-	phys_addr_t first, last;
-
-	/*
-	 * Calculate the first and last indices, rounding the first up and
-	 * the second down.
-	 */
-	first = dma & ~IOR_DMA_GRAIN_MASK;
-	last = (dma + s - 1) & ~IOR_DMA_GRAIN_MASK;
-	first_idx = first >> IOR_LSBITS;		/* Convert to indices */
-	last_idx = last >> IOR_LSBITS;
-
-	for (dma_idx = first_idx; dma_idx <= last_idx; dma_idx++)
-		_ior_dma_to_phys[dma_idx].offset = delta >> IOR_DMA_SHIFT;
-}
-
-/**
- * setup_phys_to_dma - set up conversion from DMA to physical addresses
- * @phys_idx:	Top IOR_LSBITS bits of the DMA address, i.e. an index
- *		into the array _phys_to_dma.
- * @delta:	Value that, when added to the DMA address, will yield the
- *		physical address
- * @s:		Number of bytes in the section of memory with the given delta
- *		between DMA and physical addresses.
- */
-static void setup_phys_to_dma(phys_addr_t phys, dma_addr_t delta, phys_addr_t s)
-{
-	int phys_idx, first_idx, last_idx;
-	phys_addr_t first, last;
-
-	/*
-	 * Calculate the first and last indices, rounding the first up and
-	 * the second down.
-	 */
-	first = phys & ~IOR_PHYS_GRAIN_MASK;
-	last = (phys + s - 1) & ~IOR_PHYS_GRAIN_MASK;
-	first_idx = first >> IOR_LSBITS;		/* Convert to indices */
-	last_idx = last >> IOR_LSBITS;
-
-	for (phys_idx = first_idx; phys_idx <= last_idx; phys_idx++)
-		_ior_phys_to_dma[phys_idx].offset = delta >> IOR_PHYS_SHIFT;
-}
-
-/**
- * ioremap_add_map - add to the physical and DMA address conversion arrays
- * @phys:	Process's view of the address of the start of the memory chunk
- * @dma:	DMA address of the start of the memory chunk
- * @size:	Size, in bytes, of the chunk of memory
- *
- * NOTE: It might be obvious, but the assumption is that all @size bytes have
- * the same offset between the physical address and the DMA address.
- */
-void ioremap_add_map(phys_addr_t phys, phys_addr_t dma, phys_addr_t size)
-{
-	if (size == 0)
-		return;
-
-	if ((dma & IOR_DMA_GRAIN_MASK) != 0 ||
-		(phys & IOR_PHYS_GRAIN_MASK) != 0 ||
-		(size & IOR_PHYS_GRAIN_MASK) != 0)
-		pr_crit("Memory allocation must be in chunks of 0x%x bytes\n",
-			IOR_PHYS_GRAIN);
-
-	setup_dma_to_phys(dma, phys - dma, size);
-	setup_phys_to_dma(phys, dma - phys, size);
-}
diff --git a/arch/mips/powertv/memory.c b/arch/mips/powertv/memory.c
deleted file mode 100644
index bc2f3ca..0000000
--- a/arch/mips/powertv/memory.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- *  This program is free software; you can distribute 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 it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You 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.
- *
- * Apparently originally from arch/mips/malta-memory.c. Modified to work
- * with the PowerTV bootloader.
- */
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <linux/pfn.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/sections.h>
-
-#include <asm/mach-powertv/asic.h>
-#include <asm/mach-powertv/ioremap.h>
-
-#include "init.h"
-
-/* Memory constants */
-#define KIBIBYTE(n)		((n) * 1024)	/* Number of kibibytes */
-#define MEBIBYTE(n)		((n) * KIBIBYTE(1024)) /* Number of mebibytes */
-#define DEFAULT_MEMSIZE		MEBIBYTE(128)	/* If no memsize provided */
-
-#define BLDR_SIZE	KIBIBYTE(256)		/* Memory reserved for bldr */
-#define RV_SIZE		MEBIBYTE(4)		/* Size of reset vector */
-
-#define LOW_MEM_END	0x20000000		/* Highest low memory address */
-#define BLDR_ALIAS	0x10000000		/* Bootloader address */
-#define RV_PHYS		0x1fc00000		/* Reset vector address */
-#define LOW_RAM_END	RV_PHYS			/* End of real RAM in low mem */
-
-/*
- * Very low-level conversion from processor physical address to device
- * DMA address for the first bank of memory.
- */
-#define PHYS_TO_DMA(paddr)	((paddr) + (CONFIG_LOW_RAM_DMA - LOW_RAM_ALIAS))
-
-unsigned long ptv_memsize;
-
-/*
- * struct low_mem_reserved - Items in low memory that are reserved
- * @start:	Physical address of item
- * @size:	Size, in bytes, of this item
- * @is_aliased: True if this is RAM aliased from another location. If false,
- *		it is something other than aliased RAM and the RAM in the
- *		unaliased address is still visible outside of low memory.
- */
-struct low_mem_reserved {
-	phys_addr_t	start;
-	phys_addr_t	size;
-	bool		is_aliased;
-};
-
-/*
- * Must be in ascending address order
- */
-struct low_mem_reserved low_mem_reserved[] = {
-	{BLDR_ALIAS, BLDR_SIZE, true},	/* Bootloader RAM */
-	{RV_PHYS, RV_SIZE, false},	/* Reset vector */
-};
-
-/*
- * struct mem_layout - layout of a piece of the system RAM
- * @phys:	Physical address of the start of this piece of RAM. This is the
- *		address at which both the processor and I/O devices see the
- *		RAM.
- * @alias:	Alias of this piece of memory in order to make it appear in
- *		the low memory part of the processor's address space. I/O
- *		devices don't see anything here.
- * @size:	Size, in bytes, of this piece of RAM
- */
-struct mem_layout {
-	phys_addr_t	phys;
-	phys_addr_t	alias;
-	phys_addr_t	size;
-};
-
-/*
- * struct mem_layout_list - list descriptor for layouts of system RAM pieces
- * @family:	Specifies the family being described
- * @n:		Number of &struct mem_layout elements
- * @layout:	Pointer to the list of &mem_layout structures
- */
-struct mem_layout_list {
-	enum family_type	family;
-	size_t			n;
-	struct mem_layout	*layout;
-};
-
-static struct mem_layout f1500_layout[] = {
-	{0x20000000, 0x10000000, MEBIBYTE(256)},
-};
-
-static struct mem_layout f4500_layout[] = {
-	{0x40000000, 0x10000000, MEBIBYTE(256)},
-	{0x20000000, 0x20000000, MEBIBYTE(32)},
-};
-
-static struct mem_layout f8500_layout[] = {
-	{0x40000000, 0x10000000, MEBIBYTE(256)},
-	{0x20000000, 0x20000000, MEBIBYTE(32)},
-	{0x30000000, 0x30000000, MEBIBYTE(32)},
-};
-
-static struct mem_layout fx600_layout[] = {
-	{0x20000000, 0x10000000, MEBIBYTE(256)},
-	{0x60000000, 0x60000000, MEBIBYTE(128)},
-};
-
-static struct mem_layout_list layout_list[] = {
-	{FAMILY_1500, ARRAY_SIZE(f1500_layout), f1500_layout},
-	{FAMILY_1500VZE, ARRAY_SIZE(f1500_layout), f1500_layout},
-	{FAMILY_1500VZF, ARRAY_SIZE(f1500_layout), f1500_layout},
-	{FAMILY_4500, ARRAY_SIZE(f4500_layout), f4500_layout},
-	{FAMILY_8500, ARRAY_SIZE(f8500_layout), f8500_layout},
-	{FAMILY_8500RNG, ARRAY_SIZE(f8500_layout), f8500_layout},
-	{FAMILY_4600, ARRAY_SIZE(fx600_layout), fx600_layout},
-	{FAMILY_4600VZA, ARRAY_SIZE(fx600_layout), fx600_layout},
-	{FAMILY_8600, ARRAY_SIZE(fx600_layout), fx600_layout},
-	{FAMILY_8600VZB, ARRAY_SIZE(fx600_layout), fx600_layout},
-};
-
-/* If we can't determine the layout, use this */
-static struct mem_layout default_layout[] = {
-	{0x20000000, 0x10000000, MEBIBYTE(128)},
-};
-
-/**
- * register_non_ram - register low memory not available for RAM usage
- */
-static __init void register_non_ram(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(low_mem_reserved); i++)
-		add_memory_region(low_mem_reserved[i].start,
-			low_mem_reserved[i].size, BOOT_MEM_RESERVED);
-}
-
-/**
- * get_memsize - get the size of memory as a single bank
- */
-static phys_addr_t get_memsize(void)
-{
-	static char cmdline[COMMAND_LINE_SIZE] __initdata;
-	phys_addr_t memsize = 0;
-	char *memsize_str;
-	char *ptr;
-
-	/* Check the command line first for a memsize directive */
-	strcpy(cmdline, arcs_cmdline);
-	ptr = strstr(cmdline, "memsize=");
-	if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
-		ptr = strstr(ptr, " memsize=");
-
-	if (ptr) {
-		memsize = memparse(ptr + 8, &ptr);
-	} else {
-		/* otherwise look in the environment */
-		memsize_str = prom_getenv("memsize");
-
-		if (memsize_str != NULL) {
-			pr_info("prom memsize = %s\n", memsize_str);
-			memsize = simple_strtol(memsize_str, NULL, 0);
-		}
-
-		if (memsize == 0) {
-			if (_prom_memsize != 0) {
-				memsize = _prom_memsize;
-				pr_info("_prom_memsize = 0x%x\n", memsize);
-				/* add in memory that the bootloader doesn't
-				 * report */
-				memsize += BLDR_SIZE;
-			} else {
-				memsize = DEFAULT_MEMSIZE;
-				pr_info("Memsize not passed by bootloader, "
-					"defaulting to 0x%x\n", memsize);
-			}
-		}
-	}
-
-	return memsize;
-}
-
-/**
- * register_low_ram - register an aliased section of RAM
- * @p:		Alias address of memory
- * @n:		Number of bytes in this section of memory
- *
- * Returns the number of bytes registered
- *
- */
-static __init phys_addr_t register_low_ram(phys_addr_t p, phys_addr_t n)
-{
-	phys_addr_t s;
-	int i;
-	phys_addr_t orig_n;
-
-	orig_n = n;
-
-	BUG_ON(p + n > RV_PHYS);
-
-	for (i = 0; n != 0 && i < ARRAY_SIZE(low_mem_reserved); i++) {
-		phys_addr_t start;
-		phys_addr_t size;
-
-		start = low_mem_reserved[i].start;
-		size = low_mem_reserved[i].size;
-
-		/* Handle memory before this low memory section */
-		if (p < start) {
-			phys_addr_t s;
-			s = min(n, start - p);
-			add_memory_region(p, s, BOOT_MEM_RAM);
-			p += s;
-			n -= s;
-		}
-
-		/* Handle the low memory section itself. If it's aliased,
-		 * we reduce the number of byes left, but if not, the RAM
-		 * is available elsewhere and we don't reduce the number of
-		 * bytes remaining. */
-		if (p == start) {
-			if (low_mem_reserved[i].is_aliased) {
-				s = min(n, size);
-				n -= s;
-				p += s;
-			} else
-				p += n;
-		}
-	}
-
-	return orig_n - n;
-}
-
-/*
- * register_ram - register real RAM
- * @p:	Address of memory as seen by devices
- * @alias:	If the memory is seen at an additional address by the processor,
- *		this will be the address, otherwise it is the same as @p.
- * @n:		Number of bytes in this section of memory
- */
-static __init void register_ram(phys_addr_t p, phys_addr_t alias,
-	phys_addr_t n)
-{
-	/*
-	 * If some or all of this memory has an alias, break it into the
-	 * aliased and non-aliased portion.
-	 */
-	if (p != alias) {
-		phys_addr_t alias_size;
-		phys_addr_t registered;
-
-		alias_size = min(n, LOW_RAM_END - alias);
-		registered = register_low_ram(alias, alias_size);
-		ioremap_add_map(alias, p, n);
-		n -= registered;
-		p += registered;
-	}
-
-#ifdef CONFIG_HIGHMEM
-	if (n != 0) {
-		add_memory_region(p, n, BOOT_MEM_RAM);
-		ioremap_add_map(p, p, n);
-	}
-#endif
-}
-
-/**
- * register_address_space - register things in the address space
- * @memsize:	Number of bytes of RAM installed
- *
- * Takes the given number of bytes of RAM and registers as many of the regions,
- * or partial regions, as it can. So, the default configuration might have
- * two regions with 256 MiB each. If the memsize passed in on the command line
- * is 384 MiB, it will register the first region with 256 MiB and the second
- * with 128 MiB.
- */
-static __init void register_address_space(phys_addr_t memsize)
-{
-	int i;
-	phys_addr_t size;
-	size_t n;
-	struct mem_layout *layout;
-	enum family_type family;
-
-	/*
-	 * Register all of the things that aren't available to the kernel as
-	 * memory.
-	 */
-	register_non_ram();
-
-	/* Find the appropriate memory description */
-	family = platform_get_family();
-
-	for (i = 0; i < ARRAY_SIZE(layout_list); i++) {
-		if (layout_list[i].family == family)
-			break;
-	}
-
-	if (i == ARRAY_SIZE(layout_list)) {
-		n = ARRAY_SIZE(default_layout);
-		layout = default_layout;
-	} else {
-		n = layout_list[i].n;
-		layout = layout_list[i].layout;
-	}
-
-	for (i = 0; memsize != 0 && i < n; i++) {
-		size = min(memsize, layout[i].size);
-		register_ram(layout[i].phys, layout[i].alias, size);
-		memsize -= size;
-	}
-}
-
-void __init prom_meminit(void)
-{
-	ptv_memsize = get_memsize();
-	register_address_space(ptv_memsize);
-}
-
-void __init prom_free_prom_memory(void)
-{
-	unsigned long addr;
-	int i;
-
-	for (i = 0; i < boot_mem_map.nr_map; i++) {
-		if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
-			continue;
-
-		addr = boot_mem_map.map[i].addr;
-		free_init_pages("prom memory",
-				addr, addr + boot_mem_map.map[i].size);
-	}
-}
diff --git a/arch/mips/powertv/pci/Makefile b/arch/mips/powertv/pci/Makefile
deleted file mode 100644
index 2610a6a..0000000
--- a/arch/mips/powertv/pci/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Copyright (C) 2009  Scientific-Atlanta, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-#
-
-obj-$(CONFIG_PCI)	+= fixup-powertv.o
diff --git a/arch/mips/powertv/pci/fixup-powertv.c b/arch/mips/powertv/pci/fixup-powertv.c
deleted file mode 100644
index d7ecbae..0000000
--- a/arch/mips/powertv/pci/fixup-powertv.c
+++ /dev/null
@@ -1,37 +0,0 @@
-#include <linux/init.h>
-#include <linux/export.h>
-#include <linux/pci.h>
-#include <asm/mach-powertv/interrupts.h>
-#include "powertv-pci.h"
-
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	return asic_pcie_map_irq(dev, slot, pin);
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-	return 0;
-}
-
-/*
- * asic_pcie_map_irq
- *
- * Parameters:
- * *dev - pointer to a pci_dev structure  (not used)
- * slot - slot number  (not used)
- * pin - pin number  (not used)
- *
- * Return Value:
- * Returns: IRQ number (always the PCI Express IRQ number)
- *
- * Description:
- * asic_pcie_map_irq will return the IRQ number of the PCI Express interrupt.
- *
- */
-int asic_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	return irq_pciexp;
-}
-EXPORT_SYMBOL(asic_pcie_map_irq);
diff --git a/arch/mips/powertv/pci/powertv-pci.h b/arch/mips/powertv/pci/powertv-pci.h
deleted file mode 100644
index 1b5886b..0000000
--- a/arch/mips/powertv/pci/powertv-pci.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *				powertv-pci.c
- *
- * Copyright (C) 2009  Cisco Systems, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have 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
- */
-/*
- * Local definitions for the powertv PCI code
- */
-
-#ifndef _POWERTV_PCI_POWERTV_PCI_H_
-#define _POWERTV_PCI_POWERTV_PCI_H_
-extern int asic_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
-extern int asic_pcie_init(void);
-extern int asic_pcie_init(void);
-
-extern int log_level;
-#endif
diff --git a/arch/mips/powertv/powertv-clock.h b/arch/mips/powertv/powertv-clock.h
deleted file mode 100644
index d94c543..0000000
--- a/arch/mips/powertv/powertv-clock.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2009  Cisco Systems, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have 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
- *
- * Author: David VomLehn
- */
-
-#ifndef _POWERTV_POWERTV_CLOCK_H
-#define _POWERTV_POWERTV_CLOCK_H
-extern int powertv_clockevent_init(void);
-extern void powertv_clocksource_init(void);
-extern unsigned int mips_get_pll_freq(void);
-#endif
diff --git a/arch/mips/powertv/powertv-usb.c b/arch/mips/powertv/powertv-usb.c
deleted file mode 100644
index d845eac..0000000
--- a/arch/mips/powertv/powertv-usb.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- *				powertv-usb.c
- *
- * Description:	 ASIC-specific USB device setup and shutdown
- *
- * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
- * Copyright (C) 2009 Cisco Systems, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have 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
- *
- * Author:	 Ken Eppinett
- *		 David Schleef <ds@schleef.org>
- *
- * NOTE: The bootloader allocates persistent memory at an address which is
- * 16 MiB below the end of the highest address in KSEG0. All fixed
- * address memory reservations must avoid this region.
- */
-
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <asm/mach-powertv/asic.h>
-#include <asm/mach-powertv/interrupts.h>
-
-/* misc_clk_ctl1 values */
-#define MCC1_30MHZ_POWERUP_SELECT	(1 << 14)
-#define MCC1_DIV9			(1 << 13)
-#define MCC1_ETHMIPS_POWERUP_SELECT	(1 << 11)
-#define MCC1_USB_POWERUP_SELECT		(1 << 1)
-#define MCC1_CLOCK108_POWERUP_SELECT	(1 << 0)
-
-/* Possible values for clock select */
-#define MCC1_USB_CLOCK_HIGH_Z		(0 << 4)
-#define MCC1_USB_CLOCK_48MHZ		(1 << 4)
-#define MCC1_USB_CLOCK_24MHZ		(2 << 4)
-#define MCC1_USB_CLOCK_6MHZ		(3 << 4)
-
-#define MCC1_CONFIG	(MCC1_30MHZ_POWERUP_SELECT |		\
-			 MCC1_DIV9 |				\
-			 MCC1_ETHMIPS_POWERUP_SELECT |		\
-			 MCC1_USB_POWERUP_SELECT |		\
-			 MCC1_CLOCK108_POWERUP_SELECT)
-
-/* misc_clk_ctl2 values */
-#define MCC2_GMII_GCLK_TO_PAD		(1 << 31)
-#define MCC2_ETHER125_0_CLOCK_SELECT	(1 << 29)
-#define MCC2_RMII_0_CLOCK_SELECT	(1 << 28)
-#define MCC2_GMII_TX0_CLOCK_SELECT	(1 << 27)
-#define MCC2_GMII_RX0_CLOCK_SELECT	(1 << 26)
-#define MCC2_ETHER125_1_CLOCK_SELECT	(1 << 24)
-#define MCC2_RMII_1_CLOCK_SELECT	(1 << 23)
-#define MCC2_GMII_TX1_CLOCK_SELECT	(1 << 22)
-#define MCC2_GMII_RX1_CLOCK_SELECT	(1 << 21)
-#define MCC2_ETHER125_2_CLOCK_SELECT	(1 << 19)
-#define MCC2_RMII_2_CLOCK_SELECT	(1 << 18)
-#define MCC2_GMII_TX2_CLOCK_SELECT	(1 << 17)
-#define MCC2_GMII_RX2_CLOCK_SELECT	(1 << 16)
-
-#define ETHER_CLK_CONFIG	(MCC2_GMII_GCLK_TO_PAD |	\
-				 MCC2_ETHER125_0_CLOCK_SELECT | \
-				 MCC2_RMII_0_CLOCK_SELECT |	\
-				 MCC2_GMII_TX0_CLOCK_SELECT |	\
-				 MCC2_GMII_RX0_CLOCK_SELECT |	\
-				 MCC2_ETHER125_1_CLOCK_SELECT | \
-				 MCC2_RMII_1_CLOCK_SELECT |	\
-				 MCC2_GMII_TX1_CLOCK_SELECT |	\
-				 MCC2_GMII_RX1_CLOCK_SELECT |	\
-				 MCC2_ETHER125_2_CLOCK_SELECT | \
-				 MCC2_RMII_2_CLOCK_SELECT |	\
-				 MCC2_GMII_TX2_CLOCK_SELECT |	\
-				 MCC2_GMII_RX2_CLOCK_SELECT)
-
-/* misc_clk_ctl2 definitions for Gaia */
-#define FSX4A_REF_SELECT		(1 << 16)
-#define FSX4B_REF_SELECT		(1 << 17)
-#define FSX4C_REF_SELECT		(1 << 18)
-#define DDR_PLL_REF_SELECT		(1 << 19)
-#define MIPS_PLL_REF_SELECT		(1 << 20)
-
-/* Definitions for the QAM frequency select register FS432X4A4_QAM_CTL */
-#define QAM_FS_SDIV_SHIFT		29
-#define QAM_FS_MD_SHIFT			24
-#define QAM_FS_MD_MASK			0x1f	/* Cut down to 5 bits */
-#define QAM_FS_PE_SHIFT			8
-
-#define QAM_FS_DISABLE_DIVIDE_BY_3		(1 << 5)
-#define QAM_FS_ENABLE_PROGRAM			(1 << 4)
-#define QAM_FS_ENABLE_OUTPUT			(1 << 3)
-#define QAM_FS_SELECT_TEST_BYPASS		(1 << 2)
-#define QAM_FS_DISABLE_DIGITAL_STANDBY		(1 << 1)
-#define QAM_FS_CHOOSE_FS			(1 << 0)
-
-/* Definitions for fs432x4a_ctl register */
-#define QAM_FS_NSDIV_54MHZ			(1 << 2)
-
-/* Definitions for bcm1_usb2_ctl register */
-#define BCM1_USB2_CTL_BISTOK				(1 << 11)
-#define BCM1_USB2_CTL_PORT2_SHIFT_JK			(1 << 7)
-#define BCM1_USB2_CTL_PORT1_SHIFT_JK			(1 << 6)
-#define BCM1_USB2_CTL_PORT2_FAST_EDGE			(1 << 5)
-#define BCM1_USB2_CTL_PORT1_FAST_EDGE			(1 << 4)
-#define BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH		(1 << 1)
-#define BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH	(1 << 0)
-
-/* Definitions for crt_spare register */
-#define CRT_SPARE_PORT2_SHIFT_JK			(1 << 21)
-#define CRT_SPARE_PORT1_SHIFT_JK			(1 << 20)
-#define CRT_SPARE_PORT2_FAST_EDGE			(1 << 19)
-#define CRT_SPARE_PORT1_FAST_EDGE			(1 << 18)
-#define CRT_SPARE_DIVIDE_BY_9_FROM_432			(1 << 17)
-#define CRT_SPARE_USB_DIVIDE_BY_9			(1 << 16)
-
-/* Definitions for usb2_stbus_obc register */
-#define USB_STBUS_OBC_STORE32_LOAD32			0x3
-
-/* Definitions for usb2_stbus_mess_size register */
-#define USB2_STBUS_MESS_SIZE_2				0x1	/* 2 packets */
-
-/* Definitions for usb2_stbus_chunk_size register */
-#define USB2_STBUS_CHUNK_SIZE_2				0x1	/* 2 packets */
-
-/* Definitions for usb2_strap register */
-#define USB2_STRAP_HFREQ_SELECT				0x1
-
-/*
- * USB Host Resource Definition
- */
-
-static struct resource ehci_resources[] = {
-	{
-		.parent = &asic_resource,
-		.start	= 0,
-		.end	= 0xff,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= irq_usbehci,
-		.end	= irq_usbehci,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 ehci_dmamask = 0xffffffffULL;
-
-static struct platform_device ehci_device = {
-	.name = "powertv-ehci",
-	.id = 0,
-	.num_resources = 2,
-	.resource = ehci_resources,
-	.dev = {
-		.dma_mask = &ehci_dmamask,
-		.coherent_dma_mask = 0xffffffff,
-	},
-};
-
-static struct resource ohci_resources[] = {
-	{
-		.parent = &asic_resource,
-		.start	= 0,
-		.end	= 0xff,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= irq_usbohci,
-		.end	= irq_usbohci,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 ohci_dmamask = 0xffffffffULL;
-
-static struct platform_device ohci_device = {
-	.name = "powertv-ohci",
-	.id = 0,
-	.num_resources = 2,
-	.resource = ohci_resources,
-	.dev = {
-		.dma_mask = &ohci_dmamask,
-		.coherent_dma_mask = 0xffffffff,
-	},
-};
-
-static unsigned usb_users;
-static DEFINE_SPINLOCK(usb_regs_lock);
-
-/*
- *
- * fs_update - set frequency synthesizer for USB
- * @pe_bits		Phase tap setting
- * @md_bits		Coarse selector bus for algorithm of phase tap
- * @sdiv_bits		Output divider setting
- * @disable_div_by_3	Either QAM_FS_DISABLE_DIVIDE_BY_3 or zero
- * @standby		Either QAM_FS_DISABLE_DIGITAL_STANDBY or zero
- *
- * QAM frequency selection code, which affects the frequency at which USB
- * runs. The frequency is calculated as:
- *			       2^15 * ndiv * Fin
- * Fout = ------------------------------------------------------------
- *	  (sdiv * (ipe * (1 + md/32) - (ipe - 2^15)*(1 + (md + 1)/32)))
- * where:
- * Fin		54 MHz
- * ndiv		QAM_FS_NSDIV_54MHZ ? 8 : 16
- * sdiv		1 << (sdiv_bits + 1)
- * ipe		Same as pe_bits
- * md		A five-bit, two's-complement integer (range [-16, 15]), which
- *		is the lower 5 bits of md_bits.
- */
-static void fs_update(u32 pe_bits, int md_bits, u32 sdiv_bits,
-	u32 disable_div_by_3, u32 standby)
-{
-	u32 val;
-
-	val = ((sdiv_bits << QAM_FS_SDIV_SHIFT) |
-		((md_bits & QAM_FS_MD_MASK) << QAM_FS_MD_SHIFT) |
-		(pe_bits << QAM_FS_PE_SHIFT) |
-		QAM_FS_ENABLE_OUTPUT |
-		standby |
-		disable_div_by_3);
-	asic_write(val, fs432x4b4_usb_ctl);
-	asic_write(val | QAM_FS_ENABLE_PROGRAM, fs432x4b4_usb_ctl);
-	asic_write(val | QAM_FS_ENABLE_PROGRAM | QAM_FS_CHOOSE_FS,
-		fs432x4b4_usb_ctl);
-}
-
-/*
- * usb_eye_configure - for optimizing the shape USB eye waveform
- * @set:	Bits to set in the register
- * @clear:	Bits to clear in the register; each bit with a one will
- *		be set in the register, zero bits will not be modified
- */
-static void usb_eye_configure(u32 set, u32 clear)
-{
-	u32 old;
-
-	old = asic_read(crt_spare);
-	old |= set;
-	old &= ~clear;
-	asic_write(old, crt_spare);
-}
-
-/*
- * platform_configure_usb - usb configuration based on platform type.
- */
-static void platform_configure_usb(void)
-{
-	u32 bcm1_usb2_ctl_value;
-	enum asic_type asic_type;
-	unsigned long flags;
-
-	spin_lock_irqsave(&usb_regs_lock, flags);
-	usb_users++;
-
-	if (usb_users != 1) {
-		spin_unlock_irqrestore(&usb_regs_lock, flags);
-		return;
-	}
-
-	asic_type = platform_get_asic();
-
-	switch (asic_type) {
-	case ASIC_ZEUS:
-		fs_update(0x0000, -15, 0x02, 0, 0);
-		bcm1_usb2_ctl_value = BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH |
-			BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH;
-		break;
-
-	case ASIC_CRONUS:
-	case ASIC_CRONUSLITE:
-		usb_eye_configure(0, CRT_SPARE_USB_DIVIDE_BY_9);
-		fs_update(0x8000, -14, 0x03, QAM_FS_DISABLE_DIVIDE_BY_3,
-			QAM_FS_DISABLE_DIGITAL_STANDBY);
-		bcm1_usb2_ctl_value = BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH |
-			BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH;
-		break;
-
-	case ASIC_CALLIOPE:
-		fs_update(0x0000, -15, 0x02, QAM_FS_DISABLE_DIVIDE_BY_3,
-			QAM_FS_DISABLE_DIGITAL_STANDBY);
-
-		switch (platform_get_family()) {
-		case FAMILY_1500VZE:
-			break;
-
-		case FAMILY_1500VZF:
-			usb_eye_configure(CRT_SPARE_PORT2_SHIFT_JK |
-				CRT_SPARE_PORT1_SHIFT_JK |
-				CRT_SPARE_PORT2_FAST_EDGE |
-				CRT_SPARE_PORT1_FAST_EDGE, 0);
-			break;
-
-		default:
-			usb_eye_configure(CRT_SPARE_PORT2_SHIFT_JK |
-				CRT_SPARE_PORT1_SHIFT_JK, 0);
-			break;
-		}
-
-		bcm1_usb2_ctl_value = BCM1_USB2_CTL_BISTOK |
-			BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH |
-			BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH;
-		break;
-
-	case ASIC_GAIA:
-		fs_update(0x8000, -14, 0x03, QAM_FS_DISABLE_DIVIDE_BY_3,
-			QAM_FS_DISABLE_DIGITAL_STANDBY);
-		bcm1_usb2_ctl_value = BCM1_USB2_CTL_BISTOK |
-			BCM1_USB2_CTL_EHCI_PRT_PWR_ACTIVE_HIGH |
-			BCM1_USB2_CTL_APP_PRT_OVRCUR_IN_ACTIVE_HIGH;
-		break;
-
-	default:
-		pr_err("Unknown ASIC type: %d\n", asic_type);
-		bcm1_usb2_ctl_value = 0;
-		break;
-	}
-
-	/* turn on USB power */
-	asic_write(0, usb2_strap);
-	/* Enable all OHCI interrupts */
-	asic_write(bcm1_usb2_ctl_value, usb2_control);
-	/* usb2_stbus_obc store32/load32 */
-	asic_write(USB_STBUS_OBC_STORE32_LOAD32, usb2_stbus_obc);
-	/* usb2_stbus_mess_size 2 packets */
-	asic_write(USB2_STBUS_MESS_SIZE_2, usb2_stbus_mess_size);
-	/* usb2_stbus_chunk_size 2 packets */
-	asic_write(USB2_STBUS_CHUNK_SIZE_2, usb2_stbus_chunk_size);
-	spin_unlock_irqrestore(&usb_regs_lock, flags);
-}
-
-static void platform_unconfigure_usb(void)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&usb_regs_lock, flags);
-	usb_users--;
-	if (usb_users == 0)
-		asic_write(USB2_STRAP_HFREQ_SELECT, usb2_strap);
-	spin_unlock_irqrestore(&usb_regs_lock, flags);
-}
-
-/*
- * Set up the USB EHCI interface
- */
-void platform_configure_usb_ehci()
-{
-	platform_configure_usb();
-}
-EXPORT_SYMBOL(platform_configure_usb_ehci);
-
-/*
- * Set up the USB OHCI interface
- */
-void platform_configure_usb_ohci()
-{
-	platform_configure_usb();
-}
-EXPORT_SYMBOL(platform_configure_usb_ohci);
-
-/*
- * Shut the USB EHCI interface down
- */
-void platform_unconfigure_usb_ehci()
-{
-	platform_unconfigure_usb();
-}
-EXPORT_SYMBOL(platform_unconfigure_usb_ehci);
-
-/*
- * Shut the USB OHCI interface down
- */
-void platform_unconfigure_usb_ohci()
-{
-	platform_unconfigure_usb();
-}
-EXPORT_SYMBOL(platform_unconfigure_usb_ohci);
-
-/**
- * platform_devices_init - sets up USB device resourse.
- */
-int __init platform_usb_devices_init(struct platform_device **ehci_dev,
-	struct platform_device **ohci_dev)
-{
-	*ehci_dev = &ehci_device;
-	ehci_resources[0].start = asic_reg_phys_addr(ehci_hcapbase);
-	ehci_resources[0].end += ehci_resources[0].start;
-
-	*ohci_dev = &ohci_device;
-	ohci_resources[0].start = asic_reg_phys_addr(ohci_hc_revision);
-	ohci_resources[0].end += ohci_resources[0].start;
-
-	return 0;
-}
diff --git a/arch/mips/powertv/powertv_setup.c b/arch/mips/powertv/powertv_setup.c
deleted file mode 100644
index 24689bf..0000000
--- a/arch/mips/powertv/powertv_setup.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- *  This program is free software; you can distribute 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 it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- */
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/screen_info.h>
-#include <linux/notifier.h>
-#include <linux/etherdevice.h>
-#include <linux/if_ether.h>
-#include <linux/ctype.h>
-#include <linux/cpu.h>
-#include <linux/time.h>
-
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/mips-boards/generic.h>
-#include <asm/dma.h>
-#include <asm/asm.h>
-#include <asm/traps.h>
-#include <asm/asm-offsets.h>
-#include "reset.h"
-
-#define VAL(n)		STR(n)
-
-/*
- * Macros for loading addresses and storing registers:
- * LONG_L_	Stringified version of LONG_L for use in asm() statement
- * LONG_S_	Stringified version of LONG_S for use in asm() statement
- * PTR_LA_	Stringified version of PTR_LA for use in asm() statement
- * REG_SIZE	Number of 8-bit bytes in a full width register
- */
-#define LONG_L_		VAL(LONG_L) " "
-#define LONG_S_		VAL(LONG_S) " "
-#define PTR_LA_		VAL(PTR_LA) " "
-
-#ifdef CONFIG_64BIT
-#warning TODO: 64-bit code needs to be verified
-#define REG_SIZE	"8"		/* In bytes */
-#endif
-
-#ifdef CONFIG_32BIT
-#define REG_SIZE	"4"		/* In bytes */
-#endif
-
-static void register_panic_notifier(void);
-static int panic_handler(struct notifier_block *notifier_block,
-	unsigned long event, void *cause_string);
-
-const char *get_system_type(void)
-{
-	return "PowerTV";
-}
-
-void __init plat_mem_setup(void)
-{
-	panic_on_oops = 1;
-	register_panic_notifier();
-
-#if 0
-	mips_pcibios_init();
-#endif
-	mips_reboot_setup();
-}
-
-/*
- * Install a panic notifier for platform-specific diagnostics
- */
-static void register_panic_notifier()
-{
-	static struct notifier_block panic_notifier = {
-		.notifier_call = panic_handler,
-		.next = NULL,
-		.priority	= INT_MAX
-	};
-	atomic_notifier_chain_register(&panic_notifier_list, &panic_notifier);
-}
-
-static int panic_handler(struct notifier_block *notifier_block,
-	unsigned long event, void *cause_string)
-{
-	struct pt_regs	my_regs;
-
-	/* Save all of the registers */
-	{
-		unsigned long	at, v0, v1; /* Must be on the stack */
-
-		/* Start by saving $at and v0 on the stack. We use $at
-		 * ourselves, but it looks like the compiler may use v0 or v1
-		 * to load the address of the pt_regs structure. We'll come
-		 * back later to store the registers in the pt_regs
-		 * structure. */
-		__asm__ __volatile__ (
-			".set	noat\n"
-			LONG_S_		"$at, %[at]\n"
-			LONG_S_		"$2, %[v0]\n"
-			LONG_S_		"$3, %[v1]\n"
-		:
-			[at] "=m" (at),
-			[v0] "=m" (v0),
-			[v1] "=m" (v1)
-		:
-		:	"at"
-		);
-
-		__asm__ __volatile__ (
-			".set	noat\n"
-			"move		$at, %[pt_regs]\n"
-
-			/* Argument registers */
-			LONG_S_		"$4, " VAL(PT_R4) "($at)\n"
-			LONG_S_		"$5, " VAL(PT_R5) "($at)\n"
-			LONG_S_		"$6, " VAL(PT_R6) "($at)\n"
-			LONG_S_		"$7, " VAL(PT_R7) "($at)\n"
-
-			/* Temporary regs */
-			LONG_S_		"$8, " VAL(PT_R8) "($at)\n"
-			LONG_S_		"$9, " VAL(PT_R9) "($at)\n"
-			LONG_S_		"$10, " VAL(PT_R10) "($at)\n"
-			LONG_S_		"$11, " VAL(PT_R11) "($at)\n"
-			LONG_S_		"$12, " VAL(PT_R12) "($at)\n"
-			LONG_S_		"$13, " VAL(PT_R13) "($at)\n"
-			LONG_S_		"$14, " VAL(PT_R14) "($at)\n"
-			LONG_S_		"$15, " VAL(PT_R15) "($at)\n"
-
-			/* "Saved" registers */
-			LONG_S_		"$16, " VAL(PT_R16) "($at)\n"
-			LONG_S_		"$17, " VAL(PT_R17) "($at)\n"
-			LONG_S_		"$18, " VAL(PT_R18) "($at)\n"
-			LONG_S_		"$19, " VAL(PT_R19) "($at)\n"
-			LONG_S_		"$20, " VAL(PT_R20) "($at)\n"
-			LONG_S_		"$21, " VAL(PT_R21) "($at)\n"
-			LONG_S_		"$22, " VAL(PT_R22) "($at)\n"
-			LONG_S_		"$23, " VAL(PT_R23) "($at)\n"
-
-			/* Add'l temp regs */
-			LONG_S_		"$24, " VAL(PT_R24) "($at)\n"
-			LONG_S_		"$25, " VAL(PT_R25) "($at)\n"
-
-			/* Kernel temp regs */
-			LONG_S_		"$26, " VAL(PT_R26) "($at)\n"
-			LONG_S_		"$27, " VAL(PT_R27) "($at)\n"
-
-			/* Global pointer, stack pointer, frame pointer and
-			 * return address */
-			LONG_S_		"$gp, " VAL(PT_R28) "($at)\n"
-			LONG_S_		"$sp, " VAL(PT_R29) "($at)\n"
-			LONG_S_		"$fp, " VAL(PT_R30) "($at)\n"
-			LONG_S_		"$ra, " VAL(PT_R31) "($at)\n"
-
-			/* Now we can get the $at and v0 registers back and
-			 * store them */
-			LONG_L_		"$8, %[at]\n"
-			LONG_S_		"$8, " VAL(PT_R1) "($at)\n"
-			LONG_L_		"$8, %[v0]\n"
-			LONG_S_		"$8, " VAL(PT_R2) "($at)\n"
-			LONG_L_		"$8, %[v1]\n"
-			LONG_S_		"$8, " VAL(PT_R3) "($at)\n"
-		:
-		:
-			[at] "m" (at),
-			[v0] "m" (v0),
-			[v1] "m" (v1),
-			[pt_regs] "r" (&my_regs)
-		:	"at", "t0"
-		);
-
-		/* Set the current EPC value to be the current location in this
-		 * function */
-		__asm__ __volatile__ (
-			".set	noat\n"
-		"1:\n"
-			PTR_LA_		"$at, 1b\n"
-			LONG_S_		"$at, %[cp0_epc]\n"
-		:
-			[cp0_epc] "=m" (my_regs.cp0_epc)
-		:
-		:	"at"
-		);
-
-		my_regs.cp0_cause = read_c0_cause();
-		my_regs.cp0_status = read_c0_status();
-	}
-
-	pr_crit("I'm feeling a bit sleepy. hmmmmm... perhaps a nap would... "
-		"zzzz... \n");
-
-	return NOTIFY_DONE;
-}
-
-/* Information about the RF MAC address, if one was supplied on the
- * command line. */
-static bool have_rfmac;
-static u8 rfmac[ETH_ALEN];
-
-static int rfmac_param(char *p)
-{
-	u8	*q;
-	bool	is_high_nibble;
-	int	c;
-
-	/* Skip a leading "0x", if present */
-	if (*p == '0' && *(p+1) == 'x')
-		p += 2;
-
-	q = rfmac;
-	is_high_nibble = true;
-
-	for (c = (unsigned char) *p++;
-		isxdigit(c) && q - rfmac < ETH_ALEN;
-		c = (unsigned char) *p++) {
-		int	nibble;
-
-		nibble = (isdigit(c) ? (c - '0') :
-			(isupper(c) ? c - 'A' + 10 : c - 'a' + 10));
-
-		if (is_high_nibble)
-			*q = nibble << 4;
-		else
-			*q++ |= nibble;
-
-		is_high_nibble = !is_high_nibble;
-	}
-
-	/* If we parsed all the way to the end of the parameter value and
-	 * parsed all ETH_ALEN bytes, we have a usable RF MAC address */
-	have_rfmac = (c == '\0' && q - rfmac == ETH_ALEN);
-
-	return 0;
-}
-
-early_param("rfmac", rfmac_param);
-
-/*
- * Generate an Ethernet MAC address that has a good chance of being unique.
- * @addr:	Pointer to six-byte array containing the Ethernet address
- * Generates an Ethernet MAC address that is highly likely to be unique for
- * this particular system on a network with other systems of the same type.
- *
- * The problem we are solving is that, when eth_random_addr() is used to
- * generate MAC addresses at startup, there isn't much entropy for the random
- * number generator to use and the addresses it produces are fairly likely to
- * be the same as those of other identical systems on the same local network.
- * This is true even for relatively small numbers of systems (for the reason
- * why, see the Wikipedia entry for "Birthday problem" at:
- *	http://en.wikipedia.org/wiki/Birthday_problem
- *
- * The good news is that we already have a MAC address known to be unique, the
- * RF MAC address. The bad news is that this address is already in use on the
- * RF interface. Worse, the obvious trick, taking the RF MAC address and
- * turning on the locally managed bit, has already been used for other devices.
- * Still, this does give us something to work with.
- *
- * The approach we take is:
- * 1.	If we can't get the RF MAC Address, just call eth_random_addr.
- * 2.	Use the 24-bit NIC-specific bits of the RF MAC address as the last 24
- *	bits of the new address. This is very likely to be unique, except for
- *	the current box.
- * 3.	To avoid using addresses already on the current box, we set the top
- *	six bits of the address with a value different from any currently
- *	registered Scientific Atlanta organizationally unique identifyer
- *	(OUI). This avoids duplication with any addresses on the system that
- *	were generated from valid Scientific Atlanta-registered address by
- *	simply flipping the locally managed bit.
- * 4.	We aren't generating a multicast address, so we leave the multicast
- *	bit off. Since we aren't using a registered address, we have to set
- *	the locally managed bit.
- * 5.	We then randomly generate the remaining 16-bits. This does two
- *	things:
- *	a.	It allows us to call this function for more than one device
- *		in this system
- *	b.	It ensures that things will probably still work even if
- *		some device on the device network has a locally managed
- *		address that matches the top six bits from step 2.
- */
-void platform_random_ether_addr(u8 addr[ETH_ALEN])
-{
-	const int num_random_bytes = 2;
-	const unsigned char non_sciatl_oui_bits = 0xc0u;
-	const unsigned char mac_addr_locally_managed = (1 << 1);
-
-	if (!have_rfmac) {
-		pr_warning("rfmac not available on command line; "
-			"generating random MAC address\n");
-		eth_random_addr(addr);
-	}
-
-	else {
-		int	i;
-
-		/* Set the first byte to something that won't match a Scientific
-		 * Atlanta OUI, is locally managed, and isn't a multicast
-		 * address */
-		addr[0] = non_sciatl_oui_bits | mac_addr_locally_managed;
-
-		/* Get some bytes of random address information */
-		get_random_bytes(&addr[1], num_random_bytes);
-
-		/* Copy over the NIC-specific bits of the RF MAC address */
-		for (i = 1 + num_random_bytes; i < ETH_ALEN; i++)
-			addr[i] = rfmac[i];
-	}
-}
diff --git a/arch/mips/powertv/reset.c b/arch/mips/powertv/reset.c
deleted file mode 100644
index 11c32fb..0000000
--- a/arch/mips/powertv/reset.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- *  This program is free software; you can distribute 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 it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You 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/pm.h>
-
-#include <linux/io.h>
-#include <asm/reboot.h>			/* Not included by linux/reboot.h */
-
-#include <asm/mach-powertv/asic_regs.h>
-#include "reset.h"
-
-static void mips_machine_restart(char *command)
-{
-	writel(0x1, asic_reg_addr(watchdog));
-}
-
-void mips_reboot_setup(void)
-{
-	_machine_restart = mips_machine_restart;
-}
diff --git a/arch/mips/powertv/reset.h b/arch/mips/powertv/reset.h
deleted file mode 100644
index 888fd09..0000000
--- a/arch/mips/powertv/reset.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Definitions from powertv reset.c file
- *
- * Copyright (C) 2009  Cisco Systems, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have 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
- *
- * Author: David VomLehn
- */
-
-#ifndef _POWERTV_POWERTV_RESET_H
-#define _POWERTV_POWERTV_RESET_H
-extern void mips_reboot_setup(void);
-#endif
diff --git a/arch/mips/powertv/time.c b/arch/mips/powertv/time.c
deleted file mode 100644
index f38b0d4..0000000
--- a/arch/mips/powertv/time.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- * Portions copyright (C) 2009 Cisco Systems, Inc.
- *
- *  This program is free software; you can distribute 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 it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You 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.
- *
- * Setting up the clock on the MIPS boards.
- */
-
-#include <linux/init.h>
-#include <asm/mach-powertv/interrupts.h>
-#include <asm/time.h>
-
-#include "powertv-clock.h"
-
-unsigned int get_c0_compare_int(void)
-{
-	return irq_mips_timer;
-}
-
-void __init plat_time_init(void)
-{
-	powertv_clocksource_init();
-}
diff --git a/arch/mips/ralink/clk.c b/arch/mips/ralink/clk.c
index bba0cdf..5d0983d 100644
--- a/arch/mips/ralink/clk.c
+++ b/arch/mips/ralink/clk.c
@@ -26,7 +26,7 @@
 	struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
 
 	if (!clk)
-		panic("failed to add clock\n");
+		panic("failed to add clock");
 
 	clk->cl.dev_id = dev;
 	clk->cl.clk = clk;
diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c
index d217509..a3ad56c 100644
--- a/arch/mips/ralink/mt7620.c
+++ b/arch/mips/ralink/mt7620.c
@@ -350,7 +350,7 @@
 		name = "MT7620A";
 		soc_info->compatible = "ralink,mt7620a-soc";
 	} else {
-		panic("mt7620: unknown SoC, n0:%08x n1:%08x\n", n0, n1);
+		panic("mt7620: unknown SoC, n0:%08x n1:%08x", n0, n1);
 	}
 
 	rev = __raw_readl(sysc + SYSC_REG_CHIP_REV);
diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c
index ce38d11..eccc552 100644
--- a/arch/mips/ralink/of.c
+++ b/arch/mips/ralink/of.c
@@ -21,6 +21,7 @@
 #include <asm/reboot.h>
 #include <asm/bootinfo.h>
 #include <asm/addrspace.h>
+#include <asm/prom.h>
 
 #include "common.h"
 
@@ -108,7 +109,7 @@
 	strncpy(of_ids[1].compatible, "palmbus", len);
 
 	if (of_platform_populate(NULL, of_ids, NULL, NULL))
-		panic("failed to populate DT\n");
+		panic("failed to populate DT");
 
 	/* make sure ithat the reset controller is setup early */
 	ralink_rst_init();
diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c
index ca7ee3a..bb82a82 100644
--- a/arch/mips/ralink/rt305x.c
+++ b/arch/mips/ralink/rt305x.c
@@ -276,7 +276,7 @@
 		name = "RT5350";
 		soc_info->compatible = "ralink,rt5350-soc";
 	} else {
-		panic("rt305x: unknown SoC, n0:%08x n1:%08x\n", n0, n1);
+		panic("rt305x: unknown SoC, n0:%08x n1:%08x", n0, n1);
 	}
 
 	id = __raw_readl(sysc + SYSC_REG_CHIP_ID);
diff --git a/arch/mips/ralink/timer.c b/arch/mips/ralink/timer.c
index e49241a..2027857 100644
--- a/arch/mips/ralink/timer.c
+++ b/arch/mips/ralink/timer.c
@@ -126,7 +126,7 @@
 		return -ENOENT;
 	}
 
-	rt->membase = devm_request_and_ioremap(&pdev->dev, res);
+	rt->membase = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(rt->membase))
 		return PTR_ERR(rt->membase);
 
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index c5d7670..74742dc 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -2,3 +2,4 @@
 generic-y += clkdev.h
 generic-y += exec.h
 generic-y += trace_clock.h
+generic-y += preempt.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 195653e..7840562 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -67,3 +67,4 @@
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/openrisc/include/asm/prom.h b/arch/openrisc/include/asm/prom.h
deleted file mode 100644
index 93c9980..0000000
--- a/arch/openrisc/include/asm/prom.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * OpenRISC Linux
- *
- * Linux architectural port borrowing liberally from similar works of
- * others.  All original copyrights apply as per the original source
- * declaration.
- *
- * OpenRISC implementation:
- * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
- * et al.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#ifndef _ASM_OPENRISC_PROM_H
-#define _ASM_OPENRISC_PROM_H
-
-#define HAVE_ARCH_DEVTREE_FIXUPS
-
-#endif /* _ASM_OPENRISC_PROM_H */
diff --git a/arch/openrisc/kernel/prom.c b/arch/openrisc/kernel/prom.c
index a63e768..6a44340 100644
--- a/arch/openrisc/kernel/prom.c
+++ b/arch/openrisc/kernel/prom.c
@@ -18,83 +18,15 @@
  *
  */
 
-#include <stdarg.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
 #include <linux/init.h>
-#include <linux/threads.h>
-#include <linux/spinlock.h>
 #include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/stringify.h>
-#include <linux/delay.h>
-#include <linux/initrd.h>
-#include <linux/bitops.h>
-#include <linux/module.h>
-#include <linux/kexec.h>
-#include <linux/debugfs.h>
-#include <linux/irq.h>
 #include <linux/memblock.h>
 #include <linux/of_fdt.h>
 
-#include <asm/prom.h>
 #include <asm/page.h>
-#include <asm/processor.h>
-#include <asm/irq.h>
-#include <linux/io.h>
-#include <asm/mmu.h>
-#include <asm/pgtable.h>
-#include <asm/sections.h>
-#include <asm/setup.h>
-
-extern char cmd_line[COMMAND_LINE_SIZE];
-
-void __init early_init_dt_add_memory_arch(u64 base, u64 size)
-{
-	size &= PAGE_MASK;
-	memblock_add(base, size);
-}
 
 void __init early_init_devtree(void *params)
 {
-	void *alloc;
-
-	/* Setup flat device-tree pointer */
-	initial_boot_params = params;
-
-
-	/* Retrieve various informations from the /chosen node of the
-	 * device-tree, including the platform type, initrd location and
-	 * size, TCE reserve, and more ...
-	 */
-	of_scan_flat_dt(early_init_dt_scan_chosen, cmd_line);
-
-	/* Scan memory nodes and rebuild MEMBLOCKs */
-	of_scan_flat_dt(early_init_dt_scan_root, NULL);
-	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
-
-	/* Save command line for /proc/cmdline and then parse parameters */
-	strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
-
+	early_init_dt_scan(params);
 	memblock_allow_resize();
-
-	/* We must copy the flattend device tree from init memory to regular
-	 * memory because the device tree references the strings in it
-	 * directly.
-	 */
-
-	alloc = __va(memblock_alloc(initial_boot_params->totalsize, PAGE_SIZE));
-
-	memcpy(alloc, initial_boot_params, initial_boot_params->totalsize);
-
-	initial_boot_params = alloc;
 }
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
-{
-	initrd_start = (unsigned long)__va(start);
-	initrd_end = (unsigned long)__va(end);
-	initrd_below_start_ok = 1;
-}
-#endif
diff --git a/arch/openrisc/kernel/setup.c b/arch/openrisc/kernel/setup.c
index d7359ff..09a769b 100644
--- a/arch/openrisc/kernel/setup.c
+++ b/arch/openrisc/kernel/setup.c
@@ -50,8 +50,6 @@
 
 #include "vmlinux.h"
 
-char __initdata cmd_line[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
-
 static unsigned long __init setup_memory(void)
 {
 	unsigned long bootmap_size;
@@ -285,7 +283,7 @@
 {
 	unsigned long max_low_pfn;
 
-	unflatten_device_tree();
+	unflatten_and_copy_device_tree();
 
 	setup_cpuinfo();
 
@@ -316,7 +314,7 @@
 		conswitchp = &dummy_con;
 #endif
 
-	*cmdline_p = cmd_line;
+	*cmdline_p = boot_command_line;
 
 	printk(KERN_INFO "OpenRISC Linux -- http://openrisc.net\n");
 }
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index ad2ce8d..7dcde53 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -287,6 +287,9 @@
 	def_bool y
 	depends on COMPAT && SYSVIPC
 
+config AUDIT_ARCH
+	def_bool y
+
 config HPUX
 	bool "Support for HP-UX binaries"
 	depends on !64BIT
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
index e02f665..7187664 100644
--- a/arch/parisc/Makefile
+++ b/arch/parisc/Makefile
@@ -94,7 +94,7 @@
 	else echo $(obj)/palo.conf; \
 	fi)
 
-palo: vmlinuz
+palo lifimage: vmlinuz
 	@if test ! -x "$(PALO)"; then \
 		echo 'ERROR: Please install palo first (apt-get install palo)';\
 		echo 'or build it from source and install it somewhere in your $$PATH';\
@@ -109,16 +109,23 @@
 	fi
 	$(PALO) -f $(PALOCONF)
 
-# Shorthands for known targets not supported by parisc, use vmlinux/vmlinuz as default
+BOOT_TARGETS    = zImage Image palo lifimage
+INSTALL_TARGETS = zinstall install
+
+PHONY += bzImage $(BOOT_TARGETS) $(INSTALL_TARGETS)
+
+bzImage zImage: vmlinuz
 Image: vmlinux
-zImage bzImage: vmlinuz
 
 vmlinuz: vmlinux
 	@gzip -cf -9 $< > $@
 
-install: vmlinuz
-	sh $(src)/arch/parisc/install.sh \
-			$(KERNELRELEASE) $< System.map "$(INSTALL_PATH)"
+install:
+	$(CONFIG_SHELL) $(src)/arch/parisc/install.sh \
+			$(KERNELRELEASE) vmlinux System.map "$(INSTALL_PATH)"
+zinstall:
+	$(CONFIG_SHELL) $(src)/arch/parisc/install.sh \
+			$(KERNELRELEASE) vmlinuz System.map "$(INSTALL_PATH)"
 
 CLEAN_FILES	+= lifimage
 MRPROPER_FILES	+= palo.conf
@@ -127,10 +134,11 @@
 	@echo  '* vmlinux	- Uncompressed kernel image (./vmlinux)'
 	@echo  '  vmlinuz	- Compressed kernel image (./vmlinuz)'
 	@echo  '  palo		- Bootable image (./lifimage)'
-	@echo  '  install	- Install kernel using'
+	@echo  '  install	- Install uncompressed vmlinux kernel using'
 	@echo  '		  (your) ~/bin/$(INSTALLKERNEL) or'
 	@echo  '		  (distribution) /sbin/$(INSTALLKERNEL) or'
 	@echo  '		  copy to $$(INSTALL_PATH)'
+	@echo  '  zinstall	- Install compressed vmlinuz kernel'
 endef
 
 # we require gcc 3.3 or above to compile the kernel
diff --git a/arch/parisc/configs/712_defconfig b/arch/parisc/configs/712_defconfig
index 0f90569..9387cc2 100644
--- a/arch/parisc/configs/712_defconfig
+++ b/arch/parisc/configs/712_defconfig
@@ -40,6 +40,8 @@
 CONFIG_LLC2=m
 CONFIG_NET_PKTGEN=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_PARPORT=y
diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig
index b647b18..9002532 100644
--- a/arch/parisc/configs/a500_defconfig
+++ b/arch/parisc/configs/a500_defconfig
@@ -79,6 +79,8 @@
 CONFIG_LLC2=m
 CONFIG_NET_PKTGEN=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_BLK_DEV_UMEM=m
diff --git a/arch/parisc/configs/b180_defconfig b/arch/parisc/configs/b180_defconfig
index e289f5b..f1a0c25 100644
--- a/arch/parisc/configs/b180_defconfig
+++ b/arch/parisc/configs/b180_defconfig
@@ -4,6 +4,7 @@
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODVERSIONS=y
@@ -27,6 +28,8 @@
 # CONFIG_INET_LRO is not set
 CONFIG_IPV6=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_PARPORT=y
 CONFIG_PARPORT_PC=y
diff --git a/arch/parisc/configs/c3000_defconfig b/arch/parisc/configs/c3000_defconfig
index 311ca36..ec1b014 100644
--- a/arch/parisc/configs/c3000_defconfig
+++ b/arch/parisc/configs/c3000_defconfig
@@ -5,6 +5,7 @@
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
 CONFIG_KALLSYMS_ALL=y
@@ -39,6 +40,8 @@
 CONFIG_IP_NF_QUEUE=m
 CONFIG_NET_PKTGEN=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_BLK_DEV_UMEM=m
diff --git a/arch/parisc/configs/c8000_defconfig b/arch/parisc/configs/c8000_defconfig
index f110063..e1c8d20 100644
--- a/arch/parisc/configs/c8000_defconfig
+++ b/arch/parisc/configs/c8000_defconfig
@@ -62,6 +62,8 @@
 CONFIG_LLC2=m
 CONFIG_DNS_RESOLVER=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 CONFIG_PARPORT=y
 CONFIG_PARPORT_PC=y
diff --git a/arch/parisc/configs/default_defconfig b/arch/parisc/configs/default_defconfig
index dfe88f6..ba61495 100644
--- a/arch/parisc/configs/default_defconfig
+++ b/arch/parisc/configs/default_defconfig
@@ -49,6 +49,8 @@
 CONFIG_INET6_IPCOMP=y
 CONFIG_LLC2=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_PARPORT=y
diff --git a/arch/parisc/configs/generic-32bit_defconfig b/arch/parisc/configs/generic-32bit_defconfig
new file mode 100644
index 0000000..33b148f
--- /dev/null
+++ b/arch/parisc/configs/generic-32bit_defconfig
@@ -0,0 +1,328 @@
+CONFIG_LOCALVERSION="-32bit"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_LZO=y
+CONFIG_EXPERT=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_PERF_EVENTS=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PA7100LC=y
+CONFIG_SMP=y
+CONFIG_HZ_100=y
+CONFIG_IOMMU_CCIO=y
+CONFIG_GSC_LASI=y
+CONFIG_GSC_WAX=y
+CONFIG_EISA=y
+CONFIG_PCI=y
+CONFIG_GSC_DINO=y
+CONFIG_PCI_LBA=y
+CONFIG_PCCARD=m
+CONFIG_YENTA=m
+# CONFIG_PDC_CHASSIS is not set
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=m
+CONFIG_LLC2=m
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_PARPORT=y
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_1284=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=6144
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_GENERIC=y
+CONFIG_BLK_DEV_NS87415=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_LASI700=y
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_ZALON=y
+CONFIG_SCSI_DH=y
+CONFIG_ATA=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_UEVENT=y
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_DUMMY=m
+CONFIG_TUN=m
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+CONFIG_NET_TULIP=y
+CONFIG_TULIP=y
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+# CONFIG_NET_VENDOR_HP is not set
+CONFIG_LASI_82596=y
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_NET_PACKET_ENGINE is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_VIA is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPPOE=m
+# CONFIG_WLAN is not set
+CONFIG_INPUT_POLLDEV=y
+CONFIG_KEYBOARD_HIL_OLD=m
+CONFIG_KEYBOARD_HIL=m
+CONFIG_MOUSE_SERIAL=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+CONFIG_LEGACY_PTY_COUNT=64
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=8
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_PRINTER=m
+CONFIG_PPDEV=m
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_HWMON is not set
+CONFIG_AGP=y
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FB_FOREIGN_ENDIAN=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_MATROX=m
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_VOODOO1=m
+CONFIG_DUMMY_CONSOLE_COLUMNS=128
+CONFIG_DUMMY_CONSOLE_ROWS=48
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_SOUND=m
+CONFIG_SND=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_AD1889=m
+CONFIG_SND_HARMONY=m
+CONFIG_HIDRAW=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_KYE=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_KENSINGTON=y
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_LOGITECH_DJ=m
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_ORTEK=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
+CONFIG_HID_ZEROPLUS=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_UHCI_HCD=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_DMADEVICES=y
+CONFIG_AUXDISPLAY=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_RT=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V2=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_VFAT_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_NFS_FS=m
+# CONFIG_NFS_V2 is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+CONFIG_CIFS=m
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_RT_MUTEX_TESTER=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_RCU_CPU_STALL_INFO=y
+CONFIG_LATENCYTOP=y
+CONFIG_LKDTM=m
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_T10DIF=y
+CONFIG_FONTS=y
diff --git a/arch/parisc/configs/generic-64bit_defconfig b/arch/parisc/configs/generic-64bit_defconfig
new file mode 100644
index 0000000..5874ceb
--- /dev/null
+++ b/arch/parisc/configs/generic-64bit_defconfig
@@ -0,0 +1,346 @@
+CONFIG_LOCALVERSION="-64bit"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_BLK_DEV_INTEGRITY=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_PA8X00=y
+CONFIG_MLONGCALLS=y
+CONFIG_64BIT=y
+CONFIG_SMP=y
+# CONFIG_COMPACTION is not set
+CONFIG_HPPB=y
+CONFIG_IOMMU_CCIO=y
+CONFIG_GSC_LASI=y
+CONFIG_GSC_WAX=y
+CONFIG_PCI=y
+CONFIG_PCI_STUB=m
+CONFIG_PCI_IOV=y
+CONFIG_GSC_DINO=y
+CONFIG_PCI_LBA=y
+CONFIG_BINFMT_MISC=m
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=m
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=m
+CONFIG_INET_DIAG=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_ADVANCED is not set
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_DCB=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_IDE=y
+CONFIG_IDE_GD=m
+CONFIG_IDE_GD_ATAPI=y
+CONFIG_BLK_DEV_IDECD=m
+CONFIG_BLK_DEV_NS87415=y
+CONFIG_BLK_DEV_SIIMAGE=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_SCSI_ISCSI_ATTRS=y
+CONFIG_SCSI_SRP_ATTRS=y
+CONFIG_ISCSI_BOOT_SYSFS=y
+CONFIG_SCSI_MPT2SAS=y
+CONFIG_SCSI_LASI700=m
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_ZALON=y
+CONFIG_SCSI_QLA_ISCSI=m
+CONFIG_SCSI_DH=y
+CONFIG_ATA=y
+CONFIG_ATA_GENERIC=y
+CONFIG_MD=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_RAID=m
+CONFIG_DM_UEVENT=y
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=y
+CONFIG_FUSION_SAS=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_TUN=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+CONFIG_NET_TULIP=y
+CONFIG_TULIP=y
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+CONFIG_HP100=m
+CONFIG_E1000=y
+CONFIG_LASI_82596=y
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+CONFIG_QLA3XXX=m
+CONFIG_QLCNIC=m
+CONFIG_QLGE=m
+# CONFIG_NET_VENDOR_REALTEK is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PHYLIB=y
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_BROADCOM_PHY=m
+CONFIG_ICPLUS_PHY=m
+CONFIG_REALTEK_PHY=m
+CONFIG_NATIONAL_PHY=m
+CONFIG_STE10XP=m
+CONFIG_LSI_ET1011C_PHY=m
+CONFIG_MDIO_BITBANG=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_HIL_OLD is not set
+# CONFIG_KEYBOARD_HIL is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+CONFIG_SERIO_SERPORT=m
+# CONFIG_HP_SDC is not set
+CONFIG_SERIO_RAW=m
+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_NOZOMI=m
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=8
+CONFIG_SERIAL_8250_RUNTIME_UARTS=8
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_JSM=m
+CONFIG_IPMI_HANDLER=y
+CONFIG_IPMI_DEVICE_INTERFACE=y
+CONFIG_IPMI_SI=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_TCG_TPM=m
+CONFIG_TCG_ATMEL=m
+CONFIG_PTP_1588_CLOCK=m
+CONFIG_SENSORS_I5K_AMB=m
+CONFIG_SENSORS_F71882FG=m
+CONFIG_SENSORS_PC87427=m
+CONFIG_SENSORS_VT1211=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_WATCHDOG=y
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_SSB=m
+CONFIG_SSB_DRIVER_PCICORE=y
+CONFIG_HTC_PASIC3=m
+CONFIG_LPC_SCH=m
+CONFIG_MFD_SM501=m
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=m
+CONFIG_REGULATOR_USERSPACE_CONSUMER=m
+CONFIG_MEDIA_SUPPORT=m
+CONFIG_AGP=y
+CONFIG_AGP_PARISC=y
+CONFIG_DRM=y
+CONFIG_DRM_RADEON=y
+CONFIG_DRM_RADEON_UMS=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+CONFIG_HID=m
+CONFIG_HIDRAW=y
+CONFIG_HID_DRAGONRISE=m
+CONFIG_DRAGONRISE_FF=y
+CONFIG_HID_KYE=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_TWINHAN=m
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_HID_NTRIG=m
+CONFIG_HID_PANTHERLORD=m
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SUNPLUS=m
+CONFIG_HID_GREENASIA=m
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_SMARTJOYPLUS=m
+CONFIG_SMARTJOYPLUS_FF=y
+CONFIG_HID_TOPSEED=m
+CONFIG_HID_THRUSTMASTER=m
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_HID_ZEROPLUS=m
+CONFIG_ZEROPLUS_FF=y
+CONFIG_USB_HID=m
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DYNAMIC_MINORS=y
+CONFIG_USB_MON=m
+CONFIG_USB_WUSB_CBAF=m
+CONFIG_USB_XHCI_HCD=m
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_R8A66597_HCD=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+CONFIG_UIO=y
+CONFIG_UIO_PDRV_GENIRQ=m
+CONFIG_UIO_AEC=m
+CONFIG_UIO_SERCOS3=m
+CONFIG_UIO_PCI_GENERIC=m
+CONFIG_STAGING=y
+# CONFIG_NET_VENDOR_SILICOM is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_XFS_FS=m
+CONFIG_BTRFS_FS=m
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V2=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+CONFIG_ISO9660_FS=y
+CONFIG_UDF_FS=y
+CONFIG_VFAT_FS=m
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_SYSV_FS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V4=m
+CONFIG_NFS_V4_1=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V4=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_UTF8=m
+CONFIG_PRINTK_TIME=y
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=m
+CONFIG_LIBCRC32C=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index ff4c9fa..a603b9e 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -4,3 +4,4 @@
 	  div64.h irq_regs.h kdebug.h kvm_para.h local64.h local.h param.h \
 	  poll.h xor.h clkdev.h exec.h
 generic-y += trace_clock.h
+generic-y += preempt.h
diff --git a/arch/parisc/include/asm/assembly.h b/arch/parisc/include/asm/assembly.h
index 0da8482..b3069fd 100644
--- a/arch/parisc/include/asm/assembly.h
+++ b/arch/parisc/include/asm/assembly.h
@@ -515,5 +515,17 @@
 	nop	/* 7 */
 	.endm
 
+	/*
+	 * ASM_EXCEPTIONTABLE_ENTRY
+	 *
+	 * Creates an exception table entry.
+	 * Do not convert to a assembler macro. This won't work.
+	 */
+#define ASM_EXCEPTIONTABLE_ENTRY(fault_addr, except_addr)	\
+	.section __ex_table,"aw"			!	\
+	ASM_ULONG_INSN	fault_addr, except_addr		!	\
+	.previous
+
+
 #endif /* __ASSEMBLY__ */
 #endif
diff --git a/arch/parisc/include/asm/delay.h b/arch/parisc/include/asm/delay.h
index 912ee7e..08e58e6 100644
--- a/arch/parisc/include/asm/delay.h
+++ b/arch/parisc/include/asm/delay.h
@@ -1,15 +1,5 @@
-#ifndef _PARISC_DELAY_H
-#define _PARISC_DELAY_H
-
-#include <asm/special_insns.h>    /* for mfctl() */
-#include <asm/processor.h> /* for boot_cpu_data */
-
-
-/*
- * Copyright (C) 1993 Linus Torvalds
- *
- * Delay routines
- */
+#ifndef _ASM_PARISC_DELAY_H
+#define _ASM_PARISC_DELAY_H
 
 static __inline__ void __delay(unsigned long loops) {
 	asm volatile(
@@ -19,25 +9,14 @@
 		: "=r" (loops) : "0" (loops));
 }
 
-static __inline__ void __cr16_delay(unsigned long clocks) {
-	unsigned long start;
+extern void __udelay(unsigned long usecs);
+extern void __udelay_bad(unsigned long usecs);
 
-	/*
-	 * Note: Due to unsigned math, cr16 rollovers shouldn't be
-	 * a problem here. However, on 32 bit, we need to make sure
-	 * we don't pass in too big a value. The current default
-	 * value of MAX_UDELAY_MS should help prevent this.
-	 */
-
-	start = mfctl(16);
-	while ((mfctl(16) - start) < clocks)
-	    ;
+static inline void udelay(unsigned long usecs)
+{
+	if (__builtin_constant_p(usecs) && (usecs) > 20000)
+		__udelay_bad(usecs);
+	__udelay(usecs);
 }
 
-static __inline__ void __udelay(unsigned long usecs) {
-	__cr16_delay(usecs * ((unsigned long)boot_cpu_data.cpu_hz / 1000000UL));
-}
-
-#define udelay(n) __udelay(n)
-
-#endif /* defined(_PARISC_DELAY_H) */
+#endif /* _ASM_PARISC_DELAY_H */
diff --git a/arch/parisc/include/asm/hardirq.h b/arch/parisc/include/asm/hardirq.h
index 241c345..9b3bd03 100644
--- a/arch/parisc/include/asm/hardirq.h
+++ b/arch/parisc/include/asm/hardirq.h
@@ -21,7 +21,6 @@
 	unsigned int irq_stack_usage;
 #ifdef CONFIG_SMP
 	unsigned int irq_resched_count;
-	unsigned int irq_call_count;
 #endif
 	unsigned int irq_unaligned_count;
 	unsigned int irq_fpassist_count;
diff --git a/arch/parisc/include/asm/ptrace.h b/arch/parisc/include/asm/ptrace.h
index a2db278..3c3cb00 100644
--- a/arch/parisc/include/asm/ptrace.h
+++ b/arch/parisc/include/asm/ptrace.h
@@ -19,5 +19,9 @@
 #define user_stack_pointer(regs)	((regs)->gr[30])
 unsigned long profile_pc(struct pt_regs *);
 
+static inline unsigned long regs_return_value(struct pt_regs *regs)
+{
+	return regs->gr[20];
+}
 
 #endif
diff --git a/arch/parisc/include/asm/thread_info.h b/arch/parisc/include/asm/thread_info.h
index 540c88f..bc7cf12 100644
--- a/arch/parisc/include/asm/thread_info.h
+++ b/arch/parisc/include/asm/thread_info.h
@@ -59,6 +59,7 @@
 #define TIF_32BIT               4       /* 32 bit binary */
 #define TIF_MEMDIE		5	/* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK	6	/* restore saved signal mask */
+#define TIF_SYSCALL_AUDIT	7	/* syscall auditing active */
 #define TIF_NOTIFY_RESUME	8	/* callback before returning to user */
 #define TIF_SINGLESTEP		9	/* single stepping? */
 #define TIF_BLOCKSTEP		10	/* branch stepping? */
@@ -68,6 +69,7 @@
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 #define _TIF_32BIT		(1 << TIF_32BIT)
+#define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
 #define _TIF_BLOCKSTEP		(1 << TIF_BLOCKSTEP)
@@ -75,7 +77,7 @@
 #define _TIF_USER_WORK_MASK     (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | \
                                  _TIF_NEED_RESCHED)
 #define _TIF_SYSCALL_TRACE_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP |	\
-				 _TIF_BLOCKSTEP)
+				 _TIF_BLOCKSTEP | _TIF_SYSCALL_AUDIT)
 
 #endif /* __KERNEL__ */
 
diff --git a/arch/parisc/include/asm/traps.h b/arch/parisc/include/asm/traps.h
index 1945f99..4736020 100644
--- a/arch/parisc/include/asm/traps.h
+++ b/arch/parisc/include/asm/traps.h
@@ -6,7 +6,7 @@
 
 /* traps.c */
 void parisc_terminate(char *msg, struct pt_regs *regs,
-		int code, unsigned long offset);
+		int code, unsigned long offset) __noreturn __cold;
 
 /* mm/fault.c */
 void do_page_fault(struct pt_regs *regs, unsigned long code,
diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h
index e0a8235..63f4dd0 100644
--- a/arch/parisc/include/asm/uaccess.h
+++ b/arch/parisc/include/asm/uaccess.h
@@ -4,11 +4,14 @@
 /*
  * User space memory access functions
  */
+#include <asm/processor.h>
 #include <asm/page.h>
 #include <asm/cache.h>
 #include <asm/errno.h>
 #include <asm-generic/uaccess-unaligned.h>
 
+#include <linux/sched.h>
+
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1
 
@@ -33,12 +36,43 @@
 extern int __put_kernel_bad(void);
 extern int __put_user_bad(void);
 
-static inline long access_ok(int type, const void __user * addr,
-		unsigned long size)
+
+/*
+ * Test whether a block of memory is a valid user space address.
+ * Returns 0 if the range is valid, nonzero otherwise.
+ */
+static inline int __range_not_ok(unsigned long addr, unsigned long size,
+				 unsigned long limit)
 {
-	return 1;
+	unsigned long __newaddr = addr + size;
+	return (__newaddr < addr || __newaddr > limit || size > limit);
 }
 
+/**
+ * access_ok: - Checks if a user space pointer is valid
+ * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE.  Note that
+ *        %VERIFY_WRITE is a superset of %VERIFY_READ - if it is safe
+ *        to write to a block, it is always safe to read from it.
+ * @addr: User space pointer to start of block to check
+ * @size: Size of block to check
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * Checks if a pointer to a block of memory in user space is valid.
+ *
+ * Returns true (nonzero) if the memory block may be valid, false (zero)
+ * if it is definitely invalid.
+ *
+ * Note that, depending on architecture, this function probably just
+ * checks that the pointer is in the user space range - after calling
+ * this function, memory access functions may still return -EFAULT.
+ */
+#define access_ok(type, addr, size)					\
+(	__chk_user_ptr(addr),						\
+	!__range_not_ok((unsigned long) (__force void *) (addr),	\
+			size, user_addr_max())				\
+)
+
 #define put_user __put_user
 #define get_user __get_user
 
@@ -59,12 +93,13 @@
 /*
  * The exception table contains two values: the first is an address
  * for an instruction that is allowed to fault, and the second is
- * the address to the fixup routine. 
+ * the address to the fixup routine. Even on a 64bit kernel we could
+ * use a 32bit (unsigned int) address here.
  */
 
 struct exception_table_entry {
-	unsigned long insn;  /* address of insn that is allowed to fault.   */
-	long fixup;          /* fixup routine */
+	unsigned long insn;	/* address of insn that is allowed to fault. */
+	unsigned long fixup;	/* fixup routine */
 };
 
 #define ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr )\
@@ -218,7 +253,11 @@
 /*
  * Complex access routines -- macros
  */
-#define user_addr_max() (~0UL)
+#ifdef CONFIG_COMPAT
+#define user_addr_max() (TASK_SIZE)
+#else
+#define user_addr_max() (DEFAULT_TASK_SIZE)
+#endif
 
 #define strnlen_user lstrnlen_user
 #define strlen_user(str) lstrnlen_user(str, 0x7fffffffL)
diff --git a/arch/parisc/install.sh b/arch/parisc/install.sh
index 4da682b..6f68784 100644
--- a/arch/parisc/install.sh
+++ b/arch/parisc/install.sh
@@ -19,20 +19,48 @@
 #   $4 - default install path (blank if root directory)
 #
 
+verify () {
+	if [ ! -f "$1" ]; then
+		echo ""                                                   1>&2
+		echo " *** Missing file: $1"                              1>&2
+		echo ' *** You need to run "make" before "make install".' 1>&2
+		echo ""                                                   1>&2
+		exit 1
+	fi
+}
+
+# Make sure the files actually exist
+
+verify "$2"
+verify "$3"
+
 # User may have a custom install script
 
-if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi
-if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi
+if [ -n "${INSTALLKERNEL}" ]; then
+  if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi
+  if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi
+fi
 
 # Default install
 
-if [ -f $4/vmlinuz ]; then
-	mv $4/vmlinuz $4/vmlinuz.old
+if [ "$(basename $2)" = "zImage" ]; then
+# Compressed install
+  echo "Installing compressed kernel"
+  base=vmlinuz
+else
+# Normal install
+  echo "Installing normal kernel"
+  base=vmlinux
 fi
 
-if [ -f $4/System.map ]; then
-	mv $4/System.map $4/System.old
+if [ -f $4/$base-$1 ]; then
+  mv $4/$base-$1 $4/$base-$1.old
 fi
+cat $2 > $4/$base-$1
 
-cat $2 > $4/vmlinuz
-cp $3 $4/System.map
+# Install system map file
+if [ -f $4/System.map-$1 ]; then
+  mv $4/System.map-$1 $4/System.map-$1.old
+fi
+cp $3 $4/System.map-$1
+
diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
index 66ee3f1..ff87b46 100644
--- a/arch/parisc/kernel/Makefile
+++ b/arch/parisc/kernel/Makefile
@@ -29,7 +29,9 @@
 obj-$(CONFIG_MODULES)	+= module.o
 obj-$(CONFIG_64BIT)	+= binfmt_elf32.o sys_parisc32.o signal32.o
 obj-$(CONFIG_STACKTRACE)+= stacktrace.o
+obj-$(CONFIG_AUDIT)	+= audit.o
+obj64-$(CONFIG_AUDIT)	+= compat_audit.o
 # only supported for PCX-W/U in 64-bit mode at the moment
-obj-$(CONFIG_64BIT)	+= perf.o perf_asm.o
+obj-$(CONFIG_64BIT)	+= perf.o perf_asm.o $(obj64-y)
 obj-$(CONFIG_FUNCTION_TRACER)		+= ftrace.o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER)	+= ftrace.o
diff --git a/arch/parisc/kernel/audit.c b/arch/parisc/kernel/audit.c
new file mode 100644
index 0000000..eb64a61
--- /dev/null
+++ b/arch/parisc/kernel/audit.c
@@ -0,0 +1,81 @@
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/audit.h>
+#include <asm/unistd.h>
+
+static unsigned dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+static unsigned read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+static unsigned write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+static unsigned chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
+int audit_classify_arch(int arch)
+{
+#ifdef CONFIG_COMPAT
+	if (arch == AUDIT_ARCH_PARISC)
+		return 1;
+#endif
+	return 0;
+}
+
+int audit_classify_syscall(int abi, unsigned syscall)
+{
+#ifdef CONFIG_COMPAT
+	extern int parisc32_classify_syscall(unsigned);
+	if (abi == AUDIT_ARCH_PARISC)
+		return parisc32_classify_syscall(syscall);
+#endif
+	switch (syscall) {
+	case __NR_open:
+		return 2;
+	case __NR_openat:
+		return 3;
+	case __NR_execve:
+		return 5;
+	default:
+		return 0;
+	}
+}
+
+static int __init audit_classes_init(void)
+{
+#ifdef CONFIG_COMPAT
+	extern __u32 parisc32_dir_class[];
+	extern __u32 parisc32_write_class[];
+	extern __u32 parisc32_read_class[];
+	extern __u32 parisc32_chattr_class[];
+	extern __u32 parisc32_signal_class[];
+	audit_register_class(AUDIT_CLASS_WRITE_32, parisc32_write_class);
+	audit_register_class(AUDIT_CLASS_READ_32, parisc32_read_class);
+	audit_register_class(AUDIT_CLASS_DIR_WRITE_32, parisc32_dir_class);
+	audit_register_class(AUDIT_CLASS_CHATTR_32, parisc32_chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL_32, parisc32_signal_class);
+#endif
+	audit_register_class(AUDIT_CLASS_WRITE, write_class);
+	audit_register_class(AUDIT_CLASS_READ, read_class);
+	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
+	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
+	return 0;
+}
+
+__initcall(audit_classes_init);
diff --git a/arch/parisc/kernel/compat_audit.c b/arch/parisc/kernel/compat_audit.c
new file mode 100644
index 0000000..c74478f6
--- /dev/null
+++ b/arch/parisc/kernel/compat_audit.c
@@ -0,0 +1,40 @@
+#include <asm/unistd.h>
+
+unsigned int parisc32_dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+unsigned int parisc32_chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+unsigned int parisc32_write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+unsigned int parisc32_read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+unsigned int parisc32_signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
+int parisc32_classify_syscall(unsigned syscall)
+{
+	switch (syscall) {
+	case __NR_open:
+		return 2;
+	case __NR_openat:
+		return 3;
+	case __NR_execve:
+		return 5;
+	default:
+		return 1;
+	}
+}
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S
index 37aabd7..d2d5825 100644
--- a/arch/parisc/kernel/head.S
+++ b/arch/parisc/kernel/head.S
@@ -195,6 +195,8 @@
 	ldw             MEM_PDC_HI(%r0),%r6
 	depd            %r6, 31, 32, %r3        /* move to upper word */
 
+	mfctl		%cr30,%r6		/* PCX-W2 firmware bug */
+
 	ldo             PDC_PSW(%r0),%arg0              /* 21 */
 	ldo             PDC_PSW_SET_DEFAULTS(%r0),%arg1 /* 2 */
 	ldo             PDC_PSW_WIDE_BIT(%r0),%arg2     /* 2 */
@@ -203,6 +205,8 @@
 	copy            %r0,%arg3
 
 stext_pdc_ret:
+	mtctl		%r6,%cr30		/* restore task thread info */
+
 	/* restore rfi target address*/
 	ldd             TI_TASK-THREAD_SZ_ALGN(%sp), %r10
 	tophys_r1       %r10
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
index 2e6443b..8ceac47 100644
--- a/arch/parisc/kernel/irq.c
+++ b/arch/parisc/kernel/irq.c
@@ -179,10 +179,6 @@
 	for_each_online_cpu(j)
 		seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count);
 	seq_puts(p, "  Rescheduling interrupts\n");
-	seq_printf(p, "%*s: ", prec, "CAL");
-	for_each_online_cpu(j)
-		seq_printf(p, "%10u ", irq_stats(j)->irq_call_count);
-	seq_puts(p, "  Function call interrupts\n");
 #endif
 	seq_printf(p, "%*s: ", prec, "UAH");
 	for_each_online_cpu(j)
@@ -499,22 +495,9 @@
 	*irq_stack_in_use = 1;
 }
 
-asmlinkage void do_softirq(void)
+void do_softirq_own_stack(void)
 {
-	__u32 pending;
-	unsigned long flags;
-
-	if (in_interrupt())
-		return;
-
-	local_irq_save(flags);
-
-	pending = local_softirq_pending();
-
-	if (pending)
-		execute_on_irq_stack(__do_softirq, 0);
-
-	local_irq_restore(flags);
+	execute_on_irq_stack(__do_softirq, 0);
 }
 #endif /* CONFIG_IRQSTACKS */
 
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 534abd4..e842ee2 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -19,6 +19,7 @@
 #include <linux/security.h>
 #include <linux/compat.h>
 #include <linux/signal.h>
+#include <linux/audit.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -267,11 +268,28 @@
 
 long do_syscall_trace_enter(struct pt_regs *regs)
 {
+	long ret = 0;
+
 	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
 	    tracehook_report_syscall_entry(regs))
-		return -1L;
+		ret = -1L;
 
-	return regs->gr[20];
+#ifdef CONFIG_64BIT
+	if (!is_compat_task())
+		audit_syscall_entry(AUDIT_ARCH_PARISC64,
+			regs->gr[20],
+			regs->gr[26], regs->gr[25],
+			regs->gr[24], regs->gr[23]);
+	else
+#endif
+		audit_syscall_entry(AUDIT_ARCH_PARISC,
+			regs->gr[20] & 0xffffffff,
+			regs->gr[26] & 0xffffffff,
+			regs->gr[25] & 0xffffffff,
+			regs->gr[24] & 0xffffffff,
+			regs->gr[23] & 0xffffffff);
+
+	return ret ? : regs->gr[20];
 }
 
 void do_syscall_trace_exit(struct pt_regs *regs)
@@ -279,6 +297,8 @@
 	int stepping = test_thread_flag(TIF_SINGLESTEP) ||
 		test_thread_flag(TIF_BLOCKSTEP);
 
+	audit_syscall_exit(regs);
+
 	if (stepping || test_thread_flag(TIF_SYSCALL_TRACE))
 		tracehook_report_syscall_exit(regs, stepping);
 }
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
index 7349a3f..72a3c65 100644
--- a/arch/parisc/kernel/setup.c
+++ b/arch/parisc/kernel/setup.c
@@ -318,8 +318,12 @@
 	pdc_stable_write(0x40, &osid, sizeof(osid));
 	
 	processor_init();
-	printk(KERN_INFO "CPU(s): %d x %s at %d.%06d MHz\n",
-			num_present_cpus(),
+#ifdef CONFIG_SMP
+	pr_info("CPU(s): %d out of %d %s at %d.%06d MHz online\n",
+		num_online_cpus(), num_present_cpus(),
+#else
+	pr_info("CPU(s): 1 x %s at %d.%06d MHz\n",
+#endif
 			boot_cpu_data.cpu_name,
 			boot_cpu_data.cpu_hz / 1000000,
 			boot_cpu_data.cpu_hz % 1000000	);
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index 8a252f2..ceda229 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -72,7 +72,6 @@
 	IPI_NOP=0,
 	IPI_RESCHEDULE=1,
 	IPI_CALL_FUNC,
-	IPI_CALL_FUNC_SINGLE,
 	IPI_CPU_START,
 	IPI_CPU_STOP,
 	IPI_CPU_TEST
@@ -126,11 +125,6 @@
 	unsigned long ops;
 	unsigned long flags;
 
-	/* Count this now; we may make a call that never returns. */
-	inc_irq_stat(irq_call_count);
-
-	mb();	/* Order interrupt and bit testing. */
-
 	for (;;) {
 		spinlock_t *lock = &per_cpu(ipi_lock, this_cpu);
 		spin_lock_irqsave(lock, flags);
@@ -164,11 +158,6 @@
 				generic_smp_call_function_interrupt();
 				break;
 
-			case IPI_CALL_FUNC_SINGLE:
-				smp_debug(100, KERN_DEBUG "CPU%d IPI_CALL_FUNC_SINGLE\n", this_cpu);
-				generic_smp_call_function_single_interrupt();
-				break;
-
 			case IPI_CPU_START:
 				smp_debug(100, KERN_DEBUG "CPU%d IPI_CPU_START\n", this_cpu);
 				break;
@@ -260,7 +249,7 @@
 
 void arch_send_call_function_single_ipi(int cpu)
 {
-	send_IPI_single(cpu, IPI_CALL_FUNC_SINGLE);
+	send_IPI_single(cpu, IPI_CALL_FUNC);
 }
 
 /*
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index e767ab7..a63bb179 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -649,10 +649,8 @@
 	/* Two exception table entries, one for the load,
 	   the other for the store. Either return -EFAULT.
 	   Each of the entries must be relocated. */
-	.section __ex_table,"aw"
-	ASM_ULONG_INSN (1b - linux_gateway_page), (3b - linux_gateway_page)
-	ASM_ULONG_INSN (2b - linux_gateway_page), (3b - linux_gateway_page)
-	.previous
+	ASM_EXCEPTIONTABLE_ENTRY(1b-linux_gateway_page, 3b-linux_gateway_page)
+	ASM_EXCEPTIONTABLE_ENTRY(2b-linux_gateway_page, 3b-linux_gateway_page)
 
 
 	/* Make sure nothing else is placed on this page */
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 04e47c6..1cd1d0c 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -291,11 +291,6 @@
 	do_exit(SIGSEGV);
 }
 
-int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs)
-{
-	return syscall(regs);
-}
-
 /* gdb uses break 4,8 */
 #define GDB_BREAK_INSN 0x10004
 static void handle_gdb_break(struct pt_regs *regs, int wot)
@@ -805,14 +800,14 @@
 	else {
 
 	    /*
-	     * The kernel should never fault on its own address space.
+	     * The kernel should never fault on its own address space,
+	     * unless pagefault_disable() was called before.
 	     */
 
-	    if (fault_space == 0) 
+	    if (fault_space == 0 && !in_atomic())
 	    {
 		pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC);
 		parisc_terminate("Kernel Fault", regs, code, fault_address);
-	
 	    }
 	}
 
diff --git a/arch/parisc/lib/Makefile b/arch/parisc/lib/Makefile
index 5651536..8fa92b8 100644
--- a/arch/parisc/lib/Makefile
+++ b/arch/parisc/lib/Makefile
@@ -3,6 +3,6 @@
 #
 
 lib-y	:= lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o \
-	   ucmpdi2.o
+	   ucmpdi2.o delay.o
 
 obj-y	:= iomap.o
diff --git a/arch/parisc/lib/delay.c b/arch/parisc/lib/delay.c
new file mode 100644
index 0000000..ec9255f
--- /dev/null
+++ b/arch/parisc/lib/delay.c
@@ -0,0 +1,73 @@
+/*
+ *	Precise Delay Loops for parisc
+ *
+ *	based on code by:
+ *	Copyright (C) 1993 Linus Torvalds
+ *	Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *	Copyright (C) 2008 Jiri Hladky <hladky _dot_ jiri _at_ gmail _dot_ com>
+ *
+ *	parisc implementation:
+ *	Copyright (C) 2013 Helge Deller <deller@gmx.de>
+ */
+
+
+#include <linux/module.h>
+#include <linux/preempt.h>
+#include <linux/init.h>
+
+#include <asm/processor.h>
+#include <asm/delay.h>
+
+#include <asm/special_insns.h>    /* for mfctl() */
+#include <asm/processor.h> /* for boot_cpu_data */
+
+/* CR16 based delay: */
+static void __cr16_delay(unsigned long __loops)
+{
+	/*
+	 * Note: Due to unsigned math, cr16 rollovers shouldn't be
+	 * a problem here. However, on 32 bit, we need to make sure
+	 * we don't pass in too big a value. The current default
+	 * value of MAX_UDELAY_MS should help prevent this.
+	 */
+	u32 bclock, now, loops = __loops;
+	int cpu;
+
+	preempt_disable();
+	cpu = smp_processor_id();
+	bclock = mfctl(16);
+	for (;;) {
+		now = mfctl(16);
+		if ((now - bclock) >= loops)
+			break;
+
+		/* Allow RT tasks to run */
+		preempt_enable();
+		asm volatile("	nop\n");
+		barrier();
+		preempt_disable();
+
+		/*
+		 * It is possible that we moved to another CPU, and
+		 * since CR16's are per-cpu we need to calculate
+		 * that. The delay must guarantee that we wait "at
+		 * least" the amount of time. Being moved to another
+		 * CPU could make the wait longer but we just need to
+		 * make sure we waited long enough. Rebalance the
+		 * counter for this CPU.
+		 */
+		if (unlikely(cpu != smp_processor_id())) {
+			loops -= (now - bclock);
+			cpu = smp_processor_id();
+			bclock = mfctl(16);
+		}
+	}
+	preempt_enable();
+}
+
+
+void __udelay(unsigned long usecs)
+{
+	__cr16_delay(usecs * ((unsigned long)boot_cpu_data.cpu_hz / 1000000UL));
+}
+EXPORT_SYMBOL(__udelay);
diff --git a/arch/parisc/lib/lusercopy.S b/arch/parisc/lib/lusercopy.S
index 6f2d935..a512f07 100644
--- a/arch/parisc/lib/lusercopy.S
+++ b/arch/parisc/lib/lusercopy.S
@@ -88,9 +88,7 @@
 	ldo        1(%r25),%r25
 	.previous
 
-	.section __ex_table,"aw"
-	ASM_ULONG_INSN 1b,2b
-	.previous
+	ASM_EXCEPTIONTABLE_ENTRY(1b,2b)
 
 	.procend
 
@@ -129,10 +127,8 @@
 	copy        %r24,%r26    /* reset r26 so 0 is returned on fault */
 	.previous
 
-	.section __ex_table,"aw"
-	ASM_ULONG_INSN 1b,3b
-	ASM_ULONG_INSN 2b,3b
-	.previous
+	ASM_EXCEPTIONTABLE_ENTRY(1b,3b)
+	ASM_EXCEPTIONTABLE_ENTRY(2b,3b)
 
 	.procend
 
diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c
index ac4370b..b5507ec 100644
--- a/arch/parisc/lib/memcpy.c
+++ b/arch/parisc/lib/memcpy.c
@@ -56,7 +56,7 @@
 #ifdef __KERNEL__
 #include <linux/module.h>
 #include <linux/compiler.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #define s_space "%%sr1"
 #define d_space "%%sr2"
 #else
@@ -524,4 +524,17 @@
 EXPORT_SYMBOL(copy_from_user);
 EXPORT_SYMBOL(copy_in_user);
 EXPORT_SYMBOL(memcpy);
+
+long probe_kernel_read(void *dst, const void *src, size_t size)
+{
+	unsigned long addr = (unsigned long)src;
+
+	if (size < 0 || addr < PAGE_SIZE)
+		return -EFAULT;
+
+	/* check for I/O space F_EXTEND(0xfff00000) access as well? */
+
+	return __probe_kernel_read(dst, src, size);
+}
+
 #endif
diff --git a/arch/parisc/math-emu/float.h b/arch/parisc/math-emu/float.h
index ce76f6d..7a51f97 100644
--- a/arch/parisc/math-emu/float.h
+++ b/arch/parisc/math-emu/float.h
@@ -484,7 +484,6 @@
  * |                                                     |G|L|E|U|X|
  * +-------+-------+-------+-------+-------+-------+-------+-------+
  */
-#define Allexception(object) (object)
 #define Greaterthanbit(object) Bitfield_extract( 27, 1,object)
 #define Lessthanbit(object) Bitfield_extract( 28, 1,object)
 #define Equalbit(object) Bitfield_extract( 29, 1,object)
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
index 00c0ed3..7584a5d 100644
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -142,6 +142,12 @@
 {
 	const struct exception_table_entry *fix;
 
+	/* If we only stored 32bit addresses in the exception table we can drop
+	 * out if we faulted on a 64bit address. */
+	if ((sizeof(regs->iaoq[0]) > sizeof(fix->insn))
+		&& (regs->iaoq[0] >> 32))
+			return 0;
+
 	fix = search_exception_tables(regs->iaoq[0]);
 	if (fix) {
 		struct exception_data *d;
@@ -171,20 +177,25 @@
 			      unsigned long address)
 {
 	struct vm_area_struct *vma, *prev_vma;
-	struct task_struct *tsk = current;
-	struct mm_struct *mm = tsk->mm;
+	struct task_struct *tsk;
+	struct mm_struct *mm;
 	unsigned long acc_type;
 	int fault;
-	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
+	unsigned int flags;
 
-	if (in_atomic() || !mm)
+	if (in_atomic())
 		goto no_context;
 
+	tsk = current;
+	mm = tsk->mm;
+	if (!mm)
+		goto no_context;
+
+	flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 	if (user_mode(regs))
 		flags |= FAULT_FLAG_USER;
 
 	acc_type = parisc_acctyp(code, regs->iir);
-
 	if (acc_type & VM_WRITE)
 		flags |= FAULT_FLAG_WRITE;
 retry:
@@ -269,12 +280,22 @@
 		}
 		show_regs(regs);
 #endif
-		/* FIXME: actually we need to get the signo and code correct */
-		si.si_signo = SIGSEGV;
+		switch (code) {
+		case 15:	/* Data TLB miss fault/Data page fault */
+		case 17:	/* NA data TLB miss / page fault */
+		case 18:	/* Unaligned access - PCXS only */
+			si.si_signo = SIGBUS;
+			si.si_code = BUS_ADRERR;
+			break;
+		case 16:	/* Non-access instruction TLB miss fault */
+		case 26:	/* PCXL: Data memory access rights trap */
+		default:
+			si.si_signo = SIGSEGV;
+			si.si_code = SEGV_MAPERR;
+		}
 		si.si_errno = 0;
-		si.si_code = SEGV_MAPERR;
 		si.si_addr = (void __user *) address;
-		force_sig_info(SIGSEGV, &si, current);
+		force_sig_info(si.si_signo, &si, current);
 		return;
 	}
 
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 38f3b7e..2f898d6 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -97,7 +97,7 @@
 	select VIRT_TO_BUS if !PPC64
 	select HAVE_IDE
 	select HAVE_IOREMAP_PROT
-	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_EFFICIENT_UNALIGNED_ACCESS if !CPU_LITTLE_ENDIAN
 	select HAVE_KPROBES
 	select HAVE_ARCH_KGDB
 	select HAVE_KRETPROBES
@@ -138,6 +138,10 @@
 	select OLD_SIGSUSPEND
 	select OLD_SIGACTION if PPC32
 	select HAVE_DEBUG_STACKOVERFLOW
+	select HAVE_IRQ_EXIT_ON_IRQ_STACK
+
+config GENERIC_CSUM
+	def_bool CPU_LITTLE_ENDIAN
 
 config EARLY_PRINTK
 	bool
@@ -404,7 +408,7 @@
 
 config FA_DUMP
 	bool "Firmware-assisted dump"
-	depends on PPC64 && PPC_RTAS && CRASH_DUMP
+	depends on PPC64 && PPC_RTAS && CRASH_DUMP && KEXEC
 	help
 	  A robust mechanism to get reliable kernel crash dump with
 	  assistance from firmware. This approach does not use kexec,
@@ -417,7 +421,7 @@
 
 config IRQ_ALL_CPUS
 	bool "Distribute interrupts on all CPUs by default"
-	depends on SMP && !MV64360
+	depends on SMP
 	help
 	  This option gives the kernel permission to distribute IRQs across
 	  multiple CPUs.  Saying N here will route all IRQs to the first
@@ -1009,6 +1013,9 @@
 	default "0x00000000"
 endif
 
+config	ARCH_RANDOM
+	def_bool n
+
 source "net/Kconfig"
 
 source "drivers/Kconfig"
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 51cfb78..607acf5 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -36,17 +36,26 @@
 endif
 
 ifeq ($(CONFIG_PPC64),y)
-OLDARCH	:= ppc64
-
 new_nm := $(shell if $(NM) --help 2>&1 | grep -- '--synthetic' > /dev/null; then echo y; else echo n; fi)
 
 ifeq ($(new_nm),y)
 NM		:= $(NM) --synthetic
 endif
+endif
 
+ifeq ($(CONFIG_PPC64),y)
+ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y)
+OLDARCH	:= ppc64le
+else
+OLDARCH	:= ppc64
+endif
+else
+ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y)
+OLDARCH	:= ppcle
 else
 OLDARCH	:= ppc
 endif
+endif
 
 # It seems there are times we use this Makefile without
 # including the config file, but this replicates the old behaviour
@@ -56,11 +65,29 @@
 
 UTS_MACHINE := $(OLDARCH)
 
+ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y)
+override CC	+= -mlittle-endian -mno-strict-align
+override AS	+= -mlittle-endian
+override LD	+= -EL
+override CROSS32CC += -mlittle-endian
+override CROSS32AS += -mlittle-endian
+LDEMULATION	:= lppc
+GNUTARGET	:= powerpcle
+MULTIPLEWORD	:= -mno-multiple
+else
+override CC	+= -mbig-endian
+override AS	+= -mbig-endian
+override LD	+= -EB
+LDEMULATION	:= ppc
+GNUTARGET	:= powerpc
+MULTIPLEWORD	:= -mmultiple
+endif
+
 ifeq ($(HAS_BIARCH),y)
 override AS	+= -a$(CONFIG_WORD_SIZE)
-override LD	+= -m elf$(CONFIG_WORD_SIZE)ppc
+override LD	+= -m elf$(CONFIG_WORD_SIZE)$(LDEMULATION)
 override CC	+= -m$(CONFIG_WORD_SIZE)
-override AR	:= GNUTARGET=elf$(CONFIG_WORD_SIZE)-powerpc $(AR)
+override AR	:= GNUTARGET=elf$(CONFIG_WORD_SIZE)-$(GNUTARGET) $(AR)
 endif
 
 LDFLAGS_vmlinux-y := -Bstatic
@@ -86,7 +113,7 @@
 CFLAGS-$(CONFIG_PPC64)	:= -mtraceback=no -mcall-aixdesc
 CFLAGS-$(CONFIG_PPC64)	+= $(call cc-option,-mcmodel=medium,-mminimal-toc)
 CFLAGS-$(CONFIG_PPC64)	+= $(call cc-option,-mno-pointers-to-nested-functions)
-CFLAGS-$(CONFIG_PPC32)	:= -ffixed-r2 -mmultiple
+CFLAGS-$(CONFIG_PPC32)	:= -ffixed-r2 $(MULTIPLEWORD)
 
 ifeq ($(CONFIG_PPC_BOOK3S_64),y)
 CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power7,-mtune=power4)
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 15ca225..ca7f08c 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -22,7 +22,8 @@
 BOOTCFLAGS    := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
 		 -fno-strict-aliasing -Os -msoft-float -pipe \
 		 -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \
-		 -isystem $(shell $(CROSS32CC) -print-file-name=include)
+		 -isystem $(shell $(CROSS32CC) -print-file-name=include) \
+		 -mbig-endian
 BOOTAFLAGS	:= -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
 
 ifdef CONFIG_DEBUG_INFO
diff --git a/arch/powerpc/boot/dts/b4860emu.dts b/arch/powerpc/boot/dts/b4860emu.dts
new file mode 100644
index 0000000..7290021
--- /dev/null
+++ b/arch/powerpc/boot/dts/b4860emu.dts
@@ -0,0 +1,218 @@
+/*
+ * B4860 emulator Device Tree Source
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its 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") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "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 Freescale Semiconductor 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.
+ */
+
+/dts-v1/;
+
+/include/ "fsl/e6500_power_isa.dtsi"
+
+/ {
+	compatible = "fsl,B4860";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	aliases {
+		ccsr = &soc;
+
+		serial0 = &serial0;
+		serial1 = &serial1;
+		serial2 = &serial2;
+		serial3 = &serial3;
+		dma0 = &dma0;
+		dma1 = &dma1;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: PowerPC,e6500@0 {
+			device_type = "cpu";
+			reg = <0 1>;
+			next-level-cache = <&L2>;
+		};
+		cpu1: PowerPC,e6500@2 {
+			device_type = "cpu";
+			reg = <2 3>;
+			next-level-cache = <&L2>;
+		};
+		cpu2: PowerPC,e6500@4 {
+			device_type = "cpu";
+			reg = <4 5>;
+			next-level-cache = <&L2>;
+		};
+		cpu3: PowerPC,e6500@6 {
+			device_type = "cpu";
+			reg = <6 7>;
+			next-level-cache = <&L2>;
+		};
+	};
+};
+
+/ {
+	model = "fsl,B4860QDS";
+	compatible = "fsl,B4860EMU", "fsl,B4860QDS";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	ifc: localbus@ffe124000 {
+		reg = <0xf 0xfe124000 0 0x2000>;
+		ranges = <0 0 0xf 0xe8000000 0x08000000
+			  2 0 0xf 0xff800000 0x00010000
+			  3 0 0xf 0xffdf0000 0x00008000>;
+
+		nor@0,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x0 0x0 0x8000000>;
+			bank-width = <2>;
+			device-width = <1>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+	};
+
+	soc: soc@ffe000000 {
+		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+		reg = <0xf 0xfe000000 0 0x00001000>;
+	};
+};
+
+&ifc {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	compatible = "fsl,ifc", "simple-bus";
+	interrupts = <25 2 0 0>;
+};
+
+&soc {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	device_type = "soc";
+	compatible = "simple-bus";
+
+	soc-sram-error {
+		compatible = "fsl,soc-sram-error";
+		interrupts = <16 2 1 2>;
+	};
+
+	corenet-law@0 {
+		compatible = "fsl,corenet-law";
+		reg = <0x0 0x1000>;
+		fsl,num-laws = <32>;
+	};
+
+	ddr1: memory-controller@8000 {
+		compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
+		reg = <0x8000 0x1000>;
+		interrupts = <16 2 1 8>;
+	};
+
+	ddr2: memory-controller@9000 {
+		compatible = "fsl,qoriq-memory-controller-v4.5","fsl,qoriq-memory-controller";
+		reg = <0x9000 0x1000>;
+		interrupts = <16 2 1 9>;
+	};
+
+	cpc: l3-cache-controller@10000 {
+		compatible = "fsl,b4-l3-cache-controller", "cache";
+		reg = <0x10000 0x1000
+		       0x11000 0x1000>;
+		interrupts = <16 2 1 4>;
+	};
+
+	corenet-cf@18000 {
+		compatible = "fsl,b4-corenet-cf";
+		reg = <0x18000 0x1000>;
+		interrupts = <16 2 1 0>;
+		fsl,ccf-num-csdids = <32>;
+		fsl,ccf-num-snoopids = <32>;
+	};
+
+	iommu@20000 {
+		compatible = "fsl,pamu-v1.0", "fsl,pamu";
+		reg = <0x20000 0x4000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		interrupts = <
+			24 2 0 0
+			16 2 1 1>;
+		pamu0: pamu@0 {
+			reg = <0 0x1000>;
+			fsl,primary-cache-geometry = <8 1>;
+			fsl,secondary-cache-geometry = <32 2>;
+		};
+	};
+
+/include/ "fsl/qoriq-mpic.dtsi"
+
+	guts: global-utilities@e0000 {
+		compatible = "fsl,b4-device-config";
+		reg = <0xe0000 0xe00>;
+		fsl,has-rstcr;
+		fsl,liodn-bits = <12>;
+	};
+
+	clockgen: global-utilities@e1000 {
+		compatible = "fsl,b4-clockgen", "fsl,qoriq-clockgen-2.0";
+		reg = <0xe1000 0x1000>;
+	};
+
+/include/ "fsl/qoriq-dma-0.dtsi"
+	dma@100300 {
+		fsl,iommu-parent = <&pamu0>;
+		fsl,liodn-reg = <&guts 0x580>; /* DMA1LIODNR */
+	};
+
+/include/ "fsl/qoriq-dma-1.dtsi"
+	dma@101300 {
+		fsl,iommu-parent = <&pamu0>;
+		fsl,liodn-reg = <&guts 0x584>; /* DMA2LIODNR */
+	};
+
+/include/ "fsl/qoriq-i2c-0.dtsi"
+/include/ "fsl/qoriq-i2c-1.dtsi"
+/include/ "fsl/qoriq-duart-0.dtsi"
+/include/ "fsl/qoriq-duart-1.dtsi"
+
+	L2: l2-cache-controller@c20000 {
+		compatible = "fsl,b4-l2-cache-controller";
+		reg = <0xc20000 0x1000>;
+		next-level-cache = <&cpc>;
+	};
+};
diff --git a/arch/powerpc/boot/dts/b4qds.dtsi b/arch/powerpc/boot/dts/b4qds.dtsi
index e6d2f8f..8b47edc 100644
--- a/arch/powerpc/boot/dts/b4qds.dtsi
+++ b/arch/powerpc/boot/dts/b4qds.dtsi
@@ -120,25 +120,38 @@
 		};
 
 		i2c@118000 {
-			eeprom@50 {
-				compatible = "at24,24c64";
-				reg = <0x50>;
-			};
-			eeprom@51 {
-				compatible = "at24,24c256";
-				reg = <0x51>;
-			};
-			eeprom@53 {
-				compatible = "at24,24c256";
-				reg = <0x53>;
-			};
-			eeprom@57 {
-				compatible = "at24,24c256";
-				reg = <0x57>;
-			};
-			rtc@68 {
-				compatible = "dallas,ds3232";
-				reg = <0x68>;
+			mux@77 {
+				compatible = "nxp,pca9547";
+				reg = <0x77>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				i2c@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					eeprom@50 {
+						compatible = "at24,24c64";
+						reg = <0x50>;
+					};
+					eeprom@51 {
+						compatible = "at24,24c256";
+						reg = <0x51>;
+					};
+					eeprom@53 {
+						compatible = "at24,24c256";
+						reg = <0x53>;
+					};
+					eeprom@57 {
+						compatible = "at24,24c256";
+						reg = <0x57>;
+					};
+					rtc@68 {
+						compatible = "dallas,ds3232";
+						reg = <0x68>;
+					};
+				};
 			};
 		};
 
diff --git a/arch/powerpc/boot/dts/c293pcie.dts b/arch/powerpc/boot/dts/c293pcie.dts
index 1238bda..6681cc2 100644
--- a/arch/powerpc/boot/dts/c293pcie.dts
+++ b/arch/powerpc/boot/dts/c293pcie.dts
@@ -45,6 +45,7 @@
 	ifc: ifc@fffe1e000 {
 		reg = <0xf 0xffe1e000 0 0x2000>;
 		ranges = <0x0 0x0 0xf 0xec000000 0x04000000
+			  0x1 0x0 0xf 0xff800000 0x00010000
 			  0x2 0x0 0xf 0xffdf0000 0x00010000>;
 
 	};
diff --git a/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi b/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi
index 7b4426e..c6e451a 100644
--- a/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi
@@ -34,6 +34,8 @@
 
 /dts-v1/;
 
+/include/ "e6500_power_isa.dtsi"
+
 / {
 	compatible = "fsl,B4420";
 	#address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi b/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi
index e5cf6c8..9813975 100644
--- a/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi
@@ -41,7 +41,7 @@
 
 &rio {
 	compatible = "fsl,srio";
-	interrupts = <16 2 1 11>;
+	interrupts = <16 2 1 20>;
 	#address-cells = <2>;
 	#size-cells = <2>;
 	fsl,iommu-parent = <&pamu0>;
diff --git a/arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi b/arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi
index 5263fa4..9bc26b1 100644
--- a/arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi
@@ -34,6 +34,8 @@
 
 /dts-v1/;
 
+/include/ "e6500_power_isa.dtsi"
+
 / {
 	compatible = "fsl,B4860";
 	#address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi b/arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi
index 5180d9d..0c0efa9 100644
--- a/arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi
@@ -130,7 +130,7 @@
 
 /include/ "pq3-esdhc-0.dtsi"
 	sdhc@2e000 {
-		fsl,sdhci-auto-cmd12;
+		sdhci,auto-cmd12;
 		interrupts = <41 0x2 0 0>;
 	};
 
diff --git a/arch/powerpc/boot/dts/fsl/bsc9131si-pre.dtsi b/arch/powerpc/boot/dts/fsl/bsc9131si-pre.dtsi
index 743e4ae..f6ec4a6 100644
--- a/arch/powerpc/boot/dts/fsl/bsc9131si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/bsc9131si-pre.dtsi
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
 	compatible = "fsl,BSC9131";
 	#address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/t4240emu.dts b/arch/powerpc/boot/dts/t4240emu.dts
new file mode 100644
index 0000000..ee24ab3
--- /dev/null
+++ b/arch/powerpc/boot/dts/t4240emu.dts
@@ -0,0 +1,268 @@
+/*
+ * T4240 emulator Device Tree Source
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its 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") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "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 Freescale Semiconductor 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.
+ */
+
+/dts-v1/;
+
+/include/ "fsl/e6500_power_isa.dtsi"
+/ {
+	compatible = "fsl,T4240";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	aliases {
+		ccsr = &soc;
+
+		serial0 = &serial0;
+		serial1 = &serial1;
+		serial2 = &serial2;
+		serial3 = &serial3;
+		dma0 = &dma0;
+		dma1 = &dma1;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: PowerPC,e6500@0 {
+			device_type = "cpu";
+			reg = <0 1>;
+			next-level-cache = <&L2_1>;
+		};
+		cpu1: PowerPC,e6500@2 {
+			device_type = "cpu";
+			reg = <2 3>;
+			next-level-cache = <&L2_1>;
+		};
+		cpu2: PowerPC,e6500@4 {
+			device_type = "cpu";
+			reg = <4 5>;
+			next-level-cache = <&L2_1>;
+		};
+		cpu3: PowerPC,e6500@6 {
+			device_type = "cpu";
+			reg = <6 7>;
+			next-level-cache = <&L2_1>;
+		};
+
+		cpu4: PowerPC,e6500@8 {
+			device_type = "cpu";
+			reg = <8 9>;
+			next-level-cache = <&L2_2>;
+		};
+		cpu5: PowerPC,e6500@10 {
+			device_type = "cpu";
+			reg = <10 11>;
+			next-level-cache = <&L2_2>;
+		};
+		cpu6: PowerPC,e6500@12 {
+			device_type = "cpu";
+			reg = <12 13>;
+			next-level-cache = <&L2_2>;
+		};
+		cpu7: PowerPC,e6500@14 {
+			device_type = "cpu";
+			reg = <14 15>;
+			next-level-cache = <&L2_2>;
+		};
+
+		cpu8: PowerPC,e6500@16 {
+			device_type = "cpu";
+			reg = <16 17>;
+			next-level-cache = <&L2_3>;
+		};
+		cpu9: PowerPC,e6500@18 {
+			device_type = "cpu";
+			reg = <18 19>;
+			next-level-cache = <&L2_3>;
+		};
+		cpu10: PowerPC,e6500@20 {
+			device_type = "cpu";
+			reg = <20 21>;
+			next-level-cache = <&L2_3>;
+		};
+		cpu11: PowerPC,e6500@22 {
+			device_type = "cpu";
+			reg = <22 23>;
+			next-level-cache = <&L2_3>;
+		};
+	};
+};
+
+/ {
+	model = "fsl,T4240QDS";
+	compatible = "fsl,T4240EMU", "fsl,T4240QDS";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	ifc: localbus@ffe124000 {
+		reg = <0xf 0xfe124000 0 0x2000>;
+		ranges = <0 0 0xf 0xe8000000 0x08000000
+			  2 0 0xf 0xff800000 0x00010000
+			  3 0 0xf 0xffdf0000 0x00008000>;
+
+		nor@0,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "cfi-flash";
+			reg = <0x0 0x0 0x8000000>;
+
+			bank-width = <2>;
+			device-width = <1>;
+		};
+
+	};
+
+	memory {
+		device_type = "memory";
+	};
+
+	soc: soc@ffe000000 {
+		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+		reg = <0xf 0xfe000000 0 0x00001000>;
+
+	};
+};
+
+&ifc {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	compatible = "fsl,ifc", "simple-bus";
+	interrupts = <25 2 0 0>;
+};
+
+&soc {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	device_type = "soc";
+	compatible = "simple-bus";
+
+	soc-sram-error {
+		compatible = "fsl,soc-sram-error";
+		interrupts = <16 2 1 29>;
+	};
+
+	corenet-law@0 {
+		compatible = "fsl,corenet-law";
+		reg = <0x0 0x1000>;
+		fsl,num-laws = <32>;
+	};
+
+	ddr1: memory-controller@8000 {
+		compatible = "fsl,qoriq-memory-controller-v4.7",
+				"fsl,qoriq-memory-controller";
+		reg = <0x8000 0x1000>;
+		interrupts = <16 2 1 23>;
+	};
+
+	ddr2: memory-controller@9000 {
+		compatible = "fsl,qoriq-memory-controller-v4.7",
+				"fsl,qoriq-memory-controller";
+		reg = <0x9000 0x1000>;
+		interrupts = <16 2 1 22>;
+	};
+
+	ddr3: memory-controller@a000 {
+		compatible = "fsl,qoriq-memory-controller-v4.7",
+				"fsl,qoriq-memory-controller";
+		reg = <0xa000 0x1000>;
+		interrupts = <16 2 1 21>;
+	};
+
+	cpc: l3-cache-controller@10000 {
+		compatible = "fsl,t4240-l3-cache-controller", "cache";
+		reg = <0x10000 0x1000
+		       0x11000 0x1000
+		       0x12000 0x1000>;
+		interrupts = <16 2 1 27
+			      16 2 1 26
+			      16 2 1 25>;
+	};
+
+	corenet-cf@18000 {
+		compatible = "fsl,corenet-cf";
+		reg = <0x18000 0x1000>;
+		interrupts = <16 2 1 31>;
+		fsl,ccf-num-csdids = <32>;
+		fsl,ccf-num-snoopids = <32>;
+	};
+
+	iommu@20000 {
+		compatible = "fsl,pamu-v1.0", "fsl,pamu";
+		reg = <0x20000 0x6000>;
+		interrupts = <
+			24 2 0 0
+			16 2 1 30>;
+	};
+
+/include/ "fsl/qoriq-mpic.dtsi"
+
+	guts: global-utilities@e0000 {
+		compatible = "fsl,t4240-device-config", "fsl,qoriq-device-config-2.0";
+		reg = <0xe0000 0xe00>;
+		fsl,has-rstcr;
+		fsl,liodn-bits = <12>;
+	};
+
+	clockgen: global-utilities@e1000 {
+		compatible = "fsl,t4240-clockgen", "fsl,qoriq-clockgen-2.0";
+		reg = <0xe1000 0x1000>;
+	};
+
+/include/ "fsl/qoriq-dma-0.dtsi"
+/include/ "fsl/qoriq-dma-1.dtsi"
+
+/include/ "fsl/qoriq-i2c-0.dtsi"
+/include/ "fsl/qoriq-i2c-1.dtsi"
+/include/ "fsl/qoriq-duart-0.dtsi"
+/include/ "fsl/qoriq-duart-1.dtsi"
+
+	L2_1: l2-cache-controller@c20000 {
+		compatible = "fsl,t4240-l2-cache-controller";
+		reg = <0xc20000 0x40000>;
+		next-level-cache = <&cpc>;
+	};
+	L2_2: l2-cache-controller@c60000 {
+		compatible = "fsl,t4240-l2-cache-controller";
+		reg = <0xc60000 0x40000>;
+		next-level-cache = <&cpc>;
+	};
+	L2_3: l2-cache-controller@ca0000 {
+		compatible = "fsl,t4240-l2-cache-controller";
+		reg = <0xca0000 0x40000>;
+		next-level-cache = <&cpc>;
+	};
+};
diff --git a/arch/powerpc/boot/dts/t4240qds.dts b/arch/powerpc/boot/dts/t4240qds.dts
index 0555976..63e81b0 100644
--- a/arch/powerpc/boot/dts/t4240qds.dts
+++ b/arch/powerpc/boot/dts/t4240qds.dts
@@ -118,35 +118,52 @@
 		};
 
 		i2c@118000 {
-			eeprom@51 {
-				compatible = "at24,24c256";
-				reg = <0x51>;
+			mux@77 {
+				compatible = "nxp,pca9547";
+				reg = <0x77>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				i2c@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					eeprom@51 {
+						compatible = "at24,24c256";
+						reg = <0x51>;
+					};
+					eeprom@52 {
+						compatible = "at24,24c256";
+						reg = <0x52>;
+					};
+					eeprom@53 {
+						compatible = "at24,24c256";
+						reg = <0x53>;
+					};
+					eeprom@54 {
+						compatible = "at24,24c256";
+						reg = <0x54>;
+					};
+					eeprom@55 {
+						compatible = "at24,24c256";
+						reg = <0x55>;
+					};
+					eeprom@56 {
+						compatible = "at24,24c256";
+						reg = <0x56>;
+					};
+					rtc@68 {
+						compatible = "dallas,ds3232";
+						reg = <0x68>;
+						interrupts = <0x1 0x1 0 0>;
+					};
+				};
 			};
-			eeprom@52 {
-				compatible = "at24,24c256";
-				reg = <0x52>;
-			};
-			eeprom@53 {
-				compatible = "at24,24c256";
-				reg = <0x53>;
-			};
-			eeprom@54 {
-				compatible = "at24,24c256";
-				reg = <0x54>;
-			};
-			eeprom@55 {
-				compatible = "at24,24c256";
-				reg = <0x55>;
-			};
-			eeprom@56 {
-				compatible = "at24,24c256";
-				reg = <0x56>;
-			};
-			rtc@68 {
-				compatible = "dallas,ds3232";
-				reg = <0x68>;
-				interrupts = <0x1 0x1 0 0>;
-			};
+		};
+
+		sdhc@114000 {
+			voltage-ranges = <1800 1800 3300 3300>;
 		};
 	};
 
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index cd7af84..2e1af74 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -147,21 +147,29 @@
 make_space=y
 
 case "$platform" in
+of)
+    platformo="$object/of.o $object/epapr.o"
+    make_space=n
+    ;;
 pseries)
     platformo="$object/of.o $object/epapr.o"
     link_address='0x4000000'
+    make_space=n
     ;;
 maple)
     platformo="$object/of.o $object/epapr.o"
     link_address='0x400000'
+    make_space=n
     ;;
 pmac|chrp)
     platformo="$object/of.o $object/epapr.o"
+    make_space=n
     ;;
 coff)
     platformo="$object/crt0.o $object/of.o $object/epapr.o"
     lds=$object/zImage.coff.lds
     link_address='0x500000'
+    make_space=n
     pie=
     ;;
 miboot|uboot*)
diff --git a/arch/powerpc/configs/corenet32_smp_defconfig b/arch/powerpc/configs/corenet32_smp_defconfig
index 3dfab4c..bbd794d 100644
--- a/arch/powerpc/configs/corenet32_smp_defconfig
+++ b/arch/powerpc/configs/corenet32_smp_defconfig
@@ -23,11 +23,7 @@
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_MAC_PARTITION=y
-CONFIG_P2041_RDB=y
-CONFIG_P3041_DS=y
-CONFIG_P4080_DS=y
-CONFIG_P5020_DS=y
-CONFIG_P5040_DS=y
+CONFIG_CORENET_GENERIC=y
 CONFIG_HIGHMEM=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_MISC=m
@@ -104,6 +100,7 @@
 CONFIG_E1000=y
 CONFIG_E1000E=y
 CONFIG_VITESSE_PHY=y
+CONFIG_AT803X_PHY=y
 CONFIG_FIXED_PHY=y
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_KEYBOARD is not set
diff --git a/arch/powerpc/configs/corenet64_smp_defconfig b/arch/powerpc/configs/corenet64_smp_defconfig
index fa94fb3..63508dd 100644
--- a/arch/powerpc/configs/corenet64_smp_defconfig
+++ b/arch/powerpc/configs/corenet64_smp_defconfig
@@ -21,10 +21,7 @@
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_MAC_PARTITION=y
-CONFIG_B4_QDS=y
-CONFIG_P5020_DS=y
-CONFIG_P5040_DS=y
-CONFIG_T4240_QDS=y
+CONFIG_CORENET_GENERIC=y
 # CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_MATH_EMULATION=y
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig
index dc098d9..d2e0fab 100644
--- a/arch/powerpc/configs/mpc85xx_defconfig
+++ b/arch/powerpc/configs/mpc85xx_defconfig
@@ -138,6 +138,7 @@
 CONFIG_DAVICOM_PHY=y
 CONFIG_CICADA_PHY=y
 CONFIG_VITESSE_PHY=y
+CONFIG_AT803X_PHY=y
 CONFIG_FIXED_PHY=y
 CONFIG_INPUT_FF_MEMLESS=m
 # CONFIG_INPUT_MOUSEDEV is not set
diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig
index 5bca601..4cb7b59 100644
--- a/arch/powerpc/configs/mpc85xx_smp_defconfig
+++ b/arch/powerpc/configs/mpc85xx_smp_defconfig
@@ -138,6 +138,7 @@
 CONFIG_DAVICOM_PHY=y
 CONFIG_CICADA_PHY=y
 CONFIG_VITESSE_PHY=y
+CONFIG_AT803X_PHY=y
 CONFIG_FIXED_PHY=y
 CONFIG_INPUT_FF_MEMLESS=m
 # CONFIG_INPUT_MOUSEDEV is not set
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 0e8cfd0..581a3bc 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -2,7 +2,6 @@
 CONFIG_ALTIVEC=y
 CONFIG_VSX=y
 CONFIG_SMP=y
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_IRQ_DOMAIN_DEBUG=y
@@ -25,7 +24,6 @@
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_PARTITION_ADVANCED=y
-CONFIG_EFI_PARTITION=y
 CONFIG_PPC_SPLPAR=y
 CONFIG_SCANLOG=m
 CONFIG_PPC_SMLPAR=y
@@ -50,12 +48,10 @@
 CONFIG_HZ_100=y
 CONFIG_BINFMT_MISC=m
 CONFIG_PPC_TRANSACTIONAL_MEM=y
-CONFIG_HOTPLUG_CPU=y
 CONFIG_KEXEC=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_SCHED_SMT=y
-CONFIG_PPC_DENORMALISATION=y
 CONFIG_PCCARD=y
 CONFIG_ELECTRA_CF=y
 CONFIG_HOTPLUG_PCI=y
@@ -89,7 +85,6 @@
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_CT_NETLINK=m
-CONFIG_NETFILTER_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_DSCP=m
@@ -131,7 +126,6 @@
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_U32=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -157,6 +151,7 @@
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_VIRTIO_BLK=m
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_GENERIC=y
@@ -185,6 +180,10 @@
 CONFIG_SCSI_QLA_FC=m
 CONFIG_SCSI_QLA_ISCSI=m
 CONFIG_SCSI_LPFC=m
+CONFIG_SCSI_VIRTIO=m
+CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DH_ALUA=m
 CONFIG_ATA=y
 CONFIG_SATA_SIL24=y
 CONFIG_SATA_SVW=y
@@ -203,6 +202,9 @@
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_QL=m
+CONFIG_DM_MULTIPATH_ST=m
+CONFIG_DM_UEVENT=y
 CONFIG_ADB_PMU=y
 CONFIG_PMAC_SMU=y
 CONFIG_THERM_PM72=y
@@ -216,6 +218,8 @@
 CONFIG_NETCONSOLE=y
 CONFIG_NETPOLL_TRAP=y
 CONFIG_TUN=m
+CONFIG_VIRTIO_NET=m
+CONFIG_VHOST_NET=m
 CONFIG_VORTEX=y
 CONFIG_ACENIC=m
 CONFIG_ACENIC_OMIT_TIGON_I=y
@@ -262,6 +266,7 @@
 CONFIG_HVC_RTAS=y
 CONFIG_HVC_BEAT=y
 CONFIG_HVCS=m
+CONFIG_VIRTIO_CONSOLE=m
 CONFIG_IBM_BSR=m
 CONFIG_RAW_DRIVER=y
 CONFIG_I2C_CHARDEV=y
@@ -301,7 +306,6 @@
 CONFIG_HID_PANTHERLORD=y
 CONFIG_HID_PETALYNX=y
 CONFIG_HID_SAMSUNG=y
-CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
 CONFIG_USB_HIDDEV=y
 CONFIG_USB=y
@@ -328,6 +332,8 @@
 CONFIG_EDAC_PASEMI=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
+CONFIG_VIRTIO_PCI=m
+CONFIG_VIRTIO_BALLOON=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
@@ -386,21 +392,19 @@
 CONFIG_CRC_T10DIF=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_LOCKUP_DETECTOR=y
 CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_LATENCYTOP=y
 CONFIG_SCHED_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
-CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_CODE_PATCHING_SELFTEST=y
 CONFIG_FTR_FIXUP_SELFTEST=y
 CONFIG_MSI_BITMAP_SELFTEST=y
 CONFIG_XMON=y
 CONFIG_BOOTX_TEXT=y
 CONFIG_PPC_EARLY_DEBUG=y
-CONFIG_PPC_EARLY_DEBUG_BOOTX=y
-CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_HMAC=y
@@ -422,4 +426,3 @@
 CONFIG_VIRTUALIZATION=y
 CONFIG_KVM_BOOK3S_64=m
 CONFIG_KVM_BOOK3S_64_HV=y
-CONFIG_VHOST_NET=m
diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig
index 0085dc4..f627fda 100644
--- a/arch/powerpc/configs/ppc64e_defconfig
+++ b/arch/powerpc/configs/ppc64e_defconfig
@@ -1,7 +1,6 @@
 CONFIG_PPC64=y
 CONFIG_PPC_BOOK3E_64=y
 CONFIG_SMP=y
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_NO_HZ=y
@@ -23,7 +22,7 @@
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_MAC_PARTITION=y
 CONFIG_EFI_PARTITION=y
-CONFIG_P5020_DS=y
+CONFIG_CORENET_GENERIC=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -61,7 +60,6 @@
 CONFIG_NF_CONNTRACK_SIP=m
 CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NF_CT_NETLINK=m
-CONFIG_NETFILTER_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_DSCP=m
@@ -103,7 +101,6 @@
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_U32=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -193,7 +190,6 @@
 CONFIG_INPUT_EVDEV=m
 CONFIG_INPUT_MISC=y
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_VT_HW_CONSOLE_BINDING=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
@@ -230,7 +226,6 @@
 CONFIG_HID_PANTHERLORD=y
 CONFIG_HID_PETALYNX=y
 CONFIG_HID_SAMSUNG=y
-CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
 CONFIG_HID_GREENASIA=y
 CONFIG_HID_SMARTJOYPLUS=y
@@ -302,19 +297,18 @@
 CONFIG_CRC_T10DIF=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_LATENCYTOP=y
 CONFIG_IRQSOFF_TRACER=y
 CONFIG_SCHED_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
-CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_CODE_PATCHING_SELFTEST=y
 CONFIG_FTR_FIXUP_SELFTEST=y
 CONFIG_MSI_BITMAP_SELFTEST=y
 CONFIG_XMON=y
-CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig
index 20ebfaf..c2353bf 100644
--- a/arch/powerpc/configs/ppc6xx_defconfig
+++ b/arch/powerpc/configs/ppc6xx_defconfig
@@ -71,7 +71,7 @@
 CONFIG_QE_GPIO=y
 CONFIG_PPC_BESTCOMM=y
 CONFIG_GPIO_MPC8XXX=y
-CONFIG_MCU_MPC8349EMITX=m
+CONFIG_MCU_MPC8349EMITX=y
 CONFIG_HIGHMEM=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 1d4b976..e9a8b4e 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -3,7 +3,6 @@
 CONFIG_VSX=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2048
-CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_AUDIT=y
@@ -33,7 +32,6 @@
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_PARTITION_ADVANCED=y
-CONFIG_EFI_PARTITION=y
 CONFIG_PPC_SPLPAR=y
 CONFIG_SCANLOG=m
 CONFIG_PPC_SMLPAR=y
@@ -44,7 +42,6 @@
 CONFIG_HZ_100=y
 CONFIG_BINFMT_MISC=m
 CONFIG_PPC_TRANSACTIONAL_MEM=y
-CONFIG_HOTPLUG_CPU=y
 CONFIG_KEXEC=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_MEMORY_HOTPLUG=y
@@ -52,7 +49,6 @@
 CONFIG_PPC_64K_PAGES=y
 CONFIG_PPC_SUBPAGE_PROT=y
 CONFIG_SCHED_SMT=y
-CONFIG_PPC_DENORMALISATION=y
 CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_RPA=m
 CONFIG_HOTPLUG_PCI_RPA_DLPAR=m
@@ -113,7 +109,6 @@
 CONFIG_NETFILTER_XT_MATCH_TIME=m
 CONFIG_NETFILTER_XT_MATCH_U32=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_ECN=m
@@ -132,6 +127,7 @@
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_VIRTIO_BLK=m
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_GENERIC=y
@@ -157,6 +153,10 @@
 CONFIG_SCSI_QLA_FC=m
 CONFIG_SCSI_QLA_ISCSI=m
 CONFIG_SCSI_LPFC=m
+CONFIG_SCSI_VIRTIO=m
+CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DH_ALUA=m
 CONFIG_ATA=y
 # CONFIG_ATA_SFF is not set
 CONFIG_MD=y
@@ -174,11 +174,16 @@
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
 CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_QL=m
+CONFIG_DM_MULTIPATH_ST=m
+CONFIG_DM_UEVENT=y
 CONFIG_BONDING=m
 CONFIG_DUMMY=m
 CONFIG_NETCONSOLE=y
 CONFIG_NETPOLL_TRAP=y
 CONFIG_TUN=m
+CONFIG_VIRTIO_NET=m
+CONFIG_VHOST_NET=m
 CONFIG_VORTEX=y
 CONFIG_ACENIC=m
 CONFIG_ACENIC_OMIT_TIGON_I=y
@@ -216,6 +221,7 @@
 CONFIG_HVC_CONSOLE=y
 CONFIG_HVC_RTAS=y
 CONFIG_HVCS=m
+CONFIG_VIRTIO_CONSOLE=m
 CONFIG_IBM_BSR=m
 CONFIG_GEN_RTC=y
 CONFIG_RAW_DRIVER=y
@@ -237,7 +243,6 @@
 CONFIG_HID_PANTHERLORD=y
 CONFIG_HID_PETALYNX=y
 CONFIG_HID_SAMSUNG=y
-CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
 CONFIG_USB_HIDDEV=y
 CONFIG_USB=y
@@ -258,6 +263,8 @@
 CONFIG_INFINIBAND_IPOIB_CM=y
 CONFIG_INFINIBAND_SRP=m
 CONFIG_INFINIBAND_ISER=m
+CONFIG_VIRTIO_PCI=m
+CONFIG_VIRTIO_BALLOON=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
@@ -314,18 +321,17 @@
 CONFIG_CRC_T10DIF=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOCKUP_DETECTOR=y
 CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_LOCKUP_DETECTOR=y
 CONFIG_LATENCYTOP=y
 CONFIG_SCHED_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
-CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_CODE_PATCHING_SELFTEST=y
 CONFIG_FTR_FIXUP_SELFTEST=y
 CONFIG_MSI_BITMAP_SELFTEST=y
 CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
-CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_HMAC=y
@@ -347,4 +353,3 @@
 CONFIG_VIRTUALIZATION=y
 CONFIG_KVM_BOOK3S_64=m
 CONFIG_KVM_BOOK3S_64_HV=y
-CONFIG_VHOST_NET=m
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 704e6f1..d8f9d2f 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -2,4 +2,5 @@
 generic-y += clkdev.h
 generic-y += rwsem.h
 generic-y += trace_clock.h
+generic-y += preempt.h
 generic-y += vtime.h
\ No newline at end of file
diff --git a/arch/powerpc/include/asm/archrandom.h b/arch/powerpc/include/asm/archrandom.h
new file mode 100644
index 0000000..d853d16
--- /dev/null
+++ b/arch/powerpc/include/asm/archrandom.h
@@ -0,0 +1,32 @@
+#ifndef _ASM_POWERPC_ARCHRANDOM_H
+#define _ASM_POWERPC_ARCHRANDOM_H
+
+#ifdef CONFIG_ARCH_RANDOM
+
+#include <asm/machdep.h>
+
+static inline int arch_get_random_long(unsigned long *v)
+{
+	if (ppc_md.get_random_long)
+		return ppc_md.get_random_long(v);
+
+	return 0;
+}
+
+static inline int arch_get_random_int(unsigned int *v)
+{
+	unsigned long val;
+	int rc;
+
+	rc = arch_get_random_long(&val);
+	if (rc)
+		*v = val;
+
+	return rc;
+}
+
+int powernv_get_random_long(unsigned long *v);
+
+#endif /* CONFIG_ARCH_RANDOM */
+
+#endif /* _ASM_POWERPC_ARCHRANDOM_H */
diff --git a/arch/powerpc/include/asm/checksum.h b/arch/powerpc/include/asm/checksum.h
index ce0c284..8251a3b 100644
--- a/arch/powerpc/include/asm/checksum.h
+++ b/arch/powerpc/include/asm/checksum.h
@@ -14,6 +14,9 @@
  * which always checksum on 4 octet boundaries.  ihl is the number
  * of 32-bit words and is always >= 5.
  */
+#ifdef CONFIG_GENERIC_CSUM
+#include <asm-generic/checksum.h>
+#else
 extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl);
 
 /*
@@ -123,5 +126,7 @@
 	return sum;
 #endif
 }
+
+#endif
 #endif /* __KERNEL__ */
 #endif
diff --git a/arch/powerpc/include/asm/emulated_ops.h b/arch/powerpc/include/asm/emulated_ops.h
index 5a8b82a..4358e30 100644
--- a/arch/powerpc/include/asm/emulated_ops.h
+++ b/arch/powerpc/include/asm/emulated_ops.h
@@ -43,6 +43,7 @@
 	struct ppc_emulated_entry popcntb;
 	struct ppc_emulated_entry spe;
 	struct ppc_emulated_entry string;
+	struct ppc_emulated_entry sync;
 	struct ppc_emulated_entry unaligned;
 #ifdef CONFIG_MATH_EMULATION
 	struct ppc_emulated_entry math;
diff --git a/arch/powerpc/include/asm/hvsi.h b/arch/powerpc/include/asm/hvsi.h
index d3f64f3..d4a5315 100644
--- a/arch/powerpc/include/asm/hvsi.h
+++ b/arch/powerpc/include/asm/hvsi.h
@@ -25,7 +25,7 @@
 struct hvsi_header {
 	uint8_t  type;
 	uint8_t  len;
-	uint16_t seqno;
+	__be16 seqno;
 } __attribute__((packed));
 
 struct hvsi_data {
@@ -35,24 +35,24 @@
 
 struct hvsi_control {
 	struct hvsi_header hdr;
-	uint16_t verb;
+	__be16 verb;
 	/* optional depending on verb: */
-	uint32_t word;
-	uint32_t mask;
+	__be32 word;
+	__be32 mask;
 } __attribute__((packed));
 
 struct hvsi_query {
 	struct hvsi_header hdr;
-	uint16_t verb;
+	__be16 verb;
 } __attribute__((packed));
 
 struct hvsi_query_response {
 	struct hvsi_header hdr;
-	uint16_t verb;
-	uint16_t query_seqno;
+	__be16 verb;
+	__be16 query_seqno;
 	union {
 		uint8_t  version;
-		uint32_t mctrl_word;
+		__be32 mctrl_word;
 	} u;
 } __attribute__((packed));
 
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
index 5a64757..575fbf8 100644
--- a/arch/powerpc/include/asm/io.h
+++ b/arch/powerpc/include/asm/io.h
@@ -21,7 +21,7 @@
 /*
  * has legacy ISA devices ?
  */
-#define arch_has_dev_port()	(isa_bridge_pcidev != NULL)
+#define arch_has_dev_port()	(isa_bridge_pcidev != NULL || isa_io_special)
 #endif
 
 #include <linux/device.h>
@@ -113,7 +113,7 @@
 
 /* gcc 4.0 and older doesn't have 'Z' constraint */
 #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ == 0)
-#define DEF_MMIO_IN_LE(name, size, insn)				\
+#define DEF_MMIO_IN_X(name, size, insn)				\
 static inline u##size name(const volatile u##size __iomem *addr)	\
 {									\
 	u##size ret;							\
@@ -122,7 +122,7 @@
 	return ret;							\
 }
 
-#define DEF_MMIO_OUT_LE(name, size, insn) 				\
+#define DEF_MMIO_OUT_X(name, size, insn)				\
 static inline void name(volatile u##size __iomem *addr, u##size val)	\
 {									\
 	__asm__ __volatile__("sync;"#insn" %1,0,%2"			\
@@ -130,7 +130,7 @@
 	IO_SET_SYNC_FLAG();						\
 }
 #else /* newer gcc */
-#define DEF_MMIO_IN_LE(name, size, insn)				\
+#define DEF_MMIO_IN_X(name, size, insn)				\
 static inline u##size name(const volatile u##size __iomem *addr)	\
 {									\
 	u##size ret;							\
@@ -139,7 +139,7 @@
 	return ret;							\
 }
 
-#define DEF_MMIO_OUT_LE(name, size, insn) 				\
+#define DEF_MMIO_OUT_X(name, size, insn)				\
 static inline void name(volatile u##size __iomem *addr, u##size val)	\
 {									\
 	__asm__ __volatile__("sync;"#insn" %1,%y0"			\
@@ -148,7 +148,7 @@
 }
 #endif
 
-#define DEF_MMIO_IN_BE(name, size, insn)				\
+#define DEF_MMIO_IN_D(name, size, insn)				\
 static inline u##size name(const volatile u##size __iomem *addr)	\
 {									\
 	u##size ret;							\
@@ -157,7 +157,7 @@
 	return ret;							\
 }
 
-#define DEF_MMIO_OUT_BE(name, size, insn)				\
+#define DEF_MMIO_OUT_D(name, size, insn)				\
 static inline void name(volatile u##size __iomem *addr, u##size val)	\
 {									\
 	__asm__ __volatile__("sync;"#insn"%U0%X0 %1,%0"			\
@@ -165,22 +165,37 @@
 	IO_SET_SYNC_FLAG();						\
 }
 
+DEF_MMIO_IN_D(in_8,     8, lbz);
+DEF_MMIO_OUT_D(out_8,   8, stb);
 
-DEF_MMIO_IN_BE(in_8,     8, lbz);
-DEF_MMIO_IN_BE(in_be16, 16, lhz);
-DEF_MMIO_IN_BE(in_be32, 32, lwz);
-DEF_MMIO_IN_LE(in_le16, 16, lhbrx);
-DEF_MMIO_IN_LE(in_le32, 32, lwbrx);
+#ifdef __BIG_ENDIAN__
+DEF_MMIO_IN_D(in_be16, 16, lhz);
+DEF_MMIO_IN_D(in_be32, 32, lwz);
+DEF_MMIO_IN_X(in_le16, 16, lhbrx);
+DEF_MMIO_IN_X(in_le32, 32, lwbrx);
 
-DEF_MMIO_OUT_BE(out_8,     8, stb);
-DEF_MMIO_OUT_BE(out_be16, 16, sth);
-DEF_MMIO_OUT_BE(out_be32, 32, stw);
-DEF_MMIO_OUT_LE(out_le16, 16, sthbrx);
-DEF_MMIO_OUT_LE(out_le32, 32, stwbrx);
+DEF_MMIO_OUT_D(out_be16, 16, sth);
+DEF_MMIO_OUT_D(out_be32, 32, stw);
+DEF_MMIO_OUT_X(out_le16, 16, sthbrx);
+DEF_MMIO_OUT_X(out_le32, 32, stwbrx);
+#else
+DEF_MMIO_IN_X(in_be16, 16, lhbrx);
+DEF_MMIO_IN_X(in_be32, 32, lwbrx);
+DEF_MMIO_IN_D(in_le16, 16, lhz);
+DEF_MMIO_IN_D(in_le32, 32, lwz);
+
+DEF_MMIO_OUT_X(out_be16, 16, sthbrx);
+DEF_MMIO_OUT_X(out_be32, 32, stwbrx);
+DEF_MMIO_OUT_D(out_le16, 16, sth);
+DEF_MMIO_OUT_D(out_le32, 32, stw);
+
+#endif /* __BIG_ENDIAN */
 
 #ifdef __powerpc64__
-DEF_MMIO_OUT_BE(out_be64, 64, std);
-DEF_MMIO_IN_BE(in_be64, 64, ld);
+
+#ifdef __BIG_ENDIAN__
+DEF_MMIO_OUT_D(out_be64, 64, std);
+DEF_MMIO_IN_D(in_be64, 64, ld);
 
 /* There is no asm instructions for 64 bits reverse loads and stores */
 static inline u64 in_le64(const volatile u64 __iomem *addr)
@@ -192,6 +207,22 @@
 {
 	out_be64(addr, swab64(val));
 }
+#else
+DEF_MMIO_OUT_D(out_le64, 64, std);
+DEF_MMIO_IN_D(in_le64, 64, ld);
+
+/* There is no asm instructions for 64 bits reverse loads and stores */
+static inline u64 in_be64(const volatile u64 __iomem *addr)
+{
+	return swab64(in_le64(addr));
+}
+
+static inline void out_be64(volatile u64 __iomem *addr, u64 val)
+{
+	out_le64(addr, swab64(val));
+}
+
+#endif
 #endif /* __powerpc64__ */
 
 /*
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
index ae098c4..f016bb6 100644
--- a/arch/powerpc/include/asm/jump_label.h
+++ b/arch/powerpc/include/asm/jump_label.h
@@ -19,7 +19,7 @@
 
 static __always_inline bool arch_static_branch(struct static_key *key)
 {
-	asm goto("1:\n\t"
+	asm_volatile_goto("1:\n\t"
 		 "nop\n\t"
 		 ".pushsection __jump_table,  \"aw\"\n\t"
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
diff --git a/arch/powerpc/include/asm/lppaca.h b/arch/powerpc/include/asm/lppaca.h
index 4470d1e..844c28d 100644
--- a/arch/powerpc/include/asm/lppaca.h
+++ b/arch/powerpc/include/asm/lppaca.h
@@ -84,8 +84,8 @@
 	 * the processor is yielded (either because of an OS yield or a
 	 * hypervisor preempt).  An even value implies that the processor is
 	 * currently executing.
-	 * NOTE: This value will ALWAYS be zero for dedicated processors and
-	 * will NEVER be zero for shared processors (ie, initialized to a 1).
+	 * NOTE: Even dedicated processor partitions can yield so this
+	 * field cannot be used to determine if we are shared or dedicated.
 	 */
 	volatile __be32 yield_count;
 	volatile __be32 dispersion_count; /* dispatch changed physical cpu */
@@ -106,15 +106,15 @@
 #define lppaca_of(cpu)	(*paca[cpu].lppaca_ptr)
 
 /*
- * Old kernels used a reserved bit in the VPA to determine if it was running
- * in shared processor mode. New kernels look for a non zero yield count
- * but KVM still needs to set the bit to keep the old stuff happy.
+ * We are using a non architected field to determine if a partition is
+ * shared or dedicated. This currently works on both KVM and PHYP, but
+ * we will have to transition to something better.
  */
 #define LPPACA_OLD_SHARED_PROC		2
 
 static inline bool lppaca_shared_proc(struct lppaca *l)
 {
-	return l->yield_count != 0;
+	return !!(l->__old_status & LPPACA_OLD_SHARED_PROC);
 }
 
 /*
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 8b48090..ad3025d 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -78,6 +78,18 @@
 				    long index);
 	void		(*tce_flush)(struct iommu_table *tbl);
 
+	/* _rm versions are for real mode use only */
+	int		(*tce_build_rm)(struct iommu_table *tbl,
+				     long index,
+				     long npages,
+				     unsigned long uaddr,
+				     enum dma_data_direction direction,
+				     struct dma_attrs *attrs);
+	void		(*tce_free_rm)(struct iommu_table *tbl,
+				    long index,
+				    long npages);
+	void		(*tce_flush_rm)(struct iommu_table *tbl);
+
 	void __iomem *	(*ioremap)(phys_addr_t addr, unsigned long size,
 				   unsigned long flags, void *caller);
 	void		(*iounmap)(volatile void __iomem *token);
@@ -263,6 +275,10 @@
 	ssize_t (*cpu_probe)(const char *, size_t);
 	ssize_t (*cpu_release)(const char *, size_t);
 #endif
+
+#ifdef CONFIG_ARCH_RANDOM
+	int (*get_random_long)(unsigned long *v);
+#endif
 };
 
 extern void e500_idle(void);
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index c4cf011..807014d 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -135,8 +135,8 @@
 #ifndef __ASSEMBLY__
 
 struct hash_pte {
-	unsigned long v;
-	unsigned long r;
+	__be64 v;
+	__be64 r;
 };
 
 extern struct hash_pte *htab_address;
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index c5cd728..033c06b 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -129,6 +129,9 @@
 #define OPAL_LPC_READ				67
 #define OPAL_LPC_WRITE				68
 #define OPAL_RETURN_CPU				69
+#define OPAL_FLASH_VALIDATE			76
+#define OPAL_FLASH_MANAGE			77
+#define OPAL_FLASH_UPDATE			78
 
 #ifndef __ASSEMBLY__
 
@@ -460,10 +463,12 @@
 
 enum {
 	OPAL_PHB_ERROR_DATA_TYPE_P7IOC = 1,
+	OPAL_PHB_ERROR_DATA_TYPE_PHB3 = 2
 };
 
 enum {
 	OPAL_P7IOC_NUM_PEST_REGS = 128,
+	OPAL_PHB3_NUM_PEST_REGS = 256
 };
 
 struct OpalIoPhbErrorCommon {
@@ -531,28 +536,94 @@
 	uint64_t pestB[OPAL_P7IOC_NUM_PEST_REGS];
 };
 
+struct OpalIoPhb3ErrorData {
+	struct OpalIoPhbErrorCommon common;
+
+	uint32_t brdgCtl;
+
+	/* PHB3 UTL regs */
+	uint32_t portStatusReg;
+	uint32_t rootCmplxStatus;
+	uint32_t busAgentStatus;
+
+	/* PHB3 cfg regs */
+	uint32_t deviceStatus;
+	uint32_t slotStatus;
+	uint32_t linkStatus;
+	uint32_t devCmdStatus;
+	uint32_t devSecStatus;
+
+	/* cfg AER regs */
+	uint32_t rootErrorStatus;
+	uint32_t uncorrErrorStatus;
+	uint32_t corrErrorStatus;
+	uint32_t tlpHdr1;
+	uint32_t tlpHdr2;
+	uint32_t tlpHdr3;
+	uint32_t tlpHdr4;
+	uint32_t sourceId;
+
+	uint32_t rsv3;
+
+	/* Record data about the call to allocate a buffer */
+	uint64_t errorClass;
+	uint64_t correlator;
+
+	uint64_t nFir;			/* 000 */
+	uint64_t nFirMask;		/* 003 */
+	uint64_t nFirWOF;		/* 008 */
+
+	/* PHB3 MMIO Error Regs */
+	uint64_t phbPlssr;		/* 120 */
+	uint64_t phbCsr;		/* 110 */
+	uint64_t lemFir;		/* C00 */
+	uint64_t lemErrorMask;		/* C18 */
+	uint64_t lemWOF;		/* C40 */
+	uint64_t phbErrorStatus;	/* C80 */
+	uint64_t phbFirstErrorStatus;	/* C88 */
+	uint64_t phbErrorLog0;		/* CC0 */
+	uint64_t phbErrorLog1;		/* CC8 */
+	uint64_t mmioErrorStatus;	/* D00 */
+	uint64_t mmioFirstErrorStatus;	/* D08 */
+	uint64_t mmioErrorLog0;		/* D40 */
+	uint64_t mmioErrorLog1;		/* D48 */
+	uint64_t dma0ErrorStatus;	/* D80 */
+	uint64_t dma0FirstErrorStatus;	/* D88 */
+	uint64_t dma0ErrorLog0;		/* DC0 */
+	uint64_t dma0ErrorLog1;		/* DC8 */
+	uint64_t dma1ErrorStatus;	/* E00 */
+	uint64_t dma1FirstErrorStatus;	/* E08 */
+	uint64_t dma1ErrorLog0;		/* E40 */
+	uint64_t dma1ErrorLog1;		/* E48 */
+	uint64_t pestA[OPAL_PHB3_NUM_PEST_REGS];
+	uint64_t pestB[OPAL_PHB3_NUM_PEST_REGS];
+};
+
 typedef struct oppanel_line {
 	const char * 	line;
 	uint64_t 	line_len;
 } oppanel_line_t;
 
+/* /sys/firmware/opal */
+extern struct kobject *opal_kobj;
+
 /* API functions */
-int64_t opal_console_write(int64_t term_number, int64_t *length,
+int64_t opal_console_write(int64_t term_number, __be64 *length,
 			   const uint8_t *buffer);
-int64_t opal_console_read(int64_t term_number, int64_t *length,
+int64_t opal_console_read(int64_t term_number, __be64 *length,
 			  uint8_t *buffer);
 int64_t opal_console_write_buffer_space(int64_t term_number,
-					int64_t *length);
-int64_t opal_rtc_read(uint32_t *year_month_day,
-		      uint64_t *hour_minute_second_millisecond);
+					__be64 *length);
+int64_t opal_rtc_read(__be32 *year_month_day,
+		      __be64 *hour_minute_second_millisecond);
 int64_t opal_rtc_write(uint32_t year_month_day,
 		       uint64_t hour_minute_second_millisecond);
 int64_t opal_cec_power_down(uint64_t request);
 int64_t opal_cec_reboot(void);
 int64_t opal_read_nvram(uint64_t buffer, uint64_t size, uint64_t offset);
 int64_t opal_write_nvram(uint64_t buffer, uint64_t size, uint64_t offset);
-int64_t opal_handle_interrupt(uint64_t isn, uint64_t *outstanding_event_mask);
-int64_t opal_poll_events(uint64_t *outstanding_event_mask);
+int64_t opal_handle_interrupt(uint64_t isn, __be64 *outstanding_event_mask);
+int64_t opal_poll_events(__be64 *outstanding_event_mask);
 int64_t opal_pci_set_hub_tce_memory(uint64_t hub_id, uint64_t tce_mem_addr,
 				    uint64_t tce_mem_size);
 int64_t opal_pci_set_phb_tce_memory(uint64_t phb_id, uint64_t tce_mem_addr,
@@ -560,9 +631,9 @@
 int64_t opal_pci_config_read_byte(uint64_t phb_id, uint64_t bus_dev_func,
 				  uint64_t offset, uint8_t *data);
 int64_t opal_pci_config_read_half_word(uint64_t phb_id, uint64_t bus_dev_func,
-				       uint64_t offset, uint16_t *data);
+				       uint64_t offset, __be16 *data);
 int64_t opal_pci_config_read_word(uint64_t phb_id, uint64_t bus_dev_func,
-				  uint64_t offset, uint32_t *data);
+				  uint64_t offset, __be32 *data);
 int64_t opal_pci_config_write_byte(uint64_t phb_id, uint64_t bus_dev_func,
 				   uint64_t offset, uint8_t data);
 int64_t opal_pci_config_write_half_word(uint64_t phb_id, uint64_t bus_dev_func,
@@ -570,14 +641,14 @@
 int64_t opal_pci_config_write_word(uint64_t phb_id, uint64_t bus_dev_func,
 				   uint64_t offset, uint32_t data);
 int64_t opal_set_xive(uint32_t isn, uint16_t server, uint8_t priority);
-int64_t opal_get_xive(uint32_t isn, uint16_t *server, uint8_t *priority);
+int64_t opal_get_xive(uint32_t isn, __be16 *server, uint8_t *priority);
 int64_t opal_register_exception_handler(uint64_t opal_exception,
 					uint64_t handler_address,
 					uint64_t glue_cache_line);
 int64_t opal_pci_eeh_freeze_status(uint64_t phb_id, uint64_t pe_number,
 				   uint8_t *freeze_state,
-				   uint16_t *pci_error_type,
-				   uint64_t *phb_status);
+				   __be16 *pci_error_type,
+				   __be64 *phb_status);
 int64_t opal_pci_eeh_freeze_clear(uint64_t phb_id, uint64_t pe_number,
 				  uint64_t eeh_action_token);
 int64_t opal_pci_shpc(uint64_t phb_id, uint64_t shpc_action, uint8_t *state);
@@ -614,13 +685,13 @@
 int64_t opal_pci_set_xive_pe(uint64_t phb_id, uint32_t pe_number,
 			     uint32_t xive_num);
 int64_t opal_get_xive_source(uint64_t phb_id, uint32_t xive_num,
-			     int32_t *interrupt_source_number);
+			     __be32 *interrupt_source_number);
 int64_t opal_get_msi_32(uint64_t phb_id, uint32_t mve_number, uint32_t xive_num,
-			uint8_t msi_range, uint32_t *msi_address,
-			uint32_t *message_data);
+			uint8_t msi_range, __be32 *msi_address,
+			__be32 *message_data);
 int64_t opal_get_msi_64(uint64_t phb_id, uint32_t mve_number,
 			uint32_t xive_num, uint8_t msi_range,
-			uint64_t *msi_address, uint32_t *message_data);
+			__be64 *msi_address, __be32 *message_data);
 int64_t opal_start_cpu(uint64_t thread_number, uint64_t start_address);
 int64_t opal_query_cpu_status(uint64_t thread_number, uint8_t *thread_status);
 int64_t opal_write_oppanel(oppanel_line_t *lines, uint64_t num_lines);
@@ -642,7 +713,7 @@
 int64_t opal_pci_reinit(uint64_t phb_id, uint8_t reinit_scope);
 int64_t opal_pci_mask_pe_error(uint64_t phb_id, uint16_t pe_number, uint8_t error_type, uint8_t mask_action);
 int64_t opal_set_slot_led_status(uint64_t phb_id, uint64_t slot_id, uint8_t led_type, uint8_t led_action);
-int64_t opal_get_epow_status(uint64_t *status);
+int64_t opal_get_epow_status(__be64 *status);
 int64_t opal_set_system_attention_led(uint8_t led_action);
 int64_t opal_pci_next_error(uint64_t phb_id, uint64_t *first_frozen_pe,
 			    uint16_t *pci_error_type, uint16_t *severity);
@@ -656,6 +727,9 @@
 		       uint32_t addr, uint32_t data, uint32_t sz);
 int64_t opal_lpc_read(uint32_t chip_id, enum OpalLPCAddressType addr_type,
 		      uint32_t addr, uint32_t *data, uint32_t sz);
+int64_t opal_validate_flash(uint64_t buffer, uint32_t *size, uint32_t *result);
+int64_t opal_manage_flash(uint8_t op);
+int64_t opal_update_flash(uint64_t blk_list);
 
 /* Internal functions */
 extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
@@ -684,6 +758,7 @@
 extern void opal_get_rtc_time(struct rtc_time *tm);
 extern unsigned long opal_get_boot_time(void);
 extern void opal_nvram_init(void);
+extern void opal_flash_init(void);
 
 extern int opal_machine_check(struct pt_regs *regs);
 
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
index b9f4262..32e4e21 100644
--- a/arch/powerpc/include/asm/page.h
+++ b/arch/powerpc/include/asm/page.h
@@ -78,7 +78,7 @@
  *
  * Also, KERNELBASE >= PAGE_OFFSET and PHYSICAL_START >= MEMORY_START
  *
- * There are two was to determine a physical address from a virtual one:
+ * There are two ways to determine a physical address from a virtual one:
  * va = pa + PAGE_OFFSET - MEMORY_START
  * va = pa + KERNELBASE - PHYSICAL_START
  *
@@ -403,7 +403,7 @@
 
 struct vm_area_struct;
 
-#ifdef CONFIG_PPC_64K_PAGES
+#if defined(CONFIG_PPC_64K_PAGES) && defined(CONFIG_PPC64)
 typedef pte_t *pgtable_t;
 #else
 typedef struct page *pgtable_t;
diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h
index 46db094..4a191c4 100644
--- a/arch/powerpc/include/asm/pgtable-ppc64.h
+++ b/arch/powerpc/include/asm/pgtable-ppc64.h
@@ -394,6 +394,8 @@
 	hpte_slot_array[index] = hidx << 4 | 0x1 << 3;
 }
 
+struct page *realmode_pfn_to_page(unsigned long pfn);
+
 static inline char *get_hpte_slot_array(pmd_t *pmdp)
 {
 	/*
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index d7fe9f5..3132bb9 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -143,6 +143,8 @@
 #define PPC_INST_LSWX			0x7c00042a
 #define PPC_INST_LWARX			0x7c000028
 #define PPC_INST_LWSYNC			0x7c2004ac
+#define PPC_INST_SYNC			0x7c0004ac
+#define PPC_INST_SYNC_MASK		0xfc0007fe
 #define PPC_INST_LXVD2X			0x7c000698
 #define PPC_INST_MCRXR			0x7c000400
 #define PPC_INST_MCRXR_MASK		0xfc0007fe
@@ -181,6 +183,7 @@
 #define PPC_INST_TLBIVAX		0x7c000624
 #define PPC_INST_TLBSRX_DOT		0x7c0006a5
 #define PPC_INST_XXLOR			0xf0000510
+#define PPC_INST_XXSWAPD		0xf0000250
 #define PPC_INST_XVCPSGNDP		0xf0000780
 #define PPC_INST_TRECHKPT		0x7c0007dd
 #define PPC_INST_TRECLAIM		0x7c00075d
@@ -200,6 +203,7 @@
 /* Misc instructions for BPF compiler */
 #define PPC_INST_LD			0xe8000000
 #define PPC_INST_LHZ			0xa0000000
+#define PPC_INST_LHBRX			0x7c00062c
 #define PPC_INST_LWZ			0x80000000
 #define PPC_INST_STD			0xf8000000
 #define PPC_INST_STDU			0xf8000001
@@ -218,7 +222,7 @@
 #define PPC_INST_MULLW			0x7c0001d6
 #define PPC_INST_MULHWU			0x7c000016
 #define PPC_INST_MULLI			0x1c000000
-#define PPC_INST_DIVWU			0x7c0003d6
+#define PPC_INST_DIVWU			0x7c000396
 #define PPC_INST_RLWINM			0x54000000
 #define PPC_INST_RLDICR			0x78000004
 #define PPC_INST_SLW			0x7c000030
@@ -344,6 +348,8 @@
 					       VSX_XX1((s), a, b))
 #define XXLOR(t, a, b)		stringify_in_c(.long PPC_INST_XXLOR | \
 					       VSX_XX3((t), a, b))
+#define XXSWAPD(t, a)		stringify_in_c(.long PPC_INST_XXSWAPD | \
+					       VSX_XX3((t), a, a))
 #define XVCPSGNDP(t, a, b)	stringify_in_c(.long (PPC_INST_XVCPSGNDP | \
 					       VSX_XX3((t), (a), (b))))
 
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 5995457..3c1acc3 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -98,123 +98,51 @@
 #define REST_8GPRS(n, base)	REST_4GPRS(n, base); REST_4GPRS(n+4, base)
 #define REST_10GPRS(n, base)	REST_8GPRS(n, base); REST_2GPRS(n+8, base)
 
-#define SAVE_FPR(n, base)	stfd	n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base)
+#define SAVE_FPR(n, base)	stfd	n,8*TS_FPRWIDTH*(n)(base)
 #define SAVE_2FPRS(n, base)	SAVE_FPR(n, base); SAVE_FPR(n+1, base)
 #define SAVE_4FPRS(n, base)	SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base)
 #define SAVE_8FPRS(n, base)	SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base)
 #define SAVE_16FPRS(n, base)	SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base)
 #define SAVE_32FPRS(n, base)	SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base)
-#define REST_FPR(n, base)	lfd	n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base)
+#define REST_FPR(n, base)	lfd	n,8*TS_FPRWIDTH*(n)(base)
 #define REST_2FPRS(n, base)	REST_FPR(n, base); REST_FPR(n+1, base)
 #define REST_4FPRS(n, base)	REST_2FPRS(n, base); REST_2FPRS(n+2, base)
 #define REST_8FPRS(n, base)	REST_4FPRS(n, base); REST_4FPRS(n+4, base)
 #define REST_16FPRS(n, base)	REST_8FPRS(n, base); REST_8FPRS(n+8, base)
 #define REST_32FPRS(n, base)	REST_16FPRS(n, base); REST_16FPRS(n+16, base)
 
-#define SAVE_VR(n,b,base)	li b,THREAD_VR0+(16*(n));  stvx n,base,b
+#define SAVE_VR(n,b,base)	li b,16*(n);  stvx n,base,b
 #define SAVE_2VRS(n,b,base)	SAVE_VR(n,b,base); SAVE_VR(n+1,b,base)
 #define SAVE_4VRS(n,b,base)	SAVE_2VRS(n,b,base); SAVE_2VRS(n+2,b,base)
 #define SAVE_8VRS(n,b,base)	SAVE_4VRS(n,b,base); SAVE_4VRS(n+4,b,base)
 #define SAVE_16VRS(n,b,base)	SAVE_8VRS(n,b,base); SAVE_8VRS(n+8,b,base)
 #define SAVE_32VRS(n,b,base)	SAVE_16VRS(n,b,base); SAVE_16VRS(n+16,b,base)
-#define REST_VR(n,b,base)	li b,THREAD_VR0+(16*(n)); lvx n,base,b
+#define REST_VR(n,b,base)	li b,16*(n); lvx n,base,b
 #define REST_2VRS(n,b,base)	REST_VR(n,b,base); REST_VR(n+1,b,base)
 #define REST_4VRS(n,b,base)	REST_2VRS(n,b,base); REST_2VRS(n+2,b,base)
 #define REST_8VRS(n,b,base)	REST_4VRS(n,b,base); REST_4VRS(n+4,b,base)
 #define REST_16VRS(n,b,base)	REST_8VRS(n,b,base); REST_8VRS(n+8,b,base)
 #define REST_32VRS(n,b,base)	REST_16VRS(n,b,base); REST_16VRS(n+16,b,base)
 
-/* Save/restore FPRs, VRs and VSRs from their checkpointed backups in
- * thread_struct:
- */
-#define SAVE_FPR_TRANSACT(n, base)	stfd n,THREAD_TRANSACT_FPR0+	\
-					8*TS_FPRWIDTH*(n)(base)
-#define SAVE_2FPRS_TRANSACT(n, base)	SAVE_FPR_TRANSACT(n, base);	\
-					SAVE_FPR_TRANSACT(n+1, base)
-#define SAVE_4FPRS_TRANSACT(n, base)	SAVE_2FPRS_TRANSACT(n, base);	\
-					SAVE_2FPRS_TRANSACT(n+2, base)
-#define SAVE_8FPRS_TRANSACT(n, base)	SAVE_4FPRS_TRANSACT(n, base);	\
-					SAVE_4FPRS_TRANSACT(n+4, base)
-#define SAVE_16FPRS_TRANSACT(n, base)	SAVE_8FPRS_TRANSACT(n, base);	\
-					SAVE_8FPRS_TRANSACT(n+8, base)
-#define SAVE_32FPRS_TRANSACT(n, base)	SAVE_16FPRS_TRANSACT(n, base);	\
-					SAVE_16FPRS_TRANSACT(n+16, base)
+#ifdef __BIG_ENDIAN__
+#define STXVD2X_ROT(n,b,base)		STXVD2X(n,b,base)
+#define LXVD2X_ROT(n,b,base)		LXVD2X(n,b,base)
+#else
+#define STXVD2X_ROT(n,b,base)		XXSWAPD(n,n);		\
+					STXVD2X(n,b,base);	\
+					XXSWAPD(n,n)
 
-#define REST_FPR_TRANSACT(n, base)	lfd	n,THREAD_TRANSACT_FPR0+	\
-					8*TS_FPRWIDTH*(n)(base)
-#define REST_2FPRS_TRANSACT(n, base)	REST_FPR_TRANSACT(n, base);	\
-					REST_FPR_TRANSACT(n+1, base)
-#define REST_4FPRS_TRANSACT(n, base)	REST_2FPRS_TRANSACT(n, base);	\
-					REST_2FPRS_TRANSACT(n+2, base)
-#define REST_8FPRS_TRANSACT(n, base)	REST_4FPRS_TRANSACT(n, base);	\
-					REST_4FPRS_TRANSACT(n+4, base)
-#define REST_16FPRS_TRANSACT(n, base)	REST_8FPRS_TRANSACT(n, base);	\
-					REST_8FPRS_TRANSACT(n+8, base)
-#define REST_32FPRS_TRANSACT(n, base)	REST_16FPRS_TRANSACT(n, base);	\
-					REST_16FPRS_TRANSACT(n+16, base)
-
-
-#define SAVE_VR_TRANSACT(n,b,base)	li b,THREAD_TRANSACT_VR0+(16*(n)); \
-					stvx n,b,base
-#define SAVE_2VRS_TRANSACT(n,b,base)	SAVE_VR_TRANSACT(n,b,base);	\
-					SAVE_VR_TRANSACT(n+1,b,base)
-#define SAVE_4VRS_TRANSACT(n,b,base)	SAVE_2VRS_TRANSACT(n,b,base);	\
-					SAVE_2VRS_TRANSACT(n+2,b,base)
-#define SAVE_8VRS_TRANSACT(n,b,base)	SAVE_4VRS_TRANSACT(n,b,base);	\
-					SAVE_4VRS_TRANSACT(n+4,b,base)
-#define SAVE_16VRS_TRANSACT(n,b,base)	SAVE_8VRS_TRANSACT(n,b,base);	\
-					SAVE_8VRS_TRANSACT(n+8,b,base)
-#define SAVE_32VRS_TRANSACT(n,b,base)	SAVE_16VRS_TRANSACT(n,b,base);	\
-					SAVE_16VRS_TRANSACT(n+16,b,base)
-
-#define REST_VR_TRANSACT(n,b,base)	li b,THREAD_TRANSACT_VR0+(16*(n)); \
-					lvx n,b,base
-#define REST_2VRS_TRANSACT(n,b,base)	REST_VR_TRANSACT(n,b,base);	\
-					REST_VR_TRANSACT(n+1,b,base)
-#define REST_4VRS_TRANSACT(n,b,base)	REST_2VRS_TRANSACT(n,b,base);	\
-					REST_2VRS_TRANSACT(n+2,b,base)
-#define REST_8VRS_TRANSACT(n,b,base)	REST_4VRS_TRANSACT(n,b,base);	\
-					REST_4VRS_TRANSACT(n+4,b,base)
-#define REST_16VRS_TRANSACT(n,b,base)	REST_8VRS_TRANSACT(n,b,base);	\
-					REST_8VRS_TRANSACT(n+8,b,base)
-#define REST_32VRS_TRANSACT(n,b,base)	REST_16VRS_TRANSACT(n,b,base);	\
-					REST_16VRS_TRANSACT(n+16,b,base)
-
-
-#define SAVE_VSR_TRANSACT(n,b,base)	li b,THREAD_TRANSACT_VSR0+(16*(n)); \
-					STXVD2X(n,R##base,R##b)
-#define SAVE_2VSRS_TRANSACT(n,b,base)	SAVE_VSR_TRANSACT(n,b,base);	\
-	                                SAVE_VSR_TRANSACT(n+1,b,base)
-#define SAVE_4VSRS_TRANSACT(n,b,base)	SAVE_2VSRS_TRANSACT(n,b,base);	\
-	                                SAVE_2VSRS_TRANSACT(n+2,b,base)
-#define SAVE_8VSRS_TRANSACT(n,b,base)	SAVE_4VSRS_TRANSACT(n,b,base);	\
-	                                SAVE_4VSRS_TRANSACT(n+4,b,base)
-#define SAVE_16VSRS_TRANSACT(n,b,base)	SAVE_8VSRS_TRANSACT(n,b,base);	\
-	                                SAVE_8VSRS_TRANSACT(n+8,b,base)
-#define SAVE_32VSRS_TRANSACT(n,b,base)	SAVE_16VSRS_TRANSACT(n,b,base);	\
-	                                SAVE_16VSRS_TRANSACT(n+16,b,base)
-
-#define REST_VSR_TRANSACT(n,b,base)	li b,THREAD_TRANSACT_VSR0+(16*(n)); \
-					LXVD2X(n,R##base,R##b)
-#define REST_2VSRS_TRANSACT(n,b,base)	REST_VSR_TRANSACT(n,b,base);    \
-	                                REST_VSR_TRANSACT(n+1,b,base)
-#define REST_4VSRS_TRANSACT(n,b,base)	REST_2VSRS_TRANSACT(n,b,base);	\
-	                                REST_2VSRS_TRANSACT(n+2,b,base)
-#define REST_8VSRS_TRANSACT(n,b,base)	REST_4VSRS_TRANSACT(n,b,base);	\
-	                                REST_4VSRS_TRANSACT(n+4,b,base)
-#define REST_16VSRS_TRANSACT(n,b,base)	REST_8VSRS_TRANSACT(n,b,base);	\
-	                                REST_8VSRS_TRANSACT(n+8,b,base)
-#define REST_32VSRS_TRANSACT(n,b,base)	REST_16VSRS_TRANSACT(n,b,base);	\
-	                                REST_16VSRS_TRANSACT(n+16,b,base)
-
+#define LXVD2X_ROT(n,b,base)		LXVD2X(n,b,base);	\
+					XXSWAPD(n,n)
+#endif
 /* Save the lower 32 VSRs in the thread VSR region */
-#define SAVE_VSR(n,b,base)	li b,THREAD_VSR0+(16*(n));  STXVD2X(n,R##base,R##b)
+#define SAVE_VSR(n,b,base)	li b,16*(n);  STXVD2X_ROT(n,R##base,R##b)
 #define SAVE_2VSRS(n,b,base)	SAVE_VSR(n,b,base); SAVE_VSR(n+1,b,base)
 #define SAVE_4VSRS(n,b,base)	SAVE_2VSRS(n,b,base); SAVE_2VSRS(n+2,b,base)
 #define SAVE_8VSRS(n,b,base)	SAVE_4VSRS(n,b,base); SAVE_4VSRS(n+4,b,base)
 #define SAVE_16VSRS(n,b,base)	SAVE_8VSRS(n,b,base); SAVE_8VSRS(n+8,b,base)
 #define SAVE_32VSRS(n,b,base)	SAVE_16VSRS(n,b,base); SAVE_16VSRS(n+16,b,base)
-#define REST_VSR(n,b,base)	li b,THREAD_VSR0+(16*(n)); LXVD2X(n,R##base,R##b)
+#define REST_VSR(n,b,base)	li b,16*(n); LXVD2X_ROT(n,R##base,R##b)
 #define REST_2VSRS(n,b,base)	REST_VSR(n,b,base); REST_VSR(n+1,b,base)
 #define REST_4VSRS(n,b,base)	REST_2VSRS(n,b,base); REST_2VSRS(n+2,b,base)
 #define REST_8VSRS(n,b,base)	REST_4VSRS(n,b,base); REST_4VSRS(n+4,b,base)
@@ -478,13 +406,6 @@
 	std	ra,TASKTHREADPPR(rb);					\
 END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,945)
 
-#define RESTORE_PPR(ra, rb)						\
-BEGIN_FTR_SECTION_NESTED(946)						\
-	ld	ra,PACACURRENT(r13);					\
-	ld	rb,TASKTHREADPPR(ra);					\
-	mtspr	SPRN_PPR,rb;	/* Restore PPR */			\
-END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,946)
-
 #endif
 
 /*
@@ -832,6 +753,35 @@
 #define N_SLINE	68
 #define N_SO	100
 
-#endif /*  __ASSEMBLY__ */
+/*
+ * Create an endian fixup trampoline
+ *
+ * This starts with a "tdi 0,0,0x48" instruction which is
+ * essentially a "trap never", and thus akin to a nop.
+ *
+ * The opcode for this instruction read with the wrong endian
+ * however results in a b . + 8
+ *
+ * So essentially we use that trick to execute the following
+ * trampoline in "reverse endian" if we are running with the
+ * MSR_LE bit set the "wrong" way for whatever endianness the
+ * kernel is built for.
+ */
 
+#ifdef CONFIG_PPC_BOOK3E
+#define FIXUP_ENDIAN
+#else
+#define FIXUP_ENDIAN						   \
+	tdi   0,0,0x48;	  /* Reverse endian of b . + 8		*/ \
+	b     $+36;	  /* Skip trampoline if endian is good	*/ \
+	.long 0x05009f42; /* bcl 20,31,$+4			*/ \
+	.long 0xa602487d; /* mflr r10				*/ \
+	.long 0x1c004a39; /* addi r10,r10,28			*/ \
+	.long 0xa600607d; /* mfmsr r11				*/ \
+	.long 0x01006b69; /* xori r11,r11,1			*/ \
+	.long 0xa6035a7d; /* mtsrr0 r10				*/ \
+	.long 0xa6037b7d; /* mtsrr1 r11				*/ \
+	.long 0x2400004c  /* rfid				*/
+#endif /* !CONFIG_PPC_BOOK3E */
+#endif /*  __ASSEMBLY__ */
 #endif /* _ASM_POWERPC_PPC_ASM_H */
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index ce4de5a..7794b2b 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -14,8 +14,18 @@
 
 #ifdef CONFIG_VSX
 #define TS_FPRWIDTH 2
+
+#ifdef __BIG_ENDIAN__
+#define TS_FPROFFSET 0
+#define TS_VSRLOWOFFSET 1
+#else
+#define TS_FPROFFSET 1
+#define TS_VSRLOWOFFSET 0
+#endif
+
 #else
 #define TS_FPRWIDTH 1
+#define TS_FPROFFSET 0
 #endif
 
 #ifdef CONFIG_PPC64
@@ -142,26 +152,22 @@
 	unsigned long seg;
 } mm_segment_t;
 
-#define TS_FPROFFSET 0
-#define TS_VSRLOWOFFSET 1
-#define TS_FPR(i) fpr[i][TS_FPROFFSET]
-#define TS_TRANS_FPR(i) transact_fpr[i][TS_FPROFFSET]
+#define TS_FPR(i) fp_state.fpr[i][TS_FPROFFSET]
+#define TS_TRANS_FPR(i) transact_fp.fpr[i][TS_FPROFFSET]
 
-struct thread_struct {
-	unsigned long	ksp;		/* Kernel stack pointer */
-#ifdef CONFIG_PPC64
-	unsigned long	ksp_vsid;
-#endif
-	struct pt_regs	*regs;		/* Pointer to saved register state */
-	mm_segment_t	fs;		/* for get_fs() validation */
-#ifdef CONFIG_BOOKE
-	/* BookE base exception scratch space; align on cacheline */
-	unsigned long	normsave[8] ____cacheline_aligned;
-#endif
-#ifdef CONFIG_PPC32
-	void		*pgdir;		/* root of page-table tree */
-	unsigned long	ksp_limit;	/* if ksp <= ksp_limit stack overflow */
-#endif
+/* FP and VSX 0-31 register set */
+struct thread_fp_state {
+	u64	fpr[32][TS_FPRWIDTH] __attribute__((aligned(16)));
+	u64	fpscr;		/* Floating point status */
+};
+
+/* Complete AltiVec register set including VSCR */
+struct thread_vr_state {
+	vector128	vr[32] __attribute__((aligned(16)));
+	vector128	vscr __attribute__((aligned(16)));
+};
+
+struct debug_reg {
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
 	/*
 	 * The following help to manage the use of Debug Control Registers
@@ -198,13 +204,26 @@
 	unsigned long	dvc2;
 #endif
 #endif
-	/* FP and VSX 0-31 register set */
-	double		fpr[32][TS_FPRWIDTH] __attribute__((aligned(16)));
-	struct {
+};
 
-		unsigned int pad;
-		unsigned int val;	/* Floating point status */
-	} fpscr;
+struct thread_struct {
+	unsigned long	ksp;		/* Kernel stack pointer */
+#ifdef CONFIG_PPC64
+	unsigned long	ksp_vsid;
+#endif
+	struct pt_regs	*regs;		/* Pointer to saved register state */
+	mm_segment_t	fs;		/* for get_fs() validation */
+#ifdef CONFIG_BOOKE
+	/* BookE base exception scratch space; align on cacheline */
+	unsigned long	normsave[8] ____cacheline_aligned;
+#endif
+#ifdef CONFIG_PPC32
+	void		*pgdir;		/* root of page-table tree */
+	unsigned long	ksp_limit;	/* if ksp <= ksp_limit stack overflow */
+#endif
+	struct debug_reg debug;
+	struct thread_fp_state	fp_state;
+	struct thread_fp_state	*fp_save_area;
 	int		fpexc_mode;	/* floating-point exception mode */
 	unsigned int	align_ctl;	/* alignment handling control */
 #ifdef CONFIG_PPC64
@@ -222,10 +241,8 @@
 	struct arch_hw_breakpoint hw_brk; /* info on the hardware breakpoint */
 	unsigned long	trap_nr;	/* last trap # on this thread */
 #ifdef CONFIG_ALTIVEC
-	/* Complete AltiVec register set */
-	vector128	vr[32] __attribute__((aligned(16)));
-	/* AltiVec status */
-	vector128	vscr __attribute__((aligned(16)));
+	struct thread_vr_state vr_state;
+	struct thread_vr_state *vr_save_area;
 	unsigned long	vrsave;
 	int		used_vr;	/* set if process has used altivec */
 #endif /* CONFIG_ALTIVEC */
@@ -262,13 +279,8 @@
 	 * transact_fpr[] is the new set of transactional values.
 	 * VRs work the same way.
 	 */
-	double		transact_fpr[32][TS_FPRWIDTH];
-	struct {
-		unsigned int pad;
-		unsigned int val;	/* Floating point status */
-	} transact_fpscr;
-	vector128	transact_vr[32] __attribute__((aligned(16)));
-	vector128	transact_vscr __attribute__((aligned(16)));
+	struct thread_fp_state transact_fp;
+	struct thread_vr_state transact_vr;
 	unsigned long	transact_vrsave;
 #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
 #ifdef CONFIG_KVM_BOOK3S_32_HANDLER
@@ -322,8 +334,6 @@
 	.ksp = INIT_SP, \
 	.regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \
 	.fs = KERNEL_DS, \
-	.fpr = {{0}}, \
-	.fpscr = { .val = 0, }, \
 	.fpexc_mode = 0, \
 	.ppr = INIT_PPR, \
 }
@@ -361,6 +371,11 @@
 extern int get_unalign_ctl(struct task_struct *tsk, unsigned long adr);
 extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val);
 
+extern void load_fp_state(struct thread_fp_state *fp);
+extern void store_fp_state(struct thread_fp_state *fp);
+extern void load_vr_state(struct thread_vr_state *vr);
+extern void store_vr_state(struct thread_vr_state *vr);
+
 static inline unsigned int __unpack_fe01(unsigned long msr_bits)
 {
 	return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8);
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index 7d0c7f3..d977b9b 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -1,4 +1,3 @@
-#include <linux/of.h>	/* linux/of.h gets to determine #include ordering */
 #ifndef _POWERPC_PROM_H
 #define _POWERPC_PROM_H
 #ifdef __KERNEL__
@@ -20,21 +19,17 @@
 #include <asm/irq.h>
 #include <linux/atomic.h>
 
-#define HAVE_ARCH_DEVTREE_FIXUPS
+/* These includes should be removed once implicit includes are cleaned up. */
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
 
 /*
  * OF address retreival & translation
  */
 
-/* Translate a DMA address from device space to CPU space */
-extern u64 of_translate_dma_address(struct device_node *dev,
-				    const __be32 *in_addr);
-
-#ifdef CONFIG_PCI
-extern unsigned long pci_address_to_pio(phys_addr_t address);
-#define pci_address_to_pio pci_address_to_pio
-#endif	/* CONFIG_PCI */
-
 /* Parse the ibm,dma-window property of an OF node into the busno, phys and
  * size parameters.
  */
@@ -44,16 +39,6 @@
 
 extern void kdump_move_device_tree(void);
 
-/* cache lookup */
-struct device_node *of_find_next_cache_node(struct device_node *np);
-
-#ifdef CONFIG_NUMA
-extern int of_node_to_nid(struct device_node *device);
-#else
-static inline int of_node_to_nid(struct device_node *device) { return 0; }
-#endif
-#define of_node_to_nid of_node_to_nid
-
 extern void of_instantiate_rtc(void);
 
 extern int of_get_ibm_chip_id(struct device_node *np);
@@ -143,14 +128,5 @@
  */
 extern unsigned char ibm_architecture_vec[];
 
-/* These includes are put at the bottom because they may contain things
- * that are overridden by this file.  Ideally they shouldn't be included
- * by this file, but there are a bunch of .c files that currently depend
- * on it.  Eventually they will be cleaned up. */
-#include <linux/of_fdt.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/platform_device.h>
-
 #endif /* __KERNEL__ */
 #endif /* _POWERPC_PROM_H */
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 10d1ef0..126f6e9 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -115,7 +115,12 @@
 #define MSR_64BIT	MSR_SF
 
 /* Server variant */
-#define MSR_		(MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_ISF |MSR_HV)
+#define __MSR		(MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_ISF |MSR_HV)
+#ifdef __BIG_ENDIAN__
+#define MSR_		__MSR
+#else
+#define MSR_		(__MSR | MSR_LE)
+#endif
 #define MSR_KERNEL	(MSR_ | MSR_64BIT)
 #define MSR_USER32	(MSR_ | MSR_PR | MSR_EE)
 #define MSR_USER64	(MSR_USER32 | MSR_64BIT)
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h
index ed8f836..2e31aac 100644
--- a/arch/powerpc/include/asm/reg_booke.h
+++ b/arch/powerpc/include/asm/reg_booke.h
@@ -381,7 +381,7 @@
 #define DBCR0_IA34T	0x00004000	/* Instr Addr 3-4 range Toggle */
 #define DBCR0_FT	0x00000001	/* Freeze Timers on debug event */
 
-#define dbcr_iac_range(task)	((task)->thread.dbcr0)
+#define dbcr_iac_range(task)	((task)->thread.debug.dbcr0)
 #define DBCR_IAC12I	DBCR0_IA12			/* Range Inclusive */
 #define DBCR_IAC12X	(DBCR0_IA12 | DBCR0_IA12X)	/* Range Exclusive */
 #define DBCR_IAC12MODE	(DBCR0_IA12 | DBCR0_IA12X)	/* IAC 1-2 Mode Bits */
@@ -395,7 +395,7 @@
 #define DBCR1_DAC1W	0x20000000	/* DAC1 Write Debug Event */
 #define DBCR1_DAC2W	0x10000000	/* DAC2 Write Debug Event */
 
-#define dbcr_dac(task)	((task)->thread.dbcr1)
+#define dbcr_dac(task)	((task)->thread.debug.dbcr1)
 #define DBCR_DAC1R	DBCR1_DAC1R
 #define DBCR_DAC1W	DBCR1_DAC1W
 #define DBCR_DAC2R	DBCR1_DAC2R
@@ -441,7 +441,7 @@
 #define DBCR0_CRET	0x00000020	/* Critical Return Debug Event */
 #define DBCR0_FT	0x00000001	/* Freeze Timers on debug event */
 
-#define dbcr_dac(task)	((task)->thread.dbcr0)
+#define dbcr_dac(task)	((task)->thread.debug.dbcr0)
 #define DBCR_DAC1R	DBCR0_DAC1R
 #define DBCR_DAC1W	DBCR0_DAC1W
 #define DBCR_DAC2R	DBCR0_DAC2R
@@ -475,7 +475,7 @@
 #define DBCR1_IAC34MX	0x000000C0	/* Instr Addr 3-4 range eXclusive */
 #define DBCR1_IAC34AT	0x00000001	/* Instr Addr 3-4 range Toggle */
 
-#define dbcr_iac_range(task)	((task)->thread.dbcr1)
+#define dbcr_iac_range(task)	((task)->thread.debug.dbcr1)
 #define DBCR_IAC12I	DBCR1_IAC12M	/* Range Inclusive */
 #define DBCR_IAC12X	DBCR1_IAC12MX	/* Range Exclusive */
 #define DBCR_IAC12MODE	DBCR1_IAC12MX	/* IAC 1-2 Mode Bits */
diff --git a/arch/powerpc/include/asm/scom.h b/arch/powerpc/include/asm/scom.h
index 0cabfd7..f5cde45 100644
--- a/arch/powerpc/include/asm/scom.h
+++ b/arch/powerpc/include/asm/scom.h
@@ -54,8 +54,8 @@
 	scom_map_t (*map)(struct device_node *ctrl_dev, u64 reg, u64 count);
 	void (*unmap)(scom_map_t map);
 
-	u64 (*read)(scom_map_t map, u32 reg);
-	void (*write)(scom_map_t map, u32 reg, u64 value);
+	int (*read)(scom_map_t map, u64 reg, u64 *value);
+	int (*write)(scom_map_t map, u64 reg, u64 value);
 };
 
 extern const struct scom_controller *scom_controller;
@@ -133,10 +133,18 @@
  * scom_read - Read a SCOM register
  * @map: Result of scom_map
  * @reg: Register index within that map
+ * @value: Updated with the value read
+ *
+ * Returns 0 (success) or a negative error code
  */
-static inline u64 scom_read(scom_map_t map, u32 reg)
+static inline int scom_read(scom_map_t map, u64 reg, u64 *value)
 {
-	return scom_controller->read(map, reg);
+	int rc;
+
+	rc = scom_controller->read(map, reg, value);
+	if (rc)
+		*value = 0xfffffffffffffffful;
+	return rc;
 }
 
 /**
@@ -144,12 +152,15 @@
  * @map: Result of scom_map
  * @reg: Register index within that map
  * @value: Value to write
+ *
+ * Returns 0 (success) or a negative error code
  */
-static inline void scom_write(scom_map_t map, u32 reg, u64 value)
+static inline int scom_write(scom_map_t map, u64 reg, u64 value)
 {
-	scom_controller->write(map, reg, value);
+	return scom_controller->write(map, reg, value);
 }
 
+
 #endif /* CONFIG_PPC_SCOM */
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h
index d3ca855..703a841 100644
--- a/arch/powerpc/include/asm/setup.h
+++ b/arch/powerpc/include/asm/setup.h
@@ -23,6 +23,10 @@
 
 #define PTRRELOC(x)	((typeof(x)) add_reloc_offset((unsigned long)(x)))
 
+void check_for_initrd(void);
+void do_init_bootmem(void);
+void setup_panic(void);
+
 #endif /* !__ASSEMBLY__ */
 
 #endif	/* _ASM_POWERPC_SETUP_H */
diff --git a/arch/powerpc/include/asm/sfp-machine.h b/arch/powerpc/include/asm/sfp-machine.h
index 3a7a67a..d89beab 100644
--- a/arch/powerpc/include/asm/sfp-machine.h
+++ b/arch/powerpc/include/asm/sfp-machine.h
@@ -125,7 +125,7 @@
 #define FP_EX_DIVZERO         (1 << (31 - 5))
 #define FP_EX_INEXACT         (1 << (31 - 6))
 
-#define __FPU_FPSCR	(current->thread.fpscr.val)
+#define __FPU_FPSCR	(current->thread.fp_state.fpscr)
 
 /* We only actually write to the destination register
  * if exceptions signalled (if any) will not trap.
diff --git a/arch/powerpc/include/asm/string.h b/arch/powerpc/include/asm/string.h
index e40010a..0dffad6 100644
--- a/arch/powerpc/include/asm/string.h
+++ b/arch/powerpc/include/asm/string.h
@@ -10,7 +10,9 @@
 #define __HAVE_ARCH_STRNCMP
 #define __HAVE_ARCH_STRCAT
 #define __HAVE_ARCH_MEMSET
+#ifdef __BIG_ENDIAN__
 #define __HAVE_ARCH_MEMCPY
+#endif
 #define __HAVE_ARCH_MEMMOVE
 #define __HAVE_ARCH_MEMCMP
 #define __HAVE_ARCH_MEMCHR
@@ -22,7 +24,9 @@
 extern int strncmp(const char *, const char *, __kernel_size_t);
 extern char * strcat(char *, const char *);
 extern void * memset(void *,int,__kernel_size_t);
+#ifdef __BIG_ENDIAN__
 extern void * memcpy(void *,const void *,__kernel_size_t);
+#endif
 extern void * memmove(void *,const void *,__kernel_size_t);
 extern int memcmp(const void *,const void *,__kernel_size_t);
 extern void * memchr(const void *,int,__kernel_size_t);
diff --git a/arch/powerpc/include/asm/switch_to.h b/arch/powerpc/include/asm/switch_to.h
index 2be5618..9ee1261 100644
--- a/arch/powerpc/include/asm/switch_to.h
+++ b/arch/powerpc/include/asm/switch_to.h
@@ -35,6 +35,7 @@
 extern void enable_kernel_spe(void);
 extern void giveup_spe(struct task_struct *);
 extern void load_up_spe(struct task_struct *);
+extern void switch_booke_debug_regs(struct thread_struct *new_thread);
 
 #ifndef CONFIG_SMP
 extern void discard_lazy_cpu_state(void);
diff --git a/arch/powerpc/include/asm/uprobes.h b/arch/powerpc/include/asm/uprobes.h
index 2301602..75c6ecd 100644
--- a/arch/powerpc/include/asm/uprobes.h
+++ b/arch/powerpc/include/asm/uprobes.h
@@ -37,6 +37,7 @@
 struct arch_uprobe {
 	union {
 		u8	insn[MAX_UINSN_BYTES];
+		u8	ixol[MAX_UINSN_BYTES];
 		u32	ainsn;
 	};
 };
@@ -45,11 +46,4 @@
 	unsigned long	saved_trap_nr;
 };
 
-extern int  arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
-extern int  arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
-extern int  arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
-extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
-extern int  arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
-extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
-extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs);
 #endif	/* _ASM_UPROBES_H */
diff --git a/arch/powerpc/include/asm/word-at-a-time.h b/arch/powerpc/include/asm/word-at-a-time.h
index d0b6d4a..9a5c928 100644
--- a/arch/powerpc/include/asm/word-at-a-time.h
+++ b/arch/powerpc/include/asm/word-at-a-time.h
@@ -8,6 +8,8 @@
 #include <linux/kernel.h>
 #include <asm/asm-compat.h>
 
+#ifdef __BIG_ENDIAN__
+
 struct word_at_a_time {
 	const unsigned long high_bits, low_bits;
 };
@@ -38,4 +40,80 @@
 	return (val + c->high_bits) & ~rhs;
 }
 
+#else
+
+struct word_at_a_time {
+	const unsigned long one_bits, high_bits;
+};
+
+#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) }
+
+#ifdef CONFIG_64BIT
+
+/* Alan Modra's little-endian strlen tail for 64-bit */
+#define create_zero_mask(mask) (mask)
+
+static inline unsigned long find_zero(unsigned long mask)
+{
+	unsigned long leading_zero_bits;
+	long trailing_zero_bit_mask;
+
+	asm ("addi %1,%2,-1\n\t"
+	     "andc %1,%1,%2\n\t"
+	     "popcntd %0,%1"
+	     : "=r" (leading_zero_bits), "=&r" (trailing_zero_bit_mask)
+	     : "r" (mask));
+	return leading_zero_bits >> 3;
+}
+
+#else	/* 32-bit case */
+
+/*
+ * This is largely generic for little-endian machines, but the
+ * optimal byte mask counting is probably going to be something
+ * that is architecture-specific. If you have a reliably fast
+ * bit count instruction, that might be better than the multiply
+ * and shift, for example.
+ */
+
+/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */
+static inline long count_masked_bytes(long mask)
+{
+	/* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */
+	long a = (0x0ff0001+mask) >> 23;
+	/* Fix the 1 for 00 case */
+	return a & mask;
+}
+
+static inline unsigned long create_zero_mask(unsigned long bits)
+{
+	bits = (bits - 1) & ~bits;
+	return bits >> 7;
+}
+
+static inline unsigned long find_zero(unsigned long mask)
+{
+	return count_masked_bytes(mask);
+}
+
+#endif
+
+/* Return nonzero if it has a zero */
+static inline unsigned long has_zero(unsigned long a, unsigned long *bits, const struct word_at_a_time *c)
+{
+	unsigned long mask = ((a - c->one_bits) & ~a) & c->high_bits;
+	*bits = mask;
+	return mask;
+}
+
+static inline unsigned long prep_zero_mask(unsigned long a, unsigned long bits, const struct word_at_a_time *c)
+{
+	return bits;
+}
+
+/* The mask we created is directly usable as a bytemask */
+#define zero_bytemask(mask) (mask)
+
+#endif
+
 #endif /* _ASM_WORD_AT_A_TIME_H */
diff --git a/arch/powerpc/include/asm/xor.h b/arch/powerpc/include/asm/xor.h
index c82eb12..0abb97f 100644
--- a/arch/powerpc/include/asm/xor.h
+++ b/arch/powerpc/include/asm/xor.h
@@ -1 +1,68 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2012
+ *
+ * Author: Anton Blanchard <anton@au.ibm.com>
+ */
+#ifndef _ASM_POWERPC_XOR_H
+#define _ASM_POWERPC_XOR_H
+
+#ifdef CONFIG_ALTIVEC
+
+#include <asm/cputable.h>
+
+void xor_altivec_2(unsigned long bytes, unsigned long *v1_in,
+		   unsigned long *v2_in);
+void xor_altivec_3(unsigned long bytes, unsigned long *v1_in,
+		   unsigned long *v2_in, unsigned long *v3_in);
+void xor_altivec_4(unsigned long bytes, unsigned long *v1_in,
+		   unsigned long *v2_in, unsigned long *v3_in,
+		   unsigned long *v4_in);
+void xor_altivec_5(unsigned long bytes, unsigned long *v1_in,
+		   unsigned long *v2_in, unsigned long *v3_in,
+		   unsigned long *v4_in, unsigned long *v5_in);
+
+static struct xor_block_template xor_block_altivec = {
+	.name = "altivec",
+	.do_2 = xor_altivec_2,
+	.do_3 = xor_altivec_3,
+	.do_4 = xor_altivec_4,
+	.do_5 = xor_altivec_5,
+};
+
+#define XOR_SPEED_ALTIVEC()				\
+	do {						\
+		if (cpu_has_feature(CPU_FTR_ALTIVEC))	\
+			xor_speed(&xor_block_altivec);	\
+	} while (0)
+#else
+#define XOR_SPEED_ALTIVEC()
+#endif
+
+/* Also try the generic routines. */
 #include <asm-generic/xor.h>
+
+#undef XOR_TRY_TEMPLATES
+#define XOR_TRY_TEMPLATES				\
+do {							\
+	xor_speed(&xor_block_8regs);			\
+	xor_speed(&xor_block_8regs_p);			\
+	xor_speed(&xor_block_32regs);			\
+	xor_speed(&xor_block_32regs_p);			\
+	XOR_SPEED_ALTIVEC();				\
+} while (0)
+
+#endif /* _ASM_POWERPC_XOR_H */
diff --git a/arch/powerpc/include/uapi/asm/byteorder.h b/arch/powerpc/include/uapi/asm/byteorder.h
index aa6cc4f..ca931d0 100644
--- a/arch/powerpc/include/uapi/asm/byteorder.h
+++ b/arch/powerpc/include/uapi/asm/byteorder.h
@@ -7,6 +7,10 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
+#ifdef __LITTLE_ENDIAN__
+#include <linux/byteorder/little_endian.h>
+#else
 #include <linux/byteorder/big_endian.h>
+#endif
 
 #endif /* _ASM_POWERPC_BYTEORDER_H */
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index a27ccd5..de91f3a 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -54,8 +54,6 @@
 /* DSISR bits reported for a DCBZ instruction: */
 #define DCBZ	0x5f	/* 8xx/82xx dcbz faults when cache not enabled */
 
-#define SWAP(a, b)	(t = (a), (a) = (b), (b) = t)
-
 /*
  * The PowerPC stores certain bits of the instruction that caused the
  * alignment exception in the DSISR register.  This array maps those
@@ -256,11 +254,17 @@
  * bottom 4 bytes of each register, and the loads clear the
  * top 4 bytes of the affected register.
  */
+#ifdef __BIG_ENDIAN__
 #ifdef CONFIG_PPC64
 #define REG_BYTE(rp, i)		*((u8 *)((rp) + ((i) >> 2)) + ((i) & 3) + 4)
 #else
 #define REG_BYTE(rp, i)		*((u8 *)(rp) + (i))
 #endif
+#endif
+
+#ifdef __LITTLE_ENDIAN__
+#define REG_BYTE(rp, i)		(*(((u8 *)((rp) + ((i)>>2)) + ((i)&3))))
+#endif
 
 #define SWIZ_PTR(p)		((unsigned char __user *)((p) ^ swiz))
 
@@ -305,6 +309,15 @@
 			nb0 = nb + reg * 4 - 128;
 			nb = 128 - reg * 4;
 		}
+#ifdef __LITTLE_ENDIAN__
+		/*
+		 *  String instructions are endian neutral but the code
+		 *  below is not.  Force byte swapping on so that the
+		 *  effects of swizzling are undone in the load/store
+		 *  loops below.
+		 */
+		flags ^= SW;
+#endif
 	} else {
 		/* lwm, stmw */
 		nb = (32 - reg) * 4;
@@ -458,7 +471,7 @@
 static int emulate_spe(struct pt_regs *regs, unsigned int reg,
 		       unsigned int instr)
 {
-	int t, ret;
+	int ret;
 	union {
 		u64 ll;
 		u32 w[2];
@@ -581,24 +594,18 @@
 	if (flags & SW) {
 		switch (flags & 0xf0) {
 		case E8:
-			SWAP(data.v[0], data.v[7]);
-			SWAP(data.v[1], data.v[6]);
-			SWAP(data.v[2], data.v[5]);
-			SWAP(data.v[3], data.v[4]);
+			data.ll = swab64(data.ll);
 			break;
 		case E4:
-
-			SWAP(data.v[0], data.v[3]);
-			SWAP(data.v[1], data.v[2]);
-			SWAP(data.v[4], data.v[7]);
-			SWAP(data.v[5], data.v[6]);
+			data.w[0] = swab32(data.w[0]);
+			data.w[1] = swab32(data.w[1]);
 			break;
 		/* Its half word endian */
 		default:
-			SWAP(data.v[0], data.v[1]);
-			SWAP(data.v[2], data.v[3]);
-			SWAP(data.v[4], data.v[5]);
-			SWAP(data.v[6], data.v[7]);
+			data.h[0] = swab16(data.h[0]);
+			data.h[1] = swab16(data.h[1]);
+			data.h[2] = swab16(data.h[2]);
+			data.h[3] = swab16(data.h[3]);
 			break;
 		}
 	}
@@ -658,14 +665,31 @@
 	flush_vsx_to_thread(current);
 
 	if (reg < 32)
-		ptr = (char *) &current->thread.TS_FPR(reg);
+		ptr = (char *) &current->thread.fp_state.fpr[reg][0];
 	else
-		ptr = (char *) &current->thread.vr[reg - 32];
+		ptr = (char *) &current->thread.vr_state.vr[reg - 32];
 
 	lptr = (unsigned long *) ptr;
 
+#ifdef __LITTLE_ENDIAN__
+	if (flags & SW) {
+		elsize = length;
+		sw = length-1;
+	} else {
+		/*
+		 * The elements are BE ordered, even in LE mode, so process
+		 * them in reverse order.
+		 */
+		addr += length - elsize;
+
+		/* 8 byte memory accesses go in the top 8 bytes of the VR */
+		if (length == 8)
+			ptr += 8;
+	}
+#else
 	if (flags & SW)
 		sw = elsize-1;
+#endif
 
 	for (j = 0; j < length; j += elsize) {
 		for (i = 0; i < elsize; ++i) {
@@ -675,19 +699,31 @@
 				ret |= __get_user(ptr[i^sw], addr + i);
 		}
 		ptr  += elsize;
+#ifdef __LITTLE_ENDIAN__
+		addr -= elsize;
+#else
 		addr += elsize;
+#endif
 	}
 
+#ifdef __BIG_ENDIAN__
+#define VSX_HI 0
+#define VSX_LO 1
+#else
+#define VSX_HI 1
+#define VSX_LO 0
+#endif
+
 	if (!ret) {
 		if (flags & U)
 			regs->gpr[areg] = regs->dar;
 
 		/* Splat load copies the same data to top and bottom 8 bytes */
 		if (flags & SPLT)
-			lptr[1] = lptr[0];
-		/* For 8 byte loads, zero the top 8 bytes */
+			lptr[VSX_LO] = lptr[VSX_HI];
+		/* For 8 byte loads, zero the low 8 bytes */
 		else if (!(flags & ST) && (8 == length))
-			lptr[1] = 0;
+			lptr[VSX_LO] = 0;
 	} else
 		return -EFAULT;
 
@@ -710,18 +746,28 @@
 	unsigned int dsisr;
 	unsigned char __user *addr;
 	unsigned long p, swiz;
-	int ret, t;
-	union {
+	int ret, i;
+	union data {
 		u64 ll;
 		double dd;
 		unsigned char v[8];
 		struct {
+#ifdef __LITTLE_ENDIAN__
+			int	 low32;
+			unsigned hi32;
+#else
 			unsigned hi32;
 			int	 low32;
+#endif
 		} x32;
 		struct {
+#ifdef __LITTLE_ENDIAN__
+			short	      low16;
+			unsigned char hi48[6];
+#else
 			unsigned char hi48[6];
 			short	      low16;
+#endif
 		} x16;
 	} data;
 
@@ -780,8 +826,9 @@
 
 	/* Byteswap little endian loads and stores */
 	swiz = 0;
-	if (regs->msr & MSR_LE) {
+	if ((regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE)) {
 		flags ^= SW;
+#ifdef __BIG_ENDIAN__
 		/*
 		 * So-called "PowerPC little endian" mode works by
 		 * swizzling addresses rather than by actually doing
@@ -794,6 +841,7 @@
 		 */
 		if (cpu_has_feature(CPU_FTR_PPC_LE))
 			swiz = 7;
+#endif
 	}
 
 	/* DAR has the operand effective address */
@@ -818,7 +866,7 @@
 			elsize = 8;
 
 		flags = 0;
-		if (regs->msr & MSR_LE)
+		if ((regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE))
 			flags |= SW;
 		if (instruction & 0x100)
 			flags |= ST;
@@ -878,32 +926,36 @@
 	 * get it from register values
 	 */
 	if (!(flags & ST)) {
+		unsigned int start = 0;
+
+		switch (nb) {
+		case 4:
+			start = offsetof(union data, x32.low32);
+			break;
+		case 2:
+			start = offsetof(union data, x16.low16);
+			break;
+		}
+
 		data.ll = 0;
 		ret = 0;
-		p = (unsigned long) addr;
-		switch (nb) {
-		case 8:
-			ret |= __get_user_inatomic(data.v[0], SWIZ_PTR(p++));
-			ret |= __get_user_inatomic(data.v[1], SWIZ_PTR(p++));
-			ret |= __get_user_inatomic(data.v[2], SWIZ_PTR(p++));
-			ret |= __get_user_inatomic(data.v[3], SWIZ_PTR(p++));
-		case 4:
-			ret |= __get_user_inatomic(data.v[4], SWIZ_PTR(p++));
-			ret |= __get_user_inatomic(data.v[5], SWIZ_PTR(p++));
-		case 2:
-			ret |= __get_user_inatomic(data.v[6], SWIZ_PTR(p++));
-			ret |= __get_user_inatomic(data.v[7], SWIZ_PTR(p++));
-			if (unlikely(ret))
-				return -EFAULT;
-		}
+		p = (unsigned long)addr;
+
+		for (i = 0; i < nb; i++)
+			ret |= __get_user_inatomic(data.v[start + i],
+						   SWIZ_PTR(p++));
+
+		if (unlikely(ret))
+			return -EFAULT;
+
 	} else if (flags & F) {
-		data.dd = current->thread.TS_FPR(reg);
+		data.ll = current->thread.TS_FPR(reg);
 		if (flags & S) {
 			/* Single-precision FP store requires conversion... */
 #ifdef CONFIG_PPC_FPU
 			preempt_disable();
 			enable_kernel_fp();
-			cvt_df(&data.dd, (float *)&data.v[4]);
+			cvt_df(&data.dd, (float *)&data.x32.low32);
 			preempt_enable();
 #else
 			return 0;
@@ -915,17 +967,13 @@
 	if (flags & SW) {
 		switch (nb) {
 		case 8:
-			SWAP(data.v[0], data.v[7]);
-			SWAP(data.v[1], data.v[6]);
-			SWAP(data.v[2], data.v[5]);
-			SWAP(data.v[3], data.v[4]);
+			data.ll = swab64(data.ll);
 			break;
 		case 4:
-			SWAP(data.v[4], data.v[7]);
-			SWAP(data.v[5], data.v[6]);
+			data.x32.low32 = swab32(data.x32.low32);
 			break;
 		case 2:
-			SWAP(data.v[6], data.v[7]);
+			data.x16.low16 = swab16(data.x16.low16);
 			break;
 		}
 	}
@@ -947,7 +995,7 @@
 #ifdef CONFIG_PPC_FPU
 		preempt_disable();
 		enable_kernel_fp();
-		cvt_fd((float *)&data.v[4], &data.dd);
+		cvt_fd((float *)&data.x32.low32, &data.dd);
 		preempt_enable();
 #else
 		return 0;
@@ -957,25 +1005,28 @@
 
 	/* Store result to memory or update registers */
 	if (flags & ST) {
-		ret = 0;
-		p = (unsigned long) addr;
+		unsigned int start = 0;
+
 		switch (nb) {
-		case 8:
-			ret |= __put_user_inatomic(data.v[0], SWIZ_PTR(p++));
-			ret |= __put_user_inatomic(data.v[1], SWIZ_PTR(p++));
-			ret |= __put_user_inatomic(data.v[2], SWIZ_PTR(p++));
-			ret |= __put_user_inatomic(data.v[3], SWIZ_PTR(p++));
 		case 4:
-			ret |= __put_user_inatomic(data.v[4], SWIZ_PTR(p++));
-			ret |= __put_user_inatomic(data.v[5], SWIZ_PTR(p++));
+			start = offsetof(union data, x32.low32);
+			break;
 		case 2:
-			ret |= __put_user_inatomic(data.v[6], SWIZ_PTR(p++));
-			ret |= __put_user_inatomic(data.v[7], SWIZ_PTR(p++));
+			start = offsetof(union data, x16.low16);
+			break;
 		}
+
+		ret = 0;
+		p = (unsigned long)addr;
+
+		for (i = 0; i < nb; i++)
+			ret |= __put_user_inatomic(data.v[start + i],
+						   SWIZ_PTR(p++));
+
 		if (unlikely(ret))
 			return -EFAULT;
 	} else if (flags & F)
-		current->thread.TS_FPR(reg) = data.dd;
+		current->thread.TS_FPR(reg) = data.ll;
 	else
 		regs->gpr[reg] = data.ll;
 
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 502c7a4..e60a369 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -90,16 +90,17 @@
 	DEFINE(THREAD_NORMSAVES, offsetof(struct thread_struct, normsave[0]));
 #endif
 	DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode));
-	DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
-	DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr));
+	DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fp_state));
+	DEFINE(THREAD_FPSAVEAREA, offsetof(struct thread_struct, fp_save_area));
+	DEFINE(FPSTATE_FPSCR, offsetof(struct thread_fp_state, fpscr));
 #ifdef CONFIG_ALTIVEC
-	DEFINE(THREAD_VR0, offsetof(struct thread_struct, vr[0]));
+	DEFINE(THREAD_VRSTATE, offsetof(struct thread_struct, vr_state));
+	DEFINE(THREAD_VRSAVEAREA, offsetof(struct thread_struct, vr_save_area));
 	DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave));
-	DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr));
 	DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr));
+	DEFINE(VRSTATE_VSCR, offsetof(struct thread_vr_state, vscr));
 #endif /* CONFIG_ALTIVEC */
 #ifdef CONFIG_VSX
-	DEFINE(THREAD_VSR0, offsetof(struct thread_struct, fpr));
 	DEFINE(THREAD_USED_VSR, offsetof(struct thread_struct, used_vsr));
 #endif /* CONFIG_VSX */
 #ifdef CONFIG_PPC64
@@ -114,7 +115,7 @@
 #endif /* CONFIG_SPE */
 #endif /* CONFIG_PPC64 */
 #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
-	DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, dbcr0));
+	DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, debug.dbcr0));
 #endif
 #ifdef CONFIG_KVM_BOOK3S_32_HANDLER
 	DEFINE(THREAD_KVM_SVCPU, offsetof(struct thread_struct, kvm_shadow_vcpu));
@@ -143,20 +144,12 @@
 	DEFINE(THREAD_TM_PPR, offsetof(struct thread_struct, tm_ppr));
 	DEFINE(THREAD_TM_DSCR, offsetof(struct thread_struct, tm_dscr));
 	DEFINE(PT_CKPT_REGS, offsetof(struct thread_struct, ckpt_regs));
-	DEFINE(THREAD_TRANSACT_VR0, offsetof(struct thread_struct,
-					 transact_vr[0]));
-	DEFINE(THREAD_TRANSACT_VSCR, offsetof(struct thread_struct,
-					  transact_vscr));
+	DEFINE(THREAD_TRANSACT_VRSTATE, offsetof(struct thread_struct,
+						 transact_vr));
 	DEFINE(THREAD_TRANSACT_VRSAVE, offsetof(struct thread_struct,
 					    transact_vrsave));
-	DEFINE(THREAD_TRANSACT_FPR0, offsetof(struct thread_struct,
-					  transact_fpr[0]));
-	DEFINE(THREAD_TRANSACT_FPSCR, offsetof(struct thread_struct,
-					   transact_fpscr));
-#ifdef CONFIG_VSX
-	DEFINE(THREAD_TRANSACT_VSR0, offsetof(struct thread_struct,
-					  transact_fpr[0]));
-#endif
+	DEFINE(THREAD_TRANSACT_FPSTATE, offsetof(struct thread_struct,
+						 transact_fp));
 	/* Local pt_regs on stack for Transactional Memory funcs. */
 	DEFINE(TM_FRAME_SIZE, STACK_FRAME_OVERHEAD +
 	       sizeof(struct pt_regs) + 16);
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index 55593ee..1fb331d 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -327,11 +327,11 @@
 	/* Isolate the PHB and send event */
 	eeh_pe_state_mark(phb_pe, EEH_PE_ISOLATED);
 	eeh_serialize_unlock(flags);
-	eeh_send_failure_event(phb_pe);
 
 	pr_err("EEH: PHB#%x failure detected\n",
 		phb_pe->phb->global_number);
 	dump_stack();
+	eeh_send_failure_event(phb_pe);
 
 	return 1;
 out:
@@ -454,8 +454,6 @@
 	eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
 	eeh_serialize_unlock(flags);
 
-	eeh_send_failure_event(pe);
-
 	/* Most EEH events are due to device driver bugs.  Having
 	 * a stack trace will help the device-driver authors figure
 	 * out what happened.  So print that out.
@@ -464,6 +462,8 @@
 		pe->addr, pe->phb->global_number);
 	dump_stack();
 
+	eeh_send_failure_event(pe);
+
 	return 1;
 
 dn_unlock:
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index c04cdf7..bbfb029 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -673,9 +673,7 @@
 
 resume_kernel:
 	/* check current_thread_info, _TIF_EMULATE_STACK_STORE */
-	CURRENT_THREAD_INFO(r9, r1)
-	ld	r8,TI_FLAGS(r9)
-	andis.	r8,r8,_TIF_EMULATE_STACK_STORE@h
+	andis.	r8,r4,_TIF_EMULATE_STACK_STORE@h
 	beq+	1f
 
 	addi	r8,r1,INT_FRAME_SIZE	/* Get the kprobed function entry */
@@ -820,6 +818,12 @@
 	andi.	r0,r3,MSR_RI
 	beq-	unrecov_restore
 
+	/* Load PPR from thread struct before we clear MSR:RI */
+BEGIN_FTR_SECTION
+	ld	r2,PACACURRENT(r13)
+	ld	r2,TASKTHREADPPR(r2)
+END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
+
 	/*
 	 * Clear RI before restoring r13.  If we are returning to
 	 * userspace and we take an exception after restoring r13,
@@ -840,8 +844,10 @@
 	 */
 	andi.	r0,r3,MSR_PR
 	beq	1f
+BEGIN_FTR_SECTION
+	mtspr	SPRN_PPR,r2	/* Restore PPR */
+END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
 	ACCOUNT_CPU_USER_EXIT(r2, r4)
-	RESTORE_PPR(r2, r4)
 	REST_GPR(13, r1)
 1:
 	mtspr	SPRN_SRR1,r3
@@ -1017,7 +1023,7 @@
 	
         li      r9,1
         rldicr  r9,r9,MSR_SF_LG,(63-MSR_SF_LG)
-	ori	r9,r9,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP|MSR_RI
+	ori	r9,r9,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP|MSR_RI|MSR_LE
 	andc	r6,r0,r9
 	sync				/* disable interrupts so SRR0/1 */
 	mtmsrd	r0			/* don't get trashed */
@@ -1032,6 +1038,8 @@
 	b	.	/* prevent speculative execution */
 
 _STATIC(rtas_return_loc)
+	FIXUP_ENDIAN
+
 	/* relocation is off at this point */
 	GET_PACA(r4)
 	clrldi	r4,r4,2			/* convert to realmode address */
@@ -1103,28 +1111,30 @@
 	std	r10,_CCR(r1)
 	std	r11,_MSR(r1)
 
-	/* Get the PROM entrypoint */
-	mtlr	r4
+	/* Put PROM address in SRR0 */
+	mtsrr0	r4
 
-	/* Switch MSR to 32 bits mode
+	/* Setup our trampoline return addr in LR */
+	bcl	20,31,$+4
+0:	mflr	r4
+	addi	r4,r4,(1f - 0b)
+       	mtlr	r4
+
+	/* Prepare a 32-bit mode big endian MSR
 	 */
 #ifdef CONFIG_PPC_BOOK3E
 	rlwinm	r11,r11,0,1,31
-	mtmsr	r11
+	mtsrr1	r11
+	rfi
 #else /* CONFIG_PPC_BOOK3E */
-        mfmsr   r11
-        li      r12,1
-        rldicr  r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
-        andc    r11,r11,r12
-        li      r12,1
-        rldicr  r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
-        andc    r11,r11,r12
-        mtmsrd  r11
+	LOAD_REG_IMMEDIATE(r12, MSR_SF | MSR_ISF | MSR_LE)
+	andc	r11,r11,r12
+	mtsrr1	r11
+	rfid
 #endif /* CONFIG_PPC_BOOK3E */
-        isync
 
-	/* Enter PROM here... */
-	blrl
+1:	/* Return from OF */
+	FIXUP_ENDIAN
 
 	/* Just make sure that r1 top 32 bits didn't get
 	 * corrupt by OF
diff --git a/arch/powerpc/kernel/epapr_paravirt.c b/arch/powerpc/kernel/epapr_paravirt.c
index 6300c13..7898be9 100644
--- a/arch/powerpc/kernel/epapr_paravirt.c
+++ b/arch/powerpc/kernel/epapr_paravirt.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/of.h>
+#include <linux/of_fdt.h>
 #include <asm/epapr_hcalls.h>
 #include <asm/cacheflush.h>
 #include <asm/code-patching.h>
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 2d06704..e775156 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -399,7 +399,7 @@
 
 /* Altivec Unavailable Interrupt */
 	START_EXCEPTION(altivec_unavailable);
-	NORMAL_EXCEPTION_PROLOG(0x200, BOOKE_INTERRUPT_ALTIVEC_UNAVAIL,
+	NORMAL_EXCEPTION_PROLOG(0x200, BOOKE_INTERRUPT_SPE_ALTIVEC_UNAVAIL,
 				PROLOG_ADDITION_NONE)
 	/* we can probably do a shorter exception entry for that one... */
 	EXCEPTION_COMMON(0x200, PACA_EXGEN, INTS_KEEP)
@@ -421,7 +421,8 @@
 
 /* AltiVec Assist */
 	START_EXCEPTION(altivec_assist);
-	NORMAL_EXCEPTION_PROLOG(0x220, BOOKE_INTERRUPT_ALTIVEC_ASSIST,
+	NORMAL_EXCEPTION_PROLOG(0x220,
+				BOOKE_INTERRUPT_SPE_FP_DATA_ALTIVEC_ASSIST,
 				PROLOG_ADDITION_NONE)
 	EXCEPTION_COMMON(0x220, PACA_EXGEN, INTS_DISABLE)
 	bl	.save_nvgprs
@@ -607,6 +608,7 @@
 	NORMAL_EXCEPTION_PROLOG(0x260, BOOKE_INTERRUPT_PERFORMANCE_MONITOR,
 				PROLOG_ADDITION_NONE)
 	EXCEPTION_COMMON(0x260, PACA_EXGEN, INTS_DISABLE)
+	CHECK_NAPPING()
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	.performance_monitor_exception
 	b	.ret_from_except_lite
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S
index caeaabf..f7f5b8b 100644
--- a/arch/powerpc/kernel/fpu.S
+++ b/arch/powerpc/kernel/fpu.S
@@ -35,15 +35,6 @@
 2:	REST_32VSRS(n,c,base);						\
 3:
 
-#define __REST_32FPVSRS_TRANSACT(n,c,base)				\
-BEGIN_FTR_SECTION							\
-	b	2f;							\
-END_FTR_SECTION_IFSET(CPU_FTR_VSX);					\
-	REST_32FPRS_TRANSACT(n,base);					\
-	b	3f;							\
-2:	REST_32VSRS_TRANSACT(n,c,base);					\
-3:
-
 #define __SAVE_32FPVSRS(n,c,base)					\
 BEGIN_FTR_SECTION							\
 	b	2f;							\
@@ -54,40 +45,12 @@
 3:
 #else
 #define __REST_32FPVSRS(n,b,base)	REST_32FPRS(n, base)
-#define __REST_32FPVSRS_TRANSACT(n,b,base)	REST_32FPRS(n, base)
 #define __SAVE_32FPVSRS(n,b,base)	SAVE_32FPRS(n, base)
 #endif
 #define REST_32FPVSRS(n,c,base) __REST_32FPVSRS(n,__REG_##c,__REG_##base)
-#define REST_32FPVSRS_TRANSACT(n,c,base) \
-	__REST_32FPVSRS_TRANSACT(n,__REG_##c,__REG_##base)
 #define SAVE_32FPVSRS(n,c,base) __SAVE_32FPVSRS(n,__REG_##c,__REG_##base)
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-/*
- * Wrapper to call load_up_fpu from C.
- * void do_load_up_fpu(struct pt_regs *regs);
- */
-_GLOBAL(do_load_up_fpu)
-	mflr	r0
-	std	r0, 16(r1)
-	stdu	r1, -112(r1)
-
-	subi	r6, r3, STACK_FRAME_OVERHEAD
-	/* load_up_fpu expects r12=MSR, r13=PACA, and returns
-	 * with r12 = new MSR.
-	 */
-	ld	r12,_MSR(r6)
-	GET_PACA(r13)
-
-	bl	load_up_fpu
-	std	r12,_MSR(r6)
-
-	ld	r0, 112+16(r1)
-	addi	r1, r1, 112
-	mtlr	r0
-	blr
-
-
 /* void do_load_up_transact_fpu(struct thread_struct *thread)
  *
  * This is similar to load_up_fpu but for the transactional version of the FP
@@ -105,9 +68,10 @@
 	SYNC
 	MTMSRD(r5)
 
-	lfd	fr0,THREAD_TRANSACT_FPSCR(r3)
+	addi	r7,r3,THREAD_TRANSACT_FPSTATE
+	lfd	fr0,FPSTATE_FPSCR(r7)
 	MTFSF_L(fr0)
-	REST_32FPVSRS_TRANSACT(0, R4, R3)
+	REST_32FPVSRS(0, R4, R7)
 
 	/* FP/VSX off again */
 	MTMSRD(r6)
@@ -117,11 +81,33 @@
 #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
 
 /*
+ * Load state from memory into FP registers including FPSCR.
+ * Assumes the caller has enabled FP in the MSR.
+ */
+_GLOBAL(load_fp_state)
+	lfd	fr0,FPSTATE_FPSCR(r3)
+	MTFSF_L(fr0)
+	REST_32FPVSRS(0, R4, R3)
+	blr
+
+/*
+ * Store FP state into memory, including FPSCR
+ * Assumes the caller has enabled FP in the MSR.
+ */
+_GLOBAL(store_fp_state)
+	SAVE_32FPVSRS(0, R4, R3)
+	mffs	fr0
+	stfd	fr0,FPSTATE_FPSCR(r3)
+	blr
+
+/*
  * This task wants to use the FPU now.
  * On UP, disable FP for the task which had the FPU previously,
  * and save its floating-point registers in its thread_struct.
  * Load up this task's FP registers from its thread_struct,
  * enable the FPU for the current task and return to the task.
+ * Note that on 32-bit this can only use registers that will be
+ * restored by fast_exception_return, i.e. r3 - r6, r10 and r11.
  */
 _GLOBAL(load_up_fpu)
 	mfmsr	r5
@@ -147,9 +133,10 @@
 	beq	1f
 	toreal(r4)
 	addi	r4,r4,THREAD		/* want last_task_used_math->thread */
-	SAVE_32FPVSRS(0, R5, R4)
+	addi	r10,r4,THREAD_FPSTATE
+	SAVE_32FPVSRS(0, R5, R10)
 	mffs	fr0
-	stfd	fr0,THREAD_FPSCR(r4)
+	stfd	fr0,FPSTATE_FPSCR(r10)
 	PPC_LL	r5,PT_REGS(r4)
 	toreal(r5)
 	PPC_LL	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
@@ -160,7 +147,7 @@
 #endif /* CONFIG_SMP */
 	/* enable use of FP after return */
 #ifdef CONFIG_PPC32
-	mfspr	r5,SPRN_SPRG_THREAD		/* current task's THREAD (phys) */
+	mfspr	r5,SPRN_SPRG_THREAD	/* current task's THREAD (phys) */
 	lwz	r4,THREAD_FPEXC_MODE(r5)
 	ori	r9,r9,MSR_FP		/* enable FP for current */
 	or	r9,r9,r4
@@ -172,9 +159,10 @@
 	or	r12,r12,r4
 	std	r12,_MSR(r1)
 #endif
-	lfd	fr0,THREAD_FPSCR(r5)
+	addi	r10,r5,THREAD_FPSTATE
+	lfd	fr0,FPSTATE_FPSCR(r10)
 	MTFSF_L(fr0)
-	REST_32FPVSRS(0, R4, R5)
+	REST_32FPVSRS(0, R4, R10)
 #ifndef CONFIG_SMP
 	subi	r4,r5,THREAD
 	fromreal(r4)
@@ -206,11 +194,15 @@
 	PPC_LCMPI	0,r3,0
 	beqlr-				/* if no previous owner, done */
 	addi	r3,r3,THREAD	        /* want THREAD of task */
+	PPC_LL	r6,THREAD_FPSAVEAREA(r3)
 	PPC_LL	r5,PT_REGS(r3)
-	PPC_LCMPI	0,r5,0
-	SAVE_32FPVSRS(0, R4 ,R3)
+	PPC_LCMPI	0,r6,0
+	bne	2f
+	addi	r6,r3,THREAD_FPSTATE
+2:	PPC_LCMPI	0,r5,0
+	SAVE_32FPVSRS(0, R4, R6)
 	mffs	fr0
-	stfd	fr0,THREAD_FPSCR(r3)
+	stfd	fr0,FPSTATE_FPSCR(r6)
 	beq	1f
 	PPC_LL	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
 	li	r3,MSR_FP|MSR_FE0|MSR_FE1
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c
index 1fb7856..9b27b29 100644
--- a/arch/powerpc/kernel/ftrace.c
+++ b/arch/powerpc/kernel/ftrace.c
@@ -174,7 +174,11 @@
 
 	pr_devel(" %08x %08x\n", jmp[0], jmp[1]);
 
+#ifdef __LITTLE_ENDIAN__
+	ptr = ((unsigned long)jmp[1] << 32) + jmp[0];
+#else
 	ptr = ((unsigned long)jmp[0] << 32) + jmp[1];
+#endif
 
 	/* This should match what was called */
 	if (ptr != ppc_function_entry((void *)addr)) {
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 3d11d80..2ae41ab 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -68,6 +68,7 @@
 _GLOBAL(__start)
 	/* NOP this out unconditionally */
 BEGIN_FTR_SECTION
+	FIXUP_ENDIAN
 	b	.__start_initialization_multiplatform
 END_FTR_SECTION(0, 1)
 
@@ -115,6 +116,7 @@
  */
 	.globl	__secondary_hold
 __secondary_hold:
+	FIXUP_ENDIAN
 #ifndef CONFIG_PPC_BOOK3E
 	mfmsr	r24
 	ori	r24,r24,MSR_RI
@@ -205,6 +207,7 @@
  * as SCOM before entry).
  */
 _GLOBAL(generic_secondary_smp_init)
+	FIXUP_ENDIAN
 	mr	r24,r3
 	mr	r25,r4
 
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 1b92a97..7ee876d 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -858,6 +858,9 @@
 	addis	r11, r11, 0x0080	/* Add 8M */
 	mtspr	SPRN_MD_RPN, r11
 
+	addi	r10, r10, 0x0100
+	mtspr	SPRN_MD_CTR, r10
+
 	addis	r8, r8, 0x0080		/* Add 8M */
 	mtspr	SPRN_MD_EPN, r8
 	mtspr	SPRN_MD_TWC, r9
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 289afaf..f45726a1 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -555,27 +555,27 @@
 #ifdef CONFIG_SPE
 	/* SPE Unavailable */
 	START_EXCEPTION(SPEUnavailable)
-	NORMAL_EXCEPTION_PROLOG(SPE_UNAVAIL)
+	NORMAL_EXCEPTION_PROLOG(SPE_ALTIVEC_UNAVAIL)
 	beq	1f
 	bl	load_up_spe
 	b	fast_exception_return
 1:	addi	r3,r1,STACK_FRAME_OVERHEAD
 	EXC_XFER_EE_LITE(0x2010, KernelSPE)
 #else
-	EXCEPTION(0x2020, SPE_UNAVAIL, SPEUnavailable, \
+	EXCEPTION(0x2020, SPE_ALTIVEC_UNAVAIL, SPEUnavailable, \
 		  unknown_exception, EXC_XFER_EE)
 #endif /* CONFIG_SPE */
 
 	/* SPE Floating Point Data */
 #ifdef CONFIG_SPE
-	EXCEPTION(0x2030, SPE_FP_DATA, SPEFloatingPointData, \
-		  SPEFloatingPointException, EXC_XFER_EE);
+	EXCEPTION(0x2030, SPE_FP_DATA_ALTIVEC_ASSIST, SPEFloatingPointData,
+		  SPEFloatingPointException, EXC_XFER_EE)
 
 	/* SPE Floating Point Round */
 	EXCEPTION(0x2050, SPE_FP_ROUND, SPEFloatingPointRound, \
 		  SPEFloatingPointRoundException, EXC_XFER_EE)
 #else
-	EXCEPTION(0x2040, SPE_FP_DATA, SPEFloatingPointData, \
+	EXCEPTION(0x2040, SPE_FP_DATA_ALTIVEC_ASSIST, SPEFloatingPointData,
 		  unknown_exception, EXC_XFER_EE)
 	EXCEPTION(0x2050, SPE_FP_ROUND, SPEFloatingPointRound, \
 		  unknown_exception, EXC_XFER_EE)
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index 16a7c23..1114d13 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -292,6 +292,7 @@
 		return rc;
 	return count;
 }
+static BUS_ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe);
 
 static ssize_t ibmebus_store_remove(struct bus_type *bus,
 				    const char *buf, size_t count)
@@ -317,13 +318,14 @@
 		return -ENODEV;
 	}
 }
+static BUS_ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove);
 
-
-static struct bus_attribute ibmebus_bus_attrs[] = {
-	__ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe),
-	__ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove),
-	__ATTR_NULL
+static struct attribute *ibmbus_bus_attrs[] = {
+	&bus_attr_probe.attr,
+	&bus_attr_remove.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(ibmbus_bus);
 
 static int ibmebus_bus_bus_match(struct device *dev, struct device_driver *drv)
 {
@@ -713,7 +715,7 @@
 struct bus_type ibmebus_bus_type = {
 	.name      = "ibmebus",
 	.uevent    = of_device_uevent_modalias,
-	.bus_attrs = ibmebus_bus_attrs,
+	.bus_groups = ibmbus_bus_groups,
 	.match     = ibmebus_bus_bus_match,
 	.probe     = ibmebus_bus_device_probe,
 	.remove    = ibmebus_bus_device_remove,
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 57d286a..ba01656 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -495,14 +495,15 @@
 void do_IRQ(struct pt_regs *regs)
 {
 	struct pt_regs *old_regs = set_irq_regs(regs);
-	struct thread_info *curtp, *irqtp;
+	struct thread_info *curtp, *irqtp, *sirqtp;
 
 	/* Switch to the irq stack to handle this */
 	curtp = current_thread_info();
 	irqtp = hardirq_ctx[raw_smp_processor_id()];
+	sirqtp = softirq_ctx[raw_smp_processor_id()];
 
 	/* Already there ? */
-	if (unlikely(curtp == irqtp)) {
+	if (unlikely(curtp == irqtp || curtp == sirqtp)) {
 		__do_irq(regs);
 		set_irq_regs(old_regs);
 		return;
@@ -593,7 +594,7 @@
 	}
 }
 
-static inline void do_softirq_onstack(void)
+void do_softirq_own_stack(void)
 {
 	struct thread_info *curtp, *irqtp;
 
@@ -611,21 +612,6 @@
 		set_bits(irqtp->flags, &curtp->flags);
 }
 
-void do_softirq(void)
-{
-	unsigned long flags;
-
-	if (in_interrupt())
-		return;
-
-	local_irq_save(flags);
-
-	if (local_softirq_pending())
-		do_softirq_onstack();
-
-	local_irq_restore(flags);
-}
-
 irq_hw_number_t virq_to_hw(unsigned int virq)
 {
 	struct irq_data *irq_data = irq_get_irq_data(virq);
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
index c1eef24..83e89d3 100644
--- a/arch/powerpc/kernel/kgdb.c
+++ b/arch/powerpc/kernel/kgdb.c
@@ -151,15 +151,16 @@
 	return 1;
 }
 
+static DEFINE_PER_CPU(struct thread_info, kgdb_thread_info);
 static int kgdb_singlestep(struct pt_regs *regs)
 {
 	struct thread_info *thread_info, *exception_thread_info;
-	struct thread_info *backup_current_thread_info;
+	struct thread_info *backup_current_thread_info =
+		&__get_cpu_var(kgdb_thread_info);
 
 	if (user_mode(regs))
 		return 0;
 
-	backup_current_thread_info = kmalloc(sizeof(struct thread_info), GFP_KERNEL);
 	/*
 	 * On Book E and perhaps other processors, singlestep is handled on
 	 * the critical exception stack.  This causes current_thread_info()
@@ -185,7 +186,6 @@
 		/* Restore current_thread_info lastly. */
 		memcpy(exception_thread_info, backup_current_thread_info, sizeof *thread_info);
 
-	kfree(backup_current_thread_info);
 	return 1;
 }
 
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index 22e88dd..40bd7bd 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -35,7 +35,7 @@
 	phys_addr_t			taddr;
 } legacy_serial_infos[MAX_LEGACY_SERIAL_PORTS];
 
-static struct __initdata of_device_id legacy_serial_parents[] = {
+static struct of_device_id legacy_serial_parents[] __initdata = {
 	{.type = "soc",},
 	{.type = "tsi-bridge",},
 	{.type = "opb", },
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c
index 611acdf..be4e6d6 100644
--- a/arch/powerpc/kernel/machine_kexec_64.c
+++ b/arch/powerpc/kernel/machine_kexec_64.c
@@ -312,7 +312,7 @@
  */
 struct paca_struct kexec_paca;
 
-/* Our assembly helper, in kexec_stub.S */
+/* Our assembly helper, in misc_64.S */
 extern void kexec_sequence(void *newstack, unsigned long start,
 			   void *image, void *control,
 			   void (*clear_all)(void)) __noreturn;
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 2b0ad98..e47d268 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -659,6 +659,20 @@
 	blr
 
 /*
+ * 64-bit comparison: __cmpdi2(s64 a, s64 b)
+ * Returns 0 if a < b, 1 if a == b, 2 if a > b.
+ */
+_GLOBAL(__cmpdi2)
+	cmpw	r3,r5
+	li	r3,1
+	bne	1f
+	cmplw	r4,r6
+	beqlr
+1:	li	r3,0
+	bltlr
+	li	r3,2
+	blr
+/*
  * 64-bit comparison: __ucmpdi2(u64 a, u64 b)
  * Returns 0 if a < b, 1 if a == b, 2 if a > b.
  */
diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c
index 2d27570..9547381 100644
--- a/arch/powerpc/kernel/module.c
+++ b/arch/powerpc/kernel/module.c
@@ -25,8 +25,7 @@
 #include <asm/uaccess.h>
 #include <asm/firmware.h>
 #include <linux/sort.h>
-
-#include "setup.h"
+#include <asm/setup.h>
 
 LIST_HEAD(module_bug_list);
 
diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c
index 2e3200c..6cff040 100644
--- a/arch/powerpc/kernel/module_32.c
+++ b/arch/powerpc/kernel/module_32.c
@@ -26,8 +26,7 @@
 #include <linux/cache.h>
 #include <linux/bug.h>
 #include <linux/sort.h>
-
-#include "setup.h"
+#include <asm/setup.h>
 
 #if 0
 #define DEBUGP printk
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index 6ee59a0..12664c1 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -26,8 +26,7 @@
 #include <asm/firmware.h>
 #include <asm/code-patching.h>
 #include <linux/sort.h>
-
-#include "setup.h"
+#include <asm/setup.h>
 
 /* FIXME: We don't do .init separately.  To do this, we'd need to have
    a separate r2 value in the init and core section, and stub between
@@ -62,6 +61,16 @@
    r2) into the stub. */
 static struct ppc64_stub_entry ppc64_stub =
 { .jump = {
+#ifdef __LITTLE_ENDIAN__
+	0x00, 0x00, 0x82, 0x3d, /* addis   r12,r2, <high> */
+	0x00, 0x00, 0x8c, 0x39, /* addi    r12,r12, <low> */
+	/* Save current r2 value in magic place on the stack. */
+	0x28, 0x00, 0x41, 0xf8, /* std     r2,40(r1) */
+	0x20, 0x00, 0x6c, 0xe9, /* ld      r11,32(r12) */
+	0x28, 0x00, 0x4c, 0xe8, /* ld      r2,40(r12) */
+	0xa6, 0x03, 0x69, 0x7d, /* mtctr   r11 */
+	0x20, 0x04, 0x80, 0x4e  /* bctr */
+#else
 	0x3d, 0x82, 0x00, 0x00, /* addis   r12,r2, <high> */
 	0x39, 0x8c, 0x00, 0x00, /* addi    r12,r12, <low> */
 	/* Save current r2 value in magic place on the stack. */
@@ -70,6 +79,7 @@
 	0xe8, 0x4c, 0x00, 0x28, /* ld      r2,40(r12) */
 	0x7d, 0x69, 0x03, 0xa6, /* mtctr   r11 */
 	0x4e, 0x80, 0x04, 0x20  /* bctr */
+#endif
 } };
 
 /* Count how many different 24-bit relocations (different symbol,
@@ -269,8 +279,13 @@
 
 	*entry = ppc64_stub;
 
+#ifdef __LITTLE_ENDIAN__
+	loc1 = (Elf64_Half *)&entry->jump[0];
+	loc2 = (Elf64_Half *)&entry->jump[4];
+#else
 	loc1 = (Elf64_Half *)&entry->jump[2];
 	loc2 = (Elf64_Half *)&entry->jump[6];
+#endif
 
 	/* Stub uses address relative to r2. */
 	reladdr = (unsigned long)entry - my_r2(sechdrs, me);
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 8213ee1..fd82c28 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -223,9 +223,13 @@
 {
 	loff_t tmp_index;
 	int rc;
-	
+	struct nvram_header phead;
+
+	memcpy(&phead, &part->header, NVRAM_HEADER_LEN);
+	phead.length = cpu_to_be16(phead.length);
+
 	tmp_index = part->index;
-	rc = ppc_md.nvram_write((char *)&part->header, NVRAM_HEADER_LEN, &tmp_index); 
+	rc = ppc_md.nvram_write((char *)&phead, NVRAM_HEADER_LEN, &tmp_index);
 
 	return rc;
 }
@@ -505,6 +509,8 @@
 
 		memcpy(&phead, header, NVRAM_HEADER_LEN);
 
+		phead.length = be16_to_cpu(phead.length);
+
 		err = 0;
 		c_sum = nvram_checksum(&phead);
 		if (c_sum != phead.checksum) {
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 3fc16e3..0620eaa 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -46,7 +46,7 @@
 static struct lppaca *extra_lppacas;
 static long __initdata lppaca_size;
 
-static void allocate_lppacas(int nr_cpus, unsigned long limit)
+static void __init allocate_lppacas(int nr_cpus, unsigned long limit)
 {
 	if (nr_cpus <= NR_LPPACAS)
 		return;
@@ -57,7 +57,7 @@
 						 PAGE_SIZE, limit));
 }
 
-static struct lppaca *new_lppaca(int cpu)
+static struct lppaca * __init new_lppaca(int cpu)
 {
 	struct lppaca *lp;
 
@@ -70,7 +70,7 @@
 	return lp;
 }
 
-static void free_lppacas(void)
+static void __init free_lppacas(void)
 {
 	long new_size = 0, nr;
 
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 905a24b..a1e3e40 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -228,7 +228,7 @@
  */
 static int pci_read_irq_line(struct pci_dev *pci_dev)
 {
-	struct of_irq oirq;
+	struct of_phandle_args oirq;
 	unsigned int virq;
 
 	pr_debug("PCI: Try to map irq for %s...\n", pci_name(pci_dev));
@@ -237,7 +237,7 @@
 	memset(&oirq, 0xff, sizeof(oirq));
 #endif
 	/* Try to get a mapping from the device-tree */
-	if (of_irq_map_pci(pci_dev, &oirq)) {
+	if (of_irq_parse_pci(pci_dev, &oirq)) {
 		u8 line, pin;
 
 		/* If that fails, lets fallback to what is in the config
@@ -263,11 +263,10 @@
 			irq_set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
 	} else {
 		pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
-			 oirq.size, oirq.specifier[0], oirq.specifier[1],
-			 of_node_full_name(oirq.controller));
+			 oirq.args_count, oirq.args[0], oirq.args[1],
+			 of_node_full_name(oirq.np));
 
-		virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
-					     oirq.size);
+		virq = irq_create_of_mapping(&oirq);
 	}
 	if(virq == NO_IRQ) {
 		pr_debug(" Failed to map !\n");
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c
index 4368ec6..ac0b034 100644
--- a/arch/powerpc/kernel/pci_of_scan.c
+++ b/arch/powerpc/kernel/pci_of_scan.c
@@ -302,7 +302,7 @@
 			    struct device_node *dn)
 {
 	struct pci_dev *dev = NULL;
-	const u32 *reg;
+	const __be32 *reg;
 	int reglen, devfn;
 
 	pr_debug("  * %s\n", dn->full_name);
@@ -312,7 +312,7 @@
 	reg = of_get_property(dn, "reg", &reglen);
 	if (reg == NULL || reglen < 20)
 		return NULL;
-	devfn = (reg[0] >> 8) & 0xff;
+	devfn = (of_read_number(reg, 1) >> 8) & 0xff;
 
 	/* Check if the PCI device is already there */
 	dev = pci_get_slot(bus, devfn);
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 21646db..3bd77ed 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -79,10 +79,12 @@
 EXPORT_SYMBOL(strcmp);
 EXPORT_SYMBOL(strncmp);
 
+#ifndef CONFIG_GENERIC_CSUM
 EXPORT_SYMBOL(csum_partial);
 EXPORT_SYMBOL(csum_partial_copy_generic);
 EXPORT_SYMBOL(ip_fast_csum);
 EXPORT_SYMBOL(csum_tcpudp_magic);
+#endif
 
 EXPORT_SYMBOL(__copy_tofrom_user);
 EXPORT_SYMBOL(__clear_user);
@@ -98,9 +100,13 @@
 
 #ifdef CONFIG_PPC_FPU
 EXPORT_SYMBOL(giveup_fpu);
+EXPORT_SYMBOL(load_fp_state);
+EXPORT_SYMBOL(store_fp_state);
 #endif
 #ifdef CONFIG_ALTIVEC
 EXPORT_SYMBOL(giveup_altivec);
+EXPORT_SYMBOL(load_vr_state);
+EXPORT_SYMBOL(store_vr_state);
 #endif /* CONFIG_ALTIVEC */
 #ifdef CONFIG_VSX
 EXPORT_SYMBOL(giveup_vsx);
@@ -143,10 +149,14 @@
 EXPORT_SYMBOL(__lshrdi3);
 int __ucmpdi2(unsigned long long, unsigned long long);
 EXPORT_SYMBOL(__ucmpdi2);
+int __cmpdi2(long long, long long);
+EXPORT_SYMBOL(__cmpdi2);
 #endif
 long long __bswapdi2(long long);
 EXPORT_SYMBOL(__bswapdi2);
+#ifdef __BIG_ENDIAN__
 EXPORT_SYMBOL(memcpy);
+#endif
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memmove);
 EXPORT_SYMBOL(memcmp);
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 96d2fdf..75c2d10 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -314,28 +314,28 @@
  */
 static void set_debug_reg_defaults(struct thread_struct *thread)
 {
-	thread->iac1 = thread->iac2 = 0;
+	thread->debug.iac1 = thread->debug.iac2 = 0;
 #if CONFIG_PPC_ADV_DEBUG_IACS > 2
-	thread->iac3 = thread->iac4 = 0;
+	thread->debug.iac3 = thread->debug.iac4 = 0;
 #endif
-	thread->dac1 = thread->dac2 = 0;
+	thread->debug.dac1 = thread->debug.dac2 = 0;
 #if CONFIG_PPC_ADV_DEBUG_DVCS > 0
-	thread->dvc1 = thread->dvc2 = 0;
+	thread->debug.dvc1 = thread->debug.dvc2 = 0;
 #endif
-	thread->dbcr0 = 0;
+	thread->debug.dbcr0 = 0;
 #ifdef CONFIG_BOOKE
 	/*
 	 * Force User/Supervisor bits to b11 (user-only MSR[PR]=1)
 	 */
-	thread->dbcr1 = DBCR1_IAC1US | DBCR1_IAC2US |	\
+	thread->debug.dbcr1 = DBCR1_IAC1US | DBCR1_IAC2US |
 			DBCR1_IAC3US | DBCR1_IAC4US;
 	/*
 	 * Force Data Address Compare User/Supervisor bits to be User-only
 	 * (0b11 MSR[PR]=1) and set all other bits in DBCR2 register to be 0.
 	 */
-	thread->dbcr2 = DBCR2_DAC1US | DBCR2_DAC2US;
+	thread->debug.dbcr2 = DBCR2_DAC1US | DBCR2_DAC2US;
 #else
-	thread->dbcr1 = 0;
+	thread->debug.dbcr1 = 0;
 #endif
 }
 
@@ -348,22 +348,22 @@
 	 */
 	mtmsr(mfmsr() & ~MSR_DE);
 
-	mtspr(SPRN_IAC1, thread->iac1);
-	mtspr(SPRN_IAC2, thread->iac2);
+	mtspr(SPRN_IAC1, thread->debug.iac1);
+	mtspr(SPRN_IAC2, thread->debug.iac2);
 #if CONFIG_PPC_ADV_DEBUG_IACS > 2
-	mtspr(SPRN_IAC3, thread->iac3);
-	mtspr(SPRN_IAC4, thread->iac4);
+	mtspr(SPRN_IAC3, thread->debug.iac3);
+	mtspr(SPRN_IAC4, thread->debug.iac4);
 #endif
-	mtspr(SPRN_DAC1, thread->dac1);
-	mtspr(SPRN_DAC2, thread->dac2);
+	mtspr(SPRN_DAC1, thread->debug.dac1);
+	mtspr(SPRN_DAC2, thread->debug.dac2);
 #if CONFIG_PPC_ADV_DEBUG_DVCS > 0
-	mtspr(SPRN_DVC1, thread->dvc1);
-	mtspr(SPRN_DVC2, thread->dvc2);
+	mtspr(SPRN_DVC1, thread->debug.dvc1);
+	mtspr(SPRN_DVC2, thread->debug.dvc2);
 #endif
-	mtspr(SPRN_DBCR0, thread->dbcr0);
-	mtspr(SPRN_DBCR1, thread->dbcr1);
+	mtspr(SPRN_DBCR0, thread->debug.dbcr0);
+	mtspr(SPRN_DBCR1, thread->debug.dbcr1);
 #ifdef CONFIG_BOOKE
-	mtspr(SPRN_DBCR2, thread->dbcr2);
+	mtspr(SPRN_DBCR2, thread->debug.dbcr2);
 #endif
 }
 /*
@@ -371,12 +371,13 @@
  * debug registers, set the debug registers from the values
  * stored in the new thread.
  */
-static void switch_booke_debug_regs(struct thread_struct *new_thread)
+void switch_booke_debug_regs(struct thread_struct *new_thread)
 {
-	if ((current->thread.dbcr0 & DBCR0_IDM)
-		|| (new_thread->dbcr0 & DBCR0_IDM))
+	if ((current->thread.debug.dbcr0 & DBCR0_IDM)
+		|| (new_thread->debug.dbcr0 & DBCR0_IDM))
 			prime_debug_regs(new_thread);
 }
+EXPORT_SYMBOL_GPL(switch_booke_debug_regs);
 #else	/* !CONFIG_PPC_ADV_DEBUG_REGS */
 #ifndef CONFIG_HAVE_HW_BREAKPOINT
 static void set_debug_reg_defaults(struct thread_struct *thread)
@@ -596,12 +597,13 @@
 	struct task_struct *new)
 {
 	struct thread_struct *new_thread, *old_thread;
-	unsigned long flags;
 	struct task_struct *last;
 #ifdef CONFIG_PPC_BOOK3S_64
 	struct ppc64_tlb_batch *batch;
 #endif
 
+	WARN_ON(!irqs_disabled());
+
 	/* Back up the TAR across context switches.
 	 * Note that the TAR is not available for use in the kernel.  (To
 	 * provide this, the TAR should be backed up/restored on exception
@@ -721,8 +723,6 @@
 	}
 #endif /* CONFIG_PPC_BOOK3S_64 */
 
-	local_irq_save(flags);
-
 	/*
 	 * We can't take a PMU exception inside _switch() since there is a
 	 * window where the kernel stack SLB and the kernel stack are out
@@ -742,8 +742,6 @@
 	}
 #endif /* CONFIG_PPC_BOOK3S_64 */
 
-	local_irq_restore(flags);
-
 	return last;
 }
 
@@ -1008,6 +1006,11 @@
 	p->thread.ptrace_bps[0] = NULL;
 #endif
 
+	p->thread.fp_save_area = NULL;
+#ifdef CONFIG_ALTIVEC
+	p->thread.vr_save_area = NULL;
+#endif
+
 #ifdef CONFIG_PPC_STD_MMU_64
 	if (mmu_has_feature(MMU_FTR_SLB)) {
 		unsigned long sp_vsid;
@@ -1113,12 +1116,12 @@
 #ifdef CONFIG_VSX
 	current->thread.used_vsr = 0;
 #endif
-	memset(current->thread.fpr, 0, sizeof(current->thread.fpr));
-	current->thread.fpscr.val = 0;
+	memset(&current->thread.fp_state, 0, sizeof(current->thread.fp_state));
+	current->thread.fp_save_area = NULL;
 #ifdef CONFIG_ALTIVEC
-	memset(current->thread.vr, 0, sizeof(current->thread.vr));
-	memset(&current->thread.vscr, 0, sizeof(current->thread.vscr));
-	current->thread.vscr.u[3] = 0x00010000; /* Java mode disabled */
+	memset(&current->thread.vr_state, 0, sizeof(current->thread.vr_state));
+	current->thread.vr_state.vscr.u[3] = 0x00010000; /* Java mode disabled */
+	current->thread.vr_save_area = NULL;
 	current->thread.vrsave = 0;
 	current->thread.used_vr = 0;
 #endif /* CONFIG_ALTIVEC */
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index b7634ce..f3a4709 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -546,15 +546,6 @@
 	memblock_add(base, size);
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
-{
-	initrd_start = (unsigned long)__va(start);
-	initrd_end = (unsigned long)__va(end);
-	initrd_below_start_ok = 1;
-}
-#endif
-
 static void __init early_reserve_mem_dt(void)
 {
 	unsigned long i, len, dt_root;
@@ -761,37 +752,6 @@
  *******/
 
 /**
- *	of_find_next_cache_node - Find a node's subsidiary cache
- *	@np:	node of type "cpu" or "cache"
- *
- *	Returns a node pointer with refcount incremented, use
- *	of_node_put() on it when done.  Caller should hold a reference
- *	to np.
- */
-struct device_node *of_find_next_cache_node(struct device_node *np)
-{
-	struct device_node *child;
-	const phandle *handle;
-
-	handle = of_get_property(np, "l2-cache", NULL);
-	if (!handle)
-		handle = of_get_property(np, "next-level-cache", NULL);
-
-	if (handle)
-		return of_find_node_by_phandle(*handle);
-
-	/* OF on pmac has nodes instead of properties named "l2-cache"
-	 * beneath CPU nodes.
-	 */
-	if (!strcmp(np->type, "cpu"))
-		for_each_child_of_node(np, child)
-			if (!strcmp(child->type, "cache"))
-				return child;
-
-	return NULL;
-}
-
-/**
  * of_get_ibm_chip_id - Returns the IBM "chip-id" of a device
  * @np: device node of the device
  *
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 5fe2842..cb64a6e 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -858,7 +858,8 @@
 {
 	ihandle root;
 	prom_arg_t ret;
-	__be32 *cores;
+	u32 cores;
+	unsigned char *ptcores;
 
 	root = call_prom("open", 1, 1, ADDR("/"));
 	if (root != 0) {
@@ -868,15 +869,30 @@
 		 * (we assume this is the same for all cores) and use it to
 		 * divide NR_CPUS.
 		 */
-		cores = (__be32 *)&ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET];
-		if (be32_to_cpup(cores) != NR_CPUS) {
+
+		/* The core value may start at an odd address. If such a word
+		 * access is made at a cache line boundary, this leads to an
+		 * exception which may not be handled at this time.
+		 * Forcing a per byte access to avoid exception.
+		 */
+		ptcores = &ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET];
+		cores = 0;
+		cores |= ptcores[0] << 24;
+		cores |= ptcores[1] << 16;
+		cores |= ptcores[2] << 8;
+		cores |= ptcores[3];
+		if (cores != NR_CPUS) {
 			prom_printf("WARNING ! "
 				    "ibm_architecture_vec structure inconsistent: %lu!\n",
-				    be32_to_cpup(cores));
+				    cores);
 		} else {
-			*cores = cpu_to_be32(DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads()));
+			cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
 			prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n",
-				    be32_to_cpup(cores), NR_CPUS);
+				    cores, NR_CPUS);
+			ptcores[0] = (cores >> 24) & 0xff;
+			ptcores[1] = (cores >> 16) & 0xff;
+			ptcores[2] = (cores >> 8) & 0xff;
+			ptcores[3] = cores & 0xff;
 		}
 
 		/* try calling the ibm,client-architecture-support method */
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 9a0d24c..75fb404 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -362,7 +362,7 @@
 		   void *kbuf, void __user *ubuf)
 {
 #ifdef CONFIG_VSX
-	double buf[33];
+	u64 buf[33];
 	int i;
 #endif
 	flush_fp_to_thread(target);
@@ -371,15 +371,15 @@
 	/* copy to local buffer then write that out */
 	for (i = 0; i < 32 ; i++)
 		buf[i] = target->thread.TS_FPR(i);
-	memcpy(&buf[32], &target->thread.fpscr, sizeof(double));
+	buf[32] = target->thread.fp_state.fpscr;
 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
 
 #else
-	BUILD_BUG_ON(offsetof(struct thread_struct, fpscr) !=
-		     offsetof(struct thread_struct, TS_FPR(32)));
+	BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
+		     offsetof(struct thread_fp_state, fpr[32][0]));
 
 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-				   &target->thread.fpr, 0, -1);
+				   &target->thread.fp_state, 0, -1);
 #endif
 }
 
@@ -388,7 +388,7 @@
 		   const void *kbuf, const void __user *ubuf)
 {
 #ifdef CONFIG_VSX
-	double buf[33];
+	u64 buf[33];
 	int i;
 #endif
 	flush_fp_to_thread(target);
@@ -400,14 +400,14 @@
 		return i;
 	for (i = 0; i < 32 ; i++)
 		target->thread.TS_FPR(i) = buf[i];
-	memcpy(&target->thread.fpscr, &buf[32], sizeof(double));
+	target->thread.fp_state.fpscr = buf[32];
 	return 0;
 #else
-	BUILD_BUG_ON(offsetof(struct thread_struct, fpscr) !=
-		     offsetof(struct thread_struct, TS_FPR(32)));
+	BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
+		     offsetof(struct thread_fp_state, fpr[32][0]));
 
 	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-				  &target->thread.fpr, 0, -1);
+				  &target->thread.fp_state, 0, -1);
 #endif
 }
 
@@ -440,11 +440,11 @@
 
 	flush_altivec_to_thread(target);
 
-	BUILD_BUG_ON(offsetof(struct thread_struct, vscr) !=
-		     offsetof(struct thread_struct, vr[32]));
+	BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
+		     offsetof(struct thread_vr_state, vr[32]));
 
 	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-				  &target->thread.vr, 0,
+				  &target->thread.vr_state, 0,
 				  33 * sizeof(vector128));
 	if (!ret) {
 		/*
@@ -471,11 +471,12 @@
 
 	flush_altivec_to_thread(target);
 
-	BUILD_BUG_ON(offsetof(struct thread_struct, vscr) !=
-		     offsetof(struct thread_struct, vr[32]));
+	BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
+		     offsetof(struct thread_vr_state, vr[32]));
 
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-				 &target->thread.vr, 0, 33 * sizeof(vector128));
+				 &target->thread.vr_state, 0,
+				 33 * sizeof(vector128));
 	if (!ret && count > 0) {
 		/*
 		 * We use only the first word of vrsave.
@@ -514,13 +515,13 @@
 		   unsigned int pos, unsigned int count,
 		   void *kbuf, void __user *ubuf)
 {
-	double buf[32];
+	u64 buf[32];
 	int ret, i;
 
 	flush_vsx_to_thread(target);
 
 	for (i = 0; i < 32 ; i++)
-		buf[i] = target->thread.fpr[i][TS_VSRLOWOFFSET];
+		buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
 	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 				  buf, 0, 32 * sizeof(double));
 
@@ -531,7 +532,7 @@
 		   unsigned int pos, unsigned int count,
 		   const void *kbuf, const void __user *ubuf)
 {
-	double buf[32];
+	u64 buf[32];
 	int ret,i;
 
 	flush_vsx_to_thread(target);
@@ -539,7 +540,7 @@
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 				 buf, 0, 32 * sizeof(double));
 	for (i = 0; i < 32 ; i++)
-		target->thread.fpr[i][TS_VSRLOWOFFSET] = buf[i];
+		target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
 
 
 	return ret;
@@ -657,7 +658,7 @@
 #endif
 #ifdef CONFIG_SPE
 	[REGSET_SPE] = {
-		.n = 35,
+		.core_note_type = NT_PPC_SPE, .n = 35,
 		.size = sizeof(u32), .align = sizeof(u32),
 		.active = evr_active, .get = evr_get, .set = evr_set
 	},
@@ -854,8 +855,8 @@
 
 	if (regs != NULL) {
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
-		task->thread.dbcr0 &= ~DBCR0_BT;
-		task->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC;
+		task->thread.debug.dbcr0 &= ~DBCR0_BT;
+		task->thread.debug.dbcr0 |= DBCR0_IDM | DBCR0_IC;
 		regs->msr |= MSR_DE;
 #else
 		regs->msr &= ~MSR_BE;
@@ -871,8 +872,8 @@
 
 	if (regs != NULL) {
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
-		task->thread.dbcr0 &= ~DBCR0_IC;
-		task->thread.dbcr0 = DBCR0_IDM | DBCR0_BT;
+		task->thread.debug.dbcr0 &= ~DBCR0_IC;
+		task->thread.debug.dbcr0 = DBCR0_IDM | DBCR0_BT;
 		regs->msr |= MSR_DE;
 #else
 		regs->msr &= ~MSR_SE;
@@ -894,16 +895,16 @@
 		 * And, after doing so, if all debug flags are off, turn
 		 * off DBCR0(IDM) and MSR(DE) .... Torez
 		 */
-		task->thread.dbcr0 &= ~DBCR0_IC;
+		task->thread.debug.dbcr0 &= ~(DBCR0_IC|DBCR0_BT);
 		/*
 		 * Test to see if any of the DBCR_ACTIVE_EVENTS bits are set.
 		 */
-		if (!DBCR_ACTIVE_EVENTS(task->thread.dbcr0,
-					task->thread.dbcr1)) {
+		if (!DBCR_ACTIVE_EVENTS(task->thread.debug.dbcr0,
+					task->thread.debug.dbcr1)) {
 			/*
 			 * All debug events were off.....
 			 */
-			task->thread.dbcr0 &= ~DBCR0_IDM;
+			task->thread.debug.dbcr0 &= ~DBCR0_IDM;
 			regs->msr &= ~MSR_DE;
 		}
 #else
@@ -1022,14 +1023,14 @@
 	 */
 
 	/* DAC's hold the whole address without any mode flags */
-	task->thread.dac1 = data & ~0x3UL;
+	task->thread.debug.dac1 = data & ~0x3UL;
 
-	if (task->thread.dac1 == 0) {
+	if (task->thread.debug.dac1 == 0) {
 		dbcr_dac(task) &= ~(DBCR_DAC1R | DBCR_DAC1W);
-		if (!DBCR_ACTIVE_EVENTS(task->thread.dbcr0,
-					task->thread.dbcr1)) {
+		if (!DBCR_ACTIVE_EVENTS(task->thread.debug.dbcr0,
+					task->thread.debug.dbcr1)) {
 			task->thread.regs->msr &= ~MSR_DE;
-			task->thread.dbcr0 &= ~DBCR0_IDM;
+			task->thread.debug.dbcr0 &= ~DBCR0_IDM;
 		}
 		return 0;
 	}
@@ -1041,7 +1042,7 @@
 
 	/* Set the Internal Debugging flag (IDM bit 1) for the DBCR0
 	   register */
-	task->thread.dbcr0 |= DBCR0_IDM;
+	task->thread.debug.dbcr0 |= DBCR0_IDM;
 
 	/* Check for write and read flags and set DBCR0
 	   accordingly */
@@ -1071,10 +1072,10 @@
 			      struct ppc_hw_breakpoint *bp_info)
 {
 	int slot;
-	int slot1_in_use = ((child->thread.dbcr0 & DBCR0_IAC1) != 0);
-	int slot2_in_use = ((child->thread.dbcr0 & DBCR0_IAC2) != 0);
-	int slot3_in_use = ((child->thread.dbcr0 & DBCR0_IAC3) != 0);
-	int slot4_in_use = ((child->thread.dbcr0 & DBCR0_IAC4) != 0);
+	int slot1_in_use = ((child->thread.debug.dbcr0 & DBCR0_IAC1) != 0);
+	int slot2_in_use = ((child->thread.debug.dbcr0 & DBCR0_IAC2) != 0);
+	int slot3_in_use = ((child->thread.debug.dbcr0 & DBCR0_IAC3) != 0);
+	int slot4_in_use = ((child->thread.debug.dbcr0 & DBCR0_IAC4) != 0);
 
 	if (dbcr_iac_range(child) & DBCR_IAC12MODE)
 		slot2_in_use = 1;
@@ -1093,9 +1094,9 @@
 		/* We need a pair of IAC regsisters */
 		if ((!slot1_in_use) && (!slot2_in_use)) {
 			slot = 1;
-			child->thread.iac1 = bp_info->addr;
-			child->thread.iac2 = bp_info->addr2;
-			child->thread.dbcr0 |= DBCR0_IAC1;
+			child->thread.debug.iac1 = bp_info->addr;
+			child->thread.debug.iac2 = bp_info->addr2;
+			child->thread.debug.dbcr0 |= DBCR0_IAC1;
 			if (bp_info->addr_mode ==
 					PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE)
 				dbcr_iac_range(child) |= DBCR_IAC12X;
@@ -1104,9 +1105,9 @@
 #if CONFIG_PPC_ADV_DEBUG_IACS > 2
 		} else if ((!slot3_in_use) && (!slot4_in_use)) {
 			slot = 3;
-			child->thread.iac3 = bp_info->addr;
-			child->thread.iac4 = bp_info->addr2;
-			child->thread.dbcr0 |= DBCR0_IAC3;
+			child->thread.debug.iac3 = bp_info->addr;
+			child->thread.debug.iac4 = bp_info->addr2;
+			child->thread.debug.dbcr0 |= DBCR0_IAC3;
 			if (bp_info->addr_mode ==
 					PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE)
 				dbcr_iac_range(child) |= DBCR_IAC34X;
@@ -1126,30 +1127,30 @@
 			 */
 			if (slot2_in_use || (slot3_in_use == slot4_in_use)) {
 				slot = 1;
-				child->thread.iac1 = bp_info->addr;
-				child->thread.dbcr0 |= DBCR0_IAC1;
+				child->thread.debug.iac1 = bp_info->addr;
+				child->thread.debug.dbcr0 |= DBCR0_IAC1;
 				goto out;
 			}
 		}
 		if (!slot2_in_use) {
 			slot = 2;
-			child->thread.iac2 = bp_info->addr;
-			child->thread.dbcr0 |= DBCR0_IAC2;
+			child->thread.debug.iac2 = bp_info->addr;
+			child->thread.debug.dbcr0 |= DBCR0_IAC2;
 #if CONFIG_PPC_ADV_DEBUG_IACS > 2
 		} else if (!slot3_in_use) {
 			slot = 3;
-			child->thread.iac3 = bp_info->addr;
-			child->thread.dbcr0 |= DBCR0_IAC3;
+			child->thread.debug.iac3 = bp_info->addr;
+			child->thread.debug.dbcr0 |= DBCR0_IAC3;
 		} else if (!slot4_in_use) {
 			slot = 4;
-			child->thread.iac4 = bp_info->addr;
-			child->thread.dbcr0 |= DBCR0_IAC4;
+			child->thread.debug.iac4 = bp_info->addr;
+			child->thread.debug.dbcr0 |= DBCR0_IAC4;
 #endif
 		} else
 			return -ENOSPC;
 	}
 out:
-	child->thread.dbcr0 |= DBCR0_IDM;
+	child->thread.debug.dbcr0 |= DBCR0_IDM;
 	child->thread.regs->msr |= MSR_DE;
 
 	return slot;
@@ -1159,49 +1160,49 @@
 {
 	switch (slot) {
 	case 1:
-		if ((child->thread.dbcr0 & DBCR0_IAC1) == 0)
+		if ((child->thread.debug.dbcr0 & DBCR0_IAC1) == 0)
 			return -ENOENT;
 
 		if (dbcr_iac_range(child) & DBCR_IAC12MODE) {
 			/* address range - clear slots 1 & 2 */
-			child->thread.iac2 = 0;
+			child->thread.debug.iac2 = 0;
 			dbcr_iac_range(child) &= ~DBCR_IAC12MODE;
 		}
-		child->thread.iac1 = 0;
-		child->thread.dbcr0 &= ~DBCR0_IAC1;
+		child->thread.debug.iac1 = 0;
+		child->thread.debug.dbcr0 &= ~DBCR0_IAC1;
 		break;
 	case 2:
-		if ((child->thread.dbcr0 & DBCR0_IAC2) == 0)
+		if ((child->thread.debug.dbcr0 & DBCR0_IAC2) == 0)
 			return -ENOENT;
 
 		if (dbcr_iac_range(child) & DBCR_IAC12MODE)
 			/* used in a range */
 			return -EINVAL;
-		child->thread.iac2 = 0;
-		child->thread.dbcr0 &= ~DBCR0_IAC2;
+		child->thread.debug.iac2 = 0;
+		child->thread.debug.dbcr0 &= ~DBCR0_IAC2;
 		break;
 #if CONFIG_PPC_ADV_DEBUG_IACS > 2
 	case 3:
-		if ((child->thread.dbcr0 & DBCR0_IAC3) == 0)
+		if ((child->thread.debug.dbcr0 & DBCR0_IAC3) == 0)
 			return -ENOENT;
 
 		if (dbcr_iac_range(child) & DBCR_IAC34MODE) {
 			/* address range - clear slots 3 & 4 */
-			child->thread.iac4 = 0;
+			child->thread.debug.iac4 = 0;
 			dbcr_iac_range(child) &= ~DBCR_IAC34MODE;
 		}
-		child->thread.iac3 = 0;
-		child->thread.dbcr0 &= ~DBCR0_IAC3;
+		child->thread.debug.iac3 = 0;
+		child->thread.debug.dbcr0 &= ~DBCR0_IAC3;
 		break;
 	case 4:
-		if ((child->thread.dbcr0 & DBCR0_IAC4) == 0)
+		if ((child->thread.debug.dbcr0 & DBCR0_IAC4) == 0)
 			return -ENOENT;
 
 		if (dbcr_iac_range(child) & DBCR_IAC34MODE)
 			/* Used in a range */
 			return -EINVAL;
-		child->thread.iac4 = 0;
-		child->thread.dbcr0 &= ~DBCR0_IAC4;
+		child->thread.debug.iac4 = 0;
+		child->thread.debug.dbcr0 &= ~DBCR0_IAC4;
 		break;
 #endif
 	default:
@@ -1231,18 +1232,18 @@
 			dbcr_dac(child) |= DBCR_DAC1R;
 		if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
 			dbcr_dac(child) |= DBCR_DAC1W;
-		child->thread.dac1 = (unsigned long)bp_info->addr;
+		child->thread.debug.dac1 = (unsigned long)bp_info->addr;
 #if CONFIG_PPC_ADV_DEBUG_DVCS > 0
 		if (byte_enable) {
-			child->thread.dvc1 =
+			child->thread.debug.dvc1 =
 				(unsigned long)bp_info->condition_value;
-			child->thread.dbcr2 |=
+			child->thread.debug.dbcr2 |=
 				((byte_enable << DBCR2_DVC1BE_SHIFT) |
 				 (condition_mode << DBCR2_DVC1M_SHIFT));
 		}
 #endif
 #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE
-	} else if (child->thread.dbcr2 & DBCR2_DAC12MODE) {
+	} else if (child->thread.debug.dbcr2 & DBCR2_DAC12MODE) {
 		/* Both dac1 and dac2 are part of a range */
 		return -ENOSPC;
 #endif
@@ -1252,19 +1253,19 @@
 			dbcr_dac(child) |= DBCR_DAC2R;
 		if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
 			dbcr_dac(child) |= DBCR_DAC2W;
-		child->thread.dac2 = (unsigned long)bp_info->addr;
+		child->thread.debug.dac2 = (unsigned long)bp_info->addr;
 #if CONFIG_PPC_ADV_DEBUG_DVCS > 0
 		if (byte_enable) {
-			child->thread.dvc2 =
+			child->thread.debug.dvc2 =
 				(unsigned long)bp_info->condition_value;
-			child->thread.dbcr2 |=
+			child->thread.debug.dbcr2 |=
 				((byte_enable << DBCR2_DVC2BE_SHIFT) |
 				 (condition_mode << DBCR2_DVC2M_SHIFT));
 		}
 #endif
 	} else
 		return -ENOSPC;
-	child->thread.dbcr0 |= DBCR0_IDM;
+	child->thread.debug.dbcr0 |= DBCR0_IDM;
 	child->thread.regs->msr |= MSR_DE;
 
 	return slot + 4;
@@ -1276,32 +1277,32 @@
 		if ((dbcr_dac(child) & (DBCR_DAC1R | DBCR_DAC1W)) == 0)
 			return -ENOENT;
 
-		child->thread.dac1 = 0;
+		child->thread.debug.dac1 = 0;
 		dbcr_dac(child) &= ~(DBCR_DAC1R | DBCR_DAC1W);
 #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE
-		if (child->thread.dbcr2 & DBCR2_DAC12MODE) {
-			child->thread.dac2 = 0;
-			child->thread.dbcr2 &= ~DBCR2_DAC12MODE;
+		if (child->thread.debug.dbcr2 & DBCR2_DAC12MODE) {
+			child->thread.debug.dac2 = 0;
+			child->thread.debug.dbcr2 &= ~DBCR2_DAC12MODE;
 		}
-		child->thread.dbcr2 &= ~(DBCR2_DVC1M | DBCR2_DVC1BE);
+		child->thread.debug.dbcr2 &= ~(DBCR2_DVC1M | DBCR2_DVC1BE);
 #endif
 #if CONFIG_PPC_ADV_DEBUG_DVCS > 0
-		child->thread.dvc1 = 0;
+		child->thread.debug.dvc1 = 0;
 #endif
 	} else if (slot == 2) {
 		if ((dbcr_dac(child) & (DBCR_DAC2R | DBCR_DAC2W)) == 0)
 			return -ENOENT;
 
 #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE
-		if (child->thread.dbcr2 & DBCR2_DAC12MODE)
+		if (child->thread.debug.dbcr2 & DBCR2_DAC12MODE)
 			/* Part of a range */
 			return -EINVAL;
-		child->thread.dbcr2 &= ~(DBCR2_DVC2M | DBCR2_DVC2BE);
+		child->thread.debug.dbcr2 &= ~(DBCR2_DVC2M | DBCR2_DVC2BE);
 #endif
 #if CONFIG_PPC_ADV_DEBUG_DVCS > 0
-		child->thread.dvc2 = 0;
+		child->thread.debug.dvc2 = 0;
 #endif
-		child->thread.dac2 = 0;
+		child->thread.debug.dac2 = 0;
 		dbcr_dac(child) &= ~(DBCR_DAC2R | DBCR_DAC2W);
 	} else
 		return -EINVAL;
@@ -1343,22 +1344,22 @@
 			return -EIO;
 	}
 
-	if (child->thread.dbcr0 &
+	if (child->thread.debug.dbcr0 &
 	    (DBCR0_DAC1R | DBCR0_DAC1W | DBCR0_DAC2R | DBCR0_DAC2W))
 		return -ENOSPC;
 
 	if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ)
-		child->thread.dbcr0 |= (DBCR0_DAC1R | DBCR0_IDM);
+		child->thread.debug.dbcr0 |= (DBCR0_DAC1R | DBCR0_IDM);
 	if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
-		child->thread.dbcr0 |= (DBCR0_DAC1W | DBCR0_IDM);
-	child->thread.dac1 = bp_info->addr;
-	child->thread.dac2 = bp_info->addr2;
+		child->thread.debug.dbcr0 |= (DBCR0_DAC1W | DBCR0_IDM);
+	child->thread.debug.dac1 = bp_info->addr;
+	child->thread.debug.dac2 = bp_info->addr2;
 	if (mode == PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE)
-		child->thread.dbcr2  |= DBCR2_DAC12M;
+		child->thread.debug.dbcr2  |= DBCR2_DAC12M;
 	else if (mode == PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE)
-		child->thread.dbcr2  |= DBCR2_DAC12MX;
+		child->thread.debug.dbcr2  |= DBCR2_DAC12MX;
 	else	/* PPC_BREAKPOINT_MODE_MASK */
-		child->thread.dbcr2  |= DBCR2_DAC12MM;
+		child->thread.debug.dbcr2  |= DBCR2_DAC12MM;
 	child->thread.regs->msr |= MSR_DE;
 
 	return 5;
@@ -1489,9 +1490,9 @@
 		rc = del_dac(child, (int)data - 4);
 
 	if (!rc) {
-		if (!DBCR_ACTIVE_EVENTS(child->thread.dbcr0,
-					child->thread.dbcr1)) {
-			child->thread.dbcr0 &= ~DBCR0_IDM;
+		if (!DBCR_ACTIVE_EVENTS(child->thread.debug.dbcr0,
+					child->thread.debug.dbcr1)) {
+			child->thread.debug.dbcr0 &= ~DBCR0_IDM;
 			child->thread.regs->msr &= ~MSR_DE;
 		}
 	}
@@ -1554,10 +1555,10 @@
 
 			flush_fp_to_thread(child);
 			if (fpidx < (PT_FPSCR - PT_FPR0))
-				tmp = ((unsigned long *)child->thread.fpr)
-					[fpidx * TS_FPRWIDTH];
+				memcpy(&tmp, &child->thread.fp_state.fpr,
+				       sizeof(long));
 			else
-				tmp = child->thread.fpscr.val;
+				tmp = child->thread.fp_state.fpscr;
 		}
 		ret = put_user(tmp, datalp);
 		break;
@@ -1587,10 +1588,10 @@
 
 			flush_fp_to_thread(child);
 			if (fpidx < (PT_FPSCR - PT_FPR0))
-				((unsigned long *)child->thread.fpr)
-					[fpidx * TS_FPRWIDTH] = data;
+				memcpy(&child->thread.fp_state.fpr, &data,
+				       sizeof(long));
 			else
-				child->thread.fpscr.val = data;
+				child->thread.fp_state.fpscr = data;
 			ret = 0;
 		}
 		break;
@@ -1669,7 +1670,7 @@
 		if (addr > 0)
 			break;
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
-		ret = put_user(child->thread.dac1, datalp);
+		ret = put_user(child->thread.debug.dac1, datalp);
 #else
 		dabr_fake = ((child->thread.hw_brk.address & (~HW_BRK_TYPE_DABR)) |
 			     (child->thread.hw_brk.type & HW_BRK_TYPE_DABR));
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
index f51599e..f52b7db 100644
--- a/arch/powerpc/kernel/ptrace32.c
+++ b/arch/powerpc/kernel/ptrace32.c
@@ -43,7 +43,6 @@
 #define FPRNUMBER(i) (((i) - PT_FPR0) >> 1)
 #define FPRHALF(i) (((i) - PT_FPR0) & 1)
 #define FPRINDEX(i) TS_FPRWIDTH * FPRNUMBER(i) * 2 + FPRHALF(i)
-#define FPRINDEX_3264(i) (TS_FPRWIDTH * ((i) - PT_FPR0))
 
 long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 			compat_ulong_t caddr, compat_ulong_t cdata)
@@ -105,7 +104,7 @@
 			 * to be an array of unsigned int (32 bits) - the
 			 * index passed in is based on this assumption.
 			 */
-			tmp = ((unsigned int *)child->thread.fpr)
+			tmp = ((unsigned int *)child->thread.fp_state.fpr)
 				[FPRINDEX(index)];
 		}
 		ret = put_user((unsigned int)tmp, (u32 __user *)data);
@@ -147,8 +146,7 @@
 		if (numReg >= PT_FPR0) {
 			flush_fp_to_thread(child);
 			/* get 64 bit FPR */
-			tmp = ((u64 *)child->thread.fpr)
-				[FPRINDEX_3264(numReg)];
+			tmp = child->thread.fp_state.fpr[numReg - PT_FPR0][0];
 		} else { /* register within PT_REGS struct */
 			unsigned long tmp2;
 			ret = ptrace_get_reg(child, numReg, &tmp2);
@@ -207,7 +205,7 @@
 			 * to be an array of unsigned int (32 bits) - the
 			 * index passed in is based on this assumption.
 			 */
-			((unsigned int *)child->thread.fpr)
+			((unsigned int *)child->thread.fp_state.fpr)
 				[FPRINDEX(index)] = data;
 			ret = 0;
 		}
@@ -251,8 +249,7 @@
 			u64 *tmp;
 			flush_fp_to_thread(child);
 			/* get 64 bit FPR ... */
-			tmp = &(((u64 *)child->thread.fpr)
-				[FPRINDEX_3264(numReg)]);
+			tmp = &child->thread.fp_state.fpr[numReg - PT_FPR0][0];
 			/* ... write the 32 bit part we want */
 			((u32 *)tmp)[index % 2] = data;
 			ret = 0;
@@ -269,7 +266,7 @@
 		if (addr > 0)
 			break;
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
-		ret = put_user(child->thread.dac1, (u32 __user *)data);
+		ret = put_user(child->thread.debug.dac1, (u32 __user *)data);
 #else
 		dabr_fake = (
 			(child->thread.hw_brk.address & (~HW_BRK_TYPE_DABR)) |
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index 6e7b7cd..7d4c717 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -223,7 +223,7 @@
 static int phb_set_bus_ranges(struct device_node *dev,
 			      struct pci_controller *phb)
 {
-	const int *bus_range;
+	const __be32 *bus_range;
 	unsigned int len;
 
 	bus_range = of_get_property(dev, "bus-range", &len);
@@ -231,8 +231,8 @@
 		return 1;
  	}
 
-	phb->first_busno =  bus_range[0];
-	phb->last_busno  =  bus_range[1];
+	phb->first_busno = be32_to_cpu(bus_range[0]);
+	phb->last_busno  = be32_to_cpu(bus_range[1]);
 
 	return 0;
 }
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 3d261c0..febc804 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -62,8 +62,6 @@
 #include <mm/mmu_decl.h>
 #include <asm/fadump.h>
 
-#include "setup.h"
-
 #ifdef DEBUG
 #include <asm/udbg.h>
 #define DBG(fmt...) udbg_printf(fmt)
diff --git a/arch/powerpc/kernel/setup.h b/arch/powerpc/kernel/setup.h
deleted file mode 100644
index 4c67ad7..0000000
--- a/arch/powerpc/kernel/setup.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _POWERPC_KERNEL_SETUP_H
-#define _POWERPC_KERNEL_SETUP_H
-
-void check_for_initrd(void);
-void do_init_bootmem(void);
-void setup_panic(void);
-extern int do_early_xmon;
-
-#endif /* _POWERPC_KERNEL_SETUP_H */
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index a4bbcae..b903dc5 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -40,8 +40,6 @@
 #include <asm/mmu_context.h>
 #include <asm/epapr_hcalls.h>
 
-#include "setup.h"
-
 #define DBG(fmt...)
 
 extern void bootx_init(unsigned long r4, unsigned long phys);
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 278ca93..4085aaa 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -68,8 +68,6 @@
 #include <asm/hugetlb.h>
 #include <asm/epapr_hcalls.h>
 
-#include "setup.h"
-
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
 #else
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 149cd58..749778e 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -265,27 +265,27 @@
 unsigned long copy_fpr_to_user(void __user *to,
 			       struct task_struct *task)
 {
-	double buf[ELF_NFPREG];
+	u64 buf[ELF_NFPREG];
 	int i;
 
 	/* save FPR copy to local buffer then write to the thread_struct */
 	for (i = 0; i < (ELF_NFPREG - 1) ; i++)
 		buf[i] = task->thread.TS_FPR(i);
-	memcpy(&buf[i], &task->thread.fpscr, sizeof(double));
+	buf[i] = task->thread.fp_state.fpscr;
 	return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double));
 }
 
 unsigned long copy_fpr_from_user(struct task_struct *task,
 				 void __user *from)
 {
-	double buf[ELF_NFPREG];
+	u64 buf[ELF_NFPREG];
 	int i;
 
 	if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double)))
 		return 1;
 	for (i = 0; i < (ELF_NFPREG - 1) ; i++)
 		task->thread.TS_FPR(i) = buf[i];
-	memcpy(&task->thread.fpscr, &buf[i], sizeof(double));
+	task->thread.fp_state.fpscr = buf[i];
 
 	return 0;
 }
@@ -293,25 +293,25 @@
 unsigned long copy_vsx_to_user(void __user *to,
 			       struct task_struct *task)
 {
-	double buf[ELF_NVSRHALFREG];
+	u64 buf[ELF_NVSRHALFREG];
 	int i;
 
 	/* save FPR copy to local buffer then write to the thread_struct */
 	for (i = 0; i < ELF_NVSRHALFREG; i++)
-		buf[i] = task->thread.fpr[i][TS_VSRLOWOFFSET];
+		buf[i] = task->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
 	return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double));
 }
 
 unsigned long copy_vsx_from_user(struct task_struct *task,
 				 void __user *from)
 {
-	double buf[ELF_NVSRHALFREG];
+	u64 buf[ELF_NVSRHALFREG];
 	int i;
 
 	if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double)))
 		return 1;
 	for (i = 0; i < ELF_NVSRHALFREG ; i++)
-		task->thread.fpr[i][TS_VSRLOWOFFSET] = buf[i];
+		task->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
 	return 0;
 }
 
@@ -319,27 +319,27 @@
 unsigned long copy_transact_fpr_to_user(void __user *to,
 				  struct task_struct *task)
 {
-	double buf[ELF_NFPREG];
+	u64 buf[ELF_NFPREG];
 	int i;
 
 	/* save FPR copy to local buffer then write to the thread_struct */
 	for (i = 0; i < (ELF_NFPREG - 1) ; i++)
 		buf[i] = task->thread.TS_TRANS_FPR(i);
-	memcpy(&buf[i], &task->thread.transact_fpscr, sizeof(double));
+	buf[i] = task->thread.transact_fp.fpscr;
 	return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double));
 }
 
 unsigned long copy_transact_fpr_from_user(struct task_struct *task,
 					  void __user *from)
 {
-	double buf[ELF_NFPREG];
+	u64 buf[ELF_NFPREG];
 	int i;
 
 	if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double)))
 		return 1;
 	for (i = 0; i < (ELF_NFPREG - 1) ; i++)
 		task->thread.TS_TRANS_FPR(i) = buf[i];
-	memcpy(&task->thread.transact_fpscr, &buf[i], sizeof(double));
+	task->thread.transact_fp.fpscr = buf[i];
 
 	return 0;
 }
@@ -347,25 +347,25 @@
 unsigned long copy_transact_vsx_to_user(void __user *to,
 				  struct task_struct *task)
 {
-	double buf[ELF_NVSRHALFREG];
+	u64 buf[ELF_NVSRHALFREG];
 	int i;
 
 	/* save FPR copy to local buffer then write to the thread_struct */
 	for (i = 0; i < ELF_NVSRHALFREG; i++)
-		buf[i] = task->thread.transact_fpr[i][TS_VSRLOWOFFSET];
+		buf[i] = task->thread.transact_fp.fpr[i][TS_VSRLOWOFFSET];
 	return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double));
 }
 
 unsigned long copy_transact_vsx_from_user(struct task_struct *task,
 					  void __user *from)
 {
-	double buf[ELF_NVSRHALFREG];
+	u64 buf[ELF_NVSRHALFREG];
 	int i;
 
 	if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double)))
 		return 1;
 	for (i = 0; i < ELF_NVSRHALFREG ; i++)
-		task->thread.transact_fpr[i][TS_VSRLOWOFFSET] = buf[i];
+		task->thread.transact_fp.fpr[i][TS_VSRLOWOFFSET] = buf[i];
 	return 0;
 }
 #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
@@ -373,14 +373,14 @@
 inline unsigned long copy_fpr_to_user(void __user *to,
 				      struct task_struct *task)
 {
-	return __copy_to_user(to, task->thread.fpr,
+	return __copy_to_user(to, task->thread.fp_state.fpr,
 			      ELF_NFPREG * sizeof(double));
 }
 
 inline unsigned long copy_fpr_from_user(struct task_struct *task,
 					void __user *from)
 {
-	return __copy_from_user(task->thread.fpr, from,
+	return __copy_from_user(task->thread.fp_state.fpr, from,
 			      ELF_NFPREG * sizeof(double));
 }
 
@@ -388,14 +388,14 @@
 inline unsigned long copy_transact_fpr_to_user(void __user *to,
 					 struct task_struct *task)
 {
-	return __copy_to_user(to, task->thread.transact_fpr,
+	return __copy_to_user(to, task->thread.transact_fp.fpr,
 			      ELF_NFPREG * sizeof(double));
 }
 
 inline unsigned long copy_transact_fpr_from_user(struct task_struct *task,
 						 void __user *from)
 {
-	return __copy_from_user(task->thread.transact_fpr, from,
+	return __copy_from_user(task->thread.transact_fp.fpr, from,
 				ELF_NFPREG * sizeof(double));
 }
 #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
@@ -423,7 +423,7 @@
 	/* save altivec registers */
 	if (current->thread.used_vr) {
 		flush_altivec_to_thread(current);
-		if (__copy_to_user(&frame->mc_vregs, current->thread.vr,
+		if (__copy_to_user(&frame->mc_vregs, &current->thread.vr_state,
 				   ELF_NVRREG * sizeof(vector128)))
 			return 1;
 		/* set MSR_VEC in the saved MSR value to indicate that
@@ -534,17 +534,17 @@
 	/* save altivec registers */
 	if (current->thread.used_vr) {
 		flush_altivec_to_thread(current);
-		if (__copy_to_user(&frame->mc_vregs, current->thread.vr,
+		if (__copy_to_user(&frame->mc_vregs, &current->thread.vr_state,
 				   ELF_NVRREG * sizeof(vector128)))
 			return 1;
 		if (msr & MSR_VEC) {
 			if (__copy_to_user(&tm_frame->mc_vregs,
-					   current->thread.transact_vr,
+					   &current->thread.transact_vr,
 					   ELF_NVRREG * sizeof(vector128)))
 				return 1;
 		} else {
 			if (__copy_to_user(&tm_frame->mc_vregs,
-					   current->thread.vr,
+					   &current->thread.vr_state,
 					   ELF_NVRREG * sizeof(vector128)))
 				return 1;
 		}
@@ -692,11 +692,12 @@
 	regs->msr &= ~MSR_VEC;
 	if (msr & MSR_VEC) {
 		/* restore altivec registers from the stack */
-		if (__copy_from_user(current->thread.vr, &sr->mc_vregs,
+		if (__copy_from_user(&current->thread.vr_state, &sr->mc_vregs,
 				     sizeof(sr->mc_vregs)))
 			return 1;
 	} else if (current->thread.used_vr)
-		memset(current->thread.vr, 0, ELF_NVRREG * sizeof(vector128));
+		memset(&current->thread.vr_state, 0,
+		       ELF_NVRREG * sizeof(vector128));
 
 	/* Always get VRSAVE back */
 	if (__get_user(current->thread.vrsave, (u32 __user *)&sr->mc_vregs[32]))
@@ -722,7 +723,7 @@
 			return 1;
 	} else if (current->thread.used_vsr)
 		for (i = 0; i < 32 ; i++)
-			current->thread.fpr[i][TS_VSRLOWOFFSET] = 0;
+			current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0;
 #endif /* CONFIG_VSX */
 	/*
 	 * force the process to reload the FP registers from
@@ -798,15 +799,16 @@
 	regs->msr &= ~MSR_VEC;
 	if (msr & MSR_VEC) {
 		/* restore altivec registers from the stack */
-		if (__copy_from_user(current->thread.vr, &sr->mc_vregs,
+		if (__copy_from_user(&current->thread.vr_state, &sr->mc_vregs,
 				     sizeof(sr->mc_vregs)) ||
-		    __copy_from_user(current->thread.transact_vr,
+		    __copy_from_user(&current->thread.transact_vr,
 				     &tm_sr->mc_vregs,
 				     sizeof(sr->mc_vregs)))
 			return 1;
 	} else if (current->thread.used_vr) {
-		memset(current->thread.vr, 0, ELF_NVRREG * sizeof(vector128));
-		memset(current->thread.transact_vr, 0,
+		memset(&current->thread.vr_state, 0,
+		       ELF_NVRREG * sizeof(vector128));
+		memset(&current->thread.transact_vr, 0,
 		       ELF_NVRREG * sizeof(vector128));
 	}
 
@@ -838,8 +840,8 @@
 			return 1;
 	} else if (current->thread.used_vsr)
 		for (i = 0; i < 32 ; i++) {
-			current->thread.fpr[i][TS_VSRLOWOFFSET] = 0;
-			current->thread.transact_fpr[i][TS_VSRLOWOFFSET] = 0;
+			current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0;
+			current->thread.transact_fp.fpr[i][TS_VSRLOWOFFSET] = 0;
 		}
 #endif /* CONFIG_VSX */
 
@@ -1030,7 +1032,7 @@
 		if (__put_user(0, &rt_sf->uc.uc_link))
 			goto badframe;
 
-	current->thread.fpscr.val = 0;	/* turn off all fp exceptions */
+	current->thread.fp_state.fpscr = 0;	/* turn off all fp exceptions */
 
 	/* create a stack frame for the caller of the handler */
 	newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16);
@@ -1045,8 +1047,9 @@
 	regs->gpr[5] = (unsigned long) &rt_sf->uc;
 	regs->gpr[6] = (unsigned long) rt_sf;
 	regs->nip = (unsigned long) ka->sa.sa_handler;
-	/* enter the signal handler in big-endian mode */
+	/* enter the signal handler in native-endian mode */
 	regs->msr &= ~MSR_LE;
+	regs->msr |= (MSR_KERNEL & MSR_LE);
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 	/* Remove TM bits from thread's MSR.  The MSR in the sigcontext
 	 * just indicates to userland that we were doing a transaction, but we
@@ -1309,7 +1312,7 @@
 	unsigned char tmp;
 	unsigned long new_msr = regs->msr;
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
-	unsigned long new_dbcr0 = current->thread.dbcr0;
+	unsigned long new_dbcr0 = current->thread.debug.dbcr0;
 #endif
 
 	for (i=0; i<ndbg; i++) {
@@ -1324,7 +1327,7 @@
 			} else {
 				new_dbcr0 &= ~DBCR0_IC;
 				if (!DBCR_ACTIVE_EVENTS(new_dbcr0,
-						current->thread.dbcr1)) {
+						current->thread.debug.dbcr1)) {
 					new_msr &= ~MSR_DE;
 					new_dbcr0 &= ~DBCR0_IDM;
 				}
@@ -1359,7 +1362,7 @@
 	   the user is really doing something wrong. */
 	regs->msr = new_msr;
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
-	current->thread.dbcr0 = new_dbcr0;
+	current->thread.debug.dbcr0 = new_dbcr0;
 #endif
 
 	if (!access_ok(VERIFY_READ, ctx, sizeof(*ctx))
@@ -1462,7 +1465,7 @@
 
 	regs->link = tramp;
 
-	current->thread.fpscr.val = 0;	/* turn off all fp exceptions */
+	current->thread.fp_state.fpscr = 0;	/* turn off all fp exceptions */
 
 	/* create a stack frame for the caller of the handler */
 	newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index f93ec28..b3c6157 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -103,7 +103,8 @@
 	if (current->thread.used_vr) {
 		flush_altivec_to_thread(current);
 		/* Copy 33 vec registers (vr0..31 and vscr) to the stack */
-		err |= __copy_to_user(v_regs, current->thread.vr, 33 * sizeof(vector128));
+		err |= __copy_to_user(v_regs, &current->thread.vr_state,
+				      33 * sizeof(vector128));
 		/* set MSR_VEC in the MSR value in the frame to indicate that sc->v_reg)
 		 * contains valid data.
 		 */
@@ -195,18 +196,18 @@
 	if (current->thread.used_vr) {
 		flush_altivec_to_thread(current);
 		/* Copy 33 vec registers (vr0..31 and vscr) to the stack */
-		err |= __copy_to_user(v_regs, current->thread.vr,
+		err |= __copy_to_user(v_regs, &current->thread.vr_state,
 				      33 * sizeof(vector128));
 		/* If VEC was enabled there are transactional VRs valid too,
 		 * else they're a copy of the checkpointed VRs.
 		 */
 		if (msr & MSR_VEC)
 			err |= __copy_to_user(tm_v_regs,
-					      current->thread.transact_vr,
+					      &current->thread.transact_vr,
 					      33 * sizeof(vector128));
 		else
 			err |= __copy_to_user(tm_v_regs,
-					      current->thread.vr,
+					      &current->thread.vr_state,
 					      33 * sizeof(vector128));
 
 		/* set MSR_VEC in the MSR value in the frame to indicate
@@ -349,10 +350,10 @@
 		return -EFAULT;
 	/* Copy 33 vec registers (vr0..31 and vscr) from the stack */
 	if (v_regs != NULL && (msr & MSR_VEC) != 0)
-		err |= __copy_from_user(current->thread.vr, v_regs,
+		err |= __copy_from_user(&current->thread.vr_state, v_regs,
 					33 * sizeof(vector128));
 	else if (current->thread.used_vr)
-		memset(current->thread.vr, 0, 33 * sizeof(vector128));
+		memset(&current->thread.vr_state, 0, 33 * sizeof(vector128));
 	/* Always get VRSAVE back */
 	if (v_regs != NULL)
 		err |= __get_user(current->thread.vrsave, (u32 __user *)&v_regs[33]);
@@ -374,7 +375,7 @@
 		err |= copy_vsx_from_user(current, v_regs);
 	else
 		for (i = 0; i < 32 ; i++)
-			current->thread.fpr[i][TS_VSRLOWOFFSET] = 0;
+			current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0;
 #endif
 	return err;
 }
@@ -468,14 +469,14 @@
 		return -EFAULT;
 	/* Copy 33 vec registers (vr0..31 and vscr) from the stack */
 	if (v_regs != NULL && tm_v_regs != NULL && (msr & MSR_VEC) != 0) {
-		err |= __copy_from_user(current->thread.vr, v_regs,
+		err |= __copy_from_user(&current->thread.vr_state, v_regs,
 					33 * sizeof(vector128));
-		err |= __copy_from_user(current->thread.transact_vr, tm_v_regs,
+		err |= __copy_from_user(&current->thread.transact_vr, tm_v_regs,
 					33 * sizeof(vector128));
 	}
 	else if (current->thread.used_vr) {
-		memset(current->thread.vr, 0, 33 * sizeof(vector128));
-		memset(current->thread.transact_vr, 0, 33 * sizeof(vector128));
+		memset(&current->thread.vr_state, 0, 33 * sizeof(vector128));
+		memset(&current->thread.transact_vr, 0, 33 * sizeof(vector128));
 	}
 	/* Always get VRSAVE back */
 	if (v_regs != NULL && tm_v_regs != NULL) {
@@ -507,8 +508,8 @@
 		err |= copy_transact_vsx_from_user(current, tm_v_regs);
 	} else {
 		for (i = 0; i < 32 ; i++) {
-			current->thread.fpr[i][TS_VSRLOWOFFSET] = 0;
-			current->thread.transact_fpr[i][TS_VSRLOWOFFSET] = 0;
+			current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0;
+			current->thread.transact_fp.fpr[i][TS_VSRLOWOFFSET] = 0;
 		}
 	}
 #endif
@@ -747,7 +748,7 @@
 		goto badframe;
 
 	/* Make sure signal handler doesn't get spurious FP exceptions */
-	current->thread.fpscr.val = 0;
+	current->thread.fp_state.fpscr = 0;
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 	/* Remove TM bits from thread's MSR.  The MSR in the sigcontext
 	 * just indicates to userland that we were doing a transaction, but we
@@ -773,8 +774,9 @@
 
 	/* Set up "regs" so we "return" to the signal handler. */
 	err |= get_user(regs->nip, &funct_desc_ptr->entry);
-	/* enter the signal handler in big-endian mode */
+	/* enter the signal handler in native-endian mode */
 	regs->msr &= ~MSR_LE;
+	regs->msr |= (MSR_KERNEL & MSR_LE);
 	regs->gpr[1] = newsp;
 	err |= get_user(regs->gpr[2], &funct_desc_ptr->toc);
 	regs->gpr[3] = signr;
diff --git a/arch/powerpc/kernel/swsusp_asm64.S b/arch/powerpc/kernel/swsusp_asm64.S
index 2204598..988f38d 100644
--- a/arch/powerpc/kernel/swsusp_asm64.S
+++ b/arch/powerpc/kernel/swsusp_asm64.S
@@ -114,7 +114,9 @@
 	SAVE_SPECIAL(MSR)
 	SAVE_SPECIAL(XER)
 #ifdef CONFIG_PPC_BOOK3S_64
+BEGIN_FW_FTR_SECTION
 	SAVE_SPECIAL(SDR1)
+END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR)
 #else
 	SAVE_SPR(TCR)
 
@@ -231,7 +233,9 @@
 	/* can't use RESTORE_SPECIAL(MSR) */
 	ld	r0, SL_MSR(r11)
 	mtmsrd	r0, 0
+BEGIN_FW_FTR_SECTION
 	RESTORE_SPECIAL(SDR1)
+END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR)
 #else
 	/* Restore SPRG1, be used to save paca */
 	ld	r0, SL_SPRG1(r11)
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S
index cd809ea..ef47bcbd 100644
--- a/arch/powerpc/kernel/tm.S
+++ b/arch/powerpc/kernel/tm.S
@@ -12,16 +12,15 @@
 #include <asm/reg.h>
 
 #ifdef CONFIG_VSX
-/* See fpu.S, this is very similar but to save/restore checkpointed FPRs/VSRs */
-#define __SAVE_32FPRS_VSRS_TRANSACT(n,c,base)	\
+/* See fpu.S, this is borrowed from there */
+#define __SAVE_32FPRS_VSRS(n,c,base)		\
 BEGIN_FTR_SECTION				\
 	b	2f;				\
 END_FTR_SECTION_IFSET(CPU_FTR_VSX);		\
-	SAVE_32FPRS_TRANSACT(n,base);		\
+	SAVE_32FPRS(n,base);			\
 	b	3f;				\
-2:	SAVE_32VSRS_TRANSACT(n,c,base);		\
+2:	SAVE_32VSRS(n,c,base);			\
 3:
-/* ...and this is just plain borrowed from there. */
 #define __REST_32FPRS_VSRS(n,c,base)		\
 BEGIN_FTR_SECTION				\
 	b	2f;				\
@@ -31,11 +30,11 @@
 2:	REST_32VSRS(n,c,base);			\
 3:
 #else
-#define __SAVE_32FPRS_VSRS_TRANSACT(n,c,base) SAVE_32FPRS_TRANSACT(n, base)
-#define __REST_32FPRS_VSRS(n,c,base)	      REST_32FPRS(n, base)
+#define __SAVE_32FPRS_VSRS(n,c,base)	SAVE_32FPRS(n, base)
+#define __REST_32FPRS_VSRS(n,c,base)	REST_32FPRS(n, base)
 #endif
-#define SAVE_32FPRS_VSRS_TRANSACT(n,c,base) \
-	__SAVE_32FPRS_VSRS_TRANSACT(n,__REG_##c,__REG_##base)
+#define SAVE_32FPRS_VSRS(n,c,base) \
+	__SAVE_32FPRS_VSRS(n,__REG_##c,__REG_##base)
 #define REST_32FPRS_VSRS(n,c,base) \
 	__REST_32FPRS_VSRS(n,__REG_##c,__REG_##base)
 
@@ -107,7 +106,7 @@
 _GLOBAL(tm_reclaim)
 	mfcr	r6
 	mflr	r0
-	std	r6, 8(r1)
+	stw	r6, 8(r1)
 	std	r0, 16(r1)
 	std	r2, 40(r1)
 	stdu	r1, -TM_FRAME_SIZE(r1)
@@ -157,10 +156,11 @@
 	andis.		r0, r4, MSR_VEC@h
 	beq	dont_backup_vec
 
-	SAVE_32VRS_TRANSACT(0, r6, r3)	/* r6 scratch, r3 thread */
+	addi	r7, r3, THREAD_TRANSACT_VRSTATE
+	SAVE_32VRS(0, r6, r7)	/* r6 scratch, r7 transact vr state */
 	mfvscr	vr0
-	li	r6, THREAD_TRANSACT_VSCR
-	stvx	vr0, r3, r6
+	li	r6, VRSTATE_VSCR
+	stvx	vr0, r7, r6
 dont_backup_vec:
 	mfspr	r0, SPRN_VRSAVE
 	std	r0, THREAD_TRANSACT_VRSAVE(r3)
@@ -168,10 +168,11 @@
 	andi.	r0, r4, MSR_FP
 	beq	dont_backup_fp
 
-	SAVE_32FPRS_VSRS_TRANSACT(0, R6, R3)	/* r6 scratch, r3 thread */
+	addi	r7, r3, THREAD_TRANSACT_FPSTATE
+	SAVE_32FPRS_VSRS(0, R6, R7)	/* r6 scratch, r7 transact fp state */
 
 	mffs    fr0
-	stfd    fr0,THREAD_TRANSACT_FPSCR(r3)
+	stfd    fr0,FPSTATE_FPSCR(r7)
 
 dont_backup_fp:
 	/* The moment we treclaim, ALL of our GPRs will switch
@@ -284,7 +285,7 @@
 	REST_NVGPRS(r1)
 
 	addi    r1, r1, TM_FRAME_SIZE
-	ld	r4, 8(r1)
+	lwz	r4, 8(r1)
 	ld	r0, 16(r1)
 	mtcr	r4
 	mtlr	r0
@@ -309,7 +310,7 @@
 _GLOBAL(tm_recheckpoint)
 	mfcr	r5
 	mflr	r0
-	std	r5, 8(r1)
+	stw	r5, 8(r1)
 	std	r0, 16(r1)
 	std	r2, 40(r1)
 	stdu	r1, -TM_FRAME_SIZE(r1)
@@ -358,10 +359,11 @@
 	andis.	r0, r4, MSR_VEC@h
 	beq	dont_restore_vec
 
-	li	r5, THREAD_VSCR
-	lvx	vr0, r3, r5
+	addi	r8, r3, THREAD_VRSTATE
+	li	r5, VRSTATE_VSCR
+	lvx	vr0, r8, r5
 	mtvscr	vr0
-	REST_32VRS(0, r5, r3)			/* r5 scratch, r3 THREAD ptr */
+	REST_32VRS(0, r5, r8)			/* r5 scratch, r8 ptr */
 dont_restore_vec:
 	ld	r5, THREAD_VRSAVE(r3)
 	mtspr	SPRN_VRSAVE, r5
@@ -370,9 +372,10 @@
 	andi.	r0, r4, MSR_FP
 	beq	dont_restore_fp
 
-	lfd	fr0, THREAD_FPSCR(r3)
+	addi	r8, r3, THREAD_FPSTATE
+	lfd	fr0, FPSTATE_FPSCR(r8)
 	MTFSF_L(fr0)
-	REST_32FPRS_VSRS(0, R4, R3)
+	REST_32FPRS_VSRS(0, R4, R8)
 
 dont_restore_fp:
 	mtmsr	r6				/* FP/Vec off again! */
@@ -441,7 +444,7 @@
 	REST_NVGPRS(r1)
 
 	addi    r1, r1, TM_FRAME_SIZE
-	ld	r4, 8(r1)
+	lwz	r4, 8(r1)
 	ld	r0, 16(r1)
 	mtcr	r4
 	mtlr	r0
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index f783c93..62c3dd8 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -351,8 +351,8 @@
 #define REASON_TRAP		ESR_PTR
 
 /* single-step stuff */
-#define single_stepping(regs)	(current->thread.dbcr0 & DBCR0_IC)
-#define clear_single_step(regs)	(current->thread.dbcr0 &= ~DBCR0_IC)
+#define single_stepping(regs)	(current->thread.debug.dbcr0 & DBCR0_IC)
+#define clear_single_step(regs)	(current->thread.debug.dbcr0 &= ~DBCR0_IC)
 
 #else
 /* On non-4xx, the reason for the machine check or program
@@ -816,7 +816,7 @@
 
 	flush_fp_to_thread(current);
 
-	code = __parse_fpscr(current->thread.fpscr.val);
+	code = __parse_fpscr(current->thread.fp_state.fpscr);
 
 	_exception(SIGFPE, regs, code, regs->nip);
 }
@@ -1018,6 +1018,13 @@
 		return emulate_isel(regs, instword);
 	}
 
+	/* Emulate sync instruction variants */
+	if ((instword & PPC_INST_SYNC_MASK) == PPC_INST_SYNC) {
+		PPC_WARN_EMULATED(sync, regs);
+		asm volatile("sync");
+		return 0;
+	}
+
 #ifdef CONFIG_PPC64
 	/* Emulate the mfspr rD, DSCR. */
 	if ((((instword & PPC_INST_MFSPR_DSCR_USER_MASK) ==
@@ -1069,7 +1076,7 @@
 		return 0;
 	case 1: {
 			int code = 0;
-			code = __parse_fpscr(current->thread.fpscr.val);
+			code = __parse_fpscr(current->thread.fp_state.fpscr);
 			_exception(SIGFPE, regs, code, regs->nip);
 			return 0;
 		}
@@ -1371,8 +1378,6 @@
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 
-extern void do_load_up_fpu(struct pt_regs *regs);
-
 void fp_unavailable_tm(struct pt_regs *regs)
 {
 	/* Note:  This does not handle any kind of FP laziness. */
@@ -1403,8 +1408,6 @@
 }
 
 #ifdef CONFIG_ALTIVEC
-extern void do_load_up_altivec(struct pt_regs *regs);
-
 void altivec_unavailable_tm(struct pt_regs *regs)
 {
 	/* See the comments in fp_unavailable_tm().  This function operates
@@ -1465,7 +1468,8 @@
 
 	if (!user_mode(regs)) {
 		debugger(regs);
-		die("Kernel Mode Software FPU Emulation", regs, SIGFPE);
+		die("Kernel Mode Unimplemented Instruction or SW FPU Emulation",
+			regs, SIGFPE);
 	}
 
 	if (!emulate_math(regs))
@@ -1486,7 +1490,7 @@
 	if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) {
 		dbcr_dac(current) &= ~(DBCR_DAC1R | DBCR_DAC1W);
 #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE
-		current->thread.dbcr2 &= ~DBCR2_DAC12MODE;
+		current->thread.debug.dbcr2 &= ~DBCR2_DAC12MODE;
 #endif
 		do_send_trap(regs, mfspr(SPRN_DAC1), debug_status, TRAP_HWBKPT,
 			     5);
@@ -1497,24 +1501,24 @@
 			     6);
 		changed |= 0x01;
 	}  else if (debug_status & DBSR_IAC1) {
-		current->thread.dbcr0 &= ~DBCR0_IAC1;
+		current->thread.debug.dbcr0 &= ~DBCR0_IAC1;
 		dbcr_iac_range(current) &= ~DBCR_IAC12MODE;
 		do_send_trap(regs, mfspr(SPRN_IAC1), debug_status, TRAP_HWBKPT,
 			     1);
 		changed |= 0x01;
 	}  else if (debug_status & DBSR_IAC2) {
-		current->thread.dbcr0 &= ~DBCR0_IAC2;
+		current->thread.debug.dbcr0 &= ~DBCR0_IAC2;
 		do_send_trap(regs, mfspr(SPRN_IAC2), debug_status, TRAP_HWBKPT,
 			     2);
 		changed |= 0x01;
 	}  else if (debug_status & DBSR_IAC3) {
-		current->thread.dbcr0 &= ~DBCR0_IAC3;
+		current->thread.debug.dbcr0 &= ~DBCR0_IAC3;
 		dbcr_iac_range(current) &= ~DBCR_IAC34MODE;
 		do_send_trap(regs, mfspr(SPRN_IAC3), debug_status, TRAP_HWBKPT,
 			     3);
 		changed |= 0x01;
 	}  else if (debug_status & DBSR_IAC4) {
-		current->thread.dbcr0 &= ~DBCR0_IAC4;
+		current->thread.debug.dbcr0 &= ~DBCR0_IAC4;
 		do_send_trap(regs, mfspr(SPRN_IAC4), debug_status, TRAP_HWBKPT,
 			     4);
 		changed |= 0x01;
@@ -1524,19 +1528,20 @@
 	 * Check all other debug flags and see if that bit needs to be turned
 	 * back on or not.
 	 */
-	if (DBCR_ACTIVE_EVENTS(current->thread.dbcr0, current->thread.dbcr1))
+	if (DBCR_ACTIVE_EVENTS(current->thread.debug.dbcr0,
+	    current->thread.debug.dbcr1))
 		regs->msr |= MSR_DE;
 	else
 		/* Make sure the IDM flag is off */
-		current->thread.dbcr0 &= ~DBCR0_IDM;
+		current->thread.debug.dbcr0 &= ~DBCR0_IDM;
 
 	if (changed & 0x01)
-		mtspr(SPRN_DBCR0, current->thread.dbcr0);
+		mtspr(SPRN_DBCR0, current->thread.debug.dbcr0);
 }
 
 void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
 {
-	current->thread.dbsr = debug_status;
+	current->thread.debug.dbsr = debug_status;
 
 	/* Hack alert: On BookE, Branch Taken stops on the branch itself, while
 	 * on server, it stops on the target of the branch. In order to simulate
@@ -1553,8 +1558,8 @@
 
 		/* Do the single step trick only when coming from userspace */
 		if (user_mode(regs)) {
-			current->thread.dbcr0 &= ~DBCR0_BT;
-			current->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC;
+			current->thread.debug.dbcr0 &= ~DBCR0_BT;
+			current->thread.debug.dbcr0 |= DBCR0_IDM | DBCR0_IC;
 			regs->msr |= MSR_DE;
 			return;
 		}
@@ -1582,13 +1587,13 @@
 			return;
 
 		if (user_mode(regs)) {
-			current->thread.dbcr0 &= ~DBCR0_IC;
-			if (DBCR_ACTIVE_EVENTS(current->thread.dbcr0,
-					       current->thread.dbcr1))
+			current->thread.debug.dbcr0 &= ~DBCR0_IC;
+			if (DBCR_ACTIVE_EVENTS(current->thread.debug.dbcr0,
+					       current->thread.debug.dbcr1))
 				regs->msr |= MSR_DE;
 			else
 				/* Make sure the IDM bit is off */
-				current->thread.dbcr0 &= ~DBCR0_IDM;
+				current->thread.debug.dbcr0 &= ~DBCR0_IDM;
 		}
 
 		_exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
@@ -1634,7 +1639,7 @@
 		/* XXX quick hack for now: set the non-Java bit in the VSCR */
 		printk_ratelimited(KERN_ERR "Unrecognized altivec instruction "
 				   "in %s at %lx\n", current->comm, regs->nip);
-		current->thread.vscr.u[3] |= 0x10000;
+		current->thread.vr_state.vscr.u[3] |= 0x10000;
 	}
 }
 #endif /* CONFIG_ALTIVEC */
@@ -1815,6 +1820,7 @@
 	WARN_EMULATED_SETUP(popcntb),
 	WARN_EMULATED_SETUP(spe),
 	WARN_EMULATED_SETUP(string),
+	WARN_EMULATED_SETUP(sync),
 	WARN_EMULATED_SETUP(unaligned),
 #ifdef CONFIG_MATH_EMULATION
 	WARN_EMULATED_SETUP(math),
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index 1d9c926..094e45c 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -34,8 +34,7 @@
 #include <asm/firmware.h>
 #include <asm/vdso.h>
 #include <asm/vdso_datapage.h>
-
-#include "setup.h"
+#include <asm/setup.h>
 
 #undef DEBUG
 
diff --git a/arch/powerpc/kernel/vdso32/vdso32.lds.S b/arch/powerpc/kernel/vdso32/vdso32.lds.S
index f223409..e58ee10 100644
--- a/arch/powerpc/kernel/vdso32/vdso32.lds.S
+++ b/arch/powerpc/kernel/vdso32/vdso32.lds.S
@@ -4,7 +4,11 @@
  */
 #include <asm/vdso.h>
 
+#ifdef __LITTLE_ENDIAN__
+OUTPUT_FORMAT("elf32-powerpcle", "elf32-powerpcle", "elf32-powerpcle")
+#else
 OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc")
+#endif
 OUTPUT_ARCH(powerpc:common)
 ENTRY(_start)
 
diff --git a/arch/powerpc/kernel/vdso64/vdso64.lds.S b/arch/powerpc/kernel/vdso64/vdso64.lds.S
index e486381..64fb183 100644
--- a/arch/powerpc/kernel/vdso64/vdso64.lds.S
+++ b/arch/powerpc/kernel/vdso64/vdso64.lds.S
@@ -4,7 +4,11 @@
  */
 #include <asm/vdso.h>
 
+#ifdef __LITTLE_ENDIAN__
+OUTPUT_FORMAT("elf64-powerpcle", "elf64-powerpcle", "elf64-powerpcle")
+#else
 OUTPUT_FORMAT("elf64-powerpc", "elf64-powerpc", "elf64-powerpc")
+#endif
 OUTPUT_ARCH(powerpc:common64)
 ENTRY(_start)
 
diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c
index 604d094..c4bfadb 100644
--- a/arch/powerpc/kernel/vecemu.c
+++ b/arch/powerpc/kernel/vecemu.c
@@ -271,7 +271,7 @@
 	vb = (instr >> 11) & 0x1f;
 	vc = (instr >> 6) & 0x1f;
 
-	vrs = current->thread.vr;
+	vrs = current->thread.vr_state.vr;
 	switch (instr & 0x3f) {
 	case 10:
 		switch (vc) {
@@ -320,12 +320,12 @@
 		case 14:	/* vctuxs */
 			for (i = 0; i < 4; ++i)
 				vrs[vd].u[i] = ctuxs(vrs[vb].u[i], va,
-						&current->thread.vscr.u[3]);
+					&current->thread.vr_state.vscr.u[3]);
 			break;
 		case 15:	/* vctsxs */
 			for (i = 0; i < 4; ++i)
 				vrs[vd].u[i] = ctsxs(vrs[vb].u[i], va,
-						&current->thread.vscr.u[3]);
+					&current->thread.vr_state.vscr.u[3]);
 			break;
 		default:
 			return -EINVAL;
diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S
index 9e20999..0458a9a 100644
--- a/arch/powerpc/kernel/vector.S
+++ b/arch/powerpc/kernel/vector.S
@@ -8,29 +8,6 @@
 #include <asm/ptrace.h>
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-/*
- * Wrapper to call load_up_altivec from C.
- * void do_load_up_altivec(struct pt_regs *regs);
- */
-_GLOBAL(do_load_up_altivec)
-	mflr	r0
-	std	r0, 16(r1)
-	stdu	r1, -112(r1)
-
-	subi	r6, r3, STACK_FRAME_OVERHEAD
-	/* load_up_altivec expects r12=MSR, r13=PACA, and returns
-	 * with r12 = new MSR.
-	 */
-	ld	r12,_MSR(r6)
-	GET_PACA(r13)
-	bl	load_up_altivec
-	std	r12,_MSR(r6)
-
-	ld	r0, 112+16(r1)
-	addi	r1, r1, 112
-	mtlr	r0
-	blr
-
 /* void do_load_up_transact_altivec(struct thread_struct *thread)
  *
  * This is similar to load_up_altivec but for the transactional version of the
@@ -46,10 +23,11 @@
 	li	r4,1
 	stw	r4,THREAD_USED_VR(r3)
 
-	li	r10,THREAD_TRANSACT_VSCR
+	li	r10,THREAD_TRANSACT_VRSTATE+VRSTATE_VSCR
 	lvx	vr0,r10,r3
 	mtvscr	vr0
-	REST_32VRS_TRANSACT(0,r4,r3)
+	addi	r10,r3,THREAD_TRANSACT_VRSTATE
+	REST_32VRS(0,r4,r10)
 
 	/* Disable VEC again. */
 	MTMSRD(r6)
@@ -59,12 +37,36 @@
 #endif
 
 /*
- * load_up_altivec(unused, unused, tsk)
+ * Load state from memory into VMX registers including VSCR.
+ * Assumes the caller has enabled VMX in the MSR.
+ */
+_GLOBAL(load_vr_state)
+	li	r4,VRSTATE_VSCR
+	lvx	vr0,r4,r3
+	mtvscr	vr0
+	REST_32VRS(0,r4,r3)
+	blr
+
+/*
+ * Store VMX state into memory, including VSCR.
+ * Assumes the caller has enabled VMX in the MSR.
+ */
+_GLOBAL(store_vr_state)
+	SAVE_32VRS(0, r4, r3)
+	mfvscr	vr0
+	li	r4, VRSTATE_VSCR
+	stvx	vr0, r4, r3
+	blr
+
+/*
  * Disable VMX for the task which had it previously,
  * and save its vector registers in its thread_struct.
  * Enables the VMX for use in the kernel on return.
  * On SMP we know the VMX is free, since we give it up every
  * switch (ie, no lazy save of the vector registers).
+ *
+ * Note that on 32-bit this can only use registers that will be
+ * restored by fast_exception_return, i.e. r3 - r6, r10 and r11.
  */
 _GLOBAL(load_up_altivec)
 	mfmsr	r5			/* grab the current MSR */
@@ -90,10 +92,11 @@
 	/* Save VMX state to last_task_used_altivec's THREAD struct */
 	toreal(r4)
 	addi	r4,r4,THREAD
-	SAVE_32VRS(0,r5,r4)
+	addi	r6,r4,THREAD_VRSTATE
+	SAVE_32VRS(0,r5,r6)
 	mfvscr	vr0
-	li	r10,THREAD_VSCR
-	stvx	vr0,r10,r4
+	li	r10,VRSTATE_VSCR
+	stvx	vr0,r10,r6
 	/* Disable VMX for last_task_used_altivec */
 	PPC_LL	r5,PT_REGS(r4)
 	toreal(r5)
@@ -125,12 +128,13 @@
 	oris	r12,r12,MSR_VEC@h
 	std	r12,_MSR(r1)
 #endif
+	addi	r6,r5,THREAD_VRSTATE
 	li	r4,1
-	li	r10,THREAD_VSCR
+	li	r10,VRSTATE_VSCR
 	stw	r4,THREAD_USED_VR(r5)
-	lvx	vr0,r10,r5
+	lvx	vr0,r10,r6
 	mtvscr	vr0
-	REST_32VRS(0,r4,r5)
+	REST_32VRS(0,r4,r6)
 #ifndef CONFIG_SMP
 	/* Update last_task_used_altivec to 'current' */
 	subi	r4,r5,THREAD		/* Back to 'current' */
@@ -165,12 +169,16 @@
 	PPC_LCMPI	0,r3,0
 	beqlr				/* if no previous owner, done */
 	addi	r3,r3,THREAD		/* want THREAD of task */
+	PPC_LL	r7,THREAD_VRSAVEAREA(r3)
 	PPC_LL	r5,PT_REGS(r3)
-	PPC_LCMPI	0,r5,0
-	SAVE_32VRS(0,r4,r3)
+	PPC_LCMPI	0,r7,0
+	bne	2f
+	addi	r7,r3,THREAD_VRSTATE
+2:	PPC_LCMPI	0,r5,0
+	SAVE_32VRS(0,r4,r7)
 	mfvscr	vr0
-	li	r4,THREAD_VSCR
-	stvx	vr0,r4,r3
+	li	r4,VRSTATE_VSCR
+	stvx	vr0,r4,r7
 	beq	1f
 	PPC_LL	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
 #ifdef CONFIG_VSX
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index d38cc08..f99cefb 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -997,21 +997,36 @@
 /* sysfs bus functions and data structures for CMO */
 
 #define viobus_cmo_rd_attr(name)                                        \
-static ssize_t                                                          \
-viobus_cmo_##name##_show(struct bus_type *bt, char *buf)                \
+static ssize_t cmo_##name##_show(struct bus_type *bt, char *buf)        \
 {                                                                       \
 	return sprintf(buf, "%lu\n", vio_cmo.name);                     \
-}
+}                                                                       \
+static BUS_ATTR_RO(cmo_##name)
 
 #define viobus_cmo_pool_rd_attr(name, var)                              \
 static ssize_t                                                          \
-viobus_cmo_##name##_pool_show_##var(struct bus_type *bt, char *buf)     \
+cmo_##name##_##var##_show(struct bus_type *bt, char *buf)               \
 {                                                                       \
 	return sprintf(buf, "%lu\n", vio_cmo.name.var);                 \
+}                                                                       \
+static BUS_ATTR_RO(cmo_##name##_##var)
+
+viobus_cmo_rd_attr(entitled);
+viobus_cmo_rd_attr(spare);
+viobus_cmo_rd_attr(min);
+viobus_cmo_rd_attr(desired);
+viobus_cmo_rd_attr(curr);
+viobus_cmo_pool_rd_attr(reserve, size);
+viobus_cmo_pool_rd_attr(excess, size);
+viobus_cmo_pool_rd_attr(excess, free);
+
+static ssize_t cmo_high_show(struct bus_type *bt, char *buf)
+{
+	return sprintf(buf, "%lu\n", vio_cmo.high);
 }
 
-static ssize_t viobus_cmo_high_reset(struct bus_type *bt, const char *buf,
-                                     size_t count)
+static ssize_t cmo_high_store(struct bus_type *bt, const char *buf,
+			      size_t count)
 {
 	unsigned long flags;
 
@@ -1021,35 +1036,26 @@
 
 	return count;
 }
+static BUS_ATTR_RW(cmo_high);
 
-viobus_cmo_rd_attr(entitled);
-viobus_cmo_pool_rd_attr(reserve, size);
-viobus_cmo_pool_rd_attr(excess, size);
-viobus_cmo_pool_rd_attr(excess, free);
-viobus_cmo_rd_attr(spare);
-viobus_cmo_rd_attr(min);
-viobus_cmo_rd_attr(desired);
-viobus_cmo_rd_attr(curr);
-viobus_cmo_rd_attr(high);
-
-static struct bus_attribute vio_cmo_bus_attrs[] = {
-	__ATTR(cmo_entitled, S_IRUGO, viobus_cmo_entitled_show, NULL),
-	__ATTR(cmo_reserve_size, S_IRUGO, viobus_cmo_reserve_pool_show_size, NULL),
-	__ATTR(cmo_excess_size, S_IRUGO, viobus_cmo_excess_pool_show_size, NULL),
-	__ATTR(cmo_excess_free, S_IRUGO, viobus_cmo_excess_pool_show_free, NULL),
-	__ATTR(cmo_spare,   S_IRUGO, viobus_cmo_spare_show,   NULL),
-	__ATTR(cmo_min,     S_IRUGO, viobus_cmo_min_show,     NULL),
-	__ATTR(cmo_desired, S_IRUGO, viobus_cmo_desired_show, NULL),
-	__ATTR(cmo_curr,    S_IRUGO, viobus_cmo_curr_show,    NULL),
-	__ATTR(cmo_high,    S_IWUSR|S_IRUSR|S_IWGRP|S_IRGRP|S_IROTH,
-	       viobus_cmo_high_show, viobus_cmo_high_reset),
-	__ATTR_NULL
+static struct attribute *vio_bus_attrs[] = {
+	&bus_attr_cmo_entitled.attr,
+	&bus_attr_cmo_spare.attr,
+	&bus_attr_cmo_min.attr,
+	&bus_attr_cmo_desired.attr,
+	&bus_attr_cmo_curr.attr,
+	&bus_attr_cmo_high.attr,
+	&bus_attr_cmo_reserve_size.attr,
+	&bus_attr_cmo_excess_size.attr,
+	&bus_attr_cmo_excess_free.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(vio_bus);
 
 static void vio_cmo_sysfs_init(void)
 {
 	vio_bus_type.dev_attrs = vio_cmo_dev_attrs;
-	vio_bus_type.bus_attrs = vio_cmo_bus_attrs;
+	vio_bus_type.bus_groups = vio_bus_groups;
 }
 #else /* CONFIG_PPC_SMLPAR */
 int vio_cmo_entitlement_update(size_t new_entitlement) { return 0; }
@@ -1531,12 +1537,12 @@
 
 	dn = dev->of_node;
 	if (!dn) {
-		strcat(buf, "\n");
+		strcpy(buf, "\n");
 		return strlen(buf);
 	}
 	cp = of_get_property(dn, "compatible", NULL);
 	if (!cp) {
-		strcat(buf, "\n");
+		strcpy(buf, "\n");
 		return strlen(buf);
 	}
 
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index ffaef2c..e593ff2 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -6,6 +6,7 @@
 
 menuconfig VIRTUALIZATION
 	bool "Virtualization"
+	depends on !CPU_LITTLE_ENDIAN
 	---help---
 	  Say Y here to get to see options for using your Linux host to run
 	  other operating systems inside virtual machines (guests).
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 294b7af..c71103b 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -1066,7 +1066,7 @@
 BEGIN_FTR_SECTION
 	mfspr	r8, SPRN_DSCR
 	ld	r7, HSTATE_DSCR(r13)
-	std	r8, VCPU_DSCR(r7)
+	std	r8, VCPU_DSCR(r9)
 	mtspr	SPRN_DSCR, r7
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index 27db1e6..c0b48f96 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -444,7 +444,7 @@
 #ifdef CONFIG_VSX
 	u64 *vcpu_vsx = vcpu->arch.vsr;
 #endif
-	u64 *thread_fpr = (u64*)t->fpr;
+	u64 *thread_fpr = &t->fp_state.fpr[0][0];
 	int i;
 
 	/*
@@ -466,14 +466,14 @@
 		/*
 		 * Note that on CPUs with VSX, giveup_fpu stores
 		 * both the traditional FP registers and the added VSX
-		 * registers into thread.fpr[].
+		 * registers into thread.fp_state.fpr[].
 		 */
 		if (current->thread.regs->msr & MSR_FP)
 			giveup_fpu(current);
 		for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++)
 			vcpu_fpr[i] = thread_fpr[get_fpr_index(i)];
 
-		vcpu->arch.fpscr = t->fpscr.val;
+		vcpu->arch.fpscr = t->fp_state.fpscr;
 
 #ifdef CONFIG_VSX
 		if (cpu_has_feature(CPU_FTR_VSX))
@@ -486,8 +486,8 @@
 	if (msr & MSR_VEC) {
 		if (current->thread.regs->msr & MSR_VEC)
 			giveup_altivec(current);
-		memcpy(vcpu->arch.vr, t->vr, sizeof(vcpu->arch.vr));
-		vcpu->arch.vscr = t->vscr;
+		memcpy(vcpu->arch.vr, t->vr_state.vr, sizeof(vcpu->arch.vr));
+		vcpu->arch.vscr = t->vr_state.vscr;
 	}
 #endif
 
@@ -539,7 +539,7 @@
 #ifdef CONFIG_VSX
 	u64 *vcpu_vsx = vcpu->arch.vsr;
 #endif
-	u64 *thread_fpr = (u64*)t->fpr;
+	u64 *thread_fpr = &t->fp_state.fpr[0][0];
 	int i;
 
 	/* When we have paired singles, we emulate in software */
@@ -584,15 +584,15 @@
 		for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr) / 2; i++)
 			thread_fpr[get_fpr_index(i) + 1] = vcpu_vsx[i];
 #endif
-		t->fpscr.val = vcpu->arch.fpscr;
+		t->fp_state.fpscr = vcpu->arch.fpscr;
 		t->fpexc_mode = 0;
 		kvmppc_load_up_fpu();
 	}
 
 	if (msr & MSR_VEC) {
 #ifdef CONFIG_ALTIVEC
-		memcpy(t->vr, vcpu->arch.vr, sizeof(vcpu->arch.vr));
-		t->vscr = vcpu->arch.vscr;
+		memcpy(t->vr_state.vr, vcpu->arch.vr, sizeof(vcpu->arch.vr));
+		t->vr_state.vscr = vcpu->arch.vscr;
 		t->vrsave = -1;
 		kvmppc_load_up_altivec();
 #endif
@@ -1116,12 +1116,10 @@
 int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 {
 	int ret;
-	double fpr[32][TS_FPRWIDTH];
-	unsigned int fpscr;
+	struct thread_fp_state fp;
 	int fpexc_mode;
 #ifdef CONFIG_ALTIVEC
-	vector128 vr[32];
-	vector128 vscr;
+	struct thread_vr_state vr;
 	unsigned long uninitialized_var(vrsave);
 	int used_vr;
 #endif
@@ -1153,8 +1151,7 @@
 	/* Save FPU state in stack */
 	if (current->thread.regs->msr & MSR_FP)
 		giveup_fpu(current);
-	memcpy(fpr, current->thread.fpr, sizeof(current->thread.fpr));
-	fpscr = current->thread.fpscr.val;
+	fp = current->thread.fp_state;
 	fpexc_mode = current->thread.fpexc_mode;
 
 #ifdef CONFIG_ALTIVEC
@@ -1163,8 +1160,7 @@
 	if (used_vr) {
 		if (current->thread.regs->msr & MSR_VEC)
 			giveup_altivec(current);
-		memcpy(vr, current->thread.vr, sizeof(current->thread.vr));
-		vscr = current->thread.vscr;
+		vr = current->thread.vr_state;
 		vrsave = current->thread.vrsave;
 	}
 #endif
@@ -1196,15 +1192,13 @@
 	current->thread.regs->msr = ext_msr;
 
 	/* Restore FPU/VSX state from stack */
-	memcpy(current->thread.fpr, fpr, sizeof(current->thread.fpr));
-	current->thread.fpscr.val = fpscr;
+	current->thread.fp_state = fp;
 	current->thread.fpexc_mode = fpexc_mode;
 
 #ifdef CONFIG_ALTIVEC
 	/* Restore Altivec state from stack */
 	if (used_vr && current->thread.used_vr) {
-		memcpy(current->thread.vr, vr, sizeof(current->thread.vr));
-		current->thread.vscr = vscr;
+		current->thread.vr_state = vr;
 		current->thread.vrsave = vrsave;
 	}
 	current->thread.used_vr = used_vr;
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 17722d8..5133199 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -656,9 +656,8 @@
 {
 	int ret, s;
 #ifdef CONFIG_PPC_FPU
-	unsigned int fpscr;
+	struct thread_fp_state fp;
 	int fpexc_mode;
-	u64 fpr[32];
 #endif
 
 	if (!vcpu->arch.sane) {
@@ -677,13 +676,13 @@
 #ifdef CONFIG_PPC_FPU
 	/* Save userspace FPU state in stack */
 	enable_kernel_fp();
-	memcpy(fpr, current->thread.fpr, sizeof(current->thread.fpr));
-	fpscr = current->thread.fpscr.val;
+	fp = current->thread.fp_state;
 	fpexc_mode = current->thread.fpexc_mode;
 
 	/* Restore guest FPU state to thread */
-	memcpy(current->thread.fpr, vcpu->arch.fpr, sizeof(vcpu->arch.fpr));
-	current->thread.fpscr.val = vcpu->arch.fpscr;
+	memcpy(current->thread.fp_state.fpr, vcpu->arch.fpr,
+	       sizeof(vcpu->arch.fpr));
+	current->thread.fp_state.fpscr = vcpu->arch.fpscr;
 
 	/*
 	 * Since we can't trap on MSR_FP in GS-mode, we consider the guest
@@ -709,12 +708,12 @@
 	vcpu->fpu_active = 0;
 
 	/* Save guest FPU state from thread */
-	memcpy(vcpu->arch.fpr, current->thread.fpr, sizeof(vcpu->arch.fpr));
-	vcpu->arch.fpscr = current->thread.fpscr.val;
+	memcpy(vcpu->arch.fpr, current->thread.fp_state.fpr,
+	       sizeof(vcpu->arch.fpr));
+	vcpu->arch.fpscr = current->thread.fp_state.fpscr;
 
 	/* Restore userspace FPU state from stack */
-	memcpy(current->thread.fpr, fpr, sizeof(current->thread.fpr));
-	current->thread.fpscr.val = fpscr;
+	current->thread.fp_state = fp;
 	current->thread.fpexc_mode = fpexc_mode;
 #endif
 
diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c
index 1c6a9d72..c65593a 100644
--- a/arch/powerpc/kvm/e500_mmu_host.c
+++ b/arch/powerpc/kvm/e500_mmu_host.c
@@ -332,6 +332,13 @@
 	unsigned long hva;
 	int pfnmap = 0;
 	int tsize = BOOK3E_PAGESZ_4K;
+	int ret = 0;
+	unsigned long mmu_seq;
+	struct kvm *kvm = vcpu_e500->vcpu.kvm;
+
+	/* used to check for invalidations in progress */
+	mmu_seq = kvm->mmu_notifier_seq;
+	smp_rmb();
 
 	/*
 	 * Translate guest physical to true physical, acquiring
@@ -449,6 +456,12 @@
 		gvaddr &= ~((tsize_pages << PAGE_SHIFT) - 1);
 	}
 
+	spin_lock(&kvm->mmu_lock);
+	if (mmu_notifier_retry(kvm, mmu_seq)) {
+		ret = -EAGAIN;
+		goto out;
+	}
+
 	kvmppc_e500_ref_setup(ref, gtlbe, pfn);
 
 	kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize,
@@ -457,10 +470,13 @@
 	/* Clear i-cache for new pages */
 	kvmppc_mmu_flush_icache(pfn);
 
+out:
+	spin_unlock(&kvm->mmu_lock);
+
 	/* Drop refcount on page, so that mmu notifiers can clear it */
 	kvm_release_pfn_clean(pfn);
 
-	return 0;
+	return ret;
 }
 
 /* XXX only map the one-one case, for now use TLB0 */
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 4504332..95a20e1 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -10,15 +10,23 @@
 CFLAGS_REMOVE_feature-fixups.o = -pg
 
 obj-y			:= string.o alloc.o \
-			   checksum_$(CONFIG_WORD_SIZE).o crtsavres.o
+			   crtsavres.o
 obj-$(CONFIG_PPC32)	+= div64.o copy_32.o
 obj-$(CONFIG_HAS_IOMEM)	+= devres.o
 
 obj-$(CONFIG_PPC64)	+= copypage_64.o copyuser_64.o \
-			   memcpy_64.o usercopy_64.o mem_64.o string.o \
-			   checksum_wrappers_64.o hweight_64.o \
-			   copyuser_power7.o string_64.o copypage_power7.o \
-			   memcpy_power7.o
+			   usercopy_64.o mem_64.o string.o \
+			   hweight_64.o \
+			   copyuser_power7.o string_64.o copypage_power7.o
+ifeq ($(CONFIG_GENERIC_CSUM),)
+obj-y			+= checksum_$(CONFIG_WORD_SIZE).o
+obj-$(CONFIG_PPC64)	+= checksum_wrappers_64.o
+endif
+
+ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),)
+obj-$(CONFIG_PPC64)		+= memcpy_power7.o memcpy_64.o 
+endif
+
 obj-$(CONFIG_PPC_EMULATE_SSTEP)	+= sstep.o ldstfp.o
 
 ifeq ($(CONFIG_PPC64),y)
@@ -31,3 +39,6 @@
 obj-y			+= code-patching.o
 obj-y			+= feature-fixups.o
 obj-$(CONFIG_FTR_FIXUP_SELFTEST) += feature-fixups-test.o
+
+obj-$(CONFIG_ALTIVEC)	+= xor_vmx.o
+CFLAGS_xor_vmx.o += -maltivec -mabi=altivec
diff --git a/arch/powerpc/lib/copyuser_power7.S b/arch/powerpc/lib/copyuser_power7.S
index d1f1179..e8e9c36 100644
--- a/arch/powerpc/lib/copyuser_power7.S
+++ b/arch/powerpc/lib/copyuser_power7.S
@@ -19,6 +19,14 @@
  */
 #include <asm/ppc_asm.h>
 
+#ifdef __BIG_ENDIAN__
+#define LVS(VRT,RA,RB)		lvsl	VRT,RA,RB
+#define VPERM(VRT,VRA,VRB,VRC)	vperm	VRT,VRA,VRB,VRC
+#else
+#define LVS(VRT,RA,RB)		lvsr	VRT,RA,RB
+#define VPERM(VRT,VRA,VRB,VRC)	vperm	VRT,VRB,VRA,VRC
+#endif
+
 	.macro err1
 100:
 	.section __ex_table,"a"
@@ -552,13 +560,13 @@
 	li	r10,32
 	li	r11,48
 
-	lvsl	vr16,0,r4	/* Setup permute control vector */
+	LVS(vr16,0,r4)		/* Setup permute control vector */
 err3;	lvx	vr0,0,r4
 	addi	r4,r4,16
 
 	bf	cr7*4+3,5f
 err3;	lvx	vr1,r0,r4
-	vperm	vr8,vr0,vr1,vr16
+	VPERM(vr8,vr0,vr1,vr16)
 	addi	r4,r4,16
 err3;	stvx	vr8,r0,r3
 	addi	r3,r3,16
@@ -566,9 +574,9 @@
 
 5:	bf	cr7*4+2,6f
 err3;	lvx	vr1,r0,r4
-	vperm	vr8,vr0,vr1,vr16
+	VPERM(vr8,vr0,vr1,vr16)
 err3;	lvx	vr0,r4,r9
-	vperm	vr9,vr1,vr0,vr16
+	VPERM(vr9,vr1,vr0,vr16)
 	addi	r4,r4,32
 err3;	stvx	vr8,r0,r3
 err3;	stvx	vr9,r3,r9
@@ -576,13 +584,13 @@
 
 6:	bf	cr7*4+1,7f
 err3;	lvx	vr3,r0,r4
-	vperm	vr8,vr0,vr3,vr16
+	VPERM(vr8,vr0,vr3,vr16)
 err3;	lvx	vr2,r4,r9
-	vperm	vr9,vr3,vr2,vr16
+	VPERM(vr9,vr3,vr2,vr16)
 err3;	lvx	vr1,r4,r10
-	vperm	vr10,vr2,vr1,vr16
+	VPERM(vr10,vr2,vr1,vr16)
 err3;	lvx	vr0,r4,r11
-	vperm	vr11,vr1,vr0,vr16
+	VPERM(vr11,vr1,vr0,vr16)
 	addi	r4,r4,64
 err3;	stvx	vr8,r0,r3
 err3;	stvx	vr9,r3,r9
@@ -611,21 +619,21 @@
 	.align	5
 8:
 err4;	lvx	vr7,r0,r4
-	vperm	vr8,vr0,vr7,vr16
+	VPERM(vr8,vr0,vr7,vr16)
 err4;	lvx	vr6,r4,r9
-	vperm	vr9,vr7,vr6,vr16
+	VPERM(vr9,vr7,vr6,vr16)
 err4;	lvx	vr5,r4,r10
-	vperm	vr10,vr6,vr5,vr16
+	VPERM(vr10,vr6,vr5,vr16)
 err4;	lvx	vr4,r4,r11
-	vperm	vr11,vr5,vr4,vr16
+	VPERM(vr11,vr5,vr4,vr16)
 err4;	lvx	vr3,r4,r12
-	vperm	vr12,vr4,vr3,vr16
+	VPERM(vr12,vr4,vr3,vr16)
 err4;	lvx	vr2,r4,r14
-	vperm	vr13,vr3,vr2,vr16
+	VPERM(vr13,vr3,vr2,vr16)
 err4;	lvx	vr1,r4,r15
-	vperm	vr14,vr2,vr1,vr16
+	VPERM(vr14,vr2,vr1,vr16)
 err4;	lvx	vr0,r4,r16
-	vperm	vr15,vr1,vr0,vr16
+	VPERM(vr15,vr1,vr0,vr16)
 	addi	r4,r4,128
 err4;	stvx	vr8,r0,r3
 err4;	stvx	vr9,r3,r9
@@ -649,13 +657,13 @@
 
 	bf	cr7*4+1,9f
 err3;	lvx	vr3,r0,r4
-	vperm	vr8,vr0,vr3,vr16
+	VPERM(vr8,vr0,vr3,vr16)
 err3;	lvx	vr2,r4,r9
-	vperm	vr9,vr3,vr2,vr16
+	VPERM(vr9,vr3,vr2,vr16)
 err3;	lvx	vr1,r4,r10
-	vperm	vr10,vr2,vr1,vr16
+	VPERM(vr10,vr2,vr1,vr16)
 err3;	lvx	vr0,r4,r11
-	vperm	vr11,vr1,vr0,vr16
+	VPERM(vr11,vr1,vr0,vr16)
 	addi	r4,r4,64
 err3;	stvx	vr8,r0,r3
 err3;	stvx	vr9,r3,r9
@@ -665,9 +673,9 @@
 
 9:	bf	cr7*4+2,10f
 err3;	lvx	vr1,r0,r4
-	vperm	vr8,vr0,vr1,vr16
+	VPERM(vr8,vr0,vr1,vr16)
 err3;	lvx	vr0,r4,r9
-	vperm	vr9,vr1,vr0,vr16
+	VPERM(vr9,vr1,vr0,vr16)
 	addi	r4,r4,32
 err3;	stvx	vr8,r0,r3
 err3;	stvx	vr9,r3,r9
@@ -675,7 +683,7 @@
 
 10:	bf	cr7*4+3,11f
 err3;	lvx	vr1,r0,r4
-	vperm	vr8,vr0,vr1,vr16
+	VPERM(vr8,vr0,vr1,vr16)
 	addi	r4,r4,16
 err3;	stvx	vr8,r0,r3
 	addi	r3,r3,16
diff --git a/arch/powerpc/lib/memcpy_power7.S b/arch/powerpc/lib/memcpy_power7.S
index 0663630..e4177db 100644
--- a/arch/powerpc/lib/memcpy_power7.S
+++ b/arch/powerpc/lib/memcpy_power7.S
@@ -20,6 +20,15 @@
 #include <asm/ppc_asm.h>
 
 _GLOBAL(memcpy_power7)
+
+#ifdef __BIG_ENDIAN__
+#define LVS(VRT,RA,RB)		lvsl	VRT,RA,RB
+#define VPERM(VRT,VRA,VRB,VRC)	vperm	VRT,VRA,VRB,VRC
+#else
+#define LVS(VRT,RA,RB)		lvsr	VRT,RA,RB
+#define VPERM(VRT,VRA,VRB,VRC)	vperm	VRT,VRB,VRA,VRC
+#endif
+
 #ifdef CONFIG_ALTIVEC
 	cmpldi	r5,16
 	cmpldi	cr1,r5,4096
@@ -485,13 +494,13 @@
 	li	r10,32
 	li	r11,48
 
-	lvsl	vr16,0,r4	/* Setup permute control vector */
+	LVS(vr16,0,r4)		/* Setup permute control vector */
 	lvx	vr0,0,r4
 	addi	r4,r4,16
 
 	bf	cr7*4+3,5f
 	lvx	vr1,r0,r4
-	vperm	vr8,vr0,vr1,vr16
+	VPERM(vr8,vr0,vr1,vr16)
 	addi	r4,r4,16
 	stvx	vr8,r0,r3
 	addi	r3,r3,16
@@ -499,9 +508,9 @@
 
 5:	bf	cr7*4+2,6f
 	lvx	vr1,r0,r4
-	vperm	vr8,vr0,vr1,vr16
+	VPERM(vr8,vr0,vr1,vr16)
 	lvx	vr0,r4,r9
-	vperm	vr9,vr1,vr0,vr16
+	VPERM(vr9,vr1,vr0,vr16)
 	addi	r4,r4,32
 	stvx	vr8,r0,r3
 	stvx	vr9,r3,r9
@@ -509,13 +518,13 @@
 
 6:	bf	cr7*4+1,7f
 	lvx	vr3,r0,r4
-	vperm	vr8,vr0,vr3,vr16
+	VPERM(vr8,vr0,vr3,vr16)
 	lvx	vr2,r4,r9
-	vperm	vr9,vr3,vr2,vr16
+	VPERM(vr9,vr3,vr2,vr16)
 	lvx	vr1,r4,r10
-	vperm	vr10,vr2,vr1,vr16
+	VPERM(vr10,vr2,vr1,vr16)
 	lvx	vr0,r4,r11
-	vperm	vr11,vr1,vr0,vr16
+	VPERM(vr11,vr1,vr0,vr16)
 	addi	r4,r4,64
 	stvx	vr8,r0,r3
 	stvx	vr9,r3,r9
@@ -544,21 +553,21 @@
 	.align	5
 8:
 	lvx	vr7,r0,r4
-	vperm	vr8,vr0,vr7,vr16
+	VPERM(vr8,vr0,vr7,vr16)
 	lvx	vr6,r4,r9
-	vperm	vr9,vr7,vr6,vr16
+	VPERM(vr9,vr7,vr6,vr16)
 	lvx	vr5,r4,r10
-	vperm	vr10,vr6,vr5,vr16
+	VPERM(vr10,vr6,vr5,vr16)
 	lvx	vr4,r4,r11
-	vperm	vr11,vr5,vr4,vr16
+	VPERM(vr11,vr5,vr4,vr16)
 	lvx	vr3,r4,r12
-	vperm	vr12,vr4,vr3,vr16
+	VPERM(vr12,vr4,vr3,vr16)
 	lvx	vr2,r4,r14
-	vperm	vr13,vr3,vr2,vr16
+	VPERM(vr13,vr3,vr2,vr16)
 	lvx	vr1,r4,r15
-	vperm	vr14,vr2,vr1,vr16
+	VPERM(vr14,vr2,vr1,vr16)
 	lvx	vr0,r4,r16
-	vperm	vr15,vr1,vr0,vr16
+	VPERM(vr15,vr1,vr0,vr16)
 	addi	r4,r4,128
 	stvx	vr8,r0,r3
 	stvx	vr9,r3,r9
@@ -582,13 +591,13 @@
 
 	bf	cr7*4+1,9f
 	lvx	vr3,r0,r4
-	vperm	vr8,vr0,vr3,vr16
+	VPERM(vr8,vr0,vr3,vr16)
 	lvx	vr2,r4,r9
-	vperm	vr9,vr3,vr2,vr16
+	VPERM(vr9,vr3,vr2,vr16)
 	lvx	vr1,r4,r10
-	vperm	vr10,vr2,vr1,vr16
+	VPERM(vr10,vr2,vr1,vr16)
 	lvx	vr0,r4,r11
-	vperm	vr11,vr1,vr0,vr16
+	VPERM(vr11,vr1,vr0,vr16)
 	addi	r4,r4,64
 	stvx	vr8,r0,r3
 	stvx	vr9,r3,r9
@@ -598,9 +607,9 @@
 
 9:	bf	cr7*4+2,10f
 	lvx	vr1,r0,r4
-	vperm	vr8,vr0,vr1,vr16
+	VPERM(vr8,vr0,vr1,vr16)
 	lvx	vr0,r4,r9
-	vperm	vr9,vr1,vr0,vr16
+	VPERM(vr9,vr1,vr0,vr16)
 	addi	r4,r4,32
 	stvx	vr8,r0,r3
 	stvx	vr9,r3,r9
@@ -608,7 +617,7 @@
 
 10:	bf	cr7*4+3,11f
 	lvx	vr1,r0,r4
-	vperm	vr8,vr0,vr1,vr16
+	VPERM(vr8,vr0,vr1,vr16)
 	addi	r4,r4,16
 	stvx	vr8,r0,r3
 	addi	r3,r3,16
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index b1faa15..c0511c2 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -212,11 +212,19 @@
 {
 	int err;
 	unsigned long x, b, c;
+#ifdef __LITTLE_ENDIAN__
+	int len = nb; /* save a copy of the length for byte reversal */
+#endif
 
 	/* unaligned, do this in pieces */
 	x = 0;
 	for (; nb > 0; nb -= c) {
+#ifdef __LITTLE_ENDIAN__
+		c = 1;
+#endif
+#ifdef __BIG_ENDIAN__
 		c = max_align(ea);
+#endif
 		if (c > nb)
 			c = max_align(nb);
 		err = read_mem_aligned(&b, ea, c);
@@ -225,7 +233,24 @@
 		x = (x << (8 * c)) + b;
 		ea += c;
 	}
+#ifdef __LITTLE_ENDIAN__
+	switch (len) {
+	case 2:
+		*dest = byterev_2(x);
+		break;
+	case 4:
+		*dest = byterev_4(x);
+		break;
+#ifdef __powerpc64__
+	case 8:
+		*dest = byterev_8(x);
+		break;
+#endif
+	}
+#endif
+#ifdef __BIG_ENDIAN__
 	*dest = x;
+#endif
 	return 0;
 }
 
@@ -273,9 +298,29 @@
 	int err;
 	unsigned long c;
 
+#ifdef __LITTLE_ENDIAN__
+	switch (nb) {
+	case 2:
+		val = byterev_2(val);
+		break;
+	case 4:
+		val = byterev_4(val);
+		break;
+#ifdef __powerpc64__
+	case 8:
+		val = byterev_8(val);
+		break;
+#endif
+	}
+#endif
 	/* unaligned or little-endian, do this in pieces */
 	for (; nb > 0; nb -= c) {
+#ifdef __LITTLE_ENDIAN__
+		c = 1;
+#endif
+#ifdef __BIG_ENDIAN__
 		c = max_align(ea);
+#endif
 		if (c > nb)
 			c = max_align(nb);
 		err = write_mem_aligned(val >> (nb - c) * 8, ea, c);
@@ -310,22 +355,36 @@
 				struct pt_regs *regs)
 {
 	int err;
-	unsigned long val[sizeof(double) / sizeof(long)];
+	union {
+		double dbl;
+		unsigned long ul[2];
+		struct {
+#ifdef __BIG_ENDIAN__
+			unsigned _pad_;
+			unsigned word;
+#endif
+#ifdef __LITTLE_ENDIAN__
+			unsigned word;
+			unsigned _pad_;
+#endif
+		} single;
+	} data;
 	unsigned long ptr;
 
 	if (!address_ok(regs, ea, nb))
 		return -EFAULT;
 	if ((ea & 3) == 0)
 		return (*func)(rn, ea);
-	ptr = (unsigned long) &val[0];
+	ptr = (unsigned long) &data.ul;
 	if (sizeof(unsigned long) == 8 || nb == 4) {
-		err = read_mem_unaligned(&val[0], ea, nb, regs);
-		ptr += sizeof(unsigned long) - nb;
+		err = read_mem_unaligned(&data.ul[0], ea, nb, regs);
+		if (nb == 4)
+			ptr = (unsigned long)&(data.single.word);
 	} else {
 		/* reading a double on 32-bit */
-		err = read_mem_unaligned(&val[0], ea, 4, regs);
+		err = read_mem_unaligned(&data.ul[0], ea, 4, regs);
 		if (!err)
-			err = read_mem_unaligned(&val[1], ea + 4, 4, regs);
+			err = read_mem_unaligned(&data.ul[1], ea + 4, 4, regs);
 	}
 	if (err)
 		return err;
@@ -337,28 +396,42 @@
 				 struct pt_regs *regs)
 {
 	int err;
-	unsigned long val[sizeof(double) / sizeof(long)];
+	union {
+		double dbl;
+		unsigned long ul[2];
+		struct {
+#ifdef __BIG_ENDIAN__
+			unsigned _pad_;
+			unsigned word;
+#endif
+#ifdef __LITTLE_ENDIAN__
+			unsigned word;
+			unsigned _pad_;
+#endif
+		} single;
+	} data;
 	unsigned long ptr;
 
 	if (!address_ok(regs, ea, nb))
 		return -EFAULT;
 	if ((ea & 3) == 0)
 		return (*func)(rn, ea);
-	ptr = (unsigned long) &val[0];
+	ptr = (unsigned long) &data.ul[0];
 	if (sizeof(unsigned long) == 8 || nb == 4) {
-		ptr += sizeof(unsigned long) - nb;
+		if (nb == 4)
+			ptr = (unsigned long)&(data.single.word);
 		err = (*func)(rn, ptr);
 		if (err)
 			return err;
-		err = write_mem_unaligned(val[0], ea, nb, regs);
+		err = write_mem_unaligned(data.ul[0], ea, nb, regs);
 	} else {
 		/* writing a double on 32-bit */
 		err = (*func)(rn, ptr);
 		if (err)
 			return err;
-		err = write_mem_unaligned(val[0], ea, 4, regs);
+		err = write_mem_unaligned(data.ul[0], ea, 4, regs);
 		if (!err)
-			err = write_mem_unaligned(val[1], ea + 4, 4, regs);
+			err = write_mem_unaligned(data.ul[1], ea + 4, 4, regs);
 	}
 	return err;
 }
diff --git a/arch/powerpc/lib/xor_vmx.c b/arch/powerpc/lib/xor_vmx.c
new file mode 100644
index 0000000..e905f7c
--- /dev/null
+++ b/arch/powerpc/lib/xor_vmx.c
@@ -0,0 +1,177 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2012
+ *
+ * Author: Anton Blanchard <anton@au.ibm.com>
+ */
+#include <altivec.h>
+
+#include <linux/preempt.h>
+#include <linux/export.h>
+#include <linux/sched.h>
+#include <asm/switch_to.h>
+
+typedef vector signed char unative_t;
+
+#define DEFINE(V)				\
+	unative_t *V = (unative_t *)V##_in;	\
+	unative_t V##_0, V##_1, V##_2, V##_3
+
+#define LOAD(V)			\
+	do {			\
+		V##_0 = V[0];	\
+		V##_1 = V[1];	\
+		V##_2 = V[2];	\
+		V##_3 = V[3];	\
+	} while (0)
+
+#define STORE(V)		\
+	do {			\
+		V[0] = V##_0;	\
+		V[1] = V##_1;	\
+		V[2] = V##_2;	\
+		V[3] = V##_3;	\
+	} while (0)
+
+#define XOR(V1, V2)					\
+	do {						\
+		V1##_0 = vec_xor(V1##_0, V2##_0);	\
+		V1##_1 = vec_xor(V1##_1, V2##_1);	\
+		V1##_2 = vec_xor(V1##_2, V2##_2);	\
+		V1##_3 = vec_xor(V1##_3, V2##_3);	\
+	} while (0)
+
+void xor_altivec_2(unsigned long bytes, unsigned long *v1_in,
+		   unsigned long *v2_in)
+{
+	DEFINE(v1);
+	DEFINE(v2);
+	unsigned long lines = bytes / (sizeof(unative_t)) / 4;
+
+	preempt_disable();
+	enable_kernel_altivec();
+
+	do {
+		LOAD(v1);
+		LOAD(v2);
+		XOR(v1, v2);
+		STORE(v1);
+
+		v1 += 4;
+		v2 += 4;
+	} while (--lines > 0);
+
+	preempt_enable();
+}
+EXPORT_SYMBOL(xor_altivec_2);
+
+void xor_altivec_3(unsigned long bytes, unsigned long *v1_in,
+		   unsigned long *v2_in, unsigned long *v3_in)
+{
+	DEFINE(v1);
+	DEFINE(v2);
+	DEFINE(v3);
+	unsigned long lines = bytes / (sizeof(unative_t)) / 4;
+
+	preempt_disable();
+	enable_kernel_altivec();
+
+	do {
+		LOAD(v1);
+		LOAD(v2);
+		LOAD(v3);
+		XOR(v1, v2);
+		XOR(v1, v3);
+		STORE(v1);
+
+		v1 += 4;
+		v2 += 4;
+		v3 += 4;
+	} while (--lines > 0);
+
+	preempt_enable();
+}
+EXPORT_SYMBOL(xor_altivec_3);
+
+void xor_altivec_4(unsigned long bytes, unsigned long *v1_in,
+		   unsigned long *v2_in, unsigned long *v3_in,
+		   unsigned long *v4_in)
+{
+	DEFINE(v1);
+	DEFINE(v2);
+	DEFINE(v3);
+	DEFINE(v4);
+	unsigned long lines = bytes / (sizeof(unative_t)) / 4;
+
+	preempt_disable();
+	enable_kernel_altivec();
+
+	do {
+		LOAD(v1);
+		LOAD(v2);
+		LOAD(v3);
+		LOAD(v4);
+		XOR(v1, v2);
+		XOR(v3, v4);
+		XOR(v1, v3);
+		STORE(v1);
+
+		v1 += 4;
+		v2 += 4;
+		v3 += 4;
+		v4 += 4;
+	} while (--lines > 0);
+
+	preempt_enable();
+}
+EXPORT_SYMBOL(xor_altivec_4);
+
+void xor_altivec_5(unsigned long bytes, unsigned long *v1_in,
+		   unsigned long *v2_in, unsigned long *v3_in,
+		   unsigned long *v4_in, unsigned long *v5_in)
+{
+	DEFINE(v1);
+	DEFINE(v2);
+	DEFINE(v3);
+	DEFINE(v4);
+	DEFINE(v5);
+	unsigned long lines = bytes / (sizeof(unative_t)) / 4;
+
+	preempt_disable();
+	enable_kernel_altivec();
+
+	do {
+		LOAD(v1);
+		LOAD(v2);
+		LOAD(v3);
+		LOAD(v4);
+		LOAD(v5);
+		XOR(v1, v2);
+		XOR(v3, v4);
+		XOR(v1, v5);
+		XOR(v1, v3);
+		STORE(v1);
+
+		v1 += 4;
+		v2 += 4;
+		v3 += 4;
+		v4 += 4;
+		v5 += 4;
+	} while (--lines > 0);
+
+	preempt_enable();
+}
+EXPORT_SYMBOL(xor_altivec_5);
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index c33d939..3ea26c2 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -35,7 +35,11 @@
 #define DBG_LOW(fmt...)
 #endif
 
+#ifdef __BIG_ENDIAN__
 #define HPTE_LOCK_BIT 3
+#else
+#define HPTE_LOCK_BIT (56+3)
+#endif
 
 DEFINE_RAW_SPINLOCK(native_tlbie_lock);
 
@@ -172,7 +176,7 @@
 
 static inline void native_lock_hpte(struct hash_pte *hptep)
 {
-	unsigned long *word = &hptep->v;
+	unsigned long *word = (unsigned long *)&hptep->v;
 
 	while (1) {
 		if (!test_and_set_bit_lock(HPTE_LOCK_BIT, word))
@@ -184,7 +188,7 @@
 
 static inline void native_unlock_hpte(struct hash_pte *hptep)
 {
-	unsigned long *word = &hptep->v;
+	unsigned long *word = (unsigned long *)&hptep->v;
 
 	clear_bit_unlock(HPTE_LOCK_BIT, word);
 }
@@ -204,10 +208,10 @@
 	}
 
 	for (i = 0; i < HPTES_PER_GROUP; i++) {
-		if (! (hptep->v & HPTE_V_VALID)) {
+		if (! (be64_to_cpu(hptep->v) & HPTE_V_VALID)) {
 			/* retry with lock held */
 			native_lock_hpte(hptep);
-			if (! (hptep->v & HPTE_V_VALID))
+			if (! (be64_to_cpu(hptep->v) & HPTE_V_VALID))
 				break;
 			native_unlock_hpte(hptep);
 		}
@@ -226,14 +230,14 @@
 			i, hpte_v, hpte_r);
 	}
 
-	hptep->r = hpte_r;
+	hptep->r = cpu_to_be64(hpte_r);
 	/* Guarantee the second dword is visible before the valid bit */
 	eieio();
 	/*
 	 * Now set the first dword including the valid bit
 	 * NOTE: this also unlocks the hpte
 	 */
-	hptep->v = hpte_v;
+	hptep->v = cpu_to_be64(hpte_v);
 
 	__asm__ __volatile__ ("ptesync" : : : "memory");
 
@@ -254,12 +258,12 @@
 
 	for (i = 0; i < HPTES_PER_GROUP; i++) {
 		hptep = htab_address + hpte_group + slot_offset;
-		hpte_v = hptep->v;
+		hpte_v = be64_to_cpu(hptep->v);
 
 		if ((hpte_v & HPTE_V_VALID) && !(hpte_v & HPTE_V_BOLTED)) {
 			/* retry with lock held */
 			native_lock_hpte(hptep);
-			hpte_v = hptep->v;
+			hpte_v = be64_to_cpu(hptep->v);
 			if ((hpte_v & HPTE_V_VALID)
 			    && !(hpte_v & HPTE_V_BOLTED))
 				break;
@@ -294,7 +298,7 @@
 
 	native_lock_hpte(hptep);
 
-	hpte_v = hptep->v;
+	hpte_v = be64_to_cpu(hptep->v);
 	/*
 	 * We need to invalidate the TLB always because hpte_remove doesn't do
 	 * a tlb invalidate. If a hash bucket gets full, we "evict" a more/less
@@ -308,8 +312,8 @@
 	} else {
 		DBG_LOW(" -> hit\n");
 		/* Update the HPTE */
-		hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) |
-			(newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C));
+		hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) & ~(HPTE_R_PP | HPTE_R_N)) |
+			(newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C)));
 	}
 	native_unlock_hpte(hptep);
 
@@ -334,7 +338,7 @@
 	slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
 	for (i = 0; i < HPTES_PER_GROUP; i++) {
 		hptep = htab_address + slot;
-		hpte_v = hptep->v;
+		hpte_v = be64_to_cpu(hptep->v);
 
 		if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID))
 			/* HPTE matches */
@@ -369,8 +373,9 @@
 	hptep = htab_address + slot;
 
 	/* Update the HPTE */
-	hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) |
-		(newpp & (HPTE_R_PP | HPTE_R_N));
+	hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) &
+			~(HPTE_R_PP | HPTE_R_N)) |
+		(newpp & (HPTE_R_PP | HPTE_R_N)));
 	/*
 	 * Ensure it is out of the tlb too. Bolted entries base and
 	 * actual page size will be same.
@@ -392,7 +397,7 @@
 
 	want_v = hpte_encode_avpn(vpn, bpsize, ssize);
 	native_lock_hpte(hptep);
-	hpte_v = hptep->v;
+	hpte_v = be64_to_cpu(hptep->v);
 
 	/*
 	 * We need to invalidate the TLB always because hpte_remove doesn't do
@@ -458,7 +463,7 @@
 		hptep = htab_address + slot;
 		want_v = hpte_encode_avpn(vpn, psize, ssize);
 		native_lock_hpte(hptep);
-		hpte_v = hptep->v;
+		hpte_v = be64_to_cpu(hptep->v);
 
 		/* Even if we miss, we need to invalidate the TLB */
 		if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID))
@@ -519,11 +524,12 @@
 			int *psize, int *apsize, int *ssize, unsigned long *vpn)
 {
 	unsigned long avpn, pteg, vpi;
-	unsigned long hpte_v = hpte->v;
+	unsigned long hpte_v = be64_to_cpu(hpte->v);
+	unsigned long hpte_r = be64_to_cpu(hpte->r);
 	unsigned long vsid, seg_off;
 	int size, a_size, shift;
 	/* Look at the 8 bit LP value */
-	unsigned int lp = (hpte->r >> LP_SHIFT) & ((1 << LP_BITS) - 1);
+	unsigned int lp = (hpte_r >> LP_SHIFT) & ((1 << LP_BITS) - 1);
 
 	if (!(hpte_v & HPTE_V_LARGE)) {
 		size   = MMU_PAGE_4K;
@@ -612,7 +618,7 @@
 		 * running,  right?  and for crash dump, we probably
 		 * don't want to wait for a maybe bad cpu.
 		 */
-		hpte_v = hptep->v;
+		hpte_v = be64_to_cpu(hptep->v);
 
 		/*
 		 * Call __tlbie() here rather than tlbie() since we
@@ -664,7 +670,7 @@
 			hptep = htab_address + slot;
 			want_v = hpte_encode_avpn(vpn, psize, ssize);
 			native_lock_hpte(hptep);
-			hpte_v = hptep->v;
+			hpte_v = be64_to_cpu(hptep->v);
 			if (!HPTE_V_COMPARE(hpte_v, want_v) ||
 			    !(hpte_v & HPTE_V_VALID))
 				native_unlock_hpte(hptep);
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index bde8b55..6176b3c 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -251,19 +251,18 @@
 					 void *data)
 {
 	char *type = of_get_flat_dt_prop(node, "device_type", NULL);
-	u32 *prop;
+	__be32 *prop;
 	unsigned long size = 0;
 
 	/* We are scanning "cpu" nodes only */
 	if (type == NULL || strcmp(type, "cpu") != 0)
 		return 0;
 
-	prop = (u32 *)of_get_flat_dt_prop(node, "ibm,processor-segment-sizes",
-					  &size);
+	prop = of_get_flat_dt_prop(node, "ibm,processor-segment-sizes", &size);
 	if (prop == NULL)
 		return 0;
 	for (; size >= 4; size -= 4, ++prop) {
-		if (prop[0] == 40) {
+		if (be32_to_cpu(prop[0]) == 40) {
 			DBG("1T segment support detected\n");
 			cur_cpu_spec->mmu_features |= MMU_FTR_1T_SEGMENT;
 			return 1;
@@ -307,23 +306,22 @@
 					  void *data)
 {
 	char *type = of_get_flat_dt_prop(node, "device_type", NULL);
-	u32 *prop;
+	__be32 *prop;
 	unsigned long size = 0;
 
 	/* We are scanning "cpu" nodes only */
 	if (type == NULL || strcmp(type, "cpu") != 0)
 		return 0;
 
-	prop = (u32 *)of_get_flat_dt_prop(node,
-					  "ibm,segment-page-sizes", &size);
+	prop = of_get_flat_dt_prop(node, "ibm,segment-page-sizes", &size);
 	if (prop != NULL) {
 		pr_info("Page sizes from device-tree:\n");
 		size /= 4;
 		cur_cpu_spec->mmu_features &= ~(MMU_FTR_16M_PAGE);
 		while(size > 0) {
-			unsigned int base_shift = prop[0];
-			unsigned int slbenc = prop[1];
-			unsigned int lpnum = prop[2];
+			unsigned int base_shift = be32_to_cpu(prop[0]);
+			unsigned int slbenc = be32_to_cpu(prop[1]);
+			unsigned int lpnum = be32_to_cpu(prop[2]);
 			struct mmu_psize_def *def;
 			int idx, base_idx;
 
@@ -356,8 +354,8 @@
 				def->tlbiel = 0;
 
 			while (size > 0 && lpnum) {
-				unsigned int shift = prop[0];
-				int penc  = prop[1];
+				unsigned int shift = be32_to_cpu(prop[0]);
+				int penc  = be32_to_cpu(prop[1]);
 
 				prop += 2; size -= 2;
 				lpnum--;
@@ -390,8 +388,8 @@
 					const char *uname, int depth,
 					void *data) {
 	char *type = of_get_flat_dt_prop(node, "device_type", NULL);
-	unsigned long *addr_prop;
-	u32 *page_count_prop;
+	__be64 *addr_prop;
+	__be32 *page_count_prop;
 	unsigned int expected_pages;
 	long unsigned int phys_addr;
 	long unsigned int block_size;
@@ -405,12 +403,12 @@
 	page_count_prop = of_get_flat_dt_prop(node, "ibm,expected#pages", NULL);
 	if (page_count_prop == NULL)
 		return 0;
-	expected_pages = (1 << page_count_prop[0]);
+	expected_pages = (1 << be32_to_cpu(page_count_prop[0]));
 	addr_prop = of_get_flat_dt_prop(node, "reg", NULL);
 	if (addr_prop == NULL)
 		return 0;
-	phys_addr = addr_prop[0];
-	block_size = addr_prop[1];
+	phys_addr = be64_to_cpu(addr_prop[0]);
+	block_size = be64_to_cpu(addr_prop[1]);
 	if (block_size != (16 * GB))
 		return 0;
 	printk(KERN_INFO "Huge page(16GB) memory: "
@@ -534,16 +532,16 @@
 				       void *data)
 {
 	char *type = of_get_flat_dt_prop(node, "device_type", NULL);
-	u32 *prop;
+	__be32 *prop;
 
 	/* We are scanning "cpu" nodes only */
 	if (type == NULL || strcmp(type, "cpu") != 0)
 		return 0;
 
-	prop = (u32 *)of_get_flat_dt_prop(node, "ibm,pft-size", NULL);
+	prop = of_get_flat_dt_prop(node, "ibm,pft-size", NULL);
 	if (prop != NULL) {
 		/* pft_size[0] is the NUMA CEC cookie */
-		ppc64_pft_size = prop[1];
+		ppc64_pft_size = be32_to_cpu(prop[1]);
 		return 1;
 	}
 	return 0;
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index d47d3da..cff59f1 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -213,7 +213,12 @@
 	 */
 	BUG_ON(first_memblock_base != 0);
 
+#ifdef CONFIG_PIN_TLB
+	/* 8xx can only access 24MB at the moment */
+	memblock_set_current_limit(min_t(u64, first_memblock_size, 0x01800000));
+#else
 	/* 8xx can only access 8MB at the moment */
 	memblock_set_current_limit(min_t(u64, first_memblock_size, 0x00800000));
+#endif
 }
 #endif /* CONFIG_8xx */
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 8ed035d..e3734ed 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -304,5 +304,54 @@
 				  struct page *start_page, unsigned long size)
 {
 }
-#endif /* CONFIG_SPARSEMEM_VMEMMAP */
 
+/*
+ * We do not have access to the sparsemem vmemmap, so we fallback to
+ * walking the list of sparsemem blocks which we already maintain for
+ * the sake of crashdump. In the long run, we might want to maintain
+ * a tree if performance of that linear walk becomes a problem.
+ *
+ * realmode_pfn_to_page functions can fail due to:
+ * 1) As real sparsemem blocks do not lay in RAM continously (they
+ * are in virtual address space which is not available in the real mode),
+ * the requested page struct can be split between blocks so get_page/put_page
+ * may fail.
+ * 2) When huge pages are used, the get_page/put_page API will fail
+ * in real mode as the linked addresses in the page struct are virtual
+ * too.
+ */
+struct page *realmode_pfn_to_page(unsigned long pfn)
+{
+	struct vmemmap_backing *vmem_back;
+	struct page *page;
+	unsigned long page_size = 1 << mmu_psize_defs[mmu_vmemmap_psize].shift;
+	unsigned long pg_va = (unsigned long) pfn_to_page(pfn);
+
+	for (vmem_back = vmemmap_list; vmem_back; vmem_back = vmem_back->list) {
+		if (pg_va < vmem_back->virt_addr)
+			continue;
+
+		/* Check that page struct is not split between real pages */
+		if ((pg_va + sizeof(struct page)) >
+				(vmem_back->virt_addr + page_size))
+			return NULL;
+
+		page = (struct page *) (vmem_back->phys + pg_va -
+				vmem_back->virt_addr);
+		return page;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(realmode_pfn_to_page);
+
+#elif defined(CONFIG_FLATMEM)
+
+struct page *realmode_pfn_to_page(unsigned long pfn)
+{
+	struct page *page = pfn_to_page(pfn);
+	return page;
+}
+EXPORT_SYMBOL_GPL(realmode_pfn_to_page);
+
+#endif /* CONFIG_SPARSEMEM_VMEMMAP/CONFIG_FLATMEM */
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index c916127..33d6784 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -195,7 +195,7 @@
 	u32 len;
 	prop = of_get_property(memory, "linux,drconf-usable-memory", &len);
 	if (!prop || len < sizeof(unsigned int))
-		return 0;
+		return NULL;
 	return prop;
 }
 
@@ -1154,7 +1154,7 @@
  * represented in the device tree as a node (i.e. memory@XXXX) for
  * each memblock.
  */
-int hot_add_node_scn_to_nid(unsigned long scn_addr)
+static int hot_add_node_scn_to_nid(unsigned long scn_addr)
 {
 	struct device_node *memory;
 	int nid = -1;
@@ -1235,7 +1235,7 @@
         struct device_node *memory = NULL;
         unsigned int drconf_cell_cnt = 0;
         u64 lmb_size = 0;
-	const __be32 *dm = 0;
+	const __be32 *dm = NULL;
 
         memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
         if (memory) {
@@ -1535,7 +1535,7 @@
 }
 static DECLARE_WORK(topology_work, topology_work_fn);
 
-void topology_schedule_update(void)
+static void topology_schedule_update(void)
 {
 	schedule_work(&topology_work);
 }
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c
index edda589..841e0d0 100644
--- a/arch/powerpc/mm/pgtable.c
+++ b/arch/powerpc/mm/pgtable.c
@@ -32,8 +32,6 @@
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
 
-#include "mmu_decl.h"
-
 static inline int is_exec_fault(void)
 {
 	return current->thread.regs && TRAP(current->thread.regs) == 0x400;
@@ -72,7 +70,7 @@
  * support falls into the same category.
  */
 
-static pte_t set_pte_filter(pte_t pte, unsigned long addr)
+static pte_t set_pte_filter(pte_t pte)
 {
 	pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
 	if (pte_looks_normal(pte) && !(cpu_has_feature(CPU_FTR_COHERENT_ICACHE) ||
@@ -81,17 +79,6 @@
 		if (!pg)
 			return pte;
 		if (!test_bit(PG_arch_1, &pg->flags)) {
-#ifdef CONFIG_8xx
-			/* On 8xx, cache control instructions (particularly
-			 * "dcbst" from flush_dcache_icache) fault as write
-			 * operation if there is an unpopulated TLB entry
-			 * for the address in question. To workaround that,
-			 * we invalidate the TLB here, thus avoiding dcbst
-			 * misbehaviour.
-			 */
-			/* 8xx doesn't care about PID, size or ind args */
-			_tlbil_va(addr, 0, 0, 0);
-#endif /* CONFIG_8xx */
 			flush_dcache_icache_page(pg);
 			set_bit(PG_arch_1, &pg->flags);
 		}
@@ -111,7 +98,7 @@
  * as we don't have two bits to spare for _PAGE_EXEC and _PAGE_HWEXEC so
  * instead we "filter out" the exec permission for non clean pages.
  */
-static pte_t set_pte_filter(pte_t pte, unsigned long addr)
+static pte_t set_pte_filter(pte_t pte)
 {
 	struct page *pg;
 
@@ -193,7 +180,7 @@
 	 * this context might not have been activated yet when this
 	 * is called.
 	 */
-	pte = set_pte_filter(pte, addr);
+	pte = set_pte_filter(pte);
 
 	/* Perform the setting of the PTE */
 	__set_pte_at(mm, addr, ptep, pte, 0);
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index 8a5dfaf..9aee27c 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -39,6 +39,7 @@
 #define r_X		5
 #define r_addr		6
 #define r_scratch1	7
+#define r_scratch2	8
 #define r_D		14
 #define r_HL		15
 #define r_M		16
@@ -92,6 +93,8 @@
 				     ___PPC_RA(base) | IMM_L(i))
 #define PPC_LHZ(r, base, i)	EMIT(PPC_INST_LHZ | ___PPC_RT(r) |	      \
 				     ___PPC_RA(base) | IMM_L(i))
+#define PPC_LHBRX(r, base, b)	EMIT(PPC_INST_LHBRX | ___PPC_RT(r) |	      \
+				     ___PPC_RA(base) | ___PPC_RB(b))
 /* Convenience helpers for the above with 'far' offsets: */
 #define PPC_LD_OFFS(r, base, i) do { if ((i) < 32768) PPC_LD(r, base, i);     \
 		else {	PPC_ADDIS(r, base, IMM_HA(i));			      \
@@ -186,6 +189,14 @@
 				PPC_ORI(d, d, (uintptr_t)(i) & 0xffff);	      \
 		} } while (0);
 
+#define PPC_LHBRX_OFFS(r, base, i) \
+		do { PPC_LI32(r, i); PPC_LHBRX(r, r, base); } while(0)
+#ifdef __LITTLE_ENDIAN__
+#define PPC_NTOHS_OFFS(r, base, i)	PPC_LHBRX_OFFS(r, base, i)
+#else
+#define PPC_NTOHS_OFFS(r, base, i)	PPC_LHZ_OFFS(r, base, i)
+#endif
+
 static inline bool is_nearbranch(int offset)
 {
 	return (offset < 32768) && (offset >= -32768);
diff --git a/arch/powerpc/net/bpf_jit_64.S b/arch/powerpc/net/bpf_jit_64.S
index 7d3a3b5..e76eba7 100644
--- a/arch/powerpc/net/bpf_jit_64.S
+++ b/arch/powerpc/net/bpf_jit_64.S
@@ -43,8 +43,11 @@
 	cmpd	r_scratch1, r_addr
 	blt	bpf_slow_path_word
 	/* Nope, just hitting the header.  cr0 here is eq or gt! */
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	r_A, r_D, r_addr
+#else
 	lwzx	r_A, r_D, r_addr
-	/* When big endian we don't need to byteswap. */
+#endif
 	blr	/* Return success, cr0 != LT */
 
 	.globl	sk_load_half
@@ -56,7 +59,11 @@
 	subi	r_scratch1, r_HL, 2
 	cmpd	r_scratch1, r_addr
 	blt	bpf_slow_path_half
+#ifdef __LITTLE_ENDIAN__
+	lhbrx	r_A, r_D, r_addr
+#else
 	lhzx	r_A, r_D, r_addr
+#endif
 	blr
 
 	.globl	sk_load_byte
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index bf56e33..ac3c2a1 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -17,14 +17,8 @@
 
 #include "bpf_jit.h"
 
-#ifndef __BIG_ENDIAN
-/* There are endianness assumptions herein. */
-#error "Little-endian PPC not supported in BPF compiler"
-#endif
-
 int bpf_jit_enable __read_mostly;
 
-
 static inline void bpf_flush_icache(void *start, void *end)
 {
 	smp_wmb();
@@ -193,6 +187,26 @@
 				PPC_MUL(r_A, r_A, r_scratch1);
 			}
 			break;
+		case BPF_S_ALU_MOD_X: /* A %= X; */
+			ctx->seen |= SEEN_XREG;
+			PPC_CMPWI(r_X, 0);
+			if (ctx->pc_ret0 != -1) {
+				PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
+			} else {
+				PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);
+				PPC_LI(r_ret, 0);
+				PPC_JMP(exit_addr);
+			}
+			PPC_DIVWU(r_scratch1, r_A, r_X);
+			PPC_MUL(r_scratch1, r_X, r_scratch1);
+			PPC_SUB(r_A, r_A, r_scratch1);
+			break;
+		case BPF_S_ALU_MOD_K: /* A %= K; */
+			PPC_LI32(r_scratch2, K);
+			PPC_DIVWU(r_scratch1, r_A, r_scratch2);
+			PPC_MUL(r_scratch1, r_scratch2, r_scratch1);
+			PPC_SUB(r_A, r_A, r_scratch1);
+			break;
 		case BPF_S_ALU_DIV_X: /* A /= X; */
 			ctx->seen |= SEEN_XREG;
 			PPC_CMPWI(r_X, 0);
@@ -346,18 +360,11 @@
 			break;
 
 			/*** Ancillary info loads ***/
-
-			/* None of the BPF_S_ANC* codes appear to be passed by
-			 * sk_chk_filter().  The interpreter and the x86 BPF
-			 * compiler implement them so we do too -- they may be
-			 * planted in future.
-			 */
 		case BPF_S_ANC_PROTOCOL: /* A = ntohs(skb->protocol); */
 			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
 						  protocol) != 2);
-			PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
-							  protocol));
-			/* ntohs is a NOP with BE loads. */
+			PPC_NTOHS_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+							    protocol));
 			break;
 		case BPF_S_ANC_IFINDEX:
 			PPC_LD_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,
@@ -691,4 +698,5 @@
 {
 	if (fp->bpf_func != sk_run_filter)
 		module_free(NULL, fp->bpf_func);
+	kfree(fp);
 }
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
index e504166..fd8a376 100644
--- a/arch/powerpc/platforms/512x/clock.c
+++ b/arch/powerpc/platforms/512x/clock.c
@@ -24,6 +24,7 @@
 #include <linux/mutex.h>
 #include <linux/io.h>
 
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <asm/mpc5xxx.h>
 #include <asm/mpc5121.h>
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index a82a41b..36b5652 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -60,8 +60,6 @@
 		;
 }
 
-#if IS_ENABLED(CONFIG_FB_FSL_DIU)
-
 struct fsl_diu_shared_fb {
 	u8		gamma[0x300];	/* 32-bit aligned! */
 	struct diu_ad	ad0;		/* 32-bit aligned! */
@@ -71,7 +69,7 @@
 };
 
 #define DIU_DIV_MASK	0x000000ff
-void mpc512x_set_pixel_clock(unsigned int pixclock)
+static void mpc512x_set_pixel_clock(unsigned int pixclock)
 {
 	unsigned long bestval, bestfreq, speed, busfreq;
 	unsigned long minpixclock, maxpixclock, pixval;
@@ -164,7 +162,7 @@
 	iounmap(ccm);
 }
 
-enum fsl_diu_monitor_port
+static enum fsl_diu_monitor_port
 mpc512x_valid_monitor_port(enum fsl_diu_monitor_port port)
 {
 	return FSL_DIU_PORT_DVI;
@@ -179,7 +177,7 @@
 	free_reserved_page(page);
 }
 
-void mpc512x_release_bootmem(void)
+static void mpc512x_release_bootmem(void)
 {
 	unsigned long addr = diu_shared_fb.fb_phys & PAGE_MASK;
 	unsigned long size = diu_shared_fb.fb_len;
@@ -205,7 +203,7 @@
  * address range will be reserved in setup_arch() after bootmem
  * allocator is up.
  */
-void __init mpc512x_init_diu(void)
+static void __init mpc512x_init_diu(void)
 {
 	struct device_node *np;
 	struct diu __iomem *diu_reg;
@@ -274,7 +272,7 @@
 	iounmap(diu_reg);
 }
 
-void __init mpc512x_setup_diu(void)
+static void __init mpc512x_setup_diu(void)
 {
 	int ret;
 
@@ -303,8 +301,6 @@
 	diu_ops.release_bootmem		= mpc512x_release_bootmem;
 }
 
-#endif
-
 void __init mpc512x_init_IRQ(void)
 {
 	struct device_node *np;
@@ -337,7 +333,7 @@
 	{},
 };
 
-void __init mpc512x_declare_of_platform_devices(void)
+static void __init mpc512x_declare_of_platform_devices(void)
 {
 	if (of_platform_bus_probe(NULL, of_bus_ids, NULL))
 		printk(KERN_ERR __FILE__ ": "
@@ -387,7 +383,7 @@
 		    ((u32)(_base) + sizeof(struct mpc52xx_psc)))
 
 /* Init PSC FIFO space for TX and RX slices */
-void __init mpc512x_psc_fifo_init(void)
+static void __init mpc512x_psc_fifo_init(void)
 {
 	struct device_node *np;
 	void __iomem *psc;
diff --git a/arch/powerpc/platforms/512x/pdm360ng.c b/arch/powerpc/platforms/512x/pdm360ng.c
index 24b314d..116f2325 100644
--- a/arch/powerpc/platforms/512x/pdm360ng.c
+++ b/arch/powerpc/platforms/512x/pdm360ng.c
@@ -14,6 +14,8 @@
 
 #include <linux/kernel.h>
 #include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 
 #include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig
index 90f4496..af54174 100644
--- a/arch/powerpc/platforms/52xx/Kconfig
+++ b/arch/powerpc/platforms/52xx/Kconfig
@@ -57,5 +57,5 @@
 
 config PPC_MPC5200_LPBFIFO
 	tristate "MPC5200 LocalPlus bus FIFO driver"
-	depends on PPC_MPC52xx
+	depends on PPC_MPC52xx && PPC_BESTCOMM
 	select PPC_BESTCOMM_GEN_BD
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
index b69221b..2898b73 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -340,7 +340,7 @@
 {
 	int l1irq;
 	int l2irq;
-	struct irq_chip *irqchip;
+	struct irq_chip *uninitialized_var(irqchip);
 	void *hndlr;
 	int type;
 	u32 reg;
@@ -373,9 +373,8 @@
 	case MPC52xx_IRQ_L1_PERP: irqchip = &mpc52xx_periph_irqchip; break;
 	case MPC52xx_IRQ_L1_SDMA: irqchip = &mpc52xx_sdma_irqchip; break;
 	case MPC52xx_IRQ_L1_CRIT:
-	default:
 		pr_warn("%s: Critical IRQ #%d is unsupported! Nopping it.\n",
-			__func__, l1irq);
+			__func__, l2irq);
 		irq_set_chip(virq, &no_irq_chip);
 		return 0;
 	}
diff --git a/arch/powerpc/platforms/82xx/mpc8272_ads.c b/arch/powerpc/platforms/82xx/mpc8272_ads.c
index 30394b4..6a14cf5 100644
--- a/arch/powerpc/platforms/82xx/mpc8272_ads.c
+++ b/arch/powerpc/platforms/82xx/mpc8272_ads.c
@@ -16,6 +16,8 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/fsl_devices.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 #include <linux/io.h>
 
diff --git a/arch/powerpc/platforms/82xx/pq2fads.c b/arch/powerpc/platforms/82xx/pq2fads.c
index e1dceee..e5f82ec 100644
--- a/arch/powerpc/platforms/82xx/pq2fads.c
+++ b/arch/powerpc/platforms/82xx/pq2fads.c
@@ -15,6 +15,8 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/fsl_devices.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 
 #include <asm/io.h>
diff --git a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
index 7bc3158..fd71cfd 100644
--- a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
+++ b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
@@ -204,7 +204,6 @@
 	ret = mcu_gpiochip_remove(mcu);
 	if (ret)
 		return ret;
-	i2c_set_clientdata(client, NULL);
 	kfree(mcu);
 	return 0;
 }
diff --git a/arch/powerpc/platforms/83xx/suspend.c b/arch/powerpc/platforms/83xx/suspend.c
index 1d769a2..3d9716c 100644
--- a/arch/powerpc/platforms/83xx/suspend.c
+++ b/arch/powerpc/platforms/83xx/suspend.c
@@ -20,6 +20,8 @@
 #include <linux/freezer.h>
 #include <linux/suspend.h>
 #include <linux/fsl_devices.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/export.h>
 
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index de2eb93..4d46349 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -218,83 +218,16 @@
 	  This board is a 3U CompactPCI Single Board Computer with a Freescale
 	  P2020 processor.
 
-config P2041_RDB
-	bool "Freescale P2041 RDB"
-	select DEFAULT_UIMAGE
-	select PPC_E500MC
-	select PHYS_64BIT
-	select SWIOTLB
-	select ARCH_REQUIRE_GPIOLIB
-	select GPIO_MPC8XXX
-	select HAS_RAPIDIO
-	select PPC_EPAPR_HV_PIC
-	help
-	  This option enables support for the P2041 RDB board
-
-config P3041_DS
-	bool "Freescale P3041 DS"
-	select DEFAULT_UIMAGE
-	select PPC_E500MC
-	select PHYS_64BIT
-	select SWIOTLB
-	select ARCH_REQUIRE_GPIOLIB
-	select GPIO_MPC8XXX
-	select HAS_RAPIDIO
-	select PPC_EPAPR_HV_PIC
-	help
-	  This option enables support for the P3041 DS board
-
-config P4080_DS
-	bool "Freescale P4080 DS"
-	select DEFAULT_UIMAGE
-	select PPC_E500MC
-	select PHYS_64BIT
-	select SWIOTLB
-	select ARCH_REQUIRE_GPIOLIB
-	select GPIO_MPC8XXX
-	select HAS_RAPIDIO
-	select PPC_EPAPR_HV_PIC
-	help
-	  This option enables support for the P4080 DS board
-
 config SGY_CTS1000
 	tristate "Servergy CTS-1000 support"
 	select GPIOLIB
 	select OF_GPIO
-	depends on P4080_DS
+	depends on CORENET_GENERIC
 	help
 	  Enable this to support functionality in Servergy's CTS-1000 systems.
 
 endif # PPC32
 
-config P5020_DS
-	bool "Freescale P5020 DS"
-	select DEFAULT_UIMAGE
-	select E500
-	select PPC_E500MC
-	select PHYS_64BIT
-	select SWIOTLB
-	select ARCH_REQUIRE_GPIOLIB
-	select GPIO_MPC8XXX
-	select HAS_RAPIDIO
-	select PPC_EPAPR_HV_PIC
-	help
-	  This option enables support for the P5020 DS board
-
-config P5040_DS
-	bool "Freescale P5040 DS"
-	select DEFAULT_UIMAGE
-	select E500
-	select PPC_E500MC
-	select PHYS_64BIT
-	select SWIOTLB
-	select ARCH_REQUIRE_GPIOLIB
-	select GPIO_MPC8XXX
-	select HAS_RAPIDIO
-	select PPC_EPAPR_HV_PIC
-	help
-	  This option enables support for the P5040 DS board
-
 config PPC_QEMU_E500
 	bool "QEMU generic e500 platform"
 	select DEFAULT_UIMAGE
@@ -310,10 +243,8 @@
 	  unset based on the emulated CPU (or actual host CPU in the case
 	  of KVM).
 
-if PPC64
-
-config T4240_QDS
-	bool "Freescale T4240 QDS"
+config CORENET_GENERIC
+	bool "Freescale CoreNet Generic"
 	select DEFAULT_UIMAGE
 	select E500
 	select PPC_E500MC
@@ -324,26 +255,14 @@
 	select HAS_RAPIDIO
 	select PPC_EPAPR_HV_PIC
 	help
-	  This option enables support for the T4240 QDS board
+	  This option enables support for the FSL CoreNet based boards.
+	  For 32bit kernel, the following boards are supported:
+	    P2041 RDB, P3041 DS and P4080 DS
+	  For 64bit kernel, the following boards are supported:
+	    T4240 QDS and B4 QDS
+	  The following boards are supported for both 32bit and 64bit kernel:
+	    P5020 DS and P5040 DS
 
-config B4_QDS
-	bool "Freescale B4 QDS"
-	select DEFAULT_UIMAGE
-	select E500
-	select PPC_E500MC
-	select PHYS_64BIT
-	select SWIOTLB
-	select GPIOLIB
-	select ARCH_REQUIRE_GPIOLIB
-	select HAS_RAPIDIO
-	select PPC_EPAPR_HV_PIC
-	help
-	  This option enables support for the B4 QDS board
-	  The B4 application development system B4 QDS is a complete
-	  debugging environment intended for engineers developing
-	  applications for the B4.
-
-endif
 endif # FSL_SOC_BOOKE
 
 config TQM85xx
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index 53c9f75..dd4c0b5 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -18,13 +18,7 @@
 obj-$(CONFIG_P1022_DS)    += p1022_ds.o
 obj-$(CONFIG_P1022_RDK)   += p1022_rdk.o
 obj-$(CONFIG_P1023_RDS)   += p1023_rds.o
-obj-$(CONFIG_P2041_RDB)   += p2041_rdb.o corenet_ds.o
-obj-$(CONFIG_P3041_DS)    += p3041_ds.o corenet_ds.o
-obj-$(CONFIG_P4080_DS)    += p4080_ds.o corenet_ds.o
-obj-$(CONFIG_P5020_DS)    += p5020_ds.o corenet_ds.o
-obj-$(CONFIG_P5040_DS)    += p5040_ds.o corenet_ds.o
-obj-$(CONFIG_T4240_QDS)   += t4240_qds.o corenet_ds.o
-obj-$(CONFIG_B4_QDS)	  += b4_qds.o corenet_ds.o
+obj-$(CONFIG_CORENET_GENERIC)   += corenet_generic.o
 obj-$(CONFIG_STX_GP3)	  += stx_gp3.o
 obj-$(CONFIG_TQM85xx)	  += tqm85xx.o
 obj-$(CONFIG_SBC8548)     += sbc8548.o
diff --git a/arch/powerpc/platforms/85xx/b4_qds.c b/arch/powerpc/platforms/85xx/b4_qds.c
deleted file mode 100644
index 0c6702f..0000000
--- a/arch/powerpc/platforms/85xx/b4_qds.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * B4 QDS Setup
- * Should apply for QDS platform of B4860 and it's personalities.
- * viz B4860/B4420/B4220QDS
- *
- * Copyright 2012 Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/phy.h>
-
-#include <asm/time.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <mm/mmu_decl.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/mpic.h>
-
-#include <linux/of_platform.h>
-#include <sysdev/fsl_soc.h>
-#include <sysdev/fsl_pci.h>
-#include <asm/ehv_pic.h>
-
-#include "corenet_ds.h"
-
-/*
- * Called very early, device-tree isn't unflattened
- */
-static int __init b4_qds_probe(void)
-{
-	unsigned long root = of_get_flat_dt_root();
-#ifdef CONFIG_SMP
-	extern struct smp_ops_t smp_85xx_ops;
-#endif
-
-	if ((of_flat_dt_is_compatible(root, "fsl,B4860QDS")) ||
-		(of_flat_dt_is_compatible(root, "fsl,B4420QDS")) ||
-			(of_flat_dt_is_compatible(root, "fsl,B4220QDS")))
-		return 1;
-
-	/* Check if we're running under the Freescale hypervisor */
-	if ((of_flat_dt_is_compatible(root, "fsl,B4860QDS-hv")) ||
-		(of_flat_dt_is_compatible(root, "fsl,B4420QDS-hv")) ||
-			(of_flat_dt_is_compatible(root, "fsl,B4220QDS-hv"))) {
-		ppc_md.init_IRQ = ehv_pic_init;
-		ppc_md.get_irq = ehv_pic_get_irq;
-		ppc_md.restart = fsl_hv_restart;
-		ppc_md.power_off = fsl_hv_halt;
-		ppc_md.halt = fsl_hv_halt;
-#ifdef CONFIG_SMP
-		/*
-		 * Disable the timebase sync operations because we can't write
-		 * to the timebase registers under the hypervisor.
-		  */
-		smp_85xx_ops.give_timebase = NULL;
-		smp_85xx_ops.take_timebase = NULL;
-#endif
-		return 1;
-	}
-
-	return 0;
-}
-
-define_machine(b4_qds) {
-	.name			= "B4 QDS",
-	.probe			= b4_qds_probe,
-	.setup_arch		= corenet_ds_setup_arch,
-	.init_IRQ		= corenet_ds_pic_init,
-#ifdef CONFIG_PCI
-	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
-#endif
-/* coreint doesn't play nice with lazy EE, use legacy mpic for now */
-#ifdef CONFIG_PPC64
-	.get_irq		= mpic_get_irq,
-#else
-	.get_irq		= mpic_get_coreint_irq,
-#endif
-	.restart		= fsl_rstcr_restart,
-	.calibrate_decr		= generic_calibrate_decr,
-	.progress		= udbg_progress,
-#ifdef CONFIG_PPC64
-	.power_save		= book3e_idle,
-#else
-	.power_save		= e500_idle,
-#endif
-};
-
-machine_arch_initcall(b4_qds, corenet_ds_publish_devices);
-
-#ifdef CONFIG_SWIOTLB
-machine_arch_initcall(b4_qds, swiotlb_setup_bus_notifier);
-#endif
diff --git a/arch/powerpc/platforms/85xx/c293pcie.c b/arch/powerpc/platforms/85xx/c293pcie.c
index 6208e49..213d5b8 100644
--- a/arch/powerpc/platforms/85xx/c293pcie.c
+++ b/arch/powerpc/platforms/85xx/c293pcie.c
@@ -11,6 +11,7 @@
 
 #include <linux/stddef.h>
 #include <linux/kernel.h>
+#include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 
 #include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/85xx/common.c b/arch/powerpc/platforms/85xx/common.c
index d0861a0..eba78c8 100644
--- a/arch/powerpc/platforms/85xx/common.c
+++ b/arch/powerpc/platforms/85xx/common.c
@@ -5,6 +5,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
 #include <sysdev/cpm2_pic.h>
diff --git a/arch/powerpc/platforms/85xx/corenet_ds.c b/arch/powerpc/platforms/85xx/corenet_ds.c
deleted file mode 100644
index aa3690b..0000000
--- a/arch/powerpc/platforms/85xx/corenet_ds.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Corenet based SoC DS Setup
- *
- * Maintained by Kumar Gala (see MAINTAINERS for contact information)
- *
- * Copyright 2009-2011 Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-
-#include <asm/time.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <asm/ppc-pci.h>
-#include <mm/mmu_decl.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/mpic.h>
-
-#include <linux/of_platform.h>
-#include <sysdev/fsl_soc.h>
-#include <sysdev/fsl_pci.h>
-#include "smp.h"
-
-void __init corenet_ds_pic_init(void)
-{
-	struct mpic *mpic;
-	unsigned int flags = MPIC_BIG_ENDIAN | MPIC_SINGLE_DEST_CPU |
-		MPIC_NO_RESET;
-
-	if (ppc_md.get_irq == mpic_get_coreint_irq)
-		flags |= MPIC_ENABLE_COREINT;
-
-	mpic = mpic_alloc(NULL, 0, flags, 0, 512, " OpenPIC  ");
-	BUG_ON(mpic == NULL);
-
-	mpic_init(mpic);
-}
-
-/*
- * Setup the architecture
- */
-void __init corenet_ds_setup_arch(void)
-{
-	mpc85xx_smp_init();
-
-	swiotlb_detect_4g();
-
-	pr_info("%s board from Freescale Semiconductor\n", ppc_md.name);
-}
-
-static const struct of_device_id of_device_ids[] = {
-	{
-		.compatible	= "simple-bus"
-	},
-	{
-		.compatible	= "fsl,srio",
-	},
-	{
-		.compatible	= "fsl,p4080-pcie",
-	},
-	{
-		.compatible	= "fsl,qoriq-pcie-v2.2",
-	},
-	{
-		.compatible	= "fsl,qoriq-pcie-v2.3",
-	},
-	{
-		.compatible	= "fsl,qoriq-pcie-v2.4",
-	},
-	{
-		.compatible	= "fsl,qoriq-pcie-v3.0",
-	},
-	/* The following two are for the Freescale hypervisor */
-	{
-		.name		= "hypervisor",
-	},
-	{
-		.name		= "handles",
-	},
-	{}
-};
-
-int __init corenet_ds_publish_devices(void)
-{
-	return of_platform_bus_probe(NULL, of_device_ids, NULL);
-}
diff --git a/arch/powerpc/platforms/85xx/corenet_ds.h b/arch/powerpc/platforms/85xx/corenet_ds.h
deleted file mode 100644
index ddd700b..0000000
--- a/arch/powerpc/platforms/85xx/corenet_ds.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Corenet based SoC DS Setup
- *
- * Copyright 2009 Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#ifndef CORENET_DS_H
-#define CORENET_DS_H
-
-extern void __init corenet_ds_pic_init(void);
-extern void __init corenet_ds_setup_arch(void);
-extern int __init corenet_ds_publish_devices(void);
-
-#endif
diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c
new file mode 100644
index 0000000..fbd871e
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/corenet_generic.c
@@ -0,0 +1,182 @@
+/*
+ * Corenet based SoC DS Setup
+ *
+ * Maintained by Kumar Gala (see MAINTAINERS for contact information)
+ *
+ * Copyright 2009-2011 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/ppc-pci.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+#include <asm/ehv_pic.h>
+
+#include <linux/of_platform.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+#include "smp.h"
+
+void __init corenet_gen_pic_init(void)
+{
+	struct mpic *mpic;
+	unsigned int flags = MPIC_BIG_ENDIAN | MPIC_SINGLE_DEST_CPU |
+		MPIC_NO_RESET;
+
+	if (ppc_md.get_irq == mpic_get_coreint_irq)
+		flags |= MPIC_ENABLE_COREINT;
+
+	mpic = mpic_alloc(NULL, 0, flags, 0, 512, " OpenPIC  ");
+	BUG_ON(mpic == NULL);
+
+	mpic_init(mpic);
+}
+
+/*
+ * Setup the architecture
+ */
+void __init corenet_gen_setup_arch(void)
+{
+	mpc85xx_smp_init();
+
+	swiotlb_detect_4g();
+
+	pr_info("%s board from Freescale Semiconductor\n", ppc_md.name);
+}
+
+static const struct of_device_id of_device_ids[] = {
+	{
+		.compatible	= "simple-bus"
+	},
+	{
+		.compatible	= "fsl,srio",
+	},
+	{
+		.compatible	= "fsl,p4080-pcie",
+	},
+	{
+		.compatible	= "fsl,qoriq-pcie-v2.2",
+	},
+	{
+		.compatible	= "fsl,qoriq-pcie-v2.3",
+	},
+	{
+		.compatible	= "fsl,qoriq-pcie-v2.4",
+	},
+	{
+		.compatible	= "fsl,qoriq-pcie-v3.0",
+	},
+	/* The following two are for the Freescale hypervisor */
+	{
+		.name		= "hypervisor",
+	},
+	{
+		.name		= "handles",
+	},
+	{}
+};
+
+int __init corenet_gen_publish_devices(void)
+{
+	return of_platform_bus_probe(NULL, of_device_ids, NULL);
+}
+
+static const char * const boards[] __initconst = {
+	"fsl,P2041RDB",
+	"fsl,P3041DS",
+	"fsl,P4080DS",
+	"fsl,P5020DS",
+	"fsl,P5040DS",
+	"fsl,T4240QDS",
+	"fsl,B4860QDS",
+	"fsl,B4420QDS",
+	"fsl,B4220QDS",
+	NULL
+};
+
+static const char * const hv_boards[] __initconst = {
+	"fsl,P2041RDB-hv",
+	"fsl,P3041DS-hv",
+	"fsl,P4080DS-hv",
+	"fsl,P5020DS-hv",
+	"fsl,P5040DS-hv",
+	"fsl,T4240QDS-hv",
+	"fsl,B4860QDS-hv",
+	"fsl,B4420QDS-hv",
+	"fsl,B4220QDS-hv",
+	NULL
+};
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init corenet_generic_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+#ifdef CONFIG_SMP
+	extern struct smp_ops_t smp_85xx_ops;
+#endif
+
+	if (of_flat_dt_match(root, boards))
+		return 1;
+
+	/* Check if we're running under the Freescale hypervisor */
+	if (of_flat_dt_match(root, hv_boards)) {
+		ppc_md.init_IRQ = ehv_pic_init;
+		ppc_md.get_irq = ehv_pic_get_irq;
+		ppc_md.restart = fsl_hv_restart;
+		ppc_md.power_off = fsl_hv_halt;
+		ppc_md.halt = fsl_hv_halt;
+#ifdef CONFIG_SMP
+		/*
+		 * Disable the timebase sync operations because we can't write
+		 * to the timebase registers under the hypervisor.
+		  */
+		smp_85xx_ops.give_timebase = NULL;
+		smp_85xx_ops.take_timebase = NULL;
+#endif
+		return 1;
+	}
+
+	return 0;
+}
+
+define_machine(corenet_generic) {
+	.name			= "CoreNet Generic",
+	.probe			= corenet_generic_probe,
+	.setup_arch		= corenet_gen_setup_arch,
+	.init_IRQ		= corenet_gen_pic_init,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+	.get_irq		= mpic_get_coreint_irq,
+	.restart		= fsl_rstcr_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+#ifdef CONFIG_PPC64
+	.power_save		= book3e_idle,
+#else
+	.power_save		= e500_idle,
+#endif
+};
+
+machine_arch_initcall(corenet_generic, corenet_gen_publish_devices);
+
+#ifdef CONFIG_SWIOTLB
+machine_arch_initcall(corenet_generic, swiotlb_setup_bus_notifier);
+#endif
diff --git a/arch/powerpc/platforms/85xx/p1010rdb.c b/arch/powerpc/platforms/85xx/p1010rdb.c
index 0252961..d6a3dd3 100644
--- a/arch/powerpc/platforms/85xx/p1010rdb.c
+++ b/arch/powerpc/platforms/85xx/p1010rdb.c
@@ -66,6 +66,8 @@
 
 	if (of_flat_dt_is_compatible(root, "fsl,P1010RDB"))
 		return 1;
+	if (of_flat_dt_is_compatible(root, "fsl,P1010RDB-PB"))
+		return 1;
 	return 0;
 }
 
diff --git a/arch/powerpc/platforms/85xx/p2041_rdb.c b/arch/powerpc/platforms/85xx/p2041_rdb.c
deleted file mode 100644
index 000c089..0000000
--- a/arch/powerpc/platforms/85xx/p2041_rdb.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * P2041 RDB Setup
- *
- * Copyright 2011 Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/phy.h>
-
-#include <asm/time.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <mm/mmu_decl.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/mpic.h>
-
-#include <linux/of_platform.h>
-#include <sysdev/fsl_soc.h>
-#include <sysdev/fsl_pci.h>
-#include <asm/ehv_pic.h>
-
-#include "corenet_ds.h"
-
-/*
- * Called very early, device-tree isn't unflattened
- */
-static int __init p2041_rdb_probe(void)
-{
-	unsigned long root = of_get_flat_dt_root();
-#ifdef CONFIG_SMP
-	extern struct smp_ops_t smp_85xx_ops;
-#endif
-
-	if (of_flat_dt_is_compatible(root, "fsl,P2041RDB"))
-		return 1;
-
-	/* Check if we're running under the Freescale hypervisor */
-	if (of_flat_dt_is_compatible(root, "fsl,P2041RDB-hv")) {
-		ppc_md.init_IRQ = ehv_pic_init;
-		ppc_md.get_irq = ehv_pic_get_irq;
-		ppc_md.restart = fsl_hv_restart;
-		ppc_md.power_off = fsl_hv_halt;
-		ppc_md.halt = fsl_hv_halt;
-#ifdef CONFIG_SMP
-		/*
-		 * Disable the timebase sync operations because we can't write
-		 * to the timebase registers under the hypervisor.
-		  */
-		smp_85xx_ops.give_timebase = NULL;
-		smp_85xx_ops.take_timebase = NULL;
-#endif
-		return 1;
-	}
-
-	return 0;
-}
-
-define_machine(p2041_rdb) {
-	.name			= "P2041 RDB",
-	.probe			= p2041_rdb_probe,
-	.setup_arch		= corenet_ds_setup_arch,
-	.init_IRQ		= corenet_ds_pic_init,
-#ifdef CONFIG_PCI
-	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
-#endif
-	.get_irq		= mpic_get_coreint_irq,
-	.restart		= fsl_rstcr_restart,
-	.calibrate_decr		= generic_calibrate_decr,
-	.progress		= udbg_progress,
-	.power_save		= e500_idle,
-};
-
-machine_arch_initcall(p2041_rdb, corenet_ds_publish_devices);
-
-#ifdef CONFIG_SWIOTLB
-machine_arch_initcall(p2041_rdb, swiotlb_setup_bus_notifier);
-#endif
diff --git a/arch/powerpc/platforms/85xx/p3041_ds.c b/arch/powerpc/platforms/85xx/p3041_ds.c
deleted file mode 100644
index b3edc20..0000000
--- a/arch/powerpc/platforms/85xx/p3041_ds.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * P3041 DS Setup
- *
- * Maintained by Kumar Gala (see MAINTAINERS for contact information)
- *
- * Copyright 2009-2010 Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/phy.h>
-
-#include <asm/time.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <mm/mmu_decl.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/mpic.h>
-
-#include <linux/of_platform.h>
-#include <sysdev/fsl_soc.h>
-#include <sysdev/fsl_pci.h>
-#include <asm/ehv_pic.h>
-
-#include "corenet_ds.h"
-
-/*
- * Called very early, device-tree isn't unflattened
- */
-static int __init p3041_ds_probe(void)
-{
-	unsigned long root = of_get_flat_dt_root();
-#ifdef CONFIG_SMP
-	extern struct smp_ops_t smp_85xx_ops;
-#endif
-
-	if (of_flat_dt_is_compatible(root, "fsl,P3041DS"))
-		return 1;
-
-	/* Check if we're running under the Freescale hypervisor */
-	if (of_flat_dt_is_compatible(root, "fsl,P3041DS-hv")) {
-		ppc_md.init_IRQ = ehv_pic_init;
-		ppc_md.get_irq = ehv_pic_get_irq;
-		ppc_md.restart = fsl_hv_restart;
-		ppc_md.power_off = fsl_hv_halt;
-		ppc_md.halt = fsl_hv_halt;
-#ifdef CONFIG_SMP
-		/*
-		 * Disable the timebase sync operations because we can't write
-		 * to the timebase registers under the hypervisor.
-		  */
-		smp_85xx_ops.give_timebase = NULL;
-		smp_85xx_ops.take_timebase = NULL;
-#endif
-		return 1;
-	}
-
-	return 0;
-}
-
-define_machine(p3041_ds) {
-	.name			= "P3041 DS",
-	.probe			= p3041_ds_probe,
-	.setup_arch		= corenet_ds_setup_arch,
-	.init_IRQ		= corenet_ds_pic_init,
-#ifdef CONFIG_PCI
-	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
-#endif
-	.get_irq		= mpic_get_coreint_irq,
-	.restart		= fsl_rstcr_restart,
-	.calibrate_decr		= generic_calibrate_decr,
-	.progress		= udbg_progress,
-	.power_save		= e500_idle,
-};
-
-machine_arch_initcall(p3041_ds, corenet_ds_publish_devices);
-
-#ifdef CONFIG_SWIOTLB
-machine_arch_initcall(p3041_ds, swiotlb_setup_bus_notifier);
-#endif
diff --git a/arch/powerpc/platforms/85xx/p4080_ds.c b/arch/powerpc/platforms/85xx/p4080_ds.c
deleted file mode 100644
index 54df106..0000000
--- a/arch/powerpc/platforms/85xx/p4080_ds.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * P4080 DS Setup
- *
- * Maintained by Kumar Gala (see MAINTAINERS for contact information)
- *
- * Copyright 2009 Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-
-#include <asm/time.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <mm/mmu_decl.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/mpic.h>
-
-#include <linux/of_platform.h>
-#include <sysdev/fsl_soc.h>
-#include <sysdev/fsl_pci.h>
-#include <asm/ehv_pic.h>
-
-#include "corenet_ds.h"
-
-/*
- * Called very early, device-tree isn't unflattened
- */
-static int __init p4080_ds_probe(void)
-{
-	unsigned long root = of_get_flat_dt_root();
-#ifdef CONFIG_SMP
-	extern struct smp_ops_t smp_85xx_ops;
-#endif
-
-	if (of_flat_dt_is_compatible(root, "fsl,P4080DS"))
-		return 1;
-
-	/* Check if we're running under the Freescale hypervisor */
-	if (of_flat_dt_is_compatible(root, "fsl,P4080DS-hv")) {
-		ppc_md.init_IRQ = ehv_pic_init;
-		ppc_md.get_irq = ehv_pic_get_irq;
-		ppc_md.restart = fsl_hv_restart;
-		ppc_md.power_off = fsl_hv_halt;
-		ppc_md.halt = fsl_hv_halt;
-#ifdef CONFIG_SMP
-		/*
-		 * Disable the timebase sync operations because we can't write
-		 * to the timebase registers under the hypervisor.
-		  */
-		smp_85xx_ops.give_timebase = NULL;
-		smp_85xx_ops.take_timebase = NULL;
-#endif
-		return 1;
-	}
-
-	return 0;
-}
-
-define_machine(p4080_ds) {
-	.name			= "P4080 DS",
-	.probe			= p4080_ds_probe,
-	.setup_arch		= corenet_ds_setup_arch,
-	.init_IRQ		= corenet_ds_pic_init,
-#ifdef CONFIG_PCI
-	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
-#endif
-	.get_irq		= mpic_get_coreint_irq,
-	.restart		= fsl_rstcr_restart,
-	.calibrate_decr		= generic_calibrate_decr,
-	.progress		= udbg_progress,
-	.power_save		= e500_idle,
-};
-
-machine_arch_initcall(p4080_ds, corenet_ds_publish_devices);
-#ifdef CONFIG_SWIOTLB
-machine_arch_initcall(p4080_ds, swiotlb_setup_bus_notifier);
-#endif
diff --git a/arch/powerpc/platforms/85xx/p5020_ds.c b/arch/powerpc/platforms/85xx/p5020_ds.c
deleted file mode 100644
index 39cfa40..0000000
--- a/arch/powerpc/platforms/85xx/p5020_ds.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * P5020 DS Setup
- *
- * Maintained by Kumar Gala (see MAINTAINERS for contact information)
- *
- * Copyright 2009-2010 Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/phy.h>
-
-#include <asm/time.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <mm/mmu_decl.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/mpic.h>
-
-#include <linux/of_platform.h>
-#include <sysdev/fsl_soc.h>
-#include <sysdev/fsl_pci.h>
-#include <asm/ehv_pic.h>
-
-#include "corenet_ds.h"
-
-/*
- * Called very early, device-tree isn't unflattened
- */
-static int __init p5020_ds_probe(void)
-{
-	unsigned long root = of_get_flat_dt_root();
-#ifdef CONFIG_SMP
-	extern struct smp_ops_t smp_85xx_ops;
-#endif
-
-	if (of_flat_dt_is_compatible(root, "fsl,P5020DS"))
-		return 1;
-
-	/* Check if we're running under the Freescale hypervisor */
-	if (of_flat_dt_is_compatible(root, "fsl,P5020DS-hv")) {
-		ppc_md.init_IRQ = ehv_pic_init;
-		ppc_md.get_irq = ehv_pic_get_irq;
-		ppc_md.restart = fsl_hv_restart;
-		ppc_md.power_off = fsl_hv_halt;
-		ppc_md.halt = fsl_hv_halt;
-#ifdef CONFIG_SMP
-		/*
-		 * Disable the timebase sync operations because we can't write
-		 * to the timebase registers under the hypervisor.
-		  */
-		smp_85xx_ops.give_timebase = NULL;
-		smp_85xx_ops.take_timebase = NULL;
-#endif
-		return 1;
-	}
-
-	return 0;
-}
-
-define_machine(p5020_ds) {
-	.name			= "P5020 DS",
-	.probe			= p5020_ds_probe,
-	.setup_arch		= corenet_ds_setup_arch,
-	.init_IRQ		= corenet_ds_pic_init,
-#ifdef CONFIG_PCI
-	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
-#endif
-	.get_irq		= mpic_get_coreint_irq,
-	.restart		= fsl_rstcr_restart,
-	.calibrate_decr		= generic_calibrate_decr,
-	.progress		= udbg_progress,
-#ifdef CONFIG_PPC64
-	.power_save		= book3e_idle,
-#else
-	.power_save		= e500_idle,
-#endif
-};
-
-machine_arch_initcall(p5020_ds, corenet_ds_publish_devices);
-
-#ifdef CONFIG_SWIOTLB
-machine_arch_initcall(p5020_ds, swiotlb_setup_bus_notifier);
-#endif
diff --git a/arch/powerpc/platforms/85xx/p5040_ds.c b/arch/powerpc/platforms/85xx/p5040_ds.c
deleted file mode 100644
index f70e74c..0000000
--- a/arch/powerpc/platforms/85xx/p5040_ds.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * P5040 DS Setup
- *
- * Copyright 2009-2010 Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-
-#include <asm/machdep.h>
-#include <asm/udbg.h>
-#include <asm/mpic.h>
-
-#include <linux/of_fdt.h>
-
-#include <sysdev/fsl_soc.h>
-#include <sysdev/fsl_pci.h>
-#include <asm/ehv_pic.h>
-
-#include "corenet_ds.h"
-
-/*
- * Called very early, device-tree isn't unflattened
- */
-static int __init p5040_ds_probe(void)
-{
-	unsigned long root = of_get_flat_dt_root();
-#ifdef CONFIG_SMP
-	extern struct smp_ops_t smp_85xx_ops;
-#endif
-
-	if (of_flat_dt_is_compatible(root, "fsl,P5040DS"))
-		return 1;
-
-	/* Check if we're running under the Freescale hypervisor */
-	if (of_flat_dt_is_compatible(root, "fsl,P5040DS-hv")) {
-		ppc_md.init_IRQ = ehv_pic_init;
-		ppc_md.get_irq = ehv_pic_get_irq;
-		ppc_md.restart = fsl_hv_restart;
-		ppc_md.power_off = fsl_hv_halt;
-		ppc_md.halt = fsl_hv_halt;
-#ifdef CONFIG_SMP
-		/*
-		 * Disable the timebase sync operations because we can't write
-		 * to the timebase registers under the hypervisor.
-		  */
-		smp_85xx_ops.give_timebase = NULL;
-		smp_85xx_ops.take_timebase = NULL;
-#endif
-		return 1;
-	}
-
-	return 0;
-}
-
-define_machine(p5040_ds) {
-	.name			= "P5040 DS",
-	.probe			= p5040_ds_probe,
-	.setup_arch		= corenet_ds_setup_arch,
-	.init_IRQ		= corenet_ds_pic_init,
-#ifdef CONFIG_PCI
-	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
-#endif
-	.get_irq		= mpic_get_coreint_irq,
-	.restart		= fsl_rstcr_restart,
-	.calibrate_decr		= generic_calibrate_decr,
-	.progress		= udbg_progress,
-#ifdef CONFIG_PPC64
-	.power_save		= book3e_idle,
-#else
-	.power_save		= e500_idle,
-#endif
-};
-
-machine_arch_initcall(p5040_ds, corenet_ds_publish_devices);
-
-#ifdef CONFIG_SWIOTLB
-machine_arch_initcall(p5040_ds, swiotlb_setup_bus_notifier);
-#endif
diff --git a/arch/powerpc/platforms/85xx/ppa8548.c b/arch/powerpc/platforms/85xx/ppa8548.c
index 6a7704b..3daff7c 100644
--- a/arch/powerpc/platforms/85xx/ppa8548.c
+++ b/arch/powerpc/platforms/85xx/ppa8548.c
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/reboot.h>
 #include <linux/seq_file.h>
+#include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 
 #include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/85xx/sgy_cts1000.c b/arch/powerpc/platforms/85xx/sgy_cts1000.c
index 7179726..b9197ce 100644
--- a/arch/powerpc/platforms/85xx/sgy_cts1000.c
+++ b/arch/powerpc/platforms/85xx/sgy_cts1000.c
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/of_gpio.h>
+#include <linux/of_irq.h>
 #include <linux/workqueue.h>
 #include <linux/reboot.h>
 #include <linux/interrupt.h>
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 281b7f0..393f975 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/kexec.h>
 #include <linux/highmem.h>
 #include <linux/cpu.h>
diff --git a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
index 3bbbf74..55a9682 100644
--- a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
+++ b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
@@ -9,6 +9,8 @@
  */
 
 #include <linux/irq.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/io.h>
 
diff --git a/arch/powerpc/platforms/85xx/t4240_qds.c b/arch/powerpc/platforms/85xx/t4240_qds.c
deleted file mode 100644
index 91ead6b..0000000
--- a/arch/powerpc/platforms/85xx/t4240_qds.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * T4240 QDS Setup
- *
- * Maintained by Kumar Gala (see MAINTAINERS for contact information)
- *
- * Copyright 2012 Freescale Semiconductor Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/phy.h>
-
-#include <asm/time.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <mm/mmu_decl.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <asm/mpic.h>
-
-#include <linux/of_platform.h>
-#include <sysdev/fsl_soc.h>
-#include <sysdev/fsl_pci.h>
-#include <asm/ehv_pic.h>
-
-#include "corenet_ds.h"
-
-/*
- * Called very early, device-tree isn't unflattened
- */
-static int __init t4240_qds_probe(void)
-{
-	unsigned long root = of_get_flat_dt_root();
-#ifdef CONFIG_SMP
-	extern struct smp_ops_t smp_85xx_ops;
-#endif
-
-	if (of_flat_dt_is_compatible(root, "fsl,T4240QDS"))
-		return 1;
-
-	/* Check if we're running under the Freescale hypervisor */
-	if (of_flat_dt_is_compatible(root, "fsl,T4240QDS-hv")) {
-		ppc_md.init_IRQ = ehv_pic_init;
-		ppc_md.get_irq = ehv_pic_get_irq;
-		ppc_md.restart = fsl_hv_restart;
-		ppc_md.power_off = fsl_hv_halt;
-		ppc_md.halt = fsl_hv_halt;
-#ifdef CONFIG_SMP
-		/*
-		 * Disable the timebase sync operations because we can't write
-		 * to the timebase registers under the hypervisor.
-		  */
-		smp_85xx_ops.give_timebase = NULL;
-		smp_85xx_ops.take_timebase = NULL;
-#endif
-		return 1;
-	}
-
-	return 0;
-}
-
-define_machine(t4240_qds) {
-	.name			= "T4240 QDS",
-	.probe			= t4240_qds_probe,
-	.setup_arch		= corenet_ds_setup_arch,
-	.init_IRQ		= corenet_ds_pic_init,
-#ifdef CONFIG_PCI
-	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
-#endif
-	.get_irq		= mpic_get_coreint_irq,
-	.restart		= fsl_rstcr_restart,
-	.calibrate_decr		= generic_calibrate_decr,
-	.progress		= udbg_progress,
-#ifdef CONFIG_PPC64
-	.power_save		= book3e_idle,
-#else
-	.power_save		= e500_idle,
-#endif
-};
-
-machine_arch_initcall(t4240_qds, corenet_ds_publish_devices);
-
-#ifdef CONFIG_SWIOTLB
-machine_arch_initcall(t4240_qds, swiotlb_setup_bus_notifier);
-#endif
diff --git a/arch/powerpc/platforms/86xx/pic.c b/arch/powerpc/platforms/86xx/pic.c
index 9982f57..d5b98c0 100644
--- a/arch/powerpc/platforms/86xx/pic.c
+++ b/arch/powerpc/platforms/86xx/pic.c
@@ -10,6 +10,7 @@
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
 #include <asm/mpic.h>
diff --git a/arch/powerpc/platforms/8xx/ep88xc.c b/arch/powerpc/platforms/8xx/ep88xc.c
index 7d9ac60..e621666 100644
--- a/arch/powerpc/platforms/8xx/ep88xc.c
+++ b/arch/powerpc/platforms/8xx/ep88xc.c
@@ -10,6 +10,8 @@
  */
 
 #include <linux/init.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 
 #include <asm/machdep.h>
diff --git a/arch/powerpc/platforms/8xx/mpc86xads_setup.c b/arch/powerpc/platforms/8xx/mpc86xads_setup.c
index 866feff..6308464 100644
--- a/arch/powerpc/platforms/8xx/mpc86xads_setup.c
+++ b/arch/powerpc/platforms/8xx/mpc86xads_setup.c
@@ -15,6 +15,8 @@
  */
 
 #include <linux/init.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 
 #include <asm/io.h>
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
index 5d98398..c126258 100644
--- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c
+++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
@@ -25,6 +25,8 @@
 #include <linux/fs_uart_pd.h>
 #include <linux/fsl_devices.h>
 #include <linux/mii.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 
 #include <asm/delay.h>
diff --git a/arch/powerpc/platforms/8xx/tqm8xx_setup.c b/arch/powerpc/platforms/8xx/tqm8xx_setup.c
index 8d21ab7..251aba8 100644
--- a/arch/powerpc/platforms/8xx/tqm8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/tqm8xx_setup.c
@@ -28,6 +28,7 @@
 #include <linux/fs_uart_pd.h>
 #include <linux/fsl_devices.h>
 #include <linux/mii.h>
+#include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 
 #include <asm/delay.h>
@@ -48,7 +49,7 @@
 	int port, pin, flags;
 };
 
-static struct __initdata cpm_pin tqm8xx_pins[] = {
+static struct cpm_pin tqm8xx_pins[] __initdata = {
 	/* SMC1 */
 	{CPM_PORTB, 24, CPM_PIN_INPUT}, /* RX */
 	{CPM_PORTB, 25, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TX */
@@ -63,7 +64,7 @@
 	{CPM_PORTC, 11, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_GPIO},
 };
 
-static struct __initdata cpm_pin tqm8xx_fec_pins[] = {
+static struct cpm_pin tqm8xx_fec_pins[] __initdata = {
 	/* MII */
 	{CPM_PORTD, 3, CPM_PIN_OUTPUT},
 	{CPM_PORTD, 4, CPM_PIN_OUTPUT},
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 6704e2e..c2a566f 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -93,22 +93,23 @@
 
 config GENERIC_CPU
 	bool "Generic"
+	depends on !CPU_LITTLE_ENDIAN
 
 config CELL_CPU
 	bool "Cell Broadband Engine"
-	depends on PPC_BOOK3S_64
+	depends on PPC_BOOK3S_64 && !CPU_LITTLE_ENDIAN
 
 config POWER4_CPU
 	bool "POWER4"
-	depends on PPC_BOOK3S_64
+	depends on PPC_BOOK3S_64 && !CPU_LITTLE_ENDIAN
 
 config POWER5_CPU
 	bool "POWER5"
-	depends on PPC_BOOK3S_64
+	depends on PPC_BOOK3S_64 && !CPU_LITTLE_ENDIAN
 
 config POWER6_CPU
 	bool "POWER6"
-	depends on PPC_BOOK3S_64
+	depends on PPC_BOOK3S_64 && !CPU_LITTLE_ENDIAN
 
 config POWER7_CPU
 	bool "POWER7"
diff --git a/arch/powerpc/platforms/cell/celleb_scc_pciex.c b/arch/powerpc/platforms/cell/celleb_scc_pciex.c
index 14be2bd..4278acf 100644
--- a/arch/powerpc/platforms/cell/celleb_scc_pciex.c
+++ b/arch/powerpc/platforms/cell/celleb_scc_pciex.c
@@ -486,7 +486,6 @@
 				     struct pci_controller *phb)
 {
 	struct resource	r;
-	struct of_irq oirq;
 	int virq;
 
 	/* SMMIO registers; used inside this file */
@@ -507,12 +506,11 @@
 	phb->ops = &scc_pciex_pci_ops;
 
 	/* internal interrupt handler */
-	if (of_irq_map_one(node, 1, &oirq)) {
+	virq = irq_of_parse_and_map(node, 1);
+	if (!virq) {
 		pr_err("PCIEXC:Failed to map irq\n");
 		goto error;
 	}
-	virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
-				     oirq.size);
 	if (request_irq(virq, pciex_handle_internal_irq,
 			0, "pciex", (void *)phb)) {
 		pr_err("PCIEXC:Failed to request irq\n");
diff --git a/arch/powerpc/platforms/cell/celleb_scc_sio.c b/arch/powerpc/platforms/cell/celleb_scc_sio.c
index 9c339ec..c8eb571 100644
--- a/arch/powerpc/platforms/cell/celleb_scc_sio.c
+++ b/arch/powerpc/platforms/cell/celleb_scc_sio.c
@@ -45,7 +45,7 @@
 	struct device_node *node;
 	int i;
 	struct uart_port req;
-	struct of_irq irq;
+	struct of_phandle_args irq;
 	struct resource res;
 
 	for_each_compatible_node(node, "serial", "toshiba,sio-scc") {
@@ -53,7 +53,7 @@
 			if (!(txx9_serial_bitmap & (1<<i)))
 				continue;
 
-			if (of_irq_map_one(node, i, &irq))
+			if (of_irq_parse_one(node, i, &irq))
 				continue;
 			if (of_address_to_resource(node,
 				txx9_scc_tab[i].index, &res))
@@ -66,8 +66,7 @@
 #ifdef CONFIG_SERIAL_TXX9_CONSOLE
 			req.membase = ioremap(req.mapbase, 0x24);
 #endif
-			req.irq = irq_create_of_mapping(irq.controller,
-				irq.specifier, irq.size);
+			req.irq = irq_create_of_mapping(&irq);
 			req.flags |= UPF_IOREMAP | UPF_BUGGY_UART
 				/*HAVE_CTS_LINE*/;
 			req.uartclk = 83300000;
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 8e29944..1f72f4a 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -235,12 +235,9 @@
 	/* First, we check whether we have a real "interrupts" in the device
 	 * tree in case the device-tree is ever fixed
 	 */
-	struct of_irq oirq;
-	if (of_irq_map_one(pic->host->of_node, 0, &oirq) == 0) {
-		virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
-					     oirq.size);
+	virq = irq_of_parse_and_map(pic->host->of_node, 0);
+	if (virq)
 		return virq;
-	}
 
 	/* Now do the horrible hacks */
 	tmp = of_get_property(pic->host->of_node, "#interrupt-cells", NULL);
diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c
index 2bb6977..c3327f3 100644
--- a/arch/powerpc/platforms/cell/spu_manage.c
+++ b/arch/powerpc/platforms/cell/spu_manage.c
@@ -177,21 +177,20 @@
 
 static int __init spu_map_interrupts(struct spu *spu, struct device_node *np)
 {
-	struct of_irq oirq;
+	struct of_phandle_args oirq;
 	int ret;
 	int i;
 
 	for (i=0; i < 3; i++) {
-		ret = of_irq_map_one(np, i, &oirq);
+		ret = of_irq_parse_one(np, i, &oirq);
 		if (ret) {
 			pr_debug("spu_new: failed to get irq %d\n", i);
 			goto err;
 		}
 		ret = -EINVAL;
-		pr_debug("  irq %d no 0x%x on %s\n", i, oirq.specifier[0],
-			 oirq.controller->full_name);
-		spu->irqs[i] = irq_create_of_mapping(oirq.controller,
-					oirq.specifier, oirq.size);
+		pr_debug("  irq %d no 0x%x on %s\n", i, oirq.args[0],
+			 oirq.np->full_name);
+		spu->irqs[i] = irq_create_of_mapping(&oirq);
 		if (spu->irqs[i] == NO_IRQ) {
 			pr_debug("spu_new: failed to map it !\n");
 			goto err;
@@ -200,7 +199,7 @@
 	return 0;
 
 err:
-	pr_debug("failed to map irq %x for spu %s\n", *oirq.specifier,
+	pr_debug("failed to map irq %x for spu %s\n", *oirq.args,
 		spu->name);
 	for (; i >= 0; i--) {
 		if (spu->irqs[i] != NO_IRQ)
diff --git a/arch/powerpc/platforms/chrp/nvram.c b/arch/powerpc/platforms/chrp/nvram.c
index d3ceff0..9ef8cc3 100644
--- a/arch/powerpc/platforms/chrp/nvram.c
+++ b/arch/powerpc/platforms/chrp/nvram.c
@@ -66,7 +66,7 @@
 void __init chrp_nvram_init(void)
 {
 	struct device_node *nvram;
-	const unsigned int *nbytes_p;
+	const __be32 *nbytes_p;
 	unsigned int proplen;
 
 	nvram = of_find_node_by_type(NULL, "nvram");
@@ -79,7 +79,7 @@
 		return;
 	}
 
-	nvram_size = *nbytes_p;
+	nvram_size = be32_to_cpup(nbytes_p);
 
 	printk(KERN_INFO "CHRP nvram contains %u bytes\n", nvram_size);
 	of_node_put(nvram);
diff --git a/arch/powerpc/platforms/embedded6xx/flipper-pic.c b/arch/powerpc/platforms/embedded6xx/flipper-pic.c
index 53d6eee0..4cde8e7 100644
--- a/arch/powerpc/platforms/embedded6xx/flipper-pic.c
+++ b/arch/powerpc/platforms/embedded6xx/flipper-pic.c
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <asm/io.h>
 
 #include "flipper-pic.h"
diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
index 3006b51..6c03034 100644
--- a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
+++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
@@ -18,6 +18,8 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <asm/io.h>
 
 #include "hlwd-pic.h"
@@ -181,6 +183,7 @@
 					   &hlwd_irq_domain_ops, io_base);
 	if (!irq_domain) {
 		pr_err("failed to allocate irq_domain\n");
+		iounmap(io_base);
 		return NULL;
 	}
 
diff --git a/arch/powerpc/platforms/fsl_uli1575.c b/arch/powerpc/platforms/fsl_uli1575.c
index 92ac9b5..b97f6f3 100644
--- a/arch/powerpc/platforms/fsl_uli1575.c
+++ b/arch/powerpc/platforms/fsl_uli1575.c
@@ -321,8 +321,7 @@
 {
 	struct pci_controller *hose = pci_bus_to_host(dev->bus);
 	struct device_node *hosenode = hose ? hose->dn : NULL;
-	struct of_irq oirq;
-	int virq, pin = 2;
+	struct of_phandle_args oirq;
 	u32 laddr[3];
 
 	if (!machine_is(mpc86xx_hpcd))
@@ -331,12 +330,13 @@
 	if (!hosenode)
 		return;
 
+	oirq.np = hosenode;
+	oirq.args[0] = 2;
+	oirq.args_count = 1;
 	laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(31, 0) << 8);
 	laddr[1] = laddr[2] = 0;
-	of_irq_map_raw(hosenode, &pin, 1, laddr, &oirq);
-	virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
-				     oirq.size);
-	dev->irq = virq;
+	of_irq_parse_raw(laddr, &oirq);
+	dev->irq = irq_create_of_mapping(&oirq);
 }
 
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, hpcd_quirk_uli1575);
diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c
index 0237ab7..15adee5 100644
--- a/arch/powerpc/platforms/pasemi/gpio_mdio.c
+++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c
@@ -30,6 +30,7 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/phy.h>
+#include <linux/of_address.h>
 #include <linux/of_mdio.h>
 #include <linux/of_platform.h>
 
diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c
index f5e3cda..e49d07f 100644
--- a/arch/powerpc/platforms/powermac/pfunc_base.c
+++ b/arch/powerpc/platforms/powermac/pfunc_base.c
@@ -4,6 +4,7 @@
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
+#include <linux/of_irq.h>
 
 #include <asm/pmac_feature.h>
 #include <asm/pmac_pfunc.h>
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 31036b5..4c24bf6 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -393,8 +393,8 @@
 #endif
 }
 
-int of_irq_map_oldworld(struct device_node *device, int index,
-			struct of_irq *out_irq)
+int of_irq_parse_oldworld(struct device_node *device, int index,
+			struct of_phandle_args *out_irq)
 {
 	const u32 *ints = NULL;
 	int intlen;
@@ -422,9 +422,9 @@
 	if (index >= intlen)
 		return -EINVAL;
 
-	out_irq->controller = NULL;
-	out_irq->specifier[0] = ints[index];
-	out_irq->size = 1;
+	out_irq->np = NULL;
+	out_irq->args[0] = ints[index];
+	out_irq->args_count = 1;
 
 	return 0;
 }
diff --git a/arch/powerpc/platforms/powernv/Kconfig b/arch/powerpc/platforms/powernv/Kconfig
index 6fae5eb..9fced3f 100644
--- a/arch/powerpc/platforms/powernv/Kconfig
+++ b/arch/powerpc/platforms/powernv/Kconfig
@@ -9,6 +9,8 @@
 	select EPAPR_BOOT
 	select PPC_INDIRECT_PIO
 	select PPC_UDBG_16550
+	select PPC_SCOM
+	select ARCH_RANDOM
 	default y
 
 config POWERNV_MSI
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
index 300c437..873fa13 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -1,6 +1,8 @@
 obj-y			+= setup.o opal-takeover.o opal-wrappers.o opal.o
-obj-y			+= opal-rtc.o opal-nvram.o opal-lpc.o
+obj-y			+= opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o
+obj-y			+= rng.o
 
 obj-$(CONFIG_SMP)	+= smp.o
 obj-$(CONFIG_PCI)	+= pci.o pci-p5ioc2.o pci-ioda.o
 obj-$(CONFIG_EEH)	+= eeh-ioda.o eeh-powernv.o
+obj-$(CONFIG_PPC_SCOM)	+= opal-xscom.o
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c
index cf42e74..02245ce 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -59,26 +59,60 @@
 };
 
 #ifdef CONFIG_DEBUG_FS
-static int ioda_eeh_dbgfs_set(void *data, u64 val)
+static int ioda_eeh_dbgfs_set(void *data, int offset, u64 val)
 {
 	struct pci_controller *hose = data;
 	struct pnv_phb *phb = hose->private_data;
 
-	out_be64(phb->regs + 0xD10, val);
+	out_be64(phb->regs + offset, val);
 	return 0;
 }
 
-static int ioda_eeh_dbgfs_get(void *data, u64 *val)
+static int ioda_eeh_dbgfs_get(void *data, int offset, u64 *val)
 {
 	struct pci_controller *hose = data;
 	struct pnv_phb *phb = hose->private_data;
 
-	*val = in_be64(phb->regs + 0xD10);
+	*val = in_be64(phb->regs + offset);
 	return 0;
 }
 
-DEFINE_SIMPLE_ATTRIBUTE(ioda_eeh_dbgfs_ops, ioda_eeh_dbgfs_get,
-			ioda_eeh_dbgfs_set, "0x%llx\n");
+static int ioda_eeh_outb_dbgfs_set(void *data, u64 val)
+{
+	return ioda_eeh_dbgfs_set(data, 0xD10, val);
+}
+
+static int ioda_eeh_outb_dbgfs_get(void *data, u64 *val)
+{
+	return ioda_eeh_dbgfs_get(data, 0xD10, val);
+}
+
+static int ioda_eeh_inbA_dbgfs_set(void *data, u64 val)
+{
+	return ioda_eeh_dbgfs_set(data, 0xD90, val);
+}
+
+static int ioda_eeh_inbA_dbgfs_get(void *data, u64 *val)
+{
+	return ioda_eeh_dbgfs_get(data, 0xD90, val);
+}
+
+static int ioda_eeh_inbB_dbgfs_set(void *data, u64 val)
+{
+	return ioda_eeh_dbgfs_set(data, 0xE10, val);
+}
+
+static int ioda_eeh_inbB_dbgfs_get(void *data, u64 *val)
+{
+	return ioda_eeh_dbgfs_get(data, 0xE10, val);
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(ioda_eeh_outb_dbgfs_ops, ioda_eeh_outb_dbgfs_get,
+			ioda_eeh_outb_dbgfs_set, "0x%llx\n");
+DEFINE_SIMPLE_ATTRIBUTE(ioda_eeh_inbA_dbgfs_ops, ioda_eeh_inbA_dbgfs_get,
+			ioda_eeh_inbA_dbgfs_set, "0x%llx\n");
+DEFINE_SIMPLE_ATTRIBUTE(ioda_eeh_inbB_dbgfs_ops, ioda_eeh_inbB_dbgfs_get,
+			ioda_eeh_inbB_dbgfs_set, "0x%llx\n");
 #endif /* CONFIG_DEBUG_FS */
 
 /**
@@ -106,27 +140,30 @@
 		ioda_eeh_nb_init = 1;
 	}
 
-	/* FIXME: Enable it for PHB3 later */
-	if (phb->type == PNV_PHB_IODA1) {
+	/* We needn't HUB diag-data on PHB3 */
+	if (phb->type == PNV_PHB_IODA1 && !hub_diag) {
+		hub_diag = (char *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
 		if (!hub_diag) {
-			hub_diag = (char *)__get_free_page(GFP_KERNEL |
-							   __GFP_ZERO);
-			if (!hub_diag) {
-				pr_err("%s: Out of memory !\n",
-				       __func__);
-				return -ENOMEM;
-			}
+			pr_err("%s: Out of memory !\n", __func__);
+			return -ENOMEM;
 		}
+	}
 
 #ifdef CONFIG_DEBUG_FS
-		if (phb->dbgfs)
-			debugfs_create_file("err_injct", 0600,
-					    phb->dbgfs, hose,
-					    &ioda_eeh_dbgfs_ops);
+	if (phb->dbgfs) {
+		debugfs_create_file("err_injct_outbound", 0600,
+				    phb->dbgfs, hose,
+				    &ioda_eeh_outb_dbgfs_ops);
+		debugfs_create_file("err_injct_inboundA", 0600,
+				    phb->dbgfs, hose,
+				    &ioda_eeh_inbA_dbgfs_ops);
+		debugfs_create_file("err_injct_inboundB", 0600,
+				    phb->dbgfs, hose,
+				    &ioda_eeh_inbB_dbgfs_ops);
+	}
 #endif
 
-		phb->eeh_state |= PNV_EEH_STATE_ENABLED;
-	}
+	phb->eeh_state |= PNV_EEH_STATE_ENABLED;
 
 	return 0;
 }
@@ -546,8 +583,8 @@
 			phb->diag.blob, PNV_PCI_DIAG_BUF_SIZE);
 	if (ret) {
 		spin_unlock_irqrestore(&phb->lock, flags);
-		pr_warning("%s: Failed to get log for PHB#%x-PE#%x\n",
-			   __func__, hose->global_number, pe->addr);
+		pr_warning("%s: Can't get log for PHB#%x-PE#%x (%lld)\n",
+			   __func__, hose->global_number, pe->addr, ret);
 		return -EIO;
 	}
 
@@ -710,6 +747,73 @@
 	}
 }
 
+static void ioda_eeh_phb3_phb_diag(struct pci_controller *hose,
+				    struct OpalIoPhbErrorCommon *common)
+{
+	struct OpalIoPhb3ErrorData *data;
+	int i;
+
+	data = (struct OpalIoPhb3ErrorData*)common;
+	pr_info("PHB3 PHB#%x Diag-data (Version: %d)\n\n",
+		hose->global_number, common->version);
+
+	pr_info("  brdgCtl:              %08x\n", data->brdgCtl);
+
+	pr_info("  portStatusReg:        %08x\n", data->portStatusReg);
+	pr_info("  rootCmplxStatus:      %08x\n", data->rootCmplxStatus);
+	pr_info("  busAgentStatus:       %08x\n", data->busAgentStatus);
+
+	pr_info("  deviceStatus:         %08x\n", data->deviceStatus);
+	pr_info("  slotStatus:           %08x\n", data->slotStatus);
+	pr_info("  linkStatus:           %08x\n", data->linkStatus);
+	pr_info("  devCmdStatus:         %08x\n", data->devCmdStatus);
+	pr_info("  devSecStatus:         %08x\n", data->devSecStatus);
+
+	pr_info("  rootErrorStatus:      %08x\n", data->rootErrorStatus);
+	pr_info("  uncorrErrorStatus:    %08x\n", data->uncorrErrorStatus);
+	pr_info("  corrErrorStatus:      %08x\n", data->corrErrorStatus);
+	pr_info("  tlpHdr1:              %08x\n", data->tlpHdr1);
+	pr_info("  tlpHdr2:              %08x\n", data->tlpHdr2);
+	pr_info("  tlpHdr3:              %08x\n", data->tlpHdr3);
+	pr_info("  tlpHdr4:              %08x\n", data->tlpHdr4);
+	pr_info("  sourceId:             %08x\n", data->sourceId);
+	pr_info("  errorClass:           %016llx\n", data->errorClass);
+	pr_info("  correlator:           %016llx\n", data->correlator);
+	pr_info("  nFir:                 %016llx\n", data->nFir);
+	pr_info("  nFirMask:             %016llx\n", data->nFirMask);
+	pr_info("  nFirWOF:              %016llx\n", data->nFirWOF);
+	pr_info("  PhbPlssr:             %016llx\n", data->phbPlssr);
+	pr_info("  PhbCsr:               %016llx\n", data->phbCsr);
+	pr_info("  lemFir:               %016llx\n", data->lemFir);
+	pr_info("  lemErrorMask:         %016llx\n", data->lemErrorMask);
+	pr_info("  lemWOF:               %016llx\n", data->lemWOF);
+	pr_info("  phbErrorStatus:       %016llx\n", data->phbErrorStatus);
+	pr_info("  phbFirstErrorStatus:  %016llx\n", data->phbFirstErrorStatus);
+	pr_info("  phbErrorLog0:         %016llx\n", data->phbErrorLog0);
+	pr_info("  phbErrorLog1:         %016llx\n", data->phbErrorLog1);
+	pr_info("  mmioErrorStatus:      %016llx\n", data->mmioErrorStatus);
+	pr_info("  mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus);
+	pr_info("  mmioErrorLog0:        %016llx\n", data->mmioErrorLog0);
+	pr_info("  mmioErrorLog1:        %016llx\n", data->mmioErrorLog1);
+	pr_info("  dma0ErrorStatus:      %016llx\n", data->dma0ErrorStatus);
+	pr_info("  dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus);
+	pr_info("  dma0ErrorLog0:        %016llx\n", data->dma0ErrorLog0);
+	pr_info("  dma0ErrorLog1:        %016llx\n", data->dma0ErrorLog1);
+	pr_info("  dma1ErrorStatus:      %016llx\n", data->dma1ErrorStatus);
+	pr_info("  dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus);
+	pr_info("  dma1ErrorLog0:        %016llx\n", data->dma1ErrorLog0);
+	pr_info("  dma1ErrorLog1:        %016llx\n", data->dma1ErrorLog1);
+
+	for (i = 0; i < OPAL_PHB3_NUM_PEST_REGS; i++) {
+		if ((data->pestA[i] >> 63) == 0 &&
+		    (data->pestB[i] >> 63) == 0)
+			continue;
+
+		pr_info("  PE[%3d] PESTA:        %016llx\n", i, data->pestA[i]);
+		pr_info("          PESTB:        %016llx\n", data->pestB[i]);
+	}
+}
+
 static void ioda_eeh_phb_diag(struct pci_controller *hose)
 {
 	struct pnv_phb *phb = hose->private_data;
@@ -728,6 +832,9 @@
 	case OPAL_PHB_ERROR_DATA_TYPE_P7IOC:
 		ioda_eeh_p7ioc_phb_diag(hose, common);
 		break;
+	case OPAL_PHB_ERROR_DATA_TYPE_PHB3:
+		ioda_eeh_phb3_phb_diag(hose, common);
+		break;
 	default:
 		pr_warning("%s: Unrecognized I/O chip %d\n",
 			   __func__, common->ioType);
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c
index 79663d2..73b9814 100644
--- a/arch/powerpc/platforms/powernv/eeh-powernv.c
+++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
@@ -144,11 +144,8 @@
 	/*
 	 * Enable EEH explicitly so that we will do EEH check
 	 * while accessing I/O stuff
-	 *
-	 * FIXME: Enable that for PHB3 later
 	 */
-	if (phb->type == PNV_PHB_IODA1)
-		eeh_subsystem_enabled = 1;
+	eeh_subsystem_enabled = 1;
 
 	/* Save memory bars */
 	eeh_save_bars(edev);
diff --git a/arch/powerpc/platforms/powernv/opal-flash.c b/arch/powerpc/platforms/powernv/opal-flash.c
new file mode 100644
index 0000000..6ffa6b1
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/opal-flash.c
@@ -0,0 +1,667 @@
+/*
+ * PowerNV OPAL Firmware Update Interface
+ *
+ * Copyright 2013 IBM 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; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/pagemap.h>
+
+#include <asm/opal.h>
+
+/* FLASH status codes */
+#define FLASH_NO_OP		-1099	/* No operation initiated by user */
+#define FLASH_NO_AUTH		-9002	/* Not a service authority partition */
+
+/* Validate image status values */
+#define VALIDATE_IMG_READY	-1001	/* Image ready for validation */
+#define VALIDATE_IMG_INCOMPLETE	-1002	/* User copied < VALIDATE_BUF_SIZE */
+
+/* Manage image status values */
+#define MANAGE_ACTIVE_ERR	-9001	/* Cannot overwrite active img */
+
+/* Flash image status values */
+#define FLASH_IMG_READY		0	/* Img ready for flash on reboot */
+#define FLASH_INVALID_IMG	-1003	/* Flash image shorter than expected */
+#define FLASH_IMG_NULL_DATA	-1004	/* Bad data in sg list entry */
+#define FLASH_IMG_BAD_LEN	-1005	/* Bad length in sg list entry */
+
+/* Manage operation tokens */
+#define FLASH_REJECT_TMP_SIDE	0	/* Reject temporary fw image */
+#define FLASH_COMMIT_TMP_SIDE	1	/* Commit temporary fw image */
+
+/* Update tokens */
+#define FLASH_UPDATE_CANCEL	0	/* Cancel update request */
+#define FLASH_UPDATE_INIT	1	/* Initiate update */
+
+/* Validate image update result tokens */
+#define VALIDATE_TMP_UPDATE	0     /* T side will be updated */
+#define VALIDATE_FLASH_AUTH	1     /* Partition does not have authority */
+#define VALIDATE_INVALID_IMG	2     /* Candidate image is not valid */
+#define VALIDATE_CUR_UNKNOWN	3     /* Current fixpack level is unknown */
+/*
+ * Current T side will be committed to P side before being replace with new
+ * image, and the new image is downlevel from current image
+ */
+#define VALIDATE_TMP_COMMIT_DL	4
+/*
+ * Current T side will be committed to P side before being replaced with new
+ * image
+ */
+#define VALIDATE_TMP_COMMIT	5
+/*
+ * T side will be updated with a downlevel image
+ */
+#define VALIDATE_TMP_UPDATE_DL	6
+/*
+ * The candidate image's release date is later than the system's firmware
+ * service entitlement date - service warranty period has expired
+ */
+#define VALIDATE_OUT_OF_WRNTY	7
+
+/* Validate buffer size */
+#define VALIDATE_BUF_SIZE	4096
+
+/* XXX: Assume candidate image size is <= 256MB */
+#define MAX_IMAGE_SIZE	0x10000000
+
+/* Flash sg list version */
+#define SG_LIST_VERSION (1UL)
+
+/* Image status */
+enum {
+	IMAGE_INVALID,
+	IMAGE_LOADING,
+	IMAGE_READY,
+};
+
+/* Candidate image data */
+struct image_data_t {
+	int		status;
+	void		*data;
+	uint32_t	size;
+};
+
+/* Candidate image header */
+struct image_header_t {
+	uint16_t	magic;
+	uint16_t	version;
+	uint32_t	size;
+};
+
+/* Scatter/gather entry */
+struct opal_sg_entry {
+	void	*data;
+	long	length;
+};
+
+/* We calculate number of entries based on PAGE_SIZE */
+#define SG_ENTRIES_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct opal_sg_entry))
+
+/*
+ * This struct is very similar but not identical to that
+ * needed by the opal flash update. All we need to do for
+ * opal is rewrite num_entries into a version/length and
+ * translate the pointers to absolute.
+ */
+struct opal_sg_list {
+	unsigned long num_entries;
+	struct opal_sg_list *next;
+	struct opal_sg_entry entry[SG_ENTRIES_PER_NODE];
+};
+
+struct validate_flash_t {
+	int		status;		/* Return status */
+	void		*buf;		/* Candiate image buffer */
+	uint32_t	buf_size;	/* Image size */
+	uint32_t	result;		/* Update results token */
+};
+
+struct manage_flash_t {
+	int status;		/* Return status */
+};
+
+struct update_flash_t {
+	int status;		/* Return status */
+};
+
+static struct image_header_t	image_header;
+static struct image_data_t	image_data;
+static struct validate_flash_t	validate_flash_data;
+static struct manage_flash_t	manage_flash_data;
+static struct update_flash_t	update_flash_data;
+
+static DEFINE_MUTEX(image_data_mutex);
+
+/*
+ * Validate candidate image
+ */
+static inline void opal_flash_validate(void)
+{
+	struct validate_flash_t *args_buf = &validate_flash_data;
+
+	args_buf->status = opal_validate_flash(__pa(args_buf->buf),
+					       &(args_buf->buf_size),
+					       &(args_buf->result));
+}
+
+/*
+ * Validate output format:
+ *     validate result token
+ *     current image version details
+ *     new image version details
+ */
+static ssize_t validate_show(struct kobject *kobj,
+			     struct kobj_attribute *attr, char *buf)
+{
+	struct validate_flash_t *args_buf = &validate_flash_data;
+	int len;
+
+	/* Candidate image is not validated */
+	if (args_buf->status < VALIDATE_TMP_UPDATE) {
+		len = sprintf(buf, "%d\n", args_buf->status);
+		goto out;
+	}
+
+	/* Result token */
+	len = sprintf(buf, "%d\n", args_buf->result);
+
+	/* Current and candidate image version details */
+	if ((args_buf->result != VALIDATE_TMP_UPDATE) &&
+	    (args_buf->result < VALIDATE_CUR_UNKNOWN))
+		goto out;
+
+	if (args_buf->buf_size > (VALIDATE_BUF_SIZE - len)) {
+		memcpy(buf + len, args_buf->buf, VALIDATE_BUF_SIZE - len);
+		len = VALIDATE_BUF_SIZE;
+	} else {
+		memcpy(buf + len, args_buf->buf, args_buf->buf_size);
+		len += args_buf->buf_size;
+	}
+out:
+	/* Set status to default */
+	args_buf->status = FLASH_NO_OP;
+	return len;
+}
+
+/*
+ * Validate candidate firmware image
+ *
+ * Note:
+ *   We are only interested in first 4K bytes of the
+ *   candidate image.
+ */
+static ssize_t validate_store(struct kobject *kobj,
+			      struct kobj_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct validate_flash_t *args_buf = &validate_flash_data;
+
+	if (buf[0] != '1')
+		return -EINVAL;
+
+	mutex_lock(&image_data_mutex);
+
+	if (image_data.status != IMAGE_READY ||
+	    image_data.size < VALIDATE_BUF_SIZE) {
+		args_buf->result = VALIDATE_INVALID_IMG;
+		args_buf->status = VALIDATE_IMG_INCOMPLETE;
+		goto out;
+	}
+
+	/* Copy first 4k bytes of candidate image */
+	memcpy(args_buf->buf, image_data.data, VALIDATE_BUF_SIZE);
+
+	args_buf->status = VALIDATE_IMG_READY;
+	args_buf->buf_size = VALIDATE_BUF_SIZE;
+
+	/* Validate candidate image */
+	opal_flash_validate();
+
+out:
+	mutex_unlock(&image_data_mutex);
+	return count;
+}
+
+/*
+ * Manage flash routine
+ */
+static inline void opal_flash_manage(uint8_t op)
+{
+	struct manage_flash_t *const args_buf = &manage_flash_data;
+
+	args_buf->status = opal_manage_flash(op);
+}
+
+/*
+ * Show manage flash status
+ */
+static ssize_t manage_show(struct kobject *kobj,
+			   struct kobj_attribute *attr, char *buf)
+{
+	struct manage_flash_t *const args_buf = &manage_flash_data;
+	int rc;
+
+	rc = sprintf(buf, "%d\n", args_buf->status);
+	/* Set status to default*/
+	args_buf->status = FLASH_NO_OP;
+	return rc;
+}
+
+/*
+ * Manage operations:
+ *   0 - Reject
+ *   1 - Commit
+ */
+static ssize_t manage_store(struct kobject *kobj,
+			    struct kobj_attribute *attr,
+			    const char *buf, size_t count)
+{
+	uint8_t op;
+	switch (buf[0]) {
+	case '0':
+		op = FLASH_REJECT_TMP_SIDE;
+		break;
+	case '1':
+		op = FLASH_COMMIT_TMP_SIDE;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* commit/reject temporary image */
+	opal_flash_manage(op);
+	return count;
+}
+
+/*
+ * Free sg list
+ */
+static void free_sg_list(struct opal_sg_list *list)
+{
+	struct opal_sg_list *sg1;
+	while (list) {
+		sg1 = list->next;
+		kfree(list);
+		list = sg1;
+	}
+	list = NULL;
+}
+
+/*
+ * Build candidate image scatter gather list
+ *
+ * list format:
+ *   -----------------------------------
+ *  |  VER (8) | Entry length in bytes  |
+ *   -----------------------------------
+ *  |  Pointer to next entry            |
+ *   -----------------------------------
+ *  |  Address of memory area 1         |
+ *   -----------------------------------
+ *  |  Length of memory area 1          |
+ *   -----------------------------------
+ *  |   .........                       |
+ *   -----------------------------------
+ *  |   .........                       |
+ *   -----------------------------------
+ *  |  Address of memory area N         |
+ *   -----------------------------------
+ *  |  Length of memory area N          |
+ *   -----------------------------------
+ */
+static struct opal_sg_list *image_data_to_sglist(void)
+{
+	struct opal_sg_list *sg1, *list = NULL;
+	void *addr;
+	int size;
+
+	addr = image_data.data;
+	size = image_data.size;
+
+	sg1 = kzalloc((sizeof(struct opal_sg_list)), GFP_KERNEL);
+	if (!sg1)
+		return NULL;
+
+	list = sg1;
+	sg1->num_entries = 0;
+	while (size > 0) {
+		/* Translate virtual address to physical address */
+		sg1->entry[sg1->num_entries].data =
+			(void *)(vmalloc_to_pfn(addr) << PAGE_SHIFT);
+
+		if (size > PAGE_SIZE)
+			sg1->entry[sg1->num_entries].length = PAGE_SIZE;
+		else
+			sg1->entry[sg1->num_entries].length = size;
+
+		sg1->num_entries++;
+		if (sg1->num_entries >= SG_ENTRIES_PER_NODE) {
+			sg1->next = kzalloc((sizeof(struct opal_sg_list)),
+					    GFP_KERNEL);
+			if (!sg1->next) {
+				pr_err("%s : Failed to allocate memory\n",
+				       __func__);
+				goto nomem;
+			}
+
+			sg1 = sg1->next;
+			sg1->num_entries = 0;
+		}
+		addr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+	return list;
+nomem:
+	free_sg_list(list);
+	return NULL;
+}
+
+/*
+ * OPAL update flash
+ */
+static int opal_flash_update(int op)
+{
+	struct opal_sg_list *sg, *list, *next;
+	unsigned long addr;
+	int64_t rc = OPAL_PARAMETER;
+
+	if (op == FLASH_UPDATE_CANCEL) {
+		pr_alert("FLASH: Image update cancelled\n");
+		addr = '\0';
+		goto flash;
+	}
+
+	list = image_data_to_sglist();
+	if (!list)
+		goto invalid_img;
+
+	/* First entry address */
+	addr = __pa(list);
+
+	/* Translate sg list address to absolute */
+	for (sg = list; sg; sg = next) {
+		next = sg->next;
+		/* Don't translate NULL pointer for last entry */
+		if (sg->next)
+			sg->next = (struct opal_sg_list *)__pa(sg->next);
+		else
+			sg->next = NULL;
+
+		/* Make num_entries into the version/length field */
+		sg->num_entries = (SG_LIST_VERSION << 56) |
+			(sg->num_entries * sizeof(struct opal_sg_entry) + 16);
+	}
+
+	pr_alert("FLASH: Image is %u bytes\n", image_data.size);
+	pr_alert("FLASH: Image update requested\n");
+	pr_alert("FLASH: Image will be updated during system reboot\n");
+	pr_alert("FLASH: This will take several minutes. Do not power off!\n");
+
+flash:
+	rc = opal_update_flash(addr);
+
+invalid_img:
+	return rc;
+}
+
+/*
+ * Show candidate image status
+ */
+static ssize_t update_show(struct kobject *kobj,
+			   struct kobj_attribute *attr, char *buf)
+{
+	struct update_flash_t *const args_buf = &update_flash_data;
+	return sprintf(buf, "%d\n", args_buf->status);
+}
+
+/*
+ * Set update image flag
+ *  1 - Flash new image
+ *  0 - Cancel flash request
+ */
+static ssize_t update_store(struct kobject *kobj,
+			    struct kobj_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct update_flash_t *const args_buf = &update_flash_data;
+	int rc = count;
+
+	mutex_lock(&image_data_mutex);
+
+	switch (buf[0]) {
+	case '0':
+		if (args_buf->status == FLASH_IMG_READY)
+			opal_flash_update(FLASH_UPDATE_CANCEL);
+		args_buf->status = FLASH_NO_OP;
+		break;
+	case '1':
+		/* Image is loaded? */
+		if (image_data.status == IMAGE_READY)
+			args_buf->status =
+				opal_flash_update(FLASH_UPDATE_INIT);
+		else
+			args_buf->status = FLASH_INVALID_IMG;
+		break;
+	default:
+		rc = -EINVAL;
+	}
+
+	mutex_unlock(&image_data_mutex);
+	return rc;
+}
+
+/*
+ * Free image buffer
+ */
+static void free_image_buf(void)
+{
+	void *addr;
+	int size;
+
+	addr = image_data.data;
+	size = PAGE_ALIGN(image_data.size);
+	while (size > 0) {
+		ClearPageReserved(vmalloc_to_page(addr));
+		addr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+	vfree(image_data.data);
+	image_data.data = NULL;
+	image_data.status = IMAGE_INVALID;
+}
+
+/*
+ * Allocate image buffer.
+ */
+static int alloc_image_buf(char *buffer, size_t count)
+{
+	void *addr;
+	int size;
+
+	if (count < sizeof(struct image_header_t)) {
+		pr_warn("FLASH: Invalid candidate image\n");
+		return -EINVAL;
+	}
+
+	memcpy(&image_header, (void *)buffer, sizeof(struct image_header_t));
+	image_data.size = be32_to_cpu(image_header.size);
+	pr_debug("FLASH: Candiate image size = %u\n", image_data.size);
+
+	if (image_data.size > MAX_IMAGE_SIZE) {
+		pr_warn("FLASH: Too large image\n");
+		return -EINVAL;
+	}
+	if (image_data.size < VALIDATE_BUF_SIZE) {
+		pr_warn("FLASH: Image is shorter than expected\n");
+		return -EINVAL;
+	}
+
+	image_data.data = vzalloc(PAGE_ALIGN(image_data.size));
+	if (!image_data.data) {
+		pr_err("%s : Failed to allocate memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	/* Pin memory */
+	addr = image_data.data;
+	size = PAGE_ALIGN(image_data.size);
+	while (size > 0) {
+		SetPageReserved(vmalloc_to_page(addr));
+		addr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+
+	image_data.status = IMAGE_LOADING;
+	return 0;
+}
+
+/*
+ * Copy candidate image
+ *
+ * Parse candidate image header to get total image size
+ * and pre-allocate required memory.
+ */
+static ssize_t image_data_write(struct file *filp, struct kobject *kobj,
+				struct bin_attribute *bin_attr,
+				char *buffer, loff_t pos, size_t count)
+{
+	int rc;
+
+	mutex_lock(&image_data_mutex);
+
+	/* New image ? */
+	if (pos == 0) {
+		/* Free memory, if already allocated */
+		if (image_data.data)
+			free_image_buf();
+
+		/* Cancel outstanding image update request */
+		if (update_flash_data.status == FLASH_IMG_READY)
+			opal_flash_update(FLASH_UPDATE_CANCEL);
+
+		/* Allocate memory */
+		rc = alloc_image_buf(buffer, count);
+		if (rc)
+			goto out;
+	}
+
+	if (image_data.status != IMAGE_LOADING) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	if ((pos + count) > image_data.size) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	memcpy(image_data.data + pos, (void *)buffer, count);
+	rc = count;
+
+	/* Set image status */
+	if ((pos + count) == image_data.size) {
+		pr_debug("FLASH: Candidate image loaded....\n");
+		image_data.status = IMAGE_READY;
+	}
+
+out:
+	mutex_unlock(&image_data_mutex);
+	return rc;
+}
+
+/*
+ * sysfs interface :
+ *  OPAL uses below sysfs files for code update.
+ *  We create these files under /sys/firmware/opal.
+ *
+ *   image		: Interface to load candidate firmware image
+ *   validate_flash	: Validate firmware image
+ *   manage_flash	: Commit/Reject firmware image
+ *   update_flash	: Flash new firmware image
+ *
+ */
+static struct bin_attribute image_data_attr = {
+	.attr = {.name = "image", .mode = 0200},
+	.size = MAX_IMAGE_SIZE,	/* Limit image size */
+	.write = image_data_write,
+};
+
+static struct kobj_attribute validate_attribute =
+	__ATTR(validate_flash, 0600, validate_show, validate_store);
+
+static struct kobj_attribute manage_attribute =
+	__ATTR(manage_flash, 0600, manage_show, manage_store);
+
+static struct kobj_attribute update_attribute =
+	__ATTR(update_flash, 0600, update_show, update_store);
+
+static struct attribute *image_op_attrs[] = {
+	&validate_attribute.attr,
+	&manage_attribute.attr,
+	&update_attribute.attr,
+	NULL	/* need to NULL terminate the list of attributes */
+};
+
+static struct attribute_group image_op_attr_group = {
+	.attrs = image_op_attrs,
+};
+
+void __init opal_flash_init(void)
+{
+	int ret;
+
+	/* Allocate validate image buffer */
+	validate_flash_data.buf = kzalloc(VALIDATE_BUF_SIZE, GFP_KERNEL);
+	if (!validate_flash_data.buf) {
+		pr_err("%s : Failed to allocate memory\n", __func__);
+		return;
+	}
+
+	/* Make sure /sys/firmware/opal directory is created */
+	if (!opal_kobj) {
+		pr_warn("FLASH: opal kobject is not available\n");
+		goto nokobj;
+	}
+
+	/* Create the sysfs files */
+	ret = sysfs_create_group(opal_kobj, &image_op_attr_group);
+	if (ret) {
+		pr_warn("FLASH: Failed to create sysfs files\n");
+		goto nokobj;
+	}
+
+	ret = sysfs_create_bin_file(opal_kobj, &image_data_attr);
+	if (ret) {
+		pr_warn("FLASH: Failed to create sysfs files\n");
+		goto nosysfs_file;
+	}
+
+	/* Set default status */
+	validate_flash_data.status = FLASH_NO_OP;
+	manage_flash_data.status = FLASH_NO_OP;
+	update_flash_data.status = FLASH_NO_OP;
+	image_data.status = IMAGE_INVALID;
+	return;
+
+nosysfs_file:
+	sysfs_remove_group(opal_kobj, &image_op_attr_group);
+
+nokobj:
+	kfree(validate_flash_data.buf);
+	return;
+}
diff --git a/arch/powerpc/platforms/powernv/opal-lpc.c b/arch/powerpc/platforms/powernv/opal-lpc.c
index a7614bb..e7e59e4 100644
--- a/arch/powerpc/platforms/powernv/opal-lpc.c
+++ b/arch/powerpc/platforms/powernv/opal-lpc.c
@@ -17,6 +17,7 @@
 #include <asm/firmware.h>
 #include <asm/xics.h>
 #include <asm/opal.h>
+#include <asm/prom.h>
 
 static int opal_lpc_chip_id = -1;
 
diff --git a/arch/powerpc/platforms/powernv/opal-nvram.c b/arch/powerpc/platforms/powernv/opal-nvram.c
index 3f83e1a..acd9f7e 100644
--- a/arch/powerpc/platforms/powernv/opal-nvram.c
+++ b/arch/powerpc/platforms/powernv/opal-nvram.c
@@ -65,7 +65,7 @@
 void __init opal_nvram_init(void)
 {
 	struct device_node *np;
-	const u32 *nbytes_p;
+	const __be32 *nbytes_p;
 
 	np = of_find_compatible_node(NULL, NULL, "ibm,opal-nvram");
 	if (np == NULL)
@@ -76,7 +76,7 @@
 		of_node_put(np);
 		return;
 	}
-	nvram_size = *nbytes_p;
+	nvram_size = be32_to_cpup(nbytes_p);
 
 	printk(KERN_INFO "OPAL nvram setup, %u bytes\n", nvram_size);
 	of_node_put(np);
diff --git a/arch/powerpc/platforms/powernv/opal-rtc.c b/arch/powerpc/platforms/powernv/opal-rtc.c
index 2aa7641..7d07c7e 100644
--- a/arch/powerpc/platforms/powernv/opal-rtc.c
+++ b/arch/powerpc/platforms/powernv/opal-rtc.c
@@ -37,10 +37,12 @@
 	struct rtc_time tm;
 	u32 y_m_d;
 	u64 h_m_s_ms;
+	__be32 __y_m_d;
+	__be64 __h_m_s_ms;
 	long rc = OPAL_BUSY;
 
 	while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
-		rc = opal_rtc_read(&y_m_d, &h_m_s_ms);
+		rc = opal_rtc_read(&__y_m_d, &__h_m_s_ms);
 		if (rc == OPAL_BUSY_EVENT)
 			opal_poll_events(NULL);
 		else
@@ -48,6 +50,8 @@
 	}
 	if (rc != OPAL_SUCCESS)
 		return 0;
+	y_m_d = be32_to_cpu(__y_m_d);
+	h_m_s_ms = be64_to_cpu(__h_m_s_ms);
 	opal_to_tm(y_m_d, h_m_s_ms, &tm);
 	return mktime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
 		      tm.tm_hour, tm.tm_min, tm.tm_sec);
@@ -58,9 +62,11 @@
 	long rc = OPAL_BUSY;
 	u32 y_m_d;
 	u64 h_m_s_ms;
+	__be32 __y_m_d;
+	__be64 __h_m_s_ms;
 
 	while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
-		rc = opal_rtc_read(&y_m_d, &h_m_s_ms);
+		rc = opal_rtc_read(&__y_m_d, &__h_m_s_ms);
 		if (rc == OPAL_BUSY_EVENT)
 			opal_poll_events(NULL);
 		else
@@ -68,6 +74,8 @@
 	}
 	if (rc != OPAL_SUCCESS)
 		return;
+	y_m_d = be32_to_cpu(__y_m_d);
+	h_m_s_ms = be64_to_cpu(__h_m_s_ms);
 	opal_to_tm(y_m_d, h_m_s_ms, tm);
 }
 
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S
index 8f38445..e780650 100644
--- a/arch/powerpc/platforms/powernv/opal-wrappers.S
+++ b/arch/powerpc/platforms/powernv/opal-wrappers.S
@@ -24,7 +24,7 @@
 	mflr	r0;			\
 	mfcr	r12;			\
 	std	r0,16(r1);		\
-	std	r12,8(r1);		\
+	stw	r12,8(r1);		\
 	std	r1,PACAR1(r13);		\
 	li	r0,0;			\
 	mfmsr	r12;			\
@@ -34,7 +34,7 @@
 	mtmsrd	r12,1;			\
 	LOAD_REG_ADDR(r0,.opal_return);	\
 	mtlr	r0;			\
-	li	r0,MSR_DR|MSR_IR;	\
+	li	r0,MSR_DR|MSR_IR|MSR_LE;\
 	andc	r12,r12,r0;		\
 	li	r0,token;		\
 	mtspr	SPRN_HSRR1,r12;		\
@@ -45,8 +45,15 @@
 	hrfid
 
 _STATIC(opal_return)
+	/*
+	 * Fixup endian on OPAL return... we should be able to simplify
+	 * this by instead converting the below trampoline to a set of
+	 * bytes (always BE) since MSR:LE will end up fixed up as a side
+	 * effect of the rfid.
+	 */
+	FIXUP_ENDIAN
 	ld	r2,PACATOC(r13);
-	ld	r4,8(r1);
+	lwz	r4,8(r1);
 	ld	r5,16(r1);
 	ld	r6,PACASAVEDMSR(r13);
 	mtspr	SPRN_SRR0,r5;
@@ -116,3 +123,6 @@
 OPAL_CALL(opal_lpc_read,			OPAL_LPC_READ);
 OPAL_CALL(opal_lpc_write,			OPAL_LPC_WRITE);
 OPAL_CALL(opal_return_cpu,			OPAL_RETURN_CPU);
+OPAL_CALL(opal_validate_flash,			OPAL_FLASH_VALIDATE);
+OPAL_CALL(opal_manage_flash,			OPAL_FLASH_MANAGE);
+OPAL_CALL(opal_update_flash,			OPAL_FLASH_UPDATE);
diff --git a/arch/powerpc/platforms/powernv/opal-xscom.c b/arch/powerpc/platforms/powernv/opal-xscom.c
new file mode 100644
index 0000000..4d99a8f
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/opal-xscom.c
@@ -0,0 +1,128 @@
+/*
+ * PowerNV LPC bus handling.
+ *
+ * Copyright 2013 IBM 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; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/bug.h>
+#include <linux/gfp.h>
+#include <linux/slab.h>
+
+#include <asm/machdep.h>
+#include <asm/firmware.h>
+#include <asm/opal.h>
+#include <asm/scom.h>
+
+/*
+ * We could probably fit that inside the scom_map_t
+ * which is a void* after all but it's really too ugly
+ * so let's kmalloc it for now
+ */
+struct opal_scom_map {
+	uint32_t chip;
+	uint64_t addr;
+};
+
+static scom_map_t opal_scom_map(struct device_node *dev, u64 reg, u64 count)
+{
+	struct opal_scom_map *m;
+	const __be32 *gcid;
+
+	if (!of_get_property(dev, "scom-controller", NULL)) {
+		pr_err("%s: device %s is not a SCOM controller\n",
+			__func__, dev->full_name);
+		return SCOM_MAP_INVALID;
+	}
+	gcid = of_get_property(dev, "ibm,chip-id", NULL);
+	if (!gcid) {
+		pr_err("%s: device %s has no ibm,chip-id\n",
+			__func__, dev->full_name);
+		return SCOM_MAP_INVALID;
+	}
+	m = kmalloc(sizeof(struct opal_scom_map), GFP_KERNEL);
+	if (!m)
+		return NULL;
+	m->chip = be32_to_cpup(gcid);
+	m->addr = reg;
+
+	return (scom_map_t)m;
+}
+
+static void opal_scom_unmap(scom_map_t map)
+{
+	kfree(map);
+}
+
+static int opal_xscom_err_xlate(int64_t rc)
+{
+	switch(rc) {
+	case 0:
+		return 0;
+	/* Add more translations if necessary */
+	default:
+		return -EIO;
+	}
+}
+
+static u64 opal_scom_unmangle(u64 reg)
+{
+	/*
+	 * XSCOM indirect addresses have the top bit set. Additionally
+	 * the reset of the top 3 nibbles is always 0.
+	 *
+	 * Because the debugfs interface uses signed offsets and shifts
+	 * the address left by 3, we basically cannot use the top 4 bits
+	 * of the 64-bit address, and thus cannot use the indirect bit.
+	 *
+	 * To deal with that, we support the indirect bit being in bit
+	 * 4 (IBM notation) instead of bit 0 in this API, we do the
+	 * conversion here. To leave room for further xscom address
+	 * expansion, we only clear out the top byte
+	 *
+	 */
+	if (reg & (1ull << 59))
+		reg = (reg & ~(0xffull << 56)) | (1ull << 63);
+	return reg;
+}
+
+static int opal_scom_read(scom_map_t map, u64 reg, u64 *value)
+{
+	struct opal_scom_map *m = map;
+	int64_t rc;
+
+	reg = opal_scom_unmangle(reg);
+	rc = opal_xscom_read(m->chip, m->addr + reg, (uint64_t *)__pa(value));
+	return opal_xscom_err_xlate(rc);
+}
+
+static int opal_scom_write(scom_map_t map, u64 reg, u64 value)
+{
+	struct opal_scom_map *m = map;
+	int64_t rc;
+
+	reg = opal_scom_unmangle(reg);
+	rc = opal_xscom_write(m->chip, m->addr + reg, value);
+	return opal_xscom_err_xlate(rc);
+}
+
+static const struct scom_controller opal_scom_controller = {
+	.map	= opal_scom_map,
+	.unmap	= opal_scom_unmap,
+	.read	= opal_scom_read,
+	.write	= opal_scom_write
+};
+
+static int opal_xscom_init(void)
+{
+	if (firmware_has_feature(FW_FEATURE_OPALv3))
+		scom_init(&opal_scom_controller);
+	return 0;
+}
+arch_initcall(opal_xscom_init);
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 2911abe..1c798cd 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -13,15 +13,20 @@
 
 #include <linux/types.h>
 #include <linux/of.h>
+#include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
 #include <linux/slab.h>
+#include <linux/kobject.h>
 #include <asm/opal.h>
 #include <asm/firmware.h>
 
 #include "powernv.h"
 
+/* /sys/firmware/opal */
+struct kobject *opal_kobj;
+
 struct opal {
 	u64 base;
 	u64 entry;
@@ -77,6 +82,7 @@
 
 static int __init opal_register_exception_handlers(void)
 {
+#ifdef __BIG_ENDIAN__
 	u64 glue;
 
 	if (!(powerpc_firmware_features & FW_FEATURE_OPAL))
@@ -94,6 +100,7 @@
 					0, glue);
 	glue += 128;
 	opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue);
+#endif
 
 	return 0;
 }
@@ -164,27 +171,28 @@
 
 int opal_get_chars(uint32_t vtermno, char *buf, int count)
 {
-	s64 len, rc;
-	u64 evt;
+	s64 rc;
+	__be64 evt, len;
 
 	if (!opal.entry)
 		return -ENODEV;
 	opal_poll_events(&evt);
-	if ((evt & OPAL_EVENT_CONSOLE_INPUT) == 0)
+	if ((be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_INPUT) == 0)
 		return 0;
-	len = count;
-	rc = opal_console_read(vtermno, &len, buf);
+	len = cpu_to_be64(count);
+	rc = opal_console_read(vtermno, &len, buf);	
 	if (rc == OPAL_SUCCESS)
-		return len;
+		return be64_to_cpu(len);
 	return 0;
 }
 
 int opal_put_chars(uint32_t vtermno, const char *data, int total_len)
 {
 	int written = 0;
+	__be64 olen;
 	s64 len, rc;
 	unsigned long flags;
-	u64 evt;
+	__be64 evt;
 
 	if (!opal.entry)
 		return -ENODEV;
@@ -199,13 +207,14 @@
 	 */
 	spin_lock_irqsave(&opal_write_lock, flags);
 	if (firmware_has_feature(FW_FEATURE_OPALv2)) {
-		rc = opal_console_write_buffer_space(vtermno, &len);
+		rc = opal_console_write_buffer_space(vtermno, &olen);
+		len = be64_to_cpu(olen);
 		if (rc || len < total_len) {
 			spin_unlock_irqrestore(&opal_write_lock, flags);
 			/* Closed -> drop characters */
 			if (rc)
 				return total_len;
-			opal_poll_events(&evt);
+			opal_poll_events(NULL);
 			return -EAGAIN;
 		}
 	}
@@ -216,8 +225,9 @@
 	rc = OPAL_BUSY;
 	while(total_len > 0 && (rc == OPAL_BUSY ||
 				rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) {
-		len = total_len;
-		rc = opal_console_write(vtermno, &len, data);
+		olen = cpu_to_be64(total_len);
+		rc = opal_console_write(vtermno, &olen, data);
+		len = be64_to_cpu(olen);
 
 		/* Closed or other error drop */
 		if (rc != OPAL_SUCCESS && rc != OPAL_BUSY &&
@@ -237,7 +247,8 @@
 		 */
 		do
 			opal_poll_events(&evt);
-		while(rc == OPAL_SUCCESS && (evt & OPAL_EVENT_CONSOLE_OUTPUT));
+		while(rc == OPAL_SUCCESS &&
+			(be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_OUTPUT));
 	}
 	spin_unlock_irqrestore(&opal_write_lock, flags);
 	return written;
@@ -360,7 +371,7 @@
 
 static irqreturn_t opal_interrupt(int irq, void *data)
 {
-	uint64_t events;
+	__be64 events;
 
 	opal_handle_interrupt(virq_to_hw(irq), &events);
 
@@ -369,10 +380,21 @@
 	return IRQ_HANDLED;
 }
 
+static int opal_sysfs_init(void)
+{
+	opal_kobj = kobject_create_and_add("opal", firmware_kobj);
+	if (!opal_kobj) {
+		pr_warn("kobject_create_and_add opal failed\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
 static int __init opal_init(void)
 {
 	struct device_node *np, *consoles;
-	const u32 *irqs;
+	const __be32 *irqs;
 	int rc, i, irqlen;
 
 	opal_node = of_find_node_by_path("/ibm,opal");
@@ -414,6 +436,14 @@
 				   " (0x%x)\n", rc, irq, hwirq);
 		opal_irqs[i] = irq;
 	}
+
+	/* Create "opal" kobject under /sys/firmware */
+	rc = opal_sysfs_init();
+	if (rc == 0) {
+		/* Setup code update interface */
+		opal_flash_init();
+	}
+
 	return 0;
 }
 subsys_initcall(opal_init);
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 74a5a57..084cdfa 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -70,6 +70,16 @@
 define_pe_printk_level(pe_warn, KERN_WARNING);
 define_pe_printk_level(pe_info, KERN_INFO);
 
+/*
+ * stdcix is only supposed to be used in hypervisor real mode as per
+ * the architecture spec
+ */
+static inline void __raw_rm_writeq(u64 val, volatile void __iomem *paddr)
+{
+	__asm__ __volatile__("stdcix %0,0,%1"
+		: : "r" (val), "r" (paddr) : "memory");
+}
+
 static int pnv_ioda_alloc_pe(struct pnv_phb *phb)
 {
 	unsigned long pe;
@@ -153,13 +163,23 @@
 		rid_end = pe->rid + 1;
 	}
 
-	/* Associate PE in PELT */
+	/*
+	 * Associate PE in PELT. We need add the PE into the
+	 * corresponding PELT-V as well. Otherwise, the error
+	 * originated from the PE might contribute to other
+	 * PEs.
+	 */
 	rc = opal_pci_set_pe(phb->opal_id, pe->pe_number, pe->rid,
 			     bcomp, dcomp, fcomp, OPAL_MAP_PE);
 	if (rc) {
 		pe_err(pe, "OPAL error %ld trying to setup PELT table\n", rc);
 		return -ENXIO;
 	}
+
+	rc = opal_pci_set_peltv(phb->opal_id, pe->pe_number,
+				pe->pe_number, OPAL_ADD_PE_TO_DOMAIN);
+	if (rc)
+		pe_warn(pe, "OPAL error %d adding self to PELTV\n", rc);
 	opal_pci_eeh_freeze_clear(phb->opal_id, pe->pe_number,
 				  OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
 
@@ -454,10 +474,13 @@
 	}
 }
 
-static void pnv_pci_ioda1_tce_invalidate(struct iommu_table *tbl,
-					 u64 *startp, u64 *endp)
+static void pnv_pci_ioda1_tce_invalidate(struct pnv_ioda_pe *pe,
+					 struct iommu_table *tbl,
+					 __be64 *startp, __be64 *endp, bool rm)
 {
-	u64 __iomem *invalidate = (u64 __iomem *)tbl->it_index;
+	__be64 __iomem *invalidate = rm ?
+		(__be64 __iomem *)pe->tce_inval_reg_phys :
+		(__be64 __iomem *)tbl->it_index;
 	unsigned long start, end, inc;
 
 	start = __pa(startp);
@@ -484,7 +507,10 @@
 
         mb(); /* Ensure above stores are visible */
         while (start <= end) {
-                __raw_writeq(start, invalidate);
+		if (rm)
+			__raw_rm_writeq(cpu_to_be64(start), invalidate);
+		else
+			__raw_writeq(cpu_to_be64(start), invalidate);
                 start += inc;
         }
 
@@ -496,10 +522,12 @@
 
 static void pnv_pci_ioda2_tce_invalidate(struct pnv_ioda_pe *pe,
 					 struct iommu_table *tbl,
-					 u64 *startp, u64 *endp)
+					 __be64 *startp, __be64 *endp, bool rm)
 {
 	unsigned long start, end, inc;
-	u64 __iomem *invalidate = (u64 __iomem *)tbl->it_index;
+	__be64 __iomem *invalidate = rm ?
+		(__be64 __iomem *)pe->tce_inval_reg_phys :
+		(__be64 __iomem *)tbl->it_index;
 
 	/* We'll invalidate DMA address in PE scope */
 	start = 0x2ul << 60;
@@ -515,22 +543,25 @@
 	mb();
 
 	while (start <= end) {
-		__raw_writeq(start, invalidate);
+		if (rm)
+			__raw_rm_writeq(cpu_to_be64(start), invalidate);
+		else
+			__raw_writeq(cpu_to_be64(start), invalidate);
 		start += inc;
 	}
 }
 
 void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl,
-				 u64 *startp, u64 *endp)
+				 __be64 *startp, __be64 *endp, bool rm)
 {
 	struct pnv_ioda_pe *pe = container_of(tbl, struct pnv_ioda_pe,
 					      tce32_table);
 	struct pnv_phb *phb = pe->phb;
 
 	if (phb->type == PNV_PHB_IODA1)
-		pnv_pci_ioda1_tce_invalidate(tbl, startp, endp);
+		pnv_pci_ioda1_tce_invalidate(pe, tbl, startp, endp, rm);
 	else
-		pnv_pci_ioda2_tce_invalidate(pe, tbl, startp, endp);
+		pnv_pci_ioda2_tce_invalidate(pe, tbl, startp, endp, rm);
 }
 
 static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb,
@@ -603,7 +634,9 @@
 		 * bus number, print that out instead.
 		 */
 		tbl->it_busno = 0;
-		tbl->it_index = (unsigned long)ioremap(be64_to_cpup(swinvp), 8);
+		pe->tce_inval_reg_phys = be64_to_cpup(swinvp);
+		tbl->it_index = (unsigned long)ioremap(pe->tce_inval_reg_phys,
+				8);
 		tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE |
 			       TCE_PCI_SWINV_PAIR;
 	}
@@ -681,7 +714,9 @@
 		 * bus number, print that out instead.
 		 */
 		tbl->it_busno = 0;
-		tbl->it_index = (unsigned long)ioremap(be64_to_cpup(swinvp), 8);
+		pe->tce_inval_reg_phys = be64_to_cpup(swinvp);
+		tbl->it_index = (unsigned long)ioremap(pe->tce_inval_reg_phys,
+				8);
 		tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE;
 	}
 	iommu_init_table(tbl, phb->hose->node);
@@ -786,8 +821,7 @@
 	struct irq_data *idata;
 	struct irq_chip *ichip;
 	unsigned int xive_num = hwirq - phb->msi_base;
-	uint64_t addr64;
-	uint32_t addr32, data;
+	__be32 data;
 	int rc;
 
 	/* No PE assigned ? bail out ... no MSI for you ! */
@@ -811,6 +845,8 @@
 	}
 
 	if (is_64) {
+		__be64 addr64;
+
 		rc = opal_get_msi_64(phb->opal_id, pe->mve_number, xive_num, 1,
 				     &addr64, &data);
 		if (rc) {
@@ -818,9 +854,11 @@
 				pci_name(dev), rc);
 			return -EIO;
 		}
-		msg->address_hi = addr64 >> 32;
-		msg->address_lo = addr64 & 0xfffffffful;
+		msg->address_hi = be64_to_cpu(addr64) >> 32;
+		msg->address_lo = be64_to_cpu(addr64) & 0xfffffffful;
 	} else {
+		__be32 addr32;
+
 		rc = opal_get_msi_32(phb->opal_id, pe->mve_number, xive_num, 1,
 				     &addr32, &data);
 		if (rc) {
@@ -829,9 +867,9 @@
 			return -EIO;
 		}
 		msg->address_hi = 0;
-		msg->address_lo = addr32;
+		msg->address_lo = be32_to_cpu(addr32);
 	}
-	msg->data = data;
+	msg->data = be32_to_cpu(data);
 
 	/*
 	 * Change the IRQ chip for the MSI interrupts on PHB3.
@@ -1106,8 +1144,8 @@
 	struct pci_controller *hose;
 	struct pnv_phb *phb;
 	unsigned long size, m32map_off, iomap_off, pemap_off;
-	const u64 *prop64;
-	const u32 *prop32;
+	const __be64 *prop64;
+	const __be32 *prop32;
 	int len;
 	u64 phb_id;
 	void *aux;
@@ -1142,8 +1180,8 @@
 	spin_lock_init(&phb->lock);
 	prop32 = of_get_property(np, "bus-range", &len);
 	if (prop32 && len == 8) {
-		hose->first_busno = prop32[0];
-		hose->last_busno = prop32[1];
+		hose->first_busno = be32_to_cpu(prop32[0]);
+		hose->last_busno = be32_to_cpu(prop32[1]);
 	} else {
 		pr_warn("  Broken <bus-range> on %s\n", np->full_name);
 		hose->first_busno = 0;
@@ -1171,12 +1209,13 @@
 		pr_err("  Failed to map registers !\n");
 
 	/* Initialize more IODA stuff */
+	phb->ioda.total_pe = 1;
 	prop32 = of_get_property(np, "ibm,opal-num-pes", NULL);
-	if (!prop32)
-		phb->ioda.total_pe = 1;
-	else
-		phb->ioda.total_pe = *prop32;
-
+	if (prop32)
+		phb->ioda.total_pe = be32_to_cpup(prop32);
+	prop32 = of_get_property(np, "ibm,opal-reserved-pe", NULL);
+	if (prop32)
+		phb->ioda.reserved_pe = be32_to_cpup(prop32);
 	phb->ioda.m32_size = resource_size(&hose->mem_resources[0]);
 	/* FW Has already off top 64k of M32 space (MSI space) */
 	phb->ioda.m32_size += 0x10000;
@@ -1205,7 +1244,7 @@
 	if (phb->type == PNV_PHB_IODA1)
 		phb->ioda.io_segmap = aux + iomap_off;
 	phb->ioda.pe_array = aux + pemap_off;
-	set_bit(0, phb->ioda.pe_alloc);
+	set_bit(phb->ioda.reserved_pe, phb->ioda.pe_alloc);
 
 	INIT_LIST_HEAD(&phb->ioda.pe_dma_list);
 	INIT_LIST_HEAD(&phb->ioda.pe_list);
@@ -1230,8 +1269,10 @@
 					 segment_size);
 #endif
 
-	pr_info("  %d PE's M32: 0x%x [segment=0x%x] IO: 0x%x [segment=0x%x]\n",
+	pr_info("  %d (%d) PE's M32: 0x%x [segment=0x%x]"
+		" IO: 0x%x [segment=0x%x]\n",
 		phb->ioda.total_pe,
+		phb->ioda.reserved_pe,
 		phb->ioda.m32_size, phb->ioda.m32_segsize,
 		phb->ioda.io_size, phb->ioda.io_segsize);
 
@@ -1268,13 +1309,6 @@
 	rc = opal_pci_reset(phb_id, OPAL_PCI_IODA_TABLE_RESET, OPAL_ASSERT_RESET);
 	if (rc)
 		pr_warning("  OPAL Error %ld performing IODA table reset !\n", rc);
-
-	/*
-	 * On IODA1 map everything to PE#0, on IODA2 we assume the IODA reset
-	 * has cleared the RTT which has the same effect
-	 */
-	if (ioda_type == PNV_PHB_IODA1)
-		opal_pci_set_pe(phb_id, 0, 0, 7, 1, 1 , OPAL_MAP_PE);
 }
 
 void __init pnv_pci_init_ioda2_phb(struct device_node *np)
@@ -1285,7 +1319,7 @@
 void __init pnv_pci_init_ioda_hub(struct device_node *np)
 {
 	struct device_node *phbn;
-	const u64 *prop64;
+	const __be64 *prop64;
 	u64 hub_id;
 
 	pr_info("Probing IODA IO-Hub %s\n", np->full_name);
diff --git a/arch/powerpc/platforms/powernv/pci-p5ioc2.c b/arch/powerpc/platforms/powernv/pci-p5ioc2.c
index b68db63..f8b4bd8 100644
--- a/arch/powerpc/platforms/powernv/pci-p5ioc2.c
+++ b/arch/powerpc/platforms/powernv/pci-p5ioc2.c
@@ -99,7 +99,7 @@
 					   void *tce_mem, u64 tce_size)
 {
 	struct pnv_phb *phb;
-	const u64 *prop64;
+	const __be64 *prop64;
 	u64 phb_id;
 	int64_t rc;
 	static int primary = 1;
@@ -178,7 +178,7 @@
 void __init pnv_pci_init_p5ioc2_hub(struct device_node *np)
 {
 	struct device_node *phbn;
-	const u64 *prop64;
+	const __be64 *prop64;
 	u64 hub_id;
 	void *tce_mem;
 	uint64_t tce_per_phb;
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index a28d3b5..4eb33a9 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -236,17 +236,21 @@
 {
 	s64	rc;
 	u8	fstate;
-	u16	pcierr;
+	__be16	pcierr;
 	u32	pe_no;
 
 	/*
 	 * Get the PE#. During the PCI probe stage, we might not
 	 * setup that yet. So all ER errors should be mapped to
-	 * PE#0
+	 * reserved PE.
 	 */
 	pe_no = PCI_DN(dn)->pe_number;
-	if (pe_no == IODA_INVALID_PE)
-		pe_no = 0;
+	if (pe_no == IODA_INVALID_PE) {
+		if (phb->type == PNV_PHB_P5IOC2)
+			pe_no = 0;
+		else
+			pe_no = phb->ioda.reserved_pe;
+	}
 
 	/* Read freeze status */
 	rc = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, &fstate, &pcierr,
@@ -283,16 +287,16 @@
 		break;
 	}
 	case 2: {
-		u16 v16;
+		__be16 v16;
 		rc = opal_pci_config_read_half_word(phb->opal_id, bdfn, where,
 						   &v16);
-		*val = (rc == OPAL_SUCCESS) ? v16 : 0xffff;
+		*val = (rc == OPAL_SUCCESS) ? be16_to_cpu(v16) : 0xffff;
 		break;
 	}
 	case 4: {
-		u32 v32;
+		__be32 v32;
 		rc = opal_pci_config_read_word(phb->opal_id, bdfn, where, &v32);
-		*val = (rc == OPAL_SUCCESS) ? v32 : 0xffffffff;
+		*val = (rc == OPAL_SUCCESS) ? be32_to_cpu(v32) : 0xffffffff;
 		break;
 	}
 	default:
@@ -401,10 +405,10 @@
 
 static int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
 			 unsigned long uaddr, enum dma_data_direction direction,
-			 struct dma_attrs *attrs)
+			 struct dma_attrs *attrs, bool rm)
 {
 	u64 proto_tce;
-	u64 *tcep, *tces;
+	__be64 *tcep, *tces;
 	u64 rpn;
 
 	proto_tce = TCE_PCI_READ; // Read allowed
@@ -412,33 +416,48 @@
 	if (direction != DMA_TO_DEVICE)
 		proto_tce |= TCE_PCI_WRITE;
 
-	tces = tcep = ((u64 *)tbl->it_base) + index - tbl->it_offset;
+	tces = tcep = ((__be64 *)tbl->it_base) + index - tbl->it_offset;
 	rpn = __pa(uaddr) >> TCE_SHIFT;
 
 	while (npages--)
-		*(tcep++) = proto_tce | (rpn++ << TCE_RPN_SHIFT);
+		*(tcep++) = cpu_to_be64(proto_tce | (rpn++ << TCE_RPN_SHIFT));
 
 	/* Some implementations won't cache invalid TCEs and thus may not
 	 * need that flush. We'll probably turn it_type into a bit mask
 	 * of flags if that becomes the case
 	 */
 	if (tbl->it_type & TCE_PCI_SWINV_CREATE)
-		pnv_pci_ioda_tce_invalidate(tbl, tces, tcep - 1);
+		pnv_pci_ioda_tce_invalidate(tbl, tces, tcep - 1, rm);
 
 	return 0;
 }
 
-static void pnv_tce_free(struct iommu_table *tbl, long index, long npages)
+static int pnv_tce_build_vm(struct iommu_table *tbl, long index, long npages,
+			    unsigned long uaddr,
+			    enum dma_data_direction direction,
+			    struct dma_attrs *attrs)
 {
-	u64 *tcep, *tces;
+	return pnv_tce_build(tbl, index, npages, uaddr, direction, attrs,
+			false);
+}
 
-	tces = tcep = ((u64 *)tbl->it_base) + index - tbl->it_offset;
+static void pnv_tce_free(struct iommu_table *tbl, long index, long npages,
+		bool rm)
+{
+	__be64 *tcep, *tces;
+
+	tces = tcep = ((__be64 *)tbl->it_base) + index - tbl->it_offset;
 
 	while (npages--)
-		*(tcep++) = 0;
+		*(tcep++) = cpu_to_be64(0);
 
 	if (tbl->it_type & TCE_PCI_SWINV_FREE)
-		pnv_pci_ioda_tce_invalidate(tbl, tces, tcep - 1);
+		pnv_pci_ioda_tce_invalidate(tbl, tces, tcep - 1, rm);
+}
+
+static void pnv_tce_free_vm(struct iommu_table *tbl, long index, long npages)
+{
+	pnv_tce_free(tbl, index, npages, false);
 }
 
 static unsigned long pnv_tce_get(struct iommu_table *tbl, long index)
@@ -446,6 +465,19 @@
 	return ((u64 *)tbl->it_base)[index - tbl->it_offset];
 }
 
+static int pnv_tce_build_rm(struct iommu_table *tbl, long index, long npages,
+			    unsigned long uaddr,
+			    enum dma_data_direction direction,
+			    struct dma_attrs *attrs)
+{
+	return pnv_tce_build(tbl, index, npages, uaddr, direction, attrs, true);
+}
+
+static void pnv_tce_free_rm(struct iommu_table *tbl, long index, long npages)
+{
+	pnv_tce_free(tbl, index, npages, true);
+}
+
 void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
 			       void *tce_mem, u64 tce_size,
 			       u64 dma_offset)
@@ -484,8 +516,8 @@
 	swinvp = of_get_property(hose->dn, "linux,tce-sw-invalidate-info",
 				 NULL);
 	if (swinvp) {
-		tbl->it_busno = swinvp[1];
-		tbl->it_index = (unsigned long)ioremap(swinvp[0], 8);
+		tbl->it_busno = be64_to_cpu(swinvp[1]);
+		tbl->it_index = (unsigned long)ioremap(be64_to_cpup(swinvp), 8);
 		tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE;
 	}
 	return tbl;
@@ -610,8 +642,10 @@
 
 	/* Configure IOMMU DMA hooks */
 	ppc_md.pci_dma_dev_setup = pnv_pci_dma_dev_setup;
-	ppc_md.tce_build = pnv_tce_build;
-	ppc_md.tce_free = pnv_tce_free;
+	ppc_md.tce_build = pnv_tce_build_vm;
+	ppc_md.tce_free = pnv_tce_free_vm;
+	ppc_md.tce_build_rm = pnv_tce_build_rm;
+	ppc_md.tce_free_rm = pnv_tce_free_rm;
 	ppc_md.tce_get = pnv_tce_get;
 	ppc_md.pci_probe_mode = pnv_pci_probe_mode;
 	set_pci_dma_ops(&dma_iommu_ops);
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index d633c64..911c24e 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -17,7 +17,7 @@
 	PNV_PHB_MODEL_PHB3,
 };
 
-#define PNV_PCI_DIAG_BUF_SIZE	4096
+#define PNV_PCI_DIAG_BUF_SIZE	8192
 #define PNV_IODA_PE_DEV		(1 << 0)	/* PE has single PCI device	*/
 #define PNV_IODA_PE_BUS		(1 << 1)	/* PE has primary PCI bus	*/
 #define PNV_IODA_PE_BUS_ALL	(1 << 2)	/* PE has subordinate buses	*/
@@ -52,6 +52,7 @@
 	int			tce32_seg;
 	int			tce32_segcount;
 	struct iommu_table	tce32_table;
+	phys_addr_t		tce_inval_reg_phys;
 
 	/* XXX TODO: Add support for additional 64-bit iommus */
 
@@ -124,6 +125,7 @@
 		struct {
 			/* Global bridge info */
 			unsigned int		total_pe;
+			unsigned int		reserved_pe;
 			unsigned int		m32_size;
 			unsigned int		m32_segsize;
 			unsigned int		m32_pci_base;
@@ -193,6 +195,6 @@
 extern void pnv_pci_init_ioda_hub(struct device_node *np);
 extern void pnv_pci_init_ioda2_phb(struct device_node *np);
 extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl,
-					u64 *startp, u64 *endp);
+					__be64 *startp, __be64 *endp, bool rm);
 
 #endif /* __POWERNV_PCI_H */
diff --git a/arch/powerpc/platforms/powernv/rng.c b/arch/powerpc/platforms/powernv/rng.c
new file mode 100644
index 0000000..8844628
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/rng.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2013, Michael Ellerman, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt)	"powernv-rng: " fmt
+
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+#include <asm/archrandom.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+
+
+struct powernv_rng {
+	void __iomem *regs;
+	unsigned long mask;
+};
+
+static DEFINE_PER_CPU(struct powernv_rng *, powernv_rng);
+
+
+static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val)
+{
+	unsigned long parity;
+
+	/* Calculate the parity of the value */
+	asm ("popcntd %0,%1" : "=r" (parity) : "r" (val));
+
+	/* xor our value with the previous mask */
+	val ^= rng->mask;
+
+	/* update the mask based on the parity of this value */
+	rng->mask = (rng->mask << 1) | (parity & 1);
+
+	return val;
+}
+
+int powernv_get_random_long(unsigned long *v)
+{
+	struct powernv_rng *rng;
+
+	rng = get_cpu_var(powernv_rng);
+
+	*v = rng_whiten(rng, in_be64(rng->regs));
+
+	put_cpu_var(rng);
+
+	return 1;
+}
+EXPORT_SYMBOL_GPL(powernv_get_random_long);
+
+static __init void rng_init_per_cpu(struct powernv_rng *rng,
+				    struct device_node *dn)
+{
+	int chip_id, cpu;
+
+	chip_id = of_get_ibm_chip_id(dn);
+	if (chip_id == -1)
+		pr_warn("No ibm,chip-id found for %s.\n", dn->full_name);
+
+	for_each_possible_cpu(cpu) {
+		if (per_cpu(powernv_rng, cpu) == NULL ||
+		    cpu_to_chip_id(cpu) == chip_id) {
+			per_cpu(powernv_rng, cpu) = rng;
+		}
+	}
+}
+
+static __init int rng_create(struct device_node *dn)
+{
+	struct powernv_rng *rng;
+	unsigned long val;
+
+	rng = kzalloc(sizeof(*rng), GFP_KERNEL);
+	if (!rng)
+		return -ENOMEM;
+
+	rng->regs = of_iomap(dn, 0);
+	if (!rng->regs) {
+		kfree(rng);
+		return -ENXIO;
+	}
+
+	val = in_be64(rng->regs);
+	rng->mask = val;
+
+	rng_init_per_cpu(rng, dn);
+
+	pr_info_once("Registering arch random hook.\n");
+
+	ppc_md.get_random_long = powernv_get_random_long;
+
+	return 0;
+}
+
+static __init int rng_init(void)
+{
+	struct device_node *dn;
+	int rc;
+
+	for_each_compatible_node(dn, NULL, "ibm,power-rng") {
+		rc = rng_create(dn);
+		if (rc) {
+			pr_err("Failed creating rng for %s (%d).\n",
+				dn->full_name, rc);
+			continue;
+		}
+
+		/* Create devices for hwrng driver */
+		of_platform_device_create(dn, NULL, NULL);
+	}
+
+	return 0;
+}
+subsys_initcall(rng_init);
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index e239dcf..19884b2 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -23,6 +23,7 @@
 #include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/of.h>
+#include <linux/of_fdt.h>
 #include <linux/interrupt.h>
 #include <linux/bug.h>
 
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 6c61ec5..fbccac9 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -3,7 +3,7 @@
 
 obj-y			:= lpar.o hvCall.o nvram.o reconfig.o \
 			   setup.o iommu.o event_sources.o ras.o \
-			   firmware.o power.o dlpar.o mobility.o
+			   firmware.o power.o dlpar.o mobility.o rng.o
 obj-$(CONFIG_SMP)	+= smp.o
 obj-$(CONFIG_SCANLOG)	+= scanlog.o
 obj-$(CONFIG_EEH)	+= eeh_pseries.o
diff --git a/arch/powerpc/platforms/pseries/event_sources.c b/arch/powerpc/platforms/pseries/event_sources.c
index 2605c31..18380e8 100644
--- a/arch/powerpc/platforms/pseries/event_sources.c
+++ b/arch/powerpc/platforms/pseries/event_sources.c
@@ -25,7 +25,7 @@
 				const char *name)
 {
 	int i, index, count = 0;
-	struct of_irq oirq;
+	struct of_phandle_args oirq;
 	const u32 *opicprop;
 	unsigned int opicplen;
 	unsigned int virqs[16];
@@ -55,13 +55,11 @@
 	/* Else use normal interrupt tree parsing */
 	else {
 		/* First try to do a proper OF tree parsing */
-		for (index = 0; of_irq_map_one(np, index, &oirq) == 0;
+		for (index = 0; of_irq_parse_one(np, index, &oirq) == 0;
 		     index++) {
 			if (count > 15)
 				break;
-			virqs[count] = irq_create_of_mapping(oirq.controller,
-							    oirq.specifier,
-							    oirq.size);
+			virqs[count] = irq_create_of_mapping(&oirq);
 			if (virqs[count] == NO_IRQ) {
 				pr_err("event-sources: Unable to allocate "
 				       "interrupt number for %s\n",
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index 9a432de..9590dbb 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -10,12 +10,14 @@
  */
 
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/memblock.h>
 #include <linux/vmalloc.h>
 #include <linux/memory.h>
 
 #include <asm/firmware.h>
 #include <asm/machdep.h>
+#include <asm/prom.h>
 #include <asm/sparsemem.h>
 
 static unsigned long get_memblock_size(void)
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 0307901..f253361 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -52,7 +52,7 @@
 
 
 static void tce_invalidate_pSeries_sw(struct iommu_table *tbl,
-				      u64 *startp, u64 *endp)
+				      __be64 *startp, __be64 *endp)
 {
 	u64 __iomem *invalidate = (u64 __iomem *)tbl->it_index;
 	unsigned long start, end, inc;
@@ -86,7 +86,7 @@
 			      struct dma_attrs *attrs)
 {
 	u64 proto_tce;
-	u64 *tcep, *tces;
+	__be64 *tcep, *tces;
 	u64 rpn;
 
 	proto_tce = TCE_PCI_READ; // Read allowed
@@ -94,12 +94,12 @@
 	if (direction != DMA_TO_DEVICE)
 		proto_tce |= TCE_PCI_WRITE;
 
-	tces = tcep = ((u64 *)tbl->it_base) + index;
+	tces = tcep = ((__be64 *)tbl->it_base) + index;
 
 	while (npages--) {
 		/* can't move this out since we might cross MEMBLOCK boundary */
 		rpn = __pa(uaddr) >> TCE_SHIFT;
-		*tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
+		*tcep = cpu_to_be64(proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT);
 
 		uaddr += TCE_PAGE_SIZE;
 		tcep++;
@@ -113,9 +113,9 @@
 
 static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages)
 {
-	u64 *tcep, *tces;
+	__be64 *tcep, *tces;
 
-	tces = tcep = ((u64 *)tbl->it_base) + index;
+	tces = tcep = ((__be64 *)tbl->it_base) + index;
 
 	while (npages--)
 		*(tcep++) = 0;
@@ -126,11 +126,11 @@
 
 static unsigned long tce_get_pseries(struct iommu_table *tbl, long index)
 {
-	u64 *tcep;
+	__be64 *tcep;
 
-	tcep = ((u64 *)tbl->it_base) + index;
+	tcep = ((__be64 *)tbl->it_base) + index;
 
-	return *tcep;
+	return be64_to_cpu(*tcep);
 }
 
 static void tce_free_pSeriesLP(struct iommu_table*, long, long);
@@ -177,7 +177,7 @@
 	return ret;
 }
 
-static DEFINE_PER_CPU(u64 *, tce_page);
+static DEFINE_PER_CPU(__be64 *, tce_page);
 
 static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
 				     long npages, unsigned long uaddr,
@@ -186,7 +186,7 @@
 {
 	u64 rc = 0;
 	u64 proto_tce;
-	u64 *tcep;
+	__be64 *tcep;
 	u64 rpn;
 	long l, limit;
 	long tcenum_start = tcenum, npages_start = npages;
@@ -206,7 +206,7 @@
 	 * from iommu_alloc{,_sg}()
 	 */
 	if (!tcep) {
-		tcep = (u64 *)__get_free_page(GFP_ATOMIC);
+		tcep = (__be64 *)__get_free_page(GFP_ATOMIC);
 		/* If allocation fails, fall back to the loop implementation */
 		if (!tcep) {
 			local_irq_restore(flags);
@@ -230,7 +230,7 @@
 		limit = min_t(long, npages, 4096/TCE_ENTRY_SIZE);
 
 		for (l = 0; l < limit; l++) {
-			tcep[l] = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
+			tcep[l] = cpu_to_be64(proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT);
 			rpn++;
 		}
 
@@ -329,16 +329,16 @@
 
 /* Dynamic DMA Window support */
 struct ddw_query_response {
-	u32 windows_available;
-	u32 largest_available_block;
-	u32 page_size;
-	u32 migration_capable;
+	__be32 windows_available;
+	__be32 largest_available_block;
+	__be32 page_size;
+	__be32 migration_capable;
 };
 
 struct ddw_create_response {
-	u32 liobn;
-	u32 addr_hi;
-	u32 addr_lo;
+	__be32 liobn;
+	__be32 addr_hi;
+	__be32 addr_lo;
 };
 
 static LIST_HEAD(direct_window_list);
@@ -392,7 +392,8 @@
 					unsigned long num_pfn, const void *arg)
 {
 	const struct dynamic_dma_window_prop *maprange = arg;
-	u64 *tcep, tce_size, num_tce, dma_offset, next, proto_tce, liobn;
+	u64 tce_size, num_tce, dma_offset, next, proto_tce, liobn;
+	__be64 *tcep;
 	u32 tce_shift;
 	u64 rc = 0;
 	long l, limit;
@@ -401,7 +402,7 @@
 	tcep = __get_cpu_var(tce_page);
 
 	if (!tcep) {
-		tcep = (u64 *)__get_free_page(GFP_ATOMIC);
+		tcep = (__be64 *)__get_free_page(GFP_ATOMIC);
 		if (!tcep) {
 			local_irq_enable();
 			return -ENOMEM;
@@ -435,7 +436,7 @@
 		dma_offset = next + be64_to_cpu(maprange->dma_base);
 
 		for (l = 0; l < limit; l++) {
-			tcep[l] = proto_tce | next;
+			tcep[l] = cpu_to_be64(proto_tce | next);
 			next += tce_size;
 		}
 
@@ -780,7 +781,7 @@
 	list_for_each_entry(window, &direct_window_list, list) {
 		if (window->device == pdn) {
 			direct64 = window->prop;
-			dma_addr = direct64->dma_base;
+			dma_addr = be64_to_cpu(direct64->dma_base);
 			break;
 		}
 	}
@@ -1045,11 +1046,11 @@
 		dev_dbg(&dev->dev, "no free dynamic windows");
 		goto out_restore_window;
 	}
-	if (query.page_size & 4) {
+	if (be32_to_cpu(query.page_size) & 4) {
 		page_shift = 24; /* 16MB */
-	} else if (query.page_size & 2) {
+	} else if (be32_to_cpu(query.page_size) & 2) {
 		page_shift = 16; /* 64kB */
-	} else if (query.page_size & 1) {
+	} else if (be32_to_cpu(query.page_size) & 1) {
 		page_shift = 12; /* 4kB */
 	} else {
 		dev_dbg(&dev->dev, "no supported direct page size in mask %x",
@@ -1059,7 +1060,7 @@
 	/* verify the window * number of ptes will map the partition */
 	/* check largest block * page size > max memory hotplug addr */
 	max_addr = memory_hotplug_max();
-	if (query.largest_available_block < (max_addr >> page_shift)) {
+	if (be32_to_cpu(query.largest_available_block) < (max_addr >> page_shift)) {
 		dev_dbg(&dev->dev, "can't map partiton max 0x%llx with %u "
 			  "%llu-sized pages\n", max_addr,  query.largest_available_block,
 			  1ULL << page_shift);
@@ -1085,7 +1086,7 @@
 	if (ret != 0)
 		goto out_free_prop;
 
-	ddwprop->liobn = cpu_to_be32(create.liobn);
+	ddwprop->liobn = create.liobn;
 	ddwprop->dma_base = cpu_to_be64(of_read_number(&create.addr_hi, 2));
 	ddwprop->tce_shift = cpu_to_be32(page_shift);
 	ddwprop->window_shift = cpu_to_be32(len);
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index d276cd3..057fc89 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -429,9 +429,6 @@
 	loff_t p;
 	int size;
 
-	/* Scan nvram for partitions */
-	nvram_scan_partitions();
-
 	/* Look for ours */
 	p = nvram_find_partition(part->name, NVRAM_SIG_OS, &size);
 
@@ -795,6 +792,9 @@
 {
 	int rc;
 
+	/* Scan nvram for partitions */
+	nvram_scan_partitions();
+
 	rc = pseries_nvram_init_os_partition(&rtas_log_partition);
 	nvram_init_oops_partition(rc == 0);
 	return 0;
@@ -804,7 +804,7 @@
 int __init pSeries_nvram_init(void)
 {
 	struct device_node *nvram;
-	const unsigned int *nbytes_p;
+	const __be32 *nbytes_p;
 	unsigned int proplen;
 
 	nvram = of_find_node_by_type(NULL, "nvram");
@@ -817,7 +817,7 @@
 		return -EIO;
 	}
 
-	nvram_size = *nbytes_p;
+	nvram_size = be32_to_cpup(nbytes_p);
 
 	nvram_fetch = rtas_token("nvram-fetch");
 	nvram_store = rtas_token("nvram-store");
diff --git a/arch/powerpc/platforms/pseries/rng.c b/arch/powerpc/platforms/pseries/rng.c
new file mode 100644
index 0000000..a702f1c
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/rng.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2013, Michael Ellerman, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt)	"pseries-rng: " fmt
+
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <asm/archrandom.h>
+#include <asm/machdep.h>
+
+
+static int pseries_get_random_long(unsigned long *v)
+{
+	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+	if (plpar_hcall(H_RANDOM, retbuf) == H_SUCCESS) {
+		*v = retbuf[0];
+		return 1;
+	}
+
+	return 0;
+}
+
+static __init int rng_init(void)
+{
+	struct device_node *dn;
+
+	dn = of_find_compatible_node(NULL, NULL, "ibm,random");
+	if (!dn)
+		return -ENODEV;
+
+	pr_info("Registering arch random hook.\n");
+
+	ppc_md.get_random_long = pseries_get_random_long;
+
+	return 0;
+}
+subsys_initcall(rng_init);
diff --git a/arch/powerpc/platforms/wsp/scom_smp.c b/arch/powerpc/platforms/wsp/scom_smp.c
index b56b70a..268bc89 100644
--- a/arch/powerpc/platforms/wsp/scom_smp.c
+++ b/arch/powerpc/platforms/wsp/scom_smp.c
@@ -116,7 +116,14 @@
 
 	scom_write(scom, SCOM_RAMIC, cmd);
 
-	while (!((val = scom_read(scom, SCOM_RAMC)) & mask)) {
+	for (;;) {
+		if (scom_read(scom, SCOM_RAMC, &val) != 0) {
+			pr_err("SCOM error on instruction 0x%08x, thread %d\n",
+			       insn, thread);
+			return -1;
+		}
+		if (val & mask)
+			break;
 		pr_devel("Waiting on RAMC = 0x%llx\n", val);
 		if (++n == 3) {
 			pr_err("RAMC timeout on instruction 0x%08x, thread %d\n",
@@ -151,9 +158,7 @@
 	if (rc)
 		return rc;
 
-	*out_gpr = scom_read(scom, SCOM_RAMD);
-
-	return 0;
+	return scom_read(scom, SCOM_RAMD, out_gpr);
 }
 
 static int a2_scom_getspr(scom_map_t scom, int thread, int spr, u64 *out_spr)
@@ -353,7 +358,10 @@
 
 	pr_devel("Bringing up CPU%d using SCOM...\n", lcpu);
 
-	pccr0 = scom_read(scom, SCOM_PCCR0);
+	if (scom_read(scom, SCOM_PCCR0, &pccr0) != 0) {
+		printk(KERN_ERR "XSCOM failure readng PCCR0 on CPU%d\n", lcpu);
+		return -1;
+	}
 	scom_write(scom, SCOM_PCCR0, pccr0 | SCOM_PCCR0_ENABLE_DEBUG |
 				     SCOM_PCCR0_ENABLE_RAM);
 
diff --git a/arch/powerpc/platforms/wsp/scom_wsp.c b/arch/powerpc/platforms/wsp/scom_wsp.c
index 4052e22..8928507 100644
--- a/arch/powerpc/platforms/wsp/scom_wsp.c
+++ b/arch/powerpc/platforms/wsp/scom_wsp.c
@@ -50,18 +50,22 @@
 	iounmap((void *)map);
 }
 
-static u64 wsp_scom_read(scom_map_t map, u32 reg)
+static int wsp_scom_read(scom_map_t map, u64 reg, u64 *value)
 {
 	u64 __iomem *addr = (u64 __iomem *)map;
 
-	return in_be64(addr + reg);
+	*value = in_be64(addr + reg);
+
+	return 0;
 }
 
-static void wsp_scom_write(scom_map_t map, u32 reg, u64 value)
+static int wsp_scom_write(scom_map_t map, u64 reg, u64 value)
 {
 	u64 __iomem *addr = (u64 __iomem *)map;
 
-	return out_be64(addr + reg, value);
+	out_be64(addr + reg, value);
+
+	return 0;
 }
 
 static const struct scom_controller wsp_scom_controller = {
diff --git a/arch/powerpc/platforms/wsp/wsp.c b/arch/powerpc/platforms/wsp/wsp.c
index d25cc96..ddb6efe 100644
--- a/arch/powerpc/platforms/wsp/wsp.c
+++ b/arch/powerpc/platforms/wsp/wsp.c
@@ -89,6 +89,7 @@
 	struct device_node *dn;
 	struct device_node *mine;
 	struct device_node *me;
+	int rc;
 
 	me = of_get_cpu_node(smp_processor_id(), NULL);
 	mine = scom_find_parent(me);
@@ -101,15 +102,15 @@
 
 		/* read-modify-write it so the HW probe does not get
 		 * confused */
-		val = scom_read(m, 0);
-		val |= 1;
-		scom_write(m, 0, val);
+		rc = scom_read(m, 0, &val);
+		if (rc == 0)
+			scom_write(m, 0, val | 1);
 		scom_unmap(m);
 	}
 	m = scom_map(mine, 0, 1);
-	val = scom_read(m, 0);
-	val |= 1;
-	scom_write(m, 0, val);
+	rc = scom_read(m, 0, &val);
+	if (rc == 0)
+		scom_write(m, 0, val | 1);
 	/* should never return */
 	scom_unmap(m);
 }
diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig
index ab4cb54..13ec968 100644
--- a/arch/powerpc/sysdev/Kconfig
+++ b/arch/powerpc/sysdev/Kconfig
@@ -28,7 +28,7 @@
 
 config SCOM_DEBUGFS
 	bool "Expose SCOM controllers via debugfs"
-	depends on PPC_SCOM
+	depends on PPC_SCOM && DEBUG_FS
 	default n
 
 config GE_FPGA
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c
index 4dd5341..4f78695 100644
--- a/arch/powerpc/sysdev/cpm_common.c
+++ b/arch/powerpc/sysdev/cpm_common.c
@@ -22,6 +22,7 @@
 #include <linux/spinlock.h>
 #include <linux/export.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/slab.h>
 
 #include <asm/udbg.h>
diff --git a/arch/powerpc/sysdev/ehv_pic.c b/arch/powerpc/sysdev/ehv_pic.c
index 9cd0e60..b74085c 100644
--- a/arch/powerpc/sysdev/ehv_pic.c
+++ b/arch/powerpc/sysdev/ehv_pic.c
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
diff --git a/arch/powerpc/sysdev/fsl_gtm.c b/arch/powerpc/sysdev/fsl_gtm.c
index 0eb871c..06ac3c6 100644
--- a/arch/powerpc/sysdev/fsl_gtm.c
+++ b/arch/powerpc/sysdev/fsl_gtm.c
@@ -19,6 +19,8 @@
 #include <linux/list.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/spinlock.h>
 #include <linux/bitops.h>
 #include <linux/slab.h>
@@ -401,16 +403,15 @@
 		gtm->clock = *clock;
 
 		for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) {
-			int ret;
-			struct resource irq;
+			unsigned int irq;
 
-			ret = of_irq_to_resource(np, i, &irq);
-			if (ret == NO_IRQ) {
+			irq = irq_of_parse_and_map(np, i);
+			if (irq == NO_IRQ) {
 				pr_err("%s: not enough interrupts specified\n",
 				       np->full_name);
 				goto err;
 			}
-			gtm->timers[i].irq = irq.start;
+			gtm->timers[i].irq = irq;
 			gtm->timers[i].gtm = gtm;
 		}
 
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index ccfb50d..2103963 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -40,7 +40,7 @@
 
 static int fsl_pcie_bus_fixup, is_mpc83xx_pci;
 
-static void quirk_fsl_pcie_header(struct pci_dev *dev)
+static void quirk_fsl_pcie_early(struct pci_dev *dev)
 {
 	u8 hdr_type;
 
@@ -562,7 +562,8 @@
 }
 #endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */
 
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID,
+			quirk_fsl_pcie_early);
 
 #if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)
 struct mpc83xx_pcie_priv {
diff --git a/arch/powerpc/sysdev/fsl_pmc.c b/arch/powerpc/sysdev/fsl_pmc.c
index 592a0f8..8cf4aa0 100644
--- a/arch/powerpc/sysdev/fsl_pmc.c
+++ b/arch/powerpc/sysdev/fsl_pmc.c
@@ -18,6 +18,7 @@
 #include <linux/suspend.h>
 #include <linux/delay.h>
 #include <linux/device.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 
 struct pmc_regs {
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index e2fb317..95dd892 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -28,6 +28,8 @@
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
diff --git a/arch/powerpc/sysdev/fsl_rmu.c b/arch/powerpc/sysdev/fsl_rmu.c
index 14bd522..00e224a 100644
--- a/arch/powerpc/sysdev/fsl_rmu.c
+++ b/arch/powerpc/sysdev/fsl_rmu.c
@@ -27,6 +27,7 @@
 #include <linux/types.h>
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/slab.h>
 
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index c6d0073..4c5a19e 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -21,8 +21,6 @@
 
 extern void fsl_rstcr_restart(char *cmd);
 
-#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
-
 /* The different ports that the DIU can be connected to */
 enum fsl_diu_monitor_port {
 	FSL_DIU_PORT_DVI,	/* DVI */
@@ -43,7 +41,6 @@
 };
 
 extern struct platform_diu_data_ops diu_ops;
-#endif
 
 void fsl_hv_restart(char *cmd);
 void fsl_hv_halt(void);
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 1be54fa..0e166ed 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -535,7 +535,7 @@
 		mpic->fixups[irq].data = readl(base + 4) | 0x80000000;
 	}
 }
- 
+
 
 static void __init mpic_scan_ht_pics(struct mpic *mpic)
 {
@@ -1088,8 +1088,14 @@
 	 * is done here.
 	 */
 	if (!mpic_is_ipi(mpic, hw) && (mpic->flags & MPIC_NO_RESET)) {
+		int cpu;
+
+		preempt_disable();
+		cpu = mpic_processor_id(mpic);
+		preempt_enable();
+
 		mpic_set_vector(virq, hw);
-		mpic_set_destination(virq, mpic_processor_id(mpic));
+		mpic_set_destination(virq, cpu);
 		mpic_irq_set_priority(virq, 8);
 	}
 
@@ -1475,7 +1481,7 @@
 	 * as a default instead of the value read from the HW.
 	 */
 	last_irq = (greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
-				>> MPIC_GREG_FEATURE_LAST_SRC_SHIFT;	
+				>> MPIC_GREG_FEATURE_LAST_SRC_SHIFT;
 	if (isu_size)
 		last_irq = isu_size  * MPIC_MAX_ISU - 1;
 	of_property_read_u32(mpic->node, "last-interrupt-source", &last_irq);
@@ -1625,7 +1631,7 @@
 			/* start with vector = source number, and masked */
 			u32 vecpri = MPIC_VECPRI_MASK | i |
 				(8 << MPIC_VECPRI_PRIORITY_SHIFT);
-		
+
 			/* check if protected */
 			if (mpic->protected && test_bit(i, mpic->protected))
 				continue;
@@ -1634,7 +1640,7 @@
 			mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu);
 		}
 	}
-	
+
 	/* Init spurious vector */
 	mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), mpic->spurious_vec);
 
diff --git a/arch/powerpc/sysdev/mpic_msgr.c b/arch/powerpc/sysdev/mpic_msgr.c
index c753258..2c9b52a 100644
--- a/arch/powerpc/sysdev/mpic_msgr.c
+++ b/arch/powerpc/sysdev/mpic_msgr.c
@@ -237,15 +237,13 @@
 		raw_spin_lock_init(&msgr->lock);
 
 		if (receive_mask & (1 << i)) {
-			struct resource irq;
-
-			if (of_irq_to_resource(np, irq_index, &irq) == NO_IRQ) {
+			msgr->irq = irq_of_parse_and_map(np, irq_index);
+			if (msgr->irq == NO_IRQ) {
 				dev_err(&dev->dev,
 						"Missing interrupt specifier");
 				kfree(msgr);
 				return -EFAULT;
 			}
-			msgr->irq = irq.start;
 			irq_index += 1;
 		} else {
 			msgr->irq = NO_IRQ;
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
index bbf342c..7dc39f3 100644
--- a/arch/powerpc/sysdev/mpic_msi.c
+++ b/arch/powerpc/sysdev/mpic_msi.c
@@ -35,7 +35,7 @@
 	const struct irq_domain_ops *ops = mpic->irqhost->ops;
 	struct device_node *np;
 	int flags, index, i;
-	struct of_irq oirq;
+	struct of_phandle_args oirq;
 
 	pr_debug("mpic: found U3, guessing msi allocator setup\n");
 
@@ -63,9 +63,9 @@
 		pr_debug("mpic: mapping hwirqs for %s\n", np->full_name);
 
 		index = 0;
-		while (of_irq_map_one(np, index++, &oirq) == 0) {
-			ops->xlate(mpic->irqhost, NULL, oirq.specifier,
-						oirq.size, &hwirq, &flags);
+		while (of_irq_parse_one(np, index++, &oirq) == 0) {
+			ops->xlate(mpic->irqhost, NULL, oirq.args,
+						oirq.args_count, &hwirq, &flags);
 			msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, hwirq);
 		}
 	}
diff --git a/arch/powerpc/sysdev/mpic_timer.c b/arch/powerpc/sysdev/mpic_timer.c
index c06db92..22d7d57 100644
--- a/arch/powerpc/sysdev/mpic_timer.c
+++ b/arch/powerpc/sysdev/mpic_timer.c
@@ -19,7 +19,9 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/of_irq.h>
 #include <linux/syscore_ops.h>
 #include <sysdev/fsl_soc.h>
 #include <asm/io.h>
diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c
index 4a25c26..a3a8fad 100644
--- a/arch/powerpc/sysdev/mv64x60_dev.c
+++ b/arch/powerpc/sysdev/mv64x60_dev.c
@@ -228,7 +228,7 @@
 
 	if (id == 0) {
 		pdev = platform_device_register_simple("orion-mdio", -1, &r[1], 1);
-		if (!pdev)
+		if (IS_ERR(pdev))
 			return pdev;
 	}
 
diff --git a/arch/powerpc/sysdev/of_rtc.c b/arch/powerpc/sysdev/of_rtc.c
index c9e803f..6f54b54 100644
--- a/arch/powerpc/sysdev/of_rtc.c
+++ b/arch/powerpc/sysdev/of_rtc.c
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/init.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/slab.h>
 
diff --git a/arch/powerpc/sysdev/ppc4xx_ocm.c b/arch/powerpc/sysdev/ppc4xx_ocm.c
index 1b15f93..b7c4345 100644
--- a/arch/powerpc/sysdev/ppc4xx_ocm.c
+++ b/arch/powerpc/sysdev/ppc4xx_ocm.c
@@ -26,6 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/dma-mapping.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <asm/rheap.h>
 #include <asm/ppc4xx_ocm.h>
 #include <linux/slab.h>
diff --git a/arch/powerpc/sysdev/ppc4xx_soc.c b/arch/powerpc/sysdev/ppc4xx_soc.c
index 0debcc3..5c77c9b 100644
--- a/arch/powerpc/sysdev/ppc4xx_soc.c
+++ b/arch/powerpc/sysdev/ppc4xx_soc.c
@@ -19,6 +19,7 @@
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
 #include <asm/dcr.h>
diff --git a/arch/powerpc/sysdev/scom.c b/arch/powerpc/sysdev/scom.c
index 9193e12..6f5a8d1 100644
--- a/arch/powerpc/sysdev/scom.c
+++ b/arch/powerpc/sysdev/scom.c
@@ -25,6 +25,7 @@
 #include <asm/debug.h>
 #include <asm/prom.h>
 #include <asm/scom.h>
+#include <asm/uaccess.h>
 
 const struct scom_controller *scom_controller;
 EXPORT_SYMBOL_GPL(scom_controller);
@@ -53,7 +54,7 @@
 {
 	struct device_node *parent;
 	unsigned int cells, size;
-	const u32 *prop;
+	const __be32 *prop, *sprop;
 	u64 reg, cnt;
 	scom_map_t ret;
 
@@ -62,12 +63,24 @@
 	if (parent == NULL)
 		return 0;
 
-	prop = of_get_property(parent, "#scom-cells", NULL);
-	cells = prop ? *prop : 1;
-
+	/*
+	 * We support "scom-reg" properties for adding scom registers
+	 * to a random device-tree node with an explicit scom-parent
+	 *
+	 * We also support the simple "reg" property if the device is
+	 * a direct child of a scom controller.
+	 *
+	 * In case both exist, "scom-reg" takes precedence.
+	 */
 	prop = of_get_property(dev, "scom-reg", &size);
+	sprop = of_get_property(parent, "#scom-cells", NULL);
+	if (!prop && parent == dev->parent) {
+		prop = of_get_property(dev, "reg", &size);
+		sprop = of_get_property(parent, "#address-cells", NULL);
+	}
 	if (!prop)
-		return 0;
+		return NULL;
+	cells = sprop ? be32_to_cpup(sprop) : 1;
 	size >>= 2;
 
 	if (index >= (size / (2*cells)))
@@ -86,62 +99,89 @@
 #ifdef CONFIG_SCOM_DEBUGFS
 struct scom_debug_entry {
 	struct device_node *dn;
-	unsigned long addr;
-	scom_map_t map;
-	spinlock_t lock;
-	char name[8];
-	struct debugfs_blob_wrapper blob;
+	struct debugfs_blob_wrapper path;
+	char name[16];
 };
 
-static int scom_addr_set(void *data, u64 val)
+static ssize_t scom_debug_read(struct file *filp, char __user *ubuf,
+			       size_t count, loff_t *ppos)
 {
-	struct scom_debug_entry *ent = data;
+	struct scom_debug_entry *ent = filp->private_data;
+	u64 __user *ubuf64 = (u64 __user *)ubuf;
+	loff_t off = *ppos;
+	ssize_t done = 0; 
+	u64 reg, reg_cnt, val;
+	scom_map_t map;
+	int rc;
 
-	ent->addr = 0;
-	scom_unmap(ent->map);
+	if (off < 0 || (off & 7) || (count & 7))
+		return -EINVAL;
+	reg = off >> 3;
+	reg_cnt = count >> 3;
 
-	ent->map = scom_map(ent->dn, val, 1);
-	if (scom_map_ok(ent->map))
-		ent->addr = val;
-	else
-		return -EFAULT;
+	map = scom_map(ent->dn, reg, reg_cnt);
+	if (!scom_map_ok(map))
+		return -ENXIO;
 
-	return 0;
+	for (reg = 0; reg < reg_cnt; reg++) {
+		rc = scom_read(map, reg, &val);
+		if (!rc)
+			rc = put_user(val, ubuf64);
+		if (rc) {
+			if (!done)
+				done = rc;
+			break;
+		}
+		ubuf64++;
+		*ppos += 8;
+		done += 8;
+	}
+	scom_unmap(map);
+	return done;
 }
 
-static int scom_addr_get(void *data, u64 *val)
+static ssize_t scom_debug_write(struct file* filp, const char __user *ubuf,
+				size_t count, loff_t *ppos)
 {
-	struct scom_debug_entry *ent = data;
-	*val = ent->addr;
-	return 0;
-}
-DEFINE_SIMPLE_ATTRIBUTE(scom_addr_fops, scom_addr_get, scom_addr_set,
-			"0x%llx\n");
+	struct scom_debug_entry *ent = filp->private_data;
+	u64 __user *ubuf64 = (u64 __user *)ubuf;
+	loff_t off = *ppos;
+	ssize_t done = 0; 
+	u64 reg, reg_cnt, val;
+	scom_map_t map;
+	int rc;
 
-static int scom_val_set(void *data, u64 val)
-{
-	struct scom_debug_entry *ent = data;
+	if (off < 0 || (off & 7) || (count & 7))
+		return -EINVAL;
+	reg = off >> 3;
+	reg_cnt = count >> 3;
 
-	if (!scom_map_ok(ent->map))
-		return -EFAULT;
+	map = scom_map(ent->dn, reg, reg_cnt);
+	if (!scom_map_ok(map))
+		return -ENXIO;
 
-	scom_write(ent->map, 0, val);
-
-	return 0;
+	for (reg = 0; reg < reg_cnt; reg++) {
+		rc = get_user(val, ubuf64);
+		if (!rc)
+			rc = scom_write(map, reg,  val);
+		if (rc) {
+			if (!done)
+				done = rc;
+			break;
+		}
+		ubuf64++;
+		done += 8;
+	}
+	scom_unmap(map);
+	return done;
 }
 
-static int scom_val_get(void *data, u64 *val)
-{
-	struct scom_debug_entry *ent = data;
-
-	if (!scom_map_ok(ent->map))
-		return -EFAULT;
-
-	*val = scom_read(ent->map, 0);
-	return 0;
-}
-DEFINE_SIMPLE_ATTRIBUTE(scom_val_fops, scom_val_get, scom_val_set,
-			"0x%llx\n");
+static const struct file_operations scom_debug_fops = {
+	.read =		scom_debug_read,
+	.write =	scom_debug_write,
+	.open =		simple_open,
+	.llseek =	default_llseek,
+};
 
 static int scom_debug_init_one(struct dentry *root, struct device_node *dn,
 			       int i)
@@ -154,11 +194,9 @@
 		return -ENOMEM;
 
 	ent->dn = of_node_get(dn);
-	ent->map = SCOM_MAP_INVALID;
-	spin_lock_init(&ent->lock);
-	snprintf(ent->name, 8, "scom%d", i);
-	ent->blob.data = (void*) dn->full_name;
-	ent->blob.size = strlen(dn->full_name);
+	snprintf(ent->name, 16, "%08x", i);
+	ent->path.data = (void*) dn->full_name;
+	ent->path.size = strlen(dn->full_name);
 
 	dir = debugfs_create_dir(ent->name, root);
 	if (!dir) {
@@ -167,9 +205,8 @@
 		return -1;
 	}
 
-	debugfs_create_file("addr", 0600, dir, ent, &scom_addr_fops);
-	debugfs_create_file("value", 0600, dir, ent, &scom_val_fops);
-	debugfs_create_blob("path", 0400, dir, &ent->blob);
+	debugfs_create_blob("devspec", 0400, dir, &ent->path);
+	debugfs_create_file("access", 0600, dir, ent, &scom_debug_fops);
 
 	return 0;
 }
@@ -185,8 +222,13 @@
 		return -1;
 
 	i = rc = 0;
-	for_each_node_with_property(dn, "scom-controller")
-		rc |= scom_debug_init_one(root, dn, i++);
+	for_each_node_with_property(dn, "scom-controller") {
+		int id = of_get_ibm_chip_id(dn);
+		if (id == -1)
+			id = i;
+		rc |= scom_debug_init_one(root, dn, id);
+		i++;
+	}
 
 	return rc;
 }
diff --git a/arch/powerpc/sysdev/xics/ics-opal.c b/arch/powerpc/sysdev/xics/ics-opal.c
index 39d7221..3c6ee1b 100644
--- a/arch/powerpc/sysdev/xics/ics-opal.c
+++ b/arch/powerpc/sysdev/xics/ics-opal.c
@@ -112,6 +112,7 @@
 				 bool force)
 {
 	unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
+	__be16 oserver;
 	int16_t server;
 	int8_t priority;
 	int64_t rc;
@@ -120,13 +121,13 @@
 	if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
 		return -1;
 
-	rc = opal_get_xive(hw_irq, &server, &priority);
+	rc = opal_get_xive(hw_irq, &oserver, &priority);
 	if (rc != OPAL_SUCCESS) {
-		pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)"
-		       " error %lld\n",
-		       __func__, d->irq, hw_irq, server, rc);
+		pr_err("%s: opal_get_xive(irq=%d [hw 0x%x]) error %lld\n",
+		       __func__, d->irq, hw_irq, rc);
 		return -1;
 	}
+	server = be16_to_cpu(oserver);
 
 	wanted_server = xics_get_irq_server(d->irq, cpumask, 1);
 	if (wanted_server < 0) {
@@ -181,7 +182,7 @@
 {
 	unsigned int hw_irq = (unsigned int)virq_to_hw(virq);
 	int64_t rc;
-	int16_t server;
+	__be16 server;
 	int8_t priority;
 
 	if (WARN_ON(hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS))
@@ -201,7 +202,7 @@
 static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec)
 {
 	int64_t rc;
-	int16_t server;
+	__be16 server;
 	int8_t priority;
 
 	/* Check if HAL knows about this interrupt */
@@ -215,14 +216,14 @@
 static long ics_opal_get_server(struct ics *ics, unsigned long vec)
 {
 	int64_t rc;
-	int16_t server;
+	__be16 server;
 	int8_t priority;
 
 	/* Check if HAL knows about this interrupt */
 	rc = opal_get_xive(vec, &server, &priority);
 	if (rc != OPAL_SUCCESS)
 		return -1;
-	return ics_opal_unmangle_server(server);
+	return ics_opal_unmangle_server(be16_to_cpu(server));
 }
 
 int __init ics_opal_init(void)
diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c
index 8d73c3c..83f943a 100644
--- a/arch/powerpc/sysdev/xilinx_intc.c
+++ b/arch/powerpc/sysdev/xilinx_intc.c
@@ -23,6 +23,8 @@
 #include <linux/kernel.h>
 #include <linux/irq.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/i8259.h>
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 7143793..f75d7e5 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -99,6 +99,7 @@
 	select CLONE_BACKWARDS2
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_CPU_DEVICES if !SMP
+	select GENERIC_FIND_FIRST_BIT
 	select GENERIC_SMP_IDLE_THREAD
 	select GENERIC_TIME_VSYSCALL_OLD
 	select HAVE_ALIGNED_STRUCT_PAGE if SLUB
@@ -237,6 +238,67 @@
 
 endchoice
 
+config MARCH_G5_TUNE
+	def_bool TUNE_G5 || MARCH_G5 && TUNE_DEFAULT
+
+config MARCH_Z900_TUNE
+	def_bool TUNE_Z900 || MARCH_Z900 && TUNE_DEFAULT
+
+config MARCH_Z990_TUNE
+	def_bool TUNE_Z990 || MARCH_Z990 && TUNE_DEFAULT
+
+config MARCH_Z9_109_TUNE
+	def_bool TUNE_Z9_109 || MARCH_Z9_109 && TUNE_DEFAULT
+
+config MARCH_Z10_TUNE
+	def_bool TUNE_Z10 || MARCH_Z10 && TUNE_DEFAULT
+
+config MARCH_Z196_TUNE
+	def_bool TUNE_Z196 || MARCH_Z196 && TUNE_DEFAULT
+
+config MARCH_ZEC12_TUNE
+	def_bool TUNE_ZEC12 || MARCH_ZEC12 && TUNE_DEFAULT
+
+choice
+	prompt "Tune code generation"
+	default TUNE_DEFAULT
+	help
+	  Cause the compiler to tune (-mtune) the generated code for a machine.
+	  This will make the code run faster on the selected machine but
+	  somewhat slower on other machines.
+	  This option only changes how the compiler emits instructions, not the
+	  selection of instructions itself, so the resulting kernel will run on
+	  all other machines.
+
+config TUNE_DEFAULT
+	bool "Default"
+	help
+	  Tune the generated code for the target processor for which the kernel
+	  will be compiled.
+
+config TUNE_G5
+	bool "System/390 model G5 and G6"
+
+config TUNE_Z900
+	bool "IBM zSeries model z800 and z900"
+
+config TUNE_Z990
+	bool "IBM zSeries model z890 and z990"
+
+config TUNE_Z9_109
+	bool "IBM System z9"
+
+config TUNE_Z10
+	bool "IBM System z10"
+
+config TUNE_Z196
+	bool "IBM zEnterprise 114 and 196"
+
+config TUNE_ZEC12
+	bool "IBM zBC12 and zEC12"
+
+endchoice
+
 config 64BIT
 	def_bool y
 	prompt "64 bit kernel"
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index a7d68a4..874e6d6 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -35,13 +35,21 @@
 
 export LD_BFD
 
-cflags-$(CONFIG_MARCH_G5)   += $(call cc-option,-march=g5)
-cflags-$(CONFIG_MARCH_Z900) += $(call cc-option,-march=z900)
-cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990)
-cflags-$(CONFIG_MARCH_Z9_109) += $(call cc-option,-march=z9-109)
-cflags-$(CONFIG_MARCH_Z10) += $(call cc-option,-march=z10)
-cflags-$(CONFIG_MARCH_Z196) += $(call cc-option,-march=z196)
-cflags-$(CONFIG_MARCH_ZEC12) += $(call cc-option,-march=zEC12)
+cflags-$(CONFIG_MARCH_G5)     += -march=g5
+cflags-$(CONFIG_MARCH_Z900)   += -march=z900
+cflags-$(CONFIG_MARCH_Z990)   += -march=z990
+cflags-$(CONFIG_MARCH_Z9_109) += -march=z9-109
+cflags-$(CONFIG_MARCH_Z10)    += -march=z10
+cflags-$(CONFIG_MARCH_Z196)   += -march=z196
+cflags-$(CONFIG_MARCH_ZEC12)  += -march=zEC12
+
+cflags-$(CONFIG_MARCH_G5_TUNE)		+= -mtune=g5
+cflags-$(CONFIG_MARCH_Z900_TUNE)	+= -mtune=z900
+cflags-$(CONFIG_MARCH_Z990_TUNE)	+= -mtune=z990
+cflags-$(CONFIG_MARCH_Z9_109_TUNE)	+= -mtune=z9-109
+cflags-$(CONFIG_MARCH_Z10_TUNE)		+= -mtune=z10
+cflags-$(CONFIG_MARCH_Z196_TUNE)	+= -mtune=z196
+cflags-$(CONFIG_MARCH_ZEC12_TUNE)	+= -mtune=zEC12
 
 #KBUILD_IMAGE is necessary for make rpm
 KBUILD_IMAGE	:=arch/s390/boot/image
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index 87a2209..4c4a1ce 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -48,9 +48,9 @@
  * /proc entries (sysctl)
  */
 static const char appldata_proc_name[APPLDATA_PROC_NAME_LENGTH] = "appldata";
-static int appldata_timer_handler(ctl_table *ctl, int write,
+static int appldata_timer_handler(struct ctl_table *ctl, int write,
 				  void __user *buffer, size_t *lenp, loff_t *ppos);
-static int appldata_interval_handler(ctl_table *ctl, int write,
+static int appldata_interval_handler(struct ctl_table *ctl, int write,
 					 void __user *buffer,
 					 size_t *lenp, loff_t *ppos);
 
@@ -201,10 +201,10 @@
  * Start/Stop timer, show status of timer (0 = not active, 1 = active)
  */
 static int
-appldata_timer_handler(ctl_table *ctl, int write,
+appldata_timer_handler(struct ctl_table *ctl, int write,
 			   void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-	int len;
+	unsigned int len;
 	char buf[2];
 
 	if (!*lenp || *ppos) {
@@ -243,10 +243,11 @@
  * current timer interval.
  */
 static int
-appldata_interval_handler(ctl_table *ctl, int write,
+appldata_interval_handler(struct ctl_table *ctl, int write,
 			   void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-	int len, interval;
+	unsigned int len;
+	int interval;
 	char buf[16];
 
 	if (!*lenp || *ppos) {
@@ -286,11 +287,12 @@
  * monitoring (0 = not in process, 1 = in process)
  */
 static int
-appldata_generic_handler(ctl_table *ctl, int write,
+appldata_generic_handler(struct ctl_table *ctl, int write,
 			   void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	struct appldata_ops *ops = NULL, *tmp_ops;
-	int rc, len, found;
+	unsigned int len;
+	int rc, found;
 	char buf[2];
 	struct list_head *lh;
 
diff --git a/arch/s390/configs/default_defconfig b/arch/s390/configs/default_defconfig
new file mode 100644
index 0000000..e0af2ee
--- /dev/null
+++ b/arch/s390/configs/default_defconfig
@@ -0,0 +1,655 @@
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_PERF=y
+CONFIG_CFS_BANDWIDTH=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_CGROUP=y
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_BLK_DEV_THROTTLING=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_IBM_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_CFQ_GROUP_IOSCHED=y
+CONFIG_DEFAULT_DEADLINE=y
+CONFIG_MARCH_Z9_109=y
+CONFIG_PREEMPT=y
+CONFIG_HZ_100=y
+CONFIG_MEMORY_HOTPLUG=y
+CONFIG_MEMORY_HOTREMOVE=y
+CONFIG_KSM=y
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_PCI=y
+CONFIG_PCI_DEBUG=y
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_S390=y
+CONFIG_CHSC_SCH=y
+CONFIG_CRASH_DUMP=y
+CONFIG_ZFCPDUMP=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_HIBERNATION=y
+CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=m
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_UDP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_GRE=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMEOUT=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NF_CT_NETLINK_TIMEOUT=m
+CONFIG_NETFILTER_TPROXY=m
+CONFIG_NETFILTER_XT_SET=m
+CONFIG_NETFILTER_XT_TARGET_AUDIT=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CT=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_BPF=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_CPU=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_IPVS=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_SET=m
+CONFIG_IP_SET_BITMAP_IP=m
+CONFIG_IP_SET_BITMAP_IPMAC=m
+CONFIG_IP_SET_BITMAP_PORT=m
+CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPPORT=m
+CONFIG_IP_SET_HASH_IPPORTIP=m
+CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETPORT=m
+CONFIG_IP_SET_HASH_NETIFACE=m
+CONFIG_IP_SET_LIST_SET=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+CONFIG_IP_VS_FTP=m
+CONFIG_IP_VS_PE_SIP=m
+CONFIG_NF_CONNTRACK_IPV4=m
+# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT_IPV4=m
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_SECURITY=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_IP6_NF_SECURITY=m
+CONFIG_NF_NAT_IPV6=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NET_SCTPPROBE=m
+CONFIG_RDS=m
+CONFIG_RDS_RDMA=m
+CONFIG_RDS_TCP=m
+CONFIG_RDS_DEBUG=y
+CONFIG_L2TP=m
+CONFIG_L2TP_DEBUGFS=m
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=m
+CONFIG_L2TP_ETH=m
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFB=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+CONFIG_NET_SCH_MQPRIO=m
+CONFIG_NET_SCH_CHOKE=m
+CONFIG_NET_SCH_QFQ=m
+CONFIG_NET_SCH_CODEL=m
+CONFIG_NET_SCH_FQ_CODEL=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_SCH_PLUG=m
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+CONFIG_NET_CLS_CGROUP=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_ACT_SKBEDIT=m
+CONFIG_NET_ACT_CSUM=m
+CONFIG_DNS_RESOLVER=y
+CONFIG_BPF_JIT=y
+CONFIG_NET_PKTGEN=m
+CONFIG_NET_TCPPROBE=m
+CONFIG_DEVTMPFS=y
+CONFIG_CONNECTOR=y
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_OSD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_XIP=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_ATA_OVER_ETH=m
+CONFIG_VIRTIO_BLK=y
+CONFIG_ENCLOSURE_SERVICES=m
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=m
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_ENCLOSURE=m
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+CONFIG_SCSI_SRP_ATTRS=m
+CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_ISCSI_TCP=m
+CONFIG_LIBFCOE=m
+CONFIG_SCSI_DEBUG=m
+CONFIG_ZFCP=y
+CONFIG_SCSI_VIRTIO=m
+CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DH_HP_SW=m
+CONFIG_SCSI_DH_EMC=m
+CONFIG_SCSI_DH_ALUA=m
+CONFIG_SCSI_OSD_INITIATOR=m
+CONFIG_SCSI_OSD_ULD=m
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
+CONFIG_DM_LOG_USERSPACE=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_QL=m
+CONFIG_DM_MULTIPATH_ST=m
+CONFIG_DM_DELAY=m
+CONFIG_DM_UEVENT=y
+CONFIG_DM_FLAKEY=m
+CONFIG_DM_VERITY=m
+CONFIG_DM_SWITCH=m
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_DUMMY=m
+CONFIG_EQUALIZER=m
+CONFIG_IFB=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_VXLAN=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_VIRTIO_NET=m
+CONFIG_NLMON=m
+CONFIG_VHOST_NET=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+CONFIG_MLX4_EN=m
+# CONFIG_NET_VENDOR_NATSEMI is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
+CONFIG_LEGACY_PTY_COUNT=0
+CONFIG_HW_RANDOM_VIRTIO=m
+CONFIG_RAW_DRIVER=m
+CONFIG_HANGCHECK_TIMER=m
+CONFIG_TN3270_FS=y
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_ZVM_WATCHDOG=m
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_MLX4_INFINIBAND=m
+CONFIG_VIRTIO_BALLOON=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_JBD_DEBUG=y
+CONFIG_JBD2_DEBUG=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+CONFIG_JFS_STATISTICS=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+CONFIG_XFS_DEBUG=y
+CONFIG_GFS2_FS=m
+CONFIG_OCFS2_FS=m
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
+CONFIG_NILFS2_FS=m
+CONFIG_FANOTIFY=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V1=m
+CONFIG_QFMT_V2=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
+CONFIG_FSCACHE=m
+CONFIG_CACHEFILES=m
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_HUGETLBFS=y
+CONFIG_CONFIGFS_FS=m
+CONFIG_ECRYPT_FS=m
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_ROMFS_FS=m
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=m
+CONFIG_NFS_SWAP=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_V4_SECURITY_LABEL=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_UPCALL=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG is not set
+CONFIG_CIFS_DFS_UPCALL=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_UTF8=m
+CONFIG_DLM=m
+CONFIG_PRINTK_TIME=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+CONFIG_READABLE_ASM=y
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_SLUB_DEBUG_ON=y
+CONFIG_SLUB_STATS=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_VM=y
+CONFIG_DEBUG_VM_RB=y
+CONFIG_MEMORY_NOTIFIER_ERROR_INJECT=m
+CONFIG_DEBUG_PER_CPU_MAPS=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_RT_MUTEX_TESTER=y
+CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_LOCK_STAT=y
+CONFIG_DEBUG_LOCKDEP=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_DEBUG_LOCKING_API_SELFTESTS=y
+CONFIG_DEBUG_WRITECOUNT=y
+CONFIG_DEBUG_LIST=y
+CONFIG_DEBUG_SG=y
+CONFIG_DEBUG_NOTIFIERS=y
+CONFIG_DEBUG_CREDENTIALS=y
+CONFIG_PROVE_RCU=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_RCU_CPU_STALL_TIMEOUT=300
+CONFIG_NOTIFIER_ERROR_INJECTION=m
+CONFIG_CPU_NOTIFIER_ERROR_INJECT=m
+CONFIG_PM_NOTIFIER_ERROR_INJECT=m
+CONFIG_FAULT_INJECTION=y
+CONFIG_FAILSLAB=y
+CONFIG_FAIL_PAGE_ALLOC=y
+CONFIG_FAIL_MAKE_REQUEST=y
+CONFIG_FAIL_IO_TIMEOUT=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
+CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
+CONFIG_LATENCYTOP=y
+CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y
+CONFIG_BLK_DEV_IO_TRACE=y
+# CONFIG_KPROBE_EVENT is not set
+CONFIG_LKDTM=m
+CONFIG_KPROBES_SANITY_TEST=y
+CONFIG_RBTREE_TEST=m
+CONFIG_INTERVAL_TREE_TEST=m
+CONFIG_ATOMIC64_SELFTEST=y
+CONFIG_DMA_API_DEBUG=y
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_S390_PTDUMP=y
+CONFIG_ENCRYPTED_KEYS=m
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_IMA=y
+CONFIG_IMA_APPRAISE=y
+CONFIG_CRYPTO_USER=m
+# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_CRC32=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_ZLIB=y
+CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_ZCRYPT=m
+CONFIG_CRYPTO_SHA1_S390=m
+CONFIG_CRYPTO_SHA256_S390=m
+CONFIG_CRYPTO_SHA512_S390=m
+CONFIG_CRYPTO_DES_S390=m
+CONFIG_CRYPTO_AES_S390=m
+CONFIG_CRYPTO_GHASH_S390=m
+CONFIG_ASYMMETRIC_KEY_TYPE=m
+CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
+CONFIG_PUBLIC_KEY_ALGO_RSA=m
+CONFIG_X509_CERTIFICATE_PARSER=m
+CONFIG_CRC7=m
+CONFIG_CRC8=m
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_CORDIC=m
+CONFIG_CMM=m
+CONFIG_APPLDATA_BASE=y
+CONFIG_KVM=m
+CONFIG_KVM_S390_UCONTROL=y
diff --git a/arch/s390/configs/gcov_defconfig b/arch/s390/configs/gcov_defconfig
new file mode 100644
index 0000000..b9f6b4c
--- /dev/null
+++ b/arch/s390/configs/gcov_defconfig
@@ -0,0 +1,618 @@
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_PERF=y
+CONFIG_BLK_CGROUP=y
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+CONFIG_JUMP_LABEL=y
+CONFIG_GCOV_KERNEL=y
+CONFIG_GCOV_PROFILE_ALL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_BLK_DEV_THROTTLING=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_IBM_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_CFQ_GROUP_IOSCHED=y
+CONFIG_DEFAULT_DEADLINE=y
+CONFIG_MARCH_Z9_109=y
+CONFIG_HZ_100=y
+CONFIG_MEMORY_HOTPLUG=y
+CONFIG_MEMORY_HOTREMOVE=y
+CONFIG_KSM=y
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_PCI=y
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_S390=y
+CONFIG_CHSC_SCH=y
+CONFIG_CRASH_DUMP=y
+CONFIG_ZFCPDUMP=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_HIBERNATION=y
+CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=m
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_UDP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_GRE=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMEOUT=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NF_CT_NETLINK_TIMEOUT=m
+CONFIG_NETFILTER_TPROXY=m
+CONFIG_NETFILTER_XT_SET=m
+CONFIG_NETFILTER_XT_TARGET_AUDIT=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CT=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_BPF=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_CPU=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_IPVS=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_SET=m
+CONFIG_IP_SET_BITMAP_IP=m
+CONFIG_IP_SET_BITMAP_IPMAC=m
+CONFIG_IP_SET_BITMAP_PORT=m
+CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPPORT=m
+CONFIG_IP_SET_HASH_IPPORTIP=m
+CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETPORT=m
+CONFIG_IP_SET_HASH_NETIFACE=m
+CONFIG_IP_SET_LIST_SET=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+CONFIG_IP_VS_FTP=m
+CONFIG_IP_VS_PE_SIP=m
+CONFIG_NF_CONNTRACK_IPV4=m
+# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT_IPV4=m
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_SECURITY=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_IP6_NF_SECURITY=m
+CONFIG_NF_NAT_IPV6=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NET_SCTPPROBE=m
+CONFIG_RDS=m
+CONFIG_RDS_RDMA=m
+CONFIG_RDS_TCP=m
+CONFIG_L2TP=m
+CONFIG_L2TP_DEBUGFS=m
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=m
+CONFIG_L2TP_ETH=m
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFB=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+CONFIG_NET_SCH_MQPRIO=m
+CONFIG_NET_SCH_CHOKE=m
+CONFIG_NET_SCH_QFQ=m
+CONFIG_NET_SCH_CODEL=m
+CONFIG_NET_SCH_FQ_CODEL=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_SCH_PLUG=m
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+CONFIG_NET_CLS_CGROUP=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_ACT_SKBEDIT=m
+CONFIG_NET_ACT_CSUM=m
+CONFIG_DNS_RESOLVER=y
+CONFIG_BPF_JIT=y
+CONFIG_NET_PKTGEN=m
+CONFIG_NET_TCPPROBE=m
+CONFIG_DEVTMPFS=y
+CONFIG_CONNECTOR=y
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_OSD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_XIP=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_ATA_OVER_ETH=m
+CONFIG_VIRTIO_BLK=y
+CONFIG_ENCLOSURE_SERVICES=m
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=m
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_ENCLOSURE=m
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+CONFIG_SCSI_SRP_ATTRS=m
+CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_ISCSI_TCP=m
+CONFIG_LIBFCOE=m
+CONFIG_SCSI_DEBUG=m
+CONFIG_ZFCP=y
+CONFIG_SCSI_VIRTIO=m
+CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DH_HP_SW=m
+CONFIG_SCSI_DH_EMC=m
+CONFIG_SCSI_DH_ALUA=m
+CONFIG_SCSI_OSD_INITIATOR=m
+CONFIG_SCSI_OSD_ULD=m
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
+CONFIG_DM_LOG_USERSPACE=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_QL=m
+CONFIG_DM_MULTIPATH_ST=m
+CONFIG_DM_DELAY=m
+CONFIG_DM_UEVENT=y
+CONFIG_DM_FLAKEY=m
+CONFIG_DM_VERITY=m
+CONFIG_DM_SWITCH=m
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_DUMMY=m
+CONFIG_EQUALIZER=m
+CONFIG_IFB=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_VXLAN=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_VIRTIO_NET=m
+CONFIG_NLMON=m
+CONFIG_VHOST_NET=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+CONFIG_MLX4_EN=m
+# CONFIG_NET_VENDOR_NATSEMI is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
+CONFIG_LEGACY_PTY_COUNT=0
+CONFIG_HW_RANDOM_VIRTIO=m
+CONFIG_RAW_DRIVER=m
+CONFIG_HANGCHECK_TIMER=m
+CONFIG_TN3270_FS=y
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_ZVM_WATCHDOG=m
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_MLX4_INFINIBAND=m
+CONFIG_VIRTIO_BALLOON=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_JBD_DEBUG=y
+CONFIG_JBD2_DEBUG=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+CONFIG_JFS_STATISTICS=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+CONFIG_GFS2_FS=m
+CONFIG_OCFS2_FS=m
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
+CONFIG_NILFS2_FS=m
+CONFIG_FANOTIFY=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V1=m
+CONFIG_QFMT_V2=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
+CONFIG_FSCACHE=m
+CONFIG_CACHEFILES=m
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_HUGETLBFS=y
+CONFIG_CONFIGFS_FS=m
+CONFIG_ECRYPT_FS=m
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_ROMFS_FS=m
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=m
+CONFIG_NFS_SWAP=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_V4_SECURITY_LABEL=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_UPCALL=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG is not set
+CONFIG_CIFS_DFS_UPCALL=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_UTF8=m
+CONFIG_DLM=m
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MEMORY_NOTIFIER_ERROR_INJECT=m
+CONFIG_TIMER_STATS=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+CONFIG_NOTIFIER_ERROR_INJECTION=m
+CONFIG_CPU_NOTIFIER_ERROR_INJECT=m
+CONFIG_PM_NOTIFIER_ERROR_INJECT=m
+CONFIG_LATENCYTOP=y
+CONFIG_BLK_DEV_IO_TRACE=y
+# CONFIG_KPROBE_EVENT is not set
+CONFIG_LKDTM=m
+CONFIG_RBTREE_TEST=m
+CONFIG_INTERVAL_TREE_TEST=m
+CONFIG_ATOMIC64_SELFTEST=y
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_S390_PTDUMP=y
+CONFIG_ENCRYPTED_KEYS=m
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_IMA=y
+CONFIG_IMA_APPRAISE=y
+CONFIG_CRYPTO_USER=m
+# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_CRC32=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_ZLIB=y
+CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_ZCRYPT=m
+CONFIG_CRYPTO_SHA1_S390=m
+CONFIG_CRYPTO_SHA256_S390=m
+CONFIG_CRYPTO_SHA512_S390=m
+CONFIG_CRYPTO_DES_S390=m
+CONFIG_CRYPTO_AES_S390=m
+CONFIG_CRYPTO_GHASH_S390=m
+CONFIG_ASYMMETRIC_KEY_TYPE=m
+CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
+CONFIG_PUBLIC_KEY_ALGO_RSA=m
+CONFIG_X509_CERTIFICATE_PARSER=m
+CONFIG_CRC7=m
+CONFIG_CRC8=m
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_CORDIC=m
+CONFIG_CMM=m
+CONFIG_APPLDATA_BASE=y
+CONFIG_KVM=m
+CONFIG_KVM_S390_UCONTROL=y
diff --git a/arch/s390/configs/performance_defconfig b/arch/s390/configs/performance_defconfig
new file mode 100644
index 0000000..91087b4
--- /dev/null
+++ b/arch/s390/configs/performance_defconfig
@@ -0,0 +1,610 @@
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_PERF=y
+CONFIG_BLK_CGROUP=y
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_BLK_DEV_THROTTLING=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_IBM_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_CFQ_GROUP_IOSCHED=y
+CONFIG_DEFAULT_DEADLINE=y
+CONFIG_MARCH_Z9_109=y
+CONFIG_HZ_100=y
+CONFIG_MEMORY_HOTPLUG=y
+CONFIG_MEMORY_HOTREMOVE=y
+CONFIG_KSM=y
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_PCI=y
+CONFIG_HOTPLUG_PCI=y
+CONFIG_HOTPLUG_PCI_S390=y
+CONFIG_CHSC_SCH=y
+CONFIG_CRASH_DUMP=y
+CONFIG_ZFCPDUMP=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_HIBERNATION=y
+CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+CONFIG_NET_IPVTI=m
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_UDP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_GRE=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMEOUT=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NF_CT_NETLINK_TIMEOUT=m
+CONFIG_NETFILTER_TPROXY=m
+CONFIG_NETFILTER_XT_SET=m
+CONFIG_NETFILTER_XT_TARGET_AUDIT=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CT=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_BPF=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_CPU=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_IPVS=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_SET=m
+CONFIG_IP_SET_BITMAP_IP=m
+CONFIG_IP_SET_BITMAP_IPMAC=m
+CONFIG_IP_SET_BITMAP_PORT=m
+CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPPORT=m
+CONFIG_IP_SET_HASH_IPPORTIP=m
+CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETPORT=m
+CONFIG_IP_SET_HASH_NETIFACE=m
+CONFIG_IP_SET_LIST_SET=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+CONFIG_IP_VS_FTP=m
+CONFIG_IP_VS_PE_SIP=m
+CONFIG_NF_CONNTRACK_IPV4=m
+# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT_IPV4=m
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_SECURITY=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_IP6_NF_SECURITY=m
+CONFIG_NF_NAT_IPV6=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NET_SCTPPROBE=m
+CONFIG_RDS=m
+CONFIG_RDS_RDMA=m
+CONFIG_RDS_TCP=m
+CONFIG_L2TP=m
+CONFIG_L2TP_DEBUGFS=m
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=m
+CONFIG_L2TP_ETH=m
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFB=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+CONFIG_NET_SCH_MQPRIO=m
+CONFIG_NET_SCH_CHOKE=m
+CONFIG_NET_SCH_QFQ=m
+CONFIG_NET_SCH_CODEL=m
+CONFIG_NET_SCH_FQ_CODEL=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_SCH_PLUG=m
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+CONFIG_NET_CLS_CGROUP=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_ACT_SKBEDIT=m
+CONFIG_NET_ACT_CSUM=m
+CONFIG_DNS_RESOLVER=y
+CONFIG_BPF_JIT=y
+CONFIG_NET_PKTGEN=m
+CONFIG_NET_TCPPROBE=m
+CONFIG_DEVTMPFS=y
+CONFIG_CONNECTOR=y
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_OSD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_XIP=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_ATA_OVER_ETH=m
+CONFIG_VIRTIO_BLK=y
+CONFIG_ENCLOSURE_SERVICES=m
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=m
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_ENCLOSURE=m
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+CONFIG_SCSI_SRP_ATTRS=m
+CONFIG_SCSI_SRP_TGT_ATTRS=y
+CONFIG_ISCSI_TCP=m
+CONFIG_LIBFCOE=m
+CONFIG_SCSI_DEBUG=m
+CONFIG_ZFCP=y
+CONFIG_SCSI_VIRTIO=m
+CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DH_HP_SW=m
+CONFIG_SCSI_DH_EMC=m
+CONFIG_SCSI_DH_ALUA=m
+CONFIG_SCSI_OSD_INITIATOR=m
+CONFIG_SCSI_OSD_ULD=m
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_RAID=m
+CONFIG_DM_LOG_USERSPACE=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_QL=m
+CONFIG_DM_MULTIPATH_ST=m
+CONFIG_DM_DELAY=m
+CONFIG_DM_UEVENT=y
+CONFIG_DM_FLAKEY=m
+CONFIG_DM_VERITY=m
+CONFIG_DM_SWITCH=m
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_DUMMY=m
+CONFIG_EQUALIZER=m
+CONFIG_IFB=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_VXLAN=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_VIRTIO_NET=m
+CONFIG_NLMON=m
+CONFIG_VHOST_NET=m
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+CONFIG_MLX4_EN=m
+# CONFIG_NET_VENDOR_NATSEMI is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
+CONFIG_LEGACY_PTY_COUNT=0
+CONFIG_HW_RANDOM_VIRTIO=m
+CONFIG_RAW_DRIVER=m
+CONFIG_HANGCHECK_TIMER=m
+CONFIG_TN3270_FS=y
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_ZVM_WATCHDOG=m
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_MLX4_INFINIBAND=m
+CONFIG_VIRTIO_BALLOON=m
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_JBD_DEBUG=y
+CONFIG_JBD2_DEBUG=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+CONFIG_JFS_STATISTICS=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+CONFIG_GFS2_FS=m
+CONFIG_OCFS2_FS=m
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
+CONFIG_NILFS2_FS=m
+CONFIG_FANOTIFY=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V1=m
+CONFIG_QFMT_V2=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
+CONFIG_FSCACHE=m
+CONFIG_CACHEFILES=m
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_HUGETLBFS=y
+CONFIG_CONFIGFS_FS=m
+CONFIG_ECRYPT_FS=m
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_ROMFS_FS=m
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=m
+CONFIG_NFS_SWAP=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_V4_SECURITY_LABEL=y
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_UPCALL=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG is not set
+CONFIG_CIFS_DFS_UPCALL=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_UTF8=m
+CONFIG_DLM=m
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_TIMER_STATS=y
+CONFIG_RCU_TORTURE_TEST=m
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+CONFIG_LATENCYTOP=y
+CONFIG_BLK_DEV_IO_TRACE=y
+# CONFIG_KPROBE_EVENT is not set
+CONFIG_LKDTM=m
+CONFIG_ATOMIC64_SELFTEST=y
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_S390_PTDUMP=y
+CONFIG_ENCRYPTED_KEYS=m
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_IMA=y
+CONFIG_IMA_APPRAISE=y
+CONFIG_CRYPTO_USER=m
+# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_CRC32=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_ZLIB=y
+CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_ZCRYPT=m
+CONFIG_CRYPTO_SHA1_S390=m
+CONFIG_CRYPTO_SHA256_S390=m
+CONFIG_CRYPTO_SHA512_S390=m
+CONFIG_CRYPTO_DES_S390=m
+CONFIG_CRYPTO_AES_S390=m
+CONFIG_CRYPTO_GHASH_S390=m
+CONFIG_ASYMMETRIC_KEY_TYPE=m
+CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
+CONFIG_PUBLIC_KEY_ALGO_RSA=m
+CONFIG_X509_CERTIFICATE_PARSER=m
+CONFIG_CRC7=m
+CONFIG_CRC8=m
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_CORDIC=m
+CONFIG_CMM=m
+CONFIG_APPLDATA_BASE=y
+CONFIG_KVM=m
+CONFIG_KVM_S390_UCONTROL=y
diff --git a/arch/s390/configs/zfcpdump_defconfig b/arch/s390/configs/zfcpdump_defconfig
new file mode 100644
index 0000000..d725c4d
--- /dev/null
+++ b/arch/s390/configs/zfcpdump_defconfig
@@ -0,0 +1,86 @@
+# CONFIG_SWAP is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_IBM_PARTITION=y
+CONFIG_DEFAULT_DEADLINE=y
+CONFIG_MARCH_Z9_109=y
+# CONFIG_COMPAT is not set
+CONFIG_NR_CPUS=2
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_HZ_100=y
+# CONFIG_COMPACTION is not set
+# CONFIG_MIGRATION is not set
+# CONFIG_CHECK_STACK is not set
+# CONFIG_CHSC_SCH is not set
+# CONFIG_SCM_BUS is not set
+CONFIG_CRASH_DUMP=y
+CONFIG_ZFCPDUMP=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_IUCV is not set
+CONFIG_ATM=y
+CONFIG_ATM_LANE=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_BLK_DEV_XPRAM is not set
+# CONFIG_DCSSBLK is not set
+# CONFIG_DASD is not set
+CONFIG_ENCLOSURE_SERVICES=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_ENCLOSURE=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SRP_ATTRS=y
+CONFIG_ZFCP=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_HVC_IUCV is not set
+CONFIG_RAW_DRIVER=y
+# CONFIG_SCLP_ASYNC is not set
+# CONFIG_HMC_DRV is not set
+# CONFIG_S390_TAPE is not set
+# CONFIG_VMCP is not set
+# CONFIG_MONWRITER is not set
+# CONFIG_S390_VMUR is not set
+# CONFIG_HID is not set
+CONFIG_MEMSTICK=y
+CONFIG_MEMSTICK_DEBUG=y
+CONFIG_MEMSTICK_UNSAFE_RESUME=y
+CONFIG_MSPRO_BLOCK=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_INOTIFY_USER is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+# CONFIG_FTRACE is not set
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+# CONFIG_PFAULT is not set
+# CONFIG_S390_HYPFS_FS is not set
+# CONFIG_VIRTUALIZATION is not set
+# CONFIG_S390_GUEST is not set
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
index b4dbade..46cae13 100644
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -725,6 +725,8 @@
 	}
 };
 
+static int xts_aes_alg_reg;
+
 static int ctr_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
 			   unsigned int key_len)
 {
@@ -846,6 +848,8 @@
 	}
 };
 
+static int ctr_aes_alg_reg;
+
 static int __init aes_s390_init(void)
 {
 	int ret;
@@ -884,6 +888,7 @@
 		ret = crypto_register_alg(&xts_aes_alg);
 		if (ret)
 			goto xts_aes_err;
+		xts_aes_alg_reg = 1;
 	}
 
 	if (crypt_s390_func_available(KMCTR_AES_128_ENCRYPT,
@@ -902,6 +907,7 @@
 			free_page((unsigned long) ctrblk);
 			goto ctr_aes_err;
 		}
+		ctr_aes_alg_reg = 1;
 	}
 
 out:
@@ -921,9 +927,12 @@
 
 static void __exit aes_s390_fini(void)
 {
-	crypto_unregister_alg(&ctr_aes_alg);
-	free_page((unsigned long) ctrblk);
-	crypto_unregister_alg(&xts_aes_alg);
+	if (ctr_aes_alg_reg) {
+		crypto_unregister_alg(&ctr_aes_alg);
+		free_page((unsigned long) ctrblk);
+	}
+	if (xts_aes_alg_reg)
+		crypto_unregister_alg(&xts_aes_alg);
 	crypto_unregister_alg(&cbc_aes_alg);
 	crypto_unregister_alg(&ecb_aes_alg);
 	crypto_unregister_alg(&aes_alg);
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index d204c65..33f5751 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -38,13 +38,14 @@
 CONFIG_MODVERSIONS=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
-# CONFIG_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEADLINE=y
+CONFIG_MARCH_Z196=y
 CONFIG_HZ_100=y
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_KSM=y
 CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_CMA=y
 CONFIG_CRASH_DUMP=y
 CONFIG_BINFMT_MISC=m
 CONFIG_HIBERNATION=y
@@ -152,6 +153,7 @@
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
+CONFIG_CRYPTO_CRCT10DIF=m
 CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index f313f9c..7a5288f 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -2,3 +2,4 @@
 
 generic-y += clkdev.h
 generic-y += trace_clock.h
+generic-y += preempt.h
diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h
index c797832..fa9aaf7 100644
--- a/arch/s390/include/asm/atomic.h
+++ b/arch/s390/include/asm/atomic.h
@@ -19,21 +19,50 @@
 
 #define ATOMIC_INIT(i)  { (i) }
 
-#define __CS_LOOP(ptr, op_val, op_string) ({				\
+#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
+
+#define __ATOMIC_OR	"lao"
+#define __ATOMIC_AND	"lan"
+#define __ATOMIC_ADD	"laa"
+
+#define __ATOMIC_LOOP(ptr, op_val, op_string)				\
+({									\
+	int old_val;							\
+									\
+	typecheck(atomic_t *, ptr);					\
+	asm volatile(							\
+		op_string "	%0,%2,%1\n"				\
+		: "=d" (old_val), "+Q" ((ptr)->counter)			\
+		: "d" (op_val)						\
+		: "cc", "memory");					\
+	old_val;							\
+})
+
+#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */
+
+#define __ATOMIC_OR	"or"
+#define __ATOMIC_AND	"nr"
+#define __ATOMIC_ADD	"ar"
+
+#define __ATOMIC_LOOP(ptr, op_val, op_string)				\
+({									\
 	int old_val, new_val;						\
+									\
+	typecheck(atomic_t *, ptr);					\
 	asm volatile(							\
 		"	l	%0,%2\n"				\
 		"0:	lr	%1,%0\n"				\
 		op_string "	%1,%3\n"				\
 		"	cs	%0,%1,%2\n"				\
 		"	jl	0b"					\
-		: "=&d" (old_val), "=&d" (new_val),			\
-		  "=Q" (((atomic_t *)(ptr))->counter)			\
-		: "d" (op_val),	 "Q" (((atomic_t *)(ptr))->counter)	\
+		: "=&d" (old_val), "=&d" (new_val), "+Q" ((ptr)->counter)\
+		: "d" (op_val)						\
 		: "cc", "memory");					\
-	new_val;							\
+	old_val;							\
 })
 
+#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */
+
 static inline int atomic_read(const atomic_t *v)
 {
 	int c;
@@ -53,32 +82,45 @@
 
 static inline int atomic_add_return(int i, atomic_t *v)
 {
-	return __CS_LOOP(v, i, "ar");
+	return __ATOMIC_LOOP(v, i, __ATOMIC_ADD) + i;
 }
-#define atomic_add(_i, _v)		atomic_add_return(_i, _v)
+
+static inline void atomic_add(int i, atomic_t *v)
+{
+#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
+	if (__builtin_constant_p(i) && (i > -129) && (i < 128)) {
+		asm volatile(
+			"asi	%0,%1\n"
+			: "+Q" (v->counter)
+			: "i" (i)
+			: "cc", "memory");
+	} else {
+		atomic_add_return(i, v);
+	}
+#else
+	atomic_add_return(i, v);
+#endif
+}
+
 #define atomic_add_negative(_i, _v)	(atomic_add_return(_i, _v) < 0)
-#define atomic_inc(_v)			atomic_add_return(1, _v)
+#define atomic_inc(_v)			atomic_add(1, _v)
 #define atomic_inc_return(_v)		atomic_add_return(1, _v)
 #define atomic_inc_and_test(_v)		(atomic_add_return(1, _v) == 0)
-
-static inline int atomic_sub_return(int i, atomic_t *v)
-{
-	return __CS_LOOP(v, i, "sr");
-}
-#define atomic_sub(_i, _v)		atomic_sub_return(_i, _v)
+#define atomic_sub(_i, _v)		atomic_add(-(int)(_i), _v)
+#define atomic_sub_return(_i, _v)	atomic_add_return(-(int)(_i), _v)
 #define atomic_sub_and_test(_i, _v)	(atomic_sub_return(_i, _v) == 0)
-#define atomic_dec(_v)			atomic_sub_return(1, _v)
+#define atomic_dec(_v)			atomic_sub(1, _v)
 #define atomic_dec_return(_v)		atomic_sub_return(1, _v)
 #define atomic_dec_and_test(_v)		(atomic_sub_return(1, _v) == 0)
 
-static inline void atomic_clear_mask(unsigned long mask, atomic_t *v)
+static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
 {
-	__CS_LOOP(v, ~mask, "nr");
+	__ATOMIC_LOOP(v, ~mask, __ATOMIC_AND);
 }
 
-static inline void atomic_set_mask(unsigned long mask, atomic_t *v)
+static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
 {
-	__CS_LOOP(v, mask, "or");
+	__ATOMIC_LOOP(v, mask, __ATOMIC_OR);
 }
 
 #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
@@ -87,8 +129,8 @@
 {
 	asm volatile(
 		"	cs	%0,%2,%1"
-		: "+d" (old), "=Q" (v->counter)
-		: "d" (new), "Q" (v->counter)
+		: "+d" (old), "+Q" (v->counter)
+		: "d" (new)
 		: "cc", "memory");
 	return old;
 }
@@ -109,27 +151,56 @@
 }
 
 
-#undef __CS_LOOP
+#undef __ATOMIC_LOOP
 
 #define ATOMIC64_INIT(i)  { (i) }
 
 #ifdef CONFIG_64BIT
 
-#define __CSG_LOOP(ptr, op_val, op_string) ({				\
+#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
+
+#define __ATOMIC64_OR	"laog"
+#define __ATOMIC64_AND	"lang"
+#define __ATOMIC64_ADD	"laag"
+
+#define __ATOMIC64_LOOP(ptr, op_val, op_string)				\
+({									\
+	long long old_val;						\
+									\
+	typecheck(atomic64_t *, ptr);					\
+	asm volatile(							\
+		op_string "	%0,%2,%1\n"				\
+		: "=d" (old_val), "+Q" ((ptr)->counter)			\
+		: "d" (op_val)						\
+		: "cc", "memory");					\
+	old_val;							\
+})
+
+#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */
+
+#define __ATOMIC64_OR	"ogr"
+#define __ATOMIC64_AND	"ngr"
+#define __ATOMIC64_ADD	"agr"
+
+#define __ATOMIC64_LOOP(ptr, op_val, op_string)				\
+({									\
 	long long old_val, new_val;					\
+									\
+	typecheck(atomic64_t *, ptr);					\
 	asm volatile(							\
 		"	lg	%0,%2\n"				\
 		"0:	lgr	%1,%0\n"				\
 		op_string "	%1,%3\n"				\
 		"	csg	%0,%1,%2\n"				\
 		"	jl	0b"					\
-		: "=&d" (old_val), "=&d" (new_val),			\
-		  "=Q" (((atomic_t *)(ptr))->counter)			\
-		: "d" (op_val),	"Q" (((atomic_t *)(ptr))->counter)	\
+		: "=&d" (old_val), "=&d" (new_val), "+Q" ((ptr)->counter)\
+		: "d" (op_val)						\
 		: "cc", "memory");					\
-	new_val;							\
+	old_val;							\
 })
 
+#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */
+
 static inline long long atomic64_read(const atomic64_t *v)
 {
 	long long c;
@@ -149,22 +220,17 @@
 
 static inline long long atomic64_add_return(long long i, atomic64_t *v)
 {
-	return __CSG_LOOP(v, i, "agr");
-}
-
-static inline long long atomic64_sub_return(long long i, atomic64_t *v)
-{
-	return __CSG_LOOP(v, i, "sgr");
+	return __ATOMIC64_LOOP(v, i, __ATOMIC64_ADD) + i;
 }
 
 static inline void atomic64_clear_mask(unsigned long mask, atomic64_t *v)
 {
-	__CSG_LOOP(v, ~mask, "ngr");
+	__ATOMIC64_LOOP(v, ~mask, __ATOMIC64_AND);
 }
 
 static inline void atomic64_set_mask(unsigned long mask, atomic64_t *v)
 {
-	__CSG_LOOP(v, mask, "ogr");
+	__ATOMIC64_LOOP(v, mask, __ATOMIC64_OR);
 }
 
 #define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
@@ -174,13 +240,13 @@
 {
 	asm volatile(
 		"	csg	%0,%2,%1"
-		: "+d" (old), "=Q" (v->counter)
-		: "d" (new), "Q" (v->counter)
+		: "+d" (old), "+Q" (v->counter)
+		: "d" (new)
 		: "cc", "memory");
 	return old;
 }
 
-#undef __CSG_LOOP
+#undef __ATOMIC64_LOOP
 
 #else /* CONFIG_64BIT */
 
@@ -216,8 +282,8 @@
 		"	lm	%0,%N0,%1\n"
 		"0:	cds	%0,%2,%1\n"
 		"	jl	0b\n"
-		: "=&d" (rp_old), "=Q" (v->counter)
-		: "d" (rp_new), "Q" (v->counter)
+		: "=&d" (rp_old), "+Q" (v->counter)
+		: "d" (rp_new)
 		: "cc");
 	return rp_old.pair;
 }
@@ -230,8 +296,8 @@
 
 	asm volatile(
 		"	cds	%0,%2,%1"
-		: "+&d" (rp_old), "=Q" (v->counter)
-		: "d" (rp_new), "Q" (v->counter)
+		: "+&d" (rp_old), "+Q" (v->counter)
+		: "d" (rp_new)
 		: "cc");
 	return rp_old.pair;
 }
@@ -248,17 +314,6 @@
 	return new;
 }
 
-static inline long long atomic64_sub_return(long long i, atomic64_t *v)
-{
-	long long old, new;
-
-	do {
-		old = atomic64_read(v);
-		new = old - i;
-	} while (atomic64_cmpxchg(v, old, new) != old);
-	return new;
-}
-
 static inline void atomic64_set_mask(unsigned long long mask, atomic64_t *v)
 {
 	long long old, new;
@@ -281,7 +336,24 @@
 
 #endif /* CONFIG_64BIT */
 
-static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u)
+static inline void atomic64_add(long long i, atomic64_t *v)
+{
+#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
+	if (__builtin_constant_p(i) && (i > -129) && (i < 128)) {
+		asm volatile(
+			"agsi	%0,%1\n"
+			: "+Q" (v->counter)
+			: "i" (i)
+			: "cc", "memory");
+	} else {
+		atomic64_add_return(i, v);
+	}
+#else
+	atomic64_add_return(i, v);
+#endif
+}
+
+static inline int atomic64_add_unless(atomic64_t *v, long long i, long long u)
 {
 	long long c, old;
 
@@ -289,7 +361,7 @@
 	for (;;) {
 		if (unlikely(c == u))
 			break;
-		old = atomic64_cmpxchg(v, c, c + a);
+		old = atomic64_cmpxchg(v, c, c + i);
 		if (likely(old == c))
 			break;
 		c = old;
@@ -314,14 +386,14 @@
 	return dec;
 }
 
-#define atomic64_add(_i, _v)		atomic64_add_return(_i, _v)
 #define atomic64_add_negative(_i, _v)	(atomic64_add_return(_i, _v) < 0)
-#define atomic64_inc(_v)		atomic64_add_return(1, _v)
+#define atomic64_inc(_v)		atomic64_add(1, _v)
 #define atomic64_inc_return(_v)		atomic64_add_return(1, _v)
 #define atomic64_inc_and_test(_v)	(atomic64_add_return(1, _v) == 0)
-#define atomic64_sub(_i, _v)		atomic64_sub_return(_i, _v)
+#define atomic64_sub_return(_i, _v)	atomic64_add_return(-(long long)(_i), _v)
+#define atomic64_sub(_i, _v)		atomic64_add(-(long long)(_i), _v)
 #define atomic64_sub_and_test(_i, _v)	(atomic64_sub_return(_i, _v) == 0)
-#define atomic64_dec(_v)		atomic64_sub_return(1, _v)
+#define atomic64_dec(_v)		atomic64_sub(1, _v)
 #define atomic64_dec_return(_v)		atomic64_sub_return(1, _v)
 #define atomic64_dec_and_test(_v)	(atomic64_sub_return(1, _v) == 0)
 #define atomic64_inc_not_zero(v)	atomic64_add_unless((v), 1, 0)
diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h
index 10135a3..6e6ad06 100644
--- a/arch/s390/include/asm/bitops.h
+++ b/arch/s390/include/asm/bitops.h
@@ -1,10 +1,40 @@
 /*
- *  S390 version
- *    Copyright IBM Corp. 1999
- *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *    Copyright IBM Corp. 1999,2013
  *
- *  Derived from "include/asm-i386/bitops.h"
- *    Copyright (C) 1992, Linus Torvalds
+ *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
+ *
+ * The description below was taken in large parts from the powerpc
+ * bitops header file:
+ * Within a word, bits are numbered LSB first.  Lot's of places make
+ * this assumption by directly testing bits with (val & (1<<nr)).
+ * This can cause confusion for large (> 1 word) bitmaps on a
+ * big-endian system because, unlike little endian, the number of each
+ * bit depends on the word size.
+ *
+ * The bitop functions are defined to work on unsigned longs, so for an
+ * s390x system the bits end up numbered:
+ *   |63..............0|127............64|191...........128|255...........196|
+ * and on s390:
+ *   |31.....0|63....31|95....64|127...96|159..128|191..160|223..192|255..224|
+ *
+ * There are a few little-endian macros used mostly for filesystem
+ * bitmaps, these work on similar bit arrays layouts, but
+ * byte-oriented:
+ *   |7...0|15...8|23...16|31...24|39...32|47...40|55...48|63...56|
+ *
+ * The main difference is that bit 3-5 (64b) or 3-4 (32b) in the bit
+ * number field needs to be reversed compared to the big-endian bit
+ * fields. This can be achieved by XOR with 0x38 (64b) or 0x18 (32b).
+ *
+ * We also have special functions which work with an MSB0 encoding:
+ * on an s390x system the bits are numbered:
+ *   |0..............63|64............127|128...........191|192...........255|
+ * and on s390:
+ *   |0.....31|31....63|64....95|96...127|128..159|160..191|192..223|224..255|
+ *
+ * The main difference is that bit 0-63 (64b) or 0-31 (32b) in the bit
+ * number field needs to be reversed compared to the LSB0 encoded bit
+ * fields. This can be achieved by XOR with 0x3f (64b) or 0x1f (32b).
  *
  */
 
@@ -15,556 +45,348 @@
 #error only <linux/bitops.h> can be included directly
 #endif
 
+#include <linux/typecheck.h>
 #include <linux/compiler.h>
 
-/*
- * 32 bit bitops format:
- * bit 0 is the LSB of *addr; bit 31 is the MSB of *addr;
- * bit 32 is the LSB of *(addr+4). That combined with the
- * big endian byte order on S390 give the following bit
- * order in memory:
- *    1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10 \
- *    0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
- * after that follows the next long with bit numbers
- *    3f 3e 3d 3c 3b 3a 39 38 37 36 35 34 33 32 31 30
- *    2f 2e 2d 2c 2b 2a 29 28 27 26 25 24 23 22 21 20
- * The reason for this bit ordering is the fact that
- * in the architecture independent code bits operations
- * of the form "flags |= (1 << bitnr)" are used INTERMIXED
- * with operation of the form "set_bit(bitnr, flags)".
- *
- * 64 bit bitops format:
- * bit 0 is the LSB of *addr; bit 63 is the MSB of *addr;
- * bit 64 is the LSB of *(addr+8). That combined with the
- * big endian byte order on S390 give the following bit
- * order in memory:
- *    3f 3e 3d 3c 3b 3a 39 38 37 36 35 34 33 32 31 30
- *    2f 2e 2d 2c 2b 2a 29 28 27 26 25 24 23 22 21 20
- *    1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10
- *    0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
- * after that follows the next long with bit numbers
- *    7f 7e 7d 7c 7b 7a 79 78 77 76 75 74 73 72 71 70
- *    6f 6e 6d 6c 6b 6a 69 68 67 66 65 64 63 62 61 60
- *    5f 5e 5d 5c 5b 5a 59 58 57 56 55 54 53 52 51 50
- *    4f 4e 4d 4c 4b 4a 49 48 47 46 45 44 43 42 41 40
- * The reason for this bit ordering is the fact that
- * in the architecture independent code bits operations
- * of the form "flags |= (1 << bitnr)" are used INTERMIXED
- * with operation of the form "set_bit(bitnr, flags)".
- */
-
-/* bitmap tables from arch/s390/kernel/bitmap.c */
-extern const char _oi_bitmap[];
-extern const char _ni_bitmap[];
-extern const char _zb_findmap[];
-extern const char _sb_findmap[];
-
 #ifndef CONFIG_64BIT
 
 #define __BITOPS_OR		"or"
 #define __BITOPS_AND		"nr"
 #define __BITOPS_XOR		"xr"
 
-#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string)	\
+#define __BITOPS_LOOP(__addr, __val, __op_string)		\
+({								\
+	unsigned long __old, __new;				\
+								\
+	typecheck(unsigned long *, (__addr));			\
 	asm volatile(						\
 		"	l	%0,%2\n"			\
 		"0:	lr	%1,%0\n"			\
 		__op_string "	%1,%3\n"			\
 		"	cs	%0,%1,%2\n"			\
 		"	jl	0b"				\
-		: "=&d" (__old), "=&d" (__new),			\
-		  "=Q" (*(unsigned long *) __addr)		\
-		: "d" (__val), "Q" (*(unsigned long *) __addr)	\
-		: "cc");
+		: "=&d" (__old), "=&d" (__new), "+Q" (*(__addr))\
+		: "d" (__val)					\
+		: "cc");					\
+	__old;							\
+})
 
 #else /* CONFIG_64BIT */
 
+#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
+
+#define __BITOPS_OR		"laog"
+#define __BITOPS_AND		"lang"
+#define __BITOPS_XOR		"laxg"
+
+#define __BITOPS_LOOP(__addr, __val, __op_string)		\
+({								\
+	unsigned long __old;					\
+								\
+	typecheck(unsigned long *, (__addr));			\
+	asm volatile(						\
+		__op_string "	%0,%2,%1\n"			\
+		: "=d" (__old),	"+Q" (*(__addr))		\
+		: "d" (__val)					\
+		: "cc");					\
+	__old;							\
+})
+
+#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */
+
 #define __BITOPS_OR		"ogr"
 #define __BITOPS_AND		"ngr"
 #define __BITOPS_XOR		"xgr"
 
-#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string)	\
+#define __BITOPS_LOOP(__addr, __val, __op_string)		\
+({								\
+	unsigned long __old, __new;				\
+								\
+	typecheck(unsigned long *, (__addr));			\
 	asm volatile(						\
 		"	lg	%0,%2\n"			\
 		"0:	lgr	%1,%0\n"			\
 		__op_string "	%1,%3\n"			\
 		"	csg	%0,%1,%2\n"			\
 		"	jl	0b"				\
-		: "=&d" (__old), "=&d" (__new),			\
-		  "=Q" (*(unsigned long *) __addr)		\
-		: "d" (__val), "Q" (*(unsigned long *) __addr)	\
-		: "cc");
+		: "=&d" (__old), "=&d" (__new), "+Q" (*(__addr))\
+		: "d" (__val)					\
+		: "cc");					\
+	__old;							\
+})
+
+#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */
 
 #endif /* CONFIG_64BIT */
 
 #define __BITOPS_WORDS(bits) (((bits) + BITS_PER_LONG - 1) / BITS_PER_LONG)
 
-#ifdef CONFIG_SMP
-/*
- * SMP safe set_bit routine based on compare and swap (CS)
- */
-static inline void set_bit_cs(unsigned long nr, volatile unsigned long *ptr)
+static inline unsigned long *
+__bitops_word(unsigned long nr, volatile unsigned long *ptr)
 {
-        unsigned long addr, old, new, mask;
+	unsigned long addr;
 
-	addr = (unsigned long) ptr;
-	/* calculate address for CS */
-	addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
-	/* make OR mask */
-	mask = 1UL << (nr & (BITS_PER_LONG - 1));
-	/* Do the atomic update. */
-	__BITOPS_LOOP(old, new, addr, mask, __BITOPS_OR);
+	addr = (unsigned long)ptr + ((nr ^ (nr & (BITS_PER_LONG - 1))) >> 3);
+	return (unsigned long *)addr;
 }
 
-/*
- * SMP safe clear_bit routine based on compare and swap (CS)
- */
-static inline void clear_bit_cs(unsigned long nr, volatile unsigned long *ptr)
+static inline unsigned char *
+__bitops_byte(unsigned long nr, volatile unsigned long *ptr)
 {
-        unsigned long addr, old, new, mask;
+	return ((unsigned char *)ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
+}
 
-	addr = (unsigned long) ptr;
-	/* calculate address for CS */
-	addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
-	/* make AND mask */
+static inline void set_bit(unsigned long nr, volatile unsigned long *ptr)
+{
+	unsigned long *addr = __bitops_word(nr, ptr);
+	unsigned long mask;
+
+#ifdef CONFIG_HAVE_MARCH_ZEC12_FEATURES
+	if (__builtin_constant_p(nr)) {
+		unsigned char *caddr = __bitops_byte(nr, ptr);
+
+		asm volatile(
+			"oi	%0,%b1\n"
+			: "+Q" (*caddr)
+			: "i" (1 << (nr & 7))
+			: "cc");
+		return;
+	}
+#endif
+	mask = 1UL << (nr & (BITS_PER_LONG - 1));
+	__BITOPS_LOOP(addr, mask, __BITOPS_OR);
+}
+
+static inline void clear_bit(unsigned long nr, volatile unsigned long *ptr)
+{
+	unsigned long *addr = __bitops_word(nr, ptr);
+	unsigned long mask;
+
+#ifdef CONFIG_HAVE_MARCH_ZEC12_FEATURES
+	if (__builtin_constant_p(nr)) {
+		unsigned char *caddr = __bitops_byte(nr, ptr);
+
+		asm volatile(
+			"ni	%0,%b1\n"
+			: "+Q" (*caddr)
+			: "i" (~(1 << (nr & 7)))
+			: "cc");
+		return;
+	}
+#endif
 	mask = ~(1UL << (nr & (BITS_PER_LONG - 1)));
-	/* Do the atomic update. */
-	__BITOPS_LOOP(old, new, addr, mask, __BITOPS_AND);
+	__BITOPS_LOOP(addr, mask, __BITOPS_AND);
 }
 
-/*
- * SMP safe change_bit routine based on compare and swap (CS)
- */
-static inline void change_bit_cs(unsigned long nr, volatile unsigned long *ptr)
+static inline void change_bit(unsigned long nr, volatile unsigned long *ptr)
 {
-        unsigned long addr, old, new, mask;
+	unsigned long *addr = __bitops_word(nr, ptr);
+	unsigned long mask;
 
-	addr = (unsigned long) ptr;
-	/* calculate address for CS */
-	addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
-	/* make XOR mask */
+#ifdef CONFIG_HAVE_MARCH_ZEC12_FEATURES
+	if (__builtin_constant_p(nr)) {
+		unsigned char *caddr = __bitops_byte(nr, ptr);
+
+		asm volatile(
+			"xi	%0,%b1\n"
+			: "+Q" (*caddr)
+			: "i" (1 << (nr & 7))
+			: "cc");
+		return;
+	}
+#endif
 	mask = 1UL << (nr & (BITS_PER_LONG - 1));
-	/* Do the atomic update. */
-	__BITOPS_LOOP(old, new, addr, mask, __BITOPS_XOR);
+	__BITOPS_LOOP(addr, mask, __BITOPS_XOR);
 }
 
-/*
- * SMP safe test_and_set_bit routine based on compare and swap (CS)
- */
 static inline int
-test_and_set_bit_cs(unsigned long nr, volatile unsigned long *ptr)
+test_and_set_bit(unsigned long nr, volatile unsigned long *ptr)
 {
-        unsigned long addr, old, new, mask;
+	unsigned long *addr = __bitops_word(nr, ptr);
+	unsigned long old, mask;
 
-	addr = (unsigned long) ptr;
-	/* calculate address for CS */
-	addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
-	/* make OR/test mask */
 	mask = 1UL << (nr & (BITS_PER_LONG - 1));
-	/* Do the atomic update. */
-	__BITOPS_LOOP(old, new, addr, mask, __BITOPS_OR);
+	old = __BITOPS_LOOP(addr, mask, __BITOPS_OR);
 	barrier();
 	return (old & mask) != 0;
 }
 
-/*
- * SMP safe test_and_clear_bit routine based on compare and swap (CS)
- */
 static inline int
-test_and_clear_bit_cs(unsigned long nr, volatile unsigned long *ptr)
+test_and_clear_bit(unsigned long nr, volatile unsigned long *ptr)
 {
-        unsigned long addr, old, new, mask;
+	unsigned long *addr = __bitops_word(nr, ptr);
+	unsigned long old, mask;
 
-	addr = (unsigned long) ptr;
-	/* calculate address for CS */
-	addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
-	/* make AND/test mask */
 	mask = ~(1UL << (nr & (BITS_PER_LONG - 1)));
-	/* Do the atomic update. */
-	__BITOPS_LOOP(old, new, addr, mask, __BITOPS_AND);
+	old = __BITOPS_LOOP(addr, mask, __BITOPS_AND);
 	barrier();
-	return (old ^ new) != 0;
+	return (old & ~mask) != 0;
 }
 
-/*
- * SMP safe test_and_change_bit routine based on compare and swap (CS) 
- */
 static inline int
-test_and_change_bit_cs(unsigned long nr, volatile unsigned long *ptr)
+test_and_change_bit(unsigned long nr, volatile unsigned long *ptr)
 {
-        unsigned long addr, old, new, mask;
+	unsigned long *addr = __bitops_word(nr, ptr);
+	unsigned long old, mask;
 
-	addr = (unsigned long) ptr;
-	/* calculate address for CS */
-	addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
-	/* make XOR/test mask */
 	mask = 1UL << (nr & (BITS_PER_LONG - 1));
-	/* Do the atomic update. */
-	__BITOPS_LOOP(old, new, addr, mask, __BITOPS_XOR);
+	old = __BITOPS_LOOP(addr, mask, __BITOPS_XOR);
 	barrier();
 	return (old & mask) != 0;
 }
-#endif /* CONFIG_SMP */
 
-/*
- * fast, non-SMP set_bit routine
- */
 static inline void __set_bit(unsigned long nr, volatile unsigned long *ptr)
 {
-	unsigned long addr;
+	unsigned char *addr = __bitops_byte(nr, ptr);
 
-	addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
-	asm volatile(
-		"	oc	%O0(1,%R0),%1"
-		: "+Q" (*(char *) addr) : "Q" (_oi_bitmap[nr & 7]) : "cc");
+	*addr |= 1 << (nr & 7);
 }
 
 static inline void 
-__constant_set_bit(const unsigned long nr, volatile unsigned long *ptr)
-{
-	unsigned long addr;
-
-	addr = ((unsigned long) ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
-	*(unsigned char *) addr |= 1 << (nr & 7);
-}
-
-#define set_bit_simple(nr,addr) \
-(__builtin_constant_p((nr)) ? \
- __constant_set_bit((nr),(addr)) : \
- __set_bit((nr),(addr)) )
-
-/*
- * fast, non-SMP clear_bit routine
- */
-static inline void 
 __clear_bit(unsigned long nr, volatile unsigned long *ptr)
 {
-	unsigned long addr;
+	unsigned char *addr = __bitops_byte(nr, ptr);
 
-	addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
-	asm volatile(
-		"	nc	%O0(1,%R0),%1"
-		: "+Q" (*(char *) addr) : "Q" (_ni_bitmap[nr & 7]) : "cc");
+	*addr &= ~(1 << (nr & 7));
 }
 
-static inline void 
-__constant_clear_bit(const unsigned long nr, volatile unsigned long *ptr)
-{
-	unsigned long addr;
-
-	addr = ((unsigned long) ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
-	*(unsigned char *) addr &= ~(1 << (nr & 7));
-}
-
-#define clear_bit_simple(nr,addr) \
-(__builtin_constant_p((nr)) ? \
- __constant_clear_bit((nr),(addr)) : \
- __clear_bit((nr),(addr)) )
-
-/* 
- * fast, non-SMP change_bit routine 
- */
 static inline void __change_bit(unsigned long nr, volatile unsigned long *ptr)
 {
-	unsigned long addr;
+	unsigned char *addr = __bitops_byte(nr, ptr);
 
-	addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
-	asm volatile(
-		"	xc	%O0(1,%R0),%1"
-		: "+Q" (*(char *) addr) : "Q" (_oi_bitmap[nr & 7]) : "cc");
+	*addr ^= 1 << (nr & 7);
 }
 
-static inline void 
-__constant_change_bit(const unsigned long nr, volatile unsigned long *ptr) 
-{
-	unsigned long addr;
-
-	addr = ((unsigned long) ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
-	*(unsigned char *) addr ^= 1 << (nr & 7);
-}
-
-#define change_bit_simple(nr,addr) \
-(__builtin_constant_p((nr)) ? \
- __constant_change_bit((nr),(addr)) : \
- __change_bit((nr),(addr)) )
-
-/*
- * fast, non-SMP test_and_set_bit routine
- */
 static inline int
-test_and_set_bit_simple(unsigned long nr, volatile unsigned long *ptr)
+__test_and_set_bit(unsigned long nr, volatile unsigned long *ptr)
 {
-	unsigned long addr;
+	unsigned char *addr = __bitops_byte(nr, ptr);
 	unsigned char ch;
 
-	addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
-	ch = *(unsigned char *) addr;
-	asm volatile(
-		"	oc	%O0(1,%R0),%1"
-		: "+Q" (*(char *) addr)	: "Q" (_oi_bitmap[nr & 7])
-		: "cc", "memory");
+	ch = *addr;
+	*addr |= 1 << (nr & 7);
 	return (ch >> (nr & 7)) & 1;
 }
-#define __test_and_set_bit(X,Y)		test_and_set_bit_simple(X,Y)
 
-/*
- * fast, non-SMP test_and_clear_bit routine
- */
 static inline int
-test_and_clear_bit_simple(unsigned long nr, volatile unsigned long *ptr)
+__test_and_clear_bit(unsigned long nr, volatile unsigned long *ptr)
 {
-	unsigned long addr;
+	unsigned char *addr = __bitops_byte(nr, ptr);
 	unsigned char ch;
 
-	addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
-	ch = *(unsigned char *) addr;
-	asm volatile(
-		"	nc	%O0(1,%R0),%1"
-		: "+Q" (*(char *) addr)	: "Q" (_ni_bitmap[nr & 7])
-		: "cc", "memory");
+	ch = *addr;
+	*addr &= ~(1 << (nr & 7));
 	return (ch >> (nr & 7)) & 1;
 }
-#define __test_and_clear_bit(X,Y)	test_and_clear_bit_simple(X,Y)
 
-/*
- * fast, non-SMP test_and_change_bit routine
- */
 static inline int
-test_and_change_bit_simple(unsigned long nr, volatile unsigned long *ptr)
+__test_and_change_bit(unsigned long nr, volatile unsigned long *ptr)
 {
-	unsigned long addr;
+	unsigned char *addr = __bitops_byte(nr, ptr);
 	unsigned char ch;
 
-	addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
-	ch = *(unsigned char *) addr;
-	asm volatile(
-		"	xc	%O0(1,%R0),%1"
-		: "+Q" (*(char *) addr)	: "Q" (_oi_bitmap[nr & 7])
-		: "cc", "memory");
-	return (ch >> (nr & 7)) & 1;
-}
-#define __test_and_change_bit(X,Y)	test_and_change_bit_simple(X,Y)
-
-#ifdef CONFIG_SMP
-#define set_bit             set_bit_cs
-#define clear_bit           clear_bit_cs
-#define change_bit          change_bit_cs
-#define test_and_set_bit    test_and_set_bit_cs
-#define test_and_clear_bit  test_and_clear_bit_cs
-#define test_and_change_bit test_and_change_bit_cs
-#else
-#define set_bit             set_bit_simple
-#define clear_bit           clear_bit_simple
-#define change_bit          change_bit_simple
-#define test_and_set_bit    test_and_set_bit_simple
-#define test_and_clear_bit  test_and_clear_bit_simple
-#define test_and_change_bit test_and_change_bit_simple
-#endif
-
-
-/*
- * This routine doesn't need to be atomic.
- */
-
-static inline int __test_bit(unsigned long nr, const volatile unsigned long *ptr)
-{
-	unsigned long addr;
-	unsigned char ch;
-
-	addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
-	ch = *(volatile unsigned char *) addr;
+	ch = *addr;
+	*addr ^= 1 << (nr & 7);
 	return (ch >> (nr & 7)) & 1;
 }
 
-static inline int 
-__constant_test_bit(unsigned long nr, const volatile unsigned long *addr) {
-    return (((volatile char *) addr)
-	    [(nr^(BITS_PER_LONG-8))>>3] & (1<<(nr&7))) != 0;
-}
-
-#define test_bit(nr,addr) \
-(__builtin_constant_p((nr)) ? \
- __constant_test_bit((nr),(addr)) : \
- __test_bit((nr),(addr)) )
-
-/*
- * Optimized find bit helper functions.
- */
-
-/**
- * __ffz_word_loop - find byte offset of first long != -1UL
- * @addr: pointer to array of unsigned long
- * @size: size of the array in bits
- */
-static inline unsigned long __ffz_word_loop(const unsigned long *addr,
-					    unsigned long size)
+static inline int test_bit(unsigned long nr, const volatile unsigned long *ptr)
 {
-	typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype;
-	unsigned long bytes = 0;
+	const volatile unsigned char *addr;
 
-	asm volatile(
-#ifndef CONFIG_64BIT
-		"	ahi	%1,-1\n"
-		"	sra	%1,5\n"
-		"	jz	1f\n"
-		"0:	c	%2,0(%0,%3)\n"
-		"	jne	1f\n"
-		"	la	%0,4(%0)\n"
-		"	brct	%1,0b\n"
-		"1:\n"
-#else
-		"	aghi	%1,-1\n"
-		"	srag	%1,%1,6\n"
-		"	jz	1f\n"
-		"0:	cg	%2,0(%0,%3)\n"
-		"	jne	1f\n"
-		"	la	%0,8(%0)\n"
-		"	brct	%1,0b\n"
-		"1:\n"
-#endif
-		: "+&a" (bytes), "+&d" (size)
-		: "d" (-1UL), "a" (addr), "m" (*(addrtype *) addr)
-		: "cc" );
-	return bytes;
-}
-
-/**
- * __ffs_word_loop - find byte offset of first long != 0UL
- * @addr: pointer to array of unsigned long
- * @size: size of the array in bits
- */
-static inline unsigned long __ffs_word_loop(const unsigned long *addr,
-					    unsigned long size)
-{
-	typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype;
-	unsigned long bytes = 0;
-
-	asm volatile(
-#ifndef CONFIG_64BIT
-		"	ahi	%1,-1\n"
-		"	sra	%1,5\n"
-		"	jz	1f\n"
-		"0:	c	%2,0(%0,%3)\n"
-		"	jne	1f\n"
-		"	la	%0,4(%0)\n"
-		"	brct	%1,0b\n"
-		"1:\n"
-#else
-		"	aghi	%1,-1\n"
-		"	srag	%1,%1,6\n"
-		"	jz	1f\n"
-		"0:	cg	%2,0(%0,%3)\n"
-		"	jne	1f\n"
-		"	la	%0,8(%0)\n"
-		"	brct	%1,0b\n"
-		"1:\n"
-#endif
-		: "+&a" (bytes), "+&a" (size)
-		: "d" (0UL), "a" (addr), "m" (*(addrtype *) addr)
-		: "cc" );
-	return bytes;
-}
-
-/**
- * __ffz_word - add number of the first unset bit
- * @nr: base value the bit number is added to
- * @word: the word that is searched for unset bits
- */
-static inline unsigned long __ffz_word(unsigned long nr, unsigned long word)
-{
-#ifdef CONFIG_64BIT
-	if ((word & 0xffffffff) == 0xffffffff) {
-		word >>= 32;
-		nr += 32;
-	}
-#endif
-	if ((word & 0xffff) == 0xffff) {
-		word >>= 16;
-		nr += 16;
-	}
-	if ((word & 0xff) == 0xff) {
-		word >>= 8;
-		nr += 8;
-	}
-	return nr + _zb_findmap[(unsigned char) word];
-}
-
-/**
- * __ffs_word - add number of the first set bit
- * @nr: base value the bit number is added to
- * @word: the word that is searched for set bits
- */
-static inline unsigned long __ffs_word(unsigned long nr, unsigned long word)
-{
-#ifdef CONFIG_64BIT
-	if ((word & 0xffffffff) == 0) {
-		word >>= 32;
-		nr += 32;
-	}
-#endif
-	if ((word & 0xffff) == 0) {
-		word >>= 16;
-		nr += 16;
-	}
-	if ((word & 0xff) == 0) {
-		word >>= 8;
-		nr += 8;
-	}
-	return nr + _sb_findmap[(unsigned char) word];
-}
-
-
-/**
- * __load_ulong_be - load big endian unsigned long
- * @p: pointer to array of unsigned long
- * @offset: byte offset of source value in the array
- */
-static inline unsigned long __load_ulong_be(const unsigned long *p,
-					    unsigned long offset)
-{
-	p = (unsigned long *)((unsigned long) p + offset);
-	return *p;
-}
-
-/**
- * __load_ulong_le - load little endian unsigned long
- * @p: pointer to array of unsigned long
- * @offset: byte offset of source value in the array
- */
-static inline unsigned long __load_ulong_le(const unsigned long *p,
-					    unsigned long offset)
-{
-	unsigned long word;
-
-	p = (unsigned long *)((unsigned long) p + offset);
-#ifndef CONFIG_64BIT
-	asm volatile(
-		"	ic	%0,%O1(%R1)\n"
-		"	icm	%0,2,%O1+1(%R1)\n"
-		"	icm	%0,4,%O1+2(%R1)\n"
-		"	icm	%0,8,%O1+3(%R1)"
-		: "=&d" (word) : "Q" (*p) : "cc");
-#else
-	asm volatile(
-		"	lrvg	%0,%1"
-		: "=d" (word) : "m" (*p) );
-#endif
-	return word;
+	addr = ((const volatile unsigned char *)ptr);
+	addr += (nr ^ (BITS_PER_LONG - 8)) >> 3;
+	return (*addr >> (nr & 7)) & 1;
 }
 
 /*
- * The various find bit functions.
+ * Functions which use MSB0 bit numbering.
+ * On an s390x system the bits are numbered:
+ *   |0..............63|64............127|128...........191|192...........255|
+ * and on s390:
+ *   |0.....31|31....63|64....95|96...127|128..159|160..191|192..223|224..255|
  */
+unsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size);
+unsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size,
+				unsigned long offset);
 
-/*
- * ffz - find first zero in word.
- * @word: The word to search
+static inline void set_bit_inv(unsigned long nr, volatile unsigned long *ptr)
+{
+	return set_bit(nr ^ (BITS_PER_LONG - 1), ptr);
+}
+
+static inline void clear_bit_inv(unsigned long nr, volatile unsigned long *ptr)
+{
+	return clear_bit(nr ^ (BITS_PER_LONG - 1), ptr);
+}
+
+static inline void __set_bit_inv(unsigned long nr, volatile unsigned long *ptr)
+{
+	return __set_bit(nr ^ (BITS_PER_LONG - 1), ptr);
+}
+
+static inline void __clear_bit_inv(unsigned long nr, volatile unsigned long *ptr)
+{
+	return __clear_bit(nr ^ (BITS_PER_LONG - 1), ptr);
+}
+
+static inline int test_bit_inv(unsigned long nr,
+			       const volatile unsigned long *ptr)
+{
+	return test_bit(nr ^ (BITS_PER_LONG - 1), ptr);
+}
+
+#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES
+
+/**
+ * __flogr - find leftmost one
+ * @word - The word to search
  *
- * Undefined if no zero exists, so code should check against ~0UL first.
+ * Returns the bit number of the most significant bit set,
+ * where the most significant bit has bit number 0.
+ * If no bit is set this function returns 64.
  */
-static inline unsigned long ffz(unsigned long word)
+static inline unsigned char __flogr(unsigned long word)
 {
-	return __ffz_word(0, word);
+	if (__builtin_constant_p(word)) {
+		unsigned long bit = 0;
+
+		if (!word)
+			return 64;
+		if (!(word & 0xffffffff00000000UL)) {
+			word <<= 32;
+			bit += 32;
+		}
+		if (!(word & 0xffff000000000000UL)) {
+			word <<= 16;
+			bit += 16;
+		}
+		if (!(word & 0xff00000000000000UL)) {
+			word <<= 8;
+			bit += 8;
+		}
+		if (!(word & 0xf000000000000000UL)) {
+			word <<= 4;
+			bit += 4;
+		}
+		if (!(word & 0xc000000000000000UL)) {
+			word <<= 2;
+			bit += 2;
+		}
+		if (!(word & 0x8000000000000000UL)) {
+			word <<= 1;
+			bit += 1;
+		}
+		return bit;
+	} else {
+		register unsigned long bit asm("4") = word;
+		register unsigned long out asm("5");
+
+		asm volatile(
+			"       flogr   %[bit],%[bit]\n"
+			: [bit] "+d" (bit), [out] "=d" (out) : : "cc");
+		return bit;
+	}
 }
 
 /**
@@ -573,337 +395,83 @@
  *
  * Undefined if no bit exists, so code should check against 0 first.
  */
-static inline unsigned long __ffs (unsigned long word)
+static inline unsigned long __ffs(unsigned long word)
 {
-	return __ffs_word(0, word);
+	return __flogr(-word & word) ^ (BITS_PER_LONG - 1);
 }
 
 /**
  * ffs - find first bit set
- * @x: the word to search
+ * @word: the word to search
  *
- * This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
+ * This is defined the same way as the libc and
+ * compiler builtin ffs routines (man ffs).
  */
-static inline int ffs(int x)
+static inline int ffs(int word)
 {
-	if (!x)
-		return 0;
-	return __ffs_word(1, x);
+	unsigned long mask = 2 * BITS_PER_LONG - 1;
+	unsigned int val = (unsigned int)word;
+
+	return (1 + (__flogr(-val & val) ^ (BITS_PER_LONG - 1))) & mask;
 }
 
 /**
- * find_first_zero_bit - find the first zero bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
+ * __fls - find last (most-significant) set bit in a long word
+ * @word: the word to search
  *
- * Returns the bit-number of the first zero bit, not the number of the byte
- * containing a bit.
+ * Undefined if no set bit exists, so code should check against 0 first.
  */
-static inline unsigned long find_first_zero_bit(const unsigned long *addr,
-						unsigned long size)
+static inline unsigned long __fls(unsigned long word)
 {
-	unsigned long bytes, bits;
-
-        if (!size)
-                return 0;
-	bytes = __ffz_word_loop(addr, size);
-	bits = __ffz_word(bytes*8, __load_ulong_be(addr, bytes));
-	return (bits < size) ? bits : size;
+	return __flogr(word) ^ (BITS_PER_LONG - 1);
 }
-#define find_first_zero_bit find_first_zero_bit
 
 /**
- * find_first_bit - find the first set bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
+ * fls64 - find last set bit in a 64-bit word
+ * @word: the word to search
  *
- * Returns the bit-number of the first set bit, not the number of the byte
- * containing a bit.
+ * This is defined in a similar way as the libc and compiler builtin
+ * ffsll, but returns the position of the most significant set bit.
+ *
+ * fls64(value) returns 0 if value is 0 or the position of the last
+ * set bit if value is nonzero. The last (most significant) bit is
+ * at position 64.
  */
-static inline unsigned long find_first_bit(const unsigned long * addr,
-					   unsigned long size)
+static inline int fls64(unsigned long word)
 {
-	unsigned long bytes, bits;
+	unsigned long mask = 2 * BITS_PER_LONG - 1;
 
-        if (!size)
-                return 0;
-	bytes = __ffs_word_loop(addr, size);
-	bits = __ffs_word(bytes*8, __load_ulong_be(addr, bytes));
-	return (bits < size) ? bits : size;
+	return (1 + (__flogr(word) ^ (BITS_PER_LONG - 1))) & mask;
 }
-#define find_first_bit find_first_bit
-
-/*
- * Big endian variant whichs starts bit counting from left using
- * the flogr (find leftmost one) instruction.
- */
-static inline unsigned long __flo_word(unsigned long nr, unsigned long val)
-{
-	register unsigned long bit asm("2") = val;
-	register unsigned long out asm("3");
-
-	asm volatile (
-		"	.insn	rre,0xb9830000,%[bit],%[bit]\n"
-		: [bit] "+d" (bit), [out] "=d" (out) : : "cc");
-	return nr + bit;
-}
-
-/*
- * 64 bit special left bitops format:
- * order in memory:
- *    00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
- *    10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
- *    20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
- *    30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
- * after that follows the next long with bit numbers
- *    40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
- *    50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
- *    60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
- *    70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
- * The reason for this bit ordering is the fact that
- * the hardware sets bits in a bitmap starting at bit 0
- * and we don't want to scan the bitmap from the 'wrong
- * end'.
- */
-static inline unsigned long find_first_bit_left(const unsigned long *addr,
-						unsigned long size)
-{
-	unsigned long bytes, bits;
-
-	if (!size)
-		return 0;
-	bytes = __ffs_word_loop(addr, size);
-	bits = __flo_word(bytes * 8, __load_ulong_be(addr, bytes));
-	return (bits < size) ? bits : size;
-}
-
-static inline int find_next_bit_left(const unsigned long *addr,
-				     unsigned long size,
-				     unsigned long offset)
-{
-	const unsigned long *p;
-	unsigned long bit, set;
-
-	if (offset >= size)
-		return size;
-	bit = offset & (BITS_PER_LONG - 1);
-	offset -= bit;
-	size -= offset;
-	p = addr + offset / BITS_PER_LONG;
-	if (bit) {
-		set = __flo_word(0, *p & (~0UL >> bit));
-		if (set >= size)
-			return size + offset;
-		if (set < BITS_PER_LONG)
-			return set + offset;
-		offset += BITS_PER_LONG;
-		size -= BITS_PER_LONG;
-		p++;
-	}
-	return offset + find_first_bit_left(p, size);
-}
-
-#define for_each_set_bit_left(bit, addr, size)				\
-	for ((bit) = find_first_bit_left((addr), (size));		\
-	     (bit) < (size);						\
-	     (bit) = find_next_bit_left((addr), (size), (bit) + 1))
-
-/* same as for_each_set_bit() but use bit as value to start with */
-#define for_each_set_bit_left_cont(bit, addr, size)			\
-	for ((bit) = find_next_bit_left((addr), (size), (bit));		\
-	     (bit) < (size);						\
-	     (bit) = find_next_bit_left((addr), (size), (bit) + 1))
 
 /**
- * find_next_zero_bit - find the first zero bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
+ * fls - find last (most-significant) bit set
+ * @word: the word to search
+ *
+ * This is defined the same way as ffs.
+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
  */
-static inline int find_next_zero_bit (const unsigned long * addr,
-				      unsigned long size,
-				      unsigned long offset)
+static inline int fls(int word)
 {
-        const unsigned long *p;
-	unsigned long bit, set;
-
-	if (offset >= size)
-		return size;
-	bit = offset & (BITS_PER_LONG - 1);
-	offset -= bit;
-	size -= offset;
-	p = addr + offset / BITS_PER_LONG;
-	if (bit) {
-		/*
-		 * __ffz_word returns BITS_PER_LONG
-		 * if no zero bit is present in the word.
-		 */
-		set = __ffz_word(bit, *p >> bit);
-		if (set >= size)
-			return size + offset;
-		if (set < BITS_PER_LONG)
-			return set + offset;
-		offset += BITS_PER_LONG;
-		size -= BITS_PER_LONG;
-		p++;
-	}
-	return offset + find_first_zero_bit(p, size);
-}
-#define find_next_zero_bit find_next_zero_bit
-
-/**
- * find_next_bit - find the first set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-static inline int find_next_bit (const unsigned long * addr,
-				 unsigned long size,
-				 unsigned long offset)
-{
-        const unsigned long *p;
-	unsigned long bit, set;
-
-	if (offset >= size)
-		return size;
-	bit = offset & (BITS_PER_LONG - 1);
-	offset -= bit;
-	size -= offset;
-	p = addr + offset / BITS_PER_LONG;
-	if (bit) {
-		/*
-		 * __ffs_word returns BITS_PER_LONG
-		 * if no one bit is present in the word.
-		 */
-		set = __ffs_word(0, *p & (~0UL << bit));
-		if (set >= size)
-			return size + offset;
-		if (set < BITS_PER_LONG)
-			return set + offset;
-		offset += BITS_PER_LONG;
-		size -= BITS_PER_LONG;
-		p++;
-	}
-	return offset + find_first_bit(p, size);
-}
-#define find_next_bit find_next_bit
-
-/*
- * Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is cleared.
- */
-static inline int sched_find_first_bit(unsigned long *b)
-{
-	return find_first_bit(b, 140);
+	return fls64((unsigned int)word);
 }
 
-#include <asm-generic/bitops/fls.h>
+#else /* CONFIG_HAVE_MARCH_Z9_109_FEATURES */
+
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/ffs.h>
 #include <asm-generic/bitops/__fls.h>
+#include <asm-generic/bitops/fls.h>
 #include <asm-generic/bitops/fls64.h>
 
+#endif /* CONFIG_HAVE_MARCH_Z9_109_FEATURES */
+
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/hweight.h>
 #include <asm-generic/bitops/lock.h>
-
-/*
- * ATTENTION: intel byte ordering convention for ext2 and minix !!
- * bit 0 is the LSB of addr; bit 31 is the MSB of addr;
- * bit 32 is the LSB of (addr+4).
- * That combined with the little endian byte order of Intel gives the
- * following bit order in memory:
- *    07 06 05 04 03 02 01 00 15 14 13 12 11 10 09 08 \
- *    23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24
- */
-
-static inline int find_first_zero_bit_le(void *vaddr, unsigned int size)
-{
-	unsigned long bytes, bits;
-
-        if (!size)
-                return 0;
-	bytes = __ffz_word_loop(vaddr, size);
-	bits = __ffz_word(bytes*8, __load_ulong_le(vaddr, bytes));
-	return (bits < size) ? bits : size;
-}
-#define find_first_zero_bit_le find_first_zero_bit_le
-
-static inline int find_next_zero_bit_le(void *vaddr, unsigned long size,
-					  unsigned long offset)
-{
-        unsigned long *addr = vaddr, *p;
-	unsigned long bit, set;
-
-        if (offset >= size)
-                return size;
-	bit = offset & (BITS_PER_LONG - 1);
-	offset -= bit;
-	size -= offset;
-	p = addr + offset / BITS_PER_LONG;
-        if (bit) {
-		/*
-		 * s390 version of ffz returns BITS_PER_LONG
-		 * if no zero bit is present in the word.
-		 */
-		set = __ffz_word(bit, __load_ulong_le(p, 0) >> bit);
-		if (set >= size)
-			return size + offset;
-		if (set < BITS_PER_LONG)
-			return set + offset;
-		offset += BITS_PER_LONG;
-		size -= BITS_PER_LONG;
-		p++;
-        }
-	return offset + find_first_zero_bit_le(p, size);
-}
-#define find_next_zero_bit_le find_next_zero_bit_le
-
-static inline unsigned long find_first_bit_le(void *vaddr, unsigned long size)
-{
-	unsigned long bytes, bits;
-
-	if (!size)
-		return 0;
-	bytes = __ffs_word_loop(vaddr, size);
-	bits = __ffs_word(bytes*8, __load_ulong_le(vaddr, bytes));
-	return (bits < size) ? bits : size;
-}
-#define find_first_bit_le find_first_bit_le
-
-static inline int find_next_bit_le(void *vaddr, unsigned long size,
-				     unsigned long offset)
-{
-	unsigned long *addr = vaddr, *p;
-	unsigned long bit, set;
-
-	if (offset >= size)
-		return size;
-	bit = offset & (BITS_PER_LONG - 1);
-	offset -= bit;
-	size -= offset;
-	p = addr + offset / BITS_PER_LONG;
-	if (bit) {
-		/*
-		 * s390 version of ffz returns BITS_PER_LONG
-		 * if no zero bit is present in the word.
-		 */
-		set = __ffs_word(0, __load_ulong_le(p, 0) & (~0UL << bit));
-		if (set >= size)
-			return size + offset;
-		if (set < BITS_PER_LONG)
-			return set + offset;
-		offset += BITS_PER_LONG;
-		size -= BITS_PER_LONG;
-		p++;
-	}
-	return offset + find_first_bit_le(p, size);
-}
-#define find_next_bit_le find_next_bit_le
-
+#include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/le.h>
-
 #include <asm-generic/bitops/ext2-atomic-setbit.h>
 
 #endif /* _S390_BITOPS_H */
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
index c1e7c64..4bf9da0 100644
--- a/arch/s390/include/asm/compat.h
+++ b/arch/s390/include/asm/compat.h
@@ -22,6 +22,7 @@
 #define PSW32_MASK_ASC		0x0000C000UL
 #define PSW32_MASK_CC		0x00003000UL
 #define PSW32_MASK_PM		0x00000f00UL
+#define PSW32_MASK_RI		0x00000080UL
 
 #define PSW32_MASK_USER		0x0000FF00UL
 
@@ -35,7 +36,9 @@
 #define PSW32_ASC_SECONDARY	0x00008000UL
 #define PSW32_ASC_HOME		0x0000C000UL
 
-extern u32 psw32_user_bits;
+#define PSW32_USER_BITS (PSW32_MASK_DAT | PSW32_MASK_IO | PSW32_MASK_EXT | \
+			 PSW32_DEFAULT_KEY | PSW32_MASK_BASE | \
+			 PSW32_MASK_MCHECK | PSW32_MASK_PSTATE | PSW32_ASC_HOME)
 
 #define COMPAT_USER_HZ		100
 #define COMPAT_UTS_MACHINE	"s390\0\0\0\0"
diff --git a/arch/s390/include/asm/ctl_reg.h b/arch/s390/include/asm/ctl_reg.h
index debfda3..9b69c0b 100644
--- a/arch/s390/include/asm/ctl_reg.h
+++ b/arch/s390/include/asm/ctl_reg.h
@@ -8,69 +8,59 @@
 #define __ASM_CTL_REG_H
 
 #ifdef CONFIG_64BIT
+# define __CTL_LOAD	"lctlg"
+# define __CTL_STORE	"stctg"
+#else
+# define __CTL_LOAD	"lctl"
+# define __CTL_STORE	"stctl"
+#endif
 
-#define __ctl_load(array, low, high) ({				\
-	typedef struct { char _[sizeof(array)]; } addrtype;	\
-	asm volatile(						\
-		"	lctlg	%1,%2,%0\n"			\
-		: : "Q" (*(addrtype *)(&array)),		\
-		    "i" (low), "i" (high));			\
-	})
+#define __ctl_load(array, low, high) {					\
+	typedef struct { char _[sizeof(array)]; } addrtype;		\
+									\
+	BUILD_BUG_ON(sizeof(addrtype) != (high - low + 1) * sizeof(long));\
+	asm volatile(							\
+		__CTL_LOAD " %1,%2,%0\n"				\
+		: : "Q" (*(addrtype *)(&array)), "i" (low), "i" (high));\
+}
 
-#define __ctl_store(array, low, high) ({			\
-	typedef struct { char _[sizeof(array)]; } addrtype;	\
-	asm volatile(						\
-		"	stctg	%1,%2,%0\n"			\
-		: "=Q" (*(addrtype *)(&array))			\
-		: "i" (low), "i" (high));			\
-	})
+#define __ctl_store(array, low, high) {					\
+	typedef struct { char _[sizeof(array)]; } addrtype;		\
+									\
+	BUILD_BUG_ON(sizeof(addrtype) != (high - low + 1) * sizeof(long));\
+	asm volatile(							\
+		__CTL_STORE " %1,%2,%0\n"				\
+		: "=Q" (*(addrtype *)(&array))				\
+		: "i" (low), "i" (high));				\
+}
 
-#else /* CONFIG_64BIT */
+static inline void __ctl_set_bit(unsigned int cr, unsigned int bit)
+{
+	unsigned long reg;
 
-#define __ctl_load(array, low, high) ({				\
-	typedef struct { char _[sizeof(array)]; } addrtype;	\
-	asm volatile(						\
-		"	lctl	%1,%2,%0\n"			\
-		: : "Q" (*(addrtype *)(&array)),		\
-		    "i" (low), "i" (high));			\
-})
+	__ctl_store(reg, cr, cr);
+	reg |= 1UL << bit;
+	__ctl_load(reg, cr, cr);
+}
 
-#define __ctl_store(array, low, high) ({			\
-	typedef struct { char _[sizeof(array)]; } addrtype;	\
-	asm volatile(						\
-		"	stctl	%1,%2,%0\n"			\
-		: "=Q" (*(addrtype *)(&array))			\
-		: "i" (low), "i" (high));			\
-	})
+static inline void __ctl_clear_bit(unsigned int cr, unsigned int bit)
+{
+	unsigned long reg;
 
-#endif /* CONFIG_64BIT */
+	__ctl_store(reg, cr, cr);
+	reg &= ~(1UL << bit);
+	__ctl_load(reg, cr, cr);
+}
 
-#define __ctl_set_bit(cr, bit) ({	\
-	unsigned long __dummy;		\
-	__ctl_store(__dummy, cr, cr);	\
-	__dummy |= 1UL << (bit);	\
-	__ctl_load(__dummy, cr, cr);	\
-})
-
-#define __ctl_clear_bit(cr, bit) ({	\
-	unsigned long __dummy;		\
-	__ctl_store(__dummy, cr, cr);	\
-	__dummy &= ~(1UL << (bit));	\
-	__ctl_load(__dummy, cr, cr);	\
-})
+void smp_ctl_set_bit(int cr, int bit);
+void smp_ctl_clear_bit(int cr, int bit);
 
 #ifdef CONFIG_SMP
-
-extern void smp_ctl_set_bit(int cr, int bit);
-extern void smp_ctl_clear_bit(int cr, int bit);
-#define ctl_set_bit(cr, bit) smp_ctl_set_bit(cr, bit)
-#define ctl_clear_bit(cr, bit) smp_ctl_clear_bit(cr, bit)
-
+# define ctl_set_bit(cr, bit) smp_ctl_set_bit(cr, bit)
+# define ctl_clear_bit(cr, bit) smp_ctl_clear_bit(cr, bit)
 #else
-
-#define ctl_set_bit(cr, bit) __ctl_set_bit(cr, bit)
-#define ctl_clear_bit(cr, bit) __ctl_clear_bit(cr, bit)
-
-#endif /* CONFIG_SMP */
+# define ctl_set_bit(cr, bit) __ctl_set_bit(cr, bit)
+# define ctl_clear_bit(cr, bit) __ctl_clear_bit(cr, bit)
+#endif
 
 #endif /* __ASM_CTL_REG_H */
diff --git a/arch/s390/include/asm/debug.h b/arch/s390/include/asm/debug.h
index 188c505..530c15e 100644
--- a/arch/s390/include/asm/debug.h
+++ b/arch/s390/include/asm/debug.h
@@ -107,6 +107,11 @@
 void debug_set_critical(void);
 void debug_stop_all(void);
 
+static inline bool debug_level_enabled(debug_info_t* id, int level)
+{
+	return level <= id->level;
+}
+
 static inline debug_entry_t*
 debug_event(debug_info_t* id, int level, void* data, int length)
 {
diff --git a/arch/s390/include/asm/dis.h b/arch/s390/include/asm/dis.h
new file mode 100644
index 0000000..04a83f5
--- /dev/null
+++ b/arch/s390/include/asm/dis.h
@@ -0,0 +1,52 @@
+/*
+ * Disassemble s390 instructions.
+ *
+ * Copyright IBM Corp. 2007
+ * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+
+#ifndef __ASM_S390_DIS_H__
+#define __ASM_S390_DIS_H__
+
+/* Type of operand */
+#define OPERAND_GPR	0x1	/* Operand printed as %rx */
+#define OPERAND_FPR	0x2	/* Operand printed as %fx */
+#define OPERAND_AR	0x4	/* Operand printed as %ax */
+#define OPERAND_CR	0x8	/* Operand printed as %cx */
+#define OPERAND_DISP	0x10	/* Operand printed as displacement */
+#define OPERAND_BASE	0x20	/* Operand printed as base register */
+#define OPERAND_INDEX	0x40	/* Operand printed as index register */
+#define OPERAND_PCREL	0x80	/* Operand printed as pc-relative symbol */
+#define OPERAND_SIGNED	0x100	/* Operand printed as signed value */
+#define OPERAND_LENGTH	0x200	/* Operand printed as length (+1) */
+
+
+struct s390_operand {
+	int bits;		/* The number of bits in the operand. */
+	int shift;		/* The number of bits to shift. */
+	int flags;		/* One bit syntax flags. */
+};
+
+struct s390_insn {
+	const char name[5];
+	unsigned char opfrag;
+	unsigned char format;
+};
+
+
+static inline int insn_length(unsigned char code)
+{
+	return ((((int) code + 64) >> 7) + 1) << 1;
+}
+
+void show_code(struct pt_regs *regs);
+void print_fn_code(unsigned char *code, unsigned long len);
+int insn_to_mnemonic(unsigned char *instruction, char *buf, unsigned int len);
+struct s390_insn *find_insn(unsigned char *code);
+
+static inline int is_known_insn(unsigned char *code)
+{
+	return !!find_insn(code);
+}
+
+#endif /* __ASM_S390_DIS_H__ */
diff --git a/arch/s390/include/asm/fcx.h b/arch/s390/include/asm/fcx.h
index ef61709..7ecb92b 100644
--- a/arch/s390/include/asm/fcx.h
+++ b/arch/s390/include/asm/fcx.h
@@ -12,9 +12,9 @@
 
 #define TCW_FORMAT_DEFAULT		0
 #define TCW_TIDAW_FORMAT_DEFAULT	0
-#define TCW_FLAGS_INPUT_TIDA		1 << (23 - 5)
-#define TCW_FLAGS_TCCB_TIDA		1 << (23 - 6)
-#define TCW_FLAGS_OUTPUT_TIDA		1 << (23 - 7)
+#define TCW_FLAGS_INPUT_TIDA		(1 << (23 - 5))
+#define TCW_FLAGS_TCCB_TIDA		(1 << (23 - 6))
+#define TCW_FLAGS_OUTPUT_TIDA		(1 << (23 - 7))
 #define TCW_FLAGS_TIDAW_FORMAT(x)	((x) & 3) << (23 - 9)
 #define TCW_FLAGS_GET_TIDAW_FORMAT(x)	(((x) >> (23 - 9)) & 3)
 
@@ -54,11 +54,11 @@
 	u32 intrg;
 } __attribute__ ((packed, aligned(64)));
 
-#define TIDAW_FLAGS_LAST		1 << (7 - 0)
-#define TIDAW_FLAGS_SKIP		1 << (7 - 1)
-#define TIDAW_FLAGS_DATA_INT		1 << (7 - 2)
-#define TIDAW_FLAGS_TTIC		1 << (7 - 3)
-#define TIDAW_FLAGS_INSERT_CBC		1 << (7 - 4)
+#define TIDAW_FLAGS_LAST		(1 << (7 - 0))
+#define TIDAW_FLAGS_SKIP		(1 << (7 - 1))
+#define TIDAW_FLAGS_DATA_INT		(1 << (7 - 2))
+#define TIDAW_FLAGS_TTIC		(1 << (7 - 3))
+#define TIDAW_FLAGS_INSERT_CBC		(1 << (7 - 4))
 
 /**
  * struct tidaw - Transport-Indirect-Addressing Word (TIDAW)
@@ -106,9 +106,9 @@
 	u8 sense[32];
 } __attribute__ ((packed));
 
-#define TSA_INTRG_FLAGS_CU_STATE_VALID		1 << (7 - 0)
-#define TSA_INTRG_FLAGS_DEV_STATE_VALID		1 << (7 - 1)
-#define TSA_INTRG_FLAGS_OP_STATE_VALID		1 << (7 - 2)
+#define TSA_INTRG_FLAGS_CU_STATE_VALID		(1 << (7 - 0))
+#define TSA_INTRG_FLAGS_DEV_STATE_VALID		(1 << (7 - 1))
+#define TSA_INTRG_FLAGS_OP_STATE_VALID		(1 << (7 - 2))
 
 /**
  * struct tsa_intrg - Interrogate Transport-Status Area (Intrg. TSA)
@@ -140,10 +140,10 @@
 #define TSB_FORMAT_DDPC		2
 #define TSB_FORMAT_INTRG	3
 
-#define TSB_FLAGS_DCW_OFFSET_VALID	1 << (7 - 0)
-#define TSB_FLAGS_COUNT_VALID		1 << (7 - 1)
-#define TSB_FLAGS_CACHE_MISS		1 << (7 - 2)
-#define TSB_FLAGS_TIME_VALID		1 << (7 - 3)
+#define TSB_FLAGS_DCW_OFFSET_VALID	(1 << (7 - 0))
+#define TSB_FLAGS_COUNT_VALID		(1 << (7 - 1))
+#define TSB_FLAGS_CACHE_MISS		(1 << (7 - 2))
+#define TSB_FLAGS_TIME_VALID		(1 << (7 - 3))
 #define TSB_FLAGS_FORMAT(x)		((x) & 7)
 #define TSB_FORMAT(t)			((t)->flags & 7)
 
@@ -179,9 +179,9 @@
 #define DCW_INTRG_RCQ_PRIMARY		1
 #define DCW_INTRG_RCQ_SECONDARY		2
 
-#define DCW_INTRG_FLAGS_MPM		1 < (7 - 0)
-#define DCW_INTRG_FLAGS_PPR		1 < (7 - 1)
-#define DCW_INTRG_FLAGS_CRIT		1 < (7 - 2)
+#define DCW_INTRG_FLAGS_MPM		(1 << (7 - 0))
+#define DCW_INTRG_FLAGS_PPR		(1 << (7 - 1))
+#define DCW_INTRG_FLAGS_CRIT		(1 << (7 - 2))
 
 /**
  * struct dcw_intrg_data - Interrogate DCW data
@@ -216,7 +216,7 @@
 	u8  prog_data[0];
 } __attribute__ ((packed));
 
-#define DCW_FLAGS_CC		1 << (7 - 1)
+#define DCW_FLAGS_CC		(1 << (7 - 1))
 
 #define DCW_CMD_WRITE		0x01
 #define DCW_CMD_READ		0x02
diff --git a/arch/s390/include/asm/ipl.h b/arch/s390/include/asm/ipl.h
index 2bd6cb8..2fcccc0 100644
--- a/arch/s390/include/asm/ipl.h
+++ b/arch/s390/include/asm/ipl.h
@@ -7,6 +7,7 @@
 #ifndef _ASM_S390_IPL_H
 #define _ASM_S390_IPL_H
 
+#include <asm/lowcore.h>
 #include <asm/types.h>
 #include <asm/cio.h>
 #include <asm/setup.h>
@@ -86,7 +87,14 @@
  */
 extern u32 ipl_flags;
 extern u32 dump_prefix_page;
-extern unsigned int zfcpdump_prefix_array[];
+
+struct dump_save_areas {
+	struct save_area **areas;
+	int count;
+};
+
+extern struct dump_save_areas dump_save_areas;
+struct save_area *dump_save_area_create(int cpu);
 
 extern void do_reipl(void);
 extern void do_halt(void);
diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h
index 6c32190..346b1c8 100644
--- a/arch/s390/include/asm/jump_label.h
+++ b/arch/s390/include/asm/jump_label.h
@@ -15,7 +15,7 @@
 
 static __always_inline bool arch_static_branch(struct static_key *key)
 {
-	asm goto("0:	brcl 0,0\n"
+	asm_volatile_goto("0:	brcl 0,0\n"
 		".pushsection __jump_table, \"aw\"\n"
 		ASM_ALIGN "\n"
 		ASM_PTR " 0b, %l[label], %0\n"
diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h
index 9f973d8..5d1f950 100644
--- a/arch/s390/include/asm/mmu_context.h
+++ b/arch/s390/include/asm/mmu_context.h
@@ -40,14 +40,8 @@
 	pgd_t *pgd = mm->pgd;
 
 	S390_lowcore.user_asce = mm->context.asce_bits | __pa(pgd);
-	if (s390_user_mode != HOME_SPACE_MODE) {
-		/* Load primary space page table origin. */
-		asm volatile(LCTL_OPCODE" 1,1,%0\n"
-			     : : "m" (S390_lowcore.user_asce) );
-	} else
-		/* Load home space page table origin. */
-		asm volatile(LCTL_OPCODE" 13,13,%0"
-			     : : "m" (S390_lowcore.user_asce) );
+	/* Load primary space page table origin. */
+	asm volatile(LCTL_OPCODE" 1,1,%0\n" : : "m" (S390_lowcore.user_asce));
 	set_fs(current->thread.mm_segment);
 }
 
diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h
index 1e51f29..316c850 100644
--- a/arch/s390/include/asm/page.h
+++ b/arch/s390/include/asm/page.h
@@ -30,7 +30,12 @@
 #include <asm/setup.h>
 #ifndef __ASSEMBLY__
 
-void storage_key_init_range(unsigned long start, unsigned long end);
+static inline void storage_key_init_range(unsigned long start, unsigned long end)
+{
+#if PAGE_DEFAULT_KEY
+	__storage_key_init_range(start, end);
+#endif
+}
 
 static inline void clear_page(void *page)
 {
diff --git a/arch/s390/include/asm/pci_debug.h b/arch/s390/include/asm/pci_debug.h
index 1ca5d10..ac24b26 100644
--- a/arch/s390/include/asm/pci_debug.h
+++ b/arch/s390/include/asm/pci_debug.h
@@ -6,14 +6,9 @@
 extern debug_info_t *pci_debug_msg_id;
 extern debug_info_t *pci_debug_err_id;
 
-#ifdef CONFIG_PCI_DEBUG
 #define zpci_dbg(imp, fmt, args...)				\
 	debug_sprintf_event(pci_debug_msg_id, imp, fmt, ##args)
 
-#else /* !CONFIG_PCI_DEBUG */
-#define zpci_dbg(imp, fmt, args...) do { } while (0)
-#endif
-
 #define zpci_err(text...)							\
 	do {									\
 		char debug_buffer[16];						\
diff --git a/arch/s390/include/asm/pci_insn.h b/arch/s390/include/asm/pci_insn.h
index df6eac9..649eb62 100644
--- a/arch/s390/include/asm/pci_insn.h
+++ b/arch/s390/include/asm/pci_insn.h
@@ -54,11 +54,9 @@
 struct zpci_fib {
 	u32 fmt		:  8;	/* format */
 	u32		: 24;
-	u32 reserved1;
+	u32		: 32;
 	u8 fc;			/* function controls */
-	u8 reserved2;
-	u16 reserved3;
-	u32 reserved4;
+	u64		: 56;
 	u64 pba;		/* PCI base address */
 	u64 pal;		/* PCI address limit */
 	u64 iota;		/* I/O Translation Anchor */
@@ -70,14 +68,13 @@
 	u32 sum		:  1;	/* Adapter int summary bit enabled */
 	u32		:  1;
 	u32 aisbo	:  6;	/* Adapter int summary bit offset */
-	u32 reserved5;
+	u32		: 32;
 	u64 aibv;		/* Adapter int bit vector address */
 	u64 aisb;		/* Adapter int summary bit address */
 	u64 fmb_addr;		/* Function measurement block address and key */
-	u64 reserved6;
-	u64 reserved7;
-} __packed;
-
+	u32		: 32;
+	u32 gd;
+} __packed __aligned(8);
 
 int zpci_mod_fc(u64 req, struct zpci_fib *fib);
 int zpci_refresh_trans(u64 fn, u64 addr, u64 range);
diff --git a/arch/s390/include/asm/percpu.h b/arch/s390/include/asm/percpu.h
index 86fe0ee..fa91e00 100644
--- a/arch/s390/include/asm/percpu.h
+++ b/arch/s390/include/asm/percpu.h
@@ -10,16 +10,22 @@
  */
 #define __my_cpu_offset S390_lowcore.percpu_offset
 
+#ifdef CONFIG_64BIT
+
 /*
  * For 64 bit module code, the module may be more than 4G above the
  * per cpu area, use weak definitions to force the compiler to
  * generate external references.
  */
-#if defined(CONFIG_SMP) && defined(CONFIG_64BIT) && defined(MODULE)
+#if defined(CONFIG_SMP) && defined(MODULE)
 #define ARCH_NEEDS_WEAK_PER_CPU
 #endif
 
-#define arch_this_cpu_to_op(pcp, val, op)				\
+/*
+ * We use a compare-and-swap loop since that uses less cpu cycles than
+ * disabling and enabling interrupts like the generic variant would do.
+ */
+#define arch_this_cpu_to_op_simple(pcp, val, op)			\
 ({									\
 	typedef typeof(pcp) pcp_op_T__;					\
 	pcp_op_T__ old__, new__, prev__;				\
@@ -30,42 +36,101 @@
 	do {								\
 		old__ = prev__;						\
 		new__ = old__ op (val);					\
-		switch (sizeof(*ptr__)) {				\
-		case 8:							\
-			prev__ = cmpxchg64(ptr__, old__, new__);	\
-			break;						\
-		default:						\
-			prev__ = cmpxchg(ptr__, old__, new__);		\
-		}							\
+		prev__ = cmpxchg(ptr__, old__, new__);			\
 	} while (prev__ != old__);					\
 	preempt_enable();						\
 	new__;								\
 })
 
-#define this_cpu_add_1(pcp, val) arch_this_cpu_to_op(pcp, val, +)
-#define this_cpu_add_2(pcp, val) arch_this_cpu_to_op(pcp, val, +)
-#define this_cpu_add_4(pcp, val) arch_this_cpu_to_op(pcp, val, +)
-#define this_cpu_add_8(pcp, val) arch_this_cpu_to_op(pcp, val, +)
+#define this_cpu_add_1(pcp, val)	arch_this_cpu_to_op_simple(pcp, val, +)
+#define this_cpu_add_2(pcp, val)	arch_this_cpu_to_op_simple(pcp, val, +)
+#define this_cpu_add_return_1(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +)
+#define this_cpu_add_return_2(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +)
+#define this_cpu_and_1(pcp, val)	arch_this_cpu_to_op_simple(pcp, val, &)
+#define this_cpu_and_2(pcp, val)	arch_this_cpu_to_op_simple(pcp, val, &)
+#define this_cpu_or_1(pcp, val)		arch_this_cpu_to_op_simple(pcp, val, |)
+#define this_cpu_or_2(pcp, val)		arch_this_cpu_to_op_simple(pcp, val, |)
 
-#define this_cpu_add_return_1(pcp, val) arch_this_cpu_to_op(pcp, val, +)
-#define this_cpu_add_return_2(pcp, val) arch_this_cpu_to_op(pcp, val, +)
-#define this_cpu_add_return_4(pcp, val) arch_this_cpu_to_op(pcp, val, +)
-#define this_cpu_add_return_8(pcp, val) arch_this_cpu_to_op(pcp, val, +)
+#ifndef CONFIG_HAVE_MARCH_Z196_FEATURES
 
-#define this_cpu_and_1(pcp, val) arch_this_cpu_to_op(pcp, val, &)
-#define this_cpu_and_2(pcp, val) arch_this_cpu_to_op(pcp, val, &)
-#define this_cpu_and_4(pcp, val) arch_this_cpu_to_op(pcp, val, &)
-#define this_cpu_and_8(pcp, val) arch_this_cpu_to_op(pcp, val, &)
+#define this_cpu_add_4(pcp, val)	arch_this_cpu_to_op_simple(pcp, val, +)
+#define this_cpu_add_8(pcp, val)	arch_this_cpu_to_op_simple(pcp, val, +)
+#define this_cpu_add_return_4(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +)
+#define this_cpu_add_return_8(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +)
+#define this_cpu_and_4(pcp, val)	arch_this_cpu_to_op_simple(pcp, val, &)
+#define this_cpu_and_8(pcp, val)	arch_this_cpu_to_op_simple(pcp, val, &)
+#define this_cpu_or_4(pcp, val)		arch_this_cpu_to_op_simple(pcp, val, |)
+#define this_cpu_or_8(pcp, val)		arch_this_cpu_to_op_simple(pcp, val, |)
 
-#define this_cpu_or_1(pcp, val) arch_this_cpu_to_op(pcp, val, |)
-#define this_cpu_or_2(pcp, val) arch_this_cpu_to_op(pcp, val, |)
-#define this_cpu_or_4(pcp, val) arch_this_cpu_to_op(pcp, val, |)
-#define this_cpu_or_8(pcp, val) arch_this_cpu_to_op(pcp, val, |)
+#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */
 
-#define this_cpu_xor_1(pcp, val) arch_this_cpu_to_op(pcp, val, ^)
-#define this_cpu_xor_2(pcp, val) arch_this_cpu_to_op(pcp, val, ^)
-#define this_cpu_xor_4(pcp, val) arch_this_cpu_to_op(pcp, val, ^)
-#define this_cpu_xor_8(pcp, val) arch_this_cpu_to_op(pcp, val, ^)
+#define arch_this_cpu_add(pcp, val, op1, op2, szcast)			\
+{									\
+	typedef typeof(pcp) pcp_op_T__; 				\
+	pcp_op_T__ val__ = (val);					\
+	pcp_op_T__ old__, *ptr__;					\
+	preempt_disable();						\
+	ptr__ = __this_cpu_ptr(&(pcp)); 				\
+	if (__builtin_constant_p(val__) &&				\
+	    ((szcast)val__ > -129) && ((szcast)val__ < 128)) {		\
+		asm volatile(						\
+			op2 "   %[ptr__],%[val__]\n"			\
+			: [ptr__] "+Q" (*ptr__) 			\
+			: [val__] "i" ((szcast)val__)			\
+			: "cc");					\
+	} else {							\
+		asm volatile(						\
+			op1 "   %[old__],%[val__],%[ptr__]\n"		\
+			: [old__] "=d" (old__), [ptr__] "+Q" (*ptr__)	\
+			: [val__] "d" (val__)				\
+			: "cc");					\
+	}								\
+	preempt_enable();						\
+}
+
+#define this_cpu_add_4(pcp, val) arch_this_cpu_add(pcp, val, "laa", "asi", int)
+#define this_cpu_add_8(pcp, val) arch_this_cpu_add(pcp, val, "laag", "agsi", long)
+
+#define arch_this_cpu_add_return(pcp, val, op)				\
+({									\
+	typedef typeof(pcp) pcp_op_T__; 				\
+	pcp_op_T__ val__ = (val);					\
+	pcp_op_T__ old__, *ptr__;					\
+	preempt_disable();						\
+	ptr__ = __this_cpu_ptr(&(pcp)); 				\
+	asm volatile(							\
+		op "    %[old__],%[val__],%[ptr__]\n"			\
+		: [old__] "=d" (old__), [ptr__] "+Q" (*ptr__)		\
+		: [val__] "d" (val__)					\
+		: "cc");						\
+	preempt_enable();						\
+	old__ + val__;							\
+})
+
+#define this_cpu_add_return_4(pcp, val) arch_this_cpu_add_return(pcp, val, "laa")
+#define this_cpu_add_return_8(pcp, val) arch_this_cpu_add_return(pcp, val, "laag")
+
+#define arch_this_cpu_to_op(pcp, val, op)				\
+{									\
+	typedef typeof(pcp) pcp_op_T__; 				\
+	pcp_op_T__ val__ = (val);					\
+	pcp_op_T__ old__, *ptr__;					\
+	preempt_disable();						\
+	ptr__ = __this_cpu_ptr(&(pcp)); 				\
+	asm volatile(							\
+		op "    %[old__],%[val__],%[ptr__]\n"			\
+		: [old__] "=d" (old__), [ptr__] "+Q" (*ptr__)		\
+		: [val__] "d" (val__)					\
+		: "cc");						\
+	preempt_enable();						\
+}
+
+#define this_cpu_and_4(pcp, val)	arch_this_cpu_to_op(pcp, val, "lan")
+#define this_cpu_and_8(pcp, val)	arch_this_cpu_to_op(pcp, val, "lang")
+#define this_cpu_or_4(pcp, val)		arch_this_cpu_to_op(pcp, val, "lao")
+#define this_cpu_or_8(pcp, val)		arch_this_cpu_to_op(pcp, val, "laog")
+
+#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */
 
 #define arch_this_cpu_cmpxchg(pcp, oval, nval)				\
 ({									\
@@ -74,13 +139,7 @@
 	pcp_op_T__ *ptr__;						\
 	preempt_disable();						\
 	ptr__ = __this_cpu_ptr(&(pcp));					\
-	switch (sizeof(*ptr__)) {					\
-	case 8:								\
-		ret__ = cmpxchg64(ptr__, oval, nval);			\
-		break;							\
-	default:							\
-		ret__ = cmpxchg(ptr__, oval, nval);			\
-	}								\
+	ret__ = cmpxchg(ptr__, oval, nval);				\
 	preempt_enable();						\
 	ret__;								\
 })
@@ -104,9 +163,7 @@
 #define this_cpu_xchg_1(pcp, nval) arch_this_cpu_xchg(pcp, nval)
 #define this_cpu_xchg_2(pcp, nval) arch_this_cpu_xchg(pcp, nval)
 #define this_cpu_xchg_4(pcp, nval) arch_this_cpu_xchg(pcp, nval)
-#ifdef CONFIG_64BIT
 #define this_cpu_xchg_8(pcp, nval) arch_this_cpu_xchg(pcp, nval)
-#endif
 
 #define arch_this_cpu_cmpxchg_double(pcp1, pcp2, o1, o2, n1, n2)	\
 ({									\
@@ -124,9 +181,9 @@
 })
 
 #define this_cpu_cmpxchg_double_4 arch_this_cpu_cmpxchg_double
-#ifdef CONFIG_64BIT
 #define this_cpu_cmpxchg_double_8 arch_this_cpu_cmpxchg_double
-#endif
+
+#endif /* CONFIG_64BIT */
 
 #include <asm-generic/percpu.h>
 
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 9b60a36..2204400 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -748,7 +748,9 @@
 
 static inline void pgste_set_pte(pte_t *ptep, pte_t entry)
 {
-	if (!MACHINE_HAS_ESOP && (pte_val(entry) & _PAGE_WRITE)) {
+	if (!MACHINE_HAS_ESOP &&
+	    (pte_val(entry) & _PAGE_PRESENT) &&
+	    (pte_val(entry) & _PAGE_WRITE)) {
 		/*
 		 * Without enhanced suppression-on-protection force
 		 * the dirty bit on for all writable ptes.
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index ca7821f..0a876bc 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -134,19 +134,17 @@
  * Do necessary setup to start up a new thread.
  */
 #define start_thread(regs, new_psw, new_stackp) do {			\
-	regs->psw.mask	= psw_user_bits | PSW_MASK_EA | PSW_MASK_BA;	\
+	regs->psw.mask	= PSW_USER_BITS | PSW_MASK_EA | PSW_MASK_BA;	\
 	regs->psw.addr	= new_psw | PSW_ADDR_AMODE;			\
 	regs->gprs[15]	= new_stackp;					\
 	execve_tail();							\
 } while (0)
 
 #define start_thread31(regs, new_psw, new_stackp) do {			\
-	regs->psw.mask	= psw_user_bits | PSW_MASK_BA;			\
+	regs->psw.mask	= PSW_USER_BITS | PSW_MASK_BA;			\
 	regs->psw.addr	= new_psw | PSW_ADDR_AMODE;			\
 	regs->gprs[15]	= new_stackp;					\
-	__tlb_flush_mm(current->mm);					\
 	crst_table_downgrade(current->mm, 1UL << 31);			\
-	update_mm(current->mm, current);				\
 	execve_tail();							\
 } while (0)
 
@@ -169,17 +167,15 @@
  */
 extern unsigned long thread_saved_pc(struct task_struct *t);
 
-extern void show_code(struct pt_regs *regs);
-extern void print_fn_code(unsigned char *code, unsigned long len);
-extern int insn_to_mnemonic(unsigned char *instruction, char *buf,
-			    unsigned int len);
-
 unsigned long get_wchan(struct task_struct *p);
 #define task_pt_regs(tsk) ((struct pt_regs *) \
         (task_stack_page(tsk) + THREAD_SIZE) - 1)
 #define KSTK_EIP(tsk)	(task_pt_regs(tsk)->psw.addr)
 #define KSTK_ESP(tsk)	(task_pt_regs(tsk)->gprs[15])
 
+/* Has task runtime instrumentation enabled ? */
+#define is_ri_task(tsk) (!!(tsk)->thread.ri_cb)
+
 static inline unsigned short stap(void)
 {
 	unsigned short cpu_address;
@@ -348,9 +344,9 @@
 }
 
 #define local_mcck_enable() \
-	__set_psw_mask(psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK)
+	__set_psw_mask(PSW_KERNEL_BITS | PSW_MASK_DAT | PSW_MASK_MCHECK)
 #define local_mcck_disable() \
-	__set_psw_mask(psw_kernel_bits | PSW_MASK_DAT)
+	__set_psw_mask(PSW_KERNEL_BITS | PSW_MASK_DAT)
 
 /*
  * Basic Machine Check/Program Check Handler.
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index 52b5653..9c82ceb 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -10,8 +10,11 @@
 
 #ifndef __ASSEMBLY__
 
-extern long psw_kernel_bits;
-extern long psw_user_bits;
+#define PSW_KERNEL_BITS	(PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_ASC_HOME | \
+			 PSW_MASK_EA | PSW_MASK_BA)
+#define PSW_USER_BITS	(PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | \
+			 PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_MCHECK | \
+			 PSW_MASK_PSTATE | PSW_ASC_PRIMARY)
 
 /*
  * The pt_regs struct defines the way the registers are stored on
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index 59880dba..df802ee 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -48,13 +48,6 @@
 void create_mem_hole(struct mem_chunk mem_chunk[], unsigned long addr,
 		     unsigned long size);
 
-#define PRIMARY_SPACE_MODE	0
-#define ACCESS_REGISTER_MODE	1
-#define SECONDARY_SPACE_MODE	2
-#define HOME_SPACE_MODE		3
-
-extern unsigned int s390_user_mode;
-
 /*
  * Machine features detected in head.S
  */
diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h
index b64f15c..ac9bed8 100644
--- a/arch/s390/include/asm/smp.h
+++ b/arch/s390/include/asm/smp.h
@@ -14,7 +14,6 @@
 #define raw_smp_processor_id()	(S390_lowcore.cpu_nr)
 
 extern struct mutex smp_cpu_state_mutex;
-extern struct save_area *zfcpdump_save_areas[NR_CPUS + 1];
 
 extern int __cpu_up(unsigned int cpu, struct task_struct *tidle);
 
diff --git a/arch/s390/include/asm/switch_to.h b/arch/s390/include/asm/switch_to.h
index 6dbd5597..29c81f8 100644
--- a/arch/s390/include/asm/switch_to.h
+++ b/arch/s390/include/asm/switch_to.h
@@ -13,58 +13,94 @@
 extern struct task_struct *__switch_to(void *, void *);
 extern void update_cr_regs(struct task_struct *task);
 
-static inline void save_fp_regs(s390_fp_regs *fpregs)
+static inline int test_fp_ctl(u32 fpc)
 {
-	asm volatile(
-		"	std	0,%O0+8(%R0)\n"
-		"	std	2,%O0+24(%R0)\n"
-		"	std	4,%O0+40(%R0)\n"
-		"	std	6,%O0+56(%R0)"
-		: "=Q" (*fpregs) : "Q" (*fpregs));
+	u32 orig_fpc;
+	int rc;
+
 	if (!MACHINE_HAS_IEEE)
-		return;
+		return 0;
+
 	asm volatile(
-		"	stfpc	%0\n"
-		"	std	1,%O0+16(%R0)\n"
-		"	std	3,%O0+32(%R0)\n"
-		"	std	5,%O0+48(%R0)\n"
-		"	std	7,%O0+64(%R0)\n"
-		"	std	8,%O0+72(%R0)\n"
-		"	std	9,%O0+80(%R0)\n"
-		"	std	10,%O0+88(%R0)\n"
-		"	std	11,%O0+96(%R0)\n"
-		"	std	12,%O0+104(%R0)\n"
-		"	std	13,%O0+112(%R0)\n"
-		"	std	14,%O0+120(%R0)\n"
-		"	std	15,%O0+128(%R0)\n"
-		: "=Q" (*fpregs) : "Q" (*fpregs));
+		"	efpc    %1\n"
+		"	sfpc	%2\n"
+		"0:	sfpc	%1\n"
+		"	la	%0,0\n"
+		"1:\n"
+		EX_TABLE(0b,1b)
+		: "=d" (rc), "=d" (orig_fpc)
+		: "d" (fpc), "0" (-EINVAL));
+	return rc;
 }
 
-static inline void restore_fp_regs(s390_fp_regs *fpregs)
+static inline void save_fp_ctl(u32 *fpc)
 {
-	asm volatile(
-		"	ld	0,%O0+8(%R0)\n"
-		"	ld	2,%O0+24(%R0)\n"
-		"	ld	4,%O0+40(%R0)\n"
-		"	ld	6,%O0+56(%R0)"
-		: : "Q" (*fpregs));
 	if (!MACHINE_HAS_IEEE)
 		return;
+
 	asm volatile(
-		"	lfpc	%0\n"
-		"	ld	1,%O0+16(%R0)\n"
-		"	ld	3,%O0+32(%R0)\n"
-		"	ld	5,%O0+48(%R0)\n"
-		"	ld	7,%O0+64(%R0)\n"
-		"	ld	8,%O0+72(%R0)\n"
-		"	ld	9,%O0+80(%R0)\n"
-		"	ld	10,%O0+88(%R0)\n"
-		"	ld	11,%O0+96(%R0)\n"
-		"	ld	12,%O0+104(%R0)\n"
-		"	ld	13,%O0+112(%R0)\n"
-		"	ld	14,%O0+120(%R0)\n"
-		"	ld	15,%O0+128(%R0)\n"
-		: : "Q" (*fpregs));
+		"       stfpc   %0\n"
+		: "+Q" (*fpc));
+}
+
+static inline int restore_fp_ctl(u32 *fpc)
+{
+	int rc;
+
+	if (!MACHINE_HAS_IEEE)
+		return 0;
+
+	asm volatile(
+		"0:	lfpc    %1\n"
+		"	la	%0,0\n"
+		"1:\n"
+		EX_TABLE(0b,1b)
+		: "=d" (rc) : "Q" (*fpc), "0" (-EINVAL));
+	return rc;
+}
+
+static inline void save_fp_regs(freg_t *fprs)
+{
+	asm volatile("std 0,%0" : "=Q" (fprs[0]));
+	asm volatile("std 2,%0" : "=Q" (fprs[2]));
+	asm volatile("std 4,%0" : "=Q" (fprs[4]));
+	asm volatile("std 6,%0" : "=Q" (fprs[6]));
+	if (!MACHINE_HAS_IEEE)
+		return;
+	asm volatile("std 1,%0" : "=Q" (fprs[1]));
+	asm volatile("std 3,%0" : "=Q" (fprs[3]));
+	asm volatile("std 5,%0" : "=Q" (fprs[5]));
+	asm volatile("std 7,%0" : "=Q" (fprs[7]));
+	asm volatile("std 8,%0" : "=Q" (fprs[8]));
+	asm volatile("std 9,%0" : "=Q" (fprs[9]));
+	asm volatile("std 10,%0" : "=Q" (fprs[10]));
+	asm volatile("std 11,%0" : "=Q" (fprs[11]));
+	asm volatile("std 12,%0" : "=Q" (fprs[12]));
+	asm volatile("std 13,%0" : "=Q" (fprs[13]));
+	asm volatile("std 14,%0" : "=Q" (fprs[14]));
+	asm volatile("std 15,%0" : "=Q" (fprs[15]));
+}
+
+static inline void restore_fp_regs(freg_t *fprs)
+{
+	asm volatile("ld 0,%0" : : "Q" (fprs[0]));
+	asm volatile("ld 2,%0" : : "Q" (fprs[2]));
+	asm volatile("ld 4,%0" : : "Q" (fprs[4]));
+	asm volatile("ld 6,%0" : : "Q" (fprs[6]));
+	if (!MACHINE_HAS_IEEE)
+		return;
+	asm volatile("ld 1,%0" : : "Q" (fprs[1]));
+	asm volatile("ld 3,%0" : : "Q" (fprs[3]));
+	asm volatile("ld 5,%0" : : "Q" (fprs[5]));
+	asm volatile("ld 7,%0" : : "Q" (fprs[7]));
+	asm volatile("ld 8,%0" : : "Q" (fprs[8]));
+	asm volatile("ld 9,%0" : : "Q" (fprs[9]));
+	asm volatile("ld 10,%0" : : "Q" (fprs[10]));
+	asm volatile("ld 11,%0" : : "Q" (fprs[11]));
+	asm volatile("ld 12,%0" : : "Q" (fprs[12]));
+	asm volatile("ld 13,%0" : : "Q" (fprs[13]));
+	asm volatile("ld 14,%0" : : "Q" (fprs[14]));
+	asm volatile("ld 15,%0" : : "Q" (fprs[15]));
 }
 
 static inline void save_access_regs(unsigned int *acrs)
@@ -83,12 +119,14 @@
 
 #define switch_to(prev,next,last) do {					\
 	if (prev->mm) {							\
-		save_fp_regs(&prev->thread.fp_regs);			\
+		save_fp_ctl(&prev->thread.fp_regs.fpc);			\
+		save_fp_regs(prev->thread.fp_regs.fprs);		\
 		save_access_regs(&prev->thread.acrs[0]);		\
 		save_ri_cb(prev->thread.ri_cb);				\
 	}								\
 	if (next->mm) {							\
-		restore_fp_regs(&next->thread.fp_regs);			\
+		restore_fp_ctl(&next->thread.fp_regs.fpc);		\
+		restore_fp_regs(next->thread.fp_regs.fprs);		\
 		restore_access_regs(&next->thread.acrs[0]);		\
 		restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb);	\
 		update_cr_regs(next);					\
diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h
index 8ad8af9..8beee1c 100644
--- a/arch/s390/include/asm/timex.h
+++ b/arch/s390/include/asm/timex.h
@@ -71,30 +71,32 @@
 
 typedef unsigned long long cycles_t;
 
+static inline void get_tod_clock_ext(char clk[16])
+{
+	typedef struct { char _[sizeof(clk)]; } addrtype;
+
+	asm volatile("stcke %0" : "=Q" (*(addrtype *) clk) : : "cc");
+}
+
 static inline unsigned long long get_tod_clock(void)
 {
-	unsigned long long clk;
-
-#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES
-	asm volatile(".insn s,0xb27c0000,%0" : "=Q" (clk) : : "cc");
-#else
-	asm volatile("stck %0" : "=Q" (clk) : : "cc");
-#endif
-	return clk;
-}
-
-static inline void get_tod_clock_ext(char *clk)
-{
-	asm volatile("stcke %0" : "=Q" (*clk) : : "cc");
-}
-
-static inline unsigned long long get_tod_clock_xt(void)
-{
 	unsigned char clk[16];
 	get_tod_clock_ext(clk);
 	return *((unsigned long long *)&clk[1]);
 }
 
+static inline unsigned long long get_tod_clock_fast(void)
+{
+#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES
+	unsigned long long clk;
+
+	asm volatile("stckf %0" : "=Q" (clk) : : "cc");
+	return clk;
+#else
+	return get_tod_clock();
+#endif
+}
+
 static inline cycles_t get_cycles(void)
 {
 	return (cycles_t) get_tod_clock() >> 2;
@@ -125,7 +127,7 @@
  */
 static inline unsigned long long get_tod_clock_monotonic(void)
 {
-	return get_tod_clock_xt() - sched_clock_base_cc;
+	return get_tod_clock() - sched_clock_base_cc;
 }
 
 /**
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
index 9c33ed4..79330af 100644
--- a/arch/s390/include/asm/uaccess.h
+++ b/arch/s390/include/asm/uaccess.h
@@ -94,9 +94,7 @@
 
 struct uaccess_ops {
 	size_t (*copy_from_user)(size_t, const void __user *, void *);
-	size_t (*copy_from_user_small)(size_t, const void __user *, void *);
 	size_t (*copy_to_user)(size_t, void __user *, const void *);
-	size_t (*copy_to_user_small)(size_t, void __user *, const void *);
 	size_t (*copy_in_user)(size_t, void __user *, const void __user *);
 	size_t (*clear_user)(size_t, void __user *);
 	size_t (*strnlen_user)(size_t, const char __user *);
@@ -106,22 +104,20 @@
 };
 
 extern struct uaccess_ops uaccess;
-extern struct uaccess_ops uaccess_std;
 extern struct uaccess_ops uaccess_mvcos;
-extern struct uaccess_ops uaccess_mvcos_switch;
 extern struct uaccess_ops uaccess_pt;
 
 extern int __handle_fault(unsigned long, unsigned long, int);
 
 static inline int __put_user_fn(size_t size, void __user *ptr, void *x)
 {
-	size = uaccess.copy_to_user_small(size, ptr, x);
+	size = uaccess.copy_to_user(size, ptr, x);
 	return size ? -EFAULT : size;
 }
 
 static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
 {
-	size = uaccess.copy_from_user_small(size, ptr, x);
+	size = uaccess.copy_from_user(size, ptr, x);
 	return size ? -EFAULT : size;
 }
 
@@ -226,10 +222,7 @@
 static inline unsigned long __must_check
 __copy_to_user(void __user *to, const void *from, unsigned long n)
 {
-	if (__builtin_constant_p(n) && (n <= 256))
-		return uaccess.copy_to_user_small(n, to, from);
-	else
-		return uaccess.copy_to_user(n, to, from);
+	return uaccess.copy_to_user(n, to, from);
 }
 
 #define __copy_to_user_inatomic __copy_to_user
@@ -275,10 +268,7 @@
 static inline unsigned long __must_check
 __copy_from_user(void *to, const void __user *from, unsigned long n)
 {
-	if (__builtin_constant_p(n) && (n <= 256))
-		return uaccess.copy_from_user_small(n, from, to);
-	else
-		return uaccess.copy_from_user(n, from, to);
+	return uaccess.copy_from_user(n, from, to);
 }
 
 extern void copy_from_user_overflow(void)
diff --git a/arch/s390/include/uapi/asm/ptrace.h b/arch/s390/include/uapi/asm/ptrace.h
index 7a84619..7e0b498 100644
--- a/arch/s390/include/uapi/asm/ptrace.h
+++ b/arch/s390/include/uapi/asm/ptrace.h
@@ -199,6 +199,7 @@
 typedef struct
 {
 	__u32   fpc;
+	__u32	pad;
 	freg_t  fprs[NUM_FPRS];              
 } s390_fp_regs;
 
@@ -206,7 +207,6 @@
 #define FPC_FLAGS_MASK          0x00F80000
 #define FPC_DXC_MASK            0x0000FF00
 #define FPC_RM_MASK             0x00000003
-#define FPC_VALID_MASK          0xF8F8FF03
 
 /* this typedef defines how a Program Status Word looks like */
 typedef struct 
@@ -263,7 +263,7 @@
 #define PSW_MASK_EA		0x0000000100000000UL
 #define PSW_MASK_BA		0x0000000080000000UL
 
-#define PSW_MASK_USER		0x0000FF8180000000UL
+#define PSW_MASK_USER		0x0000FF0180000000UL
 
 #define PSW_ADDR_AMODE		0x0000000000000000UL
 #define PSW_ADDR_INSN		0xFFFFFFFFFFFFFFFFUL
diff --git a/arch/s390/include/uapi/asm/sigcontext.h b/arch/s390/include/uapi/asm/sigcontext.h
index 584787f..b30de9c 100644
--- a/arch/s390/include/uapi/asm/sigcontext.h
+++ b/arch/s390/include/uapi/asm/sigcontext.h
@@ -49,6 +49,7 @@
 typedef struct
 {
 	unsigned int fpc;
+	unsigned int pad;
 	double   fprs[__NUM_FPRS];
 } _s390_fp_regs;
 
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 4bb2a46..2403303 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -28,7 +28,7 @@
 
 CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
 
-obj-y	:= bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o
+obj-y	:= traps.o time.o process.o base.o early.o setup.o vtime.o
 obj-y	+= processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o
 obj-y	+= debug.o irq.o ipl.o dis.o diag.o sclp.o vdso.o
 obj-y	+= sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
diff --git a/arch/s390/kernel/bitmap.c b/arch/s390/kernel/bitmap.c
deleted file mode 100644
index 102da5e..0000000
--- a/arch/s390/kernel/bitmap.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *    Bitmaps for set_bit, clear_bit, test_and_set_bit, ...
- *    See include/asm/{bitops.h|posix_types.h} for details
- *
- *    Copyright IBM Corp. 1999, 2009
- *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
- */
-
-#include <linux/bitops.h>
-#include <linux/module.h>
-
-const char _oi_bitmap[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
-EXPORT_SYMBOL(_oi_bitmap);
-
-const char _ni_bitmap[] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f };
-EXPORT_SYMBOL(_ni_bitmap);
-
-const char _zb_findmap[] = {
-	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
-	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
-	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
-	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,
-	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
-	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
-	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
-	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,
-	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
-	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
-	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
-	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,
-	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
-	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
-	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
-	0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8 };
-EXPORT_SYMBOL(_zb_findmap);
-
-const char _sb_findmap[] = {
-	8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-	5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-	6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-	5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-	7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-	5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-	6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-	5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
-	4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };
-EXPORT_SYMBOL(_sb_findmap);
diff --git a/arch/s390/kernel/cache.c b/arch/s390/kernel/cache.c
index dd62071..3a414c0 100644
--- a/arch/s390/kernel/cache.c
+++ b/arch/s390/kernel/cache.c
@@ -146,15 +146,14 @@
 	ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0);
 	for (level = 0; level < CACHE_MAX_LEVEL; level++) {
 		switch (ct.ci[level].scope) {
-		case CACHE_SCOPE_NOTEXISTS:
-		case CACHE_SCOPE_RESERVED:
-			return;
 		case CACHE_SCOPE_SHARED:
 			private = 0;
 			break;
 		case CACHE_SCOPE_PRIVATE:
 			private = 1;
 			break;
+		default:
+			return;
 		}
 		if (ct.ci[level].type == CACHE_TYPE_SEPARATE) {
 			rc  = cache_add(level, private, CACHE_TYPE_DATA);
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 1f1b8c7..e030d2b 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -58,10 +58,6 @@
 
 #include "compat_linux.h"
 
-u32 psw32_user_bits = PSW32_MASK_DAT | PSW32_MASK_IO | PSW32_MASK_EXT |
-		      PSW32_DEFAULT_KEY | PSW32_MASK_BASE | PSW32_MASK_MCHECK |
-		      PSW32_MASK_PSTATE | PSW32_ASC_HOME;
- 
 /* For this source file, we want overflow handling. */
 
 #undef high2lowuid
diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
index 976518c..1bfda3e 100644
--- a/arch/s390/kernel/compat_linux.h
+++ b/arch/s390/kernel/compat_linux.h
@@ -27,6 +27,7 @@
 typedef struct
 {
 	unsigned int	fpc;
+	unsigned int	pad;
 	freg_t32	fprs[__NUM_FPRS];              
 } _s390_fp_regs32;
 
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index 44b2526..6e24429 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -99,7 +99,7 @@
 			break;
 		}
 	}
-	return err;
+	return err ? -EFAULT : 0;
 }
 
 int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
@@ -148,62 +148,71 @@
 			break;
 		}
 	}
-	return err;
+	return err ? -EFAULT : 0;
 }
 
 static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
 {
-	_s390_regs_common32 regs32;
-	int err, i;
+	_sigregs32 user_sregs;
+	int i;
 
-	regs32.psw.mask = psw32_user_bits |
-		((__u32)(regs->psw.mask >> 32) & PSW32_MASK_USER);
-	regs32.psw.addr = (__u32) regs->psw.addr |
+	user_sregs.regs.psw.mask = (__u32)(regs->psw.mask >> 32);
+	user_sregs.regs.psw.mask &= PSW32_MASK_USER | PSW32_MASK_RI;
+	user_sregs.regs.psw.mask |= PSW32_USER_BITS;
+	user_sregs.regs.psw.addr = (__u32) regs->psw.addr |
 		(__u32)(regs->psw.mask & PSW_MASK_BA);
 	for (i = 0; i < NUM_GPRS; i++)
-		regs32.gprs[i] = (__u32) regs->gprs[i];
+		user_sregs.regs.gprs[i] = (__u32) regs->gprs[i];
 	save_access_regs(current->thread.acrs);
-	memcpy(regs32.acrs, current->thread.acrs, sizeof(regs32.acrs));
-	err = __copy_to_user(&sregs->regs, &regs32, sizeof(regs32));
-	if (err)
-		return err;
-	save_fp_regs(&current->thread.fp_regs);
-	/* s390_fp_regs and _s390_fp_regs32 are the same ! */
-	return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
-			      sizeof(_s390_fp_regs32));
+	memcpy(&user_sregs.regs.acrs, current->thread.acrs,
+	       sizeof(user_sregs.regs.acrs));
+	save_fp_ctl(&current->thread.fp_regs.fpc);
+	save_fp_regs(current->thread.fp_regs.fprs);
+	memcpy(&user_sregs.fpregs, &current->thread.fp_regs,
+	       sizeof(user_sregs.fpregs));
+	if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs32)))
+		return -EFAULT;
+	return 0;
 }
 
 static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
 {
-	_s390_regs_common32 regs32;
-	int err, i;
+	_sigregs32 user_sregs;
+	int i;
 
 	/* Alwys make any pending restarted system call return -EINTR */
 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
 
-	err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
-	if (err)
-		return err;
+	if (__copy_from_user(&user_sregs, &sregs->regs, sizeof(user_sregs)))
+		return -EFAULT;
+
+	if (!is_ri_task(current) && (user_sregs.regs.psw.mask & PSW32_MASK_RI))
+		return -EINVAL;
+
+	/* Loading the floating-point-control word can fail. Do that first. */
+	if (restore_fp_ctl(&user_sregs.fpregs.fpc))
+		return -EINVAL;
+
+	/* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */
 	regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
-		(__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 |
-		(__u64)(regs32.psw.addr & PSW32_ADDR_AMODE);
+		(__u64)(user_sregs.regs.psw.mask & PSW32_MASK_USER) << 32 |
+		(__u64)(user_sregs.regs.psw.mask & PSW32_MASK_RI) << 32 |
+		(__u64)(user_sregs.regs.psw.addr & PSW32_ADDR_AMODE);
 	/* Check for invalid user address space control. */
-	if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
-		regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
+	if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_HOME)
+		regs->psw.mask = PSW_ASC_PRIMARY |
 			(regs->psw.mask & ~PSW_MASK_ASC);
-	regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
+	regs->psw.addr = (__u64)(user_sregs.regs.psw.addr & PSW32_ADDR_INSN);
 	for (i = 0; i < NUM_GPRS; i++)
-		regs->gprs[i] = (__u64) regs32.gprs[i];
-	memcpy(current->thread.acrs, regs32.acrs, sizeof(current->thread.acrs));
+		regs->gprs[i] = (__u64) user_sregs.regs.gprs[i];
+	memcpy(&current->thread.acrs, &user_sregs.regs.acrs,
+	       sizeof(current->thread.acrs));
 	restore_access_regs(current->thread.acrs);
 
-	err = __copy_from_user(&current->thread.fp_regs, &sregs->fpregs,
-			       sizeof(_s390_fp_regs32));
-	current->thread.fp_regs.fpc &= FPC_VALID_MASK;
-	if (err)
-		return err;
+	memcpy(&current->thread.fp_regs, &user_sregs.fpregs,
+	       sizeof(current->thread.fp_regs));
 
-	restore_fp_regs(&current->thread.fp_regs);
+	restore_fp_regs(current->thread.fp_regs.fprs);
 	clear_thread_flag(TIF_SYSCALL);	/* No longer in a system call */
 	return 0;
 }
@@ -215,18 +224,18 @@
 
 	for (i = 0; i < NUM_GPRS; i++)
 		gprs_high[i] = regs->gprs[i] >> 32;
-
-	return __copy_to_user(uregs, &gprs_high, sizeof(gprs_high));
+	if (__copy_to_user(uregs, &gprs_high, sizeof(gprs_high)))
+		return -EFAULT;
+	return 0;
 }
 
 static int restore_sigregs_gprs_high(struct pt_regs *regs, __u32 __user *uregs)
 {
 	__u32 gprs_high[NUM_GPRS];
-	int err, i;
+	int i;
 
-	err = __copy_from_user(&gprs_high, uregs, sizeof(gprs_high));
-	if (err)
-		return err;
+	if (__copy_from_user(&gprs_high, uregs, sizeof(gprs_high)))
+		return -EFAULT;
 	for (i = 0; i < NUM_GPRS; i++)
 		*(__u32 *)&regs->gprs[i] = gprs_high[i];
 	return 0;
@@ -348,7 +357,7 @@
 	regs->gprs[15] = (__force __u64) frame;
 	/* Force 31 bit amode and default user address space control. */
 	regs->psw.mask = PSW_MASK_BA |
-		(psw_user_bits & PSW_MASK_ASC) |
+		(PSW_USER_BITS & PSW_MASK_ASC) |
 		(regs->psw.mask & ~PSW_MASK_ASC);
 	regs->psw.addr = (__force __u64) ka->sa.sa_handler;
 
@@ -415,7 +424,7 @@
 	regs->gprs[15] = (__force __u64) frame;
 	/* Force 31 bit amode and default user address space control. */
 	regs->psw.mask = PSW_MASK_BA |
-		(psw_user_bits & PSW_MASK_ASC) |
+		(PSW_USER_BITS & PSW_MASK_ASC) |
 		(regs->psw.mask & ~PSW_MASK_ASC);
 	regs->psw.addr = (__u64 __force) ka->sa.sa_handler;
 
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c
index c84f33d..f45b2ab 100644
--- a/arch/s390/kernel/crash_dump.c
+++ b/arch/s390/kernel/crash_dump.c
@@ -22,6 +22,32 @@
 #define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
 #define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y))))
 
+struct dump_save_areas dump_save_areas;
+
+/*
+ * Allocate and add a save area for a CPU
+ */
+struct save_area *dump_save_area_create(int cpu)
+{
+	struct save_area **save_areas, *save_area;
+
+	save_area = kmalloc(sizeof(*save_area), GFP_KERNEL);
+	if (!save_area)
+		return NULL;
+	if (cpu + 1 > dump_save_areas.count) {
+		dump_save_areas.count = cpu + 1;
+		save_areas = krealloc(dump_save_areas.areas,
+				      dump_save_areas.count * sizeof(void *),
+				      GFP_KERNEL | __GFP_ZERO);
+		if (!save_areas) {
+			kfree(save_area);
+			return NULL;
+		}
+		dump_save_areas.areas = save_areas;
+	}
+	dump_save_areas.areas[cpu] = save_area;
+	return save_area;
+}
 
 /*
  * Return physical address for virtual address
@@ -40,28 +66,25 @@
 }
 
 /*
- * Copy up to one page to vmalloc or real memory
+ * Copy real to virtual or real memory
  */
-static ssize_t copy_page_real(void *buf, void *src, size_t csize)
+static int copy_from_realmem(void *dest, void *src, size_t count)
 {
-	size_t size;
+	unsigned long size;
 
-	if (is_vmalloc_addr(buf)) {
-		BUG_ON(csize >= PAGE_SIZE);
-		/* If buf is not page aligned, copy first part */
-		size = min(roundup(__pa(buf), PAGE_SIZE) - __pa(buf), csize);
-		if (size) {
-			if (memcpy_real(load_real_addr(buf), src, size))
-				return -EFAULT;
-			buf += size;
-			src += size;
-		}
-		/* Copy second part */
-		size = csize - size;
-		return (size) ? memcpy_real(load_real_addr(buf), src, size) : 0;
-	} else {
-		return memcpy_real(buf, src, csize);
-	}
+	if (!count)
+		return 0;
+	if (!is_vmalloc_or_module_addr(dest))
+		return memcpy_real(dest, src, count);
+	do {
+		size = min(count, PAGE_SIZE - (__pa(dest) & ~PAGE_MASK));
+		if (memcpy_real(load_real_addr(dest), src, size))
+			return -EFAULT;
+		count -= size;
+		dest += size;
+		src += size;
+	} while (count);
+	return 0;
 }
 
 /*
@@ -114,7 +137,7 @@
 		rc = copy_to_user_real((void __force __user *) buf,
 				       (void *) src, csize);
 	else
-		rc = copy_page_real(buf, (void *) src, csize);
+		rc = copy_from_realmem(buf, (void *) src, csize);
 	return (rc == 0) ? rc : csize;
 }
 
@@ -210,7 +233,7 @@
 	if (OLDMEM_BASE) {
 		if ((unsigned long) src < OLDMEM_SIZE) {
 			copied = min(count, OLDMEM_SIZE - (unsigned long) src);
-			rc = memcpy_real(dest, src + OLDMEM_BASE, copied);
+			rc = copy_from_realmem(dest, src + OLDMEM_BASE, copied);
 			if (rc)
 				return rc;
 		}
@@ -223,7 +246,7 @@
 				return rc;
 		}
 	}
-	return memcpy_real(dest + copied, src + copied, count - copied);
+	return copy_from_realmem(dest + copied, src + copied, count - copied);
 }
 
 /*
@@ -453,8 +476,8 @@
 {
 	int i, cpus = 0;
 
-	for (i = 0; zfcpdump_save_areas[i]; i++) {
-		if (zfcpdump_save_areas[i]->pref_reg == 0)
+	for (i = 0; i < dump_save_areas.count; i++) {
+		if (dump_save_areas.areas[i]->pref_reg == 0)
 			continue;
 		cpus++;
 	}
@@ -525,8 +548,8 @@
 
 	ptr = nt_prpsinfo(ptr);
 
-	for (i = 0; zfcpdump_save_areas[i]; i++) {
-		sa = zfcpdump_save_areas[i];
+	for (i = 0; i < dump_save_areas.count; i++) {
+		sa = dump_save_areas.areas[i];
 		if (sa->pref_reg == 0)
 			continue;
 		ptr = fill_cpu_elf_notes(ptr, sa);
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index f1279dc..ee8390d 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -867,7 +867,7 @@
 debug_finish_entry(debug_info_t * id, debug_entry_t* active, int level,
 			int exception)
 {
-	active->id.stck = get_tod_clock();
+	active->id.stck = get_tod_clock_fast();
 	active->id.fields.cpuid = smp_processor_id();
 	active->caller = __builtin_return_address(0);
 	active->id.fields.exception = exception;
@@ -889,7 +889,7 @@
  * if debug_active is already off
  */
 static int
-s390dbf_procactive(ctl_table *table, int write,
+s390dbf_procactive(struct ctl_table *table, int write,
                      void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	if (!write || debug_stoppable || !debug_active)
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c
index be87d3e..993efe6 100644
--- a/arch/s390/kernel/dis.c
+++ b/arch/s390/kernel/dis.c
@@ -23,6 +23,7 @@
 #include <linux/kdebug.h>
 
 #include <asm/uaccess.h>
+#include <asm/dis.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
 #include <asm/mathemu.h>
@@ -37,17 +38,6 @@
 #define ONELONG "%016lx: "
 #endif /* CONFIG_64BIT */
 
-#define OPERAND_GPR	0x1	/* Operand printed as %rx */
-#define OPERAND_FPR	0x2	/* Operand printed as %fx */
-#define OPERAND_AR	0x4	/* Operand printed as %ax */
-#define OPERAND_CR	0x8	/* Operand printed as %cx */
-#define OPERAND_DISP	0x10	/* Operand printed as displacement */
-#define OPERAND_BASE	0x20	/* Operand printed as base register */
-#define OPERAND_INDEX	0x40	/* Operand printed as index register */
-#define OPERAND_PCREL	0x80	/* Operand printed as pc-relative symbol */
-#define OPERAND_SIGNED	0x100	/* Operand printed as signed value */
-#define OPERAND_LENGTH	0x200	/* Operand printed as length (+1) */
-
 enum {
 	UNUSED,	/* Indicates the end of the operand list */
 	R_8,	/* GPR starting at position 8 */
@@ -155,19 +145,7 @@
 	INSTR_S_00, INSTR_S_RD,
 };
 
-struct operand {
-	int bits;		/* The number of bits in the operand. */
-	int shift;		/* The number of bits to shift. */
-	int flags;		/* One bit syntax flags. */
-};
-
-struct insn {
-	const char name[5];
-	unsigned char opfrag;
-	unsigned char format;
-};
-
-static const struct operand operands[] =
+static const struct s390_operand operands[] =
 {
 	[UNUSED]  = { 0, 0, 0 },
 	[R_8]	 = {  4,  8, OPERAND_GPR },
@@ -479,7 +457,7 @@
 	[LONG_INSN_PCISTB] = "pcistb",
 };
 
-static struct insn opcode[] = {
+static struct s390_insn opcode[] = {
 #ifdef CONFIG_64BIT
 	{ "bprp", 0xc5, INSTR_MII_UPI },
 	{ "bpp", 0xc7, INSTR_SMI_U0RDP },
@@ -668,7 +646,7 @@
 	{ "", 0, INSTR_INVALID }
 };
 
-static struct insn opcode_01[] = {
+static struct s390_insn opcode_01[] = {
 #ifdef CONFIG_64BIT
 	{ "ptff", 0x04, INSTR_E },
 	{ "pfpo", 0x0a, INSTR_E },
@@ -684,7 +662,7 @@
 	{ "", 0, INSTR_INVALID }
 };
 
-static struct insn opcode_a5[] = {
+static struct s390_insn opcode_a5[] = {
 #ifdef CONFIG_64BIT
 	{ "iihh", 0x00, INSTR_RI_RU },
 	{ "iihl", 0x01, INSTR_RI_RU },
@@ -706,7 +684,7 @@
 	{ "", 0, INSTR_INVALID }
 };
 
-static struct insn opcode_a7[] = {
+static struct s390_insn opcode_a7[] = {
 #ifdef CONFIG_64BIT
 	{ "tmhh", 0x02, INSTR_RI_RU },
 	{ "tmhl", 0x03, INSTR_RI_RU },
@@ -728,7 +706,7 @@
 	{ "", 0, INSTR_INVALID }
 };
 
-static struct insn opcode_aa[] = {
+static struct s390_insn opcode_aa[] = {
 #ifdef CONFIG_64BIT
 	{ { 0, LONG_INSN_RINEXT }, 0x00, INSTR_RI_RI },
 	{ "rion", 0x01, INSTR_RI_RI },
@@ -739,7 +717,7 @@
 	{ "", 0, INSTR_INVALID }
 };
 
-static struct insn opcode_b2[] = {
+static struct s390_insn opcode_b2[] = {
 #ifdef CONFIG_64BIT
 	{ "stckf", 0x7c, INSTR_S_RD },
 	{ "lpp", 0x80, INSTR_S_RD },
@@ -851,7 +829,7 @@
 	{ "", 0, INSTR_INVALID }
 };
 
-static struct insn opcode_b3[] = {
+static struct s390_insn opcode_b3[] = {
 #ifdef CONFIG_64BIT
 	{ "maylr", 0x38, INSTR_RRF_F0FF },
 	{ "mylr", 0x39, INSTR_RRF_F0FF },
@@ -1034,7 +1012,7 @@
 	{ "", 0, INSTR_INVALID }
 };
 
-static struct insn opcode_b9[] = {
+static struct s390_insn opcode_b9[] = {
 #ifdef CONFIG_64BIT
 	{ "lpgr", 0x00, INSTR_RRE_RR },
 	{ "lngr", 0x01, INSTR_RRE_RR },
@@ -1167,7 +1145,7 @@
 	{ "", 0, INSTR_INVALID }
 };
 
-static struct insn opcode_c0[] = {
+static struct s390_insn opcode_c0[] = {
 #ifdef CONFIG_64BIT
 	{ "lgfi", 0x01, INSTR_RIL_RI },
 	{ "xihf", 0x06, INSTR_RIL_RU },
@@ -1187,7 +1165,7 @@
 	{ "", 0, INSTR_INVALID }
 };
 
-static struct insn opcode_c2[] = {
+static struct s390_insn opcode_c2[] = {
 #ifdef CONFIG_64BIT
 	{ "msgfi", 0x00, INSTR_RIL_RI },
 	{ "msfi", 0x01, INSTR_RIL_RI },
@@ -1205,7 +1183,7 @@
 	{ "", 0, INSTR_INVALID }
 };
 
-static struct insn opcode_c4[] = {
+static struct s390_insn opcode_c4[] = {
 #ifdef CONFIG_64BIT
 	{ "llhrl", 0x02, INSTR_RIL_RP },
 	{ "lghrl", 0x04, INSTR_RIL_RP },
@@ -1222,7 +1200,7 @@
 	{ "", 0, INSTR_INVALID }
 };
 
-static struct insn opcode_c6[] = {
+static struct s390_insn opcode_c6[] = {
 #ifdef CONFIG_64BIT
 	{ "exrl", 0x00, INSTR_RIL_RP },
 	{ "pfdrl", 0x02, INSTR_RIL_UP },
@@ -1240,7 +1218,7 @@
 	{ "", 0, INSTR_INVALID }
 };
 
-static struct insn opcode_c8[] = {
+static struct s390_insn opcode_c8[] = {
 #ifdef CONFIG_64BIT
 	{ "mvcos", 0x00, INSTR_SSF_RRDRD },
 	{ "ectg", 0x01, INSTR_SSF_RRDRD },
@@ -1251,7 +1229,7 @@
 	{ "", 0, INSTR_INVALID }
 };
 
-static struct insn opcode_cc[] = {
+static struct s390_insn opcode_cc[] = {
 #ifdef CONFIG_64BIT
 	{ "brcth", 0x06, INSTR_RIL_RP },
 	{ "aih", 0x08, INSTR_RIL_RI },
@@ -1263,7 +1241,7 @@
 	{ "", 0, INSTR_INVALID }
 };
 
-static struct insn opcode_e3[] = {
+static struct s390_insn opcode_e3[] = {
 #ifdef CONFIG_64BIT
 	{ "ltg", 0x02, INSTR_RXY_RRRD },
 	{ "lrag", 0x03, INSTR_RXY_RRRD },
@@ -1369,7 +1347,7 @@
 	{ "", 0, INSTR_INVALID }
 };
 
-static struct insn opcode_e5[] = {
+static struct s390_insn opcode_e5[] = {
 #ifdef CONFIG_64BIT
 	{ "strag", 0x02, INSTR_SSE_RDRD },
 	{ "mvhhi", 0x44, INSTR_SIL_RDI },
@@ -1391,7 +1369,7 @@
 	{ "", 0, INSTR_INVALID }
 };
 
-static struct insn opcode_eb[] = {
+static struct s390_insn opcode_eb[] = {
 #ifdef CONFIG_64BIT
 	{ "lmg", 0x04, INSTR_RSY_RRRD },
 	{ "srag", 0x0a, INSTR_RSY_RRRD },
@@ -1465,7 +1443,7 @@
 	{ "", 0, INSTR_INVALID }
 };
 
-static struct insn opcode_ec[] = {
+static struct s390_insn opcode_ec[] = {
 #ifdef CONFIG_64BIT
 	{ "brxhg", 0x44, INSTR_RIE_RRP },
 	{ "brxlg", 0x45, INSTR_RIE_RRP },
@@ -1504,7 +1482,7 @@
 	{ "", 0, INSTR_INVALID }
 };
 
-static struct insn opcode_ed[] = {
+static struct s390_insn opcode_ed[] = {
 #ifdef CONFIG_64BIT
 	{ "mayl", 0x38, INSTR_RXF_FRRDF },
 	{ "myl", 0x39, INSTR_RXF_FRRDF },
@@ -1572,7 +1550,7 @@
 
 /* Extracts an operand value from an instruction.  */
 static unsigned int extract_operand(unsigned char *code,
-				    const struct operand *operand)
+				    const struct s390_operand *operand)
 {
 	unsigned int val;
 	int bits;
@@ -1608,16 +1586,11 @@
 	return val;
 }
 
-static inline int insn_length(unsigned char code)
-{
-	return ((((int) code + 64) >> 7) + 1) << 1;
-}
-
-static struct insn *find_insn(unsigned char *code)
+struct s390_insn *find_insn(unsigned char *code)
 {
 	unsigned char opfrag = code[1];
 	unsigned char opmask;
-	struct insn *table;
+	struct s390_insn *table;
 
 	switch (code[0]) {
 	case 0x01:
@@ -1706,7 +1679,7 @@
  */
 int insn_to_mnemonic(unsigned char *instruction, char *buf, unsigned int len)
 {
-	struct insn *insn;
+	struct s390_insn *insn;
 
 	insn = find_insn(instruction);
 	if (!insn)
@@ -1722,9 +1695,9 @@
 
 static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
 {
-	struct insn *insn;
+	struct s390_insn *insn;
 	const unsigned char *ops;
-	const struct operand *operand;
+	const struct s390_operand *operand;
 	unsigned int value;
 	char separator;
 	char *ptr;
diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c
index 99e7f60..e6af940 100644
--- a/arch/s390/kernel/dumpstack.c
+++ b/arch/s390/kernel/dumpstack.c
@@ -15,6 +15,7 @@
 #include <linux/sched.h>
 #include <asm/processor.h>
 #include <asm/debug.h>
+#include <asm/dis.h>
 #include <asm/ipl.h>
 
 #ifndef CONFIG_64BIT
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index dc8770d..96543ac 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -206,6 +206,7 @@
  */
 static noinline __init void init_kernel_storage_key(void)
 {
+#if PAGE_DEFAULT_KEY
 	unsigned long end_pfn, init_pfn;
 
 	end_pfn = PFN_UP(__pa(&_end));
@@ -213,6 +214,7 @@
 	for (init_pfn = 0 ; init_pfn < end_pfn; init_pfn++)
 		page_set_storage_key(init_pfn << PAGE_SHIFT,
 				     PAGE_DEFAULT_KEY, 0);
+#endif
 }
 
 static __initdata char sysinfo_page[PAGE_SIZE] __aligned(PAGE_SIZE);
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index cc30d1f..0dc2b6d 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -266,6 +266,7 @@
 	tm	__TI_flags+3(%r12),_TIF_SYSCALL
 	jno	sysc_return
 	lm	%r2,%r7,__PT_R2(%r11)	# load svc arguments
+	l	%r10,__TI_sysc_table(%r12)	# 31 bit system call table
 	xr	%r8,%r8			# svc 0 returns -ENOSYS
 	clc	__PT_INT_CODE+2(2,%r11),BASED(.Lnr_syscalls+2)
 	jnl	sysc_nr_ok		# invalid svc number -> do svc 0
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
index e9b04c3..cb533f7 100644
--- a/arch/s390/kernel/entry.h
+++ b/arch/s390/kernel/entry.h
@@ -23,7 +23,6 @@
 
 void do_protection_exception(struct pt_regs *regs);
 void do_dat_exception(struct pt_regs *regs);
-void do_asce_exception(struct pt_regs *regs);
 
 void addressing_exception(struct pt_regs *regs);
 void data_exception(struct pt_regs *regs);
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 2b2188b..e5b43c9 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -297,6 +297,7 @@
 	tm	__TI_flags+7(%r12),_TIF_SYSCALL
 	jno	sysc_return
 	lmg	%r2,%r7,__PT_R2(%r11)	# load svc arguments
+	lg	%r10,__TI_sysc_table(%r12)	# address of system call table
 	lghi	%r8,0			# svc 0 returns -ENOSYS
 	llgh	%r1,__PT_INT_CODE+2(%r11)	# load new svc number
 	cghi	%r1,NR_syscalls
diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c
index 1014ad5..224db03 100644
--- a/arch/s390/kernel/ftrace.c
+++ b/arch/s390/kernel/ftrace.c
@@ -151,14 +151,13 @@
 	if (unlikely(atomic_read(&current->tracing_graph_pause)))
 		goto out;
 	ip = (ip & PSW_ADDR_INSN) - MCOUNT_INSN_SIZE;
+	trace.func = ip;
+	trace.depth = current->curr_ret_stack + 1;
+	/* Only trace if the calling function expects to. */
+	if (!ftrace_graph_entry(&trace))
+		goto out;
 	if (ftrace_push_return_trace(parent, ip, &trace.depth, 0) == -EBUSY)
 		goto out;
-	trace.func = ip;
-	/* Only trace if the calling function expects to. */
-	if (!ftrace_graph_entry(&trace)) {
-		current->curr_ret_stack--;
-		goto out;
-	}
 	parent = (unsigned long) return_to_handler;
 out:
 	return parent;
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index fd8db63..429afcc 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -437,7 +437,7 @@
 
 #if defined(CONFIG_64BIT)
 #if defined(CONFIG_MARCH_ZEC12)
-	.long 3, 0xc100efe3, 0xf46ce000, 0x00400000
+	.long 3, 0xc100efe3, 0xf46ce800, 0x00400000
 #elif defined(CONFIG_MARCH_Z196)
 	.long 2, 0xc100efe3, 0xf46c0000
 #elif defined(CONFIG_MARCH_Z10)
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index feb719d..633ca75 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -2051,12 +2051,12 @@
 	__ctl_clear_bit(0,28);
 
 	/* Set new machine check handler */
-	S390_lowcore.mcck_new_psw.mask = psw_kernel_bits | PSW_MASK_DAT;
+	S390_lowcore.mcck_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT;
 	S390_lowcore.mcck_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;
 
 	/* Set new program check handler */
-	S390_lowcore.program_new_psw.mask = psw_kernel_bits | PSW_MASK_DAT;
+	S390_lowcore.program_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT;
 	S390_lowcore.program_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
 
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index 8ac2097..bb27a26 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -157,39 +157,29 @@
 /*
  * Switch to the asynchronous interrupt stack for softirq execution.
  */
-asmlinkage void do_softirq(void)
+void do_softirq_own_stack(void)
 {
-	unsigned long flags, old, new;
+	unsigned long old, new;
 
-	if (in_interrupt())
-		return;
-
-	local_irq_save(flags);
-
-	if (local_softirq_pending()) {
-		/* Get current stack pointer. */
-		asm volatile("la %0,0(15)" : "=a" (old));
-		/* Check against async. stack address range. */
-		new = S390_lowcore.async_stack;
-		if (((new - old) >> (PAGE_SHIFT + THREAD_ORDER)) != 0) {
-			/* Need to switch to the async. stack. */
-			new -= STACK_FRAME_OVERHEAD;
-			((struct stack_frame *) new)->back_chain = old;
-
-			asm volatile("   la    15,0(%0)\n"
-				     "   basr  14,%2\n"
-				     "   la    15,0(%1)\n"
-				     : : "a" (new), "a" (old),
-				         "a" (__do_softirq)
-				     : "0", "1", "2", "3", "4", "5", "14",
-				       "cc", "memory" );
-		} else {
-			/* We are already on the async stack. */
-			__do_softirq();
-		}
+	/* Get current stack pointer. */
+	asm volatile("la %0,0(15)" : "=a" (old));
+	/* Check against async. stack address range. */
+	new = S390_lowcore.async_stack;
+	if (((new - old) >> (PAGE_SHIFT + THREAD_ORDER)) != 0) {
+		/* Need to switch to the async. stack. */
+		new -= STACK_FRAME_OVERHEAD;
+		((struct stack_frame *) new)->back_chain = old;
+		asm volatile("   la    15,0(%0)\n"
+			     "   basr  14,%2\n"
+			     "   la    15,0(%1)\n"
+			     : : "a" (new), "a" (old),
+			         "a" (__do_softirq)
+			     : "0", "1", "2", "3", "4", "5", "14",
+			       "cc", "memory" );
+	} else {
+		/* We are already on the async stack. */
+		__do_softirq();
 	}
-
-	local_irq_restore(flags);
 }
 
 /*
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 0ce9fb2..59a9c35 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -26,11 +26,12 @@
 #include <linux/stop_machine.h>
 #include <linux/kdebug.h>
 #include <linux/uaccess.h>
-#include <asm/cacheflush.h>
-#include <asm/sections.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/hardirq.h>
+#include <asm/cacheflush.h>
+#include <asm/sections.h>
+#include <asm/dis.h>
 
 DEFINE_PER_CPU(struct kprobe *, current_kprobe);
 DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
@@ -59,6 +60,8 @@
 
 static int __kprobes is_prohibited_opcode(kprobe_opcode_t *insn)
 {
+	if (!is_known_insn((unsigned char *)insn))
+		return -EINVAL;
 	switch (insn[0] >> 8) {
 	case 0x0c:	/* bassm */
 	case 0x0b:	/* bsm	 */
@@ -67,6 +70,11 @@
 	case 0xac:	/* stnsm */
 	case 0xad:	/* stosm */
 		return -EINVAL;
+	case 0xc6:
+		switch (insn[0] & 0x0f) {
+		case 0x00: /* exrl   */
+			return -EINVAL;
+		}
 	}
 	switch (insn[0]) {
 	case 0x0101:	/* pr	 */
@@ -180,7 +188,6 @@
 		break;
 	case 0xc6:
 		switch (insn[0] & 0x0f) {
-		case 0x00: /* exrl   */
 		case 0x02: /* pfdrl  */
 		case 0x04: /* cghrl  */
 		case 0x05: /* chrl   */
@@ -204,7 +211,7 @@
 	s64 disp, new_disp;
 	u64 addr, new_addr;
 
-	memcpy(p->ainsn.insn, p->addr, ((p->opcode >> 14) + 3) & -2);
+	memcpy(p->ainsn.insn, p->addr, insn_length(p->opcode >> 8));
 	if (!is_insn_relative_long(p->ainsn.insn))
 		return;
 	/*
@@ -248,7 +255,7 @@
 	p->ainsn.insn = NULL;
 	if (is_kernel_addr(p->addr))
 		p->ainsn.insn = get_dmainsn_slot();
-	if (is_module_addr(p->addr))
+	else if (is_module_addr(p->addr))
 		p->ainsn.insn = get_insn_slot();
 	return p->ainsn.insn ? 0 : -ENOMEM;
 }
@@ -604,7 +611,7 @@
 		ip += (unsigned long) p->addr - (unsigned long) p->ainsn.insn;
 
 	if (fixup & FIXUP_BRANCH_NOT_TAKEN) {
-		int ilen = ((p->ainsn.insn[0] >> 14) + 3) & -2;
+		int ilen = insn_length(p->ainsn.insn[0] >> 8);
 		if (ip - (unsigned long) p->ainsn.insn == ilen)
 			ip = (unsigned long) p->addr + ilen;
 	}
diff --git a/arch/s390/kernel/pgm_check.S b/arch/s390/kernel/pgm_check.S
index 14bdecb..4a460c4 100644
--- a/arch/s390/kernel/pgm_check.S
+++ b/arch/s390/kernel/pgm_check.S
@@ -78,7 +78,7 @@
 PGM_CHECK_DEFAULT			/* 35 */
 PGM_CHECK_DEFAULT			/* 36 */
 PGM_CHECK_DEFAULT			/* 37 */
-PGM_CHECK_64BIT(do_asce_exception)	/* 38 */
+PGM_CHECK_DEFAULT			/* 38 */
 PGM_CHECK_64BIT(do_dat_exception)	/* 39 */
 PGM_CHECK_64BIT(do_dat_exception)	/* 3a */
 PGM_CHECK_64BIT(do_dat_exception)	/* 3b */
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index c5dbb33..7ed0d4e 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -139,7 +139,7 @@
 	if (unlikely(p->flags & PF_KTHREAD)) {
 		/* kernel thread */
 		memset(&frame->childregs, 0, sizeof(struct pt_regs));
-		frame->childregs.psw.mask = psw_kernel_bits | PSW_MASK_DAT |
+		frame->childregs.psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT |
 				PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
 		frame->childregs.psw.addr = PSW_ADDR_AMODE |
 				(unsigned long) kernel_thread_starter;
@@ -165,7 +165,8 @@
 	 * save fprs to current->thread.fp_regs to merge them with
 	 * the emulated registers and then copy the result to the child.
 	 */
-	save_fp_regs(&current->thread.fp_regs);
+	save_fp_ctl(&current->thread.fp_regs.fpc);
+	save_fp_regs(current->thread.fp_regs.fprs);
 	memcpy(&p->thread.fp_regs, &current->thread.fp_regs,
 	       sizeof(s390_fp_regs));
 	/* Set a new TLS ?  */
@@ -173,7 +174,9 @@
 		p->thread.acrs[0] = frame->childregs.gprs[6];
 #else /* CONFIG_64BIT */
 	/* Save the fpu registers to new thread structure. */
-	save_fp_regs(&p->thread.fp_regs);
+	save_fp_ctl(&p->thread.fp_regs.fpc);
+	save_fp_regs(p->thread.fp_regs.fprs);
+	p->thread.fp_regs.pad = 0;
 	/* Set a new TLS ?  */
 	if (clone_flags & CLONE_SETTLS) {
 		unsigned long tls = frame->childregs.gprs[6];
@@ -205,10 +208,12 @@
 	 * save fprs to current->thread.fp_regs to merge them with
 	 * the emulated registers and then copy the result to the dump.
 	 */
-	save_fp_regs(&current->thread.fp_regs);
+	save_fp_ctl(&current->thread.fp_regs.fpc);
+	save_fp_regs(current->thread.fp_regs.fprs);
 	memcpy(fpregs, &current->thread.fp_regs, sizeof(s390_fp_regs));
 #else /* CONFIG_64BIT */
-	save_fp_regs(fpregs);
+	save_fp_ctl(&fpregs->fpc);
+	save_fp_regs(fpregs->fprs);
 #endif /* CONFIG_64BIT */
 	return 1;
 }
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 9556905..e65c91c 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -198,9 +198,11 @@
 		 * psw and gprs are stored on the stack
 		 */
 		tmp = *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr);
-		if (addr == (addr_t) &dummy->regs.psw.mask)
+		if (addr == (addr_t) &dummy->regs.psw.mask) {
 			/* Return a clean psw mask. */
-			tmp = psw_user_bits | (tmp & PSW_MASK_USER);
+			tmp &= PSW_MASK_USER | PSW_MASK_RI;
+			tmp |= PSW_USER_BITS;
+		}
 
 	} else if (addr < (addr_t) &dummy->regs.orig_gpr2) {
 		/*
@@ -239,8 +241,7 @@
 		offset = addr - (addr_t) &dummy->regs.fp_regs;
 		tmp = *(addr_t *)((addr_t) &child->thread.fp_regs + offset);
 		if (addr == (addr_t) &dummy->regs.fp_regs.fpc)
-			tmp &= (unsigned long) FPC_VALID_MASK
-				<< (BITS_PER_LONG - 32);
+			tmp <<= BITS_PER_LONG - 32;
 
 	} else if (addr < (addr_t) (&dummy->regs.per_info + 1)) {
 		/*
@@ -321,11 +322,15 @@
 		/*
 		 * psw and gprs are stored on the stack
 		 */
-		if (addr == (addr_t) &dummy->regs.psw.mask &&
-		    ((data & ~PSW_MASK_USER) != psw_user_bits ||
-		     ((data & PSW_MASK_EA) && !(data & PSW_MASK_BA))))
-			/* Invalid psw mask. */
-			return -EINVAL;
+		if (addr == (addr_t) &dummy->regs.psw.mask) {
+			unsigned long mask = PSW_MASK_USER;
+
+			mask |= is_ri_task(child) ? PSW_MASK_RI : 0;
+			if ((data & ~mask) != PSW_USER_BITS)
+				return -EINVAL;
+			if ((data & PSW_MASK_EA) && !(data & PSW_MASK_BA))
+				return -EINVAL;
+		}
 		*(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data;
 
 	} else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) {
@@ -363,10 +368,10 @@
 		/*
 		 * floating point regs. are stored in the thread structure
 		 */
-		if (addr == (addr_t) &dummy->regs.fp_regs.fpc &&
-		    (data & ~((unsigned long) FPC_VALID_MASK
-			      << (BITS_PER_LONG - 32))) != 0)
-			return -EINVAL;
+		if (addr == (addr_t) &dummy->regs.fp_regs.fpc)
+			if ((unsigned int) data != 0 ||
+			    test_fp_ctl(data >> (BITS_PER_LONG - 32)))
+				return -EINVAL;
 		offset = addr - (addr_t) &dummy->regs.fp_regs;
 		*(addr_t *)((addr_t) &child->thread.fp_regs + offset) = data;
 
@@ -557,7 +562,8 @@
 		if (addr == (addr_t) &dummy32->regs.psw.mask) {
 			/* Fake a 31 bit psw mask. */
 			tmp = (__u32)(regs->psw.mask >> 32);
-			tmp = psw32_user_bits | (tmp & PSW32_MASK_USER);
+			tmp &= PSW32_MASK_USER | PSW32_MASK_RI;
+			tmp |= PSW32_USER_BITS;
 		} else if (addr == (addr_t) &dummy32->regs.psw.addr) {
 			/* Fake a 31 bit psw address. */
 			tmp = (__u32) regs->psw.addr |
@@ -654,13 +660,16 @@
 		 * psw, gprs, acrs and orig_gpr2 are stored on the stack
 		 */
 		if (addr == (addr_t) &dummy32->regs.psw.mask) {
+			__u32 mask = PSW32_MASK_USER;
+
+			mask |= is_ri_task(child) ? PSW32_MASK_RI : 0;
 			/* Build a 64 bit psw mask from 31 bit mask. */
-			if ((tmp & ~PSW32_MASK_USER) != psw32_user_bits)
+			if ((tmp & ~mask) != PSW32_USER_BITS)
 				/* Invalid psw mask. */
 				return -EINVAL;
 			regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
 				(regs->psw.mask & PSW_MASK_BA) |
-				(__u64)(tmp & PSW32_MASK_USER) << 32;
+				(__u64)(tmp & mask) << 32;
 		} else if (addr == (addr_t) &dummy32->regs.psw.addr) {
 			/* Build a 64 bit psw address from 31 bit address. */
 			regs->psw.addr = (__u64) tmp & PSW32_ADDR_INSN;
@@ -696,8 +705,7 @@
 		 * floating point regs. are stored in the thread structure 
 		 */
 		if (addr == (addr_t) &dummy32->regs.fp_regs.fpc &&
-		    (tmp & ~FPC_VALID_MASK) != 0)
-			/* Invalid floating point control. */
+		    test_fp_ctl(tmp))
 			return -EINVAL;
 	        offset = addr - (addr_t) &dummy32->regs.fp_regs;
 		*(__u32 *)((addr_t) &child->thread.fp_regs + offset) = tmp;
@@ -895,8 +903,10 @@
 			   const struct user_regset *regset, unsigned int pos,
 			   unsigned int count, void *kbuf, void __user *ubuf)
 {
-	if (target == current)
-		save_fp_regs(&target->thread.fp_regs);
+	if (target == current) {
+		save_fp_ctl(&target->thread.fp_regs.fpc);
+		save_fp_regs(target->thread.fp_regs.fprs);
+	}
 
 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 				   &target->thread.fp_regs, 0, -1);
@@ -909,19 +919,21 @@
 {
 	int rc = 0;
 
-	if (target == current)
-		save_fp_regs(&target->thread.fp_regs);
+	if (target == current) {
+		save_fp_ctl(&target->thread.fp_regs.fpc);
+		save_fp_regs(target->thread.fp_regs.fprs);
+	}
 
 	/* If setting FPC, must validate it first. */
 	if (count > 0 && pos < offsetof(s390_fp_regs, fprs)) {
-		u32 fpc[2] = { target->thread.fp_regs.fpc, 0 };
-		rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fpc,
+		u32 ufpc[2] = { target->thread.fp_regs.fpc, 0 };
+		rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ufpc,
 					0, offsetof(s390_fp_regs, fprs));
 		if (rc)
 			return rc;
-		if ((fpc[0] & ~FPC_VALID_MASK) != 0 || fpc[1] != 0)
+		if (ufpc[1] != 0 || test_fp_ctl(ufpc[0]))
 			return -EINVAL;
-		target->thread.fp_regs.fpc = fpc[0];
+		target->thread.fp_regs.fpc = ufpc[0];
 	}
 
 	if (rc == 0 && count > 0)
@@ -929,8 +941,10 @@
 					target->thread.fp_regs.fprs,
 					offsetof(s390_fp_regs, fprs), -1);
 
-	if (rc == 0 && target == current)
-		restore_fp_regs(&target->thread.fp_regs);
+	if (rc == 0 && target == current) {
+		restore_fp_ctl(&target->thread.fp_regs.fpc);
+		restore_fp_regs(target->thread.fp_regs.fprs);
+	}
 
 	return rc;
 }
diff --git a/arch/s390/kernel/runtime_instr.c b/arch/s390/kernel/runtime_instr.c
index e1c9d1c..d817cce 100644
--- a/arch/s390/kernel/runtime_instr.c
+++ b/arch/s390/kernel/runtime_instr.c
@@ -40,8 +40,6 @@
 static void init_runtime_instr_cb(struct runtime_instr_cb *cb)
 {
 	cb->buf_limit = 0xfff;
-	if (s390_user_mode == HOME_SPACE_MODE)
-		cb->home_space = 1;
 	cb->int_requested = 1;
 	cb->pstate = 1;
 	cb->pstate_set_buf = 1;
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index aeed8a6..ffe1c53 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -64,12 +64,6 @@
 #include <asm/sclp.h>
 #include "entry.h"
 
-long psw_kernel_bits	= PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_ASC_PRIMARY |
-			  PSW_MASK_EA | PSW_MASK_BA;
-long psw_user_bits	= PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT |
-			  PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_MCHECK |
-			  PSW_MASK_PSTATE | PSW_ASC_HOME;
-
 /*
  * User copy operations.
  */
@@ -300,43 +294,14 @@
 }
 early_param("vmalloc", parse_vmalloc);
 
-unsigned int s390_user_mode = PRIMARY_SPACE_MODE;
-EXPORT_SYMBOL_GPL(s390_user_mode);
-
-static void __init set_user_mode_primary(void)
-{
-	psw_kernel_bits = (psw_kernel_bits & ~PSW_MASK_ASC) | PSW_ASC_HOME;
-	psw_user_bits = (psw_user_bits & ~PSW_MASK_ASC) | PSW_ASC_PRIMARY;
-#ifdef CONFIG_COMPAT
-	psw32_user_bits =
-		(psw32_user_bits & ~PSW32_MASK_ASC) | PSW32_ASC_PRIMARY;
-#endif
-	uaccess = MACHINE_HAS_MVCOS ? uaccess_mvcos_switch : uaccess_pt;
-}
-
 static int __init early_parse_user_mode(char *p)
 {
-	if (p && strcmp(p, "primary") == 0)
-		s390_user_mode = PRIMARY_SPACE_MODE;
-	else if (!p || strcmp(p, "home") == 0)
-		s390_user_mode = HOME_SPACE_MODE;
-	else
-		return 1;
-	return 0;
+	if (!p || strcmp(p, "primary") == 0)
+		return 0;
+	return 1;
 }
 early_param("user_mode", early_parse_user_mode);
 
-static void __init setup_addressing_mode(void)
-{
-	if (s390_user_mode != PRIMARY_SPACE_MODE)
-		return;
-	set_user_mode_primary();
-	if (MACHINE_HAS_MVCOS)
-		pr_info("Address spaces switched, mvcos available\n");
-	else
-		pr_info("Address spaces switched, mvcos not available\n");
-}
-
 void *restart_stack __attribute__((__section__(".data")));
 
 static void __init setup_lowcore(void)
@@ -348,24 +313,24 @@
 	 */
 	BUILD_BUG_ON(sizeof(struct _lowcore) != LC_PAGES * 4096);
 	lc = __alloc_bootmem_low(LC_PAGES * PAGE_SIZE, LC_PAGES * PAGE_SIZE, 0);
-	lc->restart_psw.mask = psw_kernel_bits;
+	lc->restart_psw.mask = PSW_KERNEL_BITS;
 	lc->restart_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
-	lc->external_new_psw.mask = psw_kernel_bits |
+	lc->external_new_psw.mask = PSW_KERNEL_BITS |
 		PSW_MASK_DAT | PSW_MASK_MCHECK;
 	lc->external_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) ext_int_handler;
-	lc->svc_new_psw.mask = psw_kernel_bits |
+	lc->svc_new_psw.mask = PSW_KERNEL_BITS |
 		PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
 	lc->svc_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) system_call;
-	lc->program_new_psw.mask = psw_kernel_bits |
+	lc->program_new_psw.mask = PSW_KERNEL_BITS |
 		PSW_MASK_DAT | PSW_MASK_MCHECK;
 	lc->program_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) pgm_check_handler;
-	lc->mcck_new_psw.mask = psw_kernel_bits;
+	lc->mcck_new_psw.mask = PSW_KERNEL_BITS;
 	lc->mcck_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
-	lc->io_new_psw.mask = psw_kernel_bits |
+	lc->io_new_psw.mask = PSW_KERNEL_BITS |
 		PSW_MASK_DAT | PSW_MASK_MCHECK;
 	lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
 	lc->clock_comparator = -1ULL;
@@ -1043,10 +1008,7 @@
 	init_mm.end_data = (unsigned long) &_edata;
 	init_mm.brk = (unsigned long) &_end;
 
-	if (MACHINE_HAS_MVCOS)
-		memcpy(&uaccess, &uaccess_mvcos, sizeof(uaccess));
-	else
-		memcpy(&uaccess, &uaccess_std, sizeof(uaccess));
+	uaccess = MACHINE_HAS_MVCOS ? uaccess_mvcos : uaccess_pt;
 
 	parse_early_param();
 	detect_memory_layout(memory_chunk, memory_end);
@@ -1054,7 +1016,6 @@
 	setup_ipl();
 	reserve_oldmem();
 	setup_memory_end();
-	setup_addressing_mode();
 	reserve_crashkernel();
 	setup_memory();
 	setup_resources();
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index c45becf..fb53587 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -57,40 +57,48 @@
 
 	/* Copy a 'clean' PSW mask to the user to avoid leaking
 	   information about whether PER is currently on.  */
-	user_sregs.regs.psw.mask = psw_user_bits |
-		(regs->psw.mask & PSW_MASK_USER);
+	user_sregs.regs.psw.mask = PSW_USER_BITS |
+		(regs->psw.mask & (PSW_MASK_USER | PSW_MASK_RI));
 	user_sregs.regs.psw.addr = regs->psw.addr;
 	memcpy(&user_sregs.regs.gprs, &regs->gprs, sizeof(sregs->regs.gprs));
 	memcpy(&user_sregs.regs.acrs, current->thread.acrs,
-	       sizeof(sregs->regs.acrs));
+	       sizeof(user_sregs.regs.acrs));
 	/* 
 	 * We have to store the fp registers to current->thread.fp_regs
 	 * to merge them with the emulated registers.
 	 */
-	save_fp_regs(&current->thread.fp_regs);
+	save_fp_ctl(&current->thread.fp_regs.fpc);
+	save_fp_regs(current->thread.fp_regs.fprs);
 	memcpy(&user_sregs.fpregs, &current->thread.fp_regs,
-	       sizeof(s390_fp_regs));
-	return __copy_to_user(sregs, &user_sregs, sizeof(_sigregs));
+	       sizeof(user_sregs.fpregs));
+	if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs)))
+		return -EFAULT;
+	return 0;
 }
 
-/* Returns positive number on error */
 static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
 {
-	int err;
 	_sigregs user_sregs;
 
 	/* Alwys make any pending restarted system call return -EINTR */
 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
 
-	err = __copy_from_user(&user_sregs, sregs, sizeof(_sigregs));
-	if (err)
-		return err;
-	/* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */
+	if (__copy_from_user(&user_sregs, sregs, sizeof(user_sregs)))
+		return -EFAULT;
+
+	if (!is_ri_task(current) && (user_sregs.regs.psw.mask & PSW_MASK_RI))
+		return -EINVAL;
+
+	/* Loading the floating-point-control word can fail. Do that first. */
+	if (restore_fp_ctl(&user_sregs.fpregs.fpc))
+		return -EINVAL;
+
+	/* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */
 	regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
-		(user_sregs.regs.psw.mask & PSW_MASK_USER);
+		(user_sregs.regs.psw.mask & (PSW_MASK_USER | PSW_MASK_RI));
 	/* Check for invalid user address space control. */
-	if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
-		regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
+	if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_HOME)
+		regs->psw.mask = PSW_ASC_PRIMARY |
 			(regs->psw.mask & ~PSW_MASK_ASC);
 	/* Check for invalid amode */
 	if (regs->psw.mask & PSW_MASK_EA)
@@ -98,14 +106,13 @@
 	regs->psw.addr = user_sregs.regs.psw.addr;
 	memcpy(&regs->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs));
 	memcpy(&current->thread.acrs, &user_sregs.regs.acrs,
-	       sizeof(sregs->regs.acrs));
+	       sizeof(current->thread.acrs));
 	restore_access_regs(current->thread.acrs);
 
 	memcpy(&current->thread.fp_regs, &user_sregs.fpregs,
-	       sizeof(s390_fp_regs));
-	current->thread.fp_regs.fpc &= FPC_VALID_MASK;
+	       sizeof(current->thread.fp_regs));
 
-	restore_fp_regs(&current->thread.fp_regs);
+	restore_fp_regs(current->thread.fp_regs.fprs);
 	clear_thread_flag(TIF_SYSCALL);	/* No longer in a system call */
 	return 0;
 }
@@ -224,7 +231,7 @@
 	regs->gprs[15] = (unsigned long) frame;
 	/* Force default amode and default user address space control. */
 	regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
-		(psw_user_bits & PSW_MASK_ASC) |
+		(PSW_USER_BITS & PSW_MASK_ASC) |
 		(regs->psw.mask & ~PSW_MASK_ASC);
 	regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
 
@@ -295,7 +302,7 @@
 	regs->gprs[15] = (unsigned long) frame;
 	/* Force default amode and default user address space control. */
 	regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
-		(psw_user_bits & PSW_MASK_ASC) |
+		(PSW_USER_BITS & PSW_MASK_ASC) |
 		(regs->psw.mask & ~PSW_MASK_ASC);
 	regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
 
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 1a4313a..dc4a534 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -283,7 +283,7 @@
 	struct _lowcore *lc = lowcore_ptr[pcpu - pcpu_devices];
 	unsigned long source_cpu = stap();
 
-	__load_psw_mask(psw_kernel_bits);
+	__load_psw_mask(PSW_KERNEL_BITS);
 	if (pcpu->address == source_cpu)
 		func(data);	/* should not return */
 	/* Stop target cpu (if func returns this stops the current cpu). */
@@ -395,7 +395,7 @@
 	int cpu;
 
 	/* Disable all interrupts/machine checks */
-	__load_psw_mask(psw_kernel_bits | PSW_MASK_DAT);
+	__load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_DAT);
 	trace_hardirqs_off();
 
 	debug_set_critical();
@@ -533,9 +533,6 @@
 
 #if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_CRASH_DUMP)
 
-struct save_area *zfcpdump_save_areas[NR_CPUS + 1];
-EXPORT_SYMBOL_GPL(zfcpdump_save_areas);
-
 static void __init smp_get_save_area(int cpu, u16 address)
 {
 	void *lc = pcpu_devices[0].lowcore;
@@ -546,15 +543,9 @@
 	if (!OLDMEM_BASE && (address == boot_cpu_address ||
 			     ipl_info.type != IPL_TYPE_FCP_DUMP))
 		return;
-	if (cpu >= NR_CPUS) {
-		pr_warning("CPU %i exceeds the maximum %i and is excluded "
-			   "from the dump\n", cpu, NR_CPUS - 1);
-		return;
-	}
-	save_area = kmalloc(sizeof(struct save_area), GFP_KERNEL);
+	save_area = dump_save_area_create(cpu);
 	if (!save_area)
 		panic("could not allocate memory for save area\n");
-	zfcpdump_save_areas[cpu] = save_area;
 #ifdef CONFIG_CRASH_DUMP
 	if (address == boot_cpu_address) {
 		/* Copy the registers of the boot cpu. */
@@ -693,7 +684,7 @@
 	S390_lowcore.restart_source = -1UL;
 	restore_access_regs(S390_lowcore.access_regs_save_area);
 	__ctl_load(S390_lowcore.cregs_save_area, 0, 15);
-	__load_psw_mask(psw_kernel_bits | PSW_MASK_DAT);
+	__load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_DAT);
 	cpu_init();
 	preempt_disable();
 	init_cpu_timer();
@@ -929,7 +920,7 @@
 		idle_count = ACCESS_ONCE(idle->idle_count);
 		if (ACCESS_ONCE(idle->clock_idle_enter))
 			idle_count++;
-	} while ((sequence & 1) || (idle->sequence != sequence));
+	} while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
 	return sprintf(buf, "%llu\n", idle_count);
 }
 static DEVICE_ATTR(idle_count, 0444, show_idle_count, NULL);
@@ -947,7 +938,7 @@
 		idle_time = ACCESS_ONCE(idle->idle_time);
 		idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
 		idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
-	} while ((sequence & 1) || (idle->sequence != sequence));
+	} while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
 	idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0;
 	return sprintf(buf, "%llu\n", idle_time >> 12);
 }
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c
index 05d75c4..a84476f 100644
--- a/arch/s390/kernel/vdso.c
+++ b/arch/s390/kernel/vdso.c
@@ -84,8 +84,7 @@
  */
 static void vdso_init_data(struct vdso_data *vd)
 {
-	vd->ectg_available =
-		s390_user_mode != HOME_SPACE_MODE && test_facility(31);
+	vd->ectg_available = test_facility(31);
 }
 
 #ifdef CONFIG_64BIT
@@ -102,7 +101,7 @@
 
 	lowcore->vdso_per_cpu_data = __LC_PASTE;
 
-	if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled)
+	if (!vdso_enabled)
 		return 0;
 
 	segment_table = __get_free_pages(GFP_KERNEL, SEGMENT_ORDER);
@@ -147,7 +146,7 @@
 	unsigned long segment_table, page_table, page_frame;
 	u32 *psal, *aste;
 
-	if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled)
+	if (!vdso_enabled)
 		return;
 
 	psal = (u32 *)(addr_t) lowcore->paste[4];
@@ -165,7 +164,7 @@
 {
 	unsigned long cr5;
 
-	if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled)
+	if (!vdso_enabled)
 		return;
 	cr5 = offsetof(struct _lowcore, paste);
 	__ctl_load(cr5, 5, 5);
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index abcfab5..8c34363 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -161,7 +161,7 @@
 	trace_hardirqs_on();
 
 	/* Wait for external, I/O or machine check interrupt. */
-	psw_mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_DAT |
+	psw_mask = PSW_KERNEL_BITS | PSW_MASK_WAIT | PSW_MASK_DAT |
 		PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
 	idle->nohz_delay = 0;
 
@@ -191,7 +191,7 @@
 		sequence = ACCESS_ONCE(idle->sequence);
 		idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
 		idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
-	} while ((sequence & 1) || (idle->sequence != sequence));
+	} while ((sequence & 1) || (ACCESS_ONCE(idle->sequence) != sequence));
 	return idle_enter ? ((idle_exit ?: now) - idle_enter) : 0;
 }
 
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 7f35cb3..7f1f7ac 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -385,7 +385,7 @@
 	}
 
 	if ((!rc) && (vcpu->arch.sie_block->ckc <
-		get_tod_clock() + vcpu->arch.sie_block->epoch)) {
+		get_tod_clock_fast() + vcpu->arch.sie_block->epoch)) {
 		if ((!psw_extint_disabled(vcpu)) &&
 			(vcpu->arch.sie_block->gcr[0] & 0x800ul))
 			rc = 1;
@@ -425,7 +425,7 @@
 		goto no_timer;
 	}
 
-	now = get_tod_clock() + vcpu->arch.sie_block->epoch;
+	now = get_tod_clock_fast() + vcpu->arch.sie_block->epoch;
 	if (vcpu->arch.sie_block->ckc < now) {
 		__unset_cpu_idle(vcpu);
 		return 0;
@@ -515,7 +515,7 @@
 	}
 
 	if ((vcpu->arch.sie_block->ckc <
-		get_tod_clock() + vcpu->arch.sie_block->epoch))
+		get_tod_clock_fast() + vcpu->arch.sie_block->epoch))
 		__try_deliver_ckc_interrupt(vcpu);
 
 	if (atomic_read(&fi->active)) {
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 776dafe..ed8064c 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -343,10 +343,11 @@
 
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
-	save_fp_regs(&vcpu->arch.host_fpregs);
+	save_fp_ctl(&vcpu->arch.host_fpregs.fpc);
+	save_fp_regs(vcpu->arch.host_fpregs.fprs);
 	save_access_regs(vcpu->arch.host_acrs);
-	vcpu->arch.guest_fpregs.fpc &= FPC_VALID_MASK;
-	restore_fp_regs(&vcpu->arch.guest_fpregs);
+	restore_fp_ctl(&vcpu->arch.guest_fpregs.fpc);
+	restore_fp_regs(vcpu->arch.guest_fpregs.fprs);
 	restore_access_regs(vcpu->run->s.regs.acrs);
 	gmap_enable(vcpu->arch.gmap);
 	atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
@@ -356,9 +357,11 @@
 {
 	atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
 	gmap_disable(vcpu->arch.gmap);
-	save_fp_regs(&vcpu->arch.guest_fpregs);
+	save_fp_ctl(&vcpu->arch.guest_fpregs.fpc);
+	save_fp_regs(vcpu->arch.guest_fpregs.fprs);
 	save_access_regs(vcpu->run->s.regs.acrs);
-	restore_fp_regs(&vcpu->arch.host_fpregs);
+	restore_fp_ctl(&vcpu->arch.host_fpregs.fpc);
+	restore_fp_regs(vcpu->arch.host_fpregs.fprs);
 	restore_access_regs(vcpu->arch.host_acrs);
 }
 
@@ -618,9 +621,12 @@
 
 int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 {
+	if (test_fp_ctl(fpu->fpc))
+		return -EINVAL;
 	memcpy(&vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
-	vcpu->arch.guest_fpregs.fpc = fpu->fpc & FPC_VALID_MASK;
-	restore_fp_regs(&vcpu->arch.guest_fpregs);
+	vcpu->arch.guest_fpregs.fpc = fpu->fpc;
+	restore_fp_ctl(&vcpu->arch.guest_fpregs.fpc);
+	restore_fp_regs(vcpu->arch.guest_fpregs.fprs);
 	return 0;
 }
 
@@ -876,7 +882,8 @@
 	 * copying in vcpu load/put. Lets update our copies before we save
 	 * it into the save area
 	 */
-	save_fp_regs(&vcpu->arch.guest_fpregs);
+	save_fp_ctl(&vcpu->arch.guest_fpregs.fpc);
+	save_fp_regs(vcpu->arch.guest_fpregs.fprs);
 	save_access_regs(vcpu->run->s.regs.acrs);
 
 	if (__guestcopy(vcpu, addr + offsetof(struct save_area, fp_regs),
diff --git a/arch/s390/kvm/trace.h b/arch/s390/kvm/trace.h
index c2f582bb1c..0c991c6 100644
--- a/arch/s390/kvm/trace.h
+++ b/arch/s390/kvm/trace.h
@@ -4,6 +4,7 @@
 #include <linux/tracepoint.h>
 #include <asm/sigp.h>
 #include <asm/debug.h>
+#include <asm/dis.h>
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM kvm
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index 20b0e97..b068729 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -2,7 +2,7 @@
 # Makefile for s390-specific library files..
 #
 
-lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
+lib-y += delay.o string.o uaccess_pt.o find.o
 obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o mem32.o
 obj-$(CONFIG_64BIT) += mem64.o
 lib-$(CONFIG_64BIT) += uaccess_mvcos.o
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
index 57c87d7..a9f3d00 100644
--- a/arch/s390/lib/delay.c
+++ b/arch/s390/lib/delay.c
@@ -44,7 +44,7 @@
 	do {
 		set_clock_comparator(end);
 		vtime_stop_cpu();
-	} while (get_tod_clock() < end);
+	} while (get_tod_clock_fast() < end);
 	lockdep_on();
 	__ctl_load(cr0, 0, 0);
 	__ctl_load(cr6, 6, 6);
@@ -55,7 +55,7 @@
 {
 	u64 clock_saved, end;
 
-	end = get_tod_clock() + (usecs << 12);
+	end = get_tod_clock_fast() + (usecs << 12);
 	do {
 		clock_saved = 0;
 		if (end < S390_lowcore.clock_comparator) {
@@ -65,7 +65,7 @@
 		vtime_stop_cpu();
 		if (clock_saved)
 			local_tick_enable(clock_saved);
-	} while (get_tod_clock() < end);
+	} while (get_tod_clock_fast() < end);
 }
 
 /*
@@ -109,8 +109,8 @@
 {
 	u64 end;
 
-	end = get_tod_clock() + (usecs << 12);
-	while (get_tod_clock() < end)
+	end = get_tod_clock_fast() + (usecs << 12);
+	while (get_tod_clock_fast() < end)
 		cpu_relax();
 }
 
@@ -120,10 +120,10 @@
 
 	nsecs <<= 9;
 	do_div(nsecs, 125);
-	end = get_tod_clock() + nsecs;
+	end = get_tod_clock_fast() + nsecs;
 	if (nsecs & ~0xfffUL)
 		__udelay(nsecs >> 12);
-	while (get_tod_clock() < end)
+	while (get_tod_clock_fast() < end)
 		barrier();
 }
 EXPORT_SYMBOL(__ndelay);
diff --git a/arch/s390/lib/find.c b/arch/s390/lib/find.c
new file mode 100644
index 0000000..620d34d
--- /dev/null
+++ b/arch/s390/lib/find.c
@@ -0,0 +1,77 @@
+/*
+ * MSB0 numbered special bitops handling.
+ *
+ * On s390x the bits are numbered:
+ *   |0..............63|64............127|128...........191|192...........255|
+ * and on s390:
+ *   |0.....31|31....63|64....95|96...127|128..159|160..191|192..223|224..255|
+ *
+ * The reason for this bit numbering is the fact that the hardware sets bits
+ * in a bitmap starting at bit 0 (MSB) and we don't want to scan the bitmap
+ * from the 'wrong end'.
+ */
+
+#include <linux/compiler.h>
+#include <linux/bitops.h>
+#include <linux/export.h>
+
+unsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size)
+{
+	const unsigned long *p = addr;
+	unsigned long result = 0;
+	unsigned long tmp;
+
+	while (size & ~(BITS_PER_LONG - 1)) {
+		if ((tmp = *(p++)))
+			goto found;
+		result += BITS_PER_LONG;
+		size -= BITS_PER_LONG;
+	}
+	if (!size)
+		return result;
+	tmp = (*p) & (~0UL << (BITS_PER_LONG - size));
+	if (!tmp)		/* Are any bits set? */
+		return result + size;	/* Nope. */
+found:
+	return result + (__fls(tmp) ^ (BITS_PER_LONG - 1));
+}
+EXPORT_SYMBOL(find_first_bit_inv);
+
+unsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size,
+				unsigned long offset)
+{
+	const unsigned long *p = addr + (offset / BITS_PER_LONG);
+	unsigned long result = offset & ~(BITS_PER_LONG - 1);
+	unsigned long tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset %= BITS_PER_LONG;
+	if (offset) {
+		tmp = *(p++);
+		tmp &= (~0UL >> offset);
+		if (size < BITS_PER_LONG)
+			goto found_first;
+		if (tmp)
+			goto found_middle;
+		size -= BITS_PER_LONG;
+		result += BITS_PER_LONG;
+	}
+	while (size & ~(BITS_PER_LONG-1)) {
+		if ((tmp = *(p++)))
+			goto found_middle;
+		result += BITS_PER_LONG;
+		size -= BITS_PER_LONG;
+	}
+	if (!size)
+		return result;
+	tmp = *p;
+found_first:
+	tmp &= (~0UL << (BITS_PER_LONG - size));
+	if (!tmp)		/* Are any bits set? */
+		return result + size;	/* Nope. */
+found_middle:
+	return result + (__fls(tmp) ^ (BITS_PER_LONG - 1));
+}
+EXPORT_SYMBOL(find_next_bit_inv);
diff --git a/arch/s390/lib/uaccess_mvcos.c b/arch/s390/lib/uaccess_mvcos.c
index 1829742..4b7993b 100644
--- a/arch/s390/lib/uaccess_mvcos.c
+++ b/arch/s390/lib/uaccess_mvcos.c
@@ -65,13 +65,6 @@
 	return size;
 }
 
-static size_t copy_from_user_mvcos_check(size_t size, const void __user *ptr, void *x)
-{
-	if (size <= 256)
-		return copy_from_user_std(size, ptr, x);
-	return copy_from_user_mvcos(size, ptr, x);
-}
-
 static size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
 {
 	register unsigned long reg0 asm("0") = 0x810000UL;
@@ -101,14 +94,6 @@
 	return size;
 }
 
-static size_t copy_to_user_mvcos_check(size_t size, void __user *ptr,
-				       const void *x)
-{
-	if (size <= 256)
-		return copy_to_user_std(size, ptr, x);
-	return copy_to_user_mvcos(size, ptr, x);
-}
-
 static size_t copy_in_user_mvcos(size_t size, void __user *to,
 				 const void __user *from)
 {
@@ -201,23 +186,8 @@
 }
 
 struct uaccess_ops uaccess_mvcos = {
-	.copy_from_user = copy_from_user_mvcos_check,
-	.copy_from_user_small = copy_from_user_std,
-	.copy_to_user = copy_to_user_mvcos_check,
-	.copy_to_user_small = copy_to_user_std,
-	.copy_in_user = copy_in_user_mvcos,
-	.clear_user = clear_user_mvcos,
-	.strnlen_user = strnlen_user_std,
-	.strncpy_from_user = strncpy_from_user_std,
-	.futex_atomic_op = futex_atomic_op_std,
-	.futex_atomic_cmpxchg = futex_atomic_cmpxchg_std,
-};
-
-struct uaccess_ops uaccess_mvcos_switch = {
 	.copy_from_user = copy_from_user_mvcos,
-	.copy_from_user_small = copy_from_user_mvcos,
 	.copy_to_user = copy_to_user_mvcos,
-	.copy_to_user_small = copy_to_user_mvcos,
 	.copy_in_user = copy_in_user_mvcos,
 	.clear_user = clear_user_mvcos,
 	.strnlen_user = strnlen_user_mvcos,
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index 1694d73..97e03ca 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -461,9 +461,7 @@
 
 struct uaccess_ops uaccess_pt = {
 	.copy_from_user		= copy_from_user_pt,
-	.copy_from_user_small	= copy_from_user_pt,
 	.copy_to_user		= copy_to_user_pt,
-	.copy_to_user_small	= copy_to_user_pt,
 	.copy_in_user		= copy_in_user_pt,
 	.clear_user		= clear_user_pt,
 	.strnlen_user		= strnlen_user_pt,
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c
deleted file mode 100644
index 4a75d47..0000000
--- a/arch/s390/lib/uaccess_std.c
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- *  Standard user space access functions based on mvcp/mvcs and doing
- *  interesting things in the secondary space mode.
- *
- *    Copyright IBM Corp. 2006
- *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
- *		 Gerald Schaefer (gerald.schaefer@de.ibm.com)
- */
-
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/uaccess.h>
-#include <asm/futex.h>
-#include "uaccess.h"
-
-#ifndef CONFIG_64BIT
-#define AHI	"ahi"
-#define ALR	"alr"
-#define CLR	"clr"
-#define LHI	"lhi"
-#define SLR	"slr"
-#else
-#define AHI	"aghi"
-#define ALR	"algr"
-#define CLR	"clgr"
-#define LHI	"lghi"
-#define SLR	"slgr"
-#endif
-
-size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
-{
-	unsigned long tmp1, tmp2;
-
-	tmp1 = -256UL;
-	asm volatile(
-		"0: mvcp  0(%0,%2),0(%1),%3\n"
-		"10:jz    8f\n"
-		"1:"ALR"  %0,%3\n"
-		"   la    %1,256(%1)\n"
-		"   la    %2,256(%2)\n"
-		"2: mvcp  0(%0,%2),0(%1),%3\n"
-		"11:jnz   1b\n"
-		"   j     8f\n"
-		"3: la    %4,255(%1)\n"	/* %4 = ptr + 255 */
-		"  "LHI"  %3,-4096\n"
-		"   nr    %4,%3\n"	/* %4 = (ptr + 255) & -4096 */
-		"  "SLR"  %4,%1\n"
-		"  "CLR"  %0,%4\n"	/* copy crosses next page boundary? */
-		"   jnh   5f\n"
-		"4: mvcp  0(%4,%2),0(%1),%3\n"
-		"12:"SLR"  %0,%4\n"
-		"  "ALR"  %2,%4\n"
-		"5:"LHI"  %4,-1\n"
-		"  "ALR"  %4,%0\n"	/* copy remaining size, subtract 1 */
-		"   bras  %3,7f\n"	/* memset loop */
-		"   xc    0(1,%2),0(%2)\n"
-		"6: xc    0(256,%2),0(%2)\n"
-		"   la    %2,256(%2)\n"
-		"7:"AHI"  %4,-256\n"
-		"   jnm   6b\n"
-		"   ex    %4,0(%3)\n"
-		"   j     9f\n"
-		"8:"SLR"  %0,%0\n"
-		"9: \n"
-		EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,5b)
-		EX_TABLE(10b,3b) EX_TABLE(11b,3b) EX_TABLE(12b,5b)
-		: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
-		: : "cc", "memory");
-	return size;
-}
-
-static size_t copy_from_user_std_check(size_t size, const void __user *ptr,
-				       void *x)
-{
-	if (size <= 1024)
-		return copy_from_user_std(size, ptr, x);
-	return copy_from_user_pt(size, ptr, x);
-}
-
-size_t copy_to_user_std(size_t size, void __user *ptr, const void *x)
-{
-	unsigned long tmp1, tmp2;
-
-	tmp1 = -256UL;
-	asm volatile(
-		"0: mvcs  0(%0,%1),0(%2),%3\n"
-		"7: jz    5f\n"
-		"1:"ALR"  %0,%3\n"
-		"   la    %1,256(%1)\n"
-		"   la    %2,256(%2)\n"
-		"2: mvcs  0(%0,%1),0(%2),%3\n"
-		"8: jnz   1b\n"
-		"   j     5f\n"
-		"3: la    %4,255(%1)\n" /* %4 = ptr + 255 */
-		"  "LHI"  %3,-4096\n"
-		"   nr    %4,%3\n"	/* %4 = (ptr + 255) & -4096 */
-		"  "SLR"  %4,%1\n"
-		"  "CLR"  %0,%4\n"	/* copy crosses next page boundary? */
-		"   jnh   6f\n"
-		"4: mvcs  0(%4,%1),0(%2),%3\n"
-		"9:"SLR"  %0,%4\n"
-		"   j     6f\n"
-		"5:"SLR"  %0,%0\n"
-		"6: \n"
-		EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,6b)
-		EX_TABLE(7b,3b) EX_TABLE(8b,3b) EX_TABLE(9b,6b)
-		: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
-		: : "cc", "memory");
-	return size;
-}
-
-static size_t copy_to_user_std_check(size_t size, void __user *ptr,
-				     const void *x)
-{
-	if (size <= 1024)
-		return copy_to_user_std(size, ptr, x);
-	return copy_to_user_pt(size, ptr, x);
-}
-
-static size_t copy_in_user_std(size_t size, void __user *to,
-			       const void __user *from)
-{
-	unsigned long tmp1;
-
-	asm volatile(
-		"   sacf  256\n"
-		"  "AHI"  %0,-1\n"
-		"   jo    5f\n"
-		"   bras  %3,3f\n"
-		"0:"AHI"  %0,257\n"
-		"1: mvc   0(1,%1),0(%2)\n"
-		"   la    %1,1(%1)\n"
-		"   la    %2,1(%2)\n"
-		"  "AHI"  %0,-1\n"
-		"   jnz   1b\n"
-		"   j     5f\n"
-		"2: mvc   0(256,%1),0(%2)\n"
-		"   la    %1,256(%1)\n"
-		"   la    %2,256(%2)\n"
-		"3:"AHI"  %0,-256\n"
-		"   jnm   2b\n"
-		"4: ex    %0,1b-0b(%3)\n"
-		"5: "SLR"  %0,%0\n"
-		"6: sacf  0\n"
-		EX_TABLE(1b,6b) EX_TABLE(2b,0b) EX_TABLE(4b,0b)
-		: "+a" (size), "+a" (to), "+a" (from), "=a" (tmp1)
-		: : "cc", "memory");
-	return size;
-}
-
-static size_t clear_user_std(size_t size, void __user *to)
-{
-	unsigned long tmp1, tmp2;
-
-	asm volatile(
-		"   sacf  256\n"
-		"  "AHI"  %0,-1\n"
-		"   jo    5f\n"
-		"   bras  %3,3f\n"
-		"   xc    0(1,%1),0(%1)\n"
-		"0:"AHI"  %0,257\n"
-		"   la    %2,255(%1)\n" /* %2 = ptr + 255 */
-		"   srl   %2,12\n"
-		"   sll   %2,12\n"	/* %2 = (ptr + 255) & -4096 */
-		"  "SLR"  %2,%1\n"
-		"  "CLR"  %0,%2\n"	/* clear crosses next page boundary? */
-		"   jnh   5f\n"
-		"  "AHI"  %2,-1\n"
-		"1: ex    %2,0(%3)\n"
-		"  "AHI"  %2,1\n"
-		"  "SLR"  %0,%2\n"
-		"   j     5f\n"
-		"2: xc    0(256,%1),0(%1)\n"
-		"   la    %1,256(%1)\n"
-		"3:"AHI"  %0,-256\n"
-		"   jnm   2b\n"
-		"4: ex    %0,0(%3)\n"
-		"5: "SLR"  %0,%0\n"
-		"6: sacf  0\n"
-		EX_TABLE(1b,6b) EX_TABLE(2b,0b) EX_TABLE(4b,0b)
-		: "+a" (size), "+a" (to), "=a" (tmp1), "=a" (tmp2)
-		: : "cc", "memory");
-	return size;
-}
-
-size_t strnlen_user_std(size_t size, const char __user *src)
-{
-	register unsigned long reg0 asm("0") = 0UL;
-	unsigned long tmp1, tmp2;
-
-	if (unlikely(!size))
-		return 0;
-	asm volatile(
-		"   la    %2,0(%1)\n"
-		"   la    %3,0(%0,%1)\n"
-		"  "SLR"  %0,%0\n"
-		"   sacf  256\n"
-		"0: srst  %3,%2\n"
-		"   jo    0b\n"
-		"   la    %0,1(%3)\n"	/* strnlen_user results includes \0 */
-		"  "SLR"  %0,%1\n"
-		"1: sacf  0\n"
-		EX_TABLE(0b,1b)
-		: "+a" (size), "+a" (src), "=a" (tmp1), "=a" (tmp2)
-		: "d" (reg0) : "cc", "memory");
-	return size;
-}
-
-size_t strncpy_from_user_std(size_t count, const char __user *src, char *dst)
-{
-	size_t done, len, offset, len_str;
-
-	if (unlikely(!count))
-		return 0;
-	done = 0;
-	do {
-		offset = (size_t)src & ~PAGE_MASK;
-		len = min(count - done, PAGE_SIZE - offset);
-		if (copy_from_user_std(len, src, dst))
-			return -EFAULT;
-		len_str = strnlen(dst, len);
-		done += len_str;
-		src += len_str;
-		dst += len_str;
-	} while ((len_str == len) && (done < count));
-	return done;
-}
-
-#define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg)	\
-	asm volatile(							\
-		"   sacf  256\n"					\
-		"0: l     %1,0(%6)\n"					\
-		"1:"insn						\
-		"2: cs    %1,%2,0(%6)\n"				\
-		"3: jl    1b\n"						\
-		"   lhi   %0,0\n"					\
-		"4: sacf  0\n"						\
-		EX_TABLE(0b,4b) EX_TABLE(2b,4b) EX_TABLE(3b,4b)		\
-		: "=d" (ret), "=&d" (oldval), "=&d" (newval),		\
-		  "=m" (*uaddr)						\
-		: "0" (-EFAULT), "d" (oparg), "a" (uaddr),		\
-		  "m" (*uaddr) : "cc");
-
-int futex_atomic_op_std(int op, u32 __user *uaddr, int oparg, int *old)
-{
-	int oldval = 0, newval, ret;
-
-	switch (op) {
-	case FUTEX_OP_SET:
-		__futex_atomic_op("lr %2,%5\n",
-				  ret, oldval, newval, uaddr, oparg);
-		break;
-	case FUTEX_OP_ADD:
-		__futex_atomic_op("lr %2,%1\nar %2,%5\n",
-				  ret, oldval, newval, uaddr, oparg);
-		break;
-	case FUTEX_OP_OR:
-		__futex_atomic_op("lr %2,%1\nor %2,%5\n",
-				  ret, oldval, newval, uaddr, oparg);
-		break;
-	case FUTEX_OP_ANDN:
-		__futex_atomic_op("lr %2,%1\nnr %2,%5\n",
-				  ret, oldval, newval, uaddr, oparg);
-		break;
-	case FUTEX_OP_XOR:
-		__futex_atomic_op("lr %2,%1\nxr %2,%5\n",
-				  ret, oldval, newval, uaddr, oparg);
-		break;
-	default:
-		ret = -ENOSYS;
-	}
-	*old = oldval;
-	return ret;
-}
-
-int futex_atomic_cmpxchg_std(u32 *uval, u32 __user *uaddr,
-			     u32 oldval, u32 newval)
-{
-	int ret;
-
-	asm volatile(
-		"   sacf 256\n"
-		"0: cs   %1,%4,0(%5)\n"
-		"1: la   %0,0\n"
-		"2: sacf 0\n"
-		EX_TABLE(0b,2b) EX_TABLE(1b,2b)
-		: "=d" (ret), "+d" (oldval), "=m" (*uaddr)
-		: "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
-		: "cc", "memory" );
-	*uval = oldval;
-	return ret;
-}
-
-struct uaccess_ops uaccess_std = {
-	.copy_from_user = copy_from_user_std_check,
-	.copy_from_user_small = copy_from_user_std,
-	.copy_to_user = copy_to_user_std_check,
-	.copy_to_user_small = copy_to_user_std,
-	.copy_in_user = copy_in_user_std,
-	.clear_user = clear_user_std,
-	.strnlen_user = strnlen_user_std,
-	.strncpy_from_user = strncpy_from_user_std,
-	.futex_atomic_op = futex_atomic_op_std,
-	.futex_atomic_cmpxchg = futex_atomic_cmpxchg_std,
-};
diff --git a/arch/s390/math-emu/math.c b/arch/s390/math-emu/math.c
index 58bff54..a6ba0d7 100644
--- a/arch/s390/math-emu/math.c
+++ b/arch/s390/math-emu/math.c
@@ -19,6 +19,8 @@
 #include <math-emu/double.h>
 #include <math-emu/quad.h>
 
+#define FPC_VALID_MASK		0xF8F8FF03
+
 /*
  * I miss a macro to round a floating point number to the
  * nearest integer in the same floating point format.
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index 9d84a1f..79ddd58 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -253,12 +253,12 @@
 
 static struct ctl_table cmm_table[];
 
-static int cmm_pages_handler(ctl_table *ctl, int write, void __user *buffer,
-			     size_t *lenp, loff_t *ppos)
+static int cmm_pages_handler(struct ctl_table *ctl, int write,
+			     void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	char buf[16], *p;
+	unsigned int len;
 	long nr;
-	int len;
 
 	if (!*lenp || (*ppos && !write)) {
 		*lenp = 0;
@@ -293,12 +293,12 @@
 	return 0;
 }
 
-static int cmm_timeout_handler(ctl_table *ctl, int write,  void __user *buffer,
-			       size_t *lenp, loff_t *ppos)
+static int cmm_timeout_handler(struct ctl_table *ctl, int write,
+			       void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	char buf[64], *p;
 	long nr, seconds;
-	int len;
+	unsigned int len;
 
 	if (!*lenp || (*ppos && !write)) {
 		*lenp = 0;
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index fc66792..d95265b2 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -115,13 +115,8 @@
 	if (trans_exc_code == 2)
 		/* Access via secondary space, set_fs setting decides */
 		return current->thread.mm_segment.ar4;
-	if (s390_user_mode == HOME_SPACE_MODE)
-		/* User space if the access has been done via home space. */
-		return trans_exc_code == 3;
 	/*
-	 * If the user space is not the home space the kernel runs in home
-	 * space. Access via secondary space has already been covered,
-	 * access via primary space or access register is from user space
+	 * Access via primary space or access register is from user space
 	 * and access via home space is from the kernel.
 	 */
 	return trans_exc_code != 3;
@@ -428,50 +423,13 @@
 		do_fault_error(regs, fault);
 }
 
-#ifdef CONFIG_64BIT
-void __kprobes do_asce_exception(struct pt_regs *regs)
-{
-	struct mm_struct *mm = current->mm;
-	struct vm_area_struct *vma;
-	unsigned long trans_exc_code;
-
-	/*
-	 * The instruction that caused the program check has
-	 * been nullified. Don't signal single step via SIGTRAP.
-	 */
-	clear_tsk_thread_flag(current, TIF_PER_TRAP);
-
-	trans_exc_code = regs->int_parm_long;
-	if (unlikely(!user_space_fault(trans_exc_code) || in_atomic() || !mm))
-		goto no_context;
-
-	down_read(&mm->mmap_sem);
-	vma = find_vma(mm, trans_exc_code & __FAIL_ADDR_MASK);
-	up_read(&mm->mmap_sem);
-
-	if (vma) {
-		update_mm(mm, current);
-		return;
-	}
-
-	/* User mode accesses just cause a SIGSEGV */
-	if (user_mode(regs)) {
-		do_sigsegv(regs, SEGV_MAPERR);
-		return;
-	}
-
-no_context:
-	do_no_context(regs);
-}
-#endif
-
 int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write)
 {
 	struct pt_regs regs;
 	int access, fault;
 
 	/* Emulate a uaccess fault from kernel mode. */
-	regs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK;
+	regs.psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT | PSW_MASK_MCHECK;
 	if (!irqs_disabled())
 		regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT;
 	regs.psw.addr = (unsigned long) __builtin_return_address(0);
diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c
index 5d758db..639fce46 100644
--- a/arch/s390/mm/gup.c
+++ b/arch/s390/mm/gup.c
@@ -180,9 +180,15 @@
 	addr = start;
 	len = (unsigned long) nr_pages << PAGE_SHIFT;
 	end = start + len;
-	if ((end < start) || (end > TASK_SIZE))
+	if ((end <= start) || (end > TASK_SIZE))
 		return 0;
-
+	/*
+	 * local_irq_save() doesn't prevent pagetable teardown, but does
+	 * prevent the pagetables from being freed on s390.
+	 *
+	 * So long as we atomically load page table pointers versus teardown,
+	 * we can follow the address down to the the page and take a ref on it.
+	 */
 	local_irq_save(flags);
 	pgdp = pgd_offset(mm, addr);
 	do {
@@ -219,63 +225,22 @@
 			struct page **pages)
 {
 	struct mm_struct *mm = current->mm;
-	unsigned long addr, len, end;
-	unsigned long next;
-	pgd_t *pgdp, pgd;
-	int nr = 0;
+	int nr, ret;
 
 	start &= PAGE_MASK;
-	addr = start;
-	len = (unsigned long) nr_pages << PAGE_SHIFT;
-	end = start + len;
-	if ((end < start) || (end > TASK_SIZE))
-		goto slow_irqon;
+	nr = __get_user_pages_fast(start, nr_pages, write, pages);
+	if (nr == nr_pages)
+		return nr;
 
-	/*
-	 * local_irq_disable() doesn't prevent pagetable teardown, but does
-	 * prevent the pagetables from being freed on s390.
-	 *
-	 * So long as we atomically load page table pointers versus teardown,
-	 * we can follow the address down to the the page and take a ref on it.
-	 */
-	local_irq_disable();
-	pgdp = pgd_offset(mm, addr);
-	do {
-		pgd = *pgdp;
-		barrier();
-		next = pgd_addr_end(addr, end);
-		if (pgd_none(pgd))
-			goto slow;
-		if (!gup_pud_range(pgdp, pgd, addr, next, write, pages, &nr))
-			goto slow;
-	} while (pgdp++, addr = next, addr != end);
-	local_irq_enable();
-
-	VM_BUG_ON(nr != (end - start) >> PAGE_SHIFT);
-	return nr;
-
-	{
-		int ret;
-slow:
-		local_irq_enable();
-slow_irqon:
-		/* Try to get the remaining pages with get_user_pages */
-		start += nr << PAGE_SHIFT;
-		pages += nr;
-
-		down_read(&mm->mmap_sem);
-		ret = get_user_pages(current, mm, start,
-			(end - start) >> PAGE_SHIFT, write, 0, pages, NULL);
-		up_read(&mm->mmap_sem);
-
-		/* Have to be a bit careful with return values */
-		if (nr > 0) {
-			if (ret < 0)
-				ret = nr;
-			else
-				ret += nr;
-		}
-
-		return ret;
-	}
+	/* Try to get the remaining pages with get_user_pages */
+	start += nr << PAGE_SHIFT;
+	pages += nr;
+	down_read(&mm->mmap_sem);
+	ret = get_user_pages(current, mm, start,
+			     nr_pages - nr, write, 0, pages, NULL);
+	up_read(&mm->mmap_sem);
+	/* Have to be a bit careful with return values */
+	if (nr > 0)
+		ret = (ret < 0) ? nr : ret + nr;
+	return ret;
 }
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c
index 4002329..6bcb045 100644
--- a/arch/s390/mm/mmap.c
+++ b/arch/s390/mm/mmap.c
@@ -101,18 +101,12 @@
 
 int s390_mmap_check(unsigned long addr, unsigned long len, unsigned long flags)
 {
-	int rc;
-
 	if (is_compat_task() || (TASK_SIZE >= (1UL << 53)))
 		return 0;
 	if (!(flags & MAP_FIXED))
 		addr = 0;
-	if ((addr + len) >= TASK_SIZE) {
-		rc = crst_table_upgrade(current->mm, 1UL << 53);
-		if (rc)
-			return rc;
-		update_mm(current->mm, current);
-	}
+	if ((addr + len) >= TASK_SIZE)
+		return crst_table_upgrade(current->mm, 1UL << 53);
 	return 0;
 }
 
@@ -132,7 +126,6 @@
 		rc = crst_table_upgrade(mm, 1UL << 53);
 		if (rc)
 			return (unsigned long) rc;
-		update_mm(mm, current);
 		area = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
 	}
 	return area;
@@ -155,7 +148,6 @@
 		rc = crst_table_upgrade(mm, 1UL << 53);
 		if (rc)
 			return (unsigned long) rc;
-		update_mm(mm, current);
 		area = arch_get_unmapped_area_topdown(filp, addr, len,
 						      pgoff, flags);
 	}
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
index 9903974..8400f49 100644
--- a/arch/s390/mm/pageattr.c
+++ b/arch/s390/mm/pageattr.c
@@ -9,6 +9,7 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 
+#if PAGE_DEFAULT_KEY
 static inline unsigned long sske_frame(unsigned long addr, unsigned char skey)
 {
 	asm volatile(".insn rrf,0xb22b0000,%[skey],%[addr],9,0"
@@ -16,7 +17,7 @@
 	return addr;
 }
 
-void storage_key_init_range(unsigned long start, unsigned long end)
+void __storage_key_init_range(unsigned long start, unsigned long end)
 {
 	unsigned long boundary, size;
 
@@ -36,6 +37,7 @@
 		start += PAGE_SIZE;
 	}
 }
+#endif
 
 static pte_t *walk_page_table(unsigned long addr)
 {
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index de8cbc3..0a2e5e0 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -48,12 +48,23 @@
 }
 
 #ifdef CONFIG_64BIT
+static void __crst_table_upgrade(void *arg)
+{
+	struct mm_struct *mm = arg;
+
+	if (current->active_mm == mm)
+		update_mm(mm, current);
+	__tlb_flush_local();
+}
+
 int crst_table_upgrade(struct mm_struct *mm, unsigned long limit)
 {
 	unsigned long *table, *pgd;
 	unsigned long entry;
+	int flush;
 
 	BUG_ON(limit > (1UL << 53));
+	flush = 0;
 repeat:
 	table = crst_table_alloc(mm);
 	if (!table)
@@ -79,12 +90,15 @@
 		mm->pgd = (pgd_t *) table;
 		mm->task_size = mm->context.asce_limit;
 		table = NULL;
+		flush = 1;
 	}
 	spin_unlock_bh(&mm->page_table_lock);
 	if (table)
 		crst_table_free(mm, table);
 	if (mm->context.asce_limit < limit)
 		goto repeat;
+	if (flush)
+		on_each_cpu(__crst_table_upgrade, mm, 0);
 	return 0;
 }
 
@@ -92,6 +106,8 @@
 {
 	pgd_t *pgd;
 
+	if (current->active_mm == mm)
+		__tlb_flush_mm(mm);
 	while (mm->context.asce_limit > limit) {
 		pgd = mm->pgd;
 		switch (pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) {
@@ -114,6 +130,8 @@
 		mm->task_size = mm->context.asce_limit;
 		crst_table_free(mm, (unsigned long *) pgd);
 	}
+	if (current->active_mm == mm)
+		update_mm(mm, current);
 }
 #endif
 
@@ -1087,10 +1105,9 @@
 			continue;
 		/* Allocate new page table with pgstes */
 		new = page_table_alloc_pgste(mm, addr);
-		if (!new) {
-			mm->context.has_pgste = 0;
-			continue;
-		}
+		if (!new)
+			return -ENOMEM;
+
 		spin_lock(&mm->page_table_lock);
 		if (likely((unsigned long *) pmd_deref(*pmd) == table)) {
 			/* Nuke pmd entry pointing to the "short" page table */
@@ -1128,13 +1145,15 @@
 		if (pud_none_or_clear_bad(pud))
 			continue;
 		next = page_table_realloc_pmd(tlb, mm, pud, addr, next);
+		if (unlikely(IS_ERR_VALUE(next)))
+			return next;
 	} while (pud++, addr = next, addr != end);
 
 	return addr;
 }
 
-static void page_table_realloc(struct mmu_gather *tlb, struct mm_struct *mm,
-			       unsigned long addr, unsigned long end)
+static unsigned long page_table_realloc(struct mmu_gather *tlb, struct mm_struct *mm,
+					unsigned long addr, unsigned long end)
 {
 	unsigned long next;
 	pgd_t *pgd;
@@ -1145,7 +1164,11 @@
 		if (pgd_none_or_clear_bad(pgd))
 			continue;
 		next = page_table_realloc_pud(tlb, mm, pgd, addr, next);
+		if (unlikely(IS_ERR_VALUE(next)))
+			return next;
 	} while (pgd++, addr = next, addr != end);
+
+	return 0;
 }
 
 /*
@@ -1157,10 +1180,6 @@
 	struct mm_struct *mm = tsk->mm;
 	struct mmu_gather tlb;
 
-	/* Do we have switched amode? If no, we cannot do sie */
-	if (s390_user_mode == HOME_SPACE_MODE)
-		return -EINVAL;
-
 	/* Do we have pgstes? if yes, we are done */
 	if (mm_has_pgste(tsk->mm))
 		return 0;
@@ -1169,9 +1188,9 @@
 	/* split thp mappings and disable thp for future mappings */
 	thp_split_mm(mm);
 	/* Reallocate the page tables with pgstes */
-	mm->context.has_pgste = 1;
 	tlb_gather_mmu(&tlb, mm, 0, TASK_SIZE);
-	page_table_realloc(&tlb, mm, 0, TASK_SIZE);
+	if (!page_table_realloc(&tlb, mm, 0, TASK_SIZE))
+		mm->context.has_pgste = 1;
 	tlb_finish_mmu(&tlb, 0, TASK_SIZE);
 	up_write(&mm->mmap_sem);
 	return mm->context.has_pgste ? 0 : -ENOMEM;
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 7092392..16871da 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -12,8 +12,8 @@
 #include <linux/random.h>
 #include <linux/init.h>
 #include <asm/cacheflush.h>
-#include <asm/processor.h>
 #include <asm/facility.h>
+#include <asm/dis.h>
 
 /*
  * Conventions:
@@ -156,8 +156,8 @@
 		EMIT6(0xeb8ff058, 0x0024);
 		/* lgr %r14,%r15 */
 		EMIT4(0xb90400ef);
-		/* ahi %r15,<offset> */
-		EMIT4_IMM(0xa7fa0000, (jit->seen & SEEN_MEM) ? -112 : -80);
+		/* aghi %r15,<offset> */
+		EMIT4_IMM(0xa7fb0000, (jit->seen & SEEN_MEM) ? -112 : -80);
 		/* stg %r14,152(%r15) */
 		EMIT6(0xe3e0f098, 0x0024);
 	} else if ((jit->seen & SEEN_XREG) && (jit->seen & SEEN_LITERAL))
@@ -881,7 +881,9 @@
 	struct bpf_binary_header *header = (void *)addr;
 
 	if (fp->bpf_func == sk_run_filter)
-		return;
+		goto free_filter;
 	set_memory_rw(addr, header->pages);
 	module_free(NULL, header);
+free_filter:
+	kfree(fp);
 }
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index f17a834..0c9a177 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -120,26 +120,17 @@
 static int zpci_set_airq(struct zpci_dev *zdev)
 {
 	u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_REG_INT);
-	struct zpci_fib *fib;
-	int rc;
+	struct zpci_fib fib = {0};
 
-	fib = (void *) get_zeroed_page(GFP_KERNEL);
-	if (!fib)
-		return -ENOMEM;
+	fib.isc = PCI_ISC;
+	fib.sum = 1;		/* enable summary notifications */
+	fib.noi = airq_iv_end(zdev->aibv);
+	fib.aibv = (unsigned long) zdev->aibv->vector;
+	fib.aibvo = 0;		/* each zdev has its own interrupt vector */
+	fib.aisb = (unsigned long) zpci_aisb_iv->vector + (zdev->aisb/64)*8;
+	fib.aisbo = zdev->aisb & 63;
 
-	fib->isc = PCI_ISC;
-	fib->sum = 1;		/* enable summary notifications */
-	fib->noi = airq_iv_end(zdev->aibv);
-	fib->aibv = (unsigned long) zdev->aibv->vector;
-	fib->aibvo = 0;		/* each zdev has its own interrupt vector */
-	fib->aisb = (unsigned long) zpci_aisb_iv->vector + (zdev->aisb/64)*8;
-	fib->aisbo = zdev->aisb & 63;
-
-	rc = zpci_mod_fc(req, fib);
-	pr_debug("%s mpcifc returned noi: %d\n", __func__, fib->noi);
-
-	free_page((unsigned long) fib);
-	return rc;
+	return zpci_mod_fc(req, &fib);
 }
 
 struct mod_pci_args {
@@ -152,22 +143,14 @@
 static int mod_pci(struct zpci_dev *zdev, int fn, u8 dmaas, struct mod_pci_args *args)
 {
 	u64 req = ZPCI_CREATE_REQ(zdev->fh, dmaas, fn);
-	struct zpci_fib *fib;
-	int rc;
+	struct zpci_fib fib = {0};
 
-	/* The FIB must be available even if it's not used */
-	fib = (void *) get_zeroed_page(GFP_KERNEL);
-	if (!fib)
-		return -ENOMEM;
+	fib.pba = args->base;
+	fib.pal = args->limit;
+	fib.iota = args->iota;
+	fib.fmb_addr = args->fmb_addr;
 
-	fib->pba = args->base;
-	fib->pal = args->limit;
-	fib->iota = args->iota;
-	fib->fmb_addr = args->fmb_addr;
-
-	rc = zpci_mod_fc(req, fib);
-	free_page((unsigned long) fib);
-	return rc;
+	return zpci_mod_fc(req, &fib);
 }
 
 /* Modify PCI: Register I/O address translation parameters */
@@ -424,7 +407,6 @@
 	struct msi_msg msg;
 	int rc;
 
-	pr_debug("%s: requesting %d MSI-X interrupts...", __func__, nvec);
 	if (type != PCI_CAP_ID_MSIX && type != PCI_CAP_ID_MSI)
 		return -EINVAL;
 	msi_vecs = min(nvec, ZPCI_MSI_VEC_MAX);
@@ -489,7 +471,6 @@
 out_si:
 	airq_iv_free_bit(zpci_aisb_iv, aisb);
 out:
-	dev_err(&pdev->dev, "register MSI failed with: %d\n", rc);
 	return rc;
 }
 
@@ -499,14 +480,10 @@
 	struct msi_desc *msi;
 	int rc;
 
-	pr_info("%s: on pdev: %p\n", __func__, pdev);
-
 	/* Disable adapter interrupts */
 	rc = zpci_clear_airq(zdev);
-	if (rc) {
-		dev_err(&pdev->dev, "deregister MSI failed with: %d\n", rc);
+	if (rc)
 		return;
-	}
 
 	/* Release MSI interrupts */
 	list_for_each_entry(msi, &pdev->msi_list, list) {
@@ -625,8 +602,11 @@
 	r->name = name;
 
 	rc = request_resource(&iomem_resource, r);
-	if (rc)
-		pr_debug("request resource %pR failed\n", r);
+	if (rc) {
+		kfree(r->name);
+		kfree(r);
+		return ERR_PTR(-ENOMEM);
+	}
 	return r;
 }
 
@@ -708,6 +688,47 @@
 	zdev->pdev = NULL;
 }
 
+#ifdef CONFIG_HIBERNATE_CALLBACKS
+static int zpci_restore(struct device *dev)
+{
+	struct zpci_dev *zdev = get_zdev(to_pci_dev(dev));
+	int ret = 0;
+
+	if (zdev->state != ZPCI_FN_STATE_ONLINE)
+		goto out;
+
+	ret = clp_enable_fh(zdev, ZPCI_NR_DMA_SPACES);
+	if (ret)
+		goto out;
+
+	zpci_map_resources(zdev);
+	zpci_register_ioat(zdev, 0, zdev->start_dma + PAGE_OFFSET,
+			   zdev->start_dma + zdev->iommu_size - 1,
+			   (u64) zdev->dma_table);
+
+out:
+	return ret;
+}
+
+static int zpci_freeze(struct device *dev)
+{
+	struct zpci_dev *zdev = get_zdev(to_pci_dev(dev));
+
+	if (zdev->state != ZPCI_FN_STATE_ONLINE)
+		return 0;
+
+	zpci_unregister_ioat(zdev, 0);
+	return clp_disable_fh(zdev);
+}
+
+struct dev_pm_ops pcibios_pm_ops = {
+	.thaw_noirq = zpci_restore,
+	.freeze_noirq = zpci_freeze,
+	.restore_noirq = zpci_restore,
+	.poweroff_noirq = zpci_freeze,
+};
+#endif /* CONFIG_HIBERNATE_CALLBACKS */
+
 static int zpci_scan_bus(struct zpci_dev *zdev)
 {
 	struct resource *res;
@@ -781,7 +802,6 @@
 	rc = clp_enable_fh(zdev, ZPCI_NR_DMA_SPACES);
 	if (rc)
 		goto out;
-	pr_info("Enabled fh: 0x%x fid: 0x%x\n", zdev->fh, zdev->fid);
 
 	rc = zpci_dma_init_device(zdev);
 	if (rc)
@@ -901,10 +921,6 @@
 	    || !test_facility(71) || !test_facility(72))
 		return 0;
 
-	pr_info("Probing PCI hardware: PCI:%d  SID:%d  AEN:%d\n",
-		test_facility(69), test_facility(70),
-		test_facility(71));
-
 	rc = zpci_debug_init();
 	if (rc)
 		goto out;
diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c
index 475563c..8414798 100644
--- a/arch/s390/pci/pci_clp.c
+++ b/arch/s390/pci/pci_clp.c
@@ -16,6 +16,16 @@
 #include <asm/pci_debug.h>
 #include <asm/pci_clp.h>
 
+static inline void zpci_err_clp(unsigned int rsp, int rc)
+{
+	struct {
+		unsigned int rsp;
+		int rc;
+	} __packed data = {rsp, rc};
+
+	zpci_err_hex(&data, sizeof(data));
+}
+
 /*
  * Call Logical Processor
  * Retry logic is handled by the caller.
@@ -54,7 +64,6 @@
 	zdev->msi_addr = response->msia;
 	zdev->fmb_update = response->mui;
 
-	pr_debug("Supported number of MSI vectors: %u\n", response->noi);
 	switch (response->version) {
 	case 1:
 		zdev->max_bus_speed = PCIE_SPEED_5_0GT;
@@ -84,8 +93,8 @@
 	if (!rc && rrb->response.hdr.rsp == CLP_RC_OK)
 		clp_store_query_pci_fngrp(zdev, &rrb->response);
 	else {
-		pr_err("Query PCI FNGRP failed with response: %x  cc: %d\n",
-			rrb->response.hdr.rsp, rc);
+		zpci_err("Q PCI FGRP:\n");
+		zpci_err_clp(rrb->response.hdr.rsp, rc);
 		rc = -EIO;
 	}
 	clp_free_block(rrb);
@@ -131,8 +140,8 @@
 		if (rrb->response.pfgid)
 			rc = clp_query_pci_fngrp(zdev, rrb->response.pfgid);
 	} else {
-		pr_err("Query PCI failed with response: %x  cc: %d\n",
-			 rrb->response.hdr.rsp, rc);
+		zpci_err("Q PCI FN:\n");
+		zpci_err_clp(rrb->response.hdr.rsp, rc);
 		rc = -EIO;
 	}
 out:
@@ -206,8 +215,8 @@
 	if (!rc && rrb->response.hdr.rsp == CLP_RC_OK)
 		*fh = rrb->response.fh;
 	else {
-		zpci_dbg(0, "SPF fh:%x, cc:%d, resp:%x\n", *fh, rc,
-			 rrb->response.hdr.rsp);
+		zpci_err("Set PCI FN:\n");
+		zpci_err_clp(rrb->response.hdr.rsp, rc);
 		rc = -EIO;
 	}
 	clp_free_block(rrb);
@@ -262,8 +271,8 @@
 		/* Get PCI function handle list */
 		rc = clp_instr(rrb);
 		if (rc || rrb->response.hdr.rsp != CLP_RC_OK) {
-			pr_err("List PCI failed with response: 0x%x  cc: %d\n",
-				rrb->response.hdr.rsp, rc);
+			zpci_err("List PCI FN:\n");
+			zpci_err_clp(rrb->response.hdr.rsp, rc);
 			rc = -EIO;
 			goto out;
 		}
@@ -273,17 +282,11 @@
 
 		entries = (rrb->response.hdr.len - LIST_PCI_HDR_LEN) /
 			rrb->response.entry_size;
-		pr_info("Detected number of PCI functions: %u\n", entries);
 
-		/* Store the returned resume token as input for the next call */
 		resume_token = rrb->response.resume_token;
-
 		for (i = 0; i < entries; i++)
 			cb(&rrb->response.fh_list[i]);
 	} while (resume_token);
-
-	pr_debug("Maximum number of supported PCI functions: %u\n",
-		rrb->response.max_fn);
 out:
 	return rc;
 }
diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c
index 7e5573a..9b83d08 100644
--- a/arch/s390/pci/pci_dma.c
+++ b/arch/s390/pci/pci_dma.c
@@ -145,10 +145,8 @@
 		return -EINVAL;
 
 	spin_lock_irqsave(&zdev->dma_table_lock, irq_flags);
-	if (!zdev->dma_table) {
-		dev_err(&zdev->pdev->dev, "Missing DMA table\n");
+	if (!zdev->dma_table)
 		goto no_refresh;
-	}
 
 	for (i = 0; i < nr_pages; i++) {
 		dma_update_cpu_trans(zdev, page_addr, dma_addr, flags);
@@ -280,11 +278,8 @@
 	size = nr_pages * PAGE_SIZE;
 
 	dma_addr = zdev->start_dma + iommu_page_index * PAGE_SIZE;
-	if (dma_addr + size > zdev->end_dma) {
-		dev_err(dev, "(dma_addr: 0x%16.16LX + size: 0x%16.16lx) > end_dma: 0x%16.16Lx\n",
-			 dma_addr, size, zdev->end_dma);
+	if (dma_addr + size > zdev->end_dma)
 		goto out_free;
-	}
 
 	if (direction == DMA_NONE || direction == DMA_TO_DEVICE)
 		flags |= ZPCI_TABLE_PROTECTED;
@@ -297,7 +292,8 @@
 out_free:
 	dma_free_iommu(zdev, iommu_page_index, nr_pages);
 out_err:
-	dev_err(dev, "Failed to map addr: %lx\n", pa);
+	zpci_err("map error:\n");
+	zpci_err_hex(&pa, sizeof(pa));
 	return DMA_ERROR_CODE;
 }
 
@@ -312,8 +308,10 @@
 	npages = iommu_num_pages(dma_addr, size, PAGE_SIZE);
 	dma_addr = dma_addr & PAGE_MASK;
 	if (dma_update_trans(zdev, 0, dma_addr, npages * PAGE_SIZE,
-			     ZPCI_TABLE_PROTECTED | ZPCI_PTE_INVALID))
-		dev_err(dev, "Failed to unmap addr: %Lx\n", dma_addr);
+			     ZPCI_TABLE_PROTECTED | ZPCI_PTE_INVALID)) {
+		zpci_err("unmap error:\n");
+		zpci_err_hex(&dma_addr, sizeof(dma_addr));
+	}
 
 	atomic64_add(npages, (atomic64_t *) &zdev->fmb->unmapped_pages);
 	iommu_page_index = (dma_addr - zdev->start_dma) >> PAGE_SHIFT;
diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c
index 0aecaf9..278e671 100644
--- a/arch/s390/pci/pci_event.c
+++ b/arch/s390/pci/pci_event.c
@@ -10,6 +10,7 @@
 
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <asm/pci_debug.h>
 
 /* Content Code Description for PCI Function Error */
 struct zpci_ccdf_err {
@@ -41,25 +42,15 @@
 	u16 pec;			/* PCI event code */
 } __packed;
 
-static void zpci_event_log_err(struct zpci_ccdf_err *ccdf)
-{
-	struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
-
-	zpci_err("SEI error CCD:\n");
-	zpci_err_hex(ccdf, sizeof(*ccdf));
-	dev_err(&zdev->pdev->dev, "event code: 0x%x\n", ccdf->pec);
-}
-
 static void zpci_event_log_avail(struct zpci_ccdf_avail *ccdf)
 {
 	struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
+	struct pci_dev *pdev = zdev ? zdev->pdev : NULL;
 
-	pr_err("%s%s: availability event: fh: 0x%x  fid: 0x%x  event code: 0x%x  reason:",
-		(zdev) ? dev_driver_string(&zdev->pdev->dev) : "?",
-		(zdev) ? dev_name(&zdev->pdev->dev) : "?",
-		ccdf->fh, ccdf->fid, ccdf->pec);
-	print_hex_dump(KERN_CONT, "ccdf", DUMP_PREFIX_OFFSET,
-		       16, 1, ccdf, sizeof(*ccdf), false);
+	pr_info("%s: Event 0x%x reconfigured PCI function 0x%x\n",
+		pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid);
+	zpci_err("avail CCDF:\n");
+	zpci_err_hex(ccdf, sizeof(*ccdf));
 
 	switch (ccdf->pec) {
 	case 0x0301:
@@ -79,14 +70,16 @@
 void zpci_event_error(void *data)
 {
 	struct zpci_ccdf_err *ccdf = data;
-	struct zpci_dev *zdev;
+	struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
 
-	zpci_event_log_err(ccdf);
-	zdev = get_zdev_by_fid(ccdf->fid);
-	if (!zdev) {
-		pr_err("Error event for unknown fid: %x", ccdf->fid);
+	zpci_err("error CCDF:\n");
+	zpci_err_hex(ccdf, sizeof(*ccdf));
+
+	if (!zdev)
 		return;
-	}
+
+	pr_err("%s: Event 0x%x reports an error for PCI function 0x%x\n",
+	       pci_name(zdev->pdev), ccdf->pec, ccdf->fid);
 }
 
 void zpci_event_availability(void *data)
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index e1c7bb9..f3414ad 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -4,3 +4,4 @@
 generic-y += clkdev.h
 generic-y += trace_clock.h
 generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 280bea9..231efbb 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -34,3 +34,4 @@
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 063af10..0833736 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -149,47 +149,32 @@
 	hardirq_ctx[cpu] = NULL;
 }
 
-asmlinkage void do_softirq(void)
+void do_softirq_own_stack(void)
 {
-	unsigned long flags;
 	struct thread_info *curctx;
 	union irq_ctx *irqctx;
 	u32 *isp;
 
-	if (in_interrupt())
-		return;
+	curctx = current_thread_info();
+	irqctx = softirq_ctx[smp_processor_id()];
+	irqctx->tinfo.task = curctx->task;
+	irqctx->tinfo.previous_sp = current_stack_pointer;
 
-	local_irq_save(flags);
+	/* build the stack frame on the softirq stack */
+	isp = (u32 *)((char *)irqctx + sizeof(*irqctx));
 
-	if (local_softirq_pending()) {
-		curctx = current_thread_info();
-		irqctx = softirq_ctx[smp_processor_id()];
-		irqctx->tinfo.task = curctx->task;
-		irqctx->tinfo.previous_sp = current_stack_pointer;
-
-		/* build the stack frame on the softirq stack */
-		isp = (u32 *)((char *)irqctx + sizeof(*irqctx));
-
-		__asm__ __volatile__ (
-			"mov	r15, r9		\n"
-			"jsr	@%0		\n"
-			/* switch to the softirq stack */
-			" mov	%1, r15		\n"
-			/* restore the thread stack */
-			"mov	r9, r15		\n"
-			: /* no outputs */
-			: "r" (__do_softirq), "r" (isp)
-			: "memory", "r0", "r1", "r2", "r3", "r4",
-			  "r5", "r6", "r7", "r8", "r9", "r15", "t", "pr"
-		);
-
-		/*
-		 * Shouldn't happen, we returned above if in_interrupt():
-		 */
-		WARN_ON_ONCE(softirq_count());
-	}
-
-	local_irq_restore(flags);
+	__asm__ __volatile__ (
+		"mov	r15, r9		\n"
+		"jsr	@%0		\n"
+		/* switch to the softirq stack */
+		" mov	%1, r15		\n"
+		/* restore the thread stack */
+		"mov	r9, r15		\n"
+		: /* no outputs */
+		: "r" (__do_softirq), "r" (isp)
+		: "memory", "r0", "r1", "r2", "r3", "r4",
+		  "r5", "r6", "r7", "r8", "r9", "r15", "t", "pr"
+	);
 }
 #else
 static inline void handle_one_irq(unsigned int irq)
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 7e4a97f..bf39066 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -16,3 +16,4 @@
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += preempt.h
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h
index 5080d16..ec2e2e2 100644
--- a/arch/sparc/include/asm/jump_label.h
+++ b/arch/sparc/include/asm/jump_label.h
@@ -9,7 +9,7 @@
 
 static __always_inline bool arch_static_branch(struct static_key *key)
 {
-		asm goto("1:\n\t"
+		asm_volatile_goto("1:\n\t"
 			 "nop\n\t"
 			 "nop\n\t"
 			 ".pushsection __jump_table,  \"aw\"\n\t"
diff --git a/arch/sparc/include/asm/prom.h b/arch/sparc/include/asm/prom.h
index 67c6257..11ebd65 100644
--- a/arch/sparc/include/asm/prom.h
+++ b/arch/sparc/include/asm/prom.h
@@ -43,10 +43,6 @@
 				 const char *name,
 				 int def);
 extern int of_find_in_proplist(const char *list, const char *match, int len);
-#ifdef CONFIG_NUMA
-extern int of_node_to_nid(struct device_node *dp);
-#define of_node_to_nid of_node_to_nid
-#endif
 
 extern void prom_build_devicetree(void);
 extern void of_populate_present_mask(void);
@@ -63,13 +59,5 @@
 extern void irq_trans_init(struct device_node *dp);
 extern char *build_path_component(struct device_node *dp);
 
-/* SPARC has local implementations */
-extern int of_address_to_resource(struct device_node *dev, int index,
-				  struct resource *r);
-#define of_address_to_resource of_address_to_resource
-
-void __iomem *of_iomap(struct device_node *node, int index);
-#define of_iomap of_iomap
-
 #endif /* __KERNEL__ */
 #endif /* _SPARC_PROM_H */
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c
index d4840ce..666193f 100644
--- a/arch/sparc/kernel/irq_64.c
+++ b/arch/sparc/kernel/irq_64.c
@@ -698,30 +698,19 @@
 	set_irq_regs(old_regs);
 }
 
-void do_softirq(void)
+void do_softirq_own_stack(void)
 {
-	unsigned long flags;
+	void *orig_sp, *sp = softirq_stack[smp_processor_id()];
 
-	if (in_interrupt())
-		return;
+	sp += THREAD_SIZE - 192 - STACK_BIAS;
 
-	local_irq_save(flags);
-
-	if (local_softirq_pending()) {
-		void *orig_sp, *sp = softirq_stack[smp_processor_id()];
-
-		sp += THREAD_SIZE - 192 - STACK_BIAS;
-
-		__asm__ __volatile__("mov %%sp, %0\n\t"
-				     "mov %1, %%sp"
-				     : "=&r" (orig_sp)
-				     : "r" (sp));
-		__do_softirq();
-		__asm__ __volatile__("mov %0, %%sp"
-				     : : "r" (orig_sp));
-	}
-
-	local_irq_restore(flags);
+	__asm__ __volatile__("mov %%sp, %0\n\t"
+			     "mov %1, %%sp"
+			     : "=&r" (orig_sp)
+			     : "r" (sp));
+	__do_softirq();
+	__asm__ __volatile__("mov %0, %%sp"
+			     : : "r" (orig_sp));
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/sparc/kernel/prom_64.c b/arch/sparc/kernel/prom_64.c
index d397d7f..6b39125 100644
--- a/arch/sparc/kernel/prom_64.c
+++ b/arch/sparc/kernel/prom_64.c
@@ -373,6 +373,59 @@
 	return (tlb_type == spitfire ? "upa-portid" : "portid");
 }
 
+bool arch_find_n_match_cpu_physical_id(struct device_node *cpun,
+				       int cpu, unsigned int *thread)
+{
+	const char *mid_prop = get_mid_prop();
+	int this_cpu_id;
+
+	/* On hypervisor based platforms we interrogate the 'reg'
+	 * property.  On everything else we look for a 'upa-portis',
+	 * 'portid', or 'cpuid' property.
+	 */
+
+	if (tlb_type == hypervisor) {
+		struct property *prop = of_find_property(cpun, "reg", NULL);
+		u32 *regs;
+
+		if (!prop) {
+			pr_warn("CPU node missing reg property\n");
+			return false;
+		}
+		regs = prop->value;
+		this_cpu_id = regs[0] & 0x0fffffff;
+	} else {
+		this_cpu_id = of_getintprop_default(cpun, mid_prop, -1);
+
+		if (this_cpu_id < 0) {
+			mid_prop = "cpuid";
+			this_cpu_id = of_getintprop_default(cpun, mid_prop, -1);
+		}
+		if (this_cpu_id < 0) {
+			pr_warn("CPU node missing cpu ID property\n");
+			return false;
+		}
+	}
+	if (this_cpu_id == cpu) {
+		if (thread) {
+			int proc_id = cpu_data(cpu).proc_id;
+
+			/* On sparc64, the cpu thread information is obtained
+			 * either from OBP or the machine description.  We've
+			 * actually probed this information already long before
+			 * this interface gets called so instead of interrogating
+			 * both the OF node and the MDESC again, just use what
+			 * we discovered already.
+			 */
+			if (proc_id < 0)
+				proc_id = 0;
+			*thread = proc_id;
+		}
+		return true;
+	}
+	return false;
+}
+
 static void *of_iterate_over_cpus(void *(*func)(struct device_node *, int, int), int arg)
 {
 	struct device_node *dp;
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
index 9c7be59..218b6b2 100644
--- a/arch/sparc/net/bpf_jit_comp.c
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -808,4 +808,5 @@
 {
 	if (fp->bpf_func != sk_run_filter)
 		module_free(NULL, fp->bpf_func);
+	kfree(fp);
 }
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 664d6ad..22f3bd1 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -38,3 +38,4 @@
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/tile/include/asm/atomic.h b/arch/tile/include/asm/atomic.h
index d385eaa..7097984 100644
--- a/arch/tile/include/asm/atomic.h
+++ b/arch/tile/include/asm/atomic.h
@@ -166,7 +166,7 @@
  *
  * Atomically sets @v to @i and returns old @v
  */
-static inline u64 atomic64_xchg(atomic64_t *v, u64 n)
+static inline long long atomic64_xchg(atomic64_t *v, long long n)
 {
 	return xchg64(&v->counter, n);
 }
@@ -180,7 +180,8 @@
  * Atomically checks if @v holds @o and replaces it with @n if so.
  * Returns the old value at @v.
  */
-static inline u64 atomic64_cmpxchg(atomic64_t *v, u64 o, u64 n)
+static inline long long atomic64_cmpxchg(atomic64_t *v, long long o,
+					long long n)
 {
 	return cmpxchg64(&v->counter, o, n);
 }
diff --git a/arch/tile/include/asm/atomic_32.h b/arch/tile/include/asm/atomic_32.h
index 0d0395b..1ad4a1f 100644
--- a/arch/tile/include/asm/atomic_32.h
+++ b/arch/tile/include/asm/atomic_32.h
@@ -80,7 +80,7 @@
 /* A 64bit atomic type */
 
 typedef struct {
-	u64 __aligned(8) counter;
+	long long counter;
 } atomic64_t;
 
 #define ATOMIC64_INIT(val) { (val) }
@@ -91,14 +91,14 @@
  *
  * Atomically reads the value of @v.
  */
-static inline u64 atomic64_read(const atomic64_t *v)
+static inline long long atomic64_read(const atomic64_t *v)
 {
 	/*
 	 * Requires an atomic op to read both 32-bit parts consistently.
 	 * Casting away const is safe since the atomic support routines
 	 * do not write to memory if the value has not been modified.
 	 */
-	return _atomic64_xchg_add((u64 *)&v->counter, 0);
+	return _atomic64_xchg_add((long long *)&v->counter, 0);
 }
 
 /**
@@ -108,7 +108,7 @@
  *
  * Atomically adds @i to @v.
  */
-static inline void atomic64_add(u64 i, atomic64_t *v)
+static inline void atomic64_add(long long i, atomic64_t *v)
 {
 	_atomic64_xchg_add(&v->counter, i);
 }
@@ -120,7 +120,7 @@
  *
  * Atomically adds @i to @v and returns @i + @v
  */
-static inline u64 atomic64_add_return(u64 i, atomic64_t *v)
+static inline long long atomic64_add_return(long long i, atomic64_t *v)
 {
 	smp_mb();  /* barrier for proper semantics */
 	return _atomic64_xchg_add(&v->counter, i) + i;
@@ -135,7 +135,8 @@
  * Atomically adds @a to @v, so long as @v was not already @u.
  * Returns non-zero if @v was not @u, and zero otherwise.
  */
-static inline u64 atomic64_add_unless(atomic64_t *v, u64 a, u64 u)
+static inline long long atomic64_add_unless(atomic64_t *v, long long a,
+					long long u)
 {
 	smp_mb();  /* barrier for proper semantics */
 	return _atomic64_xchg_add_unless(&v->counter, a, u) != u;
@@ -151,7 +152,7 @@
  * atomic64_set() can't be just a raw store, since it would be lost if it
  * fell between the load and store of one of the other atomic ops.
  */
-static inline void atomic64_set(atomic64_t *v, u64 n)
+static inline void atomic64_set(atomic64_t *v, long long n)
 {
 	_atomic64_xchg(&v->counter, n);
 }
@@ -236,11 +237,13 @@
 extern struct __get_user __atomic_or(volatile int *p, int *lock, int n);
 extern struct __get_user __atomic_andn(volatile int *p, int *lock, int n);
 extern struct __get_user __atomic_xor(volatile int *p, int *lock, int n);
-extern u64 __atomic64_cmpxchg(volatile u64 *p, int *lock, u64 o, u64 n);
-extern u64 __atomic64_xchg(volatile u64 *p, int *lock, u64 n);
-extern u64 __atomic64_xchg_add(volatile u64 *p, int *lock, u64 n);
-extern u64 __atomic64_xchg_add_unless(volatile u64 *p,
-				      int *lock, u64 o, u64 n);
+extern long long __atomic64_cmpxchg(volatile long long *p, int *lock,
+					long long o, long long n);
+extern long long __atomic64_xchg(volatile long long *p, int *lock, long long n);
+extern long long __atomic64_xchg_add(volatile long long *p, int *lock,
+					long long n);
+extern long long __atomic64_xchg_add_unless(volatile long long *p,
+					int *lock, long long o, long long n);
 
 /* Return failure from the atomic wrappers. */
 struct __get_user __atomic_bad_address(int __user *addr);
diff --git a/arch/tile/include/asm/cmpxchg.h b/arch/tile/include/asm/cmpxchg.h
index 4001d5e..0ccda3c 100644
--- a/arch/tile/include/asm/cmpxchg.h
+++ b/arch/tile/include/asm/cmpxchg.h
@@ -35,10 +35,10 @@
 int _atomic_xchg_add(int *v, int i);
 int _atomic_xchg_add_unless(int *v, int a, int u);
 int _atomic_cmpxchg(int *ptr, int o, int n);
-u64 _atomic64_xchg(u64 *v, u64 n);
-u64 _atomic64_xchg_add(u64 *v, u64 i);
-u64 _atomic64_xchg_add_unless(u64 *v, u64 a, u64 u);
-u64 _atomic64_cmpxchg(u64 *v, u64 o, u64 n);
+long long _atomic64_xchg(long long *v, long long n);
+long long _atomic64_xchg_add(long long *v, long long i);
+long long _atomic64_xchg_add_unless(long long *v, long long a, long long u);
+long long _atomic64_cmpxchg(long long *v, long long o, long long n);
 
 #define xchg(ptr, n)							\
 	({								\
@@ -53,7 +53,8 @@
 		if (sizeof(*(ptr)) != 4)				\
 			__cmpxchg_called_with_bad_pointer();		\
 		smp_mb();						\
-		(typeof(*(ptr)))_atomic_cmpxchg((int *)ptr, (int)o, (int)n); \
+		(typeof(*(ptr)))_atomic_cmpxchg((int *)ptr, (int)o,	\
+						(int)n);		\
 	})
 
 #define xchg64(ptr, n)							\
@@ -61,7 +62,8 @@
 		if (sizeof(*(ptr)) != 8)				\
 			__xchg_called_with_bad_pointer();		\
 		smp_mb();						\
-		(typeof(*(ptr)))_atomic64_xchg((u64 *)(ptr), (u64)(n));	\
+		(typeof(*(ptr)))_atomic64_xchg((long long *)(ptr),	\
+						(long long)(n));	\
 	})
 
 #define cmpxchg64(ptr, o, n)						\
@@ -69,7 +71,8 @@
 		if (sizeof(*(ptr)) != 8)				\
 			__cmpxchg_called_with_bad_pointer();		\
 		smp_mb();						\
-		(typeof(*(ptr)))_atomic64_cmpxchg((u64 *)ptr, (u64)o, (u64)n); \
+		(typeof(*(ptr)))_atomic64_cmpxchg((long long *)ptr,	\
+					(long long)o, (long long)n);	\
 	})
 
 #else
@@ -81,10 +84,11 @@
 		switch (sizeof(*(ptr))) {				\
 		case 4:							\
 			__x = (typeof(__x))(unsigned long)		\
-				__insn_exch4((ptr), (u32)(unsigned long)(n)); \
+				__insn_exch4((ptr),			\
+					(u32)(unsigned long)(n));	\
 			break;						\
 		case 8:							\
-			__x = (typeof(__x))			\
+			__x = (typeof(__x))				\
 				__insn_exch((ptr), (unsigned long)(n));	\
 			break;						\
 		default:						\
@@ -103,10 +107,12 @@
 		switch (sizeof(*(ptr))) {				\
 		case 4:							\
 			__x = (typeof(__x))(unsigned long)		\
-				__insn_cmpexch4((ptr), (u32)(unsigned long)(n)); \
+				__insn_cmpexch4((ptr),			\
+					(u32)(unsigned long)(n));	\
 			break;						\
 		case 8:							\
-			__x = (typeof(__x))__insn_cmpexch((ptr), (u64)(n)); \
+			__x = (typeof(__x))__insn_cmpexch((ptr),	\
+						(long long)(n));	\
 			break;						\
 		default:						\
 			__cmpxchg_called_with_bad_pointer();		\
diff --git a/arch/tile/include/asm/percpu.h b/arch/tile/include/asm/percpu.h
index 63294f5..4f7ae39 100644
--- a/arch/tile/include/asm/percpu.h
+++ b/arch/tile/include/asm/percpu.h
@@ -15,9 +15,37 @@
 #ifndef _ASM_TILE_PERCPU_H
 #define _ASM_TILE_PERCPU_H
 
-register unsigned long __my_cpu_offset __asm__("tp");
-#define __my_cpu_offset __my_cpu_offset
-#define set_my_cpu_offset(tp) (__my_cpu_offset = (tp))
+register unsigned long my_cpu_offset_reg asm("tp");
+
+#ifdef CONFIG_PREEMPT
+/*
+ * For full preemption, we can't just use the register variable
+ * directly, since we need barrier() to hazard against it, causing the
+ * compiler to reload anything computed from a previous "tp" value.
+ * But we also don't want to use volatile asm, since we'd like the
+ * compiler to be able to cache the value across multiple percpu reads.
+ * So we use a fake stack read as a hazard against barrier().
+ * The 'U' constraint is like 'm' but disallows postincrement.
+ */
+static inline unsigned long __my_cpu_offset(void)
+{
+	unsigned long tp;
+	register unsigned long *sp asm("sp");
+	asm("move %0, tp" : "=r" (tp) : "U" (*sp));
+	return tp;
+}
+#define __my_cpu_offset __my_cpu_offset()
+#else
+/*
+ * We don't need to hazard against barrier() since "tp" doesn't ever
+ * change with PREEMPT_NONE, and with PREEMPT_VOLUNTARY it only
+ * changes at function call points, at which we are already re-reading
+ * the value of "tp" due to "my_cpu_offset_reg" being a global variable.
+ */
+#define __my_cpu_offset my_cpu_offset_reg
+#endif
+
+#define set_my_cpu_offset(tp) (my_cpu_offset_reg = (tp))
 
 #include <asm-generic/percpu.h>
 
diff --git a/arch/tile/kernel/hardwall.c b/arch/tile/kernel/hardwall.c
index df27a1f..531f4c3 100644
--- a/arch/tile/kernel/hardwall.c
+++ b/arch/tile/kernel/hardwall.c
@@ -66,7 +66,7 @@
 		0,
 		"udn",
 		LIST_HEAD_INIT(hardwall_types[HARDWALL_UDN].list),
-		__SPIN_LOCK_INITIALIZER(hardwall_types[HARDWALL_UDN].lock),
+		__SPIN_LOCK_UNLOCKED(hardwall_types[HARDWALL_UDN].lock),
 		NULL
 	},
 #ifndef __tilepro__
@@ -77,7 +77,7 @@
 		1,  /* disabled pending hypervisor support */
 		"idn",
 		LIST_HEAD_INIT(hardwall_types[HARDWALL_IDN].list),
-		__SPIN_LOCK_INITIALIZER(hardwall_types[HARDWALL_IDN].lock),
+		__SPIN_LOCK_UNLOCKED(hardwall_types[HARDWALL_IDN].lock),
 		NULL
 	},
 	{  /* access to user-space IPI */
@@ -87,7 +87,7 @@
 		0,
 		"ipi",
 		LIST_HEAD_INIT(hardwall_types[HARDWALL_IPI].list),
-		__SPIN_LOCK_INITIALIZER(hardwall_types[HARDWALL_IPI].lock),
+		__SPIN_LOCK_UNLOCKED(hardwall_types[HARDWALL_IPI].lock),
 		NULL
 	},
 #endif
diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S
index 088d5c1..2cbe6d5 100644
--- a/arch/tile/kernel/intvec_32.S
+++ b/arch/tile/kernel/intvec_32.S
@@ -815,6 +815,9 @@
 	}
 	bzt     r28, 1f
 	bnz     r29, 1f
+	/* Disable interrupts explicitly for preemption. */
+	IRQ_DISABLE(r20,r21)
+	TRACE_IRQS_OFF
 	jal     preempt_schedule_irq
 	FEEDBACK_REENTER(interrupt_return)
 1:
diff --git a/arch/tile/kernel/intvec_64.S b/arch/tile/kernel/intvec_64.S
index ec755d3..b8fc497 100644
--- a/arch/tile/kernel/intvec_64.S
+++ b/arch/tile/kernel/intvec_64.S
@@ -841,6 +841,9 @@
 	}
 	beqzt   r28, 1f
 	bnez    r29, 1f
+	/* Disable interrupts explicitly for preemption. */
+	IRQ_DISABLE(r20,r21)
+	TRACE_IRQS_OFF
 	jal     preempt_schedule_irq
 	FEEDBACK_REENTER(interrupt_return)
 1:
diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c
index 362284a..c93977a 100644
--- a/arch/tile/kernel/stack.c
+++ b/arch/tile/kernel/stack.c
@@ -23,6 +23,7 @@
 #include <linux/mmzone.h>
 #include <linux/dcache.h>
 #include <linux/fs.h>
+#include <linux/string.h>
 #include <asm/backtrace.h>
 #include <asm/page.h>
 #include <asm/ucontext.h>
@@ -332,21 +333,18 @@
 	}
 
 	if (vma->vm_file) {
-		char *s;
 		p = d_path(&vma->vm_file->f_path, buf, bufsize);
 		if (IS_ERR(p))
 			p = "?";
-		s = strrchr(p, '/');
-		if (s)
-			p = s+1;
+		name = kbasename(p);
 	} else {
-		p = "anon";
+		name = "anon";
 	}
 
 	/* Generate a string description of the vma info. */
-	namelen = strlen(p);
+	namelen = strlen(name);
 	remaining = (bufsize - 1) - namelen;
-	memmove(buf, p, namelen);
+	memmove(buf, name, namelen);
 	snprintf(buf + namelen, remaining, "[%lx+%lx] ",
 		 vma->vm_start, vma->vm_end - vma->vm_start);
 }
diff --git a/arch/tile/lib/atomic_32.c b/arch/tile/lib/atomic_32.c
index 759efa3..c89b211 100644
--- a/arch/tile/lib/atomic_32.c
+++ b/arch/tile/lib/atomic_32.c
@@ -107,19 +107,19 @@
 EXPORT_SYMBOL(_atomic_xor);
 
 
-u64 _atomic64_xchg(u64 *v, u64 n)
+long long _atomic64_xchg(long long *v, long long n)
 {
 	return __atomic64_xchg(v, __atomic_setup(v), n);
 }
 EXPORT_SYMBOL(_atomic64_xchg);
 
-u64 _atomic64_xchg_add(u64 *v, u64 i)
+long long _atomic64_xchg_add(long long *v, long long i)
 {
 	return __atomic64_xchg_add(v, __atomic_setup(v), i);
 }
 EXPORT_SYMBOL(_atomic64_xchg_add);
 
-u64 _atomic64_xchg_add_unless(u64 *v, u64 a, u64 u)
+long long _atomic64_xchg_add_unless(long long *v, long long a, long long u)
 {
 	/*
 	 * Note: argument order is switched here since it is easier
@@ -130,7 +130,7 @@
 }
 EXPORT_SYMBOL(_atomic64_xchg_add_unless);
 
-u64 _atomic64_cmpxchg(u64 *v, u64 o, u64 n)
+long long _atomic64_cmpxchg(long long *v, long long o, long long n)
 {
 	return __atomic64_cmpxchg(v, __atomic_setup(v), o, n);
 }
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index b30f34a..fdde187 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -3,3 +3,4 @@
 generic-y += ftrace.h pci.h io.h param.h delay.h mutex.h current.h exec.h
 generic-y += switch_to.h clkdev.h
 generic-y += trace_clock.h
+generic-y += preempt.h
diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c
index 829df49..41ebbfe 100644
--- a/arch/um/kernel/exitcode.c
+++ b/arch/um/kernel/exitcode.c
@@ -40,9 +40,11 @@
 		const char __user *buffer, size_t count, loff_t *pos)
 {
 	char *end, buf[sizeof("nnnnn\0")];
+	size_t size;
 	int tmp;
 
-	if (copy_from_user(buf, buffer, count))
+	size = min(count, sizeof(buf));
+	if (copy_from_user(buf, buffer, size))
 		return -EFAULT;
 
 	tmp = simple_strtol(buf, &end, 0);
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 89d8b6c..00045cb 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -60,3 +60,4 @@
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index ee2fb9d..725e157 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -123,6 +123,7 @@
 	select COMPAT_OLD_SIGACTION if IA32_EMULATION
 	select RTC_LIB
 	select HAVE_DEBUG_STACKOVERFLOW
+	select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64
 
 config INSTRUCTION_DECODER
 	def_bool y
@@ -756,20 +757,25 @@
 	  BIOS code.
 
 config GART_IOMMU
-	bool "GART IOMMU support" if EXPERT
-	default y
+	bool "Old AMD GART IOMMU support"
 	select SWIOTLB
 	depends on X86_64 && PCI && AMD_NB
 	---help---
-	  Support for full DMA access of devices with 32bit memory access only
-	  on systems with more than 3GB. This is usually needed for USB,
-	  sound, many IDE/SATA chipsets and some other devices.
-	  Provides a driver for the AMD Athlon64/Opteron/Turion/Sempron GART
-	  based hardware IOMMU and a software bounce buffer based IOMMU used
-	  on Intel systems and as fallback.
-	  The code is only active when needed (enough memory and limited
-	  device) unless CONFIG_IOMMU_DEBUG or iommu=force is specified
-	  too.
+	  Provides a driver for older AMD Athlon64/Opteron/Turion/Sempron
+	  GART based hardware IOMMUs.
+
+	  The GART supports full DMA access for devices with 32-bit access
+	  limitations, on systems with more than 3 GB. This is usually needed
+	  for USB, sound, many IDE/SATA chipsets and some other devices.
+
+	  Newer systems typically have a modern AMD IOMMU, supported via
+	  the CONFIG_AMD_IOMMU=y config option.
+
+	  In normal configurations this driver is only active when needed:
+	  there's more than 3 GB of memory and the system contains a
+	  32-bit limited device.
+
+	  If unsure, say Y.
 
 config CALGARY_IOMMU
 	bool "IBM Calgary IOMMU support"
@@ -825,14 +831,16 @@
 config NR_CPUS
 	int "Maximum number of CPUs" if SMP && !MAXSMP
 	range 2 8 if SMP && X86_32 && !X86_BIGSMP
-	range 2 512 if SMP && !MAXSMP
+	range 2 512 if SMP && !MAXSMP && !CPUMASK_OFFSTACK
+	range 2 8192 if SMP && !MAXSMP && CPUMASK_OFFSTACK && X86_64
 	default "1" if !SMP
-	default "4096" if MAXSMP
+	default "8192" if MAXSMP
 	default "32" if SMP && (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP || X86_ES7000)
 	default "8" if SMP
 	---help---
 	  This allows you to specify the maximum number of CPUs which this
-	  kernel will support.  The maximum supported value is 512 and the
+	  kernel will support.  If CPUMASK_OFFSTACK is enabled, the maximum
+	  supported value is 4096, otherwise the maximum value is 512.  The
 	  minimum value which makes sense is 2.
 
 	  This is purely to save memory - each supported CPU adds
@@ -860,7 +868,7 @@
 
 config X86_UP_APIC
 	bool "Local APIC support on uniprocessors"
-	depends on X86_32 && !SMP && !X86_32_NON_STANDARD
+	depends on X86_32 && !SMP && !X86_32_NON_STANDARD && !PCI_MSI
 	---help---
 	  A local APIC (Advanced Programmable Interrupt Controller) is an
 	  integrated interrupt controller in the CPU. If you have a single-CPU
@@ -885,11 +893,11 @@
 
 config X86_LOCAL_APIC
 	def_bool y
-	depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC
+	depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC || PCI_MSI
 
 config X86_IO_APIC
 	def_bool y
-	depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC
+	depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC || PCI_MSI
 
 config X86_VISWS_APIC
 	def_bool y
@@ -1033,6 +1041,7 @@
 
 config MICROCODE
 	tristate "CPU microcode loading support"
+	depends on CPU_SUP_AMD || CPU_SUP_INTEL
 	select FW_LOADER
 	---help---
 
@@ -1593,7 +1602,7 @@
           This kernel feature allows a bzImage to be loaded directly
 	  by EFI firmware without the use of a bootloader.
 
-	  See Documentation/x86/efi-stub.txt for more information.
+	  See Documentation/efi-stub.txt for more information.
 
 config SECCOMP
 	def_bool y
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 78d91af..0f3621e 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -59,6 +59,16 @@
 	  with klogd/syslogd or the X server. You should normally N here,
 	  unless you want to debug such a crash. You need usb debug device.
 
+config EARLY_PRINTK_EFI
+	bool "Early printk via the EFI framebuffer"
+	depends on EFI && EARLY_PRINTK
+	select FONT_SUPPORT
+	---help---
+	  Write kernel log output directly into the EFI framebuffer.
+
+	  This is useful for kernel debugging when your machine crashes very
+	  early before the console code is initialized.
+
 config X86_PTDUMP
 	bool "Export kernel pagetable layout to userspace via debugfs"
 	depends on DEBUG_KERNEL
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index 379814b..dce69a2 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -71,7 +71,8 @@
 $(obj)/bzImage: asflags-y  := $(SVGA_MODE)
 
 quiet_cmd_image = BUILD   $@
-cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/zoffset.h > $@
+cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin \
+			       $(obj)/zoffset.h $@
 
 $(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE
 	$(call if_changed,image)
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index b7388a4..a7677ba 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -19,214 +19,10 @@
 
 static efi_system_table_t *sys_table;
 
-static void efi_char16_printk(efi_char16_t *str)
-{
-	struct efi_simple_text_output_protocol *out;
 
-	out = (struct efi_simple_text_output_protocol *)sys_table->con_out;
-	efi_call_phys2(out->output_string, out, str);
-}
+#include "../../../../drivers/firmware/efi/efi-stub-helper.c"
 
-static void efi_printk(char *str)
-{
-	char *s8;
 
-	for (s8 = str; *s8; s8++) {
-		efi_char16_t ch[2] = { 0 };
-
-		ch[0] = *s8;
-		if (*s8 == '\n') {
-			efi_char16_t nl[2] = { '\r', 0 };
-			efi_char16_printk(nl);
-		}
-
-		efi_char16_printk(ch);
-	}
-}
-
-static efi_status_t __get_map(efi_memory_desc_t **map, unsigned long *map_size,
-			      unsigned long *desc_size)
-{
-	efi_memory_desc_t *m = NULL;
-	efi_status_t status;
-	unsigned long key;
-	u32 desc_version;
-
-	*map_size = sizeof(*m) * 32;
-again:
-	/*
-	 * Add an additional efi_memory_desc_t because we're doing an
-	 * allocation which may be in a new descriptor region.
-	 */
-	*map_size += sizeof(*m);
-	status = efi_call_phys3(sys_table->boottime->allocate_pool,
-				EFI_LOADER_DATA, *map_size, (void **)&m);
-	if (status != EFI_SUCCESS)
-		goto fail;
-
-	status = efi_call_phys5(sys_table->boottime->get_memory_map, map_size,
-				m, &key, desc_size, &desc_version);
-	if (status == EFI_BUFFER_TOO_SMALL) {
-		efi_call_phys1(sys_table->boottime->free_pool, m);
-		goto again;
-	}
-
-	if (status != EFI_SUCCESS)
-		efi_call_phys1(sys_table->boottime->free_pool, m);
-
-fail:
-	*map = m;
-	return status;
-}
-
-/*
- * Allocate at the highest possible address that is not above 'max'.
- */
-static efi_status_t high_alloc(unsigned long size, unsigned long align,
-			      unsigned long *addr, unsigned long max)
-{
-	unsigned long map_size, desc_size;
-	efi_memory_desc_t *map;
-	efi_status_t status;
-	unsigned long nr_pages;
-	u64 max_addr = 0;
-	int i;
-
-	status = __get_map(&map, &map_size, &desc_size);
-	if (status != EFI_SUCCESS)
-		goto fail;
-
-	nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
-again:
-	for (i = 0; i < map_size / desc_size; i++) {
-		efi_memory_desc_t *desc;
-		unsigned long m = (unsigned long)map;
-		u64 start, end;
-
-		desc = (efi_memory_desc_t *)(m + (i * desc_size));
-		if (desc->type != EFI_CONVENTIONAL_MEMORY)
-			continue;
-
-		if (desc->num_pages < nr_pages)
-			continue;
-
-		start = desc->phys_addr;
-		end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT);
-
-		if ((start + size) > end || (start + size) > max)
-			continue;
-
-		if (end - size > max)
-			end = max;
-
-		if (round_down(end - size, align) < start)
-			continue;
-
-		start = round_down(end - size, align);
-
-		/*
-		 * Don't allocate at 0x0. It will confuse code that
-		 * checks pointers against NULL.
-		 */
-		if (start == 0x0)
-			continue;
-
-		if (start > max_addr)
-			max_addr = start;
-	}
-
-	if (!max_addr)
-		status = EFI_NOT_FOUND;
-	else {
-		status = efi_call_phys4(sys_table->boottime->allocate_pages,
-					EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
-					nr_pages, &max_addr);
-		if (status != EFI_SUCCESS) {
-			max = max_addr;
-			max_addr = 0;
-			goto again;
-		}
-
-		*addr = max_addr;
-	}
-
-free_pool:
-	efi_call_phys1(sys_table->boottime->free_pool, map);
-
-fail:
-	return status;
-}
-
-/*
- * Allocate at the lowest possible address.
- */
-static efi_status_t low_alloc(unsigned long size, unsigned long align,
-			      unsigned long *addr)
-{
-	unsigned long map_size, desc_size;
-	efi_memory_desc_t *map;
-	efi_status_t status;
-	unsigned long nr_pages;
-	int i;
-
-	status = __get_map(&map, &map_size, &desc_size);
-	if (status != EFI_SUCCESS)
-		goto fail;
-
-	nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
-	for (i = 0; i < map_size / desc_size; i++) {
-		efi_memory_desc_t *desc;
-		unsigned long m = (unsigned long)map;
-		u64 start, end;
-
-		desc = (efi_memory_desc_t *)(m + (i * desc_size));
-
-		if (desc->type != EFI_CONVENTIONAL_MEMORY)
-			continue;
-
-		if (desc->num_pages < nr_pages)
-			continue;
-
-		start = desc->phys_addr;
-		end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT);
-
-		/*
-		 * Don't allocate at 0x0. It will confuse code that
-		 * checks pointers against NULL. Skip the first 8
-		 * bytes so we start at a nice even number.
-		 */
-		if (start == 0x0)
-			start += 8;
-
-		start = round_up(start, align);
-		if ((start + size) > end)
-			continue;
-
-		status = efi_call_phys4(sys_table->boottime->allocate_pages,
-					EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
-					nr_pages, &start);
-		if (status == EFI_SUCCESS) {
-			*addr = start;
-			break;
-		}
-	}
-
-	if (i == map_size / desc_size)
-		status = EFI_NOT_FOUND;
-
-free_pool:
-	efi_call_phys1(sys_table->boottime->free_pool, map);
-fail:
-	return status;
-}
-
-static void low_free(unsigned long size, unsigned long addr)
-{
-	unsigned long nr_pages;
-
-	nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
-	efi_call_phys2(sys_table->boottime->free_pages, addr, nr_pages);
-}
 
 static void find_bits(unsigned long mask, u8 *pos, u8 *size)
 {
@@ -624,242 +420,6 @@
 	}
 }
 
-struct initrd {
-	efi_file_handle_t *handle;
-	u64 size;
-};
-
-/*
- * Check the cmdline for a LILO-style initrd= arguments.
- *
- * We only support loading an initrd from the same filesystem as the
- * kernel image.
- */
-static efi_status_t handle_ramdisks(efi_loaded_image_t *image,
-				    struct setup_header *hdr)
-{
-	struct initrd *initrds;
-	unsigned long initrd_addr;
-	efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
-	u64 initrd_total;
-	efi_file_io_interface_t *io;
-	efi_file_handle_t *fh;
-	efi_status_t status;
-	int nr_initrds;
-	char *str;
-	int i, j, k;
-
-	initrd_addr = 0;
-	initrd_total = 0;
-
-	str = (char *)(unsigned long)hdr->cmd_line_ptr;
-
-	j = 0;			/* See close_handles */
-
-	if (!str || !*str)
-		return EFI_SUCCESS;
-
-	for (nr_initrds = 0; *str; nr_initrds++) {
-		str = strstr(str, "initrd=");
-		if (!str)
-			break;
-
-		str += 7;
-
-		/* Skip any leading slashes */
-		while (*str == '/' || *str == '\\')
-			str++;
-
-		while (*str && *str != ' ' && *str != '\n')
-			str++;
-	}
-
-	if (!nr_initrds)
-		return EFI_SUCCESS;
-
-	status = efi_call_phys3(sys_table->boottime->allocate_pool,
-				EFI_LOADER_DATA,
-				nr_initrds * sizeof(*initrds),
-				&initrds);
-	if (status != EFI_SUCCESS) {
-		efi_printk("Failed to alloc mem for initrds\n");
-		goto fail;
-	}
-
-	str = (char *)(unsigned long)hdr->cmd_line_ptr;
-	for (i = 0; i < nr_initrds; i++) {
-		struct initrd *initrd;
-		efi_file_handle_t *h;
-		efi_file_info_t *info;
-		efi_char16_t filename_16[256];
-		unsigned long info_sz;
-		efi_guid_t info_guid = EFI_FILE_INFO_ID;
-		efi_char16_t *p;
-		u64 file_sz;
-
-		str = strstr(str, "initrd=");
-		if (!str)
-			break;
-
-		str += 7;
-
-		initrd = &initrds[i];
-		p = filename_16;
-
-		/* Skip any leading slashes */
-		while (*str == '/' || *str == '\\')
-			str++;
-
-		while (*str && *str != ' ' && *str != '\n') {
-			if ((u8 *)p >= (u8 *)filename_16 + sizeof(filename_16))
-				break;
-
-			if (*str == '/') {
-				*p++ = '\\';
-				*str++;
-			} else {
-				*p++ = *str++;
-			}
-		}
-
-		*p = '\0';
-
-		/* Only open the volume once. */
-		if (!i) {
-			efi_boot_services_t *boottime;
-
-			boottime = sys_table->boottime;
-
-			status = efi_call_phys3(boottime->handle_protocol,
-					image->device_handle, &fs_proto, &io);
-			if (status != EFI_SUCCESS) {
-				efi_printk("Failed to handle fs_proto\n");
-				goto free_initrds;
-			}
-
-			status = efi_call_phys2(io->open_volume, io, &fh);
-			if (status != EFI_SUCCESS) {
-				efi_printk("Failed to open volume\n");
-				goto free_initrds;
-			}
-		}
-
-		status = efi_call_phys5(fh->open, fh, &h, filename_16,
-					EFI_FILE_MODE_READ, (u64)0);
-		if (status != EFI_SUCCESS) {
-			efi_printk("Failed to open initrd file: ");
-			efi_char16_printk(filename_16);
-			efi_printk("\n");
-			goto close_handles;
-		}
-
-		initrd->handle = h;
-
-		info_sz = 0;
-		status = efi_call_phys4(h->get_info, h, &info_guid,
-					&info_sz, NULL);
-		if (status != EFI_BUFFER_TOO_SMALL) {
-			efi_printk("Failed to get initrd info size\n");
-			goto close_handles;
-		}
-
-grow:
-		status = efi_call_phys3(sys_table->boottime->allocate_pool,
-					EFI_LOADER_DATA, info_sz, &info);
-		if (status != EFI_SUCCESS) {
-			efi_printk("Failed to alloc mem for initrd info\n");
-			goto close_handles;
-		}
-
-		status = efi_call_phys4(h->get_info, h, &info_guid,
-					&info_sz, info);
-		if (status == EFI_BUFFER_TOO_SMALL) {
-			efi_call_phys1(sys_table->boottime->free_pool, info);
-			goto grow;
-		}
-
-		file_sz = info->file_size;
-		efi_call_phys1(sys_table->boottime->free_pool, info);
-
-		if (status != EFI_SUCCESS) {
-			efi_printk("Failed to get initrd info\n");
-			goto close_handles;
-		}
-
-		initrd->size = file_sz;
-		initrd_total += file_sz;
-	}
-
-	if (initrd_total) {
-		unsigned long addr;
-
-		/*
-		 * Multiple initrd's need to be at consecutive
-		 * addresses in memory, so allocate enough memory for
-		 * all the initrd's.
-		 */
-		status = high_alloc(initrd_total, 0x1000,
-				   &initrd_addr, hdr->initrd_addr_max);
-		if (status != EFI_SUCCESS) {
-			efi_printk("Failed to alloc highmem for initrds\n");
-			goto close_handles;
-		}
-
-		/* We've run out of free low memory. */
-		if (initrd_addr > hdr->initrd_addr_max) {
-			efi_printk("We've run out of free low memory\n");
-			status = EFI_INVALID_PARAMETER;
-			goto free_initrd_total;
-		}
-
-		addr = initrd_addr;
-		for (j = 0; j < nr_initrds; j++) {
-			u64 size;
-
-			size = initrds[j].size;
-			while (size) {
-				u64 chunksize;
-				if (size > EFI_READ_CHUNK_SIZE)
-					chunksize = EFI_READ_CHUNK_SIZE;
-				else
-					chunksize = size;
-				status = efi_call_phys3(fh->read,
-							initrds[j].handle,
-							&chunksize, addr);
-				if (status != EFI_SUCCESS) {
-					efi_printk("Failed to read initrd\n");
-					goto free_initrd_total;
-				}
-				addr += chunksize;
-				size -= chunksize;
-			}
-
-			efi_call_phys1(fh->close, initrds[j].handle);
-		}
-
-	}
-
-	efi_call_phys1(sys_table->boottime->free_pool, initrds);
-
-	hdr->ramdisk_image = initrd_addr;
-	hdr->ramdisk_size = initrd_total;
-
-	return status;
-
-free_initrd_total:
-	low_free(initrd_total, initrd_addr);
-
-close_handles:
-	for (k = j; k < i; k++)
-		efi_call_phys1(fh->close, initrds[k].handle);
-free_initrds:
-	efi_call_phys1(sys_table->boottime->free_pool, initrds);
-fail:
-	hdr->ramdisk_image = 0;
-	hdr->ramdisk_size = 0;
-
-	return status;
-}
 
 /*
  * Because the x86 boot code expects to be passed a boot_params we
@@ -875,14 +435,15 @@
 	struct efi_info *efi;
 	efi_loaded_image_t *image;
 	void *options;
-	u32 load_options_size;
 	efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
 	int options_size = 0;
 	efi_status_t status;
-	unsigned long cmdline;
+	char *cmdline_ptr;
 	u16 *s2;
 	u8 *s1;
 	int i;
+	unsigned long ramdisk_addr;
+	unsigned long ramdisk_size;
 
 	sys_table = _table;
 
@@ -893,13 +454,14 @@
 	status = efi_call_phys3(sys_table->boottime->handle_protocol,
 				handle, &proto, (void *)&image);
 	if (status != EFI_SUCCESS) {
-		efi_printk("Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
+		efi_printk(sys_table, "Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
 		return NULL;
 	}
 
-	status = low_alloc(0x4000, 1, (unsigned long *)&boot_params);
+	status = efi_low_alloc(sys_table, 0x4000, 1,
+			       (unsigned long *)&boot_params);
 	if (status != EFI_SUCCESS) {
-		efi_printk("Failed to alloc lowmem for boot params\n");
+		efi_printk(sys_table, "Failed to alloc lowmem for boot params\n");
 		return NULL;
 	}
 
@@ -926,40 +488,11 @@
 	hdr->type_of_loader = 0x21;
 
 	/* Convert unicode cmdline to ascii */
-	options = image->load_options;
-	load_options_size = image->load_options_size / 2; /* ASCII */
-	cmdline = 0;
-	s2 = (u16 *)options;
-
-	if (s2) {
-		while (*s2 && *s2 != '\n' && options_size < load_options_size) {
-			s2++;
-			options_size++;
-		}
-
-		if (options_size) {
-			if (options_size > hdr->cmdline_size)
-				options_size = hdr->cmdline_size;
-
-			options_size++;	/* NUL termination */
-
-			status = low_alloc(options_size, 1, &cmdline);
-			if (status != EFI_SUCCESS) {
-				efi_printk("Failed to alloc mem for cmdline\n");
-				goto fail;
-			}
-
-			s1 = (u8 *)(unsigned long)cmdline;
-			s2 = (u16 *)options;
-
-			for (i = 0; i < options_size - 1; i++)
-				*s1++ = *s2++;
-
-			*s1 = '\0';
-		}
-	}
-
-	hdr->cmd_line_ptr = cmdline;
+	cmdline_ptr = efi_convert_cmdline_to_ascii(sys_table, image,
+						   &options_size);
+	if (!cmdline_ptr)
+		goto fail;
+	hdr->cmd_line_ptr = (unsigned long)cmdline_ptr;
 
 	hdr->ramdisk_image = 0;
 	hdr->ramdisk_size = 0;
@@ -969,96 +502,64 @@
 
 	memset(sdt, 0, sizeof(*sdt));
 
-	status = handle_ramdisks(image, hdr);
+	status = handle_cmdline_files(sys_table, image,
+				      (char *)(unsigned long)hdr->cmd_line_ptr,
+				      "initrd=", hdr->initrd_addr_max,
+				      &ramdisk_addr, &ramdisk_size);
 	if (status != EFI_SUCCESS)
 		goto fail2;
+	hdr->ramdisk_image = ramdisk_addr;
+	hdr->ramdisk_size = ramdisk_size;
 
 	return boot_params;
 fail2:
-	if (options_size)
-		low_free(options_size, hdr->cmd_line_ptr);
+	efi_free(sys_table, options_size, hdr->cmd_line_ptr);
 fail:
-	low_free(0x4000, (unsigned long)boot_params);
+	efi_free(sys_table, 0x4000, (unsigned long)boot_params);
 	return NULL;
 }
 
-static efi_status_t exit_boot(struct boot_params *boot_params,
-			      void *handle)
+static void add_e820ext(struct boot_params *params,
+			struct setup_data *e820ext, u32 nr_entries)
 {
-	struct efi_info *efi = &boot_params->efi_info;
-	struct e820entry *e820_map = &boot_params->e820_map[0];
-	struct e820entry *prev = NULL;
-	unsigned long size, key, desc_size, _size;
-	efi_memory_desc_t *mem_map;
+	struct setup_data *data;
 	efi_status_t status;
-	__u32 desc_version;
-	bool called_exit = false;
-	u8 nr_entries;
+	unsigned long size;
+
+	e820ext->type = SETUP_E820_EXT;
+	e820ext->len = nr_entries * sizeof(struct e820entry);
+	e820ext->next = 0;
+
+	data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
+
+	while (data && data->next)
+		data = (struct setup_data *)(unsigned long)data->next;
+
+	if (data)
+		data->next = (unsigned long)e820ext;
+	else
+		params->hdr.setup_data = (unsigned long)e820ext;
+}
+
+static efi_status_t setup_e820(struct boot_params *params,
+			       struct setup_data *e820ext, u32 e820ext_size)
+{
+	struct e820entry *e820_map = &params->e820_map[0];
+	struct efi_info *efi = &params->efi_info;
+	struct e820entry *prev = NULL;
+	u32 nr_entries;
+	u32 nr_desc;
 	int i;
 
-	size = sizeof(*mem_map) * 32;
-
-again:
-	size += sizeof(*mem_map) * 2;
-	_size = size;
-	status = low_alloc(size, 1, (unsigned long *)&mem_map);
-	if (status != EFI_SUCCESS)
-		return status;
-
-get_map:
-	status = efi_call_phys5(sys_table->boottime->get_memory_map, &size,
-				mem_map, &key, &desc_size, &desc_version);
-	if (status == EFI_BUFFER_TOO_SMALL) {
-		low_free(_size, (unsigned long)mem_map);
-		goto again;
-	}
-
-	if (status != EFI_SUCCESS)
-		goto free_mem_map;
-
-	memcpy(&efi->efi_loader_signature, EFI_LOADER_SIGNATURE, sizeof(__u32));
-	efi->efi_systab = (unsigned long)sys_table;
-	efi->efi_memdesc_size = desc_size;
-	efi->efi_memdesc_version = desc_version;
-	efi->efi_memmap = (unsigned long)mem_map;
-	efi->efi_memmap_size = size;
-
-#ifdef CONFIG_X86_64
-	efi->efi_systab_hi = (unsigned long)sys_table >> 32;
-	efi->efi_memmap_hi = (unsigned long)mem_map >> 32;
-#endif
-
-	/* Might as well exit boot services now */
-	status = efi_call_phys2(sys_table->boottime->exit_boot_services,
-				handle, key);
-	if (status != EFI_SUCCESS) {
-		/*
-		 * ExitBootServices() will fail if any of the event
-		 * handlers change the memory map. In which case, we
-		 * must be prepared to retry, but only once so that
-		 * we're guaranteed to exit on repeated failures instead
-		 * of spinning forever.
-		 */
-		if (called_exit)
-			goto free_mem_map;
-
-		called_exit = true;
-		goto get_map;
-	}
-
-	/* Historic? */
-	boot_params->alt_mem_k = 32 * 1024;
-
-	/*
-	 * Convert the EFI memory map to E820.
-	 */
 	nr_entries = 0;
-	for (i = 0; i < size / desc_size; i++) {
+	nr_desc = efi->efi_memmap_size / efi->efi_memdesc_size;
+
+	for (i = 0; i < nr_desc; i++) {
 		efi_memory_desc_t *d;
 		unsigned int e820_type = 0;
-		unsigned long m = (unsigned long)mem_map;
+		unsigned long m = efi->efi_memmap;
 
-		d = (efi_memory_desc_t *)(m + (i * desc_size));
+		d = (efi_memory_desc_t *)(m + (i * efi->efi_memdesc_size));
 		switch (d->type) {
 		case EFI_RESERVED_TYPE:
 		case EFI_RUNTIME_SERVICES_CODE:
@@ -1095,60 +596,150 @@
 
 		/* Merge adjacent mappings */
 		if (prev && prev->type == e820_type &&
-		    (prev->addr + prev->size) == d->phys_addr)
+		    (prev->addr + prev->size) == d->phys_addr) {
 			prev->size += d->num_pages << 12;
-		else {
-			e820_map->addr = d->phys_addr;
-			e820_map->size = d->num_pages << 12;
-			e820_map->type = e820_type;
-			prev = e820_map++;
-			nr_entries++;
+			continue;
 		}
+
+		if (nr_entries == ARRAY_SIZE(params->e820_map)) {
+			u32 need = (nr_desc - i) * sizeof(struct e820entry) +
+				   sizeof(struct setup_data);
+
+			if (!e820ext || e820ext_size < need)
+				return EFI_BUFFER_TOO_SMALL;
+
+			/* boot_params map full, switch to e820 extended */
+			e820_map = (struct e820entry *)e820ext->data;
+		}
+
+		e820_map->addr = d->phys_addr;
+		e820_map->size = d->num_pages << PAGE_SHIFT;
+		e820_map->type = e820_type;
+		prev = e820_map++;
+		nr_entries++;
 	}
 
-	boot_params->e820_entries = nr_entries;
+	if (nr_entries > ARRAY_SIZE(params->e820_map)) {
+		u32 nr_e820ext = nr_entries - ARRAY_SIZE(params->e820_map);
+
+		add_e820ext(params, e820ext, nr_e820ext);
+		nr_entries -= nr_e820ext;
+	}
+
+	params->e820_entries = (u8)nr_entries;
+
+	return EFI_SUCCESS;
+}
+
+static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext,
+				  u32 *e820ext_size)
+{
+	efi_status_t status;
+	unsigned long size;
+
+	size = sizeof(struct setup_data) +
+		sizeof(struct e820entry) * nr_desc;
+
+	if (*e820ext) {
+		efi_call_phys1(sys_table->boottime->free_pool, *e820ext);
+		*e820ext = NULL;
+		*e820ext_size = 0;
+	}
+
+	status = efi_call_phys3(sys_table->boottime->allocate_pool,
+				EFI_LOADER_DATA, size, e820ext);
+
+	if (status == EFI_SUCCESS)
+		*e820ext_size = size;
+
+	return status;
+}
+
+static efi_status_t exit_boot(struct boot_params *boot_params,
+			      void *handle)
+{
+	struct efi_info *efi = &boot_params->efi_info;
+	unsigned long map_sz, key, desc_size;
+	efi_memory_desc_t *mem_map;
+	struct setup_data *e820ext;
+	__u32 e820ext_size;
+	__u32 nr_desc, prev_nr_desc;
+	efi_status_t status;
+	__u32 desc_version;
+	bool called_exit = false;
+	u8 nr_entries;
+	int i;
+
+	nr_desc = 0;
+	e820ext = NULL;
+	e820ext_size = 0;
+
+get_map:
+	status = efi_get_memory_map(sys_table, &mem_map, &map_sz, &desc_size,
+				    &desc_version, &key);
+
+	if (status != EFI_SUCCESS)
+		return status;
+
+	prev_nr_desc = nr_desc;
+	nr_desc = map_sz / desc_size;
+	if (nr_desc > prev_nr_desc &&
+	    nr_desc > ARRAY_SIZE(boot_params->e820_map)) {
+		u32 nr_e820ext = nr_desc - ARRAY_SIZE(boot_params->e820_map);
+
+		status = alloc_e820ext(nr_e820ext, &e820ext, &e820ext_size);
+		if (status != EFI_SUCCESS)
+			goto free_mem_map;
+
+		efi_call_phys1(sys_table->boottime->free_pool, mem_map);
+		goto get_map; /* Allocated memory, get map again */
+	}
+
+	memcpy(&efi->efi_loader_signature, EFI_LOADER_SIGNATURE, sizeof(__u32));
+	efi->efi_systab = (unsigned long)sys_table;
+	efi->efi_memdesc_size = desc_size;
+	efi->efi_memdesc_version = desc_version;
+	efi->efi_memmap = (unsigned long)mem_map;
+	efi->efi_memmap_size = map_sz;
+
+#ifdef CONFIG_X86_64
+	efi->efi_systab_hi = (unsigned long)sys_table >> 32;
+	efi->efi_memmap_hi = (unsigned long)mem_map >> 32;
+#endif
+
+	/* Might as well exit boot services now */
+	status = efi_call_phys2(sys_table->boottime->exit_boot_services,
+				handle, key);
+	if (status != EFI_SUCCESS) {
+		/*
+		 * ExitBootServices() will fail if any of the event
+		 * handlers change the memory map. In which case, we
+		 * must be prepared to retry, but only once so that
+		 * we're guaranteed to exit on repeated failures instead
+		 * of spinning forever.
+		 */
+		if (called_exit)
+			goto free_mem_map;
+
+		called_exit = true;
+		efi_call_phys1(sys_table->boottime->free_pool, mem_map);
+		goto get_map;
+	}
+
+	/* Historic? */
+	boot_params->alt_mem_k = 32 * 1024;
+
+	status = setup_e820(boot_params, e820ext, e820ext_size);
+	if (status != EFI_SUCCESS)
+		return status;
 
 	return EFI_SUCCESS;
 
 free_mem_map:
-	low_free(_size, (unsigned long)mem_map);
+	efi_call_phys1(sys_table->boottime->free_pool, mem_map);
 	return status;
 }
 
-static efi_status_t relocate_kernel(struct setup_header *hdr)
-{
-	unsigned long start, nr_pages;
-	efi_status_t status;
-
-	/*
-	 * The EFI firmware loader could have placed the kernel image
-	 * anywhere in memory, but the kernel has various restrictions
-	 * on the max physical address it can run at. Attempt to move
-	 * the kernel to boot_params.pref_address, or as low as
-	 * possible.
-	 */
-	start = hdr->pref_address;
-	nr_pages = round_up(hdr->init_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
-
-	status = efi_call_phys4(sys_table->boottime->allocate_pages,
-				EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
-				nr_pages, &start);
-	if (status != EFI_SUCCESS) {
-		status = low_alloc(hdr->init_size, hdr->kernel_alignment,
-				   &start);
-		if (status != EFI_SUCCESS)
-			efi_printk("Failed to alloc mem for kernel\n");
-	}
-
-	if (status == EFI_SUCCESS)
-		memcpy((void *)start, (void *)(unsigned long)hdr->code32_start,
-		       hdr->init_size);
-
-	hdr->pref_address = hdr->code32_start;
-	hdr->code32_start = (__u32)start;
-
-	return status;
-}
 
 /*
  * On success we return a pointer to a boot_params structure, and NULL
@@ -1157,7 +748,7 @@
 struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
 			     struct boot_params *boot_params)
 {
-	struct desc_ptr *gdt, *idt;
+	struct desc_ptr *gdt;
 	efi_loaded_image_t *image;
 	struct setup_header *hdr = &boot_params->hdr;
 	efi_status_t status;
@@ -1177,37 +768,33 @@
 				EFI_LOADER_DATA, sizeof(*gdt),
 				(void **)&gdt);
 	if (status != EFI_SUCCESS) {
-		efi_printk("Failed to alloc mem for gdt structure\n");
+		efi_printk(sys_table, "Failed to alloc mem for gdt structure\n");
 		goto fail;
 	}
 
 	gdt->size = 0x800;
-	status = low_alloc(gdt->size, 8, (unsigned long *)&gdt->address);
+	status = efi_low_alloc(sys_table, gdt->size, 8,
+			   (unsigned long *)&gdt->address);
 	if (status != EFI_SUCCESS) {
-		efi_printk("Failed to alloc mem for gdt\n");
+		efi_printk(sys_table, "Failed to alloc mem for gdt\n");
 		goto fail;
 	}
 
-	status = efi_call_phys3(sys_table->boottime->allocate_pool,
-				EFI_LOADER_DATA, sizeof(*idt),
-				(void **)&idt);
-	if (status != EFI_SUCCESS) {
-		efi_printk("Failed to alloc mem for idt structure\n");
-		goto fail;
-	}
-
-	idt->size = 0;
-	idt->address = 0;
-
 	/*
 	 * If the kernel isn't already loaded at the preferred load
 	 * address, relocate it.
 	 */
 	if (hdr->pref_address != hdr->code32_start) {
-		status = relocate_kernel(hdr);
-
+		unsigned long bzimage_addr = hdr->code32_start;
+		status = efi_relocate_kernel(sys_table, &bzimage_addr,
+					     hdr->init_size, hdr->init_size,
+					     hdr->pref_address,
+					     hdr->kernel_alignment);
 		if (status != EFI_SUCCESS)
 			goto fail;
+
+		hdr->pref_address = hdr->code32_start;
+		hdr->code32_start = bzimage_addr;
 	}
 
 	status = exit_boot(boot_params, handle);
@@ -1267,10 +854,8 @@
 	desc->base2 = 0x00;
 #endif /* CONFIG_X86_64 */
 
-	asm volatile ("lidt %0" : : "m" (*idt));
-	asm volatile ("lgdt %0" : : "m" (*gdt));
-
 	asm volatile("cli");
+	asm volatile ("lgdt %0" : : "m" (*gdt));
 
 	return boot_params;
 fail:
diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h
index e5b0a8f..81b6b65 100644
--- a/arch/x86/boot/compressed/eboot.h
+++ b/arch/x86/boot/compressed/eboot.h
@@ -11,9 +11,6 @@
 
 #define DESC_TYPE_CODE_DATA	(1 << 0)
 
-#define EFI_PAGE_SIZE		(1UL << EFI_PAGE_SHIFT)
-#define EFI_READ_CHUNK_SIZE	(1024 * 1024)
-
 #define EFI_CONSOLE_OUT_DEVICE_GUID    \
 	EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, \
 		  0x3f, 0xc1, 0x4d)
@@ -62,10 +59,4 @@
 	void *blt;
 };
 
-struct efi_simple_text_output_protocol {
-	void *reset;
-	void *output_string;
-	void *test_string;
-};
-
 #endif /* BOOT_COMPRESSED_EBOOT_H */
diff --git a/arch/x86/boot/compressed/mkpiggy.c b/arch/x86/boot/compressed/mkpiggy.c
index 958a641..b669ab6 100644
--- a/arch/x86/boot/compressed/mkpiggy.c
+++ b/arch/x86/boot/compressed/mkpiggy.c
@@ -36,11 +36,12 @@
 	uint32_t olen;
 	long ilen;
 	unsigned long offs;
-	FILE *f;
+	FILE *f = NULL;
+	int retval = 1;
 
 	if (argc < 2) {
 		fprintf(stderr, "Usage: %s compressed_file\n", argv[0]);
-		return 1;
+		goto bail;
 	}
 
 	/* Get the information for the compressed kernel image first */
@@ -48,7 +49,7 @@
 	f = fopen(argv[1], "r");
 	if (!f) {
 		perror(argv[1]);
-		return 1;
+		goto bail;
 	}
 
 
@@ -58,12 +59,11 @@
 
 	if (fread(&olen, sizeof(olen), 1, f) != 1) {
 		perror(argv[1]);
-		return 1;
+		goto bail;
 	}
 
 	ilen = ftell(f);
 	olen = get_unaligned_le32(&olen);
-	fclose(f);
 
 	/*
 	 * Now we have the input (compressed) and output (uncompressed)
@@ -91,5 +91,9 @@
 	printf(".incbin \"%s\"\n", argv[1]);
 	printf("input_data_end:\n");
 
-	return 0;
+	retval = 0;
+bail:
+	if (f)
+		fclose(f);
+	return retval;
 }
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
index c941d6a..8e15b22 100644
--- a/arch/x86/boot/tools/build.c
+++ b/arch/x86/boot/tools/build.c
@@ -5,14 +5,15 @@
  */
 
 /*
- * This file builds a disk-image from two different files:
+ * This file builds a disk-image from three different files:
  *
  * - setup: 8086 machine code, sets up system parm
  * - system: 80386 code for actual system
+ * - zoffset.h: header with ZO_* defines
  *
- * It does some checking that all files are of the correct type, and
- * just writes the result to stdout, removing headers and padding to
- * the right amount. It also writes some system data to stderr.
+ * It does some checking that all files are of the correct type, and writes
+ * the result to the specified destination, removing headers and padding to
+ * the right amount. It also writes some system data to stdout.
  */
 
 /*
@@ -136,7 +137,7 @@
 
 static void usage(void)
 {
-	die("Usage: build setup system [zoffset.h] [> image]");
+	die("Usage: build setup system zoffset.h image");
 }
 
 #ifdef CONFIG_EFI_STUB
@@ -265,7 +266,7 @@
 	int c;
 	u32 sys_size;
 	struct stat sb;
-	FILE *file;
+	FILE *file, *dest;
 	int fd;
 	void *kernel;
 	u32 crc = 0xffffffffUL;
@@ -280,10 +281,13 @@
 	startup_64 = 0x200;
 #endif
 
-	if (argc == 4)
-		parse_zoffset(argv[3]);
-	else if (argc != 3)
+	if (argc != 5)
 		usage();
+	parse_zoffset(argv[3]);
+
+	dest = fopen(argv[4], "w");
+	if (!dest)
+		die("Unable to write `%s': %m", argv[4]);
 
 	/* Copy the setup code */
 	file = fopen(argv[1], "r");
@@ -318,7 +322,7 @@
 	/* Set the default root device */
 	put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
 
-	fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i);
+	printf("Setup is %d bytes (padded to %d bytes).\n", c, i);
 
 	/* Open and stat the kernel file */
 	fd = open(argv[2], O_RDONLY);
@@ -327,7 +331,7 @@
 	if (fstat(fd, &sb))
 		die("Unable to stat `%s': %m", argv[2]);
 	sz = sb.st_size;
-	fprintf (stderr, "System is %d kB\n", (sz+1023)/1024);
+	printf("System is %d kB\n", (sz+1023)/1024);
 	kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
 	if (kernel == MAP_FAILED)
 		die("Unable to mmap '%s': %m", argv[2]);
@@ -348,27 +352,31 @@
 #endif
 
 	crc = partial_crc32(buf, i, crc);
-	if (fwrite(buf, 1, i, stdout) != i)
+	if (fwrite(buf, 1, i, dest) != i)
 		die("Writing setup failed");
 
 	/* Copy the kernel code */
 	crc = partial_crc32(kernel, sz, crc);
-	if (fwrite(kernel, 1, sz, stdout) != sz)
+	if (fwrite(kernel, 1, sz, dest) != sz)
 		die("Writing kernel failed");
 
 	/* Add padding leaving 4 bytes for the checksum */
 	while (sz++ < (sys_size*16) - 4) {
 		crc = partial_crc32_one('\0', crc);
-		if (fwrite("\0", 1, 1, stdout) != 1)
+		if (fwrite("\0", 1, 1, dest) != 1)
 			die("Writing padding failed");
 	}
 
 	/* Write the CRC */
-	fprintf(stderr, "CRC %x\n", crc);
+	printf("CRC %x\n", crc);
 	put_unaligned_le32(crc, buf);
-	if (fwrite(buf, 1, 4, stdout) != 4)
+	if (fwrite(buf, 1, 4, dest) != 4)
 		die("Writing CRC failed");
 
+	/* Catch any delayed write failures */
+	if (fclose(dest))
+		die("Writing image failed");
+
 	close(fd);
 
 	/* Everything is OK */
diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig
index 9444708..a7fef26 100644
--- a/arch/x86/configs/i386_defconfig
+++ b/arch/x86/configs/i386_defconfig
@@ -142,6 +142,8 @@
 CONFIG_MAC80211_LEDS=y
 CONFIG_RFKILL=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_DEBUG_DEVRES=y
 CONFIG_CONNECTOR=y
 CONFIG_BLK_DEV_LOOP=y
diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
index 671524d..c1119d4 100644
--- a/arch/x86/configs/x86_64_defconfig
+++ b/arch/x86/configs/x86_64_defconfig
@@ -141,6 +141,8 @@
 CONFIG_MAC80211_LEDS=y
 CONFIG_RFKILL=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_DEBUG_DEVRES=y
 CONFIG_CONNECTOR=y
 CONFIG_BLK_DEV_LOOP=y
diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h
index 722aa3b..da31c8b 100644
--- a/arch/x86/include/asm/atomic.h
+++ b/arch/x86/include/asm/atomic.h
@@ -6,6 +6,7 @@
 #include <asm/processor.h>
 #include <asm/alternative.h>
 #include <asm/cmpxchg.h>
+#include <asm/rmwcc.h>
 
 /*
  * Atomic operations that C can't guarantee us.  Useful for
@@ -76,12 +77,7 @@
  */
 static inline int atomic_sub_and_test(int i, atomic_t *v)
 {
-	unsigned char c;
-
-	asm volatile(LOCK_PREFIX "subl %2,%0; sete %1"
-		     : "+m" (v->counter), "=qm" (c)
-		     : "ir" (i) : "memory");
-	return c;
+	GEN_BINARY_RMWcc(LOCK_PREFIX "subl", v->counter, i, "%0", "e");
 }
 
 /**
@@ -118,12 +114,7 @@
  */
 static inline int atomic_dec_and_test(atomic_t *v)
 {
-	unsigned char c;
-
-	asm volatile(LOCK_PREFIX "decl %0; sete %1"
-		     : "+m" (v->counter), "=qm" (c)
-		     : : "memory");
-	return c != 0;
+	GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, "%0", "e");
 }
 
 /**
@@ -136,12 +127,7 @@
  */
 static inline int atomic_inc_and_test(atomic_t *v)
 {
-	unsigned char c;
-
-	asm volatile(LOCK_PREFIX "incl %0; sete %1"
-		     : "+m" (v->counter), "=qm" (c)
-		     : : "memory");
-	return c != 0;
+	GEN_UNARY_RMWcc(LOCK_PREFIX "incl", v->counter, "%0", "e");
 }
 
 /**
@@ -155,12 +141,7 @@
  */
 static inline int atomic_add_negative(int i, atomic_t *v)
 {
-	unsigned char c;
-
-	asm volatile(LOCK_PREFIX "addl %2,%0; sets %1"
-		     : "+m" (v->counter), "=qm" (c)
-		     : "ir" (i) : "memory");
-	return c;
+	GEN_BINARY_RMWcc(LOCK_PREFIX "addl", v->counter, i, "%0", "s");
 }
 
 /**
diff --git a/arch/x86/include/asm/atomic64_64.h b/arch/x86/include/asm/atomic64_64.h
index 0e1cbfc..3f065c9 100644
--- a/arch/x86/include/asm/atomic64_64.h
+++ b/arch/x86/include/asm/atomic64_64.h
@@ -72,12 +72,7 @@
  */
 static inline int atomic64_sub_and_test(long i, atomic64_t *v)
 {
-	unsigned char c;
-
-	asm volatile(LOCK_PREFIX "subq %2,%0; sete %1"
-		     : "=m" (v->counter), "=qm" (c)
-		     : "er" (i), "m" (v->counter) : "memory");
-	return c;
+	GEN_BINARY_RMWcc(LOCK_PREFIX "subq", v->counter, i, "%0", "e");
 }
 
 /**
@@ -116,12 +111,7 @@
  */
 static inline int atomic64_dec_and_test(atomic64_t *v)
 {
-	unsigned char c;
-
-	asm volatile(LOCK_PREFIX "decq %0; sete %1"
-		     : "=m" (v->counter), "=qm" (c)
-		     : "m" (v->counter) : "memory");
-	return c != 0;
+	GEN_UNARY_RMWcc(LOCK_PREFIX "decq", v->counter, "%0", "e");
 }
 
 /**
@@ -134,12 +124,7 @@
  */
 static inline int atomic64_inc_and_test(atomic64_t *v)
 {
-	unsigned char c;
-
-	asm volatile(LOCK_PREFIX "incq %0; sete %1"
-		     : "=m" (v->counter), "=qm" (c)
-		     : "m" (v->counter) : "memory");
-	return c != 0;
+	GEN_UNARY_RMWcc(LOCK_PREFIX "incq", v->counter, "%0", "e");
 }
 
 /**
@@ -153,12 +138,7 @@
  */
 static inline int atomic64_add_negative(long i, atomic64_t *v)
 {
-	unsigned char c;
-
-	asm volatile(LOCK_PREFIX "addq %2,%0; sets %1"
-		     : "=m" (v->counter), "=qm" (c)
-		     : "er" (i), "m" (v->counter) : "memory");
-	return c;
+	GEN_BINARY_RMWcc(LOCK_PREFIX "addq", v->counter, i, "%0", "s");
 }
 
 /**
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
index 41639ce..6d76d09 100644
--- a/arch/x86/include/asm/bitops.h
+++ b/arch/x86/include/asm/bitops.h
@@ -14,6 +14,7 @@
 
 #include <linux/compiler.h>
 #include <asm/alternative.h>
+#include <asm/rmwcc.h>
 
 #if BITS_PER_LONG == 32
 # define _BITOPS_LONG_SHIFT 5
@@ -204,12 +205,7 @@
  */
 static inline int test_and_set_bit(long nr, volatile unsigned long *addr)
 {
-	int oldbit;
-
-	asm volatile(LOCK_PREFIX "bts %2,%1\n\t"
-		     "sbb %0,%0" : "=r" (oldbit), ADDR : "Ir" (nr) : "memory");
-
-	return oldbit;
+	GEN_BINARY_RMWcc(LOCK_PREFIX "bts", *addr, nr, "%0", "c");
 }
 
 /**
@@ -255,13 +251,7 @@
  */
 static inline int test_and_clear_bit(long nr, volatile unsigned long *addr)
 {
-	int oldbit;
-
-	asm volatile(LOCK_PREFIX "btr %2,%1\n\t"
-		     "sbb %0,%0"
-		     : "=r" (oldbit), ADDR : "Ir" (nr) : "memory");
-
-	return oldbit;
+	GEN_BINARY_RMWcc(LOCK_PREFIX "btr", *addr, nr, "%0", "c");
 }
 
 /**
@@ -314,13 +304,7 @@
  */
 static inline int test_and_change_bit(long nr, volatile unsigned long *addr)
 {
-	int oldbit;
-
-	asm volatile(LOCK_PREFIX "btc %2,%1\n\t"
-		     "sbb %0,%0"
-		     : "=r" (oldbit), ADDR : "Ir" (nr) : "memory");
-
-	return oldbit;
+	GEN_BINARY_RMWcc(LOCK_PREFIX "btc", *addr, nr, "%0", "c");
 }
 
 static __always_inline int constant_test_bit(long nr, const volatile unsigned long *addr)
diff --git a/arch/x86/include/asm/calling.h b/arch/x86/include/asm/calling.h
index 0fa6750..cb4c73b 100644
--- a/arch/x86/include/asm/calling.h
+++ b/arch/x86/include/asm/calling.h
@@ -48,6 +48,8 @@
 
 #include <asm/dwarf2.h>
 
+#ifdef CONFIG_X86_64
+
 /*
  * 64-bit system call stack frame layout defines and helpers,
  * for assembly code:
@@ -192,3 +194,51 @@
 	.macro icebp
 	.byte 0xf1
 	.endm
+
+#else /* CONFIG_X86_64 */
+
+/*
+ * For 32bit only simplified versions of SAVE_ALL/RESTORE_ALL. These
+ * are different from the entry_32.S versions in not changing the segment
+ * registers. So only suitable for in kernel use, not when transitioning
+ * from or to user space. The resulting stack frame is not a standard
+ * pt_regs frame. The main use case is calling C code from assembler
+ * when all the registers need to be preserved.
+ */
+
+	.macro SAVE_ALL
+	pushl_cfi %eax
+	CFI_REL_OFFSET eax, 0
+	pushl_cfi %ebp
+	CFI_REL_OFFSET ebp, 0
+	pushl_cfi %edi
+	CFI_REL_OFFSET edi, 0
+	pushl_cfi %esi
+	CFI_REL_OFFSET esi, 0
+	pushl_cfi %edx
+	CFI_REL_OFFSET edx, 0
+	pushl_cfi %ecx
+	CFI_REL_OFFSET ecx, 0
+	pushl_cfi %ebx
+	CFI_REL_OFFSET ebx, 0
+	.endm
+
+	.macro RESTORE_ALL
+	popl_cfi %ebx
+	CFI_RESTORE ebx
+	popl_cfi %ecx
+	CFI_RESTORE ecx
+	popl_cfi %edx
+	CFI_RESTORE edx
+	popl_cfi %esi
+	CFI_RESTORE esi
+	popl_cfi %edi
+	CFI_RESTORE edi
+	popl_cfi %ebp
+	CFI_RESTORE ebp
+	popl_cfi %eax
+	CFI_RESTORE eax
+	.endm
+
+#endif /* CONFIG_X86_64 */
+
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index d3f5c63..89270b4 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -374,7 +374,7 @@
 		 * Catch too early usage of this before alternatives
 		 * have run.
 		 */
-		asm goto("1: jmp %l[t_warn]\n"
+		asm_volatile_goto("1: jmp %l[t_warn]\n"
 			 "2:\n"
 			 ".section .altinstructions,\"a\"\n"
 			 " .long 1b - .\n"
@@ -388,7 +388,7 @@
 
 #endif
 
-		asm goto("1: jmp %l[t_no]\n"
+		asm_volatile_goto("1: jmp %l[t_no]\n"
 			 "2:\n"
 			 ".section .altinstructions,\"a\"\n"
 			 " .long 1b - .\n"
@@ -453,7 +453,7 @@
  * have. Thus, we force the jump to the widest, 4-byte, signed relative
  * offset even though the last would often fit in less bytes.
  */
-		asm goto("1: .byte 0xe9\n .long %l[t_dynamic] - 2f\n"
+		asm_volatile_goto("1: .byte 0xe9\n .long %l[t_dynamic] - 2f\n"
 			 "2:\n"
 			 ".section .altinstructions,\"a\"\n"
 			 " .long 1b - .\n"		/* src offset */
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 0062a01..65c6e6e 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -109,6 +109,8 @@
 	return IS_ENABLED(CONFIG_X86_64) == efi_enabled(EFI_64BIT);
 }
 
+extern struct console early_efi_console;
+
 #else
 /*
  * IF EFI is not configured, have the EFI calls return -ENOSYS.
diff --git a/arch/x86/include/asm/intel-mid.h b/arch/x86/include/asm/intel-mid.h
new file mode 100644
index 0000000..459769d
--- /dev/null
+++ b/arch/x86/include/asm/intel-mid.h
@@ -0,0 +1,113 @@
+/*
+ * intel-mid.h: Intel MID specific setup code
+ *
+ * (C) Copyright 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+#ifndef _ASM_X86_INTEL_MID_H
+#define _ASM_X86_INTEL_MID_H
+
+#include <linux/sfi.h>
+#include <linux/platform_device.h>
+
+extern int intel_mid_pci_init(void);
+extern int get_gpio_by_name(const char *name);
+extern void intel_scu_device_register(struct platform_device *pdev);
+extern int __init sfi_parse_mrtc(struct sfi_table_header *table);
+extern int __init sfi_parse_mtmr(struct sfi_table_header *table);
+extern int sfi_mrtc_num;
+extern struct sfi_rtc_table_entry sfi_mrtc_array[];
+
+/*
+ * Here defines the array of devices platform data that IAFW would export
+ * through SFI "DEVS" table, we use name and type to match the device and
+ * its platform data.
+ */
+struct devs_id {
+	char name[SFI_NAME_LEN + 1];
+	u8 type;
+	u8 delay;
+	void *(*get_platform_data)(void *info);
+	/* Custom handler for devices */
+	void (*device_handler)(struct sfi_device_table_entry *pentry,
+				struct devs_id *dev);
+};
+
+#define sfi_device(i)   \
+	static const struct devs_id *const __intel_mid_sfi_##i##_dev __used \
+	__attribute__((__section__(".x86_intel_mid_dev.init"))) = &i
+
+/*
+ * Medfield is the follow-up of Moorestown, it combines two chip solution into
+ * one. Other than that it also added always-on and constant tsc and lapic
+ * timers. Medfield is the platform name, and the chip name is called Penwell
+ * we treat Medfield/Penwell as a variant of Moorestown. Penwell can be
+ * identified via MSRs.
+ */
+enum intel_mid_cpu_type {
+	/* 1 was Moorestown */
+	INTEL_MID_CPU_CHIP_PENWELL = 2,
+};
+
+extern enum intel_mid_cpu_type __intel_mid_cpu_chip;
+
+#ifdef CONFIG_X86_INTEL_MID
+
+static inline enum intel_mid_cpu_type intel_mid_identify_cpu(void)
+{
+	return __intel_mid_cpu_chip;
+}
+
+static inline bool intel_mid_has_msic(void)
+{
+	return (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_PENWELL);
+}
+
+#else /* !CONFIG_X86_INTEL_MID */
+
+#define intel_mid_identify_cpu()    (0)
+#define intel_mid_has_msic()    (0)
+
+#endif /* !CONFIG_X86_INTEL_MID */
+
+enum intel_mid_timer_options {
+	INTEL_MID_TIMER_DEFAULT,
+	INTEL_MID_TIMER_APBT_ONLY,
+	INTEL_MID_TIMER_LAPIC_APBT,
+};
+
+extern enum intel_mid_timer_options intel_mid_timer_options;
+
+/*
+ * Penwell uses spread spectrum clock, so the freq number is not exactly
+ * the same as reported by MSR based on SDM.
+ */
+#define PENWELL_FSB_FREQ_83SKU         83200
+#define PENWELL_FSB_FREQ_100SKU        99840
+
+#define SFI_MTMR_MAX_NUM 8
+#define SFI_MRTC_MAX	8
+
+extern struct console early_mrst_console;
+extern void mrst_early_console_init(void);
+
+extern struct console early_hsu_console;
+extern void hsu_early_console_init(const char *);
+
+extern void intel_scu_devices_create(void);
+extern void intel_scu_devices_destroy(void);
+
+/* VRTC timer */
+#define MRST_VRTC_MAP_SZ	(1024)
+/*#define MRST_VRTC_PGOFFSET	(0xc00) */
+
+extern void intel_mid_rtc_init(void);
+
+/* the offset for the mapping of global gpio pin to irq */
+#define INTEL_MID_IRQ_OFFSET 0x100
+
+#endif /* _ASM_X86_INTEL_MID_H */
diff --git a/arch/x86/include/asm/mrst-vrtc.h b/arch/x86/include/asm/intel_mid_vrtc.h
similarity index 81%
rename from arch/x86/include/asm/mrst-vrtc.h
rename to arch/x86/include/asm/intel_mid_vrtc.h
index 1e69a75..86ff468 100644
--- a/arch/x86/include/asm/mrst-vrtc.h
+++ b/arch/x86/include/asm/intel_mid_vrtc.h
@@ -1,5 +1,5 @@
-#ifndef _MRST_VRTC_H
-#define _MRST_VRTC_H
+#ifndef _INTEL_MID_VRTC_H
+#define _INTEL_MID_VRTC_H
 
 extern unsigned char vrtc_cmos_read(unsigned char reg);
 extern void vrtc_cmos_write(unsigned char val, unsigned char reg);
diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
index 64507f3..6a2cefb 100644
--- a/arch/x86/include/asm/jump_label.h
+++ b/arch/x86/include/asm/jump_label.h
@@ -18,7 +18,7 @@
 
 static __always_inline bool arch_static_branch(struct static_key *key)
 {
-	asm goto("1:"
+	asm_volatile_goto("1:"
 		".byte " __stringify(STATIC_KEY_INIT_NOP) "\n\t"
 		".pushsection __jump_table,  \"aw\" \n\t"
 		_ASM_ALIGN "\n\t"
diff --git a/arch/x86/include/asm/local.h b/arch/x86/include/asm/local.h
index 2d89e39..5b23e60 100644
--- a/arch/x86/include/asm/local.h
+++ b/arch/x86/include/asm/local.h
@@ -52,12 +52,7 @@
  */
 static inline int local_sub_and_test(long i, local_t *l)
 {
-	unsigned char c;
-
-	asm volatile(_ASM_SUB "%2,%0; sete %1"
-		     : "+m" (l->a.counter), "=qm" (c)
-		     : "ir" (i) : "memory");
-	return c;
+	GEN_BINARY_RMWcc(_ASM_SUB, l->a.counter, i, "%0", "e");
 }
 
 /**
@@ -70,12 +65,7 @@
  */
 static inline int local_dec_and_test(local_t *l)
 {
-	unsigned char c;
-
-	asm volatile(_ASM_DEC "%0; sete %1"
-		     : "+m" (l->a.counter), "=qm" (c)
-		     : : "memory");
-	return c != 0;
+	GEN_UNARY_RMWcc(_ASM_DEC, l->a.counter, "%0", "e");
 }
 
 /**
@@ -88,12 +78,7 @@
  */
 static inline int local_inc_and_test(local_t *l)
 {
-	unsigned char c;
-
-	asm volatile(_ASM_INC "%0; sete %1"
-		     : "+m" (l->a.counter), "=qm" (c)
-		     : : "memory");
-	return c != 0;
+	GEN_UNARY_RMWcc(_ASM_INC, l->a.counter, "%0", "e");
 }
 
 /**
@@ -107,12 +92,7 @@
  */
 static inline int local_add_negative(long i, local_t *l)
 {
-	unsigned char c;
-
-	asm volatile(_ASM_ADD "%2,%0; sets %1"
-		     : "+m" (l->a.counter), "=qm" (c)
-		     : "ir" (i) : "memory");
-	return c;
+	GEN_BINARY_RMWcc(_ASM_ADD, l->a.counter, i, "%0", "s");
 }
 
 /**
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index cbe6b9e..c696a86 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -16,6 +16,7 @@
 #define MCG_EXT_CNT_SHIFT	16
 #define MCG_EXT_CNT(c)		(((c) & MCG_EXT_CNT_MASK) >> MCG_EXT_CNT_SHIFT)
 #define MCG_SER_P		(1ULL<<24)   /* MCA recovery/new status bits */
+#define MCG_ELOG_P		(1ULL<<26)   /* Extended error log supported */
 
 /* MCG_STATUS register defines */
 #define MCG_STATUS_RIPV  (1ULL<<0)   /* restart ip valid */
diff --git a/arch/x86/include/asm/misc.h b/arch/x86/include/asm/misc.h
new file mode 100644
index 0000000..475f5bb
--- /dev/null
+++ b/arch/x86/include/asm/misc.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_MISC_H
+#define _ASM_X86_MISC_H
+
+int num_digits(int val);
+
+#endif /* _ASM_X86_MISC_H */
diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h
deleted file mode 100644
index fc18bf3..0000000
--- a/arch/x86/include/asm/mrst.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * mrst.h: Intel Moorestown platform specific setup code
- *
- * (C) Copyright 2009 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; version 2
- * of the License.
- */
-#ifndef _ASM_X86_MRST_H
-#define _ASM_X86_MRST_H
-
-#include <linux/sfi.h>
-
-extern int pci_mrst_init(void);
-extern int __init sfi_parse_mrtc(struct sfi_table_header *table);
-extern int sfi_mrtc_num;
-extern struct sfi_rtc_table_entry sfi_mrtc_array[];
-
-/*
- * Medfield is the follow-up of Moorestown, it combines two chip solution into
- * one. Other than that it also added always-on and constant tsc and lapic
- * timers. Medfield is the platform name, and the chip name is called Penwell
- * we treat Medfield/Penwell as a variant of Moorestown. Penwell can be
- * identified via MSRs.
- */
-enum mrst_cpu_type {
-	/* 1 was Moorestown */
-	MRST_CPU_CHIP_PENWELL = 2,
-};
-
-extern enum mrst_cpu_type __mrst_cpu_chip;
-
-#ifdef CONFIG_X86_INTEL_MID
-
-static inline enum mrst_cpu_type mrst_identify_cpu(void)
-{
-	return __mrst_cpu_chip;
-}
-
-#else /* !CONFIG_X86_INTEL_MID */
-
-#define mrst_identify_cpu()    (0)
-
-#endif /* !CONFIG_X86_INTEL_MID */
-
-enum mrst_timer_options {
-	MRST_TIMER_DEFAULT,
-	MRST_TIMER_APBT_ONLY,
-	MRST_TIMER_LAPIC_APBT,
-};
-
-extern enum mrst_timer_options mrst_timer_options;
-
-/*
- * Penwell uses spread spectrum clock, so the freq number is not exactly
- * the same as reported by MSR based on SDM.
- */
-#define PENWELL_FSB_FREQ_83SKU         83200
-#define PENWELL_FSB_FREQ_100SKU        99840
-
-#define SFI_MTMR_MAX_NUM 8
-#define SFI_MRTC_MAX	8
-
-extern struct console early_mrst_console;
-extern void mrst_early_console_init(void);
-
-extern struct console early_hsu_console;
-extern void hsu_early_console_init(const char *);
-
-extern void intel_scu_devices_create(void);
-extern void intel_scu_devices_destroy(void);
-
-/* VRTC timer */
-#define MRST_VRTC_MAP_SZ	(1024)
-/*#define MRST_VRTC_PGOFFSET	(0xc00) */
-
-extern void mrst_rtc_init(void);
-
-#endif /* _ASM_X86_MRST_H */
diff --git a/arch/x86/include/asm/mutex_64.h b/arch/x86/include/asm/mutex_64.h
index e7e6751..07537a4 100644
--- a/arch/x86/include/asm/mutex_64.h
+++ b/arch/x86/include/asm/mutex_64.h
@@ -20,7 +20,7 @@
 static inline void __mutex_fastpath_lock(atomic_t *v,
 					 void (*fail_fn)(atomic_t *))
 {
-	asm volatile goto(LOCK_PREFIX "   decl %0\n"
+	asm_volatile_goto(LOCK_PREFIX "   decl %0\n"
 			  "   jns %l[exit]\n"
 			  : : "m" (v->counter)
 			  : "memory", "cc"
@@ -75,7 +75,7 @@
 static inline void __mutex_fastpath_unlock(atomic_t *v,
 					   void (*fail_fn)(atomic_t *))
 {
-	asm volatile goto(LOCK_PREFIX "   incl %0\n"
+	asm_volatile_goto(LOCK_PREFIX "   incl %0\n"
 			  "   jg %l[exit]\n"
 			  : : "m" (v->counter)
 			  : "memory", "cc"
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index 0da5200..94220d1 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -128,7 +128,8 @@
 do {									\
 	typedef typeof(var) pao_T__;					\
 	const int pao_ID__ = (__builtin_constant_p(val) &&		\
-			      ((val) == 1 || (val) == -1)) ? (val) : 0;	\
+			      ((val) == 1 || (val) == -1)) ?		\
+				(int)(val) : 0;				\
 	if (0) {							\
 		pao_T__ pao_tmp__;					\
 		pao_tmp__ = (val);					\
@@ -377,9 +378,6 @@
 #define __this_cpu_or_1(pcp, val)	percpu_to_op("or", (pcp), val)
 #define __this_cpu_or_2(pcp, val)	percpu_to_op("or", (pcp), val)
 #define __this_cpu_or_4(pcp, val)	percpu_to_op("or", (pcp), val)
-#define __this_cpu_xor_1(pcp, val)	percpu_to_op("xor", (pcp), val)
-#define __this_cpu_xor_2(pcp, val)	percpu_to_op("xor", (pcp), val)
-#define __this_cpu_xor_4(pcp, val)	percpu_to_op("xor", (pcp), val)
 #define __this_cpu_xchg_1(pcp, val)	percpu_xchg_op(pcp, val)
 #define __this_cpu_xchg_2(pcp, val)	percpu_xchg_op(pcp, val)
 #define __this_cpu_xchg_4(pcp, val)	percpu_xchg_op(pcp, val)
@@ -399,9 +397,6 @@
 #define this_cpu_or_1(pcp, val)		percpu_to_op("or", (pcp), val)
 #define this_cpu_or_2(pcp, val)		percpu_to_op("or", (pcp), val)
 #define this_cpu_or_4(pcp, val)		percpu_to_op("or", (pcp), val)
-#define this_cpu_xor_1(pcp, val)	percpu_to_op("xor", (pcp), val)
-#define this_cpu_xor_2(pcp, val)	percpu_to_op("xor", (pcp), val)
-#define this_cpu_xor_4(pcp, val)	percpu_to_op("xor", (pcp), val)
 #define this_cpu_xchg_1(pcp, nval)	percpu_xchg_op(pcp, nval)
 #define this_cpu_xchg_2(pcp, nval)	percpu_xchg_op(pcp, nval)
 #define this_cpu_xchg_4(pcp, nval)	percpu_xchg_op(pcp, nval)
@@ -446,7 +441,6 @@
 #define __this_cpu_add_8(pcp, val)	percpu_add_op((pcp), val)
 #define __this_cpu_and_8(pcp, val)	percpu_to_op("and", (pcp), val)
 #define __this_cpu_or_8(pcp, val)	percpu_to_op("or", (pcp), val)
-#define __this_cpu_xor_8(pcp, val)	percpu_to_op("xor", (pcp), val)
 #define __this_cpu_add_return_8(pcp, val) percpu_add_return_op(pcp, val)
 #define __this_cpu_xchg_8(pcp, nval)	percpu_xchg_op(pcp, nval)
 #define __this_cpu_cmpxchg_8(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
@@ -456,7 +450,6 @@
 #define this_cpu_add_8(pcp, val)	percpu_add_op((pcp), val)
 #define this_cpu_and_8(pcp, val)	percpu_to_op("and", (pcp), val)
 #define this_cpu_or_8(pcp, val)		percpu_to_op("or", (pcp), val)
-#define this_cpu_xor_8(pcp, val)	percpu_to_op("xor", (pcp), val)
 #define this_cpu_add_return_8(pcp, val)	percpu_add_return_op(pcp, val)
 #define this_cpu_xchg_8(pcp, nval)	percpu_xchg_op(pcp, nval)
 #define this_cpu_cmpxchg_8(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
diff --git a/arch/x86/include/asm/preempt.h b/arch/x86/include/asm/preempt.h
new file mode 100644
index 0000000..8729723
--- /dev/null
+++ b/arch/x86/include/asm/preempt.h
@@ -0,0 +1,100 @@
+#ifndef __ASM_PREEMPT_H
+#define __ASM_PREEMPT_H
+
+#include <asm/rmwcc.h>
+#include <asm/percpu.h>
+#include <linux/thread_info.h>
+
+DECLARE_PER_CPU(int, __preempt_count);
+
+/*
+ * We mask the PREEMPT_NEED_RESCHED bit so as not to confuse all current users
+ * that think a non-zero value indicates we cannot preempt.
+ */
+static __always_inline int preempt_count(void)
+{
+	return __this_cpu_read_4(__preempt_count) & ~PREEMPT_NEED_RESCHED;
+}
+
+static __always_inline void preempt_count_set(int pc)
+{
+	__this_cpu_write_4(__preempt_count, pc);
+}
+
+/*
+ * must be macros to avoid header recursion hell
+ */
+#define task_preempt_count(p) \
+	(task_thread_info(p)->saved_preempt_count & ~PREEMPT_NEED_RESCHED)
+
+#define init_task_preempt_count(p) do { \
+	task_thread_info(p)->saved_preempt_count = PREEMPT_DISABLED; \
+} while (0)
+
+#define init_idle_preempt_count(p, cpu) do { \
+	task_thread_info(p)->saved_preempt_count = PREEMPT_ENABLED; \
+	per_cpu(__preempt_count, (cpu)) = PREEMPT_ENABLED; \
+} while (0)
+
+/*
+ * We fold the NEED_RESCHED bit into the preempt count such that
+ * preempt_enable() can decrement and test for needing to reschedule with a
+ * single instruction.
+ *
+ * We invert the actual bit, so that when the decrement hits 0 we know we both
+ * need to resched (the bit is cleared) and can resched (no preempt count).
+ */
+
+static __always_inline void set_preempt_need_resched(void)
+{
+	__this_cpu_and_4(__preempt_count, ~PREEMPT_NEED_RESCHED);
+}
+
+static __always_inline void clear_preempt_need_resched(void)
+{
+	__this_cpu_or_4(__preempt_count, PREEMPT_NEED_RESCHED);
+}
+
+static __always_inline bool test_preempt_need_resched(void)
+{
+	return !(__this_cpu_read_4(__preempt_count) & PREEMPT_NEED_RESCHED);
+}
+
+/*
+ * The various preempt_count add/sub methods
+ */
+
+static __always_inline void __preempt_count_add(int val)
+{
+	__this_cpu_add_4(__preempt_count, val);
+}
+
+static __always_inline void __preempt_count_sub(int val)
+{
+	__this_cpu_add_4(__preempt_count, -val);
+}
+
+static __always_inline bool __preempt_count_dec_and_test(void)
+{
+	GEN_UNARY_RMWcc("decl", __preempt_count, __percpu_arg(0), "e");
+}
+
+/*
+ * Returns true when we need to resched and can (barring IRQ state).
+ */
+static __always_inline bool should_resched(void)
+{
+	return unlikely(!__this_cpu_read_4(__preempt_count));
+}
+
+#ifdef CONFIG_PREEMPT
+  extern asmlinkage void ___preempt_schedule(void);
+# define __preempt_schedule() asm ("call ___preempt_schedule")
+  extern asmlinkage void preempt_schedule(void);
+# ifdef CONFIG_CONTEXT_TRACKING
+    extern asmlinkage void ___preempt_schedule_context(void);
+#   define __preempt_schedule_context() asm ("call ___preempt_schedule_context")
+# endif
+#endif
+
+#endif /* __ASM_PREEMPT_H */
diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h
index bade6ac..fbeb06e 100644
--- a/arch/x86/include/asm/prom.h
+++ b/arch/x86/include/asm/prom.h
@@ -39,10 +39,5 @@
 
 extern char cmd_line[COMMAND_LINE_SIZE];
 
-#define pci_address_to_pio pci_address_to_pio
-unsigned long pci_address_to_pio(phys_addr_t addr);
-
-#define HAVE_ARCH_DEVTREE_FIXUPS
-
 #endif /* __ASSEMBLY__ */
 #endif
diff --git a/arch/x86/include/asm/rmwcc.h b/arch/x86/include/asm/rmwcc.h
new file mode 100644
index 0000000..1ff990f
--- /dev/null
+++ b/arch/x86/include/asm/rmwcc.h
@@ -0,0 +1,41 @@
+#ifndef _ASM_X86_RMWcc
+#define _ASM_X86_RMWcc
+
+#ifdef CC_HAVE_ASM_GOTO
+
+#define __GEN_RMWcc(fullop, var, cc, ...)				\
+do {									\
+	asm_volatile_goto (fullop "; j" cc " %l[cc_label]"		\
+			: : "m" (var), ## __VA_ARGS__ 			\
+			: "memory" : cc_label);				\
+	return 0;							\
+cc_label:								\
+	return 1;							\
+} while (0)
+
+#define GEN_UNARY_RMWcc(op, var, arg0, cc) 				\
+	__GEN_RMWcc(op " " arg0, var, cc)
+
+#define GEN_BINARY_RMWcc(op, var, val, arg0, cc)			\
+	__GEN_RMWcc(op " %1, " arg0, var, cc, "er" (val))
+
+#else /* !CC_HAVE_ASM_GOTO */
+
+#define __GEN_RMWcc(fullop, var, cc, ...)				\
+do {									\
+	char c;								\
+	asm volatile (fullop "; set" cc " %1"				\
+			: "+m" (var), "=qm" (c)				\
+			: __VA_ARGS__ : "memory");			\
+	return c != 0;							\
+} while (0)
+
+#define GEN_UNARY_RMWcc(op, var, arg0, cc)				\
+	__GEN_RMWcc(op " " arg0, var, cc)
+
+#define GEN_BINARY_RMWcc(op, var, val, arg0, cc)			\
+	__GEN_RMWcc(op " %2, " arg0, var, cc, "er" (val))
+
+#endif /* CC_HAVE_ASM_GOTO */
+
+#endif /* _ASM_X86_RMWcc */
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index 3475554..59bcf4e 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -51,9 +51,9 @@
 extern void setup_default_timer_irq(void);
 
 #ifdef CONFIG_X86_INTEL_MID
-extern void x86_mrst_early_setup(void);
+extern void x86_intel_mid_early_setup(void);
 #else
-static inline void x86_mrst_early_setup(void) { }
+static inline void x86_intel_mid_early_setup(void) { }
 #endif
 
 #ifdef CONFIG_X86_INTEL_CE
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index 2781119..c46a46b 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -28,8 +28,7 @@
 	__u32			flags;		/* low level flags */
 	__u32			status;		/* thread synchronous flags */
 	__u32			cpu;		/* current CPU */
-	int			preempt_count;	/* 0 => preemptable,
-						   <0 => BUG */
+	int			saved_preempt_count;
 	mm_segment_t		addr_limit;
 	struct restart_block    restart_block;
 	void __user		*sysenter_return;
@@ -49,7 +48,7 @@
 	.exec_domain	= &default_exec_domain,	\
 	.flags		= 0,			\
 	.cpu		= 0,			\
-	.preempt_count	= INIT_PREEMPT_COUNT,	\
+	.saved_preempt_count = INIT_PREEMPT_COUNT,	\
 	.addr_limit	= KERNEL_DS,		\
 	.restart_block = {			\
 		.fn = do_no_restart_syscall,	\
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 5838fa9..8ec57c0 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -542,5 +542,103 @@
 # include <asm/uaccess_64.h>
 #endif
 
+unsigned long __must_check _copy_from_user(void *to, const void __user *from,
+					   unsigned n);
+unsigned long __must_check _copy_to_user(void __user *to, const void *from,
+					 unsigned n);
+
+#ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS
+# define copy_user_diag __compiletime_error
+#else
+# define copy_user_diag __compiletime_warning
+#endif
+
+extern void copy_user_diag("copy_from_user() buffer size is too small")
+copy_from_user_overflow(void);
+extern void copy_user_diag("copy_to_user() buffer size is too small")
+copy_to_user_overflow(void) __asm__("copy_from_user_overflow");
+
+#undef copy_user_diag
+
+#ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS
+
+extern void
+__compiletime_warning("copy_from_user() buffer size is not provably correct")
+__copy_from_user_overflow(void) __asm__("copy_from_user_overflow");
+#define __copy_from_user_overflow(size, count) __copy_from_user_overflow()
+
+extern void
+__compiletime_warning("copy_to_user() buffer size is not provably correct")
+__copy_to_user_overflow(void) __asm__("copy_from_user_overflow");
+#define __copy_to_user_overflow(size, count) __copy_to_user_overflow()
+
+#else
+
+static inline void
+__copy_from_user_overflow(int size, unsigned long count)
+{
+	WARN(1, "Buffer overflow detected (%d < %lu)!\n", size, count);
+}
+
+#define __copy_to_user_overflow __copy_from_user_overflow
+
+#endif
+
+static inline unsigned long __must_check
+copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+	int sz = __compiletime_object_size(to);
+
+	might_fault();
+
+	/*
+	 * While we would like to have the compiler do the checking for us
+	 * even in the non-constant size case, any false positives there are
+	 * a problem (especially when DEBUG_STRICT_USER_COPY_CHECKS, but even
+	 * without - the [hopefully] dangerous looking nature of the warning
+	 * would make people go look at the respecitive call sites over and
+	 * over again just to find that there's no problem).
+	 *
+	 * And there are cases where it's just not realistic for the compiler
+	 * to prove the count to be in range. For example when multiple call
+	 * sites of a helper function - perhaps in different source files -
+	 * all doing proper range checking, yet the helper function not doing
+	 * so again.
+	 *
+	 * Therefore limit the compile time checking to the constant size
+	 * case, and do only runtime checking for non-constant sizes.
+	 */
+
+	if (likely(sz < 0 || sz >= n))
+		n = _copy_from_user(to, from, n);
+	else if(__builtin_constant_p(n))
+		copy_from_user_overflow();
+	else
+		__copy_from_user_overflow(sz, n);
+
+	return n;
+}
+
+static inline unsigned long __must_check
+copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+	int sz = __compiletime_object_size(from);
+
+	might_fault();
+
+	/* See the comment in copy_from_user() above. */
+	if (likely(sz < 0 || sz >= n))
+		n = _copy_to_user(to, from, n);
+	else if(__builtin_constant_p(n))
+		copy_to_user_overflow();
+	else
+		__copy_to_user_overflow(sz, n);
+
+	return n;
+}
+
+#undef __copy_from_user_overflow
+#undef __copy_to_user_overflow
+
 #endif /* _ASM_X86_UACCESS_H */
 
diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
index 7f760a9..3c03a5d 100644
--- a/arch/x86/include/asm/uaccess_32.h
+++ b/arch/x86/include/asm/uaccess_32.h
@@ -184,33 +184,4 @@
        return __copy_from_user_ll_nocache_nozero(to, from, n);
 }
 
-unsigned long __must_check copy_to_user(void __user *to,
-					const void *from, unsigned long n);
-unsigned long __must_check _copy_from_user(void *to,
-					  const void __user *from,
-					  unsigned long n);
-
-
-extern void copy_from_user_overflow(void)
-#ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS
-	__compiletime_error("copy_from_user() buffer size is not provably correct")
-#else
-	__compiletime_warning("copy_from_user() buffer size is not provably correct")
-#endif
-;
-
-static inline unsigned long __must_check copy_from_user(void *to,
-					  const void __user *from,
-					  unsigned long n)
-{
-	int sz = __compiletime_object_size(to);
-
-	if (likely(sz == -1 || sz >= n))
-		n = _copy_from_user(to, from, n);
-	else
-		copy_from_user_overflow();
-
-	return n;
-}
-
 #endif /* _ASM_X86_UACCESS_32_H */
diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h
index 4f7923d..190413d 100644
--- a/arch/x86/include/asm/uaccess_64.h
+++ b/arch/x86/include/asm/uaccess_64.h
@@ -46,42 +46,13 @@
 }
 
 __must_check unsigned long
-_copy_to_user(void __user *to, const void *from, unsigned len);
-__must_check unsigned long
-_copy_from_user(void *to, const void __user *from, unsigned len);
-__must_check unsigned long
 copy_in_user(void __user *to, const void __user *from, unsigned len);
 
-static inline unsigned long __must_check copy_from_user(void *to,
-					  const void __user *from,
-					  unsigned long n)
-{
-	int sz = __compiletime_object_size(to);
-
-	might_fault();
-	if (likely(sz == -1 || sz >= n))
-		n = _copy_from_user(to, from, n);
-#ifdef CONFIG_DEBUG_VM
-	else
-		WARN(1, "Buffer overflow detected!\n");
-#endif
-	return n;
-}
-
 static __always_inline __must_check
-int copy_to_user(void __user *dst, const void *src, unsigned size)
-{
-	might_fault();
-
-	return _copy_to_user(dst, src, size);
-}
-
-static __always_inline __must_check
-int __copy_from_user(void *dst, const void __user *src, unsigned size)
+int __copy_from_user_nocheck(void *dst, const void __user *src, unsigned size)
 {
 	int ret = 0;
 
-	might_fault();
 	if (!__builtin_constant_p(size))
 		return copy_user_generic(dst, (__force void *)src, size);
 	switch (size) {
@@ -121,11 +92,17 @@
 }
 
 static __always_inline __must_check
-int __copy_to_user(void __user *dst, const void *src, unsigned size)
+int __copy_from_user(void *dst, const void __user *src, unsigned size)
+{
+	might_fault();
+	return __copy_from_user_nocheck(dst, src, size);
+}
+
+static __always_inline __must_check
+int __copy_to_user_nocheck(void __user *dst, const void *src, unsigned size)
 {
 	int ret = 0;
 
-	might_fault();
 	if (!__builtin_constant_p(size))
 		return copy_user_generic((__force void *)dst, src, size);
 	switch (size) {
@@ -165,6 +142,13 @@
 }
 
 static __always_inline __must_check
+int __copy_to_user(void __user *dst, const void *src, unsigned size)
+{
+	might_fault();
+	return __copy_to_user_nocheck(dst, src, size);
+}
+
+static __always_inline __must_check
 int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
 {
 	int ret = 0;
@@ -220,13 +204,13 @@
 static __must_check __always_inline int
 __copy_from_user_inatomic(void *dst, const void __user *src, unsigned size)
 {
-	return copy_user_generic(dst, (__force const void *)src, size);
+	return __copy_from_user_nocheck(dst, (__force const void *)src, size);
 }
 
 static __must_check __always_inline int
 __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size)
 {
-	return copy_user_generic((__force void *)dst, src, size);
+	return __copy_to_user_nocheck((__force void *)dst, src, size);
 }
 
 extern long __copy_user_nocache(void *dst, const void __user *src,
diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h
index 6e51979..3087ea9 100644
--- a/arch/x86/include/asm/uprobes.h
+++ b/arch/x86/include/asm/uprobes.h
@@ -35,7 +35,10 @@
 
 struct arch_uprobe {
 	u16				fixups;
-	u8				insn[MAX_UINSN_BYTES];
+	union {
+		u8			insn[MAX_UINSN_BYTES];
+		u8			ixol[MAX_UINSN_BYTES];
+	};
 #ifdef CONFIG_X86_64
 	unsigned long			rip_rela_target_address;
 #endif
@@ -49,11 +52,4 @@
 	unsigned int			saved_tf;
 };
 
-extern int  arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
-extern int  arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
-extern int  arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
-extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
-extern int  arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
-extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
-extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs);
 #endif	/* _ASM_UPROBES_H */
diff --git a/arch/x86/include/asm/uv/uv.h b/arch/x86/include/asm/uv/uv.h
index 062921e..6b964a0 100644
--- a/arch/x86/include/asm/uv/uv.h
+++ b/arch/x86/include/asm/uv/uv.h
@@ -12,6 +12,7 @@
 extern int is_uv_system(void);
 extern void uv_cpu_init(void);
 extern void uv_nmi_init(void);
+extern void uv_register_nmi_notifier(void);
 extern void uv_system_init(void);
 extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
 						 struct mm_struct *mm,
@@ -25,6 +26,7 @@
 static inline int is_uv_system(void)	{ return 0; }
 static inline void uv_cpu_init(void)	{ }
 static inline void uv_system_init(void)	{ }
+static inline void uv_register_nmi_notifier(void) { }
 static inline const struct cpumask *
 uv_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm,
 		    unsigned long start, unsigned long end, unsigned int cpu)
diff --git a/arch/x86/include/asm/uv/uv_hub.h b/arch/x86/include/asm/uv/uv_hub.h
index 2c32df9..a30836c 100644
--- a/arch/x86/include/asm/uv/uv_hub.h
+++ b/arch/x86/include/asm/uv/uv_hub.h
@@ -502,8 +502,8 @@
 	unsigned short	nr_online_cpus;
 	unsigned short	pnode;
 	short		memory_nid;
-	spinlock_t	nmi_lock;
-	unsigned long	nmi_count;
+	spinlock_t	nmi_lock;	/* obsolete, see uv_hub_nmi */
+	unsigned long	nmi_count;	/* obsolete, see uv_hub_nmi */
 };
 extern struct uv_blade_info *uv_blade_info;
 extern short *uv_node_to_blade;
@@ -576,6 +576,59 @@
 	return uv_possible_blades;
 }
 
+/* Per Hub NMI support */
+extern void uv_nmi_setup(void);
+
+/* BMC sets a bit this MMR non-zero before sending an NMI */
+#define UVH_NMI_MMR		UVH_SCRATCH5
+#define UVH_NMI_MMR_CLEAR	UVH_SCRATCH5_ALIAS
+#define UVH_NMI_MMR_SHIFT	63
+#define	UVH_NMI_MMR_TYPE	"SCRATCH5"
+
+/* Newer SMM NMI handler, not present in all systems */
+#define UVH_NMI_MMRX		UVH_EVENT_OCCURRED0
+#define UVH_NMI_MMRX_CLEAR	UVH_EVENT_OCCURRED0_ALIAS
+#define UVH_NMI_MMRX_SHIFT	(is_uv1_hub() ? \
+					UV1H_EVENT_OCCURRED0_EXTIO_INT0_SHFT :\
+					UVXH_EVENT_OCCURRED0_EXTIO_INT0_SHFT)
+#define	UVH_NMI_MMRX_TYPE	"EXTIO_INT0"
+
+/* Non-zero indicates newer SMM NMI handler present */
+#define UVH_NMI_MMRX_SUPPORTED	UVH_EXTIO_INT0_BROADCAST
+
+/* Indicates to BIOS that we want to use the newer SMM NMI handler */
+#define UVH_NMI_MMRX_REQ	UVH_SCRATCH5_ALIAS_2
+#define UVH_NMI_MMRX_REQ_SHIFT	62
+
+struct uv_hub_nmi_s {
+	raw_spinlock_t	nmi_lock;
+	atomic_t	in_nmi;		/* flag this node in UV NMI IRQ */
+	atomic_t	cpu_owner;	/* last locker of this struct */
+	atomic_t	read_mmr_count;	/* count of MMR reads */
+	atomic_t	nmi_count;	/* count of true UV NMIs */
+	unsigned long	nmi_value;	/* last value read from NMI MMR */
+};
+
+struct uv_cpu_nmi_s {
+	struct uv_hub_nmi_s	*hub;
+	atomic_t		state;
+	atomic_t		pinging;
+	int			queries;
+	int			pings;
+};
+
+DECLARE_PER_CPU(struct uv_cpu_nmi_s, __uv_cpu_nmi);
+#define uv_cpu_nmi			(__get_cpu_var(__uv_cpu_nmi))
+#define uv_hub_nmi			(uv_cpu_nmi.hub)
+#define uv_cpu_nmi_per(cpu)		(per_cpu(__uv_cpu_nmi, cpu))
+#define uv_hub_nmi_per(cpu)		(uv_cpu_nmi_per(cpu).hub)
+
+/* uv_cpu_nmi_states */
+#define	UV_NMI_STATE_OUT		0
+#define	UV_NMI_STATE_IN			1
+#define	UV_NMI_STATE_DUMP		2
+#define	UV_NMI_STATE_DUMP_DONE		3
+
 /* Update SCIR state */
 static inline void uv_set_scir_bits(unsigned char value)
 {
diff --git a/arch/x86/include/asm/uv/uv_mmrs.h b/arch/x86/include/asm/uv/uv_mmrs.h
index bd5f80e..e42249b 100644
--- a/arch/x86/include/asm/uv/uv_mmrs.h
+++ b/arch/x86/include/asm/uv/uv_mmrs.h
@@ -461,6 +461,23 @@
 
 
 /* ========================================================================= */
+/*                         UVH_EXTIO_INT0_BROADCAST                          */
+/* ========================================================================= */
+#define UVH_EXTIO_INT0_BROADCAST 0x61448UL
+#define UVH_EXTIO_INT0_BROADCAST_32 0x3f0
+
+#define UVH_EXTIO_INT0_BROADCAST_ENABLE_SHFT		0
+#define UVH_EXTIO_INT0_BROADCAST_ENABLE_MASK		0x0000000000000001UL
+
+union uvh_extio_int0_broadcast_u {
+	unsigned long	v;
+	struct uvh_extio_int0_broadcast_s {
+		unsigned long	enable:1;			/* RW */
+		unsigned long	rsvd_1_63:63;
+	} s;
+};
+
+/* ========================================================================= */
 /*                         UVH_GR0_TLB_INT0_CONFIG                           */
 /* ========================================================================= */
 #define UVH_GR0_TLB_INT0_CONFIG 0x61b00UL
@@ -2606,6 +2623,20 @@
 };
 
 /* ========================================================================= */
+/*                            UVH_SCRATCH5_ALIAS                             */
+/* ========================================================================= */
+#define UVH_SCRATCH5_ALIAS 0x2d0208UL
+#define UVH_SCRATCH5_ALIAS_32 0x780
+
+
+/* ========================================================================= */
+/*                           UVH_SCRATCH5_ALIAS_2                            */
+/* ========================================================================= */
+#define UVH_SCRATCH5_ALIAS_2 0x2d0210UL
+#define UVH_SCRATCH5_ALIAS_2_32 0x788
+
+
+/* ========================================================================= */
 /*                          UVXH_EVENT_OCCURRED2                             */
 /* ========================================================================= */
 #define UVXH_EVENT_OCCURRED2 0x70100UL
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
index c15ddaf..9c3733c 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -158,7 +158,7 @@
 	X86_SUBARCH_PC = 0,
 	X86_SUBARCH_LGUEST,
 	X86_SUBARCH_XEN,
-	X86_SUBARCH_MRST,
+	X86_SUBARCH_INTEL_MID,
 	X86_SUBARCH_CE4100,
 	X86_NR_SUBARCHS,
 };
diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h
index b80420b..b8f1c01 100644
--- a/arch/x86/include/uapi/asm/hyperv.h
+++ b/arch/x86/include/uapi/asm/hyperv.h
@@ -27,6 +27,19 @@
 #define HV_X64_MSR_VP_RUNTIME_AVAILABLE		(1 << 0)
 /* Partition Reference Counter (HV_X64_MSR_TIME_REF_COUNT) available*/
 #define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE	(1 << 1)
+
+/*
+ * There is a single feature flag that signifies the presence of the MSR
+ * that can be used to retrieve both the local APIC Timer frequency as
+ * well as the TSC frequency.
+ */
+
+/* Local APIC timer frequency MSR (HV_X64_MSR_APIC_FREQUENCY) is available */
+#define HV_X64_MSR_APIC_FREQUENCY_AVAILABLE (1 << 11)
+
+/* TSC frequency MSR (HV_X64_MSR_TSC_FREQUENCY) is available */
+#define HV_X64_MSR_TSC_FREQUENCY_AVAILABLE (1 << 11)
+
 /*
  * Basic SynIC MSRs (HV_X64_MSR_SCONTROL through HV_X64_MSR_EOM
  * and HV_X64_MSR_SINT0 through HV_X64_MSR_SINT15) available
@@ -136,6 +149,12 @@
 /* MSR used to read the per-partition time reference counter */
 #define HV_X64_MSR_TIME_REF_COUNT		0x40000020
 
+/* MSR used to retrieve the TSC frequency */
+#define HV_X64_MSR_TSC_FREQUENCY		0x40000022
+
+/* MSR used to retrieve the local APIC timer frequency */
+#define HV_X64_MSR_APIC_FREQUENCY		0x40000023
+
 /* Define the virtual APIC registers */
 #define HV_X64_MSR_EOI				0x40000070
 #define HV_X64_MSR_ICR				0x40000071
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index a5408b9..9b0a34e 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -36,6 +36,8 @@
 obj-y			+= pci-iommu_table.o
 obj-y			+= resource.o
 
+obj-$(CONFIG_PREEMPT)	+= preempt.o
+
 obj-y				+= process.o
 obj-y				+= i387.o xsave.o
 obj-y				+= ptrace.o
diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c
index c9876ef..af5b08a 100644
--- a/arch/x86/kernel/apb_timer.c
+++ b/arch/x86/kernel/apb_timer.c
@@ -40,7 +40,7 @@
 
 #include <asm/fixmap.h>
 #include <asm/apb_timer.h>
-#include <asm/mrst.h>
+#include <asm/intel-mid.h>
 #include <asm/time.h>
 
 #define APBT_CLOCKEVENT_RATING		110
@@ -157,13 +157,13 @@
 
 	adev->num = smp_processor_id();
 	adev->timer = dw_apb_clockevent_init(smp_processor_id(), "apbt0",
-		mrst_timer_options == MRST_TIMER_LAPIC_APBT ?
+		intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT ?
 		APBT_CLOCKEVENT_RATING - 100 : APBT_CLOCKEVENT_RATING,
 		adev_virt_addr(adev), 0, apbt_freq);
 	/* Firmware does EOI handling for us. */
 	adev->timer->eoi = NULL;
 
-	if (mrst_timer_options == MRST_TIMER_LAPIC_APBT) {
+	if (intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT) {
 		global_clock_event = &adev->timer->ced;
 		printk(KERN_DEBUG "%s clockevent registered as global\n",
 		       global_clock_event->name);
@@ -253,7 +253,7 @@
 
 static __init int apbt_late_init(void)
 {
-	if (mrst_timer_options == MRST_TIMER_LAPIC_APBT ||
+	if (intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT ||
 		!apb_timer_block_enabled)
 		return 0;
 	/* This notifier should be called after workqueue is ready */
@@ -340,7 +340,7 @@
 	}
 #ifdef CONFIG_SMP
 	/* kernel cmdline disable apb timer, so we will use lapic timers */
-	if (mrst_timer_options == MRST_TIMER_LAPIC_APBT) {
+	if (intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT) {
 		printk(KERN_INFO "apbt: disabled per cpu timer\n");
 		return;
 	}
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 1191ac1..ad0dc04 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -39,12 +39,6 @@
 #include <asm/x86_init.h>
 #include <asm/nmi.h>
 
-/* BMC sets a bit this MMR non-zero before sending an NMI */
-#define UVH_NMI_MMR				UVH_SCRATCH5
-#define UVH_NMI_MMR_CLEAR			(UVH_NMI_MMR + 8)
-#define UV_NMI_PENDING_MASK			(1UL << 63)
-DEFINE_PER_CPU(unsigned long, cpu_last_nmi_count);
-
 DEFINE_PER_CPU(int, x2apic_extra_bits);
 
 #define PR_DEVEL(fmt, args...)	pr_devel("%s: " fmt, __func__, args)
@@ -58,7 +52,6 @@
 EXPORT_SYMBOL_GPL(uv_min_hub_revision_id);
 unsigned int uv_apicid_hibits;
 EXPORT_SYMBOL_GPL(uv_apicid_hibits);
-static DEFINE_SPINLOCK(uv_nmi_lock);
 
 static struct apic apic_x2apic_uv_x;
 
@@ -113,7 +106,7 @@
 		break;
 	case UV3_HUB_PART_NUMBER:
 	case UV3_HUB_PART_NUMBER_X:
-		uv_min_hub_revision_id += UV3_HUB_REVISION_BASE - 1;
+		uv_min_hub_revision_id += UV3_HUB_REVISION_BASE;
 		break;
 	}
 
@@ -847,68 +840,6 @@
 		set_x2apic_extra_bits(uv_hub_info->pnode);
 }
 
-/*
- * When NMI is received, print a stack trace.
- */
-int uv_handle_nmi(unsigned int reason, struct pt_regs *regs)
-{
-	unsigned long real_uv_nmi;
-	int bid;
-
-	/*
-	 * Each blade has an MMR that indicates when an NMI has been sent
-	 * to cpus on the blade. If an NMI is detected, atomically
-	 * clear the MMR and update a per-blade NMI count used to
-	 * cause each cpu on the blade to notice a new NMI.
-	 */
-	bid = uv_numa_blade_id();
-	real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & UV_NMI_PENDING_MASK);
-
-	if (unlikely(real_uv_nmi)) {
-		spin_lock(&uv_blade_info[bid].nmi_lock);
-		real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & UV_NMI_PENDING_MASK);
-		if (real_uv_nmi) {
-			uv_blade_info[bid].nmi_count++;
-			uv_write_local_mmr(UVH_NMI_MMR_CLEAR, UV_NMI_PENDING_MASK);
-		}
-		spin_unlock(&uv_blade_info[bid].nmi_lock);
-	}
-
-	if (likely(__get_cpu_var(cpu_last_nmi_count) == uv_blade_info[bid].nmi_count))
-		return NMI_DONE;
-
-	__get_cpu_var(cpu_last_nmi_count) = uv_blade_info[bid].nmi_count;
-
-	/*
-	 * Use a lock so only one cpu prints at a time.
-	 * This prevents intermixed output.
-	 */
-	spin_lock(&uv_nmi_lock);
-	pr_info("UV NMI stack dump cpu %u:\n", smp_processor_id());
-	dump_stack();
-	spin_unlock(&uv_nmi_lock);
-
-	return NMI_HANDLED;
-}
-
-void uv_register_nmi_notifier(void)
-{
-	if (register_nmi_handler(NMI_UNKNOWN, uv_handle_nmi, 0, "uv"))
-		printk(KERN_WARNING "UV NMI handler failed to register\n");
-}
-
-void uv_nmi_init(void)
-{
-	unsigned int value;
-
-	/*
-	 * Unmask NMI on all cpus
-	 */
-	value = apic_read(APIC_LVT1) | APIC_DM_NMI;
-	value &= ~APIC_LVT_MASKED;
-	apic_write(APIC_LVT1, value);
-}
-
 void __init uv_system_init(void)
 {
 	union uvh_rh_gam_config_mmr_u  m_n_config;
@@ -1046,6 +977,7 @@
 	map_mmr_high(max_pnode);
 	map_mmioh_high(min_pnode, max_pnode);
 
+	uv_nmi_setup();
 	uv_cpu_init();
 	uv_scir_register_cpu_notifier();
 	uv_register_nmi_notifier();
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index 2861082..9f6b934 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -32,7 +32,6 @@
 	OFFSET(TI_flags, thread_info, flags);
 	OFFSET(TI_status, thread_info, status);
 	OFFSET(TI_addr_limit, thread_info, addr_limit);
-	OFFSET(TI_preempt_count, thread_info, preempt_count);
 
 	BLANK();
 	OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx);
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 903a264..3daece7 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -823,8 +823,8 @@
 	.c_vendor	= "AMD",
 	.c_ident	= { "AuthenticAMD" },
 #ifdef CONFIG_X86_32
-	.c_models = {
-		{ .vendor = X86_VENDOR_AMD, .family = 4, .model_names =
+	.legacy_models = {
+		{ .family = 4, .model_names =
 		  {
 			  [3] = "486 DX/2",
 			  [7] = "486 DX/2-WB",
@@ -835,7 +835,7 @@
 		  }
 		},
 	},
-	.c_size_cache	= amd_size_cache,
+	.legacy_cache_size = amd_size_cache,
 #endif
 	.c_early_init   = early_init_amd,
 	.c_detect_tlb	= cpu_detect_tlb_amd,
diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c
index fbf6c3b..8d5652d 100644
--- a/arch/x86/kernel/cpu/centaur.c
+++ b/arch/x86/kernel/cpu/centaur.c
@@ -468,10 +468,10 @@
 #endif
 }
 
+#ifdef CONFIG_X86_32
 static unsigned int
 centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size)
 {
-#ifdef CONFIG_X86_32
 	/* VIA C3 CPUs (670-68F) need further shifting. */
 	if ((c->x86 == 6) && ((c->x86_model == 7) || (c->x86_model == 8)))
 		size >>= 8;
@@ -484,16 +484,18 @@
 	if ((c->x86 == 6) && (c->x86_model == 9) &&
 				(c->x86_mask == 1) && (size == 65))
 		size -= 1;
-#endif
 	return size;
 }
+#endif
 
 static const struct cpu_dev centaur_cpu_dev = {
 	.c_vendor	= "Centaur",
 	.c_ident	= { "CentaurHauls" },
 	.c_early_init	= early_init_centaur,
 	.c_init		= init_centaur,
-	.c_size_cache	= centaur_size_cache,
+#ifdef CONFIG_X86_32
+	.legacy_cache_size = centaur_size_cache,
+#endif
 	.c_x86_vendor	= X86_VENDOR_CENTAUR,
 };
 
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 2793d1f..6abc172 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -346,7 +346,8 @@
 /* Look up CPU names by table lookup. */
 static const char *table_lookup_model(struct cpuinfo_x86 *c)
 {
-	const struct cpu_model_info *info;
+#ifdef CONFIG_X86_32
+	const struct legacy_cpu_model_info *info;
 
 	if (c->x86_model >= 16)
 		return NULL;	/* Range check */
@@ -354,13 +355,14 @@
 	if (!this_cpu)
 		return NULL;
 
-	info = this_cpu->c_models;
+	info = this_cpu->legacy_models;
 
-	while (info && info->family) {
+	while (info->family) {
 		if (info->family == c->x86)
 			return info->model_names[c->x86_model];
 		info++;
 	}
+#endif
 	return NULL;		/* Not found */
 }
 
@@ -450,8 +452,8 @@
 	c->x86_tlbsize += ((ebx >> 16) & 0xfff) + (ebx & 0xfff);
 #else
 	/* do processor-specific cache resizing */
-	if (this_cpu->c_size_cache)
-		l2size = this_cpu->c_size_cache(c, l2size);
+	if (this_cpu->legacy_cache_size)
+		l2size = this_cpu->legacy_cache_size(c, l2size);
 
 	/* Allow user to override all this if necessary. */
 	if (cachesize_override != -1)
@@ -1095,6 +1097,9 @@
 
 DEFINE_PER_CPU(unsigned int, irq_count) __visible = -1;
 
+DEFINE_PER_CPU(int, __preempt_count) = INIT_PREEMPT_COUNT;
+EXPORT_PER_CPU_SYMBOL(__preempt_count);
+
 DEFINE_PER_CPU(struct task_struct *, fpu_owner_task);
 
 /*
@@ -1169,6 +1174,8 @@
 
 DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task;
 EXPORT_PER_CPU_SYMBOL(current_task);
+DEFINE_PER_CPU(int, __preempt_count) = INIT_PREEMPT_COUNT;
+EXPORT_PER_CPU_SYMBOL(__preempt_count);
 DEFINE_PER_CPU(struct task_struct *, fpu_owner_task);
 
 #ifdef CONFIG_CC_STACKPROTECTOR
diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h
index 4041c24..c37dc37 100644
--- a/arch/x86/kernel/cpu/cpu.h
+++ b/arch/x86/kernel/cpu/cpu.h
@@ -1,12 +1,6 @@
 #ifndef ARCH_X86_CPU_H
 #define ARCH_X86_CPU_H
 
-struct cpu_model_info {
-	int		vendor;
-	int		family;
-	const char	*model_names[16];
-};
-
 /* attempt to consolidate cpu attributes */
 struct cpu_dev {
 	const char	*c_vendor;
@@ -14,15 +8,23 @@
 	/* some have two possibilities for cpuid string */
 	const char	*c_ident[2];
 
-	struct		cpu_model_info c_models[4];
-
 	void            (*c_early_init)(struct cpuinfo_x86 *);
 	void		(*c_bsp_init)(struct cpuinfo_x86 *);
 	void		(*c_init)(struct cpuinfo_x86 *);
 	void		(*c_identify)(struct cpuinfo_x86 *);
 	void		(*c_detect_tlb)(struct cpuinfo_x86 *);
-	unsigned int	(*c_size_cache)(struct cpuinfo_x86 *, unsigned int);
 	int		c_x86_vendor;
+#ifdef CONFIG_X86_32
+	/* Optional vendor specific routine to obtain the cache size. */
+	unsigned int	(*legacy_cache_size)(struct cpuinfo_x86 *,
+					     unsigned int);
+
+	/* Family/stepping-based lookup table for model names. */
+	struct legacy_cpu_model_info {
+		int		family;
+		const char	*model_names[16];
+	}		legacy_models[5];
+#endif
 };
 
 struct _tlb_table {
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index ec72995..dc1ec0d 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -665,8 +665,8 @@
 	.c_vendor	= "Intel",
 	.c_ident	= { "GenuineIntel" },
 #ifdef CONFIG_X86_32
-	.c_models = {
-		{ .vendor = X86_VENDOR_INTEL, .family = 4, .model_names =
+	.legacy_models = {
+		{ .family = 4, .model_names =
 		  {
 			  [0] = "486 DX-25/33",
 			  [1] = "486 DX-50",
@@ -679,7 +679,7 @@
 			  [9] = "486 DX/4-WB"
 		  }
 		},
-		{ .vendor = X86_VENDOR_INTEL, .family = 5, .model_names =
+		{ .family = 5, .model_names =
 		  {
 			  [0] = "Pentium 60/66 A-step",
 			  [1] = "Pentium 60/66",
@@ -690,7 +690,7 @@
 			  [8] = "Mobile Pentium MMX"
 		  }
 		},
-		{ .vendor = X86_VENDOR_INTEL, .family = 6, .model_names =
+		{ .family = 6, .model_names =
 		  {
 			  [0] = "Pentium Pro A-step",
 			  [1] = "Pentium Pro",
@@ -704,7 +704,7 @@
 			  [11] = "Pentium III (Tualatin)",
 		  }
 		},
-		{ .vendor = X86_VENDOR_INTEL, .family = 15, .model_names =
+		{ .family = 15, .model_names =
 		  {
 			  [0] = "Pentium 4 (Unknown)",
 			  [1] = "Pentium 4 (Willamette)",
@@ -714,7 +714,7 @@
 		  }
 		},
 	},
-	.c_size_cache	= intel_size_cache,
+	.legacy_cache_size = intel_size_cache,
 #endif
 	.c_detect_tlb	= intel_detect_tlb,
 	.c_early_init   = early_init_intel,
diff --git a/arch/x86/kernel/cpu/mcheck/mce-apei.c b/arch/x86/kernel/cpu/mcheck/mce-apei.c
index cd8b166..de8b60a 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-apei.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-apei.c
@@ -42,8 +42,7 @@
 	struct mce m;
 
 	/* Only corrected MC is reported */
-	if (!corrected || !(mem_err->validation_bits &
-				CPER_MEM_VALID_PHYSICAL_ADDRESS))
+	if (!corrected || !(mem_err->validation_bits & CPER_MEM_VALID_PA))
 		return;
 
 	mce_setup(&m);
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index 71a39f3..9f7ca26 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -15,6 +15,7 @@
 #include <linux/clocksource.h>
 #include <linux/module.h>
 #include <linux/hardirq.h>
+#include <linux/efi.h>
 #include <linux/interrupt.h>
 #include <asm/processor.h>
 #include <asm/hypervisor.h>
@@ -23,6 +24,8 @@
 #include <asm/desc.h>
 #include <asm/idle.h>
 #include <asm/irq_regs.h>
+#include <asm/i8259.h>
+#include <asm/apic.h>
 
 struct ms_hyperv_info ms_hyperv;
 EXPORT_SYMBOL_GPL(ms_hyperv);
@@ -76,6 +79,30 @@
 	printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n",
 	       ms_hyperv.features, ms_hyperv.hints);
 
+#ifdef CONFIG_X86_LOCAL_APIC
+	if (ms_hyperv.features & HV_X64_MSR_APIC_FREQUENCY_AVAILABLE) {
+		/*
+		 * Get the APIC frequency.
+		 */
+		u64	hv_lapic_frequency;
+
+		rdmsrl(HV_X64_MSR_APIC_FREQUENCY, hv_lapic_frequency);
+		hv_lapic_frequency = div_u64(hv_lapic_frequency, HZ);
+		lapic_timer_frequency = hv_lapic_frequency;
+		printk(KERN_INFO "HyperV: LAPIC Timer Frequency: %#x\n",
+				lapic_timer_frequency);
+
+		/*
+		 * On Hyper-V, when we are booting off an EFI firmware stack,
+		 * we do not have many legacy devices including PIC, PIT etc.
+		 */
+		if (efi_enabled(EFI_BOOT)) {
+			printk(KERN_INFO "HyperV: Using null_legacy_pic\n");
+			legacy_pic = &null_legacy_pic;
+		}
+	}
+#endif
+
 	if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
 		clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100);
 }
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 897783b..8e13293 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -1276,16 +1276,16 @@
 static int __kprobes
 perf_event_nmi_handler(unsigned int cmd, struct pt_regs *regs)
 {
-	int ret;
 	u64 start_clock;
 	u64 finish_clock;
+	int ret;
 
 	if (!atomic_read(&active_events))
 		return NMI_DONE;
 
-	start_clock = local_clock();
+	start_clock = sched_clock();
 	ret = x86_pmu.handle_irq(regs);
-	finish_clock = local_clock();
+	finish_clock = sched_clock();
 
 	perf_sample_event_took(finish_clock - start_clock);
 
@@ -1888,10 +1888,7 @@
 	userpg->cap_user_rdpmc = x86_pmu.attr_rdpmc;
 	userpg->pmc_width = x86_pmu.cntval_bits;
 
-	if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
-		return;
-
-	if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
+	if (!sched_clock_stable)
 		return;
 
 	userpg->cap_user_time = 1;
@@ -1899,10 +1896,8 @@
 	userpg->time_shift = CYC2NS_SCALE_FACTOR;
 	userpg->time_offset = this_cpu_read(cyc2ns_offset) - now;
 
-	if (sched_clock_stable && !check_tsc_disabled()) {
-		userpg->cap_user_time_zero = 1;
-		userpg->time_zero = this_cpu_read(cyc2ns_offset);
-	}
+	userpg->cap_user_time_zero = 1;
+	userpg->time_zero = this_cpu_read(cyc2ns_offset);
 }
 
 /*
@@ -1994,7 +1989,7 @@
 		frame.return_address = 0;
 
 		bytes = copy_from_user_nmi(&frame, fp, sizeof(frame));
-		if (bytes != sizeof(frame))
+		if (bytes != 0)
 			break;
 
 		if (!valid_user_frame(fp, sizeof(frame)))
@@ -2046,7 +2041,7 @@
 		frame.return_address = 0;
 
 		bytes = copy_from_user_nmi(&frame, fp, sizeof(frame));
-		if (bytes != sizeof(frame))
+		if (bytes != 0)
 			break;
 
 		if (!valid_user_frame(fp, sizeof(frame)))
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index cc16faa..fd00bb2 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -164,6 +164,11 @@
 	struct perf_guest_switch_msr	guest_switch_msrs[X86_PMC_IDX_MAX];
 
 	/*
+	 * Intel checkpoint mask
+	 */
+	u64				intel_cp_status;
+
+	/*
 	 * manage shared (per-core, per-cpu) registers
 	 * used on Intel NHM/WSM/SNB
 	 */
@@ -440,6 +445,7 @@
 	int		lbr_nr;			   /* hardware stack size */
 	u64		lbr_sel_mask;		   /* LBR_SELECT valid bits */
 	const int	*lbr_sel_map;		   /* lbr_select mappings */
+	bool		lbr_double_abort;	   /* duplicated lbr aborts */
 
 	/*
 	 * Extra registers for events
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index f31a165..0fa4f24 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -190,9 +190,9 @@
 	EVENT_EXTRA_END
 };
 
-EVENT_ATTR_STR(mem-loads, mem_ld_nhm, "event=0x0b,umask=0x10,ldlat=3");
-EVENT_ATTR_STR(mem-loads, mem_ld_snb, "event=0xcd,umask=0x1,ldlat=3");
-EVENT_ATTR_STR(mem-stores, mem_st_snb, "event=0xcd,umask=0x2");
+EVENT_ATTR_STR(mem-loads,	mem_ld_nhm,	"event=0x0b,umask=0x10,ldlat=3");
+EVENT_ATTR_STR(mem-loads,	mem_ld_snb,	"event=0xcd,umask=0x1,ldlat=3");
+EVENT_ATTR_STR(mem-stores,	mem_st_snb,	"event=0xcd,umask=0x2");
 
 struct attribute *nhm_events_attrs[] = {
 	EVENT_PTR(mem_ld_nhm),
@@ -1184,6 +1184,11 @@
 	wrmsrl(hwc->config_base, ctrl_val);
 }
 
+static inline bool event_is_checkpointed(struct perf_event *event)
+{
+	return (event->hw.config & HSW_IN_TX_CHECKPOINTED) != 0;
+}
+
 static void intel_pmu_disable_event(struct perf_event *event)
 {
 	struct hw_perf_event *hwc = &event->hw;
@@ -1197,6 +1202,7 @@
 
 	cpuc->intel_ctrl_guest_mask &= ~(1ull << hwc->idx);
 	cpuc->intel_ctrl_host_mask &= ~(1ull << hwc->idx);
+	cpuc->intel_cp_status &= ~(1ull << hwc->idx);
 
 	/*
 	 * must disable before any actual event
@@ -1271,6 +1277,9 @@
 	if (event->attr.exclude_guest)
 		cpuc->intel_ctrl_host_mask |= (1ull << hwc->idx);
 
+	if (unlikely(event_is_checkpointed(event)))
+		cpuc->intel_cp_status |= (1ull << hwc->idx);
+
 	if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
 		intel_pmu_enable_fixed(hwc);
 		return;
@@ -1289,6 +1298,17 @@
 int intel_pmu_save_and_restart(struct perf_event *event)
 {
 	x86_perf_event_update(event);
+	/*
+	 * For a checkpointed counter always reset back to 0.  This
+	 * avoids a situation where the counter overflows, aborts the
+	 * transaction and is then set back to shortly before the
+	 * overflow, and overflows and aborts again.
+	 */
+	if (unlikely(event_is_checkpointed(event))) {
+		/* No race with NMIs because the counter should not be armed */
+		wrmsrl(event->hw.event_base, 0);
+		local64_set(&event->hw.prev_count, 0);
+	}
 	return x86_perf_event_set_period(event);
 }
 
@@ -1372,6 +1392,13 @@
 		x86_pmu.drain_pebs(regs);
 	}
 
+	/*
+	 * Checkpointed counters can lead to 'spurious' PMIs because the
+	 * rollback caused by the PMI will have cleared the overflow status
+	 * bit. Therefore always force probe these counters.
+	 */
+	status |= cpuc->intel_cp_status;
+
 	for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
 		struct perf_event *event = cpuc->events[bit];
 
@@ -1837,6 +1864,20 @@
 	      event->attr.precise_ip > 0))
 		return -EOPNOTSUPP;
 
+	if (event_is_checkpointed(event)) {
+		/*
+		 * Sampling of checkpointed events can cause situations where
+		 * the CPU constantly aborts because of a overflow, which is
+		 * then checkpointed back and ignored. Forbid checkpointing
+		 * for sampling.
+		 *
+		 * But still allow a long sampling period, so that perf stat
+		 * from KVM works.
+		 */
+		if (event->attr.sample_period > 0 &&
+		    event->attr.sample_period < 0x7fffffff)
+			return -EOPNOTSUPP;
+	}
 	return 0;
 }
 
@@ -2182,10 +2223,36 @@
 	}
 }
 
-EVENT_ATTR_STR(mem-loads,      mem_ld_hsw,     "event=0xcd,umask=0x1,ldlat=3");
-EVENT_ATTR_STR(mem-stores,     mem_st_hsw,     "event=0xd0,umask=0x82")
+EVENT_ATTR_STR(mem-loads,	mem_ld_hsw,	"event=0xcd,umask=0x1,ldlat=3");
+EVENT_ATTR_STR(mem-stores,	mem_st_hsw,	"event=0xd0,umask=0x82")
+
+/* Haswell special events */
+EVENT_ATTR_STR(tx-start,	tx_start,	"event=0xc9,umask=0x1");
+EVENT_ATTR_STR(tx-commit,	tx_commit,	"event=0xc9,umask=0x2");
+EVENT_ATTR_STR(tx-abort,	tx_abort,	"event=0xc9,umask=0x4");
+EVENT_ATTR_STR(tx-capacity,	tx_capacity,	"event=0x54,umask=0x2");
+EVENT_ATTR_STR(tx-conflict,	tx_conflict,	"event=0x54,umask=0x1");
+EVENT_ATTR_STR(el-start,	el_start,	"event=0xc8,umask=0x1");
+EVENT_ATTR_STR(el-commit,	el_commit,	"event=0xc8,umask=0x2");
+EVENT_ATTR_STR(el-abort,	el_abort,	"event=0xc8,umask=0x4");
+EVENT_ATTR_STR(el-capacity,	el_capacity,	"event=0x54,umask=0x2");
+EVENT_ATTR_STR(el-conflict,	el_conflict,	"event=0x54,umask=0x1");
+EVENT_ATTR_STR(cycles-t,	cycles_t,	"event=0x3c,in_tx=1");
+EVENT_ATTR_STR(cycles-ct,	cycles_ct,	"event=0x3c,in_tx=1,in_tx_cp=1");
 
 static struct attribute *hsw_events_attrs[] = {
+	EVENT_PTR(tx_start),
+	EVENT_PTR(tx_commit),
+	EVENT_PTR(tx_abort),
+	EVENT_PTR(tx_capacity),
+	EVENT_PTR(tx_conflict),
+	EVENT_PTR(el_start),
+	EVENT_PTR(el_commit),
+	EVENT_PTR(el_abort),
+	EVENT_PTR(el_capacity),
+	EVENT_PTR(el_conflict),
+	EVENT_PTR(cycles_t),
+	EVENT_PTR(cycles_ct),
 	EVENT_PTR(mem_ld_hsw),
 	EVENT_PTR(mem_st_hsw),
 	NULL
@@ -2452,6 +2519,7 @@
 		x86_pmu.hw_config = hsw_hw_config;
 		x86_pmu.get_event_constraints = hsw_get_event_constraints;
 		x86_pmu.cpu_events = hsw_events_attrs;
+		x86_pmu.lbr_double_abort = true;
 		pr_cont("Haswell events, ");
 		break;
 
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index ab3ba1c..ae96cfa 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -12,6 +12,7 @@
 
 #define BTS_BUFFER_SIZE		(PAGE_SIZE << 4)
 #define PEBS_BUFFER_SIZE	PAGE_SIZE
+#define PEBS_FIXUP_SIZE		PAGE_SIZE
 
 /*
  * pebs_record_32 for p4 and core not supported
@@ -182,18 +183,32 @@
  * Same as pebs_record_nhm, with two additional fields.
  */
 struct pebs_record_hsw {
-	struct pebs_record_nhm nhm;
-	/*
-	 * Real IP of the event. In the Intel documentation this
-	 * is called eventingrip.
-	 */
-	u64 real_ip;
-	/*
-	 * TSX tuning information field: abort cycles and abort flags.
-	 */
-	u64 tsx_tuning;
+	u64 flags, ip;
+	u64 ax, bx, cx, dx;
+	u64 si, di, bp, sp;
+	u64 r8,  r9,  r10, r11;
+	u64 r12, r13, r14, r15;
+	u64 status, dla, dse, lat;
+	u64 real_ip, tsx_tuning;
 };
 
+union hsw_tsx_tuning {
+	struct {
+		u32 cycles_last_block     : 32,
+		    hle_abort		  : 1,
+		    rtm_abort		  : 1,
+		    instruction_abort     : 1,
+		    non_instruction_abort : 1,
+		    retry		  : 1,
+		    data_conflict	  : 1,
+		    capacity_writes	  : 1,
+		    capacity_reads	  : 1;
+	};
+	u64	    value;
+};
+
+#define PEBS_HSW_TSX_FLAGS	0xff00000000ULL
+
 void init_debug_store_on_cpu(int cpu)
 {
 	struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
@@ -214,12 +229,14 @@
 	wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA, 0, 0);
 }
 
+static DEFINE_PER_CPU(void *, insn_buffer);
+
 static int alloc_pebs_buffer(int cpu)
 {
 	struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
 	int node = cpu_to_node(cpu);
 	int max, thresh = 1; /* always use a single PEBS record */
-	void *buffer;
+	void *buffer, *ibuffer;
 
 	if (!x86_pmu.pebs)
 		return 0;
@@ -228,6 +245,19 @@
 	if (unlikely(!buffer))
 		return -ENOMEM;
 
+	/*
+	 * HSW+ already provides us the eventing ip; no need to allocate this
+	 * buffer then.
+	 */
+	if (x86_pmu.intel_cap.pebs_format < 2) {
+		ibuffer = kzalloc_node(PEBS_FIXUP_SIZE, GFP_KERNEL, node);
+		if (!ibuffer) {
+			kfree(buffer);
+			return -ENOMEM;
+		}
+		per_cpu(insn_buffer, cpu) = ibuffer;
+	}
+
 	max = PEBS_BUFFER_SIZE / x86_pmu.pebs_record_size;
 
 	ds->pebs_buffer_base = (u64)(unsigned long)buffer;
@@ -248,6 +278,9 @@
 	if (!ds || !x86_pmu.pebs)
 		return;
 
+	kfree(per_cpu(insn_buffer, cpu));
+	per_cpu(insn_buffer, cpu) = NULL;
+
 	kfree((void *)(unsigned long)ds->pebs_buffer_base);
 	ds->pebs_buffer_base = 0;
 }
@@ -715,6 +748,7 @@
 	unsigned long old_to, to = cpuc->lbr_entries[0].to;
 	unsigned long ip = regs->ip;
 	int is_64bit = 0;
+	void *kaddr;
 
 	/*
 	 * We don't need to fixup if the PEBS assist is fault like
@@ -738,7 +772,7 @@
 	 * unsigned math, either ip is before the start (impossible) or
 	 * the basic block is larger than 1 page (sanity)
 	 */
-	if ((ip - to) > PAGE_SIZE)
+	if ((ip - to) > PEBS_FIXUP_SIZE)
 		return 0;
 
 	/*
@@ -749,29 +783,33 @@
 		return 1;
 	}
 
+	if (!kernel_ip(ip)) {
+		int size, bytes;
+		u8 *buf = this_cpu_read(insn_buffer);
+
+		size = ip - to; /* Must fit our buffer, see above */
+		bytes = copy_from_user_nmi(buf, (void __user *)to, size);
+		if (bytes != 0)
+			return 0;
+
+		kaddr = buf;
+	} else {
+		kaddr = (void *)to;
+	}
+
 	do {
 		struct insn insn;
-		u8 buf[MAX_INSN_SIZE];
-		void *kaddr;
 
 		old_to = to;
-		if (!kernel_ip(ip)) {
-			int bytes, size = MAX_INSN_SIZE;
-
-			bytes = copy_from_user_nmi(buf, (void __user *)to, size);
-			if (bytes != size)
-				return 0;
-
-			kaddr = buf;
-		} else
-			kaddr = (void *)to;
 
 #ifdef CONFIG_X86_64
 		is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32);
 #endif
 		insn_init(&insn, kaddr, is_64bit);
 		insn_get_length(&insn);
+
 		to += insn.length;
+		kaddr += insn.length;
 	} while (to < ip);
 
 	if (to == ip) {
@@ -786,16 +824,34 @@
 	return 0;
 }
 
+static inline u64 intel_hsw_weight(struct pebs_record_hsw *pebs)
+{
+	if (pebs->tsx_tuning) {
+		union hsw_tsx_tuning tsx = { .value = pebs->tsx_tuning };
+		return tsx.cycles_last_block;
+	}
+	return 0;
+}
+
+static inline u64 intel_hsw_transaction(struct pebs_record_hsw *pebs)
+{
+	u64 txn = (pebs->tsx_tuning & PEBS_HSW_TSX_FLAGS) >> 32;
+
+	/* For RTM XABORTs also log the abort code from AX */
+	if ((txn & PERF_TXN_TRANSACTION) && (pebs->ax & 1))
+		txn |= ((pebs->ax >> 24) & 0xff) << PERF_TXN_ABORT_SHIFT;
+	return txn;
+}
+
 static void __intel_pmu_pebs_event(struct perf_event *event,
 				   struct pt_regs *iregs, void *__pebs)
 {
 	/*
-	 * We cast to pebs_record_nhm to get the load latency data
-	 * if extra_reg MSR_PEBS_LD_LAT_THRESHOLD used
+	 * We cast to the biggest pebs_record but are careful not to
+	 * unconditionally access the 'extra' entries.
 	 */
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	struct pebs_record_nhm *pebs = __pebs;
-	struct pebs_record_hsw *pebs_hsw = __pebs;
+	struct pebs_record_hsw *pebs = __pebs;
 	struct perf_sample_data data;
 	struct pt_regs regs;
 	u64 sample_type;
@@ -854,7 +910,7 @@
 	regs.sp = pebs->sp;
 
 	if (event->attr.precise_ip > 1 && x86_pmu.intel_cap.pebs_format >= 2) {
-		regs.ip = pebs_hsw->real_ip;
+		regs.ip = pebs->real_ip;
 		regs.flags |= PERF_EFLAGS_EXACT;
 	} else if (event->attr.precise_ip > 1 && intel_pmu_pebs_fixup_ip(&regs))
 		regs.flags |= PERF_EFLAGS_EXACT;
@@ -862,9 +918,18 @@
 		regs.flags &= ~PERF_EFLAGS_EXACT;
 
 	if ((event->attr.sample_type & PERF_SAMPLE_ADDR) &&
-		x86_pmu.intel_cap.pebs_format >= 1)
+	    x86_pmu.intel_cap.pebs_format >= 1)
 		data.addr = pebs->dla;
 
+	if (x86_pmu.intel_cap.pebs_format >= 2) {
+		/* Only set the TSX weight when no memory weight. */
+		if ((event->attr.sample_type & PERF_SAMPLE_WEIGHT) && !fll)
+			data.weight = intel_hsw_weight(pebs);
+
+		if (event->attr.sample_type & PERF_SAMPLE_TRANSACTION)
+			data.txn = intel_hsw_transaction(pebs);
+	}
+
 	if (has_branch_stack(event))
 		data.br_stack = &cpuc->lbr_stack;
 
@@ -913,17 +978,34 @@
 	__intel_pmu_pebs_event(event, iregs, at);
 }
 
-static void __intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, void *at,
-					void *top)
+static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	struct debug_store *ds = cpuc->ds;
 	struct perf_event *event = NULL;
+	void *at, *top;
 	u64 status = 0;
 	int bit;
 
+	if (!x86_pmu.pebs_active)
+		return;
+
+	at  = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base;
+	top = (struct pebs_record_nhm *)(unsigned long)ds->pebs_index;
+
 	ds->pebs_index = ds->pebs_buffer_base;
 
+	if (unlikely(at > top))
+		return;
+
+	/*
+	 * Should not happen, we program the threshold at 1 and do not
+	 * set a reset value.
+	 */
+	WARN_ONCE(top - at > x86_pmu.max_pebs_events * x86_pmu.pebs_record_size,
+		  "Unexpected number of pebs records %ld\n",
+		  (long)(top - at) / x86_pmu.pebs_record_size);
+
 	for (; at < top; at += x86_pmu.pebs_record_size) {
 		struct pebs_record_nhm *p = at;
 
@@ -951,61 +1033,6 @@
 	}
 }
 
-static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
-{
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	struct debug_store *ds = cpuc->ds;
-	struct pebs_record_nhm *at, *top;
-	int n;
-
-	if (!x86_pmu.pebs_active)
-		return;
-
-	at  = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base;
-	top = (struct pebs_record_nhm *)(unsigned long)ds->pebs_index;
-
-	ds->pebs_index = ds->pebs_buffer_base;
-
-	n = top - at;
-	if (n <= 0)
-		return;
-
-	/*
-	 * Should not happen, we program the threshold at 1 and do not
-	 * set a reset value.
-	 */
-	WARN_ONCE(n > x86_pmu.max_pebs_events,
-		  "Unexpected number of pebs records %d\n", n);
-
-	return __intel_pmu_drain_pebs_nhm(iregs, at, top);
-}
-
-static void intel_pmu_drain_pebs_hsw(struct pt_regs *iregs)
-{
-	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	struct debug_store *ds = cpuc->ds;
-	struct pebs_record_hsw *at, *top;
-	int n;
-
-	if (!x86_pmu.pebs_active)
-		return;
-
-	at  = (struct pebs_record_hsw *)(unsigned long)ds->pebs_buffer_base;
-	top = (struct pebs_record_hsw *)(unsigned long)ds->pebs_index;
-
-	n = top - at;
-	if (n <= 0)
-		return;
-	/*
-	 * Should not happen, we program the threshold at 1 and do not
-	 * set a reset value.
-	 */
-	WARN_ONCE(n > x86_pmu.max_pebs_events,
-		  "Unexpected number of pebs records %d\n", n);
-
-	return __intel_pmu_drain_pebs_nhm(iregs, at, top);
-}
-
 /*
  * BTS, PEBS probe and setup
  */
@@ -1040,7 +1067,7 @@
 		case 2:
 			pr_cont("PEBS fmt2%c, ", pebs_type);
 			x86_pmu.pebs_record_size = sizeof(struct pebs_record_hsw);
-			x86_pmu.drain_pebs = intel_pmu_drain_pebs_hsw;
+			x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm;
 			break;
 
 		default:
diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
index d5be06a..d82d155 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
@@ -284,6 +284,7 @@
 	int lbr_format = x86_pmu.intel_cap.lbr_format;
 	u64 tos = intel_pmu_lbr_tos();
 	int i;
+	int out = 0;
 
 	for (i = 0; i < x86_pmu.lbr_nr; i++) {
 		unsigned long lbr_idx = (tos - i) & mask;
@@ -306,15 +307,27 @@
 		}
 		from = (u64)((((s64)from) << skip) >> skip);
 
-		cpuc->lbr_entries[i].from	= from;
-		cpuc->lbr_entries[i].to		= to;
-		cpuc->lbr_entries[i].mispred	= mis;
-		cpuc->lbr_entries[i].predicted	= pred;
-		cpuc->lbr_entries[i].in_tx	= in_tx;
-		cpuc->lbr_entries[i].abort	= abort;
-		cpuc->lbr_entries[i].reserved	= 0;
+		/*
+		 * Some CPUs report duplicated abort records,
+		 * with the second entry not having an abort bit set.
+		 * Skip them here. This loop runs backwards,
+		 * so we need to undo the previous record.
+		 * If the abort just happened outside the window
+		 * the extra entry cannot be removed.
+		 */
+		if (abort && x86_pmu.lbr_double_abort && out > 0)
+			out--;
+
+		cpuc->lbr_entries[out].from	 = from;
+		cpuc->lbr_entries[out].to	 = to;
+		cpuc->lbr_entries[out].mispred	 = mis;
+		cpuc->lbr_entries[out].predicted = pred;
+		cpuc->lbr_entries[out].in_tx	 = in_tx;
+		cpuc->lbr_entries[out].abort	 = abort;
+		cpuc->lbr_entries[out].reserved	 = 0;
+		out++;
 	}
-	cpuc->lbr_stack.nr = i;
+	cpuc->lbr_stack.nr = out;
 }
 
 void intel_pmu_lbr_read(void)
@@ -478,7 +491,7 @@
 
 		/* may fail if text not present */
 		bytes = copy_from_user_nmi(buf, (void __user *)from, size);
-		if (bytes != size)
+		if (bytes != 0)
 			return X86_BR_NONE;
 
 		addr = buf;
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
index 4118f9f..29c2487 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
@@ -997,6 +997,20 @@
 		}
 	}
 
+	if (!err) {
+		/*
+		 * For PCI bus with no UBOX device, find the next bus
+		 * that has UBOX device and use its mapping.
+		 */
+		i = -1;
+		for (bus = 255; bus >= 0; bus--) {
+			if (pcibus_to_physid[bus] >= 0)
+				i = pcibus_to_physid[bus];
+			else
+				pcibus_to_physid[bus] = i;
+		}
+	}
+
 	if (ubox_dev)
 		pci_dev_put(ubox_dev);
 
@@ -1099,6 +1113,24 @@
 	&format_attr_umask.attr,
 	&format_attr_edge.attr,
 	&format_attr_thresh8.attr,
+	&format_attr_match_rds.attr,
+	&format_attr_match_rnid30.attr,
+	&format_attr_match_rnid4.attr,
+	&format_attr_match_dnid.attr,
+	&format_attr_match_mc.attr,
+	&format_attr_match_opc.attr,
+	&format_attr_match_vnw.attr,
+	&format_attr_match0.attr,
+	&format_attr_match1.attr,
+	&format_attr_mask_rds.attr,
+	&format_attr_mask_rnid30.attr,
+	&format_attr_mask_rnid4.attr,
+	&format_attr_mask_dnid.attr,
+	&format_attr_mask_mc.attr,
+	&format_attr_mask_opc.attr,
+	&format_attr_mask_vnw.attr,
+	&format_attr_mask0.attr,
+	&format_attr_mask1.attr,
 	NULL,
 };
 
@@ -1312,17 +1344,83 @@
 	IVT_UNCORE_PCI_COMMON_INIT(),
 };
 
+/* registers in IRP boxes are not properly aligned */
+static unsigned ivt_uncore_irp_ctls[] = {0xd8, 0xdc, 0xe0, 0xe4};
+static unsigned ivt_uncore_irp_ctrs[] = {0xa0, 0xb0, 0xb8, 0xc0};
+
+static void ivt_uncore_irp_enable_event(struct intel_uncore_box *box, struct perf_event *event)
+{
+	struct pci_dev *pdev = box->pci_dev;
+	struct hw_perf_event *hwc = &event->hw;
+
+	pci_write_config_dword(pdev, ivt_uncore_irp_ctls[hwc->idx],
+			       hwc->config | SNBEP_PMON_CTL_EN);
+}
+
+static void ivt_uncore_irp_disable_event(struct intel_uncore_box *box, struct perf_event *event)
+{
+	struct pci_dev *pdev = box->pci_dev;
+	struct hw_perf_event *hwc = &event->hw;
+
+	pci_write_config_dword(pdev, ivt_uncore_irp_ctls[hwc->idx], hwc->config);
+}
+
+static u64 ivt_uncore_irp_read_counter(struct intel_uncore_box *box, struct perf_event *event)
+{
+	struct pci_dev *pdev = box->pci_dev;
+	struct hw_perf_event *hwc = &event->hw;
+	u64 count = 0;
+
+	pci_read_config_dword(pdev, ivt_uncore_irp_ctrs[hwc->idx], (u32 *)&count);
+	pci_read_config_dword(pdev, ivt_uncore_irp_ctrs[hwc->idx] + 4, (u32 *)&count + 1);
+
+	return count;
+}
+
+static struct intel_uncore_ops ivt_uncore_irp_ops = {
+	.init_box	= ivt_uncore_pci_init_box,
+	.disable_box	= snbep_uncore_pci_disable_box,
+	.enable_box	= snbep_uncore_pci_enable_box,
+	.disable_event	= ivt_uncore_irp_disable_event,
+	.enable_event	= ivt_uncore_irp_enable_event,
+	.read_counter	= ivt_uncore_irp_read_counter,
+};
+
+static struct intel_uncore_type ivt_uncore_irp = {
+	.name			= "irp",
+	.num_counters		= 4,
+	.num_boxes		= 1,
+	.perf_ctr_bits		= 48,
+	.event_mask		= IVT_PMON_RAW_EVENT_MASK,
+	.box_ctl		= SNBEP_PCI_PMON_BOX_CTL,
+	.ops			= &ivt_uncore_irp_ops,
+	.format_group		= &ivt_uncore_format_group,
+};
+
+static struct intel_uncore_ops ivt_uncore_qpi_ops = {
+	.init_box	= ivt_uncore_pci_init_box,
+	.disable_box	= snbep_uncore_pci_disable_box,
+	.enable_box	= snbep_uncore_pci_enable_box,
+	.disable_event	= snbep_uncore_pci_disable_event,
+	.enable_event	= snbep_qpi_enable_event,
+	.read_counter	= snbep_uncore_pci_read_counter,
+	.hw_config	= snbep_qpi_hw_config,
+	.get_constraint	= uncore_get_constraint,
+	.put_constraint	= uncore_put_constraint,
+};
+
 static struct intel_uncore_type ivt_uncore_qpi = {
-	.name		= "qpi",
-	.num_counters   = 4,
-	.num_boxes	= 3,
-	.perf_ctr_bits	= 48,
-	.perf_ctr	= SNBEP_PCI_PMON_CTR0,
-	.event_ctl	= SNBEP_PCI_PMON_CTL0,
-	.event_mask	= IVT_QPI_PCI_PMON_RAW_EVENT_MASK,
-	.box_ctl	= SNBEP_PCI_PMON_BOX_CTL,
-	.ops		= &ivt_uncore_pci_ops,
-	.format_group	= &ivt_uncore_qpi_format_group,
+	.name			= "qpi",
+	.num_counters		= 4,
+	.num_boxes		= 3,
+	.perf_ctr_bits		= 48,
+	.perf_ctr		= SNBEP_PCI_PMON_CTR0,
+	.event_ctl		= SNBEP_PCI_PMON_CTL0,
+	.event_mask		= IVT_QPI_PCI_PMON_RAW_EVENT_MASK,
+	.box_ctl		= SNBEP_PCI_PMON_BOX_CTL,
+	.num_shared_regs	= 1,
+	.ops			= &ivt_uncore_qpi_ops,
+	.format_group		= &ivt_uncore_qpi_format_group,
 };
 
 static struct intel_uncore_type ivt_uncore_r2pcie = {
@@ -1346,6 +1444,7 @@
 enum {
 	IVT_PCI_UNCORE_HA,
 	IVT_PCI_UNCORE_IMC,
+	IVT_PCI_UNCORE_IRP,
 	IVT_PCI_UNCORE_QPI,
 	IVT_PCI_UNCORE_R2PCIE,
 	IVT_PCI_UNCORE_R3QPI,
@@ -1354,6 +1453,7 @@
 static struct intel_uncore_type *ivt_pci_uncores[] = {
 	[IVT_PCI_UNCORE_HA]	= &ivt_uncore_ha,
 	[IVT_PCI_UNCORE_IMC]	= &ivt_uncore_imc,
+	[IVT_PCI_UNCORE_IRP]	= &ivt_uncore_irp,
 	[IVT_PCI_UNCORE_QPI]	= &ivt_uncore_qpi,
 	[IVT_PCI_UNCORE_R2PCIE]	= &ivt_uncore_r2pcie,
 	[IVT_PCI_UNCORE_R3QPI]	= &ivt_uncore_r3qpi,
@@ -1401,6 +1501,10 @@
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef1),
 		.driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_IMC, 7),
 	},
+	{ /* IRP */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe39),
+		.driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_IRP, 0),
+	},
 	{ /* QPI0 Port 0 */
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe32),
 		.driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_QPI, 0),
@@ -1429,6 +1533,16 @@
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe3e),
 		.driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_R3QPI, 2),
 	},
+	{ /* QPI Port 0 filter  */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe86),
+		.driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
+						   SNBEP_PCI_QPI_PORT0_FILTER),
+	},
+	{ /* QPI Port 0 filter  */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe96),
+		.driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
+						   SNBEP_PCI_QPI_PORT1_FILTER),
+	},
 	{ /* end: all zeroes */ }
 };
 
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
index aee6317..06fe3ed 100644
--- a/arch/x86/kernel/cpu/proc.c
+++ b/arch/x86/kernel/cpu/proc.c
@@ -11,15 +11,12 @@
 			      unsigned int cpu)
 {
 #ifdef CONFIG_SMP
-	if (c->x86_max_cores * smp_num_siblings > 1) {
-		seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
-		seq_printf(m, "siblings\t: %d\n",
-			   cpumask_weight(cpu_core_mask(cpu)));
-		seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
-		seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
-		seq_printf(m, "apicid\t\t: %d\n", c->apicid);
-		seq_printf(m, "initial apicid\t: %d\n", c->initial_apicid);
-	}
+	seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
+	seq_printf(m, "siblings\t: %d\n", cpumask_weight(cpu_core_mask(cpu)));
+	seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
+	seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
+	seq_printf(m, "apicid\t\t: %d\n", c->apicid);
+	seq_printf(m, "initial apicid\t: %d\n", c->initial_apicid);
 #endif
 }
 
diff --git a/arch/x86/kernel/cpu/umc.c b/arch/x86/kernel/cpu/umc.c
index 202759a..75c5ad5 100644
--- a/arch/x86/kernel/cpu/umc.c
+++ b/arch/x86/kernel/cpu/umc.c
@@ -11,8 +11,8 @@
 static const struct cpu_dev umc_cpu_dev = {
 	.c_vendor	= "UMC",
 	.c_ident	= { "UMC UMC UMC" },
-	.c_models = {
-		{ .vendor = X86_VENDOR_UMC, .family = 4, .model_names =
+	.legacy_models	= {
+		{ .family = 4, .model_names =
 		  {
 			  [1] = "U5D",
 			  [2] = "U5S",
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index e0e0841..18677a9 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -127,12 +127,12 @@
 	cpu_emergency_vmxoff();
 	cpu_emergency_svm_disable();
 
-	lapic_shutdown();
 #ifdef CONFIG_X86_IO_APIC
 	/* Prevent crash_kexec() from deadlocking on ioapic_lock. */
 	ioapic_zap_locks();
 	disable_IO_APIC();
 #endif
+	lapic_shutdown();
 #ifdef CONFIG_HPET_TIMER
 	hpet_disable();
 #endif
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 376dc78..d35078e 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -20,22 +20,13 @@
 #include <asm/hpet.h>
 #include <asm/apic.h>
 #include <asm/pci_x86.h>
+#include <asm/setup.h>
 
 __initdata u64 initial_dtb;
 char __initdata cmd_line[COMMAND_LINE_SIZE];
 
 int __initdata of_ioapic;
 
-unsigned long pci_address_to_pio(phys_addr_t address)
-{
-	/*
-	 * The ioport address can be directly used by inX / outX
-	 */
-	BUG_ON(address >= (1 << 16));
-	return (unsigned long)address;
-}
-EXPORT_SYMBOL_GPL(pci_address_to_pio);
-
 void __init early_init_dt_scan_chosen_arch(unsigned long node)
 {
 	BUG();
@@ -51,15 +42,6 @@
 	return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS));
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
-{
-	initrd_start = (unsigned long)__va(start);
-	initrd_end = (unsigned long)__va(end);
-	initrd_below_start_ok = 1;
-}
-#endif
-
 void __init add_dtb(u64 data)
 {
 	initial_dtb = data + offsetof(struct setup_data, data);
@@ -105,7 +87,6 @@
 
 static int x86_of_pci_irq_enable(struct pci_dev *dev)
 {
-	struct of_irq oirq;
 	u32 virq;
 	int ret;
 	u8 pin;
@@ -116,12 +97,7 @@
 	if (!pin)
 		return 0;
 
-	ret = of_irq_map_pci(dev, &oirq);
-	if (ret)
-		return ret;
-
-	virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
-			oirq.size);
+	virq = of_irq_parse_and_map_pci(dev, 0, 0);
 	if (virq == 0)
 		return -EINVAL;
 	dev->irq = virq;
@@ -230,7 +206,7 @@
 static void __init x86_flattree_get_config(void)
 {
 	u32 size, map_len;
-	void *new_dtb;
+	struct boot_param_header *dt;
 
 	if (!initial_dtb)
 		return;
@@ -238,24 +214,17 @@
 	map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK),
 			(u64)sizeof(struct boot_param_header));
 
-	initial_boot_params = early_memremap(initial_dtb, map_len);
-	size = be32_to_cpu(initial_boot_params->totalsize);
+	dt = early_memremap(initial_dtb, map_len);
+	size = be32_to_cpu(dt->totalsize);
 	if (map_len < size) {
-		early_iounmap(initial_boot_params, map_len);
-		initial_boot_params = early_memremap(initial_dtb, size);
+		early_iounmap(dt, map_len);
+		dt = early_memremap(initial_dtb, size);
 		map_len = size;
 	}
 
-	new_dtb = alloc_bootmem(size);
-	memcpy(new_dtb, initial_boot_params, size);
-	early_iounmap(initial_boot_params, map_len);
-
-	initial_boot_params = new_dtb;
-
-	/* root level address cells */
-	of_scan_flat_dt(early_init_dt_scan_root, NULL);
-
-	unflatten_device_tree();
+	initial_boot_params = dt;
+	unflatten_and_copy_device_tree();
+	early_iounmap(dt, map_len);
 }
 #else
 static inline void x86_flattree_get_config(void) { }
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index d15f575..01d1c18 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -14,9 +14,11 @@
 #include <xen/hvc-console.h>
 #include <asm/pci-direct.h>
 #include <asm/fixmap.h>
-#include <asm/mrst.h>
+#include <asm/intel-mid.h>
 #include <asm/pgtable.h>
 #include <linux/usb/ehci_def.h>
+#include <linux/efi.h>
+#include <asm/efi.h>
 
 /* Simple VGA output */
 #define VGABASE		(__ISA_IO_base + 0xb8000)
@@ -234,6 +236,11 @@
 			early_console_register(&early_hsu_console, keep);
 		}
 #endif
+#ifdef CONFIG_EARLY_PRINTK_EFI
+		if (!strncmp(buf, "efi", 3))
+			early_console_register(&early_efi_console, keep);
+#endif
+
 		buf++;
 	}
 	return 0;
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index f0dcb0c..fd1bc1b 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -362,12 +362,9 @@
 #ifdef CONFIG_PREEMPT
 ENTRY(resume_kernel)
 	DISABLE_INTERRUPTS(CLBR_ANY)
-	cmpl $0,TI_preempt_count(%ebp)	# non-zero preempt_count ?
-	jnz restore_all
 need_resched:
-	movl TI_flags(%ebp), %ecx	# need_resched set ?
-	testb $_TIF_NEED_RESCHED, %cl
-	jz restore_all
+	cmpl $0,PER_CPU_VAR(__preempt_count)
+	jnz restore_all
 	testl $X86_EFLAGS_IF,PT_EFLAGS(%esp)	# interrupts off (exception path) ?
 	jz restore_all
 	call preempt_schedule_irq
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index b077f4c..603be7c 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1103,10 +1103,8 @@
 	/* Returning to kernel space. Check if we need preemption */
 	/* rcx:	 threadinfo. interrupts off. */
 ENTRY(retint_kernel)
-	cmpl $0,TI_preempt_count(%rcx)
+	cmpl $0,PER_CPU_VAR(__preempt_count)
 	jnz  retint_restore_args
-	bt  $TIF_NEED_RESCHED,TI_flags(%rcx)
-	jnc  retint_restore_args
 	bt   $9,EFLAGS-ARGOFFSET(%rsp)	/* interrupts off? */
 	jnc  retint_restore_args
 	call preempt_schedule_irq
@@ -1342,7 +1340,7 @@
 	.previous
 
 /* Call softirq on interrupt stack. Interrupts are off. */
-ENTRY(call_softirq)
+ENTRY(do_softirq_own_stack)
 	CFI_STARTPROC
 	pushq_cfi %rbp
 	CFI_REL_OFFSET rbp,0
@@ -1359,7 +1357,7 @@
 	decl PER_CPU_VAR(irq_count)
 	ret
 	CFI_ENDPROC
-END(call_softirq)
+END(do_softirq_own_stack)
 
 #ifdef CONFIG_XEN
 zeroentry xen_hypervisor_callback xen_do_hypervisor_callback
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
index 06f87be..c61a14a 100644
--- a/arch/x86/kernel/head32.c
+++ b/arch/x86/kernel/head32.c
@@ -35,8 +35,8 @@
 
 	/* Call the subarch specific early setup function */
 	switch (boot_params.hdr.hardware_subarch) {
-	case X86_SUBARCH_MRST:
-		x86_mrst_early_setup();
+	case X86_SUBARCH_INTEL_MID:
+		x86_intel_mid_early_setup();
 		break;
 	case X86_SUBARCH_CE4100:
 		x86_ce4100_early_setup();
diff --git a/arch/x86/kernel/i386_ksyms_32.c b/arch/x86/kernel/i386_ksyms_32.c
index 0fa6912..05fd74f 100644
--- a/arch/x86/kernel/i386_ksyms_32.c
+++ b/arch/x86/kernel/i386_ksyms_32.c
@@ -37,3 +37,10 @@
 
 EXPORT_SYMBOL(csum_partial);
 EXPORT_SYMBOL(empty_zero_page);
+
+#ifdef CONFIG_PREEMPT
+EXPORT_SYMBOL(___preempt_schedule);
+#ifdef CONFIG_CONTEXT_TRACKING
+EXPORT_SYMBOL(___preempt_schedule_context);
+#endif
+#endif
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c
index 9a5c460..2e977b5 100644
--- a/arch/x86/kernel/i8259.c
+++ b/arch/x86/kernel/i8259.c
@@ -312,8 +312,7 @@
 	 */
 	outb_pic(0x11, PIC_MASTER_CMD);	/* ICW1: select 8259A-1 init */
 
-	/* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 on x86-64,
-	   to 0x20-0x27 on i386 */
+	/* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 */
 	outb_pic(IRQ0_VECTOR, PIC_MASTER_IMR);
 
 	/* 8259A-1 (the master) has a slave on IR2 */
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
index 4186755..d7fcbed 100644
--- a/arch/x86/kernel/irq_32.c
+++ b/arch/x86/kernel/irq_32.c
@@ -100,9 +100,6 @@
 	irqctx->tinfo.task = curctx->tinfo.task;
 	irqctx->tinfo.previous_esp = current_stack_pointer;
 
-	/* Copy the preempt_count so that the [soft]irq checks work. */
-	irqctx->tinfo.preempt_count = curctx->tinfo.preempt_count;
-
 	if (unlikely(overflow))
 		call_on_stack(print_stack_overflow, isp);
 
@@ -131,7 +128,6 @@
 					       THREAD_SIZE_ORDER));
 	memset(&irqctx->tinfo, 0, sizeof(struct thread_info));
 	irqctx->tinfo.cpu		= cpu;
-	irqctx->tinfo.preempt_count	= HARDIRQ_OFFSET;
 	irqctx->tinfo.addr_limit	= MAKE_MM_SEG(0);
 
 	per_cpu(hardirq_ctx, cpu) = irqctx;
@@ -149,35 +145,21 @@
 	       cpu, per_cpu(hardirq_ctx, cpu),  per_cpu(softirq_ctx, cpu));
 }
 
-asmlinkage void do_softirq(void)
+void do_softirq_own_stack(void)
 {
-	unsigned long flags;
 	struct thread_info *curctx;
 	union irq_ctx *irqctx;
 	u32 *isp;
 
-	if (in_interrupt())
-		return;
+	curctx = current_thread_info();
+	irqctx = __this_cpu_read(softirq_ctx);
+	irqctx->tinfo.task = curctx->task;
+	irqctx->tinfo.previous_esp = current_stack_pointer;
 
-	local_irq_save(flags);
+	/* build the stack frame on the softirq stack */
+	isp = (u32 *) ((char *)irqctx + sizeof(*irqctx));
 
-	if (local_softirq_pending()) {
-		curctx = current_thread_info();
-		irqctx = __this_cpu_read(softirq_ctx);
-		irqctx->tinfo.task = curctx->task;
-		irqctx->tinfo.previous_esp = current_stack_pointer;
-
-		/* build the stack frame on the softirq stack */
-		isp = (u32 *) ((char *)irqctx + sizeof(*irqctx));
-
-		call_on_stack(__do_softirq, isp);
-		/*
-		 * Shouldn't happen, we returned above if in_interrupt():
-		 */
-		WARN_ON_ONCE(softirq_count());
-	}
-
-	local_irq_restore(flags);
+	call_on_stack(__do_softirq, isp);
 }
 
 bool handle_irq(unsigned irq, struct pt_regs *regs)
diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c
index d04d3ec..4d1c746 100644
--- a/arch/x86/kernel/irq_64.c
+++ b/arch/x86/kernel/irq_64.c
@@ -87,24 +87,3 @@
 	generic_handle_irq_desc(irq, desc);
 	return true;
 }
-
-
-extern void call_softirq(void);
-
-asmlinkage void do_softirq(void)
-{
-	__u32 pending;
-	unsigned long flags;
-
-	if (in_interrupt())
-		return;
-
-	local_irq_save(flags);
-	pending = local_softirq_pending();
-	/* Switch to interrupt stack */
-	if (pending) {
-		call_softirq();
-		WARN_ON_ONCE(softirq_count());
-	}
-	local_irq_restore(flags);
-}
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 697b93a..b2046e4 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -609,7 +609,7 @@
 
 struct dentry *kvm_init_debugfs(void)
 {
-	d_kvm_debug = debugfs_create_dir("kvm", NULL);
+	d_kvm_debug = debugfs_create_dir("kvm-guest", NULL);
 	if (!d_kvm_debug)
 		printk(KERN_WARNING "Could not create 'kvm' debugfs directory\n");
 
@@ -775,11 +775,22 @@
 	if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT))
 		return;
 
-	printk(KERN_INFO "KVM setup paravirtual spinlock\n");
-
-	static_key_slow_inc(&paravirt_ticketlocks_enabled);
-
 	pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(kvm_lock_spinning);
 	pv_lock_ops.unlock_kick = kvm_unlock_kick;
 }
+
+static __init int kvm_spinlock_init_jump(void)
+{
+	if (!kvm_para_available())
+		return 0;
+	if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT))
+		return 0;
+
+	static_key_slow_inc(&paravirt_ticketlocks_enabled);
+	printk(KERN_INFO "KVM setup paravirtual spinlock\n");
+
+	return 0;
+}
+early_initcall(kvm_spinlock_init_jump);
+
 #endif	/* CONFIG_PARAVIRT_SPINLOCKS */
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
index 88458fa..05266b5 100644
--- a/arch/x86/kernel/msr.c
+++ b/arch/x86/kernel/msr.c
@@ -46,7 +46,7 @@
 static loff_t msr_seek(struct file *file, loff_t offset, int orig)
 {
 	loff_t ret;
-	struct inode *inode = file->f_mapping->host;
+	struct inode *inode = file_inode(file);
 
 	mutex_lock(&inode->i_mutex);
 	switch (orig) {
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
index ba77ebc..6fcb49c 100644
--- a/arch/x86/kernel/nmi.c
+++ b/arch/x86/kernel/nmi.c
@@ -113,10 +113,10 @@
 		u64 before, delta, whole_msecs;
 		int remainder_ns, decimal_msecs, thishandled;
 
-		before = local_clock();
+		before = sched_clock();
 		thishandled = a->handler(type, regs);
 		handled += thishandled;
-		delta = local_clock() - before;
+		delta = sched_clock() - before;
 		trace_nmi_handler(a->handler, (int)delta, thishandled);
 
 		if (delta < nmi_longest_ns)
diff --git a/arch/x86/kernel/preempt.S b/arch/x86/kernel/preempt.S
new file mode 100644
index 0000000..ca7f0d5
--- /dev/null
+++ b/arch/x86/kernel/preempt.S
@@ -0,0 +1,25 @@
+
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+#include <asm/asm.h>
+#include <asm/calling.h>
+
+ENTRY(___preempt_schedule)
+	CFI_STARTPROC
+	SAVE_ALL
+	call preempt_schedule
+	RESTORE_ALL
+	ret
+	CFI_ENDPROC
+
+#ifdef CONFIG_CONTEXT_TRACKING
+
+ENTRY(___preempt_schedule_context)
+	CFI_STARTPROC
+	SAVE_ALL
+	call preempt_schedule_context
+	RESTORE_ALL
+	ret
+	CFI_ENDPROC
+
+#endif
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index c83516b..3fb8d95 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -391,9 +391,9 @@
 		 * The switch back from broadcast mode needs to be
 		 * called with interrupts disabled.
 		 */
-		 local_irq_disable();
-		 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
-		 local_irq_enable();
+		local_irq_disable();
+		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
+		local_irq_enable();
 	} else
 		default_idle();
 }
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 884f98f..c2ec1aa 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -292,6 +292,14 @@
 		set_iopl_mask(next->iopl);
 
 	/*
+	 * If it were not for PREEMPT_ACTIVE we could guarantee that the
+	 * preempt_count of all tasks was equal here and this would not be
+	 * needed.
+	 */
+	task_thread_info(prev_p)->saved_preempt_count = this_cpu_read(__preempt_count);
+	this_cpu_write(__preempt_count, task_thread_info(next_p)->saved_preempt_count);
+
+	/*
 	 * Now maybe handle debug registers and/or IO bitmaps
 	 */
 	if (unlikely(task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV ||
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index bb1dc51..45ab4d6 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -363,6 +363,14 @@
 	this_cpu_write(old_rsp, next->usersp);
 	this_cpu_write(current_task, next_p);
 
+	/*
+	 * If it were not for PREEMPT_ACTIVE we could guarantee that the
+	 * preempt_count of all tasks was equal here and this would not be
+	 * needed.
+	 */
+	task_thread_info(prev_p)->saved_preempt_count = this_cpu_read(__preempt_count);
+	this_cpu_write(__preempt_count, task_thread_info(next_p)->saved_preempt_count);
+
 	this_cpu_write(kernel_stack,
 		  (unsigned long)task_stack_page(next_p) +
 		  THREAD_SIZE - KERNEL_STACK_OFFSET);
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index e643e74..da3c599 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -61,7 +61,7 @@
 	if (reboot_type != BOOT_BIOS) {
 		reboot_type = BOOT_BIOS;
 		pr_info("%s series board detected. Selecting %s-method for reboots.\n",
-			"BIOS", d->ident);
+			d->ident, "BIOS");
 	}
 	return 0;
 }
@@ -117,7 +117,7 @@
 	if (reboot_type != BOOT_CF9) {
 		reboot_type = BOOT_CF9;
 		pr_info("%s series board detected. Selecting %s-method for reboots.\n",
-			"PCI", d->ident);
+			d->ident, "PCI");
 	}
 	return 0;
 }
@@ -127,7 +127,7 @@
 	if (reboot_type != BOOT_KBD) {
 		reboot_type = BOOT_KBD;
 		pr_info("%s series board detected. Selecting %s-method for reboot.\n",
-			"KBD", d->ident);
+			d->ident, "KBD");
 	}
 	return 0;
 }
@@ -136,148 +136,8 @@
  * This is a single dmi_table handling all reboot quirks.
  */
 static struct dmi_system_id __initdata reboot_dmi_table[] = {
-	{	/* Handle problems with rebooting on Dell E520's */
-		.callback = set_bios_reboot,
-		.ident = "Dell E520",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM061"),
-		},
-	},
-	{	/* Handle problems with rebooting on Dell 1300's */
-		.callback = set_bios_reboot,
-		.ident = "Dell PowerEdge 1300",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
-		},
-	},
-	{	/* Handle problems with rebooting on Dell 300's */
-		.callback = set_bios_reboot,
-		.ident = "Dell PowerEdge 300",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
-		},
-	},
-	{	/* Handle problems with rebooting on Dell Optiplex 745's SFF */
-		.callback = set_bios_reboot,
-		.ident = "Dell OptiPlex 745",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
-		},
-	},
-	{	/* Handle problems with rebooting on Dell Optiplex 745's DFF */
-		.callback = set_bios_reboot,
-		.ident = "Dell OptiPlex 745",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
-			DMI_MATCH(DMI_BOARD_NAME, "0MM599"),
-		},
-	},
-	{	/* Handle problems with rebooting on Dell Optiplex 745 with 0KW626 */
-		.callback = set_bios_reboot,
-		.ident = "Dell OptiPlex 745",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
-			DMI_MATCH(DMI_BOARD_NAME, "0KW626"),
-		},
-	},
-	{	/* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */
-		.callback = set_bios_reboot,
-		.ident = "Dell OptiPlex 330",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 330"),
-			DMI_MATCH(DMI_BOARD_NAME, "0KP561"),
-		},
-	},
-	{	/* Handle problems with rebooting on Dell Optiplex 360 with 0T656F */
-		.callback = set_bios_reboot,
-		.ident = "Dell OptiPlex 360",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 360"),
-			DMI_MATCH(DMI_BOARD_NAME, "0T656F"),
-		},
-	},
-	{	/* Handle problems with rebooting on Dell OptiPlex 760 with 0G919G */
-		.callback = set_bios_reboot,
-		.ident = "Dell OptiPlex 760",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 760"),
-			DMI_MATCH(DMI_BOARD_NAME, "0G919G"),
-		},
-	},
-	{	/* Handle problems with rebooting on Dell 2400's */
-		.callback = set_bios_reboot,
-		.ident = "Dell PowerEdge 2400",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
-		},
-	},
-	{	/* Handle problems with rebooting on Dell T5400's */
-		.callback = set_bios_reboot,
-		.ident = "Dell Precision T5400",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T5400"),
-		},
-	},
-	{	/* Handle problems with rebooting on Dell T7400's */
-		.callback = set_bios_reboot,
-		.ident = "Dell Precision T7400",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T7400"),
-		},
-	},
-	{	/* Handle problems with rebooting on HP laptops */
-		.callback = set_bios_reboot,
-		.ident = "HP Compaq Laptop",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"),
-		},
-	},
-	{	/* Handle problems with rebooting on Dell XPS710 */
-		.callback = set_bios_reboot,
-		.ident = "Dell XPS710",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Dell XPS710"),
-		},
-	},
-	{	/* Handle problems with rebooting on Dell DXP061 */
-		.callback = set_bios_reboot,
-		.ident = "Dell DXP061",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Dell DXP061"),
-		},
-	},
-	{	/* Handle problems with rebooting on Sony VGN-Z540N */
-		.callback = set_bios_reboot,
-		.ident = "Sony VGN-Z540N",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-Z540N"),
-		},
-	},
-	{	/* Handle problems with rebooting on ASUS P4S800 */
-		.callback = set_bios_reboot,
-		.ident = "ASUS P4S800",
-		.matches = {
-			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
-			DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
-		},
-	},
 
+	/* Acer */
 	{	/* Handle reboot issue on Acer Aspire one */
 		.callback = set_kbd_reboot,
 		.ident = "Acer Aspire One A110",
@@ -286,6 +146,8 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"),
 		},
 	},
+
+	/* Apple */
 	{	/* Handle problems with rebooting on Apple MacBook5 */
 		.callback = set_pci_reboot,
 		.ident = "Apple MacBook5",
@@ -318,12 +180,40 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1"),
 		},
 	},
-	{	/* Handle problems with rebooting on the Latitude E6320. */
-		.callback = set_pci_reboot,
-		.ident = "Dell Latitude E6320",
+
+	/* ASUS */
+	{	/* Handle problems with rebooting on ASUS P4S800 */
+		.callback = set_bios_reboot,
+		.ident = "ASUS P4S800",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
+		},
+	},
+
+	/* Dell */
+	{	/* Handle problems with rebooting on Dell DXP061 */
+		.callback = set_bios_reboot,
+		.ident = "Dell DXP061",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6320"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Dell DXP061"),
+		},
+	},
+	{	/* Handle problems with rebooting on Dell E520's */
+		.callback = set_bios_reboot,
+		.ident = "Dell E520",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM061"),
+		},
+	},
+	{	/* Handle problems with rebooting on the Latitude E5410. */
+		.callback = set_pci_reboot,
+		.ident = "Dell Latitude E5410",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E5410"),
 		},
 	},
 	{	/* Handle problems with rebooting on the Latitude E5420. */
@@ -334,6 +224,14 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E5420"),
 		},
 	},
+	{	/* Handle problems with rebooting on the Latitude E6320. */
+		.callback = set_pci_reboot,
+		.ident = "Dell Latitude E6320",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6320"),
+		},
+	},
 	{	/* Handle problems with rebooting on the Latitude E6420. */
 		.callback = set_pci_reboot,
 		.ident = "Dell Latitude E6420",
@@ -342,6 +240,59 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6420"),
 		},
 	},
+	{	/* Handle problems with rebooting on Dell Optiplex 330 with 0KP561 */
+		.callback = set_bios_reboot,
+		.ident = "Dell OptiPlex 330",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 330"),
+			DMI_MATCH(DMI_BOARD_NAME, "0KP561"),
+		},
+	},
+	{	/* Handle problems with rebooting on Dell Optiplex 360 with 0T656F */
+		.callback = set_bios_reboot,
+		.ident = "Dell OptiPlex 360",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 360"),
+			DMI_MATCH(DMI_BOARD_NAME, "0T656F"),
+		},
+	},
+	{	/* Handle problems with rebooting on Dell Optiplex 745's SFF */
+		.callback = set_bios_reboot,
+		.ident = "Dell OptiPlex 745",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
+		},
+	},
+	{	/* Handle problems with rebooting on Dell Optiplex 745's DFF */
+		.callback = set_bios_reboot,
+		.ident = "Dell OptiPlex 745",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
+			DMI_MATCH(DMI_BOARD_NAME, "0MM599"),
+		},
+	},
+	{	/* Handle problems with rebooting on Dell Optiplex 745 with 0KW626 */
+		.callback = set_bios_reboot,
+		.ident = "Dell OptiPlex 745",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 745"),
+			DMI_MATCH(DMI_BOARD_NAME, "0KW626"),
+		},
+	},
+	{	/* Handle problems with rebooting on Dell OptiPlex 760 with 0G919G */
+		.callback = set_bios_reboot,
+		.ident = "Dell OptiPlex 760",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 760"),
+			DMI_MATCH(DMI_BOARD_NAME, "0G919G"),
+		},
+	},
 	{	/* Handle problems with rebooting on the OptiPlex 990. */
 		.callback = set_pci_reboot,
 		.ident = "Dell OptiPlex 990",
@@ -350,6 +301,38 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"),
 		},
 	},
+	{	/* Handle problems with rebooting on Dell 300's */
+		.callback = set_bios_reboot,
+		.ident = "Dell PowerEdge 300",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
+		},
+	},
+	{	/* Handle problems with rebooting on Dell 1300's */
+		.callback = set_bios_reboot,
+		.ident = "Dell PowerEdge 1300",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
+		},
+	},
+	{	/* Handle problems with rebooting on Dell 2400's */
+		.callback = set_bios_reboot,
+		.ident = "Dell PowerEdge 2400",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
+		},
+	},
+	{	/* Handle problems with rebooting on the Dell PowerEdge C6100. */
+		.callback = set_pci_reboot,
+		.ident = "Dell PowerEdge C6100",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "C6100"),
+		},
+	},
 	{	/* Handle problems with rebooting on the Precision M6600. */
 		.callback = set_pci_reboot,
 		.ident = "Dell Precision M6600",
@@ -358,22 +341,51 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "Precision M6600"),
 		},
 	},
-	{	/* Handle problems with rebooting on the Dell PowerEdge C6100. */
-		.callback = set_pci_reboot,
-		.ident = "Dell PowerEdge C6100",
+	{	/* Handle problems with rebooting on Dell T5400's */
+		.callback = set_bios_reboot,
+		.ident = "Dell Precision T5400",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "C6100"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T5400"),
 		},
 	},
-	{	/* Some C6100 machines were shipped with vendor being 'Dell'. */
-		.callback = set_pci_reboot,
-		.ident = "Dell PowerEdge C6100",
+	{	/* Handle problems with rebooting on Dell T7400's */
+		.callback = set_bios_reboot,
+		.ident = "Dell Precision T7400",
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "C6100"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation T7400"),
 		},
 	},
+	{	/* Handle problems with rebooting on Dell XPS710 */
+		.callback = set_bios_reboot,
+		.ident = "Dell XPS710",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Dell XPS710"),
+		},
+	},
+
+	/* Hewlett-Packard */
+	{	/* Handle problems with rebooting on HP laptops */
+		.callback = set_bios_reboot,
+		.ident = "HP Compaq Laptop",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"),
+		},
+	},
+
+	/* Sony */
+	{	/* Handle problems with rebooting on Sony VGN-Z540N */
+		.callback = set_bios_reboot,
+		.ident = "Sony VGN-Z540N",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-Z540N"),
+		},
+	},
+
 	{ }
 };
 
@@ -527,10 +539,13 @@
 
 		case BOOT_CF9_COND:
 			if (port_cf9_safe) {
-				u8 cf9 = inb(0xcf9) & ~6;
+				u8 reboot_code = reboot_mode == REBOOT_WARM ?
+					0x06 : 0x0E;
+				u8 cf9 = inb(0xcf9) & ~reboot_code;
 				outb(cf9|2, 0xcf9); /* Request hard reset */
 				udelay(50);
-				outb(cf9|6, 0xcf9); /* Actually do the reset */
+				/* Actually do the reset */
+				outb(cf9|reboot_code, 0xcf9);
 				udelay(50);
 			}
 			reboot_type = BOOT_KBD;
@@ -542,6 +557,10 @@
 void native_machine_shutdown(void)
 {
 	/* Stop the cpus and apics */
+#ifdef CONFIG_X86_IO_APIC
+	disable_IO_APIC();
+#endif
+
 #ifdef CONFIG_SMP
 	/*
 	 * Stop all of the others. Also disable the local irq to
@@ -554,10 +573,6 @@
 
 	lapic_shutdown();
 
-#ifdef CONFIG_X86_IO_APIC
-	disable_IO_APIC();
-#endif
-
 #ifdef CONFIG_HPET_TIMER
 	hpet_disable();
 #endif
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
index 0aa2939..ca9622a 100644
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -12,7 +12,7 @@
 #include <asm/vsyscall.h>
 #include <asm/x86_init.h>
 #include <asm/time.h>
-#include <asm/mrst.h>
+#include <asm/intel-mid.h>
 #include <asm/rtc.h>
 
 #ifdef CONFIG_X86_32
@@ -189,9 +189,17 @@
 		return 0;
 
 	/* Intel MID platforms don't have ioport rtc */
-	if (mrst_identify_cpu())
+	if (intel_mid_identify_cpu())
 		return -ENODEV;
 
+#ifdef CONFIG_ACPI
+	if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_CMOS_RTC) {
+		/* This warning can likely go away again in a year or two. */
+		pr_info("ACPI: not registering RTC platform device\n");
+		return -ENODEV;
+	}
+#endif
+
 	platform_device_register(&rtc_device);
 	dev_info(&rtc_device.dev,
 		 "registered platform RTC device (no PNP device found)\n");
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index f0de629..918d489 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -993,6 +993,7 @@
 		efi_init();
 
 	dmi_scan_machine();
+	dmi_memdev_walk();
 	dmi_set_dump_stack_arch_desc();
 
 	/*
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 6cacab6..2a16558 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -73,11 +73,10 @@
 #include <asm/setup.h>
 #include <asm/uv/uv.h>
 #include <linux/mc146818rtc.h>
-
 #include <asm/smpboot_hooks.h>
 #include <asm/i8259.h>
-
 #include <asm/realmode.h>
+#include <asm/misc.h>
 
 /* State of each CPU */
 DEFINE_PER_CPU(int, cpu_state) = { 0 };
@@ -648,22 +647,46 @@
 	return (send_status | accept_status);
 }
 
+void smp_announce(void)
+{
+	int num_nodes = num_online_nodes();
+
+	printk(KERN_INFO "x86: Booted up %d node%s, %d CPUs\n",
+	       num_nodes, (num_nodes > 1 ? "s" : ""), num_online_cpus());
+}
+
 /* reduce the number of lines printed when booting a large cpu count system */
 static void announce_cpu(int cpu, int apicid)
 {
 	static int current_node = -1;
 	int node = early_cpu_to_node(cpu);
-	int max_cpu_present = find_last_bit(cpumask_bits(cpu_present_mask), NR_CPUS);
+	static int width, node_width;
+
+	if (!width)
+		width = num_digits(num_possible_cpus()) + 1; /* + '#' sign */
+
+	if (!node_width)
+		node_width = num_digits(num_possible_nodes()) + 1; /* + '#' */
+
+	if (cpu == 1)
+		printk(KERN_INFO "x86: Booting SMP configuration:\n");
 
 	if (system_state == SYSTEM_BOOTING) {
 		if (node != current_node) {
 			if (current_node > (-1))
-				pr_cont(" OK\n");
+				pr_cont("\n");
 			current_node = node;
-			pr_info("Booting Node %3d, Processors ", node);
+
+			printk(KERN_INFO ".... node %*s#%d, CPUs:  ",
+			       node_width - num_digits(node), " ", node);
 		}
-		pr_cont(" #%4d%s", cpu, cpu == max_cpu_present ? " OK\n" : "");
-		return;
+
+		/* Add padding for the BSP */
+		if (cpu == 1)
+			pr_cont("%*s", width + 1, " ");
+
+		pr_cont("%*s#%d", width - num_digits(cpu), " ", cpu);
+
 	} else
 		pr_info("Booting Node %d Processor %d APIC 0x%x\n",
 			node, cpu, apicid);
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 8c8093b..729aa77 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -88,7 +88,7 @@
 
 static inline void preempt_conditional_sti(struct pt_regs *regs)
 {
-	inc_preempt_count();
+	preempt_count_inc();
 	if (regs->flags & X86_EFLAGS_IF)
 		local_irq_enable();
 }
@@ -103,7 +103,7 @@
 {
 	if (regs->flags & X86_EFLAGS_IF)
 		local_irq_disable();
-	dec_preempt_count();
+	preempt_count_dec();
 }
 
 static int __kprobes
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 10c4f30..da6b35a 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -199,6 +199,15 @@
 		__x86_cpu_dev_end = .;
 	}
 
+#ifdef CONFIG_X86_INTEL_MID
+	.x86_intel_mid_dev.init : AT(ADDR(.x86_intel_mid_dev.init) - \
+								LOAD_OFFSET) {
+		__x86_intel_mid_dev_start = .;
+		*(.x86_intel_mid_dev.init)
+		__x86_intel_mid_dev_end = .;
+	}
+#endif
+
 	/*
 	 * start address and size of operations which during runtime
 	 * can be patched with virtualization friendly instructions or
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index b014d94..0406819 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -66,3 +66,10 @@
 #ifndef CONFIG_PARAVIRT
 EXPORT_SYMBOL(native_load_gs_index);
 #endif
+
+#ifdef CONFIG_PREEMPT
+EXPORT_SYMBOL(___preempt_schedule);
+#ifdef CONFIG_CONTEXT_TRACKING
+EXPORT_SYMBOL(___preempt_schedule_context);
+#endif
+#endif
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 3b8e745..2b2fce1 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -3255,25 +3255,29 @@
 
 static void ept_load_pdptrs(struct kvm_vcpu *vcpu)
 {
+	struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
+
 	if (!test_bit(VCPU_EXREG_PDPTR,
 		      (unsigned long *)&vcpu->arch.regs_dirty))
 		return;
 
 	if (is_paging(vcpu) && is_pae(vcpu) && !is_long_mode(vcpu)) {
-		vmcs_write64(GUEST_PDPTR0, vcpu->arch.mmu.pdptrs[0]);
-		vmcs_write64(GUEST_PDPTR1, vcpu->arch.mmu.pdptrs[1]);
-		vmcs_write64(GUEST_PDPTR2, vcpu->arch.mmu.pdptrs[2]);
-		vmcs_write64(GUEST_PDPTR3, vcpu->arch.mmu.pdptrs[3]);
+		vmcs_write64(GUEST_PDPTR0, mmu->pdptrs[0]);
+		vmcs_write64(GUEST_PDPTR1, mmu->pdptrs[1]);
+		vmcs_write64(GUEST_PDPTR2, mmu->pdptrs[2]);
+		vmcs_write64(GUEST_PDPTR3, mmu->pdptrs[3]);
 	}
 }
 
 static void ept_save_pdptrs(struct kvm_vcpu *vcpu)
 {
+	struct kvm_mmu *mmu = vcpu->arch.walk_mmu;
+
 	if (is_paging(vcpu) && is_pae(vcpu) && !is_long_mode(vcpu)) {
-		vcpu->arch.mmu.pdptrs[0] = vmcs_read64(GUEST_PDPTR0);
-		vcpu->arch.mmu.pdptrs[1] = vmcs_read64(GUEST_PDPTR1);
-		vcpu->arch.mmu.pdptrs[2] = vmcs_read64(GUEST_PDPTR2);
-		vcpu->arch.mmu.pdptrs[3] = vmcs_read64(GUEST_PDPTR3);
+		mmu->pdptrs[0] = vmcs_read64(GUEST_PDPTR0);
+		mmu->pdptrs[1] = vmcs_read64(GUEST_PDPTR1);
+		mmu->pdptrs[2] = vmcs_read64(GUEST_PDPTR2);
+		mmu->pdptrs[3] = vmcs_read64(GUEST_PDPTR3);
 	}
 
 	__set_bit(VCPU_EXREG_PDPTR,
@@ -7777,10 +7781,6 @@
 		vmcs_write64(GUEST_PDPTR1, vmcs12->guest_pdptr1);
 		vmcs_write64(GUEST_PDPTR2, vmcs12->guest_pdptr2);
 		vmcs_write64(GUEST_PDPTR3, vmcs12->guest_pdptr3);
-		__clear_bit(VCPU_EXREG_PDPTR,
-				(unsigned long *)&vcpu->arch.regs_avail);
-		__clear_bit(VCPU_EXREG_PDPTR,
-				(unsigned long *)&vcpu->arch.regs_dirty);
 	}
 
 	kvm_register_write(vcpu, VCPU_REGS_RSP, vmcs12->guest_rsp);
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 96b2c66..992d63b 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -16,7 +16,7 @@
 
 obj-$(CONFIG_SMP) += msr-smp.o cache-smp.o
 
-lib-y := delay.o
+lib-y := delay.o misc.o
 lib-y += thunk_$(BITS).o
 lib-y += usercopy_$(BITS).o usercopy.o getuser.o putuser.o
 lib-y += memcpy_$(BITS).o
diff --git a/arch/x86/lib/misc.c b/arch/x86/lib/misc.c
new file mode 100644
index 0000000..76b373a
--- /dev/null
+++ b/arch/x86/lib/misc.c
@@ -0,0 +1,21 @@
+/*
+ * Count the digits of @val including a possible sign.
+ *
+ * (Typed on and submitted from hpa's mobile phone.)
+ */
+int num_digits(int val)
+{
+	int m = 10;
+	int d = 1;
+
+	if (val < 0) {
+		d++;
+		val = -val;
+	}
+
+	while (val >= m) {
+		m *= 10;
+		d++;
+	}
+	return d;
+}
diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c
index 4f74d94..ddf9ecb 100644
--- a/arch/x86/lib/usercopy.c
+++ b/arch/x86/lib/usercopy.c
@@ -11,39 +11,26 @@
 #include <linux/sched.h>
 
 /*
- * best effort, GUP based copy_from_user() that is NMI-safe
+ * We rely on the nested NMI work to allow atomic faults from the NMI path; the
+ * nested NMI paths are careful to preserve CR2.
  */
 unsigned long
 copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
 {
-	unsigned long offset, addr = (unsigned long)from;
-	unsigned long size, len = 0;
-	struct page *page;
-	void *map;
-	int ret;
+	unsigned long ret;
 
 	if (__range_not_ok(from, n, TASK_SIZE))
-		return len;
+		return 0;
 
-	do {
-		ret = __get_user_pages_fast(addr, 1, 0, &page);
-		if (!ret)
-			break;
+	/*
+	 * Even though this function is typically called from NMI/IRQ context
+	 * disable pagefaults so that its behaviour is consistent even when
+	 * called form other contexts.
+	 */
+	pagefault_disable();
+	ret = __copy_from_user_inatomic(to, from, n);
+	pagefault_enable();
 
-		offset = addr & (PAGE_SIZE - 1);
-		size = min(PAGE_SIZE - offset, n - len);
-
-		map = kmap_atomic(page);
-		memcpy(to, map+offset, size);
-		kunmap_atomic(map);
-		put_page(page);
-
-		len  += size;
-		to   += size;
-		addr += size;
-
-	} while (len < n);
-
-	return len;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(copy_from_user_nmi);
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index 3eb18ac..e2f5e21 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -654,14 +654,13 @@
  * Returns number of bytes that could not be copied.
  * On success, this will be zero.
  */
-unsigned long
-copy_to_user(void __user *to, const void *from, unsigned long n)
+unsigned long _copy_to_user(void __user *to, const void *from, unsigned n)
 {
 	if (access_ok(VERIFY_WRITE, to, n))
 		n = __copy_to_user(to, from, n);
 	return n;
 }
-EXPORT_SYMBOL(copy_to_user);
+EXPORT_SYMBOL(_copy_to_user);
 
 /**
  * copy_from_user: - Copy a block of data from user space.
@@ -679,8 +678,7 @@
  * If some data could not be copied, this function will pad the copied
  * data to the requested size using zero bytes.
  */
-unsigned long
-_copy_from_user(void *to, const void __user *from, unsigned long n)
+unsigned long _copy_from_user(void *to, const void __user *from, unsigned n)
 {
 	if (access_ok(VERIFY_READ, from, n))
 		n = __copy_from_user(to, from, n);
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 3aaeffc..7a517bb 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -51,7 +51,7 @@
 	return 0;
 }
 
-static inline int __kprobes notify_page_fault(struct pt_regs *regs)
+static inline int __kprobes kprobes_fault(struct pt_regs *regs)
 {
 	int ret = 0;
 
@@ -1048,7 +1048,7 @@
 			return;
 
 		/* kprobes don't want to hook the spurious faults: */
-		if (notify_page_fault(regs))
+		if (kprobes_fault(regs))
 			return;
 		/*
 		 * Don't take the mm semaphore here. If we fixup a prefetch
@@ -1060,8 +1060,28 @@
 	}
 
 	/* kprobes don't want to hook the spurious faults: */
-	if (unlikely(notify_page_fault(regs)))
+	if (unlikely(kprobes_fault(regs)))
 		return;
+
+	if (unlikely(error_code & PF_RSVD))
+		pgtable_bad(regs, error_code, address);
+
+	if (static_cpu_has(X86_FEATURE_SMAP)) {
+		if (unlikely(smap_violation(error_code, regs))) {
+			bad_area_nosemaphore(regs, error_code, address);
+			return;
+		}
+	}
+
+	/*
+	 * If we're in an interrupt, have no user context or are running
+	 * in an atomic region then we must not take the fault:
+	 */
+	if (unlikely(in_atomic() || !mm)) {
+		bad_area_nosemaphore(regs, error_code, address);
+		return;
+	}
+
 	/*
 	 * It's safe to allow irq's after cr2 has been saved and the
 	 * vmalloc fault has been handled.
@@ -1078,27 +1098,8 @@
 			local_irq_enable();
 	}
 
-	if (unlikely(error_code & PF_RSVD))
-		pgtable_bad(regs, error_code, address);
-
-	if (static_cpu_has(X86_FEATURE_SMAP)) {
-		if (unlikely(smap_violation(error_code, regs))) {
-			bad_area_nosemaphore(regs, error_code, address);
-			return;
-		}
-	}
-
 	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
 
-	/*
-	 * If we're in an interrupt, have no user context or are running
-	 * in an atomic region then we must not take the fault:
-	 */
-	if (unlikely(in_atomic() || !mm)) {
-		bad_area_nosemaphore(regs, error_code, address);
-		return;
-	}
-
 	if (error_code & PF_WRITE)
 		flags |= FAULT_FLAG_WRITE;
 
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 04664cd..ce32017 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -399,8 +399,25 @@
 	return mapped_ram_size;
 }
 
-/* (PUD_SHIFT-PMD_SHIFT)/2 */
-#define STEP_SIZE_SHIFT 5
+static unsigned long __init get_new_step_size(unsigned long step_size)
+{
+	/*
+	 * Explain why we shift by 5 and why we don't have to worry about
+	 * 'step_size << 5' overflowing:
+	 *
+	 * initial mapped size is PMD_SIZE (2M).
+	 * We can not set step_size to be PUD_SIZE (1G) yet.
+	 * In worse case, when we cross the 1G boundary, and
+	 * PG_LEVEL_2M is not set, we will need 1+1+512 pages (2M + 8k)
+	 * to map 1G range with PTE. Use 5 as shift for now.
+	 *
+	 * Don't need to worry about overflow, on 32bit, when step_size
+	 * is 0, round_down() returns 0 for start, and that turns it
+	 * into 0x100000000ULL.
+	 */
+	return step_size << 5;
+}
+
 void __init init_mem_mapping(void)
 {
 	unsigned long end, real_end, start, last_start;
@@ -449,7 +466,7 @@
 		min_pfn_mapped = last_start >> PAGE_SHIFT;
 		/* only increase step_size after big range get mapped */
 		if (new_mapped_ram_size > mapped_ram_size)
-			step_size <<= STEP_SIZE_SHIFT;
+			step_size = get_new_step_size(step_size);
 		mapped_ram_size += new_mapped_ram_size;
 	}
 
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 79c216a..516593e 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -772,13 +772,21 @@
 	return;
 }
 
+static void bpf_jit_free_deferred(struct work_struct *work)
+{
+	struct sk_filter *fp = container_of(work, struct sk_filter, work);
+	unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
+	struct bpf_binary_header *header = (void *)addr;
+
+	set_memory_rw(addr, header->pages);
+	module_free(NULL, header);
+	kfree(fp);
+}
+
 void bpf_jit_free(struct sk_filter *fp)
 {
 	if (fp->bpf_func != sk_run_filter) {
-		unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
-		struct bpf_binary_header *header = (void *)addr;
-
-		set_memory_rw(addr, header->pages);
-		module_free(NULL, header);
+		INIT_WORK(&fp->work, bpf_jit_free_deferred);
+		schedule_work(&fp->work);
 	}
 }
diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c
index d6aa6e8..5d04be5 100644
--- a/arch/x86/oprofile/backtrace.c
+++ b/arch/x86/oprofile/backtrace.c
@@ -47,7 +47,7 @@
 	unsigned long bytes;
 
 	bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead));
-	if (bytes != sizeof(bufhead))
+	if (bytes != 0)
 		return NULL;
 
 	fp = (struct stack_frame_ia32 *) compat_ptr(bufhead[0].next_frame);
@@ -93,7 +93,7 @@
 	unsigned long bytes;
 
 	bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead));
-	if (bytes != sizeof(bufhead))
+	if (bytes != 0)
 		return NULL;
 
 	oprofile_add_trace(bufhead[0].return_address);
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile
index ee0af58..e063eed 100644
--- a/arch/x86/pci/Makefile
+++ b/arch/x86/pci/Makefile
@@ -18,7 +18,7 @@
 obj-$(CONFIG_X86_NUMAQ)		+= numaq_32.o
 obj-$(CONFIG_X86_NUMACHIP)	+= numachip.o
 
-obj-$(CONFIG_X86_INTEL_MID)	+= mrst.o
+obj-$(CONFIG_X86_INTEL_MID)	+= intel_mid_pci.o
 
 obj-y				+= common.o early.o
 obj-y				+= bus_numa.o
diff --git a/arch/x86/pci/mrst.c b/arch/x86/pci/intel_mid_pci.c
similarity index 95%
rename from arch/x86/pci/mrst.c
rename to arch/x86/pci/intel_mid_pci.c
index 903fded..51384ca 100644
--- a/arch/x86/pci/mrst.c
+++ b/arch/x86/pci/intel_mid_pci.c
@@ -1,5 +1,5 @@
 /*
- * Moorestown PCI support
+ * Intel MID PCI support
  *   Copyright (c) 2008 Intel Corporation
  *     Jesse Barnes <jesse.barnes@intel.com>
  *
@@ -150,12 +150,12 @@
 	 * shim. Therefore, use the header type in shim instead.
 	 */
 	if (reg >= 0x100 || reg == PCI_STATUS || reg == PCI_HEADER_TYPE)
-		return 0;
+		return false;
 	if (bus == 0 && (devfn == PCI_DEVFN(2, 0)
 				|| devfn == PCI_DEVFN(0, 0)
 				|| devfn == PCI_DEVFN(3, 0)))
-		return 1;
-	return 0; /* Langwell on others */
+		return true;
+	return false; /* Langwell on others */
 }
 
 static int pci_read(struct pci_bus *bus, unsigned int devfn, int where,
@@ -205,7 +205,7 @@
 			       where, size, value);
 }
 
-static int mrst_pci_irq_enable(struct pci_dev *dev)
+static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 {
 	u8 pin;
 	struct io_apic_irq_attr irq_attr;
@@ -225,23 +225,23 @@
 	return 0;
 }
 
-struct pci_ops pci_mrst_ops = {
+struct pci_ops intel_mid_pci_ops = {
 	.read = pci_read,
 	.write = pci_write,
 };
 
 /**
- * pci_mrst_init - installs pci_mrst_ops
+ * intel_mid_pci_init - installs intel_mid_pci_ops
  *
  * Moorestown has an interesting PCI implementation (see above).
  * Called when the early platform detection installs it.
  */
-int __init pci_mrst_init(void)
+int __init intel_mid_pci_init(void)
 {
 	pr_info("Intel MID platform detected, using MID PCI ops\n");
 	pci_mmcfg_late_init();
-	pcibios_enable_irq = mrst_pci_irq_enable;
-	pci_root_ops = pci_mrst_ops;
+	pcibios_enable_irq = intel_mid_pci_irq_enable;
+	pci_root_ops = intel_mid_pci_ops;
 	pci_soc_mode = 1;
 	/* Continue with standard init */
 	return 1;
diff --git a/arch/x86/platform/Makefile b/arch/x86/platform/Makefile
index 01e0231..20342d4 100644
--- a/arch/x86/platform/Makefile
+++ b/arch/x86/platform/Makefile
@@ -4,7 +4,7 @@
 obj-y	+= geode/
 obj-y	+= goldfish/
 obj-y	+= iris/
-obj-y	+= mrst/
+obj-y	+= intel-mid/
 obj-y	+= olpc/
 obj-y	+= scx200/
 obj-y	+= sfi/
diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile
index 6db1cc4..b7b0b35 100644
--- a/arch/x86/platform/efi/Makefile
+++ b/arch/x86/platform/efi/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_EFI) 		+= efi.o efi_$(BITS).o efi_stub_$(BITS).o
 obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
+obj-$(CONFIG_EARLY_PRINTK_EFI)	+= early_printk.o
diff --git a/arch/x86/platform/efi/early_printk.c b/arch/x86/platform/efi/early_printk.c
new file mode 100644
index 0000000..6599a00
--- /dev/null
+++ b/arch/x86/platform/efi/early_printk.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2013 Intel Corporation; author Matt Fleming
+ *
+ *  This file is part of the Linux kernel, and is made available under
+ *  the terms of the GNU General Public License version 2.
+ */
+
+#include <linux/console.h>
+#include <linux/efi.h>
+#include <linux/font.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <asm/setup.h>
+
+static const struct font_desc *font;
+static u32 efi_x, efi_y;
+
+static __init void early_efi_clear_scanline(unsigned int y)
+{
+	unsigned long base, *dst;
+	u16 len;
+
+	base = boot_params.screen_info.lfb_base;
+	len = boot_params.screen_info.lfb_linelength;
+
+	dst = early_ioremap(base + y*len, len);
+	if (!dst)
+		return;
+
+	memset(dst, 0, len);
+	early_iounmap(dst, len);
+}
+
+static __init void early_efi_scroll_up(void)
+{
+	unsigned long base, *dst, *src;
+	u16 len;
+	u32 i, height;
+
+	base = boot_params.screen_info.lfb_base;
+	len = boot_params.screen_info.lfb_linelength;
+	height = boot_params.screen_info.lfb_height;
+
+	for (i = 0; i < height - font->height; i++) {
+		dst = early_ioremap(base + i*len, len);
+		if (!dst)
+			return;
+
+		src = early_ioremap(base + (i + font->height) * len, len);
+		if (!src) {
+			early_iounmap(dst, len);
+			return;
+		}
+
+		memmove(dst, src, len);
+
+		early_iounmap(src, len);
+		early_iounmap(dst, len);
+	}
+}
+
+static void early_efi_write_char(u32 *dst, unsigned char c, unsigned int h)
+{
+	const u32 color_black = 0x00000000;
+	const u32 color_white = 0x00ffffff;
+	const u8 *src;
+	u8 s8;
+	int m;
+
+	src = font->data + c * font->height;
+	s8 = *(src + h);
+
+	for (m = 0; m < 8; m++) {
+		if ((s8 >> (7 - m)) & 1)
+			*dst = color_white;
+		else
+			*dst = color_black;
+		dst++;
+	}
+}
+
+static __init void
+early_efi_write(struct console *con, const char *str, unsigned int num)
+{
+	struct screen_info *si;
+	unsigned long base;
+	unsigned int len;
+	const char *s;
+	void *dst;
+
+	base = boot_params.screen_info.lfb_base;
+	si = &boot_params.screen_info;
+	len = si->lfb_linelength;
+
+	while (num) {
+		unsigned int linemax;
+		unsigned int h, count = 0;
+
+		for (s = str; *s && *s != '\n'; s++) {
+			if (count == num)
+				break;
+			count++;
+		}
+
+		linemax = (si->lfb_width - efi_x) / font->width;
+		if (count > linemax)
+			count = linemax;
+
+		for (h = 0; h < font->height; h++) {
+			unsigned int n, x;
+
+			dst = early_ioremap(base + (efi_y + h) * len, len);
+			if (!dst)
+				return;
+
+			s = str;
+			n = count;
+			x = efi_x;
+
+			while (n-- > 0) {
+				early_efi_write_char(dst + x*4, *s, h);
+				x += font->width;
+				s++;
+			}
+
+			early_iounmap(dst, len);
+		}
+
+		num -= count;
+		efi_x += count * font->width;
+		str += count;
+
+		if (num > 0 && *s == '\n') {
+			efi_x = 0;
+			efi_y += font->height;
+			str++;
+			num--;
+		}
+
+		if (efi_x >= si->lfb_width) {
+			efi_x = 0;
+			efi_y += font->height;
+		}
+
+		if (efi_y + font->height >= si->lfb_height) {
+			u32 i;
+
+			efi_y -= font->height;
+			early_efi_scroll_up();
+
+			for (i = 0; i < font->height; i++)
+				early_efi_clear_scanline(efi_y + i);
+		}
+	}
+}
+
+static __init int early_efi_setup(struct console *con, char *options)
+{
+	struct screen_info *si;
+	u16 xres, yres;
+	u32 i;
+
+	si = &boot_params.screen_info;
+	xres = si->lfb_width;
+	yres = si->lfb_height;
+
+	/*
+	 * early_efi_write_char() implicitly assumes a framebuffer with
+	 * 32-bits per pixel.
+	 */
+	if (si->lfb_depth != 32)
+		return -ENODEV;
+
+	font = get_default_font(xres, yres, -1, -1);
+	if (!font)
+		return -ENODEV;
+
+	efi_y = rounddown(yres, font->height) - font->height;
+	for (i = 0; i < (yres - efi_y) / font->height; i++)
+		early_efi_scroll_up();
+
+	return 0;
+}
+
+struct console early_efi_console = {
+	.name =		"earlyefi",
+	.write =	early_efi_write,
+	.setup =	early_efi_setup,
+	.flags =	CON_PRINTBUFFER,
+	.index =	-1,
+};
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index c7e22ab..92c0234 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -60,19 +60,6 @@
 
 static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 };
 
-struct efi __read_mostly efi = {
-	.mps        = EFI_INVALID_TABLE_ADDR,
-	.acpi       = EFI_INVALID_TABLE_ADDR,
-	.acpi20     = EFI_INVALID_TABLE_ADDR,
-	.smbios     = EFI_INVALID_TABLE_ADDR,
-	.sal_systab = EFI_INVALID_TABLE_ADDR,
-	.boot_info  = EFI_INVALID_TABLE_ADDR,
-	.hcdp       = EFI_INVALID_TABLE_ADDR,
-	.uga        = EFI_INVALID_TABLE_ADDR,
-	.uv_systab  = EFI_INVALID_TABLE_ADDR,
-};
-EXPORT_SYMBOL(efi);
-
 struct efi_memory_map memmap;
 
 static struct efi efi_phys __initdata;
@@ -80,6 +67,13 @@
 
 unsigned long x86_efi_facility;
 
+static __initdata efi_config_table_type_t arch_tables[] = {
+#ifdef CONFIG_X86_UV
+	{UV_SYSTEM_TABLE_GUID, "UVsystab", &efi.uv_systab},
+#endif
+	{NULL_GUID, NULL, NULL},
+};
+
 /*
  * Returns 1 if 'facility' is enabled, 0 otherwise.
  */
@@ -399,6 +393,8 @@
 
 	memblock_reserve(pmap, memmap.nr_map * memmap.desc_size);
 
+	efi.memmap = &memmap;
+
 	return 0;
 }
 
@@ -578,80 +574,6 @@
 	return 0;
 }
 
-static int __init efi_config_init(u64 tables, int nr_tables)
-{
-	void *config_tables, *tablep;
-	int i, sz;
-
-	if (efi_enabled(EFI_64BIT))
-		sz = sizeof(efi_config_table_64_t);
-	else
-		sz = sizeof(efi_config_table_32_t);
-
-	/*
-	 * Let's see what config tables the firmware passed to us.
-	 */
-	config_tables = early_ioremap(tables, nr_tables * sz);
-	if (config_tables == NULL) {
-		pr_err("Could not map Configuration table!\n");
-		return -ENOMEM;
-	}
-
-	tablep = config_tables;
-	pr_info("");
-	for (i = 0; i < efi.systab->nr_tables; i++) {
-		efi_guid_t guid;
-		unsigned long table;
-
-		if (efi_enabled(EFI_64BIT)) {
-			u64 table64;
-			guid = ((efi_config_table_64_t *)tablep)->guid;
-			table64 = ((efi_config_table_64_t *)tablep)->table;
-			table = table64;
-#ifdef CONFIG_X86_32
-			if (table64 >> 32) {
-				pr_cont("\n");
-				pr_err("Table located above 4GB, disabling EFI.\n");
-				early_iounmap(config_tables,
-					      efi.systab->nr_tables * sz);
-				return -EINVAL;
-			}
-#endif
-		} else {
-			guid = ((efi_config_table_32_t *)tablep)->guid;
-			table = ((efi_config_table_32_t *)tablep)->table;
-		}
-		if (!efi_guidcmp(guid, MPS_TABLE_GUID)) {
-			efi.mps = table;
-			pr_cont(" MPS=0x%lx ", table);
-		} else if (!efi_guidcmp(guid, ACPI_20_TABLE_GUID)) {
-			efi.acpi20 = table;
-			pr_cont(" ACPI 2.0=0x%lx ", table);
-		} else if (!efi_guidcmp(guid, ACPI_TABLE_GUID)) {
-			efi.acpi = table;
-			pr_cont(" ACPI=0x%lx ", table);
-		} else if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID)) {
-			efi.smbios = table;
-			pr_cont(" SMBIOS=0x%lx ", table);
-#ifdef CONFIG_X86_UV
-		} else if (!efi_guidcmp(guid, UV_SYSTEM_TABLE_GUID)) {
-			efi.uv_systab = table;
-			pr_cont(" UVsystab=0x%lx ", table);
-#endif
-		} else if (!efi_guidcmp(guid, HCDP_TABLE_GUID)) {
-			efi.hcdp = table;
-			pr_cont(" HCDP=0x%lx ", table);
-		} else if (!efi_guidcmp(guid, UGA_IO_PROTOCOL_GUID)) {
-			efi.uga = table;
-			pr_cont(" UGA=0x%lx ", table);
-		}
-		tablep += sz;
-	}
-	pr_cont("\n");
-	early_iounmap(config_tables, efi.systab->nr_tables * sz);
-	return 0;
-}
-
 static int __init efi_runtime_init(void)
 {
 	efi_runtime_services_t *runtime;
@@ -745,7 +667,7 @@
 		efi.systab->hdr.revision >> 16,
 		efi.systab->hdr.revision & 0xffff, vendor);
 
-	if (efi_config_init(efi.systab->tables, efi.systab->nr_tables))
+	if (efi_config_init(arch_tables))
 		return;
 
 	set_bit(EFI_CONFIG_TABLES, &x86_efi_facility);
@@ -816,34 +738,6 @@
 	}
 }
 
-/*
- * We can't ioremap data in EFI boot services RAM, because we've already mapped
- * it as RAM.  So, look it up in the existing EFI memory map instead.  Only
- * callable after efi_enter_virtual_mode and before efi_free_boot_services.
- */
-void __iomem *efi_lookup_mapped_addr(u64 phys_addr)
-{
-	void *p;
-	if (WARN_ON(!memmap.map))
-		return NULL;
-	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
-		efi_memory_desc_t *md = p;
-		u64 size = md->num_pages << EFI_PAGE_SHIFT;
-		u64 end = md->phys_addr + size;
-		if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
-		    md->type != EFI_BOOT_SERVICES_CODE &&
-		    md->type != EFI_BOOT_SERVICES_DATA)
-			continue;
-		if (!md->virt_addr)
-			continue;
-		if (phys_addr >= md->phys_addr && phys_addr < end) {
-			phys_addr += md->virt_addr - md->phys_addr;
-			return (__force void __iomem *)(unsigned long)phys_addr;
-		}
-	}
-	return NULL;
-}
-
 void efi_memory_uc(u64 addr, unsigned long size)
 {
 	unsigned long page_shift = 1UL << EFI_PAGE_SHIFT;
diff --git a/arch/x86/platform/geode/alix.c b/arch/x86/platform/geode/alix.c
index 90e23e7..76b6632 100644
--- a/arch/x86/platform/geode/alix.c
+++ b/arch/x86/platform/geode/alix.c
@@ -98,7 +98,7 @@
 	.dev.platform_data = &alix_leds_data,
 };
 
-static struct __initdata platform_device *alix_devs[] = {
+static struct platform_device *alix_devs[] __initdata = {
 	&alix_buttons_dev,
 	&alix_leds_dev,
 };
diff --git a/arch/x86/platform/geode/geos.c b/arch/x86/platform/geode/geos.c
index c2e6d53..aa733fb 100644
--- a/arch/x86/platform/geode/geos.c
+++ b/arch/x86/platform/geode/geos.c
@@ -87,7 +87,7 @@
 	.dev.platform_data = &geos_leds_data,
 };
 
-static struct __initdata platform_device *geos_devs[] = {
+static struct platform_device *geos_devs[] __initdata = {
 	&geos_buttons_dev,
 	&geos_leds_dev,
 };
diff --git a/arch/x86/platform/geode/net5501.c b/arch/x86/platform/geode/net5501.c
index 646e3b5..927e38c 100644
--- a/arch/x86/platform/geode/net5501.c
+++ b/arch/x86/platform/geode/net5501.c
@@ -78,7 +78,7 @@
 	.dev.platform_data = &net5501_leds_data,
 };
 
-static struct __initdata platform_device *net5501_devs[] = {
+static struct platform_device *net5501_devs[] __initdata = {
 	&net5501_buttons_dev,
 	&net5501_leds_dev,
 };
diff --git a/arch/x86/platform/intel-mid/Makefile b/arch/x86/platform/intel-mid/Makefile
new file mode 100644
index 0000000..01cc29e
--- /dev/null
+++ b/arch/x86/platform/intel-mid/Makefile
@@ -0,0 +1,7 @@
+obj-$(CONFIG_X86_INTEL_MID) += intel-mid.o
+obj-$(CONFIG_X86_INTEL_MID) += intel_mid_vrtc.o
+obj-$(CONFIG_EARLY_PRINTK_INTEL_MID) += early_printk_intel_mid.o
+# SFI specific code
+ifdef CONFIG_X86_INTEL_MID
+obj-$(CONFIG_SFI) += sfi.o device_libs/
+endif
diff --git a/arch/x86/platform/intel-mid/device_libs/Makefile b/arch/x86/platform/intel-mid/device_libs/Makefile
new file mode 100644
index 0000000..097e7a7
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/Makefile
@@ -0,0 +1,22 @@
+# IPC Devices
+obj-y += platform_ipc.o
+obj-$(subst m,y,$(CONFIG_MFD_INTEL_MSIC)) += platform_msic.o
+obj-$(subst m,y,$(CONFIG_SND_MFLD_MACHINE)) += platform_msic_audio.o
+obj-$(subst m,y,$(CONFIG_GPIO_MSIC)) += platform_msic_gpio.o
+obj-$(subst m,y,$(CONFIG_MFD_INTEL_MSIC)) += platform_msic_ocd.o
+obj-$(subst m,y,$(CONFIG_MFD_INTEL_MSIC)) += platform_msic_battery.o
+obj-$(subst m,y,$(CONFIG_INTEL_MID_POWER_BUTTON)) += platform_msic_power_btn.o
+obj-$(subst m,y,$(CONFIG_GPIO_INTEL_PMIC)) += platform_pmic_gpio.o
+obj-$(subst m,y,$(CONFIG_INTEL_MFLD_THERMAL)) += platform_msic_thermal.o
+# I2C Devices
+obj-$(subst m,y,$(CONFIG_SENSORS_EMC1403)) += platform_emc1403.o
+obj-$(subst m,y,$(CONFIG_SENSORS_LIS3LV02D)) += platform_lis331.o
+obj-$(subst m,y,$(CONFIG_GPIO_PCA953X)) += platform_max7315.o
+obj-$(subst m,y,$(CONFIG_INPUT_MPU3050)) += platform_mpu3050.o
+obj-$(subst m,y,$(CONFIG_INPUT_BMA150)) += platform_bma023.o
+obj-$(subst m,y,$(CONFIG_GPIO_PCA953X)) += platform_tca6416.o
+obj-$(subst m,y,$(CONFIG_DRM_MEDFIELD)) += platform_tc35876x.o
+# SPI Devices
+obj-$(subst m,y,$(CONFIG_SERIAL_MRST_MAX3110)) += platform_max3111.o
+# MISC Devices
+obj-$(subst m,y,$(CONFIG_KEYBOARD_GPIO)) += platform_gpio_keys.o
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_bma023.c b/arch/x86/platform/intel-mid/device_libs/platform_bma023.c
new file mode 100644
index 0000000..0ae7f2a
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_bma023.c
@@ -0,0 +1,20 @@
+/*
+ * platform_bma023.c: bma023 platform data initilization file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <asm/intel-mid.h>
+
+static const struct devs_id bma023_dev_id __initconst = {
+	.name = "bma023",
+	.type = SFI_DEV_TYPE_I2C,
+	.delay = 1,
+};
+
+sfi_device(bma023_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_emc1403.c b/arch/x86/platform/intel-mid/device_libs/platform_emc1403.c
new file mode 100644
index 0000000..0d942c1
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_emc1403.c
@@ -0,0 +1,41 @@
+/*
+ * platform_emc1403.c: emc1403 platform data initilization file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <asm/intel-mid.h>
+
+static void __init *emc1403_platform_data(void *info)
+{
+	static short intr2nd_pdata;
+	struct i2c_board_info *i2c_info = info;
+	int intr = get_gpio_by_name("thermal_int");
+	int intr2nd = get_gpio_by_name("thermal_alert");
+
+	if (intr == -1 || intr2nd == -1)
+		return NULL;
+
+	i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
+	intr2nd_pdata = intr2nd + INTEL_MID_IRQ_OFFSET;
+
+	return &intr2nd_pdata;
+}
+
+static const struct devs_id emc1403_dev_id __initconst = {
+	.name = "emc1403",
+	.type = SFI_DEV_TYPE_I2C,
+	.delay = 1,
+	.get_platform_data = &emc1403_platform_data,
+};
+
+sfi_device(emc1403_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_gpio_keys.c b/arch/x86/platform/intel-mid/device_libs/platform_gpio_keys.c
new file mode 100644
index 0000000..a013a48
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_gpio_keys.c
@@ -0,0 +1,83 @@
+/*
+ * platform_gpio_keys.c: gpio_keys platform data initilization file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/input.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/platform_device.h>
+#include <asm/intel-mid.h>
+
+#define DEVICE_NAME "gpio-keys"
+
+/*
+ * we will search these buttons in SFI GPIO table (by name)
+ * and register them dynamically. Please add all possible
+ * buttons here, we will shrink them if no GPIO found.
+ */
+static struct gpio_keys_button gpio_button[] = {
+	{KEY_POWER,		-1, 1, "power_btn",	EV_KEY, 0, 3000},
+	{KEY_PROG1,		-1, 1, "prog_btn1",	EV_KEY, 0, 20},
+	{KEY_PROG2,		-1, 1, "prog_btn2",	EV_KEY, 0, 20},
+	{SW_LID,		-1, 1, "lid_switch",	EV_SW,  0, 20},
+	{KEY_VOLUMEUP,		-1, 1, "vol_up",	EV_KEY, 0, 20},
+	{KEY_VOLUMEDOWN,	-1, 1, "vol_down",	EV_KEY, 0, 20},
+	{KEY_CAMERA,		-1, 1, "camera_full",	EV_KEY, 0, 20},
+	{KEY_CAMERA_FOCUS,	-1, 1, "camera_half",	EV_KEY, 0, 20},
+	{SW_KEYPAD_SLIDE,	-1, 1, "MagSw1",	EV_SW,  0, 20},
+	{SW_KEYPAD_SLIDE,	-1, 1, "MagSw2",	EV_SW,  0, 20},
+};
+
+static struct gpio_keys_platform_data gpio_keys = {
+	.buttons	= gpio_button,
+	.rep		= 1,
+	.nbuttons	= -1, /* will fill it after search */
+};
+
+static struct platform_device pb_device = {
+	.name		= DEVICE_NAME,
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &gpio_keys,
+	},
+};
+
+/*
+ * Shrink the non-existent buttons, register the gpio button
+ * device if there is some
+ */
+static int __init pb_keys_init(void)
+{
+	struct gpio_keys_button *gb = gpio_button;
+	int i, num, good = 0;
+
+	num = sizeof(gpio_button) / sizeof(struct gpio_keys_button);
+	for (i = 0; i < num; i++) {
+		gb[i].gpio = get_gpio_by_name(gb[i].desc);
+		pr_debug("info[%2d]: name = %s, gpio = %d\n", i, gb[i].desc,
+					gb[i].gpio);
+		if (gb[i].gpio == -1)
+			continue;
+
+		if (i != good)
+			gb[good] = gb[i];
+		good++;
+	}
+
+	if (good) {
+		gpio_keys.nbuttons = good;
+		return platform_device_register(&pb_device);
+	}
+	return 0;
+}
+late_initcall(pb_keys_init);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_ipc.c b/arch/x86/platform/intel-mid/device_libs/platform_ipc.c
new file mode 100644
index 0000000..a84b73d
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_ipc.c
@@ -0,0 +1,68 @@
+/*
+ * platform_ipc.c: IPC platform library file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/sfi.h>
+#include <linux/gpio.h>
+#include <asm/intel-mid.h>
+#include "platform_ipc.h"
+
+void __init ipc_device_handler(struct sfi_device_table_entry *pentry,
+				struct devs_id *dev)
+{
+	struct platform_device *pdev;
+	void *pdata = NULL;
+	static struct resource res __initdata = {
+		.name = "IRQ",
+		.flags = IORESOURCE_IRQ,
+	};
+
+	pr_debug("IPC bus, name = %16.16s, irq = 0x%2x\n",
+		pentry->name, pentry->irq);
+
+	/*
+	 * We need to call platform init of IPC devices to fill misc_pdata
+	 * structure. It will be used in msic_init for initialization.
+	 */
+	if (dev != NULL)
+		pdata = dev->get_platform_data(pentry);
+
+	/*
+	 * On Medfield the platform device creation is handled by the MSIC
+	 * MFD driver so we don't need to do it here.
+	 */
+	if (intel_mid_has_msic())
+		return;
+
+	pdev = platform_device_alloc(pentry->name, 0);
+	if (pdev == NULL) {
+		pr_err("out of memory for SFI platform device '%s'.\n",
+			pentry->name);
+		return;
+	}
+	res.start = pentry->irq;
+	platform_device_add_resources(pdev, &res, 1);
+
+	pdev->dev.platform_data = pdata;
+	intel_scu_device_register(pdev);
+}
+
+static const struct devs_id pmic_audio_dev_id __initconst = {
+	.name = "pmic_audio",
+	.type = SFI_DEV_TYPE_IPC,
+	.delay = 1,
+	.device_handler = &ipc_device_handler,
+};
+
+sfi_device(pmic_audio_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_ipc.h b/arch/x86/platform/intel-mid/device_libs/platform_ipc.h
new file mode 100644
index 0000000..8f568dd
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_ipc.h
@@ -0,0 +1,17 @@
+/*
+ * platform_ipc.h: IPC platform library header file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+#ifndef _PLATFORM_IPC_H_
+#define _PLATFORM_IPC_H_
+
+extern void __init ipc_device_handler(struct sfi_device_table_entry *pentry,
+			struct devs_id *dev) __attribute__((weak));
+#endif
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_lis331.c b/arch/x86/platform/intel-mid/device_libs/platform_lis331.c
new file mode 100644
index 0000000..15278c1
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_lis331.c
@@ -0,0 +1,39 @@
+/*
+ * platform_lis331.c:  lis331 platform data initilization file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <asm/intel-mid.h>
+
+static void __init *lis331dl_platform_data(void *info)
+{
+	static short intr2nd_pdata;
+	struct i2c_board_info *i2c_info = info;
+	int intr = get_gpio_by_name("accel_int");
+	int intr2nd = get_gpio_by_name("accel_2");
+
+	if (intr == -1 || intr2nd == -1)
+		return NULL;
+
+	i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
+	intr2nd_pdata = intr2nd + INTEL_MID_IRQ_OFFSET;
+
+	return &intr2nd_pdata;
+}
+
+static const struct devs_id lis331dl_dev_id __initconst = {
+	.name = "i2c_accel",
+	.type = SFI_DEV_TYPE_I2C,
+	.get_platform_data = &lis331dl_platform_data,
+};
+
+sfi_device(lis331dl_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_max3111.c b/arch/x86/platform/intel-mid/device_libs/platform_max3111.c
new file mode 100644
index 0000000..afd1df9
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_max3111.c
@@ -0,0 +1,35 @@
+/*
+ * platform_max3111.c: max3111 platform data initilization file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <asm/intel-mid.h>
+
+static void __init *max3111_platform_data(void *info)
+{
+	struct spi_board_info *spi_info = info;
+	int intr = get_gpio_by_name("max3111_int");
+
+	spi_info->mode = SPI_MODE_0;
+	if (intr == -1)
+		return NULL;
+	spi_info->irq = intr + INTEL_MID_IRQ_OFFSET;
+	return NULL;
+}
+
+static const struct devs_id max3111_dev_id __initconst = {
+	.name = "spi_max3111",
+	.type = SFI_DEV_TYPE_SPI,
+	.get_platform_data = &max3111_platform_data,
+};
+
+sfi_device(max3111_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_max7315.c b/arch/x86/platform/intel-mid/device_libs/platform_max7315.c
new file mode 100644
index 0000000..94ade10
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_max7315.c
@@ -0,0 +1,79 @@
+/*
+ * platform_max7315.c: max7315 platform data initilization file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/platform_data/pca953x.h>
+#include <asm/intel-mid.h>
+
+#define MAX7315_NUM 2
+
+static void __init *max7315_platform_data(void *info)
+{
+	static struct pca953x_platform_data max7315_pdata[MAX7315_NUM];
+	static int nr;
+	struct pca953x_platform_data *max7315 = &max7315_pdata[nr];
+	struct i2c_board_info *i2c_info = info;
+	int gpio_base, intr;
+	char base_pin_name[SFI_NAME_LEN + 1];
+	char intr_pin_name[SFI_NAME_LEN + 1];
+
+	if (nr == MAX7315_NUM) {
+		pr_err("too many max7315s, we only support %d\n",
+				MAX7315_NUM);
+		return NULL;
+	}
+	/* we have several max7315 on the board, we only need load several
+	 * instances of the same pca953x driver to cover them
+	 */
+	strcpy(i2c_info->type, "max7315");
+	if (nr++) {
+		sprintf(base_pin_name, "max7315_%d_base", nr);
+		sprintf(intr_pin_name, "max7315_%d_int", nr);
+	} else {
+		strcpy(base_pin_name, "max7315_base");
+		strcpy(intr_pin_name, "max7315_int");
+	}
+
+	gpio_base = get_gpio_by_name(base_pin_name);
+	intr = get_gpio_by_name(intr_pin_name);
+
+	if (gpio_base == -1)
+		return NULL;
+	max7315->gpio_base = gpio_base;
+	if (intr != -1) {
+		i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
+		max7315->irq_base = gpio_base + INTEL_MID_IRQ_OFFSET;
+	} else {
+		i2c_info->irq = -1;
+		max7315->irq_base = -1;
+	}
+	return max7315;
+}
+
+static const struct devs_id max7315_dev_id __initconst = {
+	.name = "i2c_max7315",
+	.type = SFI_DEV_TYPE_I2C,
+	.delay = 1,
+	.get_platform_data = &max7315_platform_data,
+};
+
+static const struct devs_id max7315_2_dev_id __initconst = {
+	.name = "i2c_max7315_2",
+	.type = SFI_DEV_TYPE_I2C,
+	.delay = 1,
+	.get_platform_data = &max7315_platform_data,
+};
+
+sfi_device(max7315_dev_id);
+sfi_device(max7315_2_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_mpu3050.c b/arch/x86/platform/intel-mid/device_libs/platform_mpu3050.c
new file mode 100644
index 0000000..dd28d63
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_mpu3050.c
@@ -0,0 +1,36 @@
+/*
+ * platform_mpu3050.c: mpu3050 platform data initilization file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <asm/intel-mid.h>
+
+static void *mpu3050_platform_data(void *info)
+{
+	struct i2c_board_info *i2c_info = info;
+	int intr = get_gpio_by_name("mpu3050_int");
+
+	if (intr == -1)
+		return NULL;
+
+	i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
+	return NULL;
+}
+
+static const struct devs_id mpu3050_dev_id __initconst = {
+	.name = "mpu3050",
+	.type = SFI_DEV_TYPE_I2C,
+	.delay = 1,
+	.get_platform_data = &mpu3050_platform_data,
+};
+
+sfi_device(mpu3050_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic.c b/arch/x86/platform/intel-mid/device_libs/platform_msic.c
new file mode 100644
index 0000000..9f4a775
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_msic.c
@@ -0,0 +1,87 @@
+/*
+ * platform_msic.c: MSIC platform data initilization file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/scatterlist.h>
+#include <linux/init.h>
+#include <linux/sfi.h>
+#include <linux/mfd/intel_msic.h>
+#include <asm/intel_scu_ipc.h>
+#include <asm/intel-mid.h>
+#include "platform_msic.h"
+
+struct intel_msic_platform_data msic_pdata;
+
+static struct resource msic_resources[] = {
+	{
+		.start	= INTEL_MSIC_IRQ_PHYS_BASE,
+		.end	= INTEL_MSIC_IRQ_PHYS_BASE + 64 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device msic_device = {
+	.name		= "intel_msic",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &msic_pdata,
+	},
+	.num_resources	= ARRAY_SIZE(msic_resources),
+	.resource	= msic_resources,
+};
+
+static int msic_scu_status_change(struct notifier_block *nb,
+				  unsigned long code, void *data)
+{
+	if (code == SCU_DOWN) {
+		platform_device_unregister(&msic_device);
+		return 0;
+	}
+
+	return platform_device_register(&msic_device);
+}
+
+static int __init msic_init(void)
+{
+	static struct notifier_block msic_scu_notifier = {
+		.notifier_call	= msic_scu_status_change,
+	};
+
+	/*
+	 * We need to be sure that the SCU IPC is ready before MSIC device
+	 * can be registered.
+	 */
+	if (intel_mid_has_msic())
+		intel_scu_notifier_add(&msic_scu_notifier);
+
+	return 0;
+}
+arch_initcall(msic_init);
+
+/*
+ * msic_generic_platform_data - sets generic platform data for the block
+ * @info: pointer to the SFI device table entry for this block
+ * @block: MSIC block
+ *
+ * Function sets IRQ number from the SFI table entry for given device to
+ * the MSIC platform data.
+ */
+void *msic_generic_platform_data(void *info, enum intel_msic_block block)
+{
+	struct sfi_device_table_entry *entry = info;
+
+	BUG_ON(block < 0 || block >= INTEL_MSIC_BLOCK_LAST);
+	msic_pdata.irq[block] = entry->irq;
+
+	return NULL;
+}
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic.h b/arch/x86/platform/intel-mid/device_libs/platform_msic.h
new file mode 100644
index 0000000..917eb56
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_msic.h
@@ -0,0 +1,19 @@
+/*
+ * platform_msic.h: MSIC platform data header file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+#ifndef _PLATFORM_MSIC_H_
+#define _PLATFORM_MSIC_H_
+
+extern struct intel_msic_platform_data msic_pdata;
+
+extern void *msic_generic_platform_data(void *info,
+			enum intel_msic_block block) __attribute__((weak));
+#endif
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic_audio.c b/arch/x86/platform/intel-mid/device_libs/platform_msic_audio.c
new file mode 100644
index 0000000..2962939
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_msic_audio.c
@@ -0,0 +1,47 @@
+/*
+ * platform_msic_audio.c: MSIC audio platform data initilization file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/scatterlist.h>
+#include <linux/init.h>
+#include <linux/sfi.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/intel_msic.h>
+#include <asm/intel-mid.h>
+
+#include "platform_msic.h"
+#include "platform_ipc.h"
+
+static void *msic_audio_platform_data(void *info)
+{
+	struct platform_device *pdev;
+
+	pdev = platform_device_register_simple("sst-platform", -1, NULL, 0);
+
+	if (IS_ERR(pdev)) {
+		pr_err("failed to create audio platform device\n");
+		return NULL;
+	}
+
+	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_AUDIO);
+}
+
+static const struct devs_id msic_audio_dev_id __initconst = {
+	.name = "msic_audio",
+	.type = SFI_DEV_TYPE_IPC,
+	.delay = 1,
+	.get_platform_data = &msic_audio_platform_data,
+	.device_handler = &ipc_device_handler,
+};
+
+sfi_device(msic_audio_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic_battery.c b/arch/x86/platform/intel-mid/device_libs/platform_msic_battery.c
new file mode 100644
index 0000000..f446c33
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_msic_battery.c
@@ -0,0 +1,37 @@
+/*
+ * platform_msic_battery.c: MSIC battery platform data initilization file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/scatterlist.h>
+#include <linux/init.h>
+#include <linux/sfi.h>
+#include <linux/mfd/intel_msic.h>
+#include <asm/intel-mid.h>
+
+#include "platform_msic.h"
+#include "platform_ipc.h"
+
+static void __init *msic_battery_platform_data(void *info)
+{
+	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_BATTERY);
+}
+
+static const struct devs_id msic_battery_dev_id __initconst = {
+	.name = "msic_battery",
+	.type = SFI_DEV_TYPE_IPC,
+	.delay = 1,
+	.get_platform_data = &msic_battery_platform_data,
+	.device_handler = &ipc_device_handler,
+};
+
+sfi_device(msic_battery_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic_gpio.c b/arch/x86/platform/intel-mid/device_libs/platform_msic_gpio.c
new file mode 100644
index 0000000..2a4f7b1
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_msic_gpio.c
@@ -0,0 +1,48 @@
+/*
+ * platform_msic_gpio.c: MSIC GPIO platform data initilization file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/scatterlist.h>
+#include <linux/sfi.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/mfd/intel_msic.h>
+#include <asm/intel-mid.h>
+
+#include "platform_msic.h"
+#include "platform_ipc.h"
+
+static void __init *msic_gpio_platform_data(void *info)
+{
+	static struct intel_msic_gpio_pdata msic_gpio_pdata;
+
+	int gpio = get_gpio_by_name("msic_gpio_base");
+
+	if (gpio < 0)
+		return NULL;
+
+	msic_gpio_pdata.gpio_base = gpio;
+	msic_pdata.gpio = &msic_gpio_pdata;
+
+	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_GPIO);
+}
+
+static const struct devs_id msic_gpio_dev_id __initconst = {
+	.name = "msic_gpio",
+	.type = SFI_DEV_TYPE_IPC,
+	.delay = 1,
+	.get_platform_data = &msic_gpio_platform_data,
+	.device_handler = &ipc_device_handler,
+};
+
+sfi_device(msic_gpio_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic_ocd.c b/arch/x86/platform/intel-mid/device_libs/platform_msic_ocd.c
new file mode 100644
index 0000000..6497111
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_msic_ocd.c
@@ -0,0 +1,49 @@
+/*
+ * platform_msic_ocd.c: MSIC OCD platform data initilization file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/scatterlist.h>
+#include <linux/sfi.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/mfd/intel_msic.h>
+#include <asm/intel-mid.h>
+
+#include "platform_msic.h"
+#include "platform_ipc.h"
+
+static void __init *msic_ocd_platform_data(void *info)
+{
+	static struct intel_msic_ocd_pdata msic_ocd_pdata;
+	int gpio;
+
+	gpio = get_gpio_by_name("ocd_gpio");
+
+	if (gpio < 0)
+		return NULL;
+
+	msic_ocd_pdata.gpio = gpio;
+	msic_pdata.ocd = &msic_ocd_pdata;
+
+	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_OCD);
+}
+
+static const struct devs_id msic_ocd_dev_id __initconst = {
+	.name = "msic_ocd",
+	.type = SFI_DEV_TYPE_IPC,
+	.delay = 1,
+	.get_platform_data = &msic_ocd_platform_data,
+	.device_handler = &ipc_device_handler,
+};
+
+sfi_device(msic_ocd_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic_power_btn.c b/arch/x86/platform/intel-mid/device_libs/platform_msic_power_btn.c
new file mode 100644
index 0000000..83a3459
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_msic_power_btn.c
@@ -0,0 +1,36 @@
+/*
+ * platform_msic_power_btn.c: MSIC power btn platform data initilization file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/scatterlist.h>
+#include <linux/sfi.h>
+#include <linux/init.h>
+#include <linux/mfd/intel_msic.h>
+#include <asm/intel-mid.h>
+
+#include "platform_msic.h"
+#include "platform_ipc.h"
+
+static void __init *msic_power_btn_platform_data(void *info)
+{
+	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_POWER_BTN);
+}
+
+static const struct devs_id msic_power_btn_dev_id __initconst = {
+	.name = "msic_power_btn",
+	.type = SFI_DEV_TYPE_IPC,
+	.delay = 1,
+	.get_platform_data = &msic_power_btn_platform_data,
+	.device_handler = &ipc_device_handler,
+};
+
+sfi_device(msic_power_btn_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic_thermal.c b/arch/x86/platform/intel-mid/device_libs/platform_msic_thermal.c
new file mode 100644
index 0000000..a351878
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_msic_thermal.c
@@ -0,0 +1,37 @@
+/*
+ * platform_msic_thermal.c: msic_thermal platform data initilization file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/input.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/intel_msic.h>
+#include <asm/intel-mid.h>
+
+#include "platform_msic.h"
+#include "platform_ipc.h"
+
+static void __init *msic_thermal_platform_data(void *info)
+{
+	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_THERMAL);
+}
+
+static const struct devs_id msic_thermal_dev_id __initconst = {
+	.name = "msic_thermal",
+	.type = SFI_DEV_TYPE_IPC,
+	.delay = 1,
+	.get_platform_data = &msic_thermal_platform_data,
+	.device_handler = &ipc_device_handler,
+};
+
+sfi_device(msic_thermal_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_pmic_gpio.c b/arch/x86/platform/intel-mid/device_libs/platform_pmic_gpio.c
new file mode 100644
index 0000000..d87182a
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_pmic_gpio.c
@@ -0,0 +1,54 @@
+/*
+ * platform_pmic_gpio.c: PMIC GPIO platform data initilization file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/scatterlist.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/sfi.h>
+#include <linux/intel_pmic_gpio.h>
+#include <asm/intel-mid.h>
+
+#include "platform_ipc.h"
+
+static void __init *pmic_gpio_platform_data(void *info)
+{
+	static struct intel_pmic_gpio_platform_data pmic_gpio_pdata;
+	int gpio_base = get_gpio_by_name("pmic_gpio_base");
+
+	if (gpio_base == -1)
+		gpio_base = 64;
+	pmic_gpio_pdata.gpio_base = gpio_base;
+	pmic_gpio_pdata.irq_base = gpio_base + INTEL_MID_IRQ_OFFSET;
+	pmic_gpio_pdata.gpiointr = 0xffffeff8;
+
+	return &pmic_gpio_pdata;
+}
+
+static const struct devs_id pmic_gpio_spi_dev_id __initconst = {
+	.name = "pmic_gpio",
+	.type = SFI_DEV_TYPE_SPI,
+	.delay = 1,
+	.get_platform_data = &pmic_gpio_platform_data,
+};
+
+static const struct devs_id pmic_gpio_ipc_dev_id __initconst = {
+	.name = "pmic_gpio",
+	.type = SFI_DEV_TYPE_IPC,
+	.delay = 1,
+	.get_platform_data = &pmic_gpio_platform_data,
+	.device_handler = &ipc_device_handler
+};
+
+sfi_device(pmic_gpio_spi_dev_id);
+sfi_device(pmic_gpio_ipc_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c b/arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c
new file mode 100644
index 0000000..740fc75
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c
@@ -0,0 +1,36 @@
+/*
+ * platform_tc35876x.c: tc35876x platform data initilization file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/gpio.h>
+#include <linux/i2c/tc35876x.h>
+#include <asm/intel-mid.h>
+
+/*tc35876x DSI_LVDS bridge chip and panel platform data*/
+static void *tc35876x_platform_data(void *data)
+{
+	static struct tc35876x_platform_data pdata;
+
+	/* gpio pins set to -1 will not be used by the driver */
+	pdata.gpio_bridge_reset = get_gpio_by_name("LCMB_RXEN");
+	pdata.gpio_panel_bl_en = get_gpio_by_name("6S6P_BL_EN");
+	pdata.gpio_panel_vadd = get_gpio_by_name("EN_VREG_LCD_V3P3");
+
+	return &pdata;
+}
+
+static const struct devs_id tc35876x_dev_id __initconst = {
+	.name = "i2c_disp_brig",
+	.type = SFI_DEV_TYPE_I2C,
+	.get_platform_data = &tc35876x_platform_data,
+};
+
+sfi_device(tc35876x_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_tca6416.c b/arch/x86/platform/intel-mid/device_libs/platform_tca6416.c
new file mode 100644
index 0000000..22881c9
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_tca6416.c
@@ -0,0 +1,57 @@
+/*
+ * platform_tca6416.c: tca6416 platform data initilization file
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/platform_data/pca953x.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <asm/intel-mid.h>
+
+#define TCA6416_NAME	"tca6416"
+#define TCA6416_BASE	"tca6416_base"
+#define TCA6416_INTR	"tca6416_int"
+
+static void *tca6416_platform_data(void *info)
+{
+	static struct pca953x_platform_data tca6416;
+	struct i2c_board_info *i2c_info = info;
+	int gpio_base, intr;
+	char base_pin_name[SFI_NAME_LEN + 1];
+	char intr_pin_name[SFI_NAME_LEN + 1];
+
+	strcpy(i2c_info->type, TCA6416_NAME);
+	strcpy(base_pin_name, TCA6416_BASE);
+	strcpy(intr_pin_name, TCA6416_INTR);
+
+	gpio_base = get_gpio_by_name(base_pin_name);
+	intr = get_gpio_by_name(intr_pin_name);
+
+	if (gpio_base == -1)
+		return NULL;
+	tca6416.gpio_base = gpio_base;
+	if (intr != -1) {
+		i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
+		tca6416.irq_base = gpio_base + INTEL_MID_IRQ_OFFSET;
+	} else {
+		i2c_info->irq = -1;
+		tca6416.irq_base = -1;
+	}
+	return &tca6416;
+}
+
+static const struct devs_id tca6416_dev_id __initconst = {
+	.name = "tca6416",
+	.type = SFI_DEV_TYPE_I2C,
+	.delay = 1,
+	.get_platform_data = &tca6416_platform_data,
+};
+
+sfi_device(tca6416_dev_id);
diff --git a/arch/x86/platform/mrst/early_printk_mrst.c b/arch/x86/platform/intel-mid/early_printk_intel_mid.c
similarity index 96%
rename from arch/x86/platform/mrst/early_printk_mrst.c
rename to arch/x86/platform/intel-mid/early_printk_intel_mid.c
index 028454f..4f702f5 100644
--- a/arch/x86/platform/mrst/early_printk_mrst.c
+++ b/arch/x86/platform/intel-mid/early_printk_intel_mid.c
@@ -1,5 +1,5 @@
 /*
- * early_printk_mrst.c - early consoles for Intel MID platforms
+ * early_printk_intel_mid.c - early consoles for Intel MID platforms
  *
  * Copyright (c) 2008-2010, Intel Corporation
  *
@@ -27,7 +27,7 @@
 
 #include <asm/fixmap.h>
 #include <asm/pgtable.h>
-#include <asm/mrst.h>
+#include <asm/intel-mid.h>
 
 #define MRST_SPI_TIMEOUT		0x200000
 #define MRST_REGBASE_SPI0		0xff128000
@@ -152,7 +152,7 @@
 	spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9;
 	freq = 100000000 / (spi0_cdiv + 1);
 
-	if (mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL)
+	if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_PENWELL)
 		mrst_spi_paddr = MRST_REGBASE_SPI1;
 
 	pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
@@ -213,13 +213,14 @@
 	}
 
 	if (!timeout)
-		pr_warning("MRST earlycon: timed out\n");
+		pr_warn("MRST earlycon: timed out\n");
 	else
 		max3110_write_data(c);
 }
 
 /* Early SPI only uses polling mode */
-static void early_mrst_spi_write(struct console *con, const char *str, unsigned n)
+static void early_mrst_spi_write(struct console *con, const char *str,
+					unsigned n)
 {
 	int i;
 
diff --git a/arch/x86/platform/intel-mid/intel-mid.c b/arch/x86/platform/intel-mid/intel-mid.c
new file mode 100644
index 0000000..f90e290
--- /dev/null
+++ b/arch/x86/platform/intel-mid/intel-mid.c
@@ -0,0 +1,213 @@
+/*
+ * intel-mid.c: Intel MID platform setup code
+ *
+ * (C) Copyright 2008, 2012 Intel Corporation
+ * Author: Jacob Pan (jacob.jun.pan@intel.com)
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#define pr_fmt(fmt) "intel_mid: " fmt
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/scatterlist.h>
+#include <linux/sfi.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+
+#include <asm/setup.h>
+#include <asm/mpspec_def.h>
+#include <asm/hw_irq.h>
+#include <asm/apic.h>
+#include <asm/io_apic.h>
+#include <asm/intel-mid.h>
+#include <asm/intel_mid_vrtc.h>
+#include <asm/io.h>
+#include <asm/i8259.h>
+#include <asm/intel_scu_ipc.h>
+#include <asm/apb_timer.h>
+#include <asm/reboot.h>
+
+/*
+ * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock,
+ * cmdline option x86_intel_mid_timer can be used to override the configuration
+ * to prefer one or the other.
+ * at runtime, there are basically three timer configurations:
+ * 1. per cpu apbt clock only
+ * 2. per cpu always-on lapic clocks only, this is Penwell/Medfield only
+ * 3. per cpu lapic clock (C3STOP) and one apbt clock, with broadcast.
+ *
+ * by default (without cmdline option), platform code first detects cpu type
+ * to see if we are on lincroft or penwell, then set up both lapic or apbt
+ * clocks accordingly.
+ * i.e. by default, medfield uses configuration #2, moorestown uses #1.
+ * config #3 is supported but not recommended on medfield.
+ *
+ * rating and feature summary:
+ * lapic (with C3STOP) --------- 100
+ * apbt (always-on) ------------ 110
+ * lapic (always-on,ARAT) ------ 150
+ */
+
+enum intel_mid_timer_options intel_mid_timer_options;
+
+enum intel_mid_cpu_type __intel_mid_cpu_chip;
+EXPORT_SYMBOL_GPL(__intel_mid_cpu_chip);
+
+static void intel_mid_power_off(void)
+{
+}
+
+static void intel_mid_reboot(void)
+{
+	intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0);
+}
+
+static unsigned long __init intel_mid_calibrate_tsc(void)
+{
+	unsigned long fast_calibrate;
+	u32 lo, hi, ratio, fsb;
+
+	rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+	pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi);
+	ratio = (hi >> 8) & 0x1f;
+	pr_debug("ratio is %d\n", ratio);
+	if (!ratio) {
+		pr_err("read a zero ratio, should be incorrect!\n");
+		pr_err("force tsc ratio to 16 ...\n");
+		ratio = 16;
+	}
+	rdmsr(MSR_FSB_FREQ, lo, hi);
+	if ((lo & 0x7) == 0x7)
+		fsb = PENWELL_FSB_FREQ_83SKU;
+	else
+		fsb = PENWELL_FSB_FREQ_100SKU;
+	fast_calibrate = ratio * fsb;
+	pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
+	lapic_timer_frequency = fsb * 1000 / HZ;
+	/* mark tsc clocksource as reliable */
+	set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
+
+	if (fast_calibrate)
+		return fast_calibrate;
+
+	return 0;
+}
+
+static void __init intel_mid_time_init(void)
+{
+	sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr);
+	switch (intel_mid_timer_options) {
+	case INTEL_MID_TIMER_APBT_ONLY:
+		break;
+	case INTEL_MID_TIMER_LAPIC_APBT:
+		x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock;
+		x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock;
+		break;
+	default:
+		if (!boot_cpu_has(X86_FEATURE_ARAT))
+			break;
+		x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock;
+		x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock;
+		return;
+	}
+	/* we need at least one APB timer */
+	pre_init_apic_IRQ0();
+	apbt_time_init();
+}
+
+static void intel_mid_arch_setup(void)
+{
+	if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27)
+		__intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_PENWELL;
+	else {
+		pr_err("Unknown Intel MID CPU (%d:%d), default to Penwell\n",
+			boot_cpu_data.x86, boot_cpu_data.x86_model);
+		__intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_PENWELL;
+	}
+}
+
+/* MID systems don't have i8042 controller */
+static int intel_mid_i8042_detect(void)
+{
+	return 0;
+}
+
+/*
+ * Moorestown does not have external NMI source nor port 0x61 to report
+ * NMI status. The possible NMI sources are from pmu as a result of NMI
+ * watchdog or lock debug. Reading io port 0x61 results in 0xff which
+ * misled NMI handler.
+ */
+static unsigned char intel_mid_get_nmi_reason(void)
+{
+	return 0;
+}
+
+/*
+ * Moorestown specific x86_init function overrides and early setup
+ * calls.
+ */
+void __init x86_intel_mid_early_setup(void)
+{
+	x86_init.resources.probe_roms = x86_init_noop;
+	x86_init.resources.reserve_resources = x86_init_noop;
+
+	x86_init.timers.timer_init = intel_mid_time_init;
+	x86_init.timers.setup_percpu_clockev = x86_init_noop;
+
+	x86_init.irqs.pre_vector_init = x86_init_noop;
+
+	x86_init.oem.arch_setup = intel_mid_arch_setup;
+
+	x86_cpuinit.setup_percpu_clockev = apbt_setup_secondary_clock;
+
+	x86_platform.calibrate_tsc = intel_mid_calibrate_tsc;
+	x86_platform.i8042_detect = intel_mid_i8042_detect;
+	x86_init.timers.wallclock_init = intel_mid_rtc_init;
+	x86_platform.get_nmi_reason = intel_mid_get_nmi_reason;
+
+	x86_init.pci.init = intel_mid_pci_init;
+	x86_init.pci.fixup_irqs = x86_init_noop;
+
+	legacy_pic = &null_legacy_pic;
+
+	pm_power_off = intel_mid_power_off;
+	machine_ops.emergency_restart  = intel_mid_reboot;
+
+	/* Avoid searching for BIOS MP tables */
+	x86_init.mpparse.find_smp_config = x86_init_noop;
+	x86_init.mpparse.get_smp_config = x86_init_uint_noop;
+	set_bit(MP_BUS_ISA, mp_bus_not_pci);
+}
+
+/*
+ * if user does not want to use per CPU apb timer, just give it a lower rating
+ * than local apic timer and skip the late per cpu timer init.
+ */
+static inline int __init setup_x86_intel_mid_timer(char *arg)
+{
+	if (!arg)
+		return -EINVAL;
+
+	if (strcmp("apbt_only", arg) == 0)
+		intel_mid_timer_options = INTEL_MID_TIMER_APBT_ONLY;
+	else if (strcmp("lapic_and_apbt", arg) == 0)
+		intel_mid_timer_options = INTEL_MID_TIMER_LAPIC_APBT;
+	else {
+		pr_warn("X86 INTEL_MID timer option %s not recognised"
+			   " use x86_intel_mid_timer=apbt_only or lapic_and_apbt\n",
+			   arg);
+		return -EINVAL;
+	}
+	return 0;
+}
+__setup("x86_intel_mid_timer=", setup_x86_intel_mid_timer);
+
diff --git a/arch/x86/platform/mrst/vrtc.c b/arch/x86/platform/intel-mid/intel_mid_vrtc.c
similarity index 90%
rename from arch/x86/platform/mrst/vrtc.c
rename to arch/x86/platform/intel-mid/intel_mid_vrtc.c
index 5e355b1..4762cff 100644
--- a/arch/x86/platform/mrst/vrtc.c
+++ b/arch/x86/platform/intel-mid/intel_mid_vrtc.c
@@ -1,5 +1,5 @@
 /*
- * vrtc.c: Driver for virtual RTC device on Intel MID platform
+ * intel_mid_vrtc.c: Driver for virtual RTC device on Intel MID platform
  *
  * (C) Copyright 2009 Intel Corporation
  *
@@ -23,8 +23,8 @@
 #include <linux/sfi.h>
 #include <linux/platform_device.h>
 
-#include <asm/mrst.h>
-#include <asm/mrst-vrtc.h>
+#include <asm/intel-mid.h>
+#include <asm/intel_mid_vrtc.h>
 #include <asm/time.h>
 #include <asm/fixmap.h>
 
@@ -79,7 +79,7 @@
 	/* vRTC YEAR reg contains the offset to 1972 */
 	year += 1972;
 
-	printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d "
+	pr_info("vRTC: sec: %d min: %d hour: %d day: %d "
 		"mon: %d year: %d\n", sec, min, hour, mday, mon, year);
 
 	now->tv_sec = mktime(year, mon, mday, hour, min, sec);
@@ -109,15 +109,14 @@
 		vrtc_cmos_write(tm.tm_sec, RTC_SECONDS);
 		spin_unlock_irqrestore(&rtc_lock, flags);
 	} else {
-		printk(KERN_ERR
-		       "%s: Invalid vRTC value: write of %lx to vRTC failed\n",
+		pr_err("%s: Invalid vRTC value: write of %lx to vRTC failed\n",
 			__FUNCTION__, now->tv_sec);
 		retval = -EINVAL;
 	}
 	return retval;
 }
 
-void __init mrst_rtc_init(void)
+void __init intel_mid_rtc_init(void)
 {
 	unsigned long vrtc_paddr;
 
@@ -155,10 +154,10 @@
 };
 
 /* Register the RTC device if appropriate */
-static int __init mrst_device_create(void)
+static int __init intel_mid_device_create(void)
 {
 	/* No Moorestown, no device */
-	if (!mrst_identify_cpu())
+	if (!intel_mid_identify_cpu())
 		return -ENODEV;
 	/* No timer, no device */
 	if (!sfi_mrtc_num)
@@ -175,4 +174,4 @@
 	return platform_device_register(&vrtc_device);
 }
 
-module_init(mrst_device_create);
+module_init(intel_mid_device_create);
diff --git a/arch/x86/platform/intel-mid/sfi.c b/arch/x86/platform/intel-mid/sfi.c
new file mode 100644
index 0000000..c84c1ca
--- /dev/null
+++ b/arch/x86/platform/intel-mid/sfi.c
@@ -0,0 +1,488 @@
+/*
+ * intel_mid_sfi.c: Intel MID SFI initialization code
+ *
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/scatterlist.h>
+#include <linux/sfi.h>
+#include <linux/intel_pmic_gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/skbuff.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/mmc/core.h>
+#include <linux/mmc/card.h>
+#include <linux/blkdev.h>
+
+#include <asm/setup.h>
+#include <asm/mpspec_def.h>
+#include <asm/hw_irq.h>
+#include <asm/apic.h>
+#include <asm/io_apic.h>
+#include <asm/intel-mid.h>
+#include <asm/intel_mid_vrtc.h>
+#include <asm/io.h>
+#include <asm/i8259.h>
+#include <asm/intel_scu_ipc.h>
+#include <asm/apb_timer.h>
+#include <asm/reboot.h>
+
+#define	SFI_SIG_OEM0	"OEM0"
+#define MAX_IPCDEVS	24
+#define MAX_SCU_SPI	24
+#define MAX_SCU_I2C	24
+
+static struct platform_device *ipc_devs[MAX_IPCDEVS];
+static struct spi_board_info *spi_devs[MAX_SCU_SPI];
+static struct i2c_board_info *i2c_devs[MAX_SCU_I2C];
+static struct sfi_gpio_table_entry *gpio_table;
+static struct sfi_timer_table_entry sfi_mtimer_array[SFI_MTMR_MAX_NUM];
+static int ipc_next_dev;
+static int spi_next_dev;
+static int i2c_next_dev;
+static int i2c_bus[MAX_SCU_I2C];
+static int gpio_num_entry;
+static u32 sfi_mtimer_usage[SFI_MTMR_MAX_NUM];
+int sfi_mrtc_num;
+int sfi_mtimer_num;
+
+struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX];
+EXPORT_SYMBOL_GPL(sfi_mrtc_array);
+
+struct blocking_notifier_head intel_scu_notifier =
+			BLOCKING_NOTIFIER_INIT(intel_scu_notifier);
+EXPORT_SYMBOL_GPL(intel_scu_notifier);
+
+#define intel_mid_sfi_get_pdata(dev, priv)	\
+	((dev)->get_platform_data ? (dev)->get_platform_data(priv) : NULL)
+
+/* parse all the mtimer info to a static mtimer array */
+int __init sfi_parse_mtmr(struct sfi_table_header *table)
+{
+	struct sfi_table_simple *sb;
+	struct sfi_timer_table_entry *pentry;
+	struct mpc_intsrc mp_irq;
+	int totallen;
+
+	sb = (struct sfi_table_simple *)table;
+	if (!sfi_mtimer_num) {
+		sfi_mtimer_num = SFI_GET_NUM_ENTRIES(sb,
+					struct sfi_timer_table_entry);
+		pentry = (struct sfi_timer_table_entry *) sb->pentry;
+		totallen = sfi_mtimer_num * sizeof(*pentry);
+		memcpy(sfi_mtimer_array, pentry, totallen);
+	}
+
+	pr_debug("SFI MTIMER info (num = %d):\n", sfi_mtimer_num);
+	pentry = sfi_mtimer_array;
+	for (totallen = 0; totallen < sfi_mtimer_num; totallen++, pentry++) {
+		pr_debug("timer[%d]: paddr = 0x%08x, freq = %dHz, irq = %d\n",
+			totallen, (u32)pentry->phys_addr,
+			pentry->freq_hz, pentry->irq);
+			if (!pentry->irq)
+				continue;
+			mp_irq.type = MP_INTSRC;
+			mp_irq.irqtype = mp_INT;
+/* triggering mode edge bit 2-3, active high polarity bit 0-1 */
+			mp_irq.irqflag = 5;
+			mp_irq.srcbus = MP_BUS_ISA;
+			mp_irq.srcbusirq = pentry->irq;	/* IRQ */
+			mp_irq.dstapic = MP_APIC_ALL;
+			mp_irq.dstirq = pentry->irq;
+			mp_save_irq(&mp_irq);
+	}
+
+	return 0;
+}
+
+struct sfi_timer_table_entry *sfi_get_mtmr(int hint)
+{
+	int i;
+	if (hint < sfi_mtimer_num) {
+		if (!sfi_mtimer_usage[hint]) {
+			pr_debug("hint taken for timer %d irq %d\n",
+				hint, sfi_mtimer_array[hint].irq);
+			sfi_mtimer_usage[hint] = 1;
+			return &sfi_mtimer_array[hint];
+		}
+	}
+	/* take the first timer available */
+	for (i = 0; i < sfi_mtimer_num;) {
+		if (!sfi_mtimer_usage[i]) {
+			sfi_mtimer_usage[i] = 1;
+			return &sfi_mtimer_array[i];
+		}
+		i++;
+	}
+	return NULL;
+}
+
+void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr)
+{
+	int i;
+	for (i = 0; i < sfi_mtimer_num;) {
+		if (mtmr->irq == sfi_mtimer_array[i].irq) {
+			sfi_mtimer_usage[i] = 0;
+			return;
+		}
+		i++;
+	}
+}
+
+/* parse all the mrtc info to a global mrtc array */
+int __init sfi_parse_mrtc(struct sfi_table_header *table)
+{
+	struct sfi_table_simple *sb;
+	struct sfi_rtc_table_entry *pentry;
+	struct mpc_intsrc mp_irq;
+
+	int totallen;
+
+	sb = (struct sfi_table_simple *)table;
+	if (!sfi_mrtc_num) {
+		sfi_mrtc_num = SFI_GET_NUM_ENTRIES(sb,
+						struct sfi_rtc_table_entry);
+		pentry = (struct sfi_rtc_table_entry *)sb->pentry;
+		totallen = sfi_mrtc_num * sizeof(*pentry);
+		memcpy(sfi_mrtc_array, pentry, totallen);
+	}
+
+	pr_debug("SFI RTC info (num = %d):\n", sfi_mrtc_num);
+	pentry = sfi_mrtc_array;
+	for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) {
+		pr_debug("RTC[%d]: paddr = 0x%08x, irq = %d\n",
+			totallen, (u32)pentry->phys_addr, pentry->irq);
+		mp_irq.type = MP_INTSRC;
+		mp_irq.irqtype = mp_INT;
+		mp_irq.irqflag = 0xf;	/* level trigger and active low */
+		mp_irq.srcbus = MP_BUS_ISA;
+		mp_irq.srcbusirq = pentry->irq;	/* IRQ */
+		mp_irq.dstapic = MP_APIC_ALL;
+		mp_irq.dstirq = pentry->irq;
+		mp_save_irq(&mp_irq);
+	}
+	return 0;
+}
+
+
+/*
+ * Parsing GPIO table first, since the DEVS table will need this table
+ * to map the pin name to the actual pin.
+ */
+static int __init sfi_parse_gpio(struct sfi_table_header *table)
+{
+	struct sfi_table_simple *sb;
+	struct sfi_gpio_table_entry *pentry;
+	int num, i;
+
+	if (gpio_table)
+		return 0;
+	sb = (struct sfi_table_simple *)table;
+	num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry);
+	pentry = (struct sfi_gpio_table_entry *)sb->pentry;
+
+	gpio_table = kmalloc(num * sizeof(*pentry), GFP_KERNEL);
+	if (!gpio_table)
+		return -1;
+	memcpy(gpio_table, pentry, num * sizeof(*pentry));
+	gpio_num_entry = num;
+
+	pr_debug("GPIO pin info:\n");
+	for (i = 0; i < num; i++, pentry++)
+		pr_debug("info[%2d]: controller = %16.16s, pin_name = %16.16s,"
+		" pin = %d\n", i,
+			pentry->controller_name,
+			pentry->pin_name,
+			pentry->pin_no);
+	return 0;
+}
+
+int get_gpio_by_name(const char *name)
+{
+	struct sfi_gpio_table_entry *pentry = gpio_table;
+	int i;
+
+	if (!pentry)
+		return -1;
+	for (i = 0; i < gpio_num_entry; i++, pentry++) {
+		if (!strncmp(name, pentry->pin_name, SFI_NAME_LEN))
+			return pentry->pin_no;
+	}
+	return -1;
+}
+
+void __init intel_scu_device_register(struct platform_device *pdev)
+{
+	if (ipc_next_dev == MAX_IPCDEVS)
+		pr_err("too many SCU IPC devices");
+	else
+		ipc_devs[ipc_next_dev++] = pdev;
+}
+
+static void __init intel_scu_spi_device_register(struct spi_board_info *sdev)
+{
+	struct spi_board_info *new_dev;
+
+	if (spi_next_dev == MAX_SCU_SPI) {
+		pr_err("too many SCU SPI devices");
+		return;
+	}
+
+	new_dev = kzalloc(sizeof(*sdev), GFP_KERNEL);
+	if (!new_dev) {
+		pr_err("failed to alloc mem for delayed spi dev %s\n",
+			sdev->modalias);
+		return;
+	}
+	memcpy(new_dev, sdev, sizeof(*sdev));
+
+	spi_devs[spi_next_dev++] = new_dev;
+}
+
+static void __init intel_scu_i2c_device_register(int bus,
+						struct i2c_board_info *idev)
+{
+	struct i2c_board_info *new_dev;
+
+	if (i2c_next_dev == MAX_SCU_I2C) {
+		pr_err("too many SCU I2C devices");
+		return;
+	}
+
+	new_dev = kzalloc(sizeof(*idev), GFP_KERNEL);
+	if (!new_dev) {
+		pr_err("failed to alloc mem for delayed i2c dev %s\n",
+			idev->type);
+		return;
+	}
+	memcpy(new_dev, idev, sizeof(*idev));
+
+	i2c_bus[i2c_next_dev] = bus;
+	i2c_devs[i2c_next_dev++] = new_dev;
+}
+
+/* Called by IPC driver */
+void intel_scu_devices_create(void)
+{
+	int i;
+
+	for (i = 0; i < ipc_next_dev; i++)
+		platform_device_add(ipc_devs[i]);
+
+	for (i = 0; i < spi_next_dev; i++)
+		spi_register_board_info(spi_devs[i], 1);
+
+	for (i = 0; i < i2c_next_dev; i++) {
+		struct i2c_adapter *adapter;
+		struct i2c_client *client;
+
+		adapter = i2c_get_adapter(i2c_bus[i]);
+		if (adapter) {
+			client = i2c_new_device(adapter, i2c_devs[i]);
+			if (!client)
+				pr_err("can't create i2c device %s\n",
+					i2c_devs[i]->type);
+		} else
+			i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1);
+	}
+	intel_scu_notifier_post(SCU_AVAILABLE, NULL);
+}
+EXPORT_SYMBOL_GPL(intel_scu_devices_create);
+
+/* Called by IPC driver */
+void intel_scu_devices_destroy(void)
+{
+	int i;
+
+	intel_scu_notifier_post(SCU_DOWN, NULL);
+
+	for (i = 0; i < ipc_next_dev; i++)
+		platform_device_del(ipc_devs[i]);
+}
+EXPORT_SYMBOL_GPL(intel_scu_devices_destroy);
+
+static void __init install_irq_resource(struct platform_device *pdev, int irq)
+{
+	/* Single threaded */
+	static struct resource res __initdata = {
+		.name = "IRQ",
+		.flags = IORESOURCE_IRQ,
+	};
+	res.start = irq;
+	platform_device_add_resources(pdev, &res, 1);
+}
+
+static void __init sfi_handle_ipc_dev(struct sfi_device_table_entry *pentry,
+					struct devs_id *dev)
+{
+	struct platform_device *pdev;
+	void *pdata = NULL;
+
+	pr_debug("IPC bus, name = %16.16s, irq = 0x%2x\n",
+		pentry->name, pentry->irq);
+	pdata = intel_mid_sfi_get_pdata(dev, pentry);
+
+	pdev = platform_device_alloc(pentry->name, 0);
+	if (pdev == NULL) {
+		pr_err("out of memory for SFI platform device '%s'.\n",
+			pentry->name);
+		return;
+	}
+	install_irq_resource(pdev, pentry->irq);
+
+	pdev->dev.platform_data = pdata;
+	platform_device_add(pdev);
+}
+
+static void __init sfi_handle_spi_dev(struct sfi_device_table_entry *pentry,
+					struct devs_id *dev)
+{
+	struct spi_board_info spi_info;
+	void *pdata = NULL;
+
+	memset(&spi_info, 0, sizeof(spi_info));
+	strncpy(spi_info.modalias, pentry->name, SFI_NAME_LEN);
+	spi_info.irq = ((pentry->irq == (u8)0xff) ? 0 : pentry->irq);
+	spi_info.bus_num = pentry->host_num;
+	spi_info.chip_select = pentry->addr;
+	spi_info.max_speed_hz = pentry->max_freq;
+	pr_debug("SPI bus=%d, name=%16.16s, irq=0x%2x, max_freq=%d, cs=%d\n",
+		spi_info.bus_num,
+		spi_info.modalias,
+		spi_info.irq,
+		spi_info.max_speed_hz,
+		spi_info.chip_select);
+
+	pdata = intel_mid_sfi_get_pdata(dev, &spi_info);
+
+	spi_info.platform_data = pdata;
+	if (dev->delay)
+		intel_scu_spi_device_register(&spi_info);
+	else
+		spi_register_board_info(&spi_info, 1);
+}
+
+static void __init sfi_handle_i2c_dev(struct sfi_device_table_entry *pentry,
+					struct devs_id *dev)
+{
+	struct i2c_board_info i2c_info;
+	void *pdata = NULL;
+
+	memset(&i2c_info, 0, sizeof(i2c_info));
+	strncpy(i2c_info.type, pentry->name, SFI_NAME_LEN);
+	i2c_info.irq = ((pentry->irq == (u8)0xff) ? 0 : pentry->irq);
+	i2c_info.addr = pentry->addr;
+	pr_debug("I2C bus = %d, name = %16.16s, irq = 0x%2x, addr = 0x%x\n",
+		pentry->host_num,
+		i2c_info.type,
+		i2c_info.irq,
+		i2c_info.addr);
+	pdata = intel_mid_sfi_get_pdata(dev, &i2c_info);
+	i2c_info.platform_data = pdata;
+
+	if (dev->delay)
+		intel_scu_i2c_device_register(pentry->host_num, &i2c_info);
+	else
+		i2c_register_board_info(pentry->host_num, &i2c_info, 1);
+}
+
+extern struct devs_id *const __x86_intel_mid_dev_start[],
+		      *const __x86_intel_mid_dev_end[];
+
+static struct devs_id __init *get_device_id(u8 type, char *name)
+{
+	struct devs_id *const *dev_table;
+
+	for (dev_table = __x86_intel_mid_dev_start;
+			dev_table < __x86_intel_mid_dev_end; dev_table++) {
+		struct devs_id *dev = *dev_table;
+		if (dev->type == type &&
+			!strncmp(dev->name, name, SFI_NAME_LEN)) {
+			return dev;
+		}
+	}
+
+	return NULL;
+}
+
+static int __init sfi_parse_devs(struct sfi_table_header *table)
+{
+	struct sfi_table_simple *sb;
+	struct sfi_device_table_entry *pentry;
+	struct devs_id *dev = NULL;
+	int num, i;
+	int ioapic;
+	struct io_apic_irq_attr irq_attr;
+
+	sb = (struct sfi_table_simple *)table;
+	num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry);
+	pentry = (struct sfi_device_table_entry *)sb->pentry;
+
+	for (i = 0; i < num; i++, pentry++) {
+		int irq = pentry->irq;
+
+		if (irq != (u8)0xff) { /* native RTE case */
+			/* these SPI2 devices are not exposed to system as PCI
+			 * devices, but they have separate RTE entry in IOAPIC
+			 * so we have to enable them one by one here
+			 */
+			ioapic = mp_find_ioapic(irq);
+			irq_attr.ioapic = ioapic;
+			irq_attr.ioapic_pin = irq;
+			irq_attr.trigger = 1;
+			irq_attr.polarity = 1;
+			io_apic_set_pci_routing(NULL, irq, &irq_attr);
+		} else
+			irq = 0; /* No irq */
+
+		dev = get_device_id(pentry->type, pentry->name);
+
+		if (!dev)
+			continue;
+
+		if (dev->device_handler) {
+			dev->device_handler(pentry, dev);
+		} else {
+			switch (pentry->type) {
+			case SFI_DEV_TYPE_IPC:
+				sfi_handle_ipc_dev(pentry, dev);
+				break;
+			case SFI_DEV_TYPE_SPI:
+				sfi_handle_spi_dev(pentry, dev);
+				break;
+			case SFI_DEV_TYPE_I2C:
+				sfi_handle_i2c_dev(pentry, dev);
+				break;
+			case SFI_DEV_TYPE_UART:
+			case SFI_DEV_TYPE_HSI:
+			default:
+				break;
+			}
+		}
+	}
+	return 0;
+}
+
+static int __init intel_mid_platform_init(void)
+{
+	sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, sfi_parse_gpio);
+	sfi_table_parse(SFI_SIG_DEVS, NULL, NULL, sfi_parse_devs);
+	return 0;
+}
+arch_initcall(intel_mid_platform_init);
diff --git a/arch/x86/platform/mrst/Makefile b/arch/x86/platform/mrst/Makefile
deleted file mode 100644
index af1da7e..0000000
--- a/arch/x86/platform/mrst/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_X86_INTEL_MID)	+= mrst.o
-obj-$(CONFIG_X86_INTEL_MID)	+= vrtc.o
-obj-$(CONFIG_EARLY_PRINTK_INTEL_MID)	+= early_printk_mrst.o
diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c
deleted file mode 100644
index 3ca5957..0000000
--- a/arch/x86/platform/mrst/mrst.c
+++ /dev/null
@@ -1,1052 +0,0 @@
-/*
- * mrst.c: Intel Moorestown platform specific setup code
- *
- * (C) Copyright 2008 Intel Corporation
- * Author: Jacob Pan (jacob.jun.pan@intel.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; version 2
- * of the License.
- */
-
-#define pr_fmt(fmt) "mrst: " fmt
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/scatterlist.h>
-#include <linux/sfi.h>
-#include <linux/intel_pmic_gpio.h>
-#include <linux/spi/spi.h>
-#include <linux/i2c.h>
-#include <linux/platform_data/pca953x.h>
-#include <linux/gpio_keys.h>
-#include <linux/input.h>
-#include <linux/platform_device.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-#include <linux/notifier.h>
-#include <linux/mfd/intel_msic.h>
-#include <linux/gpio.h>
-#include <linux/i2c/tc35876x.h>
-
-#include <asm/setup.h>
-#include <asm/mpspec_def.h>
-#include <asm/hw_irq.h>
-#include <asm/apic.h>
-#include <asm/io_apic.h>
-#include <asm/mrst.h>
-#include <asm/mrst-vrtc.h>
-#include <asm/io.h>
-#include <asm/i8259.h>
-#include <asm/intel_scu_ipc.h>
-#include <asm/apb_timer.h>
-#include <asm/reboot.h>
-
-/*
- * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock,
- * cmdline option x86_mrst_timer can be used to override the configuration
- * to prefer one or the other.
- * at runtime, there are basically three timer configurations:
- * 1. per cpu apbt clock only
- * 2. per cpu always-on lapic clocks only, this is Penwell/Medfield only
- * 3. per cpu lapic clock (C3STOP) and one apbt clock, with broadcast.
- *
- * by default (without cmdline option), platform code first detects cpu type
- * to see if we are on lincroft or penwell, then set up both lapic or apbt
- * clocks accordingly.
- * i.e. by default, medfield uses configuration #2, moorestown uses #1.
- * config #3 is supported but not recommended on medfield.
- *
- * rating and feature summary:
- * lapic (with C3STOP) --------- 100
- * apbt (always-on) ------------ 110
- * lapic (always-on,ARAT) ------ 150
- */
-
-enum mrst_timer_options mrst_timer_options;
-
-static u32 sfi_mtimer_usage[SFI_MTMR_MAX_NUM];
-static struct sfi_timer_table_entry sfi_mtimer_array[SFI_MTMR_MAX_NUM];
-enum mrst_cpu_type __mrst_cpu_chip;
-EXPORT_SYMBOL_GPL(__mrst_cpu_chip);
-
-int sfi_mtimer_num;
-
-struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX];
-EXPORT_SYMBOL_GPL(sfi_mrtc_array);
-int sfi_mrtc_num;
-
-static void mrst_power_off(void)
-{
-}
-
-static void mrst_reboot(void)
-{
-	intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0);
-}
-
-/* parse all the mtimer info to a static mtimer array */
-static int __init sfi_parse_mtmr(struct sfi_table_header *table)
-{
-	struct sfi_table_simple *sb;
-	struct sfi_timer_table_entry *pentry;
-	struct mpc_intsrc mp_irq;
-	int totallen;
-
-	sb = (struct sfi_table_simple *)table;
-	if (!sfi_mtimer_num) {
-		sfi_mtimer_num = SFI_GET_NUM_ENTRIES(sb,
-					struct sfi_timer_table_entry);
-		pentry = (struct sfi_timer_table_entry *) sb->pentry;
-		totallen = sfi_mtimer_num * sizeof(*pentry);
-		memcpy(sfi_mtimer_array, pentry, totallen);
-	}
-
-	pr_debug("SFI MTIMER info (num = %d):\n", sfi_mtimer_num);
-	pentry = sfi_mtimer_array;
-	for (totallen = 0; totallen < sfi_mtimer_num; totallen++, pentry++) {
-		pr_debug("timer[%d]: paddr = 0x%08x, freq = %dHz,"
-			" irq = %d\n", totallen, (u32)pentry->phys_addr,
-			pentry->freq_hz, pentry->irq);
-			if (!pentry->irq)
-				continue;
-			mp_irq.type = MP_INTSRC;
-			mp_irq.irqtype = mp_INT;
-/* triggering mode edge bit 2-3, active high polarity bit 0-1 */
-			mp_irq.irqflag = 5;
-			mp_irq.srcbus = MP_BUS_ISA;
-			mp_irq.srcbusirq = pentry->irq;	/* IRQ */
-			mp_irq.dstapic = MP_APIC_ALL;
-			mp_irq.dstirq = pentry->irq;
-			mp_save_irq(&mp_irq);
-	}
-
-	return 0;
-}
-
-struct sfi_timer_table_entry *sfi_get_mtmr(int hint)
-{
-	int i;
-	if (hint < sfi_mtimer_num) {
-		if (!sfi_mtimer_usage[hint]) {
-			pr_debug("hint taken for timer %d irq %d\n",\
-				hint, sfi_mtimer_array[hint].irq);
-			sfi_mtimer_usage[hint] = 1;
-			return &sfi_mtimer_array[hint];
-		}
-	}
-	/* take the first timer available */
-	for (i = 0; i < sfi_mtimer_num;) {
-		if (!sfi_mtimer_usage[i]) {
-			sfi_mtimer_usage[i] = 1;
-			return &sfi_mtimer_array[i];
-		}
-		i++;
-	}
-	return NULL;
-}
-
-void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr)
-{
-	int i;
-	for (i = 0; i < sfi_mtimer_num;) {
-		if (mtmr->irq == sfi_mtimer_array[i].irq) {
-			sfi_mtimer_usage[i] = 0;
-			return;
-		}
-		i++;
-	}
-}
-
-/* parse all the mrtc info to a global mrtc array */
-int __init sfi_parse_mrtc(struct sfi_table_header *table)
-{
-	struct sfi_table_simple *sb;
-	struct sfi_rtc_table_entry *pentry;
-	struct mpc_intsrc mp_irq;
-
-	int totallen;
-
-	sb = (struct sfi_table_simple *)table;
-	if (!sfi_mrtc_num) {
-		sfi_mrtc_num = SFI_GET_NUM_ENTRIES(sb,
-						struct sfi_rtc_table_entry);
-		pentry = (struct sfi_rtc_table_entry *)sb->pentry;
-		totallen = sfi_mrtc_num * sizeof(*pentry);
-		memcpy(sfi_mrtc_array, pentry, totallen);
-	}
-
-	pr_debug("SFI RTC info (num = %d):\n", sfi_mrtc_num);
-	pentry = sfi_mrtc_array;
-	for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) {
-		pr_debug("RTC[%d]: paddr = 0x%08x, irq = %d\n",
-			totallen, (u32)pentry->phys_addr, pentry->irq);
-		mp_irq.type = MP_INTSRC;
-		mp_irq.irqtype = mp_INT;
-		mp_irq.irqflag = 0xf;	/* level trigger and active low */
-		mp_irq.srcbus = MP_BUS_ISA;
-		mp_irq.srcbusirq = pentry->irq;	/* IRQ */
-		mp_irq.dstapic = MP_APIC_ALL;
-		mp_irq.dstirq = pentry->irq;
-		mp_save_irq(&mp_irq);
-	}
-	return 0;
-}
-
-static unsigned long __init mrst_calibrate_tsc(void)
-{
-	unsigned long fast_calibrate;
-	u32 lo, hi, ratio, fsb;
-
-	rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
-	pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi);
-	ratio = (hi >> 8) & 0x1f;
-	pr_debug("ratio is %d\n", ratio);
-	if (!ratio) {
-		pr_err("read a zero ratio, should be incorrect!\n");
-		pr_err("force tsc ratio to 16 ...\n");
-		ratio = 16;
-	}
-	rdmsr(MSR_FSB_FREQ, lo, hi);
-	if ((lo & 0x7) == 0x7)
-		fsb = PENWELL_FSB_FREQ_83SKU;
-	else
-		fsb = PENWELL_FSB_FREQ_100SKU;
-	fast_calibrate = ratio * fsb;
-	pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
-	lapic_timer_frequency = fsb * 1000 / HZ;
-	/* mark tsc clocksource as reliable */
-	set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
-	
-	if (fast_calibrate)
-		return fast_calibrate;
-
-	return 0;
-}
-
-static void __init mrst_time_init(void)
-{
-	sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr);
-	switch (mrst_timer_options) {
-	case MRST_TIMER_APBT_ONLY:
-		break;
-	case MRST_TIMER_LAPIC_APBT:
-		x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock;
-		x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock;
-		break;
-	default:
-		if (!boot_cpu_has(X86_FEATURE_ARAT))
-			break;
-		x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock;
-		x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock;
-		return;
-	}
-	/* we need at least one APB timer */
-	pre_init_apic_IRQ0();
-	apbt_time_init();
-}
-
-static void mrst_arch_setup(void)
-{
-	if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27)
-		__mrst_cpu_chip = MRST_CPU_CHIP_PENWELL;
-	else {
-		pr_err("Unknown Intel MID CPU (%d:%d), default to Penwell\n",
-			boot_cpu_data.x86, boot_cpu_data.x86_model);
-		__mrst_cpu_chip = MRST_CPU_CHIP_PENWELL;
-	}
-}
-
-/* MID systems don't have i8042 controller */
-static int mrst_i8042_detect(void)
-{
-	return 0;
-}
-
-/*
- * Moorestown does not have external NMI source nor port 0x61 to report
- * NMI status. The possible NMI sources are from pmu as a result of NMI
- * watchdog or lock debug. Reading io port 0x61 results in 0xff which
- * misled NMI handler.
- */
-static unsigned char mrst_get_nmi_reason(void)
-{
-	return 0;
-}
-
-/*
- * Moorestown specific x86_init function overrides and early setup
- * calls.
- */
-void __init x86_mrst_early_setup(void)
-{
-	x86_init.resources.probe_roms = x86_init_noop;
-	x86_init.resources.reserve_resources = x86_init_noop;
-
-	x86_init.timers.timer_init = mrst_time_init;
-	x86_init.timers.setup_percpu_clockev = x86_init_noop;
-
-	x86_init.irqs.pre_vector_init = x86_init_noop;
-
-	x86_init.oem.arch_setup = mrst_arch_setup;
-
-	x86_cpuinit.setup_percpu_clockev = apbt_setup_secondary_clock;
-
-	x86_platform.calibrate_tsc = mrst_calibrate_tsc;
-	x86_platform.i8042_detect = mrst_i8042_detect;
-	x86_init.timers.wallclock_init = mrst_rtc_init;
-	x86_platform.get_nmi_reason = mrst_get_nmi_reason;
-
-	x86_init.pci.init = pci_mrst_init;
-	x86_init.pci.fixup_irqs = x86_init_noop;
-
-	legacy_pic = &null_legacy_pic;
-
-	/* Moorestown specific power_off/restart method */
-	pm_power_off = mrst_power_off;
-	machine_ops.emergency_restart  = mrst_reboot;
-
-	/* Avoid searching for BIOS MP tables */
-	x86_init.mpparse.find_smp_config = x86_init_noop;
-	x86_init.mpparse.get_smp_config = x86_init_uint_noop;
-	set_bit(MP_BUS_ISA, mp_bus_not_pci);
-}
-
-/*
- * if user does not want to use per CPU apb timer, just give it a lower rating
- * than local apic timer and skip the late per cpu timer init.
- */
-static inline int __init setup_x86_mrst_timer(char *arg)
-{
-	if (!arg)
-		return -EINVAL;
-
-	if (strcmp("apbt_only", arg) == 0)
-		mrst_timer_options = MRST_TIMER_APBT_ONLY;
-	else if (strcmp("lapic_and_apbt", arg) == 0)
-		mrst_timer_options = MRST_TIMER_LAPIC_APBT;
-	else {
-		pr_warning("X86 MRST timer option %s not recognised"
-			   " use x86_mrst_timer=apbt_only or lapic_and_apbt\n",
-			   arg);
-		return -EINVAL;
-	}
-	return 0;
-}
-__setup("x86_mrst_timer=", setup_x86_mrst_timer);
-
-/*
- * Parsing GPIO table first, since the DEVS table will need this table
- * to map the pin name to the actual pin.
- */
-static struct sfi_gpio_table_entry *gpio_table;
-static int gpio_num_entry;
-
-static int __init sfi_parse_gpio(struct sfi_table_header *table)
-{
-	struct sfi_table_simple *sb;
-	struct sfi_gpio_table_entry *pentry;
-	int num, i;
-
-	if (gpio_table)
-		return 0;
-	sb = (struct sfi_table_simple *)table;
-	num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry);
-	pentry = (struct sfi_gpio_table_entry *)sb->pentry;
-
-	gpio_table = kmalloc(num * sizeof(*pentry), GFP_KERNEL);
-	if (!gpio_table)
-		return -1;
-	memcpy(gpio_table, pentry, num * sizeof(*pentry));
-	gpio_num_entry = num;
-
-	pr_debug("GPIO pin info:\n");
-	for (i = 0; i < num; i++, pentry++)
-		pr_debug("info[%2d]: controller = %16.16s, pin_name = %16.16s,"
-		" pin = %d\n", i,
-			pentry->controller_name,
-			pentry->pin_name,
-			pentry->pin_no);
-	return 0;
-}
-
-static int get_gpio_by_name(const char *name)
-{
-	struct sfi_gpio_table_entry *pentry = gpio_table;
-	int i;
-
-	if (!pentry)
-		return -1;
-	for (i = 0; i < gpio_num_entry; i++, pentry++) {
-		if (!strncmp(name, pentry->pin_name, SFI_NAME_LEN))
-			return pentry->pin_no;
-	}
-	return -1;
-}
-
-/*
- * Here defines the array of devices platform data that IAFW would export
- * through SFI "DEVS" table, we use name and type to match the device and
- * its platform data.
- */
-struct devs_id {
-	char name[SFI_NAME_LEN + 1];
-	u8 type;
-	u8 delay;
-	void *(*get_platform_data)(void *info);
-};
-
-/* the offset for the mapping of global gpio pin to irq */
-#define MRST_IRQ_OFFSET 0x100
-
-static void __init *pmic_gpio_platform_data(void *info)
-{
-	static struct intel_pmic_gpio_platform_data pmic_gpio_pdata;
-	int gpio_base = get_gpio_by_name("pmic_gpio_base");
-
-	if (gpio_base == -1)
-		gpio_base = 64;
-	pmic_gpio_pdata.gpio_base = gpio_base;
-	pmic_gpio_pdata.irq_base = gpio_base + MRST_IRQ_OFFSET;
-	pmic_gpio_pdata.gpiointr = 0xffffeff8;
-
-	return &pmic_gpio_pdata;
-}
-
-static void __init *max3111_platform_data(void *info)
-{
-	struct spi_board_info *spi_info = info;
-	int intr = get_gpio_by_name("max3111_int");
-
-	spi_info->mode = SPI_MODE_0;
-	if (intr == -1)
-		return NULL;
-	spi_info->irq = intr + MRST_IRQ_OFFSET;
-	return NULL;
-}
-
-/* we have multiple max7315 on the board ... */
-#define MAX7315_NUM 2
-static void __init *max7315_platform_data(void *info)
-{
-	static struct pca953x_platform_data max7315_pdata[MAX7315_NUM];
-	static int nr;
-	struct pca953x_platform_data *max7315 = &max7315_pdata[nr];
-	struct i2c_board_info *i2c_info = info;
-	int gpio_base, intr;
-	char base_pin_name[SFI_NAME_LEN + 1];
-	char intr_pin_name[SFI_NAME_LEN + 1];
-
-	if (nr == MAX7315_NUM) {
-		pr_err("too many max7315s, we only support %d\n",
-				MAX7315_NUM);
-		return NULL;
-	}
-	/* we have several max7315 on the board, we only need load several
-	 * instances of the same pca953x driver to cover them
-	 */
-	strcpy(i2c_info->type, "max7315");
-	if (nr++) {
-		sprintf(base_pin_name, "max7315_%d_base", nr);
-		sprintf(intr_pin_name, "max7315_%d_int", nr);
-	} else {
-		strcpy(base_pin_name, "max7315_base");
-		strcpy(intr_pin_name, "max7315_int");
-	}
-
-	gpio_base = get_gpio_by_name(base_pin_name);
-	intr = get_gpio_by_name(intr_pin_name);
-
-	if (gpio_base == -1)
-		return NULL;
-	max7315->gpio_base = gpio_base;
-	if (intr != -1) {
-		i2c_info->irq = intr + MRST_IRQ_OFFSET;
-		max7315->irq_base = gpio_base + MRST_IRQ_OFFSET;
-	} else {
-		i2c_info->irq = -1;
-		max7315->irq_base = -1;
-	}
-	return max7315;
-}
-
-static void *tca6416_platform_data(void *info)
-{
-	static struct pca953x_platform_data tca6416;
-	struct i2c_board_info *i2c_info = info;
-	int gpio_base, intr;
-	char base_pin_name[SFI_NAME_LEN + 1];
-	char intr_pin_name[SFI_NAME_LEN + 1];
-
-	strcpy(i2c_info->type, "tca6416");
-	strcpy(base_pin_name, "tca6416_base");
-	strcpy(intr_pin_name, "tca6416_int");
-
-	gpio_base = get_gpio_by_name(base_pin_name);
-	intr = get_gpio_by_name(intr_pin_name);
-
-	if (gpio_base == -1)
-		return NULL;
-	tca6416.gpio_base = gpio_base;
-	if (intr != -1) {
-		i2c_info->irq = intr + MRST_IRQ_OFFSET;
-		tca6416.irq_base = gpio_base + MRST_IRQ_OFFSET;
-	} else {
-		i2c_info->irq = -1;
-		tca6416.irq_base = -1;
-	}
-	return &tca6416;
-}
-
-static void *mpu3050_platform_data(void *info)
-{
-	struct i2c_board_info *i2c_info = info;
-	int intr = get_gpio_by_name("mpu3050_int");
-
-	if (intr == -1)
-		return NULL;
-
-	i2c_info->irq = intr + MRST_IRQ_OFFSET;
-	return NULL;
-}
-
-static void __init *emc1403_platform_data(void *info)
-{
-	static short intr2nd_pdata;
-	struct i2c_board_info *i2c_info = info;
-	int intr = get_gpio_by_name("thermal_int");
-	int intr2nd = get_gpio_by_name("thermal_alert");
-
-	if (intr == -1 || intr2nd == -1)
-		return NULL;
-
-	i2c_info->irq = intr + MRST_IRQ_OFFSET;
-	intr2nd_pdata = intr2nd + MRST_IRQ_OFFSET;
-
-	return &intr2nd_pdata;
-}
-
-static void __init *lis331dl_platform_data(void *info)
-{
-	static short intr2nd_pdata;
-	struct i2c_board_info *i2c_info = info;
-	int intr = get_gpio_by_name("accel_int");
-	int intr2nd = get_gpio_by_name("accel_2");
-
-	if (intr == -1 || intr2nd == -1)
-		return NULL;
-
-	i2c_info->irq = intr + MRST_IRQ_OFFSET;
-	intr2nd_pdata = intr2nd + MRST_IRQ_OFFSET;
-
-	return &intr2nd_pdata;
-}
-
-static void __init *no_platform_data(void *info)
-{
-	return NULL;
-}
-
-static struct resource msic_resources[] = {
-	{
-		.start	= INTEL_MSIC_IRQ_PHYS_BASE,
-		.end	= INTEL_MSIC_IRQ_PHYS_BASE + 64 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct intel_msic_platform_data msic_pdata;
-
-static struct platform_device msic_device = {
-	.name		= "intel_msic",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &msic_pdata,
-	},
-	.num_resources	= ARRAY_SIZE(msic_resources),
-	.resource	= msic_resources,
-};
-
-static inline bool mrst_has_msic(void)
-{
-	return mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL;
-}
-
-static int msic_scu_status_change(struct notifier_block *nb,
-				  unsigned long code, void *data)
-{
-	if (code == SCU_DOWN) {
-		platform_device_unregister(&msic_device);
-		return 0;
-	}
-
-	return platform_device_register(&msic_device);
-}
-
-static int __init msic_init(void)
-{
-	static struct notifier_block msic_scu_notifier = {
-		.notifier_call	= msic_scu_status_change,
-	};
-
-	/*
-	 * We need to be sure that the SCU IPC is ready before MSIC device
-	 * can be registered.
-	 */
-	if (mrst_has_msic())
-		intel_scu_notifier_add(&msic_scu_notifier);
-
-	return 0;
-}
-arch_initcall(msic_init);
-
-/*
- * msic_generic_platform_data - sets generic platform data for the block
- * @info: pointer to the SFI device table entry for this block
- * @block: MSIC block
- *
- * Function sets IRQ number from the SFI table entry for given device to
- * the MSIC platform data.
- */
-static void *msic_generic_platform_data(void *info, enum intel_msic_block block)
-{
-	struct sfi_device_table_entry *entry = info;
-
-	BUG_ON(block < 0 || block >= INTEL_MSIC_BLOCK_LAST);
-	msic_pdata.irq[block] = entry->irq;
-
-	return no_platform_data(info);
-}
-
-static void *msic_battery_platform_data(void *info)
-{
-	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_BATTERY);
-}
-
-static void *msic_gpio_platform_data(void *info)
-{
-	static struct intel_msic_gpio_pdata pdata;
-	int gpio = get_gpio_by_name("msic_gpio_base");
-
-	if (gpio < 0)
-		return NULL;
-
-	pdata.gpio_base = gpio;
-	msic_pdata.gpio = &pdata;
-
-	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_GPIO);
-}
-
-static void *msic_audio_platform_data(void *info)
-{
-	struct platform_device *pdev;
-
-	pdev = platform_device_register_simple("sst-platform", -1, NULL, 0);
-	if (IS_ERR(pdev)) {
-		pr_err("failed to create audio platform device\n");
-		return NULL;
-	}
-
-	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_AUDIO);
-}
-
-static void *msic_power_btn_platform_data(void *info)
-{
-	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_POWER_BTN);
-}
-
-static void *msic_ocd_platform_data(void *info)
-{
-	static struct intel_msic_ocd_pdata pdata;
-	int gpio = get_gpio_by_name("ocd_gpio");
-
-	if (gpio < 0)
-		return NULL;
-
-	pdata.gpio = gpio;
-	msic_pdata.ocd = &pdata;
-
-	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_OCD);
-}
-
-static void *msic_thermal_platform_data(void *info)
-{
-	return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_THERMAL);
-}
-
-/* tc35876x DSI-LVDS bridge chip and panel platform data */
-static void *tc35876x_platform_data(void *data)
-{
-       static struct tc35876x_platform_data pdata;
-
-       /* gpio pins set to -1 will not be used by the driver */
-       pdata.gpio_bridge_reset = get_gpio_by_name("LCMB_RXEN");
-       pdata.gpio_panel_bl_en = get_gpio_by_name("6S6P_BL_EN");
-       pdata.gpio_panel_vadd = get_gpio_by_name("EN_VREG_LCD_V3P3");
-
-       return &pdata;
-}
-
-static const struct devs_id __initconst device_ids[] = {
-	{"bma023", SFI_DEV_TYPE_I2C, 1, &no_platform_data},
-	{"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data},
-	{"pmic_gpio", SFI_DEV_TYPE_IPC, 1, &pmic_gpio_platform_data},
-	{"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data},
-	{"i2c_max7315", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data},
-	{"i2c_max7315_2", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data},
-	{"tca6416", SFI_DEV_TYPE_I2C, 1, &tca6416_platform_data},
-	{"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data},
-	{"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data},
-	{"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data},
-	{"mpu3050", SFI_DEV_TYPE_I2C, 1, &mpu3050_platform_data},
-	{"i2c_disp_brig", SFI_DEV_TYPE_I2C, 0, &tc35876x_platform_data},
-
-	/* MSIC subdevices */
-	{"msic_battery", SFI_DEV_TYPE_IPC, 1, &msic_battery_platform_data},
-	{"msic_gpio", SFI_DEV_TYPE_IPC, 1, &msic_gpio_platform_data},
-	{"msic_audio", SFI_DEV_TYPE_IPC, 1, &msic_audio_platform_data},
-	{"msic_power_btn", SFI_DEV_TYPE_IPC, 1, &msic_power_btn_platform_data},
-	{"msic_ocd", SFI_DEV_TYPE_IPC, 1, &msic_ocd_platform_data},
-	{"msic_thermal", SFI_DEV_TYPE_IPC, 1, &msic_thermal_platform_data},
-
-	{},
-};
-
-#define MAX_IPCDEVS	24
-static struct platform_device *ipc_devs[MAX_IPCDEVS];
-static int ipc_next_dev;
-
-#define MAX_SCU_SPI	24
-static struct spi_board_info *spi_devs[MAX_SCU_SPI];
-static int spi_next_dev;
-
-#define MAX_SCU_I2C	24
-static struct i2c_board_info *i2c_devs[MAX_SCU_I2C];
-static int i2c_bus[MAX_SCU_I2C];
-static int i2c_next_dev;
-
-static void __init intel_scu_device_register(struct platform_device *pdev)
-{
-	if(ipc_next_dev == MAX_IPCDEVS)
-		pr_err("too many SCU IPC devices");
-	else
-		ipc_devs[ipc_next_dev++] = pdev;
-}
-
-static void __init intel_scu_spi_device_register(struct spi_board_info *sdev)
-{
-	struct spi_board_info *new_dev;
-
-	if (spi_next_dev == MAX_SCU_SPI) {
-		pr_err("too many SCU SPI devices");
-		return;
-	}
-
-	new_dev = kzalloc(sizeof(*sdev), GFP_KERNEL);
-	if (!new_dev) {
-		pr_err("failed to alloc mem for delayed spi dev %s\n",
-			sdev->modalias);
-		return;
-	}
-	memcpy(new_dev, sdev, sizeof(*sdev));
-
-	spi_devs[spi_next_dev++] = new_dev;
-}
-
-static void __init intel_scu_i2c_device_register(int bus,
-						struct i2c_board_info *idev)
-{
-	struct i2c_board_info *new_dev;
-
-	if (i2c_next_dev == MAX_SCU_I2C) {
-		pr_err("too many SCU I2C devices");
-		return;
-	}
-
-	new_dev = kzalloc(sizeof(*idev), GFP_KERNEL);
-	if (!new_dev) {
-		pr_err("failed to alloc mem for delayed i2c dev %s\n",
-			idev->type);
-		return;
-	}
-	memcpy(new_dev, idev, sizeof(*idev));
-
-	i2c_bus[i2c_next_dev] = bus;
-	i2c_devs[i2c_next_dev++] = new_dev;
-}
-
-BLOCKING_NOTIFIER_HEAD(intel_scu_notifier);
-EXPORT_SYMBOL_GPL(intel_scu_notifier);
-
-/* Called by IPC driver */
-void intel_scu_devices_create(void)
-{
-	int i;
-
-	for (i = 0; i < ipc_next_dev; i++)
-		platform_device_add(ipc_devs[i]);
-
-	for (i = 0; i < spi_next_dev; i++)
-		spi_register_board_info(spi_devs[i], 1);
-
-	for (i = 0; i < i2c_next_dev; i++) {
-		struct i2c_adapter *adapter;
-		struct i2c_client *client;
-
-		adapter = i2c_get_adapter(i2c_bus[i]);
-		if (adapter) {
-			client = i2c_new_device(adapter, i2c_devs[i]);
-			if (!client)
-				pr_err("can't create i2c device %s\n",
-					i2c_devs[i]->type);
-		} else
-			i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1);
-	}
-	intel_scu_notifier_post(SCU_AVAILABLE, NULL);
-}
-EXPORT_SYMBOL_GPL(intel_scu_devices_create);
-
-/* Called by IPC driver */
-void intel_scu_devices_destroy(void)
-{
-	int i;
-
-	intel_scu_notifier_post(SCU_DOWN, NULL);
-
-	for (i = 0; i < ipc_next_dev; i++)
-		platform_device_del(ipc_devs[i]);
-}
-EXPORT_SYMBOL_GPL(intel_scu_devices_destroy);
-
-static void __init install_irq_resource(struct platform_device *pdev, int irq)
-{
-	/* Single threaded */
-	static struct resource __initdata res = {
-		.name = "IRQ",
-		.flags = IORESOURCE_IRQ,
-	};
-	res.start = irq;
-	platform_device_add_resources(pdev, &res, 1);
-}
-
-static void __init sfi_handle_ipc_dev(struct sfi_device_table_entry *entry)
-{
-	const struct devs_id *dev = device_ids;
-	struct platform_device *pdev;
-	void *pdata = NULL;
-
-	while (dev->name[0]) {
-		if (dev->type == SFI_DEV_TYPE_IPC &&
-			!strncmp(dev->name, entry->name, SFI_NAME_LEN)) {
-			pdata = dev->get_platform_data(entry);
-			break;
-		}
-		dev++;
-	}
-
-	/*
-	 * On Medfield the platform device creation is handled by the MSIC
-	 * MFD driver so we don't need to do it here.
-	 */
-	if (mrst_has_msic())
-		return;
-
-	pdev = platform_device_alloc(entry->name, 0);
-	if (pdev == NULL) {
-		pr_err("out of memory for SFI platform device '%s'.\n",
-			entry->name);
-		return;
-	}
-	install_irq_resource(pdev, entry->irq);
-
-	pdev->dev.platform_data = pdata;
-	intel_scu_device_register(pdev);
-}
-
-static void __init sfi_handle_spi_dev(struct spi_board_info *spi_info)
-{
-	const struct devs_id *dev = device_ids;
-	void *pdata = NULL;
-
-	while (dev->name[0]) {
-		if (dev->type == SFI_DEV_TYPE_SPI &&
-				!strncmp(dev->name, spi_info->modalias, SFI_NAME_LEN)) {
-			pdata = dev->get_platform_data(spi_info);
-			break;
-		}
-		dev++;
-	}
-	spi_info->platform_data = pdata;
-	if (dev->delay)
-		intel_scu_spi_device_register(spi_info);
-	else
-		spi_register_board_info(spi_info, 1);
-}
-
-static void __init sfi_handle_i2c_dev(int bus, struct i2c_board_info *i2c_info)
-{
-	const struct devs_id *dev = device_ids;
-	void *pdata = NULL;
-
-	while (dev->name[0]) {
-		if (dev->type == SFI_DEV_TYPE_I2C &&
-			!strncmp(dev->name, i2c_info->type, SFI_NAME_LEN)) {
-			pdata = dev->get_platform_data(i2c_info);
-			break;
-		}
-		dev++;
-	}
-	i2c_info->platform_data = pdata;
-
-	if (dev->delay)
-		intel_scu_i2c_device_register(bus, i2c_info);
-	else
-		i2c_register_board_info(bus, i2c_info, 1);
- }
-
-
-static int __init sfi_parse_devs(struct sfi_table_header *table)
-{
-	struct sfi_table_simple *sb;
-	struct sfi_device_table_entry *pentry;
-	struct spi_board_info spi_info;
-	struct i2c_board_info i2c_info;
-	int num, i, bus;
-	int ioapic;
-	struct io_apic_irq_attr irq_attr;
-
-	sb = (struct sfi_table_simple *)table;
-	num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry);
-	pentry = (struct sfi_device_table_entry *)sb->pentry;
-
-	for (i = 0; i < num; i++, pentry++) {
-		int irq = pentry->irq;
-
-		if (irq != (u8)0xff) { /* native RTE case */
-			/* these SPI2 devices are not exposed to system as PCI
-			 * devices, but they have separate RTE entry in IOAPIC
-			 * so we have to enable them one by one here
-			 */
-			ioapic = mp_find_ioapic(irq);
-			irq_attr.ioapic = ioapic;
-			irq_attr.ioapic_pin = irq;
-			irq_attr.trigger = 1;
-			irq_attr.polarity = 1;
-			io_apic_set_pci_routing(NULL, irq, &irq_attr);
-		} else
-			irq = 0; /* No irq */
-
-		switch (pentry->type) {
-		case SFI_DEV_TYPE_IPC:
-			pr_debug("info[%2d]: IPC bus, name = %16.16s, "
-				"irq = 0x%2x\n", i, pentry->name, pentry->irq);
-			sfi_handle_ipc_dev(pentry);
-			break;
-		case SFI_DEV_TYPE_SPI:
-			memset(&spi_info, 0, sizeof(spi_info));
-			strncpy(spi_info.modalias, pentry->name, SFI_NAME_LEN);
-			spi_info.irq = irq;
-			spi_info.bus_num = pentry->host_num;
-			spi_info.chip_select = pentry->addr;
-			spi_info.max_speed_hz = pentry->max_freq;
-			pr_debug("info[%2d]: SPI bus = %d, name = %16.16s, "
-				"irq = 0x%2x, max_freq = %d, cs = %d\n", i,
-				spi_info.bus_num,
-				spi_info.modalias,
-				spi_info.irq,
-				spi_info.max_speed_hz,
-				spi_info.chip_select);
-			sfi_handle_spi_dev(&spi_info);
-			break;
-		case SFI_DEV_TYPE_I2C:
-			memset(&i2c_info, 0, sizeof(i2c_info));
-			bus = pentry->host_num;
-			strncpy(i2c_info.type, pentry->name, SFI_NAME_LEN);
-			i2c_info.irq = irq;
-			i2c_info.addr = pentry->addr;
-			pr_debug("info[%2d]: I2C bus = %d, name = %16.16s, "
-				"irq = 0x%2x, addr = 0x%x\n", i, bus,
-				i2c_info.type,
-				i2c_info.irq,
-				i2c_info.addr);
-			sfi_handle_i2c_dev(bus, &i2c_info);
-			break;
-		case SFI_DEV_TYPE_UART:
-		case SFI_DEV_TYPE_HSI:
-		default:
-			;
-		}
-	}
-	return 0;
-}
-
-static int __init mrst_platform_init(void)
-{
-	sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, sfi_parse_gpio);
-	sfi_table_parse(SFI_SIG_DEVS, NULL, NULL, sfi_parse_devs);
-	return 0;
-}
-arch_initcall(mrst_platform_init);
-
-/*
- * we will search these buttons in SFI GPIO table (by name)
- * and register them dynamically. Please add all possible
- * buttons here, we will shrink them if no GPIO found.
- */
-static struct gpio_keys_button gpio_button[] = {
-	{KEY_POWER,		-1, 1, "power_btn",	EV_KEY, 0, 3000},
-	{KEY_PROG1,		-1, 1, "prog_btn1",	EV_KEY, 0, 20},
-	{KEY_PROG2,		-1, 1, "prog_btn2",	EV_KEY, 0, 20},
-	{SW_LID,		-1, 1, "lid_switch",	EV_SW,  0, 20},
-	{KEY_VOLUMEUP,		-1, 1, "vol_up",	EV_KEY, 0, 20},
-	{KEY_VOLUMEDOWN,	-1, 1, "vol_down",	EV_KEY, 0, 20},
-	{KEY_CAMERA,		-1, 1, "camera_full",	EV_KEY, 0, 20},
-	{KEY_CAMERA_FOCUS,	-1, 1, "camera_half",	EV_KEY, 0, 20},
-	{SW_KEYPAD_SLIDE,	-1, 1, "MagSw1",	EV_SW,  0, 20},
-	{SW_KEYPAD_SLIDE,	-1, 1, "MagSw2",	EV_SW,  0, 20},
-};
-
-static struct gpio_keys_platform_data mrst_gpio_keys = {
-	.buttons	= gpio_button,
-	.rep		= 1,
-	.nbuttons	= -1, /* will fill it after search */
-};
-
-static struct platform_device pb_device = {
-	.name		= "gpio-keys",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &mrst_gpio_keys,
-	},
-};
-
-/*
- * Shrink the non-existent buttons, register the gpio button
- * device if there is some
- */
-static int __init pb_keys_init(void)
-{
-	struct gpio_keys_button *gb = gpio_button;
-	int i, num, good = 0;
-
-	num = sizeof(gpio_button) / sizeof(struct gpio_keys_button);
-	for (i = 0; i < num; i++) {
-		gb[i].gpio = get_gpio_by_name(gb[i].desc);
-		pr_debug("info[%2d]: name = %s, gpio = %d\n", i, gb[i].desc, gb[i].gpio);
-		if (gb[i].gpio == -1)
-			continue;
-
-		if (i != good)
-			gb[good] = gb[i];
-		good++;
-	}
-
-	if (good) {
-		mrst_gpio_keys.nbuttons = good;
-		return platform_device_register(&pb_device);
-	}
-	return 0;
-}
-late_initcall(pb_keys_init);
diff --git a/arch/x86/platform/uv/Makefile b/arch/x86/platform/uv/Makefile
index 6c40995..52079be 100644
--- a/arch/x86/platform/uv/Makefile
+++ b/arch/x86/platform/uv/Makefile
@@ -1 +1 @@
-obj-$(CONFIG_X86_UV)		+= tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o
+obj-$(CONFIG_X86_UV)		+= tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o uv_nmi.o
diff --git a/arch/x86/platform/uv/uv_nmi.c b/arch/x86/platform/uv/uv_nmi.c
new file mode 100644
index 0000000..2e863ad
--- /dev/null
+++ b/arch/x86/platform/uv/uv_nmi.c
@@ -0,0 +1,700 @@
+/*
+ * SGI NMI support routines
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ *  Copyright (c) 2009-2013 Silicon Graphics, Inc.  All Rights Reserved.
+ *  Copyright (c) Mike Travis
+ */
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/kdb.h>
+#include <linux/kexec.h>
+#include <linux/kgdb.h>
+#include <linux/module.h>
+#include <linux/nmi.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <asm/apic.h>
+#include <asm/current.h>
+#include <asm/kdebug.h>
+#include <asm/local64.h>
+#include <asm/nmi.h>
+#include <asm/traps.h>
+#include <asm/uv/uv.h>
+#include <asm/uv/uv_hub.h>
+#include <asm/uv/uv_mmrs.h>
+
+/*
+ * UV handler for NMI
+ *
+ * Handle system-wide NMI events generated by the global 'power nmi' command.
+ *
+ * Basic operation is to field the NMI interrupt on each cpu and wait
+ * until all cpus have arrived into the nmi handler.  If some cpus do not
+ * make it into the handler, try and force them in with the IPI(NMI) signal.
+ *
+ * We also have to lessen UV Hub MMR accesses as much as possible as this
+ * disrupts the UV Hub's primary mission of directing NumaLink traffic and
+ * can cause system problems to occur.
+ *
+ * To do this we register our primary NMI notifier on the NMI_UNKNOWN
+ * chain.  This reduces the number of false NMI calls when the perf
+ * tools are running which generate an enormous number of NMIs per
+ * second (~4M/s for 1024 cpu threads).  Our secondary NMI handler is
+ * very short as it only checks that if it has been "pinged" with the
+ * IPI(NMI) signal as mentioned above, and does not read the UV Hub's MMR.
+ *
+ */
+
+static struct uv_hub_nmi_s **uv_hub_nmi_list;
+
+DEFINE_PER_CPU(struct uv_cpu_nmi_s, __uv_cpu_nmi);
+EXPORT_PER_CPU_SYMBOL_GPL(__uv_cpu_nmi);
+
+static unsigned long nmi_mmr;
+static unsigned long nmi_mmr_clear;
+static unsigned long nmi_mmr_pending;
+
+static atomic_t	uv_in_nmi;
+static atomic_t uv_nmi_cpu = ATOMIC_INIT(-1);
+static atomic_t uv_nmi_cpus_in_nmi = ATOMIC_INIT(-1);
+static atomic_t uv_nmi_slave_continue;
+static atomic_t uv_nmi_kexec_failed;
+static cpumask_var_t uv_nmi_cpu_mask;
+
+/* Values for uv_nmi_slave_continue */
+#define SLAVE_CLEAR	0
+#define SLAVE_CONTINUE	1
+#define SLAVE_EXIT	2
+
+/*
+ * Default is all stack dumps go to the console and buffer.
+ * Lower level to send to log buffer only.
+ */
+static int uv_nmi_loglevel = 7;
+module_param_named(dump_loglevel, uv_nmi_loglevel, int, 0644);
+
+/*
+ * The following values show statistics on how perf events are affecting
+ * this system.
+ */
+static int param_get_local64(char *buffer, const struct kernel_param *kp)
+{
+	return sprintf(buffer, "%lu\n", local64_read((local64_t *)kp->arg));
+}
+
+static int param_set_local64(const char *val, const struct kernel_param *kp)
+{
+	/* clear on any write */
+	local64_set((local64_t *)kp->arg, 0);
+	return 0;
+}
+
+static struct kernel_param_ops param_ops_local64 = {
+	.get = param_get_local64,
+	.set = param_set_local64,
+};
+#define param_check_local64(name, p) __param_check(name, p, local64_t)
+
+static local64_t uv_nmi_count;
+module_param_named(nmi_count, uv_nmi_count, local64, 0644);
+
+static local64_t uv_nmi_misses;
+module_param_named(nmi_misses, uv_nmi_misses, local64, 0644);
+
+static local64_t uv_nmi_ping_count;
+module_param_named(ping_count, uv_nmi_ping_count, local64, 0644);
+
+static local64_t uv_nmi_ping_misses;
+module_param_named(ping_misses, uv_nmi_ping_misses, local64, 0644);
+
+/*
+ * Following values allow tuning for large systems under heavy loading
+ */
+static int uv_nmi_initial_delay = 100;
+module_param_named(initial_delay, uv_nmi_initial_delay, int, 0644);
+
+static int uv_nmi_slave_delay = 100;
+module_param_named(slave_delay, uv_nmi_slave_delay, int, 0644);
+
+static int uv_nmi_loop_delay = 100;
+module_param_named(loop_delay, uv_nmi_loop_delay, int, 0644);
+
+static int uv_nmi_trigger_delay = 10000;
+module_param_named(trigger_delay, uv_nmi_trigger_delay, int, 0644);
+
+static int uv_nmi_wait_count = 100;
+module_param_named(wait_count, uv_nmi_wait_count, int, 0644);
+
+static int uv_nmi_retry_count = 500;
+module_param_named(retry_count, uv_nmi_retry_count, int, 0644);
+
+/*
+ * Valid NMI Actions:
+ *  "dump"	- dump process stack for each cpu
+ *  "ips"	- dump IP info for each cpu
+ *  "kdump"	- do crash dump
+ *  "kdb"	- enter KDB/KGDB (default)
+ */
+static char uv_nmi_action[8] = "kdb";
+module_param_string(action, uv_nmi_action, sizeof(uv_nmi_action), 0644);
+
+static inline bool uv_nmi_action_is(const char *action)
+{
+	return (strncmp(uv_nmi_action, action, strlen(action)) == 0);
+}
+
+/* Setup which NMI support is present in system */
+static void uv_nmi_setup_mmrs(void)
+{
+	if (uv_read_local_mmr(UVH_NMI_MMRX_SUPPORTED)) {
+		uv_write_local_mmr(UVH_NMI_MMRX_REQ,
+					1UL << UVH_NMI_MMRX_REQ_SHIFT);
+		nmi_mmr = UVH_NMI_MMRX;
+		nmi_mmr_clear = UVH_NMI_MMRX_CLEAR;
+		nmi_mmr_pending = 1UL << UVH_NMI_MMRX_SHIFT;
+		pr_info("UV: SMI NMI support: %s\n", UVH_NMI_MMRX_TYPE);
+	} else {
+		nmi_mmr = UVH_NMI_MMR;
+		nmi_mmr_clear = UVH_NMI_MMR_CLEAR;
+		nmi_mmr_pending = 1UL << UVH_NMI_MMR_SHIFT;
+		pr_info("UV: SMI NMI support: %s\n", UVH_NMI_MMR_TYPE);
+	}
+}
+
+/* Read NMI MMR and check if NMI flag was set by BMC. */
+static inline int uv_nmi_test_mmr(struct uv_hub_nmi_s *hub_nmi)
+{
+	hub_nmi->nmi_value = uv_read_local_mmr(nmi_mmr);
+	atomic_inc(&hub_nmi->read_mmr_count);
+	return !!(hub_nmi->nmi_value & nmi_mmr_pending);
+}
+
+static inline void uv_local_mmr_clear_nmi(void)
+{
+	uv_write_local_mmr(nmi_mmr_clear, nmi_mmr_pending);
+}
+
+/*
+ * If first cpu in on this hub, set hub_nmi "in_nmi" and "owner" values and
+ * return true.  If first cpu in on the system, set global "in_nmi" flag.
+ */
+static int uv_set_in_nmi(int cpu, struct uv_hub_nmi_s *hub_nmi)
+{
+	int first = atomic_add_unless(&hub_nmi->in_nmi, 1, 1);
+
+	if (first) {
+		atomic_set(&hub_nmi->cpu_owner, cpu);
+		if (atomic_add_unless(&uv_in_nmi, 1, 1))
+			atomic_set(&uv_nmi_cpu, cpu);
+
+		atomic_inc(&hub_nmi->nmi_count);
+	}
+	return first;
+}
+
+/* Check if this is a system NMI event */
+static int uv_check_nmi(struct uv_hub_nmi_s *hub_nmi)
+{
+	int cpu = smp_processor_id();
+	int nmi = 0;
+
+	local64_inc(&uv_nmi_count);
+	uv_cpu_nmi.queries++;
+
+	do {
+		nmi = atomic_read(&hub_nmi->in_nmi);
+		if (nmi)
+			break;
+
+		if (raw_spin_trylock(&hub_nmi->nmi_lock)) {
+
+			/* check hub MMR NMI flag */
+			if (uv_nmi_test_mmr(hub_nmi)) {
+				uv_set_in_nmi(cpu, hub_nmi);
+				nmi = 1;
+				break;
+			}
+
+			/* MMR NMI flag is clear */
+			raw_spin_unlock(&hub_nmi->nmi_lock);
+
+		} else {
+			/* wait a moment for the hub nmi locker to set flag */
+			cpu_relax();
+			udelay(uv_nmi_slave_delay);
+
+			/* re-check hub in_nmi flag */
+			nmi = atomic_read(&hub_nmi->in_nmi);
+			if (nmi)
+				break;
+		}
+
+		/* check if this BMC missed setting the MMR NMI flag */
+		if (!nmi) {
+			nmi = atomic_read(&uv_in_nmi);
+			if (nmi)
+				uv_set_in_nmi(cpu, hub_nmi);
+		}
+
+	} while (0);
+
+	if (!nmi)
+		local64_inc(&uv_nmi_misses);
+
+	return nmi;
+}
+
+/* Need to reset the NMI MMR register, but only once per hub. */
+static inline void uv_clear_nmi(int cpu)
+{
+	struct uv_hub_nmi_s *hub_nmi = uv_hub_nmi;
+
+	if (cpu == atomic_read(&hub_nmi->cpu_owner)) {
+		atomic_set(&hub_nmi->cpu_owner, -1);
+		atomic_set(&hub_nmi->in_nmi, 0);
+		uv_local_mmr_clear_nmi();
+		raw_spin_unlock(&hub_nmi->nmi_lock);
+	}
+}
+
+/* Print non-responding cpus */
+static void uv_nmi_nr_cpus_pr(char *fmt)
+{
+	static char cpu_list[1024];
+	int len = sizeof(cpu_list);
+	int c = cpumask_weight(uv_nmi_cpu_mask);
+	int n = cpulist_scnprintf(cpu_list, len, uv_nmi_cpu_mask);
+
+	if (n >= len-1)
+		strcpy(&cpu_list[len - 6], "...\n");
+
+	printk(fmt, c, cpu_list);
+}
+
+/* Ping non-responding cpus attemping to force them into the NMI handler */
+static void uv_nmi_nr_cpus_ping(void)
+{
+	int cpu;
+
+	for_each_cpu(cpu, uv_nmi_cpu_mask)
+		atomic_set(&uv_cpu_nmi_per(cpu).pinging, 1);
+
+	apic->send_IPI_mask(uv_nmi_cpu_mask, APIC_DM_NMI);
+}
+
+/* Clean up flags for cpus that ignored both NMI and ping */
+static void uv_nmi_cleanup_mask(void)
+{
+	int cpu;
+
+	for_each_cpu(cpu, uv_nmi_cpu_mask) {
+		atomic_set(&uv_cpu_nmi_per(cpu).pinging, 0);
+		atomic_set(&uv_cpu_nmi_per(cpu).state, UV_NMI_STATE_OUT);
+		cpumask_clear_cpu(cpu, uv_nmi_cpu_mask);
+	}
+}
+
+/* Loop waiting as cpus enter nmi handler */
+static int uv_nmi_wait_cpus(int first)
+{
+	int i, j, k, n = num_online_cpus();
+	int last_k = 0, waiting = 0;
+
+	if (first) {
+		cpumask_copy(uv_nmi_cpu_mask, cpu_online_mask);
+		k = 0;
+	} else {
+		k = n - cpumask_weight(uv_nmi_cpu_mask);
+	}
+
+	udelay(uv_nmi_initial_delay);
+	for (i = 0; i < uv_nmi_retry_count; i++) {
+		int loop_delay = uv_nmi_loop_delay;
+
+		for_each_cpu(j, uv_nmi_cpu_mask) {
+			if (atomic_read(&uv_cpu_nmi_per(j).state)) {
+				cpumask_clear_cpu(j, uv_nmi_cpu_mask);
+				if (++k >= n)
+					break;
+			}
+		}
+		if (k >= n) {		/* all in? */
+			k = n;
+			break;
+		}
+		if (last_k != k) {	/* abort if no new cpus coming in */
+			last_k = k;
+			waiting = 0;
+		} else if (++waiting > uv_nmi_wait_count)
+			break;
+
+		/* extend delay if waiting only for cpu 0 */
+		if (waiting && (n - k) == 1 &&
+		    cpumask_test_cpu(0, uv_nmi_cpu_mask))
+			loop_delay *= 100;
+
+		udelay(loop_delay);
+	}
+	atomic_set(&uv_nmi_cpus_in_nmi, k);
+	return n - k;
+}
+
+/* Wait until all slave cpus have entered UV NMI handler */
+static void uv_nmi_wait(int master)
+{
+	/* indicate this cpu is in */
+	atomic_set(&uv_cpu_nmi.state, UV_NMI_STATE_IN);
+
+	/* if not the first cpu in (the master), then we are a slave cpu */
+	if (!master)
+		return;
+
+	do {
+		/* wait for all other cpus to gather here */
+		if (!uv_nmi_wait_cpus(1))
+			break;
+
+		/* if not all made it in, send IPI NMI to them */
+		uv_nmi_nr_cpus_pr(KERN_ALERT
+			"UV: Sending NMI IPI to %d non-responding CPUs: %s\n");
+		uv_nmi_nr_cpus_ping();
+
+		/* if all cpus are in, then done */
+		if (!uv_nmi_wait_cpus(0))
+			break;
+
+		uv_nmi_nr_cpus_pr(KERN_ALERT
+			"UV: %d CPUs not in NMI loop: %s\n");
+	} while (0);
+
+	pr_alert("UV: %d of %d CPUs in NMI\n",
+		atomic_read(&uv_nmi_cpus_in_nmi), num_online_cpus());
+}
+
+static void uv_nmi_dump_cpu_ip_hdr(void)
+{
+	printk(KERN_DEFAULT
+		"\nUV: %4s %6s %-32s %s   (Note: PID 0 not listed)\n",
+		"CPU", "PID", "COMMAND", "IP");
+}
+
+static void uv_nmi_dump_cpu_ip(int cpu, struct pt_regs *regs)
+{
+	printk(KERN_DEFAULT "UV: %4d %6d %-32.32s ",
+		cpu, current->pid, current->comm);
+
+	printk_address(regs->ip, 1);
+}
+
+/* Dump this cpu's state */
+static void uv_nmi_dump_state_cpu(int cpu, struct pt_regs *regs)
+{
+	const char *dots = " ................................. ";
+
+	if (uv_nmi_action_is("ips")) {
+		if (cpu == 0)
+			uv_nmi_dump_cpu_ip_hdr();
+
+		if (current->pid != 0)
+			uv_nmi_dump_cpu_ip(cpu, regs);
+
+	} else if (uv_nmi_action_is("dump")) {
+		printk(KERN_DEFAULT
+			"UV:%sNMI process trace for CPU %d\n", dots, cpu);
+		show_regs(regs);
+	}
+	atomic_set(&uv_cpu_nmi.state, UV_NMI_STATE_DUMP_DONE);
+}
+
+/* Trigger a slave cpu to dump it's state */
+static void uv_nmi_trigger_dump(int cpu)
+{
+	int retry = uv_nmi_trigger_delay;
+
+	if (atomic_read(&uv_cpu_nmi_per(cpu).state) != UV_NMI_STATE_IN)
+		return;
+
+	atomic_set(&uv_cpu_nmi_per(cpu).state, UV_NMI_STATE_DUMP);
+	do {
+		cpu_relax();
+		udelay(10);
+		if (atomic_read(&uv_cpu_nmi_per(cpu).state)
+				!= UV_NMI_STATE_DUMP)
+			return;
+	} while (--retry > 0);
+
+	pr_crit("UV: CPU %d stuck in process dump function\n", cpu);
+	atomic_set(&uv_cpu_nmi_per(cpu).state, UV_NMI_STATE_DUMP_DONE);
+}
+
+/* Wait until all cpus ready to exit */
+static void uv_nmi_sync_exit(int master)
+{
+	atomic_dec(&uv_nmi_cpus_in_nmi);
+	if (master) {
+		while (atomic_read(&uv_nmi_cpus_in_nmi) > 0)
+			cpu_relax();
+		atomic_set(&uv_nmi_slave_continue, SLAVE_CLEAR);
+	} else {
+		while (atomic_read(&uv_nmi_slave_continue))
+			cpu_relax();
+	}
+}
+
+/* Walk through cpu list and dump state of each */
+static void uv_nmi_dump_state(int cpu, struct pt_regs *regs, int master)
+{
+	if (master) {
+		int tcpu;
+		int ignored = 0;
+		int saved_console_loglevel = console_loglevel;
+
+		pr_alert("UV: tracing %s for %d CPUs from CPU %d\n",
+			uv_nmi_action_is("ips") ? "IPs" : "processes",
+			atomic_read(&uv_nmi_cpus_in_nmi), cpu);
+
+		console_loglevel = uv_nmi_loglevel;
+		atomic_set(&uv_nmi_slave_continue, SLAVE_EXIT);
+		for_each_online_cpu(tcpu) {
+			if (cpumask_test_cpu(tcpu, uv_nmi_cpu_mask))
+				ignored++;
+			else if (tcpu == cpu)
+				uv_nmi_dump_state_cpu(tcpu, regs);
+			else
+				uv_nmi_trigger_dump(tcpu);
+		}
+		if (ignored)
+			printk(KERN_DEFAULT "UV: %d CPUs ignored NMI\n",
+				ignored);
+
+		console_loglevel = saved_console_loglevel;
+		pr_alert("UV: process trace complete\n");
+	} else {
+		while (!atomic_read(&uv_nmi_slave_continue))
+			cpu_relax();
+		while (atomic_read(&uv_cpu_nmi.state) != UV_NMI_STATE_DUMP)
+			cpu_relax();
+		uv_nmi_dump_state_cpu(cpu, regs);
+	}
+	uv_nmi_sync_exit(master);
+}
+
+static void uv_nmi_touch_watchdogs(void)
+{
+	touch_softlockup_watchdog_sync();
+	clocksource_touch_watchdog();
+	rcu_cpu_stall_reset();
+	touch_nmi_watchdog();
+}
+
+#if defined(CONFIG_KEXEC)
+static void uv_nmi_kdump(int cpu, int master, struct pt_regs *regs)
+{
+	/* Call crash to dump system state */
+	if (master) {
+		pr_emerg("UV: NMI executing crash_kexec on CPU%d\n", cpu);
+		crash_kexec(regs);
+
+		pr_emerg("UV: crash_kexec unexpectedly returned, ");
+		if (!kexec_crash_image) {
+			pr_cont("crash kernel not loaded\n");
+			atomic_set(&uv_nmi_kexec_failed, 1);
+			uv_nmi_sync_exit(1);
+			return;
+		}
+		pr_cont("kexec busy, stalling cpus while waiting\n");
+	}
+
+	/* If crash exec fails the slaves should return, otherwise stall */
+	while (atomic_read(&uv_nmi_kexec_failed) == 0)
+		mdelay(10);
+
+	/* Crash kernel most likely not loaded, return in an orderly fashion */
+	uv_nmi_sync_exit(0);
+}
+
+#else /* !CONFIG_KEXEC */
+static inline void uv_nmi_kdump(int cpu, int master, struct pt_regs *regs)
+{
+	if (master)
+		pr_err("UV: NMI kdump: KEXEC not supported in this kernel\n");
+}
+#endif /* !CONFIG_KEXEC */
+
+#ifdef CONFIG_KGDB_KDB
+/* Call KDB from NMI handler */
+static void uv_call_kdb(int cpu, struct pt_regs *regs, int master)
+{
+	int ret;
+
+	if (master) {
+		/* call KGDB NMI handler as MASTER */
+		ret = kgdb_nmicallin(cpu, X86_TRAP_NMI, regs,
+					&uv_nmi_slave_continue);
+		if (ret) {
+			pr_alert("KDB returned error, is kgdboc set?\n");
+			atomic_set(&uv_nmi_slave_continue, SLAVE_EXIT);
+		}
+	} else {
+		/* wait for KGDB signal that it's ready for slaves to enter */
+		int sig;
+
+		do {
+			cpu_relax();
+			sig = atomic_read(&uv_nmi_slave_continue);
+		} while (!sig);
+
+		/* call KGDB as slave */
+		if (sig == SLAVE_CONTINUE)
+			kgdb_nmicallback(cpu, regs);
+	}
+	uv_nmi_sync_exit(master);
+}
+
+#else /* !CONFIG_KGDB_KDB */
+static inline void uv_call_kdb(int cpu, struct pt_regs *regs, int master)
+{
+	pr_err("UV: NMI error: KGDB/KDB is not enabled in this kernel\n");
+}
+#endif /* !CONFIG_KGDB_KDB */
+
+/*
+ * UV NMI handler
+ */
+int uv_handle_nmi(unsigned int reason, struct pt_regs *regs)
+{
+	struct uv_hub_nmi_s *hub_nmi = uv_hub_nmi;
+	int cpu = smp_processor_id();
+	int master = 0;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	/* If not a UV System NMI, ignore */
+	if (!atomic_read(&uv_cpu_nmi.pinging) && !uv_check_nmi(hub_nmi)) {
+		local_irq_restore(flags);
+		return NMI_DONE;
+	}
+
+	/* Indicate we are the first CPU into the NMI handler */
+	master = (atomic_read(&uv_nmi_cpu) == cpu);
+
+	/* If NMI action is "kdump", then attempt to do it */
+	if (uv_nmi_action_is("kdump"))
+		uv_nmi_kdump(cpu, master, regs);
+
+	/* Pause as all cpus enter the NMI handler */
+	uv_nmi_wait(master);
+
+	/* Dump state of each cpu */
+	if (uv_nmi_action_is("ips") || uv_nmi_action_is("dump"))
+		uv_nmi_dump_state(cpu, regs, master);
+
+	/* Call KDB if enabled */
+	else if (uv_nmi_action_is("kdb"))
+		uv_call_kdb(cpu, regs, master);
+
+	/* Clear per_cpu "in nmi" flag */
+	atomic_set(&uv_cpu_nmi.state, UV_NMI_STATE_OUT);
+
+	/* Clear MMR NMI flag on each hub */
+	uv_clear_nmi(cpu);
+
+	/* Clear global flags */
+	if (master) {
+		if (cpumask_weight(uv_nmi_cpu_mask))
+			uv_nmi_cleanup_mask();
+		atomic_set(&uv_nmi_cpus_in_nmi, -1);
+		atomic_set(&uv_nmi_cpu, -1);
+		atomic_set(&uv_in_nmi, 0);
+	}
+
+	uv_nmi_touch_watchdogs();
+	local_irq_restore(flags);
+
+	return NMI_HANDLED;
+}
+
+/*
+ * NMI handler for pulling in CPUs when perf events are grabbing our NMI
+ */
+int uv_handle_nmi_ping(unsigned int reason, struct pt_regs *regs)
+{
+	int ret;
+
+	uv_cpu_nmi.queries++;
+	if (!atomic_read(&uv_cpu_nmi.pinging)) {
+		local64_inc(&uv_nmi_ping_misses);
+		return NMI_DONE;
+	}
+
+	uv_cpu_nmi.pings++;
+	local64_inc(&uv_nmi_ping_count);
+	ret = uv_handle_nmi(reason, regs);
+	atomic_set(&uv_cpu_nmi.pinging, 0);
+	return ret;
+}
+
+void uv_register_nmi_notifier(void)
+{
+	if (register_nmi_handler(NMI_UNKNOWN, uv_handle_nmi, 0, "uv"))
+		pr_warn("UV: NMI handler failed to register\n");
+
+	if (register_nmi_handler(NMI_LOCAL, uv_handle_nmi_ping, 0, "uvping"))
+		pr_warn("UV: PING NMI handler failed to register\n");
+}
+
+void uv_nmi_init(void)
+{
+	unsigned int value;
+
+	/*
+	 * Unmask NMI on all cpus
+	 */
+	value = apic_read(APIC_LVT1) | APIC_DM_NMI;
+	value &= ~APIC_LVT_MASKED;
+	apic_write(APIC_LVT1, value);
+}
+
+void uv_nmi_setup(void)
+{
+	int size = sizeof(void *) * (1 << NODES_SHIFT);
+	int cpu, nid;
+
+	/* Setup hub nmi info */
+	uv_nmi_setup_mmrs();
+	uv_hub_nmi_list = kzalloc(size, GFP_KERNEL);
+	pr_info("UV: NMI hub list @ 0x%p (%d)\n", uv_hub_nmi_list, size);
+	BUG_ON(!uv_hub_nmi_list);
+	size = sizeof(struct uv_hub_nmi_s);
+	for_each_present_cpu(cpu) {
+		nid = cpu_to_node(cpu);
+		if (uv_hub_nmi_list[nid] == NULL) {
+			uv_hub_nmi_list[nid] = kzalloc_node(size,
+							    GFP_KERNEL, nid);
+			BUG_ON(!uv_hub_nmi_list[nid]);
+			raw_spin_lock_init(&(uv_hub_nmi_list[nid]->nmi_lock));
+			atomic_set(&uv_hub_nmi_list[nid]->cpu_owner, -1);
+		}
+		uv_hub_nmi_per(cpu) = uv_hub_nmi_list[nid];
+	}
+	BUG_ON(!alloc_cpumask_var(&uv_nmi_cpu_mask, GFP_KERNEL));
+}
+
+
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index d1e4777..31d0475 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -278,6 +278,15 @@
 		   old memory can be recycled */
 		make_lowmem_page_readwrite(xen_initial_gdt);
 
+#ifdef CONFIG_X86_32
+		/*
+		 * Xen starts us with XEN_FLAT_RING1_DS, but linux code
+		 * expects __USER_DS
+		 */
+		loadsegment(ds, __USER_DS);
+		loadsegment(es, __USER_DS);
+#endif
+
 		xen_filter_cpu_maps();
 		xen_setup_vcpu_info_placement();
 	}
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 1b98264..228d6ae 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -28,3 +28,4 @@
 generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += xor.h
+generic-y += preempt.h
diff --git a/arch/xtensa/include/asm/prom.h b/arch/xtensa/include/asm/prom.h
deleted file mode 100644
index f3d7cd2..0000000
--- a/arch/xtensa/include/asm/prom.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _XTENSA_ASM_PROM_H
-#define _XTENSA_ASM_PROM_H
-
-#define HAVE_ARCH_DEVTREE_FIXUPS
-
-#endif /* _XTENSA_ASM_PROM_H */
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index de1dfa1..21dbe6b 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -1122,7 +1122,7 @@
  * a3: exctable, original value in excsave1
  */
 
-fast_syscall_spill_registers_fixup:
+ENTRY(fast_syscall_spill_registers_fixup)
 
 	rsr	a2, windowbase	# get current windowbase (a2 is saved)
 	xsr	a0, depc	# restore depc and a0
@@ -1134,22 +1134,26 @@
 	 */
 
 	xsr	a3, excsave1	# get spill-mask
-	slli	a2, a3, 1	# shift left by one
+	slli	a3, a3, 1	# shift left by one
 
-	slli	a3, a2, 32-WSBITS
-	src	a2, a2, a3	# a1 = xxwww1yyxxxwww1yy......
+	slli	a2, a3, 32-WSBITS
+	src	a2, a3, a2	# a2 = xxwww1yyxxxwww1yy......
 	wsr	a2, windowstart	# set corrected windowstart
 
-	rsr	a3, excsave1
-	l32i	a2, a3, EXC_TABLE_DOUBLE_SAVE	# restore a2
-	l32i	a3, a3, EXC_TABLE_PARAM	# original WB (in user task)
+	srli	a3, a3, 1
+	rsr	a2, excsave1
+	l32i	a2, a2, EXC_TABLE_DOUBLE_SAVE	# restore a2
+	xsr	a2, excsave1
+	s32i	a3, a2, EXC_TABLE_DOUBLE_SAVE	# save a3
+	l32i	a3, a2, EXC_TABLE_PARAM	# original WB (in user task)
+	xsr	a2, excsave1
 
 	/* Return to the original (user task) WINDOWBASE.
 	 * We leave the following frame behind:
 	 * a0, a1, a2	same
-	 * a3:		trashed (saved in excsave_1)
+	 * a3:		trashed (saved in EXC_TABLE_DOUBLE_SAVE)
 	 * depc:	depc (we have to return to that address)
-	 * excsave_1:	a3
+	 * excsave_1:	exctable
 	 */
 
 	wsr	a3, windowbase
@@ -1159,9 +1163,9 @@
 	 *  a0: return address
 	 *  a1: used, stack pointer
 	 *  a2: kernel stack pointer
-	 *  a3: available, saved in EXCSAVE_1
+	 *  a3: available
 	 *  depc: exception address
-	 *  excsave: a3
+	 *  excsave: exctable
 	 * Note: This frame might be the same as above.
 	 */
 
@@ -1181,9 +1185,12 @@
 	rsr	a0, exccause
 	addx4	a0, a0, a3              	# find entry in table
 	l32i	a0, a0, EXC_TABLE_FAST_USER     # load handler
+	l32i	a3, a3, EXC_TABLE_DOUBLE_SAVE
 	jx	a0
 
-fast_syscall_spill_registers_fixup_return:
+ENDPROC(fast_syscall_spill_registers_fixup)
+
+ENTRY(fast_syscall_spill_registers_fixup_return)
 
 	/* When we return here, all registers have been restored (a2: DEPC) */
 
@@ -1191,13 +1198,13 @@
 
 	/* Restore fixup handler. */
 
-	xsr	a3, excsave1
-	movi	a2, fast_syscall_spill_registers_fixup
-	s32i	a2, a3, EXC_TABLE_FIXUP
-	s32i	a0, a3, EXC_TABLE_DOUBLE_SAVE
-	rsr	a2, windowbase
-	s32i	a2, a3, EXC_TABLE_PARAM
-	l32i	a2, a3, EXC_TABLE_KSTK
+	rsr	a2, excsave1
+	s32i	a3, a2, EXC_TABLE_DOUBLE_SAVE
+	movi	a3, fast_syscall_spill_registers_fixup
+	s32i	a3, a2, EXC_TABLE_FIXUP
+	rsr	a3, windowbase
+	s32i	a3, a2, EXC_TABLE_PARAM
+	l32i	a2, a2, EXC_TABLE_KSTK
 
 	/* Load WB at the time the exception occurred. */
 
@@ -1206,8 +1213,12 @@
 	wsr	a3, windowbase
 	rsync
 
+	rsr	a3, excsave1
+	l32i	a3, a3, EXC_TABLE_DOUBLE_SAVE
+
 	rfde
 
+ENDPROC(fast_syscall_spill_registers_fixup_return)
 
 /*
  * spill all registers.
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 946fb8d..6e2b663 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -21,11 +21,8 @@
 #include <linux/screen_info.h>
 #include <linux/bootmem.h>
 #include <linux/kernel.h>
-
-#ifdef CONFIG_OF
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
-#endif
 
 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
 # include <linux/console.h>
@@ -64,8 +61,8 @@
 struct rtc_ops *rtc_ops;
 
 #ifdef CONFIG_BLK_DEV_INITRD
-extern void *initrd_start;
-extern void *initrd_end;
+extern unsigned long initrd_start;
+extern unsigned long initrd_end;
 int initrd_is_mapped = 0;
 extern int initrd_below_start_ok;
 #endif
@@ -152,8 +149,8 @@
 {
 	meminfo_t* mi;
 	mi = (meminfo_t*)(tag->data);
-	initrd_start = __va(mi->start);
-	initrd_end = __va(mi->end);
+	initrd_start = (unsigned long)__va(mi->start);
+	initrd_end = (unsigned long)__va(mi->end);
 
 	return 0;
 }
@@ -170,13 +167,6 @@
 
 __tagtable(BP_TAG_FDT, parse_tag_fdt);
 
-void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
-{
-	initrd_start = (void *)__va(start);
-	initrd_end = (void *)__va(end);
-	initrd_below_start_ok = 1;
-}
-
 #endif /* CONFIG_OF */
 
 #endif /* CONFIG_BLK_DEV_INITRD */
@@ -222,9 +212,13 @@
 }
 
 #ifdef CONFIG_OF
+bool __initdata dt_memory_scan = false;
 
 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
 {
+	if (!dt_memory_scan)
+		return;
+
 	size &= PAGE_MASK;
 	add_sysmem_bank(MEMORY_TYPE_CONVENTIONAL, base, base + size);
 }
@@ -236,31 +230,13 @@
 
 void __init early_init_devtree(void *params)
 {
-	/* Setup flat device-tree pointer */
-	initial_boot_params = params;
-
-	/* Retrieve various informations from the /chosen node of the
-	 * device-tree, including the platform type, initrd location and
-	 * size, TCE reserve, and more ...
-	 */
-	if (!command_line[0])
-		of_scan_flat_dt(early_init_dt_scan_chosen, command_line);
-
-	/* Scan memory nodes and rebuild MEMBLOCKs */
-	of_scan_flat_dt(early_init_dt_scan_root, NULL);
 	if (sysmem.nr_banks == 0)
-		of_scan_flat_dt(early_init_dt_scan_memory, NULL);
-}
+		dt_memory_scan = true;
 
-static void __init copy_devtree(void)
-{
-	void *alloc = early_init_dt_alloc_memory_arch(
-			be32_to_cpu(initial_boot_params->totalsize), 8);
-	if (alloc) {
-		memcpy(alloc, initial_boot_params,
-				be32_to_cpu(initial_boot_params->totalsize));
-		initial_boot_params = alloc;
-	}
+	early_init_dt_scan(params);
+
+	if (!command_line[0])
+		strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
 }
 
 static int __init xtensa_device_probe(void)
@@ -525,10 +501,7 @@
 
 	bootmem_init();
 
-#ifdef CONFIG_OF
-	copy_devtree();
-	unflatten_device_tree();
-#endif
+	unflatten_and_copy_device_tree();
 
 	platform_setup(cmdline_p);
 
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index 718eca1..98b67d5 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -341,7 +341,7 @@
 
 	sp = regs->areg[1];
 
-	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) {
+	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && sas_ss_flags(sp) == 0) {
 		sp = current->sas_ss_sp + current->sas_ss_size;
 	}
 
diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c
index 56f88b7..e9e1aad 100644
--- a/arch/xtensa/platforms/iss/network.c
+++ b/arch/xtensa/platforms/iss/network.c
@@ -737,7 +737,8 @@
 		return 1;
 	}
 
-	if ((new = alloc_bootmem(sizeof new)) == NULL) {
+	new = alloc_bootmem(sizeof(*new));
+	if (new == NULL) {
 		printk("Alloc_bootmem failed\n");
 		return 1;
 	}
diff --git a/block/partitions/efi.c b/block/partitions/efi.c
index 1eb09ee..a8287b4 100644
--- a/block/partitions/efi.c
+++ b/block/partitions/efi.c
@@ -222,11 +222,16 @@
 	 * the disk size.
 	 *
 	 * Hybrid MBRs do not necessarily comply with this.
+	 *
+	 * Consider a bad value here to be a warning to support dd'ing
+	 * an image from a smaller disk to a larger disk.
 	 */
 	if (ret == GPT_MBR_PROTECTIVE) {
 		sz = le32_to_cpu(mbr->partition_record[part].size_in_lba);
 		if (sz != (uint32_t) total_sectors - 1 && sz != 0xFFFFFFFF)
-			ret = 0;
+			pr_debug("GPT: mbr size in lba (%u) different than whole disk (%u).\n",
+				 sz, min_t(uint32_t,
+					   total_sectors - 1, 0xFFFFFFFF));
 	}
 done:
 	return ret;
diff --git a/drivers/Kconfig b/drivers/Kconfig
index aa43b91..8f45144 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -166,4 +166,6 @@
 
 source "drivers/fmc/Kconfig"
 
+source "drivers/phy/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index ab93de8..687da89 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -8,6 +8,8 @@
 obj-y				+= irqchip/
 obj-y				+= bus/
 
+obj-$(CONFIG_GENERIC_PHY)	+= phy/
+
 # GPIO must come after pinctrl as gpios may need to mux pins etc
 obj-y				+= pinctrl/
 obj-y				+= gpio/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 22327e6..e11faae 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -24,7 +24,7 @@
 	  are configured, ACPI is used.
 
 	  The project home page for the Linux ACPI subsystem is here:
-	  <http://www.lesswatts.org/projects/acpi/>
+	  <https://01.org/linux-acpi>
 
 	  Linux support for ACPI is based on Intel Corporation's ACPI
 	  Component Architecture (ACPI CA).  For more information on the
@@ -123,9 +123,9 @@
 	default y
 	help
 	  This driver handles events on the power, sleep, and lid buttons.
-	  A daemon reads /proc/acpi/event and perform user-defined actions
-	  such as shutting down the system.  This is necessary for
-	  software-controlled poweroff.
+	  A daemon reads events from input devices or via netlink and
+	  performs user-defined actions such as shutting down the system.
+	  This is necessary for software-controlled poweroff.
 
 	  To compile this driver as a module, choose M here:
 	  the module will be called button.
@@ -372,4 +372,25 @@
 
 source "drivers/acpi/apei/Kconfig"
 
+config ACPI_EXTLOG
+	tristate "Extended Error Log support"
+	depends on X86_MCE && X86_LOCAL_APIC
+	select EFI
+	select UEFI_CPER
+	default n
+	help
+	  Certain usages such as Predictive Failure Analysis (PFA) require
+	  more information about the error than what can be described in
+	  processor machine check banks. Most server processors log
+	  additional information about the error in processor uncore
+	  registers. Since the addresses and layout of these registers vary
+	  widely from one processor to another, system software cannot
+	  readily make use of them. To complicate matters further, some of
+	  the additional error information cannot be constructed without
+	  detailed knowledge about platform topology.
+
+	  Enhanced MCA Logging allows firmware to provide additional error
+	  information to system software, synchronous with MCE or CMCI. This
+	  driver adds support for that functionality.
+
 endif	# ACPI
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index cdaf68b..bce34af 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -82,3 +82,5 @@
 obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o
 
 obj-$(CONFIG_ACPI_APEI)		+= apei/
+
+obj-$(CONFIG_ACPI_EXTLOG)	+= acpi_extlog.o
diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c
new file mode 100644
index 0000000..a6869e1
--- /dev/null
+++ b/drivers/acpi/acpi_extlog.c
@@ -0,0 +1,327 @@
+/*
+ * Extended Error Log driver
+ *
+ * Copyright (C) 2013 Intel Corp.
+ * Author: Chen, Gong <gong.chen@intel.com>
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <acpi/acpi_bus.h>
+#include <linux/cper.h>
+#include <linux/ratelimit.h>
+#include <asm/cpu.h>
+#include <asm/mce.h>
+
+#include "apei/apei-internal.h"
+
+#define EXT_ELOG_ENTRY_MASK	GENMASK_ULL(51, 0) /* elog entry address mask */
+
+#define EXTLOG_DSM_REV		0x0
+#define	EXTLOG_FN_QUERY		0x0
+#define	EXTLOG_FN_ADDR		0x1
+
+#define FLAG_OS_OPTIN		BIT(0)
+#define EXTLOG_QUERY_L1_EXIST	BIT(1)
+#define ELOG_ENTRY_VALID	(1ULL<<63)
+#define ELOG_ENTRY_LEN		0x1000
+
+#define EMCA_BUG \
+	"Can not request iomem region <0x%016llx-0x%016llx> - eMCA disabled\n"
+
+struct extlog_l1_head {
+	u32 ver;	/* Header Version */
+	u32 hdr_len;	/* Header Length */
+	u64 total_len;	/* entire L1 Directory length including this header */
+	u64 elog_base;	/* MCA Error Log Directory base address */
+	u64 elog_len;	/* MCA Error Log Directory length */
+	u32 flags;	/* bit 0 - OS/VMM Opt-in */
+	u8  rev0[12];
+	u32 entries;	/* Valid L1 Directory entries per logical processor */
+	u8  rev1[12];
+};
+
+static u8 extlog_dsm_uuid[] = "663E35AF-CC10-41A4-88EA-5470AF055295";
+
+/* L1 table related physical address */
+static u64 elog_base;
+static size_t elog_size;
+static u64 l1_dirbase;
+static size_t l1_size;
+
+/* L1 table related virtual address */
+static void __iomem *extlog_l1_addr;
+static void __iomem *elog_addr;
+
+static void *elog_buf;
+
+static u64 *l1_entry_base;
+static u32 l1_percpu_entry;
+
+#define ELOG_IDX(cpu, bank) \
+	(cpu_physical_id(cpu) * l1_percpu_entry + (bank))
+
+#define ELOG_ENTRY_DATA(idx) \
+	(*(l1_entry_base + (idx)))
+
+#define ELOG_ENTRY_ADDR(phyaddr) \
+	(phyaddr - elog_base + (u8 *)elog_addr)
+
+static struct acpi_generic_status *extlog_elog_entry_check(int cpu, int bank)
+{
+	int idx;
+	u64 data;
+	struct acpi_generic_status *estatus;
+
+	WARN_ON(cpu < 0);
+	idx = ELOG_IDX(cpu, bank);
+	data = ELOG_ENTRY_DATA(idx);
+	if ((data & ELOG_ENTRY_VALID) == 0)
+		return NULL;
+
+	data &= EXT_ELOG_ENTRY_MASK;
+	estatus = (struct acpi_generic_status *)ELOG_ENTRY_ADDR(data);
+
+	/* if no valid data in elog entry, just return */
+	if (estatus->block_status == 0)
+		return NULL;
+
+	return estatus;
+}
+
+static void __print_extlog_rcd(const char *pfx,
+			       struct acpi_generic_status *estatus, int cpu)
+{
+	static atomic_t seqno;
+	unsigned int curr_seqno;
+	char pfx_seq[64];
+
+	if (!pfx) {
+		if (estatus->error_severity <= CPER_SEV_CORRECTED)
+			pfx = KERN_INFO;
+		else
+			pfx = KERN_ERR;
+	}
+	curr_seqno = atomic_inc_return(&seqno);
+	snprintf(pfx_seq, sizeof(pfx_seq), "%s{%u}", pfx, curr_seqno);
+	printk("%s""Hardware error detected on CPU%d\n", pfx_seq, cpu);
+	cper_estatus_print(pfx_seq, estatus);
+}
+
+static int print_extlog_rcd(const char *pfx,
+			    struct acpi_generic_status *estatus, int cpu)
+{
+	/* Not more than 2 messages every 5 seconds */
+	static DEFINE_RATELIMIT_STATE(ratelimit_corrected, 5*HZ, 2);
+	static DEFINE_RATELIMIT_STATE(ratelimit_uncorrected, 5*HZ, 2);
+	struct ratelimit_state *ratelimit;
+
+	if (estatus->error_severity == CPER_SEV_CORRECTED ||
+	    (estatus->error_severity == CPER_SEV_INFORMATIONAL))
+		ratelimit = &ratelimit_corrected;
+	else
+		ratelimit = &ratelimit_uncorrected;
+	if (__ratelimit(ratelimit)) {
+		__print_extlog_rcd(pfx, estatus, cpu);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int extlog_print(struct notifier_block *nb, unsigned long val,
+			void *data)
+{
+	struct mce *mce = (struct mce *)data;
+	int	bank = mce->bank;
+	int	cpu = mce->extcpu;
+	struct acpi_generic_status *estatus;
+	int rc;
+
+	estatus = extlog_elog_entry_check(cpu, bank);
+	if (estatus == NULL)
+		return NOTIFY_DONE;
+
+	memcpy(elog_buf, (void *)estatus, ELOG_ENTRY_LEN);
+	/* clear record status to enable BIOS to update it again */
+	estatus->block_status = 0;
+
+	rc = print_extlog_rcd(NULL, (struct acpi_generic_status *)elog_buf, cpu);
+
+	return NOTIFY_DONE;
+}
+
+static int extlog_get_dsm(acpi_handle handle, int rev, int func, u64 *ret)
+{
+	struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
+	struct acpi_object_list input;
+	union acpi_object params[4], *obj;
+	u8 uuid[16];
+	int i;
+
+	acpi_str_to_uuid(extlog_dsm_uuid, uuid);
+	input.count = 4;
+	input.pointer = params;
+	params[0].type = ACPI_TYPE_BUFFER;
+	params[0].buffer.length = 16;
+	params[0].buffer.pointer = uuid;
+	params[1].type = ACPI_TYPE_INTEGER;
+	params[1].integer.value = rev;
+	params[2].type = ACPI_TYPE_INTEGER;
+	params[2].integer.value = func;
+	params[3].type = ACPI_TYPE_PACKAGE;
+	params[3].package.count = 0;
+	params[3].package.elements = NULL;
+
+	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DSM", &input, &buf)))
+		return -1;
+
+	*ret = 0;
+	obj = (union acpi_object *)buf.pointer;
+	if (obj->type == ACPI_TYPE_INTEGER) {
+		*ret = obj->integer.value;
+	} else if (obj->type == ACPI_TYPE_BUFFER) {
+		if (obj->buffer.length <= 8) {
+			for (i = 0; i < obj->buffer.length; i++)
+				*ret |= (obj->buffer.pointer[i] << (i * 8));
+		}
+	}
+	kfree(buf.pointer);
+
+	return 0;
+}
+
+static bool extlog_get_l1addr(void)
+{
+	acpi_handle handle;
+	u64 ret;
+
+	if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
+		return false;
+
+	if (extlog_get_dsm(handle, EXTLOG_DSM_REV, EXTLOG_FN_QUERY, &ret) ||
+	    !(ret & EXTLOG_QUERY_L1_EXIST))
+		return false;
+
+	if (extlog_get_dsm(handle, EXTLOG_DSM_REV, EXTLOG_FN_ADDR, &ret))
+		return false;
+
+	l1_dirbase = ret;
+	/* Spec says L1 directory must be 4K aligned, bail out if it isn't */
+	if (l1_dirbase & ((1 << 12) - 1)) {
+		pr_warn(FW_BUG "L1 Directory is invalid at physical %llx\n",
+			l1_dirbase);
+		return false;
+	}
+
+	return true;
+}
+static struct notifier_block extlog_mce_dec = {
+	.notifier_call	= extlog_print,
+};
+
+static int __init extlog_init(void)
+{
+	struct extlog_l1_head *l1_head;
+	void __iomem *extlog_l1_hdr;
+	size_t l1_hdr_size;
+	struct resource *r;
+	u64 cap;
+	int rc;
+
+	rc = -ENODEV;
+
+	rdmsrl(MSR_IA32_MCG_CAP, cap);
+	if (!(cap & MCG_ELOG_P))
+		return rc;
+
+	if (!extlog_get_l1addr())
+		return rc;
+
+	rc = -EINVAL;
+	/* get L1 header to fetch necessary information */
+	l1_hdr_size = sizeof(struct extlog_l1_head);
+	r = request_mem_region(l1_dirbase, l1_hdr_size, "L1 DIR HDR");
+	if (!r) {
+		pr_warn(FW_BUG EMCA_BUG,
+			(unsigned long long)l1_dirbase,
+			(unsigned long long)l1_dirbase + l1_hdr_size);
+		goto err;
+	}
+
+	extlog_l1_hdr = acpi_os_map_memory(l1_dirbase, l1_hdr_size);
+	l1_head = (struct extlog_l1_head *)extlog_l1_hdr;
+	l1_size = l1_head->total_len;
+	l1_percpu_entry = l1_head->entries;
+	elog_base = l1_head->elog_base;
+	elog_size = l1_head->elog_len;
+	acpi_os_unmap_memory(extlog_l1_hdr, l1_hdr_size);
+	release_mem_region(l1_dirbase, l1_hdr_size);
+
+	/* remap L1 header again based on completed information */
+	r = request_mem_region(l1_dirbase, l1_size, "L1 Table");
+	if (!r) {
+		pr_warn(FW_BUG EMCA_BUG,
+			(unsigned long long)l1_dirbase,
+			(unsigned long long)l1_dirbase + l1_size);
+		goto err;
+	}
+	extlog_l1_addr = acpi_os_map_memory(l1_dirbase, l1_size);
+	l1_entry_base = (u64 *)((u8 *)extlog_l1_addr + l1_hdr_size);
+
+	/* remap elog table */
+	r = request_mem_region(elog_base, elog_size, "Elog Table");
+	if (!r) {
+		pr_warn(FW_BUG EMCA_BUG,
+			(unsigned long long)elog_base,
+			(unsigned long long)elog_base + elog_size);
+		goto err_release_l1_dir;
+	}
+	elog_addr = acpi_os_map_memory(elog_base, elog_size);
+
+	rc = -ENOMEM;
+	/* allocate buffer to save elog record */
+	elog_buf = kmalloc(ELOG_ENTRY_LEN, GFP_KERNEL);
+	if (elog_buf == NULL)
+		goto err_release_elog;
+
+	mce_register_decode_chain(&extlog_mce_dec);
+	/* enable OS to be involved to take over management from BIOS */
+	((struct extlog_l1_head *)extlog_l1_addr)->flags |= FLAG_OS_OPTIN;
+
+	return 0;
+
+err_release_elog:
+	if (elog_addr)
+		acpi_os_unmap_memory(elog_addr, elog_size);
+	release_mem_region(elog_base, elog_size);
+err_release_l1_dir:
+	if (extlog_l1_addr)
+		acpi_os_unmap_memory(extlog_l1_addr, l1_size);
+	release_mem_region(l1_dirbase, l1_size);
+err:
+	pr_warn(FW_BUG "Extended error log disabled because of problems parsing f/w tables\n");
+	return rc;
+}
+
+static void __exit extlog_exit(void)
+{
+	mce_unregister_decode_chain(&extlog_mce_dec);
+	((struct extlog_l1_head *)extlog_l1_addr)->flags &= ~FLAG_OS_OPTIN;
+	if (extlog_l1_addr)
+		acpi_os_unmap_memory(extlog_l1_addr, l1_size);
+	if (elog_addr)
+		acpi_os_unmap_memory(elog_addr, elog_size);
+	release_mem_region(elog_base, elog_size);
+	release_mem_region(l1_dirbase, l1_size);
+	kfree(elog_buf);
+}
+
+module_init(extlog_init);
+module_exit(extlog_exit);
+
+MODULE_AUTHOR("Chen, Gong <gong.chen@intel.com>");
+MODULE_DESCRIPTION("Extended MCA Error Log Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig
index f0c1ce9..786294b 100644
--- a/drivers/acpi/apei/Kconfig
+++ b/drivers/acpi/apei/Kconfig
@@ -2,6 +2,8 @@
 	bool "ACPI Platform Error Interface (APEI)"
 	select MISC_FILESYSTEMS
 	select PSTORE
+	select EFI
+	select UEFI_CPER
 	depends on X86
 	help
 	  APEI allows to report errors (for example from the chipset)
diff --git a/drivers/acpi/apei/Makefile b/drivers/acpi/apei/Makefile
index d1d1bc0..5d575a9 100644
--- a/drivers/acpi/apei/Makefile
+++ b/drivers/acpi/apei/Makefile
@@ -3,4 +3,4 @@
 obj-$(CONFIG_ACPI_APEI_EINJ)	+= einj.o
 obj-$(CONFIG_ACPI_APEI_ERST_DEBUG) += erst-dbg.o
 
-apei-y := apei-base.o hest.o cper.o erst.o
+apei-y := apei-base.o hest.o erst.o
diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h
index f220d64..21ba34a 100644
--- a/drivers/acpi/apei/apei-internal.h
+++ b/drivers/acpi/apei/apei-internal.h
@@ -122,11 +122,11 @@
 struct dentry *apei_get_debugfs_dir(void);
 
 #define apei_estatus_for_each_section(estatus, section)			\
-	for (section = (struct acpi_hest_generic_data *)(estatus + 1);	\
+	for (section = (struct acpi_generic_data *)(estatus + 1);	\
 	     (void *)section - (void *)estatus < estatus->data_length;	\
 	     section = (void *)(section+1) + section->error_data_length)
 
-static inline u32 apei_estatus_len(struct acpi_hest_generic_status *estatus)
+static inline u32 cper_estatus_len(struct acpi_generic_status *estatus)
 {
 	if (estatus->raw_data_length)
 		return estatus->raw_data_offset + \
@@ -135,10 +135,10 @@
 		return sizeof(*estatus) + estatus->data_length;
 }
 
-void apei_estatus_print(const char *pfx,
-			const struct acpi_hest_generic_status *estatus);
-int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus);
-int apei_estatus_check(const struct acpi_hest_generic_status *estatus);
+void cper_estatus_print(const char *pfx,
+			const struct acpi_generic_status *estatus);
+int cper_estatus_check_header(const struct acpi_generic_status *estatus);
+int cper_estatus_check(const struct acpi_generic_status *estatus);
 
 int apei_osc_setup(void);
 #endif
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 8ec37bb..a30bc31 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -75,13 +75,13 @@
 #define GHES_ESTATUS_CACHE_LEN(estatus_len)			\
 	(sizeof(struct ghes_estatus_cache) + (estatus_len))
 #define GHES_ESTATUS_FROM_CACHE(estatus_cache)			\
-	((struct acpi_hest_generic_status *)			\
+	((struct acpi_generic_status *)				\
 	 ((struct ghes_estatus_cache *)(estatus_cache) + 1))
 
 #define GHES_ESTATUS_NODE_LEN(estatus_len)			\
 	(sizeof(struct ghes_estatus_node) + (estatus_len))
-#define GHES_ESTATUS_FROM_NODE(estatus_node)				\
-	((struct acpi_hest_generic_status *)				\
+#define GHES_ESTATUS_FROM_NODE(estatus_node)			\
+	((struct acpi_generic_status *)				\
 	 ((struct ghes_estatus_node *)(estatus_node) + 1))
 
 bool ghes_disable;
@@ -378,17 +378,17 @@
 	ghes->flags |= GHES_TO_CLEAR;
 
 	rc = -EIO;
-	len = apei_estatus_len(ghes->estatus);
+	len = cper_estatus_len(ghes->estatus);
 	if (len < sizeof(*ghes->estatus))
 		goto err_read_block;
 	if (len > ghes->generic->error_block_length)
 		goto err_read_block;
-	if (apei_estatus_check_header(ghes->estatus))
+	if (cper_estatus_check_header(ghes->estatus))
 		goto err_read_block;
 	ghes_copy_tofrom_phys(ghes->estatus + 1,
 			      buf_paddr + sizeof(*ghes->estatus),
 			      len - sizeof(*ghes->estatus), 1);
-	if (apei_estatus_check(ghes->estatus))
+	if (cper_estatus_check(ghes->estatus))
 		goto err_read_block;
 	rc = 0;
 
@@ -409,7 +409,7 @@
 	ghes->flags &= ~GHES_TO_CLEAR;
 }
 
-static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int sev)
+static void ghes_handle_memory_failure(struct acpi_generic_data *gdata, int sev)
 {
 #ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE
 	unsigned long pfn;
@@ -419,7 +419,7 @@
 
 	if (sec_sev == GHES_SEV_CORRECTED &&
 	    (gdata->flags & CPER_SEC_ERROR_THRESHOLD_EXCEEDED) &&
-	    (mem_err->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS)) {
+	    (mem_err->validation_bits & CPER_MEM_VALID_PA)) {
 		pfn = mem_err->physical_addr >> PAGE_SHIFT;
 		if (pfn_valid(pfn))
 			memory_failure_queue(pfn, 0, MF_SOFT_OFFLINE);
@@ -430,7 +430,7 @@
 	}
 	if (sev == GHES_SEV_RECOVERABLE &&
 	    sec_sev == GHES_SEV_RECOVERABLE &&
-	    mem_err->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS) {
+	    mem_err->validation_bits & CPER_MEM_VALID_PA) {
 		pfn = mem_err->physical_addr >> PAGE_SHIFT;
 		memory_failure_queue(pfn, 0, 0);
 	}
@@ -438,10 +438,10 @@
 }
 
 static void ghes_do_proc(struct ghes *ghes,
-			 const struct acpi_hest_generic_status *estatus)
+			 const struct acpi_generic_status *estatus)
 {
 	int sev, sec_sev;
-	struct acpi_hest_generic_data *gdata;
+	struct acpi_generic_data *gdata;
 
 	sev = ghes_severity(estatus->error_severity);
 	apei_estatus_for_each_section(estatus, gdata) {
@@ -496,7 +496,7 @@
 
 static void __ghes_print_estatus(const char *pfx,
 				 const struct acpi_hest_generic *generic,
-				 const struct acpi_hest_generic_status *estatus)
+				 const struct acpi_generic_status *estatus)
 {
 	static atomic_t seqno;
 	unsigned int curr_seqno;
@@ -513,12 +513,12 @@
 	snprintf(pfx_seq, sizeof(pfx_seq), "%s{%u}" HW_ERR, pfx, curr_seqno);
 	printk("%s""Hardware error from APEI Generic Hardware Error Source: %d\n",
 	       pfx_seq, generic->header.source_id);
-	apei_estatus_print(pfx_seq, estatus);
+	cper_estatus_print(pfx_seq, estatus);
 }
 
 static int ghes_print_estatus(const char *pfx,
 			      const struct acpi_hest_generic *generic,
-			      const struct acpi_hest_generic_status *estatus)
+			      const struct acpi_generic_status *estatus)
 {
 	/* Not more than 2 messages every 5 seconds */
 	static DEFINE_RATELIMIT_STATE(ratelimit_corrected, 5*HZ, 2);
@@ -540,15 +540,15 @@
  * GHES error status reporting throttle, to report more kinds of
  * errors, instead of just most frequently occurred errors.
  */
-static int ghes_estatus_cached(struct acpi_hest_generic_status *estatus)
+static int ghes_estatus_cached(struct acpi_generic_status *estatus)
 {
 	u32 len;
 	int i, cached = 0;
 	unsigned long long now;
 	struct ghes_estatus_cache *cache;
-	struct acpi_hest_generic_status *cache_estatus;
+	struct acpi_generic_status *cache_estatus;
 
-	len = apei_estatus_len(estatus);
+	len = cper_estatus_len(estatus);
 	rcu_read_lock();
 	for (i = 0; i < GHES_ESTATUS_CACHES_SIZE; i++) {
 		cache = rcu_dereference(ghes_estatus_caches[i]);
@@ -571,19 +571,19 @@
 
 static struct ghes_estatus_cache *ghes_estatus_cache_alloc(
 	struct acpi_hest_generic *generic,
-	struct acpi_hest_generic_status *estatus)
+	struct acpi_generic_status *estatus)
 {
 	int alloced;
 	u32 len, cache_len;
 	struct ghes_estatus_cache *cache;
-	struct acpi_hest_generic_status *cache_estatus;
+	struct acpi_generic_status *cache_estatus;
 
 	alloced = atomic_add_return(1, &ghes_estatus_cache_alloced);
 	if (alloced > GHES_ESTATUS_CACHE_ALLOCED_MAX) {
 		atomic_dec(&ghes_estatus_cache_alloced);
 		return NULL;
 	}
-	len = apei_estatus_len(estatus);
+	len = cper_estatus_len(estatus);
 	cache_len = GHES_ESTATUS_CACHE_LEN(len);
 	cache = (void *)gen_pool_alloc(ghes_estatus_pool, cache_len);
 	if (!cache) {
@@ -603,7 +603,7 @@
 {
 	u32 len;
 
-	len = apei_estatus_len(GHES_ESTATUS_FROM_CACHE(cache));
+	len = cper_estatus_len(GHES_ESTATUS_FROM_CACHE(cache));
 	len = GHES_ESTATUS_CACHE_LEN(len);
 	gen_pool_free(ghes_estatus_pool, (unsigned long)cache, len);
 	atomic_dec(&ghes_estatus_cache_alloced);
@@ -619,7 +619,7 @@
 
 static void ghes_estatus_cache_add(
 	struct acpi_hest_generic *generic,
-	struct acpi_hest_generic_status *estatus)
+	struct acpi_generic_status *estatus)
 {
 	int i, slot = -1, count;
 	unsigned long long now, duration, period, max_period = 0;
@@ -751,7 +751,7 @@
 	struct llist_node *llnode, *next;
 	struct ghes_estatus_node *estatus_node;
 	struct acpi_hest_generic *generic;
-	struct acpi_hest_generic_status *estatus;
+	struct acpi_generic_status *estatus;
 	u32 len, node_len;
 
 	llnode = llist_del_all(&ghes_estatus_llist);
@@ -765,7 +765,7 @@
 		estatus_node = llist_entry(llnode, struct ghes_estatus_node,
 					   llnode);
 		estatus = GHES_ESTATUS_FROM_NODE(estatus_node);
-		len = apei_estatus_len(estatus);
+		len = cper_estatus_len(estatus);
 		node_len = GHES_ESTATUS_NODE_LEN(len);
 		ghes_do_proc(estatus_node->ghes, estatus);
 		if (!ghes_estatus_cached(estatus)) {
@@ -784,7 +784,7 @@
 	struct llist_node *llnode;
 	struct ghes_estatus_node *estatus_node;
 	struct acpi_hest_generic *generic;
-	struct acpi_hest_generic_status *estatus;
+	struct acpi_generic_status *estatus;
 	u32 len, node_len;
 
 	llnode = llist_del_all(&ghes_estatus_llist);
@@ -797,7 +797,7 @@
 		estatus_node = llist_entry(llnode, struct ghes_estatus_node,
 					   llnode);
 		estatus = GHES_ESTATUS_FROM_NODE(estatus_node);
-		len = apei_estatus_len(estatus);
+		len = cper_estatus_len(estatus);
 		node_len = GHES_ESTATUS_NODE_LEN(len);
 		generic = estatus_node->generic;
 		ghes_print_estatus(NULL, generic, estatus);
@@ -843,7 +843,7 @@
 #ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
 		u32 len, node_len;
 		struct ghes_estatus_node *estatus_node;
-		struct acpi_hest_generic_status *estatus;
+		struct acpi_generic_status *estatus;
 #endif
 		if (!(ghes->flags & GHES_TO_CLEAR))
 			continue;
@@ -851,7 +851,7 @@
 		if (ghes_estatus_cached(ghes->estatus))
 			goto next;
 		/* Save estatus for further processing in IRQ context */
-		len = apei_estatus_len(ghes->estatus);
+		len = cper_estatus_len(ghes->estatus);
 		node_len = GHES_ESTATUS_NODE_LEN(len);
 		estatus_node = (void *)gen_pool_alloc(ghes_estatus_pool,
 						      node_len);
@@ -923,7 +923,7 @@
 
 	rc = -EIO;
 	if (generic->error_block_length <
-	    sizeof(struct acpi_hest_generic_status)) {
+	    sizeof(struct acpi_generic_status)) {
 		pr_warning(FW_BUG GHES_PFX "Invalid error block length: %u for generic hardware error source: %d\n",
 			   generic->error_block_length,
 			   generic->header.source_id);
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index b587ec8..e1bd9a1 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -174,7 +174,7 @@
 	printk("\n");
 }
 
-static acpi_status acpi_str_to_uuid(char *str, u8 *uuid)
+acpi_status acpi_str_to_uuid(char *str, u8 *uuid)
 {
 	int i;
 	static int opc_map_to_uuid[16] = {6, 4, 2, 0, 11, 9, 16, 14, 19, 21,
@@ -195,6 +195,7 @@
 	}
 	return AE_OK;
 }
+EXPORT_SYMBOL_GPL(acpi_str_to_uuid);
 
 acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context)
 {
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index 59d3202..a94383d 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -1025,60 +1025,4 @@
 	}
 }
 EXPORT_SYMBOL_GPL(acpi_dev_pm_detach);
-
-/**
- * acpi_dev_pm_add_dependent - Add physical device depending for PM.
- * @handle: Handle of ACPI device node.
- * @depdev: Device depending on that node for PM.
- */
-void acpi_dev_pm_add_dependent(acpi_handle handle, struct device *depdev)
-{
-	struct acpi_device_physical_node *dep;
-	struct acpi_device *adev;
-
-	if (!depdev || acpi_bus_get_device(handle, &adev))
-		return;
-
-	mutex_lock(&adev->physical_node_lock);
-
-	list_for_each_entry(dep, &adev->power_dependent, node)
-		if (dep->dev == depdev)
-			goto out;
-
-	dep = kzalloc(sizeof(*dep), GFP_KERNEL);
-	if (dep) {
-		dep->dev = depdev;
-		list_add_tail(&dep->node, &adev->power_dependent);
-	}
-
- out:
-	mutex_unlock(&adev->physical_node_lock);
-}
-EXPORT_SYMBOL_GPL(acpi_dev_pm_add_dependent);
-
-/**
- * acpi_dev_pm_remove_dependent - Remove physical device depending for PM.
- * @handle: Handle of ACPI device node.
- * @depdev: Device depending on that node for PM.
- */
-void acpi_dev_pm_remove_dependent(acpi_handle handle, struct device *depdev)
-{
-	struct acpi_device_physical_node *dep;
-	struct acpi_device *adev;
-
-	if (!depdev || acpi_bus_get_device(handle, &adev))
-		return;
-
-	mutex_lock(&adev->physical_node_lock);
-
-	list_for_each_entry(dep, &adev->power_dependent, node)
-		if (dep->dev == depdev) {
-			list_del(&dep->node);
-			kfree(dep);
-			break;
-		}
-
-	mutex_unlock(&adev->physical_node_lock);
-}
-EXPORT_SYMBOL_GPL(acpi_dev_pm_remove_dependent);
 #endif /* CONFIG_PM */
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 0dbe5cd..c2ad391 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -59,16 +59,9 @@
 #define ACPI_POWER_RESOURCE_STATE_ON	0x01
 #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
 
-struct acpi_power_dependent_device {
-	struct list_head node;
-	struct acpi_device *adev;
-	struct work_struct work;
-};
-
 struct acpi_power_resource {
 	struct acpi_device device;
 	struct list_head list_node;
-	struct list_head dependent;
 	char *name;
 	u32 system_level;
 	u32 order;
@@ -233,32 +226,6 @@
 	return 0;
 }
 
-static void acpi_power_resume_dependent(struct work_struct *work)
-{
-	struct acpi_power_dependent_device *dep;
-	struct acpi_device_physical_node *pn;
-	struct acpi_device *adev;
-	int state;
-
-	dep = container_of(work, struct acpi_power_dependent_device, work);
-	adev = dep->adev;
-	if (acpi_power_get_inferred_state(adev, &state))
-		return;
-
-	if (state > ACPI_STATE_D0)
-		return;
-
-	mutex_lock(&adev->physical_node_lock);
-
-	list_for_each_entry(pn, &adev->physical_node_list, node)
-		pm_request_resume(pn->dev);
-
-	list_for_each_entry(pn, &adev->power_dependent, node)
-		pm_request_resume(pn->dev);
-
-	mutex_unlock(&adev->physical_node_lock);
-}
-
 static int __acpi_power_on(struct acpi_power_resource *resource)
 {
 	acpi_status status = AE_OK;
@@ -283,14 +250,8 @@
 				  resource->name));
 	} else {
 		result = __acpi_power_on(resource);
-		if (result) {
+		if (result)
 			resource->ref_count--;
-		} else {
-			struct acpi_power_dependent_device *dep;
-
-			list_for_each_entry(dep, &resource->dependent, node)
-				schedule_work(&dep->work);
-		}
 	}
 	return result;
 }
@@ -390,52 +351,6 @@
 	return result;
 }
 
-static void acpi_power_add_dependent(struct acpi_power_resource *resource,
-				     struct acpi_device *adev)
-{
-	struct acpi_power_dependent_device *dep;
-
-	mutex_lock(&resource->resource_lock);
-
-	list_for_each_entry(dep, &resource->dependent, node)
-		if (dep->adev == adev)
-			goto out;
-
-	dep = kzalloc(sizeof(*dep), GFP_KERNEL);
-	if (!dep)
-		goto out;
-
-	dep->adev = adev;
-	INIT_WORK(&dep->work, acpi_power_resume_dependent);
-	list_add_tail(&dep->node, &resource->dependent);
-
- out:
-	mutex_unlock(&resource->resource_lock);
-}
-
-static void acpi_power_remove_dependent(struct acpi_power_resource *resource,
-					struct acpi_device *adev)
-{
-	struct acpi_power_dependent_device *dep;
-	struct work_struct *work = NULL;
-
-	mutex_lock(&resource->resource_lock);
-
-	list_for_each_entry(dep, &resource->dependent, node)
-		if (dep->adev == adev) {
-			list_del(&dep->node);
-			work = &dep->work;
-			break;
-		}
-
-	mutex_unlock(&resource->resource_lock);
-
-	if (work) {
-		cancel_work_sync(work);
-		kfree(dep);
-	}
-}
-
 static struct attribute *attrs[] = {
 	NULL,
 };
@@ -524,8 +439,6 @@
 
 void acpi_power_add_remove_device(struct acpi_device *adev, bool add)
 {
-	struct acpi_device_power_state *ps;
-	struct acpi_power_resource_entry *entry;
 	int state;
 
 	if (adev->wakeup.flags.valid)
@@ -535,16 +448,6 @@
 	if (!adev->power.flags.power_resources)
 		return;
 
-	ps = &adev->power.states[ACPI_STATE_D0];
-	list_for_each_entry(entry, &ps->resources, node) {
-		struct acpi_power_resource *resource = entry->resource;
-
-		if (add)
-			acpi_power_add_dependent(resource, adev);
-		else
-			acpi_power_remove_dependent(resource, adev);
-	}
-
 	for (state = ACPI_STATE_D0; state <= ACPI_STATE_D3_HOT; state++)
 		acpi_power_expose_hide(adev,
 				       &adev->power.states[state].resources,
@@ -882,7 +785,6 @@
 	acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER,
 				ACPI_STA_DEFAULT);
 	mutex_init(&resource->resource_lock);
-	INIT_LIST_HEAD(&resource->dependent);
 	INIT_LIST_HEAD(&resource->list_node);
 	resource->name = device->pnp.bus_id;
 	strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
@@ -936,8 +838,10 @@
 		mutex_lock(&resource->resource_lock);
 
 		result = acpi_power_get_state(resource->device.handle, &state);
-		if (result)
+		if (result) {
+			mutex_unlock(&resource->resource_lock);
 			continue;
+		}
 
 		if (state == ACPI_POWER_RESOURCE_STATE_OFF
 		    && resource->ref_count) {
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index f98dd00..c7414a5 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -119,17 +119,10 @@
  */
 static void acpi_safe_halt(void)
 {
-	current_thread_info()->status &= ~TS_POLLING;
-	/*
-	 * TS_POLLING-cleared state must be visible before we
-	 * test NEED_RESCHED:
-	 */
-	smp_mb();
-	if (!need_resched()) {
+	if (!tif_need_resched()) {
 		safe_halt();
 		local_irq_disable();
 	}
-	current_thread_info()->status |= TS_POLLING;
 }
 
 #ifdef ARCH_APICTIMER_STOPS_ON_C3
@@ -737,6 +730,11 @@
 	if (unlikely(!pr))
 		return -EINVAL;
 
+	if (cx->entry_method == ACPI_CSTATE_FFH) {
+		if (current_set_polling_and_test())
+			return -EINVAL;
+	}
+
 	lapic_timer_state_broadcast(pr, cx, 1);
 	acpi_idle_do_entry(cx);
 
@@ -790,18 +788,9 @@
 	if (unlikely(!pr))
 		return -EINVAL;
 
-	if (cx->entry_method != ACPI_CSTATE_FFH) {
-		current_thread_info()->status &= ~TS_POLLING;
-		/*
-		 * TS_POLLING-cleared state must be visible before we test
-		 * NEED_RESCHED:
-		 */
-		smp_mb();
-
-		if (unlikely(need_resched())) {
-			current_thread_info()->status |= TS_POLLING;
+	if (cx->entry_method == ACPI_CSTATE_FFH) {
+		if (current_set_polling_and_test())
 			return -EINVAL;
-		}
 	}
 
 	/*
@@ -819,9 +808,6 @@
 
 	sched_clock_idle_wakeup_event(0);
 
-	if (cx->entry_method != ACPI_CSTATE_FFH)
-		current_thread_info()->status |= TS_POLLING;
-
 	lapic_timer_state_broadcast(pr, cx, 0);
 	return index;
 }
@@ -858,18 +844,9 @@
 		}
 	}
 
-	if (cx->entry_method != ACPI_CSTATE_FFH) {
-		current_thread_info()->status &= ~TS_POLLING;
-		/*
-		 * TS_POLLING-cleared state must be visible before we test
-		 * NEED_RESCHED:
-		 */
-		smp_mb();
-
-		if (unlikely(need_resched())) {
-			current_thread_info()->status |= TS_POLLING;
+	if (cx->entry_method == ACPI_CSTATE_FFH) {
+		if (current_set_polling_and_test())
 			return -EINVAL;
-		}
 	}
 
 	acpi_unlazy_tlb(smp_processor_id());
@@ -915,9 +892,6 @@
 
 	sched_clock_idle_wakeup_event(0);
 
-	if (cx->entry_method != ACPI_CSTATE_FFH)
-		current_thread_info()->status |= TS_POLLING;
-
 	lapic_timer_state_broadcast(pr, cx, 0);
 	return index;
 }
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 407ad13..fee8a29 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -999,7 +999,6 @@
 	INIT_LIST_HEAD(&device->wakeup_list);
 	INIT_LIST_HEAD(&device->physical_node_list);
 	mutex_init(&device->physical_node_lock);
-	INIT_LIST_HEAD(&device->power_dependent);
 
 	new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
 	if (!new_bus_id) {
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 9d715ae..e2903d0 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -292,6 +292,10 @@
 	{ PCI_VDEVICE(INTEL, 0x8d66), board_ahci }, /* Wellsburg RAID */
 	{ PCI_VDEVICE(INTEL, 0x8d6e), board_ahci }, /* Wellsburg RAID */
 	{ PCI_VDEVICE(INTEL, 0x23a3), board_ahci }, /* Coleto Creek AHCI */
+	{ PCI_VDEVICE(INTEL, 0x9c83), board_ahci }, /* Wildcat Point-LP AHCI */
+	{ PCI_VDEVICE(INTEL, 0x9c85), board_ahci }, /* Wildcat Point-LP RAID */
+	{ PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */
+	{ PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */
 
 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -1343,7 +1347,7 @@
 	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
 		host->flags |= ATA_HOST_PARALLEL_SCAN;
 	else
-		printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
+		dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n");
 
 	if (pi.flags & ATA_FLAG_EM)
 		ahci_reset_em(host);
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 1145637..2289efd 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -339,6 +339,7 @@
 	.sdev_attrs		= ahci_sdev_attrs
 
 extern struct ata_port_operations ahci_ops;
+extern struct ata_port_operations ahci_platform_ops;
 extern struct ata_port_operations ahci_pmp_retry_srst_ops;
 
 unsigned int ahci_dev_classify(struct ata_port *ap);
@@ -368,6 +369,7 @@
 irqreturn_t ahci_thread_fn(int irq, void *dev_instance);
 void ahci_print_info(struct ata_host *host, const char *scc_s);
 int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis);
+void ahci_error_handler(struct ata_port *ap);
 
 static inline void __iomem *__ahci_port_base(struct ata_host *host,
 					     unsigned int port_no)
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 58debb0..ae2d73f 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -1,6 +1,6 @@
 /*
+ * copyright (c) 2013 Freescale Semiconductor, Inc.
  * Freescale IMX AHCI SATA platform driver
- * Copyright 2013 Freescale Semiconductor, Inc.
  *
  * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov
  *
@@ -25,10 +25,13 @@
 #include <linux/of_device.h>
 #include <linux/mfd/syscon.h>
 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/libata.h>
 #include "ahci.h"
 
 enum {
-	HOST_TIMER1MS = 0xe0, /* Timer 1-ms */
+	PORT_PHY_CTL = 0x178,			/* Port0 PHY Control */
+	PORT_PHY_CTL_PDDQ_LOC = 0x100000,	/* PORT_PHY_CTL bits */
+	HOST_TIMER1MS = 0xe0,			/* Timer 1-ms */
 };
 
 struct imx_ahci_priv {
@@ -36,6 +39,56 @@
 	struct clk *sata_ref_clk;
 	struct clk *ahb_clk;
 	struct regmap *gpr;
+	bool no_device;
+	bool first_time;
+};
+
+static int ahci_imx_hotplug;
+module_param_named(hotplug, ahci_imx_hotplug, int, 0644);
+MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support)");
+
+static void ahci_imx_error_handler(struct ata_port *ap)
+{
+	u32 reg_val;
+	struct ata_device *dev;
+	struct ata_host *host = dev_get_drvdata(ap->dev);
+	struct ahci_host_priv *hpriv = host->private_data;
+	void __iomem *mmio = hpriv->mmio;
+	struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent);
+
+	ahci_error_handler(ap);
+
+	if (!(imxpriv->first_time) || ahci_imx_hotplug)
+		return;
+
+	imxpriv->first_time = false;
+
+	ata_for_each_dev(dev, &ap->link, ENABLED)
+		return;
+	/*
+	 * Disable link to save power.  An imx ahci port can't be recovered
+	 * without full reset once the pddq mode is enabled making it
+	 * impossible to use as part of libata LPM.
+	 */
+	reg_val = readl(mmio + PORT_PHY_CTL);
+	writel(reg_val | PORT_PHY_CTL_PDDQ_LOC, mmio + PORT_PHY_CTL);
+	regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
+			IMX6Q_GPR13_SATA_MPLL_CLK_EN,
+			!IMX6Q_GPR13_SATA_MPLL_CLK_EN);
+	clk_disable_unprepare(imxpriv->sata_ref_clk);
+	imxpriv->no_device = true;
+}
+
+static struct ata_port_operations ahci_imx_ops = {
+	.inherits	= &ahci_platform_ops,
+	.error_handler	= ahci_imx_error_handler,
+};
+
+static const struct ata_port_info ahci_imx_port_info = {
+	.flags		= AHCI_FLAG_COMMON,
+	.pio_mask	= ATA_PIO4,
+	.udma_mask	= ATA_UDMA6,
+	.port_ops	= &ahci_imx_ops,
 };
 
 static int imx6q_sata_init(struct device *dev, void __iomem *mmio)
@@ -117,9 +170,51 @@
 	clk_disable_unprepare(imxpriv->sata_ref_clk);
 }
 
+static int imx_ahci_suspend(struct device *dev)
+{
+	struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
+
+	/*
+	 * If no_device is set, The CLKs had been gated off in the
+	 * initialization so don't do it again here.
+	 */
+	if (!imxpriv->no_device) {
+		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
+				IMX6Q_GPR13_SATA_MPLL_CLK_EN,
+				!IMX6Q_GPR13_SATA_MPLL_CLK_EN);
+		clk_disable_unprepare(imxpriv->sata_ref_clk);
+	}
+
+	return 0;
+}
+
+static int imx_ahci_resume(struct device *dev)
+{
+	struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
+	int ret;
+
+	if (!imxpriv->no_device) {
+		ret = clk_prepare_enable(imxpriv->sata_ref_clk);
+		if (ret < 0) {
+			dev_err(dev, "pre-enable sata_ref clock err:%d\n", ret);
+			return ret;
+		}
+
+		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
+				IMX6Q_GPR13_SATA_MPLL_CLK_EN,
+				IMX6Q_GPR13_SATA_MPLL_CLK_EN);
+		usleep_range(1000, 2000);
+	}
+
+	return 0;
+}
+
 static struct ahci_platform_data imx6q_sata_pdata = {
 	.init = imx6q_sata_init,
 	.exit = imx6q_sata_exit,
+	.ata_port_info = &ahci_imx_port_info,
+	.suspend = imx_ahci_suspend,
+	.resume = imx_ahci_resume,
 };
 
 static const struct of_device_id imx_ahci_of_match[] = {
@@ -152,6 +247,8 @@
 	ahci_dev = &ahci_pdev->dev;
 	ahci_dev->parent = dev;
 
+	imxpriv->no_device = false;
+	imxpriv->first_time = true;
 	imxpriv->ahb_clk = devm_clk_get(dev, "ahb");
 	if (IS_ERR(imxpriv->ahb_clk)) {
 		dev_err(dev, "can't get ahb clock.\n");
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 2daaee0..f955431 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -49,10 +49,11 @@
 };
 MODULE_DEVICE_TABLE(platform, ahci_devtype);
 
-static struct ata_port_operations ahci_platform_ops = {
+struct ata_port_operations ahci_platform_ops = {
 	.inherits	= &ahci_ops,
 	.host_stop	= ahci_host_stop,
 };
+EXPORT_SYMBOL_GPL(ahci_platform_ops);
 
 static struct ata_port_operations ahci_platform_retry_srst_ops = {
 	.inherits	= &ahci_pmp_retry_srst_ops,
@@ -184,7 +185,7 @@
 	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
 		host->flags |= ATA_HOST_PARALLEL_SCAN;
 	else
-		printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
+		dev_info(dev, "SSS flag set, parallel bus scan disabled\n");
 
 	if (pi.flags & ATA_FLAG_EM)
 		ahci_reset_em(host);
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 513ad7e..6334c8d 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -100,7 +100,7 @@
 
 enum {
 	PIIX_IOCFG		= 0x54, /* IDE I/O configuration register */
-	ICH5_PMR		= 0x90, /* port mapping register */
+	ICH5_PMR		= 0x90, /* address map register */
 	ICH5_PCS		= 0x92,	/* port control and status */
 	PIIX_SIDPR_BAR		= 5,
 	PIIX_SIDPR_LEN		= 16,
@@ -233,7 +233,7 @@
 	  PCI_CLASS_STORAGE_IDE << 8, 0xffff00, ich6m_sata },
 	/* 82801GB/GR/GH (ICH7, identical to ICH6) */
 	{ 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
-	/* 2801GBM/GHM (ICH7M, identical to ICH6M) */
+	/* 82801GBM/GHM (ICH7M, identical to ICH6M)  */
 	{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata },
 	/* Enterprise Southbridge 2 (631xESB/632xESB) */
 	{ 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
@@ -517,7 +517,7 @@
 	const struct ich_laptop *lap = &ich_laptop[0];
 	u8 mask;
 
-	/* Check for specials - Acer Aspire 5602WLMi */
+	/* Check for specials */
 	while (lap->device) {
 		if (lap->device == pdev->device &&
 		    lap->subvendor == pdev->subsystem_vendor &&
@@ -1366,38 +1366,39 @@
 	const int *map;
 	int i, invalid_map = 0;
 	u8 map_value;
+	char buf[32];
+	char *p = buf, *end = buf + sizeof(buf);
 
 	pci_read_config_byte(pdev, ICH5_PMR, &map_value);
 
 	map = map_db->map[map_value & map_db->mask];
 
-	dev_info(&pdev->dev, "MAP [");
 	for (i = 0; i < 4; i++) {
 		switch (map[i]) {
 		case RV:
 			invalid_map = 1;
-			pr_cont(" XX");
+			p += scnprintf(p, end - p, " XX");
 			break;
 
 		case NA:
-			pr_cont(" --");
+			p += scnprintf(p, end - p, " --");
 			break;
 
 		case IDE:
 			WARN_ON((i & 1) || map[i + 1] != IDE);
 			pinfo[i / 2] = piix_port_info[ich_pata_100];
 			i++;
-			pr_cont(" IDE IDE");
+			p += scnprintf(p, end - p, " IDE IDE");
 			break;
 
 		default:
-			pr_cont(" P%d", map[i]);
+			p += scnprintf(p, end - p, " P%d", map[i]);
 			if (i & 1)
 				pinfo[i / 2].flags |= ATA_FLAG_SLAVE_POSS;
 			break;
 		}
 	}
-	pr_cont(" ]\n");
+	dev_info(&pdev->dev, "MAP [%s ]\n", buf);
 
 	if (invalid_map)
 		dev_err(&pdev->dev, "invalid MAP value %u\n", map_value);
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index acfd0f7..c482f8c 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -89,7 +89,6 @@
 static int ahci_hardreset(struct ata_link *link, unsigned int *class,
 			  unsigned long deadline);
 static void ahci_postreset(struct ata_link *link, unsigned int *class);
-static void ahci_error_handler(struct ata_port *ap);
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
 static void ahci_dev_config(struct ata_device *dev);
 #ifdef CONFIG_PM
@@ -189,14 +188,15 @@
 };
 EXPORT_SYMBOL_GPL(ahci_pmp_retry_srst_ops);
 
-int ahci_em_messages = 1;
+static bool ahci_em_messages __read_mostly = true;
 EXPORT_SYMBOL_GPL(ahci_em_messages);
-module_param(ahci_em_messages, int, 0444);
+module_param(ahci_em_messages, bool, 0444);
 /* add other LED protocol types when they become supported */
 MODULE_PARM_DESC(ahci_em_messages,
 	"AHCI Enclosure Management Message control (0 = off, 1 = on)");
 
-int devslp_idle_timeout = 1000;	/* device sleep idle timeout in ms */
+/* device sleep idle timeout in ms */
+static int devslp_idle_timeout __read_mostly = 1000;
 module_param(devslp_idle_timeout, int, 0644);
 MODULE_PARM_DESC(devslp_idle_timeout, "device sleep idle timeout");
 
@@ -778,8 +778,16 @@
 				rc = ap->ops->transmit_led_message(ap,
 							       emp->led_state,
 							       4);
+				/*
+				 * If busy, give a breather but do not
+				 * release EH ownership by using msleep()
+				 * instead of ata_msleep().  EM Transmit
+				 * bit is busy for the whole host and
+				 * releasing ownership will cause other
+				 * ports to fail the same way.
+				 */
 				if (rc == -EBUSY)
-					ata_msleep(ap, 1);
+					msleep(1);
 				else
 					break;
 			}
@@ -1267,9 +1275,11 @@
 {
 	struct ata_port *ap = link->ap;
 	struct ahci_host_priv *hpriv = ap->host->private_data;
+	struct ahci_port_priv *pp = ap->private_data;
 	const char *reason = NULL;
 	unsigned long now, msecs;
 	struct ata_taskfile tf;
+	bool fbs_disabled = false;
 	int rc;
 
 	DPRINTK("ENTER\n");
@@ -1279,6 +1289,16 @@
 	if (rc && rc != -EOPNOTSUPP)
 		ata_link_warn(link, "failed to reset engine (errno=%d)\n", rc);
 
+	/*
+	 * According to AHCI-1.2 9.3.9: if FBS is enable, software shall
+	 * clear PxFBS.EN to '0' prior to issuing software reset to devices
+	 * that is attached to port multiplier.
+	 */
+	if (!ata_is_host_link(link) && pp->fbs_enabled) {
+		ahci_disable_fbs(ap);
+		fbs_disabled = true;
+	}
+
 	ata_tf_init(link->device, &tf);
 
 	/* issue the first D2H Register FIS */
@@ -1319,6 +1339,10 @@
 	} else
 		*class = ahci_dev_classify(ap);
 
+	/* re-enable FBS if disabled before */
+	if (fbs_disabled)
+		ahci_enable_fbs(ap);
+
 	DPRINTK("EXIT, class=%u\n", *class);
 	return 0;
 
@@ -1981,7 +2005,7 @@
 	writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
 }
 
-static void ahci_error_handler(struct ata_port *ap)
+void ahci_error_handler(struct ata_port *ap)
 {
 	if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
 		/* restart engine */
@@ -1994,6 +2018,7 @@
 	if (!ata_dev_enabled(ap->link.device))
 		ahci_stop_engine(ap);
 }
+EXPORT_SYMBOL_GPL(ahci_error_handler);
 
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
 {
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 4ba8b04..ab714d2 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -1035,17 +1035,3 @@
 {
 	ata_acpi_clear_gtf(dev);
 }
-
-void ata_scsi_acpi_bind(struct ata_device *dev)
-{
-	acpi_handle handle = ata_dev_acpi_handle(dev);
-	if (handle)
-		acpi_dev_pm_add_dependent(handle, &dev->sdev->sdev_gendev);
-}
-
-void ata_scsi_acpi_unbind(struct ata_device *dev)
-{
-	acpi_handle handle = ata_dev_acpi_handle(dev);
-	if (handle)
-		acpi_dev_pm_remove_dependent(handle, &dev->sdev->sdev_gendev);
-}
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 83b1a9f..81a94a3 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4126,6 +4126,7 @@
 	{ "TORiSAN DVD-ROM DRD-N216", NULL,	ATA_HORKAGE_MAX_SEC_128 },
 	{ "QUANTUM DAT    DAT72-000", NULL,	ATA_HORKAGE_ATAPI_MOD16_DMA },
 	{ "Slimtype DVD A  DS8A8SH", NULL,	ATA_HORKAGE_MAX_SEC_LBA48 },
+	{ "Slimtype DVD A  DS8A9SH", NULL,	ATA_HORKAGE_MAX_SEC_LBA48 },
 
 	/* Devices we expect to fail diagnostics */
 
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index c69fcce..77bbc82 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1322,14 +1322,14 @@
  *	should be retried.  To be used from EH.
  *
  *	SCSI midlayer limits the number of retries to scmd->allowed.
- *	scmd->retries is decremented for commands which get retried
+ *	scmd->allowed is incremented for commands which get retried
  *	due to unrelated failures (qc->err_mask is zero).
  */
 void ata_eh_qc_retry(struct ata_queued_cmd *qc)
 {
 	struct scsi_cmnd *scmd = qc->scsicmd;
-	if (!qc->err_mask && scmd->retries)
-		scmd->retries--;
+	if (!qc->err_mask)
+		scmd->allowed++;
 	__ata_eh_qc_complete(qc);
 }
 
@@ -2293,6 +2293,7 @@
 		{ ATA_CMD_IDLE, 		"IDLE" },
 		{ ATA_CMD_EDD, 			"EXECUTE DEVICE DIAGNOSTIC" },
 		{ ATA_CMD_DOWNLOAD_MICRO,   	"DOWNLOAD MICROCODE" },
+		{ ATA_CMD_DOWNLOAD_MICRO_DMA,	"DOWNLOAD MICROCODE DMA" },
 		{ ATA_CMD_NOP,			"NOP" },
 		{ ATA_CMD_FLUSH, 		"FLUSH CACHE" },
 		{ ATA_CMD_FLUSH_EXT, 		"FLUSH CACHE EXT" },
@@ -2313,6 +2314,8 @@
 		{ ATA_CMD_WRITE_QUEUED_FUA_EXT, "WRITE DMA QUEUED FUA EXT" },
 		{ ATA_CMD_FPDMA_READ,		"READ FPDMA QUEUED" },
 		{ ATA_CMD_FPDMA_WRITE,		"WRITE FPDMA QUEUED" },
+		{ ATA_CMD_FPDMA_SEND,		"SEND FPDMA QUEUED" },
+		{ ATA_CMD_FPDMA_RECV,		"RECEIVE FPDMA QUEUED" },
 		{ ATA_CMD_PIO_READ,		"READ SECTOR(S)" },
 		{ ATA_CMD_PIO_READ_EXT,		"READ SECTOR(S) EXT" },
 		{ ATA_CMD_PIO_WRITE,		"WRITE SECTOR(S)" },
@@ -2339,12 +2342,15 @@
 		{ ATA_CMD_WRITE_LOG_EXT,	"WRITE LOG EXT" },
 		{ ATA_CMD_READ_LOG_DMA_EXT,	"READ LOG DMA EXT" },
 		{ ATA_CMD_WRITE_LOG_DMA_EXT, 	"WRITE LOG DMA EXT" },
+		{ ATA_CMD_TRUSTED_NONDATA,	"TRUSTED NON-DATA" },
 		{ ATA_CMD_TRUSTED_RCV,		"TRUSTED RECEIVE" },
 		{ ATA_CMD_TRUSTED_RCV_DMA, 	"TRUSTED RECEIVE DMA" },
 		{ ATA_CMD_TRUSTED_SND,		"TRUSTED SEND" },
 		{ ATA_CMD_TRUSTED_SND_DMA, 	"TRUSTED SEND DMA" },
 		{ ATA_CMD_PMP_READ,		"READ BUFFER" },
+		{ ATA_CMD_PMP_READ_DMA,		"READ BUFFER DMA" },
 		{ ATA_CMD_PMP_WRITE,		"WRITE BUFFER" },
+		{ ATA_CMD_PMP_WRITE_DMA,	"WRITE BUFFER DMA" },
 		{ ATA_CMD_CONF_OVERLAY,		"DEVICE CONFIGURATION OVERLAY" },
 		{ ATA_CMD_SEC_SET_PASS,		"SECURITY SET PASSWORD" },
 		{ ATA_CMD_SEC_UNLOCK,		"SECURITY UNLOCK" },
@@ -2363,6 +2369,8 @@
 		{ ATA_CMD_CFA_TRANS_SECT,	"CFA TRANSLATE SECTOR" },
 		{ ATA_CMD_CFA_ERASE,		"CFA ERASE SECTORS" },
 		{ ATA_CMD_CFA_WRITE_MULT_NE, 	"CFA WRITE MULTIPLE WITHOUT ERASE" },
+		{ ATA_CMD_REQ_SENSE_DATA,	"REQUEST SENSE DATA EXT" },
+		{ ATA_CMD_SANITIZE_DEVICE,	"SANITIZE DEVICE" },
 		{ ATA_CMD_READ_LONG,		"READ LONG (with retries)" },
 		{ ATA_CMD_READ_LONG_ONCE,	"READ LONG (without retries)" },
 		{ ATA_CMD_WRITE_LONG,		"WRITE LONG (with retries)" },
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 97a0cef..db6dfcf 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3679,7 +3679,6 @@
 			if (!IS_ERR(sdev)) {
 				dev->sdev = sdev;
 				scsi_device_put(sdev);
-				ata_scsi_acpi_bind(dev);
 			} else {
 				dev->sdev = NULL;
 			}
@@ -3767,8 +3766,6 @@
 	struct scsi_device *sdev;
 	unsigned long flags;
 
-	ata_scsi_acpi_unbind(dev);
-
 	/* Alas, we need to grab scan_mutex to ensure SCSI device
 	 * state doesn't change underneath us and thus
 	 * scsi_device_get() always succeeds.  The mutex locking can
diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c
index 150a917..e37413228 100644
--- a/drivers/ata/libata-transport.c
+++ b/drivers/ata/libata-transport.c
@@ -321,25 +321,25 @@
 /*
  * ATA link attributes
  */
+static int noop(int x) { return x; }
 
-
-#define ata_link_show_linkspeed(field)					\
+#define ata_link_show_linkspeed(field, format)			        \
 static ssize_t								\
 show_ata_link_##field(struct device *dev,				\
 		      struct device_attribute *attr, char *buf)		\
 {									\
 	struct ata_link *link = transport_class_to_link(dev);		\
 									\
-	return sprintf(buf,"%s\n", sata_spd_string(fls(link->field)));	\
+	return sprintf(buf, "%s\n", sata_spd_string(format(link->field))); \
 }
 
-#define ata_link_linkspeed_attr(field)					\
-	ata_link_show_linkspeed(field)					\
+#define ata_link_linkspeed_attr(field, format)				\
+	ata_link_show_linkspeed(field, format)				\
 static DEVICE_ATTR(field, S_IRUGO, show_ata_link_##field, NULL)
 
-ata_link_linkspeed_attr(hw_sata_spd_limit);
-ata_link_linkspeed_attr(sata_spd_limit);
-ata_link_linkspeed_attr(sata_spd);
+ata_link_linkspeed_attr(hw_sata_spd_limit, fls);
+ata_link_linkspeed_attr(sata_spd_limit, fls);
+ata_link_linkspeed_attr(sata_spd, noop);
 
 
 static DECLARE_TRANSPORT_CLASS(ata_link_class,
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index eeeb778..45b5ab3 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -121,8 +121,6 @@
 extern void ata_acpi_bind_port(struct ata_port *ap);
 extern void ata_acpi_bind_dev(struct ata_device *dev);
 extern acpi_handle ata_dev_acpi_handle(struct ata_device *dev);
-extern void ata_scsi_acpi_bind(struct ata_device *dev);
-extern void ata_scsi_acpi_unbind(struct ata_device *dev);
 #else
 static inline void ata_acpi_dissociate(struct ata_host *host) { }
 static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; }
@@ -133,8 +131,6 @@
 				      pm_message_t state) { }
 static inline void ata_acpi_bind_port(struct ata_port *ap) {}
 static inline void ata_acpi_bind_dev(struct ata_device *dev) {}
-static inline void ata_scsi_acpi_bind(struct ata_device *dev) {}
-static inline void ata_scsi_acpi_unbind(struct ata_device *dev) {}
 #endif
 
 /* libata-scsi.c */
diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
index 4bceb88..b33d1f9 100644
--- a/drivers/ata/pata_isapnp.c
+++ b/drivers/ata/pata_isapnp.c
@@ -78,7 +78,7 @@
 
 	ap->ioaddr.cmd_addr = cmd_addr;
 
-	if (pnp_port_valid(idev, 1) == 0) {
+	if (pnp_port_valid(idev, 1)) {
 		ctl_addr = devm_ioport_map(&idev->dev,
 					   pnp_port_start(idev, 1), 1);
 		ap->ioaddr.altstatus_addr = ctl_addr;
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 2e39173..523524b 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -31,6 +31,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/libata.h>
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 851bd3f..fb0b40a 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -24,6 +24,8 @@
 #include <scsi/scsi_cmnd.h>
 #include <linux/libata.h>
 #include <asm/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
 static unsigned int intr_coalescing_count;
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
index 7f5e5d9..ea3b3dc 100644
--- a/drivers/ata/sata_highbank.c
+++ b/drivers/ata/sata_highbank.c
@@ -343,13 +343,11 @@
 {
 	struct device_node *sata_node = dev->of_node;
 	int phy_count = 0, phy, port = 0, i;
-	void __iomem *cphy_base[CPHY_PHY_COUNT];
-	struct device_node *phy_nodes[CPHY_PHY_COUNT];
-	u32 tx_atten[CPHY_PORT_COUNT];
+	void __iomem *cphy_base[CPHY_PHY_COUNT] = {};
+	struct device_node *phy_nodes[CPHY_PHY_COUNT] = {};
+	u32 tx_atten[CPHY_PORT_COUNT] = {};
 
 	memset(port_data, 0, sizeof(struct phy_lane_info) * CPHY_PORT_COUNT);
-	memset(phy_nodes, 0, sizeof(struct device_node*) * CPHY_PHY_COUNT);
-	memset(tx_atten, 0xff, CPHY_PORT_COUNT);
 
 	do {
 		u32 tmp;
diff --git a/drivers/ata/sata_rcar.c b/drivers/ata/sata_rcar.c
index c2d95e9..1dae9a9 100644
--- a/drivers/ata/sata_rcar.c
+++ b/drivers/ata/sata_rcar.c
@@ -792,7 +792,7 @@
 		dev_err(&pdev->dev, "failed to get access to sata clock\n");
 		return PTR_ERR(priv->clk);
 	}
-	clk_enable(priv->clk);
+	clk_prepare_enable(priv->clk);
 
 	host = ata_host_alloc(&pdev->dev, 1);
 	if (!host) {
@@ -822,7 +822,7 @@
 		return 0;
 
 cleanup:
-	clk_disable(priv->clk);
+	clk_disable_unprepare(priv->clk);
 
 	return ret;
 }
@@ -841,7 +841,7 @@
 	iowrite32(0, base + SATAINTSTAT_REG);
 	iowrite32(0x7ff, base + SATAINTMASK_REG);
 
-	clk_disable(priv->clk);
+	clk_disable_unprepare(priv->clk);
 
 	return 0;
 }
@@ -861,7 +861,7 @@
 		/* mask */
 		iowrite32(0x7ff, base + SATAINTMASK_REG);
 
-		clk_disable(priv->clk);
+		clk_disable_unprepare(priv->clk);
 	}
 
 	return ret;
@@ -873,7 +873,7 @@
 	struct sata_rcar_priv *priv = host->private_data;
 	void __iomem *base = priv->base;
 
-	clk_enable(priv->clk);
+	clk_prepare_enable(priv->clk);
 
 	/* ack and mask */
 	iowrite32(0, base + SATAINTSTAT_REG);
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 4c289ab..73f6c29 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -591,37 +591,6 @@
 	bus_put(dev->bus);
 }
 
-static int driver_add_attrs(struct bus_type *bus, struct device_driver *drv)
-{
-	int error = 0;
-	int i;
-
-	if (bus->drv_attrs) {
-		for (i = 0; bus->drv_attrs[i].attr.name; i++) {
-			error = driver_create_file(drv, &bus->drv_attrs[i]);
-			if (error)
-				goto err;
-		}
-	}
-done:
-	return error;
-err:
-	while (--i >= 0)
-		driver_remove_file(drv, &bus->drv_attrs[i]);
-	goto done;
-}
-
-static void driver_remove_attrs(struct bus_type *bus,
-				struct device_driver *drv)
-{
-	int i;
-
-	if (bus->drv_attrs) {
-		for (i = 0; bus->drv_attrs[i].attr.name; i++)
-			driver_remove_file(drv, &bus->drv_attrs[i]);
-	}
-}
-
 static int __must_check add_bind_files(struct device_driver *drv)
 {
 	int ret;
@@ -720,16 +689,12 @@
 		printk(KERN_ERR "%s: uevent attr (%s) failed\n",
 			__func__, drv->name);
 	}
-	error = driver_add_attrs(bus, drv);
+	error = driver_add_groups(drv, bus->drv_groups);
 	if (error) {
 		/* How the hell do we get out of this pickle? Give up */
-		printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
-			__func__, drv->name);
-	}
-	error = driver_add_groups(drv, bus->drv_groups);
-	if (error)
 		printk(KERN_ERR "%s: driver_create_groups(%s) failed\n",
 			__func__, drv->name);
+	}
 
 	if (!drv->suppress_bind_attrs) {
 		error = add_bind_files(drv);
@@ -766,7 +731,6 @@
 
 	if (!drv->suppress_bind_attrs)
 		remove_bind_files(drv);
-	driver_remove_attrs(drv->bus, drv);
 	driver_remove_groups(drv, drv->bus->drv_groups);
 	driver_remove_file(drv, &driver_attr_uevent);
 	klist_remove(&drv->p->knode_bus);
@@ -846,42 +810,6 @@
 }
 #endif  /*  0  */
 
-
-/**
- * bus_add_attrs - Add default attributes for this bus.
- * @bus: Bus that has just been registered.
- */
-
-static int bus_add_attrs(struct bus_type *bus)
-{
-	int error = 0;
-	int i;
-
-	if (bus->bus_attrs) {
-		for (i = 0; bus->bus_attrs[i].attr.name; i++) {
-			error = bus_create_file(bus, &bus->bus_attrs[i]);
-			if (error)
-				goto err;
-		}
-	}
-done:
-	return error;
-err:
-	while (--i >= 0)
-		bus_remove_file(bus, &bus->bus_attrs[i]);
-	goto done;
-}
-
-static void bus_remove_attrs(struct bus_type *bus)
-{
-	int i;
-
-	if (bus->bus_attrs) {
-		for (i = 0; bus->bus_attrs[i].attr.name; i++)
-			bus_remove_file(bus, &bus->bus_attrs[i]);
-	}
-}
-
 static int bus_add_groups(struct bus_type *bus,
 			  const struct attribute_group **groups)
 {
@@ -983,9 +911,6 @@
 	if (retval)
 		goto bus_probe_files_fail;
 
-	retval = bus_add_attrs(bus);
-	if (retval)
-		goto bus_attrs_fail;
 	retval = bus_add_groups(bus, bus->bus_groups);
 	if (retval)
 		goto bus_groups_fail;
@@ -994,8 +919,6 @@
 	return 0;
 
 bus_groups_fail:
-	bus_remove_attrs(bus);
-bus_attrs_fail:
 	remove_probe_files(bus);
 bus_probe_files_fail:
 	kset_unregister(bus->p->drivers_kset);
@@ -1024,7 +947,6 @@
 	pr_debug("bus: '%s': unregistering\n", bus->name);
 	if (bus->dev_root)
 		device_unregister(bus->dev_root);
-	bus_remove_attrs(bus);
 	bus_remove_groups(bus, bus->bus_groups);
 	remove_probe_files(bus);
 	kset_unregister(bus->p->drivers_kset);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 8b7818b..f96f704 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -47,18 +47,6 @@
 	return ret;
 }
 
-static const void *class_attr_namespace(struct kobject *kobj,
-					const struct attribute *attr)
-{
-	struct class_attribute *class_attr = to_class_attr(attr);
-	struct subsys_private *cp = to_subsys_private(kobj);
-	const void *ns = NULL;
-
-	if (class_attr->namespace)
-		ns = class_attr->namespace(cp->class, class_attr);
-	return ns;
-}
-
 static void class_release(struct kobject *kobj)
 {
 	struct subsys_private *cp = to_subsys_private(kobj);
@@ -86,7 +74,6 @@
 static const struct sysfs_ops class_sysfs_ops = {
 	.show	   = class_attr_show,
 	.store	   = class_attr_store,
-	.namespace = class_attr_namespace,
 };
 
 static struct kobj_type class_ktype = {
@@ -99,21 +86,23 @@
 static struct kset *class_kset;
 
 
-int class_create_file(struct class *cls, const struct class_attribute *attr)
+int class_create_file_ns(struct class *cls, const struct class_attribute *attr,
+			 const void *ns)
 {
 	int error;
 	if (cls)
-		error = sysfs_create_file(&cls->p->subsys.kobj,
-					  &attr->attr);
+		error = sysfs_create_file_ns(&cls->p->subsys.kobj,
+					     &attr->attr, ns);
 	else
 		error = -EINVAL;
 	return error;
 }
 
-void class_remove_file(struct class *cls, const struct class_attribute *attr)
+void class_remove_file_ns(struct class *cls, const struct class_attribute *attr,
+			  const void *ns)
 {
 	if (cls)
-		sysfs_remove_file(&cls->p->subsys.kobj, &attr->attr);
+		sysfs_remove_file_ns(&cls->p->subsys.kobj, &attr->attr, ns);
 }
 
 static struct class *class_get(struct class *cls)
@@ -600,8 +589,8 @@
 	return 0;
 }
 
-EXPORT_SYMBOL_GPL(class_create_file);
-EXPORT_SYMBOL_GPL(class_remove_file);
+EXPORT_SYMBOL_GPL(class_create_file_ns);
+EXPORT_SYMBOL_GPL(class_remove_file_ns);
 EXPORT_SYMBOL_GPL(class_unregister);
 EXPORT_SYMBOL_GPL(class_destroy);
 
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 34abf4d..67b180d 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -455,64 +455,6 @@
 }
 static DEVICE_ATTR_RW(online);
 
-static int device_add_attributes(struct device *dev,
-				 struct device_attribute *attrs)
-{
-	int error = 0;
-	int i;
-
-	if (attrs) {
-		for (i = 0; attrs[i].attr.name; i++) {
-			error = device_create_file(dev, &attrs[i]);
-			if (error)
-				break;
-		}
-		if (error)
-			while (--i >= 0)
-				device_remove_file(dev, &attrs[i]);
-	}
-	return error;
-}
-
-static void device_remove_attributes(struct device *dev,
-				     struct device_attribute *attrs)
-{
-	int i;
-
-	if (attrs)
-		for (i = 0; attrs[i].attr.name; i++)
-			device_remove_file(dev, &attrs[i]);
-}
-
-static int device_add_bin_attributes(struct device *dev,
-				     struct bin_attribute *attrs)
-{
-	int error = 0;
-	int i;
-
-	if (attrs) {
-		for (i = 0; attrs[i].attr.name; i++) {
-			error = device_create_bin_file(dev, &attrs[i]);
-			if (error)
-				break;
-		}
-		if (error)
-			while (--i >= 0)
-				device_remove_bin_file(dev, &attrs[i]);
-	}
-	return error;
-}
-
-static void device_remove_bin_attributes(struct device *dev,
-					 struct bin_attribute *attrs)
-{
-	int i;
-
-	if (attrs)
-		for (i = 0; attrs[i].attr.name; i++)
-			device_remove_bin_file(dev, &attrs[i]);
-}
-
 int device_add_groups(struct device *dev, const struct attribute_group **groups)
 {
 	return sysfs_create_groups(&dev->kobj, groups);
@@ -534,18 +476,12 @@
 		error = device_add_groups(dev, class->dev_groups);
 		if (error)
 			return error;
-		error = device_add_attributes(dev, class->dev_attrs);
-		if (error)
-			goto err_remove_class_groups;
-		error = device_add_bin_attributes(dev, class->dev_bin_attrs);
-		if (error)
-			goto err_remove_class_attrs;
 	}
 
 	if (type) {
 		error = device_add_groups(dev, type->groups);
 		if (error)
-			goto err_remove_class_bin_attrs;
+			goto err_remove_class_groups;
 	}
 
 	error = device_add_groups(dev, dev->groups);
@@ -563,12 +499,6 @@
  err_remove_type_groups:
 	if (type)
 		device_remove_groups(dev, type->groups);
- err_remove_class_bin_attrs:
-	if (class)
-		device_remove_bin_attributes(dev, class->dev_bin_attrs);
- err_remove_class_attrs:
-	if (class)
-		device_remove_attributes(dev, class->dev_attrs);
  err_remove_class_groups:
 	if (class)
 		device_remove_groups(dev, class->dev_groups);
@@ -587,11 +517,8 @@
 	if (type)
 		device_remove_groups(dev, type->groups);
 
-	if (class) {
-		device_remove_attributes(dev, class->dev_attrs);
-		device_remove_bin_attributes(dev, class->dev_bin_attrs);
+	if (class)
 		device_remove_groups(dev, class->dev_groups);
-	}
 }
 
 static ssize_t dev_show(struct device *dev, struct device_attribute *attr,
@@ -1881,6 +1808,7 @@
  */
 int device_rename(struct device *dev, const char *new_name)
 {
+	struct kobject *kobj = &dev->kobj;
 	char *old_device_name = NULL;
 	int error;
 
@@ -1888,8 +1816,7 @@
 	if (!dev)
 		return -EINVAL;
 
-	pr_debug("device: '%s': %s: renaming to '%s'\n", dev_name(dev),
-		 __func__, new_name);
+	dev_dbg(dev, "renaming to %s\n", new_name);
 
 	old_device_name = kstrdup(dev_name(dev), GFP_KERNEL);
 	if (!old_device_name) {
@@ -1898,13 +1825,14 @@
 	}
 
 	if (dev->class) {
-		error = sysfs_rename_link(&dev->class->p->subsys.kobj,
-			&dev->kobj, old_device_name, new_name);
+		error = sysfs_rename_link_ns(&dev->class->p->subsys.kobj,
+					     kobj, old_device_name,
+					     new_name, kobject_namespace(kobj));
 		if (error)
 			goto out;
 	}
 
-	error = kobject_rename(&dev->kobj, new_name);
+	error = kobject_rename(kobj, new_name);
 	if (error)
 		goto out;
 
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index 507379e..545c4de 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -91,7 +91,8 @@
 	if (unlikely(!dr))
 		return NULL;
 
-	memset(dr, 0, tot_size);
+	memset(dr, 0, offsetof(struct devres, data));
+
 	INIT_LIST_HEAD(&dr->node.entry);
 	dr->node.release = release;
 	return dr;
@@ -110,7 +111,7 @@
 {
 	struct devres *dr;
 
-	dr = alloc_dr(release, size, gfp);
+	dr = alloc_dr(release, size, gfp | __GFP_ZERO);
 	if (unlikely(!dr))
 		return NULL;
 	set_node_dbginfo(&dr->node, name, size);
@@ -135,7 +136,7 @@
 {
 	struct devres *dr;
 
-	dr = alloc_dr(release, size, gfp);
+	dr = alloc_dr(release, size, gfp | __GFP_ZERO);
 	if (unlikely(!dr))
 		return NULL;
 	return dr->data;
@@ -745,58 +746,62 @@
 EXPORT_SYMBOL_GPL(devm_remove_action);
 
 /*
- * Managed kzalloc/kfree
+ * Managed kmalloc/kfree
  */
-static void devm_kzalloc_release(struct device *dev, void *res)
+static void devm_kmalloc_release(struct device *dev, void *res)
 {
 	/* noop */
 }
 
-static int devm_kzalloc_match(struct device *dev, void *res, void *data)
+static int devm_kmalloc_match(struct device *dev, void *res, void *data)
 {
 	return res == data;
 }
 
 /**
- * devm_kzalloc - Resource-managed kzalloc
+ * devm_kmalloc - Resource-managed kmalloc
  * @dev: Device to allocate memory for
  * @size: Allocation size
  * @gfp: Allocation gfp flags
  *
- * Managed kzalloc.  Memory allocated with this function is
+ * Managed kmalloc.  Memory allocated with this function is
  * automatically freed on driver detach.  Like all other devres
  * resources, guaranteed alignment is unsigned long long.
  *
  * RETURNS:
  * Pointer to allocated memory on success, NULL on failure.
  */
-void * devm_kzalloc(struct device *dev, size_t size, gfp_t gfp)
+void * devm_kmalloc(struct device *dev, size_t size, gfp_t gfp)
 {
 	struct devres *dr;
 
 	/* use raw alloc_dr for kmalloc caller tracing */
-	dr = alloc_dr(devm_kzalloc_release, size, gfp);
+	dr = alloc_dr(devm_kmalloc_release, size, gfp);
 	if (unlikely(!dr))
 		return NULL;
 
+	/*
+	 * This is named devm_kzalloc_release for historical reasons
+	 * The initial implementation did not support kmalloc, only kzalloc
+	 */
 	set_node_dbginfo(&dr->node, "devm_kzalloc_release", size);
 	devres_add(dev, dr->data);
 	return dr->data;
 }
-EXPORT_SYMBOL_GPL(devm_kzalloc);
+EXPORT_SYMBOL_GPL(devm_kmalloc);
 
 /**
  * devm_kfree - Resource-managed kfree
  * @dev: Device this memory belongs to
  * @p: Memory to free
  *
- * Free memory allocated with devm_kzalloc().
+ * Free memory allocated with devm_kmalloc().
  */
 void devm_kfree(struct device *dev, void *p)
 {
 	int rc;
 
-	rc = devres_destroy(dev, devm_kzalloc_release, devm_kzalloc_match, p);
+	rc = devres_destroy(dev, devm_kmalloc_release, devm_kmalloc_match, p);
 	WARN_ON(rc);
 }
 EXPORT_SYMBOL_GPL(devm_kfree);
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 10a4467..eb8fb94 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -282,31 +282,35 @@
 	return st.size;
 }
 
-static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
+static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
 {
 	long size;
 	char *buf;
+	int rc;
 
 	size = fw_file_size(file);
 	if (size <= 0)
-		return false;
+		return -EINVAL;
 	buf = vmalloc(size);
 	if (!buf)
-		return false;
-	if (kernel_read(file, 0, buf, size) != size) {
+		return -ENOMEM;
+	rc = kernel_read(file, 0, buf, size);
+	if (rc != size) {
+		if (rc > 0)
+			rc = -EIO;
 		vfree(buf);
-		return false;
+		return rc;
 	}
 	fw_buf->data = buf;
 	fw_buf->size = size;
-	return true;
+	return 0;
 }
 
-static bool fw_get_filesystem_firmware(struct device *device,
+static int fw_get_filesystem_firmware(struct device *device,
 				       struct firmware_buf *buf)
 {
 	int i;
-	bool success = false;
+	int rc = -ENOENT;
 	char *path = __getname();
 
 	for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
@@ -321,14 +325,17 @@
 		file = filp_open(path, O_RDONLY, 0);
 		if (IS_ERR(file))
 			continue;
-		success = fw_read_file_contents(file, buf);
+		rc = fw_read_file_contents(file, buf);
 		fput(file);
-		if (success)
+		if (rc)
+			dev_warn(device, "firmware, attempted to load %s, but failed with error %d\n",
+				path, rc);
+		else
 			break;
 	}
 	__putname(path);
 
-	if (success) {
+	if (!rc) {
 		dev_dbg(device, "firmware: direct-loading firmware %s\n",
 			buf->fw_id);
 		mutex_lock(&fw_lock);
@@ -337,7 +344,7 @@
 		mutex_unlock(&fw_lock);
 	}
 
-	return success;
+	return rc;
 }
 
 /* firmware holds the ownership of pages */
@@ -1086,9 +1093,14 @@
 		}
 	}
 
-	if (!fw_get_filesystem_firmware(device, fw->priv))
+	ret = fw_get_filesystem_firmware(device, fw->priv);
+	if (ret) {
+		dev_warn(device, "Direct firmware load failed with error %d\n",
+			 ret);
+		dev_warn(device, "Falling back to user helper\n");
 		ret = fw_load_from_user_helper(fw, name, device,
 					       uevent, nowait, timeout);
+	}
 
 	/* don't cache firmware handled without uevent */
 	if (!ret)
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 9e59f65..bece691 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -333,8 +333,10 @@
 		online_type = ONLINE_KEEP;
 	else if (!strncmp(buf, "offline", min_t(int, count, 7)))
 		online_type = -1;
-	else
-		return -EINVAL;
+	else {
+		ret = -EINVAL;
+		goto err;
+	}
 
 	switch (online_type) {
 	case ONLINE_KERNEL:
@@ -357,6 +359,7 @@
 		ret = -EINVAL; /* should never happen */
 	}
 
+err:
 	unlock_device_hotplug();
 
 	if (ret)
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 4f8bef3..47051cd 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -488,6 +488,11 @@
 	if (ret && ACPI_HANDLE(_dev))
 		acpi_dev_pm_detach(_dev, true);
 
+	if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {
+		dev_warn(_dev, "probe deferral not supported\n");
+		ret = -ENXIO;
+	}
+
 	return ret;
 }
 
@@ -553,8 +558,7 @@
 /**
  * platform_driver_probe - register driver for non-hotpluggable device
  * @drv: platform driver structure
- * @probe: the driver probe routine, probably from an __init section,
- *         must not return -EPROBE_DEFER.
+ * @probe: the driver probe routine, probably from an __init section
  *
  * Use this instead of platform_driver_register() when you know the device
  * is not hotpluggable and has already been registered, and you want to
@@ -565,8 +569,7 @@
  * into system-on-chip processors, where the controller devices have been
  * configured as part of board setup.
  *
- * This is incompatible with deferred probing so probe() must not
- * return -EPROBE_DEFER.
+ * Note that this is incompatible with deferred probing.
  *
  * Returns zero if the driver registered and bound to a device, else returns
  * a negative error code and with the driver not registered.
@@ -576,6 +579,12 @@
 {
 	int retval, code;
 
+	/*
+	 * Prevent driver from requesting probe deferral to avoid further
+	 * futile probe attempts.
+	 */
+	drv->prevent_deferred_probe = true;
+
 	/* make sure driver won't have bind/unbind attributes */
 	drv->driver.suppress_bind_attrs = true;
 
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig
index f0d3054..4251570 100644
--- a/drivers/base/regmap/Kconfig
+++ b/drivers/base/regmap/Kconfig
@@ -3,7 +3,7 @@
 # subsystems should select the appropriate symbols.
 
 config REGMAP
-	default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_MMIO || REGMAP_IRQ)
+	default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_MMIO || REGMAP_IRQ)
 	select LZO_COMPRESS
 	select LZO_DECOMPRESS
 	select IRQ_DOMAIN if REGMAP_IRQ
@@ -15,6 +15,9 @@
 config REGMAP_SPI
 	tristate
 
+config REGMAP_SPMI
+	tristate
+
 config REGMAP_MMIO
 	tristate
 
diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile
index cf12998..a7c670b 100644
--- a/drivers/base/regmap/Makefile
+++ b/drivers/base/regmap/Makefile
@@ -3,5 +3,6 @@
 obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o
 obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o
 obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o
+obj-$(CONFIG_REGMAP_SPMI) += regmap-spmi.o
 obj-$(CONFIG_REGMAP_MMIO) += regmap-mmio.o
 obj-$(CONFIG_REGMAP_IRQ) += regmap-irq.o
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
index 57f7778..33414b1 100644
--- a/drivers/base/regmap/internal.h
+++ b/drivers/base/regmap/internal.h
@@ -44,7 +44,6 @@
 
 struct regmap_async {
 	struct list_head list;
-	struct work_struct cleanup;
 	struct regmap *map;
 	void *work_buf;
 };
@@ -64,9 +63,11 @@
 	void *bus_context;
 	const char *name;
 
+	bool async;
 	spinlock_t async_lock;
 	wait_queue_head_t async_waitq;
 	struct list_head async_list;
+	struct list_head async_free;
 	int async_ret;
 
 #ifdef CONFIG_DEBUG_FS
@@ -179,6 +180,9 @@
 	/* lsb */
 	unsigned int shift;
 	unsigned int reg;
+
+	unsigned int id_size;
+	unsigned int id_offset;
 };
 
 #ifdef CONFIG_DEBUG_FS
@@ -218,7 +222,7 @@
 int regcache_lookup_reg(struct regmap *map, unsigned int reg);
 
 int _regmap_raw_write(struct regmap *map, unsigned int reg,
-		      const void *val, size_t val_len, bool async);
+		      const void *val, size_t val_len);
 
 void regmap_async_complete_cb(struct regmap_async *async, int ret);
 
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index d6c2d69..d4dd771 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -307,6 +307,8 @@
 	if (!map->cache_dirty)
 		goto out;
 
+	map->async = true;
+
 	/* Apply any patch first */
 	map->cache_bypass = 1;
 	for (i = 0; i < map->patch_regs; i++) {
@@ -332,11 +334,15 @@
 		map->cache_dirty = false;
 
 out:
-	trace_regcache_sync(map->dev, name, "stop");
 	/* Restore the bypass state */
+	map->async = false;
 	map->cache_bypass = bypass;
 	map->unlock(map->lock_arg);
 
+	regmap_async_complete(map);
+
+	trace_regcache_sync(map->dev, name, "stop");
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(regcache_sync);
@@ -375,17 +381,23 @@
 	if (!map->cache_dirty)
 		goto out;
 
+	map->async = true;
+
 	if (map->cache_ops->sync)
 		ret = map->cache_ops->sync(map, min, max);
 	else
 		ret = regcache_default_sync(map, min, max);
 
 out:
-	trace_regcache_sync(map->dev, name, "stop region");
 	/* Restore the bypass state */
 	map->cache_bypass = bypass;
+	map->async = false;
 	map->unlock(map->lock_arg);
 
+	regmap_async_complete(map);
+
+	trace_regcache_sync(map->dev, name, "stop region");
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(regcache_sync_region);
@@ -631,8 +643,7 @@
 
 	map->cache_bypass = 1;
 
-	ret = _regmap_raw_write(map, base, *data, count * val_bytes,
-				false);
+	ret = _regmap_raw_write(map, base, *data, count * val_bytes);
 
 	map->cache_bypass = 0;
 
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index de11eca..c5471cd 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -15,10 +15,19 @@
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
 #include <linux/device.h>
+#include <linux/list.h>
 
 #include "internal.h"
 
+struct regmap_debugfs_node {
+	struct regmap *map;
+	const char *name;
+	struct list_head link;
+};
+
 static struct dentry *regmap_debugfs_root;
+static LIST_HEAD(regmap_debugfs_early_list);
+static DEFINE_MUTEX(regmap_debugfs_early_lock);
 
 /* Calculate the length of a fixed format  */
 static size_t regmap_calc_reg_len(int max_val, char *buf, size_t buf_size)
@@ -465,6 +474,20 @@
 	struct rb_node *next;
 	struct regmap_range_node *range_node;
 
+	/* If we don't have the debugfs root yet, postpone init */
+	if (!regmap_debugfs_root) {
+		struct regmap_debugfs_node *node;
+		node = kzalloc(sizeof(*node), GFP_KERNEL);
+		if (!node)
+			return;
+		node->map = map;
+		node->name = name;
+		mutex_lock(&regmap_debugfs_early_lock);
+		list_add(&node->link, &regmap_debugfs_early_list);
+		mutex_unlock(&regmap_debugfs_early_lock);
+		return;
+	}
+
 	INIT_LIST_HEAD(&map->debugfs_off_cache);
 	mutex_init(&map->cache_lock);
 
@@ -519,18 +542,42 @@
 
 void regmap_debugfs_exit(struct regmap *map)
 {
-	debugfs_remove_recursive(map->debugfs);
-	mutex_lock(&map->cache_lock);
-	regmap_debugfs_free_dump_cache(map);
-	mutex_unlock(&map->cache_lock);
-	kfree(map->debugfs_name);
+	if (map->debugfs) {
+		debugfs_remove_recursive(map->debugfs);
+		mutex_lock(&map->cache_lock);
+		regmap_debugfs_free_dump_cache(map);
+		mutex_unlock(&map->cache_lock);
+		kfree(map->debugfs_name);
+	} else {
+		struct regmap_debugfs_node *node, *tmp;
+
+		mutex_lock(&regmap_debugfs_early_lock);
+		list_for_each_entry_safe(node, tmp, &regmap_debugfs_early_list,
+					 link) {
+			if (node->map == map) {
+				list_del(&node->link);
+				kfree(node);
+			}
+		}
+		mutex_unlock(&regmap_debugfs_early_lock);
+	}
 }
 
 void regmap_debugfs_initcall(void)
 {
+	struct regmap_debugfs_node *node, *tmp;
+
 	regmap_debugfs_root = debugfs_create_dir("regmap", NULL);
 	if (!regmap_debugfs_root) {
 		pr_warn("regmap: Failed to create debugfs root\n");
 		return;
 	}
+
+	mutex_lock(&regmap_debugfs_early_lock);
+	list_for_each_entry_safe(node, tmp, &regmap_debugfs_early_list, link) {
+		regmap_debugfs_init(node->map, node->name);
+		list_del(&node->link);
+		kfree(node);
+	}
+	mutex_unlock(&regmap_debugfs_early_lock);
 }
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index d10456f..763c60d 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -105,6 +105,22 @@
 					"Failed to sync wakes in %x: %d\n",
 					reg, ret);
 		}
+
+		if (!d->chip->init_ack_masked)
+			continue;
+		/*
+		 * Ack all the masked interrupts uncondictionly,
+		 * OR if there is masked interrupt which hasn't been Acked,
+		 * it'll be ignored in irq handler, then may introduce irq storm
+		 */
+		if (d->mask_buf[i] && d->chip->ack_base) {
+			reg = d->chip->ack_base +
+				(i * map->reg_stride * d->irq_reg_stride);
+			ret = regmap_write(map, reg, d->mask_buf[i]);
+			if (ret != 0)
+				dev_err(d->map->dev, "Failed to ack 0x%x: %d\n",
+					reg, ret);
+		}
 	}
 
 	if (d->chip->runtime_pm)
diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c
index 4c506bd..37f12ae 100644
--- a/drivers/base/regmap/regmap-spi.c
+++ b/drivers/base/regmap/regmap-spi.c
@@ -73,7 +73,8 @@
 
 	spi_message_init(&async->m);
 	spi_message_add_tail(&async->t[0], &async->m);
-	spi_message_add_tail(&async->t[1], &async->m);
+	if (val)
+		spi_message_add_tail(&async->t[1], &async->m);
 
 	async->m.complete = regmap_spi_complete;
 	async->m.context = async;
diff --git a/drivers/base/regmap/regmap-spmi.c b/drivers/base/regmap/regmap-spmi.c
new file mode 100644
index 0000000..ac23910
--- /dev/null
+++ b/drivers/base/regmap/regmap-spmi.c
@@ -0,0 +1,90 @@
+/*
+ * Register map access API - SPMI support
+ *
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Based on regmap-i2c.c:
+ * Copyright 2011 Wolfson Microelectronics plc
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/regmap.h>
+#include <linux/spmi.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+static int regmap_spmi_read(void *context,
+			    const void *reg, size_t reg_size,
+			    void *val, size_t val_size)
+{
+	BUG_ON(reg_size != 2);
+	return spmi_ext_register_readl(context, *(u16 *)reg,
+				       val, val_size);
+}
+
+static int regmap_spmi_gather_write(void *context,
+				    const void *reg, size_t reg_size,
+				    const void *val, size_t val_size)
+{
+	BUG_ON(reg_size != 2);
+	return spmi_ext_register_writel(context, *(u16 *)reg, val, val_size);
+}
+
+static int regmap_spmi_write(void *context, const void *data,
+			     size_t count)
+{
+	BUG_ON(count < 2);
+	return regmap_spmi_gather_write(context, data, 2, data + 2, count - 2);
+}
+
+static struct regmap_bus regmap_spmi = {
+	.read				= regmap_spmi_read,
+	.write				= regmap_spmi_write,
+	.gather_write			= regmap_spmi_gather_write,
+	.reg_format_endian_default	= REGMAP_ENDIAN_NATIVE,
+	.val_format_endian_default	= REGMAP_ENDIAN_NATIVE,
+};
+
+/**
+ * regmap_init_spmi(): Initialize register map
+ *
+ * @sdev: Device that will be interacted with
+ * @config: Configuration for register map
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer to
+ * a struct regmap.
+ */
+struct regmap *regmap_init_spmi(struct spmi_device *sdev,
+				const struct regmap_config *config)
+{
+	return regmap_init(&sdev->dev, &regmap_spmi, sdev, config);
+}
+EXPORT_SYMBOL_GPL(regmap_init_spmi);
+
+/**
+ * devm_regmap_init_spmi(): Initialise managed register map
+ *
+ * @sdev: Device that will be interacted with
+ * @config: Configuration for register map
+ *
+ * The return value will be an ERR_PTR() on error or a valid pointer
+ * to a struct regmap.  The regmap will be automatically freed by the
+ * device management code.
+ */
+struct regmap *devm_regmap_init_spmi(struct spmi_device *sdev,
+				     const struct regmap_config *config)
+{
+	return devm_regmap_init(&sdev->dev, &regmap_spmi, sdev, config);
+}
+EXPORT_SYMBOL_GPL(devm_regmap_init_spmi);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 7d689a1..9c021d9 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -42,15 +42,6 @@
 static int _regmap_bus_raw_write(void *context, unsigned int reg,
 				 unsigned int val);
 
-static void async_cleanup(struct work_struct *work)
-{
-	struct regmap_async *async = container_of(work, struct regmap_async,
-						  cleanup);
-
-	kfree(async->work_buf);
-	kfree(async);
-}
-
 bool regmap_reg_in_ranges(unsigned int reg,
 			  const struct regmap_range *ranges,
 			  unsigned int nranges)
@@ -465,6 +456,7 @@
 
 	spin_lock_init(&map->async_lock);
 	INIT_LIST_HEAD(&map->async_list);
+	INIT_LIST_HEAD(&map->async_free);
 	init_waitqueue_head(&map->async_waitq);
 
 	if (config->read_flag_mask || config->write_flag_mask) {
@@ -821,6 +813,8 @@
 	rm_field->reg = reg_field.reg;
 	rm_field->shift = reg_field.lsb;
 	rm_field->mask = ((BIT(field_bits) - 1) << reg_field.lsb);
+	rm_field->id_size = reg_field.id_size;
+	rm_field->id_offset = reg_field.id_offset;
 }
 
 /**
@@ -942,12 +936,22 @@
  */
 void regmap_exit(struct regmap *map)
 {
+	struct regmap_async *async;
+
 	regcache_exit(map);
 	regmap_debugfs_exit(map);
 	regmap_range_exit(map);
 	if (map->bus && map->bus->free_context)
 		map->bus->free_context(map->bus_context);
 	kfree(map->work_buf);
+	while (!list_empty(&map->async_free)) {
+		async = list_first_entry_or_null(&map->async_free,
+						 struct regmap_async,
+						 list);
+		list_del(&async->list);
+		kfree(async->work_buf);
+		kfree(async);
+	}
 	kfree(map);
 }
 EXPORT_SYMBOL_GPL(regmap_exit);
@@ -1039,7 +1043,7 @@
 }
 
 int _regmap_raw_write(struct regmap *map, unsigned int reg,
-		      const void *val, size_t val_len, bool async)
+		      const void *val, size_t val_len)
 {
 	struct regmap_range_node *range;
 	unsigned long flags;
@@ -1091,7 +1095,7 @@
 			dev_dbg(map->dev, "Writing window %d/%zu\n",
 				win_residue, val_len / map->format.val_bytes);
 			ret = _regmap_raw_write(map, reg, val, win_residue *
-						map->format.val_bytes, async);
+						map->format.val_bytes);
 			if (ret != 0)
 				return ret;
 
@@ -1114,49 +1118,72 @@
 
 	u8[0] |= map->write_flag_mask;
 
-	if (async && map->bus->async_write) {
-		struct regmap_async *async = map->bus->async_alloc();
-		if (!async)
-			return -ENOMEM;
+	/*
+	 * Essentially all I/O mechanisms will be faster with a single
+	 * buffer to write.  Since register syncs often generate raw
+	 * writes of single registers optimise that case.
+	 */
+	if (val != work_val && val_len == map->format.val_bytes) {
+		memcpy(work_val, val, map->format.val_bytes);
+		val = work_val;
+	}
+
+	if (map->async && map->bus->async_write) {
+		struct regmap_async *async;
 
 		trace_regmap_async_write_start(map->dev, reg, val_len);
 
-		async->work_buf = kzalloc(map->format.buf_size,
-					  GFP_KERNEL | GFP_DMA);
-		if (!async->work_buf) {
-			kfree(async);
-			return -ENOMEM;
+		spin_lock_irqsave(&map->async_lock, flags);
+		async = list_first_entry_or_null(&map->async_free,
+						 struct regmap_async,
+						 list);
+		if (async)
+			list_del(&async->list);
+		spin_unlock_irqrestore(&map->async_lock, flags);
+
+		if (!async) {
+			async = map->bus->async_alloc();
+			if (!async)
+				return -ENOMEM;
+
+			async->work_buf = kzalloc(map->format.buf_size,
+						  GFP_KERNEL | GFP_DMA);
+			if (!async->work_buf) {
+				kfree(async);
+				return -ENOMEM;
+			}
 		}
 
-		INIT_WORK(&async->cleanup, async_cleanup);
 		async->map = map;
 
 		/* If the caller supplied the value we can use it safely. */
 		memcpy(async->work_buf, map->work_buf, map->format.pad_bytes +
 		       map->format.reg_bytes + map->format.val_bytes);
-		if (val == work_val)
-			val = async->work_buf + map->format.pad_bytes +
-				map->format.reg_bytes;
 
 		spin_lock_irqsave(&map->async_lock, flags);
 		list_add_tail(&async->list, &map->async_list);
 		spin_unlock_irqrestore(&map->async_lock, flags);
 
-		ret = map->bus->async_write(map->bus_context, async->work_buf,
-					    map->format.reg_bytes +
-					    map->format.pad_bytes,
-					    val, val_len, async);
+		if (val != work_val)
+			ret = map->bus->async_write(map->bus_context,
+						    async->work_buf,
+						    map->format.reg_bytes +
+						    map->format.pad_bytes,
+						    val, val_len, async);
+		else
+			ret = map->bus->async_write(map->bus_context,
+						    async->work_buf,
+						    map->format.reg_bytes +
+						    map->format.pad_bytes +
+						    val_len, NULL, 0, async);
 
 		if (ret != 0) {
 			dev_err(map->dev, "Failed to schedule write: %d\n",
 				ret);
 
 			spin_lock_irqsave(&map->async_lock, flags);
-			list_del(&async->list);
+			list_move(&async->list, &map->async_free);
 			spin_unlock_irqrestore(&map->async_lock, flags);
-
-			kfree(async->work_buf);
-			kfree(async);
 		}
 
 		return ret;
@@ -1253,7 +1280,7 @@
 				 map->work_buf +
 				 map->format.reg_bytes +
 				 map->format.pad_bytes,
-				 map->format.val_bytes, false);
+				 map->format.val_bytes);
 }
 
 static inline void *_regmap_map_get_context(struct regmap *map)
@@ -1318,6 +1345,37 @@
 EXPORT_SYMBOL_GPL(regmap_write);
 
 /**
+ * regmap_write_async(): Write a value to a single register asynchronously
+ *
+ * @map: Register map to write to
+ * @reg: Register to write to
+ * @val: Value to be written
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_write_async(struct regmap *map, unsigned int reg, unsigned int val)
+{
+	int ret;
+
+	if (reg % map->reg_stride)
+		return -EINVAL;
+
+	map->lock(map->lock_arg);
+
+	map->async = true;
+
+	ret = _regmap_write(map, reg, val);
+
+	map->async = false;
+
+	map->unlock(map->lock_arg);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_write_async);
+
+/**
  * regmap_raw_write(): Write raw values to one or more registers
  *
  * @map: Register map to write to
@@ -1345,7 +1403,7 @@
 
 	map->lock(map->lock_arg);
 
-	ret = _regmap_raw_write(map, reg, val, val_len, false);
+	ret = _regmap_raw_write(map, reg, val, val_len);
 
 	map->unlock(map->lock_arg);
 
@@ -1369,6 +1427,74 @@
 }
 EXPORT_SYMBOL_GPL(regmap_field_write);
 
+/**
+ * regmap_field_update_bits():	Perform a read/modify/write cycle
+ *                              on the register field
+ *
+ * @field: Register field to write to
+ * @mask: Bitmask to change
+ * @val: Value to be written
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_field_update_bits(struct regmap_field *field, unsigned int mask, unsigned int val)
+{
+	mask = (mask << field->shift) & field->mask;
+
+	return regmap_update_bits(field->regmap, field->reg,
+				  mask, val << field->shift);
+}
+EXPORT_SYMBOL_GPL(regmap_field_update_bits);
+
+/**
+ * regmap_fields_write(): Write a value to a single register field with port ID
+ *
+ * @field: Register field to write to
+ * @id: port ID
+ * @val: Value to be written
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_fields_write(struct regmap_field *field, unsigned int id,
+			unsigned int val)
+{
+	if (id >= field->id_size)
+		return -EINVAL;
+
+	return regmap_update_bits(field->regmap,
+				  field->reg + (field->id_offset * id),
+				  field->mask, val << field->shift);
+}
+EXPORT_SYMBOL_GPL(regmap_fields_write);
+
+/**
+ * regmap_fields_update_bits():	Perform a read/modify/write cycle
+ *                              on the register field
+ *
+ * @field: Register field to write to
+ * @id: port ID
+ * @mask: Bitmask to change
+ * @val: Value to be written
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_fields_update_bits(struct regmap_field *field,  unsigned int id,
+			      unsigned int mask, unsigned int val)
+{
+	if (id >= field->id_size)
+		return -EINVAL;
+
+	mask = (mask << field->shift) & field->mask;
+
+	return regmap_update_bits(field->regmap,
+				  field->reg + (field->id_offset * id),
+				  mask, val << field->shift);
+}
+EXPORT_SYMBOL_GPL(regmap_fields_update_bits);
+
 /*
  * regmap_bulk_write(): Write multiple registers to the device
  *
@@ -1418,16 +1544,15 @@
 	 */
 	if (map->use_single_rw) {
 		for (i = 0; i < val_count; i++) {
-			ret = regmap_raw_write(map,
-					       reg + (i * map->reg_stride),
-					       val + (i * val_bytes),
-					       val_bytes);
+			ret = _regmap_raw_write(map,
+						reg + (i * map->reg_stride),
+						val + (i * val_bytes),
+						val_bytes);
 			if (ret != 0)
 				return ret;
 		}
 	} else {
-		ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count,
-					false);
+		ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count);
 	}
 
 	if (val_bytes != 1)
@@ -1439,6 +1564,47 @@
 }
 EXPORT_SYMBOL_GPL(regmap_bulk_write);
 
+/*
+ * regmap_multi_reg_write(): Write multiple registers to the device
+ *
+ * where the set of register are supplied in any order
+ *
+ * @map: Register map to write to
+ * @regs: Array of structures containing register,value to be written
+ * @num_regs: Number of registers to write
+ *
+ * This function is intended to be used for writing a large block of data
+ * atomically to the device in single transfer for those I2C client devices
+ * that implement this alternative block write mode.
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_multi_reg_write(struct regmap *map, struct reg_default *regs,
+				int num_regs)
+{
+	int ret = 0, i;
+
+	for (i = 0; i < num_regs; i++) {
+		int reg = regs[i].reg;
+		if (reg % map->reg_stride)
+			return -EINVAL;
+	}
+
+	map->lock(map->lock_arg);
+
+	for (i = 0; i < num_regs; i++) {
+		ret = _regmap_write(map, regs[i].reg, regs[i].def);
+		if (ret != 0)
+			goto out;
+	}
+out:
+	map->unlock(map->lock_arg);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_multi_reg_write);
+
 /**
  * regmap_raw_write_async(): Write raw values to one or more registers
  *                           asynchronously
@@ -1473,7 +1639,11 @@
 
 	map->lock(map->lock_arg);
 
-	ret = _regmap_raw_write(map, reg, val, val_len, true);
+	map->async = true;
+
+	ret = _regmap_raw_write(map, reg, val, val_len);
+
+	map->async = false;
 
 	map->unlock(map->lock_arg);
 
@@ -1677,6 +1847,39 @@
 EXPORT_SYMBOL_GPL(regmap_field_read);
 
 /**
+ * regmap_fields_read(): Read a value to a single register field with port ID
+ *
+ * @field: Register field to read from
+ * @id: port ID
+ * @val: Pointer to store read value
+ *
+ * A value of zero will be returned on success, a negative errno will
+ * be returned in error cases.
+ */
+int regmap_fields_read(struct regmap_field *field, unsigned int id,
+		       unsigned int *val)
+{
+	int ret;
+	unsigned int reg_val;
+
+	if (id >= field->id_size)
+		return -EINVAL;
+
+	ret = regmap_read(field->regmap,
+			  field->reg + (field->id_offset * id),
+			  &reg_val);
+	if (ret != 0)
+		return ret;
+
+	reg_val &= field->mask;
+	reg_val >>= field->shift;
+	*val = reg_val;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_fields_read);
+
+/**
  * regmap_bulk_read(): Read multiple registers from the device
  *
  * @map: Register map to write to
@@ -1788,6 +1991,41 @@
 EXPORT_SYMBOL_GPL(regmap_update_bits);
 
 /**
+ * regmap_update_bits_async: Perform a read/modify/write cycle on the register
+ *                           map asynchronously
+ *
+ * @map: Register map to update
+ * @reg: Register to update
+ * @mask: Bitmask to change
+ * @val: New value for bitmask
+ *
+ * With most buses the read must be done synchronously so this is most
+ * useful for devices with a cache which do not need to interact with
+ * the hardware to determine the current register value.
+ *
+ * Returns zero for success, a negative number on error.
+ */
+int regmap_update_bits_async(struct regmap *map, unsigned int reg,
+			     unsigned int mask, unsigned int val)
+{
+	bool change;
+	int ret;
+
+	map->lock(map->lock_arg);
+
+	map->async = true;
+
+	ret = _regmap_update_bits(map, reg, mask, val, &change);
+
+	map->async = false;
+
+	map->unlock(map->lock_arg);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_update_bits_async);
+
+/**
  * regmap_update_bits_check: Perform a read/modify/write cycle on the
  *                           register map and report if updated
  *
@@ -1812,6 +2050,43 @@
 }
 EXPORT_SYMBOL_GPL(regmap_update_bits_check);
 
+/**
+ * regmap_update_bits_check_async: Perform a read/modify/write cycle on the
+ *                                 register map asynchronously and report if
+ *                                 updated
+ *
+ * @map: Register map to update
+ * @reg: Register to update
+ * @mask: Bitmask to change
+ * @val: New value for bitmask
+ * @change: Boolean indicating if a write was done
+ *
+ * With most buses the read must be done synchronously so this is most
+ * useful for devices with a cache which do not need to interact with
+ * the hardware to determine the current register value.
+ *
+ * Returns zero for success, a negative number on error.
+ */
+int regmap_update_bits_check_async(struct regmap *map, unsigned int reg,
+				   unsigned int mask, unsigned int val,
+				   bool *change)
+{
+	int ret;
+
+	map->lock(map->lock_arg);
+
+	map->async = true;
+
+	ret = _regmap_update_bits(map, reg, mask, val, change);
+
+	map->async = false;
+
+	map->unlock(map->lock_arg);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regmap_update_bits_check_async);
+
 void regmap_async_complete_cb(struct regmap_async *async, int ret)
 {
 	struct regmap *map = async->map;
@@ -1820,8 +2095,7 @@
 	trace_regmap_async_io_complete(map->dev);
 
 	spin_lock(&map->async_lock);
-
-	list_del(&async->list);
+	list_move(&async->list, &map->async_free);
 	wake = list_empty(&map->async_list);
 
 	if (ret != 0)
@@ -1829,8 +2103,6 @@
 
 	spin_unlock(&map->async_lock);
 
-	schedule_work(&async->cleanup);
-
 	if (wake)
 		wake_up(&map->async_waitq);
 }
@@ -1906,6 +2178,7 @@
 	bypass = map->cache_bypass;
 
 	map->cache_bypass = true;
+	map->async = true;
 
 	/* Write out first; it's useful to apply even if we fail later. */
 	for (i = 0; i < num_regs; i++) {
@@ -1929,10 +2202,13 @@
 	}
 
 out:
+	map->async = false;
 	map->cache_bypass = bypass;
 
 	map->unlock(map->lock_arg);
 
+	regmap_async_complete(map);
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(regmap_register_patch);
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 90ee350..e15430a 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -30,28 +30,37 @@
 	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
 	return sprintf(buf, "0x%03X\n", core->id.manuf);
 }
+static DEVICE_ATTR_RO(manuf);
+
 static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
 	return sprintf(buf, "0x%03X\n", core->id.id);
 }
+static DEVICE_ATTR_RO(id);
+
 static ssize_t rev_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
 	return sprintf(buf, "0x%02X\n", core->id.rev);
 }
+static DEVICE_ATTR_RO(rev);
+
 static ssize_t class_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct bcma_device *core = container_of(dev, struct bcma_device, dev);
 	return sprintf(buf, "0x%X\n", core->id.class);
 }
-static struct device_attribute bcma_device_attrs[] = {
-	__ATTR_RO(manuf),
-	__ATTR_RO(id),
-	__ATTR_RO(rev),
-	__ATTR_RO(class),
-	__ATTR_NULL,
+static DEVICE_ATTR_RO(class);
+
+static struct attribute *bcma_device_attrs[] = {
+	&dev_attr_manuf.attr,
+	&dev_attr_id.attr,
+	&dev_attr_rev.attr,
+	&dev_attr_class.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(bcma_device);
 
 static struct bus_type bcma_bus_type = {
 	.name		= "bcma",
@@ -59,7 +68,7 @@
 	.probe		= bcma_device_probe,
 	.remove		= bcma_device_remove,
 	.uevent		= bcma_device_uevent,
-	.dev_attrs	= bcma_device_attrs,
+	.dev_groups	= bcma_device_groups,
 };
 
 static u16 bcma_cc_core_id(struct bcma_bus *bus)
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index e07a5fd..e67fa16 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -505,7 +505,7 @@
 config BLK_DEV_HD
 	bool "Very old hard disk (MFM/RLL/IDE) driver"
 	depends on HAVE_IDE
-	depends on !ARM || ARCH_RPC || ARCH_SHARK || BROKEN
+	depends on !ARM || ARCH_RPC || BROKEN
 	help
 	  This is a very old hard disk driver that lacks the enhanced
 	  functionality of the newer ones.
diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index 2009266..bb5b90e 100644
--- a/drivers/bus/arm-cci.c
+++ b/drivers/bus/arm-cci.c
@@ -18,11 +18,21 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/spinlock.h>
 
 #include <asm/cacheflush.h>
+#include <asm/irq_regs.h>
+#include <asm/pmu.h>
 #include <asm/smp_plat.h>
 
+#define DRIVER_NAME		"CCI-400"
+#define DRIVER_NAME_PMU		DRIVER_NAME " PMU"
+#define PMU_NAME		"CCI_400"
+
 #define CCI_PORT_CTRL		0x0
 #define CCI_CTRL_STATUS		0xc
 
@@ -54,6 +64,568 @@
 static void __iomem *cci_ctrl_base;
 static unsigned long cci_ctrl_phys;
 
+#ifdef CONFIG_HW_PERF_EVENTS
+
+#define CCI_PMCR		0x0100
+#define CCI_PID2		0x0fe8
+
+#define CCI_PMCR_CEN		0x00000001
+#define CCI_PMCR_NCNT_MASK	0x0000f800
+#define CCI_PMCR_NCNT_SHIFT	11
+
+#define CCI_PID2_REV_MASK	0xf0
+#define CCI_PID2_REV_SHIFT	4
+
+/* Port ids */
+#define CCI_PORT_S0	0
+#define CCI_PORT_S1	1
+#define CCI_PORT_S2	2
+#define CCI_PORT_S3	3
+#define CCI_PORT_S4	4
+#define CCI_PORT_M0	5
+#define CCI_PORT_M1	6
+#define CCI_PORT_M2	7
+
+#define CCI_REV_R0		0
+#define CCI_REV_R1		1
+#define CCI_REV_R0_P4		4
+#define CCI_REV_R1_P2		6
+
+#define CCI_PMU_EVT_SEL		0x000
+#define CCI_PMU_CNTR		0x004
+#define CCI_PMU_CNTR_CTRL	0x008
+#define CCI_PMU_OVRFLW		0x00c
+
+#define CCI_PMU_OVRFLW_FLAG	1
+
+#define CCI_PMU_CNTR_BASE(idx)	((idx) * SZ_4K)
+
+/*
+ * Instead of an event id to monitor CCI cycles, a dedicated counter is
+ * provided. Use 0xff to represent CCI cycles and hope that no future revisions
+ * make use of this event in hardware.
+ */
+enum cci400_perf_events {
+	CCI_PMU_CYCLES = 0xff
+};
+
+#define CCI_PMU_EVENT_MASK		0xff
+#define CCI_PMU_EVENT_SOURCE(event)	((event >> 5) & 0x7)
+#define CCI_PMU_EVENT_CODE(event)	(event & 0x1f)
+
+#define CCI_PMU_MAX_HW_EVENTS 5   /* CCI PMU has 4 counters + 1 cycle counter */
+
+#define CCI_PMU_CYCLE_CNTR_IDX		0
+#define CCI_PMU_CNTR0_IDX		1
+#define CCI_PMU_CNTR_LAST(cci_pmu)	(CCI_PMU_CYCLE_CNTR_IDX + cci_pmu->num_events - 1)
+
+/*
+ * CCI PMU event id is an 8-bit value made of two parts - bits 7:5 for one of 8
+ * ports and bits 4:0 are event codes. There are different event codes
+ * associated with each port type.
+ *
+ * Additionally, the range of events associated with the port types changed
+ * between Rev0 and Rev1.
+ *
+ * The constants below define the range of valid codes for each port type for
+ * the different revisions and are used to validate the event to be monitored.
+ */
+
+#define CCI_REV_R0_SLAVE_PORT_MIN_EV	0x00
+#define CCI_REV_R0_SLAVE_PORT_MAX_EV	0x13
+#define CCI_REV_R0_MASTER_PORT_MIN_EV	0x14
+#define CCI_REV_R0_MASTER_PORT_MAX_EV	0x1a
+
+#define CCI_REV_R1_SLAVE_PORT_MIN_EV	0x00
+#define CCI_REV_R1_SLAVE_PORT_MAX_EV	0x14
+#define CCI_REV_R1_MASTER_PORT_MIN_EV	0x00
+#define CCI_REV_R1_MASTER_PORT_MAX_EV	0x11
+
+struct pmu_port_event_ranges {
+	u8 slave_min;
+	u8 slave_max;
+	u8 master_min;
+	u8 master_max;
+};
+
+static struct pmu_port_event_ranges port_event_range[] = {
+	[CCI_REV_R0] = {
+		.slave_min = CCI_REV_R0_SLAVE_PORT_MIN_EV,
+		.slave_max = CCI_REV_R0_SLAVE_PORT_MAX_EV,
+		.master_min = CCI_REV_R0_MASTER_PORT_MIN_EV,
+		.master_max = CCI_REV_R0_MASTER_PORT_MAX_EV,
+	},
+	[CCI_REV_R1] = {
+		.slave_min = CCI_REV_R1_SLAVE_PORT_MIN_EV,
+		.slave_max = CCI_REV_R1_SLAVE_PORT_MAX_EV,
+		.master_min = CCI_REV_R1_MASTER_PORT_MIN_EV,
+		.master_max = CCI_REV_R1_MASTER_PORT_MAX_EV,
+	},
+};
+
+struct cci_pmu_drv_data {
+	void __iomem *base;
+	struct arm_pmu *cci_pmu;
+	int nr_irqs;
+	int irqs[CCI_PMU_MAX_HW_EVENTS];
+	unsigned long active_irqs;
+	struct perf_event *events[CCI_PMU_MAX_HW_EVENTS];
+	unsigned long used_mask[BITS_TO_LONGS(CCI_PMU_MAX_HW_EVENTS)];
+	struct pmu_port_event_ranges *port_ranges;
+	struct pmu_hw_events hw_events;
+};
+static struct cci_pmu_drv_data *pmu;
+
+static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs)
+{
+	int i;
+
+	for (i = 0; i < nr_irqs; i++)
+		if (irq == irqs[i])
+			return true;
+
+	return false;
+}
+
+static int probe_cci_revision(void)
+{
+	int rev;
+	rev = readl_relaxed(cci_ctrl_base + CCI_PID2) & CCI_PID2_REV_MASK;
+	rev >>= CCI_PID2_REV_SHIFT;
+
+	if (rev <= CCI_REV_R0_P4)
+		return CCI_REV_R0;
+	else if (rev <= CCI_REV_R1_P2)
+		return CCI_REV_R1;
+
+	return -ENOENT;
+}
+
+static struct pmu_port_event_ranges *port_range_by_rev(void)
+{
+	int rev = probe_cci_revision();
+
+	if (rev < 0)
+		return NULL;
+
+	return &port_event_range[rev];
+}
+
+static int pmu_is_valid_slave_event(u8 ev_code)
+{
+	return pmu->port_ranges->slave_min <= ev_code &&
+		ev_code <= pmu->port_ranges->slave_max;
+}
+
+static int pmu_is_valid_master_event(u8 ev_code)
+{
+	return pmu->port_ranges->master_min <= ev_code &&
+		ev_code <= pmu->port_ranges->master_max;
+}
+
+static int pmu_validate_hw_event(u8 hw_event)
+{
+	u8 ev_source = CCI_PMU_EVENT_SOURCE(hw_event);
+	u8 ev_code = CCI_PMU_EVENT_CODE(hw_event);
+
+	switch (ev_source) {
+	case CCI_PORT_S0:
+	case CCI_PORT_S1:
+	case CCI_PORT_S2:
+	case CCI_PORT_S3:
+	case CCI_PORT_S4:
+		/* Slave Interface */
+		if (pmu_is_valid_slave_event(ev_code))
+			return hw_event;
+		break;
+	case CCI_PORT_M0:
+	case CCI_PORT_M1:
+	case CCI_PORT_M2:
+		/* Master Interface */
+		if (pmu_is_valid_master_event(ev_code))
+			return hw_event;
+		break;
+	}
+
+	return -ENOENT;
+}
+
+static int pmu_is_valid_counter(struct arm_pmu *cci_pmu, int idx)
+{
+	return CCI_PMU_CYCLE_CNTR_IDX <= idx &&
+		idx <= CCI_PMU_CNTR_LAST(cci_pmu);
+}
+
+static u32 pmu_read_register(int idx, unsigned int offset)
+{
+	return readl_relaxed(pmu->base + CCI_PMU_CNTR_BASE(idx) + offset);
+}
+
+static void pmu_write_register(u32 value, int idx, unsigned int offset)
+{
+	return writel_relaxed(value, pmu->base + CCI_PMU_CNTR_BASE(idx) + offset);
+}
+
+static void pmu_disable_counter(int idx)
+{
+	pmu_write_register(0, idx, CCI_PMU_CNTR_CTRL);
+}
+
+static void pmu_enable_counter(int idx)
+{
+	pmu_write_register(1, idx, CCI_PMU_CNTR_CTRL);
+}
+
+static void pmu_set_event(int idx, unsigned long event)
+{
+	event &= CCI_PMU_EVENT_MASK;
+	pmu_write_register(event, idx, CCI_PMU_EVT_SEL);
+}
+
+static u32 pmu_get_max_counters(void)
+{
+	u32 n_cnts = (readl_relaxed(cci_ctrl_base + CCI_PMCR) &
+		      CCI_PMCR_NCNT_MASK) >> CCI_PMCR_NCNT_SHIFT;
+
+	/* add 1 for cycle counter */
+	return n_cnts + 1;
+}
+
+static struct pmu_hw_events *pmu_get_hw_events(void)
+{
+	return &pmu->hw_events;
+}
+
+static int pmu_get_event_idx(struct pmu_hw_events *hw, struct perf_event *event)
+{
+	struct arm_pmu *cci_pmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event *hw_event = &event->hw;
+	unsigned long cci_event = hw_event->config_base & CCI_PMU_EVENT_MASK;
+	int idx;
+
+	if (cci_event == CCI_PMU_CYCLES) {
+		if (test_and_set_bit(CCI_PMU_CYCLE_CNTR_IDX, hw->used_mask))
+			return -EAGAIN;
+
+		return CCI_PMU_CYCLE_CNTR_IDX;
+	}
+
+	for (idx = CCI_PMU_CNTR0_IDX; idx <= CCI_PMU_CNTR_LAST(cci_pmu); ++idx)
+		if (!test_and_set_bit(idx, hw->used_mask))
+			return idx;
+
+	/* No counters available */
+	return -EAGAIN;
+}
+
+static int pmu_map_event(struct perf_event *event)
+{
+	int mapping;
+	u8 config = event->attr.config & CCI_PMU_EVENT_MASK;
+
+	if (event->attr.type < PERF_TYPE_MAX)
+		return -ENOENT;
+
+	if (config == CCI_PMU_CYCLES)
+		mapping = config;
+	else
+		mapping = pmu_validate_hw_event(config);
+
+	return mapping;
+}
+
+static int pmu_request_irq(struct arm_pmu *cci_pmu, irq_handler_t handler)
+{
+	int i;
+	struct platform_device *pmu_device = cci_pmu->plat_device;
+
+	if (unlikely(!pmu_device))
+		return -ENODEV;
+
+	if (pmu->nr_irqs < 1) {
+		dev_err(&pmu_device->dev, "no irqs for CCI PMUs defined\n");
+		return -ENODEV;
+	}
+
+	/*
+	 * Register all available CCI PMU interrupts. In the interrupt handler
+	 * we iterate over the counters checking for interrupt source (the
+	 * overflowing counter) and clear it.
+	 *
+	 * This should allow handling of non-unique interrupt for the counters.
+	 */
+	for (i = 0; i < pmu->nr_irqs; i++) {
+		int err = request_irq(pmu->irqs[i], handler, IRQF_SHARED,
+				"arm-cci-pmu", cci_pmu);
+		if (err) {
+			dev_err(&pmu_device->dev, "unable to request IRQ%d for ARM CCI PMU counters\n",
+				pmu->irqs[i]);
+			return err;
+		}
+
+		set_bit(i, &pmu->active_irqs);
+	}
+
+	return 0;
+}
+
+static irqreturn_t pmu_handle_irq(int irq_num, void *dev)
+{
+	unsigned long flags;
+	struct arm_pmu *cci_pmu = (struct arm_pmu *)dev;
+	struct pmu_hw_events *events = cci_pmu->get_hw_events();
+	struct perf_sample_data data;
+	struct pt_regs *regs;
+	int idx, handled = IRQ_NONE;
+
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
+	regs = get_irq_regs();
+	/*
+	 * Iterate over counters and update the corresponding perf events.
+	 * This should work regardless of whether we have per-counter overflow
+	 * interrupt or a combined overflow interrupt.
+	 */
+	for (idx = CCI_PMU_CYCLE_CNTR_IDX; idx <= CCI_PMU_CNTR_LAST(cci_pmu); idx++) {
+		struct perf_event *event = events->events[idx];
+		struct hw_perf_event *hw_counter;
+
+		if (!event)
+			continue;
+
+		hw_counter = &event->hw;
+
+		/* Did this counter overflow? */
+		if (!pmu_read_register(idx, CCI_PMU_OVRFLW) & CCI_PMU_OVRFLW_FLAG)
+			continue;
+
+		pmu_write_register(CCI_PMU_OVRFLW_FLAG, idx, CCI_PMU_OVRFLW);
+
+		handled = IRQ_HANDLED;
+
+		armpmu_event_update(event);
+		perf_sample_data_init(&data, 0, hw_counter->last_period);
+		if (!armpmu_event_set_period(event))
+			continue;
+
+		if (perf_event_overflow(event, &data, regs))
+			cci_pmu->disable(event);
+	}
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+
+	return IRQ_RETVAL(handled);
+}
+
+static void pmu_free_irq(struct arm_pmu *cci_pmu)
+{
+	int i;
+
+	for (i = 0; i < pmu->nr_irqs; i++) {
+		if (!test_and_clear_bit(i, &pmu->active_irqs))
+			continue;
+
+		free_irq(pmu->irqs[i], cci_pmu);
+	}
+}
+
+static void pmu_enable_event(struct perf_event *event)
+{
+	unsigned long flags;
+	struct arm_pmu *cci_pmu = to_arm_pmu(event->pmu);
+	struct pmu_hw_events *events = cci_pmu->get_hw_events();
+	struct hw_perf_event *hw_counter = &event->hw;
+	int idx = hw_counter->idx;
+
+	if (unlikely(!pmu_is_valid_counter(cci_pmu, idx))) {
+		dev_err(&cci_pmu->plat_device->dev, "Invalid CCI PMU counter %d\n", idx);
+		return;
+	}
+
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
+
+	/* Configure the event to count, unless you are counting cycles */
+	if (idx != CCI_PMU_CYCLE_CNTR_IDX)
+		pmu_set_event(idx, hw_counter->config_base);
+
+	pmu_enable_counter(idx);
+
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+}
+
+static void pmu_disable_event(struct perf_event *event)
+{
+	struct arm_pmu *cci_pmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event *hw_counter = &event->hw;
+	int idx = hw_counter->idx;
+
+	if (unlikely(!pmu_is_valid_counter(cci_pmu, idx))) {
+		dev_err(&cci_pmu->plat_device->dev, "Invalid CCI PMU counter %d\n", idx);
+		return;
+	}
+
+	pmu_disable_counter(idx);
+}
+
+static void pmu_start(struct arm_pmu *cci_pmu)
+{
+	u32 val;
+	unsigned long flags;
+	struct pmu_hw_events *events = cci_pmu->get_hw_events();
+
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
+
+	/* Enable all the PMU counters. */
+	val = readl_relaxed(cci_ctrl_base + CCI_PMCR) | CCI_PMCR_CEN;
+	writel(val, cci_ctrl_base + CCI_PMCR);
+
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+}
+
+static void pmu_stop(struct arm_pmu *cci_pmu)
+{
+	u32 val;
+	unsigned long flags;
+	struct pmu_hw_events *events = cci_pmu->get_hw_events();
+
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
+
+	/* Disable all the PMU counters. */
+	val = readl_relaxed(cci_ctrl_base + CCI_PMCR) & ~CCI_PMCR_CEN;
+	writel(val, cci_ctrl_base + CCI_PMCR);
+
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+}
+
+static u32 pmu_read_counter(struct perf_event *event)
+{
+	struct arm_pmu *cci_pmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event *hw_counter = &event->hw;
+	int idx = hw_counter->idx;
+	u32 value;
+
+	if (unlikely(!pmu_is_valid_counter(cci_pmu, idx))) {
+		dev_err(&cci_pmu->plat_device->dev, "Invalid CCI PMU counter %d\n", idx);
+		return 0;
+	}
+	value = pmu_read_register(idx, CCI_PMU_CNTR);
+
+	return value;
+}
+
+static void pmu_write_counter(struct perf_event *event, u32 value)
+{
+	struct arm_pmu *cci_pmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event *hw_counter = &event->hw;
+	int idx = hw_counter->idx;
+
+	if (unlikely(!pmu_is_valid_counter(cci_pmu, idx)))
+		dev_err(&cci_pmu->plat_device->dev, "Invalid CCI PMU counter %d\n", idx);
+	else
+		pmu_write_register(value, idx, CCI_PMU_CNTR);
+}
+
+static int cci_pmu_init(struct arm_pmu *cci_pmu, struct platform_device *pdev)
+{
+	*cci_pmu = (struct arm_pmu){
+		.name             = PMU_NAME,
+		.max_period       = (1LLU << 32) - 1,
+		.get_hw_events    = pmu_get_hw_events,
+		.get_event_idx    = pmu_get_event_idx,
+		.map_event        = pmu_map_event,
+		.request_irq      = pmu_request_irq,
+		.handle_irq       = pmu_handle_irq,
+		.free_irq         = pmu_free_irq,
+		.enable           = pmu_enable_event,
+		.disable          = pmu_disable_event,
+		.start            = pmu_start,
+		.stop             = pmu_stop,
+		.read_counter     = pmu_read_counter,
+		.write_counter    = pmu_write_counter,
+	};
+
+	cci_pmu->plat_device = pdev;
+	cci_pmu->num_events = pmu_get_max_counters();
+
+	return armpmu_register(cci_pmu, -1);
+}
+
+static const struct of_device_id arm_cci_pmu_matches[] = {
+	{
+		.compatible = "arm,cci-400-pmu",
+	},
+	{},
+};
+
+static int cci_pmu_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int i, ret, irq;
+
+	pmu = devm_kzalloc(&pdev->dev, sizeof(*pmu), GFP_KERNEL);
+	if (!pmu)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	pmu->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(pmu->base))
+		return -ENOMEM;
+
+	/*
+	 * CCI PMU has 5 overflow signals - one per counter; but some may be tied
+	 * together to a common interrupt.
+	 */
+	pmu->nr_irqs = 0;
+	for (i = 0; i < CCI_PMU_MAX_HW_EVENTS; i++) {
+		irq = platform_get_irq(pdev, i);
+		if (irq < 0)
+			break;
+
+		if (is_duplicate_irq(irq, pmu->irqs, pmu->nr_irqs))
+			continue;
+
+		pmu->irqs[pmu->nr_irqs++] = irq;
+	}
+
+	/*
+	 * Ensure that the device tree has as many interrupts as the number
+	 * of counters.
+	 */
+	if (i < CCI_PMU_MAX_HW_EVENTS) {
+		dev_warn(&pdev->dev, "In-correct number of interrupts: %d, should be %d\n",
+			i, CCI_PMU_MAX_HW_EVENTS);
+		return -EINVAL;
+	}
+
+	pmu->port_ranges = port_range_by_rev();
+	if (!pmu->port_ranges) {
+		dev_warn(&pdev->dev, "CCI PMU version not supported\n");
+		return -EINVAL;
+	}
+
+	pmu->cci_pmu = devm_kzalloc(&pdev->dev, sizeof(*(pmu->cci_pmu)), GFP_KERNEL);
+	if (!pmu->cci_pmu)
+		return -ENOMEM;
+
+	pmu->hw_events.events = pmu->events;
+	pmu->hw_events.used_mask = pmu->used_mask;
+	raw_spin_lock_init(&pmu->hw_events.pmu_lock);
+
+	ret = cci_pmu_init(pmu->cci_pmu, pdev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int cci_platform_probe(struct platform_device *pdev)
+{
+	if (!cci_probed())
+		return -ENODEV;
+
+	return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+}
+
+#endif /* CONFIG_HW_PERF_EVENTS */
+
 struct cpu_port {
 	u64 mpidr;
 	u32 port;
@@ -120,7 +692,7 @@
 }
 EXPORT_SYMBOL_GPL(cci_ace_get_port);
 
-static void __init cci_ace_init_ports(void)
+static void cci_ace_init_ports(void)
 {
 	int port, cpu;
 	struct device_node *cpun;
@@ -386,7 +958,7 @@
 	{},
 };
 
-static int __init cci_probe(void)
+static int cci_probe(void)
 {
 	struct cci_nb_ports const *cci_config;
 	int ret, i, nb_ace = 0, nb_ace_lite = 0;
@@ -490,7 +1062,7 @@
 static int cci_init_status = -EAGAIN;
 static DEFINE_MUTEX(cci_probing);
 
-static int __init cci_init(void)
+static int cci_init(void)
 {
 	if (cci_init_status != -EAGAIN)
 		return cci_init_status;
@@ -502,18 +1074,55 @@
 	return cci_init_status;
 }
 
+#ifdef CONFIG_HW_PERF_EVENTS
+static struct platform_driver cci_pmu_driver = {
+	.driver = {
+		   .name = DRIVER_NAME_PMU,
+		   .of_match_table = arm_cci_pmu_matches,
+		  },
+	.probe = cci_pmu_probe,
+};
+
+static struct platform_driver cci_platform_driver = {
+	.driver = {
+		   .name = DRIVER_NAME,
+		   .of_match_table = arm_cci_matches,
+		  },
+	.probe = cci_platform_probe,
+};
+
+static int __init cci_platform_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&cci_pmu_driver);
+	if (ret)
+		return ret;
+
+	return platform_driver_register(&cci_platform_driver);
+}
+
+#else
+
+static int __init cci_platform_init(void)
+{
+	return 0;
+}
+
+#endif
 /*
  * To sort out early init calls ordering a helper function is provided to
  * check if the CCI driver has beed initialized. Function check if the driver
  * has been initialized, if not it calls the init function that probes
  * the driver and updates the return value.
  */
-bool __init cci_probed(void)
+bool cci_probed(void)
 {
 	return cci_init() == 0;
 }
 EXPORT_SYMBOL_GPL(cci_probed);
 
 early_initcall(cci_init);
+core_initcall(cci_platform_init);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("ARM CCI support");
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c
index 0671e45..8fedbc2 100644
--- a/drivers/char/bsr.c
+++ b/drivers/char/bsr.c
@@ -21,6 +21,7 @@
 
 #include <linux/kernel.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 #include <linux/fs.h>
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 448ce5e..dca5834 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -486,8 +486,7 @@
 		}
 
 		sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev));
-		irq_flags = devp->hd_flags & HPET_SHARED_IRQ
-						? IRQF_SHARED : IRQF_DISABLED;
+		irq_flags = devp->hd_flags & HPET_SHARED_IRQ ? IRQF_SHARED : 0;
 		if (request_irq(irq, hpet_interrupt, irq_flags,
 				devp->hd_name, (void *)devp)) {
 			printk(KERN_ERR "hpet: IRQ %d is not free\n", irq);
@@ -971,8 +970,6 @@
 		struct acpi_resource_fixed_memory32 *fixmem32;
 
 		fixmem32 = &res->data.fixed_memory32;
-		if (!fixmem32)
-			return AE_NO_MEMORY;
 
 		hdp->hd_phys_address = fixmem32->address;
 		hdp->hd_address = ioremap(fixmem32->address,
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 0aa9d91..c206de2 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -290,6 +290,19 @@
 
 	  If unsure, say Y.
 
+config HW_RANDOM_POWERNV
+	tristate "PowerNV Random Number Generator support"
+	depends on HW_RANDOM && PPC_POWERNV
+	default HW_RANDOM
+	---help---
+	  This is the driver for Random Number Generator hardware found
+	  in POWER7+ and above machines for PowerNV platform.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called powernv-rng.
+
+	  If unsure, say Y.
+
 config HW_RANDOM_EXYNOS
 	tristate "EXYNOS HW random number generator support"
 	depends on HW_RANDOM && HAS_IOMEM && HAVE_CLK
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index bed467c..d7d2435 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -24,6 +24,7 @@
 obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o
 obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o
 obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
+obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o
 obj-$(CONFIG_HW_RANDOM_EXYNOS)	+= exynos-rng.o
 obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o
 obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c
index c6df5b2..c66279b 100644
--- a/drivers/char/hw_random/pasemi-rng.c
+++ b/drivers/char/hw_random/pasemi-rng.c
@@ -24,6 +24,7 @@
 #include <linux/platform_device.h>
 #include <linux/hw_random.h>
 #include <linux/delay.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <asm/io.h>
 
diff --git a/drivers/char/hw_random/powernv-rng.c b/drivers/char/hw_random/powernv-rng.c
new file mode 100644
index 0000000..3f4f632
--- /dev/null
+++ b/drivers/char/hw_random/powernv-rng.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013 Michael Ellerman, Guo Chao, IBM 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; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/random.h>
+#include <linux/hw_random.h>
+
+static int powernv_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+{
+	unsigned long *buf;
+	int i, len;
+
+	/* We rely on rng_buffer_size() being >= sizeof(unsigned long) */
+	len = max / sizeof(unsigned long);
+
+	buf = (unsigned long *)data;
+
+	for (i = 0; i < len; i++)
+		powernv_get_random_long(buf++);
+
+	return len * sizeof(unsigned long);
+}
+
+static struct hwrng powernv_hwrng = {
+	.name = "powernv-rng",
+	.read = powernv_rng_read,
+};
+
+static int powernv_rng_remove(struct platform_device *pdev)
+{
+	hwrng_unregister(&powernv_hwrng);
+
+	return 0;
+}
+
+static int powernv_rng_probe(struct platform_device *pdev)
+{
+	int rc;
+
+	rc = hwrng_register(&powernv_hwrng);
+	if (rc) {
+		/* We only register one device, ignore any others */
+		if (rc == -EEXIST)
+			rc = -ENODEV;
+
+		return rc;
+	}
+
+	pr_info("Registered powernv hwrng.\n");
+
+	return 0;
+}
+
+static struct of_device_id powernv_rng_match[] = {
+	{ .compatible	= "ibm,power-rng",},
+	{},
+};
+MODULE_DEVICE_TABLE(of, powernv_rng_match);
+
+static struct platform_driver powernv_rng_driver = {
+	.driver = {
+		.name = "powernv_rng",
+		.of_match_table = powernv_rng_match,
+	},
+	.probe	= powernv_rng_probe,
+	.remove = powernv_rng_remove,
+};
+module_platform_driver(powernv_rng_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Bare metal HWRNG driver for POWER7+ and above");
diff --git a/drivers/char/hw_random/ppc4xx-rng.c b/drivers/char/hw_random/ppc4xx-rng.c
index 732c330..521f76b 100644
--- a/drivers/char/hw_random/ppc4xx-rng.c
+++ b/drivers/char/hw_random/ppc4xx-rng.c
@@ -13,6 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/hw_random.h>
 #include <linux/delay.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <asm/io.h>
 
diff --git a/drivers/char/hw_random/pseries-rng.c b/drivers/char/hw_random/pseries-rng.c
index 5f11979..b761459a 100644
--- a/drivers/char/hw_random/pseries-rng.c
+++ b/drivers/char/hw_random/pseries-rng.c
@@ -17,6 +17,9 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/hw_random.h>
 #include <asm/vio.h>
@@ -25,10 +28,15 @@
 
 static int pseries_rng_data_read(struct hwrng *rng, u32 *data)
 {
-	if (plpar_hcall(H_RANDOM, (unsigned long *)data) != H_SUCCESS) {
-		printk(KERN_ERR "pseries rng hcall error\n");
-		return 0;
+	int rc;
+
+	rc = plpar_hcall(H_RANDOM, (unsigned long *)data);
+	if (rc != H_SUCCESS) {
+		pr_err_ratelimited("H_RANDOM call failed %d\n", rc);
+		return -EIO;
 	}
+
+	/* The hypervisor interface returns 64 bits */
 	return 8;
 }
 
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index fd0f7c4..ffa97d2 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -187,8 +187,8 @@
 	if (misc->minor == MISC_DYNAMIC_MINOR) {
 		int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);
 		if (i >= DYNAMIC_MINORS) {
-			mutex_unlock(&misc_mtx);
-			return -EBUSY;
+			err = -EBUSY;
+			goto out;
 		}
 		misc->minor = DYNAMIC_MINORS - i - 1;
 		set_bit(i, misc_minors);
@@ -197,8 +197,8 @@
 
 		list_for_each_entry(c, &misc_list, list) {
 			if (c->minor == misc->minor) {
-				mutex_unlock(&misc_mtx);
-				return -EBUSY;
+				err = -EBUSY;
+				goto out;
 			}
 		}
 	}
diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c
index cfdfe49..1fd00dc0 100644
--- a/drivers/char/nwbutton.c
+++ b/drivers/char/nwbutton.c
@@ -220,7 +220,7 @@
 		return -EBUSY;
 	}
 
-	if (request_irq (IRQ_NETWINDER_BUTTON, button_handler, IRQF_DISABLED,
+	if (request_irq (IRQ_NETWINDER_BUTTON, button_handler, 0,
 			"nwbutton", NULL)) {
 		printk (KERN_WARNING "nwbutton: IRQ %d is not free.\n",
 				IRQ_NETWINDER_BUTTON);
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 7737b5b..7a744d3 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -640,7 +640,7 @@
  */
 void add_device_randomness(const void *buf, unsigned int size)
 {
-	unsigned long time = get_cycles() ^ jiffies;
+	unsigned long time = random_get_entropy() ^ jiffies;
 
 	mix_pool_bytes(&input_pool, buf, size, NULL);
 	mix_pool_bytes(&input_pool, &time, sizeof(time), NULL);
@@ -677,7 +677,7 @@
 		goto out;
 
 	sample.jiffies = jiffies;
-	sample.cycles = get_cycles();
+	sample.cycles = random_get_entropy();
 	sample.num = num;
 	mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL);
 
@@ -744,7 +744,7 @@
 	struct fast_pool	*fast_pool = &__get_cpu_var(irq_randomness);
 	struct pt_regs		*regs = get_irq_regs();
 	unsigned long		now = jiffies;
-	__u32			input[4], cycles = get_cycles();
+	__u32			input[4], cycles = random_get_entropy();
 
 	input[0] = cycles ^ jiffies;
 	input[1] = irq;
@@ -1459,12 +1459,11 @@
 
 static u32 random_int_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned;
 
-static int __init random_int_secret_init(void)
+int random_int_secret_init(void)
 {
 	get_random_bytes(random_int_secret, sizeof(random_int_secret));
 	return 0;
 }
-late_initcall(random_int_secret_init);
 
 /*
  * Get a random word for internal kernel use only. Similar to urandom but
@@ -1483,7 +1482,7 @@
 
 	hash = get_cpu_var(get_random_int_hash);
 
-	hash[0] += current->pid + jiffies + get_cycles();
+	hash[0] += current->pid + jiffies + random_get_entropy();
 	md5_transform(hash, random_int_secret);
 	ret = hash[0];
 	put_cpu_var(get_random_int_hash);
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index c0cbbd4..3525996 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -227,7 +227,7 @@
 
 #ifdef RTC_IRQ
 /*
- *	A very tiny interrupt handler. It runs with IRQF_DISABLED set,
+ *	A very tiny interrupt handler. It runs with interrupts disabled,
  *	but there is possibility of conflicting with the set_rtc_mmss()
  *	call (the rtc irq and the timer irq can easily run at the same
  *	time in two different CPUs). So we need to serialize
@@ -1040,8 +1040,7 @@
 		rtc_int_handler_ptr = rtc_interrupt;
 	}
 
-	if (request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED,
-			"rtc", NULL)) {
+	if (request_irq(RTC_IRQ, rtc_int_handler_ptr, 0, "rtc", NULL)) {
 		/* Yeah right, seeing as irq 8 doesn't even hit the bus. */
 		rtc_has_irq = 0;
 		printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ);
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index 5816b39..8bab592 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -108,8 +108,7 @@
 	/* hook this subchannel up to the system controller interrupt */
 	mutex_lock(&scdrv_mutex);
 	rv = request_irq(SGI_UART_VECTOR, scdrv_interrupt,
-			 IRQF_SHARED | IRQF_DISABLED,
-			 SYSCTL_BASENAME, sd);
+			 IRQF_SHARED, SYSCTL_BASENAME, sd);
 	if (rv) {
 		ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
 		kfree(sd);
diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c
index ee15694..59bcefd 100644
--- a/drivers/char/snsc_event.c
+++ b/drivers/char/snsc_event.c
@@ -292,8 +292,7 @@
 
 	/* hook event subchannel up to the system controller interrupt */
 	rv = request_irq(SGI_UART_VECTOR, scdrv_event_interrupt,
-			 IRQF_SHARED | IRQF_DISABLED,
-			 "system controller events", event_sd);
+			 IRQF_SHARED, "system controller events", event_sd);
 	if (rv) {
 		printk(KERN_WARNING "%s: irq request failed (%d)\n",
 		       __func__, rv);
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index e95e0ab..100cd1d 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -222,7 +222,7 @@
 	/* This device is wired through the FPGA IO space of the ATCA blade
 	 * we can't share this IRQ */
 	result = request_irq(telclk_interrupt, &tlclk_interrupt,
-			     IRQF_DISABLED, "telco_clock", tlclk_interrupt);
+			     0, "telco_clock", tlclk_interrupt);
 	if (result == -EBUSY)
 		printk(KERN_ERR "tlclk: Interrupt can't be reserved.\n");
 	else
diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c
index 06189e5..94c280d 100644
--- a/drivers/char/tpm/xen-tpmfront.c
+++ b/drivers/char/tpm/xen-tpmfront.c
@@ -10,6 +10,7 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
+#include <xen/xen.h>
 #include <xen/events.h>
 #include <xen/interface/io/tpmif.h>
 #include <xen/grant_table.h>
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index 5224da5..f6345f9 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -721,7 +721,7 @@
 {
 	struct hwicap_drvdata *drvdata;
 
-	drvdata = (struct hwicap_drvdata *)dev_get_drvdata(dev);
+	drvdata = dev_get_drvdata(dev);
 
 	if (!drvdata)
 		return 0;
@@ -731,7 +731,6 @@
 	iounmap(drvdata->base_address);
 	release_mem_region(drvdata->mem_start, drvdata->mem_size);
 	kfree(drvdata);
-	dev_set_drvdata(dev, NULL);
 
 	mutex_lock(&icap_sem);
 	probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0;
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 279407a..5c51115 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -93,6 +93,20 @@
 	  This adds the clock driver support for Freescale PowerPC corenet
 	  platforms using common clock framework.
 
+config COMMON_CLK_XGENE
+	bool "Clock driver for APM XGene SoC"
+	default y
+	depends on ARM64
+	---help---
+	  Sypport for the APM X-Gene SoC reference, PLL, and device clocks.
+
+config COMMON_CLK_KEYSTONE
+	tristate "Clock drivers for Keystone based SOCs"
+	depends on ARCH_KEYSTONE && OF
+	---help---
+          Supports clock drivers for Keystone based SOCs. These SOCs have local
+	  a power sleep control module that gate the clock to the IPs and PLLs.
+
 endmenu
 
 source "drivers/clk/mvebu/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 7b11106..7a10bc9 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -11,6 +11,7 @@
 
 # SoCs specific
 obj-$(CONFIG_ARCH_BCM2835)	+= clk-bcm2835.o
+obj-$(CONFIG_ARCH_EFM32)	+= clk-efm32gg.o
 obj-$(CONFIG_ARCH_NOMADIK)	+= clk-nomadik.o
 obj-$(CONFIG_ARCH_HIGHBANK)	+= clk-highbank.o
 obj-$(CONFIG_ARCH_NSPIRE)	+= clk-nspire.o
@@ -32,6 +33,8 @@
 obj-$(CONFIG_ARCH_ZYNQ)		+= zynq/
 obj-$(CONFIG_ARCH_TEGRA)	+= tegra/
 obj-$(CONFIG_PLAT_SAMSUNG)	+= samsung/
+obj-$(CONFIG_COMMON_CLK_XGENE)  += clk-xgene.o
+obj-$(CONFIG_COMMON_CLK_KEYSTONE)	+= keystone/
 
 obj-$(CONFIG_X86)		+= x86/
 
diff --git a/drivers/clk/clk-bcm2835.c b/drivers/clk/clk-bcm2835.c
index 5fb4ff5..6b950ca 100644
--- a/drivers/clk/clk-bcm2835.c
+++ b/drivers/clk/clk-bcm2835.c
@@ -20,14 +20,8 @@
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/clk/bcm2835.h>
-#include <linux/clk-provider.h>
 #include <linux/of.h>
 
-static const struct of_device_id clk_match[] __initconst = {
-	{ .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
-	{ }
-};
-
 /*
  * These are fixed clocks. They're probably not all root clocks and it may
  * be possible to turn them on and off but until this is mapped out better
@@ -63,6 +57,4 @@
 	ret = clk_register_clkdev(clk, NULL, "20215000.uart");
 	if (ret)
 		pr_err("uart1_pclk alias not registered\n");
-
-	of_clk_init(clk_match);
 }
diff --git a/drivers/clk/clk-efm32gg.c b/drivers/clk/clk-efm32gg.c
new file mode 100644
index 0000000..bac2ddf
--- /dev/null
+++ b/drivers/clk/clk-efm32gg.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2013 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <dt-bindings/clock/efm32-cmu.h>
+
+#define CMU_HFPERCLKEN0		0x44
+
+static struct clk *clk[37];
+static struct clk_onecell_data clk_data = {
+	.clks = clk,
+	.clk_num = ARRAY_SIZE(clk),
+};
+
+static int __init efm32gg_cmu_init(struct device_node *np)
+{
+	int i;
+	void __iomem *base;
+
+	for (i = 0; i < ARRAY_SIZE(clk); ++i)
+		clk[i] = ERR_PTR(-ENOENT);
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		pr_warn("Failed to map address range for efm32gg,cmu node\n");
+		return -EADDRNOTAVAIL;
+	}
+
+	clk[clk_HFXO] = clk_register_fixed_rate(NULL, "HFXO", NULL,
+			CLK_IS_ROOT, 48000000);
+
+	clk[clk_HFPERCLKUSART0] = clk_register_gate(NULL, "HFPERCLK.USART0",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 0, 0, NULL);
+	clk[clk_HFPERCLKUSART1] = clk_register_gate(NULL, "HFPERCLK.USART1",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 1, 0, NULL);
+	clk[clk_HFPERCLKUSART2] = clk_register_gate(NULL, "HFPERCLK.USART2",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 2, 0, NULL);
+	clk[clk_HFPERCLKUART0] = clk_register_gate(NULL, "HFPERCLK.UART0",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 3, 0, NULL);
+	clk[clk_HFPERCLKUART1] = clk_register_gate(NULL, "HFPERCLK.UART1",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 4, 0, NULL);
+	clk[clk_HFPERCLKTIMER0] = clk_register_gate(NULL, "HFPERCLK.TIMER0",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 5, 0, NULL);
+	clk[clk_HFPERCLKTIMER1] = clk_register_gate(NULL, "HFPERCLK.TIMER1",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 6, 0, NULL);
+	clk[clk_HFPERCLKTIMER2] = clk_register_gate(NULL, "HFPERCLK.TIMER2",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 7, 0, NULL);
+	clk[clk_HFPERCLKTIMER3] = clk_register_gate(NULL, "HFPERCLK.TIMER3",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 8, 0, NULL);
+	clk[clk_HFPERCLKACMP0] = clk_register_gate(NULL, "HFPERCLK.ACMP0",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 9, 0, NULL);
+	clk[clk_HFPERCLKACMP1] = clk_register_gate(NULL, "HFPERCLK.ACMP1",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 10, 0, NULL);
+	clk[clk_HFPERCLKI2C0] = clk_register_gate(NULL, "HFPERCLK.I2C0",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 11, 0, NULL);
+	clk[clk_HFPERCLKI2C1] = clk_register_gate(NULL, "HFPERCLK.I2C1",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 12, 0, NULL);
+	clk[clk_HFPERCLKGPIO] = clk_register_gate(NULL, "HFPERCLK.GPIO",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 13, 0, NULL);
+	clk[clk_HFPERCLKVCMP] = clk_register_gate(NULL, "HFPERCLK.VCMP",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 14, 0, NULL);
+	clk[clk_HFPERCLKPRS] = clk_register_gate(NULL, "HFPERCLK.PRS",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 15, 0, NULL);
+	clk[clk_HFPERCLKADC0] = clk_register_gate(NULL, "HFPERCLK.ADC0",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 16, 0, NULL);
+	clk[clk_HFPERCLKDAC0] = clk_register_gate(NULL, "HFPERCLK.DAC0",
+			"HFXO", 0, base + CMU_HFPERCLKEN0, 17, 0, NULL);
+
+	return of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+CLK_OF_DECLARE(efm32ggcmu, "efm32gg,cmu", efm32gg_cmu_init);
diff --git a/drivers/clk/clk-highbank.c b/drivers/clk/clk-highbank.c
index 2e08cb0..2e7e9d9 100644
--- a/drivers/clk/clk-highbank.c
+++ b/drivers/clk/clk-highbank.c
@@ -20,8 +20,7 @@
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/of.h>
-
-extern void __iomem *sregs_base;
+#include <linux/of_address.h>
 
 #define HB_PLL_LOCK_500		0x20000000
 #define HB_PLL_LOCK		0x10000000
@@ -280,6 +279,7 @@
 	const char *clk_name = node->name;
 	const char *parent_name;
 	struct clk_init_data init;
+	struct device_node *srnp;
 	int rc;
 
 	rc = of_property_read_u32(node, "reg", &reg);
@@ -290,7 +290,11 @@
 	if (WARN_ON(!hb_clk))
 		return NULL;
 
-	hb_clk->reg = sregs_base + reg;
+	/* Map system registers */
+	srnp = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs");
+	hb_clk->reg = of_iomap(srnp, 0);
+	BUG_ON(!hb_clk->reg);
+	hb_clk->reg += reg;
 
 	of_property_read_string(node, "clock-output-names", &clk_name);
 
diff --git a/drivers/clk/clk-nomadik.c b/drivers/clk/clk-nomadik.c
index 51410c2..6a934a5 100644
--- a/drivers/clk/clk-nomadik.c
+++ b/drivers/clk/clk-nomadik.c
@@ -27,6 +27,14 @@
  */
 
 #define SRC_CR			0x00U
+#define SRC_CR_T0_ENSEL		BIT(15)
+#define SRC_CR_T1_ENSEL		BIT(17)
+#define SRC_CR_T2_ENSEL		BIT(19)
+#define SRC_CR_T3_ENSEL		BIT(21)
+#define SRC_CR_T4_ENSEL		BIT(23)
+#define SRC_CR_T5_ENSEL		BIT(25)
+#define SRC_CR_T6_ENSEL		BIT(27)
+#define SRC_CR_T7_ENSEL		BIT(29)
 #define SRC_XTALCR		0x0CU
 #define SRC_XTALCR_XTALTIMEN	BIT(20)
 #define SRC_XTALCR_SXTALDIS	BIT(19)
@@ -54,6 +62,79 @@
 /* Base address of the SRC */
 static void __iomem *src_base;
 
+static int nomadik_clk_reboot_handler(struct notifier_block *this,
+				unsigned long code,
+				void *unused)
+{
+	u32 val;
+
+	/* The main chrystal need to be enabled for reboot to work */
+	val = readl(src_base + SRC_XTALCR);
+	val &= ~SRC_XTALCR_MXTALOVER;
+	val |= SRC_XTALCR_MXTALEN;
+	pr_crit("force-enabling MXTALO\n");
+	writel(val, src_base + SRC_XTALCR);
+	return NOTIFY_OK;
+}
+
+static struct notifier_block nomadik_clk_reboot_notifier = {
+	.notifier_call = nomadik_clk_reboot_handler,
+};
+
+static const struct of_device_id nomadik_src_match[] __initconst = {
+	{ .compatible = "stericsson,nomadik-src" },
+	{ /* sentinel */ }
+};
+
+static void __init nomadik_src_init(void)
+{
+	struct device_node *np;
+	u32 val;
+
+	np = of_find_matching_node(NULL, nomadik_src_match);
+	if (!np) {
+		pr_crit("no matching node for SRC, aborting clock init\n");
+		return;
+	}
+	src_base = of_iomap(np, 0);
+	if (!src_base) {
+		pr_err("%s: must have src parent node with REGS (%s)\n",
+		       __func__, np->name);
+		return;
+	}
+
+	/* Set all timers to use the 2.4 MHz TIMCLK */
+	val = readl(src_base + SRC_CR);
+	val |= SRC_CR_T0_ENSEL;
+	val |= SRC_CR_T1_ENSEL;
+	val |= SRC_CR_T2_ENSEL;
+	val |= SRC_CR_T3_ENSEL;
+	val |= SRC_CR_T4_ENSEL;
+	val |= SRC_CR_T5_ENSEL;
+	val |= SRC_CR_T6_ENSEL;
+	val |= SRC_CR_T7_ENSEL;
+	writel(val, src_base + SRC_CR);
+
+	val = readl(src_base + SRC_XTALCR);
+	pr_info("SXTALO is %s\n",
+		(val & SRC_XTALCR_SXTALDIS) ? "disabled" : "enabled");
+	pr_info("MXTAL is %s\n",
+		(val & SRC_XTALCR_MXTALSTAT) ? "enabled" : "disabled");
+	if (of_property_read_bool(np, "disable-sxtalo")) {
+		/* The machine uses an external oscillator circuit */
+		val |= SRC_XTALCR_SXTALDIS;
+		pr_info("disabling SXTALO\n");
+	}
+	if (of_property_read_bool(np, "disable-mxtalo")) {
+		/* Disable this too: also run by external oscillator */
+		val |= SRC_XTALCR_MXTALOVER;
+		val &= ~SRC_XTALCR_MXTALEN;
+		pr_info("disabling MXTALO\n");
+	}
+	writel(val, src_base + SRC_XTALCR);
+	register_reboot_notifier(&nomadik_clk_reboot_notifier);
+}
+
 /**
  * struct clk_pll1 - Nomadik PLL1 clock
  * @hw: corresponding clock hardware entry
@@ -431,6 +512,9 @@
 	const char *parent_name;
 	u32 pll_id;
 
+	if (!src_base)
+		nomadik_src_init();
+
 	if (of_property_read_u32(np, "pll-id", &pll_id)) {
 		pr_err("%s: PLL \"%s\" missing pll-id property\n",
 			__func__, clk_name);
@@ -441,6 +525,8 @@
 	if (!IS_ERR(clk))
 		of_clk_add_provider(np, of_clk_src_simple_get, clk);
 }
+CLK_OF_DECLARE(nomadik_pll_clk,
+	"st,nomadik-pll-clock", of_nomadik_pll_setup);
 
 static void __init of_nomadik_hclk_setup(struct device_node *np)
 {
@@ -448,6 +534,9 @@
 	const char *clk_name = np->name;
 	const char *parent_name;
 
+	if (!src_base)
+		nomadik_src_init();
+
 	parent_name = of_clk_get_parent_name(np, 0);
 	/*
 	 * The HCLK divides PLL1 with 1 (passthru), 2, 3 or 4.
@@ -460,6 +549,8 @@
 	if (!IS_ERR(clk))
 		of_clk_add_provider(np, of_clk_src_simple_get, clk);
 }
+CLK_OF_DECLARE(nomadik_hclk_clk,
+	"st,nomadik-hclk-clock", of_nomadik_hclk_setup);
 
 static void __init of_nomadik_src_clk_setup(struct device_node *np)
 {
@@ -468,6 +559,9 @@
 	const char *parent_name;
 	u32 clk_id;
 
+	if (!src_base)
+		nomadik_src_init();
+
 	if (of_property_read_u32(np, "clock-id", &clk_id)) {
 		pr_err("%s: SRC clock \"%s\" missing clock-id property\n",
 			__func__, clk_name);
@@ -478,89 +572,5 @@
 	if (!IS_ERR(clk))
 		of_clk_add_provider(np, of_clk_src_simple_get, clk);
 }
-
-static const struct of_device_id nomadik_src_match[] __initconst = {
-	{ .compatible = "stericsson,nomadik-src" },
-	{ /* sentinel */ }
-};
-
-static const struct of_device_id nomadik_src_clk_match[] __initconst = {
-	{
-		.compatible = "fixed-clock",
-		.data = of_fixed_clk_setup,
-	},
-	{
-		.compatible = "fixed-factor-clock",
-		.data = of_fixed_factor_clk_setup,
-	},
-	{
-		.compatible = "st,nomadik-pll-clock",
-		.data = of_nomadik_pll_setup,
-	},
-	{
-		.compatible = "st,nomadik-hclk-clock",
-		.data = of_nomadik_hclk_setup,
-	},
-	{
-		.compatible = "st,nomadik-src-clock",
-		.data = of_nomadik_src_clk_setup,
-	},
-	{ /* sentinel */ }
-};
-
-static int nomadik_clk_reboot_handler(struct notifier_block *this,
-				unsigned long code,
-				void *unused)
-{
-	u32 val;
-
-	/* The main chrystal need to be enabled for reboot to work */
-	val = readl(src_base + SRC_XTALCR);
-	val &= ~SRC_XTALCR_MXTALOVER;
-	val |= SRC_XTALCR_MXTALEN;
-	pr_crit("force-enabling MXTALO\n");
-	writel(val, src_base + SRC_XTALCR);
-	return NOTIFY_OK;
-}
-
-static struct notifier_block nomadik_clk_reboot_notifier = {
-	.notifier_call = nomadik_clk_reboot_handler,
-};
-
-void __init nomadik_clk_init(void)
-{
-	struct device_node *np;
-	u32 val;
-
-	np = of_find_matching_node(NULL, nomadik_src_match);
-	if (!np) {
-		pr_crit("no matching node for SRC, aborting clock init\n");
-		return;
-	}
-	src_base = of_iomap(np, 0);
-	if (!src_base) {
-		pr_err("%s: must have src parent node with REGS (%s)\n",
-		       __func__, np->name);
-		return;
-	}
-	val = readl(src_base + SRC_XTALCR);
-	pr_info("SXTALO is %s\n",
-		(val & SRC_XTALCR_SXTALDIS) ? "disabled" : "enabled");
-	pr_info("MXTAL is %s\n",
-		(val & SRC_XTALCR_MXTALSTAT) ? "enabled" : "disabled");
-	if (of_property_read_bool(np, "disable-sxtalo")) {
-		/* The machine uses an external oscillator circuit */
-		val |= SRC_XTALCR_SXTALDIS;
-		pr_info("disabling SXTALO\n");
-	}
-	if (of_property_read_bool(np, "disable-mxtalo")) {
-		/* Disable this too: also run by external oscillator */
-		val |= SRC_XTALCR_MXTALOVER;
-		val &= ~SRC_XTALCR_MXTALEN;
-		pr_info("disabling MXTALO\n");
-	}
-	writel(val, src_base + SRC_XTALCR);
-	register_reboot_notifier(&nomadik_clk_reboot_notifier);
-
-	of_clk_init(nomadik_src_clk_match);
-}
+CLK_OF_DECLARE(nomadik_src_clk,
+	"st,nomadik-src-clock", of_nomadik_src_clk_setup);
diff --git a/drivers/clk/clk-ppc-corenet.c b/drivers/clk/clk-ppc-corenet.c
index e9587073..c4f76ed 100644
--- a/drivers/clk/clk-ppc-corenet.c
+++ b/drivers/clk/clk-ppc-corenet.c
@@ -11,6 +11,7 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/of.h>
 #include <linux/slab.h>
diff --git a/drivers/clk/clk-prima2.c b/drivers/clk/clk-prima2.c
index 5ab95f1..6c15e33 100644
--- a/drivers/clk/clk-prima2.c
+++ b/drivers/clk/clk-prima2.c
@@ -1015,16 +1015,6 @@
 	},
 };
 
-static struct of_device_id clkc_ids[] = {
-	{ .compatible = "sirf,prima2-clkc" },
-	{},
-};
-
-static struct of_device_id rsc_ids[] = {
-	{ .compatible = "sirf,prima2-rsc" },
-	{},
-};
-
 enum prima2_clk_index {
 	/* 0    1     2      3      4      5      6       7         8      9 */
 	rtc,    osc,   pll1,  pll2,  pll3,  mem,   sys,   security, dsp,   gps,
@@ -1082,24 +1072,16 @@
 static struct clk *prima2_clks[maxclk];
 static struct clk_onecell_data clk_data;
 
-void __init sirfsoc_of_clk_init(void)
+static void __init sirfsoc_clk_init(struct device_node *np)
 {
-	struct device_node *np;
+	struct device_node *rscnp;
 	int i;
 
-	np = of_find_matching_node(NULL, rsc_ids);
-	if (!np)
-		panic("unable to find compatible rsc node in dtb\n");
-
-	sirfsoc_rsc_vbase = of_iomap(np, 0);
+	rscnp = of_find_compatible_node(NULL, NULL, "sirf,prima2-rsc");
+	sirfsoc_rsc_vbase = of_iomap(rscnp, 0);
 	if (!sirfsoc_rsc_vbase)
 		panic("unable to map rsc registers\n");
-
-	of_node_put(np);
-
-	np = of_find_matching_node(NULL, clkc_ids);
-	if (!np)
-		return;
+	of_node_put(rscnp);
 
 	sirfsoc_clk_vbase = of_iomap(np, 0);
 	if (!sirfsoc_clk_vbase)
@@ -1124,3 +1106,4 @@
 
 	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 }
+CLK_OF_DECLARE(sirfsoc_clk, "sirf,prima2-clkc", sirfsoc_clk_init);
diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c
index 82306f5..7fd5c5e 100644
--- a/drivers/clk/clk-vt8500.c
+++ b/drivers/clk/clk-vt8500.c
@@ -15,11 +15,14 @@
 
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/bitops.h>
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 
+#define LEGACY_PMC_BASE		0xD8130000
+
 /* All clocks share the same lock as none can be changed concurrently */
 static DEFINE_SPINLOCK(_lock);
 
@@ -53,6 +56,21 @@
 
 static void __iomem *pmc_base;
 
+static __init void vtwm_set_pmc_base(void)
+{
+	struct device_node *np =
+		of_find_compatible_node(NULL, NULL, "via,vt8500-pmc");
+
+	if (np)
+		pmc_base = of_iomap(np, 0);
+	else
+		pmc_base = ioremap(LEGACY_PMC_BASE, 0x1000);
+	of_node_put(np);
+
+	if (!pmc_base)
+		pr_err("%s:of_iomap(pmc) failed\n", __func__);
+}
+
 #define to_clk_device(_hw) container_of(_hw, struct clk_device, hw)
 
 #define VT8500_PMC_BUSY_MASK		0x18
@@ -222,6 +240,9 @@
 	int rc;
 	int clk_init_flags = 0;
 
+	if (!pmc_base)
+		vtwm_set_pmc_base();
+
 	dev_clk = kzalloc(sizeof(*dev_clk), GFP_KERNEL);
 	if (WARN_ON(!dev_clk))
 		return;
@@ -636,6 +657,9 @@
 	struct clk_init_data init;
 	int rc;
 
+	if (!pmc_base)
+		vtwm_set_pmc_base();
+
 	rc = of_property_read_u32(node, "reg", &reg);
 	if (WARN_ON(rc))
 		return;
@@ -694,13 +718,3 @@
 	vtwm_pll_clk_init(node, PLL_TYPE_WM8850);
 }
 CLK_OF_DECLARE(wm8850_pll, "wm,wm8850-pll-clock", wm8850_pll_init);
-
-void __init vtwm_clk_init(void __iomem *base)
-{
-	if (!base)
-		return;
-
-	pmc_base = base;
-
-	of_clk_init(NULL);
-}
diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c
index 805b4c3..b131041 100644
--- a/drivers/clk/clk-wm831x.c
+++ b/drivers/clk/clk-wm831x.c
@@ -391,14 +391,8 @@
 	return 0;
 }
 
-static int wm831x_clk_remove(struct platform_device *pdev)
-{
-	return 0;
-}
-
 static struct platform_driver wm831x_clk_driver = {
 	.probe = wm831x_clk_probe,
-	.remove = wm831x_clk_remove,
 	.driver		= {
 		.name	= "wm831x-clk",
 		.owner	= THIS_MODULE,
diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c
new file mode 100644
index 0000000..dd8a62d
--- /dev/null
+++ b/drivers/clk/clk-xgene.c
@@ -0,0 +1,521 @@
+/*
+ * clk-xgene.c - AppliedMicro X-Gene Clock Interface
+ *
+ * Copyright (c) 2013, Applied Micro Circuits Corporation
+ * Author: Loc Ho <lho@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/spinlock.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <asm/setup.h>
+
+/* Register SCU_PCPPLL bit fields */
+#define N_DIV_RD(src)			(((src) & 0x000001ff))
+
+/* Register SCU_SOCPLL bit fields */
+#define CLKR_RD(src)			(((src) & 0x07000000)>>24)
+#define CLKOD_RD(src)			(((src) & 0x00300000)>>20)
+#define REGSPEC_RESET_F1_MASK		0x00010000
+#define CLKF_RD(src)			(((src) & 0x000001ff))
+
+#define XGENE_CLK_DRIVER_VER		"0.1"
+
+static DEFINE_SPINLOCK(clk_lock);
+
+static inline u32 xgene_clk_read(void *csr)
+{
+	return readl_relaxed(csr);
+}
+
+static inline void xgene_clk_write(u32 data, void *csr)
+{
+	return writel_relaxed(data, csr);
+}
+
+/* PLL Clock */
+enum xgene_pll_type {
+	PLL_TYPE_PCP = 0,
+	PLL_TYPE_SOC = 1,
+};
+
+struct xgene_clk_pll {
+	struct clk_hw	hw;
+	const char	*name;
+	void __iomem	*reg;
+	spinlock_t	*lock;
+	u32		pll_offset;
+	enum xgene_pll_type	type;
+};
+
+#define to_xgene_clk_pll(_hw) container_of(_hw, struct xgene_clk_pll, hw)
+
+static int xgene_clk_pll_is_enabled(struct clk_hw *hw)
+{
+	struct xgene_clk_pll *pllclk = to_xgene_clk_pll(hw);
+	u32 data;
+
+	data = xgene_clk_read(pllclk->reg + pllclk->pll_offset);
+	pr_debug("%s pll %s\n", pllclk->name,
+		data & REGSPEC_RESET_F1_MASK ? "disabled" : "enabled");
+
+	return data & REGSPEC_RESET_F1_MASK ? 0 : 1;
+}
+
+static unsigned long xgene_clk_pll_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct xgene_clk_pll *pllclk = to_xgene_clk_pll(hw);
+	unsigned long fref;
+	unsigned long fvco;
+	u32 pll;
+	u32 nref;
+	u32 nout;
+	u32 nfb;
+
+	pll = xgene_clk_read(pllclk->reg + pllclk->pll_offset);
+
+	if (pllclk->type == PLL_TYPE_PCP) {
+		/*
+		 * PLL VCO = Reference clock * NF
+		 * PCP PLL = PLL_VCO / 2
+		 */
+		nout = 2;
+		fvco = parent_rate * (N_DIV_RD(pll) + 4);
+	} else {
+		/*
+		 * Fref = Reference Clock / NREF;
+		 * Fvco = Fref * NFB;
+		 * Fout = Fvco / NOUT;
+		 */
+		nref = CLKR_RD(pll) + 1;
+		nout = CLKOD_RD(pll) + 1;
+		nfb = CLKF_RD(pll);
+		fref = parent_rate / nref;
+		fvco = fref * nfb;
+	}
+	pr_debug("%s pll recalc rate %ld parent %ld\n", pllclk->name,
+		fvco / nout, parent_rate);
+
+	return fvco / nout;
+}
+
+const struct clk_ops xgene_clk_pll_ops = {
+	.is_enabled = xgene_clk_pll_is_enabled,
+	.recalc_rate = xgene_clk_pll_recalc_rate,
+};
+
+static struct clk *xgene_register_clk_pll(struct device *dev,
+	const char *name, const char *parent_name,
+	unsigned long flags, void __iomem *reg, u32 pll_offset,
+	u32 type, spinlock_t *lock)
+{
+	struct xgene_clk_pll *apmclk;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/* allocate the APM clock structure */
+	apmclk = kzalloc(sizeof(*apmclk), GFP_KERNEL);
+	if (!apmclk) {
+		pr_err("%s: could not allocate APM clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = name;
+	init.ops = &xgene_clk_pll_ops;
+	init.flags = flags;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
+
+	apmclk->name = name;
+	apmclk->reg = reg;
+	apmclk->lock = lock;
+	apmclk->pll_offset = pll_offset;
+	apmclk->type = type;
+	apmclk->hw.init = &init;
+
+	/* Register the clock */
+	clk = clk_register(dev, &apmclk->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: could not register clk %s\n", __func__, name);
+		kfree(apmclk);
+		return NULL;
+	}
+	return clk;
+}
+
+static void xgene_pllclk_init(struct device_node *np, enum xgene_pll_type pll_type)
+{
+        const char *clk_name = np->full_name;
+        struct clk *clk;
+        void *reg;
+
+        reg = of_iomap(np, 0);
+        if (reg == NULL) {
+                pr_err("Unable to map CSR register for %s\n", np->full_name);
+                return;
+        }
+        of_property_read_string(np, "clock-output-names", &clk_name);
+        clk = xgene_register_clk_pll(NULL,
+                        clk_name, of_clk_get_parent_name(np, 0),
+                        CLK_IS_ROOT, reg, 0, pll_type, &clk_lock);
+        if (!IS_ERR(clk)) {
+                of_clk_add_provider(np, of_clk_src_simple_get, clk);
+                clk_register_clkdev(clk, clk_name, NULL);
+                pr_debug("Add %s clock PLL\n", clk_name);
+        }
+}
+
+static void xgene_socpllclk_init(struct device_node *np)
+{
+	xgene_pllclk_init(np, PLL_TYPE_SOC);
+}
+
+static void xgene_pcppllclk_init(struct device_node *np)
+{
+	xgene_pllclk_init(np, PLL_TYPE_PCP);
+}
+
+/* IP Clock */
+struct xgene_dev_parameters {
+	void __iomem *csr_reg;		/* CSR for IP clock */
+	u32 reg_clk_offset;		/* Offset to clock enable CSR */
+	u32 reg_clk_mask;		/* Mask bit for clock enable */
+	u32 reg_csr_offset;		/* Offset to CSR reset */
+	u32 reg_csr_mask;		/* Mask bit for disable CSR reset */
+	void __iomem *divider_reg;	/* CSR for divider */
+	u32 reg_divider_offset;		/* Offset to divider register */
+	u32 reg_divider_shift;		/* Bit shift to divider field */
+	u32 reg_divider_width;		/* Width of the bit to divider field */
+};
+
+struct xgene_clk {
+	struct clk_hw	hw;
+	const char	*name;
+	spinlock_t	*lock;
+	struct xgene_dev_parameters	param;
+};
+
+#define to_xgene_clk(_hw) container_of(_hw, struct xgene_clk, hw)
+
+static int xgene_clk_enable(struct clk_hw *hw)
+{
+	struct xgene_clk *pclk = to_xgene_clk(hw);
+	unsigned long flags = 0;
+	u32 data;
+
+	if (pclk->lock)
+		spin_lock_irqsave(pclk->lock, flags);
+
+	if (pclk->param.csr_reg != NULL) {
+		pr_debug("%s clock enabled\n", pclk->name);
+		/* First enable the clock */
+		data = xgene_clk_read(pclk->param.csr_reg +
+					pclk->param.reg_clk_offset);
+		data |= pclk->param.reg_clk_mask;
+		xgene_clk_write(data, pclk->param.csr_reg +
+					pclk->param.reg_clk_offset);
+		pr_debug("%s clock PADDR base 0x%016LX clk offset 0x%08X mask 0x%08X value 0x%08X\n",
+			pclk->name, __pa(pclk->param.csr_reg),
+			pclk->param.reg_clk_offset, pclk->param.reg_clk_mask,
+			data);
+
+		/* Second enable the CSR */
+		data = xgene_clk_read(pclk->param.csr_reg +
+					pclk->param.reg_csr_offset);
+		data &= ~pclk->param.reg_csr_mask;
+		xgene_clk_write(data, pclk->param.csr_reg +
+					pclk->param.reg_csr_offset);
+		pr_debug("%s CSR RESET PADDR base 0x%016LX csr offset 0x%08X mask 0x%08X value 0x%08X\n",
+			pclk->name, __pa(pclk->param.csr_reg),
+			pclk->param.reg_csr_offset, pclk->param.reg_csr_mask,
+			data);
+	}
+
+	if (pclk->lock)
+		spin_unlock_irqrestore(pclk->lock, flags);
+
+	return 0;
+}
+
+static void xgene_clk_disable(struct clk_hw *hw)
+{
+	struct xgene_clk *pclk = to_xgene_clk(hw);
+	unsigned long flags = 0;
+	u32 data;
+
+	if (pclk->lock)
+		spin_lock_irqsave(pclk->lock, flags);
+
+	if (pclk->param.csr_reg != NULL) {
+		pr_debug("%s clock disabled\n", pclk->name);
+		/* First put the CSR in reset */
+		data = xgene_clk_read(pclk->param.csr_reg +
+					pclk->param.reg_csr_offset);
+		data |= pclk->param.reg_csr_mask;
+		xgene_clk_write(data, pclk->param.csr_reg +
+					pclk->param.reg_csr_offset);
+
+		/* Second disable the clock */
+		data = xgene_clk_read(pclk->param.csr_reg +
+					pclk->param.reg_clk_offset);
+		data &= ~pclk->param.reg_clk_mask;
+		xgene_clk_write(data, pclk->param.csr_reg +
+					pclk->param.reg_clk_offset);
+	}
+
+	if (pclk->lock)
+		spin_unlock_irqrestore(pclk->lock, flags);
+}
+
+static int xgene_clk_is_enabled(struct clk_hw *hw)
+{
+	struct xgene_clk *pclk = to_xgene_clk(hw);
+	u32 data = 0;
+
+	if (pclk->param.csr_reg != NULL) {
+		pr_debug("%s clock checking\n", pclk->name);
+		data = xgene_clk_read(pclk->param.csr_reg +
+					pclk->param.reg_clk_offset);
+		pr_debug("%s clock is %s\n", pclk->name,
+			data & pclk->param.reg_clk_mask ? "enabled" :
+							"disabled");
+	}
+
+	if (pclk->param.csr_reg == NULL)
+		return 1;
+	return data & pclk->param.reg_clk_mask ? 1 : 0;
+}
+
+static unsigned long xgene_clk_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct xgene_clk *pclk = to_xgene_clk(hw);
+	u32 data;
+
+	if (pclk->param.divider_reg) {
+		data = xgene_clk_read(pclk->param.divider_reg +
+					pclk->param.reg_divider_offset);
+		data >>= pclk->param.reg_divider_shift;
+		data &= (1 << pclk->param.reg_divider_width) - 1;
+
+		pr_debug("%s clock recalc rate %ld parent %ld\n",
+			pclk->name, parent_rate / data, parent_rate);
+		return parent_rate / data;
+	} else {
+		pr_debug("%s clock recalc rate %ld parent %ld\n",
+			pclk->name, parent_rate, parent_rate);
+		return parent_rate;
+	}
+}
+
+static int xgene_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct xgene_clk *pclk = to_xgene_clk(hw);
+	unsigned long flags = 0;
+	u32 data;
+	u32 divider;
+	u32 divider_save;
+
+	if (pclk->lock)
+		spin_lock_irqsave(pclk->lock, flags);
+
+	if (pclk->param.divider_reg) {
+		/* Let's compute the divider */
+		if (rate > parent_rate)
+			rate = parent_rate;
+		divider_save = divider = parent_rate / rate; /* Rounded down */
+		divider &= (1 << pclk->param.reg_divider_width) - 1;
+		divider <<= pclk->param.reg_divider_shift;
+
+		/* Set new divider */
+		data = xgene_clk_read(pclk->param.divider_reg +
+				pclk->param.reg_divider_offset);
+		data &= ~((1 << pclk->param.reg_divider_width) - 1);
+		data |= divider;
+		xgene_clk_write(data, pclk->param.divider_reg +
+					pclk->param.reg_divider_offset);
+		pr_debug("%s clock set rate %ld\n", pclk->name,
+			parent_rate / divider_save);
+	} else {
+		divider_save = 1;
+	}
+
+	if (pclk->lock)
+		spin_unlock_irqrestore(pclk->lock, flags);
+
+	return parent_rate / divider_save;
+}
+
+static long xgene_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	struct xgene_clk *pclk = to_xgene_clk(hw);
+	unsigned long parent_rate = *prate;
+	u32 divider;
+
+	if (pclk->param.divider_reg) {
+		/* Let's compute the divider */
+		if (rate > parent_rate)
+			rate = parent_rate;
+		divider = parent_rate / rate;   /* Rounded down */
+	} else {
+		divider = 1;
+	}
+
+	return parent_rate / divider;
+}
+
+const struct clk_ops xgene_clk_ops = {
+	.enable = xgene_clk_enable,
+	.disable = xgene_clk_disable,
+	.is_enabled = xgene_clk_is_enabled,
+	.recalc_rate = xgene_clk_recalc_rate,
+	.set_rate = xgene_clk_set_rate,
+	.round_rate = xgene_clk_round_rate,
+};
+
+static struct clk *xgene_register_clk(struct device *dev,
+		const char *name, const char *parent_name,
+		struct xgene_dev_parameters *parameters, spinlock_t *lock)
+{
+	struct xgene_clk *apmclk;
+	struct clk *clk;
+	struct clk_init_data init;
+	int rc;
+
+	/* allocate the APM clock structure */
+	apmclk = kzalloc(sizeof(*apmclk), GFP_KERNEL);
+	if (!apmclk) {
+		pr_err("%s: could not allocate APM clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = name;
+	init.ops = &xgene_clk_ops;
+	init.flags = 0;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
+
+	apmclk->name = name;
+	apmclk->lock = lock;
+	apmclk->hw.init = &init;
+	apmclk->param = *parameters;
+
+	/* Register the clock */
+	clk = clk_register(dev, &apmclk->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: could not register clk %s\n", __func__, name);
+		kfree(apmclk);
+		return clk;
+	}
+
+	/* Register the clock for lookup */
+	rc = clk_register_clkdev(clk, name, NULL);
+	if (rc != 0) {
+		pr_err("%s: could not register lookup clk %s\n",
+			__func__, name);
+	}
+	return clk;
+}
+
+static void __init xgene_devclk_init(struct device_node *np)
+{
+	const char *clk_name = np->full_name;
+	struct clk *clk;
+	struct resource res;
+	int rc;
+	struct xgene_dev_parameters parameters;
+	int i;
+
+	/* Check if the entry is disabled */
+        if (!of_device_is_available(np))
+                return;
+
+	/* Parse the DTS register for resource */
+	parameters.csr_reg = NULL;
+	parameters.divider_reg = NULL;
+	for (i = 0; i < 2; i++) {
+		void *map_res;
+		rc = of_address_to_resource(np, i, &res);
+		if (rc != 0) {
+			if (i == 0) {
+				pr_err("no DTS register for %s\n", 
+					np->full_name);
+				return;
+			}
+			break;
+		}
+		map_res = of_iomap(np, i);
+		if (map_res == NULL) {
+			pr_err("Unable to map resource %d for %s\n",
+				i, np->full_name);
+			goto err;
+		}
+		if (strcmp(res.name, "div-reg") == 0)
+			parameters.divider_reg = map_res;
+		else /* if (strcmp(res->name, "csr-reg") == 0) */
+			parameters.csr_reg = map_res;
+	}
+	if (of_property_read_u32(np, "csr-offset", &parameters.reg_csr_offset))
+		parameters.reg_csr_offset = 0;
+	if (of_property_read_u32(np, "csr-mask", &parameters.reg_csr_mask))
+		parameters.reg_csr_mask = 0xF;
+	if (of_property_read_u32(np, "enable-offset",
+				&parameters.reg_clk_offset))
+		parameters.reg_clk_offset = 0x8;
+	if (of_property_read_u32(np, "enable-mask", &parameters.reg_clk_mask))
+		parameters.reg_clk_mask = 0xF;
+	if (of_property_read_u32(np, "divider-offset",
+				&parameters.reg_divider_offset))
+		parameters.reg_divider_offset = 0;
+	if (of_property_read_u32(np, "divider-width",
+				&parameters.reg_divider_width))
+		parameters.reg_divider_width = 0;
+	if (of_property_read_u32(np, "divider-shift",
+				&parameters.reg_divider_shift))
+		parameters.reg_divider_shift = 0;
+	of_property_read_string(np, "clock-output-names", &clk_name);
+
+	clk = xgene_register_clk(NULL, clk_name,
+		of_clk_get_parent_name(np, 0), &parameters, &clk_lock);
+	if (IS_ERR(clk))
+		goto err;
+	pr_debug("Add %s clock\n", clk_name);
+	rc = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+	if (rc != 0)
+		pr_err("%s: could register provider clk %s\n", __func__,
+			np->full_name);
+
+	return;
+
+err:
+	if (parameters.csr_reg)
+		iounmap(parameters.csr_reg);
+	if (parameters.divider_reg)
+		iounmap(parameters.divider_reg);
+}
+
+CLK_OF_DECLARE(xgene_socpll_clock, "apm,xgene-socpll-clock", xgene_socpllclk_init);
+CLK_OF_DECLARE(xgene_pcppll_clock, "apm,xgene-pcppll-clock", xgene_pcppllclk_init);
+CLK_OF_DECLARE(xgene_dev_clock, "apm,xgene-device-clock", xgene_devclk_init);
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index a004769..2cf2ea6 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1080,13 +1080,16 @@
 }
 EXPORT_SYMBOL_GPL(clk_get_rate);
 
-static u8 clk_fetch_parent_index(struct clk *clk, struct clk *parent)
+static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
 {
-	u8 i;
+	int i;
 
-	if (!clk->parents)
-		clk->parents = kzalloc((sizeof(struct clk*) * clk->num_parents),
-								GFP_KERNEL);
+	if (!clk->parents) {
+		clk->parents = kcalloc(clk->num_parents,
+					sizeof(struct clk *), GFP_KERNEL);
+		if (!clk->parents)
+			return -ENOMEM;
+	}
 
 	/*
 	 * find index of new parent clock using cached parent ptrs,
@@ -1094,16 +1097,19 @@
 	 * them now to avoid future calls to __clk_lookup.
 	 */
 	for (i = 0; i < clk->num_parents; i++) {
-		if (clk->parents && clk->parents[i] == parent)
-			break;
-		else if (!strcmp(clk->parent_names[i], parent->name)) {
-			if (clk->parents)
-				clk->parents[i] = __clk_lookup(parent->name);
-			break;
+		if (clk->parents[i] == parent)
+			return i;
+
+		if (clk->parents[i])
+			continue;
+
+		if (!strcmp(clk->parent_names[i], parent->name)) {
+			clk->parents[i] = __clk_lookup(parent->name);
+			return i;
 		}
 	}
 
-	return i;
+	return -EINVAL;
 }
 
 static void clk_reparent(struct clk *clk, struct clk *new_parent)
@@ -1265,7 +1271,7 @@
 	struct clk *old_parent, *parent;
 	unsigned long best_parent_rate = 0;
 	unsigned long new_rate;
-	u8 p_index = 0;
+	int p_index = 0;
 
 	/* sanity */
 	if (IS_ERR_OR_NULL(clk))
@@ -1306,7 +1312,7 @@
 	/* try finding the new parent index */
 	if (parent) {
 		p_index = clk_fetch_parent_index(clk, parent);
-		if (p_index == clk->num_parents) {
+		if (p_index < 0) {
 			pr_debug("%s: clk %s can not be parent of clk %s\n",
 				 __func__, parent->name, clk->name);
 			return NULL;
@@ -1532,7 +1538,7 @@
 
 	if (!clk->parents)
 		clk->parents =
-			kzalloc((sizeof(struct clk*) * clk->num_parents),
+			kcalloc(clk->num_parents, sizeof(struct clk *),
 					GFP_KERNEL);
 
 	ret = clk_get_parent_by_index(clk, index);
@@ -1568,7 +1574,7 @@
 int clk_set_parent(struct clk *clk, struct clk *parent)
 {
 	int ret = 0;
-	u8 p_index = 0;
+	int p_index = 0;
 	unsigned long p_rate = 0;
 
 	if (!clk)
@@ -1597,10 +1603,10 @@
 	if (parent) {
 		p_index = clk_fetch_parent_index(clk, parent);
 		p_rate = parent->rate;
-		if (p_index == clk->num_parents) {
+		if (p_index < 0) {
 			pr_debug("%s: clk %s can not be parent of clk %s\n",
 					__func__, parent->name, clk->name);
-			ret = -EINVAL;
+			ret = p_index;
 			goto out;
 		}
 	}
@@ -1689,8 +1695,8 @@
 	 * for clock drivers to statically initialize clk->parents.
 	 */
 	if (clk->num_parents > 1 && !clk->parents) {
-		clk->parents = kzalloc((sizeof(struct clk*) * clk->num_parents),
-				GFP_KERNEL);
+		clk->parents = kcalloc(clk->num_parents, sizeof(struct clk *),
+					GFP_KERNEL);
 		/*
 		 * __clk_lookup returns NULL for parents that have not been
 		 * clk_init'd; thus any access to clk->parents[] must check
@@ -1830,8 +1836,8 @@
 	hw->clk = clk;
 
 	/* allocate local copy in case parent_names is __initdata */
-	clk->parent_names = kzalloc((sizeof(char*) * clk->num_parents),
-			GFP_KERNEL);
+	clk->parent_names = kcalloc(clk->num_parents, sizeof(char *),
+					GFP_KERNEL);
 
 	if (!clk->parent_names) {
 		pr_err("%s: could not allocate clk->parent_names\n", __func__);
@@ -2196,6 +2202,12 @@
 	return clk;
 }
 
+int of_clk_get_parent_count(struct device_node *np)
+{
+	return of_count_phandle_with_args(np, "clocks", "#clock-cells");
+}
+EXPORT_SYMBOL_GPL(of_clk_get_parent_count);
+
 const char *of_clk_get_parent_name(struct device_node *np, int index)
 {
 	struct of_phandle_args clkspec;
diff --git a/drivers/clk/keystone/Makefile b/drivers/clk/keystone/Makefile
new file mode 100644
index 0000000..0477cf6
--- /dev/null
+++ b/drivers/clk/keystone/Makefile
@@ -0,0 +1 @@
+obj-y			+= pll.o gate.o
diff --git a/drivers/clk/keystone/gate.c b/drivers/clk/keystone/gate.c
new file mode 100644
index 0000000..1f333bc
--- /dev/null
+++ b/drivers/clk/keystone/gate.c
@@ -0,0 +1,264 @@
+/*
+ * Clock driver for Keystone 2 based devices
+ *
+ * Copyright (C) 2013 Texas Instruments.
+ *	Murali Karicheri <m-karicheri2@ti.com>
+ *	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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/of.h>
+#include <linux/module.h>
+
+/* PSC register offsets */
+#define PTCMD			0x120
+#define PTSTAT			0x128
+#define PDSTAT			0x200
+#define PDCTL			0x300
+#define MDSTAT			0x800
+#define MDCTL			0xa00
+
+/* PSC module states */
+#define PSC_STATE_SWRSTDISABLE	0
+#define PSC_STATE_SYNCRST	1
+#define PSC_STATE_DISABLE	2
+#define PSC_STATE_ENABLE	3
+
+#define MDSTAT_STATE_MASK	0x3f
+#define MDSTAT_MCKOUT		BIT(12)
+#define PDSTAT_STATE_MASK	0x1f
+#define MDCTL_FORCE		BIT(31)
+#define MDCTL_LRESET		BIT(8)
+#define PDCTL_NEXT		BIT(0)
+
+/* Maximum timeout to bail out state transition for module */
+#define STATE_TRANS_MAX_COUNT	0xffff
+
+static void __iomem *domain_transition_base;
+
+/**
+ * struct clk_psc_data - PSC data
+ * @control_base: Base address for a PSC control
+ * @domain_base: Base address for a PSC domain
+ * @domain_id: PSC domain id number
+ */
+struct clk_psc_data {
+	void __iomem *control_base;
+	void __iomem *domain_base;
+	u32 domain_id;
+};
+
+/**
+ * struct clk_psc - PSC clock structure
+ * @hw: clk_hw for the psc
+ * @psc_data: PSC driver specific data
+ * @lock: Spinlock used by the driver
+ */
+struct clk_psc {
+	struct clk_hw hw;
+	struct clk_psc_data *psc_data;
+	spinlock_t *lock;
+};
+
+static DEFINE_SPINLOCK(psc_lock);
+
+#define to_clk_psc(_hw) container_of(_hw, struct clk_psc, hw)
+
+static void psc_config(void __iomem *control_base, void __iomem *domain_base,
+						u32 next_state, u32 domain_id)
+{
+	u32 ptcmd, pdstat, pdctl, mdstat, mdctl, ptstat;
+	u32 count = STATE_TRANS_MAX_COUNT;
+
+	mdctl = readl(control_base + MDCTL);
+	mdctl &= ~MDSTAT_STATE_MASK;
+	mdctl |= next_state;
+	/* For disable, we always put the module in local reset */
+	if (next_state == PSC_STATE_DISABLE)
+		mdctl &= ~MDCTL_LRESET;
+	writel(mdctl, control_base + MDCTL);
+
+	pdstat = readl(domain_base + PDSTAT);
+	if (!(pdstat & PDSTAT_STATE_MASK)) {
+		pdctl = readl(domain_base + PDCTL);
+		pdctl |= PDCTL_NEXT;
+		writel(pdctl, domain_base + PDCTL);
+	}
+
+	ptcmd = 1 << domain_id;
+	writel(ptcmd, domain_transition_base + PTCMD);
+	do {
+		ptstat = readl(domain_transition_base + PTSTAT);
+	} while (((ptstat >> domain_id) & 1) && count--);
+
+	count = STATE_TRANS_MAX_COUNT;
+	do {
+		mdstat = readl(control_base + MDSTAT);
+	} while (!((mdstat & MDSTAT_STATE_MASK) == next_state) && count--);
+}
+
+static int keystone_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_psc *psc = to_clk_psc(hw);
+	struct clk_psc_data *data = psc->psc_data;
+	u32 mdstat = readl(data->control_base + MDSTAT);
+
+	return (mdstat & MDSTAT_MCKOUT) ? 1 : 0;
+}
+
+static int keystone_clk_enable(struct clk_hw *hw)
+{
+	struct clk_psc *psc = to_clk_psc(hw);
+	struct clk_psc_data *data = psc->psc_data;
+	unsigned long flags = 0;
+
+	if (psc->lock)
+		spin_lock_irqsave(psc->lock, flags);
+
+	psc_config(data->control_base, data->domain_base,
+				PSC_STATE_ENABLE, data->domain_id);
+
+	if (psc->lock)
+		spin_unlock_irqrestore(psc->lock, flags);
+
+	return 0;
+}
+
+static void keystone_clk_disable(struct clk_hw *hw)
+{
+	struct clk_psc *psc = to_clk_psc(hw);
+	struct clk_psc_data *data = psc->psc_data;
+	unsigned long flags = 0;
+
+	if (psc->lock)
+		spin_lock_irqsave(psc->lock, flags);
+
+	psc_config(data->control_base, data->domain_base,
+				PSC_STATE_DISABLE, data->domain_id);
+
+	if (psc->lock)
+		spin_unlock_irqrestore(psc->lock, flags);
+}
+
+static const struct clk_ops clk_psc_ops = {
+	.enable = keystone_clk_enable,
+	.disable = keystone_clk_disable,
+	.is_enabled = keystone_clk_is_enabled,
+};
+
+/**
+ * clk_register_psc - register psc clock
+ * @dev: device that is registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @psc_data: platform data to configure this clock
+ * @lock: spinlock used by this clock
+ */
+static struct clk *clk_register_psc(struct device *dev,
+			const char *name,
+			const char *parent_name,
+			struct clk_psc_data *psc_data,
+			spinlock_t *lock)
+{
+	struct clk_init_data init;
+	struct clk_psc *psc;
+	struct clk *clk;
+
+	psc = kzalloc(sizeof(*psc), GFP_KERNEL);
+	if (!psc)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &clk_psc_ops;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	psc->psc_data = psc_data;
+	psc->lock = lock;
+	psc->hw.init = &init;
+
+	clk = clk_register(NULL, &psc->hw);
+	if (IS_ERR(clk))
+		kfree(psc);
+
+	return clk;
+}
+
+/**
+ * of_psc_clk_init - initialize psc clock through DT
+ * @node: device tree node for this clock
+ * @lock: spinlock used by this clock
+ */
+static void __init of_psc_clk_init(struct device_node *node, spinlock_t *lock)
+{
+	const char *clk_name = node->name;
+	const char *parent_name;
+	struct clk_psc_data *data;
+	struct clk *clk;
+	int i;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		pr_err("%s: Out of memory\n", __func__);
+		return;
+	}
+
+	i = of_property_match_string(node, "reg-names", "control");
+	data->control_base = of_iomap(node, i);
+	if (!data->control_base) {
+		pr_err("%s: control ioremap failed\n", __func__);
+		goto out;
+	}
+
+	i = of_property_match_string(node, "reg-names", "domain");
+	data->domain_base = of_iomap(node, i);
+	if (!data->domain_base) {
+		pr_err("%s: domain ioremap failed\n", __func__);
+		iounmap(data->control_base);
+		goto out;
+	}
+
+	of_property_read_u32(node, "domain-id", &data->domain_id);
+
+	/* Domain transition registers at fixed address space of domain_id 0 */
+	if (!domain_transition_base && !data->domain_id)
+		domain_transition_base = data->domain_base;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+	parent_name = of_clk_get_parent_name(node, 0);
+	if (!parent_name) {
+		pr_err("%s: Parent clock not found\n", __func__);
+		goto out;
+	}
+
+	clk = clk_register_psc(NULL, clk_name, parent_name, data, lock);
+	if (clk) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		return;
+	}
+
+	pr_err("%s: error registering clk %s\n", __func__, node->name);
+out:
+	kfree(data);
+	return;
+}
+
+/**
+ * of_keystone_psc_clk_init - initialize psc clock through DT
+ * @node: device tree node for this clock
+ */
+static void __init of_keystone_psc_clk_init(struct device_node *node)
+{
+	of_psc_clk_init(node, &psc_lock);
+}
+CLK_OF_DECLARE(keystone_gate_clk, "ti,keystone,psc-clock",
+					of_keystone_psc_clk_init);
diff --git a/drivers/clk/keystone/pll.c b/drivers/clk/keystone/pll.c
new file mode 100644
index 0000000..47a1bd9
--- /dev/null
+++ b/drivers/clk/keystone/pll.c
@@ -0,0 +1,305 @@
+/*
+ * PLL clock driver for Keystone devices
+ *
+ * Copyright (C) 2013 Texas Instruments Inc.
+ *	Murali Karicheri <m-karicheri2@ti.com>
+ *	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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/of.h>
+#include <linux/module.h>
+
+#define PLLM_LOW_MASK		0x3f
+#define PLLM_HIGH_MASK		0x7ffc0
+#define MAIN_PLLM_HIGH_MASK	0x7f000
+#define PLLM_HIGH_SHIFT		6
+#define PLLD_MASK		0x3f
+
+/**
+ * struct clk_pll_data - pll data structure
+ * @has_pllctrl: If set to non zero, lower 6 bits of multiplier is in pllm
+ *	register of pll controller, else it is in the pll_ctrl0((bit 11-6)
+ * @phy_pllm: Physical address of PLLM in pll controller. Used when
+ *	has_pllctrl is non zero.
+ * @phy_pll_ctl0: Physical address of PLL ctrl0. This could be that of
+ *	Main PLL or any other PLLs in the device such as ARM PLL, DDR PLL
+ *	or PA PLL available on keystone2. These PLLs are controlled by
+ *	this register. Main PLL is controlled by a PLL controller.
+ * @pllm: PLL register map address
+ * @pll_ctl0: PLL controller map address
+ * @pllm_lower_mask: multiplier lower mask
+ * @pllm_upper_mask: multiplier upper mask
+ * @pllm_upper_shift: multiplier upper shift
+ * @plld_mask: divider mask
+ * @postdiv: Post divider
+ */
+struct clk_pll_data {
+	bool has_pllctrl;
+	u32 phy_pllm;
+	u32 phy_pll_ctl0;
+	void __iomem *pllm;
+	void __iomem *pll_ctl0;
+	u32 pllm_lower_mask;
+	u32 pllm_upper_mask;
+	u32 pllm_upper_shift;
+	u32 plld_mask;
+	u32 postdiv;
+};
+
+/**
+ * struct clk_pll - Main pll clock
+ * @hw: clk_hw for the pll
+ * @pll_data: PLL driver specific data
+ */
+struct clk_pll {
+	struct clk_hw hw;
+	struct clk_pll_data *pll_data;
+};
+
+#define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw)
+
+static unsigned long clk_pllclk_recalc(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct clk_pll *pll = to_clk_pll(hw);
+	struct clk_pll_data *pll_data = pll->pll_data;
+	unsigned long rate = parent_rate;
+	u32  mult = 0, prediv, postdiv, val;
+
+	/*
+	 * get bits 0-5 of multiplier from pllctrl PLLM register
+	 * if has_pllctrl is non zero
+	 */
+	if (pll_data->has_pllctrl) {
+		val = readl(pll_data->pllm);
+		mult = (val & pll_data->pllm_lower_mask);
+	}
+
+	/* bit6-12 of PLLM is in Main PLL control register */
+	val = readl(pll_data->pll_ctl0);
+	mult |= ((val & pll_data->pllm_upper_mask)
+			>> pll_data->pllm_upper_shift);
+	prediv = (val & pll_data->plld_mask);
+	postdiv = pll_data->postdiv;
+
+	rate /= (prediv + 1);
+	rate = (rate * (mult + 1));
+	rate /= postdiv;
+
+	return rate;
+}
+
+static const struct clk_ops clk_pll_ops = {
+	.recalc_rate = clk_pllclk_recalc,
+};
+
+static struct clk *clk_register_pll(struct device *dev,
+			const char *name,
+			const char *parent_name,
+			struct clk_pll_data *pll_data)
+{
+	struct clk_init_data init;
+	struct clk_pll *pll;
+	struct clk *clk;
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &clk_pll_ops;
+	init.flags = 0;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	pll->pll_data	= pll_data;
+	pll->hw.init = &init;
+
+	clk = clk_register(NULL, &pll->hw);
+	if (IS_ERR(clk))
+		goto out;
+
+	return clk;
+out:
+	kfree(pll);
+	return NULL;
+}
+
+/**
+ * _of_clk_init - PLL initialisation via DT
+ * @node: device tree node for this clock
+ * @pllctrl: If true, lower 6 bits of multiplier is in pllm register of
+ *		pll controller, else it is in the control regsiter0(bit 11-6)
+ */
+static void __init _of_pll_clk_init(struct device_node *node, bool pllctrl)
+{
+	struct clk_pll_data *pll_data;
+	const char *parent_name;
+	struct clk *clk;
+	int i;
+
+	pll_data = kzalloc(sizeof(*pll_data), GFP_KERNEL);
+	if (!pll_data) {
+		pr_err("%s: Out of memory\n", __func__);
+		return;
+	}
+
+	parent_name = of_clk_get_parent_name(node, 0);
+	if (of_property_read_u32(node, "fixed-postdiv",	&pll_data->postdiv))
+		goto out;
+
+	i = of_property_match_string(node, "reg-names", "control");
+	pll_data->pll_ctl0 = of_iomap(node, i);
+	if (!pll_data->pll_ctl0) {
+		pr_err("%s: ioremap failed\n", __func__);
+		goto out;
+	}
+
+	pll_data->pllm_lower_mask = PLLM_LOW_MASK;
+	pll_data->pllm_upper_shift = PLLM_HIGH_SHIFT;
+	pll_data->plld_mask = PLLD_MASK;
+	pll_data->has_pllctrl = pllctrl;
+	if (!pll_data->has_pllctrl) {
+		pll_data->pllm_upper_mask = PLLM_HIGH_MASK;
+	} else {
+		pll_data->pllm_upper_mask = MAIN_PLLM_HIGH_MASK;
+		i = of_property_match_string(node, "reg-names", "multiplier");
+		pll_data->pllm = of_iomap(node, i);
+		if (!pll_data->pllm) {
+			iounmap(pll_data->pll_ctl0);
+			goto out;
+		}
+	}
+
+	clk = clk_register_pll(NULL, node->name, parent_name, pll_data);
+	if (clk) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		return;
+	}
+
+out:
+	pr_err("%s: error initializing pll %s\n", __func__, node->name);
+	kfree(pll_data);
+}
+
+/**
+ * of_keystone_pll_clk_init - PLL initialisation DT wrapper
+ * @node: device tree node for this clock
+ */
+static void __init of_keystone_pll_clk_init(struct device_node *node)
+{
+	_of_pll_clk_init(node, false);
+}
+CLK_OF_DECLARE(keystone_pll_clock, "ti,keystone,pll-clock",
+					of_keystone_pll_clk_init);
+
+/**
+ * of_keystone_pll_main_clk_init - Main PLL initialisation DT wrapper
+ * @node: device tree node for this clock
+ */
+static void __init of_keystone_main_pll_clk_init(struct device_node *node)
+{
+	_of_pll_clk_init(node, true);
+}
+CLK_OF_DECLARE(keystone_main_pll_clock, "ti,keystone,main-pll-clock",
+						of_keystone_main_pll_clk_init);
+
+/**
+ * of_pll_div_clk_init - PLL divider setup function
+ * @node: device tree node for this clock
+ */
+static void __init of_pll_div_clk_init(struct device_node *node)
+{
+	const char *parent_name;
+	void __iomem *reg;
+	u32 shift, mask;
+	struct clk *clk;
+	const char *clk_name = node->name;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+	reg = of_iomap(node, 0);
+	if (!reg) {
+		pr_err("%s: ioremap failed\n", __func__);
+		return;
+	}
+
+	parent_name = of_clk_get_parent_name(node, 0);
+	if (!parent_name) {
+		pr_err("%s: missing parent clock\n", __func__);
+		return;
+	}
+
+	if (of_property_read_u32(node, "bit-shift", &shift)) {
+		pr_err("%s: missing 'shift' property\n", __func__);
+		return;
+	}
+
+	if (of_property_read_u32(node, "bit-mask", &mask)) {
+		pr_err("%s: missing 'bit-mask' property\n", __func__);
+		return;
+	}
+
+	clk = clk_register_divider(NULL, clk_name, parent_name, 0, reg, shift,
+				 mask, 0, NULL);
+	if (clk)
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	else
+		pr_err("%s: error registering divider %s\n", __func__, clk_name);
+}
+CLK_OF_DECLARE(pll_divider_clock, "ti,keystone,pll-divider-clock", of_pll_div_clk_init);
+
+/**
+ * of_pll_mux_clk_init - PLL mux setup function
+ * @node: device tree node for this clock
+ */
+static void __init of_pll_mux_clk_init(struct device_node *node)
+{
+	void __iomem *reg;
+	u32 shift, mask;
+	struct clk *clk;
+	const char *parents[2];
+	const char *clk_name = node->name;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+	reg = of_iomap(node, 0);
+	if (!reg) {
+		pr_err("%s: ioremap failed\n", __func__);
+		return;
+	}
+
+	parents[0] = of_clk_get_parent_name(node, 0);
+	parents[1] = of_clk_get_parent_name(node, 1);
+	if (!parents[0] || !parents[1]) {
+		pr_err("%s: missing parent clocks\n", __func__);
+		return;
+	}
+
+	if (of_property_read_u32(node, "bit-shift", &shift)) {
+		pr_err("%s: missing 'shift' property\n", __func__);
+		return;
+	}
+
+	if (of_property_read_u32(node, "bit-mask", &mask)) {
+		pr_err("%s: missing 'bit-mask' property\n", __func__);
+		return;
+	}
+
+	clk = clk_register_mux(NULL, clk_name, (const char **)&parents,
+				ARRAY_SIZE(parents) , 0, reg, shift, mask,
+				0, NULL);
+	if (clk)
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	else
+		pr_err("%s: error registering mux %s\n", __func__, clk_name);
+}
+CLK_OF_DECLARE(pll_mux_clock, "ti,keystone,pll-mux-clock", of_pll_mux_clk_init);
diff --git a/drivers/clk/mvebu/armada-370.c b/drivers/clk/mvebu/armada-370.c
index fc777bd..81a202d 100644
--- a/drivers/clk/mvebu/armada-370.c
+++ b/drivers/clk/mvebu/armada-370.c
@@ -39,8 +39,8 @@
 };
 
 static const u32 a370_tclk_freqs[] __initconst = {
-	16600000,
-	20000000,
+	166000000,
+	200000000,
 };
 
 static u32 __init a370_get_tclk_freq(void __iomem *sar)
diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c
index c396fe3..9fc9359 100644
--- a/drivers/clk/mxs/clk-imx23.c
+++ b/drivers/clk/mxs/clk-imx23.c
@@ -12,6 +12,7 @@
 #include <linux/clk.h>
 #include <linux/clk/mxs.h>
 #include <linux/clkdev.h>
+#include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/io.h>
@@ -100,16 +101,16 @@
 	cpu, hbus, xbus, emi, uart,
 };
 
-int __init mx23_clocks_init(void)
+static void __init mx23_clocks_init(struct device_node *np)
 {
-	struct device_node *np;
+	struct device_node *dcnp;
 	u32 i;
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx23-digctl");
-	digctrl = of_iomap(np, 0);
+	dcnp = of_find_compatible_node(NULL, NULL, "fsl,imx23-digctl");
+	digctrl = of_iomap(dcnp, 0);
 	WARN_ON(!digctrl);
+	of_node_put(dcnp);
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx23-clkctrl");
 	clkctrl = of_iomap(np, 0);
 	WARN_ON(!clkctrl);
 
@@ -162,7 +163,7 @@
 		if (IS_ERR(clks[i])) {
 			pr_err("i.MX23 clk %d: register failed with %ld\n",
 				i, PTR_ERR(clks[i]));
-			return PTR_ERR(clks[i]);
+			return;
 		}
 
 	clk_data.clks = clks;
@@ -172,5 +173,5 @@
 	for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
 		clk_prepare_enable(clks[clks_init_on[i]]);
 
-	return 0;
 }
+CLK_OF_DECLARE(imx23_clkctrl, "fsl,imx23-clkctrl", mx23_clocks_init);
diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
index 4faf0af..a6c3501 100644
--- a/drivers/clk/mxs/clk-imx28.c
+++ b/drivers/clk/mxs/clk-imx28.c
@@ -12,6 +12,7 @@
 #include <linux/clk.h>
 #include <linux/clk/mxs.h>
 #include <linux/clkdev.h>
+#include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/io.h>
@@ -154,16 +155,16 @@
 	cpu, hbus, xbus, emi, uart,
 };
 
-int __init mx28_clocks_init(void)
+static void __init mx28_clocks_init(struct device_node *np)
 {
-	struct device_node *np;
+	struct device_node *dcnp;
 	u32 i;
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx28-digctl");
-	digctrl = of_iomap(np, 0);
+	dcnp = of_find_compatible_node(NULL, NULL, "fsl,imx28-digctl");
+	digctrl = of_iomap(dcnp, 0);
 	WARN_ON(!digctrl);
+	of_node_put(dcnp);
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx28-clkctrl");
 	clkctrl = of_iomap(np, 0);
 	WARN_ON(!clkctrl);
 
@@ -239,7 +240,7 @@
 		if (IS_ERR(clks[i])) {
 			pr_err("i.MX28 clk %d: register failed with %ld\n",
 				i, PTR_ERR(clks[i]));
-			return PTR_ERR(clks[i]);
+			return;
 		}
 
 	clk_data.clks = clks;
@@ -250,6 +251,5 @@
 
 	for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
 		clk_prepare_enable(clks[clks_init_on[i]]);
-
-	return 0;
 }
+CLK_OF_DECLARE(imx28_clkctrl, "fsl,imx28-clkctrl", mx28_clocks_init);
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index 3413380..8eb4799 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -8,6 +8,4 @@
 obj-$(CONFIG_SOC_EXYNOS5420)	+= clk-exynos5420.o
 obj-$(CONFIG_SOC_EXYNOS5440)	+= clk-exynos5440.o
 obj-$(CONFIG_ARCH_EXYNOS)	+= clk-exynos-audss.o
-ifdef CONFIG_COMMON_CLK
 obj-$(CONFIG_ARCH_S3C64XX)	+= clk-s3c64xx.o
-endif
diff --git a/drivers/clk/socfpga/clk.c b/drivers/clk/socfpga/clk.c
index 5bb848c..81dd31a 100644
--- a/drivers/clk/socfpga/clk.c
+++ b/drivers/clk/socfpga/clk.c
@@ -49,7 +49,7 @@
 #define SOCFPGA_L4_SP_CLK		"l4_sp_clk"
 #define SOCFPGA_NAND_CLK		"nand_clk"
 #define SOCFPGA_NAND_X_CLK		"nand_x_clk"
-#define SOCFPGA_MMC_CLK			"mmc_clk"
+#define SOCFPGA_MMC_CLK			"sdmmc_clk"
 #define SOCFPGA_DB_CLK			"gpio_db_clk"
 
 #define div_mask(width)	((1 << (width)) - 1)
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 34ee69f..9bbd035 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -16,7 +16,6 @@
 
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
-#include <linux/clk/sunxi.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 
@@ -617,11 +616,8 @@
 	}
 }
 
-void __init sunxi_init_clocks(void)
+static void __init sunxi_init_clocks(struct device_node *np)
 {
-	/* Register all the simple and basic clocks on DT */
-	of_clk_init(NULL);
-
 	/* Register factor clocks */
 	of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup);
 
@@ -634,3 +630,8 @@
 	/* Register gate clocks */
 	of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup);
 }
+CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sunxi_init_clocks);
+CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sunxi_init_clocks);
+CLK_OF_DECLARE(sun5i_a13_clk_init, "allwinner,sun5i-a13", sunxi_init_clocks);
+CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sunxi_init_clocks);
+CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sunxi_init_clocks);
diff --git a/drivers/clk/ux500/Makefile b/drivers/clk/ux500/Makefile
index c6a806e..521483f 100644
--- a/drivers/clk/ux500/Makefile
+++ b/drivers/clk/ux500/Makefile
@@ -8,6 +8,7 @@
 obj-y += clk-sysctrl.o
 
 # Clock definitions
+obj-y += u8500_of_clk.o
 obj-y += u8500_clk.o
 obj-y += u9540_clk.o
 obj-y += u8540_clk.o
diff --git a/drivers/clk/ux500/u8500_of_clk.c b/drivers/clk/ux500/u8500_of_clk.c
new file mode 100644
index 0000000..cdeff29
--- /dev/null
+++ b/drivers/clk/ux500/u8500_of_clk.c
@@ -0,0 +1,559 @@
+/*
+ * Clock definitions for u8500 platform.
+ *
+ * Copyright (C) 2012 ST-Ericsson SA
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/of.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/platform_data/clk-ux500.h>
+#include "clk.h"
+
+#define PRCC_NUM_PERIPH_CLUSTERS 6
+#define PRCC_PERIPHS_PER_CLUSTER 32
+
+static struct clk *prcmu_clk[PRCMU_NUM_CLKS];
+static struct clk *prcc_pclk[(PRCC_NUM_PERIPH_CLUSTERS + 1) * PRCC_PERIPHS_PER_CLUSTER];
+static struct clk *prcc_kclk[(PRCC_NUM_PERIPH_CLUSTERS + 1) * PRCC_PERIPHS_PER_CLUSTER];
+
+#define PRCC_SHOW(clk, base, bit) \
+	clk[(base * PRCC_PERIPHS_PER_CLUSTER) + bit]
+#define PRCC_PCLK_STORE(clk, base, bit)	\
+	prcc_pclk[(base * PRCC_PERIPHS_PER_CLUSTER) + bit] = clk
+#define PRCC_KCLK_STORE(clk, base, bit)        \
+	prcc_kclk[(base * PRCC_PERIPHS_PER_CLUSTER) + bit] = clk
+
+struct clk *ux500_twocell_get(struct of_phandle_args *clkspec, void *data)
+{
+	struct clk **clk_data = data;
+	unsigned int base, bit;
+
+	if (clkspec->args_count != 2)
+		return  ERR_PTR(-EINVAL);
+
+	base = clkspec->args[0];
+	bit = clkspec->args[1];
+
+	if (base != 1 && base != 2 && base != 3 && base != 5 && base != 6) {
+		pr_err("%s: invalid PRCC base %d\n", __func__, base);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return PRCC_SHOW(clk_data, base, bit);
+}
+
+static const struct of_device_id u8500_clk_of_match[] = {
+	{ .compatible = "stericsson,u8500-clks", },
+	{ },
+};
+
+void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
+		       u32 clkrst5_base, u32 clkrst6_base)
+{
+	struct prcmu_fw_version *fw_version;
+	struct device_node *np = NULL;
+	struct device_node *child = NULL;
+	const char *sgaclk_parent = NULL;
+	struct clk *clk, *rtc_clk, *twd_clk;
+
+	if (of_have_populated_dt())
+		np = of_find_matching_node(NULL, u8500_clk_of_match);
+	if (!np) {
+		pr_err("Either DT or U8500 Clock node not found\n");
+		return;
+	}
+
+	/* Clock sources */
+	clk = clk_reg_prcmu_gate("soc0_pll", NULL, PRCMU_PLLSOC0,
+				CLK_IS_ROOT|CLK_IGNORE_UNUSED);
+	prcmu_clk[PRCMU_PLLSOC0] = clk;
+
+	clk = clk_reg_prcmu_gate("soc1_pll", NULL, PRCMU_PLLSOC1,
+				CLK_IS_ROOT|CLK_IGNORE_UNUSED);
+	prcmu_clk[PRCMU_PLLSOC1] = clk;
+
+	clk = clk_reg_prcmu_gate("ddr_pll", NULL, PRCMU_PLLDDR,
+				CLK_IS_ROOT|CLK_IGNORE_UNUSED);
+	prcmu_clk[PRCMU_PLLDDR] = clk;
+
+	/* FIXME: Add sys, ulp and int clocks here. */
+
+	rtc_clk = clk_register_fixed_rate(NULL, "rtc32k", "NULL",
+				CLK_IS_ROOT|CLK_IGNORE_UNUSED,
+				32768);
+
+	/* PRCMU clocks */
+	fw_version = prcmu_get_fw_version();
+	if (fw_version != NULL) {
+		switch (fw_version->project) {
+		case PRCMU_FW_PROJECT_U8500_C2:
+		case PRCMU_FW_PROJECT_U8520:
+		case PRCMU_FW_PROJECT_U8420:
+			sgaclk_parent = "soc0_pll";
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (sgaclk_parent)
+		clk = clk_reg_prcmu_gate("sgclk", sgaclk_parent,
+					PRCMU_SGACLK, 0);
+	else
+		clk = clk_reg_prcmu_gate("sgclk", NULL,
+					PRCMU_SGACLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_SGACLK] = clk;
+
+	clk = clk_reg_prcmu_gate("uartclk", NULL, PRCMU_UARTCLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_UARTCLK] = clk;
+
+	clk = clk_reg_prcmu_gate("msp02clk", NULL, PRCMU_MSP02CLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_MSP02CLK] = clk;
+
+	clk = clk_reg_prcmu_gate("msp1clk", NULL, PRCMU_MSP1CLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_MSP1CLK] = clk;
+
+	clk = clk_reg_prcmu_gate("i2cclk", NULL, PRCMU_I2CCLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_I2CCLK] = clk;
+
+	clk = clk_reg_prcmu_gate("slimclk", NULL, PRCMU_SLIMCLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_SLIMCLK] = clk;
+
+	clk = clk_reg_prcmu_gate("per1clk", NULL, PRCMU_PER1CLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_PER1CLK] = clk;
+
+	clk = clk_reg_prcmu_gate("per2clk", NULL, PRCMU_PER2CLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_PER2CLK] = clk;
+
+	clk = clk_reg_prcmu_gate("per3clk", NULL, PRCMU_PER3CLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_PER3CLK] = clk;
+
+	clk = clk_reg_prcmu_gate("per5clk", NULL, PRCMU_PER5CLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_PER5CLK] = clk;
+
+	clk = clk_reg_prcmu_gate("per6clk", NULL, PRCMU_PER6CLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_PER6CLK] = clk;
+
+	clk = clk_reg_prcmu_gate("per7clk", NULL, PRCMU_PER7CLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_PER7CLK] = clk;
+
+	clk = clk_reg_prcmu_scalable("lcdclk", NULL, PRCMU_LCDCLK, 0,
+				CLK_IS_ROOT|CLK_SET_RATE_GATE);
+	prcmu_clk[PRCMU_LCDCLK] = clk;
+
+	clk = clk_reg_prcmu_opp_gate("bmlclk", NULL, PRCMU_BMLCLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_BMLCLK] = clk;
+
+	clk = clk_reg_prcmu_scalable("hsitxclk", NULL, PRCMU_HSITXCLK, 0,
+				CLK_IS_ROOT|CLK_SET_RATE_GATE);
+	prcmu_clk[PRCMU_HSITXCLK] = clk;
+
+	clk = clk_reg_prcmu_scalable("hsirxclk", NULL, PRCMU_HSIRXCLK, 0,
+				CLK_IS_ROOT|CLK_SET_RATE_GATE);
+	prcmu_clk[PRCMU_HSIRXCLK] = clk;
+
+	clk = clk_reg_prcmu_scalable("hdmiclk", NULL, PRCMU_HDMICLK, 0,
+				CLK_IS_ROOT|CLK_SET_RATE_GATE);
+	prcmu_clk[PRCMU_HDMICLK] = clk;
+
+	clk = clk_reg_prcmu_gate("apeatclk", NULL, PRCMU_APEATCLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_APEATCLK] = clk;
+
+	clk = clk_reg_prcmu_gate("apetraceclk", NULL, PRCMU_APETRACECLK,
+				CLK_IS_ROOT);
+	prcmu_clk[PRCMU_APETRACECLK] = clk;
+
+	clk = clk_reg_prcmu_gate("mcdeclk", NULL, PRCMU_MCDECLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_MCDECLK] = clk;
+
+	clk = clk_reg_prcmu_opp_gate("ipi2cclk", NULL, PRCMU_IPI2CCLK,
+				CLK_IS_ROOT);
+	prcmu_clk[PRCMU_IPI2CCLK] = clk;
+
+	clk = clk_reg_prcmu_gate("dsialtclk", NULL, PRCMU_DSIALTCLK,
+				CLK_IS_ROOT);
+	prcmu_clk[PRCMU_DSIALTCLK] = clk;
+
+	clk = clk_reg_prcmu_gate("dmaclk", NULL, PRCMU_DMACLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_DMACLK] = clk;
+
+	clk = clk_reg_prcmu_gate("b2r2clk", NULL, PRCMU_B2R2CLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_B2R2CLK] = clk;
+
+	clk = clk_reg_prcmu_scalable("tvclk", NULL, PRCMU_TVCLK, 0,
+				CLK_IS_ROOT|CLK_SET_RATE_GATE);
+	prcmu_clk[PRCMU_TVCLK] = clk;
+
+	clk = clk_reg_prcmu_gate("sspclk", NULL, PRCMU_SSPCLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_SSPCLK] = clk;
+
+	clk = clk_reg_prcmu_gate("rngclk", NULL, PRCMU_RNGCLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_RNGCLK] = clk;
+
+	clk = clk_reg_prcmu_gate("uiccclk", NULL, PRCMU_UICCCLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_UICCCLK] = clk;
+
+	clk = clk_reg_prcmu_gate("timclk", NULL, PRCMU_TIMCLK, CLK_IS_ROOT);
+	prcmu_clk[PRCMU_TIMCLK] = clk;
+
+	clk = clk_reg_prcmu_opp_volt_scalable("sdmmcclk", NULL, PRCMU_SDMMCCLK,
+					100000000,
+					CLK_IS_ROOT|CLK_SET_RATE_GATE);
+	prcmu_clk[PRCMU_SDMMCCLK] = clk;
+
+	clk = clk_reg_prcmu_scalable("dsi_pll", "hdmiclk",
+				PRCMU_PLLDSI, 0, CLK_SET_RATE_GATE);
+	prcmu_clk[PRCMU_PLLDSI] = clk;
+
+	clk = clk_reg_prcmu_scalable("dsi0clk", "dsi_pll",
+				PRCMU_DSI0CLK, 0, CLK_SET_RATE_GATE);
+	prcmu_clk[PRCMU_DSI0CLK] = clk;
+
+	clk = clk_reg_prcmu_scalable("dsi1clk", "dsi_pll",
+				PRCMU_DSI1CLK, 0, CLK_SET_RATE_GATE);
+	prcmu_clk[PRCMU_DSI1CLK] = clk;
+
+	clk = clk_reg_prcmu_scalable("dsi0escclk", "tvclk",
+				PRCMU_DSI0ESCCLK, 0, CLK_SET_RATE_GATE);
+	prcmu_clk[PRCMU_DSI0ESCCLK] = clk;
+
+	clk = clk_reg_prcmu_scalable("dsi1escclk", "tvclk",
+				PRCMU_DSI1ESCCLK, 0, CLK_SET_RATE_GATE);
+	prcmu_clk[PRCMU_DSI1ESCCLK] = clk;
+
+	clk = clk_reg_prcmu_scalable("dsi2escclk", "tvclk",
+				PRCMU_DSI2ESCCLK, 0, CLK_SET_RATE_GATE);
+	prcmu_clk[PRCMU_DSI2ESCCLK] = clk;
+
+	clk = clk_reg_prcmu_scalable_rate("armss", NULL,
+				PRCMU_ARMSS, 0, CLK_IS_ROOT|CLK_IGNORE_UNUSED);
+	prcmu_clk[PRCMU_ARMSS] = clk;
+
+	twd_clk = clk_register_fixed_factor(NULL, "smp_twd", "armss",
+				CLK_IGNORE_UNUSED, 1, 2);
+
+	/*
+	 * FIXME: Add special handled PRCMU clocks here:
+	 * 1. clkout0yuv, use PRCMU as parent + need regulator + pinctrl.
+	 * 2. ab9540_clkout1yuv, see clkout0yuv
+	 */
+
+	/* PRCC P-clocks */
+	clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", clkrst1_base,
+				BIT(0), 0);
+	PRCC_PCLK_STORE(clk, 1, 0);
+
+	clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", clkrst1_base,
+				BIT(1), 0);
+	PRCC_PCLK_STORE(clk, 1, 1);
+
+	clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", clkrst1_base,
+				BIT(2), 0);
+	PRCC_PCLK_STORE(clk, 1, 2);
+
+	clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", clkrst1_base,
+				BIT(3), 0);
+	PRCC_PCLK_STORE(clk, 1, 3);
+
+	clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", clkrst1_base,
+				BIT(4), 0);
+	PRCC_PCLK_STORE(clk, 1, 4);
+
+	clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", clkrst1_base,
+				BIT(5), 0);
+	PRCC_PCLK_STORE(clk, 1, 5);
+
+	clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", clkrst1_base,
+				BIT(6), 0);
+	PRCC_PCLK_STORE(clk, 1, 6);
+
+	clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", clkrst1_base,
+				BIT(7), 0);
+	PRCC_PCLK_STORE(clk, 1, 7);
+
+	clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", clkrst1_base,
+				BIT(8), 0);
+	PRCC_PCLK_STORE(clk, 1, 8);
+
+	clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", clkrst1_base,
+				BIT(9), 0);
+	PRCC_PCLK_STORE(clk, 1, 9);
+
+	clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", clkrst1_base,
+				BIT(10), 0);
+	PRCC_PCLK_STORE(clk, 1, 10);
+
+	clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", clkrst1_base,
+				BIT(11), 0);
+	PRCC_PCLK_STORE(clk, 1, 11);
+
+	clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", clkrst2_base,
+				BIT(0), 0);
+	PRCC_PCLK_STORE(clk, 2, 0);
+
+	clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", clkrst2_base,
+				BIT(1), 0);
+	PRCC_PCLK_STORE(clk, 2, 1);
+
+	clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", clkrst2_base,
+				BIT(2), 0);
+	PRCC_PCLK_STORE(clk, 2, 2);
+
+	clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", clkrst2_base,
+				BIT(3), 0);
+	PRCC_PCLK_STORE(clk, 2, 3);
+
+	clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", clkrst2_base,
+				BIT(4), 0);
+	PRCC_PCLK_STORE(clk, 2, 4);
+
+	clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", clkrst2_base,
+				BIT(5), 0);
+	PRCC_PCLK_STORE(clk, 2, 5);
+
+	clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", clkrst2_base,
+				BIT(6), 0);
+	PRCC_PCLK_STORE(clk, 2, 6);
+
+	clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", clkrst2_base,
+				BIT(7), 0);
+	PRCC_PCLK_STORE(clk, 2, 7);
+
+	clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", clkrst2_base,
+				BIT(8), 0);
+	PRCC_PCLK_STORE(clk, 2, 8);
+
+	clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", clkrst2_base,
+				BIT(9), 0);
+	PRCC_PCLK_STORE(clk, 2, 9);
+
+	clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", clkrst2_base,
+				BIT(10), 0);
+	PRCC_PCLK_STORE(clk, 2, 10);
+
+	clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", clkrst2_base,
+				BIT(11), 0);
+	PRCC_PCLK_STORE(clk, 2, 11);
+
+	clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", clkrst2_base,
+				BIT(12), 0);
+	PRCC_PCLK_STORE(clk, 2, 12);
+
+	clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", clkrst3_base,
+				BIT(0), 0);
+	PRCC_PCLK_STORE(clk, 3, 0);
+
+	clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", clkrst3_base,
+				BIT(1), 0);
+	PRCC_PCLK_STORE(clk, 3, 1);
+
+	clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", clkrst3_base,
+				BIT(2), 0);
+	PRCC_PCLK_STORE(clk, 3, 2);
+
+	clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", clkrst3_base,
+				BIT(3), 0);
+	PRCC_PCLK_STORE(clk, 3, 3);
+
+	clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", clkrst3_base,
+				BIT(4), 0);
+	PRCC_PCLK_STORE(clk, 3, 4);
+
+	clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", clkrst3_base,
+				BIT(5), 0);
+	PRCC_PCLK_STORE(clk, 3, 5);
+
+	clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", clkrst3_base,
+				BIT(6), 0);
+	PRCC_PCLK_STORE(clk, 3, 6);
+
+	clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", clkrst3_base,
+				BIT(7), 0);
+	PRCC_PCLK_STORE(clk, 3, 7);
+
+	clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", clkrst3_base,
+				BIT(8), 0);
+	PRCC_PCLK_STORE(clk, 3, 8);
+
+	clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", clkrst5_base,
+				BIT(0), 0);
+	PRCC_PCLK_STORE(clk, 5, 0);
+
+	clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", clkrst5_base,
+				BIT(1), 0);
+	PRCC_PCLK_STORE(clk, 5, 1);
+
+	clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", clkrst6_base,
+				BIT(0), 0);
+	PRCC_PCLK_STORE(clk, 6, 0);
+
+	clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", clkrst6_base,
+				BIT(1), 0);
+	PRCC_PCLK_STORE(clk, 6, 1);
+
+	clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", clkrst6_base,
+				BIT(2), 0);
+	PRCC_PCLK_STORE(clk, 6, 2);
+
+	clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", clkrst6_base,
+				BIT(3), 0);
+	PRCC_PCLK_STORE(clk, 6, 3);
+
+	clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", clkrst6_base,
+				BIT(4), 0);
+	PRCC_PCLK_STORE(clk, 6, 4);
+
+	clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", clkrst6_base,
+				BIT(5), 0);
+	PRCC_PCLK_STORE(clk, 6, 5);
+
+	clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", clkrst6_base,
+				BIT(6), 0);
+	PRCC_PCLK_STORE(clk, 6, 6);
+
+	clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", clkrst6_base,
+				BIT(7), 0);
+	PRCC_PCLK_STORE(clk, 6, 7);
+
+	/* PRCC K-clocks
+	 *
+	 * FIXME: Some drivers requires PERPIH[n| to be automatically enabled
+	 * by enabling just the K-clock, even if it is not a valid parent to
+	 * the K-clock. Until drivers get fixed we might need some kind of
+	 * "parent muxed join".
+	 */
+
+	/* Periph1 */
+	clk = clk_reg_prcc_kclk("p1_uart0_kclk", "uartclk",
+			clkrst1_base, BIT(0), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 1, 0);
+
+	clk = clk_reg_prcc_kclk("p1_uart1_kclk", "uartclk",
+			clkrst1_base, BIT(1), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 1, 1);
+
+	clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk",
+			clkrst1_base, BIT(2), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 1, 2);
+
+	clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk",
+			clkrst1_base, BIT(3), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 1, 3);
+
+	clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk",
+			clkrst1_base, BIT(4), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 1, 4);
+
+	clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmcclk",
+			clkrst1_base, BIT(5), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 1, 5);
+
+	clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk",
+			clkrst1_base, BIT(6), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 1, 6);
+
+	clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk",
+			clkrst1_base, BIT(8), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 1, 8);
+
+	clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk",
+			clkrst1_base, BIT(9), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 1, 9);
+
+	clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk",
+			clkrst1_base, BIT(10), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 1, 10);
+
+	/* Periph2 */
+	clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk",
+			clkrst2_base, BIT(0), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 2, 0);
+
+	clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmcclk",
+			clkrst2_base, BIT(2), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 2, 2);
+
+	clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk",
+			clkrst2_base, BIT(3), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 2, 3);
+
+	clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmcclk",
+			clkrst2_base, BIT(4), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 2, 4);
+
+	clk = clk_reg_prcc_kclk("p2_sdi3_kclk", "sdmmcclk",
+			clkrst2_base, BIT(5), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 2, 5);
+
+	/* Note that rate is received from parent. */
+	clk = clk_reg_prcc_kclk("p2_ssirx_kclk", "hsirxclk",
+			clkrst2_base, BIT(6),
+			CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
+	PRCC_KCLK_STORE(clk, 2, 6);
+
+	clk = clk_reg_prcc_kclk("p2_ssitx_kclk", "hsitxclk",
+			clkrst2_base, BIT(7),
+			CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
+	PRCC_KCLK_STORE(clk, 2, 7);
+
+	/* Periph3 */
+	clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk",
+			clkrst3_base, BIT(1), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 3, 1);
+
+	clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk",
+			clkrst3_base, BIT(2), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 3, 2);
+
+	clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk",
+			clkrst3_base, BIT(3), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 3, 3);
+
+	clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmcclk",
+			clkrst3_base, BIT(4), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 3, 4);
+
+	clk = clk_reg_prcc_kclk("p3_ske_kclk", "rtc32k",
+			clkrst3_base, BIT(5), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 3, 5);
+
+	clk = clk_reg_prcc_kclk("p3_uart2_kclk", "uartclk",
+			clkrst3_base, BIT(6), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 3, 6);
+
+	clk = clk_reg_prcc_kclk("p3_sdi5_kclk", "sdmmcclk",
+			clkrst3_base, BIT(7), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 3, 7);
+
+	/* Periph6 */
+	clk = clk_reg_prcc_kclk("p3_rng_kclk", "rngclk",
+			clkrst6_base, BIT(0), CLK_SET_RATE_GATE);
+	PRCC_KCLK_STORE(clk, 6, 0);
+
+	for_each_child_of_node(np, child) {
+		static struct clk_onecell_data clk_data;
+
+		if (!of_node_cmp(child->name, "prcmu-clock")) {
+			clk_data.clks = prcmu_clk;
+			clk_data.clk_num = ARRAY_SIZE(prcmu_clk);
+			of_clk_add_provider(child, of_clk_src_onecell_get, &clk_data);
+		}
+		if (!of_node_cmp(child->name, "prcc-periph-clock"))
+			of_clk_add_provider(child, ux500_twocell_get, prcc_pclk);
+
+		if (!of_node_cmp(child->name, "prcc-kernel-clock"))
+			of_clk_add_provider(child, ux500_twocell_get, prcc_kclk);
+
+		if (!of_node_cmp(child->name, "rtc32k-clock"))
+			of_clk_add_provider(child, of_clk_src_simple_get, rtc_clk);
+
+		if (!of_node_cmp(child->name, "smp-twd-clock"))
+			of_clk_add_provider(child, of_clk_src_simple_get, twd_clk);
+	}
+}
diff --git a/drivers/clk/ux500/u8540_clk.c b/drivers/clk/ux500/u8540_clk.c
index f262588..20c8add 100644
--- a/drivers/clk/ux500/u8540_clk.c
+++ b/drivers/clk/ux500/u8540_clk.c
@@ -83,7 +83,7 @@
 	clk_register_clkdev(clk, NULL, "lcd");
 	clk_register_clkdev(clk, "lcd", "mcde");
 
-	clk = clk_reg_prcmu_opp_gate("bmlclk", NULL, PRCMU_BML8580CLK,
+	clk = clk_reg_prcmu_opp_gate("bmlclk", NULL, PRCMU_BMLCLK,
 				CLK_IS_ROOT);
 	clk_register_clkdev(clk, NULL, "bml");
 
diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c
index 67ccf4a..f5e4c21 100644
--- a/drivers/clk/versatile/clk-icst.c
+++ b/drivers/clk/versatile/clk-icst.c
@@ -107,7 +107,7 @@
 
 	vco = icst_hz_to_vco(icst->params, rate);
 	icst->rate = icst_hz(icst->params, vco);
-	vco_set(icst->vcoreg, icst->lockreg, vco);
+	vco_set(icst->lockreg, icst->vcoreg, vco);
 	return 0;
 }
 
diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c
index cc40fe6..10772aa 100644
--- a/drivers/clk/zynq/clkc.c
+++ b/drivers/clk/zynq/clkc.c
@@ -117,13 +117,19 @@
 		goto err;
 	fclk_gate_lock = kmalloc(sizeof(*fclk_gate_lock), GFP_KERNEL);
 	if (!fclk_gate_lock)
-		goto err;
+		goto err_fclk_gate_lock;
 	spin_lock_init(fclk_lock);
 	spin_lock_init(fclk_gate_lock);
 
 	mux_name = kasprintf(GFP_KERNEL, "%s_mux", clk_name);
+	if (!mux_name)
+		goto err_mux_name;
 	div0_name = kasprintf(GFP_KERNEL, "%s_div0", clk_name);
+	if (!div0_name)
+		goto err_div0_name;
 	div1_name = kasprintf(GFP_KERNEL, "%s_div1", clk_name);
+	if (!div1_name)
+		goto err_div1_name;
 
 	clk = clk_register_mux(NULL, mux_name, parents, 4,
 			CLK_SET_RATE_NO_REPARENT, fclk_ctrl_reg, 4, 2, 0,
@@ -147,6 +153,14 @@
 
 	return;
 
+err_div1_name:
+	kfree(div0_name);
+err_div0_name:
+	kfree(mux_name);
+err_mux_name:
+	kfree(fclk_gate_lock);
+err_fclk_gate_lock:
+	kfree(fclk_lock);
 err:
 	clks[fclk] = ERR_PTR(-ENOMEM);
 }
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 971d796..bdb953e 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -34,6 +34,7 @@
 	bool
 
 config SUN4I_TIMER
+	select CLKSRC_MMIO
 	bool
 
 config VT8500_TIMER
@@ -71,10 +72,33 @@
 	help
 	  Use the always on PRCMU Timer as sched_clock
 
+config CLKSRC_EFM32
+	bool "Clocksource for Energy Micro's EFM32 SoCs" if !ARCH_EFM32
+	depends on OF && ARM && (ARCH_EFM32 || COMPILE_TEST)
+	default ARCH_EFM32
+	help
+	  Support to use the timers of EFM32 SoCs as clock source and clock
+	  event device.
+
 config ARM_ARCH_TIMER
 	bool
 	select CLKSRC_OF if OF
 
+config ARM_ARCH_TIMER_EVTSTREAM
+	bool "Support for ARM architected timer event stream generation"
+	default y if ARM_ARCH_TIMER
+	help
+	  This option enables support for event stream generation based on
+	  the ARM architected timer. It is used for waking up CPUs executing
+	  the wfe instruction at a frequency represented as a power-of-2
+	  divisor of the clock rate.
+	  The main use of the event stream is wfe-based timeouts of userspace
+	  locking implementations. It might also be useful for imposing timeout
+	  on wfe to safeguard against any programming errors in case an expected
+	  event is not generated.
+	  This must be disabled for hardware validation purposes to detect any
+	  hardware anomalies of missing events.
+
 config ARM_GLOBAL_TIMER
 	bool
 	select CLKSRC_OF if OF
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 704d6d3..33621ef 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -27,6 +27,7 @@
 obj-$(CONFIG_ARCH_NSPIRE)	+= zevio-timer.o
 obj-$(CONFIG_ARCH_BCM)		+= bcm_kona_timer.o
 obj-$(CONFIG_CADENCE_TTC_TIMER)	+= cadence_ttc_timer.o
+obj-$(CONFIG_CLKSRC_EFM32)	+= time-efm32.o
 obj-$(CONFIG_CLKSRC_EXYNOS_MCT)	+= exynos_mct.o
 obj-$(CONFIG_CLKSRC_SAMSUNG_PWM)	+= samsung_pwm_timer.o
 obj-$(CONFIG_VF_PIT_TIMER)	+= vf_pit_timer.o
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index fbd9ccd..95fb944 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -13,12 +13,14 @@
 #include <linux/device.h>
 #include <linux/smp.h>
 #include <linux/cpu.h>
+#include <linux/cpu_pm.h>
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/sched_clock.h>
 
 #include <asm/arch_timer.h>
 #include <asm/virt.h>
@@ -294,6 +296,19 @@
 	clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff);
 }
 
+static void arch_timer_configure_evtstream(void)
+{
+	int evt_stream_div, pos;
+
+	/* Find the closest power of two to the divisor */
+	evt_stream_div = arch_timer_rate / ARCH_TIMER_EVT_STREAM_FREQ;
+	pos = fls(evt_stream_div);
+	if (pos > 1 && !(evt_stream_div & (1 << (pos - 2))))
+		pos--;
+	/* enable event stream */
+	arch_timer_evtstrm_enable(min(pos, 15));
+}
+
 static int arch_timer_setup(struct clock_event_device *clk)
 {
 	__arch_timer_setup(ARCH_CP15_TIMER, clk);
@@ -307,6 +322,8 @@
 	}
 
 	arch_counter_set_user_access();
+	if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM))
+		arch_timer_configure_evtstream();
 
 	return 0;
 }
@@ -389,7 +406,7 @@
 	.rating	= 400,
 	.read	= arch_counter_read,
 	.mask	= CLOCKSOURCE_MASK(56),
-	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
+	.flags	= CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP,
 };
 
 static struct cyclecounter cyclecounter = {
@@ -419,6 +436,9 @@
 	cyclecounter.mult = clocksource_counter.mult;
 	cyclecounter.shift = clocksource_counter.shift;
 	timecounter_init(&timecounter, &cyclecounter, start_count);
+
+	/* 56 bits minimum, so we assume worst case rollover */
+	sched_clock_register(arch_timer_read_counter, 56, arch_timer_rate);
 }
 
 static void arch_timer_stop(struct clock_event_device *clk)
@@ -460,6 +480,33 @@
 	.notifier_call = arch_timer_cpu_notify,
 };
 
+#ifdef CONFIG_CPU_PM
+static unsigned int saved_cntkctl;
+static int arch_timer_cpu_pm_notify(struct notifier_block *self,
+				    unsigned long action, void *hcpu)
+{
+	if (action == CPU_PM_ENTER)
+		saved_cntkctl = arch_timer_get_cntkctl();
+	else if (action == CPU_PM_ENTER_FAILED || action == CPU_PM_EXIT)
+		arch_timer_set_cntkctl(saved_cntkctl);
+	return NOTIFY_OK;
+}
+
+static struct notifier_block arch_timer_cpu_pm_notifier = {
+	.notifier_call = arch_timer_cpu_pm_notify,
+};
+
+static int __init arch_timer_cpu_pm_init(void)
+{
+	return cpu_pm_register_notifier(&arch_timer_cpu_pm_notifier);
+}
+#else
+static int __init arch_timer_cpu_pm_init(void)
+{
+	return 0;
+}
+#endif
+
 static int __init arch_timer_register(void)
 {
 	int err;
@@ -499,11 +546,17 @@
 	if (err)
 		goto out_free_irq;
 
+	err = arch_timer_cpu_pm_init();
+	if (err)
+		goto out_unreg_notify;
+
 	/* Immediately configure the timer on the boot CPU */
 	arch_timer_setup(this_cpu_ptr(arch_timer_evt));
 
 	return 0;
 
+out_unreg_notify:
+	unregister_cpu_notifier(&arch_timer_cpu_nb);
 out_free_irq:
 	if (arch_timer_use_virtual)
 		free_percpu_irq(arch_timer_ppi[VIRT_PPI], arch_timer_evt);
diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c
index b66c1f3..c639b1a 100644
--- a/drivers/clocksource/arm_global_timer.c
+++ b/drivers/clocksource/arm_global_timer.c
@@ -169,7 +169,8 @@
 	int cpu = smp_processor_id();
 
 	clk->name = "arm_global_timer";
-	clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+	clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
+		CLOCK_EVT_FEAT_PERCPU;
 	clk->set_mode = gt_clockevent_set_mode;
 	clk->set_next_event = gt_clockevent_set_next_event;
 	clk->cpumask = cpumask_of(cpu);
diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c
index 07ea7ce..26ed331 100644
--- a/drivers/clocksource/bcm2835_timer.c
+++ b/drivers/clocksource/bcm2835_timer.c
@@ -49,7 +49,7 @@
 
 static void __iomem *system_clock __read_mostly;
 
-static u32 notrace bcm2835_sched_read(void)
+static u64 notrace bcm2835_sched_read(void)
 {
 	return readl_relaxed(system_clock);
 }
@@ -110,7 +110,7 @@
 		panic("Can't read clock-frequency");
 
 	system_clock = base + REG_COUNTER_LO;
-	setup_sched_clock(bcm2835_sched_read, 32, freq);
+	sched_clock_register(bcm2835_sched_read, 32, freq);
 
 	clocksource_mmio_init(base + REG_COUNTER_LO, node->name,
 		freq, 300, 32, clocksource_mmio_readl_up);
diff --git a/drivers/clocksource/clksrc-dbx500-prcmu.c b/drivers/clocksource/clksrc-dbx500-prcmu.c
index a9fd4ad..b375106 100644
--- a/drivers/clocksource/clksrc-dbx500-prcmu.c
+++ b/drivers/clocksource/clksrc-dbx500-prcmu.c
@@ -53,7 +53,7 @@
 
 #ifdef CONFIG_CLKSRC_DBX500_PRCMU_SCHED_CLOCK
 
-static u32 notrace dbx500_prcmu_sched_clock_read(void)
+static u64 notrace dbx500_prcmu_sched_clock_read(void)
 {
 	if (unlikely(!clksrc_dbx500_timer_base))
 		return 0;
@@ -81,8 +81,7 @@
 		       clksrc_dbx500_timer_base + PRCMU_TIMER_REF);
 	}
 #ifdef CONFIG_CLKSRC_DBX500_PRCMU_SCHED_CLOCK
-	setup_sched_clock(dbx500_prcmu_sched_clock_read,
-			 32, RATE_32K);
+	sched_clock_register(dbx500_prcmu_sched_clock_read, 32, RATE_32K);
 #endif
 	clocksource_register_hz(&clocksource_dbx500_prcmu, RATE_32K);
 }
diff --git a/drivers/clocksource/clksrc-of.c b/drivers/clocksource/clksrc-of.c
index b9ddd9e..35639cf4 100644
--- a/drivers/clocksource/clksrc-of.c
+++ b/drivers/clocksource/clksrc-of.c
@@ -35,5 +35,6 @@
 
 		init_func = match->data;
 		init_func(np);
+		of_node_put(np);
 	}
 }
diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c
index 4cbae4f..45ba8ae 100644
--- a/drivers/clocksource/dw_apb_timer_of.c
+++ b/drivers/clocksource/dw_apb_timer_of.c
@@ -23,7 +23,7 @@
 #include <linux/clk.h>
 #include <linux/sched_clock.h>
 
-static void timer_get_base_and_rate(struct device_node *np,
+static void __init timer_get_base_and_rate(struct device_node *np,
 				    void __iomem **base, u32 *rate)
 {
 	struct clk *timer_clk;
@@ -55,11 +55,11 @@
 
 try_clock_freq:
 	if (of_property_read_u32(np, "clock-freq", rate) &&
-		of_property_read_u32(np, "clock-frequency", rate))
+	    of_property_read_u32(np, "clock-frequency", rate))
 		panic("No clock nor clock-frequency property for %s", np->name);
 }
 
-static void add_clockevent(struct device_node *event_timer)
+static void __init add_clockevent(struct device_node *event_timer)
 {
 	void __iomem *iobase;
 	struct dw_apb_clock_event_device *ced;
@@ -82,7 +82,7 @@
 static void __iomem *sched_io_base;
 static u32 sched_rate;
 
-static void add_clocksource(struct device_node *source_timer)
+static void __init add_clocksource(struct device_node *source_timer)
 {
 	void __iomem *iobase;
 	struct dw_apb_clocksource *cs;
@@ -106,7 +106,7 @@
 	sched_rate = rate;
 }
 
-static u32 read_sched_clock(void)
+static u64 read_sched_clock(void)
 {
 	return __raw_readl(sched_io_base);
 }
@@ -117,7 +117,7 @@
 	{ /* Sentinel */ },
 };
 
-static void init_sched_clock(void)
+static void __init init_sched_clock(void)
 {
 	struct device_node *sched_timer;
 
@@ -128,7 +128,7 @@
 		of_node_put(sched_timer);
 	}
 
-	setup_sched_clock(read_sched_clock, 32, sched_rate);
+	sched_clock_register(read_sched_clock, 32, sched_rate);
 }
 
 static int num_called;
@@ -138,12 +138,10 @@
 	case 0:
 		pr_debug("%s: found clockevent timer\n", __func__);
 		add_clockevent(timer);
-		of_node_put(timer);
 		break;
 	case 1:
 		pr_debug("%s: found clocksource timer\n", __func__);
 		add_clocksource(timer);
-		of_node_put(timer);
 		init_sched_clock();
 		break;
 	default:
diff --git a/drivers/clocksource/em_sti.c b/drivers/clocksource/em_sti.c
index 3a5909c..9d17083 100644
--- a/drivers/clocksource/em_sti.c
+++ b/drivers/clocksource/em_sti.c
@@ -78,7 +78,7 @@
 	int ret;
 
 	/* enable clock */
-	ret = clk_enable(p->clk);
+	ret = clk_prepare_enable(p->clk);
 	if (ret) {
 		dev_err(&p->pdev->dev, "cannot enable clock\n");
 		return ret;
@@ -107,7 +107,7 @@
 	em_sti_write(p, STI_INTENCLR, 3);
 
 	/* stop clock */
-	clk_disable(p->clk);
+	clk_disable_unprepare(p->clk);
 }
 
 static cycle_t em_sti_count(struct em_sti_priv *p)
diff --git a/drivers/clocksource/mxs_timer.c b/drivers/clocksource/mxs_timer.c
index 0f5e65f..445b68a 100644
--- a/drivers/clocksource/mxs_timer.c
+++ b/drivers/clocksource/mxs_timer.c
@@ -222,7 +222,7 @@
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-static u32 notrace mxs_read_sched_clock_v2(void)
+static u64 notrace mxs_read_sched_clock_v2(void)
 {
 	return ~readl_relaxed(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1));
 }
@@ -236,7 +236,7 @@
 	else {
 		clocksource_mmio_init(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1),
 			"mxs_timer", c, 200, 32, clocksource_mmio_readl_down);
-		setup_sched_clock(mxs_read_sched_clock_v2, 32, c);
+		sched_clock_register(mxs_read_sched_clock_v2, 32, c);
 	}
 
 	return 0;
diff --git a/drivers/clocksource/nomadik-mtu.c b/drivers/clocksource/nomadik-mtu.c
index 1b74bea..ed7b73b 100644
--- a/drivers/clocksource/nomadik-mtu.c
+++ b/drivers/clocksource/nomadik-mtu.c
@@ -76,7 +76,7 @@
  * local implementation which uses the clocksource to get some
  * better resolution when scheduling the kernel.
  */
-static u32 notrace nomadik_read_sched_clock(void)
+static u64 notrace nomadik_read_sched_clock(void)
 {
 	if (unlikely(!mtu_base))
 		return 0;
@@ -231,7 +231,7 @@
 		       "mtu_0");
 
 #ifdef CONFIG_CLKSRC_NOMADIK_MTU_SCHED_CLOCK
-	setup_sched_clock(nomadik_read_sched_clock, 32, rate);
+	sched_clock_register(nomadik_read_sched_clock, 32, rate);
 #endif
 
 	/* Timer 1 is used for events, register irq and clockevents */
diff --git a/drivers/clocksource/samsung_pwm_timer.c b/drivers/clocksource/samsung_pwm_timer.c
index ab29476..85082e8 100644
--- a/drivers/clocksource/samsung_pwm_timer.c
+++ b/drivers/clocksource/samsung_pwm_timer.c
@@ -331,7 +331,7 @@
  * this wraps around for now, since it is just a relative time
  * stamp. (Inspired by U300 implementation.)
  */
-static u32 notrace samsung_read_sched_clock(void)
+static u64 notrace samsung_read_sched_clock(void)
 {
 	return samsung_clocksource_read(NULL);
 }
@@ -357,7 +357,7 @@
 	else
 		pwm.source_reg = pwm.base + pwm.source_id * 0x0c + 0x14;
 
-	setup_sched_clock(samsung_read_sched_clock,
+	sched_clock_register(samsung_read_sched_clock,
 						pwm.variant.bits, clock_rate);
 
 	samsung_clocksource.mask = CLOCKSOURCE_MASK(pwm.variant.bits);
diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c
index 8ead025..2fb4695 100644
--- a/drivers/clocksource/sun4i_timer.c
+++ b/drivers/clocksource/sun4i_timer.c
@@ -37,6 +37,8 @@
 #define TIMER_INTVAL_REG(val)	(0x10 * (val) + 0x14)
 #define TIMER_CNTVAL_REG(val)	(0x10 * (val) + 0x18)
 
+#define TIMER_SYNC_TICKS	3
+
 static void __iomem *timer_base;
 static u32 ticks_per_jiffy;
 
@@ -50,7 +52,7 @@
 {
 	u32 old = readl(timer_base + TIMER_CNTVAL_REG(1));
 
-	while ((old - readl(timer_base + TIMER_CNTVAL_REG(1))) < 3)
+	while ((old - readl(timer_base + TIMER_CNTVAL_REG(1))) < TIMER_SYNC_TICKS)
 		cpu_relax();
 }
 
@@ -104,7 +106,7 @@
 				   struct clock_event_device *unused)
 {
 	sun4i_clkevt_time_stop(0);
-	sun4i_clkevt_time_setup(0, evt);
+	sun4i_clkevt_time_setup(0, evt - TIMER_SYNC_TICKS);
 	sun4i_clkevt_time_start(0, false);
 
 	return 0;
@@ -131,7 +133,7 @@
 
 static struct irqaction sun4i_timer_irq = {
 	.name = "sun4i_timer0",
-	.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.flags = IRQF_TIMER | IRQF_IRQPOLL,
 	.handler = sun4i_timer_interrupt,
 	.dev_id = &sun4i_clockevent,
 };
@@ -187,8 +189,8 @@
 
 	sun4i_clockevent.cpumask = cpumask_of(0);
 
-	clockevents_config_and_register(&sun4i_clockevent, rate, 0x1,
-					0xffffffff);
+	clockevents_config_and_register(&sun4i_clockevent, rate,
+					TIMER_SYNC_TICKS, 0xffffffff);
 }
 CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-timer",
 		       sun4i_timer_init);
diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
index 8a61872..00fdd11 100644
--- a/drivers/clocksource/tcb_clksrc.c
+++ b/drivers/clocksource/tcb_clksrc.c
@@ -100,7 +100,7 @@
 			|| tcd->clkevt.mode == CLOCK_EVT_MODE_ONESHOT) {
 		__raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR));
 		__raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR));
-		clk_disable(tcd->clk);
+		clk_disable_unprepare(tcd->clk);
 	}
 
 	switch (m) {
@@ -109,7 +109,7 @@
 	 * of oneshot, we get lower overhead and improved accuracy.
 	 */
 	case CLOCK_EVT_MODE_PERIODIC:
-		clk_enable(tcd->clk);
+		clk_prepare_enable(tcd->clk);
 
 		/* slow clock, count up to RC, then irq and restart */
 		__raw_writel(timer_clock
@@ -126,7 +126,7 @@
 		break;
 
 	case CLOCK_EVT_MODE_ONESHOT:
-		clk_enable(tcd->clk);
+		clk_prepare_enable(tcd->clk);
 
 		/* slow clock, count up to RC, then irq and stop */
 		__raw_writel(timer_clock | ATMEL_TC_CPCSTOP
@@ -180,15 +180,22 @@
 
 static struct irqaction tc_irqaction = {
 	.name		= "tc_clkevt",
-	.flags		= IRQF_TIMER | IRQF_DISABLED,
+	.flags		= IRQF_TIMER,
 	.handler	= ch2_irq,
 };
 
-static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
+static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
 {
+	int ret;
 	struct clk *t2_clk = tc->clk[2];
 	int irq = tc->irq[2];
 
+	/* try to enable t2 clk to avoid future errors in mode change */
+	ret = clk_prepare_enable(t2_clk);
+	if (ret)
+		return ret;
+	clk_disable_unprepare(t2_clk);
+
 	clkevt.regs = tc->regs;
 	clkevt.clk = t2_clk;
 	tc_irqaction.dev_id = &clkevt;
@@ -197,16 +204,21 @@
 
 	clkevt.clkevt.cpumask = cpumask_of(0);
 
+	ret = setup_irq(irq, &tc_irqaction);
+	if (ret)
+		return ret;
+
 	clockevents_config_and_register(&clkevt.clkevt, 32768, 1, 0xffff);
 
-	setup_irq(irq, &tc_irqaction);
+	return ret;
 }
 
 #else /* !CONFIG_GENERIC_CLOCKEVENTS */
 
-static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
+static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
 {
 	/* NOTHING */
+	return 0;
 }
 
 #endif
@@ -265,6 +277,7 @@
 	int best_divisor_idx = -1;
 	int clk32k_divisor_idx = -1;
 	int i;
+	int ret;
 
 	tc = atmel_tc_alloc(CONFIG_ATMEL_TCB_CLKSRC_BLOCK, clksrc.name);
 	if (!tc) {
@@ -275,7 +288,11 @@
 	pdev = tc->pdev;
 
 	t0_clk = tc->clk[0];
-	clk_enable(t0_clk);
+	ret = clk_prepare_enable(t0_clk);
+	if (ret) {
+		pr_debug("can't enable T0 clk\n");
+		goto err_free_tc;
+	}
 
 	/* How fast will we be counting?  Pick something over 5 MHz.  */
 	rate = (u32) clk_get_rate(t0_clk);
@@ -313,17 +330,39 @@
 		/* tclib will give us three clocks no matter what the
 		 * underlying platform supports.
 		 */
-		clk_enable(tc->clk[1]);
+		ret = clk_prepare_enable(tc->clk[1]);
+		if (ret) {
+			pr_debug("can't enable T1 clk\n");
+			goto err_disable_t0;
+		}
 		/* setup both channel 0 & 1 */
 		tcb_setup_dual_chan(tc, best_divisor_idx);
 	}
 
 	/* and away we go! */
-	clocksource_register_hz(&clksrc, divided_rate);
+	ret = clocksource_register_hz(&clksrc, divided_rate);
+	if (ret)
+		goto err_disable_t1;
 
 	/* channel 2:  periodic and oneshot timer support */
-	setup_clkevents(tc, clk32k_divisor_idx);
+	ret = setup_clkevents(tc, clk32k_divisor_idx);
+	if (ret)
+		goto err_unregister_clksrc;
 
 	return 0;
+
+err_unregister_clksrc:
+	clocksource_unregister(&clksrc);
+
+err_disable_t1:
+	if (!tc->tcb_config || tc->tcb_config->counter_width != 32)
+		clk_disable_unprepare(tc->clk[1]);
+
+err_disable_t0:
+	clk_disable_unprepare(t0_clk);
+
+err_free_tc:
+	atmel_tc_free(tc);
+	return ret;
 }
 arch_initcall(tcb_clksrc_init);
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c
index 9396170..6428492 100644
--- a/drivers/clocksource/tegra20_timer.c
+++ b/drivers/clocksource/tegra20_timer.c
@@ -98,7 +98,7 @@
 	.set_mode	= tegra_timer_set_mode,
 };
 
-static u32 notrace tegra_read_sched_clock(void)
+static u64 notrace tegra_read_sched_clock(void)
 {
 	return timer_readl(TIMERUS_CNTR_1US);
 }
@@ -181,8 +181,6 @@
 		rate = clk_get_rate(clk);
 	}
 
-	of_node_put(np);
-
 	switch (rate) {
 	case 12000000:
 		timer_writel(0x000b, TIMERUS_USEC_CFG);
@@ -200,7 +198,7 @@
 		WARN(1, "Unknown clock rate");
 	}
 
-	setup_sched_clock(tegra_read_sched_clock, 32, 1000000);
+	sched_clock_register(tegra_read_sched_clock, 32, 1000000);
 
 	if (clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US,
 		"timer_us", 1000000, 300, 32, clocksource_mmio_readl_up)) {
@@ -241,8 +239,6 @@
 	else
 		clk_prepare_enable(clk);
 
-	of_node_put(np);
-
 	register_persistent_clock(NULL, tegra_read_persistent_clock);
 }
 CLOCKSOURCE_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc);
diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c
index 0198504..d8e47e5 100644
--- a/drivers/clocksource/time-armada-370-xp.c
+++ b/drivers/clocksource/time-armada-370-xp.c
@@ -96,7 +96,7 @@
 		local_base + TIMER_CTRL_OFF);
 }
 
-static u32 notrace armada_370_xp_read_sched_clock(void)
+static u64 notrace armada_370_xp_read_sched_clock(void)
 {
 	return ~readl(timer_base + TIMER0_VAL_OFF);
 }
@@ -258,7 +258,7 @@
 	/*
 	 * Set scale and timer for sched_clock.
 	 */
-	setup_sched_clock(armada_370_xp_read_sched_clock, 32, timer_clk);
+	sched_clock_register(armada_370_xp_read_sched_clock, 32, timer_clk);
 
 	/*
 	 * Setup free-running clocksource timer (interrupts
diff --git a/drivers/clocksource/time-efm32.c b/drivers/clocksource/time-efm32.c
new file mode 100644
index 0000000..1a6205b
--- /dev/null
+++ b/drivers/clocksource/time-efm32.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2013 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/clk.h>
+
+#define TIMERn_CTRL			0x00
+#define TIMERn_CTRL_PRESC(val)			(((val) & 0xf) << 24)
+#define TIMERn_CTRL_PRESC_1024			TIMERn_CTRL_PRESC(10)
+#define TIMERn_CTRL_CLKSEL(val)			(((val) & 0x3) << 16)
+#define TIMERn_CTRL_CLKSEL_PRESCHFPERCLK	TIMERn_CTRL_CLKSEL(0)
+#define TIMERn_CTRL_OSMEN			0x00000010
+#define TIMERn_CTRL_MODE(val)			(((val) & 0x3) <<  0)
+#define TIMERn_CTRL_MODE_UP			TIMERn_CTRL_MODE(0)
+#define TIMERn_CTRL_MODE_DOWN			TIMERn_CTRL_MODE(1)
+
+#define TIMERn_CMD			0x04
+#define TIMERn_CMD_START			0x00000001
+#define TIMERn_CMD_STOP				0x00000002
+
+#define TIMERn_IEN			0x0c
+#define TIMERn_IF			0x10
+#define TIMERn_IFS			0x14
+#define TIMERn_IFC			0x18
+#define TIMERn_IRQ_UF				0x00000002
+
+#define TIMERn_TOP			0x1c
+#define TIMERn_CNT			0x24
+
+struct efm32_clock_event_ddata {
+	struct clock_event_device evtdev;
+	void __iomem *base;
+	unsigned periodic_top;
+};
+
+static void efm32_clock_event_set_mode(enum clock_event_mode mode,
+				       struct clock_event_device *evtdev)
+{
+	struct efm32_clock_event_ddata *ddata =
+		container_of(evtdev, struct efm32_clock_event_ddata, evtdev);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD);
+		writel_relaxed(ddata->periodic_top, ddata->base + TIMERn_TOP);
+		writel_relaxed(TIMERn_CTRL_PRESC_1024 |
+			       TIMERn_CTRL_CLKSEL_PRESCHFPERCLK |
+			       TIMERn_CTRL_MODE_DOWN,
+			       ddata->base + TIMERn_CTRL);
+		writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD);
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+		writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD);
+		writel_relaxed(TIMERn_CTRL_PRESC_1024 |
+			       TIMERn_CTRL_CLKSEL_PRESCHFPERCLK |
+			       TIMERn_CTRL_OSMEN |
+			       TIMERn_CTRL_MODE_DOWN,
+			       ddata->base + TIMERn_CTRL);
+		break;
+
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD);
+		break;
+
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+}
+
+static int efm32_clock_event_set_next_event(unsigned long evt,
+					    struct clock_event_device *evtdev)
+{
+	struct efm32_clock_event_ddata *ddata =
+		container_of(evtdev, struct efm32_clock_event_ddata, evtdev);
+
+	writel_relaxed(TIMERn_CMD_STOP, ddata->base + TIMERn_CMD);
+	writel_relaxed(evt, ddata->base + TIMERn_CNT);
+	writel_relaxed(TIMERn_CMD_START, ddata->base + TIMERn_CMD);
+
+	return 0;
+}
+
+static irqreturn_t efm32_clock_event_handler(int irq, void *dev_id)
+{
+	struct efm32_clock_event_ddata *ddata = dev_id;
+
+	writel_relaxed(TIMERn_IRQ_UF, ddata->base + TIMERn_IFC);
+
+	ddata->evtdev.event_handler(&ddata->evtdev);
+
+	return IRQ_HANDLED;
+}
+
+static struct efm32_clock_event_ddata clock_event_ddata = {
+	.evtdev = {
+		.name = "efm32 clockevent",
+		.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_MODE_PERIODIC,
+		.set_mode = efm32_clock_event_set_mode,
+		.set_next_event = efm32_clock_event_set_next_event,
+		.rating = 200,
+	},
+};
+
+static struct irqaction efm32_clock_event_irq = {
+	.name = "efm32 clockevent",
+	.flags = IRQF_TIMER,
+	.handler = efm32_clock_event_handler,
+	.dev_id = &clock_event_ddata,
+};
+
+static int __init efm32_clocksource_init(struct device_node *np)
+{
+	struct clk *clk;
+	void __iomem *base;
+	unsigned long rate;
+	int ret;
+
+	clk = of_clk_get(np, 0);
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
+		pr_err("failed to get clock for clocksource (%d)\n", ret);
+		goto err_clk_get;
+	}
+
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		pr_err("failed to enable timer clock for clocksource (%d)\n",
+		       ret);
+		goto err_clk_enable;
+	}
+	rate = clk_get_rate(clk);
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		ret = -EADDRNOTAVAIL;
+		pr_err("failed to map registers for clocksource\n");
+		goto err_iomap;
+	}
+
+	writel_relaxed(TIMERn_CTRL_PRESC_1024 |
+		       TIMERn_CTRL_CLKSEL_PRESCHFPERCLK |
+		       TIMERn_CTRL_MODE_UP, base + TIMERn_CTRL);
+	writel_relaxed(TIMERn_CMD_START, base + TIMERn_CMD);
+
+	ret = clocksource_mmio_init(base + TIMERn_CNT, "efm32 timer",
+				    DIV_ROUND_CLOSEST(rate, 1024), 200, 16,
+				    clocksource_mmio_readl_up);
+	if (ret) {
+		pr_err("failed to init clocksource (%d)\n", ret);
+		goto err_clocksource_init;
+	}
+
+	return 0;
+
+err_clocksource_init:
+
+	iounmap(base);
+err_iomap:
+
+	clk_disable_unprepare(clk);
+err_clk_enable:
+
+	clk_put(clk);
+err_clk_get:
+
+	return ret;
+}
+
+static int __init efm32_clockevent_init(struct device_node *np)
+{
+	struct clk *clk;
+	void __iomem *base;
+	unsigned long rate;
+	int irq;
+	int ret;
+
+	clk = of_clk_get(np, 0);
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
+		pr_err("failed to get clock for clockevent (%d)\n", ret);
+		goto err_clk_get;
+	}
+
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		pr_err("failed to enable timer clock for clockevent (%d)\n",
+		       ret);
+		goto err_clk_enable;
+	}
+	rate = clk_get_rate(clk);
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		ret = -EADDRNOTAVAIL;
+		pr_err("failed to map registers for clockevent\n");
+		goto err_iomap;
+	}
+
+	irq = irq_of_parse_and_map(np, 0);
+	if (!irq) {
+		ret = -ENOENT;
+		pr_err("failed to get irq for clockevent\n");
+		goto err_get_irq;
+	}
+
+	writel_relaxed(TIMERn_IRQ_UF, base + TIMERn_IEN);
+
+	clock_event_ddata.base = base;
+	clock_event_ddata.periodic_top = DIV_ROUND_CLOSEST(rate, 1024 * HZ);
+
+	setup_irq(irq, &efm32_clock_event_irq);
+
+	clockevents_config_and_register(&clock_event_ddata.evtdev,
+					DIV_ROUND_CLOSEST(rate, 1024),
+					0xf, 0xffff);
+
+	return 0;
+
+err_get_irq:
+
+	iounmap(base);
+err_iomap:
+
+	clk_disable_unprepare(clk);
+err_clk_enable:
+
+	clk_put(clk);
+err_clk_get:
+
+	return ret;
+}
+
+/*
+ * This function asserts that we have exactly one clocksource and one
+ * clock_event_device in the end.
+ */
+static void __init efm32_timer_init(struct device_node *np)
+{
+	static int has_clocksource, has_clockevent;
+	int ret;
+
+	if (!has_clocksource) {
+		ret = efm32_clocksource_init(np);
+		if (!ret) {
+			has_clocksource = 1;
+			return;
+		}
+	}
+
+	if (!has_clockevent) {
+		ret = efm32_clockevent_init(np);
+		if (!ret) {
+			has_clockevent = 1;
+			return;
+		}
+	}
+}
+CLOCKSOURCE_OF_DECLARE(efm32, "efm32,timer", efm32_timer_init);
diff --git a/drivers/clocksource/timer-prima2.c b/drivers/clocksource/timer-prima2.c
index ef3cfb2..8a492d3 100644
--- a/drivers/clocksource/timer-prima2.c
+++ b/drivers/clocksource/timer-prima2.c
@@ -165,9 +165,9 @@
 };
 
 /* Overwrite weak default sched_clock with more precise one */
-static u32 notrace sirfsoc_read_sched_clock(void)
+static u64 notrace sirfsoc_read_sched_clock(void)
 {
-	return (u32)(sirfsoc_timer_read(NULL) & 0xffffffff);
+	return sirfsoc_timer_read(NULL);
 }
 
 static void __init sirfsoc_clockevent_init(void)
@@ -206,7 +206,7 @@
 
 	BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
 
-	setup_sched_clock(sirfsoc_read_sched_clock, 32, CLOCK_TICK_RATE);
+	sched_clock_register(sirfsoc_read_sched_clock, 64, CLOCK_TICK_RATE);
 
 	BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
 
diff --git a/drivers/clocksource/vf_pit_timer.c b/drivers/clocksource/vf_pit_timer.c
index 587e020..02821b0 100644
--- a/drivers/clocksource/vf_pit_timer.c
+++ b/drivers/clocksource/vf_pit_timer.c
@@ -52,7 +52,7 @@
 	__raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG);
 }
 
-static unsigned int pit_read_sched_clock(void)
+static u64 pit_read_sched_clock(void)
 {
 	return __raw_readl(clksrc_base + PITCVAL);
 }
@@ -64,7 +64,7 @@
 	__raw_writel(~0UL, clksrc_base + PITLDVAL);
 	__raw_writel(PITTCTRL_TEN, clksrc_base + PITTCTRL);
 
-	setup_sched_clock(pit_read_sched_clock, 32, rate);
+	sched_clock_register(pit_read_sched_clock, 32, rate);
 	return clocksource_mmio_init(clksrc_base + PITCVAL, "vf-pit", rate,
 			300, 32, clocksource_mmio_readl_down);
 }
diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c
index 64f553f..ad3c0e8 100644
--- a/drivers/clocksource/vt8500_timer.c
+++ b/drivers/clocksource/vt8500_timer.c
@@ -137,14 +137,12 @@
 	if (!regbase) {
 		pr_err("%s: Missing iobase description in Device Tree\n",
 								__func__);
-		of_node_put(np);
 		return;
 	}
 	timer_irq = irq_of_parse_and_map(np, 0);
 	if (!timer_irq) {
 		pr_err("%s: Missing irq description in Device Tree\n",
 								__func__);
-		of_node_put(np);
 		return;
 	}
 
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 08ae128..c73fc2b 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -65,6 +65,7 @@
 
 	msg = (struct cn_msg *)buffer;
 	ev = (struct proc_event *)msg->data;
+	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
 	ktime_get_ts(&ts); /* get high res monotonic timestamp */
 	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
@@ -80,6 +81,7 @@
 	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
+	msg->flags = 0; /* not used */
 	/*  If cn_netlink_send() failed, the data is not sent */
 	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
 }
@@ -96,6 +98,7 @@
 
 	msg = (struct cn_msg *)buffer;
 	ev = (struct proc_event *)msg->data;
+	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
 	ktime_get_ts(&ts); /* get high res monotonic timestamp */
 	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
@@ -106,6 +109,7 @@
 	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
+	msg->flags = 0; /* not used */
 	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
 }
 
@@ -122,6 +126,7 @@
 
 	msg = (struct cn_msg *)buffer;
 	ev = (struct proc_event *)msg->data;
+	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	ev->what = which_id;
 	ev->event_data.id.process_pid = task->pid;
 	ev->event_data.id.process_tgid = task->tgid;
@@ -145,6 +150,7 @@
 	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
+	msg->flags = 0; /* not used */
 	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
 }
 
@@ -160,6 +166,7 @@
 
 	msg = (struct cn_msg *)buffer;
 	ev = (struct proc_event *)msg->data;
+	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
 	ktime_get_ts(&ts); /* get high res monotonic timestamp */
 	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
@@ -170,6 +177,7 @@
 	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
+	msg->flags = 0; /* not used */
 	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
 }
 
@@ -185,6 +193,7 @@
 
 	msg = (struct cn_msg *)buffer;
 	ev = (struct proc_event *)msg->data;
+	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
 	ktime_get_ts(&ts); /* get high res monotonic timestamp */
 	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
@@ -203,6 +212,7 @@
 	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
+	msg->flags = 0; /* not used */
 	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
 }
 
@@ -218,6 +228,7 @@
 
 	msg = (struct cn_msg *)buffer;
 	ev = (struct proc_event *)msg->data;
+	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
 	ktime_get_ts(&ts); /* get high res monotonic timestamp */
 	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
@@ -229,6 +240,7 @@
 	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
+	msg->flags = 0; /* not used */
 	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
 }
 
@@ -244,6 +256,7 @@
 
 	msg = (struct cn_msg *)buffer;
 	ev = (struct proc_event *)msg->data;
+	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
 	ktime_get_ts(&ts); /* get high res monotonic timestamp */
 	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
@@ -254,6 +267,7 @@
 	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
+	msg->flags = 0; /* not used */
 	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
 }
 
@@ -269,6 +283,7 @@
 
 	msg = (struct cn_msg *)buffer;
 	ev = (struct proc_event *)msg->data;
+	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	get_seq(&msg->seq, &ev->cpu);
 	ktime_get_ts(&ts); /* get high res monotonic timestamp */
 	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
@@ -281,6 +296,7 @@
 	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
+	msg->flags = 0; /* not used */
 	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
 }
 
@@ -304,6 +320,7 @@
 
 	msg = (struct cn_msg *)buffer;
 	ev = (struct proc_event *)msg->data;
+	memset(&ev->event_data, 0, sizeof(ev->event_data));
 	msg->seq = rcvd_seq;
 	ktime_get_ts(&ts); /* get high res monotonic timestamp */
 	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
@@ -313,6 +330,7 @@
 	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
 	msg->ack = rcvd_ack + 1;
 	msg->len = sizeof(*ev);
+	msg->flags = 0; /* not used */
 	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
 }
 
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index 6ecfa75..a36749f 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -109,7 +109,7 @@
 
 	data = nlmsg_data(nlh);
 
-	memcpy(data, msg, sizeof(*data) + msg->len);
+	memcpy(data, msg, size);
 
 	NETLINK_CB(skb).dst_group = group;
 
@@ -157,17 +157,18 @@
 static void cn_rx_skb(struct sk_buff *__skb)
 {
 	struct nlmsghdr *nlh;
-	int err;
 	struct sk_buff *skb;
+	int len, err;
 
 	skb = skb_get(__skb);
 
 	if (skb->len >= NLMSG_HDRLEN) {
 		nlh = nlmsg_hdr(skb);
+		len = nlmsg_len(nlh);
 
-		if (nlh->nlmsg_len < sizeof(struct cn_msg) ||
+		if (len < (int)sizeof(struct cn_msg) ||
 		    skb->len < nlh->nlmsg_len ||
-		    nlh->nlmsg_len > CONNECTOR_MAX_MSG_SIZE) {
+		    len > CONNECTOR_MAX_MSG_SIZE) {
 			kfree_skb(skb);
 			return;
 		}
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index d2c3253..506fd23 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -986,12 +986,12 @@
 {
 	int ret;
 
+	if (acpi_disabled)
+		return -ENODEV;
+
 	/* don't keep reloading if cpufreq_driver exists */
 	if (cpufreq_get_current_driver())
-		return 0;
-
-	if (acpi_disabled)
-		return 0;
+		return -EEXIST;
 
 	pr_debug("acpi_cpufreq_init\n");
 
diff --git a/drivers/cpufreq/integrator-cpufreq.c b/drivers/cpufreq/integrator-cpufreq.c
index f7c99df..3d79bca 100644
--- a/drivers/cpufreq/integrator-cpufreq.c
+++ b/drivers/cpufreq/integrator-cpufreq.c
@@ -15,18 +15,19 @@
 #include <linux/smp.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
 
-#include <mach/hardware.h>
-#include <mach/platform.h>
 #include <asm/mach-types.h>
 #include <asm/hardware/icst.h>
 
-static struct cpufreq_driver integrator_driver;
+static void __iomem *cm_base;
+/* The cpufreq driver only use the OSC register */
+#define INTEGRATOR_HDR_OSC_OFFSET       0x08
+#define INTEGRATOR_HDR_LOCK_OFFSET      0x14
 
-#define CM_ID  	__io_address(INTEGRATOR_HDR_ID)
-#define CM_OSC	__io_address(INTEGRATOR_HDR_OSC)
-#define CM_STAT __io_address(INTEGRATOR_HDR_STAT)
-#define CM_LOCK __io_address(INTEGRATOR_HDR_LOCK)
+static struct cpufreq_driver integrator_driver;
 
 static const struct icst_params lclk_params = {
 	.ref		= 24000000,
@@ -100,7 +101,7 @@
 	BUG_ON(cpu != smp_processor_id());
 
 	/* get current setting */
-	cm_osc = __raw_readl(CM_OSC);
+	cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET);
 
 	if (machine_is_integrator()) {
 		vco.s = (cm_osc >> 8) & 7;
@@ -128,7 +129,7 @@
 
 	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
 
-	cm_osc = __raw_readl(CM_OSC);
+	cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET);
 
 	if (machine_is_integrator()) {
 		cm_osc &= 0xfffff800;
@@ -138,9 +139,9 @@
 	}
 	cm_osc |= vco.v;
 
-	__raw_writel(0xa05f, CM_LOCK);
-	__raw_writel(cm_osc, CM_OSC);
-	__raw_writel(0, CM_LOCK);
+	__raw_writel(0xa05f, cm_base + INTEGRATOR_HDR_LOCK_OFFSET);
+	__raw_writel(cm_osc, cm_base + INTEGRATOR_HDR_OSC_OFFSET);
+	__raw_writel(0, cm_base + INTEGRATOR_HDR_LOCK_OFFSET);
 
 	/*
 	 * Restore the CPUs allowed mask.
@@ -165,7 +166,7 @@
 	BUG_ON(cpu != smp_processor_id());
 
 	/* detect memory etc. */
-	cm_osc = __raw_readl(CM_OSC);
+	cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET);
 
 	if (machine_is_integrator()) {
 		vco.s = (cm_osc >> 8) & 7;
@@ -202,19 +203,43 @@
 	.name		= "integrator",
 };
 
-static int __init integrator_cpu_init(void)
+static int __init integrator_cpufreq_probe(struct platform_device *pdev)
 {
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+        if (!res)
+		return -ENODEV;
+
+	cm_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!cm_base)
+		return -ENODEV;
+
 	return cpufreq_register_driver(&integrator_driver);
 }
 
-static void __exit integrator_cpu_exit(void)
+static void __exit integrator_cpufreq_remove(struct platform_device *pdev)
 {
 	cpufreq_unregister_driver(&integrator_driver);
 }
 
+static const struct of_device_id integrator_cpufreq_match[] = {
+	{ .compatible = "arm,core-module-integrator"},
+	{ },
+};
+
+static struct platform_driver integrator_cpufreq_driver = {
+	.driver = {
+		.name = "integrator-cpufreq",
+		.owner = THIS_MODULE,
+		.of_match_table = integrator_cpufreq_match,
+	},
+	.remove = __exit_p(integrator_cpufreq_remove),
+};
+
+module_platform_driver_probe(integrator_cpufreq_driver,
+			     integrator_cpufreq_probe);
+
 MODULE_AUTHOR ("Russell M. King");
 MODULE_DESCRIPTION ("cpufreq driver for ARM Integrator CPUs");
 MODULE_LICENSE ("GPL");
-
-module_init(integrator_cpu_init);
-module_exit(integrator_cpu_exit);
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 32b3479..eb3fdc7 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -48,7 +48,7 @@
 }
 
 struct sample {
-	int core_pct_busy;
+	int32_t core_pct_busy;
 	u64 aperf;
 	u64 mperf;
 	int freq;
@@ -68,7 +68,7 @@
 	int32_t i_gain;
 	int32_t d_gain;
 	int deadband;
-	int last_err;
+	int32_t last_err;
 };
 
 struct cpudata {
@@ -153,16 +153,15 @@
 	pid->d_gain = div_fp(int_tofp(percent), int_tofp(100));
 }
 
-static signed int pid_calc(struct _pid *pid, int busy)
+static signed int pid_calc(struct _pid *pid, int32_t busy)
 {
-	signed int err, result;
+	signed int result;
 	int32_t pterm, dterm, fp_error;
 	int32_t integral_limit;
 
-	err = pid->setpoint - busy;
-	fp_error = int_tofp(err);
+	fp_error = int_tofp(pid->setpoint) - busy;
 
-	if (abs(err) <= pid->deadband)
+	if (abs(fp_error) <= int_tofp(pid->deadband))
 		return 0;
 
 	pterm = mul_fp(pid->p_gain, fp_error);
@@ -176,8 +175,8 @@
 	if (pid->integral < -integral_limit)
 		pid->integral = -integral_limit;
 
-	dterm = mul_fp(pid->d_gain, (err - pid->last_err));
-	pid->last_err = err;
+	dterm = mul_fp(pid->d_gain, fp_error - pid->last_err);
+	pid->last_err = fp_error;
 
 	result = pterm + mul_fp(pid->integral, pid->i_gain) + dterm;
 
@@ -367,12 +366,13 @@
 static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
 {
 	int max_perf = cpu->pstate.turbo_pstate;
+	int max_perf_adj;
 	int min_perf;
 	if (limits.no_turbo)
 		max_perf = cpu->pstate.max_pstate;
 
-	max_perf = fp_toint(mul_fp(int_tofp(max_perf), limits.max_perf));
-	*max = clamp_t(int, max_perf,
+	max_perf_adj = fp_toint(mul_fp(int_tofp(max_perf), limits.max_perf));
+	*max = clamp_t(int, max_perf_adj,
 			cpu->pstate.min_pstate, cpu->pstate.turbo_pstate);
 
 	min_perf = fp_toint(mul_fp(int_tofp(max_perf), limits.min_perf));
@@ -383,6 +383,7 @@
 static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
 {
 	int max_perf, min_perf;
+	u64 val;
 
 	intel_pstate_get_min_max(cpu, &min_perf, &max_perf);
 
@@ -394,11 +395,11 @@
 	trace_cpu_frequency(pstate * 100000, cpu->cpu);
 
 	cpu->pstate.current_pstate = pstate;
+	val = pstate << 8;
 	if (limits.no_turbo)
-		wrmsrl(MSR_IA32_PERF_CTL, BIT(32) | (pstate << 8));
-	else
-		wrmsrl(MSR_IA32_PERF_CTL, pstate << 8);
+		val |= (u64)1 << 32;
 
+	wrmsrl(MSR_IA32_PERF_CTL, val);
 }
 
 static inline void intel_pstate_pstate_increase(struct cpudata *cpu, int steps)
@@ -435,8 +436,9 @@
 					struct sample *sample)
 {
 	u64 core_pct;
-	core_pct = div64_u64(sample->aperf * 100, sample->mperf);
-	sample->freq = cpu->pstate.max_pstate * core_pct * 1000;
+	core_pct = div64_u64(int_tofp(sample->aperf * 100),
+			     sample->mperf);
+	sample->freq = fp_toint(cpu->pstate.max_pstate * core_pct * 1000);
 
 	sample->core_pct_busy = core_pct;
 }
@@ -468,22 +470,19 @@
 	mod_timer_pinned(&cpu->timer, jiffies + delay);
 }
 
-static inline int intel_pstate_get_scaled_busy(struct cpudata *cpu)
+static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu)
 {
-	int32_t busy_scaled;
 	int32_t core_busy, max_pstate, current_pstate;
 
-	core_busy = int_tofp(cpu->samples[cpu->sample_ptr].core_pct_busy);
+	core_busy = cpu->samples[cpu->sample_ptr].core_pct_busy;
 	max_pstate = int_tofp(cpu->pstate.max_pstate);
 	current_pstate = int_tofp(cpu->pstate.current_pstate);
-	busy_scaled = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
-
-	return fp_toint(busy_scaled);
+	return mul_fp(core_busy, div_fp(max_pstate, current_pstate));
 }
 
 static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
 {
-	int busy_scaled;
+	int32_t busy_scaled;
 	struct _pid *pid;
 	signed int ctl = 0;
 	int steps;
@@ -637,8 +636,8 @@
 
 static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
 {
-	int rc, min_pstate, max_pstate;
 	struct cpudata *cpu;
+	int rc;
 
 	rc = intel_pstate_init_cpu(policy->cpu);
 	if (rc)
@@ -652,9 +651,8 @@
 	else
 		policy->policy = CPUFREQ_POLICY_POWERSAVE;
 
-	intel_pstate_get_min_max(cpu, &min_pstate, &max_pstate);
-	policy->min = min_pstate * 100000;
-	policy->max = max_pstate * 100000;
+	policy->min = cpu->pstate.min_pstate * 100000;
+	policy->max = cpu->pstate.turbo_pstate * 100000;
 
 	/* cpuinfo and default policy values */
 	policy->cpuinfo.min_freq = cpu->pstate.min_pstate * 100000;
diff --git a/drivers/cpufreq/pasemi-cpufreq.c b/drivers/cpufreq/pasemi-cpufreq.c
index 534e43a..f4ec814 100644
--- a/drivers/cpufreq/pasemi-cpufreq.c
+++ b/drivers/cpufreq/pasemi-cpufreq.c
@@ -28,6 +28,7 @@
 #include <linux/cpufreq.h>
 #include <linux/timer.h>
 #include <linux/module.h>
+#include <linux/of_address.h>
 
 #include <asm/hw_irq.h>
 #include <asm/io.h>
diff --git a/drivers/cpufreq/s3c64xx-cpufreq.c b/drivers/cpufreq/s3c64xx-cpufreq.c
index 8a72b0c..15631f9 100644
--- a/drivers/cpufreq/s3c64xx-cpufreq.c
+++ b/drivers/cpufreq/s3c64xx-cpufreq.c
@@ -166,7 +166,7 @@
 		if (freq->frequency == CPUFREQ_ENTRY_INVALID)
 			continue;
 
-		dvfs = &s3c64xx_dvfs_table[freq->index];
+		dvfs = &s3c64xx_dvfs_table[freq->driver_data];
 		found = 0;
 
 		for (i = 0; i < count; i++) {
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
index 8e36603..d6f57d5 100644
--- a/drivers/cpuidle/Kconfig.arm
+++ b/drivers/cpuidle/Kconfig.arm
@@ -4,7 +4,7 @@
 
 config ARM_HIGHBANK_CPUIDLE
 	bool "CPU Idle Driver for Calxeda processors"
-	depends on ARCH_HIGHBANK
+	depends on ARM_PSCI
 	select ARM_CPU_SUSPEND
 	help
 	  Select this to enable cpuidle on Calxeda processors.
diff --git a/drivers/cpuidle/cpuidle-calxeda.c b/drivers/cpuidle/cpuidle-calxeda.c
index 3460584..3679563 100644
--- a/drivers/cpuidle/cpuidle-calxeda.c
+++ b/drivers/cpuidle/cpuidle-calxeda.c
@@ -21,53 +21,30 @@
  */
 
 #include <linux/cpuidle.h>
+#include <linux/cpu_pm.h>
 #include <linux/init.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/time.h>
-#include <linux/delay.h>
-#include <linux/suspend.h>
+#include <linux/mm.h>
+#include <linux/platform_device.h>
 #include <asm/cpuidle.h>
-#include <asm/proc-fns.h>
-#include <asm/smp_scu.h>
 #include <asm/suspend.h>
-#include <asm/cacheflush.h>
-#include <asm/cp15.h>
-
-extern void highbank_set_cpu_jump(int cpu, void *jump_addr);
-extern void __iomem *scu_base_addr;
-
-static noinline void calxeda_idle_restore(void)
-{
-	set_cr(get_cr() | CR_C);
-	set_auxcr(get_auxcr() | 0x40);
-	scu_power_mode(scu_base_addr, SCU_PM_NORMAL);
-}
+#include <asm/psci.h>
 
 static int calxeda_idle_finish(unsigned long val)
 {
-	/* Already flushed cache, but do it again as the outer cache functions
-	 * dirty the cache with spinlocks */
-	flush_cache_all();
-
-	set_auxcr(get_auxcr() & ~0x40);
-	set_cr(get_cr() & ~CR_C);
-
-	scu_power_mode(scu_base_addr, SCU_PM_DORMANT);
-
-	cpu_do_idle();
-
-	/* Restore things if we didn't enter power-gating */
-	calxeda_idle_restore();
-	return 1;
+	const struct psci_power_state ps = {
+		.type = PSCI_POWER_STATE_TYPE_POWER_DOWN,
+	};
+	return psci_ops.cpu_suspend(ps, __pa(cpu_resume));
 }
 
 static int calxeda_pwrdown_idle(struct cpuidle_device *dev,
 				struct cpuidle_driver *drv,
 				int index)
 {
-	highbank_set_cpu_jump(smp_processor_id(), cpu_resume);
+	cpu_pm_enter();
 	cpu_suspend(0, calxeda_idle_finish);
+	cpu_pm_exit();
+
 	return index;
 }
 
@@ -88,11 +65,17 @@
 	.state_count = 2,
 };
 
-static int __init calxeda_cpuidle_init(void)
+static int __init calxeda_cpuidle_probe(struct platform_device *pdev)
 {
-	if (!of_machine_is_compatible("calxeda,highbank"))
-		return -ENODEV;
-
 	return cpuidle_register(&calxeda_idle_driver, NULL);
 }
-module_init(calxeda_cpuidle_init);
+
+static struct platform_driver calxeda_cpuidle_plat_driver = {
+        .driver = {
+                .name = "cpuidle-calxeda",
+                .owner = THIS_MODULE,
+        },
+        .probe = calxeda_cpuidle_probe,
+};
+
+module_platform_driver(calxeda_cpuidle_plat_driver);
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index f88e3d8..efaf630 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -27,6 +27,9 @@
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 #include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/slab.h>
 #include <asm/dcr.h>
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index b010d42..bc6d820 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -5,6 +5,9 @@
  * Copyright 2008-2012 Freescale Semiconductor, Inc.
  */
 
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
 #include "compat.h"
 #include "regs.h"
 #include "intern.h"
@@ -224,7 +227,7 @@
 	topregs = (struct caam_full __iomem *)ctrl;
 
 	/* Get the IRQ of the controller (for security violations only) */
-	ctrlpriv->secvio_irq = of_irq_to_resource(nprop, 0, NULL);
+	ctrlpriv->secvio_irq = irq_of_parse_and_map(nprop, 0);
 
 	/*
 	 * Enable DECO watchdogs and, if this is a PHYS_ADDR_T_64BIT kernel,
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index 105ba4d..bdb786d 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -5,6 +5,8 @@
  * Copyright 2008-2012 Freescale Semiconductor, Inc.
  */
 
+#include <linux/of_irq.h>
+
 #include "compat.h"
 #include "regs.h"
 #include "jr.h"
@@ -403,7 +405,7 @@
 		dma_set_mask(jrdev, DMA_BIT_MASK(32));
 
 	/* Identify the interrupt */
-	jrpriv->irq = of_irq_to_resource(np, 0, NULL);
+	jrpriv->irq = irq_of_parse_and_map(np, 0);
 
 	/* Now do the platform independent part */
 	error = caam_jr_init(jrdev); /* now turn on hardware */
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 8bdde57..e28104b 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -1818,7 +1818,7 @@
 		goto err;
 	}
 
-	dd->irq = of_irq_to_resource(node, 0, NULL);
+	dd->irq = irq_of_parse_and_map(node, 0);
 	if (!dd->irq) {
 		dev_err(dev, "can't translate OF irq value\n");
 		err = -EINVAL;
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 661dc3e..6cd0e60 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -32,6 +32,8 @@
 #include <linux/interrupt.h>
 #include <linux/crypto.h>
 #include <linux/hw_random.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/dma-mapping.h>
 #include <linux/io.h>
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index f238cfd..c61a6ec 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -154,6 +154,18 @@
 	  This DMA controller transfers data from memory to peripheral fifo
 	  or vice versa. It does not support memory to memory data transfer.
 
+config S3C24XX_DMAC
+	tristate "Samsung S3C24XX DMA support"
+	depends on ARCH_S3C24XX && !S3C24XX_DMA
+	select DMA_ENGINE
+	select DMA_VIRTUAL_CHANNELS
+	help
+	  Support for the Samsung S3C24XX DMA controller driver. The
+	  DMA controller is having multiple DMA channels which can be
+	  configured for different peripherals like audio, UART, SPI.
+	  The DMA controller can transfer data from memory to peripheral,
+	  periphal to memory, periphal to periphal and memory to memory.
+
 source "drivers/dma/sh/Kconfig"
 
 config COH901318
@@ -195,7 +207,7 @@
 
 config TI_EDMA
 	bool "TI EDMA support"
-	depends on ARCH_DAVINCI || ARCH_OMAP
+	depends on ARCH_DAVINCI || ARCH_OMAP || ARCH_KEYSTONE
 	select DMA_ENGINE
 	select DMA_VIRTUAL_CHANNELS
 	select TI_PRIV_EDMA
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index db89035..0ce2da9 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -30,6 +30,7 @@
 obj-$(CONFIG_TI_EDMA) += edma.o
 obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
 obj-$(CONFIG_TEGRA20_APB_DMA) += tegra20-apb-dma.o
+obj-$(CONFIG_S3C24XX_DMAC) += s3c24xx-dma.o
 obj-$(CONFIG_PL330_DMA) += pl330.o
 obj-$(CONFIG_PCH_DMA) += pch_dma.o
 obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o
diff --git a/drivers/dma/bestcomm/sram.c b/drivers/dma/bestcomm/sram.c
index 5e2ed30..2074e0e 100644
--- a/drivers/dma/bestcomm/sram.c
+++ b/drivers/dma/bestcomm/sram.c
@@ -19,6 +19,7 @@
 #include <linux/string.h>
 #include <linux/ioport.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 
 #include <asm/io.h>
 #include <asm/mmu.h>
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index 098a8da..10b577f 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -305,7 +305,9 @@
 				edma_alloc_slot(EDMA_CTLR(echan->ch_num),
 						EDMA_SLOT_ANY);
 			if (echan->slot[i] < 0) {
+				kfree(edesc);
 				dev_err(dev, "Failed to allocate slot\n");
+				kfree(edesc);
 				return NULL;
 			}
 		}
@@ -345,6 +347,7 @@
 			ccnt = sg_dma_len(sg) / (acnt * bcnt);
 			if (ccnt > (SZ_64K - 1)) {
 				dev_err(dev, "Exceeded max SG segment size\n");
+				kfree(edesc);
 				return NULL;
 			}
 			cidx = acnt * bcnt;
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index b3f3e90..61517dd 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -33,6 +33,8 @@
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmapool.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
 #include "dmaengine.h"
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 2fe4353..448750d 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -39,7 +39,9 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
 #include <linux/random.h>
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
index 370ff82..e24b5ef 100644
--- a/drivers/dma/ppc4xx/adma.c
+++ b/drivers/dma/ppc4xx/adma.c
@@ -42,6 +42,8 @@
 #include <linux/uaccess.h>
 #include <linux/proc_fs.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <asm/dcr.h>
 #include <asm/dcr-regs.h>
diff --git a/drivers/dma/s3c24xx-dma.c b/drivers/dma/s3c24xx-dma.c
new file mode 100644
index 0000000..4cb1279
--- /dev/null
+++ b/drivers/dma/s3c24xx-dma.c
@@ -0,0 +1,1350 @@
+/*
+ * S3C24XX DMA handling
+ *
+ * Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
+ *
+ * based on amba-pl08x.c
+ *
+ * Copyright (c) 2006 ARM Ltd.
+ * Copyright (c) 2010 ST-Ericsson SA
+ *
+ * Author: Peter Pearse <peter.pearse@arm.com>
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * The DMA controllers in S3C24XX SoCs have a varying number of DMA signals
+ * that can be routed to any of the 4 to 8 hardware-channels.
+ *
+ * Therefore on these DMA controllers the number of channels
+ * and the number of incoming DMA signals are two totally different things.
+ * It is usually not possible to theoretically handle all physical signals,
+ * so a multiplexing scheme with possible denial of use is necessary.
+ *
+ * Open items:
+ * - bursts
+ */
+
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_data/dma-s3c24xx.h>
+
+#include "dmaengine.h"
+#include "virt-dma.h"
+
+#define MAX_DMA_CHANNELS	8
+
+#define S3C24XX_DISRC			0x00
+#define S3C24XX_DISRCC			0x04
+#define S3C24XX_DISRCC_INC_INCREMENT	0
+#define S3C24XX_DISRCC_INC_FIXED	BIT(0)
+#define S3C24XX_DISRCC_LOC_AHB		0
+#define S3C24XX_DISRCC_LOC_APB		BIT(1)
+
+#define S3C24XX_DIDST			0x08
+#define S3C24XX_DIDSTC			0x0c
+#define S3C24XX_DIDSTC_INC_INCREMENT	0
+#define S3C24XX_DIDSTC_INC_FIXED	BIT(0)
+#define S3C24XX_DIDSTC_LOC_AHB		0
+#define S3C24XX_DIDSTC_LOC_APB		BIT(1)
+#define S3C24XX_DIDSTC_INT_TC0		0
+#define S3C24XX_DIDSTC_INT_RELOAD	BIT(2)
+
+#define S3C24XX_DCON			0x10
+
+#define S3C24XX_DCON_TC_MASK		0xfffff
+#define S3C24XX_DCON_DSZ_BYTE		(0 << 20)
+#define S3C24XX_DCON_DSZ_HALFWORD	(1 << 20)
+#define S3C24XX_DCON_DSZ_WORD		(2 << 20)
+#define S3C24XX_DCON_DSZ_MASK		(3 << 20)
+#define S3C24XX_DCON_DSZ_SHIFT		20
+#define S3C24XX_DCON_AUTORELOAD		0
+#define S3C24XX_DCON_NORELOAD		BIT(22)
+#define S3C24XX_DCON_HWTRIG		BIT(23)
+#define S3C24XX_DCON_HWSRC_SHIFT	24
+#define S3C24XX_DCON_SERV_SINGLE	0
+#define S3C24XX_DCON_SERV_WHOLE		BIT(27)
+#define S3C24XX_DCON_TSZ_UNIT		0
+#define S3C24XX_DCON_TSZ_BURST4		BIT(28)
+#define S3C24XX_DCON_INT		BIT(29)
+#define S3C24XX_DCON_SYNC_PCLK		0
+#define S3C24XX_DCON_SYNC_HCLK		BIT(30)
+#define S3C24XX_DCON_DEMAND		0
+#define S3C24XX_DCON_HANDSHAKE		BIT(31)
+
+#define S3C24XX_DSTAT			0x14
+#define S3C24XX_DSTAT_STAT_BUSY		BIT(20)
+#define S3C24XX_DSTAT_CURRTC_MASK	0xfffff
+
+#define S3C24XX_DMASKTRIG		0x20
+#define S3C24XX_DMASKTRIG_SWTRIG	BIT(0)
+#define S3C24XX_DMASKTRIG_ON		BIT(1)
+#define S3C24XX_DMASKTRIG_STOP		BIT(2)
+
+#define S3C24XX_DMAREQSEL		0x24
+#define S3C24XX_DMAREQSEL_HW		BIT(0)
+
+/*
+ * S3C2410, S3C2440 and S3C2442 SoCs cannot select any physical channel
+ * for a DMA source. Instead only specific channels are valid.
+ * All of these SoCs have 4 physical channels and the number of request
+ * source bits is 3. Additionally we also need 1 bit to mark the channel
+ * as valid.
+ * Therefore we separate the chansel element of the channel data into 4
+ * parts of 4 bits each, to hold the information if the channel is valid
+ * and the hw request source to use.
+ *
+ * Example:
+ * SDI is valid on channels 0, 2 and 3 - with varying hw request sources.
+ * For it the chansel field would look like
+ *
+ * ((BIT(3) | 1) << 3 * 4) | // channel 3, with request source 1
+ * ((BIT(3) | 2) << 2 * 4) | // channel 2, with request source 2
+ * ((BIT(3) | 2) << 0 * 4)   // channel 0, with request source 2
+ */
+#define S3C24XX_CHANSEL_WIDTH		4
+#define S3C24XX_CHANSEL_VALID		BIT(3)
+#define S3C24XX_CHANSEL_REQ_MASK	7
+
+/*
+ * struct soc_data - vendor-specific config parameters for individual SoCs
+ * @stride: spacing between the registers of each channel
+ * @has_reqsel: does the controller use the newer requestselection mechanism
+ * @has_clocks: are controllable dma-clocks present
+ */
+struct soc_data {
+	int stride;
+	bool has_reqsel;
+	bool has_clocks;
+};
+
+/*
+ * enum s3c24xx_dma_chan_state - holds the virtual channel states
+ * @S3C24XX_DMA_CHAN_IDLE: the channel is idle
+ * @S3C24XX_DMA_CHAN_RUNNING: the channel has allocated a physical transport
+ * channel and is running a transfer on it
+ * @S3C24XX_DMA_CHAN_WAITING: the channel is waiting for a physical transport
+ * channel to become available (only pertains to memcpy channels)
+ */
+enum s3c24xx_dma_chan_state {
+	S3C24XX_DMA_CHAN_IDLE,
+	S3C24XX_DMA_CHAN_RUNNING,
+	S3C24XX_DMA_CHAN_WAITING,
+};
+
+/*
+ * struct s3c24xx_sg - structure containing data per sg
+ * @src_addr: src address of sg
+ * @dst_addr: dst address of sg
+ * @len: transfer len in bytes
+ * @node: node for txd's dsg_list
+ */
+struct s3c24xx_sg {
+	dma_addr_t src_addr;
+	dma_addr_t dst_addr;
+	size_t len;
+	struct list_head node;
+};
+
+/*
+ * struct s3c24xx_txd - wrapper for struct dma_async_tx_descriptor
+ * @vd: virtual DMA descriptor
+ * @dsg_list: list of children sg's
+ * @at: sg currently being transfered
+ * @width: transfer width
+ * @disrcc: value for source control register
+ * @didstc: value for destination control register
+ * @dcon: base value for dcon register
+ */
+struct s3c24xx_txd {
+	struct virt_dma_desc vd;
+	struct list_head dsg_list;
+	struct list_head *at;
+	u8 width;
+	u32 disrcc;
+	u32 didstc;
+	u32 dcon;
+};
+
+struct s3c24xx_dma_chan;
+
+/*
+ * struct s3c24xx_dma_phy - holder for the physical channels
+ * @id: physical index to this channel
+ * @valid: does the channel have all required elements
+ * @base: virtual memory base (remapped) for the this channel
+ * @irq: interrupt for this channel
+ * @clk: clock for this channel
+ * @lock: a lock to use when altering an instance of this struct
+ * @serving: virtual channel currently being served by this physicalchannel
+ * @host: a pointer to the host (internal use)
+ */
+struct s3c24xx_dma_phy {
+	unsigned int			id;
+	bool				valid;
+	void __iomem			*base;
+	unsigned int			irq;
+	struct clk			*clk;
+	spinlock_t			lock;
+	struct s3c24xx_dma_chan		*serving;
+	struct s3c24xx_dma_engine	*host;
+};
+
+/*
+ * struct s3c24xx_dma_chan - this structure wraps a DMA ENGINE channel
+ * @id: the id of the channel
+ * @name: name of the channel
+ * @vc: wrappped virtual channel
+ * @phy: the physical channel utilized by this channel, if there is one
+ * @runtime_addr: address for RX/TX according to the runtime config
+ * @at: active transaction on this channel
+ * @lock: a lock for this channel data
+ * @host: a pointer to the host (internal use)
+ * @state: whether the channel is idle, running etc
+ * @slave: whether this channel is a device (slave) or for memcpy
+ */
+struct s3c24xx_dma_chan {
+	int id;
+	const char *name;
+	struct virt_dma_chan vc;
+	struct s3c24xx_dma_phy *phy;
+	struct dma_slave_config cfg;
+	struct s3c24xx_txd *at;
+	struct s3c24xx_dma_engine *host;
+	enum s3c24xx_dma_chan_state state;
+	bool slave;
+};
+
+/*
+ * struct s3c24xx_dma_engine - the local state holder for the S3C24XX
+ * @pdev: the corresponding platform device
+ * @pdata: platform data passed in from the platform/machine
+ * @base: virtual memory base (remapped)
+ * @slave: slave engine for this instance
+ * @memcpy: memcpy engine for this instance
+ * @phy_chans: array of data for the physical channels
+ */
+struct s3c24xx_dma_engine {
+	struct platform_device			*pdev;
+	const struct s3c24xx_dma_platdata	*pdata;
+	struct soc_data				*sdata;
+	void __iomem				*base;
+	struct dma_device			slave;
+	struct dma_device			memcpy;
+	struct s3c24xx_dma_phy			*phy_chans;
+};
+
+/*
+ * Physical channel handling
+ */
+
+/*
+ * Check whether a certain channel is busy or not.
+ */
+static int s3c24xx_dma_phy_busy(struct s3c24xx_dma_phy *phy)
+{
+	unsigned int val = readl(phy->base + S3C24XX_DSTAT);
+	return val & S3C24XX_DSTAT_STAT_BUSY;
+}
+
+static bool s3c24xx_dma_phy_valid(struct s3c24xx_dma_chan *s3cchan,
+				  struct s3c24xx_dma_phy *phy)
+{
+	struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
+	const struct s3c24xx_dma_platdata *pdata = s3cdma->pdata;
+	struct s3c24xx_dma_channel *cdata = &pdata->channels[s3cchan->id];
+	int phyvalid;
+
+	/* every phy is valid for memcopy channels */
+	if (!s3cchan->slave)
+		return true;
+
+	/* On newer variants all phys can be used for all virtual channels */
+	if (s3cdma->sdata->has_reqsel)
+		return true;
+
+	phyvalid = (cdata->chansel >> (phy->id * S3C24XX_CHANSEL_WIDTH));
+	return (phyvalid & S3C24XX_CHANSEL_VALID) ? true : false;
+}
+
+/*
+ * Allocate a physical channel for a virtual channel
+ *
+ * Try to locate a physical channel to be used for this transfer. If all
+ * are taken return NULL and the requester will have to cope by using
+ * some fallback PIO mode or retrying later.
+ */
+static
+struct s3c24xx_dma_phy *s3c24xx_dma_get_phy(struct s3c24xx_dma_chan *s3cchan)
+{
+	struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
+	const struct s3c24xx_dma_platdata *pdata = s3cdma->pdata;
+	struct s3c24xx_dma_channel *cdata;
+	struct s3c24xx_dma_phy *phy = NULL;
+	unsigned long flags;
+	int i;
+	int ret;
+
+	if (s3cchan->slave)
+		cdata = &pdata->channels[s3cchan->id];
+
+	for (i = 0; i < s3cdma->pdata->num_phy_channels; i++) {
+		phy = &s3cdma->phy_chans[i];
+
+		if (!phy->valid)
+			continue;
+
+		if (!s3c24xx_dma_phy_valid(s3cchan, phy))
+			continue;
+
+		spin_lock_irqsave(&phy->lock, flags);
+
+		if (!phy->serving) {
+			phy->serving = s3cchan;
+			spin_unlock_irqrestore(&phy->lock, flags);
+			break;
+		}
+
+		spin_unlock_irqrestore(&phy->lock, flags);
+	}
+
+	/* No physical channel available, cope with it */
+	if (i == s3cdma->pdata->num_phy_channels) {
+		dev_warn(&s3cdma->pdev->dev, "no phy channel available\n");
+		return NULL;
+	}
+
+	/* start the phy clock */
+	if (s3cdma->sdata->has_clocks) {
+		ret = clk_enable(phy->clk);
+		if (ret) {
+			dev_err(&s3cdma->pdev->dev, "could not enable clock for channel %d, err %d\n",
+				phy->id, ret);
+			phy->serving = NULL;
+			return NULL;
+		}
+	}
+
+	return phy;
+}
+
+/*
+ * Mark the physical channel as free.
+ *
+ * This drops the link between the physical and virtual channel.
+ */
+static inline void s3c24xx_dma_put_phy(struct s3c24xx_dma_phy *phy)
+{
+	struct s3c24xx_dma_engine *s3cdma = phy->host;
+
+	if (s3cdma->sdata->has_clocks)
+		clk_disable(phy->clk);
+
+	phy->serving = NULL;
+}
+
+/*
+ * Stops the channel by writing the stop bit.
+ * This should not be used for an on-going transfer, but as a method of
+ * shutting down a channel (eg, when it's no longer used) or terminating a
+ * transfer.
+ */
+static void s3c24xx_dma_terminate_phy(struct s3c24xx_dma_phy *phy)
+{
+	writel(S3C24XX_DMASKTRIG_STOP, phy->base + S3C24XX_DMASKTRIG);
+}
+
+/*
+ * Virtual channel handling
+ */
+
+static inline
+struct s3c24xx_dma_chan *to_s3c24xx_dma_chan(struct dma_chan *chan)
+{
+	return container_of(chan, struct s3c24xx_dma_chan, vc.chan);
+}
+
+static u32 s3c24xx_dma_getbytes_chan(struct s3c24xx_dma_chan *s3cchan)
+{
+	struct s3c24xx_dma_phy *phy = s3cchan->phy;
+	struct s3c24xx_txd *txd = s3cchan->at;
+	u32 tc = readl(phy->base + S3C24XX_DSTAT) & S3C24XX_DSTAT_CURRTC_MASK;
+
+	return tc * txd->width;
+}
+
+static int s3c24xx_dma_set_runtime_config(struct s3c24xx_dma_chan *s3cchan,
+				  struct dma_slave_config *config)
+{
+	if (!s3cchan->slave)
+		return -EINVAL;
+
+	/* Reject definitely invalid configurations */
+	if (config->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES ||
+	    config->dst_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES)
+		return -EINVAL;
+
+	s3cchan->cfg = *config;
+
+	return 0;
+}
+
+/*
+ * Transfer handling
+ */
+
+static inline
+struct s3c24xx_txd *to_s3c24xx_txd(struct dma_async_tx_descriptor *tx)
+{
+	return container_of(tx, struct s3c24xx_txd, vd.tx);
+}
+
+static struct s3c24xx_txd *s3c24xx_dma_get_txd(void)
+{
+	struct s3c24xx_txd *txd = kzalloc(sizeof(*txd), GFP_NOWAIT);
+
+	if (txd) {
+		INIT_LIST_HEAD(&txd->dsg_list);
+		txd->dcon = S3C24XX_DCON_INT | S3C24XX_DCON_NORELOAD;
+	}
+
+	return txd;
+}
+
+static void s3c24xx_dma_free_txd(struct s3c24xx_txd *txd)
+{
+	struct s3c24xx_sg *dsg, *_dsg;
+
+	list_for_each_entry_safe(dsg, _dsg, &txd->dsg_list, node) {
+		list_del(&dsg->node);
+		kfree(dsg);
+	}
+
+	kfree(txd);
+}
+
+static void s3c24xx_dma_start_next_sg(struct s3c24xx_dma_chan *s3cchan,
+				       struct s3c24xx_txd *txd)
+{
+	struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
+	struct s3c24xx_dma_phy *phy = s3cchan->phy;
+	const struct s3c24xx_dma_platdata *pdata = s3cdma->pdata;
+	struct s3c24xx_sg *dsg = list_entry(txd->at, struct s3c24xx_sg, node);
+	u32 dcon = txd->dcon;
+	u32 val;
+
+	/* transfer-size and -count from len and width */
+	switch (txd->width) {
+	case 1:
+		dcon |= S3C24XX_DCON_DSZ_BYTE | dsg->len;
+		break;
+	case 2:
+		dcon |= S3C24XX_DCON_DSZ_HALFWORD | (dsg->len / 2);
+		break;
+	case 4:
+		dcon |= S3C24XX_DCON_DSZ_WORD | (dsg->len / 4);
+		break;
+	}
+
+	if (s3cchan->slave) {
+		struct s3c24xx_dma_channel *cdata =
+					&pdata->channels[s3cchan->id];
+
+		if (s3cdma->sdata->has_reqsel) {
+			writel_relaxed((cdata->chansel << 1) |
+							S3C24XX_DMAREQSEL_HW,
+					phy->base + S3C24XX_DMAREQSEL);
+		} else {
+			int csel = cdata->chansel >> (phy->id *
+							S3C24XX_CHANSEL_WIDTH);
+
+			csel &= S3C24XX_CHANSEL_REQ_MASK;
+			dcon |= csel << S3C24XX_DCON_HWSRC_SHIFT;
+			dcon |= S3C24XX_DCON_HWTRIG;
+		}
+	} else {
+		if (s3cdma->sdata->has_reqsel)
+			writel_relaxed(0, phy->base + S3C24XX_DMAREQSEL);
+	}
+
+	writel_relaxed(dsg->src_addr, phy->base + S3C24XX_DISRC);
+	writel_relaxed(txd->disrcc, phy->base + S3C24XX_DISRCC);
+	writel_relaxed(dsg->dst_addr, phy->base + S3C24XX_DIDST);
+	writel_relaxed(txd->didstc, phy->base + S3C24XX_DIDSTC);
+	writel_relaxed(dcon, phy->base + S3C24XX_DCON);
+
+	val = readl_relaxed(phy->base + S3C24XX_DMASKTRIG);
+	val &= ~S3C24XX_DMASKTRIG_STOP;
+	val |= S3C24XX_DMASKTRIG_ON;
+
+	/* trigger the dma operation for memcpy transfers */
+	if (!s3cchan->slave)
+		val |= S3C24XX_DMASKTRIG_SWTRIG;
+
+	writel(val, phy->base + S3C24XX_DMASKTRIG);
+}
+
+/*
+ * Set the initial DMA register values and start first sg.
+ */
+static void s3c24xx_dma_start_next_txd(struct s3c24xx_dma_chan *s3cchan)
+{
+	struct s3c24xx_dma_phy *phy = s3cchan->phy;
+	struct virt_dma_desc *vd = vchan_next_desc(&s3cchan->vc);
+	struct s3c24xx_txd *txd = to_s3c24xx_txd(&vd->tx);
+
+	list_del(&txd->vd.node);
+
+	s3cchan->at = txd;
+
+	/* Wait for channel inactive */
+	while (s3c24xx_dma_phy_busy(phy))
+		cpu_relax();
+
+	/* point to the first element of the sg list */
+	txd->at = txd->dsg_list.next;
+	s3c24xx_dma_start_next_sg(s3cchan, txd);
+}
+
+static void s3c24xx_dma_free_txd_list(struct s3c24xx_dma_engine *s3cdma,
+				struct s3c24xx_dma_chan *s3cchan)
+{
+	LIST_HEAD(head);
+
+	vchan_get_all_descriptors(&s3cchan->vc, &head);
+	vchan_dma_desc_free_list(&s3cchan->vc, &head);
+}
+
+/*
+ * Try to allocate a physical channel.  When successful, assign it to
+ * this virtual channel, and initiate the next descriptor.  The
+ * virtual channel lock must be held at this point.
+ */
+static void s3c24xx_dma_phy_alloc_and_start(struct s3c24xx_dma_chan *s3cchan)
+{
+	struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
+	struct s3c24xx_dma_phy *phy;
+
+	phy = s3c24xx_dma_get_phy(s3cchan);
+	if (!phy) {
+		dev_dbg(&s3cdma->pdev->dev, "no physical channel available for xfer on %s\n",
+			s3cchan->name);
+		s3cchan->state = S3C24XX_DMA_CHAN_WAITING;
+		return;
+	}
+
+	dev_dbg(&s3cdma->pdev->dev, "allocated physical channel %d for xfer on %s\n",
+		phy->id, s3cchan->name);
+
+	s3cchan->phy = phy;
+	s3cchan->state = S3C24XX_DMA_CHAN_RUNNING;
+
+	s3c24xx_dma_start_next_txd(s3cchan);
+}
+
+static void s3c24xx_dma_phy_reassign_start(struct s3c24xx_dma_phy *phy,
+	struct s3c24xx_dma_chan *s3cchan)
+{
+	struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
+
+	dev_dbg(&s3cdma->pdev->dev, "reassigned physical channel %d for xfer on %s\n",
+		phy->id, s3cchan->name);
+
+	/*
+	 * We do this without taking the lock; we're really only concerned
+	 * about whether this pointer is NULL or not, and we're guaranteed
+	 * that this will only be called when it _already_ is non-NULL.
+	 */
+	phy->serving = s3cchan;
+	s3cchan->phy = phy;
+	s3cchan->state = S3C24XX_DMA_CHAN_RUNNING;
+	s3c24xx_dma_start_next_txd(s3cchan);
+}
+
+/*
+ * Free a physical DMA channel, potentially reallocating it to another
+ * virtual channel if we have any pending.
+ */
+static void s3c24xx_dma_phy_free(struct s3c24xx_dma_chan *s3cchan)
+{
+	struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
+	struct s3c24xx_dma_chan *p, *next;
+
+retry:
+	next = NULL;
+
+	/* Find a waiting virtual channel for the next transfer. */
+	list_for_each_entry(p, &s3cdma->memcpy.channels, vc.chan.device_node)
+		if (p->state == S3C24XX_DMA_CHAN_WAITING) {
+			next = p;
+			break;
+		}
+
+	if (!next) {
+		list_for_each_entry(p, &s3cdma->slave.channels,
+				    vc.chan.device_node)
+			if (p->state == S3C24XX_DMA_CHAN_WAITING &&
+				      s3c24xx_dma_phy_valid(p, s3cchan->phy)) {
+				next = p;
+				break;
+			}
+	}
+
+	/* Ensure that the physical channel is stopped */
+	s3c24xx_dma_terminate_phy(s3cchan->phy);
+
+	if (next) {
+		bool success;
+
+		/*
+		 * Eww.  We know this isn't going to deadlock
+		 * but lockdep probably doesn't.
+		 */
+		spin_lock(&next->vc.lock);
+		/* Re-check the state now that we have the lock */
+		success = next->state == S3C24XX_DMA_CHAN_WAITING;
+		if (success)
+			s3c24xx_dma_phy_reassign_start(s3cchan->phy, next);
+		spin_unlock(&next->vc.lock);
+
+		/* If the state changed, try to find another channel */
+		if (!success)
+			goto retry;
+	} else {
+		/* No more jobs, so free up the physical channel */
+		s3c24xx_dma_put_phy(s3cchan->phy);
+	}
+
+	s3cchan->phy = NULL;
+	s3cchan->state = S3C24XX_DMA_CHAN_IDLE;
+}
+
+static void s3c24xx_dma_unmap_buffers(struct s3c24xx_txd *txd)
+{
+	struct device *dev = txd->vd.tx.chan->device->dev;
+	struct s3c24xx_sg *dsg;
+
+	if (!(txd->vd.tx.flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+		if (txd->vd.tx.flags & DMA_COMPL_SRC_UNMAP_SINGLE)
+			list_for_each_entry(dsg, &txd->dsg_list, node)
+				dma_unmap_single(dev, dsg->src_addr, dsg->len,
+						DMA_TO_DEVICE);
+		else {
+			list_for_each_entry(dsg, &txd->dsg_list, node)
+				dma_unmap_page(dev, dsg->src_addr, dsg->len,
+						DMA_TO_DEVICE);
+		}
+	}
+
+	if (!(txd->vd.tx.flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+		if (txd->vd.tx.flags & DMA_COMPL_DEST_UNMAP_SINGLE)
+			list_for_each_entry(dsg, &txd->dsg_list, node)
+				dma_unmap_single(dev, dsg->dst_addr, dsg->len,
+						DMA_FROM_DEVICE);
+		else
+			list_for_each_entry(dsg, &txd->dsg_list, node)
+				dma_unmap_page(dev, dsg->dst_addr, dsg->len,
+						DMA_FROM_DEVICE);
+	}
+}
+
+static void s3c24xx_dma_desc_free(struct virt_dma_desc *vd)
+{
+	struct s3c24xx_txd *txd = to_s3c24xx_txd(&vd->tx);
+	struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(vd->tx.chan);
+
+	if (!s3cchan->slave)
+		s3c24xx_dma_unmap_buffers(txd);
+
+	s3c24xx_dma_free_txd(txd);
+}
+
+static irqreturn_t s3c24xx_dma_irq(int irq, void *data)
+{
+	struct s3c24xx_dma_phy *phy = data;
+	struct s3c24xx_dma_chan *s3cchan = phy->serving;
+	struct s3c24xx_txd *txd;
+
+	dev_dbg(&phy->host->pdev->dev, "interrupt on channel %d\n", phy->id);
+
+	/*
+	 * Interrupts happen to notify the completion of a transfer and the
+	 * channel should have moved into its stop state already on its own.
+	 * Therefore interrupts on channels not bound to a virtual channel
+	 * should never happen. Nevertheless send a terminate command to the
+	 * channel if the unlikely case happens.
+	 */
+	if (unlikely(!s3cchan)) {
+		dev_err(&phy->host->pdev->dev, "interrupt on unused channel %d\n",
+			phy->id);
+
+		s3c24xx_dma_terminate_phy(phy);
+
+		return IRQ_HANDLED;
+	}
+
+	spin_lock(&s3cchan->vc.lock);
+	txd = s3cchan->at;
+	if (txd) {
+		/* when more sg's are in this txd, start the next one */
+		if (!list_is_last(txd->at, &txd->dsg_list)) {
+			txd->at = txd->at->next;
+			s3c24xx_dma_start_next_sg(s3cchan, txd);
+		} else {
+			s3cchan->at = NULL;
+			vchan_cookie_complete(&txd->vd);
+
+			/*
+			 * And start the next descriptor (if any),
+			 * otherwise free this channel.
+			 */
+			if (vchan_next_desc(&s3cchan->vc))
+				s3c24xx_dma_start_next_txd(s3cchan);
+			else
+				s3c24xx_dma_phy_free(s3cchan);
+		}
+	}
+	spin_unlock(&s3cchan->vc.lock);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * The DMA ENGINE API
+ */
+
+static int s3c24xx_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+			 unsigned long arg)
+{
+	struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(chan);
+	struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&s3cchan->vc.lock, flags);
+
+	switch (cmd) {
+	case DMA_SLAVE_CONFIG:
+		ret = s3c24xx_dma_set_runtime_config(s3cchan,
+					      (struct dma_slave_config *)arg);
+		break;
+	case DMA_TERMINATE_ALL:
+		if (!s3cchan->phy && !s3cchan->at) {
+			dev_err(&s3cdma->pdev->dev, "trying to terminate already stopped channel %d\n",
+				s3cchan->id);
+			ret = -EINVAL;
+			break;
+		}
+
+		s3cchan->state = S3C24XX_DMA_CHAN_IDLE;
+
+		 /* Mark physical channel as free */
+		if (s3cchan->phy)
+			s3c24xx_dma_phy_free(s3cchan);
+
+		/* Dequeue current job */
+		if (s3cchan->at) {
+			s3c24xx_dma_desc_free(&s3cchan->at->vd);
+			s3cchan->at = NULL;
+		}
+
+		/* Dequeue jobs not yet fired as well */
+		s3c24xx_dma_free_txd_list(s3cdma, s3cchan);
+		break;
+	default:
+		/* Unknown command */
+		ret = -ENXIO;
+		break;
+	}
+
+	spin_unlock_irqrestore(&s3cchan->vc.lock, flags);
+
+	return ret;
+}
+
+static int s3c24xx_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+	return 0;
+}
+
+static void s3c24xx_dma_free_chan_resources(struct dma_chan *chan)
+{
+	/* Ensure all queued descriptors are freed */
+	vchan_free_chan_resources(to_virt_chan(chan));
+}
+
+static enum dma_status s3c24xx_dma_tx_status(struct dma_chan *chan,
+		dma_cookie_t cookie, struct dma_tx_state *txstate)
+{
+	struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(chan);
+	struct s3c24xx_txd *txd;
+	struct s3c24xx_sg *dsg;
+	struct virt_dma_desc *vd;
+	unsigned long flags;
+	enum dma_status ret;
+	size_t bytes = 0;
+
+	spin_lock_irqsave(&s3cchan->vc.lock, flags);
+	ret = dma_cookie_status(chan, cookie, txstate);
+	if (ret == DMA_SUCCESS) {
+		spin_unlock_irqrestore(&s3cchan->vc.lock, flags);
+		return ret;
+	}
+
+	/*
+	 * There's no point calculating the residue if there's
+	 * no txstate to store the value.
+	 */
+	if (!txstate) {
+		spin_unlock_irqrestore(&s3cchan->vc.lock, flags);
+		return ret;
+	}
+
+	vd = vchan_find_desc(&s3cchan->vc, cookie);
+	if (vd) {
+		/* On the issued list, so hasn't been processed yet */
+		txd = to_s3c24xx_txd(&vd->tx);
+
+		list_for_each_entry(dsg, &txd->dsg_list, node)
+			bytes += dsg->len;
+	} else {
+		/*
+		 * Currently running, so sum over the pending sg's and
+		 * the currently active one.
+		 */
+		txd = s3cchan->at;
+
+		dsg = list_entry(txd->at, struct s3c24xx_sg, node);
+		list_for_each_entry_from(dsg, &txd->dsg_list, node)
+			bytes += dsg->len;
+
+		bytes += s3c24xx_dma_getbytes_chan(s3cchan);
+	}
+	spin_unlock_irqrestore(&s3cchan->vc.lock, flags);
+
+	/*
+	 * This cookie not complete yet
+	 * Get number of bytes left in the active transactions and queue
+	 */
+	dma_set_residue(txstate, bytes);
+
+	/* Whether waiting or running, we're in progress */
+	return ret;
+}
+
+/*
+ * Initialize a descriptor to be used by memcpy submit
+ */
+static struct dma_async_tx_descriptor *s3c24xx_dma_prep_memcpy(
+		struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+		size_t len, unsigned long flags)
+{
+	struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(chan);
+	struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
+	struct s3c24xx_txd *txd;
+	struct s3c24xx_sg *dsg;
+	int src_mod, dest_mod;
+
+	dev_dbg(&s3cdma->pdev->dev, "prepare memcpy of %d bytes from %s\n",
+			len, s3cchan->name);
+
+	if ((len & S3C24XX_DCON_TC_MASK) != len) {
+		dev_err(&s3cdma->pdev->dev, "memcpy size %d to large\n", len);
+		return NULL;
+	}
+
+	txd = s3c24xx_dma_get_txd();
+	if (!txd)
+		return NULL;
+
+	dsg = kzalloc(sizeof(*dsg), GFP_NOWAIT);
+	if (!dsg) {
+		s3c24xx_dma_free_txd(txd);
+		return NULL;
+	}
+	list_add_tail(&dsg->node, &txd->dsg_list);
+
+	dsg->src_addr = src;
+	dsg->dst_addr = dest;
+	dsg->len = len;
+
+	/*
+	 * Determine a suitable transfer width.
+	 * The DMA controller cannot fetch/store information which is not
+	 * naturally aligned on the bus, i.e., a 4 byte fetch must start at
+	 * an address divisible by 4 - more generally addr % width must be 0.
+	 */
+	src_mod = src % 4;
+	dest_mod = dest % 4;
+	switch (len % 4) {
+	case 0:
+		txd->width = (src_mod == 0 && dest_mod == 0) ? 4 : 1;
+		break;
+	case 2:
+		txd->width = ((src_mod == 2 || src_mod == 0) &&
+			      (dest_mod == 2 || dest_mod == 0)) ? 2 : 1;
+		break;
+	default:
+		txd->width = 1;
+		break;
+	}
+
+	txd->disrcc = S3C24XX_DISRCC_LOC_AHB | S3C24XX_DISRCC_INC_INCREMENT;
+	txd->didstc = S3C24XX_DIDSTC_LOC_AHB | S3C24XX_DIDSTC_INC_INCREMENT;
+	txd->dcon |= S3C24XX_DCON_DEMAND | S3C24XX_DCON_SYNC_HCLK |
+		     S3C24XX_DCON_SERV_WHOLE;
+
+	return vchan_tx_prep(&s3cchan->vc, &txd->vd, flags);
+}
+
+static struct dma_async_tx_descriptor *s3c24xx_dma_prep_slave_sg(
+		struct dma_chan *chan, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_transfer_direction direction,
+		unsigned long flags, void *context)
+{
+	struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(chan);
+	struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
+	const struct s3c24xx_dma_platdata *pdata = s3cdma->pdata;
+	struct s3c24xx_dma_channel *cdata = &pdata->channels[s3cchan->id];
+	struct s3c24xx_txd *txd;
+	struct s3c24xx_sg *dsg;
+	struct scatterlist *sg;
+	dma_addr_t slave_addr;
+	u32 hwcfg = 0;
+	int tmp;
+
+	dev_dbg(&s3cdma->pdev->dev, "prepare transaction of %d bytes from %s\n",
+			sg_dma_len(sgl), s3cchan->name);
+
+	txd = s3c24xx_dma_get_txd();
+	if (!txd)
+		return NULL;
+
+	if (cdata->handshake)
+		txd->dcon |= S3C24XX_DCON_HANDSHAKE;
+
+	switch (cdata->bus) {
+	case S3C24XX_DMA_APB:
+		txd->dcon |= S3C24XX_DCON_SYNC_PCLK;
+		hwcfg |= S3C24XX_DISRCC_LOC_APB;
+		break;
+	case S3C24XX_DMA_AHB:
+		txd->dcon |= S3C24XX_DCON_SYNC_HCLK;
+		hwcfg |= S3C24XX_DISRCC_LOC_AHB;
+		break;
+	}
+
+	/*
+	 * Always assume our peripheral desintation is a fixed
+	 * address in memory.
+	 */
+	hwcfg |= S3C24XX_DISRCC_INC_FIXED;
+
+	/*
+	 * Individual dma operations are requested by the slave,
+	 * so serve only single atomic operations (S3C24XX_DCON_SERV_SINGLE).
+	 */
+	txd->dcon |= S3C24XX_DCON_SERV_SINGLE;
+
+	if (direction == DMA_MEM_TO_DEV) {
+		txd->disrcc = S3C24XX_DISRCC_LOC_AHB |
+			      S3C24XX_DISRCC_INC_INCREMENT;
+		txd->didstc = hwcfg;
+		slave_addr = s3cchan->cfg.dst_addr;
+		txd->width = s3cchan->cfg.dst_addr_width;
+	} else if (direction == DMA_DEV_TO_MEM) {
+		txd->disrcc = hwcfg;
+		txd->didstc = S3C24XX_DIDSTC_LOC_AHB |
+			      S3C24XX_DIDSTC_INC_INCREMENT;
+		slave_addr = s3cchan->cfg.src_addr;
+		txd->width = s3cchan->cfg.src_addr_width;
+	} else {
+		s3c24xx_dma_free_txd(txd);
+		dev_err(&s3cdma->pdev->dev,
+			"direction %d unsupported\n", direction);
+		return NULL;
+	}
+
+	for_each_sg(sgl, sg, sg_len, tmp) {
+		dsg = kzalloc(sizeof(*dsg), GFP_NOWAIT);
+		if (!dsg) {
+			s3c24xx_dma_free_txd(txd);
+			return NULL;
+		}
+		list_add_tail(&dsg->node, &txd->dsg_list);
+
+		dsg->len = sg_dma_len(sg);
+		if (direction == DMA_MEM_TO_DEV) {
+			dsg->src_addr = sg_dma_address(sg);
+			dsg->dst_addr = slave_addr;
+		} else { /* DMA_DEV_TO_MEM */
+			dsg->src_addr = slave_addr;
+			dsg->dst_addr = sg_dma_address(sg);
+		}
+		break;
+	}
+
+	return vchan_tx_prep(&s3cchan->vc, &txd->vd, flags);
+}
+
+/*
+ * Slave transactions callback to the slave device to allow
+ * synchronization of slave DMA signals with the DMAC enable
+ */
+static void s3c24xx_dma_issue_pending(struct dma_chan *chan)
+{
+	struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(chan);
+	unsigned long flags;
+
+	spin_lock_irqsave(&s3cchan->vc.lock, flags);
+	if (vchan_issue_pending(&s3cchan->vc)) {
+		if (!s3cchan->phy && s3cchan->state != S3C24XX_DMA_CHAN_WAITING)
+			s3c24xx_dma_phy_alloc_and_start(s3cchan);
+	}
+	spin_unlock_irqrestore(&s3cchan->vc.lock, flags);
+}
+
+/*
+ * Bringup and teardown
+ */
+
+/*
+ * Initialise the DMAC memcpy/slave channels.
+ * Make a local wrapper to hold required data
+ */
+static int s3c24xx_dma_init_virtual_channels(struct s3c24xx_dma_engine *s3cdma,
+		struct dma_device *dmadev, unsigned int channels, bool slave)
+{
+	struct s3c24xx_dma_chan *chan;
+	int i;
+
+	INIT_LIST_HEAD(&dmadev->channels);
+
+	/*
+	 * Register as many many memcpy as we have physical channels,
+	 * we won't always be able to use all but the code will have
+	 * to cope with that situation.
+	 */
+	for (i = 0; i < channels; i++) {
+		chan = devm_kzalloc(dmadev->dev, sizeof(*chan), GFP_KERNEL);
+		if (!chan) {
+			dev_err(dmadev->dev,
+				"%s no memory for channel\n", __func__);
+			return -ENOMEM;
+		}
+
+		chan->id = i;
+		chan->host = s3cdma;
+		chan->state = S3C24XX_DMA_CHAN_IDLE;
+
+		if (slave) {
+			chan->slave = true;
+			chan->name = kasprintf(GFP_KERNEL, "slave%d", i);
+			if (!chan->name)
+				return -ENOMEM;
+		} else {
+			chan->name = kasprintf(GFP_KERNEL, "memcpy%d", i);
+			if (!chan->name)
+				return -ENOMEM;
+		}
+		dev_dbg(dmadev->dev,
+			 "initialize virtual channel \"%s\"\n",
+			 chan->name);
+
+		chan->vc.desc_free = s3c24xx_dma_desc_free;
+		vchan_init(&chan->vc, dmadev);
+	}
+	dev_info(dmadev->dev, "initialized %d virtual %s channels\n",
+		 i, slave ? "slave" : "memcpy");
+	return i;
+}
+
+static void s3c24xx_dma_free_virtual_channels(struct dma_device *dmadev)
+{
+	struct s3c24xx_dma_chan *chan = NULL;
+	struct s3c24xx_dma_chan *next;
+
+	list_for_each_entry_safe(chan,
+				 next, &dmadev->channels, vc.chan.device_node)
+		list_del(&chan->vc.chan.device_node);
+}
+
+/* s3c2410, s3c2440 and s3c2442 have a 0x40 stride without separate clocks */
+static struct soc_data soc_s3c2410 = {
+	.stride = 0x40,
+	.has_reqsel = false,
+	.has_clocks = false,
+};
+
+/* s3c2412 and s3c2413 have a 0x40 stride and dmareqsel mechanism */
+static struct soc_data soc_s3c2412 = {
+	.stride = 0x40,
+	.has_reqsel = true,
+	.has_clocks = true,
+};
+
+/* s3c2443 and following have a 0x100 stride and dmareqsel mechanism */
+static struct soc_data soc_s3c2443 = {
+	.stride = 0x100,
+	.has_reqsel = true,
+	.has_clocks = true,
+};
+
+static struct platform_device_id s3c24xx_dma_driver_ids[] = {
+	{
+		.name		= "s3c2410-dma",
+		.driver_data	= (kernel_ulong_t)&soc_s3c2410,
+	}, {
+		.name		= "s3c2412-dma",
+		.driver_data	= (kernel_ulong_t)&soc_s3c2412,
+	}, {
+		.name		= "s3c2443-dma",
+		.driver_data	= (kernel_ulong_t)&soc_s3c2443,
+	},
+	{ },
+};
+
+static struct soc_data *s3c24xx_dma_get_soc_data(struct platform_device *pdev)
+{
+	return (struct soc_data *)
+			 platform_get_device_id(pdev)->driver_data;
+}
+
+static int s3c24xx_dma_probe(struct platform_device *pdev)
+{
+	const struct s3c24xx_dma_platdata *pdata = dev_get_platdata(&pdev->dev);
+	struct s3c24xx_dma_engine *s3cdma;
+	struct soc_data *sdata;
+	struct resource *res;
+	int ret;
+	int i;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "platform data missing\n");
+		return -ENODEV;
+	}
+
+	/* Basic sanity check */
+	if (pdata->num_phy_channels > MAX_DMA_CHANNELS) {
+		dev_err(&pdev->dev, "to many dma channels %d, max %d\n",
+			pdata->num_phy_channels, MAX_DMA_CHANNELS);
+		return -EINVAL;
+	}
+
+	sdata = s3c24xx_dma_get_soc_data(pdev);
+	if (!sdata)
+		return -EINVAL;
+
+	s3cdma = devm_kzalloc(&pdev->dev, sizeof(*s3cdma), GFP_KERNEL);
+	if (!s3cdma)
+		return -ENOMEM;
+
+	s3cdma->pdev = pdev;
+	s3cdma->pdata = pdata;
+	s3cdma->sdata = sdata;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	s3cdma->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(s3cdma->base))
+		return PTR_ERR(s3cdma->base);
+
+	s3cdma->phy_chans = devm_kzalloc(&pdev->dev,
+					      sizeof(struct s3c24xx_dma_phy) *
+							pdata->num_phy_channels,
+					      GFP_KERNEL);
+	if (!s3cdma->phy_chans)
+		return -ENOMEM;
+
+	/* aquire irqs and clocks for all physical channels */
+	for (i = 0; i < pdata->num_phy_channels; i++) {
+		struct s3c24xx_dma_phy *phy = &s3cdma->phy_chans[i];
+		char clk_name[6];
+
+		phy->id = i;
+		phy->base = s3cdma->base + (i * sdata->stride);
+		phy->host = s3cdma;
+
+		phy->irq = platform_get_irq(pdev, i);
+		if (phy->irq < 0) {
+			dev_err(&pdev->dev, "failed to get irq %d, err %d\n",
+				i, phy->irq);
+			continue;
+		}
+
+		ret = devm_request_irq(&pdev->dev, phy->irq, s3c24xx_dma_irq,
+				       0, pdev->name, phy);
+		if (ret) {
+			dev_err(&pdev->dev, "Unable to request irq for channel %d, error %d\n",
+				i, ret);
+			continue;
+		}
+
+		if (sdata->has_clocks) {
+			sprintf(clk_name, "dma.%d", i);
+			phy->clk = devm_clk_get(&pdev->dev, clk_name);
+			if (IS_ERR(phy->clk) && sdata->has_clocks) {
+				dev_err(&pdev->dev, "unable to aquire clock for channel %d, error %lu",
+					i, PTR_ERR(phy->clk));
+				continue;
+			}
+
+			ret = clk_prepare(phy->clk);
+			if (ret) {
+				dev_err(&pdev->dev, "clock for phy %d failed, error %d\n",
+					i, ret);
+				continue;
+			}
+		}
+
+		spin_lock_init(&phy->lock);
+		phy->valid = true;
+
+		dev_dbg(&pdev->dev, "physical channel %d is %s\n",
+			i, s3c24xx_dma_phy_busy(phy) ? "BUSY" : "FREE");
+	}
+
+	/* Initialize memcpy engine */
+	dma_cap_set(DMA_MEMCPY, s3cdma->memcpy.cap_mask);
+	dma_cap_set(DMA_PRIVATE, s3cdma->memcpy.cap_mask);
+	s3cdma->memcpy.dev = &pdev->dev;
+	s3cdma->memcpy.device_alloc_chan_resources =
+					s3c24xx_dma_alloc_chan_resources;
+	s3cdma->memcpy.device_free_chan_resources =
+					s3c24xx_dma_free_chan_resources;
+	s3cdma->memcpy.device_prep_dma_memcpy = s3c24xx_dma_prep_memcpy;
+	s3cdma->memcpy.device_tx_status = s3c24xx_dma_tx_status;
+	s3cdma->memcpy.device_issue_pending = s3c24xx_dma_issue_pending;
+	s3cdma->memcpy.device_control = s3c24xx_dma_control;
+
+	/* Initialize slave engine for SoC internal dedicated peripherals */
+	dma_cap_set(DMA_SLAVE, s3cdma->slave.cap_mask);
+	dma_cap_set(DMA_PRIVATE, s3cdma->slave.cap_mask);
+	s3cdma->slave.dev = &pdev->dev;
+	s3cdma->slave.device_alloc_chan_resources =
+					s3c24xx_dma_alloc_chan_resources;
+	s3cdma->slave.device_free_chan_resources =
+					s3c24xx_dma_free_chan_resources;
+	s3cdma->slave.device_tx_status = s3c24xx_dma_tx_status;
+	s3cdma->slave.device_issue_pending = s3c24xx_dma_issue_pending;
+	s3cdma->slave.device_prep_slave_sg = s3c24xx_dma_prep_slave_sg;
+	s3cdma->slave.device_control = s3c24xx_dma_control;
+
+	/* Register as many memcpy channels as there are physical channels */
+	ret = s3c24xx_dma_init_virtual_channels(s3cdma, &s3cdma->memcpy,
+						pdata->num_phy_channels, false);
+	if (ret <= 0) {
+		dev_warn(&pdev->dev,
+			 "%s failed to enumerate memcpy channels - %d\n",
+			 __func__, ret);
+		goto err_memcpy;
+	}
+
+	/* Register slave channels */
+	ret = s3c24xx_dma_init_virtual_channels(s3cdma, &s3cdma->slave,
+				pdata->num_channels, true);
+	if (ret <= 0) {
+		dev_warn(&pdev->dev,
+			"%s failed to enumerate slave channels - %d\n",
+				__func__, ret);
+		goto err_slave;
+	}
+
+	ret = dma_async_device_register(&s3cdma->memcpy);
+	if (ret) {
+		dev_warn(&pdev->dev,
+			"%s failed to register memcpy as an async device - %d\n",
+			__func__, ret);
+		goto err_memcpy_reg;
+	}
+
+	ret = dma_async_device_register(&s3cdma->slave);
+	if (ret) {
+		dev_warn(&pdev->dev,
+			"%s failed to register slave as an async device - %d\n",
+			__func__, ret);
+		goto err_slave_reg;
+	}
+
+	platform_set_drvdata(pdev, s3cdma);
+	dev_info(&pdev->dev, "Loaded dma driver with %d physical channels\n",
+		 pdata->num_phy_channels);
+
+	return 0;
+
+err_slave_reg:
+	dma_async_device_unregister(&s3cdma->memcpy);
+err_memcpy_reg:
+	s3c24xx_dma_free_virtual_channels(&s3cdma->slave);
+err_slave:
+	s3c24xx_dma_free_virtual_channels(&s3cdma->memcpy);
+err_memcpy:
+	if (sdata->has_clocks)
+		for (i = 0; i < pdata->num_phy_channels; i++) {
+			struct s3c24xx_dma_phy *phy = &s3cdma->phy_chans[i];
+			if (phy->valid)
+				clk_unprepare(phy->clk);
+		}
+
+	return ret;
+}
+
+static int s3c24xx_dma_remove(struct platform_device *pdev)
+{
+	const struct s3c24xx_dma_platdata *pdata = dev_get_platdata(&pdev->dev);
+	struct s3c24xx_dma_engine *s3cdma = platform_get_drvdata(pdev);
+	struct soc_data *sdata = s3c24xx_dma_get_soc_data(pdev);
+	int i;
+
+	dma_async_device_unregister(&s3cdma->slave);
+	dma_async_device_unregister(&s3cdma->memcpy);
+
+	s3c24xx_dma_free_virtual_channels(&s3cdma->slave);
+	s3c24xx_dma_free_virtual_channels(&s3cdma->memcpy);
+
+	if (sdata->has_clocks)
+		for (i = 0; i < pdata->num_phy_channels; i++) {
+			struct s3c24xx_dma_phy *phy = &s3cdma->phy_chans[i];
+			if (phy->valid)
+				clk_unprepare(phy->clk);
+		}
+
+	return 0;
+}
+
+static struct platform_driver s3c24xx_dma_driver = {
+	.driver		= {
+		.name	= "s3c24xx-dma",
+		.owner	= THIS_MODULE,
+	},
+	.id_table	= s3c24xx_dma_driver_ids,
+	.probe		= s3c24xx_dma_probe,
+	.remove		= s3c24xx_dma_remove,
+};
+
+module_platform_driver(s3c24xx_dma_driver);
+
+bool s3c24xx_dma_filter(struct dma_chan *chan, void *param)
+{
+	struct s3c24xx_dma_chan *s3cchan;
+
+	if (chan->device->dev->driver != &s3c24xx_dma_driver.driver)
+		return false;
+
+	s3cchan = to_s3c24xx_dma_chan(chan);
+
+	return s3cchan->id == (int)param;
+}
+EXPORT_SYMBOL(s3c24xx_dma_filter);
+
+MODULE_DESCRIPTION("S3C24XX DMA Driver");
+MODULE_AUTHOR("Heiko Stuebner");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/sh/rcar-hpbdma.c b/drivers/dma/sh/rcar-hpbdma.c
index 45a5202..ebad845 100644
--- a/drivers/dma/sh/rcar-hpbdma.c
+++ b/drivers/dma/sh/rcar-hpbdma.c
@@ -93,6 +93,7 @@
 	void __iomem *base;
 	const struct hpb_dmae_slave_config *cfg;
 	char dev_id[16];		/* unique name per DMAC of channel */
+	dma_addr_t slave_addr;
 };
 
 struct hpb_dmae_device {
@@ -432,7 +433,6 @@
 		hpb_chan->xfer_mode = XFER_DOUBLE;
 	} else {
 		dev_err(hpb_chan->shdma_chan.dev, "DCR setting error");
-		shdma_free_irq(&hpb_chan->shdma_chan);
 		return -EINVAL;
 	}
 
@@ -446,7 +446,8 @@
 	return 0;
 }
 
-static int hpb_dmae_set_slave(struct shdma_chan *schan, int slave_id, bool try)
+static int hpb_dmae_set_slave(struct shdma_chan *schan, int slave_id,
+			      dma_addr_t slave_addr, bool try)
 {
 	struct hpb_dmae_chan *chan = to_chan(schan);
 	const struct hpb_dmae_slave_config *sc =
@@ -457,6 +458,7 @@
 	if (try)
 		return 0;
 	chan->cfg = sc;
+	chan->slave_addr = slave_addr ? : sc->addr;
 	return hpb_dmae_alloc_chan_resources(chan, sc);
 }
 
@@ -468,7 +470,7 @@
 {
 	struct hpb_dmae_chan *chan = to_chan(schan);
 
-	return chan->cfg->addr;
+	return chan->slave_addr;
 }
 
 static struct shdma_desc *hpb_dmae_embedded_desc(void *buf, int i)
@@ -614,7 +616,6 @@
 	shdma_for_each_chan(schan, &hpbdev->shdma_dev, i) {
 		BUG_ON(!schan);
 
-		shdma_free_irq(schan);
 		shdma_chan_remove(schan);
 	}
 	dma_dev->chancnt = 0;
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 3c9e4e9..b53d0de 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -339,8 +339,8 @@
 	if (pvt->fam == 0xf && pvt->ext_model < K8_REV_F) {
 		csbase		= pvt->csels[dct].csbases[csrow];
 		csmask		= pvt->csels[dct].csmasks[csrow];
-		base_bits	= GENMASK(21, 31) | GENMASK(9, 15);
-		mask_bits	= GENMASK(21, 29) | GENMASK(9, 15);
+		base_bits	= GENMASK_ULL(31, 21) | GENMASK_ULL(15, 9);
+		mask_bits	= GENMASK_ULL(29, 21) | GENMASK_ULL(15, 9);
 		addr_shift	= 4;
 
 	/*
@@ -352,16 +352,16 @@
 		csbase          = pvt->csels[dct].csbases[csrow];
 		csmask          = pvt->csels[dct].csmasks[csrow >> 1];
 
-		*base  = (csbase & GENMASK(5,  15)) << 6;
-		*base |= (csbase & GENMASK(19, 30)) << 8;
+		*base  = (csbase & GENMASK_ULL(15,  5)) << 6;
+		*base |= (csbase & GENMASK_ULL(30, 19)) << 8;
 
 		*mask = ~0ULL;
 		/* poke holes for the csmask */
-		*mask &= ~((GENMASK(5, 15)  << 6) |
-			   (GENMASK(19, 30) << 8));
+		*mask &= ~((GENMASK_ULL(15, 5)  << 6) |
+			   (GENMASK_ULL(30, 19) << 8));
 
-		*mask |= (csmask & GENMASK(5, 15))  << 6;
-		*mask |= (csmask & GENMASK(19, 30)) << 8;
+		*mask |= (csmask & GENMASK_ULL(15, 5))  << 6;
+		*mask |= (csmask & GENMASK_ULL(30, 19)) << 8;
 
 		return;
 	} else {
@@ -370,9 +370,11 @@
 		addr_shift	= 8;
 
 		if (pvt->fam == 0x15)
-			base_bits = mask_bits = GENMASK(19,30) | GENMASK(5,13);
+			base_bits = mask_bits =
+				GENMASK_ULL(30,19) | GENMASK_ULL(13,5);
 		else
-			base_bits = mask_bits = GENMASK(19,28) | GENMASK(5,13);
+			base_bits = mask_bits =
+				GENMASK_ULL(28,19) | GENMASK_ULL(13,5);
 	}
 
 	*base  = (csbase & base_bits) << addr_shift;
@@ -561,7 +563,7 @@
 	 * section 3.4.2 of AMD publication 24592: AMD x86-64 Architecture
 	 * Programmer's Manual Volume 1 Application Programming.
 	 */
-	dram_addr = (sys_addr & GENMASK(0, 39)) - dram_base;
+	dram_addr = (sys_addr & GENMASK_ULL(39, 0)) - dram_base;
 
 	edac_dbg(2, "using DRAM Base register to translate SysAddr 0x%lx to DramAddr 0x%lx\n",
 		 (unsigned long)sys_addr, (unsigned long)dram_addr);
@@ -597,7 +599,7 @@
 	 * concerning translating a DramAddr to an InputAddr.
 	 */
 	intlv_shift = num_node_interleave_bits(dram_intlv_en(pvt, 0));
-	input_addr = ((dram_addr >> intlv_shift) & GENMASK(12, 35)) +
+	input_addr = ((dram_addr >> intlv_shift) & GENMASK_ULL(35, 12)) +
 		      (dram_addr & 0xfff);
 
 	edac_dbg(2, "  Intlv Shift=%d DramAddr=0x%lx maps to InputAddr=0x%lx\n",
@@ -849,7 +851,7 @@
 		end_bit   = 39;
 	}
 
-	addr = m->addr & GENMASK(start_bit, end_bit);
+	addr = m->addr & GENMASK_ULL(end_bit, start_bit);
 
 	/*
 	 * Erratum 637 workaround
@@ -861,7 +863,7 @@
 		u16 mce_nid;
 		u8 intlv_en;
 
-		if ((addr & GENMASK(24, 47)) >> 24 != 0x00fdf7)
+		if ((addr & GENMASK_ULL(47, 24)) >> 24 != 0x00fdf7)
 			return addr;
 
 		mce_nid	= amd_get_nb_id(m->extcpu);
@@ -871,7 +873,7 @@
 		intlv_en = tmp >> 21 & 0x7;
 
 		/* add [47:27] + 3 trailing bits */
-		cc6_base  = (tmp & GENMASK(0, 20)) << 3;
+		cc6_base  = (tmp & GENMASK_ULL(20, 0)) << 3;
 
 		/* reverse and add DramIntlvEn */
 		cc6_base |= intlv_en ^ 0x7;
@@ -880,18 +882,18 @@
 		cc6_base <<= 24;
 
 		if (!intlv_en)
-			return cc6_base | (addr & GENMASK(0, 23));
+			return cc6_base | (addr & GENMASK_ULL(23, 0));
 
 		amd64_read_pci_cfg(pvt->F1, DRAM_LOCAL_NODE_BASE, &tmp);
 
 							/* faster log2 */
-		tmp_addr  = (addr & GENMASK(12, 23)) << __fls(intlv_en + 1);
+		tmp_addr  = (addr & GENMASK_ULL(23, 12)) << __fls(intlv_en + 1);
 
 		/* OR DramIntlvSel into bits [14:12] */
-		tmp_addr |= (tmp & GENMASK(21, 23)) >> 9;
+		tmp_addr |= (tmp & GENMASK_ULL(23, 21)) >> 9;
 
 		/* add remaining [11:0] bits from original MC4_ADDR */
-		tmp_addr |= addr & GENMASK(0, 11);
+		tmp_addr |= addr & GENMASK_ULL(11, 0);
 
 		return cc6_base | tmp_addr;
 	}
@@ -952,12 +954,12 @@
 
 	amd64_read_pci_cfg(f1, DRAM_LOCAL_NODE_LIM, &llim);
 
-	pvt->ranges[range].lim.lo &= GENMASK(0, 15);
+	pvt->ranges[range].lim.lo &= GENMASK_ULL(15, 0);
 
 				    /* {[39:27],111b} */
 	pvt->ranges[range].lim.lo |= ((llim & 0x1fff) << 3 | 0x7) << 16;
 
-	pvt->ranges[range].lim.hi &= GENMASK(0, 7);
+	pvt->ranges[range].lim.hi &= GENMASK_ULL(7, 0);
 
 				    /* [47:40] */
 	pvt->ranges[range].lim.hi |= llim >> 13;
@@ -1330,7 +1332,7 @@
 			chan_off = dram_base;
 	}
 
-	return (sys_addr & GENMASK(6,47)) - (chan_off & GENMASK(23,47));
+	return (sys_addr & GENMASK_ULL(47,6)) - (chan_off & GENMASK_ULL(47,23));
 }
 
 /*
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index d2443cf..6dc1fcc 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -160,14 +160,6 @@
 #define OFF false
 
 /*
- * Create a contiguous bitmask starting at bit position @lo and ending at
- * position @hi. For example
- *
- * GENMASK(21, 39) gives us the 64bit vector 0x000000ffffe00000.
- */
-#define GENMASK(lo, hi)			(((1ULL << ((hi) - (lo) + 1)) - 1) << (lo))
-
-/*
  * PCI-defined configuration space registers
  */
 #define PCI_DEVICE_ID_AMD_15H_M30H_NB_F1 0x141b
diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c
index c2eaf33..9ee1c76 100644
--- a/drivers/edac/cell_edac.c
+++ b/drivers/edac/cell_edac.c
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/stop_machine.h>
 #include <linux/io.h>
+#include <linux/of_address.h>
 #include <asm/machdep.h>
 #include <asm/cell-regs.h>
 
diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c
index bb53467..d5a98a4 100644
--- a/drivers/edac/ghes_edac.c
+++ b/drivers/edac/ghes_edac.c
@@ -297,15 +297,14 @@
 	}
 
 	/* Error address */
-	if (mem_err->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS) {
+	if (mem_err->validation_bits & CPER_MEM_VALID_PA) {
 		e->page_frame_number = mem_err->physical_addr >> PAGE_SHIFT;
 		e->offset_in_page = mem_err->physical_addr & ~PAGE_MASK;
 	}
 
 	/* Error grain */
-	if (mem_err->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS_MASK) {
+	if (mem_err->validation_bits & CPER_MEM_VALID_PA_MASK)
 		e->grain = ~(mem_err->physical_addr_mask & ~PAGE_MASK);
-	}
 
 	/* Memory error location, mapped on e->location */
 	p = e->location;
@@ -315,6 +314,8 @@
 		p += sprintf(p, "card:%d ", mem_err->card);
 	if (mem_err->validation_bits & CPER_MEM_VALID_MODULE)
 		p += sprintf(p, "module:%d ", mem_err->module);
+	if (mem_err->validation_bits & CPER_MEM_VALID_RANK_NUMBER)
+		p += sprintf(p, "rank:%d ", mem_err->rank);
 	if (mem_err->validation_bits & CPER_MEM_VALID_BANK)
 		p += sprintf(p, "bank:%d ", mem_err->bank);
 	if (mem_err->validation_bits & CPER_MEM_VALID_ROW)
@@ -323,6 +324,15 @@
 		p += sprintf(p, "col:%d ", mem_err->column);
 	if (mem_err->validation_bits & CPER_MEM_VALID_BIT_POSITION)
 		p += sprintf(p, "bit_pos:%d ", mem_err->bit_pos);
+	if (mem_err->validation_bits & CPER_MEM_VALID_MODULE_HANDLE) {
+		const char *bank = NULL, *device = NULL;
+		dmi_memdev_name(mem_err->mem_dev_handle, &bank, &device);
+		if (bank != NULL && device != NULL)
+			p += sprintf(p, "DIMM location:%s %s ", bank, device);
+		else
+			p += sprintf(p, "DIMM DMI handle: 0x%.4x ",
+				     mem_err->mem_dev_handle);
+	}
 	if (p > e->location)
 		*(p - 1) = '\0';
 
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index e04462b..88f60c5 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -50,7 +50,7 @@
  * Get a bit field at register value <v>, from bit <lo> to bit <hi>
  */
 #define GET_BITFIELD(v, lo, hi)	\
-	(((v) & ((1ULL << ((hi) - (lo) + 1)) - 1) << (lo)) >> (lo))
+	(((v) & GENMASK_ULL(hi, lo)) >> (lo))
 
 /*
  * sbridge Memory Controller Registers
diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c
index 5985807..e23f1c2 100644
--- a/drivers/extcon/extcon-adc-jack.c
+++ b/drivers/extcon/extcon-adc-jack.c
@@ -27,16 +27,16 @@
 
 /**
  * struct adc_jack_data - internal data for adc_jack device driver
- * @edev        - extcon device.
- * @cable_names - list of supported cables.
- * @num_cables  - size of cable_names.
- * @adc_conditions       - list of adc value conditions.
- * @num_conditions       - size of adc_conditions.
- * @irq         - irq number of attach/detach event (0 if not exist).
- * @handling_delay      - interrupt handler will schedule extcon event
- *                      handling at handling_delay jiffies.
- * @handler     - extcon event handler called by interrupt handler.
- * @chan       - iio channel being queried.
+ * @edev:		extcon device.
+ * @cable_names:	list of supported cables.
+ * @num_cables:		size of cable_names.
+ * @adc_conditions:	list of adc value conditions.
+ * @num_conditions:	size of adc_conditions.
+ * @irq:		irq number of attach/detach event (0 if not exist).
+ * @handling_delay:	interrupt handler will schedule extcon event
+ *			handling at handling_delay jiffies.
+ * @handler:		extcon event handler called by interrupt handler.
+ * @chan:		iio channel being queried.
  */
 struct adc_jack_data {
 	struct extcon_dev edev;
@@ -64,7 +64,7 @@
 
 	ret = iio_read_channel_raw(data->chan, &adc_val);
 	if (ret < 0) {
-		dev_err(data->edev.dev, "read channel() error: %d\n", ret);
+		dev_err(&data->edev.dev, "read channel() error: %d\n", ret);
 		return;
 	}
 
@@ -95,7 +95,7 @@
 static int adc_jack_probe(struct platform_device *pdev)
 {
 	struct adc_jack_data *data;
-	struct adc_jack_pdata *pdata = pdev->dev.platform_data;
+	struct adc_jack_pdata *pdata = dev_get_platdata(&pdev->dev);
 	int i, err = 0;
 
 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
@@ -110,6 +110,7 @@
 		goto out;
 	}
 
+	data->edev.dev.parent = &pdev->dev;
 	data->edev.supported_cable = pdata->cable_names;
 
 	/* Check the length of array and set num_cables */
@@ -148,7 +149,7 @@
 
 	platform_set_drvdata(pdev, data);
 
-	err = extcon_dev_register(&data->edev, &pdev->dev);
+	err = extcon_dev_register(&data->edev);
 	if (err)
 		goto out;
 
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index e557130..3c55ec8 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -86,8 +86,8 @@
 };
 
 static const struct arizona_micd_config micd_default_modes[] = {
-	{ ARIZONA_ACCDET_SRC, 1 << ARIZONA_MICD_BIAS_SRC_SHIFT, 0 },
-	{ 0,                  2 << ARIZONA_MICD_BIAS_SRC_SHIFT, 1 },
+	{ ARIZONA_ACCDET_SRC, 1, 0 },
+	{ 0,                  2, 1 },
 };
 
 static const struct arizona_micd_range micd_default_ranges[] = {
@@ -182,7 +182,8 @@
 					info->micd_modes[mode].gpio);
 	regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
 			   ARIZONA_MICD_BIAS_SRC_MASK,
-			   info->micd_modes[mode].bias);
+			   info->micd_modes[mode].bias <<
+			   ARIZONA_MICD_BIAS_SRC_SHIFT);
 	regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
 			   ARIZONA_ACCDET_SRC, info->micd_modes[mode].src);
 
@@ -193,7 +194,7 @@
 
 static const char *arizona_extcon_get_micbias(struct arizona_extcon_info *info)
 {
-	switch (info->micd_modes[0].bias >> ARIZONA_MICD_BIAS_SRC_SHIFT) {
+	switch (info->micd_modes[0].bias) {
 	case 1:
 		return "MICBIAS1";
 	case 2:
@@ -388,7 +389,7 @@
 			   >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
 
 		if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 &&
-		    (val < 100 || val > 0x3fb)) {
+		    (val < 100 || val >= 0x3fb)) {
 			range++;
 			dev_dbg(arizona->dev, "Moving to HPDET range %d\n",
 				range);
@@ -401,7 +402,7 @@
 		}
 
 		/* If we go out of range report top of range */
-		if (val < 100 || val > 0x3fb) {
+		if (val < 100 || val >= 0x3fb) {
 			dev_dbg(arizona->dev, "Measurement out of range\n");
 			return ARIZONA_HPDET_MAX;
 		}
@@ -514,7 +515,7 @@
 		}
 
 		/*
-		 * If we measure the mic as 
+		 * If we measure the mic as high impedance
 		 */
 		if (!id_gpio || info->hpdet_res[1] > 50) {
 			dev_dbg(arizona->dev, "Detected mic\n");
@@ -564,11 +565,10 @@
 	}
 
 	ret = arizona_hpdet_read(info);
-	if (ret == -EAGAIN) {
+	if (ret == -EAGAIN)
 		goto out;
-	} else if (ret < 0) {
+	else if (ret < 0)
 		goto done;
-	}
 	reading = ret;
 
 	/* Reset back to starting range */
@@ -578,11 +578,10 @@
 			   0);
 
 	ret = arizona_hpdet_do_id(info, &reading, &mic);
-	if (ret == -EAGAIN) {
+	if (ret == -EAGAIN)
 		goto out;
-	} else if (ret < 0) {
+	else if (ret < 0)
 		goto done;
-	}
 
 	/* Report high impedence cables as line outputs */
 	if (reading >= 5000)
@@ -738,8 +737,8 @@
 static void arizona_micd_timeout_work(struct work_struct *work)
 {
 	struct arizona_extcon_info *info = container_of(work,
-							struct arizona_extcon_info,
-							micd_timeout_work.work);
+						struct arizona_extcon_info,
+						micd_timeout_work.work);
 
 	mutex_lock(&info->lock);
 
@@ -756,8 +755,8 @@
 static void arizona_micd_detect(struct work_struct *work)
 {
 	struct arizona_extcon_info *info = container_of(work,
-							struct arizona_extcon_info,
-							micd_detect_work.work);
+						struct arizona_extcon_info,
+						micd_detect_work.work);
 	struct arizona *arizona = info->arizona;
 	unsigned int val = 0, lvl;
 	int ret, i, key;
@@ -769,7 +768,8 @@
 	for (i = 0; i < 10 && !(val & 0x7fc); i++) {
 		ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
 		if (ret != 0) {
-			dev_err(arizona->dev, "Failed to read MICDET: %d\n", ret);
+			dev_err(arizona->dev,
+				"Failed to read MICDET: %d\n", ret);
 			mutex_unlock(&info->lock);
 			return;
 		}
@@ -777,7 +777,8 @@
 		dev_dbg(arizona->dev, "MICDET: %x\n", val);
 
 		if (!(val & ARIZONA_MICD_VALID)) {
-			dev_warn(arizona->dev, "Microphone detection state invalid\n");
+			dev_warn(arizona->dev,
+				 "Microphone detection state invalid\n");
 			mutex_unlock(&info->lock);
 			return;
 		}
@@ -925,8 +926,8 @@
 static void arizona_hpdet_work(struct work_struct *work)
 {
 	struct arizona_extcon_info *info = container_of(work,
-							struct arizona_extcon_info,
-							hpdet_work.work);
+						struct arizona_extcon_info,
+						hpdet_work.work);
 
 	mutex_lock(&info->lock);
 	arizona_start_hpdet_acc_id(info);
@@ -973,10 +974,13 @@
 					   &info->hpdet_work,
 					   msecs_to_jiffies(HPDET_DEBOUNCE));
 
-		if (cancelled_mic)
+		if (cancelled_mic) {
+			int micd_timeout = info->micd_timeout;
+
 			queue_delayed_work(system_power_efficient_wq,
 					   &info->micd_timeout_work,
-					   msecs_to_jiffies(info->micd_timeout));
+					   msecs_to_jiffies(micd_timeout));
+		}
 
 		goto out;
 	}
@@ -1039,6 +1043,7 @@
 	else
 		info->micd_timeout = DEFAULT_MICD_TIMEOUT;
 
+out:
 	/* Clear trig_sts to make sure DCVDD is not forced up */
 	regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG,
 		     ARIZONA_MICD_CLAMP_FALL_TRIG_STS |
@@ -1046,7 +1051,6 @@
 		     ARIZONA_JD1_FALL_TRIG_STS |
 		     ARIZONA_JD1_RISE_TRIG_STS);
 
-out:
 	mutex_unlock(&info->lock);
 
 	pm_runtime_mark_last_busy(info->dev);
@@ -1129,9 +1133,10 @@
 	}
 
 	info->edev.name = "Headset Jack";
+	info->edev.dev.parent = arizona->dev;
 	info->edev.supported_cable = arizona_cable;
 
-	ret = extcon_dev_register(&info->edev, arizona->dev);
+	ret = extcon_dev_register(&info->edev);
 	if (ret < 0) {
 		dev_err(arizona->dev, "extcon_dev_register() failed: %d\n",
 			ret);
diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c
index 148382f..15443d3 100644
--- a/drivers/extcon/extcon-class.c
+++ b/drivers/extcon/extcon-class.c
@@ -74,7 +74,7 @@
 
 /**
  * check_mutually_exclusive - Check if new_state violates mutually_exclusive
- *			    condition.
+ *			      condition.
  * @edev:	the extcon device
  * @new_state:	new cable attach status for @edev
  *
@@ -105,7 +105,7 @@
 			  char *buf)
 {
 	int i, count = 0;
-	struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
+	struct extcon_dev *edev = dev_get_drvdata(dev);
 
 	if (edev->print_state) {
 		int ret = edev->print_state(edev, buf);
@@ -129,13 +129,12 @@
 	return count;
 }
 
-int extcon_set_state(struct extcon_dev *edev, u32 state);
 static ssize_t state_store(struct device *dev, struct device_attribute *attr,
 			   const char *buf, size_t count)
 {
 	u32 state;
 	ssize_t ret = 0;
-	struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
+	struct extcon_dev *edev = dev_get_drvdata(dev);
 
 	ret = sscanf(buf, "0x%x", &state);
 	if (ret == 0)
@@ -153,7 +152,7 @@
 static ssize_t name_show(struct device *dev, struct device_attribute *attr,
 		char *buf)
 {
-	struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
+	struct extcon_dev *edev = dev_get_drvdata(dev);
 
 	/* Optional callback given by the user */
 	if (edev->print_name) {
@@ -162,7 +161,7 @@
 			return ret;
 	}
 
-	return sprintf(buf, "%s\n", dev_name(edev->dev));
+	return sprintf(buf, "%s\n", dev_name(&edev->dev));
 }
 static DEVICE_ATTR_RO(name);
 
@@ -189,7 +188,7 @@
 
 /**
  * extcon_update_state() - Update the cable attach states of the extcon device
- *			only for the masked bits.
+ *			   only for the masked bits.
  * @edev:	the extcon device
  * @mask:	the bit mask to designate updated bits.
  * @state:	new cable attach status for @edev
@@ -227,11 +226,10 @@
 		edev->state |= state & mask;
 
 		raw_notifier_call_chain(&edev->nh, old_state, edev);
-
 		/* This could be in interrupt handler */
 		prop_buf = (char *)get_zeroed_page(GFP_ATOMIC);
 		if (prop_buf) {
-			length = name_show(edev->dev, NULL, prop_buf);
+			length = name_show(&edev->dev, NULL, prop_buf);
 			if (length > 0) {
 				if (prop_buf[length - 1] == '\n')
 					prop_buf[length - 1] = 0;
@@ -239,7 +237,7 @@
 					"NAME=%s", prop_buf);
 				envp[env_offset++] = name_buf;
 			}
-			length = state_show(edev->dev, NULL, prop_buf);
+			length = state_show(&edev->dev, NULL, prop_buf);
 			if (length > 0) {
 				if (prop_buf[length - 1] == '\n')
 					prop_buf[length - 1] = 0;
@@ -251,14 +249,14 @@
 			/* Unlock early before uevent */
 			spin_unlock_irqrestore(&edev->lock, flags);
 
-			kobject_uevent_env(&edev->dev->kobj, KOBJ_CHANGE, envp);
+			kobject_uevent_env(&edev->dev.kobj, KOBJ_CHANGE, envp);
 			free_page((unsigned long)prop_buf);
 		} else {
 			/* Unlock early before uevent */
 			spin_unlock_irqrestore(&edev->lock, flags);
 
-			dev_err(edev->dev, "out of memory in extcon_set_state\n");
-			kobject_uevent(&edev->dev->kobj, KOBJ_CHANGE);
+			dev_err(&edev->dev, "out of memory in extcon_set_state\n");
+			kobject_uevent(&edev->dev.kobj, KOBJ_CHANGE);
 		}
 	} else {
 		/* No changes */
@@ -339,8 +337,9 @@
 
 /**
  * extcon_set_cable_state_() - Set the status of a specific cable.
- * @edev:	the extcon device that has the cable.
- * @index:	cable index that can be retrieved by extcon_find_cable_index().
+ * @edev:		the extcon device that has the cable.
+ * @index:		cable index that can be retrieved by
+ *			extcon_find_cable_index().
  * @cable_state:	the new cable status. The default semantics is
  *			true: attached / false: detached.
  */
@@ -359,8 +358,8 @@
 
 /**
  * extcon_set_cable_state() - Set the status of a specific cable.
- * @edev:	the extcon device that has the cable.
- * @cable_name:	cable name.
+ * @edev:		the extcon device that has the cable.
+ * @cable_name:		cable name.
  * @cable_state:	the new cable status. The default semantics is
  *			true: attached / false: detached.
  *
@@ -419,14 +418,14 @@
 
 /**
  * extcon_register_interest() - Register a notifier for a state change of a
- *			      specific cable, not an entier set of cables of a
- *			      extcon device.
- * @obj:	an empty extcon_specific_cable_nb object to be returned.
+ *				specific cable, not an entier set of cables of a
+ *				extcon device.
+ * @obj:		an empty extcon_specific_cable_nb object to be returned.
  * @extcon_name:	the name of extcon device.
  *			if NULL, extcon_register_interest will register
  *			every cable with the target cable_name given.
  * @cable_name:		the target cable name.
- * @nb:		the notifier block to get notified.
+ * @nb:			the notifier block to get notified.
  *
  * Provide an empty extcon_specific_cable_nb. extcon_register_interest() sets
  * the struct for you.
@@ -452,7 +451,8 @@
 		if (!obj->edev)
 			return -ENODEV;
 
-		obj->cable_index = extcon_find_cable_index(obj->edev, cable_name);
+		obj->cable_index = extcon_find_cable_index(obj->edev,
+							  cable_name);
 		if (obj->cable_index < 0)
 			return obj->cable_index;
 
@@ -460,7 +460,8 @@
 
 		obj->internal_nb.notifier_call = _call_per_cable;
 
-		return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb);
+		return raw_notifier_chain_register(&obj->edev->nh,
+						  &obj->internal_nb);
 	} else {
 		struct class_dev_iter iter;
 		struct extcon_dev *extd;
@@ -470,7 +471,7 @@
 			return -ENODEV;
 		class_dev_iter_init(&iter, extcon_class, NULL, NULL);
 		while ((dev = class_dev_iter_next(&iter))) {
-			extd = (struct extcon_dev *)dev_get_drvdata(dev);
+			extd = dev_get_drvdata(dev);
 
 			if (extcon_find_cable_index(extd, cable_name) < 0)
 				continue;
@@ -487,7 +488,7 @@
 
 /**
  * extcon_unregister_interest() - Unregister the notifier registered by
- *				extcon_register_interest().
+ *				  extcon_register_interest().
  * @obj:	the extcon_specific_cable_nb object returned by
  *		extcon_register_interest().
  */
@@ -502,7 +503,7 @@
 
 /**
  * extcon_register_notifier() - Register a notifiee to get notified by
- *			      any attach status changes from the extcon.
+ *				any attach status changes from the extcon.
  * @edev:	the extcon device.
  * @nb:		a notifier block to be registered.
  *
@@ -556,7 +557,6 @@
 
 static void extcon_dev_release(struct device *dev)
 {
-	kfree(dev);
 }
 
 static const char *muex_name = "mutually_exclusive";
@@ -567,14 +567,13 @@
 /**
  * extcon_dev_register() - Register a new extcon device
  * @edev	: the new extcon device (should be allocated before calling)
- * @dev		: the parent device for this extcon device.
  *
  * Among the members of edev struct, please set the "user initializing data"
  * in any case and set the "optional callbacks" if required. However, please
  * do not set the values of "internal data", which are initialized by
  * this function.
  */
-int extcon_dev_register(struct extcon_dev *edev, struct device *dev)
+int extcon_dev_register(struct extcon_dev *edev)
 {
 	int ret, index = 0;
 
@@ -594,19 +593,20 @@
 	}
 
 	if (index > SUPPORTED_CABLE_MAX) {
-		dev_err(edev->dev, "extcon: maximum number of supported cables exceeded.\n");
+		dev_err(&edev->dev, "extcon: maximum number of supported cables exceeded.\n");
 		return -EINVAL;
 	}
 
-	edev->dev = kzalloc(sizeof(struct device), GFP_KERNEL);
-	if (!edev->dev)
-		return -ENOMEM;
-	edev->dev->parent = dev;
-	edev->dev->class = extcon_class;
-	edev->dev->release = extcon_dev_release;
+	edev->dev.class = extcon_class;
+	edev->dev.release = extcon_dev_release;
 
-	edev->name = edev->name ? edev->name : dev_name(dev);
-	dev_set_name(edev->dev, "%s", edev->name);
+	edev->name = edev->name ? edev->name : dev_name(edev->dev.parent);
+	if (IS_ERR_OR_NULL(edev->name)) {
+		dev_err(&edev->dev,
+			"extcon device name is null\n");
+		return -EINVAL;
+	}
+	dev_set_name(&edev->dev, "%s", edev->name);
 
 	if (edev->max_supported) {
 		char buf[10];
@@ -714,7 +714,7 @@
 			goto err_alloc_groups;
 		}
 
-		edev->extcon_dev_type.name = dev_name(edev->dev);
+		edev->extcon_dev_type.name = dev_name(&edev->dev);
 		edev->extcon_dev_type.release = dummy_sysfs_dev_release;
 
 		for (index = 0; index < edev->max_supported; index++)
@@ -724,25 +724,24 @@
 			edev->extcon_dev_type.groups[index] =
 				&edev->attr_g_muex;
 
-		edev->dev->type = &edev->extcon_dev_type;
+		edev->dev.type = &edev->extcon_dev_type;
 	}
 
-	ret = device_register(edev->dev);
+	ret = device_register(&edev->dev);
 	if (ret) {
-		put_device(edev->dev);
+		put_device(&edev->dev);
 		goto err_dev;
 	}
 #if defined(CONFIG_ANDROID)
 	if (switch_class)
-		ret = class_compat_create_link(switch_class, edev->dev,
-					       NULL);
+		ret = class_compat_create_link(switch_class, &edev->dev, NULL);
 #endif /* CONFIG_ANDROID */
 
 	spin_lock_init(&edev->lock);
 
 	RAW_INIT_NOTIFIER_HEAD(&edev->nh);
 
-	dev_set_drvdata(edev->dev, edev);
+	dev_set_drvdata(&edev->dev, edev);
 	edev->state = 0;
 
 	mutex_lock(&extcon_dev_list_lock);
@@ -768,7 +767,6 @@
 	if (edev->max_supported)
 		kfree(edev->cables);
 err_sysfs_alloc:
-	kfree(edev->dev);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(extcon_dev_register);
@@ -788,9 +786,9 @@
 	list_del(&edev->entry);
 	mutex_unlock(&extcon_dev_list_lock);
 
-	if (IS_ERR_OR_NULL(get_device(edev->dev))) {
-		dev_err(edev->dev, "Failed to unregister extcon_dev (%s)\n",
-				dev_name(edev->dev));
+	if (IS_ERR_OR_NULL(get_device(&edev->dev))) {
+		dev_err(&edev->dev, "Failed to unregister extcon_dev (%s)\n",
+				dev_name(&edev->dev));
 		return;
 	}
 
@@ -812,10 +810,10 @@
 
 #if defined(CONFIG_ANDROID)
 	if (switch_class)
-		class_compat_remove_link(switch_class, edev->dev, NULL);
+		class_compat_remove_link(switch_class, &edev->dev, NULL);
 #endif
-	device_unregister(edev->dev);
-	put_device(edev->dev);
+	device_unregister(&edev->dev);
+	put_device(&edev->dev);
 }
 EXPORT_SYMBOL_GPL(extcon_dev_unregister);
 
diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c
index f874c30..7e0dff5 100644
--- a/drivers/extcon/extcon-gpio.c
+++ b/drivers/extcon/extcon-gpio.c
@@ -34,6 +34,7 @@
 struct gpio_extcon_data {
 	struct extcon_dev edev;
 	unsigned gpio;
+	bool gpio_active_low;
 	const char *state_on;
 	const char *state_off;
 	int irq;
@@ -49,6 +50,8 @@
 			     work);
 
 	state = gpio_get_value(data->gpio);
+	if (data->gpio_active_low)
+		state = !state;
 	extcon_set_state(&data->edev, state);
 }
 
@@ -78,9 +81,9 @@
 
 static int gpio_extcon_probe(struct platform_device *pdev)
 {
-	struct gpio_extcon_platform_data *pdata = pdev->dev.platform_data;
+	struct gpio_extcon_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct gpio_extcon_data *extcon_data;
-	int ret = 0;
+	int ret;
 
 	if (!pdata)
 		return -EBUSY;
@@ -95,14 +98,22 @@
 		return -ENOMEM;
 
 	extcon_data->edev.name = pdata->name;
+	extcon_data->edev.dev.parent = &pdev->dev;
 	extcon_data->gpio = pdata->gpio;
+	extcon_data->gpio_active_low = pdata->gpio_active_low;
 	extcon_data->state_on = pdata->state_on;
 	extcon_data->state_off = pdata->state_off;
 	if (pdata->state_on && pdata->state_off)
 		extcon_data->edev.print_state = extcon_gpio_print_state;
-	extcon_data->debounce_jiffies = msecs_to_jiffies(pdata->debounce);
+	if (pdata->debounce) {
+		ret = gpio_set_debounce(extcon_data->gpio,
+					pdata->debounce * 1000);
+		if (ret < 0)
+			extcon_data->debounce_jiffies =
+				msecs_to_jiffies(pdata->debounce);
+	}
 
-	ret = extcon_dev_register(&extcon_data->edev, &pdev->dev);
+	ret = extcon_dev_register(&extcon_data->edev);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
index b56bdaa..da268fb 100644
--- a/drivers/extcon/extcon-max77693.c
+++ b/drivers/extcon/extcon-max77693.c
@@ -189,14 +189,17 @@
 
 	/* The below accessories have same ADC value so ADCLow and
 	   ADC1K bit is used to separate specific accessory */
-	MAX77693_MUIC_GND_USB_OTG = 0x100,	/* ADC:0x0, VBVolot:0, ADCLow:0, ADC1K:0 */
-	MAX77693_MUIC_GND_USB_OTG_VB = 0x104,	/* ADC:0x0, VBVolot:1, ADCLow:0, ADC1K:0 */
-	MAX77693_MUIC_GND_AV_CABLE_LOAD = 0x102,/* ADC:0x0, VBVolot:0, ADCLow:1, ADC1K:0 */
-	MAX77693_MUIC_GND_MHL = 0x103,		/* ADC:0x0, VBVolot:0, ADCLow:1, ADC1K:1 */
-	MAX77693_MUIC_GND_MHL_VB = 0x107,	/* ADC:0x0, VBVolot:1, ADCLow:1, ADC1K:1 */
+						/* ADC|VBVolot|ADCLow|ADC1K| */
+	MAX77693_MUIC_GND_USB_OTG = 0x100,	/* 0x0|      0|     0|    0| */
+	MAX77693_MUIC_GND_USB_OTG_VB = 0x104,	/* 0x0|      1|     0|    0| */
+	MAX77693_MUIC_GND_AV_CABLE_LOAD = 0x102,/* 0x0|      0|     1|    0| */
+	MAX77693_MUIC_GND_MHL = 0x103,		/* 0x0|      0|     1|    1| */
+	MAX77693_MUIC_GND_MHL_VB = 0x107,	/* 0x0|      1|     1|    1| */
 };
 
-/* MAX77693 MUIC device support below list of accessories(external connector) */
+/*
+ * MAX77693 MUIC device support below list of accessories(external connector)
+ */
 enum {
 	EXTCON_CABLE_USB = 0,
 	EXTCON_CABLE_USB_HOST,
@@ -395,12 +398,12 @@
 			vbvolt >>= STATUS2_VBVOLT_SHIFT;
 
 			/**
-			 * [0x1][VBVolt][ADCLow][ADC1K]
-			 * [0x1    0	   0       0  ]	: USB_OTG
-			 * [0x1    1	   0       0  ]	: USB_OTG_VB
-			 * [0x1    0       1       0  ] : Audio Video Cable with load
-			 * [0x1    0       1       1  ] : MHL without charging connector
-			 * [0x1    1       1       1  ] : MHL with charging connector
+			 * [0x1|VBVolt|ADCLow|ADC1K]
+			 * [0x1|     0|     0|    0] USB_OTG
+			 * [0x1|     1|     0|    0] USB_OTG_VB
+			 * [0x1|     0|     1|    0] Audio Video cable with load
+			 * [0x1|     0|     1|    1] MHL without charging cable
+			 * [0x1|     1|     1|    1] MHL with charging cable
 			 */
 			cable_type = ((0x1 << 8)
 					| (vbvolt << 2)
@@ -723,11 +726,11 @@
 		if (ret < 0)
 			return ret;
 		break;
-	case MAX77693_MUIC_ADC_REMOTE_S3_BUTTON:	/* DOCK_KEY_PREV */
-	case MAX77693_MUIC_ADC_REMOTE_S7_BUTTON:	/* DOCK_KEY_NEXT */
-	case MAX77693_MUIC_ADC_REMOTE_S9_BUTTON:	/* DOCK_VOL_DOWN */
-	case MAX77693_MUIC_ADC_REMOTE_S10_BUTTON:	/* DOCK_VOL_UP */
-	case MAX77693_MUIC_ADC_REMOTE_S12_BUTTON:	/* DOCK_KEY_PLAY_PAUSE */
+	case MAX77693_MUIC_ADC_REMOTE_S3_BUTTON:      /* DOCK_KEY_PREV */
+	case MAX77693_MUIC_ADC_REMOTE_S7_BUTTON:      /* DOCK_KEY_NEXT */
+	case MAX77693_MUIC_ADC_REMOTE_S9_BUTTON:      /* DOCK_VOL_DOWN */
+	case MAX77693_MUIC_ADC_REMOTE_S10_BUTTON:     /* DOCK_VOL_UP */
+	case MAX77693_MUIC_ADC_REMOTE_S12_BUTTON:     /* DOCK_KEY_PLAY_PAUSE */
 		/*
 		 * Button of DOCK device
 		 * - the Prev/Next/Volume Up/Volume Down/Play-Pause button
@@ -815,19 +818,21 @@
 		case MAX77693_MUIC_GND_MHL_VB:
 			/*
 			 * MHL cable with MHL_TA(USB/TA) cable
-			 * - MHL cable include two port(HDMI line and separate micro-
-			 * usb port. When the target connect MHL cable, extcon driver
-			 * check whether MHL_TA(USB/TA) cable is connected. If MHL_TA
-			 * cable is connected, extcon driver notify state to notifiee
-			 * for charging battery.
+			 * - MHL cable include two port(HDMI line and separate
+			 * micro-usb port. When the target connect MHL cable,
+			 * extcon driver check whether MHL_TA(USB/TA) cable is
+			 * connected. If MHL_TA cable is connected, extcon
+			 * driver notify state to notifiee for charging battery.
 			 *
 			 * Features of 'MHL_TA(USB/TA) with MHL cable'
 			 * - Support MHL
-			 * - Support charging through micro-usb port without data connection
+			 * - Support charging through micro-usb port without
+			 *   data connection
 			 */
 			extcon_set_cable_state(info->edev, "MHL_TA", attached);
 			if (!cable_attached)
-				extcon_set_cable_state(info->edev, "MHL", cable_attached);
+				extcon_set_cable_state(info->edev,
+						      "MHL", cable_attached);
 			break;
 		}
 
@@ -839,47 +844,51 @@
 		case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD:		/* Dock-Audio */
 			/*
 			 * Dock-Audio device with USB/TA cable
-			 * - Dock device include two port(Dock-Audio and micro-usb
-			 * port). When the target connect Dock-Audio device, extcon
-			 * driver check whether USB/TA cable is connected. If USB/TA
-			 * cable is connected, extcon driver notify state to notifiee
-			 * for charging battery.
+			 * - Dock device include two port(Dock-Audio and micro-
+			 * usb port). When the target connect Dock-Audio device,
+			 * extcon driver check whether USB/TA cable is connected
+			 * or not. If USB/TA cable is connected, extcon driver
+			 * notify state to notifiee for charging battery.
 			 *
 			 * Features of 'USB/TA cable with Dock-Audio device'
 			 * - Support external output feature of audio.
-			 * - Support charging through micro-usb port without data
-			 *           connection.
+			 * - Support charging through micro-usb port without
+			 *   data connection.
 			 */
 			extcon_set_cable_state(info->edev, "USB", attached);
 
 			if (!cable_attached)
-				extcon_set_cable_state(info->edev, "Dock-Audio", cable_attached);
+				extcon_set_cable_state(info->edev, "Dock-Audio",
+						      cable_attached);
 			break;
 		case MAX77693_MUIC_ADC_RESERVED_ACC_3:		/* Dock-Smart */
 			/*
 			 * Dock-Smart device with USB/TA cable
 			 * - Dock-Desk device include three type of cable which
 			 * are HDMI, USB for mouse/keyboard and micro-usb port
-			 * for USB/TA cable. Dock-Smart device need always exteranl
-			 * power supply(USB/TA cable through micro-usb cable). Dock-
-			 * Smart device support screen output of target to separate
-			 * monitor and mouse/keyboard for desktop mode.
+			 * for USB/TA cable. Dock-Smart device need always
+			 * exteranl power supply(USB/TA cable through micro-usb
+			 * cable). Dock-Smart device support screen output of
+			 * target to separate monitor and mouse/keyboard for
+			 * desktop mode.
 			 *
 			 * Features of 'USB/TA cable with Dock-Smart device'
 			 * - Support MHL
 			 * - Support external output feature of audio
-			 * - Support charging through micro-usb port without data
-			 *	     connection if TA cable is connected to target.
-			 * - Support charging and data connection through micro-usb port
-			 *           if USB cable is connected between target and host
-			 *	     device.
+			 * - Support charging through micro-usb port without
+			 *   data connection if TA cable is connected to target.
+			 * - Support charging and data connection through micro-
+			 *   usb port if USB cable is connected between target
+			 *   and host device
 			 * - Support OTG device (Mouse/Keyboard)
 			 */
-			ret = max77693_muic_set_path(info, info->path_usb, attached);
+			ret = max77693_muic_set_path(info, info->path_usb,
+						    attached);
 			if (ret < 0)
 				return ret;
 
-			extcon_set_cable_state(info->edev, "Dock-Smart", attached);
+			extcon_set_cable_state(info->edev, "Dock-Smart",
+					      attached);
 			extcon_set_cable_state(info->edev, "MHL", attached);
 
 			break;
@@ -889,25 +898,28 @@
 		switch (chg_type) {
 		case MAX77693_CHARGER_TYPE_NONE:
 			/*
-			 * When MHL(with USB/TA cable) or Dock-Audio with USB/TA cable
-			 * is attached, muic device happen below two interrupt.
-			 * - 'MAX77693_MUIC_IRQ_INT1_ADC' for detecting MHL/Dock-Audio.
-			 * - 'MAX77693_MUIC_IRQ_INT2_CHGTYP' for detecting USB/TA cable
-			 *   connected to MHL or Dock-Audio.
-			 * Always, happen eariler MAX77693_MUIC_IRQ_INT1_ADC interrupt
-			 * than MAX77693_MUIC_IRQ_INT2_CHGTYP interrupt.
+			 * When MHL(with USB/TA cable) or Dock-Audio with USB/TA
+			 * cable is attached, muic device happen below two irq.
+			 * - 'MAX77693_MUIC_IRQ_INT1_ADC' for detecting
+			 *    MHL/Dock-Audio.
+			 * - 'MAX77693_MUIC_IRQ_INT2_CHGTYP' for detecting
+			 *    USB/TA cable connected to MHL or Dock-Audio.
+			 * Always, happen eariler MAX77693_MUIC_IRQ_INT1_ADC
+			 * irq than MAX77693_MUIC_IRQ_INT2_CHGTYP irq.
 			 *
-			 * If user attach MHL (with USB/TA cable and immediately detach
-			 * MHL with USB/TA cable before MAX77693_MUIC_IRQ_INT2_CHGTYP
-			 * interrupt is happened, USB/TA cable remain connected state to
-			 * target. But USB/TA cable isn't connected to target. The user
-			 * be face with unusual action. So, driver should check this
-			 * situation in spite of, that previous charger type is N/A.
+			 * If user attach MHL (with USB/TA cable and immediately
+			 * detach MHL with USB/TA cable before MAX77693_MUIC_IRQ
+			 * _INT2_CHGTYP irq is happened, USB/TA cable remain
+			 * connected state to target. But USB/TA cable isn't
+			 * connected to target. The user be face with unusual
+			 * action. So, driver should check this situation in
+			 * spite of, that previous charger type is N/A.
 			 */
 			break;
 		case MAX77693_CHARGER_TYPE_USB:
 			/* Only USB cable, PATH:AP_USB */
-			ret = max77693_muic_set_path(info, info->path_usb, attached);
+			ret = max77693_muic_set_path(info, info->path_usb,
+						    attached);
 			if (ret < 0)
 				return ret;
 
@@ -953,7 +965,7 @@
 
 	mutex_lock(&info->mutex);
 
-	for (i = 0 ; i < ARRAY_SIZE(muic_irqs) ; i++)
+	for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
 		if (info->irq == muic_irqs[i].virq)
 			irq_type = muic_irqs[i].irq;
 
@@ -1171,8 +1183,9 @@
 		goto err_irq;
 	}
 	info->edev->name = DEV_NAME;
+	info->edev->dev.parent = &pdev->dev;
 	info->edev->supported_cable = max77693_extcon_cable;
-	ret = extcon_dev_register(info->edev, NULL);
+	ret = extcon_dev_register(info->edev);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register extcon device\n");
 		goto err_irq;
@@ -1188,7 +1201,7 @@
 		num_init_data = ARRAY_SIZE(default_init_data);
 	}
 
-	for (i = 0 ; i < num_init_data ; i++) {
+	for (i = 0; i < num_init_data; i++) {
 		enum max77693_irq_source irq_src
 				= MAX77693_IRQ_GROUP_NR;
 
@@ -1214,7 +1227,8 @@
 	}
 
 	if (pdata->muic_data) {
-		struct max77693_muic_platform_data *muic_pdata = pdata->muic_data;
+		struct max77693_muic_platform_data *muic_pdata
+						   = pdata->muic_data;
 
 		/*
 		 * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
index 67d6738..6a00464 100644
--- a/drivers/extcon/extcon-max8997.c
+++ b/drivers/extcon/extcon-max8997.c
@@ -426,7 +426,8 @@
 		break;
 	case MAX8997_MUIC_ADC_FACTORY_MODE_USB_OFF:
 	case MAX8997_MUIC_ADC_FACTORY_MODE_USB_ON:
-		ret = max8997_muic_handle_usb(info, MAX8997_USB_DEVICE, attached);
+		ret = max8997_muic_handle_usb(info,
+					     MAX8997_USB_DEVICE, attached);
 		if (ret < 0)
 			return ret;
 		break;
@@ -504,7 +505,8 @@
 		}
 		break;
 	case MAX8997_CHARGER_TYPE_DOWNSTREAM_PORT:
-		extcon_set_cable_state(info->edev, "Charge-downstream", attached);
+		extcon_set_cable_state(info->edev,
+				      "Charge-downstream", attached);
 		break;
 	case MAX8997_CHARGER_TYPE_DEDICATED_CHG:
 		extcon_set_cable_state(info->edev, "TA", attached);
@@ -537,7 +539,7 @@
 
 	mutex_lock(&info->mutex);
 
-	for (i = 0 ; i < ARRAY_SIZE(muic_irqs) ; i++)
+	for (i = 0; i < ARRAY_SIZE(muic_irqs); i++)
 		if (info->irq == muic_irqs[i].virq)
 			irq_type = muic_irqs[i].irq;
 
@@ -705,8 +707,9 @@
 		goto err_irq;
 	}
 	info->edev->name = DEV_NAME;
+	info->edev->dev.parent = &pdev->dev;
 	info->edev->supported_cable = max8997_extcon_cable;
-	ret = extcon_dev_register(info->edev, NULL);
+	ret = extcon_dev_register(info->edev);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register extcon device\n");
 		goto err_irq;
diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c
index 89fdd05..6c91976 100644
--- a/drivers/extcon/extcon-palmas.c
+++ b/drivers/extcon/extcon-palmas.c
@@ -135,7 +135,7 @@
 static int palmas_usb_probe(struct platform_device *pdev)
 {
 	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
-	struct palmas_usb_platform_data	*pdata = pdev->dev.platform_data;
+	struct palmas_usb_platform_data	*pdata = dev_get_platdata(&pdev->dev);
 	struct device_node *node = pdev->dev.of_node;
 	struct palmas_usb *palmas_usb;
 	int status;
@@ -178,9 +178,10 @@
 	platform_set_drvdata(pdev, palmas_usb);
 
 	palmas_usb->edev.supported_cable = palmas_extcon_cable;
+	palmas_usb->edev.dev.parent = palmas_usb->dev;
 	palmas_usb->edev.mutually_exclusive = mutually_exclusive;
 
-	status = extcon_dev_register(&palmas_usb->edev, palmas_usb->dev);
+	status = extcon_dev_register(&palmas_usb->edev);
 	if (status) {
 		dev_err(&pdev->dev, "failed to register extcon device\n");
 		return status;
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index fa0affb..c7e81ff 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -8,6 +8,7 @@
 #include <linux/bootmem.h>
 #include <linux/random.h>
 #include <asm/dmi.h>
+#include <asm/unaligned.h>
 
 /*
  * DMI stands for "Desktop Management Interface".  It is part
@@ -25,6 +26,13 @@
 /* DMI system identification string used during boot */
 static char dmi_ids_string[128] __initdata;
 
+static struct dmi_memdev_info {
+	const char *device;
+	const char *bank;
+	u16 handle;
+} *dmi_memdev;
+static int dmi_memdev_nr;
+
 static const char * __init dmi_string_nosave(const struct dmi_header *dm, u8 s)
 {
 	const u8 *bp = ((u8 *) dm) + dm->length;
@@ -322,6 +330,42 @@
 	dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d - 1)));
 }
 
+static void __init count_mem_devices(const struct dmi_header *dm, void *v)
+{
+	if (dm->type != DMI_ENTRY_MEM_DEVICE)
+		return;
+	dmi_memdev_nr++;
+}
+
+static void __init save_mem_devices(const struct dmi_header *dm, void *v)
+{
+	const char *d = (const char *)dm;
+	static int nr;
+
+	if (dm->type != DMI_ENTRY_MEM_DEVICE)
+		return;
+	if (nr >= dmi_memdev_nr) {
+		pr_warn(FW_BUG "Too many DIMM entries in SMBIOS table\n");
+		return;
+	}
+	dmi_memdev[nr].handle = get_unaligned(&dm->handle);
+	dmi_memdev[nr].device = dmi_string(dm, d[0x10]);
+	dmi_memdev[nr].bank = dmi_string(dm, d[0x11]);
+	nr++;
+}
+
+void __init dmi_memdev_walk(void)
+{
+	if (!dmi_available)
+		return;
+
+	if (dmi_walk_early(count_mem_devices) == 0 && dmi_memdev_nr) {
+		dmi_memdev = dmi_alloc(sizeof(*dmi_memdev) * dmi_memdev_nr);
+		if (dmi_memdev)
+			dmi_walk_early(save_mem_devices);
+	}
+}
+
 /*
  *	Process a DMI table entry. Right now all we care about are the BIOS
  *	and machine entries. For 2.5 we should pull the smbus controller info
@@ -815,3 +859,20 @@
 	return !strcmp(info, str);
 }
 EXPORT_SYMBOL_GPL(dmi_match);
+
+void dmi_memdev_name(u16 handle, const char **bank, const char **device)
+{
+	int n;
+
+	if (dmi_memdev == NULL)
+		return;
+
+	for (n = 0; n < dmi_memdev_nr; n++) {
+		if (handle == dmi_memdev[n].handle) {
+			*bank = dmi_memdev[n].bank;
+			*device = dmi_memdev[n].device;
+			break;
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(dmi_memdev_name);
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index b0fc7c7..3150aa4 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -36,4 +36,7 @@
 	  backend for pstore by default. This setting can be overridden
 	  using the efivars module's pstore_disable parameter.
 
+config UEFI_CPER
+	def_bool n
+
 endmenu
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index 99245ab..9ba156d 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -4,3 +4,4 @@
 obj-y					+= efi.o vars.o
 obj-$(CONFIG_EFI_VARS)			+= efivars.o
 obj-$(CONFIG_EFI_VARS_PSTORE)		+= efi-pstore.o
+obj-$(CONFIG_UEFI_CPER)			+= cper.o
diff --git a/drivers/acpi/apei/cper.c b/drivers/firmware/efi/cper.c
similarity index 76%
rename from drivers/acpi/apei/cper.c
rename to drivers/firmware/efi/cper.c
index 33dc6a0..1491dd4 100644
--- a/drivers/acpi/apei/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -5,10 +5,10 @@
  *	Author: Huang Ying <ying.huang@intel.com>
  *
  * CPER is the format used to describe platform hardware error by
- * various APEI tables, such as ERST, BERT and HEST etc.
+ * various tables, such as ERST, BERT and HEST etc.
  *
  * For more information about CPER, please refer to Appendix N of UEFI
- * Specification version 2.3.
+ * Specification version 2.4.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License version
@@ -28,10 +28,12 @@
 #include <linux/module.h>
 #include <linux/time.h>
 #include <linux/cper.h>
+#include <linux/dmi.h>
 #include <linux/acpi.h>
 #include <linux/pci.h>
 #include <linux/aer.h>
 
+#define INDENT_SP	" "
 /*
  * CPER record ID need to be unique even after reboot, because record
  * ID is used as index for ERST storage, while CPER records from
@@ -73,7 +75,7 @@
  * printed, with @pfx is printed at the beginning of each line.
  */
 void cper_print_bits(const char *pfx, unsigned int bits,
-		     const char *strs[], unsigned int strs_size)
+		     const char * const strs[], unsigned int strs_size)
 {
 	int i, len = 0;
 	const char *str;
@@ -98,32 +100,32 @@
 		printk("%s\n", buf);
 }
 
-static const char *cper_proc_type_strs[] = {
+static const char * const cper_proc_type_strs[] = {
 	"IA32/X64",
 	"IA64",
 };
 
-static const char *cper_proc_isa_strs[] = {
+static const char * const cper_proc_isa_strs[] = {
 	"IA32",
 	"IA64",
 	"X64",
 };
 
-static const char *cper_proc_error_type_strs[] = {
+static const char * const cper_proc_error_type_strs[] = {
 	"cache error",
 	"TLB error",
 	"bus error",
 	"micro-architectural error",
 };
 
-static const char *cper_proc_op_strs[] = {
+static const char * const cper_proc_op_strs[] = {
 	"unknown or generic",
 	"data read",
 	"data write",
 	"instruction execution",
 };
 
-static const char *cper_proc_flag_strs[] = {
+static const char * const cper_proc_flag_strs[] = {
 	"restartable",
 	"precise IP",
 	"overflow",
@@ -191,46 +193,58 @@
 	"memory sparing",
 	"scrub corrected error",
 	"scrub uncorrected error",
+	"physical memory map-out event",
 };
 
 static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem)
 {
 	if (mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS)
 		printk("%s""error_status: 0x%016llx\n", pfx, mem->error_status);
-	if (mem->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS)
+	if (mem->validation_bits & CPER_MEM_VALID_PA)
 		printk("%s""physical_address: 0x%016llx\n",
 		       pfx, mem->physical_addr);
-	if (mem->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS_MASK)
+	if (mem->validation_bits & CPER_MEM_VALID_PA_MASK)
 		printk("%s""physical_address_mask: 0x%016llx\n",
 		       pfx, mem->physical_addr_mask);
 	if (mem->validation_bits & CPER_MEM_VALID_NODE)
-		printk("%s""node: %d\n", pfx, mem->node);
+		pr_debug("node: %d\n", mem->node);
 	if (mem->validation_bits & CPER_MEM_VALID_CARD)
-		printk("%s""card: %d\n", pfx, mem->card);
+		pr_debug("card: %d\n", mem->card);
 	if (mem->validation_bits & CPER_MEM_VALID_MODULE)
-		printk("%s""module: %d\n", pfx, mem->module);
+		pr_debug("module: %d\n", mem->module);
+	if (mem->validation_bits & CPER_MEM_VALID_RANK_NUMBER)
+		pr_debug("rank: %d\n", mem->rank);
 	if (mem->validation_bits & CPER_MEM_VALID_BANK)
-		printk("%s""bank: %d\n", pfx, mem->bank);
+		pr_debug("bank: %d\n", mem->bank);
 	if (mem->validation_bits & CPER_MEM_VALID_DEVICE)
-		printk("%s""device: %d\n", pfx, mem->device);
+		pr_debug("device: %d\n", mem->device);
 	if (mem->validation_bits & CPER_MEM_VALID_ROW)
-		printk("%s""row: %d\n", pfx, mem->row);
+		pr_debug("row: %d\n", mem->row);
 	if (mem->validation_bits & CPER_MEM_VALID_COLUMN)
-		printk("%s""column: %d\n", pfx, mem->column);
+		pr_debug("column: %d\n", mem->column);
 	if (mem->validation_bits & CPER_MEM_VALID_BIT_POSITION)
-		printk("%s""bit_position: %d\n", pfx, mem->bit_pos);
+		pr_debug("bit_position: %d\n", mem->bit_pos);
 	if (mem->validation_bits & CPER_MEM_VALID_REQUESTOR_ID)
-		printk("%s""requestor_id: 0x%016llx\n", pfx, mem->requestor_id);
+		pr_debug("requestor_id: 0x%016llx\n", mem->requestor_id);
 	if (mem->validation_bits & CPER_MEM_VALID_RESPONDER_ID)
-		printk("%s""responder_id: 0x%016llx\n", pfx, mem->responder_id);
+		pr_debug("responder_id: 0x%016llx\n", mem->responder_id);
 	if (mem->validation_bits & CPER_MEM_VALID_TARGET_ID)
-		printk("%s""target_id: 0x%016llx\n", pfx, mem->target_id);
+		pr_debug("target_id: 0x%016llx\n", mem->target_id);
 	if (mem->validation_bits & CPER_MEM_VALID_ERROR_TYPE) {
 		u8 etype = mem->error_type;
 		printk("%s""error_type: %d, %s\n", pfx, etype,
 		       etype < ARRAY_SIZE(cper_mem_err_type_strs) ?
 		       cper_mem_err_type_strs[etype] : "unknown");
 	}
+	if (mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE) {
+		const char *bank = NULL, *device = NULL;
+		dmi_memdev_name(mem->mem_dev_handle, &bank, &device);
+		if (bank != NULL && device != NULL)
+			printk("%s""DIMM location: %s %s", pfx, bank, device);
+		else
+			printk("%s""DIMM DMI handle: 0x%.4x",
+			       pfx, mem->mem_dev_handle);
+	}
 }
 
 static const char *cper_pcie_port_type_strs[] = {
@@ -248,7 +262,7 @@
 };
 
 static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
-			    const struct acpi_hest_generic_data *gdata)
+			    const struct acpi_generic_data *gdata)
 {
 	if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE)
 		printk("%s""port_type: %d, %s\n", pfx, pcie->port_type,
@@ -283,55 +297,45 @@
 	pfx, pcie->bridge.secondary_status, pcie->bridge.control);
 }
 
-static const char *apei_estatus_section_flag_strs[] = {
-	"primary",
-	"containment warning",
-	"reset",
-	"threshold exceeded",
-	"resource not accessible",
-	"latent error",
-};
-
-static void apei_estatus_print_section(
-	const char *pfx, const struct acpi_hest_generic_data *gdata, int sec_no)
+static void cper_estatus_print_section(
+	const char *pfx, const struct acpi_generic_data *gdata, int sec_no)
 {
 	uuid_le *sec_type = (uuid_le *)gdata->section_type;
 	__u16 severity;
+	char newpfx[64];
 
 	severity = gdata->error_severity;
-	printk("%s""section: %d, severity: %d, %s\n", pfx, sec_no, severity,
+	printk("%s""Error %d, type: %s\n", pfx, sec_no,
 	       cper_severity_str(severity));
-	printk("%s""flags: 0x%02x\n", pfx, gdata->flags);
-	cper_print_bits(pfx, gdata->flags, apei_estatus_section_flag_strs,
-			ARRAY_SIZE(apei_estatus_section_flag_strs));
 	if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID)
 		printk("%s""fru_id: %pUl\n", pfx, (uuid_le *)gdata->fru_id);
 	if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT)
 		printk("%s""fru_text: %.20s\n", pfx, gdata->fru_text);
 
+	snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
 	if (!uuid_le_cmp(*sec_type, CPER_SEC_PROC_GENERIC)) {
 		struct cper_sec_proc_generic *proc_err = (void *)(gdata + 1);
-		printk("%s""section_type: general processor error\n", pfx);
+		printk("%s""section_type: general processor error\n", newpfx);
 		if (gdata->error_data_length >= sizeof(*proc_err))
-			cper_print_proc_generic(pfx, proc_err);
+			cper_print_proc_generic(newpfx, proc_err);
 		else
 			goto err_section_too_small;
 	} else if (!uuid_le_cmp(*sec_type, CPER_SEC_PLATFORM_MEM)) {
 		struct cper_sec_mem_err *mem_err = (void *)(gdata + 1);
-		printk("%s""section_type: memory error\n", pfx);
+		printk("%s""section_type: memory error\n", newpfx);
 		if (gdata->error_data_length >= sizeof(*mem_err))
-			cper_print_mem(pfx, mem_err);
+			cper_print_mem(newpfx, mem_err);
 		else
 			goto err_section_too_small;
 	} else if (!uuid_le_cmp(*sec_type, CPER_SEC_PCIE)) {
 		struct cper_sec_pcie *pcie = (void *)(gdata + 1);
-		printk("%s""section_type: PCIe error\n", pfx);
+		printk("%s""section_type: PCIe error\n", newpfx);
 		if (gdata->error_data_length >= sizeof(*pcie))
-			cper_print_pcie(pfx, pcie, gdata);
+			cper_print_pcie(newpfx, pcie, gdata);
 		else
 			goto err_section_too_small;
 	} else
-		printk("%s""section type: unknown, %pUl\n", pfx, sec_type);
+		printk("%s""section type: unknown, %pUl\n", newpfx, sec_type);
 
 	return;
 
@@ -339,34 +343,38 @@
 	pr_err(FW_WARN "error section length is too small\n");
 }
 
-void apei_estatus_print(const char *pfx,
-			const struct acpi_hest_generic_status *estatus)
+void cper_estatus_print(const char *pfx,
+			const struct acpi_generic_status *estatus)
 {
-	struct acpi_hest_generic_data *gdata;
+	struct acpi_generic_data *gdata;
 	unsigned int data_len, gedata_len;
 	int sec_no = 0;
+	char newpfx[64];
 	__u16 severity;
 
-	printk("%s""APEI generic hardware error status\n", pfx);
 	severity = estatus->error_severity;
-	printk("%s""severity: %d, %s\n", pfx, severity,
-	       cper_severity_str(severity));
+	if (severity == CPER_SEV_CORRECTED)
+		printk("%s%s\n", pfx,
+		       "It has been corrected by h/w "
+		       "and requires no further action");
+	printk("%s""event severity: %s\n", pfx, cper_severity_str(severity));
 	data_len = estatus->data_length;
-	gdata = (struct acpi_hest_generic_data *)(estatus + 1);
-	while (data_len > sizeof(*gdata)) {
+	gdata = (struct acpi_generic_data *)(estatus + 1);
+	snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
+	while (data_len >= sizeof(*gdata)) {
 		gedata_len = gdata->error_data_length;
-		apei_estatus_print_section(pfx, gdata, sec_no);
+		cper_estatus_print_section(newpfx, gdata, sec_no);
 		data_len -= gedata_len + sizeof(*gdata);
 		gdata = (void *)(gdata + 1) + gedata_len;
 		sec_no++;
 	}
 }
-EXPORT_SYMBOL_GPL(apei_estatus_print);
+EXPORT_SYMBOL_GPL(cper_estatus_print);
 
-int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus)
+int cper_estatus_check_header(const struct acpi_generic_status *estatus)
 {
 	if (estatus->data_length &&
-	    estatus->data_length < sizeof(struct acpi_hest_generic_data))
+	    estatus->data_length < sizeof(struct acpi_generic_data))
 		return -EINVAL;
 	if (estatus->raw_data_length &&
 	    estatus->raw_data_offset < sizeof(*estatus) + estatus->data_length)
@@ -374,19 +382,19 @@
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(apei_estatus_check_header);
+EXPORT_SYMBOL_GPL(cper_estatus_check_header);
 
-int apei_estatus_check(const struct acpi_hest_generic_status *estatus)
+int cper_estatus_check(const struct acpi_generic_status *estatus)
 {
-	struct acpi_hest_generic_data *gdata;
+	struct acpi_generic_data *gdata;
 	unsigned int data_len, gedata_len;
 	int rc;
 
-	rc = apei_estatus_check_header(estatus);
+	rc = cper_estatus_check_header(estatus);
 	if (rc)
 		return rc;
 	data_len = estatus->data_length;
-	gdata = (struct acpi_hest_generic_data *)(estatus + 1);
+	gdata = (struct acpi_generic_data *)(estatus + 1);
 	while (data_len >= sizeof(*gdata)) {
 		gedata_len = gdata->error_data_length;
 		if (gedata_len > data_len - sizeof(*gdata))
@@ -399,4 +407,4 @@
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(apei_estatus_check);
+EXPORT_SYMBOL_GPL(cper_estatus_check);
diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c
new file mode 100644
index 0000000..b6bffbf
--- /dev/null
+++ b/drivers/firmware/efi/efi-stub-helper.c
@@ -0,0 +1,636 @@
+/*
+ * Helper functions used by the EFI stub on multiple
+ * architectures. This should be #included by the EFI stub
+ * implementation files.
+ *
+ * Copyright 2011 Intel Corporation; author Matt Fleming
+ *
+ * This file is part of the Linux kernel, and is made available
+ * under the terms of the GNU General Public License version 2.
+ *
+ */
+#define EFI_READ_CHUNK_SIZE	(1024 * 1024)
+
+struct file_info {
+	efi_file_handle_t *handle;
+	u64 size;
+};
+
+
+
+
+static void efi_char16_printk(efi_system_table_t *sys_table_arg,
+			      efi_char16_t *str)
+{
+	struct efi_simple_text_output_protocol *out;
+
+	out = (struct efi_simple_text_output_protocol *)sys_table_arg->con_out;
+	efi_call_phys2(out->output_string, out, str);
+}
+
+static void efi_printk(efi_system_table_t *sys_table_arg, char *str)
+{
+	char *s8;
+
+	for (s8 = str; *s8; s8++) {
+		efi_char16_t ch[2] = { 0 };
+
+		ch[0] = *s8;
+		if (*s8 == '\n') {
+			efi_char16_t nl[2] = { '\r', 0 };
+			efi_char16_printk(sys_table_arg, nl);
+		}
+
+		efi_char16_printk(sys_table_arg, ch);
+	}
+}
+
+
+static efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg,
+				       efi_memory_desc_t **map,
+				       unsigned long *map_size,
+				       unsigned long *desc_size,
+				       u32 *desc_ver,
+				       unsigned long *key_ptr)
+{
+	efi_memory_desc_t *m = NULL;
+	efi_status_t status;
+	unsigned long key;
+	u32 desc_version;
+
+	*map_size = sizeof(*m) * 32;
+again:
+	/*
+	 * Add an additional efi_memory_desc_t because we're doing an
+	 * allocation which may be in a new descriptor region.
+	 */
+	*map_size += sizeof(*m);
+	status = efi_call_phys3(sys_table_arg->boottime->allocate_pool,
+				EFI_LOADER_DATA, *map_size, (void **)&m);
+	if (status != EFI_SUCCESS)
+		goto fail;
+
+	status = efi_call_phys5(sys_table_arg->boottime->get_memory_map,
+				map_size, m, &key, desc_size, &desc_version);
+	if (status == EFI_BUFFER_TOO_SMALL) {
+		efi_call_phys1(sys_table_arg->boottime->free_pool, m);
+		goto again;
+	}
+
+	if (status != EFI_SUCCESS)
+		efi_call_phys1(sys_table_arg->boottime->free_pool, m);
+	if (key_ptr && status == EFI_SUCCESS)
+		*key_ptr = key;
+	if (desc_ver && status == EFI_SUCCESS)
+		*desc_ver = desc_version;
+
+fail:
+	*map = m;
+	return status;
+}
+
+/*
+ * Allocate at the highest possible address that is not above 'max'.
+ */
+static efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg,
+			       unsigned long size, unsigned long align,
+			       unsigned long *addr, unsigned long max)
+{
+	unsigned long map_size, desc_size;
+	efi_memory_desc_t *map;
+	efi_status_t status;
+	unsigned long nr_pages;
+	u64 max_addr = 0;
+	int i;
+
+	status = efi_get_memory_map(sys_table_arg, &map, &map_size, &desc_size,
+				    NULL, NULL);
+	if (status != EFI_SUCCESS)
+		goto fail;
+
+	/*
+	 * Enforce minimum alignment that EFI requires when requesting
+	 * a specific address.  We are doing page-based allocations,
+	 * so we must be aligned to a page.
+	 */
+	if (align < EFI_PAGE_SIZE)
+		align = EFI_PAGE_SIZE;
+
+	nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
+again:
+	for (i = 0; i < map_size / desc_size; i++) {
+		efi_memory_desc_t *desc;
+		unsigned long m = (unsigned long)map;
+		u64 start, end;
+
+		desc = (efi_memory_desc_t *)(m + (i * desc_size));
+		if (desc->type != EFI_CONVENTIONAL_MEMORY)
+			continue;
+
+		if (desc->num_pages < nr_pages)
+			continue;
+
+		start = desc->phys_addr;
+		end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT);
+
+		if ((start + size) > end || (start + size) > max)
+			continue;
+
+		if (end - size > max)
+			end = max;
+
+		if (round_down(end - size, align) < start)
+			continue;
+
+		start = round_down(end - size, align);
+
+		/*
+		 * Don't allocate at 0x0. It will confuse code that
+		 * checks pointers against NULL.
+		 */
+		if (start == 0x0)
+			continue;
+
+		if (start > max_addr)
+			max_addr = start;
+	}
+
+	if (!max_addr)
+		status = EFI_NOT_FOUND;
+	else {
+		status = efi_call_phys4(sys_table_arg->boottime->allocate_pages,
+					EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
+					nr_pages, &max_addr);
+		if (status != EFI_SUCCESS) {
+			max = max_addr;
+			max_addr = 0;
+			goto again;
+		}
+
+		*addr = max_addr;
+	}
+
+	efi_call_phys1(sys_table_arg->boottime->free_pool, map);
+
+fail:
+	return status;
+}
+
+/*
+ * Allocate at the lowest possible address.
+ */
+static efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg,
+			      unsigned long size, unsigned long align,
+			      unsigned long *addr)
+{
+	unsigned long map_size, desc_size;
+	efi_memory_desc_t *map;
+	efi_status_t status;
+	unsigned long nr_pages;
+	int i;
+
+	status = efi_get_memory_map(sys_table_arg, &map, &map_size, &desc_size,
+				    NULL, NULL);
+	if (status != EFI_SUCCESS)
+		goto fail;
+
+	/*
+	 * Enforce minimum alignment that EFI requires when requesting
+	 * a specific address.  We are doing page-based allocations,
+	 * so we must be aligned to a page.
+	 */
+	if (align < EFI_PAGE_SIZE)
+		align = EFI_PAGE_SIZE;
+
+	nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
+	for (i = 0; i < map_size / desc_size; i++) {
+		efi_memory_desc_t *desc;
+		unsigned long m = (unsigned long)map;
+		u64 start, end;
+
+		desc = (efi_memory_desc_t *)(m + (i * desc_size));
+
+		if (desc->type != EFI_CONVENTIONAL_MEMORY)
+			continue;
+
+		if (desc->num_pages < nr_pages)
+			continue;
+
+		start = desc->phys_addr;
+		end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT);
+
+		/*
+		 * Don't allocate at 0x0. It will confuse code that
+		 * checks pointers against NULL. Skip the first 8
+		 * bytes so we start at a nice even number.
+		 */
+		if (start == 0x0)
+			start += 8;
+
+		start = round_up(start, align);
+		if ((start + size) > end)
+			continue;
+
+		status = efi_call_phys4(sys_table_arg->boottime->allocate_pages,
+					EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
+					nr_pages, &start);
+		if (status == EFI_SUCCESS) {
+			*addr = start;
+			break;
+		}
+	}
+
+	if (i == map_size / desc_size)
+		status = EFI_NOT_FOUND;
+
+	efi_call_phys1(sys_table_arg->boottime->free_pool, map);
+fail:
+	return status;
+}
+
+static void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
+		     unsigned long addr)
+{
+	unsigned long nr_pages;
+
+	if (!size)
+		return;
+
+	nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
+	efi_call_phys2(sys_table_arg->boottime->free_pages, addr, nr_pages);
+}
+
+
+/*
+ * Check the cmdline for a LILO-style file= arguments.
+ *
+ * We only support loading a file from the same filesystem as
+ * the kernel image.
+ */
+static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
+					 efi_loaded_image_t *image,
+					 char *cmd_line, char *option_string,
+					 unsigned long max_addr,
+					 unsigned long *load_addr,
+					 unsigned long *load_size)
+{
+	struct file_info *files;
+	unsigned long file_addr;
+	efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
+	u64 file_size_total;
+	efi_file_io_interface_t *io;
+	efi_file_handle_t *fh;
+	efi_status_t status;
+	int nr_files;
+	char *str;
+	int i, j, k;
+
+	file_addr = 0;
+	file_size_total = 0;
+
+	str = cmd_line;
+
+	j = 0;			/* See close_handles */
+
+	if (!load_addr || !load_size)
+		return EFI_INVALID_PARAMETER;
+
+	*load_addr = 0;
+	*load_size = 0;
+
+	if (!str || !*str)
+		return EFI_SUCCESS;
+
+	for (nr_files = 0; *str; nr_files++) {
+		str = strstr(str, option_string);
+		if (!str)
+			break;
+
+		str += strlen(option_string);
+
+		/* Skip any leading slashes */
+		while (*str == '/' || *str == '\\')
+			str++;
+
+		while (*str && *str != ' ' && *str != '\n')
+			str++;
+	}
+
+	if (!nr_files)
+		return EFI_SUCCESS;
+
+	status = efi_call_phys3(sys_table_arg->boottime->allocate_pool,
+				EFI_LOADER_DATA,
+				nr_files * sizeof(*files),
+				(void **)&files);
+	if (status != EFI_SUCCESS) {
+		efi_printk(sys_table_arg, "Failed to alloc mem for file handle list\n");
+		goto fail;
+	}
+
+	str = cmd_line;
+	for (i = 0; i < nr_files; i++) {
+		struct file_info *file;
+		efi_file_handle_t *h;
+		efi_file_info_t *info;
+		efi_char16_t filename_16[256];
+		unsigned long info_sz;
+		efi_guid_t info_guid = EFI_FILE_INFO_ID;
+		efi_char16_t *p;
+		u64 file_sz;
+
+		str = strstr(str, option_string);
+		if (!str)
+			break;
+
+		str += strlen(option_string);
+
+		file = &files[i];
+		p = filename_16;
+
+		/* Skip any leading slashes */
+		while (*str == '/' || *str == '\\')
+			str++;
+
+		while (*str && *str != ' ' && *str != '\n') {
+			if ((u8 *)p >= (u8 *)filename_16 + sizeof(filename_16))
+				break;
+
+			if (*str == '/') {
+				*p++ = '\\';
+				str++;
+			} else {
+				*p++ = *str++;
+			}
+		}
+
+		*p = '\0';
+
+		/* Only open the volume once. */
+		if (!i) {
+			efi_boot_services_t *boottime;
+
+			boottime = sys_table_arg->boottime;
+
+			status = efi_call_phys3(boottime->handle_protocol,
+					image->device_handle, &fs_proto,
+						(void **)&io);
+			if (status != EFI_SUCCESS) {
+				efi_printk(sys_table_arg, "Failed to handle fs_proto\n");
+				goto free_files;
+			}
+
+			status = efi_call_phys2(io->open_volume, io, &fh);
+			if (status != EFI_SUCCESS) {
+				efi_printk(sys_table_arg, "Failed to open volume\n");
+				goto free_files;
+			}
+		}
+
+		status = efi_call_phys5(fh->open, fh, &h, filename_16,
+					EFI_FILE_MODE_READ, (u64)0);
+		if (status != EFI_SUCCESS) {
+			efi_printk(sys_table_arg, "Failed to open file: ");
+			efi_char16_printk(sys_table_arg, filename_16);
+			efi_printk(sys_table_arg, "\n");
+			goto close_handles;
+		}
+
+		file->handle = h;
+
+		info_sz = 0;
+		status = efi_call_phys4(h->get_info, h, &info_guid,
+					&info_sz, NULL);
+		if (status != EFI_BUFFER_TOO_SMALL) {
+			efi_printk(sys_table_arg, "Failed to get file info size\n");
+			goto close_handles;
+		}
+
+grow:
+		status = efi_call_phys3(sys_table_arg->boottime->allocate_pool,
+					EFI_LOADER_DATA, info_sz,
+					(void **)&info);
+		if (status != EFI_SUCCESS) {
+			efi_printk(sys_table_arg, "Failed to alloc mem for file info\n");
+			goto close_handles;
+		}
+
+		status = efi_call_phys4(h->get_info, h, &info_guid,
+					&info_sz, info);
+		if (status == EFI_BUFFER_TOO_SMALL) {
+			efi_call_phys1(sys_table_arg->boottime->free_pool,
+				       info);
+			goto grow;
+		}
+
+		file_sz = info->file_size;
+		efi_call_phys1(sys_table_arg->boottime->free_pool, info);
+
+		if (status != EFI_SUCCESS) {
+			efi_printk(sys_table_arg, "Failed to get file info\n");
+			goto close_handles;
+		}
+
+		file->size = file_sz;
+		file_size_total += file_sz;
+	}
+
+	if (file_size_total) {
+		unsigned long addr;
+
+		/*
+		 * Multiple files need to be at consecutive addresses in memory,
+		 * so allocate enough memory for all the files.  This is used
+		 * for loading multiple files.
+		 */
+		status = efi_high_alloc(sys_table_arg, file_size_total, 0x1000,
+				    &file_addr, max_addr);
+		if (status != EFI_SUCCESS) {
+			efi_printk(sys_table_arg, "Failed to alloc highmem for files\n");
+			goto close_handles;
+		}
+
+		/* We've run out of free low memory. */
+		if (file_addr > max_addr) {
+			efi_printk(sys_table_arg, "We've run out of free low memory\n");
+			status = EFI_INVALID_PARAMETER;
+			goto free_file_total;
+		}
+
+		addr = file_addr;
+		for (j = 0; j < nr_files; j++) {
+			unsigned long size;
+
+			size = files[j].size;
+			while (size) {
+				unsigned long chunksize;
+				if (size > EFI_READ_CHUNK_SIZE)
+					chunksize = EFI_READ_CHUNK_SIZE;
+				else
+					chunksize = size;
+				status = efi_call_phys3(fh->read,
+							files[j].handle,
+							&chunksize,
+							(void *)addr);
+				if (status != EFI_SUCCESS) {
+					efi_printk(sys_table_arg, "Failed to read file\n");
+					goto free_file_total;
+				}
+				addr += chunksize;
+				size -= chunksize;
+			}
+
+			efi_call_phys1(fh->close, files[j].handle);
+		}
+
+	}
+
+	efi_call_phys1(sys_table_arg->boottime->free_pool, files);
+
+	*load_addr = file_addr;
+	*load_size = file_size_total;
+
+	return status;
+
+free_file_total:
+	efi_free(sys_table_arg, file_size_total, file_addr);
+
+close_handles:
+	for (k = j; k < i; k++)
+		efi_call_phys1(fh->close, files[k].handle);
+free_files:
+	efi_call_phys1(sys_table_arg->boottime->free_pool, files);
+fail:
+	*load_addr = 0;
+	*load_size = 0;
+
+	return status;
+}
+/*
+ * Relocate a kernel image, either compressed or uncompressed.
+ * In the ARM64 case, all kernel images are currently
+ * uncompressed, and as such when we relocate it we need to
+ * allocate additional space for the BSS segment. Any low
+ * memory that this function should avoid needs to be
+ * unavailable in the EFI memory map, as if the preferred
+ * address is not available the lowest available address will
+ * be used.
+ */
+static efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg,
+					unsigned long *image_addr,
+					unsigned long image_size,
+					unsigned long alloc_size,
+					unsigned long preferred_addr,
+					unsigned long alignment)
+{
+	unsigned long cur_image_addr;
+	unsigned long new_addr = 0;
+	efi_status_t status;
+	unsigned long nr_pages;
+	efi_physical_addr_t efi_addr = preferred_addr;
+
+	if (!image_addr || !image_size || !alloc_size)
+		return EFI_INVALID_PARAMETER;
+	if (alloc_size < image_size)
+		return EFI_INVALID_PARAMETER;
+
+	cur_image_addr = *image_addr;
+
+	/*
+	 * The EFI firmware loader could have placed the kernel image
+	 * anywhere in memory, but the kernel has restrictions on the
+	 * max physical address it can run at.  Some architectures
+	 * also have a prefered address, so first try to relocate
+	 * to the preferred address.  If that fails, allocate as low
+	 * as possible while respecting the required alignment.
+	 */
+	nr_pages = round_up(alloc_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE;
+	status = efi_call_phys4(sys_table_arg->boottime->allocate_pages,
+				EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
+				nr_pages, &efi_addr);
+	new_addr = efi_addr;
+	/*
+	 * If preferred address allocation failed allocate as low as
+	 * possible.
+	 */
+	if (status != EFI_SUCCESS) {
+		status = efi_low_alloc(sys_table_arg, alloc_size, alignment,
+				       &new_addr);
+	}
+	if (status != EFI_SUCCESS) {
+		efi_printk(sys_table_arg, "ERROR: Failed to allocate usable memory for kernel.\n");
+		return status;
+	}
+
+	/*
+	 * We know source/dest won't overlap since both memory ranges
+	 * have been allocated by UEFI, so we can safely use memcpy.
+	 */
+	memcpy((void *)new_addr, (void *)cur_image_addr, image_size);
+
+	/* Return the new address of the relocated image. */
+	*image_addr = new_addr;
+
+	return status;
+}
+
+/*
+ * Convert the unicode UEFI command line to ASCII to pass to kernel.
+ * Size of memory allocated return in *cmd_line_len.
+ * Returns NULL on error.
+ */
+static char *efi_convert_cmdline_to_ascii(efi_system_table_t *sys_table_arg,
+				      efi_loaded_image_t *image,
+				      int *cmd_line_len)
+{
+	u16 *s2;
+	u8 *s1 = NULL;
+	unsigned long cmdline_addr = 0;
+	int load_options_size = image->load_options_size / 2; /* ASCII */
+	void *options = image->load_options;
+	int options_size = 0;
+	efi_status_t status;
+	int i;
+	u16 zero = 0;
+
+	if (options) {
+		s2 = options;
+		while (*s2 && *s2 != '\n' && options_size < load_options_size) {
+			s2++;
+			options_size++;
+		}
+	}
+
+	if (options_size == 0) {
+		/* No command line options, so return empty string*/
+		options_size = 1;
+		options = &zero;
+	}
+
+	options_size++;  /* NUL termination */
+#ifdef CONFIG_ARM
+	/*
+	 * For ARM, allocate at a high address to avoid reserved
+	 * regions at low addresses that we don't know the specfics of
+	 * at the time we are processing the command line.
+	 */
+	status = efi_high_alloc(sys_table_arg, options_size, 0,
+			    &cmdline_addr, 0xfffff000);
+#else
+	status = efi_low_alloc(sys_table_arg, options_size, 0,
+			    &cmdline_addr);
+#endif
+	if (status != EFI_SUCCESS)
+		return NULL;
+
+	s1 = (u8 *)cmdline_addr;
+	s2 = (u16 *)options;
+
+	for (i = 0; i < options_size - 1; i++)
+		*s1++ = *s2++;
+
+	*s1 = '\0';
+
+	*cmd_line_len = options_size;
+	return (char *)cmdline_addr;
+}
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 5145fa3..2e2fbde 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -13,11 +13,27 @@
  * This file is released under the GPLv2.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kobject.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/efi.h>
+#include <linux/io.h>
+
+struct efi __read_mostly efi = {
+	.mps        = EFI_INVALID_TABLE_ADDR,
+	.acpi       = EFI_INVALID_TABLE_ADDR,
+	.acpi20     = EFI_INVALID_TABLE_ADDR,
+	.smbios     = EFI_INVALID_TABLE_ADDR,
+	.sal_systab = EFI_INVALID_TABLE_ADDR,
+	.boot_info  = EFI_INVALID_TABLE_ADDR,
+	.hcdp       = EFI_INVALID_TABLE_ADDR,
+	.uga        = EFI_INVALID_TABLE_ADDR,
+	.uv_systab  = EFI_INVALID_TABLE_ADDR,
+};
+EXPORT_SYMBOL(efi);
 
 static struct kobject *efi_kobj;
 static struct kobject *efivars_kobj;
@@ -132,3 +148,127 @@
 }
 
 subsys_initcall(efisubsys_init);
+
+
+/*
+ * We can't ioremap data in EFI boot services RAM, because we've already mapped
+ * it as RAM.  So, look it up in the existing EFI memory map instead.  Only
+ * callable after efi_enter_virtual_mode and before efi_free_boot_services.
+ */
+void __iomem *efi_lookup_mapped_addr(u64 phys_addr)
+{
+	struct efi_memory_map *map;
+	void *p;
+	map = efi.memmap;
+	if (!map)
+		return NULL;
+	if (WARN_ON(!map->map))
+		return NULL;
+	for (p = map->map; p < map->map_end; p += map->desc_size) {
+		efi_memory_desc_t *md = p;
+		u64 size = md->num_pages << EFI_PAGE_SHIFT;
+		u64 end = md->phys_addr + size;
+		if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
+		    md->type != EFI_BOOT_SERVICES_CODE &&
+		    md->type != EFI_BOOT_SERVICES_DATA)
+			continue;
+		if (!md->virt_addr)
+			continue;
+		if (phys_addr >= md->phys_addr && phys_addr < end) {
+			phys_addr += md->virt_addr - md->phys_addr;
+			return (__force void __iomem *)(unsigned long)phys_addr;
+		}
+	}
+	return NULL;
+}
+
+static __initdata efi_config_table_type_t common_tables[] = {
+	{ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
+	{ACPI_TABLE_GUID, "ACPI", &efi.acpi},
+	{HCDP_TABLE_GUID, "HCDP", &efi.hcdp},
+	{MPS_TABLE_GUID, "MPS", &efi.mps},
+	{SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
+	{SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
+	{UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
+	{NULL_GUID, NULL, 0},
+};
+
+static __init int match_config_table(efi_guid_t *guid,
+				     unsigned long table,
+				     efi_config_table_type_t *table_types)
+{
+	u8 str[EFI_VARIABLE_GUID_LEN + 1];
+	int i;
+
+	if (table_types) {
+		efi_guid_unparse(guid, str);
+
+		for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
+			efi_guid_unparse(&table_types[i].guid, str);
+
+			if (!efi_guidcmp(*guid, table_types[i].guid)) {
+				*(table_types[i].ptr) = table;
+				pr_cont(" %s=0x%lx ",
+					table_types[i].name, table);
+				return 1;
+			}
+		}
+	}
+
+	return 0;
+}
+
+int __init efi_config_init(efi_config_table_type_t *arch_tables)
+{
+	void *config_tables, *tablep;
+	int i, sz;
+
+	if (efi_enabled(EFI_64BIT))
+		sz = sizeof(efi_config_table_64_t);
+	else
+		sz = sizeof(efi_config_table_32_t);
+
+	/*
+	 * Let's see what config tables the firmware passed to us.
+	 */
+	config_tables = early_memremap(efi.systab->tables,
+				       efi.systab->nr_tables * sz);
+	if (config_tables == NULL) {
+		pr_err("Could not map Configuration table!\n");
+		return -ENOMEM;
+	}
+
+	tablep = config_tables;
+	pr_info("");
+	for (i = 0; i < efi.systab->nr_tables; i++) {
+		efi_guid_t guid;
+		unsigned long table;
+
+		if (efi_enabled(EFI_64BIT)) {
+			u64 table64;
+			guid = ((efi_config_table_64_t *)tablep)->guid;
+			table64 = ((efi_config_table_64_t *)tablep)->table;
+			table = table64;
+#ifndef CONFIG_64BIT
+			if (table64 >> 32) {
+				pr_cont("\n");
+				pr_err("Table located above 4GB, disabling EFI.\n");
+				early_iounmap(config_tables,
+					       efi.systab->nr_tables * sz);
+				return -EINVAL;
+			}
+#endif
+		} else {
+			guid = ((efi_config_table_32_t *)tablep)->guid;
+			table = ((efi_config_table_32_t *)tablep)->table;
+		}
+
+		if (!match_config_table(&guid, table, common_tables))
+			match_config_table(&guid, table, arch_tables);
+
+		tablep += sz;
+	}
+	pr_cont("\n");
+	early_iounmap(config_tables, efi.systab->nr_tables * sz);
+	return 0;
+}
diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c
index 8a7432a..933eb02 100644
--- a/drivers/firmware/efi/efivars.c
+++ b/drivers/firmware/efi/efivars.c
@@ -564,7 +564,7 @@
 	return 0;
 }
 
-void efivars_sysfs_exit(void)
+static void efivars_sysfs_exit(void)
 {
 	/* Remove all entries and destroy */
 	__efivar_entry_iter(efivar_sysfs_destroy, &efivar_sysfs_list, NULL, NULL);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index b6ed304..0f04444 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -30,10 +30,6 @@
 	  Selecting this from the architecture code will cause the gpiolib
 	  code to always get built in.
 
-config GPIO_DEVRES
-	def_bool y
-	depends on HAS_IOMEM
-
 
 menuconfig GPIOLIB
 	bool "GPIO Support"
@@ -47,6 +43,10 @@
 
 if GPIOLIB
 
+config GPIO_DEVRES
+	def_bool y
+	depends on HAS_IOMEM
+
 config OF_GPIO
 	def_bool y
 	depends on OF
@@ -129,7 +129,7 @@
 
 config GPIO_EM
 	tristate "Emma Mobile GPIO"
-	depends on ARM
+	depends on ARM && OF_GPIO
 	help
 	  Say yes here to support GPIO on Renesas Emma Mobile SoCs.
 
@@ -213,7 +213,7 @@
 
 config GPIO_PL061
 	bool "PrimeCell PL061 GPIO support"
-	depends on ARM && ARM_AMBA
+	depends on ARM_AMBA
 	select GENERIC_IRQ_CHIP
 	help
 	  Say yes here to support the PrimeCell PL061 GPIO device
@@ -320,6 +320,15 @@
 
 	  If unsure, say N.
 
+config GPIO_IOP
+	tristate "Intel IOP GPIO"
+	depends on ARM && (ARCH_IOP32X || ARCH_IOP33X)
+	help
+	  Say yes here to support the GPIO functionality of a number of Intel
+	  IOP32X or IOP33X.
+
+	  If unsure, say N.
+
 config GPIO_VX855
 	tristate "VIA VX855/VX875 GPIO"
 	depends on PCI
@@ -360,6 +369,10 @@
 	  Select this to support Aeroflex Gaisler GRGPIO cores from the GRLIB
 	  VHDL IP core library.
 
+config GPIO_TB10X
+	bool
+	select OF_GPIO
+
 comment "I2C GPIO expanders:"
 
 config GPIO_ARIZONA
@@ -612,12 +625,12 @@
 
 	  If unsure, say N
 
-config GPIO_LANGWELL
-	bool "Intel Langwell/Penwell GPIO support"
+config GPIO_INTEL_MID
+	bool "Intel Mid GPIO support"
 	depends on PCI && X86
 	select IRQ_DOMAIN
 	help
-	  Say Y here to support Intel Langwell/Penwell GPIO.
+	  Say Y here to support Intel Mid GPIO.
 
 config GPIO_PCH
 	tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7223/ML7831) GPIO"
@@ -703,7 +716,7 @@
 comment "AC97 GPIO expanders:"
 
 config GPIO_UCB1400
-	bool "Philips UCB1400 GPIO"
+	tristate "Philips UCB1400 GPIO"
 	depends on UCB1400_CORE
 	help
 	  This enables support for the Philips UCB1400 GPIO pins.
@@ -759,6 +772,12 @@
 	  Enable support for GPIO on intel MSIC controllers found in
 	  intel MID devices
 
+config GPIO_BCM_KONA
+	bool "Broadcom Kona GPIO"
+	depends on OF_GPIO
+	help
+	  Turn on GPIO support for Broadcom "Kona" chips.
+
 comment "USB GPIO expanders:"
 
 config GPIO_VIPERBOARD
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 98e23eb..7971e36 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -16,6 +16,7 @@
 obj-$(CONFIG_GPIO_ADP5588)	+= gpio-adp5588.o
 obj-$(CONFIG_GPIO_AMD8111)	+= gpio-amd8111.o
 obj-$(CONFIG_GPIO_ARIZONA)	+= gpio-arizona.o
+obj-$(CONFIG_GPIO_BCM_KONA)	+= gpio-bcm-kona.o
 obj-$(CONFIG_GPIO_BT8XX)	+= gpio-bt8xx.o
 obj-$(CONFIG_GPIO_CLPS711X)	+= gpio-clps711x.o
 obj-$(CONFIG_GPIO_CS5535)	+= gpio-cs5535.o
@@ -28,11 +29,12 @@
 obj-$(CONFIG_GPIO_GE_FPGA)	+= gpio-ge.o
 obj-$(CONFIG_GPIO_GRGPIO)	+= gpio-grgpio.o
 obj-$(CONFIG_GPIO_ICH)		+= gpio-ich.o
+obj-$(CONFIG_GPIO_IOP)		+= gpio-iop.o
 obj-$(CONFIG_GPIO_IT8761E)	+= gpio-it8761e.o
 obj-$(CONFIG_GPIO_JANZ_TTL)	+= gpio-janz-ttl.o
 obj-$(CONFIG_GPIO_KEMPLD)	+= gpio-kempld.o
 obj-$(CONFIG_ARCH_KS8695)	+= gpio-ks8695.o
-obj-$(CONFIG_GPIO_LANGWELL)	+= gpio-langwell.o
+obj-$(CONFIG_GPIO_INTEL_MID)	+= gpio-intel-mid.o
 obj-$(CONFIG_ARCH_LPC32XX)	+= gpio-lpc32xx.o
 obj-$(CONFIG_GPIO_LYNXPOINT)	+= gpio-lynxpoint.o
 obj-$(CONFIG_GPIO_MAX730X)	+= gpio-max730x.o
@@ -71,6 +73,7 @@
 obj-$(CONFIG_GPIO_STMPE)	+= gpio-stmpe.o
 obj-$(CONFIG_GPIO_STP_XWAY)	+= gpio-stp-xway.o
 obj-$(CONFIG_GPIO_SX150X)	+= gpio-sx150x.o
+obj-$(CONFIG_GPIO_TB10X)	+= gpio-tb10x.o
 obj-$(CONFIG_GPIO_TC3589X)	+= gpio-tc3589x.o
 obj-$(CONFIG_ARCH_TEGRA)	+= gpio-tegra.o
 obj-$(CONFIG_GPIO_TIMBERDALE)	+= gpio-timberdale.o
diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c
index 3e7812f..307464f 100644
--- a/drivers/gpio/devres.c
+++ b/drivers/gpio/devres.c
@@ -15,10 +15,95 @@
  */
 
 #include <linux/module.h>
+#include <linux/err.h>
 #include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/device.h>
 #include <linux/gfp.h>
 
+static void devm_gpiod_release(struct device *dev, void *res)
+{
+	struct gpio_desc **desc = res;
+
+	gpiod_put(*desc);
+}
+
+static int devm_gpiod_match(struct device *dev, void *res, void *data)
+{
+	struct gpio_desc **this = res, **gpio = data;
+
+	return *this == *gpio;
+}
+
+/**
+ * devm_gpiod_get - Resource-managed gpiod_get()
+ * @dev:	GPIO consumer
+ * @con_id:	function within the GPIO consumer
+ *
+ * Managed gpiod_get(). GPIO descriptors returned from this function are
+ * automatically disposed on driver detach. See gpiod_get() for detailed
+ * information about behavior and return values.
+ */
+struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
+					      const char *con_id)
+{
+	return devm_gpiod_get_index(dev, con_id, 0);
+}
+EXPORT_SYMBOL(devm_gpiod_get);
+
+/**
+ * devm_gpiod_get_index - Resource-managed gpiod_get_index()
+ * @dev:	GPIO consumer
+ * @con_id:	function within the GPIO consumer
+ * @idx:	index of the GPIO to obtain in the consumer
+ *
+ * Managed gpiod_get_index(). GPIO descriptors returned from this function are
+ * automatically disposed on driver detach. See gpiod_get_index() for detailed
+ * information about behavior and return values.
+ */
+struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
+						    const char *con_id,
+						    unsigned int idx)
+{
+	struct gpio_desc **dr;
+	struct gpio_desc *desc;
+
+	dr = devres_alloc(devm_gpiod_release, sizeof(struct gpiod_desc *),
+			  GFP_KERNEL);
+	if (!dr)
+		return ERR_PTR(-ENOMEM);
+
+	desc = gpiod_get_index(dev, con_id, idx);
+	if (IS_ERR(desc)) {
+		devres_free(dr);
+		return desc;
+	}
+
+	*dr = desc;
+	devres_add(dev, dr);
+
+	return desc;
+}
+EXPORT_SYMBOL(devm_gpiod_get_index);
+
+/**
+ * devm_gpiod_put - Resource-managed gpiod_put()
+ * @desc:	GPIO descriptor to dispose of
+ *
+ * Dispose of a GPIO descriptor obtained with devm_gpiod_get() or
+ * devm_gpiod_get_index(). Normally this function will not be called as the GPIO
+ * will be disposed of by the resource management code.
+ */
+void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
+{
+	WARN_ON(devres_release(dev, devm_gpiod_release, devm_gpiod_match,
+		&desc));
+}
+EXPORT_SYMBOL(devm_gpiod_put);
+
+
+
+
 static void devm_gpio_release(struct device *dev, void *res)
 {
 	unsigned *gpio = res;
diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
index 5d518d5..1e04bf9 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -176,7 +176,6 @@
 	return ret;
 
 exit_destroy:
-	spi_set_drvdata(spi, NULL);
 	mutex_destroy(&chip->lock);
 	return ret;
 }
@@ -190,8 +189,6 @@
 	if (chip == NULL)
 		return -ENODEV;
 
-	spi_set_drvdata(spi, NULL);
-
 	ret = gpiochip_remove(&chip->gpio_chip);
 	if (!ret)
 		mutex_destroy(&chip->lock);
@@ -212,7 +209,7 @@
 	.driver = {
 		.name		= "74x164",
 		.owner		= THIS_MODULE,
-		.of_match_table	= of_match_ptr(gen_74x164_dt_ids),
+		.of_match_table	= gen_74x164_dt_ids,
 	},
 	.probe		= gen_74x164_probe,
 	.remove		= gen_74x164_remove,
diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
index c0f3fc4..b204033 100644
--- a/drivers/gpio/gpio-adnp.c
+++ b/drivers/gpio/gpio-adnp.c
@@ -325,9 +325,9 @@
 		pending &= isr & ier;
 
 		for_each_set_bit(bit, &pending, 8) {
-			unsigned int virq;
-			virq = irq_find_mapping(adnp->domain, base + bit);
-			handle_nested_irq(virq);
+			unsigned int child_irq;
+			child_irq = irq_find_mapping(adnp->domain, base + bit);
+			handle_nested_irq(child_irq);
 		}
 	}
 
@@ -594,7 +594,7 @@
 	.driver = {
 		.name = "gpio-adnp",
 		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(adnp_of_match),
+		.of_match_table = adnp_of_match,
 	},
 	.probe = adnp_i2c_probe,
 	.remove = adnp_i2c_remove,
diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
index fa8b6a7..dceb5dc 100644
--- a/drivers/gpio/gpio-arizona.c
+++ b/drivers/gpio/gpio-arizona.c
@@ -109,10 +109,14 @@
 	arizona_gpio->arizona = arizona;
 	arizona_gpio->gpio_chip = template_chip;
 	arizona_gpio->gpio_chip.dev = &pdev->dev;
+#ifdef CONFIG_OF_GPIO
+	arizona_gpio->gpio_chip.of_node = arizona->dev->of_node;
+#endif
 
 	switch (arizona->type) {
 	case WM5102:
 	case WM5110:
+	case WM8997:
 		arizona_gpio->gpio_chip.ngpio = 5;
 		break;
 	default:
diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c
new file mode 100644
index 0000000..72c927d
--- /dev/null
+++ b/drivers/gpio/gpio-bcm-kona.c
@@ -0,0 +1,640 @@
+/*
+ * Copyright (C) 2012-2013 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/module.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+
+#define BCM_GPIO_PASSWD				0x00a5a501
+#define GPIO_PER_BANK				32
+#define GPIO_MAX_BANK_NUM			8
+
+#define GPIO_BANK(gpio)				((gpio) >> 5)
+#define GPIO_BIT(gpio)				((gpio) & (GPIO_PER_BANK - 1))
+
+#define GPIO_OUT_STATUS(bank)			(0x00000000 + ((bank) << 2))
+#define GPIO_IN_STATUS(bank)			(0x00000020 + ((bank) << 2))
+#define GPIO_OUT_SET(bank)			(0x00000040 + ((bank) << 2))
+#define GPIO_OUT_CLEAR(bank)			(0x00000060 + ((bank) << 2))
+#define GPIO_INT_STATUS(bank)			(0x00000080 + ((bank) << 2))
+#define GPIO_INT_MASK(bank)			(0x000000a0 + ((bank) << 2))
+#define GPIO_INT_MSKCLR(bank)			(0x000000c0 + ((bank) << 2))
+#define GPIO_CONTROL(bank)			(0x00000100 + ((bank) << 2))
+#define GPIO_PWD_STATUS(bank)			(0x00000500 + ((bank) << 2))
+
+#define GPIO_GPPWR_OFFSET			0x00000520
+
+#define GPIO_GPCTR0_DBR_SHIFT			5
+#define GPIO_GPCTR0_DBR_MASK			0x000001e0
+
+#define GPIO_GPCTR0_ITR_SHIFT			3
+#define GPIO_GPCTR0_ITR_MASK			0x00000018
+#define GPIO_GPCTR0_ITR_CMD_RISING_EDGE		0x00000001
+#define GPIO_GPCTR0_ITR_CMD_FALLING_EDGE	0x00000002
+#define GPIO_GPCTR0_ITR_CMD_BOTH_EDGE		0x00000003
+
+#define GPIO_GPCTR0_IOTR_MASK			0x00000001
+#define GPIO_GPCTR0_IOTR_CMD_0UTPUT		0x00000000
+#define GPIO_GPCTR0_IOTR_CMD_INPUT		0x00000001
+
+#define GPIO_GPCTR0_DB_ENABLE_MASK		0x00000100
+
+#define LOCK_CODE				0xffffffff
+#define UNLOCK_CODE				0x00000000
+
+struct bcm_kona_gpio {
+	void __iomem *reg_base;
+	int num_bank;
+	spinlock_t lock;
+	struct gpio_chip gpio_chip;
+	struct irq_domain *irq_domain;
+	struct bcm_kona_gpio_bank *banks;
+	struct platform_device *pdev;
+};
+
+struct bcm_kona_gpio_bank {
+	int id;
+	int irq;
+	/* Used in the interrupt handler */
+	struct bcm_kona_gpio *kona_gpio;
+};
+
+static inline struct bcm_kona_gpio *to_kona_gpio(struct gpio_chip *chip)
+{
+	return container_of(chip, struct bcm_kona_gpio, gpio_chip);
+}
+
+static void bcm_kona_gpio_set_lockcode_bank(void __iomem *reg_base,
+					    int bank_id, int lockcode)
+{
+	writel(BCM_GPIO_PASSWD, reg_base + GPIO_GPPWR_OFFSET);
+	writel(lockcode, reg_base + GPIO_PWD_STATUS(bank_id));
+}
+
+static inline void bcm_kona_gpio_lock_bank(void __iomem *reg_base, int bank_id)
+{
+	bcm_kona_gpio_set_lockcode_bank(reg_base, bank_id, LOCK_CODE);
+}
+
+static inline void bcm_kona_gpio_unlock_bank(void __iomem *reg_base,
+					     int bank_id)
+{
+	bcm_kona_gpio_set_lockcode_bank(reg_base, bank_id, UNLOCK_CODE);
+}
+
+static void bcm_kona_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
+{
+	struct bcm_kona_gpio *kona_gpio;
+	void __iomem *reg_base;
+	int bank_id = GPIO_BANK(gpio);
+	int bit = GPIO_BIT(gpio);
+	u32 val, reg_offset;
+	unsigned long flags;
+
+	kona_gpio = to_kona_gpio(chip);
+	reg_base = kona_gpio->reg_base;
+	spin_lock_irqsave(&kona_gpio->lock, flags);
+	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+	/* determine the GPIO pin direction */
+	val = readl(reg_base + GPIO_CONTROL(gpio));
+	val &= GPIO_GPCTR0_IOTR_MASK;
+
+	/* this function only applies to output pin */
+	if (GPIO_GPCTR0_IOTR_CMD_INPUT == val)
+		goto out;
+
+	reg_offset = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
+
+	val = readl(reg_base + reg_offset);
+	val |= BIT(bit);
+	writel(val, reg_base + reg_offset);
+
+out:
+	bcm_kona_gpio_lock_bank(reg_base, bank_id);
+	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+}
+
+static int bcm_kona_gpio_get(struct gpio_chip *chip, unsigned gpio)
+{
+	struct bcm_kona_gpio *kona_gpio;
+	void __iomem *reg_base;
+	int bank_id = GPIO_BANK(gpio);
+	int bit = GPIO_BIT(gpio);
+	u32 val, reg_offset;
+	unsigned long flags;
+
+	kona_gpio = to_kona_gpio(chip);
+	reg_base = kona_gpio->reg_base;
+	spin_lock_irqsave(&kona_gpio->lock, flags);
+	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+	/* determine the GPIO pin direction */
+	val = readl(reg_base + GPIO_CONTROL(gpio));
+	val &= GPIO_GPCTR0_IOTR_MASK;
+
+	/* read the GPIO bank status */
+	reg_offset = (GPIO_GPCTR0_IOTR_CMD_INPUT == val) ?
+	    GPIO_IN_STATUS(bank_id) : GPIO_OUT_STATUS(bank_id);
+	val = readl(reg_base + reg_offset);
+
+	bcm_kona_gpio_lock_bank(reg_base, bank_id);
+	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+
+	/* return the specified bit status */
+	return !!(val & bit);
+}
+
+static int bcm_kona_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+	struct bcm_kona_gpio *kona_gpio;
+	void __iomem *reg_base;
+	u32 val;
+	unsigned long flags;
+	int bank_id = GPIO_BANK(gpio);
+
+	kona_gpio = to_kona_gpio(chip);
+	reg_base = kona_gpio->reg_base;
+	spin_lock_irqsave(&kona_gpio->lock, flags);
+	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+	val = readl(reg_base + GPIO_CONTROL(gpio));
+	val &= ~GPIO_GPCTR0_IOTR_MASK;
+	val |= GPIO_GPCTR0_IOTR_CMD_INPUT;
+	writel(val, reg_base + GPIO_CONTROL(gpio));
+
+	bcm_kona_gpio_lock_bank(reg_base, bank_id);
+	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+
+	return 0;
+}
+
+static int bcm_kona_gpio_direction_output(struct gpio_chip *chip,
+					  unsigned gpio, int value)
+{
+	struct bcm_kona_gpio *kona_gpio;
+	void __iomem *reg_base;
+	int bank_id = GPIO_BANK(gpio);
+	int bit = GPIO_BIT(gpio);
+	u32 val, reg_offset;
+	unsigned long flags;
+
+	kona_gpio = to_kona_gpio(chip);
+	reg_base = kona_gpio->reg_base;
+	spin_lock_irqsave(&kona_gpio->lock, flags);
+	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+	val = readl(reg_base + GPIO_CONTROL(gpio));
+	val &= ~GPIO_GPCTR0_IOTR_MASK;
+	val |= GPIO_GPCTR0_IOTR_CMD_0UTPUT;
+	writel(val, reg_base + GPIO_CONTROL(gpio));
+	reg_offset = value ? GPIO_OUT_SET(bank_id) : GPIO_OUT_CLEAR(bank_id);
+
+	val = readl(reg_base + reg_offset);
+	val |= BIT(bit);
+	writel(val, reg_base + reg_offset);
+
+	bcm_kona_gpio_lock_bank(reg_base, bank_id);
+	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+
+	return 0;
+}
+
+static int bcm_kona_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
+{
+	struct bcm_kona_gpio *kona_gpio;
+
+	kona_gpio = to_kona_gpio(chip);
+	if (gpio >= kona_gpio->gpio_chip.ngpio)
+		return -ENXIO;
+	return irq_create_mapping(kona_gpio->irq_domain, gpio);
+}
+
+static int bcm_kona_gpio_set_debounce(struct gpio_chip *chip, unsigned gpio,
+				      unsigned debounce)
+{
+	struct bcm_kona_gpio *kona_gpio;
+	void __iomem *reg_base;
+	u32 val, res;
+	unsigned long flags;
+	int bank_id = GPIO_BANK(gpio);
+
+	kona_gpio = to_kona_gpio(chip);
+	reg_base = kona_gpio->reg_base;
+	/* debounce must be 1-128ms (or 0) */
+	if ((debounce > 0 && debounce < 1000) || debounce > 128000) {
+		dev_err(chip->dev, "Debounce value %u not in range\n",
+			debounce);
+		return -EINVAL;
+	}
+
+	/* calculate debounce bit value */
+	if (debounce != 0) {
+		/* Convert to ms */
+		debounce /= 1000;
+		/* find the MSB */
+		res = fls(debounce) - 1;
+		/* Check if MSB-1 is set (round up or down) */
+		if (res > 0 && (debounce & BIT(res - 1)))
+			res++;
+	}
+
+	/* spin lock for read-modify-write of the GPIO register */
+	spin_lock_irqsave(&kona_gpio->lock, flags);
+	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+	val = readl(reg_base + GPIO_CONTROL(gpio));
+	val &= ~GPIO_GPCTR0_DBR_MASK;
+
+	if (debounce == 0) {
+		/* disable debounce */
+		val &= ~GPIO_GPCTR0_DB_ENABLE_MASK;
+	} else {
+		val |= GPIO_GPCTR0_DB_ENABLE_MASK |
+		    (res << GPIO_GPCTR0_DBR_SHIFT);
+	}
+
+	writel(val, reg_base + GPIO_CONTROL(gpio));
+
+	bcm_kona_gpio_lock_bank(reg_base, bank_id);
+	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+
+	return 0;
+}
+
+static struct gpio_chip template_chip = {
+	.label = "bcm-kona-gpio",
+	.owner = THIS_MODULE,
+	.direction_input = bcm_kona_gpio_direction_input,
+	.get = bcm_kona_gpio_get,
+	.direction_output = bcm_kona_gpio_direction_output,
+	.set = bcm_kona_gpio_set,
+	.set_debounce = bcm_kona_gpio_set_debounce,
+	.to_irq = bcm_kona_gpio_to_irq,
+	.base = 0,
+};
+
+static void bcm_kona_gpio_irq_ack(struct irq_data *d)
+{
+	struct bcm_kona_gpio *kona_gpio;
+	void __iomem *reg_base;
+	int gpio = d->hwirq;
+	int bank_id = GPIO_BANK(gpio);
+	int bit = GPIO_BIT(gpio);
+	u32 val;
+	unsigned long flags;
+
+	kona_gpio = irq_data_get_irq_chip_data(d);
+	reg_base = kona_gpio->reg_base;
+	spin_lock_irqsave(&kona_gpio->lock, flags);
+	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+	val = readl(reg_base + GPIO_INT_STATUS(bank_id));
+	val |= BIT(bit);
+	writel(val, reg_base + GPIO_INT_STATUS(bank_id));
+
+	bcm_kona_gpio_lock_bank(reg_base, bank_id);
+	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+}
+
+static void bcm_kona_gpio_irq_mask(struct irq_data *d)
+{
+	struct bcm_kona_gpio *kona_gpio;
+	void __iomem *reg_base;
+	int gpio = d->hwirq;
+	int bank_id = GPIO_BANK(gpio);
+	int bit = GPIO_BIT(gpio);
+	u32 val;
+	unsigned long flags;
+
+	kona_gpio = irq_data_get_irq_chip_data(d);
+	reg_base = kona_gpio->reg_base;
+	spin_lock_irqsave(&kona_gpio->lock, flags);
+	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+	val = readl(reg_base + GPIO_INT_MASK(bank_id));
+	val |= BIT(bit);
+	writel(val, reg_base + GPIO_INT_MASK(bank_id));
+
+	bcm_kona_gpio_lock_bank(reg_base, bank_id);
+	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+}
+
+static void bcm_kona_gpio_irq_unmask(struct irq_data *d)
+{
+	struct bcm_kona_gpio *kona_gpio;
+	void __iomem *reg_base;
+	int gpio = d->hwirq;
+	int bank_id = GPIO_BANK(gpio);
+	int bit = GPIO_BIT(gpio);
+	u32 val;
+	unsigned long flags;
+
+	kona_gpio = irq_data_get_irq_chip_data(d);
+	reg_base = kona_gpio->reg_base;
+	spin_lock_irqsave(&kona_gpio->lock, flags);
+	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+	val = readl(reg_base + GPIO_INT_MSKCLR(bank_id));
+	val |= BIT(bit);
+	writel(val, reg_base + GPIO_INT_MSKCLR(bank_id));
+
+	bcm_kona_gpio_lock_bank(reg_base, bank_id);
+	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+}
+
+static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	struct bcm_kona_gpio *kona_gpio;
+	void __iomem *reg_base;
+	int gpio = d->hwirq;
+	u32 lvl_type;
+	u32 val;
+	unsigned long flags;
+	int bank_id = GPIO_BANK(gpio);
+
+	kona_gpio = irq_data_get_irq_chip_data(d);
+	reg_base = kona_gpio->reg_base;
+	switch (type & IRQ_TYPE_SENSE_MASK) {
+	case IRQ_TYPE_EDGE_RISING:
+		lvl_type = GPIO_GPCTR0_ITR_CMD_RISING_EDGE;
+		break;
+
+	case IRQ_TYPE_EDGE_FALLING:
+		lvl_type = GPIO_GPCTR0_ITR_CMD_FALLING_EDGE;
+		break;
+
+	case IRQ_TYPE_EDGE_BOTH:
+		lvl_type = GPIO_GPCTR0_ITR_CMD_BOTH_EDGE;
+		break;
+
+	case IRQ_TYPE_LEVEL_HIGH:
+	case IRQ_TYPE_LEVEL_LOW:
+		/* BCM GPIO doesn't support level triggering */
+	default:
+		dev_err(kona_gpio->gpio_chip.dev,
+			"Invalid BCM GPIO irq type 0x%x\n", type);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&kona_gpio->lock, flags);
+	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+	val = readl(reg_base + GPIO_CONTROL(gpio));
+	val &= ~GPIO_GPCTR0_ITR_MASK;
+	val |= lvl_type << GPIO_GPCTR0_ITR_SHIFT;
+	writel(val, reg_base + GPIO_CONTROL(gpio));
+
+	bcm_kona_gpio_lock_bank(reg_base, bank_id);
+	spin_unlock_irqrestore(&kona_gpio->lock, flags);
+
+	return 0;
+}
+
+static void bcm_kona_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	void __iomem *reg_base;
+	int bit, bank_id;
+	unsigned long sta;
+	struct bcm_kona_gpio_bank *bank = irq_get_handler_data(irq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+
+	chained_irq_enter(chip, desc);
+
+	/*
+	 * For bank interrupts, we can't use chip_data to store the kona_gpio
+	 * pointer, since GIC needs it for its own purposes. Therefore, we get
+	 * our pointer from the bank structure.
+	 */
+	reg_base = bank->kona_gpio->reg_base;
+	bank_id = bank->id;
+	bcm_kona_gpio_unlock_bank(reg_base, bank_id);
+
+	while ((sta = readl(reg_base + GPIO_INT_STATUS(bank_id)) &
+		    (~(readl(reg_base + GPIO_INT_MASK(bank_id)))))) {
+		for_each_set_bit(bit, &sta, 32) {
+			int hwirq = GPIO_PER_BANK * bank_id + bit;
+			int child_irq =
+				irq_find_mapping(bank->kona_gpio->irq_domain,
+						 hwirq);
+			/*
+			 * Clear interrupt before handler is called so we don't
+			 * miss any interrupt occurred during executing them.
+			 */
+			writel(readl(reg_base + GPIO_INT_STATUS(bank_id)) |
+			       BIT(bit), reg_base + GPIO_INT_STATUS(bank_id));
+			/* Invoke interrupt handler */
+			generic_handle_irq(child_irq);
+		}
+	}
+
+	bcm_kona_gpio_lock_bank(reg_base, bank_id);
+
+	chained_irq_exit(chip, desc);
+}
+
+static struct irq_chip bcm_gpio_irq_chip = {
+	.name = "bcm-kona-gpio",
+	.irq_ack = bcm_kona_gpio_irq_ack,
+	.irq_mask = bcm_kona_gpio_irq_mask,
+	.irq_unmask = bcm_kona_gpio_irq_unmask,
+	.irq_set_type = bcm_kona_gpio_irq_set_type,
+};
+
+static struct __initconst of_device_id bcm_kona_gpio_of_match[] = {
+	{ .compatible = "brcm,kona-gpio" },
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, bcm_kona_gpio_of_match);
+
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpio_lock_class;
+
+static int bcm_kona_gpio_irq_map(struct irq_domain *d, unsigned int irq,
+				 irq_hw_number_t hwirq)
+{
+	int ret;
+
+	ret = irq_set_chip_data(irq, d->host_data);
+	if (ret < 0)
+		return ret;
+	irq_set_lockdep_class(irq, &gpio_lock_class);
+	irq_set_chip_and_handler(irq, &bcm_gpio_irq_chip, handle_simple_irq);
+#ifdef CONFIG_ARM
+	set_irq_flags(irq, IRQF_VALID);
+#else
+	irq_set_noprobe(irq);
+#endif
+
+	return 0;
+}
+
+static void bcm_kona_gpio_irq_unmap(struct irq_domain *d, unsigned int irq)
+{
+	irq_set_chip_and_handler(irq, NULL, NULL);
+	irq_set_chip_data(irq, NULL);
+}
+
+static struct irq_domain_ops bcm_kona_irq_ops = {
+	.map = bcm_kona_gpio_irq_map,
+	.unmap = bcm_kona_gpio_irq_unmap,
+	.xlate = irq_domain_xlate_twocell,
+};
+
+static void bcm_kona_gpio_reset(struct bcm_kona_gpio *kona_gpio)
+{
+	void __iomem *reg_base;
+	int i;
+
+	reg_base = kona_gpio->reg_base;
+	/* disable interrupts and clear status */
+	for (i = 0; i < kona_gpio->num_bank; i++) {
+		bcm_kona_gpio_unlock_bank(reg_base, i);
+		writel(0xffffffff, reg_base + GPIO_INT_MASK(i));
+		writel(0xffffffff, reg_base + GPIO_INT_STATUS(i));
+		bcm_kona_gpio_lock_bank(reg_base, i);
+	}
+}
+
+static int bcm_kona_gpio_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	const struct of_device_id *match;
+	struct resource *res;
+	struct bcm_kona_gpio_bank *bank;
+	struct bcm_kona_gpio *kona_gpio;
+	struct gpio_chip *chip;
+	int ret;
+	int i;
+
+	match = of_match_device(bcm_kona_gpio_of_match, dev);
+	if (!match) {
+		dev_err(dev, "Failed to find gpio controller\n");
+		return -ENODEV;
+	}
+
+	kona_gpio = devm_kzalloc(dev, sizeof(*kona_gpio), GFP_KERNEL);
+	if (!kona_gpio)
+		return -ENOMEM;
+
+	kona_gpio->gpio_chip = template_chip;
+	chip = &kona_gpio->gpio_chip;
+	kona_gpio->num_bank = of_irq_count(dev->of_node);
+	if (kona_gpio->num_bank == 0) {
+		dev_err(dev, "Couldn't determine # GPIO banks\n");
+		return -ENOENT;
+	}
+	if (kona_gpio->num_bank > GPIO_MAX_BANK_NUM) {
+		dev_err(dev, "Too many GPIO banks configured (max=%d)\n",
+			GPIO_MAX_BANK_NUM);
+		return -ENXIO;
+	}
+	kona_gpio->banks = devm_kzalloc(dev,
+					kona_gpio->num_bank *
+					sizeof(*kona_gpio->banks), GFP_KERNEL);
+	if (!kona_gpio->banks)
+		return -ENOMEM;
+
+	kona_gpio->pdev = pdev;
+	platform_set_drvdata(pdev, kona_gpio);
+	chip->of_node = dev->of_node;
+	chip->ngpio = kona_gpio->num_bank * GPIO_PER_BANK;
+
+	kona_gpio->irq_domain = irq_domain_add_linear(dev->of_node,
+						      chip->ngpio,
+						      &bcm_kona_irq_ops,
+						      kona_gpio);
+	if (!kona_gpio->irq_domain) {
+		dev_err(dev, "Couldn't allocate IRQ domain\n");
+		return -ENXIO;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	kona_gpio->reg_base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(kona_gpio->reg_base)) {
+		ret = -ENXIO;
+		goto err_irq_domain;
+	}
+
+	for (i = 0; i < kona_gpio->num_bank; i++) {
+		bank = &kona_gpio->banks[i];
+		bank->id = i;
+		bank->irq = platform_get_irq(pdev, i);
+		bank->kona_gpio = kona_gpio;
+		if (bank->irq < 0) {
+			dev_err(dev, "Couldn't get IRQ for bank %d", i);
+			ret = -ENOENT;
+			goto err_irq_domain;
+		}
+	}
+
+	dev_info(&pdev->dev, "Setting up Kona GPIO\n");
+
+	bcm_kona_gpio_reset(kona_gpio);
+
+	ret = gpiochip_add(chip);
+	if (ret < 0) {
+		dev_err(dev, "Couldn't add GPIO chip -- %d\n", ret);
+		goto err_irq_domain;
+	}
+	for (i = 0; i < chip->ngpio; i++) {
+		int irq = bcm_kona_gpio_to_irq(chip, i);
+		irq_set_lockdep_class(irq, &gpio_lock_class);
+		irq_set_chip_and_handler(irq, &bcm_gpio_irq_chip,
+					 handle_simple_irq);
+#ifdef CONFIG_ARM
+		set_irq_flags(irq, IRQF_VALID);
+#else
+		irq_set_noprobe(irq);
+#endif
+	}
+	for (i = 0; i < kona_gpio->num_bank; i++) {
+		bank = &kona_gpio->banks[i];
+		irq_set_chained_handler(bank->irq, bcm_kona_gpio_irq_handler);
+		irq_set_handler_data(bank->irq, bank);
+	}
+
+	spin_lock_init(&kona_gpio->lock);
+
+	return 0;
+
+err_irq_domain:
+	irq_domain_remove(kona_gpio->irq_domain);
+
+	return ret;
+}
+
+static struct platform_driver bcm_kona_gpio_driver = {
+	.driver = {
+			.name = "bcm-kona-gpio",
+			.owner = THIS_MODULE,
+			.of_match_table = bcm_kona_gpio_of_match,
+	},
+	.probe = bcm_kona_gpio_probe,
+};
+
+module_platform_driver(bcm_kona_gpio_driver);
+
+MODULE_AUTHOR("Broadcom");
+MODULE_DESCRIPTION("Broadcom Kona GPIO Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpio/gpio-bt8xx.c b/drivers/gpio/gpio-bt8xx.c
index 8369e71..9dfe36f 100644
--- a/drivers/gpio/gpio-bt8xx.c
+++ b/drivers/gpio/gpio-bt8xx.c
@@ -228,7 +228,6 @@
 err_release_mem:
 	release_mem_region(pci_resource_start(dev, 0),
 			   pci_resource_len(dev, 0));
-	pci_set_drvdata(dev, NULL);
 err_disable:
 	pci_disable_device(dev);
 err_freebg:
@@ -252,7 +251,6 @@
 			   pci_resource_len(pdev, 0));
 	pci_disable_device(pdev);
 
-	pci_set_drvdata(pdev, NULL);
 	kfree(bg);
 }
 
diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c
index 0edaf2c..0924f20 100644
--- a/drivers/gpio/gpio-clps711x.c
+++ b/drivers/gpio/gpio-clps711x.c
@@ -87,7 +87,7 @@
 	.driver	= {
 		.name		= "clps711x-gpio",
 		.owner		= THIS_MODULE,
-		.of_match_table	= of_match_ptr(clps711x_gpio_ids),
+		.of_match_table	= clps711x_gpio_ids,
 	},
 	.probe	= clps711x_gpio_probe,
 	.remove	= clps711x_gpio_remove,
diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c
index 17df6db..8847adf 100644
--- a/drivers/gpio/gpio-davinci.c
+++ b/drivers/gpio/gpio-davinci.c
@@ -15,8 +15,9 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
-
-#include <asm/mach/irq.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/gpio-davinci.h>
 
 struct davinci_gpio_regs {
 	u32	dir;
@@ -31,13 +32,14 @@
 	u32	intstat;
 };
 
+#define BINTEN	0x8 /* GPIO Interrupt Per-Bank Enable Register */
+
 #define chip2controller(chip)	\
 	container_of(chip, struct davinci_gpio_controller, chip)
 
-static struct davinci_gpio_controller chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)];
 static void __iomem *gpio_base;
 
-static struct davinci_gpio_regs __iomem __init *gpio2regs(unsigned gpio)
+static struct davinci_gpio_regs __iomem *gpio2regs(unsigned gpio)
 {
 	void __iomem *ptr;
 
@@ -65,7 +67,7 @@
 	return g;
 }
 
-static int __init davinci_gpio_irq_setup(void);
+static int davinci_gpio_irq_setup(struct platform_device *pdev);
 
 /*--------------------------------------------------------------------------*/
 
@@ -131,33 +133,53 @@
 	__raw_writel((1 << offset), value ? &g->set_data : &g->clr_data);
 }
 
-static int __init davinci_gpio_setup(void)
+static int davinci_gpio_probe(struct platform_device *pdev)
 {
 	int i, base;
 	unsigned ngpio;
-	struct davinci_soc_info *soc_info = &davinci_soc_info;
-	struct davinci_gpio_regs *regs;
+	struct davinci_gpio_controller *chips;
+	struct davinci_gpio_platform_data *pdata;
+	struct davinci_gpio_regs __iomem *regs;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
 
-	if (soc_info->gpio_type != GPIO_TYPE_DAVINCI)
-		return 0;
+	pdata = dev->platform_data;
+	if (!pdata) {
+		dev_err(dev, "No platform data found\n");
+		return -EINVAL;
+	}
 
 	/*
 	 * The gpio banks conceptually expose a segmented bitmap,
 	 * and "ngpio" is one more than the largest zero-based
 	 * bit index that's valid.
 	 */
-	ngpio = soc_info->gpio_num;
+	ngpio = pdata->ngpio;
 	if (ngpio == 0) {
-		pr_err("GPIO setup:  how many GPIOs?\n");
+		dev_err(dev, "How many GPIOs?\n");
 		return -EINVAL;
 	}
 
 	if (WARN_ON(DAVINCI_N_GPIO < ngpio))
 		ngpio = DAVINCI_N_GPIO;
 
-	gpio_base = ioremap(soc_info->gpio_base, SZ_4K);
-	if (WARN_ON(!gpio_base))
+	chips = devm_kzalloc(dev,
+			     ngpio * sizeof(struct davinci_gpio_controller),
+			     GFP_KERNEL);
+	if (!chips) {
+		dev_err(dev, "Memory allocation failed\n");
 		return -ENOMEM;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "Invalid memory resource\n");
+		return -EBUSY;
+	}
+
+	gpio_base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(gpio_base))
+		return PTR_ERR(gpio_base);
 
 	for (i = 0, base = 0; base < ngpio; i++, base += 32) {
 		chips[i].chip.label = "DaVinci";
@@ -183,13 +205,10 @@
 		gpiochip_add(&chips[i].chip);
 	}
 
-	soc_info->gpio_ctlrs = chips;
-	soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32);
-
-	davinci_gpio_irq_setup();
+	platform_set_drvdata(pdev, chips);
+	davinci_gpio_irq_setup(pdev);
 	return 0;
 }
-pure_initcall(davinci_gpio_setup);
 
 /*--------------------------------------------------------------------------*/
 /*
@@ -302,13 +321,14 @@
 
 static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset)
 {
-	struct davinci_soc_info *soc_info = &davinci_soc_info;
+	struct davinci_gpio_controller *d = chip2controller(chip);
 
-	/* NOTE:  we assume for now that only irqs in the first gpio_chip
+	/*
+	 * NOTE:  we assume for now that only irqs in the first gpio_chip
 	 * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs).
 	 */
-	if (offset < soc_info->gpio_unbanked)
-		return soc_info->gpio_irq + offset;
+	if (offset < d->irq_base)
+		return d->gpio_irq + offset;
 	else
 		return -ENODEV;
 }
@@ -317,12 +337,11 @@
 {
 	struct davinci_gpio_controller *d;
 	struct davinci_gpio_regs __iomem *g;
-	struct davinci_soc_info *soc_info = &davinci_soc_info;
 	u32 mask;
 
 	d = (struct davinci_gpio_controller *)data->handler_data;
 	g = (struct davinci_gpio_regs __iomem *)d->regs;
-	mask = __gpio_mask(data->irq - soc_info->gpio_irq);
+	mask = __gpio_mask(data->irq - d->gpio_irq);
 
 	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
 		return -EINVAL;
@@ -343,24 +362,33 @@
  * (dm6446) can be set appropriately for GPIOV33 pins.
  */
 
-static int __init davinci_gpio_irq_setup(void)
+static int davinci_gpio_irq_setup(struct platform_device *pdev)
 {
 	unsigned	gpio, irq, bank;
 	struct clk	*clk;
 	u32		binten = 0;
 	unsigned	ngpio, bank_irq;
-	struct davinci_soc_info *soc_info = &davinci_soc_info;
-	struct davinci_gpio_regs	__iomem *g;
+	struct device *dev = &pdev->dev;
+	struct resource	*res;
+	struct davinci_gpio_controller *chips = platform_get_drvdata(pdev);
+	struct davinci_gpio_platform_data *pdata = dev->platform_data;
+	struct davinci_gpio_regs __iomem *g;
 
-	ngpio = soc_info->gpio_num;
-
-	bank_irq = soc_info->gpio_irq;
-	if (bank_irq == 0) {
-		printk(KERN_ERR "Don't know first GPIO bank IRQ.\n");
-		return -EINVAL;
+	ngpio = pdata->ngpio;
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(dev, "Invalid IRQ resource\n");
+		return -EBUSY;
 	}
 
-	clk = clk_get(NULL, "gpio");
+	bank_irq = res->start;
+
+	if (!bank_irq) {
+		dev_err(dev, "Invalid IRQ resource\n");
+		return -ENODEV;
+	}
+
+	clk = devm_clk_get(dev, "gpio");
 	if (IS_ERR(clk)) {
 		printk(KERN_ERR "Error %ld getting gpio clock?\n",
 		       PTR_ERR(clk));
@@ -368,16 +396,17 @@
 	}
 	clk_prepare_enable(clk);
 
-	/* Arrange gpio_to_irq() support, handling either direct IRQs or
+	/*
+	 * Arrange gpio_to_irq() support, handling either direct IRQs or
 	 * banked IRQs.  Having GPIOs in the first GPIO bank use direct
 	 * IRQs, while the others use banked IRQs, would need some setup
 	 * tweaks to recognize hardware which can do that.
 	 */
 	for (gpio = 0, bank = 0; gpio < ngpio; bank++, gpio += 32) {
 		chips[bank].chip.to_irq = gpio_to_irq_banked;
-		chips[bank].irq_base = soc_info->gpio_unbanked
+		chips[bank].irq_base = pdata->gpio_unbanked
 			? -EINVAL
-			: (soc_info->intc_irq_num + gpio);
+			: (pdata->intc_irq_num + gpio);
 	}
 
 	/*
@@ -385,7 +414,7 @@
 	 * controller only handling trigger modes.  We currently assume no
 	 * IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs.
 	 */
-	if (soc_info->gpio_unbanked) {
+	if (pdata->gpio_unbanked) {
 		static struct irq_chip_type gpio_unbanked;
 
 		/* pass "bank 0" GPIO IRQs to AINTC */
@@ -405,7 +434,7 @@
 		__raw_writel(~0, &g->set_rising);
 
 		/* set the direct IRQs up to use that irqchip */
-		for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) {
+		for (gpio = 0; gpio < pdata->gpio_unbanked; gpio++, irq++) {
 			irq_set_chip(irq, &gpio_unbanked.chip);
 			irq_set_handler_data(irq, &chips[gpio / 32]);
 			irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH);
@@ -450,12 +479,31 @@
 	}
 
 done:
-	/* BINTEN -- per-bank interrupt enable. genirq would also let these
+	/*
+	 * BINTEN -- per-bank interrupt enable. genirq would also let these
 	 * bits be set/cleared dynamically.
 	 */
-	__raw_writel(binten, gpio_base + 0x08);
+	__raw_writel(binten, gpio_base + BINTEN);
 
 	printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0));
 
 	return 0;
 }
+
+static struct platform_driver davinci_gpio_driver = {
+	.probe		= davinci_gpio_probe,
+	.driver		= {
+		.name	= "davinci_gpio",
+		.owner	= THIS_MODULE,
+	},
+};
+
+/**
+ * GPIO driver registration needs to be done before machine_init functions
+ * access GPIO. Hence davinci_gpio_drv_reg() is a postcore_initcall.
+ */
+static int __init davinci_gpio_drv_reg(void)
+{
+	return platform_driver_register(&davinci_gpio_driver);
+}
+postcore_initcall(davinci_gpio_drv_reg);
diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c
index c6e1f08..ec19036 100644
--- a/drivers/gpio/gpio-em.c
+++ b/drivers/gpio/gpio-em.c
@@ -232,16 +232,16 @@
 	em_gio_direction_input(chip, offset);
 }
 
-static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int virq,
-				 irq_hw_number_t hw)
+static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int irq,
+				 irq_hw_number_t hwirq)
 {
 	struct em_gio_priv *p = h->host_data;
 
-	pr_debug("gio: map hw irq = %d, virq = %d\n", (int)hw, virq);
+	pr_debug("gio: map hw irq = %d, irq = %d\n", (int)hwirq, irq);
 
-	irq_set_chip_data(virq, h->host_data);
-	irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
-	set_irq_flags(virq, IRQF_VALID); /* kill me now */
+	irq_set_chip_data(irq, h->host_data);
+	irq_set_chip_and_handler(irq, &p->irq_chip, handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID); /* kill me now */
 	return 0;
 }
 
@@ -319,6 +319,7 @@
 	}
 
 	gpio_chip = &p->gpio_chip;
+	gpio_chip->of_node = pdev->dev.of_node;
 	gpio_chip->direction_input = em_gio_direction_input;
 	gpio_chip->get = em_gio_get;
 	gpio_chip->direction_output = em_gio_direction_output;
diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c
index 56b98ee..80829f3 100644
--- a/drivers/gpio/gpio-ep93xx.c
+++ b/drivers/gpio/gpio-ep93xx.c
@@ -51,15 +51,15 @@
 {
 	BUG_ON(port > 2);
 
-	__raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port]));
+	writeb_relaxed(0, EP93XX_GPIO_REG(int_en_register_offset[port]));
 
-	__raw_writeb(gpio_int_type2[port],
+	writeb_relaxed(gpio_int_type2[port],
 		EP93XX_GPIO_REG(int_type2_register_offset[port]));
 
-	__raw_writeb(gpio_int_type1[port],
+	writeb_relaxed(gpio_int_type1[port],
 		EP93XX_GPIO_REG(int_type1_register_offset[port]));
 
-	__raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port],
+	writeb(gpio_int_unmasked[port] & gpio_int_enabled[port],
 		EP93XX_GPIO_REG(int_en_register_offset[port]));
 }
 
@@ -74,7 +74,7 @@
 	else
 		gpio_int_debounce[port] &= ~port_mask;
 
-	__raw_writeb(gpio_int_debounce[port],
+	writeb(gpio_int_debounce[port],
 		EP93XX_GPIO_REG(int_debounce_register_offset[port]));
 }
 
@@ -83,7 +83,7 @@
 	unsigned char status;
 	int i;
 
-	status = __raw_readb(EP93XX_GPIO_A_INT_STATUS);
+	status = readb(EP93XX_GPIO_A_INT_STATUS);
 	for (i = 0; i < 8; i++) {
 		if (status & (1 << i)) {
 			int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i;
@@ -91,7 +91,7 @@
 		}
 	}
 
-	status = __raw_readb(EP93XX_GPIO_B_INT_STATUS);
+	status = readb(EP93XX_GPIO_B_INT_STATUS);
 	for (i = 0; i < 8; i++) {
 		if (status & (1 << i)) {
 			int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i;
@@ -124,7 +124,7 @@
 		ep93xx_gpio_update_int_params(port);
 	}
 
-	__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
+	writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
 }
 
 static void ep93xx_gpio_irq_mask_ack(struct irq_data *d)
@@ -139,7 +139,7 @@
 	gpio_int_unmasked[port] &= ~port_mask;
 	ep93xx_gpio_update_int_params(port);
 
-	__raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
+	writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port]));
 }
 
 static void ep93xx_gpio_irq_mask(struct irq_data *d)
diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c
new file mode 100644
index 0000000..be803af
--- /dev/null
+++ b/drivers/gpio/gpio-intel-mid.c
@@ -0,0 +1,471 @@
+/*
+ * Moorestown platform Langwell chip GPIO driver
+ *
+ * Copyright (c) 2008, 2009, 2013, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Supports:
+ * Moorestown platform Langwell chip.
+ * Medfield platform Penwell chip.
+ * Clovertrail platform Cloverview chip.
+ * Merrifield platform Tangier chip.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/stddef.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/irqdomain.h>
+
+#define INTEL_MID_IRQ_TYPE_EDGE		(1 << 0)
+#define INTEL_MID_IRQ_TYPE_LEVEL	(1 << 1)
+
+/*
+ * Langwell chip has 64 pins and thus there are 2 32bit registers to control
+ * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit
+ * registers to control them, so we only define the order here instead of a
+ * structure, to get a bit offset for a pin (use GPDR as an example):
+ *
+ * nreg = ngpio / 32;
+ * reg = offset / 32;
+ * bit = offset % 32;
+ * reg_addr = reg_base + GPDR * nreg * 4 + reg * 4;
+ *
+ * so the bit of reg_addr is to control pin offset's GPDR feature
+*/
+
+enum GPIO_REG {
+	GPLR = 0,	/* pin level read-only */
+	GPDR,		/* pin direction */
+	GPSR,		/* pin set */
+	GPCR,		/* pin clear */
+	GRER,		/* rising edge detect */
+	GFER,		/* falling edge detect */
+	GEDR,		/* edge detect result */
+	GAFR,		/* alt function */
+};
+
+/* intel_mid gpio driver data */
+struct intel_mid_gpio_ddata {
+	u16 ngpio;		/* number of gpio pins */
+	u32 gplr_offset;	/* offset of first GPLR register from base */
+	u32 flis_base;		/* base address of FLIS registers */
+	u32 flis_len;		/* length of FLIS registers */
+	u32 (*get_flis_offset)(int gpio);
+	u32 chip_irq_type;	/* chip interrupt type */
+};
+
+struct intel_mid_gpio {
+	struct gpio_chip		chip;
+	void __iomem			*reg_base;
+	spinlock_t			lock;
+	struct pci_dev			*pdev;
+	struct irq_domain		*domain;
+};
+
+#define to_intel_gpio_priv(chip) container_of(chip, struct intel_mid_gpio, chip)
+
+static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
+			      enum GPIO_REG reg_type)
+{
+	struct intel_mid_gpio *priv = to_intel_gpio_priv(chip);
+	unsigned nreg = chip->ngpio / 32;
+	u8 reg = offset / 32;
+
+	return priv->reg_base + reg_type * nreg * 4 + reg * 4;
+}
+
+static void __iomem *gpio_reg_2bit(struct gpio_chip *chip, unsigned offset,
+				   enum GPIO_REG reg_type)
+{
+	struct intel_mid_gpio *priv = to_intel_gpio_priv(chip);
+	unsigned nreg = chip->ngpio / 32;
+	u8 reg = offset / 16;
+
+	return priv->reg_base + reg_type * nreg * 4 + reg * 4;
+}
+
+static int intel_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	void __iomem *gafr = gpio_reg_2bit(chip, offset, GAFR);
+	u32 value = readl(gafr);
+	int shift = (offset % 16) << 1, af = (value >> shift) & 3;
+
+	if (af) {
+		value &= ~(3 << shift);
+		writel(value, gafr);
+	}
+	return 0;
+}
+
+static int intel_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	void __iomem *gplr = gpio_reg(chip, offset, GPLR);
+
+	return readl(gplr) & BIT(offset % 32);
+}
+
+static void intel_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	void __iomem *gpsr, *gpcr;
+
+	if (value) {
+		gpsr = gpio_reg(chip, offset, GPSR);
+		writel(BIT(offset % 32), gpsr);
+	} else {
+		gpcr = gpio_reg(chip, offset, GPCR);
+		writel(BIT(offset % 32), gpcr);
+	}
+}
+
+static int intel_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct intel_mid_gpio *priv = to_intel_gpio_priv(chip);
+	void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
+	u32 value;
+	unsigned long flags;
+
+	if (priv->pdev)
+		pm_runtime_get(&priv->pdev->dev);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	value = readl(gpdr);
+	value &= ~BIT(offset % 32);
+	writel(value, gpdr);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (priv->pdev)
+		pm_runtime_put(&priv->pdev->dev);
+
+	return 0;
+}
+
+static int intel_gpio_direction_output(struct gpio_chip *chip,
+			unsigned offset, int value)
+{
+	struct intel_mid_gpio *priv = to_intel_gpio_priv(chip);
+	void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
+	unsigned long flags;
+
+	intel_gpio_set(chip, offset, value);
+
+	if (priv->pdev)
+		pm_runtime_get(&priv->pdev->dev);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	value = readl(gpdr);
+	value |= BIT(offset % 32);
+	writel(value, gpdr);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (priv->pdev)
+		pm_runtime_put(&priv->pdev->dev);
+
+	return 0;
+}
+
+static int intel_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct intel_mid_gpio *priv = to_intel_gpio_priv(chip);
+	return irq_create_mapping(priv->domain, offset);
+}
+
+static int intel_mid_irq_type(struct irq_data *d, unsigned type)
+{
+	struct intel_mid_gpio *priv = irq_data_get_irq_chip_data(d);
+	u32 gpio = irqd_to_hwirq(d);
+	unsigned long flags;
+	u32 value;
+	void __iomem *grer = gpio_reg(&priv->chip, gpio, GRER);
+	void __iomem *gfer = gpio_reg(&priv->chip, gpio, GFER);
+
+	if (gpio >= priv->chip.ngpio)
+		return -EINVAL;
+
+	if (priv->pdev)
+		pm_runtime_get(&priv->pdev->dev);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (type & IRQ_TYPE_EDGE_RISING)
+		value = readl(grer) | BIT(gpio % 32);
+	else
+		value = readl(grer) & (~BIT(gpio % 32));
+	writel(value, grer);
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		value = readl(gfer) | BIT(gpio % 32);
+	else
+		value = readl(gfer) & (~BIT(gpio % 32));
+	writel(value, gfer);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (priv->pdev)
+		pm_runtime_put(&priv->pdev->dev);
+
+	return 0;
+}
+
+static void intel_mid_irq_unmask(struct irq_data *d)
+{
+}
+
+static void intel_mid_irq_mask(struct irq_data *d)
+{
+}
+
+static struct irq_chip intel_mid_irqchip = {
+	.name		= "INTEL_MID-GPIO",
+	.irq_mask	= intel_mid_irq_mask,
+	.irq_unmask	= intel_mid_irq_unmask,
+	.irq_set_type	= intel_mid_irq_type,
+};
+
+static const struct intel_mid_gpio_ddata gpio_lincroft = {
+	.ngpio = 64,
+};
+
+static const struct intel_mid_gpio_ddata gpio_penwell_aon = {
+	.ngpio = 96,
+	.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
+};
+
+static const struct intel_mid_gpio_ddata gpio_penwell_core = {
+	.ngpio = 96,
+	.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
+};
+
+static const struct intel_mid_gpio_ddata gpio_cloverview_aon = {
+	.ngpio = 96,
+	.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE | INTEL_MID_IRQ_TYPE_LEVEL,
+};
+
+static const struct intel_mid_gpio_ddata gpio_cloverview_core = {
+	.ngpio = 96,
+	.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
+};
+
+static const struct intel_mid_gpio_ddata gpio_tangier = {
+	.ngpio = 192,
+	.gplr_offset = 4,
+	.flis_base = 0xff0c0000,
+	.flis_len = 0x8000,
+	.get_flis_offset = NULL,
+	.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
+};
+
+static DEFINE_PCI_DEVICE_TABLE(intel_gpio_ids) = {
+	{
+		/* Lincroft */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f),
+		.driver_data = (kernel_ulong_t)&gpio_lincroft,
+	},
+	{
+		/* Penwell AON */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f),
+		.driver_data = (kernel_ulong_t)&gpio_penwell_aon,
+	},
+	{
+		/* Penwell Core */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a),
+		.driver_data = (kernel_ulong_t)&gpio_penwell_core,
+	},
+	{
+		/* Cloverview Aon */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08eb),
+		.driver_data = (kernel_ulong_t)&gpio_cloverview_aon,
+	},
+	{
+		/* Cloverview Core */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08f7),
+		.driver_data = (kernel_ulong_t)&gpio_cloverview_core,
+	},
+	{
+		/* Tangier */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1199),
+		.driver_data = (kernel_ulong_t)&gpio_tangier,
+	},
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, intel_gpio_ids);
+
+static void intel_mid_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+	struct irq_data *data = irq_desc_get_irq_data(desc);
+	struct intel_mid_gpio *priv = irq_data_get_irq_handler_data(data);
+	struct irq_chip *chip = irq_data_get_irq_chip(data);
+	u32 base, gpio, mask;
+	unsigned long pending;
+	void __iomem *gedr;
+
+	/* check GPIO controller to check which pin triggered the interrupt */
+	for (base = 0; base < priv->chip.ngpio; base += 32) {
+		gedr = gpio_reg(&priv->chip, base, GEDR);
+		while ((pending = readl(gedr))) {
+			gpio = __ffs(pending);
+			mask = BIT(gpio);
+			/* Clear before handling so we can't lose an edge */
+			writel(mask, gedr);
+			generic_handle_irq(irq_find_mapping(priv->domain,
+							    base + gpio));
+		}
+	}
+
+	chip->irq_eoi(data);
+}
+
+static void intel_mid_irq_init_hw(struct intel_mid_gpio *priv)
+{
+	void __iomem *reg;
+	unsigned base;
+
+	for (base = 0; base < priv->chip.ngpio; base += 32) {
+		/* Clear the rising-edge detect register */
+		reg = gpio_reg(&priv->chip, base, GRER);
+		writel(0, reg);
+		/* Clear the falling-edge detect register */
+		reg = gpio_reg(&priv->chip, base, GFER);
+		writel(0, reg);
+		/* Clear the edge detect status register */
+		reg = gpio_reg(&priv->chip, base, GEDR);
+		writel(~0, reg);
+	}
+}
+
+static int intel_gpio_irq_map(struct irq_domain *d, unsigned int irq,
+			    irq_hw_number_t hwirq)
+{
+	struct intel_mid_gpio *priv = d->host_data;
+
+	irq_set_chip_and_handler_name(irq, &intel_mid_irqchip,
+				      handle_simple_irq, "demux");
+	irq_set_chip_data(irq, priv);
+	irq_set_irq_type(irq, IRQ_TYPE_NONE);
+
+	return 0;
+}
+
+static const struct irq_domain_ops intel_gpio_irq_ops = {
+	.map = intel_gpio_irq_map,
+	.xlate = irq_domain_xlate_twocell,
+};
+
+static int intel_gpio_runtime_idle(struct device *dev)
+{
+	pm_schedule_suspend(dev, 500);
+	return -EBUSY;
+}
+
+static const struct dev_pm_ops intel_gpio_pm_ops = {
+	SET_RUNTIME_PM_OPS(NULL, NULL, intel_gpio_runtime_idle)
+};
+
+static int intel_gpio_probe(struct pci_dev *pdev,
+			  const struct pci_device_id *id)
+{
+	void __iomem *base;
+	struct intel_mid_gpio *priv;
+	u32 gpio_base;
+	u32 irq_base;
+	int retval;
+	struct intel_mid_gpio_ddata *ddata =
+				(struct intel_mid_gpio_ddata *)id->driver_data;
+
+	retval = pcim_enable_device(pdev);
+	if (retval)
+		return retval;
+
+	retval = pcim_iomap_regions(pdev, 1 << 0 | 1 << 1, pci_name(pdev));
+	if (retval) {
+		dev_err(&pdev->dev, "I/O memory mapping error\n");
+		return retval;
+	}
+
+	base = pcim_iomap_table(pdev)[1];
+
+	irq_base = readl(base);
+	gpio_base = readl(sizeof(u32) + base);
+
+	/* release the IO mapping, since we already get the info from bar1 */
+	pcim_iounmap_regions(pdev, 1 << 1);
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&pdev->dev, "can't allocate chip data\n");
+		return -ENOMEM;
+	}
+
+	priv->reg_base = pcim_iomap_table(pdev)[0];
+	priv->chip.label = dev_name(&pdev->dev);
+	priv->chip.request = intel_gpio_request;
+	priv->chip.direction_input = intel_gpio_direction_input;
+	priv->chip.direction_output = intel_gpio_direction_output;
+	priv->chip.get = intel_gpio_get;
+	priv->chip.set = intel_gpio_set;
+	priv->chip.to_irq = intel_gpio_to_irq;
+	priv->chip.base = gpio_base;
+	priv->chip.ngpio = ddata->ngpio;
+	priv->chip.can_sleep = 0;
+	priv->pdev = pdev;
+
+	spin_lock_init(&priv->lock);
+
+	priv->domain = irq_domain_add_simple(pdev->dev.of_node, ddata->ngpio,
+					irq_base, &intel_gpio_irq_ops, priv);
+	if (!priv->domain)
+		return -ENOMEM;
+
+	pci_set_drvdata(pdev, priv);
+	retval = gpiochip_add(&priv->chip);
+	if (retval) {
+		dev_err(&pdev->dev, "gpiochip_add error %d\n", retval);
+		return retval;
+	}
+
+	intel_mid_irq_init_hw(priv);
+
+	irq_set_handler_data(pdev->irq, priv);
+	irq_set_chained_handler(pdev->irq, intel_mid_irq_handler);
+
+	pm_runtime_put_noidle(&pdev->dev);
+	pm_runtime_allow(&pdev->dev);
+
+	return 0;
+}
+
+static struct pci_driver intel_gpio_driver = {
+	.name		= "intel_mid_gpio",
+	.id_table	= intel_gpio_ids,
+	.probe		= intel_gpio_probe,
+	.driver		= {
+		.pm	= &intel_gpio_pm_ops,
+	},
+};
+
+static int __init intel_gpio_init(void)
+{
+	return pci_register_driver(&intel_gpio_driver);
+}
+
+device_initcall(intel_gpio_init);
diff --git a/drivers/gpio/gpio-iop.c b/drivers/gpio/gpio-iop.c
new file mode 100644
index 0000000..c22a61b
--- /dev/null
+++ b/drivers/gpio/gpio-iop.c
@@ -0,0 +1,130 @@
+/*
+ * arch/arm/plat-iop/gpio.c
+ * GPIO handling for Intel IOP3xx processors.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/export.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+
+#define IOP3XX_N_GPIOS	8
+
+#define GPIO_IN			0
+#define GPIO_OUT		1
+#define GPIO_LOW		0
+#define GPIO_HIGH		1
+
+/* Memory base offset */
+static void __iomem *base;
+
+#define IOP3XX_GPIO_REG(reg)	(base + (reg))
+#define IOP3XX_GPOE		IOP3XX_GPIO_REG(0x0000)
+#define IOP3XX_GPID		IOP3XX_GPIO_REG(0x0004)
+#define IOP3XX_GPOD		IOP3XX_GPIO_REG(0x0008)
+
+static void gpio_line_config(int line, int direction)
+{
+	unsigned long flags;
+	u32 val;
+
+	local_irq_save(flags);
+	val = readl(IOP3XX_GPOE);
+	if (direction == GPIO_IN) {
+		val |= BIT(line);
+	} else if (direction == GPIO_OUT) {
+		val &= ~BIT(line);
+	}
+	writel(val, IOP3XX_GPOE);
+	local_irq_restore(flags);
+}
+
+static int gpio_line_get(int line)
+{
+	return !!(readl(IOP3XX_GPID) & BIT(line));
+}
+
+static void gpio_line_set(int line, int value)
+{
+	unsigned long flags;
+	u32 val;
+
+	local_irq_save(flags);
+	val = readl(IOP3XX_GPOD);
+	if (value == GPIO_LOW) {
+		val &= ~BIT(line);
+	} else if (value == GPIO_HIGH) {
+		val |= BIT(line);
+	}
+	writel(val, IOP3XX_GPOD);
+	local_irq_restore(flags);
+}
+
+static int iop3xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+	gpio_line_config(gpio, GPIO_IN);
+	return 0;
+}
+
+static int iop3xx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int level)
+{
+	gpio_line_set(gpio, level);
+	gpio_line_config(gpio, GPIO_OUT);
+	return 0;
+}
+
+static int iop3xx_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+	return gpio_line_get(gpio);
+}
+
+static void iop3xx_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)
+{
+	gpio_line_set(gpio, value);
+}
+
+static struct gpio_chip iop3xx_chip = {
+	.label			= "iop3xx",
+	.direction_input	= iop3xx_gpio_direction_input,
+	.get			= iop3xx_gpio_get_value,
+	.direction_output	= iop3xx_gpio_direction_output,
+	.set			= iop3xx_gpio_set_value,
+	.base			= 0,
+	.ngpio			= IOP3XX_N_GPIOS,
+};
+
+static int iop3xx_gpio_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(&pdev->dev, res);
+
+	return gpiochip_add(&iop3xx_chip);
+}
+
+static struct platform_driver iop3xx_gpio_driver = {
+	.driver = {
+		.name = "gpio-iop",
+		.owner = THIS_MODULE,
+	},
+	.probe = iop3xx_gpio_probe,
+};
+
+static int __init iop3xx_gpio_init(void)
+{
+	return platform_driver_register(&iop3xx_gpio_driver);
+}
+arch_initcall(iop3xx_gpio_init);
diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c
deleted file mode 100644
index bfa1af1..0000000
--- a/drivers/gpio/gpio-langwell.c
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * Moorestown platform Langwell chip GPIO driver
- *
- * Copyright (c) 2008, 2009, 2013, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* Supports:
- * Moorestown platform Langwell chip.
- * Medfield platform Penwell chip.
- */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/stddef.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-#include <linux/pm_runtime.h>
-#include <linux/irqdomain.h>
-
-/*
- * Langwell chip has 64 pins and thus there are 2 32bit registers to control
- * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit
- * registers to control them, so we only define the order here instead of a
- * structure, to get a bit offset for a pin (use GPDR as an example):
- *
- * nreg = ngpio / 32;
- * reg = offset / 32;
- * bit = offset % 32;
- * reg_addr = reg_base + GPDR * nreg * 4 + reg * 4;
- *
- * so the bit of reg_addr is to control pin offset's GPDR feature
-*/
-
-enum GPIO_REG {
-	GPLR = 0,	/* pin level read-only */
-	GPDR,		/* pin direction */
-	GPSR,		/* pin set */
-	GPCR,		/* pin clear */
-	GRER,		/* rising edge detect */
-	GFER,		/* falling edge detect */
-	GEDR,		/* edge detect result */
-	GAFR,		/* alt function */
-};
-
-struct lnw_gpio {
-	struct gpio_chip		chip;
-	void __iomem			*reg_base;
-	spinlock_t			lock;
-	struct pci_dev			*pdev;
-	struct irq_domain		*domain;
-};
-
-#define to_lnw_priv(chip)	container_of(chip, struct lnw_gpio, chip)
-
-static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
-			      enum GPIO_REG reg_type)
-{
-	struct lnw_gpio *lnw = to_lnw_priv(chip);
-	unsigned nreg = chip->ngpio / 32;
-	u8 reg = offset / 32;
-
-	return lnw->reg_base + reg_type * nreg * 4 + reg * 4;
-}
-
-static void __iomem *gpio_reg_2bit(struct gpio_chip *chip, unsigned offset,
-				   enum GPIO_REG reg_type)
-{
-	struct lnw_gpio *lnw = to_lnw_priv(chip);
-	unsigned nreg = chip->ngpio / 32;
-	u8 reg = offset / 16;
-
-	return lnw->reg_base + reg_type * nreg * 4 + reg * 4;
-}
-
-static int lnw_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-	void __iomem *gafr = gpio_reg_2bit(chip, offset, GAFR);
-	u32 value = readl(gafr);
-	int shift = (offset % 16) << 1, af = (value >> shift) & 3;
-
-	if (af) {
-		value &= ~(3 << shift);
-		writel(value, gafr);
-	}
-	return 0;
-}
-
-static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	void __iomem *gplr = gpio_reg(chip, offset, GPLR);
-
-	return readl(gplr) & BIT(offset % 32);
-}
-
-static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	void __iomem *gpsr, *gpcr;
-
-	if (value) {
-		gpsr = gpio_reg(chip, offset, GPSR);
-		writel(BIT(offset % 32), gpsr);
-	} else {
-		gpcr = gpio_reg(chip, offset, GPCR);
-		writel(BIT(offset % 32), gpcr);
-	}
-}
-
-static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	struct lnw_gpio *lnw = to_lnw_priv(chip);
-	void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
-	u32 value;
-	unsigned long flags;
-
-	if (lnw->pdev)
-		pm_runtime_get(&lnw->pdev->dev);
-
-	spin_lock_irqsave(&lnw->lock, flags);
-	value = readl(gpdr);
-	value &= ~BIT(offset % 32);
-	writel(value, gpdr);
-	spin_unlock_irqrestore(&lnw->lock, flags);
-
-	if (lnw->pdev)
-		pm_runtime_put(&lnw->pdev->dev);
-
-	return 0;
-}
-
-static int lnw_gpio_direction_output(struct gpio_chip *chip,
-			unsigned offset, int value)
-{
-	struct lnw_gpio *lnw = to_lnw_priv(chip);
-	void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
-	unsigned long flags;
-
-	lnw_gpio_set(chip, offset, value);
-
-	if (lnw->pdev)
-		pm_runtime_get(&lnw->pdev->dev);
-
-	spin_lock_irqsave(&lnw->lock, flags);
-	value = readl(gpdr);
-	value |= BIT(offset % 32);
-	writel(value, gpdr);
-	spin_unlock_irqrestore(&lnw->lock, flags);
-
-	if (lnw->pdev)
-		pm_runtime_put(&lnw->pdev->dev);
-
-	return 0;
-}
-
-static int lnw_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct lnw_gpio *lnw = to_lnw_priv(chip);
-	return irq_create_mapping(lnw->domain, offset);
-}
-
-static int lnw_irq_type(struct irq_data *d, unsigned type)
-{
-	struct lnw_gpio *lnw = irq_data_get_irq_chip_data(d);
-	u32 gpio = irqd_to_hwirq(d);
-	unsigned long flags;
-	u32 value;
-	void __iomem *grer = gpio_reg(&lnw->chip, gpio, GRER);
-	void __iomem *gfer = gpio_reg(&lnw->chip, gpio, GFER);
-
-	if (gpio >= lnw->chip.ngpio)
-		return -EINVAL;
-
-	if (lnw->pdev)
-		pm_runtime_get(&lnw->pdev->dev);
-
-	spin_lock_irqsave(&lnw->lock, flags);
-	if (type & IRQ_TYPE_EDGE_RISING)
-		value = readl(grer) | BIT(gpio % 32);
-	else
-		value = readl(grer) & (~BIT(gpio % 32));
-	writel(value, grer);
-
-	if (type & IRQ_TYPE_EDGE_FALLING)
-		value = readl(gfer) | BIT(gpio % 32);
-	else
-		value = readl(gfer) & (~BIT(gpio % 32));
-	writel(value, gfer);
-	spin_unlock_irqrestore(&lnw->lock, flags);
-
-	if (lnw->pdev)
-		pm_runtime_put(&lnw->pdev->dev);
-
-	return 0;
-}
-
-static void lnw_irq_unmask(struct irq_data *d)
-{
-}
-
-static void lnw_irq_mask(struct irq_data *d)
-{
-}
-
-static struct irq_chip lnw_irqchip = {
-	.name		= "LNW-GPIO",
-	.irq_mask	= lnw_irq_mask,
-	.irq_unmask	= lnw_irq_unmask,
-	.irq_set_type	= lnw_irq_type,
-};
-
-static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = {   /* pin number */
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), .driver_data = 64 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f), .driver_data = 96 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a), .driver_data = 96 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08eb), .driver_data = 96 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08f7), .driver_data = 96 },
-	{ 0, }
-};
-MODULE_DEVICE_TABLE(pci, lnw_gpio_ids);
-
-static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
-{
-	struct irq_data *data = irq_desc_get_irq_data(desc);
-	struct lnw_gpio *lnw = irq_data_get_irq_handler_data(data);
-	struct irq_chip *chip = irq_data_get_irq_chip(data);
-	u32 base, gpio, mask;
-	unsigned long pending;
-	void __iomem *gedr;
-
-	/* check GPIO controller to check which pin triggered the interrupt */
-	for (base = 0; base < lnw->chip.ngpio; base += 32) {
-		gedr = gpio_reg(&lnw->chip, base, GEDR);
-		while ((pending = readl(gedr))) {
-			gpio = __ffs(pending);
-			mask = BIT(gpio);
-			/* Clear before handling so we can't lose an edge */
-			writel(mask, gedr);
-			generic_handle_irq(irq_find_mapping(lnw->domain,
-							    base + gpio));
-		}
-	}
-
-	chip->irq_eoi(data);
-}
-
-static void lnw_irq_init_hw(struct lnw_gpio *lnw)
-{
-	void __iomem *reg;
-	unsigned base;
-
-	for (base = 0; base < lnw->chip.ngpio; base += 32) {
-		/* Clear the rising-edge detect register */
-		reg = gpio_reg(&lnw->chip, base, GRER);
-		writel(0, reg);
-		/* Clear the falling-edge detect register */
-		reg = gpio_reg(&lnw->chip, base, GFER);
-		writel(0, reg);
-		/* Clear the edge detect status register */
-		reg = gpio_reg(&lnw->chip, base, GEDR);
-		writel(~0, reg);
-	}
-}
-
-static int lnw_gpio_irq_map(struct irq_domain *d, unsigned int virq,
-			    irq_hw_number_t hw)
-{
-	struct lnw_gpio *lnw = d->host_data;
-
-	irq_set_chip_and_handler_name(virq, &lnw_irqchip, handle_simple_irq,
-				      "demux");
-	irq_set_chip_data(virq, lnw);
-	irq_set_irq_type(virq, IRQ_TYPE_NONE);
-
-	return 0;
-}
-
-static const struct irq_domain_ops lnw_gpio_irq_ops = {
-	.map = lnw_gpio_irq_map,
-	.xlate = irq_domain_xlate_twocell,
-};
-
-static int lnw_gpio_runtime_idle(struct device *dev)
-{
-	pm_schedule_suspend(dev, 500);
-	return -EBUSY;
-}
-
-static const struct dev_pm_ops lnw_gpio_pm_ops = {
-	SET_RUNTIME_PM_OPS(NULL, NULL, lnw_gpio_runtime_idle)
-};
-
-static int lnw_gpio_probe(struct pci_dev *pdev,
-			  const struct pci_device_id *id)
-{
-	void __iomem *base;
-	struct lnw_gpio *lnw;
-	u32 gpio_base;
-	u32 irq_base;
-	int retval;
-	int ngpio = id->driver_data;
-
-	retval = pcim_enable_device(pdev);
-	if (retval)
-		return retval;
-
-	retval = pcim_iomap_regions(pdev, 1 << 0 | 1 << 1, pci_name(pdev));
-	if (retval) {
-		dev_err(&pdev->dev, "I/O memory mapping error\n");
-		return retval;
-	}
-
-	base = pcim_iomap_table(pdev)[1];
-
-	irq_base = readl(base);
-	gpio_base = readl(sizeof(u32) + base);
-
-	/* release the IO mapping, since we already get the info from bar1 */
-	pcim_iounmap_regions(pdev, 1 << 1);
-
-	lnw = devm_kzalloc(&pdev->dev, sizeof(*lnw), GFP_KERNEL);
-	if (!lnw) {
-		dev_err(&pdev->dev, "can't allocate chip data\n");
-		return -ENOMEM;
-	}
-
-	lnw->reg_base = pcim_iomap_table(pdev)[0];
-	lnw->chip.label = dev_name(&pdev->dev);
-	lnw->chip.request = lnw_gpio_request;
-	lnw->chip.direction_input = lnw_gpio_direction_input;
-	lnw->chip.direction_output = lnw_gpio_direction_output;
-	lnw->chip.get = lnw_gpio_get;
-	lnw->chip.set = lnw_gpio_set;
-	lnw->chip.to_irq = lnw_gpio_to_irq;
-	lnw->chip.base = gpio_base;
-	lnw->chip.ngpio = ngpio;
-	lnw->chip.can_sleep = 0;
-	lnw->pdev = pdev;
-
-	spin_lock_init(&lnw->lock);
-
-	lnw->domain = irq_domain_add_simple(pdev->dev.of_node, ngpio, irq_base,
-					    &lnw_gpio_irq_ops, lnw);
-	if (!lnw->domain)
-		return -ENOMEM;
-
-	pci_set_drvdata(pdev, lnw);
-	retval = gpiochip_add(&lnw->chip);
-	if (retval) {
-		dev_err(&pdev->dev, "gpiochip_add error %d\n", retval);
-		return retval;
-	}
-
-	lnw_irq_init_hw(lnw);
-
-	irq_set_handler_data(pdev->irq, lnw);
-	irq_set_chained_handler(pdev->irq, lnw_irq_handler);
-
-	pm_runtime_put_noidle(&pdev->dev);
-	pm_runtime_allow(&pdev->dev);
-
-	return 0;
-}
-
-static struct pci_driver lnw_gpio_driver = {
-	.name		= "langwell_gpio",
-	.id_table	= lnw_gpio_ids,
-	.probe		= lnw_gpio_probe,
-	.driver		= {
-		.pm	= &lnw_gpio_pm_ops,
-	},
-};
-
-static int __init lnw_gpio_init(void)
-{
-	return pci_register_driver(&lnw_gpio_driver);
-}
-
-device_initcall(lnw_gpio_init);
diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c
index 90a80eb..2d5555d 100644
--- a/drivers/gpio/gpio-lpc32xx.c
+++ b/drivers/gpio/gpio-lpc32xx.c
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/errno.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/platform_device.h>
 #include <linux/module.h>
diff --git a/drivers/gpio/gpio-lynxpoint.c b/drivers/gpio/gpio-lynxpoint.c
index 2d9ca60..a080474 100644
--- a/drivers/gpio/gpio-lynxpoint.c
+++ b/drivers/gpio/gpio-lynxpoint.c
@@ -242,26 +242,28 @@
 	return irq_create_mapping(lg->domain, offset);
 }
 
-static void lp_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+static void lp_gpio_irq_handler(unsigned hwirq, struct irq_desc *desc)
 {
 	struct irq_data *data = irq_desc_get_irq_data(desc);
 	struct lp_gpio *lg = irq_data_get_irq_handler_data(data);
 	struct irq_chip *chip = irq_data_get_irq_chip(data);
 	u32 base, pin, mask;
-	unsigned long reg, pending;
-	unsigned virq;
+	unsigned long reg, ena, pending;
 
 	/* check from GPIO controller which pin triggered the interrupt */
 	for (base = 0; base < lg->chip.ngpio; base += 32) {
 		reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT);
+		ena = lp_gpio_reg(&lg->chip, base, LP_INT_ENABLE);
 
-		while ((pending = inl(reg))) {
+		while ((pending = (inl(reg) & inl(ena)))) {
+			unsigned irq;
+
 			pin = __ffs(pending);
 			mask = BIT(pin);
 			/* Clear before handling so we don't lose an edge */
 			outl(mask, reg);
-			virq = irq_find_mapping(lg->domain, base + pin);
-			generic_handle_irq(virq);
+			irq = irq_find_mapping(lg->domain, base + pin);
+			generic_handle_irq(irq);
 		}
 	}
 	chip->irq_eoi(data);
@@ -324,15 +326,15 @@
 	}
 }
 
-static int lp_gpio_irq_map(struct irq_domain *d, unsigned int virq,
-			    irq_hw_number_t hw)
+static int lp_gpio_irq_map(struct irq_domain *d, unsigned int irq,
+			    irq_hw_number_t hwirq)
 {
 	struct lp_gpio *lg = d->host_data;
 
-	irq_set_chip_and_handler_name(virq, &lp_irqchip, handle_simple_irq,
+	irq_set_chip_and_handler_name(irq, &lp_irqchip, handle_simple_irq,
 				      "demux");
-	irq_set_chip_data(virq, lg);
-	irq_set_irq_type(virq, IRQ_TYPE_NONE);
+	irq_set_chip_data(irq, lg);
+	irq_set_irq_type(irq, IRQ_TYPE_NONE);
 
 	return 0;
 }
diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c
index 3fd2caa..c0b7835 100644
--- a/drivers/gpio/gpio-mc33880.c
+++ b/drivers/gpio/gpio-mc33880.c
@@ -142,7 +142,6 @@
 	return ret;
 
 exit_destroy:
-	spi_set_drvdata(spi, NULL);
 	mutex_destroy(&mc->lock);
 	return ret;
 }
@@ -156,8 +155,6 @@
 	if (mc == NULL)
 		return -ENODEV;
 
-	spi_set_drvdata(spi, NULL);
-
 	ret = gpiochip_remove(&mc->chip);
 	if (!ret)
 		mutex_destroy(&mc->lock);
diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c
index a0b33a2..914e859 100644
--- a/drivers/gpio/gpio-mpc8xxx.c
+++ b/drivers/gpio/gpio-mpc8xxx.c
@@ -14,6 +14,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
+#include <linux/of_irq.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/irq.h>
@@ -282,16 +283,16 @@
 	.irq_set_type	= mpc8xxx_irq_set_type,
 };
 
-static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int virq,
-				irq_hw_number_t hw)
+static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int irq,
+				irq_hw_number_t hwirq)
 {
 	struct mpc8xxx_gpio_chip *mpc8xxx_gc = h->host_data;
 
 	if (mpc8xxx_gc->of_dev_id_data)
 		mpc8xxx_irq_chip.irq_set_type = mpc8xxx_gc->of_dev_id_data;
 
-	irq_set_chip_data(virq, h->host_data);
-	irq_set_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq);
+	irq_set_chip_data(irq, h->host_data);
+	irq_set_chip_and_handler(irq, &mpc8xxx_irq_chip, handle_level_irq);
 
 	return 0;
 }
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
index f8e6af2..532bcb3 100644
--- a/drivers/gpio/gpio-mxs.c
+++ b/drivers/gpio/gpio-mxs.c
@@ -254,7 +254,6 @@
 	struct device_node *parent;
 	static void __iomem *base;
 	struct mxs_gpio_port *port;
-	struct resource *iores = NULL;
 	int irq_base;
 	int err;
 
@@ -262,16 +261,10 @@
 	if (!port)
 		return -ENOMEM;
 
-	if (np) {
-		port->id = of_alias_get_id(np, "gpio");
-		if (port->id < 0)
-			return port->id;
-		port->devid = (enum mxs_gpio_id) of_id->data;
-	} else {
-		port->id = pdev->id;
-		port->devid = pdev->id_entry->driver_data;
-	}
-
+	port->id = of_alias_get_id(np, "gpio");
+	if (port->id < 0)
+		return port->id;
+	port->devid = (enum mxs_gpio_id) of_id->data;
 	port->irq = platform_get_irq(pdev, 0);
 	if (port->irq < 0)
 		return port->irq;
@@ -281,18 +274,11 @@
 	 * share the same one
 	 */
 	if (!base) {
-		if (np) {
-			parent = of_get_parent(np);
-			base = of_iomap(parent, 0);
-			of_node_put(parent);
-			if (!base)
-				return -EADDRNOTAVAIL;
-		} else {
-			iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-			base = devm_ioremap_resource(&pdev->dev, iores);
-			if (IS_ERR(base))
-				return PTR_ERR(base);
-		}
+		parent = of_get_parent(np);
+		base = of_iomap(parent, 0);
+		of_node_put(parent);
+		if (!base)
+			return -EADDRNOTAVAIL;
 	}
 	port->base = base;
 
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 89675f8..f319c9f 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -514,6 +514,14 @@
 		return -EINVAL;
 	}
 
+	retval = gpio_lock_as_irq(&bank->chip, offset);
+	if (retval) {
+		dev_err(bank->dev, "unable to lock offset %d for IRQ\n",
+			offset);
+		spin_unlock_irqrestore(&bank->lock, flags);
+		return retval;
+	}
+
 	bank->irq_usage |= 1 << GPIO_INDEX(bank, gpio);
 	spin_unlock_irqrestore(&bank->lock, flags);
 
@@ -797,6 +805,7 @@
 	unsigned offset = GPIO_INDEX(bank, gpio);
 
 	spin_lock_irqsave(&bank->lock, flags);
+	gpio_unlock_as_irq(&bank->chip, offset);
 	bank->irq_usage &= ~(1 << offset);
 	_disable_gpio_module(bank, offset);
 	_reset_gpio(bank, gpio);
@@ -957,22 +966,13 @@
 {
 	struct gpio_bank *bank;
 	unsigned long flags;
-	int retval = 0;
 
 	bank = container_of(chip, struct gpio_bank, chip);
 	spin_lock_irqsave(&bank->lock, flags);
-
-	if (LINE_USED(bank->irq_usage, offset)) {
-			retval = -EINVAL;
-			goto exit;
-	}
-
 	bank->set_dataout(bank, offset, value);
 	_set_gpio_direction(bank, offset, 0);
-
-exit:
 	spin_unlock_irqrestore(&bank->lock, flags);
-	return retval;
+	return 0;
 }
 
 static int gpio_debounce(struct gpio_chip *chip, unsigned offset,
diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c
index 8588af0..11801e98 100644
--- a/drivers/gpio/gpio-palmas.c
+++ b/drivers/gpio/gpio-palmas.c
@@ -31,6 +31,10 @@
 	struct palmas *palmas;
 };
 
+struct palmas_device_data {
+	int ngpio;
+};
+
 static inline struct palmas_gpio *to_palmas_gpio(struct gpio_chip *chip)
 {
 	return container_of(chip, struct palmas_gpio, gpio_chip);
@@ -42,23 +46,26 @@
 	struct palmas *palmas = pg->palmas;
 	unsigned int val;
 	int ret;
+	unsigned int reg;
+	int gpio16 = (offset/8);
 
-	ret = palmas_read(palmas, PALMAS_GPIO_BASE, PALMAS_GPIO_DATA_DIR, &val);
+	offset %= 8;
+	reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;
+
+	ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);
 	if (ret < 0) {
-		dev_err(gc->dev, "GPIO_DATA_DIR read failed, err = %d\n", ret);
+		dev_err(gc->dev, "Reg 0x%02x read failed, %d\n", reg, ret);
 		return ret;
 	}
 
-	if (val & (1 << offset)) {
-		ret = palmas_read(palmas, PALMAS_GPIO_BASE,
-				  PALMAS_GPIO_DATA_OUT, &val);
-	} else {
-		ret = palmas_read(palmas, PALMAS_GPIO_BASE,
-				  PALMAS_GPIO_DATA_IN, &val);
-	}
+	if (val & BIT(offset))
+		reg = (gpio16) ? PALMAS_GPIO_DATA_OUT2 : PALMAS_GPIO_DATA_OUT;
+	else
+		reg = (gpio16) ? PALMAS_GPIO_DATA_IN2 : PALMAS_GPIO_DATA_IN;
+
+	ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val);
 	if (ret < 0) {
-		dev_err(gc->dev, "GPIO_DATA_IN/OUT read failed, err = %d\n",
-			ret);
+		dev_err(gc->dev, "Reg 0x%02x read failed, %d\n", reg, ret);
 		return ret;
 	}
 	return !!(val & BIT(offset));
@@ -70,17 +77,20 @@
 	struct palmas_gpio *pg = to_palmas_gpio(gc);
 	struct palmas *palmas = pg->palmas;
 	int ret;
+	unsigned int reg;
+	int gpio16 = (offset/8);
 
-	if (value)
-		ret = palmas_write(palmas, PALMAS_GPIO_BASE,
-				PALMAS_GPIO_SET_DATA_OUT, BIT(offset));
+	offset %= 8;
+	if (gpio16)
+		reg = (value) ?
+			PALMAS_GPIO_SET_DATA_OUT2 : PALMAS_GPIO_CLEAR_DATA_OUT2;
 	else
-		ret = palmas_write(palmas, PALMAS_GPIO_BASE,
-				PALMAS_GPIO_CLEAR_DATA_OUT, BIT(offset));
+		reg = (value) ?
+			PALMAS_GPIO_SET_DATA_OUT : PALMAS_GPIO_CLEAR_DATA_OUT;
+
+	ret = palmas_write(palmas, PALMAS_GPIO_BASE, reg, BIT(offset));
 	if (ret < 0)
-		dev_err(gc->dev, "%s write failed, err = %d\n",
-			(value) ? "GPIO_SET_DATA_OUT" : "GPIO_CLEAR_DATA_OUT",
-			ret);
+		dev_err(gc->dev, "Reg 0x%02x write failed, %d\n", reg, ret);
 }
 
 static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset,
@@ -89,14 +99,19 @@
 	struct palmas_gpio *pg = to_palmas_gpio(gc);
 	struct palmas *palmas = pg->palmas;
 	int ret;
+	unsigned int reg;
+	int gpio16 = (offset/8);
+
+	offset %= 8;
+	reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;
 
 	/* Set the initial value */
 	palmas_gpio_set(gc, offset, value);
 
-	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE,
-		PALMAS_GPIO_DATA_DIR, BIT(offset), BIT(offset));
+	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg,
+				BIT(offset), BIT(offset));
 	if (ret < 0)
-		dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret);
+		dev_err(gc->dev, "Reg 0x%02x update failed, %d\n", reg, ret);
 	return ret;
 }
 
@@ -105,11 +120,15 @@
 	struct palmas_gpio *pg = to_palmas_gpio(gc);
 	struct palmas *palmas = pg->palmas;
 	int ret;
+	unsigned int reg;
+	int gpio16 = (offset/8);
 
-	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE,
-		PALMAS_GPIO_DATA_DIR, BIT(offset), 0);
+	offset %= 8;
+	reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR;
+
+	ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, BIT(offset), 0);
 	if (ret < 0)
-		dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret);
+		dev_err(gc->dev, "Reg 0x%02x update failed, %d\n", reg, ret);
 	return ret;
 }
 
@@ -121,12 +140,36 @@
 	return palmas_irq_get_virq(palmas, PALMAS_GPIO_0_IRQ + offset);
 }
 
+static const struct palmas_device_data palmas_dev_data = {
+	.ngpio = 8,
+};
+
+static const struct palmas_device_data tps80036_dev_data = {
+	.ngpio = 16,
+};
+
+static struct of_device_id of_palmas_gpio_match[] = {
+	{ .compatible = "ti,palmas-gpio", .data = &palmas_dev_data,},
+	{ .compatible = "ti,tps65913-gpio", .data = &palmas_dev_data,},
+	{ .compatible = "ti,tps65914-gpio", .data = &palmas_dev_data,},
+	{ .compatible = "ti,tps80036-gpio", .data = &tps80036_dev_data,},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_palmas_gpio_match);
+
 static int palmas_gpio_probe(struct platform_device *pdev)
 {
 	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
 	struct palmas_platform_data *palmas_pdata;
 	struct palmas_gpio *palmas_gpio;
 	int ret;
+	const struct of_device_id *match;
+	const struct palmas_device_data *dev_data;
+
+	match = of_match_device(of_palmas_gpio_match, &pdev->dev);
+	dev_data = match->data;
+	if (!dev_data)
+		dev_data = &palmas_dev_data;
 
 	palmas_gpio = devm_kzalloc(&pdev->dev,
 				sizeof(*palmas_gpio), GFP_KERNEL);
@@ -138,7 +181,7 @@
 	palmas_gpio->palmas = palmas;
 	palmas_gpio->gpio_chip.owner = THIS_MODULE;
 	palmas_gpio->gpio_chip.label = dev_name(&pdev->dev);
-	palmas_gpio->gpio_chip.ngpio = 8;
+	palmas_gpio->gpio_chip.ngpio = dev_data->ngpio;
 	palmas_gpio->gpio_chip.can_sleep = 1;
 	palmas_gpio->gpio_chip.direction_input = palmas_gpio_input;
 	palmas_gpio->gpio_chip.direction_output = palmas_gpio_output;
@@ -172,15 +215,6 @@
 	return gpiochip_remove(&palmas_gpio->gpio_chip);
 }
 
-static struct of_device_id of_palmas_gpio_match[] = {
-	{ .compatible = "ti,palmas-gpio"},
-	{ .compatible = "ti,tps65913-gpio"},
-	{ .compatible = "ti,tps65914-gpio"},
-	{ .compatible = "ti,tps80036-gpio"},
-	{ },
-};
-MODULE_DEVICE_TABLE(of, of_palmas_gpio_match);
-
 static struct platform_driver palmas_gpio_driver = {
 	.driver.name	= "palmas-gpio",
 	.driver.owner	= THIS_MODULE,
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index cdd1aa1..6e48c07 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -683,17 +683,6 @@
 	int ret;
 	u8 val[MAX_BANK];
 
-	/* Let every port in proper state, that could save power */
-	memset(val, 0, NBANK(chip));
-	pca953x_write_regs(chip, PCA957X_PUPD, val);
-	memset(val, 0xFF, NBANK(chip));
-	pca953x_write_regs(chip, PCA957X_CFG, val);
-	memset(val, 0, NBANK(chip));
-	pca953x_write_regs(chip, PCA957X_OUT, val);
-
-	ret = pca953x_read_regs(chip, PCA957X_IN, val);
-	if (ret)
-		goto out;
 	ret = pca953x_read_regs(chip, PCA957X_OUT, chip->reg_output);
 	if (ret)
 		goto out;
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
index 9e61bb0..1535686 100644
--- a/drivers/gpio/gpio-pcf857x.c
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -26,9 +26,10 @@
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/workqueue.h>
 
 
 static const struct i2c_device_id pcf857x_id[] = {
@@ -50,6 +51,27 @@
 };
 MODULE_DEVICE_TABLE(i2c, pcf857x_id);
 
+#ifdef CONFIG_OF
+static const struct of_device_id pcf857x_of_table[] = {
+	{ .compatible = "nxp,pcf8574" },
+	{ .compatible = "nxp,pcf8574a" },
+	{ .compatible = "nxp,pca8574" },
+	{ .compatible = "nxp,pca9670" },
+	{ .compatible = "nxp,pca9672" },
+	{ .compatible = "nxp,pca9674" },
+	{ .compatible = "nxp,pcf8575" },
+	{ .compatible = "nxp,pca8575" },
+	{ .compatible = "nxp,pca9671" },
+	{ .compatible = "nxp,pca9673" },
+	{ .compatible = "nxp,pca9675" },
+	{ .compatible = "maxim,max7328" },
+	{ .compatible = "maxim,max7329" },
+	{ .compatible = "ti,tca9554" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, pcf857x_of_table);
+#endif
+
 /*
  * The pcf857x, pca857x, and pca967x chips only expose one read and one
  * write register.  Writing a "one" bit (to match the reset state) lets
@@ -66,12 +88,11 @@
 	struct gpio_chip	chip;
 	struct i2c_client	*client;
 	struct mutex		lock;		/* protect 'out' */
-	struct work_struct	work;		/* irq demux work */
 	struct irq_domain	*irq_domain;	/* for irq demux  */
 	spinlock_t		slock;		/* protect irq demux */
 	unsigned		out;		/* software latch */
 	unsigned		status;		/* current status */
-	int			irq;		/* real irq number */
+	unsigned		irq_mapped;	/* mapped gpio irqs */
 
 	int (*write)(struct i2c_client *client, unsigned data);
 	int (*read)(struct i2c_client *client);
@@ -164,48 +185,54 @@
 static int pcf857x_to_irq(struct gpio_chip *chip, unsigned offset)
 {
 	struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
+	int ret;
 
-	return irq_create_mapping(gpio->irq_domain, offset);
+	ret = irq_create_mapping(gpio->irq_domain, offset);
+	if (ret > 0)
+		gpio->irq_mapped |= (1 << offset);
+
+	return ret;
 }
 
-static void pcf857x_irq_demux_work(struct work_struct *work)
+static irqreturn_t pcf857x_irq(int irq, void *data)
 {
-	struct pcf857x *gpio = container_of(work,
-					       struct pcf857x,
-					       work);
+	struct pcf857x  *gpio = data;
 	unsigned long change, i, status, flags;
 
 	status = gpio->read(gpio->client);
 
 	spin_lock_irqsave(&gpio->slock, flags);
 
-	change = gpio->status ^ status;
+	/*
+	 * call the interrupt handler iff gpio is used as
+	 * interrupt source, just to avoid bad irqs
+	 */
+
+	change = ((gpio->status ^ status) & gpio->irq_mapped);
 	for_each_set_bit(i, &change, gpio->chip.ngpio)
 		generic_handle_irq(irq_find_mapping(gpio->irq_domain, i));
 	gpio->status = status;
 
 	spin_unlock_irqrestore(&gpio->slock, flags);
-}
-
-static irqreturn_t pcf857x_irq_demux(int irq, void *data)
-{
-	struct pcf857x	*gpio = data;
-
-	/*
-	 * pcf857x can't read/write data here,
-	 * since i2c data access might go to sleep.
-	 */
-	schedule_work(&gpio->work);
 
 	return IRQ_HANDLED;
 }
 
-static int pcf857x_irq_domain_map(struct irq_domain *domain, unsigned int virq,
+static int pcf857x_irq_domain_map(struct irq_domain *domain, unsigned int irq,
 				 irq_hw_number_t hw)
 {
-	irq_set_chip_and_handler(virq,
+	struct pcf857x *gpio = domain->host_data;
+
+	irq_set_chip_and_handler(irq,
 				 &dummy_irq_chip,
 				 handle_level_irq);
+#ifdef CONFIG_ARM
+	set_irq_flags(irq, IRQF_VALID);
+#else
+	irq_set_noprobe(irq);
+#endif
+	gpio->irq_mapped |= (1 << hw);
+
 	return 0;
 }
 
@@ -218,8 +245,6 @@
 	if (gpio->irq_domain)
 		irq_domain_remove(gpio->irq_domain);
 
-	if (gpio->irq)
-		free_irq(gpio->irq, gpio);
 }
 
 static int pcf857x_irq_domain_init(struct pcf857x *gpio,
@@ -230,20 +255,21 @@
 	gpio->irq_domain = irq_domain_add_linear(client->dev.of_node,
 						 gpio->chip.ngpio,
 						 &pcf857x_irq_domain_ops,
-						 NULL);
+						 gpio);
 	if (!gpio->irq_domain)
 		goto fail;
 
 	/* enable real irq */
-	status = request_irq(client->irq, pcf857x_irq_demux, 0,
-			     dev_name(&client->dev), gpio);
+	status = devm_request_threaded_irq(&client->dev, client->irq,
+				NULL, pcf857x_irq, IRQF_ONESHOT |
+				IRQF_TRIGGER_FALLING,
+				dev_name(&client->dev), gpio);
+
 	if (status)
 		goto fail;
 
 	/* enable gpio_to_irq() */
-	INIT_WORK(&gpio->work, pcf857x_irq_demux_work);
 	gpio->chip.to_irq	= pcf857x_to_irq;
-	gpio->irq		= client->irq;
 
 	return 0;
 
@@ -257,14 +283,18 @@
 static int pcf857x_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
-	struct pcf857x_platform_data	*pdata;
+	struct pcf857x_platform_data	*pdata = dev_get_platdata(&client->dev);
+	struct device_node		*np = client->dev.of_node;
 	struct pcf857x			*gpio;
+	unsigned int			n_latch = 0;
 	int				status;
 
-	pdata = dev_get_platdata(&client->dev);
-	if (!pdata) {
+	if (IS_ENABLED(CONFIG_OF) && np)
+		of_property_read_u32(np, "lines-initial-states", &n_latch);
+	else if (pdata)
+		n_latch = pdata->n_latch;
+	else
 		dev_dbg(&client->dev, "no platform data\n");
-	}
 
 	/* Allocate, initialize, and register this gpio_chip. */
 	gpio = devm_kzalloc(&client->dev, sizeof(*gpio), GFP_KERNEL);
@@ -357,11 +387,11 @@
 	 * may cause transient glitching since it can't know the last value
 	 * written (some pins may need to be driven low).
 	 *
-	 * Using pdata->n_latch avoids that trouble.  When left initialized
-	 * to zero, our software copy of the "latch" then matches the chip's
-	 * all-ones reset state.  Otherwise it flags pins to be driven low.
+	 * Using n_latch avoids that trouble.  When left initialized to zero,
+	 * our software copy of the "latch" then matches the chip's all-ones
+	 * reset state.  Otherwise it flags pins to be driven low.
 	 */
-	gpio->out = pdata ? ~pdata->n_latch : ~0;
+	gpio->out = ~n_latch;
 	gpio->status = gpio->out;
 
 	status = gpiochip_add(&gpio->chip);
@@ -423,6 +453,7 @@
 	.driver = {
 		.name	= "pcf857x",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(pcf857x_of_table),
 	},
 	.probe	= pcf857x_probe,
 	.remove	= pcf857x_remove,
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index 4274e2e..f22f7f3 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -238,15 +238,15 @@
 	.irq_set_type	= pl061_irq_type,
 };
 
-static int pl061_irq_map(struct irq_domain *d, unsigned int virq,
-			 irq_hw_number_t hw)
+static int pl061_irq_map(struct irq_domain *d, unsigned int irq,
+			 irq_hw_number_t hwirq)
 {
 	struct pl061_gpio *chip = d->host_data;
 
-	irq_set_chip_and_handler_name(virq, &pl061_irqchip, handle_simple_irq,
+	irq_set_chip_and_handler_name(irq, &pl061_irqchip, handle_simple_irq,
 				      "pl061");
-	irq_set_chip_data(virq, chip);
-	irq_set_irq_type(virq, IRQ_TYPE_NONE);
+	irq_set_chip_data(irq, chip);
+	irq_set_irq_type(irq, IRQ_TYPE_NONE);
 
 	return 0;
 }
diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
index 6038966..d3f15ae 100644
--- a/drivers/gpio/gpio-rcar.c
+++ b/drivers/gpio/gpio-rcar.c
@@ -22,6 +22,7 @@
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/platform_data/gpio-rcar.h>
 #include <linux/platform_device.h>
@@ -266,16 +267,16 @@
 	return irq_create_mapping(gpio_to_priv(chip)->irq_domain, offset);
 }
 
-static int gpio_rcar_irq_domain_map(struct irq_domain *h, unsigned int virq,
-				 irq_hw_number_t hw)
+static int gpio_rcar_irq_domain_map(struct irq_domain *h, unsigned int irq,
+				 irq_hw_number_t hwirq)
 {
 	struct gpio_rcar_priv *p = h->host_data;
 
-	dev_dbg(&p->pdev->dev, "map hw irq = %d, virq = %d\n", (int)hw, virq);
+	dev_dbg(&p->pdev->dev, "map hw irq = %d, irq = %d\n", (int)hwirq, irq);
 
-	irq_set_chip_data(virq, h->host_data);
-	irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
-	set_irq_flags(virq, IRQF_VALID); /* kill me now */
+	irq_set_chip_data(irq, h->host_data);
+	irq_set_chip_and_handler(irq, &p->irq_chip, handle_level_irq);
+	set_irq_flags(irq, IRQF_VALID); /* kill me now */
 	return 0;
 }
 
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index 358a21c..76e02b9 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -1033,7 +1033,7 @@
 }
 #endif
 
-#ifdef CONFIG_PLAT_S3C64XX
+#ifdef CONFIG_ARCH_S3C64XX
 static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
 {
 	return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
@@ -1174,7 +1174,7 @@
  */
 
 static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
-#ifdef CONFIG_PLAT_S3C64XX
+#ifdef CONFIG_ARCH_S3C64XX
 	{
 		.chip	= {
 			.base	= S3C64XX_GPA(0),
@@ -1227,7 +1227,7 @@
 };
 
 static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
-#ifdef CONFIG_PLAT_S3C64XX
+#ifdef CONFIG_ARCH_S3C64XX
 	{
 		.base	= S3C64XX_GPH_BASE + 0x4,
 		.chip	= {
@@ -1257,7 +1257,7 @@
 };
 
 static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
-#ifdef CONFIG_PLAT_S3C64XX
+#ifdef CONFIG_ARCH_S3C64XX
 	{
 		.base	= S3C64XX_GPF_BASE,
 		.config	= &samsung_gpio_cfgs[6],
@@ -2082,34 +2082,14 @@
 	int i, nr_chips;
 	int group = 0;
 
-#if defined(CONFIG_PINCTRL_EXYNOS) || defined(CONFIG_PINCTRL_EXYNOS5440)
 	/*
-	* This gpio driver includes support for device tree support and there
-	* are platforms using it. In order to maintain compatibility with those
-	* platforms, and to allow non-dt Exynos4210 platforms to use this
-	* gpiolib support, a check is added to find out if there is a active
-	* pin-controller driver support available. If it is available, this
-	* gpiolib support is ignored and the gpiolib support available in
-	* pin-controller driver is used. This is a temporary check and will go
-	* away when all of the Exynos4210 platforms have switched to using
-	* device tree and the pin-ctrl driver.
-	*/
-	struct device_node *pctrl_np;
-	static const struct of_device_id exynos_pinctrl_ids[] = {
-		{ .compatible = "samsung,s3c2412-pinctrl", },
-		{ .compatible = "samsung,s3c2416-pinctrl", },
-		{ .compatible = "samsung,s3c2440-pinctrl", },
-		{ .compatible = "samsung,s3c2450-pinctrl", },
-		{ .compatible = "samsung,exynos4210-pinctrl", },
-		{ .compatible = "samsung,exynos4x12-pinctrl", },
-		{ .compatible = "samsung,exynos5250-pinctrl", },
-		{ .compatible = "samsung,exynos5440-pinctrl", },
-		{ }
-	};
-	for_each_matching_node(pctrl_np, exynos_pinctrl_ids)
-		if (pctrl_np && of_device_is_available(pctrl_np))
-			return -ENODEV;
-#endif
+	 * Currently there are two drivers that can provide GPIO support for
+	 * Samsung SoCs. For device tree enabled platforms, the new
+	 * pinctrl-samsung driver is used, providing both GPIO and pin control
+	 * interfaces. For legacy (non-DT) platforms this driver is used.
+	 */
+	if (of_have_populated_dt())
+		return -ENODEV;
 
 	samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
 
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c
index b33bad1..2647e24 100644
--- a/drivers/gpio/gpio-stmpe.c
+++ b/drivers/gpio/gpio-stmpe.c
@@ -254,9 +254,10 @@
 		while (stat) {
 			int bit = __ffs(stat);
 			int line = bank * 8 + bit;
-			int virq = irq_find_mapping(stmpe_gpio->domain, line);
+			int child_irq = irq_find_mapping(stmpe_gpio->domain,
+							 line);
 
-			handle_nested_irq(virq);
+			handle_nested_irq(child_irq);
 			stat &= ~(1 << bit);
 		}
 
@@ -271,7 +272,7 @@
 	return IRQ_HANDLED;
 }
 
-static int stmpe_gpio_irq_map(struct irq_domain *d, unsigned int virq,
+static int stmpe_gpio_irq_map(struct irq_domain *d, unsigned int irq,
 			      irq_hw_number_t hwirq)
 {
 	struct stmpe_gpio *stmpe_gpio = d->host_data;
@@ -279,26 +280,26 @@
 	if (!stmpe_gpio)
 		return -EINVAL;
 
-	irq_set_chip_data(hwirq, stmpe_gpio);
-	irq_set_chip_and_handler(hwirq, &stmpe_gpio_irq_chip,
+	irq_set_chip_data(irq, stmpe_gpio);
+	irq_set_chip_and_handler(irq, &stmpe_gpio_irq_chip,
 				 handle_simple_irq);
-	irq_set_nested_thread(hwirq, 1);
+	irq_set_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
-	set_irq_flags(hwirq, IRQF_VALID);
+	set_irq_flags(irq, IRQF_VALID);
 #else
-	irq_set_noprobe(hwirq);
+	irq_set_noprobe(irq);
 #endif
 
 	return 0;
 }
 
-static void stmpe_gpio_irq_unmap(struct irq_domain *d, unsigned int virq)
+static void stmpe_gpio_irq_unmap(struct irq_domain *d, unsigned int irq)
 {
 #ifdef CONFIG_ARM
-	set_irq_flags(virq, 0);
+	set_irq_flags(irq, 0);
 #endif
-	irq_set_chip_and_handler(virq, NULL, NULL);
-	irq_set_chip_data(virq, NULL);
+	irq_set_chip_and_handler(irq, NULL, NULL);
+	irq_set_chip_data(irq, NULL);
 }
 
 static const struct irq_domain_ops stmpe_gpio_irq_simple_ops = {
diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c
new file mode 100644
index 0000000..0502b9a
--- /dev/null
+++ b/drivers/gpio/gpio-tb10x.c
@@ -0,0 +1,328 @@
+/* Abilis Systems MODULE DESCRIPTION
+ *
+ * Copyright (C) Abilis Systems 2013
+ *
+ * Authors: Sascha Leuenberger <sascha.leuenberger@abilis.com>
+ *          Christian Ruppert <christian.ruppert@abilis.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/pinctrl/consumer.h>
+
+#define TB10X_GPIO_DIR_IN	(0x00000000)
+#define TB10X_GPIO_DIR_OUT	(0x00000001)
+#define OFFSET_TO_REG_DDR	(0x00)
+#define OFFSET_TO_REG_DATA	(0x04)
+#define OFFSET_TO_REG_INT_EN	(0x08)
+#define OFFSET_TO_REG_CHANGE	(0x0C)
+#define OFFSET_TO_REG_WRMASK	(0x10)
+#define OFFSET_TO_REG_INT_TYPE	(0x14)
+
+
+/**
+ * @spinlock: used for atomic read/modify/write of registers
+ * @base: register base address
+ * @domain: IRQ domain of GPIO generated interrupts managed by this controller
+ * @irq: Interrupt line of parent interrupt controller
+ * @gc: gpio_chip structure associated to this GPIO controller
+ */
+struct tb10x_gpio {
+	spinlock_t spinlock;
+	void __iomem *base;
+	struct irq_domain *domain;
+	int irq;
+	struct gpio_chip gc;
+};
+
+static inline u32 tb10x_reg_read(struct tb10x_gpio *gpio, unsigned int offs)
+{
+	return ioread32(gpio->base + offs);
+}
+
+static inline void tb10x_reg_write(struct tb10x_gpio *gpio, unsigned int offs,
+				u32 val)
+{
+	iowrite32(val, gpio->base + offs);
+}
+
+static inline void tb10x_set_bits(struct tb10x_gpio *gpio, unsigned int offs,
+				u32 mask, u32 val)
+{
+	u32 r;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpio->spinlock, flags);
+
+	r = tb10x_reg_read(gpio, offs);
+	r = (r & ~mask) | (val & mask);
+
+	tb10x_reg_write(gpio, offs, r);
+
+	spin_unlock_irqrestore(&gpio->spinlock, flags);
+}
+
+static inline struct tb10x_gpio *to_tb10x_gpio(struct gpio_chip *chip)
+{
+	return container_of(chip, struct tb10x_gpio, gc);
+}
+
+static int tb10x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+	struct tb10x_gpio *tb10x_gpio = to_tb10x_gpio(chip);
+	int mask = BIT(offset);
+	int val = TB10X_GPIO_DIR_IN << offset;
+
+	tb10x_set_bits(tb10x_gpio, OFFSET_TO_REG_DDR, mask, val);
+
+	return 0;
+}
+
+static int tb10x_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct tb10x_gpio *tb10x_gpio = to_tb10x_gpio(chip);
+	int val;
+
+	val = tb10x_reg_read(tb10x_gpio, OFFSET_TO_REG_DATA);
+
+	if (val & BIT(offset))
+		return 1;
+	else
+		return 0;
+}
+
+static void tb10x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct tb10x_gpio *tb10x_gpio = to_tb10x_gpio(chip);
+	int mask = BIT(offset);
+	int val = value << offset;
+
+	tb10x_set_bits(tb10x_gpio, OFFSET_TO_REG_DATA, mask, val);
+}
+
+static int tb10x_gpio_direction_out(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	struct tb10x_gpio *tb10x_gpio = to_tb10x_gpio(chip);
+	int mask = BIT(offset);
+	int val = TB10X_GPIO_DIR_OUT << offset;
+
+	tb10x_set_bits(tb10x_gpio, OFFSET_TO_REG_DDR, mask, val);
+
+	return 0;
+}
+
+static int tb10x_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void tb10x_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	pinctrl_free_gpio(chip->base + offset);
+}
+
+static int tb10x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct tb10x_gpio *tb10x_gpio = to_tb10x_gpio(chip);
+
+	return irq_create_mapping(tb10x_gpio->domain, offset);
+}
+
+static int tb10x_gpio_irq_set_type(struct irq_data *data, unsigned int type)
+{
+	if ((type & IRQF_TRIGGER_MASK) != IRQ_TYPE_EDGE_BOTH) {
+		pr_err("Only (both) edge triggered interrupts supported.\n");
+		return -EINVAL;
+	}
+
+	irqd_set_trigger_type(data, type);
+
+	return IRQ_SET_MASK_OK;
+}
+
+static irqreturn_t tb10x_gpio_irq_cascade(int irq, void *data)
+{
+	struct tb10x_gpio *tb10x_gpio = data;
+	u32 r = tb10x_reg_read(tb10x_gpio, OFFSET_TO_REG_CHANGE);
+	u32 m = tb10x_reg_read(tb10x_gpio, OFFSET_TO_REG_INT_EN);
+	const unsigned long bits = r & m;
+	int i;
+
+	for_each_set_bit(i, &bits, 32)
+		generic_handle_irq(irq_find_mapping(tb10x_gpio->domain, i));
+
+	return IRQ_HANDLED;
+}
+
+static int tb10x_gpio_probe(struct platform_device *pdev)
+{
+	struct tb10x_gpio *tb10x_gpio;
+	struct resource *mem;
+	struct device_node *dn = pdev->dev.of_node;
+	int ret = -EBUSY;
+	u32 ngpio;
+
+	if (!dn)
+		return -EINVAL;
+
+	if (of_property_read_u32(dn, "abilis,ngpio", &ngpio))
+		return -EINVAL;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "No memory resource defined.\n");
+		return -EINVAL;
+	}
+
+	tb10x_gpio = devm_kzalloc(&pdev->dev, sizeof(*tb10x_gpio), GFP_KERNEL);
+	if (tb10x_gpio == NULL)
+		return -ENOMEM;
+
+	spin_lock_init(&tb10x_gpio->spinlock);
+
+	tb10x_gpio->base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(tb10x_gpio->base))
+		return PTR_ERR(tb10x_gpio->base);
+
+	tb10x_gpio->gc.label		= of_node_full_name(dn);
+	tb10x_gpio->gc.dev		= &pdev->dev;
+	tb10x_gpio->gc.owner		= THIS_MODULE;
+	tb10x_gpio->gc.direction_input	= tb10x_gpio_direction_in;
+	tb10x_gpio->gc.get		= tb10x_gpio_get;
+	tb10x_gpio->gc.direction_output	= tb10x_gpio_direction_out;
+	tb10x_gpio->gc.set		= tb10x_gpio_set;
+	tb10x_gpio->gc.request		= tb10x_gpio_request;
+	tb10x_gpio->gc.free		= tb10x_gpio_free;
+	tb10x_gpio->gc.base		= -1;
+	tb10x_gpio->gc.ngpio		= ngpio;
+	tb10x_gpio->gc.can_sleep	= 0;
+
+
+	ret = gpiochip_add(&tb10x_gpio->gc);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Could not add gpiochip.\n");
+		goto fail_gpiochip_registration;
+	}
+
+	platform_set_drvdata(pdev, tb10x_gpio);
+
+	if (of_find_property(dn, "interrupt-controller", NULL)) {
+		struct irq_chip_generic *gc;
+
+		ret = platform_get_irq(pdev, 0);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "No interrupt specified.\n");
+			goto fail_get_irq;
+		}
+
+		tb10x_gpio->gc.to_irq	= tb10x_gpio_to_irq;
+		tb10x_gpio->irq		= ret;
+
+		ret = devm_request_irq(&pdev->dev, ret, tb10x_gpio_irq_cascade,
+				IRQF_TRIGGER_NONE | IRQF_SHARED,
+				dev_name(&pdev->dev), tb10x_gpio);
+		if (ret != 0)
+			goto fail_request_irq;
+
+		tb10x_gpio->domain = irq_domain_add_linear(dn,
+						tb10x_gpio->gc.ngpio,
+						&irq_generic_chip_ops, NULL);
+		if (!tb10x_gpio->domain) {
+			ret = -ENOMEM;
+			goto fail_irq_domain;
+		}
+
+		ret = irq_alloc_domain_generic_chips(tb10x_gpio->domain,
+				tb10x_gpio->gc.ngpio, 1, tb10x_gpio->gc.label,
+				handle_edge_irq, IRQ_NOREQUEST, IRQ_NOPROBE,
+				IRQ_GC_INIT_MASK_CACHE);
+		if (ret)
+			goto fail_irq_domain;
+
+		gc = tb10x_gpio->domain->gc->gc[0];
+		gc->reg_base                         = tb10x_gpio->base;
+		gc->chip_types[0].type               = IRQ_TYPE_EDGE_BOTH;
+		gc->chip_types[0].chip.irq_ack       = irq_gc_ack_set_bit;
+		gc->chip_types[0].chip.irq_mask      = irq_gc_mask_clr_bit;
+		gc->chip_types[0].chip.irq_unmask    = irq_gc_mask_set_bit;
+		gc->chip_types[0].chip.irq_set_type  = tb10x_gpio_irq_set_type;
+		gc->chip_types[0].regs.ack           = OFFSET_TO_REG_CHANGE;
+		gc->chip_types[0].regs.mask          = OFFSET_TO_REG_INT_EN;
+	}
+
+	return 0;
+
+fail_irq_domain:
+fail_request_irq:
+fail_get_irq:
+	gpiochip_remove(&tb10x_gpio->gc);
+fail_gpiochip_registration:
+fail_ioremap:
+	return ret;
+}
+
+static int __exit tb10x_gpio_remove(struct platform_device *pdev)
+{
+	struct tb10x_gpio *tb10x_gpio = platform_get_drvdata(pdev);
+	int ret;
+
+	if (tb10x_gpio->gc.to_irq) {
+		irq_remove_generic_chip(tb10x_gpio->domain->gc->gc[0],
+					BIT(tb10x_gpio->gc.ngpio) - 1, 0, 0);
+		kfree(tb10x_gpio->domain->gc);
+		irq_domain_remove(tb10x_gpio->domain);
+		free_irq(tb10x_gpio->irq, tb10x_gpio);
+	}
+	ret = gpiochip_remove(&tb10x_gpio->gc);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct of_device_id tb10x_gpio_dt_ids[] = {
+	{ .compatible = "abilis,tb10x-gpio" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, tb10x_gpio_dt_ids);
+
+static struct platform_driver tb10x_gpio_driver = {
+	.probe		= tb10x_gpio_probe,
+	.remove		= tb10x_gpio_remove,
+	.driver = {
+		.name	= "tb10x-gpio",
+		.of_match_table = of_match_ptr(tb10x_gpio_dt_ids),
+		.owner	= THIS_MODULE,
+	}
+};
+
+module_platform_driver(tb10x_gpio_driver);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("tb10x gpio.");
+MODULE_VERSION("0.0.1");
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
index 4a5de27..ddb5fef 100644
--- a/drivers/gpio/gpio-tc3589x.c
+++ b/drivers/gpio/gpio-tc3589x.c
@@ -96,27 +96,27 @@
 }
 
 /**
- * tc3589x_gpio_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
+ * tc3589x_gpio_irq_get_irq(): Map a hardware IRQ on a chip to a Linux IRQ
  *
  * @tc3589x_gpio: tc3589x_gpio_irq controller to operate on.
- * @irq: index of the interrupt requested in the chip IRQs
+ * @irq: index of the hardware interrupt requested in the chip IRQs
  *
  * Useful for drivers to request their own IRQs.
  */
-static int tc3589x_gpio_irq_get_virq(struct tc3589x_gpio *tc3589x_gpio,
-				     int irq)
+static int tc3589x_gpio_irq_get_irq(struct tc3589x_gpio *tc3589x_gpio,
+				     int hwirq)
 {
 	if (!tc3589x_gpio)
 		return -EINVAL;
 
-	return irq_create_mapping(tc3589x_gpio->domain, irq);
+	return irq_create_mapping(tc3589x_gpio->domain, hwirq);
 }
 
 static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
 	struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
 
-	return tc3589x_gpio_irq_get_virq(tc3589x_gpio, offset);
+	return tc3589x_gpio_irq_get_irq(tc3589x_gpio, offset);
 }
 
 static struct gpio_chip template_chip = {
@@ -242,9 +242,9 @@
 		while (stat) {
 			int bit = __ffs(stat);
 			int line = i * 8 + bit;
-			int virq = tc3589x_gpio_irq_get_virq(tc3589x_gpio, line);
+			int irq = tc3589x_gpio_irq_get_irq(tc3589x_gpio, line);
 
-			handle_nested_irq(virq);
+			handle_nested_irq(irq);
 			stat &= ~(1 << bit);
 		}
 
@@ -254,31 +254,31 @@
 	return IRQ_HANDLED;
 }
 
-static int tc3589x_gpio_irq_map(struct irq_domain *d, unsigned int virq,
+static int tc3589x_gpio_irq_map(struct irq_domain *d, unsigned int irq,
 				irq_hw_number_t hwirq)
 {
 	struct tc3589x *tc3589x_gpio = d->host_data;
 
-	irq_set_chip_data(virq, tc3589x_gpio);
-	irq_set_chip_and_handler(virq, &tc3589x_gpio_irq_chip,
+	irq_set_chip_data(irq, tc3589x_gpio);
+	irq_set_chip_and_handler(irq, &tc3589x_gpio_irq_chip,
 				handle_simple_irq);
-	irq_set_nested_thread(virq, 1);
+	irq_set_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
-	set_irq_flags(virq, IRQF_VALID);
+	set_irq_flags(irq, IRQF_VALID);
 #else
-	irq_set_noprobe(virq);
+	irq_set_noprobe(irq);
 #endif
 
 	return 0;
 }
 
-static void tc3589x_gpio_irq_unmap(struct irq_domain *d, unsigned int virq)
+static void tc3589x_gpio_irq_unmap(struct irq_domain *d, unsigned int irq)
 {
 #ifdef CONFIG_ARM
-	set_irq_flags(virq, 0);
+	set_irq_flags(irq, 0);
 #endif
-	irq_set_chip_and_handler(virq, NULL, NULL);
-	irq_set_chip_data(virq, NULL);
+	irq_set_chip_and_handler(irq, NULL, NULL);
+	irq_set_chip_data(irq, NULL);
 }
 
 static struct irq_domain_ops tc3589x_irq_ops = {
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 9a62672..cfd3b90 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -75,6 +75,7 @@
 #endif
 };
 
+static struct device *dev;
 static struct irq_domain *irq_domain;
 static void __iomem *regs;
 static u32 tegra_gpio_bank_count;
@@ -205,6 +206,7 @@
 	int lvl_type;
 	int val;
 	unsigned long flags;
+	int ret;
 
 	switch (type & IRQ_TYPE_SENSE_MASK) {
 	case IRQ_TYPE_EDGE_RISING:
@@ -231,6 +233,12 @@
 		return -EINVAL;
 	}
 
+	ret = gpio_lock_as_irq(&tegra_gpio_chip, gpio);
+	if (ret) {
+		dev_err(dev, "unable to lock Tegra GPIO %d as IRQ\n", gpio);
+		return ret;
+	}
+
 	spin_lock_irqsave(&bank->lvl_lock[port], flags);
 
 	val = tegra_gpio_readl(GPIO_INT_LVL(gpio));
@@ -251,6 +259,13 @@
 	return 0;
 }
 
+static void tegra_gpio_irq_shutdown(struct irq_data *d)
+{
+	int gpio = d->hwirq;
+
+	gpio_unlock_as_irq(&tegra_gpio_chip, gpio);
+}
+
 static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
 	struct tegra_gpio_bank *bank;
@@ -368,6 +383,7 @@
 	.irq_mask	= tegra_gpio_irq_mask,
 	.irq_unmask	= tegra_gpio_irq_unmask,
 	.irq_set_type	= tegra_gpio_irq_set_type,
+	.irq_shutdown	= tegra_gpio_irq_shutdown,
 #ifdef CONFIG_PM_SLEEP
 	.irq_set_wake	= tegra_gpio_irq_set_wake,
 #endif
@@ -413,6 +429,8 @@
 	int i;
 	int j;
 
+	dev = &pdev->dev;
+
 	match = of_match_device(tegra_gpio_of_match, &pdev->dev);
 	if (!match) {
 		dev_err(&pdev->dev, "Error: No device match found\n");
diff --git a/drivers/gpio/gpio-tnetv107x.c b/drivers/gpio/gpio-tnetv107x.c
index 3fa3e28..58445bb 100644
--- a/drivers/gpio/gpio-tnetv107x.c
+++ b/drivers/gpio/gpio-tnetv107x.c
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/gpio.h>
+#include <linux/platform_data/gpio-davinci.h>
 
 #include <mach/common.h>
 #include <mach/tnetv107x.h>
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
index d8e4f6e..0c7e891 100644
--- a/drivers/gpio/gpio-twl4030.c
+++ b/drivers/gpio/gpio-twl4030.c
@@ -594,7 +594,7 @@
 	.driver = {
 		.name	= "twl4030_gpio",
 		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(twl_gpio_match),
+		.of_match_table = twl_gpio_match,
 	},
 	.probe		= gpio_twl4030_probe,
 	.remove		= gpio_twl4030_remove,
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 5c1ef2b..ae0ffdc 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -11,7 +11,7 @@
  */
 
 #include <linux/errno.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/export.h>
 #include <linux/acpi_gpio.h>
 #include <linux/acpi.h>
@@ -33,14 +33,15 @@
 }
 
 /**
- * acpi_get_gpio() - Translate ACPI GPIO pin to GPIO number usable with GPIO API
+ * acpi_get_gpiod() - Translate ACPI GPIO pin to GPIO descriptor usable with GPIO API
  * @path:	ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1")
  * @pin:	ACPI GPIO pin number (0-based, controller-relative)
  *
- * Returns GPIO number to use with Linux generic GPIO API, or errno error value
+ * Returns GPIO descriptor to use with Linux generic GPIO API, or ERR_PTR
+ * error value
  */
 
-int acpi_get_gpio(char *path, int pin)
+static struct gpio_desc *acpi_get_gpiod(char *path, int pin)
 {
 	struct gpio_chip *chip;
 	acpi_handle handle;
@@ -48,18 +49,17 @@
 
 	status = acpi_get_handle(NULL, path, &handle);
 	if (ACPI_FAILURE(status))
-		return -ENODEV;
+		return ERR_PTR(-ENODEV);
 
 	chip = gpiochip_find(handle, acpi_gpiochip_find);
 	if (!chip)
-		return -ENODEV;
+		return ERR_PTR(-ENODEV);
 
-	if (!gpio_is_valid(chip->base + pin))
-		return -EINVAL;
+	if (pin < 0 || pin > chip->ngpio)
+		return ERR_PTR(-EINVAL);
 
-	return chip->base + pin;
+	return gpio_to_desc(chip->base + pin);
 }
-EXPORT_SYMBOL_GPL(acpi_get_gpio);
 
 static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)
 {
@@ -73,15 +73,8 @@
 static irqreturn_t acpi_gpio_irq_handler_evt(int irq, void *data)
 {
 	struct acpi_gpio_evt_pin *evt_pin = data;
-	struct acpi_object_list args;
-	union acpi_object arg;
 
-	arg.type = ACPI_TYPE_INTEGER;
-	arg.integer.value = evt_pin->pin;
-	args.count = 1;
-	args.pointer = &arg;
-
-	acpi_evaluate_object(evt_pin->evt_handle, NULL, &args, NULL);
+	acpi_execute_simple_method(evt_pin->evt_handle, NULL, evt_pin->pin);
 
 	return IRQ_HANDLED;
 }
@@ -201,84 +194,6 @@
 }
 EXPORT_SYMBOL(acpi_gpiochip_request_interrupts);
 
-struct acpi_gpio_lookup {
-	struct acpi_gpio_info info;
-	int index;
-	int gpio;
-	int n;
-};
-
-static int acpi_find_gpio(struct acpi_resource *ares, void *data)
-{
-	struct acpi_gpio_lookup *lookup = data;
-
-	if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
-		return 1;
-
-	if (lookup->n++ == lookup->index && lookup->gpio < 0) {
-		const struct acpi_resource_gpio *agpio = &ares->data.gpio;
-
-		lookup->gpio = acpi_get_gpio(agpio->resource_source.string_ptr,
-					     agpio->pin_table[0]);
-		lookup->info.gpioint =
-			agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
-	}
-
-	return 1;
-}
-
-/**
- * acpi_get_gpio_by_index() - get a GPIO number from device resources
- * @dev: pointer to a device to get GPIO from
- * @index: index of GpioIo/GpioInt resource (starting from %0)
- * @info: info pointer to fill in (optional)
- *
- * Function goes through ACPI resources for @dev and based on @index looks
- * up a GpioIo/GpioInt resource, translates it to the Linux GPIO number,
- * and returns it. @index matches GpioIo/GpioInt resources only so if there
- * are total %3 GPIO resources, the index goes from %0 to %2.
- *
- * If the GPIO cannot be translated or there is an error, negative errno is
- * returned.
- *
- * Note: if the GPIO resource has multiple entries in the pin list, this
- * function only returns the first.
- */
-int acpi_get_gpio_by_index(struct device *dev, int index,
-			   struct acpi_gpio_info *info)
-{
-	struct acpi_gpio_lookup lookup;
-	struct list_head resource_list;
-	struct acpi_device *adev;
-	acpi_handle handle;
-	int ret;
-
-	if (!dev)
-		return -EINVAL;
-
-	handle = ACPI_HANDLE(dev);
-	if (!handle || acpi_bus_get_device(handle, &adev))
-		return -ENODEV;
-
-	memset(&lookup, 0, sizeof(lookup));
-	lookup.index = index;
-	lookup.gpio = -ENODEV;
-
-	INIT_LIST_HEAD(&resource_list);
-	ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
-				     &lookup);
-	if (ret < 0)
-		return ret;
-
-	acpi_dev_free_resource_list(&resource_list);
-
-	if (lookup.gpio >= 0 && info)
-		*info = lookup.info;
-
-	return lookup.gpio;
-}
-EXPORT_SYMBOL_GPL(acpi_get_gpio_by_index);
-
 /**
  * acpi_gpiochip_free_interrupts() - Free GPIO _EVT ACPI event interrupts.
  * @chip:      gpio chip
@@ -316,3 +231,82 @@
 	kfree(evt_pins);
 }
 EXPORT_SYMBOL(acpi_gpiochip_free_interrupts);
+
+struct acpi_gpio_lookup {
+	struct acpi_gpio_info info;
+	int index;
+	struct gpio_desc *desc;
+	int n;
+};
+
+static int acpi_find_gpio(struct acpi_resource *ares, void *data)
+{
+	struct acpi_gpio_lookup *lookup = data;
+
+	if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
+		return 1;
+
+	if (lookup->n++ == lookup->index && !lookup->desc) {
+		const struct acpi_resource_gpio *agpio = &ares->data.gpio;
+
+		lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr,
+					      agpio->pin_table[0]);
+		lookup->info.gpioint =
+			agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
+		lookup->info.active_low =
+			agpio->polarity == ACPI_ACTIVE_LOW;
+	}
+
+	return 1;
+}
+
+/**
+ * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources
+ * @dev: pointer to a device to get GPIO from
+ * @index: index of GpioIo/GpioInt resource (starting from %0)
+ * @info: info pointer to fill in (optional)
+ *
+ * Function goes through ACPI resources for @dev and based on @index looks
+ * up a GpioIo/GpioInt resource, translates it to the Linux GPIO descriptor,
+ * and returns it. @index matches GpioIo/GpioInt resources only so if there
+ * are total %3 GPIO resources, the index goes from %0 to %2.
+ *
+ * If the GPIO cannot be translated or there is an error an ERR_PTR is
+ * returned.
+ *
+ * Note: if the GPIO resource has multiple entries in the pin list, this
+ * function only returns the first.
+ */
+struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
+					  struct acpi_gpio_info *info)
+{
+	struct acpi_gpio_lookup lookup;
+	struct list_head resource_list;
+	struct acpi_device *adev;
+	acpi_handle handle;
+	int ret;
+
+	if (!dev)
+		return ERR_PTR(-EINVAL);
+
+	handle = ACPI_HANDLE(dev);
+	if (!handle || acpi_bus_get_device(handle, &adev))
+		return ERR_PTR(-ENODEV);
+
+	memset(&lookup, 0, sizeof(lookup));
+	lookup.index = index;
+
+	INIT_LIST_HEAD(&resource_list);
+	ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
+				     &lookup);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	acpi_dev_free_resource_list(&resource_list);
+
+	if (lookup.desc && info)
+		*info = lookup.info;
+
+	return lookup.desc ? lookup.desc : ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL_GPL(acpi_get_gpiod_by_index);
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index 0dfaf20..e0a98f5 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -15,19 +15,21 @@
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/io.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_gpio.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/slab.h>
 
+struct gpio_desc;
+
 /* Private data structure for of_gpiochip_find_and_xlate */
 struct gg_data {
 	enum of_gpio_flags *flags;
 	struct of_phandle_args gpiospec;
 
-	int out_gpio;
+	struct gpio_desc *out_gpio;
 };
 
 /* Private function for resolving node pointer to gpio_chip */
@@ -45,28 +47,31 @@
 	if (ret < 0)
 		return false;
 
-	gg_data->out_gpio = ret + gc->base;
+	gg_data->out_gpio = gpio_to_desc(ret + gc->base);
 	return true;
 }
 
 /**
- * of_get_named_gpio_flags() - Get a GPIO number and flags to use with GPIO API
+ * of_get_named_gpiod_flags() - Get a GPIO descriptor and flags for GPIO API
  * @np:		device node to get GPIO from
  * @propname:	property name containing gpio specifier(s)
  * @index:	index of the GPIO
  * @flags:	a flags pointer to fill in
  *
- * Returns GPIO number to use with Linux generic GPIO API, or one of the errno
+ * Returns GPIO descriptor to use with Linux GPIO API, or one of the errno
  * value on the error condition. If @flags is not NULL the function also fills
  * in flags for the GPIO.
  */
-int of_get_named_gpio_flags(struct device_node *np, const char *propname,
-			   int index, enum of_gpio_flags *flags)
+struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
+		     const char *propname, int index, enum of_gpio_flags *flags)
 {
 	/* Return -EPROBE_DEFER to support probe() functions to be called
 	 * later when the GPIO actually becomes available
 	 */
-	struct gg_data gg_data = { .flags = flags, .out_gpio = -EPROBE_DEFER };
+	struct gg_data gg_data = {
+		.flags = flags,
+		.out_gpio = ERR_PTR(-EPROBE_DEFER)
+	};
 	int ret;
 
 	/* .of_xlate might decide to not fill in the flags, so clear it. */
@@ -78,16 +83,17 @@
 	if (ret) {
 		pr_debug("%s: can't parse gpios property of node '%s[%d]'\n",
 			__func__, np->full_name, index);
-		return ret;
+		return ERR_PTR(ret);
 	}
 
 	gpiochip_find(&gg_data, of_gpiochip_find_and_xlate);
 
 	of_node_put(gg_data.gpiospec.np);
-	pr_debug("%s exited with status %d\n", __func__, gg_data.out_gpio);
+	pr_debug("%s exited with status %d\n", __func__,
+		 PTR_RET(gg_data.out_gpio));
 	return gg_data.out_gpio;
 }
-EXPORT_SYMBOL(of_get_named_gpio_flags);
+EXPORT_SYMBOL(of_get_named_gpiod_flags);
 
 /**
  * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags
@@ -190,10 +196,15 @@
 	struct of_phandle_args pinspec;
 	struct pinctrl_dev *pctldev;
 	int index = 0, ret;
+	const char *name;
+	static const char group_names_propname[] = "gpio-ranges-group-names";
+	struct property *group_names;
 
 	if (!np)
 		return;
 
+	group_names = of_find_property(np, group_names_propname, NULL);
+
 	for (;; index++) {
 		ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3,
 				index, &pinspec);
@@ -204,14 +215,56 @@
 		if (!pctldev)
 			break;
 
-		ret = gpiochip_add_pin_range(chip,
-					     pinctrl_dev_get_devname(pctldev),
-					     pinspec.args[0],
-					     pinspec.args[1],
-					     pinspec.args[2]);
+		if (pinspec.args[2]) {
+			if (group_names) {
+				ret = of_property_read_string_index(np,
+						group_names_propname,
+						index, &name);
+				if (strlen(name)) {
+					pr_err("%s: Group name of numeric GPIO ranges must be the empty string.\n",
+						np->full_name);
+					break;
+				}
+			}
+			/* npins != 0: linear range */
+			ret = gpiochip_add_pin_range(chip,
+					pinctrl_dev_get_devname(pctldev),
+					pinspec.args[0],
+					pinspec.args[1],
+					pinspec.args[2]);
+			if (ret)
+				break;
+		} else {
+			/* npins == 0: special range */
+			if (pinspec.args[1]) {
+				pr_err("%s: Illegal gpio-range format.\n",
+					np->full_name);
+				break;
+			}
 
-		if (ret)
-			break;
+			if (!group_names) {
+				pr_err("%s: GPIO group range requested but no %s property.\n",
+					np->full_name, group_names_propname);
+				break;
+			}
+
+			ret = of_property_read_string_index(np,
+						group_names_propname,
+						index, &name);
+			if (ret)
+				break;
+
+			if (!strlen(name)) {
+				pr_err("%s: Group name of GPIO group range cannot be the empty string.\n",
+				np->full_name);
+				break;
+			}
+
+			ret = gpiochip_add_pingroup_range(chip, pctldev,
+						pinspec.args[0], name);
+			if (ret)
+				break;
+		}
 	}
 }
 
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 86ef346..7dd4461 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -10,22 +10,18 @@
 #include <linux/seq_file.h>
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
+#include <linux/acpi_gpio.h>
 #include <linux/idr.h>
 #include <linux/slab.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/gpio.h>
 
-/* Optional implementation infrastructure for GPIO interfaces.
+/* Implementation infrastructure for GPIO interfaces.
  *
- * Platforms may want to use this if they tend to use very many GPIOs
- * that aren't part of a System-On-Chip core; or across I2C/SPI/etc.
- *
- * When kernel footprint or instruction count is an issue, simpler
- * implementations may be preferred.  The GPIO programming interface
- * allows for inlining speed-critical get/set operations for common
- * cases, so that access to SOC-integrated GPIOs can sometimes cost
- * only an instruction or two per bit.
+ * The GPIO programming interface allows for inlining speed-critical
+ * get/set operations for common cases, so that access to SOC-integrated
+ * GPIOs can sometimes cost only an instruction or two per bit.
  */
 
 
@@ -57,9 +53,10 @@
 #define FLAG_SYSFS	3	/* exported via /sys/class/gpio/control */
 #define FLAG_TRIG_FALL	4	/* trigger on falling edge */
 #define FLAG_TRIG_RISE	5	/* trigger on rising edge */
-#define FLAG_ACTIVE_LOW	6	/* sysfs value has active low */
+#define FLAG_ACTIVE_LOW	6	/* value has active low */
 #define FLAG_OPEN_DRAIN	7	/* Gpio is open drain type */
 #define FLAG_OPEN_SOURCE 8	/* Gpio is open source type */
+#define FLAG_USED_AS_IRQ 9	/* GPIO is connected to an IRQ */
 
 #define ID_SHIFT	16	/* add new flags before this one */
 
@@ -74,34 +71,50 @@
 
 #define GPIO_OFFSET_VALID(chip, offset) (offset >= 0 && offset < chip->ngpio)
 
+static DEFINE_MUTEX(gpio_lookup_lock);
+static LIST_HEAD(gpio_lookup_list);
 static LIST_HEAD(gpio_chips);
 
 #ifdef CONFIG_GPIO_SYSFS
 static DEFINE_IDR(dirent_idr);
 #endif
 
-/*
- * Internal gpiod_* API using descriptors instead of the integer namespace.
- * Most of this should eventually go public.
- */
 static int gpiod_request(struct gpio_desc *desc, const char *label);
 static void gpiod_free(struct gpio_desc *desc);
-static int gpiod_direction_input(struct gpio_desc *desc);
-static int gpiod_direction_output(struct gpio_desc *desc, int value);
-static int gpiod_get_direction(const struct gpio_desc *desc);
-static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce);
-static int gpiod_get_value_cansleep(const struct gpio_desc *desc);
-static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value);
-static int gpiod_get_value(const struct gpio_desc *desc);
-static void gpiod_set_value(struct gpio_desc *desc, int value);
-static int gpiod_cansleep(const struct gpio_desc *desc);
-static int gpiod_to_irq(const struct gpio_desc *desc);
-static int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
-static int gpiod_export_link(struct device *dev, const char *name,
-			     struct gpio_desc *desc);
-static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value);
-static void gpiod_unexport(struct gpio_desc *desc);
 
+#ifdef CONFIG_DEBUG_FS
+#define gpiod_emerg(desc, fmt, ...)			                \
+	pr_emerg("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \
+                 ##__VA_ARGS__)
+#define gpiod_crit(desc, fmt, ...)			                \
+	pr_crit("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label,  \
+                 ##__VA_ARGS__)
+#define gpiod_err(desc, fmt, ...)				        \
+	pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label,   \
+                 ##__VA_ARGS__)
+#define gpiod_warn(desc, fmt, ...)				        \
+	pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label,  \
+                 ##__VA_ARGS__)
+#define gpiod_info(desc, fmt, ...)				        \
+	pr_info("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label,  \
+                ##__VA_ARGS__)
+#define gpiod_dbg(desc, fmt, ...)				   \
+	pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \
+                 ##__VA_ARGS__)
+#else
+#define gpiod_emerg(desc, fmt, ...)			           \
+	pr_emerg("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
+#define gpiod_crit(desc, fmt, ...)			           \
+	pr_crit("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
+#define gpiod_err(desc, fmt, ...)				   \
+	pr_err("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
+#define gpiod_warn(desc, fmt, ...)				   \
+	pr_warn("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
+#define gpiod_info(desc, fmt, ...)				   \
+	pr_info("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
+#define gpiod_dbg(desc, fmt, ...)				   \
+	pr_debug("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
+#endif
 
 static inline void desc_set_label(struct gpio_desc *d, const char *label)
 {
@@ -121,23 +134,36 @@
 /**
  * Convert a GPIO number to its descriptor
  */
-static struct gpio_desc *gpio_to_desc(unsigned gpio)
+struct gpio_desc *gpio_to_desc(unsigned gpio)
 {
 	if (WARN(!gpio_is_valid(gpio), "invalid GPIO %d\n", gpio))
 		return NULL;
 	else
 		return &gpio_desc[gpio];
 }
+EXPORT_SYMBOL_GPL(gpio_to_desc);
+
+/**
+ * Convert an offset on a certain chip to a corresponding descriptor
+ */
+static struct gpio_desc *gpiochip_offset_to_desc(struct gpio_chip *chip,
+						 unsigned int offset)
+{
+	unsigned int gpio = chip->base + offset;
+
+	return gpio_to_desc(gpio);
+}
 
 /**
  * Convert a GPIO descriptor to the integer namespace.
  * This should disappear in the future but is needed since we still
  * use GPIO numbers for error messages and sysfs nodes
  */
-static int desc_to_gpio(const struct gpio_desc *desc)
+int desc_to_gpio(const struct gpio_desc *desc)
 {
-	return desc->chip->base + gpio_chip_hwgpio(desc);
+	return desc - &gpio_desc[0];
 }
+EXPORT_SYMBOL_GPL(desc_to_gpio);
 
 
 /* Warn when drivers omit gpio_request() calls -- legal but ill-advised
@@ -172,16 +198,15 @@
 	return 0;
 }
 
-static struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
+/**
+ * gpiod_to_chip - Return the GPIO chip to which a GPIO descriptor belongs
+ * @desc:	descriptor to return the chip of
+ */
+struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
 {
 	return desc ? desc->chip : NULL;
 }
-
-/* caller holds gpio_lock *OR* gpio is marked as requested */
-struct gpio_chip *gpio_to_chip(unsigned gpio)
-{
-	return gpiod_to_chip(gpio_to_desc(gpio));
-}
+EXPORT_SYMBOL_GPL(gpiod_to_chip);
 
 /* dynamic allocation of GPIOs, e.g. on a hotplugged device */
 static int gpiochip_find_base(int ngpio)
@@ -207,8 +232,15 @@
 	}
 }
 
-/* caller ensures gpio is valid and requested, chip->get_direction may sleep  */
-static int gpiod_get_direction(const struct gpio_desc *desc)
+/**
+ * gpiod_get_direction - return the current direction of a GPIO
+ * @desc:	GPIO to get the direction of
+ *
+ * Return GPIOF_DIR_IN or GPIOF_DIR_OUT, or an error code in case of error.
+ *
+ * This function may sleep if gpiod_cansleep() is true.
+ */
+int gpiod_get_direction(const struct gpio_desc *desc)
 {
 	struct gpio_chip	*chip;
 	unsigned		offset;
@@ -234,6 +266,7 @@
 	}
 	return status;
 }
+EXPORT_SYMBOL_GPL(gpiod_get_direction);
 
 #ifdef CONFIG_GPIO_SYSFS
 
@@ -318,17 +351,10 @@
 
 	mutex_lock(&sysfs_lock);
 
-	if (!test_bit(FLAG_EXPORT, &desc->flags)) {
+	if (!test_bit(FLAG_EXPORT, &desc->flags))
 		status = -EIO;
-	} else {
-		int value;
-
-		value = !!gpiod_get_value_cansleep(desc);
-		if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
-			value = !value;
-
-		status = sprintf(buf, "%d\n", value);
-	}
+	else
+		status = sprintf(buf, "%d\n", gpiod_get_value_cansleep(desc));
 
 	mutex_unlock(&sysfs_lock);
 	return status;
@@ -351,9 +377,7 @@
 
 		status = kstrtol(buf, 0, &value);
 		if (status == 0) {
-			if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
-				value = !value;
-			gpiod_set_value_cansleep(desc, value != 0);
+			gpiod_set_value_cansleep(desc, value);
 			status = size;
 		}
 	}
@@ -395,6 +419,7 @@
 	desc->flags &= ~GPIO_TRIGGER_MASK;
 
 	if (!gpio_flags) {
+		gpiod_unlock_as_irq(desc);
 		ret = 0;
 		goto free_id;
 	}
@@ -408,7 +433,7 @@
 			IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
 
 	if (!value_sd) {
-		value_sd = sysfs_get_dirent(dev->kobj.sd, NULL, "value");
+		value_sd = sysfs_get_dirent(dev->kobj.sd, "value");
 		if (!value_sd) {
 			ret = -ENODEV;
 			goto err_out;
@@ -433,6 +458,12 @@
 	if (ret < 0)
 		goto free_id;
 
+	ret = gpiod_lock_as_irq(desc);
+	if (ret < 0) {
+		gpiod_warn(desc, "failed to flag the GPIO for IRQ\n");
+		goto free_id;
+	}
+
 	desc->flags |= gpio_flags;
 	return 0;
 
@@ -736,7 +767,7 @@
 
 
 /**
- * gpio_export - export a GPIO through sysfs
+ * gpiod_export - export a GPIO through sysfs
  * @gpio: gpio to make available, already requested
  * @direction_may_change: true if userspace may change gpio direction
  * Context: arch_initcall or later
@@ -750,7 +781,7 @@
  *
  * Returns zero on success, else an error.
  */
-static int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
+int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
 {
 	unsigned long		flags;
 	int			status;
@@ -828,12 +859,7 @@
 		 status);
 	return status;
 }
-
-int gpio_export(unsigned gpio, bool direction_may_change)
-{
-	return gpiod_export(gpio_to_desc(gpio), direction_may_change);
-}
-EXPORT_SYMBOL_GPL(gpio_export);
+EXPORT_SYMBOL_GPL(gpiod_export);
 
 static int match_export(struct device *dev, const void *data)
 {
@@ -841,7 +867,7 @@
 }
 
 /**
- * gpio_export_link - create a sysfs link to an exported GPIO node
+ * gpiod_export_link - create a sysfs link to an exported GPIO node
  * @dev: device under which to create symlink
  * @name: name of the symlink
  * @gpio: gpio to create symlink to, already exported
@@ -851,8 +877,8 @@
  *
  * Returns zero on success, else an error.
  */
-static int gpiod_export_link(struct device *dev, const char *name,
-			     struct gpio_desc *desc)
+int gpiod_export_link(struct device *dev, const char *name,
+		      struct gpio_desc *desc)
 {
 	int			status = -EINVAL;
 
@@ -883,15 +909,10 @@
 
 	return status;
 }
-
-int gpio_export_link(struct device *dev, const char *name, unsigned gpio)
-{
-	return gpiod_export_link(dev, name, gpio_to_desc(gpio));
-}
-EXPORT_SYMBOL_GPL(gpio_export_link);
+EXPORT_SYMBOL_GPL(gpiod_export_link);
 
 /**
- * gpio_sysfs_set_active_low - set the polarity of gpio sysfs value
+ * gpiod_sysfs_set_active_low - set the polarity of gpio sysfs value
  * @gpio: gpio to change
  * @value: non-zero to use active low, i.e. inverted values
  *
@@ -902,7 +923,7 @@
  *
  * Returns zero on success, else an error.
  */
-static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
+int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
 {
 	struct device		*dev = NULL;
 	int			status = -EINVAL;
@@ -933,20 +954,15 @@
 
 	return status;
 }
-
-int gpio_sysfs_set_active_low(unsigned gpio, int value)
-{
-	return gpiod_sysfs_set_active_low(gpio_to_desc(gpio), value);
-}
-EXPORT_SYMBOL_GPL(gpio_sysfs_set_active_low);
+EXPORT_SYMBOL_GPL(gpiod_sysfs_set_active_low);
 
 /**
- * gpio_unexport - reverse effect of gpio_export()
+ * gpiod_unexport - reverse effect of gpio_export()
  * @gpio: gpio to make unavailable
  *
  * This is implicit on gpio_free().
  */
-static void gpiod_unexport(struct gpio_desc *desc)
+void gpiod_unexport(struct gpio_desc *desc)
 {
 	int			status = 0;
 	struct device		*dev = NULL;
@@ -979,12 +995,7 @@
 		pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),
 			 status);
 }
-
-void gpio_unexport(unsigned gpio)
-{
-	gpiod_unexport(gpio_to_desc(gpio));
-}
-EXPORT_SYMBOL_GPL(gpio_unexport);
+EXPORT_SYMBOL_GPL(gpiod_unexport);
 
 static int gpiochip_export(struct gpio_chip *chip)
 {
@@ -1091,27 +1102,6 @@
 {
 }
 
-static inline int gpiod_export(struct gpio_desc *desc,
-			       bool direction_may_change)
-{
-	return -ENOSYS;
-}
-
-static inline int gpiod_export_link(struct device *dev, const char *name,
-				    struct gpio_desc *desc)
-{
-	return -ENOSYS;
-}
-
-static inline int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
-{
-	return -ENOSYS;
-}
-
-static inline void gpiod_unexport(struct gpio_desc *desc)
-{
-}
-
 #endif /* CONFIG_GPIO_SYSFS */
 
 /*
@@ -1320,6 +1310,53 @@
 #ifdef CONFIG_PINCTRL
 
 /**
+ * gpiochip_add_pingroup_range() - add a range for GPIO <-> pin mapping
+ * @chip: the gpiochip to add the range for
+ * @pinctrl: the dev_name() of the pin controller to map to
+ * @gpio_offset: the start offset in the current gpio_chip number space
+ * @pin_group: name of the pin group inside the pin controller
+ */
+int gpiochip_add_pingroup_range(struct gpio_chip *chip,
+			struct pinctrl_dev *pctldev,
+			unsigned int gpio_offset, const char *pin_group)
+{
+	struct gpio_pin_range *pin_range;
+	int ret;
+
+	pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL);
+	if (!pin_range) {
+		pr_err("%s: GPIO chip: failed to allocate pin ranges\n",
+				chip->label);
+		return -ENOMEM;
+	}
+
+	/* Use local offset as range ID */
+	pin_range->range.id = gpio_offset;
+	pin_range->range.gc = chip;
+	pin_range->range.name = chip->label;
+	pin_range->range.base = chip->base + gpio_offset;
+	pin_range->pctldev = pctldev;
+
+	ret = pinctrl_get_group_pins(pctldev, pin_group,
+					&pin_range->range.pins,
+					&pin_range->range.npins);
+	if (ret < 0)
+		return ret;
+
+	pinctrl_add_gpio_range(pctldev, &pin_range->range);
+
+	pr_debug("GPIO chip %s: created GPIO range %d->%d ==> %s PINGRP %s\n",
+		 chip->label, gpio_offset,
+		 gpio_offset + pin_range->range.npins - 1,
+		 pinctrl_dev_get_devname(pctldev), pin_group);
+
+	list_add_tail(&pin_range->node, &chip->pin_ranges);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range);
+
+/**
  * gpiochip_add_pin_range() - add a range for GPIO <-> pin mapping
  * @chip: the gpiochip to add the range for
  * @pinctrl_name: the dev_name() of the pin controller to map to
@@ -1398,7 +1435,7 @@
 	int			status = -EPROBE_DEFER;
 	unsigned long		flags;
 
-	if (!desc || !desc->chip) {
+	if (!desc) {
 		pr_warn("%s: invalid GPIO\n", __func__);
 		return -EINVAL;
 	}
@@ -1406,6 +1443,8 @@
 	spin_lock_irqsave(&gpio_lock, flags);
 
 	chip = desc->chip;
+	if (chip == NULL)
+		goto done;
 
 	if (!try_module_get(chip->owner))
 		goto done;
@@ -1621,7 +1660,16 @@
  * rely on gpio_request() having been called beforehand.
  */
 
-static int gpiod_direction_input(struct gpio_desc *desc)
+/**
+ * gpiod_direction_input - set the GPIO direction to input
+ * @desc:	GPIO to set to input
+ *
+ * Set the direction of the passed GPIO to input, such as gpiod_get_value() can
+ * be called safely on it.
+ *
+ * Return 0 in case of success, else an error code.
+ */
+int gpiod_direction_input(struct gpio_desc *desc)
 {
 	unsigned long		flags;
 	struct gpio_chip	*chip;
@@ -1635,8 +1683,9 @@
 
 	chip = desc->chip;
 	if (!chip->get || !chip->direction_input) {
-		pr_warn("%s: missing get() or direction_input() operations\n",
-			__func__);
+		gpiod_warn(desc,
+			"%s: missing get() or direction_input() operations\n",
+			 __func__);
 		return -EIO;
 	}
 
@@ -1656,8 +1705,7 @@
 	if (status) {
 		status = chip->request(chip, offset);
 		if (status < 0) {
-			pr_debug("GPIO-%d: chip request fail, %d\n",
-				desc_to_gpio(desc), status);
+			gpiod_dbg(desc, "chip request fail, %d\n", status);
 			/* and it's not available to anyone else ...
 			 * gpio_request() is the fully clean solution.
 			 */
@@ -1675,18 +1723,22 @@
 fail:
 	spin_unlock_irqrestore(&gpio_lock, flags);
 	if (status)
-		pr_debug("%s: gpio-%d status %d\n", __func__,
-			 desc_to_gpio(desc), status);
+		gpiod_dbg(desc, "%s status %d\n", __func__, status);
 	return status;
 }
+EXPORT_SYMBOL_GPL(gpiod_direction_input);
 
-int gpio_direction_input(unsigned gpio)
-{
-	return gpiod_direction_input(gpio_to_desc(gpio));
-}
-EXPORT_SYMBOL_GPL(gpio_direction_input);
-
-static int gpiod_direction_output(struct gpio_desc *desc, int value)
+/**
+ * gpiod_direction_output - set the GPIO direction to input
+ * @desc:	GPIO to set to output
+ * @value:	initial output value of the GPIO
+ *
+ * Set the direction of the passed GPIO to output, such as gpiod_set_value() can
+ * be called safely on it. The initial value of the output must be specified.
+ *
+ * Return 0 in case of success, else an error code.
+ */
+int gpiod_direction_output(struct gpio_desc *desc, int value)
 {
 	unsigned long		flags;
 	struct gpio_chip	*chip;
@@ -1698,6 +1750,14 @@
 		return -EINVAL;
 	}
 
+	/* GPIOs used for IRQs shall not be set as output */
+	if (test_bit(FLAG_USED_AS_IRQ, &desc->flags)) {
+		gpiod_err(desc,
+			  "%s: tried to set a GPIO tied to an IRQ as output\n",
+			  __func__);
+		return -EIO;
+	}
+
 	/* Open drain pin should not be driven to 1 */
 	if (value && test_bit(FLAG_OPEN_DRAIN,  &desc->flags))
 		return gpiod_direction_input(desc);
@@ -1708,8 +1768,9 @@
 
 	chip = desc->chip;
 	if (!chip->set || !chip->direction_output) {
-		pr_warn("%s: missing set() or direction_output() operations\n",
-			__func__);
+		gpiod_warn(desc,
+		       "%s: missing set() or direction_output() operations\n",
+		       __func__);
 		return -EIO;
 	}
 
@@ -1729,8 +1790,7 @@
 	if (status) {
 		status = chip->request(chip, offset);
 		if (status < 0) {
-			pr_debug("GPIO-%d: chip request fail, %d\n",
-				desc_to_gpio(desc), status);
+			gpiod_dbg(desc, "chip request fail, %d\n", status);
 			/* and it's not available to anyone else ...
 			 * gpio_request() is the fully clean solution.
 			 */
@@ -1748,26 +1808,20 @@
 fail:
 	spin_unlock_irqrestore(&gpio_lock, flags);
 	if (status)
-		pr_debug("%s: gpio-%d status %d\n", __func__,
-			 desc_to_gpio(desc), status);
+		gpiod_dbg(desc, "%s: gpio status %d\n", __func__, status);
 	return status;
 }
-
-int gpio_direction_output(unsigned gpio, int value)
-{
-	return gpiod_direction_output(gpio_to_desc(gpio), value);
-}
-EXPORT_SYMBOL_GPL(gpio_direction_output);
+EXPORT_SYMBOL_GPL(gpiod_direction_output);
 
 /**
- * gpio_set_debounce - sets @debounce time for a @gpio
+ * gpiod_set_debounce - sets @debounce time for a @gpio
  * @gpio: the gpio to set debounce time
  * @debounce: debounce time is microseconds
  *
  * returns -ENOTSUPP if the controller does not support setting
  * debounce.
  */
-static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
+int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
 {
 	unsigned long		flags;
 	struct gpio_chip	*chip;
@@ -1781,8 +1835,9 @@
 
 	chip = desc->chip;
 	if (!chip->set || !chip->set_debounce) {
-		pr_debug("%s: missing set() or set_debounce() operations\n",
-			__func__);
+		gpiod_dbg(desc,
+			  "%s: missing set() or set_debounce() operations\n",
+			  __func__);
 		return -ENOTSUPP;
 	}
 
@@ -1804,17 +1859,23 @@
 fail:
 	spin_unlock_irqrestore(&gpio_lock, flags);
 	if (status)
-		pr_debug("%s: gpio-%d status %d\n", __func__,
-			 desc_to_gpio(desc), status);
+		gpiod_dbg(desc, "%s: status %d\n", __func__, status);
 
 	return status;
 }
+EXPORT_SYMBOL_GPL(gpiod_set_debounce);
 
-int gpio_set_debounce(unsigned gpio, unsigned debounce)
+/**
+ * gpiod_is_active_low - test whether a GPIO is active-low or not
+ * @desc: the gpio descriptor to test
+ *
+ * Returns 1 if the GPIO is active-low, 0 otherwise.
+ */
+int gpiod_is_active_low(const struct gpio_desc *desc)
 {
-	return gpiod_set_debounce(gpio_to_desc(gpio), debounce);
+	return test_bit(FLAG_ACTIVE_LOW, &desc->flags);
 }
-EXPORT_SYMBOL_GPL(gpio_set_debounce);
+EXPORT_SYMBOL_GPL(gpiod_is_active_low);
 
 /* I/O calls are only valid after configuration completed; the relevant
  * "is this a valid GPIO" error checks should already have been done.
@@ -1838,42 +1899,68 @@
  * that the GPIO was actually requested.
  */
 
-/**
- * __gpio_get_value() - return a gpio's value
- * @gpio: gpio whose value will be returned
- * Context: any
- *
- * This is used directly or indirectly to implement gpio_get_value().
- * It returns the zero or nonzero value provided by the associated
- * gpio_chip.get() method; or zero if no such method is provided.
- */
-static int gpiod_get_value(const struct gpio_desc *desc)
+static int _gpiod_get_raw_value(const struct gpio_desc *desc)
 {
 	struct gpio_chip	*chip;
 	int value;
 	int offset;
 
-	if (!desc)
-		return 0;
 	chip = desc->chip;
 	offset = gpio_chip_hwgpio(desc);
-	/* Should be using gpio_get_value_cansleep() */
-	WARN_ON(chip->can_sleep);
 	value = chip->get ? chip->get(chip, offset) : 0;
 	trace_gpio_value(desc_to_gpio(desc), 1, value);
 	return value;
 }
 
-int __gpio_get_value(unsigned gpio)
+/**
+ * gpiod_get_raw_value() - return a gpio's raw value
+ * @desc: gpio whose value will be returned
+ *
+ * Return the GPIO's raw value, i.e. the value of the physical line disregarding
+ * its ACTIVE_LOW status.
+ *
+ * This function should be called from contexts where we cannot sleep, and will
+ * complain if the GPIO chip functions potentially sleep.
+ */
+int gpiod_get_raw_value(const struct gpio_desc *desc)
 {
-	return gpiod_get_value(gpio_to_desc(gpio));
+	if (!desc)
+		return 0;
+	/* Should be using gpio_get_value_cansleep() */
+	WARN_ON(desc->chip->can_sleep);
+	return _gpiod_get_raw_value(desc);
 }
-EXPORT_SYMBOL_GPL(__gpio_get_value);
+EXPORT_SYMBOL_GPL(gpiod_get_raw_value);
+
+/**
+ * gpiod_get_value() - return a gpio's value
+ * @desc: gpio whose value will be returned
+ *
+ * Return the GPIO's logical value, i.e. taking the ACTIVE_LOW status into
+ * account.
+ *
+ * This function should be called from contexts where we cannot sleep, and will
+ * complain if the GPIO chip functions potentially sleep.
+ */
+int gpiod_get_value(const struct gpio_desc *desc)
+{
+	int value;
+	if (!desc)
+		return 0;
+	/* Should be using gpio_get_value_cansleep() */
+	WARN_ON(desc->chip->can_sleep);
+
+	value = _gpiod_get_raw_value(desc);
+	if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
+		value = !value;
+
+	return value;
+}
+EXPORT_SYMBOL_GPL(gpiod_get_value);
 
 /*
  *  _gpio_set_open_drain_value() - Set the open drain gpio's value.
- * @gpio: Gpio whose state need to be set.
- * @chip: Gpio chip.
+ * @desc: gpio descriptor whose state need to be set.
  * @value: Non-zero for setting it HIGH otherise it will set to LOW.
  */
 static void _gpio_set_open_drain_value(struct gpio_desc *desc, int value)
@@ -1893,14 +1980,14 @@
 	}
 	trace_gpio_direction(desc_to_gpio(desc), value, err);
 	if (err < 0)
-		pr_err("%s: Error in set_value for open drain gpio%d err %d\n",
-					__func__, desc_to_gpio(desc), err);
+		gpiod_err(desc,
+			  "%s: Error in set_value for open drain err %d\n",
+			  __func__, err);
 }
 
 /*
- *  _gpio_set_open_source() - Set the open source gpio's value.
- * @gpio: Gpio whose state need to be set.
- * @chip: Gpio chip.
+ *  _gpio_set_open_source_value() - Set the open source gpio's value.
+ * @desc: gpio descriptor whose state need to be set.
  * @value: Non-zero for setting it HIGH otherise it will set to LOW.
  */
 static void _gpio_set_open_source_value(struct gpio_desc *desc, int value)
@@ -1920,28 +2007,16 @@
 	}
 	trace_gpio_direction(desc_to_gpio(desc), !value, err);
 	if (err < 0)
-		pr_err("%s: Error in set_value for open source gpio%d err %d\n",
-					__func__, desc_to_gpio(desc), err);
+		gpiod_err(desc,
+			  "%s: Error in set_value for open source err %d\n",
+			  __func__, err);
 }
 
-/**
- * __gpio_set_value() - assign a gpio's value
- * @gpio: gpio whose value will be assigned
- * @value: value to assign
- * Context: any
- *
- * This is used directly or indirectly to implement gpio_set_value().
- * It invokes the associated gpio_chip.set() method.
- */
-static void gpiod_set_value(struct gpio_desc *desc, int value)
+static void _gpiod_set_raw_value(struct gpio_desc *desc, int value)
 {
 	struct gpio_chip	*chip;
 
-	if (!desc)
-		return;
 	chip = desc->chip;
-	/* Should be using gpio_set_value_cansleep() */
-	WARN_ON(chip->can_sleep);
 	trace_gpio_value(desc_to_gpio(desc), 0, value);
 	if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))
 		_gpio_set_open_drain_value(desc, value);
@@ -1951,44 +2026,71 @@
 		chip->set(chip, gpio_chip_hwgpio(desc), value);
 }
 
-void __gpio_set_value(unsigned gpio, int value)
+/**
+ * gpiod_set_raw_value() - assign a gpio's raw value
+ * @desc: gpio whose value will be assigned
+ * @value: value to assign
+ *
+ * Set the raw value of the GPIO, i.e. the value of its physical line without
+ * regard for its ACTIVE_LOW status.
+ *
+ * This function should be called from contexts where we cannot sleep, and will
+ * complain if the GPIO chip functions potentially sleep.
+ */
+void gpiod_set_raw_value(struct gpio_desc *desc, int value)
 {
-	return gpiod_set_value(gpio_to_desc(gpio), value);
+	if (!desc)
+		return;
+	/* Should be using gpio_set_value_cansleep() */
+	WARN_ON(desc->chip->can_sleep);
+	_gpiod_set_raw_value(desc, value);
 }
-EXPORT_SYMBOL_GPL(__gpio_set_value);
+EXPORT_SYMBOL_GPL(gpiod_set_raw_value);
 
 /**
- * __gpio_cansleep() - report whether gpio value access will sleep
- * @gpio: gpio in question
- * Context: any
+ * gpiod_set_value() - assign a gpio's value
+ * @desc: gpio whose value will be assigned
+ * @value: value to assign
  *
- * This is used directly or indirectly to implement gpio_cansleep().  It
- * returns nonzero if access reading or writing the GPIO value can sleep.
+ * Set the logical value of the GPIO, i.e. taking its ACTIVE_LOW status into
+ * account
+ *
+ * This function should be called from contexts where we cannot sleep, and will
+ * complain if the GPIO chip functions potentially sleep.
  */
-static int gpiod_cansleep(const struct gpio_desc *desc)
+void gpiod_set_value(struct gpio_desc *desc, int value)
+{
+	if (!desc)
+		return;
+	/* Should be using gpio_set_value_cansleep() */
+	WARN_ON(desc->chip->can_sleep);
+	if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
+		value = !value;
+	_gpiod_set_raw_value(desc, value);
+}
+EXPORT_SYMBOL_GPL(gpiod_set_value);
+
+/**
+ * gpiod_cansleep() - report whether gpio value access may sleep
+ * @desc: gpio to check
+ *
+ */
+int gpiod_cansleep(const struct gpio_desc *desc)
 {
 	if (!desc)
 		return 0;
-	/* only call this on GPIOs that are valid! */
 	return desc->chip->can_sleep;
 }
-
-int __gpio_cansleep(unsigned gpio)
-{
-	return gpiod_cansleep(gpio_to_desc(gpio));
-}
-EXPORT_SYMBOL_GPL(__gpio_cansleep);
+EXPORT_SYMBOL_GPL(gpiod_cansleep);
 
 /**
- * __gpio_to_irq() - return the IRQ corresponding to a GPIO
- * @gpio: gpio whose IRQ will be returned (already requested)
- * Context: any
+ * gpiod_to_irq() - return the IRQ corresponding to a GPIO
+ * @desc: gpio whose IRQ will be returned (already requested)
  *
- * This is used directly or indirectly to implement gpio_to_irq().
- * It returns the number of the IRQ signaled by this (input) GPIO,
- * or a negative errno.
+ * Return the IRQ corresponding to the passed GPIO, or an error code in case of
+ * error.
  */
-static int gpiod_to_irq(const struct gpio_desc *desc)
+int gpiod_to_irq(const struct gpio_desc *desc)
 {
 	struct gpio_chip	*chip;
 	int			offset;
@@ -1999,62 +2101,366 @@
 	offset = gpio_chip_hwgpio(desc);
 	return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO;
 }
+EXPORT_SYMBOL_GPL(gpiod_to_irq);
 
-int __gpio_to_irq(unsigned gpio)
-{
-	return gpiod_to_irq(gpio_to_desc(gpio));
-}
-EXPORT_SYMBOL_GPL(__gpio_to_irq);
-
-
-/* There's no value in making it easy to inline GPIO calls that may sleep.
- * Common examples include ones connected to I2C or SPI chips.
+/**
+ * gpiod_lock_as_irq() - lock a GPIO to be used as IRQ
+ * @gpio: the GPIO line to lock as used for IRQ
+ *
+ * This is used directly by GPIO drivers that want to lock down
+ * a certain GPIO line to be used as IRQs, for example in the
+ * .to_irq() callback of their gpio_chip, or in the .irq_enable()
+ * of its irq_chip implementation if the GPIO is known from that
+ * code.
  */
-
-static int gpiod_get_value_cansleep(const struct gpio_desc *desc)
+int gpiod_lock_as_irq(struct gpio_desc *desc)
 {
-	struct gpio_chip	*chip;
+	if (!desc)
+		return -EINVAL;
+
+	if (test_bit(FLAG_IS_OUT, &desc->flags)) {
+		gpiod_err(desc,
+			  "%s: tried to flag a GPIO set as output for IRQ\n",
+			  __func__);
+		return -EIO;
+	}
+
+	set_bit(FLAG_USED_AS_IRQ, &desc->flags);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(gpiod_lock_as_irq);
+
+int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
+{
+	return gpiod_lock_as_irq(gpiochip_offset_to_desc(chip, offset));
+}
+EXPORT_SYMBOL_GPL(gpio_lock_as_irq);
+
+/**
+ * gpiod_unlock_as_irq() - unlock a GPIO used as IRQ
+ * @gpio: the GPIO line to unlock from IRQ usage
+ *
+ * This is used directly by GPIO drivers that want to indicate
+ * that a certain GPIO is no longer used exclusively for IRQ.
+ */
+void gpiod_unlock_as_irq(struct gpio_desc *desc)
+{
+	if (!desc)
+		return;
+
+	clear_bit(FLAG_USED_AS_IRQ, &desc->flags);
+}
+EXPORT_SYMBOL_GPL(gpiod_unlock_as_irq);
+
+void gpio_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
+{
+	return gpiod_unlock_as_irq(gpiochip_offset_to_desc(chip, offset));
+}
+EXPORT_SYMBOL_GPL(gpio_unlock_as_irq);
+
+/**
+ * gpiod_get_raw_value_cansleep() - return a gpio's raw value
+ * @desc: gpio whose value will be returned
+ *
+ * Return the GPIO's raw value, i.e. the value of the physical line disregarding
+ * its ACTIVE_LOW status.
+ *
+ * This function is to be called from contexts that can sleep.
+ */
+int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc)
+{
+	might_sleep_if(extra_checks);
+	if (!desc)
+		return 0;
+	return _gpiod_get_raw_value(desc);
+}
+EXPORT_SYMBOL_GPL(gpiod_get_raw_value_cansleep);
+
+/**
+ * gpiod_get_value_cansleep() - return a gpio's value
+ * @desc: gpio whose value will be returned
+ *
+ * Return the GPIO's logical value, i.e. taking the ACTIVE_LOW status into
+ * account.
+ *
+ * This function is to be called from contexts that can sleep.
+ */
+int gpiod_get_value_cansleep(const struct gpio_desc *desc)
+{
 	int value;
-	int offset;
 
 	might_sleep_if(extra_checks);
 	if (!desc)
 		return 0;
-	chip = desc->chip;
-	offset = gpio_chip_hwgpio(desc);
-	value = chip->get ? chip->get(chip, offset) : 0;
-	trace_gpio_value(desc_to_gpio(desc), 1, value);
+
+	value = _gpiod_get_raw_value(desc);
+	if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
+		value = !value;
+
 	return value;
 }
+EXPORT_SYMBOL_GPL(gpiod_get_value_cansleep);
 
-int gpio_get_value_cansleep(unsigned gpio)
+/**
+ * gpiod_set_raw_value_cansleep() - assign a gpio's raw value
+ * @desc: gpio whose value will be assigned
+ * @value: value to assign
+ *
+ * Set the raw value of the GPIO, i.e. the value of its physical line without
+ * regard for its ACTIVE_LOW status.
+ *
+ * This function is to be called from contexts that can sleep.
+ */
+void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value)
 {
-	return gpiod_get_value_cansleep(gpio_to_desc(gpio));
-}
-EXPORT_SYMBOL_GPL(gpio_get_value_cansleep);
-
-static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
-{
-	struct gpio_chip	*chip;
-
 	might_sleep_if(extra_checks);
 	if (!desc)
 		return;
-	chip = desc->chip;
-	trace_gpio_value(desc_to_gpio(desc), 0, value);
-	if (test_bit(FLAG_OPEN_DRAIN,  &desc->flags))
-		_gpio_set_open_drain_value(desc, value);
-	else if (test_bit(FLAG_OPEN_SOURCE,  &desc->flags))
-		_gpio_set_open_source_value(desc, value);
-	else
-		chip->set(chip, gpio_chip_hwgpio(desc), value);
+	_gpiod_set_raw_value(desc, value);
+}
+EXPORT_SYMBOL_GPL(gpiod_set_raw_value_cansleep);
+
+/**
+ * gpiod_set_value_cansleep() - assign a gpio's value
+ * @desc: gpio whose value will be assigned
+ * @value: value to assign
+ *
+ * Set the logical value of the GPIO, i.e. taking its ACTIVE_LOW status into
+ * account
+ *
+ * This function is to be called from contexts that can sleep.
+ */
+void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
+{
+	might_sleep_if(extra_checks);
+	if (!desc)
+		return;
+
+	if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
+		value = !value;
+	_gpiod_set_raw_value(desc, value);
+}
+EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep);
+
+/**
+ * gpiod_add_table() - register GPIO device consumers
+ * @table: array of consumers to register
+ * @num: number of consumers in table
+ */
+void gpiod_add_table(struct gpiod_lookup *table, size_t size)
+{
+	mutex_lock(&gpio_lookup_lock);
+
+	while (size--) {
+		list_add_tail(&table->list, &gpio_lookup_list);
+		table++;
+	}
+
+	mutex_unlock(&gpio_lookup_lock);
 }
 
-void gpio_set_value_cansleep(unsigned gpio, int value)
+/*
+ * Caller must have a acquired gpio_lookup_lock
+ */
+static struct gpio_chip *find_chip_by_name(const char *name)
 {
-	return gpiod_set_value_cansleep(gpio_to_desc(gpio), value);
+	struct gpio_chip *chip = NULL;
+
+	list_for_each_entry(chip, &gpio_lookup_list, list) {
+		if (chip->label == NULL)
+			continue;
+		if (!strcmp(chip->label, name))
+			break;
+	}
+
+	return chip;
 }
-EXPORT_SYMBOL_GPL(gpio_set_value_cansleep);
+
+#ifdef CONFIG_OF
+static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
+				      unsigned int idx, unsigned long *flags)
+{
+	char prop_name[32]; /* 32 is max size of property name */
+	enum of_gpio_flags of_flags;
+	struct gpio_desc *desc;
+
+	if (con_id)
+		snprintf(prop_name, 32, "%s-gpios", con_id);
+	else
+		snprintf(prop_name, 32, "gpios");
+
+	desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx,
+					&of_flags);
+
+	if (IS_ERR(desc))
+		return desc;
+
+	if (of_flags & OF_GPIO_ACTIVE_LOW)
+		*flags |= GPIOF_ACTIVE_LOW;
+
+	return desc;
+}
+#else
+static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
+				      unsigned int idx, unsigned long *flags)
+{
+	return ERR_PTR(-ENODEV);
+}
+#endif
+
+static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
+					unsigned int idx, unsigned long *flags)
+{
+	struct acpi_gpio_info info;
+	struct gpio_desc *desc;
+
+	desc = acpi_get_gpiod_by_index(dev, idx, &info);
+	if (IS_ERR(desc))
+		return desc;
+
+	if (info.gpioint && info.active_low)
+		*flags |= GPIOF_ACTIVE_LOW;
+
+	return desc;
+}
+
+static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
+				    unsigned int idx, unsigned long *flags)
+{
+	const char *dev_id = dev ? dev_name(dev) : NULL;
+	struct gpio_desc *desc = ERR_PTR(-ENODEV);
+	unsigned int match, best = 0;
+	struct gpiod_lookup *p;
+
+	mutex_lock(&gpio_lookup_lock);
+
+	list_for_each_entry(p, &gpio_lookup_list, list) {
+		match = 0;
+
+		if (p->dev_id) {
+			if (!dev_id || strcmp(p->dev_id, dev_id))
+				continue;
+
+			match += 2;
+		}
+
+		if (p->con_id) {
+			if (!con_id || strcmp(p->con_id, con_id))
+				continue;
+
+			match += 1;
+		}
+
+		if (p->idx != idx)
+			continue;
+
+		if (match > best) {
+			struct gpio_chip *chip;
+
+			chip = find_chip_by_name(p->chip_label);
+
+			if (!chip) {
+				dev_warn(dev, "cannot find GPIO chip %s\n",
+					 p->chip_label);
+				continue;
+			}
+
+			if (chip->ngpio >= p->chip_hwnum) {
+				dev_warn(dev, "GPIO chip %s has %d GPIOs\n",
+					 chip->label, chip->ngpio);
+				continue;
+			}
+
+			desc = gpio_to_desc(chip->base + p->chip_hwnum);
+			*flags = p->flags;
+
+			if (match != 3)
+				best = match;
+			else
+				break;
+		}
+	}
+
+	mutex_unlock(&gpio_lookup_lock);
+
+	return desc;
+}
+
+/**
+ * gpio_get - obtain a GPIO for a given GPIO function
+ * @dev:	GPIO consumer
+ * @con_id:	function within the GPIO consumer
+ *
+ * Return the GPIO descriptor corresponding to the function con_id of device
+ * dev, or an IS_ERR() condition if an error occured.
+ */
+struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id)
+{
+	return gpiod_get_index(dev, con_id, 0);
+}
+EXPORT_SYMBOL_GPL(gpiod_get);
+
+/**
+ * gpiod_get_index - obtain a GPIO from a multi-index GPIO function
+ * @dev:	GPIO consumer
+ * @con_id:	function within the GPIO consumer
+ * @idx:	index of the GPIO to obtain in the consumer
+ *
+ * This variant of gpiod_get() allows to access GPIOs other than the first
+ * defined one for functions that define several GPIOs.
+ *
+ * Return a valid GPIO descriptor, or an IS_ERR() condition in case of error.
+ */
+struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
+					       const char *con_id,
+					       unsigned int idx)
+{
+	struct gpio_desc *desc;
+	int status;
+	unsigned long flags = 0;
+
+	dev_dbg(dev, "GPIO lookup for consumer %s\n", con_id);
+
+	/* Using device tree? */
+	if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) {
+		dev_dbg(dev, "using device tree for GPIO lookup\n");
+		desc = of_find_gpio(dev, con_id, idx, &flags);
+	} else if (IS_ENABLED(CONFIG_ACPI) && dev && ACPI_HANDLE(dev)) {
+		dev_dbg(dev, "using ACPI for GPIO lookup\n");
+		desc = acpi_find_gpio(dev, con_id, idx, &flags);
+	} else {
+		dev_dbg(dev, "using lookup tables for GPIO lookup");
+		desc = gpiod_find(dev, con_id, idx, &flags);
+	}
+
+	if (IS_ERR(desc)) {
+		dev_warn(dev, "lookup for GPIO %s failed\n", con_id);
+		return desc;
+	}
+
+	status = gpiod_request(desc, con_id);
+
+	if (status < 0)
+		return ERR_PTR(status);
+
+	if (flags & GPIOF_ACTIVE_LOW)
+		set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+
+	return desc;
+}
+EXPORT_SYMBOL_GPL(gpiod_get_index);
+
+/**
+ * gpiod_put - dispose of a GPIO descriptor
+ * @desc:	GPIO descriptor to dispose of
+ *
+ * No descriptor can be used after gpiod_put() has been called on it.
+ */
+void gpiod_put(struct gpio_desc *desc)
+{
+	gpiod_free(desc);
+}
+EXPORT_SYMBOL_GPL(gpiod_put);
 
 #ifdef CONFIG_DEBUG_FS
 
@@ -2064,6 +2470,7 @@
 	unsigned		gpio = chip->base;
 	struct gpio_desc	*gdesc = &chip->desc[0];
 	int			is_out;
+	int			is_irq;
 
 	for (i = 0; i < chip->ngpio; i++, gpio++, gdesc++) {
 		if (!test_bit(FLAG_REQUESTED, &gdesc->flags))
@@ -2071,12 +2478,14 @@
 
 		gpiod_get_direction(gdesc);
 		is_out = test_bit(FLAG_IS_OUT, &gdesc->flags);
-		seq_printf(s, " gpio-%-3d (%-20.20s) %s %s",
+		is_irq = test_bit(FLAG_USED_AS_IRQ, &gdesc->flags);
+		seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s",
 			gpio, gdesc->label,
 			is_out ? "out" : "in ",
 			chip->get
 				? (chip->get(chip, i) ? "hi" : "lo")
-				: "?  ");
+				: "?  ",
+			is_irq ? "IRQ" : "   ");
 		seq_printf(s, "\n");
 	}
 }
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index e572dd2..fe58d08 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -61,7 +61,7 @@
 
 /** Ioctl table */
 static const struct drm_ioctl_desc drm_ioctls[] = {
-	DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED|DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
 	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
 	DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
@@ -402,9 +402,16 @@
 		cmd = ioctl->cmd_drv;
 	}
 	else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
+		u32 drv_size;
+
 		ioctl = &drm_ioctls[nr];
-		cmd = ioctl->cmd;
+
+		drv_size = _IOC_SIZE(ioctl->cmd);
 		usize = asize = _IOC_SIZE(cmd);
+		if (drv_size > asize)
+			asize = drv_size;
+
+		cmd = ioctl->cmd;
 	} else
 		goto err_i1;
 
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 1688ff5..830f750 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2925,6 +2925,8 @@
 			/* Speaker Allocation Data Block */
 			if (dbl == 3) {
 				*sadb = kmalloc(dbl, GFP_KERNEL);
+				if (!*sadb)
+					return -ENOMEM;
 				memcpy(*sadb, &db[1], dbl);
 				count = dbl;
 				break;
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index f6f6cc7..3d13ca6e2 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -416,14 +416,6 @@
 		return;
 
 	/*
-	 * fbdev->blank can be called from irq context in case of a panic.
-	 * Since we already have our own special panic handler which will
-	 * restore the fbdev console mode completely, just bail out early.
-	 */
-	if (oops_in_progress)
-		return;
-
-	/*
 	 * For each CRTC in this fb, turn the connectors on/off.
 	 */
 	drm_modeset_lock_all(dev);
diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c
index 92babac..2db731f 100644
--- a/drivers/gpu/drm/gma500/gtt.c
+++ b/drivers/gpu/drm/gma500/gtt.c
@@ -204,6 +204,7 @@
 	if (IS_ERR(pages))
 		return PTR_ERR(pages);
 
+	gt->npage = gt->gem.size / PAGE_SIZE;
 	gt->pages = pages;
 
 	return 0;
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.h b/drivers/gpu/drm/gma500/mdfld_dsi_output.h
index 45d5af0..5b646c1 100644
--- a/drivers/gpu/drm/gma500/mdfld_dsi_output.h
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.h
@@ -39,7 +39,7 @@
 #include "psb_intel_reg.h"
 #include "mdfld_output.h"
 
-#include <asm/mrst.h>
+#include <asm/intel-mid.h>
 
 #define FLD_MASK(start, end)	(((1 << ((start) - (end) + 1)) - 1) << (end))
 #define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c
index 08747fd..7a9ce00 100644
--- a/drivers/gpu/drm/gma500/oaktrail_device.c
+++ b/drivers/gpu/drm/gma500/oaktrail_device.c
@@ -26,7 +26,7 @@
 #include "psb_drv.h"
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
-#include <asm/mrst.h>
+#include <asm/intel-mid.h>
 #include <asm/intel_scu_ipc.h>
 #include "mid_bios.h"
 #include "intel_bios.h"
diff --git a/drivers/gpu/drm/gma500/oaktrail_lvds.c b/drivers/gpu/drm/gma500/oaktrail_lvds.c
index e77d721..3ece553 100644
--- a/drivers/gpu/drm/gma500/oaktrail_lvds.c
+++ b/drivers/gpu/drm/gma500/oaktrail_lvds.c
@@ -22,7 +22,7 @@
 
 #include <linux/i2c.h>
 #include <drm/drmP.h>
-#include <asm/mrst.h>
+#include <asm/intel-mid.h>
 
 #include "intel_bios.h"
 #include "psb_drv.h"
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index c27a210..d5c784d 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1290,12 +1290,9 @@
 	 * then we do not take part in VGA arbitration and the
 	 * vga_client_register() fails with -ENODEV.
 	 */
-	if (!HAS_PCH_SPLIT(dev)) {
-		ret = vga_client_register(dev->pdev, dev, NULL,
-					  i915_vga_set_decode);
-		if (ret && ret != -ENODEV)
-			goto out;
-	}
+	ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode);
+	if (ret && ret != -ENODEV)
+		goto out;
 
 	intel_register_dsm_handler();
 
@@ -1351,12 +1348,6 @@
 	 */
 	intel_fbdev_initial_config(dev);
 
-	/*
-	 * Must do this after fbcon init so that
-	 * vgacon_save_screen() works during the handover.
-	 */
-	i915_disable_vga_mem(dev);
-
 	/* Only enable hotplug handling once the fbdev is fully set up. */
 	dev_priv->enable_hotplug_processing = true;
 
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 69d8ed5..2ad2788 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -505,6 +505,8 @@
 		intel_modeset_suspend_hw(dev);
 	}
 
+	i915_gem_suspend_gtt_mappings(dev);
+
 	i915_save_state(dev);
 
 	intel_opregion_fini(dev);
@@ -648,7 +650,8 @@
 		mutex_lock(&dev->struct_mutex);
 		i915_gem_restore_gtt_mappings(dev);
 		mutex_unlock(&dev->struct_mutex);
-	}
+	} else if (drm_core_check_feature(dev, DRIVER_MODESET))
+		i915_check_and_clear_faults(dev);
 
 	__i915_drm_thaw(dev);
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 35874b3..ab0f2c0 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -497,10 +497,12 @@
 
 	/* FIXME: Need a more generic return type */
 	gen6_gtt_pte_t (*pte_encode)(dma_addr_t addr,
-				     enum i915_cache_level level);
+				     enum i915_cache_level level,
+				     bool valid); /* Create a valid PTE */
 	void (*clear_range)(struct i915_address_space *vm,
 			    unsigned int first_entry,
-			    unsigned int num_entries);
+			    unsigned int num_entries,
+			    bool use_scratch);
 	void (*insert_entries)(struct i915_address_space *vm,
 			       struct sg_table *st,
 			       unsigned int first_entry,
@@ -2065,6 +2067,8 @@
 void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
 			      struct drm_i915_gem_object *obj);
 
+void i915_check_and_clear_faults(struct drm_device *dev);
+void i915_gem_suspend_gtt_mappings(struct drm_device *dev);
 void i915_gem_restore_gtt_mappings(struct drm_device *dev);
 int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj);
 void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj,
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 212f6d8..1f7b4ca 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -58,9 +58,10 @@
 #define HSW_WT_ELLC_LLC_AGE0		HSW_CACHEABILITY_CONTROL(0x6)
 
 static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr,
-				     enum i915_cache_level level)
+				     enum i915_cache_level level,
+				     bool valid)
 {
-	gen6_gtt_pte_t pte = GEN6_PTE_VALID;
+	gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
 	pte |= GEN6_PTE_ADDR_ENCODE(addr);
 
 	switch (level) {
@@ -79,9 +80,10 @@
 }
 
 static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr,
-				     enum i915_cache_level level)
+				     enum i915_cache_level level,
+				     bool valid)
 {
-	gen6_gtt_pte_t pte = GEN6_PTE_VALID;
+	gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
 	pte |= GEN6_PTE_ADDR_ENCODE(addr);
 
 	switch (level) {
@@ -105,9 +107,10 @@
 #define BYT_PTE_SNOOPED_BY_CPU_CACHES	(1 << 2)
 
 static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr,
-				     enum i915_cache_level level)
+				     enum i915_cache_level level,
+				     bool valid)
 {
-	gen6_gtt_pte_t pte = GEN6_PTE_VALID;
+	gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
 	pte |= GEN6_PTE_ADDR_ENCODE(addr);
 
 	/* Mark the page as writeable.  Other platforms don't have a
@@ -122,9 +125,10 @@
 }
 
 static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr,
-				     enum i915_cache_level level)
+				     enum i915_cache_level level,
+				     bool valid)
 {
-	gen6_gtt_pte_t pte = GEN6_PTE_VALID;
+	gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
 	pte |= HSW_PTE_ADDR_ENCODE(addr);
 
 	if (level != I915_CACHE_NONE)
@@ -134,9 +138,10 @@
 }
 
 static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr,
-				      enum i915_cache_level level)
+				      enum i915_cache_level level,
+				      bool valid)
 {
-	gen6_gtt_pte_t pte = GEN6_PTE_VALID;
+	gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0;
 	pte |= HSW_PTE_ADDR_ENCODE(addr);
 
 	switch (level) {
@@ -236,7 +241,8 @@
 /* PPGTT support for Sandybdrige/Gen6 and later */
 static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
 				   unsigned first_entry,
-				   unsigned num_entries)
+				   unsigned num_entries,
+				   bool use_scratch)
 {
 	struct i915_hw_ppgtt *ppgtt =
 		container_of(vm, struct i915_hw_ppgtt, base);
@@ -245,7 +251,7 @@
 	unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
 	unsigned last_pte, i;
 
-	scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC);
+	scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true);
 
 	while (num_entries) {
 		last_pte = first_pte + num_entries;
@@ -282,7 +288,7 @@
 		dma_addr_t page_addr;
 
 		page_addr = sg_page_iter_dma_address(&sg_iter);
-		pt_vaddr[act_pte] = vm->pte_encode(page_addr, cache_level);
+		pt_vaddr[act_pte] = vm->pte_encode(page_addr, cache_level, true);
 		if (++act_pte == I915_PPGTT_PT_ENTRIES) {
 			kunmap_atomic(pt_vaddr);
 			act_pt++;
@@ -367,7 +373,7 @@
 	}
 
 	ppgtt->base.clear_range(&ppgtt->base, 0,
-				ppgtt->num_pd_entries * I915_PPGTT_PT_ENTRIES);
+				ppgtt->num_pd_entries * I915_PPGTT_PT_ENTRIES, true);
 
 	ppgtt->pd_offset = first_pd_entry_in_global_pt * sizeof(gen6_gtt_pte_t);
 
@@ -444,7 +450,8 @@
 {
 	ppgtt->base.clear_range(&ppgtt->base,
 				i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT,
-				obj->base.size >> PAGE_SHIFT);
+				obj->base.size >> PAGE_SHIFT,
+				true);
 }
 
 extern int intel_iommu_gfx_mapped;
@@ -485,15 +492,65 @@
 		dev_priv->mm.interruptible = interruptible;
 }
 
+void i915_check_and_clear_faults(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
+	int i;
+
+	if (INTEL_INFO(dev)->gen < 6)
+		return;
+
+	for_each_ring(ring, dev_priv, i) {
+		u32 fault_reg;
+		fault_reg = I915_READ(RING_FAULT_REG(ring));
+		if (fault_reg & RING_FAULT_VALID) {
+			DRM_DEBUG_DRIVER("Unexpected fault\n"
+					 "\tAddr: 0x%08lx\\n"
+					 "\tAddress space: %s\n"
+					 "\tSource ID: %d\n"
+					 "\tType: %d\n",
+					 fault_reg & PAGE_MASK,
+					 fault_reg & RING_FAULT_GTTSEL_MASK ? "GGTT" : "PPGTT",
+					 RING_FAULT_SRCID(fault_reg),
+					 RING_FAULT_FAULT_TYPE(fault_reg));
+			I915_WRITE(RING_FAULT_REG(ring),
+				   fault_reg & ~RING_FAULT_VALID);
+		}
+	}
+	POSTING_READ(RING_FAULT_REG(&dev_priv->ring[RCS]));
+}
+
+void i915_gem_suspend_gtt_mappings(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	/* Don't bother messing with faults pre GEN6 as we have little
+	 * documentation supporting that it's a good idea.
+	 */
+	if (INTEL_INFO(dev)->gen < 6)
+		return;
+
+	i915_check_and_clear_faults(dev);
+
+	dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
+				       dev_priv->gtt.base.start / PAGE_SIZE,
+				       dev_priv->gtt.base.total / PAGE_SIZE,
+				       false);
+}
+
 void i915_gem_restore_gtt_mappings(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj;
 
+	i915_check_and_clear_faults(dev);
+
 	/* First fill our portion of the GTT with scratch pages */
 	dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
 				       dev_priv->gtt.base.start / PAGE_SIZE,
-				       dev_priv->gtt.base.total / PAGE_SIZE);
+				       dev_priv->gtt.base.total / PAGE_SIZE,
+				       true);
 
 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
 		i915_gem_clflush_object(obj, obj->pin_display);
@@ -536,7 +593,7 @@
 
 	for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
 		addr = sg_page_iter_dma_address(&sg_iter);
-		iowrite32(vm->pte_encode(addr, level), &gtt_entries[i]);
+		iowrite32(vm->pte_encode(addr, level, true), &gtt_entries[i]);
 		i++;
 	}
 
@@ -548,7 +605,7 @@
 	 */
 	if (i != 0)
 		WARN_ON(readl(&gtt_entries[i-1]) !=
-			vm->pte_encode(addr, level));
+			vm->pte_encode(addr, level, true));
 
 	/* This next bit makes the above posting read even more important. We
 	 * want to flush the TLBs only after we're certain all the PTE updates
@@ -560,7 +617,8 @@
 
 static void gen6_ggtt_clear_range(struct i915_address_space *vm,
 				  unsigned int first_entry,
-				  unsigned int num_entries)
+				  unsigned int num_entries,
+				  bool use_scratch)
 {
 	struct drm_i915_private *dev_priv = vm->dev->dev_private;
 	gen6_gtt_pte_t scratch_pte, __iomem *gtt_base =
@@ -573,7 +631,8 @@
 		 first_entry, num_entries, max_entries))
 		num_entries = max_entries;
 
-	scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC);
+	scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, use_scratch);
+
 	for (i = 0; i < num_entries; i++)
 		iowrite32(scratch_pte, &gtt_base[i]);
 	readl(gtt_base);
@@ -594,7 +653,8 @@
 
 static void i915_ggtt_clear_range(struct i915_address_space *vm,
 				  unsigned int first_entry,
-				  unsigned int num_entries)
+				  unsigned int num_entries,
+				  bool unused)
 {
 	intel_gtt_clear_range(first_entry, num_entries);
 }
@@ -622,7 +682,8 @@
 
 	dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
 				       entry,
-				       obj->base.size >> PAGE_SHIFT);
+				       obj->base.size >> PAGE_SHIFT,
+				       true);
 
 	obj->has_global_gtt_mapping = 0;
 }
@@ -709,11 +770,11 @@
 		const unsigned long count = (hole_end - hole_start) / PAGE_SIZE;
 		DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n",
 			      hole_start, hole_end);
-		ggtt_vm->clear_range(ggtt_vm, hole_start / PAGE_SIZE, count);
+		ggtt_vm->clear_range(ggtt_vm, hole_start / PAGE_SIZE, count, true);
 	}
 
 	/* And finally clear the reserved guard page */
-	ggtt_vm->clear_range(ggtt_vm, end / PAGE_SIZE - 1, 1);
+	ggtt_vm->clear_range(ggtt_vm, end / PAGE_SIZE - 1, 1, true);
 }
 
 static bool
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index c159e1a..ef9b354 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -604,6 +604,10 @@
 #define   ARB_MODE_SWIZZLE_IVB	(1<<5)
 #define RENDER_HWS_PGA_GEN7	(0x04080)
 #define RING_FAULT_REG(ring)	(0x4094 + 0x100*(ring)->id)
+#define   RING_FAULT_GTTSEL_MASK (1<<11)
+#define   RING_FAULT_SRCID(x)	((x >> 3) & 0xff)
+#define   RING_FAULT_FAULT_TYPE(x) ((x >> 1) & 0x3)
+#define   RING_FAULT_VALID	(1<<0)
 #define DONE_REG		0x40b0
 #define BSD_HWS_PGA_GEN7	(0x04180)
 #define BLT_HWS_PGA_GEN7	(0x04280)
@@ -3881,6 +3885,9 @@
 #define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG		0x9030
 #define  GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB	(1<<11)
 
+#define HSW_SCRATCH1				0xb038
+#define  HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE	(1<<27)
+
 #define HSW_FUSE_STRAP		0x42014
 #define  HSW_CDCLK_LIMIT	(1 << 24)
 
@@ -4276,7 +4283,9 @@
 #define FDI_RX_CHICKEN(pipe) _PIPE(pipe, _FDI_RXA_CHICKEN, _FDI_RXB_CHICKEN)
 
 #define SOUTH_DSPCLK_GATE_D	0xc2020
+#define  PCH_DPLUNIT_CLOCK_GATE_DISABLE (1<<30)
 #define  PCH_DPLSUNIT_CLOCK_GATE_DISABLE (1<<29)
+#define  PCH_CPUNIT_CLOCK_GATE_DISABLE (1<<14)
 #define  PCH_LP_PARTITION_LEVEL_DISABLE  (1<<12)
 
 /* CPU: FDI_TX */
@@ -4728,6 +4737,9 @@
 #define GEN7_ROW_CHICKEN2_GT2		0xf4f4
 #define   DOP_CLOCK_GATING_DISABLE	(1<<0)
 
+#define HSW_ROW_CHICKEN3		0xe49c
+#define  HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE    (1 << 6)
+
 #define G4X_AUD_VID_DID			(dev_priv->info->display_mmio_offset + 0x62020)
 #define INTEL_AUDIO_DEVCL		0x808629FB
 #define INTEL_AUDIO_DEVBLC		0x80862801
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index ea9022e..10d1de5 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -83,8 +83,7 @@
 	return true;
 }
 
-static void intel_crt_get_config(struct intel_encoder *encoder,
-				 struct intel_crtc_config *pipe_config)
+static unsigned int intel_crt_get_flags(struct intel_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
 	struct intel_crt *crt = intel_encoder_to_crt(encoder);
@@ -102,7 +101,25 @@
 	else
 		flags |= DRM_MODE_FLAG_NVSYNC;
 
-	pipe_config->adjusted_mode.flags |= flags;
+	return flags;
+}
+
+static void intel_crt_get_config(struct intel_encoder *encoder,
+				 struct intel_crtc_config *pipe_config)
+{
+	pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder);
+}
+
+static void hsw_crt_get_config(struct intel_encoder *encoder,
+			       struct intel_crtc_config *pipe_config)
+{
+	intel_ddi_get_config(encoder, pipe_config);
+
+	pipe_config->adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC |
+					      DRM_MODE_FLAG_NHSYNC |
+					      DRM_MODE_FLAG_PVSYNC |
+					      DRM_MODE_FLAG_NVSYNC);
+	pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder);
 }
 
 /* Note: The caller is required to filter out dpms modes not supported by the
@@ -799,7 +816,10 @@
 	crt->base.mode_set = intel_crt_mode_set;
 	crt->base.disable = intel_disable_crt;
 	crt->base.enable = intel_enable_crt;
-	crt->base.get_config = intel_crt_get_config;
+	if (IS_HASWELL(dev))
+		crt->base.get_config = hsw_crt_get_config;
+	else
+		crt->base.get_config = intel_crt_get_config;
 	if (I915_HAS_HOTPLUG(dev))
 		crt->base.hpd_pin = HPD_CRT;
 	if (HAS_DDI(dev))
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 63de270..b53fff8 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1249,8 +1249,8 @@
 		intel_dp_check_link_status(intel_dp);
 }
 
-static void intel_ddi_get_config(struct intel_encoder *encoder,
-				 struct intel_crtc_config *pipe_config)
+void intel_ddi_get_config(struct intel_encoder *encoder,
+			  struct intel_crtc_config *pipe_config)
 {
 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
@@ -1268,6 +1268,23 @@
 		flags |= DRM_MODE_FLAG_NVSYNC;
 
 	pipe_config->adjusted_mode.flags |= flags;
+
+	switch (temp & TRANS_DDI_BPC_MASK) {
+	case TRANS_DDI_BPC_6:
+		pipe_config->pipe_bpp = 18;
+		break;
+	case TRANS_DDI_BPC_8:
+		pipe_config->pipe_bpp = 24;
+		break;
+	case TRANS_DDI_BPC_10:
+		pipe_config->pipe_bpp = 30;
+		break;
+	case TRANS_DDI_BPC_12:
+		pipe_config->pipe_bpp = 36;
+		break;
+	default:
+		break;
+	}
 }
 
 static void intel_ddi_destroy(struct drm_encoder *encoder)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e5822e7..d78d33f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2327,9 +2327,10 @@
 			   FDI_FE_ERRC_ENABLE);
 }
 
-static bool pipe_has_enabled_pch(struct intel_crtc *intel_crtc)
+static bool pipe_has_enabled_pch(struct intel_crtc *crtc)
 {
-	return intel_crtc->base.enabled && intel_crtc->config.has_pch_encoder;
+	return crtc->base.enabled && crtc->active &&
+		crtc->config.has_pch_encoder;
 }
 
 static void ivb_modeset_global_resources(struct drm_device *dev)
@@ -2979,6 +2980,48 @@
 		   I915_READ(VSYNCSHIFT(cpu_transcoder)));
 }
 
+static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t temp;
+
+	temp = I915_READ(SOUTH_CHICKEN1);
+	if (temp & FDI_BC_BIFURCATION_SELECT)
+		return;
+
+	WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE);
+	WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE);
+
+	temp |= FDI_BC_BIFURCATION_SELECT;
+	DRM_DEBUG_KMS("enabling fdi C rx\n");
+	I915_WRITE(SOUTH_CHICKEN1, temp);
+	POSTING_READ(SOUTH_CHICKEN1);
+}
+
+static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc)
+{
+	struct drm_device *dev = intel_crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	switch (intel_crtc->pipe) {
+	case PIPE_A:
+		break;
+	case PIPE_B:
+		if (intel_crtc->config.fdi_lanes > 2)
+			WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT);
+		else
+			cpt_enable_fdi_bc_bifurcation(dev);
+
+		break;
+	case PIPE_C:
+		cpt_enable_fdi_bc_bifurcation(dev);
+
+		break;
+	default:
+		BUG();
+	}
+}
+
 /*
  * Enable PCH resources required for PCH ports:
  *   - PCH PLLs
@@ -2997,6 +3040,9 @@
 
 	assert_pch_transcoder_disabled(dev_priv, pipe);
 
+	if (IS_IVYBRIDGE(dev))
+		ivybridge_update_fdi_bc_bifurcation(intel_crtc);
+
 	/* Write the TU size bits before fdi link training, so that error
 	 * detection works. */
 	I915_WRITE(FDI_RX_TUSIZE1(pipe),
@@ -3941,8 +3987,6 @@
  * consider. */
 void intel_connector_dpms(struct drm_connector *connector, int mode)
 {
-	struct intel_encoder *encoder = intel_attached_encoder(connector);
-
 	/* All the simple cases only support two dpms states. */
 	if (mode != DRM_MODE_DPMS_ON)
 		mode = DRM_MODE_DPMS_OFF;
@@ -3953,10 +3997,8 @@
 	connector->dpms = mode;
 
 	/* Only need to change hw state when actually enabled */
-	if (encoder->base.crtc)
-		intel_encoder_dpms(encoder, mode);
-	else
-		WARN_ON(encoder->connectors_active != false);
+	if (connector->encoder)
+		intel_encoder_dpms(to_intel_encoder(connector->encoder), mode);
 
 	intel_modeset_check_state(connector->dev);
 }
@@ -4987,6 +5029,22 @@
 	if (!(tmp & PIPECONF_ENABLE))
 		return false;
 
+	if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
+		switch (tmp & PIPECONF_BPC_MASK) {
+		case PIPECONF_6BPC:
+			pipe_config->pipe_bpp = 18;
+			break;
+		case PIPECONF_8BPC:
+			pipe_config->pipe_bpp = 24;
+			break;
+		case PIPECONF_10BPC:
+			pipe_config->pipe_bpp = 30;
+			break;
+		default:
+			break;
+		}
+	}
+
 	intel_get_pipe_timings(crtc, pipe_config);
 
 	i9xx_get_pfit_config(crtc, pipe_config);
@@ -5580,48 +5638,6 @@
 	return true;
 }
 
-static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	uint32_t temp;
-
-	temp = I915_READ(SOUTH_CHICKEN1);
-	if (temp & FDI_BC_BIFURCATION_SELECT)
-		return;
-
-	WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE);
-	WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE);
-
-	temp |= FDI_BC_BIFURCATION_SELECT;
-	DRM_DEBUG_KMS("enabling fdi C rx\n");
-	I915_WRITE(SOUTH_CHICKEN1, temp);
-	POSTING_READ(SOUTH_CHICKEN1);
-}
-
-static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc)
-{
-	struct drm_device *dev = intel_crtc->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	switch (intel_crtc->pipe) {
-	case PIPE_A:
-		break;
-	case PIPE_B:
-		if (intel_crtc->config.fdi_lanes > 2)
-			WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT);
-		else
-			cpt_enable_fdi_bc_bifurcation(dev);
-
-		break;
-	case PIPE_C:
-		cpt_enable_fdi_bc_bifurcation(dev);
-
-		break;
-	default:
-		BUG();
-	}
-}
-
 int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp)
 {
 	/*
@@ -5815,9 +5831,6 @@
 					     &intel_crtc->config.fdi_m_n);
 	}
 
-	if (IS_IVYBRIDGE(dev))
-		ivybridge_update_fdi_bc_bifurcation(intel_crtc);
-
 	ironlake_set_pipeconf(crtc);
 
 	/* Set up the display plane register */
@@ -5885,6 +5898,23 @@
 	if (!(tmp & PIPECONF_ENABLE))
 		return false;
 
+	switch (tmp & PIPECONF_BPC_MASK) {
+	case PIPECONF_6BPC:
+		pipe_config->pipe_bpp = 18;
+		break;
+	case PIPECONF_8BPC:
+		pipe_config->pipe_bpp = 24;
+		break;
+	case PIPECONF_10BPC:
+		pipe_config->pipe_bpp = 30;
+		break;
+	case PIPECONF_12BPC:
+		pipe_config->pipe_bpp = 36;
+		break;
+	default:
+		break;
+	}
+
 	if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) {
 		struct intel_shared_dpll *pll;
 
@@ -8616,6 +8646,9 @@
 	PIPE_CONF_CHECK_X(dpll_hw_state.fp0);
 	PIPE_CONF_CHECK_X(dpll_hw_state.fp1);
 
+	if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5)
+		PIPE_CONF_CHECK_I(pipe_bpp);
+
 #undef PIPE_CONF_CHECK_X
 #undef PIPE_CONF_CHECK_I
 #undef PIPE_CONF_CHECK_FLAGS
@@ -10049,33 +10082,6 @@
 	POSTING_READ(vga_reg);
 }
 
-static void i915_enable_vga_mem(struct drm_device *dev)
-{
-	/* Enable VGA memory on Intel HD */
-	if (HAS_PCH_SPLIT(dev)) {
-		vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
-		outb(inb(VGA_MSR_READ) | VGA_MSR_MEM_EN, VGA_MSR_WRITE);
-		vga_set_legacy_decoding(dev->pdev, VGA_RSRC_LEGACY_IO |
-						   VGA_RSRC_LEGACY_MEM |
-						   VGA_RSRC_NORMAL_IO |
-						   VGA_RSRC_NORMAL_MEM);
-		vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
-	}
-}
-
-void i915_disable_vga_mem(struct drm_device *dev)
-{
-	/* Disable VGA memory on Intel HD */
-	if (HAS_PCH_SPLIT(dev)) {
-		vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
-		outb(inb(VGA_MSR_READ) & ~VGA_MSR_MEM_EN, VGA_MSR_WRITE);
-		vga_set_legacy_decoding(dev->pdev, VGA_RSRC_LEGACY_IO |
-						   VGA_RSRC_NORMAL_IO |
-						   VGA_RSRC_NORMAL_MEM);
-		vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
-	}
-}
-
 void intel_modeset_init_hw(struct drm_device *dev)
 {
 	intel_init_power_well(dev);
@@ -10354,7 +10360,6 @@
 	if (I915_READ(vga_reg) != VGA_DISP_DISABLE) {
 		DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
 		i915_disable_vga(dev);
-		i915_disable_vga_mem(dev);
 	}
 }
 
@@ -10568,8 +10573,6 @@
 
 	intel_disable_fbc(dev);
 
-	i915_enable_vga_mem(dev);
-
 	intel_disable_gt_powersave(dev);
 
 	ironlake_teardown_rc6(dev);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 79c14e2..1a43137 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1401,6 +1401,26 @@
 		else
 			pipe_config->port_clock = 270000;
 	}
+
+	if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp &&
+	    pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) {
+		/*
+		 * This is a big fat ugly hack.
+		 *
+		 * Some machines in UEFI boot mode provide us a VBT that has 18
+		 * bpp and 1.62 GHz link bandwidth for eDP, which for reasons
+		 * unknown we fail to light up. Yet the same BIOS boots up with
+		 * 24 bpp and 2.7 GHz link. Use the same bpp as the BIOS uses as
+		 * max, not what it tells us to use.
+		 *
+		 * Note: This will still be broken if the eDP panel is not lit
+		 * up by the BIOS, and thus we can't get the mode at module
+		 * load.
+		 */
+		DRM_DEBUG_KMS("pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n",
+			      pipe_config->pipe_bpp, dev_priv->vbt.edp_bpp);
+		dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp;
+	}
 }
 
 static bool is_edp_psr(struct intel_dp *intel_dp)
@@ -1467,7 +1487,7 @@
 
 	/* Avoid continuous PSR exit by masking memup and hpd */
 	I915_WRITE(EDP_PSR_DEBUG_CTL, EDP_PSR_DEBUG_MASK_MEMUP |
-		   EDP_PSR_DEBUG_MASK_HPD);
+		   EDP_PSR_DEBUG_MASK_HPD | EDP_PSR_DEBUG_MASK_LPSP);
 
 	intel_dp->psr_setup_done = true;
 }
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 28cae80..7f2b384 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -765,6 +765,8 @@
 extern bool
 intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
 extern void intel_ddi_fdi_disable(struct drm_crtc *crtc);
+extern void intel_ddi_get_config(struct intel_encoder *encoder,
+				 struct intel_crtc_config *pipe_config);
 
 extern void intel_display_handle_reset(struct drm_device *dev);
 extern bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
@@ -793,6 +795,5 @@
 extern void hsw_pc8_restore_interrupts(struct drm_device *dev);
 extern void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
 extern void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
-extern void i915_disable_vga_mem(struct drm_device *dev);
 
 #endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 831a5c0..b8af94a 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -700,6 +700,22 @@
 	},
 	{
 		.callback = intel_no_lvds_dmi_callback,
+		.ident = "Intel D410PT",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
+			DMI_MATCH(DMI_BOARD_NAME, "D410PT"),
+		},
+	},
+	{
+		.callback = intel_no_lvds_dmi_callback,
+		.ident = "Intel D425KT",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
+			DMI_EXACT_MATCH(DMI_BOARD_NAME, "D425KT"),
+		},
+	},
+	{
+		.callback = intel_no_lvds_dmi_callback,
 		.ident = "Intel D510MO",
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index dd176b7..26c2ea3 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3864,8 +3864,6 @@
 				      dev_priv->rps.rpe_delay),
 			 dev_priv->rps.rpe_delay);
 
-	INIT_DELAYED_WORK(&dev_priv->rps.vlv_work, vlv_rps_timer_work);
-
 	valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay);
 
 	gen6_enable_rps_interrupts(dev);
@@ -4761,7 +4759,9 @@
 	 * gating for the panel power sequencer or it will fail to
 	 * start up when no ports are active.
 	 */
-	I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE);
+	I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE |
+		   PCH_DPLUNIT_CLOCK_GATE_DISABLE |
+		   PCH_CPUNIT_CLOCK_GATE_DISABLE);
 	I915_WRITE(SOUTH_CHICKEN2, I915_READ(SOUTH_CHICKEN2) |
 		   DPLS_EDP_PPS_FIX_DIS);
 	/* The below fixes the weird display corruption, a few pixels shifted
@@ -4955,6 +4955,11 @@
 	I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER,
 			GEN7_WA_L3_CHICKEN_MODE);
 
+	/* L3 caching of data atomics doesn't work -- disable it. */
+	I915_WRITE(HSW_SCRATCH1, HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE);
+	I915_WRITE(HSW_ROW_CHICKEN3,
+		   _MASKED_BIT_ENABLE(HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE));
+
 	/* This is required by WaCatErrorRejectionIssue:hsw */
 	I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
 			I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
@@ -5681,5 +5686,7 @@
 
 	INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work,
 			  intel_gen6_powersave_work);
+
+	INIT_DELAYED_WORK(&dev_priv->rps.vlv_work, vlv_rps_timer_work);
 }
 
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c
index 37712a6..e290cfa 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c
@@ -113,7 +113,7 @@
 		pmc->use_msi = false;
 		break;
 	default:
-		pmc->use_msi = nouveau_boolopt(device->cfgopt, "NvMSI", true);
+		pmc->use_msi = nouveau_boolopt(device->cfgopt, "NvMSI", false);
 		if (pmc->use_msi) {
 			pmc->use_msi = pci_enable_msi(device->pdev) == 0;
 			if (pmc->use_msi) {
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index 32923d2..5e891b2 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -707,24 +707,37 @@
 	switch (connector->connector_type) {
 	case DRM_MODE_CONNECTOR_DVII:
 	case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
-		if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) ||
-		    (drm_detect_hdmi_monitor(radeon_connector->edid) &&
-		     (radeon_connector->audio == RADEON_AUDIO_AUTO)))
-			return ATOM_ENCODER_MODE_HDMI;
-		else if (radeon_connector->use_digital)
+		if (radeon_audio != 0) {
+			if (radeon_connector->use_digital &&
+			    (radeon_connector->audio == RADEON_AUDIO_ENABLE))
+				return ATOM_ENCODER_MODE_HDMI;
+			else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+				 (radeon_connector->audio == RADEON_AUDIO_AUTO))
+				return ATOM_ENCODER_MODE_HDMI;
+			else if (radeon_connector->use_digital)
+				return ATOM_ENCODER_MODE_DVI;
+			else
+				return ATOM_ENCODER_MODE_CRT;
+		} else if (radeon_connector->use_digital) {
 			return ATOM_ENCODER_MODE_DVI;
-		else
+		} else {
 			return ATOM_ENCODER_MODE_CRT;
+		}
 		break;
 	case DRM_MODE_CONNECTOR_DVID:
 	case DRM_MODE_CONNECTOR_HDMIA:
 	default:
-		if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) ||
-		    (drm_detect_hdmi_monitor(radeon_connector->edid) &&
-		     (radeon_connector->audio == RADEON_AUDIO_AUTO)))
-			return ATOM_ENCODER_MODE_HDMI;
-		else
+		if (radeon_audio != 0) {
+			if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
+				return ATOM_ENCODER_MODE_HDMI;
+			else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+				 (radeon_connector->audio == RADEON_AUDIO_AUTO))
+				return ATOM_ENCODER_MODE_HDMI;
+			else
+				return ATOM_ENCODER_MODE_DVI;
+		} else {
 			return ATOM_ENCODER_MODE_DVI;
+		}
 		break;
 	case DRM_MODE_CONNECTOR_LVDS:
 		return ATOM_ENCODER_MODE_LVDS;
@@ -732,14 +745,19 @@
 	case DRM_MODE_CONNECTOR_DisplayPort:
 		dig_connector = radeon_connector->con_priv;
 		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
-		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
+		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
 			return ATOM_ENCODER_MODE_DP;
-		else if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) ||
-			 (drm_detect_hdmi_monitor(radeon_connector->edid) &&
-			  (radeon_connector->audio == RADEON_AUDIO_AUTO)))
-			return ATOM_ENCODER_MODE_HDMI;
-		else
+		} else if (radeon_audio != 0) {
+			if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
+				return ATOM_ENCODER_MODE_HDMI;
+			else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+				 (radeon_connector->audio == RADEON_AUDIO_AUTO))
+				return ATOM_ENCODER_MODE_HDMI;
+			else
+				return ATOM_ENCODER_MODE_DVI;
+		} else {
 			return ATOM_ENCODER_MODE_DVI;
+		}
 		break;
 	case DRM_MODE_CONNECTOR_eDP:
 		return ATOM_ENCODER_MODE_DP;
@@ -1655,7 +1673,7 @@
 			 * does the same thing and more.
 			 */
 			if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730) &&
-			    (rdev->family != CHIP_RS880))
+			    (rdev->family != CHIP_RS780) && (rdev->family != CHIP_RS880))
 				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
 		}
 		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
diff --git a/drivers/gpu/drm/radeon/btc_dpm.c b/drivers/gpu/drm/radeon/btc_dpm.c
index b162e98..9b6950d 100644
--- a/drivers/gpu/drm/radeon/btc_dpm.c
+++ b/drivers/gpu/drm/radeon/btc_dpm.c
@@ -1930,7 +1930,7 @@
 			}
 			j++;
 
-			if (j > SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE)
+			if (j >= SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE)
 				return -EINVAL;
 
 			tmp = RREG32(MC_PMG_CMD_MRS);
@@ -1945,7 +1945,7 @@
 			}
 			j++;
 
-			if (j > SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE)
+			if (j >= SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE)
 				return -EINVAL;
 			break;
 		case MC_SEQ_RESERVE_M >> 2:
@@ -1959,7 +1959,7 @@
 			}
 			j++;
 
-			if (j > SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE)
+			if (j >= SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE)
 				return -EINVAL;
 			break;
 		default:
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index d02fd1c..9cd2bc9 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -77,6 +77,8 @@
 static void cik_program_aspm(struct radeon_device *rdev);
 static void cik_init_pg(struct radeon_device *rdev);
 static void cik_init_cg(struct radeon_device *rdev);
+static void cik_fini_pg(struct radeon_device *rdev);
+static void cik_fini_cg(struct radeon_device *rdev);
 static void cik_enable_gui_idle_interrupt(struct radeon_device *rdev,
 					  bool enable);
 
@@ -1692,6 +1694,7 @@
 			       fw_name);
 			release_firmware(rdev->smc_fw);
 			rdev->smc_fw = NULL;
+			err = 0;
 		} else if (rdev->smc_fw->size != smc_req_size) {
 			printk(KERN_ERR
 			       "cik_smc: Bogus length %zu in firmware \"%s\"\n",
@@ -3180,6 +3183,7 @@
 	r = radeon_ib_get(rdev, ring->idx, &ib, NULL, 256);
 	if (r) {
 		DRM_ERROR("radeon: failed to get ib (%d).\n", r);
+		radeon_scratch_free(rdev, scratch);
 		return r;
 	}
 	ib.ptr[0] = PACKET3(PACKET3_SET_UCONFIG_REG, 1);
@@ -3196,6 +3200,8 @@
 	r = radeon_fence_wait(ib.fence, false);
 	if (r) {
 		DRM_ERROR("radeon: fence wait failed (%d).\n", r);
+		radeon_scratch_free(rdev, scratch);
+		radeon_ib_free(rdev, &ib);
 		return r;
 	}
 	for (i = 0; i < rdev->usec_timeout; i++) {
@@ -4185,6 +4191,10 @@
 	dev_info(rdev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
 		 RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS));
 
+	/* disable CG/PG */
+	cik_fini_pg(rdev);
+	cik_fini_cg(rdev);
+
 	/* stop the rlc */
 	cik_rlc_stop(rdev);
 
diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c
index 85a69d2..9fcd338 100644
--- a/drivers/gpu/drm/radeon/dce6_afmt.c
+++ b/drivers/gpu/drm/radeon/dce6_afmt.c
@@ -113,6 +113,9 @@
 	u8 *sadb;
 	int sad_count;
 
+	/* XXX: setting this register causes hangs on some asics */
+	return;
+
 	if (!dig->afmt->pin)
 		return;
 
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 555164e..b5c67a9 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -3131,7 +3131,7 @@
 		rdev->config.evergreen.sx_max_export_size = 256;
 		rdev->config.evergreen.sx_max_export_pos_size = 64;
 		rdev->config.evergreen.sx_max_export_smx_size = 192;
-		rdev->config.evergreen.max_hw_contexts = 8;
+		rdev->config.evergreen.max_hw_contexts = 4;
 		rdev->config.evergreen.sq_num_cf_insts = 2;
 
 		rdev->config.evergreen.sc_prim_fifo_size = 0x40;
diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c
index f71ce39..57fcc4b 100644
--- a/drivers/gpu/drm/radeon/evergreen_hdmi.c
+++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c
@@ -67,6 +67,9 @@
 	u8 *sadb;
 	int sad_count;
 
+	/* XXX: setting this register causes hangs on some asics */
+	return;
+
 	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
 		if (connector->encoder == encoder)
 			radeon_connector = to_radeon_connector(connector);
@@ -288,8 +291,8 @@
 	/* fglrx clears sth in AFMT_AUDIO_PACKET_CONTROL2 here */
 
 	WREG32(HDMI_ACR_PACKET_CONTROL + offset,
-	       HDMI_ACR_AUTO_SEND | /* allow hw to sent ACR packets when required */
-	       HDMI_ACR_SOURCE); /* select SW CTS value */
+	       HDMI_ACR_SOURCE | /* select SW CTS value */
+	       HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */
 
 	evergreen_hdmi_update_ACR(encoder, mode->clock);
 
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index 8768fd6..4f6d296 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -1501,7 +1501,7 @@
  * 6. COMMAND [29:22] | BYTE_COUNT [20:0]
  */
 #              define PACKET3_CP_DMA_DST_SEL(x)    ((x) << 20)
-                /* 0 - SRC_ADDR
+                /* 0 - DST_ADDR
 		 * 1 - GDS
 		 */
 #              define PACKET3_CP_DMA_ENGINE(x)     ((x) << 27)
@@ -1516,7 +1516,7 @@
 #              define PACKET3_CP_DMA_CP_SYNC       (1 << 31)
 /* COMMAND */
 #              define PACKET3_CP_DMA_DIS_WC        (1 << 21)
-#              define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 23)
+#              define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 22)
                 /* 0 - none
 		 * 1 - 8 in 16
 		 * 2 - 8 in 32
diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c
index 7139906..b419055 100644
--- a/drivers/gpu/drm/radeon/kv_dpm.c
+++ b/drivers/gpu/drm/radeon/kv_dpm.c
@@ -2635,7 +2635,7 @@
 	pi->caps_sclk_ds = true;
 	pi->enable_auto_thermal_throttling = true;
 	pi->disable_nb_ps3_in_battery = false;
-	pi->bapm_enable = true;
+	pi->bapm_enable = false;
 	pi->voltage_drop_t = 0;
 	pi->caps_sclk_throttle_low_notification = false;
 	pi->caps_fps = false; /* true? */
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 93c1f9e..cac2866 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -804,6 +804,7 @@
 			       fw_name);
 			release_firmware(rdev->smc_fw);
 			rdev->smc_fw = NULL;
+			err = 0;
 		} else if (rdev->smc_fw->size != smc_req_size) {
 			printk(KERN_ERR
 			       "ni_mc: Bogus length %zu in firmware \"%s\"\n",
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 2a1b187..f9be220 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -2302,6 +2302,7 @@
 			       fw_name);
 			release_firmware(rdev->smc_fw);
 			rdev->smc_fw = NULL;
+			err = 0;
 		} else if (rdev->smc_fw->size != smc_req_size) {
 			printk(KERN_ERR
 			       "smc: Bogus length %zu in firmware \"%s\"\n",
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
index b0fa600..06022e3 100644
--- a/drivers/gpu/drm/radeon/r600_hdmi.c
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -57,15 +57,15 @@
 static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = {
     /*	     32kHz	  44.1kHz	48kHz    */
     /* Clock      N     CTS      N     CTS      N     CTS */
-    {  25174,  4576,  28125,  7007,  31250,  6864,  28125 }, /*  25,20/1.001 MHz */
+    {  25175,  4576,  28125,  7007,  31250,  6864,  28125 }, /*  25,20/1.001 MHz */
     {  25200,  4096,  25200,  6272,  28000,  6144,  25200 }, /*  25.20       MHz */
     {  27000,  4096,  27000,  6272,  30000,  6144,  27000 }, /*  27.00       MHz */
     {  27027,  4096,  27027,  6272,  30030,  6144,  27027 }, /*  27.00*1.001 MHz */
     {  54000,  4096,  54000,  6272,  60000,  6144,  54000 }, /*  54.00       MHz */
     {  54054,  4096,  54054,  6272,  60060,  6144,  54054 }, /*  54.00*1.001 MHz */
-    {  74175, 11648, 210937, 17836, 234375, 11648, 140625 }, /*  74.25/1.001 MHz */
+    {  74176, 11648, 210937, 17836, 234375, 11648, 140625 }, /*  74.25/1.001 MHz */
     {  74250,  4096,  74250,  6272,  82500,  6144,  74250 }, /*  74.25       MHz */
-    { 148351, 11648, 421875,  8918, 234375,  5824, 140625 }, /* 148.50/1.001 MHz */
+    { 148352, 11648, 421875,  8918, 234375,  5824, 140625 }, /* 148.50/1.001 MHz */
     { 148500,  4096, 148500,  6272, 165000,  6144, 148500 }, /* 148.50       MHz */
     {      0,  4096,      0,  6272,      0,  6144,      0 }  /* Other */
 };
@@ -75,8 +75,15 @@
  */
 static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int N, int freq)
 {
-	if (*CTS == 0)
-		*CTS = clock * N / (128 * freq) * 1000;
+	u64 n;
+	u32 d;
+
+	if (*CTS == 0) {
+		n = (u64)clock * (u64)N * 1000ULL;
+		d = 128 * freq;
+		do_div(n, d);
+		*CTS = n;
+	}
 	DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n",
 		  N, *CTS, freq);
 }
@@ -302,6 +309,9 @@
 	u8 *sadb;
 	int sad_count;
 
+	/* XXX: setting this register causes hangs on some asics */
+	return;
+
 	list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
 		if (connector->encoder == encoder)
 			radeon_connector = to_radeon_connector(connector);
@@ -444,8 +454,8 @@
 	}
 
 	WREG32(HDMI0_ACR_PACKET_CONTROL + offset,
-	       HDMI0_ACR_AUTO_SEND | /* allow hw to sent ACR packets when required */
-	       HDMI0_ACR_SOURCE); /* select SW CTS value */
+	       HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */
+	       HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */
 
 	WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
 	       HDMI0_NULL_SEND | /* send null packets when required */
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
index e673fe2..7b3c7b5 100644
--- a/drivers/gpu/drm/radeon/r600d.h
+++ b/drivers/gpu/drm/radeon/r600d.h
@@ -1523,7 +1523,7 @@
  */
 #              define PACKET3_CP_DMA_CP_SYNC       (1 << 31)
 /* COMMAND */
-#              define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 23)
+#              define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 22)
                 /* 0 - none
 		 * 1 - 8 in 16
 		 * 2 - 8 in 32
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index a400ac1..24f4960 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1272,8 +1272,8 @@
 struct radeon_clock_and_voltage_limits {
 	u32 sclk;
 	u32 mclk;
-	u32 vddc;
-	u32 vddci;
+	u16 vddc;
+	u16 vddci;
 };
 
 struct radeon_clock_array {
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 79159b5..6456573 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -1658,9 +1658,12 @@
 			drm_object_attach_property(&radeon_connector->base.base,
 						      rdev->mode_info.underscan_vborder_property,
 						      0);
-			drm_object_attach_property(&radeon_connector->base.base,
-						   rdev->mode_info.audio_property,
-						   RADEON_AUDIO_DISABLE);
+			if (radeon_audio != 0)
+				drm_object_attach_property(&radeon_connector->base.base,
+							   rdev->mode_info.audio_property,
+							   (radeon_audio == 1) ?
+							   RADEON_AUDIO_AUTO :
+							   RADEON_AUDIO_DISABLE);
 			subpixel_order = SubPixelHorizontalRGB;
 			connector->interlace_allowed = true;
 			if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
@@ -1754,10 +1757,12 @@
 							      rdev->mode_info.underscan_vborder_property,
 							      0);
 			}
-			if (ASIC_IS_DCE2(rdev)) {
+			if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
 				drm_object_attach_property(&radeon_connector->base.base,
-							      rdev->mode_info.audio_property,
-							      RADEON_AUDIO_DISABLE);
+							   rdev->mode_info.audio_property,
+							   (radeon_audio == 1) ?
+							   RADEON_AUDIO_AUTO :
+							   RADEON_AUDIO_DISABLE);
 			}
 			if (connector_type == DRM_MODE_CONNECTOR_DVII) {
 				radeon_connector->dac_load_detect = true;
@@ -1799,10 +1804,12 @@
 							      rdev->mode_info.underscan_vborder_property,
 							      0);
 			}
-			if (ASIC_IS_DCE2(rdev)) {
+			if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
 				drm_object_attach_property(&radeon_connector->base.base,
-							      rdev->mode_info.audio_property,
-							      RADEON_AUDIO_DISABLE);
+							   rdev->mode_info.audio_property,
+							   (radeon_audio == 1) ?
+							   RADEON_AUDIO_AUTO :
+							   RADEON_AUDIO_DISABLE);
 			}
 			subpixel_order = SubPixelHorizontalRGB;
 			connector->interlace_allowed = true;
@@ -1843,10 +1850,12 @@
 							      rdev->mode_info.underscan_vborder_property,
 							      0);
 			}
-			if (ASIC_IS_DCE2(rdev)) {
+			if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
 				drm_object_attach_property(&radeon_connector->base.base,
-							      rdev->mode_info.audio_property,
-							      RADEON_AUDIO_DISABLE);
+							   rdev->mode_info.audio_property,
+							   (radeon_audio == 1) ?
+							   RADEON_AUDIO_AUTO :
+							   RADEON_AUDIO_DISABLE);
 			}
 			connector->interlace_allowed = true;
 			/* in theory with a DP to VGA converter... */
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index 66c2228..80285e3 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -85,9 +85,8 @@
 		   VRAM, also but everything into VRAM on AGP cards to avoid
 		   image corruptions */
 		if (p->ring == R600_RING_TYPE_UVD_INDEX &&
-		    p->rdev->family < CHIP_PALM &&
 		    (i == 0 || drm_pci_device_is_agp(p->rdev->ddev))) {
-
+			/* TODO: is this still needed for NI+ ? */
 			p->relocs[i].lobj.domain =
 				RADEON_GEM_DOMAIN_VRAM;
 
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index cdd12dc..9c14a1b 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -153,7 +153,7 @@
 int radeon_testing = 0;
 int radeon_connector_table = 0;
 int radeon_tv = 1;
-int radeon_audio = 1;
+int radeon_audio = -1;
 int radeon_disp_priority = 0;
 int radeon_hw_i2c = 0;
 int radeon_pcie_gen2 = -1;
@@ -196,7 +196,7 @@
 MODULE_PARM_DESC(tv, "TV enable (0 = disable)");
 module_param_named(tv, radeon_tv, int, 0444);
 
-MODULE_PARM_DESC(audio, "Audio enable (1 = enable)");
+MODULE_PARM_DESC(audio, "Audio enable (-1 = auto, 0 = disable, 1 = enable)");
 module_param_named(audio, radeon_audio, int, 0444);
 
 MODULE_PARM_DESC(disp_priority, "Display Priority (0 = auto, 1 = normal, 2 = high)");
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index ac07ad1..4f6b7fc 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -945,6 +945,8 @@
 		if (enable) {
 			mutex_lock(&rdev->pm.mutex);
 			rdev->pm.dpm.uvd_active = true;
+			/* disable this for now */
+#if 0
 			if ((rdev->pm.dpm.sd == 1) && (rdev->pm.dpm.hd == 0))
 				dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_SD;
 			else if ((rdev->pm.dpm.sd == 2) && (rdev->pm.dpm.hd == 0))
@@ -954,6 +956,7 @@
 			else if ((rdev->pm.dpm.sd == 0) && (rdev->pm.dpm.hd == 2))
 				dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD2;
 			else
+#endif
 				dpm_state = POWER_STATE_TYPE_INTERNAL_UVD;
 			rdev->pm.dpm.state = dpm_state;
 			mutex_unlock(&rdev->pm.mutex);
diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c
index f4d6bce..12e8099 100644
--- a/drivers/gpu/drm/radeon/radeon_test.c
+++ b/drivers/gpu/drm/radeon/radeon_test.c
@@ -36,8 +36,8 @@
 	struct radeon_bo *vram_obj = NULL;
 	struct radeon_bo **gtt_obj = NULL;
 	uint64_t gtt_addr, vram_addr;
-	unsigned i, n, size;
-	int r, ring;
+	unsigned n, size;
+	int i, r, ring;
 
 	switch (flag) {
 	case RADEON_TEST_COPY_DMA:
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index a0f1185..308eff5 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -476,7 +476,8 @@
 		return -EINVAL;
 	}
 
-	if (p->rdev->family < CHIP_PALM && (cmd == 0 || cmd == 0x3) &&
+	/* TODO: is this still necessary on NI+ ? */
+	if ((cmd == 0 || cmd == 0x3) &&
 	    (start >> 28) != (p->rdev->uvd.gpu_addr >> 28)) {
 		DRM_ERROR("msg/fb buffer %LX-%LX out of 256MB segment!\n",
 			  start, end);
@@ -798,7 +799,8 @@
 		    (rdev->pm.dpm.hd != hd)) {
 			rdev->pm.dpm.sd = sd;
 			rdev->pm.dpm.hd = hd;
-			streams_changed = true;
+			/* disable this for now */
+			/*streams_changed = true;*/
 		}
 	}
 
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index c354c10..d96f7cb 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -85,6 +85,9 @@
 			       uint32_t incr, uint32_t flags);
 static void si_enable_gui_idle_interrupt(struct radeon_device *rdev,
 					 bool enable);
+static void si_fini_pg(struct radeon_device *rdev);
+static void si_fini_cg(struct radeon_device *rdev);
+static void si_rlc_stop(struct radeon_device *rdev);
 
 static const u32 verde_rlc_save_restore_register_list[] =
 {
@@ -1678,6 +1681,7 @@
 		       fw_name);
 		release_firmware(rdev->smc_fw);
 		rdev->smc_fw = NULL;
+		err = 0;
 	} else if (rdev->smc_fw->size != smc_req_size) {
 		printk(KERN_ERR
 		       "si_smc: Bogus length %zu in firmware \"%s\"\n",
@@ -3608,6 +3612,13 @@
 	dev_info(rdev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
 		 RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS));
 
+	/* disable PG/CG */
+	si_fini_pg(rdev);
+	si_fini_cg(rdev);
+
+	/* stop the rlc */
+	si_rlc_stop(rdev);
+
 	/* Disable CP parsing/prefetching */
 	WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT);
 
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
index 9ace287..2332aa1 100644
--- a/drivers/gpu/drm/radeon/si_dpm.c
+++ b/drivers/gpu/drm/radeon/si_dpm.c
@@ -5208,7 +5208,7 @@
 					table->mc_reg_table_entry[k].mc_data[j] |= 0x100;
 			}
 			j++;
-			if (j > SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
+			if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
 				return -EINVAL;
 
 			if (!pi->mem_gddr5) {
@@ -5218,7 +5218,7 @@
 					table->mc_reg_table_entry[k].mc_data[j] =
 						(table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16;
 				j++;
-				if (j > SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
+				if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
 					return -EINVAL;
 			}
 			break;
@@ -5231,7 +5231,7 @@
 					(temp_reg & 0xffff0000) |
 					(table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
 			j++;
-			if (j > SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
+			if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
 				return -EINVAL;
 			break;
 		default:
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h
index 52d2ab6..7e2e0ea 100644
--- a/drivers/gpu/drm/radeon/sid.h
+++ b/drivers/gpu/drm/radeon/sid.h
@@ -1553,7 +1553,7 @@
  * 6. COMMAND [30:21] | BYTE_COUNT [20:0]
  */
 #              define PACKET3_CP_DMA_DST_SEL(x)    ((x) << 20)
-                /* 0 - SRC_ADDR
+                /* 0 - DST_ADDR
 		 * 1 - GDS
 		 */
 #              define PACKET3_CP_DMA_ENGINE(x)     ((x) << 27)
@@ -1568,7 +1568,7 @@
 #              define PACKET3_CP_DMA_CP_SYNC       (1 << 31)
 /* COMMAND */
 #              define PACKET3_CP_DMA_DIS_WC        (1 << 21)
-#              define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 23)
+#              define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 22)
                 /* 0 - none
 		 * 1 - 8 in 16
 		 * 2 - 8 in 32
diff --git a/drivers/gpu/drm/radeon/trinity_dpm.c b/drivers/gpu/drm/radeon/trinity_dpm.c
index 7f998bf..9364129 100644
--- a/drivers/gpu/drm/radeon/trinity_dpm.c
+++ b/drivers/gpu/drm/radeon/trinity_dpm.c
@@ -1868,7 +1868,7 @@
 	for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++)
 		pi->at[i] = TRINITY_AT_DFLT;
 
-	pi->enable_bapm = true;
+	pi->enable_bapm = false;
 	pi->enable_nbps_policy = true;
 	pi->enable_sclk_ds = true;
 	pi->enable_gfx_power_gating = true;
diff --git a/drivers/gpu/drm/radeon/uvd_v1_0.c b/drivers/gpu/drm/radeon/uvd_v1_0.c
index 3100fa9..7266805 100644
--- a/drivers/gpu/drm/radeon/uvd_v1_0.c
+++ b/drivers/gpu/drm/radeon/uvd_v1_0.c
@@ -212,8 +212,8 @@
 	/* enable VCPU clock */
 	WREG32(UVD_VCPU_CNTL,  1 << 9);
 
-	/* enable UMC and NC0 */
-	WREG32_P(UVD_LMI_CTRL2, 1 << 13, ~((1 << 8) | (1 << 13)));
+	/* enable UMC */
+	WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8));
 
 	/* boot up the VCPU */
 	WREG32(UVD_SOFT_RESET, 0);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 1a90f0a..0508f93 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -740,9 +740,17 @@
 	struct vmw_fpriv *vmw_fp;
 
 	vmw_fp = vmw_fpriv(file_priv);
-	ttm_object_file_release(&vmw_fp->tfile);
-	if (vmw_fp->locked_master)
+
+	if (vmw_fp->locked_master) {
+		struct vmw_master *vmaster =
+			vmw_master(vmw_fp->locked_master);
+
+		ttm_lock_set_kill(&vmaster->lock, true, SIGTERM);
+		ttm_vt_unlock(&vmaster->lock);
 		drm_master_put(&vmw_fp->locked_master);
+	}
+
+	ttm_object_file_release(&vmw_fp->tfile);
 	kfree(vmw_fp);
 }
 
@@ -925,14 +933,13 @@
 
 	vmw_fp->locked_master = drm_master_get(file_priv->master);
 	ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile);
-	vmw_execbuf_release_pinned_bo(dev_priv);
-
 	if (unlikely((ret != 0))) {
 		DRM_ERROR("Unable to lock TTM at VT switch.\n");
 		drm_master_put(&vmw_fp->locked_master);
 	}
 
-	ttm_lock_set_kill(&vmaster->lock, true, SIGTERM);
+	ttm_lock_set_kill(&vmaster->lock, false, SIGTERM);
+	vmw_execbuf_release_pinned_bo(dev_priv);
 
 	if (!dev_priv->enable_fb) {
 		ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index 0e67cf4..37fb4be 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -970,7 +970,7 @@
 	if (new_backup)
 		res->backup_offset = new_backup_offset;
 
-	if (!res->func->may_evict)
+	if (!res->func->may_evict || res->id == -1)
 		return;
 
 	write_lock(&dev_priv->resource_lock);
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 71b70e3..c91d547 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -241,6 +241,7 @@
 	  - Sharkoon Drakonia / Perixx MX-2000 gaming mice
 	  - Tracer Sniper TRM-503 / NOVA Gaming Slider X200 /
 	    Zalman ZM-GM1
+	  - SHARKOON DarkGlider Gaming mouse
 
 config HOLTEK_FF
 	bool "Holtek On Line Grip force feedback support"
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index b8470b1..e80da62 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -319,7 +319,7 @@
 
 static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
 {
-	__u32 raw_value;
+	__s32 raw_value;
 	switch (item->tag) {
 	case HID_GLOBAL_ITEM_TAG_PUSH:
 
@@ -370,10 +370,11 @@
 		return 0;
 
 	case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
-		/* Units exponent negative numbers are given through a
-		 * two's complement.
-		 * See "6.2.2.7 Global Items" for more information. */
-		raw_value = item_udata(item);
+		/* Many devices provide unit exponent as a two's complement
+		 * nibble due to the common misunderstanding of HID
+		 * specification 1.11, 6.2.2.7 Global Items. Attempt to handle
+		 * both this and the standard encoding. */
+		raw_value = item_sdata(item);
 		if (!(raw_value & 0xfffffff0))
 			parser->global.unit_exponent = hid_snto32(raw_value, 4);
 		else
@@ -1715,6 +1716,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
@@ -1869,6 +1871,7 @@
 
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO2, USB_DEVICE_ID_NINTENDO_WIIMOTE) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
 	{ }
 };
diff --git a/drivers/hid/hid-holtek-mouse.c b/drivers/hid/hid-holtek-mouse.c
index 7e6db3c..e696566 100644
--- a/drivers/hid/hid-holtek-mouse.c
+++ b/drivers/hid/hid-holtek-mouse.c
@@ -27,6 +27,7 @@
  * - USB ID 04d9:a067, sold as Sharkoon Drakonia and Perixx MX-2000
  * - USB ID 04d9:a04a, sold as Tracer Sniper TRM-503, NOVA Gaming Slider X200
  *   and Zalman ZM-GM1
+ * - USB ID 04d9:a081, sold as SHARKOON DarkGlider Gaming mouse
  */
 
 static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
@@ -46,6 +47,7 @@
 			}
 			break;
 		case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A:
+		case USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081:
 			if (*rsize >= 113 && rdesc[106] == 0xff && rdesc[107] == 0x7f
 					&& rdesc[111] == 0xff && rdesc[112] == 0x7f) {
 				hid_info(hdev, "Fixing up report descriptor\n");
@@ -63,6 +65,8 @@
 			USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
 			USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
+			USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, holtek_mouse_devices);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index e60e8d5..f0296a5 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -450,6 +450,7 @@
 #define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD	0xa055
 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067	0xa067
 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A04A	0xa04a
+#define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081	0xa081
 
 #define USB_VENDOR_ID_IMATION		0x0718
 #define USB_DEVICE_ID_DISC_STAKKA	0xd000
@@ -632,6 +633,7 @@
 #define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN	0x0003
 
 #define USB_VENDOR_ID_NINTENDO		0x057e
+#define USB_VENDOR_ID_NINTENDO2		0x054c
 #define USB_DEVICE_ID_NINTENDO_WIIMOTE	0x0306
 #define USB_DEVICE_ID_NINTENDO_WIIMOTE2	0x0330
 
@@ -791,6 +793,8 @@
 #define USB_DEVICE_ID_SYNAPTICS_COMP_TP	0x0009
 #define USB_DEVICE_ID_SYNAPTICS_WTP	0x0010
 #define USB_DEVICE_ID_SYNAPTICS_DPAD	0x0013
+#define USB_DEVICE_ID_SYNAPTICS_LTS1	0x0af8
+#define USB_DEVICE_ID_SYNAPTICS_LTS2	0x1d10
 
 #define USB_VENDOR_ID_THINGM		0x27b8
 #define USB_DEVICE_ID_BLINK1		0x01ed
@@ -918,4 +922,7 @@
 #define USB_VENDOR_ID_PRIMAX	0x0461
 #define USB_DEVICE_ID_PRIMAX_KEYBOARD	0x4e05
 
+#define USB_VENDOR_ID_SIS	0x0457
+#define USB_DEVICE_ID_SIS_TS	0x1013
+
 #endif
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 8741d95..d97f232 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -192,6 +192,7 @@
 	return -EINVAL;
 }
 
+
 /**
  * hidinput_calc_abs_res - calculate an absolute axis resolution
  * @field: the HID report field to calculate resolution for
@@ -234,23 +235,17 @@
 	case ABS_MT_TOOL_Y:
 	case ABS_MT_TOUCH_MAJOR:
 	case ABS_MT_TOUCH_MINOR:
-		if (field->unit & 0xffffff00)		/* Not a length */
-			return 0;
-		unit_exponent += hid_snto32(field->unit >> 4, 4) - 1;
-		switch (field->unit & 0xf) {
-		case 0x1:				/* If centimeters */
+		if (field->unit == 0x11) {		/* If centimeters */
 			/* Convert to millimeters */
 			unit_exponent += 1;
-			break;
-		case 0x3:				/* If inches */
+		} else if (field->unit == 0x13) {	/* If inches */
 			/* Convert to millimeters */
 			prev = physical_extents;
 			physical_extents *= 254;
 			if (physical_extents < prev)
 				return 0;
 			unit_exponent -= 1;
-			break;
-		default:
+		} else {
 			return 0;
 		}
 		break;
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c
index 602c188..6101816 100644
--- a/drivers/hid/hid-roccat-kone.c
+++ b/drivers/hid/hid-roccat-kone.c
@@ -382,7 +382,7 @@
 }
 #define PROFILE_ATTR(number)					\
 static struct bin_attribute bin_attr_profile##number = {	\
-	.attr = { .name = "profile##number", .mode = 0660 },	\
+	.attr = { .name = "profile" #number, .mode = 0660 },	\
 	.size = sizeof(struct kone_profile),			\
 	.read = kone_sysfs_read_profilex,			\
 	.write = kone_sysfs_write_profilex,			\
diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c
index 5ddf605..5e99fcd 100644
--- a/drivers/hid/hid-roccat-koneplus.c
+++ b/drivers/hid/hid-roccat-koneplus.c
@@ -229,13 +229,13 @@
 
 #define PROFILE_ATTR(number)						\
 static struct bin_attribute bin_attr_profile##number##_settings = {	\
-	.attr = { .name = "profile##number##_settings", .mode = 0440 },	\
+	.attr = { .name = "profile" #number "_settings", .mode = 0440 },	\
 	.size = KONEPLUS_SIZE_PROFILE_SETTINGS,				\
 	.read = koneplus_sysfs_read_profilex_settings,			\
 	.private = &profile_numbers[number-1],				\
 };									\
 static struct bin_attribute bin_attr_profile##number##_buttons = {	\
-	.attr = { .name = "profile##number##_buttons", .mode = 0440 },	\
+	.attr = { .name = "profile" #number "_buttons", .mode = 0440 },	\
 	.size = KONEPLUS_SIZE_PROFILE_BUTTONS,				\
 	.read = koneplus_sysfs_read_profilex_buttons,			\
 	.private = &profile_numbers[number-1],				\
diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c
index 515bc03..0c8e1ef 100644
--- a/drivers/hid/hid-roccat-kovaplus.c
+++ b/drivers/hid/hid-roccat-kovaplus.c
@@ -257,13 +257,13 @@
 
 #define PROFILE_ATTR(number)						\
 static struct bin_attribute bin_attr_profile##number##_settings = {	\
-	.attr = { .name = "profile##number##_settings", .mode = 0440 },	\
+	.attr = { .name = "profile" #number "_settings", .mode = 0440 },	\
 	.size = KOVAPLUS_SIZE_PROFILE_SETTINGS,				\
 	.read = kovaplus_sysfs_read_profilex_settings,			\
 	.private = &profile_numbers[number-1],				\
 };									\
 static struct bin_attribute bin_attr_profile##number##_buttons = {	\
-	.attr = { .name = "profile##number##_buttons", .mode = 0440 },	\
+	.attr = { .name = "profile" #number "_buttons", .mode = 0440 },	\
 	.size = KOVAPLUS_SIZE_PROFILE_BUTTONS,				\
 	.read = kovaplus_sysfs_read_profilex_buttons,			\
 	.private = &profile_numbers[number-1],				\
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c
index 5a6dbbe..1a07e07 100644
--- a/drivers/hid/hid-roccat-pyra.c
+++ b/drivers/hid/hid-roccat-pyra.c
@@ -225,13 +225,13 @@
 
 #define PROFILE_ATTR(number)						\
 static struct bin_attribute bin_attr_profile##number##_settings = {	\
-	.attr = { .name = "profile##number##_settings", .mode = 0440 },	\
+	.attr = { .name = "profile" #number "_settings", .mode = 0440 },	\
 	.size = PYRA_SIZE_PROFILE_SETTINGS,				\
 	.read = pyra_sysfs_read_profilex_settings,			\
 	.private = &profile_numbers[number-1],				\
 };									\
 static struct bin_attribute bin_attr_profile##number##_buttons = {	\
-	.attr = { .name = "profile##number##_buttons", .mode = 0440 },	\
+	.attr = { .name = "profile" #number "_buttons", .mode = 0440 },	\
 	.size = PYRA_SIZE_PROFILE_BUTTONS,				\
 	.read = pyra_sysfs_read_profilex_buttons,			\
 	.private = &profile_numbers[number-1],				\
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
index 10e1581..88fc5ae 100644
--- a/drivers/hid/hid-sensor-hub.c
+++ b/drivers/hid/hid-sensor-hub.c
@@ -465,6 +465,39 @@
 	return 1;
 }
 
+int sensor_hub_device_open(struct hid_sensor_hub_device *hsdev)
+{
+	int ret = 0;
+	struct sensor_hub_data *data =  hid_get_drvdata(hsdev->hdev);
+
+	mutex_lock(&data->mutex);
+	if (!hsdev->ref_cnt) {
+		ret = hid_hw_open(hsdev->hdev);
+		if (ret) {
+			hid_err(hsdev->hdev, "failed to open hid device\n");
+			mutex_unlock(&data->mutex);
+			return ret;
+		}
+	}
+	hsdev->ref_cnt++;
+	mutex_unlock(&data->mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(sensor_hub_device_open);
+
+void sensor_hub_device_close(struct hid_sensor_hub_device *hsdev)
+{
+	struct sensor_hub_data *data =  hid_get_drvdata(hsdev->hdev);
+
+	mutex_lock(&data->mutex);
+	hsdev->ref_cnt--;
+	if (!hsdev->ref_cnt)
+		hid_hw_close(hsdev->hdev);
+	mutex_unlock(&data->mutex);
+}
+EXPORT_SYMBOL_GPL(sensor_hub_device_close);
+
 static int sensor_hub_probe(struct hid_device *hdev,
 				const struct hid_device_id *id)
 {
@@ -506,12 +539,6 @@
 		hid_err(hdev, "hw start failed\n");
 		return ret;
 	}
-	ret = hid_hw_open(hdev);
-	if (ret) {
-		hid_err(hdev, "failed to open input interrupt pipe\n");
-		goto err_stop_hw;
-	}
-
 	INIT_LIST_HEAD(&sd->dyn_callback_list);
 	sd->hid_sensor_client_cnt = 0;
 	report_enum = &hdev->report_enum[HID_INPUT_REPORT];
@@ -520,7 +547,7 @@
 	if (dev_cnt > HID_MAX_PHY_DEVICES) {
 		hid_err(hdev, "Invalid Physical device count\n");
 		ret = -EINVAL;
-		goto err_close;
+		goto err_stop_hw;
 	}
 	sd->hid_sensor_hub_client_devs = kzalloc(dev_cnt *
 						sizeof(struct mfd_cell),
@@ -528,7 +555,7 @@
 	if (sd->hid_sensor_hub_client_devs == NULL) {
 		hid_err(hdev, "Failed to allocate memory for mfd cells\n");
 			ret = -ENOMEM;
-			goto err_close;
+			goto err_stop_hw;
 	}
 	list_for_each_entry(report, &report_enum->report_list, list) {
 		hid_dbg(hdev, "Report id:%x\n", report->id);
@@ -565,8 +592,6 @@
 	for (i = 0; i < sd->hid_sensor_client_cnt ; ++i)
 		kfree(sd->hid_sensor_hub_client_devs[i].name);
 	kfree(sd->hid_sensor_hub_client_devs);
-err_close:
-	hid_hw_close(hdev);
 err_stop_hw:
 	hid_hw_stop(hdev);
 
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index abb20db..1446f52 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -834,7 +834,8 @@
 		goto done;
 	}
 
-	if (vendor == USB_VENDOR_ID_NINTENDO) {
+	if (vendor == USB_VENDOR_ID_NINTENDO ||
+	    vendor == USB_VENDOR_ID_NINTENDO2) {
 		if (product == USB_DEVICE_ID_NINTENDO_WIIMOTE) {
 			devtype = WIIMOTE_DEV_GEN10;
 			goto done;
@@ -1855,6 +1856,8 @@
 static const struct hid_device_id wiimote_hid_devices[] = {
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO,
 				USB_DEVICE_ID_NINTENDO_WIIMOTE) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO2,
+				USB_DEVICE_ID_NINTENDO_WIIMOTE) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO,
 				USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
 	{ }
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index 2e7d644..71adf9e 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -119,12 +119,22 @@
  * the rumble motor, this flag shouldn't be set.
  */
 
+/* used by wiimod_rumble and wiipro_rumble */
+static void wiimod_rumble_worker(struct work_struct *work)
+{
+	struct wiimote_data *wdata = container_of(work, struct wiimote_data,
+						  rumble_worker);
+
+	spin_lock_irq(&wdata->state.lock);
+	wiiproto_req_rumble(wdata, wdata->state.cache_rumble);
+	spin_unlock_irq(&wdata->state.lock);
+}
+
 static int wiimod_rumble_play(struct input_dev *dev, void *data,
 			      struct ff_effect *eff)
 {
 	struct wiimote_data *wdata = input_get_drvdata(dev);
 	__u8 value;
-	unsigned long flags;
 
 	/*
 	 * The wiimote supports only a single rumble motor so if any magnitude
@@ -137,9 +147,10 @@
 	else
 		value = 0;
 
-	spin_lock_irqsave(&wdata->state.lock, flags);
-	wiiproto_req_rumble(wdata, value);
-	spin_unlock_irqrestore(&wdata->state.lock, flags);
+	/* Locking state.lock here might deadlock with input_event() calls.
+	 * schedule_work acts as barrier. Merging multiple changes is fine. */
+	wdata->state.cache_rumble = value;
+	schedule_work(&wdata->rumble_worker);
 
 	return 0;
 }
@@ -147,6 +158,8 @@
 static int wiimod_rumble_probe(const struct wiimod_ops *ops,
 			       struct wiimote_data *wdata)
 {
+	INIT_WORK(&wdata->rumble_worker, wiimod_rumble_worker);
+
 	set_bit(FF_RUMBLE, wdata->input->ffbit);
 	if (input_ff_create_memless(wdata->input, NULL, wiimod_rumble_play))
 		return -ENOMEM;
@@ -159,6 +172,8 @@
 {
 	unsigned long flags;
 
+	cancel_work_sync(&wdata->rumble_worker);
+
 	spin_lock_irqsave(&wdata->state.lock, flags);
 	wiiproto_req_rumble(wdata, 0);
 	spin_unlock_irqrestore(&wdata->state.lock, flags);
@@ -1731,7 +1746,6 @@
 {
 	struct wiimote_data *wdata = input_get_drvdata(dev);
 	__u8 value;
-	unsigned long flags;
 
 	/*
 	 * The wiimote supports only a single rumble motor so if any magnitude
@@ -1744,9 +1758,10 @@
 	else
 		value = 0;
 
-	spin_lock_irqsave(&wdata->state.lock, flags);
-	wiiproto_req_rumble(wdata, value);
-	spin_unlock_irqrestore(&wdata->state.lock, flags);
+	/* Locking state.lock here might deadlock with input_event() calls.
+	 * schedule_work acts as barrier. Merging multiple changes is fine. */
+	wdata->state.cache_rumble = value;
+	schedule_work(&wdata->rumble_worker);
 
 	return 0;
 }
@@ -1756,6 +1771,8 @@
 {
 	int ret, i;
 
+	INIT_WORK(&wdata->rumble_worker, wiimod_rumble_worker);
+
 	wdata->extension.input = input_allocate_device();
 	if (!wdata->extension.input)
 		return -ENOMEM;
@@ -1817,12 +1834,13 @@
 	if (!wdata->extension.input)
 		return;
 
+	input_unregister_device(wdata->extension.input);
+	wdata->extension.input = NULL;
+	cancel_work_sync(&wdata->rumble_worker);
+
 	spin_lock_irqsave(&wdata->state.lock, flags);
 	wiiproto_req_rumble(wdata, 0);
 	spin_unlock_irqrestore(&wdata->state.lock, flags);
-
-	input_unregister_device(wdata->extension.input);
-	wdata->extension.input = NULL;
 }
 
 static const struct wiimod_ops wiimod_pro = {
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index f1474f3..75db0c4 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -133,13 +133,15 @@
 	__u8 *cmd_read_buf;
 	__u8 cmd_read_size;
 
-	/* calibration data */
+	/* calibration/cache data */
 	__u16 calib_bboard[4][3];
+	__u8 cache_rumble;
 };
 
 struct wiimote_data {
 	struct hid_device *hdev;
 	struct input_dev *input;
+	struct work_struct rumble_worker;
 	struct led_classdev *leds[4];
 	struct input_dev *accel;
 	struct input_dev *ir;
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 8918dd1..6a6dd5c 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -308,18 +308,25 @@
 static void drop_ref(struct hidraw *hidraw, int exists_bit)
 {
 	if (exists_bit) {
-		hid_hw_close(hidraw->hid);
 		hidraw->exist = 0;
-		if (hidraw->open)
+		if (hidraw->open) {
+			hid_hw_close(hidraw->hid);
 			wake_up_interruptible(&hidraw->wait);
+		}
 	} else {
 		--hidraw->open;
 	}
-
-	if (!hidraw->open && !hidraw->exist) {
-		device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
-		hidraw_table[hidraw->minor] = NULL;
-		kfree(hidraw);
+	if (!hidraw->open) {
+		if (!hidraw->exist) {
+			device_destroy(hidraw_class,
+					MKDEV(hidraw_major, hidraw->minor));
+			hidraw_table[hidraw->minor] = NULL;
+			kfree(hidraw);
+		} else {
+			/* close device for last reader */
+			hid_hw_power(hidraw->hid, PM_HINT_NORMAL);
+			hid_hw_close(hidraw->hid);
+		}
 	}
 }
 
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
index 5bf2fb7..93b00d7 100644
--- a/drivers/hid/uhid.c
+++ b/drivers/hid/uhid.c
@@ -615,7 +615,7 @@
 
 static struct miscdevice uhid_misc = {
 	.fops		= &uhid_fops,
-	.minor		= MISC_DYNAMIC_MINOR,
+	.minor		= UHID_MINOR,
 	.name		= UHID_NAME,
 };
 
@@ -634,4 +634,5 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>");
 MODULE_DESCRIPTION("User-space I/O driver support for HID subsystem");
+MODULE_ALIAS_MISCDEV(UHID_MINOR);
 MODULE_ALIAS("devname:" UHID_NAME);
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 0734552..3fca3be 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -110,6 +110,9 @@
 	{ USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X, HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X, HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS },
+	{ USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1, HID_QUIRK_NO_INIT_REPORTS },
+	{ USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2, HID_QUIRK_NO_INIT_REPORTS },
+	{ USB_VENDOR_ID_SIS, USB_DEVICE_ID_SIS_TS, HID_QUIRK_NO_INIT_REPORTS },
 
 	{ 0, 0 }
 };
diff --git a/drivers/hsi/hsi.c b/drivers/hsi/hsi.c
index 66d4458..749f7b5 100644
--- a/drivers/hsi/hsi.c
+++ b/drivers/hsi/hsi.c
@@ -33,11 +33,13 @@
 {
 	return sprintf(buf, "hsi:%s\n", dev_name(dev));
 }
+static DEVICE_ATTR_RO(modalias);
 
-static struct device_attribute hsi_bus_dev_attrs[] = {
-	__ATTR_RO(modalias),
-	__ATTR_NULL,
+static struct attribute *hsi_bus_dev_attrs[] = {
+	&dev_attr_modalias.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(hsi_bus_dev);
 
 static int hsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
@@ -53,7 +55,7 @@
 
 static struct bus_type hsi_bus_type = {
 	.name		= "hsi",
-	.dev_attrs	= hsi_bus_dev_attrs,
+	.dev_groups	= hsi_bus_dev_groups,
 	.match		= hsi_bus_match,
 	.uevent		= hsi_bus_uevent,
 };
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index 6de6c98..cea623c 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -47,8 +47,8 @@
 			(unsigned long *) vmbus_connection.send_int_page +
 			(channel->offermsg.child_relid >> 5));
 
-		monitorpage = vmbus_connection.monitor_pages;
-		monitorpage++; /* Get the child to parent monitor page */
+		/* Get the child to parent monitor page */
+		monitorpage = vmbus_connection.monitor_pages[1];
 
 		sync_set_bit(channel->monitor_bit,
 			(unsigned long *)&monitorpage->trigger_group
@@ -60,50 +60,6 @@
 }
 
 /*
- * vmbus_get_debug_info -Retrieve various channel debug info
- */
-void vmbus_get_debug_info(struct vmbus_channel *channel,
-			      struct vmbus_channel_debug_info *debuginfo)
-{
-	struct hv_monitor_page *monitorpage;
-	u8 monitor_group = (u8)channel->offermsg.monitorid / 32;
-	u8 monitor_offset = (u8)channel->offermsg.monitorid % 32;
-
-	debuginfo->relid = channel->offermsg.child_relid;
-	debuginfo->state = channel->state;
-	memcpy(&debuginfo->interfacetype,
-	       &channel->offermsg.offer.if_type, sizeof(uuid_le));
-	memcpy(&debuginfo->interface_instance,
-	       &channel->offermsg.offer.if_instance,
-	       sizeof(uuid_le));
-
-	monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages;
-
-	debuginfo->monitorid = channel->offermsg.monitorid;
-
-	debuginfo->servermonitor_pending =
-			monitorpage->trigger_group[monitor_group].pending;
-	debuginfo->servermonitor_latency =
-			monitorpage->latency[monitor_group][monitor_offset];
-	debuginfo->servermonitor_connectionid =
-			monitorpage->parameter[monitor_group]
-					[monitor_offset].connectionid.u.id;
-
-	monitorpage++;
-
-	debuginfo->clientmonitor_pending =
-			monitorpage->trigger_group[monitor_group].pending;
-	debuginfo->clientmonitor_latency =
-			monitorpage->latency[monitor_group][monitor_offset];
-	debuginfo->clientmonitor_connectionid =
-			monitorpage->parameter[monitor_group]
-					[monitor_offset].connectionid.u.id;
-
-	hv_ringbuffer_get_debuginfo(&channel->inbound, &debuginfo->inbound);
-	hv_ringbuffer_get_debuginfo(&channel->outbound, &debuginfo->outbound);
-}
-
-/*
  * vmbus_open - Open the specified channel.
  */
 int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
@@ -855,6 +811,6 @@
 	if (signal)
 		vmbus_setevent(channel);
 
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index bbff5f2..fa92046 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -203,7 +203,8 @@
 	struct vmbus_channel *primary_channel;
 	struct vmbus_channel_relid_released msg;
 
-	vmbus_device_unregister(channel->device_obj);
+	if (channel->device_obj)
+		vmbus_device_unregister(channel->device_obj);
 	memset(&msg, 0, sizeof(struct vmbus_channel_relid_released));
 	msg.child_relid = channel->offermsg.child_relid;
 	msg.header.msgtype = CHANNELMSG_RELID_RELEASED;
@@ -216,7 +217,7 @@
 	} else {
 		primary_channel = channel->primary_channel;
 		spin_lock_irqsave(&primary_channel->sc_lock, flags);
-		list_del(&channel->listentry);
+		list_del(&channel->sc_list);
 		spin_unlock_irqrestore(&primary_channel->sc_lock, flags);
 	}
 	free_channel(channel);
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index 936093e..af6edf9 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -76,10 +76,8 @@
 	msg->header.msgtype = CHANNELMSG_INITIATE_CONTACT;
 	msg->vmbus_version_requested = version;
 	msg->interrupt_page = virt_to_phys(vmbus_connection.int_page);
-	msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages);
-	msg->monitor_page2 = virt_to_phys(
-			(void *)((unsigned long)vmbus_connection.monitor_pages +
-				 PAGE_SIZE));
+	msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages[0]);
+	msg->monitor_page2 = virt_to_phys(vmbus_connection.monitor_pages[1]);
 
 	/*
 	 * Add to list before we send the request since we may
@@ -169,9 +167,10 @@
 	 * Setup the monitor notification facility. The 1st page for
 	 * parent->child and the 2nd page for child->parent
 	 */
-	vmbus_connection.monitor_pages =
-	(void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 1);
-	if (vmbus_connection.monitor_pages == NULL) {
+	vmbus_connection.monitor_pages[0] = (void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 0);
+	vmbus_connection.monitor_pages[1] = (void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 0);
+	if ((vmbus_connection.monitor_pages[0] == NULL) ||
+	    (vmbus_connection.monitor_pages[1] == NULL)) {
 		ret = -ENOMEM;
 		goto cleanup;
 	}
@@ -229,10 +228,10 @@
 		vmbus_connection.int_page = NULL;
 	}
 
-	if (vmbus_connection.monitor_pages) {
-		free_pages((unsigned long)vmbus_connection.monitor_pages, 1);
-		vmbus_connection.monitor_pages = NULL;
-	}
+	free_pages((unsigned long)vmbus_connection.monitor_pages[0], 1);
+	free_pages((unsigned long)vmbus_connection.monitor_pages[1], 1);
+	vmbus_connection.monitor_pages[0] = NULL;
+	vmbus_connection.monitor_pages[1] = NULL;
 
 	kfree(msginfo);
 
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 88f4096..f0c5e07 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -304,7 +304,7 @@
 void hv_synic_free_cpu(int cpu)
 {
 	kfree(hv_context.event_dpc[cpu]);
-	if (hv_context.synic_message_page[cpu])
+	if (hv_context.synic_event_page[cpu])
 		free_page((unsigned long)hv_context.synic_event_page[cpu]);
 	if (hv_context.synic_message_page[cpu])
 		free_page((unsigned long)hv_context.synic_message_page[cpu]);
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index 273e3dd..62dfd246 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -97,7 +97,7 @@
 	struct vmbus_channel *channel = context;
 	u32 recvlen;
 	u64 requestid;
-	u8  execute_shutdown = false;
+	bool execute_shutdown = false;
 	u8  *shut_txf_buf = util_shutdown.recv_buffer;
 
 	struct shutdown_msg_data *shutdown_msg;
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index d84918f..e055176 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -514,6 +514,13 @@
 
 extern struct hv_context hv_context;
 
+struct hv_ring_buffer_debug_info {
+	u32 current_interrupt_mask;
+	u32 current_read_index;
+	u32 current_write_index;
+	u32 bytes_avail_toread;
+	u32 bytes_avail_towrite;
+};
 
 /* Hv Interface */
 
@@ -612,7 +619,7 @@
 	 * 2 pages - 1st page for parent->child notification and 2nd
 	 * is child->parent notification
 	 */
-	void *monitor_pages;
+	struct hv_monitor_page *monitor_pages[2];
 	struct list_head chn_msg_list;
 	spinlock_t channelmsg_lock;
 
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index f9fe46f..48aad4f 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -46,24 +46,6 @@
 static struct completion probe_event;
 static int irq;
 
-struct hv_device_info {
-	u32 chn_id;
-	u32 chn_state;
-	uuid_le chn_type;
-	uuid_le chn_instance;
-
-	u32 monitor_id;
-	u32 server_monitor_pending;
-	u32 server_monitor_latency;
-	u32 server_monitor_conn_id;
-	u32 client_monitor_pending;
-	u32 client_monitor_latency;
-	u32 client_monitor_conn_id;
-
-	struct hv_dev_port_info inbound;
-	struct hv_dev_port_info outbound;
-};
-
 static int vmbus_exists(void)
 {
 	if (hv_acpi_dev == NULL)
@@ -72,52 +54,6 @@
 	return 0;
 }
 
-
-static void get_channel_info(struct hv_device *device,
-			     struct hv_device_info *info)
-{
-	struct vmbus_channel_debug_info debug_info;
-
-	if (!device->channel)
-		return;
-
-	vmbus_get_debug_info(device->channel, &debug_info);
-
-	info->chn_id = debug_info.relid;
-	info->chn_state = debug_info.state;
-	memcpy(&info->chn_type, &debug_info.interfacetype,
-	       sizeof(uuid_le));
-	memcpy(&info->chn_instance, &debug_info.interface_instance,
-	       sizeof(uuid_le));
-
-	info->monitor_id = debug_info.monitorid;
-
-	info->server_monitor_pending = debug_info.servermonitor_pending;
-	info->server_monitor_latency = debug_info.servermonitor_latency;
-	info->server_monitor_conn_id = debug_info.servermonitor_connectionid;
-
-	info->client_monitor_pending = debug_info.clientmonitor_pending;
-	info->client_monitor_latency = debug_info.clientmonitor_latency;
-	info->client_monitor_conn_id = debug_info.clientmonitor_connectionid;
-
-	info->inbound.int_mask = debug_info.inbound.current_interrupt_mask;
-	info->inbound.read_idx = debug_info.inbound.current_read_index;
-	info->inbound.write_idx = debug_info.inbound.current_write_index;
-	info->inbound.bytes_avail_toread =
-		debug_info.inbound.bytes_avail_toread;
-	info->inbound.bytes_avail_towrite =
-		debug_info.inbound.bytes_avail_towrite;
-
-	info->outbound.int_mask =
-		debug_info.outbound.current_interrupt_mask;
-	info->outbound.read_idx = debug_info.outbound.current_read_index;
-	info->outbound.write_idx = debug_info.outbound.current_write_index;
-	info->outbound.bytes_avail_toread =
-		debug_info.outbound.bytes_avail_toread;
-	info->outbound.bytes_avail_towrite =
-		debug_info.outbound.bytes_avail_towrite;
-}
-
 #define VMBUS_ALIAS_LEN ((sizeof((struct hv_vmbus_device_id *)0)->guid) * 2)
 static void print_alias_name(struct hv_device *hv_dev, char *alias_name)
 {
@@ -126,115 +62,353 @@
 		sprintf(&alias_name[i], "%02x", hv_dev->dev_type.b[i/2]);
 }
 
-/*
- * vmbus_show_device_attr - Show the device attribute in sysfs.
- *
- * This is invoked when user does a
- * "cat /sys/bus/vmbus/devices/<busdevice>/<attr name>"
- */
-static ssize_t vmbus_show_device_attr(struct device *dev,
-				      struct device_attribute *dev_attr,
-				      char *buf)
+static u8 channel_monitor_group(struct vmbus_channel *channel)
 {
-	struct hv_device *hv_dev = device_to_hv_device(dev);
-	struct hv_device_info *device_info;
-	char alias_name[VMBUS_ALIAS_LEN + 1];
-	int ret = 0;
-
-	device_info = kzalloc(sizeof(struct hv_device_info), GFP_KERNEL);
-	if (!device_info)
-		return ret;
-
-	get_channel_info(hv_dev, device_info);
-
-	if (!strcmp(dev_attr->attr.name, "class_id")) {
-		ret = sprintf(buf, "{%pUl}\n", device_info->chn_type.b);
-	} else if (!strcmp(dev_attr->attr.name, "device_id")) {
-		ret = sprintf(buf, "{%pUl}\n", device_info->chn_instance.b);
-	} else if (!strcmp(dev_attr->attr.name, "modalias")) {
-		print_alias_name(hv_dev, alias_name);
-		ret = sprintf(buf, "vmbus:%s\n", alias_name);
-	} else if (!strcmp(dev_attr->attr.name, "state")) {
-		ret = sprintf(buf, "%d\n", device_info->chn_state);
-	} else if (!strcmp(dev_attr->attr.name, "id")) {
-		ret = sprintf(buf, "%d\n", device_info->chn_id);
-	} else if (!strcmp(dev_attr->attr.name, "out_intr_mask")) {
-		ret = sprintf(buf, "%d\n", device_info->outbound.int_mask);
-	} else if (!strcmp(dev_attr->attr.name, "out_read_index")) {
-		ret = sprintf(buf, "%d\n", device_info->outbound.read_idx);
-	} else if (!strcmp(dev_attr->attr.name, "out_write_index")) {
-		ret = sprintf(buf, "%d\n", device_info->outbound.write_idx);
-	} else if (!strcmp(dev_attr->attr.name, "out_read_bytes_avail")) {
-		ret = sprintf(buf, "%d\n",
-			       device_info->outbound.bytes_avail_toread);
-	} else if (!strcmp(dev_attr->attr.name, "out_write_bytes_avail")) {
-		ret = sprintf(buf, "%d\n",
-			       device_info->outbound.bytes_avail_towrite);
-	} else if (!strcmp(dev_attr->attr.name, "in_intr_mask")) {
-		ret = sprintf(buf, "%d\n", device_info->inbound.int_mask);
-	} else if (!strcmp(dev_attr->attr.name, "in_read_index")) {
-		ret = sprintf(buf, "%d\n", device_info->inbound.read_idx);
-	} else if (!strcmp(dev_attr->attr.name, "in_write_index")) {
-		ret = sprintf(buf, "%d\n", device_info->inbound.write_idx);
-	} else if (!strcmp(dev_attr->attr.name, "in_read_bytes_avail")) {
-		ret = sprintf(buf, "%d\n",
-			       device_info->inbound.bytes_avail_toread);
-	} else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail")) {
-		ret = sprintf(buf, "%d\n",
-			       device_info->inbound.bytes_avail_towrite);
-	} else if (!strcmp(dev_attr->attr.name, "monitor_id")) {
-		ret = sprintf(buf, "%d\n", device_info->monitor_id);
-	} else if (!strcmp(dev_attr->attr.name, "server_monitor_pending")) {
-		ret = sprintf(buf, "%d\n", device_info->server_monitor_pending);
-	} else if (!strcmp(dev_attr->attr.name, "server_monitor_latency")) {
-		ret = sprintf(buf, "%d\n", device_info->server_monitor_latency);
-	} else if (!strcmp(dev_attr->attr.name, "server_monitor_conn_id")) {
-		ret = sprintf(buf, "%d\n",
-			       device_info->server_monitor_conn_id);
-	} else if (!strcmp(dev_attr->attr.name, "client_monitor_pending")) {
-		ret = sprintf(buf, "%d\n", device_info->client_monitor_pending);
-	} else if (!strcmp(dev_attr->attr.name, "client_monitor_latency")) {
-		ret = sprintf(buf, "%d\n", device_info->client_monitor_latency);
-	} else if (!strcmp(dev_attr->attr.name, "client_monitor_conn_id")) {
-		ret = sprintf(buf, "%d\n",
-			       device_info->client_monitor_conn_id);
-	}
-
-	kfree(device_info);
-	return ret;
+	return (u8)channel->offermsg.monitorid / 32;
 }
 
+static u8 channel_monitor_offset(struct vmbus_channel *channel)
+{
+	return (u8)channel->offermsg.monitorid % 32;
+}
+
+static u32 channel_pending(struct vmbus_channel *channel,
+			   struct hv_monitor_page *monitor_page)
+{
+	u8 monitor_group = channel_monitor_group(channel);
+	return monitor_page->trigger_group[monitor_group].pending;
+}
+
+static u32 channel_latency(struct vmbus_channel *channel,
+			   struct hv_monitor_page *monitor_page)
+{
+	u8 monitor_group = channel_monitor_group(channel);
+	u8 monitor_offset = channel_monitor_offset(channel);
+	return monitor_page->latency[monitor_group][monitor_offset];
+}
+
+static u32 channel_conn_id(struct vmbus_channel *channel,
+			   struct hv_monitor_page *monitor_page)
+{
+	u8 monitor_group = channel_monitor_group(channel);
+	u8 monitor_offset = channel_monitor_offset(channel);
+	return monitor_page->parameter[monitor_group][monitor_offset].connectionid.u.id;
+}
+
+static ssize_t id_show(struct device *dev, struct device_attribute *dev_attr,
+		       char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	return sprintf(buf, "%d\n", hv_dev->channel->offermsg.child_relid);
+}
+static DEVICE_ATTR_RO(id);
+
+static ssize_t state_show(struct device *dev, struct device_attribute *dev_attr,
+			  char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	return sprintf(buf, "%d\n", hv_dev->channel->state);
+}
+static DEVICE_ATTR_RO(state);
+
+static ssize_t monitor_id_show(struct device *dev,
+			       struct device_attribute *dev_attr, char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	return sprintf(buf, "%d\n", hv_dev->channel->offermsg.monitorid);
+}
+static DEVICE_ATTR_RO(monitor_id);
+
+static ssize_t class_id_show(struct device *dev,
+			       struct device_attribute *dev_attr, char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	return sprintf(buf, "{%pUl}\n",
+		       hv_dev->channel->offermsg.offer.if_type.b);
+}
+static DEVICE_ATTR_RO(class_id);
+
+static ssize_t device_id_show(struct device *dev,
+			      struct device_attribute *dev_attr, char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	return sprintf(buf, "{%pUl}\n",
+		       hv_dev->channel->offermsg.offer.if_instance.b);
+}
+static DEVICE_ATTR_RO(device_id);
+
+static ssize_t modalias_show(struct device *dev,
+			     struct device_attribute *dev_attr, char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+	char alias_name[VMBUS_ALIAS_LEN + 1];
+
+	print_alias_name(hv_dev, alias_name);
+	return sprintf(buf, "vmbus:%s\n", alias_name);
+}
+static DEVICE_ATTR_RO(modalias);
+
+static ssize_t server_monitor_pending_show(struct device *dev,
+					   struct device_attribute *dev_attr,
+					   char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	return sprintf(buf, "%d\n",
+		       channel_pending(hv_dev->channel,
+				       vmbus_connection.monitor_pages[1]));
+}
+static DEVICE_ATTR_RO(server_monitor_pending);
+
+static ssize_t client_monitor_pending_show(struct device *dev,
+					   struct device_attribute *dev_attr,
+					   char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	return sprintf(buf, "%d\n",
+		       channel_pending(hv_dev->channel,
+				       vmbus_connection.monitor_pages[1]));
+}
+static DEVICE_ATTR_RO(client_monitor_pending);
+
+static ssize_t server_monitor_latency_show(struct device *dev,
+					   struct device_attribute *dev_attr,
+					   char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	return sprintf(buf, "%d\n",
+		       channel_latency(hv_dev->channel,
+				       vmbus_connection.monitor_pages[0]));
+}
+static DEVICE_ATTR_RO(server_monitor_latency);
+
+static ssize_t client_monitor_latency_show(struct device *dev,
+					   struct device_attribute *dev_attr,
+					   char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	return sprintf(buf, "%d\n",
+		       channel_latency(hv_dev->channel,
+				       vmbus_connection.monitor_pages[1]));
+}
+static DEVICE_ATTR_RO(client_monitor_latency);
+
+static ssize_t server_monitor_conn_id_show(struct device *dev,
+					   struct device_attribute *dev_attr,
+					   char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	return sprintf(buf, "%d\n",
+		       channel_conn_id(hv_dev->channel,
+				       vmbus_connection.monitor_pages[0]));
+}
+static DEVICE_ATTR_RO(server_monitor_conn_id);
+
+static ssize_t client_monitor_conn_id_show(struct device *dev,
+					   struct device_attribute *dev_attr,
+					   char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	return sprintf(buf, "%d\n",
+		       channel_conn_id(hv_dev->channel,
+				       vmbus_connection.monitor_pages[1]));
+}
+static DEVICE_ATTR_RO(client_monitor_conn_id);
+
+static ssize_t out_intr_mask_show(struct device *dev,
+				  struct device_attribute *dev_attr, char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+	struct hv_ring_buffer_debug_info outbound;
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+	return sprintf(buf, "%d\n", outbound.current_interrupt_mask);
+}
+static DEVICE_ATTR_RO(out_intr_mask);
+
+static ssize_t out_read_index_show(struct device *dev,
+				   struct device_attribute *dev_attr, char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+	struct hv_ring_buffer_debug_info outbound;
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+	return sprintf(buf, "%d\n", outbound.current_read_index);
+}
+static DEVICE_ATTR_RO(out_read_index);
+
+static ssize_t out_write_index_show(struct device *dev,
+				    struct device_attribute *dev_attr,
+				    char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+	struct hv_ring_buffer_debug_info outbound;
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+	return sprintf(buf, "%d\n", outbound.current_write_index);
+}
+static DEVICE_ATTR_RO(out_write_index);
+
+static ssize_t out_read_bytes_avail_show(struct device *dev,
+					 struct device_attribute *dev_attr,
+					 char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+	struct hv_ring_buffer_debug_info outbound;
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+	return sprintf(buf, "%d\n", outbound.bytes_avail_toread);
+}
+static DEVICE_ATTR_RO(out_read_bytes_avail);
+
+static ssize_t out_write_bytes_avail_show(struct device *dev,
+					  struct device_attribute *dev_attr,
+					  char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+	struct hv_ring_buffer_debug_info outbound;
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+	return sprintf(buf, "%d\n", outbound.bytes_avail_towrite);
+}
+static DEVICE_ATTR_RO(out_write_bytes_avail);
+
+static ssize_t in_intr_mask_show(struct device *dev,
+				 struct device_attribute *dev_attr, char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+	struct hv_ring_buffer_debug_info inbound;
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+	return sprintf(buf, "%d\n", inbound.current_interrupt_mask);
+}
+static DEVICE_ATTR_RO(in_intr_mask);
+
+static ssize_t in_read_index_show(struct device *dev,
+				  struct device_attribute *dev_attr, char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+	struct hv_ring_buffer_debug_info inbound;
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+	return sprintf(buf, "%d\n", inbound.current_read_index);
+}
+static DEVICE_ATTR_RO(in_read_index);
+
+static ssize_t in_write_index_show(struct device *dev,
+				   struct device_attribute *dev_attr, char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+	struct hv_ring_buffer_debug_info inbound;
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+	return sprintf(buf, "%d\n", inbound.current_write_index);
+}
+static DEVICE_ATTR_RO(in_write_index);
+
+static ssize_t in_read_bytes_avail_show(struct device *dev,
+					struct device_attribute *dev_attr,
+					char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+	struct hv_ring_buffer_debug_info inbound;
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+	return sprintf(buf, "%d\n", inbound.bytes_avail_toread);
+}
+static DEVICE_ATTR_RO(in_read_bytes_avail);
+
+static ssize_t in_write_bytes_avail_show(struct device *dev,
+					 struct device_attribute *dev_attr,
+					 char *buf)
+{
+	struct hv_device *hv_dev = device_to_hv_device(dev);
+	struct hv_ring_buffer_debug_info inbound;
+
+	if (!hv_dev->channel)
+		return -ENODEV;
+	hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+	return sprintf(buf, "%d\n", inbound.bytes_avail_towrite);
+}
+static DEVICE_ATTR_RO(in_write_bytes_avail);
+
 /* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */
-static struct device_attribute vmbus_device_attrs[] = {
-	__ATTR(id, S_IRUGO, vmbus_show_device_attr, NULL),
-	__ATTR(state, S_IRUGO, vmbus_show_device_attr, NULL),
-	__ATTR(class_id, S_IRUGO, vmbus_show_device_attr, NULL),
-	__ATTR(device_id, S_IRUGO, vmbus_show_device_attr, NULL),
-	__ATTR(monitor_id, S_IRUGO, vmbus_show_device_attr, NULL),
-	__ATTR(modalias, S_IRUGO, vmbus_show_device_attr, NULL),
-
-	__ATTR(server_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL),
-	__ATTR(server_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL),
-	__ATTR(server_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL),
-
-	__ATTR(client_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL),
-	__ATTR(client_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL),
-	__ATTR(client_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL),
-
-	__ATTR(out_intr_mask, S_IRUGO, vmbus_show_device_attr, NULL),
-	__ATTR(out_read_index, S_IRUGO, vmbus_show_device_attr, NULL),
-	__ATTR(out_write_index, S_IRUGO, vmbus_show_device_attr, NULL),
-	__ATTR(out_read_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
-	__ATTR(out_write_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
-
-	__ATTR(in_intr_mask, S_IRUGO, vmbus_show_device_attr, NULL),
-	__ATTR(in_read_index, S_IRUGO, vmbus_show_device_attr, NULL),
-	__ATTR(in_write_index, S_IRUGO, vmbus_show_device_attr, NULL),
-	__ATTR(in_read_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
-	__ATTR(in_write_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
-	__ATTR_NULL
+static struct attribute *vmbus_attrs[] = {
+	&dev_attr_id.attr,
+	&dev_attr_state.attr,
+	&dev_attr_monitor_id.attr,
+	&dev_attr_class_id.attr,
+	&dev_attr_device_id.attr,
+	&dev_attr_modalias.attr,
+	&dev_attr_server_monitor_pending.attr,
+	&dev_attr_client_monitor_pending.attr,
+	&dev_attr_server_monitor_latency.attr,
+	&dev_attr_client_monitor_latency.attr,
+	&dev_attr_server_monitor_conn_id.attr,
+	&dev_attr_client_monitor_conn_id.attr,
+	&dev_attr_out_intr_mask.attr,
+	&dev_attr_out_read_index.attr,
+	&dev_attr_out_write_index.attr,
+	&dev_attr_out_read_bytes_avail.attr,
+	&dev_attr_out_write_bytes_avail.attr,
+	&dev_attr_in_intr_mask.attr,
+	&dev_attr_in_read_index.attr,
+	&dev_attr_in_write_index.attr,
+	&dev_attr_in_read_bytes_avail.attr,
+	&dev_attr_in_write_bytes_avail.attr,
+	NULL,
 };
-
+ATTRIBUTE_GROUPS(vmbus);
 
 /*
  * vmbus_uevent - add uevent for our device
@@ -383,7 +557,7 @@
 	.remove =		vmbus_remove,
 	.probe =		vmbus_probe,
 	.uevent =		vmbus_uevent,
-	.dev_attrs =	vmbus_device_attrs,
+	.dev_groups =		vmbus_groups,
 };
 
 static const char *driver_name = "hyperv";
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
index 2ebd6ce..9c8a6ba 100644
--- a/drivers/hwmon/abituguru.c
+++ b/drivers/hwmon/abituguru.c
@@ -164,7 +164,7 @@
 static const int abituguru_pwm_settings_multiplier[5] = { 0, 1, 1, 1000, 1000 };
 /*
  * Min / Max allowed values for pwm_settings. Note: pwm1 (CPU fan) is a
- * special case the minium allowed pwm% setting for this is 30% (77) on
+ * special case the minimum allowed pwm% setting for this is 30% (77) on
  * some MB's this special case is handled in the code!
  */
 static const u8 abituguru_pwm_min[5] = { 0, 170, 170, 25, 25 };
@@ -517,7 +517,7 @@
 
 	ABIT_UGURU_DEBUG(2, "testing bank1 sensor %d\n", (int)sensor_addr);
 	/*
-	 * Volt sensor test, enable volt low alarm, set min value ridicously
+	 * Volt sensor test, enable volt low alarm, set min value ridiculously
 	 * high, or vica versa if the reading is very high. If its a volt
 	 * sensor this should always give us an alarm.
 	 */
@@ -564,7 +564,7 @@
 
 	/*
 	 * Temp sensor test, enable sensor as a temp sensor, set beep value
-	 * ridicously low (but not too low, otherwise uguru ignores it).
+	 * ridiculously low (but not too low, otherwise uguru ignores it).
 	 * If its a temp sensor this should always give us an alarm.
 	 */
 	buf[0] = ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE;
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index 0cac8c0..4ae74aa8 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -176,7 +176,7 @@
 
 	/*
 	 * The abituguru3 supports up to 48 sensors, and thus has registers
-	 * sets for 48 sensors, for convienence reasons / simplicity of the
+	 * sets for 48 sensors, for convenience reasons / simplicity of the
 	 * code we always read and store all registers for all 48 sensors
 	 */
 
diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c
index a9e3d01..8d40da3 100644
--- a/drivers/hwmon/acpi_power_meter.c
+++ b/drivers/hwmon/acpi_power_meter.c
@@ -381,8 +381,10 @@
 		val = resource->oem_info;
 		break;
 	default:
-		BUG();
+		WARN(1, "Implementation error: unexpected attribute index %d\n",
+		     attr->index);
 		val = "";
+		break;
 	}
 
 	return sprintf(buf, "%s\n", val);
@@ -436,7 +438,9 @@
 		val = resource->trip[attr->index - 7] * 1000;
 		break;
 	default:
-		BUG();
+		WARN(1, "Implementation error: unexpected attribute index %d\n",
+		     attr->index);
+		break;
 	}
 
 	return sprintf(buf, "%llu\n", val);
@@ -855,7 +859,8 @@
 		dev_info(&device->dev, "Capping in progress.\n");
 		break;
 	default:
-		BUG();
+		WARN(1, "Unexpected event %d\n", event);
+		break;
 	}
 	mutex_unlock(&resource->lock);
 
@@ -991,7 +996,7 @@
 
 	result = acpi_bus_register_driver(&acpi_power_meter_driver);
 	if (result < 0)
-		return -ENODEV;
+		return result;
 
 	return 0;
 }
diff --git a/drivers/hwmon/adcxx.c b/drivers/hwmon/adcxx.c
index 751b1f0..04c08c2 100644
--- a/drivers/hwmon/adcxx.c
+++ b/drivers/hwmon/adcxx.c
@@ -203,7 +203,6 @@
 	for (i--; i >= 0; i--)
 		device_remove_file(&spi->dev, &ad_input[i].dev_attr);
 
-	spi_set_drvdata(spi, NULL);
 	mutex_unlock(&adc->lock);
 	return status;
 }
@@ -218,7 +217,6 @@
 	for (i = 0; i < 3 + adc->channels; i++)
 		device_remove_file(&spi->dev, &ad_input[i].dev_attr);
 
-	spi_set_drvdata(spi, NULL);
 	mutex_unlock(&adc->lock);
 
 	return 0;
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index 3a6d9ef..b3498ac 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -616,7 +616,7 @@
 		data->gpio = gpio;
 
 		data->last_reading = jiffies;
-	}; /* last_reading */
+	}	/* last_reading */
 
 	if (!data->valid ||
 	    time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) {
@@ -700,7 +700,7 @@
 		}
 
 		data->last_config = jiffies;
-	}; /* last_config */
+	}	/* last_config */
 
 	data->valid = 1;
 	mutex_unlock(&data->update_lock);
@@ -1791,7 +1791,7 @@
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
 		/* We need to be able to do byte I/O */
 		return -ENODEV;
-	};
+	}
 
 	/* Now, we do the remaining detection. */
 
diff --git a/drivers/hwmon/adt7310.c b/drivers/hwmon/adt7310.c
index da5f078..5994cf6 100644
--- a/drivers/hwmon/adt7310.c
+++ b/drivers/hwmon/adt7310.c
@@ -42,13 +42,8 @@
 static int adt7310_spi_read_word(struct device *dev, u8 reg)
 {
 	struct spi_device *spi = to_spi_device(dev);
-	int ret;
 
-	ret = spi_w8r16(spi, AD7310_COMMAND(reg) | ADT7310_CMD_READ);
-	if (ret < 0)
-		return ret;
-
-	return be16_to_cpu((__force __be16)ret);
+	return spi_w8r16be(spi, AD7310_COMMAND(reg) | ADT7310_CMD_READ);
 }
 
 static int adt7310_spi_write_word(struct device *dev, u8 reg, u16 data)
diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c
index addb5a4..562cc38 100644
--- a/drivers/hwmon/adt7462.c
+++ b/drivers/hwmon/adt7462.c
@@ -700,7 +700,7 @@
 		if (trange_values[i] == trange)
 			return i;
 
-	return -ENODEV;
+	return -EINVAL;
 }
 
 static struct adt7462_data *adt7462_update_device(struct device *dev)
@@ -1294,9 +1294,8 @@
 	/* trange = tmax - tmin */
 	tmin = (data->pwm_tmin[attr->index] - 64) * 1000;
 	trange_value = find_trange_value(trange - tmin);
-
 	if (trange_value < 0)
-		return -EINVAL;
+		return trange_value;
 
 	temp = trange_value << ADT7462_PWM_RANGE_SHIFT;
 	temp |= data->pwm_trange[attr->index] & ADT7462_PWM_HYST_MASK;
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 98814d1..3288f13 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -230,6 +230,7 @@
 
 static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
 {
+	u8 status, data = 0;
 	int i;
 
 	if (send_command(cmd) || send_argument(key)) {
@@ -237,6 +238,7 @@
 		return -EIO;
 	}
 
+	/* This has no effect on newer (2012) SMCs */
 	if (send_byte(len, APPLESMC_DATA_PORT)) {
 		pr_warn("%.4s: read len fail\n", key);
 		return -EIO;
@@ -250,6 +252,17 @@
 		buffer[i] = inb(APPLESMC_DATA_PORT);
 	}
 
+	/* Read the data port until bit0 is cleared */
+	for (i = 0; i < 16; i++) {
+		udelay(APPLESMC_MIN_WAIT);
+		status = inb(APPLESMC_CMD_PORT);
+		if (!(status & 0x01))
+			break;
+		data = inb(APPLESMC_DATA_PORT);
+	}
+	if (i)
+		pr_warn("flushed %d bytes, last value is: %d\n", i, data);
+
 	return 0;
 }
 
diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c
index 3ad9d84..8d9f2a0 100644
--- a/drivers/hwmon/asc7621.c
+++ b/drivers/hwmon/asc7621.c
@@ -138,7 +138,7 @@
 		dev_err(&client->dev,
 			"Unable to read from register 0x%02x.\n", reg);
 		return 0;
-	};
+	}
 	return res & 0xff;
 }
 
@@ -149,7 +149,7 @@
 		dev_err(&client->dev,
 			"Unable to write value 0x%02x to register 0x%02x.\n",
 			data, reg);
-	};
+	}
 	return res;
 }
 
@@ -1030,7 +1030,7 @@
 			}
 		}
 		data->last_high_reading = jiffies;
-	};			/* last_reading */
+	}			/* last_reading */
 
 	/* Read all the low priority registers. */
 
@@ -1044,7 +1044,7 @@
 			}
 		}
 		data->last_low_reading = jiffies;
-	};			/* last_reading */
+	}			/* last_reading */
 
 	data->valid = 1;
 
@@ -1084,11 +1084,11 @@
 		dev_err(&client->dev,
 			"Client (%d,0x%02x) config is locked.\n",
 			i2c_adapter_id(client->adapter), client->addr);
-	};
+	}
 	if (!(value & 0x04)) {
 		dev_err(&client->dev, "Client (%d,0x%02x) is not ready.\n",
 			i2c_adapter_id(client->adapter), client->addr);
-	};
+	}
 
 /*
  * Start monitoring
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c
index b25c643..1d7ff46 100644
--- a/drivers/hwmon/asus_atk0110.c
+++ b/drivers/hwmon/asus_atk0110.c
@@ -119,7 +119,7 @@
 	acpi_handle rtmp_handle;
 	acpi_handle rvlt_handle;
 	acpi_handle rfan_handle;
-	/* new inteface */
+	/* new interface */
 	acpi_handle enumerate_handle;
 	acpi_handle read_handle;
 	acpi_handle write_handle;
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c
index aecb9ea..ddff02e 100644
--- a/drivers/hwmon/atxp1.c
+++ b/drivers/hwmon/atxp1.c
@@ -147,10 +147,9 @@
 
 	/* Calculate VID */
 	vid = vid_to_reg(vcore, data->vrm);
-
 	if (vid < 0) {
 		dev_err(dev, "VID calculation failed.\n");
-		return -1;
+		return vid;
 	}
 
 	/*
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index a26ba7a..872d767 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -120,7 +120,7 @@
 
 /* Each client has this additional data */
 struct ds1621_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex update_lock;
 	char valid;			/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
@@ -151,10 +151,10 @@
 	return temp;
 }
 
-static void ds1621_init_client(struct i2c_client *client)
+static void ds1621_init_client(struct ds1621_data *data,
+			       struct i2c_client *client)
 {
 	u8 conf, new_conf, sreg, resol;
-	struct ds1621_data *data = i2c_get_clientdata(client);
 
 	new_conf = conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF);
 	/* switch to continuous conversion mode */
@@ -197,8 +197,8 @@
 
 static struct ds1621_data *ds1621_update_client(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ds1621_data *data = i2c_get_clientdata(client);
+	struct ds1621_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 new_conf;
 
 	mutex_lock(&data->update_lock);
@@ -247,8 +247,7 @@
 			const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ds1621_data *data = i2c_get_clientdata(client);
+	struct ds1621_data *data = dev_get_drvdata(dev);
 	long val;
 	int err;
 
@@ -258,7 +257,7 @@
 
 	mutex_lock(&data->update_lock);
 	data->temp[attr->index] = DS1621_TEMP_TO_REG(val, data->zbits);
-	i2c_smbus_write_word_swapped(client, DS1621_REG_TEMP[attr->index],
+	i2c_smbus_write_word_swapped(data->client, DS1621_REG_TEMP[attr->index],
 				     data->temp[attr->index]);
 	mutex_unlock(&data->update_lock);
 	return count;
@@ -282,16 +281,15 @@
 static ssize_t show_convrate(struct device *dev, struct device_attribute *da,
 			  char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ds1621_data *data = i2c_get_clientdata(client);
+	struct ds1621_data *data = dev_get_drvdata(dev);
 	return scnprintf(buf, PAGE_SIZE, "%hu\n", data->update_interval);
 }
 
 static ssize_t set_convrate(struct device *dev, struct device_attribute *da,
 			    const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ds1621_data *data = i2c_get_clientdata(client);
+	struct ds1621_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long convrate;
 	s32 err;
 	int resol = 0;
@@ -343,8 +341,7 @@
 					struct attribute *attr, int index)
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ds1621_data *data = i2c_get_clientdata(client);
+	struct ds1621_data *data = dev_get_drvdata(dev);
 
 	if (attr == &dev_attr_update_interval.attr)
 		if (data->kind == ds1621 || data->kind == ds1625)
@@ -357,52 +354,31 @@
 	.attrs = ds1621_attributes,
 	.is_visible = ds1621_attribute_visible
 };
+__ATTRIBUTE_GROUPS(ds1621);
 
 static int ds1621_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct ds1621_data *data;
-	int err;
+	struct device *hwmon_dev;
 
 	data = devm_kzalloc(&client->dev, sizeof(struct ds1621_data),
 			    GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
 
 	data->kind = id->driver_data;
+	data->client = client;
 
 	/* Initialize the DS1621 chip */
-	ds1621_init_client(client);
+	ds1621_init_client(data, client);
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &ds1621_group);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove_files;
-	}
-
-	return 0;
-
- exit_remove_files:
-	sysfs_remove_group(&client->dev.kobj, &ds1621_group);
-	return err;
-}
-
-static int ds1621_remove(struct i2c_client *client)
-{
-	struct ds1621_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &ds1621_group);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
+							   client->name, data,
+							   ds1621_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static const struct i2c_device_id ds1621_id[] = {
@@ -422,7 +398,6 @@
 		.name	= "ds1621",
 	},
 	.probe		= ds1621_probe,
-	.remove		= ds1621_remove,
 	.id_table	= ds1621_id,
 };
 
diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c
index 142e1cb..90ec117 100644
--- a/drivers/hwmon/emc1403.c
+++ b/drivers/hwmon/emc1403.c
@@ -21,7 +21,6 @@
  *
  * TODO
  *	-	cache alarm and critical limit registers
- *	-	add emc1404 support
  */
 
 #include <linux/module.h>
@@ -40,7 +39,8 @@
 #define THERMAL_REVISION_REG	0xff
 
 struct thermal_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
+	const struct attribute_group *groups[3];
 	struct mutex mutex;
 	/*
 	 * Cache the hyst value so we don't keep re-reading it. In theory
@@ -53,10 +53,11 @@
 static ssize_t show_temp(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
 	struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
-	int retval = i2c_smbus_read_byte_data(client, sda->index);
+	struct thermal_data *data = dev_get_drvdata(dev);
+	int retval;
 
+	retval = i2c_smbus_read_byte_data(data->client, sda->index);
 	if (retval < 0)
 		return retval;
 	return sprintf(buf, "%d000\n", retval);
@@ -65,27 +66,27 @@
 static ssize_t show_bit(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
 	struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr);
-	int retval = i2c_smbus_read_byte_data(client, sda->nr);
+	struct thermal_data *data = dev_get_drvdata(dev);
+	int retval;
 
+	retval = i2c_smbus_read_byte_data(data->client, sda->nr);
 	if (retval < 0)
 		return retval;
-	retval &= sda->index;
-	return sprintf(buf, "%d\n", retval ? 1 : 0);
+	return sprintf(buf, "%d\n", !!(retval & sda->index));
 }
 
 static ssize_t store_temp(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
-	struct i2c_client *client = to_i2c_client(dev);
+	struct thermal_data *data = dev_get_drvdata(dev);
 	unsigned long val;
 	int retval;
 
 	if (kstrtoul(buf, 10, &val))
 		return -EINVAL;
-	retval = i2c_smbus_write_byte_data(client, sda->index,
+	retval = i2c_smbus_write_byte_data(data->client, sda->index,
 					DIV_ROUND_CLOSEST(val, 1000));
 	if (retval < 0)
 		return retval;
@@ -95,9 +96,9 @@
 static ssize_t store_bit(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct thermal_data *data = i2c_get_clientdata(client);
 	struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr);
+	struct thermal_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int retval;
 
@@ -124,9 +125,9 @@
 static ssize_t show_hyst(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct thermal_data *data = i2c_get_clientdata(client);
 	struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
+	struct thermal_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int retval;
 	int hyst;
 
@@ -147,9 +148,9 @@
 static ssize_t store_hyst(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct thermal_data *data = i2c_get_clientdata(client);
 	struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
+	struct thermal_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	int retval;
 	int hyst;
 	unsigned long val;
@@ -232,10 +233,26 @@
 static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO | S_IWUSR,
 	show_hyst, store_hyst, 0x1A);
 
+static SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO | S_IWUSR,
+	show_temp, store_temp, 0x2D);
+static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO | S_IWUSR,
+	show_temp, store_temp, 0x2C);
+static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO | S_IWUSR,
+	show_temp, store_temp, 0x30);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 0x2A);
+static SENSOR_DEVICE_ATTR_2(temp4_min_alarm, S_IRUGO,
+	show_bit, NULL, 0x36, 0x08);
+static SENSOR_DEVICE_ATTR_2(temp4_max_alarm, S_IRUGO,
+	show_bit, NULL, 0x35, 0x08);
+static SENSOR_DEVICE_ATTR_2(temp4_crit_alarm, S_IRUGO,
+	show_bit, NULL, 0x37, 0x08);
+static SENSOR_DEVICE_ATTR(temp4_crit_hyst, S_IRUGO | S_IWUSR,
+	show_hyst, store_hyst, 0x30);
+
 static SENSOR_DEVICE_ATTR_2(power_state, S_IRUGO | S_IWUSR,
 	show_bit, store_bit, 0x03, 0x40);
 
-static struct attribute *mid_att_thermal[] = {
+static struct attribute *emc1403_attrs[] = {
 	&sensor_dev_attr_temp1_min.dev_attr.attr,
 	&sensor_dev_attr_temp1_max.dev_attr.attr,
 	&sensor_dev_attr_temp1_crit.dev_attr.attr,
@@ -264,8 +281,24 @@
 	NULL
 };
 
-static const struct attribute_group m_thermal_gr = {
-	.attrs = mid_att_thermal
+static const struct attribute_group emc1403_group = {
+	.attrs = emc1403_attrs,
+};
+
+static struct attribute *emc1404_attrs[] = {
+	&sensor_dev_attr_temp4_min.dev_attr.attr,
+	&sensor_dev_attr_temp4_max.dev_attr.attr,
+	&sensor_dev_attr_temp4_crit.dev_attr.attr,
+	&sensor_dev_attr_temp4_input.dev_attr.attr,
+	&sensor_dev_attr_temp4_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp4_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp4_crit_hyst.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group emc1404_group = {
+	.attrs = emc1404_attrs,
 };
 
 static int emc1403_detect(struct i2c_client *client,
@@ -286,10 +319,12 @@
 	case 0x23:
 		strlcpy(info->type, "emc1423", I2C_NAME_SIZE);
 		break;
-	/*
-	 * Note: 0x25 is the 1404 which is very similar and this
-	 * driver could be extended
-	 */
+	case 0x25:
+		strlcpy(info->type, "emc1404", I2C_NAME_SIZE);
+		break;
+	case 0x27:
+		strlcpy(info->type, "emc1424", I2C_NAME_SIZE);
+		break;
 	default:
 		return -ENODEV;
 	}
@@ -304,43 +339,29 @@
 static int emc1403_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
-	int res;
 	struct thermal_data *data;
+	struct device *hwmon_dev;
 
 	data = devm_kzalloc(&client->dev, sizeof(struct thermal_data),
 			    GFP_KERNEL);
 	if (data == NULL)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->mutex);
 	data->hyst_valid = jiffies - 1;		/* Expired */
 
-	res = sysfs_create_group(&client->dev.kobj, &m_thermal_gr);
-	if (res) {
-		dev_warn(&client->dev, "create group failed\n");
-		return res;
-	}
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		res = PTR_ERR(data->hwmon_dev);
-		dev_warn(&client->dev, "register hwmon dev failed\n");
-		goto thermal_error;
-	}
-	dev_info(&client->dev, "EMC1403 Thermal chip found\n");
-	return 0;
+	data->groups[0] = &emc1403_group;
+	if (id->driver_data)
+		data->groups[1] = &emc1404_group;
 
-thermal_error:
-	sysfs_remove_group(&client->dev.kobj, &m_thermal_gr);
-	return res;
-}
+	hwmon_dev = hwmon_device_register_with_groups(&client->dev,
+						      client->name, data,
+						      data->groups);
+	if (IS_ERR(hwmon_dev))
+		return PTR_ERR(hwmon_dev);
 
-static int emc1403_remove(struct i2c_client *client)
-{
-	struct thermal_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &m_thermal_gr);
+	dev_info(&client->dev, "%s Thermal chip found\n", id->name);
 	return 0;
 }
 
@@ -350,7 +371,9 @@
 
 static const struct i2c_device_id emc1403_idtable[] = {
 	{ "emc1403", 0 },
+	{ "emc1404", 1 },
 	{ "emc1423", 0 },
+	{ "emc1424", 1 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, emc1403_idtable);
@@ -362,7 +385,6 @@
 	},
 	.detect = emc1403_detect,
 	.probe = emc1403_probe,
-	.remove = emc1403_remove,
 	.id_table = emc1403_idtable,
 	.address_list = emc1403_address_list,
 };
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index 31b221e..03d8592 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -2420,7 +2420,6 @@
 exit_unregister_sysfs:
 	f71882fg_remove(pdev); /* Will unregister the sysfs files for us */
 	return err; /* f71882fg_remove() also frees our data */
-	return err;
 }
 
 static int f71882fg_remove(struct platform_device *pdev)
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
index a837b94..80c42be 100644
--- a/drivers/hwmon/f75375s.c
+++ b/drivers/hwmon/f75375s.c
@@ -275,7 +275,7 @@
 	case 3: /* Manual, speed mode */
 		return false;
 	default:
-		BUG();
+		WARN(1, "Unexpected pwm_enable value %d\n", pwm_enable);
 		return true;
 	}
 }
@@ -291,7 +291,7 @@
 	case 4: /* Auto, duty mode */
 		return true;
 	default:
-		BUG();
+		WARN(1, "Unexpected pwm_enable value %d\n", pwm_enable);
 		return false;
 	}
 }
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
index b7d6a57..73181be 100644
--- a/drivers/hwmon/gpio-fan.c
+++ b/drivers/hwmon/gpio-fan.c
@@ -31,6 +31,7 @@
 #include <linux/hwmon.h>
 #include <linux/gpio.h>
 #include <linux/gpio-fan.h>
+#include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
 
@@ -169,7 +170,7 @@
 	dev_warn(&fan_data->pdev->dev,
 		 "missing speed array entry for GPIO value 0x%x\n", ctrl_val);
 
-	return -EINVAL;
+	return -ENODEV;
 }
 
 static int rpm_to_speed_index(struct gpio_fan_data *fan_data, int rpm)
@@ -309,12 +310,6 @@
 	return ret;
 }
 
-static ssize_t show_name(struct device *dev,
-			 struct device_attribute *attr, char *buf)
-{
-	return sprintf(buf, "gpio-fan\n");
-}
-
 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);
@@ -324,26 +319,23 @@
 static DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, NULL);
 static DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, show_rpm, set_rpm);
 
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-
 static umode_t gpio_fan_is_visible(struct kobject *kobj,
 				   struct attribute *attr, int index)
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct gpio_fan_data *data = dev_get_drvdata(dev);
 
-	if (index == 1 && !data->alarm)
+	if (index == 0 && !data->alarm)
 		return 0;
-	if (index > 1 && !data->ctrl)
+	if (index > 0 && !data->ctrl)
 		return 0;
 
 	return attr->mode;
 }
 
 static struct attribute *gpio_fan_attributes[] = {
-	&dev_attr_name.attr,
-	&dev_attr_fan1_alarm.attr,		/* 1 */
-	&dev_attr_pwm1.attr,			/* 2 */
+	&dev_attr_fan1_alarm.attr,		/* 0 */
+	&dev_attr_pwm1.attr,			/* 1 */
 	&dev_attr_pwm1_enable.attr,
 	&dev_attr_pwm1_mode.attr,
 	&dev_attr_fan1_input.attr,
@@ -358,6 +350,11 @@
 	.is_visible = gpio_fan_is_visible,
 };
 
+static const struct attribute_group *gpio_fan_groups[] = {
+	&gpio_fan_group,
+	NULL
+};
+
 static int fan_ctrl_init(struct gpio_fan_data *fan_data,
 			 struct gpio_fan_platform_data *pdata)
 {
@@ -384,7 +381,7 @@
 	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)
-		return -ENODEV;
+		return fan_data->speed_index;
 
 	return 0;
 }
@@ -539,24 +536,16 @@
 			return err;
 	}
 
-	err = sysfs_create_group(&pdev->dev.kobj, &gpio_fan_group);
-	if (err)
-		return err;
-
 	/* 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;
-	}
+	fan_data->hwmon_dev = hwmon_device_register_with_groups(&pdev->dev,
+						"gpio-fan", fan_data,
+						gpio_fan_groups);
+	if (IS_ERR(fan_data->hwmon_dev))
+		return PTR_ERR(fan_data->hwmon_dev);
 
 	dev_info(&pdev->dev, "GPIO fan initialized\n");
 
 	return 0;
-
-err_remove:
-	sysfs_remove_group(&pdev->dev.kobj, &gpio_fan_group);
-	return err;
 }
 
 static int gpio_fan_remove(struct platform_device *pdev)
@@ -564,7 +553,6 @@
 	struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
 
 	hwmon_device_unregister(fan_data->hwmon_dev);
-	sysfs_remove_group(&pdev->dev.kobj, &gpio_fan_group);
 
 	return 0;
 }
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 646314f..e176a43 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/err.h>
+#include <linux/slab.h>
 #include <linux/kdev_t.h>
 #include <linux/idr.h>
 #include <linux/hwmon.h>
@@ -25,11 +26,111 @@
 #define HWMON_ID_PREFIX "hwmon"
 #define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
 
-static struct class *hwmon_class;
+struct hwmon_device {
+	const char *name;
+	struct device dev;
+};
+#define to_hwmon_device(d) container_of(d, struct hwmon_device, dev)
+
+static ssize_t
+show_name(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%s\n", to_hwmon_device(dev)->name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static struct attribute *hwmon_dev_attrs[] = {
+	&dev_attr_name.attr,
+	NULL
+};
+
+static umode_t hwmon_dev_name_is_visible(struct kobject *kobj,
+					 struct attribute *attr, int n)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+
+	if (to_hwmon_device(dev)->name == NULL)
+		return 0;
+
+	return attr->mode;
+}
+
+static struct attribute_group hwmon_dev_attr_group = {
+	.attrs		= hwmon_dev_attrs,
+	.is_visible	= hwmon_dev_name_is_visible,
+};
+
+static const struct attribute_group *hwmon_dev_attr_groups[] = {
+	&hwmon_dev_attr_group,
+	NULL
+};
+
+static void hwmon_dev_release(struct device *dev)
+{
+	kfree(to_hwmon_device(dev));
+}
+
+static struct class hwmon_class = {
+	.name = "hwmon",
+	.owner = THIS_MODULE,
+	.dev_groups = hwmon_dev_attr_groups,
+	.dev_release = hwmon_dev_release,
+};
 
 static DEFINE_IDA(hwmon_ida);
 
 /**
+ * hwmon_device_register_with_groups - register w/ hwmon
+ * @dev: the parent device
+ * @name: hwmon name attribute
+ * @drvdata: driver data to attach to created device
+ * @groups: List of attribute groups to create
+ *
+ * hwmon_device_unregister() must be called when the device is no
+ * longer needed.
+ *
+ * Returns the pointer to the new device.
+ */
+struct device *
+hwmon_device_register_with_groups(struct device *dev, const char *name,
+				  void *drvdata,
+				  const struct attribute_group **groups)
+{
+	struct hwmon_device *hwdev;
+	int err, id;
+
+	id = ida_simple_get(&hwmon_ida, 0, 0, GFP_KERNEL);
+	if (id < 0)
+		return ERR_PTR(id);
+
+	hwdev = kzalloc(sizeof(*hwdev), GFP_KERNEL);
+	if (hwdev == NULL) {
+		err = -ENOMEM;
+		goto ida_remove;
+	}
+
+	hwdev->name = name;
+	hwdev->dev.class = &hwmon_class;
+	hwdev->dev.parent = dev;
+	hwdev->dev.groups = groups;
+	hwdev->dev.of_node = dev ? dev->of_node : NULL;
+	dev_set_drvdata(&hwdev->dev, drvdata);
+	dev_set_name(&hwdev->dev, HWMON_ID_FORMAT, id);
+	err = device_register(&hwdev->dev);
+	if (err)
+		goto free;
+
+	return &hwdev->dev;
+
+free:
+	kfree(hwdev);
+ida_remove:
+	ida_simple_remove(&hwmon_ida, id);
+	return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(hwmon_device_register_with_groups);
+
+/**
  * hwmon_device_register - register w/ hwmon
  * @dev: the device to register
  *
@@ -40,20 +141,7 @@
  */
 struct device *hwmon_device_register(struct device *dev)
 {
-	struct device *hwdev;
-	int id;
-
-	id = ida_simple_get(&hwmon_ida, 0, 0, GFP_KERNEL);
-	if (id < 0)
-		return ERR_PTR(id);
-
-	hwdev = device_create(hwmon_class, dev, MKDEV(0, 0), NULL,
-			      HWMON_ID_FORMAT, id);
-
-	if (IS_ERR(hwdev))
-		ida_simple_remove(&hwmon_ida, id);
-
-	return hwdev;
+	return hwmon_device_register_with_groups(dev, NULL, NULL, NULL);
 }
 EXPORT_SYMBOL_GPL(hwmon_device_register);
 
@@ -75,6 +163,69 @@
 }
 EXPORT_SYMBOL_GPL(hwmon_device_unregister);
 
+static void devm_hwmon_release(struct device *dev, void *res)
+{
+	struct device *hwdev = *(struct device **)res;
+
+	hwmon_device_unregister(hwdev);
+}
+
+/**
+ * devm_hwmon_device_register_with_groups - register w/ hwmon
+ * @dev: the parent device
+ * @name: hwmon name attribute
+ * @drvdata: driver data to attach to created device
+ * @groups: List of attribute groups to create
+ *
+ * Returns the pointer to the new device. The new device is automatically
+ * unregistered with the parent device.
+ */
+struct device *
+devm_hwmon_device_register_with_groups(struct device *dev, const char *name,
+				       void *drvdata,
+				       const struct attribute_group **groups)
+{
+	struct device **ptr, *hwdev;
+
+	if (!dev)
+		return ERR_PTR(-EINVAL);
+
+	ptr = devres_alloc(devm_hwmon_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	hwdev = hwmon_device_register_with_groups(dev, name, drvdata, groups);
+	if (IS_ERR(hwdev))
+		goto error;
+
+	*ptr = hwdev;
+	devres_add(dev, ptr);
+	return hwdev;
+
+error:
+	devres_free(ptr);
+	return hwdev;
+}
+EXPORT_SYMBOL_GPL(devm_hwmon_device_register_with_groups);
+
+static int devm_hwmon_match(struct device *dev, void *res, void *data)
+{
+	struct device **hwdev = res;
+
+	return *hwdev == data;
+}
+
+/**
+ * devm_hwmon_device_unregister - removes a previously registered hwmon device
+ *
+ * @dev: the parent device of the device to unregister
+ */
+void devm_hwmon_device_unregister(struct device *dev)
+{
+	WARN_ON(devres_release(dev, devm_hwmon_release, devm_hwmon_match, dev));
+}
+EXPORT_SYMBOL_GPL(devm_hwmon_device_unregister);
+
 static void __init hwmon_pci_quirks(void)
 {
 #if defined CONFIG_X86 && defined CONFIG_PCI
@@ -105,19 +256,21 @@
 
 static int __init hwmon_init(void)
 {
+	int err;
+
 	hwmon_pci_quirks();
 
-	hwmon_class = class_create(THIS_MODULE, "hwmon");
-	if (IS_ERR(hwmon_class)) {
-		pr_err("couldn't create sysfs class\n");
-		return PTR_ERR(hwmon_class);
+	err = class_register(&hwmon_class);
+	if (err) {
+		pr_err("couldn't register hwmon sysfs class\n");
+		return err;
 	}
 	return 0;
 }
 
 static void __exit hwmon_exit(void)
 {
-	class_destroy(hwmon_class);
+	class_unregister(&hwmon_class);
 }
 
 subsys_initcall(hwmon_init);
diff --git a/drivers/hwmon/ina209.c b/drivers/hwmon/ina209.c
index c6fdd5b..5378fde 100644
--- a/drivers/hwmon/ina209.c
+++ b/drivers/hwmon/ina209.c
@@ -63,7 +63,7 @@
 #define INA209_SHUNT_DEFAULT		10000	/* uOhm */
 
 struct ina209_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 
 	struct mutex update_lock;
 	bool valid;
@@ -78,8 +78,8 @@
 
 static struct ina209_data *ina209_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ina209_data *data = i2c_get_clientdata(client);
+	struct ina209_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	struct ina209_data *ret = data;
 	s32 val;
 	int i;
@@ -234,7 +234,6 @@
 				   struct device_attribute *da,
 				   const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
 	struct ina209_data *data = ina209_update_device(dev);
 	long val;
 	u16 regval;
@@ -250,7 +249,8 @@
 	mutex_lock(&data->update_lock);
 	regval = ina209_reg_from_interval(data->regs[INA209_CONFIGURATION],
 					  val);
-	i2c_smbus_write_word_swapped(client, INA209_CONFIGURATION, regval);
+	i2c_smbus_write_word_swapped(data->client, INA209_CONFIGURATION,
+				     regval);
 	data->regs[INA209_CONFIGURATION] = regval;
 	data->update_interval = ina209_interval_from_reg(regval);
 	mutex_unlock(&data->update_lock);
@@ -260,8 +260,7 @@
 static ssize_t ina209_show_interval(struct device *dev,
 				    struct device_attribute *da, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ina209_data *data = i2c_get_clientdata(client);
+	struct ina209_data *data = dev_get_drvdata(dev);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", data->update_interval);
 }
@@ -285,9 +284,9 @@
 				    const char *buf,
 				    size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ina209_data *data = i2c_get_clientdata(client);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct ina209_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u32 mask = attr->index;
 	long val;
 	int i, ret;
@@ -312,7 +311,6 @@
 				const char *buf,
 				size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
 	struct ina209_data *data = ina209_update_device(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	int reg = attr->index;
@@ -332,7 +330,7 @@
 		count = ret;
 		goto abort;
 	}
-	i2c_smbus_write_word_swapped(client, reg, ret);
+	i2c_smbus_write_word_swapped(data->client, reg, ret);
 	data->regs[reg] = ret;
 abort:
 	mutex_unlock(&data->update_lock);
@@ -457,7 +455,7 @@
  * Finally, construct an array of pointers to members of the above objects,
  * as required for sysfs_create_group()
  */
-static struct attribute *ina209_attributes[] = {
+static struct attribute *ina209_attrs[] = {
 	&sensor_dev_attr_in0_input.dev_attr.attr,
 	&sensor_dev_attr_in0_input_highest.dev_attr.attr,
 	&sensor_dev_attr_in0_input_lowest.dev_attr.attr,
@@ -498,10 +496,7 @@
 
 	NULL,
 };
-
-static const struct attribute_group ina209_group = {
-	.attrs = ina209_attributes,
-};
+ATTRIBUTE_GROUPS(ina209);
 
 static void ina209_restore_conf(struct i2c_client *client,
 				struct ina209_data *data)
@@ -565,6 +560,7 @@
 {
 	struct i2c_adapter *adapter = client->adapter;
 	struct ina209_data *data;
+	struct device *hwmon_dev;
 	int ret;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
@@ -575,27 +571,23 @@
 		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 
 	ret = ina209_init_client(client, data);
 	if (ret)
 		return ret;
 
-	/* Register sysfs hooks */
-	ret = sysfs_create_group(&client->dev.kobj, &ina209_group);
-	if (ret)
+	hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
+							   client->name,
+							   data, ina209_groups);
+	if (IS_ERR(hwmon_dev)) {
+		ret = PTR_ERR(hwmon_dev);
 		goto out_restore_conf;
-
-	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, &ina209_group);
 out_restore_conf:
 	ina209_restore_conf(client, data);
 	return ret;
@@ -605,8 +597,6 @@
 {
 	struct ina209_data *data = i2c_get_clientdata(client);
 
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &ina209_group);
 	ina209_restore_conf(client, data);
 
 	return 0;
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c
index 70a39a8..93d26e8 100644
--- a/drivers/hwmon/ina2xx.c
+++ b/drivers/hwmon/ina2xx.c
@@ -78,7 +78,7 @@
 };
 
 struct ina2xx_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	const struct ina2xx_config *config;
 
 	struct mutex update_lock;
@@ -112,8 +112,8 @@
 
 static struct ina2xx_data *ina2xx_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ina2xx_data *data = i2c_get_clientdata(client);
+	struct ina2xx_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	struct ina2xx_data *ret = data;
 
 	mutex_lock(&data->update_lock);
@@ -203,41 +203,39 @@
 			  INA2XX_POWER);
 
 /* pointers to created device attributes */
-static struct attribute *ina2xx_attributes[] = {
+static struct attribute *ina2xx_attrs[] = {
 	&sensor_dev_attr_in0_input.dev_attr.attr,
 	&sensor_dev_attr_in1_input.dev_attr.attr,
 	&sensor_dev_attr_curr1_input.dev_attr.attr,
 	&sensor_dev_attr_power1_input.dev_attr.attr,
 	NULL,
 };
-
-static const struct attribute_group ina2xx_group = {
-	.attrs = ina2xx_attributes,
-};
+ATTRIBUTE_GROUPS(ina2xx);
 
 static int ina2xx_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct i2c_adapter *adapter = client->adapter;
-	struct ina2xx_data *data;
 	struct ina2xx_platform_data *pdata;
-	int ret;
-	u32 val;
+	struct device *dev = &client->dev;
+	struct ina2xx_data *data;
+	struct device *hwmon_dev;
 	long shunt = 10000; /* default shunt value 10mOhms */
+	u32 val;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
 		return -ENODEV;
 
-	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	if (dev_get_platdata(&client->dev)) {
-		pdata = dev_get_platdata(&client->dev);
+	if (dev_get_platdata(dev)) {
+		pdata = dev_get_platdata(dev);
 		shunt = pdata->shunt_uohms;
-	} else if (!of_property_read_u32(client->dev.of_node,
-				"shunt-resistor", &val)) {
-			shunt = val;
+	} else if (!of_property_read_u32(dev->of_node,
+					 "shunt-resistor", &val)) {
+		shunt = val;
 	}
 
 	if (shunt <= 0)
@@ -255,37 +253,18 @@
 	i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION,
 				     data->config->calibration_factor / shunt);
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 
-	ret = sysfs_create_group(&client->dev.kobj, &ina2xx_group);
-	if (ret)
-		return ret;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, ina2xx_groups);
+	if (IS_ERR(hwmon_dev))
+		return PTR_ERR(hwmon_dev);
 
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		ret = PTR_ERR(data->hwmon_dev);
-		goto out_err_hwmon;
-	}
-
-	dev_info(&client->dev, "power monitor %s (Rshunt = %li uOhm)\n",
+	dev_info(dev, "power monitor %s (Rshunt = %li uOhm)\n",
 		 id->name, shunt);
 
 	return 0;
-
-out_err_hwmon:
-	sysfs_remove_group(&client->dev.kobj, &ina2xx_group);
-	return ret;
-}
-
-static int ina2xx_remove(struct i2c_client *client)
-{
-	struct ina2xx_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &ina2xx_group);
-
-	return 0;
 }
 
 static const struct i2c_device_id ina2xx_id[] = {
@@ -302,7 +281,6 @@
 		.name	= "ina2xx",
 	},
 	.probe		= ina2xx_probe,
-	.remove		= ina2xx_remove,
 	.id_table	= ina2xx_id,
 };
 
diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c
index 4a58f13..6013611 100644
--- a/drivers/hwmon/jc42.c
+++ b/drivers/hwmon/jc42.c
@@ -163,7 +163,7 @@
 
 /* Each client has this additional data */
 struct jc42_data {
-	struct device	*hwmon_dev;
+	struct i2c_client *client;
 	struct mutex	update_lock;	/* protect register access */
 	bool		extended;	/* true if extended range supported */
 	bool		valid;
@@ -193,21 +193,21 @@
 
 static int jc42_suspend(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct jc42_data *data = i2c_get_clientdata(client);
+	struct jc42_data *data = dev_get_drvdata(dev);
 
 	data->config |= JC42_CFG_SHUTDOWN;
-	i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, data->config);
+	i2c_smbus_write_word_swapped(data->client, JC42_REG_CONFIG,
+				     data->config);
 	return 0;
 }
 
 static int jc42_resume(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct jc42_data *data = i2c_get_clientdata(client);
+	struct jc42_data *data = dev_get_drvdata(dev);
 
 	data->config &= ~JC42_CFG_SHUTDOWN;
-	i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, data->config);
+	i2c_smbus_write_word_swapped(data->client, JC42_REG_CONFIG,
+				     data->config);
 	return 0;
 }
 
@@ -317,15 +317,14 @@
 			   struct device_attribute *attr,		\
 			   const char *buf, size_t count)		\
 {									\
-	struct i2c_client *client = to_i2c_client(dev);			\
-	struct jc42_data *data = i2c_get_clientdata(client);		\
+	struct jc42_data *data = dev_get_drvdata(dev);			\
 	int err, ret = count;						\
 	long val;							\
-	if (kstrtol(buf, 10, &val) < 0)				\
+	if (kstrtol(buf, 10, &val) < 0)					\
 		return -EINVAL;						\
 	mutex_lock(&data->update_lock);					\
 	data->value = jc42_temp_to_reg(val, data->extended);		\
-	err = i2c_smbus_write_word_swapped(client, reg, data->value);	\
+	err = i2c_smbus_write_word_swapped(data->client, reg, data->value); \
 	if (err < 0)							\
 		ret = err;						\
 	mutex_unlock(&data->update_lock);				\
@@ -344,8 +343,7 @@
 				  struct device_attribute *attr,
 				  const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct jc42_data *data = i2c_get_clientdata(client);
+	struct jc42_data *data = dev_get_drvdata(dev);
 	unsigned long val;
 	int diff, hyst;
 	int err;
@@ -368,7 +366,7 @@
 	mutex_lock(&data->update_lock);
 	data->config = (data->config & ~JC42_CFG_HYST_MASK)
 	  | (hyst << JC42_CFG_HYST_SHIFT);
-	err = i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG,
+	err = i2c_smbus_write_word_swapped(data->client, JC42_REG_CONFIG,
 					   data->config);
 	if (err < 0)
 		ret = err;
@@ -430,8 +428,7 @@
 				  struct attribute *attr, int index)
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct jc42_data *data = i2c_get_clientdata(client);
+	struct jc42_data *data = dev_get_drvdata(dev);
 	unsigned int config = data->config;
 	bool readonly;
 
@@ -452,6 +449,7 @@
 	.attrs = jc42_attributes,
 	.is_visible = jc42_attribute_mode,
 };
+__ATTRIBUTE_GROUPS(jc42);
 
 /* Return 0 if detection is successful, -ENODEV otherwise */
 static int jc42_detect(struct i2c_client *client, struct i2c_board_info *info)
@@ -487,14 +485,16 @@
 
 static int jc42_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
-	struct jc42_data *data;
-	int config, cap, err;
 	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
+	struct jc42_data *data;
+	int config, cap;
 
 	data = devm_kzalloc(dev, sizeof(struct jc42_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
+	data->client = client;
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
 
@@ -515,29 +515,15 @@
 	}
 	data->config = config;
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&dev->kobj, &jc42_group);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove;
-	}
-
-	return 0;
-
-exit_remove:
-	sysfs_remove_group(&dev->kobj, &jc42_group);
-	return err;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data,
+							   jc42_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static int jc42_remove(struct i2c_client *client)
 {
 	struct jc42_data *data = i2c_get_clientdata(client);
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &jc42_group);
 
 	/* Restore original configuration except hysteresis */
 	if ((data->config & ~JC42_CFG_HYST_MASK) !=
@@ -553,8 +539,8 @@
 
 static struct jc42_data *jc42_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct jc42_data *data = i2c_get_clientdata(client);
+	struct jc42_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	struct jc42_data *ret = data;
 	int val;
 
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
index 016efa2..505a59e 100644
--- a/drivers/hwmon/lm70.c
+++ b/drivers/hwmon/lm70.c
@@ -174,7 +174,6 @@
 out_dev_create_file_failed:
 	device_remove_file(&spi->dev, &dev_attr_temp1_input);
 out_dev_create_temp_file_failed:
-	spi_set_drvdata(spi, NULL);
 	return status;
 }
 
@@ -185,7 +184,6 @@
 	hwmon_device_unregister(p_lm70->hwmon_dev);
 	device_remove_file(&spi->dev, &dev_attr_temp1_input);
 	device_remove_file(&spi->dev, &dev_attr_name);
-	spi_set_drvdata(spi, NULL);
 
 	return 0;
 }
diff --git a/drivers/hwmon/lm73.c b/drivers/hwmon/lm73.c
index 9bde964..9653bb8 100644
--- a/drivers/hwmon/lm73.c
+++ b/drivers/hwmon/lm73.c
@@ -55,7 +55,7 @@
 };
 
 struct lm73_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex lock;
 	u8 ctrl;			/* control register value */
 };
@@ -66,7 +66,7 @@
 			const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-	struct i2c_client *client = to_i2c_client(dev);
+	struct lm73_data *data = dev_get_drvdata(dev);
 	long temp;
 	short value;
 	s32 err;
@@ -77,7 +77,7 @@
 
 	/* Write value */
 	value = clamp_val(temp / 250, LM73_TEMP_MIN, LM73_TEMP_MAX) << 5;
-	err = i2c_smbus_write_word_swapped(client, attr->index, value);
+	err = i2c_smbus_write_word_swapped(data->client, attr->index, value);
 	return (err < 0) ? err : count;
 }
 
@@ -85,10 +85,10 @@
 			 char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-	struct i2c_client *client = to_i2c_client(dev);
+	struct lm73_data *data = dev_get_drvdata(dev);
 	int temp;
 
-	s32 err = i2c_smbus_read_word_swapped(client, attr->index);
+	s32 err = i2c_smbus_read_word_swapped(data->client, attr->index);
 	if (err < 0)
 		return err;
 
@@ -101,8 +101,7 @@
 static ssize_t set_convrate(struct device *dev, struct device_attribute *da,
 			    const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm73_data *data = i2c_get_clientdata(client);
+	struct lm73_data *data = dev_get_drvdata(dev);
 	unsigned long convrate;
 	s32 err;
 	int res = 0;
@@ -124,7 +123,8 @@
 	mutex_lock(&data->lock);
 	data->ctrl &= LM73_CTRL_TO_MASK;
 	data->ctrl |= res << LM73_CTRL_RES_SHIFT;
-	err = i2c_smbus_write_byte_data(client, LM73_REG_CTRL, data->ctrl);
+	err = i2c_smbus_write_byte_data(data->client, LM73_REG_CTRL,
+					data->ctrl);
 	mutex_unlock(&data->lock);
 
 	if (err < 0)
@@ -136,8 +136,7 @@
 static ssize_t show_convrate(struct device *dev, struct device_attribute *da,
 			     char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm73_data *data = i2c_get_clientdata(client);
+	struct lm73_data *data = dev_get_drvdata(dev);
 	int res;
 
 	res = (data->ctrl & LM73_CTRL_RES_MASK) >> LM73_CTRL_RES_SHIFT;
@@ -147,13 +146,12 @@
 static ssize_t show_maxmin_alarm(struct device *dev,
 				 struct device_attribute *da, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-	struct lm73_data *data = i2c_get_clientdata(client);
+	struct lm73_data *data = dev_get_drvdata(dev);
 	s32 ctrl;
 
 	mutex_lock(&data->lock);
-	ctrl = i2c_smbus_read_byte_data(client, LM73_REG_CTRL);
+	ctrl = i2c_smbus_read_byte_data(data->client, LM73_REG_CTRL);
 	if (ctrl < 0)
 		goto abort;
 	data->ctrl = ctrl;
@@ -183,7 +181,7 @@
 static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO,
 			show_maxmin_alarm, NULL, LM73_CTRL_LO_SHIFT);
 
-static struct attribute *lm73_attributes[] = {
+static struct attribute *lm73_attrs[] = {
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_temp1_max.dev_attr.attr,
 	&sensor_dev_attr_temp1_min.dev_attr.attr,
@@ -192,10 +190,7 @@
 	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
 	NULL
 };
-
-static const struct attribute_group lm73_group = {
-	.attrs = lm73_attributes,
-};
+ATTRIBUTE_GROUPS(lm73);
 
 /*-----------------------------------------------------------------------*/
 
@@ -204,16 +199,16 @@
 static int
 lm73_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
-	int status;
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
 	struct lm73_data *data;
 	int ctrl;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct lm73_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct lm73_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->lock);
 
 	ctrl = i2c_smbus_read_byte_data(client, LM73_REG_CTRL);
@@ -221,33 +216,13 @@
 		return ctrl;
 	data->ctrl = ctrl;
 
-	/* Register sysfs hooks */
-	status = sysfs_create_group(&client->dev.kobj, &lm73_group);
-	if (status)
-		return status;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, lm73_groups);
+	if (IS_ERR(hwmon_dev))
+		return PTR_ERR(hwmon_dev);
 
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		status = PTR_ERR(data->hwmon_dev);
-		goto exit_remove;
-	}
+	dev_info(dev, "sensor '%s'\n", client->name);
 
-	dev_info(&client->dev, "%s: sensor '%s'\n",
-		 dev_name(data->hwmon_dev), client->name);
-
-	return 0;
-
-exit_remove:
-	sysfs_remove_group(&client->dev.kobj, &lm73_group);
-	return status;
-}
-
-static int lm73_remove(struct i2c_client *client)
-{
-	struct lm73_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &lm73_group);
 	return 0;
 }
 
@@ -300,7 +275,6 @@
 		.name	= "lm73",
 	},
 	.probe		= lm73_probe,
-	.remove		= lm73_remove,
 	.id_table	= lm73_ids,
 	.detect		= lm73_detect,
 	.address_list	= normal_i2c,
diff --git a/drivers/hwmon/lm95234.c b/drivers/hwmon/lm95234.c
index 307c9ea..411202b 100644
--- a/drivers/hwmon/lm95234.c
+++ b/drivers/hwmon/lm95234.c
@@ -57,7 +57,7 @@
 
 /* Client data (each client gets its own) */
 struct lm95234_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex update_lock;
 	unsigned long last_updated, interval;	/* in jiffies */
 	bool valid;		/* false until following fields are valid */
@@ -114,9 +114,9 @@
 
 /* Fill value cache. Must be called with update lock held. */
 
-static int lm95234_fill_cache(struct i2c_client *client)
+static int lm95234_fill_cache(struct lm95234_data *data,
+			      struct i2c_client *client)
 {
-	struct lm95234_data *data = i2c_get_clientdata(client);
 	int i, ret;
 
 	ret = i2c_smbus_read_byte_data(client, LM95234_REG_CONVRATE);
@@ -157,9 +157,9 @@
 	return 0;
 }
 
-static int lm95234_update_device(struct i2c_client *client,
-				 struct lm95234_data *data)
+static int lm95234_update_device(struct lm95234_data *data)
 {
+	struct i2c_client *client = data->client;
 	int ret;
 
 	mutex_lock(&data->update_lock);
@@ -169,7 +169,7 @@
 		int i;
 
 		if (!data->valid) {
-			ret = lm95234_fill_cache(client);
+			ret = lm95234_fill_cache(data, client);
 			if (ret < 0)
 				goto abort;
 		}
@@ -209,10 +209,9 @@
 static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
 			 char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95234_data *data = i2c_get_clientdata(client);
+	struct lm95234_data *data = dev_get_drvdata(dev);
 	int index = to_sensor_dev_attr(attr)->index;
-	int ret = lm95234_update_device(client, data);
+	int ret = lm95234_update_device(data);
 
 	if (ret)
 		return ret;
@@ -224,10 +223,9 @@
 static ssize_t show_alarm(struct device *dev,
 			  struct device_attribute *attr, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95234_data *data = i2c_get_clientdata(client);
+	struct lm95234_data *data = dev_get_drvdata(dev);
 	u32 mask = to_sensor_dev_attr(attr)->index;
-	int ret = lm95234_update_device(client, data);
+	int ret = lm95234_update_device(data);
 
 	if (ret)
 		return ret;
@@ -238,10 +236,9 @@
 static ssize_t show_type(struct device *dev, struct device_attribute *attr,
 			 char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95234_data *data = i2c_get_clientdata(client);
+	struct lm95234_data *data = dev_get_drvdata(dev);
 	u8 mask = to_sensor_dev_attr(attr)->index;
-	int ret = lm95234_update_device(client, data);
+	int ret = lm95234_update_device(data);
 
 	if (ret)
 		return ret;
@@ -252,11 +249,10 @@
 static ssize_t set_type(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95234_data *data = i2c_get_clientdata(client);
+	struct lm95234_data *data = dev_get_drvdata(dev);
 	unsigned long val;
 	u8 mask = to_sensor_dev_attr(attr)->index;
-	int ret = lm95234_update_device(client, data);
+	int ret = lm95234_update_device(data);
 
 	if (ret)
 		return ret;
@@ -274,7 +270,7 @@
 	else
 		data->sensor_type &= ~mask;
 	data->valid = false;
-	i2c_smbus_write_byte_data(client, LM95234_REG_REM_MODEL,
+	i2c_smbus_write_byte_data(data->client, LM95234_REG_REM_MODEL,
 				  data->sensor_type);
 	mutex_unlock(&data->update_lock);
 
@@ -284,10 +280,9 @@
 static ssize_t show_tcrit2(struct device *dev, struct device_attribute *attr,
 			   char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95234_data *data = i2c_get_clientdata(client);
+	struct lm95234_data *data = dev_get_drvdata(dev);
 	int index = to_sensor_dev_attr(attr)->index;
-	int ret = lm95234_update_device(client, data);
+	int ret = lm95234_update_device(data);
 
 	if (ret)
 		return ret;
@@ -298,11 +293,10 @@
 static ssize_t set_tcrit2(struct device *dev, struct device_attribute *attr,
 			  const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95234_data *data = i2c_get_clientdata(client);
+	struct lm95234_data *data = dev_get_drvdata(dev);
 	int index = to_sensor_dev_attr(attr)->index;
 	long val;
-	int ret = lm95234_update_device(client, data);
+	int ret = lm95234_update_device(data);
 
 	if (ret)
 		return ret;
@@ -315,7 +309,7 @@
 
 	mutex_lock(&data->update_lock);
 	data->tcrit2[index] = val;
-	i2c_smbus_write_byte_data(client, LM95234_REG_TCRIT2(index), val);
+	i2c_smbus_write_byte_data(data->client, LM95234_REG_TCRIT2(index), val);
 	mutex_unlock(&data->update_lock);
 
 	return count;
@@ -324,10 +318,9 @@
 static ssize_t show_tcrit2_hyst(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95234_data *data = i2c_get_clientdata(client);
+	struct lm95234_data *data = dev_get_drvdata(dev);
 	int index = to_sensor_dev_attr(attr)->index;
-	int ret = lm95234_update_device(client, data);
+	int ret = lm95234_update_device(data);
 
 	if (ret)
 		return ret;
@@ -340,8 +333,7 @@
 static ssize_t show_tcrit1(struct device *dev, struct device_attribute *attr,
 			   char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95234_data *data = i2c_get_clientdata(client);
+	struct lm95234_data *data = dev_get_drvdata(dev);
 	int index = to_sensor_dev_attr(attr)->index;
 
 	return sprintf(buf, "%u", data->tcrit1[index] * 1000);
@@ -350,11 +342,10 @@
 static ssize_t set_tcrit1(struct device *dev, struct device_attribute *attr,
 			  const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95234_data *data = i2c_get_clientdata(client);
+	struct lm95234_data *data = dev_get_drvdata(dev);
 	int index = to_sensor_dev_attr(attr)->index;
+	int ret = lm95234_update_device(data);
 	long val;
-	int ret = lm95234_update_device(client, data);
 
 	if (ret)
 		return ret;
@@ -367,7 +358,7 @@
 
 	mutex_lock(&data->update_lock);
 	data->tcrit1[index] = val;
-	i2c_smbus_write_byte_data(client, LM95234_REG_TCRIT1(index), val);
+	i2c_smbus_write_byte_data(data->client, LM95234_REG_TCRIT1(index), val);
 	mutex_unlock(&data->update_lock);
 
 	return count;
@@ -376,10 +367,9 @@
 static ssize_t show_tcrit1_hyst(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95234_data *data = i2c_get_clientdata(client);
+	struct lm95234_data *data = dev_get_drvdata(dev);
 	int index = to_sensor_dev_attr(attr)->index;
-	int ret = lm95234_update_device(client, data);
+	int ret = lm95234_update_device(data);
 
 	if (ret)
 		return ret;
@@ -393,11 +383,10 @@
 			       struct device_attribute *attr,
 			       const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95234_data *data = i2c_get_clientdata(client);
+	struct lm95234_data *data = dev_get_drvdata(dev);
 	int index = to_sensor_dev_attr(attr)->index;
+	int ret = lm95234_update_device(data);
 	long val;
-	int ret = lm95234_update_device(client, data);
 
 	if (ret)
 		return ret;
@@ -411,7 +400,7 @@
 
 	mutex_lock(&data->update_lock);
 	data->thyst = val;
-	i2c_smbus_write_byte_data(client, LM95234_REG_TCRIT_HYST, val);
+	i2c_smbus_write_byte_data(data->client, LM95234_REG_TCRIT_HYST, val);
 	mutex_unlock(&data->update_lock);
 
 	return count;
@@ -420,10 +409,9 @@
 static ssize_t show_offset(struct device *dev, struct device_attribute *attr,
 			   char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95234_data *data = i2c_get_clientdata(client);
+	struct lm95234_data *data = dev_get_drvdata(dev);
 	int index = to_sensor_dev_attr(attr)->index;
-	int ret = lm95234_update_device(client, data);
+	int ret = lm95234_update_device(data);
 
 	if (ret)
 		return ret;
@@ -434,11 +422,10 @@
 static ssize_t set_offset(struct device *dev, struct device_attribute *attr,
 			  const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95234_data *data = i2c_get_clientdata(client);
+	struct lm95234_data *data = dev_get_drvdata(dev);
 	int index = to_sensor_dev_attr(attr)->index;
+	int ret = lm95234_update_device(data);
 	long val;
-	int ret = lm95234_update_device(client, data);
 
 	if (ret)
 		return ret;
@@ -452,7 +439,7 @@
 
 	mutex_lock(&data->update_lock);
 	data->toffset[index] = val;
-	i2c_smbus_write_byte_data(client, LM95234_REG_OFFSET(index), val);
+	i2c_smbus_write_byte_data(data->client, LM95234_REG_OFFSET(index), val);
 	mutex_unlock(&data->update_lock);
 
 	return count;
@@ -461,9 +448,8 @@
 static ssize_t show_interval(struct device *dev, struct device_attribute *attr,
 			     char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95234_data *data = i2c_get_clientdata(client);
-	int ret = lm95234_update_device(client, data);
+	struct lm95234_data *data = dev_get_drvdata(dev);
+	int ret = lm95234_update_device(data);
 
 	if (ret)
 		return ret;
@@ -475,11 +461,10 @@
 static ssize_t set_interval(struct device *dev, struct device_attribute *attr,
 			    const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct lm95234_data *data = i2c_get_clientdata(client);
+	struct lm95234_data *data = dev_get_drvdata(dev);
+	int ret = lm95234_update_device(data);
 	unsigned long val;
 	u8 regval;
-	int ret = lm95234_update_device(client, data);
 
 	if (ret)
 		return ret;
@@ -495,7 +480,7 @@
 
 	mutex_lock(&data->update_lock);
 	data->interval = msecs_to_jiffies(update_intervals[regval]);
-	i2c_smbus_write_byte_data(client, LM95234_REG_CONVRATE, regval);
+	i2c_smbus_write_byte_data(data->client, LM95234_REG_CONVRATE, regval);
 	mutex_unlock(&data->update_lock);
 
 	return count;
@@ -579,7 +564,7 @@
 static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval,
 		   set_interval);
 
-static struct attribute *lm95234_attributes[] = {
+static struct attribute *lm95234_attrs[] = {
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_temp2_input.dev_attr.attr,
 	&sensor_dev_attr_temp3_input.dev_attr.attr,
@@ -621,10 +606,7 @@
 	&dev_attr_update_interval.attr,
 	NULL
 };
-
-static const struct attribute_group lm95234_group = {
-	.attrs = lm95234_attributes,
-};
+ATTRIBUTE_GROUPS(lm95234);
 
 static int lm95234_detect(struct i2c_client *client,
 			  struct i2c_board_info *info)
@@ -701,13 +683,14 @@
 {
 	struct device *dev = &client->dev;
 	struct lm95234_data *data;
+	struct device *hwmon_dev;
 	int err;
 
 	data = devm_kzalloc(dev, sizeof(struct lm95234_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 
 	/* Initialize the LM95234 chip */
@@ -715,32 +698,10 @@
 	if (err < 0)
 		return err;
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&dev->kobj, &lm95234_group);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove_files;
-	}
-
-	return 0;
-
-exit_remove_files:
-	sysfs_remove_group(&dev->kobj, &lm95234_group);
-	return err;
-}
-
-static int lm95234_remove(struct i2c_client *client)
-{
-	struct lm95234_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &lm95234_group);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data,
+							   lm95234_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 /* Driver data (common to all clients) */
@@ -756,7 +717,6 @@
 		.name	= DRVNAME,
 	},
 	.probe		= lm95234_probe,
-	.remove		= lm95234_remove,
 	.id_table	= lm95234_id,
 	.detect		= lm95234_detect,
 	.address_list	= normal_i2c,
diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c
index cdc1ecc..d4172933 100644
--- a/drivers/hwmon/ltc4245.c
+++ b/drivers/hwmon/ltc4245.c
@@ -51,7 +51,9 @@
 };
 
 struct ltc4245_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
+
+	const struct attribute_group *groups[3];
 
 	struct mutex update_lock;
 	bool valid;
@@ -77,8 +79,8 @@
  */
 static void ltc4245_update_gpios(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ltc4245_data *data = i2c_get_clientdata(client);
+	struct ltc4245_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u8 gpio_curr, gpio_next, gpio_reg;
 	int i;
 
@@ -130,8 +132,8 @@
 
 static struct ltc4245_data *ltc4245_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ltc4245_data *data = i2c_get_clientdata(client);
+	struct ltc4245_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	s32 val;
 	int i;
 
@@ -455,41 +457,14 @@
 	.attrs = ltc4245_gpio_attributes,
 };
 
-static int ltc4245_sysfs_create_groups(struct i2c_client *client)
+static void ltc4245_sysfs_add_groups(struct ltc4245_data *data)
 {
-	struct ltc4245_data *data = i2c_get_clientdata(client);
-	struct device *dev = &client->dev;
-	int ret;
-
-	/* register the standard sysfs attributes */
-	ret = sysfs_create_group(&dev->kobj, &ltc4245_std_group);
-	if (ret) {
-		dev_err(dev, "unable to register standard attributes\n");
-		return ret;
-	}
+	/* standard sysfs attributes */
+	data->groups[0] = &ltc4245_std_group;
 
 	/* if we're using the extra gpio support, register it's attributes */
-	if (data->use_extra_gpios) {
-		ret = sysfs_create_group(&dev->kobj, &ltc4245_gpio_group);
-		if (ret) {
-			dev_err(dev, "unable to register gpio attributes\n");
-			sysfs_remove_group(&dev->kobj, &ltc4245_std_group);
-			return ret;
-		}
-	}
-
-	return 0;
-}
-
-static void ltc4245_sysfs_remove_groups(struct i2c_client *client)
-{
-	struct ltc4245_data *data = i2c_get_clientdata(client);
-	struct device *dev = &client->dev;
-
 	if (data->use_extra_gpios)
-		sysfs_remove_group(&dev->kobj, &ltc4245_gpio_group);
-
-	sysfs_remove_group(&dev->kobj, &ltc4245_std_group);
+		data->groups[1] = &ltc4245_gpio_group;
 }
 
 static bool ltc4245_use_extra_gpios(struct i2c_client *client)
@@ -517,7 +492,7 @@
 {
 	struct i2c_adapter *adapter = client->adapter;
 	struct ltc4245_data *data;
-	int ret;
+	struct device *hwmon_dev;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
@@ -526,7 +501,7 @@
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 	data->use_extra_gpios = ltc4245_use_extra_gpios(client);
 
@@ -534,30 +509,25 @@
 	i2c_smbus_write_byte_data(client, LTC4245_FAULT1, 0x00);
 	i2c_smbus_write_byte_data(client, LTC4245_FAULT2, 0x00);
 
-	/* Register sysfs hooks */
-	ret = ltc4245_sysfs_create_groups(client);
-	if (ret)
-		return ret;
+	/* Add sysfs hooks */
+	ltc4245_sysfs_add_groups(data);
 
-	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;
-	}
+	hwmon_dev = hwmon_device_register_with_groups(&client->dev,
+						      client->name, data,
+						      data->groups);
+	if (IS_ERR(hwmon_dev))
+		return PTR_ERR(hwmon_dev);
+
+	i2c_set_clientdata(client, hwmon_dev);
 
 	return 0;
-
-out_hwmon_device_register:
-	ltc4245_sysfs_remove_groups(client);
-	return ret;
 }
 
 static int ltc4245_remove(struct i2c_client *client)
 {
-	struct ltc4245_data *data = i2c_get_clientdata(client);
+	struct device *hwmon_dev = i2c_get_clientdata(client);
 
-	hwmon_device_unregister(data->hwmon_dev);
-	ltc4245_sysfs_remove_groups(client);
+	hwmon_device_unregister(hwmon_dev);
 
 	return 0;
 }
diff --git a/drivers/hwmon/ltc4261.c b/drivers/hwmon/ltc4261.c
index 487da58..0becd69 100644
--- a/drivers/hwmon/ltc4261.c
+++ b/drivers/hwmon/ltc4261.c
@@ -55,7 +55,7 @@
 #define FAULT_OC	(1<<2)
 
 struct ltc4261_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 
 	struct mutex update_lock;
 	bool valid;
@@ -67,8 +67,8 @@
 
 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 *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	struct ltc4261_data *ret = data;
 
 	mutex_lock(&data->update_lock);
@@ -150,7 +150,6 @@
 				 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;
 
@@ -159,7 +158,7 @@
 
 	fault = data->regs[LTC4261_FAULT] & attr->index;
 	if (fault)		/* Clear reported faults in chip register */
-		i2c_smbus_write_byte_data(client, LTC4261_FAULT, ~fault);
+		i2c_smbus_write_byte_data(data->client, LTC4261_FAULT, ~fault);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", fault ? 1 : 0);
 }
@@ -197,7 +196,7 @@
 static SENSOR_DEVICE_ATTR(curr1_max_alarm, S_IRUGO, ltc4261_show_bool, NULL,
 			  FAULT_OC);
 
-static struct attribute *ltc4261_attributes[] = {
+static struct attribute *ltc4261_attrs[] = {
 	&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,
@@ -210,62 +209,38 @@
 
 	NULL,
 };
-
-static const struct attribute_group ltc4261_group = {
-	.attrs = ltc4261_attributes,
-};
+ATTRIBUTE_GROUPS(ltc4261);
 
 static int ltc4261_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct i2c_adapter *adapter = client->adapter;
+	struct device *dev = &client->dev;
 	struct ltc4261_data *data;
-	int ret;
+	struct device *hwmon_dev;
 
 	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 status register\n");
+		dev_err(dev, "Failed to read status register\n");
 		return -ENODEV;
 	}
 
-	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	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)
-		return ret;
-
-	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);
-	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);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data,
+							   ltc4261_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static const struct i2c_device_id ltc4261_id[] = {
@@ -281,7 +256,6 @@
 		   .name = "ltc4261",
 		   },
 	.probe = ltc4261_probe,
-	.remove = ltc4261_remove,
 	.id_table = ltc4261_id,
 };
 
diff --git a/drivers/hwmon/max16065.c b/drivers/hwmon/max16065.c
index 2fa2c02..d4efc79 100644
--- a/drivers/hwmon/max16065.c
+++ b/drivers/hwmon/max16065.c
@@ -83,7 +83,8 @@
 
 struct max16065_data {
 	enum chips type;
-	struct device *hwmon_dev;
+	struct i2c_client *client;
+	const struct attribute_group *groups[4];
 	struct mutex update_lock;
 	bool valid;
 	unsigned long last_updated; /* in jiffies */
@@ -144,8 +145,8 @@
 
 static struct max16065_data *max16065_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max16065_data *data = i2c_get_clientdata(client);
+	struct max16065_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 
 	mutex_lock(&data->update_lock);
 	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
@@ -186,7 +187,7 @@
 
 	val &= (1 << attr2->index);
 	if (val)
-		i2c_smbus_write_byte_data(to_i2c_client(dev),
+		i2c_smbus_write_byte_data(data->client,
 					  MAX16065_FAULT(attr2->nr), val);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", !!val);
@@ -223,8 +224,7 @@
 				  const char *buf, size_t count)
 {
 	struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(da);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max16065_data *data = i2c_get_clientdata(client);
+	struct max16065_data *data = dev_get_drvdata(dev);
 	unsigned long val;
 	int err;
 	int limit;
@@ -238,7 +238,7 @@
 	mutex_lock(&data->update_lock);
 	data->limit[attr2->nr][attr2->index]
 	  = LIMIT_TO_MV(limit, data->range[attr2->index]);
-	i2c_smbus_write_byte_data(client,
+	i2c_smbus_write_byte_data(data->client,
 				  MAX16065_LIMIT(attr2->nr, attr2->index),
 				  limit);
 	mutex_unlock(&data->update_lock);
@@ -250,8 +250,7 @@
 				   struct device_attribute *da, char *buf)
 {
 	struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(da);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max16065_data *data = i2c_get_clientdata(client);
+	struct max16065_data *data = dev_get_drvdata(dev);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n",
 			data->limit[attr2->nr][attr2->index]);
@@ -516,8 +515,32 @@
 	NULL
 };
 
+static umode_t max16065_basic_is_visible(struct kobject *kobj,
+					 struct attribute *a, int n)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct max16065_data *data = dev_get_drvdata(dev);
+	int index = n / 4;
+
+	if (index >= data->num_adc || !data->range[index])
+		return 0;
+	return a->mode;
+}
+
+static umode_t max16065_secondary_is_visible(struct kobject *kobj,
+					     struct attribute *a, int index)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct max16065_data *data = dev_get_drvdata(dev);
+
+	if (index >= data->num_adc)
+		return 0;
+	return a->mode;
+}
+
 static const struct attribute_group max16065_basic_group = {
 	.attrs = max16065_basic_attributes,
+	.is_visible = max16065_basic_is_visible,
 };
 
 static const struct attribute_group max16065_current_group = {
@@ -526,38 +549,35 @@
 
 static const struct attribute_group max16065_min_group = {
 	.attrs = max16065_min_attributes,
+	.is_visible = max16065_secondary_is_visible,
 };
 
 static const struct attribute_group max16065_max_group = {
 	.attrs = max16065_max_attributes,
+	.is_visible = max16065_secondary_is_visible,
 };
 
-static void max16065_cleanup(struct i2c_client *client)
-{
-	sysfs_remove_group(&client->dev.kobj, &max16065_max_group);
-	sysfs_remove_group(&client->dev.kobj, &max16065_min_group);
-	sysfs_remove_group(&client->dev.kobj, &max16065_current_group);
-	sysfs_remove_group(&client->dev.kobj, &max16065_basic_group);
-}
-
 static int max16065_probe(struct i2c_client *client,
 			  const struct i2c_device_id *id)
 {
 	struct i2c_adapter *adapter = client->adapter;
 	struct max16065_data *data;
-	int i, j, val, ret;
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
+	int i, j, val;
 	bool have_secondary;		/* true if chip has secondary limits */
 	bool secondary_is_max = false;	/* secondary limits reflect max */
+	int groups = 0;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
 				     | I2C_FUNC_SMBUS_READ_WORD_DATA))
 		return -ENODEV;
 
-	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 	if (unlikely(!data))
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 
 	data->num_adc = max16065_num_adc[id->driver_data];
@@ -596,38 +616,16 @@
 		}
 	}
 
-	/* Register sysfs hooks */
-	for (i = 0; i < data->num_adc * 4; i++) {
-		/* Do not create sysfs entry if channel is disabled */
-		if (!data->range[i / 4])
-			continue;
-
-		ret = sysfs_create_file(&client->dev.kobj,
-					max16065_basic_attributes[i]);
-		if (unlikely(ret))
-			goto out;
-	}
-
-	if (have_secondary) {
-		struct attribute **attr = secondary_is_max ?
-		  max16065_max_attributes : max16065_min_attributes;
-
-		for (i = 0; i < data->num_adc; i++) {
-			if (!data->range[i])
-				continue;
-
-			ret = sysfs_create_file(&client->dev.kobj, attr[i]);
-			if (unlikely(ret))
-				goto out;
-		}
-	}
+	/* sysfs hooks */
+	data->groups[groups++] = &max16065_basic_group;
+	if (have_secondary)
+		data->groups[groups++] = secondary_is_max ?
+			&max16065_max_group : &max16065_min_group;
 
 	if (data->have_current) {
 		val = i2c_smbus_read_byte_data(client, MAX16065_CURR_CONTROL);
-		if (unlikely(val < 0)) {
-			ret = val;
-			goto out;
-		}
+		if (unlikely(val < 0))
+			return val;
 		if (val & MAX16065_CURR_ENABLE) {
 			/*
 			 * Current gain is 6, 12, 24, 48 based on values in
@@ -636,33 +634,16 @@
 			data->curr_gain = 6 << ((val >> 2) & 0x03);
 			data->range[MAX16065_NUM_ADC]
 			  = max16065_csp_adc_range[(val >> 1) & 0x01];
-			ret = sysfs_create_group(&client->dev.kobj,
-						 &max16065_current_group);
-			if (unlikely(ret))
-				goto out;
+			data->groups[groups++] = &max16065_current_group;
 		} else {
 			data->have_current = false;
 		}
 	}
 
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (unlikely(IS_ERR(data->hwmon_dev))) {
-		ret = PTR_ERR(data->hwmon_dev);
-		goto out;
-	}
-	return 0;
-
-out:
-	max16065_cleanup(client);
-	return ret;
-}
-
-static int max16065_remove(struct i2c_client *client)
-{
-	struct max16065_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	max16065_cleanup(client);
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, data->groups);
+	if (unlikely(IS_ERR(hwmon_dev)))
+		return PTR_ERR(hwmon_dev);
 
 	return 0;
 }
@@ -685,7 +666,6 @@
 		.name = "max16065",
 	},
 	.probe = max16065_probe,
-	.remove = max16065_remove,
 	.id_table = max16065_id,
 };
 
diff --git a/drivers/hwmon/max6642.c b/drivers/hwmon/max6642.c
index 57d58cd..8326fbd 100644
--- a/drivers/hwmon/max6642.c
+++ b/drivers/hwmon/max6642.c
@@ -87,7 +87,7 @@
  */
 
 struct max6642_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 	struct mutex update_lock;
 	bool valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* in jiffies */
@@ -102,10 +102,10 @@
  * Real code
  */
 
-static void max6642_init_client(struct i2c_client *client)
+static void max6642_init_client(struct max6642_data *data,
+				struct i2c_client *client)
 {
 	u8 config;
-	struct max6642_data *data = i2c_get_clientdata(client);
 
 	/*
 	 * Start the conversions.
@@ -168,14 +168,14 @@
 
 static struct max6642_data *max6642_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max6642_data *data = i2c_get_clientdata(client);
+	struct max6642_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	u16 val, tmp;
 
 	mutex_lock(&data->update_lock);
 
 	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
-		dev_dbg(&client->dev, "Updating max6642 data.\n");
+		dev_dbg(dev, "Updating max6642 data.\n");
 		val = i2c_smbus_read_byte_data(client,
 					MAX6642_REG_R_LOCAL_TEMPL);
 		tmp = (val >> 6) & 3;
@@ -209,8 +209,8 @@
 static ssize_t show_temp_max10(struct device *dev,
 			       struct device_attribute *dev_attr, char *buf)
 {
-	struct max6642_data *data = max6642_update_device(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+	struct max6642_data *data = max6642_update_device(dev);
 
 	return sprintf(buf, "%d\n",
 		       temp_from_reg10(data->temp_input[attr->index]));
@@ -219,8 +219,8 @@
 static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
 			     char *buf)
 {
-	struct max6642_data *data = max6642_update_device(dev);
 	struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
+	struct max6642_data *data = max6642_update_device(dev);
 
 	return sprintf(buf, "%d\n", temp_from_reg(data->temp_high[attr2->nr]));
 }
@@ -228,11 +228,10 @@
 static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
 			    const char *buf, size_t count)
 {
+	struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
+	struct max6642_data *data = dev_get_drvdata(dev);
 	unsigned long val;
 	int err;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max6642_data *data = i2c_get_clientdata(client);
-	struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
 
 	err = kstrtoul(buf, 10, &val);
 	if (err < 0)
@@ -240,7 +239,7 @@
 
 	mutex_lock(&data->update_lock);
 	data->temp_high[attr2->nr] = clamp_val(temp_to_reg(val), 0, 255);
-	i2c_smbus_write_byte_data(client, attr2->index,
+	i2c_smbus_write_byte_data(data->client, attr2->index,
 				  data->temp_high[attr2->nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
@@ -264,7 +263,7 @@
 static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
 static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4);
 
-static struct attribute *max6642_attributes[] = {
+static struct attribute *max6642_attrs[] = {
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_temp2_input.dev_attr.attr,
 	&sensor_dev_attr_temp1_max.dev_attr.attr,
@@ -275,54 +274,29 @@
 	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
 	NULL
 };
+ATTRIBUTE_GROUPS(max6642);
 
-static const struct attribute_group max6642_group = {
-	.attrs = max6642_attributes,
-};
-
-static int max6642_probe(struct i2c_client *new_client,
+static int max6642_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
+	struct device *dev = &client->dev;
 	struct max6642_data *data;
-	int err;
+	struct device *hwmon_dev;
 
-	data = devm_kzalloc(&new_client->dev, sizeof(struct max6642_data),
-			    GFP_KERNEL);
+	data = devm_kzalloc(dev, sizeof(struct max6642_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(new_client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 
 	/* Initialize the MAX6642 chip */
-	max6642_init_client(new_client);
+	max6642_init_client(data, client);
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&new_client->dev.kobj, &max6642_group);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(&new_client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove_files;
-	}
-
-	return 0;
-
-exit_remove_files:
-	sysfs_remove_group(&new_client->dev.kobj, &max6642_group);
-	return err;
-}
-
-static int max6642_remove(struct i2c_client *client)
-{
-	struct max6642_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &max6642_group);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev,
+							   client->name, data,
+							   max6642_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 /*
@@ -341,7 +315,6 @@
 		.name	= "max6642",
 	},
 	.probe		= max6642_probe,
-	.remove		= max6642_remove,
 	.id_table	= max6642_id,
 	.detect		= max6642_detect,
 	.address_list	= normal_i2c,
diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c
index 3c16cbd..0cafc39 100644
--- a/drivers/hwmon/max6650.c
+++ b/drivers/hwmon/max6650.c
@@ -660,7 +660,7 @@
 	/*
 	 * If mode is set to "full off", we change it to "open loop" and
 	 * set DAC to 255, which has the same effect. We do this because
-	 * there's no "full off" mode defined in hwmon specifcations.
+	 * there's no "full off" mode defined in hwmon specifications.
 	 */
 
 	if ((config & MAX6650_CFG_MODE_MASK) == MAX6650_CFG_MODE_OFF) {
diff --git a/drivers/hwmon/max6697.c b/drivers/hwmon/max6697.c
index a41b5f3..7fd3eaf 100644
--- a/drivers/hwmon/max6697.c
+++ b/drivers/hwmon/max6697.c
@@ -77,7 +77,7 @@
 };
 
 struct max6697_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
 
 	enum chips type;
 	const struct max6697_chip_data *chip;
@@ -181,8 +181,8 @@
 
 static struct max6697_data *max6697_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max6697_data *data = i2c_get_clientdata(client);
+	struct max6697_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	struct max6697_data *ret = data;
 	int val;
 	int i;
@@ -303,8 +303,7 @@
 {
 	int nr = to_sensor_dev_attr_2(devattr)->nr;
 	int index = to_sensor_dev_attr_2(devattr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max6697_data *data = i2c_get_clientdata(client);
+	struct max6697_data *data = dev_get_drvdata(dev);
 	long temp;
 	int ret;
 
@@ -316,7 +315,7 @@
 	temp = DIV_ROUND_CLOSEST(temp, 1000) + data->temp_offset;
 	temp = clamp_val(temp, 0, data->type == max6581 ? 255 : 127);
 	data->temp[nr][index] = temp;
-	ret = i2c_smbus_write_byte_data(client,
+	ret = i2c_smbus_write_byte_data(data->client,
 					index == 2 ? MAX6697_REG_MAX[nr]
 						   : MAX6697_REG_CRIT[nr],
 					temp);
@@ -405,8 +404,7 @@
 				  int index)
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct max6697_data *data = i2c_get_clientdata(client);
+	struct max6697_data *data = dev_get_drvdata(dev);
 	const struct max6697_chip_data *chip = data->chip;
 	int channel = index / 6;	/* channel number */
 	int nr = index % 6;		/* attribute index within channel */
@@ -489,6 +487,7 @@
 static const struct attribute_group max6697_group = {
 	.attrs = max6697_attributes, .is_visible = max6697_is_visible,
 };
+__ATTRIBUTE_GROUPS(max6697);
 
 static void max6697_get_config_of(struct device_node *node,
 				  struct max6697_platform_data *pdata)
@@ -525,9 +524,9 @@
 	}
 }
 
-static int max6697_init_chip(struct i2c_client *client)
+static int max6697_init_chip(struct max6697_data *data,
+			     struct i2c_client *client)
 {
-	struct max6697_data *data = i2c_get_clientdata(client);
 	struct max6697_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct max6697_platform_data p;
 	const struct max6697_chip_data *chip = data->chip;
@@ -625,6 +624,7 @@
 	struct i2c_adapter *adapter = client->adapter;
 	struct device *dev = &client->dev;
 	struct max6697_data *data;
+	struct device *hwmon_dev;
 	int err;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -636,39 +636,17 @@
 
 	data->type = id->driver_data;
 	data->chip = &max6697_chip_data[data->type];
-
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 
-	err = max6697_init_chip(client);
+	err = max6697_init_chip(data, client);
 	if (err)
 		return err;
 
-	err = sysfs_create_group(&client->dev.kobj, &max6697_group);
-	if (err)
-		return err;
-
-	data->hwmon_dev = hwmon_device_register(dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto error;
-	}
-
-	return 0;
-
-error:
-	sysfs_remove_group(&client->dev.kobj, &max6697_group);
-	return err;
-}
-
-static int max6697_remove(struct i2c_client *client)
-{
-	struct max6697_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &max6697_group);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data,
+							   max6697_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 static const struct i2c_device_id max6697_id[] = {
@@ -692,7 +670,6 @@
 		.name	= "max6697",
 	},
 	.probe = max6697_probe,
-	.remove	= max6697_remove,
 	.id_table = max6697_id,
 };
 
diff --git a/drivers/hwmon/mc13783-adc.c b/drivers/hwmon/mc13783-adc.c
index 982d862..ae00e60 100644
--- a/drivers/hwmon/mc13783-adc.c
+++ b/drivers/hwmon/mc13783-adc.c
@@ -37,7 +37,7 @@
 struct mc13783_adc_priv {
 	struct mc13xxx *mc13xxx;
 	struct device *hwmon_dev;
-	char name[10];
+	char name[PLATFORM_NAME_SIZE];
 };
 
 static ssize_t mc13783_adc_show_name(struct device *dev, struct device_attribute
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c
index 6eb03ce..d17325d 100644
--- a/drivers/hwmon/nct6775.c
+++ b/drivers/hwmon/nct6775.c
@@ -724,11 +724,8 @@
 	enum kinds kind;
 	const char *name;
 
-	struct device *hwmon_dev;
-	struct attribute_group *group_in;
-	struct attribute_group *group_fan;
-	struct attribute_group *group_temp;
-	struct attribute_group *group_pwm;
+	int num_attr_groups;
+	const struct attribute_group *groups[6];
 
 	u16 reg_temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
 				    * 3=temp_crit, 4=temp_lcrit
@@ -942,7 +939,7 @@
 	struct sensor_device_attribute_2 *a2;
 	struct attribute **attrs;
 	struct sensor_device_template **t;
-	int err, i, j, count;
+	int i, count;
 
 	if (repeat <= 0)
 		return ERR_PTR(-EINVAL);
@@ -973,7 +970,7 @@
 
 	for (i = 0; i < repeat; i++) {
 		t = tg->templates;
-		for (j = 0; *t != NULL; j++) {
+		while (*t != NULL) {
 			snprintf(su->name, sizeof(su->name),
 				 (*t)->dev_attr.attr.name, tg->base + i);
 			if ((*t)->s2) {
@@ -1002,10 +999,6 @@
 		}
 	}
 
-	err = sysfs_create_group(&dev->kobj, group);
-	if (err)
-		return ERR_PTR(-ENOMEM);
-
 	return group;
 }
 
@@ -1457,7 +1450,8 @@
 					  = nct6775_read_temp(data,
 						data->reg_temp[j][i]);
 			}
-			if (!(data->have_temp_fixed & (1 << i)))
+			if (i >= NUM_TEMP_FIXED ||
+			    !(data->have_temp_fixed & (1 << i)))
 				continue;
 			data->temp_offset[i]
 			  = nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
@@ -1545,7 +1539,7 @@
 		if (src == source)
 			return nr;
 	}
-	return -1;
+	return -ENODEV;
 }
 
 static ssize_t
@@ -1644,7 +1638,7 @@
 
 	nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
 	if (nr < 0)
-		return -ENODEV;
+		return nr;
 
 	bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
 	regindex = bit >> 3;
@@ -2726,16 +2720,6 @@
 }
 
 static ssize_t
-show_name(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct nct6775_data *data = dev_get_drvdata(dev);
-
-	return sprintf(buf, "%s\n", data->name);
-}
-
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-
-static ssize_t
 show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct nct6775_data *data = nct6775_update_device(dev);
@@ -3061,16 +3045,16 @@
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct nct6775_data *data = dev_get_drvdata(dev);
 
-	if (index == 1 && !data->have_vid)
+	if (index == 0 && !data->have_vid)
 		return 0;
 
-	if (index == 2 || index == 3) {
-		if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 2] < 0)
+	if (index == 1 || index == 2) {
+		if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 1] < 0)
 			return 0;
 	}
 
-	if (index == 4 || index == 5) {
-		if (data->BEEP_BITS[INTRUSION_ALARM_BASE + index - 4] < 0)
+	if (index == 3 || index == 4) {
+		if (data->BEEP_BITS[INTRUSION_ALARM_BASE + index - 3] < 0)
 			return 0;
 	}
 
@@ -3083,13 +3067,12 @@
  * Any change in order or content must be matched.
  */
 static struct attribute *nct6775_attributes_other[] = {
-	&dev_attr_name.attr,
-	&dev_attr_cpu0_vid.attr,				/* 1 */
-	&sensor_dev_attr_intrusion0_alarm.dev_attr.attr,	/* 2 */
-	&sensor_dev_attr_intrusion1_alarm.dev_attr.attr,	/* 3 */
-	&sensor_dev_attr_intrusion0_beep.dev_attr.attr,		/* 4 */
-	&sensor_dev_attr_intrusion1_beep.dev_attr.attr,		/* 5 */
-	&sensor_dev_attr_beep_enable.dev_attr.attr,		/* 6 */
+	&dev_attr_cpu0_vid.attr,				/* 0 */
+	&sensor_dev_attr_intrusion0_alarm.dev_attr.attr,	/* 1 */
+	&sensor_dev_attr_intrusion1_alarm.dev_attr.attr,	/* 2 */
+	&sensor_dev_attr_intrusion0_beep.dev_attr.attr,		/* 3 */
+	&sensor_dev_attr_intrusion1_beep.dev_attr.attr,		/* 4 */
+	&sensor_dev_attr_beep_enable.dev_attr.attr,		/* 5 */
 
 	NULL
 };
@@ -3099,27 +3082,6 @@
 	.is_visible = nct6775_other_is_visible,
 };
 
-/*
- * Driver and device management
- */
-
-static void nct6775_device_remove_files(struct device *dev)
-{
-	struct nct6775_data *data = dev_get_drvdata(dev);
-
-	if (data->group_pwm)
-		sysfs_remove_group(&dev->kobj, data->group_pwm);
-	if (data->group_in)
-		sysfs_remove_group(&dev->kobj, data->group_in);
-	if (data->group_fan)
-		sysfs_remove_group(&dev->kobj, data->group_fan);
-	if (data->group_temp)
-		sysfs_remove_group(&dev->kobj, data->group_temp);
-
-	sysfs_remove_group(&dev->kobj, &nct6775_group_other);
-}
-
-/* Get the monitoring functions started */
 static inline void nct6775_init_device(struct nct6775_data *data)
 {
 	int i;
@@ -3296,6 +3258,7 @@
 	int num_reg_temp;
 	u8 cr2a;
 	struct attribute_group *group;
+	struct device *hwmon_dev;
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 	if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
@@ -3870,61 +3833,36 @@
 	/* Register sysfs hooks */
 	group = nct6775_create_attr_group(dev, &nct6775_pwm_template_group,
 					  data->pwm_num);
-	if (IS_ERR(group)) {
-		err = PTR_ERR(group);
-		goto exit_remove;
-	}
-	data->group_pwm = group;
+	if (IS_ERR(group))
+		return PTR_ERR(group);
+
+	data->groups[data->num_attr_groups++] = group;
 
 	group = nct6775_create_attr_group(dev, &nct6775_in_template_group,
 					  fls(data->have_in));
-	if (IS_ERR(group)) {
-		err = PTR_ERR(group);
-		goto exit_remove;
-	}
-	data->group_in = group;
+	if (IS_ERR(group))
+		return PTR_ERR(group);
+
+	data->groups[data->num_attr_groups++] = group;
 
 	group = nct6775_create_attr_group(dev, &nct6775_fan_template_group,
 					  fls(data->has_fan));
-	if (IS_ERR(group)) {
-		err = PTR_ERR(group);
-		goto exit_remove;
-	}
-	data->group_fan = group;
+	if (IS_ERR(group))
+		return PTR_ERR(group);
+
+	data->groups[data->num_attr_groups++] = group;
 
 	group = nct6775_create_attr_group(dev, &nct6775_temp_template_group,
 					  fls(data->have_temp));
-	if (IS_ERR(group)) {
-		err = PTR_ERR(group);
-		goto exit_remove;
-	}
-	data->group_temp = group;
+	if (IS_ERR(group))
+		return PTR_ERR(group);
 
-	err = sysfs_create_group(&dev->kobj, &nct6775_group_other);
-	if (err)
-		goto exit_remove;
+	data->groups[data->num_attr_groups++] = group;
+	data->groups[data->num_attr_groups++] = &nct6775_group_other;
 
-	data->hwmon_dev = hwmon_device_register(dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove;
-	}
-
-	return 0;
-
-exit_remove:
-	nct6775_device_remove_files(dev);
-	return err;
-}
-
-static int nct6775_remove(struct platform_device *pdev)
-{
-	struct nct6775_data *data = platform_get_drvdata(pdev);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	nct6775_device_remove_files(&pdev->dev);
-
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, data->name,
+							   data, data->groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 #ifdef CONFIG_PM
@@ -4013,7 +3951,6 @@
 		.pm	= NCT6775_DEV_PM_OPS,
 	},
 	.probe		= nct6775_probe,
-	.remove		= nct6775_remove,
 };
 
 static const char * const nct6775_sio_names[] __initconst = {
@@ -4101,7 +4038,7 @@
 /*
  * when Super-I/O functions move to a separate file, the Super-I/O
  * bus will manage the lifetime of the device and this module will only keep
- * track of the nct6775 driver. But since we platform_device_alloc(), we
+ * track of the nct6775 driver. But since we use platform_device_alloc(), we
  * must keep track of the device
  */
 static struct platform_device *pdev[2];
diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c
index 6a9d6ed..a26b1d1 100644
--- a/drivers/hwmon/pmbus/lm25066.c
+++ b/drivers/hwmon/pmbus/lm25066.c
@@ -1,5 +1,5 @@
 /*
- * Hardware monitoring driver for LM25056 / LM25066 / LM5064 / LM5066
+ * Hardware monitoring driver for LM25056 / LM25063 / LM25066 / LM5064 / LM5066
  *
  * Copyright (c) 2011 Ericsson AB.
  * Copyright (c) 2013 Guenter Roeck
@@ -27,7 +27,7 @@
 #include <linux/i2c.h>
 #include "pmbus.h"
 
-enum chips { lm25056, lm25066, lm5064, lm5066 };
+enum chips { lm25056, lm25063, lm25066, lm5064, lm5066 };
 
 #define LM25066_READ_VAUX		0xd0
 #define LM25066_MFR_READ_IIN		0xd1
@@ -52,6 +52,11 @@
 #define LM25056_MFR_STS_VAUX_OV_WARN	(1 << 1)
 #define LM25056_MFR_STS_VAUX_UV_WARN	(1 << 0)
 
+/* LM25063 only */
+
+#define LM25063_READ_VOUT_MAX		0xe5
+#define LM25063_READ_VOUT_MIN		0xe6
+
 struct __coeff {
 	short m, b, R;
 };
@@ -59,7 +64,7 @@
 #define PSC_CURRENT_IN_L	(PSC_NUM_CLASSES)
 #define PSC_POWER_L		(PSC_NUM_CLASSES + 1)
 
-static struct __coeff lm25066_coeff[4][PSC_NUM_CLASSES + 2] = {
+static struct __coeff lm25066_coeff[5][PSC_NUM_CLASSES + 2] = {
 	[lm25056] = {
 		[PSC_VOLTAGE_IN] = {
 			.m = 16296,
@@ -116,6 +121,36 @@
 			.m = 16,
 		},
 	},
+	[lm25063] = {
+		[PSC_VOLTAGE_IN] = {
+			.m = 16000,
+			.R = -2,
+		},
+		[PSC_VOLTAGE_OUT] = {
+			.m = 16000,
+			.R = -2,
+		},
+		[PSC_CURRENT_IN] = {
+			.m = 10000,
+			.R = -2,
+		},
+		[PSC_CURRENT_IN_L] = {
+			.m = 10000,
+			.R = -2,
+		},
+		[PSC_POWER] = {
+			.m = 5000,
+			.R = -3,
+		},
+		[PSC_POWER_L] = {
+			.m = 5000,
+			.R = -3,
+		},
+		[PSC_TEMPERATURE] = {
+			.m = 15596,
+			.R = -3,
+		},
+	},
 	[lm5064] = {
 		[PSC_VOLTAGE_IN] = {
 			.m = 4611,
@@ -178,6 +213,7 @@
 
 struct lm25066_data {
 	int id;
+	u16 rlimit;			/* Maximum register value */
 	struct pmbus_driver_info info;
 };
 
@@ -200,6 +236,10 @@
 			/* VIN: 6.14 mV VAUX: 293 uV LSB */
 			ret = DIV_ROUND_CLOSEST(ret * 293, 6140);
 			break;
+		case lm25063:
+			/* VIN: 6.25 mV VAUX: 200.0 uV LSB */
+			ret = DIV_ROUND_CLOSEST(ret * 20, 625);
+			break;
 		case lm25066:
 			/* VIN: 4.54 mV VAUX: 283.2 uV LSB */
 			ret = DIV_ROUND_CLOSEST(ret * 2832, 45400);
@@ -253,6 +293,24 @@
 	return ret;
 }
 
+static int lm25063_read_word_data(struct i2c_client *client, int page, int reg)
+{
+	int ret;
+
+	switch (reg) {
+	case PMBUS_VIRT_READ_VOUT_MAX:
+		ret = pmbus_read_word_data(client, 0, LM25063_READ_VOUT_MAX);
+		break;
+	case PMBUS_VIRT_READ_VOUT_MIN:
+		ret = pmbus_read_word_data(client, 0, LM25063_READ_VOUT_MIN);
+		break;
+	default:
+		ret = lm25066_read_word_data(client, page, reg);
+		break;
+	}
+	return ret;
+}
+
 static int lm25056_read_word_data(struct i2c_client *client, int page, int reg)
 {
 	int ret;
@@ -308,27 +366,34 @@
 static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
 				   u16 word)
 {
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	const struct lm25066_data *data = to_lm25066_data(info);
 	int ret;
 
 	switch (reg) {
+	case PMBUS_POUT_OP_FAULT_LIMIT:
+	case PMBUS_POUT_OP_WARN_LIMIT:
 	case PMBUS_VOUT_UV_WARN_LIMIT:
 	case PMBUS_OT_FAULT_LIMIT:
 	case PMBUS_OT_WARN_LIMIT:
+	case PMBUS_IIN_OC_FAULT_LIMIT:
 	case PMBUS_VIN_UV_WARN_LIMIT:
+	case PMBUS_VIN_UV_FAULT_LIMIT:
+	case PMBUS_VIN_OV_FAULT_LIMIT:
 	case PMBUS_VIN_OV_WARN_LIMIT:
-		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
+		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
 		ret = pmbus_write_word_data(client, 0, reg, word);
 		pmbus_clear_cache(client);
 		break;
 	case PMBUS_IIN_OC_WARN_LIMIT:
-		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
+		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
 		ret = pmbus_write_word_data(client, 0,
 					    LM25066_MFR_IIN_OC_WARN_LIMIT,
 					    word);
 		pmbus_clear_cache(client);
 		break;
 	case PMBUS_PIN_OP_WARN_LIMIT:
-		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
+		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
 		ret = pmbus_write_word_data(client, 0,
 					    LM25066_MFR_PIN_OP_WARN_LIMIT,
 					    word);
@@ -337,7 +402,7 @@
 	case PMBUS_VIRT_VMON_UV_WARN_LIMIT:
 		/* Adjust from VIN coefficients (for LM25056) */
 		word = DIV_ROUND_CLOSEST((int)word * 6140, 293);
-		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
+		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
 		ret = pmbus_write_word_data(client, 0,
 					    LM25056_VAUX_UV_WARN_LIMIT, word);
 		pmbus_clear_cache(client);
@@ -345,7 +410,7 @@
 	case PMBUS_VIRT_VMON_OV_WARN_LIMIT:
 		/* Adjust from VIN coefficients (for LM25056) */
 		word = DIV_ROUND_CLOSEST((int)word * 6140, 293);
-		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff);
+		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);
 		ret = pmbus_write_word_data(client, 0,
 					    LM25056_VAUX_OV_WARN_LIMIT, word);
 		pmbus_clear_cache(client);
@@ -399,9 +464,16 @@
 		info->func[0] |= PMBUS_HAVE_STATUS_VMON;
 		info->read_word_data = lm25056_read_word_data;
 		info->read_byte_data = lm25056_read_byte_data;
+		data->rlimit = 0x0fff;
+	} else if (data->id == lm25063) {
+		info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_POUT;
+		info->read_word_data = lm25063_read_word_data;
+		data->rlimit = 0xffff;
 	} else {
 		info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
 		info->read_word_data = lm25066_read_word_data;
+		data->rlimit = 0x0fff;
 	}
 	info->write_word_data = lm25066_write_word_data;
 
@@ -432,6 +504,7 @@
 
 static const struct i2c_device_id lm25066_id[] = {
 	{"lm25056", lm25056},
+	{"lm25063", lm25063},
 	{"lm25066", lm25066},
 	{"lm5064", lm5064},
 	{"lm5066", lm5066},
@@ -453,5 +526,5 @@
 module_i2c_driver(lm25066_driver);
 
 MODULE_AUTHOR("Guenter Roeck");
-MODULE_DESCRIPTION("PMBus driver for LM25056/LM25066/LM5064/LM5066");
+MODULE_DESCRIPTION("PMBus driver for LM25066 and compatible chips");
 MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c
index 586a89e..de3c152 100644
--- a/drivers/hwmon/pmbus/ltc2978.c
+++ b/drivers/hwmon/pmbus/ltc2978.c
@@ -1,5 +1,6 @@
 /*
- * Hardware monitoring driver for LTC2974, LTC2978, LTC3880, and LTC3883
+ * Hardware monitoring driver for LTC2974, LTC2977, LTC2978, LTC3880,
+ * and LTC3883
  *
  * Copyright (c) 2011 Ericsson AB.
  * Copyright (c) 2013 Guenter Roeck
@@ -27,7 +28,7 @@
 #include <linux/i2c.h>
 #include "pmbus.h"
 
-enum chips { ltc2974, ltc2978, ltc3880, ltc3883 };
+enum chips { ltc2974, ltc2977, ltc2978, ltc3880, ltc3883 };
 
 /* Common for all chips */
 #define LTC2978_MFR_VOUT_PEAK		0xdd
@@ -35,7 +36,7 @@
 #define LTC2978_MFR_TEMPERATURE_PEAK	0xdf
 #define LTC2978_MFR_SPECIAL_ID		0xe7
 
-/* LTC2974 and LTC2978 */
+/* LTC2974, LCT2977, and LTC2978 */
 #define LTC2978_MFR_VOUT_MIN		0xfb
 #define LTC2978_MFR_VIN_MIN		0xfc
 #define LTC2978_MFR_TEMPERATURE_MIN	0xfd
@@ -53,8 +54,10 @@
 #define LTC3883_MFR_IIN_PEAK		0xe1
 
 #define LTC2974_ID			0x0212
+#define LTC2977_ID			0x0130
 #define LTC2978_ID_REV1			0x0121
 #define LTC2978_ID_REV2			0x0122
+#define LTC2978A_ID			0x0124
 #define LTC3880_ID			0x4000
 #define LTC3880_ID_MASK			0xff00
 #define LTC3883_ID			0x4300
@@ -363,6 +366,7 @@
 
 static const struct i2c_device_id ltc2978_id[] = {
 	{"ltc2974", ltc2974},
+	{"ltc2977", ltc2977},
 	{"ltc2978", ltc2978},
 	{"ltc3880", ltc3880},
 	{"ltc3883", ltc3883},
@@ -392,7 +396,10 @@
 
 	if (chip_id == LTC2974_ID) {
 		data->id = ltc2974;
-	} else if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2) {
+	} else if (chip_id == LTC2977_ID) {
+		data->id = ltc2977;
+	} else if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2 ||
+		   chip_id == LTC2978A_ID) {
 		data->id = ltc2978;
 	} else if ((chip_id & LTC3880_ID_MASK) == LTC3880_ID) {
 		data->id = ltc3880;
@@ -438,6 +445,7 @@
 			  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
 		}
 		break;
+	case ltc2977:
 	case ltc2978:
 		info->read_word_data = ltc2978_read_word_data;
 		info->pages = LTC2978_NUM_PAGES;
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 9319fcf..3cbf66e 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -97,6 +97,7 @@
 	int max_attributes;
 	int num_attributes;
 	struct attribute_group group;
+	const struct attribute_group *groups[2];
 
 	struct pmbus_sensor *sensors;
 
@@ -156,7 +157,7 @@
 
 /*
  * _pmbus_write_byte() is similar to pmbus_write_byte(), but checks if
- * a device specific mapping funcion exists and calls it if necessary.
+ * a device specific mapping function exists and calls it if necessary.
  */
 static int _pmbus_write_byte(struct i2c_client *client, int page, u8 value)
 {
@@ -348,7 +349,7 @@
 
 static struct pmbus_data *pmbus_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_client *client = to_i2c_client(dev->parent);
 	struct pmbus_data *data = i2c_get_clientdata(client);
 	const struct pmbus_driver_info *info = data->info;
 	struct pmbus_sensor *sensor;
@@ -686,7 +687,7 @@
 	if (!s1 && !s2) {
 		ret = !!regval;
 	} else if (!s1 || !s2) {
-		BUG();
+		WARN(1, "Bad boolean descriptor %p: s1=%p, s2=%p\n", b, s1, s2);
 		return 0;
 	} else {
 		long v1, v2;
@@ -733,7 +734,7 @@
 				struct device_attribute *devattr,
 				const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_client *client = to_i2c_client(dev->parent);
 	struct pmbus_data *data = i2c_get_clientdata(client);
 	struct pmbus_sensor *sensor = to_pmbus_sensor(devattr);
 	ssize_t rv = count;
@@ -1768,22 +1769,16 @@
 		goto out_kfree;
 	}
 
-	/* Register sysfs hooks */
-	ret = sysfs_create_group(&dev->kobj, &data->group);
-	if (ret) {
-		dev_err(dev, "Failed to create sysfs entries\n");
-		goto out_kfree;
-	}
-	data->hwmon_dev = hwmon_device_register(dev);
+	data->groups[0] = &data->group;
+	data->hwmon_dev = hwmon_device_register_with_groups(dev, client->name,
+							    data, data->groups);
 	if (IS_ERR(data->hwmon_dev)) {
 		ret = PTR_ERR(data->hwmon_dev);
 		dev_err(dev, "Failed to register hwmon device\n");
-		goto out_hwmon_device_register;
+		goto out_kfree;
 	}
 	return 0;
 
-out_hwmon_device_register:
-	sysfs_remove_group(&dev->kobj, &data->group);
 out_kfree:
 	kfree(data->group.attrs);
 	return ret;
@@ -1794,7 +1789,6 @@
 {
 	struct pmbus_data *data = i2c_get_clientdata(client);
 	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &data->group);
 	kfree(data->group.attrs);
 	return 0;
 }
diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c
index dfe6d95..7fa6e7d 100644
--- a/drivers/hwmon/tmp401.c
+++ b/drivers/hwmon/tmp401.c
@@ -155,7 +155,8 @@
  */
 
 struct tmp401_data {
-	struct device *hwmon_dev;
+	struct i2c_client *client;
+	const struct attribute_group *groups[3];
 	struct mutex update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* in jiffies */
@@ -231,8 +232,8 @@
 
 static struct tmp401_data *tmp401_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct tmp401_data *data = i2c_get_clientdata(client);
+	struct tmp401_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	struct tmp401_data *ret = data;
 	int i, val;
 	unsigned long next_update;
@@ -350,15 +351,12 @@
 {
 	int nr = to_sensor_dev_attr_2(devattr)->nr;
 	int index = to_sensor_dev_attr_2(devattr)->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct tmp401_data *data = tmp401_update_device(dev);
+	struct tmp401_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 	u16 reg;
 	u8 regaddr;
 
-	if (IS_ERR(data))
-		return PTR_ERR(data);
-
 	if (kstrtol(buf, 10, &val))
 		return -EINVAL;
 
@@ -405,7 +403,7 @@
 	val = clamp_val(val, temp - 255000, temp);
 	reg = ((temp - val) + 500) / 1000;
 
-	i2c_smbus_write_byte_data(to_i2c_client(dev), TMP401_TEMP_CRIT_HYST,
+	i2c_smbus_write_byte_data(data->client, TMP401_TEMP_CRIT_HYST,
 				  reg);
 
 	data->temp_crit_hyst = reg;
@@ -423,8 +421,8 @@
 static ssize_t reset_temp_history(struct device *dev,
 	struct device_attribute	*devattr, const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct tmp401_data *data = i2c_get_clientdata(client);
+	struct tmp401_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	long val;
 
 	if (kstrtol(buf, 10, &val))
@@ -447,8 +445,7 @@
 static ssize_t show_update_interval(struct device *dev,
 				    struct device_attribute *attr, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct tmp401_data *data = i2c_get_clientdata(client);
+	struct tmp401_data *data = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%u\n", data->update_interval);
 }
@@ -457,8 +454,8 @@
 				   struct device_attribute *attr,
 				   const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct tmp401_data *data = i2c_get_clientdata(client);
+	struct tmp401_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
 	unsigned long val;
 	int err, rate;
 
@@ -616,10 +613,10 @@
  * Begin non sysfs callback code (aka Real code)
  */
 
-static void tmp401_init_client(struct i2c_client *client)
+static void tmp401_init_client(struct tmp401_data *data,
+			       struct i2c_client *client)
 {
 	int config, config_orig;
-	struct tmp401_data *data = i2c_get_clientdata(client);
 
 	/* Set the conversion rate to 2 Hz */
 	i2c_smbus_write_byte_data(client, TMP401_CONVERSION_RATE_WRITE, 5);
@@ -705,77 +702,45 @@
 	return 0;
 }
 
-static int tmp401_remove(struct i2c_client *client)
-{
-	struct device *dev = &client->dev;
-	struct tmp401_data *data = i2c_get_clientdata(client);
-
-	if (data->hwmon_dev)
-		hwmon_device_unregister(data->hwmon_dev);
-
-	sysfs_remove_group(&dev->kobj, &tmp401_group);
-
-	if (data->kind == tmp411)
-		sysfs_remove_group(&dev->kobj, &tmp411_group);
-
-	if (data->kind == tmp432)
-		sysfs_remove_group(&dev->kobj, &tmp432_group);
-
-	return 0;
-}
-
 static int tmp401_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
-	struct device *dev = &client->dev;
-	int err;
-	struct tmp401_data *data;
 	const char *names[] = { "TMP401", "TMP411", "TMP431", "TMP432" };
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
+	struct tmp401_data *data;
+	int groups = 0;
 
 	data = devm_kzalloc(dev, sizeof(struct tmp401_data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	i2c_set_clientdata(client, data);
+	data->client = client;
 	mutex_init(&data->update_lock);
 	data->kind = id->driver_data;
 
 	/* Initialize the TMP401 chip */
-	tmp401_init_client(client);
+	tmp401_init_client(data, client);
 
 	/* Register sysfs hooks */
-	err = sysfs_create_group(&dev->kobj, &tmp401_group);
-	if (err)
-		return err;
+	data->groups[groups++] = &tmp401_group;
 
 	/* Register additional tmp411 sysfs hooks */
-	if (data->kind == tmp411) {
-		err = sysfs_create_group(&dev->kobj, &tmp411_group);
-		if (err)
-			goto exit_remove;
-	}
+	if (data->kind == tmp411)
+		data->groups[groups++] = &tmp411_group;
 
 	/* Register additional tmp432 sysfs hooks */
-	if (data->kind == tmp432) {
-		err = sysfs_create_group(&dev->kobj, &tmp432_group);
-		if (err)
-			goto exit_remove;
-	}
+	if (data->kind == tmp432)
+		data->groups[groups++] = &tmp432_group;
 
-	data->hwmon_dev = hwmon_device_register(dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		data->hwmon_dev = NULL;
-		goto exit_remove;
-	}
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
+							   data, data->groups);
+	if (IS_ERR(hwmon_dev))
+		return PTR_ERR(hwmon_dev);
 
 	dev_info(dev, "Detected TI %s chip\n", names[data->kind]);
 
 	return 0;
-
-exit_remove:
-	tmp401_remove(client);
-	return err;
 }
 
 static struct i2c_driver tmp401_driver = {
@@ -784,7 +749,6 @@
 		.name	= "tmp401",
 	},
 	.probe		= tmp401_probe,
-	.remove		= tmp401_remove,
 	.id_table	= tmp401_id,
 	.detect		= tmp401_detect,
 	.address_list	= normal_i2c,
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index a3feee3..bdcf2dc 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -1043,7 +1043,7 @@
 	SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13),
 };
 
-/* get reatime status of all sensors items: voltage, temp, fan */
+/* get realtime status of all sensors items: voltage, temp, fan */
 static ssize_t show_alarms_reg(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index 5febb43..df58580 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -579,7 +579,7 @@
 	return count;
 }
 
-/* get reatime status of all sensors items: voltage, temp, fan */
+/* get realtime status of all sensors items: voltage, temp, fan */
 static ssize_t
 show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
index b0c30a5..9d63d71 100644
--- a/drivers/hwmon/w83793.c
+++ b/drivers/hwmon/w83793.c
@@ -808,7 +808,7 @@
 	if (nr == TEMP_FAN_MAP) {
 		val = data->temp_fan_map[index];
 	} else if (nr == TEMP_PWM_ENABLE) {
-		/* +2 to transfrom into 2 and 3 to conform with sysfs intf */
+		/* +2 to transform into 2 and 3 to conform with sysfs intf */
 		val = ((data->pwm_enable >> index) & 0x01) + 2;
 	} else if (nr == TEMP_CRUISE) {
 		val = TEMP_FROM_REG(data->temp_cruise[index] & 0x7f);
@@ -1199,7 +1199,8 @@
 
 static int watchdog_set_timeout(struct w83793_data *data, int timeout)
 {
-	int ret, mtimeout;
+	unsigned int mtimeout;
+	int ret;
 
 	mtimeout = DIV_ROUND_UP(timeout, 60);
 
diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
index b2b8aa9..3e5ea2c 100644
--- a/drivers/i2c/busses/i2c-cpm.c
+++ b/drivers/i2c/busses/i2c-cpm.c
@@ -447,7 +447,7 @@
 
 	init_waitqueue_head(&cpm->i2c_wait);
 
-	cpm->irq = of_irq_to_resource(ofdev->dev.of_node, 0, NULL);
+	cpm->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
 	if (!cpm->irq)
 		return -EINVAL;
 
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 4c1b605..0aa0113 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -270,7 +270,8 @@
 MODULE_ALIAS("platform:i2c_designware");
 
 static struct platform_driver dw_i2c_driver = {
-	.remove		= dw_i2c_remove,
+	.probe = dw_i2c_probe,
+	.remove = dw_i2c_remove,
 	.driver		= {
 		.name	= "i2c_designware",
 		.owner	= THIS_MODULE,
@@ -282,7 +283,7 @@
 
 static int __init dw_i2c_init_driver(void)
 {
-	return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe);
+	return platform_driver_register(&dw_i2c_driver);
 }
 subsys_initcall(dw_i2c_init_driver);
 
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index ff3caa0..f744410 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -41,6 +41,8 @@
 #include <asm/irq.h>
 #include <linux/io.h>
 #include <linux/i2c.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
 #include "i2c-ibm_iic.h"
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index ccf4665..1d7efa3 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -365,7 +365,7 @@
 	clk_disable_unprepare(i2c_imx->clk);
 }
 
-static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
+static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
 							unsigned int rate)
 {
 	struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div;
@@ -589,7 +589,7 @@
 	.functionality	= i2c_imx_func,
 };
 
-static int __init i2c_imx_probe(struct platform_device *pdev)
+static int i2c_imx_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *of_id = of_match_device(i2c_imx_dt_ids,
 							   &pdev->dev);
@@ -697,7 +697,7 @@
 	return 0;   /* Return OK */
 }
 
-static int __exit i2c_imx_remove(struct platform_device *pdev)
+static int i2c_imx_remove(struct platform_device *pdev)
 {
 	struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev);
 
@@ -715,7 +715,8 @@
 }
 
 static struct platform_driver i2c_imx_driver = {
-	.remove		= __exit_p(i2c_imx_remove),
+	.probe = i2c_imx_probe,
+	.remove = i2c_imx_remove,
 	.driver	= {
 		.name	= DRIVER_NAME,
 		.owner	= THIS_MODULE,
@@ -726,7 +727,7 @@
 
 static int __init i2c_adap_imx_init(void)
 {
-	return platform_driver_probe(&i2c_imx_driver, i2c_imx_probe);
+	return platform_driver_register(&i2c_imx_driver);
 }
 subsys_initcall(i2c_adap_imx_init);
 
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index b80c768..b6a741c 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -17,6 +17,8 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/init.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/slab.h>
 
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index f4a0167..b7c8577 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -780,12 +780,13 @@
 		   .owner = THIS_MODULE,
 		   .of_match_table = mxs_i2c_dt_ids,
 		   },
+	.probe = mxs_i2c_probe,
 	.remove = mxs_i2c_remove,
 };
 
 static int __init mxs_i2c_init(void)
 {
-	return platform_driver_probe(&mxs_i2c_driver, mxs_i2c_probe);
+	return platform_driver_register(&mxs_i2c_driver);
 }
 subsys_initcall(mxs_i2c_init);
 
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 6d8308d..9967a6f 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -939,6 +939,9 @@
 		/*
 		 * ProDB0017052: Clear ARDY bit twice
 		 */
+		if (stat & OMAP_I2C_STAT_ARDY)
+			omap_i2c_ack_stat(dev, OMAP_I2C_STAT_ARDY);
+
 		if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK |
 					OMAP_I2C_STAT_AL)) {
 			omap_i2c_ack_stat(dev, (OMAP_I2C_STAT_RRDY |
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index 37e8cfa..8c87f4a 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
+#include <linux/of_irq.h>
 #include <asm/prom.h>
 #include <asm/pmac_low_i2c.h>
 
diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c
index f8f6f2e..04a17b9 100644
--- a/drivers/i2c/busses/i2c-stu300.c
+++ b/drivers/i2c/busses/i2c-stu300.c
@@ -859,8 +859,7 @@
 	.functionality	= stu300_func,
 };
 
-static int __init
-stu300_probe(struct platform_device *pdev)
+static int stu300_probe(struct platform_device *pdev)
 {
 	struct stu300_dev *dev;
 	struct i2c_adapter *adap;
@@ -966,8 +965,7 @@
 #define STU300_I2C_PM	NULL
 #endif
 
-static int __exit
-stu300_remove(struct platform_device *pdev)
+static int stu300_remove(struct platform_device *pdev)
 {
 	struct stu300_dev *dev = platform_get_drvdata(pdev);
 
@@ -989,13 +987,14 @@
 		.pm	= STU300_I2C_PM,
 		.of_match_table = stu300_dt_match,
 	},
-	.remove		= __exit_p(stu300_remove),
+	.probe = stu300_probe,
+	.remove = stu300_remove,
 
 };
 
 static int __init stu300_init(void)
 {
-	return platform_driver_probe(&stu300_i2c_driver, stu300_probe);
+	return platform_driver_register(&stu300_i2c_driver);
 }
 
 static void __exit stu300_exit(void)
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 29d3f04..3be58f8 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1134,6 +1134,9 @@
 	acpi_handle handle;
 	acpi_status status;
 
+	if (!adap->dev.parent)
+		return;
+
 	handle = ACPI_HANDLE(adap->dev.parent);
 	if (!handle)
 		return;
diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
index 74b41ae..928656e 100644
--- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
+++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
@@ -200,7 +200,7 @@
 	arb->parent = of_find_i2c_adapter_by_node(parent_np);
 	if (!arb->parent) {
 		dev_err(dev, "Cannot find parent bus\n");
-		return -EINVAL;
+		return -EPROBE_DEFER;
 	}
 
 	/* Actually add the mux adapter */
diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
index 5d4a99b..a764da7 100644
--- a/drivers/i2c/muxes/i2c-mux-gpio.c
+++ b/drivers/i2c/muxes/i2c-mux-gpio.c
@@ -66,7 +66,7 @@
 	struct device_node *adapter_np, *child;
 	struct i2c_adapter *adapter;
 	unsigned *values, *gpios;
-	int i = 0;
+	int i = 0, ret;
 
 	if (!np)
 		return -ENODEV;
@@ -79,7 +79,7 @@
 	adapter = of_find_i2c_adapter_by_node(adapter_np);
 	if (!adapter) {
 		dev_err(&pdev->dev, "Cannot find parent bus\n");
-		return -ENODEV;
+		return -EPROBE_DEFER;
 	}
 	mux->data.parent = i2c_adapter_id(adapter);
 	put_device(&adapter->dev);
@@ -116,8 +116,12 @@
 		return -ENOMEM;
 	}
 
-	for (i = 0; i < mux->data.n_gpios; i++)
-		gpios[i] = of_get_named_gpio(np, "mux-gpios", i);
+	for (i = 0; i < mux->data.n_gpios; i++) {
+		ret = of_get_named_gpio(np, "mux-gpios", i);
+		if (ret < 0)
+			return ret;
+		gpios[i] = ret;
+	}
 
 	mux->data.gpios = gpios;
 
@@ -177,7 +181,7 @@
 	if (!parent) {
 		dev_err(&pdev->dev, "Parent adapter (%d) not found\n",
 			mux->data.parent);
-		return -ENODEV;
+		return -EPROBE_DEFER;
 	}
 
 	mux->parent = parent;
diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c
index 69a9173..68a3715 100644
--- a/drivers/i2c/muxes/i2c-mux-pinctrl.c
+++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c
@@ -113,7 +113,7 @@
 	adapter = of_find_i2c_adapter_by_node(adapter_np);
 	if (!adapter) {
 		dev_err(mux->dev, "Cannot find parent bus\n");
-		return -ENODEV;
+		return -EPROBE_DEFER;
 	}
 	mux->pdata->parent_bus_num = i2c_adapter_id(adapter);
 	put_device(&adapter->dev);
@@ -211,7 +211,7 @@
 	if (!mux->parent) {
 		dev_err(&pdev->dev, "Parent adapter (%d) not found\n",
 			mux->pdata->parent_bus_num);
-		ret = -ENODEV;
+		ret = -EPROBE_DEFER;
 		goto err;
 	}
 
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 02906ca..8fb46aa 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -197,8 +197,8 @@
 
 config IDE_GENERIC
 	tristate "generic/default IDE chipset support"
-	depends on ALPHA || X86 || IA64 || M32R || MIPS || ARCH_RPC || ARCH_SHARK
-	default ARM && (ARCH_RPC || ARCH_SHARK)
+	depends on ALPHA || X86 || IA64 || M32R || MIPS || ARCH_RPC
+	default ARM && ARCH_RPC
 	help
 	  This is the generic IDE driver.  This driver attaches to the
 	  fixed legacy ports (e.g. on PCs 0x1f0/0x170, 0x1e8/0x168 and
@@ -722,13 +722,6 @@
 	  Say Y here if you want to support the Yellowstone RapIDE controller
 	  manufactured for use with Acorn computers.
 
-config IDE_H8300
-	tristate "H8300 IDE support"
-	depends on H8300
-	default y
-	help
-	  Enables the H8300 IDE driver.
-
 config BLK_DEV_GAYLE
 	tristate "Amiga Gayle IDE interface support"
 	depends on AMIGA
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index af8d016..a04ee82 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -78,8 +78,6 @@
 
 obj-$(CONFIG_BLK_DEV_IDE_PMAC)		+= pmac.o
 
-obj-$(CONFIG_IDE_H8300)			+= ide-h8300.o
-
 obj-$(CONFIG_IDE_GENERIC)		+= ide-generic.o
 obj-$(CONFIG_BLK_DEV_IDEPNP)		+= ide-pnp.o
 
diff --git a/drivers/ide/ide-h8300.c b/drivers/ide/ide-h8300.c
deleted file mode 100644
index 520f42c..0000000
--- a/drivers/ide/ide-h8300.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * H8/300 generic IDE interface
- */
-
-#include <linux/init.h>
-#include <linux/ide.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#define DRV_NAME "ide-h8300"
-
-#define bswap(d) \
-({					\
-	u16 r;				\
-	__asm__("mov.b %w1,r1h\n\t"	\
-		"mov.b %x1,r1l\n\t"	\
-		"mov.w r1,%0"		\
-		:"=r"(r)		\
-		:"r"(d)			\
-		:"er1");		\
-	(r);				\
-})
-
-static void mm_outsw(unsigned long addr, void *buf, u32 len)
-{
-	unsigned short *bp = (unsigned short *)buf;
-	for (; len > 0; len--, bp++)
-		*(volatile u16 *)addr = bswap(*bp);
-}
-
-static void mm_insw(unsigned long addr, void *buf, u32 len)
-{
-	unsigned short *bp = (unsigned short *)buf;
-	for (; len > 0; len--, bp++)
-		*bp = bswap(*(volatile u16 *)addr);
-}
-
-static void h8300_input_data(ide_drive_t *drive, struct ide_cmd *cmd,
-			     void *buf, unsigned int len)
-{
-	mm_insw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
-}
-
-static void h8300_output_data(ide_drive_t *drive, struct ide_cmd *cmd,
-			      void *buf, unsigned int len)
-{
-	mm_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
-}
-
-static const struct ide_tp_ops h8300_tp_ops = {
-	.exec_command		= ide_exec_command,
-	.read_status		= ide_read_status,
-	.read_altstatus		= ide_read_altstatus,
-	.write_devctl		= ide_write_devctl,
-
-	.dev_select		= ide_dev_select,
-	.tf_load		= ide_tf_load,
-	.tf_read		= ide_tf_read,
-
-	.input_data		= h8300_input_data,
-	.output_data		= h8300_output_data,
-};
-
-#define H8300_IDE_GAP (2)
-
-static inline void hw_setup(struct ide_hw *hw)
-{
-	int i;
-
-	memset(hw, 0, sizeof(*hw));
-	for (i = 0; i <= 7; i++)
-		hw->io_ports_array[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i;
-	hw->io_ports.ctl_addr = CONFIG_H8300_IDE_ALT;
-	hw->irq = EXT_IRQ0 + CONFIG_H8300_IDE_IRQ;
-}
-
-static const struct ide_port_info h8300_port_info = {
-	.tp_ops			= &h8300_tp_ops,
-	.host_flags		= IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_NO_DMA,
-	.chipset		= ide_generic,
-};
-
-static int __init h8300_ide_init(void)
-{
-	struct ide_hw hw, *hws[] = { &hw };
-
-	printk(KERN_INFO DRV_NAME ": H8/300 generic IDE interface\n");
-
-	if (!request_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8, "ide-h8300"))
-		goto out_busy;
-	if (!request_region(CONFIG_H8300_IDE_ALT, H8300_IDE_GAP, "ide-h8300")) {
-		release_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8);
-		goto out_busy;
-	}
-
-	hw_setup(&hw);
-
-	return ide_host_add(&h8300_port_info, hws, 1, NULL);
-
-out_busy:
-	printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n");
-
-	return -EBUSY;
-}
-
-module_init(h8300_ide_init);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-sysfs.c b/drivers/ide/ide-sysfs.c
index 883ffac..84a6a9e 100644
--- a/drivers/ide/ide-sysfs.c
+++ b/drivers/ide/ide-sysfs.c
@@ -25,6 +25,7 @@
 	ide_drive_t *drive = to_ide_device(dev);
 	return sprintf(buf, "%s\n", ide_media_string(drive));
 }
+static DEVICE_ATTR_RO(media);
 
 static ssize_t drivename_show(struct device *dev, struct device_attribute *attr,
 			      char *buf)
@@ -32,6 +33,7 @@
 	ide_drive_t *drive = to_ide_device(dev);
 	return sprintf(buf, "%s\n", drive->name);
 }
+static DEVICE_ATTR_RO(drivename);
 
 static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
 			     char *buf)
@@ -39,6 +41,7 @@
 	ide_drive_t *drive = to_ide_device(dev);
 	return sprintf(buf, "ide:m-%s\n", ide_media_string(drive));
 }
+static DEVICE_ATTR_RO(modalias);
 
 static ssize_t model_show(struct device *dev, struct device_attribute *attr,
 			  char *buf)
@@ -46,6 +49,7 @@
 	ide_drive_t *drive = to_ide_device(dev);
 	return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_PROD]);
 }
+static DEVICE_ATTR_RO(model);
 
 static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,
 			     char *buf)
@@ -53,6 +57,7 @@
 	ide_drive_t *drive = to_ide_device(dev);
 	return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_FW_REV]);
 }
+static DEVICE_ATTR_RO(firmware);
 
 static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
 			   char *buf)
@@ -60,16 +65,28 @@
 	ide_drive_t *drive = to_ide_device(dev);
 	return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_SERNO]);
 }
+static DEVICE_ATTR(serial, 0400, serial_show, NULL);
 
-struct device_attribute ide_dev_attrs[] = {
-	__ATTR_RO(media),
-	__ATTR_RO(drivename),
-	__ATTR_RO(modalias),
-	__ATTR_RO(model),
-	__ATTR_RO(firmware),
-	__ATTR(serial, 0400, serial_show, NULL),
-	__ATTR(unload_heads, 0644, ide_park_show, ide_park_store),
-	__ATTR_NULL
+static DEVICE_ATTR(unload_heads, 0644, ide_park_show, ide_park_store);
+
+static struct attribute *ide_attrs[] = {
+	&dev_attr_media.attr,
+	&dev_attr_drivename.attr,
+	&dev_attr_modalias.attr,
+	&dev_attr_model.attr,
+	&dev_attr_firmware.attr,
+	&dev_attr_serial.attr,
+	&dev_attr_unload_heads.attr,
+	NULL,
+};
+
+static const struct attribute_group ide_attr_group = {
+	.attrs = ide_attrs,
+};
+
+const struct attribute_group *ide_dev_groups[] = {
+	&ide_attr_group,
+	NULL,
 };
 
 static ssize_t store_delete_devices(struct device *portdev,
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index fa89621..2ce6268 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -158,7 +158,7 @@
 	.probe		= generic_ide_probe,
 	.remove		= generic_ide_remove,
 	.shutdown	= generic_ide_shutdown,
-	.dev_attrs	= ide_dev_attrs,
+	.dev_groups	= ide_dev_groups,
 	.suspend	= generic_ide_suspend,
 	.resume		= generic_ide_resume,
 };
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index fa6964d..f116d66 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -359,7 +359,7 @@
 	if (!(lapic_timer_reliable_states & (1 << (cstate))))
 		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
 
-	if (!need_resched()) {
+	if (!current_set_polling_and_test()) {
 
 		__monitor((void *)&current_thread_info()->flags, 0, 0);
 		smp_mb();
diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c
index 81e3dc2..28b3928 100644
--- a/drivers/iio/accel/bma180.c
+++ b/drivers/iio/accel/bma180.c
@@ -471,13 +471,10 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct bma180_data *data = iio_priv(indio_dev);
+	int64_t time_ns = iio_get_time_ns();
 	int bit, ret, i = 0;
 
 	mutex_lock(&data->mutex);
-	if (indio_dev->scan_timestamp) {
-		ret = indio_dev->scan_bytes / sizeof(s64) - 1;
-		((s64 *)data->buff)[ret] = iio_get_time_ns();
-	}
 
 	for_each_set_bit(bit, indio_dev->buffer->scan_mask,
 			 indio_dev->masklength) {
@@ -490,7 +487,7 @@
 	}
 	mutex_unlock(&data->mutex);
 
-	iio_push_to_buffers(indio_dev, (u8 *)data->buff);
+	iio_push_to_buffers_with_timestamp(indio_dev, data->buff, time_ns);
 err:
 	iio_trigger_notify_done(indio_dev->trig);
 
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index 46d22f3..dcda173 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -182,10 +182,11 @@
 };
 
 /* Function to push data to buffer */
-static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
+static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data,
+	int len)
 {
 	dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
-	iio_push_to_buffers(indio_dev, (u8 *)data);
+	iio_push_to_buffers(indio_dev, data);
 }
 
 /* Callback handler to send event after all samples are received and captured */
@@ -200,7 +201,7 @@
 				accel_state->common_attributes.data_ready);
 	if (accel_state->common_attributes.data_ready)
 		hid_sensor_push_data(indio_dev,
-				(u8 *)accel_state->accel_val,
+				accel_state->accel_val,
 				sizeof(accel_state->accel_val));
 
 	return 0;
diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c
index 709c132..d72118d 100644
--- a/drivers/iio/accel/kxsd9.c
+++ b/drivers/iio/accel/kxsd9.c
@@ -222,7 +222,6 @@
 {
 	struct iio_dev *indio_dev;
 	struct kxsd9_state *st;
-	int ret;
 
 	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (!indio_dev)
@@ -244,11 +243,7 @@
 	spi_setup(spi);
 	kxsd9_power_up(st);
 
-	ret = iio_device_register(indio_dev);
-	if (ret)
-		return ret;
-
-	return 0;
+	return iio_device_register(indio_dev);
 }
 
 static int kxsd9_remove(struct spi_device *spi)
diff --git a/drivers/iio/accel/st_accel_buffer.c b/drivers/iio/accel/st_accel_buffer.c
index d9b3507..a1e642e 100644
--- a/drivers/iio/accel/st_accel_buffer.c
+++ b/drivers/iio/accel/st_accel_buffer.c
@@ -32,16 +32,7 @@
 
 static int st_accel_buffer_preenable(struct iio_dev *indio_dev)
 {
-	int err;
-
-	err = st_sensors_set_enable(indio_dev, true);
-	if (err < 0)
-		goto st_accel_set_enable_error;
-
-	err = iio_sw_buffer_preenable(indio_dev);
-
-st_accel_set_enable_error:
-	return err;
+	return st_sensors_set_enable(indio_dev, true);
 }
 
 static int st_accel_buffer_postenable(struct iio_dev *indio_dev)
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
index 1458343..38caedc 100644
--- a/drivers/iio/accel/st_accel_core.c
+++ b/drivers/iio/accel/st_accel_core.c
@@ -452,8 +452,9 @@
 int st_accel_common_probe(struct iio_dev *indio_dev,
 				struct st_sensors_platform_data *plat_data)
 {
-	int err;
 	struct st_sensor_data *adata = iio_priv(indio_dev);
+	int irq = adata->get_irq_data_ready(indio_dev);
+	int err;
 
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &accel_info;
@@ -461,7 +462,7 @@
 	err = st_sensors_check_device_support(indio_dev,
 				ARRAY_SIZE(st_accel_sensors), st_accel_sensors);
 	if (err < 0)
-		goto st_accel_common_probe_error;
+		return err;
 
 	adata->num_data_channels = ST_ACCEL_NUMBER_DATA_CHANNELS;
 	adata->multiread_bit = adata->sensor->multi_read_bit;
@@ -478,13 +479,13 @@
 
 	err = st_sensors_init_sensor(indio_dev, plat_data);
 	if (err < 0)
-		goto st_accel_common_probe_error;
+		return err;
 
-	if (adata->get_irq_data_ready(indio_dev) > 0) {
-		err = st_accel_allocate_ring(indio_dev);
-		if (err < 0)
-			goto st_accel_common_probe_error;
+	err = st_accel_allocate_ring(indio_dev);
+	if (err < 0)
+		return err;
 
+	if (irq > 0) {
 		err = st_sensors_allocate_trigger(indio_dev,
 						 ST_ACCEL_TRIGGER_OPS);
 		if (err < 0)
@@ -495,15 +496,14 @@
 	if (err)
 		goto st_accel_device_register_error;
 
-	return err;
+	return 0;
 
 st_accel_device_register_error:
-	if (adata->get_irq_data_ready(indio_dev) > 0)
+	if (irq > 0)
 		st_sensors_deallocate_trigger(indio_dev);
 st_accel_probe_trigger_error:
-	if (adata->get_irq_data_ready(indio_dev) > 0)
-		st_accel_deallocate_ring(indio_dev);
-st_accel_common_probe_error:
+	st_accel_deallocate_ring(indio_dev);
+
 	return err;
 }
 EXPORT_SYMBOL(st_accel_common_probe);
@@ -513,10 +513,10 @@
 	struct st_sensor_data *adata = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	if (adata->get_irq_data_ready(indio_dev) > 0) {
+	if (adata->get_irq_data_ready(indio_dev) > 0)
 		st_sensors_deallocate_trigger(indio_dev);
-		st_accel_deallocate_ring(indio_dev);
-	}
+
+	st_accel_deallocate_ring(indio_dev);
 }
 EXPORT_SYMBOL(st_accel_common_remove);
 
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 09371cb..2209f28 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -145,6 +145,16 @@
 	  This driver can also be built as a module. If so, the module will be
 	  called mcp320x.
 
+config MCP3422
+	tristate "Microchip Technology MCP3422/3/4 driver"
+	depends on I2C
+	help
+	  Say yes here to build support for Microchip Technology's MCP3422,
+	  MCP3423 or MCP3424 analog to digital converters.
+
+	  This driver can also be built as a module. If so, the module will be
+	  called mcp3422.
+
 config NAU7802
 	tristate "Nuvoton NAU7802 ADC driver"
 	depends on I2C
@@ -167,6 +177,8 @@
 config TI_AM335X_ADC
 	tristate "TI's AM335X ADC driver"
 	depends on MFD_TI_AM335X_TSCADC
+	select IIO_BUFFER
+	select IIO_KFIFO_BUF
 	help
 	  Say yes here to build support for Texas Instruments ADC
 	  driver which is also a MFD client.
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 33656ef..ba9a10a 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -16,6 +16,7 @@
 obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
 obj-$(CONFIG_MAX1363) += max1363.o
 obj-$(CONFIG_MCP320X) += mcp320x.o
+obj-$(CONFIG_MCP3422) += mcp3422.o
 obj-$(CONFIG_NAU7802) += nau7802.o
 obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
 obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
index 371731d..58e9455 100644
--- a/drivers/iio/adc/ad7266.c
+++ b/drivers/iio/adc/ad7266.c
@@ -27,7 +27,7 @@
 struct ad7266_state {
 	struct spi_device	*spi;
 	struct regulator	*reg;
-	unsigned long		vref_uv;
+	unsigned long		vref_mv;
 
 	struct spi_transfer	single_xfer[3];
 	struct spi_message	single_msg;
@@ -61,17 +61,7 @@
 static int ad7266_preenable(struct iio_dev *indio_dev)
 {
 	struct ad7266_state *st = iio_priv(indio_dev);
-	int ret;
-
-	ret = ad7266_wakeup(st);
-	if (ret)
-		return ret;
-
-	ret = iio_sw_buffer_preenable(indio_dev);
-	if (ret)
-		ad7266_powerdown(st);
-
-	return ret;
+	return ad7266_wakeup(st);
 }
 
 static int ad7266_postdisable(struct iio_dev *indio_dev)
@@ -96,9 +86,8 @@
 
 	ret = spi_read(st->spi, st->data, 4);
 	if (ret == 0) {
-		if (indio_dev->scan_timestamp)
-			((s64 *)st->data)[1] = pf->timestamp;
-		iio_push_to_buffers(indio_dev, (u8 *)st->data);
+		iio_push_to_buffers_with_timestamp(indio_dev, st->data,
+			    pf->timestamp);
 	}
 
 	iio_trigger_notify_done(indio_dev->trig);
@@ -157,7 +146,7 @@
 	struct iio_chan_spec const *chan, int *val, int *val2, long m)
 {
 	struct ad7266_state *st = iio_priv(indio_dev);
-	unsigned long scale_uv;
+	unsigned long scale_mv;
 	int ret;
 
 	switch (m) {
@@ -175,16 +164,15 @@
 
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		scale_uv = (st->vref_uv * 100);
+		scale_mv = st->vref_mv;
 		if (st->mode == AD7266_MODE_DIFF)
-			scale_uv *= 2;
+			scale_mv *= 2;
 		if (st->range == AD7266_RANGE_2VREF)
-			scale_uv *= 2;
+			scale_mv *= 2;
 
-		scale_uv >>= chan->scan_type.realbits;
-		*val =  scale_uv / 100000;
-		*val2 = (scale_uv % 100000) * 10;
-		return IIO_VAL_INT_PLUS_MICRO;
+		*val = scale_mv;
+		*val2 = chan->scan_type.realbits;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	case IIO_CHAN_INFO_OFFSET:
 		if (st->range == AD7266_RANGE_2VREF &&
 			st->mode != AD7266_MODE_DIFF)
@@ -293,7 +281,7 @@
 	.driver_module = THIS_MODULE,
 };
 
-static unsigned long ad7266_available_scan_masks[] = {
+static const unsigned long ad7266_available_scan_masks[] = {
 	0x003,
 	0x00c,
 	0x030,
@@ -303,14 +291,14 @@
 	0x000,
 };
 
-static unsigned long ad7266_available_scan_masks_diff[] = {
+static const unsigned long ad7266_available_scan_masks_diff[] = {
 	0x003,
 	0x00c,
 	0x030,
 	0x000,
 };
 
-static unsigned long ad7266_available_scan_masks_fixed[] = {
+static const unsigned long ad7266_available_scan_masks_fixed[] = {
 	0x003,
 	0x000,
 };
@@ -318,7 +306,7 @@
 struct ad7266_chan_info {
 	const struct iio_chan_spec *channels;
 	unsigned int num_channels;
-	unsigned long *scan_masks;
+	const unsigned long *scan_masks;
 };
 
 #define AD7266_CHAN_INFO_INDEX(_differential, _signed, _fixed) \
@@ -415,10 +403,10 @@
 		if (ret < 0)
 			goto error_disable_reg;
 
-		st->vref_uv = ret;
+		st->vref_mv = ret / 1000;
 	} else {
 		/* Use internal reference */
-		st->vref_uv = 2500000;
+		st->vref_mv = 2500;
 	}
 
 	if (pdata) {
diff --git a/drivers/iio/adc/ad7298.c b/drivers/iio/adc/ad7298.c
index 85d1481..2a3b65c 100644
--- a/drivers/iio/adc/ad7298.c
+++ b/drivers/iio/adc/ad7298.c
@@ -159,20 +159,14 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct ad7298_state *st = iio_priv(indio_dev);
-	s64 time_ns = 0;
 	int b_sent;
 
 	b_sent = spi_sync(st->spi, &st->ring_msg);
 	if (b_sent)
 		goto done;
 
-	if (indio_dev->scan_timestamp) {
-		time_ns = iio_get_time_ns();
-		memcpy((u8 *)st->rx_buf + indio_dev->scan_bytes - sizeof(s64),
-			&time_ns, sizeof(time_ns));
-	}
-
-	iio_push_to_buffers(indio_dev, (u8 *)st->rx_buf);
+	iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf,
+		iio_get_time_ns());
 
 done:
 	iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c
index 6d2b1d8..d141d45 100644
--- a/drivers/iio/adc/ad7476.c
+++ b/drivers/iio/adc/ad7476.c
@@ -64,19 +64,14 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct ad7476_state *st = iio_priv(indio_dev);
-	s64 time_ns;
 	int b_sent;
 
 	b_sent = spi_sync(st->spi, &st->msg);
 	if (b_sent < 0)
 		goto done;
 
-	time_ns = iio_get_time_ns();
-
-	if (indio_dev->scan_timestamp)
-		((s64 *)st->data)[1] = time_ns;
-
-	iio_push_to_buffers(indio_dev, st->data);
+	iio_push_to_buffers_with_timestamp(indio_dev, st->data,
+		iio_get_time_ns());
 done:
 	iio_trigger_notify_done(indio_dev->trig);
 
@@ -132,10 +127,9 @@
 		} else {
 			scale_uv = st->chip_info->int_vref_uv;
 		}
-		scale_uv >>= chan->scan_type.realbits;
-		*val =  scale_uv / 1000;
-		*val2 = (scale_uv % 1000) * 1000;
-		return IIO_VAL_INT_PLUS_MICRO;
+		*val = scale_uv / 1000;
+		*val2 = chan->scan_type.realbits;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	}
 	return -EINVAL;
 }
diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c
index c202035..c19f8fd 100644
--- a/drivers/iio/adc/ad7791.c
+++ b/drivers/iio/adc/ad7791.c
@@ -202,7 +202,6 @@
 {
 	struct ad7791_state *st = iio_priv(indio_dev);
 	bool unipolar = !!(st->mode & AD7791_MODE_UNIPOLAR);
-	unsigned long long scale_pv;
 
 	switch (info) {
 	case IIO_CHAN_INFO_RAW:
@@ -220,23 +219,26 @@
 	case IIO_CHAN_INFO_SCALE:
 		/* The monitor channel uses an internal reference. */
 		if (chan->address == AD7791_CH_AVDD_MONITOR) {
-			scale_pv = 5850000000000ULL;
+			/*
+			 * The signal is attenuated by a factor of 5 and
+			 * compared against a 1.17V internal reference.
+			 */
+			*val = 1170 * 5;
 		} else {
 			int voltage_uv;
 
 			voltage_uv = regulator_get_voltage(st->reg);
 			if (voltage_uv < 0)
 				return voltage_uv;
-			scale_pv = (unsigned long long)voltage_uv * 1000000;
+
+			*val = voltage_uv / 1000;
 		}
 		if (unipolar)
-			scale_pv >>= chan->scan_type.realbits;
+			*val2 = chan->scan_type.realbits;
 		else
-			scale_pv >>= chan->scan_type.realbits - 1;
-		*val2 = do_div(scale_pv, 1000000000);
-		*val = scale_pv;
+			*val2 = chan->scan_type.realbits - 1;
 
-		return IIO_VAL_INT_PLUS_NANO;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	}
 
 	return -EINVAL;
diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c
index 9dd077b..acb7f90 100644
--- a/drivers/iio/adc/ad7887.c
+++ b/drivers/iio/adc/ad7887.c
@@ -78,11 +78,6 @@
 static int ad7887_ring_preenable(struct iio_dev *indio_dev)
 {
 	struct ad7887_state *st = iio_priv(indio_dev);
-	int ret;
-
-	ret = iio_sw_buffer_preenable(indio_dev);
-	if (ret < 0)
-		return ret;
 
 	/* We know this is a single long so can 'cheat' */
 	switch (*indio_dev->active_scan_mask) {
@@ -121,20 +116,14 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct ad7887_state *st = iio_priv(indio_dev);
-	s64 time_ns;
 	int b_sent;
 
 	b_sent = spi_sync(st->spi, st->ring_msg);
 	if (b_sent)
 		goto done;
 
-	time_ns = iio_get_time_ns();
-
-	if (indio_dev->scan_timestamp)
-		memcpy(st->data + indio_dev->scan_bytes - sizeof(s64),
-		       &time_ns, sizeof(time_ns));
-
-	iio_push_to_buffers(indio_dev, st->data);
+	iio_push_to_buffers_with_timestamp(indio_dev, st->data,
+		iio_get_time_ns());
 done:
 	iio_trigger_notify_done(indio_dev->trig);
 
diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c
index 4108dbb..28732c2 100644
--- a/drivers/iio/adc/ad7923.c
+++ b/drivers/iio/adc/ad7923.c
@@ -174,20 +174,14 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct ad7923_state *st = iio_priv(indio_dev);
-	s64 time_ns = 0;
 	int b_sent;
 
 	b_sent = spi_sync(st->spi, &st->ring_msg);
 	if (b_sent)
 		goto done;
 
-	if (indio_dev->scan_timestamp) {
-		time_ns = iio_get_time_ns();
-		memcpy((u8 *)st->rx_buf + indio_dev->scan_bytes - sizeof(s64),
-			&time_ns, sizeof(time_ns));
-	}
-
-	iio_push_to_buffers(indio_dev, (u8 *)st->rx_buf);
+	iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf,
+		iio_get_time_ns());
 
 done:
 	iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index f0d6335..e6fbd3e 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -368,10 +368,6 @@
 
 	memset(data, 0x00, 16);
 
-	/* Guaranteed to be aligned with 8 byte boundary */
-	if (indio_dev->scan_timestamp)
-		((s64 *)data)[1] = pf->timestamp;
-
 	reg_size = indio_dev->channels[0].scan_type.realbits +
 			indio_dev->channels[0].scan_type.shift;
 	reg_size = DIV_ROUND_UP(reg_size, 8);
@@ -391,7 +387,7 @@
 		break;
 	}
 
-	iio_push_to_buffers(indio_dev, (uint8_t *)data);
+	iio_push_to_buffers_with_timestamp(indio_dev, data, pf->timestamp);
 
 	iio_trigger_notify_done(indio_dev->trig);
 	sigma_delta->irq_dis = false;
@@ -401,7 +397,6 @@
 }
 
 static const struct iio_buffer_setup_ops ad_sd_buffer_setup_ops = {
-	.preenable = &iio_sw_buffer_preenable,
 	.postenable = &ad_sd_buffer_postenable,
 	.predisable = &iio_triggered_buffer_predisable,
 	.postdisable = &ad_sd_buffer_postdisable,
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 0f16b55..17df749 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -11,6 +11,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/input.h>
 #include <linux/interrupt.h>
 #include <linux/jiffies.h>
 #include <linux/kernel.h>
@@ -39,10 +40,36 @@
 #define at91_adc_writel(st, reg, val) \
 	(writel_relaxed(val, st->reg_base + reg))
 
+#define DRIVER_NAME		"at91_adc"
+#define MAX_POS_BITS		12
+
+#define TOUCH_SAMPLE_PERIOD_US		2000	/* 2ms */
+#define TOUCH_PEN_DETECT_DEBOUNCE_US	200
+
 struct at91_adc_caps {
+	bool	has_ts;		/* Support touch screen */
+	bool	has_tsmr;	/* only at91sam9x5, sama5d3 have TSMR reg */
+	/*
+	 * Numbers of sampling data will be averaged. Can be 0~3.
+	 * Hardware can average (2 ^ ts_filter_average) sample data.
+	 */
+	u8	ts_filter_average;
+	/* Pen Detection input pull-up resistor, can be 0~3 */
+	u8	ts_pen_detect_sensitivity;
+
+	/* startup time calculate function */
+	u32 (*calc_startup_ticks)(u8 startup_time, u32 adc_clk_khz);
+
+	u8	num_channels;
 	struct at91_adc_reg_desc registers;
 };
 
+enum atmel_adc_ts_type {
+	ATMEL_ADC_TOUCHSCREEN_NONE = 0,
+	ATMEL_ADC_TOUCHSCREEN_4WIRE = 4,
+	ATMEL_ADC_TOUCHSCREEN_5WIRE = 5,
+};
+
 struct at91_adc_state {
 	struct clk		*adc_clk;
 	u16			*buffer;
@@ -67,6 +94,26 @@
 	bool			low_res;	/* the resolution corresponds to the lowest one */
 	wait_queue_head_t	wq_data_avail;
 	struct at91_adc_caps	*caps;
+
+	/*
+	 * Following ADC channels are shared by touchscreen:
+	 *
+	 * CH0 -- Touch screen XP/UL
+	 * CH1 -- Touch screen XM/UR
+	 * CH2 -- Touch screen YP/LL
+	 * CH3 -- Touch screen YM/Sense
+	 * CH4 -- Touch screen LR(5-wire only)
+	 *
+	 * The bitfields below represents the reserved channel in the
+	 * touchscreen mode.
+	 */
+#define CHAN_MASK_TOUCHSCREEN_4WIRE	(0xf << 0)
+#define CHAN_MASK_TOUCHSCREEN_5WIRE	(0x1f << 0)
+	enum atmel_adc_ts_type	touchscreen_type;
+	struct input_dev	*ts_input;
+
+	u16			ts_sample_period_val;
+	u32			ts_pressure_threshold;
 };
 
 static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
@@ -83,13 +130,7 @@
 		j++;
 	}
 
-	if (idev->scan_timestamp) {
-		s64 *timestamp = (s64 *)((u8 *)st->buffer +
-					ALIGN(j, sizeof(s64)));
-		*timestamp = pf->timestamp;
-	}
-
-	iio_push_to_buffers(idev, (u8 *)st->buffer);
+	iio_push_to_buffers_with_timestamp(idev, st->buffer, pf->timestamp);
 
 	iio_trigger_notify_done(idev->trig);
 
@@ -101,14 +142,10 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t at91_adc_eoc_trigger(int irq, void *private)
+/* Handler for classic adc channel eoc trigger */
+void handle_adc_eoc_trigger(int irq, struct iio_dev *idev)
 {
-	struct iio_dev *idev = private;
 	struct at91_adc_state *st = iio_priv(idev);
-	u32 status = at91_adc_readl(st, st->registers->status_register);
-
-	if (!(status & st->registers->drdy_mask))
-		return IRQ_HANDLED;
 
 	if (iio_buffer_enabled(idev)) {
 		disable_irq_nosync(irq);
@@ -118,6 +155,115 @@
 		st->done = true;
 		wake_up_interruptible(&st->wq_data_avail);
 	}
+}
+
+static int at91_ts_sample(struct at91_adc_state *st)
+{
+	unsigned int xscale, yscale, reg, z1, z2;
+	unsigned int x, y, pres, xpos, ypos;
+	unsigned int rxp = 1;
+	unsigned int factor = 1000;
+	struct iio_dev *idev = iio_priv_to_dev(st);
+
+	unsigned int xyz_mask_bits = st->res;
+	unsigned int xyz_mask = (1 << xyz_mask_bits) - 1;
+
+	/* calculate position */
+	/* x position = (x / xscale) * max, max = 2^MAX_POS_BITS - 1 */
+	reg = at91_adc_readl(st, AT91_ADC_TSXPOSR);
+	xpos = reg & xyz_mask;
+	x = (xpos << MAX_POS_BITS) - xpos;
+	xscale = (reg >> 16) & xyz_mask;
+	if (xscale == 0) {
+		dev_err(&idev->dev, "Error: xscale == 0!\n");
+		return -1;
+	}
+	x /= xscale;
+
+	/* y position = (y / yscale) * max, max = 2^MAX_POS_BITS - 1 */
+	reg = at91_adc_readl(st, AT91_ADC_TSYPOSR);
+	ypos = reg & xyz_mask;
+	y = (ypos << MAX_POS_BITS) - ypos;
+	yscale = (reg >> 16) & xyz_mask;
+	if (yscale == 0) {
+		dev_err(&idev->dev, "Error: yscale == 0!\n");
+		return -1;
+	}
+	y /= yscale;
+
+	/* calculate the pressure */
+	reg = at91_adc_readl(st, AT91_ADC_TSPRESSR);
+	z1 = reg & xyz_mask;
+	z2 = (reg >> 16) & xyz_mask;
+
+	if (z1 != 0)
+		pres = rxp * (x * factor / 1024) * (z2 * factor / z1 - factor)
+			/ factor;
+	else
+		pres = st->ts_pressure_threshold;	/* no pen contacted */
+
+	dev_dbg(&idev->dev, "xpos = %d, xscale = %d, ypos = %d, yscale = %d, z1 = %d, z2 = %d, press = %d\n",
+				xpos, xscale, ypos, yscale, z1, z2, pres);
+
+	if (pres < st->ts_pressure_threshold) {
+		dev_dbg(&idev->dev, "x = %d, y = %d, pressure = %d\n",
+					x, y, pres / factor);
+		input_report_abs(st->ts_input, ABS_X, x);
+		input_report_abs(st->ts_input, ABS_Y, y);
+		input_report_abs(st->ts_input, ABS_PRESSURE, pres);
+		input_report_key(st->ts_input, BTN_TOUCH, 1);
+		input_sync(st->ts_input);
+	} else {
+		dev_dbg(&idev->dev, "pressure too low: not reporting\n");
+	}
+
+	return 0;
+}
+
+static irqreturn_t at91_adc_interrupt(int irq, void *private)
+{
+	struct iio_dev *idev = private;
+	struct at91_adc_state *st = iio_priv(idev);
+	u32 status = at91_adc_readl(st, st->registers->status_register);
+	const uint32_t ts_data_irq_mask =
+		AT91_ADC_IER_XRDY |
+		AT91_ADC_IER_YRDY |
+		AT91_ADC_IER_PRDY;
+
+	if (status & st->registers->drdy_mask)
+		handle_adc_eoc_trigger(irq, idev);
+
+	if (status & AT91_ADC_IER_PEN) {
+		at91_adc_writel(st, AT91_ADC_IDR, AT91_ADC_IER_PEN);
+		at91_adc_writel(st, AT91_ADC_IER, AT91_ADC_IER_NOPEN |
+			ts_data_irq_mask);
+		/* Set up period trigger for sampling */
+		at91_adc_writel(st, st->registers->trigger_register,
+			AT91_ADC_TRGR_MOD_PERIOD_TRIG |
+			AT91_ADC_TRGR_TRGPER_(st->ts_sample_period_val));
+	} else if (status & AT91_ADC_IER_NOPEN) {
+		at91_adc_writel(st, st->registers->trigger_register, 0);
+		at91_adc_writel(st, AT91_ADC_IDR, AT91_ADC_IER_NOPEN |
+			ts_data_irq_mask);
+		at91_adc_writel(st, AT91_ADC_IER, AT91_ADC_IER_PEN);
+
+		input_report_key(st->ts_input, BTN_TOUCH, 0);
+		input_sync(st->ts_input);
+	} else if ((status & ts_data_irq_mask) == ts_data_irq_mask) {
+		/* Now all touchscreen data is ready */
+
+		if (status & AT91_ADC_ISR_PENS) {
+			/* validate data by pen contact */
+			at91_ts_sample(st);
+		} else {
+			/* triggered by event that is no pen contact, just read
+			 * them to clean the interrupt and discard all.
+			 */
+			at91_adc_readl(st, AT91_ADC_TSXPOSR);
+			at91_adc_readl(st, AT91_ADC_TSYPOSR);
+			at91_adc_readl(st, AT91_ADC_TSPRESSR);
+		}
+	}
 
 	return IRQ_HANDLED;
 }
@@ -127,6 +273,16 @@
 	struct at91_adc_state *st = iio_priv(idev);
 	struct iio_chan_spec *chan_array, *timestamp;
 	int bit, idx = 0;
+	unsigned long rsvd_mask = 0;
+
+	/* If touchscreen is enable, then reserve the adc channels */
+	if (st->touchscreen_type == ATMEL_ADC_TOUCHSCREEN_4WIRE)
+		rsvd_mask = CHAN_MASK_TOUCHSCREEN_4WIRE;
+	else if (st->touchscreen_type == ATMEL_ADC_TOUCHSCREEN_5WIRE)
+		rsvd_mask = CHAN_MASK_TOUCHSCREEN_5WIRE;
+
+	/* set up the channel mask to reserve touchscreen channels */
+	st->channels_mask &= ~rsvd_mask;
 
 	idev->num_channels = bitmap_weight(&st->channels_mask,
 					   st->num_channels) + 1;
@@ -279,7 +435,7 @@
 	int i, ret;
 
 	st->trig = devm_kzalloc(&idev->dev,
-				st->trigger_number * sizeof(st->trig),
+				st->trigger_number * sizeof(*st->trig),
 				GFP_KERNEL);
 
 	if (st->trig == NULL) {
@@ -372,9 +528,9 @@
 		return IIO_VAL_INT;
 
 	case IIO_CHAN_INFO_SCALE:
-		*val = (st->vref_mv * 1000) >> chan->scan_type.realbits;
-		*val2 = 0;
-		return IIO_VAL_INT_PLUS_MICRO;
+		*val = st->vref_mv;
+		*val2 = chan->scan_type.realbits;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	default:
 		break;
 	}
@@ -434,8 +590,80 @@
 	return ret;
 }
 
+static u32 calc_startup_ticks_9260(u8 startup_time, u32 adc_clk_khz)
+{
+	/*
+	 * Number of ticks needed to cover the startup time of the ADC
+	 * as defined in the electrical characteristics of the board,
+	 * divided by 8. The formula thus is :
+	 *   Startup Time = (ticks + 1) * 8 / ADC Clock
+	 */
+	return round_up((startup_time * adc_clk_khz / 1000) - 1, 8) / 8;
+}
+
+static u32 calc_startup_ticks_9x5(u8 startup_time, u32 adc_clk_khz)
+{
+	/*
+	 * For sama5d3x and at91sam9x5, the formula changes to:
+	 * Startup Time = <lookup_table_value> / ADC Clock
+	 */
+	const int startup_lookup[] = {
+		0  , 8  , 16 , 24 ,
+		64 , 80 , 96 , 112,
+		512, 576, 640, 704,
+		768, 832, 896, 960
+		};
+	int i, size = ARRAY_SIZE(startup_lookup);
+	unsigned int ticks;
+
+	ticks = startup_time * adc_clk_khz / 1000;
+	for (i = 0; i < size; i++)
+		if (ticks < startup_lookup[i])
+			break;
+
+	ticks = i;
+	if (ticks == size)
+		/* Reach the end of lookup table */
+		ticks = size - 1;
+
+	return ticks;
+}
+
 static const struct of_device_id at91_adc_dt_ids[];
 
+static int at91_adc_probe_dt_ts(struct device_node *node,
+	struct at91_adc_state *st, struct device *dev)
+{
+	int ret;
+	u32 prop;
+
+	ret = of_property_read_u32(node, "atmel,adc-ts-wires", &prop);
+	if (ret) {
+		dev_info(dev, "ADC Touch screen is disabled.\n");
+		return 0;
+	}
+
+	switch (prop) {
+	case 4:
+	case 5:
+		st->touchscreen_type = prop;
+		break;
+	default:
+		dev_err(dev, "Unsupported number of touchscreen wires (%d). Should be 4 or 5.\n", prop);
+		return -EINVAL;
+	}
+
+	prop = 0;
+	of_property_read_u32(node, "atmel,adc-ts-pressure-threshold", &prop);
+	st->ts_pressure_threshold = prop;
+	if (st->ts_pressure_threshold) {
+		return 0;
+	} else {
+		dev_err(dev, "Invalid pressure threshold for the touchscreen\n");
+		return -EINVAL;
+	}
+}
+
 static int at91_adc_probe_dt(struct at91_adc_state *st,
 			     struct platform_device *pdev)
 {
@@ -460,13 +688,6 @@
 	}
 	st->channels_mask = prop;
 
-	if (of_property_read_u32(node, "atmel,adc-num-channels", &prop)) {
-		dev_err(&idev->dev, "Missing adc-num-channels property in the DT.\n");
-		ret = -EINVAL;
-		goto error_ret;
-	}
-	st->num_channels = prop;
-
 	st->sleep_mode = of_property_read_bool(node, "atmel,adc-sleep-mode");
 
 	if (of_property_read_u32(node, "atmel,adc-startup-time", &prop)) {
@@ -492,6 +713,7 @@
 		goto error_ret;
 
 	st->registers = &st->caps->registers;
+	st->num_channels = st->caps->num_channels;
 	st->trigger_number = of_get_child_count(node);
 	st->trigger_list = devm_kzalloc(&idev->dev, st->trigger_number *
 					sizeof(struct at91_adc_trigger),
@@ -523,6 +745,12 @@
 		i++;
 	}
 
+	/* Check if touchscreen is supported. */
+	if (st->caps->has_ts)
+		return at91_adc_probe_dt_ts(node, st, &idev->dev);
+	else
+		dev_info(&idev->dev, "not support touchscreen in the adc compatible string.\n");
+
 	return 0;
 
 error_ret:
@@ -554,6 +782,114 @@
 	.read_raw = &at91_adc_read_raw,
 };
 
+/* Touchscreen related functions */
+static int atmel_ts_open(struct input_dev *dev)
+{
+	struct at91_adc_state *st = input_get_drvdata(dev);
+
+	at91_adc_writel(st, AT91_ADC_IER, AT91_ADC_IER_PEN);
+	return 0;
+}
+
+static void atmel_ts_close(struct input_dev *dev)
+{
+	struct at91_adc_state *st = input_get_drvdata(dev);
+
+	at91_adc_writel(st, AT91_ADC_IDR, AT91_ADC_IER_PEN);
+}
+
+static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz)
+{
+	u32 reg = 0, pendbc;
+	int i = 0;
+
+	if (st->touchscreen_type == ATMEL_ADC_TOUCHSCREEN_4WIRE)
+		reg = AT91_ADC_TSMR_TSMODE_4WIRE_PRESS;
+	else
+		reg = AT91_ADC_TSMR_TSMODE_5WIRE;
+
+	/* a Pen Detect Debounce Time is necessary for the ADC Touch to avoid
+	 * pen detect noise.
+	 * The formula is : Pen Detect Debounce Time = (2 ^ pendbc) / ADCClock
+	 */
+	pendbc = round_up(TOUCH_PEN_DETECT_DEBOUNCE_US * adc_clk_khz / 1000, 1);
+
+	while (pendbc >> ++i)
+		;	/* Empty! Find the shift offset */
+	if (abs(pendbc - (1 << i)) < abs(pendbc - (1 << (i - 1))))
+		pendbc = i;
+	else
+		pendbc = i - 1;
+
+	if (st->caps->has_tsmr) {
+		reg |= AT91_ADC_TSMR_TSAV_(st->caps->ts_filter_average)
+				& AT91_ADC_TSMR_TSAV;
+		reg |= AT91_ADC_TSMR_PENDBC_(pendbc) & AT91_ADC_TSMR_PENDBC;
+		reg |= AT91_ADC_TSMR_NOTSDMA;
+		reg |= AT91_ADC_TSMR_PENDET_ENA;
+		reg |= 0x03 << 8;	/* TSFREQ, need bigger than TSAV */
+
+		at91_adc_writel(st, AT91_ADC_TSMR, reg);
+	} else {
+		/* TODO: for 9g45 which has no TSMR */
+	}
+
+	/* Change adc internal resistor value for better pen detection,
+	 * default value is 100 kOhm.
+	 * 0 = 200 kOhm, 1 = 150 kOhm, 2 = 100 kOhm, 3 = 50 kOhm
+	 * option only available on ES2 and higher
+	 */
+	at91_adc_writel(st, AT91_ADC_ACR, st->caps->ts_pen_detect_sensitivity
+			& AT91_ADC_ACR_PENDETSENS);
+
+	/* Sample Peroid Time = (TRGPER + 1) / ADCClock */
+	st->ts_sample_period_val = round_up((TOUCH_SAMPLE_PERIOD_US *
+			adc_clk_khz / 1000) - 1, 1);
+
+	return 0;
+}
+
+static int at91_ts_register(struct at91_adc_state *st,
+		struct platform_device *pdev)
+{
+	struct input_dev *input;
+	struct iio_dev *idev = iio_priv_to_dev(st);
+	int ret;
+
+	input = input_allocate_device();
+	if (!input) {
+		dev_err(&idev->dev, "Failed to allocate TS device!\n");
+		return -ENOMEM;
+	}
+
+	input->name = DRIVER_NAME;
+	input->id.bustype = BUS_HOST;
+	input->dev.parent = &pdev->dev;
+	input->open = atmel_ts_open;
+	input->close = atmel_ts_close;
+
+	__set_bit(EV_ABS, input->evbit);
+	__set_bit(EV_KEY, input->evbit);
+	__set_bit(BTN_TOUCH, input->keybit);
+	input_set_abs_params(input, ABS_X, 0, (1 << MAX_POS_BITS) - 1, 0, 0);
+	input_set_abs_params(input, ABS_Y, 0, (1 << MAX_POS_BITS) - 1, 0, 0);
+	input_set_abs_params(input, ABS_PRESSURE, 0, 0xffffff, 0, 0);
+
+	st->ts_input = input;
+	input_set_drvdata(input, st);
+
+	ret = input_register_device(input);
+	if (ret)
+		input_free_device(st->ts_input);
+
+	return ret;
+}
+
+static void at91_ts_unregister(struct at91_adc_state *st)
+{
+	input_unregister_device(st->ts_input);
+}
+
 static int at91_adc_probe(struct platform_device *pdev)
 {
 	unsigned int prsc, mstrclk, ticks, adc_clk, adc_clk_khz, shtim;
@@ -605,7 +941,7 @@
 	at91_adc_writel(st, AT91_ADC_CR, AT91_ADC_SWRST);
 	at91_adc_writel(st, AT91_ADC_IDR, 0xFFFFFFFF);
 	ret = request_irq(st->irq,
-			  at91_adc_eoc_trigger,
+			  at91_adc_interrupt,
 			  0,
 			  pdev->dev.driver->name,
 			  idev);
@@ -650,6 +986,10 @@
 	mstrclk = clk_get_rate(st->clk);
 	adc_clk = clk_get_rate(st->adc_clk);
 	adc_clk_khz = adc_clk / 1000;
+
+	dev_dbg(&pdev->dev, "Master clock is set as: %d Hz, adc_clk should set as: %d Hz\n",
+		mstrclk, adc_clk);
+
 	prsc = (mstrclk / (2 * adc_clk)) - 1;
 
 	if (!st->startup_time) {
@@ -657,15 +997,9 @@
 		ret = -EINVAL;
 		goto error_disable_adc_clk;
 	}
+	ticks = (*st->caps->calc_startup_ticks)(st->startup_time, adc_clk_khz);
 
 	/*
-	 * Number of ticks needed to cover the startup time of the ADC as
-	 * defined in the electrical characteristics of the board, divided by 8.
-	 * The formula thus is : Startup Time = (ticks + 1) * 8 / ADC Clock
-	 */
-	ticks = round_up((st->startup_time * adc_clk_khz /
-			  1000) - 1, 8) / 8;
-	/*
 	 * a minimal Sample and Hold Time is necessary for the ADC to guarantee
 	 * the best converted final value between two channels selection
 	 * The formula thus is : Sample and Hold Time = (shtim + 1) / ADCClock
@@ -692,30 +1026,52 @@
 	init_waitqueue_head(&st->wq_data_avail);
 	mutex_init(&st->lock);
 
-	ret = at91_adc_buffer_init(idev);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Couldn't initialize the buffer.\n");
-		goto error_disable_adc_clk;
-	}
+	/*
+	 * Since touch screen will set trigger register as period trigger. So
+	 * when touch screen is enabled, then we have to disable hardware
+	 * trigger for classic adc.
+	 */
+	if (!st->touchscreen_type) {
+		ret = at91_adc_buffer_init(idev);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "Couldn't initialize the buffer.\n");
+			goto error_disable_adc_clk;
+		}
 
-	ret = at91_adc_trigger_init(idev);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Couldn't setup the triggers.\n");
-		goto error_unregister_buffer;
+		ret = at91_adc_trigger_init(idev);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "Couldn't setup the triggers.\n");
+			at91_adc_buffer_remove(idev);
+			goto error_disable_adc_clk;
+		}
+	} else {
+		if (!st->caps->has_tsmr) {
+			dev_err(&pdev->dev, "We don't support non-TSMR adc\n");
+			goto error_disable_adc_clk;
+		}
+
+		ret = at91_ts_register(st, pdev);
+		if (ret)
+			goto error_disable_adc_clk;
+
+		at91_ts_hw_init(st, adc_clk_khz);
 	}
 
 	ret = iio_device_register(idev);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Couldn't register the device.\n");
-		goto error_remove_triggers;
+		goto error_iio_device_register;
 	}
 
 	return 0;
 
-error_remove_triggers:
-	at91_adc_trigger_remove(idev);
-error_unregister_buffer:
-	at91_adc_buffer_remove(idev);
+error_iio_device_register:
+	if (!st->touchscreen_type) {
+		at91_adc_trigger_remove(idev);
+		at91_adc_buffer_remove(idev);
+	} else {
+		at91_ts_unregister(st);
+	}
 error_disable_adc_clk:
 	clk_disable_unprepare(st->adc_clk);
 error_disable_clk:
@@ -731,8 +1087,12 @@
 	struct at91_adc_state *st = iio_priv(idev);
 
 	iio_device_unregister(idev);
-	at91_adc_trigger_remove(idev);
-	at91_adc_buffer_remove(idev);
+	if (!st->touchscreen_type) {
+		at91_adc_trigger_remove(idev);
+		at91_adc_buffer_remove(idev);
+	} else {
+		at91_ts_unregister(st);
+	}
 	clk_disable_unprepare(st->adc_clk);
 	clk_disable_unprepare(st->clk);
 	free_irq(st->irq, idev);
@@ -742,6 +1102,8 @@
 
 #ifdef CONFIG_OF
 static struct at91_adc_caps at91sam9260_caps = {
+	.calc_startup_ticks = calc_startup_ticks_9260,
+	.num_channels = 4,
 	.registers = {
 		.channel_base = AT91_ADC_CHR(0),
 		.drdy_mask = AT91_ADC_DRDY,
@@ -753,6 +1115,9 @@
 };
 
 static struct at91_adc_caps at91sam9g45_caps = {
+	.has_ts = true,
+	.calc_startup_ticks = calc_startup_ticks_9260,	/* same as 9260 */
+	.num_channels = 8,
 	.registers = {
 		.channel_base = AT91_ADC_CHR(0),
 		.drdy_mask = AT91_ADC_DRDY,
@@ -764,6 +1129,12 @@
 };
 
 static struct at91_adc_caps at91sam9x5_caps = {
+	.has_ts = true,
+	.has_tsmr = true,
+	.ts_filter_average = 3,
+	.ts_pen_detect_sensitivity = 2,
+	.calc_startup_ticks = calc_startup_ticks_9x5,
+	.num_channels = 12,
 	.registers = {
 		.channel_base = AT91_ADC_CDR0_9X5,
 		.drdy_mask = AT91_ADC_SR_DRDY_9X5,
@@ -788,7 +1159,7 @@
 	.probe = at91_adc_probe,
 	.remove = at91_adc_remove,
 	.driver = {
-		   .name = "at91_adc",
+		   .name = DRIVER_NAME,
 		   .of_match_table = of_match_ptr(at91_adc_dt_ids),
 	},
 };
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c
index 4fb35d1..6118dce 100644
--- a/drivers/iio/adc/max1363.c
+++ b/drivers/iio/adc/max1363.c
@@ -165,6 +165,8 @@
  * @thresh_low:		low threshold values
  * @vref:		Reference voltage regulator
  * @vref_uv:		Actual (external or internal) reference voltage
+ * @send:		function used to send data to the chip
+ * @recv:		function used to receive data from the chip
  */
 struct max1363_state {
 	struct i2c_client		*client;
@@ -186,6 +188,10 @@
 	s16				thresh_low[8];
 	struct regulator		*vref;
 	u32				vref_uv;
+	int				(*send)(const struct i2c_client *client,
+						const char *buf, int count);
+	int				(*recv)(const struct i2c_client *client,
+						char *buf, int count);
 };
 
 #define MAX1363_MODE_SINGLE(_num, _mask) {				\
@@ -311,13 +317,37 @@
 	return NULL;
 }
 
-static int max1363_write_basic_config(struct i2c_client *client,
-				      unsigned char d1,
-				      unsigned char d2)
+static int max1363_smbus_send(const struct i2c_client *client, const char *buf,
+		int count)
 {
-	u8 tx_buf[2] = {d1, d2};
+	int i, err;
 
-	return i2c_master_send(client, tx_buf, 2);
+	for (i = err = 0; err == 0 && i < count; ++i)
+		err = i2c_smbus_write_byte(client, buf[i]);
+
+	return err ? err : count;
+}
+
+static int max1363_smbus_recv(const struct i2c_client *client, char *buf,
+		int count)
+{
+	int i, ret;
+
+	for (i = 0; i < count; ++i) {
+		ret = i2c_smbus_read_byte(client);
+		if (ret < 0)
+			return ret;
+		buf[i] = ret;
+	}
+
+	return count;
+}
+
+static int max1363_write_basic_config(struct max1363_state *st)
+{
+	u8 tx_buf[2] = { st->setupbyte, st->configbyte };
+
+	return st->send(st->client, tx_buf, 2);
 }
 
 static int max1363_set_scan_mode(struct max1363_state *st)
@@ -327,9 +357,7 @@
 			    | MAX1363_SE_DE_MASK);
 	st->configbyte |= st->current_mode->conf;
 
-	return max1363_write_basic_config(st->client,
-					  st->setupbyte,
-					  st->configbyte);
+	return max1363_write_basic_config(st);
 }
 
 static int max1363_read_single_chan(struct iio_dev *indio_dev,
@@ -366,7 +394,7 @@
 	}
 	if (st->chip_info->bits != 8) {
 		/* Get reading */
-		data = i2c_master_recv(client, rxbuf, 2);
+		data = st->recv(client, rxbuf, 2);
 		if (data < 0) {
 			ret = data;
 			goto error_ret;
@@ -375,7 +403,7 @@
 		  ((1 << st->chip_info->bits) - 1);
 	} else {
 		/* Get reading */
-		data = i2c_master_recv(client, rxbuf, 1);
+		data = st->recv(client, rxbuf, 1);
 		if (data < 0) {
 			ret = data;
 			goto error_ret;
@@ -397,7 +425,6 @@
 {
 	struct max1363_state *st = iio_priv(indio_dev);
 	int ret;
-	unsigned long scale_uv;
 
 	switch (m) {
 	case IIO_CHAN_INFO_RAW:
@@ -406,10 +433,9 @@
 			return ret;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		scale_uv = st->vref_uv >> st->chip_info->bits;
-		*val = scale_uv / 1000;
-		*val2 = (scale_uv % 1000) * 1000;
-		return IIO_VAL_INT_PLUS_MICRO;
+		*val = st->vref_uv / 1000;
+		*val2 = st->chip_info->bits;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	default:
 		return -EINVAL;
 	}
@@ -424,11 +450,21 @@
 	d0m1to2m3, d1m0to3m2,
 };
 
-#define MAX1363_EV_M						\
-	(IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING)	\
-	 | IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING))
+static const struct iio_event_spec max1363_events[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	},
+};
 
-#define MAX1363_CHAN_U(num, addr, si, bits, evmask)			\
+#define MAX1363_CHAN_U(num, addr, si, bits, ev_spec, num_ev_spec)	\
 	{								\
 		.type = IIO_VOLTAGE,					\
 		.indexed = 1,						\
@@ -444,11 +480,12 @@
 			.endianness = IIO_BE,				\
 		},							\
 		.scan_index = si,					\
-		.event_mask = evmask,					\
+		.event_spec = ev_spec,					\
+		.num_event_specs = num_ev_spec,				\
 	}
 
 /* bipolar channel */
-#define MAX1363_CHAN_B(num, num2, addr, si, bits, evmask)		\
+#define MAX1363_CHAN_B(num, num2, addr, si, bits, ev_spec, num_ev_spec)	\
 	{								\
 		.type = IIO_VOLTAGE,					\
 		.differential = 1,					\
@@ -466,28 +503,32 @@
 			.endianness = IIO_BE,				\
 		},							\
 		.scan_index = si,					\
-		.event_mask = evmask,					\
+		.event_spec = ev_spec,					\
+		.num_event_specs = num_ev_spec,				\
 	}
 
-#define MAX1363_4X_CHANS(bits, em) {			\
-	MAX1363_CHAN_U(0, _s0, 0, bits, em),		\
-	MAX1363_CHAN_U(1, _s1, 1, bits, em),		\
-	MAX1363_CHAN_U(2, _s2, 2, bits, em),		\
-	MAX1363_CHAN_U(3, _s3, 3, bits, em),		\
-	MAX1363_CHAN_B(0, 1, d0m1, 4, bits, em),	\
-	MAX1363_CHAN_B(2, 3, d2m3, 5, bits, em),	\
-	MAX1363_CHAN_B(1, 0, d1m0, 6, bits, em),	\
-	MAX1363_CHAN_B(3, 2, d3m2, 7, bits, em),	\
-	IIO_CHAN_SOFT_TIMESTAMP(8)			\
+#define MAX1363_4X_CHANS(bits, ev_spec, num_ev_spec) {			\
+	MAX1363_CHAN_U(0, _s0, 0, bits, ev_spec, num_ev_spec),		\
+	MAX1363_CHAN_U(1, _s1, 1, bits, ev_spec, num_ev_spec),		\
+	MAX1363_CHAN_U(2, _s2, 2, bits, ev_spec, num_ev_spec),		\
+	MAX1363_CHAN_U(3, _s3, 3, bits, ev_spec, num_ev_spec),		\
+	MAX1363_CHAN_B(0, 1, d0m1, 4, bits, ev_spec, num_ev_spec),	\
+	MAX1363_CHAN_B(2, 3, d2m3, 5, bits, ev_spec, num_ev_spec),	\
+	MAX1363_CHAN_B(1, 0, d1m0, 6, bits, ev_spec, num_ev_spec),	\
+	MAX1363_CHAN_B(3, 2, d3m2, 7, bits, ev_spec, num_ev_spec),	\
+	IIO_CHAN_SOFT_TIMESTAMP(8)					\
 	}
 
-static const struct iio_chan_spec max1036_channels[] = MAX1363_4X_CHANS(8, 0);
-static const struct iio_chan_spec max1136_channels[] = MAX1363_4X_CHANS(10, 0);
-static const struct iio_chan_spec max1236_channels[] = MAX1363_4X_CHANS(12, 0);
+static const struct iio_chan_spec max1036_channels[] =
+	MAX1363_4X_CHANS(8, NULL, 0);
+static const struct iio_chan_spec max1136_channels[] =
+	MAX1363_4X_CHANS(10, NULL, 0);
+static const struct iio_chan_spec max1236_channels[] =
+	MAX1363_4X_CHANS(12, NULL, 0);
 static const struct iio_chan_spec max1361_channels[] =
-	MAX1363_4X_CHANS(10, MAX1363_EV_M);
+	MAX1363_4X_CHANS(10, max1363_events, ARRAY_SIZE(max1363_events));
 static const struct iio_chan_spec max1363_channels[] =
-	MAX1363_4X_CHANS(12, MAX1363_EV_M);
+	MAX1363_4X_CHANS(12, max1363_events, ARRAY_SIZE(max1363_events));
 
 /* Applies to max1236, max1237 */
 static const enum max1363_modes max1236_mode_list[] = {
@@ -511,32 +552,32 @@
 	d6m7to8m9, d6m7to10m11, d7m6to9m8, d7m6to11m10,
 };
 
-#define MAX1363_12X_CHANS(bits) {			\
-	MAX1363_CHAN_U(0, _s0, 0, bits, 0),		\
-	MAX1363_CHAN_U(1, _s1, 1, bits, 0),		\
-	MAX1363_CHAN_U(2, _s2, 2, bits, 0),		\
-	MAX1363_CHAN_U(3, _s3, 3, bits, 0),		\
-	MAX1363_CHAN_U(4, _s4, 4, bits, 0),		\
-	MAX1363_CHAN_U(5, _s5, 5, bits, 0),		\
-	MAX1363_CHAN_U(6, _s6, 6, bits, 0),		\
-	MAX1363_CHAN_U(7, _s7, 7, bits, 0),		\
-	MAX1363_CHAN_U(8, _s8, 8, bits, 0),		\
-	MAX1363_CHAN_U(9, _s9, 9, bits, 0),		\
-	MAX1363_CHAN_U(10, _s10, 10, bits, 0),		\
-	MAX1363_CHAN_U(11, _s11, 11, bits, 0),		\
-	MAX1363_CHAN_B(0, 1, d0m1, 12, bits, 0),	\
-	MAX1363_CHAN_B(2, 3, d2m3, 13, bits, 0),	\
-	MAX1363_CHAN_B(4, 5, d4m5, 14, bits, 0),	\
-	MAX1363_CHAN_B(6, 7, d6m7, 15, bits, 0),	\
-	MAX1363_CHAN_B(8, 9, d8m9, 16, bits, 0),	\
-	MAX1363_CHAN_B(10, 11, d10m11, 17, bits, 0),	\
-	MAX1363_CHAN_B(1, 0, d1m0, 18, bits, 0),	\
-	MAX1363_CHAN_B(3, 2, d3m2, 19, bits, 0),	\
-	MAX1363_CHAN_B(5, 4, d5m4, 20, bits, 0),	\
-	MAX1363_CHAN_B(7, 6, d7m6, 21, bits, 0),	\
-	MAX1363_CHAN_B(9, 8, d9m8, 22, bits, 0),	\
-	MAX1363_CHAN_B(11, 10, d11m10, 23, bits, 0),	\
-	IIO_CHAN_SOFT_TIMESTAMP(24)			\
+#define MAX1363_12X_CHANS(bits) {				\
+	MAX1363_CHAN_U(0, _s0, 0, bits, NULL, 0),		\
+	MAX1363_CHAN_U(1, _s1, 1, bits, NULL, 0),		\
+	MAX1363_CHAN_U(2, _s2, 2, bits, NULL, 0),		\
+	MAX1363_CHAN_U(3, _s3, 3, bits, NULL, 0),		\
+	MAX1363_CHAN_U(4, _s4, 4, bits, NULL, 0),		\
+	MAX1363_CHAN_U(5, _s5, 5, bits, NULL, 0),		\
+	MAX1363_CHAN_U(6, _s6, 6, bits, NULL, 0),		\
+	MAX1363_CHAN_U(7, _s7, 7, bits, NULL, 0),		\
+	MAX1363_CHAN_U(8, _s8, 8, bits, NULL, 0),		\
+	MAX1363_CHAN_U(9, _s9, 9, bits, NULL, 0),		\
+	MAX1363_CHAN_U(10, _s10, 10, bits, NULL, 0),		\
+	MAX1363_CHAN_U(11, _s11, 11, bits, NULL, 0),		\
+	MAX1363_CHAN_B(0, 1, d0m1, 12, bits, NULL, 0),		\
+	MAX1363_CHAN_B(2, 3, d2m3, 13, bits, NULL, 0),		\
+	MAX1363_CHAN_B(4, 5, d4m5, 14, bits, NULL, 0),		\
+	MAX1363_CHAN_B(6, 7, d6m7, 15, bits, NULL, 0),		\
+	MAX1363_CHAN_B(8, 9, d8m9, 16, bits, NULL, 0),		\
+	MAX1363_CHAN_B(10, 11, d10m11, 17, bits, NULL, 0),	\
+	MAX1363_CHAN_B(1, 0, d1m0, 18, bits, NULL, 0),		\
+	MAX1363_CHAN_B(3, 2, d3m2, 19, bits, NULL, 0),		\
+	MAX1363_CHAN_B(5, 4, d5m4, 20, bits, NULL, 0),		\
+	MAX1363_CHAN_B(7, 6, d7m6, 21, bits, NULL, 0),		\
+	MAX1363_CHAN_B(9, 8, d9m8, 22, bits, NULL, 0),		\
+	MAX1363_CHAN_B(11, 10, d11m10, 23, bits, NULL, 0),	\
+	IIO_CHAN_SOFT_TIMESTAMP(24)				\
 	}
 static const struct iio_chan_spec max1038_channels[] = MAX1363_12X_CHANS(8);
 static const struct iio_chan_spec max1138_channels[] = MAX1363_12X_CHANS(10);
@@ -561,22 +602,22 @@
 };
 
 #define MAX1363_8X_CHANS(bits) {			\
-	MAX1363_CHAN_U(0, _s0, 0, bits, 0),		\
-	MAX1363_CHAN_U(1, _s1, 1, bits, 0),		\
-	MAX1363_CHAN_U(2, _s2, 2, bits, 0),		\
-	MAX1363_CHAN_U(3, _s3, 3, bits, 0),		\
-	MAX1363_CHAN_U(4, _s4, 4, bits, 0),		\
-	MAX1363_CHAN_U(5, _s5, 5, bits, 0),		\
-	MAX1363_CHAN_U(6, _s6, 6, bits, 0),		\
-	MAX1363_CHAN_U(7, _s7, 7, bits, 0),		\
-	MAX1363_CHAN_B(0, 1, d0m1, 8, bits, 0),	\
-	MAX1363_CHAN_B(2, 3, d2m3, 9, bits, 0),	\
-	MAX1363_CHAN_B(4, 5, d4m5, 10, bits, 0),	\
-	MAX1363_CHAN_B(6, 7, d6m7, 11, bits, 0),	\
-	MAX1363_CHAN_B(1, 0, d1m0, 12, bits, 0),	\
-	MAX1363_CHAN_B(3, 2, d3m2, 13, bits, 0),	\
-	MAX1363_CHAN_B(5, 4, d5m4, 14, bits, 0),	\
-	MAX1363_CHAN_B(7, 6, d7m6, 15, bits, 0),	\
+	MAX1363_CHAN_U(0, _s0, 0, bits, NULL, 0),	\
+	MAX1363_CHAN_U(1, _s1, 1, bits, NULL, 0),	\
+	MAX1363_CHAN_U(2, _s2, 2, bits, NULL, 0),	\
+	MAX1363_CHAN_U(3, _s3, 3, bits, NULL, 0),	\
+	MAX1363_CHAN_U(4, _s4, 4, bits, NULL, 0),	\
+	MAX1363_CHAN_U(5, _s5, 5, bits, NULL, 0),	\
+	MAX1363_CHAN_U(6, _s6, 6, bits, NULL, 0),	\
+	MAX1363_CHAN_U(7, _s7, 7, bits, NULL, 0),	\
+	MAX1363_CHAN_B(0, 1, d0m1, 8, bits, NULL, 0),	\
+	MAX1363_CHAN_B(2, 3, d2m3, 9, bits, NULL, 0),	\
+	MAX1363_CHAN_B(4, 5, d4m5, 10, bits, NULL, 0),	\
+	MAX1363_CHAN_B(6, 7, d6m7, 11, bits, NULL, 0),	\
+	MAX1363_CHAN_B(1, 0, d1m0, 12, bits, NULL, 0),	\
+	MAX1363_CHAN_B(3, 2, d3m2, 13, bits, NULL, 0),	\
+	MAX1363_CHAN_B(5, 4, d5m4, 14, bits, NULL, 0),	\
+	MAX1363_CHAN_B(7, 6, d7m6, 15, bits, NULL, 0),	\
 	IIO_CHAN_SOFT_TIMESTAMP(16)			\
 }
 static const struct iio_chan_spec max11602_channels[] = MAX1363_8X_CHANS(8);
@@ -588,10 +629,10 @@
 };
 
 #define MAX1363_2X_CHANS(bits) {			\
-	MAX1363_CHAN_U(0, _s0, 0, bits, 0),		\
-	MAX1363_CHAN_U(1, _s1, 1, bits, 0),		\
-	MAX1363_CHAN_B(0, 1, d0m1, 2, bits, 0),	\
-	MAX1363_CHAN_B(1, 0, d1m0, 3, bits, 0),	\
+	MAX1363_CHAN_U(0, _s0, 0, bits, NULL, 0),	\
+	MAX1363_CHAN_U(1, _s1, 1, bits, NULL, 0),	\
+	MAX1363_CHAN_B(0, 1, d0m1, 2, bits, NULL, 0),	\
+	MAX1363_CHAN_B(1, 0, d1m0, 3, bits, NULL, 0),	\
 	IIO_CHAN_SOFT_TIMESTAMP(4)			\
 	}
 
@@ -686,20 +727,22 @@
 		"133000 665000 33300 16600 8300 4200 2000 1000");
 
 static int max1363_read_thresh(struct iio_dev *indio_dev,
-			       u64 event_code,
-			       int *val)
+	const struct iio_chan_spec *chan, enum iio_event_type type,
+	enum iio_event_direction dir, enum iio_event_info info, int *val,
+	int *val2)
 {
 	struct max1363_state *st = iio_priv(indio_dev);
-	if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING)
-		*val = st->thresh_low[IIO_EVENT_CODE_EXTRACT_CHAN(event_code)];
+	if (dir == IIO_EV_DIR_FALLING)
+		*val = st->thresh_low[chan->channel];
 	else
-		*val = st->thresh_high[IIO_EVENT_CODE_EXTRACT_CHAN(event_code)];
-	return 0;
+		*val = st->thresh_high[chan->channel];
+	return IIO_VAL_INT;
 }
 
 static int max1363_write_thresh(struct iio_dev *indio_dev,
-				u64 event_code,
-				int val)
+	const struct iio_chan_spec *chan, enum iio_event_type type,
+	enum iio_event_direction dir, enum iio_event_info info, int val,
+	int val2)
 {
 	struct max1363_state *st = iio_priv(indio_dev);
 	/* make it handle signed correctly as well */
@@ -714,13 +757,15 @@
 		break;
 	}
 
-	switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
+	switch (dir) {
 	case IIO_EV_DIR_FALLING:
-		st->thresh_low[IIO_EVENT_CODE_EXTRACT_CHAN(event_code)] = val;
+		st->thresh_low[chan->channel] = val;
 		break;
 	case IIO_EV_DIR_RISING:
-		st->thresh_high[IIO_EVENT_CODE_EXTRACT_CHAN(event_code)] = val;
+		st->thresh_high[chan->channel] = val;
 		break;
+	default:
+		return -EINVAL;
 	}
 
 	return 0;
@@ -755,24 +800,25 @@
 	u8 tx[2] = { st->setupbyte,
 		     MAX1363_MON_INT_ENABLE | (st->monitor_speed << 1) | 0xF0 };
 
-	i2c_master_recv(st->client, &rx, 1);
+	st->recv(st->client, &rx, 1);
 	mask = rx;
 	for_each_set_bit(loc, &mask, 8)
 		iio_push_event(indio_dev, max1363_event_codes[loc], timestamp);
-	i2c_master_send(st->client, tx, 2);
+	st->send(st->client, tx, 2);
 
 	return IRQ_HANDLED;
 }
 
 static int max1363_read_event_config(struct iio_dev *indio_dev,
-				     u64 event_code)
+	const struct iio_chan_spec *chan, enum iio_event_type type,
+	enum iio_event_direction dir)
 {
 	struct max1363_state *st = iio_priv(indio_dev);
 	int val;
-	int number = IIO_EVENT_CODE_EXTRACT_CHAN(event_code);
+	int number = chan->channel;
 
 	mutex_lock(&indio_dev->mlock);
-	if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING)
+	if (dir == IIO_EV_DIR_FALLING)
 		val = (1 << number) & st->mask_low;
 	else
 		val = (1 << number) & st->mask_high;
@@ -794,9 +840,7 @@
 		st->setupbyte &= ~MAX1363_SETUP_MONITOR_SETUP;
 		st->configbyte &= ~MAX1363_SCAN_MASK;
 		st->monitor_on = false;
-		return max1363_write_basic_config(st->client,
-						st->setupbyte,
-						st->configbyte);
+		return max1363_write_basic_config(st);
 	}
 
 	/* Ensure we are in the relevant mode */
@@ -858,7 +902,7 @@
 		}
 
 
-	ret = i2c_master_send(st->client, tx_buf, len);
+	ret = st->send(st->client, tx_buf, len);
 	if (ret < 0)
 		goto error_ret;
 	if (ret != len) {
@@ -875,7 +919,7 @@
 	 */
 	tx_buf[0] = st->setupbyte;
 	tx_buf[1] = MAX1363_MON_INT_ENABLE | (st->monitor_speed << 1) | 0xF0;
-	ret = i2c_master_send(st->client, tx_buf, 2);
+	ret = st->send(st->client, tx_buf, 2);
 	if (ret < 0)
 		goto error_ret;
 	if (ret != 2) {
@@ -917,17 +961,17 @@
 }
 
 static int max1363_write_event_config(struct iio_dev *indio_dev,
-				      u64 event_code,
-				      int state)
+	const struct iio_chan_spec *chan, enum iio_event_type type,
+	enum iio_event_direction dir, int state)
 {
 	int ret = 0;
 	struct max1363_state *st = iio_priv(indio_dev);
 	u16 unifiedmask;
-	int number = IIO_EVENT_CODE_EXTRACT_CHAN(event_code);
+	int number = chan->channel;
 
 	mutex_lock(&indio_dev->mlock);
 	unifiedmask = st->mask_low | st->mask_high;
-	if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING) {
+	if (dir == IIO_EV_DIR_FALLING) {
 
 		if (state == 0)
 			st->mask_low &= ~(1 << number);
@@ -995,10 +1039,10 @@
 };
 
 static const struct iio_info max1363_info = {
-	.read_event_value = &max1363_read_thresh,
-	.write_event_value = &max1363_write_thresh,
-	.read_event_config = &max1363_read_event_config,
-	.write_event_config = &max1363_write_event_config,
+	.read_event_value_new = &max1363_read_thresh,
+	.write_event_value_new = &max1363_write_thresh,
+	.read_event_config_new = &max1363_read_event_config,
+	.write_event_config_new = &max1363_write_event_config,
 	.read_raw = &max1363_read_raw,
 	.update_scan_mode = &max1363_update_scan_mode,
 	.driver_module = THIS_MODULE,
@@ -1436,7 +1480,6 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct max1363_state *st = iio_priv(indio_dev);
-	s64 time_ns;
 	__u8 *rxbuf;
 	int b_sent;
 	size_t d_size;
@@ -1464,17 +1507,13 @@
 	if (rxbuf == NULL)
 		goto done;
 	if (st->chip_info->bits != 8)
-		b_sent = i2c_master_recv(st->client, rxbuf, numvals*2);
+		b_sent = st->recv(st->client, rxbuf, numvals * 2);
 	else
-		b_sent = i2c_master_recv(st->client, rxbuf, numvals);
+		b_sent = st->recv(st->client, rxbuf, numvals);
 	if (b_sent < 0)
 		goto done_free;
 
-	time_ns = iio_get_time_ns();
-
-	if (indio_dev->scan_timestamp)
-		memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns));
-	iio_push_to_buffers(indio_dev, rxbuf);
+	iio_push_to_buffers_with_timestamp(indio_dev, rxbuf, iio_get_time_ns());
 
 done_free:
 	kfree(rxbuf);
@@ -1484,12 +1523,6 @@
 	return IRQ_HANDLED;
 }
 
-static const struct iio_buffer_setup_ops max1363_buffered_setup_ops = {
-	.postenable = &iio_triggered_buffer_postenable,
-	.preenable = &iio_sw_buffer_preenable,
-	.predisable = &iio_triggered_buffer_predisable,
-};
-
 static int max1363_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
@@ -1543,6 +1576,18 @@
 		st->vref_uv = vref_uv;
 	}
 
+	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		st->send = i2c_master_send;
+		st->recv = i2c_master_recv;
+	} else if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)
+			&& st->chip_info->bits == 8) {
+		st->send = max1363_smbus_send;
+		st->recv = max1363_smbus_recv;
+	} else {
+		ret = -EOPNOTSUPP;
+		goto error_disable_reg;
+	}
+
 	ret = max1363_alloc_scan_masks(indio_dev);
 	if (ret)
 		goto error_disable_reg;
@@ -1559,7 +1604,7 @@
 		goto error_disable_reg;
 
 	ret = iio_triggered_buffer_setup(indio_dev, NULL,
-		&max1363_trigger_handler, &max1363_buffered_setup_ops);
+		&max1363_trigger_handler, NULL);
 	if (ret)
 		goto error_disable_reg;
 
diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c
new file mode 100644
index 0000000..1294832
--- /dev/null
+++ b/drivers/iio/adc/mcp3422.c
@@ -0,0 +1,410 @@
+/*
+ * mcp3422.c - driver for the Microchip mcp3422/3/4 chip family
+ *
+ * Copyright (C) 2013, Angelo Compagnucci
+ * Author: Angelo Compagnucci <angelo.compagnucci@gmail.com>
+ *
+ * Datasheet: http://ww1.microchip.com/downloads/en/devicedoc/22088b.pdf
+ *
+ * This driver exports the value of analog input voltage to sysfs, the
+ * voltage unit is nV.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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/err.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/sysfs.h>
+#include <linux/of.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+/* Masks */
+#define MCP3422_CHANNEL_MASK	0x60
+#define MCP3422_PGA_MASK	0x03
+#define MCP3422_SRATE_MASK	0x0C
+#define MCP3422_SRATE_240	0x0
+#define MCP3422_SRATE_60	0x1
+#define MCP3422_SRATE_15	0x2
+#define MCP3422_SRATE_3	0x3
+#define MCP3422_PGA_1	0
+#define MCP3422_PGA_2	1
+#define MCP3422_PGA_4	2
+#define MCP3422_PGA_8	3
+#define MCP3422_CONT_SAMPLING	0x10
+
+#define MCP3422_CHANNEL(config)	(((config) & MCP3422_CHANNEL_MASK) >> 5)
+#define MCP3422_PGA(config)	((config) & MCP3422_PGA_MASK)
+#define MCP3422_SAMPLE_RATE(config)	(((config) & MCP3422_SRATE_MASK) >> 2)
+
+#define MCP3422_CHANNEL_VALUE(value) (((value) << 5) & MCP3422_CHANNEL_MASK)
+#define MCP3422_PGA_VALUE(value) ((value) & MCP3422_PGA_MASK)
+#define MCP3422_SAMPLE_RATE_VALUE(value) ((value << 2) & MCP3422_SRATE_MASK)
+
+#define MCP3422_CHAN(_index) \
+	{ \
+		.type = IIO_VOLTAGE, \
+		.indexed = 1, \
+		.channel = _index, \
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \
+				| BIT(IIO_CHAN_INFO_SCALE), \
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+	}
+
+/* LSB is in nV to eliminate floating point */
+static const u32 rates_to_lsb[] = {1000000, 250000, 62500, 15625};
+
+/*
+ *  scales calculated as:
+ *  rates_to_lsb[sample_rate] / (1 << pga);
+ *  pga is 1 for 0, 2
+ */
+
+static const int mcp3422_scales[4][4] = {
+	{ 1000000, 250000, 62500, 15625 },
+	{ 500000 , 125000, 31250, 7812 },
+	{ 250000 , 62500 , 15625, 3906 },
+	{ 125000 , 31250 , 7812 , 1953 } };
+
+/* Constant msleep times for data acquisitions */
+static const int mcp3422_read_times[4] = {
+	[MCP3422_SRATE_240] = 1000 / 240,
+	[MCP3422_SRATE_60] = 1000 / 60,
+	[MCP3422_SRATE_15] = 1000 / 15,
+	[MCP3422_SRATE_3] = 1000 / 3 };
+
+/* sample rates to integer conversion table */
+static const int mcp3422_sample_rates[4] = {
+	[MCP3422_SRATE_240] = 240,
+	[MCP3422_SRATE_60] = 60,
+	[MCP3422_SRATE_15] = 15,
+	[MCP3422_SRATE_3] = 3 };
+
+/* sample rates to sign extension table */
+static const int mcp3422_sign_extend[4] = {
+	[MCP3422_SRATE_240] = 12,
+	[MCP3422_SRATE_60] = 14,
+	[MCP3422_SRATE_15] = 16,
+	[MCP3422_SRATE_3] = 18 };
+
+/* Client data (each client gets its own) */
+struct mcp3422 {
+	struct i2c_client *i2c;
+	u8 config;
+	u8 pga[4];
+	struct mutex lock;
+};
+
+static int mcp3422_update_config(struct mcp3422 *adc, u8 newconfig)
+{
+	int ret;
+
+	mutex_lock(&adc->lock);
+
+	ret = i2c_master_send(adc->i2c, &newconfig, 1);
+	if (ret > 0) {
+		adc->config = newconfig;
+		ret = 0;
+	}
+
+	mutex_unlock(&adc->lock);
+
+	return ret;
+}
+
+static int mcp3422_read(struct mcp3422 *adc, int *value, u8 *config)
+{
+	int ret = 0;
+	u8 sample_rate = MCP3422_SAMPLE_RATE(adc->config);
+	u8 buf[4] = {0, 0, 0, 0};
+	u32 temp;
+
+	if (sample_rate == MCP3422_SRATE_3) {
+		ret = i2c_master_recv(adc->i2c, buf, 4);
+		temp = buf[0] << 16 | buf[1] << 8 | buf[2];
+		*config = buf[3];
+	} else {
+		ret = i2c_master_recv(adc->i2c, buf, 3);
+		temp = buf[0] << 8 | buf[1];
+		*config = buf[2];
+	}
+
+	*value = sign_extend32(temp, mcp3422_sign_extend[sample_rate]);
+
+	return ret;
+}
+
+static int mcp3422_read_channel(struct mcp3422 *adc,
+				struct iio_chan_spec const *channel, int *value)
+{
+	int ret;
+	u8 config;
+	u8 req_channel = channel->channel;
+
+	if (req_channel != MCP3422_CHANNEL(adc->config)) {
+		config = adc->config;
+		config &= ~MCP3422_CHANNEL_MASK;
+		config |= MCP3422_CHANNEL_VALUE(req_channel);
+		config &= ~MCP3422_PGA_MASK;
+		config |= MCP3422_PGA_VALUE(adc->pga[req_channel]);
+		ret = mcp3422_update_config(adc, config);
+		if (ret < 0)
+			return ret;
+		msleep(mcp3422_read_times[MCP3422_SAMPLE_RATE(adc->config)]);
+	}
+
+	return mcp3422_read(adc, value, &config);
+}
+
+static int mcp3422_read_raw(struct iio_dev *iio,
+			struct iio_chan_spec const *channel, int *val1,
+			int *val2, long mask)
+{
+	struct mcp3422 *adc = iio_priv(iio);
+	int err;
+
+	u8 sample_rate = MCP3422_SAMPLE_RATE(adc->config);
+	u8 pga		 = MCP3422_PGA(adc->config);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		err = mcp3422_read_channel(adc, channel, val1);
+		if (err < 0)
+			return -EINVAL;
+		return IIO_VAL_INT;
+
+	case IIO_CHAN_INFO_SCALE:
+
+		*val1 = 0;
+		*val2 = mcp3422_scales[sample_rate][pga];
+		return IIO_VAL_INT_PLUS_NANO;
+
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val1 = mcp3422_sample_rates[MCP3422_SAMPLE_RATE(adc->config)];
+		return IIO_VAL_INT;
+
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+static int mcp3422_write_raw(struct iio_dev *iio,
+			struct iio_chan_spec const *channel, int val1,
+			int val2, long mask)
+{
+	struct mcp3422 *adc = iio_priv(iio);
+	u8 temp;
+	u8 config = adc->config;
+	u8 req_channel = channel->channel;
+	u8 sample_rate = MCP3422_SAMPLE_RATE(config);
+	u8 i;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SCALE:
+		if (val1 != 0)
+			return -EINVAL;
+
+		for (i = 0; i < ARRAY_SIZE(mcp3422_scales[0]); i++) {
+			if (val2 == mcp3422_scales[sample_rate][i]) {
+				adc->pga[req_channel] = i;
+
+				config &= ~MCP3422_CHANNEL_MASK;
+				config |= MCP3422_CHANNEL_VALUE(req_channel);
+				config &= ~MCP3422_PGA_MASK;
+				config |= MCP3422_PGA_VALUE(adc->pga[req_channel]);
+
+				return mcp3422_update_config(adc, config);
+			}
+		}
+		return -EINVAL;
+
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		switch (val1) {
+		case 240:
+			temp = MCP3422_SRATE_240;
+			break;
+		case 60:
+			temp = MCP3422_SRATE_60;
+			break;
+		case 15:
+			temp = MCP3422_SRATE_15;
+			break;
+		case 3:
+			temp = MCP3422_SRATE_3;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		config &= ~MCP3422_CHANNEL_MASK;
+		config |= MCP3422_CHANNEL_VALUE(req_channel);
+		config &= ~MCP3422_SRATE_MASK;
+		config |= MCP3422_SAMPLE_RATE_VALUE(temp);
+
+		return mcp3422_update_config(adc, config);
+
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+static int mcp3422_write_raw_get_fmt(struct iio_dev *indio_dev,
+		struct iio_chan_spec const *chan, long mask)
+{
+	switch (mask) {
+	case IIO_CHAN_INFO_SCALE:
+		return IIO_VAL_INT_PLUS_NANO;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		return IIO_VAL_INT_PLUS_MICRO;
+	default:
+		return -EINVAL;
+	}
+}
+
+static ssize_t mcp3422_show_scales(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mcp3422 *adc = iio_priv(dev_to_iio_dev(dev));
+	u8 sample_rate = MCP3422_SAMPLE_RATE(adc->config);
+
+	return sprintf(buf, "0.%09u 0.%09u 0.%09u 0.%09u\n",
+		mcp3422_scales[sample_rate][0],
+		mcp3422_scales[sample_rate][1],
+		mcp3422_scales[sample_rate][2],
+		mcp3422_scales[sample_rate][3]);
+}
+
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("240 60 15 3");
+static IIO_DEVICE_ATTR(in_voltage_scale_available, S_IRUGO,
+		mcp3422_show_scales, NULL, 0);
+
+static struct attribute *mcp3422_attributes[] = {
+	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
+	&iio_dev_attr_in_voltage_scale_available.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group mcp3422_attribute_group = {
+	.attrs = mcp3422_attributes,
+};
+
+static const struct iio_chan_spec mcp3422_channels[] = {
+	MCP3422_CHAN(0),
+	MCP3422_CHAN(1),
+};
+
+static const struct iio_chan_spec mcp3424_channels[] = {
+	MCP3422_CHAN(0),
+	MCP3422_CHAN(1),
+	MCP3422_CHAN(2),
+	MCP3422_CHAN(3),
+};
+
+static const struct iio_info mcp3422_info = {
+	.read_raw = mcp3422_read_raw,
+	.write_raw = mcp3422_write_raw,
+	.write_raw_get_fmt = mcp3422_write_raw_get_fmt,
+	.attrs = &mcp3422_attribute_group,
+	.driver_module = THIS_MODULE,
+};
+
+static int mcp3422_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct iio_dev *indio_dev;
+	struct mcp3422 *adc;
+	int err;
+	u8 config;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+		return -ENODEV;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*adc));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	adc = iio_priv(indio_dev);
+	adc->i2c = client;
+
+	mutex_init(&adc->lock);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->name = dev_name(&client->dev);
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->info = &mcp3422_info;
+
+	switch ((unsigned int)(id->driver_data)) {
+	case 2:
+	case 3:
+		indio_dev->channels = mcp3422_channels;
+		indio_dev->num_channels = ARRAY_SIZE(mcp3422_channels);
+		break;
+	case 4:
+		indio_dev->channels = mcp3424_channels;
+		indio_dev->num_channels = ARRAY_SIZE(mcp3424_channels);
+		break;
+	}
+
+	/* meaningful default configuration */
+	config = (MCP3422_CONT_SAMPLING
+		| MCP3422_CHANNEL_VALUE(1)
+		| MCP3422_PGA_VALUE(MCP3422_PGA_1)
+		| MCP3422_SAMPLE_RATE_VALUE(MCP3422_SRATE_240));
+	mcp3422_update_config(adc, config);
+
+	err = iio_device_register(indio_dev);
+	if (err < 0)
+		return err;
+
+	i2c_set_clientdata(client, indio_dev);
+
+	return 0;
+}
+
+static int mcp3422_remove(struct i2c_client *client)
+{
+	iio_device_unregister(i2c_get_clientdata(client));
+	return 0;
+}
+
+static const struct i2c_device_id mcp3422_id[] = {
+	{ "mcp3422", 2 },
+	{ "mcp3423", 3 },
+	{ "mcp3424", 4 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mcp3422_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id mcp3422_of_match[] = {
+	{ .compatible = "mcp3422" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, mcp3422_of_match);
+#endif
+
+static struct i2c_driver mcp3422_driver = {
+	.driver = {
+		.name = "mcp3422",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(mcp3422_of_match),
+	},
+	.probe = mcp3422_probe,
+	.remove = mcp3422_remove,
+	.id_table = mcp3422_id,
+};
+module_i2c_driver(mcp3422_driver);
+
+MODULE_AUTHOR("Angelo Compagnucci <angelo.compagnucci@gmail.com>");
+MODULE_DESCRIPTION("Microchip mcp3422/3/4 driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/nau7802.c b/drivers/iio/adc/nau7802.c
index bdf0346..54c5bab 100644
--- a/drivers/iio/adc/nau7802.c
+++ b/drivers/iio/adc/nau7802.c
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/wait.h>
 #include <linux/log2.h>
+#include <linux/of.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -569,7 +570,7 @@
 	.id_table = nau7802_i2c_id,
 	.driver = {
 		   .name = "nau7802",
-		   .of_match_table = of_match_ptr(nau7802_dt_ids),
+		   .of_match_table = nau7802_dt_ids,
 	},
 };
 
diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c
index ee5f72b..b3a82b4 100644
--- a/drivers/iio/adc/ti-adc081c.c
+++ b/drivers/iio/adc/ti-adc081c.c
@@ -9,6 +9,7 @@
 #include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
+#include <linux/of.h>
 
 #include <linux/iio/iio.h>
 #include <linux/regulator/consumer.h>
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index a952538..728411e 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -28,12 +28,16 @@
 #include <linux/iio/driver.h>
 
 #include <linux/mfd/ti_am335x_tscadc.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/kfifo_buf.h>
 
 struct tiadc_device {
 	struct ti_tscadc_dev *mfd_tscadc;
 	int channels;
 	u8 channel_line[8];
 	u8 channel_step[8];
+	int buffer_en_ch_steps;
+	u16 data[8];
 };
 
 static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
@@ -56,8 +60,14 @@
 	return step_en;
 }
 
-static void tiadc_step_config(struct tiadc_device *adc_dev)
+static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
 {
+	return 1 << adc_dev->channel_step[chan];
+}
+
+static void tiadc_step_config(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
 	unsigned int stepconfig;
 	int i, steps;
 
@@ -72,7 +82,11 @@
 	 */
 
 	steps = TOTAL_STEPS - adc_dev->channels;
-	stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
+	if (iio_buffer_enabled(indio_dev))
+		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1
+					| STEPCONFIG_MODE_SWCNT;
+	else
+		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
 
 	for (i = 0; i < adc_dev->channels; i++) {
 		int chan;
@@ -85,9 +99,175 @@
 		adc_dev->channel_step[i] = steps;
 		steps++;
 	}
-
 }
 
+static irqreturn_t tiadc_irq_h(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	unsigned int status, config;
+	status = tiadc_readl(adc_dev, REG_IRQSTATUS);
+
+	/*
+	 * ADC and touchscreen share the IRQ line.
+	 * FIFO0 interrupts are used by TSC. Handle FIFO1 IRQs here only
+	 */
+	if (status & IRQENB_FIFO1OVRRUN) {
+		/* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */
+		config = tiadc_readl(adc_dev, REG_CTRL);
+		config &= ~(CNTRLREG_TSCSSENB);
+		tiadc_writel(adc_dev, REG_CTRL, config);
+		tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN
+				| IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES);
+		tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB));
+		return IRQ_HANDLED;
+	} else if (status & IRQENB_FIFO1THRES) {
+		/* Disable irq and wake worker thread */
+		tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES);
+		return IRQ_WAKE_THREAD;
+	}
+
+	return IRQ_NONE;
+}
+
+static irqreturn_t tiadc_worker_h(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int i, k, fifo1count, read;
+	u16 *data = adc_dev->data;
+
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (k = 0; k < fifo1count; k = k + i) {
+		for (i = 0; i < (indio_dev->scan_bytes)/2; i++) {
+			read = tiadc_readl(adc_dev, REG_FIFO1);
+			data[i] = read & FIFOREAD_DATA_MASK;
+		}
+		iio_push_to_buffers(indio_dev, (u8 *) data);
+	}
+
+	tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES);
+	tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
+
+	return IRQ_HANDLED;
+}
+
+static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int i, fifo1count, read;
+
+	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
+				IRQENB_FIFO1OVRRUN |
+				IRQENB_FIFO1UNDRFLW));
+
+	/* Flush FIFO. Needed in corner cases in simultaneous tsc/adc use */
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (i = 0; i < fifo1count; i++)
+		read = tiadc_readl(adc_dev, REG_FIFO1);
+
+	return 0;
+}
+
+static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct iio_buffer *buffer = indio_dev->buffer;
+	unsigned int enb = 0;
+	u8 bit;
+
+	tiadc_step_config(indio_dev);
+	for_each_set_bit(bit, buffer->scan_mask, adc_dev->channels)
+		enb |= (get_adc_step_bit(adc_dev, bit) << 1);
+	adc_dev->buffer_en_ch_steps = enb;
+
+	am335x_tsc_se_set(adc_dev->mfd_tscadc, enb);
+
+	tiadc_writel(adc_dev,  REG_IRQSTATUS, IRQENB_FIFO1THRES
+				| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
+	tiadc_writel(adc_dev,  REG_IRQENABLE, IRQENB_FIFO1THRES
+				| IRQENB_FIFO1OVRRUN);
+
+	return 0;
+}
+
+static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int fifo1count, i, read;
+
+	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
+				IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
+	am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
+
+	/* Flush FIFO of leftover data in the time it takes to disable adc */
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (i = 0; i < fifo1count; i++)
+		read = tiadc_readl(adc_dev, REG_FIFO1);
+
+	return 0;
+}
+
+static int tiadc_buffer_postdisable(struct iio_dev *indio_dev)
+{
+	tiadc_step_config(indio_dev);
+
+	return 0;
+}
+
+static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = {
+	.preenable = &tiadc_buffer_preenable,
+	.postenable = &tiadc_buffer_postenable,
+	.predisable = &tiadc_buffer_predisable,
+	.postdisable = &tiadc_buffer_postdisable,
+};
+
+static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev,
+	irqreturn_t (*pollfunc_bh)(int irq, void *p),
+	irqreturn_t (*pollfunc_th)(int irq, void *p),
+	int irq,
+	unsigned long flags,
+	const struct iio_buffer_setup_ops *setup_ops)
+{
+	int ret;
+
+	indio_dev->buffer = iio_kfifo_allocate(indio_dev);
+	if (!indio_dev->buffer)
+		return -ENOMEM;
+
+	ret = request_threaded_irq(irq,	pollfunc_th, pollfunc_bh,
+				flags, indio_dev->name, indio_dev);
+	if (ret)
+		goto error_kfifo_free;
+
+	indio_dev->setup_ops = setup_ops;
+	indio_dev->modes |= INDIO_BUFFER_HARDWARE;
+
+	ret = iio_buffer_register(indio_dev,
+				  indio_dev->channels,
+				  indio_dev->num_channels);
+	if (ret)
+		goto error_free_irq;
+
+	return 0;
+
+error_free_irq:
+	free_irq(irq, indio_dev);
+error_kfifo_free:
+	iio_kfifo_free(indio_dev->buffer);
+	return ret;
+}
+
+static void tiadc_iio_buffered_hardware_remove(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+
+	free_irq(adc_dev->mfd_tscadc->irq, indio_dev);
+	iio_kfifo_free(indio_dev->buffer);
+	iio_buffer_unregister(indio_dev);
+}
+
+
 static const char * const chan_name_ain[] = {
 	"AIN0",
 	"AIN1",
@@ -120,9 +300,10 @@
 		chan->channel = adc_dev->channel_line[i];
 		chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
 		chan->datasheet_name = chan_name_ain[chan->channel];
+		chan->scan_index = i;
 		chan->scan_type.sign = 'u';
 		chan->scan_type.realbits = 12;
-		chan->scan_type.storagebits = 32;
+		chan->scan_type.storagebits = 16;
 	}
 
 	indio_dev->channels = chan_array;
@@ -142,11 +323,14 @@
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
 	int i, map_val;
 	unsigned int fifo1count, read, stepid;
-	u32 step = UINT_MAX;
 	bool found = false;
 	u32 step_en;
 	unsigned long timeout = jiffies + usecs_to_jiffies
 				(IDLE_TIMEOUT * adc_dev->channels);
+
+	if (iio_buffer_enabled(indio_dev))
+		return -EBUSY;
+
 	step_en = get_adc_step_mask(adc_dev);
 	am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
 
@@ -168,15 +352,6 @@
 	 * Hence we need to flush out this data.
 	 */
 
-	for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) {
-		if (chan->channel == adc_dev->channel_line[i]) {
-			step = adc_dev->channel_step[i];
-			break;
-		}
-	}
-	if (WARN_ON_ONCE(step == UINT_MAX))
-		return -EINVAL;
-
 	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
 	for (i = 0; i < fifo1count; i++) {
 		read = tiadc_readl(adc_dev, REG_FIFO1);
@@ -186,7 +361,7 @@
 		if (stepid == map_val) {
 			read = read & FIFOREAD_DATA_MASK;
 			found = true;
-			*val = read;
+			*val = (u16) read;
 		}
 	}
 
@@ -237,20 +412,33 @@
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &tiadc_info;
 
-	tiadc_step_config(adc_dev);
+	tiadc_step_config(indio_dev);
+	tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
 
 	err = tiadc_channel_init(indio_dev, adc_dev->channels);
 	if (err < 0)
 		return err;
 
-	err = iio_device_register(indio_dev);
+	err = tiadc_iio_buffered_hardware_setup(indio_dev,
+		&tiadc_worker_h,
+		&tiadc_irq_h,
+		adc_dev->mfd_tscadc->irq,
+		IRQF_SHARED,
+		&tiadc_buffer_setup_ops);
+
 	if (err)
 		goto err_free_channels;
 
+	err = iio_device_register(indio_dev);
+	if (err)
+		goto err_buffer_unregister;
+
 	platform_set_drvdata(pdev, indio_dev);
 
 	return 0;
 
+err_buffer_unregister:
+	tiadc_iio_buffered_hardware_remove(indio_dev);
 err_free_channels:
 	tiadc_channels_remove(indio_dev);
 	return err;
@@ -263,6 +451,7 @@
 	u32 step_en;
 
 	iio_device_unregister(indio_dev);
+	tiadc_iio_buffered_hardware_remove(indio_dev);
 	tiadc_channels_remove(indio_dev);
 
 	step_en = get_adc_step_mask(adc_dev);
@@ -301,7 +490,7 @@
 	restore &= ~(CNTRLREG_POWERDOWN);
 	tiadc_writel(adc_dev, REG_CTRL, restore);
 
-	tiadc_step_config(adc_dev);
+	tiadc_step_config(indio_dev);
 
 	return 0;
 }
@@ -326,7 +515,7 @@
 		.name   = "TI-am335x-adc",
 		.owner	= THIS_MODULE,
 		.pm	= TIADC_PM_OPS,
-		.of_match_table = of_match_ptr(ti_adc_dt_ids),
+		.of_match_table = ti_adc_dt_ids,
 	},
 	.probe	= tiadc_probe,
 	.remove	= tiadc_remove,
diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c
index 0ea96c0..53e1c64 100644
--- a/drivers/iio/adc/twl6030-gpadc.c
+++ b/drivers/iio/adc/twl6030-gpadc.c
@@ -887,7 +887,7 @@
 	int irq;
 	int ret;
 
-	match = of_match_device(of_match_ptr(of_twl6030_match_tbl), dev);
+	match = of_match_device(of_twl6030_match_tbl, dev);
 	if (!match)
 		return -EINVAL;
 
@@ -948,9 +948,7 @@
 	indio_dev->channels = pdata->iio_channels;
 	indio_dev->num_channels = pdata->nchannels;
 
-	ret = iio_device_register(indio_dev);
-
-	return ret;
+	return iio_device_register(indio_dev);
 }
 
 static int twl6030_gpadc_remove(struct platform_device *pdev)
diff --git a/drivers/iio/buffer_cb.c b/drivers/iio/buffer_cb.c
index 415f3c6..2d9c6f8 100644
--- a/drivers/iio/buffer_cb.c
+++ b/drivers/iio/buffer_cb.c
@@ -7,26 +7,36 @@
 
 struct iio_cb_buffer {
 	struct iio_buffer buffer;
-	int (*cb)(u8 *data, void *private);
+	int (*cb)(const void *data, void *private);
 	void *private;
 	struct iio_channel *channels;
 };
 
-static int iio_buffer_cb_store_to(struct iio_buffer *buffer, u8 *data)
+static struct iio_cb_buffer *buffer_to_cb_buffer(struct iio_buffer *buffer)
 {
-	struct iio_cb_buffer *cb_buff = container_of(buffer,
-						     struct iio_cb_buffer,
-						     buffer);
+	return container_of(buffer, struct iio_cb_buffer, buffer);
+}
 
+static int iio_buffer_cb_store_to(struct iio_buffer *buffer, const void *data)
+{
+	struct iio_cb_buffer *cb_buff = buffer_to_cb_buffer(buffer);
 	return cb_buff->cb(data, cb_buff->private);
 }
 
-static struct iio_buffer_access_funcs iio_cb_access = {
+static void iio_buffer_cb_release(struct iio_buffer *buffer)
+{
+	struct iio_cb_buffer *cb_buff = buffer_to_cb_buffer(buffer);
+	kfree(cb_buff->buffer.scan_mask);
+	kfree(cb_buff);
+}
+
+static const struct iio_buffer_access_funcs iio_cb_access = {
 	.store_to = &iio_buffer_cb_store_to,
+	.release = &iio_buffer_cb_release,
 };
 
 struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev,
-					     int (*cb)(u8 *data,
+					     int (*cb)(const void *data,
 						       void *private),
 					     void *private)
 {
@@ -104,9 +114,8 @@
 
 void iio_channel_release_all_cb(struct iio_cb_buffer *cb_buff)
 {
-	kfree(cb_buff->buffer.scan_mask);
 	iio_channel_release_all(cb_buff->channels);
-	kfree(cb_buff);
+	iio_buffer_put(&cb_buff->buffer);
 }
 EXPORT_SYMBOL_GPL(iio_channel_release_all_cb);
 
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
index 87419c4..b6e77e0 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
@@ -34,6 +34,12 @@
 	struct hid_sensor_common *st = iio_trigger_get_drvdata(trig);
 	int state_val;
 
+	if (state) {
+		if (sensor_hub_device_open(st->hsdev))
+			return -EIO;
+	} else
+		sensor_hub_device_close(st->hsdev);
+
 	state_val = state ? 1 : 0;
 	if (IS_ENABLED(CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS))
 		++state_val;
diff --git a/drivers/iio/common/st_sensors/st_sensors_buffer.c b/drivers/iio/common/st_sensors/st_sensors_buffer.c
index 71a2c5f..1665c8e 100644
--- a/drivers/iio/common/st_sensors/st_sensors_buffer.c
+++ b/drivers/iio/common/st_sensors/st_sensors_buffer.c
@@ -113,11 +113,8 @@
 	if (len < 0)
 		goto st_sensors_get_buffer_element_error;
 
-	if (indio_dev->scan_timestamp)
-		*(s64 *)((u8 *)sdata->buffer_data +
-				ALIGN(len, sizeof(s64))) = pf->timestamp;
-
-	iio_push_to_buffers(indio_dev, sdata->buffer_data);
+	iio_push_to_buffers_with_timestamp(indio_dev, sdata->buffer_data,
+		pf->timestamp);
 
 st_sensors_get_buffer_element_error:
 	iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c
index 965ee22..7ba1ef2 100644
--- a/drivers/iio/common/st_sensors/st_sensors_core.c
+++ b/drivers/iio/common/st_sensors/st_sensors_core.c
@@ -198,21 +198,17 @@
 }
 EXPORT_SYMBOL(st_sensors_set_axis_enable);
 
-int st_sensors_init_sensor(struct iio_dev *indio_dev,
-					struct st_sensors_platform_data *pdata)
+static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev,
+				       struct st_sensors_platform_data *pdata)
 {
-	int err;
 	struct st_sensor_data *sdata = iio_priv(indio_dev);
 
-	mutex_init(&sdata->tb.buf_lock);
-
 	switch (pdata->drdy_int_pin) {
 	case 1:
 		if (sdata->sensor->drdy_irq.mask_int1 == 0) {
 			dev_err(&indio_dev->dev,
 					"DRDY on INT1 not available.\n");
-			err = -EINVAL;
-			goto init_error;
+			return -EINVAL;
 		}
 		sdata->drdy_int_pin = 1;
 		break;
@@ -220,39 +216,53 @@
 		if (sdata->sensor->drdy_irq.mask_int2 == 0) {
 			dev_err(&indio_dev->dev,
 					"DRDY on INT2 not available.\n");
-			err = -EINVAL;
-			goto init_error;
+			return -EINVAL;
 		}
 		sdata->drdy_int_pin = 2;
 		break;
 	default:
 		dev_err(&indio_dev->dev, "DRDY on pdata not valid.\n");
-		err = -EINVAL;
-		goto init_error;
+		return -EINVAL;
 	}
 
+	return 0;
+}
+
+int st_sensors_init_sensor(struct iio_dev *indio_dev,
+					struct st_sensors_platform_data *pdata)
+{
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+	int err = 0;
+
+	mutex_init(&sdata->tb.buf_lock);
+
+	if (pdata)
+		err = st_sensors_set_drdy_int_pin(indio_dev, pdata);
+
 	err = st_sensors_set_enable(indio_dev, false);
 	if (err < 0)
-		goto init_error;
+		return err;
 
-	err = st_sensors_set_fullscale(indio_dev,
-						sdata->current_fullscale->num);
-	if (err < 0)
-		goto init_error;
+	if (sdata->current_fullscale) {
+		err = st_sensors_set_fullscale(indio_dev,
+					       sdata->current_fullscale->num);
+		if (err < 0)
+			return err;
+	} else
+		dev_info(&indio_dev->dev, "Full-scale not possible\n");
 
 	err = st_sensors_set_odr(indio_dev, sdata->odr);
 	if (err < 0)
-		goto init_error;
+		return err;
 
 	/* set BDU */
 	err = st_sensors_write_data_with_mask(indio_dev,
 			sdata->sensor->bdu.addr, sdata->sensor->bdu.mask, true);
 	if (err < 0)
-		goto init_error;
+		return err;
 
 	err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
 
-init_error:
 	return err;
 }
 EXPORT_SYMBOL(st_sensors_init_sensor);
@@ -263,6 +273,9 @@
 	u8 drdy_mask;
 	struct st_sensor_data *sdata = iio_priv(indio_dev);
 
+	if (!sdata->sensor->drdy_irq.addr)
+		return 0;
+
 	/* Enable/Disable the interrupt generator 1. */
 	if (sdata->sensor->drdy_irq.ig1.en_addr > 0) {
 		err = st_sensors_write_data_with_mask(indio_dev,
@@ -318,10 +331,8 @@
 	unsigned int byte_for_channel = ch->scan_type.storagebits >> 3;
 
 	outdata = kmalloc(byte_for_channel, GFP_KERNEL);
-	if (!outdata) {
-		err = -EINVAL;
-		goto st_sensors_read_axis_data_error;
-	}
+	if (!outdata)
+		return -ENOMEM;
 
 	err = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
 				ch->address, byte_for_channel,
@@ -336,7 +347,7 @@
 
 st_sensors_free_memory:
 	kfree(outdata);
-st_sensors_read_axis_data_error:
+
 	return err;
 }
 
@@ -349,28 +360,25 @@
 	mutex_lock(&indio_dev->mlock);
 	if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
 		err = -EBUSY;
-		goto read_error;
+		goto out;
 	} else {
 		err = st_sensors_set_enable(indio_dev, true);
 		if (err < 0)
-			goto read_error;
+			goto out;
 
 		msleep((sdata->sensor->bootime * 1000) / sdata->odr);
 		err = st_sensors_read_axis_data(indio_dev, ch, val);
 		if (err < 0)
-			goto read_error;
+			goto out;
 
 		*val = *val >> ch->scan_type.shift;
 
 		err = st_sensors_set_enable(indio_dev, false);
 	}
+out:
 	mutex_unlock(&indio_dev->mlock);
 
 	return err;
-
-read_error:
-	mutex_unlock(&indio_dev->mlock);
-	return err;
 }
 EXPORT_SYMBOL(st_sensors_read_info_raw);
 
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 3c6a78a..f378ca8 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -57,7 +57,7 @@
 	  Say yes here to build support for Analog Devices AD5300, AD5301, AD5310,
 	  AD5311, AD5320, AD5321, AD5444, AD5446, AD5450, AD5451, AD5452, AD5453,
 	  AD5512A, AD5541A, AD5542A, AD5543, AD5553, AD5601, AD5602, AD5611, AD5612,
-	  AD5620, AD5621, AD5622, AD5640, AD5660, AD5662 DACs.
+	  AD5620, AD5621, AD5622, AD5640, AD5641, AD5660, AD5662 DACs.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad5446.
diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c
index a3a52be..cb9c636 100644
--- a/drivers/iio/dac/ad5064.c
+++ b/drivers/iio/dac/ad5064.c
@@ -239,10 +239,9 @@
 		if (scale_uv < 0)
 			return scale_uv;
 
-		scale_uv = (scale_uv * 100) >> chan->scan_type.realbits;
-		*val =  scale_uv / 100000;
-		*val2 = (scale_uv % 100000) * 10;
-		return IIO_VAL_INT_PLUS_MICRO;
+		*val = scale_uv / 1000;
+		*val2 = chan->scan_type.realbits;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	default:
 		break;
 	}
@@ -285,8 +284,9 @@
 		.name = "powerdown",
 		.read = ad5064_read_dac_powerdown,
 		.write = ad5064_write_dac_powerdown,
+		.shared = IIO_SEPARATE,
 	},
-	IIO_ENUM("powerdown_mode", false, &ad5064_powerdown_mode_enum),
+	IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5064_powerdown_mode_enum),
 	IIO_ENUM_AVAILABLE("powerdown_mode", &ad5064_powerdown_mode_enum),
 	{ },
 };
diff --git a/drivers/iio/dac/ad5360.c b/drivers/iio/dac/ad5360.c
index d2da71e..b968af5 100644
--- a/drivers/iio/dac/ad5360.c
+++ b/drivers/iio/dac/ad5360.c
@@ -379,15 +379,14 @@
 		*val = ret >> chan->scan_type.shift;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		/* vout = 4 * vref * dac_code */
-		scale_uv = ad5360_get_channel_vref(st, chan->channel) * 4 * 100;
+		scale_uv = ad5360_get_channel_vref(st, chan->channel);
 		if (scale_uv < 0)
 			return scale_uv;
 
-		scale_uv >>= (chan->scan_type.realbits);
-		*val =  scale_uv / 100000;
-		*val2 = (scale_uv % 100000) * 10;
-		return IIO_VAL_INT_PLUS_MICRO;
+		/* vout = 4 * vref * dac_code */
+		*val = scale_uv * 4 / 1000;
+		*val2 = chan->scan_type.realbits;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	case IIO_CHAN_INFO_CALIBBIAS:
 		ret = ad5360_read(indio_dev, AD5360_READBACK_OFFSET,
 			chan->address);
diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c
index 1c44ae3..a59ff0e 100644
--- a/drivers/iio/dac/ad5380.c
+++ b/drivers/iio/dac/ad5380.c
@@ -204,7 +204,6 @@
 	struct iio_chan_spec const *chan, int *val, int *val2, long info)
 {
 	struct ad5380_state *st = iio_priv(indio_dev);
-	unsigned long scale_uv;
 	int ret;
 
 	switch (info) {
@@ -225,10 +224,9 @@
 		val -= (1 << chan->scan_type.realbits) / 2;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		scale_uv = ((2 * st->vref) >> chan->scan_type.realbits) * 100;
-		*val =  scale_uv / 100000;
-		*val2 = (scale_uv % 100000) * 10;
-		return IIO_VAL_INT_PLUS_MICRO;
+		*val = 2 * st->vref;
+		*val2 = chan->scan_type.realbits;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	default:
 		break;
 	}
@@ -247,8 +245,10 @@
 		.name = "powerdown",
 		.read = ad5380_read_dac_powerdown,
 		.write = ad5380_write_dac_powerdown,
+		.shared = IIO_SEPARATE,
 	},
-	IIO_ENUM("powerdown_mode", true, &ad5380_powerdown_mode_enum),
+	IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE,
+		 &ad5380_powerdown_mode_enum),
 	IIO_ENUM_AVAILABLE("powerdown_mode", &ad5380_powerdown_mode_enum),
 	{ },
 };
@@ -269,72 +269,72 @@
 	[ID_AD5380_3] = {
 		.channel_template = AD5380_CHANNEL(14),
 		.num_channels = 40,
-		.int_vref = 1250000,
+		.int_vref = 1250,
 	},
 	[ID_AD5380_5] = {
 		.channel_template = AD5380_CHANNEL(14),
 		.num_channels = 40,
-		.int_vref = 2500000,
+		.int_vref = 2500,
 	},
 	[ID_AD5381_3] = {
 		.channel_template = AD5380_CHANNEL(12),
 		.num_channels = 16,
-		.int_vref = 1250000,
+		.int_vref = 1250,
 	},
 	[ID_AD5381_5] = {
 		.channel_template = AD5380_CHANNEL(12),
 		.num_channels = 16,
-		.int_vref = 2500000,
+		.int_vref = 2500,
 	},
 	[ID_AD5382_3] = {
 		.channel_template = AD5380_CHANNEL(14),
 		.num_channels = 32,
-		.int_vref = 1250000,
+		.int_vref = 1250,
 	},
 	[ID_AD5382_5] = {
 		.channel_template = AD5380_CHANNEL(14),
 		.num_channels = 32,
-		.int_vref = 2500000,
+		.int_vref = 2500,
 	},
 	[ID_AD5383_3] = {
 		.channel_template = AD5380_CHANNEL(12),
 		.num_channels = 32,
-		.int_vref = 1250000,
+		.int_vref = 1250,
 	},
 	[ID_AD5383_5] = {
 		.channel_template = AD5380_CHANNEL(12),
 		.num_channels = 32,
-		.int_vref = 2500000,
+		.int_vref = 2500,
 	},
 	[ID_AD5390_3] = {
 		.channel_template = AD5380_CHANNEL(14),
 		.num_channels = 16,
-		.int_vref = 1250000,
+		.int_vref = 1250,
 	},
 	[ID_AD5390_5] = {
 		.channel_template = AD5380_CHANNEL(14),
 		.num_channels = 16,
-		.int_vref = 2500000,
+		.int_vref = 2500,
 	},
 	[ID_AD5391_3] = {
 		.channel_template = AD5380_CHANNEL(12),
 		.num_channels = 16,
-		.int_vref = 1250000,
+		.int_vref = 1250,
 	},
 	[ID_AD5391_5] = {
 		.channel_template = AD5380_CHANNEL(12),
 		.num_channels = 16,
-		.int_vref = 2500000,
+		.int_vref = 2500,
 	},
 	[ID_AD5392_3] = {
 		.channel_template = AD5380_CHANNEL(14),
 		.num_channels = 8,
-		.int_vref = 1250000,
+		.int_vref = 1250,
 	},
 	[ID_AD5392_5] = {
 		.channel_template = AD5380_CHANNEL(14),
 		.num_channels = 8,
-		.int_vref = 2500000,
+		.int_vref = 2500,
 	},
 };
 
@@ -393,7 +393,7 @@
 		return ret;
 	}
 
-	if (st->chip_info->int_vref == 2500000)
+	if (st->chip_info->int_vref == 2500)
 		ctrl |= AD5380_CTRL_INT_VREF_2V5;
 
 	st->vref_reg = devm_regulator_get(dev, "vref");
@@ -409,7 +409,7 @@
 		if (ret < 0)
 			goto error_disable_reg;
 
-		st->vref = ret;
+		st->vref = ret / 1000;
 	} else {
 		st->vref = st->chip_info->int_vref;
 		ctrl |= AD5380_CTRL_INT_VREF_EN;
diff --git a/drivers/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c
index 1f78b14..3eeaa82 100644
--- a/drivers/iio/dac/ad5421.c
+++ b/drivers/iio/dac/ad5421.c
@@ -80,6 +80,29 @@
 	} data[2] ____cacheline_aligned;
 };
 
+static const struct iio_event_spec ad5421_current_event[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	},
+};
+
+static const struct iio_event_spec ad5421_temp_event[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	},
+};
+
 static const struct iio_chan_spec ad5421_channels[] = {
 	{
 		.type = IIO_CURRENT,
@@ -92,13 +115,14 @@
 		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
 			BIT(IIO_CHAN_INFO_OFFSET),
 		.scan_type = IIO_ST('u', 16, 16, 0),
-		.event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) |
-			IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING),
+		.event_spec = ad5421_current_event,
+		.num_event_specs = ARRAY_SIZE(ad5421_current_event),
 	},
 	{
 		.type = IIO_TEMP,
 		.channel = -1,
-		.event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
+		.event_spec = ad5421_temp_event,
+		.num_event_specs = ARRAY_SIZE(ad5421_temp_event),
 	},
 };
 
@@ -281,18 +305,11 @@
 	return (min * (1 << 16)) / (max - min);
 }
 
-static inline unsigned int ad5421_get_scale(struct ad5421_state *st)
-{
-	unsigned int min, max;
-
-	ad5421_get_current_min_max(st, &min, &max);
-	return ((max - min) * 1000) / (1 << 16);
-}
-
 static int ad5421_read_raw(struct iio_dev *indio_dev,
 	struct iio_chan_spec const *chan, int *val, int *val2, long m)
 {
 	struct ad5421_state *st = iio_priv(indio_dev);
+	unsigned int min, max;
 	int ret;
 
 	if (chan->type != IIO_CURRENT)
@@ -306,9 +323,10 @@
 		*val = ret;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		*val = 0;
-		*val2 = ad5421_get_scale(st);
-		return IIO_VAL_INT_PLUS_MICRO;
+		ad5421_get_current_min_max(st, &min, &max);
+		*val = max - min;
+		*val2 = (1 << 16) * 1000;
+		return IIO_VAL_FRACTIONAL;
 	case IIO_CHAN_INFO_OFFSET:
 		*val = ad5421_get_offset(st);
 		return IIO_VAL_INT;
@@ -359,15 +377,15 @@
 }
 
 static int ad5421_write_event_config(struct iio_dev *indio_dev,
-	u64 event_code, int state)
+	const struct iio_chan_spec *chan, enum iio_event_type type,
+	enum iio_event_direction dir, int state)
 {
 	struct ad5421_state *st = iio_priv(indio_dev);
 	unsigned int mask;
 
-	switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
+	switch (chan->type) {
 	case IIO_CURRENT:
-		if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
-			IIO_EV_DIR_RISING)
+		if (dir == IIO_EV_DIR_RISING)
 			mask = AD5421_FAULT_OVER_CURRENT;
 		else
 			mask = AD5421_FAULT_UNDER_CURRENT;
@@ -390,15 +408,15 @@
 }
 
 static int ad5421_read_event_config(struct iio_dev *indio_dev,
-	u64 event_code)
+	const struct iio_chan_spec *chan, enum iio_event_type type,
+	enum iio_event_direction dir)
 {
 	struct ad5421_state *st = iio_priv(indio_dev);
 	unsigned int mask;
 
-	switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
+	switch (chan->type) {
 	case IIO_CURRENT:
-		if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
-			IIO_EV_DIR_RISING)
+		if (dir == IIO_EV_DIR_RISING)
 			mask = AD5421_FAULT_OVER_CURRENT;
 		else
 			mask = AD5421_FAULT_UNDER_CURRENT;
@@ -413,12 +431,14 @@
 	return (bool)(st->fault_mask & mask);
 }
 
-static int ad5421_read_event_value(struct iio_dev *indio_dev, u64 event_code,
-	int *val)
+static int ad5421_read_event_value(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, enum iio_event_type type,
+	enum iio_event_direction dir, enum iio_event_info info, int *val,
+	int *val2)
 {
 	int ret;
 
-	switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
+	switch (chan->type) {
 	case IIO_CURRENT:
 		ret = ad5421_read(indio_dev, AD5421_REG_DAC_DATA);
 		if (ret < 0)
@@ -432,15 +452,15 @@
 		return -EINVAL;
 	}
 
-	return 0;
+	return IIO_VAL_INT;
 }
 
 static const struct iio_info ad5421_info = {
 	.read_raw =		ad5421_read_raw,
 	.write_raw =		ad5421_write_raw,
-	.read_event_config =	ad5421_read_event_config,
-	.write_event_config =	ad5421_write_event_config,
-	.read_event_value =	ad5421_read_event_value,
+	.read_event_config_new = ad5421_read_event_config,
+	.write_event_config_new = ad5421_write_event_config,
+	.read_event_value_new =	ad5421_read_event_value,
 	.driver_module =	THIS_MODULE,
 };
 
@@ -494,13 +514,7 @@
 			return ret;
 	}
 
-	ret = iio_device_register(indio_dev);
-	if (ret) {
-		dev_err(&spi->dev, "Failed to register iio device: %d\n", ret);
-		return ret;
-	}
-
-	return 0;
+	return iio_device_register(indio_dev);
 }
 
 static int ad5421_remove(struct spi_device *spi)
diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c
index 96e9ed4..1263b0e 100644
--- a/drivers/iio/dac/ad5446.c
+++ b/drivers/iio/dac/ad5446.c
@@ -132,8 +132,9 @@
 		.name = "powerdown",
 		.read = ad5446_read_dac_powerdown,
 		.write = ad5446_write_dac_powerdown,
+		.shared = IIO_SEPARATE,
 	},
-	IIO_ENUM("powerdown_mode", false, &ad5446_powerdown_mode_enum),
+	IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5446_powerdown_mode_enum),
 	IIO_ENUM_AVAILABLE("powerdown_mode", &ad5446_powerdown_mode_enum),
 	{ },
 };
@@ -162,18 +163,15 @@
 			   long m)
 {
 	struct ad5446_state *st = iio_priv(indio_dev);
-	unsigned long scale_uv;
 
 	switch (m) {
 	case IIO_CHAN_INFO_RAW:
 		*val = st->cached_val;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits;
-		*val =  scale_uv / 1000;
-		*val2 = (scale_uv % 1000) * 1000;
-		return IIO_VAL_INT_PLUS_MICRO;
-
+		*val = st->vref_mv;
+		*val2 = chan->scan_type.realbits;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	}
 	return -EINVAL;
 }
@@ -329,6 +327,7 @@
 	ID_AD5601,
 	ID_AD5611,
 	ID_AD5621,
+	ID_AD5641,
 	ID_AD5620_2500,
 	ID_AD5620_1250,
 	ID_AD5640_2500,
@@ -391,6 +390,10 @@
 		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
 		.write = ad5446_write,
 	},
+	[ID_AD5641] = {
+		.channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0),
+		.write = ad5446_write,
+	},
 	[ID_AD5620_2500] = {
 		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
 		.int_vref_mv = 2500,
@@ -445,6 +448,7 @@
 	{"ad5601", ID_AD5601},
 	{"ad5611", ID_AD5611},
 	{"ad5621", ID_AD5621},
+	{"ad5641", ID_AD5641},
 	{"ad5620-2500", ID_AD5620_2500}, /* AD5620/40/60: */
 	{"ad5620-1250", ID_AD5620_1250}, /* part numbers may look differently */
 	{"ad5640-2500", ID_AD5640_2500},
diff --git a/drivers/iio/dac/ad5449.c b/drivers/iio/dac/ad5449.c
index fff7d07..82e208f 100644
--- a/drivers/iio/dac/ad5449.c
+++ b/drivers/iio/dac/ad5449.c
@@ -101,7 +101,6 @@
 {
 	struct ad5449 *st = iio_priv(indio_dev);
 	int ret;
-	struct spi_message msg;
 	struct spi_transfer t[] = {
 		{
 			.tx_buf = &st->data[0],
@@ -114,15 +113,11 @@
 		},
 	};
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&t[0], &msg);
-	spi_message_add_tail(&t[1], &msg);
-
 	mutex_lock(&indio_dev->mlock);
 	st->data[0] = cpu_to_be16(addr << 12);
 	st->data[1] = cpu_to_be16(AD5449_CMD_NOOP);
 
-	ret = spi_sync(st->spi, &msg);
+	ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
 	if (ret < 0)
 		goto out_unlock;
 
diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c
index caffb16..c0957a9 100644
--- a/drivers/iio/dac/ad5504.c
+++ b/drivers/iio/dac/ad5504.c
@@ -100,7 +100,6 @@
 			   long m)
 {
 	struct ad5504_state *st = iio_priv(indio_dev);
-	unsigned long scale_uv;
 	int ret;
 
 	switch (m) {
@@ -113,11 +112,9 @@
 
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits;
-		*val =  scale_uv / 1000;
-		*val2 = (scale_uv % 1000) * 1000;
-		return IIO_VAL_INT_PLUS_MICRO;
-
+		*val = st->vref_mv;
+		*val2 = chan->scan_type.realbits;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	}
 	return -EINVAL;
 }
@@ -248,8 +245,10 @@
 		.name = "powerdown",
 		.read = ad5504_read_dac_powerdown,
 		.write = ad5504_write_dac_powerdown,
+		.shared = IIO_SEPARATE,
 	},
-	IIO_ENUM("powerdown_mode", true, &ad5504_powerdown_mode_enum),
+	IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE,
+		 &ad5504_powerdown_mode_enum),
 	IIO_ENUM_AVAILABLE("powerdown_mode", &ad5504_powerdown_mode_enum),
 	{ },
 };
diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c
index 714af75..774dd96 100644
--- a/drivers/iio/dac/ad5624r_spi.c
+++ b/drivers/iio/dac/ad5624r_spi.c
@@ -50,15 +50,12 @@
 			   long m)
 {
 	struct ad5624r_state *st = iio_priv(indio_dev);
-	unsigned long scale_uv;
 
 	switch (m) {
 	case IIO_CHAN_INFO_SCALE:
-		scale_uv = (st->vref_mv * 1000) >> chan->scan_type.realbits;
-		*val =  scale_uv / 1000;
-		*val2 = (scale_uv % 1000) * 1000;
-		return IIO_VAL_INT_PLUS_MICRO;
-
+		*val = st->vref_mv;
+		*val2 = chan->scan_type.realbits;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	}
 	return -EINVAL;
 }
@@ -163,8 +160,10 @@
 		.name = "powerdown",
 		.read = ad5624r_read_dac_powerdown,
 		.write = ad5624r_write_dac_powerdown,
+		.shared = IIO_SEPARATE,
 	},
-	IIO_ENUM("powerdown_mode", true, &ad5624r_powerdown_mode_enum),
+	IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE,
+		 &ad5624r_powerdown_mode_enum),
 	IIO_ENUM_AVAILABLE("powerdown_mode", &ad5624r_powerdown_mode_enum),
 	{ },
 };
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 57825ea..30e506e 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -201,7 +201,6 @@
 			   long m)
 {
 	struct ad5686_state *st = iio_priv(indio_dev);
-	unsigned long scale_uv;
 	int ret;
 
 	switch (m) {
@@ -213,14 +212,10 @@
 			return ret;
 		*val = ret;
 		return IIO_VAL_INT;
-		break;
 	case IIO_CHAN_INFO_SCALE:
-		scale_uv = (st->vref_mv * 100000)
-			>> (chan->scan_type.realbits);
-		*val =  scale_uv / 100000;
-		*val2 = (scale_uv % 100000) * 10;
-		return IIO_VAL_INT_PLUS_MICRO;
-
+		*val = st->vref_mv;
+		*val2 = chan->scan_type.realbits;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	}
 	return -EINVAL;
 }
@@ -265,8 +260,9 @@
 		.name = "powerdown",
 		.read = ad5686_read_dac_powerdown,
 		.write = ad5686_write_dac_powerdown,
+		.shared = IIO_SEPARATE,
 	},
-	IIO_ENUM("powerdown_mode", false, &ad5686_powerdown_mode_enum),
+	IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5686_powerdown_mode_enum),
 	IIO_ENUM_AVAILABLE("powerdown_mode", &ad5686_powerdown_mode_enum),
 	{ },
 };
diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c
index 36a4361..9a78d5a 100644
--- a/drivers/iio/dac/ad5755.c
+++ b/drivers/iio/dac/ad5755.c
@@ -253,15 +253,6 @@
 	return (min * (1 << chan->scan_type.realbits)) / (max - min);
 }
 
-static inline int ad5755_get_scale(struct ad5755_state *st,
-	struct iio_chan_spec const *chan)
-{
-	int min, max;
-
-	ad5755_get_min_max(st, chan, &min, &max);
-	return ((max - min) * 1000000000ULL) >> chan->scan_type.realbits;
-}
-
 static int ad5755_chan_reg_info(struct ad5755_state *st,
 	struct iio_chan_spec const *chan, long info, bool write,
 	unsigned int *reg, unsigned int *shift, unsigned int *offset)
@@ -303,13 +294,15 @@
 {
 	struct ad5755_state *st = iio_priv(indio_dev);
 	unsigned int reg, shift, offset;
+	int min, max;
 	int ret;
 
 	switch (info) {
 	case IIO_CHAN_INFO_SCALE:
-		*val = 0;
-		*val2 = ad5755_get_scale(st, chan);
-		return IIO_VAL_INT_PLUS_NANO;
+		ad5755_get_min_max(st, chan, &min, &max);
+		*val = max - min;
+		*val2 = chan->scan_type.realbits;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	case IIO_CHAN_INFO_OFFSET:
 		*val = ad5755_get_offset(st, chan);
 		return IIO_VAL_INT;
@@ -386,6 +379,7 @@
 		.name = "powerdown",
 		.read = ad5755_read_powerdown,
 		.write = ad5755_write_powerdown,
+		.shared = IIO_SEPARATE,
 	},
 	{ },
 };
@@ -595,13 +589,7 @@
 	if (ret)
 		return ret;
 
-	ret = iio_device_register(indio_dev);
-	if (ret) {
-		dev_err(&spi->dev, "Failed to register iio device: %d\n", ret);
-		return ret;
-	}
-
-	return 0;
+	return iio_device_register(indio_dev);
 }
 
 static int ad5755_remove(struct spi_device *spi)
diff --git a/drivers/iio/dac/ad5764.c b/drivers/iio/dac/ad5764.c
index df7e028..a8ff5b2 100644
--- a/drivers/iio/dac/ad5764.c
+++ b/drivers/iio/dac/ad5764.c
@@ -217,7 +217,6 @@
 	struct iio_chan_spec const *chan, int *val, int *val2, long info)
 {
 	struct ad5764_state *st = iio_priv(indio_dev);
-	unsigned long scale_uv;
 	unsigned int reg;
 	int vref;
 	int ret;
@@ -245,15 +244,14 @@
 		*val = sign_extend32(*val, 5);
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		/* vout = 4 * vref + ((dac_code / 65535) - 0.5) */
+		/* vout = 4 * vref + ((dac_code / 65536) - 0.5) */
 		vref = ad5764_get_channel_vref(st, chan->channel);
 		if (vref < 0)
 			return vref;
 
-		scale_uv = (vref * 4 * 100) >> chan->scan_type.realbits;
-		*val = scale_uv / 100000;
-		*val2 = (scale_uv % 100000) * 10;
-		return IIO_VAL_INT_PLUS_MICRO;
+		*val = vref * 4 / 1000;
+		*val2 = chan->scan_type.realbits;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	case IIO_CHAN_INFO_OFFSET:
 		*val = -(1 << chan->scan_type.realbits) / 2;
 		return IIO_VAL_INT;
diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c
index ce74589..d64acbd 100644
--- a/drivers/iio/dac/ad5791.c
+++ b/drivers/iio/dac/ad5791.c
@@ -270,9 +270,9 @@
 		*val >>= chan->scan_type.shift;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		*val = 0;
-		*val2 = (((u64)st->vref_mv) * 1000000ULL) >> chan->scan_type.realbits;
-		return IIO_VAL_INT_PLUS_MICRO;
+		*val = st->vref_mv;
+		*val2 = (1 << chan->scan_type.realbits) - 1;
+		return IIO_VAL_FRACTIONAL;
 	case IIO_CHAN_INFO_OFFSET:
 		val64 = (((u64)st->vref_neg_mv) << chan->scan_type.realbits);
 		do_div(val64, st->vref_mv);
@@ -287,11 +287,12 @@
 static const struct iio_chan_spec_ext_info ad5791_ext_info[] = {
 	{
 		.name = "powerdown",
-		.shared = true,
+		.shared = IIO_SHARED_BY_TYPE,
 		.read = ad5791_read_dac_powerdown,
 		.write = ad5791_write_dac_powerdown,
 	},
-	IIO_ENUM("powerdown_mode", true, &ad5791_powerdown_mode_enum),
+	IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE,
+		 &ad5791_powerdown_mode_enum),
 	IIO_ENUM_AVAILABLE("powerdown_mode", &ad5791_powerdown_mode_enum),
 	{ },
 };
diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c
index ed2d276..d0505fd 100644
--- a/drivers/iio/dac/ad7303.c
+++ b/drivers/iio/dac/ad7303.c
@@ -169,6 +169,7 @@
 		.name = "powerdown",
 		.read = ad7303_read_dac_powerdown,
 		.write = ad7303_write_dac_powerdown,
+		.shared = IIO_SEPARATE,
 	},
 	{ },
 };
diff --git a/drivers/iio/dac/max517.c b/drivers/iio/dac/max517.c
index 83adcbf..6e19035 100644
--- a/drivers/iio/dac/max517.c
+++ b/drivers/iio/dac/max517.c
@@ -82,15 +82,13 @@
 			   long m)
 {
 	struct max517_data *data = iio_priv(indio_dev);
-	unsigned int scale_uv;
 
 	switch (m) {
 	case IIO_CHAN_INFO_SCALE:
 		/* Corresponds to Vref / 2^(bits) */
-		scale_uv = (data->vref_mv[chan->channel] * 1000) >> 8;
-		*val =  scale_uv / 1000000;
-		*val2 = scale_uv % 1000000;
-		return IIO_VAL_INT_PLUS_MICRO;
+		*val = data->vref_mv[chan->channel];
+		*val2 = 8;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	default:
 		break;
 	}
@@ -162,7 +160,6 @@
 	struct max517_data *data;
 	struct iio_dev *indio_dev;
 	struct max517_platform_data *platform_data = client->dev.platform_data;
-	int err;
 
 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 	if (!indio_dev)
@@ -194,13 +191,7 @@
 		data->vref_mv[1] = platform_data->vref_mv[1];
 	}
 
-	err = iio_device_register(indio_dev);
-	if (err)
-		return err;
-
-	dev_info(&client->dev, "DAC registered\n");
-
-	return 0;
+	return iio_device_register(indio_dev);
 }
 
 static int max517_remove(struct i2c_client *client)
diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
index 1397b6e..9f57ae8 100644
--- a/drivers/iio/dac/mcp4725.c
+++ b/drivers/iio/dac/mcp4725.c
@@ -195,8 +195,9 @@
 		.name = "powerdown",
 		.read = mcp4725_read_powerdown,
 		.write = mcp4725_write_powerdown,
+		.shared = IIO_SEPARATE,
 	},
-	IIO_ENUM("powerdown_mode", false, &mcp4725_powerdown_mode_enum),
+	IIO_ENUM("powerdown_mode", IIO_SEPARATE, &mcp4725_powerdown_mode_enum),
 	IIO_ENUM_AVAILABLE("powerdown_mode", &mcp4725_powerdown_mode_enum),
 	{ },
 };
@@ -238,17 +239,15 @@
 			   int *val, int *val2, long mask)
 {
 	struct mcp4725_data *data = iio_priv(indio_dev);
-	unsigned long scale_uv;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
 		*val = data->dac_value;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		scale_uv = (data->vref_mv * 1000) >> 12;
-		*val =  scale_uv / 1000000;
-		*val2 = scale_uv % 1000000;
-		return IIO_VAL_INT_PLUS_MICRO;
+		*val = data->vref_mv;
+		*val2 = 12;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	}
 	return -EINVAL;
 }
@@ -321,13 +320,7 @@
 	data->powerdown_mode = pd ? pd-1 : 2; /* 500kohm_to_gnd */
 	data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
 
-	err = iio_device_register(indio_dev);
-	if (err)
-		return err;
-
-	dev_info(&client->dev, "MCP4725 DAC registered\n");
-
-	return 0;
+	return iio_device_register(indio_dev);
 }
 
 static int mcp4725_remove(struct i2c_client *client)
diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c
index a7b30be..63a25d9 100644
--- a/drivers/iio/frequency/adf4350.c
+++ b/drivers/iio/frequency/adf4350.c
@@ -351,6 +351,7 @@
 	.read = adf4350_read, \
 	.write = adf4350_write, \
 	.private = _ident, \
+	.shared = IIO_SEPARATE, \
 }
 
 static const struct iio_chan_spec_ext_info adf4350_ext_info[] = {
@@ -525,8 +526,10 @@
 	}
 
 	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
-	if (indio_dev == NULL)
-		return -ENOMEM;
+	if (indio_dev == NULL) {
+		ret =  -ENOMEM;
+		goto error_disable_clk;
+	}
 
 	st = iio_priv(indio_dev);
 
diff --git a/drivers/iio/gyro/adis16080.c b/drivers/iio/gyro/adis16080.c
index e9ec022..add5098 100644
--- a/drivers/iio/gyro/adis16080.c
+++ b/drivers/iio/gyro/adis16080.c
@@ -51,7 +51,6 @@
 		u16 addr, int *val)
 {
 	struct adis16080_state *st = iio_priv(indio_dev);
-	struct spi_message m;
 	int ret;
 	struct spi_transfer	t[] = {
 		{
@@ -66,11 +65,7 @@
 
 	st->buf = cpu_to_be16(addr | ADIS16080_DIN_WRITE);
 
-	spi_message_init(&m);
-	spi_message_add_tail(&t[0], &m);
-	spi_message_add_tail(&t[1], &m);
-
-	ret = spi_sync(st->us, &m);
+	ret = spi_sync_transfer(st->us, t, ARRAY_SIZE(t));
 	if (ret == 0)
 		*val = sign_extend32(be16_to_cpu(st->buf), 11);
 
diff --git a/drivers/iio/gyro/adis16130.c b/drivers/iio/gyro/adis16130.c
index ac66fc1..445c2ae 100644
--- a/drivers/iio/gyro/adis16130.c
+++ b/drivers/iio/gyro/adis16130.c
@@ -47,7 +47,6 @@
 {
 	int ret;
 	struct adis16130_state *st = iio_priv(indio_dev);
-	struct spi_message msg;
 	struct spi_transfer xfer = {
 		.tx_buf = st->buf,
 		.rx_buf = st->buf,
@@ -59,10 +58,7 @@
 	st->buf[0] = ADIS16130_CON_RD | reg_addr;
 	st->buf[1] = st->buf[2] = st->buf[3] = 0;
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->us, &msg);
-
+	ret = spi_sync_transfer(st->us, &xfer, 1);
 	if (ret == 0)
 		*val = (st->buf[1] << 16) | (st->buf[2] << 8) | st->buf[3];
 	mutex_unlock(&st->buf_lock);
@@ -103,7 +99,6 @@
 		default:
 			return -EINVAL;
 		}
-		break;
 	case IIO_CHAN_INFO_OFFSET:
 		switch (chan->type) {
 		case IIO_ANGL_VEL:
@@ -115,7 +110,6 @@
 		default:
 			return -EINVAL;
 		}
-		break;
 	}
 
 	return -EINVAL;
diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c
index 0654116..22b6fb8 100644
--- a/drivers/iio/gyro/adis16260.c
+++ b/drivers/iio/gyro/adis16260.c
@@ -239,7 +239,6 @@
 		default:
 			return -EINVAL;
 		}
-		break;
 	case IIO_CHAN_INFO_OFFSET:
 		*val = 250000 / 1453; /* 25 C = 0x00 */
 		return IIO_VAL_INT;
diff --git a/drivers/iio/gyro/adxrs450.c b/drivers/iio/gyro/adxrs450.c
index 6dab299..1e546ba 100644
--- a/drivers/iio/gyro/adxrs450.c
+++ b/drivers/iio/gyro/adxrs450.c
@@ -90,7 +90,6 @@
 				    u8 reg_address,
 				    u16 *val)
 {
-	struct spi_message msg;
 	struct adxrs450_state *st = iio_priv(indio_dev);
 	u32 tx;
 	int ret;
@@ -114,10 +113,7 @@
 		tx |= ADXRS450_P;
 
 	st->tx = cpu_to_be32(tx);
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
+	ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
 	if (ret) {
 		dev_err(&st->us->dev, "problem while reading 16 bit register 0x%02x\n",
 				reg_address);
@@ -169,7 +165,6 @@
  **/
 static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val)
 {
-	struct spi_message msg;
 	struct adxrs450_state *st = iio_priv(indio_dev);
 	int ret;
 	struct spi_transfer xfers[] = {
@@ -188,10 +183,7 @@
 	mutex_lock(&st->buf_lock);
 	st->tx = cpu_to_be32(ADXRS450_SENSOR_DATA);
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
+	ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers));
 	if (ret) {
 		dev_err(&st->us->dev, "Problem while reading sensor data\n");
 		goto error_ret;
@@ -354,7 +346,6 @@
 		default:
 			return -EINVAL;
 		}
-		break;
 	case IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW:
 		ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_QUAD1, &t);
 		if (ret)
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index c688d97..ea01c6bc 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -182,10 +182,11 @@
 };
 
 /* Function to push data to buffer */
-static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
+static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data,
+	int len)
 {
 	dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
-	iio_push_to_buffers(indio_dev, (u8 *)data);
+	iio_push_to_buffers(indio_dev, data);
 }
 
 /* Callback handler to send event after all samples are received and captured */
@@ -200,7 +201,7 @@
 				gyro_state->common_attributes.data_ready);
 	if (gyro_state->common_attributes.data_ready)
 		hid_sensor_push_data(indio_dev,
-				(u8 *)gyro_state->gyro_val,
+				gyro_state->gyro_val,
 				sizeof(gyro_state->gyro_val));
 
 	return 0;
diff --git a/drivers/iio/gyro/itg3200_buffer.c b/drivers/iio/gyro/itg3200_buffer.c
index 6c43af9..e3b3c50 100644
--- a/drivers/iio/gyro/itg3200_buffer.c
+++ b/drivers/iio/gyro/itg3200_buffer.c
@@ -55,11 +55,8 @@
 	if (ret < 0)
 		goto error_ret;
 
-	if (indio_dev->scan_timestamp)
-		memcpy(buf + indio_dev->scan_bytes - sizeof(s64),
-				&pf->timestamp, sizeof(pf->timestamp));
+	iio_push_to_buffers_with_timestamp(indio_dev, buf, pf->timestamp);
 
-	iio_push_to_buffers(indio_dev, (u8 *)buf);
 	iio_trigger_notify_done(indio_dev->trig);
 
 error_ret:
diff --git a/drivers/iio/gyro/st_gyro_buffer.c b/drivers/iio/gyro/st_gyro_buffer.c
index 69017c7..d67b17b 100644
--- a/drivers/iio/gyro/st_gyro_buffer.c
+++ b/drivers/iio/gyro/st_gyro_buffer.c
@@ -32,16 +32,7 @@
 
 static int st_gyro_buffer_preenable(struct iio_dev *indio_dev)
 {
-	int err;
-
-	err = st_sensors_set_enable(indio_dev, true);
-	if (err < 0)
-		goto st_gyro_set_enable_error;
-
-	err = iio_sw_buffer_preenable(indio_dev);
-
-st_gyro_set_enable_error:
-	return err;
+	return st_sensors_set_enable(indio_dev, true);
 }
 
 static int st_gyro_buffer_postenable(struct iio_dev *indio_dev)
diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c
index e13c2b0..d53d91a 100644
--- a/drivers/iio/gyro/st_gyro_core.c
+++ b/drivers/iio/gyro/st_gyro_core.c
@@ -305,8 +305,9 @@
 int st_gyro_common_probe(struct iio_dev *indio_dev,
 					struct st_sensors_platform_data *pdata)
 {
-	int err;
 	struct st_sensor_data *gdata = iio_priv(indio_dev);
+	int irq = gdata->get_irq_data_ready(indio_dev);
+	int err;
 
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &gyro_info;
@@ -314,7 +315,7 @@
 	err = st_sensors_check_device_support(indio_dev,
 				ARRAY_SIZE(st_gyro_sensors), st_gyro_sensors);
 	if (err < 0)
-		goto st_gyro_common_probe_error;
+		return err;
 
 	gdata->num_data_channels = ST_GYRO_NUMBER_DATA_CHANNELS;
 	gdata->multiread_bit = gdata->sensor->multi_read_bit;
@@ -327,13 +328,13 @@
 
 	err = st_sensors_init_sensor(indio_dev, pdata);
 	if (err < 0)
-		goto st_gyro_common_probe_error;
+		return err;
 
-	if (gdata->get_irq_data_ready(indio_dev) > 0) {
-		err = st_gyro_allocate_ring(indio_dev);
-		if (err < 0)
-			goto st_gyro_common_probe_error;
+	err = st_gyro_allocate_ring(indio_dev);
+	if (err < 0)
+		return err;
 
+	if (irq > 0) {
 		err = st_sensors_allocate_trigger(indio_dev,
 						  ST_GYRO_TRIGGER_OPS);
 		if (err < 0)
@@ -344,15 +345,14 @@
 	if (err)
 		goto st_gyro_device_register_error;
 
-	return err;
+	return 0;
 
 st_gyro_device_register_error:
-	if (gdata->get_irq_data_ready(indio_dev) > 0)
+	if (irq > 0)
 		st_sensors_deallocate_trigger(indio_dev);
 st_gyro_probe_trigger_error:
-	if (gdata->get_irq_data_ready(indio_dev) > 0)
-		st_gyro_deallocate_ring(indio_dev);
-st_gyro_common_probe_error:
+	st_gyro_deallocate_ring(indio_dev);
+
 	return err;
 }
 EXPORT_SYMBOL(st_gyro_common_probe);
@@ -362,10 +362,10 @@
 	struct st_sensor_data *gdata = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	if (gdata->get_irq_data_ready(indio_dev) > 0) {
+	if (gdata->get_irq_data_ready(indio_dev) > 0)
 		st_sensors_deallocate_trigger(indio_dev);
-		st_gyro_deallocate_ring(indio_dev);
-	}
+
+	st_gyro_deallocate_ring(indio_dev);
 }
 EXPORT_SYMBOL(st_gyro_common_remove);
 
diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h
index 9b32253..f6db6af 100644
--- a/drivers/iio/iio_core.h
+++ b/drivers/iio/iio_core.h
@@ -30,9 +30,12 @@
 						const char *buf,
 						size_t len),
 			   u64 mask,
-			   bool generic,
+			   enum iio_shared_by shared_by,
 			   struct device *dev,
 			   struct list_head *attr_list);
+void iio_free_chan_devattr_list(struct list_head *attr_list);
+
+ssize_t iio_format_value(char *buf, unsigned int type, int val, int val2);
 
 /* Event interface flags */
 #define IIO_BUSY_BIT_POS 1
@@ -50,6 +53,7 @@
 #define iio_buffer_read_first_n_outer_addr (&iio_buffer_read_first_n_outer)
 
 void iio_disable_all_buffers(struct iio_dev *indio_dev);
+void iio_buffer_wakeup_poll(struct iio_dev *indio_dev);
 
 #else
 
@@ -57,11 +61,13 @@
 #define iio_buffer_read_first_n_outer_addr NULL
 
 static inline void iio_disable_all_buffers(struct iio_dev *indio_dev) {}
+static inline void iio_buffer_wakeup_poll(struct iio_dev *indio_dev) {}
 
 #endif
 
 int iio_device_register_eventset(struct iio_dev *indio_dev);
 void iio_device_unregister_eventset(struct iio_dev *indio_dev);
+void iio_device_wakeup_eventset(struct iio_dev *indio_dev);
 int iio_event_getfd(struct iio_dev *indio_dev);
 
 #endif
diff --git a/drivers/iio/imu/adis16400_buffer.c b/drivers/iio/imu/adis16400_buffer.c
index 054c01d..f2cf829 100644
--- a/drivers/iio/imu/adis16400_buffer.c
+++ b/drivers/iio/imu/adis16400_buffer.c
@@ -82,13 +82,8 @@
 		spi_setup(st->adis.spi);
 	}
 
-	/* Guaranteed to be aligned with 8 byte boundary */
-	if (indio_dev->scan_timestamp) {
-		void *b = adis->buffer + indio_dev->scan_bytes - sizeof(s64);
-		*(s64 *)b = pf->timestamp;
-	}
-
-	iio_push_to_buffers(indio_dev, adis->buffer);
+	iio_push_to_buffers_with_timestamp(indio_dev, adis->buffer,
+		pf->timestamp);
 
 	iio_trigger_notify_done(indio_dev->trig);
 
diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c
index 99d8e0b..cb32b59 100644
--- a/drivers/iio/imu/adis_buffer.c
+++ b/drivers/iio/imu/adis_buffer.c
@@ -102,13 +102,8 @@
 		mutex_unlock(&adis->txrx_lock);
 	}
 
-	/* Guaranteed to be aligned with 8 byte boundary */
-	if (indio_dev->scan_timestamp) {
-		void *b = adis->buffer + indio_dev->scan_bytes - sizeof(s64);
-		*(s64 *)b = pf->timestamp;
-	}
-
-	iio_push_to_buffers(indio_dev, adis->buffer);
+	iio_push_to_buffers_with_timestamp(indio_dev, adis->buffer,
+		pf->timestamp);
 
 	iio_trigger_notify_done(indio_dev->trig);
 
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
index 7da0832..4295171 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
@@ -124,7 +124,6 @@
 	u8 data[INV_MPU6050_OUTPUT_DATA_SIZE];
 	u16 fifo_count;
 	s64 timestamp;
-	u64 *tmp;
 
 	mutex_lock(&indio_dev->mlock);
 	if (!(st->chip_config.accl_fifo_enable |
@@ -170,9 +169,8 @@
 		if (0 == result)
 			timestamp = 0;
 
-		tmp = (u64 *)data;
-		tmp[DIV_ROUND_UP(bytes_per_datum, 8)] = timestamp;
-		result = iio_push_to_buffers(indio_dev, data);
+		result = iio_push_to_buffers_with_timestamp(indio_dev, data,
+			timestamp);
 		if (result)
 			goto flush_fifo;
 		fifo_count -= bytes_per_datum;
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 2710f72..7f9152c 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -20,6 +20,7 @@
 #include <linux/cdev.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
+#include <linux/sched.h>
 
 #include <linux/iio/iio.h>
 #include "iio_core.h"
@@ -31,16 +32,9 @@
 	[IIO_LE] = "le",
 };
 
-static bool iio_buffer_is_active(struct iio_dev *indio_dev,
-				 struct iio_buffer *buf)
+static bool iio_buffer_is_active(struct iio_buffer *buf)
 {
-	struct list_head *p;
-
-	list_for_each(p, &indio_dev->buffer_list)
-		if (p == &buf->buffer_list)
-			return true;
-
-	return false;
+	return !list_empty(&buf->buffer_list);
 }
 
 /**
@@ -55,6 +49,9 @@
 	struct iio_dev *indio_dev = filp->private_data;
 	struct iio_buffer *rb = indio_dev->buffer;
 
+	if (!indio_dev->info)
+		return -ENODEV;
+
 	if (!rb || !rb->access->read_first_n)
 		return -EINVAL;
 	return rb->access->read_first_n(rb, n, buf);
@@ -69,6 +66,9 @@
 	struct iio_dev *indio_dev = filp->private_data;
 	struct iio_buffer *rb = indio_dev->buffer;
 
+	if (!indio_dev->info)
+		return -ENODEV;
+
 	poll_wait(filp, &rb->pollq, wait);
 	if (rb->stufftoread)
 		return POLLIN | POLLRDNORM;
@@ -76,10 +76,27 @@
 	return 0;
 }
 
+/**
+ * iio_buffer_wakeup_poll - Wakes up the buffer waitqueue
+ * @indio_dev: The IIO device
+ *
+ * Wakes up the event waitqueue used for poll(). Should usually
+ * be called when the device is unregistered.
+ */
+void iio_buffer_wakeup_poll(struct iio_dev *indio_dev)
+{
+	if (!indio_dev->buffer)
+		return;
+
+	wake_up(&indio_dev->buffer->pollq);
+}
+
 void iio_buffer_init(struct iio_buffer *buffer)
 {
 	INIT_LIST_HEAD(&buffer->demux_list);
+	INIT_LIST_HEAD(&buffer->buffer_list);
 	init_waitqueue_head(&buffer->pollq);
+	kref_init(&buffer->ref);
 }
 EXPORT_SYMBOL(iio_buffer_init);
 
@@ -146,7 +163,7 @@
 	if (ret < 0)
 		return ret;
 	mutex_lock(&indio_dev->mlock);
-	if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) {
+	if (iio_buffer_is_active(indio_dev->buffer)) {
 		ret = -EBUSY;
 		goto error_ret;
 	}
@@ -192,7 +209,7 @@
 		return ret;
 
 	mutex_lock(&indio_dev->mlock);
-	if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) {
+	if (iio_buffer_is_active(indio_dev->buffer)) {
 		ret = -EBUSY;
 		goto error_ret;
 	}
@@ -214,7 +231,7 @@
 				     &iio_show_scan_index,
 				     NULL,
 				     0,
-				     0,
+				     IIO_SEPARATE,
 				     &indio_dev->dev,
 				     &buffer->scan_el_dev_attr_list);
 	if (ret)
@@ -249,29 +266,14 @@
 					     0,
 					     &indio_dev->dev,
 					     &buffer->scan_el_dev_attr_list);
+	if (ret)
+		goto error_ret;
 	attrcount++;
 	ret = attrcount;
 error_ret:
 	return ret;
 }
 
-static void iio_buffer_remove_and_free_scan_dev_attr(struct iio_dev *indio_dev,
-						     struct iio_dev_attr *p)
-{
-	kfree(p->dev_attr.attr.name);
-	kfree(p);
-}
-
-static void __iio_buffer_attr_cleanup(struct iio_dev *indio_dev)
-{
-	struct iio_dev_attr *p, *n;
-	struct iio_buffer *buffer = indio_dev->buffer;
-
-	list_for_each_entry_safe(p, n,
-				 &buffer->scan_el_dev_attr_list, l)
-		iio_buffer_remove_and_free_scan_dev_attr(indio_dev, p);
-}
-
 static const char * const iio_scan_elements_group_name = "scan_elements";
 
 int iio_buffer_register(struct iio_dev *indio_dev,
@@ -348,7 +350,7 @@
 error_free_scan_mask:
 	kfree(buffer->scan_mask);
 error_cleanup_dynamic:
-	__iio_buffer_attr_cleanup(indio_dev);
+	iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list);
 
 	return ret;
 }
@@ -358,7 +360,7 @@
 {
 	kfree(indio_dev->buffer->scan_mask);
 	kfree(indio_dev->buffer->scan_el_group.attrs);
-	__iio_buffer_attr_cleanup(indio_dev);
+	iio_free_chan_devattr_list(&indio_dev->buffer->scan_el_dev_attr_list);
 }
 EXPORT_SYMBOL(iio_buffer_unregister);
 
@@ -396,7 +398,7 @@
 			return len;
 
 	mutex_lock(&indio_dev->mlock);
-	if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) {
+	if (iio_buffer_is_active(indio_dev->buffer)) {
 		ret = -EBUSY;
 	} else {
 		if (buffer->access->set_length)
@@ -414,13 +416,11 @@
 			       char *buf)
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	return sprintf(buf, "%d\n",
-		       iio_buffer_is_active(indio_dev,
-					    indio_dev->buffer));
+	return sprintf(buf, "%d\n", iio_buffer_is_active(indio_dev->buffer));
 }
 EXPORT_SYMBOL(iio_buffer_show_enable);
 
-/* note NULL used as error indicator as it doesn't make sense. */
+/* Note NULL used as error indicator as it doesn't make sense. */
 static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks,
 					  unsigned int masklength,
 					  const unsigned long *mask)
@@ -435,8 +435,8 @@
 	return NULL;
 }
 
-static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const long *mask,
-				  bool timestamp)
+static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
+				const unsigned long *mask, bool timestamp)
 {
 	const struct iio_chan_spec *ch;
 	unsigned bytes = 0;
@@ -460,6 +460,19 @@
 	return bytes;
 }
 
+static void iio_buffer_activate(struct iio_dev *indio_dev,
+	struct iio_buffer *buffer)
+{
+	iio_buffer_get(buffer);
+	list_add(&buffer->buffer_list, &indio_dev->buffer_list);
+}
+
+static void iio_buffer_deactivate(struct iio_buffer *buffer)
+{
+	list_del_init(&buffer->buffer_list);
+	iio_buffer_put(buffer);
+}
+
 void iio_disable_all_buffers(struct iio_dev *indio_dev)
 {
 	struct iio_buffer *buffer, *_buffer;
@@ -472,14 +485,31 @@
 
 	list_for_each_entry_safe(buffer, _buffer,
 			&indio_dev->buffer_list, buffer_list)
-		list_del_init(&buffer->buffer_list);
+		iio_buffer_deactivate(buffer);
 
 	indio_dev->currentmode = INDIO_DIRECT_MODE;
 	if (indio_dev->setup_ops->postdisable)
 		indio_dev->setup_ops->postdisable(indio_dev);
+
+	if (indio_dev->available_scan_masks == NULL)
+		kfree(indio_dev->active_scan_mask);
 }
 
-int iio_update_buffers(struct iio_dev *indio_dev,
+static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev,
+	struct iio_buffer *buffer)
+{
+	unsigned int bytes;
+
+	if (!buffer->access->set_bytes_per_datum)
+		return;
+
+	bytes = iio_compute_scan_bytes(indio_dev, buffer->scan_mask,
+		buffer->scan_timestamp);
+
+	buffer->access->set_bytes_per_datum(buffer, bytes);
+}
+
+static int __iio_update_buffers(struct iio_dev *indio_dev,
 		       struct iio_buffer *insert_buffer,
 		       struct iio_buffer *remove_buffer)
 {
@@ -509,9 +539,9 @@
 		indio_dev->active_scan_mask = NULL;
 
 	if (remove_buffer)
-		list_del(&remove_buffer->buffer_list);
+		iio_buffer_deactivate(remove_buffer);
 	if (insert_buffer)
-		list_add(&insert_buffer->buffer_list, &indio_dev->buffer_list);
+		iio_buffer_activate(indio_dev, insert_buffer);
 
 	/* If no buffers in list, we are done */
 	if (list_empty(&indio_dev->buffer_list)) {
@@ -521,7 +551,7 @@
 		return 0;
 	}
 
-	/* What scan mask do we actually have ?*/
+	/* What scan mask do we actually have? */
 	compound_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength),
 				sizeof(long), GFP_KERNEL);
 	if (compound_mask == NULL) {
@@ -546,7 +576,7 @@
 			 * Roll back.
 			 * Note can only occur when adding a buffer.
 			 */
-			list_del(&insert_buffer->buffer_list);
+			iio_buffer_deactivate(insert_buffer);
 			if (old_mask) {
 				indio_dev->active_scan_mask = old_mask;
 				success = -EINVAL;
@@ -576,7 +606,8 @@
 		iio_compute_scan_bytes(indio_dev,
 				       indio_dev->active_scan_mask,
 				       indio_dev->scan_timestamp);
-	list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list)
+	list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) {
+		iio_buffer_update_bytes_per_datum(indio_dev, buffer);
 		if (buffer->access->request_update) {
 			ret = buffer->access->request_update(buffer);
 			if (ret) {
@@ -585,6 +616,7 @@
 				goto error_run_postdisable;
 			}
 		}
+	}
 	if (indio_dev->info->update_scan_mode) {
 		ret = indio_dev->info
 			->update_scan_mode(indio_dev,
@@ -594,7 +626,7 @@
 			goto error_run_postdisable;
 		}
 	}
-	/* Definitely possible for devices to support both of these.*/
+	/* Definitely possible for devices to support both of these. */
 	if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) {
 		if (!indio_dev->trig) {
 			printk(KERN_INFO "Buffer not started: no trigger\n");
@@ -605,7 +637,7 @@
 		indio_dev->currentmode = INDIO_BUFFER_TRIGGERED;
 	} else if (indio_dev->modes & INDIO_BUFFER_HARDWARE) {
 		indio_dev->currentmode = INDIO_BUFFER_HARDWARE;
-	} else { /* should never be reached */
+	} else { /* Should never be reached */
 		ret = -EINVAL;
 		goto error_run_postdisable;
 	}
@@ -637,13 +669,50 @@
 error_remove_inserted:
 
 	if (insert_buffer)
-		list_del(&insert_buffer->buffer_list);
+		iio_buffer_deactivate(insert_buffer);
 	indio_dev->active_scan_mask = old_mask;
 	kfree(compound_mask);
 error_ret:
 
 	return ret;
 }
+
+int iio_update_buffers(struct iio_dev *indio_dev,
+		       struct iio_buffer *insert_buffer,
+		       struct iio_buffer *remove_buffer)
+{
+	int ret;
+
+	if (insert_buffer == remove_buffer)
+		return 0;
+
+	mutex_lock(&indio_dev->info_exist_lock);
+	mutex_lock(&indio_dev->mlock);
+
+	if (insert_buffer && iio_buffer_is_active(insert_buffer))
+		insert_buffer = NULL;
+
+	if (remove_buffer && !iio_buffer_is_active(remove_buffer))
+		remove_buffer = NULL;
+
+	if (!insert_buffer && !remove_buffer) {
+		ret = 0;
+		goto out_unlock;
+	}
+
+	if (indio_dev->info == NULL) {
+		ret = -ENODEV;
+		goto out_unlock;
+	}
+
+	ret = __iio_update_buffers(indio_dev, insert_buffer, remove_buffer);
+
+out_unlock:
+	mutex_unlock(&indio_dev->mlock);
+	mutex_unlock(&indio_dev->info_exist_lock);
+
+	return ret;
+}
 EXPORT_SYMBOL_GPL(iio_update_buffers);
 
 ssize_t iio_buffer_store_enable(struct device *dev,
@@ -654,7 +723,6 @@
 	int ret;
 	bool requested_state;
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct iio_buffer *pbuf = indio_dev->buffer;
 	bool inlist;
 
 	ret = strtobool(buf, &requested_state);
@@ -664,16 +732,16 @@
 	mutex_lock(&indio_dev->mlock);
 
 	/* Find out if it is in the list */
-	inlist = iio_buffer_is_active(indio_dev, pbuf);
+	inlist = iio_buffer_is_active(indio_dev->buffer);
 	/* Already in desired state */
 	if (inlist == requested_state)
 		goto done;
 
 	if (requested_state)
-		ret = iio_update_buffers(indio_dev,
+		ret = __iio_update_buffers(indio_dev,
 					 indio_dev->buffer, NULL);
 	else
-		ret = iio_update_buffers(indio_dev,
+		ret = __iio_update_buffers(indio_dev,
 					 NULL, indio_dev->buffer);
 
 	if (ret < 0)
@@ -684,24 +752,6 @@
 }
 EXPORT_SYMBOL(iio_buffer_store_enable);
 
-int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
-{
-	struct iio_buffer *buffer;
-	unsigned bytes;
-	dev_dbg(&indio_dev->dev, "%s\n", __func__);
-
-	list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list)
-		if (buffer->access->set_bytes_per_datum) {
-			bytes = iio_compute_scan_bytes(indio_dev,
-						       buffer->scan_mask,
-						       buffer->scan_timestamp);
-
-			buffer->access->set_bytes_per_datum(buffer, bytes);
-		}
-	return 0;
-}
-EXPORT_SYMBOL(iio_sw_buffer_preenable);
-
 /**
  * iio_validate_scan_mask_onehot() - Validates that exactly one channel is selected
  * @indio_dev: the iio device
@@ -729,6 +779,7 @@
 
 /**
  * iio_scan_mask_set() - set particular bit in the scan mask
+ * @indio_dev: the iio device
  * @buffer: the buffer whose scan mask we are interested in
  * @bit: the bit to be set.
  *
@@ -749,7 +800,7 @@
 	if (trialmask == NULL)
 		return -ENOMEM;
 	if (!indio_dev->masklength) {
-		WARN_ON("trying to set scanmask prior to registering buffer\n");
+		WARN_ON("Trying to set scanmask prior to registering buffer\n");
 		goto err_invalid_mask;
 	}
 	bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength);
@@ -804,8 +855,8 @@
 	struct list_head l;
 };
 
-static unsigned char *iio_demux(struct iio_buffer *buffer,
-				 unsigned char *datain)
+static const void *iio_demux(struct iio_buffer *buffer,
+				 const void *datain)
 {
 	struct iio_demux_table *t;
 
@@ -818,9 +869,9 @@
 	return buffer->demux_bounce;
 }
 
-static int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data)
+static int iio_push_to_buffer(struct iio_buffer *buffer, const void *data)
 {
-	unsigned char *dataout = iio_demux(buffer, data);
+	const void *dataout = iio_demux(buffer, data);
 
 	return buffer->access->store_to(buffer, dataout);
 }
@@ -835,7 +886,7 @@
 }
 
 
-int iio_push_to_buffers(struct iio_dev *indio_dev, unsigned char *data)
+int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data)
 {
 	int ret;
 	struct iio_buffer *buf;
@@ -958,3 +1009,45 @@
 	return ret;
 }
 EXPORT_SYMBOL_GPL(iio_update_demux);
+
+/**
+ * iio_buffer_release() - Free a buffer's resources
+ * @ref: Pointer to the kref embedded in the iio_buffer struct
+ *
+ * This function is called when the last reference to the buffer has been
+ * dropped. It will typically free all resources allocated by the buffer. Do not
+ * call this function manually, always use iio_buffer_put() when done using a
+ * buffer.
+ */
+static void iio_buffer_release(struct kref *ref)
+{
+	struct iio_buffer *buffer = container_of(ref, struct iio_buffer, ref);
+
+	buffer->access->release(buffer);
+}
+
+/**
+ * iio_buffer_get() - Grab a reference to the buffer
+ * @buffer: The buffer to grab a reference for, may be NULL
+ *
+ * Returns the pointer to the buffer that was passed into the function.
+ */
+struct iio_buffer *iio_buffer_get(struct iio_buffer *buffer)
+{
+	if (buffer)
+		kref_get(&buffer->ref);
+
+	return buffer;
+}
+EXPORT_SYMBOL_GPL(iio_buffer_get);
+
+/**
+ * iio_buffer_put() - Release the reference to the buffer
+ * @buffer: The buffer to release the reference for, may be NULL
+ */
+void iio_buffer_put(struct iio_buffer *buffer)
+{
+	if (buffer)
+		kref_put(&buffer->ref, iio_buffer_release);
+}
+EXPORT_SYMBOL_GPL(iio_buffer_put);
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index f95c697..18f72e3 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -9,6 +9,8 @@
  * Based on elements of hwmon and input subsystems.
  */
 
+#define pr_fmt(fmt) "iio-core: " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/idr.h>
@@ -28,6 +30,7 @@
 #include "iio_core_trigger.h"
 #include <linux/iio/sysfs.h>
 #include <linux/iio/events.h>
+#include <linux/iio/buffer.h>
 
 /* IDA to assign each registered device a unique id */
 static DEFINE_IDA(iio_ida);
@@ -101,6 +104,7 @@
 	[IIO_CHAN_INFO_PHASE] = "phase",
 	[IIO_CHAN_INFO_HARDWAREGAIN] = "hardwaregain",
 	[IIO_CHAN_INFO_HYSTERESIS] = "hysteresis",
+	[IIO_CHAN_INFO_INT_TIME] = "integration_time",
 };
 
 const struct iio_chan_spec
@@ -130,16 +134,13 @@
 	/* Register sysfs bus */
 	ret  = bus_register(&iio_bus_type);
 	if (ret < 0) {
-		printk(KERN_ERR
-		       "%s could not register bus type\n",
-			__FILE__);
+		pr_err("could not register bus type\n");
 		goto error_nothing;
 	}
 
 	ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio");
 	if (ret < 0) {
-		printk(KERN_ERR "%s: failed to allocate char dev region\n",
-		       __FILE__);
+		pr_err("failed to allocate char dev region\n");
 		goto error_unregister_bus_type;
 	}
 
@@ -361,22 +362,20 @@
 }
 EXPORT_SYMBOL_GPL(iio_enum_write);
 
-static ssize_t iio_read_channel_info(struct device *dev,
-				     struct device_attribute *attr,
-				     char *buf)
+/**
+ * iio_format_value() - Formats a IIO value into its string representation
+ * @buf: The buffer to which the formated value gets written
+ * @type: One of the IIO_VAL_... constants. This decides how the val and val2
+ *        parameters are formatted.
+ * @val: First part of the value, exact meaning depends on the type parameter.
+ * @val2: Second part of the value, exact meaning depends on the type parameter.
+ */
+ssize_t iio_format_value(char *buf, unsigned int type, int val, int val2)
 {
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	unsigned long long tmp;
-	int val, val2;
 	bool scale_db = false;
-	int ret = indio_dev->info->read_raw(indio_dev, this_attr->c,
-					    &val, &val2, this_attr->address);
 
-	if (ret < 0)
-		return ret;
-
-	switch (ret) {
+	switch (type) {
 	case IIO_VAL_INT:
 		return sprintf(buf, "%d\n", val);
 	case IIO_VAL_INT_PLUS_MICRO_DB:
@@ -408,6 +407,22 @@
 	}
 }
 
+static ssize_t iio_read_channel_info(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+	int val, val2;
+	int ret = indio_dev->info->read_raw(indio_dev, this_attr->c,
+					    &val, &val2, this_attr->address);
+
+	if (ret < 0)
+		return ret;
+
+	return iio_format_value(buf, ret, val, val2);
+}
+
 /**
  * iio_str_to_fixpoint() - Parse a fixed-point number from a string
  * @str: The string to parse
@@ -516,14 +531,15 @@
 						struct device_attribute *attr,
 						const char *buf,
 						size_t len),
-			   bool generic)
+			   enum iio_shared_by shared_by)
 {
-	int ret;
-	char *name_format, *full_postfix;
+	int ret = 0;
+	char *name_format = NULL;
+	char *full_postfix;
 	sysfs_attr_init(&dev_attr->attr);
 
 	/* Build up postfix of <extend_name>_<modifier>_postfix */
-	if (chan->modified && !generic) {
+	if (chan->modified && (shared_by == IIO_SEPARATE)) {
 		if (chan->extend_name)
 			full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s",
 						 iio_modifier_names[chan
@@ -544,53 +560,78 @@
 						 chan->extend_name,
 						 postfix);
 	}
-	if (full_postfix == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	if (full_postfix == NULL)
+		return -ENOMEM;
 
 	if (chan->differential) { /* Differential can not have modifier */
-		if (generic)
+		switch (shared_by) {
+		case IIO_SHARED_BY_ALL:
+			name_format = kasprintf(GFP_KERNEL, "%s", full_postfix);
+			break;
+		case IIO_SHARED_BY_DIR:
+			name_format = kasprintf(GFP_KERNEL, "%s_%s",
+						iio_direction[chan->output],
+						full_postfix);
+			break;
+		case IIO_SHARED_BY_TYPE:
 			name_format
 				= kasprintf(GFP_KERNEL, "%s_%s-%s_%s",
 					    iio_direction[chan->output],
 					    iio_chan_type_name_spec[chan->type],
 					    iio_chan_type_name_spec[chan->type],
 					    full_postfix);
-		else if (chan->indexed)
+			break;
+		case IIO_SEPARATE:
+			if (!chan->indexed) {
+				WARN_ON("Differential channels must be indexed\n");
+				ret = -EINVAL;
+				goto error_free_full_postfix;
+			}
 			name_format
-				= kasprintf(GFP_KERNEL, "%s_%s%d-%s%d_%s",
+				= kasprintf(GFP_KERNEL,
+					    "%s_%s%d-%s%d_%s",
 					    iio_direction[chan->output],
 					    iio_chan_type_name_spec[chan->type],
 					    chan->channel,
 					    iio_chan_type_name_spec[chan->type],
 					    chan->channel2,
 					    full_postfix);
-		else {
-			WARN_ON("Differential channels must be indexed\n");
-			ret = -EINVAL;
-			goto error_free_full_postfix;
+			break;
 		}
 	} else { /* Single ended */
-		if (generic)
+		switch (shared_by) {
+		case IIO_SHARED_BY_ALL:
+			name_format = kasprintf(GFP_KERNEL, "%s", full_postfix);
+			break;
+		case IIO_SHARED_BY_DIR:
+			name_format = kasprintf(GFP_KERNEL, "%s_%s",
+						iio_direction[chan->output],
+						full_postfix);
+			break;
+		case IIO_SHARED_BY_TYPE:
 			name_format
 				= kasprintf(GFP_KERNEL, "%s_%s_%s",
 					    iio_direction[chan->output],
 					    iio_chan_type_name_spec[chan->type],
 					    full_postfix);
-		else if (chan->indexed)
-			name_format
-				= kasprintf(GFP_KERNEL, "%s_%s%d_%s",
-					    iio_direction[chan->output],
-					    iio_chan_type_name_spec[chan->type],
-					    chan->channel,
-					    full_postfix);
-		else
-			name_format
-				= kasprintf(GFP_KERNEL, "%s_%s_%s",
-					    iio_direction[chan->output],
-					    iio_chan_type_name_spec[chan->type],
-					    full_postfix);
+			break;
+
+		case IIO_SEPARATE:
+			if (chan->indexed)
+				name_format
+					= kasprintf(GFP_KERNEL, "%s_%s%d_%s",
+						    iio_direction[chan->output],
+						    iio_chan_type_name_spec[chan->type],
+						    chan->channel,
+						    full_postfix);
+			else
+				name_format
+					= kasprintf(GFP_KERNEL, "%s_%s_%s",
+						    iio_direction[chan->output],
+						    iio_chan_type_name_spec[chan->type],
+						    full_postfix);
+			break;
+		}
 	}
 	if (name_format == NULL) {
 		ret = -ENOMEM;
@@ -614,16 +655,11 @@
 		dev_attr->attr.mode |= S_IWUSR;
 		dev_attr->store = writefunc;
 	}
-	kfree(name_format);
-	kfree(full_postfix);
-
-	return 0;
-
 error_free_name_format:
 	kfree(name_format);
 error_free_full_postfix:
 	kfree(full_postfix);
-error_ret:
+
 	return ret;
 }
 
@@ -642,21 +678,21 @@
 						const char *buf,
 						size_t len),
 			   u64 mask,
-			   bool generic,
+			   enum iio_shared_by shared_by,
 			   struct device *dev,
 			   struct list_head *attr_list)
 {
 	int ret;
 	struct iio_dev_attr *iio_attr, *t;
 
-	iio_attr = kzalloc(sizeof *iio_attr, GFP_KERNEL);
+	iio_attr = kzalloc(sizeof(*iio_attr), GFP_KERNEL);
 	if (iio_attr == NULL) {
 		ret = -ENOMEM;
 		goto error_ret;
 	}
 	ret = __iio_device_attr_init(&iio_attr->dev_attr,
 				     postfix, chan,
-				     readfunc, writefunc, generic);
+				     readfunc, writefunc, shared_by);
 	if (ret)
 		goto error_iio_dev_attr_free;
 	iio_attr->c = chan;
@@ -664,7 +700,7 @@
 	list_for_each_entry(t, attr_list, l)
 		if (strcmp(t->dev_attr.attr.name,
 			   iio_attr->dev_attr.attr.name) == 0) {
-			if (!generic)
+			if (shared_by == IIO_SEPARATE)
 				dev_err(dev, "tried to double register : %s\n",
 					t->dev_attr.attr.name);
 			ret = -EBUSY;
@@ -682,45 +718,67 @@
 	return ret;
 }
 
+static int iio_device_add_info_mask_type(struct iio_dev *indio_dev,
+					 struct iio_chan_spec const *chan,
+					 enum iio_shared_by shared_by,
+					 const long *infomask)
+{
+	int i, ret, attrcount = 0;
+
+	for_each_set_bit(i, infomask, sizeof(infomask)*8) {
+		ret = __iio_add_chan_devattr(iio_chan_info_postfix[i],
+					     chan,
+					     &iio_read_channel_info,
+					     &iio_write_channel_info,
+					     i,
+					     shared_by,
+					     &indio_dev->dev,
+					     &indio_dev->channel_attr_list);
+		if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE))
+			continue;
+		else if (ret < 0)
+			return ret;
+		attrcount++;
+	}
+
+	return attrcount;
+}
+
 static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
 					struct iio_chan_spec const *chan)
 {
 	int ret, attrcount = 0;
-	int i;
 	const struct iio_chan_spec_ext_info *ext_info;
 
 	if (chan->channel < 0)
 		return 0;
-	for_each_set_bit(i, &chan->info_mask_separate, sizeof(long)*8) {
-		ret = __iio_add_chan_devattr(iio_chan_info_postfix[i],
-					     chan,
-					     &iio_read_channel_info,
-					     &iio_write_channel_info,
-					     i,
-					     0,
-					     &indio_dev->dev,
-					     &indio_dev->channel_attr_list);
-		if (ret < 0)
-			goto error_ret;
-		attrcount++;
-	}
-	for_each_set_bit(i, &chan->info_mask_shared_by_type, sizeof(long)*8) {
-		ret = __iio_add_chan_devattr(iio_chan_info_postfix[i],
-					     chan,
-					     &iio_read_channel_info,
-					     &iio_write_channel_info,
-					     i,
-					     1,
-					     &indio_dev->dev,
-					     &indio_dev->channel_attr_list);
-		if (ret == -EBUSY) {
-			ret = 0;
-			continue;
-		} else if (ret < 0) {
-			goto error_ret;
-		}
-		attrcount++;
-	}
+	ret = iio_device_add_info_mask_type(indio_dev, chan,
+					    IIO_SEPARATE,
+					    &chan->info_mask_separate);
+	if (ret < 0)
+		return ret;
+	attrcount += ret;
+
+	ret = iio_device_add_info_mask_type(indio_dev, chan,
+					    IIO_SHARED_BY_TYPE,
+					    &chan->info_mask_shared_by_type);
+	if (ret < 0)
+		return ret;
+	attrcount += ret;
+
+	ret = iio_device_add_info_mask_type(indio_dev, chan,
+					    IIO_SHARED_BY_DIR,
+					    &chan->info_mask_shared_by_dir);
+	if (ret < 0)
+		return ret;
+	attrcount += ret;
+
+	ret = iio_device_add_info_mask_type(indio_dev, chan,
+					    IIO_SHARED_BY_ALL,
+					    &chan->info_mask_shared_by_all);
+	if (ret < 0)
+		return ret;
+	attrcount += ret;
 
 	if (chan->ext_info) {
 		unsigned int i = 0;
@@ -740,22 +798,31 @@
 				continue;
 
 			if (ret)
-				goto error_ret;
+				return ret;
 
 			attrcount++;
 		}
 	}
 
-	ret = attrcount;
-error_ret:
-	return ret;
+	return attrcount;
 }
 
-static void iio_device_remove_and_free_read_attr(struct iio_dev *indio_dev,
-						 struct iio_dev_attr *p)
+/**
+ * iio_free_chan_devattr_list() - Free a list of IIO device attributes
+ * @attr_list: List of IIO device attributes
+ *
+ * This function frees the memory allocated for each of the IIO device
+ * attributes in the list. Note: if you want to reuse the list after calling
+ * this function you have to reinitialize it using INIT_LIST_HEAD().
+ */
+void iio_free_chan_devattr_list(struct list_head *attr_list)
 {
-	kfree(p->dev_attr.attr.name);
-	kfree(p);
+	struct iio_dev_attr *p, *n;
+
+	list_for_each_entry_safe(p, n, attr_list, l) {
+		kfree(p->dev_attr.attr.name);
+		kfree(p);
+	}
 }
 
 static ssize_t iio_show_dev_name(struct device *dev,
@@ -771,7 +838,7 @@
 static int iio_device_register_sysfs(struct iio_dev *indio_dev)
 {
 	int i, ret = 0, attrcount, attrn, attrcount_orig = 0;
-	struct iio_dev_attr *p, *n;
+	struct iio_dev_attr *p;
 	struct attribute **attr;
 
 	/* First count elements in any existing group */
@@ -824,11 +891,7 @@
 	return 0;
 
 error_clear_attrs:
-	list_for_each_entry_safe(p, n,
-				 &indio_dev->channel_attr_list, l) {
-		list_del(&p->l);
-		iio_device_remove_and_free_read_attr(indio_dev, p);
-	}
+	iio_free_chan_devattr_list(&indio_dev->channel_attr_list);
 
 	return ret;
 }
@@ -836,12 +899,7 @@
 static void iio_device_unregister_sysfs(struct iio_dev *indio_dev)
 {
 
-	struct iio_dev_attr *p, *n;
-
-	list_for_each_entry_safe(p, n, &indio_dev->channel_attr_list, l) {
-		list_del(&p->l);
-		iio_device_remove_and_free_read_attr(indio_dev, p);
-	}
+	iio_free_chan_devattr_list(&indio_dev->channel_attr_list);
 	kfree(indio_dev->chan_attr_group.attrs);
 }
 
@@ -853,6 +911,8 @@
 	iio_device_unregister_eventset(indio_dev);
 	iio_device_unregister_sysfs(indio_dev);
 
+	iio_buffer_put(indio_dev->buffer);
+
 	ida_simple_remove(&iio_ida, indio_dev->id);
 	kfree(indio_dev);
 }
@@ -890,7 +950,7 @@
 		dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL);
 		if (dev->id < 0) {
 			/* cannot use a dev_err as the name isn't available */
-			printk(KERN_ERR "Failed to get id\n");
+			pr_err("failed to get device id\n");
 			kfree(dev);
 			return NULL;
 		}
@@ -995,6 +1055,9 @@
 	int __user *ip = (int __user *)arg;
 	int fd;
 
+	if (!indio_dev->info)
+		return -ENODEV;
+
 	if (cmd == IIO_GET_EVENT_FD_IOCTL) {
 		fd = iio_event_getfd(indio_dev);
 		if (copy_to_user(ip, &fd, sizeof(fd)))
@@ -1091,6 +1154,10 @@
 	iio_disable_all_buffers(indio_dev);
 
 	indio_dev->info = NULL;
+
+	iio_device_wakeup_eventset(indio_dev);
+	iio_buffer_wakeup_poll(indio_dev);
+
 	mutex_unlock(&indio_dev->info_exist_lock);
 }
 EXPORT_SYMBOL(iio_device_unregister);
diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c
index 6be65ef..dac15b9 100644
--- a/drivers/iio/industrialio-event.c
+++ b/drivers/iio/industrialio-event.c
@@ -76,6 +76,9 @@
 	struct iio_event_interface *ev_int = indio_dev->event_interface;
 	unsigned int events = 0;
 
+	if (!indio_dev->info)
+		return -ENODEV;
+
 	poll_wait(filep, &ev_int->wait, wait);
 
 	spin_lock_irq(&ev_int->wait.lock);
@@ -96,6 +99,9 @@
 	unsigned int copied;
 	int ret;
 
+	if (!indio_dev->info)
+		return -ENODEV;
+
 	if (count < sizeof(struct iio_event_data))
 		return -EINVAL;
 
@@ -107,9 +113,14 @@
 		}
 		/* Blocking on device; waiting for something to be there */
 		ret = wait_event_interruptible_locked_irq(ev_int->wait,
-					!kfifo_is_empty(&ev_int->det_events));
+					!kfifo_is_empty(&ev_int->det_events) ||
+					indio_dev->info == NULL);
 		if (ret)
 			goto error_unlock;
+		if (indio_dev->info == NULL) {
+			ret = -ENODEV;
+			goto error_unlock;
+		}
 		/* Single access device so no one else can get the data */
 	}
 
@@ -166,7 +177,7 @@
 	iio_device_get(indio_dev);
 
 	fd = anon_inode_getfd("iio:event", &iio_event_chrdev_fileops,
-				indio_dev, O_RDONLY);
+				indio_dev, O_RDONLY | O_CLOEXEC);
 	if (fd < 0) {
 		spin_lock_irq(&ev_int->wait.lock);
 		__clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
@@ -190,6 +201,27 @@
 	[IIO_EV_DIR_FALLING] = "falling"
 };
 
+static const char * const iio_ev_info_text[] = {
+	[IIO_EV_INFO_ENABLE] = "en",
+	[IIO_EV_INFO_VALUE] = "value",
+	[IIO_EV_INFO_HYSTERESIS] = "hysteresis",
+};
+
+static enum iio_event_direction iio_ev_attr_dir(struct iio_dev_attr *attr)
+{
+	return attr->c->event_spec[attr->address & 0xffff].dir;
+}
+
+static enum iio_event_type iio_ev_attr_type(struct iio_dev_attr *attr)
+{
+	return attr->c->event_spec[attr->address & 0xffff].type;
+}
+
+static enum iio_event_info iio_ev_attr_info(struct iio_dev_attr *attr)
+{
+	return (attr->address >> 16) & 0xffff;
+}
+
 static ssize_t iio_ev_state_store(struct device *dev,
 				  struct device_attribute *attr,
 				  const char *buf,
@@ -204,9 +236,14 @@
 	if (ret < 0)
 		return ret;
 
-	ret = indio_dev->info->write_event_config(indio_dev,
-						  this_attr->address,
-						  val);
+	if (indio_dev->info->write_event_config)
+		ret = indio_dev->info->write_event_config(indio_dev,
+			this_attr->address, val);
+	else
+		ret = indio_dev->info->write_event_config_new(indio_dev,
+			this_attr->c, iio_ev_attr_type(this_attr),
+			iio_ev_attr_dir(this_attr), val);
+
 	return (ret < 0) ? ret : len;
 }
 
@@ -216,9 +253,15 @@
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-	int val = indio_dev->info->read_event_config(indio_dev,
-						     this_attr->address);
+	int val;
 
+	if (indio_dev->info->read_event_config)
+		val = indio_dev->info->read_event_config(indio_dev,
+			this_attr->address);
+	else
+		val = indio_dev->info->read_event_config_new(indio_dev,
+			this_attr->c, iio_ev_attr_type(this_attr),
+			iio_ev_attr_dir(this_attr));
 	if (val < 0)
 		return val;
 	else
@@ -231,14 +274,24 @@
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-	int val, ret;
+	int val, val2;
+	int ret;
 
-	ret = indio_dev->info->read_event_value(indio_dev,
-						this_attr->address, &val);
-	if (ret < 0)
-		return ret;
-
-	return sprintf(buf, "%d\n", val);
+	if (indio_dev->info->read_event_value) {
+		ret = indio_dev->info->read_event_value(indio_dev,
+			this_attr->address, &val);
+		if (ret < 0)
+			return ret;
+		return sprintf(buf, "%d\n", val);
+	} else {
+		ret = indio_dev->info->read_event_value_new(indio_dev,
+			this_attr->c, iio_ev_attr_type(this_attr),
+			iio_ev_attr_dir(this_attr), iio_ev_attr_info(this_attr),
+			&val, &val2);
+		if (ret < 0)
+			return ret;
+		return iio_format_value(buf, ret, val, val2);
+	}
 }
 
 static ssize_t iio_ev_value_store(struct device *dev,
@@ -248,25 +301,120 @@
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-	int val;
+	int val, val2;
 	int ret;
 
-	if (!indio_dev->info->write_event_value)
+	if (!indio_dev->info->write_event_value &&
+		!indio_dev->info->write_event_value_new)
 		return -EINVAL;
 
-	ret = kstrtoint(buf, 10, &val);
-	if (ret)
-		return ret;
-
-	ret = indio_dev->info->write_event_value(indio_dev, this_attr->address,
-						 val);
+	if (indio_dev->info->write_event_value) {
+		ret = kstrtoint(buf, 10, &val);
+		if (ret)
+			return ret;
+		ret = indio_dev->info->write_event_value(indio_dev,
+			this_attr->address, val);
+	} else {
+		ret = iio_str_to_fixpoint(buf, 100000, &val, &val2);
+		if (ret)
+			return ret;
+		ret = indio_dev->info->write_event_value_new(indio_dev,
+			this_attr->c, iio_ev_attr_type(this_attr),
+			iio_ev_attr_dir(this_attr), iio_ev_attr_info(this_attr),
+			val, val2);
+	}
 	if (ret < 0)
 		return ret;
 
 	return len;
 }
 
-static int iio_device_add_event_sysfs(struct iio_dev *indio_dev,
+static int iio_device_add_event(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, unsigned int spec_index,
+	enum iio_event_type type, enum iio_event_direction dir,
+	enum iio_shared_by shared_by, const unsigned long *mask)
+{
+	ssize_t (*show)(struct device *, struct device_attribute *, char *);
+	ssize_t (*store)(struct device *, struct device_attribute *,
+		const char *, size_t);
+	unsigned int attrcount = 0;
+	unsigned int i;
+	char *postfix;
+	int ret;
+
+	for_each_set_bit(i, mask, sizeof(*mask)) {
+		postfix = kasprintf(GFP_KERNEL, "%s_%s_%s",
+				iio_ev_type_text[type], iio_ev_dir_text[dir],
+				iio_ev_info_text[i]);
+		if (postfix == NULL)
+			return -ENOMEM;
+
+		if (i == IIO_EV_INFO_ENABLE) {
+			show = iio_ev_state_show;
+			store = iio_ev_state_store;
+		} else {
+			show = iio_ev_value_show;
+			store = iio_ev_value_store;
+		}
+
+		ret = __iio_add_chan_devattr(postfix, chan, show, store,
+			 (i << 16) | spec_index, shared_by, &indio_dev->dev,
+			&indio_dev->event_interface->dev_attr_list);
+		kfree(postfix);
+
+		if (ret)
+			return ret;
+
+		attrcount++;
+	}
+
+	return attrcount;
+}
+
+static int iio_device_add_event_sysfs_new(struct iio_dev *indio_dev,
+	struct iio_chan_spec const *chan)
+{
+	int ret = 0, i, attrcount = 0;
+	enum iio_event_direction dir;
+	enum iio_event_type type;
+
+	for (i = 0; i < chan->num_event_specs; i++) {
+		type = chan->event_spec[i].type;
+		dir = chan->event_spec[i].dir;
+
+		ret = iio_device_add_event(indio_dev, chan, i, type, dir,
+			IIO_SEPARATE, &chan->event_spec[i].mask_separate);
+		if (ret < 0)
+			goto error_ret;
+		attrcount += ret;
+
+		ret = iio_device_add_event(indio_dev, chan, i, type, dir,
+			IIO_SHARED_BY_TYPE,
+			&chan->event_spec[i].mask_shared_by_type);
+		if (ret < 0)
+			goto error_ret;
+		attrcount += ret;
+
+		ret = iio_device_add_event(indio_dev, chan, i, type, dir,
+			IIO_SHARED_BY_DIR,
+			&chan->event_spec[i].mask_shared_by_dir);
+		if (ret < 0)
+			goto error_ret;
+		attrcount += ret;
+
+		ret = iio_device_add_event(indio_dev, chan, i, type, dir,
+			IIO_SHARED_BY_ALL,
+			&chan->event_spec[i].mask_shared_by_all);
+		if (ret < 0)
+			goto error_ret;
+		attrcount += ret;
+	}
+	ret = attrcount;
+error_ret:
+	return ret;
+}
+
+static int iio_device_add_event_sysfs_old(struct iio_dev *indio_dev,
 				      struct iio_chan_spec const *chan)
 {
 	int ret = 0, i, attrcount = 0;
@@ -339,15 +487,14 @@
 	return ret;
 }
 
-static inline void __iio_remove_event_config_attrs(struct iio_dev *indio_dev)
+
+static int iio_device_add_event_sysfs(struct iio_dev *indio_dev,
+				      struct iio_chan_spec const *chan)
 {
-	struct iio_dev_attr *p, *n;
-	list_for_each_entry_safe(p, n,
-				 &indio_dev->event_interface->
-				 dev_attr_list, l) {
-		kfree(p->dev_attr.attr.name);
-		kfree(p);
-	}
+	if (chan->event_mask)
+		return iio_device_add_event_sysfs_old(indio_dev, chan);
+	else
+		return iio_device_add_event_sysfs_new(indio_dev, chan);
 }
 
 static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev)
@@ -369,9 +516,12 @@
 {
 	int j;
 
-	for (j = 0; j < indio_dev->num_channels; j++)
+	for (j = 0; j < indio_dev->num_channels; j++) {
 		if (indio_dev->channels[j].event_mask != 0)
 			return true;
+		if (indio_dev->channels[j].num_event_specs != 0)
+			return true;
+	}
 	return false;
 }
 
@@ -441,18 +591,32 @@
 	return 0;
 
 error_free_setup_event_lines:
-	__iio_remove_event_config_attrs(indio_dev);
+	iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list);
 	kfree(indio_dev->event_interface);
 error_ret:
 
 	return ret;
 }
 
+/**
+ * iio_device_wakeup_eventset - Wakes up the event waitqueue
+ * @indio_dev: The IIO device
+ *
+ * Wakes up the event waitqueue used for poll() and blocking read().
+ * Should usually be called when the device is unregistered.
+ */
+void iio_device_wakeup_eventset(struct iio_dev *indio_dev)
+{
+	if (indio_dev->event_interface == NULL)
+		return;
+	wake_up(&indio_dev->event_interface->wait);
+}
+
 void iio_device_unregister_eventset(struct iio_dev *indio_dev)
 {
 	if (indio_dev->event_interface == NULL)
 		return;
-	__iio_remove_event_config_attrs(indio_dev);
+	iio_free_chan_devattr_list(&indio_dev->event_interface->dev_attr_list);
 	kfree(indio_dev->event_interface->group.attrs);
 	kfree(indio_dev->event_interface);
 }
diff --git a/drivers/iio/industrialio-triggered-buffer.c b/drivers/iio/industrialio-triggered-buffer.c
index 46c619b..d6f54930 100644
--- a/drivers/iio/industrialio-triggered-buffer.c
+++ b/drivers/iio/industrialio-triggered-buffer.c
@@ -17,7 +17,6 @@
 #include <linux/iio/trigger_consumer.h>
 
 static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
-	.preenable = &iio_sw_buffer_preenable,
 	.postenable = &iio_triggered_buffer_postenable,
 	.predisable = &iio_triggered_buffer_predisable,
 };
@@ -47,14 +46,17 @@
 	irqreturn_t (*pollfunc_th)(int irq, void *p),
 	const struct iio_buffer_setup_ops *setup_ops)
 {
+	struct iio_buffer *buffer;
 	int ret;
 
-	indio_dev->buffer = iio_kfifo_allocate(indio_dev);
-	if (!indio_dev->buffer) {
+	buffer = iio_kfifo_allocate(indio_dev);
+	if (!buffer) {
 		ret = -ENOMEM;
 		goto error_ret;
 	}
 
+	iio_device_attach_buffer(indio_dev, buffer);
+
 	indio_dev->pollfunc = iio_alloc_pollfunc(pollfunc_bh,
 						 pollfunc_th,
 						 IRQF_ONESHOT,
diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c
index a923c78..95c6fc8 100644
--- a/drivers/iio/kfifo_buf.c
+++ b/drivers/iio/kfifo_buf.c
@@ -7,10 +7,12 @@
 #include <linux/mutex.h>
 #include <linux/iio/kfifo_buf.h>
 #include <linux/sched.h>
+#include <linux/poll.h>
 
 struct iio_kfifo {
 	struct iio_buffer buffer;
 	struct kfifo kf;
+	struct mutex user_lock;
 	int update_needed;
 };
 
@@ -31,13 +33,18 @@
 	int ret = 0;
 	struct iio_kfifo *buf = iio_to_kfifo(r);
 
-	if (!buf->update_needed)
-		goto error_ret;
-	kfifo_free(&buf->kf);
-	ret = __iio_allocate_kfifo(buf, buf->buffer.bytes_per_datum,
+	mutex_lock(&buf->user_lock);
+	if (buf->update_needed) {
+		kfifo_free(&buf->kf);
+		ret = __iio_allocate_kfifo(buf, buf->buffer.bytes_per_datum,
 				   buf->buffer.length);
+		buf->update_needed = false;
+	} else {
+		kfifo_reset_out(&buf->kf);
+	}
 	r->stufftoread = false;
-error_ret:
+	mutex_unlock(&buf->user_lock);
+
 	return ret;
 }
 
@@ -94,7 +101,7 @@
 }
 
 static int iio_store_to_kfifo(struct iio_buffer *r,
-			      u8 *data)
+			      const void *data)
 {
 	int ret;
 	struct iio_kfifo *kf = iio_to_kfifo(r);
@@ -102,7 +109,7 @@
 	if (ret != 1)
 		return -EBUSY;
 	r->stufftoread = true;
-	wake_up_interruptible(&r->pollq);
+	wake_up_interruptible_poll(&r->pollq, POLLIN | POLLRDNORM);
 
 	return 0;
 }
@@ -113,12 +120,13 @@
 	int ret, copied;
 	struct iio_kfifo *kf = iio_to_kfifo(r);
 
-	if (n < r->bytes_per_datum || r->bytes_per_datum == 0)
-		return -EINVAL;
+	if (mutex_lock_interruptible(&kf->user_lock))
+		return -ERESTARTSYS;
 
-	ret = kfifo_to_user(&kf->kf, buf, n, &copied);
-	if (ret < 0)
-		return ret;
+	if (!kfifo_initialized(&kf->kf) || n < kfifo_esize(&kf->kf))
+		ret = -EINVAL;
+	else
+		ret = kfifo_to_user(&kf->kf, buf, n, &copied);
 
 	if (kfifo_is_empty(&kf->kf))
 		r->stufftoread = false;
@@ -126,9 +134,22 @@
 	if (!kfifo_is_empty(&kf->kf))
 		r->stufftoread = true;
 
+	mutex_unlock(&kf->user_lock);
+	if (ret < 0)
+		return ret;
+
 	return copied;
 }
 
+static void iio_kfifo_buffer_release(struct iio_buffer *buffer)
+{
+	struct iio_kfifo *kf = iio_to_kfifo(buffer);
+
+	mutex_destroy(&kf->user_lock);
+	kfifo_free(&kf->kf);
+	kfree(kf);
+}
+
 static const struct iio_buffer_access_funcs kfifo_access_funcs = {
 	.store_to = &iio_store_to_kfifo,
 	.read_first_n = &iio_read_first_n_kfifo,
@@ -137,6 +158,7 @@
 	.set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo,
 	.get_length = &iio_get_length_kfifo,
 	.set_length = &iio_set_length_kfifo,
+	.release = &iio_kfifo_buffer_release,
 };
 
 struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev)
@@ -151,13 +173,14 @@
 	kf->buffer.attrs = &iio_kfifo_attribute_group;
 	kf->buffer.access = &kfifo_access_funcs;
 	kf->buffer.length = 2;
+	mutex_init(&kf->user_lock);
 	return &kf->buffer;
 }
 EXPORT_SYMBOL(iio_kfifo_allocate);
 
 void iio_kfifo_free(struct iio_buffer *r)
 {
-	kfree(iio_to_kfifo(r));
+	iio_buffer_put(r);
 }
 EXPORT_SYMBOL(iio_kfifo_free);
 
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index bf9fa0d..f98c2b5 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -27,6 +27,29 @@
 	 To compile this driver as a module, choose M here: the
 	 module will be called apds9300.
 
+config CM36651
+	depends on I2C
+	tristate "CM36651 driver"
+	help
+	 Say Y here if you use cm36651.
+	 This option enables proximity & RGB sensor using
+	 Capella cm36651 device driver.
+
+	 To compile this driver as a module, choose M here:
+	 the module will be called cm36651.
+
+config GP2AP020A00F
+	tristate "Sharp GP2AP020A00F Proximity/ALS sensor"
+	depends on I2C
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	help
+	  Say Y here if you have a Sharp GP2AP020A00F proximity/ALS combo-chip
+	  hooked to an I2C bus.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gp2ap020a00f.
+
 config HID_SENSOR_ALS
 	depends on HID_SENSOR_HUB
 	select IIO_BUFFER
@@ -55,6 +78,16 @@
 	  changes. The ALS-control output values can be set per zone for the
 	  three current output channels.
 
+config TCS3472
+	tristate "TAOS TCS3472 color light-to-digital converter"
+	depends on I2C
+	help
+	 If you say yes here you get support for the TAOS TCS3472
+	 family of color light-to-digital converters with IR filter.
+
+	 This driver can also be built as a module.  If so, the module
+	 will be called tcs3472.
+
 config SENSORS_TSL2563
 	tristate "TAOS TSL2560, TSL2561, TSL2562 and TSL2563 ambient light sensors"
 	depends on I2C
@@ -65,6 +98,16 @@
 	 This driver can also be built as a module.  If so, the module
 	 will be called tsl2563.
 
+config TSL4531
+	tristate "TAOS TSL4531 ambient light sensors"
+	depends on I2C
+	help
+	 Say Y here if you want to build a driver for the TAOS TSL4531 family
+	 of ambient light sensors with direct lux output.
+
+	 To compile this driver as a module, choose M here: the
+	 module will be called tsl4531.
+
 config VCNL4000
 	tristate "VCNL4000 combined ALS and proximity sensor"
 	depends on I2C
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
index 354ee9a..daa327f 100644
--- a/drivers/iio/light/Makefile
+++ b/drivers/iio/light/Makefile
@@ -5,7 +5,11 @@
 # When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_ADJD_S311)		+= adjd_s311.o
 obj-$(CONFIG_APDS9300)		+= apds9300.o
+obj-$(CONFIG_CM36651)		+= cm36651.o
+obj-$(CONFIG_GP2AP020A00F)	+= gp2ap020a00f.o
 obj-$(CONFIG_HID_SENSOR_ALS)	+= hid-sensor-als.o
 obj-$(CONFIG_SENSORS_LM3533)	+= lm3533-als.o
 obj-$(CONFIG_SENSORS_TSL2563)	+= tsl2563.o
+obj-$(CONFIG_TCS3472)		+= tcs3472.o
+obj-$(CONFIG_TSL4531)		+= tsl4531.o
 obj-$(CONFIG_VCNL4000)		+= vcnl4000.o
diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c
index 23cff79..83d15c5 100644
--- a/drivers/iio/light/adjd_s311.c
+++ b/drivers/iio/light/adjd_s311.c
@@ -114,43 +114,6 @@
 	return 0;
 }
 
-static ssize_t adjd_s311_read_int_time(struct iio_dev *indio_dev,
-	uintptr_t private, const struct iio_chan_spec *chan, char *buf)
-{
-	struct adjd_s311_data *data = iio_priv(indio_dev);
-	s32 ret;
-
-	ret = i2c_smbus_read_word_data(data->client,
-		ADJD_S311_INT_REG(chan->address));
-	if (ret < 0)
-		return ret;
-
-	return sprintf(buf, "%d\n", ret & ADJD_S311_INT_MASK);
-}
-
-static ssize_t adjd_s311_write_int_time(struct iio_dev *indio_dev,
-	 uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
-	 size_t len)
-{
-	struct adjd_s311_data *data = iio_priv(indio_dev);
-	unsigned long int_time;
-	int ret;
-
-	ret = kstrtoul(buf, 10, &int_time);
-	if (ret)
-		return ret;
-
-	if (int_time > ADJD_S311_INT_MASK)
-		return -EINVAL;
-
-	ret = i2c_smbus_write_word_data(data->client,
-		ADJD_S311_INT_REG(chan->address), int_time);
-	if (ret < 0)
-		return ret;
-
-	return len;
-}
-
 static irqreturn_t adjd_s311_trigger_handler(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
@@ -175,10 +138,7 @@
 		len += 2;
 	}
 
-	if (indio_dev->scan_timestamp)
-		*(s64 *)((u8 *)data->buffer + ALIGN(len, sizeof(s64)))
-			= time_ns;
-	iio_push_to_buffers(indio_dev, (u8 *)data->buffer);
+	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, time_ns);
 
 done:
 	iio_trigger_notify_done(indio_dev->trig);
@@ -186,25 +146,16 @@
 	return IRQ_HANDLED;
 }
 
-static const struct iio_chan_spec_ext_info adjd_s311_ext_info[] = {
-	{
-		.name = "integration_time",
-		.read = adjd_s311_read_int_time,
-		.write = adjd_s311_write_int_time,
-	},
-	{ }
-};
-
 #define ADJD_S311_CHANNEL(_color, _scan_idx) { \
 	.type = IIO_INTENSITY, \
 	.modified = 1, \
 	.address = (IDX_##_color), \
 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
-		BIT(IIO_CHAN_INFO_HARDWAREGAIN), \
+		BIT(IIO_CHAN_INFO_HARDWAREGAIN) | \
+		BIT(IIO_CHAN_INFO_INT_TIME), \
 	.channel2 = (IIO_MOD_LIGHT_##_color), \
 	.scan_index = (_scan_idx), \
 	.scan_type = IIO_ST('u', 10, 16, 0), \
-	.ext_info = adjd_s311_ext_info, \
 }
 
 static const struct iio_chan_spec adjd_s311_channels[] = {
@@ -236,6 +187,18 @@
 			return ret;
 		*val = ret & ADJD_S311_CAP_MASK;
 		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_INT_TIME:
+		ret = i2c_smbus_read_word_data(data->client,
+			ADJD_S311_INT_REG(chan->address));
+		if (ret < 0)
+			return ret;
+		*val = 0;
+		/*
+		 * not documented, based on measurement:
+		 * 4095 LSBs correspond to roughly 4 ms
+		 */
+		*val2 = ret & ADJD_S311_INT_MASK;
+		return IIO_VAL_INT_PLUS_MICRO;
 	}
 	return -EINVAL;
 }
@@ -245,16 +208,20 @@
 			       int val, int val2, long mask)
 {
 	struct adjd_s311_data *data = iio_priv(indio_dev);
-	int ret;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_HARDWAREGAIN:
 		if (val < 0 || val > ADJD_S311_CAP_MASK)
 			return -EINVAL;
 
-		ret = i2c_smbus_write_byte_data(data->client,
+		return i2c_smbus_write_byte_data(data->client,
 			ADJD_S311_CAP_REG(chan->address), val);
-		return ret;
+	case IIO_CHAN_INFO_INT_TIME:
+		if (val != 0 || val2 < 0 || val2 > ADJD_S311_INT_MASK)
+			return -EINVAL;
+
+		return i2c_smbus_write_word_data(data->client,
+			ADJD_S311_INT_REG(chan->address), val2);
 	}
 	return -EINVAL;
 }
diff --git a/drivers/iio/light/apds9300.c b/drivers/iio/light/apds9300.c
index 66a58bd..51097bb 100644
--- a/drivers/iio/light/apds9300.c
+++ b/drivers/iio/light/apds9300.c
@@ -273,12 +273,14 @@
 	return ret;
 }
 
-static int apds9300_read_thresh(struct iio_dev *indio_dev, u64 event_code,
-		int *val)
+static int apds9300_read_thresh(struct iio_dev *indio_dev,
+		const struct iio_chan_spec *chan, enum iio_event_type type,
+		enum iio_event_direction dir, enum iio_event_info info,
+		int *val, int *val2)
 {
 	struct apds9300_data *data = iio_priv(indio_dev);
 
-	switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
+	switch (dir) {
 	case IIO_EV_DIR_RISING:
 		*val = data->thresh_hi;
 		break;
@@ -289,17 +291,19 @@
 		return -EINVAL;
 	}
 
-	return 0;
+	return IIO_VAL_INT;
 }
 
-static int apds9300_write_thresh(struct iio_dev *indio_dev, u64 event_code,
-		int val)
+static int apds9300_write_thresh(struct iio_dev *indio_dev,
+		const struct iio_chan_spec *chan, enum iio_event_type type,
+		enum iio_event_direction dir, enum iio_event_info info, int val,
+		int val2)
 {
 	struct apds9300_data *data = iio_priv(indio_dev);
 	int ret;
 
 	mutex_lock(&data->mutex);
-	if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING)
+	if (dir == IIO_EV_DIR_RISING)
 		ret = apds9300_set_thresh_hi(data, val);
 	else
 		ret = apds9300_set_thresh_low(data, val);
@@ -309,7 +313,9 @@
 }
 
 static int apds9300_read_interrupt_config(struct iio_dev *indio_dev,
-		u64 event_code)
+		const struct iio_chan_spec *chan,
+		enum iio_event_type type,
+		enum iio_event_direction dir)
 {
 	struct apds9300_data *data = iio_priv(indio_dev);
 
@@ -317,7 +323,8 @@
 }
 
 static int apds9300_write_interrupt_config(struct iio_dev *indio_dev,
-		u64 event_code, int state)
+		const struct iio_chan_spec *chan, enum iio_event_type type,
+		enum iio_event_direction dir, int state)
 {
 	struct apds9300_data *data = iio_priv(indio_dev);
 	int ret;
@@ -337,10 +344,24 @@
 static const struct iio_info apds9300_info = {
 	.driver_module		= THIS_MODULE,
 	.read_raw		= apds9300_read_raw,
-	.read_event_value	= apds9300_read_thresh,
-	.write_event_value	= apds9300_write_thresh,
-	.read_event_config	= apds9300_read_interrupt_config,
-	.write_event_config	= apds9300_write_interrupt_config,
+	.read_event_value_new	= apds9300_read_thresh,
+	.write_event_value_new	= apds9300_write_thresh,
+	.read_event_config_new	= apds9300_read_interrupt_config,
+	.write_event_config_new	= apds9300_write_interrupt_config,
+};
+
+static const struct iio_event_spec apds9300_event_spec[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	},
 };
 
 static const struct iio_chan_spec apds9300_channels[] = {
@@ -355,10 +376,8 @@
 		.channel2 = IIO_MOD_LIGHT_BOTH,
 		.indexed = true,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-		.event_mask = (IIO_EV_BIT(IIO_EV_TYPE_THRESH,
-					  IIO_EV_DIR_RISING) |
-			       IIO_EV_BIT(IIO_EV_TYPE_THRESH,
-					  IIO_EV_DIR_FALLING)),
+		.event_spec = apds9300_event_spec,
+		.num_event_specs = ARRAY_SIZE(apds9300_event_spec),
 	}, {
 		.type = IIO_INTENSITY,
 		.channel = 1,
diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c
new file mode 100644
index 0000000..21df571
--- /dev/null
+++ b/drivers/iio/light/cm36651.c
@@ -0,0 +1,708 @@
+/*
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Beomho Seo <beomho.seo@samsung.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General Public License version 2, as published
+ * by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/regulator/consumer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
+
+/* Slave address 0x19 for PS of 7 bit addressing protocol for I2C */
+#define CM36651_I2C_ADDR_PS		0x19
+/* Alert Response Address */
+#define CM36651_ARA			0x0C
+
+/* Ambient light sensor */
+#define CM36651_CS_CONF1		0x00
+#define CM36651_CS_CONF2		0x01
+#define CM36651_ALS_WH_M		0x02
+#define CM36651_ALS_WH_L		0x03
+#define CM36651_ALS_WL_M		0x04
+#define CM36651_ALS_WL_L		0x05
+#define CM36651_CS_CONF3		0x06
+#define CM36651_CS_CONF_REG_NUM		0x02
+
+/* Proximity sensor */
+#define CM36651_PS_CONF1		0x00
+#define CM36651_PS_THD			0x01
+#define CM36651_PS_CANC			0x02
+#define CM36651_PS_CONF2		0x03
+#define CM36651_PS_REG_NUM		0x04
+
+/* CS_CONF1 command code */
+#define CM36651_ALS_ENABLE		0x00
+#define CM36651_ALS_DISABLE		0x01
+#define CM36651_ALS_INT_EN		0x02
+#define CM36651_ALS_THRES		0x04
+
+/* CS_CONF2 command code */
+#define CM36651_CS_CONF2_DEFAULT_BIT	0x08
+
+/* CS_CONF3 channel integration time */
+#define CM36651_CS_IT1			0x00 /* Integration time 80000 usec */
+#define CM36651_CS_IT2			0x40 /* Integration time 160000 usec */
+#define CM36651_CS_IT3			0x80 /* Integration time 320000 usec */
+#define CM36651_CS_IT4			0xC0 /* Integration time 640000 usec */
+
+/* PS_CONF1 command code */
+#define CM36651_PS_ENABLE		0x00
+#define CM36651_PS_DISABLE		0x01
+#define CM36651_PS_INT_EN		0x02
+#define CM36651_PS_PERS2		0x04
+#define CM36651_PS_PERS3		0x08
+#define CM36651_PS_PERS4		0x0C
+
+/* PS_CONF1 command code: integration time */
+#define CM36651_PS_IT1			0x00 /* Integration time 320 usec */
+#define CM36651_PS_IT2			0x10 /* Integration time 420 usec */
+#define CM36651_PS_IT3			0x20 /* Integration time 520 usec */
+#define CM36651_PS_IT4			0x30 /* Integration time 640 usec */
+
+/* PS_CONF1 command code: duty ratio */
+#define CM36651_PS_DR1			0x00 /* Duty ratio 1/80 */
+#define CM36651_PS_DR2			0x40 /* Duty ratio 1/160 */
+#define CM36651_PS_DR3			0x80 /* Duty ratio 1/320 */
+#define CM36651_PS_DR4			0xC0 /* Duty ratio 1/640 */
+
+/* PS_THD command code */
+#define CM36651_PS_INITIAL_THD		0x05
+
+/* PS_CANC command code */
+#define CM36651_PS_CANC_DEFAULT		0x00
+
+/* PS_CONF2 command code */
+#define CM36651_PS_HYS1			0x00
+#define CM36651_PS_HYS2			0x01
+#define CM36651_PS_SMART_PERS_EN	0x02
+#define CM36651_PS_DIR_INT		0x04
+#define CM36651_PS_MS			0x10
+
+#define CM36651_CS_COLOR_NUM		4
+
+#define CM36651_CLOSE_PROXIMITY		0x32
+#define CM36651_FAR_PROXIMITY			0x33
+
+#define CM36651_CS_INT_TIME_AVAIL	"80000 160000 320000 640000"
+#define CM36651_PS_INT_TIME_AVAIL	"320 420 520 640"
+
+enum cm36651_operation_mode {
+	CM36651_LIGHT_EN,
+	CM36651_PROXIMITY_EN,
+	CM36651_PROXIMITY_EV_EN,
+};
+
+enum cm36651_light_channel_idx {
+	CM36651_LIGHT_CHANNEL_IDX_RED,
+	CM36651_LIGHT_CHANNEL_IDX_GREEN,
+	CM36651_LIGHT_CHANNEL_IDX_BLUE,
+	CM36651_LIGHT_CHANNEL_IDX_CLEAR,
+};
+
+enum cm36651_command {
+	CM36651_CMD_READ_RAW_LIGHT,
+	CM36651_CMD_READ_RAW_PROXIMITY,
+	CM36651_CMD_PROX_EV_EN,
+	CM36651_CMD_PROX_EV_DIS,
+};
+
+static const u8 cm36651_cs_reg[CM36651_CS_CONF_REG_NUM] = {
+	CM36651_CS_CONF1,
+	CM36651_CS_CONF2,
+};
+
+static const u8 cm36651_ps_reg[CM36651_PS_REG_NUM] = {
+	CM36651_PS_CONF1,
+	CM36651_PS_THD,
+	CM36651_PS_CANC,
+	CM36651_PS_CONF2,
+};
+
+struct cm36651_data {
+	const struct cm36651_platform_data *pdata;
+	struct i2c_client *client;
+	struct i2c_client *ps_client;
+	struct i2c_client *ara_client;
+	struct mutex lock;
+	struct regulator *vled_reg;
+	unsigned long flags;
+	int cs_int_time[CM36651_CS_COLOR_NUM];
+	int ps_int_time;
+	u8 cs_ctrl_regs[CM36651_CS_CONF_REG_NUM];
+	u8 ps_ctrl_regs[CM36651_PS_REG_NUM];
+	u16 color[CM36651_CS_COLOR_NUM];
+};
+
+static int cm36651_setup_reg(struct cm36651_data *cm36651)
+{
+	struct i2c_client *client = cm36651->client;
+	struct i2c_client *ps_client = cm36651->ps_client;
+	int i, ret;
+
+	/* CS initialization */
+	cm36651->cs_ctrl_regs[CM36651_CS_CONF1] = CM36651_ALS_ENABLE |
+							     CM36651_ALS_THRES;
+	cm36651->cs_ctrl_regs[CM36651_CS_CONF2] = CM36651_CS_CONF2_DEFAULT_BIT;
+
+	for (i = 0; i < CM36651_CS_CONF_REG_NUM; i++) {
+		ret = i2c_smbus_write_byte_data(client, cm36651_cs_reg[i],
+						     cm36651->cs_ctrl_regs[i]);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* PS initialization */
+	cm36651->ps_ctrl_regs[CM36651_PS_CONF1] = CM36651_PS_ENABLE |
+								CM36651_PS_IT2;
+	cm36651->ps_ctrl_regs[CM36651_PS_THD] = CM36651_PS_INITIAL_THD;
+	cm36651->ps_ctrl_regs[CM36651_PS_CANC] = CM36651_PS_CANC_DEFAULT;
+	cm36651->ps_ctrl_regs[CM36651_PS_CONF2] = CM36651_PS_HYS2 |
+				CM36651_PS_DIR_INT | CM36651_PS_SMART_PERS_EN;
+
+	for (i = 0; i < CM36651_PS_REG_NUM; i++) {
+		ret = i2c_smbus_write_byte_data(ps_client, cm36651_ps_reg[i],
+						     cm36651->ps_ctrl_regs[i]);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Set shutdown mode */
+	ret = i2c_smbus_write_byte_data(client, CM36651_CS_CONF1,
+							  CM36651_ALS_DISABLE);
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_smbus_write_byte_data(cm36651->ps_client,
+					 CM36651_PS_CONF1, CM36651_PS_DISABLE);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int cm36651_read_output(struct cm36651_data *cm36651,
+				struct iio_chan_spec const *chan, int *val)
+{
+	struct i2c_client *client = cm36651->client;
+	int ret = -EINVAL;
+
+	switch (chan->type) {
+	case IIO_LIGHT:
+		*val = i2c_smbus_read_word_data(client, chan->address);
+		if (*val < 0)
+			return ret;
+
+		ret = i2c_smbus_write_byte_data(client, CM36651_CS_CONF1,
+							CM36651_ALS_DISABLE);
+		if (ret < 0)
+			return ret;
+
+		ret = IIO_VAL_INT;
+		break;
+	case IIO_PROXIMITY:
+		*val = i2c_smbus_read_byte(cm36651->ps_client);
+		if (*val < 0)
+			return ret;
+
+		if (!test_bit(CM36651_PROXIMITY_EV_EN, &cm36651->flags)) {
+			ret = i2c_smbus_write_byte_data(cm36651->ps_client,
+					CM36651_PS_CONF1, CM36651_PS_DISABLE);
+			if (ret < 0)
+				return ret;
+		}
+
+		ret = IIO_VAL_INT;
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static irqreturn_t cm36651_irq_handler(int irq, void *data)
+{
+	struct iio_dev *indio_dev = data;
+	struct cm36651_data *cm36651 = iio_priv(indio_dev);
+	struct i2c_client *client = cm36651->client;
+	int ev_dir, ret;
+	u64 ev_code;
+
+	/*
+	 * The PS INT pin is an active low signal that PS INT move logic low
+	 * when the object is detect. Once the MCU host received the PS INT
+	 * "LOW" signal, the Host needs to read the data at Alert Response
+	 * Address(ARA) to clear the PS INT signal. After clearing the PS
+	 * INT pin, the PS INT signal toggles from low to high.
+	 */
+	ret = i2c_smbus_read_byte(cm36651->ara_client);
+	if (ret < 0) {
+		dev_err(&client->dev,
+				"%s: Data read failed: %d\n", __func__, ret);
+		return IRQ_HANDLED;
+	}
+	switch (ret) {
+	case CM36651_CLOSE_PROXIMITY:
+		ev_dir = IIO_EV_DIR_RISING;
+		break;
+	case CM36651_FAR_PROXIMITY:
+		ev_dir = IIO_EV_DIR_FALLING;
+		break;
+	default:
+		dev_err(&client->dev,
+			"%s: Data read wrong: %d\n", __func__, ret);
+		return IRQ_HANDLED;
+	}
+
+	ev_code = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY,
+				CM36651_CMD_READ_RAW_PROXIMITY,
+				IIO_EV_TYPE_THRESH, ev_dir);
+
+	iio_push_event(indio_dev, ev_code, iio_get_time_ns());
+
+	return IRQ_HANDLED;
+}
+
+static int cm36651_set_operation_mode(struct cm36651_data *cm36651, int cmd)
+{
+	struct i2c_client *client = cm36651->client;
+	struct i2c_client *ps_client = cm36651->ps_client;
+	int ret = -EINVAL;
+
+	switch (cmd) {
+	case CM36651_CMD_READ_RAW_LIGHT:
+		ret = i2c_smbus_write_byte_data(client, CM36651_CS_CONF1,
+				cm36651->cs_ctrl_regs[CM36651_CS_CONF1]);
+		break;
+	case CM36651_CMD_READ_RAW_PROXIMITY:
+		if (test_bit(CM36651_PROXIMITY_EV_EN, &cm36651->flags))
+			return CM36651_PROXIMITY_EV_EN;
+
+		ret = i2c_smbus_write_byte_data(ps_client, CM36651_PS_CONF1,
+				cm36651->ps_ctrl_regs[CM36651_PS_CONF1]);
+		break;
+	case CM36651_CMD_PROX_EV_EN:
+		if (test_bit(CM36651_PROXIMITY_EV_EN, &cm36651->flags)) {
+			dev_err(&client->dev,
+				"Already proximity event enable state\n");
+			return ret;
+		}
+		set_bit(CM36651_PROXIMITY_EV_EN, &cm36651->flags);
+
+		ret = i2c_smbus_write_byte_data(ps_client,
+			cm36651_ps_reg[CM36651_PS_CONF1],
+			CM36651_PS_INT_EN | CM36651_PS_PERS2 | CM36651_PS_IT2);
+
+		if (ret < 0) {
+			dev_err(&client->dev, "Proximity enable event failed\n");
+			return ret;
+		}
+		break;
+	case CM36651_CMD_PROX_EV_DIS:
+		if (!test_bit(CM36651_PROXIMITY_EV_EN, &cm36651->flags)) {
+			dev_err(&client->dev,
+				"Already proximity event disable state\n");
+			return ret;
+		}
+		clear_bit(CM36651_PROXIMITY_EV_EN, &cm36651->flags);
+		ret = i2c_smbus_write_byte_data(ps_client,
+					CM36651_PS_CONF1, CM36651_PS_DISABLE);
+		break;
+	}
+
+	if (ret < 0)
+		dev_err(&client->dev, "Write register failed\n");
+
+	return ret;
+}
+
+static int cm36651_read_channel(struct cm36651_data *cm36651,
+				struct iio_chan_spec const *chan, int *val)
+{
+	struct i2c_client *client = cm36651->client;
+	int cmd, ret;
+
+	if (chan->type == IIO_LIGHT)
+		cmd = CM36651_CMD_READ_RAW_LIGHT;
+	else if (chan->type == IIO_PROXIMITY)
+		cmd = CM36651_CMD_READ_RAW_PROXIMITY;
+	else
+		return -EINVAL;
+
+	ret = cm36651_set_operation_mode(cm36651, cmd);
+	if (ret < 0) {
+		dev_err(&client->dev, "CM36651 set operation mode failed\n");
+		return ret;
+	}
+	/* Delay for work after enable operation */
+	msleep(50);
+	ret = cm36651_read_output(cm36651, chan, val);
+	if (ret < 0) {
+		dev_err(&client->dev, "CM36651 read output failed\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static int cm36651_read_int_time(struct cm36651_data *cm36651,
+				struct iio_chan_spec const *chan, int *val)
+{
+	switch (chan->type) {
+	case IIO_LIGHT:
+		if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT1)
+			*val = 80000;
+		else if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT2)
+			*val = 160000;
+		else if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT3)
+			*val = 320000;
+		else if (cm36651->cs_int_time[chan->address] == CM36651_CS_IT4)
+			*val = 640000;
+		else
+			return -EINVAL;
+		break;
+	case IIO_PROXIMITY:
+		if (cm36651->ps_int_time == CM36651_PS_IT1)
+			*val = 320;
+		else if (cm36651->ps_int_time == CM36651_PS_IT2)
+			*val = 420;
+		else if (cm36651->ps_int_time == CM36651_PS_IT3)
+			*val = 520;
+		else if (cm36651->ps_int_time == CM36651_PS_IT4)
+			*val = 640;
+		else
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int cm36651_write_int_time(struct cm36651_data *cm36651,
+				struct iio_chan_spec const *chan, int val)
+{
+	struct i2c_client *client = cm36651->client;
+	struct i2c_client *ps_client = cm36651->ps_client;
+	int int_time, ret;
+
+	switch (chan->type) {
+	case IIO_LIGHT:
+		if (val == 80000)
+			int_time = CM36651_CS_IT1;
+		else if (val == 160000)
+			int_time = CM36651_CS_IT2;
+		else if (val == 320000)
+			int_time = CM36651_CS_IT3;
+		else if (val == 640000)
+			int_time = CM36651_CS_IT4;
+		else
+			return -EINVAL;
+
+		ret = i2c_smbus_write_byte_data(client, CM36651_CS_CONF3,
+					   int_time >> 2 * (chan->address));
+		if (ret < 0) {
+			dev_err(&client->dev, "CS integration time write failed\n");
+			return ret;
+		}
+		cm36651->cs_int_time[chan->address] = int_time;
+		break;
+	case IIO_PROXIMITY:
+		if (val == 320)
+			int_time = CM36651_PS_IT1;
+		else if (val == 420)
+			int_time = CM36651_PS_IT2;
+		else if (val == 520)
+			int_time = CM36651_PS_IT3;
+		else if (val == 640)
+			int_time = CM36651_PS_IT4;
+		else
+			return -EINVAL;
+
+		ret = i2c_smbus_write_byte_data(ps_client,
+						CM36651_PS_CONF1, int_time);
+		if (ret < 0) {
+			dev_err(&client->dev, "PS integration time write failed\n");
+			return ret;
+		}
+		cm36651->ps_int_time = int_time;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+static int cm36651_read_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int *val, int *val2, long mask)
+{
+	struct cm36651_data *cm36651 = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&cm36651->lock);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = cm36651_read_channel(cm36651, chan, val);
+		break;
+	case IIO_CHAN_INFO_INT_TIME:
+		ret = cm36651_read_int_time(cm36651, chan, val);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	mutex_unlock(&cm36651->lock);
+
+	return ret;
+}
+
+static int cm36651_write_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int val, int val2, long mask)
+{
+	struct cm36651_data *cm36651 = iio_priv(indio_dev);
+	struct i2c_client *client = cm36651->client;
+	int ret = -EINVAL;
+
+	if (mask == IIO_CHAN_INFO_INT_TIME) {
+		ret = cm36651_write_int_time(cm36651, chan, val);
+		if (ret < 0)
+			dev_err(&client->dev, "Integration time write failed\n");
+	}
+
+	return ret;
+}
+
+static int cm36651_read_prox_thresh(struct iio_dev *indio_dev,
+					u64 event_code, int *val)
+{
+	struct cm36651_data *cm36651 = iio_priv(indio_dev);
+
+	*val = cm36651->ps_ctrl_regs[CM36651_PS_THD];
+
+	return 0;
+}
+
+static int cm36651_write_prox_thresh(struct iio_dev *indio_dev,
+					u64 event_code, int val)
+{
+	struct cm36651_data *cm36651 = iio_priv(indio_dev);
+	struct i2c_client *client = cm36651->client;
+	int ret;
+
+	if (val < 3 || val > 255)
+		return -EINVAL;
+
+	cm36651->ps_ctrl_regs[CM36651_PS_THD] = val;
+	ret = i2c_smbus_write_byte_data(cm36651->ps_client, CM36651_PS_THD,
+					cm36651->ps_ctrl_regs[CM36651_PS_THD]);
+
+	if (ret < 0) {
+		dev_err(&client->dev, "PS threshold write failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int cm36651_write_prox_event_config(struct iio_dev *indio_dev,
+					u64 event_code, int state)
+{
+	struct cm36651_data *cm36651 = iio_priv(indio_dev);
+	int cmd, ret = -EINVAL;
+
+	mutex_lock(&cm36651->lock);
+
+	cmd = state ? CM36651_CMD_PROX_EV_EN : CM36651_CMD_PROX_EV_DIS;
+	ret = cm36651_set_operation_mode(cm36651, cmd);
+
+	mutex_unlock(&cm36651->lock);
+
+	return ret;
+}
+
+static int cm36651_read_prox_event_config(struct iio_dev *indio_dev,
+							u64 event_code)
+{
+	struct cm36651_data *cm36651 = iio_priv(indio_dev);
+	int event_en;
+
+	mutex_lock(&cm36651->lock);
+
+	event_en = test_bit(CM36651_PROXIMITY_EV_EN, &cm36651->flags);
+
+	mutex_unlock(&cm36651->lock);
+
+	return event_en;
+}
+
+#define CM36651_LIGHT_CHANNEL(_color, _idx) {		\
+	.type = IIO_LIGHT,				\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |	\
+			BIT(IIO_CHAN_INFO_INT_TIME),	\
+	.address = _idx,				\
+	.modified = 1,					\
+	.channel2 = IIO_MOD_LIGHT_##_color,		\
+}							\
+
+static const struct iio_chan_spec cm36651_channels[] = {
+	{
+		.type = IIO_PROXIMITY,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				BIT(IIO_CHAN_INFO_INT_TIME),
+		.event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_EITHER)
+	},
+	CM36651_LIGHT_CHANNEL(RED, CM36651_LIGHT_CHANNEL_IDX_RED),
+	CM36651_LIGHT_CHANNEL(GREEN, CM36651_LIGHT_CHANNEL_IDX_GREEN),
+	CM36651_LIGHT_CHANNEL(BLUE, CM36651_LIGHT_CHANNEL_IDX_BLUE),
+	CM36651_LIGHT_CHANNEL(CLEAR, CM36651_LIGHT_CHANNEL_IDX_CLEAR),
+};
+
+static IIO_CONST_ATTR(in_illuminance_integration_time_available,
+					CM36651_CS_INT_TIME_AVAIL);
+static IIO_CONST_ATTR(in_proximity_integration_time_available,
+					CM36651_PS_INT_TIME_AVAIL);
+
+static struct attribute *cm36651_attributes[] = {
+	&iio_const_attr_in_illuminance_integration_time_available.dev_attr.attr,
+	&iio_const_attr_in_proximity_integration_time_available.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group cm36651_attribute_group = {
+	.attrs = cm36651_attributes
+};
+
+static const struct iio_info cm36651_info = {
+	.driver_module		= THIS_MODULE,
+	.read_raw		= &cm36651_read_raw,
+	.write_raw		= &cm36651_write_raw,
+	.read_event_value	= &cm36651_read_prox_thresh,
+	.write_event_value	= &cm36651_write_prox_thresh,
+	.read_event_config	= &cm36651_read_prox_event_config,
+	.write_event_config	= &cm36651_write_prox_event_config,
+	.attrs			= &cm36651_attribute_group,
+};
+
+static int cm36651_probe(struct i2c_client *client,
+			     const struct i2c_device_id *id)
+{
+	struct cm36651_data *cm36651;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*cm36651));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	cm36651 = iio_priv(indio_dev);
+
+	cm36651->vled_reg = devm_regulator_get(&client->dev, "vled");
+	if (IS_ERR(cm36651->vled_reg)) {
+		dev_err(&client->dev, "get regulator vled failed\n");
+		return PTR_ERR(cm36651->vled_reg);
+	}
+
+	ret = regulator_enable(cm36651->vled_reg);
+	if (ret) {
+		dev_err(&client->dev, "enable regulator vled failed\n");
+		return ret;
+	}
+
+	i2c_set_clientdata(client, indio_dev);
+
+	cm36651->client = client;
+	cm36651->ps_client = i2c_new_dummy(client->adapter,
+						     CM36651_I2C_ADDR_PS);
+	cm36651->ara_client = i2c_new_dummy(client->adapter, CM36651_ARA);
+	mutex_init(&cm36651->lock);
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->channels = cm36651_channels;
+	indio_dev->num_channels = ARRAY_SIZE(cm36651_channels);
+	indio_dev->info = &cm36651_info;
+	indio_dev->name = id->name;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = cm36651_setup_reg(cm36651);
+	if (ret) {
+		dev_err(&client->dev, "%s: register setup failed\n", __func__);
+		goto error_disable_reg;
+	}
+
+	ret = request_threaded_irq(client->irq, NULL, cm36651_irq_handler,
+					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+							"cm36651", indio_dev);
+	if (ret) {
+		dev_err(&client->dev, "%s: request irq failed\n", __func__);
+		goto error_disable_reg;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&client->dev, "%s: regist device failed\n", __func__);
+		goto error_free_irq;
+	}
+
+	return 0;
+
+error_free_irq:
+	free_irq(client->irq, indio_dev);
+error_disable_reg:
+	regulator_disable(cm36651->vled_reg);
+	return ret;
+}
+
+static int cm36651_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct cm36651_data *cm36651 = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	regulator_disable(cm36651->vled_reg);
+	free_irq(client->irq, indio_dev);
+
+	return 0;
+}
+
+static const struct i2c_device_id cm36651_id[] = {
+	{ "cm36651", 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, cm36651_id);
+
+static const struct of_device_id cm36651_of_match[] = {
+	{ .compatible = "capella,cm36651" },
+	{ }
+};
+
+static struct i2c_driver cm36651_driver = {
+	.driver = {
+		.name	= "cm36651",
+		.of_match_table = of_match_ptr(cm36651_of_match),
+		.owner	= THIS_MODULE,
+	},
+	.probe		= cm36651_probe,
+	.remove		= cm36651_remove,
+	.id_table	= cm36651_id,
+};
+
+module_i2c_driver(cm36651_driver);
+
+MODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>");
+MODULE_DESCRIPTION("CM36651 proximity/ambient light sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c
new file mode 100644
index 0000000..dc79835
--- /dev/null
+++ b/drivers/iio/light/gp2ap020a00f.c
@@ -0,0 +1,1654 @@
+/*
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
+ *
+ * IIO features supported by the driver:
+ *
+ * Read-only raw channels:
+ *   - illiminance_clear [lux]
+ *   - illiminance_ir
+ *   - proximity
+ *
+ * Triggered buffer:
+ *   - illiminance_clear
+ *   - illiminance_ir
+ *   - proximity
+ *
+ * Events:
+ *   - illuminance_clear (rising and falling)
+ *   - proximity (rising and falling)
+ *     - both falling and rising thresholds for the proximity events
+ *       must be set to the values greater than 0.
+ *
+ * The driver supports triggered buffers for all the three
+ * channels as well as high and low threshold events for the
+ * illuminance_clear and proxmimity channels. Triggers
+ * can be enabled simultaneously with both illuminance_clear
+ * events. Proximity events cannot be enabled simultaneously
+ * with any triggers or illuminance events. Enabling/disabling
+ * one of the proximity events automatically enables/disables
+ * the other one.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irq_work.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/events.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define GP2A_I2C_NAME "gp2ap020a00f"
+
+/* Registers */
+#define GP2AP020A00F_OP_REG	0x00 /* Basic operations */
+#define GP2AP020A00F_ALS_REG	0x01 /* ALS related settings */
+#define GP2AP020A00F_PS_REG	0x02 /* PS related settings */
+#define GP2AP020A00F_LED_REG	0x03 /* LED reg */
+#define GP2AP020A00F_TL_L_REG	0x04 /* ALS: Threshold low LSB */
+#define GP2AP020A00F_TL_H_REG	0x05 /* ALS: Threshold low MSB */
+#define GP2AP020A00F_TH_L_REG	0x06 /* ALS: Threshold high LSB */
+#define GP2AP020A00F_TH_H_REG	0x07 /* ALS: Threshold high MSB */
+#define GP2AP020A00F_PL_L_REG	0x08 /* PS: Threshold low LSB */
+#define GP2AP020A00F_PL_H_REG	0x09 /* PS: Threshold low MSB */
+#define GP2AP020A00F_PH_L_REG	0x0a /* PS: Threshold high LSB */
+#define GP2AP020A00F_PH_H_REG	0x0b /* PS: Threshold high MSB */
+#define GP2AP020A00F_D0_L_REG	0x0c /* ALS result: Clear/Illuminance LSB */
+#define GP2AP020A00F_D0_H_REG	0x0d /* ALS result: Clear/Illuminance MSB */
+#define GP2AP020A00F_D1_L_REG	0x0e /* ALS result: IR LSB */
+#define GP2AP020A00F_D1_H_REG	0x0f /* ALS result: IR LSB */
+#define GP2AP020A00F_D2_L_REG	0x10 /* PS result LSB */
+#define GP2AP020A00F_D2_H_REG	0x11 /* PS result MSB */
+#define GP2AP020A00F_NUM_REGS	0x12 /* Number of registers */
+
+/* OP_REG bits */
+#define GP2AP020A00F_OP3_MASK		0x80 /* Software shutdown */
+#define GP2AP020A00F_OP3_SHUTDOWN	0x00
+#define GP2AP020A00F_OP3_OPERATION	0x80
+#define GP2AP020A00F_OP2_MASK		0x40 /* Auto shutdown/Continuous mode */
+#define GP2AP020A00F_OP2_AUTO_SHUTDOWN	0x00
+#define GP2AP020A00F_OP2_CONT_OPERATION	0x40
+#define GP2AP020A00F_OP_MASK		0x30 /* Operating mode selection  */
+#define GP2AP020A00F_OP_ALS_AND_PS	0x00
+#define GP2AP020A00F_OP_ALS		0x10
+#define GP2AP020A00F_OP_PS		0x20
+#define GP2AP020A00F_OP_DEBUG		0x30
+#define GP2AP020A00F_PROX_MASK		0x08 /* PS: detection/non-detection */
+#define GP2AP020A00F_PROX_NON_DETECT	0x00
+#define GP2AP020A00F_PROX_DETECT	0x08
+#define GP2AP020A00F_FLAG_P		0x04 /* PS: interrupt result  */
+#define GP2AP020A00F_FLAG_A		0x02 /* ALS: interrupt result  */
+#define GP2AP020A00F_TYPE_MASK		0x01 /* Output data type selection */
+#define GP2AP020A00F_TYPE_MANUAL_CALC	0x00
+#define GP2AP020A00F_TYPE_AUTO_CALC	0x01
+
+/* ALS_REG bits */
+#define GP2AP020A00F_PRST_MASK		0xc0 /* Number of measurement cycles */
+#define GP2AP020A00F_PRST_ONCE		0x00
+#define GP2AP020A00F_PRST_4_CYCLES	0x40
+#define GP2AP020A00F_PRST_8_CYCLES	0x80
+#define GP2AP020A00F_PRST_16_CYCLES	0xc0
+#define GP2AP020A00F_RES_A_MASK		0x38 /* ALS: Resolution */
+#define GP2AP020A00F_RES_A_800ms	0x00
+#define GP2AP020A00F_RES_A_400ms	0x08
+#define GP2AP020A00F_RES_A_200ms	0x10
+#define GP2AP020A00F_RES_A_100ms	0x18
+#define GP2AP020A00F_RES_A_25ms		0x20
+#define GP2AP020A00F_RES_A_6_25ms	0x28
+#define GP2AP020A00F_RES_A_1_56ms	0x30
+#define GP2AP020A00F_RES_A_0_39ms	0x38
+#define GP2AP020A00F_RANGE_A_MASK	0x07 /* ALS: Max measurable range */
+#define GP2AP020A00F_RANGE_A_x1		0x00
+#define GP2AP020A00F_RANGE_A_x2		0x01
+#define GP2AP020A00F_RANGE_A_x4		0x02
+#define GP2AP020A00F_RANGE_A_x8		0x03
+#define GP2AP020A00F_RANGE_A_x16	0x04
+#define GP2AP020A00F_RANGE_A_x32	0x05
+#define GP2AP020A00F_RANGE_A_x64	0x06
+#define GP2AP020A00F_RANGE_A_x128	0x07
+
+/* PS_REG bits */
+#define GP2AP020A00F_ALC_MASK		0x80 /* Auto light cancel */
+#define GP2AP020A00F_ALC_ON		0x80
+#define GP2AP020A00F_ALC_OFF		0x00
+#define GP2AP020A00F_INTTYPE_MASK	0x40 /* Interrupt type setting */
+#define GP2AP020A00F_INTTYPE_LEVEL	0x00
+#define GP2AP020A00F_INTTYPE_PULSE	0x40
+#define GP2AP020A00F_RES_P_MASK		0x38 /* PS: Resolution */
+#define GP2AP020A00F_RES_P_800ms_x2	0x00
+#define GP2AP020A00F_RES_P_400ms_x2	0x08
+#define GP2AP020A00F_RES_P_200ms_x2	0x10
+#define GP2AP020A00F_RES_P_100ms_x2	0x18
+#define GP2AP020A00F_RES_P_25ms_x2	0x20
+#define GP2AP020A00F_RES_P_6_25ms_x2	0x28
+#define GP2AP020A00F_RES_P_1_56ms_x2	0x30
+#define GP2AP020A00F_RES_P_0_39ms_x2	0x38
+#define GP2AP020A00F_RANGE_P_MASK	0x07 /* PS: Max measurable range */
+#define GP2AP020A00F_RANGE_P_x1		0x00
+#define GP2AP020A00F_RANGE_P_x2		0x01
+#define GP2AP020A00F_RANGE_P_x4		0x02
+#define GP2AP020A00F_RANGE_P_x8		0x03
+#define GP2AP020A00F_RANGE_P_x16	0x04
+#define GP2AP020A00F_RANGE_P_x32	0x05
+#define GP2AP020A00F_RANGE_P_x64	0x06
+#define GP2AP020A00F_RANGE_P_x128	0x07
+
+/* LED reg bits */
+#define GP2AP020A00F_INTVAL_MASK	0xc0 /* Intermittent operating */
+#define GP2AP020A00F_INTVAL_0		0x00
+#define GP2AP020A00F_INTVAL_4		0x40
+#define GP2AP020A00F_INTVAL_8		0x80
+#define GP2AP020A00F_INTVAL_16		0xc0
+#define GP2AP020A00F_IS_MASK		0x30 /* ILED drive peak current */
+#define GP2AP020A00F_IS_13_8mA		0x00
+#define GP2AP020A00F_IS_27_5mA		0x10
+#define GP2AP020A00F_IS_55mA		0x20
+#define GP2AP020A00F_IS_110mA		0x30
+#define GP2AP020A00F_PIN_MASK		0x0c /* INT terminal setting */
+#define GP2AP020A00F_PIN_ALS_OR_PS	0x00
+#define GP2AP020A00F_PIN_ALS		0x04
+#define GP2AP020A00F_PIN_PS		0x08
+#define GP2AP020A00F_PIN_PS_DETECT	0x0c
+#define GP2AP020A00F_FREQ_MASK		0x02 /* LED modulation frequency */
+#define GP2AP020A00F_FREQ_327_5kHz	0x00
+#define GP2AP020A00F_FREQ_81_8kHz	0x02
+#define GP2AP020A00F_RST		0x01 /* Software reset */
+
+#define GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR	0
+#define GP2AP020A00F_SCAN_MODE_LIGHT_IR		1
+#define GP2AP020A00F_SCAN_MODE_PROXIMITY	2
+#define GP2AP020A00F_CHAN_TIMESTAMP		3
+
+#define GP2AP020A00F_DATA_READY_TIMEOUT		msecs_to_jiffies(1000)
+#define GP2AP020A00F_DATA_REG(chan)		(GP2AP020A00F_D0_L_REG + \
+							(chan) * 2)
+#define GP2AP020A00F_THRESH_REG(th_val_id)	(GP2AP020A00F_TL_L_REG + \
+							(th_val_id) * 2)
+#define GP2AP020A00F_THRESH_VAL_ID(reg_addr)	((reg_addr - 4) / 2)
+
+#define GP2AP020A00F_SUBTRACT_MODE	0
+#define GP2AP020A00F_ADD_MODE		1
+
+#define GP2AP020A00F_MAX_CHANNELS	3
+
+enum gp2ap020a00f_opmode {
+	GP2AP020A00F_OPMODE_READ_RAW_CLEAR,
+	GP2AP020A00F_OPMODE_READ_RAW_IR,
+	GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY,
+	GP2AP020A00F_OPMODE_ALS,
+	GP2AP020A00F_OPMODE_PS,
+	GP2AP020A00F_OPMODE_ALS_AND_PS,
+	GP2AP020A00F_OPMODE_PROX_DETECT,
+	GP2AP020A00F_OPMODE_SHUTDOWN,
+	GP2AP020A00F_NUM_OPMODES,
+};
+
+enum gp2ap020a00f_cmd {
+	GP2AP020A00F_CMD_READ_RAW_CLEAR,
+	GP2AP020A00F_CMD_READ_RAW_IR,
+	GP2AP020A00F_CMD_READ_RAW_PROXIMITY,
+	GP2AP020A00F_CMD_TRIGGER_CLEAR_EN,
+	GP2AP020A00F_CMD_TRIGGER_CLEAR_DIS,
+	GP2AP020A00F_CMD_TRIGGER_IR_EN,
+	GP2AP020A00F_CMD_TRIGGER_IR_DIS,
+	GP2AP020A00F_CMD_TRIGGER_PROX_EN,
+	GP2AP020A00F_CMD_TRIGGER_PROX_DIS,
+	GP2AP020A00F_CMD_ALS_HIGH_EV_EN,
+	GP2AP020A00F_CMD_ALS_HIGH_EV_DIS,
+	GP2AP020A00F_CMD_ALS_LOW_EV_EN,
+	GP2AP020A00F_CMD_ALS_LOW_EV_DIS,
+	GP2AP020A00F_CMD_PROX_HIGH_EV_EN,
+	GP2AP020A00F_CMD_PROX_HIGH_EV_DIS,
+	GP2AP020A00F_CMD_PROX_LOW_EV_EN,
+	GP2AP020A00F_CMD_PROX_LOW_EV_DIS,
+};
+
+enum gp2ap020a00f_flags {
+	GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER,
+	GP2AP020A00F_FLAG_ALS_IR_TRIGGER,
+	GP2AP020A00F_FLAG_PROX_TRIGGER,
+	GP2AP020A00F_FLAG_PROX_RISING_EV,
+	GP2AP020A00F_FLAG_PROX_FALLING_EV,
+	GP2AP020A00F_FLAG_ALS_RISING_EV,
+	GP2AP020A00F_FLAG_ALS_FALLING_EV,
+	GP2AP020A00F_FLAG_LUX_MODE_HI,
+	GP2AP020A00F_FLAG_DATA_READY,
+};
+
+enum gp2ap020a00f_thresh_val_id {
+	GP2AP020A00F_THRESH_TL,
+	GP2AP020A00F_THRESH_TH,
+	GP2AP020A00F_THRESH_PL,
+	GP2AP020A00F_THRESH_PH,
+};
+
+struct gp2ap020a00f_data {
+	const struct gp2ap020a00f_platform_data *pdata;
+	struct i2c_client *client;
+	struct mutex lock;
+	char *buffer;
+	struct regulator *vled_reg;
+	unsigned long flags;
+	enum gp2ap020a00f_opmode cur_opmode;
+	struct iio_trigger *trig;
+	struct regmap *regmap;
+	unsigned int thresh_val[4];
+	u8 debug_reg_addr;
+	struct irq_work work;
+	wait_queue_head_t data_ready_queue;
+};
+
+static const u8 gp2ap020a00f_reg_init_tab[] = {
+	[GP2AP020A00F_OP_REG] = GP2AP020A00F_OP3_SHUTDOWN,
+	[GP2AP020A00F_ALS_REG] = GP2AP020A00F_RES_A_25ms |
+				 GP2AP020A00F_RANGE_A_x8,
+	[GP2AP020A00F_PS_REG] = GP2AP020A00F_ALC_ON |
+				GP2AP020A00F_RES_P_1_56ms_x2 |
+				GP2AP020A00F_RANGE_P_x4,
+	[GP2AP020A00F_LED_REG] = GP2AP020A00F_INTVAL_0 |
+				 GP2AP020A00F_IS_110mA |
+				 GP2AP020A00F_FREQ_327_5kHz,
+	[GP2AP020A00F_TL_L_REG] = 0,
+	[GP2AP020A00F_TL_H_REG] = 0,
+	[GP2AP020A00F_TH_L_REG] = 0,
+	[GP2AP020A00F_TH_H_REG] = 0,
+	[GP2AP020A00F_PL_L_REG] = 0,
+	[GP2AP020A00F_PL_H_REG] = 0,
+	[GP2AP020A00F_PH_L_REG] = 0,
+	[GP2AP020A00F_PH_H_REG] = 0,
+};
+
+static bool gp2ap020a00f_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case GP2AP020A00F_OP_REG:
+	case GP2AP020A00F_D0_L_REG:
+	case GP2AP020A00F_D0_H_REG:
+	case GP2AP020A00F_D1_L_REG:
+	case GP2AP020A00F_D1_H_REG:
+	case GP2AP020A00F_D2_L_REG:
+	case GP2AP020A00F_D2_H_REG:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct regmap_config gp2ap020a00f_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = GP2AP020A00F_D2_H_REG,
+	.cache_type = REGCACHE_RBTREE,
+
+	.volatile_reg = gp2ap020a00f_is_volatile_reg,
+};
+
+static const struct gp2ap020a00f_mutable_config_regs {
+	u8 op_reg;
+	u8 als_reg;
+	u8 ps_reg;
+	u8 led_reg;
+} opmode_regs_settings[GP2AP020A00F_NUM_OPMODES] = {
+	[GP2AP020A00F_OPMODE_READ_RAW_CLEAR] = {
+		GP2AP020A00F_OP_ALS | GP2AP020A00F_OP2_CONT_OPERATION
+		| GP2AP020A00F_OP3_OPERATION
+		| GP2AP020A00F_TYPE_AUTO_CALC,
+		GP2AP020A00F_PRST_ONCE,
+		GP2AP020A00F_INTTYPE_LEVEL,
+		GP2AP020A00F_PIN_ALS
+	},
+	[GP2AP020A00F_OPMODE_READ_RAW_IR] = {
+		GP2AP020A00F_OP_ALS | GP2AP020A00F_OP2_CONT_OPERATION
+		| GP2AP020A00F_OP3_OPERATION
+		| GP2AP020A00F_TYPE_MANUAL_CALC,
+		GP2AP020A00F_PRST_ONCE,
+		GP2AP020A00F_INTTYPE_LEVEL,
+		GP2AP020A00F_PIN_ALS
+	},
+	[GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY] = {
+		GP2AP020A00F_OP_PS | GP2AP020A00F_OP2_CONT_OPERATION
+		| GP2AP020A00F_OP3_OPERATION
+		| GP2AP020A00F_TYPE_MANUAL_CALC,
+		GP2AP020A00F_PRST_ONCE,
+		GP2AP020A00F_INTTYPE_LEVEL,
+		GP2AP020A00F_PIN_PS
+	},
+	[GP2AP020A00F_OPMODE_PROX_DETECT] = {
+		GP2AP020A00F_OP_PS | GP2AP020A00F_OP2_CONT_OPERATION
+		| GP2AP020A00F_OP3_OPERATION
+		| GP2AP020A00F_TYPE_MANUAL_CALC,
+		GP2AP020A00F_PRST_4_CYCLES,
+		GP2AP020A00F_INTTYPE_PULSE,
+		GP2AP020A00F_PIN_PS_DETECT
+	},
+	[GP2AP020A00F_OPMODE_ALS] = {
+		GP2AP020A00F_OP_ALS | GP2AP020A00F_OP2_CONT_OPERATION
+		| GP2AP020A00F_OP3_OPERATION
+		| GP2AP020A00F_TYPE_AUTO_CALC,
+		GP2AP020A00F_PRST_ONCE,
+		GP2AP020A00F_INTTYPE_LEVEL,
+		GP2AP020A00F_PIN_ALS
+	},
+	[GP2AP020A00F_OPMODE_PS] = {
+		GP2AP020A00F_OP_PS | GP2AP020A00F_OP2_CONT_OPERATION
+		| GP2AP020A00F_OP3_OPERATION
+		| GP2AP020A00F_TYPE_MANUAL_CALC,
+		GP2AP020A00F_PRST_4_CYCLES,
+		GP2AP020A00F_INTTYPE_LEVEL,
+		GP2AP020A00F_PIN_PS
+	},
+	[GP2AP020A00F_OPMODE_ALS_AND_PS] = {
+		GP2AP020A00F_OP_ALS_AND_PS
+		| GP2AP020A00F_OP2_CONT_OPERATION
+		| GP2AP020A00F_OP3_OPERATION
+		| GP2AP020A00F_TYPE_AUTO_CALC,
+		GP2AP020A00F_PRST_4_CYCLES,
+		GP2AP020A00F_INTTYPE_LEVEL,
+		GP2AP020A00F_PIN_ALS_OR_PS
+	},
+	[GP2AP020A00F_OPMODE_SHUTDOWN] = { GP2AP020A00F_OP3_SHUTDOWN, },
+};
+
+static int gp2ap020a00f_set_operation_mode(struct gp2ap020a00f_data *data,
+					enum gp2ap020a00f_opmode op)
+{
+	unsigned int op_reg_val;
+	int err;
+
+	if (op != GP2AP020A00F_OPMODE_SHUTDOWN) {
+		err = regmap_read(data->regmap, GP2AP020A00F_OP_REG,
+					&op_reg_val);
+		if (err < 0)
+			return err;
+		/*
+		 * Shutdown the device if the operation being executed entails
+		 * mode transition.
+		 */
+		if ((opmode_regs_settings[op].op_reg & GP2AP020A00F_OP_MASK) !=
+		    (op_reg_val & GP2AP020A00F_OP_MASK)) {
+			/* set shutdown mode */
+			err = regmap_update_bits(data->regmap,
+				GP2AP020A00F_OP_REG, GP2AP020A00F_OP3_MASK,
+				GP2AP020A00F_OP3_SHUTDOWN);
+			if (err < 0)
+				return err;
+		}
+
+		err = regmap_update_bits(data->regmap, GP2AP020A00F_ALS_REG,
+			GP2AP020A00F_PRST_MASK, opmode_regs_settings[op]
+								.als_reg);
+		if (err < 0)
+			return err;
+
+		err = regmap_update_bits(data->regmap, GP2AP020A00F_PS_REG,
+			GP2AP020A00F_INTTYPE_MASK, opmode_regs_settings[op]
+								.ps_reg);
+		if (err < 0)
+			return err;
+
+		err = regmap_update_bits(data->regmap, GP2AP020A00F_LED_REG,
+			GP2AP020A00F_PIN_MASK, opmode_regs_settings[op]
+								.led_reg);
+		if (err < 0)
+			return err;
+	}
+
+	/* Set OP_REG and apply operation mode (power on / off) */
+	err = regmap_update_bits(data->regmap,
+				 GP2AP020A00F_OP_REG,
+				 GP2AP020A00F_OP_MASK | GP2AP020A00F_OP2_MASK |
+				 GP2AP020A00F_OP3_MASK | GP2AP020A00F_TYPE_MASK,
+				 opmode_regs_settings[op].op_reg);
+	if (err < 0)
+		return err;
+
+	data->cur_opmode = op;
+
+	return 0;
+}
+
+static bool gp2ap020a00f_als_enabled(struct gp2ap020a00f_data *data)
+{
+	return test_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &data->flags) ||
+	       test_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &data->flags) ||
+	       test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags) ||
+	       test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags);
+}
+
+static bool gp2ap020a00f_prox_detect_enabled(struct gp2ap020a00f_data *data)
+{
+	return test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags) ||
+	       test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags);
+}
+
+static int gp2ap020a00f_write_event_threshold(struct gp2ap020a00f_data *data,
+				enum gp2ap020a00f_thresh_val_id th_val_id,
+				bool enable)
+{
+	__le16 thresh_buf = 0;
+	unsigned int thresh_reg_val;
+
+	if (!enable)
+		thresh_reg_val = 0;
+	else if (test_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags) &&
+		 th_val_id != GP2AP020A00F_THRESH_PL &&
+		 th_val_id != GP2AP020A00F_THRESH_PH)
+		/*
+		 * For the high lux mode ALS threshold has to be scaled down
+		 * to allow for proper comparison with the output value.
+		 */
+		thresh_reg_val = data->thresh_val[th_val_id] / 16;
+	else
+		thresh_reg_val = data->thresh_val[th_val_id] > 16000 ?
+					16000 :
+					data->thresh_val[th_val_id];
+
+	thresh_buf = cpu_to_le16(thresh_reg_val);
+
+	return regmap_bulk_write(data->regmap,
+				 GP2AP020A00F_THRESH_REG(th_val_id),
+				 (u8 *)&thresh_buf, 2);
+}
+
+static int gp2ap020a00f_alter_opmode(struct gp2ap020a00f_data *data,
+			enum gp2ap020a00f_opmode diff_mode, int add_sub)
+{
+	enum gp2ap020a00f_opmode new_mode;
+
+	if (diff_mode != GP2AP020A00F_OPMODE_ALS &&
+	    diff_mode != GP2AP020A00F_OPMODE_PS)
+		return -EINVAL;
+
+	if (add_sub == GP2AP020A00F_ADD_MODE) {
+		if (data->cur_opmode == GP2AP020A00F_OPMODE_SHUTDOWN)
+			new_mode =  diff_mode;
+		else
+			new_mode = GP2AP020A00F_OPMODE_ALS_AND_PS;
+	} else {
+		if (data->cur_opmode == GP2AP020A00F_OPMODE_ALS_AND_PS)
+			new_mode = (diff_mode == GP2AP020A00F_OPMODE_ALS) ?
+					GP2AP020A00F_OPMODE_PS :
+					GP2AP020A00F_OPMODE_ALS;
+		else
+			new_mode = GP2AP020A00F_OPMODE_SHUTDOWN;
+	}
+
+	return gp2ap020a00f_set_operation_mode(data, new_mode);
+}
+
+static int gp2ap020a00f_exec_cmd(struct gp2ap020a00f_data *data,
+					enum gp2ap020a00f_cmd cmd)
+{
+	int err = 0;
+
+	switch (cmd) {
+	case GP2AP020A00F_CMD_READ_RAW_CLEAR:
+		if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN)
+			return -EBUSY;
+		err = gp2ap020a00f_set_operation_mode(data,
+					GP2AP020A00F_OPMODE_READ_RAW_CLEAR);
+		break;
+	case GP2AP020A00F_CMD_READ_RAW_IR:
+		if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN)
+			return -EBUSY;
+		err = gp2ap020a00f_set_operation_mode(data,
+					GP2AP020A00F_OPMODE_READ_RAW_IR);
+		break;
+	case GP2AP020A00F_CMD_READ_RAW_PROXIMITY:
+		if (data->cur_opmode != GP2AP020A00F_OPMODE_SHUTDOWN)
+			return -EBUSY;
+		err = gp2ap020a00f_set_operation_mode(data,
+					GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY);
+		break;
+	case GP2AP020A00F_CMD_TRIGGER_CLEAR_EN:
+		if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
+			return -EBUSY;
+		if (!gp2ap020a00f_als_enabled(data))
+			err = gp2ap020a00f_alter_opmode(data,
+						GP2AP020A00F_OPMODE_ALS,
+						GP2AP020A00F_ADD_MODE);
+		set_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &data->flags);
+		break;
+	case GP2AP020A00F_CMD_TRIGGER_CLEAR_DIS:
+		clear_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &data->flags);
+		if (gp2ap020a00f_als_enabled(data))
+			break;
+		err = gp2ap020a00f_alter_opmode(data,
+						GP2AP020A00F_OPMODE_ALS,
+						GP2AP020A00F_SUBTRACT_MODE);
+		break;
+	case GP2AP020A00F_CMD_TRIGGER_IR_EN:
+		if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
+			return -EBUSY;
+		if (!gp2ap020a00f_als_enabled(data))
+			err = gp2ap020a00f_alter_opmode(data,
+						GP2AP020A00F_OPMODE_ALS,
+						GP2AP020A00F_ADD_MODE);
+		set_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &data->flags);
+		break;
+	case GP2AP020A00F_CMD_TRIGGER_IR_DIS:
+		clear_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &data->flags);
+		if (gp2ap020a00f_als_enabled(data))
+			break;
+		err = gp2ap020a00f_alter_opmode(data,
+						GP2AP020A00F_OPMODE_ALS,
+						GP2AP020A00F_SUBTRACT_MODE);
+		break;
+	case GP2AP020A00F_CMD_TRIGGER_PROX_EN:
+		if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
+			return -EBUSY;
+		err = gp2ap020a00f_alter_opmode(data,
+						GP2AP020A00F_OPMODE_PS,
+						GP2AP020A00F_ADD_MODE);
+		set_bit(GP2AP020A00F_FLAG_PROX_TRIGGER, &data->flags);
+		break;
+	case GP2AP020A00F_CMD_TRIGGER_PROX_DIS:
+		clear_bit(GP2AP020A00F_FLAG_PROX_TRIGGER, &data->flags);
+		err = gp2ap020a00f_alter_opmode(data,
+						GP2AP020A00F_OPMODE_PS,
+						GP2AP020A00F_SUBTRACT_MODE);
+		break;
+	case GP2AP020A00F_CMD_ALS_HIGH_EV_EN:
+		if (test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags))
+			return 0;
+		if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
+			return -EBUSY;
+		if (!gp2ap020a00f_als_enabled(data)) {
+			err = gp2ap020a00f_alter_opmode(data,
+						GP2AP020A00F_OPMODE_ALS,
+						GP2AP020A00F_ADD_MODE);
+			if (err < 0)
+				return err;
+		}
+		set_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags);
+		err =  gp2ap020a00f_write_event_threshold(data,
+					GP2AP020A00F_THRESH_TH, true);
+		break;
+	case GP2AP020A00F_CMD_ALS_HIGH_EV_DIS:
+		if (!test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags))
+			return 0;
+		clear_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags);
+		if (!gp2ap020a00f_als_enabled(data)) {
+			err = gp2ap020a00f_alter_opmode(data,
+						GP2AP020A00F_OPMODE_ALS,
+						GP2AP020A00F_SUBTRACT_MODE);
+			if (err < 0)
+				return err;
+		}
+		err =  gp2ap020a00f_write_event_threshold(data,
+					GP2AP020A00F_THRESH_TH, false);
+		break;
+	case GP2AP020A00F_CMD_ALS_LOW_EV_EN:
+		if (test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags))
+			return 0;
+		if (data->cur_opmode == GP2AP020A00F_OPMODE_PROX_DETECT)
+			return -EBUSY;
+		if (!gp2ap020a00f_als_enabled(data)) {
+			err = gp2ap020a00f_alter_opmode(data,
+						GP2AP020A00F_OPMODE_ALS,
+						GP2AP020A00F_ADD_MODE);
+			if (err < 0)
+				return err;
+		}
+		set_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags);
+		err =  gp2ap020a00f_write_event_threshold(data,
+					GP2AP020A00F_THRESH_TL, true);
+		break;
+	case GP2AP020A00F_CMD_ALS_LOW_EV_DIS:
+		if (!test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags))
+			return 0;
+		clear_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags);
+		if (!gp2ap020a00f_als_enabled(data)) {
+			err = gp2ap020a00f_alter_opmode(data,
+						GP2AP020A00F_OPMODE_ALS,
+						GP2AP020A00F_SUBTRACT_MODE);
+			if (err < 0)
+				return err;
+		}
+		err =  gp2ap020a00f_write_event_threshold(data,
+					GP2AP020A00F_THRESH_TL, false);
+		break;
+	case GP2AP020A00F_CMD_PROX_HIGH_EV_EN:
+		if (test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags))
+			return 0;
+		if (gp2ap020a00f_als_enabled(data) ||
+		    data->cur_opmode == GP2AP020A00F_OPMODE_PS)
+			return -EBUSY;
+		if (!gp2ap020a00f_prox_detect_enabled(data)) {
+			err = gp2ap020a00f_set_operation_mode(data,
+					GP2AP020A00F_OPMODE_PROX_DETECT);
+			if (err < 0)
+				return err;
+		}
+		set_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags);
+		err =  gp2ap020a00f_write_event_threshold(data,
+					GP2AP020A00F_THRESH_PH, true);
+		break;
+	case GP2AP020A00F_CMD_PROX_HIGH_EV_DIS:
+		if (!test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags))
+			return 0;
+		clear_bit(GP2AP020A00F_FLAG_PROX_RISING_EV, &data->flags);
+		err = gp2ap020a00f_set_operation_mode(data,
+					GP2AP020A00F_OPMODE_SHUTDOWN);
+		if (err < 0)
+			return err;
+		err =  gp2ap020a00f_write_event_threshold(data,
+					GP2AP020A00F_THRESH_PH, false);
+		break;
+	case GP2AP020A00F_CMD_PROX_LOW_EV_EN:
+		if (test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags))
+			return 0;
+		if (gp2ap020a00f_als_enabled(data) ||
+		    data->cur_opmode == GP2AP020A00F_OPMODE_PS)
+			return -EBUSY;
+		if (!gp2ap020a00f_prox_detect_enabled(data)) {
+			err = gp2ap020a00f_set_operation_mode(data,
+					GP2AP020A00F_OPMODE_PROX_DETECT);
+			if (err < 0)
+				return err;
+		}
+		set_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags);
+		err =  gp2ap020a00f_write_event_threshold(data,
+					GP2AP020A00F_THRESH_PL, true);
+		break;
+	case GP2AP020A00F_CMD_PROX_LOW_EV_DIS:
+		if (!test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags))
+			return 0;
+		clear_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV, &data->flags);
+		err = gp2ap020a00f_set_operation_mode(data,
+					GP2AP020A00F_OPMODE_SHUTDOWN);
+		if (err < 0)
+			return err;
+		err =  gp2ap020a00f_write_event_threshold(data,
+					GP2AP020A00F_THRESH_PL, false);
+		break;
+	}
+
+	return err;
+}
+
+static int wait_conversion_complete_irq(struct gp2ap020a00f_data *data)
+{
+	int ret;
+
+	ret = wait_event_timeout(data->data_ready_queue,
+				 test_bit(GP2AP020A00F_FLAG_DATA_READY,
+					  &data->flags),
+				 GP2AP020A00F_DATA_READY_TIMEOUT);
+	clear_bit(GP2AP020A00F_FLAG_DATA_READY, &data->flags);
+
+	return ret > 0 ? 0 : -ETIME;
+}
+
+static int gp2ap020a00f_read_output(struct gp2ap020a00f_data *data,
+					unsigned int output_reg, int *val)
+{
+	u8 reg_buf[2];
+	int err;
+
+	err = wait_conversion_complete_irq(data);
+	if (err < 0)
+		dev_dbg(&data->client->dev, "data ready timeout\n");
+
+	err = regmap_bulk_read(data->regmap, output_reg, reg_buf, 2);
+	if (err < 0)
+		return err;
+
+	*val = le16_to_cpup((__le16 *)reg_buf);
+
+	return err;
+}
+
+static bool gp2ap020a00f_adjust_lux_mode(struct gp2ap020a00f_data *data,
+				 int output_val)
+{
+	u8 new_range = 0xff;
+	int err;
+
+	if (!test_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags)) {
+		if (output_val > 16000) {
+			set_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags);
+			new_range = GP2AP020A00F_RANGE_A_x128;
+		}
+	} else {
+		if (output_val < 1000) {
+			clear_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags);
+			new_range = GP2AP020A00F_RANGE_A_x8;
+		}
+	}
+
+	if (new_range != 0xff) {
+		/* Clear als threshold registers to avoid spurious
+		 * events caused by lux mode transition.
+		 */
+		err =  gp2ap020a00f_write_event_threshold(data,
+					GP2AP020A00F_THRESH_TH, false);
+		if (err < 0) {
+			dev_err(&data->client->dev,
+				"Clearing als threshold register failed.\n");
+			return false;
+		}
+
+		err =  gp2ap020a00f_write_event_threshold(data,
+					GP2AP020A00F_THRESH_TL, false);
+		if (err < 0) {
+			dev_err(&data->client->dev,
+				"Clearing als threshold register failed.\n");
+			return false;
+		}
+
+		/* Change lux mode */
+		err = regmap_update_bits(data->regmap,
+			GP2AP020A00F_OP_REG,
+			GP2AP020A00F_OP3_MASK,
+			GP2AP020A00F_OP3_SHUTDOWN);
+
+		if (err < 0) {
+			dev_err(&data->client->dev,
+				"Shutting down the device failed.\n");
+			return false;
+		}
+
+		err = regmap_update_bits(data->regmap,
+			GP2AP020A00F_ALS_REG,
+			GP2AP020A00F_RANGE_A_MASK,
+			new_range);
+
+		if (err < 0) {
+			dev_err(&data->client->dev,
+				"Adjusting device lux mode failed.\n");
+			return false;
+		}
+
+		err = regmap_update_bits(data->regmap,
+			GP2AP020A00F_OP_REG,
+			GP2AP020A00F_OP3_MASK,
+			GP2AP020A00F_OP3_OPERATION);
+
+		if (err < 0) {
+			dev_err(&data->client->dev,
+				"Powering up the device failed.\n");
+			return false;
+		}
+
+		/* Adjust als threshold register values to the new lux mode */
+		if (test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &data->flags)) {
+			err =  gp2ap020a00f_write_event_threshold(data,
+					GP2AP020A00F_THRESH_TH, true);
+			if (err < 0) {
+				dev_err(&data->client->dev,
+				"Adjusting als threshold value failed.\n");
+				return false;
+			}
+		}
+
+		if (test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &data->flags)) {
+			err =  gp2ap020a00f_write_event_threshold(data,
+					GP2AP020A00F_THRESH_TL, true);
+			if (err < 0) {
+				dev_err(&data->client->dev,
+				"Adjusting als threshold value failed.\n");
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	return false;
+}
+
+static void gp2ap020a00f_output_to_lux(struct gp2ap020a00f_data *data,
+						int *output_val)
+{
+	if (test_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags))
+		*output_val *= 16;
+}
+
+static void gp2ap020a00f_iio_trigger_work(struct irq_work *work)
+{
+	struct gp2ap020a00f_data *data =
+		container_of(work, struct gp2ap020a00f_data, work);
+
+	iio_trigger_poll(data->trig, 0);
+}
+
+static irqreturn_t gp2ap020a00f_prox_sensing_handler(int irq, void *data)
+{
+	struct iio_dev *indio_dev = data;
+	struct gp2ap020a00f_data *priv = iio_priv(indio_dev);
+	unsigned int op_reg_val;
+	int ret;
+
+	/* Read interrupt flags */
+	ret = regmap_read(priv->regmap, GP2AP020A00F_OP_REG, &op_reg_val);
+	if (ret < 0)
+		return IRQ_HANDLED;
+
+	if (gp2ap020a00f_prox_detect_enabled(priv)) {
+		if (op_reg_val & GP2AP020A00F_PROX_DETECT) {
+			iio_push_event(indio_dev,
+			       IIO_UNMOD_EVENT_CODE(
+				    IIO_PROXIMITY,
+				    GP2AP020A00F_SCAN_MODE_PROXIMITY,
+				    IIO_EV_TYPE_ROC,
+				    IIO_EV_DIR_RISING),
+			       iio_get_time_ns());
+		} else {
+			iio_push_event(indio_dev,
+			       IIO_UNMOD_EVENT_CODE(
+				    IIO_PROXIMITY,
+				    GP2AP020A00F_SCAN_MODE_PROXIMITY,
+				    IIO_EV_TYPE_ROC,
+				    IIO_EV_DIR_FALLING),
+			       iio_get_time_ns());
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t gp2ap020a00f_thresh_event_handler(int irq, void *data)
+{
+	struct iio_dev *indio_dev = data;
+	struct gp2ap020a00f_data *priv = iio_priv(indio_dev);
+	u8 op_reg_flags, d0_reg_buf[2];
+	unsigned int output_val, op_reg_val;
+	int thresh_val_id, ret;
+
+	/* Read interrupt flags */
+	ret = regmap_read(priv->regmap, GP2AP020A00F_OP_REG,
+							&op_reg_val);
+	if (ret < 0)
+		goto done;
+
+	op_reg_flags = op_reg_val & (GP2AP020A00F_FLAG_A | GP2AP020A00F_FLAG_P
+					| GP2AP020A00F_PROX_DETECT);
+
+	op_reg_val &= (~GP2AP020A00F_FLAG_A & ~GP2AP020A00F_FLAG_P
+					& ~GP2AP020A00F_PROX_DETECT);
+
+	/* Clear interrupt flags (if not in INTTYPE_PULSE mode) */
+	if (priv->cur_opmode != GP2AP020A00F_OPMODE_PROX_DETECT) {
+		ret = regmap_write(priv->regmap, GP2AP020A00F_OP_REG,
+								op_reg_val);
+		if (ret < 0)
+			goto done;
+	}
+
+	if (op_reg_flags & GP2AP020A00F_FLAG_A) {
+		/* Check D0 register to assess if the lux mode
+		 * transition is required.
+		 */
+		ret = regmap_bulk_read(priv->regmap, GP2AP020A00F_D0_L_REG,
+							d0_reg_buf, 2);
+		if (ret < 0)
+			goto done;
+
+		output_val = le16_to_cpup((__le16 *)d0_reg_buf);
+
+		if (gp2ap020a00f_adjust_lux_mode(priv, output_val))
+			goto done;
+
+		gp2ap020a00f_output_to_lux(priv, &output_val);
+
+		/*
+		 * We need to check output value to distinguish
+		 * between high and low ambient light threshold event.
+		 */
+		if (test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV, &priv->flags)) {
+			thresh_val_id =
+			    GP2AP020A00F_THRESH_VAL_ID(GP2AP020A00F_TH_L_REG);
+			if (output_val > priv->thresh_val[thresh_val_id])
+				iio_push_event(indio_dev,
+				       IIO_MOD_EVENT_CODE(
+					    IIO_LIGHT,
+					    GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR,
+					    IIO_MOD_LIGHT_CLEAR,
+					    IIO_EV_TYPE_THRESH,
+					    IIO_EV_DIR_RISING),
+				       iio_get_time_ns());
+		}
+
+		if (test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV, &priv->flags)) {
+			thresh_val_id =
+			    GP2AP020A00F_THRESH_VAL_ID(GP2AP020A00F_TL_L_REG);
+			if (output_val < priv->thresh_val[thresh_val_id])
+				iio_push_event(indio_dev,
+				       IIO_MOD_EVENT_CODE(
+					    IIO_LIGHT,
+					    GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR,
+					    IIO_MOD_LIGHT_CLEAR,
+					    IIO_EV_TYPE_THRESH,
+					    IIO_EV_DIR_FALLING),
+				       iio_get_time_ns());
+		}
+	}
+
+	if (priv->cur_opmode == GP2AP020A00F_OPMODE_READ_RAW_CLEAR ||
+	    priv->cur_opmode == GP2AP020A00F_OPMODE_READ_RAW_IR ||
+	    priv->cur_opmode == GP2AP020A00F_OPMODE_READ_RAW_PROXIMITY) {
+		set_bit(GP2AP020A00F_FLAG_DATA_READY, &priv->flags);
+		wake_up(&priv->data_ready_queue);
+		goto done;
+	}
+
+	if (test_bit(GP2AP020A00F_FLAG_ALS_CLEAR_TRIGGER, &priv->flags) ||
+	    test_bit(GP2AP020A00F_FLAG_ALS_IR_TRIGGER, &priv->flags) ||
+	    test_bit(GP2AP020A00F_FLAG_PROX_TRIGGER, &priv->flags))
+		/* This fires off the trigger. */
+		irq_work_queue(&priv->work);
+
+done:
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t gp2ap020a00f_trigger_handler(int irq, void *data)
+{
+	struct iio_poll_func *pf = data;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct gp2ap020a00f_data *priv = iio_priv(indio_dev);
+	size_t d_size = 0;
+	__le32 light_lux;
+	int i, out_val, ret;
+
+	for_each_set_bit(i, indio_dev->active_scan_mask,
+		indio_dev->masklength) {
+		ret = regmap_bulk_read(priv->regmap,
+				GP2AP020A00F_DATA_REG(i),
+				&priv->buffer[d_size], 2);
+		if (ret < 0)
+			goto done;
+
+		if (i == GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR ||
+		    i == GP2AP020A00F_SCAN_MODE_LIGHT_IR) {
+			out_val = le16_to_cpup((__le16 *)&priv->buffer[d_size]);
+			gp2ap020a00f_output_to_lux(priv, &out_val);
+			light_lux = cpu_to_le32(out_val);
+			memcpy(&priv->buffer[d_size], (u8 *)&light_lux, 4);
+			d_size += 4;
+		} else {
+			d_size += 2;
+		}
+	}
+
+	iio_push_to_buffers_with_timestamp(indio_dev, priv->buffer,
+		pf->timestamp);
+done:
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static u8 gp2ap020a00f_get_thresh_reg(const struct iio_chan_spec *chan,
+					     enum iio_event_direction event_dir)
+{
+	switch (chan->type) {
+	case IIO_PROXIMITY:
+		if (event_dir == IIO_EV_DIR_RISING)
+			return GP2AP020A00F_PH_L_REG;
+		else
+			return GP2AP020A00F_PL_L_REG;
+	case IIO_LIGHT:
+		if (event_dir == IIO_EV_DIR_RISING)
+			return GP2AP020A00F_TH_L_REG;
+		else
+			return GP2AP020A00F_TL_L_REG;
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+static int gp2ap020a00f_write_event_val(struct iio_dev *indio_dev,
+					const struct iio_chan_spec *chan,
+					enum iio_event_type type,
+					enum iio_event_direction dir,
+					enum iio_event_info info,
+					int val, int val2)
+{
+	struct gp2ap020a00f_data *data = iio_priv(indio_dev);
+	bool event_en = false;
+	u8 thresh_val_id;
+	u8 thresh_reg_l;
+	int err = 0;
+
+	mutex_lock(&data->lock);
+
+	thresh_reg_l = gp2ap020a00f_get_thresh_reg(chan, dir);
+	thresh_val_id = GP2AP020A00F_THRESH_VAL_ID(thresh_reg_l);
+
+	if (thresh_val_id > GP2AP020A00F_THRESH_PH) {
+		err = -EINVAL;
+		goto error_unlock;
+	}
+
+	switch (thresh_reg_l) {
+	case GP2AP020A00F_TH_L_REG:
+		event_en = test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV,
+							&data->flags);
+		break;
+	case GP2AP020A00F_TL_L_REG:
+		event_en = test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV,
+							&data->flags);
+		break;
+	case GP2AP020A00F_PH_L_REG:
+		if (val == 0) {
+			err = -EINVAL;
+			goto error_unlock;
+		}
+		event_en = test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV,
+							&data->flags);
+		break;
+	case GP2AP020A00F_PL_L_REG:
+		if (val == 0) {
+			err = -EINVAL;
+			goto error_unlock;
+		}
+		event_en = test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV,
+							&data->flags);
+		break;
+	}
+
+	data->thresh_val[thresh_val_id] = val;
+	err =  gp2ap020a00f_write_event_threshold(data, thresh_val_id,
+							event_en);
+error_unlock:
+	mutex_unlock(&data->lock);
+
+	return err;
+}
+
+static int gp2ap020a00f_read_event_val(struct iio_dev *indio_dev,
+				       const struct iio_chan_spec *chan,
+				       enum iio_event_type type,
+				       enum iio_event_direction dir,
+				       enum iio_event_info info,
+				       int *val, int *val2)
+{
+	struct gp2ap020a00f_data *data = iio_priv(indio_dev);
+	u8 thresh_reg_l;
+	int err = IIO_VAL_INT;
+
+	mutex_lock(&data->lock);
+
+	thresh_reg_l = gp2ap020a00f_get_thresh_reg(chan, dir);
+
+	if (thresh_reg_l > GP2AP020A00F_PH_L_REG) {
+		err = -EINVAL;
+		goto error_unlock;
+	}
+
+	*val = data->thresh_val[GP2AP020A00F_THRESH_VAL_ID(thresh_reg_l)];
+
+error_unlock:
+	mutex_unlock(&data->lock);
+
+	return err;
+}
+
+static int gp2ap020a00f_write_prox_event_config(struct iio_dev *indio_dev,
+						int state)
+{
+	struct gp2ap020a00f_data *data = iio_priv(indio_dev);
+	enum gp2ap020a00f_cmd cmd_high_ev, cmd_low_ev;
+	int err;
+
+	cmd_high_ev = state ? GP2AP020A00F_CMD_PROX_HIGH_EV_EN :
+			      GP2AP020A00F_CMD_PROX_HIGH_EV_DIS;
+	cmd_low_ev = state ? GP2AP020A00F_CMD_PROX_LOW_EV_EN :
+			     GP2AP020A00F_CMD_PROX_LOW_EV_DIS;
+
+	/*
+	 * In order to enable proximity detection feature in the device
+	 * both high and low threshold registers have to be written
+	 * with different values, greater than zero.
+	 */
+	if (state) {
+		if (data->thresh_val[GP2AP020A00F_THRESH_PL] == 0)
+			return -EINVAL;
+
+		if (data->thresh_val[GP2AP020A00F_THRESH_PH] == 0)
+			return -EINVAL;
+	}
+
+	err = gp2ap020a00f_exec_cmd(data, cmd_high_ev);
+	if (err < 0)
+		return err;
+
+	err = gp2ap020a00f_exec_cmd(data, cmd_low_ev);
+	if (err < 0)
+		return err;
+
+	free_irq(data->client->irq, indio_dev);
+
+	if (state)
+		err = request_threaded_irq(data->client->irq, NULL,
+					   &gp2ap020a00f_prox_sensing_handler,
+					   IRQF_TRIGGER_RISING |
+					   IRQF_TRIGGER_FALLING |
+					   IRQF_ONESHOT,
+					   "gp2ap020a00f_prox_sensing",
+					   indio_dev);
+	else {
+		err = request_threaded_irq(data->client->irq, NULL,
+					   &gp2ap020a00f_thresh_event_handler,
+					   IRQF_TRIGGER_FALLING |
+					   IRQF_ONESHOT,
+					   "gp2ap020a00f_thresh_event",
+					   indio_dev);
+	}
+
+	return err;
+}
+
+static int gp2ap020a00f_write_event_config(struct iio_dev *indio_dev,
+					   const struct iio_chan_spec *chan,
+					   enum iio_event_type type,
+					   enum iio_event_direction dir,
+					   int state)
+{
+	struct gp2ap020a00f_data *data = iio_priv(indio_dev);
+	enum gp2ap020a00f_cmd cmd;
+	int err;
+
+	mutex_lock(&data->lock);
+
+	switch (chan->type) {
+	case IIO_PROXIMITY:
+		err = gp2ap020a00f_write_prox_event_config(indio_dev, state);
+		break;
+	case IIO_LIGHT:
+		if (dir == IIO_EV_DIR_RISING) {
+			cmd = state ? GP2AP020A00F_CMD_ALS_HIGH_EV_EN :
+				      GP2AP020A00F_CMD_ALS_HIGH_EV_DIS;
+			err = gp2ap020a00f_exec_cmd(data, cmd);
+		} else {
+			cmd = state ? GP2AP020A00F_CMD_ALS_LOW_EV_EN :
+				      GP2AP020A00F_CMD_ALS_LOW_EV_DIS;
+			err = gp2ap020a00f_exec_cmd(data, cmd);
+		}
+		break;
+	default:
+		err = -EINVAL;
+	}
+
+	mutex_unlock(&data->lock);
+
+	return err;
+}
+
+static int gp2ap020a00f_read_event_config(struct iio_dev *indio_dev,
+					   const struct iio_chan_spec *chan,
+					   enum iio_event_type type,
+					   enum iio_event_direction dir)
+{
+	struct gp2ap020a00f_data *data = iio_priv(indio_dev);
+	int event_en = 0;
+
+	mutex_lock(&data->lock);
+
+	switch (chan->type) {
+	case IIO_PROXIMITY:
+		if (dir == IIO_EV_DIR_RISING)
+			event_en = test_bit(GP2AP020A00F_FLAG_PROX_RISING_EV,
+								&data->flags);
+		else
+			event_en = test_bit(GP2AP020A00F_FLAG_PROX_FALLING_EV,
+								&data->flags);
+		break;
+	case IIO_LIGHT:
+		if (dir == IIO_EV_DIR_RISING)
+			event_en = test_bit(GP2AP020A00F_FLAG_ALS_RISING_EV,
+								&data->flags);
+		else
+			event_en = test_bit(GP2AP020A00F_FLAG_ALS_FALLING_EV,
+								&data->flags);
+		break;
+	default:
+		event_en = -EINVAL;
+		break;
+	}
+
+	mutex_unlock(&data->lock);
+
+	return event_en;
+}
+
+static int gp2ap020a00f_read_channel(struct gp2ap020a00f_data *data,
+				struct iio_chan_spec const *chan, int *val)
+{
+	enum gp2ap020a00f_cmd cmd;
+	int err;
+
+	switch (chan->scan_index) {
+	case GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR:
+		cmd = GP2AP020A00F_CMD_READ_RAW_CLEAR;
+		break;
+	case GP2AP020A00F_SCAN_MODE_LIGHT_IR:
+		cmd = GP2AP020A00F_CMD_READ_RAW_IR;
+		break;
+	case GP2AP020A00F_SCAN_MODE_PROXIMITY:
+		cmd = GP2AP020A00F_CMD_READ_RAW_PROXIMITY;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	err = gp2ap020a00f_exec_cmd(data, cmd);
+	if (err < 0) {
+		dev_err(&data->client->dev,
+			"gp2ap020a00f_exec_cmd failed\n");
+		goto error_ret;
+	}
+
+	err = gp2ap020a00f_read_output(data, chan->address, val);
+	if (err < 0)
+		dev_err(&data->client->dev,
+			"gp2ap020a00f_read_output failed\n");
+
+	err = gp2ap020a00f_set_operation_mode(data,
+					GP2AP020A00F_OPMODE_SHUTDOWN);
+	if (err < 0)
+		dev_err(&data->client->dev,
+			"Failed to shut down the device.\n");
+
+	if (cmd == GP2AP020A00F_CMD_READ_RAW_CLEAR ||
+	    cmd == GP2AP020A00F_CMD_READ_RAW_IR)
+		gp2ap020a00f_output_to_lux(data, val);
+
+error_ret:
+	return err;
+}
+
+static int gp2ap020a00f_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val, int *val2,
+			   long mask)
+{
+	struct gp2ap020a00f_data *data = iio_priv(indio_dev);
+	int err = -EINVAL;
+
+	mutex_lock(&data->lock);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		if (iio_buffer_enabled(indio_dev)) {
+			err = -EBUSY;
+			goto error_unlock;
+		}
+
+		err = gp2ap020a00f_read_channel(data, chan, val);
+		break;
+	}
+
+error_unlock:
+	mutex_unlock(&data->lock);
+
+	return err < 0 ? err : IIO_VAL_INT;
+}
+
+static const struct iio_event_spec gp2ap020a00f_event_spec_light[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	},
+};
+
+static const struct iio_event_spec gp2ap020a00f_event_spec_prox[] = {
+	{
+		.type = IIO_EV_TYPE_ROC,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	}, {
+		.type = IIO_EV_TYPE_ROC,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	},
+};
+
+static const struct iio_chan_spec gp2ap020a00f_channels[] = {
+	{
+		.type = IIO_LIGHT,
+		.channel2 = IIO_MOD_LIGHT_CLEAR,
+		.modified = 1,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 24,
+			.shift = 0,
+			.storagebits = 32,
+			.endianness = IIO_LE,
+		},
+		.scan_index = GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR,
+		.address = GP2AP020A00F_D0_L_REG,
+		.event_spec = gp2ap020a00f_event_spec_light,
+		.num_event_specs = ARRAY_SIZE(gp2ap020a00f_event_spec_light),
+	},
+	{
+		.type = IIO_LIGHT,
+		.channel2 = IIO_MOD_LIGHT_IR,
+		.modified = 1,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 24,
+			.shift = 0,
+			.storagebits = 32,
+			.endianness = IIO_LE,
+		},
+		.scan_index = GP2AP020A00F_SCAN_MODE_LIGHT_IR,
+		.address = GP2AP020A00F_D1_L_REG,
+	},
+	{
+		.type = IIO_PROXIMITY,
+		.modified = 0,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 16,
+			.shift = 0,
+			.storagebits = 16,
+			.endianness = IIO_LE,
+		},
+		.scan_index = GP2AP020A00F_SCAN_MODE_PROXIMITY,
+		.address = GP2AP020A00F_D2_L_REG,
+		.event_spec = gp2ap020a00f_event_spec_prox,
+		.num_event_specs = ARRAY_SIZE(gp2ap020a00f_event_spec_prox),
+	},
+	IIO_CHAN_SOFT_TIMESTAMP(GP2AP020A00F_CHAN_TIMESTAMP),
+};
+
+static const struct iio_info gp2ap020a00f_info = {
+	.read_raw = &gp2ap020a00f_read_raw,
+	.read_event_value_new = &gp2ap020a00f_read_event_val,
+	.read_event_config_new = &gp2ap020a00f_read_event_config,
+	.write_event_value_new = &gp2ap020a00f_write_event_val,
+	.write_event_config_new = &gp2ap020a00f_write_event_config,
+	.driver_module = THIS_MODULE,
+};
+
+static int gp2ap020a00f_buffer_postenable(struct iio_dev *indio_dev)
+{
+	struct gp2ap020a00f_data *data = iio_priv(indio_dev);
+	int i, err = 0;
+
+	mutex_lock(&data->lock);
+
+	/*
+	 * Enable triggers according to the scan_mask. Enabling either
+	 * LIGHT_CLEAR or LIGHT_IR scan mode results in enabling ALS
+	 * module in the device, which generates samples in both D0 (clear)
+	 * and D1 (ir) registers. As the two registers are bound to the
+	 * two separate IIO channels they are treated in the driver logic
+	 * as if they were controlled independently.
+	 */
+	for_each_set_bit(i, indio_dev->active_scan_mask,
+		indio_dev->masklength) {
+		switch (i) {
+		case GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR:
+			err = gp2ap020a00f_exec_cmd(data,
+					GP2AP020A00F_CMD_TRIGGER_CLEAR_EN);
+			break;
+		case GP2AP020A00F_SCAN_MODE_LIGHT_IR:
+			err = gp2ap020a00f_exec_cmd(data,
+					GP2AP020A00F_CMD_TRIGGER_IR_EN);
+			break;
+		case GP2AP020A00F_SCAN_MODE_PROXIMITY:
+			err = gp2ap020a00f_exec_cmd(data,
+					GP2AP020A00F_CMD_TRIGGER_PROX_EN);
+			break;
+		}
+	}
+
+	if (err < 0)
+		goto error_unlock;
+
+	data->buffer = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
+	if (!data->buffer) {
+		err = -ENOMEM;
+		goto error_unlock;
+	}
+
+	err = iio_triggered_buffer_postenable(indio_dev);
+
+error_unlock:
+	mutex_unlock(&data->lock);
+
+	return err;
+}
+
+static int gp2ap020a00f_buffer_predisable(struct iio_dev *indio_dev)
+{
+	struct gp2ap020a00f_data *data = iio_priv(indio_dev);
+	int i, err;
+
+	mutex_lock(&data->lock);
+
+	err = iio_triggered_buffer_predisable(indio_dev);
+	if (err < 0)
+		goto error_unlock;
+
+	for_each_set_bit(i, indio_dev->active_scan_mask,
+		indio_dev->masklength) {
+		switch (i) {
+		case GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR:
+			err = gp2ap020a00f_exec_cmd(data,
+					GP2AP020A00F_CMD_TRIGGER_CLEAR_DIS);
+			break;
+		case GP2AP020A00F_SCAN_MODE_LIGHT_IR:
+			err = gp2ap020a00f_exec_cmd(data,
+					GP2AP020A00F_CMD_TRIGGER_IR_DIS);
+			break;
+		case GP2AP020A00F_SCAN_MODE_PROXIMITY:
+			err = gp2ap020a00f_exec_cmd(data,
+					GP2AP020A00F_CMD_TRIGGER_PROX_DIS);
+			break;
+		}
+	}
+
+	if (err == 0)
+		kfree(data->buffer);
+
+error_unlock:
+	mutex_unlock(&data->lock);
+
+	return err;
+}
+
+static const struct iio_buffer_setup_ops gp2ap020a00f_buffer_setup_ops = {
+	.postenable = &gp2ap020a00f_buffer_postenable,
+	.predisable = &gp2ap020a00f_buffer_predisable,
+};
+
+static const struct iio_trigger_ops gp2ap020a00f_trigger_ops = {
+	.owner = THIS_MODULE,
+};
+
+static int gp2ap020a00f_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	struct gp2ap020a00f_data *data;
+	struct iio_dev *indio_dev;
+	struct regmap *regmap;
+	int err;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+
+	data->vled_reg = devm_regulator_get(&client->dev, "vled");
+	if (IS_ERR(data->vled_reg))
+		return PTR_ERR(data->vled_reg);
+
+	err = regulator_enable(data->vled_reg);
+	if (err)
+		return err;
+
+	regmap = devm_regmap_init_i2c(client, &gp2ap020a00f_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(&client->dev, "Regmap initialization failed.\n");
+		err = PTR_ERR(regmap);
+		goto error_regulator_disable;
+	}
+
+	/* Initialize device registers */
+	err = regmap_bulk_write(regmap, GP2AP020A00F_OP_REG,
+			gp2ap020a00f_reg_init_tab,
+			ARRAY_SIZE(gp2ap020a00f_reg_init_tab));
+
+	if (err < 0) {
+		dev_err(&client->dev, "Device initialization failed.\n");
+		goto error_regulator_disable;
+	}
+
+	i2c_set_clientdata(client, indio_dev);
+
+	data->client = client;
+	data->cur_opmode = GP2AP020A00F_OPMODE_SHUTDOWN;
+	data->regmap = regmap;
+	init_waitqueue_head(&data->data_ready_queue);
+
+	mutex_init(&data->lock);
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->channels = gp2ap020a00f_channels;
+	indio_dev->num_channels = ARRAY_SIZE(gp2ap020a00f_channels);
+	indio_dev->info = &gp2ap020a00f_info;
+	indio_dev->name = id->name;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	/* Allocate buffer */
+	err = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+		&gp2ap020a00f_trigger_handler, &gp2ap020a00f_buffer_setup_ops);
+	if (err < 0)
+		goto error_regulator_disable;
+
+	/* Allocate trigger */
+	data->trig = devm_iio_trigger_alloc(&client->dev, "%s-trigger",
+							indio_dev->name);
+	if (data->trig == NULL) {
+		err = -ENOMEM;
+		dev_err(&indio_dev->dev, "Failed to allocate iio trigger.\n");
+		goto error_uninit_buffer;
+	}
+
+	/* This needs to be requested here for read_raw calls to work. */
+	err = request_threaded_irq(client->irq, NULL,
+				   &gp2ap020a00f_thresh_event_handler,
+				   IRQF_TRIGGER_FALLING |
+				   IRQF_ONESHOT,
+				   "gp2ap020a00f_als_event",
+				   indio_dev);
+	if (err < 0) {
+		dev_err(&client->dev, "Irq request failed.\n");
+		goto error_uninit_buffer;
+	}
+
+	data->trig->ops = &gp2ap020a00f_trigger_ops;
+	data->trig->dev.parent = &data->client->dev;
+
+	init_irq_work(&data->work, gp2ap020a00f_iio_trigger_work);
+
+	err = iio_trigger_register(data->trig);
+	if (err < 0) {
+		dev_err(&client->dev, "Failed to register iio trigger.\n");
+		goto error_free_irq;
+	}
+
+	err = iio_device_register(indio_dev);
+	if (err < 0)
+		goto error_trigger_unregister;
+
+	return 0;
+
+error_trigger_unregister:
+	iio_trigger_unregister(data->trig);
+error_free_irq:
+	free_irq(client->irq, indio_dev);
+error_uninit_buffer:
+	iio_triggered_buffer_cleanup(indio_dev);
+error_regulator_disable:
+	regulator_disable(data->vled_reg);
+
+	return err;
+}
+
+static int gp2ap020a00f_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct gp2ap020a00f_data *data = iio_priv(indio_dev);
+	int err;
+
+	err = gp2ap020a00f_set_operation_mode(data,
+					GP2AP020A00F_OPMODE_SHUTDOWN);
+	if (err < 0)
+		dev_err(&indio_dev->dev, "Failed to power off the device.\n");
+
+	iio_device_unregister(indio_dev);
+	iio_trigger_unregister(data->trig);
+	free_irq(client->irq, indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+	regulator_disable(data->vled_reg);
+
+	return 0;
+}
+
+static const struct i2c_device_id gp2ap020a00f_id[] = {
+	{ GP2A_I2C_NAME, 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, gp2ap020a00f_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id gp2ap020a00f_of_match[] = {
+	{ .compatible = "sharp,gp2ap020a00f" },
+	{ }
+};
+#endif
+
+static struct i2c_driver gp2ap020a00f_driver = {
+	.driver = {
+		.name	= GP2A_I2C_NAME,
+		.of_match_table = of_match_ptr(gp2ap020a00f_of_match),
+		.owner	= THIS_MODULE,
+	},
+	.probe		= gp2ap020a00f_probe,
+	.remove		= gp2ap020a00f_remove,
+	.id_table	= gp2ap020a00f_id,
+};
+
+module_i2c_driver(gp2ap020a00f_driver);
+
+MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
+MODULE_DESCRIPTION("Sharp GP2AP020A00F Proximity/ALS sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index e59d00c..fa6ae8c 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -161,10 +161,11 @@
 };
 
 /* Function to push data to buffer */
-static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
+static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data,
+					int len)
 {
 	dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
-	iio_push_to_buffers(indio_dev, (u8 *)data);
+	iio_push_to_buffers(indio_dev, data);
 }
 
 /* Callback handler to send event after all samples are received and captured */
@@ -179,7 +180,7 @@
 				als_state->common_attributes.data_ready);
 	if (als_state->common_attributes.data_ready)
 		hid_sensor_push_data(indio_dev,
-				(u8 *)&als_state->illum,
+				&als_state->illum,
 				sizeof(als_state->illum));
 
 	return 0;
diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c
new file mode 100644
index 0000000..45df220
--- /dev/null
+++ b/drivers/iio/light/tcs3472.c
@@ -0,0 +1,367 @@
+/*
+ * tcs3472.c - Support for TAOS TCS3472 color light-to-digital converter
+ *
+ * Copyright (c) 2013 Peter Meerwald <pmeerw@pmeerw.net>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * Color light sensor with 16-bit channels for red, green, blue, clear);
+ * 7-bit I2C slave address 0x39 (TCS34721, TCS34723) or 0x29 (TCS34725,
+ * TCS34727)
+ *
+ * TODO: interrupt support, thresholds, wait time
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define TCS3472_DRV_NAME "tcs3472"
+
+#define TCS3472_COMMAND BIT(7)
+#define TCS3472_AUTO_INCR BIT(5)
+
+#define TCS3472_ENABLE (TCS3472_COMMAND | 0x00)
+#define TCS3472_ATIME (TCS3472_COMMAND | 0x01)
+#define TCS3472_WTIME (TCS3472_COMMAND | 0x03)
+#define TCS3472_AILT (TCS3472_COMMAND | 0x04)
+#define TCS3472_AIHT (TCS3472_COMMAND | 0x06)
+#define TCS3472_PERS (TCS3472_COMMAND | 0x0c)
+#define TCS3472_CONFIG (TCS3472_COMMAND | 0x0d)
+#define TCS3472_CONTROL (TCS3472_COMMAND | 0x0f)
+#define TCS3472_ID (TCS3472_COMMAND | 0x12)
+#define TCS3472_STATUS (TCS3472_COMMAND | 0x13)
+#define TCS3472_CDATA (TCS3472_COMMAND | TCS3472_AUTO_INCR | 0x14)
+#define TCS3472_RDATA (TCS3472_COMMAND | TCS3472_AUTO_INCR | 0x16)
+#define TCS3472_GDATA (TCS3472_COMMAND | TCS3472_AUTO_INCR | 0x18)
+#define TCS3472_BDATA (TCS3472_COMMAND | TCS3472_AUTO_INCR | 0x1a)
+
+#define TCS3472_STATUS_AVALID BIT(0)
+#define TCS3472_ENABLE_AEN BIT(1)
+#define TCS3472_ENABLE_PON BIT(0)
+#define TCS3472_CONTROL_AGAIN_MASK (BIT(0) | BIT(1))
+
+struct tcs3472_data {
+	struct i2c_client *client;
+	u8 enable;
+	u8 control;
+	u8 atime;
+	u16 buffer[8]; /* 4 16-bit channels + 64-bit timestamp */
+};
+
+#define TCS3472_CHANNEL(_color, _si, _addr) { \
+	.type = IIO_INTENSITY, \
+	.modified = 1, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBSCALE) | \
+		BIT(IIO_CHAN_INFO_INT_TIME), \
+	.channel2 = IIO_MOD_LIGHT_##_color, \
+	.address = _addr, \
+	.scan_index = _si, \
+	.scan_type = IIO_ST('u', 16, 16, 0), \
+}
+
+static const int tcs3472_agains[] = { 1, 4, 16, 60 };
+
+static const struct iio_chan_spec tcs3472_channels[] = {
+	TCS3472_CHANNEL(CLEAR, 0, TCS3472_CDATA),
+	TCS3472_CHANNEL(RED, 1, TCS3472_RDATA),
+	TCS3472_CHANNEL(GREEN, 2, TCS3472_GDATA),
+	TCS3472_CHANNEL(BLUE, 3, TCS3472_BDATA),
+	IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+static int tcs3472_req_data(struct tcs3472_data *data)
+{
+	int tries = 50;
+	int ret;
+
+	while (tries--) {
+		ret = i2c_smbus_read_byte_data(data->client, TCS3472_STATUS);
+		if (ret < 0)
+			return ret;
+		if (ret & TCS3472_STATUS_AVALID)
+			break;
+		msleep(20);
+	}
+
+	if (tries < 0) {
+		dev_err(&data->client->dev, "data not ready\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int tcs3472_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val, int *val2, long mask)
+{
+	struct tcs3472_data *data = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = tcs3472_req_data(data);
+		if (ret < 0)
+			return ret;
+		ret = i2c_smbus_read_word_data(data->client, chan->address);
+		if (ret < 0)
+			return ret;
+		*val = ret;
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_CALIBSCALE:
+		*val = tcs3472_agains[data->control &
+			TCS3472_CONTROL_AGAIN_MASK];
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_INT_TIME:
+		*val = 0;
+		*val2 = (256 - data->atime) * 2400;
+		return IIO_VAL_INT_PLUS_MICRO;
+	}
+	return -EINVAL;
+}
+
+static int tcs3472_write_raw(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       int val, int val2, long mask)
+{
+	struct tcs3472_data *data = iio_priv(indio_dev);
+	int i;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_CALIBSCALE:
+		if (val2 != 0)
+			return -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(tcs3472_agains); i++) {
+			if (val == tcs3472_agains[i]) {
+				data->control &= ~TCS3472_CONTROL_AGAIN_MASK;
+				data->control |= i;
+				return i2c_smbus_write_byte_data(
+					data->client, TCS3472_CONTROL,
+					data->control);
+			}
+		}
+		return -EINVAL;
+	case IIO_CHAN_INFO_INT_TIME:
+		if (val != 0)
+			return -EINVAL;
+		for (i = 0; i < 256; i++) {
+			if (val2 == (256 - i) * 2400) {
+				data->atime = i;
+				return i2c_smbus_write_word_data(
+					data->client, TCS3472_ATIME,
+					data->atime);
+			}
+
+		}
+		return -EINVAL;
+	}
+	return -EINVAL;
+}
+
+static irqreturn_t tcs3472_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct tcs3472_data *data = iio_priv(indio_dev);
+	int len = 0;
+	int i, j = 0;
+
+	int ret = tcs3472_req_data(data);
+	if (ret < 0)
+		goto done;
+
+	for_each_set_bit(i, indio_dev->active_scan_mask,
+		indio_dev->masklength) {
+		ret = i2c_smbus_read_word_data(data->client,
+			TCS3472_CDATA + 2*i);
+		if (ret < 0)
+			goto done;
+
+		data->buffer[j++] = ret;
+		len += 2;
+	}
+
+	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+		iio_get_time_ns());
+
+done:
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static ssize_t tcs3472_show_int_time_available(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	size_t len = 0;
+	int i;
+
+	for (i = 1; i <= 256; i++)
+		len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06d ",
+			2400 * i);
+
+	/* replace trailing space by newline */
+	buf[len - 1] = '\n';
+
+	return len;
+}
+
+static IIO_CONST_ATTR(calibscale_available, "1 4 16 60");
+static IIO_DEV_ATTR_INT_TIME_AVAIL(tcs3472_show_int_time_available);
+
+static struct attribute *tcs3472_attributes[] = {
+	&iio_const_attr_calibscale_available.dev_attr.attr,
+	&iio_dev_attr_integration_time_available.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group tcs3472_attribute_group = {
+	.attrs = tcs3472_attributes,
+};
+
+static const struct iio_info tcs3472_info = {
+	.read_raw = tcs3472_read_raw,
+	.write_raw = tcs3472_write_raw,
+	.attrs = &tcs3472_attribute_group,
+	.driver_module = THIS_MODULE,
+};
+
+static int tcs3472_probe(struct i2c_client *client,
+			   const struct i2c_device_id *id)
+{
+	struct tcs3472_data *data;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (indio_dev == NULL)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	i2c_set_clientdata(client, indio_dev);
+	data->client = client;
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &tcs3472_info;
+	indio_dev->name = TCS3472_DRV_NAME;
+	indio_dev->channels = tcs3472_channels;
+	indio_dev->num_channels = ARRAY_SIZE(tcs3472_channels);
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = i2c_smbus_read_byte_data(data->client, TCS3472_ID);
+	if (ret < 0)
+		return ret;
+
+	if (ret == 0x44)
+		dev_info(&client->dev, "TCS34721/34725 found\n");
+	else if (ret == 0x4d)
+		dev_info(&client->dev, "TCS34723/34727 found\n");
+	else
+		return -ENODEV;
+
+	ret = i2c_smbus_read_byte_data(data->client, TCS3472_CONTROL);
+	if (ret < 0)
+		return ret;
+	data->control = ret;
+
+	ret = i2c_smbus_read_byte_data(data->client, TCS3472_ATIME);
+	if (ret < 0)
+		return ret;
+	data->atime = ret;
+
+	ret = i2c_smbus_read_byte_data(data->client, TCS3472_ENABLE);
+	if (ret < 0)
+		return ret;
+
+	/* enable device */
+	data->enable = ret | TCS3472_ENABLE_PON | TCS3472_ENABLE_AEN;
+	ret = i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE,
+		data->enable);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+		tcs3472_trigger_handler, NULL);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0)
+		goto buffer_cleanup;
+
+	return 0;
+
+buffer_cleanup:
+	iio_triggered_buffer_cleanup(indio_dev);
+	return ret;
+}
+
+static int tcs3472_powerdown(struct tcs3472_data *data)
+{
+	return i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE,
+		data->enable & ~(TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON));
+}
+
+static int tcs3472_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+	tcs3472_powerdown(iio_priv(indio_dev));
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tcs3472_suspend(struct device *dev)
+{
+	struct tcs3472_data *data = iio_priv(i2c_get_clientdata(
+		to_i2c_client(dev)));
+	return tcs3472_powerdown(data);
+}
+
+static int tcs3472_resume(struct device *dev)
+{
+	struct tcs3472_data *data = iio_priv(i2c_get_clientdata(
+		to_i2c_client(dev)));
+	return i2c_smbus_write_byte_data(data->client, TCS3472_ENABLE,
+		data->enable | (TCS3472_ENABLE_AEN | TCS3472_ENABLE_PON));
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(tcs3472_pm_ops, tcs3472_suspend, tcs3472_resume);
+
+static const struct i2c_device_id tcs3472_id[] = {
+	{ "tcs3472", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tcs3472_id);
+
+static struct i2c_driver tcs3472_driver = {
+	.driver = {
+		.name	= TCS3472_DRV_NAME,
+		.pm	= &tcs3472_pm_ops,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= tcs3472_probe,
+	.remove		= tcs3472_remove,
+	.id_table	= tcs3472_id,
+};
+module_i2c_driver(tcs3472_driver);
+
+MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
+MODULE_DESCRIPTION("TCS3472 color light sensors driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c
index ebb962c..5e5d9de 100644
--- a/drivers/iio/light/tsl2563.c
+++ b/drivers/iio/light/tsl2563.c
@@ -526,6 +526,20 @@
 	return ret;
 }
 
+static const struct iio_event_spec tsl2563_events[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+				BIT(IIO_EV_INFO_ENABLE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+				BIT(IIO_EV_INFO_ENABLE),
+	},
+};
+
 static const struct iio_chan_spec tsl2563_channels[] = {
 	{
 		.type = IIO_LIGHT,
@@ -538,10 +552,8 @@
 		.channel2 = IIO_MOD_LIGHT_BOTH,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 		BIT(IIO_CHAN_INFO_CALIBSCALE),
-		.event_mask = (IIO_EV_BIT(IIO_EV_TYPE_THRESH,
-					  IIO_EV_DIR_RISING) |
-			       IIO_EV_BIT(IIO_EV_TYPE_THRESH,
-					  IIO_EV_DIR_FALLING)),
+		.event_spec = tsl2563_events,
+		.num_event_specs = ARRAY_SIZE(tsl2563_events),
 	}, {
 		.type = IIO_INTENSITY,
 		.modified = 1,
@@ -552,12 +564,13 @@
 };
 
 static int tsl2563_read_thresh(struct iio_dev *indio_dev,
-			       u64 event_code,
-			       int *val)
+	const struct iio_chan_spec *chan, enum iio_event_type type,
+	enum iio_event_direction dir, enum iio_event_info info, int *val,
+	int *val2)
 {
 	struct tsl2563_chip *chip = iio_priv(indio_dev);
 
-	switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
+	switch (dir) {
 	case IIO_EV_DIR_RISING:
 		*val = chip->high_thres;
 		break;
@@ -568,18 +581,19 @@
 		return -EINVAL;
 	}
 
-	return 0;
+	return IIO_VAL_INT;
 }
 
 static int tsl2563_write_thresh(struct iio_dev *indio_dev,
-				  u64 event_code,
-				  int val)
+	const struct iio_chan_spec *chan, enum iio_event_type type,
+	enum iio_event_direction dir, enum iio_event_info info, int val,
+	int val2)
 {
 	struct tsl2563_chip *chip = iio_priv(indio_dev);
 	int ret;
 	u8 address;
 
-	if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING)
+	if (dir == IIO_EV_DIR_RISING)
 		address = TSL2563_REG_HIGHLOW;
 	else
 		address = TSL2563_REG_LOWLOW;
@@ -591,7 +605,7 @@
 	ret = i2c_smbus_write_byte_data(chip->client,
 					TSL2563_CMD | (address + 1),
 					(val >> 8) & 0xFF);
-	if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_RISING)
+	if (dir == IIO_EV_DIR_RISING)
 		chip->high_thres = val;
 	else
 		chip->low_thres = val;
@@ -620,8 +634,8 @@
 }
 
 static int tsl2563_write_interrupt_config(struct iio_dev *indio_dev,
-					  u64 event_code,
-					  int state)
+	const struct iio_chan_spec *chan, enum iio_event_type type,
+	enum iio_event_direction dir, int state)
 {
 	struct tsl2563_chip *chip = iio_priv(indio_dev);
 	int ret = 0;
@@ -662,7 +676,8 @@
 }
 
 static int tsl2563_read_interrupt_config(struct iio_dev *indio_dev,
-					 u64 event_code)
+	const struct iio_chan_spec *chan, enum iio_event_type type,
+	enum iio_event_direction dir)
 {
 	struct tsl2563_chip *chip = iio_priv(indio_dev);
 	int ret;
@@ -687,10 +702,10 @@
 	.driver_module = THIS_MODULE,
 	.read_raw = &tsl2563_read_raw,
 	.write_raw = &tsl2563_write_raw,
-	.read_event_value = &tsl2563_read_thresh,
-	.write_event_value = &tsl2563_write_thresh,
-	.read_event_config = &tsl2563_read_interrupt_config,
-	.write_event_config = &tsl2563_write_interrupt_config,
+	.read_event_value_new = &tsl2563_read_thresh,
+	.write_event_value_new = &tsl2563_write_thresh,
+	.read_event_config_new = &tsl2563_read_interrupt_config,
+	.write_event_config_new = &tsl2563_write_interrupt_config,
 };
 
 static int tsl2563_probe(struct i2c_client *client,
diff --git a/drivers/iio/light/tsl4531.c b/drivers/iio/light/tsl4531.c
new file mode 100644
index 0000000..a15006e
--- /dev/null
+++ b/drivers/iio/light/tsl4531.c
@@ -0,0 +1,258 @@
+/*
+ * tsl4531.c - Support for TAOS TSL4531 ambient light sensor
+ *
+ * Copyright 2013 Peter Meerwald <pmeerw@pmeerw.net>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * IIO driver for the TSL4531x family
+ *   TSL45311/TSL45313: 7-bit I2C slave address 0x39
+ *   TSL45315/TSL45317: 7-bit I2C slave address 0x29
+ *
+ * TODO: single cycle measurement
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define TSL4531_DRV_NAME "tsl4531"
+
+#define TCS3472_COMMAND BIT(7)
+
+#define TSL4531_CONTROL (TCS3472_COMMAND | 0x00)
+#define TSL4531_CONFIG (TCS3472_COMMAND | 0x01)
+#define TSL4531_DATA (TCS3472_COMMAND | 0x04)
+#define TSL4531_ID (TCS3472_COMMAND | 0x0a)
+
+/* operating modes in control register */
+#define TSL4531_MODE_POWERDOWN 0x00
+#define TSL4531_MODE_SINGLE_ADC 0x02
+#define TSL4531_MODE_NORMAL 0x03
+
+/* integration time control in config register */
+#define TSL4531_TCNTRL_400MS 0x00
+#define TSL4531_TCNTRL_200MS 0x01
+#define TSL4531_TCNTRL_100MS 0x02
+
+/* part number in id register */
+#define TSL45311_ID 0x8
+#define TSL45313_ID 0x9
+#define TSL45315_ID 0xa
+#define TSL45317_ID 0xb
+#define TSL4531_ID_SHIFT 4
+
+struct tsl4531_data {
+	struct i2c_client *client;
+	struct mutex lock;
+	int int_time;
+};
+
+static IIO_CONST_ATTR_INT_TIME_AVAIL("0.1 0.2 0.4");
+
+static struct attribute *tsl4531_attributes[] = {
+	&iio_const_attr_integration_time_available.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group tsl4531_attribute_group = {
+	.attrs = tsl4531_attributes,
+};
+
+static const struct iio_chan_spec tsl4531_channels[] = {
+	{
+		.type = IIO_LIGHT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_INT_TIME)
+	}
+};
+
+static int tsl4531_read_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *chan,
+				int *val, int *val2, long mask)
+{
+	struct tsl4531_data *data = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = i2c_smbus_read_word_data(data->client,
+			TSL4531_DATA);
+		if (ret < 0)
+			return ret;
+		*val = ret;
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		/* 0.. 1x, 1 .. 2x, 2 .. 4x */
+		*val = 1 << data->int_time;
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_INT_TIME:
+		if (data->int_time == 0)
+			*val2 = 400000;
+		else if (data->int_time == 1)
+			*val2 = 200000;
+		else if (data->int_time == 2)
+			*val2 = 100000;
+		else
+			return -EINVAL;
+		*val = 0;
+		return IIO_VAL_INT_PLUS_MICRO;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int tsl4531_write_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int val, int val2, long mask)
+{
+	struct tsl4531_data *data = iio_priv(indio_dev);
+	int int_time, ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_INT_TIME:
+		if (val != 0)
+			return -EINVAL;
+		if (val2 == 400000)
+			int_time = 0;
+		else if (val2 == 200000)
+			int_time = 1;
+		else if (val2 == 100000)
+			int_time = 2;
+		else
+			return -EINVAL;
+		mutex_lock(&data->lock);
+		ret = i2c_smbus_write_byte_data(data->client,
+			TSL4531_CONFIG, int_time);
+		if (ret >= 0)
+			data->int_time = int_time;
+		mutex_unlock(&data->lock);
+		return ret;
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_info tsl4531_info = {
+	.read_raw = tsl4531_read_raw,
+	.write_raw = tsl4531_write_raw,
+	.attrs = &tsl4531_attribute_group,
+	.driver_module = THIS_MODULE,
+};
+
+static int tsl4531_check_id(struct i2c_client *client)
+{
+	int ret = i2c_smbus_read_byte_data(client, TSL4531_ID);
+	if (ret < 0)
+		return ret;
+
+	switch (ret >> TSL4531_ID_SHIFT) {
+	case TSL45311_ID:
+	case TSL45313_ID:
+	case TSL45315_ID:
+	case TSL45317_ID:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static int tsl4531_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	struct tsl4531_data *data;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	i2c_set_clientdata(client, indio_dev);
+	data->client = client;
+	mutex_init(&data->lock);
+
+	if (!tsl4531_check_id(client)) {
+		dev_err(&client->dev, "no TSL4531 sensor\n");
+		return -ENODEV;
+	}
+
+	ret = i2c_smbus_write_byte_data(data->client, TSL4531_CONTROL,
+		TSL4531_MODE_NORMAL);
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_smbus_write_byte_data(data->client, TSL4531_CONFIG,
+		TSL4531_TCNTRL_400MS);
+	if (ret < 0)
+		return ret;
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &tsl4531_info;
+	indio_dev->channels = tsl4531_channels;
+	indio_dev->num_channels = ARRAY_SIZE(tsl4531_channels);
+	indio_dev->name = TSL4531_DRV_NAME;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	return iio_device_register(indio_dev);
+}
+
+static int tsl4531_powerdown(struct i2c_client *client)
+{
+	return i2c_smbus_write_byte_data(client, TSL4531_CONTROL,
+		TSL4531_MODE_POWERDOWN);
+}
+
+static int tsl4531_remove(struct i2c_client *client)
+{
+	iio_device_unregister(i2c_get_clientdata(client));
+	tsl4531_powerdown(client);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tsl4531_suspend(struct device *dev)
+{
+	return tsl4531_powerdown(to_i2c_client(dev));
+}
+
+static int tsl4531_resume(struct device *dev)
+{
+	return i2c_smbus_write_byte_data(to_i2c_client(dev), TSL4531_CONTROL,
+		TSL4531_MODE_NORMAL);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(tsl4531_pm_ops, tsl4531_suspend, tsl4531_resume);
+
+static const struct i2c_device_id tsl4531_id[] = {
+	{ "tsl4531", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tsl4531_id);
+
+static struct i2c_driver tsl4531_driver = {
+	.driver = {
+		.name   = TSL4531_DRV_NAME,
+		.pm	= &tsl4531_pm_ops,
+		.owner  = THIS_MODULE,
+	},
+	.probe  = tsl4531_probe,
+	.remove = tsl4531_remove,
+	.id_table = tsl4531_id,
+};
+
+module_i2c_driver(tsl4531_driver);
+
+MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
+MODULE_DESCRIPTION("TAOS TSL4531 ambient light sensors driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index 2bb3042..ecb3341 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -179,11 +179,7 @@
 	indio_dev->name = VCNL4000_DRV_NAME;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = iio_device_register(indio_dev);
-	if (ret < 0)
-		return ret;
-
-	return 0;
+	return iio_device_register(indio_dev);
 }
 
 static int vcnl4000_remove(struct i2c_client *client)
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig
index 4fa923f..0cf0963 100644
--- a/drivers/iio/magnetometer/Kconfig
+++ b/drivers/iio/magnetometer/Kconfig
@@ -16,6 +16,16 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called ak8975.
 
+config MAG3110
+	tristate "Freescale MAG3110 3-Axis Magnetometer"
+	depends on I2C
+	help
+	  Say yes here to build support for the Freescale MAG3110 3-Axis
+	  magnetometer.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called mag3110.
+
 config HID_SENSOR_MAGNETOMETER_3D
 	depends on HID_SENSOR_HUB
 	select IIO_BUFFER
diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile
index f91b1b6..0f5d3c9 100644
--- a/drivers/iio/magnetometer/Makefile
+++ b/drivers/iio/magnetometer/Makefile
@@ -4,6 +4,7 @@
 
 # When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AK8975)	+= ak8975.o
+obj-$(CONFIG_MAG3110)	+= mag3110.o
 obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o
 
 obj-$(CONFIG_IIO_ST_MAGN_3AXIS) += st_magn.o
diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c
index 7105f22..ff284e5 100644
--- a/drivers/iio/magnetometer/ak8975.c
+++ b/drivers/iio/magnetometer/ak8975.c
@@ -263,7 +263,7 @@
  *
  * HuT = H * 1229/4096, or roughly, 3/10.
  *
- * Since 1uT = 100 gauss, our final scale factor becomes:
+ * Since 1uT = 0.01 gauss, our final scale factor becomes:
  *
  * Hadj = H * ((ASA + 128) / 256) * 3/10 * 100
  * Hadj = H * ((ASA + 128) * 30 / 256
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
index a98460b..2634920 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -183,10 +183,11 @@
 };
 
 /* Function to push data to buffer */
-static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
+static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data,
+	int len)
 {
 	dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
-	iio_push_to_buffers(indio_dev, (u8 *)data);
+	iio_push_to_buffers(indio_dev, data);
 }
 
 /* Callback handler to send event after all samples are received and captured */
@@ -201,7 +202,7 @@
 				magn_state->common_attributes.data_ready);
 	if (magn_state->common_attributes.data_ready)
 		hid_sensor_push_data(indio_dev,
-				(u8 *)magn_state->magn_val,
+				magn_state->magn_val,
 				sizeof(magn_state->magn_val));
 
 	return 0;
diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c
new file mode 100644
index 0000000..783c5b4
--- /dev/null
+++ b/drivers/iio/magnetometer/mag3110.c
@@ -0,0 +1,401 @@
+/*
+ * mag3110.c - Support for Freescale MAG3110 magnetometer sensor
+ *
+ * Copyright (c) 2013 Peter Meerwald <pmeerw@pmeerw.net>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * (7-bit I2C slave address 0x0e)
+ *
+ * TODO: irq, user offset, oversampling, continuous mode
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/delay.h>
+
+#define MAG3110_STATUS 0x00
+#define MAG3110_OUT_X 0x01 /* MSB first */
+#define MAG3110_OUT_Y 0x03
+#define MAG3110_OUT_Z 0x05
+#define MAG3110_WHO_AM_I 0x07
+#define MAG3110_OFF_X 0x09 /* MSB first */
+#define MAG3110_OFF_Y 0x0b
+#define MAG3110_OFF_Z 0x0d
+#define MAG3110_DIE_TEMP 0x0f
+#define MAG3110_CTRL_REG1 0x10
+#define MAG3110_CTRL_REG2 0x11
+
+#define MAG3110_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
+
+#define MAG3110_CTRL_DR_MASK (BIT(7) | BIT(6) | BIT(5))
+#define MAG3110_CTRL_DR_SHIFT 5
+#define MAG3110_CTRL_DR_DEFAULT 0
+
+#define MAG3110_CTRL_TM BIT(1) /* trigger single measurement */
+#define MAG3110_CTRL_AC BIT(0) /* continuous measurements */
+
+#define MAG3110_CTRL_AUTO_MRST_EN BIT(7) /* magnetic auto-reset */
+#define MAG3110_CTRL_RAW BIT(5) /* measurements not user-offset corrected */
+
+#define MAG3110_DEVICE_ID 0xc4
+
+/* Each client has this additional data */
+struct mag3110_data {
+	struct i2c_client *client;
+	struct mutex lock;
+	u8 ctrl_reg1;
+};
+
+static int mag3110_request(struct mag3110_data *data)
+{
+	int ret, tries = 150;
+
+	/* trigger measurement */
+	ret = i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1,
+		data->ctrl_reg1 | MAG3110_CTRL_TM);
+	if (ret < 0)
+		return ret;
+
+	while (tries-- > 0) {
+		ret = i2c_smbus_read_byte_data(data->client, MAG3110_STATUS);
+		if (ret < 0)
+			return ret;
+		/* wait for data ready */
+		if ((ret & MAG3110_STATUS_DRDY) == MAG3110_STATUS_DRDY)
+			break;
+		msleep(20);
+	}
+
+	if (tries < 0) {
+		dev_err(&data->client->dev, "data not ready\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int mag3110_read(struct mag3110_data *data, __be16 buf[3])
+{
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = mag3110_request(data);
+	if (ret < 0) {
+		mutex_unlock(&data->lock);
+		return ret;
+	}
+	ret = i2c_smbus_read_i2c_block_data(data->client,
+		MAG3110_OUT_X, 3 * sizeof(__be16), (u8 *) buf);
+	mutex_unlock(&data->lock);
+
+	return ret;
+}
+
+static ssize_t mag3110_show_int_plus_micros(char *buf,
+	const int (*vals)[2], int n)
+{
+	size_t len = 0;
+
+	while (n-- > 0)
+		len += scnprintf(buf + len, PAGE_SIZE - len,
+			"%d.%d ", vals[n][0], vals[n][1]);
+
+	/* replace trailing space by newline */
+	buf[len - 1] = '\n';
+
+	return len;
+}
+
+static int mag3110_get_int_plus_micros_index(const int (*vals)[2], int n,
+					int val, int val2)
+{
+	while (n-- > 0)
+		if (val == vals[n][0] && val2 == vals[n][1])
+			return n;
+
+	return -EINVAL;
+}
+
+static const int mag3110_samp_freq[8][2] = {
+	{80, 0}, {40, 0}, {20, 0}, {10, 0}, {5, 0}, {2, 500000},
+	{1, 250000}, {0, 625000}
+};
+
+static ssize_t mag3110_show_samp_freq_avail(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	return mag3110_show_int_plus_micros(buf, mag3110_samp_freq, 8);
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mag3110_show_samp_freq_avail);
+
+static int mag3110_get_samp_freq_index(struct mag3110_data *data,
+	int val, int val2)
+{
+	return mag3110_get_int_plus_micros_index(mag3110_samp_freq, 8, val,
+		val2);
+}
+
+static int mag3110_read_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int *val, int *val2, long mask)
+{
+	struct mag3110_data *data = iio_priv(indio_dev);
+	__be16 buffer[3];
+	int i, ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		switch (chan->type) {
+		case IIO_MAGN: /* in 0.1 uT / LSB */
+			ret = mag3110_read(data, buffer);
+			if (ret < 0)
+				return ret;
+			*val = sign_extend32(
+				be16_to_cpu(buffer[chan->scan_index]), 15);
+			return IIO_VAL_INT;
+		case IIO_TEMP: /* in 1 C / LSB */
+			mutex_lock(&data->lock);
+			ret = mag3110_request(data);
+			if (ret < 0) {
+				mutex_unlock(&data->lock);
+				return ret;
+			}
+			ret = i2c_smbus_read_byte_data(data->client,
+				MAG3110_DIE_TEMP);
+			mutex_unlock(&data->lock);
+			if (ret < 0)
+				return ret;
+			*val = sign_extend32(ret, 7);
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
+	case IIO_CHAN_INFO_SCALE:
+		*val = 0;
+		*val2 = 1000;
+		return IIO_VAL_INT_PLUS_MICRO;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		i = data->ctrl_reg1 >> MAG3110_CTRL_DR_SHIFT;
+		*val = mag3110_samp_freq[i][0];
+		*val2 = mag3110_samp_freq[i][1];
+		return IIO_VAL_INT_PLUS_MICRO;
+	}
+	return -EINVAL;
+}
+
+static int mag3110_write_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int val, int val2, long mask)
+{
+	struct mag3110_data *data = iio_priv(indio_dev);
+	int rate;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		rate = mag3110_get_samp_freq_index(data, val, val2);
+		if (rate < 0)
+			return -EINVAL;
+
+		data->ctrl_reg1 &= ~MAG3110_CTRL_DR_MASK;
+		data->ctrl_reg1 |= rate << MAG3110_CTRL_DR_SHIFT;
+		return i2c_smbus_write_byte_data(data->client,
+			MAG3110_CTRL_REG1, data->ctrl_reg1);
+	default:
+		return -EINVAL;
+	}
+}
+
+static irqreturn_t mag3110_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct mag3110_data *data = iio_priv(indio_dev);
+	u8 buffer[16]; /* 3 16-bit channels + 1 byte temp + padding + ts */
+	int ret;
+
+	ret = mag3110_read(data, (__be16 *) buffer);
+	if (ret < 0)
+		goto done;
+
+	if (test_bit(3, indio_dev->active_scan_mask)) {
+		ret = i2c_smbus_read_byte_data(data->client,
+			MAG3110_DIE_TEMP);
+		if (ret < 0)
+			goto done;
+		buffer[6] = ret;
+	}
+
+	iio_push_to_buffers_with_timestamp(indio_dev, buffer,
+		iio_get_time_ns());
+
+done:
+	iio_trigger_notify_done(indio_dev->trig);
+	return IRQ_HANDLED;
+}
+
+#define MAG3110_CHANNEL(axis, idx) { \
+	.type = IIO_MAGN, \
+	.modified = 1, \
+	.channel2 = IIO_MOD_##axis, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+		BIT(IIO_CHAN_INFO_SCALE), \
+	.scan_index = idx, \
+	.scan_type = IIO_ST('s', 16, 16, IIO_BE), \
+}
+
+static const struct iio_chan_spec mag3110_channels[] = {
+	MAG3110_CHANNEL(X, 0),
+	MAG3110_CHANNEL(Y, 1),
+	MAG3110_CHANNEL(Z, 2),
+	{
+		.type = IIO_TEMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.scan_index = 3,
+		.scan_type = IIO_ST('s', 8, 8, 0),
+	},
+	IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+static struct attribute *mag3110_attributes[] = {
+	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group mag3110_group = {
+	.attrs = mag3110_attributes,
+};
+
+static const struct iio_info mag3110_info = {
+	.attrs = &mag3110_group,
+	.read_raw = &mag3110_read_raw,
+	.write_raw = &mag3110_write_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static const unsigned long mag3110_scan_masks[] = {0x7, 0xf, 0};
+
+static int mag3110_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct mag3110_data *data;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(client, MAG3110_WHO_AM_I);
+	if (ret < 0)
+		return ret;
+	if (ret != MAG3110_DEVICE_ID)
+		return -ENODEV;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	data->client = client;
+	mutex_init(&data->lock);
+
+	i2c_set_clientdata(client, indio_dev);
+	indio_dev->info = &mag3110_info;
+	indio_dev->name = id->name;
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = mag3110_channels;
+	indio_dev->num_channels = ARRAY_SIZE(mag3110_channels);
+	indio_dev->available_scan_masks = mag3110_scan_masks;
+
+	data->ctrl_reg1 = MAG3110_CTRL_DR_DEFAULT;
+	ret = i2c_smbus_write_byte_data(client, MAG3110_CTRL_REG1,
+		data->ctrl_reg1);
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_smbus_write_byte_data(client, MAG3110_CTRL_REG2,
+		MAG3110_CTRL_AUTO_MRST_EN | MAG3110_CTRL_RAW);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+		mag3110_trigger_handler, NULL);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0)
+		goto buffer_cleanup;
+	return 0;
+
+buffer_cleanup:
+	iio_triggered_buffer_cleanup(indio_dev);
+	return ret;
+}
+
+static int mag3110_standby(struct mag3110_data *data)
+{
+	return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1,
+		data->ctrl_reg1 & ~MAG3110_CTRL_AC);
+}
+
+static int mag3110_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+	mag3110_standby(iio_priv(indio_dev));
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mag3110_suspend(struct device *dev)
+{
+	return mag3110_standby(iio_priv(i2c_get_clientdata(
+		to_i2c_client(dev))));
+}
+
+static int mag3110_resume(struct device *dev)
+{
+	struct mag3110_data *data = iio_priv(i2c_get_clientdata(
+		to_i2c_client(dev)));
+
+	return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1,
+		data->ctrl_reg1);
+}
+
+static SIMPLE_DEV_PM_OPS(mag3110_pm_ops, mag3110_suspend, mag3110_resume);
+#define MAG3110_PM_OPS (&mag3110_pm_ops)
+#else
+#define MAG3110_PM_OPS NULL
+#endif
+
+static const struct i2c_device_id mag3110_id[] = {
+	{ "mag3110", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mag3110_id);
+
+static struct i2c_driver mag3110_driver = {
+	.driver = {
+		.name	= "mag3110",
+		.pm	= MAG3110_PM_OPS,
+	},
+	.probe = mag3110_probe,
+	.remove = mag3110_remove,
+	.id_table = mag3110_id,
+};
+module_i2c_driver(mag3110_driver);
+
+MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
+MODULE_DESCRIPTION("Freescale MAG3110 magnetometer driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/magnetometer/st_magn_buffer.c b/drivers/iio/magnetometer/st_magn_buffer.c
index 708857b..bf427dc 100644
--- a/drivers/iio/magnetometer/st_magn_buffer.c
+++ b/drivers/iio/magnetometer/st_magn_buffer.c
@@ -25,16 +25,7 @@
 
 static int st_magn_buffer_preenable(struct iio_dev *indio_dev)
 {
-	int err;
-
-	err = st_sensors_set_enable(indio_dev, true);
-	if (err < 0)
-		goto st_magn_set_enable_error;
-
-	err = iio_sw_buffer_preenable(indio_dev);
-
-st_magn_set_enable_error:
-	return err;
+	return st_sensors_set_enable(indio_dev, true);
 }
 
 static int st_magn_buffer_postenable(struct iio_dev *indio_dev)
diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
index cab3bc7..52bbcfa 100644
--- a/drivers/iio/magnetometer/st_magn_core.c
+++ b/drivers/iio/magnetometer/st_magn_core.c
@@ -348,8 +348,9 @@
 int st_magn_common_probe(struct iio_dev *indio_dev,
 					struct st_sensors_platform_data *pdata)
 {
-	int err;
 	struct st_sensor_data *mdata = iio_priv(indio_dev);
+	int irq = mdata->get_irq_data_ready(indio_dev);
+	int err;
 
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &magn_info;
@@ -357,7 +358,7 @@
 	err = st_sensors_check_device_support(indio_dev,
 				ARRAY_SIZE(st_magn_sensors), st_magn_sensors);
 	if (err < 0)
-		goto st_magn_common_probe_error;
+		return err;
 
 	mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS;
 	mdata->multiread_bit = mdata->sensor->multi_read_bit;
@@ -370,12 +371,13 @@
 
 	err = st_sensors_init_sensor(indio_dev, pdata);
 	if (err < 0)
-		goto st_magn_common_probe_error;
+		return err;
 
-	if (mdata->get_irq_data_ready(indio_dev) > 0) {
-		err = st_magn_allocate_ring(indio_dev);
-		if (err < 0)
-			goto st_magn_common_probe_error;
+	err = st_magn_allocate_ring(indio_dev);
+	if (err < 0)
+		return err;
+
+	if (irq > 0) {
 		err = st_sensors_allocate_trigger(indio_dev, NULL);
 		if (err < 0)
 			goto st_magn_probe_trigger_error;
@@ -385,15 +387,14 @@
 	if (err)
 		goto st_magn_device_register_error;
 
-	return err;
+	return 0;
 
 st_magn_device_register_error:
-	if (mdata->get_irq_data_ready(indio_dev) > 0)
+	if (irq > 0)
 		st_sensors_deallocate_trigger(indio_dev);
 st_magn_probe_trigger_error:
-	if (mdata->get_irq_data_ready(indio_dev) > 0)
-		st_magn_deallocate_ring(indio_dev);
-st_magn_common_probe_error:
+	st_magn_deallocate_ring(indio_dev);
+
 	return err;
 }
 EXPORT_SYMBOL(st_magn_common_probe);
@@ -403,10 +404,10 @@
 	struct st_sensor_data *mdata = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	if (mdata->get_irq_data_ready(indio_dev) > 0) {
+	if (mdata->get_irq_data_ready(indio_dev) > 0)
 		st_sensors_deallocate_trigger(indio_dev);
-		st_magn_deallocate_ring(indio_dev);
-	}
+
+	st_magn_deallocate_ring(indio_dev);
 }
 EXPORT_SYMBOL(st_magn_common_remove);
 
diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig
index 26fdc0b..4f2e0f9 100644
--- a/drivers/iio/pressure/Kconfig
+++ b/drivers/iio/pressure/Kconfig
@@ -14,7 +14,7 @@
 	select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
 	help
 	  Say yes here to build support for STMicroelectronics pressure
-	  sensors: LPS331AP.
+	  sensors: LPS001WP, LPS331AP.
 
 	  This driver can also be built as a module. If so, these modules
 	  will be created:
diff --git a/drivers/iio/pressure/st_pressure.h b/drivers/iio/pressure/st_pressure.h
index b0b6306..049c21a 100644
--- a/drivers/iio/pressure/st_pressure.h
+++ b/drivers/iio/pressure/st_pressure.h
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/iio/common/st_sensors.h>
 
+#define LPS001WP_PRESS_DEV_NAME		"lps001wp"
 #define LPS331AP_PRESS_DEV_NAME		"lps331ap"
 
 /**
diff --git a/drivers/iio/pressure/st_pressure_buffer.c b/drivers/iio/pressure/st_pressure_buffer.c
index f877ef8..b37b1c9 100644
--- a/drivers/iio/pressure/st_pressure_buffer.c
+++ b/drivers/iio/pressure/st_pressure_buffer.c
@@ -32,16 +32,7 @@
 
 static int st_press_buffer_preenable(struct iio_dev *indio_dev)
 {
-	int err;
-
-	err = st_sensors_set_enable(indio_dev, true);
-	if (err < 0)
-		goto st_press_set_enable_error;
-
-	err = iio_sw_buffer_preenable(indio_dev);
-
-st_press_set_enable_error:
-	return err;
+	return st_sensors_set_enable(indio_dev, true);
 }
 
 static int st_press_buffer_postenable(struct iio_dev *indio_dev)
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c
index ceebd3c..58083f9 100644
--- a/drivers/iio/pressure/st_pressure_core.c
+++ b/drivers/iio/pressure/st_pressure_core.c
@@ -23,6 +23,7 @@
 #include <linux/iio/sysfs.h>
 #include <linux/iio/trigger.h>
 #include <linux/iio/buffer.h>
+#include <linux/regulator/consumer.h>
 #include <asm/unaligned.h>
 
 #include <linux/iio/common/st_sensors.h>
@@ -36,94 +37,200 @@
 						 ST_PRESS_LSB_PER_CELSIUS)
 #define ST_PRESS_NUMBER_DATA_CHANNELS		1
 
-/* DEFAULT VALUE FOR SENSORS */
-#define ST_PRESS_DEFAULT_OUT_XL_ADDR		0x28
-#define ST_TEMP_DEFAULT_OUT_L_ADDR		0x2b
-
 /* FULLSCALE */
 #define ST_PRESS_FS_AVL_1260MB			1260
 
-/* CUSTOM VALUES FOR SENSOR 1 */
-#define ST_PRESS_1_WAI_EXP			0xbb
-#define ST_PRESS_1_ODR_ADDR			0x20
-#define ST_PRESS_1_ODR_MASK			0x70
-#define ST_PRESS_1_ODR_AVL_1HZ_VAL		0x01
-#define ST_PRESS_1_ODR_AVL_7HZ_VAL		0x05
-#define ST_PRESS_1_ODR_AVL_13HZ_VAL		0x06
-#define ST_PRESS_1_ODR_AVL_25HZ_VAL		0x07
-#define ST_PRESS_1_PW_ADDR			0x20
-#define ST_PRESS_1_PW_MASK			0x80
-#define ST_PRESS_1_FS_ADDR			0x23
-#define ST_PRESS_1_FS_MASK			0x30
-#define ST_PRESS_1_FS_AVL_1260_VAL		0x00
-#define ST_PRESS_1_FS_AVL_1260_GAIN		ST_PRESS_KPASCAL_NANO_SCALE
-#define ST_PRESS_1_FS_AVL_TEMP_GAIN		ST_PRESS_CELSIUS_NANO_SCALE
-#define ST_PRESS_1_BDU_ADDR			0x20
-#define ST_PRESS_1_BDU_MASK			0x04
-#define ST_PRESS_1_DRDY_IRQ_ADDR		0x22
-#define ST_PRESS_1_DRDY_IRQ_INT1_MASK		0x04
-#define ST_PRESS_1_DRDY_IRQ_INT2_MASK		0x20
-#define ST_PRESS_1_MULTIREAD_BIT		true
-#define ST_PRESS_1_TEMP_OFFSET			42500
+/* CUSTOM VALUES FOR LPS331AP SENSOR */
+#define ST_PRESS_LPS331AP_WAI_EXP		0xbb
+#define ST_PRESS_LPS331AP_ODR_ADDR		0x20
+#define ST_PRESS_LPS331AP_ODR_MASK		0x70
+#define ST_PRESS_LPS331AP_ODR_AVL_1HZ_VAL	0x01
+#define ST_PRESS_LPS331AP_ODR_AVL_7HZ_VAL	0x05
+#define ST_PRESS_LPS331AP_ODR_AVL_13HZ_VAL	0x06
+#define ST_PRESS_LPS331AP_ODR_AVL_25HZ_VAL	0x07
+#define ST_PRESS_LPS331AP_PW_ADDR		0x20
+#define ST_PRESS_LPS331AP_PW_MASK		0x80
+#define ST_PRESS_LPS331AP_FS_ADDR		0x23
+#define ST_PRESS_LPS331AP_FS_MASK		0x30
+#define ST_PRESS_LPS331AP_FS_AVL_1260_VAL	0x00
+#define ST_PRESS_LPS331AP_FS_AVL_1260_GAIN	ST_PRESS_KPASCAL_NANO_SCALE
+#define ST_PRESS_LPS331AP_FS_AVL_TEMP_GAIN	ST_PRESS_CELSIUS_NANO_SCALE
+#define ST_PRESS_LPS331AP_BDU_ADDR		0x20
+#define ST_PRESS_LPS331AP_BDU_MASK		0x04
+#define ST_PRESS_LPS331AP_DRDY_IRQ_ADDR		0x22
+#define ST_PRESS_LPS331AP_DRDY_IRQ_INT1_MASK	0x04
+#define ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK	0x20
+#define ST_PRESS_LPS331AP_MULTIREAD_BIT		true
+#define ST_PRESS_LPS331AP_TEMP_OFFSET		42500
+#define ST_PRESS_LPS331AP_OUT_XL_ADDR		0x28
+#define ST_TEMP_LPS331AP_OUT_L_ADDR		0x2b
 
-static const struct iio_chan_spec st_press_channels[] = {
-	ST_SENSORS_LSM_CHANNELS(IIO_PRESSURE,
+/* CUSTOM VALUES FOR LPS001WP SENSOR */
+#define ST_PRESS_LPS001WP_WAI_EXP		0xba
+#define ST_PRESS_LPS001WP_ODR_ADDR		0x20
+#define ST_PRESS_LPS001WP_ODR_MASK		0x30
+#define ST_PRESS_LPS001WP_ODR_AVL_1HZ_VAL	0x01
+#define ST_PRESS_LPS001WP_ODR_AVL_7HZ_VAL	0x02
+#define ST_PRESS_LPS001WP_ODR_AVL_13HZ_VAL	0x03
+#define ST_PRESS_LPS001WP_PW_ADDR		0x20
+#define ST_PRESS_LPS001WP_PW_MASK		0x40
+#define ST_PRESS_LPS001WP_BDU_ADDR		0x20
+#define ST_PRESS_LPS001WP_BDU_MASK		0x04
+#define ST_PRESS_LPS001WP_MULTIREAD_BIT		true
+#define ST_PRESS_LPS001WP_OUT_L_ADDR		0x28
+#define ST_TEMP_LPS001WP_OUT_L_ADDR		0x2a
+
+static const struct iio_chan_spec st_press_lps331ap_channels[] = {
+	{
+		.type = IIO_PRESSURE,
+		.channel2 = IIO_NO_MOD,
+		.address = ST_PRESS_LPS331AP_OUT_XL_ADDR,
+		.scan_index = ST_SENSORS_SCAN_X,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 24,
+			.storagebits = 24,
+			.endianness = IIO_LE,
+		},
+		.info_mask_separate =
 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
-			ST_SENSORS_SCAN_X, 0, IIO_NO_MOD, 'u', IIO_LE, 24, 24,
-			ST_PRESS_DEFAULT_OUT_XL_ADDR),
-	ST_SENSORS_LSM_CHANNELS(IIO_TEMP,
-			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) |
-						BIT(IIO_CHAN_INFO_OFFSET),
-			-1, 0, IIO_NO_MOD, 's', IIO_LE, 16, 16,
-			ST_TEMP_DEFAULT_OUT_L_ADDR),
+		.modified = 0,
+	},
+	{
+		.type = IIO_TEMP,
+		.channel2 = IIO_NO_MOD,
+		.address = ST_TEMP_LPS331AP_OUT_L_ADDR,
+		.scan_index = -1,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 16,
+			.storagebits = 16,
+			.endianness = IIO_LE,
+		},
+		.info_mask_separate =
+			BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_OFFSET),
+		.modified = 0,
+	},
+	IIO_CHAN_SOFT_TIMESTAMP(1)
+};
+
+static const struct iio_chan_spec st_press_lps001wp_channels[] = {
+	{
+		.type = IIO_PRESSURE,
+		.channel2 = IIO_NO_MOD,
+		.address = ST_PRESS_LPS001WP_OUT_L_ADDR,
+		.scan_index = ST_SENSORS_SCAN_X,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 16,
+			.storagebits = 16,
+			.endianness = IIO_LE,
+		},
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.modified = 0,
+	},
+	{
+		.type = IIO_TEMP,
+		.channel2 = IIO_NO_MOD,
+		.address = ST_TEMP_LPS001WP_OUT_L_ADDR,
+		.scan_index = -1,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 16,
+			.storagebits = 16,
+			.endianness = IIO_LE,
+		},
+		.info_mask_separate =
+			BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_OFFSET),
+		.modified = 0,
+	},
 	IIO_CHAN_SOFT_TIMESTAMP(1)
 };
 
 static const struct st_sensors st_press_sensors[] = {
 	{
-		.wai = ST_PRESS_1_WAI_EXP,
+		.wai = ST_PRESS_LPS331AP_WAI_EXP,
 		.sensors_supported = {
 			[0] = LPS331AP_PRESS_DEV_NAME,
 		},
-		.ch = (struct iio_chan_spec *)st_press_channels,
+		.ch = (struct iio_chan_spec *)st_press_lps331ap_channels,
+		.num_ch = ARRAY_SIZE(st_press_lps331ap_channels),
 		.odr = {
-			.addr = ST_PRESS_1_ODR_ADDR,
-			.mask = ST_PRESS_1_ODR_MASK,
+			.addr = ST_PRESS_LPS331AP_ODR_ADDR,
+			.mask = ST_PRESS_LPS331AP_ODR_MASK,
 			.odr_avl = {
-				{ 1, ST_PRESS_1_ODR_AVL_1HZ_VAL, },
-				{ 7, ST_PRESS_1_ODR_AVL_7HZ_VAL, },
-				{ 13, ST_PRESS_1_ODR_AVL_13HZ_VAL, },
-				{ 25, ST_PRESS_1_ODR_AVL_25HZ_VAL, },
+				{ 1, ST_PRESS_LPS331AP_ODR_AVL_1HZ_VAL, },
+				{ 7, ST_PRESS_LPS331AP_ODR_AVL_7HZ_VAL, },
+				{ 13, ST_PRESS_LPS331AP_ODR_AVL_13HZ_VAL, },
+				{ 25, ST_PRESS_LPS331AP_ODR_AVL_25HZ_VAL, },
 			},
 		},
 		.pw = {
-			.addr = ST_PRESS_1_PW_ADDR,
-			.mask = ST_PRESS_1_PW_MASK,
+			.addr = ST_PRESS_LPS331AP_PW_ADDR,
+			.mask = ST_PRESS_LPS331AP_PW_MASK,
 			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 		},
 		.fs = {
-			.addr = ST_PRESS_1_FS_ADDR,
-			.mask = ST_PRESS_1_FS_MASK,
+			.addr = ST_PRESS_LPS331AP_FS_ADDR,
+			.mask = ST_PRESS_LPS331AP_FS_MASK,
 			.fs_avl = {
 				[0] = {
 					.num = ST_PRESS_FS_AVL_1260MB,
-					.value = ST_PRESS_1_FS_AVL_1260_VAL,
-					.gain = ST_PRESS_1_FS_AVL_1260_GAIN,
-					.gain2 = ST_PRESS_1_FS_AVL_TEMP_GAIN,
+					.value = ST_PRESS_LPS331AP_FS_AVL_1260_VAL,
+					.gain = ST_PRESS_LPS331AP_FS_AVL_1260_GAIN,
+					.gain2 = ST_PRESS_LPS331AP_FS_AVL_TEMP_GAIN,
 				},
 			},
 		},
 		.bdu = {
-			.addr = ST_PRESS_1_BDU_ADDR,
-			.mask = ST_PRESS_1_BDU_MASK,
+			.addr = ST_PRESS_LPS331AP_BDU_ADDR,
+			.mask = ST_PRESS_LPS331AP_BDU_MASK,
 		},
 		.drdy_irq = {
-			.addr = ST_PRESS_1_DRDY_IRQ_ADDR,
-			.mask_int1 = ST_PRESS_1_DRDY_IRQ_INT1_MASK,
-			.mask_int2 = ST_PRESS_1_DRDY_IRQ_INT2_MASK,
+			.addr = ST_PRESS_LPS331AP_DRDY_IRQ_ADDR,
+			.mask_int1 = ST_PRESS_LPS331AP_DRDY_IRQ_INT1_MASK,
+			.mask_int2 = ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK,
 		},
-		.multi_read_bit = ST_PRESS_1_MULTIREAD_BIT,
+		.multi_read_bit = ST_PRESS_LPS331AP_MULTIREAD_BIT,
+		.bootime = 2,
+	},
+	{
+		.wai = ST_PRESS_LPS001WP_WAI_EXP,
+		.sensors_supported = {
+			[0] = LPS001WP_PRESS_DEV_NAME,
+		},
+		.ch = (struct iio_chan_spec *)st_press_lps001wp_channels,
+		.num_ch = ARRAY_SIZE(st_press_lps001wp_channels),
+		.odr = {
+			.addr = ST_PRESS_LPS001WP_ODR_ADDR,
+			.mask = ST_PRESS_LPS001WP_ODR_MASK,
+			.odr_avl = {
+				{ 1, ST_PRESS_LPS001WP_ODR_AVL_1HZ_VAL, },
+				{ 7, ST_PRESS_LPS001WP_ODR_AVL_7HZ_VAL, },
+				{ 13, ST_PRESS_LPS001WP_ODR_AVL_13HZ_VAL, },
+			},
+		},
+		.pw = {
+			.addr = ST_PRESS_LPS001WP_PW_ADDR,
+			.mask = ST_PRESS_LPS001WP_PW_MASK,
+			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
+			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
+		},
+		.fs = {
+			.addr = 0,
+		},
+		.bdu = {
+			.addr = ST_PRESS_LPS001WP_BDU_ADDR,
+			.mask = ST_PRESS_LPS001WP_BDU_MASK,
+		},
+		.drdy_irq = {
+			.addr = 0,
+		},
+		.multi_read_bit = ST_PRESS_LPS001WP_MULTIREAD_BIT,
 		.bootime = 2,
 	},
 };
@@ -207,44 +314,85 @@
 #define ST_PRESS_TRIGGER_OPS NULL
 #endif
 
+static void st_press_power_enable(struct iio_dev *indio_dev)
+{
+	struct st_sensor_data *pdata = iio_priv(indio_dev);
+	int err;
+
+	/* Regulators not mandatory, but if requested we should enable them. */
+	pdata->vdd = devm_regulator_get_optional(&indio_dev->dev, "vdd");
+	if (!IS_ERR(pdata->vdd)) {
+		err = regulator_enable(pdata->vdd);
+		if (err != 0)
+			dev_warn(&indio_dev->dev,
+				 "Failed to enable specified Vdd supply\n");
+	}
+
+	pdata->vdd_io = devm_regulator_get_optional(&indio_dev->dev, "vddio");
+	if (!IS_ERR(pdata->vdd_io)) {
+		err = regulator_enable(pdata->vdd_io);
+		if (err != 0)
+			dev_warn(&indio_dev->dev,
+				 "Failed to enable specified Vdd_IO supply\n");
+	}
+}
+
+static void st_press_power_disable(struct iio_dev *indio_dev)
+{
+	struct st_sensor_data *pdata = iio_priv(indio_dev);
+
+	if (!IS_ERR(pdata->vdd))
+		regulator_disable(pdata->vdd);
+
+	if (!IS_ERR(pdata->vdd_io))
+		regulator_disable(pdata->vdd_io);
+}
+
 int st_press_common_probe(struct iio_dev *indio_dev,
 				struct st_sensors_platform_data *plat_data)
 {
-	int err;
 	struct st_sensor_data *pdata = iio_priv(indio_dev);
+	int irq = pdata->get_irq_data_ready(indio_dev);
+	int err;
 
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &press_info;
 
+	st_press_power_enable(indio_dev);
+
 	err = st_sensors_check_device_support(indio_dev,
-				ARRAY_SIZE(st_press_sensors), st_press_sensors);
+					      ARRAY_SIZE(st_press_sensors),
+					      st_press_sensors);
 	if (err < 0)
-		goto st_press_common_probe_error;
+		return err;
 
 	pdata->num_data_channels = ST_PRESS_NUMBER_DATA_CHANNELS;
-	pdata->multiread_bit = pdata->sensor->multi_read_bit;
-	indio_dev->channels = pdata->sensor->ch;
-	indio_dev->num_channels = ARRAY_SIZE(st_press_channels);
+	pdata->multiread_bit     = pdata->sensor->multi_read_bit;
+	indio_dev->channels      = pdata->sensor->ch;
+	indio_dev->num_channels  = pdata->sensor->num_ch;
 
-	pdata->current_fullscale = (struct st_sensor_fullscale_avl *)
-						&pdata->sensor->fs.fs_avl[0];
+	if (pdata->sensor->fs.addr != 0)
+		pdata->current_fullscale = (struct st_sensor_fullscale_avl *)
+			&pdata->sensor->fs.fs_avl[0];
+
 	pdata->odr = pdata->sensor->odr.odr_avl[0].hz;
 
-	if (!plat_data)
+	/* Some devices don't support a data ready pin. */
+	if (!plat_data && pdata->sensor->drdy_irq.addr)
 		plat_data =
 			(struct st_sensors_platform_data *)&default_press_pdata;
 
 	err = st_sensors_init_sensor(indio_dev, plat_data);
 	if (err < 0)
-		goto st_press_common_probe_error;
+		return err;
 
-	if (pdata->get_irq_data_ready(indio_dev) > 0) {
-		err = st_press_allocate_ring(indio_dev);
-		if (err < 0)
-			goto st_press_common_probe_error;
+	err = st_press_allocate_ring(indio_dev);
+	if (err < 0)
+		return err;
 
+	if (irq > 0) {
 		err = st_sensors_allocate_trigger(indio_dev,
-							ST_PRESS_TRIGGER_OPS);
+						  ST_PRESS_TRIGGER_OPS);
 		if (err < 0)
 			goto st_press_probe_trigger_error;
 	}
@@ -256,12 +404,11 @@
 	return err;
 
 st_press_device_register_error:
-	if (pdata->get_irq_data_ready(indio_dev) > 0)
+	if (irq > 0)
 		st_sensors_deallocate_trigger(indio_dev);
 st_press_probe_trigger_error:
-	if (pdata->get_irq_data_ready(indio_dev) > 0)
-		st_press_deallocate_ring(indio_dev);
-st_press_common_probe_error:
+	st_press_deallocate_ring(indio_dev);
+
 	return err;
 }
 EXPORT_SYMBOL(st_press_common_probe);
@@ -270,11 +417,13 @@
 {
 	struct st_sensor_data *pdata = iio_priv(indio_dev);
 
+	st_press_power_disable(indio_dev);
+
 	iio_device_unregister(indio_dev);
-	if (pdata->get_irq_data_ready(indio_dev) > 0) {
+	if (pdata->get_irq_data_ready(indio_dev) > 0)
 		st_sensors_deallocate_trigger(indio_dev);
-		st_press_deallocate_ring(indio_dev);
-	}
+
+	st_press_deallocate_ring(indio_dev);
 }
 EXPORT_SYMBOL(st_press_common_remove);
 
diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c
index 08aac5e..51eab7f 100644
--- a/drivers/iio/pressure/st_pressure_i2c.c
+++ b/drivers/iio/pressure/st_pressure_i2c.c
@@ -49,6 +49,7 @@
 }
 
 static const struct i2c_device_id st_press_id_table[] = {
+	{ LPS001WP_PRESS_DEV_NAME },
 	{ LPS331AP_PRESS_DEV_NAME },
 	{},
 };
diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c
index 399a29b..27322af 100644
--- a/drivers/iio/pressure/st_pressure_spi.c
+++ b/drivers/iio/pressure/st_pressure_spi.c
@@ -48,6 +48,7 @@
 }
 
 static const struct spi_device_id st_press_id_table[] = {
+	{ LPS001WP_PRESS_DEV_NAME },
 	{ LPS331AP_PRESS_DEV_NAME },
 	{},
 };
diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c
index 6d63883..84a0789 100644
--- a/drivers/iio/temperature/tmp006.c
+++ b/drivers/iio/temperature/tmp006.c
@@ -70,12 +70,16 @@
 	return i2c_smbus_read_word_swapped(data->client, reg);
 }
 
+static const int tmp006_freqs[5][2] = { {4, 0}, {2, 0}, {1, 0},
+					{0, 500000}, {0, 250000} };
+
 static int tmp006_read_raw(struct iio_dev *indio_dev,
 			    struct iio_chan_spec const *channel, int *val,
 			    int *val2, long mask)
 {
 	struct tmp006_data *data = iio_priv(indio_dev);
 	s32 ret;
+	int cr;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
@@ -106,6 +110,12 @@
 			break;
 		}
 		return IIO_VAL_INT_PLUS_MICRO;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		cr = (data->config & TMP006_CONFIG_CR_MASK)
+			>> TMP006_CONFIG_CR_SHIFT;
+		*val = tmp006_freqs[cr][0];
+		*val2 = tmp006_freqs[cr][1];
+		return IIO_VAL_INT_PLUS_MICRO;
 	default:
 		break;
 	}
@@ -113,48 +123,32 @@
 	return -EINVAL;
 }
 
-static const char * const tmp006_freqs[] = { "4", "2", "1", "0.5", "0.25" };
-
-static ssize_t tmp006_show_freq(struct device *dev,
-				struct device_attribute *attr, char *buf)
+static int tmp006_write_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int val,
+			    int val2,
+			    long mask)
 {
-	struct tmp006_data *data = iio_priv(dev_to_iio_dev(dev));
-	int cr = (data->config & TMP006_CONFIG_CR_MASK)
-		>> TMP006_CONFIG_CR_SHIFT;
-	return sprintf(buf, "%s\n", tmp006_freqs[cr]);
-}
-
-static ssize_t tmp006_store_freq(struct device *dev,
-				 struct device_attribute *attr,
-				 const char *buf, size_t len)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct tmp006_data *data = iio_priv(indio_dev);
 	int i;
-	bool found = false;
 
 	for (i = 0; i < ARRAY_SIZE(tmp006_freqs); i++)
-		if (sysfs_streq(buf, tmp006_freqs[i])) {
-			found = true;
-			break;
+		if ((val == tmp006_freqs[i][0]) &&
+		    (val2 == tmp006_freqs[i][1])) {
+			data->config &= ~TMP006_CONFIG_CR_MASK;
+			data->config |= i << TMP006_CONFIG_CR_SHIFT;
+
+			return i2c_smbus_write_word_swapped(data->client,
+							    TMP006_CONFIG,
+							    data->config);
+
 		}
-	if (!found)
-		return -EINVAL;
-
-	data->config &= ~TMP006_CONFIG_CR_MASK;
-	data->config |= i << TMP006_CONFIG_CR_SHIFT;
-
-	return i2c_smbus_write_word_swapped(data->client, TMP006_CONFIG,
-		data->config);
+	return -EINVAL;
 }
 
-static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR,
-			tmp006_show_freq, tmp006_store_freq);
-
 static IIO_CONST_ATTR(sampling_frequency_available, "4 2 1 0.5 0.25");
 
 static struct attribute *tmp006_attributes[] = {
-	&iio_dev_attr_sampling_frequency.dev_attr.attr,
 	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
 	NULL
 };
@@ -168,16 +162,19 @@
 		.type = IIO_VOLTAGE,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 			BIT(IIO_CHAN_INFO_SCALE),
+		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
 	},
 	{
 		.type = IIO_TEMP,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 			BIT(IIO_CHAN_INFO_SCALE),
+		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
 	}
 };
 
 static const struct iio_info tmp006_info = {
 	.read_raw = tmp006_read_raw,
+	.write_raw = tmp006_write_raw,
 	.attrs = &tmp006_attribute_group,
 	.driver_module = THIS_MODULE,
 };
diff --git a/drivers/iio/trigger/iio-trig-sysfs.c b/drivers/iio/trigger/iio-trig-sysfs.c
index effcd0a..15e3b85 100644
--- a/drivers/iio/trigger/iio-trig-sysfs.c
+++ b/drivers/iio/trigger/iio-trig-sysfs.c
@@ -23,7 +23,7 @@
 };
 
 static LIST_HEAD(iio_sysfs_trig_list);
-static DEFINE_MUTEX(iio_syfs_trig_list_mut);
+static DEFINE_MUTEX(iio_sysfs_trig_list_mut);
 
 static int iio_sysfs_trigger_probe(int id);
 static ssize_t iio_sysfs_trig_add(struct device *dev,
@@ -135,7 +135,7 @@
 	struct iio_sysfs_trig *t;
 	int ret;
 	bool foundit = false;
-	mutex_lock(&iio_syfs_trig_list_mut);
+	mutex_lock(&iio_sysfs_trig_list_mut);
 	list_for_each_entry(t, &iio_sysfs_trig_list, l)
 		if (id == t->id) {
 			foundit = true;
@@ -169,7 +169,7 @@
 		goto out2;
 	list_add(&t->l, &iio_sysfs_trig_list);
 	__module_get(THIS_MODULE);
-	mutex_unlock(&iio_syfs_trig_list_mut);
+	mutex_unlock(&iio_sysfs_trig_list_mut);
 	return 0;
 
 out2:
@@ -177,7 +177,7 @@
 free_t:
 	kfree(t);
 out1:
-	mutex_unlock(&iio_syfs_trig_list_mut);
+	mutex_unlock(&iio_sysfs_trig_list_mut);
 	return ret;
 }
 
@@ -185,14 +185,14 @@
 {
 	bool foundit = false;
 	struct iio_sysfs_trig *t;
-	mutex_lock(&iio_syfs_trig_list_mut);
+	mutex_lock(&iio_sysfs_trig_list_mut);
 	list_for_each_entry(t, &iio_sysfs_trig_list, l)
 		if (id == t->id) {
 			foundit = true;
 			break;
 		}
 	if (!foundit) {
-		mutex_unlock(&iio_syfs_trig_list_mut);
+		mutex_unlock(&iio_sysfs_trig_list_mut);
 		return -EINVAL;
 	}
 
@@ -202,7 +202,7 @@
 	list_del(&t->l);
 	kfree(t);
 	module_put(THIS_MODULE);
-	mutex_unlock(&iio_syfs_trig_list_mut);
+	mutex_unlock(&iio_sysfs_trig_list_mut);
 	return 0;
 }
 
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index 5ceda71..b84791f 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -31,6 +31,17 @@
 	  libibverbs, libibcm and a hardware driver library from
 	  <http://www.openfabrics.org/git/>.
 
+config INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
+       bool "Experimental and unstable ABI for userspace access to flow steering verbs"
+       depends on INFINIBAND_USER_ACCESS
+       depends on STAGING
+	---help---
+	  The final ABI for userspace access to flow steering verbs
+	  has not been defined.  To use the current ABI, *WHICH WILL
+	  CHANGE IN THE FUTURE*, say Y here.
+
+	  If unsure, say N.
+
 config INFINIBAND_USER_MEM
 	bool
 	depends on INFINIBAND_USER_ACCESS != n
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index d040b87..d8f9c6c 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -217,7 +217,9 @@
 IB_UVERBS_DECLARE_CMD(create_xsrq);
 IB_UVERBS_DECLARE_CMD(open_xrcd);
 IB_UVERBS_DECLARE_CMD(close_xrcd);
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
 IB_UVERBS_DECLARE_CMD(create_flow);
 IB_UVERBS_DECLARE_CMD(destroy_flow);
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
 
 #endif /* UVERBS_H */
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index f2b81b9..2f0f01b 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -54,7 +54,9 @@
 static struct uverbs_lock_class ah_lock_class	= { .name = "AH-uobj" };
 static struct uverbs_lock_class srq_lock_class	= { .name = "SRQ-uobj" };
 static struct uverbs_lock_class xrcd_lock_class = { .name = "XRCD-uobj" };
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
 static struct uverbs_lock_class rule_lock_class = { .name = "RULE-uobj" };
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
 
 #define INIT_UDATA(udata, ibuf, obuf, ilen, olen)			\
 	do {								\
@@ -2599,6 +2601,7 @@
 	return ret ? ret : in_len;
 }
 
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
 static int kern_spec_to_ib_spec(struct ib_kern_spec *kern_spec,
 				union ib_flow_spec *ib_spec)
 {
@@ -2824,6 +2827,7 @@
 
 	return ret ? ret : in_len;
 }
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
 
 static int __uverbs_create_xsrq(struct ib_uverbs_file *file,
 				struct ib_uverbs_create_xsrq *cmd,
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 75ad86c..2df31f6 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -115,8 +115,10 @@
 	[IB_USER_VERBS_CMD_CLOSE_XRCD]		= ib_uverbs_close_xrcd,
 	[IB_USER_VERBS_CMD_CREATE_XSRQ]		= ib_uverbs_create_xsrq,
 	[IB_USER_VERBS_CMD_OPEN_QP]		= ib_uverbs_open_qp,
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
 	[IB_USER_VERBS_CMD_CREATE_FLOW]		= ib_uverbs_create_flow,
 	[IB_USER_VERBS_CMD_DESTROY_FLOW]	= ib_uverbs_destroy_flow
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
 };
 
 static void ib_uverbs_add_one(struct ib_device *device);
@@ -605,6 +607,7 @@
 	if (!(file->device->ib_dev->uverbs_cmd_mask & (1ull << hdr.command)))
 		return -ENOSYS;
 
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
 	if (hdr.command >= IB_USER_VERBS_CMD_THRESHOLD) {
 		struct ib_uverbs_cmd_hdr_ex hdr_ex;
 
@@ -621,6 +624,7 @@
 						     (hdr_ex.out_words +
 						      hdr_ex.provider_out_words) * 4);
 	} else {
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
 		if (hdr.in_words * 4 != count)
 			return -EINVAL;
 
@@ -628,7 +632,9 @@
 						     buf + sizeof(hdr),
 						     hdr.in_words * 4,
 						     hdr.out_words * 4);
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
 	}
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
 }
 
 static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma)
diff --git a/drivers/infiniband/hw/amso1100/c2_ae.c b/drivers/infiniband/hw/amso1100/c2_ae.c
index d5d1929..cedda25 100644
--- a/drivers/infiniband/hw/amso1100/c2_ae.c
+++ b/drivers/infiniband/hw/amso1100/c2_ae.c
@@ -141,7 +141,7 @@
 		return "C2_QP_STATE_ERROR";
 	default:
 		return "<invalid QP state>";
-	};
+	}
 }
 
 void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index d6c5a73..f061264 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -1691,9 +1691,11 @@
 		ibdev->ib_dev.create_flow	= mlx4_ib_create_flow;
 		ibdev->ib_dev.destroy_flow	= mlx4_ib_destroy_flow;
 
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
 		ibdev->ib_dev.uverbs_cmd_mask	|=
 			(1ull << IB_USER_VERBS_CMD_CREATE_FLOW) |
 			(1ull << IB_USER_VERBS_CMD_DESTROY_FLOW);
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
 	}
 
 	mlx4_ib_alloc_eqs(dev, ibdev);
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 3f831de..b1a6cb3 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -164,6 +164,7 @@
 static int alloc_comp_eqs(struct mlx5_ib_dev *dev)
 {
 	struct mlx5_eq_table *table = &dev->mdev.priv.eq_table;
+	char name[MLX5_MAX_EQ_NAME];
 	struct mlx5_eq *eq, *n;
 	int ncomp_vec;
 	int nent;
@@ -180,11 +181,10 @@
 			goto clean;
 		}
 
-		snprintf(eq->name, MLX5_MAX_EQ_NAME, "mlx5_comp%d", i);
+		snprintf(name, MLX5_MAX_EQ_NAME, "mlx5_comp%d", i);
 		err = mlx5_create_map_eq(&dev->mdev, eq,
 					 i + MLX5_EQ_VEC_COMP_BASE, nent, 0,
-					 eq->name,
-					 &dev->mdev.priv.uuari.uars[0]);
+					 name, &dev->mdev.priv.uuari.uars[0]);
 		if (err) {
 			kfree(eq);
 			goto clean;
@@ -301,9 +301,8 @@
 	props->max_srq_sge	   = max_rq_sg - 1;
 	props->max_fast_reg_page_list_len = (unsigned int)-1;
 	props->local_ca_ack_delay  = dev->mdev.caps.local_ca_ack_delay;
-	props->atomic_cap	   = dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_ATOMIC ?
-		IB_ATOMIC_HCA : IB_ATOMIC_NONE;
-	props->masked_atomic_cap   = IB_ATOMIC_HCA;
+	props->atomic_cap	   = IB_ATOMIC_NONE;
+	props->masked_atomic_cap   = IB_ATOMIC_NONE;
 	props->max_pkeys	   = be16_to_cpup((__be16 *)(out_mad->data + 28));
 	props->max_mcast_grp	   = 1 << dev->mdev.caps.log_max_mcg;
 	props->max_mcast_qp_attach = dev->mdev.caps.max_qp_mcg;
@@ -1006,6 +1005,11 @@
 	ibev.device	      = &ibdev->ib_dev;
 	ibev.element.port_num = port;
 
+	if (port < 1 || port > ibdev->num_ports) {
+		mlx5_ib_warn(ibdev, "warning: event on port %d\n", port);
+		return;
+	}
+
 	if (ibdev->ib_active)
 		ib_dispatch_event(&ibev);
 }
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c
index bd41df9..3453580 100644
--- a/drivers/infiniband/hw/mlx5/mr.c
+++ b/drivers/infiniband/hw/mlx5/mr.c
@@ -42,6 +42,10 @@
 	DEF_CACHE_SIZE	= 10,
 };
 
+enum {
+	MLX5_UMR_ALIGN	= 2048
+};
+
 static __be64 *mr_align(__be64 *ptr, int align)
 {
 	unsigned long mask = align - 1;
@@ -61,13 +65,11 @@
 
 static int add_keys(struct mlx5_ib_dev *dev, int c, int num)
 {
-	struct device *ddev = dev->ib_dev.dma_device;
 	struct mlx5_mr_cache *cache = &dev->cache;
 	struct mlx5_cache_ent *ent = &cache->ent[c];
 	struct mlx5_create_mkey_mbox_in *in;
 	struct mlx5_ib_mr *mr;
 	int npages = 1 << ent->order;
-	int size = sizeof(u64) * npages;
 	int err = 0;
 	int i;
 
@@ -83,21 +85,6 @@
 		}
 		mr->order = ent->order;
 		mr->umred = 1;
-		mr->pas = kmalloc(size + 0x3f, GFP_KERNEL);
-		if (!mr->pas) {
-			kfree(mr);
-			err = -ENOMEM;
-			goto out;
-		}
-		mr->dma = dma_map_single(ddev, mr_align(mr->pas, 0x40), size,
-					 DMA_TO_DEVICE);
-		if (dma_mapping_error(ddev, mr->dma)) {
-			kfree(mr->pas);
-			kfree(mr);
-			err = -ENOMEM;
-			goto out;
-		}
-
 		in->seg.status = 1 << 6;
 		in->seg.xlt_oct_size = cpu_to_be32((npages + 1) / 2);
 		in->seg.qpn_mkey7_0 = cpu_to_be32(0xffffff << 8);
@@ -108,8 +95,6 @@
 					    sizeof(*in));
 		if (err) {
 			mlx5_ib_warn(dev, "create mkey failed %d\n", err);
-			dma_unmap_single(ddev, mr->dma, size, DMA_TO_DEVICE);
-			kfree(mr->pas);
 			kfree(mr);
 			goto out;
 		}
@@ -129,11 +114,9 @@
 
 static void remove_keys(struct mlx5_ib_dev *dev, int c, int num)
 {
-	struct device *ddev = dev->ib_dev.dma_device;
 	struct mlx5_mr_cache *cache = &dev->cache;
 	struct mlx5_cache_ent *ent = &cache->ent[c];
 	struct mlx5_ib_mr *mr;
-	int size;
 	int err;
 	int i;
 
@@ -149,14 +132,10 @@
 		ent->size--;
 		spin_unlock(&ent->lock);
 		err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr);
-		if (err) {
+		if (err)
 			mlx5_ib_warn(dev, "failed destroy mkey\n");
-		} else {
-			size = ALIGN(sizeof(u64) * (1 << mr->order), 0x40);
-			dma_unmap_single(ddev, mr->dma, size, DMA_TO_DEVICE);
-			kfree(mr->pas);
+		else
 			kfree(mr);
-		}
 	}
 }
 
@@ -408,13 +387,12 @@
 
 static void clean_keys(struct mlx5_ib_dev *dev, int c)
 {
-	struct device *ddev = dev->ib_dev.dma_device;
 	struct mlx5_mr_cache *cache = &dev->cache;
 	struct mlx5_cache_ent *ent = &cache->ent[c];
 	struct mlx5_ib_mr *mr;
-	int size;
 	int err;
 
+	cancel_delayed_work(&ent->dwork);
 	while (1) {
 		spin_lock(&ent->lock);
 		if (list_empty(&ent->head)) {
@@ -427,14 +405,10 @@
 		ent->size--;
 		spin_unlock(&ent->lock);
 		err = mlx5_core_destroy_mkey(&dev->mdev, &mr->mmr);
-		if (err) {
+		if (err)
 			mlx5_ib_warn(dev, "failed destroy mkey\n");
-		} else {
-			size = ALIGN(sizeof(u64) * (1 << mr->order), 0x40);
-			dma_unmap_single(ddev, mr->dma, size, DMA_TO_DEVICE);
-			kfree(mr->pas);
+		else
 			kfree(mr);
-		}
 	}
 }
 
@@ -540,13 +514,15 @@
 	int i;
 
 	dev->cache.stopped = 1;
-	destroy_workqueue(dev->cache.wq);
+	flush_workqueue(dev->cache.wq);
 
 	mlx5_mr_cache_debugfs_cleanup(dev);
 
 	for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++)
 		clean_keys(dev, i);
 
+	destroy_workqueue(dev->cache.wq);
+
 	return 0;
 }
 
@@ -675,10 +651,12 @@
 				  int page_shift, int order, int access_flags)
 {
 	struct mlx5_ib_dev *dev = to_mdev(pd->device);
+	struct device *ddev = dev->ib_dev.dma_device;
 	struct umr_common *umrc = &dev->umrc;
 	struct ib_send_wr wr, *bad;
 	struct mlx5_ib_mr *mr;
 	struct ib_sge sg;
+	int size = sizeof(u64) * npages;
 	int err;
 	int i;
 
@@ -697,7 +675,22 @@
 	if (!mr)
 		return ERR_PTR(-EAGAIN);
 
-	mlx5_ib_populate_pas(dev, umem, page_shift, mr_align(mr->pas, 0x40), 1);
+	mr->pas = kmalloc(size + MLX5_UMR_ALIGN - 1, GFP_KERNEL);
+	if (!mr->pas) {
+		err = -ENOMEM;
+		goto error;
+	}
+
+	mlx5_ib_populate_pas(dev, umem, page_shift,
+			     mr_align(mr->pas, MLX5_UMR_ALIGN), 1);
+
+	mr->dma = dma_map_single(ddev, mr_align(mr->pas, MLX5_UMR_ALIGN), size,
+				 DMA_TO_DEVICE);
+	if (dma_mapping_error(ddev, mr->dma)) {
+		kfree(mr->pas);
+		err = -ENOMEM;
+		goto error;
+	}
 
 	memset(&wr, 0, sizeof(wr));
 	wr.wr_id = (u64)(unsigned long)mr;
@@ -718,6 +711,9 @@
 	wait_for_completion(&mr->done);
 	up(&umrc->sem);
 
+	dma_unmap_single(ddev, mr->dma, size, DMA_TO_DEVICE);
+	kfree(mr->pas);
+
 	if (mr->status != IB_WC_SUCCESS) {
 		mlx5_ib_warn(dev, "reg umr failed\n");
 		err = -EFAULT;
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index 045f8cdb..5659ea8 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -203,7 +203,7 @@
 
 	switch (qp_type) {
 	case IB_QPT_XRC_INI:
-		size = sizeof(struct mlx5_wqe_xrc_seg);
+		size += sizeof(struct mlx5_wqe_xrc_seg);
 		/* fall through */
 	case IB_QPT_RC:
 		size += sizeof(struct mlx5_wqe_ctrl_seg) +
@@ -211,20 +211,23 @@
 			sizeof(struct mlx5_wqe_raddr_seg);
 		break;
 
+	case IB_QPT_XRC_TGT:
+		return 0;
+
 	case IB_QPT_UC:
-		size = sizeof(struct mlx5_wqe_ctrl_seg) +
+		size += sizeof(struct mlx5_wqe_ctrl_seg) +
 			sizeof(struct mlx5_wqe_raddr_seg);
 		break;
 
 	case IB_QPT_UD:
 	case IB_QPT_SMI:
 	case IB_QPT_GSI:
-		size = sizeof(struct mlx5_wqe_ctrl_seg) +
+		size += sizeof(struct mlx5_wqe_ctrl_seg) +
 			sizeof(struct mlx5_wqe_datagram_seg);
 		break;
 
 	case MLX5_IB_QPT_REG_UMR:
-		size = sizeof(struct mlx5_wqe_ctrl_seg) +
+		size += sizeof(struct mlx5_wqe_ctrl_seg) +
 			sizeof(struct mlx5_wqe_umr_ctrl_seg) +
 			sizeof(struct mlx5_mkey_seg);
 		break;
@@ -270,7 +273,8 @@
 		return wqe_size;
 
 	if (wqe_size > dev->mdev.caps.max_sq_desc_sz) {
-		mlx5_ib_dbg(dev, "\n");
+		mlx5_ib_dbg(dev, "wqe_size(%d) > max_sq_desc_sz(%d)\n",
+			    wqe_size, dev->mdev.caps.max_sq_desc_sz);
 		return -EINVAL;
 	}
 
@@ -280,9 +284,15 @@
 
 	wq_size = roundup_pow_of_two(attr->cap.max_send_wr * wqe_size);
 	qp->sq.wqe_cnt = wq_size / MLX5_SEND_WQE_BB;
+	if (qp->sq.wqe_cnt > dev->mdev.caps.max_wqes) {
+		mlx5_ib_dbg(dev, "wqe count(%d) exceeds limits(%d)\n",
+			    qp->sq.wqe_cnt, dev->mdev.caps.max_wqes);
+		return -ENOMEM;
+	}
 	qp->sq.wqe_shift = ilog2(MLX5_SEND_WQE_BB);
 	qp->sq.max_gs = attr->cap.max_send_sge;
-	qp->sq.max_post = 1 << ilog2(wq_size / wqe_size);
+	qp->sq.max_post = wq_size / wqe_size;
+	attr->cap.max_send_wr = qp->sq.max_post;
 
 	return wq_size;
 }
@@ -1280,6 +1290,11 @@
 					  MLX5_QP_OPTPAR_Q_KEY,
 			[MLX5_QP_ST_MLX] = MLX5_QP_OPTPAR_PKEY_INDEX	|
 					   MLX5_QP_OPTPAR_Q_KEY,
+			[MLX5_QP_ST_XRC] = MLX5_QP_OPTPAR_ALT_ADDR_PATH |
+					  MLX5_QP_OPTPAR_RRE            |
+					  MLX5_QP_OPTPAR_RAE            |
+					  MLX5_QP_OPTPAR_RWE            |
+					  MLX5_QP_OPTPAR_PKEY_INDEX,
 		},
 	},
 	[MLX5_QP_STATE_RTR] = {
@@ -1314,6 +1329,11 @@
 		[MLX5_QP_STATE_RTS] = {
 			[MLX5_QP_ST_UD]	 = MLX5_QP_OPTPAR_Q_KEY,
 			[MLX5_QP_ST_MLX] = MLX5_QP_OPTPAR_Q_KEY,
+			[MLX5_QP_ST_UC]	 = MLX5_QP_OPTPAR_RWE,
+			[MLX5_QP_ST_RC]	 = MLX5_QP_OPTPAR_RNR_TIMEOUT	|
+					   MLX5_QP_OPTPAR_RWE		|
+					   MLX5_QP_OPTPAR_RAE		|
+					   MLX5_QP_OPTPAR_RRE,
 		},
 	},
 };
@@ -1651,29 +1671,6 @@
 	rseg->reserved = 0;
 }
 
-static void set_atomic_seg(struct mlx5_wqe_atomic_seg *aseg, struct ib_send_wr *wr)
-{
-	if (wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP) {
-		aseg->swap_add = cpu_to_be64(wr->wr.atomic.swap);
-		aseg->compare  = cpu_to_be64(wr->wr.atomic.compare_add);
-	} else if (wr->opcode == IB_WR_MASKED_ATOMIC_FETCH_AND_ADD) {
-		aseg->swap_add = cpu_to_be64(wr->wr.atomic.compare_add);
-		aseg->compare  = cpu_to_be64(wr->wr.atomic.compare_add_mask);
-	} else {
-		aseg->swap_add = cpu_to_be64(wr->wr.atomic.compare_add);
-		aseg->compare  = 0;
-	}
-}
-
-static void set_masked_atomic_seg(struct mlx5_wqe_masked_atomic_seg *aseg,
-				  struct ib_send_wr *wr)
-{
-	aseg->swap_add		= cpu_to_be64(wr->wr.atomic.swap);
-	aseg->swap_add_mask	= cpu_to_be64(wr->wr.atomic.swap_mask);
-	aseg->compare		= cpu_to_be64(wr->wr.atomic.compare_add);
-	aseg->compare_mask	= cpu_to_be64(wr->wr.atomic.compare_add_mask);
-}
-
 static void set_datagram_seg(struct mlx5_wqe_datagram_seg *dseg,
 			     struct ib_send_wr *wr)
 {
@@ -2063,28 +2060,11 @@
 
 			case IB_WR_ATOMIC_CMP_AND_SWP:
 			case IB_WR_ATOMIC_FETCH_AND_ADD:
-				set_raddr_seg(seg, wr->wr.atomic.remote_addr,
-					      wr->wr.atomic.rkey);
-				seg  += sizeof(struct mlx5_wqe_raddr_seg);
-
-				set_atomic_seg(seg, wr);
-				seg  += sizeof(struct mlx5_wqe_atomic_seg);
-
-				size += (sizeof(struct mlx5_wqe_raddr_seg) +
-					 sizeof(struct mlx5_wqe_atomic_seg)) / 16;
-				break;
-
 			case IB_WR_MASKED_ATOMIC_CMP_AND_SWP:
-				set_raddr_seg(seg, wr->wr.atomic.remote_addr,
-					      wr->wr.atomic.rkey);
-				seg  += sizeof(struct mlx5_wqe_raddr_seg);
-
-				set_masked_atomic_seg(seg, wr);
-				seg  += sizeof(struct mlx5_wqe_masked_atomic_seg);
-
-				size += (sizeof(struct mlx5_wqe_raddr_seg) +
-					 sizeof(struct mlx5_wqe_masked_atomic_seg)) / 16;
-				break;
+				mlx5_ib_warn(dev, "Atomic operations are not supported yet\n");
+				err = -ENOSYS;
+				*bad_wr = wr;
+				goto out;
 
 			case IB_WR_LOCAL_INV:
 				next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
diff --git a/drivers/infiniband/hw/mlx5/srq.c b/drivers/infiniband/hw/mlx5/srq.c
index 84d297a..0aa478b 100644
--- a/drivers/infiniband/hw/mlx5/srq.c
+++ b/drivers/infiniband/hw/mlx5/srq.c
@@ -295,7 +295,7 @@
 	mlx5_vfree(in);
 	if (err) {
 		mlx5_ib_dbg(dev, "create SRQ failed, err %d\n", err);
-		goto err_srq;
+		goto err_usr_kern_srq;
 	}
 
 	mlx5_ib_dbg(dev, "create SRQ with srqn 0x%x\n", srq->msrq.srqn);
@@ -316,6 +316,8 @@
 
 err_core:
 	mlx5_core_destroy_srq(&dev->mdev, &srq->msrq);
+
+err_usr_kern_srq:
 	if (pd->uobject)
 		destroy_srq_user(pd, srq);
 	else
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index 7c9d35f..6902017 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -357,7 +357,7 @@
 			mthca_warn(dev, "Unhandled event %02x(%02x) on EQ %d\n",
 				   eqe->type, eqe->subtype, eq->eqn);
 			break;
-		};
+		}
 
 		set_eqe_hw(eqe);
 		++eq->cons_index;
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
index 4ed8235..50219ab 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
@@ -150,7 +150,7 @@
 		return IB_QPS_SQE;
 	case OCRDMA_QPS_ERR:
 		return IB_QPS_ERR;
-	};
+	}
 	return IB_QPS_ERR;
 }
 
@@ -171,7 +171,7 @@
 		return OCRDMA_QPS_SQE;
 	case IB_QPS_ERR:
 		return OCRDMA_QPS_ERR;
-	};
+	}
 	return OCRDMA_QPS_ERR;
 }
 
@@ -1982,7 +1982,7 @@
 		break;
 	default:
 		return -EINVAL;
-	};
+	}
 
 	cmd = ocrdma_init_emb_mqe(OCRDMA_CMD_CREATE_QP, sizeof(*cmd));
 	if (!cmd)
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
index 56e0049..0ce7674 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
@@ -531,7 +531,7 @@
 	case BE_DEV_DOWN:
 		ocrdma_close(dev);
 		break;
-	};
+	}
 }
 
 static struct ocrdma_driver ocrdma_drv = {
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
index 6e982bb..69f1d12 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
@@ -141,7 +141,7 @@
 		/* Unsupported */
 		*ib_speed = IB_SPEED_SDR;
 		*ib_width = IB_WIDTH_1X;
-	};
+	}
 }
 
 
@@ -2331,7 +2331,7 @@
 	default:
 		ibwc_status = IB_WC_GENERAL_ERR;
 		break;
-	};
+	}
 	return ibwc_status;
 }
 
@@ -2370,7 +2370,7 @@
 		pr_err("%s() invalid opcode received = 0x%x\n",
 		       __func__, hdr->cw & OCRDMA_WQE_OPCODE_MASK);
 		break;
-	};
+	}
 }
 
 static void ocrdma_set_cqe_status_flushed(struct ocrdma_qp *qp,
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index 3591855..6df2350 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -594,7 +594,7 @@
 
 	pr_debug("Entering isert_connect_release(): >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
 
-	if (device->use_frwr)
+	if (device && device->use_frwr)
 		isert_conn_free_frwr_pool(isert_conn);
 
 	if (isert_conn->conn_qp) {
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 922a7fe..24c41ba 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -422,14 +422,15 @@
  * Gameport port operations
  */
 
-static ssize_t gameport_show_description(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t gameport_description_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct gameport *gameport = to_gameport_port(dev);
 
 	return sprintf(buf, "%s\n", gameport->name);
 }
+static DEVICE_ATTR(description, S_IRUGO, gameport_description_show, NULL);
 
-static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t drvctl_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct gameport *gameport = to_gameport_port(dev);
 	struct device_driver *drv;
@@ -457,12 +458,14 @@
 
 	return error ? error : count;
 }
+static DEVICE_ATTR_WO(drvctl);
 
-static struct device_attribute gameport_device_attrs[] = {
-	__ATTR(description, S_IRUGO, gameport_show_description, NULL),
-	__ATTR(drvctl, S_IWUSR, NULL, gameport_rebind_driver),
-	__ATTR_NULL
+static struct attribute *gameport_device_attrs[] = {
+	&dev_attr_description.attr,
+	&dev_attr_drvctl.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(gameport_device);
 
 static void gameport_release_port(struct device *dev)
 {
@@ -750,7 +753,7 @@
 
 static struct bus_type gameport_bus = {
 	.name		= "gameport",
-	.dev_attrs	= gameport_device_attrs,
+	.dev_groups	= gameport_device_groups,
 	.drv_groups	= gameport_driver_groups,
 	.match		= gameport_bus_match,
 	.probe		= gameport_driver_probe,
diff --git a/drivers/input/input.c b/drivers/input/input.c
index c044699..e75d015 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -1734,6 +1734,7 @@
  */
 struct input_dev *input_allocate_device(void)
 {
+	static atomic_t input_no = ATOMIC_INIT(0);
 	struct input_dev *dev;
 
 	dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
@@ -1743,9 +1744,13 @@
 		device_initialize(&dev->dev);
 		mutex_init(&dev->mutex);
 		spin_lock_init(&dev->event_lock);
+		init_timer(&dev->timer);
 		INIT_LIST_HEAD(&dev->h_list);
 		INIT_LIST_HEAD(&dev->node);
 
+		dev_set_name(&dev->dev, "input%ld",
+			     (unsigned long) atomic_inc_return(&input_no) - 1);
+
 		__module_get(THIS_MODULE);
 	}
 
@@ -2019,7 +2024,6 @@
  */
 int input_register_device(struct input_dev *dev)
 {
-	static atomic_t input_no = ATOMIC_INIT(0);
 	struct input_devres *devres = NULL;
 	struct input_handler *handler;
 	unsigned int packet_size;
@@ -2059,7 +2063,6 @@
 	 * If delay and period are pre-set by the driver, then autorepeating
 	 * is handled by the driver itself and we don't do it in input.c.
 	 */
-	init_timer(&dev->timer);
 	if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
 		dev->timer.data = (long) dev;
 		dev->timer.function = input_repeat_key;
@@ -2073,9 +2076,6 @@
 	if (!dev->setkeycode)
 		dev->setkeycode = input_default_setkeycode;
 
-	dev_set_name(&dev->dev, "input%ld",
-		     (unsigned long) atomic_inc_return(&input_no) - 1);
-
 	error = device_add(&dev->dev);
 	if (error)
 		goto err_free_vals;
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index 134c3b4..a2e758d 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -786,10 +786,17 @@
 	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
 	input_set_capability(input_dev, EV_MSC, MSC_SCAN);
 
-	if (pdata)
+	if (pdata) {
 		error = pxa27x_keypad_build_keycode(keypad);
-	else
+	} else {
 		error = pxa27x_keypad_build_keycode_from_dt(keypad);
+		/*
+		 * Data that we get from DT resides in dynamically
+		 * allocated memory so we need to update our pdata
+		 * pointer.
+		 */
+		pdata = keypad->pdata;
+	}
 	if (error) {
 		dev_err(&pdev->dev, "failed to build keycode\n");
 		goto failed_put_clk;
diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c
index 082684e..9365535 100644
--- a/drivers/input/misc/cm109.c
+++ b/drivers/input/misc/cm109.c
@@ -351,7 +351,9 @@
 	if (status) {
 		if (status == -ESHUTDOWN)
 			return;
-		dev_err(&dev->intf->dev, "%s: urb status %d\n", __func__, status);
+		dev_err_ratelimited(&dev->intf->dev, "%s: urb status %d\n",
+				    __func__, status);
+		goto out;
 	}
 
 	/* Special keys */
@@ -418,8 +420,12 @@
 	     dev->ctl_data->byte[2],
 	     dev->ctl_data->byte[3]);
 
-	if (status)
-		dev_err(&dev->intf->dev, "%s: urb status %d\n", __func__, status);
+	if (status) {
+		if (status == -ESHUTDOWN)
+			return;
+		dev_err_ratelimited(&dev->intf->dev, "%s: urb status %d\n",
+				    __func__, status);
+	}
 
 	spin_lock(&dev->ctl_submit_lock);
 
@@ -427,7 +433,7 @@
 
 	if (likely(!dev->shutdown)) {
 
-		if (dev->buzzer_pending) {
+		if (dev->buzzer_pending || status) {
 			dev->buzzer_pending = 0;
 			dev->ctl_urb_pending = 1;
 			cm109_submit_buzz_toggle(dev);
diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c
index f34beb2..17ccba8 100644
--- a/drivers/input/misc/ixp4xx-beeper.c
+++ b/drivers/input/misc/ixp4xx-beeper.c
@@ -20,6 +20,7 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
+#include <linux/gpio.h>
 #include <mach/hardware.h>
 
 MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
@@ -35,15 +36,12 @@
 
 	spin_lock_irqsave(&beep_lock, flags);
 
-	 if (count) {
-		gpio_line_config(pin, IXP4XX_GPIO_OUT);
-		gpio_line_set(pin, IXP4XX_GPIO_LOW);
-
+	if (count) {
+		gpio_direction_output(pin, 0);
 		*IXP4XX_OSRT2 = (count & ~IXP4XX_OST_RELOAD_MASK) | IXP4XX_OST_ENABLE;
 	} else {
-		gpio_line_config(pin, IXP4XX_GPIO_IN);
-		gpio_line_set(pin, IXP4XX_GPIO_HIGH);
-
+		gpio_direction_output(pin, 1);
+		gpio_direction_input(pin);
 		*IXP4XX_OSRT2 = 0;
 	}
 
@@ -78,11 +76,13 @@
 
 static irqreturn_t ixp4xx_spkr_interrupt(int irq, void *dev_id)
 {
+	unsigned int pin = (unsigned int) dev_id;
+
 	/* clear interrupt */
 	*IXP4XX_OSST = IXP4XX_OSST_TIMER_2_PEND;
 
 	/* flip the beeper output */
-	*IXP4XX_GPIO_GPOUTR ^= (1 << (unsigned int) dev_id);
+	gpio_set_value(pin, !gpio_get_value(pin));
 
 	return IRQ_HANDLED;
 }
@@ -110,11 +110,15 @@
 	input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
 	input_dev->event = ixp4xx_spkr_event;
 
+	err = gpio_request(dev->id, "ixp4-beeper");
+	if (err)
+		goto err_free_device;
+
 	err = request_irq(IRQ_IXP4XX_TIMER2, &ixp4xx_spkr_interrupt,
 			  IRQF_NO_SUSPEND, "ixp4xx-beeper",
 			  (void *) dev->id);
 	if (err)
-		goto err_free_device;
+		goto err_free_gpio;
 
 	err = input_register_device(input_dev);
 	if (err)
@@ -126,6 +130,8 @@
 
  err_free_irq:
 	free_irq(IRQ_IXP4XX_TIMER2, (void *)dev->id);
+ err_free_gpio:
+	gpio_free(dev->id);
  err_free_device:
 	input_free_device(input_dev);
 
@@ -144,6 +150,7 @@
 	ixp4xx_spkr_control(pin, 0);
 
 	free_irq(IRQ_IXP4XX_TIMER2, (void *)dev->id);
+	gpio_free(dev->id);
 
 	return 0;
 }
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 7c5d72a..8365847 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -103,6 +103,7 @@
 	/* Dell Latitude E5500, E6400, E6500, Precision M4400 */
 	{ { 0x62, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf,
 		ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED },
+	{ { 0x73, 0x00, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_DUALPOINT },		/* Dell XT2 */
 	{ { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS },		/* Dell Vostro 1400 */
 	{ { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff,
 		ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED },				/* Toshiba Tecra A11-11L */
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index 33b3e88..1de1e5f 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -21,7 +21,7 @@
 config SERIO_I8042
 	tristate "i8042 PC Keyboard controller" if EXPERT || !X86
 	default y
-	depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \
+	depends on !PARISC && (!ARM || FOOTBRIDGE_HOST) && \
 		   (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN && !S390 && \
 		   !ARC
 	help
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 78e4de4..52c9ebf 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -223,21 +223,26 @@
 {
 	unsigned long flags;
 	unsigned char data, str;
-	int i = 0;
+	int count = 0;
+	int retval = 0;
 
 	spin_lock_irqsave(&i8042_lock, flags);
 
-	while (((str = i8042_read_status()) & I8042_STR_OBF) && (i < I8042_BUFFER_SIZE)) {
-		udelay(50);
-		data = i8042_read_data();
-		i++;
-		dbg("%02x <- i8042 (flush, %s)\n",
-		    data, str & I8042_STR_AUXDATA ? "aux" : "kbd");
+	while ((str = i8042_read_status()) & I8042_STR_OBF) {
+		if (count++ < I8042_BUFFER_SIZE) {
+			udelay(50);
+			data = i8042_read_data();
+			dbg("%02x <- i8042 (flush, %s)\n",
+			    data, str & I8042_STR_AUXDATA ? "aux" : "kbd");
+		} else {
+			retval = -EIO;
+			break;
+		}
 	}
 
 	spin_unlock_irqrestore(&i8042_lock, flags);
 
-	return i;
+	return retval;
 }
 
 /*
@@ -849,7 +854,7 @@
 
 static int i8042_controller_check(void)
 {
-	if (i8042_flush() == I8042_BUFFER_SIZE) {
+	if (i8042_flush()) {
 		pr_err("No controller found\n");
 		return -ENODEV;
 	}
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 2b56855..98707fb 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -365,7 +365,7 @@
 	return sprintf(buf, "%s\n", serio->name);
 }
 
-static ssize_t serio_show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct serio *serio = to_serio_port(dev);
 
@@ -373,54 +373,31 @@
 			serio->id.type, serio->id.proto, serio->id.id, serio->id.extra);
 }
 
-static ssize_t serio_show_id_type(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t type_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct serio *serio = to_serio_port(dev);
 	return sprintf(buf, "%02x\n", serio->id.type);
 }
 
-static ssize_t serio_show_id_proto(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t proto_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct serio *serio = to_serio_port(dev);
 	return sprintf(buf, "%02x\n", serio->id.proto);
 }
 
-static ssize_t serio_show_id_id(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct serio *serio = to_serio_port(dev);
 	return sprintf(buf, "%02x\n", serio->id.id);
 }
 
-static ssize_t serio_show_id_extra(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t extra_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct serio *serio = to_serio_port(dev);
 	return sprintf(buf, "%02x\n", serio->id.extra);
 }
 
-static DEVICE_ATTR(type, S_IRUGO, serio_show_id_type, NULL);
-static DEVICE_ATTR(proto, S_IRUGO, serio_show_id_proto, NULL);
-static DEVICE_ATTR(id, S_IRUGO, serio_show_id_id, NULL);
-static DEVICE_ATTR(extra, S_IRUGO, serio_show_id_extra, NULL);
-
-static struct attribute *serio_device_id_attrs[] = {
-	&dev_attr_type.attr,
-	&dev_attr_proto.attr,
-	&dev_attr_id.attr,
-	&dev_attr_extra.attr,
-	NULL
-};
-
-static struct attribute_group serio_id_attr_group = {
-	.name	= "id",
-	.attrs	= serio_device_id_attrs,
-};
-
-static const struct attribute_group *serio_device_attr_groups[] = {
-	&serio_id_attr_group,
-	NULL
-};
-
-static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t drvctl_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct serio *serio = to_serio_port(dev);
 	struct device_driver *drv;
@@ -474,14 +451,36 @@
 	return retval;
 }
 
-static struct device_attribute serio_device_attrs[] = {
-	__ATTR(description, S_IRUGO, serio_show_description, NULL),
-	__ATTR(modalias, S_IRUGO, serio_show_modalias, NULL),
-	__ATTR(drvctl, S_IWUSR, NULL, serio_rebind_driver),
-	__ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode),
-	__ATTR_NULL
+static DEVICE_ATTR_RO(type);
+static DEVICE_ATTR_RO(proto);
+static DEVICE_ATTR_RO(id);
+static DEVICE_ATTR_RO(extra);
+static DEVICE_ATTR_RO(modalias);
+static DEVICE_ATTR_WO(drvctl);
+static DEVICE_ATTR(description, S_IRUGO, serio_show_description, NULL);
+static DEVICE_ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode);
+
+static struct attribute *serio_device_id_attrs[] = {
+	&dev_attr_type.attr,
+	&dev_attr_proto.attr,
+	&dev_attr_id.attr,
+	&dev_attr_extra.attr,
+	&dev_attr_modalias.attr,
+	&dev_attr_description.attr,
+	&dev_attr_drvctl.attr,
+	&dev_attr_bind_mode.attr,
+	NULL
 };
 
+static struct attribute_group serio_id_attr_group = {
+	.name	= "id",
+	.attrs	= serio_device_id_attrs,
+};
+
+static const struct attribute_group *serio_device_attr_groups[] = {
+	&serio_id_attr_group,
+	NULL
+};
 
 static void serio_release_port(struct device *dev)
 {
@@ -996,7 +995,6 @@
 
 static struct bus_type serio_bus = {
 	.name		= "serio",
-	.dev_attrs	= serio_device_attrs,
 	.drv_groups	= serio_driver_groups,
 	.match		= serio_bus_match,
 	.uevent		= serio_uevent,
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
index 4b7662a..dfbcd87 100644
--- a/drivers/input/serio/xilinx_ps2.c
+++ b/drivers/input/serio/xilinx_ps2.c
@@ -25,6 +25,7 @@
 #include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
 #define DRIVER_NAME		"xilinx_ps2"
@@ -235,12 +236,12 @@
  */
 static int xps2_of_probe(struct platform_device *ofdev)
 {
-	struct resource r_irq; /* Interrupt resources */
 	struct resource r_mem; /* IO mem resources */
 	struct xps2data *drvdata;
 	struct serio *serio;
 	struct device *dev = &ofdev->dev;
 	resource_size_t remap_size, phys_addr;
+	unsigned int irq;
 	int error;
 
 	dev_info(dev, "Device Tree Probing \'%s\'\n",
@@ -254,7 +255,8 @@
 	}
 
 	/* Get IRQ for the device */
-	if (!of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq)) {
+	irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
+	if (!irq) {
 		dev_err(dev, "no IRQ found\n");
 		return -ENODEV;
 	}
@@ -267,7 +269,7 @@
 	}
 
 	spin_lock_init(&drvdata->lock);
-	drvdata->irq = r_irq.start;
+	drvdata->irq = irq;
 	drvdata->serio = serio;
 	drvdata->dev = dev;
 
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 79b69ea..e53416a 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -1031,6 +1031,7 @@
 }
 
 static enum power_supply_property wacom_battery_props[] = {
+	POWER_SUPPLY_PROP_SCOPE,
 	POWER_SUPPLY_PROP_CAPACITY
 };
 
@@ -1042,6 +1043,9 @@
 	int ret = 0;
 
 	switch (psp) {
+		case POWER_SUPPLY_PROP_SCOPE:
+			val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+			break;
 		case POWER_SUPPLY_PROP_CAPACITY:
 			val->intval =
 				wacom->wacom_wac.battery_capacity * 100 / 31;
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index b2aa503..c59b797 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -2054,6 +2054,12 @@
 static const struct wacom_features wacom_features_0x10D =
 	{ "Wacom ISDv4 10D",      WACOM_PKGLEN_MTTPC,     26202, 16325,  255,
 	  0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x10E =
+	{ "Wacom ISDv4 10E",      WACOM_PKGLEN_MTTPC,     27760, 15694,  255,
+	  0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x10F =
+	{ "Wacom ISDv4 10F",      WACOM_PKGLEN_MTTPC,     27760, 15694,  255,
+	  0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x4001 =
 	{ "Wacom ISDv4 4001",      WACOM_PKGLEN_MTTPC,     26202, 16325,  255,
 	  0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -2248,6 +2254,8 @@
 	{ USB_DEVICE_WACOM(0x100) },
 	{ USB_DEVICE_WACOM(0x101) },
 	{ USB_DEVICE_WACOM(0x10D) },
+	{ USB_DEVICE_WACOM(0x10E) },
+	{ USB_DEVICE_WACOM(0x10F) },
 	{ USB_DEVICE_WACOM(0x300) },
 	{ USB_DEVICE_WACOM(0x301) },
 	{ USB_DEVICE_WACOM(0x304) },
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index e1c5300..24e625c 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -52,6 +52,7 @@
 	u32			config_inp[4];
 	u32			bit_xp, bit_xn, bit_yp, bit_yn;
 	u32			inp_xp, inp_xn, inp_yp, inp_yn;
+	u32			step_mask;
 };
 
 static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
@@ -196,7 +197,8 @@
 
 	/* The steps1 … end and bit 0 for TS_Charge */
 	stepenable = (1 << (end_step + 2)) - 1;
-	am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable);
+	ts_dev->step_mask = stepenable;
+	am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
 }
 
 static void titsc_read_coordinates(struct titsc *ts_dev,
@@ -260,6 +262,10 @@
 	unsigned int fsm;
 
 	status = titsc_readl(ts_dev, REG_IRQSTATUS);
+	/*
+	 * ADC and touchscreen share the IRQ line.
+	 * FIFO1 interrupts are used by ADC. Handle FIFO0 IRQs here only
+	 */
 	if (status & IRQENB_FIFO0THRES) {
 
 		titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2);
@@ -316,7 +322,7 @@
 
 	if (irqclr) {
 		titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
-		am335x_tsc_se_update(ts_dev->mfd_tscadc);
+		am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
 		return IRQ_HANDLED;
 	}
 	return IRQ_NONE;
@@ -389,7 +395,7 @@
 	}
 
 	err = request_irq(ts_dev->irq, titsc_irq,
-			  0, pdev->dev.driver->name, ts_dev);
+			  IRQF_SHARED, pdev->dev.driver->name, ts_dev);
 	if (err) {
 		dev_err(&pdev->dev, "failed to allocate irq.\n");
 		goto err_free_mem;
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index fe302e3..c880eba 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -52,7 +52,7 @@
 	select PCI_PRI
 	select PCI_PASID
 	select IOMMU_API
-	depends on X86_64 && PCI && ACPI && X86_IO_APIC
+	depends on X86_64 && PCI && ACPI
 	---help---
 	  With this option you can enable support for AMD IOMMU hardware in
 	  your system. An IOMMU is a hardware component which provides
diff --git a/drivers/ipack/ipack.c b/drivers/ipack/ipack.c
index 6e066c5..d0016ba 100644
--- a/drivers/ipack/ipack.c
+++ b/drivers/ipack/ipack.c
@@ -180,20 +180,28 @@
 
 ipack_device_attr(id_format, "0x%hhu\n");
 
-static struct device_attribute ipack_dev_attrs[] = {
-	__ATTR_RO(id),
-	__ATTR_RO(id_device),
-	__ATTR_RO(id_format),
-	__ATTR_RO(id_vendor),
-	__ATTR_RO(modalias),
+static DEVICE_ATTR_RO(id);
+static DEVICE_ATTR_RO(id_device);
+static DEVICE_ATTR_RO(id_format);
+static DEVICE_ATTR_RO(id_vendor);
+static DEVICE_ATTR_RO(modalias);
+
+static struct attribute *ipack_attrs[] = {
+	&dev_attr_id.attr,
+	&dev_attr_id_device.attr,
+	&dev_attr_id_format.attr,
+	&dev_attr_id_vendor.attr,
+	&dev_attr_modalias.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(ipack);
 
 static struct bus_type ipack_bus_type = {
 	.name      = "ipack",
 	.probe     = ipack_bus_probe,
 	.match     = ipack_bus_match,
 	.remove    = ipack_bus_remove,
-	.dev_attrs = ipack_dev_attrs,
+	.dev_groups = ipack_groups,
 	.uevent	   = ipack_uevent,
 };
 
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index bb328a3..433cc85 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -21,7 +21,10 @@
 #include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/of_pci.h>
 #include <linux/irqdomain.h>
+#include <linux/slab.h>
+#include <linux/msi.h>
 #include <asm/mach/arch.h>
 #include <asm/exception.h>
 #include <asm/smp_plat.h>
@@ -51,12 +54,22 @@
 #define IPI_DOORBELL_START                      (0)
 #define IPI_DOORBELL_END                        (8)
 #define IPI_DOORBELL_MASK                       0xFF
+#define PCI_MSI_DOORBELL_START                  (16)
+#define PCI_MSI_DOORBELL_NR                     (16)
+#define PCI_MSI_DOORBELL_END                    (32)
+#define PCI_MSI_DOORBELL_MASK                   0xFFFF0000
 
 static DEFINE_RAW_SPINLOCK(irq_controller_lock);
 
 static void __iomem *per_cpu_int_base;
 static void __iomem *main_int_base;
 static struct irq_domain *armada_370_xp_mpic_domain;
+#ifdef CONFIG_PCI_MSI
+static struct irq_domain *armada_370_xp_msi_domain;
+static DECLARE_BITMAP(msi_used, PCI_MSI_DOORBELL_NR);
+static DEFINE_MUTEX(msi_used_lock);
+static phys_addr_t msi_doorbell_addr;
+#endif
 
 /*
  * In SMP mode:
@@ -87,6 +100,144 @@
 				ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
 }
 
+#ifdef CONFIG_PCI_MSI
+
+static int armada_370_xp_alloc_msi(void)
+{
+	int hwirq;
+
+	mutex_lock(&msi_used_lock);
+	hwirq = find_first_zero_bit(&msi_used, PCI_MSI_DOORBELL_NR);
+	if (hwirq >= PCI_MSI_DOORBELL_NR)
+		hwirq = -ENOSPC;
+	else
+		set_bit(hwirq, msi_used);
+	mutex_unlock(&msi_used_lock);
+
+	return hwirq;
+}
+
+static void armada_370_xp_free_msi(int hwirq)
+{
+	mutex_lock(&msi_used_lock);
+	if (!test_bit(hwirq, msi_used))
+		pr_err("trying to free unused MSI#%d\n", hwirq);
+	else
+		clear_bit(hwirq, msi_used);
+	mutex_unlock(&msi_used_lock);
+}
+
+static int armada_370_xp_setup_msi_irq(struct msi_chip *chip,
+				       struct pci_dev *pdev,
+				       struct msi_desc *desc)
+{
+	struct msi_msg msg;
+	irq_hw_number_t hwirq;
+	int virq;
+
+	hwirq = armada_370_xp_alloc_msi();
+	if (hwirq < 0)
+		return hwirq;
+
+	virq = irq_create_mapping(armada_370_xp_msi_domain, hwirq);
+	if (!virq) {
+		armada_370_xp_free_msi(hwirq);
+		return -EINVAL;
+	}
+
+	irq_set_msi_desc(virq, desc);
+
+	msg.address_lo = msi_doorbell_addr;
+	msg.address_hi = 0;
+	msg.data = 0xf00 | (hwirq + 16);
+
+	write_msi_msg(virq, &msg);
+	return 0;
+}
+
+static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip,
+					   unsigned int irq)
+{
+	struct irq_data *d = irq_get_irq_data(irq);
+	irq_dispose_mapping(irq);
+	armada_370_xp_free_msi(d->hwirq);
+}
+
+static struct irq_chip armada_370_xp_msi_irq_chip = {
+	.name = "armada_370_xp_msi_irq",
+	.irq_enable = unmask_msi_irq,
+	.irq_disable = mask_msi_irq,
+	.irq_mask = mask_msi_irq,
+	.irq_unmask = unmask_msi_irq,
+};
+
+static int armada_370_xp_msi_map(struct irq_domain *domain, unsigned int virq,
+				 irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(virq, &armada_370_xp_msi_irq_chip,
+				 handle_simple_irq);
+	set_irq_flags(virq, IRQF_VALID);
+
+	return 0;
+}
+
+static const struct irq_domain_ops armada_370_xp_msi_irq_ops = {
+	.map = armada_370_xp_msi_map,
+};
+
+static int armada_370_xp_msi_init(struct device_node *node,
+				  phys_addr_t main_int_phys_base)
+{
+	struct msi_chip *msi_chip;
+	u32 reg;
+	int ret;
+
+	msi_doorbell_addr = main_int_phys_base +
+		ARMADA_370_XP_SW_TRIG_INT_OFFS;
+
+	msi_chip = kzalloc(sizeof(*msi_chip), GFP_KERNEL);
+	if (!msi_chip)
+		return -ENOMEM;
+
+	msi_chip->setup_irq = armada_370_xp_setup_msi_irq;
+	msi_chip->teardown_irq = armada_370_xp_teardown_msi_irq;
+	msi_chip->of_node = node;
+
+	armada_370_xp_msi_domain =
+		irq_domain_add_linear(NULL, PCI_MSI_DOORBELL_NR,
+				      &armada_370_xp_msi_irq_ops,
+				      NULL);
+	if (!armada_370_xp_msi_domain) {
+		kfree(msi_chip);
+		return -ENOMEM;
+	}
+
+	ret = of_pci_msi_chip_add(msi_chip);
+	if (ret < 0) {
+		irq_domain_remove(armada_370_xp_msi_domain);
+		kfree(msi_chip);
+		return ret;
+	}
+
+	reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS)
+		| PCI_MSI_DOORBELL_MASK;
+
+	writel(reg, per_cpu_int_base +
+	       ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
+
+	/* Unmask IPI interrupt */
+	writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
+
+	return 0;
+}
+#else
+static inline int armada_370_xp_msi_init(struct device_node *node,
+					 phys_addr_t main_int_phys_base)
+{
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_SMP
 static int armada_xp_set_affinity(struct irq_data *d,
 				  const struct cpumask *mask_val, bool force)
@@ -214,12 +365,39 @@
 		if (irqnr > 1022)
 			break;
 
-		if (irqnr > 0) {
+		if (irqnr > 1) {
 			irqnr =	irq_find_mapping(armada_370_xp_mpic_domain,
 					irqnr);
 			handle_IRQ(irqnr, regs);
 			continue;
 		}
+
+#ifdef CONFIG_PCI_MSI
+		/* MSI handling */
+		if (irqnr == 1) {
+			u32 msimask, msinr;
+
+			msimask = readl_relaxed(per_cpu_int_base +
+						ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
+				& PCI_MSI_DOORBELL_MASK;
+
+			writel(~PCI_MSI_DOORBELL_MASK, per_cpu_int_base +
+			       ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
+
+			for (msinr = PCI_MSI_DOORBELL_START;
+			     msinr < PCI_MSI_DOORBELL_END; msinr++) {
+				int irq;
+
+				if (!(msimask & BIT(msinr)))
+					continue;
+
+				irq = irq_find_mapping(armada_370_xp_msi_domain,
+						       msinr - 16);
+				handle_IRQ(irq, regs);
+			}
+		}
+#endif
+
 #ifdef CONFIG_SMP
 		/* IPI Handling */
 		if (irqnr == 0) {
@@ -248,12 +426,25 @@
 static int __init armada_370_xp_mpic_of_init(struct device_node *node,
 					     struct device_node *parent)
 {
+	struct resource main_int_res, per_cpu_int_res;
 	u32 control;
 
-	main_int_base = of_iomap(node, 0);
-	per_cpu_int_base = of_iomap(node, 1);
+	BUG_ON(of_address_to_resource(node, 0, &main_int_res));
+	BUG_ON(of_address_to_resource(node, 1, &per_cpu_int_res));
 
+	BUG_ON(!request_mem_region(main_int_res.start,
+				   resource_size(&main_int_res),
+				   node->full_name));
+	BUG_ON(!request_mem_region(per_cpu_int_res.start,
+				   resource_size(&per_cpu_int_res),
+				   node->full_name));
+
+	main_int_base = ioremap(main_int_res.start,
+				resource_size(&main_int_res));
 	BUG_ON(!main_int_base);
+
+	per_cpu_int_base = ioremap(per_cpu_int_res.start,
+				   resource_size(&per_cpu_int_res));
 	BUG_ON(!per_cpu_int_base);
 
 	control = readl(main_int_base + ARMADA_370_XP_INT_CONTROL);
@@ -262,8 +453,7 @@
 		irq_domain_add_linear(node, (control >> 2) & 0x3ff,
 				&armada_370_xp_mpic_irq_ops, NULL);
 
-	if (!armada_370_xp_mpic_domain)
-		panic("Unable to add Armada_370_Xp MPIC irq domain (DT)\n");
+	BUG_ON(!armada_370_xp_mpic_domain);
 
 	irq_set_default_host(armada_370_xp_mpic_domain);
 
@@ -280,6 +470,8 @@
 
 #endif
 
+	armada_370_xp_msi_init(node, main_int_res.start);
+
 	set_handle_irq(armada_370_xp_handle_irq);
 
 	return 0;
diff --git a/drivers/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c
index 16c78f1..1693b8e 100644
--- a/drivers/irqchip/irq-bcm2835.c
+++ b/drivers/irqchip/irq-bcm2835.c
@@ -49,9 +49,11 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/irqdomain.h>
-#include <linux/irqchip/bcm2835.h>
 
 #include <asm/exception.h>
+#include <asm/mach/irq.h>
+
+#include "irqchip.h"
 
 /* Put the bank and irq (32 bits) into the hwirq */
 #define MAKE_HWIRQ(b, n)	((b << 5) | (n))
@@ -93,6 +95,8 @@
 };
 
 static struct armctrl_ic intc __read_mostly;
+static asmlinkage void __exception_irq_entry bcm2835_handle_irq(
+	struct pt_regs *regs);
 
 static void armctrl_mask_irq(struct irq_data *d)
 {
@@ -164,19 +168,11 @@
 			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 		}
 	}
+
+	set_handle_irq(bcm2835_handle_irq);
 	return 0;
 }
 
-static struct of_device_id irq_of_match[] __initconst = {
-	{ .compatible = "brcm,bcm2835-armctrl-ic", .data = armctrl_of_init },
-	{ }
-};
-
-void __init bcm2835_init_irq(void)
-{
-	of_irq_init(irq_of_match);
-}
-
 /*
  * Handle each interrupt across the entire interrupt controller.  This reads the
  * status register before handling each interrupt, which is necessary given that
@@ -200,7 +196,7 @@
 	handle_IRQ(irq_linear_revmap(intc.domain, irq), regs);
 }
 
-asmlinkage void __exception_irq_entry bcm2835_handle_irq(
+static asmlinkage void __exception_irq_entry bcm2835_handle_irq(
 	struct pt_regs *regs)
 {
 	u32 stat, irq;
@@ -222,3 +218,5 @@
 		}
 	}
 }
+
+IRQCHIP_DECLARE(bcm2835_armctrl_ic, "brcm,bcm2835-armctrl-ic", armctrl_of_init);
diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c
index 2bbb004..8e21ae0 100644
--- a/drivers/irqchip/irq-vic.c
+++ b/drivers/irqchip/irq-vic.c
@@ -469,6 +469,8 @@
 int __init vic_of_init(struct device_node *node, struct device_node *parent)
 {
 	void __iomem *regs;
+	u32 interrupt_mask = ~0;
+	u32 wakeup_mask = ~0;
 
 	if (WARN(parent, "non-root VICs are not supported"))
 		return -EINVAL;
@@ -477,10 +479,13 @@
 	if (WARN_ON(!regs))
 		return -EIO;
 
+	of_property_read_u32(node, "valid-mask", &interrupt_mask);
+	of_property_read_u32(node, "valid-wakeup-mask", &wakeup_mask);
+
 	/*
 	 * Passing 0 as first IRQ makes the simple domain allocate descriptors
 	 */
-	__vic_init(regs, 0, ~0, ~0, node);
+	__vic_init(regs, 0, interrupt_mask, wakeup_mask, node);
 
 	return 0;
 }
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 875bbe4..72156c1 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -300,6 +300,16 @@
 	  LED driver chip accessed via the I2C bus. Supported
 	  devices include PCA9633 and PCA9634
 
+config LEDS_PCA9685
+	tristate "LED support for PCA9685 I2C chip"
+	depends on LEDS_CLASS
+	depends on I2C
+	help
+	  This option enables support for LEDs connected to the PCA9685
+	  LED driver chip accessed via the I2C bus.
+	  The PCA9685 offers 12-bit PWM (4095 levels of brightness) on
+	  16 individual channels.
+
 config LEDS_WM831X_STATUS
 	tristate "LED support for status LEDs on WM831x PMICs"
 	depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 8979b0b..3cd76db 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -36,6 +36,7 @@
 obj-$(CONFIG_LEDS_FSG)			+= leds-fsg.o
 obj-$(CONFIG_LEDS_PCA955X)		+= leds-pca955x.o
 obj-$(CONFIG_LEDS_PCA963X)		+= leds-pca963x.o
+obj-$(CONFIG_LEDS_PCA9685)		+= leds-pca9685.o
 obj-$(CONFIG_LEDS_DA903X)		+= leds-da903x.o
 obj-$(CONFIG_LEDS_DA9052)		+= leds-da9052.o
 obj-$(CONFIG_LEDS_WM831X_STATUS)	+= leds-wm831x-status.o
diff --git a/drivers/leds/leds-blinkm.c b/drivers/leds/leds-blinkm.c
index a502678..66d0a57 100644
--- a/drivers/leds/leds-blinkm.c
+++ b/drivers/leds/leds-blinkm.c
@@ -161,13 +161,10 @@
 	switch (color) {
 	case RED:
 		return scnprintf(buf, PAGE_SIZE, "%02X\n", data->red);
-		break;
 	case GREEN:
 		return scnprintf(buf, PAGE_SIZE, "%02X\n", data->green);
-		break;
 	case BLUE:
 		return scnprintf(buf, PAGE_SIZE, "%02X\n", data->blue);
-		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/drivers/leds/leds-dac124s085.c b/drivers/leds/leds-dac124s085.c
index 1f9d8e6..db3ba8b 100644
--- a/drivers/leds/leds-dac124s085.c
+++ b/drivers/leds/leds-dac124s085.c
@@ -101,7 +101,6 @@
 	while (i--)
 		led_classdev_unregister(&dac->leds[i].ldev);
 
-	spi_set_drvdata(spi, NULL);
 	return ret;
 }
 
@@ -115,8 +114,6 @@
 		cancel_work_sync(&dac->leds[i].work);
 	}
 
-	spi_set_drvdata(spi, NULL);
-
 	return 0;
 }
 
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index e8b01e5..78b0e27 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/leds.h>
+#include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
 #include <linux/slab.h>
@@ -170,11 +171,11 @@
 	int count, ret;
 
 	/* count LEDs in this device, so we know how much to allocate */
-	count = of_get_child_count(np);
+	count = of_get_available_child_count(np);
 	if (!count)
 		return ERR_PTR(-ENODEV);
 
-	for_each_child_of_node(np, child)
+	for_each_available_child_of_node(np, child)
 		if (of_get_gpio(child, 0) == -EPROBE_DEFER)
 			return ERR_PTR(-EPROBE_DEFER);
 
@@ -183,7 +184,7 @@
 	if (!priv)
 		return ERR_PTR(-ENOMEM);
 
-	for_each_child_of_node(np, child) {
+	for_each_available_child_of_node(np, child) {
 		struct gpio_led led = {};
 		enum of_gpio_flags flags;
 		const char *state;
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
index fe3bcbb..6b553d9 100644
--- a/drivers/leds/leds-lp5523.c
+++ b/drivers/leds/leds-lp5523.c
@@ -29,6 +29,7 @@
 #include <linux/leds.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/of.h>
 #include <linux/platform_data/leds-lp55xx.h>
 #include <linux/slab.h>
 
diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c
index 2585cfd..bf006f4 100644
--- a/drivers/leds/leds-lp5562.c
+++ b/drivers/leds/leds-lp5562.c
@@ -17,6 +17,7 @@
 #include <linux/leds.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/of.h>
 #include <linux/platform_data/leds-lp55xx.h>
 #include <linux/slab.h>
 
diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c
index 351825b..9acc6bb 100644
--- a/drivers/leds/leds-lp55xx-common.c
+++ b/drivers/leds/leds-lp55xx-common.c
@@ -20,6 +20,8 @@
 #include <linux/module.h>
 #include <linux/platform_data/leds-lp55xx.h>
 #include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
 
 #include "leds-lp55xx-common.h"
 
@@ -165,6 +167,7 @@
 	led->led_current = pdata->led_config[chan].led_current;
 	led->max_current = pdata->led_config[chan].max_current;
 	led->chan_nr = pdata->led_config[chan].chan_nr;
+	led->cdev.default_trigger = pdata->led_config[chan].default_trigger;
 
 	if (led->chan_nr >= max_channel) {
 		dev_err(dev, "Use channel numbers between 0 and %d\n",
@@ -406,18 +409,18 @@
 	if (!pdata || !cfg)
 		return -EINVAL;
 
-	if (pdata->setup_resources) {
-		ret = pdata->setup_resources();
+	if (gpio_is_valid(pdata->enable_gpio)) {
+		ret = devm_gpio_request_one(dev, pdata->enable_gpio,
+					    GPIOF_DIR_OUT, "lp5523_enable");
 		if (ret < 0) {
-			dev_err(dev, "setup resoure err: %d\n", ret);
+			dev_err(dev, "could not acquire enable gpio (err=%d)\n",
+				ret);
 			goto err;
 		}
-	}
 
-	if (pdata->enable) {
-		pdata->enable(0);
+		gpio_set_value(pdata->enable_gpio, 0);
 		usleep_range(1000, 2000); /* Keep enable down at least 1ms */
-		pdata->enable(1);
+		gpio_set_value(pdata->enable_gpio, 1);
 		usleep_range(1000, 2000); /* 500us abs min. */
 	}
 
@@ -458,11 +461,8 @@
 	if (chip->clk)
 		clk_disable_unprepare(chip->clk);
 
-	if (pdata->enable)
-		pdata->enable(0);
-
-	if (pdata->release_resources)
-		pdata->release_resources();
+	if (gpio_is_valid(pdata->enable_gpio))
+		gpio_set_value(pdata->enable_gpio, 0);
 }
 EXPORT_SYMBOL_GPL(lp55xx_deinit_device);
 
@@ -586,6 +586,8 @@
 		of_property_read_string(child, "chan-name", &cfg[i].name);
 		of_property_read_u8(child, "led-cur", &cfg[i].led_current);
 		of_property_read_u8(child, "max-cur", &cfg[i].max_current);
+		cfg[i].default_trigger =
+			of_get_property(child, "linux,default-trigger", NULL);
 
 		i++;
 	}
@@ -593,6 +595,8 @@
 	of_property_read_string(np, "label", &pdata->label);
 	of_property_read_u8(np, "clock-mode", &pdata->clock_mode);
 
+	pdata->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0);
+
 	/* LP8501 specific */
 	of_property_read_u8(np, "pwr-sel", (u8 *)&pdata->pwr_sel);
 
diff --git a/drivers/leds/leds-lp8501.c b/drivers/leds/leds-lp8501.c
index 8d55a780..f1c704f 100644
--- a/drivers/leds/leds-lp8501.c
+++ b/drivers/leds/leds-lp8501.c
@@ -18,6 +18,7 @@
 #include <linux/leds.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/of.h>
 #include <linux/platform_data/leds-lp55xx.h>
 #include <linux/slab.h>
 
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index 141f134..c7a4230 100644
--- a/drivers/leds/leds-ns2.c
+++ b/drivers/leds/leds-ns2.c
@@ -30,6 +30,7 @@
 #include <linux/leds.h>
 #include <linux/module.h>
 #include <linux/platform_data/leds-kirkwood-ns2.h>
+#include <linux/of.h>
 #include <linux/of_gpio.h>
 
 /*
diff --git a/drivers/leds/leds-pca9685.c b/drivers/leds/leds-pca9685.c
new file mode 100644
index 0000000..6e1ef3a
--- /dev/null
+++ b/drivers/leds/leds-pca9685.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2013 Maximilian Güntner <maximilian.guentner@gmail.com>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * Based on leds-pca963x.c driver by
+ * Peter Meerwald <p.meerwald@bct-electronic.com>
+ *
+ * Driver for the NXP PCA9685 12-Bit PWM LED driver chip.
+ *
+ */
+
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/workqueue.h>
+
+#include <linux/platform_data/leds-pca9685.h>
+
+/* Register Addresses */
+#define PCA9685_MODE1 0x00
+#define PCA9685_MODE2 0x01
+#define PCA9685_LED0_ON_L 0x06
+#define PCA9685_ALL_LED_ON_L 0xFA
+
+/* MODE1 Register */
+#define PCA9685_ALLCALL 0x00
+#define PCA9685_SLEEP   0x04
+#define PCA9685_AI      0x05
+
+/* MODE2 Register */
+#define PCA9685_INVRT   0x04
+#define PCA9685_OUTDRV  0x02
+
+static const struct i2c_device_id pca9685_id[] = {
+	{ "pca9685", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, pca9685_id);
+
+struct pca9685_led {
+	struct i2c_client *client;
+	struct work_struct work;
+	u16 brightness;
+	struct led_classdev led_cdev;
+	int led_num; /* 0-15 */
+	char name[32];
+};
+
+static void pca9685_write_msg(struct i2c_client *client, u8 *buf, u8 len)
+{
+	struct i2c_msg msg = {
+		.addr = client->addr,
+		.flags = 0x00,
+		.len = len,
+		.buf = buf
+	};
+	i2c_transfer(client->adapter, &msg, 1);
+}
+
+static void pca9685_all_off(struct i2c_client *client)
+{
+	u8 i2c_buffer[5] = {PCA9685_ALL_LED_ON_L, 0x00, 0x00, 0x00, 0x10};
+	pca9685_write_msg(client, i2c_buffer, 5);
+}
+
+static void pca9685_led_work(struct work_struct *work)
+{
+	struct pca9685_led *pca9685;
+	u8 i2c_buffer[5];
+
+	pca9685 = container_of(work, struct pca9685_led, work);
+	i2c_buffer[0] = PCA9685_LED0_ON_L + 4 * pca9685->led_num;
+	/*
+	 * 4095 is the maximum brightness, so we set the ON time to 0x1000
+	 * which disables the PWM generator for that LED
+	 */
+	if (pca9685->brightness == 4095)
+		*((__le16 *)(i2c_buffer+1)) = cpu_to_le16(0x1000);
+	else
+		*((__le16 *)(i2c_buffer+1)) = 0x0000;
+
+	if (pca9685->brightness == 0)
+		*((__le16 *)(i2c_buffer+3)) = cpu_to_le16(0x1000);
+	else if (pca9685->brightness == 4095)
+		*((__le16 *)(i2c_buffer+3)) = 0x0000;
+	else
+		*((__le16 *)(i2c_buffer+3)) = cpu_to_le16(pca9685->brightness);
+
+	pca9685_write_msg(pca9685->client, i2c_buffer, 5);
+}
+
+static void pca9685_led_set(struct led_classdev *led_cdev,
+		enum led_brightness value)
+{
+	struct pca9685_led *pca9685;
+	pca9685 = container_of(led_cdev, struct pca9685_led, led_cdev);
+	pca9685->brightness = value;
+
+	schedule_work(&pca9685->work);
+}
+
+static int pca9685_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	struct pca9685_led *pca9685;
+	struct pca9685_platform_data *pdata;
+	int err;
+	u8 i;
+
+	pdata = dev_get_platdata(&client->dev);
+	if (pdata) {
+		if (pdata->leds.num_leds < 1 || pdata->leds.num_leds > 15) {
+			dev_err(&client->dev, "board info must claim 1-16 LEDs");
+			return -EINVAL;
+		}
+	}
+
+	pca9685 = devm_kzalloc(&client->dev, 16 * sizeof(*pca9685), GFP_KERNEL);
+	if (!pca9685)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, pca9685);
+	pca9685_all_off(client);
+
+	for (i = 0; i < 16; i++) {
+		pca9685[i].client = client;
+		pca9685[i].led_num = i;
+		pca9685[i].name[0] = '\0';
+		if (pdata && i < pdata->leds.num_leds) {
+			if (pdata->leds.leds[i].name)
+				strncpy(pca9685[i].name,
+					pdata->leds.leds[i].name,
+					sizeof(pca9685[i].name)-1);
+			if (pdata->leds.leds[i].default_trigger)
+				pca9685[i].led_cdev.default_trigger =
+					pdata->leds.leds[i].default_trigger;
+		}
+		if (strlen(pca9685[i].name) == 0) {
+			/*
+			 * Write adapter and address to the name as well.
+			 * Otherwise multiple chips attached to one host would
+			 * not work.
+			 */
+			snprintf(pca9685[i].name, sizeof(pca9685[i].name),
+					"pca9685:%d:x%.2x:%d",
+					client->adapter->nr, client->addr, i);
+		}
+		pca9685[i].led_cdev.name = pca9685[i].name;
+		pca9685[i].led_cdev.max_brightness = 0xfff;
+		pca9685[i].led_cdev.brightness_set = pca9685_led_set;
+
+		INIT_WORK(&pca9685[i].work, pca9685_led_work);
+		err = led_classdev_register(&client->dev, &pca9685[i].led_cdev);
+		if (err < 0)
+			goto exit;
+	}
+
+	if (pdata)
+		i2c_smbus_write_byte_data(client, PCA9685_MODE2,
+			pdata->outdrv << PCA9685_OUTDRV |
+			pdata->inverted << PCA9685_INVRT);
+	else
+		i2c_smbus_write_byte_data(client, PCA9685_MODE2,
+			PCA9685_TOTEM_POLE << PCA9685_OUTDRV);
+	/* Enable Auto-Increment, enable oscillator, ALLCALL/SUBADDR disabled */
+	i2c_smbus_write_byte_data(client, PCA9685_MODE1, BIT(PCA9685_AI));
+
+	return 0;
+
+exit:
+	while (i--) {
+		led_classdev_unregister(&pca9685[i].led_cdev);
+		cancel_work_sync(&pca9685[i].work);
+	}
+	return err;
+}
+
+static int pca9685_remove(struct i2c_client *client)
+{
+	struct pca9685_led *pca9685 = i2c_get_clientdata(client);
+	u8 i;
+
+	for (i = 0; i < 16; i++) {
+		led_classdev_unregister(&pca9685[i].led_cdev);
+		cancel_work_sync(&pca9685[i].work);
+	}
+	pca9685_all_off(client);
+	return 0;
+}
+
+static struct i2c_driver pca9685_driver = {
+	.driver = {
+		.name = "leds-pca9685",
+		.owner = THIS_MODULE,
+	},
+	.probe = pca9685_probe,
+	.remove = pca9685_remove,
+	.id_table = pca9685_id,
+};
+
+module_i2c_driver(pca9685_driver);
+
+MODULE_AUTHOR("Maximilian Güntner <maximilian.guentner@gmail.com>");
+MODULE_DESCRIPTION("PCA9685 LED Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
index bb6f948..2848171 100644
--- a/drivers/leds/leds-pwm.c
+++ b/drivers/leds/leds-pwm.c
@@ -232,7 +232,7 @@
 	.driver		= {
 		.name	= "leds_pwm",
 		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(of_pwm_leds_match),
+		.of_match_table = of_pwm_leds_match,
 	},
 };
 
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index 696238b..d26a312 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -103,6 +103,7 @@
 	bool "Use front LED as IDE LED by default"
 	depends on ADB_PMU_LED
 	depends on LEDS_CLASS
+	depends on IDE_GD_ATA
 	select LEDS_TRIGGERS
 	select LEDS_TRIGGER_IDE_DISK
 	help
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index ac5c879..4f12c6f 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -24,6 +24,8 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <asm/machdep.h>
 #include <asm/macio.h>
diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c
index cad0e19..4192901 100644
--- a/drivers/macintosh/rack-meter.c
+++ b/drivers/macintosh/rack-meter.c
@@ -25,6 +25,8 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/kernel_stat.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <asm/io.h>
 #include <asm/prom.h>
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index b3b2d36..23b4a3b 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -35,6 +35,7 @@
 #include <linux/poll.h>
 #include <linux/mutex.h>
 #include <linux/of_device.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/slab.h>
 
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 283e1b5..dee88e5 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -46,6 +46,8 @@
 #include <linux/suspend.h>
 #include <linux/cpu.h>
 #include <linux/compat.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index 71eb233..2a7f0dd 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -996,10 +996,11 @@
 		closure_bio_submit(bio, cl, s->d);
 	} else {
 		bch_writeback_add(dc);
+		s->op.cache_bio = bio;
 
 		if (bio->bi_rw & REQ_FLUSH) {
 			/* Also need to send a flush to the backing device */
-			struct bio *flush = bio_alloc_bioset(0, GFP_NOIO,
+			struct bio *flush = bio_alloc_bioset(GFP_NOIO, 0,
 							     dc->disk.bio_split);
 
 			flush->bi_rw	= WRITE_FLUSH;
@@ -1008,8 +1009,6 @@
 			flush->bi_private = cl;
 
 			closure_bio_submit(flush, cl, s->d);
-		} else {
-			s->op.cache_bio = bio;
 		}
 	}
 out:
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index a7fd821..12dc29b 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -1654,9 +1654,9 @@
 	bitmap->mddev = mddev;
 
 	if (mddev->kobj.sd)
-		bm = sysfs_get_dirent(mddev->kobj.sd, NULL, "bitmap");
+		bm = sysfs_get_dirent(mddev->kobj.sd, "bitmap");
 	if (bm) {
-		bitmap->sysfs_can_clear = sysfs_get_dirent(bm, NULL, "can_clear");
+		bitmap->sysfs_can_clear = sysfs_get_dirent(bm, "can_clear");
 		sysfs_put(bm);
 	} else
 		bitmap->sysfs_can_clear = NULL;
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
index 4caa8e6..2d2b1b7 100644
--- a/drivers/md/dm-snap-persistent.c
+++ b/drivers/md/dm-snap-persistent.c
@@ -269,6 +269,14 @@
 	return NUM_SNAPSHOT_HDR_CHUNKS + ((ps->exceptions_per_area + 1) * area);
 }
 
+static void skip_metadata(struct pstore *ps)
+{
+	uint32_t stride = ps->exceptions_per_area + 1;
+	chunk_t next_free = ps->next_free;
+	if (sector_div(next_free, stride) == NUM_SNAPSHOT_HDR_CHUNKS)
+		ps->next_free++;
+}
+
 /*
  * Read or write a metadata area.  Remembering to skip the first
  * chunk which holds the header.
@@ -502,6 +510,8 @@
 
 	ps->current_area--;
 
+	skip_metadata(ps);
+
 	return 0;
 }
 
@@ -616,8 +626,6 @@
 					struct dm_exception *e)
 {
 	struct pstore *ps = get_info(store);
-	uint32_t stride;
-	chunk_t next_free;
 	sector_t size = get_dev_size(dm_snap_cow(store->snap)->bdev);
 
 	/* Is there enough room ? */
@@ -630,10 +638,8 @@
 	 * Move onto the next free pending, making sure to take
 	 * into account the location of the metadata chunks.
 	 */
-	stride = (ps->exceptions_per_area + 1);
-	next_free = ++ps->next_free;
-	if (sector_div(next_free, stride) == 1)
-		ps->next_free++;
+	ps->next_free++;
+	skip_metadata(ps);
 
 	atomic_inc(&ps->pending_count);
 	return 0;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index adf4d7e..2445fec 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -3555,7 +3555,7 @@
 			printk(KERN_WARNING
 			       "md: cannot register extra attributes for %s\n",
 			       mdname(mddev));
-		mddev->sysfs_action = sysfs_get_dirent(mddev->kobj.sd, NULL, "sync_action");
+		mddev->sysfs_action = sysfs_get_dirent(mddev->kobj.sd, "sync_action");
 	}		
 	if (mddev->pers->sync_request != NULL &&
 	    pers->sync_request == NULL) {
@@ -8111,6 +8111,7 @@
 	u64 *p;
 	int lo, hi;
 	int rv = 1;
+	unsigned long flags;
 
 	if (bb->shift < 0)
 		/* badblocks are disabled */
@@ -8125,7 +8126,7 @@
 		sectors = next - s;
 	}
 
-	write_seqlock_irq(&bb->lock);
+	write_seqlock_irqsave(&bb->lock, flags);
 
 	p = bb->page;
 	lo = 0;
@@ -8241,7 +8242,7 @@
 	bb->changed = 1;
 	if (!acknowledged)
 		bb->unacked_exist = 1;
-	write_sequnlock_irq(&bb->lock);
+	write_sequnlock_irqrestore(&bb->lock, flags);
 
 	return rv;
 }
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 608050c..b0051f2 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -501,7 +501,7 @@
 static inline struct sysfs_dirent *sysfs_get_dirent_safe(struct sysfs_dirent *sd, char *name)
 {
 	if (sd)
-		return sysfs_get_dirent(sd, NULL, name);
+		return sysfs_get_dirent(sd, name);
 	return sd;
 }
 static inline void sysfs_notify_dirent_safe(struct sysfs_dirent *sd)
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index d60412c..aacf6bf 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1479,6 +1479,7 @@
 			}
 		}
 		if (rdev
+		    && rdev->recovery_offset == MaxSector
 		    && !test_bit(Faulty, &rdev->flags)
 		    && !test_and_set_bit(In_sync, &rdev->flags)) {
 			count++;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index df7b0a0..73dc8a3 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1782,6 +1782,7 @@
 			}
 			sysfs_notify_dirent_safe(tmp->replacement->sysfs_state);
 		} else if (tmp->rdev
+			   && tmp->rdev->recovery_offset == MaxSector
 			   && !test_bit(Faulty, &tmp->rdev->flags)
 			   && !test_and_set_bit(In_sync, &tmp->rdev->flags)) {
 			count++;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 7ff4f25..f8b9068 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -778,6 +778,12 @@
 			bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
 			bi->bi_io_vec[0].bv_offset = 0;
 			bi->bi_size = STRIPE_SIZE;
+			/*
+			 * If this is discard request, set bi_vcnt 0. We don't
+			 * want to confuse SCSI because SCSI will replace payload
+			 */
+			if (rw & REQ_DISCARD)
+				bi->bi_vcnt = 0;
 			if (rrdev)
 				set_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags);
 
@@ -816,6 +822,12 @@
 			rbi->bi_io_vec[0].bv_len = STRIPE_SIZE;
 			rbi->bi_io_vec[0].bv_offset = 0;
 			rbi->bi_size = STRIPE_SIZE;
+			/*
+			 * If this is discard request, set bi_vcnt 0. We don't
+			 * want to confuse SCSI because SCSI will replace payload
+			 */
+			if (rw & REQ_DISCARD)
+				rbi->bi_vcnt = 0;
 			if (conf->mddev->gendisk)
 				trace_block_bio_remap(bdev_get_queue(rbi->bi_bdev),
 						      rbi, disk_devt(conf->mddev->gendisk),
@@ -2910,6 +2922,14 @@
 		}
 		/* now that discard is done we can proceed with any sync */
 		clear_bit(STRIPE_DISCARD, &sh->state);
+		/*
+		 * SCSI discard will change some bio fields and the stripe has
+		 * no updated data, so remove it from hash list and the stripe
+		 * will be reinitialized
+		 */
+		spin_lock_irq(&conf->device_lock);
+		remove_hash(sh);
+		spin_unlock_irq(&conf->device_lock);
 		if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state))
 			set_bit(STRIPE_HANDLE, &sh->state);
 
diff --git a/drivers/media/dvb-frontends/tda10071.c b/drivers/media/dvb-frontends/tda10071.c
index 2521f7e..e79749c 100644
--- a/drivers/media/dvb-frontends/tda10071.c
+++ b/drivers/media/dvb-frontends/tda10071.c
@@ -912,14 +912,8 @@
 		{ 0xd5, 0x03, 0x03 },
 	};
 
-	/* firmware status */
-	ret = tda10071_rd_reg(priv, 0x51, &tmp);
-	if (ret)
-		goto error;
-
-	if (!tmp) {
+	if (priv->warm) {
 		/* warm state - wake up device from sleep */
-		priv->warm = 1;
 
 		for (i = 0; i < ARRAY_SIZE(tab); i++) {
 			ret = tda10071_wr_reg_mask(priv, tab[i].reg,
@@ -937,7 +931,6 @@
 			goto error;
 	} else {
 		/* cold state - try to download firmware */
-		priv->warm = 0;
 
 		/* request the firmware, this will block and timeout */
 		ret = request_firmware(&fw, fw_file, priv->i2c->dev.parent);
diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c
index bb0c99d..b06a7e5 100644
--- a/drivers/media/i2c/ad9389b.c
+++ b/drivers/media/i2c/ad9389b.c
@@ -628,16 +628,13 @@
 
 static const struct v4l2_dv_timings_cap ad9389b_timings_cap = {
 	.type = V4L2_DV_BT_656_1120,
-	.bt = {
-		.max_width = 1920,
-		.max_height = 1200,
-		.min_pixelclock = 25000000,
-		.max_pixelclock = 170000000,
-		.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
+	/* keep this initialization for compatibility with GCC < 4.4.6 */
+	.reserved = { 0 },
+	V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1200, 25000000, 170000000,
+		V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
 			V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
-		.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE |
-			V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM,
-	},
+		V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING |
+		V4L2_DV_BT_CAP_CUSTOM)
 };
 
 static int ad9389b_s_dv_timings(struct v4l2_subdev *sd,
diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c
index 7a576097..7c8d971 100644
--- a/drivers/media/i2c/adv7511.c
+++ b/drivers/media/i2c/adv7511.c
@@ -119,16 +119,14 @@
 
 static const struct v4l2_dv_timings_cap adv7511_timings_cap = {
 	.type = V4L2_DV_BT_656_1120,
-	.bt = {
-		.max_width = ADV7511_MAX_WIDTH,
-		.max_height = ADV7511_MAX_HEIGHT,
-		.min_pixelclock = ADV7511_MIN_PIXELCLOCK,
-		.max_pixelclock = ADV7511_MAX_PIXELCLOCK,
-		.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
+	/* keep this initialization for compatibility with GCC < 4.4.6 */
+	.reserved = { 0 },
+	V4L2_INIT_BT_TIMINGS(0, ADV7511_MAX_WIDTH, 0, ADV7511_MAX_HEIGHT,
+		ADV7511_MIN_PIXELCLOCK, ADV7511_MAX_PIXELCLOCK,
+		V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
 			V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
-		.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE |
-			V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM,
-	},
+		V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING |
+			V4L2_DV_BT_CAP_CUSTOM)
 };
 
 static inline struct adv7511_state *get_adv7511_state(struct v4l2_subdev *sd)
@@ -1126,6 +1124,7 @@
 	state->i2c_edid = i2c_new_dummy(client->adapter, state->i2c_edid_addr >> 1);
 	if (state->i2c_edid == NULL) {
 		v4l2_err(sd, "failed to register edid i2c client\n");
+		err = -ENOMEM;
 		goto err_entity;
 	}
 
@@ -1133,6 +1132,7 @@
 	state->work_queue = create_singlethread_workqueue(sd->name);
 	if (state->work_queue == NULL) {
 		v4l2_err(sd, "could not create workqueue\n");
+		err = -ENOMEM;
 		goto err_unreg_cec;
 	}
 
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
index d174890..22f729d 100644
--- a/drivers/media/i2c/adv7842.c
+++ b/drivers/media/i2c/adv7842.c
@@ -546,30 +546,24 @@
 
 static const struct v4l2_dv_timings_cap adv7842_timings_cap_analog = {
 	.type = V4L2_DV_BT_656_1120,
-	.bt = {
-		.max_width = 1920,
-		.max_height = 1200,
-		.min_pixelclock = 25000000,
-		.max_pixelclock = 170000000,
-		.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
+	/* keep this initialization for compatibility with GCC < 4.4.6 */
+	.reserved = { 0 },
+	V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1200, 25000000, 170000000,
+		V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
 			V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
-		.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE |
-			V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM,
-	},
+		V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING |
+			V4L2_DV_BT_CAP_CUSTOM)
 };
 
 static const struct v4l2_dv_timings_cap adv7842_timings_cap_digital = {
 	.type = V4L2_DV_BT_656_1120,
-	.bt = {
-		.max_width = 1920,
-		.max_height = 1200,
-		.min_pixelclock = 25000000,
-		.max_pixelclock = 225000000,
-		.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
+	/* keep this initialization for compatibility with GCC < 4.4.6 */
+	.reserved = { 0 },
+	V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1200, 25000000, 225000000,
+		V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
 			V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
-		.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE |
-			V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM,
-	},
+		V4L2_DV_BT_CAP_PROGRESSIVE | V4L2_DV_BT_CAP_REDUCED_BLANKING |
+			V4L2_DV_BT_CAP_CUSTOM)
 };
 
 static inline const struct v4l2_dv_timings_cap *
diff --git a/drivers/media/i2c/ths8200.c b/drivers/media/i2c/ths8200.c
index a58a8f6..d9f65d7 100644
--- a/drivers/media/i2c/ths8200.c
+++ b/drivers/media/i2c/ths8200.c
@@ -46,14 +46,10 @@
 
 static const struct v4l2_dv_timings_cap ths8200_timings_cap = {
 	.type = V4L2_DV_BT_656_1120,
-	.bt = {
-		.max_width = 1920,
-		.max_height = 1080,
-		.min_pixelclock = 25000000,
-		.max_pixelclock = 148500000,
-		.standards = V4L2_DV_BT_STD_CEA861,
-		.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE,
-	},
+	/* keep this initialization for compatibility with GCC < 4.4.6 */
+	.reserved = { 0 },
+	V4L2_INIT_BT_TIMINGS(0, 1920, 0, 1080, 25000000, 148500000,
+		V4L2_DV_BT_STD_CEA861, V4L2_DV_BT_CAP_PROGRESSIVE)
 };
 
 static inline struct ths8200_state *to_state(struct v4l2_subdev *sd)
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index e12bbd8..fb60da8 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -1455,6 +1455,7 @@
 
 	/* stop video capture */
 	if (res_check(fh, RESOURCE_VIDEO)) {
+		pm_qos_remove_request(&dev->qos_request);
 		videobuf_streamoff(&fh->cap);
 		res_free(dev,fh,RESOURCE_VIDEO);
 	}
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index c7caf94..eb70dda 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -112,7 +112,7 @@
 config VIDEO_S3C_CAMIF
 	tristate "Samsung S3C24XX/S3C64XX SoC Camera Interface driver"
 	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
-	depends on (PLAT_S3C64XX || PLAT_S3C24XX) && PM_RUNTIME
+	depends on (ARCH_S3C64XX || PLAT_S3C24XX) && PM_RUNTIME
 	select VIDEOBUF2_DMA_CONTIG
 	---help---
 	  This is a v4l2 driver for s3c24xx and s3c64xx SoC series camera
diff --git a/drivers/media/platform/exynos4-is/Kconfig b/drivers/media/platform/exynos4-is/Kconfig
index 53ad0f0..d2d3b4b 100644
--- a/drivers/media/platform/exynos4-is/Kconfig
+++ b/drivers/media/platform/exynos4-is/Kconfig
@@ -29,7 +29,7 @@
 config VIDEO_S5P_MIPI_CSIS
 	tristate "S5P/EXYNOS MIPI-CSI2 receiver (MIPI-CSIS) driver"
 	depends on REGULATOR
-	select S5P_SETUP_MIPIPHY
+	select GENERIC_PHY
 	help
 	  This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC MIPI-CSI2
 	  receiver (MIPI-CSIS) devices.
diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c
index 0914230..9fc2af6 100644
--- a/drivers/media/platform/exynos4-is/mipi-csis.c
+++ b/drivers/media/platform/exynos4-is/mipi-csis.c
@@ -20,6 +20,7 @@
 #include <linux/memory.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/phy/phy.h>
 #include <linux/platform_data/mipi-csis.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
@@ -180,6 +181,7 @@
  * @sd: v4l2_subdev associated with CSIS device instance
  * @index: the hardware instance index
  * @pdev: CSIS platform device
+ * @phy: pointer to the CSIS generic PHY
  * @regs: mmaped I/O registers memory
  * @supplies: CSIS regulator supplies
  * @clock: CSIS clocks
@@ -203,6 +205,7 @@
 	struct v4l2_subdev sd;
 	u8 index;
 	struct platform_device *pdev;
+	struct phy *phy;
 	void __iomem *regs;
 	struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES];
 	struct clk *clock[NUM_CSIS_CLOCKS];
@@ -779,8 +782,8 @@
 					"samsung,csis-wclk");
 
 	state->num_lanes = endpoint.bus.mipi_csi2.num_data_lanes;
-
 	of_node_put(node);
+
 	return 0;
 }
 #else
@@ -829,6 +832,10 @@
 		return -EINVAL;
 	}
 
+	state->phy = devm_phy_get(dev, "csis");
+	if (IS_ERR(state->phy))
+		return PTR_ERR(state->phy);
+
 	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	state->regs = devm_ioremap_resource(dev, mem_res);
 	if (IS_ERR(state->regs))
@@ -922,7 +929,7 @@
 	mutex_lock(&state->lock);
 	if (state->flags & ST_POWERED) {
 		s5pcsis_stop_stream(state);
-		ret = s5p_csis_phy_enable(state->index, false);
+		ret = phy_power_off(state->phy);
 		if (ret)
 			goto unlock;
 		ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES,
@@ -958,7 +965,7 @@
 					    state->supplies);
 		if (ret)
 			goto unlock;
-		ret = s5p_csis_phy_enable(state->index, true);
+		ret = phy_power_on(state->phy);
 		if (!ret) {
 			state->flags |= ST_POWERED;
 		} else {
diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index fe9898c..6a23223 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -21,6 +21,8 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/slab.h>
 #include <media/v4l2-common.h>
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
index 15d2396..9b88a460 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
@@ -1423,6 +1423,7 @@
 	jpeg->vfd_decoder->release	= video_device_release;
 	jpeg->vfd_decoder->lock		= &jpeg->lock;
 	jpeg->vfd_decoder->v4l2_dev	= &jpeg->v4l2_dev;
+	jpeg->vfd_decoder->vfl_dir	= VFL_DIR_M2M;
 
 	ret = video_register_device(jpeg->vfd_decoder, VFL_TYPE_GRABBER, -1);
 	if (ret) {
diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c
index 7a9c5e9..4f30341 100644
--- a/drivers/media/platform/sh_vou.c
+++ b/drivers/media/platform/sh_vou.c
@@ -776,7 +776,7 @@
 	v4l_bound_align_image(&pix->width, 0, VOU_MAX_IMAGE_WIDTH, 1,
 			      &pix->height, 0, VOU_MAX_IMAGE_HEIGHT, 1, 0);
 
-	for (i = 0; ARRAY_SIZE(vou_fmt); i++)
+	for (i = 0; i < ARRAY_SIZE(vou_fmt); i++)
 		if (vou_fmt[i].pfmt == pix->pixelformat)
 			return 0;
 
diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c
index 8f9f621..f975b70 100644
--- a/drivers/media/platform/soc_camera/mx3_camera.c
+++ b/drivers/media/platform/soc_camera/mx3_camera.c
@@ -266,7 +266,6 @@
 	struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
 	struct idmac_video_param *video = &ichan->params.video;
 	const struct soc_mbus_pixelfmt *host_fmt = icd->current_fmt->host_fmt;
-	unsigned long flags;
 	dma_cookie_t cookie;
 	size_t new_size;
 
@@ -328,7 +327,7 @@
 		memset(vb2_plane_vaddr(vb, 0), 0xaa, vb2_get_plane_payload(vb, 0));
 #endif
 
-	spin_lock_irqsave(&mx3_cam->lock, flags);
+	spin_lock_irq(&mx3_cam->lock);
 	list_add_tail(&buf->queue, &mx3_cam->capture);
 
 	if (!mx3_cam->active)
@@ -351,7 +350,7 @@
 	if (mx3_cam->active == buf)
 		mx3_cam->active = NULL;
 
-	spin_unlock_irqrestore(&mx3_cam->lock, flags);
+	spin_unlock_irq(&mx3_cam->lock);
 error:
 	vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
 }
diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c
index ad9309d..6c96e48 100644
--- a/drivers/media/tuners/e4000.c
+++ b/drivers/media/tuners/e4000.c
@@ -19,6 +19,7 @@
  */
 
 #include "e4000_priv.h"
+#include <linux/math64.h>
 
 /* write multiple registers */
 static int e4000_wr_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len)
@@ -233,7 +234,7 @@
 	 * or more.
 	 */
 	f_vco = c->frequency * e4000_pll_lut[i].mul;
-	sigma_delta = 0x10000UL * (f_vco % priv->cfg->clock) / priv->cfg->clock;
+	sigma_delta = div_u64(0x10000ULL * (f_vco % priv->cfg->clock), priv->cfg->clock);
 	buf[0] = f_vco / priv->cfg->clock;
 	buf[1] = (sigma_delta >> 0) & 0xff;
 	buf[2] = (sigma_delta >> 8) & 0xff;
diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c
index c43c8d3..be77482 100644
--- a/drivers/media/usb/stkwebcam/stk-webcam.c
+++ b/drivers/media/usb/stkwebcam/stk-webcam.c
@@ -111,6 +111,13 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "F3JC")
 		}
 	},
+	{
+		.ident = "T12Rg-H",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HCL Infosystems Limited"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "T12Rg-H")
+		}
+	},
 	{}
 };
 
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index 81695d4..c3bb250 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -2090,6 +2090,15 @@
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= UVC_QUIRK_PROBE_MINMAX },
+	/* Microsoft Lifecam NX-3000 */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor		= 0x045e,
+	  .idProduct		= 0x0721,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_QUIRK_PROBE_DEF },
 	/* Microsoft Lifecam VX-7000 */
 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -2174,6 +2183,15 @@
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
 	  .driver_info 		= UVC_QUIRK_PROBE_DEF },
+	/* Dell SP2008WFP Monitor */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor		= 0x05a9,
+	  .idProduct		= 0x2641,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info 		= UVC_QUIRK_PROBE_DEF },
 	/* Dell Alienware X51 */
 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_INT_INFO,
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 594c75e..de0e87f 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -353,7 +353,9 @@
 
 			if (b->m.planes[plane].bytesused > length)
 				return -EINVAL;
-			if (b->m.planes[plane].data_offset >=
+
+			if (b->m.planes[plane].data_offset > 0 &&
+			    b->m.planes[plane].data_offset >=
 			    b->m.planes[plane].bytesused)
 				return -EINVAL;
 		}
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index fd56f25..646f08f 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -423,6 +423,39 @@
 	return !!(vma->vm_flags & (VM_IO | VM_PFNMAP));
 }
 
+static int vb2_dc_get_user_pfn(unsigned long start, int n_pages,
+	struct vm_area_struct *vma, unsigned long *res)
+{
+	unsigned long pfn, start_pfn, prev_pfn;
+	unsigned int i;
+	int ret;
+
+	if (!vma_is_io(vma))
+		return -EFAULT;
+
+	ret = follow_pfn(vma, start, &pfn);
+	if (ret)
+		return ret;
+
+	start_pfn = pfn;
+	start += PAGE_SIZE;
+
+	for (i = 1; i < n_pages; ++i, start += PAGE_SIZE) {
+		prev_pfn = pfn;
+		ret = follow_pfn(vma, start, &pfn);
+
+		if (ret) {
+			pr_err("no page for address %lu\n", start);
+			return ret;
+		}
+		if (pfn != prev_pfn + 1)
+			return -EINVAL;
+	}
+
+	*res = start_pfn;
+	return 0;
+}
+
 static int vb2_dc_get_user_pages(unsigned long start, struct page **pages,
 	int n_pages, struct vm_area_struct *vma, int write)
 {
@@ -433,6 +466,9 @@
 			unsigned long pfn;
 			int ret = follow_pfn(vma, start, &pfn);
 
+			if (!pfn_valid(pfn))
+				return -EINVAL;
+
 			if (ret) {
 				pr_err("no page for address %lu\n", start);
 				return ret;
@@ -468,16 +504,49 @@
 	struct vb2_dc_buf *buf = buf_priv;
 	struct sg_table *sgt = buf->dma_sgt;
 
-	dma_unmap_sg(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
-	if (!vma_is_io(buf->vma))
-		vb2_dc_sgt_foreach_page(sgt, vb2_dc_put_dirty_page);
+	if (sgt) {
+		dma_unmap_sg(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
+		if (!vma_is_io(buf->vma))
+			vb2_dc_sgt_foreach_page(sgt, vb2_dc_put_dirty_page);
 
-	sg_free_table(sgt);
-	kfree(sgt);
+		sg_free_table(sgt);
+		kfree(sgt);
+	}
 	vb2_put_vma(buf->vma);
 	kfree(buf);
 }
 
+/*
+ * For some kind of reserved memory there might be no struct page available,
+ * so all that can be done to support such 'pages' is to try to convert
+ * pfn to dma address or at the last resort just assume that
+ * dma address == physical address (like it has been assumed in earlier version
+ * of videobuf2-dma-contig
+ */
+
+#ifdef __arch_pfn_to_dma
+static inline dma_addr_t vb2_dc_pfn_to_dma(struct device *dev, unsigned long pfn)
+{
+	return (dma_addr_t)__arch_pfn_to_dma(dev, pfn);
+}
+#elif defined(__pfn_to_bus)
+static inline dma_addr_t vb2_dc_pfn_to_dma(struct device *dev, unsigned long pfn)
+{
+	return (dma_addr_t)__pfn_to_bus(pfn);
+}
+#elif defined(__pfn_to_phys)
+static inline dma_addr_t vb2_dc_pfn_to_dma(struct device *dev, unsigned long pfn)
+{
+	return (dma_addr_t)__pfn_to_phys(pfn);
+}
+#else
+static inline dma_addr_t vb2_dc_pfn_to_dma(struct device *dev, unsigned long pfn)
+{
+	/* really, we cannot do anything better at this point */
+	return (dma_addr_t)(pfn) << PAGE_SHIFT;
+}
+#endif
+
 static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
 	unsigned long size, int write)
 {
@@ -548,6 +617,14 @@
 	/* extract page list from userspace mapping */
 	ret = vb2_dc_get_user_pages(start, pages, n_pages, vma, write);
 	if (ret) {
+		unsigned long pfn;
+		if (vb2_dc_get_user_pfn(start, n_pages, vma, &pfn) == 0) {
+			buf->dma_addr = vb2_dc_pfn_to_dma(buf->dev, pfn);
+			buf->size = size;
+			kfree(pages);
+			return buf;
+		}
+
 		pr_err("failed to get user pages\n");
 		goto fail_vma;
 	}
diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c
index ffcb10a..bbf4aea 100644
--- a/drivers/memstick/core/memstick.c
+++ b/drivers/memstick/core/memstick.c
@@ -153,24 +153,24 @@
 	struct memstick_dev *card = container_of(dev, struct memstick_dev,    \
 						 dev);                        \
 	return sprintf(buf, format, card->id.name);                           \
-}
+}                                                                             \
+static DEVICE_ATTR_RO(name);
 
 MEMSTICK_ATTR(type, "%02X");
 MEMSTICK_ATTR(category, "%02X");
 MEMSTICK_ATTR(class, "%02X");
 
-#define MEMSTICK_ATTR_RO(name) __ATTR(name, S_IRUGO, name##_show, NULL)
-
-static struct device_attribute memstick_dev_attrs[] = {
-	MEMSTICK_ATTR_RO(type),
-	MEMSTICK_ATTR_RO(category),
-	MEMSTICK_ATTR_RO(class),
-	__ATTR_NULL
+static struct attribute *memstick_dev_attrs[] = {
+	&dev_attr_type.attr,
+	&dev_attr_category.attr,
+	&dev_attr_class.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(memstick_dev);
 
 static struct bus_type memstick_bus_type = {
 	.name           = "memstick",
-	.dev_attrs      = memstick_dev_attrs,
+	.dev_groups	= memstick_dev_groups,
 	.match          = memstick_bus_match,
 	.uevent         = memstick_uevent,
 	.probe          = memstick_device_probe,
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h
index cbe384f..91614f1 100644
--- a/drivers/message/i2o/core.h
+++ b/drivers/message/i2o/core.h
@@ -33,7 +33,7 @@
 extern void __exit i2o_pci_exit(void);
 
 /* device */
-extern struct device_attribute i2o_device_attrs[];
+extern const struct attribute_group *i2o_device_groups[];
 
 extern void i2o_device_remove(struct i2o_device *);
 extern int i2o_device_parse_lct(struct i2o_controller *);
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index 4547db9..98348f4 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -138,45 +138,55 @@
 }
 
 /**
- *	i2o_device_show_class_id - Displays class id of I2O device
+ *	class_id_show - Displays class id of I2O device
  *	@dev: device of which the class id should be displayed
  *	@attr: pointer to device attribute
  *	@buf: buffer into which the class id should be printed
  *
  *	Returns the number of bytes which are printed into the buffer.
  */
-static ssize_t i2o_device_show_class_id(struct device *dev,
-					struct device_attribute *attr,
-					char *buf)
+static ssize_t class_id_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
 {
 	struct i2o_device *i2o_dev = to_i2o_device(dev);
 
 	sprintf(buf, "0x%03x\n", i2o_dev->lct_data.class_id);
 	return strlen(buf) + 1;
 }
+static DEVICE_ATTR_RO(class_id);
 
 /**
- *	i2o_device_show_tid - Displays TID of I2O device
+ *	tid_show - Displays TID of I2O device
  *	@dev: device of which the TID should be displayed
  *	@attr: pointer to device attribute
  *	@buf: buffer into which the TID should be printed
  *
  *	Returns the number of bytes which are printed into the buffer.
  */
-static ssize_t i2o_device_show_tid(struct device *dev,
-				   struct device_attribute *attr, char *buf)
+static ssize_t tid_show(struct device *dev, struct device_attribute *attr,
+			char *buf)
 {
 	struct i2o_device *i2o_dev = to_i2o_device(dev);
 
 	sprintf(buf, "0x%03x\n", i2o_dev->lct_data.tid);
 	return strlen(buf) + 1;
 }
+static DEVICE_ATTR_RO(tid);
 
 /* I2O device attributes */
-struct device_attribute i2o_device_attrs[] = {
-	__ATTR(class_id, S_IRUGO, i2o_device_show_class_id, NULL),
-	__ATTR(tid, S_IRUGO, i2o_device_show_tid, NULL),
-	__ATTR_NULL
+static struct attribute *i2o_device_attrs[] = {
+	&dev_attr_class_id.attr,
+	&dev_attr_tid.attr,
+	NULL,
+};
+
+static const struct attribute_group i2o_device_group = {
+	.attrs = i2o_device_attrs,
+};
+
+const struct attribute_group *i2o_device_groups[] = {
+	&i2o_device_group,
+	NULL,
 };
 
 /**
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c
index 813eaa3..b6b92d7 100644
--- a/drivers/message/i2o/driver.c
+++ b/drivers/message/i2o/driver.c
@@ -62,7 +62,7 @@
 struct bus_type i2o_bus_type = {
 	.name = "i2o",
 	.match = i2o_bus_match,
-	.dev_attrs = i2o_device_attrs
+	.dev_groups = i2o_device_groups,
 };
 
 /**
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index 5ac3aa4..022b186 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -569,13 +569,25 @@
 	{ .name = "arizona-ldo1" },
 };
 
+static const char *wm5102_supplies[] = {
+	"DBVDD2",
+	"DBVDD3",
+	"CPVDD",
+	"SPKVDDL",
+	"SPKVDDR",
+};
+
 static struct mfd_cell wm5102_devs[] = {
 	{ .name = "arizona-micsupp" },
 	{ .name = "arizona-extcon" },
 	{ .name = "arizona-gpio" },
 	{ .name = "arizona-haptics" },
 	{ .name = "arizona-pwm" },
-	{ .name = "wm5102-codec" },
+	{
+		.name = "wm5102-codec",
+		.parent_supplies = wm5102_supplies,
+		.num_parent_supplies = ARRAY_SIZE(wm5102_supplies),
+	},
 };
 
 static struct mfd_cell wm5110_devs[] = {
@@ -584,7 +596,17 @@
 	{ .name = "arizona-gpio" },
 	{ .name = "arizona-haptics" },
 	{ .name = "arizona-pwm" },
-	{ .name = "wm5110-codec" },
+	{
+		.name = "wm5110-codec",
+		.parent_supplies = wm5102_supplies,
+		.num_parent_supplies = ARRAY_SIZE(wm5102_supplies),
+	},
+};
+
+static const char *wm8997_supplies[] = {
+	"DBVDD2",
+	"CPVDD",
+	"SPKVDD",
 };
 
 static struct mfd_cell wm8997_devs[] = {
@@ -593,7 +615,11 @@
 	{ .name = "arizona-gpio" },
 	{ .name = "arizona-haptics" },
 	{ .name = "arizona-pwm" },
-	{ .name = "wm8997-codec" },
+	{
+		.name = "wm8997-codec",
+		.parent_supplies = wm8997_supplies,
+		.num_parent_supplies = ARRAY_SIZE(wm8997_supplies),
+	},
 };
 
 int arizona_dev_init(struct arizona *arizona)
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 53f371d..b9ce60c 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -480,7 +480,6 @@
 	CLK_MGT_ENTRY(PER6CLK, PLL_DIV, true),
 	CLK_MGT_ENTRY(PER7CLK, PLL_DIV, true),
 	CLK_MGT_ENTRY(LCDCLK, PLL_FIX, true),
-	CLK_MGT_ENTRY(BML8580CLK, PLL_DIV, true),
 	CLK_MGT_ENTRY(BMLCLK, PLL_DIV, true),
 	CLK_MGT_ENTRY(HSITXCLK, PLL_DIV, true),
 	CLK_MGT_ENTRY(HSIRXCLK, PLL_DIV, true),
diff --git a/drivers/mfd/dbx500-prcmu-regs.h b/drivers/mfd/dbx500-prcmu-regs.h
index 4f6f0fa..7cc32a8 100644
--- a/drivers/mfd/dbx500-prcmu-regs.h
+++ b/drivers/mfd/dbx500-prcmu-regs.h
@@ -32,7 +32,6 @@
 #define PRCM_PER7CLK_MGT	(0x040)
 #define PRCM_LCDCLK_MGT		(0x044)
 #define PRCM_BMLCLK_MGT		(0x04C)
-#define PRCM_BML8580CLK_MGT	(0x108)
 #define PRCM_HSITXCLK_MGT	(0x050)
 #define PRCM_HSIRXCLK_MGT	(0x054)
 #define PRCM_HDMICLK_MGT	(0x058)
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c
index 2a9b100..dbbf8ee 100644
--- a/drivers/mfd/mc13xxx-core.c
+++ b/drivers/mfd/mc13xxx-core.c
@@ -158,8 +158,6 @@
 {
 	int ret;
 
-	BUG_ON(!mutex_is_locked(&mc13xxx->lock));
-
 	if (offset > MC13XXX_NUMREGS)
 		return -EINVAL;
 
@@ -172,8 +170,6 @@
 
 int mc13xxx_reg_write(struct mc13xxx *mc13xxx, unsigned int offset, u32 val)
 {
-	BUG_ON(!mutex_is_locked(&mc13xxx->lock));
-
 	dev_vdbg(mc13xxx->dev, "[0x%02x] <- 0x%06x\n", offset, val);
 
 	if (offset > MC13XXX_NUMREGS || val > 0xffffff)
@@ -186,7 +182,6 @@
 int mc13xxx_reg_rmw(struct mc13xxx *mc13xxx, unsigned int offset,
 		u32 mask, u32 val)
 {
-	BUG_ON(!mutex_is_locked(&mc13xxx->lock));
 	BUG_ON(val & ~mask);
 	dev_vdbg(mc13xxx->dev, "[0x%02x] <- 0x%06x (mask: 0x%06x)\n",
 			offset, val, mask);
diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c
index 77189da..5f14ef6 100644
--- a/drivers/mfd/mc13xxx-spi.c
+++ b/drivers/mfd/mc13xxx-spi.c
@@ -94,10 +94,15 @@
 {
 	struct device *dev = context;
 	struct spi_device *spi = to_spi_device(dev);
+	const char *reg = data;
 
 	if (count != 4)
 		return -ENOTSUPP;
 
+	/* include errata fix for spi audio problems */
+	if (*reg == MC13783_AUDIO_CODEC || *reg == MC13783_AUDIO_DAC)
+		spi_write(spi, data, count);
+
 	return spi_write(spi, data, count);
 }
 
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index f421586..adc8ea3 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <linux/irqdomain.h>
 #include <linux/of.h>
+#include <linux/regulator/consumer.h>
 
 static struct device_type mfd_dev_type = {
 	.name	= "mfd_device",
@@ -99,6 +100,13 @@
 	pdev->dev.dma_mask = parent->dma_mask;
 	pdev->dev.dma_parms = parent->dma_parms;
 
+	ret = devm_regulator_bulk_register_supply_alias(
+			&pdev->dev, cell->parent_supplies,
+			parent, cell->parent_supplies,
+			cell->num_parent_supplies);
+	if (ret < 0)
+		goto fail_res;
+
 	if (parent->of_node && cell->of_compatible) {
 		for_each_child_of_node(parent->of_node, np) {
 			if (of_device_is_compatible(np, cell->of_compatible)) {
@@ -112,12 +120,12 @@
 		ret = platform_device_add_data(pdev,
 					cell->platform_data, cell->pdata_size);
 		if (ret)
-			goto fail_res;
+			goto fail_alias;
 	}
 
 	ret = mfd_platform_add_cell(pdev, cell);
 	if (ret)
-		goto fail_res;
+		goto fail_alias;
 
 	for (r = 0; r < cell->num_resources; r++) {
 		res[r].name = cell->resources[r].name;
@@ -152,17 +160,17 @@
 		if (!cell->ignore_resource_conflicts) {
 			ret = acpi_check_resource_conflict(&res[r]);
 			if (ret)
-				goto fail_res;
+				goto fail_alias;
 		}
 	}
 
 	ret = platform_device_add_resources(pdev, res, cell->num_resources);
 	if (ret)
-		goto fail_res;
+		goto fail_alias;
 
 	ret = platform_device_add(pdev);
 	if (ret)
-		goto fail_res;
+		goto fail_alias;
 
 	if (cell->pm_runtime_no_callbacks)
 		pm_runtime_no_callbacks(&pdev->dev);
@@ -171,6 +179,10 @@
 
 	return 0;
 
+fail_alias:
+	devm_regulator_bulk_unregister_supply_alias(&pdev->dev,
+						    cell->parent_supplies,
+						    cell->num_parent_supplies);
 fail_res:
 	kfree(res);
 fail_device:
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 8dacd4c..e760715 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -537,4 +537,5 @@
 source "drivers/misc/altera-stapl/Kconfig"
 source "drivers/misc/mei/Kconfig"
 source "drivers/misc/vmw_vmci/Kconfig"
+source "drivers/misc/mic/Kconfig"
 endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index c235d5b..0b7ea3e 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -53,3 +53,4 @@
 obj-$(CONFIG_VMWARE_VMCI)	+= vmw_vmci/
 obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
 obj-$(CONFIG_SRAM)		+= sram.o
+obj-y				+= mic/
diff --git a/drivers/misc/arm-charlcd.c b/drivers/misc/arm-charlcd.c
index 1256a4b..b7ebf80 100644
--- a/drivers/misc/arm-charlcd.c
+++ b/drivers/misc/arm-charlcd.c
@@ -297,7 +297,7 @@
 	lcd->irq = platform_get_irq(pdev, 0);
 	/* If no IRQ is supplied, we'll survive without it */
 	if (lcd->irq >= 0) {
-		if (request_irq(lcd->irq, charlcd_interrupt, IRQF_DISABLED,
+		if (request_irq(lcd->irq, charlcd_interrupt, 0,
 				DRIVERNAME, lcd)) {
 			ret = -EIO;
 			goto out_no_irq;
diff --git a/drivers/misc/atmel_pwm.c b/drivers/misc/atmel_pwm.c
index 494d050..a6dc56e 100644
--- a/drivers/misc/atmel_pwm.c
+++ b/drivers/misc/atmel_pwm.c
@@ -90,8 +90,10 @@
 	unsigned long	flags;
 	int		status = 0;
 
-	/* insist on PWM init, with this signal pinned out */
-	if (!pwm || !(pwm->mask & 1 << index))
+	if (!pwm)
+		return -EPROBE_DEFER;
+
+	if (!(pwm->mask & 1 << index))
 		return -ENODEV;
 
 	if (index < 0 || index >= PWM_NCHAN || !ch)
diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c
index 057580e..48ea33d 100644
--- a/drivers/misc/bh1780gli.c
+++ b/drivers/misc/bh1780gli.c
@@ -23,6 +23,7 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/of.h>
 
 #define BH1780_REG_CONTROL	0x80
 #define BH1780_REG_PARTID	0x8A
@@ -244,6 +245,15 @@
 	{ },
 };
 
+#ifdef CONFIG_OF
+static const struct of_device_id of_bh1780_match[] = {
+	{ .compatible = "rohm,bh1780gli", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, of_bh1780_match);
+#endif
+
 static struct i2c_driver bh1780_driver = {
 	.probe		= bh1780_probe,
 	.remove		= bh1780_remove,
@@ -251,6 +261,7 @@
 	.driver = {
 		.name = "bh1780",
 		.pm	= &bh1780_pm,
+		.of_match_table = of_match_ptr(of_bh1780_match),
 	},
 };
 
diff --git a/drivers/misc/bmp085.c b/drivers/misc/bmp085.c
index 849e2fe..2704d88 100644
--- a/drivers/misc/bmp085.c
+++ b/drivers/misc/bmp085.c
@@ -374,7 +374,7 @@
 }
 EXPORT_SYMBOL_GPL(bmp085_detect);
 
-static void __init bmp085_get_of_properties(struct bmp085_data *data)
+static void bmp085_get_of_properties(struct bmp085_data *data)
 {
 #ifdef CONFIG_OF
 	struct device_node *np = data->dev->of_node;
diff --git a/drivers/misc/carma/carma-fpga-program.c b/drivers/misc/carma/carma-fpga-program.c
index c6bd7e8..7be8983 100644
--- a/drivers/misc/carma/carma-fpga-program.c
+++ b/drivers/misc/carma/carma-fpga-program.c
@@ -10,6 +10,8 @@
  */
 
 #include <linux/dma-mapping.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/completion.h>
 #include <linux/miscdevice.h>
diff --git a/drivers/misc/carma/carma-fpga.c b/drivers/misc/carma/carma-fpga.c
index 7b56563f..08b18f3 100644
--- a/drivers/misc/carma/carma-fpga.c
+++ b/drivers/misc/carma/carma-fpga.c
@@ -88,6 +88,8 @@
  * interrupt source to the GPIO pin. Tada, we hid the interrupt. :)
  */
 
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/dma-mapping.h>
 #include <linux/miscdevice.h>
diff --git a/drivers/misc/cb710/core.c b/drivers/misc/cb710/core.c
index 2e50f81..fb397e7 100644
--- a/drivers/misc/cb710/core.c
+++ b/drivers/misc/cb710/core.c
@@ -176,7 +176,7 @@
 {
 	struct cb710_chip *chip = pci_get_drvdata(pdev);
 
-	free_irq(pdev->irq, chip);
+	devm_free_irq(&pdev->dev, pdev->irq, chip);
 	pci_save_state(pdev);
 	pci_disable_device(pdev);
 	if (state.event & PM_EVENT_SLEEP)
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 04f2e1f..9536852f 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -96,4 +96,17 @@
 
 	  If unsure, say N.
 
+config EEPROM_SUNXI_SID
+	tristate "Allwinner sunxi security ID support"
+	depends on ARCH_SUNXI && SYSFS
+	help
+	  This is a driver for the 'security ID' available on various Allwinner
+	  devices.
+
+	  Due to the potential risks involved with changing e-fuses,
+	  this driver is read-only.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called sunxi_sid.
+
 endmenu
diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile
index fc1e81d..9507aec 100644
--- a/drivers/misc/eeprom/Makefile
+++ b/drivers/misc/eeprom/Makefile
@@ -4,4 +4,5 @@
 obj-$(CONFIG_EEPROM_MAX6875)	+= max6875.o
 obj-$(CONFIG_EEPROM_93CX6)	+= eeprom_93cx6.o
 obj-$(CONFIG_EEPROM_93XX46)	+= eeprom_93xx46.o
+obj-$(CONFIG_EEPROM_SUNXI_SID)	+= sunxi_sid.o
 obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 5d4fd69..94b8a33 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -428,6 +428,9 @@
 {
 	struct at24_data *at24;
 
+	if (unlikely(off >= attr->size))
+		return -EFBIG;
+
 	at24 = dev_get_drvdata(container_of(kobj, struct device, kobj));
 	return at24_write(at24, buf, off, count);
 }
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index 840b359..4f3bca1 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -462,10 +462,17 @@
 
 /*-------------------------------------------------------------------------*/
 
+static const struct of_device_id at25_of_match[] = {
+	{ .compatible = "atmel,at25", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, at25_of_match);
+
 static struct spi_driver at25_driver = {
 	.driver = {
 		.name		= "at25",
 		.owner		= THIS_MODULE,
+		.of_match_table = at25_of_match,
 	},
 	.probe		= at25_probe,
 	.remove		= at25_remove,
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c
index 94cfc12..3a015ab 100644
--- a/drivers/misc/eeprom/eeprom_93xx46.c
+++ b/drivers/misc/eeprom/eeprom_93xx46.c
@@ -202,7 +202,7 @@
 	edev = dev_get_drvdata(dev);
 
 	if (unlikely(off >= edev->bin.size))
-		return 0;
+		return -EFBIG;
 	if ((off + count) > edev->bin.size)
 		count = edev->bin.size - off;
 	if (unlikely(!count))
diff --git a/drivers/misc/eeprom/sunxi_sid.c b/drivers/misc/eeprom/sunxi_sid.c
new file mode 100644
index 0000000..9c34e57
--- /dev/null
+++ b/drivers/misc/eeprom/sunxi_sid.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2013 Oliver Schinagl <oliver@schinagl.nl>
+ * http://www.linux-sunxi.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This driver exposes the Allwinner security ID, efuses exported in byte-
+ * sized chunks.
+ */
+
+#include <linux/compiler.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
+
+#define DRV_NAME "sunxi-sid"
+
+struct sunxi_sid_data {
+	void __iomem *reg_base;
+	unsigned int keysize;
+};
+
+/* We read the entire key, due to a 32 bit read alignment requirement. Since we
+ * want to return the requested byte, this results in somewhat slower code and
+ * uses 4 times more reads as needed but keeps code simpler. Since the SID is
+ * only very rarely probed, this is not really an issue.
+ */
+static u8 sunxi_sid_read_byte(const struct sunxi_sid_data *sid_data,
+			      const unsigned int offset)
+{
+	u32 sid_key;
+
+	if (offset >= sid_data->keysize)
+		return 0;
+
+	sid_key = ioread32be(sid_data->reg_base + round_down(offset, 4));
+	sid_key >>= (offset % 4) * 8;
+
+	return sid_key; /* Only return the last byte */
+}
+
+static ssize_t sid_read(struct file *fd, struct kobject *kobj,
+			struct bin_attribute *attr, char *buf,
+			loff_t pos, size_t size)
+{
+	struct platform_device *pdev;
+	struct sunxi_sid_data *sid_data;
+	int i;
+
+	pdev = to_platform_device(kobj_to_dev(kobj));
+	sid_data = platform_get_drvdata(pdev);
+
+	if (pos < 0 || pos >= sid_data->keysize)
+		return 0;
+	if (size > sid_data->keysize - pos)
+		size = sid_data->keysize - pos;
+
+	for (i = 0; i < size; i++)
+		buf[i] = sunxi_sid_read_byte(sid_data, pos + i);
+
+	return i;
+}
+
+static struct bin_attribute sid_bin_attr = {
+	.attr = { .name = "eeprom", .mode = S_IRUGO, },
+	.read = sid_read,
+};
+
+static int sunxi_sid_remove(struct platform_device *pdev)
+{
+	device_remove_bin_file(&pdev->dev, &sid_bin_attr);
+	dev_dbg(&pdev->dev, "driver unloaded\n");
+
+	return 0;
+}
+
+static const struct of_device_id sunxi_sid_of_match[] = {
+	{ .compatible = "allwinner,sun4i-sid", .data = (void *)16},
+	{ .compatible = "allwinner,sun7i-a20-sid", .data = (void *)512},
+	{/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, sunxi_sid_of_match);
+
+static int sunxi_sid_probe(struct platform_device *pdev)
+{
+	struct sunxi_sid_data *sid_data;
+	struct resource *res;
+	const struct of_device_id *of_dev_id;
+	u8 *entropy;
+	unsigned int i;
+
+	sid_data = devm_kzalloc(&pdev->dev, sizeof(struct sunxi_sid_data),
+				GFP_KERNEL);
+	if (!sid_data)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	sid_data->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(sid_data->reg_base))
+		return PTR_ERR(sid_data->reg_base);
+
+	of_dev_id = of_match_device(sunxi_sid_of_match, &pdev->dev);
+	if (!of_dev_id)
+		return -ENODEV;
+	sid_data->keysize = (int)of_dev_id->data;
+
+	platform_set_drvdata(pdev, sid_data);
+
+	sid_bin_attr.size = sid_data->keysize;
+	if (device_create_bin_file(&pdev->dev, &sid_bin_attr))
+		return -ENODEV;
+
+	entropy = kzalloc(sizeof(u8) * sid_data->keysize, GFP_KERNEL);
+	for (i = 0; i < sid_data->keysize; i++)
+		entropy[i] = sunxi_sid_read_byte(sid_data, i);
+	add_device_randomness(entropy, sid_data->keysize);
+	kfree(entropy);
+
+	dev_dbg(&pdev->dev, "loaded\n");
+
+	return 0;
+}
+
+static struct platform_driver sunxi_sid_driver = {
+	.probe = sunxi_sid_probe,
+	.remove = sunxi_sid_remove,
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = sunxi_sid_of_match,
+	},
+};
+module_platform_driver(sunxi_sid_driver);
+
+MODULE_AUTHOR("Oliver Schinagl <oliver@schinagl.nl>");
+MODULE_DESCRIPTION("Allwinner sunxi security id driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
index 0346d87..6b3bf9a 100644
--- a/drivers/misc/ibmasm/module.c
+++ b/drivers/misc/ibmasm/module.c
@@ -153,7 +153,6 @@
 error_heartbeat:
 	ibmasm_event_buffer_exit(sp);
 error_eventbuffer:
-	pci_set_drvdata(pdev, NULL);
 	kfree(sp);
 error_kmalloc:
         pci_release_regions(pdev);
@@ -165,7 +164,7 @@
 
 static void ibmasm_remove_one(struct pci_dev *pdev)
 {
-	struct service_processor *sp = (struct service_processor *)pci_get_drvdata(pdev);
+	struct service_processor *sp = pci_get_drvdata(pdev);
 
 	dbg("Unregistering UART\n");
 	ibmasm_unregister_uart(sp);
@@ -182,7 +181,6 @@
 	ibmasm_free_remote_input_dev(sp);
 	iounmap(sp->base_address);
 	ibmasm_event_buffer_exit(sp);
-	pci_set_drvdata(pdev, NULL);
 	kfree(sp);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index 2fc0586..a2edb2e 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -44,13 +44,25 @@
 #include <scsi/scsi_cmnd.h>
 #include <linux/debugfs.h>
 #include <linux/vmalloc.h>
+#include <linux/mman.h>
 
 #ifdef CONFIG_IDE
 #include <linux/ide.h>
 #endif
 
+/*
+ * Make sure our attempts to over run the kernel stack doesn't trigger
+ * a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we
+ * recurse past the end of THREAD_SIZE by default.
+ */
+#if defined(CONFIG_FRAME_WARN) && (CONFIG_FRAME_WARN > 0)
+#define REC_STACK_SIZE (CONFIG_FRAME_WARN / 2)
+#else
+#define REC_STACK_SIZE (THREAD_SIZE / 8)
+#endif
+#define REC_NUM_DEFAULT ((THREAD_SIZE / REC_STACK_SIZE) * 2)
+
 #define DEFAULT_COUNT 10
-#define REC_NUM_DEFAULT 10
 #define EXEC_SIZE 64
 
 enum cname {
@@ -86,6 +98,9 @@
 	CT_EXEC_STACK,
 	CT_EXEC_KMALLOC,
 	CT_EXEC_VMALLOC,
+	CT_EXEC_USERSPACE,
+	CT_ACCESS_USERSPACE,
+	CT_WRITE_RO,
 };
 
 static char* cp_name[] = {
@@ -119,6 +134,9 @@
 	"EXEC_STACK",
 	"EXEC_KMALLOC",
 	"EXEC_VMALLOC",
+	"EXEC_USERSPACE",
+	"ACCESS_USERSPACE",
+	"WRITE_RO",
 };
 
 static struct jprobe lkdtm;
@@ -139,9 +157,10 @@
 
 static u8 data_area[EXEC_SIZE];
 
+static const unsigned long rodata = 0xAA55AA55;
+
 module_param(recur_count, int, 0644);
-MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\
-				 "default is 10");
+MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test");
 module_param(cpoint_name, charp, 0444);
 MODULE_PARM_DESC(cpoint_name, " Crash Point, where kernel is to be crashed");
 module_param(cpoint_type, charp, 0444);
@@ -280,16 +299,16 @@
 	return -EINVAL;
 }
 
-static int recursive_loop(int a)
+static int recursive_loop(int remaining)
 {
-	char buf[1024];
+	char buf[REC_STACK_SIZE];
 
-	memset(buf,0xFF,1024);
-	recur_count--;
-	if (!recur_count)
+	/* Make sure compiler does not optimize this away. */
+	memset(buf, (remaining & 0xff) | 0x1, REC_STACK_SIZE);
+	if (!remaining)
 		return 0;
 	else
-        	return recursive_loop(a);
+		return recursive_loop(remaining - 1);
 }
 
 static void do_nothing(void)
@@ -297,6 +316,14 @@
 	return;
 }
 
+static noinline void corrupt_stack(void)
+{
+	/* Use default char array length that triggers stack protection. */
+	char data[8];
+
+	memset((void *)data, 0, 64);
+}
+
 static void execute_location(void *dst)
 {
 	void (*func)(void) = dst;
@@ -305,6 +332,15 @@
 	func();
 }
 
+static void execute_user_location(void *dst)
+{
+	void (*func)(void) = dst;
+
+	if (copy_to_user(dst, do_nothing, EXEC_SIZE))
+		return;
+	func();
+}
+
 static void lkdtm_do_action(enum ctype which)
 {
 	switch (which) {
@@ -325,15 +361,11 @@
 			;
 		break;
 	case CT_OVERFLOW:
-		(void) recursive_loop(0);
+		(void) recursive_loop(recur_count);
 		break;
-	case CT_CORRUPT_STACK: {
-		/* Make sure the compiler creates and uses an 8 char array. */
-		volatile char data[8];
-
-		memset((void *)data, 0, 64);
+	case CT_CORRUPT_STACK:
+		corrupt_stack();
 		break;
-	}
 	case CT_UNALIGNED_LOAD_STORE_WRITE: {
 		static u8 data[5] __attribute__((aligned(4))) = {1, 2,
 				3, 4, 5};
@@ -401,6 +433,49 @@
 		vfree(vmalloc_area);
 		break;
 	}
+	case CT_EXEC_USERSPACE: {
+		unsigned long user_addr;
+
+		user_addr = vm_mmap(NULL, 0, PAGE_SIZE,
+				    PROT_READ | PROT_WRITE | PROT_EXEC,
+				    MAP_ANONYMOUS | MAP_PRIVATE, 0);
+		if (user_addr >= TASK_SIZE) {
+			pr_warn("Failed to allocate user memory\n");
+			return;
+		}
+		execute_user_location((void *)user_addr);
+		vm_munmap(user_addr, PAGE_SIZE);
+		break;
+	}
+	case CT_ACCESS_USERSPACE: {
+		unsigned long user_addr, tmp;
+		unsigned long *ptr;
+
+		user_addr = vm_mmap(NULL, 0, PAGE_SIZE,
+				    PROT_READ | PROT_WRITE | PROT_EXEC,
+				    MAP_ANONYMOUS | MAP_PRIVATE, 0);
+		if (user_addr >= TASK_SIZE) {
+			pr_warn("Failed to allocate user memory\n");
+			return;
+		}
+
+		ptr = (unsigned long *)user_addr;
+		tmp = *ptr;
+		tmp += 0xc0dec0de;
+		*ptr = tmp;
+
+		vm_munmap(user_addr, PAGE_SIZE);
+
+		break;
+	}
+	case CT_WRITE_RO: {
+		unsigned long *ptr;
+
+		ptr = (unsigned long *)&rodata;
+		*ptr ^= 0xabcd1234;
+
+		break;
+	}
 	case CT_NONE:
 	default:
 		break;
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index f6ff711..d22c686 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -58,6 +58,7 @@
 	dev->iamthif_state = MEI_IAMTHIF_IDLE;
 	dev->iamthif_timer = 0;
 	dev->iamthif_stall_timer = 0;
+	dev->iamthif_open_count = 0;
 }
 
 /**
@@ -78,8 +79,10 @@
 
 	i = mei_me_cl_by_uuid(dev, &mei_amthif_guid);
 	if (i < 0) {
-		dev_info(&dev->pdev->dev, "amthif: failed to find the client\n");
-		return -ENOENT;
+		ret = i;
+		dev_info(&dev->pdev->dev,
+			"amthif: failed to find the client %d\n", ret);
+		return ret;
 	}
 
 	cl->me_client_id = dev->me_clients[i].client_id;
@@ -106,8 +109,9 @@
 	ret = mei_cl_link(cl, MEI_IAMTHIF_HOST_CLIENT_ID);
 
 	if (ret < 0) {
-		dev_err(&dev->pdev->dev, "amthif: failed link client\n");
-		return -ENOENT;
+		dev_err(&dev->pdev->dev,
+			"amthif: failed link client %d\n", ret);
+		return ret;
 	}
 
 	cl->state = MEI_FILE_CONNECTING;
@@ -313,13 +317,13 @@
 		mei_hdr.me_addr = dev->iamthif_cl.me_client_id;
 		mei_hdr.reserved = 0;
 		dev->iamthif_msg_buf_index += mei_hdr.length;
-		if (mei_write_message(dev, &mei_hdr,
-					(unsigned char *)dev->iamthif_msg_buf))
-			return -ENODEV;
+		ret = mei_write_message(dev, &mei_hdr, dev->iamthif_msg_buf);
+		if (ret)
+			return ret;
 
 		if (mei_hdr.msg_complete) {
 			if (mei_cl_flow_ctrl_reduce(&dev->iamthif_cl))
-				return -ENODEV;
+				return -EIO;
 			dev->iamthif_flow_control_pending = true;
 			dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
 			dev_dbg(&dev->pdev->dev, "add amthif cb to write waiting list\n");
@@ -459,6 +463,16 @@
 	struct mei_msg_hdr mei_hdr;
 	size_t len = dev->iamthif_msg_buf_size - dev->iamthif_msg_buf_index;
 	u32 msg_slots = mei_data2slots(len);
+	int rets;
+
+	rets = mei_cl_flow_ctrl_creds(cl);
+	if (rets < 0)
+		return rets;
+
+	if (rets == 0) {
+		cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
+		return 0;
+	}
 
 	mei_hdr.host_addr = cl->host_client_id;
 	mei_hdr.me_addr = cl->me_client_id;
@@ -481,16 +495,17 @@
 	dev_dbg(&dev->pdev->dev, MEI_HDR_FMT,  MEI_HDR_PRM(&mei_hdr));
 
 	*slots -=  msg_slots;
-	if (mei_write_message(dev, &mei_hdr,
-		dev->iamthif_msg_buf + dev->iamthif_msg_buf_index)) {
-			dev->iamthif_state = MEI_IAMTHIF_IDLE;
-			cl->status = -ENODEV;
-			list_del(&cb->list);
-			return -ENODEV;
+	rets = mei_write_message(dev, &mei_hdr,
+			dev->iamthif_msg_buf + dev->iamthif_msg_buf_index);
+	if (rets) {
+		dev->iamthif_state = MEI_IAMTHIF_IDLE;
+		cl->status = rets;
+		list_del(&cb->list);
+		return rets;
 	}
 
 	if (mei_cl_flow_ctrl_reduce(cl))
-		return -ENODEV;
+		return -EIO;
 
 	dev->iamthif_msg_buf_index += mei_hdr.length;
 	cl->status = 0;
@@ -720,8 +735,8 @@
 */
 int mei_amthif_release(struct mei_device *dev, struct file *file)
 {
-	if (dev->open_handle_count > 0)
-		dev->open_handle_count--;
+	if (dev->iamthif_open_count > 0)
+		dev->iamthif_open_count--;
 
 	if (dev->iamthif_file_object == file &&
 	    dev->iamthif_state != MEI_IAMTHIF_IDLE) {
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index cd2033c..4bc7d62 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -245,7 +245,7 @@
 	/* Check if we have an ME client device */
 	id = mei_me_cl_by_id(dev, cl->me_client_id);
 	if (id < 0)
-		return -ENODEV;
+		return id;
 
 	if (length > dev->me_clients[id].props.max_msg_length)
 		return -EINVAL;
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index e0684b4..87c96e4 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -187,10 +187,14 @@
  */
 int mei_cl_flush_queues(struct mei_cl *cl)
 {
+	struct mei_device *dev;
+
 	if (WARN_ON(!cl || !cl->dev))
 		return -EINVAL;
 
-	dev_dbg(&cl->dev->pdev->dev, "remove list entry belonging to cl\n");
+	dev = cl->dev;
+
+	cl_dbg(dev, cl, "remove list entry belonging to cl\n");
 	mei_io_list_flush(&cl->dev->read_list, cl);
 	mei_io_list_flush(&cl->dev->write_list, cl);
 	mei_io_list_flush(&cl->dev->write_waiting_list, cl);
@@ -271,6 +275,7 @@
 int mei_cl_link(struct mei_cl *cl, int id)
 {
 	struct mei_device *dev;
+	long open_handle_count;
 
 	if (WARN_ON(!cl || !cl->dev))
 		return -EINVAL;
@@ -284,7 +289,14 @@
 
 	if (id >= MEI_CLIENTS_MAX) {
 		dev_err(&dev->pdev->dev, "id exceded %d", MEI_CLIENTS_MAX) ;
-		return -ENOENT;
+		return -EMFILE;
+	}
+
+	open_handle_count = dev->open_handle_count + dev->iamthif_open_count;
+	if (open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT) {
+		dev_err(&dev->pdev->dev, "open_handle_count exceded %d",
+			MEI_MAX_OPEN_HANDLE_COUNT);
+		return -EMFILE;
 	}
 
 	dev->open_handle_count++;
@@ -296,7 +308,7 @@
 
 	cl->state = MEI_FILE_INITIALIZING;
 
-	dev_dbg(&dev->pdev->dev, "link cl host id = %d\n", cl->host_client_id);
+	cl_dbg(dev, cl, "link cl\n");
 	return 0;
 }
 
@@ -308,7 +320,6 @@
 int mei_cl_unlink(struct mei_cl *cl)
 {
 	struct mei_device *dev;
-	struct mei_cl *pos, *next;
 
 	/* don't shout on error exit path */
 	if (!cl)
@@ -320,14 +331,21 @@
 
 	dev = cl->dev;
 
-	list_for_each_entry_safe(pos, next, &dev->file_list, link) {
-		if (cl->host_client_id == pos->host_client_id) {
-			dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n",
-				pos->host_client_id, pos->me_client_id);
-			list_del_init(&pos->link);
-			break;
-		}
-	}
+	cl_dbg(dev, cl, "unlink client");
+
+	if (dev->open_handle_count > 0)
+		dev->open_handle_count--;
+
+	/* never clear the 0 bit */
+	if (cl->host_client_id)
+		clear_bit(cl->host_client_id, dev->host_clients_map);
+
+	list_del_init(&cl->link);
+
+	cl->state = MEI_FILE_INITIALIZING;
+
+	list_del_init(&cl->link);
+
 	return 0;
 }
 
@@ -341,17 +359,6 @@
 
 	mutex_lock(&dev->device_lock);
 
-	bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
-	dev->open_handle_count = 0;
-
-	/*
-	 * Reserving the first three client IDs
-	 * 0: Reserved for MEI Bus Message communications
-	 * 1: Reserved for Watchdog
-	 * 2: Reserved for AMTHI
-	 */
-	bitmap_set(dev->host_clients_map, 0, 3);
-
 	for (i = 0; i < dev->me_clients_num; i++) {
 		client_props = &dev->me_clients[i].props;
 
@@ -390,6 +397,8 @@
 
 	dev = cl->dev;
 
+	cl_dbg(dev, cl, "disconnecting");
+
 	if (cl->state != MEI_FILE_DISCONNECTING)
 		return 0;
 
@@ -402,13 +411,13 @@
 		dev->hbuf_is_ready = false;
 		if (mei_hbm_cl_disconnect_req(dev, cl)) {
 			rets = -ENODEV;
-			dev_err(&dev->pdev->dev, "failed to disconnect.\n");
+			cl_err(dev, cl, "failed to disconnect.\n");
 			goto free;
 		}
 		mdelay(10); /* Wait for hardware disconnection ready */
 		list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
 	} else {
-		dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n");
+		cl_dbg(dev, cl, "add disconnect cb to control write list\n");
 		list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
 
 	}
@@ -421,18 +430,17 @@
 	mutex_lock(&dev->device_lock);
 	if (MEI_FILE_DISCONNECTED == cl->state) {
 		rets = 0;
-		dev_dbg(&dev->pdev->dev, "successfully disconnected from FW client.\n");
+		cl_dbg(dev, cl, "successfully disconnected from FW client.\n");
 	} else {
 		rets = -ENODEV;
 		if (MEI_FILE_DISCONNECTED != cl->state)
-			dev_dbg(&dev->pdev->dev, "wrong status client disconnect.\n");
+			cl_err(dev, cl, "wrong status client disconnect.\n");
 
 		if (err)
-			dev_dbg(&dev->pdev->dev,
-					"wait failed disconnect err=%08x\n",
+			cl_dbg(dev, cl, "wait failed disconnect err=%08x\n",
 					err);
 
-		dev_dbg(&dev->pdev->dev, "failed to disconnect from FW client.\n");
+		cl_err(dev, cl, "failed to disconnect from FW client.\n");
 	}
 
 	mei_io_list_flush(&dev->ctrl_rd_list, cl);
@@ -639,13 +647,12 @@
 		return -ENODEV;
 
 	if (cl->read_cb) {
-		dev_dbg(&dev->pdev->dev, "read is pending.\n");
+		cl_dbg(dev, cl, "read is pending.\n");
 		return -EBUSY;
 	}
 	i = mei_me_cl_by_id(dev, cl->me_client_id);
 	if (i < 0) {
-		dev_err(&dev->pdev->dev, "no such me client %d\n",
-			cl->me_client_id);
+		cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
 		return  -ENODEV;
 	}
 
@@ -664,6 +671,7 @@
 	if (dev->hbuf_is_ready) {
 		dev->hbuf_is_ready = false;
 		if (mei_hbm_cl_flow_control_req(dev, cl)) {
+			cl_err(dev, cl, "flow control send failed\n");
 			rets = -ENODEV;
 			goto err;
 		}
@@ -691,10 +699,32 @@
 int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
 				     s32 *slots, struct mei_cl_cb *cmpl_list)
 {
-	struct mei_device *dev = cl->dev;
+	struct mei_device *dev;
+	struct mei_msg_data *buf;
 	struct mei_msg_hdr mei_hdr;
-	size_t len = cb->request_buffer.size - cb->buf_idx;
-	u32 msg_slots = mei_data2slots(len);
+	size_t len;
+	u32 msg_slots;
+	int rets;
+
+
+	if (WARN_ON(!cl || !cl->dev))
+		return -ENODEV;
+
+	dev = cl->dev;
+
+	buf = &cb->request_buffer;
+
+	rets = mei_cl_flow_ctrl_creds(cl);
+	if (rets < 0)
+		return rets;
+
+	if (rets == 0) {
+		cl_dbg(dev, cl,	"No flow control credentials: not sending.\n");
+		return 0;
+	}
+
+	len = buf->size - cb->buf_idx;
+	msg_slots = mei_data2slots(len);
 
 	mei_hdr.host_addr = cl->host_client_id;
 	mei_hdr.me_addr = cl->me_client_id;
@@ -714,16 +744,15 @@
 		return 0;
 	}
 
-	dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n",
+	cl_dbg(dev, cl, "buf: size = %d idx = %lu\n",
 			cb->request_buffer.size, cb->buf_idx);
-	dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(&mei_hdr));
 
 	*slots -=  msg_slots;
-	if (mei_write_message(dev, &mei_hdr,
-			cb->request_buffer.data + cb->buf_idx)) {
-		cl->status = -ENODEV;
+	rets = mei_write_message(dev, &mei_hdr, buf->data + cb->buf_idx);
+	if (rets) {
+		cl->status = rets;
 		list_move_tail(&cb->list, &cmpl_list->list);
-		return -ENODEV;
+		return rets;
 	}
 
 	cl->status = 0;
@@ -732,7 +761,7 @@
 
 	if (mei_hdr.msg_complete) {
 		if (mei_cl_flow_ctrl_reduce(cl))
-			return -ENODEV;
+			return -EIO;
 		list_move_tail(&cb->list, &dev->write_waiting_list.list);
 	}
 
@@ -767,7 +796,7 @@
 
 	buf = &cb->request_buffer;
 
-	dev_dbg(&dev->pdev->dev, "mei_cl_write %d\n", buf->size);
+	cl_dbg(dev, cl, "mei_cl_write %d\n", buf->size);
 
 
 	cb->fop_type = MEI_FOP_WRITE;
@@ -800,14 +829,10 @@
 	mei_hdr.me_addr = cl->me_client_id;
 	mei_hdr.reserved = 0;
 
-	dev_dbg(&dev->pdev->dev, "write " MEI_HDR_FMT "\n",
-		MEI_HDR_PRM(&mei_hdr));
 
-
-	if (mei_write_message(dev, &mei_hdr, buf->data)) {
-		rets = -EIO;
+	rets = mei_write_message(dev, &mei_hdr, buf->data);
+	if (rets)
 		goto err;
-	}
 
 	cl->writing_state = MEI_WRITING;
 	cb->buf_idx = mei_hdr.length;
@@ -898,11 +923,11 @@
 	struct mei_cl *cl, *next;
 	list_for_each_entry_safe(cl, next, &dev->file_list, link) {
 		if (waitqueue_active(&cl->rx_wait)) {
-			dev_dbg(&dev->pdev->dev, "Waking up reading client!\n");
+			cl_dbg(dev, cl, "Waking up reading client!\n");
 			wake_up_interruptible(&cl->rx_wait);
 		}
 		if (waitqueue_active(&cl->tx_wait)) {
-			dev_dbg(&dev->pdev->dev, "Waking up writing client!\n");
+			cl_dbg(dev, cl, "Waking up writing client!\n");
 			wake_up_interruptible(&cl->tx_wait);
 		}
 	}
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index 892cc42..c8396e5 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -115,4 +115,13 @@
 void mei_cl_all_wakeup(struct mei_device *dev);
 void mei_cl_all_write_clear(struct mei_device *dev);
 
+#define MEI_CL_FMT "cl:host=%02d me=%02d "
+#define MEI_CL_PRM(cl) (cl)->host_client_id, (cl)->me_client_id
+
+#define cl_dbg(dev, cl, format, arg...) \
+	dev_dbg(&(dev)->pdev->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg)
+
+#define cl_err(dev, cl, format, arg...) \
+	dev_err(&(dev)->pdev->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg)
+
 #endif /* _MEI_CLIENT_H_ */
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index 0a044832..9b3a0fb 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -49,7 +49,7 @@
 	kfree(dev->me_clients);
 	dev->me_clients = NULL;
 
-	dev_dbg(&dev->pdev->dev, "memory allocation for ME clients size=%zd.\n",
+	dev_dbg(&dev->pdev->dev, "memory allocation for ME clients size=%ld.\n",
 		dev->me_clients_num * sizeof(struct mei_me_client));
 	/* allocate storage for ME clients representation */
 	clients = kcalloc(dev->me_clients_num,
@@ -174,7 +174,7 @@
 		dev_err(&dev->pdev->dev, "version message write failed\n");
 		dev->dev_state = MEI_DEV_RESETTING;
 		mei_reset(dev, 1);
-		return -ENODEV;
+		return -EIO;
 	}
 	dev->hbm_state = MEI_HBM_START;
 	dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
@@ -677,7 +677,10 @@
 
 	case HOST_ENUM_RES_CMD:
 		enum_res = (struct hbm_host_enum_response *) mei_msg;
-		memcpy(dev->me_clients_map, enum_res->valid_addresses, 32);
+		BUILD_BUG_ON(sizeof(dev->me_clients_map)
+				< sizeof(enum_res->valid_addresses));
+		memcpy(dev->me_clients_map, enum_res->valid_addresses,
+			sizeof(enum_res->valid_addresses));
 		if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
 		    dev->hbm_state == MEI_HBM_ENUM_CLIENTS) {
 				dev->init_clients_timer = 0;
diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index 6a203b6..6c0fde5 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -110,6 +110,7 @@
 #define MEI_DEV_ID_PPT_3      0x1DBA  /* Panther Point */
 
 #define MEI_DEV_ID_LPT        0x8C3A  /* Lynx Point */
+#define MEI_DEV_ID_LPT_W      0x8D3A  /* Lynx Point - Wellsburg */
 #define MEI_DEV_ID_LPT_LP     0x9C3A  /* Lynx Point LP */
 /*
  * MEI HW Section
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 6197018..f7f3abb 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -68,6 +68,14 @@
 	mei_io_list_init(&dev->amthif_cmd_list);
 	mei_io_list_init(&dev->amthif_rd_complete_list);
 
+	bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
+	dev->open_handle_count = 0;
+
+	/*
+	 * Reserving the first client ID
+	 * 0: Reserved for MEI Bus Message communications
+	 */
+	bitmap_set(dev->host_clients_map, 0, 1);
 }
 EXPORT_SYMBOL_GPL(mei_device_init);
 
@@ -139,6 +147,10 @@
 			dev->dev_state != MEI_DEV_POWER_DOWN &&
 			dev->dev_state != MEI_DEV_POWER_UP);
 
+	if (unexpected)
+		dev_warn(&dev->pdev->dev, "unexpected reset: dev_state = %s\n",
+			 mei_dev_state_str(dev->dev_state));
+
 	ret = mei_hw_reset(dev, interrupts_enabled);
 	if (ret) {
 		dev_err(&dev->pdev->dev, "hw reset failed disabling the device\n");
@@ -165,12 +177,7 @@
 		/* remove entry if already in list */
 		dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n");
 		mei_cl_unlink(&dev->wd_cl);
-		if (dev->open_handle_count > 0)
-			dev->open_handle_count--;
 		mei_cl_unlink(&dev->iamthif_cl);
-		if (dev->open_handle_count > 0)
-			dev->open_handle_count--;
-
 		mei_amthif_reset_params(dev);
 		memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg));
 	}
@@ -182,10 +189,6 @@
 	dev->rd_msg_hdr = 0;
 	dev->wd_pending = false;
 
-	if (unexpected)
-		dev_warn(&dev->pdev->dev, "unexpected reset: dev_state = %s\n",
-			 mei_dev_state_str(dev->dev_state));
-
 	if (!interrupts_enabled) {
 		dev_dbg(&dev->pdev->dev, "intr not enabled end of reset\n");
 		return;
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 4b59cb7..7a95c07 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -113,13 +113,13 @@
 
 		if (cb->response_buffer.size == 0 ||
 		    cb->response_buffer.data == NULL) {
-			dev_err(&dev->pdev->dev, "response buffer is not allocated.\n");
+			cl_err(dev, cl, "response buffer is not allocated.\n");
 			list_del(&cb->list);
 			return -ENOMEM;
 		}
 
 		if (cb->response_buffer.size < mei_hdr->length + cb->buf_idx) {
-			dev_dbg(&dev->pdev->dev, "message overflow. size %d len %d idx %ld\n",
+			cl_dbg(dev, cl, "message overflow. size %d len %d idx %ld\n",
 				cb->response_buffer.size,
 				mei_hdr->length, cb->buf_idx);
 			buffer = krealloc(cb->response_buffer.data,
@@ -127,7 +127,7 @@
 					  GFP_KERNEL);
 
 			if (!buffer) {
-				dev_err(&dev->pdev->dev, "allocation failed.\n");
+				cl_err(dev, cl, "allocation failed.\n");
 				list_del(&cb->list);
 				return -ENOMEM;
 			}
@@ -143,9 +143,7 @@
 		if (mei_hdr->msg_complete) {
 			cl->status = 0;
 			list_del(&cb->list);
-			dev_dbg(&dev->pdev->dev, "completed read H cl = %d, ME cl = %d, length = %lu\n",
-				cl->host_client_id,
-				cl->me_client_id,
+			cl_dbg(dev, cl, "completed read length = %lu\n",
 				cb->buf_idx);
 			list_add_tail(&cb->list, &complete_list->list);
 		}
@@ -218,9 +216,11 @@
 			   s32 *slots, struct mei_cl_cb *cmpl_list)
 {
 	struct mei_device *dev = cl->dev;
-
 	u32 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
 
+	int ret;
+
+
 	if (*slots < msg_slots) {
 		/* return the cancel routine */
 		list_del(&cb->list);
@@ -229,12 +229,14 @@
 
 	*slots -= msg_slots;
 
-	if (mei_hbm_cl_flow_control_req(dev, cl)) {
-		cl->status = -ENODEV;
+	ret = mei_hbm_cl_flow_control_req(dev, cl);
+	if (ret) {
+		cl->status = ret;
 		cb->buf_idx = 0;
 		list_move_tail(&cb->list, &cmpl_list->list);
-		return -ENODEV;
+		return ret;
 	}
+
 	list_move_tail(&cb->list, &dev->read_list.list);
 
 	return 0;
@@ -256,6 +258,7 @@
 			   s32 *slots, struct mei_cl_cb *cmpl_list)
 {
 	struct mei_device *dev = cl->dev;
+	int ret;
 
 	u32 msg_slots =
 		mei_data2slots(sizeof(struct hbm_client_connect_request));
@@ -270,11 +273,12 @@
 
 	cl->state = MEI_FILE_CONNECTING;
 
-	if (mei_hbm_cl_connect_req(dev, cl)) {
-		cl->status = -ENODEV;
+	ret = mei_hbm_cl_connect_req(dev, cl);
+	if (ret) {
+		cl->status = ret;
 		cb->buf_idx = 0;
 		list_del(&cb->list);
-		return -ENODEV;
+		return ret;
 	}
 
 	list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
@@ -345,14 +349,14 @@
 
 	/* decide where to read the message too */
 	if (!mei_hdr->host_addr) {
-		dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_bus_message.\n");
+		dev_dbg(&dev->pdev->dev, "call mei_hbm_dispatch.\n");
 		mei_hbm_dispatch(dev, mei_hdr);
-		dev_dbg(&dev->pdev->dev, "end mei_irq_thread_read_bus_message.\n");
+		dev_dbg(&dev->pdev->dev, "end mei_hbm_dispatch.\n");
 	} else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id &&
 		   (MEI_FILE_CONNECTED == dev->iamthif_cl.state) &&
 		   (dev->iamthif_state == MEI_IAMTHIF_READING)) {
 
-		dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n");
+		dev_dbg(&dev->pdev->dev, "call mei_amthif_irq_read_msg.\n");
 		dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr));
 
 		ret = mei_amthif_irq_read_msg(dev, mei_hdr, cmpl_list);
@@ -423,12 +427,12 @@
 		if (MEI_WRITING == cl->writing_state &&
 		    cb->fop_type == MEI_FOP_WRITE &&
 		    cl != &dev->iamthif_cl) {
-			dev_dbg(&dev->pdev->dev, "MEI WRITE COMPLETE\n");
+			cl_dbg(dev, cl, "MEI WRITE COMPLETE\n");
 			cl->writing_state = MEI_WRITE_COMPLETE;
 			list_add_tail(&cb->list, &cmpl_list->list);
 		}
 		if (cl == &dev->iamthif_cl) {
-			dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
+			cl_dbg(dev, cl, "check iamthif flow control.\n");
 			if (dev->iamthif_flow_control_pending) {
 				ret = mei_amthif_irq_read(dev, &slots);
 				if (ret)
@@ -509,13 +513,6 @@
 		cl = cb->cl;
 		if (cl == NULL)
 			continue;
-		if (mei_cl_flow_ctrl_creds(cl) <= 0) {
-			dev_dbg(&dev->pdev->dev,
-				"No flow control credentials for client %d, not sending.\n",
-				cl->host_client_id);
-			continue;
-		}
-
 		if (cl == &dev->iamthif_cl)
 			ret = mei_amthif_irq_write_complete(cl, cb,
 						&slots, cmpl_list);
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index cabeddd..9661a81 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -60,48 +60,45 @@
 
 	int err;
 
-	err = -ENODEV;
 	if (!misc->parent)
-		goto out;
+		return -ENODEV;
 
 	pdev = container_of(misc->parent, struct pci_dev, dev);
 
 	dev = pci_get_drvdata(pdev);
 	if (!dev)
-		goto out;
+		return -ENODEV;
 
 	mutex_lock(&dev->device_lock);
-	err = -ENOMEM;
-	cl = mei_cl_allocate(dev);
-	if (!cl)
-		goto out_unlock;
+
+	cl = NULL;
 
 	err = -ENODEV;
 	if (dev->dev_state != MEI_DEV_ENABLED) {
 		dev_dbg(&dev->pdev->dev, "dev_state != MEI_ENABLED  dev_state = %s\n",
 		    mei_dev_state_str(dev->dev_state));
-		goto out_unlock;
-	}
-	err = -EMFILE;
-	if (dev->open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT) {
-		dev_err(&dev->pdev->dev, "open_handle_count exceded %d",
-			MEI_MAX_OPEN_HANDLE_COUNT);
-		goto out_unlock;
+		goto err_unlock;
 	}
 
+	err = -ENOMEM;
+	cl = mei_cl_allocate(dev);
+	if (!cl)
+		goto err_unlock;
+
+	/* open_handle_count check is handled in the mei_cl_link */
 	err = mei_cl_link(cl, MEI_HOST_CLIENT_ID_ANY);
 	if (err)
-		goto out_unlock;
+		goto err_unlock;
 
 	file->private_data = cl;
+
 	mutex_unlock(&dev->device_lock);
 
 	return nonseekable_open(inode, file);
 
-out_unlock:
+err_unlock:
 	mutex_unlock(&dev->device_lock);
 	kfree(cl);
-out:
 	return err;
 }
 
@@ -144,10 +141,6 @@
 	    cl->host_client_id,
 	    cl->me_client_id);
 
-	if (dev->open_handle_count > 0) {
-		clear_bit(cl->host_client_id, dev->host_clients_map);
-		dev->open_handle_count--;
-	}
 	mei_cl_unlink(cl);
 
 
@@ -165,10 +158,7 @@
 
 	file->private_data = NULL;
 
-	if (cb) {
-		mei_io_cb_free(cb);
-		cb = NULL;
-	}
+	mei_io_cb_free(cb);
 
 	kfree(cl);
 out:
@@ -203,12 +193,18 @@
 
 	dev = cl->dev;
 
+
 	mutex_lock(&dev->device_lock);
 	if (dev->dev_state != MEI_DEV_ENABLED) {
 		rets = -ENODEV;
 		goto out;
 	}
 
+	if (length == 0) {
+		rets = 0;
+		goto out;
+	}
+
 	if (cl == &dev->iamthif_cl) {
 		rets = mei_amthif_read(dev, file, ubuf, length, offset);
 		goto out;
@@ -347,8 +343,14 @@
 		rets = -ENODEV;
 		goto out;
 	}
-	if (length > dev->me_clients[id].props.max_msg_length || length <= 0) {
-		rets = -EMSGSIZE;
+
+	if (length == 0) {
+		rets = 0;
+		goto out;
+	}
+
+	if (length > dev->me_clients[id].props.max_msg_length) {
+		rets = -EFBIG;
 		goto out;
 	}
 
@@ -401,8 +403,11 @@
 		goto out;
 
 	rets = copy_from_user(write_cb->request_buffer.data, ubuf, length);
-	if (rets)
+	if (rets) {
+		dev_err(&dev->pdev->dev, "failed to copy data from userland\n");
+		rets = -EFAULT;
 		goto out;
+	}
 
 	if (cl == &dev->iamthif_cl) {
 		rets = mei_amthif_write(dev, write_cb);
@@ -489,11 +494,11 @@
 			rets = -ENODEV;
 			goto end;
 		}
-		clear_bit(cl->host_client_id, dev->host_clients_map);
 		mei_cl_unlink(cl);
 
 		kfree(cl);
 		cl = NULL;
+		dev->iamthif_open_count++;
 		file->private_data = &dev->iamthif_cl;
 
 		client = &data->out_client_properties;
@@ -564,7 +569,7 @@
 	dev_dbg(&dev->pdev->dev, "copy connect data from user\n");
 	if (copy_from_user(connect_data, (char __user *)data,
 				sizeof(struct mei_connect_client_data))) {
-		dev_dbg(&dev->pdev->dev, "failed to copy data from userland\n");
+		dev_err(&dev->pdev->dev, "failed to copy data from userland\n");
 		rets = -EFAULT;
 		goto out;
 	}
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 456b322..406f68e 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -414,6 +414,7 @@
 	struct file *iamthif_file_object;
 	struct mei_cl iamthif_cl;
 	struct mei_cl_cb *iamthif_current_cb;
+	long iamthif_open_count;
 	int iamthif_mtu;
 	unsigned long iamthif_timer;
 	u32 iamthif_stall_timer;
diff --git a/drivers/misc/mei/nfc.c b/drivers/misc/mei/nfc.c
index d0c6907..994ca4a 100644
--- a/drivers/misc/mei/nfc.c
+++ b/drivers/misc/mei/nfc.c
@@ -485,8 +485,11 @@
 	if (ndev->cl_info)
 		return 0;
 
-	cl_info = mei_cl_allocate(dev);
-	cl = mei_cl_allocate(dev);
+	ndev->cl_info = mei_cl_allocate(dev);
+	ndev->cl = mei_cl_allocate(dev);
+
+	cl = ndev->cl;
+	cl_info = ndev->cl_info;
 
 	if (!cl || !cl_info) {
 		ret = -ENOMEM;
@@ -527,10 +530,9 @@
 
 	cl->device_uuid = mei_nfc_guid;
 
+
 	list_add_tail(&cl->device_link, &dev->device_list);
 
-	ndev->cl_info = cl_info;
-	ndev->cl = cl;
 	ndev->req_id = 1;
 
 	INIT_WORK(&ndev->init_work, mei_nfc_init);
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 1b3844e..b96205a 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -77,6 +77,7 @@
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_2)},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_3)},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_W)},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_LP)},
 
 	/* required last entry */
@@ -189,7 +190,7 @@
 
 	schedule_delayed_work(&dev->timer_work, HZ);
 
-	pr_debug("initialization successful.\n");
+	dev_dbg(&pdev->dev, "initialization successful.\n");
 
 	return 0;
 
@@ -231,7 +232,7 @@
 	hw = to_me_hw(dev);
 
 
-	dev_err(&pdev->dev, "stop\n");
+	dev_dbg(&pdev->dev, "stop\n");
 	mei_stop(dev);
 
 	/* disable interrupts */
@@ -239,7 +240,6 @@
 
 	free_irq(pdev->irq, dev);
 	pci_disable_msi(pdev);
-	pci_set_drvdata(pdev, NULL);
 
 	if (hw->mem_addr)
 		pci_iounmap(pdev, hw->mem_addr);
@@ -262,7 +262,7 @@
 	if (!dev)
 		return -ENODEV;
 
-	dev_err(&pdev->dev, "suspend\n");
+	dev_dbg(&pdev->dev, "suspend\n");
 
 	mei_stop(dev);
 
diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c
index b892143..9e35421 100644
--- a/drivers/misc/mei/wd.c
+++ b/drivers/misc/mei/wd.c
@@ -60,7 +60,7 @@
 int mei_wd_host_init(struct mei_device *dev)
 {
 	struct mei_cl *cl = &dev->wd_cl;
-	int i;
+	int id;
 	int ret;
 
 	mei_cl_init(cl, dev);
@@ -70,19 +70,19 @@
 
 
 	/* check for valid client id */
-	i = mei_me_cl_by_uuid(dev, &mei_wd_guid);
-	if (i < 0) {
+	id = mei_me_cl_by_uuid(dev, &mei_wd_guid);
+	if (id < 0) {
 		dev_info(&dev->pdev->dev, "wd: failed to find the client\n");
-		return -ENOENT;
+		return id;
 	}
 
-	cl->me_client_id = dev->me_clients[i].client_id;
+	cl->me_client_id = dev->me_clients[id].client_id;
 
 	ret = mei_cl_link(cl, MEI_WD_HOST_CLIENT_ID);
 
 	if (ret < 0) {
 		dev_info(&dev->pdev->dev, "wd: failed link client\n");
-		return -ENOENT;
+		return ret;
 	}
 
 	cl->state = MEI_FILE_CONNECTING;
diff --git a/drivers/misc/mic/Kconfig b/drivers/misc/mic/Kconfig
new file mode 100644
index 0000000..e42b331
--- /dev/null
+++ b/drivers/misc/mic/Kconfig
@@ -0,0 +1,39 @@
+comment "Intel MIC Host Driver"
+
+config INTEL_MIC_HOST
+	tristate "Intel MIC Host Driver"
+	depends on 64BIT && PCI && X86
+	select VHOST_RING
+	default N
+	help
+	  This enables Host Driver support for the Intel Many Integrated
+	  Core (MIC) family of PCIe form factor coprocessor devices that
+	  run a 64 bit Linux OS. The driver manages card OS state and
+	  enables communication between host and card. Intel MIC X100
+	  devices are currently supported.
+
+	  If you are building a host kernel with an Intel MIC device then
+	  say M (recommended) or Y, else say N. If unsure say N.
+
+	  More information about the Intel MIC family as well as the Linux
+	  OS and tools for MIC to use with this driver are available from
+	  <http://software.intel.com/en-us/mic-developer>.
+
+comment "Intel MIC Card Driver"
+
+config INTEL_MIC_CARD
+	tristate "Intel MIC Card Driver"
+	depends on 64BIT && X86
+	select VIRTIO
+	default N
+	help
+	  This enables card driver support for the Intel Many Integrated
+	  Core (MIC) device family. The card driver communicates shutdown/
+	  crash events to the host and allows registration/configuration of
+	  virtio devices. Intel MIC X100 devices are currently supported.
+
+	  If you are building a card kernel for an Intel MIC device then
+	  say M (recommended) or Y, else say N. If unsure say N.
+
+	  For more information see
+	  <http://software.intel.com/en-us/mic-developer>.
diff --git a/drivers/misc/mic/Makefile b/drivers/misc/mic/Makefile
new file mode 100644
index 0000000..05b34d6
--- /dev/null
+++ b/drivers/misc/mic/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile - Intel MIC Linux driver.
+# Copyright(c) 2013, Intel Corporation.
+#
+obj-$(CONFIG_INTEL_MIC_HOST) += host/
+obj-$(CONFIG_INTEL_MIC_CARD) += card/
diff --git a/drivers/misc/mic/card/Makefile b/drivers/misc/mic/card/Makefile
new file mode 100644
index 0000000..69d58be
--- /dev/null
+++ b/drivers/misc/mic/card/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile - Intel MIC Linux driver.
+# Copyright(c) 2013, Intel Corporation.
+#
+ccflags-y += -DINTEL_MIC_CARD
+
+obj-$(CONFIG_INTEL_MIC_CARD) += mic_card.o
+mic_card-y += mic_x100.o
+mic_card-y += mic_device.o
+mic_card-y += mic_debugfs.o
+mic_card-y += mic_virtio.o
diff --git a/drivers/misc/mic/card/mic_debugfs.c b/drivers/misc/mic/card/mic_debugfs.c
new file mode 100644
index 0000000..421b3d7
--- /dev/null
+++ b/drivers/misc/mic/card/mic_debugfs.c
@@ -0,0 +1,130 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Disclaimer: The codes contained in these modules may be specific to
+ * the Intel Software Development Platform codenamed: Knights Ferry, and
+ * the Intel product codenamed: Knights Corner, and are not backward
+ * compatible with other Intel products. Additionally, Intel will NOT
+ * support the codes or instruction set in future products.
+ *
+ * Intel MIC Card driver.
+ *
+ */
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+
+#include "../common/mic_dev.h"
+#include "mic_device.h"
+
+/* Debugfs parent dir */
+static struct dentry *mic_dbg;
+
+/**
+ * mic_intr_test - Send interrupts to host.
+ */
+static int mic_intr_test(struct seq_file *s, void *unused)
+{
+	struct mic_driver *mdrv = s->private;
+	struct mic_device *mdev = &mdrv->mdev;
+
+	mic_send_intr(mdev, 0);
+	msleep(1000);
+	mic_send_intr(mdev, 1);
+	msleep(1000);
+	mic_send_intr(mdev, 2);
+	msleep(1000);
+	mic_send_intr(mdev, 3);
+	msleep(1000);
+
+	return 0;
+}
+
+static int mic_intr_test_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mic_intr_test, inode->i_private);
+}
+
+static int mic_intr_test_release(struct inode *inode, struct file *file)
+{
+	return single_release(inode, file);
+}
+
+static const struct file_operations intr_test_ops = {
+	.owner   = THIS_MODULE,
+	.open    = mic_intr_test_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = mic_intr_test_release
+};
+
+/**
+ * mic_create_card_debug_dir - Initialize MIC debugfs entries.
+ */
+void __init mic_create_card_debug_dir(struct mic_driver *mdrv)
+{
+	struct dentry *d;
+
+	if (!mic_dbg)
+		return;
+
+	mdrv->dbg_dir = debugfs_create_dir(mdrv->name, mic_dbg);
+	if (!mdrv->dbg_dir) {
+		dev_err(mdrv->dev, "Cant create dbg_dir %s\n", mdrv->name);
+		return;
+	}
+
+	d = debugfs_create_file("intr_test", 0444, mdrv->dbg_dir,
+		mdrv, &intr_test_ops);
+
+	if (!d) {
+		dev_err(mdrv->dev,
+			"Cant create dbg intr_test %s\n", mdrv->name);
+		return;
+	}
+}
+
+/**
+ * mic_delete_card_debug_dir - Uninitialize MIC debugfs entries.
+ */
+void mic_delete_card_debug_dir(struct mic_driver *mdrv)
+{
+	if (!mdrv->dbg_dir)
+		return;
+
+	debugfs_remove_recursive(mdrv->dbg_dir);
+}
+
+/**
+ * mic_init_card_debugfs - Initialize global debugfs entry.
+ */
+void __init mic_init_card_debugfs(void)
+{
+	mic_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
+	if (!mic_dbg)
+		pr_err("can't create debugfs dir\n");
+}
+
+/**
+ * mic_exit_card_debugfs - Uninitialize global debugfs entry
+ */
+void mic_exit_card_debugfs(void)
+{
+	debugfs_remove(mic_dbg);
+}
diff --git a/drivers/misc/mic/card/mic_device.c b/drivers/misc/mic/card/mic_device.c
new file mode 100644
index 0000000..d0980ff
--- /dev/null
+++ b/drivers/misc/mic/card/mic_device.c
@@ -0,0 +1,305 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Disclaimer: The codes contained in these modules may be specific to
+ * the Intel Software Development Platform codenamed: Knights Ferry, and
+ * the Intel product codenamed: Knights Corner, and are not backward
+ * compatible with other Intel products. Additionally, Intel will NOT
+ * support the codes or instruction set in future products.
+ *
+ * Intel MIC Card driver.
+ *
+ */
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+
+#include <linux/mic_common.h>
+#include "../common/mic_dev.h"
+#include "mic_device.h"
+#include "mic_virtio.h"
+
+static struct mic_driver *g_drv;
+static struct mic_irq *shutdown_cookie;
+
+static void mic_notify_host(u8 state)
+{
+	struct mic_driver *mdrv = g_drv;
+	struct mic_bootparam __iomem *bootparam = mdrv->dp;
+
+	iowrite8(state, &bootparam->shutdown_status);
+	dev_dbg(mdrv->dev, "%s %d system_state %d\n",
+		__func__, __LINE__, state);
+	mic_send_intr(&mdrv->mdev, ioread8(&bootparam->c2h_shutdown_db));
+}
+
+static int mic_panic_event(struct notifier_block *this, unsigned long event,
+		void *ptr)
+{
+	struct mic_driver *mdrv = g_drv;
+	struct mic_bootparam __iomem *bootparam = mdrv->dp;
+
+	iowrite8(-1, &bootparam->h2c_config_db);
+	iowrite8(-1, &bootparam->h2c_shutdown_db);
+	mic_notify_host(MIC_CRASHED);
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block mic_panic = {
+	.notifier_call  = mic_panic_event,
+};
+
+static irqreturn_t mic_shutdown_isr(int irq, void *data)
+{
+	struct mic_driver *mdrv = g_drv;
+	struct mic_bootparam __iomem *bootparam = mdrv->dp;
+
+	mic_ack_interrupt(&g_drv->mdev);
+	if (ioread8(&bootparam->shutdown_card))
+		orderly_poweroff(true);
+	return IRQ_HANDLED;
+}
+
+static int mic_shutdown_init(void)
+{
+	int rc = 0;
+	struct mic_driver *mdrv = g_drv;
+	struct mic_bootparam __iomem *bootparam = mdrv->dp;
+	int shutdown_db;
+
+	shutdown_db = mic_next_card_db();
+	shutdown_cookie = mic_request_card_irq(mic_shutdown_isr,
+			"Shutdown", mdrv, shutdown_db);
+	if (IS_ERR(shutdown_cookie))
+		rc = PTR_ERR(shutdown_cookie);
+	else
+		iowrite8(shutdown_db, &bootparam->h2c_shutdown_db);
+	return rc;
+}
+
+static void mic_shutdown_uninit(void)
+{
+	struct mic_driver *mdrv = g_drv;
+	struct mic_bootparam __iomem *bootparam = mdrv->dp;
+
+	iowrite8(-1, &bootparam->h2c_shutdown_db);
+	mic_free_card_irq(shutdown_cookie, mdrv);
+}
+
+static int __init mic_dp_init(void)
+{
+	struct mic_driver *mdrv = g_drv;
+	struct mic_device *mdev = &mdrv->mdev;
+	struct mic_bootparam __iomem *bootparam;
+	u64 lo, hi, dp_dma_addr;
+	u32 magic;
+
+	lo = mic_read_spad(&mdrv->mdev, MIC_DPLO_SPAD);
+	hi = mic_read_spad(&mdrv->mdev, MIC_DPHI_SPAD);
+
+	dp_dma_addr = lo | (hi << 32);
+	mdrv->dp = mic_card_map(mdev, dp_dma_addr, MIC_DP_SIZE);
+	if (!mdrv->dp) {
+		dev_err(mdrv->dev, "Cannot remap Aperture BAR\n");
+		return -ENOMEM;
+	}
+	bootparam = mdrv->dp;
+	magic = ioread32(&bootparam->magic);
+	if (MIC_MAGIC != magic) {
+		dev_err(mdrv->dev, "bootparam magic mismatch 0x%x\n", magic);
+		return -EIO;
+	}
+	return 0;
+}
+
+/* Uninitialize the device page */
+static void mic_dp_uninit(void)
+{
+	mic_card_unmap(&g_drv->mdev, g_drv->dp);
+}
+
+/**
+ * mic_request_card_irq - request an irq.
+ *
+ * @func: The callback function that handles the interrupt.
+ * @name: The ASCII name of the callee requesting the irq.
+ * @data: private data that is returned back when calling the
+ * function handler.
+ * @index: The doorbell index of the requester.
+ *
+ * returns: The cookie that is transparent to the caller. Passed
+ * back when calling mic_free_irq. An appropriate error code
+ * is returned on failure. Caller needs to use IS_ERR(return_val)
+ * to check for failure and PTR_ERR(return_val) to obtained the
+ * error code.
+ *
+ */
+struct mic_irq *mic_request_card_irq(irqreturn_t (*func)(int irq, void *data),
+	const char *name, void *data, int index)
+{
+	int rc = 0;
+	unsigned long cookie;
+	struct mic_driver *mdrv = g_drv;
+
+	rc  = request_irq(mic_db_to_irq(mdrv, index), func,
+		0, name, data);
+	if (rc) {
+		dev_err(mdrv->dev, "request_irq failed rc = %d\n", rc);
+		goto err;
+	}
+	mdrv->irq_info.irq_usage_count[index]++;
+	cookie = index;
+	return (struct mic_irq *)cookie;
+err:
+	return ERR_PTR(rc);
+}
+
+/**
+ * mic_free_card_irq - free irq.
+ *
+ * @cookie: cookie obtained during a successful call to mic_request_irq
+ * @data: private data specified by the calling function during the
+ * mic_request_irq
+ *
+ * returns: none.
+ */
+void mic_free_card_irq(struct mic_irq *cookie, void *data)
+{
+	int index;
+	struct mic_driver *mdrv = g_drv;
+
+	index = (unsigned long)cookie & 0xFFFFU;
+	free_irq(mic_db_to_irq(mdrv, index), data);
+	mdrv->irq_info.irq_usage_count[index]--;
+}
+
+/**
+ * mic_next_card_db - Get the doorbell with minimum usage count.
+ *
+ * Returns the irq index.
+ */
+int mic_next_card_db(void)
+{
+	int i;
+	int index = 0;
+	struct mic_driver *mdrv = g_drv;
+
+	for (i = 0; i < mdrv->intr_info.num_intr; i++) {
+		if (mdrv->irq_info.irq_usage_count[i] <
+			mdrv->irq_info.irq_usage_count[index])
+			index = i;
+	}
+
+	return index;
+}
+
+/**
+ * mic_init_irq - Initialize irq information.
+ *
+ * Returns 0 in success. Appropriate error code on failure.
+ */
+static int mic_init_irq(void)
+{
+	struct mic_driver *mdrv = g_drv;
+
+	mdrv->irq_info.irq_usage_count = kzalloc((sizeof(u32) *
+			mdrv->intr_info.num_intr),
+			GFP_KERNEL);
+	if (!mdrv->irq_info.irq_usage_count)
+		return -ENOMEM;
+	return 0;
+}
+
+/**
+ * mic_uninit_irq - Uninitialize irq information.
+ *
+ * None.
+ */
+static void mic_uninit_irq(void)
+{
+	struct mic_driver *mdrv = g_drv;
+
+	kfree(mdrv->irq_info.irq_usage_count);
+}
+
+/*
+ * mic_driver_init - MIC driver initialization tasks.
+ *
+ * Returns 0 in success. Appropriate error code on failure.
+ */
+int __init mic_driver_init(struct mic_driver *mdrv)
+{
+	int rc;
+
+	g_drv = mdrv;
+	/*
+	 * Unloading the card module is not supported. The MIC card module
+	 * handles fundamental operations like host/card initiated shutdowns
+	 * and informing the host about card crashes and cannot be unloaded.
+	 */
+	if (!try_module_get(mdrv->dev->driver->owner)) {
+		rc = -ENODEV;
+		goto done;
+	}
+	rc = mic_dp_init();
+	if (rc)
+		goto put;
+	rc = mic_init_irq();
+	if (rc)
+		goto dp_uninit;
+	rc = mic_shutdown_init();
+	if (rc)
+		goto irq_uninit;
+	rc = mic_devices_init(mdrv);
+	if (rc)
+		goto shutdown_uninit;
+	mic_create_card_debug_dir(mdrv);
+	atomic_notifier_chain_register(&panic_notifier_list, &mic_panic);
+done:
+	return rc;
+shutdown_uninit:
+	mic_shutdown_uninit();
+irq_uninit:
+	mic_uninit_irq();
+dp_uninit:
+	mic_dp_uninit();
+put:
+	module_put(mdrv->dev->driver->owner);
+	return rc;
+}
+
+/*
+ * mic_driver_uninit - MIC driver uninitialization tasks.
+ *
+ * Returns None
+ */
+void mic_driver_uninit(struct mic_driver *mdrv)
+{
+	mic_delete_card_debug_dir(mdrv);
+	mic_devices_uninit(mdrv);
+	/*
+	 * Inform the host about the shutdown status i.e. poweroff/restart etc.
+	 * The module cannot be unloaded so the only code path to call
+	 * mic_devices_uninit(..) is the shutdown callback.
+	 */
+	mic_notify_host(system_state);
+	mic_shutdown_uninit();
+	mic_uninit_irq();
+	mic_dp_uninit();
+	module_put(mdrv->dev->driver->owner);
+}
diff --git a/drivers/misc/mic/card/mic_device.h b/drivers/misc/mic/card/mic_device.h
new file mode 100644
index 0000000..347b9b3
--- /dev/null
+++ b/drivers/misc/mic/card/mic_device.h
@@ -0,0 +1,133 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Disclaimer: The codes contained in these modules may be specific to
+ * the Intel Software Development Platform codenamed: Knights Ferry, and
+ * the Intel product codenamed: Knights Corner, and are not backward
+ * compatible with other Intel products. Additionally, Intel will NOT
+ * support the codes or instruction set in future products.
+ *
+ * Intel MIC Card driver.
+ *
+ */
+#ifndef _MIC_CARD_DEVICE_H_
+#define _MIC_CARD_DEVICE_H_
+
+#include <linux/workqueue.h>
+#include <linux/io.h>
+
+/**
+ * struct mic_intr_info - Contains h/w specific interrupt sources info
+ *
+ * @num_intr: The number of irqs available
+ */
+struct mic_intr_info {
+	u32 num_intr;
+};
+
+/**
+ * struct mic_irq_info - OS specific irq information
+ *
+ * @irq_usage_count: usage count array tracking the number of sources
+ * assigned for each irq.
+ */
+struct mic_irq_info {
+	int *irq_usage_count;
+};
+
+/**
+ * struct mic_device -  MIC device information.
+ *
+ * @mmio: MMIO bar information.
+ */
+struct mic_device {
+	struct mic_mw mmio;
+};
+
+/**
+ * struct mic_driver - MIC card driver information.
+ *
+ * @name: Name for MIC driver.
+ * @dbg_dir: debugfs directory of this MIC device.
+ * @dev: The device backing this MIC.
+ * @dp: The pointer to the virtio device page.
+ * @mdev: MIC device information for the host.
+ * @hotplug_work: Hot plug work for adding/removing virtio devices.
+ * @irq_info: The OS specific irq information
+ * @intr_info: H/W specific interrupt information.
+ */
+struct mic_driver {
+	char name[20];
+	struct dentry *dbg_dir;
+	struct device *dev;
+	void __iomem *dp;
+	struct mic_device mdev;
+	struct work_struct hotplug_work;
+	struct mic_irq_info irq_info;
+	struct mic_intr_info intr_info;
+};
+
+/**
+ * struct mic_irq - opaque pointer used as cookie
+ */
+struct mic_irq;
+
+/**
+ * mic_mmio_read - read from an MMIO register.
+ * @mw: MMIO register base virtual address.
+ * @offset: register offset.
+ *
+ * RETURNS: register value.
+ */
+static inline u32 mic_mmio_read(struct mic_mw *mw, u32 offset)
+{
+	return ioread32(mw->va + offset);
+}
+
+/**
+ * mic_mmio_write - write to an MMIO register.
+ * @mw: MMIO register base virtual address.
+ * @val: the data value to put into the register
+ * @offset: register offset.
+ *
+ * RETURNS: none.
+ */
+static inline void
+mic_mmio_write(struct mic_mw *mw, u32 val, u32 offset)
+{
+	iowrite32(val, mw->va + offset);
+}
+
+int mic_driver_init(struct mic_driver *mdrv);
+void mic_driver_uninit(struct mic_driver *mdrv);
+int mic_next_card_db(void);
+struct mic_irq *mic_request_card_irq(irqreturn_t (*func)(int irq, void *data),
+	const char *name, void *data, int intr_src);
+void mic_free_card_irq(struct mic_irq *cookie, void *data);
+u32 mic_read_spad(struct mic_device *mdev, unsigned int idx);
+void mic_send_intr(struct mic_device *mdev, int doorbell);
+int mic_db_to_irq(struct mic_driver *mdrv, int db);
+u32 mic_ack_interrupt(struct mic_device *mdev);
+void mic_hw_intr_init(struct mic_driver *mdrv);
+void __iomem *
+mic_card_map(struct mic_device *mdev, dma_addr_t addr, size_t size);
+void mic_card_unmap(struct mic_device *mdev, void __iomem *addr);
+void __init mic_create_card_debug_dir(struct mic_driver *mdrv);
+void mic_delete_card_debug_dir(struct mic_driver *mdrv);
+void __init mic_init_card_debugfs(void);
+void mic_exit_card_debugfs(void);
+#endif
diff --git a/drivers/misc/mic/card/mic_virtio.c b/drivers/misc/mic/card/mic_virtio.c
new file mode 100644
index 0000000..914cc9b
--- /dev/null
+++ b/drivers/misc/mic/card/mic_virtio.c
@@ -0,0 +1,630 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Disclaimer: The codes contained in these modules may be specific to
+ * the Intel Software Development Platform codenamed: Knights Ferry, and
+ * the Intel product codenamed: Knights Corner, and are not backward
+ * compatible with other Intel products. Additionally, Intel will NOT
+ * support the codes or instruction set in future products.
+ *
+ * Adapted from:
+ *
+ * virtio for kvm on s390
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
+ *
+ * Intel MIC Card driver.
+ *
+ */
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/virtio_config.h>
+
+#include "../common/mic_dev.h"
+#include "mic_virtio.h"
+
+#define VIRTIO_SUBCODE_64 0x0D00
+
+#define MIC_MAX_VRINGS                4
+struct mic_vdev {
+	struct virtio_device vdev;
+	struct mic_device_desc __iomem *desc;
+	struct mic_device_ctrl __iomem *dc;
+	struct mic_device *mdev;
+	void __iomem *vr[MIC_MAX_VRINGS];
+	int used_size[MIC_MAX_VRINGS];
+	struct completion reset_done;
+	struct mic_irq *virtio_cookie;
+	int c2h_vdev_db;
+};
+
+static struct mic_irq *virtio_config_cookie;
+#define to_micvdev(vd) container_of(vd, struct mic_vdev, vdev)
+
+/* Helper API to obtain the parent of the virtio device */
+static inline struct device *mic_dev(struct mic_vdev *mvdev)
+{
+	return mvdev->vdev.dev.parent;
+}
+
+/* This gets the device's feature bits. */
+static u32 mic_get_features(struct virtio_device *vdev)
+{
+	unsigned int i, bits;
+	u32 features = 0;
+	struct mic_device_desc __iomem *desc = to_micvdev(vdev)->desc;
+	u8 __iomem *in_features = mic_vq_features(desc);
+	int feature_len = ioread8(&desc->feature_len);
+
+	bits = min_t(unsigned, feature_len,
+		sizeof(vdev->features)) * 8;
+	for (i = 0; i < bits; i++)
+		if (ioread8(&in_features[i / 8]) & (BIT(i % 8)))
+			features |= BIT(i);
+
+	return features;
+}
+
+static void mic_finalize_features(struct virtio_device *vdev)
+{
+	unsigned int i, bits;
+	struct mic_device_desc __iomem *desc = to_micvdev(vdev)->desc;
+	u8 feature_len = ioread8(&desc->feature_len);
+	/* Second half of bitmap is features we accept. */
+	u8 __iomem *out_features =
+		mic_vq_features(desc) + feature_len;
+
+	/* Give virtio_ring a chance to accept features. */
+	vring_transport_features(vdev);
+
+	memset_io(out_features, 0, feature_len);
+	bits = min_t(unsigned, feature_len,
+		sizeof(vdev->features)) * 8;
+	for (i = 0; i < bits; i++) {
+		if (test_bit(i, vdev->features))
+			iowrite8(ioread8(&out_features[i / 8]) | (1 << (i % 8)),
+				 &out_features[i / 8]);
+	}
+}
+
+/*
+ * Reading and writing elements in config space
+ */
+static void mic_get(struct virtio_device *vdev, unsigned int offset,
+		   void *buf, unsigned len)
+{
+	struct mic_device_desc __iomem *desc = to_micvdev(vdev)->desc;
+
+	if (offset + len > ioread8(&desc->config_len))
+		return;
+	memcpy_fromio(buf, mic_vq_configspace(desc) + offset, len);
+}
+
+static void mic_set(struct virtio_device *vdev, unsigned int offset,
+		   const void *buf, unsigned len)
+{
+	struct mic_device_desc __iomem *desc = to_micvdev(vdev)->desc;
+
+	if (offset + len > ioread8(&desc->config_len))
+		return;
+	memcpy_toio(mic_vq_configspace(desc) + offset, buf, len);
+}
+
+/*
+ * The operations to get and set the status word just access the status
+ * field of the device descriptor. set_status also interrupts the host
+ * to tell about status changes.
+ */
+static u8 mic_get_status(struct virtio_device *vdev)
+{
+	return ioread8(&to_micvdev(vdev)->desc->status);
+}
+
+static void mic_set_status(struct virtio_device *vdev, u8 status)
+{
+	struct mic_vdev *mvdev = to_micvdev(vdev);
+	if (!status)
+		return;
+	iowrite8(status, &mvdev->desc->status);
+	mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
+}
+
+/* Inform host on a virtio device reset and wait for ack from host */
+static void mic_reset_inform_host(struct virtio_device *vdev)
+{
+	struct mic_vdev *mvdev = to_micvdev(vdev);
+	struct mic_device_ctrl __iomem *dc = mvdev->dc;
+	int retry = 100, i;
+
+	iowrite8(0, &dc->host_ack);
+	iowrite8(1, &dc->vdev_reset);
+	mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
+
+	/* Wait till host completes all card accesses and acks the reset */
+	for (i = retry; i--;) {
+		if (ioread8(&dc->host_ack))
+			break;
+		msleep(100);
+	};
+
+	dev_dbg(mic_dev(mvdev), "%s: retry: %d\n", __func__, retry);
+
+	/* Reset status to 0 in case we timed out */
+	iowrite8(0, &mvdev->desc->status);
+}
+
+static void mic_reset(struct virtio_device *vdev)
+{
+	struct mic_vdev *mvdev = to_micvdev(vdev);
+
+	dev_dbg(mic_dev(mvdev), "%s: virtio id %d\n",
+		__func__, vdev->id.device);
+
+	mic_reset_inform_host(vdev);
+	complete_all(&mvdev->reset_done);
+}
+
+/*
+ * The virtio_ring code calls this API when it wants to notify the Host.
+ */
+static void mic_notify(struct virtqueue *vq)
+{
+	struct mic_vdev *mvdev = vq->priv;
+
+	mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
+}
+
+static void mic_del_vq(struct virtqueue *vq, int n)
+{
+	struct mic_vdev *mvdev = to_micvdev(vq->vdev);
+	struct vring *vr = (struct vring *)(vq + 1);
+
+	free_pages((unsigned long) vr->used, get_order(mvdev->used_size[n]));
+	vring_del_virtqueue(vq);
+	mic_card_unmap(mvdev->mdev, mvdev->vr[n]);
+	mvdev->vr[n] = NULL;
+}
+
+static void mic_del_vqs(struct virtio_device *vdev)
+{
+	struct mic_vdev *mvdev = to_micvdev(vdev);
+	struct virtqueue *vq, *n;
+	int idx = 0;
+
+	dev_dbg(mic_dev(mvdev), "%s\n", __func__);
+
+	list_for_each_entry_safe(vq, n, &vdev->vqs, list)
+		mic_del_vq(vq, idx++);
+}
+
+/*
+ * This routine will assign vring's allocated in host/io memory. Code in
+ * virtio_ring.c however continues to access this io memory as if it were local
+ * memory without io accessors.
+ */
+static struct virtqueue *mic_find_vq(struct virtio_device *vdev,
+				     unsigned index,
+				     void (*callback)(struct virtqueue *vq),
+				     const char *name)
+{
+	struct mic_vdev *mvdev = to_micvdev(vdev);
+	struct mic_vqconfig __iomem *vqconfig;
+	struct mic_vqconfig config;
+	struct virtqueue *vq;
+	void __iomem *va;
+	struct _mic_vring_info __iomem *info;
+	void *used;
+	int vr_size, _vr_size, err, magic;
+	struct vring *vr;
+	u8 type = ioread8(&mvdev->desc->type);
+
+	if (index >= ioread8(&mvdev->desc->num_vq))
+		return ERR_PTR(-ENOENT);
+
+	if (!name)
+		return ERR_PTR(-ENOENT);
+
+	/* First assign the vring's allocated in host memory */
+	vqconfig = mic_vq_config(mvdev->desc) + index;
+	memcpy_fromio(&config, vqconfig, sizeof(config));
+	_vr_size = vring_size(config.num, MIC_VIRTIO_RING_ALIGN);
+	vr_size = PAGE_ALIGN(_vr_size + sizeof(struct _mic_vring_info));
+	va = mic_card_map(mvdev->mdev, config.address, vr_size);
+	if (!va)
+		return ERR_PTR(-ENOMEM);
+	mvdev->vr[index] = va;
+	memset_io(va, 0x0, _vr_size);
+	vq = vring_new_virtqueue(index,
+				config.num, MIC_VIRTIO_RING_ALIGN, vdev,
+				false,
+				va, mic_notify, callback, name);
+	if (!vq) {
+		err = -ENOMEM;
+		goto unmap;
+	}
+	info = va + _vr_size;
+	magic = ioread32(&info->magic);
+
+	if (WARN(magic != MIC_MAGIC + type + index, "magic mismatch")) {
+		err = -EIO;
+		goto unmap;
+	}
+
+	/* Allocate and reassign used ring now */
+	mvdev->used_size[index] = PAGE_ALIGN(sizeof(__u16) * 3 +
+			sizeof(struct vring_used_elem) * config.num);
+	used = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+					get_order(mvdev->used_size[index]));
+	if (!used) {
+		err = -ENOMEM;
+		dev_err(mic_dev(mvdev), "%s %d err %d\n",
+			__func__, __LINE__, err);
+		goto del_vq;
+	}
+	iowrite64(virt_to_phys(used), &vqconfig->used_address);
+
+	/*
+	 * To reassign the used ring here we are directly accessing
+	 * struct vring_virtqueue which is a private data structure
+	 * in virtio_ring.c. At the minimum, a BUILD_BUG_ON() in
+	 * vring_new_virtqueue() would ensure that
+	 *  (&vq->vring == (struct vring *) (&vq->vq + 1));
+	 */
+	vr = (struct vring *)(vq + 1);
+	vr->used = used;
+
+	vq->priv = mvdev;
+	return vq;
+del_vq:
+	vring_del_virtqueue(vq);
+unmap:
+	mic_card_unmap(mvdev->mdev, mvdev->vr[index]);
+	return ERR_PTR(err);
+}
+
+static int mic_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+			struct virtqueue *vqs[],
+			vq_callback_t *callbacks[],
+			const char *names[])
+{
+	struct mic_vdev *mvdev = to_micvdev(vdev);
+	struct mic_device_ctrl __iomem *dc = mvdev->dc;
+	int i, err, retry = 100;
+
+	/* We must have this many virtqueues. */
+	if (nvqs > ioread8(&mvdev->desc->num_vq))
+		return -ENOENT;
+
+	for (i = 0; i < nvqs; ++i) {
+		dev_dbg(mic_dev(mvdev), "%s: %d: %s\n",
+			__func__, i, names[i]);
+		vqs[i] = mic_find_vq(vdev, i, callbacks[i], names[i]);
+		if (IS_ERR(vqs[i])) {
+			err = PTR_ERR(vqs[i]);
+			goto error;
+		}
+	}
+
+	iowrite8(1, &dc->used_address_updated);
+	/*
+	 * Send an interrupt to the host to inform it that used
+	 * rings have been re-assigned.
+	 */
+	mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
+	for (i = retry; i--;) {
+		if (!ioread8(&dc->used_address_updated))
+			break;
+		msleep(100);
+	};
+
+	dev_dbg(mic_dev(mvdev), "%s: retry: %d\n", __func__, retry);
+	if (!retry) {
+		err = -ENODEV;
+		goto error;
+	}
+
+	return 0;
+error:
+	mic_del_vqs(vdev);
+	return err;
+}
+
+/*
+ * The config ops structure as defined by virtio config
+ */
+static struct virtio_config_ops mic_vq_config_ops = {
+	.get_features = mic_get_features,
+	.finalize_features = mic_finalize_features,
+	.get = mic_get,
+	.set = mic_set,
+	.get_status = mic_get_status,
+	.set_status = mic_set_status,
+	.reset = mic_reset,
+	.find_vqs = mic_find_vqs,
+	.del_vqs = mic_del_vqs,
+};
+
+static irqreturn_t
+mic_virtio_intr_handler(int irq, void *data)
+{
+	struct mic_vdev *mvdev = data;
+	struct virtqueue *vq;
+
+	mic_ack_interrupt(mvdev->mdev);
+	list_for_each_entry(vq, &mvdev->vdev.vqs, list)
+		vring_interrupt(0, vq);
+
+	return IRQ_HANDLED;
+}
+
+static void mic_virtio_release_dev(struct device *_d)
+{
+	/*
+	 * No need for a release method similar to virtio PCI.
+	 * Provide an empty one to avoid getting a warning from core.
+	 */
+}
+
+/*
+ * adds a new device and register it with virtio
+ * appropriate drivers are loaded by the device model
+ */
+static int mic_add_device(struct mic_device_desc __iomem *d,
+	unsigned int offset, struct mic_driver *mdrv)
+{
+	struct mic_vdev *mvdev;
+	int ret;
+	int virtio_db;
+	u8 type = ioread8(&d->type);
+
+	mvdev = kzalloc(sizeof(*mvdev), GFP_KERNEL);
+	if (!mvdev) {
+		dev_err(mdrv->dev, "Cannot allocate mic dev %u type %u\n",
+			offset, type);
+		return -ENOMEM;
+	}
+
+	mvdev->mdev = &mdrv->mdev;
+	mvdev->vdev.dev.parent = mdrv->dev;
+	mvdev->vdev.dev.release = mic_virtio_release_dev;
+	mvdev->vdev.id.device = type;
+	mvdev->vdev.config = &mic_vq_config_ops;
+	mvdev->desc = d;
+	mvdev->dc = (void __iomem *)d + mic_aligned_desc_size(d);
+	init_completion(&mvdev->reset_done);
+
+	virtio_db = mic_next_card_db();
+	mvdev->virtio_cookie = mic_request_card_irq(mic_virtio_intr_handler,
+			"virtio intr", mvdev, virtio_db);
+	if (IS_ERR(mvdev->virtio_cookie)) {
+		ret = PTR_ERR(mvdev->virtio_cookie);
+		goto kfree;
+	}
+	iowrite8((u8)virtio_db, &mvdev->dc->h2c_vdev_db);
+	mvdev->c2h_vdev_db = ioread8(&mvdev->dc->c2h_vdev_db);
+
+	ret = register_virtio_device(&mvdev->vdev);
+	if (ret) {
+		dev_err(mic_dev(mvdev),
+			"Failed to register mic device %u type %u\n",
+			offset, type);
+		goto free_irq;
+	}
+	iowrite64((u64)mvdev, &mvdev->dc->vdev);
+	dev_dbg(mic_dev(mvdev), "%s: registered mic device %u type %u mvdev %p\n",
+		__func__, offset, type, mvdev);
+
+	return 0;
+
+free_irq:
+	mic_free_card_irq(mvdev->virtio_cookie, mvdev);
+kfree:
+	kfree(mvdev);
+	return ret;
+}
+
+/*
+ * match for a mic device with a specific desc pointer
+ */
+static int mic_match_desc(struct device *dev, void *data)
+{
+	struct virtio_device *vdev = dev_to_virtio(dev);
+	struct mic_vdev *mvdev = to_micvdev(vdev);
+
+	return mvdev->desc == (void __iomem *)data;
+}
+
+static void mic_handle_config_change(struct mic_device_desc __iomem *d,
+	unsigned int offset, struct mic_driver *mdrv)
+{
+	struct mic_device_ctrl __iomem *dc
+		= (void __iomem *)d + mic_aligned_desc_size(d);
+	struct mic_vdev *mvdev = (struct mic_vdev *)ioread64(&dc->vdev);
+	struct virtio_driver *drv;
+
+	if (ioread8(&dc->config_change) != MIC_VIRTIO_PARAM_CONFIG_CHANGED)
+		return;
+
+	dev_dbg(mdrv->dev, "%s %d\n", __func__, __LINE__);
+	drv = container_of(mvdev->vdev.dev.driver,
+				struct virtio_driver, driver);
+	if (drv->config_changed)
+		drv->config_changed(&mvdev->vdev);
+	iowrite8(1, &dc->guest_ack);
+}
+
+/*
+ * removes a virtio device if a hot remove event has been
+ * requested by the host.
+ */
+static int mic_remove_device(struct mic_device_desc __iomem *d,
+	unsigned int offset, struct mic_driver *mdrv)
+{
+	struct mic_device_ctrl __iomem *dc
+		= (void __iomem *)d + mic_aligned_desc_size(d);
+	struct mic_vdev *mvdev = (struct mic_vdev *)ioread64(&dc->vdev);
+	u8 status;
+	int ret = -1;
+
+	if (ioread8(&dc->config_change) == MIC_VIRTIO_PARAM_DEV_REMOVE) {
+		dev_dbg(mdrv->dev,
+			"%s %d config_change %d type %d mvdev %p\n",
+			__func__, __LINE__,
+			ioread8(&dc->config_change), ioread8(&d->type), mvdev);
+
+		status = ioread8(&d->status);
+		INIT_COMPLETION(mvdev->reset_done);
+		unregister_virtio_device(&mvdev->vdev);
+		mic_free_card_irq(mvdev->virtio_cookie, mvdev);
+		if (status & VIRTIO_CONFIG_S_DRIVER_OK)
+			wait_for_completion(&mvdev->reset_done);
+		kfree(mvdev);
+		iowrite8(1, &dc->guest_ack);
+		dev_dbg(mdrv->dev, "%s %d guest_ack %d\n",
+			__func__, __LINE__, ioread8(&dc->guest_ack));
+		ret = 0;
+	}
+
+	return ret;
+}
+
+#define REMOVE_DEVICES true
+
+static void mic_scan_devices(struct mic_driver *mdrv, bool remove)
+{
+	s8 type;
+	unsigned int i;
+	struct mic_device_desc __iomem *d;
+	struct mic_device_ctrl __iomem *dc;
+	struct device *dev;
+	int ret;
+
+	for (i = mic_aligned_size(struct mic_bootparam);
+		i < MIC_DP_SIZE; i += mic_total_desc_size(d)) {
+		d = mdrv->dp + i;
+		dc = (void __iomem *)d + mic_aligned_desc_size(d);
+		/*
+		 * This read barrier is paired with the corresponding write
+		 * barrier on the host which is inserted before adding or
+		 * removing a virtio device descriptor, by updating the type.
+		 */
+		rmb();
+		type = ioread8(&d->type);
+
+		/* end of list */
+		if (type == 0)
+			break;
+
+		if (type == -1)
+			continue;
+
+		/* device already exists */
+		dev = device_find_child(mdrv->dev, d, mic_match_desc);
+		if (dev) {
+			if (remove)
+				iowrite8(MIC_VIRTIO_PARAM_DEV_REMOVE,
+					 &dc->config_change);
+			put_device(dev);
+			mic_handle_config_change(d, i, mdrv);
+			ret = mic_remove_device(d, i, mdrv);
+			if (!ret && !remove)
+				iowrite8(-1, &d->type);
+			if (remove) {
+				iowrite8(0, &dc->config_change);
+				iowrite8(0, &dc->guest_ack);
+			}
+			continue;
+		}
+
+		/* new device */
+		dev_dbg(mdrv->dev, "%s %d Adding new virtio device %p\n",
+			__func__, __LINE__, d);
+		if (!remove)
+			mic_add_device(d, i, mdrv);
+	}
+}
+
+/*
+ * mic_hotplug_device tries to find changes in the device page.
+ */
+static void mic_hotplug_devices(struct work_struct *work)
+{
+	struct mic_driver *mdrv = container_of(work,
+		struct mic_driver, hotplug_work);
+
+	mic_scan_devices(mdrv, !REMOVE_DEVICES);
+}
+
+/*
+ * Interrupt handler for hot plug/config changes etc.
+ */
+static irqreturn_t
+mic_extint_handler(int irq, void *data)
+{
+	struct mic_driver *mdrv = (struct mic_driver *)data;
+
+	dev_dbg(mdrv->dev, "%s %d hotplug work\n",
+		__func__, __LINE__);
+	mic_ack_interrupt(&mdrv->mdev);
+	schedule_work(&mdrv->hotplug_work);
+	return IRQ_HANDLED;
+}
+
+/*
+ * Init function for virtio
+ */
+int mic_devices_init(struct mic_driver *mdrv)
+{
+	int rc;
+	struct mic_bootparam __iomem *bootparam;
+	int config_db;
+
+	INIT_WORK(&mdrv->hotplug_work, mic_hotplug_devices);
+	mic_scan_devices(mdrv, !REMOVE_DEVICES);
+
+	config_db = mic_next_card_db();
+	virtio_config_cookie = mic_request_card_irq(mic_extint_handler,
+			"virtio_config_intr", mdrv, config_db);
+	if (IS_ERR(virtio_config_cookie)) {
+		rc = PTR_ERR(virtio_config_cookie);
+		goto exit;
+	}
+
+	bootparam = mdrv->dp;
+	iowrite8(config_db, &bootparam->h2c_config_db);
+	return 0;
+exit:
+	return rc;
+}
+
+/*
+ * Uninit function for virtio
+ */
+void mic_devices_uninit(struct mic_driver *mdrv)
+{
+	struct mic_bootparam __iomem *bootparam = mdrv->dp;
+	iowrite8(-1, &bootparam->h2c_config_db);
+	mic_free_card_irq(virtio_config_cookie, mdrv);
+	flush_work(&mdrv->hotplug_work);
+	mic_scan_devices(mdrv, REMOVE_DEVICES);
+}
diff --git a/drivers/misc/mic/card/mic_virtio.h b/drivers/misc/mic/card/mic_virtio.h
new file mode 100644
index 0000000..2c5c22c
--- /dev/null
+++ b/drivers/misc/mic/card/mic_virtio.h
@@ -0,0 +1,77 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Disclaimer: The codes contained in these modules may be specific to
+ * the Intel Software Development Platform codenamed: Knights Ferry, and
+ * the Intel product codenamed: Knights Corner, and are not backward
+ * compatible with other Intel products. Additionally, Intel will NOT
+ * support the codes or instruction set in future products.
+ *
+ * Intel MIC Card driver.
+ *
+ */
+#ifndef __MIC_CARD_VIRTIO_H
+#define __MIC_CARD_VIRTIO_H
+
+#include <linux/mic_common.h>
+#include "mic_device.h"
+
+/*
+ * 64 bit I/O access
+ */
+#ifndef ioread64
+#define ioread64 readq
+#endif
+#ifndef iowrite64
+#define iowrite64 writeq
+#endif
+
+static inline unsigned mic_desc_size(struct mic_device_desc __iomem *desc)
+{
+	return mic_aligned_size(*desc)
+		+ ioread8(&desc->num_vq) * mic_aligned_size(struct mic_vqconfig)
+		+ ioread8(&desc->feature_len) * 2
+		+ ioread8(&desc->config_len);
+}
+
+static inline struct mic_vqconfig __iomem *
+mic_vq_config(struct mic_device_desc __iomem *desc)
+{
+	return (struct mic_vqconfig __iomem *)(desc + 1);
+}
+
+static inline __u8 __iomem *
+mic_vq_features(struct mic_device_desc __iomem *desc)
+{
+	return (__u8 __iomem *)(mic_vq_config(desc) + ioread8(&desc->num_vq));
+}
+
+static inline __u8 __iomem *
+mic_vq_configspace(struct mic_device_desc __iomem *desc)
+{
+	return mic_vq_features(desc) + ioread8(&desc->feature_len) * 2;
+}
+static inline unsigned mic_total_desc_size(struct mic_device_desc __iomem *desc)
+{
+	return mic_aligned_desc_size(desc) +
+		mic_aligned_size(struct mic_device_ctrl);
+}
+
+int mic_devices_init(struct mic_driver *mdrv);
+void mic_devices_uninit(struct mic_driver *mdrv);
+
+#endif
diff --git a/drivers/misc/mic/card/mic_x100.c b/drivers/misc/mic/card/mic_x100.c
new file mode 100644
index 0000000..2868945
--- /dev/null
+++ b/drivers/misc/mic/card/mic_x100.c
@@ -0,0 +1,256 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Disclaimer: The codes contained in these modules may be specific to
+ * the Intel Software Development Platform codenamed: Knights Ferry, and
+ * the Intel product codenamed: Knights Corner, and are not backward
+ * compatible with other Intel products. Additionally, Intel will NOT
+ * support the codes or instruction set in future products.
+ *
+ * Intel MIC Card driver.
+ *
+ */
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+
+#include "../common/mic_dev.h"
+#include "mic_device.h"
+#include "mic_x100.h"
+
+static const char mic_driver_name[] = "mic";
+
+static struct mic_driver g_drv;
+
+/**
+ * mic_read_spad - read from the scratchpad register
+ * @mdev: pointer to mic_device instance
+ * @idx: index to scratchpad register, 0 based
+ *
+ * This function allows reading of the 32bit scratchpad register.
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+u32 mic_read_spad(struct mic_device *mdev, unsigned int idx)
+{
+	return mic_mmio_read(&mdev->mmio,
+		MIC_X100_SBOX_BASE_ADDRESS +
+		MIC_X100_SBOX_SPAD0 + idx * 4);
+}
+
+/**
+ * __mic_send_intr - Send interrupt to Host.
+ * @mdev: pointer to mic_device instance
+ * @doorbell: Doorbell number.
+ */
+void mic_send_intr(struct mic_device *mdev, int doorbell)
+{
+	struct mic_mw *mw = &mdev->mmio;
+
+	if (doorbell > MIC_X100_MAX_DOORBELL_IDX)
+		return;
+	/* Ensure that the interrupt is ordered w.r.t previous stores. */
+	wmb();
+	mic_mmio_write(mw, MIC_X100_SBOX_SDBIC0_DBREQ_BIT,
+		       MIC_X100_SBOX_BASE_ADDRESS +
+		       (MIC_X100_SBOX_SDBIC0 + (4 * doorbell)));
+}
+
+/**
+ * mic_ack_interrupt - Device specific interrupt handling.
+ * @mdev: pointer to mic_device instance
+ *
+ * Returns: bitmask of doorbell events triggered.
+ */
+u32 mic_ack_interrupt(struct mic_device *mdev)
+{
+	return 0;
+}
+
+static inline int mic_get_sbox_irq(int db)
+{
+	return MIC_X100_IRQ_BASE + db;
+}
+
+static inline int mic_get_rdmasr_irq(int index)
+{
+	return  MIC_X100_RDMASR_IRQ_BASE + index;
+}
+
+/**
+ * mic_hw_intr_init - Initialize h/w specific interrupt
+ * information.
+ * @mdrv: pointer to mic_driver
+ */
+void mic_hw_intr_init(struct mic_driver *mdrv)
+{
+	mdrv->intr_info.num_intr = MIC_X100_NUM_SBOX_IRQ +
+				MIC_X100_NUM_RDMASR_IRQ;
+}
+
+/**
+ * mic_db_to_irq - Retrieve irq number corresponding to a doorbell.
+ * @mdrv: pointer to mic_driver
+ * @db: The doorbell obtained for which the irq is needed. Doorbell
+ * may correspond to an sbox doorbell or an rdmasr index.
+ *
+ * Returns the irq corresponding to the doorbell.
+ */
+int mic_db_to_irq(struct mic_driver *mdrv, int db)
+{
+	int rdmasr_index;
+	if (db < MIC_X100_NUM_SBOX_IRQ) {
+		return mic_get_sbox_irq(db);
+	} else {
+		rdmasr_index = db - MIC_X100_NUM_SBOX_IRQ +
+			MIC_X100_RDMASR_IRQ_BASE;
+		return mic_get_rdmasr_irq(rdmasr_index);
+	}
+}
+
+/*
+ * mic_card_map - Allocate virtual address for a remote memory region.
+ * @mdev: pointer to mic_device instance.
+ * @addr: Remote DMA address.
+ * @size: Size of the region.
+ *
+ * Returns: Virtual address backing the remote memory region.
+ */
+void __iomem *
+mic_card_map(struct mic_device *mdev, dma_addr_t addr, size_t size)
+{
+	return ioremap(addr, size);
+}
+
+/*
+ * mic_card_unmap - Unmap the virtual address for a remote memory region.
+ * @mdev: pointer to mic_device instance.
+ * @addr: Virtual address for remote memory region.
+ *
+ * Returns: None.
+ */
+void mic_card_unmap(struct mic_device *mdev, void __iomem *addr)
+{
+	iounmap(addr);
+}
+
+static int __init mic_probe(struct platform_device *pdev)
+{
+	struct mic_driver *mdrv = &g_drv;
+	struct mic_device *mdev = &mdrv->mdev;
+	int rc = 0;
+
+	mdrv->dev = &pdev->dev;
+	snprintf(mdrv->name, sizeof(mic_driver_name), mic_driver_name);
+
+	mdev->mmio.pa = MIC_X100_MMIO_BASE;
+	mdev->mmio.len = MIC_X100_MMIO_LEN;
+	mdev->mmio.va = ioremap(MIC_X100_MMIO_BASE, MIC_X100_MMIO_LEN);
+	if (!mdev->mmio.va) {
+		dev_err(&pdev->dev, "Cannot remap MMIO BAR\n");
+		rc = -EIO;
+		goto done;
+	}
+	mic_hw_intr_init(mdrv);
+	rc = mic_driver_init(mdrv);
+	if (rc) {
+		dev_err(&pdev->dev, "mic_driver_init failed rc %d\n", rc);
+		goto iounmap;
+	}
+done:
+	return rc;
+iounmap:
+	iounmap(mdev->mmio.va);
+	return rc;
+}
+
+static int mic_remove(struct platform_device *pdev)
+{
+	struct mic_driver *mdrv = &g_drv;
+	struct mic_device *mdev = &mdrv->mdev;
+
+	mic_driver_uninit(mdrv);
+	iounmap(mdev->mmio.va);
+	return 0;
+}
+
+static void mic_platform_shutdown(struct platform_device *pdev)
+{
+	mic_remove(pdev);
+}
+
+static struct platform_device mic_platform_dev = {
+	.name = mic_driver_name,
+	.id   = 0,
+	.num_resources = 0,
+};
+
+static struct platform_driver __refdata mic_platform_driver = {
+	.probe = mic_probe,
+	.remove = mic_remove,
+	.shutdown = mic_platform_shutdown,
+	.driver         = {
+		.name   = mic_driver_name,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init mic_init(void)
+{
+	int ret;
+	struct cpuinfo_x86 *c = &cpu_data(0);
+
+	if (!(c->x86 == 11 && c->x86_model == 1)) {
+		ret = -ENODEV;
+		pr_err("%s not running on X100 ret %d\n", __func__, ret);
+		goto done;
+	}
+
+	mic_init_card_debugfs();
+	ret = platform_device_register(&mic_platform_dev);
+	if (ret) {
+		pr_err("platform_device_register ret %d\n", ret);
+		goto cleanup_debugfs;
+	}
+	ret = platform_driver_register(&mic_platform_driver);
+	if (ret) {
+		pr_err("platform_driver_register ret %d\n", ret);
+		goto device_unregister;
+	}
+	return ret;
+
+device_unregister:
+	platform_device_unregister(&mic_platform_dev);
+cleanup_debugfs:
+	mic_exit_card_debugfs();
+done:
+	return ret;
+}
+
+static void __exit mic_exit(void)
+{
+	platform_driver_unregister(&mic_platform_driver);
+	platform_device_unregister(&mic_platform_dev);
+	mic_exit_card_debugfs();
+}
+
+module_init(mic_init);
+module_exit(mic_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Intel(R) MIC X100 Card driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/card/mic_x100.h b/drivers/misc/mic/card/mic_x100.h
new file mode 100644
index 0000000..d66ea55
--- /dev/null
+++ b/drivers/misc/mic/card/mic_x100.h
@@ -0,0 +1,48 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Disclaimer: The codes contained in these modules may be specific to
+ * the Intel Software Development Platform codenamed: Knights Ferry, and
+ * the Intel product codenamed: Knights Corner, and are not backward
+ * compatible with other Intel products. Additionally, Intel will NOT
+ * support the codes or instruction set in future products.
+ *
+ * Intel MIC Card driver.
+ *
+ */
+#ifndef _MIC_X100_CARD_H_
+#define _MIC_X100_CARD_H_
+
+#define MIC_X100_MMIO_BASE 0x08007C0000ULL
+#define MIC_X100_MMIO_LEN 0x00020000ULL
+#define MIC_X100_SBOX_BASE_ADDRESS 0x00010000ULL
+
+#define MIC_X100_SBOX_SPAD0 0x0000AB20
+#define MIC_X100_SBOX_SDBIC0 0x0000CC90
+#define MIC_X100_SBOX_SDBIC0_DBREQ_BIT 0x80000000
+#define MIC_X100_SBOX_RDMASR0	0x0000B180
+
+#define MIC_X100_MAX_DOORBELL_IDX 8
+
+#define MIC_X100_NUM_SBOX_IRQ 8
+#define MIC_X100_NUM_RDMASR_IRQ 8
+#define MIC_X100_SBOX_IRQ_BASE 0
+#define MIC_X100_RDMASR_IRQ_BASE 17
+
+#define MIC_X100_IRQ_BASE 26
+
+#endif
diff --git a/drivers/misc/mic/common/mic_dev.h b/drivers/misc/mic/common/mic_dev.h
new file mode 100644
index 0000000..92999c2
--- /dev/null
+++ b/drivers/misc/mic/common/mic_dev.h
@@ -0,0 +1,51 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC driver.
+ *
+ */
+#ifndef __MIC_DEV_H__
+#define __MIC_DEV_H__
+
+/**
+ * struct mic_mw - MIC memory window
+ *
+ * @pa: Base physical address.
+ * @va: Base ioremap'd virtual address.
+ * @len: Size of the memory window.
+ */
+struct mic_mw {
+	phys_addr_t pa;
+	void __iomem *va;
+	resource_size_t len;
+};
+
+/*
+ * Scratch pad register offsets used by the host to communicate
+ * device page DMA address to the card.
+ */
+#define MIC_DPLO_SPAD 14
+#define MIC_DPHI_SPAD 15
+
+/*
+ * These values are supposed to be in the config_change field of the
+ * device page when the host sends a config change interrupt to the card.
+ */
+#define MIC_VIRTIO_PARAM_DEV_REMOVE 0x1
+#define MIC_VIRTIO_PARAM_CONFIG_CHANGED 0x2
+
+#endif
diff --git a/drivers/misc/mic/host/Makefile b/drivers/misc/mic/host/Makefile
new file mode 100644
index 0000000..c2197f9
--- /dev/null
+++ b/drivers/misc/mic/host/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile - Intel MIC Linux driver.
+# Copyright(c) 2013, Intel Corporation.
+#
+obj-$(CONFIG_INTEL_MIC_HOST) += mic_host.o
+mic_host-objs := mic_main.o
+mic_host-objs += mic_x100.o
+mic_host-objs += mic_sysfs.o
+mic_host-objs += mic_smpt.o
+mic_host-objs += mic_intr.o
+mic_host-objs += mic_boot.o
+mic_host-objs += mic_debugfs.o
+mic_host-objs += mic_fops.o
+mic_host-objs += mic_virtio.o
diff --git a/drivers/misc/mic/host/mic_boot.c b/drivers/misc/mic/host/mic_boot.c
new file mode 100644
index 0000000..b079c65
--- /dev/null
+++ b/drivers/misc/mic/host/mic_boot.c
@@ -0,0 +1,300 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/pci.h>
+
+#include <linux/mic_common.h>
+#include "../common/mic_dev.h"
+#include "mic_device.h"
+#include "mic_smpt.h"
+#include "mic_virtio.h"
+
+/**
+ * mic_reset - Reset the MIC device.
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_reset(struct mic_device *mdev)
+{
+	int i;
+
+#define MIC_RESET_TO (45)
+
+	INIT_COMPLETION(mdev->reset_wait);
+	mdev->ops->reset_fw_ready(mdev);
+	mdev->ops->reset(mdev);
+
+	for (i = 0; i < MIC_RESET_TO; i++) {
+		if (mdev->ops->is_fw_ready(mdev))
+			goto done;
+		/*
+		 * Resets typically take 10s of seconds to complete.
+		 * Since an MMIO read is required to check if the
+		 * firmware is ready or not, a 1 second delay works nicely.
+		 */
+		msleep(1000);
+	}
+	mic_set_state(mdev, MIC_RESET_FAILED);
+done:
+	complete_all(&mdev->reset_wait);
+}
+
+/* Initialize the MIC bootparams */
+void mic_bootparam_init(struct mic_device *mdev)
+{
+	struct mic_bootparam *bootparam = mdev->dp;
+
+	bootparam->magic = MIC_MAGIC;
+	bootparam->c2h_shutdown_db = mdev->shutdown_db;
+	bootparam->h2c_shutdown_db = -1;
+	bootparam->h2c_config_db = -1;
+	bootparam->shutdown_status = 0;
+	bootparam->shutdown_card = 0;
+}
+
+/**
+ * mic_start - Start the MIC.
+ * @mdev: pointer to mic_device instance
+ * @buf: buffer containing boot string including firmware/ramdisk path.
+ *
+ * This function prepares an MIC for boot and initiates boot.
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+int mic_start(struct mic_device *mdev, const char *buf)
+{
+	int rc;
+	mutex_lock(&mdev->mic_mutex);
+retry:
+	if (MIC_OFFLINE != mdev->state) {
+		rc = -EINVAL;
+		goto unlock_ret;
+	}
+	if (!mdev->ops->is_fw_ready(mdev)) {
+		mic_reset(mdev);
+		/*
+		 * The state will either be MIC_OFFLINE if the reset succeeded
+		 * or MIC_RESET_FAILED if the firmware reset failed.
+		 */
+		goto retry;
+	}
+	rc = mdev->ops->load_mic_fw(mdev, buf);
+	if (rc)
+		goto unlock_ret;
+	mic_smpt_restore(mdev);
+	mic_intr_restore(mdev);
+	mdev->intr_ops->enable_interrupts(mdev);
+	mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev->dp_dma_addr);
+	mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32);
+	mdev->ops->send_firmware_intr(mdev);
+	mic_set_state(mdev, MIC_ONLINE);
+unlock_ret:
+	mutex_unlock(&mdev->mic_mutex);
+	return rc;
+}
+
+/**
+ * mic_stop - Prepare the MIC for reset and trigger reset.
+ * @mdev: pointer to mic_device instance
+ * @force: force a MIC to reset even if it is already offline.
+ *
+ * RETURNS: None.
+ */
+void mic_stop(struct mic_device *mdev, bool force)
+{
+	mutex_lock(&mdev->mic_mutex);
+	if (MIC_OFFLINE != mdev->state || force) {
+		mic_virtio_reset_devices(mdev);
+		mic_bootparam_init(mdev);
+		mic_reset(mdev);
+		if (MIC_RESET_FAILED == mdev->state)
+			goto unlock;
+		mic_set_shutdown_status(mdev, MIC_NOP);
+		if (MIC_SUSPENDED != mdev->state)
+			mic_set_state(mdev, MIC_OFFLINE);
+	}
+unlock:
+	mutex_unlock(&mdev->mic_mutex);
+}
+
+/**
+ * mic_shutdown - Initiate MIC shutdown.
+ * @mdev: pointer to mic_device instance
+ *
+ * RETURNS: None.
+ */
+void mic_shutdown(struct mic_device *mdev)
+{
+	struct mic_bootparam *bootparam = mdev->dp;
+	s8 db = bootparam->h2c_shutdown_db;
+
+	mutex_lock(&mdev->mic_mutex);
+	if (MIC_ONLINE == mdev->state && db != -1) {
+		bootparam->shutdown_card = 1;
+		mdev->ops->send_intr(mdev, db);
+		mic_set_state(mdev, MIC_SHUTTING_DOWN);
+	}
+	mutex_unlock(&mdev->mic_mutex);
+}
+
+/**
+ * mic_shutdown_work - Handle shutdown interrupt from MIC.
+ * @work: The work structure.
+ *
+ * This work is scheduled whenever the host has received a shutdown
+ * interrupt from the MIC.
+ */
+void mic_shutdown_work(struct work_struct *work)
+{
+	struct mic_device *mdev = container_of(work, struct mic_device,
+			shutdown_work);
+	struct mic_bootparam *bootparam = mdev->dp;
+
+	mutex_lock(&mdev->mic_mutex);
+	mic_set_shutdown_status(mdev, bootparam->shutdown_status);
+	bootparam->shutdown_status = 0;
+
+	/*
+	 * if state is MIC_SUSPENDED, OSPM suspend is in progress. We do not
+	 * change the state here so as to prevent users from booting the card
+	 * during and after the suspend operation.
+	 */
+	if (MIC_SHUTTING_DOWN != mdev->state &&
+	    MIC_SUSPENDED != mdev->state)
+		mic_set_state(mdev, MIC_SHUTTING_DOWN);
+	mutex_unlock(&mdev->mic_mutex);
+}
+
+/**
+ * mic_reset_trigger_work - Trigger MIC reset.
+ * @work: The work structure.
+ *
+ * This work is scheduled whenever the host wants to reset the MIC.
+ */
+void mic_reset_trigger_work(struct work_struct *work)
+{
+	struct mic_device *mdev = container_of(work, struct mic_device,
+			reset_trigger_work);
+
+	mic_stop(mdev, false);
+}
+
+/**
+ * mic_complete_resume - Complete MIC Resume after an OSPM suspend/hibernate
+ * event.
+ * @mdev: pointer to mic_device instance
+ *
+ * RETURNS: None.
+ */
+void mic_complete_resume(struct mic_device *mdev)
+{
+	if (mdev->state != MIC_SUSPENDED) {
+		dev_warn(mdev->sdev->parent, "state %d should be %d\n",
+			 mdev->state, MIC_SUSPENDED);
+		return;
+	}
+
+	/* Make sure firmware is ready */
+	if (!mdev->ops->is_fw_ready(mdev))
+		mic_stop(mdev, true);
+
+	mutex_lock(&mdev->mic_mutex);
+	mic_set_state(mdev, MIC_OFFLINE);
+	mutex_unlock(&mdev->mic_mutex);
+}
+
+/**
+ * mic_prepare_suspend - Handle suspend notification for the MIC device.
+ * @mdev: pointer to mic_device instance
+ *
+ * RETURNS: None.
+ */
+void mic_prepare_suspend(struct mic_device *mdev)
+{
+	int rc;
+
+#define MIC_SUSPEND_TIMEOUT (60 * HZ)
+
+	mutex_lock(&mdev->mic_mutex);
+	switch (mdev->state) {
+	case MIC_OFFLINE:
+		/*
+		 * Card is already offline. Set state to MIC_SUSPENDED
+		 * to prevent users from booting the card.
+		 */
+		mic_set_state(mdev, MIC_SUSPENDED);
+		mutex_unlock(&mdev->mic_mutex);
+		break;
+	case MIC_ONLINE:
+		/*
+		 * Card is online. Set state to MIC_SUSPENDING and notify
+		 * MIC user space daemon which will issue card
+		 * shutdown and reset.
+		 */
+		mic_set_state(mdev, MIC_SUSPENDING);
+		mutex_unlock(&mdev->mic_mutex);
+		rc = wait_for_completion_timeout(&mdev->reset_wait,
+						MIC_SUSPEND_TIMEOUT);
+		/* Force reset the card if the shutdown completion timed out */
+		if (!rc) {
+			mutex_lock(&mdev->mic_mutex);
+			mic_set_state(mdev, MIC_SUSPENDED);
+			mutex_unlock(&mdev->mic_mutex);
+			mic_stop(mdev, true);
+		}
+		break;
+	case MIC_SHUTTING_DOWN:
+		/*
+		 * Card is shutting down. Set state to MIC_SUSPENDED
+		 * to prevent further boot of the card.
+		 */
+		mic_set_state(mdev, MIC_SUSPENDED);
+		mutex_unlock(&mdev->mic_mutex);
+		rc = wait_for_completion_timeout(&mdev->reset_wait,
+						MIC_SUSPEND_TIMEOUT);
+		/* Force reset the card if the shutdown completion timed out */
+		if (!rc)
+			mic_stop(mdev, true);
+		break;
+	default:
+		mutex_unlock(&mdev->mic_mutex);
+		break;
+	}
+}
+
+/**
+ * mic_suspend - Initiate MIC suspend. Suspend merely issues card shutdown.
+ * @mdev: pointer to mic_device instance
+ *
+ * RETURNS: None.
+ */
+void mic_suspend(struct mic_device *mdev)
+{
+	struct mic_bootparam *bootparam = mdev->dp;
+	s8 db = bootparam->h2c_shutdown_db;
+
+	mutex_lock(&mdev->mic_mutex);
+	if (MIC_SUSPENDING == mdev->state && db != -1) {
+		bootparam->shutdown_card = 1;
+		mdev->ops->send_intr(mdev, db);
+		mic_set_state(mdev, MIC_SUSPENDED);
+	}
+	mutex_unlock(&mdev->mic_mutex);
+}
diff --git a/drivers/misc/mic/host/mic_debugfs.c b/drivers/misc/mic/host/mic_debugfs.c
new file mode 100644
index 0000000..028ba5d6
--- /dev/null
+++ b/drivers/misc/mic/host/mic_debugfs.c
@@ -0,0 +1,491 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#include <linux/debugfs.h>
+#include <linux/pci.h>
+#include <linux/seq_file.h>
+
+#include <linux/mic_common.h>
+#include "../common/mic_dev.h"
+#include "mic_device.h"
+#include "mic_smpt.h"
+#include "mic_virtio.h"
+
+/* Debugfs parent dir */
+static struct dentry *mic_dbg;
+
+/**
+ * mic_log_buf_show - Display MIC kernel log buffer.
+ *
+ * log_buf addr/len is read from System.map by user space
+ * and populated in sysfs entries.
+ */
+static int mic_log_buf_show(struct seq_file *s, void *unused)
+{
+	void __iomem *log_buf_va;
+	int __iomem *log_buf_len_va;
+	struct mic_device *mdev = s->private;
+	void *kva;
+	int size;
+	unsigned long aper_offset;
+
+	if (!mdev || !mdev->log_buf_addr || !mdev->log_buf_len)
+		goto done;
+	/*
+	 * Card kernel will never be relocated and any kernel text/data mapping
+	 * can be translated to phys address by subtracting __START_KERNEL_map.
+	 */
+	aper_offset = (unsigned long)mdev->log_buf_len - __START_KERNEL_map;
+	log_buf_len_va = mdev->aper.va + aper_offset;
+	aper_offset = (unsigned long)mdev->log_buf_addr - __START_KERNEL_map;
+	log_buf_va = mdev->aper.va + aper_offset;
+	size = ioread32(log_buf_len_va);
+
+	kva = kmalloc(size, GFP_KERNEL);
+	if (!kva)
+		goto done;
+	mutex_lock(&mdev->mic_mutex);
+	memcpy_fromio(kva, log_buf_va, size);
+	switch (mdev->state) {
+	case MIC_ONLINE:
+		/* Fall through */
+	case MIC_SHUTTING_DOWN:
+		seq_write(s, kva, size);
+		break;
+	default:
+		break;
+	}
+	mutex_unlock(&mdev->mic_mutex);
+	kfree(kva);
+done:
+	return 0;
+}
+
+static int mic_log_buf_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mic_log_buf_show, inode->i_private);
+}
+
+static int mic_log_buf_release(struct inode *inode, struct file *file)
+{
+	return single_release(inode, file);
+}
+
+static const struct file_operations log_buf_ops = {
+	.owner   = THIS_MODULE,
+	.open    = mic_log_buf_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = mic_log_buf_release
+};
+
+static int mic_smpt_show(struct seq_file *s, void *pos)
+{
+	int i;
+	struct mic_device *mdev = s->private;
+	unsigned long flags;
+
+	seq_printf(s, "MIC %-2d |%-10s| %-14s %-10s\n",
+		   mdev->id, "SMPT entry", "SW DMA addr", "RefCount");
+	seq_puts(s, "====================================================\n");
+
+	if (mdev->smpt) {
+		struct mic_smpt_info *smpt_info = mdev->smpt;
+		spin_lock_irqsave(&smpt_info->smpt_lock, flags);
+		for (i = 0; i < smpt_info->info.num_reg; i++) {
+			seq_printf(s, "%9s|%-10d| %-#14llx %-10lld\n",
+				   " ",  i, smpt_info->entry[i].dma_addr,
+				   smpt_info->entry[i].ref_count);
+		}
+		spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
+	}
+	seq_puts(s, "====================================================\n");
+	return 0;
+}
+
+static int mic_smpt_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mic_smpt_show, inode->i_private);
+}
+
+static int mic_smpt_debug_release(struct inode *inode, struct file *file)
+{
+	return single_release(inode, file);
+}
+
+static const struct file_operations smpt_file_ops = {
+	.owner   = THIS_MODULE,
+	.open    = mic_smpt_debug_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = mic_smpt_debug_release
+};
+
+static int mic_soft_reset_show(struct seq_file *s, void *pos)
+{
+	struct mic_device *mdev = s->private;
+
+	mic_stop(mdev, true);
+	return 0;
+}
+
+static int mic_soft_reset_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mic_soft_reset_show, inode->i_private);
+}
+
+static int mic_soft_reset_debug_release(struct inode *inode, struct file *file)
+{
+	return single_release(inode, file);
+}
+
+static const struct file_operations soft_reset_ops = {
+	.owner   = THIS_MODULE,
+	.open    = mic_soft_reset_debug_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = mic_soft_reset_debug_release
+};
+
+static int mic_post_code_show(struct seq_file *s, void *pos)
+{
+	struct mic_device *mdev = s->private;
+	u32 reg = mdev->ops->get_postcode(mdev);
+
+	seq_printf(s, "%c%c", reg & 0xff, (reg >> 8) & 0xff);
+	return 0;
+}
+
+static int mic_post_code_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mic_post_code_show, inode->i_private);
+}
+
+static int mic_post_code_debug_release(struct inode *inode, struct file *file)
+{
+	return single_release(inode, file);
+}
+
+static const struct file_operations post_code_ops = {
+	.owner   = THIS_MODULE,
+	.open    = mic_post_code_debug_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = mic_post_code_debug_release
+};
+
+static int mic_dp_show(struct seq_file *s, void *pos)
+{
+	struct mic_device *mdev = s->private;
+	struct mic_device_desc *d;
+	struct mic_device_ctrl *dc;
+	struct mic_vqconfig *vqconfig;
+	__u32 *features;
+	__u8 *config;
+	struct mic_bootparam *bootparam = mdev->dp;
+	int i, j;
+
+	seq_printf(s, "Bootparam: magic 0x%x\n",
+		   bootparam->magic);
+	seq_printf(s, "Bootparam: h2c_shutdown_db %d\n",
+		   bootparam->h2c_shutdown_db);
+	seq_printf(s, "Bootparam: h2c_config_db %d\n",
+		   bootparam->h2c_config_db);
+	seq_printf(s, "Bootparam: c2h_shutdown_db %d\n",
+		   bootparam->c2h_shutdown_db);
+	seq_printf(s, "Bootparam: shutdown_status %d\n",
+		   bootparam->shutdown_status);
+	seq_printf(s, "Bootparam: shutdown_card %d\n",
+		   bootparam->shutdown_card);
+
+	for (i = sizeof(*bootparam); i < MIC_DP_SIZE;
+	     i += mic_total_desc_size(d)) {
+		d = mdev->dp + i;
+		dc = (void *)d + mic_aligned_desc_size(d);
+
+		/* end of list */
+		if (d->type == 0)
+			break;
+
+		if (d->type == -1)
+			continue;
+
+		seq_printf(s, "Type %d ", d->type);
+		seq_printf(s, "Num VQ %d ", d->num_vq);
+		seq_printf(s, "Feature Len %d\n", d->feature_len);
+		seq_printf(s, "Config Len %d ", d->config_len);
+		seq_printf(s, "Shutdown Status %d\n", d->status);
+
+		for (j = 0; j < d->num_vq; j++) {
+			vqconfig = mic_vq_config(d) + j;
+			seq_printf(s, "vqconfig[%d]: ", j);
+			seq_printf(s, "address 0x%llx ", vqconfig->address);
+			seq_printf(s, "num %d ", vqconfig->num);
+			seq_printf(s, "used address 0x%llx\n",
+				   vqconfig->used_address);
+		}
+
+		features = (__u32 *)mic_vq_features(d);
+		seq_printf(s, "Features: Host 0x%x ", features[0]);
+		seq_printf(s, "Guest 0x%x\n", features[1]);
+
+		config = mic_vq_configspace(d);
+		for (j = 0; j < d->config_len; j++)
+			seq_printf(s, "config[%d]=%d\n", j, config[j]);
+
+		seq_puts(s, "Device control:\n");
+		seq_printf(s, "Config Change %d ", dc->config_change);
+		seq_printf(s, "Vdev reset %d\n", dc->vdev_reset);
+		seq_printf(s, "Guest Ack %d ", dc->guest_ack);
+		seq_printf(s, "Host ack %d\n", dc->host_ack);
+		seq_printf(s, "Used address updated %d ",
+			   dc->used_address_updated);
+		seq_printf(s, "Vdev 0x%llx\n", dc->vdev);
+		seq_printf(s, "c2h doorbell %d ", dc->c2h_vdev_db);
+		seq_printf(s, "h2c doorbell %d\n", dc->h2c_vdev_db);
+	}
+
+	return 0;
+}
+
+static int mic_dp_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mic_dp_show, inode->i_private);
+}
+
+static int mic_dp_debug_release(struct inode *inode, struct file *file)
+{
+	return single_release(inode, file);
+}
+
+static const struct file_operations dp_ops = {
+	.owner   = THIS_MODULE,
+	.open    = mic_dp_debug_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = mic_dp_debug_release
+};
+
+static int mic_vdev_info_show(struct seq_file *s, void *unused)
+{
+	struct mic_device *mdev = s->private;
+	struct list_head *pos, *tmp;
+	struct mic_vdev *mvdev;
+	int i, j;
+
+	mutex_lock(&mdev->mic_mutex);
+	list_for_each_safe(pos, tmp, &mdev->vdev_list) {
+		mvdev = list_entry(pos, struct mic_vdev, list);
+		seq_printf(s, "VDEV type %d state %s in %ld out %ld\n",
+			   mvdev->virtio_id,
+			   mic_vdevup(mvdev) ? "UP" : "DOWN",
+			   mvdev->in_bytes,
+			   mvdev->out_bytes);
+		for (i = 0; i < MIC_MAX_VRINGS; i++) {
+			struct vring_desc *desc;
+			struct vring_avail *avail;
+			struct vring_used *used;
+			struct mic_vringh *mvr = &mvdev->mvr[i];
+			struct vringh *vrh = &mvr->vrh;
+			int num = vrh->vring.num;
+			if (!num)
+				continue;
+			desc = vrh->vring.desc;
+			seq_printf(s, "vring i %d avail_idx %d",
+				   i, mvr->vring.info->avail_idx & (num - 1));
+			seq_printf(s, " vring i %d avail_idx %d\n",
+				   i, mvr->vring.info->avail_idx);
+			seq_printf(s, "vrh i %d weak_barriers %d",
+				   i, vrh->weak_barriers);
+			seq_printf(s, " last_avail_idx %d last_used_idx %d",
+				   vrh->last_avail_idx, vrh->last_used_idx);
+			seq_printf(s, " completed %d\n", vrh->completed);
+			for (j = 0; j < num; j++) {
+				seq_printf(s, "desc[%d] addr 0x%llx len %d",
+					   j, desc->addr, desc->len);
+				seq_printf(s, " flags 0x%x next %d\n",
+					   desc->flags, desc->next);
+				desc++;
+			}
+			avail = vrh->vring.avail;
+			seq_printf(s, "avail flags 0x%x idx %d\n",
+				   avail->flags, avail->idx & (num - 1));
+			seq_printf(s, "avail flags 0x%x idx %d\n",
+				   avail->flags, avail->idx);
+			for (j = 0; j < num; j++)
+				seq_printf(s, "avail ring[%d] %d\n",
+					   j, avail->ring[j]);
+			used = vrh->vring.used;
+			seq_printf(s, "used flags 0x%x idx %d\n",
+				   used->flags, used->idx & (num - 1));
+			seq_printf(s, "used flags 0x%x idx %d\n",
+				   used->flags, used->idx);
+			for (j = 0; j < num; j++)
+				seq_printf(s, "used ring[%d] id %d len %d\n",
+					   j, used->ring[j].id,
+					   used->ring[j].len);
+		}
+	}
+	mutex_unlock(&mdev->mic_mutex);
+
+	return 0;
+}
+
+static int mic_vdev_info_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mic_vdev_info_show, inode->i_private);
+}
+
+static int mic_vdev_info_debug_release(struct inode *inode, struct file *file)
+{
+	return single_release(inode, file);
+}
+
+static const struct file_operations vdev_info_ops = {
+	.owner   = THIS_MODULE,
+	.open    = mic_vdev_info_debug_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = mic_vdev_info_debug_release
+};
+
+static int mic_msi_irq_info_show(struct seq_file *s, void *pos)
+{
+	struct mic_device *mdev  = s->private;
+	int reg;
+	int i, j;
+	u16 entry;
+	u16 vector;
+	struct pci_dev *pdev = container_of(mdev->sdev->parent,
+		struct pci_dev, dev);
+
+	if (pci_dev_msi_enabled(pdev)) {
+		for (i = 0; i < mdev->irq_info.num_vectors; i++) {
+			if (pdev->msix_enabled) {
+				entry = mdev->irq_info.msix_entries[i].entry;
+				vector = mdev->irq_info.msix_entries[i].vector;
+			} else {
+				entry = 0;
+				vector = pdev->irq;
+			}
+
+			reg = mdev->intr_ops->read_msi_to_src_map(mdev, entry);
+
+			seq_printf(s, "%s %-10d %s %-10d MXAR[%d]: %08X\n",
+				   "IRQ:", vector, "Entry:", entry, i, reg);
+
+			seq_printf(s, "%-10s", "offset:");
+			for (j = (MIC_NUM_OFFSETS - 1); j >= 0; j--)
+				seq_printf(s, "%4d ", j);
+			seq_puts(s, "\n");
+
+
+			seq_printf(s, "%-10s", "count:");
+			for (j = (MIC_NUM_OFFSETS - 1); j >= 0; j--)
+				seq_printf(s, "%4d ",
+					   (mdev->irq_info.mic_msi_map[i] &
+					   BIT(j)) ? 1 : 0);
+			seq_puts(s, "\n\n");
+		}
+	} else {
+		seq_puts(s, "MSI/MSIx interrupts not enabled\n");
+	}
+
+	return 0;
+}
+
+static int mic_msi_irq_info_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mic_msi_irq_info_show, inode->i_private);
+}
+
+static int
+mic_msi_irq_info_debug_release(struct inode *inode, struct file *file)
+{
+	return single_release(inode, file);
+}
+
+static const struct file_operations msi_irq_info_ops = {
+	.owner   = THIS_MODULE,
+	.open    = mic_msi_irq_info_debug_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = mic_msi_irq_info_debug_release
+};
+
+/**
+ * mic_create_debug_dir - Initialize MIC debugfs entries.
+ */
+void mic_create_debug_dir(struct mic_device *mdev)
+{
+	if (!mic_dbg)
+		return;
+
+	mdev->dbg_dir = debugfs_create_dir(dev_name(mdev->sdev), mic_dbg);
+	if (!mdev->dbg_dir)
+		return;
+
+	debugfs_create_file("log_buf", 0444, mdev->dbg_dir, mdev, &log_buf_ops);
+
+	debugfs_create_file("smpt", 0444, mdev->dbg_dir, mdev, &smpt_file_ops);
+
+	debugfs_create_file("soft_reset", 0444, mdev->dbg_dir, mdev,
+			    &soft_reset_ops);
+
+	debugfs_create_file("post_code", 0444, mdev->dbg_dir, mdev,
+			    &post_code_ops);
+
+	debugfs_create_file("dp", 0444, mdev->dbg_dir, mdev, &dp_ops);
+
+	debugfs_create_file("vdev_info", 0444, mdev->dbg_dir, mdev,
+			    &vdev_info_ops);
+
+	debugfs_create_file("msi_irq_info", 0444, mdev->dbg_dir, mdev,
+			    &msi_irq_info_ops);
+}
+
+/**
+ * mic_delete_debug_dir - Uninitialize MIC debugfs entries.
+ */
+void mic_delete_debug_dir(struct mic_device *mdev)
+{
+	if (!mdev->dbg_dir)
+		return;
+
+	debugfs_remove_recursive(mdev->dbg_dir);
+}
+
+/**
+ * mic_init_debugfs - Initialize global debugfs entry.
+ */
+void __init mic_init_debugfs(void)
+{
+	mic_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
+	if (!mic_dbg)
+		pr_err("can't create debugfs dir\n");
+}
+
+/**
+ * mic_exit_debugfs - Uninitialize global debugfs entry
+ */
+void mic_exit_debugfs(void)
+{
+	debugfs_remove(mic_dbg);
+}
diff --git a/drivers/misc/mic/host/mic_device.h b/drivers/misc/mic/host/mic_device.h
new file mode 100644
index 0000000..3574cc3
--- /dev/null
+++ b/drivers/misc/mic/host/mic_device.h
@@ -0,0 +1,203 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#ifndef _MIC_DEVICE_H_
+#define _MIC_DEVICE_H_
+
+#include <linux/cdev.h>
+#include <linux/idr.h>
+#include <linux/notifier.h>
+
+#include "mic_intr.h"
+
+/* The maximum number of MIC devices supported in a single host system. */
+#define MIC_MAX_NUM_DEVS 256
+
+/**
+ * enum mic_hw_family - The hardware family to which a device belongs.
+ */
+enum mic_hw_family {
+	MIC_FAMILY_X100 = 0,
+	MIC_FAMILY_UNKNOWN
+};
+
+/**
+ * enum mic_stepping - MIC stepping ids.
+ */
+enum mic_stepping {
+	MIC_A0_STEP = 0x0,
+	MIC_B0_STEP = 0x10,
+	MIC_B1_STEP = 0x11,
+	MIC_C0_STEP = 0x20,
+};
+
+/**
+ * struct mic_device -  MIC device information for each card.
+ *
+ * @mmio: MMIO bar information.
+ * @aper: Aperture bar information.
+ * @family: The MIC family to which this device belongs.
+ * @ops: MIC HW specific operations.
+ * @id: The unique device id for this MIC device.
+ * @stepping: Stepping ID.
+ * @attr_group: Pointer to list of sysfs attribute groups.
+ * @sdev: Device for sysfs entries.
+ * @mic_mutex: Mutex for synchronizing access to mic_device.
+ * @intr_ops: HW specific interrupt operations.
+ * @smpt_ops: Hardware specific SMPT operations.
+ * @smpt: MIC SMPT information.
+ * @intr_info: H/W specific interrupt information.
+ * @irq_info: The OS specific irq information
+ * @dbg_dir: debugfs directory of this MIC device.
+ * @cmdline: Kernel command line.
+ * @firmware: Firmware file name.
+ * @ramdisk: Ramdisk file name.
+ * @bootmode: Boot mode i.e. "linux" or "elf" for flash updates.
+ * @bootaddr: MIC boot address.
+ * @reset_trigger_work: Work for triggering reset requests.
+ * @shutdown_work: Work for handling shutdown interrupts.
+ * @state: MIC state.
+ * @shutdown_status: MIC status reported by card for shutdown/crashes.
+ * @state_sysfs: Sysfs dirent for notifying ring 3 about MIC state changes.
+ * @reset_wait: Waitqueue for sleeping while reset completes.
+ * @log_buf_addr: Log buffer address for MIC.
+ * @log_buf_len: Log buffer length address for MIC.
+ * @dp: virtio device page
+ * @dp_dma_addr: virtio device page DMA address.
+ * @shutdown_db: shutdown doorbell.
+ * @shutdown_cookie: shutdown cookie.
+ * @cdev: Character device for MIC.
+ * @vdev_list: list of virtio devices.
+ * @pm_notifier: Handles PM notifications from the OS.
+ */
+struct mic_device {
+	struct mic_mw mmio;
+	struct mic_mw aper;
+	enum mic_hw_family family;
+	struct mic_hw_ops *ops;
+	int id;
+	enum mic_stepping stepping;
+	const struct attribute_group **attr_group;
+	struct device *sdev;
+	struct mutex mic_mutex;
+	struct mic_hw_intr_ops *intr_ops;
+	struct mic_smpt_ops *smpt_ops;
+	struct mic_smpt_info *smpt;
+	struct mic_intr_info *intr_info;
+	struct mic_irq_info irq_info;
+	struct dentry *dbg_dir;
+	char *cmdline;
+	char *firmware;
+	char *ramdisk;
+	char *bootmode;
+	u32 bootaddr;
+	struct work_struct reset_trigger_work;
+	struct work_struct shutdown_work;
+	u8 state;
+	u8 shutdown_status;
+	struct sysfs_dirent *state_sysfs;
+	struct completion reset_wait;
+	void *log_buf_addr;
+	int *log_buf_len;
+	void *dp;
+	dma_addr_t dp_dma_addr;
+	int shutdown_db;
+	struct mic_irq *shutdown_cookie;
+	struct cdev cdev;
+	struct list_head vdev_list;
+	struct notifier_block pm_notifier;
+};
+
+/**
+ * struct mic_hw_ops - MIC HW specific operations.
+ * @aper_bar: Aperture bar resource number.
+ * @mmio_bar: MMIO bar resource number.
+ * @read_spad: Read from scratch pad register.
+ * @write_spad: Write to scratch pad register.
+ * @send_intr: Send an interrupt for a particular doorbell on the card.
+ * @ack_interrupt: Hardware specific operations to ack the h/w on
+ * receipt of an interrupt.
+ * @reset: Reset the remote processor.
+ * @reset_fw_ready: Reset firmware ready field.
+ * @is_fw_ready: Check if firmware is ready for OS download.
+ * @send_firmware_intr: Send an interrupt to the card firmware.
+ * @load_mic_fw: Load firmware segments required to boot the card
+ * into card memory. This includes the kernel, command line, ramdisk etc.
+ * @get_postcode: Get post code status from firmware.
+ */
+struct mic_hw_ops {
+	u8 aper_bar;
+	u8 mmio_bar;
+	u32 (*read_spad)(struct mic_device *mdev, unsigned int idx);
+	void (*write_spad)(struct mic_device *mdev, unsigned int idx, u32 val);
+	void (*send_intr)(struct mic_device *mdev, int doorbell);
+	u32 (*ack_interrupt)(struct mic_device *mdev);
+	void (*reset)(struct mic_device *mdev);
+	void (*reset_fw_ready)(struct mic_device *mdev);
+	bool (*is_fw_ready)(struct mic_device *mdev);
+	void (*send_firmware_intr)(struct mic_device *mdev);
+	int (*load_mic_fw)(struct mic_device *mdev, const char *buf);
+	u32 (*get_postcode)(struct mic_device *mdev);
+};
+
+/**
+ * mic_mmio_read - read from an MMIO register.
+ * @mw: MMIO register base virtual address.
+ * @offset: register offset.
+ *
+ * RETURNS: register value.
+ */
+static inline u32 mic_mmio_read(struct mic_mw *mw, u32 offset)
+{
+	return ioread32(mw->va + offset);
+}
+
+/**
+ * mic_mmio_write - write to an MMIO register.
+ * @mw: MMIO register base virtual address.
+ * @val: the data value to put into the register
+ * @offset: register offset.
+ *
+ * RETURNS: none.
+ */
+static inline void
+mic_mmio_write(struct mic_mw *mw, u32 val, u32 offset)
+{
+	iowrite32(val, mw->va + offset);
+}
+
+void mic_sysfs_init(struct mic_device *mdev);
+int mic_start(struct mic_device *mdev, const char *buf);
+void mic_stop(struct mic_device *mdev, bool force);
+void mic_shutdown(struct mic_device *mdev);
+void mic_reset_delayed_work(struct work_struct *work);
+void mic_reset_trigger_work(struct work_struct *work);
+void mic_shutdown_work(struct work_struct *work);
+void mic_bootparam_init(struct mic_device *mdev);
+void mic_set_state(struct mic_device *mdev, u8 state);
+void mic_set_shutdown_status(struct mic_device *mdev, u8 status);
+void mic_create_debug_dir(struct mic_device *dev);
+void mic_delete_debug_dir(struct mic_device *dev);
+void __init mic_init_debugfs(void);
+void mic_exit_debugfs(void);
+void mic_prepare_suspend(struct mic_device *mdev);
+void mic_complete_resume(struct mic_device *mdev);
+void mic_suspend(struct mic_device *mdev);
+#endif
diff --git a/drivers/misc/mic/host/mic_fops.c b/drivers/misc/mic/host/mic_fops.c
new file mode 100644
index 0000000..85776d7
--- /dev/null
+++ b/drivers/misc/mic/host/mic_fops.c
@@ -0,0 +1,222 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#include <linux/poll.h>
+#include <linux/pci.h>
+
+#include <linux/mic_common.h>
+#include "../common/mic_dev.h"
+#include "mic_device.h"
+#include "mic_fops.h"
+#include "mic_virtio.h"
+
+int mic_open(struct inode *inode, struct file *f)
+{
+	struct mic_vdev *mvdev;
+	struct mic_device *mdev = container_of(inode->i_cdev,
+		struct mic_device, cdev);
+
+	mvdev = kzalloc(sizeof(*mvdev), GFP_KERNEL);
+	if (!mvdev)
+		return -ENOMEM;
+
+	init_waitqueue_head(&mvdev->waitq);
+	INIT_LIST_HEAD(&mvdev->list);
+	mvdev->mdev = mdev;
+	mvdev->virtio_id = -1;
+
+	f->private_data = mvdev;
+	return 0;
+}
+
+int mic_release(struct inode *inode, struct file *f)
+{
+	struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data;
+
+	if (-1 != mvdev->virtio_id)
+		mic_virtio_del_device(mvdev);
+	f->private_data = NULL;
+	kfree(mvdev);
+	return 0;
+}
+
+long mic_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data;
+	void __user *argp = (void __user *)arg;
+	int ret;
+
+	switch (cmd) {
+	case MIC_VIRTIO_ADD_DEVICE:
+	{
+		ret = mic_virtio_add_device(mvdev, argp);
+		if (ret < 0) {
+			dev_err(mic_dev(mvdev),
+				"%s %d errno ret %d\n",
+				__func__, __LINE__, ret);
+			return ret;
+		}
+		break;
+	}
+	case MIC_VIRTIO_COPY_DESC:
+	{
+		struct mic_copy_desc copy;
+
+		ret = mic_vdev_inited(mvdev);
+		if (ret)
+			return ret;
+
+		if (copy_from_user(&copy, argp, sizeof(copy)))
+			return -EFAULT;
+
+		dev_dbg(mic_dev(mvdev),
+			"%s %d === iovcnt 0x%x vr_idx 0x%x update_used %d\n",
+			__func__, __LINE__, copy.iovcnt, copy.vr_idx,
+			copy.update_used);
+
+		ret = mic_virtio_copy_desc(mvdev, &copy);
+		if (ret < 0) {
+			dev_err(mic_dev(mvdev),
+				"%s %d errno ret %d\n",
+				__func__, __LINE__, ret);
+			return ret;
+		}
+		if (copy_to_user(
+			&((struct mic_copy_desc __user *)argp)->out_len,
+			&copy.out_len, sizeof(copy.out_len))) {
+			dev_err(mic_dev(mvdev), "%s %d errno ret %d\n",
+				__func__, __LINE__, -EFAULT);
+			return -EFAULT;
+		}
+		break;
+	}
+	case MIC_VIRTIO_CONFIG_CHANGE:
+	{
+		ret = mic_vdev_inited(mvdev);
+		if (ret)
+			return ret;
+
+		ret = mic_virtio_config_change(mvdev, argp);
+		if (ret < 0) {
+			dev_err(mic_dev(mvdev),
+				"%s %d errno ret %d\n",
+				__func__, __LINE__, ret);
+			return ret;
+		}
+		break;
+	}
+	default:
+		return -ENOIOCTLCMD;
+	};
+	return 0;
+}
+
+/*
+ * We return POLLIN | POLLOUT from poll when new buffers are enqueued, and
+ * not when previously enqueued buffers may be available. This means that
+ * in the card->host (TX) path, when userspace is unblocked by poll it
+ * must drain all available descriptors or it can stall.
+ */
+unsigned int mic_poll(struct file *f, poll_table *wait)
+{
+	struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data;
+	int mask = 0;
+
+	poll_wait(f, &mvdev->waitq, wait);
+
+	if (mic_vdev_inited(mvdev)) {
+		mask = POLLERR;
+	} else if (mvdev->poll_wake) {
+		mvdev->poll_wake = 0;
+		mask = POLLIN | POLLOUT;
+	}
+
+	return mask;
+}
+
+static inline int
+mic_query_offset(struct mic_vdev *mvdev, unsigned long offset,
+		 unsigned long *size, unsigned long *pa)
+{
+	struct mic_device *mdev = mvdev->mdev;
+	unsigned long start = MIC_DP_SIZE;
+	int i;
+
+	/*
+	 * MMAP interface is as follows:
+	 * offset				region
+	 * 0x0					virtio device_page
+	 * 0x1000				first vring
+	 * 0x1000 + size of 1st vring		second vring
+	 * ....
+	 */
+	if (!offset) {
+		*pa = virt_to_phys(mdev->dp);
+		*size = MIC_DP_SIZE;
+		return 0;
+	}
+
+	for (i = 0; i < mvdev->dd->num_vq; i++) {
+		struct mic_vringh *mvr = &mvdev->mvr[i];
+		if (offset == start) {
+			*pa = virt_to_phys(mvr->vring.va);
+			*size = mvr->vring.len;
+			return 0;
+		}
+		start += mvr->vring.len;
+	}
+	return -1;
+}
+
+/*
+ * Maps the device page and virtio rings to user space for readonly access.
+ */
+int
+mic_mmap(struct file *f, struct vm_area_struct *vma)
+{
+	struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data;
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	unsigned long pa, size = vma->vm_end - vma->vm_start, size_rem = size;
+	int i, err;
+
+	err = mic_vdev_inited(mvdev);
+	if (err)
+		return err;
+
+	if (vma->vm_flags & VM_WRITE)
+		return -EACCES;
+
+	while (size_rem) {
+		i = mic_query_offset(mvdev, offset, &size, &pa);
+		if (i < 0)
+			return -EINVAL;
+		err = remap_pfn_range(vma, vma->vm_start + offset,
+			pa >> PAGE_SHIFT, size, vma->vm_page_prot);
+		if (err)
+			return err;
+		dev_dbg(mic_dev(mvdev),
+			"%s %d type %d size 0x%lx off 0x%lx pa 0x%lx vma 0x%lx\n",
+			__func__, __LINE__, mvdev->virtio_id, size, offset,
+			pa, vma->vm_start + offset);
+		size_rem -= size;
+		offset += size;
+	}
+	return 0;
+}
diff --git a/drivers/misc/mic/host/mic_fops.h b/drivers/misc/mic/host/mic_fops.h
new file mode 100644
index 0000000..dc3893d
--- /dev/null
+++ b/drivers/misc/mic/host/mic_fops.h
@@ -0,0 +1,32 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#ifndef _MIC_FOPS_H_
+#define _MIC_FOPS_H_
+
+int mic_open(struct inode *inode, struct file *filp);
+int mic_release(struct inode *inode, struct file *filp);
+ssize_t mic_read(struct file *filp, char __user *buf,
+			size_t count, loff_t *pos);
+long mic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+int mic_mmap(struct file *f, struct vm_area_struct *vma);
+unsigned int mic_poll(struct file *f, poll_table *wait);
+
+#endif
diff --git a/drivers/misc/mic/host/mic_intr.c b/drivers/misc/mic/host/mic_intr.c
new file mode 100644
index 0000000..f9c29bc
--- /dev/null
+++ b/drivers/misc/mic/host/mic_intr.c
@@ -0,0 +1,630 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+
+#include "../common/mic_dev.h"
+#include "mic_device.h"
+
+/*
+ * mic_invoke_callback - Invoke callback functions registered for
+ * the corresponding source id.
+ *
+ * @mdev: pointer to the mic_device instance
+ * @idx: The interrupt source id.
+ *
+ * Returns none.
+ */
+static inline void mic_invoke_callback(struct mic_device *mdev, int idx)
+{
+	struct mic_intr_cb *intr_cb;
+	struct pci_dev *pdev = container_of(mdev->sdev->parent,
+		struct pci_dev, dev);
+
+	spin_lock(&mdev->irq_info.mic_intr_lock);
+	list_for_each_entry(intr_cb, &mdev->irq_info.cb_list[idx], list)
+		if (intr_cb->func)
+			intr_cb->func(pdev->irq, intr_cb->data);
+	spin_unlock(&mdev->irq_info.mic_intr_lock);
+}
+
+/**
+ * mic_interrupt - Generic interrupt handler for
+ * MSI and INTx based interrupts.
+ */
+static irqreturn_t mic_interrupt(int irq, void *dev)
+{
+	struct mic_device *mdev = dev;
+	struct mic_intr_info *info = mdev->intr_info;
+	u32 mask;
+	int i;
+
+	mask = mdev->ops->ack_interrupt(mdev);
+	if (!mask)
+		return IRQ_NONE;
+
+	for (i = info->intr_start_idx[MIC_INTR_DB];
+			i < info->intr_len[MIC_INTR_DB]; i++)
+		if (mask & BIT(i))
+			mic_invoke_callback(mdev, i);
+
+	return IRQ_HANDLED;
+}
+
+/* Return the interrupt offset from the index. Index is 0 based. */
+static u16 mic_map_src_to_offset(struct mic_device *mdev,
+		int intr_src, enum mic_intr_type type)
+{
+	if (type >= MIC_NUM_INTR_TYPES)
+		return MIC_NUM_OFFSETS;
+	if (intr_src >= mdev->intr_info->intr_len[type])
+		return MIC_NUM_OFFSETS;
+
+	return mdev->intr_info->intr_start_idx[type] + intr_src;
+}
+
+/* Return next available msix_entry. */
+static struct msix_entry *mic_get_available_vector(struct mic_device *mdev)
+{
+	int i;
+	struct mic_irq_info *info = &mdev->irq_info;
+
+	for (i = 0; i < info->num_vectors; i++)
+		if (!info->mic_msi_map[i])
+			return &info->msix_entries[i];
+	return NULL;
+}
+
+/**
+ * mic_register_intr_callback - Register a callback handler for the
+ * given source id.
+ *
+ * @mdev: pointer to the mic_device instance
+ * @idx: The source id to be registered.
+ * @func: The function to be called when the source id receives
+ * the interrupt.
+ * @data: Private data of the requester.
+ * Return the callback structure that was registered or an
+ * appropriate error on failure.
+ */
+static struct mic_intr_cb *mic_register_intr_callback(struct mic_device *mdev,
+			u8 idx, irqreturn_t (*func) (int irq, void *dev),
+			void *data)
+{
+	struct mic_intr_cb *intr_cb;
+	unsigned long flags;
+	int rc;
+	intr_cb = kmalloc(sizeof(*intr_cb), GFP_KERNEL);
+
+	if (!intr_cb)
+		return ERR_PTR(-ENOMEM);
+
+	intr_cb->func = func;
+	intr_cb->data = data;
+	intr_cb->cb_id = ida_simple_get(&mdev->irq_info.cb_ida,
+		0, 0, GFP_KERNEL);
+	if (intr_cb->cb_id < 0) {
+		rc = intr_cb->cb_id;
+		goto ida_fail;
+	}
+
+	spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
+	list_add_tail(&intr_cb->list, &mdev->irq_info.cb_list[idx]);
+	spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
+
+	return intr_cb;
+ida_fail:
+	kfree(intr_cb);
+	return ERR_PTR(rc);
+}
+
+/**
+ * mic_unregister_intr_callback - Unregister the callback handler
+ * identified by its callback id.
+ *
+ * @mdev: pointer to the mic_device instance
+ * @idx: The callback structure id to be unregistered.
+ * Return the source id that was unregistered or MIC_NUM_OFFSETS if no
+ * such callback handler was found.
+ */
+static u8 mic_unregister_intr_callback(struct mic_device *mdev, u32 idx)
+{
+	struct list_head *pos, *tmp;
+	struct mic_intr_cb *intr_cb;
+	unsigned long flags;
+	int i;
+
+	for (i = 0;  i < MIC_NUM_OFFSETS; i++) {
+		spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
+		list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
+			intr_cb = list_entry(pos, struct mic_intr_cb, list);
+			if (intr_cb->cb_id == idx) {
+				list_del(pos);
+				ida_simple_remove(&mdev->irq_info.cb_ida,
+						  intr_cb->cb_id);
+				kfree(intr_cb);
+				spin_unlock_irqrestore(
+					&mdev->irq_info.mic_intr_lock, flags);
+				return i;
+			}
+		}
+		spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
+	}
+	return MIC_NUM_OFFSETS;
+}
+
+/**
+ * mic_setup_msix - Initializes MSIx interrupts.
+ *
+ * @mdev: pointer to mic_device instance
+ *
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+static int mic_setup_msix(struct mic_device *mdev, struct pci_dev *pdev)
+{
+	int rc, i;
+	int entry_size = sizeof(*mdev->irq_info.msix_entries);
+
+	mdev->irq_info.msix_entries = kmalloc_array(MIC_MIN_MSIX,
+						    entry_size, GFP_KERNEL);
+	if (!mdev->irq_info.msix_entries) {
+		rc = -ENOMEM;
+		goto err_nomem1;
+	}
+
+	for (i = 0; i < MIC_MIN_MSIX; i++)
+		mdev->irq_info.msix_entries[i].entry = i;
+
+	rc = pci_enable_msix(pdev, mdev->irq_info.msix_entries,
+		MIC_MIN_MSIX);
+	if (rc) {
+		dev_dbg(&pdev->dev, "Error enabling MSIx. rc = %d\n", rc);
+		goto err_enable_msix;
+	}
+
+	mdev->irq_info.num_vectors = MIC_MIN_MSIX;
+	mdev->irq_info.mic_msi_map = kzalloc((sizeof(u32) *
+		mdev->irq_info.num_vectors), GFP_KERNEL);
+
+	if (!mdev->irq_info.mic_msi_map) {
+		rc = -ENOMEM;
+		goto err_nomem2;
+	}
+
+	dev_dbg(mdev->sdev->parent,
+		"%d MSIx irqs setup\n", mdev->irq_info.num_vectors);
+	return 0;
+err_nomem2:
+	pci_disable_msix(pdev);
+err_enable_msix:
+	kfree(mdev->irq_info.msix_entries);
+err_nomem1:
+	mdev->irq_info.num_vectors = 0;
+	return rc;
+}
+
+/**
+ * mic_setup_callbacks - Initialize data structures needed
+ * to handle callbacks.
+ *
+ * @mdev: pointer to mic_device instance
+ */
+static int mic_setup_callbacks(struct mic_device *mdev)
+{
+	int i;
+
+	mdev->irq_info.cb_list = kmalloc_array(MIC_NUM_OFFSETS,
+					       sizeof(*mdev->irq_info.cb_list),
+					       GFP_KERNEL);
+	if (!mdev->irq_info.cb_list)
+		return -ENOMEM;
+
+	for (i = 0; i < MIC_NUM_OFFSETS; i++)
+		INIT_LIST_HEAD(&mdev->irq_info.cb_list[i]);
+	ida_init(&mdev->irq_info.cb_ida);
+	spin_lock_init(&mdev->irq_info.mic_intr_lock);
+	return 0;
+}
+
+/**
+ * mic_release_callbacks - Uninitialize data structures needed
+ * to handle callbacks.
+ *
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_release_callbacks(struct mic_device *mdev)
+{
+	unsigned long flags;
+	struct list_head *pos, *tmp;
+	struct mic_intr_cb *intr_cb;
+	int i;
+
+	for (i = 0; i < MIC_NUM_OFFSETS; i++) {
+		spin_lock_irqsave(&mdev->irq_info.mic_intr_lock, flags);
+
+		if (list_empty(&mdev->irq_info.cb_list[i])) {
+			spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock,
+					       flags);
+			break;
+		}
+
+		list_for_each_safe(pos, tmp, &mdev->irq_info.cb_list[i]) {
+			intr_cb = list_entry(pos, struct mic_intr_cb, list);
+			list_del(pos);
+			ida_simple_remove(&mdev->irq_info.cb_ida,
+					  intr_cb->cb_id);
+			kfree(intr_cb);
+		}
+		spin_unlock_irqrestore(&mdev->irq_info.mic_intr_lock, flags);
+	}
+	ida_destroy(&mdev->irq_info.cb_ida);
+	kfree(mdev->irq_info.cb_list);
+}
+
+/**
+ * mic_setup_msi - Initializes MSI interrupts.
+ *
+ * @mdev: pointer to mic_device instance
+ * @pdev: PCI device structure
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+static int mic_setup_msi(struct mic_device *mdev, struct pci_dev *pdev)
+{
+	int rc;
+
+	rc = pci_enable_msi(pdev);
+	if (rc) {
+		dev_dbg(&pdev->dev, "Error enabling MSI. rc = %d\n", rc);
+		return rc;
+	}
+
+	mdev->irq_info.num_vectors = 1;
+	mdev->irq_info.mic_msi_map = kzalloc((sizeof(u32) *
+		mdev->irq_info.num_vectors), GFP_KERNEL);
+
+	if (!mdev->irq_info.mic_msi_map) {
+		rc = -ENOMEM;
+		goto err_nomem1;
+	}
+
+	rc = mic_setup_callbacks(mdev);
+	if (rc) {
+		dev_err(&pdev->dev, "Error setting up callbacks\n");
+		goto err_nomem2;
+	}
+
+	rc = request_irq(pdev->irq, mic_interrupt, 0 , "mic-msi", mdev);
+	if (rc) {
+		dev_err(&pdev->dev, "Error allocating MSI interrupt\n");
+		goto err_irq_req_fail;
+	}
+
+	dev_dbg(&pdev->dev, "%d MSI irqs setup\n", mdev->irq_info.num_vectors);
+	return 0;
+err_irq_req_fail:
+	mic_release_callbacks(mdev);
+err_nomem2:
+	kfree(mdev->irq_info.mic_msi_map);
+err_nomem1:
+	pci_disable_msi(pdev);
+	mdev->irq_info.num_vectors = 0;
+	return rc;
+}
+
+/**
+ * mic_setup_intx - Initializes legacy interrupts.
+ *
+ * @mdev: pointer to mic_device instance
+ * @pdev: PCI device structure
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+static int mic_setup_intx(struct mic_device *mdev, struct pci_dev *pdev)
+{
+	int rc;
+
+	pci_msi_off(pdev);
+
+	/* Enable intx */
+	pci_intx(pdev, 1);
+	rc = mic_setup_callbacks(mdev);
+	if (rc) {
+		dev_err(&pdev->dev, "Error setting up callbacks\n");
+		goto err_nomem;
+	}
+
+	rc = request_irq(pdev->irq, mic_interrupt,
+		IRQF_SHARED, "mic-intx", mdev);
+	if (rc)
+		goto err;
+
+	dev_dbg(&pdev->dev, "intx irq setup\n");
+	return 0;
+err:
+	mic_release_callbacks(mdev);
+err_nomem:
+	return rc;
+}
+
+/**
+ * mic_next_db - Retrieve the next doorbell interrupt source id.
+ * The id is picked sequentially from the available pool of
+ * doorlbell ids.
+ *
+ * @mdev: pointer to the mic_device instance.
+ *
+ * Returns the next doorbell interrupt source.
+ */
+int mic_next_db(struct mic_device *mdev)
+{
+	int next_db;
+
+	next_db = mdev->irq_info.next_avail_src %
+		mdev->intr_info->intr_len[MIC_INTR_DB];
+	mdev->irq_info.next_avail_src++;
+	return next_db;
+}
+
+#define COOKIE_ID_SHIFT 16
+#define GET_ENTRY(cookie) ((cookie) & 0xFFFF)
+#define GET_OFFSET(cookie) ((cookie) >> COOKIE_ID_SHIFT)
+#define MK_COOKIE(x, y) ((x) | (y) << COOKIE_ID_SHIFT)
+
+/**
+ * mic_request_irq - request an irq. mic_mutex needs
+ * to be held before calling this function.
+ *
+ * @mdev: pointer to mic_device instance
+ * @func: The callback function that handles the interrupt.
+ * The function needs to call ack_interrupts
+ * (mdev->ops->ack_interrupt(mdev)) when handling the interrupts.
+ * @name: The ASCII name of the callee requesting the irq.
+ * @data: private data that is returned back when calling the
+ * function handler.
+ * @intr_src: The source id of the requester. Its the doorbell id
+ * for Doorbell interrupts and DMA channel id for DMA interrupts.
+ * @type: The type of interrupt. Values defined in mic_intr_type
+ *
+ * returns: The cookie that is transparent to the caller. Passed
+ * back when calling mic_free_irq. An appropriate error code
+ * is returned on failure. Caller needs to use IS_ERR(return_val)
+ * to check for failure and PTR_ERR(return_val) to obtained the
+ * error code.
+ *
+ */
+struct mic_irq *mic_request_irq(struct mic_device *mdev,
+	irqreturn_t (*func)(int irq, void *dev),
+	const char *name, void *data, int intr_src,
+	enum mic_intr_type type)
+{
+	u16 offset;
+	int rc = 0;
+	struct msix_entry *msix = NULL;
+	unsigned long cookie = 0;
+	u16 entry;
+	struct mic_intr_cb *intr_cb;
+	struct pci_dev *pdev = container_of(mdev->sdev->parent,
+		struct pci_dev, dev);
+
+	offset = mic_map_src_to_offset(mdev, intr_src, type);
+	if (offset >= MIC_NUM_OFFSETS) {
+		dev_err(mdev->sdev->parent,
+			"Error mapping index %d to a valid source id.\n",
+			intr_src);
+		rc = -EINVAL;
+		goto err;
+	}
+
+	if (mdev->irq_info.num_vectors > 1) {
+		msix = mic_get_available_vector(mdev);
+		if (!msix) {
+			dev_err(mdev->sdev->parent,
+				"No MSIx vectors available for use.\n");
+			rc = -ENOSPC;
+			goto err;
+		}
+
+		rc = request_irq(msix->vector, func, 0, name, data);
+		if (rc) {
+			dev_dbg(mdev->sdev->parent,
+				"request irq failed rc = %d\n", rc);
+			goto err;
+		}
+		entry = msix->entry;
+		mdev->irq_info.mic_msi_map[entry] |= BIT(offset);
+		mdev->intr_ops->program_msi_to_src_map(mdev,
+				entry, offset, true);
+		cookie = MK_COOKIE(entry, offset);
+		dev_dbg(mdev->sdev->parent, "irq: %d assigned for src: %d\n",
+			msix->vector, intr_src);
+	} else {
+		intr_cb = mic_register_intr_callback(mdev,
+				offset, func, data);
+		if (IS_ERR(intr_cb)) {
+			dev_err(mdev->sdev->parent,
+				"No available callback entries for use\n");
+			rc = PTR_ERR(intr_cb);
+			goto err;
+		}
+
+		entry = 0;
+		if (pci_dev_msi_enabled(pdev)) {
+			mdev->irq_info.mic_msi_map[entry] |= (1 << offset);
+			mdev->intr_ops->program_msi_to_src_map(mdev,
+				entry, offset, true);
+		}
+		cookie = MK_COOKIE(entry, intr_cb->cb_id);
+		dev_dbg(mdev->sdev->parent, "callback %d registered for src: %d\n",
+			intr_cb->cb_id, intr_src);
+	}
+	return (struct mic_irq *)cookie;
+err:
+	return ERR_PTR(rc);
+}
+
+/**
+ * mic_free_irq - free irq. mic_mutex
+ *  needs to be held before calling this function.
+ *
+ * @mdev: pointer to mic_device instance
+ * @cookie: cookie obtained during a successful call to mic_request_irq
+ * @data: private data specified by the calling function during the
+ * mic_request_irq
+ *
+ * returns: none.
+ */
+void mic_free_irq(struct mic_device *mdev,
+	struct mic_irq *cookie, void *data)
+{
+	u32 offset;
+	u32 entry;
+	u8 src_id;
+	unsigned int irq;
+	struct pci_dev *pdev = container_of(mdev->sdev->parent,
+		struct pci_dev, dev);
+
+	entry = GET_ENTRY((unsigned long)cookie);
+	offset = GET_OFFSET((unsigned long)cookie);
+	if (mdev->irq_info.num_vectors > 1) {
+		if (entry >= mdev->irq_info.num_vectors) {
+			dev_warn(mdev->sdev->parent,
+				 "entry %d should be < num_irq %d\n",
+				entry, mdev->irq_info.num_vectors);
+			return;
+		}
+		irq = mdev->irq_info.msix_entries[entry].vector;
+		free_irq(irq, data);
+		mdev->irq_info.mic_msi_map[entry] &= ~(BIT(offset));
+		mdev->intr_ops->program_msi_to_src_map(mdev,
+			entry, offset, false);
+
+		dev_dbg(mdev->sdev->parent, "irq: %d freed\n", irq);
+	} else {
+		irq = pdev->irq;
+		src_id = mic_unregister_intr_callback(mdev, offset);
+		if (src_id >= MIC_NUM_OFFSETS) {
+			dev_warn(mdev->sdev->parent, "Error unregistering callback\n");
+			return;
+		}
+		if (pci_dev_msi_enabled(pdev)) {
+			mdev->irq_info.mic_msi_map[entry] &= ~(BIT(src_id));
+			mdev->intr_ops->program_msi_to_src_map(mdev,
+				entry, src_id, false);
+		}
+		dev_dbg(mdev->sdev->parent, "callback %d unregistered for src: %d\n",
+			offset, src_id);
+	}
+}
+
+/**
+ * mic_setup_interrupts - Initializes interrupts.
+ *
+ * @mdev: pointer to mic_device instance
+ * @pdev: PCI device structure
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
+{
+	int rc;
+
+	rc = mic_setup_msix(mdev, pdev);
+	if (!rc)
+		goto done;
+
+	rc = mic_setup_msi(mdev, pdev);
+	if (!rc)
+		goto done;
+
+	rc = mic_setup_intx(mdev, pdev);
+	if (rc) {
+		dev_err(mdev->sdev->parent, "no usable interrupts\n");
+		return rc;
+	}
+done:
+	mdev->intr_ops->enable_interrupts(mdev);
+	return 0;
+}
+
+/**
+ * mic_free_interrupts - Frees interrupts setup by mic_setup_interrupts
+ *
+ * @mdev: pointer to mic_device instance
+ * @pdev: PCI device structure
+ *
+ * returns none.
+ */
+void mic_free_interrupts(struct mic_device *mdev, struct pci_dev *pdev)
+{
+	int i;
+
+	mdev->intr_ops->disable_interrupts(mdev);
+	if (mdev->irq_info.num_vectors > 1) {
+		for (i = 0; i < mdev->irq_info.num_vectors; i++) {
+			if (mdev->irq_info.mic_msi_map[i])
+				dev_warn(&pdev->dev, "irq %d may still be in use.\n",
+					 mdev->irq_info.msix_entries[i].vector);
+		}
+		kfree(mdev->irq_info.mic_msi_map);
+		kfree(mdev->irq_info.msix_entries);
+		pci_disable_msix(pdev);
+	} else {
+		if (pci_dev_msi_enabled(pdev)) {
+			free_irq(pdev->irq, mdev);
+			kfree(mdev->irq_info.mic_msi_map);
+			pci_disable_msi(pdev);
+		} else {
+			free_irq(pdev->irq, mdev);
+		}
+		mic_release_callbacks(mdev);
+	}
+}
+
+/**
+ * mic_intr_restore - Restore MIC interrupt registers.
+ *
+ * @mdev: pointer to mic_device instance.
+ *
+ * Restore the interrupt registers to values previously
+ * stored in the SW data structures. mic_mutex needs to
+ * be held before calling this function.
+ *
+ * returns None.
+ */
+void mic_intr_restore(struct mic_device *mdev)
+{
+	int entry, offset;
+	struct pci_dev *pdev = container_of(mdev->sdev->parent,
+		struct pci_dev, dev);
+
+	if (!pci_dev_msi_enabled(pdev))
+		return;
+
+	for (entry = 0; entry < mdev->irq_info.num_vectors; entry++) {
+		for (offset = 0; offset < MIC_NUM_OFFSETS; offset++) {
+			if (mdev->irq_info.mic_msi_map[entry] & BIT(offset))
+				mdev->intr_ops->program_msi_to_src_map(mdev,
+					entry, offset, true);
+		}
+	}
+}
diff --git a/drivers/misc/mic/host/mic_intr.h b/drivers/misc/mic/host/mic_intr.h
new file mode 100644
index 0000000..6091aa9
--- /dev/null
+++ b/drivers/misc/mic/host/mic_intr.h
@@ -0,0 +1,137 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#ifndef _MIC_INTR_H_
+#define _MIC_INTR_H_
+
+/*
+ * The minimum number of msix vectors required for normal operation.
+ * 3 for virtio network, console and block devices.
+ * 1 for card shutdown notifications.
+ */
+#define MIC_MIN_MSIX 4
+#define MIC_NUM_OFFSETS 32
+
+/**
+ * mic_intr_source - The type of source that will generate
+ * the interrupt.The number of types needs to be in sync with
+ * MIC_NUM_INTR_TYPES
+ *
+ * MIC_INTR_DB: The source is a doorbell
+ * MIC_INTR_DMA: The source is a DMA channel
+ * MIC_INTR_ERR: The source is an error interrupt e.g. SBOX ERR
+ * MIC_NUM_INTR_TYPES: Total number of interrupt sources.
+ */
+enum mic_intr_type {
+	MIC_INTR_DB = 0,
+	MIC_INTR_DMA,
+	MIC_INTR_ERR,
+	MIC_NUM_INTR_TYPES
+};
+
+/**
+ * struct mic_intr_info - Contains h/w specific interrupt sources
+ * information.
+ *
+ * @intr_start_idx: Contains the starting indexes of the
+ * interrupt types.
+ * @intr_len: Contains the length of the interrupt types.
+ */
+struct mic_intr_info {
+	u16 intr_start_idx[MIC_NUM_INTR_TYPES];
+	u16 intr_len[MIC_NUM_INTR_TYPES];
+};
+
+/**
+ * struct mic_irq_info - OS specific irq information
+ *
+ * @next_avail_src: next available doorbell that can be assigned.
+ * @msix_entries: msix entries allocated while setting up MSI-x
+ * @mic_msi_map: The MSI/MSI-x mapping information.
+ * @num_vectors: The number of MSI/MSI-x vectors that have been allocated.
+ * @cb_ida: callback ID allocator to track the callbacks registered.
+ * @mic_intr_lock: spinlock to protect the interrupt callback list.
+ * @cb_list: Array of callback lists one for each source.
+ */
+struct mic_irq_info {
+	int next_avail_src;
+	struct msix_entry *msix_entries;
+	u32 *mic_msi_map;
+	u16 num_vectors;
+	struct ida cb_ida;
+	spinlock_t mic_intr_lock;
+	struct list_head *cb_list;
+};
+
+/**
+ * struct mic_intr_cb - Interrupt callback structure.
+ *
+ * @func: The callback function
+ * @data: Private data of the requester.
+ * @cb_id: The callback id. Identifies this callback.
+ * @list: list head pointing to the next callback structure.
+ */
+struct mic_intr_cb {
+	irqreturn_t (*func) (int irq, void *data);
+	void *data;
+	int cb_id;
+	struct list_head list;
+};
+
+/**
+ * struct mic_irq - opaque pointer used as cookie
+ */
+struct mic_irq;
+
+/* Forward declaration */
+struct mic_device;
+
+/**
+ * struct mic_hw_intr_ops: MIC HW specific interrupt operations
+ * @intr_init: Initialize H/W specific interrupt information.
+ * @enable_interrupts: Enable interrupts from the hardware.
+ * @disable_interrupts: Disable interrupts from the hardware.
+ * @program_msi_to_src_map: Update MSI mapping registers with
+ * irq information.
+ * @read_msi_to_src_map: Read MSI mapping registers containing
+ * irq information.
+ */
+struct mic_hw_intr_ops {
+	void (*intr_init)(struct mic_device *mdev);
+	void (*enable_interrupts)(struct mic_device *mdev);
+	void (*disable_interrupts)(struct mic_device *mdev);
+	void (*program_msi_to_src_map) (struct mic_device *mdev,
+			int idx, int intr_src, bool set);
+	u32 (*read_msi_to_src_map) (struct mic_device *mdev,
+			int idx);
+};
+
+int mic_next_db(struct mic_device *mdev);
+struct mic_irq *mic_request_irq(struct mic_device *mdev,
+	irqreturn_t (*func)(int irq, void *data),
+	const char *name, void *data, int intr_src,
+	enum mic_intr_type type);
+
+void mic_free_irq(struct mic_device *mdev,
+		struct mic_irq *cookie, void *data);
+int mic_setup_interrupts(struct mic_device *mdev, struct pci_dev *pdev);
+void mic_free_interrupts(struct mic_device *mdev, struct pci_dev *pdev);
+void mic_intr_restore(struct mic_device *mdev);
+#endif
diff --git a/drivers/misc/mic/host/mic_main.c b/drivers/misc/mic/host/mic_main.c
new file mode 100644
index 0000000..ad838c7
--- /dev/null
+++ b/drivers/misc/mic/host/mic_main.c
@@ -0,0 +1,536 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ * Global TODO's across the driver to be added after initial base
+ * patches are accepted upstream:
+ * 1) Enable DMA support.
+ * 2) Enable per vring interrupt support.
+ */
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/poll.h>
+#include <linux/suspend.h>
+
+#include <linux/mic_common.h>
+#include "../common/mic_dev.h"
+#include "mic_device.h"
+#include "mic_x100.h"
+#include "mic_smpt.h"
+#include "mic_fops.h"
+#include "mic_virtio.h"
+
+static const char mic_driver_name[] = "mic";
+
+static DEFINE_PCI_DEVICE_TABLE(mic_pci_tbl) = {
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2250)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2251)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2252)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2253)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2254)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2255)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2256)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2257)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2258)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_2259)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225a)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225b)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225c)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225d)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MIC_X100_PCI_DEVICE_225e)},
+
+	/* required last entry */
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, mic_pci_tbl);
+
+/* ID allocator for MIC devices */
+static struct ida g_mic_ida;
+/* Class of MIC devices for sysfs accessibility. */
+static struct class *g_mic_class;
+/* Base device node number for MIC devices */
+static dev_t g_mic_devno;
+
+static const struct file_operations mic_fops = {
+	.open = mic_open,
+	.release = mic_release,
+	.unlocked_ioctl = mic_ioctl,
+	.poll = mic_poll,
+	.mmap = mic_mmap,
+	.owner = THIS_MODULE,
+};
+
+/* Initialize the device page */
+static int mic_dp_init(struct mic_device *mdev)
+{
+	mdev->dp = kzalloc(MIC_DP_SIZE, GFP_KERNEL);
+	if (!mdev->dp) {
+		dev_err(mdev->sdev->parent, "%s %d err %d\n",
+			__func__, __LINE__, -ENOMEM);
+		return -ENOMEM;
+	}
+
+	mdev->dp_dma_addr = mic_map_single(mdev,
+		mdev->dp, MIC_DP_SIZE);
+	if (mic_map_error(mdev->dp_dma_addr)) {
+		kfree(mdev->dp);
+		dev_err(mdev->sdev->parent, "%s %d err %d\n",
+			__func__, __LINE__, -ENOMEM);
+		return -ENOMEM;
+	}
+	mdev->ops->write_spad(mdev, MIC_DPLO_SPAD, mdev->dp_dma_addr);
+	mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32);
+	return 0;
+}
+
+/* Uninitialize the device page */
+static void mic_dp_uninit(struct mic_device *mdev)
+{
+	mic_unmap_single(mdev, mdev->dp_dma_addr, MIC_DP_SIZE);
+	kfree(mdev->dp);
+}
+
+/**
+ * mic_shutdown_db - Shutdown doorbell interrupt handler.
+ */
+static irqreturn_t mic_shutdown_db(int irq, void *data)
+{
+	struct mic_device *mdev = data;
+	struct mic_bootparam *bootparam = mdev->dp;
+
+	mdev->ops->ack_interrupt(mdev);
+
+	switch (bootparam->shutdown_status) {
+	case MIC_HALTED:
+	case MIC_POWER_OFF:
+	case MIC_RESTART:
+		/* Fall through */
+	case MIC_CRASHED:
+		schedule_work(&mdev->shutdown_work);
+		break;
+	default:
+		break;
+	};
+	return IRQ_HANDLED;
+}
+
+/**
+ * mic_ops_init: Initialize HW specific operation tables.
+ *
+ * @mdev: pointer to mic_device instance
+ *
+ * returns none.
+ */
+static void mic_ops_init(struct mic_device *mdev)
+{
+	switch (mdev->family) {
+	case MIC_FAMILY_X100:
+		mdev->ops = &mic_x100_ops;
+		mdev->intr_ops = &mic_x100_intr_ops;
+		mdev->smpt_ops = &mic_x100_smpt_ops;
+		break;
+	default:
+		break;
+	}
+}
+
+/**
+ * mic_get_family - Determine hardware family to which this MIC belongs.
+ *
+ * @pdev: The pci device structure
+ *
+ * returns family.
+ */
+static enum mic_hw_family mic_get_family(struct pci_dev *pdev)
+{
+	enum mic_hw_family family;
+
+	switch (pdev->device) {
+	case MIC_X100_PCI_DEVICE_2250:
+	case MIC_X100_PCI_DEVICE_2251:
+	case MIC_X100_PCI_DEVICE_2252:
+	case MIC_X100_PCI_DEVICE_2253:
+	case MIC_X100_PCI_DEVICE_2254:
+	case MIC_X100_PCI_DEVICE_2255:
+	case MIC_X100_PCI_DEVICE_2256:
+	case MIC_X100_PCI_DEVICE_2257:
+	case MIC_X100_PCI_DEVICE_2258:
+	case MIC_X100_PCI_DEVICE_2259:
+	case MIC_X100_PCI_DEVICE_225a:
+	case MIC_X100_PCI_DEVICE_225b:
+	case MIC_X100_PCI_DEVICE_225c:
+	case MIC_X100_PCI_DEVICE_225d:
+	case MIC_X100_PCI_DEVICE_225e:
+		family = MIC_FAMILY_X100;
+		break;
+	default:
+		family = MIC_FAMILY_UNKNOWN;
+		break;
+	}
+	return family;
+}
+
+/**
+* mic_pm_notifier: Notifier callback function that handles
+* PM notifications.
+*
+* @notifier_block: The notifier structure.
+* @pm_event: The event for which the driver was notified.
+* @unused: Meaningless. Always NULL.
+*
+* returns NOTIFY_DONE
+*/
+static int mic_pm_notifier(struct notifier_block *notifier,
+		unsigned long pm_event, void *unused)
+{
+	struct mic_device *mdev = container_of(notifier,
+		struct mic_device, pm_notifier);
+
+	switch (pm_event) {
+	case PM_HIBERNATION_PREPARE:
+		/* Fall through */
+	case PM_SUSPEND_PREPARE:
+		mic_prepare_suspend(mdev);
+		break;
+	case PM_POST_HIBERNATION:
+		/* Fall through */
+	case PM_POST_SUSPEND:
+		/* Fall through */
+	case PM_POST_RESTORE:
+		mic_complete_resume(mdev);
+		break;
+	case PM_RESTORE_PREPARE:
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+/**
+ * mic_device_init - Allocates and initializes the MIC device structure
+ *
+ * @mdev: pointer to mic_device instance
+ * @pdev: The pci device structure
+ *
+ * returns none.
+ */
+static int
+mic_device_init(struct mic_device *mdev, struct pci_dev *pdev)
+{
+	int rc;
+
+	mdev->family = mic_get_family(pdev);
+	mdev->stepping = pdev->revision;
+	mic_ops_init(mdev);
+	mic_sysfs_init(mdev);
+	mutex_init(&mdev->mic_mutex);
+	mdev->irq_info.next_avail_src = 0;
+	INIT_WORK(&mdev->reset_trigger_work, mic_reset_trigger_work);
+	INIT_WORK(&mdev->shutdown_work, mic_shutdown_work);
+	init_completion(&mdev->reset_wait);
+	INIT_LIST_HEAD(&mdev->vdev_list);
+	mdev->pm_notifier.notifier_call = mic_pm_notifier;
+	rc = register_pm_notifier(&mdev->pm_notifier);
+	if (rc) {
+		dev_err(&pdev->dev, "register_pm_notifier failed rc %d\n",
+			rc);
+		goto register_pm_notifier_fail;
+	}
+	return 0;
+register_pm_notifier_fail:
+	flush_work(&mdev->shutdown_work);
+	flush_work(&mdev->reset_trigger_work);
+	return rc;
+}
+
+/**
+ * mic_device_uninit - Frees resources allocated during mic_device_init(..)
+ *
+ * @mdev: pointer to mic_device instance
+ *
+ * returns none
+ */
+static void mic_device_uninit(struct mic_device *mdev)
+{
+	/* The cmdline sysfs entry might have allocated cmdline */
+	kfree(mdev->cmdline);
+	kfree(mdev->firmware);
+	kfree(mdev->ramdisk);
+	kfree(mdev->bootmode);
+	flush_work(&mdev->reset_trigger_work);
+	flush_work(&mdev->shutdown_work);
+	unregister_pm_notifier(&mdev->pm_notifier);
+}
+
+/**
+ * mic_probe - Device Initialization Routine
+ *
+ * @pdev: PCI device structure
+ * @ent: entry in mic_pci_tbl
+ *
+ * returns 0 on success, < 0 on failure.
+ */
+static int mic_probe(struct pci_dev *pdev,
+		const struct pci_device_id *ent)
+{
+	int rc;
+	struct mic_device *mdev;
+
+	mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+	if (!mdev) {
+		rc = -ENOMEM;
+		dev_err(&pdev->dev, "mdev kmalloc failed rc %d\n", rc);
+		goto mdev_alloc_fail;
+	}
+	mdev->id = ida_simple_get(&g_mic_ida, 0, MIC_MAX_NUM_DEVS, GFP_KERNEL);
+	if (mdev->id < 0) {
+		rc = mdev->id;
+		dev_err(&pdev->dev, "ida_simple_get failed rc %d\n", rc);
+		goto ida_fail;
+	}
+
+	rc = mic_device_init(mdev, pdev);
+	if (rc) {
+		dev_err(&pdev->dev, "mic_device_init failed rc %d\n", rc);
+		goto device_init_fail;
+	}
+
+	rc = pci_enable_device(pdev);
+	if (rc) {
+		dev_err(&pdev->dev, "failed to enable pci device.\n");
+		goto uninit_device;
+	}
+
+	pci_set_master(pdev);
+
+	rc = pci_request_regions(pdev, mic_driver_name);
+	if (rc) {
+		dev_err(&pdev->dev, "failed to get pci regions.\n");
+		goto disable_device;
+	}
+
+	rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+	if (rc) {
+		dev_err(&pdev->dev, "Cannot set DMA mask\n");
+		goto release_regions;
+	}
+
+	mdev->mmio.pa = pci_resource_start(pdev, mdev->ops->mmio_bar);
+	mdev->mmio.len = pci_resource_len(pdev, mdev->ops->mmio_bar);
+	mdev->mmio.va = pci_ioremap_bar(pdev, mdev->ops->mmio_bar);
+	if (!mdev->mmio.va) {
+		dev_err(&pdev->dev, "Cannot remap MMIO BAR\n");
+		rc = -EIO;
+		goto release_regions;
+	}
+
+	mdev->aper.pa = pci_resource_start(pdev, mdev->ops->aper_bar);
+	mdev->aper.len = pci_resource_len(pdev, mdev->ops->aper_bar);
+	mdev->aper.va = ioremap_wc(mdev->aper.pa, mdev->aper.len);
+	if (!mdev->aper.va) {
+		dev_err(&pdev->dev, "Cannot remap Aperture BAR\n");
+		rc = -EIO;
+		goto unmap_mmio;
+	}
+
+	mdev->intr_ops->intr_init(mdev);
+	rc = mic_setup_interrupts(mdev, pdev);
+	if (rc) {
+		dev_err(&pdev->dev, "mic_setup_interrupts failed %d\n", rc);
+		goto unmap_aper;
+	}
+	rc = mic_smpt_init(mdev);
+	if (rc) {
+		dev_err(&pdev->dev, "smpt_init failed %d\n", rc);
+		goto free_interrupts;
+	}
+
+	pci_set_drvdata(pdev, mdev);
+
+	mdev->sdev = device_create_with_groups(g_mic_class, &pdev->dev,
+		MKDEV(MAJOR(g_mic_devno), mdev->id), NULL,
+		mdev->attr_group, "mic%d", mdev->id);
+	if (IS_ERR(mdev->sdev)) {
+		rc = PTR_ERR(mdev->sdev);
+		dev_err(&pdev->dev,
+			"device_create_with_groups failed rc %d\n", rc);
+		goto smpt_uninit;
+	}
+	mdev->state_sysfs = sysfs_get_dirent(mdev->sdev->kobj.sd, "state");
+	if (!mdev->state_sysfs) {
+		rc = -ENODEV;
+		dev_err(&pdev->dev, "sysfs_get_dirent failed rc %d\n", rc);
+		goto destroy_device;
+	}
+
+	rc = mic_dp_init(mdev);
+	if (rc) {
+		dev_err(&pdev->dev, "mic_dp_init failed rc %d\n", rc);
+		goto sysfs_put;
+	}
+	mutex_lock(&mdev->mic_mutex);
+
+	mdev->shutdown_db = mic_next_db(mdev);
+	mdev->shutdown_cookie = mic_request_irq(mdev, mic_shutdown_db,
+		"shutdown-interrupt", mdev, mdev->shutdown_db, MIC_INTR_DB);
+	if (IS_ERR(mdev->shutdown_cookie)) {
+		rc = PTR_ERR(mdev->shutdown_cookie);
+		mutex_unlock(&mdev->mic_mutex);
+		goto dp_uninit;
+	}
+	mutex_unlock(&mdev->mic_mutex);
+	mic_bootparam_init(mdev);
+
+	mic_create_debug_dir(mdev);
+	cdev_init(&mdev->cdev, &mic_fops);
+	mdev->cdev.owner = THIS_MODULE;
+	rc = cdev_add(&mdev->cdev, MKDEV(MAJOR(g_mic_devno), mdev->id), 1);
+	if (rc) {
+		dev_err(&pdev->dev, "cdev_add err id %d rc %d\n", mdev->id, rc);
+		goto cleanup_debug_dir;
+	}
+	return 0;
+cleanup_debug_dir:
+	mic_delete_debug_dir(mdev);
+	mutex_lock(&mdev->mic_mutex);
+	mic_free_irq(mdev, mdev->shutdown_cookie, mdev);
+	mutex_unlock(&mdev->mic_mutex);
+dp_uninit:
+	mic_dp_uninit(mdev);
+sysfs_put:
+	sysfs_put(mdev->state_sysfs);
+destroy_device:
+	device_destroy(g_mic_class, MKDEV(MAJOR(g_mic_devno), mdev->id));
+smpt_uninit:
+	mic_smpt_uninit(mdev);
+free_interrupts:
+	mic_free_interrupts(mdev, pdev);
+unmap_aper:
+	iounmap(mdev->aper.va);
+unmap_mmio:
+	iounmap(mdev->mmio.va);
+release_regions:
+	pci_release_regions(pdev);
+disable_device:
+	pci_disable_device(pdev);
+uninit_device:
+	mic_device_uninit(mdev);
+device_init_fail:
+	ida_simple_remove(&g_mic_ida, mdev->id);
+ida_fail:
+	kfree(mdev);
+mdev_alloc_fail:
+	dev_err(&pdev->dev, "Probe failed rc %d\n", rc);
+	return rc;
+}
+
+/**
+ * mic_remove - Device Removal Routine
+ * mic_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device.
+ *
+ * @pdev: PCI device structure
+ */
+static void mic_remove(struct pci_dev *pdev)
+{
+	struct mic_device *mdev;
+
+	mdev = pci_get_drvdata(pdev);
+	if (!mdev)
+		return;
+
+	mic_stop(mdev, false);
+	cdev_del(&mdev->cdev);
+	mic_delete_debug_dir(mdev);
+	mutex_lock(&mdev->mic_mutex);
+	mic_free_irq(mdev, mdev->shutdown_cookie, mdev);
+	mutex_unlock(&mdev->mic_mutex);
+	flush_work(&mdev->shutdown_work);
+	mic_dp_uninit(mdev);
+	sysfs_put(mdev->state_sysfs);
+	device_destroy(g_mic_class, MKDEV(MAJOR(g_mic_devno), mdev->id));
+	mic_smpt_uninit(mdev);
+	mic_free_interrupts(mdev, pdev);
+	iounmap(mdev->mmio.va);
+	iounmap(mdev->aper.va);
+	mic_device_uninit(mdev);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	ida_simple_remove(&g_mic_ida, mdev->id);
+	kfree(mdev);
+}
+static struct pci_driver mic_driver = {
+	.name = mic_driver_name,
+	.id_table = mic_pci_tbl,
+	.probe = mic_probe,
+	.remove = mic_remove
+};
+
+static int __init mic_init(void)
+{
+	int ret;
+
+	ret = alloc_chrdev_region(&g_mic_devno, 0,
+		MIC_MAX_NUM_DEVS, mic_driver_name);
+	if (ret) {
+		pr_err("alloc_chrdev_region failed ret %d\n", ret);
+		goto error;
+	}
+
+	g_mic_class = class_create(THIS_MODULE, mic_driver_name);
+	if (IS_ERR(g_mic_class)) {
+		ret = PTR_ERR(g_mic_class);
+		pr_err("class_create failed ret %d\n", ret);
+		goto cleanup_chrdev;
+	}
+
+	mic_init_debugfs();
+	ida_init(&g_mic_ida);
+	ret = pci_register_driver(&mic_driver);
+	if (ret) {
+		pr_err("pci_register_driver failed ret %d\n", ret);
+		goto cleanup_debugfs;
+	}
+	return ret;
+cleanup_debugfs:
+	mic_exit_debugfs();
+	class_destroy(g_mic_class);
+cleanup_chrdev:
+	unregister_chrdev_region(g_mic_devno, MIC_MAX_NUM_DEVS);
+error:
+	return ret;
+}
+
+static void __exit mic_exit(void)
+{
+	pci_unregister_driver(&mic_driver);
+	ida_destroy(&g_mic_ida);
+	mic_exit_debugfs();
+	class_destroy(g_mic_class);
+	unregister_chrdev_region(g_mic_devno, MIC_MAX_NUM_DEVS);
+}
+
+module_init(mic_init);
+module_exit(mic_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Intel(R) MIC X100 Host driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mic/host/mic_smpt.c b/drivers/misc/mic/host/mic_smpt.c
new file mode 100644
index 0000000..fae474c
--- /dev/null
+++ b/drivers/misc/mic/host/mic_smpt.c
@@ -0,0 +1,442 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#include <linux/pci.h>
+
+#include "../common/mic_dev.h"
+#include "mic_device.h"
+#include "mic_smpt.h"
+
+static inline u64 mic_system_page_mask(struct mic_device *mdev)
+{
+	return (1ULL << mdev->smpt->info.page_shift) - 1ULL;
+}
+
+static inline u8 mic_sys_addr_to_smpt(struct mic_device *mdev, dma_addr_t pa)
+{
+	return (pa - mdev->smpt->info.base) >> mdev->smpt->info.page_shift;
+}
+
+static inline u64 mic_smpt_to_pa(struct mic_device *mdev, u8 index)
+{
+	return mdev->smpt->info.base + (index * mdev->smpt->info.page_size);
+}
+
+static inline u64 mic_smpt_offset(struct mic_device *mdev, dma_addr_t pa)
+{
+	return pa & mic_system_page_mask(mdev);
+}
+
+static inline u64 mic_smpt_align_low(struct mic_device *mdev, dma_addr_t pa)
+{
+	return ALIGN(pa - mic_system_page_mask(mdev),
+		mdev->smpt->info.page_size);
+}
+
+static inline u64 mic_smpt_align_high(struct mic_device *mdev, dma_addr_t pa)
+{
+	return ALIGN(pa, mdev->smpt->info.page_size);
+}
+
+/* Total Cumulative system memory accessible by MIC across all SMPT entries */
+static inline u64 mic_max_system_memory(struct mic_device *mdev)
+{
+	return mdev->smpt->info.num_reg * mdev->smpt->info.page_size;
+}
+
+/* Maximum system memory address accessible by MIC */
+static inline u64 mic_max_system_addr(struct mic_device *mdev)
+{
+	return mdev->smpt->info.base + mic_max_system_memory(mdev) - 1ULL;
+}
+
+/* Check if the DMA address is a MIC system memory address */
+static inline bool
+mic_is_system_addr(struct mic_device *mdev, dma_addr_t pa)
+{
+	return pa >= mdev->smpt->info.base && pa <= mic_max_system_addr(mdev);
+}
+
+/* Populate an SMPT entry and update the reference counts. */
+static void mic_add_smpt_entry(int spt, s64 *ref, u64 addr,
+		int entries, struct mic_device *mdev)
+{
+	struct mic_smpt_info *smpt_info = mdev->smpt;
+	int i;
+
+	for (i = spt; i < spt + entries; i++,
+		addr += smpt_info->info.page_size) {
+		if (!smpt_info->entry[i].ref_count &&
+		    (smpt_info->entry[i].dma_addr != addr)) {
+			mdev->smpt_ops->set(mdev, addr, i);
+			smpt_info->entry[i].dma_addr = addr;
+		}
+		smpt_info->entry[i].ref_count += ref[i - spt];
+	}
+}
+
+/*
+ * Find an available MIC address in MIC SMPT address space
+ * for a given DMA address and size.
+ */
+static dma_addr_t mic_smpt_op(struct mic_device *mdev, u64 dma_addr,
+				int entries, s64 *ref, size_t size)
+{
+	int spt;
+	int ae = 0;
+	int i;
+	unsigned long flags;
+	dma_addr_t mic_addr = 0;
+	dma_addr_t addr = dma_addr;
+	struct mic_smpt_info *smpt_info = mdev->smpt;
+
+	spin_lock_irqsave(&smpt_info->smpt_lock, flags);
+
+	/* find existing entries */
+	for (i = 0; i < smpt_info->info.num_reg; i++) {
+		if (smpt_info->entry[i].dma_addr == addr) {
+			ae++;
+			addr += smpt_info->info.page_size;
+		} else if (ae) /* cannot find contiguous entries */
+			goto not_found;
+
+		if (ae == entries)
+			goto found;
+	}
+
+	/* find free entry */
+	for (ae = 0, i = 0; i < smpt_info->info.num_reg; i++) {
+		ae = (smpt_info->entry[i].ref_count == 0) ? ae + 1 : 0;
+		if (ae == entries)
+			goto found;
+	}
+
+not_found:
+	spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
+	return mic_addr;
+
+found:
+	spt = i - entries + 1;
+	mic_addr = mic_smpt_to_pa(mdev, spt);
+	mic_add_smpt_entry(spt, ref, dma_addr, entries, mdev);
+	smpt_info->map_count++;
+	smpt_info->ref_count += (s64)size;
+	spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
+	return mic_addr;
+}
+
+/*
+ * Returns number of smpt entries needed for dma_addr to dma_addr + size
+ * also returns the reference count array for each of those entries
+ * and the starting smpt address
+ */
+static int mic_get_smpt_ref_count(struct mic_device *mdev, dma_addr_t dma_addr,
+				size_t size, s64 *ref,  u64 *smpt_start)
+{
+	u64 start =  dma_addr;
+	u64 end = dma_addr + size;
+	int i = 0;
+
+	while (start < end) {
+		ref[i++] = min(mic_smpt_align_high(mdev, start + 1),
+			end) - start;
+		start = mic_smpt_align_high(mdev, start + 1);
+	}
+
+	if (smpt_start)
+		*smpt_start = mic_smpt_align_low(mdev, dma_addr);
+
+	return i;
+}
+
+/*
+ * mic_to_dma_addr - Converts a MIC address to a DMA address.
+ *
+ * @mdev: pointer to mic_device instance.
+ * @mic_addr: MIC address.
+ *
+ * returns a DMA address.
+ */
+static dma_addr_t
+mic_to_dma_addr(struct mic_device *mdev, dma_addr_t mic_addr)
+{
+	struct mic_smpt_info *smpt_info = mdev->smpt;
+	int spt;
+	dma_addr_t dma_addr;
+
+	if (!mic_is_system_addr(mdev, mic_addr)) {
+		dev_err(mdev->sdev->parent,
+			"mic_addr is invalid. mic_addr = 0x%llx\n", mic_addr);
+		return -EINVAL;
+	}
+	spt = mic_sys_addr_to_smpt(mdev, mic_addr);
+	dma_addr = smpt_info->entry[spt].dma_addr +
+		mic_smpt_offset(mdev, mic_addr);
+	return dma_addr;
+}
+
+/**
+ * mic_map - Maps a DMA address to a MIC physical address.
+ *
+ * @mdev: pointer to mic_device instance.
+ * @dma_addr: DMA address.
+ * @size: Size of the region to be mapped.
+ *
+ * This API converts the DMA address provided to a DMA address understood
+ * by MIC. Caller should check for errors by calling mic_map_error(..).
+ *
+ * returns DMA address as required by MIC.
+ */
+dma_addr_t mic_map(struct mic_device *mdev, dma_addr_t dma_addr, size_t size)
+{
+	dma_addr_t mic_addr = 0;
+	int num_entries;
+	s64 *ref;
+	u64 smpt_start;
+
+	if (!size || size > mic_max_system_memory(mdev))
+		return mic_addr;
+
+	ref = kmalloc(mdev->smpt->info.num_reg * sizeof(s64), GFP_KERNEL);
+	if (!ref)
+		return mic_addr;
+
+	num_entries = mic_get_smpt_ref_count(mdev, dma_addr, size,
+		ref, &smpt_start);
+
+	/* Set the smpt table appropriately and get 16G aligned mic address */
+	mic_addr = mic_smpt_op(mdev, smpt_start, num_entries, ref, size);
+
+	kfree(ref);
+
+	/*
+	 * If mic_addr is zero then its an error case
+	 * since mic_addr can never be zero.
+	 * else generate mic_addr by adding the 16G offset in dma_addr
+	 */
+	if (!mic_addr && MIC_FAMILY_X100 == mdev->family) {
+		dev_err(mdev->sdev->parent,
+			"mic_map failed dma_addr 0x%llx size 0x%lx\n",
+			dma_addr, size);
+		return mic_addr;
+	} else {
+		return mic_addr + mic_smpt_offset(mdev, dma_addr);
+	}
+}
+
+/**
+ * mic_unmap - Unmaps a MIC physical address.
+ *
+ * @mdev: pointer to mic_device instance.
+ * @mic_addr: MIC physical address.
+ * @size: Size of the region to be unmapped.
+ *
+ * This API unmaps the mappings created by mic_map(..).
+ *
+ * returns None.
+ */
+void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
+{
+	struct mic_smpt_info *smpt_info = mdev->smpt;
+	s64 *ref;
+	int num_smpt;
+	int spt;
+	int i;
+	unsigned long flags;
+
+	if (!size)
+		return;
+
+	if (!mic_is_system_addr(mdev, mic_addr)) {
+		dev_err(mdev->sdev->parent,
+			"invalid address: 0x%llx\n", mic_addr);
+		return;
+	}
+
+	spt = mic_sys_addr_to_smpt(mdev, mic_addr);
+	ref = kmalloc(mdev->smpt->info.num_reg * sizeof(s64), GFP_KERNEL);
+	if (!ref)
+		return;
+
+	/* Get number of smpt entries to be mapped, ref count array */
+	num_smpt = mic_get_smpt_ref_count(mdev, mic_addr, size, ref, NULL);
+
+	spin_lock_irqsave(&smpt_info->smpt_lock, flags);
+	smpt_info->unmap_count++;
+	smpt_info->ref_count -= (s64)size;
+
+	for (i = spt; i < spt + num_smpt; i++) {
+		smpt_info->entry[i].ref_count -= ref[i - spt];
+		if (smpt_info->entry[i].ref_count < 0)
+			dev_warn(mdev->sdev->parent,
+				 "ref count for entry %d is negative\n", i);
+	}
+	spin_unlock_irqrestore(&smpt_info->smpt_lock, flags);
+	kfree(ref);
+}
+
+/**
+ * mic_map_single - Maps a virtual address to a MIC physical address.
+ *
+ * @mdev: pointer to mic_device instance.
+ * @va: Kernel direct mapped virtual address.
+ * @size: Size of the region to be mapped.
+ *
+ * This API calls pci_map_single(..) for the direct mapped virtual address
+ * and then converts the DMA address provided to a DMA address understood
+ * by MIC. Caller should check for errors by calling mic_map_error(..).
+ *
+ * returns DMA address as required by MIC.
+ */
+dma_addr_t mic_map_single(struct mic_device *mdev, void *va, size_t size)
+{
+	dma_addr_t mic_addr = 0;
+	struct pci_dev *pdev = container_of(mdev->sdev->parent,
+		struct pci_dev, dev);
+	dma_addr_t dma_addr =
+		pci_map_single(pdev, va, size, PCI_DMA_BIDIRECTIONAL);
+
+	if (!pci_dma_mapping_error(pdev, dma_addr)) {
+		mic_addr = mic_map(mdev, dma_addr, size);
+		if (!mic_addr) {
+			dev_err(mdev->sdev->parent,
+				"mic_map failed dma_addr 0x%llx size 0x%lx\n",
+				dma_addr, size);
+			pci_unmap_single(pdev, dma_addr,
+					 size, PCI_DMA_BIDIRECTIONAL);
+		}
+	}
+	return mic_addr;
+}
+
+/**
+ * mic_unmap_single - Unmaps a MIC physical address.
+ *
+ * @mdev: pointer to mic_device instance.
+ * @mic_addr: MIC physical address.
+ * @size: Size of the region to be unmapped.
+ *
+ * This API unmaps the mappings created by mic_map_single(..).
+ *
+ * returns None.
+ */
+void
+mic_unmap_single(struct mic_device *mdev, dma_addr_t mic_addr, size_t size)
+{
+	struct pci_dev *pdev = container_of(mdev->sdev->parent,
+		struct pci_dev, dev);
+	dma_addr_t dma_addr = mic_to_dma_addr(mdev, mic_addr);
+	mic_unmap(mdev, mic_addr, size);
+	pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL);
+}
+
+/**
+ * mic_smpt_init - Initialize MIC System Memory Page Tables.
+ *
+ * @mdev: pointer to mic_device instance.
+ *
+ * returns 0 for success and -errno for error.
+ */
+int mic_smpt_init(struct mic_device *mdev)
+{
+	int i, err = 0;
+	dma_addr_t dma_addr;
+	struct mic_smpt_info *smpt_info;
+
+	mdev->smpt = kmalloc(sizeof(*mdev->smpt), GFP_KERNEL);
+	if (!mdev->smpt)
+		return -ENOMEM;
+
+	smpt_info = mdev->smpt;
+	mdev->smpt_ops->init(mdev);
+	smpt_info->entry = kmalloc_array(smpt_info->info.num_reg,
+					 sizeof(*smpt_info->entry), GFP_KERNEL);
+	if (!smpt_info->entry) {
+		err = -ENOMEM;
+		goto free_smpt;
+	}
+	spin_lock_init(&smpt_info->smpt_lock);
+	for (i = 0; i < smpt_info->info.num_reg; i++) {
+		dma_addr = i * smpt_info->info.page_size;
+		smpt_info->entry[i].dma_addr = dma_addr;
+		smpt_info->entry[i].ref_count = 0;
+		mdev->smpt_ops->set(mdev, dma_addr, i);
+	}
+	smpt_info->ref_count = 0;
+	smpt_info->map_count = 0;
+	smpt_info->unmap_count = 0;
+	return 0;
+free_smpt:
+	kfree(smpt_info);
+	return err;
+}
+
+/**
+ * mic_smpt_uninit - UnInitialize MIC System Memory Page Tables.
+ *
+ * @mdev: pointer to mic_device instance.
+ *
+ * returns None.
+ */
+void mic_smpt_uninit(struct mic_device *mdev)
+{
+	struct mic_smpt_info *smpt_info = mdev->smpt;
+	int i;
+
+	dev_dbg(mdev->sdev->parent,
+		"nodeid %d SMPT ref count %lld map %lld unmap %lld\n",
+		mdev->id, smpt_info->ref_count,
+		smpt_info->map_count, smpt_info->unmap_count);
+
+	for (i = 0; i < smpt_info->info.num_reg; i++) {
+		dev_dbg(mdev->sdev->parent,
+			"SMPT entry[%d] dma_addr = 0x%llx ref_count = %lld\n",
+			i, smpt_info->entry[i].dma_addr,
+			smpt_info->entry[i].ref_count);
+		if (smpt_info->entry[i].ref_count)
+			dev_warn(mdev->sdev->parent,
+				 "ref count for entry %d is not zero\n", i);
+	}
+	kfree(smpt_info->entry);
+	kfree(smpt_info);
+}
+
+/**
+ * mic_smpt_restore - Restore MIC System Memory Page Tables.
+ *
+ * @mdev: pointer to mic_device instance.
+ *
+ * Restore the SMPT registers to values previously stored in the
+ * SW data structures. Some MIC steppings lose register state
+ * across resets and this API should be called for performing
+ * a restore operation if required.
+ *
+ * returns None.
+ */
+void mic_smpt_restore(struct mic_device *mdev)
+{
+	int i;
+	dma_addr_t dma_addr;
+
+	for (i = 0; i < mdev->smpt->info.num_reg; i++) {
+		dma_addr = mdev->smpt->entry[i].dma_addr;
+		mdev->smpt_ops->set(mdev, dma_addr, i);
+	}
+}
diff --git a/drivers/misc/mic/host/mic_smpt.h b/drivers/misc/mic/host/mic_smpt.h
new file mode 100644
index 0000000..51970ab
--- /dev/null
+++ b/drivers/misc/mic/host/mic_smpt.h
@@ -0,0 +1,98 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#ifndef MIC_SMPT_H
+#define MIC_SMPT_H
+/**
+ * struct mic_smpt_ops - MIC HW specific SMPT operations.
+ * @init: Initialize hardware specific SMPT information in mic_smpt_hw_info.
+ * @set: Set the value for a particular SMPT entry.
+ */
+struct mic_smpt_ops {
+	void (*init)(struct mic_device *mdev);
+	void (*set)(struct mic_device *mdev, dma_addr_t dma_addr, u8 index);
+};
+
+/**
+ * struct mic_smpt - MIC SMPT entry information.
+ * @dma_addr: Base DMA address for this SMPT entry.
+ * @ref_count: Number of active mappings for this SMPT entry in bytes.
+ */
+struct mic_smpt {
+	dma_addr_t dma_addr;
+	s64 ref_count;
+};
+
+/**
+ * struct mic_smpt_hw_info - MIC SMPT hardware specific information.
+ * @num_reg: Number of SMPT registers.
+ * @page_shift: System memory page shift.
+ * @page_size: System memory page size.
+ * @base: System address base.
+ */
+struct mic_smpt_hw_info {
+	u8 num_reg;
+	u8 page_shift;
+	u64 page_size;
+	u64 base;
+};
+
+/**
+ * struct mic_smpt_info - MIC SMPT information.
+ * @entry: Array of SMPT entries.
+ * @smpt_lock: Spin lock protecting access to SMPT data structures.
+ * @info: Hardware specific SMPT information.
+ * @ref_count: Number of active SMPT mappings (for debug).
+ * @map_count: Number of SMPT mappings created (for debug).
+ * @unmap_count: Number of SMPT mappings destroyed (for debug).
+ */
+struct mic_smpt_info {
+	struct mic_smpt *entry;
+	spinlock_t smpt_lock;
+	struct mic_smpt_hw_info info;
+	s64 ref_count;
+	s64 map_count;
+	s64 unmap_count;
+};
+
+dma_addr_t mic_map_single(struct mic_device *mdev, void *va, size_t size);
+void mic_unmap_single(struct mic_device *mdev,
+	dma_addr_t mic_addr, size_t size);
+dma_addr_t mic_map(struct mic_device *mdev,
+	dma_addr_t dma_addr, size_t size);
+void mic_unmap(struct mic_device *mdev, dma_addr_t mic_addr, size_t size);
+
+/**
+ * mic_map_error - Check a MIC address for errors.
+ *
+ * @mdev: pointer to mic_device instance.
+ *
+ * returns Whether there was an error during mic_map..(..) APIs.
+ */
+static inline bool mic_map_error(dma_addr_t mic_addr)
+{
+	return !mic_addr;
+}
+
+int mic_smpt_init(struct mic_device *mdev);
+void mic_smpt_uninit(struct mic_device *mdev);
+void mic_smpt_restore(struct mic_device *mdev);
+
+#endif
diff --git a/drivers/misc/mic/host/mic_sysfs.c b/drivers/misc/mic/host/mic_sysfs.c
new file mode 100644
index 0000000..6dd864e
--- /dev/null
+++ b/drivers/misc/mic/host/mic_sysfs.c
@@ -0,0 +1,459 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#include <linux/pci.h>
+
+#include <linux/mic_common.h>
+#include "../common/mic_dev.h"
+#include "mic_device.h"
+
+/*
+ * A state-to-string lookup table, for exposing a human readable state
+ * via sysfs. Always keep in sync with enum mic_states
+ */
+static const char * const mic_state_string[] = {
+	[MIC_OFFLINE] = "offline",
+	[MIC_ONLINE] = "online",
+	[MIC_SHUTTING_DOWN] = "shutting_down",
+	[MIC_RESET_FAILED] = "reset_failed",
+	[MIC_SUSPENDING] = "suspending",
+	[MIC_SUSPENDED] = "suspended",
+};
+
+/*
+ * A shutdown-status-to-string lookup table, for exposing a human
+ * readable state via sysfs. Always keep in sync with enum mic_shutdown_status
+ */
+static const char * const mic_shutdown_status_string[] = {
+	[MIC_NOP] = "nop",
+	[MIC_CRASHED] = "crashed",
+	[MIC_HALTED] = "halted",
+	[MIC_POWER_OFF] = "poweroff",
+	[MIC_RESTART] = "restart",
+};
+
+void mic_set_shutdown_status(struct mic_device *mdev, u8 shutdown_status)
+{
+	dev_dbg(mdev->sdev->parent, "Shutdown Status %s -> %s\n",
+		mic_shutdown_status_string[mdev->shutdown_status],
+		mic_shutdown_status_string[shutdown_status]);
+	mdev->shutdown_status = shutdown_status;
+}
+
+void mic_set_state(struct mic_device *mdev, u8 state)
+{
+	dev_dbg(mdev->sdev->parent, "State %s -> %s\n",
+		mic_state_string[mdev->state],
+		mic_state_string[state]);
+	mdev->state = state;
+	sysfs_notify_dirent(mdev->state_sysfs);
+}
+
+static ssize_t
+family_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	static const char x100[] = "x100";
+	static const char unknown[] = "Unknown";
+	const char *card = NULL;
+	struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+	if (!mdev)
+		return -EINVAL;
+
+	switch (mdev->family) {
+	case MIC_FAMILY_X100:
+		card = x100;
+		break;
+	default:
+		card = unknown;
+		break;
+	}
+	return scnprintf(buf, PAGE_SIZE, "%s\n", card);
+}
+static DEVICE_ATTR_RO(family);
+
+static ssize_t
+stepping_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct mic_device *mdev = dev_get_drvdata(dev->parent);
+	char *string = "??";
+
+	if (!mdev)
+		return -EINVAL;
+
+	switch (mdev->stepping) {
+	case MIC_A0_STEP:
+		string = "A0";
+		break;
+	case MIC_B0_STEP:
+		string = "B0";
+		break;
+	case MIC_B1_STEP:
+		string = "B1";
+		break;
+	case MIC_C0_STEP:
+		string = "C0";
+		break;
+	default:
+		break;
+	}
+	return scnprintf(buf, PAGE_SIZE, "%s\n", string);
+}
+static DEVICE_ATTR_RO(stepping);
+
+static ssize_t
+state_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+	if (!mdev || mdev->state >= MIC_LAST)
+		return -EINVAL;
+
+	return scnprintf(buf, PAGE_SIZE, "%s\n",
+		mic_state_string[mdev->state]);
+}
+
+static ssize_t
+state_store(struct device *dev, struct device_attribute *attr,
+	    const char *buf, size_t count)
+{
+	int rc = 0;
+	struct mic_device *mdev = dev_get_drvdata(dev->parent);
+	if (!mdev)
+		return -EINVAL;
+	if (sysfs_streq(buf, "boot")) {
+		rc = mic_start(mdev, buf);
+		if (rc) {
+			dev_err(mdev->sdev->parent,
+				"mic_boot failed rc %d\n", rc);
+			count = rc;
+		}
+		goto done;
+	}
+
+	if (sysfs_streq(buf, "reset")) {
+		schedule_work(&mdev->reset_trigger_work);
+		goto done;
+	}
+
+	if (sysfs_streq(buf, "shutdown")) {
+		mic_shutdown(mdev);
+		goto done;
+	}
+
+	if (sysfs_streq(buf, "suspend")) {
+		mic_suspend(mdev);
+		goto done;
+	}
+
+	count = -EINVAL;
+done:
+	return count;
+}
+static DEVICE_ATTR_RW(state);
+
+static ssize_t shutdown_status_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+	if (!mdev || mdev->shutdown_status >= MIC_STATUS_LAST)
+		return -EINVAL;
+
+	return scnprintf(buf, PAGE_SIZE, "%s\n",
+		mic_shutdown_status_string[mdev->shutdown_status]);
+}
+static DEVICE_ATTR_RO(shutdown_status);
+
+static ssize_t
+cmdline_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct mic_device *mdev = dev_get_drvdata(dev->parent);
+	char *cmdline;
+
+	if (!mdev)
+		return -EINVAL;
+
+	cmdline = mdev->cmdline;
+
+	if (cmdline)
+		return scnprintf(buf, PAGE_SIZE, "%s\n", cmdline);
+	return 0;
+}
+
+static ssize_t
+cmdline_store(struct device *dev, struct device_attribute *attr,
+	      const char *buf, size_t count)
+{
+	struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+	if (!mdev)
+		return -EINVAL;
+
+	mutex_lock(&mdev->mic_mutex);
+	kfree(mdev->cmdline);
+
+	mdev->cmdline = kmalloc(count + 1, GFP_KERNEL);
+	if (!mdev->cmdline) {
+		count = -ENOMEM;
+		goto unlock;
+	}
+
+	strncpy(mdev->cmdline, buf, count);
+
+	if (mdev->cmdline[count - 1] == '\n')
+		mdev->cmdline[count - 1] = '\0';
+	else
+		mdev->cmdline[count] = '\0';
+unlock:
+	mutex_unlock(&mdev->mic_mutex);
+	return count;
+}
+static DEVICE_ATTR_RW(cmdline);
+
+static ssize_t
+firmware_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct mic_device *mdev = dev_get_drvdata(dev->parent);
+	char *firmware;
+
+	if (!mdev)
+		return -EINVAL;
+
+	firmware = mdev->firmware;
+
+	if (firmware)
+		return scnprintf(buf, PAGE_SIZE, "%s\n", firmware);
+	return 0;
+}
+
+static ssize_t
+firmware_store(struct device *dev, struct device_attribute *attr,
+	       const char *buf, size_t count)
+{
+	struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+	if (!mdev)
+		return -EINVAL;
+
+	mutex_lock(&mdev->mic_mutex);
+	kfree(mdev->firmware);
+
+	mdev->firmware = kmalloc(count + 1, GFP_KERNEL);
+	if (!mdev->firmware) {
+		count = -ENOMEM;
+		goto unlock;
+	}
+	strncpy(mdev->firmware, buf, count);
+
+	if (mdev->firmware[count - 1] == '\n')
+		mdev->firmware[count - 1] = '\0';
+	else
+		mdev->firmware[count] = '\0';
+unlock:
+	mutex_unlock(&mdev->mic_mutex);
+	return count;
+}
+static DEVICE_ATTR_RW(firmware);
+
+static ssize_t
+ramdisk_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct mic_device *mdev = dev_get_drvdata(dev->parent);
+	char *ramdisk;
+
+	if (!mdev)
+		return -EINVAL;
+
+	ramdisk = mdev->ramdisk;
+
+	if (ramdisk)
+		return scnprintf(buf, PAGE_SIZE, "%s\n", ramdisk);
+	return 0;
+}
+
+static ssize_t
+ramdisk_store(struct device *dev, struct device_attribute *attr,
+	      const char *buf, size_t count)
+{
+	struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+	if (!mdev)
+		return -EINVAL;
+
+	mutex_lock(&mdev->mic_mutex);
+	kfree(mdev->ramdisk);
+
+	mdev->ramdisk = kmalloc(count + 1, GFP_KERNEL);
+	if (!mdev->ramdisk) {
+		count = -ENOMEM;
+		goto unlock;
+	}
+
+	strncpy(mdev->ramdisk, buf, count);
+
+	if (mdev->ramdisk[count - 1] == '\n')
+		mdev->ramdisk[count - 1] = '\0';
+	else
+		mdev->ramdisk[count] = '\0';
+unlock:
+	mutex_unlock(&mdev->mic_mutex);
+	return count;
+}
+static DEVICE_ATTR_RW(ramdisk);
+
+static ssize_t
+bootmode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct mic_device *mdev = dev_get_drvdata(dev->parent);
+	char *bootmode;
+
+	if (!mdev)
+		return -EINVAL;
+
+	bootmode = mdev->bootmode;
+
+	if (bootmode)
+		return scnprintf(buf, PAGE_SIZE, "%s\n", bootmode);
+	return 0;
+}
+
+static ssize_t
+bootmode_store(struct device *dev, struct device_attribute *attr,
+	       const char *buf, size_t count)
+{
+	struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+	if (!mdev)
+		return -EINVAL;
+
+	if (!sysfs_streq(buf, "linux") && !sysfs_streq(buf, "elf"))
+		return -EINVAL;
+
+	mutex_lock(&mdev->mic_mutex);
+	kfree(mdev->bootmode);
+
+	mdev->bootmode = kmalloc(count + 1, GFP_KERNEL);
+	if (!mdev->bootmode) {
+		count = -ENOMEM;
+		goto unlock;
+	}
+
+	strncpy(mdev->bootmode, buf, count);
+
+	if (mdev->bootmode[count - 1] == '\n')
+		mdev->bootmode[count - 1] = '\0';
+	else
+		mdev->bootmode[count] = '\0';
+unlock:
+	mutex_unlock(&mdev->mic_mutex);
+	return count;
+}
+static DEVICE_ATTR_RW(bootmode);
+
+static ssize_t
+log_buf_addr_show(struct device *dev, struct device_attribute *attr,
+		  char *buf)
+{
+	struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+	if (!mdev)
+		return -EINVAL;
+
+	return scnprintf(buf, PAGE_SIZE, "%p\n", mdev->log_buf_addr);
+}
+
+static ssize_t
+log_buf_addr_store(struct device *dev, struct device_attribute *attr,
+		   const char *buf, size_t count)
+{
+	struct mic_device *mdev = dev_get_drvdata(dev->parent);
+	int ret;
+	unsigned long addr;
+
+	if (!mdev)
+		return -EINVAL;
+
+	ret = kstrtoul(buf, 16, &addr);
+	if (ret)
+		goto exit;
+
+	mdev->log_buf_addr = (void *)addr;
+	ret = count;
+exit:
+	return ret;
+}
+static DEVICE_ATTR_RW(log_buf_addr);
+
+static ssize_t
+log_buf_len_show(struct device *dev, struct device_attribute *attr,
+		 char *buf)
+{
+	struct mic_device *mdev = dev_get_drvdata(dev->parent);
+
+	if (!mdev)
+		return -EINVAL;
+
+	return scnprintf(buf, PAGE_SIZE, "%p\n", mdev->log_buf_len);
+}
+
+static ssize_t
+log_buf_len_store(struct device *dev, struct device_attribute *attr,
+		  const char *buf, size_t count)
+{
+	struct mic_device *mdev = dev_get_drvdata(dev->parent);
+	int ret;
+	unsigned long addr;
+
+	if (!mdev)
+		return -EINVAL;
+
+	ret = kstrtoul(buf, 16, &addr);
+	if (ret)
+		goto exit;
+
+	mdev->log_buf_len = (int *)addr;
+	ret = count;
+exit:
+	return ret;
+}
+static DEVICE_ATTR_RW(log_buf_len);
+
+static struct attribute *mic_default_attrs[] = {
+	&dev_attr_family.attr,
+	&dev_attr_stepping.attr,
+	&dev_attr_state.attr,
+	&dev_attr_shutdown_status.attr,
+	&dev_attr_cmdline.attr,
+	&dev_attr_firmware.attr,
+	&dev_attr_ramdisk.attr,
+	&dev_attr_bootmode.attr,
+	&dev_attr_log_buf_addr.attr,
+	&dev_attr_log_buf_len.attr,
+
+	NULL
+};
+
+ATTRIBUTE_GROUPS(mic_default);
+
+void mic_sysfs_init(struct mic_device *mdev)
+{
+	mdev->attr_group = mic_default_groups;
+}
diff --git a/drivers/misc/mic/host/mic_virtio.c b/drivers/misc/mic/host/mic_virtio.c
new file mode 100644
index 0000000..5b8494b
--- /dev/null
+++ b/drivers/misc/mic/host/mic_virtio.c
@@ -0,0 +1,700 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+
+#include <linux/mic_common.h>
+#include "../common/mic_dev.h"
+#include "mic_device.h"
+#include "mic_smpt.h"
+#include "mic_virtio.h"
+
+/*
+ * Initiates the copies across the PCIe bus from card memory to
+ * a user space buffer.
+ */
+static int mic_virtio_copy_to_user(struct mic_vdev *mvdev,
+		void __user *ubuf, size_t len, u64 addr)
+{
+	int err;
+	void __iomem *dbuf = mvdev->mdev->aper.va + addr;
+	/*
+	 * We are copying from IO below an should ideally use something
+	 * like copy_to_user_fromio(..) if it existed.
+	 */
+	if (copy_to_user(ubuf, dbuf, len)) {
+		err = -EFAULT;
+		dev_err(mic_dev(mvdev), "%s %d err %d\n",
+			__func__, __LINE__, err);
+		goto err;
+	}
+	mvdev->in_bytes += len;
+	err = 0;
+err:
+	return err;
+}
+
+/*
+ * Initiates copies across the PCIe bus from a user space
+ * buffer to card memory.
+ */
+static int mic_virtio_copy_from_user(struct mic_vdev *mvdev,
+		void __user *ubuf, size_t len, u64 addr)
+{
+	int err;
+	void __iomem *dbuf = mvdev->mdev->aper.va + addr;
+	/*
+	 * We are copying to IO below and should ideally use something
+	 * like copy_from_user_toio(..) if it existed.
+	 */
+	if (copy_from_user(dbuf, ubuf, len)) {
+		err = -EFAULT;
+		dev_err(mic_dev(mvdev), "%s %d err %d\n",
+			__func__, __LINE__, err);
+		goto err;
+	}
+	mvdev->out_bytes += len;
+	err = 0;
+err:
+	return err;
+}
+
+#define MIC_VRINGH_READ true
+
+/* The function to call to notify the card about added buffers */
+static void mic_notify(struct vringh *vrh)
+{
+	struct mic_vringh *mvrh = container_of(vrh, struct mic_vringh, vrh);
+	struct mic_vdev *mvdev = mvrh->mvdev;
+	s8 db = mvdev->dc->h2c_vdev_db;
+
+	if (db != -1)
+		mvdev->mdev->ops->send_intr(mvdev->mdev, db);
+}
+
+/* Determine the total number of bytes consumed in a VRINGH KIOV */
+static inline u32 mic_vringh_iov_consumed(struct vringh_kiov *iov)
+{
+	int i;
+	u32 total = iov->consumed;
+
+	for (i = 0; i < iov->i; i++)
+		total += iov->iov[i].iov_len;
+	return total;
+}
+
+/*
+ * Traverse the VRINGH KIOV and issue the APIs to trigger the copies.
+ * This API is heavily based on the vringh_iov_xfer(..) implementation
+ * in vringh.c. The reason we cannot reuse vringh_iov_pull_kern(..)
+ * and vringh_iov_push_kern(..) directly is because there is no
+ * way to override the VRINGH xfer(..) routines as of v3.10.
+ */
+static int mic_vringh_copy(struct mic_vdev *mvdev, struct vringh_kiov *iov,
+	void __user *ubuf, size_t len, bool read, size_t *out_len)
+{
+	int ret = 0;
+	size_t partlen, tot_len = 0;
+
+	while (len && iov->i < iov->used) {
+		partlen = min(iov->iov[iov->i].iov_len, len);
+		if (read)
+			ret = mic_virtio_copy_to_user(mvdev,
+				ubuf, partlen,
+				(u64)iov->iov[iov->i].iov_base);
+		else
+			ret = mic_virtio_copy_from_user(mvdev,
+				ubuf, partlen,
+				(u64)iov->iov[iov->i].iov_base);
+		if (ret) {
+			dev_err(mic_dev(mvdev), "%s %d err %d\n",
+				__func__, __LINE__, ret);
+			break;
+		}
+		len -= partlen;
+		ubuf += partlen;
+		tot_len += partlen;
+		iov->consumed += partlen;
+		iov->iov[iov->i].iov_len -= partlen;
+		iov->iov[iov->i].iov_base += partlen;
+		if (!iov->iov[iov->i].iov_len) {
+			/* Fix up old iov element then increment. */
+			iov->iov[iov->i].iov_len = iov->consumed;
+			iov->iov[iov->i].iov_base -= iov->consumed;
+
+			iov->consumed = 0;
+			iov->i++;
+		}
+	}
+	*out_len = tot_len;
+	return ret;
+}
+
+/*
+ * Use the standard VRINGH infrastructure in the kernel to fetch new
+ * descriptors, initiate the copies and update the used ring.
+ */
+static int _mic_virtio_copy(struct mic_vdev *mvdev,
+	struct mic_copy_desc *copy)
+{
+	int ret = 0, iovcnt = copy->iovcnt;
+	struct iovec iov;
+	struct iovec __user *u_iov = copy->iov;
+	void __user *ubuf = NULL;
+	struct mic_vringh *mvr = &mvdev->mvr[copy->vr_idx];
+	struct vringh_kiov *riov = &mvr->riov;
+	struct vringh_kiov *wiov = &mvr->wiov;
+	struct vringh *vrh = &mvr->vrh;
+	u16 *head = &mvr->head;
+	struct mic_vring *vr = &mvr->vring;
+	size_t len = 0, out_len;
+
+	copy->out_len = 0;
+	/* Fetch a new IOVEC if all previous elements have been processed */
+	if (riov->i == riov->used && wiov->i == wiov->used) {
+		ret = vringh_getdesc_kern(vrh, riov, wiov,
+				head, GFP_KERNEL);
+		/* Check if there are available descriptors */
+		if (ret <= 0)
+			return ret;
+	}
+	while (iovcnt) {
+		if (!len) {
+			/* Copy over a new iovec from user space. */
+			ret = copy_from_user(&iov, u_iov, sizeof(*u_iov));
+			if (ret) {
+				ret = -EINVAL;
+				dev_err(mic_dev(mvdev), "%s %d err %d\n",
+					__func__, __LINE__, ret);
+				break;
+			}
+			len = iov.iov_len;
+			ubuf = iov.iov_base;
+		}
+		/* Issue all the read descriptors first */
+		ret = mic_vringh_copy(mvdev, riov, ubuf, len,
+			MIC_VRINGH_READ, &out_len);
+		if (ret) {
+			dev_err(mic_dev(mvdev), "%s %d err %d\n",
+				__func__, __LINE__, ret);
+			break;
+		}
+		len -= out_len;
+		ubuf += out_len;
+		copy->out_len += out_len;
+		/* Issue the write descriptors next */
+		ret = mic_vringh_copy(mvdev, wiov, ubuf, len,
+			!MIC_VRINGH_READ, &out_len);
+		if (ret) {
+			dev_err(mic_dev(mvdev), "%s %d err %d\n",
+				__func__, __LINE__, ret);
+			break;
+		}
+		len -= out_len;
+		ubuf += out_len;
+		copy->out_len += out_len;
+		if (!len) {
+			/* One user space iovec is now completed */
+			iovcnt--;
+			u_iov++;
+		}
+		/* Exit loop if all elements in KIOVs have been processed. */
+		if (riov->i == riov->used && wiov->i == wiov->used)
+			break;
+	}
+	/*
+	 * Update the used ring if a descriptor was available and some data was
+	 * copied in/out and the user asked for a used ring update.
+	 */
+	if (*head != USHRT_MAX && copy->out_len && copy->update_used) {
+		u32 total = 0;
+
+		/* Determine the total data consumed */
+		total += mic_vringh_iov_consumed(riov);
+		total += mic_vringh_iov_consumed(wiov);
+		vringh_complete_kern(vrh, *head, total);
+		*head = USHRT_MAX;
+		if (vringh_need_notify_kern(vrh) > 0)
+			vringh_notify(vrh);
+		vringh_kiov_cleanup(riov);
+		vringh_kiov_cleanup(wiov);
+		/* Update avail idx for user space */
+		vr->info->avail_idx = vrh->last_avail_idx;
+	}
+	return ret;
+}
+
+static inline int mic_verify_copy_args(struct mic_vdev *mvdev,
+		struct mic_copy_desc *copy)
+{
+	if (copy->vr_idx >= mvdev->dd->num_vq) {
+		dev_err(mic_dev(mvdev), "%s %d err %d\n",
+			__func__, __LINE__, -EINVAL);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/* Copy a specified number of virtio descriptors in a chain */
+int mic_virtio_copy_desc(struct mic_vdev *mvdev,
+		struct mic_copy_desc *copy)
+{
+	int err;
+	struct mic_vringh *mvr = &mvdev->mvr[copy->vr_idx];
+
+	err = mic_verify_copy_args(mvdev, copy);
+	if (err)
+		return err;
+
+	mutex_lock(&mvr->vr_mutex);
+	if (!mic_vdevup(mvdev)) {
+		err = -ENODEV;
+		dev_err(mic_dev(mvdev), "%s %d err %d\n",
+			__func__, __LINE__, err);
+		goto err;
+	}
+	err = _mic_virtio_copy(mvdev, copy);
+	if (err) {
+		dev_err(mic_dev(mvdev), "%s %d err %d\n",
+			__func__, __LINE__, err);
+	}
+err:
+	mutex_unlock(&mvr->vr_mutex);
+	return err;
+}
+
+static void mic_virtio_init_post(struct mic_vdev *mvdev)
+{
+	struct mic_vqconfig *vqconfig = mic_vq_config(mvdev->dd);
+	int i;
+
+	for (i = 0; i < mvdev->dd->num_vq; i++) {
+		if (!le64_to_cpu(vqconfig[i].used_address)) {
+			dev_warn(mic_dev(mvdev), "used_address zero??\n");
+			continue;
+		}
+		mvdev->mvr[i].vrh.vring.used =
+			mvdev->mdev->aper.va +
+			le64_to_cpu(vqconfig[i].used_address);
+	}
+
+	mvdev->dc->used_address_updated = 0;
+
+	dev_dbg(mic_dev(mvdev), "%s: device type %d LINKUP\n",
+		__func__, mvdev->virtio_id);
+}
+
+static inline void mic_virtio_device_reset(struct mic_vdev *mvdev)
+{
+	int i;
+
+	dev_dbg(mic_dev(mvdev), "%s: status %d device type %d RESET\n",
+		__func__, mvdev->dd->status, mvdev->virtio_id);
+
+	for (i = 0; i < mvdev->dd->num_vq; i++)
+		/*
+		 * Avoid lockdep false positive. The + 1 is for the mic
+		 * mutex which is held in the reset devices code path.
+		 */
+		mutex_lock_nested(&mvdev->mvr[i].vr_mutex, i + 1);
+
+	/* 0 status means "reset" */
+	mvdev->dd->status = 0;
+	mvdev->dc->vdev_reset = 0;
+	mvdev->dc->host_ack = 1;
+
+	for (i = 0; i < mvdev->dd->num_vq; i++) {
+		struct vringh *vrh = &mvdev->mvr[i].vrh;
+		mvdev->mvr[i].vring.info->avail_idx = 0;
+		vrh->completed = 0;
+		vrh->last_avail_idx = 0;
+		vrh->last_used_idx = 0;
+	}
+
+	for (i = 0; i < mvdev->dd->num_vq; i++)
+		mutex_unlock(&mvdev->mvr[i].vr_mutex);
+}
+
+void mic_virtio_reset_devices(struct mic_device *mdev)
+{
+	struct list_head *pos, *tmp;
+	struct mic_vdev *mvdev;
+
+	dev_dbg(mdev->sdev->parent, "%s\n",  __func__);
+
+	list_for_each_safe(pos, tmp, &mdev->vdev_list) {
+		mvdev = list_entry(pos, struct mic_vdev, list);
+		mic_virtio_device_reset(mvdev);
+		mvdev->poll_wake = 1;
+		wake_up(&mvdev->waitq);
+	}
+}
+
+void mic_bh_handler(struct work_struct *work)
+{
+	struct mic_vdev *mvdev = container_of(work, struct mic_vdev,
+			virtio_bh_work);
+
+	if (mvdev->dc->used_address_updated)
+		mic_virtio_init_post(mvdev);
+
+	if (mvdev->dc->vdev_reset)
+		mic_virtio_device_reset(mvdev);
+
+	mvdev->poll_wake = 1;
+	wake_up(&mvdev->waitq);
+}
+
+static irqreturn_t mic_virtio_intr_handler(int irq, void *data)
+{
+	struct mic_vdev *mvdev = data;
+	struct mic_device *mdev = mvdev->mdev;
+
+	mdev->ops->ack_interrupt(mdev);
+	schedule_work(&mvdev->virtio_bh_work);
+	return IRQ_HANDLED;
+}
+
+int mic_virtio_config_change(struct mic_vdev *mvdev,
+			void __user *argp)
+{
+	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
+	int ret = 0, retry = 100, i;
+	struct mic_bootparam *bootparam = mvdev->mdev->dp;
+	s8 db = bootparam->h2c_config_db;
+
+	mutex_lock(&mvdev->mdev->mic_mutex);
+	for (i = 0; i < mvdev->dd->num_vq; i++)
+		mutex_lock_nested(&mvdev->mvr[i].vr_mutex, i + 1);
+
+	if (db == -1 || mvdev->dd->type == -1) {
+		ret = -EIO;
+		goto exit;
+	}
+
+	if (copy_from_user(mic_vq_configspace(mvdev->dd),
+			   argp, mvdev->dd->config_len)) {
+		dev_err(mic_dev(mvdev), "%s %d err %d\n",
+			__func__, __LINE__, -EFAULT);
+		ret = -EFAULT;
+		goto exit;
+	}
+	mvdev->dc->config_change = MIC_VIRTIO_PARAM_CONFIG_CHANGED;
+	mvdev->mdev->ops->send_intr(mvdev->mdev, db);
+
+	for (i = retry; i--;) {
+		ret = wait_event_timeout(wake,
+			mvdev->dc->guest_ack, msecs_to_jiffies(100));
+		if (ret)
+			break;
+	}
+
+	dev_dbg(mic_dev(mvdev),
+		"%s %d retry: %d\n", __func__, __LINE__, retry);
+	mvdev->dc->config_change = 0;
+	mvdev->dc->guest_ack = 0;
+exit:
+	for (i = 0; i < mvdev->dd->num_vq; i++)
+		mutex_unlock(&mvdev->mvr[i].vr_mutex);
+	mutex_unlock(&mvdev->mdev->mic_mutex);
+	return ret;
+}
+
+static int mic_copy_dp_entry(struct mic_vdev *mvdev,
+					void __user *argp,
+					__u8 *type,
+					struct mic_device_desc **devpage)
+{
+	struct mic_device *mdev = mvdev->mdev;
+	struct mic_device_desc dd, *dd_config, *devp;
+	struct mic_vqconfig *vqconfig;
+	int ret = 0, i;
+	bool slot_found = false;
+
+	if (copy_from_user(&dd, argp, sizeof(dd))) {
+		dev_err(mic_dev(mvdev), "%s %d err %d\n",
+			__func__, __LINE__, -EFAULT);
+		return -EFAULT;
+	}
+
+	if (mic_aligned_desc_size(&dd) > MIC_MAX_DESC_BLK_SIZE ||
+	    dd.num_vq > MIC_MAX_VRINGS) {
+		dev_err(mic_dev(mvdev), "%s %d err %d\n",
+			__func__, __LINE__, -EINVAL);
+		return -EINVAL;
+	}
+
+	dd_config = kmalloc(mic_desc_size(&dd), GFP_KERNEL);
+	if (dd_config == NULL) {
+		dev_err(mic_dev(mvdev), "%s %d err %d\n",
+			__func__, __LINE__, -ENOMEM);
+		return -ENOMEM;
+	}
+	if (copy_from_user(dd_config, argp, mic_desc_size(&dd))) {
+		ret = -EFAULT;
+		dev_err(mic_dev(mvdev), "%s %d err %d\n",
+			__func__, __LINE__, ret);
+		goto exit;
+	}
+
+	vqconfig = mic_vq_config(dd_config);
+	for (i = 0; i < dd.num_vq; i++) {
+		if (le16_to_cpu(vqconfig[i].num) > MIC_MAX_VRING_ENTRIES) {
+			ret =  -EINVAL;
+			dev_err(mic_dev(mvdev), "%s %d err %d\n",
+				__func__, __LINE__, ret);
+			goto exit;
+		}
+	}
+
+	/* Find the first free device page entry */
+	for (i = mic_aligned_size(struct mic_bootparam);
+		i < MIC_DP_SIZE - mic_total_desc_size(dd_config);
+		i += mic_total_desc_size(devp)) {
+		devp = mdev->dp + i;
+		if (devp->type == 0 || devp->type == -1) {
+			slot_found = true;
+			break;
+		}
+	}
+	if (!slot_found) {
+		ret =  -EINVAL;
+		dev_err(mic_dev(mvdev), "%s %d err %d\n",
+			__func__, __LINE__, ret);
+		goto exit;
+	}
+	/*
+	 * Save off the type before doing the memcpy. Type will be set in the
+	 * end after completing all initialization for the new device.
+	 */
+	*type = dd_config->type;
+	dd_config->type = 0;
+	memcpy(devp, dd_config, mic_desc_size(dd_config));
+
+	*devpage = devp;
+exit:
+	kfree(dd_config);
+	return ret;
+}
+
+static void mic_init_device_ctrl(struct mic_vdev *mvdev,
+				struct mic_device_desc *devpage)
+{
+	struct mic_device_ctrl *dc;
+
+	dc = (void *)devpage + mic_aligned_desc_size(devpage);
+
+	dc->config_change = 0;
+	dc->guest_ack = 0;
+	dc->vdev_reset = 0;
+	dc->host_ack = 0;
+	dc->used_address_updated = 0;
+	dc->c2h_vdev_db = -1;
+	dc->h2c_vdev_db = -1;
+	mvdev->dc = dc;
+}
+
+int mic_virtio_add_device(struct mic_vdev *mvdev,
+			void __user *argp)
+{
+	struct mic_device *mdev = mvdev->mdev;
+	struct mic_device_desc *dd = NULL;
+	struct mic_vqconfig *vqconfig;
+	int vr_size, i, j, ret;
+	u8 type = 0;
+	s8 db;
+	char irqname[10];
+	struct mic_bootparam *bootparam = mdev->dp;
+	u16 num;
+
+	mutex_lock(&mdev->mic_mutex);
+
+	ret = mic_copy_dp_entry(mvdev, argp, &type, &dd);
+	if (ret) {
+		mutex_unlock(&mdev->mic_mutex);
+		return ret;
+	}
+
+	mic_init_device_ctrl(mvdev, dd);
+
+	mvdev->dd = dd;
+	mvdev->virtio_id = type;
+	vqconfig = mic_vq_config(dd);
+	INIT_WORK(&mvdev->virtio_bh_work, mic_bh_handler);
+
+	for (i = 0; i < dd->num_vq; i++) {
+		struct mic_vringh *mvr = &mvdev->mvr[i];
+		struct mic_vring *vr = &mvdev->mvr[i].vring;
+		num = le16_to_cpu(vqconfig[i].num);
+		mutex_init(&mvr->vr_mutex);
+		vr_size = PAGE_ALIGN(vring_size(num, MIC_VIRTIO_RING_ALIGN) +
+			sizeof(struct _mic_vring_info));
+		vr->va = (void *)
+			__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+					 get_order(vr_size));
+		if (!vr->va) {
+			ret = -ENOMEM;
+			dev_err(mic_dev(mvdev), "%s %d err %d\n",
+				__func__, __LINE__, ret);
+			goto err;
+		}
+		vr->len = vr_size;
+		vr->info = vr->va + vring_size(num, MIC_VIRTIO_RING_ALIGN);
+		vr->info->magic = MIC_MAGIC + mvdev->virtio_id + i;
+		vqconfig[i].address = mic_map_single(mdev,
+			vr->va, vr_size);
+		if (mic_map_error(vqconfig[i].address)) {
+			free_pages((unsigned long)vr->va, get_order(vr_size));
+			ret = -ENOMEM;
+			dev_err(mic_dev(mvdev), "%s %d err %d\n",
+				__func__, __LINE__, ret);
+			goto err;
+		}
+		vqconfig[i].address = cpu_to_le64(vqconfig[i].address);
+
+		vring_init(&vr->vr, num, vr->va, MIC_VIRTIO_RING_ALIGN);
+		ret = vringh_init_kern(&mvr->vrh,
+			*(u32 *)mic_vq_features(mvdev->dd), num, false,
+			vr->vr.desc, vr->vr.avail, vr->vr.used);
+		if (ret) {
+			dev_err(mic_dev(mvdev), "%s %d err %d\n",
+				__func__, __LINE__, ret);
+			goto err;
+		}
+		vringh_kiov_init(&mvr->riov, NULL, 0);
+		vringh_kiov_init(&mvr->wiov, NULL, 0);
+		mvr->head = USHRT_MAX;
+		mvr->mvdev = mvdev;
+		mvr->vrh.notify = mic_notify;
+		dev_dbg(mdev->sdev->parent,
+			"%s %d index %d va %p info %p vr_size 0x%x\n",
+			__func__, __LINE__, i, vr->va, vr->info, vr_size);
+	}
+
+	snprintf(irqname, sizeof(irqname), "mic%dvirtio%d", mdev->id,
+		 mvdev->virtio_id);
+	mvdev->virtio_db = mic_next_db(mdev);
+	mvdev->virtio_cookie = mic_request_irq(mdev, mic_virtio_intr_handler,
+			irqname, mvdev, mvdev->virtio_db, MIC_INTR_DB);
+	if (IS_ERR(mvdev->virtio_cookie)) {
+		ret = PTR_ERR(mvdev->virtio_cookie);
+		dev_dbg(mdev->sdev->parent, "request irq failed\n");
+		goto err;
+	}
+
+	mvdev->dc->c2h_vdev_db = mvdev->virtio_db;
+
+	list_add_tail(&mvdev->list, &mdev->vdev_list);
+	/*
+	 * Order the type update with previous stores. This write barrier
+	 * is paired with the corresponding read barrier before the uncached
+	 * system memory read of the type, on the card while scanning the
+	 * device page.
+	 */
+	smp_wmb();
+	dd->type = type;
+
+	dev_dbg(mdev->sdev->parent, "Added virtio device id %d\n", dd->type);
+
+	db = bootparam->h2c_config_db;
+	if (db != -1)
+		mdev->ops->send_intr(mdev, db);
+	mutex_unlock(&mdev->mic_mutex);
+	return 0;
+err:
+	vqconfig = mic_vq_config(dd);
+	for (j = 0; j < i; j++) {
+		struct mic_vringh *mvr = &mvdev->mvr[j];
+		mic_unmap_single(mdev, le64_to_cpu(vqconfig[j].address),
+				 mvr->vring.len);
+		free_pages((unsigned long)mvr->vring.va,
+			   get_order(mvr->vring.len));
+	}
+	mutex_unlock(&mdev->mic_mutex);
+	return ret;
+}
+
+void mic_virtio_del_device(struct mic_vdev *mvdev)
+{
+	struct list_head *pos, *tmp;
+	struct mic_vdev *tmp_mvdev;
+	struct mic_device *mdev = mvdev->mdev;
+	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
+	int i, ret, retry = 100;
+	struct mic_vqconfig *vqconfig;
+	struct mic_bootparam *bootparam = mdev->dp;
+	s8 db;
+
+	mutex_lock(&mdev->mic_mutex);
+	db = bootparam->h2c_config_db;
+	if (db == -1)
+		goto skip_hot_remove;
+	dev_dbg(mdev->sdev->parent,
+		"Requesting hot remove id %d\n", mvdev->virtio_id);
+	mvdev->dc->config_change = MIC_VIRTIO_PARAM_DEV_REMOVE;
+	mdev->ops->send_intr(mdev, db);
+	for (i = retry; i--;) {
+		ret = wait_event_timeout(wake,
+			mvdev->dc->guest_ack, msecs_to_jiffies(100));
+		if (ret)
+			break;
+	}
+	dev_dbg(mdev->sdev->parent,
+		"Device id %d config_change %d guest_ack %d\n",
+		mvdev->virtio_id, mvdev->dc->config_change,
+		mvdev->dc->guest_ack);
+	mvdev->dc->config_change = 0;
+	mvdev->dc->guest_ack = 0;
+skip_hot_remove:
+	mic_free_irq(mdev, mvdev->virtio_cookie, mvdev);
+	flush_work(&mvdev->virtio_bh_work);
+	vqconfig = mic_vq_config(mvdev->dd);
+	for (i = 0; i < mvdev->dd->num_vq; i++) {
+		struct mic_vringh *mvr = &mvdev->mvr[i];
+		vringh_kiov_cleanup(&mvr->riov);
+		vringh_kiov_cleanup(&mvr->wiov);
+		mic_unmap_single(mdev, le64_to_cpu(vqconfig[i].address),
+				 mvr->vring.len);
+		free_pages((unsigned long)mvr->vring.va,
+			   get_order(mvr->vring.len));
+	}
+
+	list_for_each_safe(pos, tmp, &mdev->vdev_list) {
+		tmp_mvdev = list_entry(pos, struct mic_vdev, list);
+		if (tmp_mvdev == mvdev) {
+			list_del(pos);
+			dev_dbg(mdev->sdev->parent,
+				"Removing virtio device id %d\n",
+				mvdev->virtio_id);
+			break;
+		}
+	}
+	/*
+	 * Order the type update with previous stores. This write barrier
+	 * is paired with the corresponding read barrier before the uncached
+	 * system memory read of the type, on the card while scanning the
+	 * device page.
+	 */
+	smp_wmb();
+	mvdev->dd->type = -1;
+	mutex_unlock(&mdev->mic_mutex);
+}
diff --git a/drivers/misc/mic/host/mic_virtio.h b/drivers/misc/mic/host/mic_virtio.h
new file mode 100644
index 0000000..184f3c8
--- /dev/null
+++ b/drivers/misc/mic/host/mic_virtio.h
@@ -0,0 +1,138 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#ifndef MIC_VIRTIO_H
+#define MIC_VIRTIO_H
+
+#include <linux/virtio_config.h>
+#include <linux/mic_ioctl.h>
+
+/*
+ * Note on endianness.
+ * 1. Host can be both BE or LE
+ * 2. Guest/card is LE. Host uses le_to_cpu to access desc/avail
+ *    rings and ioreadXX/iowriteXX to access used ring.
+ * 3. Device page exposed by host to guest contains LE values. Guest
+ *    accesses these using ioreadXX/iowriteXX etc. This way in general we
+ *    obey the virtio spec according to which guest works with native
+ *    endianness and host is aware of guest endianness and does all
+ *    required endianness conversion.
+ * 4. Data provided from user space to guest (in ADD_DEVICE and
+ *    CONFIG_CHANGE ioctl's) is not interpreted by the driver and should be
+ *    in guest endianness.
+ */
+
+/**
+ * struct mic_vringh - Virtio ring host information.
+ *
+ * @vring: The MIC vring used for setting up user space mappings.
+ * @vrh: The host VRINGH used for accessing the card vrings.
+ * @riov: The VRINGH read kernel IOV.
+ * @wiov: The VRINGH write kernel IOV.
+ * @head: The VRINGH head index address passed to vringh_getdesc_kern(..).
+ * @vr_mutex: Mutex for synchronizing access to the VRING.
+ * @mvdev: Back pointer to MIC virtio device for vringh_notify(..).
+ */
+struct mic_vringh {
+	struct mic_vring vring;
+	struct vringh vrh;
+	struct vringh_kiov riov;
+	struct vringh_kiov wiov;
+	u16 head;
+	struct mutex vr_mutex;
+	struct mic_vdev *mvdev;
+};
+
+/**
+ * struct mic_vdev - Host information for a card Virtio device.
+ *
+ * @virtio_id - Virtio device id.
+ * @waitq - Waitqueue to allow ring3 apps to poll.
+ * @mdev - Back pointer to host MIC device.
+ * @poll_wake - Used for waking up threads blocked in poll.
+ * @out_bytes - Debug stats for number of bytes copied from host to card.
+ * @in_bytes - Debug stats for number of bytes copied from card to host.
+ * @mvr - Store per VRING data structures.
+ * @virtio_bh_work - Work struct used to schedule virtio bottom half handling.
+ * @dd - Virtio device descriptor.
+ * @dc - Virtio device control fields.
+ * @list - List of Virtio devices.
+ * @virtio_db - The doorbell used by the card to interrupt the host.
+ * @virtio_cookie - The cookie returned while requesting interrupts.
+ */
+struct mic_vdev {
+	int virtio_id;
+	wait_queue_head_t waitq;
+	struct mic_device *mdev;
+	int poll_wake;
+	unsigned long out_bytes;
+	unsigned long in_bytes;
+	struct mic_vringh mvr[MIC_MAX_VRINGS];
+	struct work_struct virtio_bh_work;
+	struct mic_device_desc *dd;
+	struct mic_device_ctrl *dc;
+	struct list_head list;
+	int virtio_db;
+	struct mic_irq *virtio_cookie;
+};
+
+void mic_virtio_uninit(struct mic_device *mdev);
+int mic_virtio_add_device(struct mic_vdev *mvdev,
+			void __user *argp);
+void mic_virtio_del_device(struct mic_vdev *mvdev);
+int mic_virtio_config_change(struct mic_vdev *mvdev,
+			void __user *argp);
+int mic_virtio_copy_desc(struct mic_vdev *mvdev,
+	struct mic_copy_desc *request);
+void mic_virtio_reset_devices(struct mic_device *mdev);
+void mic_bh_handler(struct work_struct *work);
+
+/* Helper API to obtain the MIC PCIe device */
+static inline struct device *mic_dev(struct mic_vdev *mvdev)
+{
+	return mvdev->mdev->sdev->parent;
+}
+
+/* Helper API to check if a virtio device is initialized */
+static inline int mic_vdev_inited(struct mic_vdev *mvdev)
+{
+	/* Device has not been created yet */
+	if (!mvdev->dd || !mvdev->dd->type) {
+		dev_err(mic_dev(mvdev), "%s %d err %d\n",
+			__func__, __LINE__, -EINVAL);
+		return -EINVAL;
+	}
+
+	/* Device has been removed/deleted */
+	if (mvdev->dd->type == -1) {
+		dev_err(mic_dev(mvdev), "%s %d err %d\n",
+			__func__, __LINE__, -ENODEV);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+/* Helper API to check if a virtio device is running */
+static inline bool mic_vdevup(struct mic_vdev *mvdev)
+{
+	return !!mvdev->dd->status;
+}
+#endif
diff --git a/drivers/misc/mic/host/mic_x100.c b/drivers/misc/mic/host/mic_x100.c
new file mode 100644
index 0000000..81e9541
--- /dev/null
+++ b/drivers/misc/mic/host/mic_x100.c
@@ -0,0 +1,570 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+
+#include "../common/mic_dev.h"
+#include "mic_device.h"
+#include "mic_x100.h"
+#include "mic_smpt.h"
+
+/**
+ * mic_x100_write_spad - write to the scratchpad register
+ * @mdev: pointer to mic_device instance
+ * @idx: index to the scratchpad register, 0 based
+ * @val: the data value to put into the register
+ *
+ * This function allows writing of a 32bit value to the indexed scratchpad
+ * register.
+ *
+ * RETURNS: none.
+ */
+static void
+mic_x100_write_spad(struct mic_device *mdev, unsigned int idx, u32 val)
+{
+	dev_dbg(mdev->sdev->parent, "Writing 0x%x to scratch pad index %d\n",
+		val, idx);
+	mic_mmio_write(&mdev->mmio, val,
+		       MIC_X100_SBOX_BASE_ADDRESS +
+		       MIC_X100_SBOX_SPAD0 + idx * 4);
+}
+
+/**
+ * mic_x100_read_spad - read from the scratchpad register
+ * @mdev: pointer to mic_device instance
+ * @idx: index to scratchpad register, 0 based
+ *
+ * This function allows reading of the 32bit scratchpad register.
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+static u32
+mic_x100_read_spad(struct mic_device *mdev, unsigned int idx)
+{
+	u32 val = mic_mmio_read(&mdev->mmio,
+		MIC_X100_SBOX_BASE_ADDRESS +
+		MIC_X100_SBOX_SPAD0 + idx * 4);
+
+	dev_dbg(mdev->sdev->parent,
+		"Reading 0x%x from scratch pad index %d\n", val, idx);
+	return val;
+}
+
+/**
+ * mic_x100_enable_interrupts - Enable interrupts.
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_x100_enable_interrupts(struct mic_device *mdev)
+{
+	u32 reg;
+	struct mic_mw *mw = &mdev->mmio;
+	u32 sice0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICE0;
+	u32 siac0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SIAC0;
+
+	reg = mic_mmio_read(mw, sice0);
+	reg |= MIC_X100_SBOX_DBR_BITS(0xf) | MIC_X100_SBOX_DMA_BITS(0xff);
+	mic_mmio_write(mw, reg, sice0);
+
+	/*
+	 * Enable auto-clear when enabling interrupts. Applicable only for
+	 * MSI-x. Legacy and MSI mode cannot have auto-clear enabled.
+	 */
+	if (mdev->irq_info.num_vectors > 1) {
+		reg = mic_mmio_read(mw, siac0);
+		reg |= MIC_X100_SBOX_DBR_BITS(0xf) |
+			MIC_X100_SBOX_DMA_BITS(0xff);
+		mic_mmio_write(mw, reg, siac0);
+	}
+}
+
+/**
+ * mic_x100_disable_interrupts - Disable interrupts.
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_x100_disable_interrupts(struct mic_device *mdev)
+{
+	u32 reg;
+	struct mic_mw *mw = &mdev->mmio;
+	u32 sice0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICE0;
+	u32 siac0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SIAC0;
+	u32 sicc0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICC0;
+
+	reg = mic_mmio_read(mw, sice0);
+	mic_mmio_write(mw, reg, sicc0);
+
+	if (mdev->irq_info.num_vectors > 1) {
+		reg = mic_mmio_read(mw, siac0);
+		reg &= ~(MIC_X100_SBOX_DBR_BITS(0xf) |
+			MIC_X100_SBOX_DMA_BITS(0xff));
+		mic_mmio_write(mw, reg, siac0);
+	}
+}
+
+/**
+ * mic_x100_send_sbox_intr - Send an MIC_X100_SBOX interrupt to MIC.
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_x100_send_sbox_intr(struct mic_device *mdev,
+			int doorbell)
+{
+	struct mic_mw *mw = &mdev->mmio;
+	u64 apic_icr_offset = MIC_X100_SBOX_APICICR0 + doorbell * 8;
+	u32 apicicr_low = mic_mmio_read(mw, MIC_X100_SBOX_BASE_ADDRESS +
+					apic_icr_offset);
+
+	/* for MIC we need to make sure we "hit" the send_icr bit (13) */
+	apicicr_low = (apicicr_low | (1 << 13));
+
+	/* Ensure that the interrupt is ordered w.r.t. previous stores. */
+	wmb();
+	mic_mmio_write(mw, apicicr_low,
+		       MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
+}
+
+/**
+ * mic_x100_send_rdmasr_intr - Send an RDMASR interrupt to MIC.
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_x100_send_rdmasr_intr(struct mic_device *mdev,
+			int doorbell)
+{
+	int rdmasr_offset = MIC_X100_SBOX_RDMASR0 + (doorbell << 2);
+	/* Ensure that the interrupt is ordered w.r.t. previous stores. */
+	wmb();
+	mic_mmio_write(&mdev->mmio, 0,
+		       MIC_X100_SBOX_BASE_ADDRESS + rdmasr_offset);
+}
+
+/**
+ * __mic_x100_send_intr - Send interrupt to MIC.
+ * @mdev: pointer to mic_device instance
+ * @doorbell: doorbell number.
+ */
+static void mic_x100_send_intr(struct mic_device *mdev, int doorbell)
+{
+	int rdmasr_db;
+	if (doorbell < MIC_X100_NUM_SBOX_IRQ) {
+		mic_x100_send_sbox_intr(mdev, doorbell);
+	} else {
+		rdmasr_db = doorbell - MIC_X100_NUM_SBOX_IRQ +
+			MIC_X100_RDMASR_IRQ_BASE;
+		mic_x100_send_rdmasr_intr(mdev, rdmasr_db);
+	}
+}
+
+/**
+ * mic_ack_interrupt - Device specific interrupt handling.
+ * @mdev: pointer to mic_device instance
+ *
+ * Returns: bitmask of doorbell events triggered.
+ */
+static u32 mic_x100_ack_interrupt(struct mic_device *mdev)
+{
+	u32 reg = 0;
+	struct mic_mw *mw = &mdev->mmio;
+	u32 sicr0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICR0;
+
+	/* Clear pending bit array. */
+	if (MIC_A0_STEP == mdev->stepping)
+		mic_mmio_write(mw, 1, MIC_X100_SBOX_BASE_ADDRESS +
+			MIC_X100_SBOX_MSIXPBACR);
+
+	if (mdev->irq_info.num_vectors <= 1) {
+		reg = mic_mmio_read(mw, sicr0);
+
+		if (unlikely(!reg))
+			goto done;
+
+		mic_mmio_write(mw, reg, sicr0);
+	}
+
+	if (mdev->stepping >= MIC_B0_STEP)
+		mdev->intr_ops->enable_interrupts(mdev);
+done:
+	return reg;
+}
+
+/**
+ * mic_x100_hw_intr_init - Initialize h/w specific interrupt
+ * information.
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_x100_hw_intr_init(struct mic_device *mdev)
+{
+	mdev->intr_info = (struct mic_intr_info *)mic_x100_intr_init;
+}
+
+/**
+ * mic_x100_read_msi_to_src_map - read from the MSI mapping registers
+ * @mdev: pointer to mic_device instance
+ * @idx: index to the mapping register, 0 based
+ *
+ * This function allows reading of the 32bit MSI mapping register.
+ *
+ * RETURNS: The value in the register.
+ */
+static u32
+mic_x100_read_msi_to_src_map(struct mic_device *mdev, int idx)
+{
+	return mic_mmio_read(&mdev->mmio,
+		MIC_X100_SBOX_BASE_ADDRESS +
+		MIC_X100_SBOX_MXAR0 + idx * 4);
+}
+
+/**
+ * mic_x100_program_msi_to_src_map - program the MSI mapping registers
+ * @mdev: pointer to mic_device instance
+ * @idx: index to the mapping register, 0 based
+ * @offset: The bit offset in the register that needs to be updated.
+ * @set: boolean specifying if the bit in the specified offset needs
+ * to be set or cleared.
+ *
+ * RETURNS: None.
+ */
+static void
+mic_x100_program_msi_to_src_map(struct mic_device *mdev,
+				int idx, int offset, bool set)
+{
+	unsigned long reg;
+	struct mic_mw *mw = &mdev->mmio;
+	u32 mxar = MIC_X100_SBOX_BASE_ADDRESS +
+		MIC_X100_SBOX_MXAR0 + idx * 4;
+
+	reg = mic_mmio_read(mw, mxar);
+	if (set)
+		__set_bit(offset, &reg);
+	else
+		__clear_bit(offset, &reg);
+	mic_mmio_write(mw, reg, mxar);
+}
+
+/*
+ * mic_x100_reset_fw_ready - Reset Firmware ready status field.
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_x100_reset_fw_ready(struct mic_device *mdev)
+{
+	mdev->ops->write_spad(mdev, MIC_X100_DOWNLOAD_INFO, 0);
+}
+
+/*
+ * mic_x100_is_fw_ready - Check if firmware is ready.
+ * @mdev: pointer to mic_device instance
+ */
+static bool mic_x100_is_fw_ready(struct mic_device *mdev)
+{
+	u32 scratch2 = mdev->ops->read_spad(mdev, MIC_X100_DOWNLOAD_INFO);
+	return MIC_X100_SPAD2_DOWNLOAD_STATUS(scratch2) ? true : false;
+}
+
+/**
+ * mic_x100_get_apic_id - Get bootstrap APIC ID.
+ * @mdev: pointer to mic_device instance
+ */
+static u32 mic_x100_get_apic_id(struct mic_device *mdev)
+{
+	u32 scratch2 = 0;
+
+	scratch2 = mdev->ops->read_spad(mdev, MIC_X100_DOWNLOAD_INFO);
+	return MIC_X100_SPAD2_APIC_ID(scratch2);
+}
+
+/**
+ * mic_x100_send_firmware_intr - Send an interrupt to the firmware on MIC.
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_x100_send_firmware_intr(struct mic_device *mdev)
+{
+	u32 apicicr_low;
+	u64 apic_icr_offset = MIC_X100_SBOX_APICICR7;
+	int vector = MIC_X100_BSP_INTERRUPT_VECTOR;
+	struct mic_mw *mw = &mdev->mmio;
+
+	/*
+	 * For MIC we need to make sure we "hit"
+	 * the send_icr bit (13).
+	 */
+	apicicr_low = (vector | (1 << 13));
+
+	mic_mmio_write(mw, mic_x100_get_apic_id(mdev),
+		       MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset + 4);
+
+	/* Ensure that the interrupt is ordered w.r.t. previous stores. */
+	wmb();
+	mic_mmio_write(mw, apicicr_low,
+		       MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
+}
+
+/**
+ * mic_x100_hw_reset - Reset the MIC device.
+ * @mdev: pointer to mic_device instance
+ */
+static void mic_x100_hw_reset(struct mic_device *mdev)
+{
+	u32 reset_reg;
+	u32 rgcr = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_RGCR;
+	struct mic_mw *mw = &mdev->mmio;
+
+	/* Ensure that the reset is ordered w.r.t. previous loads and stores */
+	mb();
+	/* Trigger reset */
+	reset_reg = mic_mmio_read(mw, rgcr);
+	reset_reg |= 0x1;
+	mic_mmio_write(mw, reset_reg, rgcr);
+	/*
+	 * It seems we really want to delay at least 1 second
+	 * after touching reset to prevent a lot of problems.
+	 */
+	msleep(1000);
+}
+
+/**
+ * mic_x100_load_command_line - Load command line to MIC.
+ * @mdev: pointer to mic_device instance
+ * @fw: the firmware image
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+static int
+mic_x100_load_command_line(struct mic_device *mdev, const struct firmware *fw)
+{
+	u32 len = 0;
+	u32 boot_mem;
+	char *buf;
+	void __iomem *cmd_line_va = mdev->aper.va + mdev->bootaddr + fw->size;
+#define CMDLINE_SIZE 2048
+
+	boot_mem = mdev->aper.len >> 20;
+	buf = kzalloc(CMDLINE_SIZE, GFP_KERNEL);
+	if (!buf) {
+		dev_err(mdev->sdev->parent,
+			"%s %d allocation failed\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+	len += snprintf(buf, CMDLINE_SIZE - len,
+		" mem=%dM", boot_mem);
+	if (mdev->cmdline)
+		snprintf(buf + len, CMDLINE_SIZE - len, " %s", mdev->cmdline);
+	memcpy_toio(cmd_line_va, buf, strlen(buf) + 1);
+	kfree(buf);
+	return 0;
+}
+
+/**
+ * mic_x100_load_ramdisk - Load ramdisk to MIC.
+ * @mdev: pointer to mic_device instance
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+static int
+mic_x100_load_ramdisk(struct mic_device *mdev)
+{
+	const struct firmware *fw;
+	int rc;
+	struct boot_params __iomem *bp = mdev->aper.va + mdev->bootaddr;
+
+	rc = request_firmware(&fw,
+			mdev->ramdisk, mdev->sdev->parent);
+	if (rc < 0) {
+		dev_err(mdev->sdev->parent,
+			"ramdisk request_firmware failed: %d %s\n",
+			rc, mdev->ramdisk);
+		goto error;
+	}
+	/*
+	 * Typically the bootaddr for card OS is 64M
+	 * so copy over the ramdisk @ 128M.
+	 */
+	memcpy_toio(mdev->aper.va + (mdev->bootaddr << 1), fw->data, fw->size);
+	iowrite32(cpu_to_le32(mdev->bootaddr << 1), &bp->hdr.ramdisk_image);
+	iowrite32(cpu_to_le32(fw->size), &bp->hdr.ramdisk_size);
+	release_firmware(fw);
+error:
+	return rc;
+}
+
+/**
+ * mic_x100_get_boot_addr - Get MIC boot address.
+ * @mdev: pointer to mic_device instance
+ *
+ * This function is called during firmware load to determine
+ * the address at which the OS should be downloaded in card
+ * memory i.e. GDDR.
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+static int
+mic_x100_get_boot_addr(struct mic_device *mdev)
+{
+	u32 scratch2, boot_addr;
+	int rc = 0;
+
+	scratch2 = mdev->ops->read_spad(mdev, MIC_X100_DOWNLOAD_INFO);
+	boot_addr = MIC_X100_SPAD2_DOWNLOAD_ADDR(scratch2);
+	dev_dbg(mdev->sdev->parent, "%s %d boot_addr 0x%x\n",
+		__func__, __LINE__, boot_addr);
+	if (boot_addr > (1 << 31)) {
+		dev_err(mdev->sdev->parent,
+			"incorrect bootaddr 0x%x\n",
+			boot_addr);
+		rc = -EINVAL;
+		goto error;
+	}
+	mdev->bootaddr = boot_addr;
+error:
+	return rc;
+}
+
+/**
+ * mic_x100_load_firmware - Load firmware to MIC.
+ * @mdev: pointer to mic_device instance
+ * @buf: buffer containing boot string including firmware/ramdisk path.
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+static int
+mic_x100_load_firmware(struct mic_device *mdev, const char *buf)
+{
+	int rc;
+	const struct firmware *fw;
+
+	rc = mic_x100_get_boot_addr(mdev);
+	if (rc)
+		goto error;
+	/* load OS */
+	rc = request_firmware(&fw, mdev->firmware, mdev->sdev->parent);
+	if (rc < 0) {
+		dev_err(mdev->sdev->parent,
+			"ramdisk request_firmware failed: %d %s\n",
+			rc, mdev->firmware);
+		goto error;
+	}
+	if (mdev->bootaddr > mdev->aper.len - fw->size) {
+		rc = -EINVAL;
+		dev_err(mdev->sdev->parent, "%s %d rc %d bootaddr 0x%x\n",
+			__func__, __LINE__, rc, mdev->bootaddr);
+		release_firmware(fw);
+		goto error;
+	}
+	memcpy_toio(mdev->aper.va + mdev->bootaddr, fw->data, fw->size);
+	mdev->ops->write_spad(mdev, MIC_X100_FW_SIZE, fw->size);
+	if (!strcmp(mdev->bootmode, "elf"))
+		goto done;
+	/* load command line */
+	rc = mic_x100_load_command_line(mdev, fw);
+	if (rc) {
+		dev_err(mdev->sdev->parent, "%s %d rc %d\n",
+			__func__, __LINE__, rc);
+		goto error;
+	}
+	release_firmware(fw);
+	/* load ramdisk */
+	if (mdev->ramdisk)
+		rc = mic_x100_load_ramdisk(mdev);
+error:
+	dev_dbg(mdev->sdev->parent, "%s %d rc %d\n", __func__, __LINE__, rc);
+done:
+	return rc;
+}
+
+/**
+ * mic_x100_get_postcode - Get postcode status from firmware.
+ * @mdev: pointer to mic_device instance
+ *
+ * RETURNS: postcode.
+ */
+static u32 mic_x100_get_postcode(struct mic_device *mdev)
+{
+	return mic_mmio_read(&mdev->mmio, MIC_X100_POSTCODE);
+}
+
+/**
+ * mic_x100_smpt_set - Update an SMPT entry with a DMA address.
+ * @mdev: pointer to mic_device instance
+ *
+ * RETURNS: none.
+ */
+static void
+mic_x100_smpt_set(struct mic_device *mdev, dma_addr_t dma_addr, u8 index)
+{
+#define SNOOP_ON	(0 << 0)
+#define SNOOP_OFF	(1 << 0)
+/*
+ * Sbox Smpt Reg Bits:
+ * Bits	31:2	Host address
+ * Bits	1	RSVD
+ * Bits	0	No snoop
+ */
+#define BUILD_SMPT(NO_SNOOP, HOST_ADDR)  \
+	(u32)(((HOST_ADDR) << 2) | ((NO_SNOOP) & 0x01))
+
+	uint32_t smpt_reg_val = BUILD_SMPT(SNOOP_ON,
+			dma_addr >> mdev->smpt->info.page_shift);
+	mic_mmio_write(&mdev->mmio, smpt_reg_val,
+		       MIC_X100_SBOX_BASE_ADDRESS +
+		       MIC_X100_SBOX_SMPT00 + (4 * index));
+}
+
+/**
+ * mic_x100_smpt_hw_init - Initialize SMPT X100 specific fields.
+ * @mdev: pointer to mic_device instance
+ *
+ * RETURNS: none.
+ */
+static void mic_x100_smpt_hw_init(struct mic_device *mdev)
+{
+	struct mic_smpt_hw_info *info = &mdev->smpt->info;
+
+	info->num_reg = 32;
+	info->page_shift = 34;
+	info->page_size = (1ULL << info->page_shift);
+	info->base = 0x8000000000ULL;
+}
+
+struct mic_smpt_ops mic_x100_smpt_ops = {
+	.init = mic_x100_smpt_hw_init,
+	.set = mic_x100_smpt_set,
+};
+
+struct mic_hw_ops mic_x100_ops = {
+	.aper_bar = MIC_X100_APER_BAR,
+	.mmio_bar = MIC_X100_MMIO_BAR,
+	.read_spad = mic_x100_read_spad,
+	.write_spad = mic_x100_write_spad,
+	.send_intr = mic_x100_send_intr,
+	.ack_interrupt = mic_x100_ack_interrupt,
+	.reset = mic_x100_hw_reset,
+	.reset_fw_ready = mic_x100_reset_fw_ready,
+	.is_fw_ready = mic_x100_is_fw_ready,
+	.send_firmware_intr = mic_x100_send_firmware_intr,
+	.load_mic_fw = mic_x100_load_firmware,
+	.get_postcode = mic_x100_get_postcode,
+};
+
+struct mic_hw_intr_ops mic_x100_intr_ops = {
+	.intr_init = mic_x100_hw_intr_init,
+	.enable_interrupts = mic_x100_enable_interrupts,
+	.disable_interrupts = mic_x100_disable_interrupts,
+	.program_msi_to_src_map = mic_x100_program_msi_to_src_map,
+	.read_msi_to_src_map = mic_x100_read_msi_to_src_map,
+};
diff --git a/drivers/misc/mic/host/mic_x100.h b/drivers/misc/mic/host/mic_x100.h
new file mode 100644
index 0000000..8b7daa1
--- /dev/null
+++ b/drivers/misc/mic/host/mic_x100.h
@@ -0,0 +1,98 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#ifndef _MIC_X100_HW_H_
+#define _MIC_X100_HW_H_
+
+#define MIC_X100_PCI_DEVICE_2250 0x2250
+#define MIC_X100_PCI_DEVICE_2251 0x2251
+#define MIC_X100_PCI_DEVICE_2252 0x2252
+#define MIC_X100_PCI_DEVICE_2253 0x2253
+#define MIC_X100_PCI_DEVICE_2254 0x2254
+#define MIC_X100_PCI_DEVICE_2255 0x2255
+#define MIC_X100_PCI_DEVICE_2256 0x2256
+#define MIC_X100_PCI_DEVICE_2257 0x2257
+#define MIC_X100_PCI_DEVICE_2258 0x2258
+#define MIC_X100_PCI_DEVICE_2259 0x2259
+#define MIC_X100_PCI_DEVICE_225a 0x225a
+#define MIC_X100_PCI_DEVICE_225b 0x225b
+#define MIC_X100_PCI_DEVICE_225c 0x225c
+#define MIC_X100_PCI_DEVICE_225d 0x225d
+#define MIC_X100_PCI_DEVICE_225e 0x225e
+
+#define MIC_X100_APER_BAR 0
+#define MIC_X100_MMIO_BAR 4
+
+#define MIC_X100_SBOX_BASE_ADDRESS 0x00010000
+#define MIC_X100_SBOX_SPAD0 0x0000AB20
+#define MIC_X100_SBOX_SICR0_DBR(x) ((x) & 0xf)
+#define MIC_X100_SBOX_SICR0_DMA(x) (((x) >> 8) & 0xff)
+#define MIC_X100_SBOX_SICE0_DBR(x) ((x) & 0xf)
+#define MIC_X100_SBOX_DBR_BITS(x) ((x) & 0xf)
+#define MIC_X100_SBOX_SICE0_DMA(x) (((x) >> 8) & 0xff)
+#define MIC_X100_SBOX_DMA_BITS(x) (((x) & 0xff) << 8)
+
+#define MIC_X100_SBOX_APICICR0 0x0000A9D0
+#define MIC_X100_SBOX_SICR0 0x00009004
+#define MIC_X100_SBOX_SICE0 0x0000900C
+#define MIC_X100_SBOX_SICC0 0x00009010
+#define MIC_X100_SBOX_SIAC0 0x00009014
+#define MIC_X100_SBOX_MSIXPBACR 0x00009084
+#define MIC_X100_SBOX_MXAR0 0x00009044
+#define MIC_X100_SBOX_SMPT00 0x00003100
+#define MIC_X100_SBOX_RDMASR0 0x0000B180
+
+#define MIC_X100_DOORBELL_IDX_START 0
+#define MIC_X100_NUM_DOORBELL 4
+#define MIC_X100_DMA_IDX_START 8
+#define MIC_X100_NUM_DMA 8
+#define MIC_X100_ERR_IDX_START 30
+#define MIC_X100_NUM_ERR 1
+
+#define MIC_X100_NUM_SBOX_IRQ 8
+#define MIC_X100_NUM_RDMASR_IRQ 8
+#define MIC_X100_RDMASR_IRQ_BASE 17
+#define MIC_X100_SPAD2_DOWNLOAD_STATUS(x) ((x) & 0x1)
+#define MIC_X100_SPAD2_APIC_ID(x)	(((x) >> 1) & 0x1ff)
+#define MIC_X100_SPAD2_DOWNLOAD_ADDR(x) ((x) & 0xfffff000)
+#define MIC_X100_SBOX_APICICR7 0x0000AA08
+#define MIC_X100_SBOX_RGCR 0x00004010
+#define MIC_X100_SBOX_SDBIC0 0x0000CC90
+#define MIC_X100_DOWNLOAD_INFO 2
+#define MIC_X100_FW_SIZE 5
+#define MIC_X100_POSTCODE 0x242c
+
+static const u16 mic_x100_intr_init[] = {
+		MIC_X100_DOORBELL_IDX_START,
+		MIC_X100_DMA_IDX_START,
+		MIC_X100_ERR_IDX_START,
+		MIC_X100_NUM_DOORBELL,
+		MIC_X100_NUM_DMA,
+		MIC_X100_NUM_ERR,
+};
+
+/* Host->Card(bootstrap) Interrupt Vector */
+#define MIC_X100_BSP_INTERRUPT_VECTOR 229
+
+extern struct mic_hw_ops mic_x100_ops;
+extern struct mic_smpt_ops mic_x100_smpt_ops;
+extern struct mic_hw_intr_ops mic_x100_intr_ops;
+
+#endif
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index 68b7c77..3075492 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -395,7 +395,7 @@
 	iowrite32(0, pht->caddr + PHN_IRQCTL);
 	ioread32(pht->caddr + PHN_IRQCTL); /* PCI posting */
 	retval = request_irq(pdev->irq, phantom_isr,
-			IRQF_SHARED | IRQF_DISABLED, "phantom", pht);
+			IRQF_SHARED, "phantom", pht);
 	if (retval) {
 		dev_err(&pdev->dev, "can't establish ISR\n");
 		goto err_unmo;
diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c
index f84ff0c..eda38cb 100644
--- a/drivers/misc/pti.c
+++ b/drivers/misc/pti.c
@@ -892,7 +892,6 @@
 	}
 
 	iounmap(drv_data->pti_ioaddr);
-	pci_set_drvdata(pdev, NULL);
 	kfree(drv_data);
 	pci_release_region(pdev, 1);
 	pci_disable_device(pdev);
diff --git a/drivers/misc/ti_dac7512.c b/drivers/misc/ti_dac7512.c
index 9b23722..83da711 100644
--- a/drivers/misc/ti_dac7512.c
+++ b/drivers/misc/ti_dac7512.c
@@ -22,9 +22,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/spi/spi.h>
-
-#define DAC7512_DRV_NAME	"dac7512"
-#define DRIVER_VERSION		"1.0"
+#include <linux/of.h>
 
 static ssize_t dac7512_store_val(struct device *dev,
 				 struct device_attribute *attr,
@@ -75,13 +73,29 @@
 	return 0;
 }
 
+static const struct spi_device_id dac7512_id_table[] = {
+	{ "dac7512", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, dac7512_id_table);
+
+#ifdef CONFIG_OF
+static const struct of_device_id dac7512_of_match[] = {
+	{ .compatible = "ti,dac7512", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, dac7512_of_match);
+#endif
+
 static struct spi_driver dac7512_driver = {
 	.driver = {
-		.name	= DAC7512_DRV_NAME,
+		.name	= "dac7512",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(dac7512_of_match),
 	},
 	.probe	= dac7512_probe,
 	.remove	= dac7512_remove,
+	.id_table = dac7512_id_table,
 };
 
 module_spi_driver(dac7512_driver);
@@ -89,4 +103,3 @@
 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
 MODULE_DESCRIPTION("DAC7512 16-bit DAC");
 MODULE_LICENSE("GPL v2");
-MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c
index f8d66543..a606c89 100644
--- a/drivers/misc/tifm_7xx1.c
+++ b/drivers/misc/tifm_7xx1.c
@@ -356,8 +356,10 @@
 	pci_set_drvdata(dev, fm);
 
 	fm->addr = pci_ioremap_bar(dev, 0);
-	if (!fm->addr)
+	if (!fm->addr) {
+		rc = -ENODEV;
 		goto err_out_free;
+	}
 
 	rc = request_irq(dev->irq, tifm_7xx1_isr, IRQF_SHARED, DRIVER_NAME, fm);
 	if (rc)
@@ -378,7 +380,6 @@
 err_out_unmap:
 	iounmap(fm->addr);
 err_out_free:
-	pci_set_drvdata(dev, NULL);
 	tifm_free_adapter(fm);
 err_out_int:
 	pci_intx(dev, 0);
@@ -405,8 +406,6 @@
 	for (cnt = 0; cnt < fm->num_sockets; cnt++)
 		tifm_7xx1_sock_power_off(tifm_7xx1_sock_addr(fm->addr, cnt));
 
-	pci_set_drvdata(dev, NULL);
-
 	iounmap(fm->addr);
 	pci_intx(dev, 0);
 	pci_release_regions(dev);
diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c
index 0ab7c92..a511b2a 100644
--- a/drivers/misc/tifm_core.c
+++ b/drivers/misc/tifm_core.c
@@ -145,15 +145,17 @@
 	struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev);
 	return sprintf(buf, "%x", sock->type);
 }
+static DEVICE_ATTR_RO(type);
 
-static struct device_attribute tifm_dev_attrs[] = {
-	__ATTR(type, S_IRUGO, type_show, NULL),
-	__ATTR_NULL
+static struct attribute *tifm_dev_attrs[] = {
+	&dev_attr_type.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(tifm_dev);
 
 static struct bus_type tifm_bus_type = {
 	.name      = "tifm",
-	.dev_attrs = tifm_dev_attrs,
+	.dev_groups = tifm_dev_groups,
 	.match     = tifm_bus_match,
 	.uevent    = tifm_uevent,
 	.probe     = tifm_device_probe,
diff --git a/drivers/misc/vmw_vmci/vmci_guest.c b/drivers/misc/vmw_vmci/vmci_guest.c
index b3a2b76..c98b03b 100644
--- a/drivers/misc/vmw_vmci/vmci_guest.c
+++ b/drivers/misc/vmw_vmci/vmci_guest.c
@@ -649,7 +649,7 @@
 	return 0;
 
 err_free_irq:
-	free_irq(vmci_dev->irq, &vmci_dev);
+	free_irq(vmci_dev->irq, vmci_dev);
 	tasklet_kill(&vmci_dev->datagram_tasklet);
 	tasklet_kill(&vmci_dev->bm_tasklet);
 
diff --git a/drivers/misc/vmw_vmci/vmci_host.c b/drivers/misc/vmw_vmci/vmci_host.c
index d4722b3..1723a6e 100644
--- a/drivers/misc/vmw_vmci/vmci_host.c
+++ b/drivers/misc/vmw_vmci/vmci_host.c
@@ -243,11 +243,7 @@
 	/*
 	 * Lock physical page backing a given user VA.
 	 */
-	down_read(&current->mm->mmap_sem);
-	retval = get_user_pages(current, current->mm,
-				PAGE_ALIGN(uva),
-				1, 1, 0, &page, NULL);
-	up_read(&current->mm->mmap_sem);
+	retval = get_user_pages_fast(PAGE_ALIGN(uva), 1, 1, &page);
 	if (retval != 1)
 		return VMCI_ERROR_GENERIC;
 
diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.c b/drivers/misc/vmw_vmci/vmci_queue_pair.c
index a0515a6..1b7b303 100644
--- a/drivers/misc/vmw_vmci/vmci_queue_pair.c
+++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c
@@ -732,13 +732,9 @@
 	int retval;
 	int err = VMCI_SUCCESS;
 
-	down_write(&current->mm->mmap_sem);
-	retval = get_user_pages(current,
-				current->mm,
-				(uintptr_t) produce_uva,
-				produce_q->kernel_if->num_pages,
-				1, 0,
-				produce_q->kernel_if->u.h.header_page, NULL);
+	retval = get_user_pages_fast((uintptr_t) produce_uva,
+				     produce_q->kernel_if->num_pages, 1,
+				     produce_q->kernel_if->u.h.header_page);
 	if (retval < produce_q->kernel_if->num_pages) {
 		pr_warn("get_user_pages(produce) failed (retval=%d)", retval);
 		qp_release_pages(produce_q->kernel_if->u.h.header_page,
@@ -747,12 +743,9 @@
 		goto out;
 	}
 
-	retval = get_user_pages(current,
-				current->mm,
-				(uintptr_t) consume_uva,
-				consume_q->kernel_if->num_pages,
-				1, 0,
-				consume_q->kernel_if->u.h.header_page, NULL);
+	retval = get_user_pages_fast((uintptr_t) consume_uva,
+				     consume_q->kernel_if->num_pages, 1,
+				     consume_q->kernel_if->u.h.header_page);
 	if (retval < consume_q->kernel_if->num_pages) {
 		pr_warn("get_user_pages(consume) failed (retval=%d)", retval);
 		qp_release_pages(consume_q->kernel_if->u.h.header_page,
@@ -763,8 +756,6 @@
 	}
 
  out:
-	up_write(&current->mm->mmap_sem);
-
 	return err;
 }
 
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 704bf66..3e227bd 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -27,7 +27,7 @@
 
 #define to_mmc_driver(d)	container_of(d, struct mmc_driver, drv)
 
-static ssize_t mmc_type_show(struct device *dev,
+static ssize_t type_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
 	struct mmc_card *card = mmc_dev_to_card(dev);
@@ -45,11 +45,13 @@
 		return -EFAULT;
 	}
 }
+static DEVICE_ATTR_RO(type);
 
-static struct device_attribute mmc_dev_attrs[] = {
-	__ATTR(type, S_IRUGO, mmc_type_show, NULL),
-	__ATTR_NULL,
+static struct attribute *mmc_dev_attrs[] = {
+	&dev_attr_type.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(mmc_dev);
 
 /*
  * This currently matches any MMC driver to any MMC card - drivers
@@ -218,7 +220,7 @@
 
 static struct bus_type mmc_bus_type = {
 	.name		= "mmc",
-	.dev_attrs	= mmc_dev_attrs,
+	.dev_groups	= mmc_dev_groups,
 	.match		= mmc_bus_match,
 	.uevent		= mmc_bus_uevent,
 	.probe		= mmc_bus_probe,
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index 6d67492..ef89565 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -34,7 +34,8 @@
 									\
 	func = dev_to_sdio_func (dev);					\
 	return sprintf (buf, format_string, func->field);		\
-}
+}									\
+static DEVICE_ATTR_RO(field)
 
 sdio_config_attr(class, "0x%02x\n");
 sdio_config_attr(vendor, "0x%04x\n");
@@ -47,14 +48,16 @@
 	return sprintf(buf, "sdio:c%02Xv%04Xd%04X\n",
 			func->class, func->vendor, func->device);
 }
+static DEVICE_ATTR_RO(modalias);
 
-static struct device_attribute sdio_dev_attrs[] = {
-	__ATTR_RO(class),
-	__ATTR_RO(vendor),
-	__ATTR_RO(device),
-	__ATTR_RO(modalias),
-	__ATTR_NULL,
+static struct attribute *sdio_dev_attrs[] = {
+	&dev_attr_class.attr,
+	&dev_attr_vendor.attr,
+	&dev_attr_device.attr,
+	&dev_attr_modalias.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(sdio_dev);
 
 static const struct sdio_device_id *sdio_match_one(struct sdio_func *func,
 	const struct sdio_device_id *id)
@@ -225,7 +228,7 @@
 
 static struct bus_type sdio_bus_type = {
 	.name		= "sdio",
-	.dev_attrs	= sdio_dev_attrs,
+	.dev_groups	= sdio_dev_groups,
 	.match		= sdio_bus_match,
 	.uevent		= sdio_bus_uevent,
 	.probe		= sdio_bus_probe,
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index 06c5b0b..deecee0 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -655,7 +655,7 @@
 	.enable_sdio_irq	= mvsd_enable_sdio_irq,
 };
 
-static void __init
+static void
 mv_conf_mbus_windows(struct mvsd_host *host,
 		     const struct mbus_dram_target_info *dram)
 {
@@ -677,7 +677,7 @@
 	}
 }
 
-static int __init mvsd_probe(struct platform_device *pdev)
+static int mvsd_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct mmc_host *mmc = NULL;
@@ -819,7 +819,7 @@
 	return ret;
 }
 
-static int __exit mvsd_remove(struct platform_device *pdev)
+static int mvsd_remove(struct platform_device *pdev)
 {
 	struct mmc_host *mmc = platform_get_drvdata(pdev);
 
@@ -872,7 +872,8 @@
 MODULE_DEVICE_TABLE(of, mvsdio_dt_ids);
 
 static struct platform_driver mvsd_driver = {
-	.remove		= __exit_p(mvsd_remove),
+	.probe		= mvsd_probe,
+	.remove		= mvsd_remove,
 	.suspend	= mvsd_suspend,
 	.resume		= mvsd_resume,
 	.driver		= {
@@ -881,7 +882,7 @@
 	},
 };
 
-module_platform_driver_probe(mvsd_driver, mvsd_probe);
+module_platform_driver(mvsd_driver);
 
 /* maximum card clock frequency (default 50MHz) */
 module_param(maxfreq, int, 0);
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 26b14f9..6bc9618 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -168,12 +168,25 @@
  */
 static inline int set_4byte(struct m25p *flash, u32 jedec_id, int enable)
 {
+	int status;
+	bool need_wren = false;
+
 	switch (JEDEC_MFR(jedec_id)) {
-	case CFI_MFR_MACRONIX:
 	case CFI_MFR_ST: /* Micron, actually */
+		/* Some Micron need WREN command; all will accept it */
+		need_wren = true;
+	case CFI_MFR_MACRONIX:
 	case 0xEF /* winbond */:
+		if (need_wren)
+			write_enable(flash);
+
 		flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B;
-		return spi_write(flash->spi, flash->command, 1);
+		status = spi_write(flash->spi, flash->command, 1);
+
+		if (need_wren)
+			write_disable(flash);
+
+		return status;
 	default:
 		/* Spansion style */
 		flash->command[0] = OPCODE_BRWR;
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 060feea..bd1ce7d 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -1139,7 +1139,7 @@
 	return 0;
 }
 
-static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev,
+static int atmel_pmecc_nand_init_params(struct platform_device *pdev,
 					 struct atmel_nand_host *host)
 {
 	struct mtd_info *mtd = &host->mtd;
@@ -1548,7 +1548,7 @@
 }
 #endif
 
-static int __init atmel_hw_nand_init_params(struct platform_device *pdev,
+static int atmel_hw_nand_init_params(struct platform_device *pdev,
 					 struct atmel_nand_host *host)
 {
 	struct mtd_info *mtd = &host->mtd;
@@ -1987,7 +1987,7 @@
 /*
  * Probe for the NAND device.
  */
-static int __init atmel_nand_probe(struct platform_device *pdev)
+static int atmel_nand_probe(struct platform_device *pdev)
 {
 	struct atmel_nand_host *host;
 	struct mtd_info *mtd;
@@ -2184,7 +2184,7 @@
 /*
  * Remove a NAND device.
  */
-static int __exit atmel_nand_remove(struct platform_device *pdev)
+static int atmel_nand_remove(struct platform_device *pdev)
 {
 	struct atmel_nand_host *host = platform_get_drvdata(pdev);
 	struct mtd_info *mtd = &host->mtd;
@@ -2270,7 +2270,8 @@
 };
 
 static struct platform_driver atmel_nand_driver = {
-	.remove		= __exit_p(atmel_nand_remove),
+	.probe		= atmel_nand_probe,
+	.remove		= atmel_nand_remove,
 	.driver		= {
 		.name	= "atmel_nand",
 		.owner	= THIS_MODULE,
@@ -2278,7 +2279,7 @@
 	},
 };
 
-module_platform_driver_probe(atmel_nand_driver, atmel_nand_probe);
+module_platform_driver(atmel_nand_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Rick Bronson");
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 2065720..e59c886 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -28,6 +28,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
index 317a771..2730c78 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -24,6 +24,7 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 04e0725..4d203e8 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -18,6 +18,7 @@
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/mtd.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
 #include <linux/io.h>
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index 59ab069..a9830ff 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -349,7 +349,7 @@
 
 int common_nfc_set_geometry(struct gpmi_nand_data *this)
 {
-	return set_geometry_by_ecc_info(this) ? 0 : legacy_set_geometry(this);
+	return legacy_set_geometry(this);
 }
 
 struct dma_chan *get_dma_chan(struct gpmi_nand_data *this)
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 3c60a00..439bc38 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -36,7 +36,9 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
 #include <asm/mpc5121.h>
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 7ed4841..d340b2f 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2869,10 +2869,8 @@
 
 	len = le16_to_cpu(p->ext_param_page_length) * 16;
 	ep = kmalloc(len, GFP_KERNEL);
-	if (!ep) {
-		ret = -ENOMEM;
-		goto ext_out;
-	}
+	if (!ep)
+		return -ENOMEM;
 
 	/* Send our own NAND_CMD_PARAM. */
 	chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
@@ -2920,7 +2918,7 @@
 	}
 
 	pr_info("ONFI extended param page detected.\n");
-	return 0;
+	ret = 0;
 
 ext_out:
 	kfree(ep);
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 8e148f1..69eaba6 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -30,6 +30,7 @@
 #include <linux/mtd/ndfc.h>
 #include <linux/slab.h>
 #include <linux/mtd/mtd.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <asm/io.h>
 
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c
index 5a67082..4d17436 100644
--- a/drivers/mtd/nand/pasemi_nand.c
+++ b/drivers/mtd/nand/pasemi_nand.c
@@ -28,6 +28,8 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand_ecc.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/pci.h>
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index dd03dfd..c28d4e2 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1320,7 +1320,12 @@
 	for (cs = 0; cs < pdata->num_cs; cs++) {
 		struct mtd_info *mtd = info->host[cs]->mtd;
 
-		mtd->name = pdev->name;
+		/*
+		 * The mtd name matches the one used in 'mtdparts' kernel
+		 * parameter. This name cannot be changed or otherwise
+		 * user's mtd partitions configuration would get broken.
+		 */
+		mtd->name = "pxa3xx_nand-0";
 		info->cs = cs;
 		ret = pxa3xx_nand_scan(mtd);
 		if (ret) {
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
index 09dde7d..49bd9155 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/socrates_nand.c
@@ -15,6 +15,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/io.h>
 
diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index c071d41..33bb1f2 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -900,10 +900,9 @@
 		 * number.
 		 */
 		image_seq = be32_to_cpu(ech->image_seq);
-		if (!ubi->image_seq && image_seq)
+		if (!ubi->image_seq)
 			ubi->image_seq = image_seq;
-		if (ubi->image_seq && image_seq &&
-		    ubi->image_seq != image_seq) {
+		if (image_seq && ubi->image_seq != image_seq) {
 			ubi_err("bad image sequence number %d in PEB %d, expected %d",
 				image_seq, pnum, ubi->image_seq);
 			ubi_dump_ec_hdr(ech);
@@ -1417,9 +1416,11 @@
 				ai = alloc_ai("ubi_aeb_slab_cache2");
 				if (!ai)
 					return -ENOMEM;
-			}
 
-			err = scan_all(ubi, ai, UBI_FM_MAX_START);
+				err = scan_all(ubi, ai, 0);
+			} else {
+				err = scan_all(ubi, ai, UBI_FM_MAX_START);
+			}
 		}
 	}
 #else
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index f5aa4b0..ead8613 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -407,6 +407,7 @@
 	 */
 	for (i = 0; i < pool_size; i++) {
 		int scrub = 0;
+		int image_seq;
 
 		pnum = be32_to_cpu(pebs[i]);
 
@@ -425,10 +426,16 @@
 		} else if (ret == UBI_IO_BITFLIPS)
 			scrub = 1;
 
-		if (be32_to_cpu(ech->image_seq) != ubi->image_seq) {
+		/*
+		 * Older UBI implementations have image_seq set to zero, so
+		 * we shouldn't fail if image_seq == 0.
+		 */
+		image_seq = be32_to_cpu(ech->image_seq);
+
+		if (image_seq && (image_seq != ubi->image_seq)) {
 			ubi_err("bad image seq: 0x%x, expected: 0x%x",
 				be32_to_cpu(ech->image_seq), ubi->image_seq);
-			err = UBI_BAD_FASTMAP;
+			ret = UBI_BAD_FASTMAP;
 			goto out;
 		}
 
@@ -819,6 +826,10 @@
 	list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list)
 		list_move_tail(&tmp_aeb->u.list, &ai->free);
 
+	ubi_assert(list_empty(&used));
+	ubi_assert(list_empty(&eba_orphans));
+	ubi_assert(list_empty(&free));
+
 	/*
 	 * If fastmap is leaking PEBs (must not happen), raise a
 	 * fat warning and fall back to scanning mode.
@@ -834,6 +845,19 @@
 fail_bad:
 	ret = UBI_BAD_FASTMAP;
 fail:
+	list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &used, u.list) {
+		kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
+		list_del(&tmp_aeb->u.list);
+	}
+	list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &eba_orphans, u.list) {
+		kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
+		list_del(&tmp_aeb->u.list);
+	}
+	list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) {
+		kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
+		list_del(&tmp_aeb->u.list);
+	}
+
 	return ret;
 }
 
@@ -923,6 +947,8 @@
 	}
 
 	for (i = 0; i < used_blocks; i++) {
+		int image_seq;
+
 		pnum = be32_to_cpu(fmsb->block_loc[i]);
 
 		if (ubi_io_is_bad(ubi, pnum)) {
@@ -940,10 +966,17 @@
 		} else if (ret == UBI_IO_BITFLIPS)
 			fm->to_be_tortured[i] = 1;
 
+		image_seq = be32_to_cpu(ech->image_seq);
 		if (!ubi->image_seq)
-			ubi->image_seq = be32_to_cpu(ech->image_seq);
+			ubi->image_seq = image_seq;
 
-		if (be32_to_cpu(ech->image_seq) != ubi->image_seq) {
+		/*
+		 * Older UBI implementations have image_seq set to zero, so
+		 * we shouldn't fail if image_seq == 0.
+		 */
+		if (image_seq && (image_seq != ubi->image_seq)) {
+			ubi_err("wrong image seq:%d instead of %d",
+				be32_to_cpu(ech->image_seq), ubi->image_seq);
 			ret = UBI_BAD_FASTMAP;
 			goto free_hdr;
 		}
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index c95bfb1..02317c1 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -599,10 +599,6 @@
 	return_unused_pool_pebs(ubi, pool);
 
 	for (pool->size = 0; pool->size < pool->max_size; pool->size++) {
-		if (!ubi->free.rb_node ||
-		   (ubi->free_count - ubi->beb_rsvd_pebs < 1))
-			break;
-
 		pool->pebs[pool->size] = __wl_get_peb(ubi);
 		if (pool->pebs[pool->size] < 0)
 			break;
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index 3a8c753..a7271e0 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -102,8 +102,7 @@
 #ifdef CONFIG_WD80x3
 	{wd_probe, 0},
 #endif
-#if defined(CONFIG_NE2000) || \
-    defined(CONFIG_NE_H8300)  /* ISA (use ne2k-pci for PCI cards) */
+#if defined(CONFIG_NE2000) /* ISA (use ne2k-pci for PCI cards) */
 	{ne_probe, 0},
 #endif
 #ifdef CONFIG_LANCE		/* ISA/VLB (use pcnet32 for PCI cards) */
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index c29b836..ec9b646 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -149,14 +149,6 @@
 	return -EPERM;
 }
 
-static const void *bonding_namespace(struct class *cls,
-				     const struct class_attribute *attr)
-{
-	const struct bond_net *bn =
-		container_of(attr, struct bond_net, class_attr_bonding_masters);
-	return bn->net;
-}
-
 /* class attribute for bond_masters file.  This ends up in /sys/class/net */
 static const struct class_attribute class_attr_bonding_masters = {
 	.attr = {
@@ -165,7 +157,6 @@
 	},
 	.show = bonding_show_bonds,
 	.store = bonding_store_bonds,
-	.namespace = bonding_namespace,
 };
 
 int bond_create_slave_symlinks(struct net_device *master,
@@ -1787,7 +1778,8 @@
 	bn->class_attr_bonding_masters = class_attr_bonding_masters;
 	sysfs_attr_init(&bn->class_attr_bonding_masters.attr);
 
-	ret = netdev_class_create_file(&bn->class_attr_bonding_masters);
+	ret = netdev_class_create_file_ns(&bn->class_attr_bonding_masters,
+					  bn->net);
 	/*
 	 * Permit multiple loads of the module by ignoring failures to
 	 * create the bonding_masters sysfs file.  Bonding devices
@@ -1817,7 +1809,7 @@
  */
 void bond_destroy_sysfs(struct bond_net *bn)
 {
-	netdev_class_remove_file(&bn->class_attr_bonding_masters);
+	netdev_class_remove_file_ns(&bn->class_attr_bonding_masters, bn->net);
 }
 
 /*
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 3b1ff61..693d8ff 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -1405,10 +1405,10 @@
 
 static const struct platform_device_id at91_can_id_table[] = {
 	{
-		.name = "at91_can",
+		.name = "at91sam9x5_can",
 		.driver_data = (kernel_ulong_t)&at91_at91sam9x5_data,
 	}, {
-		.name = "at91sam9x5_can",
+		.name = "at91_can",
 		.driver_data = (kernel_ulong_t)&at91_at91sam9263_data,
 	}, {
 		/* sentinel */
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index a668cd4..e3fc07c 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -814,9 +814,6 @@
 			msg_ctrl_save = priv->read_reg(priv,
 					C_CAN_IFACE(MSGCTRL_REG, 0));
 
-			if (msg_ctrl_save & IF_MCONT_EOB)
-				return num_rx_pkts;
-
 			if (msg_ctrl_save & IF_MCONT_MSGLST) {
 				c_can_handle_lost_msg_obj(dev, 0, msg_obj);
 				num_rx_pkts++;
@@ -824,6 +821,9 @@
 				continue;
 			}
 
+			if (msg_ctrl_save & IF_MCONT_EOB)
+				return num_rx_pkts;
+
 			if (!(msg_ctrl_save & IF_MCONT_NEWDAT))
 				continue;
 
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index f9cba41..1870c47 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -705,14 +705,14 @@
 	size_t size;
 
 	size = nla_total_size(sizeof(u32));   /* IFLA_CAN_STATE */
-	size += sizeof(struct can_ctrlmode);  /* IFLA_CAN_CTRLMODE */
+	size += nla_total_size(sizeof(struct can_ctrlmode));  /* IFLA_CAN_CTRLMODE */
 	size += nla_total_size(sizeof(u32));  /* IFLA_CAN_RESTART_MS */
-	size += sizeof(struct can_bittiming); /* IFLA_CAN_BITTIMING */
-	size += sizeof(struct can_clock);     /* IFLA_CAN_CLOCK */
+	size += nla_total_size(sizeof(struct can_bittiming)); /* IFLA_CAN_BITTIMING */
+	size += nla_total_size(sizeof(struct can_clock));     /* IFLA_CAN_CLOCK */
 	if (priv->do_get_berr_counter)        /* IFLA_CAN_BERR_COUNTER */
-		size += sizeof(struct can_berr_counter);
+		size += nla_total_size(sizeof(struct can_berr_counter));
 	if (priv->bittiming_const)	      /* IFLA_CAN_BITTIMING_CONST */
-		size += sizeof(struct can_bittiming_const);
+		size += nla_total_size(sizeof(struct can_bittiming_const));
 
 	return size;
 }
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 3f21142..8f5ce74 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -62,7 +62,7 @@
 #define FLEXCAN_MCR_BCC			BIT(16)
 #define FLEXCAN_MCR_LPRIO_EN		BIT(13)
 #define FLEXCAN_MCR_AEN			BIT(12)
-#define FLEXCAN_MCR_MAXMB(x)		((x) & 0xf)
+#define FLEXCAN_MCR_MAXMB(x)		((x) & 0x1f)
 #define FLEXCAN_MCR_IDAM_A		(0 << 8)
 #define FLEXCAN_MCR_IDAM_B		(1 << 8)
 #define FLEXCAN_MCR_IDAM_C		(2 << 8)
@@ -735,9 +735,11 @@
 	 *
 	 */
 	reg_mcr = flexcan_read(&regs->mcr);
+	reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff);
 	reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |
 		FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN |
-		FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS;
+		FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS |
+		FLEXCAN_MCR_MAXMB(FLEXCAN_TX_BUF_ID);
 	netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr);
 	flexcan_write(reg_mcr, &regs->mcr);
 
@@ -771,6 +773,10 @@
 	netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl);
 	flexcan_write(reg_ctrl, &regs->ctrl);
 
+	/* Abort any pending TX, mark Mailbox as INACTIVE */
+	flexcan_write(FLEXCAN_MB_CNT_CODE(0x4),
+		      &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
+
 	/* acceptance mask/acceptance code (accept everything) */
 	flexcan_write(0x0, &regs->rxgmask);
 	flexcan_write(0x0, &regs->rx14mask);
@@ -979,9 +985,9 @@
 }
 
 static const struct of_device_id flexcan_of_match[] = {
-	{ .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, },
-	{ .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },
 	{ .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
+	{ .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },
+	{ .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, },
 	{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, flexcan_of_match);
diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c
index 6aa737a..ab506d6 100644
--- a/drivers/net/can/grcan.c
+++ b/drivers/net/can/grcan.c
@@ -34,10 +34,7 @@
 #include <linux/io.h>
 #include <linux/can/dev.h>
 #include <linux/spinlock.h>
-
 #include <linux/of_platform.h>
-#include <asm/prom.h>
-
 #include <linux/of_irq.h>
 
 #include <linux/dma-mapping.h>
diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c
index 31ad339..047accd 100644
--- a/drivers/net/can/sja1000/sja1000_of_platform.c
+++ b/drivers/net/can/sja1000/sja1000_of_platform.c
@@ -44,7 +44,6 @@
 #include <linux/of_platform.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
-#include <asm/prom.h>
 
 #include "sja1000.h"
 
diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c
index 3b95465..4b2d5ed 100644
--- a/drivers/net/can/usb/kvaser_usb.c
+++ b/drivers/net/can/usb/kvaser_usb.c
@@ -1544,9 +1544,9 @@
 	return 0;
 }
 
-static void kvaser_usb_get_endpoints(const struct usb_interface *intf,
-				     struct usb_endpoint_descriptor **in,
-				     struct usb_endpoint_descriptor **out)
+static int kvaser_usb_get_endpoints(const struct usb_interface *intf,
+				    struct usb_endpoint_descriptor **in,
+				    struct usb_endpoint_descriptor **out)
 {
 	const struct usb_host_interface *iface_desc;
 	struct usb_endpoint_descriptor *endpoint;
@@ -1557,12 +1557,18 @@
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
 		endpoint = &iface_desc->endpoint[i].desc;
 
-		if (usb_endpoint_is_bulk_in(endpoint))
+		if (!*in && usb_endpoint_is_bulk_in(endpoint))
 			*in = endpoint;
 
-		if (usb_endpoint_is_bulk_out(endpoint))
+		if (!*out && usb_endpoint_is_bulk_out(endpoint))
 			*out = endpoint;
+
+		/* use first bulk endpoint for in and out */
+		if (*in && *out)
+			return 0;
 	}
+
+	return -ENODEV;
 }
 
 static int kvaser_usb_probe(struct usb_interface *intf,
@@ -1576,8 +1582,8 @@
 	if (!dev)
 		return -ENOMEM;
 
-	kvaser_usb_get_endpoints(intf, &dev->bulk_in, &dev->bulk_out);
-	if (!dev->bulk_in || !dev->bulk_out) {
+	err = kvaser_usb_get_endpoints(intf, &dev->bulk_in, &dev->bulk_out);
+	if (err) {
 		dev_err(&intf->dev, "Cannot get usb endpoint(s)");
 		return err;
 	}
diff --git a/drivers/net/ethernet/8390/Kconfig b/drivers/net/ethernet/8390/Kconfig
index becef25..0988811 100644
--- a/drivers/net/ethernet/8390/Kconfig
+++ b/drivers/net/ethernet/8390/Kconfig
@@ -146,13 +146,6 @@
 	  To compile this driver as a module, choose M here: the module will be
 	  called pcnet_cs.  If unsure, say N.
 
-config NE_H8300
-	tristate "NE2000 compatible support for H8/300"
-	depends on H8300H_AKI3068NET || H8300H_H8MAX
-	---help---
-	  Say Y here if you want to use the NE2000 compatible
-	  controller on the Renesas H8/300 processor.
-
 config STNIC
 	tristate "National DP83902AV  support"
 	depends on SUPERH
diff --git a/drivers/net/ethernet/8390/Makefile b/drivers/net/ethernet/8390/Makefile
index 588954a..ff3b318 100644
--- a/drivers/net/ethernet/8390/Makefile
+++ b/drivers/net/ethernet/8390/Makefile
@@ -10,7 +10,6 @@
 obj-$(CONFIG_MCF8390) += mcf8390.o 8390.o
 obj-$(CONFIG_NE2000) += ne.o 8390p.o
 obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
-obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
 obj-$(CONFIG_PCMCIA_AXNET) += axnet_cs.o 8390.o
 obj-$(CONFIG_PCMCIA_PCNET) += pcnet_cs.o 8390.o
 obj-$(CONFIG_STNIC) += stnic.o 8390.o
diff --git a/drivers/net/ethernet/8390/ne-h8300.c b/drivers/net/ethernet/8390/ne-h8300.c
deleted file mode 100644
index 7fc28f2..0000000
--- a/drivers/net/ethernet/8390/ne-h8300.c
+++ /dev/null
@@ -1,684 +0,0 @@
-/* ne-h8300.c: A NE2000 clone on H8/300 driver for linux. */
-/*
-    original ne.c
-    Written 1992-94 by Donald Becker.
-
-    Copyright 1993 United States Government as represented by the
-    Director, National Security Agency.
-
-    This software may be used and distributed according to the terms
-    of the GNU General Public License, incorporated herein by reference.
-
-    The author may be reached as becker@scyld.com, or C/O
-    Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
-
-    H8/300 modified
-    Yoshinori Sato <ysato@users.sourceforge.jp>
-*/
-
-static const char version1[] =
-"ne-h8300.c:v1.00 2004/04/11 ysato\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/jiffies.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#define EI_SHIFT(x)	(ei_local->reg_offset[x])
-
-#include "8390.h"
-
-#define DRV_NAME "ne-h8300"
-
-/* Some defines that people can play with if so inclined. */
-
-/* Do we perform extra sanity checks on stuff ? */
-/* #define NE_SANITY_CHECK */
-
-/* Do we implement the read before write bugfix ? */
-/* #define NE_RW_BUGFIX */
-
-/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
-/* #define PACKETBUF_MEMSIZE	0x40 */
-
-/* A zero-terminated list of I/O addresses to be probed at boot. */
-
-/* ---- No user-serviceable parts below ---- */
-
-static const char version[] =
-    "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#include "lib8390.c"
-
-#define NE_BASE	 (dev->base_addr)
-#define NE_CMD	 	0x00
-#define NE_DATAPORT	(ei_status.word16?0x20:0x10)	/* NatSemi-defined port window offset. */
-#define NE_RESET	(ei_status.word16?0x3f:0x1f)	/* Issue a read to reset, a write to clear. */
-#define NE_IO_EXTENT	(ei_status.word16?0x40:0x20)
-
-#define NESM_START_PG	0x40	/* First page of TX buffer */
-#define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
-
-static int ne_probe1(struct net_device *dev, int ioaddr);
-
-static int ne_open(struct net_device *dev);
-static int ne_close(struct net_device *dev);
-
-static void ne_reset_8390(struct net_device *dev);
-static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-			  int ring_page);
-static void ne_block_input(struct net_device *dev, int count,
-			  struct sk_buff *skb, int ring_offset);
-static void ne_block_output(struct net_device *dev, const int count,
-		const unsigned char *buf, const int start_page);
-
-
-static u32 reg_offset[16];
-
-static int __init init_reg_offset(struct net_device *dev,unsigned long base_addr)
-{
-	struct ei_device *ei_local = netdev_priv(dev);
-	int i;
-	unsigned char bus_width;
-
-	bus_width = *(volatile unsigned char *)ABWCR;
-	bus_width &= 1 << ((base_addr >> 21) & 7);
-
-	for (i = 0; i < ARRAY_SIZE(reg_offset); i++)
-		if (bus_width == 0)
-			reg_offset[i] = i * 2 + 1;
-		else
-			reg_offset[i] = i;
-
-	ei_local->reg_offset = reg_offset;
-	return 0;
-}
-
-static int __initdata h8300_ne_count = 0;
-#ifdef CONFIG_H8300H_H8MAX
-static unsigned long __initdata h8300_ne_base[] = { 0x800600 };
-static int h8300_ne_irq[] = {EXT_IRQ4};
-#endif
-#ifdef CONFIG_H8300H_AKI3068NET
-static unsigned long __initdata h8300_ne_base[] = { 0x200000 };
-static int h8300_ne_irq[] = {EXT_IRQ5};
-#endif
-
-static inline int init_dev(struct net_device *dev)
-{
-	if (h8300_ne_count < ARRAY_SIZE(h8300_ne_base)) {
-		dev->base_addr = h8300_ne_base[h8300_ne_count];
-		dev->irq       = h8300_ne_irq[h8300_ne_count];
-		h8300_ne_count++;
-		return 0;
-	} else
-		return -ENODEV;
-}
-
-/*  Probe for various non-shared-memory ethercards.
-
-   NEx000-clone boards have a Station Address PROM (SAPROM) in the packet
-   buffer memory space.  NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of
-   the SAPROM, while other supposed NE2000 clones must be detected by their
-   SA prefix.
-
-   Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
-   mode results in doubled values, which can be detected and compensated for.
-
-   The probe is also responsible for initializing the card and filling
-   in the 'dev' and 'ei_status' structures.
-
-   We use the minimum memory size for some ethercard product lines, iff we can't
-   distinguish models.  You can increase the packet buffer size by setting
-   PACKETBUF_MEMSIZE.  Reported Cabletron packet buffer locations are:
-	E1010   starts at 0x100 and ends at 0x2000.
-	E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory")
-	E2010	 starts at 0x100 and ends at 0x4000.
-	E2010-x starts at 0x100 and ends at 0xffff.  */
-
-static int __init do_ne_probe(struct net_device *dev)
-{
-	unsigned int base_addr = dev->base_addr;
-
-	/* First check any supplied i/o locations. User knows best. <cough> */
-	if (base_addr > 0x1ff)	/* Check a single specified location. */
-		return ne_probe1(dev, base_addr);
-	else if (base_addr != 0)	/* Don't probe at all. */
-		return -ENXIO;
-
-	return -ENODEV;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
-	free_irq(dev->irq, dev);
-	release_region(dev->base_addr, NE_IO_EXTENT);
-}
-
-#ifndef MODULE
-struct net_device * __init ne_probe(int unit)
-{
-	struct net_device *dev = ____alloc_ei_netdev(0);
-	int err;
-
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-	if (init_dev(dev))
-		return ERR_PTR(-ENODEV);
-
-	sprintf(dev->name, "eth%d", unit);
-	netdev_boot_setup_check(dev);
-
-	err = init_reg_offset(dev, dev->base_addr);
-	if (err)
-		goto out;
-
-	err = do_ne_probe(dev);
-	if (err)
-		goto out;
-	return dev;
-out:
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-#endif
-
-static const struct net_device_ops ne_netdev_ops = {
-	.ndo_open		= ne_open,
-	.ndo_stop		= ne_close,
-
-	.ndo_start_xmit		= __ei_start_xmit,
-	.ndo_tx_timeout		= __ei_tx_timeout,
-	.ndo_get_stats		= __ei_get_stats,
-	.ndo_set_rx_mode	= __ei_set_multicast_list,
-	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address	= eth_mac_addr,
-	.ndo_change_mtu		= eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= __ei_poll,
-#endif
-};
-
-static int __init ne_probe1(struct net_device *dev, int ioaddr)
-{
-	int i;
-	unsigned char SA_prom[16];
-	int wordlength = 2;
-	const char *name = NULL;
-	int start_page, stop_page;
-	int reg0, ret;
-	static unsigned version_printed;
-	struct ei_device *ei_local = netdev_priv(dev);
-	unsigned char bus_width;
-
-	if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
-		return -EBUSY;
-
-	reg0 = inb_p(ioaddr);
-	if (reg0 == 0xFF) {
-		ret = -ENODEV;
-		goto err_out;
-	}
-
-	/* Do a preliminary verification that we have a 8390. */
-	{
-		int regd;
-		outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
-		regd = inb_p(ioaddr + EI_SHIFT(0x0d));
-		outb_p(0xff, ioaddr + EI_SHIFT(0x0d));
-		outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
-		inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
-		if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
-			outb_p(reg0, ioaddr + EI_SHIFT(0));
-			outb_p(regd, ioaddr + EI_SHIFT(0x0d));	/* Restore the old values. */
-			ret = -ENODEV;
-			goto err_out;
-		}
-	}
-
-	if (ei_debug  &&  version_printed++ == 0)
-		printk(KERN_INFO "%s", version1);
-
-	printk(KERN_INFO "NE*000 ethercard probe at %08x:", ioaddr);
-
-	/* Read the 16 bytes of station address PROM.
-	   We must first initialize registers, similar to NS8390_init(eifdev, 0).
-	   We can't reliably read the SAPROM address without this.
-	   (I learned the hard way!). */
-	{
-		struct {unsigned char value, offset; } program_seq[] =
-		{
-			{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
-			{0x48,	EN0_DCFG},	/* Set byte-wide (0x48) access. */
-			{0x00,	EN0_RCNTLO},	/* Clear the count regs. */
-			{0x00,	EN0_RCNTHI},
-			{0x00,	EN0_IMR},	/* Mask completion irq. */
-			{0xFF,	EN0_ISR},
-			{E8390_RXOFF, EN0_RXCR},	/* 0x20  Set to monitor */
-			{E8390_TXOFF, EN0_TXCR},	/* 0x02  and loopback mode. */
-			{32,	EN0_RCNTLO},
-			{0x00,	EN0_RCNTHI},
-			{0x00,	EN0_RSARLO},	/* DMA starting at 0x0000. */
-			{0x00,	EN0_RSARHI},
-			{E8390_RREAD+E8390_START, E8390_CMD},
-		};
-
-		for (i = 0; i < ARRAY_SIZE(program_seq); i++)
-			outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
-
-	}
-	bus_width = *(volatile unsigned char *)ABWCR;
-	bus_width &= 1 << ((ioaddr >> 21) & 7);
-	ei_status.word16 = (bus_width == 0); /* temporary setting */
-	for(i = 0; i < 16 /*sizeof(SA_prom)*/; i++) {
-		SA_prom[i] = inb_p(ioaddr + NE_DATAPORT);
-		inb_p(ioaddr + NE_DATAPORT); /* dummy read */
-	}
-
-	start_page = NESM_START_PG;
-	stop_page = NESM_STOP_PG;
-
-	if (bus_width)
-		wordlength = 1;
-	else
-		outb_p(0x49, ioaddr + EN0_DCFG);
-
-	/* Set up the rest of the parameters. */
-	name = (wordlength == 2) ? "NE2000" : "NE1000";
-
-	if (! dev->irq) {
-		printk(" failed to detect IRQ line.\n");
-		ret = -EAGAIN;
-		goto err_out;
-	}
-
-	/* Snarf the interrupt now.  There's no point in waiting since we cannot
-	   share and the board will usually be enabled. */
-	ret = request_irq(dev->irq, __ei_interrupt, 0, name, dev);
-	if (ret) {
-		printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
-		goto err_out;
-	}
-
-	dev->base_addr = ioaddr;
-
-	for (i = 0; i < ETH_ALEN; i++)
-		dev->dev_addr[i] = SA_prom[i];
-	printk(" %pM\n", dev->dev_addr);
-
-	printk("%s: %s found at %#x, using IRQ %d.\n",
-		dev->name, name, ioaddr, dev->irq);
-
-	ei_status.name = name;
-	ei_status.tx_start_page = start_page;
-	ei_status.stop_page = stop_page;
-	ei_status.word16 = (wordlength == 2);
-
-	ei_status.rx_start_page = start_page + TX_PAGES;
-#ifdef PACKETBUF_MEMSIZE
-	 /* Allow the packet buffer size to be overridden by know-it-alls. */
-	ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
-#endif
-
-	ei_status.reset_8390 = &ne_reset_8390;
-	ei_status.block_input = &ne_block_input;
-	ei_status.block_output = &ne_block_output;
-	ei_status.get_8390_hdr = &ne_get_8390_hdr;
-	ei_status.priv = 0;
-
-	dev->netdev_ops = &ne_netdev_ops;
-
-	__NS8390_init(dev, 0);
-
-	ret = register_netdev(dev);
-	if (ret)
-		goto out_irq;
-	return 0;
-out_irq:
-	free_irq(dev->irq, dev);
-err_out:
-	release_region(ioaddr, NE_IO_EXTENT);
-	return ret;
-}
-
-static int ne_open(struct net_device *dev)
-{
-	__ei_open(dev);
-	return 0;
-}
-
-static int ne_close(struct net_device *dev)
-{
-	if (ei_debug > 1)
-		printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
-	__ei_close(dev);
-	return 0;
-}
-
-/* Hard reset the card.  This used to pause for the same period that a
-   8390 reset command required, but that shouldn't be necessary. */
-
-static void ne_reset_8390(struct net_device *dev)
-{
-	unsigned long reset_start_time = jiffies;
-	struct ei_device *ei_local = netdev_priv(dev);
-
-	if (ei_debug > 1)
-		printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
-
-	/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
-	outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
-
-	ei_status.txing = 0;
-	ei_status.dmaing = 0;
-
-	/* This check _should_not_ be necessary, omit eventually. */
-	while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
-		if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
-			printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name);
-			break;
-		}
-	outb_p(ENISR_RESET, NE_BASE + EN0_ISR);	/* Ack intr. */
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
-   we don't need to be concerned with ring wrap as the header will be at
-   the start of a page, so we optimize accordingly. */
-
-static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-	struct ei_device *ei_local = netdev_priv(dev);
-	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
-
-	if (ei_status.dmaing)
-	{
-		printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr "
-			"[DMAstat:%d][irqlock:%d].\n",
-			dev->name, ei_status.dmaing, ei_status.irqlock);
-		return;
-	}
-
-	ei_status.dmaing |= 0x01;
-	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, NE_BASE + NE_CMD);
-	outb_p(sizeof(struct e8390_pkt_hdr), NE_BASE + EN0_RCNTLO);
-	outb_p(0, NE_BASE + EN0_RCNTHI);
-	outb_p(0, NE_BASE + EN0_RSARLO);		/* On page boundary */
-	outb_p(ring_page, NE_BASE + EN0_RSARHI);
-	outb_p(E8390_RREAD+E8390_START, NE_BASE + NE_CMD);
-
-	if (ei_status.word16) {
-		int len;
-		unsigned short *p = (unsigned short *)hdr;
-		for (len = sizeof(struct e8390_pkt_hdr)>>1; len > 0; len--)
-			*p++ = inw(NE_BASE + NE_DATAPORT);
-	} else
-		insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
-
-	outb_p(ENISR_RDC, NE_BASE + EN0_ISR);	/* Ack intr. */
-	ei_status.dmaing &= ~0x01;
-
-	le16_to_cpus(&hdr->count);
-}
-
-/* Block input and output, similar to the Crynwr packet driver.  If you
-   are porting to a new ethercard, look at the packet driver source for hints.
-   The NEx000 doesn't share the on-board packet memory -- you have to put
-   the packet out through the "remote DMA" dataport using outb. */
-
-static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
-	struct ei_device *ei_local = netdev_priv(dev);
-#ifdef NE_SANITY_CHECK
-	int xfer_count = count;
-#endif
-	char *buf = skb->data;
-
-	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
-	if (ei_status.dmaing)
-	{
-		printk(KERN_EMERG "%s: DMAing conflict in ne_block_input "
-			"[DMAstat:%d][irqlock:%d].\n",
-			dev->name, ei_status.dmaing, ei_status.irqlock);
-		return;
-	}
-	ei_status.dmaing |= 0x01;
-	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, NE_BASE + NE_CMD);
-	outb_p(count & 0xff, NE_BASE + EN0_RCNTLO);
-	outb_p(count >> 8, NE_BASE + EN0_RCNTHI);
-	outb_p(ring_offset & 0xff, NE_BASE + EN0_RSARLO);
-	outb_p(ring_offset >> 8, NE_BASE + EN0_RSARHI);
-	outb_p(E8390_RREAD+E8390_START, NE_BASE + NE_CMD);
-	if (ei_status.word16)
-	{
-		int len;
-		unsigned short *p = (unsigned short *)buf;
-		for (len = count>>1; len > 0; len--)
-			*p++ = inw(NE_BASE + NE_DATAPORT);
-		if (count & 0x01)
-		{
-			buf[count-1] = inb(NE_BASE + NE_DATAPORT);
-#ifdef NE_SANITY_CHECK
-			xfer_count++;
-#endif
-		}
-	} else {
-		insb(NE_BASE + NE_DATAPORT, buf, count);
-	}
-
-#ifdef NE_SANITY_CHECK
-	/* This was for the ALPHA version only, but enough people have
-	   been encountering problems so it is still here.  If you see
-	   this message you either 1) have a slightly incompatible clone
-	   or 2) have noise/speed problems with your bus. */
-
-	if (ei_debug > 1)
-	{
-		/* DMA termination address check... */
-		int addr, tries = 20;
-		do {
-			/* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
-			   -- it's broken for Rx on some cards! */
-			int high = inb_p(NE_BASE + EN0_RSARHI);
-			int low = inb_p(NE_BASE + EN0_RSARLO);
-			addr = (high << 8) + low;
-			if (((ring_offset + xfer_count) & 0xff) == low)
-				break;
-		} while (--tries > 0);
-	 	if (tries <= 0)
-			printk(KERN_WARNING "%s: RX transfer address mismatch,"
-				"%#4.4x (expected) vs. %#4.4x (actual).\n",
-				dev->name, ring_offset + xfer_count, addr);
-	}
-#endif
-	outb_p(ENISR_RDC, NE_BASE + EN0_ISR);	/* Ack intr. */
-	ei_status.dmaing &= ~0x01;
-}
-
-static void ne_block_output(struct net_device *dev, int count,
-		const unsigned char *buf, const int start_page)
-{
-	struct ei_device *ei_local = netdev_priv(dev);
-	unsigned long dma_start;
-#ifdef NE_SANITY_CHECK
-	int retries = 0;
-#endif
-
-	/* Round the count up for word writes.  Do we need to do this?
-	   What effect will an odd byte count have on the 8390?
-	   I should check someday. */
-
-	if (ei_status.word16 && (count & 0x01))
-		count++;
-
-	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
-	if (ei_status.dmaing)
-	{
-		printk(KERN_EMERG "%s: DMAing conflict in ne_block_output."
-			"[DMAstat:%d][irqlock:%d]\n",
-			dev->name, ei_status.dmaing, ei_status.irqlock);
-		return;
-	}
-	ei_status.dmaing |= 0x01;
-	/* We should already be in page 0, but to be safe... */
-	outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, NE_BASE + NE_CMD);
-
-#ifdef NE_SANITY_CHECK
-retry:
-#endif
-
-#ifdef NE8390_RW_BUGFIX
-	/* Handle the read-before-write bug the same way as the
-	   Crynwr packet driver -- the NatSemi method doesn't work.
-	   Actually this doesn't always work either, but if you have
-	   problems with your NEx000 this is better than nothing! */
-
-	outb_p(0x42, NE_BASE + EN0_RCNTLO);
-	outb_p(0x00, NE_BASE + EN0_RCNTHI);
-	outb_p(0x42, NE_BASE + EN0_RSARLO);
-	outb_p(0x00, NE_BASE + EN0_RSARHI);
-	outb_p(E8390_RREAD+E8390_START, NE_BASE + NE_CMD);
-	/* Make certain that the dummy read has occurred. */
-	udelay(6);
-#endif
-
-	outb_p(ENISR_RDC, NE_BASE + EN0_ISR);
-
-	/* Now the normal output. */
-	outb_p(count & 0xff, NE_BASE + EN0_RCNTLO);
-	outb_p(count >> 8,   NE_BASE + EN0_RCNTHI);
-	outb_p(0x00, NE_BASE + EN0_RSARLO);
-	outb_p(start_page, NE_BASE + EN0_RSARHI);
-
-	outb_p(E8390_RWRITE+E8390_START, NE_BASE + NE_CMD);
-	if (ei_status.word16) {
-		int len;
-		unsigned short *p = (unsigned short *)buf;
-		for (len = count>>1; len > 0; len--)
-			outw(*p++, NE_BASE + NE_DATAPORT);
-	} else {
-		outsb(NE_BASE + NE_DATAPORT, buf, count);
-	}
-
-	dma_start = jiffies;
-
-#ifdef NE_SANITY_CHECK
-	/* This was for the ALPHA version only, but enough people have
-	   been encountering problems so it is still here. */
-
-	if (ei_debug > 1)
-	{
-		/* DMA termination address check... */
-		int addr, tries = 20;
-		do {
-			int high = inb_p(NE_BASE + EN0_RSARHI);
-			int low = inb_p(NE_BASE + EN0_RSARLO);
-			addr = (high << 8) + low;
-			if ((start_page << 8) + count == addr)
-				break;
-		} while (--tries > 0);
-
-		if (tries <= 0)
-		{
-			printk(KERN_WARNING "%s: Tx packet transfer address mismatch,"
-				"%#4.4x (expected) vs. %#4.4x (actual).\n",
-				dev->name, (start_page << 8) + count, addr);
-			if (retries++ == 0)
-				goto retry;
-		}
-	}
-#endif
-
-	while ((inb_p(NE_BASE + EN0_ISR) & ENISR_RDC) == 0)
-		if (time_after(jiffies, dma_start + 2*HZ/100)) {		/* 20ms */
-			printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
-			ne_reset_8390(dev);
-			__NS8390_init(dev,1);
-			break;
-		}
-
-	outb_p(ENISR_RDC, NE_BASE + EN0_ISR);	/* Ack intr. */
-	ei_status.dmaing &= ~0x01;
-}
-
-
-#ifdef MODULE
-#define MAX_NE_CARDS	1	/* Max number of NE cards per module */
-static struct net_device *dev_ne[MAX_NE_CARDS];
-static int io[MAX_NE_CARDS];
-static int irq[MAX_NE_CARDS];
-static int bad[MAX_NE_CARDS];	/* 0xbad = bad sig or no reset ack */
-
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(bad, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O base address(es)");
-MODULE_PARM_DESC(irq, "IRQ number(s)");
-MODULE_DESCRIPTION("H8/300 NE2000 Ethernet driver");
-MODULE_LICENSE("GPL");
-
-/* This is set up so that no ISA autoprobe takes place. We can't guarantee
-that the ne2k probe is the last 8390 based probe to take place (as it
-is at boot) and so the probe will get confused by any other 8390 cards.
-ISA device autoprobes on a running machine are not recommended anyway. */
-
-int init_module(void)
-{
-	int this_dev, found = 0;
-	int err;
-
-	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-		struct net_device *dev = ____alloc_ei_netdev(0);
-		if (!dev)
-			break;
-		if (io[this_dev]) {
-			dev->irq = irq[this_dev];
-			dev->mem_end = bad[this_dev];
-			dev->base_addr = io[this_dev];
-		} else {
-			dev->base_addr = h8300_ne_base[this_dev];
-			dev->irq = h8300_ne_irq[this_dev];
-		}
-		err = init_reg_offset(dev, dev->base_addr);
-		if (!err) {
-			if (do_ne_probe(dev) == 0) {
-				dev_ne[found++] = dev;
-				continue;
-			}
-		}
-		free_netdev(dev);
-		if (found)
-			break;
-		if (io[this_dev] != 0)
-			printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", dev->base_addr);
-		else
-			printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
-		return -ENXIO;
-	}
-	if (found)
-		return 0;
-	return -ENODEV;
-}
-
-void cleanup_module(void)
-{
-	int this_dev;
-
-	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-		struct net_device *dev = dev_ne[this_dev];
-		if (dev) {
-			unregister_netdev(dev);
-			cleanup_card(dev);
-			free_netdev(dev);
-		}
-	}
-}
-#endif /* MODULE */
diff --git a/drivers/net/ethernet/amd/declance.c b/drivers/net/ethernet/amd/declance.c
index 94edc9c..1b89f1a 100644
--- a/drivers/net/ethernet/amd/declance.c
+++ b/drivers/net/ethernet/amd/declance.c
@@ -725,7 +725,6 @@
 {
 	struct net_device *dev = dev_id;
 
-	clear_ioasic_dma_irq(irq);
 	printk(KERN_ERR "%s: DMA error\n", dev->name);
 	return IRQ_HANDLED;
 }
@@ -812,7 +811,7 @@
 	if (lp->dma_irq >= 0) {
 		unsigned long flags;
 
-		if (request_irq(lp->dma_irq, lance_dma_merr_int, 0,
+		if (request_irq(lp->dma_irq, lance_dma_merr_int, IRQF_ONESHOT,
 				"lance error", dev)) {
 			free_irq(dev->irq, dev);
 			printk("%s: Can't get DMA IRQ %d\n", dev->name,
diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c
index 9e16014..d087852 100644
--- a/drivers/net/ethernet/arc/emac_main.c
+++ b/drivers/net/ethernet/arc/emac_main.c
@@ -628,12 +628,12 @@
 
 static int arc_emac_probe(struct platform_device *pdev)
 {
-	struct resource res_regs, res_irq;
+	struct resource res_regs;
 	struct device_node *phy_node;
 	struct arc_emac_priv *priv;
 	struct net_device *ndev;
 	const char *mac_addr;
-	unsigned int id, clock_frequency;
+	unsigned int id, clock_frequency, irq;
 	int err;
 
 	if (!pdev->dev.of_node)
@@ -661,8 +661,8 @@
 	}
 
 	/* Get IRQ from device tree */
-	err = of_irq_to_resource(pdev->dev.of_node, 0, &res_irq);
-	if (!err) {
+	irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+	if (!irq) {
 		dev_err(&pdev->dev, "failed to retrieve <irq> value from device tree\n");
 		return -ENODEV;
 	}
@@ -711,7 +711,7 @@
 		goto out;
 	}
 
-	ndev->irq = res_irq.start;
+	ndev->irq = irq;
 	dev_info(&pdev->dev, "IRQ is %d\n", ndev->irq);
 
 	/* Register interrupt handler for device */
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index 249468f..9e8a3e0 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -244,25 +244,33 @@
 				     struct bgmac_slot_info *slot)
 {
 	struct device *dma_dev = bgmac->core->dma_dev;
+	struct sk_buff *skb;
+	dma_addr_t dma_addr;
 	struct bgmac_rx_header *rx;
 
 	/* Alloc skb */
-	slot->skb = netdev_alloc_skb(bgmac->net_dev, BGMAC_RX_BUF_SIZE);
-	if (!slot->skb)
+	skb = netdev_alloc_skb(bgmac->net_dev, BGMAC_RX_BUF_SIZE);
+	if (!skb)
 		return -ENOMEM;
 
 	/* Poison - if everything goes fine, hardware will overwrite it */
-	rx = (struct bgmac_rx_header *)slot->skb->data;
+	rx = (struct bgmac_rx_header *)skb->data;
 	rx->len = cpu_to_le16(0xdead);
 	rx->flags = cpu_to_le16(0xbeef);
 
 	/* Map skb for the DMA */
-	slot->dma_addr = dma_map_single(dma_dev, slot->skb->data,
-					BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
-	if (dma_mapping_error(dma_dev, slot->dma_addr)) {
+	dma_addr = dma_map_single(dma_dev, skb->data,
+				  BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
+	if (dma_mapping_error(dma_dev, dma_addr)) {
 		bgmac_err(bgmac, "DMA mapping error\n");
+		dev_kfree_skb(skb);
 		return -ENOMEM;
 	}
+
+	/* Update the slot */
+	slot->skb = skb;
+	slot->dma_addr = dma_addr;
+
 	if (slot->dma_addr & 0xC0000000)
 		bgmac_warn(bgmac, "DMA address using 0xC0000000 bit(s), it may need translation trick\n");
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 97b3d32..c5e375d 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1197,8 +1197,9 @@
 /* TM (timers) host DB constants */
 #define TM_ILT_PAGE_SZ_HW	0
 #define TM_ILT_PAGE_SZ		(4096 << TM_ILT_PAGE_SZ_HW) /* 4K */
-/* #define TM_CONN_NUM		(CNIC_STARTING_CID+CNIC_ISCSI_CXT_MAX) */
-#define TM_CONN_NUM		1024
+#define TM_CONN_NUM		(BNX2X_FIRST_VF_CID + \
+				 BNX2X_VF_CIDS + \
+				 CNIC_ISCSI_CID_MAX)
 #define TM_ILT_SZ		(8 * TM_CONN_NUM)
 #define TM_ILT_LINES		DIV_ROUND_UP(TM_ILT_SZ, TM_ILT_PAGE_SZ)
 
@@ -1527,7 +1528,6 @@
 #define PCI_32BIT_FLAG			(1 << 1)
 #define ONE_PORT_FLAG			(1 << 2)
 #define NO_WOL_FLAG			(1 << 3)
-#define USING_DAC_FLAG			(1 << 4)
 #define USING_MSIX_FLAG			(1 << 5)
 #define USING_MSI_FLAG			(1 << 6)
 #define DISABLE_MSI_FLAG		(1 << 7)
@@ -1621,7 +1621,7 @@
 	u16			rx_ticks_int;
 	u16			rx_ticks;
 /* Maximal coalescing timeout in us */
-#define BNX2X_MAX_COALESCE_TOUT		(0xf0*12)
+#define BNX2X_MAX_COALESCE_TOUT		(0xff*BNX2X_BTR)
 
 	u32			lin_cnt;
 
@@ -2072,7 +2072,8 @@
 
 void bnx2x_prep_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae,
 			       u8 src_type, u8 dst_type);
-int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae);
+int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae,
+			       u32 *comp);
 
 /* FLR related routines */
 u32 bnx2x_flr_clnup_poll_count(struct bnx2x *bp);
@@ -2498,4 +2499,8 @@
 };
 
 void bnx2x_set_local_cmng(struct bnx2x *bp);
+
+#define MCPR_SCRATCH_BASE(bp) \
+	(CHIP_IS_E1x(bp) ? MCP_REG_MCPR_SCRATCH : MCP_A_REG_MCPR_SCRATCH)
+
 #endif /* bnx2x.h */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index e66beff..74d6486 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -681,6 +681,7 @@
 		}
 	}
 #endif
+	skb_record_rx_queue(skb, fp->rx_queue);
 	napi_gro_receive(&fp->napi, skb);
 }
 
@@ -2544,10 +2545,6 @@
 		}
 	}
 
-	/* Allocated memory for FW statistics  */
-	if (bnx2x_alloc_fw_stats_mem(bp))
-		LOAD_ERROR_EXIT(bp, load_error0);
-
 	/* need to be done after alloc mem, since it's self adjusting to amount
 	 * of memory available for RSS queues
 	 */
@@ -2557,6 +2554,10 @@
 		LOAD_ERROR_EXIT(bp, load_error0);
 	}
 
+	/* Allocated memory for FW statistics  */
+	if (bnx2x_alloc_fw_stats_mem(bp))
+		LOAD_ERROR_EXIT(bp, load_error0);
+
 	/* request pf to initialize status blocks */
 	if (IS_VF(bp)) {
 		rc = bnx2x_vfpf_init(bp);
@@ -2811,8 +2812,8 @@
 	if (IS_PF(bp))
 		bnx2x_clear_pf_load(bp);
 load_error0:
-	bnx2x_free_fp_mem(bp);
 	bnx2x_free_fw_stats_mem(bp);
+	bnx2x_free_fp_mem(bp);
 	bnx2x_free_mem(bp);
 
 	return rc;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index 324de5f..e8efa1c9 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -891,17 +891,8 @@
 	 * will re-enable parity attentions right after the dump.
 	 */
 
-	/* Disable parity on path 0 */
-	bnx2x_pretend_func(bp, 0);
 	bnx2x_disable_blocks_parity(bp);
 
-	/* Disable parity on path 1 */
-	bnx2x_pretend_func(bp, 1);
-	bnx2x_disable_blocks_parity(bp);
-
-	/* Return to current function */
-	bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
-
 	dump_hdr.header_size = (sizeof(struct dump_header) / 4) - 1;
 	dump_hdr.preset = DUMP_ALL_PRESETS;
 	dump_hdr.version = BNX2X_DUMP_VERSION;
@@ -928,18 +919,9 @@
 	/* Actually read the registers */
 	__bnx2x_get_regs(bp, p);
 
-	/* Re-enable parity attentions on path 0 */
-	bnx2x_pretend_func(bp, 0);
+	/* Re-enable parity attentions */
 	bnx2x_clear_blocks_parity(bp);
 	bnx2x_enable_blocks_parity(bp);
-
-	/* Re-enable parity attentions on path 1 */
-	bnx2x_pretend_func(bp, 1);
-	bnx2x_clear_blocks_parity(bp);
-	bnx2x_enable_blocks_parity(bp);
-
-	/* Return to current function */
-	bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
 }
 
 static int bnx2x_get_preset_regs_len(struct net_device *dev, u32 preset)
@@ -993,17 +975,8 @@
 	 * will re-enable parity attentions right after the dump.
 	 */
 
-	/* Disable parity on path 0 */
-	bnx2x_pretend_func(bp, 0);
 	bnx2x_disable_blocks_parity(bp);
 
-	/* Disable parity on path 1 */
-	bnx2x_pretend_func(bp, 1);
-	bnx2x_disable_blocks_parity(bp);
-
-	/* Return to current function */
-	bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
-
 	dump_hdr.header_size = (sizeof(struct dump_header) / 4) - 1;
 	dump_hdr.preset = bp->dump_preset_idx;
 	dump_hdr.version = BNX2X_DUMP_VERSION;
@@ -1032,19 +1005,10 @@
 	/* Actually read the registers */
 	__bnx2x_get_preset_regs(bp, p, dump_hdr.preset);
 
-	/* Re-enable parity attentions on path 0 */
-	bnx2x_pretend_func(bp, 0);
+	/* Re-enable parity attentions */
 	bnx2x_clear_blocks_parity(bp);
 	bnx2x_enable_blocks_parity(bp);
 
-	/* Re-enable parity attentions on path 1 */
-	bnx2x_pretend_func(bp, 1);
-	bnx2x_clear_blocks_parity(bp);
-	bnx2x_enable_blocks_parity(bp);
-
-	/* Return to current function */
-	bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
-
 	return 0;
 }
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h
index 76df015..c2dfea7 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h
@@ -640,23 +640,35 @@
  * [30] MCP Latched ump_tx_parity
  * [31] MCP Latched scpad_parity
  */
-#define MISC_AEU_ENABLE_MCP_PRTY_BITS	\
+#define MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS	\
 	(AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY | \
 	 AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY | \
-	 AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY | \
+	 AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY)
+
+#define MISC_AEU_ENABLE_MCP_PRTY_BITS	\
+	(MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS | \
 	 AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY)
 
 /* Below registers control the MCP parity attention output. When
  * MISC_AEU_ENABLE_MCP_PRTY_BITS are set - attentions are
  * enabled, when cleared - disabled.
  */
-static const u32 mcp_attn_ctl_regs[] = {
-	MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0,
-	MISC_REG_AEU_ENABLE4_NIG_0,
-	MISC_REG_AEU_ENABLE4_PXP_0,
-	MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0,
-	MISC_REG_AEU_ENABLE4_NIG_1,
-	MISC_REG_AEU_ENABLE4_PXP_1
+static const struct {
+	u32 addr;
+	u32 bits;
+} mcp_attn_ctl_regs[] = {
+	{ MISC_REG_AEU_ENABLE4_FUNC_0_OUT_0,
+		MISC_AEU_ENABLE_MCP_PRTY_BITS },
+	{ MISC_REG_AEU_ENABLE4_NIG_0,
+		MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS },
+	{ MISC_REG_AEU_ENABLE4_PXP_0,
+		MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS },
+	{ MISC_REG_AEU_ENABLE4_FUNC_1_OUT_0,
+		MISC_AEU_ENABLE_MCP_PRTY_BITS },
+	{ MISC_REG_AEU_ENABLE4_NIG_1,
+		MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS },
+	{ MISC_REG_AEU_ENABLE4_PXP_1,
+		MISC_AEU_ENABLE_MCP_PRTY_SUB_BITS }
 };
 
 static inline void bnx2x_set_mcp_parity(struct bnx2x *bp, u8 enable)
@@ -665,14 +677,14 @@
 	u32 reg_val;
 
 	for (i = 0; i < ARRAY_SIZE(mcp_attn_ctl_regs); i++) {
-		reg_val = REG_RD(bp, mcp_attn_ctl_regs[i]);
+		reg_val = REG_RD(bp, mcp_attn_ctl_regs[i].addr);
 
 		if (enable)
-			reg_val |= MISC_AEU_ENABLE_MCP_PRTY_BITS;
+			reg_val |= mcp_attn_ctl_regs[i].bits;
 		else
-			reg_val &= ~MISC_AEU_ENABLE_MCP_PRTY_BITS;
+			reg_val &= ~mcp_attn_ctl_regs[i].bits;
 
-		REG_WR(bp, mcp_attn_ctl_regs[i], reg_val);
+		REG_WR(bp, mcp_attn_ctl_regs[i].addr, reg_val);
 	}
 }
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 82b658d..b42f89c 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -503,9 +503,9 @@
 }
 
 /* issue a dmae command over the init-channel and wait for completion */
-int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae)
+int bnx2x_issue_dmae_with_comp(struct bnx2x *bp, struct dmae_command *dmae,
+			       u32 *comp)
 {
-	u32 *wb_comp = bnx2x_sp(bp, wb_comp);
 	int cnt = CHIP_REV_IS_SLOW(bp) ? (400000) : 4000;
 	int rc = 0;
 
@@ -518,14 +518,14 @@
 	spin_lock_bh(&bp->dmae_lock);
 
 	/* reset completion */
-	*wb_comp = 0;
+	*comp = 0;
 
 	/* post the command on the channel used for initializations */
 	bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp));
 
 	/* wait for completion */
 	udelay(5);
-	while ((*wb_comp & ~DMAE_PCI_ERR_FLAG) != DMAE_COMP_VAL) {
+	while ((*comp & ~DMAE_PCI_ERR_FLAG) != DMAE_COMP_VAL) {
 
 		if (!cnt ||
 		    (bp->recovery_state != BNX2X_RECOVERY_DONE &&
@@ -537,7 +537,7 @@
 		cnt--;
 		udelay(50);
 	}
-	if (*wb_comp & DMAE_PCI_ERR_FLAG) {
+	if (*comp & DMAE_PCI_ERR_FLAG) {
 		BNX2X_ERR("DMAE PCI error!\n");
 		rc = DMAE_PCI_ERROR;
 	}
@@ -574,7 +574,7 @@
 	dmae.len = len32;
 
 	/* issue the command and wait for completion */
-	rc = bnx2x_issue_dmae_with_comp(bp, &dmae);
+	rc = bnx2x_issue_dmae_with_comp(bp, &dmae, bnx2x_sp(bp, wb_comp));
 	if (rc) {
 		BNX2X_ERR("DMAE returned failure %d\n", rc);
 		bnx2x_panic();
@@ -611,7 +611,7 @@
 	dmae.len = len32;
 
 	/* issue the command and wait for completion */
-	rc = bnx2x_issue_dmae_with_comp(bp, &dmae);
+	rc = bnx2x_issue_dmae_with_comp(bp, &dmae, bnx2x_sp(bp, wb_comp));
 	if (rc) {
 		BNX2X_ERR("DMAE returned failure %d\n", rc);
 		bnx2x_panic();
@@ -751,6 +751,10 @@
 	return rc;
 }
 
+#define MCPR_TRACE_BUFFER_SIZE	(0x800)
+#define SCRATCH_BUFFER_SIZE(bp)	\
+	(CHIP_IS_E1(bp) ? 0x10000 : (CHIP_IS_E1H(bp) ? 0x20000 : 0x28000))
+
 void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl)
 {
 	u32 addr, val;
@@ -775,7 +779,17 @@
 		trace_shmem_base = bp->common.shmem_base;
 	else
 		trace_shmem_base = SHMEM2_RD(bp, other_shmem_base_addr);
-	addr = trace_shmem_base - 0x800;
+
+	/* sanity */
+	if (trace_shmem_base < MCPR_SCRATCH_BASE(bp) + MCPR_TRACE_BUFFER_SIZE ||
+	    trace_shmem_base >= MCPR_SCRATCH_BASE(bp) +
+				SCRATCH_BUFFER_SIZE(bp)) {
+		BNX2X_ERR("Unable to dump trace buffer (mark %x)\n",
+			  trace_shmem_base);
+		return;
+	}
+
+	addr = trace_shmem_base - MCPR_TRACE_BUFFER_SIZE;
 
 	/* validate TRCB signature */
 	mark = REG_RD(bp, addr);
@@ -787,14 +801,17 @@
 	/* read cyclic buffer pointer */
 	addr += 4;
 	mark = REG_RD(bp, addr);
-	mark = (CHIP_IS_E1x(bp) ? MCP_REG_MCPR_SCRATCH : MCP_A_REG_MCPR_SCRATCH)
-			+ ((mark + 0x3) & ~0x3) - 0x08000000;
+	mark = MCPR_SCRATCH_BASE(bp) + ((mark + 0x3) & ~0x3) - 0x08000000;
+	if (mark >= trace_shmem_base || mark < addr + 4) {
+		BNX2X_ERR("Mark doesn't fall inside Trace Buffer\n");
+		return;
+	}
 	printk("%s" "begin fw dump (mark 0x%x)\n", lvl, mark);
 
 	printk("%s", lvl);
 
 	/* dump buffer after the mark */
-	for (offset = mark; offset <= trace_shmem_base; offset += 0x8*4) {
+	for (offset = mark; offset < trace_shmem_base; offset += 0x8*4) {
 		for (word = 0; word < 8; word++)
 			data[word] = htonl(REG_RD(bp, offset + 4*word));
 		data[8] = 0x0;
@@ -4280,65 +4297,60 @@
 	pr_cont("%s%s", idx ? ", " : "", blk);
 }
 
-static int bnx2x_check_blocks_with_parity0(struct bnx2x *bp, u32 sig,
-					    int par_num, bool print)
+static bool bnx2x_check_blocks_with_parity0(struct bnx2x *bp, u32 sig,
+					    int *par_num, bool print)
 {
-	int i = 0;
-	u32 cur_bit = 0;
+	u32 cur_bit;
+	bool res;
+	int i;
+
+	res = false;
+
 	for (i = 0; sig; i++) {
-		cur_bit = ((u32)0x1 << i);
+		cur_bit = (0x1UL << i);
 		if (sig & cur_bit) {
-			switch (cur_bit) {
-			case AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR:
-				if (print) {
-					_print_next_block(par_num++, "BRB");
+			res |= true; /* Each bit is real error! */
+
+			if (print) {
+				switch (cur_bit) {
+				case AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR:
+					_print_next_block((*par_num)++, "BRB");
 					_print_parity(bp,
 						      BRB1_REG_BRB1_PRTY_STS);
-				}
-				break;
-			case AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR:
-				if (print) {
-					_print_next_block(par_num++, "PARSER");
+					break;
+				case AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR:
+					_print_next_block((*par_num)++,
+							  "PARSER");
 					_print_parity(bp, PRS_REG_PRS_PRTY_STS);
-				}
-				break;
-			case AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR:
-				if (print) {
-					_print_next_block(par_num++, "TSDM");
+					break;
+				case AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR:
+					_print_next_block((*par_num)++, "TSDM");
 					_print_parity(bp,
 						      TSDM_REG_TSDM_PRTY_STS);
-				}
-				break;
-			case AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR:
-				if (print) {
-					_print_next_block(par_num++,
+					break;
+				case AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR:
+					_print_next_block((*par_num)++,
 							  "SEARCHER");
 					_print_parity(bp, SRC_REG_SRC_PRTY_STS);
-				}
-				break;
-			case AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR:
-				if (print) {
-					_print_next_block(par_num++, "TCM");
-					_print_parity(bp,
-						      TCM_REG_TCM_PRTY_STS);
-				}
-				break;
-			case AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR:
-				if (print) {
-					_print_next_block(par_num++, "TSEMI");
+					break;
+				case AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR:
+					_print_next_block((*par_num)++, "TCM");
+					_print_parity(bp, TCM_REG_TCM_PRTY_STS);
+					break;
+				case AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR:
+					_print_next_block((*par_num)++,
+							  "TSEMI");
 					_print_parity(bp,
 						      TSEM_REG_TSEM_PRTY_STS_0);
 					_print_parity(bp,
 						      TSEM_REG_TSEM_PRTY_STS_1);
-				}
-				break;
-			case AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR:
-				if (print) {
-					_print_next_block(par_num++, "XPB");
+					break;
+				case AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR:
+					_print_next_block((*par_num)++, "XPB");
 					_print_parity(bp, GRCBASE_XPB +
 							  PB_REG_PB_PRTY_STS);
+					break;
 				}
-				break;
 			}
 
 			/* Clear the bit */
@@ -4346,53 +4358,59 @@
 		}
 	}
 
-	return par_num;
+	return res;
 }
 
-static int bnx2x_check_blocks_with_parity1(struct bnx2x *bp, u32 sig,
-					    int par_num, bool *global,
+static bool bnx2x_check_blocks_with_parity1(struct bnx2x *bp, u32 sig,
+					    int *par_num, bool *global,
 					    bool print)
 {
-	int i = 0;
-	u32 cur_bit = 0;
+	u32 cur_bit;
+	bool res;
+	int i;
+
+	res = false;
+
 	for (i = 0; sig; i++) {
-		cur_bit = ((u32)0x1 << i);
+		cur_bit = (0x1UL << i);
 		if (sig & cur_bit) {
+			res |= true; /* Each bit is real error! */
 			switch (cur_bit) {
 			case AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR:
 				if (print) {
-					_print_next_block(par_num++, "PBF");
+					_print_next_block((*par_num)++, "PBF");
 					_print_parity(bp, PBF_REG_PBF_PRTY_STS);
 				}
 				break;
 			case AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR:
 				if (print) {
-					_print_next_block(par_num++, "QM");
+					_print_next_block((*par_num)++, "QM");
 					_print_parity(bp, QM_REG_QM_PRTY_STS);
 				}
 				break;
 			case AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR:
 				if (print) {
-					_print_next_block(par_num++, "TM");
+					_print_next_block((*par_num)++, "TM");
 					_print_parity(bp, TM_REG_TM_PRTY_STS);
 				}
 				break;
 			case AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR:
 				if (print) {
-					_print_next_block(par_num++, "XSDM");
+					_print_next_block((*par_num)++, "XSDM");
 					_print_parity(bp,
 						      XSDM_REG_XSDM_PRTY_STS);
 				}
 				break;
 			case AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR:
 				if (print) {
-					_print_next_block(par_num++, "XCM");
+					_print_next_block((*par_num)++, "XCM");
 					_print_parity(bp, XCM_REG_XCM_PRTY_STS);
 				}
 				break;
 			case AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR:
 				if (print) {
-					_print_next_block(par_num++, "XSEMI");
+					_print_next_block((*par_num)++,
+							  "XSEMI");
 					_print_parity(bp,
 						      XSEM_REG_XSEM_PRTY_STS_0);
 					_print_parity(bp,
@@ -4401,7 +4419,7 @@
 				break;
 			case AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR:
 				if (print) {
-					_print_next_block(par_num++,
+					_print_next_block((*par_num)++,
 							  "DOORBELLQ");
 					_print_parity(bp,
 						      DORQ_REG_DORQ_PRTY_STS);
@@ -4409,7 +4427,7 @@
 				break;
 			case AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR:
 				if (print) {
-					_print_next_block(par_num++, "NIG");
+					_print_next_block((*par_num)++, "NIG");
 					if (CHIP_IS_E1x(bp)) {
 						_print_parity(bp,
 							NIG_REG_NIG_PRTY_STS);
@@ -4423,32 +4441,34 @@
 				break;
 			case AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR:
 				if (print)
-					_print_next_block(par_num++,
+					_print_next_block((*par_num)++,
 							  "VAUX PCI CORE");
 				*global = true;
 				break;
 			case AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR:
 				if (print) {
-					_print_next_block(par_num++, "DEBUG");
+					_print_next_block((*par_num)++,
+							  "DEBUG");
 					_print_parity(bp, DBG_REG_DBG_PRTY_STS);
 				}
 				break;
 			case AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR:
 				if (print) {
-					_print_next_block(par_num++, "USDM");
+					_print_next_block((*par_num)++, "USDM");
 					_print_parity(bp,
 						      USDM_REG_USDM_PRTY_STS);
 				}
 				break;
 			case AEU_INPUTS_ATTN_BITS_UCM_PARITY_ERROR:
 				if (print) {
-					_print_next_block(par_num++, "UCM");
+					_print_next_block((*par_num)++, "UCM");
 					_print_parity(bp, UCM_REG_UCM_PRTY_STS);
 				}
 				break;
 			case AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR:
 				if (print) {
-					_print_next_block(par_num++, "USEMI");
+					_print_next_block((*par_num)++,
+							  "USEMI");
 					_print_parity(bp,
 						      USEM_REG_USEM_PRTY_STS_0);
 					_print_parity(bp,
@@ -4457,21 +4477,21 @@
 				break;
 			case AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR:
 				if (print) {
-					_print_next_block(par_num++, "UPB");
+					_print_next_block((*par_num)++, "UPB");
 					_print_parity(bp, GRCBASE_UPB +
 							  PB_REG_PB_PRTY_STS);
 				}
 				break;
 			case AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR:
 				if (print) {
-					_print_next_block(par_num++, "CSDM");
+					_print_next_block((*par_num)++, "CSDM");
 					_print_parity(bp,
 						      CSDM_REG_CSDM_PRTY_STS);
 				}
 				break;
 			case AEU_INPUTS_ATTN_BITS_CCM_PARITY_ERROR:
 				if (print) {
-					_print_next_block(par_num++, "CCM");
+					_print_next_block((*par_num)++, "CCM");
 					_print_parity(bp, CCM_REG_CCM_PRTY_STS);
 				}
 				break;
@@ -4482,80 +4502,73 @@
 		}
 	}
 
-	return par_num;
+	return res;
 }
 
-static int bnx2x_check_blocks_with_parity2(struct bnx2x *bp, u32 sig,
-					    int par_num, bool print)
+static bool bnx2x_check_blocks_with_parity2(struct bnx2x *bp, u32 sig,
+					    int *par_num, bool print)
 {
-	int i = 0;
-	u32 cur_bit = 0;
+	u32 cur_bit;
+	bool res;
+	int i;
+
+	res = false;
+
 	for (i = 0; sig; i++) {
-		cur_bit = ((u32)0x1 << i);
+		cur_bit = (0x1UL << i);
 		if (sig & cur_bit) {
-			switch (cur_bit) {
-			case AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR:
-				if (print) {
-					_print_next_block(par_num++, "CSEMI");
+			res |= true; /* Each bit is real error! */
+			if (print) {
+				switch (cur_bit) {
+				case AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR:
+					_print_next_block((*par_num)++,
+							  "CSEMI");
 					_print_parity(bp,
 						      CSEM_REG_CSEM_PRTY_STS_0);
 					_print_parity(bp,
 						      CSEM_REG_CSEM_PRTY_STS_1);
-				}
-				break;
-			case AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR:
-				if (print) {
-					_print_next_block(par_num++, "PXP");
+					break;
+				case AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR:
+					_print_next_block((*par_num)++, "PXP");
 					_print_parity(bp, PXP_REG_PXP_PRTY_STS);
 					_print_parity(bp,
 						      PXP2_REG_PXP2_PRTY_STS_0);
 					_print_parity(bp,
 						      PXP2_REG_PXP2_PRTY_STS_1);
-				}
-				break;
-			case AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR:
-				if (print)
-					_print_next_block(par_num++,
-					"PXPPCICLOCKCLIENT");
-				break;
-			case AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR:
-				if (print) {
-					_print_next_block(par_num++, "CFC");
+					break;
+				case AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR:
+					_print_next_block((*par_num)++,
+							  "PXPPCICLOCKCLIENT");
+					break;
+				case AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR:
+					_print_next_block((*par_num)++, "CFC");
 					_print_parity(bp,
 						      CFC_REG_CFC_PRTY_STS);
-				}
-				break;
-			case AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR:
-				if (print) {
-					_print_next_block(par_num++, "CDU");
+					break;
+				case AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR:
+					_print_next_block((*par_num)++, "CDU");
 					_print_parity(bp, CDU_REG_CDU_PRTY_STS);
-				}
-				break;
-			case AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR:
-				if (print) {
-					_print_next_block(par_num++, "DMAE");
+					break;
+				case AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR:
+					_print_next_block((*par_num)++, "DMAE");
 					_print_parity(bp,
 						      DMAE_REG_DMAE_PRTY_STS);
-				}
-				break;
-			case AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR:
-				if (print) {
-					_print_next_block(par_num++, "IGU");
+					break;
+				case AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR:
+					_print_next_block((*par_num)++, "IGU");
 					if (CHIP_IS_E1x(bp))
 						_print_parity(bp,
 							HC_REG_HC_PRTY_STS);
 					else
 						_print_parity(bp,
 							IGU_REG_IGU_PRTY_STS);
-				}
-				break;
-			case AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR:
-				if (print) {
-					_print_next_block(par_num++, "MISC");
+					break;
+				case AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR:
+					_print_next_block((*par_num)++, "MISC");
 					_print_parity(bp,
 						      MISC_REG_MISC_PRTY_STS);
+					break;
 				}
-				break;
 			}
 
 			/* Clear the bit */
@@ -4563,40 +4576,49 @@
 		}
 	}
 
-	return par_num;
+	return res;
 }
 
-static int bnx2x_check_blocks_with_parity3(u32 sig, int par_num,
-					   bool *global, bool print)
+static bool bnx2x_check_blocks_with_parity3(struct bnx2x *bp, u32 sig,
+					    int *par_num, bool *global,
+					    bool print)
 {
-	int i = 0;
-	u32 cur_bit = 0;
+	bool res = false;
+	u32 cur_bit;
+	int i;
+
 	for (i = 0; sig; i++) {
-		cur_bit = ((u32)0x1 << i);
+		cur_bit = (0x1UL << i);
 		if (sig & cur_bit) {
 			switch (cur_bit) {
 			case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY:
 				if (print)
-					_print_next_block(par_num++, "MCP ROM");
+					_print_next_block((*par_num)++,
+							  "MCP ROM");
 				*global = true;
+				res |= true;
 				break;
 			case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY:
 				if (print)
-					_print_next_block(par_num++,
+					_print_next_block((*par_num)++,
 							  "MCP UMP RX");
 				*global = true;
+				res |= true;
 				break;
 			case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY:
 				if (print)
-					_print_next_block(par_num++,
+					_print_next_block((*par_num)++,
 							  "MCP UMP TX");
 				*global = true;
+				res |= true;
 				break;
 			case AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY:
 				if (print)
-					_print_next_block(par_num++,
+					_print_next_block((*par_num)++,
 							  "MCP SCPAD");
-				*global = true;
+				/* clear latched SCPAD PATIRY from MCP */
+				REG_WR(bp, MISC_REG_AEU_CLR_LATCH_SIGNAL,
+				       1UL << 10);
 				break;
 			}
 
@@ -4605,45 +4627,50 @@
 		}
 	}
 
-	return par_num;
+	return res;
 }
 
-static int bnx2x_check_blocks_with_parity4(struct bnx2x *bp, u32 sig,
-					    int par_num, bool print)
+static bool bnx2x_check_blocks_with_parity4(struct bnx2x *bp, u32 sig,
+					    int *par_num, bool print)
 {
-	int i = 0;
-	u32 cur_bit = 0;
+	u32 cur_bit;
+	bool res;
+	int i;
+
+	res = false;
+
 	for (i = 0; sig; i++) {
-		cur_bit = ((u32)0x1 << i);
+		cur_bit = (0x1UL << i);
 		if (sig & cur_bit) {
-			switch (cur_bit) {
-			case AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR:
-				if (print) {
-					_print_next_block(par_num++, "PGLUE_B");
+			res |= true; /* Each bit is real error! */
+			if (print) {
+				switch (cur_bit) {
+				case AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR:
+					_print_next_block((*par_num)++,
+							  "PGLUE_B");
 					_print_parity(bp,
-						PGLUE_B_REG_PGLUE_B_PRTY_STS);
-				}
-				break;
-			case AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR:
-				if (print) {
-					_print_next_block(par_num++, "ATC");
+						      PGLUE_B_REG_PGLUE_B_PRTY_STS);
+					break;
+				case AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR:
+					_print_next_block((*par_num)++, "ATC");
 					_print_parity(bp,
 						      ATC_REG_ATC_PRTY_STS);
+					break;
 				}
-				break;
 			}
-
 			/* Clear the bit */
 			sig &= ~cur_bit;
 		}
 	}
 
-	return par_num;
+	return res;
 }
 
 static bool bnx2x_parity_attn(struct bnx2x *bp, bool *global, bool print,
 			      u32 *sig)
 {
+	bool res = false;
+
 	if ((sig[0] & HW_PRTY_ASSERT_SET_0) ||
 	    (sig[1] & HW_PRTY_ASSERT_SET_1) ||
 	    (sig[2] & HW_PRTY_ASSERT_SET_2) ||
@@ -4660,23 +4687,22 @@
 		if (print)
 			netdev_err(bp->dev,
 				   "Parity errors detected in blocks: ");
-		par_num = bnx2x_check_blocks_with_parity0(bp,
-			sig[0] & HW_PRTY_ASSERT_SET_0, par_num, print);
-		par_num = bnx2x_check_blocks_with_parity1(bp,
-			sig[1] & HW_PRTY_ASSERT_SET_1, par_num, global, print);
-		par_num = bnx2x_check_blocks_with_parity2(bp,
-			sig[2] & HW_PRTY_ASSERT_SET_2, par_num, print);
-		par_num = bnx2x_check_blocks_with_parity3(
-			sig[3] & HW_PRTY_ASSERT_SET_3, par_num, global, print);
-		par_num = bnx2x_check_blocks_with_parity4(bp,
-			sig[4] & HW_PRTY_ASSERT_SET_4, par_num, print);
+		res |= bnx2x_check_blocks_with_parity0(bp,
+			sig[0] & HW_PRTY_ASSERT_SET_0, &par_num, print);
+		res |= bnx2x_check_blocks_with_parity1(bp,
+			sig[1] & HW_PRTY_ASSERT_SET_1, &par_num, global, print);
+		res |= bnx2x_check_blocks_with_parity2(bp,
+			sig[2] & HW_PRTY_ASSERT_SET_2, &par_num, print);
+		res |= bnx2x_check_blocks_with_parity3(bp,
+			sig[3] & HW_PRTY_ASSERT_SET_3, &par_num, global, print);
+		res |= bnx2x_check_blocks_with_parity4(bp,
+			sig[4] & HW_PRTY_ASSERT_SET_4, &par_num, print);
 
 		if (print)
 			pr_cont("\n");
+	}
 
-		return true;
-	} else
-		return false;
+	return res;
 }
 
 /**
@@ -7126,7 +7152,7 @@
 	int port = BP_PORT(bp);
 	int init_phase = port ? PHASE_PORT1 : PHASE_PORT0;
 	u32 low, high;
-	u32 val;
+	u32 val, reg;
 
 	DP(NETIF_MSG_HW, "starting port init  port %d\n", port);
 
@@ -7271,6 +7297,17 @@
 	val |= CHIP_IS_E1(bp) ? 0 : 0x10;
 	REG_WR(bp, MISC_REG_AEU_MASK_ATTN_FUNC_0 + port*4, val);
 
+	/* SCPAD_PARITY should NOT trigger close the gates */
+	reg = port ? MISC_REG_AEU_ENABLE4_NIG_1 : MISC_REG_AEU_ENABLE4_NIG_0;
+	REG_WR(bp, reg,
+	       REG_RD(bp, reg) &
+	       ~AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY);
+
+	reg = port ? MISC_REG_AEU_ENABLE4_PXP_1 : MISC_REG_AEU_ENABLE4_PXP_0;
+	REG_WR(bp, reg,
+	       REG_RD(bp, reg) &
+	       ~AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY);
+
 	bnx2x_init_block(bp, BLOCK_NIG, init_phase);
 
 	if (!CHIP_IS_E1x(bp)) {
@@ -11685,9 +11722,6 @@
 static int bnx2x_open(struct net_device *dev)
 {
 	struct bnx2x *bp = netdev_priv(dev);
-	bool global = false;
-	int other_engine = BP_PATH(bp) ? 0 : 1;
-	bool other_load_status, load_status;
 	int rc;
 
 	bp->stats_init = true;
@@ -11703,6 +11737,10 @@
 	 * Parity recovery is only relevant for PF driver.
 	 */
 	if (IS_PF(bp)) {
+		int other_engine = BP_PATH(bp) ? 0 : 1;
+		bool other_load_status, load_status;
+		bool global = false;
+
 		other_load_status = bnx2x_get_load_status(bp, other_engine);
 		load_status = bnx2x_get_load_status(bp, BP_PATH(bp));
 		if (!bnx2x_reset_is_done(bp, BP_PATH(bp)) ||
@@ -12080,7 +12118,6 @@
 	struct device *dev = &bp->pdev->dev;
 
 	if (dma_set_mask(dev, DMA_BIT_MASK(64)) == 0) {
-		bp->flags |= USING_DAC_FLAG;
 		if (dma_set_coherent_mask(dev, DMA_BIT_MASK(64)) != 0) {
 			dev_err(dev, "dma_set_coherent_mask failed, aborting\n");
 			return -EIO;
@@ -12248,8 +12285,7 @@
 		NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_HIGHDMA;
 
 	dev->features |= dev->hw_features | NETIF_F_HW_VLAN_CTAG_RX;
-	if (bp->flags & USING_DAC_FLAG)
-		dev->features |= NETIF_F_HIGHDMA;
+	dev->features |= NETIF_F_HIGHDMA;
 
 	/* Add Loopback capability to the device */
 	dev->hw_features |= NETIF_F_LOOPBACK;
@@ -12612,24 +12648,24 @@
 		return BNX2X_MULTI_TX_COS_E1X;
 	case BCM57712:
 	case BCM57712_MF:
-	case BCM57712_VF:
 		return BNX2X_MULTI_TX_COS_E2_E3A0;
 	case BCM57800:
 	case BCM57800_MF:
-	case BCM57800_VF:
 	case BCM57810:
 	case BCM57810_MF:
 	case BCM57840_4_10:
 	case BCM57840_2_20:
 	case BCM57840_O:
 	case BCM57840_MFO:
-	case BCM57810_VF:
 	case BCM57840_MF:
-	case BCM57840_VF:
 	case BCM57811:
 	case BCM57811_MF:
-	case BCM57811_VF:
 		return BNX2X_MULTI_TX_COS_E3B0;
+	case BCM57712_VF:
+	case BCM57800_VF:
+	case BCM57810_VF:
+	case BCM57840_VF:
+	case BCM57811_VF:
 		return 1;
 	default:
 		pr_err("Unknown board_type (%d), aborting\n", chip_id);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index 9ad012b..5e07efb 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -470,10 +470,10 @@
 				 bnx2x_vfop_qdtor, cmd->done);
 		return bnx2x_vfop_transition(bp, vf, bnx2x_vfop_qdtor,
 					     cmd->block);
+	} else {
+		BNX2X_ERR("VF[%d] failed to add a vfop\n", vf->abs_vfid);
+		return -ENOMEM;
 	}
-	DP(BNX2X_MSG_IOV, "VF[%d] failed to add a vfop. rc %d\n",
-	   vf->abs_vfid, vfop->rc);
-	return -ENOMEM;
 }
 
 static void
@@ -2018,6 +2018,8 @@
 
 void bnx2x_iov_remove_one(struct bnx2x *bp)
 {
+	int vf_idx;
+
 	/* if SRIOV is not enabled there's nothing to do */
 	if (!IS_SRIOV(bp))
 		return;
@@ -2026,6 +2028,18 @@
 	pci_disable_sriov(bp->pdev);
 	DP(BNX2X_MSG_IOV, "sriov disabled\n");
 
+	/* disable access to all VFs */
+	for (vf_idx = 0; vf_idx < bp->vfdb->sriov.total; vf_idx++) {
+		bnx2x_pretend_func(bp,
+				   HW_VF_HANDLE(bp,
+						bp->vfdb->sriov.first_vf_in_pf +
+						vf_idx));
+		DP(BNX2X_MSG_IOV, "disabling internal access for vf %d\n",
+		   bp->vfdb->sriov.first_vf_in_pf + vf_idx);
+		bnx2x_vf_enable_internal(bp, 0);
+		bnx2x_pretend_func(bp, BP_ABS_FUNC(bp));
+	}
+
 	/* free vf database */
 	__bnx2x_iov_free_vfdb(bp);
 }
@@ -3197,7 +3211,7 @@
 	 * the "acquire" messages to appear on the VF PF channel.
 	 */
 	DP(BNX2X_MSG_IOV, "about to call enable sriov\n");
-	pci_disable_sriov(bp->pdev);
+	bnx2x_disable_sriov(bp);
 	rc = pci_enable_sriov(bp->pdev, req_vfs);
 	if (rc) {
 		BNX2X_ERR("pci_enable_sriov failed with %d\n", rc);
@@ -3390,14 +3404,16 @@
 		rc = bnx2x_del_all_macs(bp, mac_obj, BNX2X_ETH_MAC, true);
 		if (rc) {
 			BNX2X_ERR("failed to delete eth macs\n");
-			return -EINVAL;
+			rc = -EINVAL;
+			goto out;
 		}
 
 		/* remove existing uc list macs */
 		rc = bnx2x_del_all_macs(bp, mac_obj, BNX2X_UC_LIST_MAC, true);
 		if (rc) {
 			BNX2X_ERR("failed to delete uc_list macs\n");
-			return -EINVAL;
+			rc = -EINVAL;
+			goto out;
 		}
 
 		/* configure the new mac to device */
@@ -3405,6 +3421,7 @@
 		bnx2x_set_mac_one(bp, (u8 *)&bulletin->mac, mac_obj, true,
 				  BNX2X_ETH_MAC, &ramrod_flags);
 
+out:
 		bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_MAC);
 	}
 
@@ -3467,7 +3484,8 @@
 					  &ramrod_flags);
 		if (rc) {
 			BNX2X_ERR("failed to delete vlans\n");
-			return -EINVAL;
+			rc = -EINVAL;
+			goto out;
 		}
 
 		/* send queue update ramrod to configure default vlan and silent
@@ -3501,7 +3519,8 @@
 			rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
 			if (rc) {
 				BNX2X_ERR("failed to configure vlan\n");
-				return -EINVAL;
+				rc =  -EINVAL;
+				goto out;
 			}
 
 			/* configure default vlan to vf queue and set silent
@@ -3519,18 +3538,18 @@
 		rc = bnx2x_queue_state_change(bp, &q_params);
 		if (rc) {
 			BNX2X_ERR("Failed to configure default VLAN\n");
-			return rc;
+			goto out;
 		}
 
 		/* clear the flag indicating that this VF needs its vlan
-		 * (will only be set if the HV configured th Vlan before vf was
-		 * and we were called because the VF came up later
+		 * (will only be set if the HV configured the Vlan before vf was
+		 * up and we were called because the VF came up later
 		 */
+out:
 		vf->cfg_flags &= ~VF_CFG_VLAN;
-
 		bnx2x_unlock_vf_pf_channel(bp, vf, CHANNEL_TLV_PF_SET_VLAN);
 	}
-	return 0;
+	return rc;
 }
 
 /* crc is the first field in the bulletin board. Compute the crc over the
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
index 86436c7..3b75070 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
@@ -196,7 +196,7 @@
 
 	} else if (bp->func_stx) {
 		*stats_comp = 0;
-		bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp));
+		bnx2x_issue_dmae_with_comp(bp, dmae, stats_comp);
 	}
 }
 
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index da16953..28757df 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
@@ -980,7 +980,7 @@
 	dmae.len = len32;
 
 	/* issue the command and wait for completion */
-	return bnx2x_issue_dmae_with_comp(bp, &dmae);
+	return bnx2x_issue_dmae_with_comp(bp, &dmae, bnx2x_sp(bp, wb_comp));
 }
 
 static void bnx2x_vf_mbx_resp(struct bnx2x *bp, struct bnx2x_virtf *vf)
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 78d6d6b..48f5288 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -106,7 +106,6 @@
 #define XGMAC_DMA_HW_FEATURE	0x00000f58	/* Enabled Hardware Features */
 
 #define XGMAC_ADDR_AE		0x80000000
-#define XGMAC_MAX_FILTER_ADDR	31
 
 /* PMT Control and Status */
 #define XGMAC_PMT_POINTER_RESET	0x80000000
@@ -384,6 +383,7 @@
 	struct device *device;
 	struct napi_struct napi;
 
+	int max_macs;
 	struct xgmac_extra_stats xstats;
 
 	spinlock_t stats_lock;
@@ -1291,14 +1291,12 @@
 	netdev_dbg(priv->dev, "# mcasts %d, # unicast %d\n",
 		 netdev_mc_count(dev), netdev_uc_count(dev));
 
-	if (dev->flags & IFF_PROMISC) {
-		writel(XGMAC_FRAME_FILTER_PR, ioaddr + XGMAC_FRAME_FILTER);
-		return;
-	}
+	if (dev->flags & IFF_PROMISC)
+		value |= XGMAC_FRAME_FILTER_PR;
 
 	memset(hash_filter, 0, sizeof(hash_filter));
 
-	if (netdev_uc_count(dev) > XGMAC_MAX_FILTER_ADDR) {
+	if (netdev_uc_count(dev) > priv->max_macs) {
 		use_hash = true;
 		value |= XGMAC_FRAME_FILTER_HUC | XGMAC_FRAME_FILTER_HPF;
 	}
@@ -1321,7 +1319,7 @@
 		goto out;
 	}
 
-	if ((netdev_mc_count(dev) + reg - 1) > XGMAC_MAX_FILTER_ADDR) {
+	if ((netdev_mc_count(dev) + reg - 1) > priv->max_macs) {
 		use_hash = true;
 		value |= XGMAC_FRAME_FILTER_HMC | XGMAC_FRAME_FILTER_HPF;
 	} else {
@@ -1342,8 +1340,8 @@
 	}
 
 out:
-	for (i = reg; i < XGMAC_MAX_FILTER_ADDR; i++)
-		xgmac_set_mac_addr(ioaddr, NULL, reg);
+	for (i = reg; i <= priv->max_macs; i++)
+		xgmac_set_mac_addr(ioaddr, NULL, i);
 	for (i = 0; i < XGMAC_NUM_HASH; i++)
 		writel(hash_filter[i], ioaddr + XGMAC_HASH(i));
 
@@ -1761,6 +1759,13 @@
 	uid = readl(priv->base + XGMAC_VERSION);
 	netdev_info(ndev, "h/w version is 0x%x\n", uid);
 
+	/* Figure out how many valid mac address filter registers we have */
+	writel(1, priv->base + XGMAC_ADDR_HIGH(31));
+	if (readl(priv->base + XGMAC_ADDR_HIGH(31)) == 1)
+		priv->max_macs = 31;
+	else
+		priv->max_macs = 7;
+
 	writel(0, priv->base + XGMAC_DMA_INTR_ENA);
 	ndev->irq = platform_get_irq(pdev, 0);
 	if (ndev->irq == -ENXIO) {
diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c
index 9c89dc8..632b318 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c
@@ -1599,7 +1599,8 @@
 	flits = skb_transport_offset(skb) / 8;
 	sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl;
 	sgl_flits = make_sgl(skb, sgp, skb_transport_header(skb),
-			     skb->tail - skb->transport_header,
+			     skb_tail_pointer(skb) -
+			     skb_transport_header(skb),
 			     adap->pdev);
 	if (need_skb_unmap()) {
 		setup_deferred_unmapping(skb, adap->pdev, sgp, sgl_flits);
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c
index 5f5896e..a7a941b 100644
--- a/drivers/net/ethernet/davicom/dm9000.c
+++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -158,18 +158,6 @@
 
 /* DM9000 network board routine ---------------------------- */
 
-static void
-dm9000_reset(board_info_t * db)
-{
-	dev_dbg(db->dev, "resetting device\n");
-
-	/* RESET device */
-	writeb(DM9000_NCR, db->io_addr);
-	udelay(200);
-	writeb(NCR_RST, db->io_data);
-	udelay(200);
-}
-
 /*
  *   Read a byte from I/O port
  */
@@ -191,6 +179,27 @@
 	writeb(value, db->io_data);
 }
 
+static void
+dm9000_reset(board_info_t *db)
+{
+	dev_dbg(db->dev, "resetting device\n");
+
+	/* Reset DM9000, see DM9000 Application Notes V1.22 Jun 11, 2004 page 29
+	 * The essential point is that we have to do a double reset, and the
+	 * instruction is to set LBK into MAC internal loopback mode.
+	 */
+	iow(db, DM9000_NCR, 0x03);
+	udelay(100); /* Application note says at least 20 us */
+	if (ior(db, DM9000_NCR) & 1)
+		dev_err(db->dev, "dm9000 did not respond to first reset\n");
+
+	iow(db, DM9000_NCR, 0);
+	iow(db, DM9000_NCR, 0x03);
+	udelay(100);
+	if (ior(db, DM9000_NCR) & 1)
+		dev_err(db->dev, "dm9000 did not respond to second reset\n");
+}
+
 /* routines for sending block to chip */
 
 static void dm9000_outblk_8bit(void __iomem *reg, void *data, int count)
@@ -744,15 +753,20 @@
 static void dm9000_show_carrier(board_info_t *db,
 				unsigned carrier, unsigned nsr)
 {
+	int lpa;
 	struct net_device *ndev = db->ndev;
+	struct mii_if_info *mii = &db->mii;
 	unsigned ncr = dm9000_read_locked(db, DM9000_NCR);
 
-	if (carrier)
-		dev_info(db->dev, "%s: link up, %dMbps, %s-duplex, no LPA\n",
+	if (carrier) {
+		lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA);
+		dev_info(db->dev,
+			 "%s: link up, %dMbps, %s-duplex, lpa 0x%04X\n",
 			 ndev->name, (nsr & NSR_SPEED) ? 10 : 100,
-			 (ncr & NCR_FDX) ? "full" : "half");
-	else
+			 (ncr & NCR_FDX) ? "full" : "half", lpa);
+	} else {
 		dev_info(db->dev, "%s: link down\n", ndev->name);
+	}
 }
 
 static void
@@ -890,9 +904,15 @@
 			(dev->features & NETIF_F_RXCSUM) ? RCSR_CSUM : 0);
 
 	iow(db, DM9000_GPCR, GPCR_GEP_CNTL);	/* Let GPIO0 output */
+	iow(db, DM9000_GPR, 0);
 
-	dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */
-	dm9000_phy_write(dev, 0, MII_DM_DSPCR, DSPCR_INIT_PARAM); /* Init */
+	/* If we are dealing with DM9000B, some extra steps are required: a
+	 * manual phy reset, and setting init params.
+	 */
+	if (db->type == TYPE_DM9000B) {
+		dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET);
+		dm9000_phy_write(dev, 0, MII_DM_DSPCR, DSPCR_INIT_PARAM);
+	}
 
 	ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0;
 
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index db02023..c99dac6 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -696,6 +696,15 @@
 	return adapter->flags & BE_FLAGS_QNQ_ASYNC_EVT_RCVD;
 }
 
+static inline int fw_major_num(const char *fw_ver)
+{
+	int fw_major = 0;
+
+	sscanf(fw_ver, "%d.", &fw_major);
+
+	return fw_major;
+}
+
 extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
 		u16 num_popped);
 extern void be_link_status_update(struct be_adapter *adapter, u8 link_status);
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index bd0e0c0..c08fd32 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -1198,7 +1198,6 @@
 
 	if (lancer_chip(adapter)) {
 		req->hdr.version = 1;
-		req->if_id = cpu_to_le16(adapter->if_handle);
 	} else if (BEx_chip(adapter)) {
 		if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC)
 			req->hdr.version = 2;
@@ -1206,6 +1205,8 @@
 		req->hdr.version = 2;
 	}
 
+	if (req->hdr.version > 0)
+		req->if_id = cpu_to_le16(adapter->if_handle);
 	req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
 	req->ulp_num = BE_ULP1_NUM;
 	req->type = BE_ETH_TX_RING_TYPE_STANDARD;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 2c38cc4..53ed58b 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -3247,6 +3247,12 @@
 
 	be_cmd_get_fw_ver(adapter, adapter->fw_ver, adapter->fw_on_flash);
 
+	if (BE2_chip(adapter) && fw_major_num(adapter->fw_ver) < 4) {
+		dev_err(dev, "Firmware on card is old(%s), IRQs may not work.",
+			adapter->fw_ver);
+		dev_err(dev, "Please upgrade firmware to version >= 4.0\n");
+	}
+
 	if (adapter->vlans_added)
 		be_vid_config(adapter);
 
diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c
index 7583a95..f8b9286 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c
@@ -32,7 +32,9 @@
 #include <linux/fs.h>
 #include <linux/platform_device.h>
 #include <linux/phy.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/of_irq.h>
 #include <linux/gfp.h>
 
 #include <asm/immap_cpm2.h>
@@ -88,7 +90,7 @@
 	struct fs_platform_info *fpi = fep->fpi;
 	int ret = -EINVAL;
 
-	fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL);
+	fep->interrupt = irq_of_parse_and_map(ofdev->dev.of_node, 0);
 	if (fep->interrupt == NO_IRQ)
 		goto out;
 
diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
index 9ae6cdb..a9a00f3 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
@@ -31,7 +31,9 @@
 #include <linux/bitops.h>
 #include <linux/fs.h>
 #include <linux/platform_device.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/of_irq.h>
 #include <linux/gfp.h>
 
 #include <asm/irq.h>
@@ -98,7 +100,7 @@
 {
 	struct platform_device *ofdev = to_platform_device(fep->dev);
 
-	fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL);
+	fep->interrupt = irq_of_parse_and_map(ofdev->dev.of_node, 0);
 	if (fep->interrupt == NO_IRQ)
 		return -EINVAL;
 
diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-scc.c b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c
index 22a02a7..d37cd4e 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mac-scc.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c
@@ -31,6 +31,8 @@
 #include <linux/bitops.h>
 #include <linux/fs.h>
 #include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
 #include <asm/irq.h>
@@ -98,7 +100,7 @@
 {
 	struct platform_device *ofdev = to_platform_device(fep->dev);
 
-	fep->interrupt = of_irq_to_resource(ofdev->dev.of_node, 0, NULL);
+	fep->interrupt = irq_of_parse_and_map(ofdev->dev.of_node, 0);
 	if (fep->interrupt == NO_IRQ)
 		return -EINVAL;
 
diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
index 844ecfa..67caaac 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
@@ -22,6 +22,7 @@
 #include <linux/mii.h>
 #include <linux/platform_device.h>
 #include <linux/mdio-bitbang.h>
+#include <linux/of_address.h>
 #include <linux/of_mdio.h>
 #include <linux/of_platform.h>
 
diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
index 2f1c46a..ac5d447 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
@@ -31,6 +31,7 @@
 #include <linux/ethtool.h>
 #include <linux/bitops.h>
 #include <linux/platform_device.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 
 #include <asm/pgtable.h>
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index c4eaade..ef95c3a 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -78,6 +78,8 @@
 #include <linux/if_vlan.h>
 #include <linux/spinlock.h>
 #include <linux/mm.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_mdio.h>
 #include <linux/of_platform.h>
 #include <linux/ip.h>
@@ -88,6 +90,7 @@
 
 #include <asm/io.h>
 #include <asm/reg.h>
+#include <asm/mpc85xx.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <linux/module.h>
@@ -939,9 +942,8 @@
 	}
 }
 
-static void gfar_detect_errata(struct gfar_private *priv)
+static void __gfar_detect_errata_83xx(struct gfar_private *priv)
 {
-	struct device *dev = &priv->ofdev->dev;
 	unsigned int pvr = mfspr(SPRN_PVR);
 	unsigned int svr = mfspr(SPRN_SVR);
 	unsigned int mod = (svr >> 16) & 0xfff6; /* w/o E suffix */
@@ -957,15 +959,33 @@
 	    (pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0))
 		priv->errata |= GFAR_ERRATA_76;
 
-	/* MPC8313 and MPC837x all rev */
-	if ((pvr == 0x80850010 && mod == 0x80b0) ||
-	    (pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0))
-		priv->errata |= GFAR_ERRATA_A002;
-
-	/* MPC8313 Rev < 2.0, MPC8548 rev 2.0 */
-	if ((pvr == 0x80850010 && mod == 0x80b0 && rev < 0x0020) ||
-	    (pvr == 0x80210020 && mod == 0x8030 && rev == 0x0020))
+	/* MPC8313 Rev < 2.0 */
+	if (pvr == 0x80850010 && mod == 0x80b0 && rev < 0x0020)
 		priv->errata |= GFAR_ERRATA_12;
+}
+
+static void __gfar_detect_errata_85xx(struct gfar_private *priv)
+{
+	unsigned int svr = mfspr(SPRN_SVR);
+
+	if ((SVR_SOC_VER(svr) == SVR_8548) && (SVR_REV(svr) == 0x20))
+		priv->errata |= GFAR_ERRATA_12;
+	if (((SVR_SOC_VER(svr) == SVR_P2020) && (SVR_REV(svr) < 0x20)) ||
+	    ((SVR_SOC_VER(svr) == SVR_P2010) && (SVR_REV(svr) < 0x20)))
+		priv->errata |= GFAR_ERRATA_76; /* aka eTSEC 20 */
+}
+
+static void gfar_detect_errata(struct gfar_private *priv)
+{
+	struct device *dev = &priv->ofdev->dev;
+
+	/* no plans to fix */
+	priv->errata |= GFAR_ERRATA_A002;
+
+	if (pvr_version_is(PVR_VER_E500V1) || pvr_version_is(PVR_VER_E500V2))
+		__gfar_detect_errata_85xx(priv);
+	else /* non-mpc85xx parts, i.e. e300 core based */
+		__gfar_detect_errata_83xx(priv);
 
 	if (priv->errata)
 		dev_info(dev, "enabled errata workarounds, flags: 0x%x\n",
@@ -1599,7 +1619,7 @@
 	/* Normaly TSEC should not hang on GRS commands, so we should
 	 * actually wait for IEVENT_GRSC flag.
 	 */
-	if (likely(!gfar_has_errata(priv, GFAR_ERRATA_A002)))
+	if (!gfar_has_errata(priv, GFAR_ERRATA_A002))
 		return 0;
 
 	/* Read the eTSEC register at offset 0xD1C. If bits 7-14 are
diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c
index 5930c39..64b329f 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.c
+++ b/drivers/net/ethernet/freescale/ucc_geth.c
@@ -31,6 +31,8 @@
 #include <linux/mii.h>
 #include <linux/phy.h>
 #include <linux/workqueue.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
 #include <linux/of_platform.h>
diff --git a/drivers/net/ethernet/freescale/xgmac_mdio.c b/drivers/net/ethernet/freescale/xgmac_mdio.c
index c1b6e7e..d449fcb9 100644
--- a/drivers/net/ethernet/freescale/xgmac_mdio.c
+++ b/drivers/net/ethernet/freescale/xgmac_mdio.c
@@ -17,6 +17,7 @@
 #include <linux/module.h>
 #include <linux/phy.h>
 #include <linux/mdio.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/of_mdio.h>
 
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index 6b5c722..cdf2321 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -39,6 +39,8 @@
 #include <linux/bitops.h>
 #include <linux/workqueue.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_net.h>
 #include <linux/slab.h>
 
diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c
index dac564c..9d75fef 100644
--- a/drivers/net/ethernet/ibm/emac/mal.c
+++ b/drivers/net/ethernet/ibm/emac/mal.c
@@ -27,6 +27,7 @@
 
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/of_irq.h>
 
 #include "core.h"
 #include <asm/dcr-regs.h>
@@ -263,7 +264,9 @@
 {
 	if (likely(napi_schedule_prep(&mal->napi))) {
 		MAL_DBG2(mal, "schedule_poll" NL);
+		spin_lock(&mal->lock);
 		mal_disable_eob_irq(mal);
+		spin_unlock(&mal->lock);
 		__napi_schedule(&mal->napi);
 	} else
 		MAL_DBG2(mal, "already in poll" NL);
@@ -442,15 +445,13 @@
 		if (unlikely(mc->ops->peek_rx(mc->dev) ||
 			     test_bit(MAL_COMMAC_RX_STOPPED, &mc->flags))) {
 			MAL_DBG2(mal, "rotting packet" NL);
-			if (napi_reschedule(napi))
-				mal_disable_eob_irq(mal);
-			else
-				MAL_DBG2(mal, "already in poll list" NL);
-
-			if (budget > 0)
-				goto again;
-			else
+			if (!napi_reschedule(napi))
 				goto more_work;
+
+			spin_lock_irqsave(&mal->lock, flags);
+			mal_disable_eob_irq(mal);
+			spin_unlock_irqrestore(&mal->lock, flags);
+			goto again;
 		}
 		mc->ops->poll_tx(mc->dev);
 	}
diff --git a/drivers/net/ethernet/ibm/emac/rgmii.c b/drivers/net/ethernet/ibm/emac/rgmii.c
index c47e23d..4fb2f96 100644
--- a/drivers/net/ethernet/ibm/emac/rgmii.c
+++ b/drivers/net/ethernet/ibm/emac/rgmii.c
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/ethtool.h>
+#include <linux/of_address.h>
 #include <asm/io.h>
 
 #include "emac.h"
diff --git a/drivers/net/ethernet/ibm/emac/tah.c b/drivers/net/ethernet/ibm/emac/tah.c
index c231a4a..9f24769 100644
--- a/drivers/net/ethernet/ibm/emac/tah.c
+++ b/drivers/net/ethernet/ibm/emac/tah.c
@@ -18,6 +18,7 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
+#include <linux/of_address.h>
 #include <asm/io.h>
 
 #include "emac.h"
diff --git a/drivers/net/ethernet/ibm/emac/zmii.c b/drivers/net/ethernet/ibm/emac/zmii.c
index 4cdf286..9ca67a3 100644
--- a/drivers/net/ethernet/ibm/emac/zmii.c
+++ b/drivers/net/ethernet/ibm/emac/zmii.c
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/ethtool.h>
+#include <linux/of_address.h>
 #include <asm/io.h>
 
 #include "emac.h"
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index 86d5142..151e00c 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -2655,6 +2655,8 @@
 	    (hw->phy.media_type != e1000_media_type_copper))
 		return -EOPNOTSUPP;
 
+	memset(&eee_curr, 0, sizeof(struct ethtool_eee));
+
 	ret_val = igb_get_eee(netdev, &eee_curr);
 	if (ret_val)
 		return ret_val;
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index 7fb5677..2c210ec 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -1131,15 +1131,13 @@
 	p->rx_discard += rdlp(mp, RX_DISCARD_FRAME_CNT);
 	p->rx_overrun += rdlp(mp, RX_OVERRUN_FRAME_CNT);
 	spin_unlock_bh(&mp->mib_counters_lock);
-
-	mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ);
 }
 
 static void mib_counters_timer_wrapper(unsigned long _mp)
 {
 	struct mv643xx_eth_private *mp = (void *)_mp;
-
 	mib_counters_update(mp);
+	mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ);
 }
 
 
@@ -2237,6 +2235,7 @@
 		mp->int_mask |= INT_TX_END_0 << i;
 	}
 
+	add_timer(&mp->mib_counters_timer);
 	port_start(mp);
 
 	wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX);
@@ -2534,6 +2533,7 @@
 	if (!ppdev)
 		return -ENOMEM;
 	ppdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+	ppdev->dev.of_node = pnp;
 
 	ret = platform_device_add_resources(ppdev, &res, 1);
 	if (ret)
@@ -2916,7 +2916,6 @@
 	mp->mib_counters_timer.data = (unsigned long)mp;
 	mp->mib_counters_timer.function = mib_counters_timer_wrapper;
 	mp->mib_counters_timer.expires = jiffies + 30 * HZ;
-	add_timer(&mp->mib_counters_timer);
 
 	spin_lock_init(&mp->mib_counters_lock);
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index ea20182..bb11624 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -1691,7 +1691,7 @@
 			vp_oper->vlan_idx = NO_INDX;
 		}
 		if (NO_INDX != vp_oper->mac_idx) {
-			__mlx4_unregister_mac(&priv->dev, port, vp_oper->mac_idx);
+			__mlx4_unregister_mac(&priv->dev, port, vp_oper->state.mac);
 			vp_oper->mac_idx = NO_INDX;
 		}
 	}
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index dec455c..afe2efa 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -70,14 +70,15 @@
 		put_page(page);
 		return -ENOMEM;
 	}
-	page_alloc->size = PAGE_SIZE << order;
+	page_alloc->page_size = PAGE_SIZE << order;
 	page_alloc->page = page;
 	page_alloc->dma = dma;
-	page_alloc->offset = frag_info->frag_align;
+	page_alloc->page_offset = frag_info->frag_align;
 	/* Not doing get_page() for each frag is a big win
 	 * on asymetric workloads.
 	 */
-	atomic_set(&page->_count, page_alloc->size / frag_info->frag_stride);
+	atomic_set(&page->_count,
+		   page_alloc->page_size / frag_info->frag_stride);
 	return 0;
 }
 
@@ -96,16 +97,19 @@
 	for (i = 0; i < priv->num_frags; i++) {
 		frag_info = &priv->frag_info[i];
 		page_alloc[i] = ring_alloc[i];
-		page_alloc[i].offset += frag_info->frag_stride;
-		if (page_alloc[i].offset + frag_info->frag_stride <= ring_alloc[i].size)
+		page_alloc[i].page_offset += frag_info->frag_stride;
+
+		if (page_alloc[i].page_offset + frag_info->frag_stride <=
+		    ring_alloc[i].page_size)
 			continue;
+
 		if (mlx4_alloc_pages(priv, &page_alloc[i], frag_info, gfp))
 			goto out;
 	}
 
 	for (i = 0; i < priv->num_frags; i++) {
 		frags[i] = ring_alloc[i];
-		dma = ring_alloc[i].dma + ring_alloc[i].offset;
+		dma = ring_alloc[i].dma + ring_alloc[i].page_offset;
 		ring_alloc[i] = page_alloc[i];
 		rx_desc->data[i].addr = cpu_to_be64(dma);
 	}
@@ -117,7 +121,7 @@
 		frag_info = &priv->frag_info[i];
 		if (page_alloc[i].page != ring_alloc[i].page) {
 			dma_unmap_page(priv->ddev, page_alloc[i].dma,
-				page_alloc[i].size, PCI_DMA_FROMDEVICE);
+				page_alloc[i].page_size, PCI_DMA_FROMDEVICE);
 			page = page_alloc[i].page;
 			atomic_set(&page->_count, 1);
 			put_page(page);
@@ -131,10 +135,12 @@
 			      int i)
 {
 	const struct mlx4_en_frag_info *frag_info = &priv->frag_info[i];
+	u32 next_frag_end = frags[i].page_offset + 2 * frag_info->frag_stride;
 
-	if (frags[i].offset + frag_info->frag_stride > frags[i].size)
-		dma_unmap_page(priv->ddev, frags[i].dma, frags[i].size,
-					 PCI_DMA_FROMDEVICE);
+
+	if (next_frag_end > frags[i].page_size)
+		dma_unmap_page(priv->ddev, frags[i].dma, frags[i].page_size,
+			       PCI_DMA_FROMDEVICE);
 
 	if (frags[i].page)
 		put_page(frags[i].page);
@@ -161,7 +167,7 @@
 
 		page_alloc = &ring->page_alloc[i];
 		dma_unmap_page(priv->ddev, page_alloc->dma,
-			       page_alloc->size, PCI_DMA_FROMDEVICE);
+			       page_alloc->page_size, PCI_DMA_FROMDEVICE);
 		page = page_alloc->page;
 		atomic_set(&page->_count, 1);
 		put_page(page);
@@ -184,10 +190,11 @@
 		       i, page_count(page_alloc->page));
 
 		dma_unmap_page(priv->ddev, page_alloc->dma,
-				page_alloc->size, PCI_DMA_FROMDEVICE);
-		while (page_alloc->offset + frag_info->frag_stride < page_alloc->size) {
+				page_alloc->page_size, PCI_DMA_FROMDEVICE);
+		while (page_alloc->page_offset + frag_info->frag_stride <
+		       page_alloc->page_size) {
 			put_page(page_alloc->page);
-			page_alloc->offset += frag_info->frag_stride;
+			page_alloc->page_offset += frag_info->frag_stride;
 		}
 		page_alloc->page = NULL;
 	}
@@ -478,7 +485,7 @@
 		/* Save page reference in skb */
 		__skb_frag_set_page(&skb_frags_rx[nr], frags[nr].page);
 		skb_frag_size_set(&skb_frags_rx[nr], frag_info->frag_size);
-		skb_frags_rx[nr].page_offset = frags[nr].offset;
+		skb_frags_rx[nr].page_offset = frags[nr].page_offset;
 		skb->truesize += frag_info->frag_stride;
 		frags[nr].page = NULL;
 	}
@@ -517,7 +524,7 @@
 
 	/* Get pointer to first fragment so we could copy the headers into the
 	 * (linear part of the) skb */
-	va = page_address(frags[0].page) + frags[0].offset;
+	va = page_address(frags[0].page) + frags[0].page_offset;
 
 	if (length <= SMALL_PACKET_SIZE) {
 		/* We are copying all relevant data to the skb - temporarily
@@ -645,7 +652,7 @@
 			dma_sync_single_for_cpu(priv->ddev, dma, sizeof(*ethh),
 						DMA_FROM_DEVICE);
 			ethh = (struct ethhdr *)(page_address(frags[0].page) +
-						 frags[0].offset);
+						 frags[0].page_offset);
 
 			if (is_multicast_ether_addr(ethh->h_dest)) {
 				struct mlx4_mac_entry *entry;
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index 5e0aa56..bf06e36 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -237,8 +237,8 @@
 struct mlx4_en_rx_alloc {
 	struct page	*page;
 	dma_addr_t	dma;
-	u32		offset;
-	u32		size;
+	u32		page_offset;
+	u32		page_size;
 };
 
 struct mlx4_en_tx_ring {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
index 5472cbd..6ca3073 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
@@ -180,28 +180,32 @@
 	return 0;
 }
 
-static void calc_block_sig(struct mlx5_cmd_prot_block *block, u8 token)
+static void calc_block_sig(struct mlx5_cmd_prot_block *block, u8 token,
+			   int csum)
 {
 	block->token = token;
-	block->ctrl_sig = ~xor8_buf(block->rsvd0, sizeof(*block) - sizeof(block->data) - 2);
-	block->sig = ~xor8_buf(block, sizeof(*block) - 1);
+	if (csum) {
+		block->ctrl_sig = ~xor8_buf(block->rsvd0, sizeof(*block) -
+					    sizeof(block->data) - 2);
+		block->sig = ~xor8_buf(block, sizeof(*block) - 1);
+	}
 }
 
-static void calc_chain_sig(struct mlx5_cmd_msg *msg, u8 token)
+static void calc_chain_sig(struct mlx5_cmd_msg *msg, u8 token, int csum)
 {
 	struct mlx5_cmd_mailbox *next = msg->next;
 
 	while (next) {
-		calc_block_sig(next->buf, token);
+		calc_block_sig(next->buf, token, csum);
 		next = next->next;
 	}
 }
 
-static void set_signature(struct mlx5_cmd_work_ent *ent)
+static void set_signature(struct mlx5_cmd_work_ent *ent, int csum)
 {
 	ent->lay->sig = ~xor8_buf(ent->lay, sizeof(*ent->lay));
-	calc_chain_sig(ent->in, ent->token);
-	calc_chain_sig(ent->out, ent->token);
+	calc_chain_sig(ent->in, ent->token, csum);
+	calc_chain_sig(ent->out, ent->token, csum);
 }
 
 static void poll_timeout(struct mlx5_cmd_work_ent *ent)
@@ -539,8 +543,7 @@
 	lay->type = MLX5_PCI_CMD_XPORT;
 	lay->token = ent->token;
 	lay->status_own = CMD_OWNER_HW;
-	if (!cmd->checksum_disabled)
-		set_signature(ent);
+	set_signature(ent, !cmd->checksum_disabled);
 	dump_command(dev, ent, 1);
 	ktime_get_ts(&ent->ts1);
 
@@ -773,8 +776,6 @@
 
 		copy = min_t(int, size, MLX5_CMD_DATA_BLOCK_SIZE);
 		block = next->buf;
-		if (xor8_buf(block, sizeof(*block)) != 0xff)
-			return -EINVAL;
 
 		memcpy(to, block->data, copy);
 		to += copy;
@@ -1361,6 +1362,7 @@
 		goto err_map;
 	}
 
+	cmd->checksum_disabled = 1;
 	cmd->max_reg_cmds = (1 << cmd->log_sz) - 1;
 	cmd->bitmask = (1 << cmd->max_reg_cmds) - 1;
 
@@ -1510,7 +1512,7 @@
 	case MLX5_CMD_STAT_BAD_SYS_STATE_ERR:		return -EIO;
 	case MLX5_CMD_STAT_BAD_RES_ERR:			return -EINVAL;
 	case MLX5_CMD_STAT_RES_BUSY:			return -EBUSY;
-	case MLX5_CMD_STAT_LIM_ERR:			return -EINVAL;
+	case MLX5_CMD_STAT_LIM_ERR:			return -ENOMEM;
 	case MLX5_CMD_STAT_BAD_RES_STATE_ERR:		return -EINVAL;
 	case MLX5_CMD_STAT_IX_ERR:			return -EINVAL;
 	case MLX5_CMD_STAT_NO_RES_ERR:			return -EAGAIN;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
index 443cc4d..2231d93 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
@@ -366,9 +366,11 @@
 		goto err_in;
 	}
 
+	snprintf(eq->name, MLX5_MAX_EQ_NAME, "%s@pci:%s",
+		 name, pci_name(dev->pdev));
 	eq->eqn = out.eq_number;
 	err = request_irq(table->msix_arr[vecidx].vector, mlx5_msix_handler, 0,
-			  name, eq);
+			  eq->name, eq);
 	if (err)
 		goto err_eq;
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index b47739b..bc0f5fb 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -165,9 +165,7 @@
 	struct mlx5_cmd_set_hca_cap_mbox_in *set_ctx = NULL;
 	struct mlx5_cmd_query_hca_cap_mbox_in query_ctx;
 	struct mlx5_cmd_set_hca_cap_mbox_out set_out;
-	struct mlx5_profile *prof = dev->profile;
 	u64 flags;
-	int csum = 1;
 	int err;
 
 	memset(&query_ctx, 0, sizeof(query_ctx));
@@ -197,20 +195,14 @@
 	memcpy(&set_ctx->hca_cap, &query_out->hca_cap,
 	       sizeof(set_ctx->hca_cap));
 
-	if (prof->mask & MLX5_PROF_MASK_CMDIF_CSUM) {
-		csum = !!prof->cmdif_csum;
-		flags = be64_to_cpu(set_ctx->hca_cap.flags);
-		if (csum)
-			flags |= MLX5_DEV_CAP_FLAG_CMDIF_CSUM;
-		else
-			flags &= ~MLX5_DEV_CAP_FLAG_CMDIF_CSUM;
-
-		set_ctx->hca_cap.flags = cpu_to_be64(flags);
-	}
-
 	if (dev->profile->mask & MLX5_PROF_MASK_QP_SIZE)
 		set_ctx->hca_cap.log_max_qp = dev->profile->log_max_qp;
 
+	flags = be64_to_cpu(query_out->hca_cap.flags);
+	/* disable checksum */
+	flags &= ~MLX5_DEV_CAP_FLAG_CMDIF_CSUM;
+
+	set_ctx->hca_cap.flags = cpu_to_be64(flags);
 	memset(&set_out, 0, sizeof(set_out));
 	set_ctx->hca_cap.log_uar_page_sz = cpu_to_be16(PAGE_SHIFT - 12);
 	set_ctx->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_SET_HCA_CAP);
@@ -225,9 +217,6 @@
 	if (err)
 		goto query_ex;
 
-	if (!csum)
-		dev->cmd.checksum_disabled = 1;
-
 query_ex:
 	kfree(query_out);
 	kfree(set_ctx);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
index 3a2408d..7b12acf 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
@@ -90,6 +90,10 @@
 	__be64			pas[0];
 };
 
+enum {
+	MAX_RECLAIM_TIME_MSECS	= 5000,
+};
+
 static int insert_page(struct mlx5_core_dev *dev, u64 addr, struct page *page, u16 func_id)
 {
 	struct rb_root *root = &dev->priv.page_root;
@@ -279,6 +283,9 @@
 	int err;
 	int i;
 
+	if (nclaimed)
+		*nclaimed = 0;
+
 	memset(&in, 0, sizeof(in));
 	outlen = sizeof(*out) + npages * sizeof(out->pas[0]);
 	out = mlx5_vzalloc(outlen);
@@ -388,20 +395,25 @@
 
 int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev)
 {
-	unsigned long end = jiffies + msecs_to_jiffies(5000);
+	unsigned long end = jiffies + msecs_to_jiffies(MAX_RECLAIM_TIME_MSECS);
 	struct fw_page *fwp;
 	struct rb_node *p;
+	int nclaimed = 0;
 	int err;
 
 	do {
 		p = rb_first(&dev->priv.page_root);
 		if (p) {
 			fwp = rb_entry(p, struct fw_page, rb_node);
-			err = reclaim_pages(dev, fwp->func_id, optimal_reclaimed_pages(), NULL);
+			err = reclaim_pages(dev, fwp->func_id,
+					    optimal_reclaimed_pages(),
+					    &nclaimed);
 			if (err) {
 				mlx5_core_warn(dev, "failed reclaiming pages (%d)\n", err);
 				return err;
 			}
+			if (nclaimed)
+				end = jiffies + msecs_to_jiffies(MAX_RECLAIM_TIME_MSECS);
 		}
 		if (time_after(jiffies, end)) {
 			mlx5_core_warn(dev, "FW did not return all pages. giving up...\n");
diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c
index bd1a2d2..ea54d95 100644
--- a/drivers/net/ethernet/moxa/moxart_ether.c
+++ b/drivers/net/ethernet/moxa/moxart_ether.c
@@ -448,7 +448,8 @@
 	irq = irq_of_parse_and_map(node, 0);
 	if (irq <= 0) {
 		netdev_err(ndev, "irq_of_parse_and_map failed\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto irq_map_fail;
 	}
 
 	priv = netdev_priv(ndev);
@@ -472,24 +473,32 @@
 	priv->tx_desc_base = dma_alloc_coherent(NULL, TX_REG_DESC_SIZE *
 						TX_DESC_NUM, &priv->tx_base,
 						GFP_DMA | GFP_KERNEL);
-	if (priv->tx_desc_base == NULL)
+	if (priv->tx_desc_base == NULL) {
+		ret = -ENOMEM;
 		goto init_fail;
+	}
 
 	priv->rx_desc_base = dma_alloc_coherent(NULL, RX_REG_DESC_SIZE *
 						RX_DESC_NUM, &priv->rx_base,
 						GFP_DMA | GFP_KERNEL);
-	if (priv->rx_desc_base == NULL)
+	if (priv->rx_desc_base == NULL) {
+		ret = -ENOMEM;
 		goto init_fail;
+	}
 
 	priv->tx_buf_base = kmalloc(priv->tx_buf_size * TX_DESC_NUM,
 				    GFP_ATOMIC);
-	if (!priv->tx_buf_base)
+	if (!priv->tx_buf_base) {
+		ret = -ENOMEM;
 		goto init_fail;
+	}
 
 	priv->rx_buf_base = kmalloc(priv->rx_buf_size * RX_DESC_NUM,
 				    GFP_ATOMIC);
-	if (!priv->rx_buf_base)
+	if (!priv->rx_buf_base) {
+		ret = -ENOMEM;
 		goto init_fail;
+	}
 
 	platform_set_drvdata(pdev, ndev);
 
@@ -522,7 +531,8 @@
 init_fail:
 	netdev_err(ndev, "init failed\n");
 	moxart_mac_free_memory(ndev);
-
+irq_map_fail:
+	free_netdev(ndev);
 	return ret;
 }
 
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index 3ca00e0..ace217c 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -2276,9 +2276,9 @@
 		temp = (cmd.rsp.arg[8] & 0x7FFE0000) >> 17;
 		npar_info->max_linkspeed_reg_offset = temp;
 	}
-	if (npar_info->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS)
-		memcpy(ahw->extra_capability, &cmd.rsp.arg[16],
-		       sizeof(ahw->extra_capability));
+
+	memcpy(ahw->extra_capability, &cmd.rsp.arg[16],
+	       sizeof(ahw->extra_capability));
 
 out:
 	qlcnic_free_mbx_args(&cmd);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index ebe4c86..ff83a9f 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -665,7 +665,7 @@
 			return err;
 	}
 
-	if (channel->tx_count) {
+	if (qlcnic_82xx_check(adapter) && channel->tx_count) {
 		err = qlcnic_validate_max_tx_rings(adapter, channel->tx_count);
 		if (err)
 			return err;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
index f8adc7b..b64e2be 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
@@ -785,8 +785,6 @@
 
 #define QLCNIC_ENABLE_IPV4_LRO		1
 #define QLCNIC_ENABLE_IPV6_LRO		2
-#define QLCNIC_NO_DEST_IPV4_CHECK	(1 << 8)
-#define QLCNIC_NO_DEST_IPV6_CHECK	(2 << 8)
 
 int qlcnic_82xx_config_hw_lro(struct qlcnic_adapter *adapter, int enable)
 {
@@ -806,11 +804,10 @@
 
 	word = 0;
 	if (enable) {
-		word = QLCNIC_ENABLE_IPV4_LRO | QLCNIC_NO_DEST_IPV4_CHECK;
+		word = QLCNIC_ENABLE_IPV4_LRO;
 		if (adapter->ahw->extra_capability[0] &
 		    QLCNIC_FW_CAP2_HW_LRO_IPV6)
-			word |= QLCNIC_ENABLE_IPV6_LRO |
-				QLCNIC_NO_DEST_IPV6_CHECK;
+			word |= QLCNIC_ENABLE_IPV6_LRO;
 	}
 
 	req.words[0] = cpu_to_le64(word);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 21d00a0..d8f4897e 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -1131,7 +1131,10 @@
 		if (err == -EIO)
 			return err;
 		adapter->ahw->extra_capability[0] = temp;
+	} else {
+		adapter->ahw->extra_capability[0] = 0;
 	}
+
 	adapter->ahw->max_mac_filters = nic_info.max_mac_filters;
 	adapter->ahw->max_mtu = nic_info.max_mtu;
 
@@ -2159,8 +2162,7 @@
 	else if (qlcnic_83xx_check(adapter))
 		fw_cmd = QLCNIC_CMD_83XX_SET_DRV_VER;
 
-	if ((ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) &&
-	    (ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_SET_DRV_VER))
+	if (ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_SET_DRV_VER)
 		qlcnic_fw_cmd_set_drv_version(adapter, fw_cmd);
 }
 
@@ -2257,7 +2259,7 @@
 
 	err = qlcnic_alloc_adapter_resources(adapter);
 	if (err)
-		goto err_out_free_netdev;
+		goto err_out_free_wq;
 
 	adapter->dev_rst_time = jiffies;
 	adapter->ahw->revision_id = pdev->revision;
@@ -2396,6 +2398,9 @@
 err_out_free_hw:
 	qlcnic_free_adapter_resources(adapter);
 
+err_out_free_wq:
+	destroy_workqueue(adapter->qlcnic_wq);
+
 err_out_free_netdev:
 	free_netdev(netdev);
 
@@ -3648,11 +3653,6 @@
 	u8 max_hw = QLCNIC_MAX_TX_RINGS;
 	u32 max_allowed;
 
-	if (!qlcnic_82xx_check(adapter)) {
-		netdev_err(netdev, "No Multi TX-Q support\n");
-		return -EINVAL;
-	}
-
 	if (!qlcnic_use_msi_x && !qlcnic_use_msi) {
 		netdev_err(netdev, "No Multi TX-Q support in INT-x mode\n");
 		return -EINVAL;
@@ -3692,8 +3692,7 @@
 	u8 max_hw = adapter->ahw->max_rx_ques;
 	u32 max_allowed;
 
-	if (qlcnic_82xx_check(adapter) && !qlcnic_use_msi_x &&
-	    !qlcnic_use_msi) {
+	if (!qlcnic_use_msi_x && !qlcnic_use_msi) {
 		netdev_err(netdev, "No RSS support in INT-x mode\n");
 		return -EINVAL;
 	}
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 5cd831e..b57c278d 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -688,12 +688,16 @@
 	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
 			  EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE |
 			  EESR_TDE | EESR_ECI,
+	.fdr_value	= 0x0000070f,
+	.rmcr_value	= 0x00000001,
 
 	.apr		= 1,
 	.mpr		= 1,
 	.tpauser	= 1,
 	.bculr		= 1,
 	.hw_swap	= 1,
+	.rpadir		= 1,
+	.rpadir_value   = 2 << 16,
 	.no_trimd	= 1,
 	.no_ade		= 1,
 	.tsu		= 1,
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 9f18ae9..21f9ad6 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -444,6 +444,18 @@
 	EF10_DMA_STAT(rx_align_error, RX_ALIGN_ERROR_PKTS),
 	EF10_DMA_STAT(rx_length_error, RX_LENGTH_ERROR_PKTS),
 	EF10_DMA_STAT(rx_nodesc_drops, RX_NODESC_DROPS),
+	EF10_DMA_STAT(rx_pm_trunc_bb_overflow, PM_TRUNC_BB_OVERFLOW),
+	EF10_DMA_STAT(rx_pm_discard_bb_overflow, PM_DISCARD_BB_OVERFLOW),
+	EF10_DMA_STAT(rx_pm_trunc_vfifo_full, PM_TRUNC_VFIFO_FULL),
+	EF10_DMA_STAT(rx_pm_discard_vfifo_full, PM_DISCARD_VFIFO_FULL),
+	EF10_DMA_STAT(rx_pm_trunc_qbb, PM_TRUNC_QBB),
+	EF10_DMA_STAT(rx_pm_discard_qbb, PM_DISCARD_QBB),
+	EF10_DMA_STAT(rx_pm_discard_mapping, PM_DISCARD_MAPPING),
+	EF10_DMA_STAT(rx_dp_q_disabled_packets, RXDP_Q_DISABLED_PKTS),
+	EF10_DMA_STAT(rx_dp_di_dropped_packets, RXDP_DI_DROPPED_PKTS),
+	EF10_DMA_STAT(rx_dp_streaming_packets, RXDP_STREAMING_PKTS),
+	EF10_DMA_STAT(rx_dp_emerg_fetch, RXDP_EMERGENCY_FETCH_CONDITIONS),
+	EF10_DMA_STAT(rx_dp_emerg_wait, RXDP_EMERGENCY_WAIT_CONDITIONS),
 };
 
 #define HUNT_COMMON_STAT_MASK ((1ULL << EF10_STAT_tx_bytes) |		\
@@ -498,44 +510,72 @@
 #define HUNT_40G_EXTRA_STAT_MASK ((1ULL << EF10_STAT_rx_align_error) |	\
 				  (1ULL << EF10_STAT_rx_length_error))
 
-#if BITS_PER_LONG == 64
-#define STAT_MASK_BITMAP(bits) (bits)
-#else
-#define STAT_MASK_BITMAP(bits) (bits) & 0xffffffff, (bits) >> 32
-#endif
+/* These statistics are only provided if the firmware supports the
+ * capability PM_AND_RXDP_COUNTERS.
+ */
+#define HUNT_PM_AND_RXDP_STAT_MASK (					\
+	(1ULL << EF10_STAT_rx_pm_trunc_bb_overflow) |			\
+	(1ULL << EF10_STAT_rx_pm_discard_bb_overflow) |			\
+	(1ULL << EF10_STAT_rx_pm_trunc_vfifo_full) |			\
+	(1ULL << EF10_STAT_rx_pm_discard_vfifo_full) |			\
+	(1ULL << EF10_STAT_rx_pm_trunc_qbb) |				\
+	(1ULL << EF10_STAT_rx_pm_discard_qbb) |				\
+	(1ULL << EF10_STAT_rx_pm_discard_mapping) |			\
+	(1ULL << EF10_STAT_rx_dp_q_disabled_packets) |			\
+	(1ULL << EF10_STAT_rx_dp_di_dropped_packets) |			\
+	(1ULL << EF10_STAT_rx_dp_streaming_packets) |			\
+	(1ULL << EF10_STAT_rx_dp_emerg_fetch) |				\
+	(1ULL << EF10_STAT_rx_dp_emerg_wait))
 
-static const unsigned long *efx_ef10_stat_mask(struct efx_nic *efx)
+static u64 efx_ef10_raw_stat_mask(struct efx_nic *efx)
 {
-	static const unsigned long hunt_40g_stat_mask[] = {
-		STAT_MASK_BITMAP(HUNT_COMMON_STAT_MASK |
-				 HUNT_40G_EXTRA_STAT_MASK)
-	};
-	static const unsigned long hunt_10g_only_stat_mask[] = {
-		STAT_MASK_BITMAP(HUNT_COMMON_STAT_MASK |
-				 HUNT_10G_ONLY_STAT_MASK)
-	};
+	u64 raw_mask = HUNT_COMMON_STAT_MASK;
 	u32 port_caps = efx_mcdi_phy_get_caps(efx);
+	struct efx_ef10_nic_data *nic_data = efx->nic_data;
 
 	if (port_caps & (1 << MC_CMD_PHY_CAP_40000FDX_LBN))
-		return hunt_40g_stat_mask;
+		raw_mask |= HUNT_40G_EXTRA_STAT_MASK;
 	else
-		return hunt_10g_only_stat_mask;
+		raw_mask |= HUNT_10G_ONLY_STAT_MASK;
+
+	if (nic_data->datapath_caps &
+	    (1 << MC_CMD_GET_CAPABILITIES_OUT_PM_AND_RXDP_COUNTERS_LBN))
+		raw_mask |= HUNT_PM_AND_RXDP_STAT_MASK;
+
+	return raw_mask;
+}
+
+static void efx_ef10_get_stat_mask(struct efx_nic *efx, unsigned long *mask)
+{
+	u64 raw_mask = efx_ef10_raw_stat_mask(efx);
+
+#if BITS_PER_LONG == 64
+	mask[0] = raw_mask;
+#else
+	mask[0] = raw_mask & 0xffffffff;
+	mask[1] = raw_mask >> 32;
+#endif
 }
 
 static size_t efx_ef10_describe_stats(struct efx_nic *efx, u8 *names)
 {
+	DECLARE_BITMAP(mask, EF10_STAT_COUNT);
+
+	efx_ef10_get_stat_mask(efx, mask);
 	return efx_nic_describe_stats(efx_ef10_stat_desc, EF10_STAT_COUNT,
-				      efx_ef10_stat_mask(efx), names);
+				      mask, names);
 }
 
 static int efx_ef10_try_update_nic_stats(struct efx_nic *efx)
 {
 	struct efx_ef10_nic_data *nic_data = efx->nic_data;
-	const unsigned long *stats_mask = efx_ef10_stat_mask(efx);
+	DECLARE_BITMAP(mask, EF10_STAT_COUNT);
 	__le64 generation_start, generation_end;
 	u64 *stats = nic_data->stats;
 	__le64 *dma_stats;
 
+	efx_ef10_get_stat_mask(efx, mask);
+
 	dma_stats = efx->stats_buffer.addr;
 	nic_data = efx->nic_data;
 
@@ -543,8 +583,9 @@
 	if (generation_end == EFX_MC_STATS_GENERATION_INVALID)
 		return 0;
 	rmb();
-	efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT, stats_mask,
+	efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT, mask,
 			     stats, efx->stats_buffer.addr, false);
+	rmb();
 	generation_start = dma_stats[MC_CMD_MAC_GENERATION_START];
 	if (generation_end != generation_start)
 		return -EAGAIN;
@@ -563,12 +604,14 @@
 static size_t efx_ef10_update_stats(struct efx_nic *efx, u64 *full_stats,
 				    struct rtnl_link_stats64 *core_stats)
 {
-	const unsigned long *mask = efx_ef10_stat_mask(efx);
+	DECLARE_BITMAP(mask, EF10_STAT_COUNT);
 	struct efx_ef10_nic_data *nic_data = efx->nic_data;
 	u64 *stats = nic_data->stats;
 	size_t stats_count = 0, index;
 	int retry;
 
+	efx_ef10_get_stat_mask(efx, mask);
+
 	/* If we're unlucky enough to read statistics during the DMA, wait
 	 * up to 10ms for it to finish (typically takes <500us)
 	 */
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index c082562..366c8e3 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -963,7 +963,7 @@
 			       bool *was_attached)
 {
 	MCDI_DECLARE_BUF(inbuf, MC_CMD_DRV_ATTACH_IN_LEN);
-	MCDI_DECLARE_BUF(outbuf, MC_CMD_DRV_ATTACH_OUT_LEN);
+	MCDI_DECLARE_BUF(outbuf, MC_CMD_DRV_ATTACH_EXT_OUT_LEN);
 	size_t outlen;
 	int rc;
 
@@ -981,6 +981,22 @@
 		goto fail;
 	}
 
+	/* We currently assume we have control of the external link
+	 * and are completely trusted by firmware.  Abort probing
+	 * if that's not true for this function.
+	 */
+	if (driver_operating &&
+	    outlen >= MC_CMD_DRV_ATTACH_EXT_OUT_LEN &&
+	    (MCDI_DWORD(outbuf, DRV_ATTACH_EXT_OUT_FUNC_FLAGS) &
+	     (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_LINKCTRL |
+	      1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_TRUSTED)) !=
+	    (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_LINKCTRL |
+	     1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_TRUSTED)) {
+		netif_err(efx, probe, efx->net_dev,
+			  "This driver version only supports one function per port\n");
+		return -ENODEV;
+	}
+
 	if (was_attached != NULL)
 		*was_attached = MCDI_DWORD(outbuf, DRV_ATTACH_OUT_OLD_STATE);
 	return 0;
diff --git a/drivers/net/ethernet/sfc/mcdi_pcol.h b/drivers/net/ethernet/sfc/mcdi_pcol.h
index b5cf624..e0a63dd 100644
--- a/drivers/net/ethernet/sfc/mcdi_pcol.h
+++ b/drivers/net/ethernet/sfc/mcdi_pcol.h
@@ -2574,8 +2574,58 @@
 #define          MC_CMD_MAC_RX_LANES01_DISP_ERR  0x39 /* enum */
 #define          MC_CMD_MAC_RX_LANES23_DISP_ERR  0x3a /* enum */
 #define          MC_CMD_MAC_RX_MATCH_FAULT  0x3b /* enum */
-#define          MC_CMD_GMAC_DMABUF_START  0x40 /* enum */
-#define          MC_CMD_GMAC_DMABUF_END    0x5f /* enum */
+/* enum: PM trunc_bb_overflow counter. Valid for EF10 with PM_AND_RXDP_COUNTERS
+ * capability only.
+ */
+#define          MC_CMD_MAC_PM_TRUNC_BB_OVERFLOW  0x3c
+/* enum: PM discard_bb_overflow counter. Valid for EF10 with
+ * PM_AND_RXDP_COUNTERS capability only.
+ */
+#define          MC_CMD_MAC_PM_DISCARD_BB_OVERFLOW  0x3d
+/* enum: PM trunc_vfifo_full counter. Valid for EF10 with PM_AND_RXDP_COUNTERS
+ * capability only.
+ */
+#define          MC_CMD_MAC_PM_TRUNC_VFIFO_FULL  0x3e
+/* enum: PM discard_vfifo_full counter. Valid for EF10 with
+ * PM_AND_RXDP_COUNTERS capability only.
+ */
+#define          MC_CMD_MAC_PM_DISCARD_VFIFO_FULL  0x3f
+/* enum: PM trunc_qbb counter. Valid for EF10 with PM_AND_RXDP_COUNTERS
+ * capability only.
+ */
+#define          MC_CMD_MAC_PM_TRUNC_QBB  0x40
+/* enum: PM discard_qbb counter. Valid for EF10 with PM_AND_RXDP_COUNTERS
+ * capability only.
+ */
+#define          MC_CMD_MAC_PM_DISCARD_QBB  0x41
+/* enum: PM discard_mapping counter. Valid for EF10 with PM_AND_RXDP_COUNTERS
+ * capability only.
+ */
+#define          MC_CMD_MAC_PM_DISCARD_MAPPING  0x42
+/* enum: RXDP counter: Number of packets dropped due to the queue being
+ * disabled. Valid for EF10 with PM_AND_RXDP_COUNTERS capability only.
+ */
+#define          MC_CMD_MAC_RXDP_Q_DISABLED_PKTS  0x43
+/* enum: RXDP counter: Number of packets dropped by the DICPU. Valid for EF10
+ * with PM_AND_RXDP_COUNTERS capability only.
+ */
+#define          MC_CMD_MAC_RXDP_DI_DROPPED_PKTS  0x45
+/* enum: RXDP counter: Number of non-host packets. Valid for EF10 with
+ * PM_AND_RXDP_COUNTERS capability only.
+ */
+#define          MC_CMD_MAC_RXDP_STREAMING_PKTS  0x46
+/* enum: RXDP counter: Number of times an emergency descriptor fetch was
+ * performed. Valid for EF10 with PM_AND_RXDP_COUNTERS capability only.
+ */
+#define          MC_CMD_MAC_RXDP_EMERGENCY_FETCH_CONDITIONS  0x47
+/* enum: RXDP counter: Number of times the DPCPU waited for an existing
+ * descriptor fetch. Valid for EF10 with PM_AND_RXDP_COUNTERS capability only.
+ */
+#define          MC_CMD_MAC_RXDP_EMERGENCY_WAIT_CONDITIONS  0x48
+/* enum: Start of GMAC stats buffer space, for Siena only. */
+#define          MC_CMD_GMAC_DMABUF_START  0x40
+/* enum: End of GMAC stats buffer space, for Siena only. */
+#define          MC_CMD_GMAC_DMABUF_END    0x5f
 #define          MC_CMD_MAC_GENERATION_END 0x60 /* enum */
 #define          MC_CMD_MAC_NSTATS  0x61 /* enum */
 
@@ -5065,6 +5115,8 @@
 #define        MC_CMD_GET_CAPABILITIES_OUT_RX_BATCHING_WIDTH 1
 #define        MC_CMD_GET_CAPABILITIES_OUT_MCAST_FILTER_CHAINING_LBN 26
 #define        MC_CMD_GET_CAPABILITIES_OUT_MCAST_FILTER_CHAINING_WIDTH 1
+#define        MC_CMD_GET_CAPABILITIES_OUT_PM_AND_RXDP_COUNTERS_LBN 27
+#define        MC_CMD_GET_CAPABILITIES_OUT_PM_AND_RXDP_COUNTERS_WIDTH 1
 /* RxDPCPU firmware id. */
 #define       MC_CMD_GET_CAPABILITIES_OUT_RX_DPCPU_FW_ID_OFST 4
 #define       MC_CMD_GET_CAPABILITIES_OUT_RX_DPCPU_FW_ID_LEN 2
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index e7dbd2d..9826594 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -469,8 +469,7 @@
  * @count: Length of the @desc array
  * @mask: Bitmask of which elements of @desc are enabled
  * @stats: Buffer to update with the converted statistics.  The length
- *	of this array must be at least the number of set bits in the
- *	first @count bits of @mask.
+ *	of this array must be at least @count.
  * @dma_buf: DMA buffer containing hardware statistics
  * @accumulate: If set, the converted values will be added rather than
  *	directly stored to the corresponding elements of @stats
@@ -503,11 +502,9 @@
 			}
 
 			if (accumulate)
-				*stats += val;
+				stats[index] += val;
 			else
-				*stats = val;
+				stats[index] = val;
 		}
-
-		++stats;
 	}
 }
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index fda29d3..890bbbe 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -386,6 +386,18 @@
 	EF10_STAT_rx_align_error,
 	EF10_STAT_rx_length_error,
 	EF10_STAT_rx_nodesc_drops,
+	EF10_STAT_rx_pm_trunc_bb_overflow,
+	EF10_STAT_rx_pm_discard_bb_overflow,
+	EF10_STAT_rx_pm_trunc_vfifo_full,
+	EF10_STAT_rx_pm_discard_vfifo_full,
+	EF10_STAT_rx_pm_trunc_qbb,
+	EF10_STAT_rx_pm_discard_qbb,
+	EF10_STAT_rx_pm_discard_mapping,
+	EF10_STAT_rx_dp_q_disabled_packets,
+	EF10_STAT_rx_dp_di_dropped_packets,
+	EF10_STAT_rx_dp_streaming_packets,
+	EF10_STAT_rx_dp_emerg_fetch,
+	EF10_STAT_rx_dp_emerg_wait,
 	EF10_STAT_COUNT
 };
 
diff --git a/drivers/net/ethernet/smsc/smc9194.c b/drivers/net/ethernet/smsc/smc9194.c
index e85c2e7..afd9873 100644
--- a/drivers/net/ethernet/smsc/smc9194.c
+++ b/drivers/net/ethernet/smsc/smc9194.c
@@ -95,14 +95,6 @@
 #define USE_32_BIT 1
 #endif
 
-#if defined(__H8300H__) || defined(__H8300S__)
-#define NO_AUTOPROBE
-#undef insl
-#undef outsl
-#define insl(a,b,l)  io_insl_noswap(a,b,l)
-#define outsl(a,b,l) io_outsl_noswap(a,b,l)
-#endif
-
 /*
  .the SMC9194 can be at any of the following port addresses.  To change,
  .for a slightly different card, you can add it to the array.  Keep in
@@ -114,12 +106,6 @@
 	unsigned int irq;
 };
 
-#if defined(CONFIG_H8S_EDOSK2674)
-static struct devlist smc_devlist[] __initdata = {
-	{.port = 0xf80000, .irq = 16},
-	{.port = 0,        .irq = 0 },
-};
-#else
 static struct devlist smc_devlist[] __initdata = {
 	{.port = 0x200, .irq = 0},
 	{.port = 0x220, .irq = 0},
@@ -139,7 +125,6 @@
 	{.port = 0x3E0, .irq = 0},
 	{.port = 0,     .irq = 0},
 };
-#endif
 /*
  . Wait time for memory to be free.  This probably shouldn't be
  . tuned that much, as waiting for this means nothing else happens
@@ -651,11 +636,7 @@
 #ifdef USE_32_BIT
 	if ( length & 0x2  ) {
 		outsl(ioaddr + DATA_1, buf,  length >> 2 );
-#if !defined(__H8300H__) && !defined(__H8300S__)
 		outw( *((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_1);
-#else
-		ctrl_outw( *((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +DATA_1);
-#endif
 	}
 	else
 		outsl(ioaddr + DATA_1, buf,  length >> 2 );
@@ -899,7 +880,6 @@
 		retval = -ENODEV;
 		goto err_out;
 	}
-#if !defined(CONFIG_H8S_EDOSK2674)
 	/* well, we've already written once, so hopefully another time won't
  	   hurt.  This time, I need to switch the bank register to bank 1,
 	   so I can access the base address register */
@@ -914,10 +894,6 @@
 		retval = -ENODEV;
 		goto err_out;
 	}
-#else
-	(void)base_address_register; /* Warning suppression */
-#endif
-
 
 	/*  check if the revision register is something that I recognize.
 	    These might need to be added to later, as future revisions
diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h
index 5730fe2..98eedb9 100644
--- a/drivers/net/ethernet/smsc/smc91x.h
+++ b/drivers/net/ethernet/smsc/smc91x.h
@@ -1124,8 +1124,7 @@
 			void __iomem *__ioaddr = ioaddr;		\
 			if (__len >= 2 && (unsigned long)__ptr & 2) {	\
 				__len -= 2;				\
-				SMC_outw(*(u16 *)__ptr, ioaddr,		\
-					DATA_REG(lp));		\
+				SMC_outsw(ioaddr, DATA_REG(lp), __ptr, 1); \
 				__ptr += 2;				\
 			}						\
 			if (SMC_CAN_USE_DATACS && lp->datacs)		\
@@ -1133,8 +1132,7 @@
 			SMC_outsl(__ioaddr, DATA_REG(lp), __ptr, __len>>2); \
 			if (__len & 2) {				\
 				__ptr += (__len & ~3);			\
-				SMC_outw(*((u16 *)__ptr), ioaddr,	\
-					 DATA_REG(lp));		\
+				SMC_outsw(ioaddr, DATA_REG(lp), __ptr, 1); \
 			}						\
 		} else if (SMC_16BIT(lp))				\
 			SMC_outsw(ioaddr, DATA_REG(lp), p, (l) >> 1);	\
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 79974e3..cc3ce55 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -639,13 +639,6 @@
 static irqreturn_t cpsw_interrupt(int irq, void *dev_id)
 {
 	struct cpsw_priv *priv = dev_id;
-	u32 rx, tx, rx_thresh;
-
-	rx_thresh = __raw_readl(&priv->wr_regs->rx_thresh_stat);
-	rx = __raw_readl(&priv->wr_regs->rx_stat);
-	tx = __raw_readl(&priv->wr_regs->tx_stat);
-	if (!rx_thresh && !rx && !tx)
-		return IRQ_NONE;
 
 	cpsw_intr_disable(priv);
 	if (priv->irq_enabled == true) {
@@ -1169,9 +1162,9 @@
 		}
 	}
 
+	napi_enable(&priv->napi);
 	cpdma_ctlr_start(priv->dma);
 	cpsw_intr_enable(priv);
-	napi_enable(&priv->napi);
 	cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_RX);
 	cpdma_ctlr_eoi(priv->dma, CPDMA_EOI_TX);
 
@@ -1771,8 +1764,8 @@
 	}
 	data->mac_control = prop;
 
-	if (!of_property_read_u32(node, "dual_emac", &prop))
-		data->dual_emac = prop;
+	if (of_property_read_bool(node, "dual_emac"))
+		data->dual_emac = 1;
 
 	/*
 	 * Populate all the child nodes here...
@@ -1782,7 +1775,7 @@
 	if (ret)
 		pr_warn("Doesn't have any child node\n");
 
-	for_each_node_by_name(slave_node, "slave") {
+	for_each_child_of_node(node, slave_node) {
 		struct cpsw_slave_data *slave_data = data->slave_data + i;
 		const void *mac_addr = NULL;
 		u32 phyid;
@@ -1791,6 +1784,10 @@
 		struct device_node *mdio_node;
 		struct platform_device *mdio;
 
+		/* This is no slave child node, continue */
+		if (strcmp(slave_node->name, "slave"))
+			continue;
+
 		parp = of_get_property(slave_node, "phy_id", &lenp);
 		if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) {
 			pr_err("Missing slave[%d] phy_id property\n", i);
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 67df09e..6a32ef9d 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -876,8 +876,7 @@
 		    netdev_mc_count(ndev) > EMAC_DEF_MAX_MULTICAST_ADDRESSES) {
 			mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST);
 			emac_add_mcast(priv, EMAC_ALL_MULTI_SET, NULL);
-		}
-		if (!netdev_mc_empty(ndev)) {
+		} else if (!netdev_mc_empty(ndev)) {
 			struct netdev_hw_addr *ha;
 
 			mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST);
diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index 0029148..1f23641 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -36,6 +36,7 @@
 #include <linux/netdevice.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_irq.h>
 #include <linux/of_mdio.h>
 #include <linux/of_platform.h>
 #include <linux/of_address.h>
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index 0721e72..5af1c3e 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -975,7 +975,6 @@
 			return -EINVAL;		/* Cannot change this parameter when up */
 		if ((ym = kmalloc(sizeof(struct yamdrv_ioctl_mcs), GFP_KERNEL)) == NULL)
 			return -ENOBUFS;
-		ym->bitrate = 9600;
 		if (copy_from_user(ym, ifr->ifr_data, sizeof(struct yamdrv_ioctl_mcs))) {
 			kfree(ym);
 			return -EFAULT;
diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c
index 42e6dee..0632d34 100644
--- a/drivers/net/ieee802154/mrf24j40.c
+++ b/drivers/net/ieee802154/mrf24j40.c
@@ -82,7 +82,6 @@
 
 	struct mutex buffer_mutex; /* only used to protect buf */
 	struct completion tx_complete;
-	struct work_struct irqwork;
 	u8 *buf; /* 3 bytes. Used for SPI single-register transfers. */
 };
 
@@ -344,6 +343,8 @@
 	if (ret)
 		goto err;
 
+	INIT_COMPLETION(devrec->tx_complete);
+
 	/* Set TXNTRIG bit of TXNCON to send packet */
 	ret = read_short_reg(devrec, REG_TXNCON, &val);
 	if (ret)
@@ -354,8 +355,6 @@
 		val |= 0x4;
 	write_short_reg(devrec, REG_TXNCON, val);
 
-	INIT_COMPLETION(devrec->tx_complete);
-
 	/* Wait for the device to send the TX complete interrupt. */
 	ret = wait_for_completion_interruptible_timeout(
 						&devrec->tx_complete,
@@ -590,17 +589,6 @@
 static irqreturn_t mrf24j40_isr(int irq, void *data)
 {
 	struct mrf24j40 *devrec = data;
-
-	disable_irq_nosync(irq);
-
-	schedule_work(&devrec->irqwork);
-
-	return IRQ_HANDLED;
-}
-
-static void mrf24j40_isrwork(struct work_struct *work)
-{
-	struct mrf24j40 *devrec = container_of(work, struct mrf24j40, irqwork);
 	u8 intstat;
 	int ret;
 
@@ -618,7 +606,7 @@
 		mrf24j40_handle_rx(devrec);
 
 out:
-	enable_irq(devrec->spi->irq);
+	return IRQ_HANDLED;
 }
 
 static int mrf24j40_probe(struct spi_device *spi)
@@ -642,7 +630,6 @@
 
 	mutex_init(&devrec->buffer_mutex);
 	init_completion(&devrec->tx_complete);
-	INIT_WORK(&devrec->irqwork, mrf24j40_isrwork);
 	devrec->spi = spi;
 	spi_set_drvdata(spi, devrec);
 
@@ -688,11 +675,12 @@
 	val &= ~0x3; /* Clear RX mode (normal) */
 	write_short_reg(devrec, REG_RXMCR, val);
 
-	ret = request_irq(spi->irq,
-			  mrf24j40_isr,
-			  IRQF_TRIGGER_FALLING,
-			  dev_name(&spi->dev),
-			  devrec);
+	ret = request_threaded_irq(spi->irq,
+				   NULL,
+				   mrf24j40_isr,
+				   IRQF_TRIGGER_LOW|IRQF_ONESHOT,
+				   dev_name(&spi->dev),
+				   devrec);
 
 	if (ret) {
 		dev_err(printdev(devrec), "Unable to get IRQ");
@@ -721,7 +709,6 @@
 	dev_dbg(printdev(devrec), "remove\n");
 
 	free_irq(spi->irq, devrec);
-	flush_work(&devrec->irqwork); /* TODO: Is this the right call? */
 	ieee802154_unregister_device(devrec->dev);
 	ieee802154_free_device(devrec->dev);
 	/* TODO: Will ieee802154_free_device() wait until ->xmit() is
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index adeee61..c9a1592 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -310,6 +310,7 @@
 			     const char *buf,
 			     size_t count)
 {
+	unsigned long flags;
 	int enabled;
 	int err;
 
@@ -324,9 +325,7 @@
 		return -EINVAL;
 	}
 
-	mutex_lock(&nt->mutex);
 	if (enabled) {	/* 1 */
-
 		/*
 		 * Skip netpoll_parse_options() -- all the attributes are
 		 * already configured via configfs. Just print them out.
@@ -334,19 +333,22 @@
 		netpoll_print_options(&nt->np);
 
 		err = netpoll_setup(&nt->np);
-		if (err) {
-			mutex_unlock(&nt->mutex);
+		if (err)
 			return err;
-		}
 
 		printk(KERN_INFO "netconsole: network logging started\n");
-
 	} else {	/* 0 */
+		/* We need to disable the netconsole before cleaning it up
+		 * otherwise we might end up in write_msg() with
+		 * nt->np.dev == NULL and nt->enabled == 1
+		 */
+		spin_lock_irqsave(&target_list_lock, flags);
+		nt->enabled = 0;
+		spin_unlock_irqrestore(&target_list_lock, flags);
 		netpoll_cleanup(&nt->np);
 	}
 
 	nt->enabled = enabled;
-	mutex_unlock(&nt->mutex);
 
 	return strnlen(buf, count);
 }
@@ -563,8 +565,10 @@
 	struct netconsole_target_attr *na =
 		container_of(attr, struct netconsole_target_attr, attr);
 
+	mutex_lock(&nt->mutex);
 	if (na->store)
 		ret = na->store(nt, buf, count);
+	mutex_unlock(&nt->mutex);
 
 	return ret;
 }
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index dc92097..56178761 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -438,17 +438,19 @@
 
 	return sprintf(buf, "0x%.8lx\n", (unsigned long)phydev->phy_id);
 }
+static DEVICE_ATTR_RO(phy_id);
 
-static struct device_attribute mdio_dev_attrs[] = {
-	__ATTR_RO(phy_id),
-	__ATTR_NULL
+static struct attribute *mdio_dev_attrs[] = {
+	&dev_attr_phy_id.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(mdio_dev);
 
 struct bus_type mdio_bus_type = {
 	.name		= "mdio_bus",
 	.match		= mdio_bus_match,
 	.pm		= MDIO_BUS_PM_OPS,
-	.dev_attrs	= mdio_dev_attrs,
+	.dev_groups	= mdio_dev_groups,
 };
 EXPORT_SYMBOL(mdio_bus_type);
 
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 807815f..7cb105c 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1293,7 +1293,8 @@
 	if (unlikely(!noblock))
 		add_wait_queue(&tfile->wq.wait, &wait);
 	while (len) {
-		current->state = TASK_INTERRUPTIBLE;
+		if (unlikely(!noblock))
+			current->state = TASK_INTERRUPTIBLE;
 
 		/* Read frames from the queue */
 		if (!(skb = skb_dequeue(&tfile->socket.sk->sk_receive_queue))) {
@@ -1320,9 +1321,10 @@
 		break;
 	}
 
-	current->state = TASK_RUNNING;
-	if (unlikely(!noblock))
+	if (unlikely(!noblock)) {
+		current->state = TASK_RUNNING;
 		remove_wait_queue(&tfile->wq.wait, &wait);
+	}
 
 	return ret;
 }
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index 3569293..8e8d0fc 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -36,8 +36,8 @@
 #define AX_RXHDR_L4_TYPE_TCP			16
 #define AX_RXHDR_L3CSUM_ERR			2
 #define AX_RXHDR_L4CSUM_ERR			1
-#define AX_RXHDR_CRC_ERR			((u32)BIT(31))
-#define AX_RXHDR_DROP_ERR			((u32)BIT(30))
+#define AX_RXHDR_CRC_ERR			((u32)BIT(29))
+#define AX_RXHDR_DROP_ERR			((u32)BIT(31))
 #define AX_ACCESS_MAC				0x01
 #define AX_ACCESS_PHY				0x02
 #define AX_ACCESS_EEPROM			0x04
@@ -78,7 +78,6 @@
 #define AX_MEDIUM_STATUS_MODE			0x22
 	#define AX_MEDIUM_GIGAMODE	0x01
 	#define AX_MEDIUM_FULL_DUPLEX	0x02
-	#define AX_MEDIUM_ALWAYS_ONE	0x04
 	#define AX_MEDIUM_EN_125MHZ	0x08
 	#define AX_MEDIUM_RXFLOW_CTRLEN	0x10
 	#define AX_MEDIUM_TXFLOW_CTRLEN	0x20
@@ -1065,8 +1064,8 @@
 
 	/* Configure default medium type => giga */
 	*tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN |
-		 AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_ALWAYS_ONE |
-		 AX_MEDIUM_FULL_DUPLEX | AX_MEDIUM_GIGAMODE;
+		 AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_FULL_DUPLEX |
+		 AX_MEDIUM_GIGAMODE;
 	ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
 			  2, 2, tmp16);
 
@@ -1225,7 +1224,7 @@
 	}
 
 	mode = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN |
-	       AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_ALWAYS_ONE;
+	       AX_MEDIUM_RXFLOW_CTRLEN;
 
 	ax88179_read_cmd(dev, AX_ACCESS_MAC, PHYSICAL_LINK_STATUS,
 			 1, 1, &link_sts);
@@ -1339,8 +1338,8 @@
 
 	/* Configure default medium type => giga */
 	*tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN |
-		 AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_ALWAYS_ONE |
-		 AX_MEDIUM_FULL_DUPLEX | AX_MEDIUM_GIGAMODE;
+		 AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_FULL_DUPLEX |
+		 AX_MEDIUM_GIGAMODE;
 	ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE,
 			  2, 2, tmp16);
 
@@ -1406,6 +1405,19 @@
 	.tx_fixup = ax88179_tx_fixup,
 };
 
+static const struct driver_info samsung_info = {
+	.description = "Samsung USB Ethernet Adapter",
+	.bind = ax88179_bind,
+	.unbind = ax88179_unbind,
+	.status = ax88179_status,
+	.link_reset = ax88179_link_reset,
+	.reset = ax88179_reset,
+	.stop = ax88179_stop,
+	.flags = FLAG_ETHER | FLAG_FRAMING_AX,
+	.rx_fixup = ax88179_rx_fixup,
+	.tx_fixup = ax88179_tx_fixup,
+};
+
 static const struct usb_device_id products[] = {
 {
 	/* ASIX AX88179 10/100/1000 */
@@ -1418,7 +1430,11 @@
 }, {
 	/* Sitecom USB 3.0 to Gigabit Adapter */
 	USB_DEVICE(0x0df6, 0x0072),
-	.driver_info = (unsigned long) &sitecom_info,
+	.driver_info = (unsigned long)&sitecom_info,
+}, {
+	/* Samsung USB Ethernet Adapter */
+	USB_DEVICE(0x04e8, 0xa100),
+	.driver_info = (unsigned long)&samsung_info,
 },
 	{ },
 };
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 3d6aaf7..818ce90 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -714,6 +714,7 @@
 	{QMI_FIXED_INTF(0x2357, 0x0201, 4)},	/* TP-LINK HSUPA Modem MA180 */
 	{QMI_FIXED_INTF(0x2357, 0x9000, 4)},	/* TP-LINK MA260 */
 	{QMI_FIXED_INTF(0x1bc7, 0x1200, 5)},	/* Telit LE920 */
+	{QMI_FIXED_INTF(0x0b3c, 0xc005, 6)},    /* Olivetti Olicard 200 */
 	{QMI_FIXED_INTF(0x1e2d, 0x0060, 4)},	/* Cinterion PLxx */
 
 	/* 4. Gobi 1000 devices */
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index bf94e10..90a429b 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1688,8 +1688,10 @@
 	if (dev->can_dma_sg && !(info->flags & FLAG_SEND_ZLP) &&
 		!(info->flags & FLAG_MULTI_PACKET)) {
 		dev->padding_pkt = kzalloc(1, GFP_KERNEL);
-		if (!dev->padding_pkt)
+		if (!dev->padding_pkt) {
+			status = -ENOMEM;
 			goto out4;
+		}
 	}
 
 	status = register_netdev (net);
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index defec2b..bbc9cb8 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -938,7 +938,9 @@
 		return -EINVAL;
 	} else {
 		vi->curr_queue_pairs = queue_pairs;
-		schedule_delayed_work(&vi->refill, 0);
+		/* virtnet_open() will refill when device is going to up. */
+		if (dev->flags & IFF_UP)
+			schedule_delayed_work(&vi->refill, 0);
 	}
 
 	return 0;
@@ -1128,6 +1130,7 @@
 	default:
 		break;
 	}
+
 	return NOTIFY_OK;
 }
 
@@ -1689,6 +1692,8 @@
 	struct virtnet_info *vi = vdev->priv;
 	int i;
 
+	unregister_hotcpu_notifier(&vi->nb);
+
 	/* Prevent config work handler from accessing the device */
 	mutex_lock(&vi->config_lock);
 	vi->config_enable = false;
@@ -1733,7 +1738,13 @@
 	vi->config_enable = true;
 	mutex_unlock(&vi->config_lock);
 
+	rtnl_lock();
 	virtnet_set_queues(vi, vi->curr_queue_pairs);
+	rtnl_unlock();
+
+	err = register_hotcpu_notifier(&vi->nb);
+	if (err)
+		return err;
 
 	return 0;
 }
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index 3f0c4f2..bcfff0d 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -1972,6 +1972,7 @@
 	}
 
 	i = port->index;
+	memset(&sync, 0, sizeof(sync));
 	sync.clock_rate = FST_RDL(card, portConfig[i].lineSpeed);
 	/* Lucky card and linux use same encoding here */
 	sync.clock_type = FST_RDB(card, portConfig[i].internalClock) ==
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index 5bbcb5e..388ddf6 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -148,10 +148,6 @@
 static int  emancipate( struct net_device * );
 #endif
 
-#ifdef __i386__
-#define ASM_CRC 1
-#endif
-
 static const char  version[] =
 	"Granch SBNI12 driver ver 5.0.1  Jun 22 2001  Denis I.Timofeev.\n";
 
@@ -1551,88 +1547,6 @@
 
 /* -------------------------------------------------------------------------- */
 
-#ifdef ASM_CRC
-
-static u32
-calc_crc32( u32  crc,  u8  *p,  u32  len )
-{
-	register u32  _crc;
-	_crc = crc;
-	
-	__asm__ __volatile__ (
-		"xorl	%%ebx, %%ebx\n"
-		"movl	%2, %%esi\n" 
-		"movl	%3, %%ecx\n" 
-		"movl	$crc32tab, %%edi\n"
-		"shrl	$2, %%ecx\n"
-		"jz	1f\n"
-
-		".align 4\n"
-	"0:\n"
-		"movb	%%al, %%bl\n"
-		"movl	(%%esi), %%edx\n"
-		"shrl	$8, %%eax\n"
-		"xorb	%%dl, %%bl\n"
-		"shrl	$8, %%edx\n"
-		"xorl	(%%edi,%%ebx,4), %%eax\n"
-
-		"movb	%%al, %%bl\n"
-		"shrl	$8, %%eax\n"
-		"xorb	%%dl, %%bl\n"
-		"shrl	$8, %%edx\n"
-		"xorl	(%%edi,%%ebx,4), %%eax\n"
-
-		"movb	%%al, %%bl\n"
-		"shrl	$8, %%eax\n"
-		"xorb	%%dl, %%bl\n"
-		"movb	%%dh, %%dl\n" 
-		"xorl	(%%edi,%%ebx,4), %%eax\n"
-
-		"movb	%%al, %%bl\n"
-		"shrl	$8, %%eax\n"
-		"xorb	%%dl, %%bl\n"
-		"addl	$4, %%esi\n"
-		"xorl	(%%edi,%%ebx,4), %%eax\n"
-
-		"decl	%%ecx\n"
-		"jnz	0b\n"
-
-	"1:\n"
-		"movl	%3, %%ecx\n"
-		"andl	$3, %%ecx\n"
-		"jz	2f\n"
-
-		"movb	%%al, %%bl\n"
-		"shrl	$8, %%eax\n"
-		"xorb	(%%esi), %%bl\n"
-		"xorl	(%%edi,%%ebx,4), %%eax\n"
-
-		"decl	%%ecx\n"
-		"jz	2f\n"
-
-		"movb	%%al, %%bl\n"
-		"shrl	$8, %%eax\n"
-		"xorb	1(%%esi), %%bl\n"
-		"xorl	(%%edi,%%ebx,4), %%eax\n"
-
-		"decl	%%ecx\n"
-		"jz	2f\n"
-
-		"movb	%%al, %%bl\n"
-		"shrl	$8, %%eax\n"
-		"xorb	2(%%esi), %%bl\n"
-		"xorl	(%%edi,%%ebx,4), %%eax\n"
-	"2:\n"
-		: "=a" (_crc)
-		: "0" (_crc), "g" (p), "g" (len)
-		: "bx", "cx", "dx", "si", "di"
-	);
-
-	return  _crc;
-}
-
-#else	/* ASM_CRC */
-
 static u32
 calc_crc32( u32  crc,  u8  *p,  u32  len )
 {
@@ -1642,9 +1556,6 @@
 	return  crc;
 }
 
-#endif	/* ASM_CRC */
-
-
 static u32  crc32tab[] __attribute__ ((aligned(8))) = {
 	0xD202EF8D,  0xA505DF1B,  0x3C0C8EA1,  0x4B0BBE37,
 	0xD56F2B94,  0xA2681B02,  0x3B614AB8,  0x4C667A2E,
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index 6a24a5a..4c0a697 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -355,6 +355,7 @@
 			ifr->ifr_settings.size = size; /* data size wanted */
 			return -ENOBUFS;
 		}
+		memset(&line, 0, sizeof(line));
 		line.clock_type = get_status(port)->clocking;
 		line.clock_rate = 0;
 		line.loopback = 0;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index e4f6590..709301f 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -208,6 +208,7 @@
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	unsigned long flags;
+	int i;
 
 	if (ath_startrecv(sc) != 0) {
 		ath_err(common, "Unable to restart recv logic\n");
@@ -235,6 +236,15 @@
 		}
 	work:
 		ath_restart_work(sc);
+
+		for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+			if (!ATH_TXQ_SETUP(sc, i))
+				continue;
+
+			spin_lock_bh(&sc->tx.txq[i].axq_lock);
+			ath_txq_schedule(sc, &sc->tx.txq[i]);
+			spin_unlock_bh(&sc->tx.txq[i].axq_lock);
+		}
 	}
 
 	ieee80211_wake_queues(sc->hw);
@@ -539,21 +549,10 @@
 
 static int ath_reset(struct ath_softc *sc)
 {
-	int i, r;
+	int r;
 
 	ath9k_ps_wakeup(sc);
-
 	r = ath_reset_internal(sc, NULL);
-
-	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
-		if (!ATH_TXQ_SETUP(sc, i))
-			continue;
-
-		spin_lock_bh(&sc->tx.txq[i].axq_lock);
-		ath_txq_schedule(sc, &sc->tx.txq[i]);
-		spin_unlock_bh(&sc->tx.txq[i].axq_lock);
-	}
-
 	ath9k_ps_restore(sc);
 
 	return r;
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 5ac713d..dd30452 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1969,15 +1969,18 @@
 static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
 			       struct ath_atx_tid *tid, struct sk_buff *skb)
 {
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 	struct ath_frame_info *fi = get_frame_info(skb);
 	struct list_head bf_head;
-	struct ath_buf *bf;
-
-	bf = fi->bf;
+	struct ath_buf *bf = fi->bf;
 
 	INIT_LIST_HEAD(&bf_head);
 	list_add_tail(&bf->list, &bf_head);
 	bf->bf_state.bf_type = 0;
+	if (tid && (tx_info->flags & IEEE80211_TX_CTL_AMPDU)) {
+		bf->bf_state.bf_type = BUF_AMPDU;
+		ath_tx_addto_baw(sc, tid, bf);
+	}
 
 	bf->bf_next = NULL;
 	bf->bf_lastbf = bf;
diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c
index 899cad3..755a0c8 100644
--- a/drivers/net/wireless/cw1200/cw1200_spi.c
+++ b/drivers/net/wireless/cw1200/cw1200_spi.c
@@ -237,7 +237,9 @@
 	struct hwbus_priv *self = dev_id;
 
 	if (self->core) {
+		cw1200_spi_lock(self);
 		cw1200_irq_handler(self->core);
+		cw1200_spi_unlock(self);
 		return IRQ_HANDLED;
 	} else {
 		return IRQ_NONE;
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 30d45e2..8ac305b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -240,6 +240,12 @@
 	.ht_params = &iwl6000_ht_params,
 };
 
+const struct iwl_cfg iwl6035_2agn_sff_cfg = {
+	.name = "Intel(R) Centrino(R) Ultimate-N 6235 AGN",
+	IWL_DEVICE_6035,
+	.ht_params = &iwl6000_ht_params,
+};
+
 const struct iwl_cfg iwl1030_bgn_cfg = {
 	.name = "Intel(R) Centrino(R) Wireless-N 1030 BGN",
 	IWL_DEVICE_6030,
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h
index e4d370b..b03c25e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/iwlwifi/iwl-config.h
@@ -280,6 +280,7 @@
 extern const struct iwl_cfg iwl2000_2bgn_d_cfg;
 extern const struct iwl_cfg iwl2030_2bgn_cfg;
 extern const struct iwl_cfg iwl6035_2agn_cfg;
+extern const struct iwl_cfg iwl6035_2agn_sff_cfg;
 extern const struct iwl_cfg iwl105_bgn_cfg;
 extern const struct iwl_cfg iwl105_bgn_d_cfg;
 extern const struct iwl_cfg iwl135_bgn_cfg;
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index dd57a36..80b4750 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -601,8 +601,10 @@
 {
 	int ret;
 
-	WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE,
-		  "%s bad state = %d", __func__, trans->state);
+	if (trans->state != IWL_TRANS_FW_ALIVE) {
+		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+		return -EIO;
+	}
 
 	if (!(cmd->flags & CMD_ASYNC))
 		lock_map_acquire_read(&trans->sync_cmd_lockdep_map);
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index 21407a3..d58e393 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -273,7 +273,10 @@
 		if (!mvmvif->queue_params[ac].uapsd)
 			continue;
 
-		cmd->flags |= cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
+		if (mvm->cur_ucode != IWL_UCODE_WOWLAN)
+			cmd->flags |=
+				cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
+
 		cmd->uapsd_ac_flags |= BIT(ac);
 
 		/* QNDP TID - the highest TID with no admission control */
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index 9a7ab84..621fb71 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -394,6 +394,11 @@
 			return false;
 		}
 
+		/*
+		 * If scan cannot be aborted, it means that we had a
+		 * SCAN_COMPLETE_NOTIFICATION in the pipe and it called
+		 * ieee80211_scan_completed already.
+		 */
 		IWL_DEBUG_SCAN(mvm, "Scan cannot be aborted, exit now: %d\n",
 			       *resp);
 		return true;
@@ -417,14 +422,19 @@
 					       SCAN_COMPLETE_NOTIFICATION };
 	int ret;
 
+	if (mvm->scan_status == IWL_MVM_SCAN_NONE)
+		return;
+
 	iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_abort,
 				   scan_abort_notif,
 				   ARRAY_SIZE(scan_abort_notif),
 				   iwl_mvm_scan_abort_notif, NULL);
 
-	ret = iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_CMD, CMD_SYNC, 0, NULL);
+	ret = iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_CMD,
+				   CMD_SYNC | CMD_SEND_IN_RFKILL, 0, NULL);
 	if (ret) {
 		IWL_ERR(mvm, "Couldn't send SCAN_ABORT_CMD: %d\n", ret);
+		/* mac80211's state will be cleaned in the fw_restart flow */
 		goto out_remove_notif;
 	}
 
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index dc02cb9..26108a1 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -139,13 +139,16 @@
 
 /* 6x00 Series */
 	{IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)},
+	{IWL_PCI_DEVICE(0x422B, 0x1108, iwl6000_3agn_cfg)},
 	{IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)},
+	{IWL_PCI_DEVICE(0x422B, 0x1128, iwl6000_3agn_cfg)},
 	{IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)},
 	{IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)},
 	{IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)},
 	{IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)},
+	{IWL_PCI_DEVICE(0x4238, 0x1118, iwl6000_3agn_cfg)},
 	{IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
 
@@ -153,12 +156,16 @@
 	{IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)},
 	{IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x0082, 0x1308, iwl6005_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x0082, 0x1328, iwl6005_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x0085, 0x1318, iwl6005_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
 	{IWL_PCI_DEVICE(0x0082, 0xC020, iwl6005_2agn_sff_cfg)},
 	{IWL_PCI_DEVICE(0x0085, 0xC220, iwl6005_2agn_sff_cfg)},
+	{IWL_PCI_DEVICE(0x0085, 0xC228, iwl6005_2agn_sff_cfg)},
 	{IWL_PCI_DEVICE(0x0082, 0x4820, iwl6005_2agn_d_cfg)},
 	{IWL_PCI_DEVICE(0x0082, 0x1304, iwl6005_2agn_mow1_cfg)},/* low 5GHz active */
 	{IWL_PCI_DEVICE(0x0082, 0x1305, iwl6005_2agn_mow2_cfg)},/* high 5GHz active */
@@ -240,8 +247,11 @@
 
 /* 6x35 Series */
 	{IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x088E, 0x406A, iwl6035_2agn_sff_cfg)},
 	{IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x088F, 0x426A, iwl6035_2agn_sff_cfg)},
 	{IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x088E, 0x446A, iwl6035_2agn_sff_cfg)},
 	{IWL_PCI_DEVICE(0x088E, 0x4860, iwl6035_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x088F, 0x5260, iwl6035_2agn_cfg)},
 
@@ -260,54 +270,86 @@
 #if IS_ENABLED(CONFIG_IWLMVM)
 /* 7000 Series */
 	{IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7260_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B1, 0x4072, iwl7260_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0x4170, iwl7260_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0x4060, iwl7260_2n_cfg)},
+	{IWL_PCI_DEVICE(0x08B1, 0x406A, iwl7260_2n_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0x4160, iwl7260_2n_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0x4062, iwl7260_n_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0x4162, iwl7260_n_cfg)},
 	{IWL_PCI_DEVICE(0x08B2, 0x4270, iwl7260_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B2, 0x4272, iwl7260_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B2, 0x4260, iwl7260_2n_cfg)},
+	{IWL_PCI_DEVICE(0x08B2, 0x426A, iwl7260_2n_cfg)},
 	{IWL_PCI_DEVICE(0x08B2, 0x4262, iwl7260_n_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0x4470, iwl7260_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B1, 0x4472, iwl7260_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0x4460, iwl7260_2n_cfg)},
+	{IWL_PCI_DEVICE(0x08B1, 0x446A, iwl7260_2n_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0x4462, iwl7260_n_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0x4870, iwl7260_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0x486E, iwl7260_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0x4A70, iwl7260_2ac_cfg_high_temp)},
 	{IWL_PCI_DEVICE(0x08B1, 0x4A6E, iwl7260_2ac_cfg_high_temp)},
 	{IWL_PCI_DEVICE(0x08B1, 0x4A6C, iwl7260_2ac_cfg_high_temp)},
+	{IWL_PCI_DEVICE(0x08B1, 0x4570, iwl7260_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B1, 0x4560, iwl7260_2n_cfg)},
+	{IWL_PCI_DEVICE(0x08B2, 0x4370, iwl7260_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B2, 0x4360, iwl7260_2n_cfg)},
+	{IWL_PCI_DEVICE(0x08B1, 0x5070, iwl7260_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0x4020, iwl7260_2n_cfg)},
+	{IWL_PCI_DEVICE(0x08B1, 0x402A, iwl7260_2n_cfg)},
 	{IWL_PCI_DEVICE(0x08B2, 0x4220, iwl7260_2n_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0x4420, iwl7260_2n_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0xC070, iwl7260_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B1, 0xC072, iwl7260_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0xC170, iwl7260_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0xC060, iwl7260_2n_cfg)},
+	{IWL_PCI_DEVICE(0x08B1, 0xC06A, iwl7260_2n_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0xC160, iwl7260_2n_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0xC062, iwl7260_n_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0xC162, iwl7260_n_cfg)},
+	{IWL_PCI_DEVICE(0x08B1, 0xC770, iwl7260_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B1, 0xC760, iwl7260_2n_cfg)},
 	{IWL_PCI_DEVICE(0x08B2, 0xC270, iwl7260_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B2, 0xC272, iwl7260_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B2, 0xC260, iwl7260_2n_cfg)},
+	{IWL_PCI_DEVICE(0x08B2, 0xC26A, iwl7260_n_cfg)},
 	{IWL_PCI_DEVICE(0x08B2, 0xC262, iwl7260_n_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0xC470, iwl7260_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B1, 0xC472, iwl7260_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0xC460, iwl7260_2n_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0xC462, iwl7260_n_cfg)},
+	{IWL_PCI_DEVICE(0x08B1, 0xC570, iwl7260_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B1, 0xC560, iwl7260_2n_cfg)},
+	{IWL_PCI_DEVICE(0x08B2, 0xC370, iwl7260_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B1, 0xC360, iwl7260_2n_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0xC020, iwl7260_2n_cfg)},
+	{IWL_PCI_DEVICE(0x08B1, 0xC02A, iwl7260_2n_cfg)},
 	{IWL_PCI_DEVICE(0x08B2, 0xC220, iwl7260_2n_cfg)},
 	{IWL_PCI_DEVICE(0x08B1, 0xC420, iwl7260_2n_cfg)},
 
 /* 3160 Series */
 	{IWL_PCI_DEVICE(0x08B3, 0x0070, iwl3160_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B3, 0x0072, iwl3160_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B3, 0x0170, iwl3160_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B3, 0x0172, iwl3160_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B3, 0x0060, iwl3160_2n_cfg)},
 	{IWL_PCI_DEVICE(0x08B3, 0x0062, iwl3160_n_cfg)},
 	{IWL_PCI_DEVICE(0x08B4, 0x0270, iwl3160_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B4, 0x0272, iwl3160_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B3, 0x0470, iwl3160_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B3, 0x0472, iwl3160_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B4, 0x0370, iwl3160_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B3, 0x8070, iwl3160_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B3, 0x8072, iwl3160_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B3, 0x8170, iwl3160_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B3, 0x8172, iwl3160_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B3, 0x8060, iwl3160_2n_cfg)},
 	{IWL_PCI_DEVICE(0x08B3, 0x8062, iwl3160_n_cfg)},
 	{IWL_PCI_DEVICE(0x08B4, 0x8270, iwl3160_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x08B3, 0x8470, iwl3160_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x08B3, 0x8570, iwl3160_2ac_cfg)},
 #endif /* CONFIG_IWLMVM */
 
 	{0}
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index bad95d2..c3f904d 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -1401,6 +1401,10 @@
 	spin_lock_init(&trans_pcie->reg_lock);
 	init_waitqueue_head(&trans_pcie->ucode_write_waitq);
 
+	err = pci_enable_device(pdev);
+	if (err)
+		goto out_no_pci;
+
 	if (!cfg->base_params->pcie_l1_allowed) {
 		/*
 		 * W/A - seems to solve weird behavior. We need to remove this
@@ -1412,10 +1416,6 @@
 				       PCIE_LINK_STATE_CLKPM);
 	}
 
-	err = pci_enable_device(pdev);
-	if (err)
-		goto out_no_pci;
-
 	pci_set_master(pdev);
 
 	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index f45eb29..1424335 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -1102,6 +1102,8 @@
 		 * non-AGG queue.
 		 */
 		iwl_clear_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id));
+
+		ssn = trans_pcie->txq[txq_id].q.read_ptr;
 	}
 
 	/* Place first TFD at index corresponding to start sequence number.
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index 9d7c0e6..37f873b 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -1422,13 +1422,19 @@
  */
 int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac)
 {
+	int ret = 0;
+
 	if (!priv->media_connected)
 		return 0;
 
 	switch (priv->bss_mode) {
 	case NL80211_IFTYPE_STATION:
 	case NL80211_IFTYPE_P2P_CLIENT:
-		return mwifiex_deauthenticate_infra(priv, mac);
+		ret = mwifiex_deauthenticate_infra(priv, mac);
+		if (ret)
+			cfg80211_disconnected(priv->netdev, 0, NULL, 0,
+					      GFP_KERNEL);
+		break;
 	case NL80211_IFTYPE_ADHOC:
 		return mwifiex_send_cmd_sync(priv,
 					     HostCmd_CMD_802_11_AD_HOC_STOP,
@@ -1440,7 +1446,7 @@
 		break;
 	}
 
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mwifiex_deauthenticate);
 
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index fd77833..c2b91f5 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -358,10 +358,12 @@
 		}
 	} while (true);
 
-	if ((adapter->int_status) || IS_CARD_RX_RCVD(adapter))
-		goto process_start;
-
 	spin_lock_irqsave(&adapter->main_proc_lock, flags);
+	if ((adapter->int_status) || IS_CARD_RX_RCVD(adapter)) {
+		spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
+		goto process_start;
+	}
+
 	adapter->mwifiex_processing = false;
 	spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
 
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index 8b05752..8c351f7 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -118,7 +118,8 @@
 	dev_dbg(adapter->dev,
 		"info: successfully disconnected from %pM: reason code %d\n",
 		priv->cfg_bssid, reason_code);
-	if (priv->bss_mode == NL80211_IFTYPE_STATION) {
+	if (priv->bss_mode == NL80211_IFTYPE_STATION ||
+	    priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
 		cfg80211_disconnected(priv->netdev, reason_code, NULL, 0,
 				      GFP_KERNEL);
 	}
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index 76d95de..dc49e52 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -105,13 +105,11 @@
 		goto exit_release_regions;
 	}
 
-	pci_enable_msi(pci_dev);
-
 	hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
 	if (!hw) {
 		rt2x00_probe_err("Failed to allocate hardware\n");
 		retval = -ENOMEM;
-		goto exit_disable_msi;
+		goto exit_release_regions;
 	}
 
 	pci_set_drvdata(pci_dev, hw);
@@ -152,9 +150,6 @@
 exit_free_device:
 	ieee80211_free_hw(hw);
 
-exit_disable_msi:
-	pci_disable_msi(pci_dev);
-
 exit_release_regions:
 	pci_release_regions(pci_dev);
 
@@ -179,8 +174,6 @@
 	rt2x00pci_free_reg(rt2x00dev);
 	ieee80211_free_hw(hw);
 
-	pci_disable_msi(pci_dev);
-
 	/*
 	 * Free the PCI device data.
 	 */
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
index 763cf1d..5a060e5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
@@ -343,7 +343,8 @@
 					(bool)GET_RX_DESC_PAGGR(pdesc));
 	rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
 	if (phystatus) {
-		p_drvinfo = (struct rx_fwinfo_92c *)(pdesc + RTL_RX_DESC_SIZE);
+		p_drvinfo = (struct rx_fwinfo_92c *)(skb->data +
+						     stats->rx_bufshift);
 		rtl92c_translate_rx_signal_stuff(hw, skb, stats, pdesc,
 						 p_drvinfo);
 	}
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
index 5715318..400fea1 100644
--- a/drivers/net/xen-netback/common.h
+++ b/drivers/net/xen-netback/common.h
@@ -163,6 +163,7 @@
 	unsigned long   credit_usec;
 	unsigned long   remaining_credit;
 	struct timer_list credit_timeout;
+	u64 credit_window_start;
 
 	/* Statistics */
 	unsigned long rx_gso_checksum_fixup;
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index 01bb854..459935a 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -312,8 +312,7 @@
 	vif->credit_bytes = vif->remaining_credit = ~0UL;
 	vif->credit_usec  = 0UL;
 	init_timer(&vif->credit_timeout);
-	/* Initialize 'expires' now: it's used to track the credit window. */
-	vif->credit_timeout.expires = jiffies;
+	vif->credit_window_start = get_jiffies_64();
 
 	dev->netdev_ops	= &xenvif_netdev_ops;
 	dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index f3e591c..900da4b 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1185,9 +1185,8 @@
 
 static bool tx_credit_exceeded(struct xenvif *vif, unsigned size)
 {
-	unsigned long now = jiffies;
-	unsigned long next_credit =
-		vif->credit_timeout.expires +
+	u64 now = get_jiffies_64();
+	u64 next_credit = vif->credit_window_start +
 		msecs_to_jiffies(vif->credit_usec / 1000);
 
 	/* Timer could already be pending in rare cases. */
@@ -1195,8 +1194,8 @@
 		return true;
 
 	/* Passed the point where we can replenish credit? */
-	if (time_after_eq(now, next_credit)) {
-		vif->credit_timeout.expires = now;
+	if (time_after_eq64(now, next_credit)) {
+		vif->credit_window_start = now;
 		tx_add_credit(vif);
 	}
 
@@ -1208,6 +1207,7 @@
 			tx_credit_callback;
 		mod_timer(&vif->credit_timeout,
 			  next_credit);
+		vif->credit_window_start = next_credit;
 
 		return true;
 	}
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index b45bce2..1b08d87 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -39,11 +39,15 @@
 static void connect(struct backend_info *);
 static void backend_create_xenvif(struct backend_info *be);
 static void unregister_hotplug_status_watch(struct backend_info *be);
+static void set_backend_state(struct backend_info *be,
+			      enum xenbus_state state);
 
 static int netback_remove(struct xenbus_device *dev)
 {
 	struct backend_info *be = dev_get_drvdata(&dev->dev);
 
+	set_backend_state(be, XenbusStateClosed);
+
 	unregister_hotplug_status_watch(be);
 	if (be->vif) {
 		kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 9d2009a..de6f899 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -17,6 +17,7 @@
 
 config OF_SELFTEST
 	bool "Device Tree Runtime self tests"
+	depends on OF_IRQ
 	help
 	  This option builds in test cases for the device tree infrastructure
 	  that are executed one at boot time, and the results dumped to the
@@ -74,10 +75,4 @@
 	depends on MTD
 	def_bool y
 
-config OF_RESERVED_MEM
-	depends on OF_FLATTREE && (DMA_CMA || (HAVE_GENERIC_DMA_COHERENT && HAVE_MEMBLOCK))
-	def_bool y
-	help
-	  Initialization code for DMA reserved memory
-
 endmenu # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index ed9660a..efd0510 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -9,4 +9,3 @@
 obj-$(CONFIG_OF_PCI)	+= of_pci.o
 obj-$(CONFIG_OF_PCI_IRQ)  += of_pci_irq.o
 obj-$(CONFIG_OF_MTD)	+= of_mtd.o
-obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
diff --git a/drivers/of/address.c b/drivers/of/address.c
index b55c218..4b9317b 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -489,7 +489,7 @@
 	int na, ns, pna, pns;
 	u64 result = OF_BAD_ADDR;
 
-	pr_debug("OF: ** translation for device %s **\n", dev->full_name);
+	pr_debug("OF: ** translation for device %s **\n", of_node_full_name(dev));
 
 	/* Increase refcount at current level */
 	of_node_get(dev);
@@ -504,13 +504,13 @@
 	bus->count_cells(dev, &na, &ns);
 	if (!OF_CHECK_COUNTS(na, ns)) {
 		printk(KERN_ERR "prom_parse: Bad cell count for %s\n",
-		       dev->full_name);
+		       of_node_full_name(dev));
 		goto bail;
 	}
 	memcpy(addr, in_addr, na * 4);
 
 	pr_debug("OF: bus is %s (na=%d, ns=%d) on %s\n",
-	    bus->name, na, ns, parent->full_name);
+	    bus->name, na, ns, of_node_full_name(parent));
 	of_dump_addr("OF: translating address:", addr, na);
 
 	/* Translate */
@@ -532,12 +532,12 @@
 		pbus->count_cells(dev, &pna, &pns);
 		if (!OF_CHECK_COUNTS(pna, pns)) {
 			printk(KERN_ERR "prom_parse: Bad cell count for %s\n",
-			       dev->full_name);
+			       of_node_full_name(dev));
 			break;
 		}
 
 		pr_debug("OF: parent bus is %s (na=%d, ns=%d) on %s\n",
-		    pbus->name, pna, pns, parent->full_name);
+		    pbus->name, pna, pns, of_node_full_name(parent));
 
 		/* Apply bus translation */
 		if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
@@ -626,6 +626,14 @@
 }
 EXPORT_SYMBOL(of_get_address);
 
+unsigned long __weak pci_address_to_pio(phys_addr_t address)
+{
+	if (address > IO_SPACE_LIMIT)
+		return (unsigned long)-1;
+
+	return (unsigned long) address;
+}
+
 static int __of_address_to_resource(struct device_node *dev,
 		const __be32 *addrp, u64 size, unsigned int flags,
 		const char *name, struct resource *r)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 865d3f6..f807d0e 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -74,6 +74,13 @@
 }
 EXPORT_SYMBOL(of_n_size_cells);
 
+#ifdef CONFIG_NUMA
+int __weak of_node_to_nid(struct device_node *np)
+{
+	return numa_node_id();
+}
+#endif
+
 #if defined(CONFIG_OF_DYNAMIC)
 /**
  *	of_node_get - Increment refcount of a node
@@ -265,9 +272,9 @@
 
 	ac = of_n_addr_cells(cpun);
 	cell = of_get_property(cpun, prop_name, &prop_len);
-	if (!cell)
+	if (!cell || !ac)
 		return false;
-	prop_len /= sizeof(*cell);
+	prop_len /= sizeof(*cell) * ac;
 	for (tid = 0; tid < prop_len; tid++) {
 		hwid = of_read_number(cell, ac);
 		if (arch_match_cpu_phys_id(cpu, hwid)) {
@@ -280,6 +287,31 @@
 	return false;
 }
 
+/*
+ * arch_find_n_match_cpu_physical_id - See if the given device node is
+ * for the cpu corresponding to logical cpu 'cpu'.  Return true if so,
+ * else false.  If 'thread' is non-NULL, the local thread number within the
+ * core is returned in it.
+ */
+bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun,
+					      int cpu, unsigned int *thread)
+{
+	/* Check for non-standard "ibm,ppc-interrupt-server#s" property
+	 * for thread ids on PowerPC. If it doesn't exist fallback to
+	 * standard "reg" property.
+	 */
+	if (IS_ENABLED(CONFIG_PPC) &&
+	    __of_find_n_match_cpu_property(cpun,
+					   "ibm,ppc-interrupt-server#s",
+					   cpu, thread))
+		return true;
+
+	if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread))
+		return true;
+
+	return false;
+}
+
 /**
  * of_get_cpu_node - Get device node associated with the given logical CPU
  *
@@ -300,26 +332,10 @@
  */
 struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
 {
-	struct device_node *cpun, *cpus;
+	struct device_node *cpun;
 
-	cpus = of_find_node_by_path("/cpus");
-	if (!cpus) {
-		pr_warn("Missing cpus node, bailing out\n");
-		return NULL;
-	}
-
-	for_each_child_of_node(cpus, cpun) {
-		if (of_node_cmp(cpun->type, "cpu"))
-			continue;
-		/* Check for non-standard "ibm,ppc-interrupt-server#s" property
-		 * for thread ids on PowerPC. If it doesn't exist fallback to
-		 * standard "reg" property.
-		 */
-		if (IS_ENABLED(CONFIG_PPC) &&
-			__of_find_n_match_cpu_property(cpun,
-				"ibm,ppc-interrupt-server#s", cpu, thread))
-			return cpun;
-		if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread))
+	for_each_node_by_type(cpun, "cpu") {
+		if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread))
 			return cpun;
 	}
 	return NULL;
@@ -1176,6 +1192,15 @@
 }
 EXPORT_SYMBOL_GPL(of_property_count_strings);
 
+void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
+{
+	int i;
+	printk("%s %s", msg, of_node_full_name(args->np));
+	for (i = 0; i < args->args_count; i++)
+		printk(i ? ",%08x" : ":%08x", args->args[i]);
+	printk("\n");
+}
+
 static int __of_parse_phandle_with_args(const struct device_node *np,
 					const char *list_name,
 					const char *cells_name,
@@ -1884,3 +1909,34 @@
 	return of_stdout == dn;
 }
 EXPORT_SYMBOL_GPL(of_device_is_stdout_path);
+
+/**
+ *	of_find_next_cache_node - Find a node's subsidiary cache
+ *	@np:	node of type "cpu" or "cache"
+ *
+ *	Returns a node pointer with refcount incremented, use
+ *	of_node_put() on it when done.  Caller should hold a reference
+ *	to np.
+ */
+struct device_node *of_find_next_cache_node(const struct device_node *np)
+{
+	struct device_node *child;
+	const phandle *handle;
+
+	handle = of_get_property(np, "l2-cache", NULL);
+	if (!handle)
+		handle = of_get_property(np, "next-level-cache", NULL);
+
+	if (handle)
+		return of_find_node_by_phandle(be32_to_cpup(handle));
+
+	/* OF on pmac has nodes instead of properties named "l2-cache"
+	 * beneath CPU nodes.
+	 */
+	if (!strcmp(np->type, "cpu"))
+		for_each_child_of_node(np, child)
+			if (!strcmp(child->type, "cache"))
+				return child;
+
+	return NULL;
+}
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 229dd9d..2fa024b 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -18,7 +18,6 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <linux/random.h>
 
 #include <asm/setup.h>  /* for COMMAND_LINE_SIZE */
 #ifdef CONFIG_PPC
@@ -619,12 +618,72 @@
 		return ret;
 }
 
+const char * __init of_flat_dt_get_machine_name(void)
+{
+	const char *name;
+	unsigned long dt_root = of_get_flat_dt_root();
+
+	name = of_get_flat_dt_prop(dt_root, "model", NULL);
+	if (!name)
+		name = of_get_flat_dt_prop(dt_root, "compatible", NULL);
+	return name;
+}
+
+/**
+ * of_flat_dt_match_machine - Iterate match tables to find matching machine.
+ *
+ * @default_match: A machine specific ptr to return in case of no match.
+ * @get_next_compat: callback function to return next compatible match table.
+ *
+ * Iterate through machine match tables to find the best match for the machine
+ * compatible string in the FDT.
+ */
+const void * __init of_flat_dt_match_machine(const void *default_match,
+		const void * (*get_next_compat)(const char * const**))
+{
+	const void *data = NULL;
+	const void *best_data = default_match;
+	const char *const *compat;
+	unsigned long dt_root;
+	unsigned int best_score = ~1, score = 0;
+
+	dt_root = of_get_flat_dt_root();
+	while ((data = get_next_compat(&compat))) {
+		score = of_flat_dt_match(dt_root, compat);
+		if (score > 0 && score < best_score) {
+			best_data = data;
+			best_score = score;
+		}
+	}
+	if (!best_data) {
+		const char *prop;
+		long size;
+
+		pr_err("\n unrecognized device tree list:\n[ ");
+
+		prop = of_get_flat_dt_prop(dt_root, "compatible", &size);
+		if (prop) {
+			while (size > 0) {
+				printk("'%s' ", prop);
+				size -= strlen(prop) + 1;
+				prop += strlen(prop) + 1;
+			}
+		}
+		printk("]\n\n");
+		return NULL;
+	}
+
+	pr_info("Machine model: %s\n", of_flat_dt_get_machine_name());
+
+	return best_data;
+}
+
 #ifdef CONFIG_BLK_DEV_INITRD
 /**
  * early_init_dt_check_for_initrd - Decode initrd location from flat tree
  * @node: reference to node containing initrd location ('chosen')
  */
-void __init early_init_dt_check_for_initrd(unsigned long node)
+static void __init early_init_dt_check_for_initrd(unsigned long node)
 {
 	u64 start, end;
 	unsigned long len;
@@ -642,12 +701,15 @@
 		return;
 	end = of_read_number(prop, len/4);
 
-	early_init_dt_setup_initrd_arch(start, end);
+	initrd_start = (unsigned long)__va(start);
+	initrd_end = (unsigned long)__va(end);
+	initrd_below_start_ok = 1;
+
 	pr_debug("initrd_start=0x%llx  initrd_end=0x%llx\n",
 		 (unsigned long long)start, (unsigned long long)end);
 }
 #else
-inline void early_init_dt_check_for_initrd(unsigned long node)
+static inline void early_init_dt_check_for_initrd(unsigned long node)
 {
 }
 #endif /* CONFIG_BLK_DEV_INITRD */
@@ -775,6 +837,25 @@
 }
 
 #ifdef CONFIG_HAVE_MEMBLOCK
+void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
+{
+	const u64 phys_offset = __pa(PAGE_OFFSET);
+	base &= PAGE_MASK;
+	size &= PAGE_MASK;
+	if (base + size < phys_offset) {
+		pr_warning("Ignoring memory block 0x%llx - 0x%llx\n",
+			   base, base + size);
+		return;
+	}
+	if (base < phys_offset) {
+		pr_warning("Ignoring memory range 0x%llx - 0x%llx\n",
+			   base, phys_offset);
+		size -= phys_offset - base;
+		base = phys_offset;
+	}
+	memblock_add(base, size);
+}
+
 /*
  * called from unflatten_device_tree() to bootstrap devicetree itself
  * Architectures can override this definition if memblock isn't used
@@ -785,6 +866,32 @@
 }
 #endif
 
+bool __init early_init_dt_scan(void *params)
+{
+	if (!params)
+		return false;
+
+	/* Setup flat device-tree pointer */
+	initial_boot_params = params;
+
+	/* check device tree validity */
+	if (be32_to_cpu(initial_boot_params->magic) != OF_DT_HEADER) {
+		initial_boot_params = NULL;
+		return false;
+	}
+
+	/* Retrieve various information from the /chosen node */
+	of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
+
+	/* Initialize {size,address}-cells info */
+	of_scan_flat_dt(early_init_dt_scan_root, NULL);
+
+	/* Setup memory, calling early_init_dt_add_memory_arch */
+	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
+
+	return true;
+}
+
 /**
  * unflatten_device_tree - create tree of device_nodes from flat blob
  *
@@ -802,15 +909,28 @@
 	of_alias_scan(early_init_dt_alloc_memory_arch);
 }
 
-#endif /* CONFIG_OF_EARLY_FLATTREE */
-
-/* Feed entire flattened device tree into the random pool */
-static int __init add_fdt_randomness(void)
+/**
+ * unflatten_and_copy_device_tree - copy and create tree of device_nodes from flat blob
+ *
+ * Copies and unflattens the device-tree passed by the firmware, creating the
+ * tree of struct device_node. It also fills the "name" and "type"
+ * pointers of the nodes so the normal device-tree walking functions
+ * can be used. This should only be used when the FDT memory has not been
+ * reserved such is the case when the FDT is built-in to the kernel init
+ * section. If the FDT memory is reserved already then unflatten_device_tree
+ * should be used instead.
+ */
+void __init unflatten_and_copy_device_tree(void)
 {
-	if (initial_boot_params)
-		add_device_randomness(initial_boot_params,
-				be32_to_cpu(initial_boot_params->totalsize));
+	int size = __be32_to_cpu(initial_boot_params->totalsize);
+	void *dt = early_init_dt_alloc_memory_arch(size,
+		__alignof__(struct boot_param_header));
 
-	return 0;
+	if (dt) {
+		memcpy(dt, initial_boot_params, size);
+		initial_boot_params = dt;
+	}
+	unflatten_device_tree();
 }
-core_initcall(add_fdt_randomness);
+
+#endif /* CONFIG_OF_EARLY_FLATTREE */
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 1752988..786b0b4 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -31,18 +31,17 @@
  * @dev: Device node of the device whose interrupt is to be mapped
  * @index: Index of the interrupt to map
  *
- * This function is a wrapper that chains of_irq_map_one() and
+ * This function is a wrapper that chains of_irq_parse_one() and
  * irq_create_of_mapping() to make things easier to callers
  */
 unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
 {
-	struct of_irq oirq;
+	struct of_phandle_args oirq;
 
-	if (of_irq_map_one(dev, index, &oirq))
+	if (of_irq_parse_one(dev, index, &oirq))
 		return 0;
 
-	return irq_create_of_mapping(oirq.controller, oirq.specifier,
-				     oirq.size);
+	return irq_create_of_mapping(&oirq);
 }
 EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
 
@@ -79,33 +78,34 @@
 }
 
 /**
- * of_irq_map_raw - Low level interrupt tree parsing
+ * of_irq_parse_raw - Low level interrupt tree parsing
  * @parent:	the device interrupt parent
- * @intspec:	interrupt specifier ("interrupts" property of the device)
- * @ointsize:   size of the passed in interrupt specifier
- * @addr:	address specifier (start of "reg" property of the device)
- * @out_irq:	structure of_irq filled by this function
+ * @addr:	address specifier (start of "reg" property of the device) in be32 format
+ * @out_irq:	structure of_irq updated by this function
  *
  * Returns 0 on success and a negative number on error
  *
  * This function is a low-level interrupt tree walking function. It
  * can be used to do a partial walk with synthetized reg and interrupts
  * properties, for example when resolving PCI interrupts when no device
- * node exist for the parent.
+ * node exist for the parent. It takes an interrupt specifier structure as
+ * input, walks the tree looking for any interrupt-map properties, translates
+ * the specifier for each map, and then returns the translated map.
  */
-int of_irq_map_raw(struct device_node *parent, const __be32 *intspec,
-		   u32 ointsize, const __be32 *addr, struct of_irq *out_irq)
+int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
 {
 	struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
-	const __be32 *tmp, *imap, *imask;
+	__be32 initial_match_array[MAX_PHANDLE_ARGS];
+	const __be32 *match_array = initial_match_array;
+	const __be32 *tmp, *imap, *imask, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = ~0 };
 	u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
 	int imaplen, match, i;
 
-	pr_debug("of_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n",
-		 parent->full_name, be32_to_cpup(intspec),
-		 be32_to_cpup(intspec + 1), ointsize);
+#ifdef DEBUG
+	of_print_phandle_args("of_irq_parse_raw: ", out_irq);
+#endif
 
-	ipar = of_node_get(parent);
+	ipar = of_node_get(out_irq->np);
 
 	/* First get the #interrupt-cells property of the current cursor
 	 * that tells us how to interpret the passed-in intspec. If there
@@ -126,9 +126,9 @@
 		goto fail;
 	}
 
-	pr_debug("of_irq_map_raw: ipar=%s, size=%d\n", ipar->full_name, intsize);
+	pr_debug("of_irq_parse_raw: ipar=%s, size=%d\n", of_node_full_name(ipar), intsize);
 
-	if (ointsize != intsize)
+	if (out_irq->args_count != intsize)
 		return -EINVAL;
 
 	/* Look for this #address-cells. We have to implement the old linux
@@ -147,6 +147,16 @@
 
 	pr_debug(" -> addrsize=%d\n", addrsize);
 
+	/* Range check so that the temporary buffer doesn't overflow */
+	if (WARN_ON(addrsize + intsize > MAX_PHANDLE_ARGS))
+		goto fail;
+
+	/* Precalculate the match array - this simplifies match loop */
+	for (i = 0; i < addrsize; i++)
+		initial_match_array[i] = addr ? addr[i] : 0;
+	for (i = 0; i < intsize; i++)
+		initial_match_array[addrsize + i] = cpu_to_be32(out_irq->args[i]);
+
 	/* Now start the actual "proper" walk of the interrupt tree */
 	while (ipar != NULL) {
 		/* Now check if cursor is an interrupt-controller and if it is
@@ -155,15 +165,19 @@
 		if (of_get_property(ipar, "interrupt-controller", NULL) !=
 				NULL) {
 			pr_debug(" -> got it !\n");
-			for (i = 0; i < intsize; i++)
-				out_irq->specifier[i] =
-						of_read_number(intspec +i, 1);
-			out_irq->size = intsize;
-			out_irq->controller = ipar;
 			of_node_put(old);
 			return 0;
 		}
 
+		/*
+		 * interrupt-map parsing does not work without a reg
+		 * property when #address-cells != 0
+		 */
+		if (addrsize && !addr) {
+			pr_debug(" -> no reg passed in when needed !\n");
+			goto fail;
+		}
+
 		/* Now look for an interrupt-map */
 		imap = of_get_property(ipar, "interrupt-map", &imaplen);
 		/* No interrupt map, check for an interrupt parent */
@@ -176,34 +190,16 @@
 
 		/* Look for a mask */
 		imask = of_get_property(ipar, "interrupt-map-mask", NULL);
-
-		/* If we were passed no "reg" property and we attempt to parse
-		 * an interrupt-map, then #address-cells must be 0.
-		 * Fail if it's not.
-		 */
-		if (addr == NULL && addrsize != 0) {
-			pr_debug(" -> no reg passed in when needed !\n");
-			goto fail;
-		}
+		if (!imask)
+			imask = dummy_imask;
 
 		/* Parse interrupt-map */
 		match = 0;
 		while (imaplen > (addrsize + intsize + 1) && !match) {
 			/* Compare specifiers */
 			match = 1;
-			for (i = 0; i < addrsize && match; ++i) {
-				__be32 mask = imask ? imask[i]
-						    : cpu_to_be32(0xffffffffu);
-				match = ((addr[i] ^ imap[i]) & mask) == 0;
-			}
-			for (; i < (addrsize + intsize) && match; ++i) {
-				__be32 mask = imask ? imask[i]
-						    : cpu_to_be32(0xffffffffu);
-				match =
-				   ((intspec[i-addrsize] ^ imap[i]) & mask) == 0;
-			}
-			imap += addrsize + intsize;
-			imaplen -= addrsize + intsize;
+			for (i = 0; i < (addrsize + intsize); i++, imaplen--)
+				match &= !((match_array[i] ^ *imap++) & imask[i]);
 
 			pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen);
 
@@ -237,6 +233,8 @@
 			    newintsize, newaddrsize);
 
 			/* Check for malformed properties */
+			if (WARN_ON(newaddrsize + newintsize > MAX_PHANDLE_ARGS))
+				goto fail;
 			if (imaplen < (newaddrsize + newintsize))
 				goto fail;
 
@@ -248,12 +246,18 @@
 		if (!match)
 			goto fail;
 
-		of_node_put(old);
-		old = of_node_get(newpar);
+		/*
+		 * Successfully parsed an interrrupt-map translation; copy new
+		 * interrupt specifier into the out_irq structure
+		 */
+		of_node_put(out_irq->np);
+		out_irq->np = of_node_get(newpar);
+
+		match_array = imap - newaddrsize - newintsize;
+		for (i = 0; i < newintsize; i++)
+			out_irq->args[i] = be32_to_cpup(imap - newintsize + i);
+		out_irq->args_count = intsize = newintsize;
 		addrsize = newaddrsize;
-		intsize = newintsize;
-		intspec = imap - intsize;
-		addr = intspec - addrsize;
 
 	skiplevel:
 		/* Iterate again with new parent */
@@ -264,46 +268,53 @@
 	}
  fail:
 	of_node_put(ipar);
-	of_node_put(old);
+	of_node_put(out_irq->np);
 	of_node_put(newpar);
 
 	return -EINVAL;
 }
-EXPORT_SYMBOL_GPL(of_irq_map_raw);
+EXPORT_SYMBOL_GPL(of_irq_parse_raw);
 
 /**
- * of_irq_map_one - Resolve an interrupt for a device
+ * of_irq_parse_one - Resolve an interrupt for a device
  * @device: the device whose interrupt is to be resolved
  * @index: index of the interrupt to resolve
  * @out_irq: structure of_irq filled by this function
  *
- * This function resolves an interrupt, walking the tree, for a given
- * device-tree node. It's the high level pendant to of_irq_map_raw().
+ * This function resolves an interrupt for a node by walking the interrupt tree,
+ * finding which interrupt controller node it is attached to, and returning the
+ * interrupt specifier that can be used to retrieve a Linux IRQ number.
  */
-int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq)
+int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_args *out_irq)
 {
 	struct device_node *p;
 	const __be32 *intspec, *tmp, *addr;
 	u32 intsize, intlen;
-	int res = -EINVAL;
+	int i, res = -EINVAL;
 
-	pr_debug("of_irq_map_one: dev=%s, index=%d\n", device->full_name, index);
+	pr_debug("of_irq_parse_one: dev=%s, index=%d\n", of_node_full_name(device), index);
 
 	/* OldWorld mac stuff is "special", handle out of line */
 	if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC)
-		return of_irq_map_oldworld(device, index, out_irq);
-
-	/* Get the interrupts property */
-	intspec = of_get_property(device, "interrupts", &intlen);
-	if (intspec == NULL)
-		return -EINVAL;
-	intlen /= sizeof(*intspec);
-
-	pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen);
+		return of_irq_parse_oldworld(device, index, out_irq);
 
 	/* Get the reg property (if any) */
 	addr = of_get_property(device, "reg", NULL);
 
+	/* Get the interrupts property */
+	intspec = of_get_property(device, "interrupts", &intlen);
+	if (intspec == NULL) {
+		/* Try the new-style interrupts-extended */
+		res = of_parse_phandle_with_args(device, "interrupts-extended",
+						"#interrupt-cells", index, out_irq);
+		if (res)
+			return -EINVAL;
+		return of_irq_parse_raw(addr, out_irq);
+	}
+	intlen /= sizeof(*intspec);
+
+	pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen);
+
 	/* Look for the interrupt parent. */
 	p = of_irq_find_parent(device);
 	if (p == NULL)
@@ -321,14 +332,20 @@
 	if ((index + 1) * intsize > intlen)
 		goto out;
 
-	/* Get new specifier and map it */
-	res = of_irq_map_raw(p, intspec + index * intsize, intsize,
-			     addr, out_irq);
+	/* Copy intspec into irq structure */
+	intspec += index * intsize;
+	out_irq->np = p;
+	out_irq->args_count = intsize;
+	for (i = 0; i < intsize; i++)
+		out_irq->args[i] = be32_to_cpup(intspec++);
+
+	/* Check if there are any interrupt-map translations to process */
+	res = of_irq_parse_raw(addr, out_irq);
  out:
 	of_node_put(p);
 	return res;
 }
-EXPORT_SYMBOL_GPL(of_irq_map_one);
+EXPORT_SYMBOL_GPL(of_irq_parse_one);
 
 /**
  * of_irq_to_resource - Decode a node's IRQ and return it as a resource
@@ -354,8 +371,8 @@
 					      &name);
 
 		r->start = r->end = irq;
-		r->flags = IORESOURCE_IRQ;
-		r->name = name ? name : dev->full_name;
+		r->flags = IORESOURCE_IRQ | irqd_get_trigger_type(irq_get_irq_data(irq));
+		r->name = name ? name : of_node_full_name(dev);
 	}
 
 	return irq;
@@ -368,9 +385,10 @@
  */
 int of_irq_count(struct device_node *dev)
 {
+	struct of_phandle_args irq;
 	int nr = 0;
 
-	while (of_irq_to_resource(dev, nr, NULL))
+	while (of_irq_parse_one(dev, nr, &irq) == 0)
 		nr++;
 
 	return nr;
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index e5ca008..8481996 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -2,7 +2,6 @@
 #include <linux/export.h>
 #include <linux/of.h>
 #include <linux/of_pci.h>
-#include <asm/prom.h>
 
 static inline int __of_pci_pci_compare(struct device_node *node,
 				       unsigned int data)
diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c
index 6770538..8736bc7 100644
--- a/drivers/of/of_pci_irq.c
+++ b/drivers/of/of_pci_irq.c
@@ -2,10 +2,9 @@
 #include <linux/of_pci.h>
 #include <linux/of_irq.h>
 #include <linux/export.h>
-#include <asm/prom.h>
 
 /**
- * of_irq_map_pci - Resolve the interrupt for a PCI device
+ * of_irq_parse_pci - Resolve the interrupt for a PCI device
  * @pdev:       the device whose interrupt is to be resolved
  * @out_irq:    structure of_irq filled by this function
  *
@@ -15,7 +14,7 @@
  * PCI tree until an device-node is found, at which point it will finish
  * resolving using the OF tree walking.
  */
-int of_irq_map_pci(const struct pci_dev *pdev, struct of_irq *out_irq)
+int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq)
 {
 	struct device_node *dn, *ppnode;
 	struct pci_dev *ppdev;
@@ -30,7 +29,7 @@
 	 */
 	dn = pci_device_to_OF_node(pdev);
 	if (dn) {
-		rc = of_irq_map_one(dn, 0, out_irq);
+		rc = of_irq_parse_one(dn, 0, out_irq);
 		if (!rc)
 			return rc;
 	}
@@ -85,9 +84,37 @@
 		pdev = ppdev;
 	}
 
+	out_irq->np = ppnode;
+	out_irq->args_count = 1;
+	out_irq->args[0] = lspec;
 	lspec_be = cpu_to_be32(lspec);
 	laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
-	laddr[1]  = laddr[2] = cpu_to_be32(0);
-	return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq);
+	laddr[1] = laddr[2] = cpu_to_be32(0);
+	return of_irq_parse_raw(laddr, out_irq);
 }
-EXPORT_SYMBOL_GPL(of_irq_map_pci);
+EXPORT_SYMBOL_GPL(of_irq_parse_pci);
+
+/**
+ * of_irq_parse_and_map_pci() - Decode a PCI irq from the device tree and map to a virq
+ * @dev: The pci device needing an irq
+ * @slot: PCI slot number; passed when used as map_irq callback. Unused
+ * @pin: PCI irq pin number; passed when used as map_irq callback. Unused
+ *
+ * @slot and @pin are unused, but included in the function so that this
+ * function can be used directly as the map_irq callback to pci_fixup_irqs().
+ */
+int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	struct of_phandle_args oirq;
+	int ret;
+
+	ret = of_irq_parse_pci(dev, &oirq);
+	if (ret) {
+		dev_err(&dev->dev, "of_irq_parse_pci() failed with rc=%d\n", ret);
+		return 0; /* Proper return code 0 == NO_IRQ */
+	}
+
+	return irq_create_of_mapping(&oirq);
+}
+EXPORT_SYMBOL_GPL(of_irq_parse_and_map_pci);
+
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
deleted file mode 100644
index 0fe40c7..0000000
--- a/drivers/of/of_reserved_mem.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Device tree based initialization code for reserved memory.
- *
- * Copyright (c) 2013 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- * Author: Marek Szyprowski <m.szyprowski@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License or (at your optional) any later version of the license.
- */
-
-#include <linux/memblock.h>
-#include <linux/err.h>
-#include <linux/of.h>
-#include <linux/of_fdt.h>
-#include <linux/of_platform.h>
-#include <linux/mm.h>
-#include <linux/sizes.h>
-#include <linux/mm_types.h>
-#include <linux/dma-contiguous.h>
-#include <linux/dma-mapping.h>
-#include <linux/of_reserved_mem.h>
-
-#define MAX_RESERVED_REGIONS	16
-struct reserved_mem {
-	phys_addr_t		base;
-	unsigned long		size;
-	struct cma		*cma;
-	char			name[32];
-};
-static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS];
-static int reserved_mem_count;
-
-static int __init fdt_scan_reserved_mem(unsigned long node, const char *uname,
-					int depth, void *data)
-{
-	struct reserved_mem *rmem = &reserved_mem[reserved_mem_count];
-	phys_addr_t base, size;
-	int is_cma, is_reserved;
-	unsigned long len;
-	const char *status;
-	__be32 *prop;
-
-	is_cma = IS_ENABLED(CONFIG_DMA_CMA) &&
-	       of_flat_dt_is_compatible(node, "linux,contiguous-memory-region");
-	is_reserved = of_flat_dt_is_compatible(node, "reserved-memory-region");
-
-	if (!is_reserved && !is_cma) {
-		/* ignore node and scan next one */
-		return 0;
-	}
-
-	status = of_get_flat_dt_prop(node, "status", &len);
-	if (status && strcmp(status, "okay") != 0) {
-		/* ignore disabled node nad scan next one */
-		return 0;
-	}
-
-	prop = of_get_flat_dt_prop(node, "reg", &len);
-	if (!prop || (len < (dt_root_size_cells + dt_root_addr_cells) *
-			     sizeof(__be32))) {
-		pr_err("Reserved mem: node %s, incorrect \"reg\" property\n",
-		       uname);
-		/* ignore node and scan next one */
-		return 0;
-	}
-	base = dt_mem_next_cell(dt_root_addr_cells, &prop);
-	size = dt_mem_next_cell(dt_root_size_cells, &prop);
-
-	if (!size) {
-		/* ignore node and scan next one */
-		return 0;
-	}
-
-	pr_info("Reserved mem: found %s, memory base %lx, size %ld MiB\n",
-		uname, (unsigned long)base, (unsigned long)size / SZ_1M);
-
-	if (reserved_mem_count == ARRAY_SIZE(reserved_mem))
-		return -ENOSPC;
-
-	rmem->base = base;
-	rmem->size = size;
-	strlcpy(rmem->name, uname, sizeof(rmem->name));
-
-	if (is_cma) {
-		struct cma *cma;
-		if (dma_contiguous_reserve_area(size, base, 0, &cma) == 0) {
-			rmem->cma = cma;
-			reserved_mem_count++;
-			if (of_get_flat_dt_prop(node,
-						"linux,default-contiguous-region",
-						NULL))
-				dma_contiguous_set_default(cma);
-		}
-	} else if (is_reserved) {
-		if (memblock_remove(base, size) == 0)
-			reserved_mem_count++;
-		else
-			pr_err("Failed to reserve memory for %s\n", uname);
-	}
-
-	return 0;
-}
-
-static struct reserved_mem *get_dma_memory_region(struct device *dev)
-{
-	struct device_node *node;
-	const char *name;
-	int i;
-
-	node = of_parse_phandle(dev->of_node, "memory-region", 0);
-	if (!node)
-		return NULL;
-
-	name = kbasename(node->full_name);
-	for (i = 0; i < reserved_mem_count; i++)
-		if (strcmp(name, reserved_mem[i].name) == 0)
-			return &reserved_mem[i];
-	return NULL;
-}
-
-/**
- * of_reserved_mem_device_init() - assign reserved memory region to given device
- *
- * This function assign memory region pointed by "memory-region" device tree
- * property to the given device.
- */
-void of_reserved_mem_device_init(struct device *dev)
-{
-	struct reserved_mem *region = get_dma_memory_region(dev);
-	if (!region)
-		return;
-
-	if (region->cma) {
-		dev_set_cma_area(dev, region->cma);
-		pr_info("Assigned CMA %s to %s device\n", region->name,
-			dev_name(dev));
-	} else {
-		if (dma_declare_coherent_memory(dev, region->base, region->base,
-		    region->size, DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) != 0)
-			pr_info("Declared reserved memory %s to %s device\n",
-				region->name, dev_name(dev));
-	}
-}
-
-/**
- * of_reserved_mem_device_release() - release reserved memory device structures
- *
- * This function releases structures allocated for memory region handling for
- * the given device.
- */
-void of_reserved_mem_device_release(struct device *dev)
-{
-	struct reserved_mem *region = get_dma_memory_region(dev);
-	if (!region && !region->cma)
-		dma_release_declared_memory(dev);
-}
-
-/**
- * early_init_dt_scan_reserved_mem() - create reserved memory regions
- *
- * This function grabs memory from early allocator for device exclusive use
- * defined in device tree structures. It should be called by arch specific code
- * once the early allocator (memblock) has been activated and all other
- * subsystems have already allocated/reserved memory.
- */
-void __init early_init_dt_scan_reserved_mem(void)
-{
-	of_scan_flat_dt_by_path("/memory/reserved-memory",
-				fdt_scan_reserved_mem, NULL);
-}
diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c
index 4ec19cb..7b66673 100644
--- a/drivers/of/pdt.c
+++ b/drivers/of/pdt.c
@@ -22,7 +22,6 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_pdt.h>
-#include <asm/prom.h>
 
 static struct of_pdt_ops *of_pdt_prom_ops __initdata;
 
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 9b439ac..fce088e 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -21,7 +21,6 @@
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
-#include <linux/of_reserved_mem.h>
 #include <linux/platform_device.h>
 
 const struct of_device_id of_default_bus_match_table[] = {
@@ -216,11 +215,11 @@
 	dev->archdata.dma_mask = 0xffffffffUL;
 #endif
 	dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+	if (!dev->dev.dma_mask)
+		dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
 	dev->dev.bus = &platform_bus_type;
 	dev->dev.platform_data = platform_data;
 
-	of_reserved_mem_device_init(&dev->dev);
-
 	/* We do not fill the DMA ops for platform devices by default.
 	 * This is currently the responsibility of the platform code
 	 * to do such, possibly using a device notifier
@@ -228,7 +227,6 @@
 
 	if (of_device_add(dev) != 0) {
 		platform_device_put(dev);
-		of_reserved_mem_device_release(&dev->dev);
 		return NULL;
 	}
 
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c
index 0eb5c38..e21012b 100644
--- a/drivers/of/selftest.c
+++ b/drivers/of/selftest.c
@@ -9,18 +9,24 @@
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_irq.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/device.h>
 
-static bool selftest_passed = true;
+static struct selftest_results {
+	int passed;
+	int failed;
+} selftest_results;
+
 #define selftest(result, fmt, ...) { \
 	if (!(result)) { \
-		pr_err("FAIL %s:%i " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \
-		selftest_passed = false; \
+		selftest_results.failed++; \
+		pr_err("FAIL %s():%i " fmt, __func__, __LINE__, ##__VA_ARGS__); \
 	} else { \
-		pr_info("pass %s:%i\n", __FILE__, __LINE__); \
+		selftest_results.passed++; \
+		pr_debug("pass %s():%i\n", __func__, __LINE__); \
 	} \
 }
 
@@ -131,7 +137,6 @@
 	struct device_node *np;
 	int rc;
 
-	pr_info("start\n");
 	np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
 	if (!np) {
 		pr_err("No testcase data in device tree\n");
@@ -154,6 +159,147 @@
 	selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc);
 }
 
+static void __init of_selftest_parse_interrupts(void)
+{
+	struct device_node *np;
+	struct of_phandle_args args;
+	int i, rc;
+
+	np = of_find_node_by_path("/testcase-data/interrupts/interrupts0");
+	if (!np) {
+		pr_err("missing testcase data\n");
+		return;
+	}
+
+	for (i = 0; i < 4; i++) {
+		bool passed = true;
+		args.args_count = 0;
+		rc = of_irq_parse_one(np, i, &args);
+
+		passed &= !rc;
+		passed &= (args.args_count == 1);
+		passed &= (args.args[0] == (i + 1));
+
+		selftest(passed, "index %i - data error on node %s rc=%i\n",
+			 i, args.np->full_name, rc);
+	}
+	of_node_put(np);
+
+	np = of_find_node_by_path("/testcase-data/interrupts/interrupts1");
+	if (!np) {
+		pr_err("missing testcase data\n");
+		return;
+	}
+
+	for (i = 0; i < 4; i++) {
+		bool passed = true;
+		args.args_count = 0;
+		rc = of_irq_parse_one(np, i, &args);
+
+		/* Test the values from tests-phandle.dtsi */
+		switch (i) {
+		case 0:
+			passed &= !rc;
+			passed &= (args.args_count == 1);
+			passed &= (args.args[0] == 9);
+			break;
+		case 1:
+			passed &= !rc;
+			passed &= (args.args_count == 3);
+			passed &= (args.args[0] == 10);
+			passed &= (args.args[1] == 11);
+			passed &= (args.args[2] == 12);
+			break;
+		case 2:
+			passed &= !rc;
+			passed &= (args.args_count == 2);
+			passed &= (args.args[0] == 13);
+			passed &= (args.args[1] == 14);
+			break;
+		case 3:
+			passed &= !rc;
+			passed &= (args.args_count == 2);
+			passed &= (args.args[0] == 15);
+			passed &= (args.args[1] == 16);
+			break;
+		default:
+			passed = false;
+		}
+		selftest(passed, "index %i - data error on node %s rc=%i\n",
+			 i, args.np->full_name, rc);
+	}
+	of_node_put(np);
+}
+
+static void __init of_selftest_parse_interrupts_extended(void)
+{
+	struct device_node *np;
+	struct of_phandle_args args;
+	int i, rc;
+
+	np = of_find_node_by_path("/testcase-data/interrupts/interrupts-extended0");
+	if (!np) {
+		pr_err("missing testcase data\n");
+		return;
+	}
+
+	for (i = 0; i < 7; i++) {
+		bool passed = true;
+		rc = of_irq_parse_one(np, i, &args);
+
+		/* Test the values from tests-phandle.dtsi */
+		switch (i) {
+		case 0:
+			passed &= !rc;
+			passed &= (args.args_count == 1);
+			passed &= (args.args[0] == 1);
+			break;
+		case 1:
+			passed &= !rc;
+			passed &= (args.args_count == 3);
+			passed &= (args.args[0] == 2);
+			passed &= (args.args[1] == 3);
+			passed &= (args.args[2] == 4);
+			break;
+		case 2:
+			passed &= !rc;
+			passed &= (args.args_count == 2);
+			passed &= (args.args[0] == 5);
+			passed &= (args.args[1] == 6);
+			break;
+		case 3:
+			passed &= !rc;
+			passed &= (args.args_count == 1);
+			passed &= (args.args[0] == 9);
+			break;
+		case 4:
+			passed &= !rc;
+			passed &= (args.args_count == 3);
+			passed &= (args.args[0] == 10);
+			passed &= (args.args[1] == 11);
+			passed &= (args.args[2] == 12);
+			break;
+		case 5:
+			passed &= !rc;
+			passed &= (args.args_count == 2);
+			passed &= (args.args[0] == 13);
+			passed &= (args.args[1] == 14);
+			break;
+		case 6:
+			passed &= !rc;
+			passed &= (args.args_count == 1);
+			passed &= (args.args[0] == 15);
+			break;
+		default:
+			passed = false;
+		}
+
+		selftest(passed, "index %i - data error on node %s rc=%i\n",
+			 i, args.np->full_name, rc);
+	}
+	of_node_put(np);
+}
+
 static int __init of_selftest(void)
 {
 	struct device_node *np;
@@ -168,7 +314,10 @@
 	pr_info("start of selftest - you will see error messages\n");
 	of_selftest_parse_phandle_with_args();
 	of_selftest_property_match_string();
-	pr_info("end of selftest - %s\n", selftest_passed ? "PASS" : "FAIL");
+	of_selftest_parse_interrupts();
+	of_selftest_parse_interrupts_extended();
+	pr_info("end of selftest - %i passed, %i failed\n",
+		selftest_results.passed, selftest_results.failed);
 	return 0;
 }
 late_initcall(of_selftest);
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index 70694ce..dc82ef0 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -37,7 +37,7 @@
 	tristate "PC-style hardware"
 	depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV && !S390 && \
 		(!M68K || ISA) && !MN10300 && !AVR32 && !BLACKFIN && \
-		!XTENSA && !CRIS && !H8300
+		!XTENSA && !CRIS
 
 	---help---
 	  You should say Y here if you have a PC-style parallel port. All
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 3d95048..43186fe 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -3,7 +3,7 @@
 
 config PCI_MVEBU
 	bool "Marvell EBU PCIe controller"
-	depends on ARCH_MVEBU || ARCH_KIRKWOOD
+	depends on ARCH_MVEBU || ARCH_DOVE || ARCH_KIRKWOOD
 	depends on OF
 
 config PCIE_DW
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index 729d5a1..c269e43 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -9,13 +9,17 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/mbus.h>
+#include <linux/msi.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/of_address.h>
-#include <linux/of_pci.h>
 #include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <linux/of_pci.h>
 #include <linux/of_platform.h>
 
 /*
@@ -103,6 +107,7 @@
 struct mvebu_pcie {
 	struct platform_device *pdev;
 	struct mvebu_pcie_port *ports;
+	struct msi_chip *msi;
 	struct resource io;
 	struct resource realio;
 	struct resource mem;
@@ -115,7 +120,6 @@
 	char *name;
 	void __iomem *base;
 	spinlock_t conf_lock;
-	int haslink;
 	u32 port;
 	u32 lane;
 	int devfn;
@@ -124,6 +128,9 @@
 	unsigned int io_target;
 	unsigned int io_attr;
 	struct clk *clk;
+	int reset_gpio;
+	int reset_active_low;
+	char *reset_name;
 	struct mvebu_sw_pci_bridge bridge;
 	struct device_node *dn;
 	struct mvebu_pcie *pcie;
@@ -133,29 +140,39 @@
 	size_t iowin_size;
 };
 
+static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
+{
+	writel(val, port->base + reg);
+}
+
+static inline u32 mvebu_readl(struct mvebu_pcie_port *port, u32 reg)
+{
+	return readl(port->base + reg);
+}
+
 static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port)
 {
-	return !(readl(port->base + PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN);
+	return !(mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN);
 }
 
 static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie_port *port, int nr)
 {
 	u32 stat;
 
-	stat = readl(port->base + PCIE_STAT_OFF);
+	stat = mvebu_readl(port, PCIE_STAT_OFF);
 	stat &= ~PCIE_STAT_BUS;
 	stat |= nr << 8;
-	writel(stat, port->base + PCIE_STAT_OFF);
+	mvebu_writel(port, stat, PCIE_STAT_OFF);
 }
 
 static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie_port *port, int nr)
 {
 	u32 stat;
 
-	stat = readl(port->base + PCIE_STAT_OFF);
+	stat = mvebu_readl(port, PCIE_STAT_OFF);
 	stat &= ~PCIE_STAT_DEV;
 	stat |= nr << 16;
-	writel(stat, port->base + PCIE_STAT_OFF);
+	mvebu_writel(port, stat, PCIE_STAT_OFF);
 }
 
 /*
@@ -163,7 +180,7 @@
  * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
  * WIN[0-3] -> DRAM bank[0-3]
  */
-static void __init mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
+static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
 {
 	const struct mbus_dram_target_info *dram;
 	u32 size;
@@ -173,33 +190,34 @@
 
 	/* First, disable and clear BARs and windows. */
 	for (i = 1; i < 3; i++) {
-		writel(0, port->base + PCIE_BAR_CTRL_OFF(i));
-		writel(0, port->base + PCIE_BAR_LO_OFF(i));
-		writel(0, port->base + PCIE_BAR_HI_OFF(i));
+		mvebu_writel(port, 0, PCIE_BAR_CTRL_OFF(i));
+		mvebu_writel(port, 0, PCIE_BAR_LO_OFF(i));
+		mvebu_writel(port, 0, PCIE_BAR_HI_OFF(i));
 	}
 
 	for (i = 0; i < 5; i++) {
-		writel(0, port->base + PCIE_WIN04_CTRL_OFF(i));
-		writel(0, port->base + PCIE_WIN04_BASE_OFF(i));
-		writel(0, port->base + PCIE_WIN04_REMAP_OFF(i));
+		mvebu_writel(port, 0, PCIE_WIN04_CTRL_OFF(i));
+		mvebu_writel(port, 0, PCIE_WIN04_BASE_OFF(i));
+		mvebu_writel(port, 0, PCIE_WIN04_REMAP_OFF(i));
 	}
 
-	writel(0, port->base + PCIE_WIN5_CTRL_OFF);
-	writel(0, port->base + PCIE_WIN5_BASE_OFF);
-	writel(0, port->base + PCIE_WIN5_REMAP_OFF);
+	mvebu_writel(port, 0, PCIE_WIN5_CTRL_OFF);
+	mvebu_writel(port, 0, PCIE_WIN5_BASE_OFF);
+	mvebu_writel(port, 0, PCIE_WIN5_REMAP_OFF);
 
 	/* Setup windows for DDR banks.  Count total DDR size on the fly. */
 	size = 0;
 	for (i = 0; i < dram->num_cs; i++) {
 		const struct mbus_dram_window *cs = dram->cs + i;
 
-		writel(cs->base & 0xffff0000,
-		       port->base + PCIE_WIN04_BASE_OFF(i));
-		writel(0, port->base + PCIE_WIN04_REMAP_OFF(i));
-		writel(((cs->size - 1) & 0xffff0000) |
-			(cs->mbus_attr << 8) |
-			(dram->mbus_dram_target_id << 4) | 1,
-		       port->base + PCIE_WIN04_CTRL_OFF(i));
+		mvebu_writel(port, cs->base & 0xffff0000,
+			     PCIE_WIN04_BASE_OFF(i));
+		mvebu_writel(port, 0, PCIE_WIN04_REMAP_OFF(i));
+		mvebu_writel(port,
+			     ((cs->size - 1) & 0xffff0000) |
+			     (cs->mbus_attr << 8) |
+			     (dram->mbus_dram_target_id << 4) | 1,
+			     PCIE_WIN04_CTRL_OFF(i));
 
 		size += cs->size;
 	}
@@ -209,41 +227,40 @@
 		size = 1 << fls(size);
 
 	/* Setup BAR[1] to all DRAM banks. */
-	writel(dram->cs[0].base, port->base + PCIE_BAR_LO_OFF(1));
-	writel(0, port->base + PCIE_BAR_HI_OFF(1));
-	writel(((size - 1) & 0xffff0000) | 1,
-	       port->base + PCIE_BAR_CTRL_OFF(1));
+	mvebu_writel(port, dram->cs[0].base, PCIE_BAR_LO_OFF(1));
+	mvebu_writel(port, 0, PCIE_BAR_HI_OFF(1));
+	mvebu_writel(port, ((size - 1) & 0xffff0000) | 1,
+		     PCIE_BAR_CTRL_OFF(1));
 }
 
-static void __init mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
+static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
 {
-	u16 cmd;
-	u32 mask;
+	u32 cmd, mask;
 
 	/* Point PCIe unit MBUS decode windows to DRAM space. */
 	mvebu_pcie_setup_wins(port);
 
 	/* Master + slave enable. */
-	cmd = readw(port->base + PCIE_CMD_OFF);
+	cmd = mvebu_readl(port, PCIE_CMD_OFF);
 	cmd |= PCI_COMMAND_IO;
 	cmd |= PCI_COMMAND_MEMORY;
 	cmd |= PCI_COMMAND_MASTER;
-	writew(cmd, port->base + PCIE_CMD_OFF);
+	mvebu_writel(port, cmd, PCIE_CMD_OFF);
 
 	/* Enable interrupt lines A-D. */
-	mask = readl(port->base + PCIE_MASK_OFF);
+	mask = mvebu_readl(port, PCIE_MASK_OFF);
 	mask |= PCIE_MASK_ENABLE_INTS;
-	writel(mask, port->base + PCIE_MASK_OFF);
+	mvebu_writel(port, mask, PCIE_MASK_OFF);
 }
 
 static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
 				 struct pci_bus *bus,
 				 u32 devfn, int where, int size, u32 *val)
 {
-	writel(PCIE_CONF_ADDR(bus->number, devfn, where),
-	       port->base + PCIE_CONF_ADDR_OFF);
+	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
+		     PCIE_CONF_ADDR_OFF);
 
-	*val = readl(port->base + PCIE_CONF_DATA_OFF);
+	*val = mvebu_readl(port, PCIE_CONF_DATA_OFF);
 
 	if (size == 1)
 		*val = (*val >> (8 * (where & 3))) & 0xff;
@@ -257,21 +274,24 @@
 				 struct pci_bus *bus,
 				 u32 devfn, int where, int size, u32 val)
 {
-	int ret = PCIBIOS_SUCCESSFUL;
+	u32 _val, shift = 8 * (where & 3);
 
-	writel(PCIE_CONF_ADDR(bus->number, devfn, where),
-	       port->base + PCIE_CONF_ADDR_OFF);
+	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
+		     PCIE_CONF_ADDR_OFF);
+	_val = mvebu_readl(port, PCIE_CONF_DATA_OFF);
 
 	if (size == 4)
-		writel(val, port->base + PCIE_CONF_DATA_OFF);
+		_val = val;
 	else if (size == 2)
-		writew(val, port->base + PCIE_CONF_DATA_OFF + (where & 3));
+		_val = (_val & ~(0xffff << shift)) | ((val & 0xffff) << shift);
 	else if (size == 1)
-		writeb(val, port->base + PCIE_CONF_DATA_OFF + (where & 3));
+		_val = (_val & ~(0xff << shift)) | ((val & 0xff) << shift);
 	else
-		ret = PCIBIOS_BAD_REGISTER_NUMBER;
+		return PCIBIOS_BAD_REGISTER_NUMBER;
 
-	return ret;
+	mvebu_writel(port, _val, PCIE_CONF_DATA_OFF);
+
+	return PCIBIOS_SUCCESSFUL;
 }
 
 static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
@@ -552,7 +572,7 @@
 	if (bus->number == 0)
 		return mvebu_sw_pci_bridge_write(port, where, size, val);
 
-	if (!port->haslink)
+	if (!mvebu_pcie_link_up(port))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	/*
@@ -594,7 +614,7 @@
 	if (bus->number == 0)
 		return mvebu_sw_pci_bridge_read(port, where, size, val);
 
-	if (!port->haslink) {
+	if (!mvebu_pcie_link_up(port)) {
 		*val = 0xffffffff;
 		return PCIBIOS_DEVICE_NOT_FOUND;
 	}
@@ -626,7 +646,7 @@
 	.write = mvebu_pcie_wr_conf,
 };
 
-static int __init mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
+static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
 {
 	struct mvebu_pcie *pcie = sys_to_pcie(sys);
 	int i;
@@ -645,19 +665,6 @@
 	return 1;
 }
 
-static int __init mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	struct of_irq oirq;
-	int ret;
-
-	ret = of_irq_map_pci(dev, &oirq);
-	if (ret)
-		return ret;
-
-	return irq_create_of_mapping(oirq.controller, oirq.specifier,
-				     oirq.size);
-}
-
 static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
 {
 	struct mvebu_pcie *pcie = sys_to_pcie(sys);
@@ -673,11 +680,17 @@
 	return bus;
 }
 
-resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
-					  const struct resource *res,
-					  resource_size_t start,
-					  resource_size_t size,
-					  resource_size_t align)
+static void mvebu_pcie_add_bus(struct pci_bus *bus)
+{
+	struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata);
+	bus->msi = pcie->msi;
+}
+
+static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
+						const struct resource *res,
+						resource_size_t start,
+						resource_size_t size,
+						resource_size_t align)
 {
 	if (dev->bus->number != 0)
 		return start;
@@ -696,7 +709,7 @@
 		return start;
 }
 
-static void __init mvebu_pcie_enable(struct mvebu_pcie *pcie)
+static void mvebu_pcie_enable(struct mvebu_pcie *pcie)
 {
 	struct hw_pci hw;
 
@@ -706,9 +719,10 @@
 	hw.private_data   = (void **)&pcie;
 	hw.setup          = mvebu_pcie_setup;
 	hw.scan           = mvebu_pcie_scan_bus;
-	hw.map_irq        = mvebu_pcie_map_irq;
+	hw.map_irq        = of_irq_parse_and_map_pci;
 	hw.ops            = &mvebu_pcie_ops;
 	hw.align_resource = mvebu_pcie_align_resource;
+	hw.add_bus        = mvebu_pcie_add_bus;
 
 	pci_common_init(&hw);
 }
@@ -718,10 +732,8 @@
  * <...> property for one that matches the given port/lane. Once
  * found, maps it.
  */
-static void __iomem * __init
-mvebu_pcie_map_registers(struct platform_device *pdev,
-			 struct device_node *np,
-			 struct mvebu_pcie_port *port)
+static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev,
+		      struct device_node *np, struct mvebu_pcie_port *port)
 {
 	struct resource regs;
 	int ret = 0;
@@ -777,7 +789,22 @@
 	return -ENOENT;
 }
 
-static int __init mvebu_pcie_probe(struct platform_device *pdev)
+static void mvebu_pcie_msi_enable(struct mvebu_pcie *pcie)
+{
+	struct device_node *msi_node;
+
+	msi_node = of_parse_phandle(pcie->pdev->dev.of_node,
+				    "msi-parent", 0);
+	if (!msi_node)
+		return;
+
+	pcie->msi = of_pci_find_msi_chip_by_node(msi_node);
+
+	if (pcie->msi)
+		pcie->msi->dev = &pcie->pdev->dev;
+}
+
+static int mvebu_pcie_probe(struct platform_device *pdev)
 {
 	struct mvebu_pcie *pcie;
 	struct device_node *np = pdev->dev.of_node;
@@ -790,6 +817,7 @@
 		return -ENOMEM;
 
 	pcie->pdev = pdev;
+	platform_set_drvdata(pdev, pcie);
 
 	/* Get the PCIe memory and I/O aperture */
 	mvebu_mbus_get_pcie_mem_aperture(&pcie->mem);
@@ -818,13 +846,14 @@
 		return ret;
 	}
 
+	i = 0;
 	for_each_child_of_node(pdev->dev.of_node, child) {
 		if (!of_device_is_available(child))
 			continue;
-		pcie->nports++;
+		i++;
 	}
 
-	pcie->ports = devm_kzalloc(&pdev->dev, pcie->nports *
+	pcie->ports = devm_kzalloc(&pdev->dev, i *
 				   sizeof(struct mvebu_pcie_port),
 				   GFP_KERNEL);
 	if (!pcie->ports)
@@ -833,6 +862,7 @@
 	i = 0;
 	for_each_child_of_node(pdev->dev.of_node, child) {
 		struct mvebu_pcie_port *port = &pcie->ports[i];
+		enum of_gpio_flags flags;
 
 		if (!of_device_is_available(child))
 			continue;
@@ -873,45 +903,68 @@
 			continue;
 		}
 
-		port->base = mvebu_pcie_map_registers(pdev, child, port);
-		if (IS_ERR(port->base)) {
-			dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n",
-				port->port, port->lane);
-			port->base = NULL;
-			continue;
-		}
+		port->reset_gpio = of_get_named_gpio_flags(child,
+						   "reset-gpios", 0, &flags);
+		if (gpio_is_valid(port->reset_gpio)) {
+			u32 reset_udelay = 20000;
 
-		mvebu_pcie_set_local_dev_nr(port, 1);
+			port->reset_active_low = flags & OF_GPIO_ACTIVE_LOW;
+			port->reset_name = kasprintf(GFP_KERNEL,
+				     "pcie%d.%d-reset", port->port, port->lane);
+			of_property_read_u32(child, "reset-delay-us",
+					     &reset_udelay);
 
-		if (mvebu_pcie_link_up(port)) {
-			port->haslink = 1;
-			dev_info(&pdev->dev, "PCIe%d.%d: link up\n",
-				 port->port, port->lane);
-		} else {
-			port->haslink = 0;
-			dev_info(&pdev->dev, "PCIe%d.%d: link down\n",
-				 port->port, port->lane);
+			ret = devm_gpio_request_one(&pdev->dev,
+			    port->reset_gpio, GPIOF_DIR_OUT, port->reset_name);
+			if (ret) {
+				if (ret == -EPROBE_DEFER)
+					return ret;
+				continue;
+			}
+
+			gpio_set_value(port->reset_gpio,
+				       (port->reset_active_low) ? 1 : 0);
+			msleep(reset_udelay/1000);
 		}
 
 		port->clk = of_clk_get_by_name(child, NULL);
 		if (IS_ERR(port->clk)) {
 			dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n",
 			       port->port, port->lane);
+			continue;
+		}
+
+		ret = clk_prepare_enable(port->clk);
+		if (ret)
+			continue;
+
+		port->base = mvebu_pcie_map_registers(pdev, child, port);
+		if (IS_ERR(port->base)) {
+			dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n",
+				port->port, port->lane);
+			port->base = NULL;
+			clk_disable_unprepare(port->clk);
+			continue;
+		}
+
+		mvebu_pcie_set_local_dev_nr(port, 1);
+
+		port->clk = of_clk_get_by_name(child, NULL);
+		if (IS_ERR(port->clk)) {
+			dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n",
+			       port->port, port->lane);
 			iounmap(port->base);
-			port->haslink = 0;
 			continue;
 		}
 
 		port->dn = child;
-
-		clk_prepare_enable(port->clk);
 		spin_lock_init(&port->conf_lock);
-
 		mvebu_sw_pci_bridge_init(port);
-
 		i++;
 	}
 
+	pcie->nports = i;
+	mvebu_pcie_msi_enable(pcie);
 	mvebu_pcie_enable(pcie);
 
 	return 0;
@@ -920,6 +973,7 @@
 static const struct of_device_id mvebu_pcie_of_match_table[] = {
 	{ .compatible = "marvell,armada-xp-pcie", },
 	{ .compatible = "marvell,armada-370-pcie", },
+	{ .compatible = "marvell,dove-pcie", },
 	{ .compatible = "marvell,kirkwood-pcie", },
 	{},
 };
@@ -931,16 +985,12 @@
 		.name = "mvebu-pcie",
 		.of_match_table =
 		   of_match_ptr(mvebu_pcie_of_match_table),
+		/* driver unloading/unbinding currently not supported */
+		.suppress_bind_attrs = true,
 	},
+	.probe = mvebu_pcie_probe,
 };
-
-static int __init mvebu_pcie_init(void)
-{
-	return platform_driver_probe(&mvebu_pcie_driver,
-				     mvebu_pcie_probe);
-}
-
-subsys_initcall(mvebu_pcie_init);
+module_platform_driver(mvebu_pcie_driver);
 
 MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
 MODULE_DESCRIPTION("Marvell EBU PCIe driver");
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 0b7d23b..1ea7523 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -552,9 +552,8 @@
 	struct acpiphp_func *func;
 	int max, pass;
 	LIST_HEAD(add_list);
-	int nr_found;
 
-	nr_found = acpiphp_rescan_slot(slot);
+	acpiphp_rescan_slot(slot);
 	max = acpiphp_max_busnr(bus);
 	for (pass = 0; pass < 2; pass++) {
 		list_for_each_entry(dev, &bus->devices, bus_list) {
@@ -574,9 +573,6 @@
 		}
 	}
 	__pci_bus_assign_resources(bus, &add_list, NULL);
-	/* Nothing more to do here if there are no new devices on this bus. */
-	if (!nr_found && (slot->flags & SLOT_ENABLED))
-		return;
 
 	acpiphp_sanitize_bus(bus);
 	acpiphp_set_hpp_values(bus);
@@ -994,14 +990,16 @@
 
 		/*
 		 * This bridge should have been registered as a hotplug function
-		 * under its parent, so the context has to be there.  If not, we
-		 * are in deep goo.
+		 * under its parent, so the context should be there, unless the
+		 * parent is going to be handled by pciehp, in which case this
+		 * bridge is not interesting to us either.
 		 */
 		mutex_lock(&acpiphp_context_lock);
 		context = acpiphp_get_context(handle);
-		if (WARN_ON(!context)) {
+		if (!context) {
 			mutex_unlock(&acpiphp_context_lock);
 			put_device(&bus->dev);
+			pci_dev_put(bridge->pci_dev);
 			kfree(bridge);
 			return;
 		}
diff --git a/drivers/pci/hotplug/s390_pci_hpc.c b/drivers/pci/hotplug/s390_pci_hpc.c
index 66e505c..3c7eb5d 100644
--- a/drivers/pci/hotplug/s390_pci_hpc.c
+++ b/drivers/pci/hotplug/s390_pci_hpc.c
@@ -133,7 +133,6 @@
 {
 	struct slot *slot = hotplug_slot->private;
 
-	pr_debug("%s - physical_slot = %s\n", __func__, hotplug_slot_name(hotplug_slot));
 	kfree(slot->hotplug_slot->info);
 	kfree(slot->hotplug_slot);
 	kfree(slot);
@@ -183,10 +182,9 @@
 	snprintf(name, SLOT_NAME_SIZE, "%08x", zdev->fid);
 	rc = pci_hp_register(slot->hotplug_slot, zdev->bus,
 			     ZPCI_DEVFN, name);
-	if (rc) {
-		pr_err("pci_hp_register failed with error %d\n", rc);
+	if (rc)
 		goto error_reg;
-	}
+
 	list_add(&slot->slot_list, &s390_hotplug_slot_list);
 	return 0;
 
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 98f7b9b..38f3c01 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -135,6 +135,7 @@
 		return retval;
 	return count;
 }
+static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
 
 /**
  * store_remove_id - remove a PCI device ID from this driver
@@ -180,12 +181,14 @@
 		return retval;
 	return count;
 }
+static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id);
 
-static struct driver_attribute pci_drv_attrs[] = {
-	__ATTR(new_id, S_IWUSR, NULL, store_new_id),
-	__ATTR(remove_id, S_IWUSR, NULL, store_remove_id),
-	__ATTR_NULL,
+static struct attribute *pci_drv_attrs[] = {
+	&driver_attr_new_id.attr,
+	&driver_attr_remove_id.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(pci_drv);
 
 /**
  * pci_match_id - See if a pci device matches a given pci_id table
@@ -1317,8 +1320,8 @@
 	.remove		= pci_device_remove,
 	.shutdown	= pci_device_shutdown,
 	.dev_attrs	= pci_dev_attrs,
-	.bus_attrs	= pci_bus_attrs,
-	.drv_attrs	= pci_drv_attrs,
+	.bus_groups	= pci_bus_groups,
+	.drv_groups	= pci_drv_groups,
 	.pm		= PCI_PM_OPS_PTR,
 };
 
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 7128cfd..d8eb880bd 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -302,10 +302,20 @@
 	}
 	return count;
 }
+static BUS_ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, bus_rescan_store);
 
-struct bus_attribute pci_bus_attrs[] = {
-	__ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, bus_rescan_store),
-	__ATTR_NULL
+struct attribute *pci_bus_attrs[] = {
+	&bus_attr_rescan.attr,
+	NULL,
+};
+
+static const struct attribute_group pci_bus_group = {
+	.attrs = pci_bus_attrs,
+};
+
+const struct attribute_group *pci_bus_groups[] = {
+	&pci_bus_group,
+	NULL,
 };
 
 static ssize_t
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 8a00c06..607be58 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -156,7 +156,7 @@
 extern struct device_attribute pci_dev_attrs[];
 extern const struct attribute_group *pcibus_groups[];
 extern struct device_type pci_dev_type;
-extern struct bus_attribute pci_bus_attrs[];
+extern const struct attribute_group *pci_bus_groups[];
 
 
 /**
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index b8f5acf..de24232 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -245,7 +245,7 @@
 }
 #endif
 
-static int __init at91_cf_probe(struct platform_device *pdev)
+static int at91_cf_probe(struct platform_device *pdev)
 {
 	struct at91_cf_socket	*cf;
 	struct at91_cf_data	*board = pdev->dev.platform_data;
@@ -354,7 +354,7 @@
 	return status;
 }
 
-static int __exit at91_cf_remove(struct platform_device *pdev)
+static int at91_cf_remove(struct platform_device *pdev)
 {
 	struct at91_cf_socket	*cf = platform_get_drvdata(pdev);
 
@@ -404,14 +404,13 @@
 		.owner		= THIS_MODULE,
 		.of_match_table = of_match_ptr(at91_cf_dt_ids),
 	},
-	.remove		= __exit_p(at91_cf_remove),
+	.probe		= at91_cf_probe,
+	.remove		= at91_cf_remove,
 	.suspend	= at91_cf_suspend,
 	.resume		= at91_cf_resume,
 };
 
-/*--------------------------------------------------------------------------*/
-
-module_platform_driver_probe(at91_cf_driver, at91_cf_probe);
+module_platform_driver(at91_cf_driver);
 
 MODULE_DESCRIPTION("AT91 Compact Flash Driver");
 MODULE_AUTHOR("David Brownell");
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 2deacbb..757119b 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -992,16 +992,17 @@
 {									\
 	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);		\
 	return p_dev->test ? sprintf(buf, format, p_dev->field) : -ENODEV; \
-}
+}									\
+static DEVICE_ATTR_RO(field);
 
 #define pcmcia_device_stringattr(name, field)					\
 static ssize_t name##_show (struct device *dev, struct device_attribute *attr, char *buf)		\
 {									\
 	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);		\
 	return p_dev->field ? sprintf(buf, "%s\n", p_dev->field) : -ENODEV; \
-}
+}									\
+static DEVICE_ATTR_RO(name);
 
-pcmcia_device_attr(func, socket, "0x%02x\n");
 pcmcia_device_attr(func_id, has_func_id, "0x%02x\n");
 pcmcia_device_attr(manf_id, has_manf_id, "0x%04x\n");
 pcmcia_device_attr(card_id, has_card_id, "0x%04x\n");
@@ -1010,8 +1011,16 @@
 pcmcia_device_stringattr(prod_id3, prod_id[2]);
 pcmcia_device_stringattr(prod_id4, prod_id[3]);
 
-static ssize_t pcmcia_show_resources(struct device *dev,
-				     struct device_attribute *attr, char *buf)
+static ssize_t function_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+	return p_dev->socket ? sprintf(buf, "0x%02x\n", p_dev->func) : -ENODEV;
+}
+static DEVICE_ATTR_RO(function);
+
+static ssize_t resources_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
 {
 	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
 	char *str = buf;
@@ -1022,8 +1031,9 @@
 
 	return str - buf;
 }
+static DEVICE_ATTR_RO(resources);
 
-static ssize_t pcmcia_show_pm_state(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t pm_state_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
 
@@ -1033,8 +1043,8 @@
 		return sprintf(buf, "on\n");
 }
 
-static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute *attr,
-				     const char *buf, size_t count)
+static ssize_t pm_state_store(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t count)
 {
 	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
 	int ret = 0;
@@ -1049,7 +1059,7 @@
 
 	return ret ? ret : count;
 }
-
+static DEVICE_ATTR_RW(pm_state);
 
 static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -1072,8 +1082,9 @@
 				p_dev->func, p_dev->device_no,
 				hash[0], hash[1], hash[2], hash[3]);
 }
+static DEVICE_ATTR_RO(modalias);
 
-static ssize_t pcmcia_store_allow_func_id_match(struct device *dev,
+static ssize_t allow_func_id_match_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
@@ -1088,22 +1099,24 @@
 
 	return count;
 }
+static DEVICE_ATTR_WO(allow_func_id_match);
 
-static struct device_attribute pcmcia_dev_attrs[] = {
-	__ATTR(function, 0444, func_show, NULL),
-	__ATTR(pm_state, 0644, pcmcia_show_pm_state, pcmcia_store_pm_state),
-	__ATTR(resources, 0444, pcmcia_show_resources, NULL),
-	__ATTR_RO(func_id),
-	__ATTR_RO(manf_id),
-	__ATTR_RO(card_id),
-	__ATTR_RO(prod_id1),
-	__ATTR_RO(prod_id2),
-	__ATTR_RO(prod_id3),
-	__ATTR_RO(prod_id4),
-	__ATTR_RO(modalias),
-	__ATTR(allow_func_id_match, 0200, NULL, pcmcia_store_allow_func_id_match),
-	__ATTR_NULL,
+static struct attribute *pcmcia_dev_attrs[] = {
+	&dev_attr_resources.attr,
+	&dev_attr_pm_state.attr,
+	&dev_attr_function.attr,
+	&dev_attr_func_id.attr,
+	&dev_attr_manf_id.attr,
+	&dev_attr_card_id.attr,
+	&dev_attr_prod_id1.attr,
+	&dev_attr_prod_id2.attr,
+	&dev_attr_prod_id3.attr,
+	&dev_attr_prod_id4.attr,
+	&dev_attr_modalias.attr,
+	&dev_attr_allow_func_id_match.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(pcmcia_dev);
 
 /* PM support, also needed for reset */
 
@@ -1389,7 +1402,7 @@
 	.name = "pcmcia",
 	.uevent = pcmcia_bus_uevent,
 	.match = pcmcia_bus_match,
-	.dev_attrs = pcmcia_dev_attrs,
+	.dev_groups = pcmcia_dev_groups,
 	.probe = pcmcia_device_probe,
 	.remove = pcmcia_device_remove,
 	.suspend = pcmcia_dev_suspend,
diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c
index a007321a..1b206ea 100644
--- a/drivers/pcmcia/electra_cf.c
+++ b/drivers/pcmcia/electra_cf.c
@@ -30,6 +30,8 @@
 #include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/slab.h>
 
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index 18c0d8d..182034d 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -48,7 +48,9 @@
 #include <linux/interrupt.h>
 #include <linux/fsl_devices.h>
 #include <linux/bitops.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
 #include <asm/io.h>
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index a4c16ee..622dd6f 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -777,15 +777,4 @@
 	.remove		= pd6729_pci_remove,
 };
 
-static int pd6729_module_init(void)
-{
-	return pci_register_driver(&pd6729_pci_driver);
-}
-
-static void pd6729_module_exit(void)
-{
-	pci_unregister_driver(&pd6729_pci_driver);
-}
-
-module_init(pd6729_module_init);
-module_exit(pd6729_module_exit);
+module_pci_driver(pd6729_pci_driver);
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 6b4ff09..dc18a3a 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -1439,20 +1439,6 @@
 	.driver.pm	= YENTA_PM_OPS,
 };
 
-
-static int __init yenta_socket_init(void)
-{
-	return pci_register_driver(&yenta_cardbus_driver);
-}
-
-
-static void __exit yenta_socket_exit(void)
-{
-	pci_unregister_driver(&yenta_cardbus_driver);
-}
-
-
-module_init(yenta_socket_init);
-module_exit(yenta_socket_exit);
+module_pci_driver(yenta_cardbus_driver);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
new file mode 100644
index 0000000..a344f3d
--- /dev/null
+++ b/drivers/phy/Kconfig
@@ -0,0 +1,54 @@
+#
+# PHY
+#
+
+menu "PHY Subsystem"
+
+config GENERIC_PHY
+	tristate "PHY Core"
+	help
+	  Generic PHY support.
+
+	  This framework is designed to provide a generic interface for PHY
+	  devices present in the kernel. This layer will have the generic
+	  API by which phy drivers can create PHY using the phy framework and
+	  phy users can obtain reference to the PHY. All the users of this
+	  framework should select this config.
+
+config PHY_EXYNOS_MIPI_VIDEO
+	tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver"
+	help
+	  Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P
+	  and EXYNOS SoCs.
+
+config OMAP_USB2
+	tristate "OMAP USB2 PHY Driver"
+	depends on ARCH_OMAP2PLUS
+	select GENERIC_PHY
+	select USB_PHY
+	select OMAP_CONTROL_USB
+	help
+	  Enable this to support the transceiver that is part of SOC. This
+	  driver takes care of all the PHY functionality apart from comparator.
+	  The USB OTG controller communicates with the comparator using this
+	  driver.
+
+config TWL4030_USB
+	tristate "TWL4030 USB Transceiver Driver"
+	depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
+	select GENERIC_PHY
+	select USB_PHY
+	help
+	  Enable this to support the USB OTG transceiver on TWL4030
+	  family chips (including the TWL5030 and TPS659x0 devices).
+	  This transceiver supports high and full speed devices plus,
+	  in host mode, low speed.
+
+config PHY_EXYNOS_DP_VIDEO
+	tristate "EXYNOS SoC series Display Port PHY driver"
+	depends on OF
+	select GENERIC_PHY
+	help
+	  Support for Display Port PHY found on Samsung EXYNOS SoCs.
+
+endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
new file mode 100644
index 0000000..d0caae9
--- /dev/null
+++ b/drivers/phy/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the phy drivers.
+#
+
+obj-$(CONFIG_GENERIC_PHY)		+= phy-core.o
+obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO)	+= phy-exynos-dp-video.o
+obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO)	+= phy-exynos-mipi-video.o
+obj-$(CONFIG_OMAP_USB2)			+= phy-omap-usb2.o
+obj-$(CONFIG_TWL4030_USB)		+= phy-twl4030-usb.o
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
new file mode 100644
index 0000000..03cf8fb
--- /dev/null
+++ b/drivers/phy/phy-core.c
@@ -0,0 +1,698 @@
+/*
+ * phy-core.c  --  Generic Phy framework.
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Author: Kishon Vijay Abraham I <kishon@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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/idr.h>
+#include <linux/pm_runtime.h>
+
+static struct class *phy_class;
+static DEFINE_MUTEX(phy_provider_mutex);
+static LIST_HEAD(phy_provider_list);
+static DEFINE_IDA(phy_ida);
+
+static void devm_phy_release(struct device *dev, void *res)
+{
+	struct phy *phy = *(struct phy **)res;
+
+	phy_put(phy);
+}
+
+static void devm_phy_provider_release(struct device *dev, void *res)
+{
+	struct phy_provider *phy_provider = *(struct phy_provider **)res;
+
+	of_phy_provider_unregister(phy_provider);
+}
+
+static void devm_phy_consume(struct device *dev, void *res)
+{
+	struct phy *phy = *(struct phy **)res;
+
+	phy_destroy(phy);
+}
+
+static int devm_phy_match(struct device *dev, void *res, void *match_data)
+{
+	return res == match_data;
+}
+
+static struct phy *phy_lookup(struct device *device, const char *port)
+{
+	unsigned int count;
+	struct phy *phy;
+	struct device *dev;
+	struct phy_consumer *consumers;
+	struct class_dev_iter iter;
+
+	class_dev_iter_init(&iter, phy_class, NULL, NULL);
+	while ((dev = class_dev_iter_next(&iter))) {
+		phy = to_phy(dev);
+		count = phy->init_data->num_consumers;
+		consumers = phy->init_data->consumers;
+		while (count--) {
+			if (!strcmp(consumers->dev_name, dev_name(device)) &&
+					!strcmp(consumers->port, port)) {
+				class_dev_iter_exit(&iter);
+				return phy;
+			}
+			consumers++;
+		}
+	}
+
+	class_dev_iter_exit(&iter);
+	return ERR_PTR(-ENODEV);
+}
+
+static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
+{
+	struct phy_provider *phy_provider;
+
+	list_for_each_entry(phy_provider, &phy_provider_list, list) {
+		if (phy_provider->dev->of_node == node)
+			return phy_provider;
+	}
+
+	return ERR_PTR(-EPROBE_DEFER);
+}
+
+int phy_pm_runtime_get(struct phy *phy)
+{
+	if (!pm_runtime_enabled(&phy->dev))
+		return -ENOTSUPP;
+
+	return pm_runtime_get(&phy->dev);
+}
+EXPORT_SYMBOL_GPL(phy_pm_runtime_get);
+
+int phy_pm_runtime_get_sync(struct phy *phy)
+{
+	if (!pm_runtime_enabled(&phy->dev))
+		return -ENOTSUPP;
+
+	return pm_runtime_get_sync(&phy->dev);
+}
+EXPORT_SYMBOL_GPL(phy_pm_runtime_get_sync);
+
+int phy_pm_runtime_put(struct phy *phy)
+{
+	if (!pm_runtime_enabled(&phy->dev))
+		return -ENOTSUPP;
+
+	return pm_runtime_put(&phy->dev);
+}
+EXPORT_SYMBOL_GPL(phy_pm_runtime_put);
+
+int phy_pm_runtime_put_sync(struct phy *phy)
+{
+	if (!pm_runtime_enabled(&phy->dev))
+		return -ENOTSUPP;
+
+	return pm_runtime_put_sync(&phy->dev);
+}
+EXPORT_SYMBOL_GPL(phy_pm_runtime_put_sync);
+
+void phy_pm_runtime_allow(struct phy *phy)
+{
+	if (!pm_runtime_enabled(&phy->dev))
+		return;
+
+	pm_runtime_allow(&phy->dev);
+}
+EXPORT_SYMBOL_GPL(phy_pm_runtime_allow);
+
+void phy_pm_runtime_forbid(struct phy *phy)
+{
+	if (!pm_runtime_enabled(&phy->dev))
+		return;
+
+	pm_runtime_forbid(&phy->dev);
+}
+EXPORT_SYMBOL_GPL(phy_pm_runtime_forbid);
+
+int phy_init(struct phy *phy)
+{
+	int ret;
+
+	ret = phy_pm_runtime_get_sync(phy);
+	if (ret < 0 && ret != -ENOTSUPP)
+		return ret;
+
+	mutex_lock(&phy->mutex);
+	if (phy->init_count++ == 0 && phy->ops->init) {
+		ret = phy->ops->init(phy);
+		if (ret < 0) {
+			dev_err(&phy->dev, "phy init failed --> %d\n", ret);
+			goto out;
+		}
+	}
+
+out:
+	mutex_unlock(&phy->mutex);
+	phy_pm_runtime_put(phy);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(phy_init);
+
+int phy_exit(struct phy *phy)
+{
+	int ret;
+
+	ret = phy_pm_runtime_get_sync(phy);
+	if (ret < 0 && ret != -ENOTSUPP)
+		return ret;
+
+	mutex_lock(&phy->mutex);
+	if (--phy->init_count == 0 && phy->ops->exit) {
+		ret = phy->ops->exit(phy);
+		if (ret < 0) {
+			dev_err(&phy->dev, "phy exit failed --> %d\n", ret);
+			goto out;
+		}
+	}
+
+out:
+	mutex_unlock(&phy->mutex);
+	phy_pm_runtime_put(phy);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(phy_exit);
+
+int phy_power_on(struct phy *phy)
+{
+	int ret = -ENOTSUPP;
+
+	ret = phy_pm_runtime_get_sync(phy);
+	if (ret < 0 && ret != -ENOTSUPP)
+		return ret;
+
+	mutex_lock(&phy->mutex);
+	if (phy->power_count++ == 0 && phy->ops->power_on) {
+		ret = phy->ops->power_on(phy);
+		if (ret < 0) {
+			dev_err(&phy->dev, "phy poweron failed --> %d\n", ret);
+			goto out;
+		}
+	}
+
+out:
+	mutex_unlock(&phy->mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(phy_power_on);
+
+int phy_power_off(struct phy *phy)
+{
+	int ret = -ENOTSUPP;
+
+	mutex_lock(&phy->mutex);
+	if (--phy->power_count == 0 && phy->ops->power_off) {
+		ret =  phy->ops->power_off(phy);
+		if (ret < 0) {
+			dev_err(&phy->dev, "phy poweroff failed --> %d\n", ret);
+			goto out;
+		}
+	}
+
+out:
+	mutex_unlock(&phy->mutex);
+	phy_pm_runtime_put(phy);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(phy_power_off);
+
+/**
+ * of_phy_get() - lookup and obtain a reference to a phy by phandle
+ * @dev: device that requests this phy
+ * @index: the index of the phy
+ *
+ * Returns the phy associated with the given phandle value,
+ * after getting a refcount to it or -ENODEV if there is no such phy or
+ * -EPROBE_DEFER if there is a phandle to the phy, but the device is
+ * not yet loaded. This function uses of_xlate call back function provided
+ * while registering the phy_provider to find the phy instance.
+ */
+static struct phy *of_phy_get(struct device *dev, int index)
+{
+	int ret;
+	struct phy_provider *phy_provider;
+	struct phy *phy = NULL;
+	struct of_phandle_args args;
+
+	ret = of_parse_phandle_with_args(dev->of_node, "phys", "#phy-cells",
+		index, &args);
+	if (ret) {
+		dev_dbg(dev, "failed to get phy in %s node\n",
+			dev->of_node->full_name);
+		return ERR_PTR(-ENODEV);
+	}
+
+	mutex_lock(&phy_provider_mutex);
+	phy_provider = of_phy_provider_lookup(args.np);
+	if (IS_ERR(phy_provider) || !try_module_get(phy_provider->owner)) {
+		phy = ERR_PTR(-EPROBE_DEFER);
+		goto err0;
+	}
+
+	phy = phy_provider->of_xlate(phy_provider->dev, &args);
+	module_put(phy_provider->owner);
+
+err0:
+	mutex_unlock(&phy_provider_mutex);
+	of_node_put(args.np);
+
+	return phy;
+}
+
+/**
+ * phy_put() - release the PHY
+ * @phy: the phy returned by phy_get()
+ *
+ * Releases a refcount the caller received from phy_get().
+ */
+void phy_put(struct phy *phy)
+{
+	if (IS_ERR(phy))
+		return;
+
+	module_put(phy->ops->owner);
+	put_device(&phy->dev);
+}
+EXPORT_SYMBOL_GPL(phy_put);
+
+/**
+ * devm_phy_put() - release the PHY
+ * @dev: device that wants to release this phy
+ * @phy: the phy returned by devm_phy_get()
+ *
+ * destroys the devres associated with this phy and invokes phy_put
+ * to release the phy.
+ */
+void devm_phy_put(struct device *dev, struct phy *phy)
+{
+	int r;
+
+	r = devres_destroy(dev, devm_phy_release, devm_phy_match, phy);
+	dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
+}
+EXPORT_SYMBOL_GPL(devm_phy_put);
+
+/**
+ * of_phy_simple_xlate() - returns the phy instance from phy provider
+ * @dev: the PHY provider device
+ * @args: of_phandle_args (not used here)
+ *
+ * Intended to be used by phy provider for the common case where #phy-cells is
+ * 0. For other cases where #phy-cells is greater than '0', the phy provider
+ * should provide a custom of_xlate function that reads the *args* and returns
+ * the appropriate phy.
+ */
+struct phy *of_phy_simple_xlate(struct device *dev, struct of_phandle_args
+	*args)
+{
+	struct phy *phy;
+	struct class_dev_iter iter;
+	struct device_node *node = dev->of_node;
+
+	class_dev_iter_init(&iter, phy_class, NULL, NULL);
+	while ((dev = class_dev_iter_next(&iter))) {
+		phy = to_phy(dev);
+		if (node != phy->dev.of_node)
+			continue;
+
+		class_dev_iter_exit(&iter);
+		return phy;
+	}
+
+	class_dev_iter_exit(&iter);
+	return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL_GPL(of_phy_simple_xlate);
+
+/**
+ * phy_get() - lookup and obtain a reference to a phy.
+ * @dev: device that requests this phy
+ * @string: the phy name as given in the dt data or the name of the controller
+ * port for non-dt case
+ *
+ * Returns the phy driver, after getting a refcount to it; or
+ * -ENODEV if there is no such phy.  The caller is responsible for
+ * calling phy_put() to release that count.
+ */
+struct phy *phy_get(struct device *dev, const char *string)
+{
+	int index = 0;
+	struct phy *phy = NULL;
+
+	if (string == NULL) {
+		dev_WARN(dev, "missing string\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (dev->of_node) {
+		index = of_property_match_string(dev->of_node, "phy-names",
+			string);
+		phy = of_phy_get(dev, index);
+		if (IS_ERR(phy)) {
+			dev_err(dev, "unable to find phy\n");
+			return phy;
+		}
+	} else {
+		phy = phy_lookup(dev, string);
+		if (IS_ERR(phy)) {
+			dev_err(dev, "unable to find phy\n");
+			return phy;
+		}
+	}
+
+	if (!try_module_get(phy->ops->owner))
+		return ERR_PTR(-EPROBE_DEFER);
+
+	get_device(&phy->dev);
+
+	return phy;
+}
+EXPORT_SYMBOL_GPL(phy_get);
+
+/**
+ * devm_phy_get() - lookup and obtain a reference to a phy.
+ * @dev: device that requests this phy
+ * @string: the phy name as given in the dt data or phy device name
+ * for non-dt case
+ *
+ * Gets the phy using phy_get(), and associates a device with it using
+ * devres. On driver detach, release function is invoked on the devres data,
+ * then, devres data is freed.
+ */
+struct phy *devm_phy_get(struct device *dev, const char *string)
+{
+	struct phy **ptr, *phy;
+
+	ptr = devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	phy = phy_get(dev, string);
+	if (!IS_ERR(phy)) {
+		*ptr = phy;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return phy;
+}
+EXPORT_SYMBOL_GPL(devm_phy_get);
+
+/**
+ * phy_create() - create a new phy
+ * @dev: device that is creating the new phy
+ * @ops: function pointers for performing phy operations
+ * @init_data: contains the list of PHY consumers or NULL
+ *
+ * Called to create a phy using phy framework.
+ */
+struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
+	struct phy_init_data *init_data)
+{
+	int ret;
+	int id;
+	struct phy *phy;
+
+	if (!dev) {
+		dev_WARN(dev, "no device provided for PHY\n");
+		ret = -EINVAL;
+		goto err0;
+	}
+
+	phy = kzalloc(sizeof(*phy), GFP_KERNEL);
+	if (!phy) {
+		ret = -ENOMEM;
+		goto err0;
+	}
+
+	id = ida_simple_get(&phy_ida, 0, 0, GFP_KERNEL);
+	if (id < 0) {
+		dev_err(dev, "unable to get id\n");
+		ret = id;
+		goto err0;
+	}
+
+	device_initialize(&phy->dev);
+	mutex_init(&phy->mutex);
+
+	phy->dev.class = phy_class;
+	phy->dev.parent = dev;
+	phy->dev.of_node = dev->of_node;
+	phy->id = id;
+	phy->ops = ops;
+	phy->init_data = init_data;
+
+	ret = dev_set_name(&phy->dev, "phy-%s.%d", dev_name(dev), id);
+	if (ret)
+		goto err1;
+
+	ret = device_add(&phy->dev);
+	if (ret)
+		goto err1;
+
+	if (pm_runtime_enabled(dev)) {
+		pm_runtime_enable(&phy->dev);
+		pm_runtime_no_callbacks(&phy->dev);
+	}
+
+	return phy;
+
+err1:
+	ida_remove(&phy_ida, phy->id);
+	put_device(&phy->dev);
+	kfree(phy);
+
+err0:
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(phy_create);
+
+/**
+ * devm_phy_create() - create a new phy
+ * @dev: device that is creating the new phy
+ * @ops: function pointers for performing phy operations
+ * @init_data: contains the list of PHY consumers or NULL
+ *
+ * Creates a new PHY device adding it to the PHY class.
+ * While at that, it also associates the device with the phy using devres.
+ * On driver detach, release function is invoked on the devres data,
+ * then, devres data is freed.
+ */
+struct phy *devm_phy_create(struct device *dev, const struct phy_ops *ops,
+	struct phy_init_data *init_data)
+{
+	struct phy **ptr, *phy;
+
+	ptr = devres_alloc(devm_phy_consume, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	phy = phy_create(dev, ops, init_data);
+	if (!IS_ERR(phy)) {
+		*ptr = phy;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return phy;
+}
+EXPORT_SYMBOL_GPL(devm_phy_create);
+
+/**
+ * phy_destroy() - destroy the phy
+ * @phy: the phy to be destroyed
+ *
+ * Called to destroy the phy.
+ */
+void phy_destroy(struct phy *phy)
+{
+	pm_runtime_disable(&phy->dev);
+	device_unregister(&phy->dev);
+}
+EXPORT_SYMBOL_GPL(phy_destroy);
+
+/**
+ * devm_phy_destroy() - destroy the PHY
+ * @dev: device that wants to release this phy
+ * @phy: the phy returned by devm_phy_get()
+ *
+ * destroys the devres associated with this phy and invokes phy_destroy
+ * to destroy the phy.
+ */
+void devm_phy_destroy(struct device *dev, struct phy *phy)
+{
+	int r;
+
+	r = devres_destroy(dev, devm_phy_consume, devm_phy_match, phy);
+	dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
+}
+EXPORT_SYMBOL_GPL(devm_phy_destroy);
+
+/**
+ * __of_phy_provider_register() - create/register phy provider with the framework
+ * @dev: struct device of the phy provider
+ * @owner: the module owner containing of_xlate
+ * @of_xlate: function pointer to obtain phy instance from phy provider
+ *
+ * Creates struct phy_provider from dev and of_xlate function pointer.
+ * This is used in the case of dt boot for finding the phy instance from
+ * phy provider.
+ */
+struct phy_provider *__of_phy_provider_register(struct device *dev,
+	struct module *owner, struct phy * (*of_xlate)(struct device *dev,
+	struct of_phandle_args *args))
+{
+	struct phy_provider *phy_provider;
+
+	phy_provider = kzalloc(sizeof(*phy_provider), GFP_KERNEL);
+	if (!phy_provider)
+		return ERR_PTR(-ENOMEM);
+
+	phy_provider->dev = dev;
+	phy_provider->owner = owner;
+	phy_provider->of_xlate = of_xlate;
+
+	mutex_lock(&phy_provider_mutex);
+	list_add_tail(&phy_provider->list, &phy_provider_list);
+	mutex_unlock(&phy_provider_mutex);
+
+	return phy_provider;
+}
+EXPORT_SYMBOL_GPL(__of_phy_provider_register);
+
+/**
+ * __devm_of_phy_provider_register() - create/register phy provider with the
+ * framework
+ * @dev: struct device of the phy provider
+ * @owner: the module owner containing of_xlate
+ * @of_xlate: function pointer to obtain phy instance from phy provider
+ *
+ * Creates struct phy_provider from dev and of_xlate function pointer.
+ * This is used in the case of dt boot for finding the phy instance from
+ * phy provider. While at that, it also associates the device with the
+ * phy provider using devres. On driver detach, release function is invoked
+ * on the devres data, then, devres data is freed.
+ */
+struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
+	struct module *owner, struct phy * (*of_xlate)(struct device *dev,
+	struct of_phandle_args *args))
+{
+	struct phy_provider **ptr, *phy_provider;
+
+	ptr = devres_alloc(devm_phy_provider_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	phy_provider = __of_phy_provider_register(dev, owner, of_xlate);
+	if (!IS_ERR(phy_provider)) {
+		*ptr = phy_provider;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return phy_provider;
+}
+EXPORT_SYMBOL_GPL(__devm_of_phy_provider_register);
+
+/**
+ * of_phy_provider_unregister() - unregister phy provider from the framework
+ * @phy_provider: phy provider returned by of_phy_provider_register()
+ *
+ * Removes the phy_provider created using of_phy_provider_register().
+ */
+void of_phy_provider_unregister(struct phy_provider *phy_provider)
+{
+	if (IS_ERR(phy_provider))
+		return;
+
+	mutex_lock(&phy_provider_mutex);
+	list_del(&phy_provider->list);
+	kfree(phy_provider);
+	mutex_unlock(&phy_provider_mutex);
+}
+EXPORT_SYMBOL_GPL(of_phy_provider_unregister);
+
+/**
+ * devm_of_phy_provider_unregister() - remove phy provider from the framework
+ * @dev: struct device of the phy provider
+ *
+ * destroys the devres associated with this phy provider and invokes
+ * of_phy_provider_unregister to unregister the phy provider.
+ */
+void devm_of_phy_provider_unregister(struct device *dev,
+	struct phy_provider *phy_provider) {
+	int r;
+
+	r = devres_destroy(dev, devm_phy_provider_release, devm_phy_match,
+		phy_provider);
+	dev_WARN_ONCE(dev, r, "couldn't find PHY provider device resource\n");
+}
+EXPORT_SYMBOL_GPL(devm_of_phy_provider_unregister);
+
+/**
+ * phy_release() - release the phy
+ * @dev: the dev member within phy
+ *
+ * When the last reference to the device is removed, it is called
+ * from the embedded kobject as release method.
+ */
+static void phy_release(struct device *dev)
+{
+	struct phy *phy;
+
+	phy = to_phy(dev);
+	dev_vdbg(dev, "releasing '%s'\n", dev_name(dev));
+	ida_remove(&phy_ida, phy->id);
+	kfree(phy);
+}
+
+static int __init phy_core_init(void)
+{
+	phy_class = class_create(THIS_MODULE, "phy");
+	if (IS_ERR(phy_class)) {
+		pr_err("failed to create phy class --> %ld\n",
+			PTR_ERR(phy_class));
+		return PTR_ERR(phy_class);
+	}
+
+	phy_class->dev_release = phy_release;
+
+	return 0;
+}
+module_init(phy_core_init);
+
+static void __exit phy_core_exit(void)
+{
+	class_destroy(phy_class);
+}
+module_exit(phy_core_exit);
+
+MODULE_DESCRIPTION("Generic PHY Framework");
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/phy-exynos-dp-video.c
new file mode 100644
index 0000000..1dbe6ce
--- /dev/null
+++ b/drivers/phy/phy-exynos-dp-video.c
@@ -0,0 +1,111 @@
+/*
+ * Samsung EXYNOS SoC series Display Port PHY driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <jg1.han@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+/* DPTX_PHY_CONTROL register */
+#define EXYNOS_DPTX_PHY_ENABLE		(1 << 0)
+
+struct exynos_dp_video_phy {
+	void __iomem *regs;
+};
+
+static int __set_phy_state(struct exynos_dp_video_phy *state, unsigned int on)
+{
+	u32 reg;
+
+	reg = readl(state->regs);
+	if (on)
+		reg |= EXYNOS_DPTX_PHY_ENABLE;
+	else
+		reg &= ~EXYNOS_DPTX_PHY_ENABLE;
+	writel(reg, state->regs);
+
+	return 0;
+}
+
+static int exynos_dp_video_phy_power_on(struct phy *phy)
+{
+	struct exynos_dp_video_phy *state = phy_get_drvdata(phy);
+
+	return __set_phy_state(state, 1);
+}
+
+static int exynos_dp_video_phy_power_off(struct phy *phy)
+{
+	struct exynos_dp_video_phy *state = phy_get_drvdata(phy);
+
+	return __set_phy_state(state, 0);
+}
+
+static struct phy_ops exynos_dp_video_phy_ops = {
+	.power_on	= exynos_dp_video_phy_power_on,
+	.power_off	= exynos_dp_video_phy_power_off,
+	.owner		= THIS_MODULE,
+};
+
+static int exynos_dp_video_phy_probe(struct platform_device *pdev)
+{
+	struct exynos_dp_video_phy *state;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct phy_provider *phy_provider;
+	struct phy *phy;
+
+	state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	state->regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(state->regs))
+		return PTR_ERR(state->regs);
+
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	if (IS_ERR(phy_provider))
+		return PTR_ERR(phy_provider);
+
+	phy = devm_phy_create(dev, &exynos_dp_video_phy_ops, NULL);
+	if (IS_ERR(phy)) {
+		dev_err(dev, "failed to create Display Port PHY\n");
+		return PTR_ERR(phy);
+	}
+	phy_set_drvdata(phy, state);
+
+	return 0;
+}
+
+static const struct of_device_id exynos_dp_video_phy_of_match[] = {
+	{ .compatible = "samsung,exynos5250-dp-video-phy" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, exynos_dp_video_phy_of_match);
+
+static struct platform_driver exynos_dp_video_phy_driver = {
+	.probe	= exynos_dp_video_phy_probe,
+	.driver = {
+		.name	= "exynos-dp-video-phy",
+		.owner	= THIS_MODULE,
+		.of_match_table	= exynos_dp_video_phy_of_match,
+	}
+};
+module_platform_driver(exynos_dp_video_phy_driver);
+
+MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
+MODULE_DESCRIPTION("Samsung EXYNOS SoC DP PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c
new file mode 100644
index 0000000..0c5efab
--- /dev/null
+++ b/drivers/phy/phy-exynos-mipi-video.c
@@ -0,0 +1,176 @@
+/*
+ * Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+/* MIPI_PHYn_CONTROL register offset: n = 0..1 */
+#define EXYNOS_MIPI_PHY_CONTROL(n)	((n) * 4)
+#define EXYNOS_MIPI_PHY_ENABLE		(1 << 0)
+#define EXYNOS_MIPI_PHY_SRESETN		(1 << 1)
+#define EXYNOS_MIPI_PHY_MRESETN		(1 << 2)
+#define EXYNOS_MIPI_PHY_RESET_MASK	(3 << 1)
+
+enum exynos_mipi_phy_id {
+	EXYNOS_MIPI_PHY_ID_CSIS0,
+	EXYNOS_MIPI_PHY_ID_DSIM0,
+	EXYNOS_MIPI_PHY_ID_CSIS1,
+	EXYNOS_MIPI_PHY_ID_DSIM1,
+	EXYNOS_MIPI_PHYS_NUM
+};
+
+#define is_mipi_dsim_phy_id(id) \
+	((id) == EXYNOS_MIPI_PHY_ID_DSIM0 || (id) == EXYNOS_MIPI_PHY_ID_DSIM1)
+
+struct exynos_mipi_video_phy {
+	spinlock_t slock;
+	struct video_phy_desc {
+		struct phy *phy;
+		unsigned int index;
+	} phys[EXYNOS_MIPI_PHYS_NUM];
+	void __iomem *regs;
+};
+
+static int __set_phy_state(struct exynos_mipi_video_phy *state,
+			enum exynos_mipi_phy_id id, unsigned int on)
+{
+	void __iomem *addr;
+	u32 reg, reset;
+
+	addr = state->regs + EXYNOS_MIPI_PHY_CONTROL(id / 2);
+
+	if (is_mipi_dsim_phy_id(id))
+		reset = EXYNOS_MIPI_PHY_MRESETN;
+	else
+		reset = EXYNOS_MIPI_PHY_SRESETN;
+
+	spin_lock(&state->slock);
+	reg = readl(addr);
+	if (on)
+		reg |= reset;
+	else
+		reg &= ~reset;
+	writel(reg, addr);
+
+	/* Clear ENABLE bit only if MRESETN, SRESETN bits are not set. */
+	if (on)
+		reg |= EXYNOS_MIPI_PHY_ENABLE;
+	else if (!(reg & EXYNOS_MIPI_PHY_RESET_MASK))
+		reg &= ~EXYNOS_MIPI_PHY_ENABLE;
+
+	writel(reg, addr);
+	spin_unlock(&state->slock);
+	return 0;
+}
+
+#define to_mipi_video_phy(desc) \
+	container_of((desc), struct exynos_mipi_video_phy, phys[(desc)->index]);
+
+static int exynos_mipi_video_phy_power_on(struct phy *phy)
+{
+	struct video_phy_desc *phy_desc = phy_get_drvdata(phy);
+	struct exynos_mipi_video_phy *state = to_mipi_video_phy(phy_desc);
+
+	return __set_phy_state(state, phy_desc->index, 1);
+}
+
+static int exynos_mipi_video_phy_power_off(struct phy *phy)
+{
+	struct video_phy_desc *phy_desc = phy_get_drvdata(phy);
+	struct exynos_mipi_video_phy *state = to_mipi_video_phy(phy_desc);
+
+	return __set_phy_state(state, phy_desc->index, 0);
+}
+
+static struct phy *exynos_mipi_video_phy_xlate(struct device *dev,
+					struct of_phandle_args *args)
+{
+	struct exynos_mipi_video_phy *state = dev_get_drvdata(dev);
+
+	if (WARN_ON(args->args[0] > EXYNOS_MIPI_PHYS_NUM))
+		return ERR_PTR(-ENODEV);
+
+	return state->phys[args->args[0]].phy;
+}
+
+static struct phy_ops exynos_mipi_video_phy_ops = {
+	.power_on	= exynos_mipi_video_phy_power_on,
+	.power_off	= exynos_mipi_video_phy_power_off,
+	.owner		= THIS_MODULE,
+};
+
+static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
+{
+	struct exynos_mipi_video_phy *state;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct phy_provider *phy_provider;
+	unsigned int i;
+
+	state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	state->regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(state->regs))
+		return PTR_ERR(state->regs);
+
+	dev_set_drvdata(dev, state);
+	spin_lock_init(&state->slock);
+
+	phy_provider = devm_of_phy_provider_register(dev,
+					exynos_mipi_video_phy_xlate);
+	if (IS_ERR(phy_provider))
+		return PTR_ERR(phy_provider);
+
+	for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) {
+		struct phy *phy = devm_phy_create(dev,
+					&exynos_mipi_video_phy_ops, NULL);
+		if (IS_ERR(phy)) {
+			dev_err(dev, "failed to create PHY %d\n", i);
+			return PTR_ERR(phy);
+		}
+
+		state->phys[i].phy = phy;
+		state->phys[i].index = i;
+		phy_set_drvdata(phy, &state->phys[i]);
+	}
+
+	return 0;
+}
+
+static const struct of_device_id exynos_mipi_video_phy_of_match[] = {
+	{ .compatible = "samsung,s5pv210-mipi-video-phy" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, exynos_mipi_video_phy_of_match);
+
+static struct platform_driver exynos_mipi_video_phy_driver = {
+	.probe	= exynos_mipi_video_phy_probe,
+	.driver = {
+		.of_match_table	= exynos_mipi_video_phy_of_match,
+		.name  = "exynos-mipi-video-phy",
+		.owner = THIS_MODULE,
+	}
+};
+module_platform_driver(exynos_mipi_video_phy_driver);
+
+MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC MIPI CSI-2/DSI PHY driver");
+MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c
similarity index 81%
rename from drivers/usb/phy/phy-omap-usb2.c
rename to drivers/phy/phy-omap-usb2.c
index d266861..bfc5c33 100644
--- a/drivers/usb/phy/phy-omap-usb2.c
+++ b/drivers/phy/phy-omap-usb2.c
@@ -28,6 +28,8 @@
 #include <linux/pm_runtime.h>
 #include <linux/delay.h>
 #include <linux/usb/omap_control_usb.h>
+#include <linux/phy/phy.h>
+#include <linux/of_platform.h>
 
 /**
  * omap_usb2_set_comparator - links the comparator present in the sytem with
@@ -118,10 +120,42 @@
 	return 0;
 }
 
+static int omap_usb_power_off(struct phy *x)
+{
+	struct omap_usb *phy = phy_get_drvdata(x);
+
+	omap_control_usb_phy_power(phy->control_dev, 0);
+
+	return 0;
+}
+
+static int omap_usb_power_on(struct phy *x)
+{
+	struct omap_usb *phy = phy_get_drvdata(x);
+
+	omap_control_usb_phy_power(phy->control_dev, 1);
+
+	return 0;
+}
+
+static struct phy_ops ops = {
+	.power_on	= omap_usb_power_on,
+	.power_off	= omap_usb_power_off,
+	.owner		= THIS_MODULE,
+};
+
 static int omap_usb2_probe(struct platform_device *pdev)
 {
-	struct omap_usb			*phy;
-	struct usb_otg			*otg;
+	struct omap_usb	*phy;
+	struct phy *generic_phy;
+	struct phy_provider *phy_provider;
+	struct usb_otg *otg;
+	struct device_node *node = pdev->dev.of_node;
+	struct device_node *control_node;
+	struct platform_device *control_pdev;
+
+	if (!node)
+		return -EINVAL;
 
 	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
 	if (!phy) {
@@ -143,12 +177,25 @@
 	phy->phy.otg		= otg;
 	phy->phy.type		= USB_PHY_TYPE_USB2;
 
-	phy->control_dev = omap_get_control_dev();
-	if (IS_ERR(phy->control_dev)) {
-		dev_dbg(&pdev->dev, "Failed to get control device\n");
-		return -ENODEV;
+	phy_provider = devm_of_phy_provider_register(phy->dev,
+			of_phy_simple_xlate);
+	if (IS_ERR(phy_provider))
+		return PTR_ERR(phy_provider);
+
+	control_node = of_parse_phandle(node, "ctrl-module", 0);
+	if (!control_node) {
+		dev_err(&pdev->dev, "Failed to get control device phandle\n");
+		return -EINVAL;
 	}
 
+	control_pdev = of_find_device_by_node(control_node);
+	if (!control_pdev) {
+		dev_err(&pdev->dev, "Failed to get control device\n");
+		return -EINVAL;
+	}
+
+	phy->control_dev = &control_pdev->dev;
+
 	phy->is_suspended	= 1;
 	omap_control_usb_phy_power(phy->control_dev, 0);
 
@@ -158,6 +205,15 @@
 	otg->start_srp		= omap_usb_start_srp;
 	otg->phy		= &phy->phy;
 
+	platform_set_drvdata(pdev, phy);
+	pm_runtime_enable(phy->dev);
+
+	generic_phy = devm_phy_create(phy->dev, &ops, NULL);
+	if (IS_ERR(generic_phy))
+		return PTR_ERR(generic_phy);
+
+	phy_set_drvdata(generic_phy, phy);
+
 	phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
 	if (IS_ERR(phy->wkupclk)) {
 		dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
@@ -173,10 +229,6 @@
 
 	usb_add_phy_dev(&phy->phy);
 
-	platform_set_drvdata(pdev, phy);
-
-	pm_runtime_enable(phy->dev);
-
 	return 0;
 }
 
diff --git a/drivers/usb/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c
similarity index 94%
rename from drivers/usb/phy/phy-twl4030-usb.c
rename to drivers/phy/phy-twl4030-usb.c
index 90730c8..daf65e6 100644
--- a/drivers/usb/phy/phy-twl4030-usb.c
+++ b/drivers/phy/phy-twl4030-usb.c
@@ -33,6 +33,7 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/usb/otg.h>
+#include <linux/phy/phy.h>
 #include <linux/usb/musb-omap.h>
 #include <linux/usb/ulpi.h>
 #include <linux/i2c/twl.h>
@@ -421,17 +422,20 @@
 	}
 }
 
-static void twl4030_phy_suspend(struct twl4030_usb *twl, int controller_off)
+static int twl4030_phy_power_off(struct phy *phy)
 {
+	struct twl4030_usb *twl = phy_get_drvdata(phy);
+
 	if (twl->asleep)
-		return;
+		return 0;
 
 	twl4030_phy_power(twl, 0);
 	twl->asleep = 1;
 	dev_dbg(twl->dev, "%s\n", __func__);
+	return 0;
 }
 
-static void __twl4030_phy_resume(struct twl4030_usb *twl)
+static void __twl4030_phy_power_on(struct twl4030_usb *twl)
 {
 	twl4030_phy_power(twl, 1);
 	twl4030_i2c_access(twl, 1);
@@ -440,11 +444,13 @@
 		twl4030_i2c_access(twl, 0);
 }
 
-static void twl4030_phy_resume(struct twl4030_usb *twl)
+static int twl4030_phy_power_on(struct phy *phy)
 {
+	struct twl4030_usb *twl = phy_get_drvdata(phy);
+
 	if (!twl->asleep)
-		return;
-	__twl4030_phy_resume(twl);
+		return 0;
+	__twl4030_phy_power_on(twl);
 	twl->asleep = 0;
 	dev_dbg(twl->dev, "%s\n", __func__);
 
@@ -457,6 +463,7 @@
 		cancel_delayed_work(&twl->id_workaround_work);
 		schedule_delayed_work(&twl->id_workaround_work, HZ);
 	}
+	return 0;
 }
 
 static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
@@ -587,9 +594,9 @@
 	}
 }
 
-static int twl4030_usb_phy_init(struct usb_phy *phy)
+static int twl4030_phy_init(struct phy *phy)
 {
-	struct twl4030_usb *twl = phy_to_twl(phy);
+	struct twl4030_usb *twl = phy_get_drvdata(phy);
 	enum omap_musb_vbus_id_status status;
 
 	/*
@@ -602,25 +609,15 @@
 	status = twl4030_usb_linkstat(twl);
 	twl->linkstat = status;
 
-	if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID)
+	if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) {
 		omap_musb_mailbox(twl->linkstat);
+		twl4030_phy_power_on(phy);
+	}
 
 	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
 	return 0;
 }
 
-static int twl4030_set_suspend(struct usb_phy *x, int suspend)
-{
-	struct twl4030_usb *twl = phy_to_twl(x);
-
-	if (suspend)
-		twl4030_phy_suspend(twl, 1);
-	else
-		twl4030_phy_resume(twl);
-
-	return 0;
-}
-
 static int twl4030_set_peripheral(struct usb_otg *otg,
 					struct usb_gadget *gadget)
 {
@@ -646,13 +643,23 @@
 	return 0;
 }
 
+static const struct phy_ops ops = {
+	.init		= twl4030_phy_init,
+	.power_on	= twl4030_phy_power_on,
+	.power_off	= twl4030_phy_power_off,
+	.owner		= THIS_MODULE,
+};
+
 static int twl4030_usb_probe(struct platform_device *pdev)
 {
 	struct twl4030_usb_data *pdata = dev_get_platdata(&pdev->dev);
 	struct twl4030_usb	*twl;
+	struct phy		*phy;
 	int			status, err;
 	struct usb_otg		*otg;
 	struct device_node	*np = pdev->dev.of_node;
+	struct phy_provider	*phy_provider;
+	struct phy_init_data	*init_data = NULL;
 
 	twl = devm_kzalloc(&pdev->dev, sizeof *twl, GFP_KERNEL);
 	if (!twl)
@@ -661,9 +668,10 @@
 	if (np)
 		of_property_read_u32(np, "usb_mode",
 				(enum twl4030_usb_mode *)&twl->usb_mode);
-	else if (pdata)
+	else if (pdata) {
 		twl->usb_mode = pdata->usb_mode;
-	else {
+		init_data = pdata->init_data;
+	} else {
 		dev_err(&pdev->dev, "twl4030 initialized without pdata\n");
 		return -EINVAL;
 	}
@@ -682,13 +690,24 @@
 	twl->phy.label		= "twl4030";
 	twl->phy.otg		= otg;
 	twl->phy.type		= USB_PHY_TYPE_USB2;
-	twl->phy.set_suspend	= twl4030_set_suspend;
-	twl->phy.init		= twl4030_usb_phy_init;
 
 	otg->phy		= &twl->phy;
 	otg->set_host		= twl4030_set_host;
 	otg->set_peripheral	= twl4030_set_peripheral;
 
+	phy_provider = devm_of_phy_provider_register(twl->dev,
+		of_phy_simple_xlate);
+	if (IS_ERR(phy_provider))
+		return PTR_ERR(phy_provider);
+
+	phy = devm_phy_create(twl->dev, &ops, init_data);
+	if (IS_ERR(phy)) {
+		dev_dbg(&pdev->dev, "Failed to create PHY\n");
+		return PTR_ERR(phy);
+	}
+
+	phy_set_drvdata(phy, twl);
+
 	/* init spinlock for workqueue */
 	spin_lock_init(&twl->lock);
 
@@ -705,6 +724,8 @@
 	if (device_create_file(&pdev->dev, &dev_attr_vbus))
 		dev_warn(&pdev->dev, "could not create sysfs file\n");
 
+	ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
+
 	/* Our job is to use irqs and status from the power module
 	 * to keep the transceiver disabled when nothing's connected.
 	 *
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index b6e864e..33f9dc1 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -49,6 +49,35 @@
 	bool "AB8505 pin controller driver"
 	depends on PINCTRL_ABX500 && ARCH_U8500
 
+config PINCTRL_ADI2
+	bool "ADI pin controller driver"
+	depends on BLACKFIN
+	select PINMUX
+	select IRQ_DOMAIN
+	help
+	  This is the pin controller and gpio driver for ADI BF54x, BF60x and
+	  future processors. This option is selected automatically when specific
+	  machine and arch are selected to build.
+
+config PINCTRL_AS3722
+	bool "Pinctrl and GPIO driver for ams AS3722 PMIC"
+	depends on MFD_AS3722 && GPIOLIB
+	select PINMUX
+	select GENERIC_PINCONF
+	help
+	  AS3722 device supports the configuration of GPIO pins for different
+	  functionality. This driver supports the pinmux, push-pull and
+	  open drain configuration for the GPIO pins of AS3722 devices. It also
+	  supports the GPIO functionality through gpiolib.
+
+config PINCTRL_BF54x
+	def_bool y if BF54x
+	select PINCTRL_ADI2
+
+config PINCTRL_BF60x
+	def_bool y if BF60x
+	select PINCTRL_ADI2
+
 config PINCTRL_AT91
 	bool "AT91 pinctrl driver"
 	depends on OF
@@ -80,6 +109,19 @@
 	select PINMUX
 	select PINCONF
 
+config PINCTRL_IMX1_CORE
+	bool
+	select PINMUX
+	select PINCONF
+
+config PINCTRL_IMX27
+	bool "IMX27 pinctrl driver"
+	depends on OF
+	depends on SOC_IMX27
+	select PINCTRL_IMX1_CORE
+	help
+	  Say Y here to enable the imx27 pinctrl driver
+
 config PINCTRL_IMX35
 	bool "IMX35 pinctrl driver"
 	depends on OF
@@ -88,6 +130,14 @@
 	help
 	  Say Y here to enable the imx35 pinctrl driver
 
+config PINCTRL_IMX50
+	bool "IMX50 pinctrl driver"
+	depends on OF
+	depends on SOC_IMX50
+	select PINCTRL_IMX
+	help
+	  Say Y here to enable the imx50 pinctrl driver
+
 config PINCTRL_IMX51
 	bool "IMX51 pinctrl driver"
 	depends on OF
@@ -292,6 +342,10 @@
 	depends on SOC_TYPE_XWAY
 	depends on PINCTRL_LANTIQ
 
+config PINCTRL_TB10X
+	bool
+	depends on ARC_PLAT_TB10X
+
 endmenu
 
 endif
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 496d9bf..4f7be29 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -14,11 +14,18 @@
 obj-$(CONFIG_PINCTRL_AB8540)	+= pinctrl-ab8540.o
 obj-$(CONFIG_PINCTRL_AB9540)	+= pinctrl-ab9540.o
 obj-$(CONFIG_PINCTRL_AB8505)	+= pinctrl-ab8505.o
+obj-$(CONFIG_PINCTRL_ADI2)	+= pinctrl-adi2.o
+obj-$(CONFIG_PINCTRL_AS3722)	+= pinctrl-as3722.o
+obj-$(CONFIG_PINCTRL_BF54x)	+= pinctrl-adi2-bf54x.o
+obj-$(CONFIG_PINCTRL_BF60x)	+= pinctrl-adi2-bf60x.o
 obj-$(CONFIG_PINCTRL_AT91)	+= pinctrl-at91.o
 obj-$(CONFIG_PINCTRL_BCM2835)	+= pinctrl-bcm2835.o
 obj-$(CONFIG_PINCTRL_BAYTRAIL)	+= pinctrl-baytrail.o
 obj-$(CONFIG_PINCTRL_IMX)	+= pinctrl-imx.o
+obj-$(CONFIG_PINCTRL_IMX1_CORE)	+= pinctrl-imx1-core.o
+obj-$(CONFIG_PINCTRL_IMX27)	+= pinctrl-imx27.o
 obj-$(CONFIG_PINCTRL_IMX35)	+= pinctrl-imx35.o
+obj-$(CONFIG_PINCTRL_IMX50)	+= pinctrl-imx50.o
 obj-$(CONFIG_PINCTRL_IMX51)	+= pinctrl-imx51.o
 obj-$(CONFIG_PINCTRL_IMX53)	+= pinctrl-imx53.o
 obj-$(CONFIG_PINCTRL_IMX6Q)	+= pinctrl-imx6q.o
@@ -52,6 +59,7 @@
 obj-$(CONFIG_PINCTRL_S3C64XX)	+= pinctrl-s3c64xx.o
 obj-$(CONFIG_PINCTRL_XWAY)	+= pinctrl-xway.o
 obj-$(CONFIG_PINCTRL_LANTIQ)	+= pinctrl-lantiq.o
+obj-$(CONFIG_PINCTRL_TB10X)	+= pinctrl-tb10x.o
 obj-$(CONFIG_PINCTRL_ST) 	+= pinctrl-st.o
 obj-$(CONFIG_PINCTRL_VF610)	+= pinctrl-vf610.o
 
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 92f86ab..5ee61a4 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -462,6 +462,20 @@
 }
 EXPORT_SYMBOL_GPL(pinctrl_find_and_add_gpio_range);
 
+int pinctrl_get_group_pins(struct pinctrl_dev *pctldev, const char *pin_group,
+				const unsigned **pins, unsigned *num_pins)
+{
+	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
+	int gs;
+
+	gs = pinctrl_get_group_selector(pctldev, pin_group);
+	if (gs < 0)
+		return gs;
+
+	return pctlops->get_group_pins(pctldev, gs, pins, num_pins);
+}
+EXPORT_SYMBOL_GPL(pinctrl_get_group_pins);
+
 /**
  * pinctrl_find_gpio_range_from_pin() - locate the GPIO range for a pin
  * @pctldev: the pin controller device to look in
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-370.c b/drivers/pinctrl/mvebu/pinctrl-armada-370.c
index 48e21a2..ae1f760 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-370.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-370.c
@@ -408,7 +408,7 @@
 	.driver = {
 		.name = "armada-370-pinctrl",
 		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(armada_370_pinctrl_of_match),
+		.of_match_table = armada_370_pinctrl_of_match,
 	},
 	.probe = armada_370_pinctrl_probe,
 	.remove = armada_370_pinctrl_remove,
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
index ab5dc04..843a51f 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
@@ -455,7 +455,7 @@
 	.driver = {
 		.name = "armada-xp-pinctrl",
 		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(armada_xp_pinctrl_of_match),
+		.of_match_table = armada_xp_pinctrl_of_match,
 	},
 	.probe = armada_xp_pinctrl_probe,
 	.remove = armada_xp_pinctrl_remove,
diff --git a/drivers/pinctrl/mvebu/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c
index 29f7e4f..4726839 100644
--- a/drivers/pinctrl/mvebu/pinctrl-dove.c
+++ b/drivers/pinctrl/mvebu/pinctrl-dove.c
@@ -335,7 +335,7 @@
 	unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2);
 
 	gcfg1 &= ~DOVE_TWSI_ENABLE_OPTION1;
-	gcfg2 &= ~(DOVE_TWSI_ENABLE_OPTION2 | DOVE_TWSI_ENABLE_OPTION2);
+	gcfg2 &= ~(DOVE_TWSI_ENABLE_OPTION2 | DOVE_TWSI_ENABLE_OPTION3);
 
 	switch (config) {
 	case 1:
@@ -806,7 +806,7 @@
 	.driver = {
 		.name = "dove-pinctrl",
 		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(dove_pinctrl_of_match),
+		.of_match_table = dove_pinctrl_of_match,
 	},
 	.probe = dove_pinctrl_probe,
 	.remove = dove_pinctrl_remove,
diff --git a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
index cdd483d..6b504b5 100644
--- a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
+++ b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
@@ -471,7 +471,7 @@
 	.driver = {
 		.name = "kirkwood-pinctrl",
 		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(kirkwood_pinctrl_of_match),
+		.of_match_table = kirkwood_pinctrl_of_match,
 	},
 	.probe = kirkwood_pinctrl_probe,
 	.remove = kirkwood_pinctrl_remove,
diff --git a/drivers/pinctrl/pinctrl-adi2-bf54x.c b/drivers/pinctrl/pinctrl-adi2-bf54x.c
new file mode 100644
index 0000000..ea9d9ab
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-adi2-bf54x.c
@@ -0,0 +1,592 @@
+/*
+ * Pinctrl Driver for ADI GPIO2 controller
+ *
+ * Copyright 2007-2013 Analog Devices Inc.
+ *
+ * Licensed under the GPLv2 or later
+ */
+
+#include <asm/portmux.h>
+#include "pinctrl-adi2.h"
+
+static const struct pinctrl_pin_desc adi_pads[] = {
+	PINCTRL_PIN(0, "PA0"),
+	PINCTRL_PIN(1, "PA1"),
+	PINCTRL_PIN(2, "PA2"),
+	PINCTRL_PIN(3, "PG3"),
+	PINCTRL_PIN(4, "PA4"),
+	PINCTRL_PIN(5, "PA5"),
+	PINCTRL_PIN(6, "PA6"),
+	PINCTRL_PIN(7, "PA7"),
+	PINCTRL_PIN(8, "PA8"),
+	PINCTRL_PIN(9, "PA9"),
+	PINCTRL_PIN(10, "PA10"),
+	PINCTRL_PIN(11, "PA11"),
+	PINCTRL_PIN(12, "PA12"),
+	PINCTRL_PIN(13, "PA13"),
+	PINCTRL_PIN(14, "PA14"),
+	PINCTRL_PIN(15, "PA15"),
+	PINCTRL_PIN(16, "PB0"),
+	PINCTRL_PIN(17, "PB1"),
+	PINCTRL_PIN(18, "PB2"),
+	PINCTRL_PIN(19, "PB3"),
+	PINCTRL_PIN(20, "PB4"),
+	PINCTRL_PIN(21, "PB5"),
+	PINCTRL_PIN(22, "PB6"),
+	PINCTRL_PIN(23, "PB7"),
+	PINCTRL_PIN(24, "PB8"),
+	PINCTRL_PIN(25, "PB9"),
+	PINCTRL_PIN(26, "PB10"),
+	PINCTRL_PIN(27, "PB11"),
+	PINCTRL_PIN(28, "PB12"),
+	PINCTRL_PIN(29, "PB13"),
+	PINCTRL_PIN(30, "PB14"),
+	PINCTRL_PIN(32, "PC0"),
+	PINCTRL_PIN(33, "PC1"),
+	PINCTRL_PIN(34, "PC2"),
+	PINCTRL_PIN(35, "PC3"),
+	PINCTRL_PIN(36, "PC4"),
+	PINCTRL_PIN(37, "PC5"),
+	PINCTRL_PIN(38, "PC6"),
+	PINCTRL_PIN(39, "PC7"),
+	PINCTRL_PIN(40, "PC8"),
+	PINCTRL_PIN(41, "PC9"),
+	PINCTRL_PIN(42, "PC10"),
+	PINCTRL_PIN(43, "PC11"),
+	PINCTRL_PIN(44, "PC12"),
+	PINCTRL_PIN(45, "PC13"),
+	PINCTRL_PIN(48, "PD0"),
+	PINCTRL_PIN(49, "PD1"),
+	PINCTRL_PIN(50, "PD2"),
+	PINCTRL_PIN(51, "PD3"),
+	PINCTRL_PIN(52, "PD4"),
+	PINCTRL_PIN(53, "PD5"),
+	PINCTRL_PIN(54, "PD6"),
+	PINCTRL_PIN(55, "PD7"),
+	PINCTRL_PIN(56, "PD8"),
+	PINCTRL_PIN(57, "PD9"),
+	PINCTRL_PIN(58, "PD10"),
+	PINCTRL_PIN(59, "PD11"),
+	PINCTRL_PIN(60, "PD12"),
+	PINCTRL_PIN(61, "PD13"),
+	PINCTRL_PIN(62, "PD14"),
+	PINCTRL_PIN(63, "PD15"),
+	PINCTRL_PIN(64, "PE0"),
+	PINCTRL_PIN(65, "PE1"),
+	PINCTRL_PIN(66, "PE2"),
+	PINCTRL_PIN(67, "PE3"),
+	PINCTRL_PIN(68, "PE4"),
+	PINCTRL_PIN(69, "PE5"),
+	PINCTRL_PIN(70, "PE6"),
+	PINCTRL_PIN(71, "PE7"),
+	PINCTRL_PIN(72, "PE8"),
+	PINCTRL_PIN(73, "PE9"),
+	PINCTRL_PIN(74, "PE10"),
+	PINCTRL_PIN(75, "PE11"),
+	PINCTRL_PIN(76, "PE12"),
+	PINCTRL_PIN(77, "PE13"),
+	PINCTRL_PIN(78, "PE14"),
+	PINCTRL_PIN(79, "PE15"),
+	PINCTRL_PIN(80, "PF0"),
+	PINCTRL_PIN(81, "PF1"),
+	PINCTRL_PIN(82, "PF2"),
+	PINCTRL_PIN(83, "PF3"),
+	PINCTRL_PIN(84, "PF4"),
+	PINCTRL_PIN(85, "PF5"),
+	PINCTRL_PIN(86, "PF6"),
+	PINCTRL_PIN(87, "PF7"),
+	PINCTRL_PIN(88, "PF8"),
+	PINCTRL_PIN(89, "PF9"),
+	PINCTRL_PIN(90, "PF10"),
+	PINCTRL_PIN(91, "PF11"),
+	PINCTRL_PIN(92, "PF12"),
+	PINCTRL_PIN(93, "PF13"),
+	PINCTRL_PIN(94, "PF14"),
+	PINCTRL_PIN(95, "PF15"),
+	PINCTRL_PIN(96, "PG0"),
+	PINCTRL_PIN(97, "PG1"),
+	PINCTRL_PIN(98, "PG2"),
+	PINCTRL_PIN(99, "PG3"),
+	PINCTRL_PIN(100, "PG4"),
+	PINCTRL_PIN(101, "PG5"),
+	PINCTRL_PIN(102, "PG6"),
+	PINCTRL_PIN(103, "PG7"),
+	PINCTRL_PIN(104, "PG8"),
+	PINCTRL_PIN(105, "PG9"),
+	PINCTRL_PIN(106, "PG10"),
+	PINCTRL_PIN(107, "PG11"),
+	PINCTRL_PIN(108, "PG12"),
+	PINCTRL_PIN(109, "PG13"),
+	PINCTRL_PIN(110, "PG14"),
+	PINCTRL_PIN(111, "PG15"),
+	PINCTRL_PIN(112, "PH0"),
+	PINCTRL_PIN(113, "PH1"),
+	PINCTRL_PIN(114, "PH2"),
+	PINCTRL_PIN(115, "PH3"),
+	PINCTRL_PIN(116, "PH4"),
+	PINCTRL_PIN(117, "PH5"),
+	PINCTRL_PIN(118, "PH6"),
+	PINCTRL_PIN(119, "PH7"),
+	PINCTRL_PIN(120, "PH8"),
+	PINCTRL_PIN(121, "PH9"),
+	PINCTRL_PIN(122, "PH10"),
+	PINCTRL_PIN(123, "PH11"),
+	PINCTRL_PIN(124, "PH12"),
+	PINCTRL_PIN(125, "PH13"),
+	PINCTRL_PIN(128, "PI0"),
+	PINCTRL_PIN(129, "PI1"),
+	PINCTRL_PIN(130, "PI2"),
+	PINCTRL_PIN(131, "PI3"),
+	PINCTRL_PIN(132, "PI4"),
+	PINCTRL_PIN(133, "PI5"),
+	PINCTRL_PIN(134, "PI6"),
+	PINCTRL_PIN(135, "PI7"),
+	PINCTRL_PIN(136, "PI8"),
+	PINCTRL_PIN(137, "PI9"),
+	PINCTRL_PIN(138, "PI10"),
+	PINCTRL_PIN(139, "PI11"),
+	PINCTRL_PIN(140, "PI12"),
+	PINCTRL_PIN(141, "PI13"),
+	PINCTRL_PIN(142, "PI14"),
+	PINCTRL_PIN(143, "PI15"),
+	PINCTRL_PIN(144, "PJ0"),
+	PINCTRL_PIN(145, "PJ1"),
+	PINCTRL_PIN(146, "PJ2"),
+	PINCTRL_PIN(147, "PJ3"),
+	PINCTRL_PIN(148, "PJ4"),
+	PINCTRL_PIN(149, "PJ5"),
+	PINCTRL_PIN(150, "PJ6"),
+	PINCTRL_PIN(151, "PJ7"),
+	PINCTRL_PIN(152, "PJ8"),
+	PINCTRL_PIN(153, "PJ9"),
+	PINCTRL_PIN(154, "PJ10"),
+	PINCTRL_PIN(155, "PJ11"),
+	PINCTRL_PIN(156, "PJ12"),
+	PINCTRL_PIN(157, "PJ13"),
+};
+
+static const unsigned uart0_pins[] = {
+	GPIO_PE7, GPIO_PE8,
+};
+
+static const unsigned uart1_pins[] = {
+	GPIO_PH0, GPIO_PH1,
+};
+
+static const unsigned uart1_ctsrts_pins[] = {
+	GPIO_PE9, GPIO_PE10,
+};
+
+static const unsigned uart2_pins[] = {
+	GPIO_PB4, GPIO_PB5,
+};
+
+static const unsigned uart3_pins[] = {
+	GPIO_PB6, GPIO_PB7,
+};
+
+static const unsigned uart3_ctsrts_pins[] = {
+	GPIO_PB2, GPIO_PB3,
+};
+
+static const unsigned rsi0_pins[] = {
+	GPIO_PC8, GPIO_PC9, GPIO_PC10, GPIO_PC11, GPIO_PC12, GPIO_PC13,
+};
+
+static const unsigned spi0_pins[] = {
+	GPIO_PE0, GPIO_PE1, GPIO_PE2,
+};
+
+static const unsigned spi1_pins[] = {
+	GPIO_PG8, GPIO_PG9, GPIO_PG10,
+};
+
+static const unsigned twi0_pins[] = {
+	GPIO_PE14, GPIO_PE15,
+};
+
+static const unsigned twi1_pins[] = {
+	GPIO_PB0, GPIO_PB1,
+};
+
+static const unsigned rotary_pins[] = {
+	GPIO_PH4, GPIO_PH3, GPIO_PH5,
+};
+
+static const unsigned can0_pins[] = {
+	GPIO_PG13, GPIO_PG12,
+};
+
+static const unsigned can1_pins[] = {
+	GPIO_PG14, GPIO_PG15,
+};
+
+static const unsigned smc0_pins[] = {
+	GPIO_PH8, GPIO_PH9, GPIO_PH10, GPIO_PH11, GPIO_PH12, GPIO_PH13,
+	GPIO_PI0, GPIO_PI1, GPIO_PI2, GPIO_PI3, GPIO_PI4, GPIO_PI5, GPIO_PI6,
+	GPIO_PI7, GPIO_PI8, GPIO_PI9, GPIO_PI10, GPIO_PI11,
+	GPIO_PI12, GPIO_PI13, GPIO_PI14, GPIO_PI15,
+};
+
+static const unsigned sport0_pins[] = {
+	GPIO_PC0, GPIO_PC2, GPIO_PC3, GPIO_PC4, GPIO_PC6, GPIO_PC7,
+};
+
+static const unsigned sport1_pins[] = {
+	GPIO_PD0, GPIO_PD2, GPIO_PD3, GPIO_PD4, GPIO_PD6, GPIO_PD7,
+};
+
+static const unsigned sport2_pins[] = {
+	GPIO_PA0, GPIO_PA2, GPIO_PA3, GPIO_PA4, GPIO_PA6, GPIO_PA7,
+};
+
+static const unsigned sport3_pins[] = {
+	GPIO_PA8, GPIO_PA10, GPIO_PA11, GPIO_PA12, GPIO_PA14, GPIO_PA15,
+};
+
+static const unsigned ppi0_8b_pins[] = {
+	GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6,
+	GPIO_PF7, GPIO_PF13, GPIO_PG0, GPIO_PG1, GPIO_PG2,
+};
+
+static const unsigned ppi0_16b_pins[] = {
+	GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6,
+	GPIO_PF7, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12,
+	GPIO_PF13, GPIO_PF14, GPIO_PF15,
+	GPIO_PG0, GPIO_PG1, GPIO_PG2,
+};
+
+static const unsigned ppi0_24b_pins[] = {
+	GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6,
+	GPIO_PF7, GPIO_PF8, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12,
+	GPIO_PF13, GPIO_PF14, GPIO_PF15, GPIO_PD0, GPIO_PD1, GPIO_PD2,
+	GPIO_PD3, GPIO_PD4, GPIO_PD5, GPIO_PG3, GPIO_PG4,
+	GPIO_PG0, GPIO_PG1, GPIO_PG2,
+};
+
+static const unsigned ppi1_8b_pins[] = {
+	GPIO_PD0, GPIO_PD1, GPIO_PD2, GPIO_PD3, GPIO_PD4, GPIO_PD5, GPIO_PD6,
+	GPIO_PD7, GPIO_PE11, GPIO_PE12, GPIO_PE13,
+};
+
+static const unsigned ppi1_16b_pins[] = {
+	GPIO_PD0, GPIO_PD1, GPIO_PD2, GPIO_PD3, GPIO_PD4, GPIO_PD5, GPIO_PD6,
+	GPIO_PD7, GPIO_PD8, GPIO_PD9, GPIO_PD10, GPIO_PD11, GPIO_PD12,
+	GPIO_PD13, GPIO_PD14, GPIO_PD15,
+	GPIO_PE11, GPIO_PE12, GPIO_PE13,
+};
+
+static const unsigned ppi2_8b_pins[] = {
+	GPIO_PD8, GPIO_PD9, GPIO_PD10, GPIO_PD11, GPIO_PD12,
+	GPIO_PD13, GPIO_PD14, GPIO_PD15,
+	GPIO_PA7, GPIO_PB0, GPIO_PB1, GPIO_PB2, GPIO_PB3,
+};
+
+static const unsigned atapi_pins[] = {
+	GPIO_PH2, GPIO_PJ3, GPIO_PJ4, GPIO_PJ5, GPIO_PJ6,
+	GPIO_PJ7, GPIO_PJ8, GPIO_PJ9, GPIO_PJ10,
+};
+
+static const unsigned atapi_alter_pins[] = {
+	GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6,
+	GPIO_PF7, GPIO_PF8, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12,
+	GPIO_PF13, GPIO_PF14, GPIO_PF15, GPIO_PG2, GPIO_PG3, GPIO_PG4,
+};
+
+static const unsigned nfc0_pins[] = {
+	GPIO_PJ1, GPIO_PJ2,
+};
+
+static const unsigned keys_4x4_pins[] = {
+	GPIO_PD8, GPIO_PD9, GPIO_PD10, GPIO_PD11,
+	GPIO_PD12, GPIO_PD13, GPIO_PD14, GPIO_PD15,
+};
+
+static const unsigned keys_8x8_pins[] = {
+	GPIO_PD8, GPIO_PD9, GPIO_PD10, GPIO_PD11,
+	GPIO_PD12, GPIO_PD13, GPIO_PD14, GPIO_PD15,
+	GPIO_PE0, GPIO_PE1, GPIO_PE2, GPIO_PE3,
+	GPIO_PE4, GPIO_PE5, GPIO_PE6, GPIO_PE7,
+};
+
+static const struct adi_pin_group adi_pin_groups[] = {
+	ADI_PIN_GROUP("uart0grp", uart0_pins),
+	ADI_PIN_GROUP("uart1grp", uart1_pins),
+	ADI_PIN_GROUP("uart1ctsrtsgrp", uart1_ctsrts_pins),
+	ADI_PIN_GROUP("uart2grp", uart2_pins),
+	ADI_PIN_GROUP("uart3grp", uart3_pins),
+	ADI_PIN_GROUP("uart3ctsrtsgrp", uart3_ctsrts_pins),
+	ADI_PIN_GROUP("rsi0grp", rsi0_pins),
+	ADI_PIN_GROUP("spi0grp", spi0_pins),
+	ADI_PIN_GROUP("spi1grp", spi1_pins),
+	ADI_PIN_GROUP("twi0grp", twi0_pins),
+	ADI_PIN_GROUP("twi1grp", twi1_pins),
+	ADI_PIN_GROUP("rotarygrp", rotary_pins),
+	ADI_PIN_GROUP("can0grp", can0_pins),
+	ADI_PIN_GROUP("can1grp", can1_pins),
+	ADI_PIN_GROUP("smc0grp", smc0_pins),
+	ADI_PIN_GROUP("sport0grp", sport0_pins),
+	ADI_PIN_GROUP("sport1grp", sport1_pins),
+	ADI_PIN_GROUP("sport2grp", sport2_pins),
+	ADI_PIN_GROUP("sport3grp", sport3_pins),
+	ADI_PIN_GROUP("ppi0_8bgrp", ppi0_8b_pins),
+	ADI_PIN_GROUP("ppi0_16bgrp", ppi0_16b_pins),
+	ADI_PIN_GROUP("ppi0_24bgrp", ppi0_24b_pins),
+	ADI_PIN_GROUP("ppi1_8bgrp", ppi1_8b_pins),
+	ADI_PIN_GROUP("ppi1_16bgrp", ppi1_16b_pins),
+	ADI_PIN_GROUP("ppi2_8bgrp", ppi2_8b_pins),
+	ADI_PIN_GROUP("atapigrp", atapi_pins),
+	ADI_PIN_GROUP("atapialtergrp", atapi_alter_pins),
+	ADI_PIN_GROUP("nfc0grp", nfc0_pins),
+	ADI_PIN_GROUP("keys_4x4grp", keys_4x4_pins),
+	ADI_PIN_GROUP("keys_8x8grp", keys_8x8_pins),
+};
+
+static const unsigned short uart0_mux[] = {
+	P_UART0_TX, P_UART0_RX,
+	0
+};
+
+static const unsigned short uart1_mux[] = {
+	P_UART1_TX, P_UART1_RX,
+	0
+};
+
+static const unsigned short uart1_ctsrts_mux[] = {
+	P_UART1_RTS, P_UART1_CTS,
+	0
+};
+
+static const unsigned short uart2_mux[] = {
+	P_UART2_TX, P_UART2_RX,
+	0
+};
+
+static const unsigned short uart3_mux[] = {
+	P_UART3_TX, P_UART3_RX,
+	0
+};
+
+static const unsigned short uart3_ctsrts_mux[] = {
+	P_UART3_RTS, P_UART3_CTS,
+	0
+};
+
+static const unsigned short rsi0_mux[] = {
+	P_SD_D0, P_SD_D1, P_SD_D2, P_SD_D3, P_SD_CLK, P_SD_CMD,
+	0
+};
+
+static const unsigned short spi0_mux[] = {
+	P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0
+};
+
+static const unsigned short spi1_mux[] = {
+	P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0
+};
+
+static const unsigned short twi0_mux[] = {
+	P_TWI0_SCL, P_TWI0_SDA, 0
+};
+
+static const unsigned short twi1_mux[] = {
+	P_TWI1_SCL, P_TWI1_SDA, 0
+};
+
+static const unsigned short rotary_mux[] = {
+	P_CNT_CUD, P_CNT_CDG, P_CNT_CZM, 0
+};
+
+static const unsigned short sport0_mux[] = {
+	P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
+	P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0
+};
+
+static const unsigned short sport1_mux[] = {
+	P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS,
+	P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0
+};
+
+static const unsigned short sport2_mux[] = {
+	P_SPORT2_TFS, P_SPORT2_DTPRI, P_SPORT2_TSCLK, P_SPORT2_RFS,
+	P_SPORT2_DRPRI, P_SPORT2_RSCLK, 0
+};
+
+static const unsigned short sport3_mux[] = {
+	P_SPORT3_TFS, P_SPORT3_DTPRI, P_SPORT3_TSCLK, P_SPORT3_RFS,
+	P_SPORT3_DRPRI, P_SPORT3_RSCLK, 0
+};
+
+static const unsigned short can0_mux[] = {
+	P_CAN0_RX, P_CAN0_TX, 0
+};
+
+static const unsigned short can1_mux[] = {
+	P_CAN1_RX, P_CAN1_TX, 0
+};
+
+static const unsigned short smc0_mux[] = {
+	P_A4, P_A5, P_A6, P_A7, P_A8, P_A9, P_A10, P_A11, P_A12,
+	P_A13, P_A14, P_A15, P_A16, P_A17, P_A18, P_A19, P_A20, P_A21,
+	P_A22, P_A23, P_A24, P_A25, P_NOR_CLK, 0,
+};
+
+static const unsigned short ppi0_8b_mux[] = {
+	P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+	P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+	P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+	0,
+};
+
+static const unsigned short ppi0_16b_mux[] = {
+	P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+	P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+	P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
+	P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15,
+	P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+	0,
+};
+
+static const unsigned short ppi0_24b_mux[] = {
+	P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+	P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+	P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
+	P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15,
+	P_PPI0_D16, P_PPI0_D17, P_PPI0_D18, P_PPI0_D19,
+	P_PPI0_D20, P_PPI0_D21, P_PPI0_D22, P_PPI0_D23,
+	P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+	0,
+};
+
+static const unsigned short ppi1_8b_mux[] = {
+	P_PPI1_D0, P_PPI1_D1, P_PPI1_D2, P_PPI1_D3,
+	P_PPI1_D4, P_PPI1_D5, P_PPI1_D6, P_PPI1_D7,
+	P_PPI1_CLK, P_PPI1_FS1, P_PPI1_FS2,
+	0,
+};
+
+static const unsigned short ppi1_16b_mux[] = {
+	P_PPI1_D0, P_PPI1_D1, P_PPI1_D2, P_PPI1_D3,
+	P_PPI1_D4, P_PPI1_D5, P_PPI1_D6, P_PPI1_D7,
+	P_PPI1_D8, P_PPI1_D9, P_PPI1_D10, P_PPI1_D11,
+	P_PPI1_D12, P_PPI1_D13, P_PPI1_D14, P_PPI1_D15,
+	P_PPI1_CLK, P_PPI1_FS1, P_PPI1_FS2,
+	0,
+};
+
+static const unsigned short ppi2_8b_mux[] = {
+	P_PPI2_D0, P_PPI2_D1, P_PPI2_D2, P_PPI2_D3,
+	P_PPI2_D4, P_PPI2_D5, P_PPI2_D6, P_PPI2_D7,
+	P_PPI2_CLK, P_PPI2_FS1, P_PPI2_FS2,
+	0,
+};
+
+static const unsigned short atapi_mux[] = {
+	P_ATAPI_RESET, P_ATAPI_DIOR, P_ATAPI_DIOW, P_ATAPI_CS0, P_ATAPI_CS1,
+	P_ATAPI_DMACK, P_ATAPI_DMARQ, P_ATAPI_INTRQ, P_ATAPI_IORDY,
+};
+
+static const unsigned short atapi_alter_mux[] = {
+	P_ATAPI_D0A, P_ATAPI_D1A, P_ATAPI_D2A, P_ATAPI_D3A, P_ATAPI_D4A,
+	P_ATAPI_D5A, P_ATAPI_D6A, P_ATAPI_D7A, P_ATAPI_D8A, P_ATAPI_D9A,
+	P_ATAPI_D10A, P_ATAPI_D11A, P_ATAPI_D12A, P_ATAPI_D13A, P_ATAPI_D14A,
+	P_ATAPI_D15A, P_ATAPI_A0A, P_ATAPI_A1A, P_ATAPI_A2A,
+	0
+};
+
+static const unsigned short nfc0_mux[] = {
+	P_NAND_CE, P_NAND_RB,
+	0
+};
+
+static const unsigned short keys_4x4_mux[] = {
+	P_KEY_ROW3, P_KEY_ROW2, P_KEY_ROW1, P_KEY_ROW0,
+	P_KEY_COL3, P_KEY_COL2, P_KEY_COL1, P_KEY_COL0,
+	0
+};
+
+static const unsigned short keys_8x8_mux[] = {
+	P_KEY_ROW7, P_KEY_ROW6, P_KEY_ROW5, P_KEY_ROW4,
+	P_KEY_ROW3, P_KEY_ROW2, P_KEY_ROW1, P_KEY_ROW0,
+	P_KEY_COL7, P_KEY_COL6, P_KEY_COL5, P_KEY_COL4,
+	P_KEY_COL3, P_KEY_COL2, P_KEY_COL1, P_KEY_COL0,
+	0
+};
+
+static const char * const uart0grp[] = { "uart0grp" };
+static const char * const uart1grp[] = { "uart1grp" };
+static const char * const uart1ctsrtsgrp[] = { "uart1ctsrtsgrp" };
+static const char * const uart2grp[] = { "uart2grp" };
+static const char * const uart3grp[] = { "uart3grp" };
+static const char * const uart3ctsrtsgrp[] = { "uart3ctsrtsgrp" };
+static const char * const rsi0grp[] = { "rsi0grp" };
+static const char * const spi0grp[] = { "spi0grp" };
+static const char * const spi1grp[] = { "spi1grp" };
+static const char * const twi0grp[] = { "twi0grp" };
+static const char * const twi1grp[] = { "twi1grp" };
+static const char * const rotarygrp[] = { "rotarygrp" };
+static const char * const can0grp[] = { "can0grp" };
+static const char * const can1grp[] = { "can1grp" };
+static const char * const smc0grp[] = { "smc0grp" };
+static const char * const sport0grp[] = { "sport0grp" };
+static const char * const sport1grp[] = { "sport1grp" };
+static const char * const sport2grp[] = { "sport2grp" };
+static const char * const sport3grp[] = { "sport3grp" };
+static const char * const ppi0_8bgrp[] = { "ppi0_8bgrp" };
+static const char * const ppi0_16bgrp[] = { "ppi0_16bgrp" };
+static const char * const ppi0_24bgrp[] = { "ppi0_24bgrp" };
+static const char * const ppi1_8bgrp[] = { "ppi1_8bgrp" };
+static const char * const ppi1_16bgrp[] = { "ppi1_16bgrp" };
+static const char * const ppi2_8bgrp[] = { "ppi2_8bgrp" };
+static const char * const atapigrp[] = { "atapigrp" };
+static const char * const atapialtergrp[] = { "atapialtergrp" };
+static const char * const nfc0grp[] = { "nfc0grp" };
+static const char * const keys_4x4grp[] = { "keys_4x4grp" };
+static const char * const keys_8x8grp[] = { "keys_8x8grp" };
+
+static const struct adi_pmx_func adi_pmx_functions[] = {
+	ADI_PMX_FUNCTION("uart0", uart0grp, uart0_mux),
+	ADI_PMX_FUNCTION("uart1", uart1grp, uart1_mux),
+	ADI_PMX_FUNCTION("uart1_ctsrts", uart1ctsrtsgrp, uart1_ctsrts_mux),
+	ADI_PMX_FUNCTION("uart2", uart2grp, uart2_mux),
+	ADI_PMX_FUNCTION("uart3", uart3grp, uart3_mux),
+	ADI_PMX_FUNCTION("uart3_ctsrts", uart3ctsrtsgrp, uart3_ctsrts_mux),
+	ADI_PMX_FUNCTION("rsi0", rsi0grp, rsi0_mux),
+	ADI_PMX_FUNCTION("spi0", spi0grp, spi0_mux),
+	ADI_PMX_FUNCTION("spi1", spi1grp, spi1_mux),
+	ADI_PMX_FUNCTION("twi0", twi0grp, twi0_mux),
+	ADI_PMX_FUNCTION("twi1", twi1grp, twi1_mux),
+	ADI_PMX_FUNCTION("rotary", rotarygrp, rotary_mux),
+	ADI_PMX_FUNCTION("can0", can0grp, can0_mux),
+	ADI_PMX_FUNCTION("can1", can1grp, can1_mux),
+	ADI_PMX_FUNCTION("smc0", smc0grp, smc0_mux),
+	ADI_PMX_FUNCTION("sport0", sport0grp, sport0_mux),
+	ADI_PMX_FUNCTION("sport1", sport1grp, sport1_mux),
+	ADI_PMX_FUNCTION("sport2", sport2grp, sport2_mux),
+	ADI_PMX_FUNCTION("sport3", sport3grp, sport3_mux),
+	ADI_PMX_FUNCTION("ppi0_8b", ppi0_8bgrp, ppi0_8b_mux),
+	ADI_PMX_FUNCTION("ppi0_16b", ppi0_16bgrp, ppi0_16b_mux),
+	ADI_PMX_FUNCTION("ppi0_24b", ppi0_24bgrp, ppi0_24b_mux),
+	ADI_PMX_FUNCTION("ppi1_8b", ppi1_8bgrp, ppi1_8b_mux),
+	ADI_PMX_FUNCTION("ppi1_16b", ppi1_16bgrp, ppi1_16b_mux),
+	ADI_PMX_FUNCTION("ppi2_8b", ppi2_8bgrp, ppi2_8b_mux),
+	ADI_PMX_FUNCTION("atapi", atapigrp, atapi_mux),
+	ADI_PMX_FUNCTION("atapi_alter", atapialtergrp, atapi_alter_mux),
+	ADI_PMX_FUNCTION("nfc0", nfc0grp, nfc0_mux),
+	ADI_PMX_FUNCTION("keys_4x4", keys_4x4grp, keys_4x4_mux),
+	ADI_PMX_FUNCTION("keys_8x8", keys_8x8grp, keys_8x8_mux),
+};
+
+static const struct adi_pinctrl_soc_data adi_bf54x_soc = {
+	.functions = adi_pmx_functions,
+	.nfunctions = ARRAY_SIZE(adi_pmx_functions),
+	.groups = adi_pin_groups,
+	.ngroups = ARRAY_SIZE(adi_pin_groups),
+	.pins = adi_pads,
+	.npins = ARRAY_SIZE(adi_pads),
+};
+
+void adi_pinctrl_soc_init(const struct adi_pinctrl_soc_data **soc)
+{
+	*soc = &adi_bf54x_soc;
+}
diff --git a/drivers/pinctrl/pinctrl-adi2-bf60x.c b/drivers/pinctrl/pinctrl-adi2-bf60x.c
new file mode 100644
index 0000000..bf57aea
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-adi2-bf60x.c
@@ -0,0 +1,521 @@
+/*
+ * Pinctrl Driver for ADI GPIO2 controller
+ *
+ * Copyright 2007-2013 Analog Devices Inc.
+ *
+ * Licensed under the GPLv2 or later
+ */
+
+#include <asm/portmux.h>
+#include "pinctrl-adi2.h"
+
+static const struct pinctrl_pin_desc adi_pads[] = {
+	PINCTRL_PIN(0, "PA0"),
+	PINCTRL_PIN(1, "PA1"),
+	PINCTRL_PIN(2, "PA2"),
+	PINCTRL_PIN(3, "PG3"),
+	PINCTRL_PIN(4, "PA4"),
+	PINCTRL_PIN(5, "PA5"),
+	PINCTRL_PIN(6, "PA6"),
+	PINCTRL_PIN(7, "PA7"),
+	PINCTRL_PIN(8, "PA8"),
+	PINCTRL_PIN(9, "PA9"),
+	PINCTRL_PIN(10, "PA10"),
+	PINCTRL_PIN(11, "PA11"),
+	PINCTRL_PIN(12, "PA12"),
+	PINCTRL_PIN(13, "PA13"),
+	PINCTRL_PIN(14, "PA14"),
+	PINCTRL_PIN(15, "PA15"),
+	PINCTRL_PIN(16, "PB0"),
+	PINCTRL_PIN(17, "PB1"),
+	PINCTRL_PIN(18, "PB2"),
+	PINCTRL_PIN(19, "PB3"),
+	PINCTRL_PIN(20, "PB4"),
+	PINCTRL_PIN(21, "PB5"),
+	PINCTRL_PIN(22, "PB6"),
+	PINCTRL_PIN(23, "PB7"),
+	PINCTRL_PIN(24, "PB8"),
+	PINCTRL_PIN(25, "PB9"),
+	PINCTRL_PIN(26, "PB10"),
+	PINCTRL_PIN(27, "PB11"),
+	PINCTRL_PIN(28, "PB12"),
+	PINCTRL_PIN(29, "PB13"),
+	PINCTRL_PIN(30, "PB14"),
+	PINCTRL_PIN(31, "PB15"),
+	PINCTRL_PIN(32, "PC0"),
+	PINCTRL_PIN(33, "PC1"),
+	PINCTRL_PIN(34, "PC2"),
+	PINCTRL_PIN(35, "PC3"),
+	PINCTRL_PIN(36, "PC4"),
+	PINCTRL_PIN(37, "PC5"),
+	PINCTRL_PIN(38, "PC6"),
+	PINCTRL_PIN(39, "PC7"),
+	PINCTRL_PIN(40, "PC8"),
+	PINCTRL_PIN(41, "PC9"),
+	PINCTRL_PIN(42, "PC10"),
+	PINCTRL_PIN(43, "PC11"),
+	PINCTRL_PIN(44, "PC12"),
+	PINCTRL_PIN(45, "PC13"),
+	PINCTRL_PIN(46, "PC14"),
+	PINCTRL_PIN(47, "PC15"),
+	PINCTRL_PIN(48, "PD0"),
+	PINCTRL_PIN(49, "PD1"),
+	PINCTRL_PIN(50, "PD2"),
+	PINCTRL_PIN(51, "PD3"),
+	PINCTRL_PIN(52, "PD4"),
+	PINCTRL_PIN(53, "PD5"),
+	PINCTRL_PIN(54, "PD6"),
+	PINCTRL_PIN(55, "PD7"),
+	PINCTRL_PIN(56, "PD8"),
+	PINCTRL_PIN(57, "PD9"),
+	PINCTRL_PIN(58, "PD10"),
+	PINCTRL_PIN(59, "PD11"),
+	PINCTRL_PIN(60, "PD12"),
+	PINCTRL_PIN(61, "PD13"),
+	PINCTRL_PIN(62, "PD14"),
+	PINCTRL_PIN(63, "PD15"),
+	PINCTRL_PIN(64, "PE0"),
+	PINCTRL_PIN(65, "PE1"),
+	PINCTRL_PIN(66, "PE2"),
+	PINCTRL_PIN(67, "PE3"),
+	PINCTRL_PIN(68, "PE4"),
+	PINCTRL_PIN(69, "PE5"),
+	PINCTRL_PIN(70, "PE6"),
+	PINCTRL_PIN(71, "PE7"),
+	PINCTRL_PIN(72, "PE8"),
+	PINCTRL_PIN(73, "PE9"),
+	PINCTRL_PIN(74, "PE10"),
+	PINCTRL_PIN(75, "PE11"),
+	PINCTRL_PIN(76, "PE12"),
+	PINCTRL_PIN(77, "PE13"),
+	PINCTRL_PIN(78, "PE14"),
+	PINCTRL_PIN(79, "PE15"),
+	PINCTRL_PIN(80, "PF0"),
+	PINCTRL_PIN(81, "PF1"),
+	PINCTRL_PIN(82, "PF2"),
+	PINCTRL_PIN(83, "PF3"),
+	PINCTRL_PIN(84, "PF4"),
+	PINCTRL_PIN(85, "PF5"),
+	PINCTRL_PIN(86, "PF6"),
+	PINCTRL_PIN(87, "PF7"),
+	PINCTRL_PIN(88, "PF8"),
+	PINCTRL_PIN(89, "PF9"),
+	PINCTRL_PIN(90, "PF10"),
+	PINCTRL_PIN(91, "PF11"),
+	PINCTRL_PIN(92, "PF12"),
+	PINCTRL_PIN(93, "PF13"),
+	PINCTRL_PIN(94, "PF14"),
+	PINCTRL_PIN(95, "PF15"),
+	PINCTRL_PIN(96, "PG0"),
+	PINCTRL_PIN(97, "PG1"),
+	PINCTRL_PIN(98, "PG2"),
+	PINCTRL_PIN(99, "PG3"),
+	PINCTRL_PIN(100, "PG4"),
+	PINCTRL_PIN(101, "PG5"),
+	PINCTRL_PIN(102, "PG6"),
+	PINCTRL_PIN(103, "PG7"),
+	PINCTRL_PIN(104, "PG8"),
+	PINCTRL_PIN(105, "PG9"),
+	PINCTRL_PIN(106, "PG10"),
+	PINCTRL_PIN(107, "PG11"),
+	PINCTRL_PIN(108, "PG12"),
+	PINCTRL_PIN(109, "PG13"),
+	PINCTRL_PIN(110, "PG14"),
+	PINCTRL_PIN(111, "PG15"),
+};
+
+static const unsigned uart0_pins[] = {
+	GPIO_PD7, GPIO_PD8,
+};
+
+static const unsigned uart0_ctsrts_pins[] = {
+	GPIO_PD9, GPIO_PD10,
+};
+
+static const unsigned uart1_pins[] = {
+	GPIO_PG15, GPIO_PG14,
+};
+
+static const unsigned uart1_ctsrts_pins[] = {
+	GPIO_PG10, GPIO_PG13,
+};
+
+static const unsigned rsi0_pins[] = {
+	GPIO_PG3, GPIO_PG2, GPIO_PG0, GPIO_PE15, GPIO_PG5, GPIO_PG6,
+};
+
+static const unsigned eth0_pins[] = {
+	GPIO_PC6, GPIO_PC7, GPIO_PC2, GPIO_PC0, GPIO_PC3, GPIO_PC1,
+	GPIO_PB13, GPIO_PD6, GPIO_PC5, GPIO_PC4, GPIO_PB14, GPIO_PB15,
+};
+
+static const unsigned eth1_pins[] = {
+	GPIO_PE10, GPIO_PE11, GPIO_PG3, GPIO_PG0, GPIO_PG2, GPIO_PE15,
+	GPIO_PG5, GPIO_PE12, GPIO_PE13, GPIO_PE14, GPIO_PG6, GPIO_PC9,
+};
+
+static const unsigned spi0_pins[] = {
+	GPIO_PD4, GPIO_PD2, GPIO_PD3,
+};
+
+static const unsigned spi1_pins[] = {
+	GPIO_PD5, GPIO_PD14, GPIO_PD13,
+};
+
+static const unsigned twi0_pins[] = {
+};
+
+static const unsigned twi1_pins[] = {
+};
+
+static const unsigned rotary_pins[] = {
+	GPIO_PG7, GPIO_PG11, GPIO_PG12,
+};
+
+static const unsigned can0_pins[] = {
+	GPIO_PG1, GPIO_PG4,
+};
+
+static const unsigned smc0_pins[] = {
+	GPIO_PA0, GPIO_PA1, GPIO_PA2, GPIO_PA3, GPIO_PA4, GPIO_PA5, GPIO_PA6,
+	GPIO_PA7, GPIO_PA8, GPIO_PA9, GPIO_PB2, GPIO_PA10, GPIO_PA11,
+	GPIO_PB3, GPIO_PA12, GPIO_PA13, GPIO_PA14, GPIO_PA15, GPIO_PB6,
+	GPIO_PB7, GPIO_PB8, GPIO_PB10, GPIO_PB11, GPIO_PB0,
+};
+
+static const unsigned sport0_pins[] = {
+	GPIO_PB5, GPIO_PB4, GPIO_PB9, GPIO_PB8, GPIO_PB7, GPIO_PB11,
+};
+
+static const unsigned sport1_pins[] = {
+	GPIO_PE2, GPIO_PE5, GPIO_PD15, GPIO_PE4, GPIO_PE3, GPIO_PE1,
+};
+
+static const unsigned sport2_pins[] = {
+	GPIO_PG4, GPIO_PG1, GPIO_PG9, GPIO_PG10, GPIO_PG7, GPIO_PB12,
+};
+
+static const unsigned ppi0_8b_pins[] = {
+	GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6,
+	GPIO_PF7, GPIO_PF13, GPIO_PF14, GPIO_PF15,
+	GPIO_PE6, GPIO_PE7, GPIO_PE8, GPIO_PE9,
+};
+
+static const unsigned ppi0_16b_pins[] = {
+	GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6,
+	GPIO_PF7, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12,
+	GPIO_PF13, GPIO_PF14, GPIO_PF15,
+	GPIO_PE6, GPIO_PE7, GPIO_PE8, GPIO_PE9,
+};
+
+static const unsigned ppi0_24b_pins[] = {
+	GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3, GPIO_PF4, GPIO_PF5, GPIO_PF6,
+	GPIO_PF7, GPIO_PF8, GPIO_PF9, GPIO_PF10, GPIO_PF11, GPIO_PF12,
+	GPIO_PF13, GPIO_PF14, GPIO_PF15, GPIO_PE0, GPIO_PE1, GPIO_PE2,
+	GPIO_PE3, GPIO_PE4, GPIO_PE5, GPIO_PE6, GPIO_PE7, GPIO_PE8,
+	GPIO_PE9, GPIO_PD12, GPIO_PD15,
+};
+
+static const unsigned ppi1_8b_pins[] = {
+	GPIO_PC0, GPIO_PC1, GPIO_PC2, GPIO_PC3, GPIO_PC4, GPIO_PC5, GPIO_PC6,
+	GPIO_PC7, GPIO_PC8, GPIO_PB13, GPIO_PB14, GPIO_PB15, GPIO_PD6,
+};
+
+static const unsigned ppi1_16b_pins[] = {
+	GPIO_PC0, GPIO_PC1, GPIO_PC2, GPIO_PC3, GPIO_PC4, GPIO_PC5, GPIO_PC6,
+	GPIO_PC7, GPIO_PC9, GPIO_PC10, GPIO_PC11, GPIO_PC12,
+	GPIO_PC13, GPIO_PC14, GPIO_PC15,
+	GPIO_PB13, GPIO_PB14, GPIO_PB15, GPIO_PD6,
+};
+
+static const unsigned ppi2_8b_pins[] = {
+	GPIO_PA0, GPIO_PA1, GPIO_PA2, GPIO_PA3, GPIO_PA4, GPIO_PA5, GPIO_PA6,
+	GPIO_PA7, GPIO_PB0, GPIO_PB1, GPIO_PB2, GPIO_PB3,
+};
+
+static const unsigned ppi2_16b_pins[] = {
+	GPIO_PA0, GPIO_PA1, GPIO_PA2, GPIO_PA3, GPIO_PA4, GPIO_PA5, GPIO_PA6,
+	GPIO_PA7, GPIO_PA8, GPIO_PA9, GPIO_PA10, GPIO_PA11, GPIO_PA12,
+	GPIO_PA13, GPIO_PA14, GPIO_PA15, GPIO_PB0, GPIO_PB1, GPIO_PB2,
+};
+
+static const unsigned lp0_pins[] = {
+	GPIO_PB0, GPIO_PB1, GPIO_PA0, GPIO_PA1, GPIO_PA2, GPIO_PA3,
+	GPIO_PA4, GPIO_PA5, GPIO_PA6, GPIO_PA7,
+};
+
+static const unsigned lp1_pins[] = {
+	GPIO_PB3, GPIO_PB2, GPIO_PA8, GPIO_PA9, GPIO_PA10, GPIO_PA11,
+	GPIO_PA12, GPIO_PA13, GPIO_PA14, GPIO_PA15,
+};
+
+static const unsigned lp2_pins[] = {
+	GPIO_PE6, GPIO_PE7, GPIO_PF0, GPIO_PF1, GPIO_PF2, GPIO_PF3,
+	GPIO_PF4, GPIO_PF5, GPIO_PF6, GPIO_PF7,
+};
+
+static const unsigned lp3_pins[] = {
+	GPIO_PE9, GPIO_PE8, GPIO_PF8, GPIO_PF9, GPIO_PF10, GPIO_PF11,
+	GPIO_PF12, GPIO_PF13, GPIO_PF14, GPIO_PF15,
+};
+
+static const struct adi_pin_group adi_pin_groups[] = {
+	ADI_PIN_GROUP("uart0grp", uart0_pins),
+	ADI_PIN_GROUP("uart0ctsrtsgrp", uart0_ctsrts_pins),
+	ADI_PIN_GROUP("uart1grp", uart1_pins),
+	ADI_PIN_GROUP("uart1ctsrtsgrp", uart1_ctsrts_pins),
+	ADI_PIN_GROUP("rsi0grp", rsi0_pins),
+	ADI_PIN_GROUP("eth0grp", eth0_pins),
+	ADI_PIN_GROUP("eth1grp", eth1_pins),
+	ADI_PIN_GROUP("spi0grp", spi0_pins),
+	ADI_PIN_GROUP("spi1grp", spi1_pins),
+	ADI_PIN_GROUP("twi0grp", twi0_pins),
+	ADI_PIN_GROUP("twi1grp", twi1_pins),
+	ADI_PIN_GROUP("rotarygrp", rotary_pins),
+	ADI_PIN_GROUP("can0grp", can0_pins),
+	ADI_PIN_GROUP("smc0grp", smc0_pins),
+	ADI_PIN_GROUP("sport0grp", sport0_pins),
+	ADI_PIN_GROUP("sport1grp", sport1_pins),
+	ADI_PIN_GROUP("sport2grp", sport2_pins),
+	ADI_PIN_GROUP("ppi0_8bgrp", ppi0_8b_pins),
+	ADI_PIN_GROUP("ppi0_16bgrp", ppi0_16b_pins),
+	ADI_PIN_GROUP("ppi0_24bgrp", ppi0_24b_pins),
+	ADI_PIN_GROUP("ppi1_8bgrp", ppi1_8b_pins),
+	ADI_PIN_GROUP("ppi1_16bgrp", ppi1_16b_pins),
+	ADI_PIN_GROUP("ppi2_8bgrp", ppi2_8b_pins),
+	ADI_PIN_GROUP("ppi2_16bgrp", ppi2_16b_pins),
+	ADI_PIN_GROUP("lp0grp", lp0_pins),
+	ADI_PIN_GROUP("lp1grp", lp1_pins),
+	ADI_PIN_GROUP("lp2grp", lp2_pins),
+	ADI_PIN_GROUP("lp3grp", lp3_pins),
+};
+
+static const unsigned short uart0_mux[] = {
+	P_UART0_TX, P_UART0_RX,
+	0
+};
+
+static const unsigned short uart0_ctsrts_mux[] = {
+	P_UART0_RTS, P_UART0_CTS,
+	0
+};
+
+static const unsigned short uart1_mux[] = {
+	P_UART1_TX, P_UART1_RX,
+	0
+};
+
+static const unsigned short uart1_ctsrts_mux[] = {
+	P_UART1_RTS, P_UART1_CTS,
+	0
+};
+
+static const unsigned short rsi0_mux[] = {
+	P_RSI_DATA0, P_RSI_DATA1, P_RSI_DATA2, P_RSI_DATA3,
+	P_RSI_CMD, P_RSI_CLK, 0
+};
+
+static const unsigned short eth0_mux[] = P_RMII0;
+static const unsigned short eth1_mux[] = P_RMII1;
+
+static const unsigned short spi0_mux[] = {
+	P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0
+};
+
+static const unsigned short spi1_mux[] = {
+	P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0
+};
+
+static const unsigned short twi0_mux[] = {
+	P_TWI0_SCL, P_TWI0_SDA, 0
+};
+
+static const unsigned short twi1_mux[] = {
+	P_TWI1_SCL, P_TWI1_SDA, 0
+};
+
+static const unsigned short rotary_mux[] = {
+	P_CNT_CUD, P_CNT_CDG, P_CNT_CZM, 0
+};
+
+static const unsigned short sport0_mux[] = {
+	P_SPORT0_ACLK, P_SPORT0_AFS, P_SPORT0_AD0, P_SPORT0_BCLK,
+	P_SPORT0_BFS, P_SPORT0_BD0, 0,
+};
+
+static const unsigned short sport1_mux[] = {
+	P_SPORT1_ACLK, P_SPORT1_AFS, P_SPORT1_AD0, P_SPORT1_BCLK,
+	P_SPORT1_BFS, P_SPORT1_BD0, 0,
+};
+
+static const unsigned short sport2_mux[] = {
+	P_SPORT2_ACLK, P_SPORT2_AFS, P_SPORT2_AD0, P_SPORT2_BCLK,
+	P_SPORT2_BFS, P_SPORT2_BD0, 0,
+};
+
+static const unsigned short can0_mux[] = {
+	P_CAN0_RX, P_CAN0_TX, 0
+};
+
+static const unsigned short smc0_mux[] = {
+	P_A3, P_A4, P_A5, P_A6, P_A7, P_A8, P_A9, P_A10, P_A11, P_A12,
+	P_A13, P_A14, P_A15, P_A16, P_A17, P_A18, P_A19, P_A20, P_A21,
+	P_A22, P_A23, P_A24, P_A25, P_NORCK, 0,
+};
+
+static const unsigned short ppi0_8b_mux[] = {
+	P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+	P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+	P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+	0,
+};
+
+static const unsigned short ppi0_16b_mux[] = {
+	P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+	P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+	P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
+	P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15,
+	P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+	0,
+};
+
+static const unsigned short ppi0_24b_mux[] = {
+	P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+	P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+	P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
+	P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15,
+	P_PPI0_D16, P_PPI0_D17, P_PPI0_D18, P_PPI0_D19,
+	P_PPI0_D20, P_PPI0_D21, P_PPI0_D22, P_PPI0_D23,
+	P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+	0,
+};
+
+static const unsigned short ppi1_8b_mux[] = {
+	P_PPI1_D0, P_PPI1_D1, P_PPI1_D2, P_PPI1_D3,
+	P_PPI1_D4, P_PPI1_D5, P_PPI1_D6, P_PPI1_D7,
+	P_PPI1_CLK, P_PPI1_FS1, P_PPI1_FS2,
+	0,
+};
+
+static const unsigned short ppi1_16b_mux[] = {
+	P_PPI1_D0, P_PPI1_D1, P_PPI1_D2, P_PPI1_D3,
+	P_PPI1_D4, P_PPI1_D5, P_PPI1_D6, P_PPI1_D7,
+	P_PPI1_D8, P_PPI1_D9, P_PPI1_D10, P_PPI1_D11,
+	P_PPI1_D12, P_PPI1_D13, P_PPI1_D14, P_PPI1_D15,
+	P_PPI1_CLK, P_PPI1_FS1, P_PPI1_FS2,
+	0,
+};
+
+static const unsigned short ppi2_8b_mux[] = {
+	P_PPI2_D0, P_PPI2_D1, P_PPI2_D2, P_PPI2_D3,
+	P_PPI2_D4, P_PPI2_D5, P_PPI2_D6, P_PPI2_D7,
+	P_PPI2_CLK, P_PPI2_FS1, P_PPI2_FS2,
+	0,
+};
+
+static const unsigned short ppi2_16b_mux[] = {
+	P_PPI2_D0, P_PPI2_D1, P_PPI2_D2, P_PPI2_D3,
+	P_PPI2_D4, P_PPI2_D5, P_PPI2_D6, P_PPI2_D7,
+	P_PPI2_D8, P_PPI2_D9, P_PPI2_D10, P_PPI2_D11,
+	P_PPI2_D12, P_PPI2_D13, P_PPI2_D14, P_PPI2_D15,
+	P_PPI2_CLK, P_PPI2_FS1, P_PPI2_FS2,
+	0,
+};
+
+static const unsigned short lp0_mux[] = {
+	P_LP0_CLK, P_LP0_ACK, P_LP0_D0, P_LP0_D1, P_LP0_D2,
+	P_LP0_D3, P_LP0_D4, P_LP0_D5, P_LP0_D6, P_LP0_D7,
+        0
+};
+
+static const unsigned short lp1_mux[] = {
+	P_LP1_CLK, P_LP1_ACK, P_LP1_D0, P_LP1_D1, P_LP1_D2,
+	P_LP1_D3, P_LP1_D4, P_LP1_D5, P_LP1_D6, P_LP1_D7,
+        0
+};
+
+static const unsigned short lp2_mux[] = {
+	P_LP2_CLK, P_LP2_ACK, P_LP2_D0, P_LP2_D1, P_LP2_D2,
+	P_LP2_D3, P_LP2_D4, P_LP2_D5, P_LP2_D6, P_LP2_D7,
+        0
+};
+
+static const unsigned short lp3_mux[] = {
+	P_LP3_CLK, P_LP3_ACK, P_LP3_D0, P_LP3_D1, P_LP3_D2,
+	P_LP3_D3, P_LP3_D4, P_LP3_D5, P_LP3_D6, P_LP3_D7,
+        0
+};
+
+static const char * const uart0grp[] = { "uart0grp" };
+static const char * const uart0ctsrtsgrp[] = { "uart0ctsrtsgrp" };
+static const char * const uart1grp[] = { "uart1grp" };
+static const char * const uart1ctsrtsgrp[] = { "uart1ctsrtsgrp" };
+static const char * const rsi0grp[] = { "rsi0grp" };
+static const char * const eth0grp[] = { "eth0grp" };
+static const char * const eth1grp[] = { "eth1grp" };
+static const char * const spi0grp[] = { "spi0grp" };
+static const char * const spi1grp[] = { "spi1grp" };
+static const char * const twi0grp[] = { "twi0grp" };
+static const char * const twi1grp[] = { "twi1grp" };
+static const char * const rotarygrp[] = { "rotarygrp" };
+static const char * const can0grp[] = { "can0grp" };
+static const char * const smc0grp[] = { "smc0grp" };
+static const char * const sport0grp[] = { "sport0grp" };
+static const char * const sport1grp[] = { "sport1grp" };
+static const char * const sport2grp[] = { "sport2grp" };
+static const char * const ppi0_8bgrp[] = { "ppi0_8bgrp" };
+static const char * const ppi0_16bgrp[] = { "ppi0_16bgrp" };
+static const char * const ppi0_24bgrp[] = { "ppi0_24bgrp" };
+static const char * const ppi1_8bgrp[] = { "ppi1_8bgrp" };
+static const char * const ppi1_16bgrp[] = { "ppi1_16bgrp" };
+static const char * const ppi2_8bgrp[] = { "ppi2_8bgrp" };
+static const char * const ppi2_16bgrp[] = { "ppi2_16bgrp" };
+static const char * const lp0grp[] = { "lp0grp" };
+static const char * const lp1grp[] = { "lp1grp" };
+static const char * const lp2grp[] = { "lp2grp" };
+static const char * const lp3grp[] = { "lp3grp" };
+
+static const struct adi_pmx_func adi_pmx_functions[] = {
+	ADI_PMX_FUNCTION("uart0", uart0grp, uart0_mux),
+	ADI_PMX_FUNCTION("uart0_ctsrts", uart0ctsrtsgrp, uart0_ctsrts_mux),
+	ADI_PMX_FUNCTION("uart1", uart1grp, uart1_mux),
+	ADI_PMX_FUNCTION("uart1_ctsrts", uart1ctsrtsgrp, uart1_ctsrts_mux),
+	ADI_PMX_FUNCTION("rsi0", rsi0grp, rsi0_mux),
+	ADI_PMX_FUNCTION("eth0", eth0grp, eth0_mux),
+	ADI_PMX_FUNCTION("eth1", eth1grp, eth1_mux),
+	ADI_PMX_FUNCTION("spi0", spi0grp, spi0_mux),
+	ADI_PMX_FUNCTION("spi1", spi1grp, spi1_mux),
+	ADI_PMX_FUNCTION("twi0", twi0grp, twi0_mux),
+	ADI_PMX_FUNCTION("twi1", twi1grp, twi1_mux),
+	ADI_PMX_FUNCTION("rotary", rotarygrp, rotary_mux),
+	ADI_PMX_FUNCTION("can0", can0grp, can0_mux),
+	ADI_PMX_FUNCTION("smc0", smc0grp, smc0_mux),
+	ADI_PMX_FUNCTION("sport0", sport0grp, sport0_mux),
+	ADI_PMX_FUNCTION("sport1", sport1grp, sport1_mux),
+	ADI_PMX_FUNCTION("sport2", sport2grp, sport2_mux),
+	ADI_PMX_FUNCTION("ppi0_8b", ppi0_8bgrp, ppi0_8b_mux),
+	ADI_PMX_FUNCTION("ppi0_16b", ppi0_16bgrp, ppi0_16b_mux),
+	ADI_PMX_FUNCTION("ppi0_24b", ppi0_24bgrp, ppi0_24b_mux),
+	ADI_PMX_FUNCTION("ppi1_8b", ppi1_8bgrp, ppi1_8b_mux),
+	ADI_PMX_FUNCTION("ppi1_16b", ppi1_16bgrp, ppi1_16b_mux),
+	ADI_PMX_FUNCTION("ppi2_8b", ppi2_8bgrp, ppi2_8b_mux),
+	ADI_PMX_FUNCTION("ppi2_16b", ppi2_16bgrp, ppi2_16b_mux),
+	ADI_PMX_FUNCTION("lp0", lp0grp, lp0_mux),
+	ADI_PMX_FUNCTION("lp1", lp1grp, lp1_mux),
+	ADI_PMX_FUNCTION("lp2", lp2grp, lp2_mux),
+	ADI_PMX_FUNCTION("lp3", lp3grp, lp3_mux),
+};
+
+static const struct adi_pinctrl_soc_data adi_bf60x_soc = {
+	.functions = adi_pmx_functions,
+	.nfunctions = ARRAY_SIZE(adi_pmx_functions),
+	.groups = adi_pin_groups,
+	.ngroups = ARRAY_SIZE(adi_pin_groups),
+	.pins = adi_pads,
+	.npins = ARRAY_SIZE(adi_pads),
+};
+
+void adi_pinctrl_soc_init(const struct adi_pinctrl_soc_data **soc)
+{
+	*soc = &adi_bf60x_soc;
+}
diff --git a/drivers/pinctrl/pinctrl-adi2.c b/drivers/pinctrl/pinctrl-adi2.c
new file mode 100644
index 0000000..7a39562
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-adi2.c
@@ -0,0 +1,1164 @@
+/*
+ * Pinctrl Driver for ADI GPIO2 controller
+ *
+ * Copyright 2007-2013 Analog Devices Inc.
+ *
+ * Licensed under the GPLv2 or later
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/irq.h>
+#include <linux/platform_data/pinctrl-adi2.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/syscore_ops.h>
+#include <linux/gpio.h>
+#include <asm/portmux.h>
+#include "pinctrl-adi2.h"
+#include "core.h"
+
+/*
+According to the BF54x HRM, pint means "pin interrupt".
+http://www.analog.com/static/imported-files/processor_manuals/ADSP-BF54x_hwr_rev1.2.pdf
+
+ADSP-BF54x processor Blackfin processors have four SIC interrupt chan-
+nels dedicated to pin interrupt purposes. These channels are managed by
+four hardware blocks, called PINT0, PINT1, PINT2, and PINT3. Every PINTx
+block can sense to up to 32 pins. While PINT0 and PINT1 can sense the
+pins of port A and port B, PINT2 and PINT3 manage all the pins from port
+C to port J as shown in Figure 9-2.
+
+n BF54x HRM:
+The ten GPIO ports are subdivided into 8-bit half ports, resulting in lower and
+upper half 8-bit units. The PINTx_ASSIGN registers control the 8-bit multi-
+plexers shown in Figure 9-3. Lower half units of eight pins can be
+forwarded to either byte 0 or byte 2 of either associated PINTx block.
+Upper half units can be forwarded to either byte 1 or byte 3 of the pin
+interrupt blocks, without further restrictions.
+
+All MMR registers in the pin interrupt module are 32 bits wide. To simply the
+mapping logic, this driver only maps a 16-bit gpio port to the upper or lower
+16 bits of a PINTx block. You can find the Figure 9-3 on page 583.
+
+Each IRQ domain is binding to a GPIO bank device. 2 GPIO bank devices can map
+to one PINT device. Two in "struct gpio_pint" are used to ease the PINT
+interrupt handler.
+
+The GPIO bank mapping to the lower 16 bits of the PINT device set its IRQ
+domain pointer in domain[0]. The IRQ domain pointer of the other bank is set
+to domain[1]. PINT interrupt handler adi_gpio_handle_pint_irq() finds out
+the current domain pointer according to whether the interrupt request mask
+is in lower 16 bits (domain[0]) or upper 16bits (domain[1]).
+
+A PINT device is not part of a GPIO port device in Blackfin. Multiple GPIO
+port devices can be mapped to the same PINT device.
+
+*/
+
+static LIST_HEAD(adi_pint_list);
+static LIST_HEAD(adi_gpio_port_list);
+
+#define DRIVER_NAME "pinctrl-adi2"
+
+#define PINT_HI_OFFSET		16
+
+/**
+ * struct gpio_port_saved - GPIO port registers that should be saved between
+ * power suspend and resume operations.
+ *
+ * @fer: PORTx_FER register
+ * @data: PORTx_DATA register
+ * @dir: PORTx_DIR register
+ * @inen: PORTx_INEN register
+ * @mux: PORTx_MUX register
+ */
+struct gpio_port_saved {
+	u16 fer;
+	u16 data;
+	u16 dir;
+	u16 inen;
+	u32 mux;
+};
+
+/**
+ * struct gpio_pint - Pin interrupt controller device. Multiple ADI GPIO
+ * banks can be mapped into one Pin interrupt controller.
+ *
+ * @node: All gpio_pint instances are added to a global list.
+ * @base: PINT device register base address
+ * @irq: IRQ of the PINT device, it is the parent IRQ of all
+ *       GPIO IRQs mapping to this device.
+ * @domain: [0] irq domain of the gpio port, whose hardware interrupts are
+ *		mapping to the low 16-bit of the pint registers.
+ *          [1] irq domain of the gpio port, whose hardware interrupts are
+ *		mapping to the high 16-bit of the pint registers.
+ * @regs: address pointer to the PINT device
+ * @map_count: No more than 2 GPIO banks can be mapped to this PINT device.
+ * @lock: This lock make sure the irq_chip operations to one PINT device
+ *        for different GPIO interrrupts are atomic.
+ * @pint_map_port: Set up the mapping between one PINT device and
+ *                 multiple GPIO banks.
+ */
+struct gpio_pint {
+	struct list_head node;
+	void __iomem *base;
+	int irq;
+	struct irq_domain *domain[2];
+	struct gpio_pint_regs *regs;
+	struct adi_pm_pint_save saved_data;
+	int map_count;
+	spinlock_t lock;
+
+	int (*pint_map_port)(struct gpio_pint *pint, bool assign,
+				u8 map, struct irq_domain *domain);
+};
+
+/**
+ * ADI pin controller
+ *
+ * @dev: a pointer back to containing device
+ * @pctl: the pinctrl device
+ * @soc: SoC data for this specific chip
+ */
+struct adi_pinctrl {
+	struct device *dev;
+	struct pinctrl_dev *pctl;
+	const struct adi_pinctrl_soc_data *soc;
+};
+
+/**
+ * struct gpio_port - GPIO bank device. Multiple ADI GPIO banks can be mapped
+ * into one pin interrupt controller.
+ *
+ * @node: All gpio_port instances are added to a list.
+ * @base: GPIO bank device register base address
+ * @irq_base: base IRQ of the GPIO bank device
+ * @width: PIN number of the GPIO bank device
+ * @regs: address pointer to the GPIO bank device
+ * @saved_data: registers that should be saved between PM operations.
+ * @dev: device structure of this GPIO bank
+ * @pint: GPIO PINT device that this GPIO bank mapped to
+ * @pint_map: GIOP bank mapping code in PINT device
+ * @pint_assign: The 32-bit PINT registers can be divided into 2 parts. A
+ *               GPIO bank can be mapped into either low 16 bits[0] or high 16
+ *               bits[1] of each PINT register.
+ * @lock: This lock make sure the irq_chip operations to one PINT device
+ *        for different GPIO interrrupts are atomic.
+ * @chip: abstract a GPIO controller
+ * @domain: The irq domain owned by the GPIO port.
+ * @rsvmap: Reservation map array for each pin in the GPIO bank
+ */
+struct gpio_port {
+	struct list_head node;
+	void __iomem *base;
+	unsigned int irq_base;
+	unsigned int width;
+	struct gpio_port_t *regs;
+	struct gpio_port_saved saved_data;
+	struct device *dev;
+
+	struct gpio_pint *pint;
+	u8 pint_map;
+	bool pint_assign;
+
+	spinlock_t lock;
+	struct gpio_chip chip;
+	struct irq_domain *domain;
+};
+
+static inline u8 pin_to_offset(struct pinctrl_gpio_range *range, unsigned pin)
+{
+	return pin - range->pin_base;
+}
+
+static inline u32 hwirq_to_pintbit(struct gpio_port *port, int hwirq)
+{
+	return port->pint_assign ? BIT(hwirq) << PINT_HI_OFFSET : BIT(hwirq);
+}
+
+static struct gpio_pint *find_gpio_pint(unsigned id)
+{
+	struct gpio_pint *pint;
+	int i = 0;
+
+	list_for_each_entry(pint, &adi_pint_list, node) {
+		if (id == i)
+			return pint;
+		i++;
+	}
+
+	return NULL;
+}
+
+static inline void port_setup(struct gpio_port *port, unsigned offset,
+	bool use_for_gpio)
+{
+	struct gpio_port_t *regs = port->regs;
+
+	if (use_for_gpio)
+		writew(readw(&regs->port_fer) & ~BIT(offset),
+			&regs->port_fer);
+	else
+		writew(readw(&regs->port_fer) | BIT(offset), &regs->port_fer);
+}
+
+static inline void portmux_setup(struct gpio_port *port, unsigned offset,
+	unsigned short function)
+{
+	struct gpio_port_t *regs = port->regs;
+	u32 pmux;
+
+	pmux = readl(&regs->port_mux);
+
+	/* The function field of each pin has 2 consecutive bits in
+	 * the mux register.
+	 */
+	pmux &= ~(0x3 << (2 * offset));
+	pmux |= (function & 0x3) << (2 * offset);
+
+	writel(pmux, &regs->port_mux);
+}
+
+static inline u16 get_portmux(struct gpio_port *port, unsigned offset)
+{
+	struct gpio_port_t *regs = port->regs;
+	u32 pmux = readl(&regs->port_mux);
+
+	/* The function field of each pin has 2 consecutive bits in
+	 * the mux register.
+	 */
+	return pmux >> (2 * offset) & 0x3;
+}
+
+static void adi_gpio_ack_irq(struct irq_data *d)
+{
+	unsigned long flags;
+	struct gpio_port *port = irq_data_get_irq_chip_data(d);
+	struct gpio_pint_regs *regs = port->pint->regs;
+	unsigned pintbit = hwirq_to_pintbit(port, d->hwirq);
+
+	spin_lock_irqsave(&port->lock, flags);
+	spin_lock(&port->pint->lock);
+
+	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {
+		if (readl(&regs->invert_set) & pintbit)
+			writel(pintbit, &regs->invert_clear);
+		else
+			writel(pintbit, &regs->invert_set);
+	}
+
+	writel(pintbit, &regs->request);
+
+	spin_unlock(&port->pint->lock);
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void adi_gpio_mask_ack_irq(struct irq_data *d)
+{
+	unsigned long flags;
+	struct gpio_port *port = irq_data_get_irq_chip_data(d);
+	struct gpio_pint_regs *regs = port->pint->regs;
+	unsigned pintbit = hwirq_to_pintbit(port, d->hwirq);
+
+	spin_lock_irqsave(&port->lock, flags);
+	spin_lock(&port->pint->lock);
+
+	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {
+		if (readl(&regs->invert_set) & pintbit)
+			writel(pintbit, &regs->invert_clear);
+		else
+			writel(pintbit, &regs->invert_set);
+	}
+
+	writel(pintbit, &regs->request);
+	writel(pintbit, &regs->mask_clear);
+
+	spin_unlock(&port->pint->lock);
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void adi_gpio_mask_irq(struct irq_data *d)
+{
+	unsigned long flags;
+	struct gpio_port *port = irq_data_get_irq_chip_data(d);
+	struct gpio_pint_regs *regs = port->pint->regs;
+
+	spin_lock_irqsave(&port->lock, flags);
+	spin_lock(&port->pint->lock);
+
+	writel(hwirq_to_pintbit(port, d->hwirq), &regs->mask_clear);
+
+	spin_unlock(&port->pint->lock);
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void adi_gpio_unmask_irq(struct irq_data *d)
+{
+	unsigned long flags;
+	struct gpio_port *port = irq_data_get_irq_chip_data(d);
+	struct gpio_pint_regs *regs = port->pint->regs;
+
+	spin_lock_irqsave(&port->lock, flags);
+	spin_lock(&port->pint->lock);
+
+	writel(hwirq_to_pintbit(port, d->hwirq), &regs->mask_set);
+
+	spin_unlock(&port->pint->lock);
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static unsigned int adi_gpio_irq_startup(struct irq_data *d)
+{
+	unsigned long flags;
+	struct gpio_port *port = irq_data_get_irq_chip_data(d);
+	struct gpio_pint_regs *regs;
+
+	if (!port) {
+		pr_err("GPIO IRQ %d :Not exist\n", d->irq);
+		return -ENODEV;
+	}
+
+	regs = port->pint->regs;
+
+	spin_lock_irqsave(&port->lock, flags);
+	spin_lock(&port->pint->lock);
+
+	port_setup(port, d->hwirq, true);
+	writew(BIT(d->hwirq), &port->regs->dir_clear);
+	writew(readw(&port->regs->inen) | BIT(d->hwirq), &port->regs->inen);
+
+	writel(hwirq_to_pintbit(port, d->hwirq), &regs->mask_set);
+
+	spin_unlock(&port->pint->lock);
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	return 0;
+}
+
+static void adi_gpio_irq_shutdown(struct irq_data *d)
+{
+	unsigned long flags;
+	struct gpio_port *port = irq_data_get_irq_chip_data(d);
+	struct gpio_pint_regs *regs = port->pint->regs;
+
+	spin_lock_irqsave(&port->lock, flags);
+	spin_lock(&port->pint->lock);
+
+	writel(hwirq_to_pintbit(port, d->hwirq), &regs->mask_clear);
+
+	spin_unlock(&port->pint->lock);
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static int adi_gpio_irq_type(struct irq_data *d, unsigned int type)
+{
+	unsigned long flags;
+	struct gpio_port *port = irq_data_get_irq_chip_data(d);
+	struct gpio_pint_regs *pint_regs;
+	unsigned pintmask;
+	unsigned int irq = d->irq;
+	int ret = 0;
+	char buf[16];
+
+	if (!port) {
+		pr_err("GPIO IRQ %d :Not exist\n", d->irq);
+		return -ENODEV;
+	}
+
+	pint_regs = port->pint->regs;
+
+	pintmask = hwirq_to_pintbit(port, d->hwirq);
+
+	spin_lock_irqsave(&port->lock, flags);
+	spin_lock(&port->pint->lock);
+
+	/* In case of interrupt autodetect, set irq type to edge sensitive. */
+	if (type == IRQ_TYPE_PROBE)
+		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+
+	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
+		    IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+		snprintf(buf, 16, "gpio-irq%d", irq);
+		port_setup(port, d->hwirq, true);
+	} else
+		goto out;
+
+	/* The GPIO interrupt is triggered only when its input value
+	 * transfer from 0 to 1. So, invert the input value if the
+	 * irq type is low or falling
+	 */
+	if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))
+		writel(pintmask, &pint_regs->invert_set);
+	else
+		writel(pintmask, &pint_regs->invert_clear);
+
+	/* In edge sensitive case, if the input value of the requested irq
+	 * is already 1, invert it.
+	 */
+	if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
+		if (gpio_get_value(port->chip.base + d->hwirq))
+			writel(pintmask, &pint_regs->invert_set);
+		else
+			writel(pintmask, &pint_regs->invert_clear);
+	}
+
+	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
+		writel(pintmask, &pint_regs->edge_set);
+		__irq_set_handler_locked(irq, handle_edge_irq);
+	} else {
+		writel(pintmask, &pint_regs->edge_clear);
+		__irq_set_handler_locked(irq, handle_level_irq);
+	}
+
+out:
+	spin_unlock(&port->pint->lock);
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int adi_gpio_set_wake(struct irq_data *d, unsigned int state)
+{
+	struct gpio_port *port = irq_data_get_irq_chip_data(d);
+
+	if (!port || !port->pint || port->pint->irq != d->irq)
+		return -EINVAL;
+
+#ifndef SEC_GCTL
+	adi_internal_set_wake(port->pint->irq, state);
+#endif
+
+	return 0;
+}
+
+static int adi_pint_suspend(void)
+{
+	struct gpio_pint *pint;
+
+	list_for_each_entry(pint, &adi_pint_list, node) {
+		writel(0xffffffff, &pint->regs->mask_clear);
+		pint->saved_data.assign = readl(&pint->regs->assign);
+		pint->saved_data.edge_set = readl(&pint->regs->edge_set);
+		pint->saved_data.invert_set = readl(&pint->regs->invert_set);
+	}
+
+	return 0;
+}
+
+static void adi_pint_resume(void)
+{
+	struct gpio_pint *pint;
+
+	list_for_each_entry(pint, &adi_pint_list, node) {
+		writel(pint->saved_data.assign, &pint->regs->assign);
+		writel(pint->saved_data.edge_set, &pint->regs->edge_set);
+		writel(pint->saved_data.invert_set, &pint->regs->invert_set);
+	}
+}
+
+static int adi_gpio_suspend(void)
+{
+	struct gpio_port *port;
+
+	list_for_each_entry(port, &adi_gpio_port_list, node) {
+		port->saved_data.fer = readw(&port->regs->port_fer);
+		port->saved_data.mux = readl(&port->regs->port_mux);
+		port->saved_data.data = readw(&port->regs->data);
+		port->saved_data.inen = readw(&port->regs->inen);
+		port->saved_data.dir = readw(&port->regs->dir_set);
+	}
+
+	return adi_pint_suspend();
+}
+
+static void adi_gpio_resume(void)
+{
+	struct gpio_port *port;
+
+	adi_pint_resume();
+
+	list_for_each_entry(port, &adi_gpio_port_list, node) {
+		writel(port->saved_data.mux, &port->regs->port_mux);
+		writew(port->saved_data.fer, &port->regs->port_fer);
+		writew(port->saved_data.inen, &port->regs->inen);
+		writew(port->saved_data.data & port->saved_data.dir,
+					&port->regs->data_set);
+		writew(port->saved_data.dir, &port->regs->dir_set);
+	}
+
+}
+
+static struct syscore_ops gpio_pm_syscore_ops = {
+	.suspend = adi_gpio_suspend,
+	.resume = adi_gpio_resume,
+};
+#else /* CONFIG_PM */
+#define adi_gpio_set_wake NULL
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_IRQ_PREFLOW_FASTEOI
+static inline void preflow_handler(struct irq_desc *desc)
+{
+	if (desc->preflow_handler)
+		desc->preflow_handler(&desc->irq_data);
+}
+#else
+static inline void preflow_handler(struct irq_desc *desc) { }
+#endif
+
+static void adi_gpio_handle_pint_irq(unsigned int inta_irq,
+			struct irq_desc *desc)
+{
+	u32 request;
+	u32 level_mask, hwirq;
+	bool umask = false;
+	struct gpio_pint *pint = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct gpio_pint_regs *regs = pint->regs;
+	struct irq_domain *domain;
+
+	preflow_handler(desc);
+	chained_irq_enter(chip, desc);
+
+	request = readl(&regs->request);
+	level_mask = readl(&regs->edge_set) & request;
+
+	hwirq = 0;
+	domain = pint->domain[0];
+	while (request) {
+		/* domain pointer need to be changed only once at IRQ 16 when
+		 * we go through IRQ requests from bit 0 to bit 31.
+		 */
+		if (hwirq == PINT_HI_OFFSET)
+			domain = pint->domain[1];
+
+		if (request & 1) {
+			if (level_mask & BIT(hwirq)) {
+				umask = true;
+				chained_irq_exit(chip, desc);
+			}
+			generic_handle_irq(irq_find_mapping(domain,
+					hwirq % PINT_HI_OFFSET));
+		}
+
+		hwirq++;
+		request >>= 1;
+	}
+
+	if (!umask)
+		chained_irq_exit(chip, desc);
+}
+
+static struct irq_chip adi_gpio_irqchip = {
+	.name = "GPIO",
+	.irq_ack = adi_gpio_ack_irq,
+	.irq_mask = adi_gpio_mask_irq,
+	.irq_mask_ack = adi_gpio_mask_ack_irq,
+	.irq_unmask = adi_gpio_unmask_irq,
+	.irq_disable = adi_gpio_mask_irq,
+	.irq_enable = adi_gpio_unmask_irq,
+	.irq_set_type = adi_gpio_irq_type,
+	.irq_startup = adi_gpio_irq_startup,
+	.irq_shutdown = adi_gpio_irq_shutdown,
+	.irq_set_wake = adi_gpio_set_wake,
+};
+
+static int adi_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pinctrl->soc->ngroups;
+}
+
+static const char *adi_get_group_name(struct pinctrl_dev *pctldev,
+				       unsigned selector)
+{
+	struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pinctrl->soc->groups[selector].name;
+}
+
+static int adi_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+			       const unsigned **pins,
+			       unsigned *num_pins)
+{
+	struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	*pins = pinctrl->soc->groups[selector].pins;
+	*num_pins = pinctrl->soc->groups[selector].num;
+	return 0;
+}
+
+static struct pinctrl_ops adi_pctrl_ops = {
+	.get_groups_count = adi_get_groups_count,
+	.get_group_name = adi_get_group_name,
+	.get_group_pins = adi_get_group_pins,
+};
+
+static int adi_pinmux_enable(struct pinctrl_dev *pctldev, unsigned selector,
+	unsigned group)
+{
+	struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+	struct gpio_port *port;
+	struct pinctrl_gpio_range *range;
+	unsigned long flags;
+	unsigned short *mux, pin;
+
+	mux = (unsigned short *)pinctrl->soc->functions[selector].mux;
+
+	while (*mux) {
+		pin = P_IDENT(*mux);
+
+		range = pinctrl_find_gpio_range_from_pin(pctldev, pin);
+		if (range == NULL) /* should not happen */
+			return -ENODEV;
+
+		port = container_of(range->gc, struct gpio_port, chip);
+
+		spin_lock_irqsave(&port->lock, flags);
+
+		portmux_setup(port, pin_to_offset(range, pin),
+				 P_FUNCT2MUX(*mux));
+		port_setup(port, pin_to_offset(range, pin), false);
+		mux++;
+
+		spin_unlock_irqrestore(&port->lock, flags);
+	}
+
+	return 0;
+}
+
+static void adi_pinmux_disable(struct pinctrl_dev *pctldev, unsigned selector,
+	unsigned group)
+{
+	struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+	struct gpio_port *port;
+	struct pinctrl_gpio_range *range;
+	unsigned long flags;
+	unsigned short *mux, pin;
+
+	mux = (unsigned short *)pinctrl->soc->functions[selector].mux;
+
+	while (*mux) {
+		pin = P_IDENT(*mux);
+
+		range = pinctrl_find_gpio_range_from_pin(pctldev, pin);
+		if (range == NULL) /* should not happen */
+			return;
+
+		port = container_of(range->gc, struct gpio_port, chip);
+
+		spin_lock_irqsave(&port->lock, flags);
+
+		port_setup(port, pin_to_offset(range, pin), true);
+		mux++;
+
+		spin_unlock_irqrestore(&port->lock, flags);
+	}
+}
+
+static int adi_pinmux_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+	struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pinctrl->soc->nfunctions;
+}
+
+static const char *adi_pinmux_get_func_name(struct pinctrl_dev *pctldev,
+					  unsigned selector)
+{
+	struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pinctrl->soc->functions[selector].name;
+}
+
+static int adi_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
+			       const char * const **groups,
+			       unsigned * const num_groups)
+{
+	struct adi_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = pinctrl->soc->functions[selector].groups;
+	*num_groups = pinctrl->soc->functions[selector].num_groups;
+	return 0;
+}
+
+static int adi_pinmux_request_gpio(struct pinctrl_dev *pctldev,
+	struct pinctrl_gpio_range *range, unsigned pin)
+{
+	struct gpio_port *port;
+	unsigned long flags;
+	u8 offset;
+
+	port = container_of(range->gc, struct gpio_port, chip);
+	offset = pin_to_offset(range, pin);
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	port_setup(port, offset, true);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	return 0;
+}
+
+static struct pinmux_ops adi_pinmux_ops = {
+	.enable = adi_pinmux_enable,
+	.disable = adi_pinmux_disable,
+	.get_functions_count = adi_pinmux_get_funcs_count,
+	.get_function_name = adi_pinmux_get_func_name,
+	.get_function_groups = adi_pinmux_get_groups,
+	.gpio_request_enable = adi_pinmux_request_gpio,
+};
+
+
+static struct pinctrl_desc adi_pinmux_desc = {
+	.name = DRIVER_NAME,
+	.pctlops = &adi_pctrl_ops,
+	.pmxops = &adi_pinmux_ops,
+	.owner = THIS_MODULE,
+};
+
+static int adi_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void adi_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	pinctrl_free_gpio(chip->base + offset);
+}
+
+static int adi_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct gpio_port *port;
+	unsigned long flags;
+
+	port = container_of(chip, struct gpio_port, chip);
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	writew(BIT(offset), &port->regs->dir_clear);
+	writew(readw(&port->regs->inen) | BIT(offset), &port->regs->inen);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	return 0;
+}
+
+static void adi_gpio_set_value(struct gpio_chip *chip, unsigned offset,
+	int value)
+{
+	struct gpio_port *port = container_of(chip, struct gpio_port, chip);
+	struct gpio_port_t *regs = port->regs;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	if (value)
+		writew(BIT(offset), &regs->data_set);
+	else
+		writew(BIT(offset), &regs->data_clear);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static int adi_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+	int value)
+{
+	struct gpio_port *port = container_of(chip, struct gpio_port, chip);
+	struct gpio_port_t *regs = port->regs;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	writew(readw(&regs->inen) & ~BIT(offset), &regs->inen);
+	if (value)
+		writew(BIT(offset), &regs->data_set);
+	else
+		writew(BIT(offset), &regs->data_clear);
+	writew(BIT(offset), &regs->dir_set);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	return 0;
+}
+
+static int adi_gpio_get_value(struct gpio_chip *chip, unsigned offset)
+{
+	struct gpio_port *port = container_of(chip, struct gpio_port, chip);
+	struct gpio_port_t *regs = port->regs;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	ret = !!(readw(&regs->data) & BIT(offset));
+
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	return ret;
+}
+
+static int adi_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct gpio_port *port = container_of(chip, struct gpio_port, chip);
+
+	if (port->irq_base >= 0)
+		return irq_find_mapping(port->domain, offset);
+	else
+		return irq_create_mapping(port->domain, offset);
+}
+
+static int adi_pint_map_port(struct gpio_pint *pint, bool assign, u8 map,
+	struct irq_domain *domain)
+{
+	struct gpio_pint_regs *regs = pint->regs;
+	u32 map_mask;
+
+	if (pint->map_count > 1)
+		return -EINVAL;
+
+	pint->map_count++;
+
+	/* The map_mask of each gpio port is a 16-bit duplicate
+	 * of the 8-bit map. It can be set to either high 16 bits or low
+	 * 16 bits of the pint assignment register.
+	 */
+	map_mask = (map << 8) | map;
+	if (assign) {
+		map_mask <<= PINT_HI_OFFSET;
+		writel((readl(&regs->assign) & 0xFFFF) | map_mask,
+			&regs->assign);
+	} else
+		writel((readl(&regs->assign) & 0xFFFF0000) | map_mask,
+			&regs->assign);
+
+	pint->domain[assign] = domain;
+
+	return 0;
+}
+
+static int adi_gpio_pint_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct gpio_pint *pint;
+
+	pint = devm_kzalloc(dev, sizeof(struct gpio_pint), GFP_KERNEL);
+	if (!pint) {
+		dev_err(dev, "Memory alloc failed\n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	pint->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(pint->base))
+		return PTR_ERR(pint->base);
+
+	pint->regs = (struct gpio_pint_regs *)pint->base;
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(dev, "Invalid IRQ resource\n");
+		return -ENODEV;
+	}
+
+	spin_lock_init(&pint->lock);
+
+	pint->irq = res->start;
+	pint->pint_map_port = adi_pint_map_port;
+	platform_set_drvdata(pdev, pint);
+
+	irq_set_chained_handler(pint->irq, adi_gpio_handle_pint_irq);
+	irq_set_handler_data(pint->irq, pint);
+
+	list_add_tail(&pint->node, &adi_pint_list);
+
+	return 0;
+}
+
+static int adi_gpio_pint_remove(struct platform_device *pdev)
+{
+	struct gpio_pint *pint = platform_get_drvdata(pdev);
+
+	list_del(&pint->node);
+	irq_set_handler(pint->irq, handle_simple_irq);
+
+	return 0;
+}
+
+static int adi_gpio_irq_map(struct irq_domain *d, unsigned int irq,
+				irq_hw_number_t hwirq)
+{
+	struct gpio_port *port = d->host_data;
+
+	if (!port)
+		return -EINVAL;
+
+	irq_set_chip_data(irq, port);
+	irq_set_chip_and_handler(irq, &adi_gpio_irqchip,
+				handle_level_irq);
+
+	return 0;
+}
+
+const struct irq_domain_ops adi_gpio_irq_domain_ops = {
+	.map = adi_gpio_irq_map,
+	.xlate = irq_domain_xlate_onecell,
+};
+
+static int adi_gpio_init_int(struct gpio_port *port)
+{
+	struct device_node *node = port->dev->of_node;
+	struct gpio_pint *pint = port->pint;
+	int ret;
+
+	port->domain = irq_domain_add_linear(node, port->width,
+				&adi_gpio_irq_domain_ops, port);
+	if (!port->domain) {
+		dev_err(port->dev, "Failed to create irqdomain\n");
+		return -ENOSYS;
+	}
+
+	/* According to BF54x and BF60x HRM, pin interrupt devices are not
+	 * part of the GPIO port device. in GPIO interrupt mode, the GPIO
+	 * pins of multiple port devices can be routed into one pin interrupt
+	 * device. The mapping can be configured by setting pint assignment
+	 * register with the mapping value of different GPIO port. This is
+	 * done via function pint_map_port().
+	 */
+	ret = pint->pint_map_port(port->pint, port->pint_assign,
+			port->pint_map,	port->domain);
+	if (ret)
+		return ret;
+
+	if (port->irq_base >= 0) {
+		ret = irq_create_strict_mappings(port->domain, port->irq_base,
+					0, port->width);
+		if (ret) {
+			dev_err(port->dev, "Couldn't associate to domain\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+#define DEVNAME_SIZE 16
+
+static int adi_gpio_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	const struct adi_pinctrl_gpio_platform_data *pdata;
+	struct resource *res;
+	struct gpio_port *port;
+	char pinctrl_devname[DEVNAME_SIZE];
+	static int gpio;
+	int ret = 0, ret1;
+
+	pdata = dev->platform_data;
+	if (!pdata)
+		return -EINVAL;
+
+	port = devm_kzalloc(dev, sizeof(struct gpio_port), GFP_KERNEL);
+	if (!port) {
+		dev_err(dev, "Memory alloc failed\n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	port->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(port->base))
+		return PTR_ERR(port->base);
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res)
+		port->irq_base = -1;
+	else
+		port->irq_base = res->start;
+
+	port->width = pdata->port_width;
+	port->dev = dev;
+	port->regs = (struct gpio_port_t *)port->base;
+	port->pint_assign = pdata->pint_assign;
+	port->pint_map = pdata->pint_map;
+
+	port->pint = find_gpio_pint(pdata->pint_id);
+	if (port->pint) {
+		ret = adi_gpio_init_int(port);
+		if (ret)
+			return ret;
+	}
+
+	spin_lock_init(&port->lock);
+
+	platform_set_drvdata(pdev, port);
+
+	port->chip.label		= "adi-gpio";
+	port->chip.direction_input	= adi_gpio_direction_input;
+	port->chip.get			= adi_gpio_get_value;
+	port->chip.direction_output	= adi_gpio_direction_output;
+	port->chip.set			= adi_gpio_set_value;
+	port->chip.request		= adi_gpio_request;
+	port->chip.free			= adi_gpio_free;
+	port->chip.to_irq		= adi_gpio_to_irq;
+	if (pdata->port_gpio_base > 0)
+		port->chip.base		= pdata->port_gpio_base;
+	else
+		port->chip.base		= gpio;
+	port->chip.ngpio		= port->width;
+	gpio = port->chip.base + port->width;
+
+	ret = gpiochip_add(&port->chip);
+	if (ret) {
+		dev_err(&pdev->dev, "Fail to add GPIO chip.\n");
+		goto out_remove_domain;
+	}
+
+	/* Add gpio pin range */
+	snprintf(pinctrl_devname, DEVNAME_SIZE, "pinctrl-adi2.%d",
+		pdata->pinctrl_id);
+	pinctrl_devname[DEVNAME_SIZE - 1] = 0;
+	ret = gpiochip_add_pin_range(&port->chip, pinctrl_devname,
+		0, pdata->port_pin_base, port->width);
+	if (ret) {
+		dev_err(&pdev->dev, "Fail to add pin range to %s.\n",
+				pinctrl_devname);
+		goto out_remove_gpiochip;
+	}
+
+	list_add_tail(&port->node, &adi_gpio_port_list);
+
+	return 0;
+
+out_remove_gpiochip:
+	ret1 = gpiochip_remove(&port->chip);
+out_remove_domain:
+	if (port->pint)
+		irq_domain_remove(port->domain);
+
+	return ret;
+}
+
+static int adi_gpio_remove(struct platform_device *pdev)
+{
+	struct gpio_port *port = platform_get_drvdata(pdev);
+	int ret;
+	u8 offset;
+
+	list_del(&port->node);
+	gpiochip_remove_pin_ranges(&port->chip);
+	ret = gpiochip_remove(&port->chip);
+	if (port->pint) {
+		for (offset = 0; offset < port->width; offset++)
+			irq_dispose_mapping(irq_find_mapping(port->domain,
+				offset));
+		irq_domain_remove(port->domain);
+	}
+
+	return ret;
+}
+
+static int adi_pinctrl_probe(struct platform_device *pdev)
+{
+	struct adi_pinctrl *pinctrl;
+
+	pinctrl = devm_kzalloc(&pdev->dev, sizeof(*pinctrl), GFP_KERNEL);
+	if (!pinctrl)
+		return -ENOMEM;
+
+	pinctrl->dev = &pdev->dev;
+
+	adi_pinctrl_soc_init(&pinctrl->soc);
+
+	adi_pinmux_desc.pins = pinctrl->soc->pins;
+	adi_pinmux_desc.npins = pinctrl->soc->npins;
+
+	/* Now register the pin controller and all pins it handles */
+	pinctrl->pctl = pinctrl_register(&adi_pinmux_desc, &pdev->dev, pinctrl);
+	if (!pinctrl->pctl) {
+		dev_err(&pdev->dev, "could not register pinctrl ADI2 driver\n");
+		return -EINVAL;
+	}
+
+	platform_set_drvdata(pdev, pinctrl);
+
+	return 0;
+}
+
+static int adi_pinctrl_remove(struct platform_device *pdev)
+{
+	struct adi_pinctrl *pinctrl = platform_get_drvdata(pdev);
+
+	pinctrl_unregister(pinctrl->pctl);
+
+	return 0;
+}
+
+static struct platform_driver adi_pinctrl_driver = {
+	.probe		= adi_pinctrl_probe,
+	.remove		= adi_pinctrl_remove,
+	.driver		= {
+		.name	= DRIVER_NAME,
+	},
+};
+
+static struct platform_driver adi_gpio_pint_driver = {
+	.probe		= adi_gpio_pint_probe,
+	.remove		= adi_gpio_pint_remove,
+	.driver		= {
+		.name	= "adi-gpio-pint",
+	},
+};
+
+static struct platform_driver adi_gpio_driver = {
+	.probe		= adi_gpio_probe,
+	.remove		= adi_gpio_remove,
+	.driver		= {
+		.name	= "adi-gpio",
+	},
+};
+
+static int __init adi_pinctrl_setup(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&adi_pinctrl_driver);
+	if (ret)
+		return ret;
+
+	ret = platform_driver_register(&adi_gpio_pint_driver);
+	if (ret)
+		goto pint_error;
+
+	ret = platform_driver_register(&adi_gpio_driver);
+	if (ret)
+		goto gpio_error;
+
+#ifdef CONFIG_PM
+	register_syscore_ops(&gpio_pm_syscore_ops);
+#endif
+	return ret;
+gpio_error:
+	platform_driver_unregister(&adi_gpio_pint_driver);
+pint_error:
+	platform_driver_unregister(&adi_pinctrl_driver);
+
+	return ret;
+}
+arch_initcall(adi_pinctrl_setup);
+
+MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
+MODULE_DESCRIPTION("ADI gpio2 pin control driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/pinctrl-adi2.h b/drivers/pinctrl/pinctrl-adi2.h
new file mode 100644
index 0000000..1f06f8d
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-adi2.h
@@ -0,0 +1,75 @@
+/*
+ * Pinctrl Driver for ADI GPIO2 controller
+ *
+ * Copyright 2007-2013 Analog Devices Inc.
+ *
+ * Licensed under the GPLv2 or later
+ */
+
+#ifndef PINCTRL_PINCTRL_ADI2_H
+#define PINCTRL_PINCTRL_ADI2_H
+
+#include <linux/pinctrl/pinctrl.h>
+
+ /**
+ * struct adi_pin_group - describes a pin group
+ * @name: the name of this pin group
+ * @pins: an array of pins
+ * @num: the number of pins in this array
+ */
+struct adi_pin_group {
+	const char *name;
+	const unsigned *pins;
+	const unsigned num;
+};
+
+#define ADI_PIN_GROUP(n, p)  \
+	{			\
+		.name = n,	\
+		.pins = p,	\
+		.num = ARRAY_SIZE(p),	\
+	}
+
+ /**
+ * struct adi_pmx_func - describes function mux setting of pin groups
+ * @name: the name of this function mux setting
+ * @groups: an array of pin groups
+ * @num_groups: the number of pin groups in this array
+ * @mux: the function mux setting array, end by zero
+ */
+struct adi_pmx_func {
+	const char *name;
+	const char * const *groups;
+	const unsigned num_groups;
+	const unsigned short *mux;
+};
+
+#define ADI_PMX_FUNCTION(n, g, m)		\
+	{					\
+		.name = n,			\
+		.groups = g,			\
+		.num_groups = ARRAY_SIZE(g),	\
+		.mux = m,			\
+	}
+
+/**
+ * struct adi_pinctrl_soc_data - ADI pin controller per-SoC configuration
+ * @functions:  The functions supported on this SoC.
+ * @nfunction:  The number of entries in @functions.
+ * @groups:     An array describing all pin groups the pin SoC supports.
+ * @ngroups:    The number of entries in @groups.
+ * @pins:       An array describing all pins the pin controller affects.
+ * @npins:      The number of entries in @pins.
+ */
+struct adi_pinctrl_soc_data {
+	const struct adi_pmx_func *functions;
+	int nfunctions;
+	const struct adi_pin_group *groups;
+	int ngroups;
+	const struct pinctrl_pin_desc *pins;
+	int npins;
+};
+
+void adi_pinctrl_soc_init(const struct adi_pinctrl_soc_data **soc);
+
+#endif /* PINCTRL_PINCTRL_ADI2_H */
diff --git a/drivers/pinctrl/pinctrl-as3722.c b/drivers/pinctrl/pinctrl-as3722.c
new file mode 100644
index 0000000..01bffc1
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-as3722.c
@@ -0,0 +1,630 @@
+/*
+ * ams AS3722 pin control and GPIO driver.
+ *
+ * Copyright (c) 2013, NVIDIA Corporation.
+ *
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mfd/as3722.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+
+#include "core.h"
+#include "pinconf.h"
+#include "pinctrl-utils.h"
+
+#define AS3722_PIN_GPIO0		0
+#define AS3722_PIN_GPIO1		1
+#define AS3722_PIN_GPIO2		2
+#define AS3722_PIN_GPIO3		3
+#define AS3722_PIN_GPIO4		4
+#define AS3722_PIN_GPIO5		5
+#define AS3722_PIN_GPIO6		6
+#define AS3722_PIN_GPIO7		7
+#define AS3722_PIN_NUM			(AS3722_PIN_GPIO7 + 1)
+
+#define AS3722_GPIO_MODE_PULL_UP           BIT(PIN_CONFIG_BIAS_PULL_UP)
+#define AS3722_GPIO_MODE_PULL_DOWN         BIT(PIN_CONFIG_BIAS_PULL_DOWN)
+#define AS3722_GPIO_MODE_HIGH_IMPED        BIT(PIN_CONFIG_BIAS_HIGH_IMPEDANCE)
+#define AS3722_GPIO_MODE_OPEN_DRAIN        BIT(PIN_CONFIG_DRIVE_OPEN_DRAIN)
+
+struct as3722_pin_function {
+	const char *name;
+	const char * const *groups;
+	unsigned ngroups;
+	int mux_option;
+};
+
+struct as3722_gpio_pin_control {
+	bool enable_gpio_invert;
+	unsigned mode_prop;
+	int io_function;
+};
+
+struct as3722_pingroup {
+	const char *name;
+	const unsigned pins[1];
+	unsigned npins;
+};
+
+struct as3722_pctrl_info {
+	struct device *dev;
+	struct pinctrl_dev *pctl;
+	struct as3722 *as3722;
+	struct gpio_chip gpio_chip;
+	int pins_current_opt[AS3722_PIN_NUM];
+	const struct as3722_pin_function *functions;
+	unsigned num_functions;
+	const struct as3722_pingroup *pin_groups;
+	int num_pin_groups;
+	const struct pinctrl_pin_desc *pins;
+	unsigned num_pins;
+	struct as3722_gpio_pin_control gpio_control[AS3722_PIN_NUM];
+};
+
+static const struct pinctrl_pin_desc as3722_pins_desc[] = {
+	PINCTRL_PIN(AS3722_PIN_GPIO0, "gpio0"),
+	PINCTRL_PIN(AS3722_PIN_GPIO1, "gpio1"),
+	PINCTRL_PIN(AS3722_PIN_GPIO2, "gpio2"),
+	PINCTRL_PIN(AS3722_PIN_GPIO3, "gpio3"),
+	PINCTRL_PIN(AS3722_PIN_GPIO4, "gpio4"),
+	PINCTRL_PIN(AS3722_PIN_GPIO5, "gpio5"),
+	PINCTRL_PIN(AS3722_PIN_GPIO6, "gpio6"),
+	PINCTRL_PIN(AS3722_PIN_GPIO7, "gpio7"),
+};
+
+static const char * const gpio_groups[] = {
+	"gpio0",
+	"gpio1",
+	"gpio2",
+	"gpio3",
+	"gpio4",
+	"gpio5",
+	"gpio6",
+	"gpio7",
+};
+
+enum as3722_pinmux_option {
+	AS3722_PINMUX_GPIO			= 0,
+	AS3722_PINMUX_INTERRUPT_OUT		= 1,
+	AS3722_PINMUX_VSUB_VBAT_UNDEB_LOW_OUT	= 2,
+	AS3722_PINMUX_GPIO_INTERRUPT		= 3,
+	AS3722_PINMUX_PWM_INPUT			= 4,
+	AS3722_PINMUX_VOLTAGE_IN_STBY		= 5,
+	AS3722_PINMUX_OC_PG_SD0			= 6,
+	AS3722_PINMUX_PG_OUT			= 7,
+	AS3722_PINMUX_CLK32K_OUT		= 8,
+	AS3722_PINMUX_WATCHDOG_INPUT		= 9,
+	AS3722_PINMUX_SOFT_RESET_IN		= 11,
+	AS3722_PINMUX_PWM_OUTPUT		= 12,
+	AS3722_PINMUX_VSUB_VBAT_LOW_DEB_OUT	= 13,
+	AS3722_PINMUX_OC_PG_SD6			= 14,
+};
+
+#define FUNCTION_GROUP(fname, mux)			\
+	{						\
+		.name = #fname,				\
+		.groups = gpio_groups,			\
+		.ngroups = ARRAY_SIZE(gpio_groups),	\
+		.mux_option = AS3722_PINMUX_##mux,	\
+	}
+
+static const struct as3722_pin_function as3722_pin_function[] = {
+	FUNCTION_GROUP(gpio, GPIO),
+	FUNCTION_GROUP(interrupt-out, INTERRUPT_OUT),
+	FUNCTION_GROUP(gpio-in-interrupt, GPIO_INTERRUPT),
+	FUNCTION_GROUP(vsup-vbat-low-undebounce-out, VSUB_VBAT_UNDEB_LOW_OUT),
+	FUNCTION_GROUP(vsup-vbat-low-debounce-out, VSUB_VBAT_LOW_DEB_OUT),
+	FUNCTION_GROUP(voltage-in-standby, VOLTAGE_IN_STBY),
+	FUNCTION_GROUP(oc-pg-sd0, OC_PG_SD0),
+	FUNCTION_GROUP(oc-pg-sd6, OC_PG_SD6),
+	FUNCTION_GROUP(powergood-out, PG_OUT),
+	FUNCTION_GROUP(pwm-in, PWM_INPUT),
+	FUNCTION_GROUP(pwm-out, PWM_OUTPUT),
+	FUNCTION_GROUP(clk32k-out, CLK32K_OUT),
+	FUNCTION_GROUP(watchdog-in, WATCHDOG_INPUT),
+	FUNCTION_GROUP(soft-reset-in, SOFT_RESET_IN),
+};
+
+#define AS3722_PINGROUP(pg_name, pin_id) \
+	{								\
+		.name = #pg_name,					\
+		.pins = {AS3722_PIN_##pin_id},				\
+		.npins = 1,						\
+	}
+
+static const struct as3722_pingroup as3722_pingroups[] = {
+	AS3722_PINGROUP(gpio0,	GPIO0),
+	AS3722_PINGROUP(gpio1,	GPIO1),
+	AS3722_PINGROUP(gpio2,	GPIO2),
+	AS3722_PINGROUP(gpio3,	GPIO3),
+	AS3722_PINGROUP(gpio4,	GPIO4),
+	AS3722_PINGROUP(gpio5,	GPIO5),
+	AS3722_PINGROUP(gpio6,	GPIO6),
+	AS3722_PINGROUP(gpio7,	GPIO7),
+};
+
+static int as3722_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
+
+	return as_pci->num_pin_groups;
+}
+
+static const char *as3722_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+		unsigned group)
+{
+	struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
+
+	return as_pci->pin_groups[group].name;
+}
+
+static int as3722_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+		unsigned group, const unsigned **pins, unsigned *num_pins)
+{
+	struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
+
+	*pins = as_pci->pin_groups[group].pins;
+	*num_pins = as_pci->pin_groups[group].npins;
+	return 0;
+}
+
+static const struct pinctrl_ops as3722_pinctrl_ops = {
+	.get_groups_count = as3722_pinctrl_get_groups_count,
+	.get_group_name = as3722_pinctrl_get_group_name,
+	.get_group_pins = as3722_pinctrl_get_group_pins,
+	.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+	.dt_free_map = pinctrl_utils_dt_free_map,
+};
+
+static int as3722_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+	struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
+
+	return as_pci->num_functions;
+}
+
+static const char *as3722_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+			unsigned function)
+{
+	struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
+
+	return as_pci->functions[function].name;
+}
+
+static int as3722_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
+		unsigned function, const char * const **groups,
+		unsigned * const num_groups)
+{
+	struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = as_pci->functions[function].groups;
+	*num_groups = as_pci->functions[function].ngroups;
+	return 0;
+}
+
+static int as3722_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned function,
+		unsigned group)
+{
+	struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
+	int gpio_cntr_reg = AS3722_GPIOn_CONTROL_REG(group);
+	u8 val = AS3722_GPIO_IOSF_VAL(as_pci->functions[function].mux_option);
+	int ret;
+
+	dev_dbg(as_pci->dev, "%s(): GPIO %u pin to function %u and val %u\n",
+		__func__, group, function, val);
+
+	ret = as3722_update_bits(as_pci->as3722, gpio_cntr_reg,
+			AS3722_GPIO_IOSF_MASK, val);
+	if (ret < 0) {
+		dev_err(as_pci->dev, "GPIO%d_CTRL_REG update failed %d\n",
+			group, ret);
+		return ret;
+	}
+	as_pci->gpio_control[group].io_function = function;
+	return ret;
+}
+
+static int as3722_pinctrl_gpio_get_mode(unsigned gpio_mode_prop, bool input)
+{
+	if (gpio_mode_prop & AS3722_GPIO_MODE_HIGH_IMPED)
+		return -EINVAL;
+
+	if (gpio_mode_prop & AS3722_GPIO_MODE_OPEN_DRAIN) {
+		if (gpio_mode_prop & AS3722_GPIO_MODE_PULL_UP)
+			return AS3722_GPIO_MODE_IO_OPEN_DRAIN_PULL_UP;
+		return AS3722_GPIO_MODE_IO_OPEN_DRAIN;
+	}
+	if (input) {
+		if (gpio_mode_prop & AS3722_GPIO_MODE_PULL_UP)
+			return AS3722_GPIO_MODE_INPUT_PULL_UP;
+		else if (gpio_mode_prop & AS3722_GPIO_MODE_PULL_DOWN)
+			return AS3722_GPIO_MODE_INPUT_PULL_DOWN;
+		return AS3722_GPIO_MODE_INPUT;
+	}
+	if (gpio_mode_prop & AS3722_GPIO_MODE_PULL_DOWN)
+		return AS3722_GPIO_MODE_OUTPUT_VDDL;
+	return AS3722_GPIO_MODE_OUTPUT_VDDH;
+}
+
+static int as3722_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev,
+		struct pinctrl_gpio_range *range, unsigned offset)
+{
+	struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
+
+	if (as_pci->gpio_control[offset].io_function)
+		return -EBUSY;
+	return 0;
+}
+
+static int as3722_pinctrl_gpio_set_direction(struct pinctrl_dev *pctldev,
+		struct pinctrl_gpio_range *range, unsigned offset, bool input)
+{
+	struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
+	struct as3722 *as3722 = as_pci->as3722;
+	int mode;
+
+	mode = as3722_pinctrl_gpio_get_mode(
+			as_pci->gpio_control[offset].mode_prop, input);
+	if (mode < 0) {
+		dev_err(as_pci->dev, "%s direction for GPIO %d not supported\n",
+			(input) ? "Input" : "Output", offset);
+		return mode;
+	}
+
+	if (as_pci->gpio_control[offset].enable_gpio_invert)
+		mode |= AS3722_GPIO_INV;
+
+	return as3722_write(as3722, AS3722_GPIOn_CONTROL_REG(offset), mode);
+}
+
+static const struct pinmux_ops as3722_pinmux_ops = {
+	.get_functions_count	= as3722_pinctrl_get_funcs_count,
+	.get_function_name	= as3722_pinctrl_get_func_name,
+	.get_function_groups	= as3722_pinctrl_get_func_groups,
+	.enable			= as3722_pinctrl_enable,
+	.gpio_request_enable	= as3722_pinctrl_gpio_request_enable,
+	.gpio_set_direction	= as3722_pinctrl_gpio_set_direction,
+};
+
+static int as3722_pinconf_get(struct pinctrl_dev *pctldev,
+			unsigned pin, unsigned long *config)
+{
+	struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
+	enum pin_config_param param = pinconf_to_config_param(*config);
+	int arg = 0;
+	u16 prop;
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		prop = AS3722_GPIO_MODE_PULL_UP |
+				AS3722_GPIO_MODE_PULL_DOWN;
+		if (!(as_pci->gpio_control[pin].mode_prop & prop))
+			arg = 1;
+		prop = 0;
+		break;
+
+	case PIN_CONFIG_BIAS_PULL_UP:
+		prop = AS3722_GPIO_MODE_PULL_UP;
+		break;
+
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		prop = AS3722_GPIO_MODE_PULL_DOWN;
+		break;
+
+	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+		prop = AS3722_GPIO_MODE_OPEN_DRAIN;
+		break;
+
+	case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
+		prop = AS3722_GPIO_MODE_HIGH_IMPED;
+		break;
+
+	default:
+		dev_err(as_pci->dev, "Properties not supported\n");
+		return -ENOTSUPP;
+	}
+
+	if (as_pci->gpio_control[pin].mode_prop & prop)
+		arg = 1;
+
+	*config = pinconf_to_config_packed(param, (u16)arg);
+	return 0;
+}
+
+static int as3722_pinconf_set(struct pinctrl_dev *pctldev,
+			unsigned pin, unsigned long *configs,
+			unsigned num_configs)
+{
+	struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);
+	enum pin_config_param param;
+	int mode_prop;
+	int i;
+
+	for (i = 0; i < num_configs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		mode_prop = as_pci->gpio_control[pin].mode_prop;
+
+		switch (param) {
+		case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
+			break;
+
+		case PIN_CONFIG_BIAS_DISABLE:
+			mode_prop &= ~(AS3722_GPIO_MODE_PULL_UP |
+					AS3722_GPIO_MODE_PULL_DOWN);
+			break;
+		case PIN_CONFIG_BIAS_PULL_UP:
+			mode_prop |= AS3722_GPIO_MODE_PULL_UP;
+			break;
+
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			mode_prop |= AS3722_GPIO_MODE_PULL_DOWN;
+			break;
+
+		case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
+			mode_prop |= AS3722_GPIO_MODE_HIGH_IMPED;
+			break;
+
+		case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+			mode_prop |= AS3722_GPIO_MODE_OPEN_DRAIN;
+			break;
+
+		default:
+			dev_err(as_pci->dev, "Properties not supported\n");
+			return -ENOTSUPP;
+		}
+
+		as_pci->gpio_control[pin].mode_prop = mode_prop;
+	}
+	return 0;
+}
+
+static const struct pinconf_ops as3722_pinconf_ops = {
+	.pin_config_get = as3722_pinconf_get,
+	.pin_config_set = as3722_pinconf_set,
+};
+
+static struct pinctrl_desc as3722_pinctrl_desc = {
+	.pctlops = &as3722_pinctrl_ops,
+	.pmxops = &as3722_pinmux_ops,
+	.confops = &as3722_pinconf_ops,
+	.owner = THIS_MODULE,
+};
+
+static inline struct as3722_pctrl_info *to_as_pci(struct gpio_chip *chip)
+{
+	return container_of(chip, struct as3722_pctrl_info, gpio_chip);
+}
+
+static int as3722_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct as3722_pctrl_info *as_pci = to_as_pci(chip);
+	struct as3722 *as3722 = as_pci->as3722;
+	int ret;
+	u32 reg;
+	u32 control;
+	u32 val;
+	int mode;
+	int invert_enable;
+
+	ret = as3722_read(as3722, AS3722_GPIOn_CONTROL_REG(offset), &control);
+	if (ret < 0) {
+		dev_err(as_pci->dev,
+			"GPIO_CONTROL%d_REG read failed: %d\n", offset, ret);
+		return ret;
+	}
+
+	invert_enable = !!(control & AS3722_GPIO_INV);
+	mode = control & AS3722_GPIO_MODE_MASK;
+	switch (mode) {
+	case AS3722_GPIO_MODE_INPUT:
+	case AS3722_GPIO_MODE_INPUT_PULL_UP:
+	case AS3722_GPIO_MODE_INPUT_PULL_DOWN:
+	case AS3722_GPIO_MODE_IO_OPEN_DRAIN:
+	case AS3722_GPIO_MODE_IO_OPEN_DRAIN_PULL_UP:
+		reg = AS3722_GPIO_SIGNAL_IN_REG;
+		break;
+	case AS3722_GPIO_MODE_OUTPUT_VDDH:
+	case AS3722_GPIO_MODE_OUTPUT_VDDL:
+		reg = AS3722_GPIO_SIGNAL_OUT_REG;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = as3722_read(as3722, reg, &val);
+	if (ret < 0) {
+		dev_err(as_pci->dev,
+			"GPIO_SIGNAL_IN_REG read failed: %d\n", ret);
+		return ret;
+	}
+
+	val = !!(val & AS3722_GPIOn_SIGNAL(offset));
+	return (invert_enable) ? !val : val;
+}
+
+static void as3722_gpio_set(struct gpio_chip *chip, unsigned offset,
+		int value)
+{
+	struct as3722_pctrl_info *as_pci = to_as_pci(chip);
+	struct as3722 *as3722 = as_pci->as3722;
+	int en_invert = as_pci->gpio_control[offset].enable_gpio_invert;
+	u32 val;
+	int ret;
+
+	if (value)
+		val = (en_invert) ? 0 : AS3722_GPIOn_SIGNAL(offset);
+	else
+		val = (en_invert) ? AS3722_GPIOn_SIGNAL(offset) : 0;
+
+	ret = as3722_update_bits(as3722, AS3722_GPIO_SIGNAL_OUT_REG,
+			AS3722_GPIOn_SIGNAL(offset), val);
+	if (ret < 0)
+		dev_err(as_pci->dev,
+			"GPIO_SIGNAL_OUT_REG update failed: %d\n", ret);
+}
+
+static int as3722_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	return pinctrl_gpio_direction_input(chip->base + offset);
+}
+
+static int as3722_gpio_direction_output(struct gpio_chip *chip,
+		unsigned offset, int value)
+{
+	as3722_gpio_set(chip, offset, value);
+	return pinctrl_gpio_direction_output(chip->base + offset);
+}
+
+static int as3722_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct as3722_pctrl_info *as_pci = to_as_pci(chip);
+
+	return as3722_irq_get_virq(as_pci->as3722, offset);
+}
+
+static int as3722_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void as3722_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	pinctrl_free_gpio(chip->base + offset);
+}
+
+static const struct gpio_chip as3722_gpio_chip = {
+	.label			= "as3722-gpio",
+	.owner			= THIS_MODULE,
+	.request		= as3722_gpio_request,
+	.free			= as3722_gpio_free,
+	.get			= as3722_gpio_get,
+	.set			= as3722_gpio_set,
+	.direction_input	= as3722_gpio_direction_input,
+	.direction_output	= as3722_gpio_direction_output,
+	.to_irq			= as3722_gpio_to_irq,
+	.can_sleep		= 1,
+	.ngpio			= AS3722_PIN_NUM,
+	.base			= -1,
+};
+
+static int as3722_pinctrl_probe(struct platform_device *pdev)
+{
+	struct as3722_pctrl_info *as_pci;
+	int ret;
+	int tret;
+
+	as_pci = devm_kzalloc(&pdev->dev, sizeof(*as_pci), GFP_KERNEL);
+	if (!as_pci)
+		return -ENOMEM;
+
+	as_pci->dev = &pdev->dev;
+	as_pci->dev->of_node = pdev->dev.parent->of_node;
+	as_pci->as3722 = dev_get_drvdata(pdev->dev.parent);
+	platform_set_drvdata(pdev, as_pci);
+
+	as_pci->pins = as3722_pins_desc;
+	as_pci->num_pins = ARRAY_SIZE(as3722_pins_desc);
+	as_pci->functions = as3722_pin_function;
+	as_pci->num_functions = ARRAY_SIZE(as3722_pin_function);
+	as_pci->pin_groups = as3722_pingroups;
+	as_pci->num_pin_groups = ARRAY_SIZE(as3722_pingroups);
+	as3722_pinctrl_desc.name = dev_name(&pdev->dev);
+	as3722_pinctrl_desc.pins = as3722_pins_desc;
+	as3722_pinctrl_desc.npins = ARRAY_SIZE(as3722_pins_desc);
+	as_pci->pctl = pinctrl_register(&as3722_pinctrl_desc,
+					&pdev->dev, as_pci);
+	if (!as_pci->pctl) {
+		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
+		return -EINVAL;
+	}
+
+	as_pci->gpio_chip = as3722_gpio_chip;
+	as_pci->gpio_chip.dev = &pdev->dev;
+	as_pci->gpio_chip.of_node = pdev->dev.parent->of_node;
+	ret = gpiochip_add(&as_pci->gpio_chip);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Couldn't register gpiochip, %d\n", ret);
+		goto fail_chip_add;
+	}
+
+	ret = gpiochip_add_pin_range(&as_pci->gpio_chip, dev_name(&pdev->dev),
+				0, 0, AS3722_PIN_NUM);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Couldn't add pin range, %d\n", ret);
+		goto fail_range_add;
+	}
+
+	return 0;
+
+fail_range_add:
+	tret = gpiochip_remove(&as_pci->gpio_chip);
+	if (tret < 0)
+		dev_warn(&pdev->dev, "Couldn't remove gpio chip, %d\n", tret);
+
+fail_chip_add:
+	pinctrl_unregister(as_pci->pctl);
+	return ret;
+}
+
+static int as3722_pinctrl_remove(struct platform_device *pdev)
+{
+	struct as3722_pctrl_info *as_pci = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = gpiochip_remove(&as_pci->gpio_chip);
+	if (ret < 0)
+		return ret;
+	pinctrl_unregister(as_pci->pctl);
+	return 0;
+}
+
+static struct of_device_id as3722_pinctrl_of_match[] = {
+	{ .compatible = "ams,as3722-pinctrl", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, as3722_pinctrl_of_match);
+
+static struct platform_driver as3722_pinctrl_driver = {
+	.driver = {
+		.name = "as3722-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = as3722_pinctrl_of_match,
+	},
+	.probe = as3722_pinctrl_probe,
+	.remove = as3722_pinctrl_remove,
+};
+module_platform_driver(as3722_pinctrl_driver);
+
+MODULE_ALIAS("platform:as3722-pinctrl");
+MODULE_DESCRIPTION("AS3722 pin control and GPIO driver");
+MODULE_AUTHOR("Laxman Dewangan<ldewangan@nvidia.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index f350fd2..a7549c4 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -33,6 +33,7 @@
 
 #include "core.h"
 
+#define MAX_GPIO_BANKS		5
 #define MAX_NB_GPIO_PER_BANK	32
 
 struct at91_pinctrl_mux_ops;
@@ -144,11 +145,11 @@
 	void (*mux_C_periph)(void __iomem *pio, unsigned mask);
 	void (*mux_D_periph)(void __iomem *pio, unsigned mask);
 	bool (*get_deglitch)(void __iomem *pio, unsigned pin);
-	void (*set_deglitch)(void __iomem *pio, unsigned mask, bool in_on);
+	void (*set_deglitch)(void __iomem *pio, unsigned mask, bool is_on);
 	bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div);
-	void (*set_debounce)(void __iomem *pio, unsigned mask, bool in_on, u32 div);
+	void (*set_debounce)(void __iomem *pio, unsigned mask, bool is_on, u32 div);
 	bool (*get_pulldown)(void __iomem *pio, unsigned pin);
-	void (*set_pulldown)(void __iomem *pio, unsigned mask, bool in_on);
+	void (*set_pulldown)(void __iomem *pio, unsigned mask, bool is_on);
 	bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin);
 	void (*disable_schmitt_trig)(void __iomem *pio, unsigned mask);
 	/* irq */
@@ -243,7 +244,7 @@
 	int i;
 
 	/*
-	 * first find the group of this node and check if we need create
+	 * first find the group of this node and check if we need to create
 	 * config maps for pins
 	 */
 	grp = at91_pinctrl_find_group_by_name(info, np->name);
@@ -417,6 +418,14 @@
 	__raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR));
 }
 
+static bool at91_mux_pio3_get_deglitch(void __iomem *pio, unsigned pin)
+{
+	if ((__raw_readl(pio + PIO_IFSR) >> pin) & 0x1)
+		return !((__raw_readl(pio + PIO_IFSCSR) >> pin) & 0x1);
+
+	return false;
+}
+
 static void at91_mux_pio3_set_deglitch(void __iomem *pio, unsigned mask, bool is_on)
 {
 	if (is_on)
@@ -428,7 +437,8 @@
 {
 	*div = __raw_readl(pio + PIO_SCDR);
 
-	return (__raw_readl(pio + PIO_IFSCSR) >> pin) & 0x1;
+	return ((__raw_readl(pio + PIO_IFSR) >> pin) & 0x1) &&
+	       ((__raw_readl(pio + PIO_IFSCSR) >> pin) & 0x1);
 }
 
 static void at91_mux_pio3_set_debounce(void __iomem *pio, unsigned mask,
@@ -438,9 +448,8 @@
 		__raw_writel(mask, pio + PIO_IFSCER);
 		__raw_writel(div & PIO_SCDR_DIV, pio + PIO_SCDR);
 		__raw_writel(mask, pio + PIO_IFER);
-	} else {
-		__raw_writel(mask, pio + PIO_IFDR);
-	}
+	} else
+		__raw_writel(mask, pio + PIO_IFSCDR);
 }
 
 static bool at91_mux_pio3_get_pulldown(void __iomem *pio, unsigned pin)
@@ -478,7 +487,7 @@
 	.mux_B_periph	= at91_mux_pio3_set_B_periph,
 	.mux_C_periph	= at91_mux_pio3_set_C_periph,
 	.mux_D_periph	= at91_mux_pio3_set_D_periph,
-	.get_deglitch	= at91_mux_get_deglitch,
+	.get_deglitch	= at91_mux_pio3_get_deglitch,
 	.set_deglitch	= at91_mux_pio3_set_deglitch,
 	.get_debounce	= at91_mux_pio3_get_debounce,
 	.set_debounce	= at91_mux_pio3_set_debounce,
@@ -564,7 +573,7 @@
 		info->functions[selector].name, info->groups[group].name);
 
 	/* first check that all the pins of the group are valid with a valid
-	 * paramter */
+	 * parameter */
 	for (i = 0; i < npins; i++) {
 		pin = &pins_conf[i];
 		ret = pin_check_config(info, info->groups[group].name, i, pin);
@@ -958,7 +967,7 @@
 	at91_pinctrl_child_count(info, np);
 
 	if (info->nbanks < 1) {
-		dev_err(&pdev->dev, "you need to specify atleast one gpio-controller\n");
+		dev_err(&pdev->dev, "you need to specify at least one gpio-controller\n");
 		return -EINVAL;
 	}
 
@@ -1495,7 +1504,7 @@
 	if (at91_gpio->pioc_idx)
 		prev = gpio_chips[at91_gpio->pioc_idx - 1];
 
-	/* The toplevel handler handles one bank of GPIOs, except
+	/* The top level handler handles one bank of GPIOs, except
 	 * on some SoC it can handles up to three...
 	 * We only set up the handler for the first of the list.
 	 */
@@ -1671,7 +1680,7 @@
 	.driver = {
 		.name = "gpio-at91",
 		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(at91_gpio_of_match),
+		.of_match_table = at91_gpio_of_match,
 	},
 	.probe = at91_gpio_probe,
 };
@@ -1680,7 +1689,7 @@
 	.driver = {
 		.name = "pinctrl-at91",
 		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(at91_pinctrl_of_match),
+		.of_match_table = at91_pinctrl_of_match,
 	},
 	.probe = at91_pinctrl_probe,
 	.remove = at91_pinctrl_remove,
diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c
index f22a219..162ac0d 100644
--- a/drivers/pinctrl/pinctrl-coh901.c
+++ b/drivers/pinctrl/pinctrl-coh901.c
@@ -529,6 +529,10 @@
 
 	dev_dbg(gpio->dev, "enable IRQ for hwirq %lu on port %s, offset %d\n",
 		 d->hwirq, port->name, offset);
+	if (gpio_lock_as_irq(&gpio->chip, d->hwirq))
+		dev_err(gpio->dev,
+			"unable to lock HW IRQ %lu for IRQ\n",
+			d->hwirq);
 	local_irq_save(flags);
 	val = readl(U300_PIN_REG(offset, ien));
 	writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, ien));
@@ -547,6 +551,7 @@
 	val = readl(U300_PIN_REG(offset, ien));
 	writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, ien));
 	local_irq_restore(flags);
+	gpio_unlock_as_irq(&gpio->chip, d->hwirq);
 }
 
 static struct irq_chip u300_gpio_irqchip = {
diff --git a/drivers/pinctrl/pinctrl-exynos5440.c b/drivers/pinctrl/pinctrl-exynos5440.c
index 544d469..8fe2ab0 100644
--- a/drivers/pinctrl/pinctrl-exynos5440.c
+++ b/drivers/pinctrl/pinctrl-exynos5440.c
@@ -1048,7 +1048,7 @@
 	.driver = {
 		.name	= "exynos5440-pinctrl",
 		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(exynos5440_pinctrl_dt_match),
+		.of_match_table = exynos5440_pinctrl_dt_match,
 	},
 };
 
diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c
index d78dd81..4779b8e 100644
--- a/drivers/pinctrl/pinctrl-imx.c
+++ b/drivers/pinctrl/pinctrl-imx.c
@@ -245,11 +245,11 @@
 			 * The input_reg[i] here is actually some IOMUXC general
 			 * purpose register, not regular select input register.
 			 */
-			val = readl(ipctl->base + pin->input_val);
+			val = readl(ipctl->base + pin->input_reg);
 			val &= ~mask;
 			val |= select << shift;
-			writel(val, ipctl->base + pin->input_val);
-		} else if (pin->input_val) {
+			writel(val, ipctl->base + pin->input_reg);
+		} else if (pin->input_reg) {
 			/*
 			 * Regular select input register can never be at offset
 			 * 0, and we only print register value for regular case.
diff --git a/drivers/pinctrl/pinctrl-imx1-core.c b/drivers/pinctrl/pinctrl-imx1-core.c
new file mode 100644
index 0000000..f77914a
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-imx1-core.c
@@ -0,0 +1,653 @@
+/*
+ * Core driver for the imx pin controller in imx1/21/27
+ *
+ * Copyright (C) 2013 Pengutronix
+ * Author: Markus Pargmann <mpa@pengutronix.de>
+ *
+ * Based on pinctrl-imx.c:
+ *	Author: Dong Aisheng <dong.aisheng@linaro.org>
+ *	Copyright (C) 2012 Freescale Semiconductor, Inc.
+ *	Copyright (C) 2012 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/slab.h>
+
+#include "core.h"
+#include "pinctrl-imx1.h"
+
+struct imx1_pinctrl {
+	struct device *dev;
+	struct pinctrl_dev *pctl;
+	void __iomem *base;
+	const struct imx1_pinctrl_soc_info *info;
+};
+
+/*
+ * MX1 register offsets
+ */
+
+#define MX1_DDIR 0x00
+#define MX1_OCR 0x04
+#define MX1_ICONFA 0x0c
+#define MX1_ICONFB 0x10
+#define MX1_GIUS 0x20
+#define MX1_GPR 0x38
+#define MX1_PUEN 0x40
+
+#define MX1_PORT_STRIDE 0x100
+
+
+/*
+ * MUX_ID format defines
+ */
+#define MX1_MUX_FUNCTION(val) (BIT(0) & val)
+#define MX1_MUX_GPIO(val) ((BIT(1) & val) >> 1)
+#define MX1_MUX_DIR(val) ((BIT(2) & val) >> 2)
+#define MX1_MUX_OCONF(val) (((BIT(4) | BIT(5)) & val) >> 4)
+#define MX1_MUX_ICONFA(val) (((BIT(8) | BIT(9)) & val) >> 8)
+#define MX1_MUX_ICONFB(val) (((BIT(10) | BIT(11)) & val) >> 10)
+
+
+/*
+ * IMX1 IOMUXC manages the pins based on ports. Each port has 32 pins. IOMUX
+ * control register are seperated into function, output configuration, input
+ * configuration A, input configuration B, GPIO in use and data direction.
+ *
+ * Those controls that are represented by 1 bit have a direct mapping between
+ * bit position and pin id. If they are represented by 2 bit, the lower 16 pins
+ * are in the first register and the upper 16 pins in the second (next)
+ * register. pin_id is stored in bit (pin_id%16)*2 and the bit above.
+ */
+
+/*
+ * Calculates the register offset from a pin_id
+ */
+static void __iomem *imx1_mem(struct imx1_pinctrl *ipctl, unsigned int pin_id)
+{
+	unsigned int port = pin_id / 32;
+	return ipctl->base + port * MX1_PORT_STRIDE;
+}
+
+/*
+ * Write to a register with 2 bits per pin. The function will automatically
+ * use the next register if the pin is managed in the second register.
+ */
+static void imx1_write_2bit(struct imx1_pinctrl *ipctl, unsigned int pin_id,
+		u32 value, u32 reg_offset)
+{
+	void __iomem *reg = imx1_mem(ipctl, pin_id) + reg_offset;
+	int offset = (pin_id % 16) * 2; /* offset, regardless of register used */
+	int mask = ~(0x3 << offset); /* Mask for 2 bits at offset */
+	u32 old_val;
+	u32 new_val;
+
+	dev_dbg(ipctl->dev, "write: register 0x%p offset %d value 0x%x\n",
+			reg, offset, value);
+
+	/* Use the next register if the pin's port pin number is >=16 */
+	if (pin_id % 32 >= 16)
+		reg += 0x04;
+
+	/* Get current state of pins */
+	old_val = readl(reg);
+	old_val &= mask;
+
+	new_val = value & 0x3; /* Make sure value is really 2 bit */
+	new_val <<= offset;
+	new_val |= old_val;/* Set new state for pin_id */
+
+	writel(new_val, reg);
+}
+
+static void imx1_write_bit(struct imx1_pinctrl *ipctl, unsigned int pin_id,
+		u32 value, u32 reg_offset)
+{
+	void __iomem *reg = imx1_mem(ipctl, pin_id) + reg_offset;
+	int offset = pin_id % 32;
+	int mask = ~BIT_MASK(offset);
+	u32 old_val;
+	u32 new_val;
+
+	/* Get current state of pins */
+	old_val = readl(reg);
+	old_val &= mask;
+
+	new_val = value & 0x1; /* Make sure value is really 1 bit */
+	new_val <<= offset;
+	new_val |= old_val;/* Set new state for pin_id */
+
+	writel(new_val, reg);
+}
+
+static int imx1_read_2bit(struct imx1_pinctrl *ipctl, unsigned int pin_id,
+		u32 reg_offset)
+{
+	void __iomem *reg = imx1_mem(ipctl, pin_id) + reg_offset;
+	int offset = pin_id % 16;
+
+	/* Use the next register if the pin's port pin number is >=16 */
+	if (pin_id % 32 >= 16)
+		reg += 0x04;
+
+	return (readl(reg) & (BIT(offset) | BIT(offset+1))) >> offset;
+}
+
+static int imx1_read_bit(struct imx1_pinctrl *ipctl, unsigned int pin_id,
+		u32 reg_offset)
+{
+	void __iomem *reg = imx1_mem(ipctl, pin_id) + reg_offset;
+	int offset = pin_id % 32;
+
+	return !!(readl(reg) & BIT(offset));
+}
+
+static const inline struct imx1_pin_group *imx1_pinctrl_find_group_by_name(
+				const struct imx1_pinctrl_soc_info *info,
+				const char *name)
+{
+	const struct imx1_pin_group *grp = NULL;
+	int i;
+
+	for (i = 0; i < info->ngroups; i++) {
+		if (!strcmp(info->groups[i].name, name)) {
+			grp = &info->groups[i];
+			break;
+		}
+	}
+
+	return grp;
+}
+
+static int imx1_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+	const struct imx1_pinctrl_soc_info *info = ipctl->info;
+
+	return info->ngroups;
+}
+
+static const char *imx1_get_group_name(struct pinctrl_dev *pctldev,
+				       unsigned selector)
+{
+	struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+	const struct imx1_pinctrl_soc_info *info = ipctl->info;
+
+	return info->groups[selector].name;
+}
+
+static int imx1_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+			       const unsigned int **pins,
+			       unsigned *npins)
+{
+	struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+	const struct imx1_pinctrl_soc_info *info = ipctl->info;
+
+	if (selector >= info->ngroups)
+		return -EINVAL;
+
+	*pins = info->groups[selector].pin_ids;
+	*npins = info->groups[selector].npins;
+
+	return 0;
+}
+
+static void imx1_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+		   unsigned offset)
+{
+	struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+
+	seq_printf(s, "GPIO %d, function %d, direction %d, oconf %d, iconfa %d, iconfb %d",
+			imx1_read_bit(ipctl, offset, MX1_GIUS),
+			imx1_read_bit(ipctl, offset, MX1_GPR),
+			imx1_read_bit(ipctl, offset, MX1_DDIR),
+			imx1_read_2bit(ipctl, offset, MX1_OCR),
+			imx1_read_2bit(ipctl, offset, MX1_ICONFA),
+			imx1_read_2bit(ipctl, offset, MX1_ICONFB));
+}
+
+static int imx1_dt_node_to_map(struct pinctrl_dev *pctldev,
+			struct device_node *np,
+			struct pinctrl_map **map, unsigned *num_maps)
+{
+	struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+	const struct imx1_pinctrl_soc_info *info = ipctl->info;
+	const struct imx1_pin_group *grp;
+	struct pinctrl_map *new_map;
+	struct device_node *parent;
+	int map_num = 1;
+	int i, j;
+
+	/*
+	 * first find the group of this node and check if we need create
+	 * config maps for pins
+	 */
+	grp = imx1_pinctrl_find_group_by_name(info, np->name);
+	if (!grp) {
+		dev_err(info->dev, "unable to find group for node %s\n",
+			np->name);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < grp->npins; i++)
+		map_num++;
+
+	new_map = kmalloc(sizeof(struct pinctrl_map) * map_num, GFP_KERNEL);
+	if (!new_map)
+		return -ENOMEM;
+
+	*map = new_map;
+	*num_maps = map_num;
+
+	/* create mux map */
+	parent = of_get_parent(np);
+	if (!parent) {
+		kfree(new_map);
+		return -EINVAL;
+	}
+	new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
+	new_map[0].data.mux.function = parent->name;
+	new_map[0].data.mux.group = np->name;
+	of_node_put(parent);
+
+	/* create config map */
+	new_map++;
+	for (i = j = 0; i < grp->npins; i++) {
+		new_map[j].type = PIN_MAP_TYPE_CONFIGS_PIN;
+		new_map[j].data.configs.group_or_pin =
+				pin_get_name(pctldev, grp->pins[i].pin_id);
+		new_map[j].data.configs.configs = &grp->pins[i].config;
+		new_map[j].data.configs.num_configs = 1;
+		j++;
+	}
+
+	dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
+		(*map)->data.mux.function, (*map)->data.mux.group, map_num);
+
+	return 0;
+}
+
+static void imx1_dt_free_map(struct pinctrl_dev *pctldev,
+				struct pinctrl_map *map, unsigned num_maps)
+{
+	kfree(map);
+}
+
+static const struct pinctrl_ops imx1_pctrl_ops = {
+	.get_groups_count = imx1_get_groups_count,
+	.get_group_name = imx1_get_group_name,
+	.get_group_pins = imx1_get_group_pins,
+	.pin_dbg_show = imx1_pin_dbg_show,
+	.dt_node_to_map = imx1_dt_node_to_map,
+	.dt_free_map = imx1_dt_free_map,
+
+};
+
+static int imx1_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
+			   unsigned group)
+{
+	struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+	const struct imx1_pinctrl_soc_info *info = ipctl->info;
+	const struct imx1_pin *pins;
+	unsigned int npins;
+	int i;
+
+	/*
+	 * Configure the mux mode for each pin in the group for a specific
+	 * function.
+	 */
+	pins = info->groups[group].pins;
+	npins = info->groups[group].npins;
+
+	WARN_ON(!pins || !npins);
+
+	dev_dbg(ipctl->dev, "enable function %s group %s\n",
+		info->functions[selector].name, info->groups[group].name);
+
+	for (i = 0; i < npins; i++) {
+		unsigned int mux = pins[i].mux_id;
+		unsigned int pin_id = pins[i].pin_id;
+		unsigned int afunction = MX1_MUX_FUNCTION(mux);
+		unsigned int gpio_in_use = MX1_MUX_GPIO(mux);
+		unsigned int direction = MX1_MUX_DIR(mux);
+		unsigned int gpio_oconf = MX1_MUX_OCONF(mux);
+		unsigned int gpio_iconfa = MX1_MUX_ICONFA(mux);
+		unsigned int gpio_iconfb = MX1_MUX_ICONFB(mux);
+
+		dev_dbg(pctldev->dev, "%s, pin 0x%x, function %d, gpio %d, direction %d, oconf %d, iconfa %d, iconfb %d\n",
+				__func__, pin_id, afunction, gpio_in_use,
+				direction, gpio_oconf, gpio_iconfa,
+				gpio_iconfb);
+
+		imx1_write_bit(ipctl, pin_id, gpio_in_use, MX1_GIUS);
+		imx1_write_bit(ipctl, pin_id, direction, MX1_DDIR);
+
+		if (gpio_in_use) {
+			imx1_write_2bit(ipctl, pin_id, gpio_oconf, MX1_OCR);
+			imx1_write_2bit(ipctl, pin_id, gpio_iconfa,
+					MX1_ICONFA);
+			imx1_write_2bit(ipctl, pin_id, gpio_iconfb,
+					MX1_ICONFB);
+		} else {
+			imx1_write_bit(ipctl, pin_id, afunction, MX1_GPR);
+		}
+	}
+
+	return 0;
+}
+
+static int imx1_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+	struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+	const struct imx1_pinctrl_soc_info *info = ipctl->info;
+
+	return info->nfunctions;
+}
+
+static const char *imx1_pmx_get_func_name(struct pinctrl_dev *pctldev,
+					  unsigned selector)
+{
+	struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+	const struct imx1_pinctrl_soc_info *info = ipctl->info;
+
+	return info->functions[selector].name;
+}
+
+static int imx1_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
+			       const char * const **groups,
+			       unsigned * const num_groups)
+{
+	struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+	const struct imx1_pinctrl_soc_info *info = ipctl->info;
+
+	*groups = info->functions[selector].groups;
+	*num_groups = info->functions[selector].num_groups;
+
+	return 0;
+}
+
+static const struct pinmux_ops imx1_pmx_ops = {
+	.get_functions_count = imx1_pmx_get_funcs_count,
+	.get_function_name = imx1_pmx_get_func_name,
+	.get_function_groups = imx1_pmx_get_groups,
+	.enable = imx1_pmx_enable,
+};
+
+static int imx1_pinconf_get(struct pinctrl_dev *pctldev,
+			     unsigned pin_id, unsigned long *config)
+{
+	struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+
+	*config = imx1_read_bit(ipctl, pin_id, MX1_PUEN);
+
+	return 0;
+}
+
+static int imx1_pinconf_set(struct pinctrl_dev *pctldev,
+			     unsigned pin_id, unsigned long *configs,
+			     unsigned num_configs)
+{
+	struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+	const struct imx1_pinctrl_soc_info *info = ipctl->info;
+	int i;
+
+	for (i = 0; i != num_configs; ++i) {
+		imx1_write_bit(ipctl, pin_id, configs[i] & 0x01, MX1_PUEN);
+
+		dev_dbg(ipctl->dev, "pinconf set pullup pin %s\n",
+			info->pins[pin_id].name);
+	}
+
+	return 0;
+}
+
+static void imx1_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+				   struct seq_file *s, unsigned pin_id)
+{
+	unsigned long config;
+
+	imx1_pinconf_get(pctldev, pin_id, &config);
+	seq_printf(s, "0x%lx", config);
+}
+
+static void imx1_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+					 struct seq_file *s, unsigned group)
+{
+	struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+	const struct imx1_pinctrl_soc_info *info = ipctl->info;
+	struct imx1_pin_group *grp;
+	unsigned long config;
+	const char *name;
+	int i, ret;
+
+	if (group > info->ngroups)
+		return;
+
+	seq_puts(s, "\n");
+	grp = &info->groups[group];
+	for (i = 0; i < grp->npins; i++) {
+		name = pin_get_name(pctldev, grp->pins[i].pin_id);
+		ret = imx1_pinconf_get(pctldev, grp->pins[i].pin_id, &config);
+		if (ret)
+			return;
+		seq_printf(s, "%s: 0x%lx", name, config);
+	}
+}
+
+static const struct pinconf_ops imx1_pinconf_ops = {
+	.pin_config_get = imx1_pinconf_get,
+	.pin_config_set = imx1_pinconf_set,
+	.pin_config_dbg_show = imx1_pinconf_dbg_show,
+	.pin_config_group_dbg_show = imx1_pinconf_group_dbg_show,
+};
+
+static struct pinctrl_desc imx1_pinctrl_desc = {
+	.pctlops = &imx1_pctrl_ops,
+	.pmxops = &imx1_pmx_ops,
+	.confops = &imx1_pinconf_ops,
+	.owner = THIS_MODULE,
+};
+
+static int imx1_pinctrl_parse_groups(struct device_node *np,
+				    struct imx1_pin_group *grp,
+				    struct imx1_pinctrl_soc_info *info,
+				    u32 index)
+{
+	int size;
+	const __be32 *list;
+	int i;
+
+	dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
+
+	/* Initialise group */
+	grp->name = np->name;
+
+	/*
+	 * the binding format is fsl,pins = <PIN MUX_ID CONFIG>
+	 */
+	list = of_get_property(np, "fsl,pins", &size);
+	/* we do not check return since it's safe node passed down */
+	if (!size || size % 12) {
+		dev_notice(info->dev, "Not a valid fsl,pins property (%s)\n",
+				np->name);
+		return -EINVAL;
+	}
+
+	grp->npins = size / 12;
+	grp->pins = devm_kzalloc(info->dev,
+			grp->npins * sizeof(struct imx1_pin), GFP_KERNEL);
+	grp->pin_ids = devm_kzalloc(info->dev,
+			grp->npins * sizeof(unsigned int), GFP_KERNEL);
+
+	if (!grp->pins || !grp->pin_ids)
+		return -ENOMEM;
+
+	for (i = 0; i < grp->npins; i++) {
+		grp->pins[i].pin_id = be32_to_cpu(*list++);
+		grp->pins[i].mux_id = be32_to_cpu(*list++);
+		grp->pins[i].config = be32_to_cpu(*list++);
+
+		grp->pin_ids[i] = grp->pins[i].pin_id;
+	}
+
+	return 0;
+}
+
+static int imx1_pinctrl_parse_functions(struct device_node *np,
+				       struct imx1_pinctrl_soc_info *info,
+				       u32 index)
+{
+	struct device_node *child;
+	struct imx1_pmx_func *func;
+	struct imx1_pin_group *grp;
+	int ret;
+	static u32 grp_index;
+	u32 i = 0;
+
+	dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
+
+	func = &info->functions[index];
+
+	/* Initialise function */
+	func->name = np->name;
+	func->num_groups = of_get_child_count(np);
+	if (func->num_groups <= 0)
+		return -EINVAL;
+
+	func->groups = devm_kzalloc(info->dev,
+			func->num_groups * sizeof(char *), GFP_KERNEL);
+
+	if (!func->groups)
+		return -ENOMEM;
+
+	for_each_child_of_node(np, child) {
+		func->groups[i] = child->name;
+		grp = &info->groups[grp_index++];
+		ret = imx1_pinctrl_parse_groups(child, grp, info, i++);
+		if (ret == -ENOMEM)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int imx1_pinctrl_parse_dt(struct platform_device *pdev,
+		struct imx1_pinctrl *pctl, struct imx1_pinctrl_soc_info *info)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *child;
+	int ret;
+	u32 nfuncs = 0;
+	u32 ngroups = 0;
+	u32 ifunc = 0;
+
+	if (!np)
+		return -ENODEV;
+
+	for_each_child_of_node(np, child) {
+		++nfuncs;
+		ngroups += of_get_child_count(child);
+	}
+
+	if (!nfuncs) {
+		dev_err(&pdev->dev, "No pin functions defined\n");
+		return -EINVAL;
+	}
+
+	info->nfunctions = nfuncs;
+	info->functions = devm_kzalloc(&pdev->dev,
+			nfuncs * sizeof(struct imx1_pmx_func), GFP_KERNEL);
+
+	info->ngroups = ngroups;
+	info->groups = devm_kzalloc(&pdev->dev,
+			ngroups * sizeof(struct imx1_pin_group), GFP_KERNEL);
+
+
+	if (!info->functions || !info->groups)
+		return -ENOMEM;
+
+	for_each_child_of_node(np, child) {
+		ret = imx1_pinctrl_parse_functions(child, info, ifunc++);
+		if (ret == -ENOMEM)
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+
+int imx1_pinctrl_core_probe(struct platform_device *pdev,
+		      struct imx1_pinctrl_soc_info *info)
+{
+	struct imx1_pinctrl *ipctl;
+	struct resource *res;
+	struct pinctrl_desc *pctl_desc;
+	int ret;
+
+	if (!info || !info->pins || !info->npins) {
+		dev_err(&pdev->dev, "wrong pinctrl info\n");
+		return -EINVAL;
+	}
+	info->dev = &pdev->dev;
+
+	/* Create state holders etc for this driver */
+	ipctl = devm_kzalloc(&pdev->dev, sizeof(*ipctl), GFP_KERNEL);
+	if (!ipctl)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENOENT;
+
+	ipctl->base = devm_ioremap_nocache(&pdev->dev, res->start,
+			resource_size(res));
+	if (!ipctl->base)
+		return -ENOMEM;
+
+	pctl_desc = &imx1_pinctrl_desc;
+	pctl_desc->name = dev_name(&pdev->dev);
+	pctl_desc->pins = info->pins;
+	pctl_desc->npins = info->npins;
+
+	ret = imx1_pinctrl_parse_dt(pdev, ipctl, info);
+	if (ret) {
+		dev_err(&pdev->dev, "fail to probe dt properties\n");
+		return ret;
+	}
+
+	ipctl->info = info;
+	ipctl->dev = info->dev;
+	platform_set_drvdata(pdev, ipctl);
+	ipctl->pctl = pinctrl_register(pctl_desc, &pdev->dev, ipctl);
+	if (!ipctl->pctl) {
+		dev_err(&pdev->dev, "could not register IMX pinctrl driver\n");
+		return -EINVAL;
+	}
+
+	dev_info(&pdev->dev, "initialized IMX pinctrl driver\n");
+
+	return 0;
+}
+
+int imx1_pinctrl_core_remove(struct platform_device *pdev)
+{
+	struct imx1_pinctrl *ipctl = platform_get_drvdata(pdev);
+
+	pinctrl_unregister(ipctl->pctl);
+
+	return 0;
+}
diff --git a/drivers/pinctrl/pinctrl-imx1.h b/drivers/pinctrl/pinctrl-imx1.h
new file mode 100644
index 0000000..692a54c
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-imx1.h
@@ -0,0 +1,73 @@
+/*
+ * IMX pinmux core definitions
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012 Linaro Ltd.
+ *
+ * Author: Dong Aisheng <dong.aisheng@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __DRIVERS_PINCTRL_IMX1_H
+#define __DRIVERS_PINCTRL_IMX1_H
+
+struct platform_device;
+
+/**
+ * struct imx1_pin - describes an IMX1/21/27 pin.
+ * @pin_id: ID of the described pin.
+ * @mux_id: ID of the mux setup.
+ * @config: Configuration of the pin (currently only pullup-enable).
+ */
+struct imx1_pin {
+	unsigned int pin_id;
+	unsigned int mux_id;
+	unsigned long config;
+};
+
+/**
+ * struct imx1_pin_group - describes an IMX pin group
+ * @name: the name of this specific pin group
+ * @pins: an array of imx1_pin structs used in this group
+ * @npins: the number of pins in this group array, i.e. the number of
+ *	elements in .pins so we can iterate over that array
+ */
+struct imx1_pin_group {
+	const char *name;
+	unsigned int *pin_ids;
+	struct imx1_pin *pins;
+	unsigned npins;
+};
+
+/**
+ * struct imx1_pmx_func - describes IMX pinmux functions
+ * @name: the name of this specific function
+ * @groups: corresponding pin groups
+ * @num_groups: the number of groups
+ */
+struct imx1_pmx_func {
+	const char *name;
+	const char **groups;
+	unsigned num_groups;
+};
+
+struct imx1_pinctrl_soc_info {
+	struct device *dev;
+	const struct pinctrl_pin_desc *pins;
+	unsigned int npins;
+	struct imx1_pin_group *groups;
+	unsigned int ngroups;
+	struct imx1_pmx_func *functions;
+	unsigned int nfunctions;
+};
+
+#define IMX_PINCTRL_PIN(pin) PINCTRL_PIN(pin, #pin)
+
+int imx1_pinctrl_core_probe(struct platform_device *pdev,
+			struct imx1_pinctrl_soc_info *info);
+int imx1_pinctrl_core_remove(struct platform_device *pdev);
+#endif /* __DRIVERS_PINCTRL_IMX1_H */
diff --git a/drivers/pinctrl/pinctrl-imx27.c b/drivers/pinctrl/pinctrl-imx27.c
new file mode 100644
index 0000000..417c992
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-imx27.c
@@ -0,0 +1,477 @@
+/*
+ * imx27 pinctrl driver based on imx pinmux core
+ *
+ * Copyright (C) 2013 Pengutronix
+ *
+ * Author: Markus Pargmann <mpa@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-imx1.h"
+
+#define PAD_ID(port, pin) (port*32 + pin)
+#define PA 0
+#define PB 1
+#define PC 2
+#define PD 3
+#define PE 4
+#define PF 5
+
+enum imx27_pads {
+	MX27_PAD_USBH2_CLK = PAD_ID(PA, 0),
+	MX27_PAD_USBH2_DIR = PAD_ID(PA, 1),
+	MX27_PAD_USBH2_DATA7 = PAD_ID(PA, 2),
+	MX27_PAD_USBH2_NXT = PAD_ID(PA, 3),
+	MX27_PAD_USBH2_STP = PAD_ID(PA, 4),
+	MX27_PAD_LSCLK = PAD_ID(PA, 5),
+	MX27_PAD_LD0 = PAD_ID(PA, 6),
+	MX27_PAD_LD1 = PAD_ID(PA, 7),
+	MX27_PAD_LD2 = PAD_ID(PA, 8),
+	MX27_PAD_LD3 = PAD_ID(PA, 9),
+	MX27_PAD_LD4 = PAD_ID(PA, 10),
+	MX27_PAD_LD5 = PAD_ID(PA, 11),
+	MX27_PAD_LD6 = PAD_ID(PA, 12),
+	MX27_PAD_LD7 = PAD_ID(PA, 13),
+	MX27_PAD_LD8 = PAD_ID(PA, 14),
+	MX27_PAD_LD9 = PAD_ID(PA, 15),
+	MX27_PAD_LD10 = PAD_ID(PA, 16),
+	MX27_PAD_LD11 = PAD_ID(PA, 17),
+	MX27_PAD_LD12 = PAD_ID(PA, 18),
+	MX27_PAD_LD13 = PAD_ID(PA, 19),
+	MX27_PAD_LD14 = PAD_ID(PA, 20),
+	MX27_PAD_LD15 = PAD_ID(PA, 21),
+	MX27_PAD_LD16 = PAD_ID(PA, 22),
+	MX27_PAD_LD17 = PAD_ID(PA, 23),
+	MX27_PAD_REV = PAD_ID(PA, 24),
+	MX27_PAD_CLS = PAD_ID(PA, 25),
+	MX27_PAD_PS = PAD_ID(PA, 26),
+	MX27_PAD_SPL_SPR = PAD_ID(PA, 27),
+	MX27_PAD_HSYNC = PAD_ID(PA, 28),
+	MX27_PAD_VSYNC = PAD_ID(PA, 29),
+	MX27_PAD_CONTRAST = PAD_ID(PA, 30),
+	MX27_PAD_OE_ACD = PAD_ID(PA, 31),
+
+	MX27_PAD_UNUSED0 = PAD_ID(PB, 0),
+	MX27_PAD_UNUSED1 = PAD_ID(PB, 1),
+	MX27_PAD_UNUSED2 = PAD_ID(PB, 2),
+	MX27_PAD_UNUSED3 = PAD_ID(PB, 3),
+	MX27_PAD_SD2_D0 = PAD_ID(PB, 4),
+	MX27_PAD_SD2_D1 = PAD_ID(PB, 5),
+	MX27_PAD_SD2_D2 = PAD_ID(PB, 6),
+	MX27_PAD_SD2_D3 = PAD_ID(PB, 7),
+	MX27_PAD_SD2_CMD = PAD_ID(PB, 8),
+	MX27_PAD_SD2_CLK = PAD_ID(PB, 9),
+	MX27_PAD_CSI_D0 = PAD_ID(PB, 10),
+	MX27_PAD_CSI_D1 = PAD_ID(PB, 11),
+	MX27_PAD_CSI_D2 = PAD_ID(PB, 12),
+	MX27_PAD_CSI_D3 = PAD_ID(PB, 13),
+	MX27_PAD_CSI_D4 = PAD_ID(PB, 14),
+	MX27_PAD_CSI_MCLK = PAD_ID(PB, 15),
+	MX27_PAD_CSI_PIXCLK = PAD_ID(PB, 16),
+	MX27_PAD_CSI_D5 = PAD_ID(PB, 17),
+	MX27_PAD_CSI_D6 = PAD_ID(PB, 18),
+	MX27_PAD_CSI_D7 = PAD_ID(PB, 19),
+	MX27_PAD_CSI_VSYNC = PAD_ID(PB, 20),
+	MX27_PAD_CSI_HSYNC = PAD_ID(PB, 21),
+	MX27_PAD_USBH1_SUSP = PAD_ID(PB, 22),
+	MX27_PAD_USB_PWR = PAD_ID(PB, 23),
+	MX27_PAD_USB_OC_B = PAD_ID(PB, 24),
+	MX27_PAD_USBH1_RCV = PAD_ID(PB, 25),
+	MX27_PAD_USBH1_FS = PAD_ID(PB, 26),
+	MX27_PAD_USBH1_OE_B = PAD_ID(PB, 27),
+	MX27_PAD_USBH1_TXDM = PAD_ID(PB, 28),
+	MX27_PAD_USBH1_TXDP = PAD_ID(PB, 29),
+	MX27_PAD_USBH1_RXDM = PAD_ID(PB, 30),
+	MX27_PAD_USBH1_RXDP = PAD_ID(PB, 31),
+
+	MX27_PAD_UNUSED4 = PAD_ID(PC, 0),
+	MX27_PAD_UNUSED5 = PAD_ID(PC, 1),
+	MX27_PAD_UNUSED6 = PAD_ID(PC, 2),
+	MX27_PAD_UNUSED7 = PAD_ID(PC, 3),
+	MX27_PAD_UNUSED8 = PAD_ID(PC, 4),
+	MX27_PAD_I2C2_SDA = PAD_ID(PC, 5),
+	MX27_PAD_I2C2_SCL = PAD_ID(PC, 6),
+	MX27_PAD_USBOTG_DATA5 = PAD_ID(PC, 7),
+	MX27_PAD_USBOTG_DATA6 = PAD_ID(PC, 8),
+	MX27_PAD_USBOTG_DATA0 = PAD_ID(PC, 9),
+	MX27_PAD_USBOTG_DATA2 = PAD_ID(PC, 10),
+	MX27_PAD_USBOTG_DATA1 = PAD_ID(PC, 11),
+	MX27_PAD_USBOTG_DATA4 = PAD_ID(PC, 12),
+	MX27_PAD_USBOTG_DATA3 = PAD_ID(PC, 13),
+	MX27_PAD_TOUT = PAD_ID(PC, 14),
+	MX27_PAD_TIN = PAD_ID(PC, 15),
+	MX27_PAD_SSI4_FS = PAD_ID(PC, 16),
+	MX27_PAD_SSI4_RXDAT = PAD_ID(PC, 17),
+	MX27_PAD_SSI4_TXDAT = PAD_ID(PC, 18),
+	MX27_PAD_SSI4_CLK = PAD_ID(PC, 19),
+	MX27_PAD_SSI1_FS = PAD_ID(PC, 20),
+	MX27_PAD_SSI1_RXDAT = PAD_ID(PC, 21),
+	MX27_PAD_SSI1_TXDAT = PAD_ID(PC, 22),
+	MX27_PAD_SSI1_CLK = PAD_ID(PC, 23),
+	MX27_PAD_SSI2_FS = PAD_ID(PC, 24),
+	MX27_PAD_SSI2_RXDAT = PAD_ID(PC, 25),
+	MX27_PAD_SSI2_TXDAT = PAD_ID(PC, 26),
+	MX27_PAD_SSI2_CLK = PAD_ID(PC, 27),
+	MX27_PAD_SSI3_FS = PAD_ID(PC, 28),
+	MX27_PAD_SSI3_RXDAT = PAD_ID(PC, 29),
+	MX27_PAD_SSI3_TXDAT = PAD_ID(PC, 30),
+	MX27_PAD_SSI3_CLK = PAD_ID(PC, 31),
+
+	MX27_PAD_SD3_CMD = PAD_ID(PD, 0),
+	MX27_PAD_SD3_CLK = PAD_ID(PD, 1),
+	MX27_PAD_ATA_DATA0 = PAD_ID(PD, 2),
+	MX27_PAD_ATA_DATA1 = PAD_ID(PD, 3),
+	MX27_PAD_ATA_DATA2 = PAD_ID(PD, 4),
+	MX27_PAD_ATA_DATA3 = PAD_ID(PD, 5),
+	MX27_PAD_ATA_DATA4 = PAD_ID(PD, 6),
+	MX27_PAD_ATA_DATA5 = PAD_ID(PD, 7),
+	MX27_PAD_ATA_DATA6 = PAD_ID(PD, 8),
+	MX27_PAD_ATA_DATA7 = PAD_ID(PD, 9),
+	MX27_PAD_ATA_DATA8 = PAD_ID(PD, 10),
+	MX27_PAD_ATA_DATA9 = PAD_ID(PD, 11),
+	MX27_PAD_ATA_DATA10 = PAD_ID(PD, 12),
+	MX27_PAD_ATA_DATA11 = PAD_ID(PD, 13),
+	MX27_PAD_ATA_DATA12 = PAD_ID(PD, 14),
+	MX27_PAD_ATA_DATA13 = PAD_ID(PD, 15),
+	MX27_PAD_ATA_DATA14 = PAD_ID(PD, 16),
+	MX27_PAD_I2C_DATA = PAD_ID(PD, 17),
+	MX27_PAD_I2C_CLK = PAD_ID(PD, 18),
+	MX27_PAD_CSPI2_SS2 = PAD_ID(PD, 19),
+	MX27_PAD_CSPI2_SS1 = PAD_ID(PD, 20),
+	MX27_PAD_CSPI2_SS0 = PAD_ID(PD, 21),
+	MX27_PAD_CSPI2_SCLK = PAD_ID(PD, 22),
+	MX27_PAD_CSPI2_MISO = PAD_ID(PD, 23),
+	MX27_PAD_CSPI2_MOSI = PAD_ID(PD, 24),
+	MX27_PAD_CSPI1_RDY = PAD_ID(PD, 25),
+	MX27_PAD_CSPI1_SS2 = PAD_ID(PD, 26),
+	MX27_PAD_CSPI1_SS1 = PAD_ID(PD, 27),
+	MX27_PAD_CSPI1_SS0 = PAD_ID(PD, 28),
+	MX27_PAD_CSPI1_SCLK = PAD_ID(PD, 29),
+	MX27_PAD_CSPI1_MISO = PAD_ID(PD, 30),
+	MX27_PAD_CSPI1_MOSI = PAD_ID(PD, 31),
+
+	MX27_PAD_USBOTG_NXT = PAD_ID(PE, 0),
+	MX27_PAD_USBOTG_STP = PAD_ID(PE, 1),
+	MX27_PAD_USBOTG_DIR = PAD_ID(PE, 2),
+	MX27_PAD_UART2_CTS = PAD_ID(PE, 3),
+	MX27_PAD_UART2_RTS = PAD_ID(PE, 4),
+	MX27_PAD_PWMO = PAD_ID(PE, 5),
+	MX27_PAD_UART2_TXD = PAD_ID(PE, 6),
+	MX27_PAD_UART2_RXD = PAD_ID(PE, 7),
+	MX27_PAD_UART3_TXD = PAD_ID(PE, 8),
+	MX27_PAD_UART3_RXD = PAD_ID(PE, 9),
+	MX27_PAD_UART3_CTS = PAD_ID(PE, 10),
+	MX27_PAD_UART3_RTS = PAD_ID(PE, 11),
+	MX27_PAD_UART1_TXD = PAD_ID(PE, 12),
+	MX27_PAD_UART1_RXD = PAD_ID(PE, 13),
+	MX27_PAD_UART1_CTS = PAD_ID(PE, 14),
+	MX27_PAD_UART1_RTS = PAD_ID(PE, 15),
+	MX27_PAD_RTCK = PAD_ID(PE, 16),
+	MX27_PAD_RESET_OUT_B = PAD_ID(PE, 17),
+	MX27_PAD_SD1_D0 = PAD_ID(PE, 18),
+	MX27_PAD_SD1_D1 = PAD_ID(PE, 19),
+	MX27_PAD_SD1_D2 = PAD_ID(PE, 20),
+	MX27_PAD_SD1_D3 = PAD_ID(PE, 21),
+	MX27_PAD_SD1_CMD = PAD_ID(PE, 22),
+	MX27_PAD_SD1_CLK = PAD_ID(PE, 23),
+	MX27_PAD_USBOTG_CLK = PAD_ID(PE, 24),
+	MX27_PAD_USBOTG_DATA7 = PAD_ID(PE, 25),
+	MX27_PAD_UNUSED9 = PAD_ID(PE, 26),
+	MX27_PAD_UNUSED10 = PAD_ID(PE, 27),
+	MX27_PAD_UNUSED11 = PAD_ID(PE, 28),
+	MX27_PAD_UNUSED12 = PAD_ID(PE, 29),
+	MX27_PAD_UNUSED13 = PAD_ID(PE, 30),
+	MX27_PAD_UNUSED14 = PAD_ID(PE, 31),
+
+	MX27_PAD_NFRB = PAD_ID(PF, 0),
+	MX27_PAD_NFCLE = PAD_ID(PF, 1),
+	MX27_PAD_NFWP_B = PAD_ID(PF, 2),
+	MX27_PAD_NFCE_B = PAD_ID(PF, 3),
+	MX27_PAD_NFALE = PAD_ID(PF, 4),
+	MX27_PAD_NFRE_B = PAD_ID(PF, 5),
+	MX27_PAD_NFWE_B = PAD_ID(PF, 6),
+	MX27_PAD_PC_POE = PAD_ID(PF, 7),
+	MX27_PAD_PC_RW_B = PAD_ID(PF, 8),
+	MX27_PAD_IOIS16 = PAD_ID(PF, 9),
+	MX27_PAD_PC_RST = PAD_ID(PF, 10),
+	MX27_PAD_PC_BVD2 = PAD_ID(PF, 11),
+	MX27_PAD_PC_BVD1 = PAD_ID(PF, 12),
+	MX27_PAD_PC_VS2 = PAD_ID(PF, 13),
+	MX27_PAD_PC_VS1 = PAD_ID(PF, 14),
+	MX27_PAD_CLKO = PAD_ID(PF, 15),
+	MX27_PAD_PC_PWRON = PAD_ID(PF, 16),
+	MX27_PAD_PC_READY = PAD_ID(PF, 17),
+	MX27_PAD_PC_WAIT_B = PAD_ID(PF, 18),
+	MX27_PAD_PC_CD2_B = PAD_ID(PF, 19),
+	MX27_PAD_PC_CD1_B = PAD_ID(PF, 20),
+	MX27_PAD_CS4_B = PAD_ID(PF, 21),
+	MX27_PAD_CS5_B = PAD_ID(PF, 22),
+	MX27_PAD_ATA_DATA15 = PAD_ID(PF, 23),
+	MX27_PAD_UNUSED15 = PAD_ID(PF, 24),
+	MX27_PAD_UNUSED16 = PAD_ID(PF, 25),
+	MX27_PAD_UNUSED17 = PAD_ID(PF, 26),
+	MX27_PAD_UNUSED18 = PAD_ID(PF, 27),
+	MX27_PAD_UNUSED19 = PAD_ID(PF, 28),
+	MX27_PAD_UNUSED20 = PAD_ID(PF, 29),
+	MX27_PAD_UNUSED21 = PAD_ID(PF, 30),
+	MX27_PAD_UNUSED22 = PAD_ID(PF, 31),
+};
+
+/* Pad names for the pinmux subsystem */
+static const struct pinctrl_pin_desc imx27_pinctrl_pads[] = {
+	IMX_PINCTRL_PIN(MX27_PAD_USBH2_CLK),
+	IMX_PINCTRL_PIN(MX27_PAD_USBH2_DIR),
+	IMX_PINCTRL_PIN(MX27_PAD_USBH2_DATA7),
+	IMX_PINCTRL_PIN(MX27_PAD_USBH2_NXT),
+	IMX_PINCTRL_PIN(MX27_PAD_USBH2_STP),
+	IMX_PINCTRL_PIN(MX27_PAD_LSCLK),
+	IMX_PINCTRL_PIN(MX27_PAD_LD0),
+	IMX_PINCTRL_PIN(MX27_PAD_LD1),
+	IMX_PINCTRL_PIN(MX27_PAD_LD2),
+	IMX_PINCTRL_PIN(MX27_PAD_LD3),
+	IMX_PINCTRL_PIN(MX27_PAD_LD4),
+	IMX_PINCTRL_PIN(MX27_PAD_LD5),
+	IMX_PINCTRL_PIN(MX27_PAD_LD6),
+	IMX_PINCTRL_PIN(MX27_PAD_LD7),
+	IMX_PINCTRL_PIN(MX27_PAD_LD8),
+	IMX_PINCTRL_PIN(MX27_PAD_LD9),
+	IMX_PINCTRL_PIN(MX27_PAD_LD10),
+	IMX_PINCTRL_PIN(MX27_PAD_LD11),
+	IMX_PINCTRL_PIN(MX27_PAD_LD12),
+	IMX_PINCTRL_PIN(MX27_PAD_LD13),
+	IMX_PINCTRL_PIN(MX27_PAD_LD14),
+	IMX_PINCTRL_PIN(MX27_PAD_LD15),
+	IMX_PINCTRL_PIN(MX27_PAD_LD16),
+	IMX_PINCTRL_PIN(MX27_PAD_LD17),
+	IMX_PINCTRL_PIN(MX27_PAD_REV),
+	IMX_PINCTRL_PIN(MX27_PAD_CLS),
+	IMX_PINCTRL_PIN(MX27_PAD_PS),
+	IMX_PINCTRL_PIN(MX27_PAD_SPL_SPR),
+	IMX_PINCTRL_PIN(MX27_PAD_HSYNC),
+	IMX_PINCTRL_PIN(MX27_PAD_VSYNC),
+	IMX_PINCTRL_PIN(MX27_PAD_CONTRAST),
+	IMX_PINCTRL_PIN(MX27_PAD_OE_ACD),
+
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED0),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED1),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED2),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED3),
+	IMX_PINCTRL_PIN(MX27_PAD_SD2_D0),
+	IMX_PINCTRL_PIN(MX27_PAD_SD2_D1),
+	IMX_PINCTRL_PIN(MX27_PAD_SD2_D2),
+	IMX_PINCTRL_PIN(MX27_PAD_SD2_D3),
+	IMX_PINCTRL_PIN(MX27_PAD_SD2_CMD),
+	IMX_PINCTRL_PIN(MX27_PAD_SD2_CLK),
+	IMX_PINCTRL_PIN(MX27_PAD_CSI_D0),
+	IMX_PINCTRL_PIN(MX27_PAD_CSI_D1),
+	IMX_PINCTRL_PIN(MX27_PAD_CSI_D2),
+	IMX_PINCTRL_PIN(MX27_PAD_CSI_D3),
+	IMX_PINCTRL_PIN(MX27_PAD_CSI_D4),
+	IMX_PINCTRL_PIN(MX27_PAD_CSI_MCLK),
+	IMX_PINCTRL_PIN(MX27_PAD_CSI_PIXCLK),
+	IMX_PINCTRL_PIN(MX27_PAD_CSI_D5),
+	IMX_PINCTRL_PIN(MX27_PAD_CSI_D6),
+	IMX_PINCTRL_PIN(MX27_PAD_CSI_D7),
+	IMX_PINCTRL_PIN(MX27_PAD_CSI_VSYNC),
+	IMX_PINCTRL_PIN(MX27_PAD_CSI_HSYNC),
+	IMX_PINCTRL_PIN(MX27_PAD_USBH1_SUSP),
+	IMX_PINCTRL_PIN(MX27_PAD_USB_PWR),
+	IMX_PINCTRL_PIN(MX27_PAD_USB_OC_B),
+	IMX_PINCTRL_PIN(MX27_PAD_USBH1_RCV),
+	IMX_PINCTRL_PIN(MX27_PAD_USBH1_FS),
+	IMX_PINCTRL_PIN(MX27_PAD_USBH1_OE_B),
+	IMX_PINCTRL_PIN(MX27_PAD_USBH1_TXDM),
+	IMX_PINCTRL_PIN(MX27_PAD_USBH1_TXDP),
+	IMX_PINCTRL_PIN(MX27_PAD_USBH1_RXDM),
+	IMX_PINCTRL_PIN(MX27_PAD_USBH1_RXDP),
+
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED4),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED5),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED6),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED7),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED8),
+	IMX_PINCTRL_PIN(MX27_PAD_I2C2_SDA),
+	IMX_PINCTRL_PIN(MX27_PAD_I2C2_SCL),
+	IMX_PINCTRL_PIN(MX27_PAD_USBOTG_DATA5),
+	IMX_PINCTRL_PIN(MX27_PAD_USBOTG_DATA6),
+	IMX_PINCTRL_PIN(MX27_PAD_USBOTG_DATA0),
+	IMX_PINCTRL_PIN(MX27_PAD_USBOTG_DATA2),
+	IMX_PINCTRL_PIN(MX27_PAD_USBOTG_DATA1),
+	IMX_PINCTRL_PIN(MX27_PAD_USBOTG_DATA4),
+	IMX_PINCTRL_PIN(MX27_PAD_USBOTG_DATA3),
+	IMX_PINCTRL_PIN(MX27_PAD_TOUT),
+	IMX_PINCTRL_PIN(MX27_PAD_TIN),
+	IMX_PINCTRL_PIN(MX27_PAD_SSI4_FS),
+	IMX_PINCTRL_PIN(MX27_PAD_SSI4_RXDAT),
+	IMX_PINCTRL_PIN(MX27_PAD_SSI4_TXDAT),
+	IMX_PINCTRL_PIN(MX27_PAD_SSI4_CLK),
+	IMX_PINCTRL_PIN(MX27_PAD_SSI1_FS),
+	IMX_PINCTRL_PIN(MX27_PAD_SSI1_RXDAT),
+	IMX_PINCTRL_PIN(MX27_PAD_SSI1_TXDAT),
+	IMX_PINCTRL_PIN(MX27_PAD_SSI1_CLK),
+	IMX_PINCTRL_PIN(MX27_PAD_SSI2_FS),
+	IMX_PINCTRL_PIN(MX27_PAD_SSI2_RXDAT),
+	IMX_PINCTRL_PIN(MX27_PAD_SSI2_TXDAT),
+	IMX_PINCTRL_PIN(MX27_PAD_SSI2_CLK),
+	IMX_PINCTRL_PIN(MX27_PAD_SSI3_FS),
+	IMX_PINCTRL_PIN(MX27_PAD_SSI3_RXDAT),
+	IMX_PINCTRL_PIN(MX27_PAD_SSI3_TXDAT),
+	IMX_PINCTRL_PIN(MX27_PAD_SSI3_CLK),
+
+	IMX_PINCTRL_PIN(MX27_PAD_SD3_CMD),
+	IMX_PINCTRL_PIN(MX27_PAD_SD3_CLK),
+	IMX_PINCTRL_PIN(MX27_PAD_ATA_DATA0),
+	IMX_PINCTRL_PIN(MX27_PAD_ATA_DATA1),
+	IMX_PINCTRL_PIN(MX27_PAD_ATA_DATA2),
+	IMX_PINCTRL_PIN(MX27_PAD_ATA_DATA3),
+	IMX_PINCTRL_PIN(MX27_PAD_ATA_DATA4),
+	IMX_PINCTRL_PIN(MX27_PAD_ATA_DATA5),
+	IMX_PINCTRL_PIN(MX27_PAD_ATA_DATA6),
+	IMX_PINCTRL_PIN(MX27_PAD_ATA_DATA7),
+	IMX_PINCTRL_PIN(MX27_PAD_ATA_DATA8),
+	IMX_PINCTRL_PIN(MX27_PAD_ATA_DATA9),
+	IMX_PINCTRL_PIN(MX27_PAD_ATA_DATA10),
+	IMX_PINCTRL_PIN(MX27_PAD_ATA_DATA11),
+	IMX_PINCTRL_PIN(MX27_PAD_ATA_DATA12),
+	IMX_PINCTRL_PIN(MX27_PAD_ATA_DATA13),
+	IMX_PINCTRL_PIN(MX27_PAD_ATA_DATA14),
+	IMX_PINCTRL_PIN(MX27_PAD_I2C_DATA),
+	IMX_PINCTRL_PIN(MX27_PAD_I2C_CLK),
+	IMX_PINCTRL_PIN(MX27_PAD_CSPI2_SS2),
+	IMX_PINCTRL_PIN(MX27_PAD_CSPI2_SS1),
+	IMX_PINCTRL_PIN(MX27_PAD_CSPI2_SS0),
+	IMX_PINCTRL_PIN(MX27_PAD_CSPI2_SCLK),
+	IMX_PINCTRL_PIN(MX27_PAD_CSPI2_MISO),
+	IMX_PINCTRL_PIN(MX27_PAD_CSPI2_MOSI),
+	IMX_PINCTRL_PIN(MX27_PAD_CSPI1_RDY),
+	IMX_PINCTRL_PIN(MX27_PAD_CSPI1_SS2),
+	IMX_PINCTRL_PIN(MX27_PAD_CSPI1_SS1),
+	IMX_PINCTRL_PIN(MX27_PAD_CSPI1_SS0),
+	IMX_PINCTRL_PIN(MX27_PAD_CSPI1_SCLK),
+	IMX_PINCTRL_PIN(MX27_PAD_CSPI1_MISO),
+	IMX_PINCTRL_PIN(MX27_PAD_CSPI1_MOSI),
+
+	IMX_PINCTRL_PIN(MX27_PAD_USBOTG_NXT),
+	IMX_PINCTRL_PIN(MX27_PAD_USBOTG_STP),
+	IMX_PINCTRL_PIN(MX27_PAD_USBOTG_DIR),
+	IMX_PINCTRL_PIN(MX27_PAD_UART2_CTS),
+	IMX_PINCTRL_PIN(MX27_PAD_UART2_RTS),
+	IMX_PINCTRL_PIN(MX27_PAD_PWMO),
+	IMX_PINCTRL_PIN(MX27_PAD_UART2_TXD),
+	IMX_PINCTRL_PIN(MX27_PAD_UART2_RXD),
+	IMX_PINCTRL_PIN(MX27_PAD_UART3_TXD),
+	IMX_PINCTRL_PIN(MX27_PAD_UART3_RXD),
+	IMX_PINCTRL_PIN(MX27_PAD_UART3_CTS),
+	IMX_PINCTRL_PIN(MX27_PAD_UART3_RTS),
+	IMX_PINCTRL_PIN(MX27_PAD_UART1_TXD),
+	IMX_PINCTRL_PIN(MX27_PAD_UART1_RXD),
+	IMX_PINCTRL_PIN(MX27_PAD_UART1_CTS),
+	IMX_PINCTRL_PIN(MX27_PAD_UART1_RTS),
+	IMX_PINCTRL_PIN(MX27_PAD_RTCK),
+	IMX_PINCTRL_PIN(MX27_PAD_RESET_OUT_B),
+	IMX_PINCTRL_PIN(MX27_PAD_SD1_D0),
+	IMX_PINCTRL_PIN(MX27_PAD_SD1_D1),
+	IMX_PINCTRL_PIN(MX27_PAD_SD1_D2),
+	IMX_PINCTRL_PIN(MX27_PAD_SD1_D3),
+	IMX_PINCTRL_PIN(MX27_PAD_SD1_CMD),
+	IMX_PINCTRL_PIN(MX27_PAD_SD1_CLK),
+	IMX_PINCTRL_PIN(MX27_PAD_USBOTG_CLK),
+	IMX_PINCTRL_PIN(MX27_PAD_USBOTG_DATA7),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED9),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED10),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED11),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED12),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED13),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED14),
+
+	IMX_PINCTRL_PIN(MX27_PAD_NFRB),
+	IMX_PINCTRL_PIN(MX27_PAD_NFCLE),
+	IMX_PINCTRL_PIN(MX27_PAD_NFWP_B),
+	IMX_PINCTRL_PIN(MX27_PAD_NFCE_B),
+	IMX_PINCTRL_PIN(MX27_PAD_NFALE),
+	IMX_PINCTRL_PIN(MX27_PAD_NFRE_B),
+	IMX_PINCTRL_PIN(MX27_PAD_NFWE_B),
+	IMX_PINCTRL_PIN(MX27_PAD_PC_POE),
+	IMX_PINCTRL_PIN(MX27_PAD_PC_RW_B),
+	IMX_PINCTRL_PIN(MX27_PAD_IOIS16),
+	IMX_PINCTRL_PIN(MX27_PAD_PC_RST),
+	IMX_PINCTRL_PIN(MX27_PAD_PC_BVD2),
+	IMX_PINCTRL_PIN(MX27_PAD_PC_BVD1),
+	IMX_PINCTRL_PIN(MX27_PAD_PC_VS2),
+	IMX_PINCTRL_PIN(MX27_PAD_PC_VS1),
+	IMX_PINCTRL_PIN(MX27_PAD_CLKO),
+	IMX_PINCTRL_PIN(MX27_PAD_PC_PWRON),
+	IMX_PINCTRL_PIN(MX27_PAD_PC_READY),
+	IMX_PINCTRL_PIN(MX27_PAD_PC_WAIT_B),
+	IMX_PINCTRL_PIN(MX27_PAD_PC_CD2_B),
+	IMX_PINCTRL_PIN(MX27_PAD_PC_CD1_B),
+	IMX_PINCTRL_PIN(MX27_PAD_CS4_B),
+	IMX_PINCTRL_PIN(MX27_PAD_CS5_B),
+	IMX_PINCTRL_PIN(MX27_PAD_ATA_DATA15),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED15),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED16),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED17),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED18),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED19),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED20),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED21),
+	IMX_PINCTRL_PIN(MX27_PAD_UNUSED22),
+};
+
+static struct imx1_pinctrl_soc_info imx27_pinctrl_info = {
+	.pins = imx27_pinctrl_pads,
+	.npins = ARRAY_SIZE(imx27_pinctrl_pads),
+};
+
+static struct of_device_id imx27_pinctrl_of_match[] = {
+	{ .compatible = "fsl,imx27-iomuxc", },
+	{ /* sentinel */ }
+};
+
+struct imx27_pinctrl_private {
+	int num_gpio_childs;
+	struct platform_device **gpio_dev;
+	struct mxc_gpio_platform_data *gpio_pdata;
+};
+
+static int imx27_pinctrl_probe(struct platform_device *pdev)
+{
+	return imx1_pinctrl_core_probe(pdev, &imx27_pinctrl_info);
+}
+
+static struct platform_driver imx27_pinctrl_driver = {
+	.driver = {
+		.name = "imx27-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(imx27_pinctrl_of_match),
+	},
+	.probe = imx27_pinctrl_probe,
+	.remove = imx1_pinctrl_core_remove,
+};
+
+static int __init imx27_pinctrl_init(void)
+{
+	return platform_driver_register(&imx27_pinctrl_driver);
+}
+arch_initcall(imx27_pinctrl_init);
+
+static void __exit imx27_pinctrl_exit(void)
+{
+	platform_driver_unregister(&imx27_pinctrl_driver);
+}
+module_exit(imx27_pinctrl_exit);
+MODULE_AUTHOR("Markus Pargmann <mpa@pengutronix.de>");
+MODULE_DESCRIPTION("Freescale IMX27 pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-imx35.c b/drivers/pinctrl/pinctrl-imx35.c
index c454982..278a04a 100644
--- a/drivers/pinctrl/pinctrl-imx35.c
+++ b/drivers/pinctrl/pinctrl-imx35.c
@@ -1019,7 +1019,7 @@
 	.driver = {
 		.name = "imx35-pinctrl",
 		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(imx35_pinctrl_of_match),
+		.of_match_table = imx35_pinctrl_of_match,
 	},
 	.probe = imx35_pinctrl_probe,
 	.remove = imx_pinctrl_remove,
diff --git a/drivers/pinctrl/pinctrl-imx50.c b/drivers/pinctrl/pinctrl-imx50.c
new file mode 100644
index 0000000..b06feed
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-imx50.c
@@ -0,0 +1,426 @@
+/*
+ * imx50 pinctrl driver based on imx pinmux core
+ *
+ * Copyright (C) 2013 Greg Ungerer <gerg@uclinux.org>
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012 Linaro, 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/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-imx.h"
+
+enum imx50_pads {
+	MX50_PAD_RESERVE0 = 0,
+	MX50_PAD_RESERVE1 = 1,
+	MX50_PAD_RESERVE2 = 2,
+	MX50_PAD_RESERVE3 = 3,
+	MX50_PAD_RESERVE4 = 4,
+	MX50_PAD_RESERVE5 = 5,
+	MX50_PAD_RESERVE6 = 6,
+	MX50_PAD_RESERVE7 = 7,
+	MX50_PAD_KEY_COL0 = 8,
+	MX50_PAD_KEY_ROW0 = 9,
+	MX50_PAD_KEY_COL1 = 10,
+	MX50_PAD_KEY_ROW1 = 11,
+	MX50_PAD_KEY_COL2 = 12,
+	MX50_PAD_KEY_ROW2 = 13,
+	MX50_PAD_KEY_COL3 = 14,
+	MX50_PAD_KEY_ROW3 = 15,
+	MX50_PAD_I2C1_SCL = 16,
+	MX50_PAD_I2C1_SDA = 17,
+	MX50_PAD_I2C2_SCL = 18,
+	MX50_PAD_I2C2_SDA = 19,
+	MX50_PAD_I2C3_SCL = 20,
+	MX50_PAD_I2C3_SDA = 21,
+	MX50_PAD_PWM1 = 22,
+	MX50_PAD_PWM2 = 23,
+	MX50_PAD_0WIRE = 24,
+	MX50_PAD_EPITO = 25,
+	MX50_PAD_WDOG = 26,
+	MX50_PAD_SSI_TXFS = 27,
+	MX50_PAD_SSI_TXC = 28,
+	MX50_PAD_SSI_TXD = 29,
+	MX50_PAD_SSI_RXD = 30,
+	MX50_PAD_SSI_RXF = 31,
+	MX50_PAD_SSI_RXC = 32,
+	MX50_PAD_UART1_TXD = 33,
+	MX50_PAD_UART1_RXD = 34,
+	MX50_PAD_UART1_CTS = 35,
+	MX50_PAD_UART1_RTS = 36,
+	MX50_PAD_UART2_TXD = 37,
+	MX50_PAD_UART2_RXD = 38,
+	MX50_PAD_UART2_CTS = 39,
+	MX50_PAD_UART2_RTS = 40,
+	MX50_PAD_UART3_TXD = 41,
+	MX50_PAD_UART3_RXD = 42,
+	MX50_PAD_UART4_TXD = 43,
+	MX50_PAD_UART4_RXD = 44,
+	MX50_PAD_CSPI_CLK = 45,
+	MX50_PAD_CSPI_MOSI = 46,
+	MX50_PAD_CSPI_MISO = 47,
+	MX50_PAD_CSPI_SS0 = 48,
+	MX50_PAD_ECSPI1_CLK = 49,
+	MX50_PAD_ECSPI1_MOSI = 50,
+	MX50_PAD_ECSPI1_MISO = 51,
+	MX50_PAD_ECSPI1_SS0 = 52,
+	MX50_PAD_ECSPI2_CLK = 53,
+	MX50_PAD_ECSPI2_MOSI = 54,
+	MX50_PAD_ECSPI2_MISO = 55,
+	MX50_PAD_ECSPI2_SS0 = 56,
+	MX50_PAD_SD1_CLK = 57,
+	MX50_PAD_SD1_CMD = 58,
+	MX50_PAD_SD1_D0 = 59,
+	MX50_PAD_SD1_D1 = 60,
+	MX50_PAD_SD1_D2 = 61,
+	MX50_PAD_SD1_D3 = 62,
+	MX50_PAD_SD2_CLK = 63,
+	MX50_PAD_SD2_CMD = 64,
+	MX50_PAD_SD2_D0 = 65,
+	MX50_PAD_SD2_D1 = 66,
+	MX50_PAD_SD2_D2 = 67,
+	MX50_PAD_SD2_D3 = 68,
+	MX50_PAD_SD2_D4 = 69,
+	MX50_PAD_SD2_D5 = 70,
+	MX50_PAD_SD2_D6 = 71,
+	MX50_PAD_SD2_D7 = 72,
+	MX50_PAD_SD2_WP = 73,
+	MX50_PAD_SD2_CD = 74,
+	MX50_PAD_DISP_D0 = 75,
+	MX50_PAD_DISP_D1 = 76,
+	MX50_PAD_DISP_D2 = 77,
+	MX50_PAD_DISP_D3 = 78,
+	MX50_PAD_DISP_D4 = 79,
+	MX50_PAD_DISP_D5 = 80,
+	MX50_PAD_DISP_D6 = 81,
+	MX50_PAD_DISP_D7 = 82,
+	MX50_PAD_DISP_WR = 83,
+	MX50_PAD_DISP_RD = 84,
+	MX50_PAD_DISP_RS = 85,
+	MX50_PAD_DISP_CS = 86,
+	MX50_PAD_DISP_BUSY = 87,
+	MX50_PAD_DISP_RESET = 88,
+	MX50_PAD_SD3_CLK = 89,
+	MX50_PAD_SD3_CMD = 90,
+	MX50_PAD_SD3_D0 = 91,
+	MX50_PAD_SD3_D1 = 92,
+	MX50_PAD_SD3_D2 = 93,
+	MX50_PAD_SD3_D3 = 94,
+	MX50_PAD_SD3_D4 = 95,
+	MX50_PAD_SD3_D5 = 96,
+	MX50_PAD_SD3_D6 = 97,
+	MX50_PAD_SD3_D7 = 98,
+	MX50_PAD_SD3_WP = 99,
+	MX50_PAD_DISP_D8 = 100,
+	MX50_PAD_DISP_D9 = 101,
+	MX50_PAD_DISP_D10 = 102,
+	MX50_PAD_DISP_D11 = 103,
+	MX50_PAD_DISP_D12 = 104,
+	MX50_PAD_DISP_D13 = 105,
+	MX50_PAD_DISP_D14 = 106,
+	MX50_PAD_DISP_D15 = 107,
+	MX50_PAD_EPDC_D0 = 108,
+	MX50_PAD_EPDC_D1 = 109,
+	MX50_PAD_EPDC_D2 = 110,
+	MX50_PAD_EPDC_D3 = 111,
+	MX50_PAD_EPDC_D4 = 112,
+	MX50_PAD_EPDC_D5 = 113,
+	MX50_PAD_EPDC_D6 = 114,
+	MX50_PAD_EPDC_D7 = 115,
+	MX50_PAD_EPDC_D8 = 116,
+	MX50_PAD_EPDC_D9 = 117,
+	MX50_PAD_EPDC_D10 = 118,
+	MX50_PAD_EPDC_D11 = 119,
+	MX50_PAD_EPDC_D12 = 120,
+	MX50_PAD_EPDC_D13 = 121,
+	MX50_PAD_EPDC_D14 = 122,
+	MX50_PAD_EPDC_D15 = 123,
+	MX50_PAD_EPDC_GDCLK = 124,
+	MX50_PAD_EPDC_GDSP = 125,
+	MX50_PAD_EPDC_GDOE = 126,
+	MX50_PAD_EPDC_GDRL = 127,
+	MX50_PAD_EPDC_SDCLK = 128,
+	MX50_PAD_EPDC_SDOEZ = 129,
+	MX50_PAD_EPDC_SDOED = 130,
+	MX50_PAD_EPDC_SDOE = 131,
+	MX50_PAD_EPDC_SDLE = 132,
+	MX50_PAD_EPDC_SDCLKN = 133,
+	MX50_PAD_EPDC_SDSHR = 134,
+	MX50_PAD_EPDC_PWRCOM = 135,
+	MX50_PAD_EPDC_PWRSTAT = 136,
+	MX50_PAD_EPDC_PWRCTRL0 = 137,
+	MX50_PAD_EPDC_PWRCTRL1 = 138,
+	MX50_PAD_EPDC_PWRCTRL2 = 139,
+	MX50_PAD_EPDC_PWRCTRL3 = 140,
+	MX50_PAD_EPDC_VCOM0 = 141,
+	MX50_PAD_EPDC_VCOM1 = 142,
+	MX50_PAD_EPDC_BDR0 = 143,
+	MX50_PAD_EPDC_BDR1 = 144,
+	MX50_PAD_EPDC_SDCE0 = 145,
+	MX50_PAD_EPDC_SDCE1 = 146,
+	MX50_PAD_EPDC_SDCE2 = 147,
+	MX50_PAD_EPDC_SDCE3 = 148,
+	MX50_PAD_EPDC_SDCE4 = 149,
+	MX50_PAD_EPDC_SDCE5 = 150,
+	MX50_PAD_EIM_DA0 = 151,
+	MX50_PAD_EIM_DA1 = 152,
+	MX50_PAD_EIM_DA2 = 153,
+	MX50_PAD_EIM_DA3 = 154,
+	MX50_PAD_EIM_DA4 = 155,
+	MX50_PAD_EIM_DA5 = 156,
+	MX50_PAD_EIM_DA6 = 157,
+	MX50_PAD_EIM_DA7 = 158,
+	MX50_PAD_EIM_DA8 = 159,
+	MX50_PAD_EIM_DA9 = 160,
+	MX50_PAD_EIM_DA10 = 161,
+	MX50_PAD_EIM_DA11 = 162,
+	MX50_PAD_EIM_DA12 = 163,
+	MX50_PAD_EIM_DA13 = 164,
+	MX50_PAD_EIM_DA14 = 165,
+	MX50_PAD_EIM_DA15 = 166,
+	MX50_PAD_EIM_CS2 = 167,
+	MX50_PAD_EIM_CS1 = 168,
+	MX50_PAD_EIM_CS0 = 169,
+	MX50_PAD_EIM_EB0 = 170,
+	MX50_PAD_EIM_EB1 = 171,
+	MX50_PAD_EIM_WAIT = 172,
+	MX50_PAD_EIM_BCLK = 173,
+	MX50_PAD_EIM_RDY = 174,
+	MX50_PAD_EIM_OE = 175,
+	MX50_PAD_EIM_RW = 176,
+	MX50_PAD_EIM_LBA = 177,
+	MX50_PAD_EIM_CRE = 178,
+};
+
+/* Pad names for the pinmux subsystem */
+static const struct pinctrl_pin_desc imx50_pinctrl_pads[] = {
+	IMX_PINCTRL_PIN(MX50_PAD_RESERVE0),
+	IMX_PINCTRL_PIN(MX50_PAD_RESERVE1),
+	IMX_PINCTRL_PIN(MX50_PAD_RESERVE2),
+	IMX_PINCTRL_PIN(MX50_PAD_RESERVE3),
+	IMX_PINCTRL_PIN(MX50_PAD_RESERVE4),
+	IMX_PINCTRL_PIN(MX50_PAD_RESERVE5),
+	IMX_PINCTRL_PIN(MX50_PAD_RESERVE6),
+	IMX_PINCTRL_PIN(MX50_PAD_RESERVE7),
+	IMX_PINCTRL_PIN(MX50_PAD_KEY_COL0),
+	IMX_PINCTRL_PIN(MX50_PAD_KEY_ROW0),
+	IMX_PINCTRL_PIN(MX50_PAD_KEY_COL1),
+	IMX_PINCTRL_PIN(MX50_PAD_KEY_ROW1),
+	IMX_PINCTRL_PIN(MX50_PAD_KEY_COL2),
+	IMX_PINCTRL_PIN(MX50_PAD_KEY_ROW2),
+	IMX_PINCTRL_PIN(MX50_PAD_KEY_COL3),
+	IMX_PINCTRL_PIN(MX50_PAD_KEY_ROW3),
+	IMX_PINCTRL_PIN(MX50_PAD_I2C1_SCL),
+	IMX_PINCTRL_PIN(MX50_PAD_I2C1_SDA),
+	IMX_PINCTRL_PIN(MX50_PAD_I2C2_SCL),
+	IMX_PINCTRL_PIN(MX50_PAD_I2C2_SDA),
+	IMX_PINCTRL_PIN(MX50_PAD_I2C3_SCL),
+	IMX_PINCTRL_PIN(MX50_PAD_I2C3_SDA),
+	IMX_PINCTRL_PIN(MX50_PAD_PWM1),
+	IMX_PINCTRL_PIN(MX50_PAD_PWM2),
+	IMX_PINCTRL_PIN(MX50_PAD_0WIRE),
+	IMX_PINCTRL_PIN(MX50_PAD_EPITO),
+	IMX_PINCTRL_PIN(MX50_PAD_WDOG),
+	IMX_PINCTRL_PIN(MX50_PAD_SSI_TXFS),
+	IMX_PINCTRL_PIN(MX50_PAD_SSI_TXC),
+	IMX_PINCTRL_PIN(MX50_PAD_SSI_TXD),
+	IMX_PINCTRL_PIN(MX50_PAD_SSI_RXD),
+	IMX_PINCTRL_PIN(MX50_PAD_SSI_RXF),
+	IMX_PINCTRL_PIN(MX50_PAD_SSI_RXC),
+	IMX_PINCTRL_PIN(MX50_PAD_UART1_TXD),
+	IMX_PINCTRL_PIN(MX50_PAD_UART1_RXD),
+	IMX_PINCTRL_PIN(MX50_PAD_UART1_CTS),
+	IMX_PINCTRL_PIN(MX50_PAD_UART1_RTS),
+	IMX_PINCTRL_PIN(MX50_PAD_UART2_TXD),
+	IMX_PINCTRL_PIN(MX50_PAD_UART2_RXD),
+	IMX_PINCTRL_PIN(MX50_PAD_UART2_CTS),
+	IMX_PINCTRL_PIN(MX50_PAD_UART2_RTS),
+	IMX_PINCTRL_PIN(MX50_PAD_UART3_TXD),
+	IMX_PINCTRL_PIN(MX50_PAD_UART3_RXD),
+	IMX_PINCTRL_PIN(MX50_PAD_UART4_TXD),
+	IMX_PINCTRL_PIN(MX50_PAD_UART4_RXD),
+	IMX_PINCTRL_PIN(MX50_PAD_CSPI_CLK),
+	IMX_PINCTRL_PIN(MX50_PAD_CSPI_MOSI),
+	IMX_PINCTRL_PIN(MX50_PAD_CSPI_MISO),
+	IMX_PINCTRL_PIN(MX50_PAD_CSPI_SS0),
+	IMX_PINCTRL_PIN(MX50_PAD_ECSPI1_CLK),
+	IMX_PINCTRL_PIN(MX50_PAD_ECSPI1_MOSI),
+	IMX_PINCTRL_PIN(MX50_PAD_ECSPI1_MISO),
+	IMX_PINCTRL_PIN(MX50_PAD_ECSPI1_SS0),
+	IMX_PINCTRL_PIN(MX50_PAD_ECSPI2_CLK),
+	IMX_PINCTRL_PIN(MX50_PAD_ECSPI2_MOSI),
+	IMX_PINCTRL_PIN(MX50_PAD_ECSPI2_MISO),
+	IMX_PINCTRL_PIN(MX50_PAD_ECSPI2_SS0),
+	IMX_PINCTRL_PIN(MX50_PAD_SD1_CLK),
+	IMX_PINCTRL_PIN(MX50_PAD_SD1_CMD),
+	IMX_PINCTRL_PIN(MX50_PAD_SD1_D0),
+	IMX_PINCTRL_PIN(MX50_PAD_SD1_D1),
+	IMX_PINCTRL_PIN(MX50_PAD_SD1_D2),
+	IMX_PINCTRL_PIN(MX50_PAD_SD1_D3),
+	IMX_PINCTRL_PIN(MX50_PAD_SD2_CLK),
+	IMX_PINCTRL_PIN(MX50_PAD_SD2_CMD),
+	IMX_PINCTRL_PIN(MX50_PAD_SD2_D0),
+	IMX_PINCTRL_PIN(MX50_PAD_SD2_D1),
+	IMX_PINCTRL_PIN(MX50_PAD_SD2_D2),
+	IMX_PINCTRL_PIN(MX50_PAD_SD2_D3),
+	IMX_PINCTRL_PIN(MX50_PAD_SD2_D4),
+	IMX_PINCTRL_PIN(MX50_PAD_SD2_D5),
+	IMX_PINCTRL_PIN(MX50_PAD_SD2_D6),
+	IMX_PINCTRL_PIN(MX50_PAD_SD2_D7),
+	IMX_PINCTRL_PIN(MX50_PAD_SD2_WP),
+	IMX_PINCTRL_PIN(MX50_PAD_SD2_CD),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_D0),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_D1),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_D2),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_D3),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_D4),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_D5),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_D6),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_D7),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_WR),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_RD),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_RS),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_CS),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_BUSY),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_RESET),
+	IMX_PINCTRL_PIN(MX50_PAD_SD3_CLK),
+	IMX_PINCTRL_PIN(MX50_PAD_SD3_CMD),
+	IMX_PINCTRL_PIN(MX50_PAD_SD3_D0),
+	IMX_PINCTRL_PIN(MX50_PAD_SD3_D1),
+	IMX_PINCTRL_PIN(MX50_PAD_SD3_D2),
+	IMX_PINCTRL_PIN(MX50_PAD_SD3_D3),
+	IMX_PINCTRL_PIN(MX50_PAD_SD3_D4),
+	IMX_PINCTRL_PIN(MX50_PAD_SD3_D5),
+	IMX_PINCTRL_PIN(MX50_PAD_SD3_D6),
+	IMX_PINCTRL_PIN(MX50_PAD_SD3_D7),
+	IMX_PINCTRL_PIN(MX50_PAD_SD3_WP),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_D8),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_D9),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_D10),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_D11),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_D12),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_D13),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_D14),
+	IMX_PINCTRL_PIN(MX50_PAD_DISP_D15),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_D0),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_D1),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_D2),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_D3),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_D4),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_D5),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_D6),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_D7),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_D8),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_D9),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_D10),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_D11),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_D12),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_D13),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_D14),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_D15),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_GDCLK),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_GDSP),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_GDOE),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_GDRL),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_SDCLK),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_SDOEZ),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_SDOED),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_SDOE),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_SDLE),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_SDCLKN),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_SDSHR),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_PWRCOM),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_PWRSTAT),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_PWRCTRL0),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_PWRCTRL1),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_PWRCTRL2),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_PWRCTRL3),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_VCOM0),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_VCOM1),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_BDR0),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_BDR1),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_SDCE0),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_SDCE1),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_SDCE2),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_SDCE3),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_SDCE4),
+	IMX_PINCTRL_PIN(MX50_PAD_EPDC_SDCE5),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_DA0),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_DA1),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_DA2),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_DA3),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_DA4),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_DA5),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_DA6),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_DA7),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_DA8),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_DA9),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_DA10),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_DA11),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_DA12),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_DA13),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_DA14),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_DA15),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_CS2),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_CS1),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_CS0),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_EB0),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_EB1),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_WAIT),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_BCLK),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_RDY),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_OE),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_RW),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_LBA),
+	IMX_PINCTRL_PIN(MX50_PAD_EIM_CRE),
+};
+
+static struct imx_pinctrl_soc_info imx50_pinctrl_info = {
+	.pins = imx50_pinctrl_pads,
+	.npins = ARRAY_SIZE(imx50_pinctrl_pads),
+};
+
+static struct of_device_id imx50_pinctrl_of_match[] = {
+	{ .compatible = "fsl,imx50-iomuxc", },
+	{ /* sentinel */ }
+};
+
+static int imx50_pinctrl_probe(struct platform_device *pdev)
+{
+	return imx_pinctrl_probe(pdev, &imx50_pinctrl_info);
+}
+
+static struct platform_driver imx50_pinctrl_driver = {
+	.driver = {
+		.name = "imx50-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(imx50_pinctrl_of_match),
+	},
+	.probe = imx50_pinctrl_probe,
+	.remove = imx_pinctrl_remove,
+};
+
+static int __init imx50_pinctrl_init(void)
+{
+	return platform_driver_register(&imx50_pinctrl_driver);
+}
+arch_initcall(imx50_pinctrl_init);
+
+static void __exit imx50_pinctrl_exit(void)
+{
+	platform_driver_unregister(&imx50_pinctrl_driver);
+}
+module_exit(imx50_pinctrl_exit);
+MODULE_DESCRIPTION("Freescale IMX50 pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-imx51.c b/drivers/pinctrl/pinctrl-imx51.c
index db268b9..19ab182 100644
--- a/drivers/pinctrl/pinctrl-imx51.c
+++ b/drivers/pinctrl/pinctrl-imx51.c
@@ -782,7 +782,7 @@
 	.driver = {
 		.name = "imx51-pinctrl",
 		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(imx51_pinctrl_of_match),
+		.of_match_table = imx51_pinctrl_of_match,
 	},
 	.probe = imx51_pinctrl_probe,
 	.remove = imx_pinctrl_remove,
diff --git a/drivers/pinctrl/pinctrl-imx53.c b/drivers/pinctrl/pinctrl-imx53.c
index 17562ae..f8d45c4 100644
--- a/drivers/pinctrl/pinctrl-imx53.c
+++ b/drivers/pinctrl/pinctrl-imx53.c
@@ -468,7 +468,7 @@
 	.driver = {
 		.name = "imx53-pinctrl",
 		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(imx53_pinctrl_of_match),
+		.of_match_table = imx53_pinctrl_of_match,
 	},
 	.probe = imx53_pinctrl_probe,
 	.remove = imx_pinctrl_remove,
diff --git a/drivers/pinctrl/pinctrl-imx6dl.c b/drivers/pinctrl/pinctrl-imx6dl.c
index a76b724..db2a148 100644
--- a/drivers/pinctrl/pinctrl-imx6dl.c
+++ b/drivers/pinctrl/pinctrl-imx6dl.c
@@ -474,7 +474,7 @@
 	.driver = {
 		.name = "imx6dl-pinctrl",
 		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(imx6dl_pinctrl_of_match),
+		.of_match_table = imx6dl_pinctrl_of_match,
 	},
 	.probe = imx6dl_pinctrl_probe,
 	.remove = imx_pinctrl_remove,
diff --git a/drivers/pinctrl/pinctrl-imx6q.c b/drivers/pinctrl/pinctrl-imx6q.c
index 76dd9c4..8eb5ac1 100644
--- a/drivers/pinctrl/pinctrl-imx6q.c
+++ b/drivers/pinctrl/pinctrl-imx6q.c
@@ -480,7 +480,7 @@
 	.driver = {
 		.name = "imx6q-pinctrl",
 		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(imx6q_pinctrl_of_match),
+		.of_match_table = imx6q_pinctrl_of_match,
 	},
 	.probe = imx6q_pinctrl_probe,
 	.remove = imx_pinctrl_remove,
diff --git a/drivers/pinctrl/pinctrl-imx6sl.c b/drivers/pinctrl/pinctrl-imx6sl.c
index 4eb7cca..f21b738 100644
--- a/drivers/pinctrl/pinctrl-imx6sl.c
+++ b/drivers/pinctrl/pinctrl-imx6sl.c
@@ -380,7 +380,7 @@
 	.driver = {
 		.name = "imx6sl-pinctrl",
 		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(imx6sl_pinctrl_of_match),
+		.of_match_table = imx6sl_pinctrl_of_match,
 	},
 	.probe = imx6sl_pinctrl_probe,
 	.remove = imx_pinctrl_remove,
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
index d7c3ae3..7111c3b 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -634,6 +634,10 @@
 {
 	struct nmk_gpio_chip *nmk_chip = irq_data_get_irq_chip_data(d);
 
+	if (gpio_lock_as_irq(&nmk_chip->chip, d->hwirq))
+		dev_err(nmk_chip->chip.dev,
+			"unable to lock HW IRQ %lu for IRQ\n",
+			d->hwirq);
 	clk_enable(nmk_chip->clk);
 	nmk_gpio_irq_unmask(d);
 	return 0;
@@ -645,6 +649,7 @@
 
 	nmk_gpio_irq_mask(d);
 	clk_disable(nmk_chip->clk);
+	gpio_unlock_as_irq(&nmk_chip->chip, d->hwirq);
 }
 
 static struct irq_chip nmk_gpio_irq_chip = {
diff --git a/drivers/pinctrl/pinctrl-palmas.c b/drivers/pinctrl/pinctrl-palmas.c
index 30c4d35..f13d0e7 100644
--- a/drivers/pinctrl/pinctrl-palmas.c
+++ b/drivers/pinctrl/pinctrl-palmas.c
@@ -891,9 +891,6 @@
 		param = pinconf_to_config_param(configs[i]);
 		param_val = pinconf_to_config_argument(configs[i]);
 
-		if (param == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
-			continue;
-
 		switch (param) {
 		case PIN_CONFIG_BIAS_DISABLE:
 		case PIN_CONFIG_BIAS_PULL_UP:
@@ -962,26 +959,9 @@
 	return 0;
 }
 
-static int palmas_pinconf_group_get(struct pinctrl_dev *pctldev,
-				unsigned group, unsigned long *config)
-{
-	dev_err(pctldev->dev, "palmas_pinconf_group_get op not supported\n");
-	return -ENOTSUPP;
-}
-
-static int palmas_pinconf_group_set(struct pinctrl_dev *pctldev,
-				unsigned group, unsigned long *configs,
-				unsigned num_configs)
-{
-	dev_err(pctldev->dev, "palmas_pinconf_group_set op not supported\n");
-	return -ENOTSUPP;
-}
-
 static const struct pinconf_ops palmas_pinconf_ops = {
 	.pin_config_get = palmas_pinconf_get,
 	.pin_config_set = palmas_pinconf_set,
-	.pin_config_group_get = palmas_pinconf_group_get,
-	.pin_config_group_set = palmas_pinconf_group_set,
 };
 
 static struct pinctrl_desc palmas_pinctrl_desc = {
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index e0718b7..e939c28 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -56,8 +56,20 @@
 #define GPIO_EXT_PORT		0x50
 #define GPIO_LS_SYNC		0x60
 
+enum rockchip_pinctrl_type {
+	RK2928,
+	RK3066B,
+	RK3188,
+};
+
+enum rockchip_pin_bank_type {
+	COMMON_BANK,
+	RK3188_BANK0,
+};
+
 /**
  * @reg_base: register base of the gpio bank
+ * @reg_pull: optional separate register for additional pull settings
  * @clk: clock of the gpio bank
  * @irq: interrupt of the gpio bank
  * @pin_base: first pin number
@@ -74,12 +86,14 @@
  */
 struct rockchip_pin_bank {
 	void __iomem			*reg_base;
+	void __iomem			*reg_pull;
 	struct clk			*clk;
 	int				irq;
 	u32				pin_base;
 	u8				nr_pins;
 	char				*name;
 	u8				bank_num;
+	enum rockchip_pin_bank_type	bank_type;
 	bool				valid;
 	struct device_node		*of_node;
 	struct rockchip_pinctrl		*drvdata;
@@ -87,7 +101,7 @@
 	struct gpio_chip		gpio_chip;
 	struct pinctrl_gpio_range	grange;
 	spinlock_t			slock;
-
+	u32				toggle_edge_mode;
 };
 
 #define PIN_BANK(id, pins, label)			\
@@ -98,18 +112,16 @@
 	}
 
 /**
- * @pull_auto: some SoCs don't allow pulls to be specified as up or down, but
- *	       instead decide this automatically based on the pad-type.
  */
 struct rockchip_pin_ctrl {
 	struct rockchip_pin_bank	*pin_banks;
 	u32				nr_banks;
 	u32				nr_pins;
 	char				*label;
+	enum rockchip_pinctrl_type	type;
 	int				mux_offset;
-	int				pull_offset;
-	bool				pull_auto;
-	int				pull_bank_stride;
+	void	(*pull_calc_reg)(struct rockchip_pin_bank *bank, int pin_num,
+				 void __iomem **reg, u8 *bit);
 };
 
 struct rockchip_pin_config {
@@ -148,6 +160,7 @@
 
 struct rockchip_pinctrl {
 	void __iomem			*reg_base;
+	void __iomem			*reg_pull;
 	struct device			*dev;
 	struct rockchip_pin_ctrl	*ctrl;
 	struct pinctrl_desc		pctl;
@@ -354,31 +367,92 @@
 	spin_unlock_irqrestore(&bank->slock, flags);
 }
 
+#define RK2928_PULL_OFFSET		0x118
+#define RK2928_PULL_PINS_PER_REG	16
+#define RK2928_PULL_BANK_STRIDE		8
+
+static void rk2928_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+				    int pin_num, void __iomem **reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	*reg = info->reg_base + RK2928_PULL_OFFSET;
+	*reg += bank->bank_num * RK2928_PULL_BANK_STRIDE;
+	*reg += (pin_num / RK2928_PULL_PINS_PER_REG) * 4;
+
+	*bit = pin_num % RK2928_PULL_PINS_PER_REG;
+};
+
+#define RK3188_PULL_BITS_PER_PIN	2
+#define RK3188_PULL_PINS_PER_REG	8
+#define RK3188_PULL_BANK_STRIDE		16
+
+static void rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+				    int pin_num, void __iomem **reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	/* The first 12 pins of the first bank are located elsewhere */
+	if (bank->bank_type == RK3188_BANK0 && pin_num < 12) {
+		*reg = bank->reg_pull +
+				((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+		*bit = pin_num % RK3188_PULL_PINS_PER_REG;
+		*bit *= RK3188_PULL_BITS_PER_PIN;
+	} else {
+		*reg = info->reg_pull - 4;
+		*reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
+		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+
+		/*
+		 * The bits in these registers have an inverse ordering
+		 * with the lowest pin being in bits 15:14 and the highest
+		 * pin in bits 1:0
+		 */
+		*bit = 7 - (pin_num % RK3188_PULL_PINS_PER_REG);
+		*bit *= RK3188_PULL_BITS_PER_PIN;
+	}
+}
+
 static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
 {
 	struct rockchip_pinctrl *info = bank->drvdata;
 	struct rockchip_pin_ctrl *ctrl = info->ctrl;
 	void __iomem *reg;
 	u8 bit;
+	u32 data;
 
 	/* rk3066b does support any pulls */
-	if (!ctrl->pull_offset)
+	if (ctrl->type == RK3066B)
 		return PIN_CONFIG_BIAS_DISABLE;
 
-	reg = info->reg_base + ctrl->pull_offset;
+	ctrl->pull_calc_reg(bank, pin_num, &reg, &bit);
 
-	if (ctrl->pull_auto) {
-		reg += bank->bank_num * ctrl->pull_bank_stride;
-		reg += (pin_num / 16) * 4;
-		bit = pin_num % 16;
-
+	switch (ctrl->type) {
+	case RK2928:
 		return !(readl_relaxed(reg) & BIT(bit))
 				? PIN_CONFIG_BIAS_PULL_PIN_DEFAULT
 				: PIN_CONFIG_BIAS_DISABLE;
-	} else {
-		dev_err(info->dev, "pull support for rk31xx not implemented\n");
+	case RK3188:
+		data = readl_relaxed(reg) >> bit;
+		data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1;
+
+		switch (data) {
+		case 0:
+			return PIN_CONFIG_BIAS_DISABLE;
+		case 1:
+			return PIN_CONFIG_BIAS_PULL_UP;
+		case 2:
+			return PIN_CONFIG_BIAS_PULL_DOWN;
+		case 3:
+			return PIN_CONFIG_BIAS_BUS_HOLD;
+		}
+
+		dev_err(info->dev, "unknown pull setting\n");
 		return -EIO;
-	}
+	default:
+		dev_err(info->dev, "unsupported pinctrl type\n");
+		return -EINVAL;
+	};
 }
 
 static int rockchip_set_pull(struct rockchip_pin_bank *bank,
@@ -395,22 +469,13 @@
 		 bank->bank_num, pin_num, pull);
 
 	/* rk3066b does support any pulls */
-	if (!ctrl->pull_offset)
+	if (ctrl->type == RK3066B)
 		return pull ? -EINVAL : 0;
 
-	reg = info->reg_base + ctrl->pull_offset;
+	ctrl->pull_calc_reg(bank, pin_num, &reg, &bit);
 
-	if (ctrl->pull_auto) {
-		if (pull != PIN_CONFIG_BIAS_PULL_PIN_DEFAULT &&
-					pull != PIN_CONFIG_BIAS_DISABLE) {
-			dev_err(info->dev, "only PIN_DEFAULT and DISABLE allowed\n");
-			return -EINVAL;
-		}
-
-		reg += bank->bank_num * ctrl->pull_bank_stride;
-		reg += (pin_num / 16) * 4;
-		bit = pin_num % 16;
-
+	switch (ctrl->type) {
+	case RK2928:
 		spin_lock_irqsave(&bank->slock, flags);
 
 		data = BIT(bit + 16);
@@ -419,14 +484,38 @@
 		writel(data, reg);
 
 		spin_unlock_irqrestore(&bank->slock, flags);
-	} else {
-		if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT) {
-			dev_err(info->dev, "pull direction (up/down) needs to be specified\n");
+		break;
+	case RK3188:
+		spin_lock_irqsave(&bank->slock, flags);
+
+		/* enable the write to the equivalent lower bits */
+		data = ((1 << RK3188_PULL_BITS_PER_PIN) - 1) << (bit + 16);
+
+		switch (pull) {
+		case PIN_CONFIG_BIAS_DISABLE:
+			break;
+		case PIN_CONFIG_BIAS_PULL_UP:
+			data |= (1 << bit);
+			break;
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			data |= (2 << bit);
+			break;
+		case PIN_CONFIG_BIAS_BUS_HOLD:
+			data |= (3 << bit);
+			break;
+		default:
+			dev_err(info->dev, "unsupported pull setting %d\n",
+				pull);
 			return -EINVAL;
 		}
 
-		dev_err(info->dev, "pull support for rk31xx not implemented\n");
-		return -EIO;
+		writel(data, reg);
+
+		spin_unlock_irqrestore(&bank->slock, flags);
+		break;
+	default:
+		dev_err(info->dev, "unsupported pinctrl type\n");
+		return -EINVAL;
 	}
 
 	return 0;
@@ -556,20 +645,17 @@
 static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
 					enum pin_config_param pull)
 {
-	/* rk3066b does support any pulls */
-	if (!ctrl->pull_offset)
+	switch (ctrl->type) {
+	case RK2928:
+		return (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT ||
+					pull == PIN_CONFIG_BIAS_DISABLE);
+	case RK3066B:
 		return pull ? false : true;
-
-	if (ctrl->pull_auto) {
-		if (pull != PIN_CONFIG_BIAS_PULL_PIN_DEFAULT &&
-					pull != PIN_CONFIG_BIAS_DISABLE)
-			return false;
-	} else {
-		if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
-			return false;
+	case RK3188:
+		return (pull != PIN_CONFIG_BIAS_PULL_PIN_DEFAULT);
 	}
 
-	return true;
+	return false;
 }
 
 /* set the pin config settings for a specified pin */
@@ -597,6 +683,7 @@
 		case PIN_CONFIG_BIAS_PULL_UP:
 		case PIN_CONFIG_BIAS_PULL_DOWN:
 		case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
+		case PIN_CONFIG_BIAS_BUS_HOLD:
 			if (!rockchip_pinconf_pull_valid(info->ctrl, param))
 				return -ENOTSUPP;
 
@@ -635,6 +722,7 @@
 	case PIN_CONFIG_BIAS_PULL_UP:
 	case PIN_CONFIG_BIAS_PULL_DOWN:
 	case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
+	case PIN_CONFIG_BIAS_BUS_HOLD:
 		if (!rockchip_pinconf_pull_valid(info->ctrl, param))
 			return -ENOTSUPP;
 
@@ -656,7 +744,11 @@
 	.pin_config_set			= rockchip_pinconf_set,
 };
 
-static const char *gpio_compat = "rockchip,gpio-bank";
+static const struct of_device_id rockchip_bank_match[] = {
+	{ .compatible = "rockchip,gpio-bank" },
+	{ .compatible = "rockchip,rk3188-gpio-bank0" },
+	{},
+};
 
 static void rockchip_pinctrl_child_count(struct rockchip_pinctrl *info,
 						struct device_node *np)
@@ -664,7 +756,7 @@
 	struct device_node *child;
 
 	for_each_child_of_node(np, child) {
-		if (of_device_is_compatible(child, gpio_compat))
+		if (of_match_node(rockchip_bank_match, child))
 			continue;
 
 		info->nfunctions++;
@@ -807,8 +899,9 @@
 	i = 0;
 
 	for_each_child_of_node(np, child) {
-		if (of_device_is_compatible(child, gpio_compat))
+		if (of_match_node(rockchip_bank_match, child))
 			continue;
+
 		ret = rockchip_pinctrl_parse_functions(child, info, i++);
 		if (ret) {
 			dev_err(&pdev->dev, "failed to parse function\n");
@@ -985,7 +1078,9 @@
 {
 	struct irq_chip *chip = irq_get_chip(irq);
 	struct rockchip_pin_bank *bank = irq_get_handler_data(irq);
+	u32 polarity = 0, data = 0;
 	u32 pend;
+	bool edge_changed = false;
 
 	dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name);
 
@@ -993,6 +1088,12 @@
 
 	pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS);
 
+	if (bank->toggle_edge_mode) {
+		polarity = readl_relaxed(bank->reg_base +
+					 GPIO_INT_POLARITY);
+		data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT);
+	}
+
 	while (pend) {
 		unsigned int virq;
 
@@ -1007,9 +1108,30 @@
 
 		dev_dbg(bank->drvdata->dev, "handling irq %d\n", irq);
 
+		/*
+		 * Triggering IRQ on both rising and falling edge
+		 * needs manual intervention.
+		 */
+		if (bank->toggle_edge_mode & BIT(irq)) {
+			if (data & BIT(irq))
+				polarity &= ~BIT(irq);
+			else
+				polarity |= BIT(irq);
+
+			edge_changed = true;
+		}
+
 		generic_handle_irq(virq);
 	}
 
+	if (bank->toggle_edge_mode && edge_changed) {
+		/* Interrupt params should only be set with ints disabled */
+		data = readl_relaxed(bank->reg_base + GPIO_INTEN);
+		writel_relaxed(0, bank->reg_base + GPIO_INTEN);
+		writel(polarity, bank->reg_base + GPIO_INT_POLARITY);
+		writel(data, bank->reg_base + GPIO_INTEN);
+	}
+
 	chained_irq_exit(chip, desc);
 }
 
@@ -1022,6 +1144,12 @@
 	u32 level;
 	u32 data;
 
+	/* make sure the pin is configured as gpio input */
+	rockchip_set_mux(bank, d->hwirq, RK_FUNC_GPIO);
+	data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
+	data &= ~mask;
+	writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
+
 	if (type & IRQ_TYPE_EDGE_BOTH)
 		__irq_set_handler_locked(d->irq, handle_edge_irq);
 	else
@@ -1033,19 +1161,37 @@
 	polarity = readl_relaxed(gc->reg_base + GPIO_INT_POLARITY);
 
 	switch (type) {
+	case IRQ_TYPE_EDGE_BOTH:
+		bank->toggle_edge_mode |= mask;
+		level |= mask;
+
+		/*
+		 * Determine gpio state. If 1 next interrupt should be falling
+		 * otherwise rising.
+		 */
+		data = readl(bank->reg_base + GPIO_EXT_PORT);
+		if (data & mask)
+			polarity &= ~mask;
+		else
+			polarity |= mask;
+		break;
 	case IRQ_TYPE_EDGE_RISING:
+		bank->toggle_edge_mode &= ~mask;
 		level |= mask;
 		polarity |= mask;
 		break;
 	case IRQ_TYPE_EDGE_FALLING:
+		bank->toggle_edge_mode &= ~mask;
 		level |= mask;
 		polarity &= ~mask;
 		break;
 	case IRQ_TYPE_LEVEL_HIGH:
+		bank->toggle_edge_mode &= ~mask;
 		level &= ~mask;
 		polarity |= mask;
 		break;
 	case IRQ_TYPE_LEVEL_LOW:
+		bank->toggle_edge_mode &= ~mask;
 		level &= ~mask;
 		polarity &= ~mask;
 		break;
@@ -1059,12 +1205,6 @@
 
 	irq_gc_unlock(gc);
 
-	/* make sure the pin is configured as gpio input */
-	rockchip_set_mux(bank, d->hwirq, RK_FUNC_GPIO);
-	data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR);
-	data &= ~mask;
-	writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR);
-
 	return 0;
 }
 
@@ -1205,6 +1345,26 @@
 	if (IS_ERR(bank->reg_base))
 		return PTR_ERR(bank->reg_base);
 
+	/*
+	 * special case, where parts of the pull setting-registers are
+	 * part of the PMU register space
+	 */
+	if (of_device_is_compatible(bank->of_node,
+				    "rockchip,rk3188-gpio-bank0")) {
+		bank->bank_type = RK3188_BANK0;
+
+		if (of_address_to_resource(bank->of_node, 1, &res)) {
+			dev_err(dev, "cannot find IO resource for bank\n");
+			return -ENOENT;
+		}
+
+		bank->reg_pull = devm_ioremap_resource(dev, &res);
+		if (IS_ERR(bank->reg_pull))
+			return PTR_ERR(bank->reg_pull);
+	} else {
+		bank->bank_type = COMMON_BANK;
+	}
+
 	bank->irq = irq_of_parse_and_map(bank->of_node, 0);
 
 	bank->clk = of_clk_get(bank->of_node, 0);
@@ -1289,6 +1449,14 @@
 	if (IS_ERR(info->reg_base))
 		return PTR_ERR(info->reg_base);
 
+	/* The RK3188 has its pull registers in a separate place */
+	if (ctrl->type == RK3188) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+		info->reg_pull = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(info->reg_base))
+			return PTR_ERR(info->reg_base);
+	}
+
 	ret = rockchip_gpiolib_register(pdev, info);
 	if (ret)
 		return ret;
@@ -1315,10 +1483,9 @@
 		.pin_banks		= rk2928_pin_banks,
 		.nr_banks		= ARRAY_SIZE(rk2928_pin_banks),
 		.label			= "RK2928-GPIO",
+		.type			= RK2928,
 		.mux_offset		= 0xa8,
-		.pull_offset		= 0x118,
-		.pull_auto		= 1,
-		.pull_bank_stride	= 8,
+		.pull_calc_reg		= rk2928_calc_pull_reg_and_bit,
 };
 
 static struct rockchip_pin_bank rk3066a_pin_banks[] = {
@@ -1334,10 +1501,9 @@
 		.pin_banks		= rk3066a_pin_banks,
 		.nr_banks		= ARRAY_SIZE(rk3066a_pin_banks),
 		.label			= "RK3066a-GPIO",
+		.type			= RK2928,
 		.mux_offset		= 0xa8,
-		.pull_offset		= 0x118,
-		.pull_auto		= 1,
-		.pull_bank_stride	= 8,
+		.pull_calc_reg		= rk2928_calc_pull_reg_and_bit,
 };
 
 static struct rockchip_pin_bank rk3066b_pin_banks[] = {
@@ -1351,8 +1517,8 @@
 		.pin_banks	= rk3066b_pin_banks,
 		.nr_banks	= ARRAY_SIZE(rk3066b_pin_banks),
 		.label		= "RK3066b-GPIO",
+		.type		= RK3066B,
 		.mux_offset	= 0x60,
-		.pull_offset	= -EINVAL,
 };
 
 static struct rockchip_pin_bank rk3188_pin_banks[] = {
@@ -1366,9 +1532,9 @@
 		.pin_banks		= rk3188_pin_banks,
 		.nr_banks		= ARRAY_SIZE(rk3188_pin_banks),
 		.label			= "RK3188-GPIO",
+		.type			= RK3188,
 		.mux_offset		= 0x68,
-		.pull_offset		= 0x164,
-		.pull_bank_stride	= 16,
+		.pull_calc_reg		= rk3188_calc_pull_reg_and_bit,
 };
 
 static const struct of_device_id rockchip_pinctrl_dt_match[] = {
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
index 92a9d6c..47ec2e8 100644
--- a/drivers/pinctrl/pinctrl-samsung.c
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -1148,7 +1148,7 @@
 	.driver = {
 		.name	= "samsung-pinctrl",
 		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(samsung_pinctrl_dt_match),
+		.of_match_table = samsung_pinctrl_dt_match,
 	},
 };
 
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index a82ace4..0846922 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -15,15 +15,21 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/list.h>
+#include <linux/interrupt.h>
+
+#include <linux/irqchip/chained_irq.h>
 
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
 #include <linux/pinctrl/pinconf-generic.h>
 
+#include <linux/platform_data/pinctrl-single.h>
+
 #include "core.h"
 #include "pinconf.h"
 
@@ -150,19 +156,36 @@
 };
 
 /**
+ * struct pcs_soc_data - SoC specific settings
+ * @flags:	initial SoC specific PCS_FEAT_xxx values
+ * @irq:	optional interrupt for the controller
+ * @irq_enable_mask:	optional SoC specific interrupt enable mask
+ * @irq_status_mask:	optional SoC specific interrupt status mask
+ * @rearm:	optional SoC specific wake-up rearm function
+ */
+struct pcs_soc_data {
+	unsigned flags;
+	int irq;
+	unsigned irq_enable_mask;
+	unsigned irq_status_mask;
+	void (*rearm)(void);
+};
+
+/**
  * struct pcs_device - pinctrl device instance
  * @res:	resources
  * @base:	virtual address of the controller
  * @size:	size of the ioremapped area
  * @dev:	device entry
  * @pctl:	pin controller device
+ * @flags:	mask of PCS_FEAT_xxx values
+ * @lock:	spinlock for register access
  * @mutex:	mutex protecting the lists
  * @width:	bits per mux register
  * @fmask:	function register mask
  * @fshift:	function register shift
  * @foff:	value to turn mux off
  * @fmax:	max number of functions in fmask
- * @is_pinconf:	whether supports pinconf
  * @bits_per_pin:number of bits per pin
  * @names:	array of register names for pins
  * @pins:	physical pins on the SoC
@@ -171,6 +194,9 @@
  * @pingroups:	list of pingroups
  * @functions:	list of functions
  * @gpiofuncs:	list of gpio functions
+ * @irqs:	list of interrupt registers
+ * @chip:	chip container for this instance
+ * @domain:	IRQ domain for this instance
  * @ngroups:	number of pingroups
  * @nfuncs:	number of functions
  * @desc:	pin controller descriptor
@@ -183,6 +209,12 @@
 	unsigned size;
 	struct device *dev;
 	struct pinctrl_dev *pctl;
+	unsigned flags;
+#define PCS_QUIRK_SHARED_IRQ	(1 << 2)
+#define PCS_FEAT_IRQ		(1 << 1)
+#define PCS_FEAT_PINCONF	(1 << 0)
+	struct pcs_soc_data socdata;
+	raw_spinlock_t lock;
 	struct mutex mutex;
 	unsigned width;
 	unsigned fmask;
@@ -190,7 +222,6 @@
 	unsigned foff;
 	unsigned fmax;
 	bool bits_per_mux;
-	bool is_pinconf;
 	unsigned bits_per_pin;
 	struct pcs_name *names;
 	struct pcs_data pins;
@@ -199,6 +230,9 @@
 	struct list_head pingroups;
 	struct list_head functions;
 	struct list_head gpiofuncs;
+	struct list_head irqs;
+	struct irq_chip chip;
+	struct irq_domain *domain;
 	unsigned ngroups;
 	unsigned nfuncs;
 	struct pinctrl_desc desc;
@@ -206,6 +240,10 @@
 	void (*write)(unsigned val, void __iomem *reg);
 };
 
+#define PCS_QUIRK_HAS_SHARED_IRQ	(pcs->flags & PCS_QUIRK_SHARED_IRQ)
+#define PCS_HAS_IRQ		(pcs->flags & PCS_FEAT_IRQ)
+#define PCS_HAS_PINCONF		(pcs->flags & PCS_FEAT_PINCONF)
+
 static int pcs_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin,
 			   unsigned long *config);
 static int pcs_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin,
@@ -429,9 +467,11 @@
 
 	for (i = 0; i < func->nvals; i++) {
 		struct pcs_func_vals *vals;
+		unsigned long flags;
 		unsigned val, mask;
 
 		vals = &func->vals[i];
+		raw_spin_lock_irqsave(&pcs->lock, flags);
 		val = pcs->read(vals->reg);
 
 		if (pcs->bits_per_mux)
@@ -442,6 +482,7 @@
 		val &= ~mask;
 		val |= (vals->val & mask);
 		pcs->write(val, vals->reg);
+		raw_spin_unlock_irqrestore(&pcs->lock, flags);
 	}
 
 	return 0;
@@ -483,13 +524,16 @@
 
 	for (i = 0; i < func->nvals; i++) {
 		struct pcs_func_vals *vals;
+		unsigned long flags;
 		unsigned val;
 
 		vals = &func->vals[i];
+		raw_spin_lock_irqsave(&pcs->lock, flags);
 		val = pcs->read(vals->reg);
 		val &= ~pcs->fmask;
 		val |= pcs->foff << pcs->fshift;
 		pcs->write(val, vals->reg);
+		raw_spin_unlock_irqrestore(&pcs->lock, flags);
 	}
 }
 
@@ -1060,7 +1104,7 @@
 	};
 
 	/* If pinconf isn't supported, don't parse properties in below. */
-	if (!pcs->is_pinconf)
+	if (!PCS_HAS_PINCONF)
 		return 0;
 
 	/* cacluate how much properties are supported in current node */
@@ -1184,7 +1228,7 @@
 	(*map)->data.mux.group = np->name;
 	(*map)->data.mux.function = np->name;
 
-	if (pcs->is_pinconf) {
+	if (PCS_HAS_PINCONF) {
 		res = pcs_parse_pinconf(pcs, np, function, map);
 		if (res)
 			goto free_pingroups;
@@ -1305,7 +1349,7 @@
 	(*map)->data.mux.group = np->name;
 	(*map)->data.mux.function = np->name;
 
-	if (pcs->is_pinconf) {
+	if (PCS_HAS_PINCONF) {
 		dev_err(pcs->dev, "pinconf not supported\n");
 		goto free_pingroups;
 	}
@@ -1440,11 +1484,33 @@
 }
 
 /**
+ * pcs_irq_free() - free interrupt
+ * @pcs: pcs driver instance
+ */
+static void pcs_irq_free(struct pcs_device *pcs)
+{
+	struct pcs_soc_data *pcs_soc = &pcs->socdata;
+
+	if (pcs_soc->irq < 0)
+		return;
+
+	if (pcs->domain)
+		irq_domain_remove(pcs->domain);
+
+	if (PCS_QUIRK_HAS_SHARED_IRQ)
+		free_irq(pcs_soc->irq, pcs_soc);
+	else
+		irq_set_chained_handler(pcs_soc->irq, NULL);
+}
+
+/**
  * pcs_free_resources() - free memory used by this driver
  * @pcs: pcs driver instance
  */
 static void pcs_free_resources(struct pcs_device *pcs)
 {
+	pcs_irq_free(pcs);
+
 	if (pcs->pctl)
 		pinctrl_unregister(pcs->pctl);
 
@@ -1493,6 +1559,268 @@
 	}
 	return ret;
 }
+/**
+ * @reg:	virtual address of interrupt register
+ * @hwirq:	hardware irq number
+ * @irq:	virtual irq number
+ * @node:	list node
+ */
+struct pcs_interrupt {
+	void __iomem *reg;
+	irq_hw_number_t hwirq;
+	unsigned int irq;
+	struct list_head node;
+};
+
+/**
+ * pcs_irq_set() - enables or disables an interrupt
+ *
+ * Note that this currently assumes one interrupt per pinctrl
+ * register that is typically used for wake-up events.
+ */
+static inline void pcs_irq_set(struct pcs_soc_data *pcs_soc,
+			       int irq, const bool enable)
+{
+	struct pcs_device *pcs;
+	struct list_head *pos;
+	unsigned mask;
+
+	pcs = container_of(pcs_soc, struct pcs_device, socdata);
+	list_for_each(pos, &pcs->irqs) {
+		struct pcs_interrupt *pcswi;
+		unsigned soc_mask;
+
+		pcswi = list_entry(pos, struct pcs_interrupt, node);
+		if (irq != pcswi->irq)
+			continue;
+
+		soc_mask = pcs_soc->irq_enable_mask;
+		raw_spin_lock(&pcs->lock);
+		mask = pcs->read(pcswi->reg);
+		if (enable)
+			mask |= soc_mask;
+		else
+			mask &= ~soc_mask;
+		pcs->write(mask, pcswi->reg);
+		raw_spin_unlock(&pcs->lock);
+	}
+}
+
+/**
+ * pcs_irq_mask() - mask pinctrl interrupt
+ * @d: interrupt data
+ */
+static void pcs_irq_mask(struct irq_data *d)
+{
+	struct pcs_soc_data *pcs_soc = irq_data_get_irq_chip_data(d);
+
+	pcs_irq_set(pcs_soc, d->irq, false);
+}
+
+/**
+ * pcs_irq_unmask() - unmask pinctrl interrupt
+ * @d: interrupt data
+ */
+static void pcs_irq_unmask(struct irq_data *d)
+{
+	struct pcs_soc_data *pcs_soc = irq_data_get_irq_chip_data(d);
+
+	pcs_irq_set(pcs_soc, d->irq, true);
+	if (pcs_soc->rearm)
+		pcs_soc->rearm();
+}
+
+/**
+ * pcs_irq_set_wake() - toggle the suspend and resume wake up
+ * @d: interrupt data
+ * @state: wake-up state
+ *
+ * Note that this should be called only for suspend and resume.
+ * For runtime PM, the wake-up events should be enabled by default.
+ */
+static int pcs_irq_set_wake(struct irq_data *d, unsigned int state)
+{
+	if (state)
+		pcs_irq_unmask(d);
+	else
+		pcs_irq_mask(d);
+
+	return 0;
+}
+
+/**
+ * pcs_irq_handle() - common interrupt handler
+ * @pcs_irq: interrupt data
+ *
+ * Note that this currently assumes we have one interrupt bit per
+ * mux register. This interrupt is typically used for wake-up events.
+ * For more complex interrupts different handlers can be specified.
+ */
+static int pcs_irq_handle(struct pcs_soc_data *pcs_soc)
+{
+	struct pcs_device *pcs;
+	struct list_head *pos;
+	int count = 0;
+
+	pcs = container_of(pcs_soc, struct pcs_device, socdata);
+	list_for_each(pos, &pcs->irqs) {
+		struct pcs_interrupt *pcswi;
+		unsigned mask;
+
+		pcswi = list_entry(pos, struct pcs_interrupt, node);
+		raw_spin_lock(&pcs->lock);
+		mask = pcs->read(pcswi->reg);
+		raw_spin_unlock(&pcs->lock);
+		if (mask & pcs_soc->irq_status_mask) {
+			generic_handle_irq(irq_find_mapping(pcs->domain,
+							    pcswi->hwirq));
+			count++;
+		}
+	}
+
+	/*
+	 * For debugging on omaps, you may want to call pcs_soc->rearm()
+	 * here to see wake-up interrupts during runtime also.
+	 */
+
+	return count;
+}
+
+/**
+ * pcs_irq_handler() - handler for the shared interrupt case
+ * @irq: interrupt
+ * @d: data
+ *
+ * Use this for cases where multiple instances of
+ * pinctrl-single share a single interrupt like on omaps.
+ */
+static irqreturn_t pcs_irq_handler(int irq, void *d)
+{
+	struct pcs_soc_data *pcs_soc = d;
+
+	return pcs_irq_handle(pcs_soc) ? IRQ_HANDLED : IRQ_NONE;
+}
+
+/**
+ * pcs_irq_handle() - handler for the dedicated chained interrupt case
+ * @irq: interrupt
+ * @desc: interrupt descriptor
+ *
+ * Use this if you have a separate interrupt for each
+ * pinctrl-single instance.
+ */
+static void pcs_irq_chain_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct pcs_soc_data *pcs_soc = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip;
+	int res;
+
+	chip = irq_get_chip(irq);
+	chained_irq_enter(chip, desc);
+	res = pcs_irq_handle(pcs_soc);
+	/* REVISIT: export and add handle_bad_irq(irq, desc)? */
+	chained_irq_exit(chip, desc);
+
+	return;
+}
+
+static int pcs_irqdomain_map(struct irq_domain *d, unsigned int irq,
+			     irq_hw_number_t hwirq)
+{
+	struct pcs_soc_data *pcs_soc = d->host_data;
+	struct pcs_device *pcs;
+	struct pcs_interrupt *pcswi;
+
+	pcs = container_of(pcs_soc, struct pcs_device, socdata);
+	pcswi = devm_kzalloc(pcs->dev, sizeof(*pcswi), GFP_KERNEL);
+	if (!pcswi)
+		return -ENOMEM;
+
+	pcswi->reg = pcs->base + hwirq;
+	pcswi->hwirq = hwirq;
+	pcswi->irq = irq;
+
+	mutex_lock(&pcs->mutex);
+	list_add_tail(&pcswi->node, &pcs->irqs);
+	mutex_unlock(&pcs->mutex);
+
+	irq_set_chip_data(irq, pcs_soc);
+	irq_set_chip_and_handler(irq, &pcs->chip,
+				 handle_level_irq);
+
+#ifdef CONFIG_ARM
+	set_irq_flags(irq, IRQF_VALID);
+#else
+	irq_set_noprobe(irq);
+#endif
+
+	return 0;
+}
+
+static struct irq_domain_ops pcs_irqdomain_ops = {
+	.map = pcs_irqdomain_map,
+	.xlate = irq_domain_xlate_onecell,
+};
+
+/**
+ * pcs_irq_init_chained_handler() - set up a chained interrupt handler
+ * @pcs: pcs driver instance
+ * @np: device node pointer
+ */
+static int pcs_irq_init_chained_handler(struct pcs_device *pcs,
+					struct device_node *np)
+{
+	struct pcs_soc_data *pcs_soc = &pcs->socdata;
+	const char *name = "pinctrl";
+	int num_irqs;
+
+	if (!pcs_soc->irq_enable_mask ||
+	    !pcs_soc->irq_status_mask) {
+		pcs_soc->irq = -1;
+		return -EINVAL;
+	}
+
+	INIT_LIST_HEAD(&pcs->irqs);
+	pcs->chip.name = name;
+	pcs->chip.irq_ack = pcs_irq_mask;
+	pcs->chip.irq_mask = pcs_irq_mask;
+	pcs->chip.irq_unmask = pcs_irq_unmask;
+	pcs->chip.irq_set_wake = pcs_irq_set_wake;
+
+	if (PCS_QUIRK_HAS_SHARED_IRQ) {
+		int res;
+
+		res = request_irq(pcs_soc->irq, pcs_irq_handler,
+				  IRQF_SHARED | IRQF_NO_SUSPEND,
+				  name, pcs_soc);
+		if (res) {
+			pcs_soc->irq = -1;
+			return res;
+		}
+	} else {
+		irq_set_handler_data(pcs_soc->irq, pcs_soc);
+		irq_set_chained_handler(pcs_soc->irq,
+					pcs_irq_chain_handler);
+	}
+
+	/*
+	 * We can use the register offset as the hardirq
+	 * number as irq_domain_add_simple maps them lazily.
+	 * This way we can easily support more than one
+	 * interrupt per function if needed.
+	 */
+	num_irqs = pcs->size;
+
+	pcs->domain = irq_domain_add_simple(np, num_irqs, 0,
+					    &pcs_irqdomain_ops,
+					    pcs_soc);
+	if (!pcs->domain) {
+		irq_set_chained_handler(pcs_soc->irq, NULL);
+		return -EINVAL;
+	}
+
+	return 0;
+}
 
 #ifdef CONFIG_PM
 static int pinctrl_single_suspend(struct platform_device *pdev,
@@ -1523,8 +1851,10 @@
 {
 	struct device_node *np = pdev->dev.of_node;
 	const struct of_device_id *match;
+	struct pcs_pdata *pdata;
 	struct resource *res;
 	struct pcs_device *pcs;
+	const struct pcs_soc_data *soc;
 	int ret;
 
 	match = of_match_device(pcs_of_match, &pdev->dev);
@@ -1537,11 +1867,14 @@
 		return -ENOMEM;
 	}
 	pcs->dev = &pdev->dev;
+	raw_spin_lock_init(&pcs->lock);
 	mutex_init(&pcs->mutex);
 	INIT_LIST_HEAD(&pcs->pingroups);
 	INIT_LIST_HEAD(&pcs->functions);
 	INIT_LIST_HEAD(&pcs->gpiofuncs);
-	pcs->is_pinconf = match->data;
+	soc = match->data;
+	pcs->flags = soc->flags;
+	memcpy(&pcs->socdata, soc, sizeof(*soc));
 
 	PCS_GET_PROP_U32("pinctrl-single,register-width", &pcs->width,
 			 "register width not specified\n");
@@ -1610,7 +1943,7 @@
 	pcs->desc.name = DRIVER_NAME;
 	pcs->desc.pctlops = &pcs_pinctrl_ops;
 	pcs->desc.pmxops = &pcs_pinmux_ops;
-	if (pcs->is_pinconf)
+	if (PCS_HAS_PINCONF)
 		pcs->desc.confops = &pcs_pinconf_ops;
 	pcs->desc.owner = THIS_MODULE;
 
@@ -1629,6 +1962,27 @@
 	if (ret < 0)
 		goto free;
 
+	pcs->socdata.irq = irq_of_parse_and_map(np, 0);
+	if (pcs->socdata.irq)
+		pcs->flags |= PCS_FEAT_IRQ;
+
+	/* We still need auxdata for some omaps for PRM interrupts */
+	pdata = dev_get_platdata(&pdev->dev);
+	if (pdata) {
+		if (pdata->rearm)
+			pcs->socdata.rearm = pdata->rearm;
+		if (pdata->irq) {
+			pcs->socdata.irq = pdata->irq;
+			pcs->flags |= PCS_FEAT_IRQ;
+		}
+	}
+
+	if (PCS_HAS_IRQ) {
+		ret = pcs_irq_init_chained_handler(pcs, np);
+		if (ret < 0)
+			dev_warn(pcs->dev, "initialized with no interrupts\n");
+	}
+
 	dev_info(pcs->dev, "%i pins at pa %p size %u\n",
 		 pcs->desc.npins, pcs->base, pcs->size);
 
@@ -1652,9 +2006,25 @@
 	return 0;
 }
 
+static const struct pcs_soc_data pinctrl_single_omap_wkup = {
+	.flags = PCS_QUIRK_SHARED_IRQ,
+	.irq_enable_mask = (1 << 14),	/* OMAP_WAKEUP_EN */
+	.irq_status_mask = (1 << 15),	/* OMAP_WAKEUP_EVENT */
+};
+
+static const struct pcs_soc_data pinctrl_single = {
+};
+
+static const struct pcs_soc_data pinconf_single = {
+	.flags = PCS_FEAT_PINCONF,
+};
+
 static struct of_device_id pcs_of_match[] = {
-	{ .compatible = "pinctrl-single", .data = (void *)false },
-	{ .compatible = "pinconf-single", .data = (void *)true },
+	{ .compatible = "ti,omap3-padconf", .data = &pinctrl_single_omap_wkup },
+	{ .compatible = "ti,omap4-padconf", .data = &pinctrl_single_omap_wkup },
+	{ .compatible = "ti,omap5-padconf", .data = &pinctrl_single_omap_wkup },
+	{ .compatible = "pinctrl-single", .data = &pinctrl_single },
+	{ .compatible = "pinconf-single", .data = &pinconf_single },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, pcs_of_match);
diff --git a/drivers/pinctrl/pinctrl-tb10x.c b/drivers/pinctrl/pinctrl-tb10x.c
new file mode 100644
index 0000000..c5e0f69
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-tb10x.c
@@ -0,0 +1,875 @@
+/*
+ * Abilis Systems TB10x pin control driver
+ *
+ * Copyright (C) Abilis Systems 2012
+ *
+ * Author: Christian Ruppert <christian.ruppert@abilis.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/stringify.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#include "pinctrl-utils.h"
+
+#define TB10X_PORT1 (0)
+#define TB10X_PORT2 (16)
+#define TB10X_PORT3 (32)
+#define TB10X_PORT4 (48)
+#define TB10X_PORT5 (128)
+#define TB10X_PORT6 (64)
+#define TB10X_PORT7 (80)
+#define TB10X_PORT8 (96)
+#define TB10X_PORT9 (112)
+#define TB10X_GPIOS (256)
+
+#define PCFG_PORT_BITWIDTH (2)
+#define PCFG_PORT_MASK(PORT) \
+	(((1 << PCFG_PORT_BITWIDTH) - 1) << (PCFG_PORT_BITWIDTH * (PORT)))
+
+static const struct pinctrl_pin_desc tb10x_pins[] = {
+	/* Port 1 */
+	PINCTRL_PIN(TB10X_PORT1 +  0, "MICLK_S0"),
+	PINCTRL_PIN(TB10X_PORT1 +  1, "MISTRT_S0"),
+	PINCTRL_PIN(TB10X_PORT1 +  2, "MIVAL_S0"),
+	PINCTRL_PIN(TB10X_PORT1 +  3, "MDI_S0"),
+	PINCTRL_PIN(TB10X_PORT1 +  4, "GPIOA0"),
+	PINCTRL_PIN(TB10X_PORT1 +  5, "GPIOA1"),
+	PINCTRL_PIN(TB10X_PORT1 +  6, "GPIOA2"),
+	PINCTRL_PIN(TB10X_PORT1 +  7, "MDI_S1"),
+	PINCTRL_PIN(TB10X_PORT1 +  8, "MIVAL_S1"),
+	PINCTRL_PIN(TB10X_PORT1 +  9, "MISTRT_S1"),
+	PINCTRL_PIN(TB10X_PORT1 + 10, "MICLK_S1"),
+	/* Port 2 */
+	PINCTRL_PIN(TB10X_PORT2 +  0, "MICLK_S2"),
+	PINCTRL_PIN(TB10X_PORT2 +  1, "MISTRT_S2"),
+	PINCTRL_PIN(TB10X_PORT2 +  2, "MIVAL_S2"),
+	PINCTRL_PIN(TB10X_PORT2 +  3, "MDI_S2"),
+	PINCTRL_PIN(TB10X_PORT2 +  4, "GPIOC0"),
+	PINCTRL_PIN(TB10X_PORT2 +  5, "GPIOC1"),
+	PINCTRL_PIN(TB10X_PORT2 +  6, "GPIOC2"),
+	PINCTRL_PIN(TB10X_PORT2 +  7, "MDI_S3"),
+	PINCTRL_PIN(TB10X_PORT2 +  8, "MIVAL_S3"),
+	PINCTRL_PIN(TB10X_PORT2 +  9, "MISTRT_S3"),
+	PINCTRL_PIN(TB10X_PORT2 + 10, "MICLK_S3"),
+	/* Port 3 */
+	PINCTRL_PIN(TB10X_PORT3 +  0, "MICLK_S4"),
+	PINCTRL_PIN(TB10X_PORT3 +  1, "MISTRT_S4"),
+	PINCTRL_PIN(TB10X_PORT3 +  2, "MIVAL_S4"),
+	PINCTRL_PIN(TB10X_PORT3 +  3, "MDI_S4"),
+	PINCTRL_PIN(TB10X_PORT3 +  4, "GPIOE0"),
+	PINCTRL_PIN(TB10X_PORT3 +  5, "GPIOE1"),
+	PINCTRL_PIN(TB10X_PORT3 +  6, "GPIOE2"),
+	PINCTRL_PIN(TB10X_PORT3 +  7, "MDI_S5"),
+	PINCTRL_PIN(TB10X_PORT3 +  8, "MIVAL_S5"),
+	PINCTRL_PIN(TB10X_PORT3 +  9, "MISTRT_S5"),
+	PINCTRL_PIN(TB10X_PORT3 + 10, "MICLK_S5"),
+	/* Port 4 */
+	PINCTRL_PIN(TB10X_PORT4 +  0, "MICLK_S6"),
+	PINCTRL_PIN(TB10X_PORT4 +  1, "MISTRT_S6"),
+	PINCTRL_PIN(TB10X_PORT4 +  2, "MIVAL_S6"),
+	PINCTRL_PIN(TB10X_PORT4 +  3, "MDI_S6"),
+	PINCTRL_PIN(TB10X_PORT4 +  4, "GPIOG0"),
+	PINCTRL_PIN(TB10X_PORT4 +  5, "GPIOG1"),
+	PINCTRL_PIN(TB10X_PORT4 +  6, "GPIOG2"),
+	PINCTRL_PIN(TB10X_PORT4 +  7, "MDI_S7"),
+	PINCTRL_PIN(TB10X_PORT4 +  8, "MIVAL_S7"),
+	PINCTRL_PIN(TB10X_PORT4 +  9, "MISTRT_S7"),
+	PINCTRL_PIN(TB10X_PORT4 + 10, "MICLK_S7"),
+	/* Port 5 */
+	PINCTRL_PIN(TB10X_PORT5 +  0, "PC_CE1N"),
+	PINCTRL_PIN(TB10X_PORT5 +  1, "PC_CE2N"),
+	PINCTRL_PIN(TB10X_PORT5 +  2, "PC_REGN"),
+	PINCTRL_PIN(TB10X_PORT5 +  3, "PC_INPACKN"),
+	PINCTRL_PIN(TB10X_PORT5 +  4, "PC_OEN"),
+	PINCTRL_PIN(TB10X_PORT5 +  5, "PC_WEN"),
+	PINCTRL_PIN(TB10X_PORT5 +  6, "PC_IORDN"),
+	PINCTRL_PIN(TB10X_PORT5 +  7, "PC_IOWRN"),
+	PINCTRL_PIN(TB10X_PORT5 +  8, "PC_RDYIRQN"),
+	PINCTRL_PIN(TB10X_PORT5 +  9, "PC_WAITN"),
+	PINCTRL_PIN(TB10X_PORT5 + 10, "PC_A0"),
+	PINCTRL_PIN(TB10X_PORT5 + 11, "PC_A1"),
+	PINCTRL_PIN(TB10X_PORT5 + 12, "PC_A2"),
+	PINCTRL_PIN(TB10X_PORT5 + 13, "PC_A3"),
+	PINCTRL_PIN(TB10X_PORT5 + 14, "PC_A4"),
+	PINCTRL_PIN(TB10X_PORT5 + 15, "PC_A5"),
+	PINCTRL_PIN(TB10X_PORT5 + 16, "PC_A6"),
+	PINCTRL_PIN(TB10X_PORT5 + 17, "PC_A7"),
+	PINCTRL_PIN(TB10X_PORT5 + 18, "PC_A8"),
+	PINCTRL_PIN(TB10X_PORT5 + 19, "PC_A9"),
+	PINCTRL_PIN(TB10X_PORT5 + 20, "PC_A10"),
+	PINCTRL_PIN(TB10X_PORT5 + 21, "PC_A11"),
+	PINCTRL_PIN(TB10X_PORT5 + 22, "PC_A12"),
+	PINCTRL_PIN(TB10X_PORT5 + 23, "PC_A13"),
+	PINCTRL_PIN(TB10X_PORT5 + 24, "PC_A14"),
+	PINCTRL_PIN(TB10X_PORT5 + 25, "PC_D0"),
+	PINCTRL_PIN(TB10X_PORT5 + 26, "PC_D1"),
+	PINCTRL_PIN(TB10X_PORT5 + 27, "PC_D2"),
+	PINCTRL_PIN(TB10X_PORT5 + 28, "PC_D3"),
+	PINCTRL_PIN(TB10X_PORT5 + 29, "PC_D4"),
+	PINCTRL_PIN(TB10X_PORT5 + 30, "PC_D5"),
+	PINCTRL_PIN(TB10X_PORT5 + 31, "PC_D6"),
+	PINCTRL_PIN(TB10X_PORT5 + 32, "PC_D7"),
+	PINCTRL_PIN(TB10X_PORT5 + 33, "PC_MOSTRT"),
+	PINCTRL_PIN(TB10X_PORT5 + 34, "PC_MOVAL"),
+	PINCTRL_PIN(TB10X_PORT5 + 35, "PC_MDO0"),
+	PINCTRL_PIN(TB10X_PORT5 + 36, "PC_MDO1"),
+	PINCTRL_PIN(TB10X_PORT5 + 37, "PC_MDO2"),
+	PINCTRL_PIN(TB10X_PORT5 + 38, "PC_MDO3"),
+	PINCTRL_PIN(TB10X_PORT5 + 39, "PC_MDO4"),
+	PINCTRL_PIN(TB10X_PORT5 + 40, "PC_MDO5"),
+	PINCTRL_PIN(TB10X_PORT5 + 41, "PC_MDO6"),
+	PINCTRL_PIN(TB10X_PORT5 + 42, "PC_MDO7"),
+	PINCTRL_PIN(TB10X_PORT5 + 43, "PC_MISTRT"),
+	PINCTRL_PIN(TB10X_PORT5 + 44, "PC_MIVAL"),
+	PINCTRL_PIN(TB10X_PORT5 + 45, "PC_MDI0"),
+	PINCTRL_PIN(TB10X_PORT5 + 46, "PC_MDI1"),
+	PINCTRL_PIN(TB10X_PORT5 + 47, "PC_MDI2"),
+	PINCTRL_PIN(TB10X_PORT5 + 48, "PC_MDI3"),
+	PINCTRL_PIN(TB10X_PORT5 + 49, "PC_MDI4"),
+	PINCTRL_PIN(TB10X_PORT5 + 50, "PC_MDI5"),
+	PINCTRL_PIN(TB10X_PORT5 + 51, "PC_MDI6"),
+	PINCTRL_PIN(TB10X_PORT5 + 52, "PC_MDI7"),
+	PINCTRL_PIN(TB10X_PORT5 + 53, "PC_MICLK"),
+	/* Port 6 */
+	PINCTRL_PIN(TB10X_PORT6 + 0, "T_MOSTRT_S0"),
+	PINCTRL_PIN(TB10X_PORT6 + 1, "T_MOVAL_S0"),
+	PINCTRL_PIN(TB10X_PORT6 + 2, "T_MDO_S0"),
+	PINCTRL_PIN(TB10X_PORT6 + 3, "T_MOSTRT_S1"),
+	PINCTRL_PIN(TB10X_PORT6 + 4, "T_MOVAL_S1"),
+	PINCTRL_PIN(TB10X_PORT6 + 5, "T_MDO_S1"),
+	PINCTRL_PIN(TB10X_PORT6 + 6, "T_MOSTRT_S2"),
+	PINCTRL_PIN(TB10X_PORT6 + 7, "T_MOVAL_S2"),
+	PINCTRL_PIN(TB10X_PORT6 + 8, "T_MDO_S2"),
+	PINCTRL_PIN(TB10X_PORT6 + 9, "T_MOSTRT_S3"),
+	/* Port 7 */
+	PINCTRL_PIN(TB10X_PORT7 + 0, "UART0_TXD"),
+	PINCTRL_PIN(TB10X_PORT7 + 1, "UART0_RXD"),
+	PINCTRL_PIN(TB10X_PORT7 + 2, "UART0_CTS"),
+	PINCTRL_PIN(TB10X_PORT7 + 3, "UART0_RTS"),
+	PINCTRL_PIN(TB10X_PORT7 + 4, "UART1_TXD"),
+	PINCTRL_PIN(TB10X_PORT7 + 5, "UART1_RXD"),
+	PINCTRL_PIN(TB10X_PORT7 + 6, "UART1_CTS"),
+	PINCTRL_PIN(TB10X_PORT7 + 7, "UART1_RTS"),
+	/* Port 8 */
+	PINCTRL_PIN(TB10X_PORT8 + 0, "SPI3_CLK"),
+	PINCTRL_PIN(TB10X_PORT8 + 1, "SPI3_MISO"),
+	PINCTRL_PIN(TB10X_PORT8 + 2, "SPI3_MOSI"),
+	PINCTRL_PIN(TB10X_PORT8 + 3, "SPI3_SSN"),
+	/* Port 9 */
+	PINCTRL_PIN(TB10X_PORT9 + 0, "SPI1_CLK"),
+	PINCTRL_PIN(TB10X_PORT9 + 1, "SPI1_MISO"),
+	PINCTRL_PIN(TB10X_PORT9 + 2, "SPI1_MOSI"),
+	PINCTRL_PIN(TB10X_PORT9 + 3, "SPI1_SSN0"),
+	PINCTRL_PIN(TB10X_PORT9 + 4, "SPI1_SSN1"),
+	/* Unmuxed GPIOs */
+	PINCTRL_PIN(TB10X_GPIOS +  0, "GPIOB0"),
+	PINCTRL_PIN(TB10X_GPIOS +  1, "GPIOB1"),
+
+	PINCTRL_PIN(TB10X_GPIOS +  2, "GPIOD0"),
+	PINCTRL_PIN(TB10X_GPIOS +  3, "GPIOD1"),
+
+	PINCTRL_PIN(TB10X_GPIOS +  4, "GPIOF0"),
+	PINCTRL_PIN(TB10X_GPIOS +  5, "GPIOF1"),
+
+	PINCTRL_PIN(TB10X_GPIOS +  6, "GPIOH0"),
+	PINCTRL_PIN(TB10X_GPIOS +  7, "GPIOH1"),
+
+	PINCTRL_PIN(TB10X_GPIOS +  8, "GPIOI0"),
+	PINCTRL_PIN(TB10X_GPIOS +  9, "GPIOI1"),
+	PINCTRL_PIN(TB10X_GPIOS + 10, "GPIOI2"),
+	PINCTRL_PIN(TB10X_GPIOS + 11, "GPIOI3"),
+	PINCTRL_PIN(TB10X_GPIOS + 12, "GPIOI4"),
+	PINCTRL_PIN(TB10X_GPIOS + 13, "GPIOI5"),
+	PINCTRL_PIN(TB10X_GPIOS + 14, "GPIOI6"),
+	PINCTRL_PIN(TB10X_GPIOS + 15, "GPIOI7"),
+	PINCTRL_PIN(TB10X_GPIOS + 16, "GPIOI8"),
+	PINCTRL_PIN(TB10X_GPIOS + 17, "GPIOI9"),
+	PINCTRL_PIN(TB10X_GPIOS + 18, "GPIOI10"),
+	PINCTRL_PIN(TB10X_GPIOS + 19, "GPIOI11"),
+
+	PINCTRL_PIN(TB10X_GPIOS + 20, "GPION0"),
+	PINCTRL_PIN(TB10X_GPIOS + 21, "GPION1"),
+	PINCTRL_PIN(TB10X_GPIOS + 22, "GPION2"),
+	PINCTRL_PIN(TB10X_GPIOS + 23, "GPION3"),
+#define MAX_PIN (TB10X_GPIOS + 24)
+	PINCTRL_PIN(MAX_PIN,  "GPION4"),
+};
+
+
+/* Port 1 */
+static const unsigned mis0_pins[]  = {	TB10X_PORT1 + 0, TB10X_PORT1 + 1,
+					TB10X_PORT1 + 2, TB10X_PORT1 + 3};
+static const unsigned gpioa_pins[] = {	TB10X_PORT1 + 4, TB10X_PORT1 + 5,
+					TB10X_PORT1 + 6};
+static const unsigned mis1_pins[]  = {	TB10X_PORT1 + 7, TB10X_PORT1 + 8,
+					TB10X_PORT1 + 9, TB10X_PORT1 + 10};
+static const unsigned mip1_pins[]  = {	TB10X_PORT1 + 0, TB10X_PORT1 + 1,
+					TB10X_PORT1 + 2, TB10X_PORT1 + 3,
+					TB10X_PORT1 + 4, TB10X_PORT1 + 5,
+					TB10X_PORT1 + 6, TB10X_PORT1 + 7,
+					TB10X_PORT1 + 8, TB10X_PORT1 + 9,
+					TB10X_PORT1 + 10};
+
+/* Port 2 */
+static const unsigned mis2_pins[]  = {	TB10X_PORT2 + 0, TB10X_PORT2 + 1,
+					TB10X_PORT2 + 2, TB10X_PORT2 + 3};
+static const unsigned gpioc_pins[] = {	TB10X_PORT2 + 4, TB10X_PORT2 + 5,
+					TB10X_PORT2 + 6};
+static const unsigned mis3_pins[]  = {	TB10X_PORT2 + 7, TB10X_PORT2 + 8,
+					TB10X_PORT2 + 9, TB10X_PORT2 + 10};
+static const unsigned mip3_pins[]  = {	TB10X_PORT2 + 0, TB10X_PORT2 + 1,
+					TB10X_PORT2 + 2, TB10X_PORT2 + 3,
+					TB10X_PORT2 + 4, TB10X_PORT2 + 5,
+					TB10X_PORT2 + 6, TB10X_PORT2 + 7,
+					TB10X_PORT2 + 8, TB10X_PORT2 + 9,
+					TB10X_PORT2 + 10};
+
+/* Port 3 */
+static const unsigned mis4_pins[]  = {	TB10X_PORT3 + 0, TB10X_PORT3 + 1,
+					TB10X_PORT3 + 2, TB10X_PORT3 + 3};
+static const unsigned gpioe_pins[] = {	TB10X_PORT3 + 4, TB10X_PORT3 + 5,
+					TB10X_PORT3 + 6};
+static const unsigned mis5_pins[]  = {	TB10X_PORT3 + 7, TB10X_PORT3 + 8,
+					TB10X_PORT3 + 9, TB10X_PORT3 + 10};
+static const unsigned mip5_pins[]  = {	TB10X_PORT3 + 0, TB10X_PORT3 + 1,
+					TB10X_PORT3 + 2, TB10X_PORT3 + 3,
+					TB10X_PORT3 + 4, TB10X_PORT3 + 5,
+					TB10X_PORT3 + 6, TB10X_PORT3 + 7,
+					TB10X_PORT3 + 8, TB10X_PORT3 + 9,
+					TB10X_PORT3 + 10};
+
+/* Port 4 */
+static const unsigned mis6_pins[]  = {	TB10X_PORT4 + 0, TB10X_PORT4 + 1,
+					TB10X_PORT4 + 2, TB10X_PORT4 + 3};
+static const unsigned gpiog_pins[] = {	TB10X_PORT4 + 4, TB10X_PORT4 + 5,
+					TB10X_PORT4 + 6};
+static const unsigned mis7_pins[]  = {	TB10X_PORT4 + 7, TB10X_PORT4 + 8,
+					TB10X_PORT4 + 9, TB10X_PORT4 + 10};
+static const unsigned mip7_pins[]  = {	TB10X_PORT4 + 0, TB10X_PORT4 + 1,
+					TB10X_PORT4 + 2, TB10X_PORT4 + 3,
+					TB10X_PORT4 + 4, TB10X_PORT4 + 5,
+					TB10X_PORT4 + 6, TB10X_PORT4 + 7,
+					TB10X_PORT4 + 8, TB10X_PORT4 + 9,
+					TB10X_PORT4 + 10};
+
+/* Port 6 */
+static const unsigned mop_pins[] = {	TB10X_PORT6 + 0, TB10X_PORT6 + 1,
+					TB10X_PORT6 + 2, TB10X_PORT6 + 3,
+					TB10X_PORT6 + 4, TB10X_PORT6 + 5,
+					TB10X_PORT6 + 6, TB10X_PORT6 + 7,
+					TB10X_PORT6 + 8, TB10X_PORT6 + 9};
+static const unsigned mos0_pins[] = {	TB10X_PORT6 + 0, TB10X_PORT6 + 1,
+					TB10X_PORT6 + 2};
+static const unsigned mos1_pins[] = {	TB10X_PORT6 + 3, TB10X_PORT6 + 4,
+					TB10X_PORT6 + 5};
+static const unsigned mos2_pins[] = {	TB10X_PORT6 + 6, TB10X_PORT6 + 7,
+					TB10X_PORT6 + 8};
+static const unsigned mos3_pins[] = {	TB10X_PORT6 + 9};
+
+/* Port 7 */
+static const unsigned uart0_pins[] = {	TB10X_PORT7 + 0, TB10X_PORT7 + 1,
+					TB10X_PORT7 + 2, TB10X_PORT7 + 3};
+static const unsigned uart1_pins[] = {	TB10X_PORT7 + 4, TB10X_PORT7 + 5,
+					TB10X_PORT7 + 6, TB10X_PORT7 + 7};
+static const unsigned gpiol_pins[] = {	TB10X_PORT7 + 0, TB10X_PORT7 + 1,
+					TB10X_PORT7 + 2, TB10X_PORT7 + 3};
+static const unsigned gpiom_pins[] = {	TB10X_PORT7 + 4, TB10X_PORT7 + 5,
+					TB10X_PORT7 + 6, TB10X_PORT7 + 7};
+
+/* Port 8 */
+static const unsigned spi3_pins[] = {	TB10X_PORT8 + 0, TB10X_PORT8 + 1,
+					TB10X_PORT8 + 2, TB10X_PORT8 + 3};
+static const unsigned jtag_pins[] = {	TB10X_PORT8 + 0, TB10X_PORT8 + 1,
+					TB10X_PORT8 + 2, TB10X_PORT8 + 3};
+
+/* Port 9 */
+static const unsigned spi1_pins[] = {	TB10X_PORT9 + 0, TB10X_PORT9 + 1,
+					TB10X_PORT9 + 2, TB10X_PORT9 + 3,
+					TB10X_PORT9 + 4};
+static const unsigned gpion_pins[] = {	TB10X_PORT9 + 0, TB10X_PORT9 + 1,
+					TB10X_PORT9 + 2, TB10X_PORT9 + 3,
+					TB10X_PORT9 + 4};
+
+/* Port 5 */
+static const unsigned gpioj_pins[] = {	TB10X_PORT5 + 0, TB10X_PORT5 + 1,
+					TB10X_PORT5 + 2, TB10X_PORT5 + 3,
+					TB10X_PORT5 + 4, TB10X_PORT5 + 5,
+					TB10X_PORT5 + 6, TB10X_PORT5 + 7,
+					TB10X_PORT5 + 8, TB10X_PORT5 + 9,
+					TB10X_PORT5 + 10, TB10X_PORT5 + 11,
+					TB10X_PORT5 + 12, TB10X_PORT5 + 13,
+					TB10X_PORT5 + 14, TB10X_PORT5 + 15,
+					TB10X_PORT5 + 16, TB10X_PORT5 + 17,
+					TB10X_PORT5 + 18, TB10X_PORT5 + 19,
+					TB10X_PORT5 + 20, TB10X_PORT5 + 21,
+					TB10X_PORT5 + 22, TB10X_PORT5 + 23,
+					TB10X_PORT5 + 24, TB10X_PORT5 + 25,
+					TB10X_PORT5 + 26, TB10X_PORT5 + 27,
+					TB10X_PORT5 + 28, TB10X_PORT5 + 29,
+					TB10X_PORT5 + 30, TB10X_PORT5 + 31};
+static const unsigned gpiok_pins[] = {	TB10X_PORT5 + 32, TB10X_PORT5 + 33,
+					TB10X_PORT5 + 34, TB10X_PORT5 + 35,
+					TB10X_PORT5 + 36, TB10X_PORT5 + 37,
+					TB10X_PORT5 + 38, TB10X_PORT5 + 39,
+					TB10X_PORT5 + 40, TB10X_PORT5 + 41,
+					TB10X_PORT5 + 42, TB10X_PORT5 + 43,
+					TB10X_PORT5 + 44, TB10X_PORT5 + 45,
+					TB10X_PORT5 + 46, TB10X_PORT5 + 47,
+					TB10X_PORT5 + 48, TB10X_PORT5 + 49,
+					TB10X_PORT5 + 50, TB10X_PORT5 + 51,
+					TB10X_PORT5 + 52, TB10X_PORT5 + 53};
+static const unsigned ciplus_pins[] = {	TB10X_PORT5 + 0, TB10X_PORT5 + 1,
+					TB10X_PORT5 + 2, TB10X_PORT5 + 3,
+					TB10X_PORT5 + 4, TB10X_PORT5 + 5,
+					TB10X_PORT5 + 6, TB10X_PORT5 + 7,
+					TB10X_PORT5 + 8, TB10X_PORT5 + 9,
+					TB10X_PORT5 + 10, TB10X_PORT5 + 11,
+					TB10X_PORT5 + 12, TB10X_PORT5 + 13,
+					TB10X_PORT5 + 14, TB10X_PORT5 + 15,
+					TB10X_PORT5 + 16, TB10X_PORT5 + 17,
+					TB10X_PORT5 + 18, TB10X_PORT5 + 19,
+					TB10X_PORT5 + 20, TB10X_PORT5 + 21,
+					TB10X_PORT5 + 22, TB10X_PORT5 + 23,
+					TB10X_PORT5 + 24, TB10X_PORT5 + 25,
+					TB10X_PORT5 + 26, TB10X_PORT5 + 27,
+					TB10X_PORT5 + 28, TB10X_PORT5 + 29,
+					TB10X_PORT5 + 30, TB10X_PORT5 + 31,
+					TB10X_PORT5 + 32, TB10X_PORT5 + 33,
+					TB10X_PORT5 + 34, TB10X_PORT5 + 35,
+					TB10X_PORT5 + 36, TB10X_PORT5 + 37,
+					TB10X_PORT5 + 38, TB10X_PORT5 + 39,
+					TB10X_PORT5 + 40, TB10X_PORT5 + 41,
+					TB10X_PORT5 + 42, TB10X_PORT5 + 43,
+					TB10X_PORT5 + 44, TB10X_PORT5 + 45,
+					TB10X_PORT5 + 46, TB10X_PORT5 + 47,
+					TB10X_PORT5 + 48, TB10X_PORT5 + 49,
+					TB10X_PORT5 + 50, TB10X_PORT5 + 51,
+					TB10X_PORT5 + 52, TB10X_PORT5 + 53};
+static const unsigned mcard_pins[] = {	TB10X_PORT5 + 3, TB10X_PORT5 + 10,
+					TB10X_PORT5 + 11, TB10X_PORT5 + 12,
+					TB10X_PORT5 + 22, TB10X_PORT5 + 23,
+					TB10X_PORT5 + 33, TB10X_PORT5 + 35,
+					TB10X_PORT5 + 36, TB10X_PORT5 + 37,
+					TB10X_PORT5 + 38, TB10X_PORT5 + 39,
+					TB10X_PORT5 + 40, TB10X_PORT5 + 41,
+					TB10X_PORT5 + 42, TB10X_PORT5 + 43,
+					TB10X_PORT5 + 45, TB10X_PORT5 + 46,
+					TB10X_PORT5 + 47, TB10X_PORT5 + 48,
+					TB10X_PORT5 + 49, TB10X_PORT5 + 50,
+					TB10X_PORT5 + 51, TB10X_PORT5 + 52,
+					TB10X_PORT5 + 53};
+static const unsigned stc0_pins[] = {	TB10X_PORT5 + 34, TB10X_PORT5 + 35,
+					TB10X_PORT5 + 36, TB10X_PORT5 + 37,
+					TB10X_PORT5 + 38, TB10X_PORT5 + 39,
+					TB10X_PORT5 + 40};
+static const unsigned stc1_pins[] = {	TB10X_PORT5 + 25, TB10X_PORT5 + 26,
+					TB10X_PORT5 + 27, TB10X_PORT5 + 28,
+					TB10X_PORT5 + 29, TB10X_PORT5 + 30,
+					TB10X_PORT5 + 44};
+
+/* Unmuxed GPIOs */
+static const unsigned gpiob_pins[] = {	TB10X_GPIOS + 0, TB10X_GPIOS + 1};
+static const unsigned gpiod_pins[] = {	TB10X_GPIOS + 2, TB10X_GPIOS + 3};
+static const unsigned gpiof_pins[] = {	TB10X_GPIOS + 4, TB10X_GPIOS + 5};
+static const unsigned gpioh_pins[] = {	TB10X_GPIOS + 6, TB10X_GPIOS + 7};
+static const unsigned gpioi_pins[] = {	TB10X_GPIOS + 8, TB10X_GPIOS + 9,
+					TB10X_GPIOS + 10, TB10X_GPIOS + 11,
+					TB10X_GPIOS + 12, TB10X_GPIOS + 13,
+					TB10X_GPIOS + 14, TB10X_GPIOS + 15,
+					TB10X_GPIOS + 16, TB10X_GPIOS + 17,
+					TB10X_GPIOS + 18, TB10X_GPIOS + 19};
+
+struct tb10x_pinfuncgrp {
+	const char *name;
+	const unsigned int *pins;
+	const unsigned int pincnt;
+	const int port;
+	const unsigned int mode;
+	const int isgpio;
+};
+#define DEFPINFUNCGRP(NAME, PORT, MODE, ISGPIO) { \
+		.name = __stringify(NAME), \
+		.pins = NAME##_pins, .pincnt = ARRAY_SIZE(NAME##_pins), \
+		.port = (PORT), .mode = (MODE), \
+		.isgpio = (ISGPIO), \
+	}
+static const struct tb10x_pinfuncgrp tb10x_pingroups[] = {
+	DEFPINFUNCGRP(mis0,   0, 0, 0),
+	DEFPINFUNCGRP(gpioa,  0, 0, 1),
+	DEFPINFUNCGRP(mis1,   0, 0, 0),
+	DEFPINFUNCGRP(mip1,   0, 1, 0),
+	DEFPINFUNCGRP(mis2,   1, 0, 0),
+	DEFPINFUNCGRP(gpioc,  1, 0, 1),
+	DEFPINFUNCGRP(mis3,   1, 0, 0),
+	DEFPINFUNCGRP(mip3,   1, 1, 0),
+	DEFPINFUNCGRP(mis4,   2, 0, 0),
+	DEFPINFUNCGRP(gpioe,  2, 0, 1),
+	DEFPINFUNCGRP(mis5,   2, 0, 0),
+	DEFPINFUNCGRP(mip5,   2, 1, 0),
+	DEFPINFUNCGRP(mis6,   3, 0, 0),
+	DEFPINFUNCGRP(gpiog,  3, 0, 1),
+	DEFPINFUNCGRP(mis7,   3, 0, 0),
+	DEFPINFUNCGRP(mip7,   3, 1, 0),
+	DEFPINFUNCGRP(gpioj,  4, 0, 1),
+	DEFPINFUNCGRP(gpiok,  4, 0, 1),
+	DEFPINFUNCGRP(ciplus, 4, 1, 0),
+	DEFPINFUNCGRP(mcard,  4, 2, 0),
+	DEFPINFUNCGRP(stc0,   4, 3, 0),
+	DEFPINFUNCGRP(stc1,   4, 3, 0),
+	DEFPINFUNCGRP(mop,    5, 0, 0),
+	DEFPINFUNCGRP(mos0,   5, 1, 0),
+	DEFPINFUNCGRP(mos1,   5, 1, 0),
+	DEFPINFUNCGRP(mos2,   5, 1, 0),
+	DEFPINFUNCGRP(mos3,   5, 1, 0),
+	DEFPINFUNCGRP(uart0,  6, 0, 0),
+	DEFPINFUNCGRP(uart1,  6, 0, 0),
+	DEFPINFUNCGRP(gpiol,  6, 1, 1),
+	DEFPINFUNCGRP(gpiom,  6, 1, 1),
+	DEFPINFUNCGRP(spi3,   7, 0, 0),
+	DEFPINFUNCGRP(jtag,   7, 1, 0),
+	DEFPINFUNCGRP(spi1,   8, 0, 0),
+	DEFPINFUNCGRP(gpion,  8, 1, 1),
+	DEFPINFUNCGRP(gpiob, -1, 0, 1),
+	DEFPINFUNCGRP(gpiod, -1, 0, 1),
+	DEFPINFUNCGRP(gpiof, -1, 0, 1),
+	DEFPINFUNCGRP(gpioh, -1, 0, 1),
+	DEFPINFUNCGRP(gpioi, -1, 0, 1),
+};
+#undef DEFPINFUNCGRP
+
+struct tb10x_of_pinfunc {
+	const char *name;
+	const char *group;
+};
+
+#define TB10X_PORTS (9)
+
+/**
+ * struct tb10x_port - state of an I/O port
+ * @mode: Node this port is currently in.
+ * @count: Number of enabled functions which require this port to be
+ *         configured in @mode.
+ */
+struct tb10x_port {
+	unsigned int mode;
+	unsigned int count;
+};
+
+/**
+ * struct tb10x_pinctrl - TB10x pin controller internal state
+ * @pctl: pointer to the pinctrl_dev structure of this pin controller.
+ * @base: register set base address.
+ * @pingroups: pointer to an array of the pin groups this driver manages.
+ * @pinfuncgrpcnt: number of pingroups in @pingroups.
+ * @pinfuncs: pointer to an array of pin functions this driver manages.
+ * @pinfuncnt: number of pin functions in @pinfuncs.
+ * @mutex: mutex for exclusive access to a pin controller's state.
+ * @ports: current state of each port.
+ * @gpios: Indicates if a given pin is currently used as GPIO (1) or not (0).
+ */
+struct tb10x_pinctrl {
+	struct pinctrl_dev *pctl;
+	void *base;
+	const struct tb10x_pinfuncgrp *pingroups;
+	unsigned int pinfuncgrpcnt;
+	struct tb10x_of_pinfunc *pinfuncs;
+	unsigned int pinfuncnt;
+	struct mutex mutex;
+	struct tb10x_port ports[TB10X_PORTS];
+	DECLARE_BITMAP(gpios, MAX_PIN + 1);
+};
+
+static inline void tb10x_pinctrl_set_config(struct tb10x_pinctrl *state,
+				unsigned int port, unsigned int mode)
+{
+	u32 pcfg;
+
+	if (state->ports[port].count)
+		return;
+
+	state->ports[port].mode = mode;
+
+	pcfg = ioread32(state->base) & ~(PCFG_PORT_MASK(port));
+	pcfg |= (mode << (PCFG_PORT_BITWIDTH * port)) & PCFG_PORT_MASK(port);
+	iowrite32(pcfg, state->base);
+}
+
+static inline unsigned int tb10x_pinctrl_get_config(
+				struct tb10x_pinctrl *state,
+				unsigned int port)
+{
+	return (ioread32(state->base) & PCFG_PORT_MASK(port))
+		>> (PCFG_PORT_BITWIDTH * port);
+}
+
+static int tb10x_get_groups_count(struct pinctrl_dev *pctl)
+{
+	struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
+	return state->pinfuncgrpcnt;
+}
+
+static const char *tb10x_get_group_name(struct pinctrl_dev *pctl, unsigned n)
+{
+	struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
+	return state->pingroups[n].name;
+}
+
+static int tb10x_get_group_pins(struct pinctrl_dev *pctl, unsigned n,
+				unsigned const **pins,
+				unsigned * const num_pins)
+{
+	struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
+
+	*pins = state->pingroups[n].pins;
+	*num_pins = state->pingroups[n].pincnt;
+
+	return 0;
+}
+
+static int tb10x_dt_node_to_map(struct pinctrl_dev *pctl,
+				struct device_node *np_config,
+				struct pinctrl_map **map, unsigned *num_maps)
+{
+	const char *string;
+	unsigned reserved_maps = 0;
+	int ret = 0;
+
+	if (of_property_read_string(np_config, "abilis,function", &string)) {
+		pr_err("%s: No abilis,function property in device tree.\n",
+			np_config->full_name);
+		return -EINVAL;
+	}
+
+	*map = NULL;
+	*num_maps = 0;
+
+	ret = pinctrl_utils_reserve_map(pctl, map, &reserved_maps,
+					num_maps, 1);
+	if (ret)
+		goto out;
+
+	ret = pinctrl_utils_add_map_mux(pctl, map, &reserved_maps,
+					num_maps, string, np_config->name);
+
+out:
+	return ret;
+}
+
+static struct pinctrl_ops tb10x_pinctrl_ops = {
+	.get_groups_count = tb10x_get_groups_count,
+	.get_group_name   = tb10x_get_group_name,
+	.get_group_pins   = tb10x_get_group_pins,
+	.dt_node_to_map   = tb10x_dt_node_to_map,
+	.dt_free_map      = pinctrl_utils_dt_free_map,
+};
+
+static int tb10x_get_functions_count(struct pinctrl_dev *pctl)
+{
+	struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
+	return state->pinfuncnt;
+}
+
+static const char *tb10x_get_function_name(struct pinctrl_dev *pctl,
+					unsigned n)
+{
+	struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
+	return state->pinfuncs[n].name;
+}
+
+static int tb10x_get_function_groups(struct pinctrl_dev *pctl,
+				unsigned n, const char * const **groups,
+				unsigned * const num_groups)
+{
+	struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
+
+	*groups = &state->pinfuncs[n].group;
+	*num_groups = 1;
+
+	return 0;
+}
+
+static int tb10x_gpio_request_enable(struct pinctrl_dev *pctl,
+					struct pinctrl_gpio_range *range,
+					unsigned pin)
+{
+	struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
+	int muxport = -1;
+	int muxmode = -1;
+	int i;
+
+	mutex_lock(&state->mutex);
+
+	/*
+	 * Figure out to which port the requested GPIO belongs and how to
+	 * configure that port.
+	 * This loop also checks for pin conflicts between GPIOs and other
+	 * functions.
+	 */
+	for (i = 0; i < state->pinfuncgrpcnt; i++) {
+		const struct tb10x_pinfuncgrp *pfg = &state->pingroups[i];
+		unsigned int port = pfg->port;
+		unsigned int mode = pfg->mode;
+		int j;
+
+		/*
+		 * Skip pin groups which are always mapped and don't need
+		 * to be configured.
+		 */
+		if (port < 0)
+			continue;
+
+		for (j = 0; j < pfg->pincnt; j++) {
+			if (pin == pfg->pins[j]) {
+				if (pfg->isgpio) {
+					/*
+					 * Remember the GPIO-only setting of
+					 * the port this pin belongs to.
+					 */
+					muxport = port;
+					muxmode = mode;
+				} else if (state->ports[port].count
+					&& (state->ports[port].mode == mode)) {
+					/*
+					 * Error: The requested pin is already
+					 * used for something else.
+					 */
+					mutex_unlock(&state->mutex);
+					return -EBUSY;
+				}
+				break;
+			}
+		}
+	}
+
+	/*
+	 * If we haven't returned an error at this point, the GPIO pin is not
+	 * used by another function and the GPIO request can be granted:
+	 * Register pin as being used as GPIO so we don't allocate it to
+	 * another function later.
+	 */
+	set_bit(pin, state->gpios);
+
+	/*
+	 * Potential conflicts between GPIOs and pin functions were caught
+	 * earlier in this function and tb10x_pinctrl_set_config will do the
+	 * Right Thing, either configure the port in GPIO only mode or leave
+	 * another mode compatible with this GPIO request untouched.
+	 */
+	if (muxport >= 0)
+		tb10x_pinctrl_set_config(state, muxport, muxmode);
+
+	mutex_unlock(&state->mutex);
+
+	return 0;
+}
+
+static void tb10x_gpio_disable_free(struct pinctrl_dev *pctl,
+					struct pinctrl_gpio_range *range,
+					unsigned pin)
+{
+	struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
+
+	mutex_lock(&state->mutex);
+
+	clear_bit(pin, state->gpios);
+
+	mutex_unlock(&state->mutex);
+}
+
+static int tb10x_pctl_enable(struct pinctrl_dev *pctl,
+			unsigned func_selector, unsigned group_selector)
+{
+	struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
+	const struct tb10x_pinfuncgrp *grp = &state->pingroups[group_selector];
+	int i;
+
+	if (grp->port < 0)
+		return 0;
+
+	mutex_lock(&state->mutex);
+
+	/*
+	 * Check if the requested function is compatible with previously
+	 * requested functions.
+	 */
+	if (state->ports[grp->port].count
+			&& (state->ports[grp->port].mode != grp->mode)) {
+		mutex_unlock(&state->mutex);
+		return -EBUSY;
+	}
+
+	/*
+	 * Check if the requested function is compatible with previously
+	 * requested GPIOs.
+	 */
+	for (i = 0; i < grp->pincnt; i++)
+		if (test_bit(grp->pins[i], state->gpios)) {
+			mutex_unlock(&state->mutex);
+			return -EBUSY;
+		}
+
+	tb10x_pinctrl_set_config(state, grp->port, grp->mode);
+
+	state->ports[grp->port].count++;
+
+	mutex_unlock(&state->mutex);
+
+	return 0;
+}
+
+static void tb10x_pctl_disable(struct pinctrl_dev *pctl,
+			unsigned func_selector, unsigned group_selector)
+{
+	struct tb10x_pinctrl *state = pinctrl_dev_get_drvdata(pctl);
+	const struct tb10x_pinfuncgrp *grp = &state->pingroups[group_selector];
+
+	if (grp->port < 0)
+		return;
+
+	mutex_lock(&state->mutex);
+
+	state->ports[grp->port].count--;
+
+	mutex_unlock(&state->mutex);
+}
+
+static struct pinmux_ops tb10x_pinmux_ops = {
+	.get_functions_count = tb10x_get_functions_count,
+	.get_function_name = tb10x_get_function_name,
+	.get_function_groups = tb10x_get_function_groups,
+	.gpio_request_enable = tb10x_gpio_request_enable,
+	.gpio_disable_free = tb10x_gpio_disable_free,
+	.enable = tb10x_pctl_enable,
+	.disable = tb10x_pctl_disable,
+};
+
+static struct pinctrl_desc tb10x_pindesc = {
+	.name = "TB10x",
+	.pins = tb10x_pins,
+	.npins = ARRAY_SIZE(tb10x_pins),
+	.owner = THIS_MODULE,
+	.pctlops = &tb10x_pinctrl_ops,
+	.pmxops  = &tb10x_pinmux_ops,
+};
+
+static int tb10x_pinctrl_probe(struct platform_device *pdev)
+{
+	int ret = -EINVAL;
+	struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	struct device *dev = &pdev->dev;
+	struct device_node *of_node = dev->of_node;
+	struct device_node *child;
+	struct tb10x_pinctrl *state;
+	int i;
+
+	if (!of_node) {
+		dev_err(dev, "No device tree node found.\n");
+		return -EINVAL;
+	}
+
+	if (!mem) {
+		dev_err(dev, "No memory resource defined.\n");
+		return -EINVAL;
+	}
+
+	state = devm_kzalloc(dev, sizeof(struct tb10x_pinctrl) +
+					of_get_child_count(of_node)
+					* sizeof(struct tb10x_of_pinfunc),
+				GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, state);
+	state->pinfuncs = (struct tb10x_of_pinfunc *)(state + 1);
+	mutex_init(&state->mutex);
+
+	state->base = devm_ioremap_resource(dev, mem);
+	if (IS_ERR(state->base)) {
+		ret = PTR_ERR(state->base);
+		goto fail;
+	}
+
+	state->pingroups = tb10x_pingroups;
+	state->pinfuncgrpcnt = ARRAY_SIZE(tb10x_pingroups);
+
+	for (i = 0; i < TB10X_PORTS; i++)
+		state->ports[i].mode = tb10x_pinctrl_get_config(state, i);
+
+	for_each_child_of_node(of_node, child) {
+		const char *name;
+
+		if (!of_property_read_string(child, "abilis,function",
+						&name)) {
+			state->pinfuncs[state->pinfuncnt].name = child->name;
+			state->pinfuncs[state->pinfuncnt].group = name;
+			state->pinfuncnt++;
+		}
+	}
+
+	state->pctl = pinctrl_register(&tb10x_pindesc, dev, state);
+	if (!state->pctl) {
+		dev_err(dev, "could not register TB10x pin driver\n");
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	return 0;
+
+fail:
+	mutex_destroy(&state->mutex);
+	return ret;
+}
+
+static int tb10x_pinctrl_remove(struct platform_device *pdev)
+{
+	struct tb10x_pinctrl *state = platform_get_drvdata(pdev);
+
+	pinctrl_unregister(state->pctl);
+	mutex_destroy(&state->mutex);
+
+	return 0;
+}
+
+
+static const struct of_device_id tb10x_pinctrl_dt_ids[] = {
+	{ .compatible = "abilis,tb10x-iomux" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, tb10x_pinctrl_dt_ids);
+
+static struct platform_driver tb10x_pinctrl_pdrv = {
+	.probe   = tb10x_pinctrl_probe,
+	.remove  = tb10x_pinctrl_remove,
+	.driver  = {
+		.name  = "tb10x_pinctrl",
+		.of_match_table = of_match_ptr(tb10x_pinctrl_dt_ids),
+		.owner = THIS_MODULE
+	}
+};
+
+module_platform_driver(tb10x_pinctrl_pdrv);
+
+MODULE_AUTHOR("Christian Ruppert <christian.ruppert@abilis.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/pinctrl-vf610.c b/drivers/pinctrl/pinctrl-vf610.c
index 68a970b..bddd913 100644
--- a/drivers/pinctrl/pinctrl-vf610.c
+++ b/drivers/pinctrl/pinctrl-vf610.c
@@ -316,7 +316,7 @@
 	.driver = {
 		.name = "vf610-pinctrl",
 		.owner = THIS_MODULE,
-		.of_match_table = of_match_ptr(vf610_pinctrl_of_match),
+		.of_match_table = vf610_pinctrl_of_match,
 	},
 	.probe = vf610_pinctrl_probe,
 	.remove = imx_pinctrl_remove,
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index 9d144a2..9248ce4 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -505,16 +505,14 @@
 			pin_free(pctldev, pins[i], NULL);
 		} else {
 			const char *gname;
-			const char *pname;
 
-			pname = desc ? desc->name : "non-existing";
 			gname = pctlops->get_group_name(pctldev,
 						setting->data.mux.group);
 			dev_warn(pctldev->dev,
 				 "not freeing pin %d (%s) as part of "
 				 "deactivating group %s - it is already "
 				 "used for some other setting",
-				 pins[i], pname, gname);
+				 pins[i], desc->name, gname);
 		}
 	}
 
diff --git a/drivers/pinctrl/sh-pfc/Kconfig b/drivers/pinctrl/sh-pfc/Kconfig
index 636a882..26187aa 100644
--- a/drivers/pinctrl/sh-pfc/Kconfig
+++ b/drivers/pinctrl/sh-pfc/Kconfig
@@ -45,6 +45,11 @@
 	depends on ARCH_R8A7790
 	select PINCTRL_SH_PFC
 
+config PINCTRL_PFC_R8A7791
+	def_bool y
+	depends on ARCH_R8A7791
+	select PINCTRL_SH_PFC
+
 config PINCTRL_PFC_SH7203
 	def_bool y
 	depends on CPU_SUBTYPE_SH7203
diff --git a/drivers/pinctrl/sh-pfc/Makefile b/drivers/pinctrl/sh-pfc/Makefile
index 5e0c222..ad8f4cf 100644
--- a/drivers/pinctrl/sh-pfc/Makefile
+++ b/drivers/pinctrl/sh-pfc/Makefile
@@ -8,6 +8,7 @@
 obj-$(CONFIG_PINCTRL_PFC_R8A7778)	+= pfc-r8a7778.o
 obj-$(CONFIG_PINCTRL_PFC_R8A7779)	+= pfc-r8a7779.o
 obj-$(CONFIG_PINCTRL_PFC_R8A7790)	+= pfc-r8a7790.o
+obj-$(CONFIG_PINCTRL_PFC_R8A7791)	+= pfc-r8a7791.o
 obj-$(CONFIG_PINCTRL_PFC_SH7203)	+= pfc-sh7203.o
 obj-$(CONFIG_PINCTRL_PFC_SH7264)	+= pfc-sh7264.o
 obj-$(CONFIG_PINCTRL_PFC_SH7269)	+= pfc-sh7269.o
diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c
index 738f14f..d77ece5 100644
--- a/drivers/pinctrl/sh-pfc/core.c
+++ b/drivers/pinctrl/sh-pfc/core.c
@@ -431,6 +431,12 @@
 		.data = &r8a7790_pinmux_info,
 	},
 #endif
+#ifdef CONFIG_PINCTRL_PFC_R8A7791
+	{
+		.compatible = "renesas,pfc-r8a7791",
+		.data = &r8a7791_pinmux_info,
+	},
+#endif
 #ifdef CONFIG_PINCTRL_PFC_SH7372
 	{
 		.compatible = "renesas,pfc-sh7372",
@@ -558,6 +564,9 @@
 #ifdef CONFIG_PINCTRL_PFC_R8A7790
 	{ "pfc-r8a7790", (kernel_ulong_t)&r8a7790_pinmux_info },
 #endif
+#ifdef CONFIG_PINCTRL_PFC_R8A7791
+	{ "pfc-r8a7791", (kernel_ulong_t)&r8a7791_pinmux_info },
+#endif
 #ifdef CONFIG_PINCTRL_PFC_SH7203
 	{ "pfc-sh7203", (kernel_ulong_t)&sh7203_pinmux_info },
 #endif
diff --git a/drivers/pinctrl/sh-pfc/core.h b/drivers/pinctrl/sh-pfc/core.h
index a1b2376..11ea872 100644
--- a/drivers/pinctrl/sh-pfc/core.h
+++ b/drivers/pinctrl/sh-pfc/core.h
@@ -69,6 +69,7 @@
 extern const struct sh_pfc_soc_info r8a7778_pinmux_info;
 extern const struct sh_pfc_soc_info r8a7779_pinmux_info;
 extern const struct sh_pfc_soc_info r8a7790_pinmux_info;
+extern const struct sh_pfc_soc_info r8a7791_pinmux_info;
 extern const struct sh_pfc_soc_info sh7203_pinmux_info;
 extern const struct sh_pfc_soc_info sh7264_pinmux_info;
 extern const struct sh_pfc_soc_info sh7269_pinmux_info;
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7778.c b/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
index 428d2a6..8b1881c 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
@@ -1288,6 +1288,49 @@
 						     arg5##_MARK, arg6##_MARK, \
 						     arg7##_MARK, arg8##_MARK, }
 
+/* - AUDIO macro -------------------------------------------------------------*/
+#define AUDIO_PFC_PIN(name, pin)	SH_PFC_PINS(name, pin)
+#define AUDIO_PFC_DAT(name, pin)	SH_PFC_MUX1(name, pin)
+
+/* - AUDIO clock -------------------------------------------------------------*/
+AUDIO_PFC_PIN(audio_clk_a,	RCAR_GP_PIN(2, 22));
+AUDIO_PFC_DAT(audio_clk_a,	AUDIO_CLKA);
+AUDIO_PFC_PIN(audio_clk_b,	RCAR_GP_PIN(2, 23));
+AUDIO_PFC_DAT(audio_clk_b,	AUDIO_CLKB);
+AUDIO_PFC_PIN(audio_clk_c,	RCAR_GP_PIN(2, 7));
+AUDIO_PFC_DAT(audio_clk_c,	AUDIO_CLKC);
+AUDIO_PFC_PIN(audio_clkout_a,	RCAR_GP_PIN(2, 16));
+AUDIO_PFC_DAT(audio_clkout_a,	AUDIO_CLKOUT_A);
+AUDIO_PFC_PIN(audio_clkout_b,	RCAR_GP_PIN(1, 16));
+AUDIO_PFC_DAT(audio_clkout_b,	AUDIO_CLKOUT_B);
+
+/* - CAN macro --------_----------------------------------------------------- */
+#define CAN_PFC_PINS(name, args...)		SH_PFC_PINS(name, args)
+#define CAN_PFC_DATA(name, tx, rx)		SH_PFC_MUX2(name, tx, rx)
+#define CAN_PFC_CLK(name, clk)			SH_PFC_MUX1(name, clk)
+
+/* - CAN0 ------------------------------------------------------------------- */
+CAN_PFC_PINS(can0_data_a,	RCAR_GP_PIN(1, 30),	RCAR_GP_PIN(1, 31));
+CAN_PFC_DATA(can0_data_a,	CAN0_TX_A,		CAN0_RX_A);
+CAN_PFC_PINS(can0_data_b,	RCAR_GP_PIN(2, 26),	RCAR_GP_PIN(2, 27));
+CAN_PFC_DATA(can0_data_b,	CAN0_TX_B,		CAN0_RX_B);
+
+/* - CAN1 ------------------------------------------------------------------- */
+CAN_PFC_PINS(can1_data_a,	RCAR_GP_PIN(4, 20),	RCAR_GP_PIN(4, 19));
+CAN_PFC_DATA(can1_data_a,	CAN1_TX_A,		CAN1_RX_A);
+CAN_PFC_PINS(can1_data_b,	RCAR_GP_PIN(2, 28),	RCAR_GP_PIN(2, 29));
+CAN_PFC_DATA(can1_data_b,	CAN1_TX_B,		CAN1_RX_B);
+
+/* - CAN_CLK  --------------------------------------------------------------- */
+CAN_PFC_PINS(can_clk_a,		RCAR_GP_PIN(3, 24));
+CAN_PFC_CLK(can_clk_a,		CAN_CLK_A);
+CAN_PFC_PINS(can_clk_b,		RCAR_GP_PIN(1, 16));
+CAN_PFC_CLK(can_clk_b,		CAN_CLK_B);
+CAN_PFC_PINS(can_clk_c,		RCAR_GP_PIN(4, 24));
+CAN_PFC_CLK(can_clk_c,		CAN_CLK_C);
+CAN_PFC_PINS(can_clk_d,		RCAR_GP_PIN(2, 25));
+CAN_PFC_CLK(can_clk_d,		CAN_CLK_D);
+
 /* - Ether ------------------------------------------------------------------ */
 SH_PFC_PINS(ether_rmii,		RCAR_GP_PIN(4, 10),	RCAR_GP_PIN(4, 11),
 				RCAR_GP_PIN(4, 13),	RCAR_GP_PIN(4, 9),
@@ -1577,6 +1620,59 @@
 SDHI_PFC_PINS(sdhi2_wp_b,	RCAR_GP_PIN(3, 28));
 SDHI_PFC_WPPN(sdhi2_wp_b,	SD2_WP_B);
 
+/* - SSI macro -------------------------------------------------------------- */
+#define SSI_PFC_PINS(name, args...)		SH_PFC_PINS(name, args)
+#define SSI_PFC_CTRL(name, sck, ws)		SH_PFC_MUX2(name, sck, ws)
+#define SSI_PFC_DATA(name, d)			SH_PFC_MUX1(name, d)
+
+/* - SSI 0/1/2 -------------------------------------------------------------- */
+SSI_PFC_PINS(ssi012_ctrl,	RCAR_GP_PIN(3, 6),	RCAR_GP_PIN(3, 7));
+SSI_PFC_CTRL(ssi012_ctrl,	SSI_SCK012,		SSI_WS012);
+SSI_PFC_PINS(ssi0_data,		RCAR_GP_PIN(3, 10));
+SSI_PFC_DATA(ssi0_data,		SSI_SDATA0);
+SSI_PFC_PINS(ssi1_a_ctrl,	RCAR_GP_PIN(2, 20),	RCAR_GP_PIN(2, 21));
+SSI_PFC_CTRL(ssi1_a_ctrl,	SSI_SCK1_A,		SSI_WS1_A);
+SSI_PFC_PINS(ssi1_b_ctrl,	PIN_NUMBER(3, 20),	RCAR_GP_PIN(1, 3));
+SSI_PFC_CTRL(ssi1_b_ctrl,	SSI_SCK1_B,		SSI_WS1_B);
+SSI_PFC_PINS(ssi1_data,		RCAR_GP_PIN(3, 9));
+SSI_PFC_DATA(ssi1_data,		SSI_SDATA1);
+SSI_PFC_PINS(ssi2_a_ctrl,	RCAR_GP_PIN(2, 26),	RCAR_GP_PIN(3, 4));
+SSI_PFC_CTRL(ssi2_a_ctrl,	SSI_SCK2_A,		SSI_WS2_A);
+SSI_PFC_PINS(ssi2_b_ctrl,	RCAR_GP_PIN(2, 6),	RCAR_GP_PIN(2, 17));
+SSI_PFC_CTRL(ssi2_b_ctrl,	SSI_SCK2_B,		SSI_WS2_B);
+SSI_PFC_PINS(ssi2_data,		RCAR_GP_PIN(3, 8));
+SSI_PFC_DATA(ssi2_data,		SSI_SDATA2);
+
+/* - SSI 3/4 ---------------------------------------------------------------- */
+SSI_PFC_PINS(ssi34_ctrl,	RCAR_GP_PIN(3, 2),	RCAR_GP_PIN(3, 3));
+SSI_PFC_CTRL(ssi34_ctrl,	SSI_SCK34,		SSI_WS34);
+SSI_PFC_PINS(ssi3_data,		RCAR_GP_PIN(3, 5));
+SSI_PFC_DATA(ssi3_data,		SSI_SDATA3);
+SSI_PFC_PINS(ssi4_ctrl,		RCAR_GP_PIN(1, 22),     RCAR_GP_PIN(1, 23));
+SSI_PFC_CTRL(ssi4_ctrl,		SSI_SCK4,               SSI_WS4);
+SSI_PFC_PINS(ssi4_data,		RCAR_GP_PIN(3, 4));
+SSI_PFC_DATA(ssi4_data,		SSI_SDATA4);
+
+/* - SSI 5 ------------------------------------------------------------------ */
+SSI_PFC_PINS(ssi5_ctrl,		RCAR_GP_PIN(2, 31),	RCAR_GP_PIN(3, 0));
+SSI_PFC_CTRL(ssi5_ctrl,		SSI_SCK5,		SSI_WS5);
+SSI_PFC_PINS(ssi5_data,		RCAR_GP_PIN(3, 1));
+SSI_PFC_DATA(ssi5_data,		SSI_SDATA5);
+
+/* - SSI 6 ------------------------------------------------------------------ */
+SSI_PFC_PINS(ssi6_ctrl,		RCAR_GP_PIN(2, 28),	RCAR_GP_PIN(2, 29));
+SSI_PFC_CTRL(ssi6_ctrl,		SSI_SCK6,		SSI_WS6);
+SSI_PFC_PINS(ssi6_data,		RCAR_GP_PIN(2, 30));
+SSI_PFC_DATA(ssi6_data,		SSI_SDATA6);
+
+/* - SSI 7/8  --------------------------------------------------------------- */
+SSI_PFC_PINS(ssi78_ctrl,	RCAR_GP_PIN(2, 24),	RCAR_GP_PIN(2, 25));
+SSI_PFC_CTRL(ssi78_ctrl,	SSI_SCK78,		SSI_WS78);
+SSI_PFC_PINS(ssi7_data,		RCAR_GP_PIN(2, 27));
+SSI_PFC_DATA(ssi7_data,		SSI_SDATA7);
+SSI_PFC_PINS(ssi8_data,		RCAR_GP_PIN(2, 26));
+SSI_PFC_DATA(ssi8_data,		SSI_SDATA8);
+
 /* - USB0 ------------------------------------------------------------------- */
 SH_PFC_PINS(usb0,		RCAR_GP_PIN(0, 1));
 SH_PFC_MUX1(usb0,		PENC0);
@@ -1624,6 +1720,19 @@
 VIN_PFC_SYNC(vin1_sync,		VI1_HSYNC,		VI1_VSYNC);
 
 static const struct sh_pfc_pin_group pinmux_groups[] = {
+	SH_PFC_PIN_GROUP(audio_clk_a),
+	SH_PFC_PIN_GROUP(audio_clk_b),
+	SH_PFC_PIN_GROUP(audio_clk_c),
+	SH_PFC_PIN_GROUP(audio_clkout_a),
+	SH_PFC_PIN_GROUP(audio_clkout_b),
+	SH_PFC_PIN_GROUP(can0_data_a),
+	SH_PFC_PIN_GROUP(can0_data_b),
+	SH_PFC_PIN_GROUP(can1_data_a),
+	SH_PFC_PIN_GROUP(can1_data_b),
+	SH_PFC_PIN_GROUP(can_clk_a),
+	SH_PFC_PIN_GROUP(can_clk_b),
+	SH_PFC_PIN_GROUP(can_clk_c),
+	SH_PFC_PIN_GROUP(can_clk_d),
 	SH_PFC_PIN_GROUP(ether_rmii),
 	SH_PFC_PIN_GROUP(ether_link),
 	SH_PFC_PIN_GROUP(ether_magic),
@@ -1713,6 +1822,25 @@
 	SH_PFC_PIN_GROUP(sdhi2_data4_b),
 	SH_PFC_PIN_GROUP(sdhi2_wp_a),
 	SH_PFC_PIN_GROUP(sdhi2_wp_b),
+	SH_PFC_PIN_GROUP(ssi012_ctrl),
+	SH_PFC_PIN_GROUP(ssi0_data),
+	SH_PFC_PIN_GROUP(ssi1_a_ctrl),
+	SH_PFC_PIN_GROUP(ssi1_b_ctrl),
+	SH_PFC_PIN_GROUP(ssi1_data),
+	SH_PFC_PIN_GROUP(ssi2_a_ctrl),
+	SH_PFC_PIN_GROUP(ssi2_b_ctrl),
+	SH_PFC_PIN_GROUP(ssi2_data),
+	SH_PFC_PIN_GROUP(ssi34_ctrl),
+	SH_PFC_PIN_GROUP(ssi3_data),
+	SH_PFC_PIN_GROUP(ssi4_ctrl),
+	SH_PFC_PIN_GROUP(ssi4_data),
+	SH_PFC_PIN_GROUP(ssi5_ctrl),
+	SH_PFC_PIN_GROUP(ssi5_data),
+	SH_PFC_PIN_GROUP(ssi6_ctrl),
+	SH_PFC_PIN_GROUP(ssi6_data),
+	SH_PFC_PIN_GROUP(ssi78_ctrl),
+	SH_PFC_PIN_GROUP(ssi7_data),
+	SH_PFC_PIN_GROUP(ssi8_data),
 	SH_PFC_PIN_GROUP(usb0),
 	SH_PFC_PIN_GROUP(usb0_ovc),
 	SH_PFC_PIN_GROUP(usb1),
@@ -1725,6 +1853,32 @@
 	SH_PFC_PIN_GROUP(vin1_sync),
 };
 
+static const char * const audio_clk_groups[] = {
+	"audio_clk_a",
+	"audio_clk_b",
+	"audio_clk_c",
+	"audio_clkout_a",
+	"audio_clkout_b",
+};
+
+static const char * const can0_groups[] = {
+	"can0_data_a",
+	"can0_data_b",
+	"can_clk_a",
+	"can_clk_b",
+	"can_clk_c",
+	"can_clk_d",
+};
+
+static const char * const can1_groups[] = {
+	"can1_data_a",
+	"can1_data_b",
+	"can_clk_a",
+	"can_clk_b",
+	"can_clk_c",
+	"can_clk_d",
+};
+
 static const char * const ether_groups[] = {
 	"ether_rmii",
 	"ether_link",
@@ -1875,6 +2029,28 @@
 	"sdhi2_wp_b",
 };
 
+static const char * const ssi_groups[] = {
+	"ssi012_ctrl",
+	"ssi0_data",
+	"ssi1_a_ctrl",
+	"ssi1_b_ctrl",
+	"ssi1_data",
+	"ssi2_a_ctrl",
+	"ssi2_b_ctrl",
+	"ssi2_data",
+	"ssi34_ctrl",
+	"ssi3_data",
+	"ssi4_ctrl",
+	"ssi4_data",
+	"ssi5_ctrl",
+	"ssi5_data",
+	"ssi6_ctrl",
+	"ssi6_data",
+	"ssi78_ctrl",
+	"ssi7_data",
+	"ssi8_data",
+};
+
 static const char * const usb0_groups[] = {
 	"usb0",
 	"usb0_ovc",
@@ -1898,6 +2074,9 @@
 };
 
 static const struct sh_pfc_function pinmux_functions[] = {
+	SH_PFC_FUNCTION(audio_clk),
+	SH_PFC_FUNCTION(can0),
+	SH_PFC_FUNCTION(can1),
 	SH_PFC_FUNCTION(ether),
 	SH_PFC_FUNCTION(hscif0),
 	SH_PFC_FUNCTION(hscif1),
@@ -1918,6 +2097,7 @@
 	SH_PFC_FUNCTION(sdhi0),
 	SH_PFC_FUNCTION(sdhi1),
 	SH_PFC_FUNCTION(sdhi2),
+	SH_PFC_FUNCTION(ssi),
 	SH_PFC_FUNCTION(usb0),
 	SH_PFC_FUNCTION(usb1),
 	SH_PFC_FUNCTION(vin0),
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
index 64fcc006..72786fc 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
@@ -781,6 +781,8 @@
 	ADICS_SAMP_MARK, DU2_CDE_MARK, QPOLB_MARK, SCIFA2_RXD_B_MARK,
 	USB1_PWEN_MARK, AUDIO_CLKOUT_D_MARK, USB1_OVC_MARK,
 	TCLK1_B_MARK,
+
+	I2C3_SCL_MARK, I2C3_SDA_MARK,
 	PINMUX_MARK_END,
 };
 
@@ -1719,10 +1721,22 @@
 	PINMUX_IPSR_DATA(IP16_6, AUDIO_CLKOUT_D),
 	PINMUX_IPSR_DATA(IP16_7, USB1_OVC),
 	PINMUX_IPSR_MODSEL_DATA(IP16_7, TCLK1_B, SEL_TMU1_1),
+
+	PINMUX_DATA(I2C3_SCL_MARK, FN_SEL_IICDVFS_1),
+	PINMUX_DATA(I2C3_SDA_MARK, FN_SEL_IICDVFS_1),
 };
 
+/* R8A7790 has 6 banks with 32 GPIOs in each = 192 GPIOs */
+#define ROW_GROUP_A(r) ('Z' - 'A' + 1 + (r))
+#define PIN_NUMBER(r, c) (((r) - 'A') * 31 + (c) + 200)
+#define PIN_A_NUMBER(r, c) PIN_NUMBER(ROW_GROUP_A(r), c)
+
 static struct sh_pfc_pin pinmux_pins[] = {
 	PINMUX_GPIO_GP_ALL(),
+
+	/* Pins not associated with a GPIO port */
+	SH_PFC_PIN_NAMED(ROW_GROUP_A('J'), 15, AJ15),
+	SH_PFC_PIN_NAMED(ROW_GROUP_A('H'), 15, AH15),
 };
 
 /* - DU RGB ----------------------------------------------------------------- */
@@ -1990,6 +2004,72 @@
 static const unsigned int hscif1_ctrl_b_mux[] = {
 	HRTS1_N_B_MARK, HCTS1_N_B_MARK,
 };
+/* - I2C1 ------------------------------------------------------------------- */
+static const unsigned int i2c1_pins[] = {
+	/* SCL, SDA */
+	RCAR_GP_PIN(1, 16), RCAR_GP_PIN(1, 17),
+};
+static const unsigned int i2c1_mux[] = {
+	I2C1_SCL_MARK, I2C1_SDA_MARK,
+};
+static const unsigned int i2c1_b_pins[] = {
+	/* SCL, SDA */
+	RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7),
+};
+static const unsigned int i2c1_b_mux[] = {
+	I2C1_SCL_B_MARK, I2C1_SDA_B_MARK,
+};
+static const unsigned int i2c1_c_pins[] = {
+	/* SCL, SDA */
+	RCAR_GP_PIN(4, 30), RCAR_GP_PIN(4, 27),
+};
+static const unsigned int i2c1_c_mux[] = {
+	I2C1_SCL_C_MARK, I2C1_SDA_C_MARK,
+};
+/* - I2C2 ------------------------------------------------------------------- */
+static const unsigned int i2c2_pins[] = {
+	/* SCL, SDA */
+	RCAR_GP_PIN(5, 5), RCAR_GP_PIN(5, 6),
+};
+static const unsigned int i2c2_mux[] = {
+	I2C2_SCL_MARK, I2C2_SDA_MARK,
+};
+static const unsigned int i2c2_b_pins[] = {
+	/* SCL, SDA */
+	RCAR_GP_PIN(4, 0), RCAR_GP_PIN(4, 1),
+};
+static const unsigned int i2c2_b_mux[] = {
+	I2C2_SCL_B_MARK, I2C2_SDA_B_MARK,
+};
+static const unsigned int i2c2_c_pins[] = {
+	/* SCL, SDA */
+	RCAR_GP_PIN(0, 6), RCAR_GP_PIN(0, 7),
+};
+static const unsigned int i2c2_c_mux[] = {
+	I2C2_SCL_C_MARK, I2C2_SDA_C_MARK,
+};
+static const unsigned int i2c2_d_pins[] = {
+	/* SCL, SDA */
+	RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 15),
+};
+static const unsigned int i2c2_d_mux[] = {
+	I2C2_SCL_D_MARK, I2C2_SDA_D_MARK,
+};
+static const unsigned int i2c2_e_pins[] = {
+	/* SCL, SDA */
+	RCAR_GP_PIN(2, 18), RCAR_GP_PIN(2, 19),
+};
+static const unsigned int i2c2_e_mux[] = {
+	I2C2_SCL_E_MARK, I2C2_SDA_E_MARK,
+};
+/* - I2C3 ------------------------------------------------------------------- */
+static const unsigned int i2c3_pins[] = {
+	/* SCL, SDA */
+	PIN_A_NUMBER('J', 15), PIN_A_NUMBER('H', 15),
+};
+static const unsigned int i2c3_mux[] = {
+	I2C3_SCL_MARK, I2C3_SDA_MARK,
+};
 /* - INTC ------------------------------------------------------------------- */
 static const unsigned int intc_irq0_pins[] = {
 	/* IRQ */
@@ -3047,6 +3127,15 @@
 	SH_PFC_PIN_GROUP(hscif1_data_b),
 	SH_PFC_PIN_GROUP(hscif1_clk_b),
 	SH_PFC_PIN_GROUP(hscif1_ctrl_b),
+	SH_PFC_PIN_GROUP(i2c1),
+	SH_PFC_PIN_GROUP(i2c1_b),
+	SH_PFC_PIN_GROUP(i2c1_c),
+	SH_PFC_PIN_GROUP(i2c2),
+	SH_PFC_PIN_GROUP(i2c2_b),
+	SH_PFC_PIN_GROUP(i2c2_c),
+	SH_PFC_PIN_GROUP(i2c2_d),
+	SH_PFC_PIN_GROUP(i2c2_e),
+	SH_PFC_PIN_GROUP(i2c3),
 	SH_PFC_PIN_GROUP(intc_irq0),
 	SH_PFC_PIN_GROUP(intc_irq1),
 	SH_PFC_PIN_GROUP(intc_irq2),
@@ -3243,6 +3332,24 @@
 	"hscif1_ctrl_b",
 };
 
+static const char * const i2c1_groups[] = {
+	"i2c1",
+	"i2c1_b",
+	"i2c1_c",
+};
+
+static const char * const i2c2_groups[] = {
+	"i2c2",
+	"i2c2_b",
+	"i2c2_c",
+	"i2c2_d",
+	"i2c2_e",
+};
+
+static const char * const i2c3_groups[] = {
+	"i2c3",
+};
+
 static const char * const intc_groups[] = {
 	"intc_irq0",
 	"intc_irq1",
@@ -3469,6 +3576,9 @@
 	SH_PFC_FUNCTION(eth),
 	SH_PFC_FUNCTION(hscif0),
 	SH_PFC_FUNCTION(hscif1),
+	SH_PFC_FUNCTION(i2c1),
+	SH_PFC_FUNCTION(i2c2),
+	SH_PFC_FUNCTION(i2c3),
 	SH_PFC_FUNCTION(intc),
 	SH_PFC_FUNCTION(mmc0),
 	SH_PFC_FUNCTION(mmc1),
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
new file mode 100644
index 0000000..bf76a65
--- /dev/null
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
@@ -0,0 +1,4214 @@
+/*
+ * r8a7791 processor support - PFC hardware block.
+ *
+ * Copyright (C) 2013 Renesas Electronics Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_data/gpio-rcar.h>
+
+#include "core.h"
+#include "sh_pfc.h"
+
+#define CPU_ALL_PORT(fn, sfx)						\
+	PORT_GP_32(0, fn, sfx),						\
+	PORT_GP_32(1, fn, sfx),						\
+	PORT_GP_32(2, fn, sfx),						\
+	PORT_GP_32(3, fn, sfx),						\
+	PORT_GP_32(4, fn, sfx),						\
+	PORT_GP_32(5, fn, sfx),						\
+	PORT_GP_32(6, fn, sfx),						\
+	PORT_GP_32(7, fn, sfx)
+
+enum {
+	PINMUX_RESERVED = 0,
+
+	PINMUX_DATA_BEGIN,
+	GP_ALL(DATA),
+	PINMUX_DATA_END,
+
+	PINMUX_FUNCTION_BEGIN,
+	GP_ALL(FN),
+
+	/* GPSR0 */
+	FN_IP0_0, FN_IP0_1, FN_IP0_2, FN_IP0_3, FN_IP0_4, FN_IP0_5,
+	FN_IP0_6, FN_IP0_7, FN_IP0_8, FN_IP0_9, FN_IP0_10, FN_IP0_11,
+	FN_IP0_12, FN_IP0_13, FN_IP0_14, FN_IP0_15, FN_IP0_18_16, FN_IP0_20_19,
+	FN_IP0_22_21, FN_IP0_24_23, FN_IP0_26_25, FN_IP0_28_27, FN_IP0_30_29,
+	FN_IP1_1_0, FN_IP1_3_2, FN_IP1_5_4, FN_IP1_7_6, FN_IP1_10_8,
+	FN_IP1_13_11, FN_IP1_16_14, FN_IP1_19_17, FN_IP1_22_20,
+
+	/* GPSR1 */
+	FN_IP1_25_23, FN_IP1_28_26, FN_IP1_31_29, FN_IP2_2_0, FN_IP2_4_3,
+	FN_IP2_6_5, FN_IP2_9_7, FN_IP2_12_10, FN_IP2_15_13, FN_IP2_18_16,
+	FN_IP2_20_19, FN_IP2_22_21, FN_EX_CS0_N, FN_IP2_24_23, FN_IP2_26_25,
+	FN_IP2_29_27, FN_IP3_2_0, FN_IP3_5_3, FN_IP3_8_6, FN_RD_N,
+	FN_IP3_11_9, FN_IP3_13_12, FN_IP3_15_14 , FN_IP3_17_16 , FN_IP3_19_18,
+	FN_IP3_21_20,
+
+	/* GPSR2 */
+	FN_IP3_27_25, FN_IP3_30_28, FN_IP4_1_0, FN_IP4_4_2, FN_IP4_7_5,
+	FN_IP4_9_8, FN_IP4_12_10, FN_IP4_15_13, FN_IP4_18_16, FN_IP4_19,
+	FN_IP4_20, FN_IP4_21, FN_IP4_23_22, FN_IP4_25_24, FN_IP4_27_26,
+	FN_IP4_30_28, FN_IP5_2_0, FN_IP5_5_3, FN_IP5_8_6, FN_IP5_11_9,
+	FN_IP5_14_12, FN_IP5_16_15, FN_IP5_19_17, FN_IP5_21_20, FN_IP5_23_22,
+	FN_IP5_25_24, FN_IP5_28_26, FN_IP5_31_29, FN_AUDIO_CLKA, FN_IP6_2_0,
+	FN_IP6_5_3, FN_IP6_7_6,
+
+	/* GPSR3 */
+	FN_IP7_5_3, FN_IP7_8_6, FN_IP7_10_9, FN_IP7_12_11, FN_IP7_14_13,
+	FN_IP7_16_15, FN_IP7_18_17, FN_IP7_20_19, FN_IP7_23_21, FN_IP7_26_24,
+	FN_IP7_29_27, FN_IP8_2_0, FN_IP8_5_3, FN_IP8_8_6, FN_IP8_11_9,
+	FN_IP8_14_12, FN_IP8_17_15, FN_IP8_20_18, FN_IP8_23_21, FN_IP8_25_24,
+	FN_IP8_27_26, FN_IP8_30_28, FN_IP9_2_0, FN_IP9_5_3, FN_IP9_6, FN_IP9_7,
+	FN_IP9_10_8, FN_IP9_11, FN_IP9_12, FN_IP9_15_13, FN_IP9_16,
+	FN_IP9_18_17,
+
+	/* GPSR4 */
+	FN_VI0_CLK, FN_IP9_20_19, FN_IP9_22_21, FN_IP9_24_23, FN_IP9_26_25,
+	FN_VI0_DATA0_VI0_B0, FN_VI0_DATA1_VI0_B1, FN_VI0_DATA2_VI0_B2,
+	FN_IP9_28_27, FN_VI0_DATA4_VI0_B4, FN_VI0_DATA5_VI0_B5,
+	FN_VI0_DATA6_VI0_B6, FN_VI0_DATA7_VI0_B7, FN_IP9_31_29, FN_IP10_2_0,
+	FN_IP10_5_3, FN_IP10_8_6, FN_IP10_11_9, FN_IP10_14_12, FN_IP10_16_15,
+	FN_IP10_18_17, FN_IP10_21_19, FN_IP10_24_22, FN_IP10_26_25,
+	FN_IP10_28_27, FN_IP10_31_29, FN_IP11_2_0, FN_IP11_5_3, FN_IP11_8_6,
+	FN_IP15_1_0, FN_IP15_3_2, FN_IP15_5_4,
+
+	/* GPSR5 */
+	FN_IP11_11_9, FN_IP11_14_12, FN_IP11_16_15, FN_IP11_18_17, FN_IP11_19,
+	FN_IP11_20, FN_IP11_21, FN_IP11_22, FN_IP11_23, FN_IP11_24,
+	FN_IP11_25, FN_IP11_26, FN_IP11_27, FN_IP11_29_28, FN_IP11_31_30,
+	FN_IP12_1_0, FN_IP12_3_2, FN_IP12_6_4, FN_IP12_9_7, FN_IP12_12_10,
+	FN_IP12_15_13, FN_IP12_17_16, FN_IP12_19_18, FN_IP12_21_20,
+	FN_IP12_23_22, FN_IP12_26_24, FN_IP12_29_27, FN_IP13_2_0, FN_IP13_4_3,
+	FN_IP13_6_5, FN_IP13_9_7, FN_IP3_24_22,
+
+	/* GPSR6 */
+	FN_IP13_10, FN_IP13_11, FN_IP13_12, FN_IP13_13, FN_IP13_14,
+	FN_IP13_15, FN_IP13_18_16, FN_IP13_21_19, FN_IP13_22, FN_IP13_24_23,
+	FN_IP13_25, FN_IP13_26, FN_IP13_27, FN_IP13_30_28, FN_IP14_1_0,
+	FN_IP14_2, FN_IP14_3, FN_IP14_4, FN_IP14_5, FN_IP14_6, FN_IP14_7,
+	FN_IP14_10_8, FN_IP14_13_11, FN_IP14_16_14, FN_IP14_19_17,
+	FN_IP14_22_20, FN_IP14_25_23, FN_IP14_28_26, FN_IP14_31_29,
+	FN_USB1_OVC, FN_DU0_DOTCLKIN,
+
+	/* GPSR7 */
+	FN_IP15_17_15, FN_IP15_20_18, FN_IP15_23_21, FN_IP15_26_24,
+	FN_IP15_29_27, FN_IP16_2_0, FN_IP16_5_3, FN_IP16_7_6, FN_IP16_9_8,
+	FN_IP16_11_10, FN_IP6_9_8, FN_IP6_11_10, FN_IP6_13_12, FN_IP6_15_14,
+	FN_IP6_18_16, FN_IP6_20_19, FN_IP6_23_21, FN_IP6_26_24, FN_IP6_29_27,
+	FN_IP7_2_0, FN_IP15_8_6, FN_IP15_11_9, FN_IP15_14_12,
+	FN_USB0_PWEN, FN_USB0_OVC, FN_USB1_PWEN,
+
+	/* IPSR0 */
+	FN_D0, FN_D1, FN_D2, FN_D3, FN_D4, FN_D5, FN_D6, FN_D7, FN_D8,
+	FN_D9, FN_D10, FN_D11, FN_D12, FN_D13, FN_D14, FN_D15,
+	FN_A0, FN_ATAWR0_N_C, FN_MSIOF0_SCK_B, FN_SCL0_C, FN_PWM2_B,
+	FN_A1, FN_MSIOF0_SYNC_B, FN_A2, FN_MSIOF0_SS1_B,
+	FN_A3, FN_MSIOF0_SS2_B, FN_A4, FN_MSIOF0_TXD_B,
+	FN_A5, FN_MSIOF0_RXD_B, FN_A6, FN_MSIOF1_SCK,
+
+	/* IPSR1 */
+	FN_A7, FN_MSIOF1_SYNC, FN_A8, FN_MSIOF1_SS1, FN_SCL0,
+	FN_A9, FN_MSIOF1_SS2, FN_SDA0,
+	FN_A10, FN_MSIOF1_TXD, FN_MSIOF1_TXD_D,
+	FN_A11, FN_MSIOF1_RXD, FN_SCL3_D, FN_MSIOF1_RXD_D,
+	FN_A12, FN_FMCLK, FN_SDA3_D, FN_MSIOF1_SCK_D,
+	FN_A13, FN_ATAG0_N_C, FN_BPFCLK, FN_MSIOF1_SS1_D,
+	FN_A14, FN_ATADIR0_N_C, FN_FMIN, FN_FMIN_C, FN_MSIOF1_SYNC_D,
+	FN_A15, FN_BPFCLK_C,
+	FN_A16, FN_DREQ2_B, FN_FMCLK_C, FN_SCIFA1_SCK_B,
+	FN_A17, FN_DACK2_B, FN_SDA0_C,
+	FN_A18, FN_DREQ1, FN_SCIFA1_RXD_C, FN_SCIFB1_RXD_C,
+
+	/* IPSR2 */
+	FN_A19, FN_DACK1, FN_SCIFA1_TXD_C, FN_SCIFB1_TXD_C, FN_SCIFB1_SCK_B,
+	FN_A20, FN_SPCLK,
+	FN_A21, FN_ATAWR0_N_B, FN_MOSI_IO0,
+	FN_A22, FN_MISO_IO1, FN_FMCLK_B, FN_TX0, FN_SCIFA0_TXD,
+	FN_A23, FN_IO2, FN_BPFCLK_B, FN_RX0, FN_SCIFA0_RXD,
+	FN_A24, FN_DREQ2, FN_IO3, FN_TX1, FN_SCIFA1_TXD,
+	FN_A25, FN_DACK2, FN_SSL, FN_DREQ1_C, FN_RX1, FN_SCIFA1_RXD,
+	FN_CS0_N, FN_ATAG0_N_B, FN_SCL1,
+	FN_CS1_N_A26, FN_ATADIR0_N_B, FN_SDA1,
+	FN_EX_CS1_N, FN_MSIOF2_SCK,
+	FN_EX_CS2_N, FN_ATAWR0_N, FN_MSIOF2_SYNC,
+	FN_EX_CS3_N, FN_ATADIR0_N, FN_MSIOF2_TXD, FN_ATAG0_N, FN_EX_WAIT1,
+
+	/* IPSR3 */
+	FN_EX_CS4_N, FN_ATARD0_N, FN_MSIOF2_RXD, FN_EX_WAIT2,
+	FN_EX_CS5_N, FN_ATACS00_N, FN_MSIOF2_SS1, FN_HRX1_B,
+	FN_SCIFB1_RXD_B, FN_PWM1, FN_TPU_TO1,
+	FN_BS_N, FN_ATACS10_N, FN_MSIOF2_SS2, FN_HTX1_B,
+	FN_SCIFB1_TXD_B, FN_PWM2, FN_TPU_TO2,
+	FN_RD_WR_N, FN_HRX2_B, FN_FMIN_B, FN_SCIFB0_RXD_B, FN_DREQ1_D,
+	FN_WE0_N, FN_HCTS2_N_B, FN_SCIFB0_TXD_B,
+	FN_WE1_N, FN_ATARD0_N_B, FN_HTX2_B, FN_SCIFB0_RTS_N_B,
+	FN_EX_WAIT0, FN_HRTS2_N_B, FN_SCIFB0_CTS_N_B,
+	FN_DREQ0, FN_PWM3, FN_TPU_TO3,
+	FN_DACK0, FN_DRACK0, FN_REMOCON,
+	FN_SPEEDIN, FN_HSCK0_C, FN_HSCK2_C, FN_SCIFB0_SCK_B,
+	FN_SCIFB2_SCK_B, FN_DREQ2_C, FN_HTX2_D,
+	FN_SSI_SCK0129, FN_HRX0_C, FN_HRX2_C, FN_SCIFB0_RXD_C, FN_SCIFB2_RXD_C,
+	FN_SSI_WS0129, FN_HTX0_C, FN_HTX2_C, FN_SCIFB0_TXD_C, FN_SCIFB2_TXD_C,
+
+	/* IPSR4 */
+	FN_SSI_SDATA0, FN_SCL0_B, FN_SCL7_B, FN_MSIOF2_SCK_C,
+	FN_SSI_SCK1, FN_SDA0_B, FN_SDA7_B, FN_MSIOF2_SYNC_C, FN_GLO_I0_D,
+	FN_SSI_WS1, FN_SCL1_B, FN_SCL8_B, FN_MSIOF2_TXD_C, FN_GLO_I1_D,
+	FN_SSI_SDATA1, FN_SDA1_B, FN_SDA8_B, FN_MSIOF2_RXD_C,
+	FN_SSI_SCK2, FN_SCL2, FN_GPS_CLK_B, FN_GLO_Q0_D, FN_HSCK1_E,
+	FN_SSI_WS2, FN_SDA2, FN_GPS_SIGN_B, FN_RX2_E,
+	FN_GLO_Q1_D, FN_HCTS1_N_E,
+	FN_SSI_SDATA2, FN_GPS_MAG_B, FN_TX2_E, FN_HRTS1_N_E,
+	FN_SSI_SCK34, FN_SSI_WS34, FN_SSI_SDATA3,
+	FN_SSI_SCK4, FN_GLO_SS_D,
+	FN_SSI_WS4, FN_GLO_RFON_D,
+	FN_SSI_SDATA4, FN_MSIOF2_SCK_D,
+	FN_SSI_SCK5, FN_MSIOF1_SCK_C, FN_TS_SDATA0, FN_GLO_I0,
+	FN_MSIOF2_SYNC_D, FN_VI1_R2_B,
+
+	/* IPSR5 */
+	FN_SSI_WS5, FN_MSIOF1_SYNC_C, FN_TS_SCK0, FN_GLO_I1,
+	FN_MSIOF2_TXD_D, FN_VI1_R3_B,
+	FN_SSI_SDATA5, FN_MSIOF1_TXD_C, FN_TS_SDEN0, FN_GLO_Q0,
+	FN_MSIOF2_SS1_D, FN_VI1_R4_B,
+	FN_SSI_SCK6, FN_MSIOF1_RXD_C, FN_TS_SPSYNC0, FN_GLO_Q1,
+	FN_MSIOF2_RXD_D, FN_VI1_R5_B,
+	FN_SSI_WS6, FN_GLO_SCLK, FN_MSIOF2_SS2_D, FN_VI1_R6_B,
+	FN_SSI_SDATA6, FN_STP_IVCXO27_0_B, FN_GLO_SDATA, FN_VI1_R7_B,
+	FN_SSI_SCK78, FN_STP_ISCLK_0_B, FN_GLO_SS,
+	FN_SSI_WS78, FN_TX0_D, FN_STP_ISD_0_B, FN_GLO_RFON,
+	FN_SSI_SDATA7, FN_RX0_D, FN_STP_ISEN_0_B,
+	FN_SSI_SDATA8, FN_TX1_D, FN_STP_ISSYNC_0_B,
+	FN_SSI_SCK9, FN_RX1_D, FN_GLO_SCLK_D,
+	FN_SSI_WS9, FN_TX3_D, FN_CAN0_TX_D, FN_GLO_SDATA_D,
+	FN_SSI_SDATA9, FN_RX3_D, FN_CAN0_RX_D,
+
+	/* IPSR6 */
+	FN_AUDIO_CLKB, FN_STP_OPWM_0_B, FN_MSIOF1_SCK_B,
+	FN_SCIF_CLK, FN_BPFCLK_E,
+	FN_AUDIO_CLKC, FN_SCIFB0_SCK_C, FN_MSIOF1_SYNC_B, FN_RX2,
+	FN_SCIFA2_RXD, FN_FMIN_E,
+	FN_AUDIO_CLKOUT, FN_MSIOF1_SS1_B, FN_TX2, FN_SCIFA2_TXD,
+	FN_IRQ0, FN_SCIFB1_RXD_D, FN_INTC_IRQ0_N,
+	FN_IRQ1, FN_SCIFB1_SCK_C, FN_INTC_IRQ1_N,
+	FN_IRQ2, FN_SCIFB1_TXD_D, FN_INTC_IRQ2_N,
+	FN_IRQ3, FN_SCL4_C, FN_MSIOF2_TXD_E, FN_INTC_IRQ3_N,
+	FN_IRQ4, FN_HRX1_C, FN_SDA4_C, FN_MSIOF2_RXD_E, FN_INTC_IRQ4_N,
+	FN_IRQ5, FN_HTX1_C, FN_SCL1_E, FN_MSIOF2_SCK_E,
+	FN_IRQ6, FN_HSCK1_C, FN_MSIOF1_SS2_B, FN_SDA1_E, FN_MSIOF2_SYNC_E,
+	FN_IRQ7, FN_HCTS1_N_C, FN_MSIOF1_TXD_B, FN_GPS_CLK_C, FN_GPS_CLK_D,
+	FN_IRQ8, FN_HRTS1_N_C, FN_MSIOF1_RXD_B, FN_GPS_SIGN_C, FN_GPS_SIGN_D,
+
+	/* IPSR7 */
+	FN_IRQ9, FN_DU1_DOTCLKIN_B, FN_CAN_CLK_D, FN_GPS_MAG_C,
+	FN_SCIF_CLK_B, FN_GPS_MAG_D,
+	FN_DU1_DR0, FN_LCDOUT0, FN_VI1_DATA0_B, FN_TX0_B,
+	FN_SCIFA0_TXD_B, FN_MSIOF2_SCK_B,
+	FN_DU1_DR1, FN_LCDOUT1, FN_VI1_DATA1_B, FN_RX0_B,
+	FN_SCIFA0_RXD_B, FN_MSIOF2_SYNC_B,
+	FN_DU1_DR2, FN_LCDOUT2, FN_SSI_SCK0129_B,
+	FN_DU1_DR3, FN_LCDOUT3, FN_SSI_WS0129_B,
+	FN_DU1_DR4, FN_LCDOUT4, FN_SSI_SDATA0_B,
+	FN_DU1_DR5, FN_LCDOUT5, FN_SSI_SCK1_B,
+	FN_DU1_DR6, FN_LCDOUT6, FN_SSI_WS1_B,
+	FN_DU1_DR7, FN_LCDOUT7, FN_SSI_SDATA1_B,
+	FN_DU1_DG0, FN_LCDOUT8, FN_VI1_DATA2_B, FN_TX1_B,
+	FN_SCIFA1_TXD_B, FN_MSIOF2_SS1_B,
+	FN_DU1_DG1, FN_LCDOUT9, FN_VI1_DATA3_B, FN_RX1_B,
+	FN_SCIFA1_RXD_B, FN_MSIOF2_SS2_B,
+	FN_DU1_DG2, FN_LCDOUT10, FN_VI1_DATA4_B, FN_SCIF1_SCK_B,
+	FN_SCIFA1_SCK, FN_SSI_SCK78_B,
+
+	/* IPSR8 */
+	FN_DU1_DG3, FN_LCDOUT11, FN_VI1_DATA5_B, FN_SSI_WS78_B,
+	FN_DU1_DG4, FN_LCDOUT12, FN_VI1_DATA6_B, FN_HRX0_B,
+	FN_SCIFB2_RXD_B, FN_SSI_SDATA7_B,
+	FN_DU1_DG5, FN_LCDOUT13, FN_VI1_DATA7_B, FN_HCTS0_N_B,
+	FN_SCIFB2_TXD_B, FN_SSI_SDATA8_B,
+	FN_DU1_DG6, FN_LCDOUT14, FN_HRTS0_N_B,
+	FN_SCIFB2_CTS_N_B, FN_SSI_SCK9_B,
+	FN_DU1_DG7, FN_LCDOUT15, FN_HTX0_B, FN_SCIFB2_RTS_N_B, FN_SSI_WS9_B,
+	FN_DU1_DB0, FN_LCDOUT16, FN_VI1_CLK_B, FN_TX2_B,
+	FN_SCIFA2_TXD_B, FN_MSIOF2_TXD_B,
+	FN_DU1_DB1, FN_LCDOUT17, FN_VI1_HSYNC_N_B, FN_RX2_B,
+	FN_SCIFA2_RXD_B, FN_MSIOF2_RXD_B,
+	FN_DU1_DB2, FN_LCDOUT18, FN_VI1_VSYNC_N_B, FN_SCIF2_SCK_B,
+	FN_SCIFA2_SCK, FN_SSI_SDATA9_B,
+	FN_DU1_DB3, FN_LCDOUT19, FN_VI1_CLKENB_B,
+	FN_DU1_DB4, FN_LCDOUT20, FN_VI1_FIELD_B, FN_CAN1_RX,
+	FN_DU1_DB5, FN_LCDOUT21, FN_TX3, FN_SCIFA3_TXD, FN_CAN1_TX,
+
+	/* IPSR9 */
+	FN_DU1_DB6, FN_LCDOUT22, FN_SCL3_C, FN_RX3, FN_SCIFA3_RXD,
+	FN_DU1_DB7, FN_LCDOUT23, FN_SDA3_C, FN_SCIF3_SCK, FN_SCIFA3_SCK,
+	FN_DU1_DOTCLKIN, FN_QSTVA_QVS,
+	FN_DU1_DOTCLKOUT0, FN_QCLK,
+	FN_DU1_DOTCLKOUT1, FN_QSTVB_QVE, FN_CAN0_TX,
+	FN_TX3_B, FN_SCL2_B, FN_PWM4,
+	FN_DU1_EXHSYNC_DU1_HSYNC, FN_QSTH_QHS,
+	FN_DU1_EXVSYNC_DU1_VSYNC, FN_QSTB_QHE,
+	FN_DU1_EXODDF_DU1_ODDF_DISP_CDE, FN_QCPV_QDE,
+	FN_CAN0_RX, FN_RX3_B, FN_SDA2_B,
+	FN_DU1_DISP, FN_QPOLA,
+	FN_DU1_CDE, FN_QPOLB, FN_PWM4_B,
+	FN_VI0_CLKENB, FN_TX4, FN_SCIFA4_TXD, FN_TS_SDATA0_D,
+	FN_VI0_FIELD, FN_RX4, FN_SCIFA4_RXD, FN_TS_SCK0_D,
+	FN_VI0_HSYNC_N, FN_TX5, FN_SCIFA5_TXD, FN_TS_SDEN0_D,
+	FN_VI0_VSYNC_N, FN_RX5, FN_SCIFA5_RXD, FN_TS_SPSYNC0_D,
+	FN_VI0_DATA3_VI0_B3, FN_SCIF3_SCK_B, FN_SCIFA3_SCK_B,
+	FN_VI0_G0, FN_SCL8, FN_STP_IVCXO27_0_C, FN_SCL4,
+	FN_HCTS2_N, FN_SCIFB2_CTS_N, FN_ATAWR1_N,
+
+	/* IPSR10 */
+	FN_VI0_G1, FN_SDA8, FN_STP_ISCLK_0_C, FN_SDA4,
+	FN_HRTS2_N, FN_SCIFB2_RTS_N, FN_ATADIR1_N,
+	FN_VI0_G2, FN_VI2_HSYNC_N, FN_STP_ISD_0_C, FN_SCL3_B,
+	FN_HSCK2, FN_SCIFB2_SCK, FN_ATARD1_N,
+	FN_VI0_G3, FN_VI2_VSYNC_N, FN_STP_ISEN_0_C, FN_SDA3_B,
+	FN_HRX2, FN_SCIFB2_RXD, FN_ATACS01_N,
+	FN_VI0_G4, FN_VI2_CLKENB, FN_STP_ISSYNC_0_C,
+	FN_HTX2, FN_SCIFB2_TXD, FN_SCIFB0_SCK_D,
+	FN_VI0_G5, FN_VI2_FIELD, FN_STP_OPWM_0_C, FN_FMCLK_D,
+	FN_CAN0_TX_E, FN_HTX1_D, FN_SCIFB0_TXD_D,
+	FN_VI0_G6, FN_VI2_CLK, FN_BPFCLK_D,
+	FN_VI0_G7, FN_VI2_DATA0, FN_FMIN_D,
+	FN_VI0_R0, FN_VI2_DATA1, FN_GLO_I0_B,
+	FN_TS_SDATA0_C, FN_ATACS11_N,
+	FN_VI0_R1, FN_VI2_DATA2, FN_GLO_I1_B,
+	FN_TS_SCK0_C, FN_ATAG1_N,
+	FN_VI0_R2, FN_VI2_DATA3, FN_GLO_Q0_B, FN_TS_SDEN0_C,
+	FN_VI0_R3, FN_VI2_DATA4, FN_GLO_Q1_B, FN_TS_SPSYNC0_C,
+	FN_VI0_R4, FN_VI2_DATA5, FN_GLO_SCLK_B, FN_TX0_C, FN_SCL1_D,
+
+	/* IPSR11 */
+	FN_VI0_R5, FN_VI2_DATA6, FN_GLO_SDATA_B, FN_RX0_C, FN_SDA1_D,
+	FN_VI0_R6, FN_VI2_DATA7, FN_GLO_SS_B, FN_TX1_C, FN_SCL4_B,
+	FN_VI0_R7, FN_GLO_RFON_B, FN_RX1_C, FN_CAN0_RX_E,
+	FN_SDA4_B, FN_HRX1_D, FN_SCIFB0_RXD_D,
+	FN_VI1_HSYNC_N, FN_AVB_RXD0, FN_TS_SDATA0_B, FN_TX4_B, FN_SCIFA4_TXD_B,
+	FN_VI1_VSYNC_N, FN_AVB_RXD1, FN_TS_SCK0_B, FN_RX4_B, FN_SCIFA4_RXD_B,
+	FN_VI1_CLKENB, FN_AVB_RXD2, FN_TS_SDEN0_B,
+	FN_VI1_FIELD, FN_AVB_RXD3, FN_TS_SPSYNC0_B,
+	FN_VI1_CLK, FN_AVB_RXD4, FN_VI1_DATA0, FN_AVB_RXD5,
+	FN_VI1_DATA1, FN_AVB_RXD6, FN_VI1_DATA2, FN_AVB_RXD7,
+	FN_VI1_DATA3, FN_AVB_RX_ER, FN_VI1_DATA4, FN_AVB_MDIO,
+	FN_VI1_DATA5, FN_AVB_RX_DV, FN_VI1_DATA6, FN_AVB_MAGIC,
+	FN_VI1_DATA7, FN_AVB_MDC,
+	FN_ETH_MDIO, FN_AVB_RX_CLK, FN_SCL2_C,
+	FN_ETH_CRS_DV, FN_AVB_LINK, FN_SDA2_C,
+
+	/* IPSR12 */
+	FN_ETH_RX_ER, FN_AVB_CRS, FN_SCL3, FN_SCL7,
+	FN_ETH_RXD0, FN_AVB_PHY_INT, FN_SDA3, FN_SDA7,
+	FN_ETH_RXD1, FN_AVB_GTXREFCLK, FN_CAN0_TX_C,
+	FN_SCL2_D, FN_MSIOF1_RXD_E,
+	FN_ETH_LINK, FN_AVB_TXD0, FN_CAN0_RX_C, FN_SDA2_D, FN_MSIOF1_SCK_E,
+	FN_ETH_REFCLK, FN_AVB_TXD1, FN_SCIFA3_RXD_B,
+	FN_CAN1_RX_C, FN_MSIOF1_SYNC_E,
+	FN_ETH_TXD1, FN_AVB_TXD2, FN_SCIFA3_TXD_B,
+	FN_CAN1_TX_C, FN_MSIOF1_TXD_E,
+	FN_ETH_TX_EN, FN_AVB_TXD3, FN_TCLK1_B, FN_CAN_CLK_B,
+	FN_ETH_MAGIC, FN_AVB_TXD4, FN_IETX_C,
+	FN_ETH_TXD0, FN_AVB_TXD5, FN_IECLK_C,
+	FN_ETH_MDC, FN_AVB_TXD6, FN_IERX_C,
+	FN_STP_IVCXO27_0, FN_AVB_TXD7, FN_SCIFB2_TXD_D,
+	FN_ADIDATA_B, FN_MSIOF0_SYNC_C,
+	FN_STP_ISCLK_0, FN_AVB_TX_EN, FN_SCIFB2_RXD_D,
+	FN_ADICS_SAMP_B, FN_MSIOF0_SCK_C,
+
+	/* IPSR13 */
+	FN_STP_ISD_0, FN_AVB_TX_ER, FN_SCIFB2_SCK_C,
+	FN_ADICLK_B, FN_MSIOF0_SS1_C,
+	FN_STP_ISEN_0, FN_AVB_TX_CLK, FN_ADICHS0_B, FN_MSIOF0_SS2_C,
+	FN_STP_ISSYNC_0, FN_AVB_COL, FN_ADICHS1_B, FN_MSIOF0_RXD_C,
+	FN_STP_OPWM_0, FN_AVB_GTX_CLK, FN_PWM0_B,
+	FN_ADICHS2_B, FN_MSIOF0_TXD_C,
+	FN_SD0_CLK, FN_SPCLK_B, FN_SD0_CMD, FN_MOSI_IO0_B,
+	FN_SD0_DATA0, FN_MISO_IO1_B, FN_SD0_DATA1, FN_IO2_B,
+	FN_SD0_DATA2, FN_IO3_B, FN_SD0_DATA3, FN_SSL_B,
+	FN_SD0_CD, FN_MMC_D6_B, FN_SIM0_RST_B, FN_CAN0_RX_F,
+	FN_SCIFA5_TXD_B, FN_TX3_C,
+	FN_SD0_WP, FN_MMC_D7_B, FN_SIM0_D_B, FN_CAN0_TX_F,
+	FN_SCIFA5_RXD_B, FN_RX3_C,
+	FN_SD1_CMD, FN_REMOCON_B, FN_SD1_DATA0, FN_SPEEDIN_B,
+	FN_SD1_DATA1, FN_IETX_B, FN_SD1_DATA2, FN_IECLK_B,
+	FN_SD1_DATA3, FN_IERX_B,
+	FN_SD1_CD, FN_PWM0, FN_TPU_TO0, FN_SCL1_C,
+
+	/* IPSR14 */
+	FN_SD1_WP, FN_PWM1_B, FN_SDA1_C,
+	FN_SD2_CLK, FN_MMC_CLK, FN_SD2_CMD, FN_MMC_CMD,
+	FN_SD2_DATA0, FN_MMC_D0, FN_SD2_DATA1, FN_MMC_D1,
+	FN_SD2_DATA2, FN_MMC_D2, FN_SD2_DATA3, FN_MMC_D3,
+	FN_SD2_CD, FN_MMC_D4, FN_SCL8_C, FN_TX5_B, FN_SCIFA5_TXD_C,
+	FN_SD2_WP, FN_MMC_D5, FN_SDA8_C, FN_RX5_B, FN_SCIFA5_RXD_C,
+	FN_MSIOF0_SCK, FN_RX2_C, FN_ADIDATA, FN_VI1_CLK_C, FN_VI1_G0_B,
+	FN_MSIOF0_SYNC, FN_TX2_C, FN_ADICS_SAMP, FN_VI1_CLKENB_C, FN_VI1_G1_B,
+	FN_MSIOF0_TXD, FN_ADICLK, FN_VI1_FIELD_C, FN_VI1_G2_B,
+	FN_MSIOF0_RXD, FN_ADICHS0, FN_VI1_DATA0_C, FN_VI1_G3_B,
+	FN_MSIOF0_SS1, FN_MMC_D6, FN_ADICHS1, FN_TX0_E,
+	FN_VI1_HSYNC_N_C, FN_SCL7_C, FN_VI1_G4_B,
+	FN_MSIOF0_SS2, FN_MMC_D7, FN_ADICHS2, FN_RX0_E,
+	FN_VI1_VSYNC_N_C, FN_SDA7_C, FN_VI1_G5_B,
+
+	/* IPSR15 */
+	FN_SIM0_RST, FN_IETX, FN_CAN1_TX_D,
+	FN_SIM0_CLK, FN_IECLK, FN_CAN_CLK_C,
+	FN_SIM0_D, FN_IERX, FN_CAN1_RX_D,
+	FN_GPS_CLK, FN_DU1_DOTCLKIN_C, FN_AUDIO_CLKB_B,
+	FN_PWM5_B, FN_SCIFA3_TXD_C,
+	FN_GPS_SIGN, FN_TX4_C, FN_SCIFA4_TXD_C, FN_PWM5,
+	FN_VI1_G6_B, FN_SCIFA3_RXD_C,
+	FN_GPS_MAG, FN_RX4_C, FN_SCIFA4_RXD_C, FN_PWM6,
+	FN_VI1_G7_B, FN_SCIFA3_SCK_C,
+	FN_HCTS0_N, FN_SCIFB0_CTS_N, FN_GLO_I0_C, FN_TCLK1, FN_VI1_DATA1_C,
+	FN_HRTS0_N, FN_SCIFB0_RTS_N, FN_GLO_I1_C, FN_VI1_DATA2_C,
+	FN_HSCK0, FN_SCIFB0_SCK, FN_GLO_Q0_C, FN_CAN_CLK,
+	FN_TCLK2, FN_VI1_DATA3_C,
+	FN_HRX0, FN_SCIFB0_RXD, FN_GLO_Q1_C, FN_CAN0_RX_B, FN_VI1_DATA4_C,
+	FN_HTX0, FN_SCIFB0_TXD, FN_GLO_SCLK_C, FN_CAN0_TX_B, FN_VI1_DATA5_C,
+
+	/* IPSR16 */
+	FN_HRX1, FN_SCIFB1_RXD, FN_VI1_R0_B, FN_GLO_SDATA_C, FN_VI1_DATA6_C,
+	FN_HTX1, FN_SCIFB1_TXD, FN_VI1_R1_B, FN_GLO_SS_C, FN_VI1_DATA7_C,
+	FN_HSCK1, FN_SCIFB1_SCK, FN_MLB_CK, FN_GLO_RFON_C,
+	FN_HCTS1_N, FN_SCIFB1_CTS_N, FN_MLB_SIG, FN_CAN1_TX_B,
+	FN_HRTS1_N, FN_SCIFB1_RTS_N, FN_MLB_DAT, FN_CAN1_RX_B,
+
+	/* MOD_SEL */
+	FN_SEL_SCIF1_0, FN_SEL_SCIF1_1, FN_SEL_SCIF1_2, FN_SEL_SCIF1_3,
+	FN_SEL_SCIFB_0, FN_SEL_SCIFB_1, FN_SEL_SCIFB_2, FN_SEL_SCIFB_3,
+	FN_SEL_SCIFB2_0, FN_SEL_SCIFB2_1, FN_SEL_SCIFB2_2, FN_SEL_SCIFB2_3,
+	FN_SEL_SCIFB1_0, FN_SEL_SCIFB1_1, FN_SEL_SCIFB1_2, FN_SEL_SCIFB1_3,
+	FN_SEL_SCIFA1_0, FN_SEL_SCIFA1_1, FN_SEL_SCIFA1_2,
+	FN_SEL_SSI9_0, FN_SEL_SSI9_1,
+	FN_SEL_SCFA_0, FN_SEL_SCFA_1,
+	FN_SEL_QSP_0, FN_SEL_QSP_1,
+	FN_SEL_SSI7_0, FN_SEL_SSI7_1,
+	FN_SEL_HSCIF1_0, FN_SEL_HSCIF1_1, FN_SEL_HSCIF1_2, FN_SEL_HSCIF1_3,
+	FN_SEL_HSCIF1_4,
+	FN_SEL_VI1_0, FN_SEL_VI1_1, FN_SEL_VI1_2,
+	FN_SEL_TMU1_0, FN_SEL_TMU1_1,
+	FN_SEL_LBS_0, FN_SEL_LBS_1, FN_SEL_LBS_2, FN_SEL_LBS_3,
+	FN_SEL_TSIF0_0, FN_SEL_TSIF0_1, FN_SEL_TSIF0_2, FN_SEL_TSIF0_3,
+	FN_SEL_SOF0_0, FN_SEL_SOF0_1, FN_SEL_SOF0_2,
+
+	/* MOD_SEL2 */
+	FN_SEL_SCIF0_0, FN_SEL_SCIF0_1, FN_SEL_SCIF0_2, FN_SEL_SCIF0_3,
+	FN_SEL_SCIF0_4,
+	FN_SEL_SCIF_0, FN_SEL_SCIF_1,
+	FN_SEL_CAN0_0, FN_SEL_CAN0_1, FN_SEL_CAN0_2, FN_SEL_CAN0_3,
+	FN_SEL_CAN0_4, FN_SEL_CAN0_5,
+	FN_SEL_CAN1_0, FN_SEL_CAN1_1, FN_SEL_CAN1_2, FN_SEL_CAN1_3,
+	FN_SEL_SCIFA2_0, FN_SEL_SCIFA2_1,
+	FN_SEL_SCIF4_0, FN_SEL_SCIF4_1, FN_SEL_SCIF4_2,
+	FN_SEL_ADG_0, FN_SEL_ADG_1,
+	FN_SEL_FM_0, FN_SEL_FM_1, FN_SEL_FM_2, FN_SEL_FM_3, FN_SEL_FM_4,
+	FN_SEL_SCIFA5_0, FN_SEL_SCIFA5_1, FN_SEL_SCIFA5_2,
+	FN_SEL_GPS_0, FN_SEL_GPS_1, FN_SEL_GPS_2, FN_SEL_GPS_3,
+	FN_SEL_SCIFA4_0, FN_SEL_SCIFA4_1, FN_SEL_SCIFA4_2,
+	FN_SEL_SCIFA3_0, FN_SEL_SCIFA3_1, FN_SEL_SCIFA3_2,
+	FN_SEL_SIM_0, FN_SEL_SIM_1,
+	FN_SEL_SSI8_0, FN_SEL_SSI8_1,
+
+	/* MOD_SEL3 */
+	FN_SEL_HSCIF2_0, FN_SEL_HSCIF2_1, FN_SEL_HSCIF2_2, FN_SEL_HSCIF2_3,
+	FN_SEL_CANCLK_0, FN_SEL_CANCLK_1, FN_SEL_CANCLK_2, FN_SEL_CANCLK_3,
+	FN_SEL_IIC8_0, FN_SEL_IIC8_1, FN_SEL_IIC8_2,
+	FN_SEL_IIC7_0, FN_SEL_IIC7_1, FN_SEL_IIC7_2,
+	FN_SEL_IIC4_0, FN_SEL_IIC4_1, FN_SEL_IIC4_2,
+	FN_SEL_IIC3_0, FN_SEL_IIC3_1, FN_SEL_IIC3_2, FN_SEL_IIC3_3,
+	FN_SEL_SCIF3_0, FN_SEL_SCIF3_1, FN_SEL_SCIF3_2, FN_SEL_SCIF3_3,
+	FN_SEL_IEB_0, FN_SEL_IEB_1, FN_SEL_IEB_2,
+	FN_SEL_MMC_0, FN_SEL_MMC_1,
+	FN_SEL_SCIF5_0, FN_SEL_SCIF5_1,
+	FN_SEL_IIC2_0, FN_SEL_IIC2_1, FN_SEL_IIC2_2, FN_SEL_IIC2_3,
+	FN_SEL_IIC1_0, FN_SEL_IIC1_1, FN_SEL_IIC1_2, FN_SEL_IIC1_3,
+	FN_SEL_IIC1_4,
+	FN_SEL_IIC0_0, FN_SEL_IIC0_1, FN_SEL_IIC0_2,
+
+	/* MOD_SEL4 */
+	FN_SEL_SOF1_0, FN_SEL_SOF1_1, FN_SEL_SOF1_2, FN_SEL_SOF1_3,
+	FN_SEL_SOF1_4,
+	FN_SEL_HSCIF0_0, FN_SEL_HSCIF0_1, FN_SEL_HSCIF0_2,
+	FN_SEL_DIS_0, FN_SEL_DIS_1, FN_SEL_DIS_2,
+	FN_SEL_RAD_0, FN_SEL_RAD_1,
+	FN_SEL_RCN_0, FN_SEL_RCN_1,
+	FN_SEL_RSP_0, FN_SEL_RSP_1,
+	FN_SEL_SCIF2_0, FN_SEL_SCIF2_1, FN_SEL_SCIF2_2, FN_SEL_SCIF2_3,
+	FN_SEL_SCIF2_4,
+	FN_SEL_SOF2_0, FN_SEL_SOF2_1, FN_SEL_SOF2_2, FN_SEL_SOF2_3,
+	FN_SEL_SOF2_4,
+	FN_SEL_SSI1_0, FN_SEL_SSI1_1,
+	FN_SEL_SSI0_0, FN_SEL_SSI0_1,
+	FN_SEL_SSP_0, FN_SEL_SSP_1, FN_SEL_SSP_2,
+	PINMUX_FUNCTION_END,
+
+	PINMUX_MARK_BEGIN,
+
+	EX_CS0_N_MARK, RD_N_MARK,
+
+	AUDIO_CLKA_MARK,
+
+	VI0_CLK_MARK, VI0_DATA0_VI0_B0_MARK, VI0_DATA1_VI0_B1_MARK,
+	VI0_DATA2_VI0_B2_MARK, VI0_DATA4_VI0_B4_MARK, VI0_DATA5_VI0_B5_MARK,
+	VI0_DATA6_VI0_B6_MARK, VI0_DATA7_VI0_B7_MARK,
+
+	SD1_CLK_MARK,
+
+	USB0_PWEN_MARK, USB0_OVC_MARK, USB1_PWEN_MARK, USB1_OVC_MARK,
+	DU0_DOTCLKIN_MARK,
+
+	/* IPSR0 */
+	D0_MARK, D1_MARK, D2_MARK, D3_MARK, D4_MARK, D5_MARK,
+	D6_MARK, D7_MARK, D8_MARK,
+	D9_MARK, D10_MARK, D11_MARK, D12_MARK, D13_MARK, D14_MARK, D15_MARK,
+	A0_MARK, ATAWR0_N_C_MARK, MSIOF0_SCK_B_MARK, SCL0_C_MARK, PWM2_B_MARK,
+	A1_MARK, MSIOF0_SYNC_B_MARK, A2_MARK, MSIOF0_SS1_B_MARK,
+	A3_MARK, MSIOF0_SS2_B_MARK, A4_MARK, MSIOF0_TXD_B_MARK,
+	A5_MARK, MSIOF0_RXD_B_MARK, A6_MARK, MSIOF1_SCK_MARK,
+
+	/* IPSR1 */
+	A7_MARK, MSIOF1_SYNC_MARK, A8_MARK, MSIOF1_SS1_MARK, SCL0_MARK,
+	A9_MARK, MSIOF1_SS2_MARK, SDA0_MARK,
+	A10_MARK, MSIOF1_TXD_MARK, MSIOF1_TXD_D_MARK,
+	A11_MARK, MSIOF1_RXD_MARK, SCL3_D_MARK, MSIOF1_RXD_D_MARK,
+	A12_MARK, FMCLK_MARK, SDA3_D_MARK, MSIOF1_SCK_D_MARK,
+	A13_MARK, ATAG0_N_C_MARK, BPFCLK_MARK, MSIOF1_SS1_D_MARK,
+	A14_MARK, ATADIR0_N_C_MARK, FMIN_MARK, FMIN_C_MARK, MSIOF1_SYNC_D_MARK,
+	A15_MARK, BPFCLK_C_MARK,
+	A16_MARK, DREQ2_B_MARK, FMCLK_C_MARK, SCIFA1_SCK_B_MARK,
+	A17_MARK, DACK2_B_MARK, SDA0_C_MARK,
+	A18_MARK, DREQ1_MARK, SCIFA1_RXD_C_MARK, SCIFB1_RXD_C_MARK,
+
+	/* IPSR2 */
+	A19_MARK, DACK1_MARK, SCIFA1_TXD_C_MARK,
+	SCIFB1_TXD_C_MARK, SCIFB1_SCK_B_MARK,
+	A20_MARK, SPCLK_MARK,
+	A21_MARK, ATAWR0_N_B_MARK, MOSI_IO0_MARK,
+	A22_MARK, MISO_IO1_MARK, FMCLK_B_MARK, TX0_MARK, SCIFA0_TXD_MARK,
+	A23_MARK, IO2_MARK, BPFCLK_B_MARK, RX0_MARK, SCIFA0_RXD_MARK,
+	A24_MARK, DREQ2_MARK, IO3_MARK, TX1_MARK, SCIFA1_TXD_MARK,
+	A25_MARK, DACK2_MARK, SSL_MARK, DREQ1_C_MARK,
+	RX1_MARK, SCIFA1_RXD_MARK,
+	CS0_N_MARK, ATAG0_N_B_MARK, SCL1_MARK,
+	CS1_N_A26_MARK, ATADIR0_N_B_MARK, SDA1_MARK,
+	EX_CS1_N_MARK, MSIOF2_SCK_MARK,
+	EX_CS2_N_MARK, ATAWR0_N_MARK, MSIOF2_SYNC_MARK,
+	EX_CS3_N_MARK, ATADIR0_N_MARK, MSIOF2_TXD_MARK,
+	ATAG0_N_MARK, EX_WAIT1_MARK,
+
+	/* IPSR3 */
+	EX_CS4_N_MARK, ATARD0_N_MARK, MSIOF2_RXD_MARK, EX_WAIT2_MARK,
+	EX_CS5_N_MARK, ATACS00_N_MARK, MSIOF2_SS1_MARK, HRX1_B_MARK,
+	SCIFB1_RXD_B_MARK, PWM1_MARK, TPU_TO1_MARK,
+	BS_N_MARK, ATACS10_N_MARK, MSIOF2_SS2_MARK, HTX1_B_MARK,
+	SCIFB1_TXD_B_MARK, PWM2_MARK, TPU_TO2_MARK,
+	RD_WR_N_MARK, HRX2_B_MARK, FMIN_B_MARK,
+	SCIFB0_RXD_B_MARK, DREQ1_D_MARK,
+	WE0_N_MARK, HCTS2_N_B_MARK, SCIFB0_TXD_B_MARK,
+	WE1_N_MARK, ATARD0_N_B_MARK, HTX2_B_MARK, SCIFB0_RTS_N_B_MARK,
+	EX_WAIT0_MARK, HRTS2_N_B_MARK, SCIFB0_CTS_N_B_MARK,
+	DREQ0_MARK, PWM3_MARK, TPU_TO3_MARK,
+	DACK0_MARK, DRACK0_MARK, REMOCON_MARK,
+	SPEEDIN_MARK, HSCK0_C_MARK, HSCK2_C_MARK, SCIFB0_SCK_B_MARK,
+	SCIFB2_SCK_B_MARK, DREQ2_C_MARK, HTX2_D_MARK,
+	SSI_SCK0129_MARK, HRX0_C_MARK, HRX2_C_MARK,
+	SCIFB0_RXD_C_MARK, SCIFB2_RXD_C_MARK,
+	SSI_WS0129_MARK, HTX0_C_MARK, HTX2_C_MARK,
+	SCIFB0_TXD_C_MARK, SCIFB2_TXD_C_MARK,
+
+	/* IPSR4 */
+	SSI_SDATA0_MARK, SCL0_B_MARK, SCL7_B_MARK, MSIOF2_SCK_C_MARK,
+	SSI_SCK1_MARK, SDA0_B_MARK, SDA7_B_MARK,
+	MSIOF2_SYNC_C_MARK, GLO_I0_D_MARK,
+	SSI_WS1_MARK, SCL1_B_MARK, SCL8_B_MARK,
+	MSIOF2_TXD_C_MARK, GLO_I1_D_MARK,
+	SSI_SDATA1_MARK, SDA1_B_MARK, SDA8_B_MARK, MSIOF2_RXD_C_MARK,
+	SSI_SCK2_MARK, SCL2_MARK, GPS_CLK_B_MARK, GLO_Q0_D_MARK, HSCK1_E_MARK,
+	SSI_WS2_MARK, SDA2_MARK, GPS_SIGN_B_MARK, RX2_E_MARK,
+	GLO_Q1_D_MARK, HCTS1_N_E_MARK,
+	SSI_SDATA2_MARK, GPS_MAG_B_MARK, TX2_E_MARK, HRTS1_N_E_MARK,
+	SSI_SCK34_MARK, SSI_WS34_MARK, SSI_SDATA3_MARK,
+	SSI_SCK4_MARK, GLO_SS_D_MARK,
+	SSI_WS4_MARK, GLO_RFON_D_MARK,
+	SSI_SDATA4_MARK, MSIOF2_SCK_D_MARK,
+	SSI_SCK5_MARK, MSIOF1_SCK_C_MARK, TS_SDATA0_MARK, GLO_I0_MARK,
+	MSIOF2_SYNC_D_MARK, VI1_R2_B_MARK,
+
+	/* IPSR5 */
+	SSI_WS5_MARK, MSIOF1_SYNC_C_MARK, TS_SCK0_MARK, GLO_I1_MARK,
+	MSIOF2_TXD_D_MARK, VI1_R3_B_MARK,
+	SSI_SDATA5_MARK, MSIOF1_TXD_C_MARK, TS_SDEN0_MARK, GLO_Q0_MARK,
+	MSIOF2_SS1_D_MARK, VI1_R4_B_MARK,
+	SSI_SCK6_MARK, MSIOF1_RXD_C_MARK, TS_SPSYNC0_MARK, GLO_Q1_MARK,
+	MSIOF2_RXD_D_MARK, VI1_R5_B_MARK,
+	SSI_WS6_MARK, GLO_SCLK_MARK, MSIOF2_SS2_D_MARK, VI1_R6_B_MARK,
+	SSI_SDATA6_MARK, STP_IVCXO27_0_B_MARK, GLO_SDATA_MARK, VI1_R7_B_MARK,
+	SSI_SCK78_MARK, STP_ISCLK_0_B_MARK, GLO_SS_MARK,
+	SSI_WS78_MARK, TX0_D_MARK, STP_ISD_0_B_MARK, GLO_RFON_MARK,
+	SSI_SDATA7_MARK, RX0_D_MARK, STP_ISEN_0_B_MARK,
+	SSI_SDATA8_MARK, TX1_D_MARK, STP_ISSYNC_0_B_MARK,
+	SSI_SCK9_MARK, RX1_D_MARK, GLO_SCLK_D_MARK,
+	SSI_WS9_MARK, TX3_D_MARK, CAN0_TX_D_MARK, GLO_SDATA_D_MARK,
+	SSI_SDATA9_MARK, RX3_D_MARK, CAN0_RX_D_MARK,
+
+	/* IPSR6 */
+	AUDIO_CLKB_MARK, STP_OPWM_0_B_MARK, MSIOF1_SCK_B_MARK,
+	SCIF_CLK_MARK, BPFCLK_E_MARK,
+	AUDIO_CLKC_MARK, SCIFB0_SCK_C_MARK, MSIOF1_SYNC_B_MARK, RX2_MARK,
+	SCIFA2_RXD_MARK, FMIN_E_MARK,
+	AUDIO_CLKOUT_MARK, MSIOF1_SS1_B_MARK, TX2_MARK, SCIFA2_TXD_MARK,
+	IRQ0_MARK, SCIFB1_RXD_D_MARK, INTC_IRQ0_N_MARK,
+	IRQ1_MARK, SCIFB1_SCK_C_MARK, INTC_IRQ1_N_MARK,
+	IRQ2_MARK, SCIFB1_TXD_D_MARK, INTC_IRQ2_N_MARK,
+	IRQ3_MARK, SCL4_C_MARK, MSIOF2_TXD_E_MARK, INTC_IRQ3_N_MARK,
+	IRQ4_MARK, HRX1_C_MARK, SDA4_C_MARK,
+	MSIOF2_RXD_E_MARK, INTC_IRQ4_N_MARK,
+	IRQ5_MARK, HTX1_C_MARK, SCL1_E_MARK, MSIOF2_SCK_E_MARK,
+	IRQ6_MARK, HSCK1_C_MARK, MSIOF1_SS2_B_MARK,
+	SDA1_E_MARK, MSIOF2_SYNC_E_MARK,
+	IRQ7_MARK, HCTS1_N_C_MARK, MSIOF1_TXD_B_MARK,
+	GPS_CLK_C_MARK, GPS_CLK_D_MARK,
+	IRQ8_MARK, HRTS1_N_C_MARK, MSIOF1_RXD_B_MARK,
+	GPS_SIGN_C_MARK, GPS_SIGN_D_MARK,
+
+	/* IPSR7 */
+	IRQ9_MARK, DU1_DOTCLKIN_B_MARK, CAN_CLK_D_MARK, GPS_MAG_C_MARK,
+	SCIF_CLK_B_MARK, GPS_MAG_D_MARK,
+	DU1_DR0_MARK, LCDOUT0_MARK, VI1_DATA0_B_MARK, TX0_B_MARK,
+	SCIFA0_TXD_B_MARK, MSIOF2_SCK_B_MARK,
+	DU1_DR1_MARK, LCDOUT1_MARK, VI1_DATA1_B_MARK, RX0_B_MARK,
+	SCIFA0_RXD_B_MARK, MSIOF2_SYNC_B_MARK,
+	DU1_DR2_MARK, LCDOUT2_MARK, SSI_SCK0129_B_MARK,
+	DU1_DR3_MARK, LCDOUT3_MARK, SSI_WS0129_B_MARK,
+	DU1_DR4_MARK, LCDOUT4_MARK, SSI_SDATA0_B_MARK,
+	DU1_DR5_MARK, LCDOUT5_MARK, SSI_SCK1_B_MARK,
+	DU1_DR6_MARK, LCDOUT6_MARK, SSI_WS1_B_MARK,
+	DU1_DR7_MARK, LCDOUT7_MARK, SSI_SDATA1_B_MARK,
+	DU1_DG0_MARK, LCDOUT8_MARK, VI1_DATA2_B_MARK, TX1_B_MARK,
+	SCIFA1_TXD_B_MARK, MSIOF2_SS1_B_MARK,
+	DU1_DG1_MARK, LCDOUT9_MARK, VI1_DATA3_B_MARK, RX1_B_MARK,
+	SCIFA1_RXD_B_MARK, MSIOF2_SS2_B_MARK,
+	DU1_DG2_MARK, LCDOUT10_MARK, VI1_DATA4_B_MARK, SCIF1_SCK_B_MARK,
+	SCIFA1_SCK_MARK, SSI_SCK78_B_MARK,
+
+	/* IPSR8 */
+	DU1_DG3_MARK, LCDOUT11_MARK, VI1_DATA5_B_MARK, SSI_WS78_B_MARK,
+	DU1_DG4_MARK, LCDOUT12_MARK, VI1_DATA6_B_MARK, HRX0_B_MARK,
+	SCIFB2_RXD_B_MARK, SSI_SDATA7_B_MARK,
+	DU1_DG5_MARK, LCDOUT13_MARK, VI1_DATA7_B_MARK, HCTS0_N_B_MARK,
+	SCIFB2_TXD_B_MARK, SSI_SDATA8_B_MARK,
+	DU1_DG6_MARK, LCDOUT14_MARK, HRTS0_N_B_MARK,
+	SCIFB2_CTS_N_B_MARK, SSI_SCK9_B_MARK,
+	DU1_DG7_MARK, LCDOUT15_MARK, HTX0_B_MARK,
+	SCIFB2_RTS_N_B_MARK, SSI_WS9_B_MARK,
+	DU1_DB0_MARK, LCDOUT16_MARK, VI1_CLK_B_MARK, TX2_B_MARK,
+	SCIFA2_TXD_B_MARK, MSIOF2_TXD_B_MARK,
+	DU1_DB1_MARK, LCDOUT17_MARK, VI1_HSYNC_N_B_MARK, RX2_B_MARK,
+	SCIFA2_RXD_B_MARK, MSIOF2_RXD_B_MARK,
+	DU1_DB2_MARK, LCDOUT18_MARK, VI1_VSYNC_N_B_MARK, SCIF2_SCK_B_MARK,
+	SCIFA2_SCK_MARK, SSI_SDATA9_B_MARK,
+	DU1_DB3_MARK, LCDOUT19_MARK, VI1_CLKENB_B_MARK,
+	DU1_DB4_MARK, LCDOUT20_MARK, VI1_FIELD_B_MARK, CAN1_RX_MARK,
+	DU1_DB5_MARK, LCDOUT21_MARK, TX3_MARK, SCIFA3_TXD_MARK, CAN1_TX_MARK,
+
+	/* IPSR9 */
+	DU1_DB6_MARK, LCDOUT22_MARK, SCL3_C_MARK, RX3_MARK, SCIFA3_RXD_MARK,
+	DU1_DB7_MARK, LCDOUT23_MARK, SDA3_C_MARK,
+	SCIF3_SCK_MARK, SCIFA3_SCK_MARK,
+	DU1_DOTCLKIN_MARK, QSTVA_QVS_MARK,
+	DU1_DOTCLKOUT0_MARK, QCLK_MARK,
+	DU1_DOTCLKOUT1_MARK, QSTVB_QVE_MARK, CAN0_TX_MARK,
+	TX3_B_MARK, SCL2_B_MARK, PWM4_MARK,
+	DU1_EXHSYNC_DU1_HSYNC_MARK, QSTH_QHS_MARK,
+	DU1_EXVSYNC_DU1_VSYNC_MARK, QSTB_QHE_MARK,
+	DU1_EXODDF_DU1_ODDF_DISP_CDE_MARK, QCPV_QDE_MARK,
+	CAN0_RX_MARK, RX3_B_MARK, SDA2_B_MARK,
+	DU1_DISP_MARK, QPOLA_MARK,
+	DU1_CDE_MARK, QPOLB_MARK, PWM4_B_MARK,
+	VI0_CLKENB_MARK, TX4_MARK, SCIFA4_TXD_MARK, TS_SDATA0_D_MARK,
+	VI0_FIELD_MARK, RX4_MARK, SCIFA4_RXD_MARK, TS_SCK0_D_MARK,
+	VI0_HSYNC_N_MARK, TX5_MARK, SCIFA5_TXD_MARK, TS_SDEN0_D_MARK,
+	VI0_VSYNC_N_MARK, RX5_MARK, SCIFA5_RXD_MARK, TS_SPSYNC0_D_MARK,
+	VI0_DATA3_VI0_B3_MARK, SCIF3_SCK_B_MARK, SCIFA3_SCK_B_MARK,
+	VI0_G0_MARK, SCL8_MARK, STP_IVCXO27_0_C_MARK, SCL4_MARK,
+	HCTS2_N_MARK, SCIFB2_CTS_N_MARK, ATAWR1_N_MARK,
+
+	/* IPSR10 */
+	VI0_G1_MARK, SDA8_MARK, STP_ISCLK_0_C_MARK, SDA4_MARK,
+	HRTS2_N_MARK, SCIFB2_RTS_N_MARK, ATADIR1_N_MARK,
+	VI0_G2_MARK, VI2_HSYNC_N_MARK, STP_ISD_0_C_MARK, SCL3_B_MARK,
+	HSCK2_MARK, SCIFB2_SCK_MARK, ATARD1_N_MARK,
+	VI0_G3_MARK, VI2_VSYNC_N_MARK, STP_ISEN_0_C_MARK, SDA3_B_MARK,
+	HRX2_MARK, SCIFB2_RXD_MARK, ATACS01_N_MARK,
+	VI0_G4_MARK, VI2_CLKENB_MARK, STP_ISSYNC_0_C_MARK,
+	HTX2_MARK, SCIFB2_TXD_MARK, SCIFB0_SCK_D_MARK,
+	VI0_G5_MARK, VI2_FIELD_MARK, STP_OPWM_0_C_MARK, FMCLK_D_MARK,
+	CAN0_TX_E_MARK, HTX1_D_MARK, SCIFB0_TXD_D_MARK,
+	VI0_G6_MARK, VI2_CLK_MARK, BPFCLK_D_MARK,
+	VI0_G7_MARK, VI2_DATA0_MARK, FMIN_D_MARK,
+	VI0_R0_MARK, VI2_DATA1_MARK, GLO_I0_B_MARK,
+	TS_SDATA0_C_MARK, ATACS11_N_MARK,
+	VI0_R1_MARK, VI2_DATA2_MARK, GLO_I1_B_MARK,
+	TS_SCK0_C_MARK, ATAG1_N_MARK,
+	VI0_R2_MARK, VI2_DATA3_MARK, GLO_Q0_B_MARK, TS_SDEN0_C_MARK,
+	VI0_R3_MARK, VI2_DATA4_MARK, GLO_Q1_B_MARK, TS_SPSYNC0_C_MARK,
+	VI0_R4_MARK, VI2_DATA5_MARK, GLO_SCLK_B_MARK, TX0_C_MARK, SCL1_D_MARK,
+
+	/* IPSR11 */
+	VI0_R5_MARK, VI2_DATA6_MARK, GLO_SDATA_B_MARK, RX0_C_MARK, SDA1_D_MARK,
+	VI0_R6_MARK, VI2_DATA7_MARK, GLO_SS_B_MARK, TX1_C_MARK, SCL4_B_MARK,
+	VI0_R7_MARK, GLO_RFON_B_MARK, RX1_C_MARK, CAN0_RX_E_MARK,
+	SDA4_B_MARK, HRX1_D_MARK, SCIFB0_RXD_D_MARK,
+	VI1_HSYNC_N_MARK, AVB_RXD0_MARK, TS_SDATA0_B_MARK,
+	TX4_B_MARK, SCIFA4_TXD_B_MARK,
+	VI1_VSYNC_N_MARK, AVB_RXD1_MARK, TS_SCK0_B_MARK,
+	RX4_B_MARK, SCIFA4_RXD_B_MARK,
+	VI1_CLKENB_MARK, AVB_RXD2_MARK, TS_SDEN0_B_MARK,
+	VI1_FIELD_MARK, AVB_RXD3_MARK, TS_SPSYNC0_B_MARK,
+	VI1_CLK_MARK, AVB_RXD4_MARK, VI1_DATA0_MARK, AVB_RXD5_MARK,
+	VI1_DATA1_MARK, AVB_RXD6_MARK, VI1_DATA2_MARK, AVB_RXD7_MARK,
+	VI1_DATA3_MARK, AVB_RX_ER_MARK, VI1_DATA4_MARK, AVB_MDIO_MARK,
+	VI1_DATA5_MARK, AVB_RX_DV_MARK, VI1_DATA6_MARK, AVB_MAGIC_MARK,
+	VI1_DATA7_MARK, AVB_MDC_MARK,
+	ETH_MDIO_MARK, AVB_RX_CLK_MARK, SCL2_C_MARK,
+	ETH_CRS_DV_MARK, AVB_LINK_MARK, SDA2_C_MARK,
+
+	/* IPSR12 */
+	ETH_RX_ER_MARK, AVB_CRS_MARK, SCL3_MARK, SCL7_MARK,
+	ETH_RXD0_MARK, AVB_PHY_INT_MARK, SDA3_MARK, SDA7_MARK,
+	ETH_RXD1_MARK, AVB_GTXREFCLK_MARK, CAN0_TX_C_MARK,
+	SCL2_D_MARK, MSIOF1_RXD_E_MARK,
+	ETH_LINK_MARK, AVB_TXD0_MARK, CAN0_RX_C_MARK,
+	SDA2_D_MARK, MSIOF1_SCK_E_MARK,
+	ETH_REFCLK_MARK, AVB_TXD1_MARK, SCIFA3_RXD_B_MARK,
+	CAN1_RX_C_MARK, MSIOF1_SYNC_E_MARK,
+	ETH_TXD1_MARK, AVB_TXD2_MARK, SCIFA3_TXD_B_MARK,
+	CAN1_TX_C_MARK, MSIOF1_TXD_E_MARK,
+	ETH_TX_EN_MARK, AVB_TXD3_MARK, TCLK1_B_MARK, CAN_CLK_B_MARK,
+	ETH_MAGIC_MARK, AVB_TXD4_MARK, IETX_C_MARK,
+	ETH_TXD0_MARK, AVB_TXD5_MARK, IECLK_C_MARK,
+	ETH_MDC_MARK, AVB_TXD6_MARK, IERX_C_MARK,
+	STP_IVCXO27_0_MARK, AVB_TXD7_MARK, SCIFB2_TXD_D_MARK,
+	ADIDATA_B_MARK, MSIOF0_SYNC_C_MARK,
+	STP_ISCLK_0_MARK, AVB_TX_EN_MARK, SCIFB2_RXD_D_MARK,
+	ADICS_SAMP_B_MARK, MSIOF0_SCK_C_MARK,
+
+	/* IPSR13 */
+	STP_ISD_0_MARK, AVB_TX_ER_MARK, SCIFB2_SCK_C_MARK,
+	ADICLK_B_MARK, MSIOF0_SS1_C_MARK,
+	STP_ISEN_0_MARK, AVB_TX_CLK_MARK, ADICHS0_B_MARK, MSIOF0_SS2_C_MARK,
+	STP_ISSYNC_0_MARK, AVB_COL_MARK, ADICHS1_B_MARK, MSIOF0_RXD_C_MARK,
+	STP_OPWM_0_MARK, AVB_GTX_CLK_MARK, PWM0_B_MARK,
+	ADICHS2_B_MARK, MSIOF0_TXD_C_MARK,
+	SD0_CLK_MARK, SPCLK_B_MARK, SD0_CMD_MARK, MOSI_IO0_B_MARK,
+	SD0_DATA0_MARK, MISO_IO1_B_MARK, SD0_DATA1_MARK, IO2_B_MARK,
+	SD0_DATA2_MARK, IO3_B_MARK, SD0_DATA3_MARK, SSL_B_MARK,
+	SD0_CD_MARK, MMC_D6_B_MARK, SIM0_RST_B_MARK, CAN0_RX_F_MARK,
+	SCIFA5_TXD_B_MARK, TX3_C_MARK,
+	SD0_WP_MARK, MMC_D7_B_MARK, SIM0_D_B_MARK, CAN0_TX_F_MARK,
+	SCIFA5_RXD_B_MARK, RX3_C_MARK,
+	SD1_CMD_MARK, REMOCON_B_MARK, SD1_DATA0_MARK, SPEEDIN_B_MARK,
+	SD1_DATA1_MARK, IETX_B_MARK, SD1_DATA2_MARK, IECLK_B_MARK,
+	SD1_DATA3_MARK, IERX_B_MARK,
+	SD1_CD_MARK, PWM0_MARK, TPU_TO0_MARK, SCL1_C_MARK,
+
+	/* IPSR14 */
+	SD1_WP_MARK, PWM1_B_MARK, SDA1_C_MARK,
+	SD2_CLK_MARK, MMC_CLK_MARK, SD2_CMD_MARK, MMC_CMD_MARK,
+	SD2_DATA0_MARK, MMC_D0_MARK, SD2_DATA1_MARK, MMC_D1_MARK,
+	SD2_DATA2_MARK, MMC_D2_MARK, SD2_DATA3_MARK, MMC_D3_MARK,
+	SD2_CD_MARK, MMC_D4_MARK, SCL8_C_MARK, TX5_B_MARK, SCIFA5_TXD_C_MARK,
+	SD2_WP_MARK, MMC_D5_MARK, SDA8_C_MARK, RX5_B_MARK, SCIFA5_RXD_C_MARK,
+	MSIOF0_SCK_MARK, RX2_C_MARK, ADIDATA_MARK,
+	VI1_CLK_C_MARK, VI1_G0_B_MARK,
+	MSIOF0_SYNC_MARK, TX2_C_MARK, ADICS_SAMP_MARK,
+	VI1_CLKENB_C_MARK, VI1_G1_B_MARK,
+	MSIOF0_TXD_MARK, ADICLK_MARK, VI1_FIELD_C_MARK, VI1_G2_B_MARK,
+	MSIOF0_RXD_MARK, ADICHS0_MARK, VI1_DATA0_C_MARK, VI1_G3_B_MARK,
+	MSIOF0_SS1_MARK, MMC_D6_MARK, ADICHS1_MARK, TX0_E_MARK,
+	VI1_HSYNC_N_C_MARK, SCL7_C_MARK, VI1_G4_B_MARK,
+	MSIOF0_SS2_MARK, MMC_D7_MARK, ADICHS2_MARK, RX0_E_MARK,
+	VI1_VSYNC_N_C_MARK, SDA7_C_MARK, VI1_G5_B_MARK,
+
+	/* IPSR15 */
+	SIM0_RST_MARK, IETX_MARK, CAN1_TX_D_MARK,
+	SIM0_CLK_MARK, IECLK_MARK, CAN_CLK_C_MARK,
+	SIM0_D_MARK, IERX_MARK, CAN1_RX_D_MARK,
+	GPS_CLK_MARK, DU1_DOTCLKIN_C_MARK, AUDIO_CLKB_B_MARK,
+	PWM5_B_MARK, SCIFA3_TXD_C_MARK,
+	GPS_SIGN_MARK, TX4_C_MARK, SCIFA4_TXD_C_MARK, PWM5_MARK,
+	VI1_G6_B_MARK, SCIFA3_RXD_C_MARK,
+	GPS_MAG_MARK, RX4_C_MARK, SCIFA4_RXD_C_MARK, PWM6_MARK,
+	VI1_G7_B_MARK, SCIFA3_SCK_C_MARK,
+	HCTS0_N_MARK, SCIFB0_CTS_N_MARK, GLO_I0_C_MARK,
+	TCLK1_MARK, VI1_DATA1_C_MARK,
+	HRTS0_N_MARK, SCIFB0_RTS_N_MARK, GLO_I1_C_MARK, VI1_DATA2_C_MARK,
+	HSCK0_MARK, SCIFB0_SCK_MARK, GLO_Q0_C_MARK, CAN_CLK_MARK,
+	TCLK2_MARK, VI1_DATA3_C_MARK,
+	HRX0_MARK, SCIFB0_RXD_MARK, GLO_Q1_C_MARK,
+	CAN0_RX_B_MARK, VI1_DATA4_C_MARK,
+	HTX0_MARK, SCIFB0_TXD_MARK, GLO_SCLK_C_MARK,
+	CAN0_TX_B_MARK, VI1_DATA5_C_MARK,
+
+	/* IPSR16 */
+	HRX1_MARK, SCIFB1_RXD_MARK, VI1_R0_B_MARK,
+	GLO_SDATA_C_MARK, VI1_DATA6_C_MARK,
+	HTX1_MARK, SCIFB1_TXD_MARK, VI1_R1_B_MARK,
+	GLO_SS_C_MARK, VI1_DATA7_C_MARK,
+	HSCK1_MARK, SCIFB1_SCK_MARK, MLB_CK_MARK, GLO_RFON_C_MARK,
+	HCTS1_N_MARK, SCIFB1_CTS_N_MARK, MLB_SIG_MARK, CAN1_TX_B_MARK,
+	HRTS1_N_MARK, SCIFB1_RTS_N_MARK, MLB_DAT_MARK, CAN1_RX_B_MARK,
+	PINMUX_MARK_END,
+};
+
+static const u16 pinmux_data[] = {
+	PINMUX_DATA_GP_ALL(), /* PINMUX_DATA(GP_M_N_DATA, GP_M_N_FN...), */
+
+	PINMUX_DATA(EX_CS0_N_MARK, FN_EX_CS0_N),
+	PINMUX_DATA(RD_N_MARK, FN_RD_N),
+	PINMUX_DATA(AUDIO_CLKA_MARK, FN_AUDIO_CLKA),
+	PINMUX_DATA(VI0_CLK_MARK, FN_VI0_CLK),
+	PINMUX_DATA(VI0_DATA0_VI0_B0_MARK, FN_VI0_DATA0_VI0_B0),
+	PINMUX_DATA(VI0_DATA1_VI0_B1_MARK, FN_VI0_DATA1_VI0_B1),
+	PINMUX_DATA(VI0_DATA2_VI0_B2_MARK, FN_VI0_DATA2_VI0_B2),
+	PINMUX_DATA(VI0_DATA4_VI0_B4_MARK, FN_VI0_DATA4_VI0_B4),
+	PINMUX_DATA(VI0_DATA5_VI0_B5_MARK, FN_VI0_DATA5_VI0_B5),
+	PINMUX_DATA(VI0_DATA6_VI0_B6_MARK, FN_VI0_DATA6_VI0_B6),
+	PINMUX_DATA(VI0_DATA7_VI0_B7_MARK, FN_VI0_DATA7_VI0_B7),
+	PINMUX_DATA(USB0_PWEN_MARK, FN_USB0_PWEN),
+	PINMUX_DATA(USB0_OVC_MARK, FN_USB0_OVC),
+	PINMUX_DATA(USB1_PWEN_MARK, FN_USB1_PWEN),
+	PINMUX_DATA(USB1_OVC_MARK, FN_USB1_OVC),
+	PINMUX_DATA(DU0_DOTCLKIN_MARK, FN_DU0_DOTCLKIN),
+
+	/* IPSR0 */
+	PINMUX_IPSR_DATA(IP0_0, D0),
+	PINMUX_IPSR_DATA(IP0_1, D1),
+	PINMUX_IPSR_DATA(IP0_2, D2),
+	PINMUX_IPSR_DATA(IP0_3, D3),
+	PINMUX_IPSR_DATA(IP0_4, D4),
+	PINMUX_IPSR_DATA(IP0_5, D5),
+	PINMUX_IPSR_DATA(IP0_6, D6),
+	PINMUX_IPSR_DATA(IP0_7, D7),
+	PINMUX_IPSR_DATA(IP0_8, D8),
+	PINMUX_IPSR_DATA(IP0_9, D9),
+	PINMUX_IPSR_DATA(IP0_10, D10),
+	PINMUX_IPSR_DATA(IP0_11, D11),
+	PINMUX_IPSR_DATA(IP0_12, D12),
+	PINMUX_IPSR_DATA(IP0_13, D13),
+	PINMUX_IPSR_DATA(IP0_14, D14),
+	PINMUX_IPSR_DATA(IP0_15, D15),
+	PINMUX_IPSR_DATA(IP0_18_16, A0),
+	PINMUX_IPSR_MODSEL_DATA(IP0_18_16, ATAWR0_N_C, SEL_LBS_2),
+	PINMUX_IPSR_MODSEL_DATA(IP0_18_16, MSIOF0_SCK_B, SEL_SOF0_1),
+	PINMUX_IPSR_MODSEL_DATA(IP0_18_16, SCL0_C, SEL_IIC0_2),
+	PINMUX_IPSR_DATA(IP0_18_16, PWM2_B),
+	PINMUX_IPSR_DATA(IP0_20_19, A1),
+	PINMUX_IPSR_MODSEL_DATA(IP0_20_19, MSIOF0_SYNC_B, SEL_SOF0_1),
+	PINMUX_IPSR_DATA(IP0_22_21, A2),
+	PINMUX_IPSR_MODSEL_DATA(IP0_22_21, MSIOF0_SS1_B, SEL_SOF0_1),
+	PINMUX_IPSR_DATA(IP0_24_23, A3),
+	PINMUX_IPSR_MODSEL_DATA(IP0_24_23, MSIOF0_SS2_B, SEL_SOF0_1),
+	PINMUX_IPSR_DATA(IP0_26_25, A4),
+	PINMUX_IPSR_MODSEL_DATA(IP0_26_25, MSIOF0_TXD_B, SEL_SOF0_1),
+	PINMUX_IPSR_DATA(IP0_28_27, A5),
+	PINMUX_IPSR_MODSEL_DATA(IP0_28_27, MSIOF0_RXD_B, SEL_SOF0_1),
+	PINMUX_IPSR_DATA(IP0_30_29, A6),
+	PINMUX_IPSR_MODSEL_DATA(IP0_30_29, MSIOF1_SCK, SEL_SOF1_0),
+
+	/* IPSR1 */
+	PINMUX_IPSR_DATA(IP1_1_0, A7),
+	PINMUX_IPSR_MODSEL_DATA(IP1_1_0, MSIOF1_SYNC, SEL_SOF1_0),
+	PINMUX_IPSR_DATA(IP1_3_2, A8),
+	PINMUX_IPSR_MODSEL_DATA(IP1_3_2, MSIOF1_SS1, SEL_SOF1_0),
+	PINMUX_IPSR_MODSEL_DATA(IP1_3_2, SCL0, SEL_IIC0_0),
+	PINMUX_IPSR_DATA(IP1_5_4, A9),
+	PINMUX_IPSR_MODSEL_DATA(IP1_5_4, MSIOF1_SS2, SEL_SOF1_0),
+	PINMUX_IPSR_MODSEL_DATA(IP1_5_4, SDA0, SEL_IIC0_0),
+	PINMUX_IPSR_DATA(IP1_7_6, A10),
+	PINMUX_IPSR_MODSEL_DATA(IP1_7_6, MSIOF1_TXD, SEL_SOF1_0),
+	PINMUX_IPSR_MODSEL_DATA(IP1_7_6, MSIOF1_TXD_D, SEL_SOF1_3),
+	PINMUX_IPSR_DATA(IP1_10_8, A11),
+	PINMUX_IPSR_MODSEL_DATA(IP1_10_8, MSIOF1_RXD, SEL_SOF1_0),
+	PINMUX_IPSR_MODSEL_DATA(IP1_10_8, SCL3_D, SEL_IIC3_3),
+	PINMUX_IPSR_MODSEL_DATA(IP1_10_8, MSIOF1_RXD_D, SEL_SOF1_3),
+	PINMUX_IPSR_DATA(IP1_13_11, A12),
+	PINMUX_IPSR_MODSEL_DATA(IP1_13_11, FMCLK, SEL_FM_0),
+	PINMUX_IPSR_MODSEL_DATA(IP1_13_11, SDA3_D, SEL_IIC3_3),
+	PINMUX_IPSR_MODSEL_DATA(IP1_13_11, MSIOF1_SCK_D, SEL_SOF1_3),
+	PINMUX_IPSR_DATA(IP1_16_14, A13),
+	PINMUX_IPSR_MODSEL_DATA(IP1_16_14, ATAG0_N_C, SEL_LBS_2),
+	PINMUX_IPSR_MODSEL_DATA(IP1_16_14, BPFCLK, SEL_FM_0),
+	PINMUX_IPSR_MODSEL_DATA(IP1_16_14, MSIOF1_SS1_D, SEL_SOF1_3),
+	PINMUX_IPSR_DATA(IP1_19_17, A14),
+	PINMUX_IPSR_MODSEL_DATA(IP1_19_17, ATADIR0_N_C, SEL_LBS_2),
+	PINMUX_IPSR_MODSEL_DATA(IP1_19_17, FMIN, SEL_FM_0),
+	PINMUX_IPSR_MODSEL_DATA(IP1_19_17, FMIN_C, SEL_FM_2),
+	PINMUX_IPSR_MODSEL_DATA(IP1_19_17, MSIOF1_SYNC_D, SEL_SOF1_3),
+	PINMUX_IPSR_DATA(IP1_22_20, A15),
+	PINMUX_IPSR_MODSEL_DATA(IP1_22_20, BPFCLK_C, SEL_FM_2),
+	PINMUX_IPSR_DATA(IP1_25_23, A16),
+	PINMUX_IPSR_MODSEL_DATA(IP1_25_23, DREQ2_B, SEL_LBS_1),
+	PINMUX_IPSR_MODSEL_DATA(IP1_25_23, FMCLK_C, SEL_FM_2),
+	PINMUX_IPSR_MODSEL_DATA(IP1_25_23, SCIFA1_SCK_B, SEL_SCIFA1_1),
+	PINMUX_IPSR_DATA(IP1_28_26, A17),
+	PINMUX_IPSR_MODSEL_DATA(IP1_28_26, DACK2_B, SEL_LBS_1),
+	PINMUX_IPSR_MODSEL_DATA(IP1_28_26, SDA0_C, SEL_IIC0_2),
+	PINMUX_IPSR_DATA(IP1_31_29, A18),
+	PINMUX_IPSR_MODSEL_DATA(IP1_31_29, DREQ1, SEL_LBS_0),
+	PINMUX_IPSR_MODSEL_DATA(IP1_31_29, SCIFA1_RXD_C, SEL_SCIFA1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP1_31_29, SCIFB1_RXD_C, SEL_SCIFB1_2),
+
+	/* IPSR2 */
+	PINMUX_IPSR_DATA(IP2_2_0, A19),
+	PINMUX_IPSR_DATA(IP2_2_0, DACK1),
+	PINMUX_IPSR_MODSEL_DATA(IP2_2_0, SCIFA1_TXD_C, SEL_SCIFA1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP2_2_0, SCIFB1_TXD_C, SEL_SCIFB1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP2_2_0, SCIFB1_SCK_B, SEL_SCIFB1_0),
+	PINMUX_IPSR_DATA(IP2_2_0, A20),
+	PINMUX_IPSR_MODSEL_DATA(IP2_4_3, SPCLK, SEL_QSP_0),
+	PINMUX_IPSR_DATA(IP2_6_5, A21),
+	PINMUX_IPSR_MODSEL_DATA(IP2_6_5, ATAWR0_N_B, SEL_LBS_1),
+	PINMUX_IPSR_MODSEL_DATA(IP2_6_5, MOSI_IO0, SEL_QSP_0),
+	PINMUX_IPSR_DATA(IP2_9_7, A22),
+	PINMUX_IPSR_MODSEL_DATA(IP2_9_7, MISO_IO1, SEL_QSP_0),
+	PINMUX_IPSR_MODSEL_DATA(IP2_9_7, FMCLK_B, SEL_FM_1),
+	PINMUX_IPSR_MODSEL_DATA(IP2_9_7, TX0, SEL_SCIF0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP2_9_7, SCIFA0_TXD, SEL_SCFA_0),
+	PINMUX_IPSR_DATA(IP2_12_10, A23),
+	PINMUX_IPSR_MODSEL_DATA(IP2_12_10, IO2, SEL_QSP_0),
+	PINMUX_IPSR_MODSEL_DATA(IP2_12_10, BPFCLK_B, SEL_FM_1),
+	PINMUX_IPSR_MODSEL_DATA(IP2_12_10, RX0, SEL_SCIF0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP2_12_10, SCIFA0_RXD, SEL_SCFA_0),
+	PINMUX_IPSR_DATA(IP2_15_13, A24),
+	PINMUX_IPSR_MODSEL_DATA(IP2_15_13, DREQ2, SEL_LBS_0),
+	PINMUX_IPSR_MODSEL_DATA(IP2_15_13, IO3, SEL_QSP_0),
+	PINMUX_IPSR_MODSEL_DATA(IP2_15_13, TX1, SEL_SCIF1_0),
+	PINMUX_IPSR_MODSEL_DATA(IP2_15_13, SCIFA1_TXD, SEL_SCIFA1_0),
+	PINMUX_IPSR_DATA(IP2_18_16, A25),
+	PINMUX_IPSR_MODSEL_DATA(IP2_18_16, DACK2, SEL_LBS_0),
+	PINMUX_IPSR_MODSEL_DATA(IP2_18_16, SSL, SEL_QSP_0),
+	PINMUX_IPSR_MODSEL_DATA(IP2_18_16, DREQ1_C, SEL_LBS_2),
+	PINMUX_IPSR_MODSEL_DATA(IP2_18_16, RX1, SEL_SCIF1_0),
+	PINMUX_IPSR_MODSEL_DATA(IP2_18_16, SCIFA1_RXD, SEL_SCIFA1_0),
+	PINMUX_IPSR_DATA(IP2_20_19, CS0_N),
+	PINMUX_IPSR_MODSEL_DATA(IP2_20_19, ATAG0_N_B, SEL_LBS_1),
+	PINMUX_IPSR_MODSEL_DATA(IP2_20_19, SCL1, SEL_IIC1_0),
+	PINMUX_IPSR_DATA(IP2_22_21, CS1_N_A26),
+	PINMUX_IPSR_MODSEL_DATA(IP2_22_21, ATADIR0_N_B, SEL_LBS_1),
+	PINMUX_IPSR_MODSEL_DATA(IP2_22_21, SDA1, SEL_IIC1_0),
+	PINMUX_IPSR_DATA(IP2_24_23, EX_CS1_N),
+	PINMUX_IPSR_MODSEL_DATA(IP2_24_23, MSIOF2_SCK, SEL_SOF2_0),
+	PINMUX_IPSR_DATA(IP2_26_25, EX_CS2_N),
+	PINMUX_IPSR_MODSEL_DATA(IP2_26_25, ATAWR0_N, SEL_LBS_0),
+	PINMUX_IPSR_MODSEL_DATA(IP2_26_25, MSIOF2_SYNC, SEL_SOF2_0),
+	PINMUX_IPSR_DATA(IP2_29_27, EX_CS3_N),
+	PINMUX_IPSR_MODSEL_DATA(IP2_29_27, ATADIR0_N, SEL_LBS_0),
+	PINMUX_IPSR_MODSEL_DATA(IP2_29_27, MSIOF2_TXD, SEL_SOF2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP2_29_27, ATAG0_N, SEL_LBS_0),
+	PINMUX_IPSR_DATA(IP2_29_27, EX_WAIT1),
+
+	/* IPSR3 */
+	PINMUX_IPSR_DATA(IP3_2_0, EX_CS4_N),
+	PINMUX_IPSR_MODSEL_DATA(IP3_2_0, ATARD0_N, SEL_LBS_0),
+	PINMUX_IPSR_MODSEL_DATA(IP3_2_0, MSIOF2_RXD, SEL_SOF2_0),
+	PINMUX_IPSR_DATA(IP3_2_0, EX_WAIT2),
+	PINMUX_IPSR_DATA(IP3_5_3, EX_CS5_N),
+	PINMUX_IPSR_DATA(IP3_5_3, ATACS00_N),
+	PINMUX_IPSR_MODSEL_DATA(IP3_5_3, MSIOF2_SS1, SEL_SOF2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP3_5_3, HRX1_B, SEL_HSCIF1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP3_5_3, SCIFB1_RXD_B, SEL_SCIFB1_1),
+	PINMUX_IPSR_DATA(IP3_5_3, PWM1),
+	PINMUX_IPSR_DATA(IP3_5_3, TPU_TO1),
+	PINMUX_IPSR_DATA(IP3_8_6, BS_N),
+	PINMUX_IPSR_DATA(IP3_8_6, ATACS10_N),
+	PINMUX_IPSR_MODSEL_DATA(IP3_8_6, MSIOF2_SS2, SEL_SOF2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP3_8_6, HTX1_B, SEL_HSCIF1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP3_8_6, SCIFB1_TXD_B, SEL_SCIFB1_1),
+	PINMUX_IPSR_DATA(IP3_8_6, PWM2),
+	PINMUX_IPSR_DATA(IP3_8_6, TPU_TO2),
+	PINMUX_IPSR_DATA(IP3_11_9, RD_WR_N),
+	PINMUX_IPSR_MODSEL_DATA(IP3_11_9, HRX2_B, SEL_HSCIF2_1),
+	PINMUX_IPSR_MODSEL_DATA(IP3_11_9, FMIN_B, SEL_FM_1),
+	PINMUX_IPSR_MODSEL_DATA(IP3_11_9, SCIFB0_RXD_B, SEL_SCIFB_1),
+	PINMUX_IPSR_MODSEL_DATA(IP3_11_9, DREQ1_D, SEL_LBS_1),
+	PINMUX_IPSR_DATA(IP3_13_12, WE0_N),
+	PINMUX_IPSR_MODSEL_DATA(IP3_13_12, HCTS2_N_B, SEL_HSCIF2_1),
+	PINMUX_IPSR_MODSEL_DATA(IP3_13_12, SCIFB0_TXD_B, SEL_SCIFB_1),
+	PINMUX_IPSR_DATA(IP3_15_14, WE1_N),
+	PINMUX_IPSR_MODSEL_DATA(IP3_15_14, ATARD0_N_B, SEL_LBS_1),
+	PINMUX_IPSR_MODSEL_DATA(IP3_15_14, HTX2_B, SEL_HSCIF2_1),
+	PINMUX_IPSR_MODSEL_DATA(IP3_15_14, SCIFB0_RTS_N_B, SEL_SCIFB_1),
+	PINMUX_IPSR_DATA(IP3_17_16, EX_WAIT0),
+	PINMUX_IPSR_MODSEL_DATA(IP3_17_16, HRTS2_N_B, SEL_HSCIF2_1),
+	PINMUX_IPSR_MODSEL_DATA(IP3_17_16, SCIFB0_CTS_N_B, SEL_SCIFB_1),
+	PINMUX_IPSR_DATA(IP3_19_18, DREQ0),
+	PINMUX_IPSR_DATA(IP3_19_18, PWM3),
+	PINMUX_IPSR_DATA(IP3_19_18, TPU_TO3),
+	PINMUX_IPSR_DATA(IP3_21_20, DACK0),
+	PINMUX_IPSR_DATA(IP3_21_20, DRACK0),
+	PINMUX_IPSR_MODSEL_DATA(IP3_21_20, REMOCON, SEL_RCN_0),
+	PINMUX_IPSR_MODSEL_DATA(IP3_24_22, SPEEDIN, SEL_RSP_0),
+	PINMUX_IPSR_MODSEL_DATA(IP3_24_22, HSCK0_C, SEL_HSCIF0_2),
+	PINMUX_IPSR_MODSEL_DATA(IP3_24_22, HSCK2_C, SEL_HSCIF2_2),
+	PINMUX_IPSR_MODSEL_DATA(IP3_24_22, SCIFB0_SCK_B, SEL_SCIFB_1),
+	PINMUX_IPSR_MODSEL_DATA(IP3_24_22, SCIFB2_SCK_B, SEL_SCIFB2_1),
+	PINMUX_IPSR_MODSEL_DATA(IP3_24_22, DREQ2_C, SEL_LBS_2),
+	PINMUX_IPSR_MODSEL_DATA(IP3_30_28, HTX2_C, SEL_HSCIF2_2),
+	PINMUX_IPSR_MODSEL_DATA(IP3_27_25, SSI_SCK0129, SEL_SSI0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP3_27_25, HRX0_C, SEL_HSCIF0_2),
+	PINMUX_IPSR_MODSEL_DATA(IP3_27_25, HRX2_C, SEL_HSCIF2_2),
+	PINMUX_IPSR_MODSEL_DATA(IP3_27_25, SCIFB0_RXD_C, SEL_SCIFB_2),
+	PINMUX_IPSR_MODSEL_DATA(IP3_27_25, SCIFB2_RXD_C, SEL_SCIFB2_2),
+	PINMUX_IPSR_MODSEL_DATA(IP3_30_28, SSI_WS0129, SEL_SSI0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP3_30_28, HTX0_C, SEL_HSCIF0_2),
+	PINMUX_IPSR_MODSEL_DATA(IP3_30_28, HTX2_C, SEL_HSCIF2_2),
+	PINMUX_IPSR_MODSEL_DATA(IP3_30_28, SCIFB0_TXD_C, SEL_SCIFB_2),
+	PINMUX_IPSR_MODSEL_DATA(IP3_30_28, SCIFB2_TXD_C, SEL_SCIFB2_2),
+
+	/* IPSR4 */
+	PINMUX_IPSR_MODSEL_DATA(IP4_1_0, SSI_SDATA0, SEL_SSI0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP4_1_0, SCL0_B, SEL_IIC0_1),
+	PINMUX_IPSR_MODSEL_DATA(IP4_1_0, SCL7_B, SEL_IIC7_1),
+	PINMUX_IPSR_MODSEL_DATA(IP4_1_0, MSIOF2_SCK_C, SEL_SOF2_2),
+	PINMUX_IPSR_MODSEL_DATA(IP4_4_2, SSI_SCK1, SEL_SSI1_0),
+	PINMUX_IPSR_MODSEL_DATA(IP4_4_2, SDA0_B, SEL_IIC0_1),
+	PINMUX_IPSR_MODSEL_DATA(IP4_4_2, SDA7_B, SEL_IIC7_1),
+	PINMUX_IPSR_MODSEL_DATA(IP4_4_2, MSIOF2_SYNC_C, SEL_SOF2_2),
+	PINMUX_IPSR_MODSEL_DATA(IP4_4_2, GLO_I0_D, SEL_GPS_3),
+	PINMUX_IPSR_MODSEL_DATA(IP4_7_5, SSI_WS1, SEL_SSI1_0),
+	PINMUX_IPSR_MODSEL_DATA(IP4_7_5, SCL1_B, SEL_IIC1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP4_7_5, SCL8_B, SEL_IIC8_1),
+	PINMUX_IPSR_MODSEL_DATA(IP4_7_5, MSIOF2_TXD_C, SEL_SOF2_2),
+	PINMUX_IPSR_MODSEL_DATA(IP4_7_5, GLO_I1_D, SEL_GPS_3),
+	PINMUX_IPSR_MODSEL_DATA(IP4_9_8, SSI_SDATA1, SEL_SSI1_0),
+	PINMUX_IPSR_MODSEL_DATA(IP4_9_8, SDA1_B, SEL_IIC1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP4_9_8, SDA8_B, SEL_IIC8_1),
+	PINMUX_IPSR_MODSEL_DATA(IP4_9_8, MSIOF2_RXD_C, SEL_SOF2_2),
+	PINMUX_IPSR_DATA(IP4_12_10, SSI_SCK2),
+	PINMUX_IPSR_MODSEL_DATA(IP4_12_10, SCL2, SEL_IIC2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP4_12_10, GPS_CLK_B, SEL_GPS_1),
+	PINMUX_IPSR_MODSEL_DATA(IP4_12_10, GLO_Q0_D, SEL_GPS_3),
+	PINMUX_IPSR_DATA(IP4_15_13, SSI_WS2),
+	PINMUX_IPSR_MODSEL_DATA(IP4_15_13, SDA2, SEL_IIC2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP4_15_13, GPS_SIGN_B, SEL_GPS_1),
+	PINMUX_IPSR_MODSEL_DATA(IP4_15_13, RX2_E, SEL_SCIF2_4),
+	PINMUX_IPSR_MODSEL_DATA(IP4_15_13, GLO_Q1_D, SEL_GPS_3),
+	PINMUX_IPSR_DATA(IP4_18_16, SSI_SDATA2),
+	PINMUX_IPSR_MODSEL_DATA(IP4_18_16, GPS_MAG_B, SEL_GPS_1),
+	PINMUX_IPSR_MODSEL_DATA(IP4_18_16, TX2_E, SEL_SCIF2_4),
+	PINMUX_IPSR_DATA(IP4_19, SSI_SCK34),
+	PINMUX_IPSR_DATA(IP4_20, SSI_WS34),
+	PINMUX_IPSR_DATA(IP4_21, SSI_SDATA3),
+	PINMUX_IPSR_DATA(IP4_23_22, SSI_SCK4),
+	PINMUX_IPSR_MODSEL_DATA(IP4_23_22, GLO_SS_D, SEL_GPS_3),
+	PINMUX_IPSR_DATA(IP4_25_24, SSI_WS4),
+	PINMUX_IPSR_MODSEL_DATA(IP4_25_24, GLO_RFON_D, SEL_GPS_3),
+	PINMUX_IPSR_DATA(IP4_27_26, SSI_SDATA4),
+	PINMUX_IPSR_MODSEL_DATA(IP4_27_26, MSIOF2_SCK_D, SEL_SOF2_3),
+	PINMUX_IPSR_DATA(IP4_30_28, SSI_SCK5),
+	PINMUX_IPSR_MODSEL_DATA(IP4_30_28, MSIOF1_SCK_C, SEL_SOF1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP4_30_28, TS_SDATA0, SEL_TSIF0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP4_30_28, GLO_I0, SEL_GPS_0),
+	PINMUX_IPSR_MODSEL_DATA(IP4_30_28, MSIOF2_SYNC_D, SEL_SOF2_3),
+	PINMUX_IPSR_DATA(IP4_30_28, VI1_R2_B),
+
+	/* IPSR5 */
+	PINMUX_IPSR_DATA(IP5_2_0, SSI_WS5),
+	PINMUX_IPSR_MODSEL_DATA(IP5_2_0, MSIOF1_SYNC_C, SEL_SOF1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP5_2_0, TS_SCK0, SEL_TSIF0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_2_0, GLO_I1, SEL_GPS_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_2_0, MSIOF2_TXD_D, SEL_SOF2_3),
+	PINMUX_IPSR_DATA(IP5_2_0, VI1_R3_B),
+	PINMUX_IPSR_DATA(IP5_5_3, SSI_SDATA5),
+	PINMUX_IPSR_MODSEL_DATA(IP5_5_3, MSIOF1_TXD_C, SEL_SOF1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP5_5_3, TS_SDEN0, SEL_TSIF0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_5_3, GLO_Q0, SEL_GPS_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_5_3, MSIOF2_SS1_D, SEL_SOF2_3),
+	PINMUX_IPSR_DATA(IP5_5_3, VI1_R4_B),
+	PINMUX_IPSR_DATA(IP5_8_6, SSI_SCK6),
+	PINMUX_IPSR_MODSEL_DATA(IP5_8_6, MSIOF1_RXD_C, SEL_SOF1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP5_8_6, TS_SPSYNC0, SEL_TSIF0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_8_6, GLO_Q1, SEL_GPS_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_8_6, MSIOF2_RXD_D, SEL_SOF2_3),
+	PINMUX_IPSR_DATA(IP5_8_6, VI1_R5_B),
+	PINMUX_IPSR_DATA(IP5_11_9, SSI_WS6),
+	PINMUX_IPSR_MODSEL_DATA(IP5_11_9, GLO_SCLK, SEL_GPS_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_11_9, MSIOF2_SS2_D, SEL_SOF2_3),
+	PINMUX_IPSR_DATA(IP5_11_9, VI1_R6_B),
+	PINMUX_IPSR_DATA(IP5_14_12, SSI_SDATA6),
+	PINMUX_IPSR_MODSEL_DATA(IP5_14_12, STP_IVCXO27_0_B, SEL_SSP_1),
+	PINMUX_IPSR_MODSEL_DATA(IP5_14_12, GLO_SDATA, SEL_GPS_0),
+	PINMUX_IPSR_DATA(IP5_14_12, VI1_R7_B),
+	PINMUX_IPSR_MODSEL_DATA(IP5_16_15, SSI_SCK78, SEL_SSI7_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_16_15, STP_ISCLK_0_B, SEL_SSP_1),
+	PINMUX_IPSR_MODSEL_DATA(IP5_16_15, GLO_SS, SEL_GPS_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_19_17, SSI_WS78, SEL_SSI7_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_19_17, TX0_D, SEL_SCIF0_3),
+	PINMUX_IPSR_MODSEL_DATA(IP5_19_17, STP_ISD_0_B, SEL_SSP_1),
+	PINMUX_IPSR_MODSEL_DATA(IP5_19_17, GLO_RFON, SEL_GPS_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_21_20, SSI_SDATA7, SEL_SSI7_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_21_20, RX0_D, SEL_SCIF0_3),
+	PINMUX_IPSR_MODSEL_DATA(IP5_21_20, STP_ISEN_0_B, SEL_SSP_1),
+	PINMUX_IPSR_MODSEL_DATA(IP5_23_22, SSI_SDATA8, SEL_SSI8_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_23_22, TX1_D, SEL_SCIF1_3),
+	PINMUX_IPSR_MODSEL_DATA(IP5_23_22, STP_ISSYNC_0_B, SEL_SSP_1),
+	PINMUX_IPSR_MODSEL_DATA(IP5_25_24, SSI_SCK9, SEL_SSI9_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_25_24, RX1_D, SEL_SCIF1_3),
+	PINMUX_IPSR_MODSEL_DATA(IP5_25_24, GLO_SCLK_D, SEL_GPS_3),
+	PINMUX_IPSR_MODSEL_DATA(IP5_28_26, SSI_WS9, SEL_SSI9_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_28_26, TX3_D, SEL_SCIF3_3),
+	PINMUX_IPSR_MODSEL_DATA(IP5_28_26, CAN0_TX_D, SEL_CAN0_3),
+	PINMUX_IPSR_MODSEL_DATA(IP5_28_26, GLO_SDATA_D, SEL_GPS_3),
+	PINMUX_IPSR_MODSEL_DATA(IP5_31_29, SSI_SDATA9, SEL_SSI9_0),
+	PINMUX_IPSR_MODSEL_DATA(IP5_31_29, RX3_D, SEL_SCIF3_3),
+	PINMUX_IPSR_MODSEL_DATA(IP5_31_29, CAN0_RX_D, SEL_CAN0_3),
+
+	/* IPSR6 */
+	PINMUX_IPSR_MODSEL_DATA(IP6_2_0, AUDIO_CLKB, SEL_ADG_0),
+	PINMUX_IPSR_MODSEL_DATA(IP6_2_0, STP_OPWM_0_B, SEL_SSP_1),
+	PINMUX_IPSR_MODSEL_DATA(IP6_2_0, MSIOF1_SCK_B, SEL_SOF1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP6_2_0, SCIF_CLK, SEL_SCIF_0),
+	PINMUX_IPSR_MODSEL_DATA(IP6_2_0, BPFCLK_E, SEL_FM_4),
+	PINMUX_IPSR_DATA(IP6_5_3, AUDIO_CLKC),
+	PINMUX_IPSR_MODSEL_DATA(IP6_5_3, SCIFB0_SCK_C, SEL_SCIFB_2),
+	PINMUX_IPSR_MODSEL_DATA(IP6_5_3, MSIOF1_SYNC_B, SEL_SOF1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP6_5_3, RX2, SEL_SCIF2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP6_5_3, SCIFA2_RXD, SEL_SCIFA2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP6_5_3, FMIN_E, SEL_FM_4),
+	PINMUX_IPSR_DATA(IP6_7_6, AUDIO_CLKOUT),
+	PINMUX_IPSR_MODSEL_DATA(IP6_7_6, MSIOF1_SS1_B, SEL_SOF1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP6_5_3, TX2, SEL_SCIF2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP6_7_6, SCIFA2_TXD, SEL_SCIFA2_0),
+	PINMUX_IPSR_DATA(IP6_9_8, IRQ0),
+	PINMUX_IPSR_MODSEL_DATA(IP6_9_8, SCIFB1_RXD_D, SEL_SCIFB1_3),
+	PINMUX_IPSR_DATA(IP6_9_8, INTC_IRQ0_N),
+	PINMUX_IPSR_DATA(IP6_11_10, IRQ1),
+	PINMUX_IPSR_MODSEL_DATA(IP6_11_10, SCIFB1_SCK_C, SEL_SCIFB1_2),
+	PINMUX_IPSR_DATA(IP6_11_10, INTC_IRQ1_N),
+	PINMUX_IPSR_DATA(IP6_13_12, IRQ2),
+	PINMUX_IPSR_MODSEL_DATA(IP6_13_12, SCIFB1_TXD_D, SEL_SCIFB1_3),
+	PINMUX_IPSR_DATA(IP6_13_12, INTC_IRQ2_N),
+	PINMUX_IPSR_DATA(IP6_15_14, IRQ3),
+	PINMUX_IPSR_MODSEL_DATA(IP6_15_14, SCL4_C, SEL_IIC4_2),
+	PINMUX_IPSR_MODSEL_DATA(IP6_15_14, MSIOF2_TXD_E, SEL_SOF2_4),
+	PINMUX_IPSR_DATA(IP6_15_14, INTC_IRQ4_N),
+	PINMUX_IPSR_DATA(IP6_18_16, IRQ4),
+	PINMUX_IPSR_MODSEL_DATA(IP6_18_16, HRX1_C, SEL_HSCIF1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP6_18_16, SDA4_C, SEL_IIC4_2),
+	PINMUX_IPSR_MODSEL_DATA(IP6_18_16, MSIOF2_RXD_E, SEL_SOF2_4),
+	PINMUX_IPSR_DATA(IP6_18_16, INTC_IRQ4_N),
+	PINMUX_IPSR_DATA(IP6_20_19, IRQ5),
+	PINMUX_IPSR_MODSEL_DATA(IP6_20_19, HTX1_C, SEL_HSCIF1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP6_20_19, SCL1_E, SEL_IIC1_4),
+	PINMUX_IPSR_MODSEL_DATA(IP6_20_19, MSIOF2_SCK_E, SEL_SOF2_4),
+	PINMUX_IPSR_DATA(IP6_23_21, IRQ6),
+	PINMUX_IPSR_MODSEL_DATA(IP6_23_21, HSCK1_C, SEL_HSCIF1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP6_23_21, MSIOF1_SS2_B, SEL_SOF1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP6_23_21, SDA1_E, SEL_IIC1_4),
+	PINMUX_IPSR_MODSEL_DATA(IP6_23_21, MSIOF2_SYNC_E, SEL_SOF2_4),
+	PINMUX_IPSR_DATA(IP6_26_24, IRQ7),
+	PINMUX_IPSR_MODSEL_DATA(IP6_26_24, HCTS1_N_C, SEL_HSCIF1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP6_26_24, MSIOF1_TXD_B, SEL_SOF1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP6_26_24, GPS_CLK_C, SEL_GPS_2),
+	PINMUX_IPSR_MODSEL_DATA(IP6_26_24, GPS_CLK_D, SEL_GPS_3),
+	PINMUX_IPSR_DATA(IP6_29_27, IRQ8),
+	PINMUX_IPSR_MODSEL_DATA(IP6_29_27, HRTS1_N_C, SEL_HSCIF1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP6_29_27, MSIOF1_RXD_B, SEL_SOF1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP6_29_27, GPS_SIGN_C, SEL_GPS_2),
+	PINMUX_IPSR_MODSEL_DATA(IP6_29_27, GPS_SIGN_D, SEL_GPS_3),
+
+	/* IPSR7 */
+	PINMUX_IPSR_DATA(IP7_2_0, IRQ9),
+	PINMUX_IPSR_MODSEL_DATA(IP7_2_0, DU1_DOTCLKIN_B, SEL_DIS_1),
+	PINMUX_IPSR_MODSEL_DATA(IP7_2_0, CAN_CLK_D, SEL_CANCLK_3),
+	PINMUX_IPSR_MODSEL_DATA(IP7_2_0, GPS_MAG_C, SEL_GPS_2),
+	PINMUX_IPSR_MODSEL_DATA(IP7_2_0, SCIF_CLK_B, SEL_SCIF_1),
+	PINMUX_IPSR_MODSEL_DATA(IP7_2_0, GPS_MAG_D, SEL_GPS_3),
+	PINMUX_IPSR_DATA(IP7_5_3, DU1_DR0),
+	PINMUX_IPSR_DATA(IP7_5_3, LCDOUT0),
+	PINMUX_IPSR_MODSEL_DATA(IP7_5_3, VI1_DATA0_B, SEL_VI1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP7_5_3, TX0_B, SEL_SCIF0_1),
+	PINMUX_IPSR_MODSEL_DATA(IP7_5_3, SCIFA0_TXD_B, SEL_SCFA_1),
+	PINMUX_IPSR_MODSEL_DATA(IP7_5_3, MSIOF2_SCK_B, SEL_SOF2_1),
+	PINMUX_IPSR_DATA(IP7_8_6, DU1_DR1),
+	PINMUX_IPSR_DATA(IP7_8_6, LCDOUT1),
+	PINMUX_IPSR_MODSEL_DATA(IP7_8_6, VI1_DATA1_B, SEL_VI1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP7_8_6, RX0_B, SEL_SCIF0_1),
+	PINMUX_IPSR_MODSEL_DATA(IP7_8_6, SCIFA0_RXD_B, SEL_SCFA_1),
+	PINMUX_IPSR_MODSEL_DATA(IP7_8_6, MSIOF2_SYNC_B, SEL_SOF2_1),
+	PINMUX_IPSR_DATA(IP7_10_9, DU1_DR2),
+	PINMUX_IPSR_DATA(IP7_10_9, LCDOUT2),
+	PINMUX_IPSR_MODSEL_DATA(IP7_10_9, SSI_SCK0129_B, SEL_SSI0_1),
+	PINMUX_IPSR_DATA(IP7_12_11, DU1_DR3),
+	PINMUX_IPSR_DATA(IP7_12_11, LCDOUT3),
+	PINMUX_IPSR_MODSEL_DATA(IP7_12_11, SSI_WS0129_B, SEL_SSI0_1),
+	PINMUX_IPSR_DATA(IP7_14_13, DU1_DR4),
+	PINMUX_IPSR_DATA(IP7_14_13, LCDOUT4),
+	PINMUX_IPSR_MODSEL_DATA(IP7_14_13, SSI_SDATA0_B, SEL_SSI0_1),
+	PINMUX_IPSR_DATA(IP7_16_15, DU1_DR5),
+	PINMUX_IPSR_DATA(IP7_16_15, LCDOUT5),
+	PINMUX_IPSR_MODSEL_DATA(IP7_16_15, SSI_SCK1_B, SEL_SSI1_1),
+	PINMUX_IPSR_DATA(IP7_18_17, DU1_DR6),
+	PINMUX_IPSR_DATA(IP7_18_17, LCDOUT6),
+	PINMUX_IPSR_MODSEL_DATA(IP7_18_17, SSI_WS1_B, SEL_SSI1_1),
+	PINMUX_IPSR_DATA(IP7_20_19, DU1_DR7),
+	PINMUX_IPSR_DATA(IP7_20_19, LCDOUT7),
+	PINMUX_IPSR_MODSEL_DATA(IP7_20_19, SSI_SDATA1_B, SEL_SSI1_1),
+	PINMUX_IPSR_DATA(IP7_23_21, DU1_DG0),
+	PINMUX_IPSR_DATA(IP7_23_21, LCDOUT8),
+	PINMUX_IPSR_MODSEL_DATA(IP7_23_21, VI1_DATA2_B, SEL_VI1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP7_23_21, TX1_B, SEL_SCIF1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP7_23_21, SCIFA1_TXD_B, SEL_SCIFA1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP7_23_21, MSIOF2_SS1_B, SEL_SOF2_1),
+	PINMUX_IPSR_DATA(IP7_26_24, DU1_DG1),
+	PINMUX_IPSR_DATA(IP7_26_24, LCDOUT9),
+	PINMUX_IPSR_MODSEL_DATA(IP7_26_24, VI1_DATA3_B, SEL_VI1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP7_26_24, RX1_B, SEL_SCIF1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP7_26_24, SCIFA1_RXD_B, SEL_SCIFA1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP7_26_24, MSIOF2_SS2_B, SEL_SOF2_1),
+	PINMUX_IPSR_DATA(IP7_29_27, DU1_DG2),
+	PINMUX_IPSR_DATA(IP7_29_27, LCDOUT10),
+	PINMUX_IPSR_MODSEL_DATA(IP7_29_27, VI1_DATA4_B, SEL_VI1_1),
+	PINMUX_IPSR_DATA(IP7_29_27, SCIF1_SCK_B),
+	PINMUX_IPSR_MODSEL_DATA(IP7_29_27, SCIFA1_SCK, SEL_SCIFA1_0),
+	PINMUX_IPSR_MODSEL_DATA(IP7_29_27, SSI_SCK78_B, SEL_SSI7_1),
+
+	/* IPSR8 */
+	PINMUX_IPSR_DATA(IP8_2_0, DU1_DG3),
+	PINMUX_IPSR_DATA(IP8_2_0, LCDOUT11),
+	PINMUX_IPSR_MODSEL_DATA(IP8_2_0, VI1_DATA5_B, SEL_VI1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP8_2_0, SSI_WS78_B, SEL_SSI7_1),
+	PINMUX_IPSR_DATA(IP8_5_3, DU1_DG4),
+	PINMUX_IPSR_DATA(IP8_5_3, LCDOUT12),
+	PINMUX_IPSR_MODSEL_DATA(IP8_5_3, VI1_DATA6_B, SEL_VI1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP8_5_3, HRX0_B, SEL_HSCIF0_1),
+	PINMUX_IPSR_MODSEL_DATA(IP8_5_3, SCIFB2_RXD_B, SEL_SCIFB2_1),
+	PINMUX_IPSR_MODSEL_DATA(IP8_5_3, SSI_SDATA7_B, SEL_SSI7_1),
+	PINMUX_IPSR_DATA(IP8_8_6, DU1_DG5),
+	PINMUX_IPSR_DATA(IP8_8_6, LCDOUT13),
+	PINMUX_IPSR_MODSEL_DATA(IP8_8_6, VI1_DATA7_B, SEL_VI1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP8_8_6, HCTS0_N_B, SEL_HSCIF0_1),
+	PINMUX_IPSR_MODSEL_DATA(IP8_8_6, SCIFB2_TXD_B, SEL_SCIFB2_1),
+	PINMUX_IPSR_MODSEL_DATA(IP8_8_6, SSI_SDATA8_B, SEL_SSI8_1),
+	PINMUX_IPSR_DATA(IP8_11_9, DU1_DG6),
+	PINMUX_IPSR_DATA(IP8_11_9, LCDOUT14),
+	PINMUX_IPSR_MODSEL_DATA(IP8_11_9, HRTS0_N_B, SEL_HSCIF0_1),
+	PINMUX_IPSR_MODSEL_DATA(IP8_11_9, SCIFB2_CTS_N_B, SEL_SCIFB2_1),
+	PINMUX_IPSR_MODSEL_DATA(IP8_11_9, SSI_SCK9_B, SEL_SSI9_1),
+	PINMUX_IPSR_DATA(IP8_14_12, DU1_DG7),
+	PINMUX_IPSR_DATA(IP8_14_12, LCDOUT15),
+	PINMUX_IPSR_MODSEL_DATA(IP8_14_12, HTX0_B, SEL_HSCIF0_1),
+	PINMUX_IPSR_MODSEL_DATA(IP8_14_12, SCIFB2_RTS_N_B, SEL_SCIFB2_1),
+	PINMUX_IPSR_MODSEL_DATA(IP8_14_12, SSI_WS9_B, SEL_SSI9_1),
+	PINMUX_IPSR_DATA(IP8_17_15, DU1_DB0),
+	PINMUX_IPSR_DATA(IP8_17_15, LCDOUT16),
+	PINMUX_IPSR_MODSEL_DATA(IP8_17_15, VI1_CLK_B, SEL_VI1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP8_17_15, TX2_B, SEL_SCIF2_1),
+	PINMUX_IPSR_MODSEL_DATA(IP8_17_15, SCIFA2_TXD_B, SEL_SCIFA2_1),
+	PINMUX_IPSR_MODSEL_DATA(IP8_17_15, MSIOF2_TXD_B, SEL_SOF2_1),
+	PINMUX_IPSR_DATA(IP8_20_18, DU1_DB1),
+	PINMUX_IPSR_DATA(IP8_20_18, LCDOUT17),
+	PINMUX_IPSR_MODSEL_DATA(IP8_20_18, VI1_HSYNC_N_B, SEL_VI1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP8_20_18, RX2_B, SEL_SCIF2_1),
+	PINMUX_IPSR_MODSEL_DATA(IP8_20_18, SCIFA2_RXD_B, SEL_SCIFA2_1),
+	PINMUX_IPSR_MODSEL_DATA(IP8_20_18, MSIOF2_RXD_B, SEL_SOF2_1),
+	PINMUX_IPSR_DATA(IP8_23_21, DU1_DB2),
+	PINMUX_IPSR_DATA(IP8_23_21, LCDOUT18),
+	PINMUX_IPSR_MODSEL_DATA(IP8_23_21, VI1_VSYNC_N_B, SEL_VI1_1),
+	PINMUX_IPSR_DATA(IP8_23_21, SCIF2_SCK_B),
+	PINMUX_IPSR_MODSEL_DATA(IP8_23_21, SCIFA2_SCK, SEL_SCIFA2_1),
+	PINMUX_IPSR_MODSEL_DATA(IP8_23_21, SSI_SDATA9_B, SEL_SSI9_1),
+	PINMUX_IPSR_DATA(IP8_25_24, DU1_DB3),
+	PINMUX_IPSR_DATA(IP8_25_24, LCDOUT19),
+	PINMUX_IPSR_MODSEL_DATA(IP8_25_24, VI1_CLKENB_B, SEL_VI1_1),
+	PINMUX_IPSR_DATA(IP8_27_26, DU1_DB4),
+	PINMUX_IPSR_DATA(IP8_27_26, LCDOUT20),
+	PINMUX_IPSR_MODSEL_DATA(IP8_27_26, VI1_FIELD_B, SEL_VI1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP8_27_26, CAN1_RX, SEL_CAN1_0),
+	PINMUX_IPSR_DATA(IP8_30_28, DU1_DB5),
+	PINMUX_IPSR_DATA(IP8_30_28, LCDOUT21),
+	PINMUX_IPSR_MODSEL_DATA(IP8_30_28, TX3, SEL_SCIF3_0),
+	PINMUX_IPSR_MODSEL_DATA(IP8_30_28, SCIFA3_TXD, SEL_SCIFA3_0),
+	PINMUX_IPSR_MODSEL_DATA(IP8_30_28, CAN1_TX, SEL_CAN1_0),
+
+	/* IPSR9 */
+	PINMUX_IPSR_DATA(IP9_2_0, DU1_DB6),
+	PINMUX_IPSR_DATA(IP9_2_0, LCDOUT22),
+	PINMUX_IPSR_MODSEL_DATA(IP9_2_0, SCL3_C, SEL_IIC3_2),
+	PINMUX_IPSR_MODSEL_DATA(IP9_2_0, RX3, SEL_SCIF3_0),
+	PINMUX_IPSR_MODSEL_DATA(IP9_2_0, SCIFA3_RXD, SEL_SCIFA3_0),
+	PINMUX_IPSR_DATA(IP9_5_3, DU1_DB7),
+	PINMUX_IPSR_DATA(IP9_5_3, LCDOUT23),
+	PINMUX_IPSR_MODSEL_DATA(IP9_5_3, SDA3_C, SEL_IIC3_2),
+	PINMUX_IPSR_MODSEL_DATA(IP9_5_3, SCIF3_SCK, SEL_SCIF3_0),
+	PINMUX_IPSR_MODSEL_DATA(IP9_5_3, SCIFA3_SCK, SEL_SCIFA3_0),
+	PINMUX_IPSR_MODSEL_DATA(IP9_6, DU1_DOTCLKIN, SEL_DIS_0),
+	PINMUX_IPSR_DATA(IP9_6, QSTVA_QVS),
+	PINMUX_IPSR_DATA(IP9_7, DU1_DOTCLKOUT0),
+	PINMUX_IPSR_DATA(IP9_7, QCLK),
+	PINMUX_IPSR_DATA(IP9_10_8, DU1_DOTCLKOUT1),
+	PINMUX_IPSR_DATA(IP9_10_8, QSTVB_QVE),
+	PINMUX_IPSR_MODSEL_DATA(IP9_10_8, CAN0_TX, SEL_CAN0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP9_10_8, TX3_B, SEL_SCIF3_1),
+	PINMUX_IPSR_MODSEL_DATA(IP9_10_8, SCL2_B, SEL_IIC2_1),
+	PINMUX_IPSR_DATA(IP9_10_8, PWM4),
+	PINMUX_IPSR_DATA(IP9_11, DU1_EXHSYNC_DU1_HSYNC),
+	PINMUX_IPSR_DATA(IP9_11, QSTH_QHS),
+	PINMUX_IPSR_DATA(IP9_12, DU1_EXVSYNC_DU1_VSYNC),
+	PINMUX_IPSR_DATA(IP9_12, QSTB_QHE),
+	PINMUX_IPSR_DATA(IP9_15_13, DU1_EXODDF_DU1_ODDF_DISP_CDE),
+	PINMUX_IPSR_DATA(IP9_15_13, QCPV_QDE),
+	PINMUX_IPSR_MODSEL_DATA(IP9_15_13, CAN0_RX, SEL_CAN0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP9_15_13, RX3_B, SEL_SCIF3_1),
+	PINMUX_IPSR_MODSEL_DATA(IP9_15_13, SDA2_B, SEL_IIC2_1),
+	PINMUX_IPSR_DATA(IP9_16, DU1_DISP),
+	PINMUX_IPSR_DATA(IP9_16, QPOLA),
+	PINMUX_IPSR_DATA(IP9_18_17, DU1_CDE),
+	PINMUX_IPSR_DATA(IP9_18_17, QPOLB),
+	PINMUX_IPSR_DATA(IP9_18_17, PWM4_B),
+	PINMUX_IPSR_DATA(IP9_20_19, VI0_CLKENB),
+	PINMUX_IPSR_MODSEL_DATA(IP9_20_19, TX4, SEL_SCIF4_0),
+	PINMUX_IPSR_MODSEL_DATA(IP9_20_19, SCIFA4_TXD, SEL_SCIFA4_0),
+	PINMUX_IPSR_MODSEL_DATA(IP9_20_19, TS_SDATA0_D, SEL_TSIF0_3),
+	PINMUX_IPSR_DATA(IP9_22_21, VI0_FIELD),
+	PINMUX_IPSR_MODSEL_DATA(IP9_22_21, RX4, SEL_SCIF4_0),
+	PINMUX_IPSR_MODSEL_DATA(IP9_22_21, SCIFA4_RXD, SEL_SCIFA4_0),
+	PINMUX_IPSR_MODSEL_DATA(IP9_22_21, TS_SCK0_D, SEL_TSIF0_3),
+	PINMUX_IPSR_DATA(IP9_24_23, VI0_HSYNC_N),
+	PINMUX_IPSR_MODSEL_DATA(IP9_24_23, TX5, SEL_SCIF5_0),
+	PINMUX_IPSR_MODSEL_DATA(IP9_24_23, SCIFA5_TXD, SEL_SCIFA5_0),
+	PINMUX_IPSR_MODSEL_DATA(IP9_24_23, TS_SDEN0_D, SEL_TSIF0_3),
+	PINMUX_IPSR_DATA(IP9_26_25, VI0_VSYNC_N),
+	PINMUX_IPSR_MODSEL_DATA(IP9_26_25, RX5, SEL_SCIF5_0),
+	PINMUX_IPSR_MODSEL_DATA(IP9_26_25, SCIFA5_RXD, SEL_SCIFA5_0),
+	PINMUX_IPSR_MODSEL_DATA(IP9_26_25, TS_SPSYNC0_D, SEL_TSIF0_3),
+	PINMUX_IPSR_DATA(IP9_28_27, VI0_DATA3_VI0_B3),
+	PINMUX_IPSR_MODSEL_DATA(IP9_28_27, SCIF3_SCK_B, SEL_SCIF3_1),
+	PINMUX_IPSR_MODSEL_DATA(IP9_28_27, SCIFA3_SCK_B, SEL_SCIFA3_1),
+	PINMUX_IPSR_DATA(IP9_31_29, VI0_G0),
+	PINMUX_IPSR_MODSEL_DATA(IP9_31_29, SCL8, SEL_IIC8_0),
+	PINMUX_IPSR_MODSEL_DATA(IP9_31_29, STP_IVCXO27_0_C, SEL_SSP_2),
+	PINMUX_IPSR_MODSEL_DATA(IP9_31_29, SCL4, SEL_IIC4_0),
+	PINMUX_IPSR_MODSEL_DATA(IP9_31_29, HCTS2_N, SEL_HSCIF2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP9_31_29, SCIFB2_CTS_N, SEL_SCIFB2_0),
+	PINMUX_IPSR_DATA(IP9_31_29, ATAWR1_N),
+
+	/* IPSR10 */
+	PINMUX_IPSR_DATA(IP10_2_0, VI0_G1),
+	PINMUX_IPSR_MODSEL_DATA(IP10_2_0, SDA8, SEL_IIC8_0),
+	PINMUX_IPSR_MODSEL_DATA(IP10_2_0, STP_ISCLK_0_C, SEL_SSP_2),
+	PINMUX_IPSR_MODSEL_DATA(IP10_2_0, SDA4, SEL_IIC4_0),
+	PINMUX_IPSR_MODSEL_DATA(IP10_2_0, HRTS2_N, SEL_HSCIF2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP10_2_0, SCIFB2_RTS_N, SEL_SCIFB2_0),
+	PINMUX_IPSR_DATA(IP10_2_0, ATADIR1_N),
+	PINMUX_IPSR_DATA(IP10_5_3, VI0_G2),
+	PINMUX_IPSR_DATA(IP10_5_3, VI2_HSYNC_N),
+	PINMUX_IPSR_MODSEL_DATA(IP10_5_3, STP_ISD_0_C, SEL_SSP_2),
+	PINMUX_IPSR_MODSEL_DATA(IP10_5_3, SCL3_B, SEL_IIC3_1),
+	PINMUX_IPSR_MODSEL_DATA(IP10_5_3, HSCK2, SEL_HSCIF2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP10_5_3, SCIFB2_SCK, SEL_SCIFB2_0),
+	PINMUX_IPSR_DATA(IP10_5_3, ATARD1_N),
+	PINMUX_IPSR_DATA(IP10_8_6, VI0_G3),
+	PINMUX_IPSR_DATA(IP10_8_6, VI2_VSYNC_N),
+	PINMUX_IPSR_MODSEL_DATA(IP10_8_6, STP_ISEN_0_C, SEL_SSP_2),
+	PINMUX_IPSR_MODSEL_DATA(IP10_8_6, SDA3_B, SEL_IIC3_1),
+	PINMUX_IPSR_MODSEL_DATA(IP10_8_6, HRX2, SEL_HSCIF2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP10_8_6, SCIFB2_RXD, SEL_SCIFB2_0),
+	PINMUX_IPSR_DATA(IP10_8_6, ATACS01_N),
+	PINMUX_IPSR_DATA(IP10_11_9, VI0_G4),
+	PINMUX_IPSR_DATA(IP10_11_9, VI2_CLKENB),
+	PINMUX_IPSR_MODSEL_DATA(IP10_11_9, STP_ISSYNC_0_C, SEL_SSP_2),
+	PINMUX_IPSR_MODSEL_DATA(IP10_11_9, HTX2, SEL_HSCIF2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP10_11_9, SCIFB2_TXD, SEL_SCIFB2_0),
+	PINMUX_IPSR_MODSEL_DATA(IP10_11_9, SCIFB0_SCK_D, SEL_SCIFB_3),
+	PINMUX_IPSR_DATA(IP10_14_12, VI0_G5),
+	PINMUX_IPSR_DATA(IP10_14_12, VI2_FIELD),
+	PINMUX_IPSR_MODSEL_DATA(IP10_14_12, STP_OPWM_0_C, SEL_SSP_2),
+	PINMUX_IPSR_MODSEL_DATA(IP10_14_12, FMCLK_D, SEL_FM_3),
+	PINMUX_IPSR_MODSEL_DATA(IP10_14_12, CAN0_TX_E, SEL_CAN0_4),
+	PINMUX_IPSR_MODSEL_DATA(IP10_14_12, HTX1_D, SEL_HSCIF1_3),
+	PINMUX_IPSR_MODSEL_DATA(IP10_14_12, SCIFB0_TXD_D, SEL_SCIFB_3),
+	PINMUX_IPSR_DATA(IP10_16_15, VI0_G6),
+	PINMUX_IPSR_DATA(IP10_16_15, VI2_CLK),
+	PINMUX_IPSR_MODSEL_DATA(IP10_16_15, BPFCLK_D, SEL_FM_3),
+	PINMUX_IPSR_DATA(IP10_18_17, VI0_G7),
+	PINMUX_IPSR_DATA(IP10_18_17, VI2_DATA0),
+	PINMUX_IPSR_MODSEL_DATA(IP10_18_17, FMIN_D, SEL_FM_3),
+	PINMUX_IPSR_DATA(IP10_21_19, VI0_R0),
+	PINMUX_IPSR_DATA(IP10_21_19, VI2_DATA1),
+	PINMUX_IPSR_MODSEL_DATA(IP10_21_19, GLO_I0_B, SEL_GPS_1),
+	PINMUX_IPSR_MODSEL_DATA(IP10_21_19, TS_SDATA0_C, SEL_TSIF0_2),
+	PINMUX_IPSR_DATA(IP10_21_19, ATACS11_N),
+	PINMUX_IPSR_DATA(IP10_24_22, VI0_R1),
+	PINMUX_IPSR_DATA(IP10_24_22, VI2_DATA2),
+	PINMUX_IPSR_MODSEL_DATA(IP10_24_22, GLO_I1_B, SEL_GPS_1),
+	PINMUX_IPSR_MODSEL_DATA(IP10_24_22, TS_SCK0_C, SEL_TSIF0_2),
+	PINMUX_IPSR_DATA(IP10_24_22, ATAG1_N),
+	PINMUX_IPSR_DATA(IP10_26_25, VI0_R2),
+	PINMUX_IPSR_DATA(IP10_26_25, VI2_DATA3),
+	PINMUX_IPSR_MODSEL_DATA(IP10_26_25, GLO_Q0_B, SEL_GPS_1),
+	PINMUX_IPSR_MODSEL_DATA(IP10_26_25, TS_SDEN0_C, SEL_TSIF0_2),
+	PINMUX_IPSR_DATA(IP10_28_27, VI0_R3),
+	PINMUX_IPSR_DATA(IP10_28_27, VI2_DATA4),
+	PINMUX_IPSR_MODSEL_DATA(IP10_28_27, GLO_Q1_B, SEL_GPS_1),
+	PINMUX_IPSR_MODSEL_DATA(IP10_28_27, TS_SPSYNC0_C, SEL_TSIF0_2),
+	PINMUX_IPSR_DATA(IP10_31_29, VI0_R4),
+	PINMUX_IPSR_DATA(IP10_31_29, VI2_DATA5),
+	PINMUX_IPSR_MODSEL_DATA(IP10_31_29, GLO_SCLK_B, SEL_GPS_1),
+	PINMUX_IPSR_MODSEL_DATA(IP10_31_29, TX0_C, SEL_SCIF0_2),
+	PINMUX_IPSR_MODSEL_DATA(IP10_31_29, SCL1_D, SEL_IIC1_3),
+
+	/* IPSR11 */
+	PINMUX_IPSR_DATA(IP11_2_0, VI0_R5),
+	PINMUX_IPSR_DATA(IP11_2_0, VI2_DATA6),
+	PINMUX_IPSR_MODSEL_DATA(IP11_2_0, GLO_SDATA_B, SEL_GPS_1),
+	PINMUX_IPSR_MODSEL_DATA(IP11_2_0, RX0_C, SEL_SCIF0_2),
+	PINMUX_IPSR_MODSEL_DATA(IP11_2_0, SDA1_D, SEL_IIC1_3),
+	PINMUX_IPSR_DATA(IP11_5_3, VI0_R6),
+	PINMUX_IPSR_DATA(IP11_5_3, VI2_DATA7),
+	PINMUX_IPSR_MODSEL_DATA(IP11_5_3, GLO_SS_B, SEL_GPS_1),
+	PINMUX_IPSR_MODSEL_DATA(IP11_5_3, TX1_C, SEL_SCIF1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP11_5_3, SCL4_B, SEL_IIC4_1),
+	PINMUX_IPSR_DATA(IP11_8_6, VI0_R7),
+	PINMUX_IPSR_MODSEL_DATA(IP11_8_6, GLO_RFON_B, SEL_GPS_1),
+	PINMUX_IPSR_MODSEL_DATA(IP11_8_6, RX1_C, SEL_SCIF1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP11_8_6, CAN0_RX_E, SEL_CAN0_4),
+	PINMUX_IPSR_MODSEL_DATA(IP11_8_6, SDA4_B, SEL_IIC4_1),
+	PINMUX_IPSR_MODSEL_DATA(IP11_8_6, HRX1_D, SEL_HSCIF1_3),
+	PINMUX_IPSR_MODSEL_DATA(IP11_8_6, SCIFB0_RXD_D, SEL_SCIFB_3),
+	PINMUX_IPSR_MODSEL_DATA(IP11_11_9, VI1_HSYNC_N, SEL_VI1_0),
+	PINMUX_IPSR_DATA(IP11_11_9, AVB_RXD0),
+	PINMUX_IPSR_MODSEL_DATA(IP11_11_9, TS_SDATA0_B, SEL_TSIF0_1),
+	PINMUX_IPSR_MODSEL_DATA(IP11_11_9, TX4_B, SEL_SCIF4_1),
+	PINMUX_IPSR_MODSEL_DATA(IP11_11_9, SCIFA4_TXD_B, SEL_SCIFA4_1),
+	PINMUX_IPSR_MODSEL_DATA(IP11_14_12, VI1_VSYNC_N, SEL_VI1_0),
+	PINMUX_IPSR_DATA(IP11_14_12, AVB_RXD1),
+	PINMUX_IPSR_MODSEL_DATA(IP11_14_12, TS_SCK0_B, SEL_TSIF0_1),
+	PINMUX_IPSR_MODSEL_DATA(IP11_14_12, RX4_B, SEL_SCIF4_1),
+	PINMUX_IPSR_MODSEL_DATA(IP11_14_12, SCIFA4_RXD_B, SEL_SCIFA4_1),
+	PINMUX_IPSR_MODSEL_DATA(IP11_16_15, VI1_CLKENB, SEL_VI1_0),
+	PINMUX_IPSR_DATA(IP11_16_15, AVB_RXD2),
+	PINMUX_IPSR_MODSEL_DATA(IP11_16_15, TS_SDEN0_B, SEL_TSIF0_1),
+	PINMUX_IPSR_MODSEL_DATA(IP11_18_17, VI1_FIELD, SEL_VI1_0),
+	PINMUX_IPSR_DATA(IP11_18_17, AVB_RXD3),
+	PINMUX_IPSR_MODSEL_DATA(IP11_18_17, TS_SPSYNC0_B, SEL_TSIF0_1),
+	PINMUX_IPSR_MODSEL_DATA(IP11_19, VI1_CLK, SEL_VI1_0),
+	PINMUX_IPSR_DATA(IP11_19, AVB_RXD4),
+	PINMUX_IPSR_MODSEL_DATA(IP11_20, VI1_DATA0, SEL_VI1_0),
+	PINMUX_IPSR_DATA(IP11_20, AVB_RXD5),
+	PINMUX_IPSR_MODSEL_DATA(IP11_21, VI1_DATA1, SEL_VI1_0),
+	PINMUX_IPSR_DATA(IP11_21, AVB_RXD6),
+	PINMUX_IPSR_MODSEL_DATA(IP11_22, VI1_DATA2, SEL_VI1_0),
+	PINMUX_IPSR_DATA(IP11_22, AVB_RXD7),
+	PINMUX_IPSR_MODSEL_DATA(IP11_23, VI1_DATA3, SEL_VI1_0),
+	PINMUX_IPSR_DATA(IP11_23, AVB_RX_ER),
+	PINMUX_IPSR_MODSEL_DATA(IP11_24, VI1_DATA4, SEL_VI1_0),
+	PINMUX_IPSR_DATA(IP11_24, AVB_MDIO),
+	PINMUX_IPSR_MODSEL_DATA(IP11_25, VI1_DATA5, SEL_VI1_0),
+	PINMUX_IPSR_DATA(IP11_25, AVB_RX_DV),
+	PINMUX_IPSR_MODSEL_DATA(IP11_26, VI1_DATA6, SEL_VI1_0),
+	PINMUX_IPSR_DATA(IP11_26, AVB_MAGIC),
+	PINMUX_IPSR_MODSEL_DATA(IP11_27, VI1_DATA7, SEL_VI1_0),
+	PINMUX_IPSR_DATA(IP11_27, AVB_MDC),
+	PINMUX_IPSR_DATA(IP11_29_28, ETH_MDIO),
+	PINMUX_IPSR_DATA(IP11_29_28, AVB_RX_CLK),
+	PINMUX_IPSR_MODSEL_DATA(IP11_29_28, SCL2_C, SEL_IIC2_2),
+	PINMUX_IPSR_DATA(IP11_31_30, ETH_CRS_DV),
+	PINMUX_IPSR_DATA(IP11_31_30, AVB_LINK),
+	PINMUX_IPSR_MODSEL_DATA(IP11_31_30, SDA2_C, SEL_IIC2_2),
+
+	/* IPSR12 */
+	PINMUX_IPSR_DATA(IP12_1_0, ETH_RX_ER),
+	PINMUX_IPSR_DATA(IP12_1_0, AVB_CRS),
+	PINMUX_IPSR_MODSEL_DATA(IP12_1_0, SCL3, SEL_IIC3_0),
+	PINMUX_IPSR_MODSEL_DATA(IP12_1_0, SCL7, SEL_IIC7_0),
+	PINMUX_IPSR_DATA(IP12_3_2, ETH_RXD0),
+	PINMUX_IPSR_DATA(IP12_3_2, AVB_PHY_INT),
+	PINMUX_IPSR_MODSEL_DATA(IP12_3_2, SDA3, SEL_IIC3_0),
+	PINMUX_IPSR_MODSEL_DATA(IP12_3_2, SDA7, SEL_IIC7_0),
+	PINMUX_IPSR_DATA(IP12_6_4, ETH_RXD1),
+	PINMUX_IPSR_DATA(IP12_6_4, AVB_GTXREFCLK),
+	PINMUX_IPSR_MODSEL_DATA(IP12_6_4, CAN0_TX_C, SEL_CAN0_2),
+	PINMUX_IPSR_MODSEL_DATA(IP12_6_4, SCL2_D, SEL_IIC2_3),
+	PINMUX_IPSR_MODSEL_DATA(IP12_6_4, MSIOF1_RXD_E, SEL_SOF1_4),
+	PINMUX_IPSR_DATA(IP12_9_7, ETH_LINK),
+	PINMUX_IPSR_DATA(IP12_9_7, AVB_TXD0),
+	PINMUX_IPSR_MODSEL_DATA(IP12_9_7, CAN0_RX_C, SEL_CAN0_2),
+	PINMUX_IPSR_MODSEL_DATA(IP12_9_7, SDA2_D, SEL_IIC2_3),
+	PINMUX_IPSR_MODSEL_DATA(IP12_9_7, MSIOF1_SCK_E, SEL_SOF1_4),
+	PINMUX_IPSR_DATA(IP12_12_10, ETH_REFCLK),
+	PINMUX_IPSR_DATA(IP12_12_10, AVB_TXD1),
+	PINMUX_IPSR_MODSEL_DATA(IP12_12_10, SCIFA3_RXD_B, SEL_SCIFA3_1),
+	PINMUX_IPSR_MODSEL_DATA(IP12_12_10, CAN1_RX_C, SEL_CAN1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP12_12_10, MSIOF1_SYNC_E, SEL_SOF1_4),
+	PINMUX_IPSR_DATA(IP12_15_13, ETH_TXD1),
+	PINMUX_IPSR_DATA(IP12_15_13, AVB_TXD2),
+	PINMUX_IPSR_MODSEL_DATA(IP12_15_13, SCIFA3_TXD_B, SEL_SCIFA3_1),
+	PINMUX_IPSR_MODSEL_DATA(IP12_15_13, CAN1_TX_C, SEL_CAN1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP12_15_13, MSIOF1_TXD_E, SEL_SOF1_4),
+	PINMUX_IPSR_DATA(IP12_17_16, ETH_TX_EN),
+	PINMUX_IPSR_DATA(IP12_17_16, AVB_TXD3),
+	PINMUX_IPSR_MODSEL_DATA(IP12_17_16, TCLK1_B, SEL_TMU1_0),
+	PINMUX_IPSR_MODSEL_DATA(IP12_17_16, CAN_CLK_B, SEL_CANCLK_1),
+	PINMUX_IPSR_DATA(IP12_19_18, ETH_MAGIC),
+	PINMUX_IPSR_DATA(IP12_19_18, AVB_TXD4),
+	PINMUX_IPSR_MODSEL_DATA(IP12_19_18, IETX_C, SEL_IEB_2),
+	PINMUX_IPSR_DATA(IP12_21_20, ETH_TXD0),
+	PINMUX_IPSR_DATA(IP12_21_20, AVB_TXD5),
+	PINMUX_IPSR_MODSEL_DATA(IP12_21_20, IECLK_C, SEL_IEB_2),
+	PINMUX_IPSR_DATA(IP12_23_22, ETH_MDC),
+	PINMUX_IPSR_DATA(IP12_23_22, AVB_TXD6),
+	PINMUX_IPSR_MODSEL_DATA(IP12_23_22, IERX_C, SEL_IEB_2),
+	PINMUX_IPSR_MODSEL_DATA(IP12_26_24, STP_IVCXO27_0, SEL_SSP_0),
+	PINMUX_IPSR_DATA(IP12_26_24, AVB_TXD7),
+	PINMUX_IPSR_MODSEL_DATA(IP12_26_24, SCIFB2_TXD_D, SEL_SCIFB2_3),
+	PINMUX_IPSR_MODSEL_DATA(IP12_26_24, ADIDATA_B, SEL_RAD_1),
+	PINMUX_IPSR_MODSEL_DATA(IP12_26_24, MSIOF0_SYNC_C, SEL_SOF0_2),
+	PINMUX_IPSR_MODSEL_DATA(IP12_29_27, STP_ISCLK_0, SEL_SSP_0),
+	PINMUX_IPSR_DATA(IP12_29_27, AVB_TX_EN),
+	PINMUX_IPSR_MODSEL_DATA(IP12_29_27, SCIFB2_RXD_D, SEL_SCIFB2_3),
+	PINMUX_IPSR_MODSEL_DATA(IP12_29_27, ADICS_SAMP_B, SEL_RAD_1),
+	PINMUX_IPSR_MODSEL_DATA(IP12_29_27, MSIOF0_SCK_C, SEL_SOF0_2),
+
+	/* IPSR13 */
+	PINMUX_IPSR_MODSEL_DATA(IP13_2_0, STP_ISD_0, SEL_SSP_0),
+	PINMUX_IPSR_DATA(IP13_2_0, AVB_TX_ER),
+	PINMUX_IPSR_MODSEL_DATA(IP13_2_0, SCIFB2_SCK_C, SEL_SCIFB2_2),
+	PINMUX_IPSR_MODSEL_DATA(IP13_2_0, ADICLK_B, SEL_RAD_1),
+	PINMUX_IPSR_MODSEL_DATA(IP13_2_0, MSIOF0_SS1_C, SEL_SOF0_2),
+	PINMUX_IPSR_MODSEL_DATA(IP13_4_3, STP_ISEN_0, SEL_SSP_0),
+	PINMUX_IPSR_DATA(IP13_4_3, AVB_TX_CLK),
+	PINMUX_IPSR_MODSEL_DATA(IP13_4_3, ADICHS0_B, SEL_RAD_1),
+	PINMUX_IPSR_MODSEL_DATA(IP13_4_3, MSIOF0_SS2_C, SEL_SOF0_2),
+	PINMUX_IPSR_MODSEL_DATA(IP13_6_5, STP_ISSYNC_0, SEL_SSP_0),
+	PINMUX_IPSR_DATA(IP13_6_5, AVB_COL),
+	PINMUX_IPSR_MODSEL_DATA(IP13_6_5, ADICHS1_B, SEL_RAD_1),
+	PINMUX_IPSR_MODSEL_DATA(IP13_6_5, MSIOF0_RXD_C, SEL_SOF0_2),
+	PINMUX_IPSR_MODSEL_DATA(IP13_9_7, STP_OPWM_0, SEL_SSP_0),
+	PINMUX_IPSR_DATA(IP13_9_7, AVB_GTX_CLK),
+	PINMUX_IPSR_DATA(IP13_9_7, PWM0_B),
+	PINMUX_IPSR_MODSEL_DATA(IP13_9_7, ADICHS2_B, SEL_RAD_1),
+	PINMUX_IPSR_MODSEL_DATA(IP13_9_7, MSIOF0_TXD_C, SEL_SOF0_2),
+	PINMUX_IPSR_DATA(IP13_10, SD0_CLK),
+	PINMUX_IPSR_MODSEL_DATA(IP13_10, SPCLK_B, SEL_QSP_1),
+	PINMUX_IPSR_DATA(IP13_11, SD0_CMD),
+	PINMUX_IPSR_MODSEL_DATA(IP13_11, MOSI_IO0_B, SEL_QSP_1),
+	PINMUX_IPSR_DATA(IP13_12, SD0_DATA0),
+	PINMUX_IPSR_MODSEL_DATA(IP13_12, MISO_IO1_B, SEL_QSP_1),
+	PINMUX_IPSR_DATA(IP13_13, SD0_DATA1),
+	PINMUX_IPSR_MODSEL_DATA(IP13_13, IO2_B, SEL_QSP_1),
+	PINMUX_IPSR_DATA(IP13_14, SD0_DATA2),
+	PINMUX_IPSR_MODSEL_DATA(IP13_14, IO3_B, SEL_QSP_1),
+	PINMUX_IPSR_DATA(IP13_15, SD0_DATA3),
+	PINMUX_IPSR_MODSEL_DATA(IP13_15, SSL_B, SEL_QSP_1),
+	PINMUX_IPSR_DATA(IP13_18_16, SD0_CD),
+	PINMUX_IPSR_MODSEL_DATA(IP13_18_16, MMC_D6_B, SEL_MMC_1),
+	PINMUX_IPSR_MODSEL_DATA(IP13_18_16, SIM0_RST_B, SEL_SIM_1),
+	PINMUX_IPSR_MODSEL_DATA(IP13_18_16, CAN0_RX_F, SEL_CAN0_5),
+	PINMUX_IPSR_MODSEL_DATA(IP13_18_16, SCIFA5_TXD_B, SEL_SCIFA5_1),
+	PINMUX_IPSR_MODSEL_DATA(IP13_18_16, TX3_C, SEL_SCIF3_2),
+	PINMUX_IPSR_DATA(IP13_21_19, SD0_WP),
+	PINMUX_IPSR_MODSEL_DATA(IP13_21_19, MMC_D7_B, SEL_MMC_1),
+	PINMUX_IPSR_MODSEL_DATA(IP13_21_19, SIM0_D_B, SEL_SIM_1),
+	PINMUX_IPSR_MODSEL_DATA(IP13_21_19, CAN0_TX_F, SEL_CAN0_5),
+	PINMUX_IPSR_MODSEL_DATA(IP13_21_19, SCIFA5_RXD_B, SEL_SCIFA5_1),
+	PINMUX_IPSR_MODSEL_DATA(IP13_21_19, RX3_C, SEL_SCIF3_2),
+	PINMUX_IPSR_DATA(IP13_22, SD1_CMD),
+	PINMUX_IPSR_MODSEL_DATA(IP13_22, REMOCON_B, SEL_RCN_1),
+	PINMUX_IPSR_DATA(IP13_24_23, SD1_DATA0),
+	PINMUX_IPSR_MODSEL_DATA(IP13_24_23, SPEEDIN_B, SEL_RSP_1),
+	PINMUX_IPSR_DATA(IP13_25, SD1_DATA1),
+	PINMUX_IPSR_MODSEL_DATA(IP13_25, IETX_B, SEL_IEB_1),
+	PINMUX_IPSR_DATA(IP13_26, SD1_DATA2),
+	PINMUX_IPSR_MODSEL_DATA(IP13_26, IECLK_B, SEL_IEB_1),
+	PINMUX_IPSR_DATA(IP13_27, SD1_DATA3),
+	PINMUX_IPSR_MODSEL_DATA(IP13_27, IERX_B, SEL_IEB_1),
+	PINMUX_IPSR_DATA(IP13_30_28, SD1_CD),
+	PINMUX_IPSR_DATA(IP13_30_28, PWM0),
+	PINMUX_IPSR_DATA(IP13_30_28, TPU_TO0),
+	PINMUX_IPSR_MODSEL_DATA(IP13_30_28, SCL1_C, SEL_IIC1_2),
+
+	/* IPSR14 */
+	PINMUX_IPSR_DATA(IP14_1_0, SD1_WP),
+	PINMUX_IPSR_DATA(IP14_1_0, PWM1_B),
+	PINMUX_IPSR_MODSEL_DATA(IP14_1_0, SDA1_C, SEL_IIC1_2),
+	PINMUX_IPSR_DATA(IP14_2, SD2_CLK),
+	PINMUX_IPSR_DATA(IP14_2, MMC_CLK),
+	PINMUX_IPSR_DATA(IP14_3, SD2_CMD),
+	PINMUX_IPSR_DATA(IP14_3, MMC_CMD),
+	PINMUX_IPSR_DATA(IP14_4, SD2_DATA0),
+	PINMUX_IPSR_DATA(IP14_4, MMC_D0),
+	PINMUX_IPSR_DATA(IP14_5, SD2_DATA1),
+	PINMUX_IPSR_DATA(IP14_5, MMC_D1),
+	PINMUX_IPSR_DATA(IP14_6, SD2_DATA2),
+	PINMUX_IPSR_DATA(IP14_6, MMC_D2),
+	PINMUX_IPSR_DATA(IP14_7, SD2_DATA3),
+	PINMUX_IPSR_DATA(IP14_7, MMC_D3),
+	PINMUX_IPSR_DATA(IP14_10_8, SD2_CD),
+	PINMUX_IPSR_DATA(IP14_10_8, MMC_D4),
+	PINMUX_IPSR_MODSEL_DATA(IP14_10_8, SCL8_C, SEL_IIC8_2),
+	PINMUX_IPSR_MODSEL_DATA(IP14_10_8, TX5_B, SEL_SCIF5_1),
+	PINMUX_IPSR_MODSEL_DATA(IP14_10_8, SCIFA5_TXD_C, SEL_SCIFA5_2),
+	PINMUX_IPSR_DATA(IP14_13_11, SD2_WP),
+	PINMUX_IPSR_DATA(IP14_13_11, MMC_D5),
+	PINMUX_IPSR_MODSEL_DATA(IP14_13_11, SDA8_C, SEL_IIC8_2),
+	PINMUX_IPSR_MODSEL_DATA(IP14_13_11, RX5_B, SEL_SCIF5_1),
+	PINMUX_IPSR_MODSEL_DATA(IP14_13_11, SCIFA5_RXD_C, SEL_SCIFA5_2),
+	PINMUX_IPSR_MODSEL_DATA(IP14_16_14, MSIOF0_SCK, SEL_SOF0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP14_16_14, RX2_C, SEL_SCIF2_2),
+	PINMUX_IPSR_MODSEL_DATA(IP14_16_14, ADIDATA, SEL_RAD_0),
+	PINMUX_IPSR_MODSEL_DATA(IP14_16_14, VI1_CLK_C, SEL_VI1_2),
+	PINMUX_IPSR_DATA(IP14_16_14, VI1_G0_B),
+	PINMUX_IPSR_MODSEL_DATA(IP14_19_17, MSIOF0_SYNC, SEL_SOF0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP14_19_17, TX2_C, SEL_SCIF2_2),
+	PINMUX_IPSR_MODSEL_DATA(IP14_19_17, ADICS_SAMP, SEL_RAD_0),
+	PINMUX_IPSR_MODSEL_DATA(IP14_19_17, VI1_CLKENB_C, SEL_VI1_2),
+	PINMUX_IPSR_DATA(IP14_19_17, VI1_G1_B),
+	PINMUX_IPSR_MODSEL_DATA(IP14_22_20, MSIOF0_TXD, SEL_SOF0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP14_22_20, ADICLK, SEL_RAD_0),
+	PINMUX_IPSR_MODSEL_DATA(IP14_22_20, VI1_FIELD_C, SEL_VI1_2),
+	PINMUX_IPSR_DATA(IP14_22_20, VI1_G2_B),
+	PINMUX_IPSR_MODSEL_DATA(IP14_25_23, MSIOF0_RXD, SEL_SOF0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP14_25_23, ADICHS0, SEL_RAD_0),
+	PINMUX_IPSR_MODSEL_DATA(IP14_25_23, VI1_DATA0_C, SEL_VI1_2),
+	PINMUX_IPSR_DATA(IP14_25_23, VI1_G3_B),
+	PINMUX_IPSR_MODSEL_DATA(IP14_28_26, MSIOF0_SS1, SEL_SOF0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP14_28_26, MMC_D6, SEL_MMC_0),
+	PINMUX_IPSR_MODSEL_DATA(IP14_28_26, ADICHS1, SEL_RAD_0),
+	PINMUX_IPSR_MODSEL_DATA(IP14_28_26, TX0_E, SEL_SCIF0_4),
+	PINMUX_IPSR_MODSEL_DATA(IP14_28_26, VI1_HSYNC_N_C, SEL_VI1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP14_28_26, SCL7_C, SEL_IIC7_2),
+	PINMUX_IPSR_DATA(IP14_28_26, VI1_G4_B),
+	PINMUX_IPSR_MODSEL_DATA(IP14_31_29, MSIOF0_SS2, SEL_SOF0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP14_31_29, MMC_D7, SEL_MMC_0),
+	PINMUX_IPSR_MODSEL_DATA(IP14_31_29, ADICHS2, SEL_RAD_0),
+	PINMUX_IPSR_MODSEL_DATA(IP14_31_29, RX0_E, SEL_SCIF0_4),
+	PINMUX_IPSR_MODSEL_DATA(IP14_31_29, VI1_VSYNC_N_C, SEL_VI1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP14_31_29, SDA7_C, SEL_IIC7_2),
+	PINMUX_IPSR_DATA(IP14_31_29, VI1_G5_B),
+
+	/* IPSR15 */
+	PINMUX_IPSR_MODSEL_DATA(IP15_1_0, SIM0_RST, SEL_SIM_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_1_0, IETX, SEL_IEB_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_1_0, CAN1_TX_D, SEL_CAN1_3),
+	PINMUX_IPSR_DATA(IP15_3_2, SIM0_CLK),
+	PINMUX_IPSR_MODSEL_DATA(IP15_3_2, IECLK, SEL_IEB_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_3_2, CAN_CLK_C, SEL_CANCLK_2),
+	PINMUX_IPSR_MODSEL_DATA(IP15_5_4, SIM0_D, SEL_SIM_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_5_4, IERX, SEL_IEB_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_5_4, CAN1_RX_D, SEL_CAN1_3),
+	PINMUX_IPSR_MODSEL_DATA(IP15_8_6, GPS_CLK, SEL_GPS_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_8_6, DU1_DOTCLKIN_C, SEL_DIS_2),
+	PINMUX_IPSR_MODSEL_DATA(IP15_8_6, AUDIO_CLKB_B, SEL_ADG_1),
+	PINMUX_IPSR_DATA(IP15_8_6, PWM5_B),
+	PINMUX_IPSR_MODSEL_DATA(IP15_8_6, SCIFA3_TXD_C, SEL_SCIFA3_2),
+	PINMUX_IPSR_MODSEL_DATA(IP15_11_9, GPS_SIGN, SEL_GPS_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_11_9, TX4_C, SEL_SCIF4_2),
+	PINMUX_IPSR_MODSEL_DATA(IP15_11_9, SCIFA4_TXD_C, SEL_SCIFA4_2),
+	PINMUX_IPSR_DATA(IP15_11_9, PWM5),
+	PINMUX_IPSR_DATA(IP15_11_9, VI1_G6_B),
+	PINMUX_IPSR_MODSEL_DATA(IP15_11_9, SCIFA3_RXD_C, SEL_SCIFA3_2),
+	PINMUX_IPSR_MODSEL_DATA(IP15_14_12, GPS_MAG, SEL_GPS_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_14_12, RX4_C, SEL_SCIF4_2),
+	PINMUX_IPSR_MODSEL_DATA(IP15_14_12, SCIFA4_RXD_C, SEL_SCIFA4_2),
+	PINMUX_IPSR_DATA(IP15_14_12, PWM6),
+	PINMUX_IPSR_DATA(IP15_14_12, VI1_G7_B),
+	PINMUX_IPSR_MODSEL_DATA(IP15_14_12, SCIFA3_SCK_C, SEL_SCIFA3_2),
+	PINMUX_IPSR_MODSEL_DATA(IP15_17_15, HCTS0_N, SEL_HSCIF0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_17_15, SCIFB0_CTS_N, SEL_SCIFB_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_17_15, GLO_I0_C, SEL_GPS_2),
+	PINMUX_IPSR_MODSEL_DATA(IP15_17_15, TCLK1, SEL_TMU1_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_17_15, VI1_DATA1_C, SEL_VI1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP15_20_18, HRTS0_N, SEL_HSCIF0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_20_18, SCIFB0_RTS_N, SEL_SCIFB_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_20_18, GLO_I1_C, SEL_GPS_2),
+	PINMUX_IPSR_MODSEL_DATA(IP15_20_18, VI1_DATA2_C, SEL_VI1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP15_23_21, HSCK0, SEL_HSCIF0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_23_21, SCIFB0_SCK, SEL_SCIFB_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_23_21, GLO_Q0_C, SEL_GPS_2),
+	PINMUX_IPSR_MODSEL_DATA(IP15_23_21, CAN_CLK, SEL_CANCLK_0),
+	PINMUX_IPSR_DATA(IP15_23_21, TCLK2),
+	PINMUX_IPSR_MODSEL_DATA(IP15_23_21, VI1_DATA3_C, SEL_VI1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP15_26_24, HRX0, SEL_HSCIF0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_26_24, SCIFB0_RXD, SEL_SCIFB_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_26_24, GLO_Q1_C, SEL_GPS_2),
+	PINMUX_IPSR_MODSEL_DATA(IP15_26_24, CAN0_RX_B, SEL_CAN0_1),
+	PINMUX_IPSR_MODSEL_DATA(IP15_26_24, VI1_DATA4_C, SEL_VI1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP15_29_27, HTX0, SEL_HSCIF0_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_29_27, SCIFB0_TXD, SEL_SCIFB_0),
+	PINMUX_IPSR_MODSEL_DATA(IP15_29_27, GLO_SCLK_C, SEL_GPS_2),
+	PINMUX_IPSR_MODSEL_DATA(IP15_29_27, CAN0_TX_B, SEL_CAN0_1),
+	PINMUX_IPSR_MODSEL_DATA(IP15_29_27, VI1_DATA5_C, SEL_VI1_2),
+
+	/* IPSR16 */
+	PINMUX_IPSR_MODSEL_DATA(IP16_2_0, HRX1, SEL_HSCIF1_0),
+	PINMUX_IPSR_MODSEL_DATA(IP16_2_0, SCIFB1_RXD, SEL_SCIFB1_0),
+	PINMUX_IPSR_DATA(IP16_2_0, VI1_R0_B),
+	PINMUX_IPSR_MODSEL_DATA(IP16_2_0, GLO_SDATA_C, SEL_GPS_2),
+	PINMUX_IPSR_MODSEL_DATA(IP16_2_0, VI1_DATA6_C, SEL_VI1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP16_5_3, HTX1, SEL_HSCIF1_0),
+	PINMUX_IPSR_MODSEL_DATA(IP16_5_3, SCIFB1_TXD, SEL_SCIFB1_0),
+	PINMUX_IPSR_DATA(IP16_5_3, VI1_R1_B),
+	PINMUX_IPSR_MODSEL_DATA(IP16_5_3, GLO_SS_C, SEL_GPS_2),
+	PINMUX_IPSR_MODSEL_DATA(IP16_5_3, VI1_DATA7_C, SEL_VI1_2),
+	PINMUX_IPSR_MODSEL_DATA(IP16_7_6, HSCK1, SEL_HSCIF1_0),
+	PINMUX_IPSR_MODSEL_DATA(IP16_7_6, SCIFB1_SCK, SEL_SCIFB1_0),
+	PINMUX_IPSR_DATA(IP16_7_6, MLB_CK),
+	PINMUX_IPSR_MODSEL_DATA(IP16_7_6, GLO_RFON_C, SEL_GPS_2),
+	PINMUX_IPSR_MODSEL_DATA(IP16_9_8, HCTS1_N, SEL_HSCIF1_0),
+	PINMUX_IPSR_DATA(IP16_9_8, SCIFB1_CTS_N),
+	PINMUX_IPSR_DATA(IP16_9_8, MLB_SIG),
+	PINMUX_IPSR_MODSEL_DATA(IP16_9_8, CAN1_TX_B, SEL_CAN1_1),
+	PINMUX_IPSR_MODSEL_DATA(IP16_11_10, HRTS1_N, SEL_HSCIF1_0),
+	PINMUX_IPSR_DATA(IP16_11_10, SCIFB1_RTS_N),
+	PINMUX_IPSR_DATA(IP16_11_10, MLB_DAT),
+	PINMUX_IPSR_MODSEL_DATA(IP16_11_10, CAN1_RX_B, SEL_CAN1_1),
+};
+
+static struct sh_pfc_pin pinmux_pins[] = {
+	PINMUX_GPIO_GP_ALL(),
+};
+
+/* - DU --------------------------------------------------------------------- */
+static const unsigned int du_rgb666_pins[] = {
+	/* R[7:2], G[7:2], B[7:2] */
+	RCAR_GP_PIN(3, 7),  RCAR_GP_PIN(3, 6),  RCAR_GP_PIN(3, 5),
+	RCAR_GP_PIN(3, 4),  RCAR_GP_PIN(3, 3),  RCAR_GP_PIN(3, 2),
+	RCAR_GP_PIN(3, 15), RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 13),
+	RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 11), RCAR_GP_PIN(3, 10),
+	RCAR_GP_PIN(3, 23), RCAR_GP_PIN(3, 22), RCAR_GP_PIN(3, 21),
+	RCAR_GP_PIN(3, 20), RCAR_GP_PIN(3, 19), RCAR_GP_PIN(3, 18),
+};
+static const unsigned int du_rgb666_mux[] = {
+	DU1_DR7_MARK, DU1_DR6_MARK, DU1_DR5_MARK, DU1_DR4_MARK,
+	DU1_DR3_MARK, DU1_DR2_MARK,
+	DU1_DG7_MARK, DU1_DG6_MARK, DU1_DG5_MARK, DU1_DG4_MARK,
+	DU1_DG3_MARK, DU1_DG2_MARK,
+	DU1_DB7_MARK, DU1_DB6_MARK, DU1_DB5_MARK, DU1_DB4_MARK,
+	DU1_DB3_MARK, DU1_DB2_MARK,
+};
+static const unsigned int du_rgb888_pins[] = {
+	/* R[7:0], G[7:0], B[7:0] */
+	RCAR_GP_PIN(3, 7),  RCAR_GP_PIN(3, 6),  RCAR_GP_PIN(3, 5),
+	RCAR_GP_PIN(3, 4),  RCAR_GP_PIN(3, 3),  RCAR_GP_PIN(3, 2),
+	RCAR_GP_PIN(3, 1),  RCAR_GP_PIN(3, 0),
+	RCAR_GP_PIN(3, 15), RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 13),
+	RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 11), RCAR_GP_PIN(3, 10),
+	RCAR_GP_PIN(3, 9),  RCAR_GP_PIN(3, 8),
+	RCAR_GP_PIN(3, 23), RCAR_GP_PIN(3, 22), RCAR_GP_PIN(3, 21),
+	RCAR_GP_PIN(3, 20), RCAR_GP_PIN(3, 19), RCAR_GP_PIN(3, 18),
+	RCAR_GP_PIN(3, 17), RCAR_GP_PIN(3, 16),
+};
+static const unsigned int du_rgb888_mux[] = {
+	DU1_DR7_MARK, DU1_DR6_MARK, DU1_DR5_MARK, DU1_DR4_MARK,
+	DU1_DR3_MARK, DU1_DR2_MARK, DU1_DR1_MARK, DU1_DR0_MARK,
+	DU1_DG7_MARK, DU1_DG6_MARK, DU1_DG5_MARK, DU1_DG4_MARK,
+	DU1_DG3_MARK, DU1_DG2_MARK, DU1_DG1_MARK, DU1_DG0_MARK,
+	DU1_DB7_MARK, DU1_DB6_MARK, DU1_DB5_MARK, DU1_DB4_MARK,
+	DU1_DB3_MARK, DU1_DB2_MARK, DU1_DB1_MARK, DU1_DB0_MARK,
+};
+static const unsigned int du_clk_out_0_pins[] = {
+	/* CLKOUT */
+	RCAR_GP_PIN(3, 25),
+};
+static const unsigned int du_clk_out_0_mux[] = {
+	DU1_DOTCLKOUT0_MARK
+};
+static const unsigned int du_clk_out_1_pins[] = {
+	/* CLKOUT */
+	RCAR_GP_PIN(3, 26),
+};
+static const unsigned int du_clk_out_1_mux[] = {
+	DU1_DOTCLKOUT1_MARK
+};
+static const unsigned int du_sync_1_pins[] = {
+	/* EXVSYNC/VSYNC, EXHSYNC/HSYNC, EXDISP/EXODDF/EXCDE */
+	RCAR_GP_PIN(3, 29), RCAR_GP_PIN(3, 28), RCAR_GP_PIN(3, 27),
+};
+static const unsigned int du_sync_1_mux[] = {
+	DU1_EXODDF_DU1_ODDF_DISP_CDE_MARK,
+	DU1_EXVSYNC_DU1_VSYNC_MARK, DU1_EXHSYNC_DU1_HSYNC_MARK
+};
+static const unsigned int du_cde_disp_pins[] = {
+	/* CDE DISP */
+	RCAR_GP_PIN(3, 31), RCAR_GP_PIN(3, 30),
+};
+static const unsigned int du0_clk_in_pins[] = {
+	/* CLKIN */
+	RCAR_GP_PIN(6, 31),
+};
+static const unsigned int du0_clk_in_mux[] = {
+	DU0_DOTCLKIN_MARK
+};
+static const unsigned int du_cde_disp_mux[] = {
+	DU1_CDE_MARK, DU1_DISP_MARK
+};
+static const unsigned int du1_clk_in_pins[] = {
+	/* CLKIN */
+	RCAR_GP_PIN(7, 20), RCAR_GP_PIN(7, 19), RCAR_GP_PIN(3, 24),
+};
+static const unsigned int du1_clk_in_mux[] = {
+	DU1_DOTCLKIN_C_MARK, DU1_DOTCLKIN_B_MARK, DU1_DOTCLKIN_MARK
+};
+/* - ETH -------------------------------------------------------------------- */
+static const unsigned int eth_link_pins[] = {
+	/* LINK */
+	RCAR_GP_PIN(5, 18),
+};
+static const unsigned int eth_link_mux[] = {
+	ETH_LINK_MARK,
+};
+static const unsigned int eth_magic_pins[] = {
+	/* MAGIC */
+	RCAR_GP_PIN(5, 22),
+};
+static const unsigned int eth_magic_mux[] = {
+	ETH_MAGIC_MARK,
+};
+static const unsigned int eth_mdio_pins[] = {
+	/* MDC, MDIO */
+	RCAR_GP_PIN(5, 24), RCAR_GP_PIN(5, 13),
+};
+static const unsigned int eth_mdio_mux[] = {
+	ETH_MDC_MARK, ETH_MDIO_MARK,
+};
+static const unsigned int eth_rmii_pins[] = {
+	/* RXD[0:1], RX_ER, CRS_DV, TXD[0:1], TX_EN, REF_CLK */
+	RCAR_GP_PIN(5, 16), RCAR_GP_PIN(5, 17), RCAR_GP_PIN(5, 15),
+	RCAR_GP_PIN(5, 14), RCAR_GP_PIN(5, 23), RCAR_GP_PIN(5, 20),
+	RCAR_GP_PIN(5, 21), RCAR_GP_PIN(5, 19),
+};
+static const unsigned int eth_rmii_mux[] = {
+	ETH_RXD0_MARK, ETH_RXD1_MARK, ETH_RX_ER_MARK, ETH_CRS_DV_MARK,
+	ETH_TXD0_MARK, ETH_TXD1_MARK, ETH_TX_EN_MARK, ETH_REFCLK_MARK,
+};
+/* - INTC ------------------------------------------------------------------- */
+static const unsigned int intc_irq0_pins[] = {
+	/* IRQ */
+	RCAR_GP_PIN(7, 10),
+};
+static const unsigned int intc_irq0_mux[] = {
+	IRQ0_MARK,
+};
+static const unsigned int intc_irq1_pins[] = {
+	/* IRQ */
+	RCAR_GP_PIN(7, 11),
+};
+static const unsigned int intc_irq1_mux[] = {
+	IRQ1_MARK,
+};
+static const unsigned int intc_irq2_pins[] = {
+	/* IRQ */
+	RCAR_GP_PIN(7, 12),
+};
+static const unsigned int intc_irq2_mux[] = {
+	IRQ2_MARK,
+};
+static const unsigned int intc_irq3_pins[] = {
+	/* IRQ */
+	RCAR_GP_PIN(7, 13),
+};
+static const unsigned int intc_irq3_mux[] = {
+	IRQ3_MARK,
+};
+/* - MMCIF ------------------------------------------------------------------ */
+static const unsigned int mmc_data1_pins[] = {
+	/* D[0] */
+	RCAR_GP_PIN(6, 18),
+};
+static const unsigned int mmc_data1_mux[] = {
+	MMC_D0_MARK,
+};
+static const unsigned int mmc_data4_pins[] = {
+	/* D[0:3] */
+	RCAR_GP_PIN(6, 18), RCAR_GP_PIN(6, 19),
+	RCAR_GP_PIN(6, 20), RCAR_GP_PIN(6, 21),
+};
+static const unsigned int mmc_data4_mux[] = {
+	MMC_D0_MARK, MMC_D1_MARK, MMC_D2_MARK, MMC_D3_MARK,
+};
+static const unsigned int mmc_data8_pins[] = {
+	/* D[0:7] */
+	RCAR_GP_PIN(6, 18), RCAR_GP_PIN(6, 19),
+	RCAR_GP_PIN(6, 20), RCAR_GP_PIN(6, 21),
+	RCAR_GP_PIN(6, 22), RCAR_GP_PIN(6, 23),
+	RCAR_GP_PIN(6, 28), RCAR_GP_PIN(6, 29),
+};
+static const unsigned int mmc_data8_mux[] = {
+	MMC_D0_MARK, MMC_D1_MARK, MMC_D2_MARK, MMC_D3_MARK,
+	MMC_D4_MARK, MMC_D5_MARK, MMC_D6_MARK, MMC_D7_MARK,
+};
+static const unsigned int mmc_ctrl_pins[] = {
+	/* CLK, CMD */
+	RCAR_GP_PIN(6, 16), RCAR_GP_PIN(6, 17),
+};
+static const unsigned int mmc_ctrl_mux[] = {
+	MMC_CLK_MARK, MMC_CMD_MARK,
+};
+/* - MSIOF0 ----------------------------------------------------------------- */
+static const unsigned int msiof0_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(6, 24),
+};
+static const unsigned int msiof0_clk_mux[] = {
+	MSIOF0_SCK_MARK,
+};
+static const unsigned int msiof0_sync_pins[] = {
+	/* SYNC */
+	RCAR_GP_PIN(6, 25),
+};
+static const unsigned int msiof0_sync_mux[] = {
+	MSIOF0_SYNC_MARK,
+};
+static const unsigned int msiof0_ss1_pins[] = {
+	/* SS1 */
+	RCAR_GP_PIN(6, 28),
+};
+static const unsigned int msiof0_ss1_mux[] = {
+	MSIOF0_SS1_MARK,
+};
+static const unsigned int msiof0_ss2_pins[] = {
+	/* SS2 */
+	RCAR_GP_PIN(6, 29),
+};
+static const unsigned int msiof0_ss2_mux[] = {
+	MSIOF0_SS2_MARK,
+};
+static const unsigned int msiof0_rx_pins[] = {
+	/* RXD */
+	RCAR_GP_PIN(6, 27),
+};
+static const unsigned int msiof0_rx_mux[] = {
+	MSIOF0_RXD_MARK,
+};
+static const unsigned int msiof0_tx_pins[] = {
+	/* TXD */
+	RCAR_GP_PIN(6, 26),
+};
+static const unsigned int msiof0_tx_mux[] = {
+	MSIOF0_TXD_MARK,
+};
+/* - MSIOF1 ----------------------------------------------------------------- */
+static const unsigned int msiof1_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(0, 22),
+};
+static const unsigned int msiof1_clk_mux[] = {
+	MSIOF1_SCK_MARK,
+};
+static const unsigned int msiof1_sync_pins[] = {
+	/* SYNC */
+	RCAR_GP_PIN(0, 23),
+};
+static const unsigned int msiof1_sync_mux[] = {
+	MSIOF1_SYNC_MARK,
+};
+static const unsigned int msiof1_ss1_pins[] = {
+	/* SS1 */
+	RCAR_GP_PIN(0, 24),
+};
+static const unsigned int msiof1_ss1_mux[] = {
+	MSIOF1_SS1_MARK,
+};
+static const unsigned int msiof1_ss2_pins[] = {
+	/* SS2 */
+	RCAR_GP_PIN(0, 25),
+};
+static const unsigned int msiof1_ss2_mux[] = {
+	MSIOF1_SS2_MARK,
+};
+static const unsigned int msiof1_rx_pins[] = {
+	/* RXD */
+	RCAR_GP_PIN(0, 27),
+};
+static const unsigned int msiof1_rx_mux[] = {
+	MSIOF1_RXD_MARK,
+};
+static const unsigned int msiof1_tx_pins[] = {
+	/* TXD */
+	RCAR_GP_PIN(0, 26),
+};
+static const unsigned int msiof1_tx_mux[] = {
+	MSIOF1_TXD_MARK,
+};
+/* - MSIOF2 ----------------------------------------------------------------- */
+static const unsigned int msiof2_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(1, 13),
+};
+static const unsigned int msiof2_clk_mux[] = {
+	MSIOF2_SCK_MARK,
+};
+static const unsigned int msiof2_sync_pins[] = {
+	/* SYNC */
+	RCAR_GP_PIN(1, 14),
+};
+static const unsigned int msiof2_sync_mux[] = {
+	MSIOF2_SYNC_MARK,
+};
+static const unsigned int msiof2_ss1_pins[] = {
+	/* SS1 */
+	RCAR_GP_PIN(1, 17),
+};
+static const unsigned int msiof2_ss1_mux[] = {
+	MSIOF2_SS1_MARK,
+};
+static const unsigned int msiof2_ss2_pins[] = {
+	/* SS2 */
+	RCAR_GP_PIN(1, 18),
+};
+static const unsigned int msiof2_ss2_mux[] = {
+	MSIOF2_SS2_MARK,
+};
+static const unsigned int msiof2_rx_pins[] = {
+	/* RXD */
+	RCAR_GP_PIN(1, 16),
+};
+static const unsigned int msiof2_rx_mux[] = {
+	MSIOF2_RXD_MARK,
+};
+static const unsigned int msiof2_tx_pins[] = {
+	/* TXD */
+	RCAR_GP_PIN(1, 15),
+};
+static const unsigned int msiof2_tx_mux[] = {
+	MSIOF2_TXD_MARK,
+};
+/* - SCIF0 ------------------------------------------------------------------ */
+static const unsigned int scif0_data_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(1, 7), RCAR_GP_PIN(1, 6),
+};
+static const unsigned int scif0_data_mux[] = {
+	RX0_MARK, TX0_MARK,
+};
+static const unsigned int scif0_data_b_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(3, 1), RCAR_GP_PIN(3, 0),
+};
+static const unsigned int scif0_data_b_mux[] = {
+	RX0_B_MARK, TX0_B_MARK,
+};
+static const unsigned int scif0_data_c_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(4, 26), RCAR_GP_PIN(4, 25),
+};
+static const unsigned int scif0_data_c_mux[] = {
+	RX0_C_MARK, TX0_C_MARK,
+};
+static const unsigned int scif0_data_d_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(2, 23), RCAR_GP_PIN(2, 22),
+};
+static const unsigned int scif0_data_d_mux[] = {
+	RX0_D_MARK, TX0_D_MARK,
+};
+static const unsigned int scif0_data_e_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(6, 29), RCAR_GP_PIN(6, 28),
+};
+static const unsigned int scif0_data_e_mux[] = {
+	RX0_E_MARK, TX0_E_MARK,
+};
+/* - SCIF1 ------------------------------------------------------------------ */
+static const unsigned int scif1_data_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(1, 9), RCAR_GP_PIN(1, 8),
+};
+static const unsigned int scif1_data_mux[] = {
+	RX1_MARK, TX1_MARK,
+};
+static const unsigned int scif1_data_b_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(3, 9), RCAR_GP_PIN(3, 8),
+};
+static const unsigned int scif1_data_b_mux[] = {
+	RX1_B_MARK, TX1_B_MARK,
+};
+static const unsigned int scif1_clk_b_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(3, 10),
+};
+static const unsigned int scif1_clk_b_mux[] = {
+	SCIF1_SCK_B_MARK,
+};
+static const unsigned int scif1_data_c_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(4, 28), RCAR_GP_PIN(4, 27),
+};
+static const unsigned int scif1_data_c_mux[] = {
+	RX1_C_MARK, TX1_C_MARK,
+};
+static const unsigned int scif1_data_d_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(2, 25), RCAR_GP_PIN(2, 24),
+};
+static const unsigned int scif1_data_d_mux[] = {
+	RX1_D_MARK, TX1_D_MARK,
+};
+/* - SCIF2 ------------------------------------------------------------------ */
+static const unsigned int scif2_data_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(2, 30), RCAR_GP_PIN(2, 31),
+};
+static const unsigned int scif2_data_mux[] = {
+	RX2_MARK, TX2_MARK,
+};
+static const unsigned int scif2_data_b_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(3, 17), RCAR_GP_PIN(3, 16),
+};
+static const unsigned int scif2_data_b_mux[] = {
+	RX2_B_MARK, TX2_B_MARK,
+};
+static const unsigned int scif2_clk_b_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(3, 18),
+};
+static const unsigned int scif2_clk_b_mux[] = {
+	SCIF2_SCK_B_MARK,
+};
+static const unsigned int scif2_data_c_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(6, 24), RCAR_GP_PIN(6, 25),
+};
+static const unsigned int scif2_data_c_mux[] = {
+	RX2_C_MARK, TX2_C_MARK,
+};
+static const unsigned int scif2_data_e_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 8),
+};
+static const unsigned int scif2_data_e_mux[] = {
+	RX2_E_MARK, TX2_E_MARK,
+};
+/* - SCIF3 ------------------------------------------------------------------ */
+static const unsigned int scif3_data_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(3, 22), RCAR_GP_PIN(3, 21),
+};
+static const unsigned int scif3_data_mux[] = {
+	RX3_MARK, TX3_MARK,
+};
+static const unsigned int scif3_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(3, 23),
+};
+static const unsigned int scif3_clk_mux[] = {
+	SCIF3_SCK_MARK,
+};
+static const unsigned int scif3_data_b_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(3, 29), RCAR_GP_PIN(3, 26),
+};
+static const unsigned int scif3_data_b_mux[] = {
+	RX3_B_MARK, TX3_B_MARK,
+};
+static const unsigned int scif3_clk_b_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(4, 8),
+};
+static const unsigned int scif3_clk_b_mux[] = {
+	SCIF3_SCK_B_MARK,
+};
+static const unsigned int scif3_data_c_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(6, 7), RCAR_GP_PIN(6, 6),
+};
+static const unsigned int scif3_data_c_mux[] = {
+	RX3_C_MARK, TX3_C_MARK,
+};
+static const unsigned int scif3_data_d_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(2, 27), RCAR_GP_PIN(2, 26),
+};
+static const unsigned int scif3_data_d_mux[] = {
+	RX3_D_MARK, TX3_D_MARK,
+};
+/* - SCIF4 ------------------------------------------------------------------ */
+static const unsigned int scif4_data_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(4, 2), RCAR_GP_PIN(4, 1),
+};
+static const unsigned int scif4_data_mux[] = {
+	RX4_MARK, TX4_MARK,
+};
+static const unsigned int scif4_data_b_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(5, 1), RCAR_GP_PIN(5, 0),
+};
+static const unsigned int scif4_data_b_mux[] = {
+	RX4_B_MARK, TX4_B_MARK,
+};
+static const unsigned int scif4_data_c_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(7, 22), RCAR_GP_PIN(7, 21),
+};
+static const unsigned int scif4_data_c_mux[] = {
+	RX4_C_MARK, TX4_C_MARK,
+};
+/* - SCIF5 ------------------------------------------------------------------ */
+static const unsigned int scif5_data_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(4, 4), RCAR_GP_PIN(4, 3),
+};
+static const unsigned int scif5_data_mux[] = {
+	RX5_MARK, TX5_MARK,
+};
+static const unsigned int scif5_data_b_pins[] = {
+	/* RX, TX */
+	RCAR_GP_PIN(6, 23), RCAR_GP_PIN(6, 22),
+};
+static const unsigned int scif5_data_b_mux[] = {
+	RX5_B_MARK, TX5_B_MARK,
+};
+/* - SCIFA0 ----------------------------------------------------------------- */
+static const unsigned int scifa0_data_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(1, 7), RCAR_GP_PIN(1, 6),
+};
+static const unsigned int scifa0_data_mux[] = {
+	SCIFA0_RXD_MARK, SCIFA0_TXD_MARK,
+};
+static const unsigned int scifa0_data_b_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(3, 1), RCAR_GP_PIN(3, 0),
+};
+static const unsigned int scifa0_data_b_mux[] = {
+	SCIFA0_RXD_B_MARK, SCIFA0_TXD_B_MARK
+};
+/* - SCIFA1 ----------------------------------------------------------------- */
+static const unsigned int scifa1_data_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(1, 9), RCAR_GP_PIN(1, 8),
+};
+static const unsigned int scifa1_data_mux[] = {
+	SCIFA1_RXD_MARK, SCIFA1_TXD_MARK,
+};
+static const unsigned int scifa1_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(3, 10),
+};
+static const unsigned int scifa1_clk_mux[] = {
+	SCIFA1_SCK_MARK,
+};
+static const unsigned int scifa1_data_b_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(3, 9), RCAR_GP_PIN(3, 8),
+};
+static const unsigned int scifa1_data_b_mux[] = {
+	SCIFA1_RXD_B_MARK, SCIFA1_TXD_B_MARK,
+};
+static const unsigned int scifa1_clk_b_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(1, 0),
+};
+static const unsigned int scifa1_clk_b_mux[] = {
+	SCIFA1_SCK_B_MARK,
+};
+static const unsigned int scifa1_data_c_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(1, 2), RCAR_GP_PIN(1, 3),
+};
+static const unsigned int scifa1_data_c_mux[] = {
+	SCIFA1_RXD_C_MARK, SCIFA1_TXD_C_MARK,
+};
+/* - SCIFA2 ----------------------------------------------------------------- */
+static const unsigned int scifa2_data_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(2, 30), RCAR_GP_PIN(2, 31),
+};
+static const unsigned int scifa2_data_mux[] = {
+	SCIFA2_RXD_MARK, SCIFA2_TXD_MARK,
+};
+static const unsigned int scifa2_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(3, 18),
+};
+static const unsigned int scifa2_clk_mux[] = {
+	SCIFA2_SCK_MARK,
+};
+static const unsigned int scifa2_data_b_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(3, 17), RCAR_GP_PIN(3, 16),
+};
+static const unsigned int scifa2_data_b_mux[] = {
+	SCIFA2_RXD_B_MARK, SCIFA2_TXD_B_MARK,
+};
+/* - SCIFA3 ----------------------------------------------------------------- */
+static const unsigned int scifa3_data_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(3, 22), RCAR_GP_PIN(3, 21),
+};
+static const unsigned int scifa3_data_mux[] = {
+	SCIFA3_RXD_MARK, SCIFA3_TXD_MARK,
+};
+static const unsigned int scifa3_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(3, 23),
+};
+static const unsigned int scifa3_clk_mux[] = {
+	SCIFA3_SCK_MARK,
+};
+static const unsigned int scifa3_data_b_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(5, 19), RCAR_GP_PIN(5, 20),
+};
+static const unsigned int scifa3_data_b_mux[] = {
+	SCIFA3_RXD_B_MARK, SCIFA3_TXD_B_MARK,
+};
+static const unsigned int scifa3_clk_b_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(4, 8),
+};
+static const unsigned int scifa3_clk_b_mux[] = {
+	SCIFA3_SCK_B_MARK,
+};
+static const unsigned int scifa3_data_c_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(7, 21), RCAR_GP_PIN(7, 20),
+};
+static const unsigned int scifa3_data_c_mux[] = {
+	SCIFA3_RXD_C_MARK, SCIFA3_TXD_C_MARK,
+};
+static const unsigned int scifa3_clk_c_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(7, 22),
+};
+static const unsigned int scifa3_clk_c_mux[] = {
+	SCIFA3_SCK_C_MARK,
+};
+/* - SCIFA4 ----------------------------------------------------------------- */
+static const unsigned int scifa4_data_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(4, 2), RCAR_GP_PIN(4, 1),
+};
+static const unsigned int scifa4_data_mux[] = {
+	SCIFA4_RXD_MARK, SCIFA4_TXD_MARK,
+};
+static const unsigned int scifa4_data_b_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(5, 1), RCAR_GP_PIN(5, 0),
+};
+static const unsigned int scifa4_data_b_mux[] = {
+	SCIFA4_RXD_B_MARK, SCIFA4_TXD_B_MARK,
+};
+static const unsigned int scifa4_data_c_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(7, 22), RCAR_GP_PIN(7, 21),
+};
+static const unsigned int scifa4_data_c_mux[] = {
+	SCIFA4_RXD_C_MARK, SCIFA4_TXD_C_MARK,
+};
+/* - SCIFA5 ----------------------------------------------------------------- */
+static const unsigned int scifa5_data_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(4, 4), RCAR_GP_PIN(4, 3),
+};
+static const unsigned int scifa5_data_mux[] = {
+	SCIFA5_RXD_MARK, SCIFA5_TXD_MARK,
+};
+static const unsigned int scifa5_data_b_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(6, 7), RCAR_GP_PIN(6, 6),
+};
+static const unsigned int scifa5_data_b_mux[] = {
+	SCIFA5_RXD_B_MARK, SCIFA5_TXD_B_MARK,
+};
+static const unsigned int scifa5_data_c_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(6, 23), RCAR_GP_PIN(6, 22),
+};
+static const unsigned int scifa5_data_c_mux[] = {
+	SCIFA5_RXD_C_MARK, SCIFA5_TXD_C_MARK,
+};
+/* - SCIFB0 ----------------------------------------------------------------- */
+static const unsigned int scifb0_data_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(7, 3), RCAR_GP_PIN(7, 4),
+};
+static const unsigned int scifb0_data_mux[] = {
+	SCIFB0_RXD_MARK, SCIFB0_TXD_MARK,
+};
+static const unsigned int scifb0_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(7, 2),
+};
+static const unsigned int scifb0_clk_mux[] = {
+	SCIFB0_SCK_MARK,
+};
+static const unsigned int scifb0_ctrl_pins[] = {
+	/* RTS, CTS */
+	RCAR_GP_PIN(7, 1), RCAR_GP_PIN(7, 0),
+};
+static const unsigned int scifb0_ctrl_mux[] = {
+	SCIFB0_RTS_N_MARK, SCIFB0_CTS_N_MARK,
+};
+static const unsigned int scifb0_data_b_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(1, 20), RCAR_GP_PIN(1, 21),
+};
+static const unsigned int scifb0_data_b_mux[] = {
+	SCIFB0_RXD_B_MARK, SCIFB0_TXD_B_MARK,
+};
+static const unsigned int scifb0_clk_b_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(5, 31),
+};
+static const unsigned int scifb0_clk_b_mux[] = {
+	SCIFB0_SCK_B_MARK,
+};
+static const unsigned int scifb0_ctrl_b_pins[] = {
+	/* RTS, CTS */
+	RCAR_GP_PIN(1, 22), RCAR_GP_PIN(1, 23),
+};
+static const unsigned int scifb0_ctrl_b_mux[] = {
+	SCIFB0_RTS_N_B_MARK, SCIFB0_CTS_N_B_MARK,
+};
+static const unsigned int scifb0_data_c_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(2, 0), RCAR_GP_PIN(2, 1),
+};
+static const unsigned int scifb0_data_c_mux[] = {
+	SCIFB0_RXD_C_MARK, SCIFB0_TXD_C_MARK,
+};
+static const unsigned int scifb0_clk_c_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(2, 30),
+};
+static const unsigned int scifb0_clk_c_mux[] = {
+	SCIFB0_SCK_C_MARK,
+};
+static const unsigned int scifb0_data_d_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(4, 28), RCAR_GP_PIN(4, 18),
+};
+static const unsigned int scifb0_data_d_mux[] = {
+	SCIFB0_RXD_D_MARK, SCIFB0_TXD_D_MARK,
+};
+static const unsigned int scifb0_clk_d_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(4, 17),
+};
+static const unsigned int scifb0_clk_d_mux[] = {
+	SCIFB0_SCK_D_MARK,
+};
+/* - SCIFB1 ----------------------------------------------------------------- */
+static const unsigned int scifb1_data_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(7, 5), RCAR_GP_PIN(7, 6),
+};
+static const unsigned int scifb1_data_mux[] = {
+	SCIFB1_RXD_MARK, SCIFB1_TXD_MARK,
+};
+static const unsigned int scifb1_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(7, 7),
+};
+static const unsigned int scifb1_clk_mux[] = {
+	SCIFB1_SCK_MARK,
+};
+static const unsigned int scifb1_ctrl_pins[] = {
+	/* RTS, CTS */
+	RCAR_GP_PIN(7, 9), RCAR_GP_PIN(7, 8),
+};
+static const unsigned int scifb1_ctrl_mux[] = {
+	SCIFB1_RTS_N_MARK, SCIFB1_CTS_N_MARK,
+};
+static const unsigned int scifb1_data_b_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(1, 17), RCAR_GP_PIN(1, 18),
+};
+static const unsigned int scifb1_data_b_mux[] = {
+	SCIFB1_RXD_B_MARK, SCIFB1_TXD_B_MARK,
+};
+static const unsigned int scifb1_clk_b_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(1, 3),
+};
+static const unsigned int scifb1_clk_b_mux[] = {
+	SCIFB1_SCK_B_MARK,
+};
+static const unsigned int scifb1_data_c_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(1, 2), RCAR_GP_PIN(1, 3),
+};
+static const unsigned int scifb1_data_c_mux[] = {
+	SCIFB1_RXD_C_MARK, SCIFB1_TXD_C_MARK,
+};
+static const unsigned int scifb1_clk_c_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(7, 11),
+};
+static const unsigned int scifb1_clk_c_mux[] = {
+	SCIFB1_SCK_C_MARK,
+};
+static const unsigned int scifb1_data_d_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(7, 10), RCAR_GP_PIN(7, 12),
+};
+static const unsigned int scifb1_data_d_mux[] = {
+	SCIFB1_RXD_D_MARK, SCIFB1_TXD_D_MARK,
+};
+/* - SCIFB2 ----------------------------------------------------------------- */
+static const unsigned int scifb2_data_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(4, 16), RCAR_GP_PIN(4, 17),
+};
+static const unsigned int scifb2_data_mux[] = {
+	SCIFB2_RXD_MARK, SCIFB2_TXD_MARK,
+};
+static const unsigned int scifb2_clk_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(4, 15),
+};
+static const unsigned int scifb2_clk_mux[] = {
+	SCIFB2_SCK_MARK,
+};
+static const unsigned int scifb2_ctrl_pins[] = {
+	/* RTS, CTS */
+	RCAR_GP_PIN(4, 14), RCAR_GP_PIN(4, 13),
+};
+static const unsigned int scifb2_ctrl_mux[] = {
+	SCIFB2_RTS_N_MARK, SCIFB2_CTS_N_MARK,
+};
+static const unsigned int scifb2_data_b_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 13),
+};
+static const unsigned int scifb2_data_b_mux[] = {
+	SCIFB2_RXD_B_MARK, SCIFB2_TXD_B_MARK,
+};
+static const unsigned int scifb2_clk_b_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(5, 31),
+};
+static const unsigned int scifb2_clk_b_mux[] = {
+	SCIFB2_SCK_B_MARK,
+};
+static const unsigned int scifb2_ctrl_b_pins[] = {
+	/* RTS, CTS */
+	RCAR_GP_PIN(3, 15), RCAR_GP_PIN(3, 14),
+};
+static const unsigned int scifb2_ctrl_b_mux[] = {
+	SCIFB2_RTS_N_B_MARK, SCIFB2_CTS_N_B_MARK,
+};
+static const unsigned int scifb2_data_c_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(2, 0), RCAR_GP_PIN(2, 1),
+};
+static const unsigned int scifb2_data_c_mux[] = {
+	SCIFB2_RXD_C_MARK, SCIFB2_TXD_C_MARK,
+};
+static const unsigned int scifb2_clk_c_pins[] = {
+	/* SCK */
+	RCAR_GP_PIN(5, 27),
+};
+static const unsigned int scifb2_clk_c_mux[] = {
+	SCIFB2_SCK_C_MARK,
+};
+static const unsigned int scifb2_data_d_pins[] = {
+	/* RXD, TXD */
+	RCAR_GP_PIN(5, 26), RCAR_GP_PIN(5, 25),
+};
+static const unsigned int scifb2_data_d_mux[] = {
+	SCIFB2_RXD_D_MARK, SCIFB2_TXD_D_MARK,
+};
+/* - SDHI0 ------------------------------------------------------------------ */
+static const unsigned int sdhi0_data1_pins[] = {
+	/* D0 */
+	RCAR_GP_PIN(6, 2),
+};
+static const unsigned int sdhi0_data1_mux[] = {
+	SD0_DATA0_MARK,
+};
+static const unsigned int sdhi0_data4_pins[] = {
+	/* D[0:3] */
+	RCAR_GP_PIN(6, 2), RCAR_GP_PIN(6, 3),
+	RCAR_GP_PIN(6, 4), RCAR_GP_PIN(6, 5),
+};
+static const unsigned int sdhi0_data4_mux[] = {
+	SD0_DATA0_MARK, SD0_DATA1_MARK, SD0_DATA2_MARK, SD0_DATA3_MARK,
+};
+static const unsigned int sdhi0_ctrl_pins[] = {
+	/* CLK, CMD */
+	RCAR_GP_PIN(6, 0), RCAR_GP_PIN(6, 1),
+};
+static const unsigned int sdhi0_ctrl_mux[] = {
+	SD0_CLK_MARK, SD0_CMD_MARK,
+};
+static const unsigned int sdhi0_cd_pins[] = {
+	/* CD */
+	RCAR_GP_PIN(6, 6),
+};
+static const unsigned int sdhi0_cd_mux[] = {
+	SD0_CD_MARK,
+};
+static const unsigned int sdhi0_wp_pins[] = {
+	/* WP */
+	RCAR_GP_PIN(6, 7),
+};
+static const unsigned int sdhi0_wp_mux[] = {
+	SD0_WP_MARK,
+};
+/* - SDHI1 ------------------------------------------------------------------ */
+static const unsigned int sdhi1_data1_pins[] = {
+	/* D0 */
+	RCAR_GP_PIN(6, 10),
+};
+static const unsigned int sdhi1_data1_mux[] = {
+	SD1_DATA0_MARK,
+};
+static const unsigned int sdhi1_data4_pins[] = {
+	/* D[0:3] */
+	RCAR_GP_PIN(6, 10), RCAR_GP_PIN(6, 11),
+	RCAR_GP_PIN(6, 12), RCAR_GP_PIN(6, 13),
+};
+static const unsigned int sdhi1_data4_mux[] = {
+	SD1_DATA0_MARK, SD1_DATA1_MARK, SD1_DATA2_MARK, SD1_DATA3_MARK,
+};
+static const unsigned int sdhi1_ctrl_pins[] = {
+	/* CLK, CMD */
+	RCAR_GP_PIN(6, 8), RCAR_GP_PIN(6, 9),
+};
+static const unsigned int sdhi1_ctrl_mux[] = {
+	SD1_CLK_MARK, SD1_CMD_MARK,
+};
+static const unsigned int sdhi1_cd_pins[] = {
+	/* CD */
+	RCAR_GP_PIN(6, 14),
+};
+static const unsigned int sdhi1_cd_mux[] = {
+	SD1_CD_MARK,
+};
+static const unsigned int sdhi1_wp_pins[] = {
+	/* WP */
+	RCAR_GP_PIN(6, 15),
+};
+static const unsigned int sdhi1_wp_mux[] = {
+	SD1_WP_MARK,
+};
+/* - SDHI2 ------------------------------------------------------------------ */
+static const unsigned int sdhi2_data1_pins[] = {
+	/* D0 */
+	RCAR_GP_PIN(6, 18),
+};
+static const unsigned int sdhi2_data1_mux[] = {
+	SD2_DATA0_MARK,
+};
+static const unsigned int sdhi2_data4_pins[] = {
+	/* D[0:3] */
+	RCAR_GP_PIN(6, 18), RCAR_GP_PIN(6, 19),
+	RCAR_GP_PIN(6, 20), RCAR_GP_PIN(6, 21),
+};
+static const unsigned int sdhi2_data4_mux[] = {
+	SD2_DATA0_MARK, SD2_DATA1_MARK, SD2_DATA2_MARK, SD2_DATA3_MARK,
+};
+static const unsigned int sdhi2_ctrl_pins[] = {
+	/* CLK, CMD */
+	RCAR_GP_PIN(6, 16), RCAR_GP_PIN(6, 17),
+};
+static const unsigned int sdhi2_ctrl_mux[] = {
+	SD2_CLK_MARK, SD2_CMD_MARK,
+};
+static const unsigned int sdhi2_cd_pins[] = {
+	/* CD */
+	RCAR_GP_PIN(6, 22),
+};
+static const unsigned int sdhi2_cd_mux[] = {
+	SD2_CD_MARK,
+};
+static const unsigned int sdhi2_wp_pins[] = {
+	/* WP */
+	RCAR_GP_PIN(6, 23),
+};
+static const unsigned int sdhi2_wp_mux[] = {
+	SD2_WP_MARK,
+};
+/* - USB0 ------------------------------------------------------------------- */
+static const unsigned int usb0_pwen_pins[] = {
+	/* PWEN */
+	RCAR_GP_PIN(7, 23),
+};
+static const unsigned int usb0_pwen_mux[] = {
+	USB0_PWEN_MARK,
+};
+static const unsigned int usb0_ovc_pins[] = {
+	/* OVC */
+	RCAR_GP_PIN(7, 24),
+};
+static const unsigned int usb0_ovc_mux[] = {
+	USB0_OVC_MARK,
+};
+/* - USB1 ------------------------------------------------------------------- */
+static const unsigned int usb1_pwen_pins[] = {
+	/* PWEN */
+	RCAR_GP_PIN(7, 25),
+};
+static const unsigned int usb1_pwen_mux[] = {
+	USB1_PWEN_MARK,
+};
+static const unsigned int usb1_ovc_pins[] = {
+	/* OVC */
+	RCAR_GP_PIN(6, 30),
+};
+static const unsigned int usb1_ovc_mux[] = {
+	USB1_OVC_MARK,
+};
+
+static const struct sh_pfc_pin_group pinmux_groups[] = {
+	SH_PFC_PIN_GROUP(du_rgb666),
+	SH_PFC_PIN_GROUP(du_rgb888),
+	SH_PFC_PIN_GROUP(du_clk_out_0),
+	SH_PFC_PIN_GROUP(du_clk_out_1),
+	SH_PFC_PIN_GROUP(du_sync_1),
+	SH_PFC_PIN_GROUP(du_cde_disp),
+	SH_PFC_PIN_GROUP(du0_clk_in),
+	SH_PFC_PIN_GROUP(du1_clk_in),
+	SH_PFC_PIN_GROUP(eth_link),
+	SH_PFC_PIN_GROUP(eth_magic),
+	SH_PFC_PIN_GROUP(eth_mdio),
+	SH_PFC_PIN_GROUP(eth_rmii),
+	SH_PFC_PIN_GROUP(intc_irq0),
+	SH_PFC_PIN_GROUP(intc_irq1),
+	SH_PFC_PIN_GROUP(intc_irq2),
+	SH_PFC_PIN_GROUP(intc_irq3),
+	SH_PFC_PIN_GROUP(mmc_data1),
+	SH_PFC_PIN_GROUP(mmc_data4),
+	SH_PFC_PIN_GROUP(mmc_data8),
+	SH_PFC_PIN_GROUP(mmc_ctrl),
+	SH_PFC_PIN_GROUP(msiof0_clk),
+	SH_PFC_PIN_GROUP(msiof0_sync),
+	SH_PFC_PIN_GROUP(msiof0_ss1),
+	SH_PFC_PIN_GROUP(msiof0_ss2),
+	SH_PFC_PIN_GROUP(msiof0_rx),
+	SH_PFC_PIN_GROUP(msiof0_tx),
+	SH_PFC_PIN_GROUP(msiof1_clk),
+	SH_PFC_PIN_GROUP(msiof1_sync),
+	SH_PFC_PIN_GROUP(msiof1_ss1),
+	SH_PFC_PIN_GROUP(msiof1_ss2),
+	SH_PFC_PIN_GROUP(msiof1_rx),
+	SH_PFC_PIN_GROUP(msiof1_tx),
+	SH_PFC_PIN_GROUP(msiof2_clk),
+	SH_PFC_PIN_GROUP(msiof2_sync),
+	SH_PFC_PIN_GROUP(msiof2_ss1),
+	SH_PFC_PIN_GROUP(msiof2_ss2),
+	SH_PFC_PIN_GROUP(msiof2_rx),
+	SH_PFC_PIN_GROUP(msiof2_tx),
+	SH_PFC_PIN_GROUP(scif0_data),
+	SH_PFC_PIN_GROUP(scif0_data_b),
+	SH_PFC_PIN_GROUP(scif0_data_c),
+	SH_PFC_PIN_GROUP(scif0_data_d),
+	SH_PFC_PIN_GROUP(scif0_data_e),
+	SH_PFC_PIN_GROUP(scif1_data),
+	SH_PFC_PIN_GROUP(scif1_data_b),
+	SH_PFC_PIN_GROUP(scif1_clk_b),
+	SH_PFC_PIN_GROUP(scif1_data_c),
+	SH_PFC_PIN_GROUP(scif1_data_d),
+	SH_PFC_PIN_GROUP(scif2_data),
+	SH_PFC_PIN_GROUP(scif2_data_b),
+	SH_PFC_PIN_GROUP(scif2_clk_b),
+	SH_PFC_PIN_GROUP(scif2_data_c),
+	SH_PFC_PIN_GROUP(scif2_data_e),
+	SH_PFC_PIN_GROUP(scif3_data),
+	SH_PFC_PIN_GROUP(scif3_clk),
+	SH_PFC_PIN_GROUP(scif3_data_b),
+	SH_PFC_PIN_GROUP(scif3_clk_b),
+	SH_PFC_PIN_GROUP(scif3_data_c),
+	SH_PFC_PIN_GROUP(scif3_data_d),
+	SH_PFC_PIN_GROUP(scif4_data),
+	SH_PFC_PIN_GROUP(scif4_data_b),
+	SH_PFC_PIN_GROUP(scif4_data_c),
+	SH_PFC_PIN_GROUP(scif5_data),
+	SH_PFC_PIN_GROUP(scif5_data_b),
+	SH_PFC_PIN_GROUP(scifa0_data),
+	SH_PFC_PIN_GROUP(scifa0_data_b),
+	SH_PFC_PIN_GROUP(scifa1_data),
+	SH_PFC_PIN_GROUP(scifa1_clk),
+	SH_PFC_PIN_GROUP(scifa1_data_b),
+	SH_PFC_PIN_GROUP(scifa1_clk_b),
+	SH_PFC_PIN_GROUP(scifa1_data_c),
+	SH_PFC_PIN_GROUP(scifa2_data),
+	SH_PFC_PIN_GROUP(scifa2_clk),
+	SH_PFC_PIN_GROUP(scifa2_data_b),
+	SH_PFC_PIN_GROUP(scifa3_data),
+	SH_PFC_PIN_GROUP(scifa3_clk),
+	SH_PFC_PIN_GROUP(scifa3_data_b),
+	SH_PFC_PIN_GROUP(scifa3_clk_b),
+	SH_PFC_PIN_GROUP(scifa3_data_c),
+	SH_PFC_PIN_GROUP(scifa3_clk_c),
+	SH_PFC_PIN_GROUP(scifa4_data),
+	SH_PFC_PIN_GROUP(scifa4_data_b),
+	SH_PFC_PIN_GROUP(scifa4_data_c),
+	SH_PFC_PIN_GROUP(scifa5_data),
+	SH_PFC_PIN_GROUP(scifa5_data_b),
+	SH_PFC_PIN_GROUP(scifa5_data_c),
+	SH_PFC_PIN_GROUP(scifb0_data),
+	SH_PFC_PIN_GROUP(scifb0_clk),
+	SH_PFC_PIN_GROUP(scifb0_ctrl),
+	SH_PFC_PIN_GROUP(scifb0_data_b),
+	SH_PFC_PIN_GROUP(scifb0_clk_b),
+	SH_PFC_PIN_GROUP(scifb0_ctrl_b),
+	SH_PFC_PIN_GROUP(scifb0_data_c),
+	SH_PFC_PIN_GROUP(scifb0_clk_c),
+	SH_PFC_PIN_GROUP(scifb0_data_d),
+	SH_PFC_PIN_GROUP(scifb0_clk_d),
+	SH_PFC_PIN_GROUP(scifb1_data),
+	SH_PFC_PIN_GROUP(scifb1_clk),
+	SH_PFC_PIN_GROUP(scifb1_ctrl),
+	SH_PFC_PIN_GROUP(scifb1_data_b),
+	SH_PFC_PIN_GROUP(scifb1_clk_b),
+	SH_PFC_PIN_GROUP(scifb1_data_c),
+	SH_PFC_PIN_GROUP(scifb1_clk_c),
+	SH_PFC_PIN_GROUP(scifb1_data_d),
+	SH_PFC_PIN_GROUP(scifb2_data),
+	SH_PFC_PIN_GROUP(scifb2_clk),
+	SH_PFC_PIN_GROUP(scifb2_ctrl),
+	SH_PFC_PIN_GROUP(scifb2_data_b),
+	SH_PFC_PIN_GROUP(scifb2_clk_b),
+	SH_PFC_PIN_GROUP(scifb2_ctrl_b),
+	SH_PFC_PIN_GROUP(scifb2_data_c),
+	SH_PFC_PIN_GROUP(scifb2_clk_c),
+	SH_PFC_PIN_GROUP(scifb2_data_d),
+	SH_PFC_PIN_GROUP(sdhi0_data1),
+	SH_PFC_PIN_GROUP(sdhi0_data4),
+	SH_PFC_PIN_GROUP(sdhi0_ctrl),
+	SH_PFC_PIN_GROUP(sdhi0_cd),
+	SH_PFC_PIN_GROUP(sdhi0_wp),
+	SH_PFC_PIN_GROUP(sdhi1_data1),
+	SH_PFC_PIN_GROUP(sdhi1_data4),
+	SH_PFC_PIN_GROUP(sdhi1_ctrl),
+	SH_PFC_PIN_GROUP(sdhi1_cd),
+	SH_PFC_PIN_GROUP(sdhi1_wp),
+	SH_PFC_PIN_GROUP(sdhi2_data1),
+	SH_PFC_PIN_GROUP(sdhi2_data4),
+	SH_PFC_PIN_GROUP(sdhi2_ctrl),
+	SH_PFC_PIN_GROUP(sdhi2_cd),
+	SH_PFC_PIN_GROUP(sdhi2_wp),
+	SH_PFC_PIN_GROUP(usb0_pwen),
+	SH_PFC_PIN_GROUP(usb0_ovc),
+	SH_PFC_PIN_GROUP(usb1_pwen),
+	SH_PFC_PIN_GROUP(usb1_ovc),
+};
+
+static const char * const du_groups[] = {
+	"du_rgb666",
+	"du_rgb888",
+	"du_clk_out_0",
+	"du_clk_out_1",
+	"du_sync_1",
+	"du_cde_disp",
+};
+
+static const char * const du0_groups[] = {
+	"du0_clk_in",
+};
+
+static const char * const du1_groups[] = {
+	"du1_clk_in",
+};
+
+static const char * const eth_groups[] = {
+	"eth_link",
+	"eth_magic",
+	"eth_mdio",
+	"eth_rmii",
+};
+
+static const char * const intc_groups[] = {
+	"intc_irq0",
+	"intc_irq1",
+	"intc_irq2",
+	"intc_irq3",
+};
+
+static const char * const mmc_groups[] = {
+	"mmc_data1",
+	"mmc_data4",
+	"mmc_data8",
+	"mmc_ctrl",
+};
+
+static const char * const msiof0_groups[] = {
+	"msiof0_clk",
+	"msiof0_ctrl",
+	"msiof0_data",
+};
+
+static const char * const msiof1_groups[] = {
+	"msiof1_clk",
+	"msiof1_ctrl",
+	"msiof1_data",
+};
+
+static const char * const msiof2_groups[] = {
+	"msiof2_clk",
+	"msiof2_ctrl",
+	"msiof2_data",
+};
+
+static const char * const scif0_groups[] = {
+	"scif0_data",
+	"scif0_data_b",
+	"scif0_data_c",
+	"scif0_data_d",
+	"scif0_data_e",
+};
+
+static const char * const scif1_groups[] = {
+	"scif1_data",
+	"scif1_data_b",
+	"scif1_clk_b",
+	"scif1_data_c",
+	"scif1_data_d",
+};
+
+static const char * const scif2_groups[] = {
+	"scif2_data",
+	"scif2_data_b",
+	"scif2_clk_b",
+	"scif2_data_c",
+	"scif2_data_e",
+};
+static const char * const scif3_groups[] = {
+	"scif3_data",
+	"scif3_clk",
+	"scif3_data_b",
+	"scif3_clk_b",
+	"scif3_data_c",
+	"scif3_data_d",
+};
+static const char * const scif4_groups[] = {
+	"scif4_data",
+	"scif4_data_b",
+	"scif4_data_c",
+};
+static const char * const scif5_groups[] = {
+	"scif5_data",
+	"scif5_data_b",
+};
+static const char * const scifa0_groups[] = {
+	"scifa0_data",
+	"scifa0_data_b",
+};
+static const char * const scifa1_groups[] = {
+	"scifa1_data",
+	"scifa1_clk",
+	"scifa1_data_b",
+	"scifa1_clk_b",
+	"scifa1_data_c",
+};
+static const char * const scifa2_groups[] = {
+	"scifa2_data",
+	"scifa2_clk",
+	"scifa2_data_b",
+};
+static const char * const scifa3_groups[] = {
+	"scifa3_data",
+	"scifa3_clk",
+	"scifa3_data_b",
+	"scifa3_clk_b",
+	"scifa3_data_c",
+	"scifa3_clk_c",
+};
+static const char * const scifa4_groups[] = {
+	"scifa4_data",
+	"scifa4_data_b",
+	"scifa4_data_c",
+};
+static const char * const scifa5_groups[] = {
+	"scifa5_data",
+	"scifa5_data_b",
+	"scifa5_data_c",
+};
+static const char * const scifb0_groups[] = {
+	"scifb0_data",
+	"scifb0_clk",
+	"scifb0_ctrl",
+	"scifb0_data_b",
+	"scifb0_clk_b",
+	"scifb0_ctrl_b",
+	"scifb0_data_c",
+	"scifb0_clk_c",
+	"scifb0_data_d",
+	"scifb0_clk_d",
+};
+static const char * const scifb1_groups[] = {
+	"scifb1_data",
+	"scifb1_clk",
+	"scifb1_ctrl",
+	"scifb1_data_b",
+	"scifb1_clk_b",
+	"scifb1_data_c",
+	"scifb1_clk_c",
+	"scifb1_data_d",
+};
+static const char * const scifb2_groups[] = {
+	"scifb2_data",
+	"scifb2_clk",
+	"scifb2_ctrl",
+	"scifb2_data_b",
+	"scifb2_clk_b",
+	"scifb2_ctrl_b",
+	"scifb0_data_c",
+	"scifb2_clk_c",
+	"scifb2_data_d",
+};
+
+static const char * const sdhi0_groups[] = {
+	"sdhi0_data1",
+	"sdhi0_data4",
+	"sdhi0_ctrl",
+	"sdhi0_cd",
+	"sdhi0_wp",
+};
+
+static const char * const sdhi1_groups[] = {
+	"sdhi1_data1",
+	"sdhi1_data4",
+	"sdhi1_ctrl",
+	"sdhi1_cd",
+	"sdhi1_wp",
+};
+
+static const char * const sdhi2_groups[] = {
+	"sdhi2_data1",
+	"sdhi2_data4",
+	"sdhi2_ctrl",
+	"sdhi2_cd",
+	"sdhi2_wp",
+};
+
+static const char * const usb0_groups[] = {
+	"usb0_pwen",
+	"usb0_ovc",
+};
+static const char * const usb1_groups[] = {
+	"usb1_pwen",
+	"usb1_ovc",
+};
+
+static const struct sh_pfc_function pinmux_functions[] = {
+	SH_PFC_FUNCTION(du),
+	SH_PFC_FUNCTION(du0),
+	SH_PFC_FUNCTION(du1),
+	SH_PFC_FUNCTION(eth),
+	SH_PFC_FUNCTION(intc),
+	SH_PFC_FUNCTION(mmc),
+	SH_PFC_FUNCTION(msiof0),
+	SH_PFC_FUNCTION(msiof1),
+	SH_PFC_FUNCTION(msiof2),
+	SH_PFC_FUNCTION(scif0),
+	SH_PFC_FUNCTION(scif1),
+	SH_PFC_FUNCTION(scif2),
+	SH_PFC_FUNCTION(scif3),
+	SH_PFC_FUNCTION(scif4),
+	SH_PFC_FUNCTION(scif5),
+	SH_PFC_FUNCTION(scifa0),
+	SH_PFC_FUNCTION(scifa1),
+	SH_PFC_FUNCTION(scifa2),
+	SH_PFC_FUNCTION(scifa3),
+	SH_PFC_FUNCTION(scifa4),
+	SH_PFC_FUNCTION(scifa5),
+	SH_PFC_FUNCTION(scifb0),
+	SH_PFC_FUNCTION(scifb1),
+	SH_PFC_FUNCTION(scifb2),
+	SH_PFC_FUNCTION(sdhi0),
+	SH_PFC_FUNCTION(sdhi1),
+	SH_PFC_FUNCTION(sdhi2),
+	SH_PFC_FUNCTION(usb0),
+	SH_PFC_FUNCTION(usb1),
+};
+
+static struct pinmux_cfg_reg pinmux_config_regs[] = {
+	{ PINMUX_CFG_REG("GPSR0", 0xE6060004, 32, 1) {
+		GP_0_31_FN, FN_IP1_22_20,
+		GP_0_30_FN, FN_IP1_19_17,
+		GP_0_29_FN, FN_IP1_16_14,
+		GP_0_28_FN, FN_IP1_13_11,
+		GP_0_27_FN, FN_IP1_10_8,
+		GP_0_26_FN, FN_IP1_7_6,
+		GP_0_25_FN, FN_IP1_5_4,
+		GP_0_24_FN, FN_IP1_3_2,
+		GP_0_23_FN, FN_IP1_1_0,
+		GP_0_22_FN, FN_IP0_30_29,
+		GP_0_21_FN, FN_IP0_28_27,
+		GP_0_20_FN, FN_IP0_26_25,
+		GP_0_19_FN, FN_IP0_24_23,
+		GP_0_18_FN, FN_IP0_22_21,
+		GP_0_17_FN, FN_IP0_20_19,
+		GP_0_16_FN, FN_IP0_18_16,
+		GP_0_15_FN, FN_IP0_15,
+		GP_0_14_FN, FN_IP0_14,
+		GP_0_13_FN, FN_IP0_13,
+		GP_0_12_FN, FN_IP0_12,
+		GP_0_11_FN, FN_IP0_11,
+		GP_0_10_FN, FN_IP0_10,
+		GP_0_9_FN, FN_IP0_9,
+		GP_0_8_FN, FN_IP0_8,
+		GP_0_7_FN, FN_IP0_7,
+		GP_0_6_FN, FN_IP0_6,
+		GP_0_5_FN, FN_IP0_5,
+		GP_0_4_FN, FN_IP0_4,
+		GP_0_3_FN, FN_IP0_3,
+		GP_0_2_FN, FN_IP0_2,
+		GP_0_1_FN, FN_IP0_1,
+		GP_0_0_FN, FN_IP0_0, }
+	},
+	{ PINMUX_CFG_REG("GPSR1", 0xE6060008, 32, 1) {
+		0, 0,
+		0, 0,
+		0, 0,
+		0, 0,
+		0, 0,
+		0, 0,
+		GP_1_25_FN, FN_IP3_21_20,
+		GP_1_24_FN, FN_IP3_19_18,
+		GP_1_23_FN, FN_IP3_17_16,
+		GP_1_22_FN, FN_IP3_15_14,
+		GP_1_21_FN, FN_IP3_13_12,
+		GP_1_20_FN, FN_IP3_11_9,
+		GP_1_19_FN, FN_RD_N,
+		GP_1_18_FN, FN_IP3_8_6,
+		GP_1_17_FN, FN_IP3_5_3,
+		GP_1_16_FN, FN_IP3_2_0,
+		GP_1_15_FN, FN_IP2_29_27,
+		GP_1_14_FN, FN_IP2_26_25,
+		GP_1_13_FN, FN_IP2_24_23,
+		GP_1_12_FN, FN_EX_CS0_N,
+		GP_1_11_FN, FN_IP2_22_21,
+		GP_1_10_FN, FN_IP2_20_19,
+		GP_1_9_FN, FN_IP2_18_16,
+		GP_1_8_FN, FN_IP2_15_13,
+		GP_1_7_FN, FN_IP2_12_10,
+		GP_1_6_FN, FN_IP2_9_7,
+		GP_1_5_FN, FN_IP2_6_5,
+		GP_1_4_FN, FN_IP2_4_3,
+		GP_1_3_FN, FN_IP2_2_0,
+		GP_1_2_FN, FN_IP1_31_29,
+		GP_1_1_FN, FN_IP1_28_26,
+		GP_1_0_FN, FN_IP1_25_23, }
+	},
+	{ PINMUX_CFG_REG("GPSR2", 0xE606000C, 32, 1) {
+		GP_2_31_FN, FN_IP6_7_6,
+		GP_2_30_FN, FN_IP6_5_3,
+		GP_2_29_FN, FN_IP6_2_0,
+		GP_2_28_FN, FN_AUDIO_CLKA,
+		GP_2_27_FN, FN_IP5_31_29,
+		GP_2_26_FN, FN_IP5_28_26,
+		GP_2_25_FN, FN_IP5_25_24,
+		GP_2_24_FN, FN_IP5_23_22,
+		GP_2_23_FN, FN_IP5_21_20,
+		GP_2_22_FN, FN_IP5_19_17,
+		GP_2_21_FN, FN_IP5_16_15,
+		GP_2_20_FN, FN_IP5_14_12,
+		GP_2_19_FN, FN_IP5_11_9,
+		GP_2_18_FN, FN_IP5_8_6,
+		GP_2_17_FN, FN_IP5_5_3,
+		GP_2_16_FN, FN_IP5_2_0,
+		GP_2_15_FN, FN_IP4_30_28,
+		GP_2_14_FN, FN_IP4_27_26,
+		GP_2_13_FN, FN_IP4_25_24,
+		GP_2_12_FN, FN_IP4_23_22,
+		GP_2_11_FN, FN_IP4_21,
+		GP_2_10_FN, FN_IP4_20,
+		GP_2_9_FN, FN_IP4_19,
+		GP_2_8_FN, FN_IP4_18_16,
+		GP_2_7_FN, FN_IP4_15_13,
+		GP_2_6_FN, FN_IP4_12_10,
+		GP_2_5_FN, FN_IP4_9_8,
+		GP_2_4_FN, FN_IP4_7_5,
+		GP_2_3_FN, FN_IP4_4_2,
+		GP_2_2_FN, FN_IP4_1_0,
+		GP_2_1_FN, FN_IP3_30_28,
+		GP_2_0_FN, FN_IP3_27_25 }
+	},
+	{ PINMUX_CFG_REG("GPSR3", 0xE6060010, 32, 1) {
+		GP_3_31_FN, FN_IP9_18_17,
+		GP_3_30_FN, FN_IP9_16,
+		GP_3_29_FN, FN_IP9_15_13,
+		GP_3_28_FN, FN_IP9_12,
+		GP_3_27_FN, FN_IP9_11,
+		GP_3_26_FN, FN_IP9_10_8,
+		GP_3_25_FN, FN_IP9_7,
+		GP_3_24_FN, FN_IP9_6,
+		GP_3_23_FN, FN_IP9_5_3,
+		GP_3_22_FN, FN_IP9_2_0,
+		GP_3_21_FN, FN_IP8_30_28,
+		GP_3_20_FN, FN_IP8_27_26,
+		GP_3_19_FN, FN_IP8_25_24,
+		GP_3_18_FN, FN_IP8_23_21,
+		GP_3_17_FN, FN_IP8_20_18,
+		GP_3_16_FN, FN_IP8_17_15,
+		GP_3_15_FN, FN_IP8_14_12,
+		GP_3_14_FN, FN_IP8_11_9,
+		GP_3_13_FN, FN_IP8_8_6,
+		GP_3_12_FN, FN_IP8_5_3,
+		GP_3_11_FN, FN_IP8_2_0,
+		GP_3_10_FN, FN_IP7_29_27,
+		GP_3_9_FN, FN_IP7_26_24,
+		GP_3_8_FN, FN_IP7_23_21,
+		GP_3_7_FN, FN_IP7_20_19,
+		GP_3_6_FN, FN_IP7_18_17,
+		GP_3_5_FN, FN_IP7_16_15,
+		GP_3_4_FN, FN_IP7_14_13,
+		GP_3_3_FN, FN_IP7_12_11,
+		GP_3_2_FN, FN_IP7_10_9,
+		GP_3_1_FN, FN_IP7_8_6,
+		GP_3_0_FN, FN_IP7_5_3 }
+	},
+	{ PINMUX_CFG_REG("GPSR4", 0xE6060014, 32, 1) {
+		GP_4_31_FN, FN_IP15_5_4,
+		GP_4_30_FN, FN_IP15_3_2,
+		GP_4_29_FN, FN_IP15_1_0,
+		GP_4_28_FN, FN_IP11_8_6,
+		GP_4_27_FN, FN_IP11_5_3,
+		GP_4_26_FN, FN_IP11_2_0,
+		GP_4_25_FN, FN_IP10_31_29,
+		GP_4_24_FN, FN_IP10_28_27,
+		GP_4_23_FN, FN_IP10_26_25,
+		GP_4_22_FN, FN_IP10_24_22,
+		GP_4_21_FN, FN_IP10_21_19,
+		GP_4_20_FN, FN_IP10_18_17,
+		GP_4_19_FN, FN_IP10_16_15,
+		GP_4_18_FN, FN_IP10_14_12,
+		GP_4_17_FN, FN_IP10_11_9,
+		GP_4_16_FN, FN_IP10_8_6,
+		GP_4_15_FN, FN_IP10_5_3,
+		GP_4_14_FN, FN_IP10_2_0,
+		GP_4_13_FN, FN_IP9_31_29,
+		GP_4_12_FN, FN_VI0_DATA7_VI0_B7,
+		GP_4_11_FN, FN_VI0_DATA6_VI0_B6,
+		GP_4_10_FN, FN_VI0_DATA5_VI0_B5,
+		GP_4_9_FN, FN_VI0_DATA4_VI0_B4,
+		GP_4_8_FN, FN_IP9_28_27,
+		GP_4_7_FN, FN_VI0_DATA2_VI0_B2,
+		GP_4_6_FN, FN_VI0_DATA1_VI0_B1,
+		GP_4_5_FN, FN_VI0_DATA0_VI0_B0,
+		GP_4_4_FN, FN_IP9_26_25,
+		GP_4_3_FN, FN_IP9_24_23,
+		GP_4_2_FN, FN_IP9_22_21,
+		GP_4_1_FN, FN_IP9_20_19,
+		GP_4_0_FN, FN_VI0_CLK }
+	},
+	{ PINMUX_CFG_REG("GPSR5", 0xE6060018, 32, 1) {
+		GP_5_31_FN, FN_IP3_24_22,
+		GP_5_30_FN, FN_IP13_9_7,
+		GP_5_29_FN, FN_IP13_6_5,
+		GP_5_28_FN, FN_IP13_4_3,
+		GP_5_27_FN, FN_IP13_2_0,
+		GP_5_26_FN, FN_IP12_29_27,
+		GP_5_25_FN, FN_IP12_26_24,
+		GP_5_24_FN, FN_IP12_23_22,
+		GP_5_23_FN, FN_IP12_21_20,
+		GP_5_22_FN, FN_IP12_19_18,
+		GP_5_21_FN, FN_IP12_17_16,
+		GP_5_20_FN, FN_IP12_15_13,
+		GP_5_19_FN, FN_IP12_12_10,
+		GP_5_18_FN, FN_IP12_9_7,
+		GP_5_17_FN, FN_IP12_6_4,
+		GP_5_16_FN, FN_IP12_3_2,
+		GP_5_15_FN, FN_IP12_1_0,
+		GP_5_14_FN, FN_IP11_31_30,
+		GP_5_13_FN, FN_IP11_29_28,
+		GP_5_12_FN, FN_IP11_27,
+		GP_5_11_FN, FN_IP11_26,
+		GP_5_10_FN, FN_IP11_25,
+		GP_5_9_FN, FN_IP11_24,
+		GP_5_8_FN, FN_IP11_23,
+		GP_5_7_FN, FN_IP11_22,
+		GP_5_6_FN, FN_IP11_21,
+		GP_5_5_FN, FN_IP11_20,
+		GP_5_4_FN, FN_IP11_19,
+		GP_5_3_FN, FN_IP11_18_17,
+		GP_5_2_FN, FN_IP11_16_15,
+		GP_5_1_FN, FN_IP11_14_12,
+		GP_5_0_FN, FN_IP11_11_9 }
+	},
+	{ PINMUX_CFG_REG("GPSR6", 0xE606001C, 32, 1) {
+		GP_6_31_FN, FN_DU0_DOTCLKIN,
+		GP_6_30_FN, FN_USB1_OVC,
+		GP_6_29_FN, FN_IP14_31_29,
+		GP_6_28_FN, FN_IP14_28_26,
+		GP_6_27_FN, FN_IP14_25_23,
+		GP_6_26_FN, FN_IP14_22_20,
+		GP_6_25_FN, FN_IP14_19_17,
+		GP_6_24_FN, FN_IP14_16_14,
+		GP_6_23_FN, FN_IP14_13_11,
+		GP_6_22_FN, FN_IP14_10_8,
+		GP_6_21_FN, FN_IP14_7,
+		GP_6_20_FN, FN_IP14_6,
+		GP_6_19_FN, FN_IP14_5,
+		GP_6_18_FN, FN_IP14_4,
+		GP_6_17_FN, FN_IP14_3,
+		GP_6_16_FN, FN_IP14_2,
+		GP_6_15_FN, FN_IP14_1_0,
+		GP_6_14_FN, FN_IP13_30_28,
+		GP_6_13_FN, FN_IP13_27,
+		GP_6_12_FN, FN_IP13_26,
+		GP_6_11_FN, FN_IP13_25,
+		GP_6_10_FN, FN_IP13_24_23,
+		GP_6_9_FN, FN_IP13_22,
+		0, 0,
+		GP_6_7_FN, FN_IP13_21_19,
+		GP_6_6_FN, FN_IP13_18_16,
+		GP_6_5_FN, FN_IP13_15,
+		GP_6_4_FN, FN_IP13_14,
+		GP_6_3_FN, FN_IP13_13,
+		GP_6_2_FN, FN_IP13_12,
+		GP_6_1_FN, FN_IP13_11,
+		GP_6_0_FN, FN_IP13_10 }
+	},
+	{ PINMUX_CFG_REG("GPSR7", 0xE6060074, 32, 1) {
+		0, 0,
+		0, 0,
+		0, 0,
+		0, 0,
+		0, 0,
+		0, 0,
+		GP_7_25_FN, FN_USB1_PWEN,
+		GP_7_24_FN, FN_USB0_OVC,
+		GP_7_23_FN, FN_USB0_PWEN,
+		GP_7_22_FN, FN_IP15_14_12,
+		GP_7_21_FN, FN_IP15_11_9,
+		GP_7_20_FN, FN_IP15_8_6,
+		GP_7_19_FN, FN_IP7_2_0,
+		GP_7_18_FN, FN_IP6_29_27,
+		GP_7_17_FN, FN_IP6_26_24,
+		GP_7_16_FN, FN_IP6_23_21,
+		GP_7_15_FN, FN_IP6_20_19,
+		GP_7_14_FN, FN_IP6_18_16,
+		GP_7_13_FN, FN_IP6_15_14,
+		GP_7_12_FN, FN_IP6_13_12,
+		GP_7_11_FN, FN_IP6_11_10,
+		GP_7_10_FN, FN_IP6_9_8,
+		GP_7_9_FN, FN_IP16_11_10,
+		GP_7_8_FN, FN_IP16_9_8,
+		GP_7_7_FN, FN_IP16_7_6,
+		GP_7_6_FN, FN_IP16_5_3,
+		GP_7_5_FN, FN_IP16_2_0,
+		GP_7_4_FN, FN_IP15_29_27,
+		GP_7_3_FN, FN_IP15_26_24,
+		GP_7_2_FN, FN_IP15_23_21,
+		GP_7_1_FN, FN_IP15_20_18,
+		GP_7_0_FN, FN_IP15_17_15 }
+	},
+	{ PINMUX_CFG_REG_VAR("IPSR0", 0xE6060020, 32,
+			     1, 2, 2, 2, 2, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1,
+			     1, 1, 1, 1, 1, 1, 1, 1) {
+		/* IP0_31 [1] */
+		0, 0,
+		/* IP0_30_29 [2] */
+		FN_A6, FN_MSIOF1_SCK,
+		0, 0,
+		/* IP0_28_27 [2] */
+		FN_A5, FN_MSIOF0_RXD_B,
+		0, 0,
+		/* IP0_26_25 [2] */
+		FN_A4, FN_MSIOF0_TXD_B,
+		0, 0,
+		/* IP0_24_23 [2] */
+		FN_A3, FN_MSIOF0_SS2_B,
+		0, 0,
+		/* IP0_22_21 [2] */
+		FN_A2, FN_MSIOF0_SS1_B,
+		0, 0,
+		/* IP0_20_19 [2] */
+		FN_A1, FN_MSIOF0_SYNC_B,
+		0, 0,
+		/* IP0_18_16 [3] */
+		FN_A0, FN_ATAWR0_N_C, FN_MSIOF0_SCK_B, FN_SCL0_C, FN_PWM2_B,
+		0, 0, 0,
+		/* IP0_15 [1] */
+		FN_D15, 0,
+		/* IP0_14 [1] */
+		FN_D14, 0,
+		/* IP0_13 [1] */
+		FN_D13, 0,
+		/* IP0_12 [1] */
+		FN_D12, 0,
+		/* IP0_11 [1] */
+		FN_D11, 0,
+		/* IP0_10 [1] */
+		FN_D10, 0,
+		/* IP0_9 [1] */
+		FN_D9, 0,
+		/* IP0_8 [1] */
+		FN_D8, 0,
+		/* IP0_7 [1] */
+		FN_D7, 0,
+		/* IP0_6 [1] */
+		FN_D6, 0,
+		/* IP0_5 [1] */
+		FN_D5, 0,
+		/* IP0_4 [1] */
+		FN_D4, 0,
+		/* IP0_3 [1] */
+		FN_D3, 0,
+		/* IP0_2 [1] */
+		FN_D2, 0,
+		/* IP0_1 [1] */
+		FN_D1, 0,
+		/* IP0_0 [1] */
+		FN_D0, 0, }
+	},
+	{ PINMUX_CFG_REG_VAR("IPSR1", 0xE6060024, 32,
+			     3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2) {
+		/* IP1_31_29 [3] */
+		FN_A18, FN_DREQ1, FN_SCIFA1_RXD_C, 0, FN_SCIFB1_RXD_C,
+		0, 0, 0,
+		/* IP1_28_26 [3] */
+		FN_A17, FN_DACK2_B, 0, FN_SDA0_C,
+		0, 0, 0, 0,
+		/* IP1_25_23 [3] */
+		FN_A16, FN_DREQ2_B, FN_FMCLK_C, 0, FN_SCIFA1_SCK_B,
+		0, 0, 0,
+		/* IP1_22_20 [3] */
+		FN_A15, FN_BPFCLK_C,
+		0, 0, 0, 0, 0, 0,
+		/* IP1_19_17 [3] */
+		FN_A14, FN_ATADIR0_N_C, FN_FMIN, FN_FMIN_C, FN_MSIOF1_SYNC_D,
+		0, 0, 0,
+		/* IP1_16_14 [3] */
+		FN_A13, FN_ATAG0_N_C, FN_BPFCLK, FN_MSIOF1_SS1_D,
+		0, 0, 0, 0,
+		/* IP1_13_11 [3] */
+		FN_A12, FN_FMCLK, FN_SDA3_D, FN_MSIOF1_SCK_D,
+		0, 0, 0, 0,
+		/* IP1_10_8 [3] */
+		FN_A11, FN_MSIOF1_RXD, FN_SCL3_D, FN_MSIOF1_RXD_D,
+		0, 0, 0, 0,
+		/* IP1_7_6 [2] */
+		FN_A10, FN_MSIOF1_TXD, 0, FN_MSIOF1_TXD_D,
+		/* IP1_5_4 [2] */
+		FN_A9, FN_MSIOF1_SS2, FN_SDA0, 0,
+		/* IP1_3_2 [2] */
+		FN_A8, FN_MSIOF1_SS1, FN_SCL0, 0,
+		/* IP1_1_0 [2] */
+		FN_A7, FN_MSIOF1_SYNC,
+		0, 0, }
+	},
+	{ PINMUX_CFG_REG_VAR("IPSR2", 0xE6060028, 32,
+			     2, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 3) {
+		/* IP2_31_20 [2] */
+		0, 0, 0, 0,
+		/* IP2_29_27 [3] */
+		FN_EX_CS3_N, FN_ATADIR0_N, FN_MSIOF2_TXD,
+		FN_ATAG0_N, 0, FN_EX_WAIT1,
+		0, 0,
+		/* IP2_26_25 [2] */
+		FN_EX_CS2_N, FN_ATAWR0_N, FN_MSIOF2_SYNC, 0,
+		/* IP2_24_23 [2] */
+		FN_EX_CS1_N, FN_MSIOF2_SCK, 0, 0,
+		/* IP2_22_21 [2] */
+		FN_CS1_N_A26, FN_ATADIR0_N_B, FN_SDA1, 0,
+		/* IP2_20_19 [2] */
+		FN_CS0_N, FN_ATAG0_N_B, FN_SCL1, 0,
+		/* IP2_18_16 [3] */
+		FN_A25, FN_DACK2, FN_SSL, FN_DREQ1_C, FN_RX1, FN_SCIFA1_RXD,
+		0, 0,
+		/* IP2_15_13 [3] */
+		FN_A24, FN_DREQ2, FN_IO3, FN_TX1, FN_SCIFA1_TXD,
+		0, 0, 0,
+		/* IP2_12_0 [3] */
+		FN_A23, FN_IO2, FN_BPFCLK_B, FN_RX0, FN_SCIFA0_RXD,
+		0, 0, 0,
+		/* IP2_9_7 [3] */
+		FN_A22, FN_MISO_IO1, FN_FMCLK_B, FN_TX0, FN_SCIFA0_TXD,
+		0, 0, 0,
+		/* IP2_6_5 [2] */
+		FN_A21, FN_ATAWR0_N_B, FN_MOSI_IO0, 0,
+		/* IP2_4_3 [2] */
+		FN_A20, FN_SPCLK, 0, 0,
+		/* IP2_2_0 [3] */
+		FN_A19, FN_DACK1, FN_SCIFA1_TXD_C, 0,
+		FN_SCIFB1_TXD_C, 0, FN_SCIFB1_SCK_B, 0, }
+	},
+	{ PINMUX_CFG_REG_VAR("IPSR3", 0xE606002C, 32,
+			     1, 3, 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 3) {
+		/* IP3_31 [1] */
+		0, 0,
+		/* IP3_30_28 [3] */
+		FN_SSI_WS0129, FN_HTX0_C, FN_HTX2_C,
+		FN_SCIFB0_TXD_C, FN_SCIFB2_TXD_C,
+		0, 0, 0,
+		/* IP3_27_25 [3] */
+		FN_SSI_SCK0129, FN_HRX0_C, FN_HRX2_C,
+		FN_SCIFB0_RXD_C, FN_SCIFB2_RXD_C,
+		0, 0, 0,
+		/* IP3_24_22 [3] */
+		FN_SPEEDIN, 0, FN_HSCK0_C, FN_HSCK2_C, FN_SCIFB0_SCK_B,
+		FN_SCIFB2_SCK_B, FN_DREQ2_C, FN_HTX2_D,
+		/* IP3_21_20 [2] */
+		FN_DACK0, FN_DRACK0, FN_REMOCON, 0,
+		/* IP3_19_18 [2] */
+		FN_DREQ0, FN_PWM3, FN_TPU_TO3, 0,
+		/* IP3_17_16 [2] */
+		FN_EX_WAIT0, FN_HRTS2_N_B, FN_SCIFB0_CTS_N_B, 0,
+		/* IP3_15_14 [2] */
+		FN_WE1_N, FN_ATARD0_N_B, FN_HTX2_B, FN_SCIFB0_RTS_N_B,
+		/* IP3_13_12 [2] */
+		FN_WE0_N, FN_HCTS2_N_B, FN_SCIFB0_TXD_B, 0,
+		/* IP3_11_9 [3] */
+		FN_RD_WR_N, FN_HRX2_B, FN_FMIN_B, FN_SCIFB0_RXD_B, FN_DREQ1_D,
+		0, 0, 0,
+		/* IP3_8_6 [3] */
+		FN_BS_N, FN_ATACS10_N, FN_MSIOF2_SS2, FN_HTX1_B,
+		FN_SCIFB1_TXD_B, FN_PWM2, FN_TPU_TO2, 0,
+		/* IP3_5_3 [3] */
+		FN_EX_CS5_N, FN_ATACS00_N, FN_MSIOF2_SS1, FN_HRX1_B,
+		FN_SCIFB1_RXD_B, FN_PWM1, FN_TPU_TO1, 0,
+		/* IP3_2_0 [3] */
+		FN_EX_CS4_N, FN_ATARD0_N, FN_MSIOF2_RXD, 0, FN_EX_WAIT2,
+		0, 0, 0, }
+	},
+	{ PINMUX_CFG_REG_VAR("IPSR4", 0xE6060030, 32,
+			     1, 3, 2, 2, 2, 1, 1, 1, 3, 3, 3, 2, 3, 3, 2) {
+		/* IP4_31 [1] */
+		0, 0,
+		/* IP4_30_28 [3] */
+		FN_SSI_SCK5, FN_MSIOF1_SCK_C, FN_TS_SDATA0, FN_GLO_I0,
+		FN_MSIOF2_SYNC_D, FN_VI1_R2_B,
+		0, 0,
+		/* IP4_27_26 [2] */
+		FN_SSI_SDATA4, FN_MSIOF2_SCK_D, 0, 0,
+		/* IP4_25_24 [2] */
+		FN_SSI_WS4, FN_GLO_RFON_D, 0, 0,
+		/* IP4_23_22 [2] */
+		FN_SSI_SCK4, FN_GLO_SS_D, 0, 0,
+		/* IP4_21 [1] */
+		FN_SSI_SDATA3, 0,
+		/* IP4_20 [1] */
+		FN_SSI_WS34, 0,
+		/* IP4_19 [1] */
+		FN_SSI_SCK34, 0,
+		/* IP4_18_16 [3] */
+		FN_SSI_SDATA2, FN_GPS_MAG_B, FN_TX2_E, FN_HRTS1_N_E,
+		0, 0, 0, 0,
+		/* IP4_15_13 [3] */
+		FN_SSI_WS2, FN_SDA2, FN_GPS_SIGN_B, FN_RX2_E,
+		FN_GLO_Q1_D, FN_HCTS1_N_E,
+		0, 0,
+		/* IP4_12_10 [3] */
+		FN_SSI_SCK2, FN_SCL2, FN_GPS_CLK_B, FN_GLO_Q0_D, FN_HSCK1_E,
+		0, 0, 0,
+		/* IP4_9_8 [2] */
+		FN_SSI_SDATA1, FN_SDA1_B, FN_SDA8_B, FN_MSIOF2_RXD_C,
+		/* IP4_7_5 [3] */
+		FN_SSI_WS1, FN_SCL1_B, FN_SCL8_B, FN_MSIOF2_TXD_C, FN_GLO_I1_D,
+		0, 0, 0,
+		/* IP4_4_2 [3] */
+		FN_SSI_SCK1, FN_SDA0_B, FN_SDA7_B,
+		FN_MSIOF2_SYNC_C, FN_GLO_I0_D,
+		0, 0, 0,
+		/* IP4_1_0 [2] */
+		FN_SSI_SDATA0, FN_SCL0_B, FN_SCL7_B, FN_MSIOF2_SCK_C, }
+	},
+	{ PINMUX_CFG_REG_VAR("IPSR5", 0xE6060034, 32,
+			     3, 3, 2, 2, 2, 3, 2, 3, 3, 3, 3, 3) {
+		/* IP5_31_29 [3] */
+		FN_SSI_SDATA9, FN_RX3_D, FN_CAN0_RX_D,
+		0, 0, 0, 0, 0,
+		/* IP5_28_26 [3] */
+		FN_SSI_WS9, FN_TX3_D, FN_CAN0_TX_D, FN_GLO_SDATA_D,
+		0, 0, 0, 0,
+		/* IP5_25_24 [2] */
+		FN_SSI_SCK9, FN_RX1_D, FN_GLO_SCLK_D, 0,
+		/* IP5_23_22 [2] */
+		FN_SSI_SDATA8, FN_TX1_D, FN_STP_ISSYNC_0_B, 0,
+		/* IP5_21_20 [2] */
+		FN_SSI_SDATA7, FN_RX0_D, FN_STP_ISEN_0_B, 0,
+		/* IP5_19_17 [3] */
+		FN_SSI_WS78, FN_TX0_D, FN_STP_ISD_0_B, FN_GLO_RFON,
+		0, 0, 0, 0,
+		/* IP5_16_15 [2] */
+		FN_SSI_SCK78, FN_STP_ISCLK_0_B, FN_GLO_SS, 0,
+		/* IP5_14_12 [3] */
+		FN_SSI_SDATA6, FN_STP_IVCXO27_0_B, FN_GLO_SDATA, FN_VI1_R7_B,
+		0, 0, 0, 0,
+		/* IP5_11_9 [3] */
+		FN_SSI_WS6, FN_GLO_SCLK, FN_MSIOF2_SS2_D, FN_VI1_R6_B,
+		0, 0, 0, 0,
+		/* IP5_8_6 [3] */
+		FN_SSI_SCK6, FN_MSIOF1_RXD_C, FN_TS_SPSYNC0, FN_GLO_Q1,
+		FN_MSIOF2_RXD_D, FN_VI1_R5_B,
+		0, 0,
+		/* IP5_5_3 [3] */
+		FN_SSI_SDATA5, FN_MSIOF1_TXD_C, FN_TS_SDEN0, FN_GLO_Q0,
+		FN_MSIOF2_SS1_D, FN_VI1_R4_B,
+		0, 0,
+		/* IP5_2_0 [3] */
+		FN_SSI_WS5, FN_MSIOF1_SYNC_C, FN_TS_SCK0, FN_GLO_I1,
+		FN_MSIOF2_TXD_D, FN_VI1_R3_B,
+		0, 0, }
+	},
+	{ PINMUX_CFG_REG_VAR("IPSR6", 0xE6060038, 32,
+			     2, 3, 3, 3, 2, 3, 2, 2, 2, 2, 2, 3, 3) {
+		/* IP6_31_30 [2] */
+		0, 0, 0, 0,
+		/* IP6_29_27 [3] */
+		FN_IRQ8, FN_HRTS1_N_C, FN_MSIOF1_RXD_B,
+		FN_GPS_SIGN_C, FN_GPS_SIGN_D,
+		0, 0, 0,
+		/* IP6_26_24 [3] */
+		FN_IRQ7, FN_HCTS1_N_C, FN_MSIOF1_TXD_B,
+		FN_GPS_CLK_C, FN_GPS_CLK_D,
+		0, 0, 0,
+		/* IP6_23_21 [3] */
+		FN_IRQ6, FN_HSCK1_C, FN_MSIOF1_SS2_B,
+		FN_SDA1_E, FN_MSIOF2_SYNC_E,
+		0, 0, 0,
+		/* IP6_20_19 [2] */
+		FN_IRQ5, FN_HTX1_C, FN_SCL1_E, FN_MSIOF2_SCK_E,
+		/* IP6_18_16 [3] */
+		FN_IRQ4, FN_HRX1_C, FN_SDA4_C, FN_MSIOF2_RXD_E, FN_INTC_IRQ4_N,
+		0, 0, 0,
+		/* IP6_15_14 [2] */
+		FN_IRQ3, FN_SCL4_C, FN_MSIOF2_TXD_E, FN_INTC_IRQ3_N,
+		/* IP6_13_12 [2] */
+		FN_IRQ2, FN_SCIFB1_TXD_D, FN_INTC_IRQ2_N, 0,
+		/* IP6_11_10 [2] */
+		FN_IRQ1, FN_SCIFB1_SCK_C, FN_INTC_IRQ1_N, 0,
+		/* IP6_9_8 [2] */
+		FN_IRQ0, FN_SCIFB1_RXD_D, FN_INTC_IRQ0_N, 0,
+		/* IP6_7_6 [2] */
+		FN_AUDIO_CLKOUT, FN_MSIOF1_SS1_B, FN_TX2, FN_SCIFA2_TXD,
+		/* IP6_5_3 [3] */
+		FN_AUDIO_CLKC, FN_SCIFB0_SCK_C, FN_MSIOF1_SYNC_B, FN_RX2,
+		FN_SCIFA2_RXD, FN_FMIN_E,
+		0, 0,
+		/* IP6_2_0 [3] */
+		FN_AUDIO_CLKB, FN_STP_OPWM_0_B, FN_MSIOF1_SCK_B,
+		FN_SCIF_CLK, 0, FN_BPFCLK_E,
+		0, 0, }
+	},
+	{ PINMUX_CFG_REG_VAR("IPSR7", 0xE606003C, 32,
+			     2, 3, 3, 3, 2, 2, 2, 2, 2, 2, 3, 3, 3) {
+		/* IP7_31_30 [2] */
+		0, 0, 0, 0,
+		/* IP7_29_27 [3] */
+		FN_DU1_DG2, FN_LCDOUT10, FN_VI1_DATA4_B, FN_SCIF1_SCK_B,
+		FN_SCIFA1_SCK, FN_SSI_SCK78_B,
+		0, 0,
+		/* IP7_26_24 [3] */
+		FN_DU1_DG1, FN_LCDOUT9, FN_VI1_DATA3_B, FN_RX1_B,
+		FN_SCIFA1_RXD_B, FN_MSIOF2_SS2_B,
+		0, 0,
+		/* IP7_23_21 [3] */
+		FN_DU1_DG0, FN_LCDOUT8, FN_VI1_DATA2_B, FN_TX1_B,
+		FN_SCIFA1_TXD_B, FN_MSIOF2_SS1_B,
+		0, 0,
+		/* IP7_20_19 [2] */
+		FN_DU1_DR7, FN_LCDOUT7, FN_SSI_SDATA1_B, 0,
+		/* IP7_18_17 [2] */
+		FN_DU1_DR6, FN_LCDOUT6, FN_SSI_WS1_B, 0,
+		/* IP7_16_15 [2] */
+		FN_DU1_DR5, FN_LCDOUT5, FN_SSI_SCK1_B, 0,
+		/* IP7_14_13 [2] */
+		FN_DU1_DR4, FN_LCDOUT4, FN_SSI_SDATA0_B, 0,
+		/* IP7_12_11 [2] */
+		FN_DU1_DR3, FN_LCDOUT3, FN_SSI_WS0129_B, 0,
+		/* IP7_10_9 [2] */
+		FN_DU1_DR2, FN_LCDOUT2, FN_SSI_SCK0129_B, 0,
+		/* IP7_8_6 [3] */
+		FN_DU1_DR1, FN_LCDOUT1, FN_VI1_DATA1_B, FN_RX0_B,
+		FN_SCIFA0_RXD_B, FN_MSIOF2_SYNC_B,
+		0, 0,
+		/* IP7_5_3 [3] */
+		FN_DU1_DR0, FN_LCDOUT0, FN_VI1_DATA0_B, FN_TX0_B,
+		FN_SCIFA0_TXD_B, FN_MSIOF2_SCK_B,
+		0, 0,
+		/* IP7_2_0 [3] */
+		FN_IRQ9, FN_DU1_DOTCLKIN_B, FN_CAN_CLK_D, FN_GPS_MAG_C,
+		FN_SCIF_CLK_B, FN_GPS_MAG_D,
+		0, 0, }
+	},
+	{ PINMUX_CFG_REG_VAR("IPSR8", 0xE6060040, 32,
+			     1, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3) {
+		/* IP8_31 [1] */
+		0, 0,
+		/* IP8_30_28 [3] */
+		FN_DU1_DB5, FN_LCDOUT21, FN_TX3, FN_SCIFA3_TXD, FN_CAN1_TX,
+		0, 0, 0,
+		/* IP8_27_26 [2] */
+		FN_DU1_DB4, FN_LCDOUT20, FN_VI1_FIELD_B, FN_CAN1_RX,
+		/* IP8_25_24 [2] */
+		FN_DU1_DB3, FN_LCDOUT19, FN_VI1_CLKENB_B, 0,
+		/* IP8_23_21 [3] */
+		FN_DU1_DB2, FN_LCDOUT18, FN_VI1_VSYNC_N_B, FN_SCIF2_SCK_B,
+		FN_SCIFA2_SCK, FN_SSI_SDATA9_B,
+		0, 0,
+		/* IP8_20_18 [3] */
+		FN_DU1_DB1, FN_LCDOUT17, FN_VI1_HSYNC_N_B, FN_RX2_B,
+		FN_SCIFA2_RXD_B, FN_MSIOF2_RXD_B,
+		0, 0,
+		/* IP8_17_15 [3] */
+		FN_DU1_DB0, FN_LCDOUT16, FN_VI1_CLK_B, FN_TX2_B,
+		FN_SCIFA2_TXD_B, FN_MSIOF2_TXD_B,
+		0, 0,
+		/* IP8_14_12 [3] */
+		FN_DU1_DG7, FN_LCDOUT15, FN_HTX0_B,
+		FN_SCIFB2_RTS_N_B, FN_SSI_WS9_B,
+		0, 0, 0,
+		/* IP8_11_9 [3] */
+		FN_DU1_DG6, FN_LCDOUT14, FN_HRTS0_N_B,
+		FN_SCIFB2_CTS_N_B, FN_SSI_SCK9_B,
+		0, 0, 0,
+		/* IP8_8_6 [3] */
+		FN_DU1_DG5, FN_LCDOUT13, FN_VI1_DATA7_B, FN_HCTS0_N_B,
+		FN_SCIFB2_TXD_B, FN_SSI_SDATA8_B,
+		0, 0,
+		/* IP8_5_3 [3] */
+		FN_DU1_DG4, FN_LCDOUT12, FN_VI1_DATA6_B, FN_HRX0_B,
+		FN_SCIFB2_RXD_B, FN_SSI_SDATA7_B,
+		0, 0,
+		/* IP8_2_0 [3] */
+		FN_DU1_DG3, FN_LCDOUT11, FN_VI1_DATA5_B, 0, FN_SSI_WS78_B,
+		0, 0, 0, }
+	},
+	{ PINMUX_CFG_REG_VAR("IPSR9", 0xE6060044, 32,
+			     3, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 1, 1, 3, 3) {
+		/* IP9_31_29 [3] */
+		FN_VI0_G0, FN_SCL8, FN_STP_IVCXO27_0_C, FN_SCL4,
+		FN_HCTS2_N, FN_SCIFB2_CTS_N, FN_ATAWR1_N, 0,
+		/* IP9_28_27 [2] */
+		FN_VI0_DATA3_VI0_B3, FN_SCIF3_SCK_B, FN_SCIFA3_SCK_B, 0,
+		/* IP9_26_25 [2] */
+		FN_VI0_VSYNC_N, FN_RX5, FN_SCIFA5_RXD, FN_TS_SPSYNC0_D,
+		/* IP9_24_23 [2] */
+		FN_VI0_HSYNC_N, FN_TX5, FN_SCIFA5_TXD, FN_TS_SDEN0_D,
+		/* IP9_22_21 [2] */
+		FN_VI0_FIELD, FN_RX4, FN_SCIFA4_RXD, FN_TS_SCK0_D,
+		/* IP9_20_19 [2] */
+		FN_VI0_CLKENB, FN_TX4, FN_SCIFA4_TXD, FN_TS_SDATA0_D,
+		/* IP9_18_17 [2] */
+		FN_DU1_CDE, FN_QPOLB, FN_PWM4_B, 0,
+		/* IP9_16 [1] */
+		FN_DU1_DISP, FN_QPOLA,
+		/* IP9_15_13 [3] */
+		FN_DU1_EXODDF_DU1_ODDF_DISP_CDE, FN_QCPV_QDE,
+		FN_CAN0_RX, FN_RX3_B, FN_SDA2_B,
+		0, 0, 0,
+		/* IP9_12 [1] */
+		FN_DU1_EXVSYNC_DU1_VSYNC, FN_QSTB_QHE,
+		/* IP9_11 [1] */
+		FN_DU1_EXHSYNC_DU1_HSYNC, FN_QSTH_QHS,
+		/* IP9_10_8 [3] */
+		FN_DU1_DOTCLKOUT1, FN_QSTVB_QVE, FN_CAN0_TX,
+		FN_TX3_B, FN_SCL2_B, FN_PWM4,
+		0, 0,
+		/* IP9_7 [1] */
+		FN_DU1_DOTCLKOUT0, FN_QCLK,
+		/* IP9_6 [1] */
+		FN_DU1_DOTCLKIN, FN_QSTVA_QVS,
+		/* IP9_5_3 [3] */
+		FN_DU1_DB7, FN_LCDOUT23, FN_SDA3_C,
+		FN_SCIF3_SCK, FN_SCIFA3_SCK,
+		0, 0, 0,
+		/* IP9_2_0 [3] */
+		FN_DU1_DB6, FN_LCDOUT22, FN_SCL3_C, FN_RX3, FN_SCIFA3_RXD,
+		0, 0, 0, }
+	},
+	{ PINMUX_CFG_REG_VAR("IPSR10", 0xE6060048, 32,
+			     3, 2, 2, 3, 3, 2, 2, 3, 3, 3, 3, 3) {
+		/* IP10_31_29 [3] */
+		FN_VI0_R4, FN_VI2_DATA5, FN_GLO_SCLK_B, FN_TX0_C, FN_SCL1_D,
+		0, 0, 0,
+		/* IP10_28_27 [2] */
+		FN_VI0_R3, FN_VI2_DATA4, FN_GLO_Q1_B, FN_TS_SPSYNC0_C,
+		/* IP10_26_25 [2] */
+		FN_VI0_R2, FN_VI2_DATA3, FN_GLO_Q0_B, FN_TS_SDEN0_C,
+		/* IP10_24_22 [3] */
+		FN_VI0_R1, FN_VI2_DATA2, FN_GLO_I1_B, FN_TS_SCK0_C, FN_ATAG1_N,
+		0, 0, 0,
+		/* IP10_21_29 [3] */
+		FN_VI0_R0, FN_VI2_DATA1, FN_GLO_I0_B,
+		FN_TS_SDATA0_C, FN_ATACS11_N,
+		0, 0, 0,
+		/* IP10_18_17 [2] */
+		FN_VI0_G7, FN_VI2_DATA0, FN_FMIN_D, 0,
+		/* IP10_16_15 [2] */
+		FN_VI0_G6, FN_VI2_CLK, FN_BPFCLK_D, 0,
+		/* IP10_14_12 [3] */
+		FN_VI0_G5, FN_VI2_FIELD, FN_STP_OPWM_0_C, FN_FMCLK_D,
+		FN_CAN0_TX_E, FN_HTX1_D, FN_SCIFB0_TXD_D, 0,
+		/* IP10_11_9 [3] */
+		FN_VI0_G4, FN_VI2_CLKENB, FN_STP_ISSYNC_0_C,
+		FN_HTX2, FN_SCIFB2_TXD, FN_SCIFB0_SCK_D,
+		0, 0,
+		/* IP10_8_6 [3] */
+		FN_VI0_G3, FN_VI2_VSYNC_N, FN_STP_ISEN_0_C, FN_SDA3_B,
+		FN_HRX2, FN_SCIFB2_RXD, FN_ATACS01_N, 0,
+		/* IP10_5_3 [3] */
+		FN_VI0_G2, FN_VI2_HSYNC_N, FN_STP_ISD_0_C, FN_SCL3_B,
+		FN_HSCK2, FN_SCIFB2_SCK, FN_ATARD1_N, 0,
+		/* IP10_2_0 [3] */
+		FN_VI0_G1, FN_SDA8, FN_STP_ISCLK_0_C, FN_SDA4,
+		FN_HRTS2_N, FN_SCIFB2_RTS_N, FN_ATADIR1_N, 0, }
+	},
+	{ PINMUX_CFG_REG_VAR("IPSR11", 0xE606004C, 32,
+			     2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
+			     3, 3, 3, 3, 3) {
+		/* IP11_31_30 [2] */
+		FN_ETH_CRS_DV, FN_AVB_LINK, FN_SDA2_C, 0,
+		/* IP11_29_28 [2] */
+		FN_ETH_MDIO, FN_AVB_RX_CLK, FN_SCL2_C, 0,
+		/* IP11_27 [1] */
+		FN_VI1_DATA7, FN_AVB_MDC,
+		/* IP11_26 [1] */
+		FN_VI1_DATA6, FN_AVB_MAGIC,
+		/* IP11_25 [1] */
+		FN_VI1_DATA5, FN_AVB_RX_DV,
+		/* IP11_24 [1] */
+		FN_VI1_DATA4, FN_AVB_MDIO,
+		/* IP11_23 [1] */
+		FN_VI1_DATA3, FN_AVB_RX_ER,
+		/* IP11_22 [1] */
+		FN_VI1_DATA2, FN_AVB_RXD7,
+		/* IP11_21 [1] */
+		FN_VI1_DATA1, FN_AVB_RXD6,
+		/* IP11_20 [1] */
+		FN_VI1_DATA0, FN_AVB_RXD5,
+		/* IP11_19 [1] */
+		FN_VI1_CLK, FN_AVB_RXD4,
+		/* IP11_18_17 [2] */
+		FN_VI1_FIELD, FN_AVB_RXD3, FN_TS_SPSYNC0_B, 0,
+		/* IP11_16_15 [2] */
+		FN_VI1_CLKENB, FN_AVB_RXD2, FN_TS_SDEN0_B, 0,
+		/* IP11_14_12 [3] */
+		FN_VI1_VSYNC_N, FN_AVB_RXD1, FN_TS_SCK0_B,
+		FN_RX4_B, FN_SCIFA4_RXD_B,
+		0, 0, 0,
+		/* IP11_11_9 [3] */
+		FN_VI1_HSYNC_N, FN_AVB_RXD0, FN_TS_SDATA0_B,
+		FN_TX4_B, FN_SCIFA4_TXD_B,
+		0, 0, 0,
+		/* IP11_8_6 [3] */
+		FN_VI0_R7, FN_GLO_RFON_B, FN_RX1_C, FN_CAN0_RX_E,
+		FN_SDA4_B, FN_HRX1_D, FN_SCIFB0_RXD_D, 0,
+		/* IP11_5_3 [3] */
+		FN_VI0_R6, FN_VI2_DATA7, FN_GLO_SS_B, FN_TX1_C, FN_SCL4_B,
+		0, 0, 0,
+		/* IP11_2_0 [3] */
+		FN_VI0_R5, FN_VI2_DATA6, FN_GLO_SDATA_B, FN_RX0_C, FN_SDA1_D,
+		0, 0, 0, }
+	},
+	{ PINMUX_CFG_REG_VAR("IPSR12", 0xE6060050, 32,
+			     2, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2) {
+		/* IP12_31_30 [2] */
+		0, 0, 0, 0,
+		/* IP12_29_27 [3] */
+		FN_STP_ISCLK_0, FN_AVB_TX_EN, FN_SCIFB2_RXD_D,
+		FN_ADICS_SAMP_B, FN_MSIOF0_SCK_C,
+		0, 0, 0,
+		/* IP12_26_24 [3] */
+		FN_STP_IVCXO27_0, FN_AVB_TXD7, FN_SCIFB2_TXD_D,
+		FN_ADIDATA_B, FN_MSIOF0_SYNC_C,
+		0, 0, 0,
+		/* IP12_23_22 [2] */
+		FN_ETH_MDC, FN_AVB_TXD6, FN_IERX_C, 0,
+		/* IP12_21_20 [2] */
+		FN_ETH_TXD0, FN_AVB_TXD5, FN_IECLK_C, 0,
+		/* IP12_19_18 [2] */
+		FN_ETH_MAGIC, FN_AVB_TXD4, FN_IETX_C, 0,
+		/* IP12_17_16 [2] */
+		FN_ETH_TX_EN, FN_AVB_TXD3, FN_TCLK1_B, FN_CAN_CLK_B,
+		/* IP12_15_13 [3] */
+		FN_ETH_TXD1, FN_AVB_TXD2, FN_SCIFA3_TXD_B,
+		FN_CAN1_TX_C, FN_MSIOF1_TXD_E,
+		0, 0, 0,
+		/* IP12_12_10 [3] */
+		FN_ETH_REFCLK, FN_AVB_TXD1, FN_SCIFA3_RXD_B,
+		FN_CAN1_RX_C, FN_MSIOF1_SYNC_E,
+		0, 0, 0,
+		/* IP12_9_7 [3] */
+		FN_ETH_LINK, FN_AVB_TXD0, FN_CAN0_RX_C,
+		FN_SDA2_D, FN_MSIOF1_SCK_E,
+		0, 0, 0,
+		/* IP12_6_4 [3] */
+		FN_ETH_RXD1, FN_AVB_GTXREFCLK, FN_CAN0_TX_C,
+		FN_SCL2_D, FN_MSIOF1_RXD_E,
+		0, 0, 0,
+		/* IP12_3_2 [2] */
+		FN_ETH_RXD0, FN_AVB_PHY_INT, FN_SDA3, FN_SDA7,
+		/* IP12_1_0 [2] */
+		FN_ETH_RX_ER, FN_AVB_CRS, FN_SCL3, FN_SCL7, }
+	},
+	{ PINMUX_CFG_REG_VAR("IPSR13", 0xE6060054, 32,
+			     1, 3, 1, 1, 1, 2, 1, 3, 3, 1, 1, 1, 1, 1, 1,
+			     3, 2, 2, 3) {
+		/* IP13_31 [1] */
+		0, 0,
+		/* IP13_30_28 [3] */
+		FN_SD1_CD, FN_PWM0, FN_TPU_TO0, FN_SCL1_C,
+		0, 0, 0, 0,
+		/* IP13_27 [1] */
+		FN_SD1_DATA3, FN_IERX_B,
+		/* IP13_26 [1] */
+		FN_SD1_DATA2, FN_IECLK_B,
+		/* IP13_25 [1] */
+		FN_SD1_DATA1, FN_IETX_B,
+		/* IP13_24_23 [2] */
+		FN_SD1_DATA0, FN_SPEEDIN_B, 0, 0,
+		/* IP13_22 [1] */
+		FN_SD1_CMD, FN_REMOCON_B,
+		/* IP13_21_19 [3] */
+		FN_SD0_WP, FN_MMC_D7_B, FN_SIM0_D_B, FN_CAN0_TX_F,
+		FN_SCIFA5_RXD_B, FN_RX3_C,
+		0, 0,
+		/* IP13_18_16 [3] */
+		FN_SD0_CD, FN_MMC_D6_B, FN_SIM0_RST_B, FN_CAN0_RX_F,
+		FN_SCIFA5_TXD_B, FN_TX3_C,
+		0, 0,
+		/* IP13_15 [1] */
+		FN_SD0_DATA3, FN_SSL_B,
+		/* IP13_14 [1] */
+		FN_SD0_DATA2, FN_IO3_B,
+		/* IP13_13 [1] */
+		FN_SD0_DATA1, FN_IO2_B,
+		/* IP13_12 [1] */
+		FN_SD0_DATA0, FN_MISO_IO1_B,
+		/* IP13_11 [1] */
+		FN_SD0_CMD, FN_MOSI_IO0_B,
+		/* IP13_10 [1] */
+		FN_SD0_CLK, FN_SPCLK_B,
+		/* IP13_9_7 [3] */
+		FN_STP_OPWM_0, FN_AVB_GTX_CLK, FN_PWM0_B,
+		FN_ADICHS2_B, FN_MSIOF0_TXD_C,
+		0, 0, 0,
+		/* IP13_6_5 [2] */
+		FN_STP_ISSYNC_0, FN_AVB_COL, FN_ADICHS1_B, FN_MSIOF0_RXD_C,
+		/* IP13_4_3 [2] */
+		FN_STP_ISEN_0, FN_AVB_TX_CLK, FN_ADICHS0_B, FN_MSIOF0_SS2_C,
+		/* IP13_2_0 [3] */
+		FN_STP_ISD_0, FN_AVB_TX_ER, FN_SCIFB2_SCK_C,
+		FN_ADICLK_B, FN_MSIOF0_SS1_C,
+		0, 0, 0, }
+	},
+	{ PINMUX_CFG_REG_VAR("IPSR14", 0xE6060058, 32,
+			     3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 2) {
+		/* IP14_31_29 [3] */
+		FN_MSIOF0_SS2, FN_MMC_D7, FN_ADICHS2, FN_RX0_E,
+		FN_VI1_VSYNC_N_C, FN_SDA7_C, FN_VI1_G5_B, 0,
+		/* IP14_28_26 [3] */
+		FN_MSIOF0_SS1, FN_MMC_D6, FN_ADICHS1, FN_TX0_E,
+		FN_VI1_HSYNC_N_C, FN_SCL7_C, FN_VI1_G4_B, 0,
+		/* IP14_25_23 [3] */
+		FN_MSIOF0_RXD, FN_ADICHS0, 0, FN_VI1_DATA0_C, FN_VI1_G3_B,
+		0, 0, 0,
+		/* IP14_22_20 [3] */
+		FN_MSIOF0_TXD, FN_ADICLK, 0, FN_VI1_FIELD_C, FN_VI1_G2_B,
+		0, 0, 0,
+		/* IP14_19_17 [3] */
+		FN_MSIOF0_SYNC, FN_TX2_C, FN_ADICS_SAMP, 0,
+		FN_VI1_CLKENB_C, FN_VI1_G1_B,
+		0, 0,
+		/* IP14_16_14 [3] */
+		FN_MSIOF0_SCK, FN_RX2_C, FN_ADIDATA, 0,
+		FN_VI1_CLK_C, FN_VI1_G0_B,
+		0, 0,
+		/* IP14_13_11 [3] */
+		FN_SD2_WP, FN_MMC_D5, FN_SDA8_C, FN_RX5_B, FN_SCIFA5_RXD_C,
+		0, 0, 0,
+		/* IP14_10_8 [3] */
+		FN_SD2_CD, FN_MMC_D4, FN_SCL8_C, FN_TX5_B, FN_SCIFA5_TXD_C,
+		0, 0, 0,
+		/* IP14_7 [1] */
+		FN_SD2_DATA3, FN_MMC_D3,
+		/* IP14_6 [1] */
+		FN_SD2_DATA2, FN_MMC_D2,
+		/* IP14_5 [1] */
+		FN_SD2_DATA1, FN_MMC_D1,
+		/* IP14_4 [1] */
+		FN_SD2_DATA0, FN_MMC_D0,
+		/* IP14_3 [1] */
+		FN_SD2_CMD, FN_MMC_CMD,
+		/* IP14_2 [1] */
+		FN_SD2_CLK, FN_MMC_CLK,
+		/* IP14_1_0 [2] */
+		FN_SD1_WP, FN_PWM1_B, FN_SDA1_C, 0, }
+	},
+	{ PINMUX_CFG_REG_VAR("IPSR15", 0xE606005C, 32,
+			     2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2) {
+		/* IP15_31_30 [2] */
+		0, 0, 0, 0,
+		/* IP15_29_27 [3] */
+		FN_HTX0, FN_SCIFB0_TXD, 0, FN_GLO_SCLK_C,
+		FN_CAN0_TX_B, FN_VI1_DATA5_C,
+		0, 0,
+		/* IP15_26_24 [3] */
+		FN_HRX0, FN_SCIFB0_RXD, 0, FN_GLO_Q1_C,
+		FN_CAN0_RX_B, FN_VI1_DATA4_C,
+		0, 0,
+		/* IP15_23_21 [3] */
+		FN_HSCK0, FN_SCIFB0_SCK, 0, FN_GLO_Q0_C, FN_CAN_CLK,
+		FN_TCLK2, FN_VI1_DATA3_C, 0,
+		/* IP15_20_18 [3] */
+		FN_HRTS0_N, FN_SCIFB0_RTS_N, 0, FN_GLO_I1_C, FN_VI1_DATA2_C,
+		0, 0, 0,
+		/* IP15_17_15 [3] */
+		FN_HCTS0_N, FN_SCIFB0_CTS_N, 0, FN_GLO_I0_C,
+		FN_TCLK1, FN_VI1_DATA1_C,
+		0, 0,
+		/* IP15_14_12 [3] */
+		FN_GPS_MAG, FN_RX4_C, FN_SCIFA4_RXD_C, FN_PWM6,
+		FN_VI1_G7_B, FN_SCIFA3_SCK_C,
+		0, 0,
+		/* IP15_11_9 [3] */
+		FN_GPS_SIGN, FN_TX4_C, FN_SCIFA4_TXD_C, FN_PWM5,
+		FN_VI1_G6_B, FN_SCIFA3_RXD_C,
+		0, 0,
+		/* IP15_8_6 [3] */
+		FN_GPS_CLK, FN_DU1_DOTCLKIN_C, FN_AUDIO_CLKB_B,
+		FN_PWM5_B, FN_SCIFA3_TXD_C,
+		0, 0, 0,
+		/* IP15_5_4 [2] */
+		FN_SIM0_D, FN_IERX, FN_CAN1_RX_D, 0,
+		/* IP15_3_2 [2] */
+		FN_SIM0_CLK, FN_IECLK, FN_CAN_CLK_C, 0,
+		/* IP15_1_0 [2] */
+		FN_SIM0_RST, FN_IETX, FN_CAN1_TX_D, 0, }
+	},
+	{ PINMUX_CFG_REG_VAR("IPSR16", 0xE6060160, 32,
+			     4, 4, 4, 4, 4, 2, 2, 2, 3, 3) {
+		/* IP16_31_28 [4] */
+		0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0,
+		/* IP16_27_24 [4] */
+		0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0,
+		/* IP16_23_20 [4] */
+		0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0,
+		/* IP16_19_16 [4] */
+		0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0,
+		/* IP16_15_12 [4] */
+		0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0,
+		/* IP16_11_10 [2] */
+		FN_HRTS1_N, FN_SCIFB1_RTS_N, FN_MLB_DAT, FN_CAN1_RX_B,
+		/* IP16_9_8 [2] */
+		FN_HCTS1_N, FN_SCIFB1_CTS_N, FN_MLB_SIG, FN_CAN1_TX_B,
+		/* IP16_7_6 [2] */
+		FN_HSCK1, FN_SCIFB1_SCK, FN_MLB_CK, FN_GLO_RFON_C,
+		/* IP16_5_3 [3] */
+		FN_HTX1, FN_SCIFB1_TXD, FN_VI1_R1_B,
+		FN_GLO_SS_C, FN_VI1_DATA7_C,
+		0, 0, 0,
+		/* IP16_2_0 [3] */
+		FN_HRX1, FN_SCIFB1_RXD, FN_VI1_R0_B,
+		FN_GLO_SDATA_C, FN_VI1_DATA6_C,
+		0, 0, 0, }
+	},
+	{ PINMUX_CFG_REG_VAR("MOD_SEL", 0xE6060090, 32,
+			     1, 2, 2, 2, 3, 2, 1, 1, 1, 1,
+			     3, 2, 2, 2, 1, 2, 2, 2) {
+		/* RESEVED [1] */
+		0, 0,
+		/* SEL_SCIF1 [2] */
+		FN_SEL_SCIF1_0, FN_SEL_SCIF1_1, FN_SEL_SCIF1_2, FN_SEL_SCIF1_3,
+		/* SEL_SCIFB [2] */
+		FN_SEL_SCIFB_0, FN_SEL_SCIFB_1, FN_SEL_SCIFB_2, FN_SEL_SCIFB_3,
+		/* SEL_SCIFB2 [2] */
+		FN_SEL_SCIFB2_0, FN_SEL_SCIFB2_1,
+		FN_SEL_SCIFB2_2, FN_SEL_SCIFB2_3,
+		/* SEL_SCIFB1 [3] */
+		FN_SEL_SCIFB1_0, FN_SEL_SCIFB1_1,
+		FN_SEL_SCIFB1_2, FN_SEL_SCIFB1_3,
+		0, 0, 0, 0,
+		/* SEL_SCIFA1 [2] */
+		FN_SEL_SCIFA1_0, FN_SEL_SCIFA1_1, FN_SEL_SCIFA1_2, 0,
+		/* SEL_SSI9 [1] */
+		FN_SEL_SSI9_0, FN_SEL_SSI9_1,
+		/* SEL_SCFA [1] */
+		FN_SEL_SCFA_0, FN_SEL_SCFA_1,
+		/* SEL_QSP [1] */
+		FN_SEL_QSP_0, FN_SEL_QSP_1,
+		/* SEL_SSI7 [1] */
+		FN_SEL_SSI7_0, FN_SEL_SSI7_1,
+		/* SEL_HSCIF1 [3] */
+		FN_SEL_HSCIF1_0, FN_SEL_HSCIF1_1, FN_SEL_HSCIF1_2,
+		FN_SEL_HSCIF1_3, FN_SEL_HSCIF1_4,
+		0, 0, 0,
+		/* RESEVED [2] */
+		0, 0, 0, 0,
+		/* SEL_VI1 [2] */
+		FN_SEL_VI1_0, FN_SEL_VI1_1, FN_SEL_VI1_2, 0,
+		/* RESEVED [2] */
+		0, 0, 0, 0,
+		/* SEL_TMU [1] */
+		FN_SEL_TMU1_0, FN_SEL_TMU1_1,
+		/* SEL_LBS [2] */
+		FN_SEL_LBS_0, FN_SEL_LBS_1, FN_SEL_LBS_2, FN_SEL_LBS_3,
+		/* SEL_TSIF0 [2] */
+		FN_SEL_TSIF0_0, FN_SEL_TSIF0_1, FN_SEL_TSIF0_2, FN_SEL_TSIF0_3,
+		/* SEL_SOF0 [2] */
+		FN_SEL_SOF0_0, FN_SEL_SOF0_1, FN_SEL_SOF0_2, 0, }
+	},
+	{ PINMUX_CFG_REG_VAR("MOD_SEL2", 0xE6060094, 32,
+			     3, 1, 1, 3, 2, 1, 1, 2, 2,
+			     1, 3, 2, 1, 2, 2, 2, 1, 1, 1) {
+		/* SEL_SCIF0 [3] */
+		FN_SEL_SCIF0_0, FN_SEL_SCIF0_1, FN_SEL_SCIF0_2,
+		FN_SEL_SCIF0_3, FN_SEL_SCIF0_4,
+		0, 0, 0,
+		/* RESEVED [1] */
+		0, 0,
+		/* SEL_SCIF [1] */
+		FN_SEL_SCIF_0, FN_SEL_SCIF_1,
+		/* SEL_CAN0 [3] */
+		FN_SEL_CAN0_0, FN_SEL_CAN0_1, FN_SEL_CAN0_2, FN_SEL_CAN0_3,
+		FN_SEL_CAN0_4, FN_SEL_CAN0_5,
+		0, 0,
+		/* SEL_CAN1 [2] */
+		FN_SEL_CAN1_0, FN_SEL_CAN1_1, FN_SEL_CAN1_2, FN_SEL_CAN1_3,
+		/* RESEVED [1] */
+		0, 0,
+		/* SEL_SCIFA2 [1] */
+		FN_SEL_SCIFA2_0, FN_SEL_SCIFA2_1,
+		/* SEL_SCIF4 [2] */
+		FN_SEL_SCIF4_0, FN_SEL_SCIF4_1, FN_SEL_SCIF4_2, 0,
+		/* RESEVED [2] */
+		0, 0, 0, 0,
+		/* SEL_ADG [1] */
+		FN_SEL_ADG_0, FN_SEL_ADG_1,
+		/* SEL_FM [3] */
+		FN_SEL_FM_0, FN_SEL_FM_1, FN_SEL_FM_2,
+		FN_SEL_FM_3, FN_SEL_FM_4,
+		0, 0, 0,
+		/* SEL_SCIFA5 [2] */
+		FN_SEL_SCIFA5_0, FN_SEL_SCIFA5_1, FN_SEL_SCIFA5_2, 0,
+		/* RESEVED [1] */
+		0, 0,
+		/* SEL_GPS [2] */
+		FN_SEL_GPS_0, FN_SEL_GPS_1, FN_SEL_GPS_2, FN_SEL_GPS_3,
+		/* SEL_SCIFA4 [2] */
+		FN_SEL_SCIFA4_0, FN_SEL_SCIFA4_1, FN_SEL_SCIFA4_2, 0,
+		/* SEL_SCIFA3 [2] */
+		FN_SEL_SCIFA3_0, FN_SEL_SCIFA3_1, FN_SEL_SCIFA3_2, 0,
+		/* SEL_SIM [1] */
+		FN_SEL_SIM_0, FN_SEL_SIM_1,
+		/* RESEVED [1] */
+		0, 0,
+		/* SEL_SSI8 [1] */
+		FN_SEL_SSI8_0, FN_SEL_SSI8_1, }
+	},
+	{ PINMUX_CFG_REG_VAR("MOD_SEL3", 0xE6060098, 32,
+			     2, 2, 2, 2, 2, 2, 2, 2,
+			     1, 1, 2, 2, 3, 2, 2, 2, 1) {
+		/* SEL_HSCIF2 [2] */
+		FN_SEL_HSCIF2_0, FN_SEL_HSCIF2_1,
+		FN_SEL_HSCIF2_2, FN_SEL_HSCIF2_3,
+		/* SEL_CANCLK [2] */
+		FN_SEL_CANCLK_0, FN_SEL_CANCLK_1,
+		FN_SEL_CANCLK_2, FN_SEL_CANCLK_3,
+		/* SEL_IIC8 [2] */
+		FN_SEL_IIC8_0, FN_SEL_IIC8_1, FN_SEL_IIC8_2, 0,
+		/* SEL_IIC7 [2] */
+		FN_SEL_IIC7_0, FN_SEL_IIC7_1, FN_SEL_IIC7_2, 0,
+		/* SEL_IIC4 [2] */
+		FN_SEL_IIC4_0, FN_SEL_IIC4_1, FN_SEL_IIC4_2, 0,
+		/* SEL_IIC3 [2] */
+		FN_SEL_IIC3_0, FN_SEL_IIC3_1, FN_SEL_IIC3_2, FN_SEL_IIC3_3,
+		/* SEL_SCIF3 [2] */
+		FN_SEL_SCIF3_0, FN_SEL_SCIF3_1, FN_SEL_SCIF3_2, FN_SEL_SCIF3_3,
+		/* SEL_IEB [2] */
+		FN_SEL_IEB_0, FN_SEL_IEB_1, FN_SEL_IEB_2,
+		/* SEL_MMC [1] */
+		FN_SEL_MMC_0, FN_SEL_MMC_1,
+		/* SEL_SCIF5 [1] */
+		FN_SEL_SCIF5_0, FN_SEL_SCIF5_1,
+		/* RESEVED [2] */
+		0, 0, 0, 0,
+		/* SEL_IIC2 [2] */
+		FN_SEL_IIC2_0, FN_SEL_IIC2_1, FN_SEL_IIC2_2, FN_SEL_IIC2_3,
+		/* SEL_IIC1 [3] */
+		FN_SEL_IIC1_0, FN_SEL_IIC1_1, FN_SEL_IIC1_2, FN_SEL_IIC1_3,
+		FN_SEL_IIC1_4,
+		0, 0, 0,
+		/* SEL_IIC0 [2] */
+		FN_SEL_IIC0_0, FN_SEL_IIC0_1, FN_SEL_IIC0_2, 0,
+		/* RESEVED [2] */
+		0, 0, 0, 0,
+		/* RESEVED [2] */
+		0, 0, 0, 0,
+		/* RESEVED [1] */
+		0, 0, }
+	},
+	{ PINMUX_CFG_REG_VAR("MOD_SEL4", 0xE606009C, 32,
+			     3, 2, 2, 1, 1, 1, 1, 3, 2,
+			     2, 3, 1, 1, 1, 2, 2, 2, 2) {
+		/* SEL_SOF1 [3] */
+		FN_SEL_SOF1_0, FN_SEL_SOF1_1, FN_SEL_SOF1_2, FN_SEL_SOF1_3,
+		FN_SEL_SOF1_4,
+		0, 0, 0,
+		/* SEL_HSCIF0 [2] */
+		FN_SEL_HSCIF0_0, FN_SEL_HSCIF0_1, FN_SEL_HSCIF0_2, 0,
+		/* SEL_DIS [2] */
+		FN_SEL_DIS_0, FN_SEL_DIS_1, FN_SEL_DIS_2, 0,
+		/* RESEVED [1] */
+		0, 0,
+		/* SEL_RAD [1] */
+		FN_SEL_RAD_0, FN_SEL_RAD_1,
+		/* SEL_RCN [1] */
+		FN_SEL_RCN_0, FN_SEL_RCN_1,
+		/* SEL_RSP [1] */
+		FN_SEL_RSP_0, FN_SEL_RSP_1,
+		/* SEL_SCIF2 [3] */
+		FN_SEL_SCIF2_0, FN_SEL_SCIF2_1, FN_SEL_SCIF2_2,
+		FN_SEL_SCIF2_3, FN_SEL_SCIF2_4,
+		0, 0, 0,
+		/* RESEVED [2] */
+		0, 0, 0, 0,
+		/* RESEVED [2] */
+		0, 0, 0, 0,
+		/* SEL_SOF2 [3] */
+		FN_SEL_SOF2_0, FN_SEL_SOF2_1, FN_SEL_SOF2_2,
+		FN_SEL_SOF2_3, FN_SEL_SOF2_4,
+		0, 0, 0,
+		/* RESEVED [1] */
+		0, 0,
+		/* SEL_SSI1 [1] */
+		FN_SEL_SSI1_0, FN_SEL_SSI1_1,
+		/* SEL_SSI0 [1] */
+		FN_SEL_SSI0_0, FN_SEL_SSI0_1,
+		/* SEL_SSP [2] */
+		FN_SEL_SSP_0, FN_SEL_SSP_1, FN_SEL_SSP_2, 0,
+		/* RESEVED [2] */
+		0, 0, 0, 0,
+		/* RESEVED [2] */
+		0, 0, 0, 0,
+		/* RESEVED [2] */
+		0, 0, 0, 0, }
+	},
+	{ },
+};
+
+const struct sh_pfc_soc_info r8a7791_pinmux_info = {
+	.name = "r8a77910_pfc",
+	.unlock_reg = 0xe6060000, /* PMMR */
+
+	.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
+
+	.pins = pinmux_pins,
+	.nr_pins = ARRAY_SIZE(pinmux_pins),
+	.groups = pinmux_groups,
+	.nr_groups = ARRAY_SIZE(pinmux_groups),
+	.functions = pinmux_functions,
+	.nr_functions = ARRAY_SIZE(pinmux_functions),
+
+	.cfg_regs = pinmux_config_regs,
+
+	.gpio_data = pinmux_data,
+	.gpio_data_size = ARRAY_SIZE(pinmux_data),
+};
diff --git a/drivers/pinctrl/sirf/pinctrl-atlas6.c b/drivers/pinctrl/sirf/pinctrl-atlas6.c
index edf45a6..8ab7898 100644
--- a/drivers/pinctrl/sirf/pinctrl-atlas6.c
+++ b/drivers/pinctrl/sirf/pinctrl-atlas6.c
@@ -122,6 +122,9 @@
 	PINCTRL_PIN(100, "ac97_dout"),
 	PINCTRL_PIN(101, "ac97_din"),
 	PINCTRL_PIN(102, "x_rtc_io"),
+
+	PINCTRL_PIN(103, "x_usb1_dp"),
+	PINCTRL_PIN(104, "x_usb1_dn"),
 };
 
 static const struct sirfsoc_muxmask lcd_16bits_sirfsoc_muxmask[] = {
@@ -139,6 +142,7 @@
 static const struct sirfsoc_padmux lcd_16bits_padmux = {
 	.muxmask_counts = ARRAY_SIZE(lcd_16bits_sirfsoc_muxmask),
 	.muxmask = lcd_16bits_sirfsoc_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(4),
 	.funcval = 0,
 };
@@ -164,6 +168,7 @@
 static const struct sirfsoc_padmux lcd_18bits_padmux = {
 	.muxmask_counts = ARRAY_SIZE(lcd_18bits_muxmask),
 	.muxmask = lcd_18bits_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(4) | BIT(15),
 	.funcval = 0,
 };
@@ -189,6 +194,7 @@
 static const struct sirfsoc_padmux lcd_24bits_padmux = {
 	.muxmask_counts = ARRAY_SIZE(lcd_24bits_muxmask),
 	.muxmask = lcd_24bits_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(4) | BIT(15),
 	.funcval = 0,
 };
@@ -214,6 +220,7 @@
 static const struct sirfsoc_padmux lcdrom_padmux = {
 	.muxmask_counts = ARRAY_SIZE(lcdrom_muxmask),
 	.muxmask = lcdrom_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(4),
 	.funcval = BIT(4),
 };
@@ -237,6 +244,7 @@
 static const struct sirfsoc_padmux uart0_padmux = {
 	.muxmask_counts = ARRAY_SIZE(uart0_muxmask),
 	.muxmask = uart0_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(9),
 	.funcval = BIT(9),
 };
@@ -284,6 +292,7 @@
 static const struct sirfsoc_padmux uart2_padmux = {
 	.muxmask_counts = ARRAY_SIZE(uart2_muxmask),
 	.muxmask = uart2_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(10),
 	.funcval = BIT(10),
 };
@@ -317,6 +326,7 @@
 static const struct sirfsoc_padmux sdmmc3_padmux = {
 	.muxmask_counts = ARRAY_SIZE(sdmmc3_muxmask),
 	.muxmask = sdmmc3_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(7),
 	.funcval = 0,
 };
@@ -336,6 +346,7 @@
 static const struct sirfsoc_padmux spi0_padmux = {
 	.muxmask_counts = ARRAY_SIZE(spi0_muxmask),
 	.muxmask = spi0_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(7),
 	.funcval = BIT(7),
 };
@@ -352,6 +363,7 @@
 static const struct sirfsoc_padmux cko1_padmux = {
 	.muxmask_counts = ARRAY_SIZE(cko1_muxmask),
 	.muxmask = cko1_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(3),
 	.funcval = 0,
 };
@@ -371,6 +383,7 @@
 static const struct sirfsoc_padmux i2s_padmux = {
 	.muxmask_counts = ARRAY_SIZE(i2s_muxmask),
 	.muxmask = i2s_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(3),
 	.funcval = BIT(3),
 };
@@ -390,6 +403,7 @@
 static const struct sirfsoc_padmux i2s_no_din_padmux = {
 	.muxmask_counts = ARRAY_SIZE(i2s_no_din_muxmask),
 	.muxmask = i2s_no_din_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(3),
 	.funcval = BIT(3),
 };
@@ -409,6 +423,7 @@
 static const struct sirfsoc_padmux i2s_6chn_padmux = {
 	.muxmask_counts = ARRAY_SIZE(i2s_6chn_muxmask),
 	.muxmask = i2s_6chn_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(1) | BIT(3) | BIT(9),
 	.funcval = BIT(1) | BIT(3) | BIT(9),
 };
@@ -439,6 +454,7 @@
 static const struct sirfsoc_padmux spi1_padmux = {
 	.muxmask_counts = ARRAY_SIZE(spi1_muxmask),
 	.muxmask = spi1_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(16),
 	.funcval = 0,
 };
@@ -455,6 +471,7 @@
 static const struct sirfsoc_padmux sdmmc1_padmux = {
 	.muxmask_counts = ARRAY_SIZE(sdmmc1_muxmask),
 	.muxmask = sdmmc1_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(5),
 	.funcval = BIT(5),
 };
@@ -471,6 +488,7 @@
 static const struct sirfsoc_padmux gps_padmux = {
 	.muxmask_counts = ARRAY_SIZE(gps_muxmask),
 	.muxmask = gps_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(13),
 	.funcval = 0,
 };
@@ -487,6 +505,7 @@
 static const struct sirfsoc_padmux sdmmc5_padmux = {
 	.muxmask_counts = ARRAY_SIZE(sdmmc5_muxmask),
 	.muxmask = sdmmc5_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(13),
 	.funcval = BIT(13),
 };
@@ -503,6 +522,7 @@
 static const struct sirfsoc_padmux usp0_padmux = {
 	.muxmask_counts = ARRAY_SIZE(usp0_muxmask),
 	.muxmask = usp0_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(1) | BIT(2) | BIT(9),
 	.funcval = 0,
 };
@@ -535,6 +555,7 @@
 static const struct sirfsoc_padmux usp1_padmux = {
 	.muxmask_counts = ARRAY_SIZE(usp1_muxmask),
 	.muxmask = usp1_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(16),
 	.funcval = BIT(16),
 };
@@ -554,6 +575,7 @@
 static const struct sirfsoc_padmux nand_padmux = {
 	.muxmask_counts = ARRAY_SIZE(nand_muxmask),
 	.muxmask = nand_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(5) | BIT(19),
 	.funcval = 0,
 };
@@ -570,6 +592,7 @@
 static const struct sirfsoc_padmux sdmmc0_padmux = {
 	.muxmask_counts = ARRAY_SIZE(sdmmc0_muxmask),
 	.muxmask = sdmmc0_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(5) | BIT(19),
 	.funcval = BIT(19),
 };
@@ -586,6 +609,7 @@
 static const struct sirfsoc_padmux sdmmc2_padmux = {
 	.muxmask_counts = ARRAY_SIZE(sdmmc2_muxmask),
 	.muxmask = sdmmc2_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(11),
 	.funcval = 0,
 };
@@ -602,6 +626,7 @@
 static const struct sirfsoc_padmux sdmmc2_nowp_padmux = {
 	.muxmask_counts = ARRAY_SIZE(sdmmc2_nowp_muxmask),
 	.muxmask = sdmmc2_nowp_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(11),
 	.funcval = 0,
 };
@@ -634,6 +659,7 @@
 static const struct sirfsoc_padmux vip_padmux = {
 	.muxmask_counts = ARRAY_SIZE(vip_muxmask),
 	.muxmask = vip_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(18),
 	.funcval = BIT(18),
 };
@@ -654,6 +680,7 @@
 static const struct sirfsoc_padmux vip_noupli_padmux = {
 	.muxmask_counts = ARRAY_SIZE(vip_noupli_muxmask),
 	.muxmask = vip_noupli_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(15),
 	.funcval = BIT(15),
 };
@@ -684,6 +711,7 @@
 static const struct sirfsoc_padmux i2c1_padmux = {
 	.muxmask_counts = ARRAY_SIZE(i2c1_muxmask),
 	.muxmask = i2c1_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(16),
 	.funcval = 0,
 };
@@ -700,6 +728,7 @@
 static const struct sirfsoc_padmux pwm0_padmux = {
 	.muxmask_counts = ARRAY_SIZE(pwm0_muxmask),
 	.muxmask = pwm0_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(12),
 	.funcval = 0,
 };
@@ -772,6 +801,7 @@
 static const struct sirfsoc_padmux warm_rst_padmux = {
 	.muxmask_counts = ARRAY_SIZE(warm_rst_muxmask),
 	.muxmask = warm_rst_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(4),
 	.funcval = 0,
 };
@@ -789,6 +819,7 @@
 static const struct sirfsoc_padmux usb0_upli_drvbus_padmux = {
 	.muxmask_counts = ARRAY_SIZE(usb0_upli_drvbus_muxmask),
 	.muxmask = usb0_upli_drvbus_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(18),
 	.funcval = 0,
 };
@@ -805,12 +836,31 @@
 static const struct sirfsoc_padmux usb1_utmi_drvbus_padmux = {
 	.muxmask_counts = ARRAY_SIZE(usb1_utmi_drvbus_muxmask),
 	.muxmask = usb1_utmi_drvbus_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(11),
 	.funcval = BIT(11), /* refer to PAD_UTMI_DRVVBUS1_ENABLE */
 };
 
 static const unsigned usb1_utmi_drvbus_pins[] = { 28 };
 
+static const struct sirfsoc_padmux usb1_dp_dn_padmux = {
+	.muxmask_counts = 0,
+	.ctrlreg = SIRFSOC_RSC_USB_UART_SHARE,
+	.funcmask = BIT(2),
+	.funcval = BIT(2),
+};
+
+static const unsigned usb1_dp_dn_pins[] = { 103, 104 };
+
+static const struct sirfsoc_padmux uart1_route_io_usb1_padmux = {
+	.muxmask_counts = 0,
+	.ctrlreg = SIRFSOC_RSC_USB_UART_SHARE,
+	.funcmask = BIT(2),
+	.funcval = 0,
+};
+
+static const unsigned uart1_route_io_usb1_pins[] = { 103, 104 };
+
 static const struct sirfsoc_muxmask pulse_count_muxmask[] = {
 	{
 		.group = 0,
@@ -859,6 +909,8 @@
 	SIRFSOC_PIN_GROUP("sdmmc5grp", sdmmc5_pins),
 	SIRFSOC_PIN_GROUP("usb0_upli_drvbusgrp", usb0_upli_drvbus_pins),
 	SIRFSOC_PIN_GROUP("usb1_utmi_drvbusgrp", usb1_utmi_drvbus_pins),
+	SIRFSOC_PIN_GROUP("usb1_dp_dngrp", usb1_dp_dn_pins),
+	SIRFSOC_PIN_GROUP("uart1_route_io_usb1grp", uart1_route_io_usb1_pins),
 	SIRFSOC_PIN_GROUP("pulse_countgrp", pulse_count_pins),
 	SIRFSOC_PIN_GROUP("i2sgrp", i2s_pins),
 	SIRFSOC_PIN_GROUP("i2s_no_dingrp", i2s_no_din_pins),
@@ -903,6 +955,8 @@
 static const char * const sdmmc2_nowpgrp[] = { "sdmmc2_nowpgrp" };
 static const char * const usb0_upli_drvbusgrp[] = { "usb0_upli_drvbusgrp" };
 static const char * const usb1_utmi_drvbusgrp[] = { "usb1_utmi_drvbusgrp" };
+static const char * const usb1_dp_dngrp[] = { "usb1_dp_dngrp" };
+static const char * const uart1_route_io_usb1grp[] = { "uart1_route_io_usb1grp" };
 static const char * const pulse_countgrp[] = { "pulse_countgrp" };
 static const char * const i2sgrp[] = { "i2sgrp" };
 static const char * const i2s_no_dingrp[] = { "i2s_no_dingrp" };
@@ -949,6 +1003,8 @@
 	SIRFSOC_PMX_FUNCTION("sdmmc2_nowp", sdmmc2_nowpgrp, sdmmc2_nowp_padmux),
 	SIRFSOC_PMX_FUNCTION("usb0_upli_drvbus", usb0_upli_drvbusgrp, usb0_upli_drvbus_padmux),
 	SIRFSOC_PMX_FUNCTION("usb1_utmi_drvbus", usb1_utmi_drvbusgrp, usb1_utmi_drvbus_padmux),
+	SIRFSOC_PMX_FUNCTION("usb1_dp_dn", usb1_dp_dngrp, usb1_dp_dn_padmux),
+	SIRFSOC_PMX_FUNCTION("uart1_route_io_usb1", uart1_route_io_usb1grp, uart1_route_io_usb1_padmux),
 	SIRFSOC_PMX_FUNCTION("pulse_count", pulse_countgrp, pulse_count_padmux),
 	SIRFSOC_PMX_FUNCTION("i2s", i2sgrp, i2s_padmux),
 	SIRFSOC_PMX_FUNCTION("i2s_no_din", i2s_no_dingrp, i2s_no_din_padmux),
diff --git a/drivers/pinctrl/sirf/pinctrl-prima2.c b/drivers/pinctrl/sirf/pinctrl-prima2.c
index 1f0ad1e..050777b 100644
--- a/drivers/pinctrl/sirf/pinctrl-prima2.c
+++ b/drivers/pinctrl/sirf/pinctrl-prima2.c
@@ -126,6 +126,9 @@
 	PINCTRL_PIN(112, "x_ldd[13]"),
 	PINCTRL_PIN(113, "x_ldd[14]"),
 	PINCTRL_PIN(114, "x_ldd[15]"),
+
+	PINCTRL_PIN(115, "x_usb1_dp"),
+	PINCTRL_PIN(116, "x_usb1_dn"),
 };
 
 static const struct sirfsoc_muxmask lcd_16bits_sirfsoc_muxmask[] = {
@@ -143,6 +146,7 @@
 static const struct sirfsoc_padmux lcd_16bits_padmux = {
 	.muxmask_counts = ARRAY_SIZE(lcd_16bits_sirfsoc_muxmask),
 	.muxmask = lcd_16bits_sirfsoc_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(4),
 	.funcval = 0,
 };
@@ -168,6 +172,7 @@
 static const struct sirfsoc_padmux lcd_18bits_padmux = {
 	.muxmask_counts = ARRAY_SIZE(lcd_18bits_muxmask),
 	.muxmask = lcd_18bits_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(4),
 	.funcval = 0,
 };
@@ -193,6 +198,7 @@
 static const struct sirfsoc_padmux lcd_24bits_padmux = {
 	.muxmask_counts = ARRAY_SIZE(lcd_24bits_muxmask),
 	.muxmask = lcd_24bits_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(4),
 	.funcval = 0,
 };
@@ -218,6 +224,7 @@
 static const struct sirfsoc_padmux lcdrom_padmux = {
 	.muxmask_counts = ARRAY_SIZE(lcdrom_muxmask),
 	.muxmask = lcdrom_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(4),
 	.funcval = BIT(4),
 };
@@ -238,6 +245,7 @@
 static const struct sirfsoc_padmux uart0_padmux = {
 	.muxmask_counts = ARRAY_SIZE(uart0_muxmask),
 	.muxmask = uart0_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(9),
 	.funcval = BIT(9),
 };
@@ -282,6 +290,7 @@
 static const struct sirfsoc_padmux uart2_padmux = {
 	.muxmask_counts = ARRAY_SIZE(uart2_muxmask),
 	.muxmask = uart2_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(10),
 	.funcval = BIT(10),
 };
@@ -315,6 +324,7 @@
 static const struct sirfsoc_padmux sdmmc3_padmux = {
 	.muxmask_counts = ARRAY_SIZE(sdmmc3_muxmask),
 	.muxmask = sdmmc3_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(7),
 	.funcval = 0,
 };
@@ -331,6 +341,7 @@
 static const struct sirfsoc_padmux spi0_padmux = {
 	.muxmask_counts = ARRAY_SIZE(spi0_muxmask),
 	.muxmask = spi0_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(7),
 	.funcval = BIT(7),
 };
@@ -361,6 +372,7 @@
 static const struct sirfsoc_padmux cko1_padmux = {
 	.muxmask_counts = ARRAY_SIZE(cko1_muxmask),
 	.muxmask = cko1_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(3),
 	.funcval = 0,
 };
@@ -379,6 +391,7 @@
 static const struct sirfsoc_padmux i2s_padmux = {
 	.muxmask_counts = ARRAY_SIZE(i2s_muxmask),
 	.muxmask = i2s_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(3) | BIT(9),
 	.funcval = BIT(3),
 };
@@ -395,6 +408,7 @@
 static const struct sirfsoc_padmux ac97_padmux = {
 	.muxmask_counts = ARRAY_SIZE(ac97_muxmask),
 	.muxmask = ac97_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(8),
 	.funcval = 0,
 };
@@ -411,6 +425,7 @@
 static const struct sirfsoc_padmux spi1_padmux = {
 	.muxmask_counts = ARRAY_SIZE(spi1_muxmask),
 	.muxmask = spi1_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(8),
 	.funcval = BIT(8),
 };
@@ -441,6 +456,7 @@
 static const struct sirfsoc_padmux gps_padmux = {
 	.muxmask_counts = ARRAY_SIZE(gps_muxmask),
 	.muxmask = gps_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(12) | BIT(13) | BIT(14),
 	.funcval = BIT(12),
 };
@@ -463,6 +479,7 @@
 static const struct sirfsoc_padmux sdmmc5_padmux = {
 	.muxmask_counts = ARRAY_SIZE(sdmmc5_muxmask),
 	.muxmask = sdmmc5_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(13) | BIT(14),
 	.funcval = BIT(13) | BIT(14),
 };
@@ -479,12 +496,27 @@
 static const struct sirfsoc_padmux usp0_padmux = {
 	.muxmask_counts = ARRAY_SIZE(usp0_muxmask),
 	.muxmask = usp0_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(1) | BIT(2) | BIT(6) | BIT(9),
 	.funcval = 0,
 };
 
 static const unsigned usp0_pins[] = { 51, 52, 53, 54, 55 };
 
+static const struct sirfsoc_muxmask usp0_uart_nostreamctrl_muxmask[] = {
+	{
+		.group = 1,
+		.mask = BIT(20) | BIT(21),
+	},
+};
+
+static const struct sirfsoc_padmux usp0_uart_nostreamctrl_padmux = {
+	.muxmask_counts = ARRAY_SIZE(usp0_uart_nostreamctrl_muxmask),
+	.muxmask = usp0_uart_nostreamctrl_muxmask,
+};
+
+static const unsigned usp0_uart_nostreamctrl_pins[] = { 52, 53 };
+
 static const struct sirfsoc_muxmask usp1_muxmask[] = {
 	{
 		.group = 1,
@@ -495,12 +527,27 @@
 static const struct sirfsoc_padmux usp1_padmux = {
 	.muxmask_counts = ARRAY_SIZE(usp1_muxmask),
 	.muxmask = usp1_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(1) | BIT(9) | BIT(10) | BIT(11),
 	.funcval = 0,
 };
 
 static const unsigned usp1_pins[] = { 56, 57, 58, 59, 60 };
 
+static const struct sirfsoc_muxmask usp1_uart_nostreamctrl_muxmask[] = {
+	{
+		.group = 1,
+		.mask = BIT(25) | BIT(26),
+	},
+};
+
+static const struct sirfsoc_padmux usp1_uart_nostreamctrl_padmux = {
+	.muxmask_counts = ARRAY_SIZE(usp1_uart_nostreamctrl_muxmask),
+	.muxmask = usp1_uart_nostreamctrl_muxmask,
+};
+
+static const unsigned usp1_uart_nostreamctrl_pins[] = { 57, 58 };
+
 static const struct sirfsoc_muxmask usp2_muxmask[] = {
 	{
 		.group = 1,
@@ -514,12 +561,27 @@
 static const struct sirfsoc_padmux usp2_padmux = {
 	.muxmask_counts = ARRAY_SIZE(usp2_muxmask),
 	.muxmask = usp2_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(13) | BIT(14),
 	.funcval = 0,
 };
 
 static const unsigned usp2_pins[] = { 61, 62, 63, 64, 65 };
 
+static const struct sirfsoc_muxmask usp2_uart_nostreamctrl_muxmask[] = {
+	{
+		.group = 1,
+		.mask = BIT(30) | BIT(31),
+	},
+};
+
+static const struct sirfsoc_padmux usp2_uart_nostreamctrl_padmux = {
+	.muxmask_counts = ARRAY_SIZE(usp2_uart_nostreamctrl_muxmask),
+	.muxmask = usp2_uart_nostreamctrl_muxmask,
+};
+
+static const unsigned usp2_uart_nostreamctrl_pins[] = { 62, 63 };
+
 static const struct sirfsoc_muxmask nand_muxmask[] = {
 	{
 		.group = 2,
@@ -530,6 +592,7 @@
 static const struct sirfsoc_padmux nand_padmux = {
 	.muxmask_counts = ARRAY_SIZE(nand_muxmask),
 	.muxmask = nand_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(5),
 	.funcval = 0,
 };
@@ -538,6 +601,7 @@
 
 static const struct sirfsoc_padmux sdmmc0_padmux = {
 	.muxmask_counts = 0,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(5),
 	.funcval = 0,
 };
@@ -554,6 +618,7 @@
 static const struct sirfsoc_padmux sdmmc2_padmux = {
 	.muxmask_counts = ARRAY_SIZE(sdmmc2_muxmask),
 	.muxmask = sdmmc2_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(5),
 	.funcval = BIT(5),
 };
@@ -586,6 +651,7 @@
 static const struct sirfsoc_padmux vip_padmux = {
 	.muxmask_counts = ARRAY_SIZE(vip_muxmask),
 	.muxmask = vip_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(0),
 	.funcval = 0,
 };
@@ -635,6 +701,7 @@
 static const struct sirfsoc_padmux viprom_padmux = {
 	.muxmask_counts = ARRAY_SIZE(viprom_muxmask),
 	.muxmask = viprom_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(0),
 	.funcval = BIT(0),
 };
@@ -651,6 +718,7 @@
 static const struct sirfsoc_padmux pwm0_padmux = {
 	.muxmask_counts = ARRAY_SIZE(pwm0_muxmask),
 	.muxmask = pwm0_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(12),
 	.funcval = 0,
 };
@@ -722,6 +790,7 @@
 static const struct sirfsoc_padmux usb0_utmi_drvbus_padmux = {
 	.muxmask_counts = ARRAY_SIZE(usb0_utmi_drvbus_muxmask),
 	.muxmask = usb0_utmi_drvbus_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(6),
 	.funcval = BIT(6), /* refer to PAD_UTMI_DRVVBUS0_ENABLE */
 };
@@ -738,12 +807,31 @@
 static const struct sirfsoc_padmux usb1_utmi_drvbus_padmux = {
 	.muxmask_counts = ARRAY_SIZE(usb1_utmi_drvbus_muxmask),
 	.muxmask = usb1_utmi_drvbus_muxmask,
+	.ctrlreg = SIRFSOC_RSC_PIN_MUX,
 	.funcmask = BIT(11),
 	.funcval = BIT(11), /* refer to PAD_UTMI_DRVVBUS1_ENABLE */
 };
 
 static const unsigned usb1_utmi_drvbus_pins[] = { 59 };
 
+static const struct sirfsoc_padmux usb1_dp_dn_padmux = {
+	.muxmask_counts = 0,
+	.ctrlreg = SIRFSOC_RSC_USB_UART_SHARE,
+	.funcmask = BIT(2),
+	.funcval = BIT(2),
+};
+
+static const unsigned usb1_dp_dn_pins[] = { 115, 116 };
+
+static const struct sirfsoc_padmux uart1_route_io_usb1_padmux = {
+	.muxmask_counts = 0,
+	.ctrlreg = SIRFSOC_RSC_USB_UART_SHARE,
+	.funcmask = BIT(2),
+	.funcval = 0,
+};
+
+static const unsigned uart1_route_io_usb1_pins[] = { 115, 116 };
+
 static const struct sirfsoc_muxmask pulse_count_muxmask[] = {
 	{
 		.group = 0,
@@ -764,12 +852,19 @@
 	SIRFSOC_PIN_GROUP("lcd_24bitsgrp", lcd_24bits_pins),
 	SIRFSOC_PIN_GROUP("lcdrom_grp", lcdrom_pins),
 	SIRFSOC_PIN_GROUP("uart0grp", uart0_pins),
+	SIRFSOC_PIN_GROUP("uart0_nostreamctrlgrp", uart0_nostreamctrl_pins),
 	SIRFSOC_PIN_GROUP("uart1grp", uart1_pins),
 	SIRFSOC_PIN_GROUP("uart2grp", uart2_pins),
 	SIRFSOC_PIN_GROUP("uart2_nostreamctrlgrp", uart2_nostreamctrl_pins),
 	SIRFSOC_PIN_GROUP("usp0grp", usp0_pins),
+	SIRFSOC_PIN_GROUP("usp0_uart_nostreamctrl_grp",
+					usp0_uart_nostreamctrl_pins),
 	SIRFSOC_PIN_GROUP("usp1grp", usp1_pins),
+	SIRFSOC_PIN_GROUP("usp1_uart_nostreamctrl_grp",
+					usp1_uart_nostreamctrl_pins),
 	SIRFSOC_PIN_GROUP("usp2grp", usp2_pins),
+	SIRFSOC_PIN_GROUP("usp2_uart_nostreamctrl_grp",
+					usp2_uart_nostreamctrl_pins),
 	SIRFSOC_PIN_GROUP("i2c0grp", i2c0_pins),
 	SIRFSOC_PIN_GROUP("i2c1grp", i2c1_pins),
 	SIRFSOC_PIN_GROUP("pwm0grp", pwm0_pins),
@@ -789,6 +884,8 @@
 	SIRFSOC_PIN_GROUP("sdmmc5grp", sdmmc5_pins),
 	SIRFSOC_PIN_GROUP("usb0_utmi_drvbusgrp", usb0_utmi_drvbus_pins),
 	SIRFSOC_PIN_GROUP("usb1_utmi_drvbusgrp", usb1_utmi_drvbus_pins),
+	SIRFSOC_PIN_GROUP("usb1_dp_dngrp", usb1_dp_dn_pins),
+	SIRFSOC_PIN_GROUP("uart1_route_io_usb1grp", uart1_route_io_usb1_pins),
 	SIRFSOC_PIN_GROUP("pulse_countgrp", pulse_count_pins),
 	SIRFSOC_PIN_GROUP("i2sgrp", i2s_pins),
 	SIRFSOC_PIN_GROUP("ac97grp", ac97_pins),
@@ -803,12 +900,19 @@
 static const char * const lcd_24bitsgrp[] = { "lcd_24bitsgrp" };
 static const char * const lcdromgrp[] = { "lcdromgrp" };
 static const char * const uart0grp[] = { "uart0grp" };
+static const char * const uart0_nostreamctrlgrp[] = { "uart0_nostreamctrlgrp" };
 static const char * const uart1grp[] = { "uart1grp" };
 static const char * const uart2grp[] = { "uart2grp" };
 static const char * const uart2_nostreamctrlgrp[] = { "uart2_nostreamctrlgrp" };
 static const char * const usp0grp[] = { "usp0grp" };
+static const char * const usp0_uart_nostreamctrl_grp[] =
+					{ "usp0_uart_nostreamctrl_grp" };
 static const char * const usp1grp[] = { "usp1grp" };
+static const char * const usp1_uart_nostreamctrl_grp[] =
+					{ "usp1_uart_nostreamctrl_grp" };
 static const char * const usp2grp[] = { "usp2grp" };
+static const char * const usp2_uart_nostreamctrl_grp[] =
+					{ "usp2_uart_nostreamctrl_grp" };
 static const char * const i2c0grp[] = { "i2c0grp" };
 static const char * const i2c1grp[] = { "i2c1grp" };
 static const char * const pwm0grp[] = { "pwm0grp" };
@@ -828,6 +932,8 @@
 static const char * const sdmmc5grp[] = { "sdmmc5grp" };
 static const char * const usb0_utmi_drvbusgrp[] = { "usb0_utmi_drvbusgrp" };
 static const char * const usb1_utmi_drvbusgrp[] = { "usb1_utmi_drvbusgrp" };
+static const char * const usb1_dp_dngrp[] = { "usb1_dp_dngrp" };
+static const char * const uart1_route_io_usb1grp[] = { "uart1_route_io_usb1grp" };
 static const char * const pulse_countgrp[] = { "pulse_countgrp" };
 static const char * const i2sgrp[] = { "i2sgrp" };
 static const char * const ac97grp[] = { "ac97grp" };
@@ -842,12 +948,19 @@
 	SIRFSOC_PMX_FUNCTION("lcd_24bits", lcd_24bitsgrp, lcd_24bits_padmux),
 	SIRFSOC_PMX_FUNCTION("lcdrom", lcdromgrp, lcdrom_padmux),
 	SIRFSOC_PMX_FUNCTION("uart0", uart0grp, uart0_padmux),
+	SIRFSOC_PMX_FUNCTION("uart0_nostreamctrl", uart0_nostreamctrlgrp, uart0_nostreamctrl_padmux),
 	SIRFSOC_PMX_FUNCTION("uart1", uart1grp, uart1_padmux),
 	SIRFSOC_PMX_FUNCTION("uart2", uart2grp, uart2_padmux),
 	SIRFSOC_PMX_FUNCTION("uart2_nostreamctrl", uart2_nostreamctrlgrp, uart2_nostreamctrl_padmux),
 	SIRFSOC_PMX_FUNCTION("usp0", usp0grp, usp0_padmux),
+	SIRFSOC_PMX_FUNCTION("usp0_uart_nostreamctrl",
+		usp0_uart_nostreamctrl_grp, usp0_uart_nostreamctrl_padmux),
 	SIRFSOC_PMX_FUNCTION("usp1", usp1grp, usp1_padmux),
+	SIRFSOC_PMX_FUNCTION("usp1_uart_nostreamctrl",
+		usp1_uart_nostreamctrl_grp, usp1_uart_nostreamctrl_padmux),
 	SIRFSOC_PMX_FUNCTION("usp2", usp2grp, usp2_padmux),
+	SIRFSOC_PMX_FUNCTION("usp2_uart_nostreamctrl",
+		usp2_uart_nostreamctrl_grp, usp2_uart_nostreamctrl_padmux),
 	SIRFSOC_PMX_FUNCTION("i2c0", i2c0grp, i2c0_padmux),
 	SIRFSOC_PMX_FUNCTION("i2c1", i2c1grp, i2c1_padmux),
 	SIRFSOC_PMX_FUNCTION("pwm0", pwm0grp, pwm0_padmux),
@@ -867,6 +980,8 @@
 	SIRFSOC_PMX_FUNCTION("sdmmc5", sdmmc5grp, sdmmc5_padmux),
 	SIRFSOC_PMX_FUNCTION("usb0_utmi_drvbus", usb0_utmi_drvbusgrp, usb0_utmi_drvbus_padmux),
 	SIRFSOC_PMX_FUNCTION("usb1_utmi_drvbus", usb1_utmi_drvbusgrp, usb1_utmi_drvbus_padmux),
+	SIRFSOC_PMX_FUNCTION("usb1_dp_dn", usb1_dp_dngrp, usb1_dp_dn_padmux),
+	SIRFSOC_PMX_FUNCTION("uart1_route_io_usb1", uart1_route_io_usb1grp, uart1_route_io_usb1_padmux),
 	SIRFSOC_PMX_FUNCTION("pulse_count", pulse_countgrp, pulse_count_padmux),
 	SIRFSOC_PMX_FUNCTION("i2s", i2sgrp, i2s_padmux),
 	SIRFSOC_PMX_FUNCTION("ac97", ac97grp, ac97_padmux),
diff --git a/drivers/pinctrl/sirf/pinctrl-sirf.c b/drivers/pinctrl/sirf/pinctrl-sirf.c
index 26f946a..b81e388 100644
--- a/drivers/pinctrl/sirf/pinctrl-sirf.c
+++ b/drivers/pinctrl/sirf/pinctrl-sirf.c
@@ -166,12 +166,12 @@
 
 	if (mux->funcmask && enable) {
 		u32 func_en_val;
+
 		func_en_val =
-			readl(spmx->rsc_virtbase + SIRFSOC_RSC_PIN_MUX);
+			readl(spmx->rsc_virtbase + mux->ctrlreg);
 		func_en_val =
-			(func_en_val & ~mux->funcmask) | (mux->
-				funcval);
-		writel(func_en_val, spmx->rsc_virtbase + SIRFSOC_RSC_PIN_MUX);
+			(func_en_val & ~mux->funcmask) | (mux->funcval);
+		writel(func_en_val, spmx->rsc_virtbase + mux->ctrlreg);
 	}
 }
 
diff --git a/drivers/pinctrl/sirf/pinctrl-sirf.h b/drivers/pinctrl/sirf/pinctrl-sirf.h
index 17cc108..d7f16b4 100644
--- a/drivers/pinctrl/sirf/pinctrl-sirf.h
+++ b/drivers/pinctrl/sirf/pinctrl-sirf.h
@@ -9,8 +9,9 @@
 #ifndef __PINMUX_SIRF_H__
 #define __PINMUX_SIRF_H__
 
-#define SIRFSOC_NUM_PADS    622
-#define SIRFSOC_RSC_PIN_MUX 0x4
+#define SIRFSOC_NUM_PADS		622
+#define SIRFSOC_RSC_USB_UART_SHARE	0
+#define SIRFSOC_RSC_PIN_MUX		0x4
 
 #define SIRFSOC_GPIO_PAD_EN(g)		((g)*0x100 + 0x84)
 #define SIRFSOC_GPIO_PAD_EN_CLR(g)	((g)*0x100 + 0x90)
@@ -61,6 +62,7 @@
 	unsigned long muxmask_counts;
 	const struct sirfsoc_muxmask *muxmask;
 	/* RSC_PIN_MUX set */
+	unsigned long ctrlreg;
 	unsigned long funcmask;
 	unsigned long funcval;
 };
diff --git a/drivers/pinctrl/spear/pinctrl-plgpio.c b/drivers/pinctrl/spear/pinctrl-plgpio.c
index 0a7f0bdb..ff2940e 100644
--- a/drivers/pinctrl/spear/pinctrl-plgpio.c
+++ b/drivers/pinctrl/spear/pinctrl-plgpio.c
@@ -735,7 +735,7 @@
 		.owner = THIS_MODULE,
 		.name = "spear-plgpio",
 		.pm = &plgpio_dev_pm_ops,
-		.of_match_table = of_match_ptr(plgpio_of_match),
+		.of_match_table = plgpio_of_match,
 	},
 };
 
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 96d6b2e..b51a746 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -504,6 +504,7 @@
 	depends on BACKLIGHT_CLASS_DEVICE
 	depends on RFKILL || RFKILL = n
 	depends on HOTPLUG_PCI
+	depends on ACPI_VIDEO || ACPI_VIDEO = n
 	select INPUT_SPARSEKMAP
 	select LEDS_CLASS
 	select NEW_LEDS
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index 9215ed7..d654f83 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -25,7 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/sfi.h>
 #include <linux/module.h>
-#include <asm/mrst.h>
+#include <asm/intel-mid.h>
 #include <asm/intel_scu_ipc.h>
 
 /* IPC defines the following message types */
@@ -579,7 +579,7 @@
 
 static int __init intel_scu_ipc_init(void)
 {
-	platform = mrst_identify_cpu();
+	platform = intel_mid_identify_cpu();
 	if (platform == 0)
 		return -ENODEV;
 	return  pci_register_driver(&ipc_driver);
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index d3fd520..13ec195 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -127,18 +127,17 @@
 		 "default is -1 (automatic)");
 #endif
 
-static int kbd_backlight = 1;
+static int kbd_backlight = -1;
 module_param(kbd_backlight, int, 0444);
 MODULE_PARM_DESC(kbd_backlight,
 		 "set this to 0 to disable keyboard backlight, "
-		 "1 to enable it (default: 0)");
+		 "1 to enable it (default: no change from current value)");
 
-static int kbd_backlight_timeout;	/* = 0 */
+static int kbd_backlight_timeout = -1;
 module_param(kbd_backlight_timeout, int, 0444);
 MODULE_PARM_DESC(kbd_backlight_timeout,
-		 "set this to 0 to set the default 10 seconds timeout, "
-		 "1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout "
-		 "(default: 0)");
+		 "meaningful values vary from 0 to 3 and their meaning depends "
+		 "on the model (default: no change from current value)");
 
 #ifdef CONFIG_PM_SLEEP
 static void sony_nc_kbd_backlight_resume(void);
@@ -1844,6 +1843,8 @@
 	if (!kbdbl_ctl)
 		return -ENOMEM;
 
+	kbdbl_ctl->mode = kbd_backlight;
+	kbdbl_ctl->timeout = kbd_backlight_timeout;
 	kbdbl_ctl->handle = handle;
 	if (handle == 0x0137)
 		kbdbl_ctl->base = 0x0C00;
@@ -1870,8 +1871,8 @@
 	if (ret)
 		goto outmode;
 
-	__sony_nc_kbd_backlight_mode_set(kbd_backlight);
-	__sony_nc_kbd_backlight_timeout_set(kbd_backlight_timeout);
+	__sony_nc_kbd_backlight_mode_set(kbdbl_ctl->mode);
+	__sony_nc_kbd_backlight_timeout_set(kbdbl_ctl->timeout);
 
 	return 0;
 
@@ -1886,17 +1887,8 @@
 static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd)
 {
 	if (kbdbl_ctl) {
-		int result;
-
 		device_remove_file(&pd->dev, &kbdbl_ctl->mode_attr);
 		device_remove_file(&pd->dev, &kbdbl_ctl->timeout_attr);
-
-		/* restore the default hw behaviour */
-		sony_call_snc_handle(kbdbl_ctl->handle,
-				kbdbl_ctl->base | 0x10000, &result);
-		sony_call_snc_handle(kbdbl_ctl->handle,
-				kbdbl_ctl->base + 0x200, &result);
-
 		kfree(kbdbl_ctl);
 		kbdbl_ctl = NULL;
 	}
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 03ca6c1..0b7efb2 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -23,7 +23,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#define TPACPI_VERSION "0.24"
+#define TPACPI_VERSION "0.25"
 #define TPACPI_SYSFS_VERSION 0x020700
 
 /*
@@ -88,6 +88,7 @@
 
 #include <linux/pci_ids.h>
 
+#include <linux/thinkpad_acpi.h>
 
 /* ThinkPad CMOS commands */
 #define TP_CMOS_VOLUME_DOWN	0
@@ -8350,6 +8351,91 @@
 	.resume = fan_resume,
 };
 
+/*************************************************************************
+ * Mute LED subdriver
+ */
+
+
+struct tp_led_table {
+	acpi_string name;
+	int on_value;
+	int off_value;
+	int state;
+};
+
+static struct tp_led_table led_tables[] = {
+	[TPACPI_LED_MUTE] = {
+		.name = "SSMS",
+		.on_value = 1,
+		.off_value = 0,
+	},
+	[TPACPI_LED_MICMUTE] = {
+		.name = "MMTS",
+		.on_value = 2,
+		.off_value = 0,
+	},
+};
+
+static int mute_led_on_off(struct tp_led_table *t, bool state)
+{
+	acpi_handle temp;
+	int output;
+
+	if (!ACPI_SUCCESS(acpi_get_handle(hkey_handle, t->name, &temp))) {
+		pr_warn("Thinkpad ACPI has no %s interface.\n", t->name);
+		return -EIO;
+	}
+
+	if (!acpi_evalf(hkey_handle, &output, t->name, "dd",
+			state ? t->on_value : t->off_value))
+		return -EIO;
+
+	t->state = state;
+	return state;
+}
+
+int tpacpi_led_set(int whichled, bool on)
+{
+	struct tp_led_table *t;
+
+	if (whichled < 0 || whichled >= TPACPI_LED_MAX)
+		return -EINVAL;
+
+	t = &led_tables[whichled];
+	if (t->state < 0 || t->state == on)
+		return t->state;
+	return mute_led_on_off(t, on);
+}
+EXPORT_SYMBOL_GPL(tpacpi_led_set);
+
+static int mute_led_init(struct ibm_init_struct *iibm)
+{
+	acpi_handle temp;
+	int i;
+
+	for (i = 0; i < TPACPI_LED_MAX; i++) {
+		struct tp_led_table *t = &led_tables[i];
+		if (ACPI_SUCCESS(acpi_get_handle(hkey_handle, t->name, &temp)))
+			mute_led_on_off(t, false);
+		else
+			t->state = -ENODEV;
+	}
+	return 0;
+}
+
+static void mute_led_exit(void)
+{
+	int i;
+
+	for (i = 0; i < TPACPI_LED_MAX; i++)
+		tpacpi_led_set(i, false);
+}
+
+static struct ibm_struct mute_led_driver_data = {
+	.name = "mute_led",
+	.exit = mute_led_exit,
+};
+
 /****************************************************************************
  ****************************************************************************
  *
@@ -8768,6 +8854,10 @@
 		.init = fan_init,
 		.data = &fan_driver_data,
 	},
+	{
+		.init = mute_led_init,
+		.data = &mute_led_driver_data,
+	},
 };
 
 static int __init set_ibm_param(const char *val, struct kernel_param *kp)
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h
index ffd53e3..c8873b0 100644
--- a/drivers/pnp/base.h
+++ b/drivers/pnp/base.h
@@ -4,7 +4,7 @@
  */
 
 extern spinlock_t pnp_lock;
-extern struct device_attribute pnp_interface_attrs[];
+extern const struct attribute_group *pnp_dev_groups[];
 void *pnp_alloc(long size);
 
 int pnp_register_protocol(struct pnp_protocol *protocol);
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index a39ee38..6936e0a 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -246,7 +246,7 @@
 	.remove  = pnp_device_remove,
 	.shutdown = pnp_device_shutdown,
 	.pm	 = &pnp_bus_dev_pm_ops,
-	.dev_attrs = pnp_interface_attrs,
+	.dev_groups = pnp_dev_groups,
 };
 
 int pnp_register_driver(struct pnp_driver *drv)
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index 0c20131..e6c403b 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -203,8 +203,8 @@
 	}
 }
 
-static ssize_t pnp_show_options(struct device *dmdev,
-				struct device_attribute *attr, char *buf)
+static ssize_t options_show(struct device *dmdev, struct device_attribute *attr,
+			    char *buf)
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
 	pnp_info_buffer_t *buffer;
@@ -241,10 +241,10 @@
 	kfree(buffer);
 	return ret;
 }
+static DEVICE_ATTR_RO(options);
 
-static ssize_t pnp_show_current_resources(struct device *dmdev,
-					  struct device_attribute *attr,
-					  char *buf)
+static ssize_t resources_show(struct device *dmdev,
+			      struct device_attribute *attr, char *buf)
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
 	pnp_info_buffer_t *buffer;
@@ -331,9 +331,9 @@
 	return buf;
 }
 
-static ssize_t pnp_set_current_resources(struct device *dmdev,
-					 struct device_attribute *attr,
-					 const char *ubuf, size_t count)
+static ssize_t resources_store(struct device *dmdev,
+			       struct device_attribute *attr, const char *ubuf,
+			       size_t count)
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
 	char *buf = (void *)ubuf;
@@ -434,9 +434,10 @@
 		return retval;
 	return count;
 }
+static DEVICE_ATTR_RW(resources);
 
-static ssize_t pnp_show_current_ids(struct device *dmdev,
-				    struct device_attribute *attr, char *buf)
+static ssize_t id_show(struct device *dmdev, struct device_attribute *attr,
+		       char *buf)
 {
 	char *str = buf;
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
@@ -448,12 +449,20 @@
 	}
 	return (str - buf);
 }
+static DEVICE_ATTR_RO(id);
 
-struct device_attribute pnp_interface_attrs[] = {
-	__ATTR(resources, S_IRUGO | S_IWUSR,
-		   pnp_show_current_resources,
-		   pnp_set_current_resources),
-	__ATTR(options, S_IRUGO, pnp_show_options, NULL),
-	__ATTR(id, S_IRUGO, pnp_show_current_ids, NULL),
-	__ATTR_NULL,
+static struct attribute *pnp_dev_attrs[] = {
+	&dev_attr_resources.attr,
+	&dev_attr_options.attr,
+	&dev_attr_id.attr,
+	NULL,
+};
+
+static const struct attribute_group pnp_dev_group = {
+	.attrs = pnp_dev_attrs,
+};
+
+const struct attribute_group *pnp_dev_groups[] = {
+	&pnp_dev_group,
+	NULL,
 };
diff --git a/drivers/ptp/ptp_ixp46x.c b/drivers/ptp/ptp_ixp46x.c
index d49b851..4a08727 100644
--- a/drivers/ptp/ptp_ixp46x.c
+++ b/drivers/ptp/ptp_ixp46x.c
@@ -259,8 +259,15 @@
 static int setup_interrupt(int gpio)
 {
 	int irq;
+	int err;
 
-	gpio_line_config(gpio, IXP4XX_GPIO_IN);
+	err = gpio_request(gpio, "ixp4-ptp");
+	if (err)
+		return err;
+
+	err = gpio_direction_input(gpio);
+	if (err)
+		return err;
 
 	irq = gpio_to_irq(gpio);
 
diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c
index 3e9b6a7..c9ae692 100644
--- a/drivers/rapidio/rio-driver.c
+++ b/drivers/rapidio/rio-driver.c
@@ -223,8 +223,8 @@
 struct bus_type rio_bus_type = {
 	.name = "rapidio",
 	.match = rio_match_bus,
-	.dev_attrs = rio_dev_attrs,
-	.bus_attrs = rio_bus_attrs,
+	.dev_groups = rio_dev_groups,
+	.bus_groups = rio_bus_groups,
 	.probe = rio_device_probe,
 	.remove = rio_device_remove,
 	.uevent	= rio_uevent,
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c
index 9331be6..e0221c6 100644
--- a/drivers/rapidio/rio-sysfs.c
+++ b/drivers/rapidio/rio-sysfs.c
@@ -27,6 +27,7 @@
 									\
 	return sprintf(buf, format_string, rdev->field);		\
 }									\
+static DEVICE_ATTR_RO(field);
 
 rio_config_attr(did, "0x%04x\n");
 rio_config_attr(vid, "0x%04x\n");
@@ -54,6 +55,7 @@
 
 	return (str - buf);
 }
+static DEVICE_ATTR_RO(routes);
 
 static ssize_t lprev_show(struct device *dev,
 			  struct device_attribute *attr, char *buf)
@@ -63,6 +65,7 @@
 	return sprintf(buf, "%s\n",
 			(rdev->prev) ? rio_name(rdev->prev) : "root");
 }
+static DEVICE_ATTR_RO(lprev);
 
 static ssize_t lnext_show(struct device *dev,
 			  struct device_attribute *attr, char *buf)
@@ -83,6 +86,7 @@
 
 	return str - buf;
 }
+static DEVICE_ATTR_RO(lnext);
 
 static ssize_t modalias_show(struct device *dev,
 			     struct device_attribute *attr, char *buf)
@@ -92,23 +96,29 @@
 	return sprintf(buf, "rapidio:v%04Xd%04Xav%04Xad%04X\n",
 		       rdev->vid, rdev->did, rdev->asm_vid, rdev->asm_did);
 }
+static DEVICE_ATTR_RO(modalias);
 
-struct device_attribute rio_dev_attrs[] = {
-	__ATTR_RO(did),
-	__ATTR_RO(vid),
-	__ATTR_RO(device_rev),
-	__ATTR_RO(asm_did),
-	__ATTR_RO(asm_vid),
-	__ATTR_RO(asm_rev),
-	__ATTR_RO(lprev),
-	__ATTR_RO(destid),
-	__ATTR_RO(modalias),
-	__ATTR_NULL,
+static struct attribute *rio_dev_attrs[] = {
+	&dev_attr_did.attr,
+	&dev_attr_vid.attr,
+	&dev_attr_device_rev.attr,
+	&dev_attr_asm_did.attr,
+	&dev_attr_asm_vid.attr,
+	&dev_attr_asm_rev.attr,
+	&dev_attr_lprev.attr,
+	&dev_attr_destid.attr,
+	&dev_attr_modalias.attr,
+	NULL,
 };
 
-static DEVICE_ATTR(routes, S_IRUGO, routes_show, NULL);
-static DEVICE_ATTR(lnext, S_IRUGO, lnext_show, NULL);
-static DEVICE_ATTR(hopcount, S_IRUGO, hopcount_show, NULL);
+static const struct attribute_group rio_dev_group = {
+	.attrs = rio_dev_attrs,
+};
+
+const struct attribute_group *rio_dev_groups[] = {
+	&rio_dev_group,
+	NULL,
+};
 
 static ssize_t
 rio_read_config(struct file *filp, struct kobject *kobj,
@@ -316,8 +326,18 @@
 
 	return rc;
 }
+static BUS_ATTR(scan, (S_IWUSR|S_IWGRP), NULL, bus_scan_store);
 
-struct bus_attribute rio_bus_attrs[] = {
-	__ATTR(scan, (S_IWUSR|S_IWGRP), NULL, bus_scan_store),
-	__ATTR_NULL
+static struct attribute *rio_bus_attrs[] = {
+	&bus_attr_scan.attr,
+	NULL,
+};
+
+static const struct attribute_group rio_bus_group = {
+	.attrs = rio_bus_attrs,
+};
+
+const struct attribute_group *rio_bus_groups[] = {
+	&rio_bus_group,
+	NULL,
 };
diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h
index 085215c..5f99d22 100644
--- a/drivers/rapidio/rio.h
+++ b/drivers/rapidio/rio.h
@@ -48,8 +48,8 @@
 extern int rio_mport_scan(int mport_id);
 
 /* Structures internal to the RIO core code */
-extern struct device_attribute rio_dev_attrs[];
-extern struct bus_attribute rio_bus_attrs[];
+extern const struct attribute_group *rio_dev_groups[];
+extern const struct attribute_group *rio_bus_groups[];
 
 #define RIO_GET_DID(size, x)	(size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16))
 #define RIO_SET_DID(size, x)	(size ? (x & 0xffff) : ((x & 0x000000ff) << 16))
diff --git a/drivers/regulator/88pm800.c b/drivers/regulator/88pm800.c
index 3459f60..d333f7e 100644
--- a/drivers/regulator/88pm800.c
+++ b/drivers/regulator/88pm800.c
@@ -141,18 +141,14 @@
 
 /* Ranges are sorted in ascending order. */
 static const struct regulator_linear_range buck1_volt_range[] = {
-	{ .min_uV = 600000, .max_uV = 1587500, .min_sel = 0, .max_sel = 0x4f,
-	  .uV_step = 12500 },
-	{ .min_uV = 1600000, .max_uV = 1800000, .min_sel = 0x50,
-	  .max_sel = 0x54, .uV_step = 50000 },
+	REGULATOR_LINEAR_RANGE(600000, 0, 0x4f, 12500),
+	REGULATOR_LINEAR_RANGE(1600000, 0x50, 0x54, 50000),
 };
 
 /* BUCK 2~5 have same ranges. */
 static const struct regulator_linear_range buck2_5_volt_range[] = {
-	{ .min_uV = 600000, .max_uV = 1587500,	.min_sel = 0, .max_sel = 0x4f,
-	  .uV_step = 12500 },
-	{ .min_uV = 1600000, .max_uV = 3300000, .min_sel = 0x50,
-	  .max_sel = 0x72, .uV_step = 50000 },
+	REGULATOR_LINEAR_RANGE(600000, 0, 0x4f, 12500),
+	REGULATOR_LINEAR_RANGE(1600000, 0x50, 0x72, 50000),
 };
 
 static const unsigned int ldo1_volt_table[] = {
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index 7023097..f704d83 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -391,7 +391,8 @@
 	else
 		config.regmap = chip->regmap_companion;
 
-	info->regulator = regulator_register(&info->desc, &config);
+	info->regulator = devm_regulator_register(&pdev->dev, &info->desc,
+						  &config);
 	if (IS_ERR(info->regulator)) {
 		dev_err(&pdev->dev, "failed to register regulator %s\n",
 			info->desc.name);
@@ -402,14 +403,6 @@
 	return 0;
 }
 
-static int pm8607_regulator_remove(struct platform_device *pdev)
-{
-	struct pm8607_regulator_info *info = platform_get_drvdata(pdev);
-
-	regulator_unregister(info->regulator);
-	return 0;
-}
-
 static struct platform_device_id pm8607_regulator_driver_ids[] = {
 	{
 		.name	= "88pm860x-regulator",
@@ -428,7 +421,6 @@
 		.owner	= THIS_MODULE,
 	},
 	.probe		= pm8607_regulator_probe,
-	.remove		= pm8607_regulator_remove,
 	.id_table	= pm8607_regulator_driver_ids,
 };
 
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index dfe5809..ce785f4 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -28,16 +28,6 @@
 	help
 	  Say yes here to enable debugging support.
 
-config REGULATOR_DUMMY
-	bool "Provide a dummy regulator if regulator lookups fail"
-	help
-	  If this option is enabled then when a regulator lookup fails
-	  and the board has not specified that it has provided full
-	  constraints the regulator core will provide an always
-	  enabled dummy regulator, allowing consumer drivers to continue.
-
-	  A warning will be generated when this substitution is done.
-
 config REGULATOR_FIXED_VOLTAGE
 	tristate "Fixed voltage regulator support"
 	help
@@ -133,6 +123,14 @@
 	  This driver provides support for the voltage regulators on the
 	  AS3711 PMIC
 
+config REGULATOR_AS3722
+	tristate "AMS AS3722 PMIC Regulators"
+	depends on MFD_AS3722
+	help
+	  This driver provides support for the voltage regulators on the
+	  AS3722 PMIC. This will enable support for all the software
+	  controllable DCDC/LDO regulators.
+
 config REGULATOR_DA903X
 	tristate "Dialog Semiconductor DA9030/DA9034 regulators"
 	depends on PMIC_DA903X
@@ -429,6 +427,14 @@
 	  on TI SoCs may be unstable without enabling this as it provides
 	  device specific optimized bias to allow/optimize functionality.
 
+config REGULATOR_STW481X_VMMC
+	bool "ST Microelectronics STW481X VMMC regulator"
+	depends on MFD_STW481X
+	default y if MFD_STW481X
+	help
+	  This driver supports the internal VMMC regulator in the STw481x
+	  PMIC chips.
+
 config REGULATOR_TPS51632
 	tristate "TI TPS51632 Power Regulator"
 	depends on I2C
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 185cce2..01c597e 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -3,7 +3,7 @@
 #
 
 
-obj-$(CONFIG_REGULATOR) += core.o dummy.o fixed-helper.o helpers.o
+obj-$(CONFIG_REGULATOR) += core.o dummy.o fixed-helper.o helpers.o devres.o
 obj-$(CONFIG_OF) += of_regulator.o
 obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
 obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
@@ -18,6 +18,7 @@
 obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
 obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
 obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
+obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
 obj-$(CONFIG_REGULATOR_DA903X)	+= da903x.o
 obj-$(CONFIG_REGULATOR_DA9052)	+= da9052-regulator.o
 obj-$(CONFIG_REGULATOR_DA9055)	+= da9055-regulator.o
@@ -56,6 +57,7 @@
 obj-$(CONFIG_REGULATOR_RC5T583)  += rc5t583-regulator.o
 obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
 obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
+obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
 obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c
index 881159d..f70a9bf 100644
--- a/drivers/regulator/aat2870-regulator.c
+++ b/drivers/regulator/aat2870-regulator.c
@@ -176,7 +176,7 @@
 	config.driver_data = ri;
 	config.init_data = dev_get_platdata(&pdev->dev);
 
-	rdev = regulator_register(&ri->desc, &config);
+	rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
 	if (IS_ERR(rdev)) {
 		dev_err(&pdev->dev, "Failed to register regulator %s\n",
 			ri->desc.name);
@@ -187,21 +187,12 @@
 	return 0;
 }
 
-static int aat2870_regulator_remove(struct platform_device *pdev)
-{
-	struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
-	regulator_unregister(rdev);
-	return 0;
-}
-
 static struct platform_driver aat2870_regulator_driver = {
 	.driver = {
 		.name	= "aat2870-regulator",
 		.owner	= THIS_MODULE,
 	},
 	.probe	= aat2870_regulator_probe,
-	.remove	= aat2870_regulator_remove,
 };
 
 static int __init aat2870_regulator_init(void)
diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c
index 7d5eaa8..77b46d0 100644
--- a/drivers/regulator/ab3100.c
+++ b/drivers/regulator/ab3100.c
@@ -535,7 +535,7 @@
 	config.dev = &pdev->dev;
 	config.driver_data = reg;
 
-	rdev = regulator_register(desc, &config);
+	rdev = devm_regulator_register(&pdev->dev, desc, &config);
 	if (IS_ERR(rdev)) {
 		err = PTR_ERR(rdev);
 		dev_err(&pdev->dev,
@@ -616,7 +616,6 @@
 	for (i = 0; i < AB3100_NUM_REGULATORS; i++) {
 		struct ab3100_regulator *reg = &ab3100_regulators[i];
 
-		regulator_unregister(reg->rdev);
 		reg->rdev = NULL;
 	}
 	return 0;
diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c
index 02ff691..29c0faa 100644
--- a/drivers/regulator/ab8500-ext.c
+++ b/drivers/regulator/ab8500-ext.c
@@ -413,16 +413,12 @@
 			&pdata->ext_regulator[i];
 
 		/* register regulator with framework */
-		info->rdev = regulator_register(&info->desc, &config);
+		info->rdev = devm_regulator_register(&pdev->dev, &info->desc,
+						     &config);
 		if (IS_ERR(info->rdev)) {
 			err = PTR_ERR(info->rdev);
 			dev_err(&pdev->dev, "failed to register regulator %s\n",
 					info->desc.name);
-			/* when we fail, un-register all earlier regulators */
-			while (--i >= 0) {
-				info = &ab8500_ext_regulator_info[i];
-				regulator_unregister(info->rdev);
-			}
 			return err;
 		}
 
@@ -433,26 +429,8 @@
 	return 0;
 }
 
-static int ab8500_ext_regulator_remove(struct platform_device *pdev)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(ab8500_ext_regulator_info); i++) {
-		struct ab8500_ext_regulator_info *info = NULL;
-		info = &ab8500_ext_regulator_info[i];
-
-		dev_vdbg(rdev_get_dev(info->rdev),
-			"%s-remove\n", info->desc.name);
-
-		regulator_unregister(info->rdev);
-	}
-
-	return 0;
-}
-
 static struct platform_driver ab8500_ext_regulator_driver = {
 	.probe = ab8500_ext_regulator_probe,
-	.remove = ab8500_ext_regulator_remove,
 	.driver         = {
 		.name   = "ab8500-ext-regulator",
 		.owner  = THIS_MODULE,
diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c
index b2b203c..48016a0 100644
--- a/drivers/regulator/ad5398.c
+++ b/drivers/regulator/ad5398.c
@@ -219,7 +219,6 @@
 	struct ad5398_chip_info *chip;
 	const struct ad5398_current_data_format *df =
 			(struct ad5398_current_data_format *)id->driver_data;
-	int ret;
 
 	if (!init_data)
 		return -EINVAL;
@@ -240,33 +239,21 @@
 	chip->current_offset = df->current_offset;
 	chip->current_mask = (chip->current_level - 1) << chip->current_offset;
 
-	chip->rdev = regulator_register(&ad5398_reg, &config);
+	chip->rdev = devm_regulator_register(&client->dev, &ad5398_reg,
+					     &config);
 	if (IS_ERR(chip->rdev)) {
-		ret = PTR_ERR(chip->rdev);
 		dev_err(&client->dev, "failed to register %s %s\n",
 			id->name, ad5398_reg.name);
-		goto err;
+		return PTR_ERR(chip->rdev);
 	}
 
 	i2c_set_clientdata(client, chip);
 	dev_dbg(&client->dev, "%s regulator driver is registered.\n", id->name);
 	return 0;
-
-err:
-	return ret;
-}
-
-static int ad5398_remove(struct i2c_client *client)
-{
-	struct ad5398_chip_info *chip = i2c_get_clientdata(client);
-
-	regulator_unregister(chip->rdev);
-	return 0;
 }
 
 static struct i2c_driver ad5398_driver = {
 	.probe = ad5398_probe,
-	.remove = ad5398_remove,
 	.driver		= {
 		.name	= "ad5398",
 	},
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
index 0d4a8cc..c734d09 100644
--- a/drivers/regulator/anatop-regulator.c
+++ b/drivers/regulator/anatop-regulator.c
@@ -200,7 +200,7 @@
 	config.regmap = sreg->anatop;
 
 	/* register regulator */
-	rdev = regulator_register(rdesc, &config);
+	rdev = devm_regulator_register(dev, rdesc, &config);
 	if (IS_ERR(rdev)) {
 		dev_err(dev, "failed to register %s\n",
 			rdesc->name);
@@ -223,7 +223,6 @@
 	struct anatop_regulator *sreg = rdev_get_drvdata(rdev);
 	const char *name = sreg->name;
 
-	regulator_unregister(rdev);
 	kfree(name);
 
 	return 0;
@@ -256,7 +255,7 @@
 }
 module_exit(anatop_regulator_exit);
 
-MODULE_AUTHOR("Nancy Chen <Nancy.Chen@freescale.com>, "
-	      "Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>");
+MODULE_AUTHOR("Nancy Chen <Nancy.Chen@freescale.com>");
+MODULE_AUTHOR("Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>");
 MODULE_DESCRIPTION("ANATOP Regulator driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
index 81d8681..4f6c205 100644
--- a/drivers/regulator/arizona-ldo1.c
+++ b/drivers/regulator/arizona-ldo1.c
@@ -226,7 +226,7 @@
 	else
 		config.init_data = &ldo1->init_data;
 
-	ldo1->regulator = regulator_register(desc, &config);
+	ldo1->regulator = devm_regulator_register(&pdev->dev, desc, &config);
 	if (IS_ERR(ldo1->regulator)) {
 		ret = PTR_ERR(ldo1->regulator);
 		dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n",
@@ -239,18 +239,8 @@
 	return 0;
 }
 
-static int arizona_ldo1_remove(struct platform_device *pdev)
-{
-	struct arizona_ldo1 *ldo1 = platform_get_drvdata(pdev);
-
-	regulator_unregister(ldo1->regulator);
-
-	return 0;
-}
-
 static struct platform_driver arizona_ldo1_driver = {
 	.probe = arizona_ldo1_probe,
-	.remove = arizona_ldo1_remove,
 	.driver		= {
 		.name	= "arizona-ldo1",
 		.owner	= THIS_MODULE,
diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c
index e87536b..724706a 100644
--- a/drivers/regulator/arizona-micsupp.c
+++ b/drivers/regulator/arizona-micsupp.c
@@ -225,7 +225,9 @@
 	regmap_update_bits(arizona->regmap, ARIZONA_MIC_CHARGE_PUMP_1,
 			   ARIZONA_CPMIC_BYPASS, 0);
 
-	micsupp->regulator = regulator_register(&arizona_micsupp, &config);
+	micsupp->regulator = devm_regulator_register(&pdev->dev,
+						     &arizona_micsupp,
+						     &config);
 	if (IS_ERR(micsupp->regulator)) {
 		ret = PTR_ERR(micsupp->regulator);
 		dev_err(arizona->dev, "Failed to register mic supply: %d\n",
@@ -238,18 +240,8 @@
 	return 0;
 }
 
-static int arizona_micsupp_remove(struct platform_device *pdev)
-{
-	struct arizona_micsupp *micsupp = platform_get_drvdata(pdev);
-
-	regulator_unregister(micsupp->regulator);
-
-	return 0;
-}
-
 static struct platform_driver arizona_micsupp_driver = {
 	.probe = arizona_micsupp_probe,
-	.remove = arizona_micsupp_remove,
 	.driver		= {
 		.name	= "arizona-micsupp",
 		.owner	= THIS_MODULE,
diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c
index 8406cd7..c77a584 100644
--- a/drivers/regulator/as3711-regulator.c
+++ b/drivers/regulator/as3711-regulator.c
@@ -117,26 +117,19 @@
 };
 
 static const struct regulator_linear_range as3711_sd_ranges[] = {
-	{ .min_uV = 612500, .max_uV = 1400000,
-	  .min_sel = 0x1, .max_sel = 0x40, .uV_step = 12500 },
-	{ .min_uV = 1425000, .max_uV = 2600000,
-	  .min_sel = 0x41, .max_sel = 0x70, .uV_step = 25000 },
-	{ .min_uV = 2650000, .max_uV = 3350000,
-	  .min_sel = 0x71, .max_sel = 0x7f, .uV_step = 50000 },
+	REGULATOR_LINEAR_RANGE(612500, 0x1, 0x40, 12500),
+	REGULATOR_LINEAR_RANGE(1425000, 0x41, 0x70, 25000),
+	REGULATOR_LINEAR_RANGE(2650000, 0x71, 0x7f, 50000),
 };
 
 static const struct regulator_linear_range as3711_aldo_ranges[] = {
-	{ .min_uV = 1200000, .max_uV = 1950000,
-	  .min_sel = 0, .max_sel = 0xf, .uV_step = 50000 },
-	{ .min_uV = 1800000, .max_uV = 3300000,
-	  .min_sel = 0x10, .max_sel = 0x1f, .uV_step = 100000 },
+	REGULATOR_LINEAR_RANGE(1200000, 0, 0xf, 50000),
+	REGULATOR_LINEAR_RANGE(1800000, 0x10, 0x1f, 100000),
 };
 
 static const struct regulator_linear_range as3711_dldo_ranges[] = {
-	{ .min_uV = 900000, .max_uV = 1700000,
-	  .min_sel = 0, .max_sel = 0x10, .uV_step = 50000 },
-	{ .min_uV = 1750000, .max_uV = 3300000,
-	  .min_sel = 0x20, .max_sel = 0x3f, .uV_step = 50000 },
+	REGULATOR_LINEAR_RANGE(900000, 0, 0x10, 50000),
+	REGULATOR_LINEAR_RANGE(1750000, 0x20, 0x3f, 50000),
 };
 
 #define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx)	\
@@ -273,33 +266,16 @@
 		config.regmap = as3711->regmap;
 		config.of_node = of_node[id];
 
-		rdev = regulator_register(&ri->desc, &config);
+		rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
 		if (IS_ERR(rdev)) {
 			dev_err(&pdev->dev, "Failed to register regulator %s\n",
 				ri->desc.name);
-			ret = PTR_ERR(rdev);
-			goto eregreg;
+			return PTR_ERR(rdev);
 		}
 		reg->rdev = rdev;
 	}
 	platform_set_drvdata(pdev, regs);
 	return 0;
-
-eregreg:
-	while (--id >= 0)
-		regulator_unregister(regs[id].rdev);
-
-	return ret;
-}
-
-static int as3711_regulator_remove(struct platform_device *pdev)
-{
-	struct as3711_regulator *regs = platform_get_drvdata(pdev);
-	int id;
-
-	for (id = 0; id < AS3711_REGULATOR_NUM; ++id)
-		regulator_unregister(regs[id].rdev);
-	return 0;
 }
 
 static struct platform_driver as3711_regulator_driver = {
@@ -308,7 +284,6 @@
 		.owner	= THIS_MODULE,
 	},
 	.probe		= as3711_regulator_probe,
-	.remove		= as3711_regulator_remove,
 };
 
 static int __init as3711_regulator_init(void)
diff --git a/drivers/regulator/as3722-regulator.c b/drivers/regulator/as3722-regulator.c
new file mode 100644
index 0000000..5917fe3
--- /dev/null
+++ b/drivers/regulator/as3722-regulator.c
@@ -0,0 +1,908 @@
+/*
+ * Voltage regulator support for AMS AS3722 PMIC
+ *
+ * Copyright (C) 2013 ams
+ *
+ * Author: Florian Lobmaier <florian.lobmaier@ams.com>
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mfd/as3722.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/slab.h>
+
+/* Regulator IDs */
+enum as3722_regulators_id {
+	AS3722_REGULATOR_ID_SD0,
+	AS3722_REGULATOR_ID_SD1,
+	AS3722_REGULATOR_ID_SD2,
+	AS3722_REGULATOR_ID_SD3,
+	AS3722_REGULATOR_ID_SD4,
+	AS3722_REGULATOR_ID_SD5,
+	AS3722_REGULATOR_ID_SD6,
+	AS3722_REGULATOR_ID_LDO0,
+	AS3722_REGULATOR_ID_LDO1,
+	AS3722_REGULATOR_ID_LDO2,
+	AS3722_REGULATOR_ID_LDO3,
+	AS3722_REGULATOR_ID_LDO4,
+	AS3722_REGULATOR_ID_LDO5,
+	AS3722_REGULATOR_ID_LDO6,
+	AS3722_REGULATOR_ID_LDO7,
+	AS3722_REGULATOR_ID_LDO9,
+	AS3722_REGULATOR_ID_LDO10,
+	AS3722_REGULATOR_ID_LDO11,
+	AS3722_REGULATOR_ID_MAX,
+};
+
+struct as3722_register_mapping {
+	u8 regulator_id;
+	const char *name;
+	const char *sname;
+	u8 vsel_reg;
+	u8 vsel_mask;
+	int n_voltages;
+	u32 enable_reg;
+	u8 enable_mask;
+	u32 control_reg;
+	u8 mode_mask;
+	u32 sleep_ctrl_reg;
+	u8 sleep_ctrl_mask;
+};
+
+struct as3722_regulator_config_data {
+	struct regulator_init_data *reg_init;
+	bool enable_tracking;
+	int ext_control;
+};
+
+struct as3722_regulators {
+	struct device *dev;
+	struct as3722 *as3722;
+	struct regulator_dev *rdevs[AS3722_REGULATOR_ID_MAX];
+	struct regulator_desc desc[AS3722_REGULATOR_ID_MAX];
+	struct as3722_regulator_config_data
+			reg_config_data[AS3722_REGULATOR_ID_MAX];
+};
+
+static const struct as3722_register_mapping as3722_reg_lookup[] = {
+	{
+		.regulator_id = AS3722_REGULATOR_ID_SD0,
+		.name = "as3722-sd0",
+		.vsel_reg = AS3722_SD0_VOLTAGE_REG,
+		.vsel_mask = AS3722_SD_VSEL_MASK,
+		.enable_reg = AS3722_SD_CONTROL_REG,
+		.enable_mask = AS3722_SDn_CTRL(0),
+		.sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
+		.sleep_ctrl_mask = AS3722_SD0_EXT_ENABLE_MASK,
+		.control_reg = AS3722_SD0_CONTROL_REG,
+		.mode_mask = AS3722_SD0_MODE_FAST,
+		.n_voltages = AS3722_SD0_VSEL_MAX + 1,
+	},
+	{
+		.regulator_id = AS3722_REGULATOR_ID_SD1,
+		.name = "as3722-sd1",
+		.vsel_reg = AS3722_SD1_VOLTAGE_REG,
+		.vsel_mask = AS3722_SD_VSEL_MASK,
+		.enable_reg = AS3722_SD_CONTROL_REG,
+		.enable_mask = AS3722_SDn_CTRL(1),
+		.sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
+		.sleep_ctrl_mask = AS3722_SD1_EXT_ENABLE_MASK,
+		.control_reg = AS3722_SD1_CONTROL_REG,
+		.mode_mask = AS3722_SD1_MODE_FAST,
+		.n_voltages = AS3722_SD0_VSEL_MAX + 1,
+	},
+	{
+		.regulator_id = AS3722_REGULATOR_ID_SD2,
+		.name = "as3722-sd2",
+		.sname = "vsup-sd2",
+		.vsel_reg = AS3722_SD2_VOLTAGE_REG,
+		.vsel_mask = AS3722_SD_VSEL_MASK,
+		.enable_reg = AS3722_SD_CONTROL_REG,
+		.enable_mask = AS3722_SDn_CTRL(2),
+		.sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
+		.sleep_ctrl_mask = AS3722_SD2_EXT_ENABLE_MASK,
+		.control_reg = AS3722_SD23_CONTROL_REG,
+		.mode_mask = AS3722_SD2_MODE_FAST,
+		.n_voltages = AS3722_SD2_VSEL_MAX + 1,
+	},
+	{
+		.regulator_id = AS3722_REGULATOR_ID_SD3,
+		.name = "as3722-sd3",
+		.sname = "vsup-sd3",
+		.vsel_reg = AS3722_SD3_VOLTAGE_REG,
+		.vsel_mask = AS3722_SD_VSEL_MASK,
+		.enable_reg = AS3722_SD_CONTROL_REG,
+		.enable_mask = AS3722_SDn_CTRL(3),
+		.sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
+		.sleep_ctrl_mask = AS3722_SD3_EXT_ENABLE_MASK,
+		.control_reg = AS3722_SD23_CONTROL_REG,
+		.mode_mask = AS3722_SD3_MODE_FAST,
+		.n_voltages = AS3722_SD2_VSEL_MAX + 1,
+	},
+	{
+		.regulator_id = AS3722_REGULATOR_ID_SD4,
+		.name = "as3722-sd4",
+		.sname = "vsup-sd4",
+		.vsel_reg = AS3722_SD4_VOLTAGE_REG,
+		.vsel_mask = AS3722_SD_VSEL_MASK,
+		.enable_reg = AS3722_SD_CONTROL_REG,
+		.enable_mask = AS3722_SDn_CTRL(4),
+		.sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,
+		.sleep_ctrl_mask = AS3722_SD4_EXT_ENABLE_MASK,
+		.control_reg = AS3722_SD4_CONTROL_REG,
+		.mode_mask = AS3722_SD4_MODE_FAST,
+		.n_voltages = AS3722_SD2_VSEL_MAX + 1,
+	},
+	{
+		.regulator_id = AS3722_REGULATOR_ID_SD5,
+		.name = "as3722-sd5",
+		.sname = "vsup-sd5",
+		.vsel_reg = AS3722_SD5_VOLTAGE_REG,
+		.vsel_mask = AS3722_SD_VSEL_MASK,
+		.enable_reg = AS3722_SD_CONTROL_REG,
+		.enable_mask = AS3722_SDn_CTRL(5),
+		.sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,
+		.sleep_ctrl_mask = AS3722_SD5_EXT_ENABLE_MASK,
+		.control_reg = AS3722_SD5_CONTROL_REG,
+		.mode_mask = AS3722_SD5_MODE_FAST,
+		.n_voltages = AS3722_SD2_VSEL_MAX + 1,
+	},
+	{
+		.regulator_id = AS3722_REGULATOR_ID_SD6,
+		.name = "as3722-sd6",
+		.vsel_reg = AS3722_SD6_VOLTAGE_REG,
+		.vsel_mask = AS3722_SD_VSEL_MASK,
+		.enable_reg = AS3722_SD_CONTROL_REG,
+		.enable_mask = AS3722_SDn_CTRL(6),
+		.sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,
+		.sleep_ctrl_mask = AS3722_SD6_EXT_ENABLE_MASK,
+		.control_reg = AS3722_SD6_CONTROL_REG,
+		.mode_mask = AS3722_SD6_MODE_FAST,
+		.n_voltages = AS3722_SD0_VSEL_MAX + 1,
+	},
+	{
+		.regulator_id = AS3722_REGULATOR_ID_LDO0,
+		.name = "as3722-ldo0",
+		.sname = "vin-ldo0",
+		.vsel_reg = AS3722_LDO0_VOLTAGE_REG,
+		.vsel_mask = AS3722_LDO0_VSEL_MASK,
+		.enable_reg = AS3722_LDOCONTROL0_REG,
+		.enable_mask = AS3722_LDO0_CTRL,
+		.sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
+		.sleep_ctrl_mask = AS3722_LDO0_EXT_ENABLE_MASK,
+		.n_voltages = AS3722_LDO0_NUM_VOLT,
+	},
+	{
+		.regulator_id = AS3722_REGULATOR_ID_LDO1,
+		.name = "as3722-ldo1",
+		.sname = "vin-ldo1-6",
+		.vsel_reg = AS3722_LDO1_VOLTAGE_REG,
+		.vsel_mask = AS3722_LDO_VSEL_MASK,
+		.enable_reg = AS3722_LDOCONTROL0_REG,
+		.enable_mask = AS3722_LDO1_CTRL,
+		.sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
+		.sleep_ctrl_mask = AS3722_LDO1_EXT_ENABLE_MASK,
+		.n_voltages = AS3722_LDO_NUM_VOLT,
+	},
+	{
+		.regulator_id = AS3722_REGULATOR_ID_LDO2,
+		.name = "as3722-ldo2",
+		.sname = "vin-ldo2-5-7",
+		.vsel_reg = AS3722_LDO2_VOLTAGE_REG,
+		.vsel_mask = AS3722_LDO_VSEL_MASK,
+		.enable_reg = AS3722_LDOCONTROL0_REG,
+		.enable_mask = AS3722_LDO2_CTRL,
+		.sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
+		.sleep_ctrl_mask = AS3722_LDO2_EXT_ENABLE_MASK,
+		.n_voltages = AS3722_LDO_NUM_VOLT,
+	},
+	{
+		.regulator_id = AS3722_REGULATOR_ID_LDO3,
+		.name = "as3722-ldo3",
+		.name = "vin-ldo3-4",
+		.vsel_reg = AS3722_LDO3_VOLTAGE_REG,
+		.vsel_mask = AS3722_LDO3_VSEL_MASK,
+		.enable_reg = AS3722_LDOCONTROL0_REG,
+		.enable_mask = AS3722_LDO3_CTRL,
+		.sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
+		.sleep_ctrl_mask = AS3722_LDO3_EXT_ENABLE_MASK,
+		.n_voltages = AS3722_LDO3_NUM_VOLT,
+	},
+	{
+		.regulator_id = AS3722_REGULATOR_ID_LDO4,
+		.name = "as3722-ldo4",
+		.name = "vin-ldo3-4",
+		.vsel_reg = AS3722_LDO4_VOLTAGE_REG,
+		.vsel_mask = AS3722_LDO_VSEL_MASK,
+		.enable_reg = AS3722_LDOCONTROL0_REG,
+		.enable_mask = AS3722_LDO4_CTRL,
+		.sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
+		.sleep_ctrl_mask = AS3722_LDO4_EXT_ENABLE_MASK,
+		.n_voltages = AS3722_LDO_NUM_VOLT,
+	},
+	{
+		.regulator_id = AS3722_REGULATOR_ID_LDO5,
+		.name = "as3722-ldo5",
+		.sname = "vin-ldo2-5-7",
+		.vsel_reg = AS3722_LDO5_VOLTAGE_REG,
+		.vsel_mask = AS3722_LDO_VSEL_MASK,
+		.enable_reg = AS3722_LDOCONTROL0_REG,
+		.enable_mask = AS3722_LDO5_CTRL,
+		.sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
+		.sleep_ctrl_mask = AS3722_LDO5_EXT_ENABLE_MASK,
+		.n_voltages = AS3722_LDO_NUM_VOLT,
+	},
+	{
+		.regulator_id = AS3722_REGULATOR_ID_LDO6,
+		.name = "as3722-ldo6",
+		.sname = "vin-ldo1-6",
+		.vsel_reg = AS3722_LDO6_VOLTAGE_REG,
+		.vsel_mask = AS3722_LDO_VSEL_MASK,
+		.enable_reg = AS3722_LDOCONTROL0_REG,
+		.enable_mask = AS3722_LDO6_CTRL,
+		.sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
+		.sleep_ctrl_mask = AS3722_LDO6_EXT_ENABLE_MASK,
+		.n_voltages = AS3722_LDO_NUM_VOLT,
+	},
+	{
+		.regulator_id = AS3722_REGULATOR_ID_LDO7,
+		.name = "as3722-ldo7",
+		.sname = "vin-ldo2-5-7",
+		.vsel_reg = AS3722_LDO7_VOLTAGE_REG,
+		.vsel_mask = AS3722_LDO_VSEL_MASK,
+		.enable_reg = AS3722_LDOCONTROL0_REG,
+		.enable_mask = AS3722_LDO7_CTRL,
+		.sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
+		.sleep_ctrl_mask = AS3722_LDO7_EXT_ENABLE_MASK,
+		.n_voltages = AS3722_LDO_NUM_VOLT,
+	},
+	{
+		.regulator_id = AS3722_REGULATOR_ID_LDO9,
+		.name = "as3722-ldo9",
+		.sname = "vin-ldo9-10",
+		.vsel_reg = AS3722_LDO9_VOLTAGE_REG,
+		.vsel_mask = AS3722_LDO_VSEL_MASK,
+		.enable_reg = AS3722_LDOCONTROL1_REG,
+		.enable_mask = AS3722_LDO9_CTRL,
+		.sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,
+		.sleep_ctrl_mask = AS3722_LDO9_EXT_ENABLE_MASK,
+		.n_voltages = AS3722_LDO_NUM_VOLT,
+	},
+	{
+		.regulator_id = AS3722_REGULATOR_ID_LDO10,
+		.name = "as3722-ldo10",
+		.sname = "vin-ldo9-10",
+		.vsel_reg = AS3722_LDO10_VOLTAGE_REG,
+		.vsel_mask = AS3722_LDO_VSEL_MASK,
+		.enable_reg = AS3722_LDOCONTROL1_REG,
+		.enable_mask = AS3722_LDO10_CTRL,
+		.sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,
+		.sleep_ctrl_mask = AS3722_LDO10_EXT_ENABLE_MASK,
+		.n_voltages = AS3722_LDO_NUM_VOLT,
+	},
+	{
+		.regulator_id = AS3722_REGULATOR_ID_LDO11,
+		.name = "as3722-ldo11",
+		.sname = "vin-ldo11",
+		.vsel_reg = AS3722_LDO11_VOLTAGE_REG,
+		.vsel_mask = AS3722_LDO_VSEL_MASK,
+		.enable_reg = AS3722_LDOCONTROL1_REG,
+		.enable_mask = AS3722_LDO11_CTRL,
+		.sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,
+		.sleep_ctrl_mask = AS3722_LDO11_EXT_ENABLE_MASK,
+		.n_voltages = AS3722_LDO_NUM_VOLT,
+	},
+};
+
+
+static const int as3722_ldo_current[] = { 150000, 300000 };
+static const int as3722_sd016_current[] = { 2500000, 3000000, 3500000 };
+
+static int as3722_current_to_index(int min_uA, int max_uA,
+		const int *curr_table, int n_currents)
+{
+	int i;
+
+	for (i = n_currents - 1; i >= 0; i--) {
+		if ((min_uA <= curr_table[i]) && (curr_table[i] <= max_uA))
+			return i;
+	}
+	return -EINVAL;
+}
+
+static int as3722_ldo_get_current_limit(struct regulator_dev *rdev)
+{
+	struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+	struct as3722 *as3722 = as3722_regs->as3722;
+	int id = rdev_get_id(rdev);
+	u32 val;
+	int ret;
+
+	ret = as3722_read(as3722, as3722_reg_lookup[id].vsel_reg, &val);
+	if (ret < 0) {
+		dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",
+			as3722_reg_lookup[id].vsel_reg, ret);
+		return ret;
+	}
+	if (val & AS3722_LDO_ILIMIT_MASK)
+		return 300000;
+	return 150000;
+}
+
+static int as3722_ldo_set_current_limit(struct regulator_dev *rdev,
+		int min_uA, int max_uA)
+{
+	struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+	struct as3722 *as3722 = as3722_regs->as3722;
+	int id = rdev_get_id(rdev);
+	int ret;
+	u32 reg = 0;
+
+	ret = as3722_current_to_index(min_uA, max_uA, as3722_ldo_current,
+				ARRAY_SIZE(as3722_ldo_current));
+	if (ret < 0) {
+		dev_err(as3722_regs->dev,
+			"Current range min:max = %d:%d does not support\n",
+			min_uA, max_uA);
+		return ret;
+	}
+	if (ret)
+		reg = AS3722_LDO_ILIMIT_BIT;
+	return as3722_update_bits(as3722, as3722_reg_lookup[id].vsel_reg,
+			AS3722_LDO_ILIMIT_MASK, reg);
+}
+
+static struct regulator_ops as3722_ldo0_ops = {
+	.is_enabled = regulator_is_enabled_regmap,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.list_voltage = regulator_list_voltage_linear,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_current_limit = as3722_ldo_get_current_limit,
+	.set_current_limit = as3722_ldo_set_current_limit,
+};
+
+static struct regulator_ops as3722_ldo0_extcntrl_ops = {
+	.list_voltage = regulator_list_voltage_linear,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_current_limit = as3722_ldo_get_current_limit,
+	.set_current_limit = as3722_ldo_set_current_limit,
+};
+
+static int as3722_ldo3_set_tracking_mode(struct as3722_regulators *as3722_reg,
+		int id, u8 mode)
+{
+	struct as3722 *as3722 = as3722_reg->as3722;
+
+	switch (mode) {
+	case AS3722_LDO3_MODE_PMOS:
+	case AS3722_LDO3_MODE_PMOS_TRACKING:
+	case AS3722_LDO3_MODE_NMOS:
+	case AS3722_LDO3_MODE_SWITCH:
+		return as3722_update_bits(as3722,
+			as3722_reg_lookup[id].vsel_reg,
+			AS3722_LDO3_MODE_MASK, mode);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static int as3722_ldo3_get_current_limit(struct regulator_dev *rdev)
+{
+	return 150000;
+}
+
+static struct regulator_ops as3722_ldo3_ops = {
+	.is_enabled = regulator_is_enabled_regmap,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.list_voltage = regulator_list_voltage_linear,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_current_limit = as3722_ldo3_get_current_limit,
+};
+
+static struct regulator_ops as3722_ldo3_extcntrl_ops = {
+	.list_voltage = regulator_list_voltage_linear,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_current_limit = as3722_ldo3_get_current_limit,
+};
+
+static const struct regulator_linear_range as3722_ldo_ranges[] = {
+	REGULATOR_LINEAR_RANGE(825000, 0x01, 0x24, 25000),
+	REGULATOR_LINEAR_RANGE(1725000, 0x40, 0x7F, 25000),
+};
+
+static struct regulator_ops as3722_ldo_ops = {
+	.is_enabled = regulator_is_enabled_regmap,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.map_voltage = regulator_map_voltage_linear_range,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.list_voltage = regulator_list_voltage_linear_range,
+	.get_current_limit = as3722_ldo_get_current_limit,
+	.set_current_limit = as3722_ldo_set_current_limit,
+};
+
+static struct regulator_ops as3722_ldo_extcntrl_ops = {
+	.map_voltage = regulator_map_voltage_linear_range,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.list_voltage = regulator_list_voltage_linear_range,
+	.get_current_limit = as3722_ldo_get_current_limit,
+	.set_current_limit = as3722_ldo_set_current_limit,
+};
+
+static unsigned int as3722_sd_get_mode(struct regulator_dev *rdev)
+{
+	struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+	struct as3722 *as3722 = as3722_regs->as3722;
+	int id = rdev_get_id(rdev);
+	u32 val;
+	int ret;
+
+	if (!as3722_reg_lookup[id].control_reg)
+		return -ENOTSUPP;
+
+	ret = as3722_read(as3722, as3722_reg_lookup[id].control_reg, &val);
+	if (ret < 0) {
+		dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",
+			as3722_reg_lookup[id].control_reg, ret);
+		return ret;
+	}
+
+	if (val & as3722_reg_lookup[id].mode_mask)
+		return REGULATOR_MODE_FAST;
+	else
+		return REGULATOR_MODE_NORMAL;
+}
+
+static int as3722_sd_set_mode(struct regulator_dev *rdev,
+		unsigned int mode)
+{
+	struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+	struct as3722 *as3722 = as3722_regs->as3722;
+	u8 id = rdev_get_id(rdev);
+	u8 val = 0;
+	int ret;
+
+	if (!as3722_reg_lookup[id].control_reg)
+		return -ERANGE;
+
+	switch (mode) {
+	case REGULATOR_MODE_FAST:
+		val = as3722_reg_lookup[id].mode_mask;
+	case REGULATOR_MODE_NORMAL: /* fall down */
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = as3722_update_bits(as3722, as3722_reg_lookup[id].control_reg,
+			as3722_reg_lookup[id].mode_mask, val);
+	if (ret < 0) {
+		dev_err(as3722_regs->dev, "Reg 0x%02x update failed: %d\n",
+			as3722_reg_lookup[id].control_reg, ret);
+		return ret;
+	}
+	return ret;
+}
+
+static int as3722_sd016_get_current_limit(struct regulator_dev *rdev)
+{
+	struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+	struct as3722 *as3722 = as3722_regs->as3722;
+	int id = rdev_get_id(rdev);
+	u32 val, reg;
+	int mask;
+	int ret;
+
+	switch (id) {
+	case AS3722_REGULATOR_ID_SD0:
+		reg = AS3722_OVCURRENT_REG;
+		mask = AS3722_OVCURRENT_SD0_TRIP_MASK;
+		break;
+	case AS3722_REGULATOR_ID_SD1:
+		reg = AS3722_OVCURRENT_REG;
+		mask = AS3722_OVCURRENT_SD1_TRIP_MASK;
+		break;
+	case AS3722_REGULATOR_ID_SD6:
+		reg = AS3722_OVCURRENT_DEB_REG;
+		mask = AS3722_OVCURRENT_SD6_TRIP_MASK;
+		break;
+	default:
+		return -EINVAL;
+	}
+	ret = as3722_read(as3722, reg, &val);
+	if (ret < 0) {
+		dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",
+			reg, ret);
+		return ret;
+	}
+	val &= mask;
+	val >>= ffs(mask) - 1;
+	if (val == 3)
+		return -EINVAL;
+	return as3722_sd016_current[val];
+}
+
+static int as3722_sd016_set_current_limit(struct regulator_dev *rdev,
+		int min_uA, int max_uA)
+{
+	struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+	struct as3722 *as3722 = as3722_regs->as3722;
+	int id = rdev_get_id(rdev);
+	int ret;
+	int val;
+	int mask;
+	u32 reg;
+
+	ret = as3722_current_to_index(min_uA, max_uA, as3722_sd016_current,
+				ARRAY_SIZE(as3722_sd016_current));
+	if (ret < 0) {
+		dev_err(as3722_regs->dev,
+			"Current range min:max = %d:%d does not support\n",
+			min_uA, max_uA);
+		return ret;
+	}
+
+	switch (id) {
+	case AS3722_REGULATOR_ID_SD0:
+		reg = AS3722_OVCURRENT_REG;
+		mask = AS3722_OVCURRENT_SD0_TRIP_MASK;
+		break;
+	case AS3722_REGULATOR_ID_SD1:
+		reg = AS3722_OVCURRENT_REG;
+		mask = AS3722_OVCURRENT_SD1_TRIP_MASK;
+		break;
+	case AS3722_REGULATOR_ID_SD6:
+		reg = AS3722_OVCURRENT_DEB_REG;
+		mask = AS3722_OVCURRENT_SD6_TRIP_MASK;
+		break;
+	default:
+		return -EINVAL;
+	}
+	val = ret & mask;
+	val <<= ffs(mask) - 1;
+	return as3722_update_bits(as3722, reg, mask, val);
+}
+
+static const struct regulator_linear_range as3722_sd2345_ranges[] = {
+	REGULATOR_LINEAR_RANGE(612500, 0x01, 0x40, 12500),
+	REGULATOR_LINEAR_RANGE(1425000, 0x41, 0x70, 25000),
+	REGULATOR_LINEAR_RANGE(2650000, 0x71, 0x7F, 50000),
+};
+
+static struct regulator_ops as3722_sd016_ops = {
+	.is_enabled = regulator_is_enabled_regmap,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.list_voltage = regulator_list_voltage_linear,
+	.map_voltage = regulator_map_voltage_linear,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_current_limit = as3722_sd016_get_current_limit,
+	.set_current_limit = as3722_sd016_set_current_limit,
+	.get_mode = as3722_sd_get_mode,
+	.set_mode = as3722_sd_set_mode,
+};
+
+static struct regulator_ops as3722_sd016_extcntrl_ops = {
+	.list_voltage = regulator_list_voltage_linear,
+	.map_voltage = regulator_map_voltage_linear,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_current_limit = as3722_sd016_get_current_limit,
+	.set_current_limit = as3722_sd016_set_current_limit,
+	.get_mode = as3722_sd_get_mode,
+	.set_mode = as3722_sd_set_mode,
+};
+
+static struct regulator_ops as3722_sd2345_ops = {
+	.is_enabled = regulator_is_enabled_regmap,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.list_voltage = regulator_list_voltage_linear_range,
+	.map_voltage = regulator_map_voltage_linear_range,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.get_mode = as3722_sd_get_mode,
+	.set_mode = as3722_sd_set_mode,
+};
+
+static struct regulator_ops as3722_sd2345_extcntrl_ops = {
+	.list_voltage = regulator_list_voltage_linear_range,
+	.map_voltage = regulator_map_voltage_linear_range,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.get_mode = as3722_sd_get_mode,
+	.set_mode = as3722_sd_set_mode,
+};
+
+static int as3722_extreg_init(struct as3722_regulators *as3722_regs, int id,
+		int ext_pwr_ctrl)
+{
+	int ret;
+	unsigned int val;
+
+	if ((ext_pwr_ctrl < AS3722_EXT_CONTROL_ENABLE1) ||
+		(ext_pwr_ctrl > AS3722_EXT_CONTROL_ENABLE3))
+		return -EINVAL;
+
+	val =  ext_pwr_ctrl << (ffs(as3722_reg_lookup[id].sleep_ctrl_mask) - 1);
+	ret = as3722_update_bits(as3722_regs->as3722,
+			as3722_reg_lookup[id].sleep_ctrl_reg,
+			as3722_reg_lookup[id].sleep_ctrl_mask, val);
+	if (ret < 0)
+		dev_err(as3722_regs->dev, "Reg 0x%02x update failed: %d\n",
+			as3722_reg_lookup[id].sleep_ctrl_reg, ret);
+	return ret;
+}
+
+static struct of_regulator_match as3722_regulator_matches[] = {
+	{ .name = "sd0", },
+	{ .name = "sd1", },
+	{ .name = "sd2", },
+	{ .name = "sd3", },
+	{ .name = "sd4", },
+	{ .name = "sd5", },
+	{ .name = "sd6", },
+	{ .name = "ldo0", },
+	{ .name = "ldo1", },
+	{ .name = "ldo2", },
+	{ .name = "ldo3", },
+	{ .name = "ldo4", },
+	{ .name = "ldo5", },
+	{ .name = "ldo6", },
+	{ .name = "ldo7", },
+	{ .name = "ldo9", },
+	{ .name = "ldo10", },
+	{ .name = "ldo11", },
+};
+
+static int as3722_get_regulator_dt_data(struct platform_device *pdev,
+		struct as3722_regulators *as3722_regs)
+{
+	struct device_node *np;
+	struct as3722_regulator_config_data *reg_config;
+	u32 prop;
+	int id;
+	int ret;
+
+	np = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
+	if (!np) {
+		dev_err(&pdev->dev, "Device is not having regulators node\n");
+		return -ENODEV;
+	}
+	pdev->dev.of_node = np;
+
+	ret = of_regulator_match(&pdev->dev, np, as3722_regulator_matches,
+			ARRAY_SIZE(as3722_regulator_matches));
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Parsing of regulator node failed: %d\n",
+			ret);
+		return ret;
+	}
+
+	for (id = 0; id < ARRAY_SIZE(as3722_regulator_matches); ++id) {
+		struct device_node *reg_node;
+
+		reg_config = &as3722_regs->reg_config_data[id];
+		reg_config->reg_init = as3722_regulator_matches[id].init_data;
+		reg_node = as3722_regulator_matches[id].of_node;
+
+		if (!reg_config->reg_init || !reg_node)
+			continue;
+
+		ret = of_property_read_u32(reg_node, "ams,ext-control", &prop);
+		if (!ret) {
+			if (prop < 3)
+				reg_config->ext_control = prop;
+			else
+				dev_warn(&pdev->dev,
+					"ext-control have invalid option: %u\n",
+					prop);
+		}
+		reg_config->enable_tracking =
+			of_property_read_bool(reg_node, "ams,enable-tracking");
+	}
+	return 0;
+}
+
+static int as3722_regulator_probe(struct platform_device *pdev)
+{
+	struct as3722 *as3722 = dev_get_drvdata(pdev->dev.parent);
+	struct as3722_regulators *as3722_regs;
+	struct as3722_regulator_config_data *reg_config;
+	struct regulator_dev *rdev;
+	struct regulator_config config = { };
+	struct regulator_ops *ops;
+	int id;
+	int ret;
+
+	as3722_regs = devm_kzalloc(&pdev->dev, sizeof(*as3722_regs),
+				GFP_KERNEL);
+	if (!as3722_regs)
+		return -ENOMEM;
+
+	as3722_regs->dev = &pdev->dev;
+	as3722_regs->as3722 = as3722;
+	platform_set_drvdata(pdev, as3722_regs);
+
+	ret = as3722_get_regulator_dt_data(pdev, as3722_regs);
+	if (ret < 0)
+		return ret;
+
+	config.dev = &pdev->dev;
+	config.driver_data = as3722_regs;
+	config.regmap = as3722->regmap;
+
+	for (id = 0; id < AS3722_REGULATOR_ID_MAX; id++) {
+		reg_config = &as3722_regs->reg_config_data[id];
+
+		as3722_regs->desc[id].name = as3722_reg_lookup[id].name;
+		as3722_regs->desc[id].supply_name = as3722_reg_lookup[id].sname;
+		as3722_regs->desc[id].id = as3722_reg_lookup[id].regulator_id;
+		as3722_regs->desc[id].n_voltages =
+					as3722_reg_lookup[id].n_voltages;
+		as3722_regs->desc[id].type = REGULATOR_VOLTAGE;
+		as3722_regs->desc[id].owner = THIS_MODULE;
+		as3722_regs->desc[id].enable_reg =
+					as3722_reg_lookup[id].enable_reg;
+		as3722_regs->desc[id].enable_mask =
+					as3722_reg_lookup[id].enable_mask;
+		as3722_regs->desc[id].vsel_reg = as3722_reg_lookup[id].vsel_reg;
+		as3722_regs->desc[id].vsel_mask =
+					as3722_reg_lookup[id].vsel_mask;
+		switch (id) {
+		case AS3722_REGULATOR_ID_LDO0:
+			if (reg_config->ext_control)
+				ops = &as3722_ldo0_extcntrl_ops;
+			else
+				ops = &as3722_ldo0_ops;
+			as3722_regs->desc[id].min_uV = 825000;
+			as3722_regs->desc[id].uV_step = 25000;
+			as3722_regs->desc[id].linear_min_sel = 1;
+			as3722_regs->desc[id].enable_time = 500;
+			break;
+		case AS3722_REGULATOR_ID_LDO3:
+			if (reg_config->ext_control)
+				ops = &as3722_ldo3_extcntrl_ops;
+			else
+				ops = &as3722_ldo3_ops;
+			as3722_regs->desc[id].min_uV = 620000;
+			as3722_regs->desc[id].uV_step = 20000;
+			as3722_regs->desc[id].linear_min_sel = 1;
+			as3722_regs->desc[id].enable_time = 500;
+			if (reg_config->enable_tracking) {
+				ret = as3722_ldo3_set_tracking_mode(as3722_regs,
+					id, AS3722_LDO3_MODE_PMOS_TRACKING);
+				if (ret < 0) {
+					dev_err(&pdev->dev,
+						"LDO3 tracking failed: %d\n",
+						ret);
+					return ret;
+				}
+			}
+			break;
+		case AS3722_REGULATOR_ID_SD0:
+		case AS3722_REGULATOR_ID_SD1:
+		case AS3722_REGULATOR_ID_SD6:
+			if (reg_config->ext_control)
+				ops = &as3722_sd016_extcntrl_ops;
+			else
+				ops = &as3722_sd016_ops;
+			as3722_regs->desc[id].min_uV = 610000;
+			as3722_regs->desc[id].uV_step = 10000;
+			as3722_regs->desc[id].linear_min_sel = 1;
+			break;
+		case AS3722_REGULATOR_ID_SD2:
+		case AS3722_REGULATOR_ID_SD3:
+		case AS3722_REGULATOR_ID_SD4:
+		case AS3722_REGULATOR_ID_SD5:
+			if (reg_config->ext_control)
+				ops = &as3722_sd2345_extcntrl_ops;
+			else
+				ops = &as3722_sd2345_ops;
+			as3722_regs->desc[id].linear_ranges =
+						as3722_sd2345_ranges;
+			as3722_regs->desc[id].n_linear_ranges =
+					ARRAY_SIZE(as3722_sd2345_ranges);
+			break;
+		default:
+			if (reg_config->ext_control)
+				ops = &as3722_ldo_extcntrl_ops;
+			else
+				ops = &as3722_ldo_ops;
+			as3722_regs->desc[id].min_uV = 825000;
+			as3722_regs->desc[id].uV_step = 25000;
+			as3722_regs->desc[id].linear_min_sel = 1;
+			as3722_regs->desc[id].enable_time = 500;
+			as3722_regs->desc[id].linear_ranges = as3722_ldo_ranges;
+			as3722_regs->desc[id].n_linear_ranges =
+						ARRAY_SIZE(as3722_ldo_ranges);
+			break;
+		}
+		as3722_regs->desc[id].ops = ops;
+		config.init_data = reg_config->reg_init;
+		config.of_node = as3722_regulator_matches[id].of_node;
+		rdev = devm_regulator_register(&pdev->dev,
+					&as3722_regs->desc[id], &config);
+		if (IS_ERR(rdev)) {
+			ret = PTR_ERR(rdev);
+			dev_err(&pdev->dev, "regulator %d register failed %d\n",
+				id, ret);
+			return ret;
+		}
+
+		as3722_regs->rdevs[id] = rdev;
+		if (reg_config->ext_control) {
+			ret = regulator_enable_regmap(rdev);
+			if (ret < 0) {
+				dev_err(&pdev->dev,
+					"Regulator %d enable failed: %d\n",
+					id, ret);
+				return ret;
+			}
+			ret = as3722_extreg_init(as3722_regs, id,
+					reg_config->ext_control);
+			if (ret < 0) {
+				dev_err(&pdev->dev,
+					"AS3722 ext control failed: %d", ret);
+				return ret;
+			}
+		}
+	}
+	return 0;
+}
+
+static const struct of_device_id of_as3722_regulator_match[] = {
+	{ .compatible = "ams,as3722-regulator", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_as3722_regulator_match);
+
+static struct platform_driver as3722_regulator_driver = {
+	.driver = {
+		.name = "as3722-regulator",
+		.owner = THIS_MODULE,
+		.of_match_table = of_as3722_regulator_match,
+	},
+	.probe = as3722_regulator_probe,
+};
+
+module_platform_driver(as3722_regulator_driver);
+
+MODULE_ALIAS("platform:as3722-regulator");
+MODULE_DESCRIPTION("AS3722 regulator driver");
+MODULE_AUTHOR("Florian Lobmaier <florian.lobmaier@ams.com>");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index a01b8b3..6382f0a 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -36,6 +36,7 @@
 #include <trace/events/regulator.h>
 
 #include "dummy.h"
+#include "internal.h"
 
 #define rdev_crit(rdev, fmt, ...)					\
 	pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
@@ -52,8 +53,8 @@
 static LIST_HEAD(regulator_list);
 static LIST_HEAD(regulator_map_list);
 static LIST_HEAD(regulator_ena_gpio_list);
+static LIST_HEAD(regulator_supply_alias_list);
 static bool has_full_constraints;
-static bool board_wants_dummy_regulator;
 
 static struct dentry *debugfs_root;
 
@@ -83,22 +84,16 @@
 };
 
 /*
- * struct regulator
+ * struct regulator_supply_alias
  *
- * One for each consumer device.
+ * Used to map lookups for a supply onto an alternative device.
  */
-struct regulator {
-	struct device *dev;
+struct regulator_supply_alias {
 	struct list_head list;
-	unsigned int always_on:1;
-	unsigned int bypass:1;
-	int uA_load;
-	int min_uV;
-	int max_uV;
-	char *supply_name;
-	struct device_attribute dev_attr;
-	struct regulator_dev *rdev;
-	struct dentry *debugfs;
+	struct device *src_dev;
+	const char *src_supply;
+	struct device *alias_dev;
+	const char *alias_supply;
 };
 
 static int _regulator_is_enabled(struct regulator_dev *rdev);
@@ -923,6 +918,36 @@
 	return 0;
 }
 
+static int machine_constraints_current(struct regulator_dev *rdev,
+	struct regulation_constraints *constraints)
+{
+	struct regulator_ops *ops = rdev->desc->ops;
+	int ret;
+
+	if (!constraints->min_uA && !constraints->max_uA)
+		return 0;
+
+	if (constraints->min_uA > constraints->max_uA) {
+		rdev_err(rdev, "Invalid current constraints\n");
+		return -EINVAL;
+	}
+
+	if (!ops->set_current_limit || !ops->get_current_limit) {
+		rdev_warn(rdev, "Operation of current configuration missing\n");
+		return 0;
+	}
+
+	/* Set regulator current in constraints range */
+	ret = ops->set_current_limit(rdev, constraints->min_uA,
+			constraints->max_uA);
+	if (ret < 0) {
+		rdev_err(rdev, "Failed to set current constraint, %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 /**
  * set_machine_constraints - sets regulator constraints
  * @rdev: regulator source
@@ -953,6 +978,10 @@
 	if (ret != 0)
 		goto out;
 
+	ret = machine_constraints_current(rdev, rdev->constraints);
+	if (ret != 0)
+		goto out;
+
 	/* do we need to setup our suspend state */
 	if (rdev->constraints->initial_state) {
 		ret = suspend_prepare(rdev, rdev->constraints->initial_state);
@@ -1186,11 +1215,39 @@
 
 static int _regulator_get_enable_time(struct regulator_dev *rdev)
 {
+	if (rdev->constraints && rdev->constraints->enable_time)
+		return rdev->constraints->enable_time;
 	if (!rdev->desc->ops->enable_time)
 		return rdev->desc->enable_time;
 	return rdev->desc->ops->enable_time(rdev);
 }
 
+static struct regulator_supply_alias *regulator_find_supply_alias(
+		struct device *dev, const char *supply)
+{
+	struct regulator_supply_alias *map;
+
+	list_for_each_entry(map, &regulator_supply_alias_list, list)
+		if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0)
+			return map;
+
+	return NULL;
+}
+
+static void regulator_supply_alias(struct device **dev, const char **supply)
+{
+	struct regulator_supply_alias *map;
+
+	map = regulator_find_supply_alias(*dev, *supply);
+	if (map) {
+		dev_dbg(*dev, "Mapping supply %s to %s,%s\n",
+				*supply, map->alias_supply,
+				dev_name(map->alias_dev));
+		*dev = map->alias_dev;
+		*supply = map->alias_supply;
+	}
+}
+
 static struct regulator_dev *regulator_dev_lookup(struct device *dev,
 						  const char *supply,
 						  int *ret)
@@ -1200,6 +1257,8 @@
 	struct regulator_map *map;
 	const char *devname = NULL;
 
+	regulator_supply_alias(&dev, &supply);
+
 	/* first do a dt based lookup */
 	if (dev && dev->of_node) {
 		node = of_get_regulator(dev, supply);
@@ -1243,16 +1302,16 @@
 
 /* Internal regulator request function */
 static struct regulator *_regulator_get(struct device *dev, const char *id,
-					bool exclusive)
+					bool exclusive, bool allow_dummy)
 {
 	struct regulator_dev *rdev;
 	struct regulator *regulator = ERR_PTR(-EPROBE_DEFER);
 	const char *devname = NULL;
-	int ret = 0;
+	int ret = -EPROBE_DEFER;
 
 	if (id == NULL) {
 		pr_err("get() with no identifier\n");
-		return regulator;
+		return ERR_PTR(-EINVAL);
 	}
 
 	if (dev)
@@ -1264,34 +1323,32 @@
 	if (rdev)
 		goto found;
 
+	regulator = ERR_PTR(ret);
+
 	/*
 	 * If we have return value from dev_lookup fail, we do not expect to
 	 * succeed, so, quit with appropriate error value
 	 */
-	if (ret) {
-		regulator = ERR_PTR(ret);
+	if (ret && ret != -ENODEV) {
 		goto out;
 	}
 
-	if (board_wants_dummy_regulator) {
-		rdev = dummy_regulator_rdev;
-		goto found;
-	}
-
-#ifdef CONFIG_REGULATOR_DUMMY
 	if (!devname)
 		devname = "deviceless";
 
-	/* If the board didn't flag that it was fully constrained then
-	 * substitute in a dummy regulator so consumers can continue.
+	/*
+	 * Assume that a regulator is physically present and enabled
+	 * even if it isn't hooked up and just provide a dummy.
 	 */
-	if (!has_full_constraints) {
+	if (has_full_constraints && allow_dummy) {
 		pr_warn("%s supply %s not found, using dummy regulator\n",
 			devname, id);
+
 		rdev = dummy_regulator_rdev;
 		goto found;
+	} else {
+		dev_err(dev, "dummy supplies not allowed\n");
 	}
-#endif
 
 	mutex_unlock(&regulator_list_mutex);
 	return regulator;
@@ -1349,44 +1406,10 @@
  */
 struct regulator *regulator_get(struct device *dev, const char *id)
 {
-	return _regulator_get(dev, id, false);
+	return _regulator_get(dev, id, false, true);
 }
 EXPORT_SYMBOL_GPL(regulator_get);
 
-static void devm_regulator_release(struct device *dev, void *res)
-{
-	regulator_put(*(struct regulator **)res);
-}
-
-/**
- * devm_regulator_get - Resource managed regulator_get()
- * @dev: device for regulator "consumer"
- * @id: Supply name or regulator ID.
- *
- * Managed regulator_get(). Regulators returned from this function are
- * automatically regulator_put() on driver detach. See regulator_get() for more
- * information.
- */
-struct regulator *devm_regulator_get(struct device *dev, const char *id)
-{
-	struct regulator **ptr, *regulator;
-
-	ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
-	if (!ptr)
-		return ERR_PTR(-ENOMEM);
-
-	regulator = regulator_get(dev, id);
-	if (!IS_ERR(regulator)) {
-		*ptr = regulator;
-		devres_add(dev, ptr);
-	} else {
-		devres_free(ptr);
-	}
-
-	return regulator;
-}
-EXPORT_SYMBOL_GPL(devm_regulator_get);
-
 /**
  * regulator_get_exclusive - obtain exclusive access to a regulator.
  * @dev: device for regulator "consumer"
@@ -1410,7 +1433,7 @@
  */
 struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
 {
-	return _regulator_get(dev, id, true);
+	return _regulator_get(dev, id, true, false);
 }
 EXPORT_SYMBOL_GPL(regulator_get_exclusive);
 
@@ -1439,40 +1462,10 @@
  */
 struct regulator *regulator_get_optional(struct device *dev, const char *id)
 {
-	return _regulator_get(dev, id, 0);
+	return _regulator_get(dev, id, false, false);
 }
 EXPORT_SYMBOL_GPL(regulator_get_optional);
 
-/**
- * devm_regulator_get_optional - Resource managed regulator_get_optional()
- * @dev: device for regulator "consumer"
- * @id: Supply name or regulator ID.
- *
- * Managed regulator_get_optional(). Regulators returned from this
- * function are automatically regulator_put() on driver detach. See
- * regulator_get_optional() for more information.
- */
-struct regulator *devm_regulator_get_optional(struct device *dev,
-					      const char *id)
-{
-	struct regulator **ptr, *regulator;
-
-	ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
-	if (!ptr)
-		return ERR_PTR(-ENOMEM);
-
-	regulator = regulator_get_optional(dev, id);
-	if (!IS_ERR(regulator)) {
-		*ptr = regulator;
-		devres_add(dev, ptr);
-	} else {
-		devres_free(ptr);
-	}
-
-	return regulator;
-}
-EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
-
 /* Locks held by regulator_put() */
 static void _regulator_put(struct regulator *regulator)
 {
@@ -1499,36 +1492,6 @@
 }
 
 /**
- * devm_regulator_get_exclusive - Resource managed regulator_get_exclusive()
- * @dev: device for regulator "consumer"
- * @id: Supply name or regulator ID.
- *
- * Managed regulator_get_exclusive(). Regulators returned from this function
- * are automatically regulator_put() on driver detach. See regulator_get() for
- * more information.
- */
-struct regulator *devm_regulator_get_exclusive(struct device *dev,
-					       const char *id)
-{
-	struct regulator **ptr, *regulator;
-
-	ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
-	if (!ptr)
-		return ERR_PTR(-ENOMEM);
-
-	regulator = _regulator_get(dev, id, 1);
-	if (!IS_ERR(regulator)) {
-		*ptr = regulator;
-		devres_add(dev, ptr);
-	} else {
-		devres_free(ptr);
-	}
-
-	return regulator;
-}
-EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
-
-/**
  * regulator_put - "free" the regulator source
  * @regulator: regulator source
  *
@@ -1544,34 +1507,133 @@
 }
 EXPORT_SYMBOL_GPL(regulator_put);
 
-static int devm_regulator_match(struct device *dev, void *res, void *data)
+/**
+ * regulator_register_supply_alias - Provide device alias for supply lookup
+ *
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: Supply name or regulator ID
+ * @alias_dev: device that should be used to lookup the supply
+ * @alias_id: Supply name or regulator ID that should be used to lookup the
+ * supply
+ *
+ * All lookups for id on dev will instead be conducted for alias_id on
+ * alias_dev.
+ */
+int regulator_register_supply_alias(struct device *dev, const char *id,
+				    struct device *alias_dev,
+				    const char *alias_id)
 {
-	struct regulator **r = res;
-	if (!r || !*r) {
-		WARN_ON(!r || !*r);
-		return 0;
-	}
-	return *r == data;
+	struct regulator_supply_alias *map;
+
+	map = regulator_find_supply_alias(dev, id);
+	if (map)
+		return -EEXIST;
+
+	map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL);
+	if (!map)
+		return -ENOMEM;
+
+	map->src_dev = dev;
+	map->src_supply = id;
+	map->alias_dev = alias_dev;
+	map->alias_supply = alias_id;
+
+	list_add(&map->list, &regulator_supply_alias_list);
+
+	pr_info("Adding alias for supply %s,%s -> %s,%s\n",
+		id, dev_name(dev), alias_id, dev_name(alias_dev));
+
+	return 0;
 }
+EXPORT_SYMBOL_GPL(regulator_register_supply_alias);
 
 /**
- * devm_regulator_put - Resource managed regulator_put()
- * @regulator: regulator to free
+ * regulator_unregister_supply_alias - Remove device alias
  *
- * Deallocate a regulator allocated with devm_regulator_get(). Normally
- * this function will not need to be called and the resource management
- * code will ensure that the resource is freed.
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: Supply name or regulator ID
+ *
+ * Remove a lookup alias if one exists for id on dev.
  */
-void devm_regulator_put(struct regulator *regulator)
+void regulator_unregister_supply_alias(struct device *dev, const char *id)
 {
-	int rc;
+	struct regulator_supply_alias *map;
 
-	rc = devres_release(regulator->dev, devm_regulator_release,
-			    devm_regulator_match, regulator);
-	if (rc != 0)
-		WARN_ON(rc);
+	map = regulator_find_supply_alias(dev, id);
+	if (map) {
+		list_del(&map->list);
+		kfree(map);
+	}
 }
-EXPORT_SYMBOL_GPL(devm_regulator_put);
+EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias);
+
+/**
+ * regulator_bulk_register_supply_alias - register multiple aliases
+ *
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: List of supply names or regulator IDs
+ * @alias_dev: device that should be used to lookup the supply
+ * @alias_id: List of supply names or regulator IDs that should be used to
+ * lookup the supply
+ * @num_id: Number of aliases to register
+ *
+ * @return 0 on success, an errno on failure.
+ *
+ * This helper function allows drivers to register several supply
+ * aliases in one operation.  If any of the aliases cannot be
+ * registered any aliases that were registered will be removed
+ * before returning to the caller.
+ */
+int regulator_bulk_register_supply_alias(struct device *dev, const char **id,
+					 struct device *alias_dev,
+					 const char **alias_id,
+					 int num_id)
+{
+	int i;
+	int ret;
+
+	for (i = 0; i < num_id; ++i) {
+		ret = regulator_register_supply_alias(dev, id[i], alias_dev,
+						      alias_id[i]);
+		if (ret < 0)
+			goto err;
+	}
+
+	return 0;
+
+err:
+	dev_err(dev,
+		"Failed to create supply alias %s,%s -> %s,%s\n",
+		id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
+
+	while (--i >= 0)
+		regulator_unregister_supply_alias(dev, id[i]);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias);
+
+/**
+ * regulator_bulk_unregister_supply_alias - unregister multiple aliases
+ *
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: List of supply names or regulator IDs
+ * @num_id: Number of aliases to unregister
+ *
+ * This helper function allows drivers to unregister several supply
+ * aliases in one operation.
+ */
+void regulator_bulk_unregister_supply_alias(struct device *dev,
+					    const char **id,
+					    int num_id)
+{
+	int i;
+
+	for (i = 0; i < num_id; ++i)
+		regulator_unregister_supply_alias(dev, id[i]);
+}
+EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias);
+
 
 /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */
 static int regulator_ena_gpio_request(struct regulator_dev *rdev,
@@ -1704,11 +1766,39 @@
 	 * together.  */
 	trace_regulator_enable_delay(rdev_get_name(rdev));
 
-	if (delay >= 1000) {
-		mdelay(delay / 1000);
-		udelay(delay % 1000);
-	} else if (delay) {
-		udelay(delay);
+	/*
+	 * Delay for the requested amount of time as per the guidelines in:
+	 *
+	 *     Documentation/timers/timers-howto.txt
+	 *
+	 * The assumption here is that regulators will never be enabled in
+	 * atomic context and therefore sleeping functions can be used.
+	 */
+	if (delay) {
+		unsigned int ms = delay / 1000;
+		unsigned int us = delay % 1000;
+
+		if (ms > 0) {
+			/*
+			 * For small enough values, handle super-millisecond
+			 * delays in the usleep_range() call below.
+			 */
+			if (ms < 20)
+				us += ms * 1000;
+			else
+				msleep(ms);
+		}
+
+		/*
+		 * Give the scheduler some room to coalesce with any other
+		 * wakeup sources. For delays shorter than 10 us, don't even
+		 * bother setting up high-resolution timers and just busy-
+		 * loop.
+		 */
+		if (us >= 10)
+			usleep_range(us, us + 100);
+		else
+			udelay(us);
 	}
 
 	trace_regulator_enable_complete(rdev_get_name(rdev));
@@ -2489,6 +2579,8 @@
 		ret = rdev->desc->ops->get_voltage(rdev);
 	} else if (rdev->desc->ops->list_voltage) {
 		ret = rdev->desc->ops->list_voltage(rdev, 0);
+	} else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) {
+		ret = rdev->desc->fixed_uV;
 	} else {
 		return -EINVAL;
 	}
@@ -2912,52 +3004,6 @@
 }
 EXPORT_SYMBOL_GPL(regulator_bulk_get);
 
-/**
- * devm_regulator_bulk_get - managed get multiple regulator consumers
- *
- * @dev:           Device to supply
- * @num_consumers: Number of consumers to register
- * @consumers:     Configuration of consumers; clients are stored here.
- *
- * @return 0 on success, an errno on failure.
- *
- * This helper function allows drivers to get several regulator
- * consumers in one operation with management, the regulators will
- * automatically be freed when the device is unbound.  If any of the
- * regulators cannot be acquired then any regulators that were
- * allocated will be freed before returning to the caller.
- */
-int devm_regulator_bulk_get(struct device *dev, int num_consumers,
-			    struct regulator_bulk_data *consumers)
-{
-	int i;
-	int ret;
-
-	for (i = 0; i < num_consumers; i++)
-		consumers[i].consumer = NULL;
-
-	for (i = 0; i < num_consumers; i++) {
-		consumers[i].consumer = devm_regulator_get(dev,
-							   consumers[i].supply);
-		if (IS_ERR(consumers[i].consumer)) {
-			ret = PTR_ERR(consumers[i].consumer);
-			dev_err(dev, "Failed to get supply '%s': %d\n",
-				consumers[i].supply, ret);
-			consumers[i].consumer = NULL;
-			goto err;
-		}
-	}
-
-	return 0;
-
-err:
-	for (i = 0; i < num_consumers && consumers[i].consumer; i++)
-		devm_regulator_put(consumers[i].consumer);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
-
 static void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
 {
 	struct regulator_bulk_data *bulk = data;
@@ -3170,7 +3216,8 @@
 	/* some attributes need specific methods to be displayed */
 	if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) ||
 	    (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) ||
-	    (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0)) {
+	    (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) ||
+		(rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1))) {
 		status = device_create_file(dev, &dev_attr_microvolts);
 		if (status < 0)
 			return status;
@@ -3614,22 +3661,6 @@
 EXPORT_SYMBOL_GPL(regulator_has_full_constraints);
 
 /**
- * regulator_use_dummy_regulator - Provide a dummy regulator when none is found
- *
- * Calling this function will cause the regulator API to provide a
- * dummy regulator to consumers if no physical regulator is found,
- * allowing most consumers to proceed as though a regulator were
- * configured.  This allows systems such as those with software
- * controllable regulators for the CPU core only to be brought up more
- * readily.
- */
-void regulator_use_dummy_regulator(void)
-{
-	board_wants_dummy_regulator = true;
-}
-EXPORT_SYMBOL_GPL(regulator_use_dummy_regulator);
-
-/**
  * rdev_get_drvdata - get rdev regulator driver data
  * @rdev: regulator
  *
diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c
index f06854c..b431ae3 100644
--- a/drivers/regulator/da903x.c
+++ b/drivers/regulator/da903x.c
@@ -253,10 +253,8 @@
 }
 
 static const struct regulator_linear_range da9034_ldo12_ranges[] = {
-	{ .min_uV = 1700000, .max_uV = 2050000, .min_sel =  0, .max_sel = 7,
-	  .uV_step =  50000 },
-	{ .min_uV = 2700000, .max_uV = 3050000, .min_sel =  8, .max_sel = 15,
-	  .uV_step =  50000 },
+	REGULATOR_LINEAR_RANGE(1700000, 0, 7, 50000),
+	REGULATOR_LINEAR_RANGE(2700000, 8, 15, 50000),
 };
 
 static struct regulator_ops da903x_regulator_ldo_ops = {
@@ -463,7 +461,7 @@
 	config.init_data = dev_get_platdata(&pdev->dev);
 	config.driver_data = ri;
 
-	rdev = regulator_register(&ri->desc, &config);
+	rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
 	if (IS_ERR(rdev)) {
 		dev_err(&pdev->dev, "failed to register regulator %s\n",
 				ri->desc.name);
@@ -474,21 +472,12 @@
 	return 0;
 }
 
-static int da903x_regulator_remove(struct platform_device *pdev)
-{
-	struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
-	regulator_unregister(rdev);
-	return 0;
-}
-
 static struct platform_driver da903x_regulator_driver = {
 	.driver	= {
 		.name	= "da903x-regulator",
 		.owner	= THIS_MODULE,
 	},
 	.probe		= da903x_regulator_probe,
-	.remove		= da903x_regulator_remove,
 };
 
 static int __init da903x_regulator_init(void)
diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c
index 1e4d483..3adeaef 100644
--- a/drivers/regulator/da9052-regulator.c
+++ b/drivers/regulator/da9052-regulator.c
@@ -70,6 +70,7 @@
 	int step_uV;
 	int min_uV;
 	int max_uV;
+	unsigned char activate_bit;
 };
 
 struct da9052_regulator {
@@ -209,6 +210,36 @@
 	return sel;
 }
 
+static int da9052_regulator_set_voltage_sel(struct regulator_dev *rdev,
+					    unsigned int selector)
+{
+	struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
+	struct da9052_regulator_info *info = regulator->info;
+	int id = rdev_get_id(rdev);
+	int ret;
+
+	ret = da9052_reg_update(regulator->da9052, rdev->desc->vsel_reg,
+				rdev->desc->vsel_mask, selector);
+	if (ret < 0)
+		return ret;
+
+	/* Some LDOs and DCDCs are DVC controlled which requires enabling of
+	 * the activate bit to implment the changes on the output.
+	 */
+	switch (id) {
+	case DA9052_ID_BUCK1:
+	case DA9052_ID_BUCK2:
+	case DA9052_ID_BUCK3:
+	case DA9052_ID_LDO2:
+	case DA9052_ID_LDO3:
+		ret = da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG,
+					info->activate_bit, info->activate_bit);
+		break;
+	}
+
+	return ret;
+}
+
 static struct regulator_ops da9052_dcdc_ops = {
 	.get_current_limit = da9052_dcdc_get_current_limit,
 	.set_current_limit = da9052_dcdc_set_current_limit,
@@ -216,7 +247,7 @@
 	.list_voltage = da9052_list_voltage,
 	.map_voltage = da9052_map_voltage,
 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
-	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.set_voltage_sel = da9052_regulator_set_voltage_sel,
 	.is_enabled = regulator_is_enabled_regmap,
 	.enable = regulator_enable_regmap,
 	.disable = regulator_disable_regmap,
@@ -226,7 +257,7 @@
 	.list_voltage = da9052_list_voltage,
 	.map_voltage = da9052_map_voltage,
 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
-	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.set_voltage_sel = da9052_regulator_set_voltage_sel,
 	.is_enabled = regulator_is_enabled_regmap,
 	.enable = regulator_enable_regmap,
 	.disable = regulator_disable_regmap,
@@ -243,14 +274,13 @@
 		.owner = THIS_MODULE,\
 		.vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \
 		.vsel_mask = (1 << (sbits)) - 1,\
-		.apply_reg = DA9052_SUPPLY_REG, \
-		.apply_bit = (abits), \
 		.enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \
 		.enable_mask = 1 << (ebits),\
 	},\
 	.min_uV = (min) * 1000,\
 	.max_uV = (max) * 1000,\
 	.step_uV = (step) * 1000,\
+	.activate_bit = (abits),\
 }
 
 #define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \
@@ -264,14 +294,13 @@
 		.owner = THIS_MODULE,\
 		.vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \
 		.vsel_mask = (1 << (sbits)) - 1,\
-		.apply_reg = DA9052_SUPPLY_REG, \
-		.apply_bit = (abits), \
 		.enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \
 		.enable_mask = 1 << (ebits),\
 	},\
 	.min_uV = (min) * 1000,\
 	.max_uV = (max) * 1000,\
 	.step_uV = (step) * 1000,\
+	.activate_bit = (abits),\
 }
 
 static struct da9052_regulator_info da9052_regulator_info[] = {
@@ -389,8 +418,9 @@
 #endif
 	}
 
-	regulator->rdev = regulator_register(&regulator->info->reg_desc,
-					     &config);
+	regulator->rdev = devm_regulator_register(&pdev->dev,
+						  &regulator->info->reg_desc,
+						  &config);
 	if (IS_ERR(regulator->rdev)) {
 		dev_err(&pdev->dev, "failed to register regulator %s\n",
 			regulator->info->reg_desc.name);
@@ -402,17 +432,8 @@
 	return 0;
 }
 
-static int da9052_regulator_remove(struct platform_device *pdev)
-{
-	struct da9052_regulator *regulator = platform_get_drvdata(pdev);
-
-	regulator_unregister(regulator->rdev);
-	return 0;
-}
-
 static struct platform_driver da9052_regulator_driver = {
 	.probe = da9052_regulator_probe,
-	.remove = da9052_regulator_remove,
 	.driver = {
 		.name = "da9052-regulator",
 		.owner = THIS_MODULE,
diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c
index 77b53e5..7f34020 100644
--- a/drivers/regulator/da9055-regulator.c
+++ b/drivers/regulator/da9055-regulator.c
@@ -564,13 +564,13 @@
 	if (ret < 0)
 		return ret;
 
-	regulator->rdev = regulator_register(&regulator->info->reg_desc,
-					     &config);
+	regulator->rdev = devm_regulator_register(&pdev->dev,
+						  &regulator->info->reg_desc,
+						  &config);
 	if (IS_ERR(regulator->rdev)) {
 		dev_err(&pdev->dev, "Failed to register regulator %s\n",
 			regulator->info->reg_desc.name);
-		ret = PTR_ERR(regulator->rdev);
-		return ret;
+		return PTR_ERR(regulator->rdev);
 	}
 
 	/* Only LDO 5 and 6 has got the over current interrupt */
@@ -588,7 +588,7 @@
 				dev_err(&pdev->dev,
 				"Failed to request Regulator IRQ %d: %d\n",
 				irq, ret);
-				goto err_regulator;
+				return ret;
 			}
 		}
 	}
@@ -596,24 +596,10 @@
 	platform_set_drvdata(pdev, regulator);
 
 	return 0;
-
-err_regulator:
-	regulator_unregister(regulator->rdev);
-	return ret;
-}
-
-static int da9055_regulator_remove(struct platform_device *pdev)
-{
-	struct da9055_regulator *regulator = platform_get_drvdata(pdev);
-
-	regulator_unregister(regulator->rdev);
-
-	return 0;
 }
 
 static struct platform_driver da9055_regulator_driver = {
 	.probe = da9055_regulator_probe,
-	.remove = da9055_regulator_remove,
 	.driver = {
 		.name = "da9055-regulator",
 		.owner = THIS_MODULE,
diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c
index b9f2653..56727eb 100644
--- a/drivers/regulator/da9063-regulator.c
+++ b/drivers/regulator/da9063-regulator.c
@@ -717,7 +717,7 @@
 {
 	struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent);
 	struct da9063_pdata *da9063_pdata = dev_get_platdata(da9063->dev);
-	struct of_regulator_match *da9063_reg_matches;
+	struct of_regulator_match *da9063_reg_matches = NULL;
 	struct da9063_regulators_pdata *regl_pdata;
 	const struct da9063_dev_model *model;
 	struct da9063_regulators *regulators;
@@ -847,13 +847,13 @@
 		if (da9063_reg_matches)
 			config.of_node = da9063_reg_matches[id].of_node;
 		config.regmap = da9063->regmap;
-		regl->rdev = regulator_register(&regl->desc, &config);
+		regl->rdev = devm_regulator_register(&pdev->dev, &regl->desc,
+						     &config);
 		if (IS_ERR(regl->rdev)) {
 			dev_err(&pdev->dev,
 				"Failed to register %s regulator\n",
 				regl->desc.name);
-			ret = PTR_ERR(regl->rdev);
-			goto err;
+			return PTR_ERR(regl->rdev);
 		}
 		id++;
 		n++;
@@ -862,9 +862,8 @@
 	/* LDOs overcurrent event support */
 	irq = platform_get_irq_byname(pdev, "LDO_LIM");
 	if (irq < 0) {
-		ret = irq;
 		dev_err(&pdev->dev, "Failed to get IRQ.\n");
-		goto err;
+		return irq;
 	}
 
 	regulators->irq_ldo_lim = regmap_irq_get_virq(da9063->regmap_irq, irq);
@@ -881,27 +880,15 @@
 	}
 
 	return 0;
-
-err:
-	/* Wind back regulators registeration */
-	while (--n >= 0)
-		regulator_unregister(regulators->regulator[n].rdev);
-
-	return ret;
 }
 
 static int da9063_regulator_remove(struct platform_device *pdev)
 {
 	struct da9063_regulators *regulators = platform_get_drvdata(pdev);
-	struct da9063_regulator *regl;
 
 	free_irq(regulators->irq_ldo_lim, regulators);
 	free_irq(regulators->irq_uvov, regulators);
 
-	for (regl = &regulators->regulator[regulators->n_regulators - 1];
-	     regl >= &regulators->regulator[0]; regl--)
-		regulator_unregister(regl->rdev);
-
 	return 0;
 }
 
diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c
index f0fe54b..6f5ecbe 100644
--- a/drivers/regulator/da9210-regulator.c
+++ b/drivers/regulator/da9210-regulator.c
@@ -25,6 +25,7 @@
 #include <linux/slab.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
 #include <linux/regmap.h>
 
 #include "da9210-regulator.h"
@@ -126,7 +127,8 @@
 			    const struct i2c_device_id *id)
 {
 	struct da9210 *chip;
-	struct da9210_pdata *pdata = i2c->dev.platform_data;
+	struct device *dev = &i2c->dev;
+	struct da9210_pdata *pdata = dev_get_platdata(dev);
 	struct regulator_dev *rdev = NULL;
 	struct regulator_config config = { };
 	int error;
@@ -147,12 +149,13 @@
 	}
 
 	config.dev = &i2c->dev;
-	if (pdata)
-		config.init_data = &pdata->da9210_constraints;
+	config.init_data = pdata ? &pdata->da9210_constraints :
+		of_get_regulator_init_data(dev, dev->of_node);
 	config.driver_data = chip;
 	config.regmap = chip->regmap;
+	config.of_node = dev->of_node;
 
-	rdev = regulator_register(&da9210_reg, &config);
+	rdev = devm_regulator_register(&i2c->dev, &da9210_reg, &config);
 	if (IS_ERR(rdev)) {
 		dev_err(&i2c->dev, "Failed to register DA9210 regulator\n");
 		return PTR_ERR(rdev);
@@ -165,13 +168,6 @@
 	return 0;
 }
 
-static int da9210_i2c_remove(struct i2c_client *i2c)
-{
-	struct da9210 *chip = i2c_get_clientdata(i2c);
-	regulator_unregister(chip->rdev);
-	return 0;
-}
-
 static const struct i2c_device_id da9210_i2c_id[] = {
 	{"da9210", 0},
 	{},
@@ -185,7 +181,6 @@
 		.owner = THIS_MODULE,
 	},
 	.probe = da9210_i2c_probe,
-	.remove = da9210_i2c_remove,
 	.id_table = da9210_i2c_id,
 };
 
diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c
new file mode 100644
index 0000000..f44818b
--- /dev/null
+++ b/drivers/regulator/devres.c
@@ -0,0 +1,415 @@
+/*
+ * devres.c  --  Voltage/Current Regulator framework devres implementation.
+ *
+ * Copyright 2013 Linaro Ltd
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/driver.h>
+#include <linux/module.h>
+
+#include "internal.h"
+
+enum {
+	NORMAL_GET,
+	EXCLUSIVE_GET,
+	OPTIONAL_GET,
+};
+
+static void devm_regulator_release(struct device *dev, void *res)
+{
+	regulator_put(*(struct regulator **)res);
+}
+
+static struct regulator *_devm_regulator_get(struct device *dev, const char *id,
+					     int get_type)
+{
+	struct regulator **ptr, *regulator;
+
+	ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	switch (get_type) {
+	case NORMAL_GET:
+		regulator = regulator_get(dev, id);
+		break;
+	case EXCLUSIVE_GET:
+		regulator = regulator_get_exclusive(dev, id);
+		break;
+	case OPTIONAL_GET:
+		regulator = regulator_get_optional(dev, id);
+		break;
+	default:
+		regulator = ERR_PTR(-EINVAL);
+	}
+
+	if (!IS_ERR(regulator)) {
+		*ptr = regulator;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return regulator;
+}
+
+/**
+ * devm_regulator_get - Resource managed regulator_get()
+ * @dev: device for regulator "consumer"
+ * @id: Supply name or regulator ID.
+ *
+ * Managed regulator_get(). Regulators returned from this function are
+ * automatically regulator_put() on driver detach. See regulator_get() for more
+ * information.
+ */
+struct regulator *devm_regulator_get(struct device *dev, const char *id)
+{
+	return _devm_regulator_get(dev, id, NORMAL_GET);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_get);
+
+/**
+ * devm_regulator_get_exclusive - Resource managed regulator_get_exclusive()
+ * @dev: device for regulator "consumer"
+ * @id: Supply name or regulator ID.
+ *
+ * Managed regulator_get_exclusive(). Regulators returned from this function
+ * are automatically regulator_put() on driver detach. See regulator_get() for
+ * more information.
+ */
+struct regulator *devm_regulator_get_exclusive(struct device *dev,
+					       const char *id)
+{
+	return _devm_regulator_get(dev, id, EXCLUSIVE_GET);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
+
+/**
+ * devm_regulator_get_optional - Resource managed regulator_get_optional()
+ * @dev: device for regulator "consumer"
+ * @id: Supply name or regulator ID.
+ *
+ * Managed regulator_get_optional(). Regulators returned from this
+ * function are automatically regulator_put() on driver detach. See
+ * regulator_get_optional() for more information.
+ */
+struct regulator *devm_regulator_get_optional(struct device *dev,
+					      const char *id)
+{
+	return _devm_regulator_get(dev, id, OPTIONAL_GET);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
+
+static int devm_regulator_match(struct device *dev, void *res, void *data)
+{
+	struct regulator **r = res;
+	if (!r || !*r) {
+		WARN_ON(!r || !*r);
+		return 0;
+	}
+	return *r == data;
+}
+
+/**
+ * devm_regulator_put - Resource managed regulator_put()
+ * @regulator: regulator to free
+ *
+ * Deallocate a regulator allocated with devm_regulator_get(). Normally
+ * this function will not need to be called and the resource management
+ * code will ensure that the resource is freed.
+ */
+void devm_regulator_put(struct regulator *regulator)
+{
+	int rc;
+
+	rc = devres_release(regulator->dev, devm_regulator_release,
+			    devm_regulator_match, regulator);
+	if (rc != 0)
+		WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_put);
+
+/**
+ * devm_regulator_bulk_get - managed get multiple regulator consumers
+ *
+ * @dev:           Device to supply
+ * @num_consumers: Number of consumers to register
+ * @consumers:     Configuration of consumers; clients are stored here.
+ *
+ * @return 0 on success, an errno on failure.
+ *
+ * This helper function allows drivers to get several regulator
+ * consumers in one operation with management, the regulators will
+ * automatically be freed when the device is unbound.  If any of the
+ * regulators cannot be acquired then any regulators that were
+ * allocated will be freed before returning to the caller.
+ */
+int devm_regulator_bulk_get(struct device *dev, int num_consumers,
+			    struct regulator_bulk_data *consumers)
+{
+	int i;
+	int ret;
+
+	for (i = 0; i < num_consumers; i++)
+		consumers[i].consumer = NULL;
+
+	for (i = 0; i < num_consumers; i++) {
+		consumers[i].consumer = devm_regulator_get(dev,
+							   consumers[i].supply);
+		if (IS_ERR(consumers[i].consumer)) {
+			ret = PTR_ERR(consumers[i].consumer);
+			dev_err(dev, "Failed to get supply '%s': %d\n",
+				consumers[i].supply, ret);
+			consumers[i].consumer = NULL;
+			goto err;
+		}
+	}
+
+	return 0;
+
+err:
+	for (i = 0; i < num_consumers && consumers[i].consumer; i++)
+		devm_regulator_put(consumers[i].consumer);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
+
+static void devm_rdev_release(struct device *dev, void *res)
+{
+	regulator_unregister(*(struct regulator_dev **)res);
+}
+
+/**
+ * devm_regulator_register - Resource managed regulator_register()
+ * @regulator_desc: regulator to register
+ * @config: runtime configuration for regulator
+ *
+ * Called by regulator drivers to register a regulator.  Returns a
+ * valid pointer to struct regulator_dev on success or an ERR_PTR() on
+ * error.  The regulator will automatically be released when the device
+ * is unbound.
+ */
+struct regulator_dev *devm_regulator_register(struct device *dev,
+				  const struct regulator_desc *regulator_desc,
+				  const struct regulator_config *config)
+{
+	struct regulator_dev **ptr, *rdev;
+
+	ptr = devres_alloc(devm_rdev_release, sizeof(*ptr),
+			   GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	rdev = regulator_register(regulator_desc, config);
+	if (!IS_ERR(rdev)) {
+		*ptr = rdev;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return rdev;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_register);
+
+static int devm_rdev_match(struct device *dev, void *res, void *data)
+{
+	struct regulator_dev **r = res;
+	if (!r || !*r) {
+		WARN_ON(!r || !*r);
+		return 0;
+	}
+	return *r == data;
+}
+
+/**
+ * devm_regulator_unregister - Resource managed regulator_unregister()
+ * @regulator: regulator to free
+ *
+ * Unregister a regulator registered with devm_regulator_register().
+ * Normally this function will not need to be called and the resource
+ * management code will ensure that the resource is freed.
+ */
+void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev)
+{
+	int rc;
+
+	rc = devres_release(dev, devm_rdev_release, devm_rdev_match, rdev);
+	if (rc != 0)
+		WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_unregister);
+
+struct regulator_supply_alias_match {
+	struct device *dev;
+	const char *id;
+};
+
+static int devm_regulator_match_supply_alias(struct device *dev, void *res,
+					     void *data)
+{
+	struct regulator_supply_alias_match *match = res;
+	struct regulator_supply_alias_match *target = data;
+
+	return match->dev == target->dev && strcmp(match->id, target->id) == 0;
+}
+
+static void devm_regulator_destroy_supply_alias(struct device *dev, void *res)
+{
+	struct regulator_supply_alias_match *match = res;
+
+	regulator_unregister_supply_alias(match->dev, match->id);
+}
+
+/**
+ * devm_regulator_register_supply_alias - Resource managed
+ * regulator_register_supply_alias()
+ *
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: Supply name or regulator ID
+ * @alias_dev: device that should be used to lookup the supply
+ * @alias_id: Supply name or regulator ID that should be used to lookup the
+ * supply
+ *
+ * The supply alias will automatically be unregistered when the source
+ * device is unbound.
+ */
+int devm_regulator_register_supply_alias(struct device *dev, const char *id,
+					 struct device *alias_dev,
+					 const char *alias_id)
+{
+	struct regulator_supply_alias_match *match;
+	int ret;
+
+	match = devres_alloc(devm_regulator_destroy_supply_alias,
+			   sizeof(struct regulator_supply_alias_match),
+			   GFP_KERNEL);
+	if (!match)
+		return -ENOMEM;
+
+	match->dev = dev;
+	match->id = id;
+
+	ret = regulator_register_supply_alias(dev, id, alias_dev, alias_id);
+	if (ret < 0) {
+		devres_free(match);
+		return ret;
+	}
+
+	devres_add(dev, match);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_register_supply_alias);
+
+/**
+ * devm_regulator_unregister_supply_alias - Resource managed
+ * regulator_unregister_supply_alias()
+ *
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: Supply name or regulator ID
+ *
+ * Unregister an alias registered with
+ * devm_regulator_register_supply_alias(). Normally this function
+ * will not need to be called and the resource management code
+ * will ensure that the resource is freed.
+ */
+void devm_regulator_unregister_supply_alias(struct device *dev, const char *id)
+{
+	struct regulator_supply_alias_match match;
+	int rc;
+
+	match.dev = dev;
+	match.id = id;
+
+	rc = devres_release(dev, devm_regulator_destroy_supply_alias,
+			    devm_regulator_match_supply_alias, &match);
+	if (rc != 0)
+		WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_unregister_supply_alias);
+
+/**
+ * devm_regulator_bulk_register_supply_alias - Managed register
+ * multiple aliases
+ *
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: List of supply names or regulator IDs
+ * @alias_dev: device that should be used to lookup the supply
+ * @alias_id: List of supply names or regulator IDs that should be used to
+ * lookup the supply
+ * @num_id: Number of aliases to register
+ *
+ * @return 0 on success, an errno on failure.
+ *
+ * This helper function allows drivers to register several supply
+ * aliases in one operation, the aliases will be automatically
+ * unregisters when the source device is unbound.  If any of the
+ * aliases cannot be registered any aliases that were registered
+ * will be removed before returning to the caller.
+ */
+int devm_regulator_bulk_register_supply_alias(struct device *dev,
+					      const char **id,
+					      struct device *alias_dev,
+					      const char **alias_id,
+					      int num_id)
+{
+	int i;
+	int ret;
+
+	for (i = 0; i < num_id; ++i) {
+		ret = devm_regulator_register_supply_alias(dev, id[i],
+							   alias_dev,
+							   alias_id[i]);
+		if (ret < 0)
+			goto err;
+	}
+
+	return 0;
+
+err:
+	dev_err(dev,
+		"Failed to create supply alias %s,%s -> %s,%s\n",
+		id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
+
+	while (--i >= 0)
+		devm_regulator_unregister_supply_alias(dev, id[i]);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias);
+
+/**
+ * devm_regulator_bulk_unregister_supply_alias - Managed unregister
+ * multiple aliases
+ *
+ * @dev: device that will be given as the regulator "consumer"
+ * @id: List of supply names or regulator IDs
+ * @num_id: Number of aliases to unregister
+ *
+ * Unregister aliases registered with
+ * devm_regulator_bulk_register_supply_alias(). Normally this function
+ * will not need to be called and the resource management code
+ * will ensure that the resource is freed.
+ */
+void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
+						 const char **id,
+						 int num_id)
+{
+	int i;
+
+	for (i = 0; i < num_id; ++i)
+		devm_regulator_unregister_supply_alias(dev, id[i]);
+}
+EXPORT_SYMBOL_GPL(devm_regulator_bulk_unregister_supply_alias);
diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c
index 70b7220..7ca3d9e 100644
--- a/drivers/regulator/fan53555.c
+++ b/drivers/regulator/fan53555.c
@@ -218,9 +218,8 @@
 	rdesc->vsel_mask = VSEL_NSEL_MASK;
 	rdesc->owner = THIS_MODULE;
 
-	di->rdev = regulator_register(&di->desc, config);
+	di->rdev = devm_regulator_register(di->dev, &di->desc, config);
 	return PTR_ERR_OR_ZERO(di->rdev);
-
 }
 
 static struct regmap_config fan53555_regmap_config = {
@@ -291,14 +290,6 @@
 
 }
 
-static int fan53555_regulator_remove(struct i2c_client *client)
-{
-	struct fan53555_device_info *di = i2c_get_clientdata(client);
-
-	regulator_unregister(di->rdev);
-	return 0;
-}
-
 static const struct i2c_device_id fan53555_id[] = {
 	{"fan53555", -1},
 	{ },
@@ -309,7 +300,6 @@
 		.name = "fan53555-regulator",
 	},
 	.probe = fan53555_regulator_probe,
-	.remove = fan53555_regulator_remove,
 	.id_table = fan53555_id,
 };
 
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index 7610920..5ea64b9 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -34,7 +34,6 @@
 struct fixed_voltage_data {
 	struct regulator_desc desc;
 	struct regulator_dev *dev;
-	int microvolts;
 };
 
 
@@ -108,30 +107,7 @@
 	return config;
 }
 
-static int fixed_voltage_get_voltage(struct regulator_dev *dev)
-{
-	struct fixed_voltage_data *data = rdev_get_drvdata(dev);
-
-	if (data->microvolts)
-		return data->microvolts;
-	else
-		return -EINVAL;
-}
-
-static int fixed_voltage_list_voltage(struct regulator_dev *dev,
-				      unsigned selector)
-{
-	struct fixed_voltage_data *data = rdev_get_drvdata(dev);
-
-	if (selector != 0)
-		return -EINVAL;
-
-	return data->microvolts;
-}
-
 static struct regulator_ops fixed_voltage_ops = {
-	.get_voltage = fixed_voltage_get_voltage,
-	.list_voltage = fixed_voltage_list_voltage,
 };
 
 static int reg_fixed_voltage_probe(struct platform_device *pdev)
@@ -186,23 +162,21 @@
 	if (config->microvolts)
 		drvdata->desc.n_voltages = 1;
 
-	drvdata->microvolts = config->microvolts;
+	drvdata->desc.fixed_uV = config->microvolts;
 
 	if (config->gpio >= 0)
 		cfg.ena_gpio = config->gpio;
 	cfg.ena_gpio_invert = !config->enable_high;
 	if (config->enabled_at_boot) {
-		if (config->enable_high) {
+		if (config->enable_high)
 			cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
-		} else {
+		else
 			cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
-		}
 	} else {
-		if (config->enable_high) {
+		if (config->enable_high)
 			cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
-		} else {
+		else
 			cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
-		}
 	}
 	if (config->gpio_is_open_drain)
 		cfg.ena_gpio_flags |= GPIOF_OPEN_DRAIN;
@@ -222,7 +196,7 @@
 	platform_set_drvdata(pdev, drvdata);
 
 	dev_dbg(&pdev->dev, "%s supplying %duV\n", drvdata->desc.name,
-		drvdata->microvolts);
+		drvdata->desc.fixed_uV);
 
 	return 0;
 
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
index 98a98ff..04406a9 100644
--- a/drivers/regulator/gpio-regulator.c
+++ b/drivers/regulator/gpio-regulator.c
@@ -283,7 +283,6 @@
 		dev_err(&pdev->dev, "No regulator type set\n");
 		ret = -EINVAL;
 		goto err_memgpio;
-		break;
 	}
 
 	drvdata->nr_gpios = config->nr_gpios;
diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c
index 6e30df1..e221a27 100644
--- a/drivers/regulator/helpers.c
+++ b/drivers/regulator/helpers.c
@@ -284,9 +284,13 @@
 	}
 
 	for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
-		range = &rdev->desc->linear_ranges[i];
+		int linear_max_uV;
 
-		if (!(min_uV <= range->max_uV && max_uV >= range->min_uV))
+		range = &rdev->desc->linear_ranges[i];
+		linear_max_uV = range->min_uV +
+			(range->max_sel - range->min_sel) * range->uV_step;
+
+		if (!(min_uV <= linear_max_uV && max_uV >= range->min_uV))
 			continue;
 
 		if (min_uV <= range->min_uV)
diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h
new file mode 100644
index 0000000..84bbda1
--- /dev/null
+++ b/drivers/regulator/internal.h
@@ -0,0 +1,38 @@
+/*
+ * internal.h  --  Voltage/Current Regulator framework internal code
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ * Copyright 2008 SlimLogic Ltd.
+ *
+ * Author: Liam Girdwood <lrg@slimlogic.co.uk>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#ifndef __REGULATOR_INTERNAL_H
+#define __REGULATOR_INTERNAL_H
+
+/*
+ * struct regulator
+ *
+ * One for each consumer device.
+ */
+struct regulator {
+	struct device *dev;
+	struct list_head list;
+	unsigned int always_on:1;
+	unsigned int bypass:1;
+	int uA_load;
+	int min_uV;
+	int max_uV;
+	char *supply_name;
+	struct device_attribute dev_attr;
+	struct regulator_dev *rdev;
+	struct dentry *debugfs;
+};
+
+#endif
diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c
index 88c1a3a..6e5da95 100644
--- a/drivers/regulator/isl6271a-regulator.c
+++ b/drivers/regulator/isl6271a-regulator.c
@@ -112,7 +112,7 @@
 	struct regulator_config config = { };
 	struct regulator_init_data *init_data	= dev_get_platdata(&i2c->dev);
 	struct isl_pmic *pmic;
-	int err, i;
+	int i;
 
 	if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -EIO;
@@ -133,32 +133,17 @@
 			config.init_data = NULL;
 		config.driver_data = pmic;
 
-		pmic->rdev[i] = regulator_register(&isl_rd[i], &config);
+		pmic->rdev[i] = devm_regulator_register(&i2c->dev, &isl_rd[i],
+							&config);
 		if (IS_ERR(pmic->rdev[i])) {
 			dev_err(&i2c->dev, "failed to register %s\n", id->name);
-			err = PTR_ERR(pmic->rdev[i]);
-			goto error;
+			return PTR_ERR(pmic->rdev[i]);
 		}
 	}
 
 	i2c_set_clientdata(i2c, pmic);
 
 	return 0;
-
-error:
-	while (--i >= 0)
-		regulator_unregister(pmic->rdev[i]);
-	return err;
-}
-
-static int isl6271a_remove(struct i2c_client *i2c)
-{
-	struct isl_pmic *pmic = i2c_get_clientdata(i2c);
-	int i;
-
-	for (i = 0; i < 3; i++)
-		regulator_unregister(pmic->rdev[i]);
-	return 0;
 }
 
 static const struct i2c_device_id isl6271a_id[] = {
@@ -174,7 +159,6 @@
 		.owner = THIS_MODULE,
 	},
 	.probe = isl6271a_probe,
-	.remove = isl6271a_remove,
 	.id_table = isl6271a_id,
 };
 
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index 5a4604e..947c05f 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -474,8 +474,8 @@
 }
 
 static const struct i2c_device_id lp3971_i2c_id[] = {
-       { "lp3971", 0 },
-       { }
+	{ "lp3971", 0 },
+	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lp3971_i2c_id);
 
diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
index 2b84b72..2e4734f 100644
--- a/drivers/regulator/lp872x.c
+++ b/drivers/regulator/lp872x.c
@@ -785,7 +785,7 @@
 	struct regulator_desc *desc;
 	struct regulator_config cfg = { };
 	struct regulator_dev *rdev;
-	int i, ret;
+	int i;
 
 	for (i = 0; i < lp->num_regulators; i++) {
 		desc = (lp->chipid == LP8720) ? &lp8720_regulator_desc[i] :
@@ -796,34 +796,16 @@
 		cfg.driver_data = lp;
 		cfg.regmap = lp->regmap;
 
-		rdev = regulator_register(desc, &cfg);
+		rdev = devm_regulator_register(lp->dev, desc, &cfg);
 		if (IS_ERR(rdev)) {
 			dev_err(lp->dev, "regulator register err");
-			ret =  PTR_ERR(rdev);
-			goto err;
+			return PTR_ERR(rdev);
 		}
 
 		*(lp->regulators + i) = rdev;
 	}
 
 	return 0;
-err:
-	while (--i >= 0) {
-		rdev = *(lp->regulators + i);
-		regulator_unregister(rdev);
-	}
-	return ret;
-}
-
-static void lp872x_regulator_unregister(struct lp872x *lp)
-{
-	struct regulator_dev *rdev;
-	int i;
-
-	for (i = 0; i < lp->num_regulators; i++) {
-		rdev = *(lp->regulators + i);
-		regulator_unregister(rdev);
-	}
 }
 
 static const struct regmap_config lp872x_regmap_config = {
@@ -979,14 +961,6 @@
 	return ret;
 }
 
-static int lp872x_remove(struct i2c_client *cl)
-{
-	struct lp872x *lp = i2c_get_clientdata(cl);
-
-	lp872x_regulator_unregister(lp);
-	return 0;
-}
-
 static const struct of_device_id lp872x_dt_ids[] = {
 	{ .compatible = "ti,lp8720", },
 	{ .compatible = "ti,lp8725", },
@@ -1008,7 +982,6 @@
 		.of_match_table = of_match_ptr(lp872x_dt_ids),
 	},
 	.probe = lp872x_probe,
-	.remove = lp872x_remove,
 	.id_table = lp872x_ids,
 };
 
diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c
index 0b015f2..948afc2 100644
--- a/drivers/regulator/lp8788-buck.c
+++ b/drivers/regulator/lp8788-buck.c
@@ -515,7 +515,7 @@
 	cfg.driver_data = buck;
 	cfg.regmap = lp->regmap;
 
-	rdev = regulator_register(&lp8788_buck_desc[id], &cfg);
+	rdev = devm_regulator_register(&pdev->dev, &lp8788_buck_desc[id], &cfg);
 	if (IS_ERR(rdev)) {
 		ret = PTR_ERR(rdev);
 		dev_err(&pdev->dev, "BUCK%d regulator register err = %d\n",
@@ -529,18 +529,8 @@
 	return 0;
 }
 
-static int lp8788_buck_remove(struct platform_device *pdev)
-{
-	struct lp8788_buck *buck = platform_get_drvdata(pdev);
-
-	regulator_unregister(buck->regulator);
-
-	return 0;
-}
-
 static struct platform_driver lp8788_buck_driver = {
 	.probe = lp8788_buck_probe,
-	.remove = lp8788_buck_remove,
 	.driver = {
 		.name = LP8788_DEV_BUCK,
 		.owner = THIS_MODULE,
diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c
index 0527d87..b9a29a2 100644
--- a/drivers/regulator/lp8788-ldo.c
+++ b/drivers/regulator/lp8788-ldo.c
@@ -543,7 +543,7 @@
 	cfg.driver_data = ldo;
 	cfg.regmap = lp->regmap;
 
-	rdev = regulator_register(&lp8788_dldo_desc[id], &cfg);
+	rdev = devm_regulator_register(&pdev->dev, &lp8788_dldo_desc[id], &cfg);
 	if (IS_ERR(rdev)) {
 		ret = PTR_ERR(rdev);
 		dev_err(&pdev->dev, "DLDO%d regulator register err = %d\n",
@@ -557,18 +557,8 @@
 	return 0;
 }
 
-static int lp8788_dldo_remove(struct platform_device *pdev)
-{
-	struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
-
-	regulator_unregister(ldo->regulator);
-
-	return 0;
-}
-
 static struct platform_driver lp8788_dldo_driver = {
 	.probe = lp8788_dldo_probe,
-	.remove = lp8788_dldo_remove,
 	.driver = {
 		.name = LP8788_DEV_DLDO,
 		.owner = THIS_MODULE,
@@ -603,7 +593,7 @@
 	cfg.driver_data = ldo;
 	cfg.regmap = lp->regmap;
 
-	rdev = regulator_register(&lp8788_aldo_desc[id], &cfg);
+	rdev = devm_regulator_register(&pdev->dev, &lp8788_aldo_desc[id], &cfg);
 	if (IS_ERR(rdev)) {
 		ret = PTR_ERR(rdev);
 		dev_err(&pdev->dev, "ALDO%d regulator register err = %d\n",
@@ -617,18 +607,8 @@
 	return 0;
 }
 
-static int lp8788_aldo_remove(struct platform_device *pdev)
-{
-	struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
-
-	regulator_unregister(ldo->regulator);
-
-	return 0;
-}
-
 static struct platform_driver lp8788_aldo_driver = {
 	.probe = lp8788_aldo_probe,
-	.remove = lp8788_aldo_remove,
 	.driver = {
 		.name = LP8788_DEV_ALDO,
 		.owner = THIS_MODULE,
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
index 3a599ee..e242dd3 100644
--- a/drivers/regulator/max1586.c
+++ b/drivers/regulator/max1586.c
@@ -166,7 +166,7 @@
 	struct max1586_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct regulator_config config = { };
 	struct max1586_data *max1586;
-	int i, id, ret = -ENOMEM;
+	int i, id;
 
 	max1586 = devm_kzalloc(&client->dev, sizeof(struct max1586_data) +
 			sizeof(struct regulator_dev *) * (MAX1586_V6 + 1),
@@ -193,7 +193,7 @@
 			continue;
 		if (id < MAX1586_V3 || id > MAX1586_V6) {
 			dev_err(&client->dev, "invalid regulator id %d\n", id);
-			goto err;
+			return -EINVAL;
 		}
 
 		if (id == MAX1586_V3) {
@@ -207,33 +207,18 @@
 		config.init_data = pdata->subdevs[i].platform_data;
 		config.driver_data = max1586;
 
-		rdev[i] = regulator_register(&max1586_reg[id], &config);
+		rdev[i] = devm_regulator_register(&client->dev,
+						  &max1586_reg[id], &config);
 		if (IS_ERR(rdev[i])) {
-			ret = PTR_ERR(rdev[i]);
 			dev_err(&client->dev, "failed to register %s\n",
 				max1586_reg[id].name);
-			goto err;
+			return PTR_ERR(rdev[i]);
 		}
 	}
 
 	i2c_set_clientdata(client, max1586);
 	dev_info(&client->dev, "Maxim 1586 regulator driver loaded\n");
 	return 0;
-
-err:
-	while (--i >= 0)
-		regulator_unregister(rdev[i]);
-	return ret;
-}
-
-static int max1586_pmic_remove(struct i2c_client *client)
-{
-	struct max1586_data *max1586 = i2c_get_clientdata(client);
-	int i;
-
-	for (i = 0; i <= MAX1586_V6; i++)
-		regulator_unregister(max1586->rdev[i]);
-	return 0;
 }
 
 static const struct i2c_device_id max1586_id[] = {
@@ -244,7 +229,6 @@
 
 static struct i2c_driver max1586_pmic_driver = {
 	.probe = max1586_pmic_probe,
-	.remove = max1586_pmic_remove,
 	.driver		= {
 		.name	= "max1586",
 		.owner	= THIS_MODULE,
diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c
index f563057..ae001cc 100644
--- a/drivers/regulator/max77686.c
+++ b/drivers/regulator/max77686.c
@@ -478,32 +478,16 @@
 		config.of_node = pdata->regulators[i].of_node;
 
 		max77686->opmode[i] = regulators[i].enable_mask;
-		max77686->rdev[i] = regulator_register(&regulators[i], &config);
+		max77686->rdev[i] = devm_regulator_register(&pdev->dev,
+						&regulators[i], &config);
 		if (IS_ERR(max77686->rdev[i])) {
-			ret = PTR_ERR(max77686->rdev[i]);
 			dev_err(&pdev->dev,
 				"regulator init failed for %d\n", i);
-			max77686->rdev[i] = NULL;
-			goto err;
+			return PTR_ERR(max77686->rdev[i]);
 		}
 	}
 
 	return 0;
-err:
-	while (--i >= 0)
-		regulator_unregister(max77686->rdev[i]);
-	return ret;
-}
-
-static int max77686_pmic_remove(struct platform_device *pdev)
-{
-	struct max77686_data *max77686 = platform_get_drvdata(pdev);
-	int i;
-
-	for (i = 0; i < MAX77686_REGULATORS; i++)
-		regulator_unregister(max77686->rdev[i]);
-
-	return 0;
 }
 
 static const struct platform_device_id max77686_pmic_id[] = {
@@ -518,7 +502,6 @@
 		.owner = THIS_MODULE,
 	},
 	.probe = max77686_pmic_probe,
-	.remove = max77686_pmic_remove,
 	.id_table = max77686_pmic_id,
 };
 
diff --git a/drivers/regulator/max77693.c b/drivers/regulator/max77693.c
index ce4b96c..feb20bf 100644
--- a/drivers/regulator/max77693.c
+++ b/drivers/regulator/max77693.c
@@ -230,7 +230,7 @@
 	struct max77693_dev *iodev = dev_get_drvdata(pdev->dev.parent);
 	struct max77693_pmic_dev *max77693_pmic;
 	struct max77693_regulator_data *rdata = NULL;
-	int num_rdata, i, ret;
+	int num_rdata, i;
 	struct regulator_config config;
 
 	num_rdata = max77693_pmic_init_rdata(&pdev->dev, &rdata);
@@ -266,36 +266,16 @@
 		config.init_data = rdata[i].initdata;
 		config.of_node = rdata[i].of_node;
 
-		max77693_pmic->rdev[i] = regulator_register(&regulators[id],
-							    &config);
+		max77693_pmic->rdev[i] = devm_regulator_register(&pdev->dev,
+						&regulators[id], &config);
 		if (IS_ERR(max77693_pmic->rdev[i])) {
-			ret = PTR_ERR(max77693_pmic->rdev[i]);
 			dev_err(max77693_pmic->dev,
 				"Failed to initialize regulator-%d\n", id);
-			max77693_pmic->rdev[i] = NULL;
-			goto err;
+			return PTR_ERR(max77693_pmic->rdev[i]);
 		}
 	}
 
 	return 0;
- err:
-	while (--i >= 0)
-		regulator_unregister(max77693_pmic->rdev[i]);
-
-	return ret;
-}
-
-static int max77693_pmic_remove(struct platform_device *pdev)
-{
-	struct max77693_pmic_dev *max77693_pmic = platform_get_drvdata(pdev);
-	struct regulator_dev **rdev = max77693_pmic->rdev;
-	int i;
-
-	for (i = 0; i < max77693_pmic->num_regulators; i++)
-		if (rdev[i])
-			regulator_unregister(rdev[i]);
-
-	return 0;
 }
 
 static const struct platform_device_id max77693_pmic_id[] = {
@@ -311,7 +291,6 @@
 		   .owner = THIS_MODULE,
 		   },
 	.probe = max77693_pmic_probe,
-	.remove = max77693_pmic_remove,
 	.id_table = max77693_pmic_id,
 };
 
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c
index 19c6f08..7f049c9 100644
--- a/drivers/regulator/max8649.c
+++ b/drivers/regulator/max8649.c
@@ -234,7 +234,8 @@
 	config.driver_data = info;
 	config.regmap = info->regmap;
 
-	info->regulator = regulator_register(&dcdc_desc, &config);
+	info->regulator = devm_regulator_register(&client->dev, &dcdc_desc,
+						  &config);
 	if (IS_ERR(info->regulator)) {
 		dev_err(info->dev, "failed to register regulator %s\n",
 			dcdc_desc.name);
@@ -244,16 +245,6 @@
 	return 0;
 }
 
-static int max8649_regulator_remove(struct i2c_client *client)
-{
-	struct max8649_regulator_info *info = i2c_get_clientdata(client);
-
-	if (info)
-		regulator_unregister(info->regulator);
-
-	return 0;
-}
-
 static const struct i2c_device_id max8649_id[] = {
 	{ "max8649", 0 },
 	{ }
@@ -262,7 +253,6 @@
 
 static struct i2c_driver max8649_driver = {
 	.probe		= max8649_regulator_probe,
-	.remove		= max8649_regulator_remove,
 	.driver		= {
 		.name	= "max8649",
 	},
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
index 144bcac..8d94d3d 100644
--- a/drivers/regulator/max8660.c
+++ b/drivers/regulator/max8660.c
@@ -439,7 +439,7 @@
 	for (i = 0; i < pdata->num_subdevs; i++) {
 
 		if (!pdata->subdevs[i].platform_data)
-			goto err_out;
+			return ret;
 
 		boot_on = pdata->subdevs[i].platform_data->constraints.boot_on;
 
@@ -465,7 +465,7 @@
 		case MAX8660_V7:
 			if (type == MAX8661) {
 				dev_err(dev, "Regulator not on this chip!\n");
-				goto err_out;
+				return -EINVAL;
 			}
 
 			if (boot_on)
@@ -475,7 +475,7 @@
 		default:
 			dev_err(dev, "invalid regulator %s\n",
 				 pdata->subdevs[i].name);
-			goto err_out;
+			return ret;
 		}
 	}
 
@@ -489,33 +489,18 @@
 		config.of_node = of_node[i];
 		config.driver_data = max8660;
 
-		rdev[i] = regulator_register(&max8660_reg[id], &config);
+		rdev[i] = devm_regulator_register(&client->dev,
+						  &max8660_reg[id], &config);
 		if (IS_ERR(rdev[i])) {
 			ret = PTR_ERR(rdev[i]);
-			dev_err(dev, "failed to register %s\n",
+			dev_err(&client->dev, "failed to register %s\n",
 				max8660_reg[id].name);
-			goto err_unregister;
+			return PTR_ERR(rdev[i]);
 		}
 	}
 
 	i2c_set_clientdata(client, max8660);
 	return 0;
-
-err_unregister:
-	while (--i >= 0)
-		regulator_unregister(rdev[i]);
-err_out:
-	return ret;
-}
-
-static int max8660_remove(struct i2c_client *client)
-{
-	struct max8660 *max8660 = i2c_get_clientdata(client);
-	int i;
-
-	for (i = 0; i < MAX8660_V_END; i++)
-		regulator_unregister(max8660->rdev[i]);
-	return 0;
 }
 
 static const struct i2c_device_id max8660_id[] = {
@@ -527,7 +512,6 @@
 
 static struct i2c_driver max8660_driver = {
 	.probe = max8660_probe,
-	.remove = max8660_remove,
 	.driver		= {
 		.name	= "max8660",
 		.owner	= THIS_MODULE,
diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c
index 4568c15..0c5fe6c 100644
--- a/drivers/regulator/max8907-regulator.c
+++ b/drivers/regulator/max8907-regulator.c
@@ -350,33 +350,17 @@
 				pmic->desc[i].ops = &max8907_out5v_hwctl_ops;
 		}
 
-		pmic->rdev[i] = regulator_register(&pmic->desc[i], &config);
+		pmic->rdev[i] = devm_regulator_register(&pdev->dev,
+						&pmic->desc[i], &config);
 		if (IS_ERR(pmic->rdev[i])) {
 			dev_err(&pdev->dev,
 				"failed to register %s regulator\n",
 				pmic->desc[i].name);
-			ret = PTR_ERR(pmic->rdev[i]);
-			goto err_unregister_regulator;
+			return PTR_ERR(pmic->rdev[i]);
 		}
 	}
 
 	return 0;
-
-err_unregister_regulator:
-	while (--i >= 0)
-		regulator_unregister(pmic->rdev[i]);
-	return ret;
-}
-
-static int max8907_regulator_remove(struct platform_device *pdev)
-{
-	struct max8907_regulator *pmic = platform_get_drvdata(pdev);
-	int i;
-
-	for (i = 0; i < MAX8907_NUM_REGULATORS; i++)
-		regulator_unregister(pmic->rdev[i]);
-
-	return 0;
 }
 
 static struct platform_driver max8907_regulator_driver = {
@@ -385,7 +369,6 @@
 		   .owner = THIS_MODULE,
 		   },
 	.probe = max8907_regulator_probe,
-	.remove = max8907_regulator_remove,
 };
 
 static int __init max8907_regulator_init(void)
diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c
index d80b5fa..7595107 100644
--- a/drivers/regulator/max8925-regulator.c
+++ b/drivers/regulator/max8925-regulator.c
@@ -312,7 +312,7 @@
 		if (pdata)
 			config.init_data = pdata;
 
-	rdev = regulator_register(&ri->desc, &config);
+	rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
 	if (IS_ERR(rdev)) {
 		dev_err(&pdev->dev, "failed to register regulator %s\n",
 				ri->desc.name);
@@ -323,22 +323,12 @@
 	return 0;
 }
 
-static int max8925_regulator_remove(struct platform_device *pdev)
-{
-	struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
-	regulator_unregister(rdev);
-
-	return 0;
-}
-
 static struct platform_driver max8925_regulator_driver = {
 	.driver		= {
 		.name	= "max8925-regulator",
 		.owner	= THIS_MODULE,
 	},
 	.probe		= max8925_regulator_probe,
-	.remove		= max8925_regulator_remove,
 };
 
 static int __init max8925_regulator_init(void)
diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c
index 5b77ab7..892aa1e 100644
--- a/drivers/regulator/max8973-regulator.c
+++ b/drivers/regulator/max8973-regulator.c
@@ -467,7 +467,7 @@
 	config.regmap = max->regmap;
 
 	/* Register the regulators */
-	rdev = regulator_register(&max->desc, &config);
+	rdev = devm_regulator_register(&client->dev, &max->desc, &config);
 	if (IS_ERR(rdev)) {
 		ret = PTR_ERR(rdev);
 		dev_err(max->dev, "regulator register failed, err %d\n", ret);
@@ -478,14 +478,6 @@
 	return 0;
 }
 
-static int max8973_remove(struct i2c_client *client)
-{
-	struct max8973_chip *max = i2c_get_clientdata(client);
-
-	regulator_unregister(max->rdev);
-	return 0;
-}
-
 static const struct i2c_device_id max8973_id[] = {
 	{.name = "max8973",},
 	{},
@@ -499,7 +491,6 @@
 		.owner = THIS_MODULE,
 	},
 	.probe = max8973_probe,
-	.remove = max8973_remove,
 	.id_table = max8973_id,
 };
 
diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
index df20069..2d618fc 100644
--- a/drivers/regulator/max8997.c
+++ b/drivers/regulator/max8997.c
@@ -690,8 +690,9 @@
 	if (max8997->ignore_gpiodvs_side_effect == false)
 		return -EINVAL;
 
-	dev_warn(&rdev->dev, "MAX8997 GPIO-DVS Side Effect Warning: GPIO SET:"
-			" %d -> %d\n", max8997->buck125_gpioindex, tmp_idx);
+	dev_warn(&rdev->dev,
+		"MAX8997 GPIO-DVS Side Effect Warning: GPIO SET:  %d -> %d\n",
+		max8997->buck125_gpioindex, tmp_idx);
 
 out:
 	if (new_idx < 0 || new_val < 0)
@@ -1081,7 +1082,7 @@
 					pdata->buck1_voltage[i] +
 					buck1245_voltage_map_desc.step);
 		if (ret < 0)
-			goto err_out;
+			return ret;
 
 		max8997->buck2_vol[i] = ret =
 			max8997_get_voltage_proper_val(
@@ -1090,7 +1091,7 @@
 					pdata->buck2_voltage[i] +
 					buck1245_voltage_map_desc.step);
 		if (ret < 0)
-			goto err_out;
+			return ret;
 
 		max8997->buck5_vol[i] = ret =
 			max8997_get_voltage_proper_val(
@@ -1099,7 +1100,7 @@
 					pdata->buck5_voltage[i] +
 					buck1245_voltage_map_desc.step);
 		if (ret < 0)
-			goto err_out;
+			return ret;
 
 		if (max_buck1 < max8997->buck1_vol[i])
 			max_buck1 = max8997->buck1_vol[i];
@@ -1143,24 +1144,23 @@
 				!gpio_is_valid(pdata->buck125_gpios[1]) ||
 				!gpio_is_valid(pdata->buck125_gpios[2])) {
 			dev_err(&pdev->dev, "GPIO NOT VALID\n");
-			ret = -EINVAL;
-			goto err_out;
+			return -EINVAL;
 		}
 
 		ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[0],
 					"MAX8997 SET1");
 		if (ret)
-			goto err_out;
+			return ret;
 
 		ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[1],
 					"MAX8997 SET2");
 		if (ret)
-			goto err_out;
+			return ret;
 
 		ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[2],
 				"MAX8997 SET3");
 		if (ret)
-			goto err_out;
+			return ret;
 
 		gpio_direction_output(pdata->buck125_gpios[0],
 				(max8997->buck125_gpioindex >> 2)
@@ -1205,33 +1205,16 @@
 		config.driver_data = max8997;
 		config.of_node = pdata->regulators[i].reg_node;
 
-		rdev[i] = regulator_register(&regulators[id], &config);
+		rdev[i] = devm_regulator_register(&pdev->dev, &regulators[id],
+						  &config);
 		if (IS_ERR(rdev[i])) {
-			ret = PTR_ERR(rdev[i]);
 			dev_err(max8997->dev, "regulator init failed for %d\n",
 					id);
-			rdev[i] = NULL;
-			goto err;
+			return PTR_ERR(rdev[i]);
 		}
 	}
 
 	return 0;
-err:
-	while (--i >= 0)
-		regulator_unregister(rdev[i]);
-err_out:
-	return ret;
-}
-
-static int max8997_pmic_remove(struct platform_device *pdev)
-{
-	struct max8997_data *max8997 = platform_get_drvdata(pdev);
-	struct regulator_dev **rdev = max8997->rdev;
-	int i;
-
-	for (i = 0; i < max8997->num_regulators; i++)
-		regulator_unregister(rdev[i]);
-	return 0;
 }
 
 static const struct platform_device_id max8997_pmic_id[] = {
@@ -1246,7 +1229,6 @@
 		.owner = THIS_MODULE,
 	},
 	.probe = max8997_pmic_probe,
-	.remove = max8997_pmic_remove,
 	.id_table = max8997_pmic_id,
 };
 
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c
index a4c53b2..ae3f065 100644
--- a/drivers/regulator/max8998.c
+++ b/drivers/regulator/max8998.c
@@ -790,16 +790,14 @@
 			dev_err(&pdev->dev,
 				"MAX8998 SET1 GPIO defined as 0 !\n");
 			WARN_ON(!pdata->buck1_set1);
-			ret = -EIO;
-			goto err_out;
+			return -EIO;
 		}
 		/* Check if SET2 is not equal to 0 */
 		if (!pdata->buck1_set2) {
 			dev_err(&pdev->dev,
 				"MAX8998 SET2 GPIO defined as 0 !\n");
 			WARN_ON(!pdata->buck1_set2);
-			ret = -EIO;
-			goto err_out;
+			return -EIO;
 		}
 
 		gpio_request(pdata->buck1_set1, "MAX8998 BUCK1_SET1");
@@ -823,7 +821,7 @@
 			ret = max8998_write_reg(i2c,
 					MAX8998_REG_BUCK1_VOLTAGE1 + v, i);
 			if (ret)
-				goto err_out;
+				return ret;
 		}
 	}
 
@@ -833,8 +831,7 @@
 			dev_err(&pdev->dev,
 				"MAX8998 SET3 GPIO defined as 0 !\n");
 			WARN_ON(!pdata->buck2_set3);
-			ret = -EIO;
-			goto err_out;
+			return -EIO;
 		}
 		gpio_request(pdata->buck2_set3, "MAX8998 BUCK2_SET3");
 		gpio_direction_output(pdata->buck2_set3,
@@ -852,7 +849,7 @@
 			ret = max8998_write_reg(i2c,
 					MAX8998_REG_BUCK2_VOLTAGE1 + v, i);
 			if (ret)
-				goto err_out;
+				return ret;
 		}
 	}
 
@@ -875,34 +872,19 @@
 		config.init_data = pdata->regulators[i].initdata;
 		config.driver_data = max8998;
 
-		rdev[i] = regulator_register(&regulators[index], &config);
+		rdev[i] = devm_regulator_register(&pdev->dev,
+						  &regulators[index], &config);
 		if (IS_ERR(rdev[i])) {
 			ret = PTR_ERR(rdev[i]);
 			dev_err(max8998->dev, "regulator %s init failed (%d)\n",
 						regulators[index].name, ret);
 			rdev[i] = NULL;
-			goto err;
+			return ret;
 		}
 	}
 
 
 	return 0;
-err:
-	while (--i >= 0)
-		regulator_unregister(rdev[i]);
-err_out:
-	return ret;
-}
-
-static int max8998_pmic_remove(struct platform_device *pdev)
-{
-	struct max8998_data *max8998 = platform_get_drvdata(pdev);
-	struct regulator_dev **rdev = max8998->rdev;
-	int i;
-
-	for (i = 0; i < max8998->num_regulators; i++)
-		regulator_unregister(rdev[i]);
-	return 0;
 }
 
 static const struct platform_device_id max8998_pmic_id[] = {
@@ -918,7 +900,6 @@
 		.owner = THIS_MODULE,
 	},
 	.probe = max8998_pmic_probe,
-	.remove = max8998_pmic_remove,
 	.id_table = max8998_pmic_id,
 };
 
diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c
index 5ff99d2..7f4a67e 100644
--- a/drivers/regulator/mc13783-regulator.c
+++ b/drivers/regulator/mc13783-regulator.c
@@ -258,34 +258,34 @@
 
 	MC13783_FIXED_DEFINE(REG, VAUDIO, REGULATORMODE0, mc13783_vaudio_val),
 	MC13783_FIXED_DEFINE(REG, VIOHI, REGULATORMODE0, mc13783_viohi_val),
-	MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0, REGULATORSETTING0,	\
+	MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0, REGULATORSETTING0,
 			    mc13783_violo_val),
-	MC13783_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0,	\
+	MC13783_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0,
 			    mc13783_vdig_val),
-	MC13783_DEFINE_REGU(VGEN, REGULATORMODE0, REGULATORSETTING0,	\
+	MC13783_DEFINE_REGU(VGEN, REGULATORMODE0, REGULATORSETTING0,
 			    mc13783_vgen_val),
-	MC13783_DEFINE_REGU(VRFDIG, REGULATORMODE0, REGULATORSETTING0,	\
+	MC13783_DEFINE_REGU(VRFDIG, REGULATORMODE0, REGULATORSETTING0,
 			    mc13783_vrfdig_val),
-	MC13783_DEFINE_REGU(VRFREF, REGULATORMODE0, REGULATORSETTING0,	\
+	MC13783_DEFINE_REGU(VRFREF, REGULATORMODE0, REGULATORSETTING0,
 			    mc13783_vrfref_val),
-	MC13783_DEFINE_REGU(VRFCP, REGULATORMODE0, REGULATORSETTING0,	\
+	MC13783_DEFINE_REGU(VRFCP, REGULATORMODE0, REGULATORSETTING0,
 			    mc13783_vrfcp_val),
-	MC13783_DEFINE_REGU(VSIM, REGULATORMODE1, REGULATORSETTING0,	\
+	MC13783_DEFINE_REGU(VSIM, REGULATORMODE1, REGULATORSETTING0,
 			    mc13783_vsim_val),
-	MC13783_DEFINE_REGU(VESIM, REGULATORMODE1, REGULATORSETTING0,	\
+	MC13783_DEFINE_REGU(VESIM, REGULATORMODE1, REGULATORSETTING0,
 			    mc13783_vesim_val),
-	MC13783_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0,	\
+	MC13783_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0,
 			    mc13783_vcam_val),
 	MC13783_FIXED_DEFINE(REG, VRFBG, REGULATORMODE1, mc13783_vrfbg_val),
-	MC13783_DEFINE_REGU(VVIB, REGULATORMODE1, REGULATORSETTING1,	\
+	MC13783_DEFINE_REGU(VVIB, REGULATORMODE1, REGULATORSETTING1,
 			    mc13783_vvib_val),
-	MC13783_DEFINE_REGU(VRF1, REGULATORMODE1, REGULATORSETTING1,	\
+	MC13783_DEFINE_REGU(VRF1, REGULATORMODE1, REGULATORSETTING1,
 			    mc13783_vrf_val),
-	MC13783_DEFINE_REGU(VRF2, REGULATORMODE1, REGULATORSETTING1,	\
+	MC13783_DEFINE_REGU(VRF2, REGULATORMODE1, REGULATORSETTING1,
 			    mc13783_vrf_val),
-	MC13783_DEFINE_REGU(VMMC1, REGULATORMODE1, REGULATORSETTING1,	\
+	MC13783_DEFINE_REGU(VMMC1, REGULATORMODE1, REGULATORSETTING1,
 			    mc13783_vmmc_val),
-	MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1, REGULATORSETTING1,	\
+	MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1, REGULATORSETTING1,
 			    mc13783_vmmc_val),
 	MC13783_GPO_DEFINE(REG, GPO1, POWERMISC, mc13783_gpo_val),
 	MC13783_GPO_DEFINE(REG, GPO2, POWERMISC, mc13783_gpo_val),
@@ -400,7 +400,7 @@
 		dev_get_platdata(&pdev->dev);
 	struct mc13xxx_regulator_init_data *mc13xxx_data;
 	struct regulator_config config = { };
-	int i, ret, num_regulators;
+	int i, num_regulators;
 
 	num_regulators = mc13xxx_get_num_regulators_dt(pdev);
 
@@ -444,32 +444,16 @@
 		config.driver_data = priv;
 		config.of_node = node;
 
-		priv->regulators[i] = regulator_register(desc, &config);
+		priv->regulators[i] = devm_regulator_register(&pdev->dev, desc,
+							      &config);
 		if (IS_ERR(priv->regulators[i])) {
 			dev_err(&pdev->dev, "failed to register regulator %s\n",
 				mc13783_regulators[i].desc.name);
-			ret = PTR_ERR(priv->regulators[i]);
-			goto err;
+			return PTR_ERR(priv->regulators[i]);
 		}
 	}
 
 	return 0;
-err:
-	while (--i >= 0)
-		regulator_unregister(priv->regulators[i]);
-
-	return ret;
-}
-
-static int mc13783_regulator_remove(struct platform_device *pdev)
-{
-	struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
-	int i;
-
-	for (i = 0; i < priv->num_regulators; i++)
-		regulator_unregister(priv->regulators[i]);
-
-	return 0;
 }
 
 static struct platform_driver mc13783_regulator_driver = {
@@ -477,7 +461,6 @@
 		.name	= "mc13783-regulator",
 		.owner	= THIS_MODULE,
 	},
-	.remove		= mc13783_regulator_remove,
 	.probe		= mc13783_regulator_probe,
 };
 
diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c
index 1037e07..96c9f80 100644
--- a/drivers/regulator/mc13892-regulator.c
+++ b/drivers/regulator/mc13892-regulator.c
@@ -611,43 +611,27 @@
 		config.driver_data = priv;
 		config.of_node = node;
 
-		priv->regulators[i] = regulator_register(desc, &config);
+		priv->regulators[i] = devm_regulator_register(&pdev->dev, desc,
+							      &config);
 		if (IS_ERR(priv->regulators[i])) {
 			dev_err(&pdev->dev, "failed to register regulator %s\n",
 				mc13892_regulators[i].desc.name);
-			ret = PTR_ERR(priv->regulators[i]);
-			goto err;
+			return PTR_ERR(priv->regulators[i]);
 		}
 	}
 
 	return 0;
-err:
-	while (--i >= 0)
-		regulator_unregister(priv->regulators[i]);
-	return ret;
 
 err_unlock:
 	mc13xxx_unlock(mc13892);
 	return ret;
 }
 
-static int mc13892_regulator_remove(struct platform_device *pdev)
-{
-	struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
-	int i;
-
-	for (i = 0; i < priv->num_regulators; i++)
-		regulator_unregister(priv->regulators[i]);
-
-	return 0;
-}
-
 static struct platform_driver mc13892_regulator_driver = {
 	.driver	= {
 		.name	= "mc13892-regulator",
 		.owner	= THIS_MODULE,
 	},
-	.remove	= mc13892_regulator_remove,
 	.probe	= mc13892_regulator_probe,
 };
 
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 7827384..ea4f36f 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -23,6 +23,8 @@
 	const __be32 *min_uA, *max_uA, *ramp_delay;
 	struct property *prop;
 	struct regulation_constraints *constraints = &(*init_data)->constraints;
+	int ret;
+	u32 pval;
 
 	constraints->name = of_get_property(np, "regulator-name", NULL);
 
@@ -73,6 +75,10 @@
 		else
 			constraints->ramp_disable = true;
 	}
+
+	ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval);
+	if (!ret)
+		constraints->enable_time = pval;
 }
 
 /**
diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c
index 7e2b165..9c62b1d 100644
--- a/drivers/regulator/palmas-regulator.c
+++ b/drivers/regulator/palmas-regulator.c
@@ -33,6 +33,7 @@
 	u8	vsel_addr;
 	u8	ctrl_addr;
 	u8	tstep_addr;
+	int	sleep_id;
 };
 
 static const struct regs_info palmas_regs_info[] = {
@@ -42,6 +43,7 @@
 		.vsel_addr	= PALMAS_SMPS12_VOLTAGE,
 		.ctrl_addr	= PALMAS_SMPS12_CTRL,
 		.tstep_addr	= PALMAS_SMPS12_TSTEP,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_SMPS12,
 	},
 	{
 		.name		= "SMPS123",
@@ -49,12 +51,14 @@
 		.vsel_addr	= PALMAS_SMPS12_VOLTAGE,
 		.ctrl_addr	= PALMAS_SMPS12_CTRL,
 		.tstep_addr	= PALMAS_SMPS12_TSTEP,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_SMPS12,
 	},
 	{
 		.name		= "SMPS3",
 		.sname		= "smps3-in",
 		.vsel_addr	= PALMAS_SMPS3_VOLTAGE,
 		.ctrl_addr	= PALMAS_SMPS3_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_SMPS3,
 	},
 	{
 		.name		= "SMPS45",
@@ -62,6 +66,7 @@
 		.vsel_addr	= PALMAS_SMPS45_VOLTAGE,
 		.ctrl_addr	= PALMAS_SMPS45_CTRL,
 		.tstep_addr	= PALMAS_SMPS45_TSTEP,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_SMPS45,
 	},
 	{
 		.name		= "SMPS457",
@@ -69,6 +74,7 @@
 		.vsel_addr	= PALMAS_SMPS45_VOLTAGE,
 		.ctrl_addr	= PALMAS_SMPS45_CTRL,
 		.tstep_addr	= PALMAS_SMPS45_TSTEP,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_SMPS45,
 	},
 	{
 		.name		= "SMPS6",
@@ -76,12 +82,14 @@
 		.vsel_addr	= PALMAS_SMPS6_VOLTAGE,
 		.ctrl_addr	= PALMAS_SMPS6_CTRL,
 		.tstep_addr	= PALMAS_SMPS6_TSTEP,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_SMPS6,
 	},
 	{
 		.name		= "SMPS7",
 		.sname		= "smps7-in",
 		.vsel_addr	= PALMAS_SMPS7_VOLTAGE,
 		.ctrl_addr	= PALMAS_SMPS7_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_SMPS7,
 	},
 	{
 		.name		= "SMPS8",
@@ -89,108 +97,128 @@
 		.vsel_addr	= PALMAS_SMPS8_VOLTAGE,
 		.ctrl_addr	= PALMAS_SMPS8_CTRL,
 		.tstep_addr	= PALMAS_SMPS8_TSTEP,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_SMPS8,
 	},
 	{
 		.name		= "SMPS9",
 		.sname		= "smps9-in",
 		.vsel_addr	= PALMAS_SMPS9_VOLTAGE,
 		.ctrl_addr	= PALMAS_SMPS9_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_SMPS9,
 	},
 	{
 		.name		= "SMPS10_OUT2",
 		.sname		= "smps10-in",
 		.ctrl_addr	= PALMAS_SMPS10_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_SMPS10,
 	},
 	{
 		.name		= "SMPS10_OUT1",
 		.sname		= "smps10-out2",
 		.ctrl_addr	= PALMAS_SMPS10_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_SMPS10,
 	},
 	{
 		.name		= "LDO1",
 		.sname		= "ldo1-in",
 		.vsel_addr	= PALMAS_LDO1_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDO1_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_LDO1,
 	},
 	{
 		.name		= "LDO2",
 		.sname		= "ldo2-in",
 		.vsel_addr	= PALMAS_LDO2_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDO2_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_LDO2,
 	},
 	{
 		.name		= "LDO3",
 		.sname		= "ldo3-in",
 		.vsel_addr	= PALMAS_LDO3_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDO3_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_LDO3,
 	},
 	{
 		.name		= "LDO4",
 		.sname		= "ldo4-in",
 		.vsel_addr	= PALMAS_LDO4_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDO4_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_LDO4,
 	},
 	{
 		.name		= "LDO5",
 		.sname		= "ldo5-in",
 		.vsel_addr	= PALMAS_LDO5_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDO5_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_LDO5,
 	},
 	{
 		.name		= "LDO6",
 		.sname		= "ldo6-in",
 		.vsel_addr	= PALMAS_LDO6_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDO6_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_LDO6,
 	},
 	{
 		.name		= "LDO7",
 		.sname		= "ldo7-in",
 		.vsel_addr	= PALMAS_LDO7_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDO7_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_LDO7,
 	},
 	{
 		.name		= "LDO8",
 		.sname		= "ldo8-in",
 		.vsel_addr	= PALMAS_LDO8_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDO8_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_LDO8,
 	},
 	{
 		.name		= "LDO9",
 		.sname		= "ldo9-in",
 		.vsel_addr	= PALMAS_LDO9_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDO9_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_LDO9,
 	},
 	{
 		.name		= "LDOLN",
 		.sname		= "ldoln-in",
 		.vsel_addr	= PALMAS_LDOLN_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDOLN_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_LDOLN,
 	},
 	{
 		.name		= "LDOUSB",
 		.sname		= "ldousb-in",
 		.vsel_addr	= PALMAS_LDOUSB_VOLTAGE,
 		.ctrl_addr	= PALMAS_LDOUSB_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_LDOUSB,
 	},
 	{
 		.name		= "REGEN1",
 		.ctrl_addr	= PALMAS_REGEN1_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_REGEN1,
 	},
 	{
 		.name		= "REGEN2",
 		.ctrl_addr	= PALMAS_REGEN2_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_REGEN2,
 	},
 	{
 		.name		= "REGEN3",
 		.ctrl_addr	= PALMAS_REGEN3_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_REGEN3,
 	},
 	{
 		.name		= "SYSEN1",
 		.ctrl_addr	= PALMAS_SYSEN1_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_SYSEN1,
 	},
 	{
 		.name		= "SYSEN2",
 		.ctrl_addr	= PALMAS_SYSEN2_CTRL,
+		.sleep_id	= PALMAS_EXTERNAL_REQSTR_ID_SYSEN2,
 	},
 };
 
@@ -478,6 +506,17 @@
 	.set_ramp_delay		= palmas_smps_set_ramp_delay,
 };
 
+static struct regulator_ops palmas_ops_ext_control_smps = {
+	.set_mode		= palmas_set_mode_smps,
+	.get_mode		= palmas_get_mode_smps,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.list_voltage		= palmas_list_voltage_smps,
+	.map_voltage		= palmas_map_voltage_smps,
+	.set_voltage_time_sel	= palma_smps_set_voltage_smps_time_sel,
+	.set_ramp_delay		= palmas_smps_set_ramp_delay,
+};
+
 static struct regulator_ops palmas_ops_smps10 = {
 	.is_enabled		= regulator_is_enabled_regmap,
 	.enable			= regulator_enable_regmap,
@@ -513,12 +552,37 @@
 	.map_voltage		= regulator_map_voltage_linear,
 };
 
+static struct regulator_ops palmas_ops_ext_control_ldo = {
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.list_voltage		= regulator_list_voltage_linear,
+	.map_voltage		= regulator_map_voltage_linear,
+};
+
 static struct regulator_ops palmas_ops_extreg = {
 	.is_enabled		= regulator_is_enabled_regmap,
 	.enable			= regulator_enable_regmap,
 	.disable		= regulator_disable_regmap,
 };
 
+static struct regulator_ops palmas_ops_ext_control_extreg = {
+};
+
+static int palmas_regulator_config_external(struct palmas *palmas, int id,
+		struct palmas_reg_init *reg_init)
+{
+	int sleep_id = palmas_regs_info[id].sleep_id;
+	int ret;
+
+	ret = palmas_ext_control_req_config(palmas, sleep_id,
+					reg_init->roof_floor, true);
+	if (ret < 0)
+		dev_err(palmas->dev,
+			"Ext control config for regulator %d failed %d\n",
+			id, ret);
+	return ret;
+}
+
 /*
  * setup the hardware based sleep configuration of the SMPS/LDO regulators
  * from the platform data. This is different to the software based control
@@ -577,7 +641,22 @@
 			return ret;
 	}
 
+	if (reg_init->roof_floor && (id != PALMAS_REG_SMPS10_OUT1) &&
+			(id != PALMAS_REG_SMPS10_OUT2)) {
+		/* Enable externally controlled regulator */
+		addr = palmas_regs_info[id].ctrl_addr;
+		ret = palmas_smps_read(palmas, addr, &reg);
+		if (ret < 0)
+			return ret;
 
+		if (!(reg & PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK)) {
+			reg |= SMPS_CTRL_MODE_ON;
+			ret = palmas_smps_write(palmas, addr, reg);
+			if (ret < 0)
+				return ret;
+		}
+		return palmas_regulator_config_external(palmas, id, reg_init);
+	}
 	return 0;
 }
 
@@ -608,6 +687,20 @@
 	if (ret)
 		return ret;
 
+	if (reg_init->roof_floor) {
+		/* Enable externally controlled regulator */
+		addr = palmas_regs_info[id].ctrl_addr;
+		ret = palmas_update_bits(palmas, PALMAS_LDO_BASE,
+				addr, PALMAS_LDO1_CTRL_MODE_ACTIVE,
+				PALMAS_LDO1_CTRL_MODE_ACTIVE);
+		if (ret < 0) {
+			dev_err(palmas->dev,
+				"LDO Register 0x%02x update failed %d\n",
+				addr, ret);
+			return ret;
+		}
+		return palmas_regulator_config_external(palmas, id, reg_init);
+	}
 	return 0;
 }
 
@@ -630,6 +723,21 @@
 			addr, ret);
 		return ret;
 	}
+
+	if (reg_init->roof_floor) {
+		/* Enable externally controlled regulator */
+		addr = palmas_regs_info[id].ctrl_addr;
+		ret = palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
+				addr, PALMAS_REGEN1_CTRL_MODE_ACTIVE,
+				PALMAS_REGEN1_CTRL_MODE_ACTIVE);
+		if (ret < 0) {
+			dev_err(palmas->dev,
+				"Resource Register 0x%02x update failed %d\n",
+				addr, ret);
+			return ret;
+		}
+		return palmas_regulator_config_external(palmas, id, reg_init);
+	}
 	return 0;
 }
 
@@ -712,7 +820,7 @@
 	int idx, ret;
 
 	node = of_node_get(node);
-	regulators = of_find_node_by_name(node, "regulators");
+	regulators = of_get_child_by_name(node, "regulators");
 	if (!regulators) {
 		dev_info(dev, "regulator node not found\n");
 		return;
@@ -740,9 +848,35 @@
 			of_property_read_bool(palmas_matches[idx].of_node,
 					     "ti,warm-reset");
 
-		pdata->reg_init[idx]->roof_floor =
-			of_property_read_bool(palmas_matches[idx].of_node,
-					      "ti,roof-floor");
+		ret = of_property_read_u32(palmas_matches[idx].of_node,
+					      "ti,roof-floor", &prop);
+		/* EINVAL: Property not found */
+		if (ret != -EINVAL) {
+			int econtrol;
+
+			/* use default value, when no value is specified */
+			econtrol = PALMAS_EXT_CONTROL_NSLEEP;
+			if (!ret) {
+				switch (prop) {
+				case 1:
+					econtrol = PALMAS_EXT_CONTROL_ENABLE1;
+					break;
+				case 2:
+					econtrol = PALMAS_EXT_CONTROL_ENABLE2;
+					break;
+				case 3:
+					econtrol = PALMAS_EXT_CONTROL_NSLEEP;
+					break;
+				default:
+					WARN_ON(1);
+					dev_warn(dev,
+					"%s: Invalid roof-floor option: %u\n",
+					     palmas_matches[idx].name, prop);
+					break;
+				}
+			}
+			pdata->reg_init[idx]->roof_floor = econtrol;
+		}
 
 		ret = of_property_read_u32(palmas_matches[idx].of_node,
 				"ti,mode-sleep", &prop);
@@ -856,7 +990,7 @@
 			if (ret < 0) {
 				dev_err(&pdev->dev,
 					"reading TSTEP reg failed: %d\n", ret);
-				goto err_unregister_regulator;
+				return ret;
 			}
 			pmic->desc[id].ramp_delay =
 					palmas_smps_ramp_delay[reg & 0x3];
@@ -868,7 +1002,9 @@
 			reg_init = pdata->reg_init[id];
 			ret = palmas_smps_init(palmas, id, reg_init);
 			if (ret)
-				goto err_unregister_regulator;
+				return ret;
+		} else {
+			reg_init = NULL;
 		}
 
 		/* Register the regulators */
@@ -909,11 +1045,15 @@
 
 			ret = palmas_smps_read(pmic->palmas, addr, &reg);
 			if (ret)
-				goto err_unregister_regulator;
+				return ret;
 			if (reg & PALMAS_SMPS12_VOLTAGE_RANGE)
 				pmic->range[id] = 1;
 
-			pmic->desc[id].ops = &palmas_ops_smps;
+			if (reg_init && reg_init->roof_floor)
+				pmic->desc[id].ops =
+						&palmas_ops_ext_control_smps;
+			else
+				pmic->desc[id].ops = &palmas_ops_smps;
 			pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
 			pmic->desc[id].vsel_reg =
 					PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
@@ -925,7 +1065,7 @@
 			addr = palmas_regs_info[id].ctrl_addr;
 			ret = palmas_smps_read(pmic->palmas, addr, &reg);
 			if (ret)
-				goto err_unregister_regulator;
+				return ret;
 			pmic->current_reg_mode[id] = reg &
 					PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
 		}
@@ -941,13 +1081,13 @@
 		pmic->desc[id].supply_name = palmas_regs_info[id].sname;
 		config.of_node = palmas_matches[id].of_node;
 
-		rdev = regulator_register(&pmic->desc[id], &config);
+		rdev = devm_regulator_register(&pdev->dev, &pmic->desc[id],
+					       &config);
 		if (IS_ERR(rdev)) {
 			dev_err(&pdev->dev,
 				"failed to register %s regulator\n",
 				pdev->name);
-			ret = PTR_ERR(rdev);
-			goto err_unregister_regulator;
+			return PTR_ERR(rdev);
 		}
 
 		/* Save regulator for cleanup */
@@ -956,6 +1096,10 @@
 
 	/* Start this loop from the id left from previous loop */
 	for (; id < PALMAS_NUM_REGS; id++) {
+		if (pdata && pdata->reg_init[id])
+			reg_init = pdata->reg_init[id];
+		else
+			reg_init = NULL;
 
 		/* Miss out regulators which are not available due
 		 * to alternate functions.
@@ -969,7 +1113,11 @@
 
 		if (id < PALMAS_REG_REGEN1) {
 			pmic->desc[id].n_voltages = PALMAS_LDO_NUM_VOLTAGES;
-			pmic->desc[id].ops = &palmas_ops_ldo;
+			if (reg_init && reg_init->roof_floor)
+				pmic->desc[id].ops =
+					&palmas_ops_ext_control_ldo;
+			else
+				pmic->desc[id].ops = &palmas_ops_ldo;
 			pmic->desc[id].min_uV = 900000;
 			pmic->desc[id].uV_step = 50000;
 			pmic->desc[id].linear_min_sel = 1;
@@ -999,7 +1147,11 @@
 				pmic->desc[id].enable_time = 2000;
 		} else {
 			pmic->desc[id].n_voltages = 1;
-			pmic->desc[id].ops = &palmas_ops_extreg;
+			if (reg_init && reg_init->roof_floor)
+				pmic->desc[id].ops =
+					&palmas_ops_ext_control_extreg;
+			else
+				pmic->desc[id].ops = &palmas_ops_extreg;
 			pmic->desc[id].enable_reg =
 					PALMAS_BASE_TO_REG(PALMAS_RESOURCE_BASE,
 						palmas_regs_info[id].ctrl_addr);
@@ -1015,13 +1167,13 @@
 		pmic->desc[id].supply_name = palmas_regs_info[id].sname;
 		config.of_node = palmas_matches[id].of_node;
 
-		rdev = regulator_register(&pmic->desc[id], &config);
+		rdev = devm_regulator_register(&pdev->dev, &pmic->desc[id],
+					       &config);
 		if (IS_ERR(rdev)) {
 			dev_err(&pdev->dev,
 				"failed to register %s regulator\n",
 				pdev->name);
-			ret = PTR_ERR(rdev);
-			goto err_unregister_regulator;
+			return PTR_ERR(rdev);
 		}
 
 		/* Save regulator for cleanup */
@@ -1037,31 +1189,14 @@
 				else
 					ret = palmas_extreg_init(palmas,
 							id, reg_init);
-				if (ret) {
-					regulator_unregister(pmic->rdev[id]);
-					goto err_unregister_regulator;
-				}
+				if (ret)
+					return ret;
 			}
 		}
 	}
 
 
 	return 0;
-
-err_unregister_regulator:
-	while (--id >= 0)
-		regulator_unregister(pmic->rdev[id]);
-	return ret;
-}
-
-static int palmas_regulators_remove(struct platform_device *pdev)
-{
-	struct palmas_pmic *pmic = platform_get_drvdata(pdev);
-	int id;
-
-	for (id = 0; id < PALMAS_NUM_REGS; id++)
-		regulator_unregister(pmic->rdev[id]);
-	return 0;
 }
 
 static struct of_device_id of_palmas_match_tbl[] = {
@@ -1083,7 +1218,6 @@
 		.owner = THIS_MODULE,
 	},
 	.probe = palmas_regulators_probe,
-	.remove = palmas_regulators_remove,
 };
 
 static int __init palmas_init(void)
diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c
index b49eaee..3727b7d 100644
--- a/drivers/regulator/pcap-regulator.c
+++ b/drivers/regulator/pcap-regulator.c
@@ -246,7 +246,8 @@
 	config.init_data = dev_get_platdata(&pdev->dev);
 	config.driver_data = pcap;
 
-	rdev = regulator_register(&pcap_regulators[pdev->id], &config);
+	rdev = devm_regulator_register(&pdev->dev, &pcap_regulators[pdev->id],
+				       &config);
 	if (IS_ERR(rdev))
 		return PTR_ERR(rdev);
 
@@ -255,22 +256,12 @@
 	return 0;
 }
 
-static int pcap_regulator_remove(struct platform_device *pdev)
-{
-	struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
-	regulator_unregister(rdev);
-
-	return 0;
-}
-
 static struct platform_driver pcap_regulator_driver = {
 	.driver = {
 		.name	= "pcap-regulator",
 		.owner	= THIS_MODULE,
 	},
 	.probe	= pcap_regulator_probe,
-	.remove	= pcap_regulator_remove,
 };
 
 static int __init pcap_regulator_init(void)
diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c
index 0f3576d..d7da1c1 100644
--- a/drivers/regulator/pcf50633-regulator.c
+++ b/drivers/regulator/pcf50633-regulator.c
@@ -90,7 +90,8 @@
 	config.driver_data = pcf;
 	config.regmap = pcf->regmap;
 
-	rdev = regulator_register(&regulators[pdev->id], &config);
+	rdev = devm_regulator_register(&pdev->dev, &regulators[pdev->id],
+				       &config);
 	if (IS_ERR(rdev))
 		return PTR_ERR(rdev);
 
@@ -102,21 +103,11 @@
 	return 0;
 }
 
-static int pcf50633_regulator_remove(struct platform_device *pdev)
-{
-	struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
-	regulator_unregister(rdev);
-
-	return 0;
-}
-
 static struct platform_driver pcf50633_regulator_driver = {
 	.driver = {
 		.name = "pcf50633-regltr",
 	},
 	.probe = pcf50633_regulator_probe,
-	.remove = pcf50633_regulator_remove,
 };
 
 static int __init pcf50633_regulator_init(void)
diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c
index 5885b45..b58affb 100644
--- a/drivers/regulator/rc5t583-regulator.c
+++ b/drivers/regulator/rc5t583-regulator.c
@@ -173,33 +173,16 @@
 		config.driver_data = reg;
 		config.regmap = rc5t583->regmap;
 
-		rdev = regulator_register(&ri->desc, &config);
+		rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
 		if (IS_ERR(rdev)) {
 			dev_err(&pdev->dev, "Failed to register regulator %s\n",
 						ri->desc.name);
-			ret = PTR_ERR(rdev);
-			goto clean_exit;
+			return PTR_ERR(rdev);
 		}
 		reg->rdev = rdev;
 	}
 	platform_set_drvdata(pdev, regs);
 	return 0;
-
-clean_exit:
-	while (--id >= 0)
-		regulator_unregister(regs[id].rdev);
-
-	return ret;
-}
-
-static int rc5t583_regulator_remove(struct platform_device *pdev)
-{
-	struct rc5t583_regulator *regs = platform_get_drvdata(pdev);
-	int id;
-
-	for (id = 0; id < RC5T583_REGULATOR_MAX; ++id)
-		regulator_unregister(regs[id].rdev);
-	return 0;
 }
 
 static struct platform_driver rc5t583_regulator_driver = {
@@ -208,7 +191,6 @@
 		.owner	= THIS_MODULE,
 	},
 	.probe		= rc5t583_regulator_probe,
-	.remove		= rc5t583_regulator_remove,
 };
 
 static int __init rc5t583_regulator_init(void)
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 5eba2ff..333677d 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -448,33 +448,17 @@
 			config.of_node = rdata[i].of_node;
 		}
 
-		s2mps11->rdev[i] = regulator_register(&regulators[i], &config);
+		s2mps11->rdev[i] = devm_regulator_register(&pdev->dev,
+						&regulators[i], &config);
 		if (IS_ERR(s2mps11->rdev[i])) {
 			ret = PTR_ERR(s2mps11->rdev[i]);
 			dev_err(&pdev->dev, "regulator init failed for %d\n",
 				i);
-			s2mps11->rdev[i] = NULL;
-			goto err;
+			return ret;
 		}
 	}
 
 	return 0;
-err:
-	for (i = 0; i < S2MPS11_REGULATOR_MAX; i++)
-		regulator_unregister(s2mps11->rdev[i]);
-
-	return ret;
-}
-
-static int s2mps11_pmic_remove(struct platform_device *pdev)
-{
-	struct s2mps11_info *s2mps11 = platform_get_drvdata(pdev);
-	int i;
-
-	for (i = 0; i < S2MPS11_REGULATOR_MAX; i++)
-		regulator_unregister(s2mps11->rdev[i]);
-
-	return 0;
 }
 
 static const struct platform_device_id s2mps11_pmic_id[] = {
@@ -489,7 +473,6 @@
 		.owner = THIS_MODULE,
 	},
 	.probe = s2mps11_pmic_probe,
-	.remove = s2mps11_pmic_remove,
 	.id_table = s2mps11_pmic_id,
 };
 
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index c24448b..cbf91e2 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -522,7 +522,7 @@
 	struct device_node *pmic_np, *regulators_np, *reg_np;
 	struct sec_regulator_data *rdata;
 	struct sec_opmode_data *rmode;
-	unsigned int i, dvs_voltage_nr = 1, ret;
+	unsigned int i, dvs_voltage_nr = 8, ret;
 
 	pmic_np = iodev->dev->of_node;
 	if (!pmic_np) {
@@ -586,15 +586,39 @@
 		rmode++;
 	}
 
-	if (of_get_property(pmic_np, "s5m8767,pmic-buck2-uses-gpio-dvs", NULL))
+	if (of_get_property(pmic_np, "s5m8767,pmic-buck2-uses-gpio-dvs", NULL)) {
 		pdata->buck2_gpiodvs = true;
 
-	if (of_get_property(pmic_np, "s5m8767,pmic-buck3-uses-gpio-dvs", NULL))
+		if (of_property_read_u32_array(pmic_np,
+				"s5m8767,pmic-buck2-dvs-voltage",
+				pdata->buck2_voltage, dvs_voltage_nr)) {
+			dev_err(iodev->dev, "buck2 voltages not specified\n");
+			return -EINVAL;
+		}
+	}
+
+	if (of_get_property(pmic_np, "s5m8767,pmic-buck3-uses-gpio-dvs", NULL)) {
 		pdata->buck3_gpiodvs = true;
 
-	if (of_get_property(pmic_np, "s5m8767,pmic-buck4-uses-gpio-dvs", NULL))
+		if (of_property_read_u32_array(pmic_np,
+				"s5m8767,pmic-buck3-dvs-voltage",
+				pdata->buck3_voltage, dvs_voltage_nr)) {
+			dev_err(iodev->dev, "buck3 voltages not specified\n");
+			return -EINVAL;
+		}
+	}
+
+	if (of_get_property(pmic_np, "s5m8767,pmic-buck4-uses-gpio-dvs", NULL)) {
 		pdata->buck4_gpiodvs = true;
 
+		if (of_property_read_u32_array(pmic_np,
+				"s5m8767,pmic-buck4-dvs-voltage",
+				pdata->buck4_voltage, dvs_voltage_nr)) {
+			dev_err(iodev->dev, "buck4 voltages not specified\n");
+			return -EINVAL;
+		}
+	}
+
 	if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
 						pdata->buck4_gpiodvs) {
 		ret = s5m8767_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np);
@@ -612,32 +636,26 @@
 				"invalid value for default dvs index, use 0\n");
 			}
 		}
-		dvs_voltage_nr = 8;
 	}
 
 	ret = s5m8767_pmic_dt_parse_ds_gpio(iodev, pdata, pmic_np);
 	if (ret)
 		return -EINVAL;
 
-	if (of_property_read_u32_array(pmic_np,
-				"s5m8767,pmic-buck2-dvs-voltage",
-				pdata->buck2_voltage, dvs_voltage_nr)) {
-		dev_err(iodev->dev, "buck2 voltages not specified\n");
-		return -EINVAL;
-	}
+	if (of_get_property(pmic_np, "s5m8767,pmic-buck2-ramp-enable", NULL))
+		pdata->buck2_ramp_enable = true;
 
-	if (of_property_read_u32_array(pmic_np,
-				"s5m8767,pmic-buck3-dvs-voltage",
-				pdata->buck3_voltage, dvs_voltage_nr)) {
-		dev_err(iodev->dev, "buck3 voltages not specified\n");
-		return -EINVAL;
-	}
+	if (of_get_property(pmic_np, "s5m8767,pmic-buck3-ramp-enable", NULL))
+		pdata->buck3_ramp_enable = true;
 
-	if (of_property_read_u32_array(pmic_np,
-				"s5m8767,pmic-buck4-dvs-voltage",
-				pdata->buck4_voltage, dvs_voltage_nr)) {
-		dev_err(iodev->dev, "buck4 voltages not specified\n");
-		return -EINVAL;
+	if (of_get_property(pmic_np, "s5m8767,pmic-buck4-ramp-enable", NULL))
+		pdata->buck4_ramp_enable = true;
+
+	if (pdata->buck2_ramp_enable || pdata->buck3_ramp_enable
+			|| pdata->buck4_ramp_enable) {
+		if (of_property_read_u32(pmic_np, "s5m8767,pmic-buck-ramp-delay",
+				&pdata->buck_ramp_delay))
+			pdata->buck_ramp_delay = 0;
 	}
 
 	return 0;
@@ -910,34 +928,17 @@
 		config.regmap = iodev->regmap;
 		config.of_node = pdata->regulators[i].reg_node;
 
-		rdev[i] = regulator_register(&regulators[id], &config);
+		rdev[i] = devm_regulator_register(&pdev->dev, &regulators[id],
+						  &config);
 		if (IS_ERR(rdev[i])) {
 			ret = PTR_ERR(rdev[i]);
 			dev_err(s5m8767->dev, "regulator init failed for %d\n",
 					id);
-			rdev[i] = NULL;
-			goto err;
+			return ret;
 		}
 	}
 
 	return 0;
-err:
-	for (i = 0; i < s5m8767->num_regulators; i++)
-		regulator_unregister(rdev[i]);
-
-	return ret;
-}
-
-static int s5m8767_pmic_remove(struct platform_device *pdev)
-{
-	struct s5m8767_info *s5m8767 = platform_get_drvdata(pdev);
-	struct regulator_dev **rdev = s5m8767->rdev;
-	int i;
-
-	for (i = 0; i < s5m8767->num_regulators; i++)
-		regulator_unregister(rdev[i]);
-
-	return 0;
 }
 
 static const struct platform_device_id s5m8767_pmic_id[] = {
@@ -952,7 +953,6 @@
 		.owner = THIS_MODULE,
 	},
 	.probe = s5m8767_pmic_probe,
-	.remove = s5m8767_pmic_remove,
 	.id_table = s5m8767_pmic_id,
 };
 
diff --git a/drivers/regulator/stw481x-vmmc.c b/drivers/regulator/stw481x-vmmc.c
new file mode 100644
index 0000000..f78857b
--- /dev/null
+++ b/drivers/regulator/stw481x-vmmc.c
@@ -0,0 +1,111 @@
+/*
+ * Regulator driver for STw4810/STw4811 VMMC regulator.
+ *
+ * Copyright (C) 2013 ST-Ericsson SA
+ * Written on behalf of Linaro for ST-Ericsson
+ *
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/mfd/stw481x.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+
+static const unsigned int stw481x_vmmc_voltages[] = {
+	1800000,
+	1800000,
+	2850000,
+	3000000,
+	1850000,
+	2600000,
+	2700000,
+	3300000,
+};
+
+static struct regulator_ops stw481x_vmmc_ops = {
+	.list_voltage = regulator_list_voltage_table,
+	.enable      = regulator_enable_regmap,
+	.disable     = regulator_disable_regmap,
+	.is_enabled  = regulator_is_enabled_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+static struct regulator_desc vmmc_regulator = {
+	.name = "VMMC",
+	.id   = 0,
+	.ops  = &stw481x_vmmc_ops,
+	.type = REGULATOR_VOLTAGE,
+	.owner = THIS_MODULE,
+	.n_voltages = ARRAY_SIZE(stw481x_vmmc_voltages),
+	.volt_table = stw481x_vmmc_voltages,
+	.enable_time = 200, /* FIXME: look this up */
+	.enable_reg = STW_CONF1,
+	.enable_mask = STW_CONF1_PDN_VMMC,
+	.vsel_reg = STW_CONF1,
+	.vsel_mask = STW_CONF1_VMMC_MASK,
+};
+
+static int stw481x_vmmc_regulator_probe(struct platform_device *pdev)
+{
+	struct stw481x *stw481x = dev_get_platdata(&pdev->dev);
+	struct regulator_config config = { };
+	int ret;
+
+	/* First disable the external VMMC if it's active */
+	ret = regmap_update_bits(stw481x->map, STW_CONF2,
+				 STW_CONF2_VMMC_EXT, 0);
+	if (ret) {
+		dev_err(&pdev->dev, "could not disable external VMMC\n");
+		return ret;
+	}
+
+	/* Register VMMC regulator */
+	config.dev = &pdev->dev;
+	config.driver_data = stw481x;
+	config.regmap = stw481x->map;
+	config.of_node = pdev->dev.of_node;
+	config.init_data = of_get_regulator_init_data(&pdev->dev,
+						      pdev->dev.of_node);
+
+	stw481x->vmmc_regulator = regulator_register(&vmmc_regulator, &config);
+	if (IS_ERR(stw481x->vmmc_regulator)) {
+		dev_err(&pdev->dev,
+			"error initializing STw481x VMMC regulator\n");
+		return PTR_ERR(stw481x->vmmc_regulator);
+	}
+
+	dev_info(&pdev->dev, "initialized STw481x VMMC regulator\n");
+	return 0;
+}
+
+static int stw481x_vmmc_regulator_remove(struct platform_device *pdev)
+{
+	struct stw481x *stw481x = dev_get_platdata(&pdev->dev);
+
+	regulator_unregister(stw481x->vmmc_regulator);
+	return 0;
+}
+
+static const struct of_device_id stw481x_vmmc_match[] = {
+	{ .compatible = "st,stw481x-vmmc", },
+	{},
+};
+
+static struct platform_driver stw481x_vmmc_regulator_driver = {
+	.driver = {
+		.name  = "stw481x-vmmc-regulator",
+		.owner = THIS_MODULE,
+		.of_match_table = stw481x_vmmc_match,
+	},
+	.probe = stw481x_vmmc_regulator_probe,
+	.remove = stw481x_vmmc_regulator_remove,
+};
+
+module_platform_driver(stw481x_vmmc_regulator_driver);
diff --git a/drivers/regulator/ti-abb-regulator.c b/drivers/regulator/ti-abb-regulator.c
index 20c271d..b187b6b 100644
--- a/drivers/regulator/ti-abb-regulator.c
+++ b/drivers/regulator/ti-abb-regulator.c
@@ -615,7 +615,7 @@
 					pname, *volt_table, vset_mask);
 			continue;
 		}
-		info->vset = efuse_val & vset_mask >> __ffs(vset_mask);
+		info->vset = (efuse_val & vset_mask) >> __ffs(vset_mask);
 		dev_dbg(dev, "[%d]v=%d vset=%x\n", i, *volt_table, info->vset);
 check_abb:
 		switch (info->opp_sel) {
@@ -708,39 +708,31 @@
 	match = of_match_device(ti_abb_of_match, dev);
 	if (!match) {
 		/* We do not expect this to happen */
-		ret = -ENODEV;
 		dev_err(dev, "%s: Unable to match device\n", __func__);
-		goto err;
+		return -ENODEV;
 	}
 	if (!match->data) {
-		ret = -EINVAL;
 		dev_err(dev, "%s: Bad data in match\n", __func__);
-		goto err;
+		return -EINVAL;
 	}
 
 	abb = devm_kzalloc(dev, sizeof(struct ti_abb), GFP_KERNEL);
-	if (!abb) {
-		dev_err(dev, "%s: Unable to allocate ABB struct\n", __func__);
-		ret = -ENOMEM;
-		goto err;
-	}
+	if (!abb)
+		return -ENOMEM;
 	abb->regs = match->data;
 
 	/* Map ABB resources */
 	pname = "base-address";
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
 	abb->base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(abb->base)) {
-		ret = PTR_ERR(abb->base);
-		goto err;
-	}
+	if (IS_ERR(abb->base))
+		return PTR_ERR(abb->base);
 
 	pname = "int-address";
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
 	if (!res) {
 		dev_err(dev, "Missing '%s' IO resource\n", pname);
-		ret = -ENODEV;
-		goto err;
+		return -ENODEV;
 	}
 	/*
 	 * We may have shared interrupt register offsets which are
@@ -750,8 +742,7 @@
 					     resource_size(res));
 	if (!abb->int_base) {
 		dev_err(dev, "Unable to map '%s'\n", pname);
-		ret = -ENOMEM;
-		goto err;
+		return -ENOMEM;
 	}
 
 	/* Map Optional resources */
@@ -771,17 +762,19 @@
 					       resource_size(res));
 	if (!abb->efuse_base) {
 		dev_err(dev, "Unable to map '%s'\n", pname);
-		ret = -ENOMEM;
-		goto err;
+		return -ENOMEM;
 	}
 
 	pname = "ldo-address";
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
-	abb->ldo_base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(abb->ldo_base)) {
-		ret = PTR_ERR(abb->ldo_base);
-		goto err;
+	if (!res) {
+		dev_dbg(dev, "Missing '%s' IO resource\n", pname);
+		ret = -ENODEV;
+		goto skip_opt;
 	}
+	abb->ldo_base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(abb->ldo_base))
+		return PTR_ERR(abb->ldo_base);
 
 	/* IF ldo_base is set, the following are mandatory */
 	pname = "ti,ldovbb-override-mask";
@@ -790,12 +783,11 @@
 				 &abb->ldovbb_override_mask);
 	if (ret) {
 		dev_err(dev, "Missing '%s' (%d)\n", pname, ret);
-		goto err;
+		return ret;
 	}
 	if (!abb->ldovbb_override_mask) {
 		dev_err(dev, "Invalid property:'%s' set as 0!\n", pname);
-		ret = -EINVAL;
-		goto err;
+		return -EINVAL;
 	}
 
 	pname = "ti,ldovbb-vset-mask";
@@ -804,12 +796,11 @@
 				 &abb->ldovbb_vset_mask);
 	if (ret) {
 		dev_err(dev, "Missing '%s' (%d)\n", pname, ret);
-		goto err;
+		return ret;
 	}
 	if (!abb->ldovbb_vset_mask) {
 		dev_err(dev, "Invalid property:'%s' set as 0!\n", pname);
-		ret = -EINVAL;
-		goto err;
+		return -EINVAL;
 	}
 
 skip_opt:
@@ -819,31 +810,29 @@
 				 &abb->txdone_mask);
 	if (ret) {
 		dev_err(dev, "Missing '%s' (%d)\n", pname, ret);
-		goto err;
+		return ret;
 	}
 	if (!abb->txdone_mask) {
 		dev_err(dev, "Invalid property:'%s' set as 0!\n", pname);
-		ret = -EINVAL;
-		goto err;
+		return -EINVAL;
 	}
 
 	initdata = of_get_regulator_init_data(dev, pdev->dev.of_node);
 	if (!initdata) {
-		ret = -ENOMEM;
 		dev_err(dev, "%s: Unable to alloc regulator init data\n",
 			__func__);
-		goto err;
+		return -ENOMEM;
 	}
 
 	/* init ABB opp_sel table */
 	ret = ti_abb_init_table(dev, abb, initdata);
 	if (ret)
-		goto err;
+		return ret;
 
 	/* init ABB timing */
 	ret = ti_abb_init_timings(dev, abb);
 	if (ret)
-		goto err;
+		return ret;
 
 	desc = &abb->rdesc;
 	desc->name = dev_name(dev);
@@ -861,12 +850,12 @@
 	config.driver_data = abb;
 	config.of_node = pdev->dev.of_node;
 
-	rdev = regulator_register(desc, &config);
+	rdev = devm_regulator_register(dev, desc, &config);
 	if (IS_ERR(rdev)) {
 		ret = PTR_ERR(rdev);
 		dev_err(dev, "%s: failed to register regulator(%d)\n",
 			__func__, ret);
-		goto err;
+		return ret;
 	}
 	platform_set_drvdata(pdev, rdev);
 
@@ -874,31 +863,12 @@
 	ti_abb_rmw(abb->regs->sr2_en_mask, 1, abb->regs->setup_reg, abb->base);
 
 	return 0;
-
-err:
-	dev_err(dev, "%s: Failed to initialize(%d)\n", __func__, ret);
-	return ret;
-}
-
-/**
- * ti_abb_remove() - cleanups
- * @pdev: ABB platform device
- *
- * Return: 0
- */
-static int ti_abb_remove(struct platform_device *pdev)
-{
-	struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
-	regulator_unregister(rdev);
-	return 0;
 }
 
 MODULE_ALIAS("platform:ti_abb");
 
 static struct platform_driver ti_abb_driver = {
 	.probe = ti_abb_probe,
-	.remove = ti_abb_remove,
 	.driver = {
 		   .name = "ti_abb",
 		   .owner = THIS_MODULE,
diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c
index 9392a7c..b0a3f09 100644
--- a/drivers/regulator/tps51632-regulator.c
+++ b/drivers/regulator/tps51632-regulator.c
@@ -343,7 +343,7 @@
 	config.regmap = tps->regmap;
 	config.of_node = client->dev.of_node;
 
-	rdev = regulator_register(&tps->desc, &config);
+	rdev = devm_regulator_register(&client->dev, &tps->desc, &config);
 	if (IS_ERR(rdev)) {
 		dev_err(tps->dev, "regulator register failed\n");
 		return PTR_ERR(rdev);
@@ -353,14 +353,6 @@
 	return 0;
 }
 
-static int tps51632_remove(struct i2c_client *client)
-{
-	struct tps51632_chip *tps = i2c_get_clientdata(client);
-
-	regulator_unregister(tps->rdev);
-	return 0;
-}
-
 static const struct i2c_device_id tps51632_id[] = {
 	{.name = "tps51632",},
 	{},
@@ -375,7 +367,6 @@
 		.of_match_table = of_match_ptr(tps51632_of_match),
 	},
 	.probe = tps51632_probe,
-	.remove = tps51632_remove,
 	.id_table = tps51632_id,
 };
 
diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c
index ec9453f..c1e33a3 100644
--- a/drivers/regulator/tps6105x-regulator.c
+++ b/drivers/regulator/tps6105x-regulator.c
@@ -137,7 +137,7 @@
 	/* This instance is not set for regulator mode so bail out */
 	if (pdata->mode != TPS6105X_MODE_VOLTAGE) {
 		dev_info(&pdev->dev,
-			 "chip not in voltage mode mode, exit probe \n");
+			"chip not in voltage mode mode, exit probe\n");
 		return 0;
 	}
 
@@ -146,8 +146,9 @@
 	config.driver_data = tps6105x;
 
 	/* Register regulator with framework */
-	tps6105x->regulator = regulator_register(&tps6105x_regulator_desc,
-						 &config);
+	tps6105x->regulator = devm_regulator_register(&pdev->dev,
+						      &tps6105x_regulator_desc,
+						      &config);
 	if (IS_ERR(tps6105x->regulator)) {
 		ret = PTR_ERR(tps6105x->regulator);
 		dev_err(&tps6105x->client->dev,
@@ -159,20 +160,12 @@
 	return 0;
 }
 
-static int tps6105x_regulator_remove(struct platform_device *pdev)
-{
-	struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
-	regulator_unregister(tps6105x->regulator);
-	return 0;
-}
-
 static struct platform_driver tps6105x_regulator_driver = {
 	.driver = {
 		.name  = "tps6105x-regulator",
 		.owner = THIS_MODULE,
 	},
 	.probe = tps6105x_regulator_probe,
-	.remove = tps6105x_regulator_remove,
 };
 
 static __init int tps6105x_regulator_init(void)
diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c
index 0b7ebb1..c2c0185 100644
--- a/drivers/regulator/tps62360-regulator.c
+++ b/drivers/regulator/tps62360-regulator.c
@@ -476,7 +476,7 @@
 	config.of_node = client->dev.of_node;
 
 	/* Register the regulators */
-	rdev = regulator_register(&tps->desc, &config);
+	rdev = devm_regulator_register(&client->dev, &tps->desc, &config);
 	if (IS_ERR(rdev)) {
 		dev_err(tps->dev,
 			"%s(): regulator register failed with err %s\n",
@@ -488,20 +488,6 @@
 	return 0;
 }
 
-/**
- * tps62360_remove - tps62360 driver i2c remove handler
- * @client: i2c driver client device structure
- *
- * Unregister TPS driver as an i2c client device driver
- */
-static int tps62360_remove(struct i2c_client *client)
-{
-	struct tps62360_chip *tps = i2c_get_clientdata(client);
-
-	regulator_unregister(tps->rdev);
-	return 0;
-}
-
 static void tps62360_shutdown(struct i2c_client *client)
 {
 	struct tps62360_chip *tps = i2c_get_clientdata(client);
@@ -535,7 +521,6 @@
 		.of_match_table = of_match_ptr(tps62360_of_match),
 	},
 	.probe = tps62360_probe,
-	.remove = tps62360_remove,
 	.shutdown = tps62360_shutdown,
 	.id_table = tps62360_id,
 };
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
index a15263d..3ef67a8 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -277,12 +277,12 @@
 		config.regmap = tps->regmap;
 
 		/* Register the regulators */
-		rdev = regulator_register(&tps->desc[i], &config);
+		rdev = devm_regulator_register(&client->dev, &tps->desc[i],
+					       &config);
 		if (IS_ERR(rdev)) {
 			dev_err(&client->dev, "failed to register %s\n",
 				id->name);
-			error = PTR_ERR(rdev);
-			goto fail;
+			return PTR_ERR(rdev);
 		}
 
 		/* Save regulator for cleanup */
@@ -293,24 +293,10 @@
 
 	/* Enable setting output voltage by I2C */
 	regmap_update_bits(tps->regmap, TPS65023_REG_CON_CTRL2,
-			TPS65023_REG_CTRL2_CORE_ADJ, TPS65023_REG_CTRL2_CORE_ADJ);
+					TPS65023_REG_CTRL2_CORE_ADJ,
+					TPS65023_REG_CTRL2_CORE_ADJ);
 
 	return 0;
-
- fail:
-	while (--i >= 0)
-		regulator_unregister(tps->rdev[i]);
-	return error;
-}
-
-static int tps_65023_remove(struct i2c_client *client)
-{
-	struct tps_pmic *tps = i2c_get_clientdata(client);
-	int i;
-
-	for (i = 0; i < TPS65023_NUM_REGULATOR; i++)
-		regulator_unregister(tps->rdev[i]);
-	return 0;
 }
 
 static const struct tps_info tps65020_regs[] = {
@@ -430,7 +416,6 @@
 		.owner = THIS_MODULE,
 	},
 	.probe = tps_65023_probe,
-	.remove = tps_65023_remove,
 	.id_table = tps_65023_id,
 };
 
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c
index 4117ff5..162a0fa 100644
--- a/drivers/regulator/tps6507x-regulator.c
+++ b/drivers/regulator/tps6507x-regulator.c
@@ -508,13 +508,13 @@
 			config.of_node = tps6507x_reg_matches[i].of_node;
 		}
 
-		rdev = regulator_register(&tps->desc[i], &config);
+		rdev = devm_regulator_register(&pdev->dev, &tps->desc[i],
+					       &config);
 		if (IS_ERR(rdev)) {
 			dev_err(tps6507x_dev->dev,
 				"failed to register %s regulator\n",
 				pdev->name);
-			error = PTR_ERR(rdev);
-			goto fail;
+			return PTR_ERR(rdev);
 		}
 
 		/* Save regulator for cleanup */
@@ -525,22 +525,6 @@
 	platform_set_drvdata(pdev, tps6507x_dev);
 
 	return 0;
-
-fail:
-	while (--i >= 0)
-		regulator_unregister(tps->rdev[i]);
-	return error;
-}
-
-static int tps6507x_pmic_remove(struct platform_device *pdev)
-{
-	struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev);
-	struct tps6507x_pmic *tps = tps6507x_dev->pmic;
-	int i;
-
-	for (i = 0; i < TPS6507X_NUM_REGULATOR; i++)
-		regulator_unregister(tps->rdev[i]);
-	return 0;
 }
 
 static struct platform_driver tps6507x_pmic_driver = {
@@ -549,7 +533,6 @@
 		.owner = THIS_MODULE,
 	},
 	.probe = tps6507x_pmic_probe,
-	.remove = tps6507x_pmic_remove,
 };
 
 static int __init tps6507x_pmic_init(void)
diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c
index c8e7045..676f755 100644
--- a/drivers/regulator/tps65090-regulator.c
+++ b/drivers/regulator/tps65090-regulator.c
@@ -180,7 +180,7 @@
 		return ERR_PTR(-ENOMEM);
 	}
 
-	regulators = of_find_node_by_name(np, "regulators");
+	regulators = of_get_child_by_name(np, "regulators");
 	if (!regulators) {
 		dev_err(&pdev->dev, "regulator node not found\n");
 		return ERR_PTR(-ENODEV);
@@ -279,7 +279,7 @@
 				if (ret < 0) {
 					dev_err(&pdev->dev,
 						"failed disable ext control\n");
-					goto scrub;
+					return ret;
 				}
 			}
 		}
@@ -296,12 +296,11 @@
 		else
 			config.of_node = NULL;
 
-		rdev = regulator_register(ri->desc, &config);
+		rdev = devm_regulator_register(&pdev->dev, ri->desc, &config);
 		if (IS_ERR(rdev)) {
 			dev_err(&pdev->dev, "failed to register regulator %s\n",
 				ri->desc->name);
-			ret = PTR_ERR(rdev);
-			goto scrub;
+			return PTR_ERR(rdev);
 		}
 		ri->rdev = rdev;
 
@@ -309,36 +308,13 @@
 		if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data &&
 				tps_pdata->enable_ext_control) {
 			ret = tps65090_config_ext_control(ri, true);
-			if (ret < 0) {
-				/* Increment num to get unregister rdev */
-				num++;
-				goto scrub;
-			}
+			if (ret < 0)
+				return ret;
 		}
 	}
 
 	platform_set_drvdata(pdev, pmic);
 	return 0;
-
-scrub:
-	while (--num >= 0) {
-		ri = &pmic[num];
-		regulator_unregister(ri->rdev);
-	}
-	return ret;
-}
-
-static int tps65090_regulator_remove(struct platform_device *pdev)
-{
-	struct tps65090_regulator *pmic = platform_get_drvdata(pdev);
-	struct tps65090_regulator *ri;
-	int num;
-
-	for (num = 0; num < TPS65090_REGULATOR_MAX; ++num) {
-		ri = &pmic[num];
-		regulator_unregister(ri->rdev);
-	}
-	return 0;
 }
 
 static struct platform_driver tps65090_regulator_driver = {
@@ -347,7 +323,6 @@
 		.owner	= THIS_MODULE,
 	},
 	.probe		= tps65090_regulator_probe,
-	.remove		= tps65090_regulator_remove,
 };
 
 static int __init tps65090_regulator_init(void)
diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c
index 90861d6..9ea1bf2 100644
--- a/drivers/regulator/tps65217-regulator.c
+++ b/drivers/regulator/tps65217-regulator.c
@@ -52,25 +52,17 @@
 };
 
 static const struct regulator_linear_range tps65217_uv1_ranges[] = {
-	{ .min_uV = 900000, .max_uV = 1500000, .min_sel =  0, .max_sel = 24,
-	  .uV_step = 25000 },
-	{ .min_uV = 1550000, .max_uV = 1800000, .min_sel = 25, .max_sel = 30,
-	  .uV_step = 50000 },
-	{ .min_uV = 1850000, .max_uV = 2900000, .min_sel = 31, .max_sel = 52,
-	  .uV_step = 50000 },
-	{ .min_uV = 3000000, .max_uV = 3200000, .min_sel = 53, .max_sel = 55,
-	  .uV_step = 100000 },
-	{ .min_uV = 3300000, .max_uV = 3300000, .min_sel = 56, .max_sel = 62,
-	  .uV_step = 0 },
+	REGULATOR_LINEAR_RANGE(900000, 0, 24, 25000),
+	REGULATOR_LINEAR_RANGE(1550000, 25, 30, 50000),
+	REGULATOR_LINEAR_RANGE(1850000, 31, 52, 50000),
+	REGULATOR_LINEAR_RANGE(3000000, 53, 55, 100000),
+	REGULATOR_LINEAR_RANGE(3300000, 56, 62, 0),
 };
 
 static const struct regulator_linear_range tps65217_uv2_ranges[] = {
-	{ .min_uV = 1500000, .max_uV = 1900000, .min_sel =  0, .max_sel = 8,
-	  .uV_step = 50000 },
-	{ .min_uV = 2000000, .max_uV = 2400000, .min_sel = 9, .max_sel = 13,
-	  .uV_step = 100000 },
-	{ .min_uV = 2450000, .max_uV = 3300000, .min_sel = 14, .max_sel = 31,
-	  .uV_step = 50000 },
+	REGULATOR_LINEAR_RANGE(1500000, 0, 8, 50000),
+	REGULATOR_LINEAR_RANGE(2000000, 9, 13, 100000),
+	REGULATOR_LINEAR_RANGE(2450000, 14, 31, 50000),
 };
 
 static int tps65217_pmic_enable(struct regulator_dev *dev)
@@ -233,7 +225,7 @@
 	struct regulator_init_data *reg_data;
 	struct regulator_dev *rdev;
 	struct regulator_config config = { };
-	int i, ret;
+	int i;
 
 	if (tps->dev->of_node)
 		pdata = tps65217_parse_dt(pdev);
@@ -269,35 +261,18 @@
 		if (tps->dev->of_node)
 			config.of_node = pdata->of_node[i];
 
-		rdev = regulator_register(&regulators[i], &config);
+		rdev = devm_regulator_register(&pdev->dev, &regulators[i],
+					       &config);
 		if (IS_ERR(rdev)) {
 			dev_err(tps->dev, "failed to register %s regulator\n",
 				pdev->name);
-			ret = PTR_ERR(rdev);
-			goto err_unregister_regulator;
+			return PTR_ERR(rdev);
 		}
 
 		/* Save regulator for cleanup */
 		tps->rdev[i] = rdev;
 	}
 	return 0;
-
-err_unregister_regulator:
-	while (--i >= 0)
-		regulator_unregister(tps->rdev[i]);
-
-	return ret;
-}
-
-static int tps65217_regulator_remove(struct platform_device *pdev)
-{
-	struct tps65217 *tps = platform_get_drvdata(pdev);
-	unsigned int i;
-
-	for (i = 0; i < TPS65217_NUM_REGULATOR; i++)
-		regulator_unregister(tps->rdev[i]);
-
-	return 0;
 }
 
 static struct platform_driver tps65217_regulator_driver = {
@@ -305,7 +280,6 @@
 		.name = "tps65217-pmic",
 	},
 	.probe = tps65217_regulator_probe,
-	.remove = tps65217_regulator_remove,
 };
 
 static int __init tps65217_regulator_init(void)
diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c
index 62e8d28..9f6bfda 100644
--- a/drivers/regulator/tps6524x-regulator.c
+++ b/drivers/regulator/tps6524x-regulator.c
@@ -577,21 +577,6 @@
 	.get_current_limit	= get_current_limit,
 };
 
-static int pmic_remove(struct spi_device *spi)
-{
-	struct tps6524x *hw = spi_get_drvdata(spi);
-	int i;
-
-	if (!hw)
-		return 0;
-	for (i = 0; i < N_REGULATORS; i++) {
-		regulator_unregister(hw->rdev[i]);
-		hw->rdev[i] = NULL;
-	}
-	spi_set_drvdata(spi, NULL);
-	return 0;
-}
-
 static int pmic_probe(struct spi_device *spi)
 {
 	struct tps6524x *hw;
@@ -599,7 +584,7 @@
 	const struct supply_info *info = supply_info;
 	struct regulator_init_data *init_data;
 	struct regulator_config config = { };
-	int ret = 0, i;
+	int i;
 
 	init_data = dev_get_platdata(dev);
 	if (!init_data) {
@@ -632,24 +617,17 @@
 		config.init_data = init_data;
 		config.driver_data = hw;
 
-		hw->rdev[i] = regulator_register(&hw->desc[i], &config);
-		if (IS_ERR(hw->rdev[i])) {
-			ret = PTR_ERR(hw->rdev[i]);
-			hw->rdev[i] = NULL;
-			goto fail;
-		}
+		hw->rdev[i] = devm_regulator_register(dev, &hw->desc[i],
+						      &config);
+		if (IS_ERR(hw->rdev[i]))
+			return PTR_ERR(hw->rdev[i]);
 	}
 
 	return 0;
-
-fail:
-	pmic_remove(spi);
-	return ret;
 }
 
 static struct spi_driver pmic_driver = {
 	.probe		= pmic_probe,
-	.remove		= pmic_remove,
 	.driver		= {
 		.name	= "tps6524x",
 		.owner	= THIS_MODULE,
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
index 2c9155b..e8e3a8a 100644
--- a/drivers/regulator/tps6586x-regulator.c
+++ b/drivers/regulator/tps6586x-regulator.c
@@ -298,7 +298,7 @@
 	struct tps6586x_platform_data *pdata;
 	int err;
 
-	regs = of_find_node_by_name(np, "regulators");
+	regs = of_get_child_by_name(np, "regulators");
 	if (!regs) {
 		dev_err(&pdev->dev, "regulator node not found\n");
 		return NULL;
@@ -379,15 +379,14 @@
 		ri = find_regulator_info(id);
 		if (!ri) {
 			dev_err(&pdev->dev, "invalid regulator ID specified\n");
-			err = -EINVAL;
-			goto fail;
+			return -EINVAL;
 		}
 
 		err = tps6586x_regulator_preinit(pdev->dev.parent, ri);
 		if (err) {
 			dev_err(&pdev->dev,
 				"regulator %d preinit failed, e %d\n", id, err);
-			goto fail;
+			return err;
 		}
 
 		config.dev = pdev->dev.parent;
@@ -397,12 +396,12 @@
 		if (tps6586x_reg_matches)
 			config.of_node = tps6586x_reg_matches[id].of_node;
 
-		rdev[id] = regulator_register(&ri->desc, &config);
+		rdev[id] = devm_regulator_register(&pdev->dev, &ri->desc,
+						   &config);
 		if (IS_ERR(rdev[id])) {
 			dev_err(&pdev->dev, "failed to register regulator %s\n",
 					ri->desc.name);
-			err = PTR_ERR(rdev[id]);
-			goto fail;
+			return PTR_ERR(rdev[id]);
 		}
 
 		if (reg_data) {
@@ -411,30 +410,13 @@
 			if (err < 0) {
 				dev_err(&pdev->dev,
 					"Slew rate config failed, e %d\n", err);
-				regulator_unregister(rdev[id]);
-				goto fail;
+				return err;
 			}
 		}
 	}
 
 	platform_set_drvdata(pdev, rdev);
 	return 0;
-
-fail:
-	while (--id >= 0)
-		regulator_unregister(rdev[id]);
-	return err;
-}
-
-static int tps6586x_regulator_remove(struct platform_device *pdev)
-{
-	struct regulator_dev **rdev = platform_get_drvdata(pdev);
-	int id = TPS6586X_ID_MAX_REGULATOR;
-
-	while (--id >= 0)
-		regulator_unregister(rdev[id]);
-
-	return 0;
 }
 
 static struct platform_driver tps6586x_regulator_driver = {
@@ -443,7 +425,6 @@
 		.owner	= THIS_MODULE,
 	},
 	.probe		= tps6586x_regulator_probe,
-	.remove		= tps6586x_regulator_remove,
 };
 
 static int __init tps6586x_regulator_init(void)
diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c
index 45c1644..23f8d1c 100644
--- a/drivers/regulator/tps65910-regulator.c
+++ b/drivers/regulator/tps65910-regulator.c
@@ -481,7 +481,7 @@
 
 	/* multiplier 0 == 1 but 2,3 normal */
 	if (!mult)
-		mult=1;
+		mult = 1;
 
 	if (sr) {
 		/* normalise to valid range */
@@ -685,7 +685,7 @@
 	case TPS65910_REG_VDD2:
 		mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;
 		volt = VDD1_2_MIN_VOLT +
-				(selector % VDD1_2_NUM_VOLT_FINE) * VDD1_2_OFFSET;
+			(selector % VDD1_2_NUM_VOLT_FINE) * VDD1_2_OFFSET;
 		break;
 	case TPS65911_REG_VDDCTRL:
 		volt = VDDCTRL_MIN_VOLT + (selector * VDDCTRL_OFFSET);
@@ -703,7 +703,7 @@
 	struct tps65910_reg *pmic = rdev_get_drvdata(dev);
 	int step_mv = 0, id = rdev_get_id(dev);
 
-	switch(id) {
+	switch (id) {
 	case TPS65911_REG_LDO1:
 	case TPS65911_REG_LDO2:
 	case TPS65911_REG_LDO4:
@@ -982,7 +982,7 @@
 	}
 
 	np = of_node_get(pdev->dev.parent->of_node);
-	regulators = of_find_node_by_name(np, "regulators");
+	regulators = of_get_child_by_name(np, "regulators");
 	if (!regulators) {
 		dev_err(&pdev->dev, "regulator node not found\n");
 		return NULL;
@@ -1074,7 +1074,7 @@
 	tps65910_reg_set_bits(pmic->mfd, TPS65910_DEVCTRL,
 				DEVCTRL_SR_CTL_I2C_SEL_MASK);
 
-	switch(tps65910_chip_id(tps65910)) {
+	switch (tps65910_chip_id(tps65910)) {
 	case TPS65910:
 		pmic->get_ctrl_reg = &tps65910_get_ctrl_register;
 		pmic->num_regulators = ARRAY_SIZE(tps65910_regs);
@@ -1177,35 +1177,19 @@
 		if (tps65910_reg_matches)
 			config.of_node = tps65910_reg_matches[i].of_node;
 
-		rdev = regulator_register(&pmic->desc[i], &config);
+		rdev = devm_regulator_register(&pdev->dev, &pmic->desc[i],
+					       &config);
 		if (IS_ERR(rdev)) {
 			dev_err(tps65910->dev,
 				"failed to register %s regulator\n",
 				pdev->name);
-			err = PTR_ERR(rdev);
-			goto err_unregister_regulator;
+			return PTR_ERR(rdev);
 		}
 
 		/* Save regulator for cleanup */
 		pmic->rdev[i] = rdev;
 	}
 	return 0;
-
-err_unregister_regulator:
-	while (--i >= 0)
-		regulator_unregister(pmic->rdev[i]);
-	return err;
-}
-
-static int tps65910_remove(struct platform_device *pdev)
-{
-	struct tps65910_reg *pmic = platform_get_drvdata(pdev);
-	int i;
-
-	for (i = 0; i < pmic->num_regulators; i++)
-		regulator_unregister(pmic->rdev[i]);
-
-	return 0;
 }
 
 static void tps65910_shutdown(struct platform_device *pdev)
@@ -1244,7 +1228,6 @@
 		.owner = THIS_MODULE,
 	},
 	.probe = tps65910_probe,
-	.remove = tps65910_remove,
 	.shutdown = tps65910_shutdown,
 };
 
diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c
index 281e52a..9cafaa0 100644
--- a/drivers/regulator/tps65912-regulator.c
+++ b/drivers/regulator/tps65912-regulator.c
@@ -119,12 +119,9 @@
 };
 
 static const struct regulator_linear_range tps65912_ldo_ranges[] = {
-	{ .min_uV = 800000, .max_uV = 1600000, .min_sel =  0, .max_sel = 32,
-	  .uV_step = 25000 },
-	{ .min_uV = 1650000, .max_uV = 3000000, .min_sel = 33, .max_sel = 60,
-	  .uV_step = 50000 },
-	{ .min_uV = 3100000, .max_uV = 3300000, .min_sel = 61, .max_sel = 63,
-	  .uV_step = 100000 },
+	REGULATOR_LINEAR_RANGE(800000, 0, 32, 25000),
+	REGULATOR_LINEAR_RANGE(1650000, 33, 60, 50000),
+	REGULATOR_LINEAR_RANGE(3100000, 61, 63, 100000),
 };
 
 static int tps65912_get_range(struct tps65912_reg *pmic, int id)
@@ -461,7 +458,7 @@
 	struct regulator_dev *rdev;
 	struct tps65912_reg *pmic;
 	struct tps65912_board *pmic_plat_data;
-	int i, err;
+	int i;
 
 	pmic_plat_data = dev_get_platdata(tps65912->dev);
 	if (!pmic_plat_data)
@@ -504,34 +501,19 @@
 		config.init_data = reg_data;
 		config.driver_data = pmic;
 
-		rdev = regulator_register(&pmic->desc[i], &config);
+		rdev = devm_regulator_register(&pdev->dev, &pmic->desc[i],
+					       &config);
 		if (IS_ERR(rdev)) {
 			dev_err(tps65912->dev,
 				"failed to register %s regulator\n",
 				pdev->name);
-			err = PTR_ERR(rdev);
-			goto err;
+			return PTR_ERR(rdev);
 		}
 
 		/* Save regulator for cleanup */
 		pmic->rdev[i] = rdev;
 	}
 	return 0;
-
-err:
-	while (--i >= 0)
-		regulator_unregister(pmic->rdev[i]);
-	return err;
-}
-
-static int tps65912_remove(struct platform_device *pdev)
-{
-	struct tps65912_reg *tps65912_reg = platform_get_drvdata(pdev);
-	int i;
-
-	for (i = 0; i < TPS65912_NUM_REGULATOR; i++)
-		regulator_unregister(tps65912_reg->rdev[i]);
-	return 0;
 }
 
 static struct platform_driver tps65912_driver = {
@@ -540,7 +522,6 @@
 		.owner = THIS_MODULE,
 	},
 	.probe = tps65912_probe,
-	.remove = tps65912_remove,
 };
 
 static int __init tps65912_init(void)
diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c
index 6511d0b..71f457a 100644
--- a/drivers/regulator/tps80031-regulator.c
+++ b/drivers/regulator/tps80031-regulator.c
@@ -719,7 +719,7 @@
 			if (ret < 0) {
 				dev_err(&pdev->dev,
 					"regulator config failed, e %d\n", ret);
-				goto fail;
+				return ret;
 			}
 
 			ret = tps80031_power_req_config(pdev->dev.parent,
@@ -727,41 +727,22 @@
 			if (ret < 0) {
 				dev_err(&pdev->dev,
 					"pwr_req config failed, err %d\n", ret);
-				goto fail;
+				return ret;
 			}
 		}
-		rdev = regulator_register(&ri->rinfo->desc, &config);
+		rdev = devm_regulator_register(&pdev->dev, &ri->rinfo->desc,
+					       &config);
 		if (IS_ERR(rdev)) {
 			dev_err(&pdev->dev,
 				"register regulator failed %s\n",
 					ri->rinfo->desc.name);
-			ret = PTR_ERR(rdev);
-			goto fail;
+			return PTR_ERR(rdev);
 		}
 		ri->rdev = rdev;
 	}
 
 	platform_set_drvdata(pdev, pmic);
 	return 0;
-fail:
-	while (--num >= 0) {
-		ri = &pmic[num];
-		regulator_unregister(ri->rdev);
-	}
-	return ret;
-}
-
-static int tps80031_regulator_remove(struct platform_device *pdev)
-{
-	struct tps80031_regulator *pmic = platform_get_drvdata(pdev);
-	struct tps80031_regulator *ri = NULL;
-	int num;
-
-	for (num = 0; num < TPS80031_REGULATOR_MAX; ++num) {
-		ri = &pmic[num];
-		regulator_unregister(ri->rdev);
-	}
-	return 0;
 }
 
 static struct platform_driver tps80031_regulator_driver = {
@@ -770,7 +751,6 @@
 		.owner	= THIS_MODULE,
 	},
 	.probe		= tps80031_regulator_probe,
-	.remove		= tps80031_regulator_remove,
 };
 
 static int __init tps80031_regulator_init(void)
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 78aae4c..8ebd785 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -1188,7 +1188,7 @@
 	config.driver_data = info;
 	config.of_node = pdev->dev.of_node;
 
-	rdev = regulator_register(&info->desc, &config);
+	rdev = devm_regulator_register(&pdev->dev, &info->desc, &config);
 	if (IS_ERR(rdev)) {
 		dev_err(&pdev->dev, "can't register %s, %ld\n",
 				info->desc.name, PTR_ERR(rdev));
@@ -1217,7 +1217,6 @@
 	struct regulator_dev *rdev = platform_get_drvdata(pdev);
 	struct twlreg_info *info = rdev->reg_data;
 
-	regulator_unregister(rdev);
 	kfree(info);
 	return 0;
 }
diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress.c
index 4668c7f..f3ae28a 100644
--- a/drivers/regulator/vexpress.c
+++ b/drivers/regulator/vexpress.c
@@ -96,7 +96,7 @@
 	config.driver_data = reg;
 	config.of_node = pdev->dev.of_node;
 
-	reg->regdev = regulator_register(&reg->desc, &config);
+	reg->regdev = devm_regulator_register(&pdev->dev, &reg->desc, &config);
 	if (IS_ERR(reg->regdev)) {
 		err = PTR_ERR(reg->regdev);
 		goto error_regulator_register;
@@ -119,7 +119,6 @@
 	struct vexpress_regulator *reg = platform_get_drvdata(pdev);
 
 	vexpress_config_func_put(reg->func);
-	regulator_unregister(reg->regdev);
 
 	return 0;
 }
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
index 11861cb..6823e6f 100644
--- a/drivers/regulator/wm831x-dcdc.c
+++ b/drivers/regulator/wm831x-dcdc.c
@@ -387,8 +387,9 @@
  * Set up DVS control.  We just log errors since we can still run
  * (with reduced performance) if we fail.
  */
-static void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
-					    struct wm831x_buckv_pdata *pdata)
+static void wm831x_buckv_dvs_init(struct platform_device *pdev,
+				  struct wm831x_dcdc *dcdc,
+				  struct wm831x_buckv_pdata *pdata)
 {
 	struct wm831x *wm831x = dcdc->wm831x;
 	int ret;
@@ -402,9 +403,9 @@
 	 */
 	dcdc->dvs_gpio_state = pdata->dvs_init_state;
 
-	ret = gpio_request_one(pdata->dvs_gpio,
-			       dcdc->dvs_gpio_state ? GPIOF_INIT_HIGH : 0,
-			       "DCDC DVS");
+	ret = devm_gpio_request_one(&pdev->dev, pdata->dvs_gpio,
+				    dcdc->dvs_gpio_state ? GPIOF_INIT_HIGH : 0,
+				    "DCDC DVS");
 	if (ret < 0) {
 		dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n",
 			dcdc->name, ret);
@@ -513,7 +514,8 @@
 	dcdc->dvs_vsel = ret & WM831X_DC1_DVS_VSEL_MASK;
 
 	if (pdata && pdata->dcdc[id])
-		wm831x_buckv_dvs_init(dcdc, pdata->dcdc[id]->driver_data);
+		wm831x_buckv_dvs_init(pdev, dcdc,
+				      pdata->dcdc[id]->driver_data);
 
 	config.dev = pdev->dev.parent;
 	if (pdata)
@@ -521,7 +523,8 @@
 	config.driver_data = dcdc;
 	config.regmap = wm831x->regmap;
 
-	dcdc->regulator = regulator_register(&dcdc->desc, &config);
+	dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
+						  &config);
 	if (IS_ERR(dcdc->regulator)) {
 		ret = PTR_ERR(dcdc->regulator);
 		dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
@@ -530,57 +533,35 @@
 	}
 
 	irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
-	ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq,
-				   IRQF_TRIGGER_RISING, dcdc->name, dcdc);
+	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+					wm831x_dcdc_uv_irq,
+					IRQF_TRIGGER_RISING, dcdc->name, dcdc);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
 			irq, ret);
-		goto err_regulator;
+		goto err;
 	}
 
 	irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "HC"));
-	ret = request_threaded_irq(irq, NULL, wm831x_dcdc_oc_irq,
-				   IRQF_TRIGGER_RISING, dcdc->name, dcdc);
+	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+					wm831x_dcdc_oc_irq,
+					IRQF_TRIGGER_RISING, dcdc->name, dcdc);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "Failed to request HC IRQ %d: %d\n",
 			irq, ret);
-		goto err_uv;
+		goto err;
 	}
 
 	platform_set_drvdata(pdev, dcdc);
 
 	return 0;
 
-err_uv:
-	free_irq(wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")),
-		 dcdc);
-err_regulator:
-	regulator_unregister(dcdc->regulator);
 err:
-	if (dcdc->dvs_gpio)
-		gpio_free(dcdc->dvs_gpio);
 	return ret;
 }
 
-static int wm831x_buckv_remove(struct platform_device *pdev)
-{
-	struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
-	struct wm831x *wm831x = dcdc->wm831x;
-
-	free_irq(wm831x_irq(wm831x, platform_get_irq_byname(pdev, "HC")),
-			    dcdc);
-	free_irq(wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")),
-			    dcdc);
-	regulator_unregister(dcdc->regulator);
-	if (dcdc->dvs_gpio)
-		gpio_free(dcdc->dvs_gpio);
-
-	return 0;
-}
-
 static struct platform_driver wm831x_buckv_driver = {
 	.probe = wm831x_buckv_probe,
-	.remove = wm831x_buckv_remove,
 	.driver		= {
 		.name	= "wm831x-buckv",
 		.owner	= THIS_MODULE,
@@ -681,7 +662,8 @@
 	config.driver_data = dcdc;
 	config.regmap = wm831x->regmap;
 
-	dcdc->regulator = regulator_register(&dcdc->desc, &config);
+	dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
+						  &config);
 	if (IS_ERR(dcdc->regulator)) {
 		ret = PTR_ERR(dcdc->regulator);
 		dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
@@ -690,38 +672,25 @@
 	}
 
 	irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
-	ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq,
-				   IRQF_TRIGGER_RISING,	dcdc->name, dcdc);
+	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+					wm831x_dcdc_uv_irq,
+					IRQF_TRIGGER_RISING, dcdc->name, dcdc);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
 			irq, ret);
-		goto err_regulator;
+		goto err;
 	}
 
 	platform_set_drvdata(pdev, dcdc);
 
 	return 0;
 
-err_regulator:
-	regulator_unregister(dcdc->regulator);
 err:
 	return ret;
 }
 
-static int wm831x_buckp_remove(struct platform_device *pdev)
-{
-	struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
-
-	free_irq(wm831x_irq(dcdc->wm831x, platform_get_irq_byname(pdev, "UV")),
-			    dcdc);
-	regulator_unregister(dcdc->regulator);
-
-	return 0;
-}
-
 static struct platform_driver wm831x_buckp_driver = {
 	.probe = wm831x_buckp_probe,
-	.remove = wm831x_buckp_remove,
 	.driver		= {
 		.name	= "wm831x-buckp",
 		.owner	= THIS_MODULE,
@@ -813,7 +782,8 @@
 	config.driver_data = dcdc;
 	config.regmap = wm831x->regmap;
 
-	dcdc->regulator = regulator_register(&dcdc->desc, &config);
+	dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
+						  &config);
 	if (IS_ERR(dcdc->regulator)) {
 		ret = PTR_ERR(dcdc->regulator);
 		dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
@@ -822,39 +792,26 @@
 	}
 
 	irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
-	ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq,
-				   IRQF_TRIGGER_RISING, dcdc->name,
-				   dcdc);
+	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+					wm831x_dcdc_uv_irq,
+					IRQF_TRIGGER_RISING, dcdc->name,
+					dcdc);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
 			irq, ret);
-		goto err_regulator;
+		goto err;
 	}
 
 	platform_set_drvdata(pdev, dcdc);
 
 	return 0;
 
-err_regulator:
-	regulator_unregister(dcdc->regulator);
 err:
 	return ret;
 }
 
-static int wm831x_boostp_remove(struct platform_device *pdev)
-{
-	struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
-
-	free_irq(wm831x_irq(dcdc->wm831x, platform_get_irq_byname(pdev, "UV")),
-		 dcdc);
-	regulator_unregister(dcdc->regulator);
-
-	return 0;
-}
-
 static struct platform_driver wm831x_boostp_driver = {
 	.probe = wm831x_boostp_probe,
-	.remove = wm831x_boostp_remove,
 	.driver		= {
 		.name	= "wm831x-boostp",
 		.owner	= THIS_MODULE,
@@ -914,7 +871,8 @@
 	config.driver_data = dcdc;
 	config.regmap = wm831x->regmap;
 
-	dcdc->regulator = regulator_register(&dcdc->desc, &config);
+	dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
+						  &config);
 	if (IS_ERR(dcdc->regulator)) {
 		ret = PTR_ERR(dcdc->regulator);
 		dev_err(wm831x->dev, "Failed to register EPE%d: %d\n",
@@ -930,18 +888,8 @@
 	return ret;
 }
 
-static int wm831x_epe_remove(struct platform_device *pdev)
-{
-	struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
-
-	regulator_unregister(dcdc->regulator);
-
-	return 0;
-}
-
 static struct platform_driver wm831x_epe_driver = {
 	.probe = wm831x_epe_probe,
-	.remove = wm831x_epe_remove,
 	.driver		= {
 		.name	= "wm831x-epe",
 		.owner	= THIS_MODULE,
diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c
index 4eb373d..0339b88 100644
--- a/drivers/regulator/wm831x-isink.c
+++ b/drivers/regulator/wm831x-isink.c
@@ -194,7 +194,8 @@
 	config.init_data = pdata->isink[id];
 	config.driver_data = isink;
 
-	isink->regulator = regulator_register(&isink->desc, &config);
+	isink->regulator = devm_regulator_register(&pdev->dev, &isink->desc,
+						   &config);
 	if (IS_ERR(isink->regulator)) {
 		ret = PTR_ERR(isink->regulator);
 		dev_err(wm831x->dev, "Failed to register ISINK%d: %d\n",
@@ -203,38 +204,26 @@
 	}
 
 	irq = wm831x_irq(wm831x, platform_get_irq(pdev, 0));
-	ret = request_threaded_irq(irq, NULL, wm831x_isink_irq,
-				   IRQF_TRIGGER_RISING, isink->name, isink);
+	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+					wm831x_isink_irq,
+					IRQF_TRIGGER_RISING, isink->name,
+					isink);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "Failed to request ISINK IRQ %d: %d\n",
 			irq, ret);
-		goto err_regulator;
+		goto err;
 	}
 
 	platform_set_drvdata(pdev, isink);
 
 	return 0;
 
-err_regulator:
-	regulator_unregister(isink->regulator);
 err:
 	return ret;
 }
 
-static int wm831x_isink_remove(struct platform_device *pdev)
-{
-	struct wm831x_isink *isink = platform_get_drvdata(pdev);
-
-	free_irq(wm831x_irq(isink->wm831x, platform_get_irq(pdev, 0)), isink);
-
-	regulator_unregister(isink->regulator);
-
-	return 0;
-}
-
 static struct platform_driver wm831x_isink_driver = {
 	.probe = wm831x_isink_probe,
-	.remove = wm831x_isink_remove,
 	.driver		= {
 		.name	= "wm831x-isink",
 		.owner	= THIS_MODULE,
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c
index 2205fbc..46d6700 100644
--- a/drivers/regulator/wm831x-ldo.c
+++ b/drivers/regulator/wm831x-ldo.c
@@ -63,10 +63,8 @@
  */
 
 static const struct regulator_linear_range wm831x_gp_ldo_ranges[] = {
-	{ .min_uV =  900000, .max_uV = 1600000, .min_sel =  0, .max_sel = 14,
-	  .uV_step =  50000 },
-	{ .min_uV = 1700000, .max_uV = 3300000, .min_sel = 15, .max_sel = 31,
-	  .uV_step = 100000 },
+	REGULATOR_LINEAR_RANGE(900000, 0, 14, 50000),
+	REGULATOR_LINEAR_RANGE(1700000, 15, 31, 100000),
 };
 
 static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev,
@@ -279,7 +277,8 @@
 	config.driver_data = ldo;
 	config.regmap = wm831x->regmap;
 
-	ldo->regulator = regulator_register(&ldo->desc, &config);
+	ldo->regulator = devm_regulator_register(&pdev->dev, &ldo->desc,
+						 &config);
 	if (IS_ERR(ldo->regulator)) {
 		ret = PTR_ERR(ldo->regulator);
 		dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
@@ -288,39 +287,26 @@
 	}
 
 	irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
-	ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq,
-				   IRQF_TRIGGER_RISING, ldo->name,
-				   ldo);
+	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+					wm831x_ldo_uv_irq,
+					IRQF_TRIGGER_RISING, ldo->name,
+					ldo);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
 			irq, ret);
-		goto err_regulator;
+		goto err;
 	}
 
 	platform_set_drvdata(pdev, ldo);
 
 	return 0;
 
-err_regulator:
-	regulator_unregister(ldo->regulator);
 err:
 	return ret;
 }
 
-static int wm831x_gp_ldo_remove(struct platform_device *pdev)
-{
-	struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
-
-	free_irq(wm831x_irq(ldo->wm831x,
-			    platform_get_irq_byname(pdev, "UV")), ldo);
-	regulator_unregister(ldo->regulator);
-
-	return 0;
-}
-
 static struct platform_driver wm831x_gp_ldo_driver = {
 	.probe = wm831x_gp_ldo_probe,
-	.remove = wm831x_gp_ldo_remove,
 	.driver		= {
 		.name	= "wm831x-ldo",
 		.owner	= THIS_MODULE,
@@ -332,10 +318,8 @@
  */
 
 static const struct regulator_linear_range wm831x_aldo_ranges[] = {
-	{ .min_uV = 1000000, .max_uV = 1600000, .min_sel =  0, .max_sel = 12,
-	  .uV_step =  50000 },
-	{ .min_uV = 1700000, .max_uV = 3500000, .min_sel = 13, .max_sel = 31,
-	  .uV_step = 100000 },
+	REGULATOR_LINEAR_RANGE(1000000, 0, 12, 50000),
+	REGULATOR_LINEAR_RANGE(1700000, 13, 31, 100000),
 };
 
 static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev,
@@ -505,7 +489,8 @@
 	config.driver_data = ldo;
 	config.regmap = wm831x->regmap;
 
-	ldo->regulator = regulator_register(&ldo->desc, &config);
+	ldo->regulator = devm_regulator_register(&pdev->dev, &ldo->desc,
+						 &config);
 	if (IS_ERR(ldo->regulator)) {
 		ret = PTR_ERR(ldo->regulator);
 		dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
@@ -514,38 +499,25 @@
 	}
 
 	irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
-	ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq,
-				   IRQF_TRIGGER_RISING, ldo->name, ldo);
+	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+					wm831x_ldo_uv_irq,
+					IRQF_TRIGGER_RISING, ldo->name, ldo);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
 			irq, ret);
-		goto err_regulator;
+		goto err;
 	}
 
 	platform_set_drvdata(pdev, ldo);
 
 	return 0;
 
-err_regulator:
-	regulator_unregister(ldo->regulator);
 err:
 	return ret;
 }
 
-static int wm831x_aldo_remove(struct platform_device *pdev)
-{
-	struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
-
-	free_irq(wm831x_irq(ldo->wm831x, platform_get_irq_byname(pdev, "UV")),
-		 ldo);
-	regulator_unregister(ldo->regulator);
-
-	return 0;
-}
-
 static struct platform_driver wm831x_aldo_driver = {
 	.probe = wm831x_aldo_probe,
-	.remove = wm831x_aldo_remove,
 	.driver		= {
 		.name	= "wm831x-aldo",
 		.owner	= THIS_MODULE,
@@ -663,7 +635,8 @@
 	config.driver_data = ldo;
 	config.regmap = wm831x->regmap;
 
-	ldo->regulator = regulator_register(&ldo->desc, &config);
+	ldo->regulator = devm_regulator_register(&pdev->dev, &ldo->desc,
+						 &config);
 	if (IS_ERR(ldo->regulator)) {
 		ret = PTR_ERR(ldo->regulator);
 		dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
@@ -679,18 +652,8 @@
 	return ret;
 }
 
-static int wm831x_alive_ldo_remove(struct platform_device *pdev)
-{
-	struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
-
-	regulator_unregister(ldo->regulator);
-
-	return 0;
-}
-
 static struct platform_driver wm831x_alive_ldo_driver = {
 	.probe = wm831x_alive_ldo_probe,
-	.remove = wm831x_alive_ldo_remove,
 	.driver		= {
 		.name	= "wm831x-alive-ldo",
 		.owner	= THIS_MODULE,
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
index 61ca929..de7b9c7 100644
--- a/drivers/regulator/wm8350-regulator.c
+++ b/drivers/regulator/wm8350-regulator.c
@@ -543,10 +543,8 @@
 }
 
 static const struct regulator_linear_range wm8350_ldo_ranges[] = {
-	{ .min_uV =  900000, .max_uV = 1650000, .min_sel =  0, .max_sel = 15,
-	  .uV_step =  50000 },
-	{ .min_uV = 1800000, .max_uV = 3300000, .min_sel = 16, .max_sel = 31,
-	  .uV_step = 100000 },
+	REGULATOR_LINEAR_RANGE(900000, 0, 15, 50000),
+	REGULATOR_LINEAR_RANGE(1800000, 16, 31, 100000),
 };
 
 static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
@@ -1206,7 +1204,8 @@
 	config.regmap = wm8350->regmap;
 
 	/* register regulator */
-	rdev = regulator_register(&wm8350_reg[pdev->id], &config);
+	rdev = devm_regulator_register(&pdev->dev, &wm8350_reg[pdev->id],
+				       &config);
 	if (IS_ERR(rdev)) {
 		dev_err(&pdev->dev, "failed to register %s\n",
 			wm8350_reg[pdev->id].name);
@@ -1217,7 +1216,6 @@
 	ret = wm8350_register_irq(wm8350, wm8350_reg[pdev->id].irq,
 				  pmic_uv_handler, 0, "UV", rdev);
 	if (ret < 0) {
-		regulator_unregister(rdev);
 		dev_err(&pdev->dev, "failed to register regulator %s IRQ\n",
 			wm8350_reg[pdev->id].name);
 		return ret;
@@ -1233,8 +1231,6 @@
 
 	wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq, rdev);
 
-	regulator_unregister(rdev);
-
 	return 0;
 }
 
diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c
index 58f51be..82d8290 100644
--- a/drivers/regulator/wm8400-regulator.c
+++ b/drivers/regulator/wm8400-regulator.c
@@ -20,10 +20,8 @@
 #include <linux/mfd/wm8400-private.h>
 
 static const struct regulator_linear_range wm8400_ldo_ranges[] = {
-	{ .min_uV =  900000, .max_uV = 1600000, .min_sel = 0, .max_sel = 14,
-	  .uV_step =  50000 },
-	{ .min_uV = 1700000, .max_uV = 3300000, .min_sel = 15, .max_sel = 31,
-	  .uV_step = 100000 },
+	REGULATOR_LINEAR_RANGE(900000, 0, 14, 50000),
+	REGULATOR_LINEAR_RANGE(1700000, 15, 31, 100000),
 };
 
 static struct regulator_ops wm8400_ldo_ops = {
@@ -219,7 +217,8 @@
 	config.driver_data = wm8400;
 	config.regmap = wm8400->regmap;
 
-	rdev = regulator_register(&regulators[pdev->id], &config);
+	rdev = devm_regulator_register(&pdev->dev, &regulators[pdev->id],
+				       &config);
 	if (IS_ERR(rdev))
 		return PTR_ERR(rdev);
 
@@ -228,21 +227,11 @@
 	return 0;
 }
 
-static int wm8400_regulator_remove(struct platform_device *pdev)
-{
-	struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
-	regulator_unregister(rdev);
-
-	return 0;
-}
-
 static struct platform_driver wm8400_regulator_driver = {
 	.driver = {
 		.name = "wm8400-regulator",
 	},
 	.probe = wm8400_regulator_probe,
-	.remove = wm8400_regulator_remove,
 };
 
 /**
diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c
index 5ee2a20..71c5911 100644
--- a/drivers/regulator/wm8994-regulator.c
+++ b/drivers/regulator/wm8994-regulator.c
@@ -165,7 +165,9 @@
 		ldo->init_data = *pdata->ldo[id].init_data;
 	}
 
-	ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &config);
+	ldo->regulator = devm_regulator_register(&pdev->dev,
+						 &wm8994_ldo_desc[id],
+						 &config);
 	if (IS_ERR(ldo->regulator)) {
 		ret = PTR_ERR(ldo->regulator);
 		dev_err(wm8994->dev, "Failed to register LDO%d: %d\n",
@@ -181,18 +183,8 @@
 	return ret;
 }
 
-static int wm8994_ldo_remove(struct platform_device *pdev)
-{
-	struct wm8994_ldo *ldo = platform_get_drvdata(pdev);
-
-	regulator_unregister(ldo->regulator);
-
-	return 0;
-}
-
 static struct platform_driver wm8994_ldo_driver = {
 	.probe = wm8994_ldo_probe,
-	.remove = wm8994_ldo_remove,
 	.driver		= {
 		.name	= "wm8994-ldo",
 		.owner	= THIS_MODULE,
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 72c5cdb..544be72 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -72,6 +72,7 @@
 	} else
 		err = -EINVAL;
 
+	pm_stay_awake(rtc->dev.parent);
 	mutex_unlock(&rtc->ops_lock);
 	/* A timer might have just expired */
 	schedule_work(&rtc->irqwork);
@@ -113,6 +114,7 @@
 		err = -EINVAL;
 	}
 
+	pm_stay_awake(rtc->dev.parent);
 	mutex_unlock(&rtc->ops_lock);
 	/* A timer might have just expired */
 	schedule_work(&rtc->irqwork);
@@ -771,9 +773,10 @@
 		alarm.time = rtc_ktime_to_tm(timer->node.expires);
 		alarm.enabled = 1;
 		err = __rtc_set_alarm(rtc, &alarm);
-		if (err == -ETIME)
+		if (err == -ETIME) {
+			pm_stay_awake(rtc->dev.parent);
 			schedule_work(&rtc->irqwork);
-		else if (err) {
+		} else if (err) {
 			timerqueue_del(&rtc->timerqueue, &timer->node);
 			timer->enabled = 0;
 			return err;
@@ -818,8 +821,10 @@
 		alarm.time = rtc_ktime_to_tm(next->expires);
 		alarm.enabled = 1;
 		err = __rtc_set_alarm(rtc, &alarm);
-		if (err == -ETIME)
+		if (err == -ETIME) {
+			pm_stay_awake(rtc->dev.parent);
 			schedule_work(&rtc->irqwork);
+		}
 	}
 }
 
@@ -845,7 +850,6 @@
 
 	mutex_lock(&rtc->ops_lock);
 again:
-	pm_relax(rtc->dev.parent);
 	__rtc_read_time(rtc, &tm);
 	now = rtc_tm_to_ktime(tm);
 	while ((next = timerqueue_getnext(&rtc->timerqueue))) {
@@ -880,6 +884,7 @@
 	} else
 		rtc_alarm_disable(rtc);
 
+	pm_relax(rtc->dev.parent);
 	mutex_unlock(&rtc->ops_lock);
 }
 
diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c
index 4e2a818..45560ff 100644
--- a/drivers/rtc/rtc-hid-sensor-time.c
+++ b/drivers/rtc/rtc-hid-sensor-time.c
@@ -275,6 +275,12 @@
 		return ret;
 	}
 
+	ret = sensor_hub_device_open(hsdev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to open sensor hub device!\n");
+		goto err_open;
+	}
+
 	time_state->rtc = devm_rtc_device_register(&pdev->dev,
 					"hid-sensor-time", &hid_time_rtc_ops,
 					THIS_MODULE);
@@ -282,17 +288,24 @@
 	if (IS_ERR_OR_NULL(time_state->rtc)) {
 		ret = time_state->rtc ? PTR_ERR(time_state->rtc) : -ENODEV;
 		time_state->rtc = NULL;
-		sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME);
 		dev_err(&pdev->dev, "rtc device register failed!\n");
+		goto err_rtc;
 	}
 
 	return ret;
+
+err_rtc:
+	sensor_hub_device_close(hsdev);
+err_open:
+	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME);
+	return ret;
 }
 
 static int hid_time_remove(struct platform_device *pdev)
 {
 	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
 
+	sensor_hub_device_close(hsdev);
 	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME);
 
 	return 0;
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c
index 9c8f609..dc4f142 100644
--- a/drivers/rtc/rtc-mpc5121.c
+++ b/drivers/rtc/rtc-mpc5121.c
@@ -14,7 +14,9 @@
 #include <linux/module.h>
 #include <linux/rtc.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/io.h>
 #include <linux/slab.h>
diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c
index 578baf9..315209d9 100644
--- a/drivers/rtc/rtc-mrst.c
+++ b/drivers/rtc/rtc-mrst.c
@@ -38,8 +38,8 @@
 
 #include <asm-generic/rtc.h>
 #include <asm/intel_scu_ipc.h>
-#include <asm/mrst.h>
-#include <asm/mrst-vrtc.h>
+#include <asm/intel-mid.h>
+#include <asm/intel_mid_vrtc.h>
 
 struct mrst_rtc {
 	struct rtc_device	*rtc;
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
index 0f0609b..e3b2571 100644
--- a/drivers/rtc/rtc-pl031.c
+++ b/drivers/rtc/rtc-pl031.c
@@ -371,6 +371,7 @@
 		}
 	}
 
+	device_init_wakeup(&adev->dev, 1);
 	ldata->rtc = rtc_device_register("pl031", &adev->dev, ops,
 					THIS_MODULE);
 	if (IS_ERR(ldata->rtc)) {
@@ -384,8 +385,6 @@
 		goto out_no_irq;
 	}
 
-	device_init_wakeup(&adev->dev, 1);
-
 	return 0;
 
 out_no_irq:
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 451bf99..244f77f 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -698,10 +698,11 @@
 	}
 
 	spin_lock(&block->profile.lock);
-	if (block->profile.data)
+	if (block->profile.data) {
 		block->profile.data->dasd_io_nr_req[counter]++;
 		if (rq_data_dir(req) == READ)
 			block->profile.data->dasd_read_nr_req[counter]++;
+	}
 	spin_unlock(&block->profile.lock);
 
 	/*
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 5adb204..cee7e27 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -2077,6 +2077,7 @@
 	int intensity = 0;
 	int r0_perm;
 	int nr_tracks;
+	int use_prefix;
 
 	startdev = dasd_alias_get_start_dev(base);
 	if (!startdev)
@@ -2106,28 +2107,46 @@
 		intensity = fdata->intensity;
 	}
 
+	use_prefix = base_priv->features.feature[8] & 0x01;
+
 	switch (intensity) {
 	case 0x00:	/* Normal format */
 	case 0x08:	/* Normal format, use cdl. */
 		cplength = 2 + (rpt*nr_tracks);
-		datasize = sizeof(struct PFX_eckd_data) +
-			sizeof(struct LO_eckd_data) +
-			rpt * nr_tracks * sizeof(struct eckd_count);
+		if (use_prefix)
+			datasize = sizeof(struct PFX_eckd_data) +
+				sizeof(struct LO_eckd_data) +
+				rpt * nr_tracks * sizeof(struct eckd_count);
+		else
+			datasize = sizeof(struct DE_eckd_data) +
+				sizeof(struct LO_eckd_data) +
+				rpt * nr_tracks * sizeof(struct eckd_count);
 		break;
 	case 0x01:	/* Write record zero and format track. */
 	case 0x09:	/* Write record zero and format track, use cdl. */
 		cplength = 2 + rpt * nr_tracks;
-		datasize = sizeof(struct PFX_eckd_data) +
-			sizeof(struct LO_eckd_data) +
-			sizeof(struct eckd_count) +
-			rpt * nr_tracks * sizeof(struct eckd_count);
+		if (use_prefix)
+			datasize = sizeof(struct PFX_eckd_data) +
+				sizeof(struct LO_eckd_data) +
+				sizeof(struct eckd_count) +
+				rpt * nr_tracks * sizeof(struct eckd_count);
+		else
+			datasize = sizeof(struct DE_eckd_data) +
+				sizeof(struct LO_eckd_data) +
+				sizeof(struct eckd_count) +
+				rpt * nr_tracks * sizeof(struct eckd_count);
 		break;
 	case 0x04:	/* Invalidate track. */
 	case 0x0c:	/* Invalidate track, use cdl. */
 		cplength = 3;
-		datasize = sizeof(struct PFX_eckd_data) +
-			sizeof(struct LO_eckd_data) +
-			sizeof(struct eckd_count);
+		if (use_prefix)
+			datasize = sizeof(struct PFX_eckd_data) +
+				sizeof(struct LO_eckd_data) +
+				sizeof(struct eckd_count);
+		else
+			datasize = sizeof(struct DE_eckd_data) +
+				sizeof(struct LO_eckd_data) +
+				sizeof(struct eckd_count);
 		break;
 	default:
 		dev_warn(&startdev->cdev->dev,
@@ -2147,14 +2166,25 @@
 
 	switch (intensity & ~0x08) {
 	case 0x00: /* Normal format. */
-		prefix(ccw++, (struct PFX_eckd_data *) data,
-		       fdata->start_unit, fdata->stop_unit,
-		       DASD_ECKD_CCW_WRITE_CKD, base, startdev);
-		/* grant subsystem permission to format R0 */
-		if (r0_perm)
-			((struct PFX_eckd_data *)data)
-				->define_extent.ga_extended |= 0x04;
-		data += sizeof(struct PFX_eckd_data);
+		if (use_prefix) {
+			prefix(ccw++, (struct PFX_eckd_data *) data,
+			       fdata->start_unit, fdata->stop_unit,
+			       DASD_ECKD_CCW_WRITE_CKD, base, startdev);
+			/* grant subsystem permission to format R0 */
+			if (r0_perm)
+				((struct PFX_eckd_data *)data)
+					->define_extent.ga_extended |= 0x04;
+			data += sizeof(struct PFX_eckd_data);
+		} else {
+			define_extent(ccw++, (struct DE_eckd_data *) data,
+				      fdata->start_unit, fdata->stop_unit,
+				      DASD_ECKD_CCW_WRITE_CKD, startdev);
+			/* grant subsystem permission to format R0 */
+			if (r0_perm)
+				((struct DE_eckd_data *) data)
+					->ga_extended |= 0x04;
+			data += sizeof(struct DE_eckd_data);
+		}
 		ccw[-1].flags |= CCW_FLAG_CC;
 		locate_record(ccw++, (struct LO_eckd_data *) data,
 			      fdata->start_unit, 0, rpt*nr_tracks,
@@ -2163,11 +2193,18 @@
 		data += sizeof(struct LO_eckd_data);
 		break;
 	case 0x01: /* Write record zero + format track. */
-		prefix(ccw++, (struct PFX_eckd_data *) data,
-		       fdata->start_unit, fdata->stop_unit,
-		       DASD_ECKD_CCW_WRITE_RECORD_ZERO,
-		       base, startdev);
-		data += sizeof(struct PFX_eckd_data);
+		if (use_prefix) {
+			prefix(ccw++, (struct PFX_eckd_data *) data,
+			       fdata->start_unit, fdata->stop_unit,
+			       DASD_ECKD_CCW_WRITE_RECORD_ZERO,
+			       base, startdev);
+			data += sizeof(struct PFX_eckd_data);
+		} else {
+			define_extent(ccw++, (struct DE_eckd_data *) data,
+			       fdata->start_unit, fdata->stop_unit,
+			       DASD_ECKD_CCW_WRITE_RECORD_ZERO, startdev);
+			data += sizeof(struct DE_eckd_data);
+		}
 		ccw[-1].flags |= CCW_FLAG_CC;
 		locate_record(ccw++, (struct LO_eckd_data *) data,
 			      fdata->start_unit, 0, rpt * nr_tracks + 1,
@@ -2176,10 +2213,17 @@
 		data += sizeof(struct LO_eckd_data);
 		break;
 	case 0x04: /* Invalidate track. */
-		prefix(ccw++, (struct PFX_eckd_data *) data,
-		       fdata->start_unit, fdata->stop_unit,
-		       DASD_ECKD_CCW_WRITE_CKD, base, startdev);
-		data += sizeof(struct PFX_eckd_data);
+		if (use_prefix) {
+			prefix(ccw++, (struct PFX_eckd_data *) data,
+			       fdata->start_unit, fdata->stop_unit,
+			       DASD_ECKD_CCW_WRITE_CKD, base, startdev);
+			data += sizeof(struct PFX_eckd_data);
+		} else {
+			define_extent(ccw++, (struct DE_eckd_data *) data,
+			       fdata->start_unit, fdata->stop_unit,
+			       DASD_ECKD_CCW_WRITE_CKD, startdev);
+			data += sizeof(struct DE_eckd_data);
+		}
 		ccw[-1].flags |= CCW_FLAG_CC;
 		locate_record(ccw++, (struct LO_eckd_data *) data,
 			      fdata->start_unit, 0, 1,
diff --git a/drivers/s390/block/scm_blk.c b/drivers/s390/block/scm_blk.c
index 5d73e6e..548209a 100644
--- a/drivers/s390/block/scm_blk.c
+++ b/drivers/s390/block/scm_blk.c
@@ -223,8 +223,12 @@
 	int ret;
 
 	while ((req = blk_peek_request(rq))) {
-		if (req->cmd_type != REQ_TYPE_FS)
+		if (req->cmd_type != REQ_TYPE_FS) {
+			blk_start_request(req);
+			blk_dump_rq_flags(req, KMSG_COMPONENT " bad request");
+			blk_end_request_all(req, -EIO);
 			continue;
+		}
 
 		if (!scm_permit_request(bdev, req)) {
 			scm_ensure_queue_restart(bdev);
diff --git a/drivers/s390/block/scm_blk.h b/drivers/s390/block/scm_blk.h
index 8b387b3..e59331e 100644
--- a/drivers/s390/block/scm_blk.h
+++ b/drivers/s390/block/scm_blk.h
@@ -107,7 +107,7 @@
 
 static inline void SCM_LOG_HEX(int level, void *data, int length)
 {
-	if (level > scm_debug->level)
+	if (!debug_level_enabled(scm_debug, level))
 		return;
 	while (length > 0) {
 		debug_event(scm_debug, level, data, length);
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c
index 4600aa1..668b32b 100644
--- a/drivers/s390/char/monwriter.c
+++ b/drivers/s390/char/monwriter.c
@@ -60,7 +60,7 @@
 	struct appldata_product_id id;
 	int rc;
 
-	strcpy(id.prod_nr, "LNXAPPL");
+	strncpy(id.prod_nr, "LNXAPPL", 7);
 	id.prod_fn = myhdr->applid;
 	id.record_nr = myhdr->record_num;
 	id.version_nr = myhdr->version;
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 24a08e8..2cdec21 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -615,10 +615,10 @@
 
 	if (rp->state != RAW3270_STATE_RESET)
 		return;
-	if (rq && rq->rc) {
+	if (rq->rc) {
 		/* Reset command failed. */
 		rp->state = RAW3270_STATE_INIT;
-	} else if (0 && MACHINE_IS_VM) {
+	} else if (MACHINE_IS_VM) {
 		raw3270_size_device_vm(rp);
 		raw3270_size_device_done(rp);
 	} else
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index a3aa374..1fe2643 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -486,7 +486,7 @@
 	timeout = 0;
 	if (timer_pending(&sclp_request_timer)) {
 		/* Get timeout TOD value */
-		timeout = get_tod_clock() +
+		timeout = get_tod_clock_fast() +
 			  sclp_tod_from_jiffies(sclp_request_timer.expires -
 						jiffies);
 	}
@@ -508,7 +508,7 @@
 	while (sclp_running_state != sclp_running_state_idle) {
 		/* Check for expired request timer */
 		if (timer_pending(&sclp_request_timer) &&
-		    get_tod_clock() > timeout &&
+		    get_tod_clock_fast() > timeout &&
 		    del_timer(&sclp_request_timer))
 			sclp_request_timer.function(sclp_request_timer.data);
 		cpu_relax();
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index 8cd34bf..77df9cb 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -145,9 +145,11 @@
 
 	if (sccb->header.response_code != 0x20)
 		return 0;
-	if (sccb->sclp_send_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK))
-		return 1;
-	return 0;
+	if (!(sccb->sclp_send_mask & (EVTYP_OPCMD_MASK | EVTYP_PMSGCMD_MASK)))
+		return 0;
+	if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK)))
+		return 0;
+	return 1;
 }
 
 bool __init sclp_has_vt220(void)
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index a0f47c8..3f4ca4e 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -810,7 +810,7 @@
 	struct winsize ws;
 
 	screen = tty3270_alloc_screen(tp->n_rows, tp->n_cols);
-	if (!screen)
+	if (IS_ERR(screen))
 		return;
 	/* Switch to new output size */
 	spin_lock_bh(&tp->view.lock);
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index 9b3a24e..cf31d33 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -313,7 +313,7 @@
 	int ret;
 
 	dev_num = iminor(inode);
-	if (dev_num > MAXMINOR)
+	if (dev_num >= MAXMINOR)
 		return -ENODEV;
 	logptr = &sys_ser[dev_num];
 
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 794820a..ffb1fcf 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -151,7 +151,7 @@
 
 	/* get info for boot cpu from lowcore, stored in the HSA */
 
-	sa = kmalloc(sizeof(*sa), GFP_KERNEL);
+	sa = dump_save_area_create(0);
 	if (!sa)
 		return -ENOMEM;
 	if (memcpy_hsa_kernel(sa, sys_info.sa_base, sys_info.sa_size) < 0) {
@@ -159,7 +159,6 @@
 		kfree(sa);
 		return -EIO;
 	}
-	zfcpdump_save_areas[0] = sa;
 	return 0;
 }
 
@@ -246,24 +245,25 @@
 static int zcore_add_lc(char __user *buf, unsigned long start, size_t count)
 {
 	unsigned long end;
-	int i = 0;
+	int i;
 
 	if (count == 0)
 		return 0;
 
 	end = start + count;
-	while (zfcpdump_save_areas[i]) {
+	for (i = 0; i < dump_save_areas.count; i++) {
 		unsigned long cp_start, cp_end; /* copy range */
 		unsigned long sa_start, sa_end; /* save area range */
 		unsigned long prefix;
 		unsigned long sa_off, len, buf_off;
+		struct save_area *save_area = dump_save_areas.areas[i];
 
-		prefix = zfcpdump_save_areas[i]->pref_reg;
+		prefix = save_area->pref_reg;
 		sa_start = prefix + sys_info.sa_base;
 		sa_end = prefix + sys_info.sa_base + sys_info.sa_size;
 
 		if ((end < sa_start) || (start > sa_end))
-			goto next;
+			continue;
 		cp_start = max(start, sa_start);
 		cp_end = min(end, sa_end);
 
@@ -272,10 +272,8 @@
 		len = cp_end - cp_start;
 
 		TRACE("copy_lc for: %lx\n", start);
-		if (copy_lc(buf + buf_off, zfcpdump_save_areas[i], sa_off, len))
+		if (copy_lc(buf + buf_off, save_area, sa_off, len))
 			return -EFAULT;
-next:
-		i++;
 	}
 	return 0;
 }
@@ -637,8 +635,8 @@
 	hdr->num_pages = mem_size / PAGE_SIZE;
 	hdr->tod = get_tod_clock();
 	get_cpu_id(&hdr->cpu_id);
-	for (i = 0; zfcpdump_save_areas[i]; i++) {
-		prefix = zfcpdump_save_areas[i]->pref_reg;
+	for (i = 0; i < dump_save_areas.count; i++) {
+		prefix = dump_save_areas.areas[i]->pref_reg;
 		hdr->real_cpu_cnt++;
 		if (!prefix)
 			continue;
diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c
index d028fd8..f055df0 100644
--- a/drivers/s390/cio/airq.c
+++ b/drivers/s390/cio/airq.c
@@ -194,15 +194,14 @@
  */
 unsigned long airq_iv_alloc_bit(struct airq_iv *iv)
 {
-	const unsigned long be_to_le = BITS_PER_LONG - 1;
 	unsigned long bit;
 
 	if (!iv->avail)
 		return -1UL;
 	spin_lock(&iv->lock);
-	bit = find_first_bit_left(iv->avail, iv->bits);
+	bit = find_first_bit_inv(iv->avail, iv->bits);
 	if (bit < iv->bits) {
-		clear_bit(bit ^ be_to_le, iv->avail);
+		clear_bit_inv(bit, iv->avail);
 		if (bit >= iv->end)
 			iv->end = bit + 1;
 	} else
@@ -220,19 +219,17 @@
  */
 void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit)
 {
-	const unsigned long be_to_le = BITS_PER_LONG - 1;
-
 	if (!iv->avail)
 		return;
 	spin_lock(&iv->lock);
 	/* Clear (possibly left over) interrupt bit */
-	clear_bit(bit ^ be_to_le, iv->vector);
+	clear_bit_inv(bit, iv->vector);
 	/* Make the bit position available again */
-	set_bit(bit ^ be_to_le, iv->avail);
+	set_bit_inv(bit, iv->avail);
 	if (bit == iv->end - 1) {
 		/* Find new end of bit-field */
 		while (--iv->end > 0)
-			if (!test_bit((iv->end - 1) ^ be_to_le, iv->avail))
+			if (!test_bit_inv(iv->end - 1, iv->avail))
 				break;
 	}
 	spin_unlock(&iv->lock);
@@ -251,15 +248,13 @@
 unsigned long airq_iv_scan(struct airq_iv *iv, unsigned long start,
 			   unsigned long end)
 {
-	const unsigned long be_to_le = BITS_PER_LONG - 1;
 	unsigned long bit;
 
 	/* Find non-zero bit starting from 'ivs->next'. */
-	bit = find_next_bit_left(iv->vector, end, start);
+	bit = find_next_bit_inv(iv->vector, end, start);
 	if (bit >= end)
 		return -1UL;
-	/* Clear interrupt bit (find left uses big-endian bit numbers) */
-	clear_bit(bit ^ be_to_le, iv->vector);
+	clear_bit_inv(bit, iv->vector);
 	return bit;
 }
 EXPORT_SYMBOL(airq_iv_scan);
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index d7da67a..88e35d8 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -878,9 +878,9 @@
 			atomic_inc(&chpid_reset_count);
 	}
 	/* Wait for machine check for all channel paths. */
-	timeout = get_tod_clock() + (RCHP_TIMEOUT << 12);
+	timeout = get_tod_clock_fast() + (RCHP_TIMEOUT << 12);
 	while (atomic_read(&chpid_reset_count) != 0) {
-		if (get_tod_clock() > timeout)
+		if (get_tod_clock_fast() > timeout)
 			break;
 		cpu_relax();
 	}
diff --git a/drivers/s390/cio/eadm_sch.c b/drivers/s390/cio/eadm_sch.c
index d9eddcb..aca7bfc 100644
--- a/drivers/s390/cio/eadm_sch.c
+++ b/drivers/s390/cio/eadm_sch.c
@@ -6,6 +6,7 @@
  */
 
 #include <linux/kernel_stat.h>
+#include <linux/completion.h>
 #include <linux/workqueue.h>
 #include <linux/spinlock.h>
 #include <linux/device.h>
@@ -42,7 +43,7 @@
 
 static void EADM_LOG_HEX(int level, void *data, int length)
 {
-	if (level > eadm_debug->level)
+	if (!debug_level_enabled(eadm_debug, level))
 		return;
 	while (length > 0) {
 		debug_event(eadm_debug, level, data, length);
@@ -159,6 +160,9 @@
 	}
 	scm_irq_handler((struct aob *)(unsigned long)scsw->aob, error);
 	private->state = EADM_IDLE;
+
+	if (private->completion)
+		complete(private->completion);
 }
 
 static struct subchannel *eadm_get_idle_sch(void)
@@ -255,13 +259,32 @@
 
 static void eadm_quiesce(struct subchannel *sch)
 {
+	struct eadm_private *private = get_eadm_private(sch);
+	DECLARE_COMPLETION_ONSTACK(completion);
 	int ret;
 
+	spin_lock_irq(sch->lock);
+	if (private->state != EADM_BUSY)
+		goto disable;
+
+	if (eadm_subchannel_clear(sch))
+		goto disable;
+
+	private->completion = &completion;
+	spin_unlock_irq(sch->lock);
+
+	wait_for_completion_io(&completion);
+
+	spin_lock_irq(sch->lock);
+	private->completion = NULL;
+
+disable:
+	eadm_subchannel_set_timeout(sch, 0);
 	do {
-		spin_lock_irq(sch->lock);
 		ret = cio_disable_subchannel(sch);
-		spin_unlock_irq(sch->lock);
 	} while (ret == -EBUSY);
+
+	spin_unlock_irq(sch->lock);
 }
 
 static int eadm_subchannel_remove(struct subchannel *sch)
diff --git a/drivers/s390/cio/eadm_sch.h b/drivers/s390/cio/eadm_sch.h
index 2779be0..9664e46 100644
--- a/drivers/s390/cio/eadm_sch.h
+++ b/drivers/s390/cio/eadm_sch.h
@@ -1,6 +1,7 @@
 #ifndef EADM_SCH_H
 #define EADM_SCH_H
 
+#include <linux/completion.h>
 #include <linux/device.h>
 #include <linux/timer.h>
 #include <linux/list.h>
@@ -9,9 +10,10 @@
 struct eadm_private {
 	union orb orb;
 	enum {EADM_IDLE, EADM_BUSY, EADM_NOT_OPER} state;
+	struct completion *completion;
+	struct subchannel *sch;
 	struct timer_list timer;
 	struct list_head head;
-	struct subchannel *sch;
 } __aligned(8);
 
 #define get_eadm_private(n) ((struct eadm_private *)dev_get_drvdata(&n->dev))
diff --git a/drivers/s390/cio/qdio_debug.h b/drivers/s390/cio/qdio_debug.h
index 647b422..dfac9bf 100644
--- a/drivers/s390/cio/qdio_debug.h
+++ b/drivers/s390/cio/qdio_debug.h
@@ -16,12 +16,6 @@
 extern debug_info_t *qdio_dbf_setup;
 extern debug_info_t *qdio_dbf_error;
 
-/* sort out low debug levels early to avoid wasted sprints */
-static inline int qdio_dbf_passes(debug_info_t *dbf_grp, int level)
-{
-	return (level <= dbf_grp->level);
-}
-
 #define DBF_ERR		3	/* error conditions	*/
 #define DBF_WARN	4	/* warning conditions	*/
 #define DBF_INFO	6	/* informational	*/
@@ -65,7 +59,7 @@
 #define DBF_DEV_EVENT(level, device, text...) \
 	do { \
 		char debug_buffer[QDIO_DBF_LEN]; \
-		if (qdio_dbf_passes(device->debug_area, level)) { \
+		if (debug_level_enabled(device->debug_area, level)) { \
 			snprintf(debug_buffer, QDIO_DBF_LEN, text); \
 			debug_text_event(device->debug_area, level, debug_buffer); \
 		} \
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 8ed52aa..3e602e8 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -338,10 +338,10 @@
 		retries++;
 
 		if (!start_time) {
-			start_time = get_tod_clock();
+			start_time = get_tod_clock_fast();
 			goto again;
 		}
-		if ((get_tod_clock() - start_time) < QDIO_BUSY_BIT_PATIENCE)
+		if (get_tod_clock_fast() - start_time < QDIO_BUSY_BIT_PATIENCE)
 			goto again;
 	}
 	if (retries) {
@@ -504,7 +504,7 @@
 	int count, stop;
 	unsigned char state = 0;
 
-	q->timestamp = get_tod_clock();
+	q->timestamp = get_tod_clock_fast();
 
 	/*
 	 * Don't check 128 buffers, as otherwise qdio_inbound_q_moved
@@ -528,7 +528,7 @@
 	case SLSB_P_INPUT_PRIMED:
 		inbound_primed(q, count);
 		q->first_to_check = add_buf(q->first_to_check, count);
-		if (atomic_sub(count, &q->nr_buf_used) == 0)
+		if (atomic_sub_return(count, &q->nr_buf_used) == 0)
 			qperf_inc(q, inbound_queue_full);
 		if (q->irq_ptr->perf_stat_enabled)
 			account_sbals(q, count);
@@ -595,7 +595,7 @@
 	 * At this point we know, that inbound first_to_check
 	 * has (probably) not moved (see qdio_inbound_processing).
 	 */
-	if (get_tod_clock() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) {
+	if (get_tod_clock_fast() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) {
 		DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in done:%02x",
 			      q->first_to_check);
 		return 1;
@@ -728,7 +728,7 @@
 	int count, stop;
 	unsigned char state = 0;
 
-	q->timestamp = get_tod_clock();
+	q->timestamp = get_tod_clock_fast();
 
 	if (need_siga_sync(q))
 		if (((queue_type(q) != QDIO_IQDIO_QFMT) &&
diff --git a/drivers/s390/crypto/zcrypt_debug.h b/drivers/s390/crypto/zcrypt_debug.h
index 841ea72..28d9349 100644
--- a/drivers/s390/crypto/zcrypt_debug.h
+++ b/drivers/s390/crypto/zcrypt_debug.h
@@ -11,12 +11,6 @@
 /* that gives us 15 characters in the text event views */
 #define ZCRYPT_DBF_LEN	16
 
-/* sort out low debug levels early to avoid wasted sprints */
-static inline int zcrypt_dbf_passes(debug_info_t *dbf_grp, int level)
-{
-	return (level <= dbf_grp->level);
-}
-
 #define DBF_ERR		3	/* error conditions	*/
 #define DBF_WARN	4	/* warning conditions	*/
 #define DBF_INFO	6	/* informational	*/
@@ -25,7 +19,7 @@
 
 #define ZCRYPT_DBF_COMMON(level, text...) \
 	do { \
-		if (zcrypt_dbf_passes(zcrypt_dbf_common, level)) { \
+		if (debug_level_enabled(zcrypt_dbf_common, level)) { \
 			char debug_buffer[ZCRYPT_DBF_LEN]; \
 			snprintf(debug_buffer, ZCRYPT_DBF_LEN, text); \
 			debug_text_event(zcrypt_dbf_common, level, \
@@ -35,7 +29,7 @@
 
 #define ZCRYPT_DBF_DEVICES(level, text...) \
 	do { \
-		if (zcrypt_dbf_passes(zcrypt_dbf_devices, level)) { \
+		if (debug_level_enabled(zcrypt_dbf_devices, level)) { \
 			char debug_buffer[ZCRYPT_DBF_LEN]; \
 			snprintf(debug_buffer, ZCRYPT_DBF_LEN, text); \
 			debug_text_event(zcrypt_dbf_devices, level, \
@@ -45,7 +39,7 @@
 
 #define ZCRYPT_DBF_DEV(level, device, text...) \
 	do { \
-		if (zcrypt_dbf_passes(device->dbf_area, level)) { \
+		if (debug_level_enabled(device->dbf_area, level)) { \
 			char debug_buffer[ZCRYPT_DBF_LEN]; \
 			snprintf(debug_buffer, ZCRYPT_DBF_LEN, text); \
 			debug_text_event(device->dbf_area, level, \
diff --git a/drivers/s390/net/claw.h b/drivers/s390/net/claw.h
index 1bc5904..3339b9b 100644
--- a/drivers/s390/net/claw.h
+++ b/drivers/s390/net/claw.h
@@ -114,15 +114,9 @@
 	debug_event(claw_dbf_##name,level,(void*)(addr),len); \
 } while (0)
 
-/* Allow to sort out low debug levels early to avoid wasted sprints */
-static inline int claw_dbf_passes(debug_info_t *dbf_grp, int level)
-{
-	return (level <= dbf_grp->level);
-}
-
 #define CLAW_DBF_TEXT_(level,name,text...) \
 	do { \
-		if (claw_dbf_passes(claw_dbf_##name, level)) { \
+		if (debug_level_enabled(claw_dbf_##name, level)) { \
 			sprintf(debug_buffer, text); \
 			debug_text_event(claw_dbf_##name, level, \
 						debug_buffer); \
diff --git a/drivers/s390/net/ctcm_dbug.c b/drivers/s390/net/ctcm_dbug.c
index 6514e1c..8363f1c9 100644
--- a/drivers/s390/net/ctcm_dbug.c
+++ b/drivers/s390/net/ctcm_dbug.c
@@ -66,7 +66,7 @@
 	char dbf_txt_buf[64];
 	va_list args;
 
-	if (level > (ctcm_dbf[dbf_nix].id)->level)
+	if (!debug_level_enabled(ctcm_dbf[dbf_nix].id, level))
 		return;
 	va_start(args, fmt);
 	vsnprintf(dbf_txt_buf, sizeof(dbf_txt_buf), fmt, args);
diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h
index 8c03392..150fcb4 100644
--- a/drivers/s390/net/lcs.h
+++ b/drivers/s390/net/lcs.h
@@ -16,15 +16,9 @@
 	debug_event(lcs_dbf_##name,level,(void*)(addr),len); \
 } while (0)
 
-/* Allow to sort out low debug levels early to avoid wasted sprints */
-static inline int lcs_dbf_passes(debug_info_t *dbf_grp, int level)
-{
-	return (level <= dbf_grp->level);
-}
-
 #define LCS_DBF_TEXT_(level,name,text...) \
 	do { \
-		if (lcs_dbf_passes(lcs_dbf_##name, level)) { \
+		if (debug_level_enabled(lcs_dbf_##name, level)) { \
 			sprintf(debug_buffer, text); \
 			debug_text_event(lcs_dbf_##name, level, debug_buffer); \
 		} \
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 279ad50..9b333fc 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -105,15 +105,9 @@
 
 DECLARE_PER_CPU(char[256], iucv_dbf_txt_buf);
 
-/* Allow to sort out low debug levels early to avoid wasted sprints */
-static inline int iucv_dbf_passes(debug_info_t *dbf_grp, int level)
-{
-	return (level <= dbf_grp->level);
-}
-
 #define IUCV_DBF_TEXT_(name, level, text...) \
 	do { \
-		if (iucv_dbf_passes(iucv_dbf_##name, level)) { \
+		if (debug_level_enabled(iucv_dbf_##name, level)) { \
 			char* __buf = get_cpu_var(iucv_dbf_txt_buf); \
 			sprintf(__buf, text); \
 			debug_text_event(iucv_dbf_##name, level, __buf); \
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 0a328d0..d7b66a2 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -5096,7 +5096,7 @@
 	char dbf_txt_buf[32];
 	va_list args;
 
-	if (level > id->level)
+	if (!debug_level_enabled(id, level))
 		return;
 	va_start(args, fmt);
 	vsnprintf(dbf_txt_buf, sizeof(dbf_txt_buf), fmt, args);
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h
index 3ac7a4b..0be3d48 100644
--- a/drivers/s390/scsi/zfcp_dbf.h
+++ b/drivers/s390/scsi/zfcp_dbf.h
@@ -278,7 +278,7 @@
 static inline
 void zfcp_dbf_hba_fsf_resp(char *tag, int level, struct zfcp_fsf_req *req)
 {
-	if (level <= req->adapter->dbf->hba->level)
+	if (debug_level_enabled(req->adapter->dbf->hba, level))
 		zfcp_dbf_hba_fsf_res(tag, req);
 }
 
@@ -317,7 +317,7 @@
 	struct zfcp_adapter *adapter = (struct zfcp_adapter *)
 					scmd->device->host->hostdata[0];
 
-	if (level <= adapter->dbf->scsi->level)
+	if (debug_level_enabled(adapter->dbf->scsi, level))
 		zfcp_dbf_scsi(tag, scmd, req);
 }
 
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index feab3a5..757eb07 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -696,7 +696,7 @@
 	while ((pci_device = pci_get_device(PCI_VENDOR_ID_BUSLOGIC,
 					PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
 					pci_device)) != NULL) {
-		struct blogic_adapter *adapter = adapter;
+		struct blogic_adapter *host_adapter = adapter;
 		struct blogic_adapter_info adapter_info;
 		enum blogic_isa_ioport mod_ioaddr_req;
 		unsigned char bus;
@@ -744,9 +744,9 @@
 		   known and enabled, note that the particular Standard ISA I/O
 		   Address should not be probed.
 		 */
-		adapter->io_addr = io_addr;
-		blogic_intreset(adapter);
-		if (blogic_cmd(adapter, BLOGIC_INQ_PCI_INFO, NULL, 0,
+		host_adapter->io_addr = io_addr;
+		blogic_intreset(host_adapter);
+		if (blogic_cmd(host_adapter, BLOGIC_INQ_PCI_INFO, NULL, 0,
 				&adapter_info, sizeof(adapter_info)) ==
 				sizeof(adapter_info)) {
 			if (adapter_info.isa_port < 6)
@@ -762,7 +762,7 @@
 		   I/O Address assigned at system initialization.
 		 */
 		mod_ioaddr_req = BLOGIC_IO_DISABLE;
-		blogic_cmd(adapter, BLOGIC_MOD_IOADDR, &mod_ioaddr_req,
+		blogic_cmd(host_adapter, BLOGIC_MOD_IOADDR, &mod_ioaddr_req,
 				sizeof(mod_ioaddr_req), NULL, 0);
 		/*
 		   For the first MultiMaster Host Adapter enumerated,
@@ -779,12 +779,12 @@
 
 			fetch_localram.offset = BLOGIC_AUTOSCSI_BASE + 45;
 			fetch_localram.count = sizeof(autoscsi_byte45);
-			blogic_cmd(adapter, BLOGIC_FETCH_LOCALRAM,
+			blogic_cmd(host_adapter, BLOGIC_FETCH_LOCALRAM,
 					&fetch_localram, sizeof(fetch_localram),
 					&autoscsi_byte45,
 					sizeof(autoscsi_byte45));
-			blogic_cmd(adapter, BLOGIC_GET_BOARD_ID, NULL, 0, &id,
-					sizeof(id));
+			blogic_cmd(host_adapter, BLOGIC_GET_BOARD_ID, NULL, 0,
+					&id, sizeof(id));
 			if (id.fw_ver_digit1 == '5')
 				force_scan_order =
 					autoscsi_byte45.force_scan_order;
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 408a42e..f0d432c 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -771,6 +771,8 @@
 static int aac_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
 {
 	struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
+	if (!capable(CAP_SYS_RAWIO))
+		return -EPERM;
 	return aac_compat_do_ioctl(dev, cmd, (unsigned long)arg);
 }
 
diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c
index c9382d6..1f4f22f 100644
--- a/drivers/scsi/fcoe/fcoe_sysfs.c
+++ b/drivers/scsi/fcoe/fcoe_sysfs.c
@@ -553,16 +553,20 @@
 	.release = fcoe_fcf_device_release,
 };
 
-static struct bus_attribute fcoe_bus_attr_group[] = {
-	__ATTR(ctlr_create, S_IWUSR, NULL, fcoe_ctlr_create_store),
-	__ATTR(ctlr_destroy, S_IWUSR, NULL, fcoe_ctlr_destroy_store),
-	__ATTR_NULL
+static BUS_ATTR(ctlr_create, S_IWUSR, NULL, fcoe_ctlr_create_store);
+static BUS_ATTR(ctlr_destroy, S_IWUSR, NULL, fcoe_ctlr_destroy_store);
+
+static struct attribute *fcoe_bus_attrs[] = {
+	&bus_attr_ctlr_create.attr,
+	&bus_attr_ctlr_destroy.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(fcoe_bus);
 
 static struct bus_type fcoe_bus_type = {
 	.name = "fcoe",
 	.match = &fcoe_bus_match,
-	.bus_attrs = fcoe_bus_attr_group,
+	.bus_groups = fcoe_bus_groups,
 };
 
 /**
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 2ef497e..ee5c183 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -20,7 +20,7 @@
  * | Device Discovery             |       0x2095       | 0x2020-0x2022, |
  * |                              |                    | 0x2011-0x2012, |
  * |                              |                    | 0x2016         |
- * | Queue Command and IO tracing |       0x3058       | 0x3006-0x300b  |
+ * | Queue Command and IO tracing |       0x3059       | 0x3006-0x300b  |
  * |                              |                    | 0x3027-0x3028  |
  * |                              |                    | 0x303d-0x3041  |
  * |                              |                    | 0x302d,0x3033  |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index df1b30b..ff9c86b 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1957,6 +1957,15 @@
 	que = MSW(sts->handle);
 	req = ha->req_q_map[que];
 
+	/* Check for invalid queue pointer */
+	if (req == NULL ||
+	    que >= find_first_zero_bit(ha->req_qid_map, ha->max_req_queues)) {
+		ql_dbg(ql_dbg_io, vha, 0x3059,
+		    "Invalid status handle (0x%x): Bad req pointer. req=%p, "
+		    "que=%u.\n", sts->handle, req, que);
+		return;
+	}
+
 	/* Validate handle. */
 	if (handle < req->num_outstanding_cmds)
 		sp = req->outstanding_cmds[handle];
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index e62d17d..5693f6d7 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2854,6 +2854,7 @@
 		gd->events |= DISK_EVENT_MEDIA_CHANGE;
 	}
 
+	blk_pm_runtime_init(sdp->request_queue, dev);
 	add_disk(gd);
 	if (sdkp->capacity)
 		sd_dif_config_host(sdkp);
@@ -2862,7 +2863,6 @@
 
 	sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
 		  sdp->removable ? "removable " : "");
-	blk_pm_runtime_init(sdp->request_queue, dev);
 	scsi_autopm_put_device(sdp);
 	put_device(&sdkp->dev);
 }
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 5cbc4bb..df5e961 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -105,8 +105,11 @@
 static int sg_add(struct device *, struct class_interface *);
 static void sg_remove(struct device *, struct class_interface *);
 
+static DEFINE_SPINLOCK(sg_open_exclusive_lock);
+
 static DEFINE_IDR(sg_index_idr);
-static DEFINE_RWLOCK(sg_index_lock);
+static DEFINE_RWLOCK(sg_index_lock);	/* Also used to lock
+							   file descriptor list for device */
 
 static struct class_interface sg_interface = {
 	.add_dev	= sg_add,
@@ -143,7 +146,8 @@
 } Sg_request;
 
 typedef struct sg_fd {		/* holds the state of a file descriptor */
-	struct list_head sfd_siblings; /* protected by sfd_lock of device */
+	/* sfd_siblings is protected by sg_index_lock */
+	struct list_head sfd_siblings;
 	struct sg_device *parentdp;	/* owning device */
 	wait_queue_head_t read_wait;	/* queue read until command done */
 	rwlock_t rq_list_lock;	/* protect access to list in req_arr */
@@ -166,12 +170,13 @@
 
 typedef struct sg_device { /* holds the state of each scsi generic device */
 	struct scsi_device *device;
+	wait_queue_head_t o_excl_wait;	/* queue open() when O_EXCL in use */
 	int sg_tablesize;	/* adapter's max scatter-gather table size */
 	u32 index;		/* device index number */
-	spinlock_t sfd_lock;	/* protect file descriptor list for device */
+	/* sfds is protected by sg_index_lock */
 	struct list_head sfds;
-	struct rw_semaphore o_sem;	/* exclude open should hold this rwsem */
 	volatile char detached;	/* 0->attached, 1->detached pending removal */
+	/* exclude protected by sg_open_exclusive_lock */
 	char exclude;		/* opened for exclusive access */
 	char sgdebug;		/* 0->off, 1->sense, 9->dump dev, 10-> all devs */
 	struct gendisk *disk;
@@ -220,14 +225,35 @@
 	return blk_verify_command(cmd, filp->f_mode & FMODE_WRITE);
 }
 
+static int get_exclude(Sg_device *sdp)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&sg_open_exclusive_lock, flags);
+	ret = sdp->exclude;
+	spin_unlock_irqrestore(&sg_open_exclusive_lock, flags);
+	return ret;
+}
+
+static int set_exclude(Sg_device *sdp, char val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&sg_open_exclusive_lock, flags);
+	sdp->exclude = val;
+	spin_unlock_irqrestore(&sg_open_exclusive_lock, flags);
+	return val;
+}
+
 static int sfds_list_empty(Sg_device *sdp)
 {
 	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(&sdp->sfd_lock, flags);
+	read_lock_irqsave(&sg_index_lock, flags);
 	ret = list_empty(&sdp->sfds);
-	spin_unlock_irqrestore(&sdp->sfd_lock, flags);
+	read_unlock_irqrestore(&sg_index_lock, flags);
 	return ret;
 }
 
@@ -239,6 +265,7 @@
 	struct request_queue *q;
 	Sg_device *sdp;
 	Sg_fd *sfp;
+	int res;
 	int retval;
 
 	nonseekable_open(inode, filp);
@@ -267,52 +294,54 @@
 		goto error_out;
 	}
 
-	if ((flags & O_EXCL) && (O_RDONLY == (flags & O_ACCMODE))) {
-		retval = -EPERM; /* Can't lock it with read only access */
+	if (flags & O_EXCL) {
+		if (O_RDONLY == (flags & O_ACCMODE)) {
+			retval = -EPERM; /* Can't lock it with read only access */
+			goto error_out;
+		}
+		if (!sfds_list_empty(sdp) && (flags & O_NONBLOCK)) {
+			retval = -EBUSY;
+			goto error_out;
+		}
+		res = wait_event_interruptible(sdp->o_excl_wait,
+					   ((!sfds_list_empty(sdp) || get_exclude(sdp)) ? 0 : set_exclude(sdp, 1)));
+		if (res) {
+			retval = res;	/* -ERESTARTSYS because signal hit process */
+			goto error_out;
+		}
+	} else if (get_exclude(sdp)) {	/* some other fd has an exclusive lock on dev */
+		if (flags & O_NONBLOCK) {
+			retval = -EBUSY;
+			goto error_out;
+		}
+		res = wait_event_interruptible(sdp->o_excl_wait, !get_exclude(sdp));
+		if (res) {
+			retval = res;	/* -ERESTARTSYS because signal hit process */
+			goto error_out;
+		}
+	}
+	if (sdp->detached) {
+		retval = -ENODEV;
 		goto error_out;
 	}
-	if (flags & O_NONBLOCK) {
-		if (flags & O_EXCL) {
-			if (!down_write_trylock(&sdp->o_sem)) {
-				retval = -EBUSY;
-				goto error_out;
-			}
-		} else {
-			if (!down_read_trylock(&sdp->o_sem)) {
-				retval = -EBUSY;
-				goto error_out;
-			}
-		}
-	} else {
-		if (flags & O_EXCL)
-			down_write(&sdp->o_sem);
-		else
-			down_read(&sdp->o_sem);
-	}
-	/* Since write lock is held, no need to check sfd_list */
-	if (flags & O_EXCL)
-		sdp->exclude = 1;	/* used by release lock */
-
 	if (sfds_list_empty(sdp)) {	/* no existing opens on this device */
 		sdp->sgdebug = 0;
 		q = sdp->device->request_queue;
 		sdp->sg_tablesize = queue_max_segments(q);
 	}
-	sfp = sg_add_sfp(sdp, dev);
-	if (!IS_ERR(sfp))
+	if ((sfp = sg_add_sfp(sdp, dev)))
 		filp->private_data = sfp;
-		/* retval is already provably zero at this point because of the
-		 * check after retval = scsi_autopm_get_device(sdp->device))
-		 */
 	else {
-		retval = PTR_ERR(sfp);
-
 		if (flags & O_EXCL) {
-			sdp->exclude = 0;	/* undo if error */
-			up_write(&sdp->o_sem);
-		} else
-			up_read(&sdp->o_sem);
+			set_exclude(sdp, 0);	/* undo if error */
+			wake_up_interruptible(&sdp->o_excl_wait);
+		}
+		retval = -ENOMEM;
+		goto error_out;
+	}
+	retval = 0;
 error_out:
+	if (retval) {
 		scsi_autopm_put_device(sdp->device);
 sdp_put:
 		scsi_device_put(sdp->device);
@@ -329,18 +358,13 @@
 {
 	Sg_device *sdp;
 	Sg_fd *sfp;
-	int excl;
 
 	if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
 		return -ENXIO;
 	SCSI_LOG_TIMEOUT(3, printk("sg_release: %s\n", sdp->disk->disk_name));
 
-	excl = sdp->exclude;
-	sdp->exclude = 0;
-	if (excl)
-		up_write(&sdp->o_sem);
-	else
-		up_read(&sdp->o_sem);
+	set_exclude(sdp, 0);
+	wake_up_interruptible(&sdp->o_excl_wait);
 
 	scsi_autopm_put_device(sdp->device);
 	kref_put(&sfp->f_ref, sg_remove_sfp);
@@ -1391,9 +1415,8 @@
 	disk->first_minor = k;
 	sdp->disk = disk;
 	sdp->device = scsidp;
-	spin_lock_init(&sdp->sfd_lock);
 	INIT_LIST_HEAD(&sdp->sfds);
-	init_rwsem(&sdp->o_sem);
+	init_waitqueue_head(&sdp->o_excl_wait);
 	sdp->sg_tablesize = queue_max_segments(q);
 	sdp->index = k;
 	kref_init(&sdp->d_ref);
@@ -1526,13 +1549,11 @@
 
 	/* Need a write lock to set sdp->detached. */
 	write_lock_irqsave(&sg_index_lock, iflags);
-	spin_lock(&sdp->sfd_lock);
 	sdp->detached = 1;
 	list_for_each_entry(sfp, &sdp->sfds, sfd_siblings) {
 		wake_up_interruptible(&sfp->read_wait);
 		kill_fasync(&sfp->async_qp, SIGPOLL, POLL_HUP);
 	}
-	spin_unlock(&sdp->sfd_lock);
 	write_unlock_irqrestore(&sg_index_lock, iflags);
 
 	sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic");
@@ -2043,7 +2064,7 @@
 
 	sfp = kzalloc(sizeof(*sfp), GFP_ATOMIC | __GFP_NOWARN);
 	if (!sfp)
-		return ERR_PTR(-ENOMEM);
+		return NULL;
 
 	init_waitqueue_head(&sfp->read_wait);
 	rwlock_init(&sfp->rq_list_lock);
@@ -2057,13 +2078,9 @@
 	sfp->cmd_q = SG_DEF_COMMAND_Q;
 	sfp->keep_orphan = SG_DEF_KEEP_ORPHAN;
 	sfp->parentdp = sdp;
-	spin_lock_irqsave(&sdp->sfd_lock, iflags);
-	if (sdp->detached) {
-		spin_unlock_irqrestore(&sdp->sfd_lock, iflags);
-		return ERR_PTR(-ENODEV);
-	}
+	write_lock_irqsave(&sg_index_lock, iflags);
 	list_add_tail(&sfp->sfd_siblings, &sdp->sfds);
-	spin_unlock_irqrestore(&sdp->sfd_lock, iflags);
+	write_unlock_irqrestore(&sg_index_lock, iflags);
 	SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p\n", sfp));
 	if (unlikely(sg_big_buff != def_reserved_size))
 		sg_big_buff = def_reserved_size;
@@ -2113,9 +2130,10 @@
 	struct sg_device *sdp = sfp->parentdp;
 	unsigned long iflags;
 
-	spin_lock_irqsave(&sdp->sfd_lock, iflags);
+	write_lock_irqsave(&sg_index_lock, iflags);
 	list_del(&sfp->sfd_siblings);
-	spin_unlock_irqrestore(&sdp->sfd_lock, iflags);
+	write_unlock_irqrestore(&sg_index_lock, iflags);
+	wake_up_interruptible(&sdp->o_excl_wait);
 
 	INIT_WORK(&sfp->ew.work, sg_remove_sfp_usercontext);
 	schedule_work(&sfp->ew.work);
@@ -2502,7 +2520,7 @@
 	return 0;
 }
 
-/* must be called while holding sg_index_lock and sfd_lock */
+/* must be called while holding sg_index_lock */
 static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
 {
 	int k, m, new_interface, blen, usg;
@@ -2587,26 +2605,22 @@
 
 	read_lock_irqsave(&sg_index_lock, iflags);
 	sdp = it ? sg_lookup_dev(it->index) : NULL;
-	if (sdp) {
-		spin_lock(&sdp->sfd_lock);
-		if (!list_empty(&sdp->sfds)) {
-			struct scsi_device *scsidp = sdp->device;
+	if (sdp && !list_empty(&sdp->sfds)) {
+		struct scsi_device *scsidp = sdp->device;
 
-			seq_printf(s, " >>> device=%s ", sdp->disk->disk_name);
-			if (sdp->detached)
-				seq_printf(s, "detached pending close ");
-			else
-				seq_printf
-				    (s, "scsi%d chan=%d id=%d lun=%d   em=%d",
-				     scsidp->host->host_no,
-				     scsidp->channel, scsidp->id,
-				     scsidp->lun,
-				     scsidp->host->hostt->emulated);
-			seq_printf(s, " sg_tablesize=%d excl=%d\n",
-				   sdp->sg_tablesize, sdp->exclude);
-			sg_proc_debug_helper(s, sdp);
-		}
-		spin_unlock(&sdp->sfd_lock);
+		seq_printf(s, " >>> device=%s ", sdp->disk->disk_name);
+		if (sdp->detached)
+			seq_printf(s, "detached pending close ");
+		else
+			seq_printf
+			    (s, "scsi%d chan=%d id=%d lun=%d   em=%d",
+			     scsidp->host->host_no,
+			     scsidp->channel, scsidp->id,
+			     scsidp->lun,
+			     scsidp->host->hostt->emulated);
+		seq_printf(s, " sg_tablesize=%d excl=%d\n",
+			   sdp->sg_tablesize, get_exclude(sdp));
+		sg_proc_debug_helper(s, sdp);
 	}
 	read_unlock_irqrestore(&sg_index_lock, iflags);
 	return 0;
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index b9c53cc..eb1f1ef 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -264,6 +264,7 @@
 config SPI_FSL_DSPI
 	tristate "Freescale DSPI controller"
 	select SPI_BITBANG
+	depends on SOC_VF610 || COMPILE_TEST
 	help
 	  This enables support for the Freescale DSPI controller in master
 	  mode. VF610 platform uses the controller.
@@ -369,7 +370,7 @@
 
 config SPI_RSPI
 	tristate "Renesas RSPI controller"
-	depends on SUPERH && SH_DMAE_BASE
+	depends on (SUPERH || ARCH_SHMOBILE) && SH_DMAE_BASE
 	help
 	  SPI driver for Renesas RSPI blocks.
 
@@ -393,7 +394,7 @@
 
 config SPI_S3C64XX
 	tristate "Samsung S3C64XX series type SPI"
-	depends on (ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5P64X0 || ARCH_EXYNOS)
+	depends on PLAT_SAMSUNG
 	select S3C64XX_DMA if ARCH_S3C64XX
 	help
 	  SPI driver for Samsung S3C64XX and newer SoCs.
diff --git a/drivers/spi/spi-altera.c b/drivers/spi/spi-altera.c
index 9a64c3f..595b62c 100644
--- a/drivers/spi/spi-altera.c
+++ b/drivers/spi/spi-altera.c
@@ -219,7 +219,7 @@
 	platform_set_drvdata(pdev, hw);
 
 	/* setup the state for the bitbang driver */
-	hw->bitbang.master = spi_master_get(master);
+	hw->bitbang.master = master;
 	if (!hw->bitbang.master)
 		return err;
 	hw->bitbang.chipselect = altera_spi_chipsel;
diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c
index 37bad95..821bf7a 100644
--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -231,7 +231,7 @@
 		master->num_chipselect = pdata->num_chipselect;
 	}
 
-	sp->bitbang.master = spi_master_get(master);
+	sp->bitbang.master = master;
 	sp->bitbang.chipselect = ath79_spi_chipselect;
 	sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0;
 	sp->bitbang.setup_transfer = spi_bitbang_setup_transfer;
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
index fd7cc56..273db0b 100644
--- a/drivers/spi/spi-atmel.c
+++ b/drivers/spi/spi-atmel.c
@@ -170,18 +170,18 @@
 /* Bit manipulation macros */
 #define SPI_BIT(name) \
 	(1 << SPI_##name##_OFFSET)
-#define SPI_BF(name,value) \
+#define SPI_BF(name, value) \
 	(((value) & ((1 << SPI_##name##_SIZE) - 1)) << SPI_##name##_OFFSET)
-#define SPI_BFEXT(name,value) \
+#define SPI_BFEXT(name, value) \
 	(((value) >> SPI_##name##_OFFSET) & ((1 << SPI_##name##_SIZE) - 1))
-#define SPI_BFINS(name,value,old) \
-	( ((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \
-	  | SPI_BF(name,value))
+#define SPI_BFINS(name, value, old) \
+	(((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \
+	  | SPI_BF(name, value))
 
 /* Register access macros */
-#define spi_readl(port,reg) \
+#define spi_readl(port, reg) \
 	__raw_readl((port)->regs + SPI_##reg)
-#define spi_writel(port,reg,value) \
+#define spi_writel(port, reg, value) \
 	__raw_writel((value), (port)->regs + SPI_##reg)
 
 /* use PIO for small transfers, avoiding DMA setup/teardown overhead and
@@ -1401,8 +1401,8 @@
 			asd = spi->controller_state;
 			bits = (asd->csr >> 4) & 0xf;
 			if (bits != xfer->bits_per_word - 8) {
-				dev_dbg(&spi->dev, "you can't yet change "
-					 "bits_per_word in transfers\n");
+				dev_dbg(&spi->dev,
+					"you can't yet change bits_per_word in transfers\n");
 				return -ENOPROTOOPT;
 			}
 		}
@@ -1516,7 +1516,7 @@
 
 	/* setup spi core then atmel-specific driver state */
 	ret = -ENOMEM;
-	master = spi_alloc_master(&pdev->dev, sizeof *as);
+	master = spi_alloc_master(&pdev->dev, sizeof(*as));
 	if (!master)
 		goto out_free;
 
@@ -1546,9 +1546,11 @@
 	INIT_LIST_HEAD(&as->queue);
 
 	as->pdev = pdev;
-	as->regs = ioremap(regs->start, resource_size(regs));
-	if (!as->regs)
+	as->regs = devm_ioremap_resource(&pdev->dev, regs);
+	if (IS_ERR(as->regs)) {
+		ret = PTR_ERR(as->regs);
 		goto out_free_buffer;
+	}
 	as->phybase = regs->start;
 	as->irq = irq;
 	as->clk = clk;
@@ -1583,7 +1585,7 @@
 	/* Initialize the hardware */
 	ret = clk_prepare_enable(clk);
 	if (ret)
-		goto out_unmap_regs;
+		goto out_free_irq;
 	spi_writel(as, CR, SPI_BIT(SWRST));
 	spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
 	if (as->caps.has_wdrbt) {
@@ -1614,9 +1616,9 @@
 	spi_writel(as, CR, SPI_BIT(SWRST));
 	spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
 	clk_disable_unprepare(clk);
+out_free_irq:
 	free_irq(irq, master);
 out_unmap_regs:
-	iounmap(as->regs);
 out_free_buffer:
 	if (!as->use_pdc)
 		tasklet_kill(&as->tasklet);
@@ -1668,36 +1670,36 @@
 	clk_disable_unprepare(as->clk);
 	clk_put(as->clk);
 	free_irq(as->irq, master);
-	iounmap(as->regs);
 
 	spi_unregister_master(master);
 
 	return 0;
 }
 
-#ifdef	CONFIG_PM
-
-static int atmel_spi_suspend(struct platform_device *pdev, pm_message_t mesg)
+#ifdef CONFIG_PM_SLEEP
+static int atmel_spi_suspend(struct device *dev)
 {
-	struct spi_master	*master = platform_get_drvdata(pdev);
+	struct spi_master	*master = dev_get_drvdata(dev);
 	struct atmel_spi	*as = spi_master_get_devdata(master);
 
 	clk_disable_unprepare(as->clk);
 	return 0;
 }
 
-static int atmel_spi_resume(struct platform_device *pdev)
+static int atmel_spi_resume(struct device *dev)
 {
-	struct spi_master	*master = platform_get_drvdata(pdev);
+	struct spi_master	*master = dev_get_drvdata(dev);
 	struct atmel_spi	*as = spi_master_get_devdata(master);
 
-	return clk_prepare_enable(as->clk);
+	clk_prepare_enable(as->clk);
 	return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(atmel_spi_pm_ops, atmel_spi_suspend, atmel_spi_resume);
+
+#define ATMEL_SPI_PM_OPS	(&atmel_spi_pm_ops)
 #else
-#define	atmel_spi_suspend	NULL
-#define	atmel_spi_resume	NULL
+#define ATMEL_SPI_PM_OPS	NULL
 #endif
 
 #if defined(CONFIG_OF)
@@ -1713,10 +1715,9 @@
 	.driver		= {
 		.name	= "atmel_spi",
 		.owner	= THIS_MODULE,
+		.pm	= ATMEL_SPI_PM_OPS,
 		.of_match_table	= of_match_ptr(atmel_spi_dt_ids),
 	},
-	.suspend	= atmel_spi_suspend,
-	.resume		= atmel_spi_resume,
 	.probe		= atmel_spi_probe,
 	.remove		= atmel_spi_remove,
 };
diff --git a/drivers/spi/spi-au1550.c b/drivers/spi/spi-au1550.c
index 1d00d9b3..c4141c9 100644
--- a/drivers/spi/spi-au1550.c
+++ b/drivers/spi/spi-au1550.c
@@ -775,7 +775,7 @@
 
 	hw = spi_master_get_devdata(master);
 
-	hw->master = spi_master_get(master);
+	hw->master = master;
 	hw->pdata = dev_get_platdata(&pdev->dev);
 	hw->dev = &pdev->dev;
 
@@ -985,6 +985,7 @@
 MODULE_ALIAS("platform:au1550-spi");
 
 static struct platform_driver au1550_spi_drv = {
+	.probe = au1550_spi_probe,
 	.remove = au1550_spi_remove,
 	.driver = {
 		.name = "au1550-spi",
@@ -1004,7 +1005,7 @@
 			printk(KERN_ERR "au1550-spi: cannot add memory"
 					"dbdma device\n");
 	}
-	return platform_driver_probe(&au1550_spi_drv, au1550_spi_probe);
+	return platform_driver_register(&au1550_spi_drv);
 }
 module_init(au1550_spi_init);
 
diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
index 52c8148..4c332143 100644
--- a/drivers/spi/spi-bcm2835.c
+++ b/drivers/spi/spi-bcm2835.c
@@ -358,7 +358,7 @@
 	bcm2835_wr(bs, BCM2835_SPI_CS,
 		   BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
 
-	err = spi_register_master(master);
+	err = devm_spi_register_master(&pdev->dev, master);
 	if (err) {
 		dev_err(&pdev->dev, "could not register SPI master: %d\n", err);
 		goto out_free_irq;
@@ -381,14 +381,12 @@
 	struct bcm2835_spi *bs = spi_master_get_devdata(master);
 
 	free_irq(bs->irq, master);
-	spi_unregister_master(master);
 
 	/* Clear FIFOs, and disable the HW block */
 	bcm2835_wr(bs, BCM2835_SPI_CS,
 		   BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
 
 	clk_disable_unprepare(bs->clk);
-	spi_master_put(master);
 
 	return 0;
 }
diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c
index 536b0e3..80d56b2 100644
--- a/drivers/spi/spi-bcm63xx.c
+++ b/drivers/spi/spi-bcm63xx.c
@@ -412,7 +412,7 @@
 	bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
 
 	/* register and we are done */
-	ret = spi_register_master(master);
+	ret = devm_spi_register_master(dev, master);
 	if (ret) {
 		dev_err(dev, "spi register failed\n");
 		goto out_clk_disable;
@@ -438,8 +438,6 @@
 	struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
 	struct bcm63xx_spi *bs = spi_master_get_devdata(master);
 
-	spi_unregister_master(master);
-
 	/* reset spi block */
 	bcm_spi_writeb(bs, 0, SPI_INT_MASK);
 
@@ -447,8 +445,6 @@
 	clk_disable_unprepare(bs->clk);
 	clk_put(bs->clk);
 
-	spi_master_put(master);
-
 	return 0;
 }
 
diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c
index 91921b5..38941e5 100644
--- a/drivers/spi/spi-bfin-sport.c
+++ b/drivers/spi/spi-bfin-sport.c
@@ -592,7 +592,7 @@
 			 */
 			if (chip_info->ctl_reg || chip_info->enable_dma) {
 				ret = -EINVAL;
-				dev_err(&spi->dev, "don't set ctl_reg/enable_dma fields");
+				dev_err(&spi->dev, "don't set ctl_reg/enable_dma fields\n");
 				goto error;
 			}
 			chip->cs_chg_udelay = chip_info->cs_chg_udelay;
@@ -879,11 +879,10 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int
-bfin_sport_spi_suspend(struct platform_device *pdev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int bfin_sport_spi_suspend(struct device *dev)
 {
-	struct bfin_sport_spi_master_data *drv_data = platform_get_drvdata(pdev);
+	struct bfin_sport_spi_master_data *drv_data = dev_get_drvdata(dev);
 	int status;
 
 	status = bfin_sport_spi_stop_queue(drv_data);
@@ -896,10 +895,9 @@
 	return status;
 }
 
-static int
-bfin_sport_spi_resume(struct platform_device *pdev)
+static int bfin_sport_spi_resume(struct device *dev)
 {
-	struct bfin_sport_spi_master_data *drv_data = platform_get_drvdata(pdev);
+	struct bfin_sport_spi_master_data *drv_data = dev_get_drvdata(dev);
 	int status;
 
 	/* Enable the SPI interface */
@@ -912,19 +910,22 @@
 
 	return status;
 }
+
+static SIMPLE_DEV_PM_OPS(bfin_sport_spi_pm_ops, bfin_sport_spi_suspend,
+			bfin_sport_spi_resume);
+
+#define BFIN_SPORT_SPI_PM_OPS		(&bfin_sport_spi_pm_ops)
 #else
-# define bfin_sport_spi_suspend NULL
-# define bfin_sport_spi_resume  NULL
+#define BFIN_SPORT_SPI_PM_OPS		NULL
 #endif
 
 static struct platform_driver bfin_sport_spi_driver = {
 	.driver	= {
-		.name = DRV_NAME,
-		.owner = THIS_MODULE,
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+		.pm	= BFIN_SPORT_SPI_PM_OPS,
 	},
 	.probe   = bfin_sport_spi_probe,
 	.remove  = bfin_sport_spi_remove,
-	.suspend = bfin_sport_spi_suspend,
-	.resume  = bfin_sport_spi_resume,
 };
 module_platform_driver(bfin_sport_spi_driver);
diff --git a/drivers/spi/spi-bfin-v3.c b/drivers/spi/spi-bfin-v3.c
index f4bf813..8f85988 100644
--- a/drivers/spi/spi-bfin-v3.c
+++ b/drivers/spi/spi-bfin-v3.c
@@ -867,7 +867,7 @@
 	tasklet_init(&drv_data->pump_transfers,
 			bfin_spi_pump_transfers, (unsigned long)drv_data);
 	/* register with the SPI framework */
-	ret = spi_register_master(master);
+	ret = devm_spi_register_master(dev, master);
 	if (ret) {
 		dev_err(dev, "can not  register spi master\n");
 		goto err_free_peripheral;
@@ -898,7 +898,6 @@
 	free_dma(drv_data->rx_dma);
 	free_dma(drv_data->tx_dma);
 
-	spi_unregister_master(drv_data->master);
 	return 0;
 }
 
diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c
index 45bdf73..f0f195a 100644
--- a/drivers/spi/spi-bfin5xx.c
+++ b/drivers/spi/spi-bfin5xx.c
@@ -524,7 +524,7 @@
 	timeout = jiffies + HZ;
 	while (!(bfin_read(&drv_data->regs->stat) & BIT_STAT_SPIF))
 		if (!time_before(jiffies, timeout)) {
-			dev_warn(&drv_data->pdev->dev, "timeout waiting for SPIF");
+			dev_warn(&drv_data->pdev->dev, "timeout waiting for SPIF\n");
 			break;
 		} else
 			cpu_relax();
@@ -913,8 +913,9 @@
 	drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next,
 					    struct spi_transfer, transfer_list);
 
-	dev_dbg(&drv_data->pdev->dev, "got a message to pump, "
-		"state is set to: baud %d, flag 0x%x, ctl 0x%x\n",
+	dev_dbg(&drv_data->pdev->dev,
+		"got a message to pump, state is set to: baud "
+		"%d, flag 0x%x, ctl 0x%x\n",
 		drv_data->cur_chip->baud, drv_data->cur_chip->flag,
 		drv_data->cur_chip->ctl_reg);
 
@@ -1013,8 +1014,8 @@
 		 * but let's assume (for now) they do.
 		 */
 		if (chip_info->ctl_reg & ~bfin_ctl_reg) {
-			dev_err(&spi->dev, "do not set bits in ctl_reg "
-				"that the SPI framework manages\n");
+			dev_err(&spi->dev,
+				"do not set bits in ctl_reg that the SPI framework manages\n");
 			goto error;
 		}
 		chip->enable_dma = chip_info->enable_dma != 0
@@ -1050,17 +1051,17 @@
 	chip->chip_select_num = spi->chip_select;
 	if (chip->chip_select_num < MAX_CTRL_CS) {
 		if (!(spi->mode & SPI_CPHA))
-			dev_warn(&spi->dev, "Warning: SPI CPHA not set:"
-				" Slave Select not under software control!\n"
-				" See Documentation/blackfin/bfin-spi-notes.txt");
+			dev_warn(&spi->dev,
+				"Warning: SPI CPHA not set: Slave Select not under software control!\n"
+				"See Documentation/blackfin/bfin-spi-notes.txt\n");
 
 		chip->flag = (1 << spi->chip_select) << 8;
 	} else
 		chip->cs_gpio = chip->chip_select_num - MAX_CTRL_CS;
 
 	if (chip->enable_dma && chip->pio_interrupt) {
-		dev_err(&spi->dev, "enable_dma is set, "
-				"do not set pio_interrupt\n");
+		dev_err(&spi->dev,
+			"enable_dma is set, do not set pio_interrupt\n");
 		goto error;
 	}
 	/*
@@ -1410,10 +1411,10 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int bfin_spi_suspend(struct platform_device *pdev, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int bfin_spi_suspend(struct device *dev)
 {
-	struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
+	struct bfin_spi_master_data *drv_data = dev_get_drvdata(dev);
 	int status = 0;
 
 	status = bfin_spi_stop_queue(drv_data);
@@ -1432,9 +1433,9 @@
 	return 0;
 }
 
-static int bfin_spi_resume(struct platform_device *pdev)
+static int bfin_spi_resume(struct device *dev)
 {
-	struct bfin_spi_master_data *drv_data = platform_get_drvdata(pdev);
+	struct bfin_spi_master_data *drv_data = dev_get_drvdata(dev);
 	int status = 0;
 
 	bfin_write(&drv_data->regs->ctl, drv_data->ctrl_reg);
@@ -1443,31 +1444,34 @@
 	/* Start the queue running */
 	status = bfin_spi_start_queue(drv_data);
 	if (status != 0) {
-		dev_err(&pdev->dev, "problem starting queue (%d)\n", status);
+		dev_err(dev, "problem starting queue (%d)\n", status);
 		return status;
 	}
 
 	return 0;
 }
+
+static SIMPLE_DEV_PM_OPS(bfin_spi_pm_ops, bfin_spi_suspend, bfin_spi_resume);
+
+#define BFIN_SPI_PM_OPS		(&bfin_spi_pm_ops)
 #else
-#define bfin_spi_suspend NULL
-#define bfin_spi_resume NULL
-#endif				/* CONFIG_PM */
+#define BFIN_SPI_PM_OPS		NULL
+#endif
 
 MODULE_ALIAS("platform:bfin-spi");
 static struct platform_driver bfin_spi_driver = {
 	.driver	= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
+		.pm	= BFIN_SPI_PM_OPS,
 	},
-	.suspend	= bfin_spi_suspend,
-	.resume		= bfin_spi_resume,
+	.probe		= bfin_spi_probe,
 	.remove		= bfin_spi_remove,
 };
 
 static int __init bfin_spi_init(void)
 {
-	return platform_driver_probe(&bfin_spi_driver, bfin_spi_probe);
+	return platform_driver_register(&bfin_spi_driver);
 }
 subsys_initcall(bfin_spi_init);
 
diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c
index 8c11355..bd222f6 100644
--- a/drivers/spi/spi-bitbang.c
+++ b/drivers/spi/spi-bitbang.c
@@ -191,7 +191,7 @@
 	bitbang = spi_master_get_devdata(spi->master);
 
 	if (!cs) {
-		cs = kzalloc(sizeof *cs, GFP_KERNEL);
+		cs = kzalloc(sizeof(*cs), GFP_KERNEL);
 		if (!cs)
 			return -ENOMEM;
 		spi->controller_state = cs;
@@ -258,7 +258,7 @@
 
 static int spi_bitbang_prepare_hardware(struct spi_master *spi)
 {
-	struct spi_bitbang 	*bitbang;
+	struct spi_bitbang	*bitbang;
 	unsigned long		flags;
 
 	bitbang = spi_master_get_devdata(spi);
@@ -273,7 +273,7 @@
 static int spi_bitbang_transfer_one(struct spi_master *master,
 				    struct spi_message *m)
 {
-	struct spi_bitbang 	*bitbang;
+	struct spi_bitbang	*bitbang;
 	unsigned		nsecs;
 	struct spi_transfer	*t = NULL;
 	unsigned		cs_change;
@@ -292,7 +292,7 @@
 	cs_change = 1;
 	status = 0;
 
-	list_for_each_entry (t, &m->transfers, transfer_list) {
+	list_for_each_entry(t, &m->transfers, transfer_list) {
 
 		/* override speed or wordsize? */
 		if (t->speed_hz || t->bits_per_word)
@@ -349,7 +349,8 @@
 		if (t->delay_usecs)
 			udelay(t->delay_usecs);
 
-		if (cs_change && !list_is_last(&t->transfer_list, &m->transfers)) {
+		if (cs_change &&
+		    !list_is_last(&t->transfer_list, &m->transfers)) {
 			/* sometimes a short mid-message deselect of the chip
 			 * may be needed to terminate a mode or command
 			 */
@@ -378,7 +379,7 @@
 
 static int spi_bitbang_unprepare_hardware(struct spi_master *spi)
 {
-	struct spi_bitbang 	*bitbang;
+	struct spi_bitbang	*bitbang;
 	unsigned long		flags;
 
 	bitbang = spi_master_get_devdata(spi);
@@ -414,10 +415,16 @@
  * This routine registers the spi_master, which will process requests in a
  * dedicated task, keeping IRQs unblocked most of the time.  To stop
  * processing those requests, call spi_bitbang_stop().
+ *
+ * On success, this routine will take a reference to master. The caller is
+ * responsible for calling spi_bitbang_stop() to decrement the reference and
+ * spi_master_put() as counterpart of spi_alloc_master() to prevent a memory
+ * leak.
  */
 int spi_bitbang_start(struct spi_bitbang *bitbang)
 {
 	struct spi_master *master = bitbang->master;
+	int ret;
 
 	if (!master || !bitbang->chipselect)
 		return -EINVAL;
@@ -449,7 +456,11 @@
 	/* driver may get busy before register() returns, especially
 	 * if someone registered boardinfo for devices
 	 */
-	return spi_register_master(master);
+	ret = spi_register_master(spi_master_get(master));
+	if (ret)
+		spi_master_put(master);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(spi_bitbang_start);
 
diff --git a/drivers/spi/spi-butterfly.c b/drivers/spi/spi-butterfly.c
index 5ed08e5..8081f96 100644
--- a/drivers/spi/spi-butterfly.c
+++ b/drivers/spi/spi-butterfly.c
@@ -147,8 +147,8 @@
 
 /* we only needed to implement one mode here, and choose SPI_MODE_0 */
 
-#define	spidelay(X)	do{}while(0)
-//#define	spidelay	ndelay
+#define spidelay(X)	do { } while (0)
+/* #define spidelay	ndelay */
 
 #include "spi-bitbang-txrx.h"
 
@@ -171,15 +171,15 @@
 	/* sector 0 = 8 pages * 264 bytes/page (1 block)
 	 * sector 1 = 248 pages * 264 bytes/page
 	 */
-	.name		= "bookkeeping",	// 66 KB
+	.name		= "bookkeeping",	/* 66 KB */
 	.offset		= 0,
 	.size		= (8 + 248) * 264,
-//	.mask_flags	= MTD_WRITEABLE,
+	/* .mask_flags	= MTD_WRITEABLE, */
 }, {
 	/* sector 2 = 256 pages * 264 bytes/page
 	 * sectors 3-5 = 512 pages * 264 bytes/page
 	 */
-	.name		= "filesystem",		// 462 KB
+	.name		= "filesystem",		/* 462 KB */
 	.offset		= MTDPART_OFS_APPEND,
 	.size		= MTDPART_SIZ_FULL,
 } };
@@ -209,7 +209,7 @@
 	 * and no way to be selective about what it binds to.
 	 */
 
-	master = spi_alloc_master(dev, sizeof *pp);
+	master = spi_alloc_master(dev, sizeof(*pp));
 	if (!master) {
 		status = -ENOMEM;
 		goto done;
@@ -225,7 +225,7 @@
 	master->bus_num = 42;
 	master->num_chipselect = 2;
 
-	pp->bitbang.master = spi_master_get(master);
+	pp->bitbang.master = master;
 	pp->bitbang.chipselect = butterfly_chipselect;
 	pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0;
 
@@ -289,7 +289,6 @@
 		pr_debug("%s: dataflash at %s\n", p->name,
 				dev_name(&pp->dataflash->dev));
 
-	// dev_info(_what?_, ...)
 	pr_info("%s: AVR Butterfly\n", p->name);
 	butterfly = pp;
 	return;
diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c
index 5655acf..e2a5a42 100644
--- a/drivers/spi/spi-clps711x.c
+++ b/drivers/spi/spi-clps711x.c
@@ -226,11 +226,10 @@
 			       dev_name(&pdev->dev), hw);
 	if (ret) {
 		dev_err(&pdev->dev, "Can't request IRQ\n");
-		clk_put(hw->spi_clk);
-		goto clk_out;
+		goto err_out;
 	}
 
-	ret = spi_register_master(master);
+	ret = devm_spi_register_master(&pdev->dev, master);
 	if (!ret) {
 		dev_info(&pdev->dev,
 			 "SPI bus driver initialized. Master clock %u Hz\n",
@@ -240,14 +239,12 @@
 
 	dev_err(&pdev->dev, "Failed to register master\n");
 
-clk_out:
 err_out:
 	while (--i >= 0)
 		if (gpio_is_valid(hw->chipselect[i]))
 			gpio_free(hw->chipselect[i]);
 
 	spi_master_put(master);
-	kfree(master);
 
 	return ret;
 }
@@ -262,9 +259,6 @@
 		if (gpio_is_valid(hw->chipselect[i]))
 			gpio_free(hw->chipselect[i]);
 
-	spi_unregister_master(master);
-	kfree(master);
-
 	return 0;
 }
 
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index 8fbfe24..dd72445 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -279,7 +279,8 @@
 	struct davinci_spi *dspi;
 	struct davinci_spi_config *spicfg;
 	u8 bits_per_word = 0;
-	u32 hz = 0, spifmt = 0, prescale = 0;
+	u32 hz = 0, spifmt = 0;
+	int prescale;
 
 	dspi = spi_master_get_devdata(spi->master);
 	spicfg = (struct davinci_spi_config *)spi->controller_data;
@@ -916,7 +917,7 @@
 	if (ret)
 		goto unmap_io;
 
-	dspi->bitbang.master = spi_master_get(master);
+	dspi->bitbang.master = master;
 	if (dspi->bitbang.master == NULL) {
 		ret = -ENODEV;
 		goto irq_free;
@@ -925,7 +926,7 @@
 	dspi->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(dspi->clk)) {
 		ret = -ENODEV;
-		goto put_master;
+		goto irq_free;
 	}
 	clk_prepare_enable(dspi->clk);
 
@@ -1015,8 +1016,6 @@
 free_clk:
 	clk_disable_unprepare(dspi->clk);
 	clk_put(dspi->clk);
-put_master:
-	spi_master_put(master);
 irq_free:
 	free_irq(dspi->irq, dspi);
 unmap_io:
@@ -1024,7 +1023,7 @@
 release_region:
 	release_mem_region(dspi->pbase, resource_size(r));
 free_master:
-	kfree(master);
+	spi_master_put(master);
 err:
 	return ret;
 }
@@ -1051,11 +1050,11 @@
 
 	clk_disable_unprepare(dspi->clk);
 	clk_put(dspi->clk);
-	spi_master_put(master);
 	free_irq(dspi->irq, dspi);
 	iounmap(dspi->base);
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	release_mem_region(dspi->pbase, resource_size(r));
+	spi_master_put(master);
 
 	return 0;
 }
diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index 4aa8be8..168c620 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -74,7 +74,7 @@
 	dwsmmio->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(dwsmmio->clk)) {
 		ret = PTR_ERR(dwsmmio->clk);
-		goto err_irq;
+		goto err_unmap;
 	}
 	clk_enable(dwsmmio->clk);
 
@@ -94,8 +94,6 @@
 	clk_disable(dwsmmio->clk);
 	clk_put(dwsmmio->clk);
 	dwsmmio->clk = NULL;
-err_irq:
-	free_irq(dws->irq, dws);
 err_unmap:
 	iounmap(dws->regs);
 err_release_reg:
@@ -115,7 +113,6 @@
 	clk_put(dwsmmio->clk);
 	dwsmmio->clk = NULL;
 
-	free_irq(dwsmmio->dws.irq, &dwsmmio->dws);
 	dw_spi_remove_host(&dwsmmio->dws);
 	iounmap(dwsmmio->dws.regs);
 	kfree(dwsmmio);
diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c
index 6055c8d..66fa995 100644
--- a/drivers/spi/spi-dw-pci.c
+++ b/drivers/spi/spi-dw-pci.c
@@ -40,7 +40,7 @@
 	int pci_bar = 0;
 	int ret;
 
-	printk(KERN_INFO "DW: found PCI SPI controller(ID: %04x:%04x)\n",
+	dev_info(&pdev->dev, "found PCI SPI controller(ID: %04x:%04x)\n",
 		pdev->vendor, pdev->device);
 
 	ret = pci_enable_device(pdev);
@@ -109,7 +109,6 @@
 {
 	struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
 
-	pci_set_drvdata(pdev, NULL);
 	dw_spi_remove_host(&dwpci->dws);
 	iounmap(dwpci->dws.regs);
 	pci_release_region(pdev, 0);
diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
index 79c958e..b897c4ad 100644
--- a/drivers/spi/spi-dw.c
+++ b/drivers/spi/spi-dw.c
@@ -870,8 +870,8 @@
 	/* Remove the queue */
 	status = destroy_queue(dws);
 	if (status != 0)
-		dev_err(&dws->master->dev, "dw_spi_remove: workqueue will not "
-			"complete, message memory not freed\n");
+		dev_err(&dws->master->dev,
+			"dw_spi_remove: workqueue will not complete, message memory not freed\n");
 
 	if (dws->dma_ops && dws->dma_ops->dma_exit)
 		dws->dma_ops->dma_exit(dws);
diff --git a/drivers/spi/spi-efm32.c b/drivers/spi/spi-efm32.c
index 7d84418..d4d3cc5 100644
--- a/drivers/spi/spi-efm32.c
+++ b/drivers/spi/spi-efm32.c
@@ -280,10 +280,6 @@
 	return IRQ_HANDLED;
 }
 
-static const struct efm32_spi_pdata efm32_spi_pdata_default = {
-	.location = 1,
-};
-
 static u32 efm32_spi_get_configured_location(struct efm32_spi_ddata *ddata)
 {
 	u32 reg = efm32_spi_read32(ddata, REG_ROUTE);
@@ -347,7 +343,7 @@
 
 	ddata = spi_master_get_devdata(master);
 
-	ddata->bitbang.master = spi_master_get(master);
+	ddata->bitbang.master = master;
 	ddata->bitbang.chipselect = efm32_spi_chipselect;
 	ddata->bitbang.setup_transfer = efm32_spi_setup_transfer;
 	ddata->bitbang.txrx_bufs = efm32_spi_txrx_bufs;
@@ -387,7 +383,7 @@
 		goto err;
 	}
 
-	if (resource_size(res) < 60) {
+	if (resource_size(res) < 0x60) {
 		ret = -EINVAL;
 		dev_err(&pdev->dev, "memory resource too small\n");
 		goto err;
@@ -467,7 +463,6 @@
 		clk_disable_unprepare(ddata->clk);
 err:
 		spi_master_put(master);
-		kfree(master);
 	}
 
 	return ret;
@@ -478,13 +473,14 @@
 	struct spi_master *master = platform_get_drvdata(pdev);
 	struct efm32_spi_ddata *ddata = spi_master_get_devdata(master);
 
+	spi_bitbang_stop(&ddata->bitbang);
+
 	efm32_spi_write32(ddata, 0, REG_IEN);
 
 	free_irq(ddata->txirq, ddata);
 	free_irq(ddata->rxirq, ddata);
 	clk_disable_unprepare(ddata->clk);
 	spi_master_put(master);
-	kfree(master);
 
 	return 0;
 }
diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c
index d22c00a..1bfaed6 100644
--- a/drivers/spi/spi-ep93xx.c
+++ b/drivers/spi/spi-ep93xx.c
@@ -330,7 +330,7 @@
 
 	dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n",
 		chip->spi->mode, div_cpsr, div_scr, dss);
-	dev_dbg(&espi->pdev->dev, "setup: cr0 %#x", cr0);
+	dev_dbg(&espi->pdev->dev, "setup: cr0 %#x\n", cr0);
 
 	ep93xx_spi_write_u8(espi, SSPCPSR, div_cpsr);
 	ep93xx_spi_write_u16(espi, SSPCR0, cr0);
@@ -509,7 +509,7 @@
 	}
 
 	if (WARN_ON(len)) {
-		dev_warn(&espi->pdev->dev, "len = %zu expected 0!", len);
+		dev_warn(&espi->pdev->dev, "len = %zu expected 0!\n", len);
 		return ERR_PTR(-EINVAL);
 	}
 
@@ -942,7 +942,7 @@
 	/* make sure that the hardware is disabled */
 	ep93xx_spi_write_u8(espi, SSPCR1, 0);
 
-	error = spi_register_master(master);
+	error = devm_spi_register_master(&pdev->dev, master);
 	if (error) {
 		dev_err(&pdev->dev, "failed to register SPI master\n");
 		goto fail_free_dma;
@@ -968,7 +968,6 @@
 
 	ep93xx_spi_release_dma(espi);
 
-	spi_unregister_master(master);
 	return 0;
 }
 
diff --git a/drivers/spi/spi-fsl-cpm.c b/drivers/spi/spi-fsl-cpm.c
index 07971e3..54b0637 100644
--- a/drivers/spi/spi-fsl-cpm.c
+++ b/drivers/spi/spi-fsl-cpm.c
@@ -20,6 +20,7 @@
 #include <linux/spi/spi.h>
 #include <linux/fsl_devices.h>
 #include <linux/dma-mapping.h>
+#include <linux/of_address.h>
 #include <asm/cpm.h>
 #include <asm/qe.h>
 
@@ -299,7 +300,7 @@
 
 		switch (mspi->subblock) {
 		default:
-			dev_warn(dev, "cell-index unspecified, assuming SPI1");
+			dev_warn(dev, "cell-index unspecified, assuming SPI1\n");
 			/* fall through */
 		case 0:
 			mspi->subblock = QE_CR_SUBBLOCK_SPI1;
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 6cd07d1..8641b03 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -108,7 +108,7 @@
 	struct spi_bitbang	bitbang;
 	struct platform_device	*pdev;
 
-	void			*base;
+	void __iomem		*base;
 	int			irq;
 	struct clk 		*clk;
 
@@ -165,7 +165,7 @@
 			}
 		}
 
-	pr_warn("Can not find valid buad rate,speed_hz is %d,clkrate is %ld\
+	pr_warn("Can not find valid baud rate,speed_hz is %d,clkrate is %ld\
 		,we use the max prescaler value.\n", speed_hz, clkrate);
 	*pbr = ARRAY_SIZE(pbr_tbl) - 1;
 	*br =  ARRAY_SIZE(brs) - 1;
@@ -450,7 +450,7 @@
 
 	dspi = spi_master_get_devdata(master);
 	dspi->pdev = pdev;
-	dspi->bitbang.master = spi_master_get(master);
+	dspi->bitbang.master = master;
 	dspi->bitbang.chipselect = dspi_chipselect;
 	dspi->bitbang.setup_transfer = dspi_setup_transfer;
 	dspi->bitbang.txrx_bufs = dspi_txrx_transfer;
@@ -476,15 +476,9 @@
 	master->bus_num = bus_num;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "can't get platform resource\n");
-		ret = -EINVAL;
-		goto out_master_put;
-	}
-
 	dspi->base = devm_ioremap_resource(&pdev->dev, res);
-	if (!dspi->base) {
-		ret = -EINVAL;
+	if (IS_ERR(dspi->base)) {
+		ret = PTR_ERR(dspi->base);
 		goto out_master_put;
 	}
 
@@ -526,7 +520,6 @@
 	clk_disable_unprepare(dspi->clk);
 out_master_put:
 	spi_master_put(master);
-	platform_set_drvdata(pdev, NULL);
 
 	return ret;
 }
@@ -537,6 +530,7 @@
 
 	/* Disconnect from the SPI framework */
 	spi_bitbang_stop(&dspi->bitbang);
+	clk_disable_unprepare(dspi->clk);
 	spi_master_put(dspi->bitbang.master);
 
 	return 0;
@@ -553,5 +547,5 @@
 module_platform_driver(fsl_dspi_driver);
 
 MODULE_DESCRIPTION("Freescale DSPI Controller Driver");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c
index b8f1103..32200d4 100644
--- a/drivers/spi/spi-fsl-espi.c
+++ b/drivers/spi/spi-fsl-espi.c
@@ -16,6 +16,8 @@
 #include <linux/fsl_devices.h>
 #include <linux/mm.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/interrupt.h>
 #include <linux/err.h>
@@ -289,8 +291,8 @@
 		if ((first->bits_per_word != t->bits_per_word) ||
 			(first->speed_hz != t->speed_hz)) {
 			espi_trans->status = -EINVAL;
-			dev_err(mspi->dev, "bits_per_word/speed_hz should be"
-					" same for the same SPI transfer\n");
+			dev_err(mspi->dev,
+				"bits_per_word/speed_hz should be same for the same SPI transfer\n");
 			return;
 		}
 
@@ -687,7 +689,7 @@
 	struct device_node *np = ofdev->dev.of_node;
 	struct spi_master *master;
 	struct resource mem;
-	struct resource irq;
+	unsigned int irq;
 	int ret = -ENOMEM;
 
 	ret = of_mpc8xxx_spi_probe(ofdev);
@@ -702,13 +704,13 @@
 	if (ret)
 		goto err;
 
-	ret = of_irq_to_resource(np, 0, &irq);
+	irq = irq_of_parse_and_map(np, 0);
 	if (!ret) {
 		ret = -EINVAL;
 		goto err;
 	}
 
-	master = fsl_espi_probe(dev, &mem, irq.start);
+	master = fsl_espi_probe(dev, &mem, irq);
 	if (IS_ERR(master)) {
 		ret = PTR_ERR(master);
 		goto err;
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
index 68b69fe..3fb09f9 100644
--- a/drivers/spi/spi-gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
 
@@ -467,7 +468,7 @@
 	}
 #endif
 
-	spi_gpio->bitbang.master = spi_master_get(master);
+	spi_gpio->bitbang.master = master;
 	spi_gpio->bitbang.chipselect = spi_gpio_chipselect;
 
 	if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) {
@@ -486,7 +487,6 @@
 
 	status = spi_bitbang_start(&spi_gpio->bitbang);
 	if (status < 0) {
-		spi_master_put(spi_gpio->bitbang.master);
 gpio_free:
 		if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
 			gpio_free(SPI_MISO_GPIO);
@@ -510,13 +510,13 @@
 
 	/* stop() unregisters child devices too */
 	status = spi_bitbang_stop(&spi_gpio->bitbang);
-	spi_master_put(spi_gpio->bitbang.master);
 
 	if (SPI_MISO_GPIO != SPI_GPIO_NO_MISO)
 		gpio_free(SPI_MISO_GPIO);
 	if (SPI_MOSI_GPIO != SPI_GPIO_NO_MOSI)
 		gpio_free(SPI_MOSI_GPIO);
 	gpio_free(SPI_SCK_GPIO);
+	spi_master_put(spi_gpio->bitbang.master);
 
 	return status;
 }
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 15323d8..b80f2f7 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -749,6 +749,35 @@
 {
 }
 
+static int
+spi_imx_prepare_message(struct spi_master *master, struct spi_message *msg)
+{
+	struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+	int ret;
+
+	ret = clk_enable(spi_imx->clk_per);
+	if (ret)
+		return ret;
+
+	ret = clk_enable(spi_imx->clk_ipg);
+	if (ret) {
+		clk_disable(spi_imx->clk_per);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+spi_imx_unprepare_message(struct spi_master *master, struct spi_message *msg)
+{
+	struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+
+	clk_disable(spi_imx->clk_ipg);
+	clk_disable(spi_imx->clk_per);
+	return 0;
+}
+
 static int spi_imx_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -786,7 +815,7 @@
 	master->num_chipselect = num_cs;
 
 	spi_imx = spi_master_get_devdata(master);
-	spi_imx->bitbang.master = spi_master_get(master);
+	spi_imx->bitbang.master = master;
 
 	for (i = 0; i < master->num_chipselect; i++) {
 		int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
@@ -810,6 +839,8 @@
 	spi_imx->bitbang.txrx_bufs = spi_imx_transfer;
 	spi_imx->bitbang.master->setup = spi_imx_setup;
 	spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
+	spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message;
+	spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
 	spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 
 	init_completion(&spi_imx->xfer_done);
@@ -872,6 +903,8 @@
 
 	dev_info(&pdev->dev, "probed\n");
 
+	clk_disable(spi_imx->clk_ipg);
+	clk_disable(spi_imx->clk_per);
 	return ret;
 
 out_clk_put:
diff --git a/drivers/spi/spi-lm70llp.c b/drivers/spi/spi-lm70llp.c
index 0759b5d..41c5765 100644
--- a/drivers/spi/spi-lm70llp.c
+++ b/drivers/spi/spi-lm70llp.c
@@ -222,7 +222,7 @@
 	/*
 	 * SPI and bitbang hookup.
 	 */
-	pp->bitbang.master = spi_master_get(master);
+	pp->bitbang.master = master;
 	pp->bitbang.chipselect = lm70_chipselect;
 	pp->bitbang.txrx_word[SPI_MODE_0] = lm70_txrx;
 	pp->bitbang.flags = SPI_3WIRE;
diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c
index dbc5e99..58d5ee0 100644
--- a/drivers/spi/spi-mpc512x-psc.c
+++ b/drivers/spi/spi-mpc512x-psc.c
@@ -20,6 +20,7 @@
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/completion.h>
 #include <linux/io.h>
@@ -522,8 +523,10 @@
 	psc_num = master->bus_num;
 	snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
 	clk = devm_clk_get(dev, clk_name);
-	if (IS_ERR(clk))
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
 		goto free_irq;
+	}
 	ret = clk_prepare_enable(clk);
 	if (ret)
 		goto free_irq;
@@ -534,7 +537,7 @@
 	if (ret < 0)
 		goto free_clock;
 
-	ret = spi_register_master(master);
+	ret = devm_spi_register_master(dev, master);
 	if (ret < 0)
 		goto free_clock;
 
@@ -557,12 +560,10 @@
 	struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
 	struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
 
-	spi_unregister_master(master);
 	clk_disable_unprepare(mps->clk_mclk);
 	free_irq(mps->irq, mps);
 	if (mps->psc)
 		iounmap(mps->psc);
-	spi_master_put(master);
 
 	return 0;
 }
diff --git a/drivers/spi/spi-mpc52xx-psc.c b/drivers/spi/spi-mpc52xx-psc.c
index 6e925dc..00ba910 100644
--- a/drivers/spi/spi-mpc52xx-psc.c
+++ b/drivers/spi/spi-mpc52xx-psc.c
@@ -383,8 +383,8 @@
 
 	mps->irq = irq;
 	if (pdata == NULL) {
-		dev_warn(dev, "probe called without platform data, no "
-				"cs_control function will be called\n");
+		dev_warn(dev,
+			 "probe called without platform data, no cs_control function will be called\n");
 		mps->cs_control = NULL;
 		mps->sysclk = 0;
 		master->bus_num = bus_num;
diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c
index de7b114..de33305 100644
--- a/drivers/spi/spi-mxs.c
+++ b/drivers/spi/spi-mxs.c
@@ -57,34 +57,53 @@
 
 #define SG_MAXLEN		0xff00
 
+/*
+ * Flags for txrx functions.  More efficient that using an argument register for
+ * each one.
+ */
+#define TXRX_WRITE		(1<<0)	/* This is a write */
+#define TXRX_DEASSERT_CS	(1<<1)	/* De-assert CS at end of txrx */
+
 struct mxs_spi {
 	struct mxs_ssp		ssp;
 	struct completion	c;
+	unsigned int		sck;	/* Rate requested (vs actual) */
 };
 
 static int mxs_spi_setup_transfer(struct spi_device *dev,
-				struct spi_transfer *t)
+				  const struct spi_transfer *t)
 {
 	struct mxs_spi *spi = spi_master_get_devdata(dev->master);
 	struct mxs_ssp *ssp = &spi->ssp;
-	uint32_t hz = 0;
+	const unsigned int hz = min(dev->max_speed_hz, t->speed_hz);
 
-	hz = dev->max_speed_hz;
-	if (t && t->speed_hz)
-		hz = min(hz, t->speed_hz);
 	if (hz == 0) {
-		dev_err(&dev->dev, "Cannot continue with zero clock\n");
+		dev_err(&dev->dev, "SPI clock rate of zero not allowed\n");
 		return -EINVAL;
 	}
 
-	mxs_ssp_set_clk_rate(ssp, hz);
+	if (hz != spi->sck) {
+		mxs_ssp_set_clk_rate(ssp, hz);
+		/*
+		 * Save requested rate, hz, rather than the actual rate,
+		 * ssp->clk_rate.  Otherwise we would set the rate every trasfer
+		 * when the actual rate is not quite the same as requested rate.
+		 */
+		spi->sck = hz;
+		/*
+		 * Perhaps we should return an error if the actual clock is
+		 * nowhere close to what was requested?
+		 */
+	}
+
+	writel(BM_SSP_CTRL0_LOCK_CS,
+		ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
 
 	writel(BF_SSP_CTRL1_SSP_MODE(BV_SSP_CTRL1_SSP_MODE__SPI) |
-		     BF_SSP_CTRL1_WORD_LENGTH
-		     (BV_SSP_CTRL1_WORD_LENGTH__EIGHT_BITS) |
-		     ((dev->mode & SPI_CPOL) ? BM_SSP_CTRL1_POLARITY : 0) |
-		     ((dev->mode & SPI_CPHA) ? BM_SSP_CTRL1_PHASE : 0),
-		     ssp->base + HW_SSP_CTRL1(ssp));
+	       BF_SSP_CTRL1_WORD_LENGTH(BV_SSP_CTRL1_WORD_LENGTH__EIGHT_BITS) |
+	       ((dev->mode & SPI_CPOL) ? BM_SSP_CTRL1_POLARITY : 0) |
+	       ((dev->mode & SPI_CPHA) ? BM_SSP_CTRL1_PHASE : 0),
+	       ssp->base + HW_SSP_CTRL1(ssp));
 
 	writel(0x0, ssp->base + HW_SSP_CMD0);
 	writel(0x0, ssp->base + HW_SSP_CMD1);
@@ -94,26 +113,15 @@
 
 static int mxs_spi_setup(struct spi_device *dev)
 {
-	int err = 0;
-
 	if (!dev->bits_per_word)
 		dev->bits_per_word = 8;
 
-	if (dev->mode & ~(SPI_CPOL | SPI_CPHA))
-		return -EINVAL;
-
-	err = mxs_spi_setup_transfer(dev, NULL);
-	if (err) {
-		dev_err(&dev->dev,
-			"Failed to setup transfer, error = %d\n", err);
-	}
-
-	return err;
+	return 0;
 }
 
-static uint32_t mxs_spi_cs_to_reg(unsigned cs)
+static u32 mxs_spi_cs_to_reg(unsigned cs)
 {
-	uint32_t select = 0;
+	u32 select = 0;
 
 	/*
 	 * i.MX28 Datasheet: 17.10.1: HW_SSP_CTRL0
@@ -131,43 +139,11 @@
 	return select;
 }
 
-static void mxs_spi_set_cs(struct mxs_spi *spi, unsigned cs)
-{
-	const uint32_t mask =
-		BM_SSP_CTRL0_WAIT_FOR_CMD | BM_SSP_CTRL0_WAIT_FOR_IRQ;
-	uint32_t select;
-	struct mxs_ssp *ssp = &spi->ssp;
-
-	writel(mask, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
-	select = mxs_spi_cs_to_reg(cs);
-	writel(select, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
-}
-
-static inline void mxs_spi_enable(struct mxs_spi *spi)
-{
-	struct mxs_ssp *ssp = &spi->ssp;
-
-	writel(BM_SSP_CTRL0_LOCK_CS,
-		ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
-	writel(BM_SSP_CTRL0_IGNORE_CRC,
-		ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
-}
-
-static inline void mxs_spi_disable(struct mxs_spi *spi)
-{
-	struct mxs_ssp *ssp = &spi->ssp;
-
-	writel(BM_SSP_CTRL0_LOCK_CS,
-		ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
-	writel(BM_SSP_CTRL0_IGNORE_CRC,
-		ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
-}
-
 static int mxs_ssp_wait(struct mxs_spi *spi, int offset, int mask, bool set)
 {
 	const unsigned long timeout = jiffies + msecs_to_jiffies(SSP_TIMEOUT);
 	struct mxs_ssp *ssp = &spi->ssp;
-	uint32_t reg;
+	u32 reg;
 
 	do {
 		reg = readl_relaxed(ssp->base + offset);
@@ -200,9 +176,9 @@
 	return IRQ_HANDLED;
 }
 
-static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs,
+static int mxs_spi_txrx_dma(struct mxs_spi *spi,
 			    unsigned char *buf, int len,
-			    int *first, int *last, int write)
+			    unsigned int flags)
 {
 	struct mxs_ssp *ssp = &spi->ssp;
 	struct dma_async_tx_descriptor *desc = NULL;
@@ -211,11 +187,11 @@
 	const int sgs = DIV_ROUND_UP(len, desc_len);
 	int sg_count;
 	int min, ret;
-	uint32_t ctrl0;
+	u32 ctrl0;
 	struct page *vm_page;
 	void *sg_buf;
 	struct {
-		uint32_t		pio[4];
+		u32			pio[4];
 		struct scatterlist	sg;
 	} *dma_xfer;
 
@@ -228,21 +204,25 @@
 
 	INIT_COMPLETION(spi->c);
 
+	/* Chip select was already programmed into CTRL0 */
 	ctrl0 = readl(ssp->base + HW_SSP_CTRL0);
-	ctrl0 &= ~BM_SSP_CTRL0_XFER_COUNT;
-	ctrl0 |= BM_SSP_CTRL0_DATA_XFER | mxs_spi_cs_to_reg(cs);
+	ctrl0 &= ~(BM_SSP_CTRL0_XFER_COUNT | BM_SSP_CTRL0_IGNORE_CRC |
+		 BM_SSP_CTRL0_READ);
+	ctrl0 |= BM_SSP_CTRL0_DATA_XFER;
 
-	if (*first)
-		ctrl0 |= BM_SSP_CTRL0_LOCK_CS;
-	if (!write)
+	if (!(flags & TXRX_WRITE))
 		ctrl0 |= BM_SSP_CTRL0_READ;
 
 	/* Queue the DMA data transfer. */
 	for (sg_count = 0; sg_count < sgs; sg_count++) {
+		/* Prepare the transfer descriptor. */
 		min = min(len, desc_len);
 
-		/* Prepare the transfer descriptor. */
-		if ((sg_count + 1 == sgs) && *last)
+		/*
+		 * De-assert CS on last segment if flag is set (i.e., no more
+		 * transfers will follow)
+		 */
+		if ((sg_count + 1 == sgs) && (flags & TXRX_DEASSERT_CS))
 			ctrl0 |= BM_SSP_CTRL0_IGNORE_CRC;
 
 		if (ssp->devid == IMX23_SSP) {
@@ -267,7 +247,7 @@
 
 		sg_init_one(&dma_xfer[sg_count].sg, sg_buf, min);
 		ret = dma_map_sg(ssp->dev, &dma_xfer[sg_count].sg, 1,
-			write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+			(flags & TXRX_WRITE) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 
 		len -= min;
 		buf += min;
@@ -287,7 +267,7 @@
 
 		desc = dmaengine_prep_slave_sg(ssp->dmach,
 				&dma_xfer[sg_count].sg, 1,
-				write ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
+				(flags & TXRX_WRITE) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
 				DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 
 		if (!desc) {
@@ -324,7 +304,7 @@
 	while (--sg_count >= 0) {
 err_mapped:
 		dma_unmap_sg(ssp->dev, &dma_xfer[sg_count].sg, 1,
-			write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+			(flags & TXRX_WRITE) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 	}
 
 	kfree(dma_xfer);
@@ -332,20 +312,19 @@
 	return ret;
 }
 
-static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs,
+static int mxs_spi_txrx_pio(struct mxs_spi *spi,
 			    unsigned char *buf, int len,
-			    int *first, int *last, int write)
+			    unsigned int flags)
 {
 	struct mxs_ssp *ssp = &spi->ssp;
 
-	if (*first)
-		mxs_spi_enable(spi);
-
-	mxs_spi_set_cs(spi, cs);
+	writel(BM_SSP_CTRL0_IGNORE_CRC,
+	       ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
 
 	while (len--) {
-		if (*last && len == 0)
-			mxs_spi_disable(spi);
+		if (len == 0 && (flags & TXRX_DEASSERT_CS))
+			writel(BM_SSP_CTRL0_IGNORE_CRC,
+			       ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
 
 		if (ssp->devid == IMX23_SSP) {
 			writel(BM_SSP_CTRL0_XFER_COUNT,
@@ -356,7 +335,7 @@
 			writel(1, ssp->base + HW_SSP_XFER_SIZE);
 		}
 
-		if (write)
+		if (flags & TXRX_WRITE)
 			writel(BM_SSP_CTRL0_READ,
 				ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
 		else
@@ -369,13 +348,13 @@
 		if (mxs_ssp_wait(spi, HW_SSP_CTRL0, BM_SSP_CTRL0_RUN, 1))
 			return -ETIMEDOUT;
 
-		if (write)
+		if (flags & TXRX_WRITE)
 			writel(*buf, ssp->base + HW_SSP_DATA(ssp));
 
 		writel(BM_SSP_CTRL0_DATA_XFER,
 			     ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
 
-		if (!write) {
+		if (!(flags & TXRX_WRITE)) {
 			if (mxs_ssp_wait(spi, HW_SSP_STATUS(ssp),
 						BM_SSP_STATUS_FIFO_EMPTY, 0))
 				return -ETIMEDOUT;
@@ -400,14 +379,15 @@
 {
 	struct mxs_spi *spi = spi_master_get_devdata(master);
 	struct mxs_ssp *ssp = &spi->ssp;
-	int first, last;
 	struct spi_transfer *t, *tmp_t;
+	unsigned int flag;
 	int status = 0;
-	int cs;
 
-	first = last = 0;
-
-	cs = m->spi->chip_select;
+	/* Program CS register bits here, it will be used for all transfers. */
+	writel(BM_SSP_CTRL0_WAIT_FOR_CMD | BM_SSP_CTRL0_WAIT_FOR_IRQ,
+	       ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
+	writel(mxs_spi_cs_to_reg(m->spi->chip_select),
+	       ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
 
 	list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list) {
 
@@ -415,16 +395,9 @@
 		if (status)
 			break;
 
-		if (&t->transfer_list == m->transfers.next)
-			first = 1;
-		if (&t->transfer_list == m->transfers.prev)
-			last = 1;
-		if ((t->rx_buf && t->tx_buf) || (t->rx_dma && t->tx_dma)) {
-			dev_err(ssp->dev,
-				"Cannot send and receive simultaneously\n");
-			status = -EINVAL;
-			break;
-		}
+		/* De-assert on last transfer, inverted by cs_change flag */
+		flag = (&t->transfer_list == m->transfers.prev) ^ t->cs_change ?
+		       TXRX_DEASSERT_CS : 0;
 
 		/*
 		 * Small blocks can be transfered via PIO.
@@ -441,26 +414,26 @@
 				STMP_OFFSET_REG_CLR);
 
 			if (t->tx_buf)
-				status = mxs_spi_txrx_pio(spi, cs,
+				status = mxs_spi_txrx_pio(spi,
 						(void *)t->tx_buf,
-						t->len, &first, &last, 1);
+						t->len, flag | TXRX_WRITE);
 			if (t->rx_buf)
-				status = mxs_spi_txrx_pio(spi, cs,
+				status = mxs_spi_txrx_pio(spi,
 						t->rx_buf, t->len,
-						&first, &last, 0);
+						flag);
 		} else {
 			writel(BM_SSP_CTRL1_DMA_ENABLE,
 				ssp->base + HW_SSP_CTRL1(ssp) +
 				STMP_OFFSET_REG_SET);
 
 			if (t->tx_buf)
-				status = mxs_spi_txrx_dma(spi, cs,
+				status = mxs_spi_txrx_dma(spi,
 						(void *)t->tx_buf, t->len,
-						&first, &last, 1);
+						flag | TXRX_WRITE);
 			if (t->rx_buf)
-				status = mxs_spi_txrx_dma(spi, cs,
+				status = mxs_spi_txrx_dma(spi,
 						t->rx_buf, t->len,
-						&first, &last, 0);
+						flag);
 		}
 
 		if (status) {
@@ -469,7 +442,6 @@
 		}
 
 		m->actual_length += t->len;
-		first = last = 0;
 	}
 
 	m->status = status;
@@ -563,7 +535,6 @@
 		goto out_dma_release;
 
 	clk_set_rate(ssp->clk, clk_freq);
-	ssp->clk_rate = clk_get_rate(ssp->clk) / 1000;
 
 	ret = stmp_reset_block(ssp->base);
 	if (ret)
@@ -571,7 +542,7 @@
 
 	platform_set_drvdata(pdev, master);
 
-	ret = spi_register_master(master);
+	ret = devm_spi_register_master(&pdev->dev, master);
 	if (ret) {
 		dev_err(&pdev->dev, "Cannot register SPI master, %d\n", ret);
 		goto out_disable_clk;
@@ -598,10 +569,8 @@
 	spi = spi_master_get_devdata(master);
 	ssp = &spi->ssp;
 
-	spi_unregister_master(master);
 	clk_disable_unprepare(ssp->clk);
 	dma_release_channel(ssp->dmach);
-	spi_master_put(master);
 
 	return 0;
 }
diff --git a/drivers/spi/spi-nuc900.c b/drivers/spi/spi-nuc900.c
index 47a68b4..e0c32bc 100644
--- a/drivers/spi/spi-nuc900.c
+++ b/drivers/spi/spi-nuc900.c
@@ -349,7 +349,7 @@
 	}
 
 	hw = spi_master_get_devdata(master);
-	hw->master = spi_master_get(master);
+	hw->master = master;
 	hw->pdata  = dev_get_platdata(&pdev->dev);
 	hw->dev = &pdev->dev;
 
@@ -435,7 +435,6 @@
 	kfree(hw->ioarea);
 err_pdata:
 	spi_master_put(hw->master);
-
 err_nomem:
 	return err;
 }
diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c
index 333cb1b..91c6685 100644
--- a/drivers/spi/spi-oc-tiny.c
+++ b/drivers/spi/spi-oc-tiny.c
@@ -306,7 +306,7 @@
 	platform_set_drvdata(pdev, hw);
 
 	/* setup the state for the bitbang driver */
-	hw->bitbang.master = spi_master_get(master);
+	hw->bitbang.master = master;
 	if (!hw->bitbang.master)
 		return err;
 	hw->bitbang.setup_transfer = tiny_spi_setup_transfer;
diff --git a/drivers/spi/spi-octeon.c b/drivers/spi/spi-octeon.c
index 5f28ddb..67249a4 100644
--- a/drivers/spi/spi-octeon.c
+++ b/drivers/spi/spi-octeon.c
@@ -272,7 +272,7 @@
 	master->bits_per_word_mask = SPI_BPW_MASK(8);
 
 	master->dev.of_node = pdev->dev.of_node;
-	err = spi_register_master(master);
+	err = devm_spi_register_master(&pdev->dev, master);
 	if (err) {
 		dev_err(&pdev->dev, "register master failed: %d\n", err);
 		goto fail;
@@ -292,8 +292,6 @@
 	struct octeon_spi *p = spi_master_get_devdata(master);
 	u64 register_base = p->register_base;
 
-	spi_unregister_master(master);
-
 	/* Clear the CSENA* and put everything in a known state. */
 	cvmx_write_csr(register_base + OCTEON_SPI_CFG, 0);
 
diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c
index 69ecf05..b6ed82b 100644
--- a/drivers/spi/spi-omap-100k.c
+++ b/drivers/spi/spi-omap-100k.c
@@ -457,7 +457,7 @@
 		goto err;
 	}
 
-	status = spi_register_master(master);
+	status = devm_spi_register_master(&pdev->dev, master);
 	if (status < 0)
 		goto err;
 
@@ -485,8 +485,6 @@
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-	spi_unregister_master(master);
-
 	return 0;
 }
 
diff --git a/drivers/spi/spi-omap-uwire.c b/drivers/spi/spi-omap-uwire.c
index a6a8f09..9313fd3 100644
--- a/drivers/spi/spi-omap-uwire.c
+++ b/drivers/spi/spi-omap-uwire.c
@@ -557,7 +557,8 @@
 		.name		= "omap_uwire",
 		.owner		= THIS_MODULE,
 	},
-	.remove		= uwire_remove,
+	.probe = uwire_probe,
+	.remove = uwire_remove,
 	// suspend ... unuse ck
 	// resume ... use ck
 };
@@ -579,7 +580,7 @@
 		omap_writel(val | 0x00AAA000, OMAP7XX_IO_CONF_9);
 	}
 
-	return platform_driver_probe(&uwire_driver, uwire_probe);
+	return platform_driver_register(&uwire_driver);
 }
 
 static void __exit omap_uwire_exit(void)
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index ed4af47..443df39 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -276,7 +276,7 @@
 	struct omap2_mcspi_cs *cs = spi->controller_state;
 	struct omap2_mcspi *mcspi;
 	unsigned int wcnt;
-	int fifo_depth, bytes_per_word;
+	int max_fifo_depth, fifo_depth, bytes_per_word;
 	u32 chconf, xferlevel;
 
 	mcspi = spi_master_get_devdata(master);
@@ -287,7 +287,12 @@
 		if (t->len % bytes_per_word != 0)
 			goto disable_fifo;
 
-		fifo_depth = gcd(t->len, OMAP2_MCSPI_MAX_FIFODEPTH);
+		if (t->rx_buf != NULL && t->tx_buf != NULL)
+			max_fifo_depth = OMAP2_MCSPI_MAX_FIFODEPTH / 2;
+		else
+			max_fifo_depth = OMAP2_MCSPI_MAX_FIFODEPTH;
+
+		fifo_depth = gcd(t->len, max_fifo_depth);
 		if (fifo_depth < 2 || fifo_depth % bytes_per_word != 0)
 			goto disable_fifo;
 
@@ -299,7 +304,8 @@
 		if (t->rx_buf != NULL) {
 			chconf |= OMAP2_MCSPI_CHCONF_FFER;
 			xferlevel |= (fifo_depth - 1) << 8;
-		} else {
+		}
+		if (t->tx_buf != NULL) {
 			chconf |= OMAP2_MCSPI_CHCONF_FFET;
 			xferlevel |= fifo_depth - 1;
 		}
@@ -498,7 +504,7 @@
 				((u32 *)xfer->rx_buf)[elements++] = w;
 		} else {
 			int bytes_per_word = mcspi_bytes_per_word(word_len);
-			dev_err(&spi->dev, "DMA RX penultimate word empty");
+			dev_err(&spi->dev, "DMA RX penultimate word empty\n");
 			count -= (bytes_per_word << 1);
 			omap2_mcspi_set_enable(spi, 1);
 			return count;
@@ -516,7 +522,7 @@
 		else /* word_len <= 32 */
 			((u32 *)xfer->rx_buf)[elements] = w;
 	} else {
-		dev_err(&spi->dev, "DMA RX last word empty");
+		dev_err(&spi->dev, "DMA RX last word empty\n");
 		count -= mcspi_bytes_per_word(word_len);
 	}
 	omap2_mcspi_set_enable(spi, 1);
@@ -1407,7 +1413,7 @@
 	if (status < 0)
 		goto disable_pm;
 
-	status = spi_register_master(master);
+	status = devm_spi_register_master(&pdev->dev, master);
 	if (status < 0)
 		goto disable_pm;
 
@@ -1435,7 +1441,6 @@
 	pm_runtime_put_sync(mcspi->dev);
 	pm_runtime_disable(&pdev->dev);
 
-	spi_unregister_master(master);
 	kfree(dma_channels);
 
 	return 0;
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c
index 1d1d321..744841e 100644
--- a/drivers/spi/spi-orion.c
+++ b/drivers/spi/spi-orion.c
@@ -84,8 +84,8 @@
 		orion_spi_clrbits(orion_spi, ORION_SPI_IF_CONFIG_REG,
 				  ORION_SPI_IF_8_16_BIT_MODE);
 	} else {
-		pr_debug("Bad bits per word value %d (only 8 or 16 are "
-			 "allowed).\n", size);
+		pr_debug("Bad bits per word value %d (only 8 or 16 are allowed).\n",
+			size);
 		return -EINVAL;
 	}
 
@@ -407,7 +407,7 @@
 	const u32 *iprop;
 	int size;
 
-	master = spi_alloc_master(&pdev->dev, sizeof *spi);
+	master = spi_alloc_master(&pdev->dev, sizeof(*spi));
 	if (master == NULL) {
 		dev_dbg(&pdev->dev, "master allocation failed\n");
 		return -ENOMEM;
@@ -457,7 +457,7 @@
 		goto out_rel_clk;
 
 	master->dev.of_node = pdev->dev.of_node;
-	status = spi_register_master(master);
+	status = devm_spi_register_master(&pdev->dev, master);
 	if (status < 0)
 		goto out_rel_clk;
 
@@ -483,8 +483,6 @@
 	clk_disable_unprepare(spi->clk);
 	clk_put(spi->clk);
 
-	spi_unregister_master(master);
-
 	return 0;
 }
 
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 9c511a9..2789b45 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -1619,7 +1619,6 @@
 		dev_err(&pl022->adev->dev,
 			"RX FIFO Trigger Level is configured incorrectly\n");
 		return -EINVAL;
-		break;
 	}
 	switch (chip_info->tx_lev_trig) {
 	case SSP_TX_1_OR_MORE_EMPTY_LOC:
@@ -1645,7 +1644,6 @@
 		dev_err(&pl022->adev->dev,
 			"TX FIFO Trigger Level is configured incorrectly\n");
 		return -EINVAL;
-		break;
 	}
 	if (chip_info->iface == SSP_INTERFACE_NATIONAL_MICROWIRE) {
 		if ((chip_info->ctrl_len < SSP_BITS_4)
@@ -2175,8 +2173,8 @@
 		status = -ENOMEM;
 		goto err_no_ioremap;
 	}
-	printk(KERN_INFO "pl022: mapped registers from %pa to %p\n",
-	       &adev->res.start, pl022->virtbase);
+	dev_info(&adev->dev, "mapped registers from %pa to %p\n",
+		&adev->res.start, pl022->virtbase);
 
 	pl022->clk = devm_clk_get(&adev->dev, NULL);
 	if (IS_ERR(pl022->clk)) {
@@ -2227,7 +2225,7 @@
 
 	/* Register with the SPI framework */
 	amba_set_drvdata(adev, pl022);
-	status = spi_register_master(master);
+	status = devm_spi_register_master(&adev->dev, master);
 	if (status != 0) {
 		dev_err(&adev->dev,
 			"probe - problem registering spi master\n");
@@ -2287,8 +2285,6 @@
 	clk_unprepare(pl022->clk);
 	amba_release_regions(adev);
 	tasklet_disable(&pl022->pump_transfers);
-	spi_unregister_master(pl022->master);
-	amba_set_drvdata(adev, NULL);
 	return 0;
 }
 
diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c
index 0ee53c2..5ee5672 100644
--- a/drivers/spi/spi-ppc4xx.c
+++ b/drivers/spi/spi-ppc4xx.c
@@ -29,6 +29,8 @@
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/wait.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
 #include <linux/interrupt.h>
@@ -396,7 +398,7 @@
 	master->dev.of_node = np;
 	platform_set_drvdata(op, master);
 	hw = spi_master_get_devdata(master);
-	hw->master = spi_master_get(master);
+	hw->master = master;
 	hw->dev = dev;
 
 	init_completion(&hw->done);
@@ -558,6 +560,7 @@
 	free_irq(hw->irqnum, hw);
 	iounmap(hw->regs);
 	free_gpios(hw);
+	spi_master_put(master);
 	return 0;
 }
 
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index 2eb06ee..cb0e1f1 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -546,8 +546,17 @@
 	if (pm_runtime_suspended(&drv_data->pdev->dev))
 		return IRQ_NONE;
 
-	sccr1_reg = read_SSCR1(reg);
+	/*
+	 * If the device is not yet in RPM suspended state and we get an
+	 * interrupt that is meant for another device, check if status bits
+	 * are all set to one. That means that the device is already
+	 * powered off.
+	 */
 	status = read_SSSR(reg);
+	if (status == ~0)
+		return IRQ_NONE;
+
+	sccr1_reg = read_SSCR1(reg);
 
 	/* Ignore possible writes if we don't need to write */
 	if (!(sccr1_reg & SSCR1_TIE))
@@ -564,8 +573,8 @@
 			write_SSTO(0, reg);
 		write_SSSR_CS(drv_data, drv_data->clear_sr);
 
-		dev_err(&drv_data->pdev->dev, "bad message state "
-			"in interrupt handler\n");
+		dev_err(&drv_data->pdev->dev,
+			"bad message state in interrupt handler\n");
 
 		/* Never fail */
 		return IRQ_HANDLED;
@@ -642,8 +651,8 @@
 		if (message->is_dma_mapped
 				|| transfer->rx_dma || transfer->tx_dma) {
 			dev_err(&drv_data->pdev->dev,
-				"pump_transfers: mapped transfer length "
-				"of %u is greater than %d\n",
+				"pump_transfers: mapped transfer length of "
+				"%u is greater than %d\n",
 				transfer->len, MAX_DMA_LEN);
 			message->status = -EINVAL;
 			giveback(drv_data);
@@ -651,11 +660,10 @@
 		}
 
 		/* warn ... we force this to PIO mode */
-		if (printk_ratelimit())
-			dev_warn(&message->spi->dev, "pump_transfers: "
-				"DMA disabled for transfer length %ld "
-				"greater than %d\n",
-				(long)drv_data->len, MAX_DMA_LEN);
+		dev_warn_ratelimited(&message->spi->dev,
+				     "pump_transfers: DMA disabled for transfer length %ld "
+				     "greater than %d\n",
+				     (long)drv_data->len, MAX_DMA_LEN);
 	}
 
 	/* Setup the transfer state based on the type of transfer */
@@ -717,11 +725,8 @@
 							message->spi,
 							bits, &dma_burst,
 							&dma_thresh))
-				if (printk_ratelimit())
-					dev_warn(&message->spi->dev,
-						"pump_transfers: "
-						"DMA burst size reduced to "
-						"match bits_per_word\n");
+				dev_warn_ratelimited(&message->spi->dev,
+						     "pump_transfers: DMA burst size reduced to match bits_per_word\n");
 		}
 
 		cr0 = clk_div
@@ -845,8 +850,8 @@
 	if (gpio_is_valid(chip_info->gpio_cs)) {
 		err = gpio_request(chip_info->gpio_cs, "SPI_CS");
 		if (err) {
-			dev_err(&spi->dev, "failed to request chip select "
-					"GPIO%d\n", chip_info->gpio_cs);
+			dev_err(&spi->dev, "failed to request chip select GPIO%d\n",
+				chip_info->gpio_cs);
 			return err;
 		}
 
@@ -890,8 +895,8 @@
 
 		if (drv_data->ssp_type == CE4100_SSP) {
 			if (spi->chip_select > 4) {
-				dev_err(&spi->dev, "failed setup: "
-				"cs number must not be > 4.\n");
+				dev_err(&spi->dev,
+					"failed setup: cs number must not be > 4.\n");
 				kfree(chip);
 				return -EINVAL;
 			}
@@ -947,8 +952,8 @@
 						spi->bits_per_word,
 						&chip->dma_burst_size,
 						&chip->dma_threshold)) {
-			dev_warn(&spi->dev, "in setup: DMA burst size reduced "
-					"to match bits_per_word\n");
+			dev_warn(&spi->dev,
+				 "in setup: DMA burst size reduced to match bits_per_word\n");
 		}
 	}
 
@@ -1196,7 +1201,7 @@
 
 	/* Register with the SPI framework */
 	platform_set_drvdata(pdev, drv_data);
-	status = spi_register_master(master);
+	status = devm_spi_register_master(&pdev->dev, master);
 	if (status != 0) {
 		dev_err(&pdev->dev, "problem registering spi master\n");
 		goto out_error_clock_enabled;
@@ -1248,9 +1253,6 @@
 	/* Release SSP */
 	pxa_ssp_free(ssp);
 
-	/* Disconnect from the SPI framework */
-	spi_unregister_master(drv_data->master);
-
 	return 0;
 }
 
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 8719206..58449ad4 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -59,6 +59,14 @@
 #define RSPI_SPCMD6		0x1c
 #define RSPI_SPCMD7		0x1e
 
+/*qspi only */
+#define QSPI_SPBFCR		0x18
+#define QSPI_SPBDCR		0x1a
+#define QSPI_SPBMUL0		0x1c
+#define QSPI_SPBMUL1		0x20
+#define QSPI_SPBMUL2		0x24
+#define QSPI_SPBMUL3		0x28
+
 /* SPCR */
 #define SPCR_SPRIE		0x80
 #define SPCR_SPE		0x40
@@ -126,6 +134,8 @@
 #define SPCMD_LSBF		0x1000
 #define SPCMD_SPB_MASK		0x0f00
 #define SPCMD_SPB_8_TO_16(bit)	(((bit - 1) << 8) & SPCMD_SPB_MASK)
+#define SPCMD_SPB_8BIT		0x0000	/* qspi only */
+#define SPCMD_SPB_16BIT		0x0100
 #define SPCMD_SPB_20BIT		0x0000
 #define SPCMD_SPB_24BIT		0x0100
 #define SPCMD_SPB_32BIT		0x0200
@@ -135,6 +145,10 @@
 #define SPCMD_CPOL		0x0002
 #define SPCMD_CPHA		0x0001
 
+/* SPBFCR */
+#define SPBFCR_TXRST		0x80	/* qspi only */
+#define SPBFCR_RXRST		0x40	/* qspi only */
+
 struct rspi_data {
 	void __iomem *addr;
 	u32 max_speed_hz;
@@ -145,6 +159,7 @@
 	spinlock_t lock;
 	struct clk *clk;
 	unsigned char spsr;
+	const struct spi_ops *ops;
 
 	/* for dmaengine */
 	struct dma_chan *chan_tx;
@@ -165,6 +180,11 @@
 	iowrite16(data, rspi->addr + offset);
 }
 
+static void rspi_write32(struct rspi_data *rspi, u32 data, u16 offset)
+{
+	iowrite32(data, rspi->addr + offset);
+}
+
 static u8 rspi_read8(struct rspi_data *rspi, u16 offset)
 {
 	return ioread8(rspi->addr + offset);
@@ -175,17 +195,103 @@
 	return ioread16(rspi->addr + offset);
 }
 
-static unsigned char rspi_calc_spbr(struct rspi_data *rspi)
+/* optional functions */
+struct spi_ops {
+	int (*set_config_register)(struct rspi_data *rspi, int access_size);
+	int (*send_pio)(struct rspi_data *rspi, struct spi_message *mesg,
+			struct spi_transfer *t);
+	int (*receive_pio)(struct rspi_data *rspi, struct spi_message *mesg,
+			   struct spi_transfer *t);
+
+};
+
+/*
+ * functions for RSPI
+ */
+static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
 {
-	int tmp;
-	unsigned char spbr;
+	int spbr;
 
-	tmp = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1;
-	spbr = clamp(tmp, 0, 255);
+	/* Sets output mode(CMOS) and MOSI signal(from previous transfer) */
+	rspi_write8(rspi, 0x00, RSPI_SPPCR);
 
-	return spbr;
+	/* Sets transfer bit rate */
+	spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz) - 1;
+	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
+
+	/* Sets number of frames to be used: 1 frame */
+	rspi_write8(rspi, 0x00, RSPI_SPDCR);
+
+	/* Sets RSPCK, SSL, next-access delay value */
+	rspi_write8(rspi, 0x00, RSPI_SPCKD);
+	rspi_write8(rspi, 0x00, RSPI_SSLND);
+	rspi_write8(rspi, 0x00, RSPI_SPND);
+
+	/* Sets parity, interrupt mask */
+	rspi_write8(rspi, 0x00, RSPI_SPCR2);
+
+	/* Sets SPCMD */
+	rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | SPCMD_SSLKP,
+		     RSPI_SPCMD0);
+
+	/* Sets RSPI mode */
+	rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
+
+	return 0;
 }
 
+/*
+ * functions for QSPI
+ */
+static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
+{
+	u16 spcmd;
+	int spbr;
+
+	/* Sets output mode(CMOS) and MOSI signal(from previous transfer) */
+	rspi_write8(rspi, 0x00, RSPI_SPPCR);
+
+	/* Sets transfer bit rate */
+	spbr = clk_get_rate(rspi->clk) / (2 * rspi->max_speed_hz);
+	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
+
+	/* Sets number of frames to be used: 1 frame */
+	rspi_write8(rspi, 0x00, RSPI_SPDCR);
+
+	/* Sets RSPCK, SSL, next-access delay value */
+	rspi_write8(rspi, 0x00, RSPI_SPCKD);
+	rspi_write8(rspi, 0x00, RSPI_SSLND);
+	rspi_write8(rspi, 0x00, RSPI_SPND);
+
+	/* Data Length Setting */
+	if (access_size == 8)
+		spcmd = SPCMD_SPB_8BIT;
+	else if (access_size == 16)
+		spcmd = SPCMD_SPB_16BIT;
+	else if (access_size == 32)
+		spcmd = SPCMD_SPB_32BIT;
+
+	spcmd |= SPCMD_SCKDEN | SPCMD_SLNDEN | SPCMD_SSLKP | SPCMD_SPNDEN;
+
+	/* Resets transfer data length */
+	rspi_write32(rspi, 0, QSPI_SPBMUL0);
+
+	/* Resets transmit and receive buffer */
+	rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR);
+	/* Sets buffer to allow normal operation */
+	rspi_write8(rspi, 0x00, QSPI_SPBFCR);
+
+	/* Sets SPCMD */
+	rspi_write16(rspi, spcmd, RSPI_SPCMD0);
+
+	/* Enables SPI function in a master mode */
+	rspi_write8(rspi, SPCR_SPE | SPCR_MSTR, RSPI_SPCR);
+
+	return 0;
+}
+
+#define set_config_register(spi, n) spi->ops->set_config_register(spi, n)
+
 static void rspi_enable_irq(struct rspi_data *rspi, u8 enable)
 {
 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) | enable, RSPI_SPCR);
@@ -220,35 +326,6 @@
 	rspi_write8(rspi, rspi_read8(rspi, RSPI_SPCR) & ~SPCR_SPE, RSPI_SPCR);
 }
 
-static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
-{
-	/* Sets output mode(CMOS) and MOSI signal(from previous transfer) */
-	rspi_write8(rspi, 0x00, RSPI_SPPCR);
-
-	/* Sets transfer bit rate */
-	rspi_write8(rspi, rspi_calc_spbr(rspi), RSPI_SPBR);
-
-	/* Sets number of frames to be used: 1 frame */
-	rspi_write8(rspi, 0x00, RSPI_SPDCR);
-
-	/* Sets RSPCK, SSL, next-access delay value */
-	rspi_write8(rspi, 0x00, RSPI_SPCKD);
-	rspi_write8(rspi, 0x00, RSPI_SSLND);
-	rspi_write8(rspi, 0x00, RSPI_SPND);
-
-	/* Sets parity, interrupt mask */
-	rspi_write8(rspi, 0x00, RSPI_SPCR2);
-
-	/* Sets SPCMD */
-	rspi_write16(rspi, SPCMD_SPB_8_TO_16(access_size) | SPCMD_SSLKP,
-		     RSPI_SPCMD0);
-
-	/* Sets RSPI mode */
-	rspi_write8(rspi, SPCR_MSTR, RSPI_SPCR);
-
-	return 0;
-}
-
 static int rspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
 			 struct spi_transfer *t)
 {
@@ -277,6 +354,43 @@
 	return 0;
 }
 
+static int qspi_send_pio(struct rspi_data *rspi, struct spi_message *mesg,
+			 struct spi_transfer *t)
+{
+	int remain = t->len;
+	u8 *data;
+
+	rspi_write8(rspi, SPBFCR_TXRST, QSPI_SPBFCR);
+	rspi_write8(rspi, 0x00, QSPI_SPBFCR);
+
+	data = (u8 *)t->tx_buf;
+	while (remain > 0) {
+
+		if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
+			dev_err(&rspi->master->dev,
+				"%s: tx empty timeout\n", __func__);
+			return -ETIMEDOUT;
+		}
+		rspi_write8(rspi, *data++, RSPI_SPDR);
+
+		if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
+			dev_err(&rspi->master->dev,
+				"%s: receive timeout\n", __func__);
+			return -ETIMEDOUT;
+		}
+		rspi_read8(rspi, RSPI_SPDR);
+
+		remain--;
+	}
+
+	/* Waiting for the last transmition */
+	rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE);
+
+	return 0;
+}
+
+#define send_pio(spi, mesg, t) spi->ops->send_pio(spi, mesg, t)
+
 static void rspi_dma_complete(void *arg)
 {
 	struct rspi_data *rspi = arg;
@@ -442,6 +556,51 @@
 	return 0;
 }
 
+static void qspi_receive_init(struct rspi_data *rspi)
+{
+	unsigned char spsr;
+
+	spsr = rspi_read8(rspi, RSPI_SPSR);
+	if (spsr & SPSR_SPRF)
+		rspi_read8(rspi, RSPI_SPDR);   /* dummy read */
+	rspi_write8(rspi, SPBFCR_TXRST | SPBFCR_RXRST, QSPI_SPBFCR);
+	rspi_write8(rspi, 0x00, QSPI_SPBFCR);
+}
+
+static int qspi_receive_pio(struct rspi_data *rspi, struct spi_message *mesg,
+			    struct spi_transfer *t)
+{
+	int remain = t->len;
+	u8 *data;
+
+	qspi_receive_init(rspi);
+
+	data = (u8 *)t->rx_buf;
+	while (remain > 0) {
+
+		if (rspi_wait_for_interrupt(rspi, SPSR_SPTEF, SPCR_SPTIE) < 0) {
+			dev_err(&rspi->master->dev,
+				"%s: tx empty timeout\n", __func__);
+			return -ETIMEDOUT;
+		}
+		/* dummy write for generate clock */
+		rspi_write8(rspi, 0x00, RSPI_SPDR);
+
+		if (rspi_wait_for_interrupt(rspi, SPSR_SPRF, SPCR_SPRIE) < 0) {
+			dev_err(&rspi->master->dev,
+				"%s: receive timeout\n", __func__);
+			return -ETIMEDOUT;
+		}
+		/* SPDR allows 8, 16 or 32-bit access */
+		*data++ = rspi_read8(rspi, RSPI_SPDR);
+		remain--;
+	}
+
+	return 0;
+}
+
+#define receive_pio(spi, mesg, t) spi->ops->receive_pio(spi, mesg, t)
+
 static int rspi_receive_dma(struct rspi_data *rspi, struct spi_transfer *t)
 {
 	struct scatterlist sg, sg_dummy;
@@ -581,7 +740,7 @@
 				if (rspi_is_dma(rspi, t))
 					ret = rspi_send_dma(rspi, t);
 				else
-					ret = rspi_send_pio(rspi, mesg, t);
+					ret = send_pio(rspi, mesg, t);
 				if (ret < 0)
 					goto error;
 			}
@@ -589,7 +748,7 @@
 				if (rspi_is_dma(rspi, t))
 					ret = rspi_receive_dma(rspi, t);
 				else
-					ret = rspi_receive_pio(rspi, mesg, t);
+					ret = receive_pio(rspi, mesg, t);
 				if (ret < 0)
 					goto error;
 			}
@@ -616,7 +775,7 @@
 		spi->bits_per_word = 8;
 	rspi->max_speed_hz = spi->max_speed_hz;
 
-	rspi_set_config_register(rspi, 8);
+	set_config_register(rspi, 8);
 
 	return 0;
 }
@@ -745,7 +904,16 @@
 	struct rspi_data *rspi;
 	int ret, irq;
 	char clk_name[16];
+	struct rspi_plat_data *rspi_pd = pdev->dev.platform_data;
+	const struct spi_ops *ops;
+	const struct platform_device_id *id_entry = pdev->id_entry;
 
+	ops = (struct spi_ops *)id_entry->driver_data;
+	/* ops parameter check */
+	if (!ops->set_config_register) {
+		dev_err(&pdev->dev, "there is no set_config_register\n");
+		return -ENODEV;
+	}
 	/* get base addr */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (unlikely(res == NULL)) {
@@ -767,7 +935,7 @@
 
 	rspi = spi_master_get_devdata(master);
 	platform_set_drvdata(pdev, rspi);
-
+	rspi->ops = ops;
 	rspi->master = master;
 	rspi->addr = ioremap(res->start, resource_size(res));
 	if (rspi->addr == NULL) {
@@ -776,7 +944,7 @@
 		goto error1;
 	}
 
-	snprintf(clk_name, sizeof(clk_name), "rspi%d", pdev->id);
+	snprintf(clk_name, sizeof(clk_name), "%s%d", id_entry->name, pdev->id);
 	rspi->clk = clk_get(&pdev->dev, clk_name);
 	if (IS_ERR(rspi->clk)) {
 		dev_err(&pdev->dev, "cannot get clock\n");
@@ -790,7 +958,10 @@
 	INIT_WORK(&rspi->ws, rspi_work);
 	init_waitqueue_head(&rspi->wait);
 
-	master->num_chipselect = 2;
+	master->num_chipselect = rspi_pd->num_chipselect;
+	if (!master->num_chipselect)
+		master->num_chipselect = 2; /* default */
+
 	master->bus_num = pdev->id;
 	master->setup = rspi_setup;
 	master->transfer = rspi_transfer;
@@ -832,11 +1003,32 @@
 	return ret;
 }
 
+static struct spi_ops rspi_ops = {
+	.set_config_register =		rspi_set_config_register,
+	.send_pio =			rspi_send_pio,
+	.receive_pio =			rspi_receive_pio,
+};
+
+static struct spi_ops qspi_ops = {
+	.set_config_register =		qspi_set_config_register,
+	.send_pio =			qspi_send_pio,
+	.receive_pio =			qspi_receive_pio,
+};
+
+static struct platform_device_id spi_driver_ids[] = {
+	{ "rspi",	(kernel_ulong_t)&rspi_ops },
+	{ "qspi",	(kernel_ulong_t)&qspi_ops },
+	{},
+};
+
+MODULE_DEVICE_TABLE(platform, spi_driver_ids);
+
 static struct platform_driver rspi_driver = {
 	.probe =	rspi_probe,
 	.remove =	rspi_remove,
+	.id_table =	spi_driver_ids,
 	.driver		= {
-		.name = "rspi",
+		.name = "renesas_spi",
 		.owner	= THIS_MODULE,
 	},
 };
diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c
index ce318d9..0dc32a1 100644
--- a/drivers/spi/spi-s3c24xx.c
+++ b/drivers/spi/spi-s3c24xx.c
@@ -280,7 +280,7 @@
  * so the caller does not need to do anything more than start the transfer
  * as normal, since the IRQ will have been re-routed to the FIQ handler.
 */
-void s3c24xx_spi_tryfiq(struct s3c24xx_spi *hw)
+static void s3c24xx_spi_tryfiq(struct s3c24xx_spi *hw)
 {
 	struct pt_regs regs;
 	enum spi_fiq_mode mode;
@@ -524,7 +524,7 @@
 	hw = spi_master_get_devdata(master);
 	memset(hw, 0, sizeof(struct s3c24xx_spi));
 
-	hw->master = spi_master_get(master);
+	hw->master = master;
 	hw->pdata = pdata = dev_get_platdata(&pdev->dev);
 	hw->dev = &pdev->dev;
 
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index 512b889..9e2020d 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -205,7 +205,6 @@
 #endif
 	struct s3c64xx_spi_port_config	*port_conf;
 	unsigned int			port_id;
-	unsigned long			gpios[4];
 	bool				cs_gpio;
 };
 
@@ -559,25 +558,18 @@
 static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd,
 						struct spi_device *spi)
 {
-	struct s3c64xx_spi_csinfo *cs;
-
 	if (sdd->tgl_spi != NULL) { /* If last device toggled after mssg */
 		if (sdd->tgl_spi != spi) { /* if last mssg on diff device */
 			/* Deselect the last toggled device */
-			cs = sdd->tgl_spi->controller_data;
-			if (sdd->cs_gpio)
-				gpio_set_value(cs->line,
+			if (spi->cs_gpio >= 0)
+				gpio_set_value(spi->cs_gpio,
 					spi->mode & SPI_CS_HIGH ? 0 : 1);
 		}
 		sdd->tgl_spi = NULL;
 	}
 
-	cs = spi->controller_data;
-	if (sdd->cs_gpio)
-		gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0);
-
-	/* Start the signals */
-	writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
+	if (spi->cs_gpio >= 0)
+		gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH ? 1 : 0);
 }
 
 static u32 s3c64xx_spi_wait_for_timeout(struct s3c64xx_spi_driver_data *sdd,
@@ -702,16 +694,11 @@
 static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd,
 						struct spi_device *spi)
 {
-	struct s3c64xx_spi_csinfo *cs = spi->controller_data;
-
 	if (sdd->tgl_spi == spi)
 		sdd->tgl_spi = NULL;
 
-	if (sdd->cs_gpio)
-		gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1);
-
-	/* Quiese the signals */
-	writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
+	if (spi->cs_gpio >= 0)
+		gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH ? 0 : 1);
 }
 
 static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
@@ -862,16 +849,12 @@
 	}
 }
 
-static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
-					    struct spi_message *msg)
+static int s3c64xx_spi_prepare_message(struct spi_master *master,
+				       struct spi_message *msg)
 {
 	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
 	struct spi_device *spi = msg->spi;
 	struct s3c64xx_spi_csinfo *cs = spi->controller_data;
-	struct spi_transfer *xfer;
-	int status = 0, cs_toggle = 0;
-	u32 speed;
-	u8 bpw;
 
 	/* If Master's(controller) state differs from that needed by Slave */
 	if (sdd->cur_speed != spi->max_speed_hz
@@ -887,107 +870,99 @@
 	if (s3c64xx_spi_map_mssg(sdd, msg)) {
 		dev_err(&spi->dev,
 			"Xfer: Unable to map message buffers!\n");
-		status = -ENOMEM;
-		goto out;
+		return -ENOMEM;
 	}
 
 	/* Configure feedback delay */
 	writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK);
 
-	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+	return 0;
+}
 
-		unsigned long flags;
-		int use_dma;
+static int s3c64xx_spi_transfer_one(struct spi_master *master,
+				    struct spi_device *spi,
+				    struct spi_transfer *xfer)
+{
+	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
+	int status;
+	u32 speed;
+	u8 bpw;
+	unsigned long flags;
+	int use_dma;
 
-		INIT_COMPLETION(sdd->xfer_completion);
+	INIT_COMPLETION(sdd->xfer_completion);
 
-		/* Only BPW and Speed may change across transfers */
-		bpw = xfer->bits_per_word;
-		speed = xfer->speed_hz ? : spi->max_speed_hz;
+	/* Only BPW and Speed may change across transfers */
+	bpw = xfer->bits_per_word;
+	speed = xfer->speed_hz ? : spi->max_speed_hz;
 
-		if (xfer->len % (bpw / 8)) {
-			dev_err(&spi->dev,
-				"Xfer length(%u) not a multiple of word size(%u)\n",
-				xfer->len, bpw / 8);
-			status = -EIO;
-			goto out;
+	if (xfer->len % (bpw / 8)) {
+		dev_err(&spi->dev,
+			"Xfer length(%u) not a multiple of word size(%u)\n",
+			xfer->len, bpw / 8);
+		return -EIO;
+	}
+
+	if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
+		sdd->cur_bpw = bpw;
+		sdd->cur_speed = speed;
+		s3c64xx_spi_config(sdd);
+	}
+
+	/* Polling method for xfers not bigger than FIFO capacity */
+	use_dma = 0;
+	if (!is_polling(sdd) &&
+	    (sdd->rx_dma.ch && sdd->tx_dma.ch &&
+	     (xfer->len > ((FIFO_LVL_MASK(sdd) >> 1) + 1))))
+		use_dma = 1;
+
+	spin_lock_irqsave(&sdd->lock, flags);
+
+	/* Pending only which is to be done */
+	sdd->state &= ~RXBUSY;
+	sdd->state &= ~TXBUSY;
+
+	enable_datapath(sdd, spi, xfer, use_dma);
+
+	/* Start the signals */
+	writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
+
+	/* Start the signals */
+	writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
+
+	spin_unlock_irqrestore(&sdd->lock, flags);
+
+	status = wait_for_xfer(sdd, xfer, use_dma);
+
+	if (status) {
+		dev_err(&spi->dev, "I/O Error: rx-%d tx-%d res:rx-%c tx-%c len-%d\n",
+			xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0,
+			(sdd->state & RXBUSY) ? 'f' : 'p',
+			(sdd->state & TXBUSY) ? 'f' : 'p',
+			xfer->len);
+
+		if (use_dma) {
+			if (xfer->tx_buf != NULL
+			    && (sdd->state & TXBUSY))
+				s3c64xx_spi_dma_stop(sdd, &sdd->tx_dma);
+			if (xfer->rx_buf != NULL
+			    && (sdd->state & RXBUSY))
+				s3c64xx_spi_dma_stop(sdd, &sdd->rx_dma);
 		}
-
-		if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
-			sdd->cur_bpw = bpw;
-			sdd->cur_speed = speed;
-			s3c64xx_spi_config(sdd);
-		}
-
-		/* Polling method for xfers not bigger than FIFO capacity */
-		use_dma = 0;
-		if (!is_polling(sdd) &&
-			(sdd->rx_dma.ch && sdd->tx_dma.ch &&
-			(xfer->len > ((FIFO_LVL_MASK(sdd) >> 1) + 1))))
-			use_dma = 1;
-
-		spin_lock_irqsave(&sdd->lock, flags);
-
-		/* Pending only which is to be done */
-		sdd->state &= ~RXBUSY;
-		sdd->state &= ~TXBUSY;
-
-		enable_datapath(sdd, spi, xfer, use_dma);
-
-		/* Slave Select */
-		enable_cs(sdd, spi);
-
-		spin_unlock_irqrestore(&sdd->lock, flags);
-
-		status = wait_for_xfer(sdd, xfer, use_dma);
-
-		if (status) {
-			dev_err(&spi->dev, "I/O Error: rx-%d tx-%d res:rx-%c tx-%c len-%d\n",
-				xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0,
-				(sdd->state & RXBUSY) ? 'f' : 'p',
-				(sdd->state & TXBUSY) ? 'f' : 'p',
-				xfer->len);
-
-			if (use_dma) {
-				if (xfer->tx_buf != NULL
-						&& (sdd->state & TXBUSY))
-					s3c64xx_spi_dma_stop(sdd, &sdd->tx_dma);
-				if (xfer->rx_buf != NULL
-						&& (sdd->state & RXBUSY))
-					s3c64xx_spi_dma_stop(sdd, &sdd->rx_dma);
-			}
-
-			goto out;
-		}
-
-		if (xfer->delay_usecs)
-			udelay(xfer->delay_usecs);
-
-		if (xfer->cs_change) {
-			/* Hint that the next mssg is gonna be
-			   for the same device */
-			if (list_is_last(&xfer->transfer_list,
-						&msg->transfers))
-				cs_toggle = 1;
-		}
-
-		msg->actual_length += xfer->len;
-
+	} else {
 		flush_fifo(sdd);
 	}
 
-out:
-	if (!cs_toggle || status)
-		disable_cs(sdd, spi);
-	else
-		sdd->tgl_spi = spi;
+	return status;
+}
+
+static int s3c64xx_spi_unprepare_message(struct spi_master *master,
+					    struct spi_message *msg)
+{
+	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
 
 	s3c64xx_spi_unmap_mssg(sdd, msg);
 
-	msg->status = status;
-
-	spi_finalize_current_message(master);
-
 	return 0;
 }
 
@@ -1071,6 +1046,8 @@
 					cs->line, err);
 				goto err_gpio_req;
 			}
+
+			spi->cs_gpio = cs->line;
 		}
 
 		spi_set_ctldata(spi, cs);
@@ -1117,11 +1094,14 @@
 	}
 
 	pm_runtime_put(&sdd->pdev->dev);
+	writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
 	disable_cs(sdd, spi);
 	return 0;
 
 setup_exit:
+	pm_runtime_put(&sdd->pdev->dev);
 	/* setup() returns with device de-selected */
+	writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
 	disable_cs(sdd, spi);
 
 	gpio_free(cs->line);
@@ -1140,8 +1120,8 @@
 	struct s3c64xx_spi_driver_data *sdd;
 
 	sdd = spi_master_get_devdata(spi->master);
-	if (cs && sdd->cs_gpio) {
-		gpio_free(cs->line);
+	if (spi->cs_gpio) {
+		gpio_free(spi->cs_gpio);
 		if (spi->dev.of_node)
 			kfree(cs);
 	}
@@ -1359,7 +1339,9 @@
 	master->setup = s3c64xx_spi_setup;
 	master->cleanup = s3c64xx_spi_cleanup;
 	master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer;
-	master->transfer_one_message = s3c64xx_spi_transfer_one_message;
+	master->prepare_message = s3c64xx_spi_prepare_message;
+	master->transfer_one = s3c64xx_spi_transfer_one;
+	master->unprepare_message = s3c64xx_spi_unprepare_message;
 	master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer;
 	master->num_chipselect = sci->num_cs;
 	master->dma_alignment = 8;
@@ -1428,9 +1410,12 @@
 	       S3C64XX_SPI_INT_TX_OVERRUN_EN | S3C64XX_SPI_INT_TX_UNDERRUN_EN,
 	       sdd->regs + S3C64XX_SPI_INT_EN);
 
-	if (spi_register_master(master)) {
-		dev_err(&pdev->dev, "cannot register SPI master\n");
-		ret = -EBUSY;
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
+	ret = devm_spi_register_master(&pdev->dev, master);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "cannot register SPI master: %d\n", ret);
 		goto err3;
 	}
 
@@ -1440,8 +1425,6 @@
 					mem_res,
 					sdd->rx_dma.dmach, sdd->tx_dma.dmach);
 
-	pm_runtime_enable(&pdev->dev);
-
 	return 0;
 
 err3:
@@ -1461,16 +1444,12 @@
 
 	pm_runtime_disable(&pdev->dev);
 
-	spi_unregister_master(master);
-
 	writel(0, sdd->regs + S3C64XX_SPI_INT_EN);
 
 	clk_disable_unprepare(sdd->src_clk);
 
 	clk_disable_unprepare(sdd->clk);
 
-	spi_master_put(master);
-
 	return 0;
 }
 
@@ -1480,11 +1459,14 @@
 	struct spi_master *master = dev_get_drvdata(dev);
 	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
 
-	spi_master_suspend(master);
+	int ret = spi_master_suspend(master);
+	if (ret)
+		return ret;
 
-	/* Disable the clock */
-	clk_disable_unprepare(sdd->src_clk);
-	clk_disable_unprepare(sdd->clk);
+	if (!pm_runtime_suspended(dev)) {
+		clk_disable_unprepare(sdd->clk);
+		clk_disable_unprepare(sdd->src_clk);
+	}
 
 	sdd->cur_speed = 0; /* Output Clock is stopped */
 
@@ -1500,15 +1482,14 @@
 	if (sci->cfg_gpio)
 		sci->cfg_gpio();
 
-	/* Enable the clock */
-	clk_prepare_enable(sdd->src_clk);
-	clk_prepare_enable(sdd->clk);
+	if (!pm_runtime_suspended(dev)) {
+		clk_prepare_enable(sdd->src_clk);
+		clk_prepare_enable(sdd->clk);
+	}
 
 	s3c64xx_spi_hwinit(sdd, sdd->port_id);
 
-	spi_master_resume(master);
-
-	return 0;
+	return spi_master_resume(master);
 }
 #endif /* CONFIG_PM_SLEEP */
 
@@ -1528,9 +1509,17 @@
 {
 	struct spi_master *master = dev_get_drvdata(dev);
 	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
+	int ret;
 
-	clk_prepare_enable(sdd->src_clk);
-	clk_prepare_enable(sdd->clk);
+	ret = clk_prepare_enable(sdd->src_clk);
+	if (ret != 0)
+		return ret;
+
+	ret = clk_prepare_enable(sdd->clk);
+	if (ret != 0) {
+		clk_disable_unprepare(sdd->src_clk);
+		return ret;
+	}
 
 	return 0;
 }
@@ -1616,6 +1605,18 @@
 };
 
 static const struct of_device_id s3c64xx_spi_dt_match[] = {
+	{ .compatible = "samsung,s3c2443-spi",
+			.data = (void *)&s3c2443_spi_port_config,
+	},
+	{ .compatible = "samsung,s3c6410-spi",
+			.data = (void *)&s3c6410_spi_port_config,
+	},
+	{ .compatible = "samsung,s5pc100-spi",
+			.data = (void *)&s5pc100_spi_port_config,
+	},
+	{ .compatible = "samsung,s5pv210-spi",
+			.data = (void *)&s5pv210_spi_port_config,
+	},
 	{ .compatible = "samsung,exynos4210-spi",
 			.data = (void *)&exynos4_spi_port_config,
 	},
@@ -1633,22 +1634,13 @@
 		.pm = &s3c64xx_spi_pm,
 		.of_match_table = of_match_ptr(s3c64xx_spi_dt_match),
 	},
+	.probe = s3c64xx_spi_probe,
 	.remove = s3c64xx_spi_remove,
 	.id_table = s3c64xx_spi_driver_ids,
 };
 MODULE_ALIAS("platform:s3c64xx-spi");
 
-static int __init s3c64xx_spi_init(void)
-{
-	return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe);
-}
-subsys_initcall(s3c64xx_spi_init);
-
-static void __exit s3c64xx_spi_exit(void)
-{
-	platform_driver_unregister(&s3c64xx_spi_driver);
-}
-module_exit(s3c64xx_spi_exit);
+module_platform_driver(s3c64xx_spi_driver);
 
 MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
 MODULE_DESCRIPTION("S3C64XX SPI Controller Driver");
diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c
index 0b68cb5..292567a 100644
--- a/drivers/spi/spi-sh-hspi.c
+++ b/drivers/spi/spi-sh-hspi.c
@@ -137,7 +137,7 @@
 			rate /= 16;
 
 		/* CLKCx calculation */
-		rate /= (((idiv_clk & 0x1F) + 1) * 2) ;
+		rate /= (((idiv_clk & 0x1F) + 1) * 2);
 
 		/* save best settings */
 		tmp = abs(target_rate - rate);
@@ -296,21 +296,22 @@
 		goto error1;
 	}
 
+	pm_runtime_enable(&pdev->dev);
+
 	master->num_chipselect	= 1;
 	master->bus_num		= pdev->id;
 	master->setup		= hspi_setup;
 	master->cleanup		= hspi_cleanup;
 	master->mode_bits	= SPI_CPOL | SPI_CPHA;
+	master->dev.of_node	= pdev->dev.of_node;
 	master->auto_runtime_pm = true;
 	master->transfer_one_message		= hspi_transfer_one_message;
-	ret = spi_register_master(master);
+	ret = devm_spi_register_master(&pdev->dev, master);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "spi_register_master error.\n");
 		goto error1;
 	}
 
-	pm_runtime_enable(&pdev->dev);
-
 	return 0;
 
  error1:
@@ -328,17 +329,23 @@
 	pm_runtime_disable(&pdev->dev);
 
 	clk_put(hspi->clk);
-	spi_unregister_master(hspi->master);
 
 	return 0;
 }
 
+static struct of_device_id hspi_of_match[] = {
+	{ .compatible = "renesas,hspi", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, hspi_of_match);
+
 static struct platform_driver hspi_driver = {
 	.probe = hspi_probe,
 	.remove = hspi_remove,
 	.driver = {
 		.name = "sh-hspi",
 		.owner = THIS_MODULE,
+		.of_match_table = hspi_of_match,
 	},
 };
 module_platform_driver(hspi_driver);
diff --git a/drivers/spi/spi-sh-sci.c b/drivers/spi/spi-sh-sci.c
index 8eefeb6..38eb24d 100644
--- a/drivers/spi/spi-sh-sci.c
+++ b/drivers/spi/spi-sh-sci.c
@@ -133,7 +133,7 @@
 	sp->info = dev_get_platdata(&dev->dev);
 
 	/* setup spi bitbang adaptor */
-	sp->bitbang.master = spi_master_get(master);
+	sp->bitbang.master = master;
 	sp->bitbang.master->bus_num = sp->info->bus_num;
 	sp->bitbang.master->num_chipselect = sp->info->num_chipselect;
 	sp->bitbang.chipselect = sh_sci_spi_chipselect;
diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c
index a1f21b7..592b4af 100644
--- a/drivers/spi/spi-sirf.c
+++ b/drivers/spi/spi-sirf.c
@@ -632,7 +632,7 @@
 	if (ret)
 		goto free_master;
 
-	sspi->bitbang.master = spi_master_get(master);
+	sspi->bitbang.master = master;
 	sspi->bitbang.chipselect = spi_sirfsoc_chipselect;
 	sspi->bitbang.setup_transfer = spi_sirfsoc_setup_transfer;
 	sspi->bitbang.txrx_bufs = spi_sirfsoc_transfer;
diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 145dd43..9146bb3 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -182,6 +182,7 @@
 	u32					cur_speed;
 
 	struct spi_device			*cur_spi;
+	struct spi_device			*cs_control;
 	unsigned				cur_pos;
 	unsigned				cur_len;
 	unsigned				words_per_32bit;
@@ -267,7 +268,7 @@
 	unsigned max_len;
 	unsigned total_fifo_words;
 
-	tspi->bytes_per_word = (bits_per_word - 1) / 8 + 1;
+	tspi->bytes_per_word = DIV_ROUND_UP(bits_per_word, 8);
 
 	if (bits_per_word == 8 || bits_per_word == 16) {
 		tspi->is_packed = 1;
@@ -676,15 +677,12 @@
 	dma_release_channel(dma_chan);
 }
 
-static int tegra_spi_start_transfer_one(struct spi_device *spi,
-		struct spi_transfer *t, bool is_first_of_msg,
-		bool is_single_xfer)
+static unsigned long tegra_spi_setup_transfer_one(struct spi_device *spi,
+		struct spi_transfer *t, bool is_first_of_msg)
 {
 	struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
 	u32 speed = t->speed_hz;
 	u8 bits_per_word = t->bits_per_word;
-	unsigned total_fifo_words;
-	int ret;
 	unsigned long command1;
 	int req_mode;
 
@@ -698,7 +696,6 @@
 	tspi->cur_rx_pos = 0;
 	tspi->cur_tx_pos = 0;
 	tspi->curr_xfer = t;
-	total_fifo_words = tegra_spi_calculate_curr_xfer_param(spi, tspi, t);
 
 	if (is_first_of_msg) {
 		tegra_spi_clear_status(tspi);
@@ -717,7 +714,12 @@
 		else if (req_mode == SPI_MODE_3)
 			command1 |= SPI_CONTROL_MODE_3;
 
-		tegra_spi_writel(tspi, command1, SPI_COMMAND1);
+		if (tspi->cs_control) {
+			if (tspi->cs_control != spi)
+				tegra_spi_writel(tspi, command1, SPI_COMMAND1);
+			tspi->cs_control = NULL;
+		} else
+			tegra_spi_writel(tspi, command1, SPI_COMMAND1);
 
 		command1 |= SPI_CS_SW_HW;
 		if (spi->mode & SPI_CS_HIGH)
@@ -732,6 +734,18 @@
 		command1 |= SPI_BIT_LENGTH(bits_per_word - 1);
 	}
 
+	return command1;
+}
+
+static int tegra_spi_start_transfer_one(struct spi_device *spi,
+		struct spi_transfer *t, unsigned long command1)
+{
+	struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
+	unsigned total_fifo_words;
+	int ret;
+
+	total_fifo_words = tegra_spi_calculate_curr_xfer_param(spi, tspi, t);
+
 	if (tspi->is_packed)
 		command1 |= SPI_PACKED;
 
@@ -803,29 +817,50 @@
 	return 0;
 }
 
+static void tegra_spi_transfer_delay(int delay)
+{
+	if (!delay)
+		return;
+
+	if (delay >= 1000)
+		mdelay(delay / 1000);
+
+	udelay(delay % 1000);
+}
+
 static int tegra_spi_transfer_one_message(struct spi_master *master,
 			struct spi_message *msg)
 {
 	bool is_first_msg = true;
-	int single_xfer;
 	struct tegra_spi_data *tspi = spi_master_get_devdata(master);
 	struct spi_transfer *xfer;
 	struct spi_device *spi = msg->spi;
 	int ret;
+	bool skip = false;
 
 	msg->status = 0;
 	msg->actual_length = 0;
 
-	single_xfer = list_is_singular(&msg->transfers);
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+		unsigned long cmd1;
+
 		INIT_COMPLETION(tspi->xfer_completion);
-		ret = tegra_spi_start_transfer_one(spi, xfer,
-					is_first_msg, single_xfer);
+
+		cmd1 = tegra_spi_setup_transfer_one(spi, xfer, is_first_msg);
+
+		if (!xfer->len) {
+			ret = 0;
+			skip = true;
+			goto complete_xfer;
+		}
+
+		ret = tegra_spi_start_transfer_one(spi, xfer, cmd1);
 		if (ret < 0) {
 			dev_err(tspi->dev,
 				"spi can not start transfer, err %d\n", ret);
-			goto exit;
+			goto complete_xfer;
 		}
+
 		is_first_msg = false;
 		ret = wait_for_completion_timeout(&tspi->xfer_completion,
 						SPI_DMA_TIMEOUT);
@@ -833,24 +868,40 @@
 			dev_err(tspi->dev,
 				"spi trasfer timeout, err %d\n", ret);
 			ret = -EIO;
-			goto exit;
+			goto complete_xfer;
 		}
 
 		if (tspi->tx_status ||  tspi->rx_status) {
 			dev_err(tspi->dev, "Error in Transfer\n");
 			ret = -EIO;
-			goto exit;
+			goto complete_xfer;
 		}
 		msg->actual_length += xfer->len;
-		if (xfer->cs_change && xfer->delay_usecs) {
+
+complete_xfer:
+		if (ret < 0 || skip) {
 			tegra_spi_writel(tspi, tspi->def_command1_reg,
 					SPI_COMMAND1);
-			udelay(xfer->delay_usecs);
+			tegra_spi_transfer_delay(xfer->delay_usecs);
+			goto exit;
+		} else if (msg->transfers.prev == &xfer->transfer_list) {
+			/* This is the last transfer in message */
+			if (xfer->cs_change)
+				tspi->cs_control = spi;
+			else {
+				tegra_spi_writel(tspi, tspi->def_command1_reg,
+						SPI_COMMAND1);
+				tegra_spi_transfer_delay(xfer->delay_usecs);
+			}
+		} else if (xfer->cs_change) {
+			tegra_spi_writel(tspi, tspi->def_command1_reg,
+					SPI_COMMAND1);
+			tegra_spi_transfer_delay(xfer->delay_usecs);
 		}
+
 	}
 	ret = 0;
 exit:
-	tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1);
 	msg->status = ret;
 	spi_finalize_current_message(master);
 	return ret;
@@ -1115,7 +1166,7 @@
 	pm_runtime_put(&pdev->dev);
 
 	master->dev.of_node = pdev->dev.of_node;
-	ret = spi_register_master(master);
+	ret = devm_spi_register_master(&pdev->dev, master);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "can not register to master err %d\n", ret);
 		goto exit_pm_disable;
@@ -1142,7 +1193,6 @@
 	struct tegra_spi_data	*tspi = spi_master_get_devdata(master);
 
 	free_irq(tspi->irq, tspi);
-	spi_unregister_master(master);
 
 	if (tspi->tx_dma_chan)
 		tegra_spi_deinit_dma_param(tspi, false);
diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c
index 1d814dc..79be8ce 100644
--- a/drivers/spi/spi-tegra20-sflash.c
+++ b/drivers/spi/spi-tegra20-sflash.c
@@ -173,7 +173,7 @@
 	unsigned remain_len = t->len - tsd->cur_pos;
 	unsigned max_word;
 
-	tsd->bytes_per_word = (t->bits_per_word - 1) / 8 + 1;
+	tsd->bytes_per_word = DIV_ROUND_UP(t->bits_per_word, 8);
 	max_word = remain_len / tsd->bytes_per_word;
 	if (max_word > SPI_FIFO_DEPTH)
 		max_word = SPI_FIFO_DEPTH;
@@ -529,7 +529,7 @@
 	pm_runtime_put(&pdev->dev);
 
 	master->dev.of_node = pdev->dev.of_node;
-	ret = spi_register_master(master);
+	ret = devm_spi_register_master(&pdev->dev, master);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "can not register to master err %d\n", ret);
 		goto exit_pm_disable;
@@ -553,7 +553,6 @@
 	struct tegra_sflash_data	*tsd = spi_master_get_devdata(master);
 
 	free_irq(tsd->irq, tsd);
-	spi_unregister_master(master);
 
 	pm_runtime_disable(&pdev->dev);
 	if (!pm_runtime_status_suspended(&pdev->dev))
diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c
index c703536..af0a678 100644
--- a/drivers/spi/spi-tegra20-slink.c
+++ b/drivers/spi/spi-tegra20-slink.c
@@ -278,12 +278,12 @@
 {
 	unsigned remain_len = t->len - tspi->cur_pos;
 	unsigned max_word;
-	unsigned bits_per_word ;
+	unsigned bits_per_word;
 	unsigned max_len;
 	unsigned total_fifo_words;
 
 	bits_per_word = t->bits_per_word;
-	tspi->bytes_per_word = (bits_per_word - 1) / 8 + 1;
+	tspi->bytes_per_word = DIV_ROUND_UP(bits_per_word, 8);
 
 	if (bits_per_word == 8 || bits_per_word == 16) {
 		tspi->is_packed = 1;
@@ -707,8 +707,7 @@
 }
 
 static int tegra_slink_start_transfer_one(struct spi_device *spi,
-		struct spi_transfer *t, bool is_first_of_msg,
-		bool is_single_xfer)
+		struct spi_transfer *t)
 {
 	struct tegra_slink_data *tspi = spi_master_get_devdata(spi->master);
 	u32 speed;
@@ -732,32 +731,12 @@
 	tspi->curr_xfer = t;
 	total_fifo_words = tegra_slink_calculate_curr_xfer_param(spi, tspi, t);
 
-	if (is_first_of_msg) {
-		tegra_slink_clear_status(tspi);
+	command = tspi->command_reg;
+	command &= ~SLINK_BIT_LENGTH(~0);
+	command |= SLINK_BIT_LENGTH(bits_per_word - 1);
 
-		command = tspi->def_command_reg;
-		command |= SLINK_BIT_LENGTH(bits_per_word - 1);
-		command |= SLINK_CS_SW | SLINK_CS_VALUE;
-
-		command2 = tspi->def_command2_reg;
-		command2 |= SLINK_SS_EN_CS(spi->chip_select);
-
-		command &= ~SLINK_MODES;
-		if (spi->mode & SPI_CPHA)
-			command |= SLINK_CK_SDA;
-
-		if (spi->mode & SPI_CPOL)
-			command |= SLINK_IDLE_SCLK_DRIVE_HIGH;
-		else
-			command |= SLINK_IDLE_SCLK_DRIVE_LOW;
-	} else {
-		command = tspi->command_reg;
-		command &= ~SLINK_BIT_LENGTH(~0);
-		command |= SLINK_BIT_LENGTH(bits_per_word - 1);
-
-		command2 = tspi->command2_reg;
-		command2 &= ~(SLINK_RXEN | SLINK_TXEN);
-	}
+	command2 = tspi->command2_reg;
+	command2 &= ~(SLINK_RXEN | SLINK_TXEN);
 
 	tegra_slink_writel(tspi, command, SLINK_COMMAND);
 	tspi->command_reg = command;
@@ -824,58 +803,72 @@
 	return 0;
 }
 
-static int tegra_slink_transfer_one_message(struct spi_master *master,
-			struct spi_message *msg)
+static int tegra_slink_prepare_message(struct spi_master *master,
+				       struct spi_message *msg)
 {
-	bool is_first_msg = true;
-	int single_xfer;
 	struct tegra_slink_data *tspi = spi_master_get_devdata(master);
-	struct spi_transfer *xfer;
 	struct spi_device *spi = msg->spi;
+
+	tegra_slink_clear_status(tspi);
+
+	tspi->command_reg = tspi->def_command_reg;
+	tspi->command_reg |= SLINK_CS_SW | SLINK_CS_VALUE;
+
+	tspi->command2_reg = tspi->def_command2_reg;
+	tspi->command2_reg |= SLINK_SS_EN_CS(spi->chip_select);
+
+	tspi->command_reg &= ~SLINK_MODES;
+	if (spi->mode & SPI_CPHA)
+		tspi->command_reg |= SLINK_CK_SDA;
+
+	if (spi->mode & SPI_CPOL)
+		tspi->command_reg |= SLINK_IDLE_SCLK_DRIVE_HIGH;
+	else
+		tspi->command_reg |= SLINK_IDLE_SCLK_DRIVE_LOW;
+
+	return 0;
+}
+
+static int tegra_slink_transfer_one(struct spi_master *master,
+				    struct spi_device *spi,
+				    struct spi_transfer *xfer)
+{
+	struct tegra_slink_data *tspi = spi_master_get_devdata(master);
 	int ret;
 
-	msg->status = 0;
-	msg->actual_length = 0;
-
-	single_xfer = list_is_singular(&msg->transfers);
-	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-		INIT_COMPLETION(tspi->xfer_completion);
-		ret = tegra_slink_start_transfer_one(spi, xfer,
-					is_first_msg, single_xfer);
-		if (ret < 0) {
-			dev_err(tspi->dev,
-				"spi can not start transfer, err %d\n", ret);
-			goto exit;
-		}
-		is_first_msg = false;
-		ret = wait_for_completion_timeout(&tspi->xfer_completion,
-						SLINK_DMA_TIMEOUT);
-		if (WARN_ON(ret == 0)) {
-			dev_err(tspi->dev,
-				"spi trasfer timeout, err %d\n", ret);
-			ret = -EIO;
-			goto exit;
-		}
-
-		if (tspi->tx_status ||  tspi->rx_status) {
-			dev_err(tspi->dev, "Error in Transfer\n");
-			ret = -EIO;
-			goto exit;
-		}
-		msg->actual_length += xfer->len;
-		if (xfer->cs_change && xfer->delay_usecs) {
-			tegra_slink_writel(tspi, tspi->def_command_reg,
-					SLINK_COMMAND);
-			udelay(xfer->delay_usecs);
-		}
+	INIT_COMPLETION(tspi->xfer_completion);
+	ret = tegra_slink_start_transfer_one(spi, xfer);
+	if (ret < 0) {
+		dev_err(tspi->dev,
+			"spi can not start transfer, err %d\n", ret);
+		return ret;
 	}
-	ret = 0;
-exit:
+
+	ret = wait_for_completion_timeout(&tspi->xfer_completion,
+					  SLINK_DMA_TIMEOUT);
+	if (WARN_ON(ret == 0)) {
+		dev_err(tspi->dev,
+			"spi trasfer timeout, err %d\n", ret);
+		return -EIO;
+	}
+
+	if (tspi->tx_status)
+		return tspi->tx_status;
+	if (tspi->rx_status)
+		return tspi->rx_status;
+
+	return 0;
+}
+
+static int tegra_slink_unprepare_message(struct spi_master *master,
+					 struct spi_message *msg)
+{
+	struct tegra_slink_data *tspi = spi_master_get_devdata(master);
+
 	tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND);
 	tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2);
-	msg->status = ret;
-	spi_finalize_current_message(master);
-	return ret;
+
+	return 0;
 }
 
 static irqreturn_t handle_cpu_based_xfer(struct tegra_slink_data *tspi)
@@ -1078,7 +1071,9 @@
 	/* the spi->mode bits understood by this driver: */
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 	master->setup = tegra_slink_setup;
-	master->transfer_one_message = tegra_slink_transfer_one_message;
+	master->prepare_message = tegra_slink_prepare_message;
+	master->transfer_one = tegra_slink_transfer_one;
+	master->unprepare_message = tegra_slink_unprepare_message;
 	master->auto_runtime_pm = true;
 	master->num_chipselect = MAX_CHIP_SELECT;
 	master->bus_num = -1;
@@ -1164,7 +1159,7 @@
 	pm_runtime_put(&pdev->dev);
 
 	master->dev.of_node = pdev->dev.of_node;
-	ret = spi_register_master(master);
+	ret = devm_spi_register_master(&pdev->dev, master);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "can not register to master err %d\n", ret);
 		goto exit_pm_disable;
@@ -1191,7 +1186,6 @@
 	struct tegra_slink_data	*tspi = spi_master_get_devdata(master);
 
 	free_irq(tspi->irq, tspi);
-	spi_unregister_master(master);
 
 	if (tspi->tx_dma_chan)
 		tegra_slink_deinit_dma_param(tspi, false);
diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c
index e12d962..0b71270 100644
--- a/drivers/spi/spi-ti-qspi.c
+++ b/drivers/spi/spi-ti-qspi.c
@@ -41,9 +41,6 @@
 struct ti_qspi {
 	struct completion       transfer_complete;
 
-	/* IRQ synchronization */
-	spinlock_t              lock;
-
 	/* list synchronization */
 	struct mutex            list_lock;
 
@@ -57,7 +54,6 @@
 	u32 spi_max_frequency;
 	u32 cmd;
 	u32 dc;
-	u32 stat;
 };
 
 #define QSPI_PID			(0x0)
@@ -397,13 +393,12 @@
 {
 	struct ti_qspi *qspi = dev_id;
 	u16 int_stat;
+	u32 stat;
 
 	irqreturn_t ret = IRQ_HANDLED;
 
-	spin_lock(&qspi->lock);
-
 	int_stat = ti_qspi_read(qspi, QSPI_INTR_STATUS_ENABLED_CLEAR);
-	qspi->stat = ti_qspi_read(qspi, QSPI_SPI_STATUS_REG);
+	stat = ti_qspi_read(qspi, QSPI_SPI_STATUS_REG);
 
 	if (!int_stat) {
 		dev_dbg(qspi->dev, "No IRQ triggered\n");
@@ -411,33 +406,12 @@
 		goto out;
 	}
 
-	ret = IRQ_WAKE_THREAD;
-
-	ti_qspi_write(qspi, QSPI_WC_INT_DISABLE, QSPI_INTR_ENABLE_CLEAR_REG);
 	ti_qspi_write(qspi, QSPI_WC_INT_DISABLE,
 				QSPI_INTR_STATUS_ENABLED_CLEAR);
-
-out:
-	spin_unlock(&qspi->lock);
-
-	return ret;
-}
-
-static irqreturn_t ti_qspi_threaded_isr(int this_irq, void *dev_id)
-{
-	struct ti_qspi *qspi = dev_id;
-	unsigned long flags;
-
-	spin_lock_irqsave(&qspi->lock, flags);
-
-	if (qspi->stat & WC)
+	if (stat & WC)
 		complete(&qspi->transfer_complete);
-
-	spin_unlock_irqrestore(&qspi->lock, flags);
-
-	ti_qspi_write(qspi, QSPI_WC_INT_EN, QSPI_INTR_ENABLE_SET_REG);
-
-	return IRQ_HANDLED;
+out:
+	return ret;
 }
 
 static int ti_qspi_runtime_resume(struct device *dev)
@@ -472,7 +446,7 @@
 	if (!master)
 		return -ENOMEM;
 
-	master->mode_bits = SPI_CPOL | SPI_CPHA;
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD;
 
 	master->bus_num = -1;
 	master->flags = SPI_MASTER_HALF_DUPLEX;
@@ -499,7 +473,6 @@
 		return irq;
 	}
 
-	spin_lock_init(&qspi->lock);
 	mutex_init(&qspi->list_lock);
 
 	qspi->base = devm_ioremap_resource(&pdev->dev, r);
@@ -508,8 +481,7 @@
 		goto free_master;
 	}
 
-	ret = devm_request_threaded_irq(&pdev->dev, irq, ti_qspi_isr,
-			ti_qspi_threaded_isr, 0,
+	ret = devm_request_irq(&pdev->dev, irq, ti_qspi_isr, 0,
 			dev_name(&pdev->dev), qspi);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n",
@@ -532,7 +504,7 @@
 	if (!of_property_read_u32(np, "spi-max-frequency", &max_freq))
 		qspi->spi_max_frequency = max_freq;
 
-	ret = spi_register_master(master);
+	ret = devm_spi_register_master(&pdev->dev, master);
 	if (ret)
 		goto free_master;
 
@@ -547,7 +519,7 @@
 {
 	struct	ti_qspi *qspi = platform_get_drvdata(pdev);
 
-	spi_unregister_master(qspi->master);
+	ti_qspi_write(qspi, QSPI_WC_INT_DISABLE, QSPI_INTR_ENABLE_CLEAR_REG);
 
 	return 0;
 }
@@ -558,7 +530,7 @@
 
 static struct platform_driver ti_qspi_driver = {
 	.probe	= ti_qspi_probe,
-	.remove	= ti_qspi_remove,
+	.remove = ti_qspi_remove,
 	.driver = {
 		.name	= "ti,dra7xxx-qspi",
 		.owner	= THIS_MODULE,
diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c
index eaeeed5..4461313 100644
--- a/drivers/spi/spi-topcliff-pch.c
+++ b/drivers/spi/spi-topcliff-pch.c
@@ -506,8 +506,8 @@
 		goto err_out;
 	}
 
-	dev_dbg(&pspi->dev, "%s Transfer List not empty. "
-		"Transfer Speed is set.\n", __func__);
+	dev_dbg(&pspi->dev,
+		"%s Transfer List not empty. Transfer Speed is set.\n", __func__);
 
 	spin_lock_irqsave(&data->lock, flags);
 	/* validate Tx/Rx buffers and Transfer length */
@@ -526,8 +526,9 @@
 			goto err_return_spinlock;
 		}
 
-		dev_dbg(&pspi->dev, "%s Tx/Rx buffer valid. Transfer length"
-			" valid\n", __func__);
+		dev_dbg(&pspi->dev,
+			"%s Tx/Rx buffer valid. Transfer length valid\n",
+			__func__);
 
 		/* if baud rate has been specified validate the same */
 		if (transfer->speed_hz > PCH_MAX_BAUDRATE)
@@ -1181,8 +1182,8 @@
 	spin_lock(&data->lock);
 	/* check if suspend has been initiated;if yes flush queue */
 	if (data->board_dat->suspend_sts || (data->status == STATUS_EXITING)) {
-		dev_dbg(&data->master->dev, "%s suspend/remove initiated,"
-			"flushing queue\n", __func__);
+		dev_dbg(&data->master->dev,
+			"%s suspend/remove initiated, flushing queue\n", __func__);
 		list_for_each_entry_safe(pmsg, tmp, data->queue.next, queue) {
 			pmsg->status = -EIO;
 
@@ -1410,13 +1411,13 @@
 	/* baseaddress + address offset) */
 	data->io_base_addr = pci_resource_start(board_dat->pdev, 1) +
 					 PCH_ADDRESS_SIZE * plat_dev->id;
-	data->io_remap_addr = pci_iomap(board_dat->pdev, 1, 0) +
-					 PCH_ADDRESS_SIZE * plat_dev->id;
+	data->io_remap_addr = pci_iomap(board_dat->pdev, 1, 0);
 	if (!data->io_remap_addr) {
 		dev_err(&plat_dev->dev, "%s pci_iomap failed\n", __func__);
 		ret = -ENOMEM;
 		goto err_pci_iomap;
 	}
+	data->io_remap_addr += PCH_ADDRESS_SIZE * plat_dev->id;
 
 	dev_dbg(&plat_dev->dev, "[ch%d] remap_addr=%p\n",
 		plat_dev->id, data->io_remap_addr);
diff --git a/drivers/spi/spi-txx9.c b/drivers/spi/spi-txx9.c
index 7c6d157..637cce2 100644
--- a/drivers/spi/spi-txx9.c
+++ b/drivers/spi/spi-txx9.c
@@ -177,7 +177,7 @@
 			| 0x08,
 			TXx9_SPCR0);
 
-	list_for_each_entry (t, &m->transfers, transfer_list) {
+	list_for_each_entry(t, &m->transfers, transfer_list) {
 		const void *txbuf = t->tx_buf;
 		void *rxbuf = t->rx_buf;
 		u32 data;
@@ -308,7 +308,7 @@
 	m->actual_length = 0;
 
 	/* check each transfer's parameters */
-	list_for_each_entry (t, &m->transfers, transfer_list) {
+	list_for_each_entry(t, &m->transfers, transfer_list) {
 		u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
 		u8 bits_per_word = t->bits_per_word;
 
@@ -406,7 +406,7 @@
 	master->num_chipselect = (u16)UINT_MAX; /* any GPIO numbers */
 	master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
 
-	ret = spi_register_master(master);
+	ret = devm_spi_register_master(&dev->dev, master);
 	if (ret)
 		goto exit;
 	return 0;
@@ -428,11 +428,9 @@
 	struct spi_master *master = spi_master_get(platform_get_drvdata(dev));
 	struct txx9spi *c = spi_master_get_devdata(master);
 
-	spi_unregister_master(master);
 	destroy_workqueue(c->workqueue);
 	clk_disable(c->clk);
 	clk_put(c->clk);
-	spi_master_put(master);
 	return 0;
 }
 
@@ -440,6 +438,7 @@
 MODULE_ALIAS("platform:spi_txx9");
 
 static struct platform_driver txx9spi_driver = {
+	.probe = txx9spi_probe,
 	.remove = txx9spi_remove,
 	.driver = {
 		.name = "spi_txx9",
@@ -449,7 +448,7 @@
 
 static int __init txx9spi_init(void)
 {
-	return platform_driver_probe(&txx9spi_driver, txx9spi_probe);
+	return platform_driver_register(&txx9spi_driver);
 }
 subsys_initcall(txx9spi_init);
 
diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c
index 0bf1b2c..ec3a83f 100644
--- a/drivers/spi/spi-xilinx.c
+++ b/drivers/spi/spi-xilinx.c
@@ -372,7 +372,7 @@
 	master->mode_bits = SPI_CPOL | SPI_CPHA;
 
 	xspi = spi_master_get_devdata(master);
-	xspi->bitbang.master = spi_master_get(master);
+	xspi->bitbang.master = master;
 	xspi->bitbang.chipselect = xilinx_spi_chipselect;
 	xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer;
 	xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs;
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 9e039c6..8d05acc 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -39,6 +39,9 @@
 #include <linux/ioport.h>
 #include <linux/acpi.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/spi.h>
+
 static void spidev_release(struct device *dev)
 {
 	struct spi_device	*spi = to_spi_device(dev);
@@ -58,11 +61,13 @@
 
 	return sprintf(buf, "%s%s\n", SPI_MODULE_PREFIX, spi->modalias);
 }
+static DEVICE_ATTR_RO(modalias);
 
-static struct device_attribute spi_dev_attrs[] = {
-	__ATTR_RO(modalias),
-	__ATTR_NULL,
+static struct attribute *spi_dev_attrs[] = {
+	&dev_attr_modalias.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(spi_dev);
 
 /* modalias support makes "modprobe $MODALIAS" new-style hotplug work,
  * and the sysfs version makes coldplug work too.
@@ -229,7 +234,7 @@
 
 struct bus_type spi_bus_type = {
 	.name		= "spi",
-	.dev_attrs	= spi_dev_attrs,
+	.dev_groups	= spi_dev_groups,
 	.match		= spi_match_device,
 	.uevent		= spi_uevent,
 	.pm		= &spi_pm,
@@ -323,7 +328,7 @@
 	if (!spi_master_get(master))
 		return NULL;
 
-	spi = kzalloc(sizeof *spi, GFP_KERNEL);
+	spi = kzalloc(sizeof(*spi), GFP_KERNEL);
 	if (!spi) {
 		dev_err(dev, "cannot alloc spi_device\n");
 		spi_master_put(master);
@@ -523,6 +528,95 @@
 
 /*-------------------------------------------------------------------------*/
 
+static void spi_set_cs(struct spi_device *spi, bool enable)
+{
+	if (spi->mode & SPI_CS_HIGH)
+		enable = !enable;
+
+	if (spi->cs_gpio >= 0)
+		gpio_set_value(spi->cs_gpio, !enable);
+	else if (spi->master->set_cs)
+		spi->master->set_cs(spi, !enable);
+}
+
+/*
+ * spi_transfer_one_message - Default implementation of transfer_one_message()
+ *
+ * This is a standard implementation of transfer_one_message() for
+ * drivers which impelment a transfer_one() operation.  It provides
+ * standard handling of delays and chip select management.
+ */
+static int spi_transfer_one_message(struct spi_master *master,
+				    struct spi_message *msg)
+{
+	struct spi_transfer *xfer;
+	bool cur_cs = true;
+	bool keep_cs = false;
+	int ret = 0;
+
+	spi_set_cs(msg->spi, true);
+
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+		trace_spi_transfer_start(msg, xfer);
+
+		INIT_COMPLETION(master->xfer_completion);
+
+		ret = master->transfer_one(master, msg->spi, xfer);
+		if (ret < 0) {
+			dev_err(&msg->spi->dev,
+				"SPI transfer failed: %d\n", ret);
+			goto out;
+		}
+
+		if (ret > 0)
+			wait_for_completion(&master->xfer_completion);
+
+		trace_spi_transfer_stop(msg, xfer);
+
+		if (msg->status != -EINPROGRESS)
+			goto out;
+
+		if (xfer->delay_usecs)
+			udelay(xfer->delay_usecs);
+
+		if (xfer->cs_change) {
+			if (list_is_last(&xfer->transfer_list,
+					 &msg->transfers)) {
+				keep_cs = true;
+			} else {
+				cur_cs = !cur_cs;
+				spi_set_cs(msg->spi, cur_cs);
+			}
+		}
+
+		msg->actual_length += xfer->len;
+	}
+
+out:
+	if (ret != 0 || !keep_cs)
+		spi_set_cs(msg->spi, false);
+
+	if (msg->status == -EINPROGRESS)
+		msg->status = ret;
+
+	spi_finalize_current_message(master);
+
+	return ret;
+}
+
+/**
+ * spi_finalize_current_transfer - report completion of a transfer
+ *
+ * Called by SPI drivers using the core transfer_one_message()
+ * implementation to notify it that the current interrupt driven
+ * transfer has finised and the next one may be scheduled.
+ */
+void spi_finalize_current_transfer(struct spi_master *master)
+{
+	complete(&master->xfer_completion);
+}
+EXPORT_SYMBOL_GPL(spi_finalize_current_transfer);
+
 /**
  * spi_pump_messages - kthread work function which processes spi message queue
  * @work: pointer to kthread work struct contained in the master struct
@@ -557,6 +651,7 @@
 			pm_runtime_mark_last_busy(master->dev.parent);
 			pm_runtime_put_autosuspend(master->dev.parent);
 		}
+		trace_spi_master_idle(master);
 		return;
 	}
 
@@ -585,6 +680,9 @@
 		}
 	}
 
+	if (!was_busy)
+		trace_spi_master_busy(master);
+
 	if (!was_busy && master->prepare_transfer_hardware) {
 		ret = master->prepare_transfer_hardware(master);
 		if (ret) {
@@ -597,6 +695,20 @@
 		}
 	}
 
+	trace_spi_message_start(master->cur_msg);
+
+	if (master->prepare_message) {
+		ret = master->prepare_message(master, master->cur_msg);
+		if (ret) {
+			dev_err(&master->dev,
+				"failed to prepare message: %d\n", ret);
+			master->cur_msg->status = ret;
+			spi_finalize_current_message(master);
+			return;
+		}
+		master->cur_msg_prepared = true;
+	}
+
 	ret = master->transfer_one_message(master, master->cur_msg);
 	if (ret) {
 		dev_err(&master->dev,
@@ -678,6 +790,7 @@
 {
 	struct spi_message *mesg;
 	unsigned long flags;
+	int ret;
 
 	spin_lock_irqsave(&master->queue_lock, flags);
 	mesg = master->cur_msg;
@@ -686,9 +799,20 @@
 	queue_kthread_work(&master->kworker, &master->pump_messages);
 	spin_unlock_irqrestore(&master->queue_lock, flags);
 
+	if (master->cur_msg_prepared && master->unprepare_message) {
+		ret = master->unprepare_message(master, mesg);
+		if (ret) {
+			dev_err(&master->dev,
+				"failed to unprepare message: %d\n", ret);
+		}
+	}
+	master->cur_msg_prepared = false;
+
 	mesg->state = NULL;
 	if (mesg->complete)
 		mesg->complete(mesg->context);
+
+	trace_spi_message_done(mesg);
 }
 EXPORT_SYMBOL_GPL(spi_finalize_current_message);
 
@@ -803,6 +927,8 @@
 
 	master->queued = true;
 	master->transfer = spi_queued_transfer;
+	if (!master->transfer_one_message)
+		master->transfer_one_message = spi_transfer_one_message;
 
 	/* Initialize and start queue */
 	ret = spi_init_queue(master);
@@ -838,10 +964,8 @@
 {
 	struct spi_device *spi;
 	struct device_node *nc;
-	const __be32 *prop;
-	char modalias[SPI_NAME_SIZE + 4];
 	int rc;
-	int len;
+	u32 value;
 
 	if (!master->dev.of_node)
 		return;
@@ -866,14 +990,14 @@
 		}
 
 		/* Device address */
-		prop = of_get_property(nc, "reg", &len);
-		if (!prop || len < sizeof(*prop)) {
-			dev_err(&master->dev, "%s has no 'reg' property\n",
-				nc->full_name);
+		rc = of_property_read_u32(nc, "reg", &value);
+		if (rc) {
+			dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n",
+				nc->full_name, rc);
 			spi_dev_put(spi);
 			continue;
 		}
-		spi->chip_select = be32_to_cpup(prop);
+		spi->chip_select = value;
 
 		/* Mode (clock phase/polarity/etc.) */
 		if (of_find_property(nc, "spi-cpha", NULL))
@@ -886,55 +1010,53 @@
 			spi->mode |= SPI_3WIRE;
 
 		/* Device DUAL/QUAD mode */
-		prop = of_get_property(nc, "spi-tx-bus-width", &len);
-		if (prop && len == sizeof(*prop)) {
-			switch (be32_to_cpup(prop)) {
-			case SPI_NBITS_SINGLE:
+		if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) {
+			switch (value) {
+			case 1:
 				break;
-			case SPI_NBITS_DUAL:
+			case 2:
 				spi->mode |= SPI_TX_DUAL;
 				break;
-			case SPI_NBITS_QUAD:
+			case 4:
 				spi->mode |= SPI_TX_QUAD;
 				break;
 			default:
 				dev_err(&master->dev,
 					"spi-tx-bus-width %d not supported\n",
-					be32_to_cpup(prop));
+					value);
 				spi_dev_put(spi);
 				continue;
 			}
 		}
 
-		prop = of_get_property(nc, "spi-rx-bus-width", &len);
-		if (prop && len == sizeof(*prop)) {
-			switch (be32_to_cpup(prop)) {
-			case SPI_NBITS_SINGLE:
+		if (!of_property_read_u32(nc, "spi-rx-bus-width", &value)) {
+			switch (value) {
+			case 1:
 				break;
-			case SPI_NBITS_DUAL:
+			case 2:
 				spi->mode |= SPI_RX_DUAL;
 				break;
-			case SPI_NBITS_QUAD:
+			case 4:
 				spi->mode |= SPI_RX_QUAD;
 				break;
 			default:
 				dev_err(&master->dev,
 					"spi-rx-bus-width %d not supported\n",
-					be32_to_cpup(prop));
+					value);
 				spi_dev_put(spi);
 				continue;
 			}
 		}
 
 		/* Device speed */
-		prop = of_get_property(nc, "spi-max-frequency", &len);
-		if (!prop || len < sizeof(*prop)) {
-			dev_err(&master->dev, "%s has no 'spi-max-frequency' property\n",
-				nc->full_name);
+		rc = of_property_read_u32(nc, "spi-max-frequency", &value);
+		if (rc) {
+			dev_err(&master->dev, "%s has no valid 'spi-max-frequency' property (%d)\n",
+				nc->full_name, rc);
 			spi_dev_put(spi);
 			continue;
 		}
-		spi->max_speed_hz = be32_to_cpup(prop);
+		spi->max_speed_hz = value;
 
 		/* IRQ */
 		spi->irq = irq_of_parse_and_map(nc, 0);
@@ -944,9 +1066,7 @@
 		spi->dev.of_node = nc;
 
 		/* Register the new device */
-		snprintf(modalias, sizeof(modalias), "%s%s", SPI_MODULE_PREFIX,
-			 spi->modalias);
-		request_module(modalias);
+		request_module("%s%s", SPI_MODULE_PREFIX, spi->modalias);
 		rc = spi_add_device(spi);
 		if (rc) {
 			dev_err(&master->dev, "spi_device register error %s\n",
@@ -1025,7 +1145,7 @@
 		return AE_OK;
 	}
 
-	strlcpy(spi->modalias, dev_name(&adev->dev), sizeof(spi->modalias));
+	strlcpy(spi->modalias, acpi_device_hid(adev), sizeof(spi->modalias));
 	if (spi_add_device(spi)) {
 		dev_err(&master->dev, "failed to add SPI device %s from ACPI\n",
 			dev_name(&adev->dev));
@@ -1097,7 +1217,7 @@
 	if (!dev)
 		return NULL;
 
-	master = kzalloc(size + sizeof *master, GFP_KERNEL);
+	master = kzalloc(size + sizeof(*master), GFP_KERNEL);
 	if (!master)
 		return NULL;
 
@@ -1122,7 +1242,7 @@
 		return 0;
 
 	nb = of_gpio_named_count(np, "cs-gpios");
-	master->num_chipselect = max(nb, (int)master->num_chipselect);
+	master->num_chipselect = max_t(int, nb, master->num_chipselect);
 
 	/* Return error only for an incorrectly formed cs-gpios property */
 	if (nb == 0 || nb == -ENOENT)
@@ -1209,6 +1329,7 @@
 	spin_lock_init(&master->bus_lock_spinlock);
 	mutex_init(&master->bus_lock_mutex);
 	master->bus_lock_flag = 0;
+	init_completion(&master->xfer_completion);
 
 	/* register the device, then userspace will see it.
 	 * registration fails if the bus ID is in use.
@@ -1245,6 +1366,41 @@
 }
 EXPORT_SYMBOL_GPL(spi_register_master);
 
+static void devm_spi_unregister(struct device *dev, void *res)
+{
+	spi_unregister_master(*(struct spi_master **)res);
+}
+
+/**
+ * dev_spi_register_master - register managed SPI master controller
+ * @dev:    device managing SPI master
+ * @master: initialized master, originally from spi_alloc_master()
+ * Context: can sleep
+ *
+ * Register a SPI device as with spi_register_master() which will
+ * automatically be unregister
+ */
+int devm_spi_register_master(struct device *dev, struct spi_master *master)
+{
+	struct spi_master **ptr;
+	int ret;
+
+	ptr = devres_alloc(devm_spi_unregister, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return -ENOMEM;
+
+	ret = spi_register_master(master);
+	if (ret != 0) {
+		*ptr = master;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(devm_spi_register_master);
+
 static int __unregister(struct device *dev, void *null)
 {
 	spi_unregister_device(to_spi_device(dev));
@@ -1402,8 +1558,7 @@
 	if (spi->master->setup)
 		status = spi->master->setup(spi);
 
-	dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s"
-				"%u bits/w, %u Hz max --> %d\n",
+	dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s%u bits/w, %u Hz max --> %d\n",
 			(int) (spi->mode & (SPI_CPOL | SPI_CPHA)),
 			(spi->mode & SPI_CS_HIGH) ? "cs_high, " : "",
 			(spi->mode & SPI_LSB_FIRST) ? "lsb, " : "",
@@ -1421,6 +1576,10 @@
 	struct spi_master *master = spi->master;
 	struct spi_transfer *xfer;
 
+	message->spi = spi;
+
+	trace_spi_message_submit(message);
+
 	if (list_empty(&message->transfers))
 		return -EINVAL;
 	if (!message->complete)
@@ -1520,7 +1679,6 @@
 		}
 	}
 
-	message->spi = spi;
 	message->status = -EINPROGRESS;
 	return master->transfer(spi, message);
 }
@@ -1762,7 +1920,7 @@
 EXPORT_SYMBOL_GPL(spi_bus_unlock);
 
 /* portable code must never pass more than 32 bytes */
-#define	SPI_BUFSIZ	max(32,SMP_CACHE_BYTES)
+#define	SPI_BUFSIZ	max(32, SMP_CACHE_BYTES)
 
 static u8	*buf;
 
@@ -1811,7 +1969,7 @@
 	}
 
 	spi_message_init(&message);
-	memset(x, 0, sizeof x);
+	memset(x, 0, sizeof(x));
 	if (n_tx) {
 		x[0].len = n_tx;
 		spi_message_add_tail(&x[0], &message);
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index ca5bcfe..d7c6e36 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -37,7 +37,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/spidev.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 
 /*
@@ -206,9 +206,9 @@
 
 	mutex_lock(&spidev->buf_lock);
 	missing = copy_from_user(spidev->buffer, buf, count);
-	if (missing == 0) {
+	if (missing == 0)
 		status = spidev_sync_write(spidev, count);
-	} else
+	else
 		status = -EFAULT;
 	mutex_unlock(&spidev->buf_lock);
 
@@ -629,7 +629,6 @@
 	/* make sure ops on existing fds can abort cleanly */
 	spin_lock_irq(&spidev->spi_lock);
 	spidev->spi = NULL;
-	spi_set_drvdata(spi, NULL);
 	spin_unlock_irq(&spidev->spi_lock);
 
 	/* prevent new opens */
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index e55ddf7..32a811d 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -374,7 +374,8 @@
 attrib##_show(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return sprintf(buf, format_string, dev_to_ssb_dev(dev)->field); \
-}
+} \
+static DEVICE_ATTR_RO(attrib);
 
 ssb_config_attr(core_num, core_index, "%u\n")
 ssb_config_attr(coreid, id.coreid, "0x%04x\n")
@@ -387,16 +388,18 @@
 	return sprintf(buf, "%s\n",
 		       ssb_core_name(dev_to_ssb_dev(dev)->id.coreid));
 }
+static DEVICE_ATTR_RO(name);
 
-static struct device_attribute ssb_device_attrs[] = {
-	__ATTR_RO(name),
-	__ATTR_RO(core_num),
-	__ATTR_RO(coreid),
-	__ATTR_RO(vendor),
-	__ATTR_RO(revision),
-	__ATTR_RO(irq),
-	__ATTR_NULL,
+static struct attribute *ssb_device_attrs[] = {
+	&dev_attr_name.attr,
+	&dev_attr_core_num.attr,
+	&dev_attr_coreid.attr,
+	&dev_attr_vendor.attr,
+	&dev_attr_revision.attr,
+	&dev_attr_irq.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(ssb_device);
 
 static struct bus_type ssb_bustype = {
 	.name		= "ssb",
@@ -407,7 +410,7 @@
 	.suspend	= ssb_device_suspend,
 	.resume		= ssb_device_resume,
 	.uevent		= ssb_device_uevent,
-	.dev_attrs	= ssb_device_attrs,
+	.dev_groups	= ssb_device_groups,
 };
 
 static void ssb_buses_lock(void)
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 3626dbc8..3bfdaa8 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -136,6 +136,8 @@
 
 source "drivers/staging/netlogic/Kconfig"
 
+source "drivers/staging/mt29f_spinand/Kconfig"
+
 source "drivers/staging/dwc2/Kconfig"
 
 source "drivers/staging/lustre/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index d1b4b80..b0d3303 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -66,3 +66,4 @@
 obj-$(CONFIG_XILLYBUS)		+= xillybus/
 obj-$(CONFIG_DGNC)			+= dgnc/
 obj-$(CONFIG_DGAP)			+= dgap/
+obj-$(CONFIG_MTD_SPINAND_MT29F)	+= mt29f_spinand/
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index c0c95be..1e9ab6d 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -10,6 +10,7 @@
 
 config ANDROID_BINDER_IPC
 	bool "Android Binder IPC Driver"
+	depends on MMU
 	default n
 	---help---
 	  Binder is used in Android for both communication between processes,
@@ -76,7 +77,7 @@
 	bool "Synchronization framework"
 	default n
 	select ANON_INODES
-	help
+	---help---
 	  This option enables the framework for synchronization between multiple
 	  drivers.  Sync implementations can take advantage of hardware
 	  synchronization built into devices like GPUs.
@@ -85,7 +86,7 @@
 	bool "Software synchronization objects"
 	default n
 	depends on SYNC
-	help
+	---help---
 	  A sync object driver that uses a 32bit counter to coordinate
 	  syncrhronization.  Useful when there is no hardware primitive backing
 	  the synchronization.
@@ -94,7 +95,7 @@
 	bool "Userspace API for SW_SYNC"
 	default n
 	depends on SW_SYNC
-	help
+	---help---
 	  Provides a user space API to the sw sync object.
 	  *WARNING* improper use of this can result in deadlocking kernel
 	  drivers from userspace.
diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c
index 6dc27da..647694f 100644
--- a/drivers/staging/android/alarm-dev.c
+++ b/drivers/staging/android/alarm-dev.c
@@ -60,7 +60,12 @@
 
 static struct devalarm alarms[ANDROID_ALARM_TYPE_COUNT];
 
-
+/**
+ * is_wakeup() - Checks to see if this alarm can wake the device
+ * @type:	 The type of alarm being checked
+ *
+ * Return: 1 if this is a wakeup alarm, otherwise 0
+ */
 static int is_wakeup(enum android_alarm_type type)
 {
 	return (type == ANDROID_ALARM_RTC_WAKEUP ||
@@ -76,7 +81,6 @@
 		hrtimer_start(&alrm->u.hrt, exp, HRTIMER_MODE_ABS);
 }
 
-
 static int devalarm_try_to_cancel(struct devalarm *alrm)
 {
 	if (is_wakeup(alrm->type))
diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c
index 8e76ddc..23948f1 100644
--- a/drivers/staging/android/ashmem.c
+++ b/drivers/staging/android/ashmem.c
@@ -37,41 +37,59 @@
 #define ASHMEM_NAME_PREFIX_LEN (sizeof(ASHMEM_NAME_PREFIX) - 1)
 #define ASHMEM_FULL_NAME_LEN (ASHMEM_NAME_LEN + ASHMEM_NAME_PREFIX_LEN)
 
-/*
- * ashmem_area - anonymous shared memory area
- * Lifecycle: From our parent file's open() until its release()
- * Locking: Protected by `ashmem_mutex'
- * Big Note: Mappings do NOT pin this structure; it dies on close()
+/**
+ * struct ashmem_area - The anonymous shared memory area
+ * @name:		The optional name in /proc/pid/maps
+ * @unpinned_list:	The list of all ashmem areas
+ * @file:		The shmem-based backing file
+ * @size:		The size of the mapping, in bytes
+ * @prot_masks:		The allowed protection bits, as vm_flags
+ *
+ * The lifecycle of this structure is from our parent file's open() until
+ * its release(). It is also protected by 'ashmem_mutex'
+ *
+ * Warning: Mappings do NOT pin this structure; It dies on close()
  */
 struct ashmem_area {
-	char name[ASHMEM_FULL_NAME_LEN]; /* optional name in /proc/pid/maps */
-	struct list_head unpinned_list;	 /* list of all ashmem areas */
-	struct file *file;		 /* the shmem-based backing file */
-	size_t size;			 /* size of the mapping, in bytes */
-	unsigned long prot_mask;	 /* allowed prot bits, as vm_flags */
+	char name[ASHMEM_FULL_NAME_LEN];
+	struct list_head unpinned_list;
+	struct file *file;
+	size_t size;
+	unsigned long prot_mask;
 };
 
-/*
- * ashmem_range - represents an interval of unpinned (evictable) pages
- * Lifecycle: From unpin to pin
- * Locking: Protected by `ashmem_mutex'
+/**
+ * struct ashmem_range - A range of unpinned/evictable pages
+ * @lru:	         The entry in the LRU list
+ * @unpinned:	         The entry in its area's unpinned list
+ * @asma:	         The associated anonymous shared memory area.
+ * @pgstart:	         The starting page (inclusive)
+ * @pgend:	         The ending page (inclusive)
+ * @purged:	         The purge status (ASHMEM_NOT or ASHMEM_WAS_PURGED)
+ *
+ * The lifecycle of this structure is from unpin to pin.
+ * It is protected by 'ashmem_mutex'
  */
 struct ashmem_range {
-	struct list_head lru;		/* entry in LRU list */
-	struct list_head unpinned;	/* entry in its area's unpinned list */
-	struct ashmem_area *asma;	/* associated area */
-	size_t pgstart;			/* starting page, inclusive */
-	size_t pgend;			/* ending page, inclusive */
-	unsigned int purged;		/* ASHMEM_NOT or ASHMEM_WAS_PURGED */
+	struct list_head lru;
+	struct list_head unpinned;
+	struct ashmem_area *asma;
+	size_t pgstart;
+	size_t pgend;
+	unsigned int purged;
 };
 
 /* LRU list of unpinned pages, protected by ashmem_mutex */
 static LIST_HEAD(ashmem_lru_list);
 
-/* Count of pages on our LRU list, protected by ashmem_mutex */
+/**
+ * long lru_count - The count of pages on our LRU list.
+ *
+ * This is protected by ashmem_mutex.
+ */
 static unsigned long lru_count;
 
-/*
+/**
  * ashmem_mutex - protects the list of and each individual ashmem_area
  *
  * Lock Ordering: ashmex_mutex -> i_mutex -> i_alloc_sem
@@ -105,28 +123,43 @@
 
 #define PROT_MASK		(PROT_EXEC | PROT_READ | PROT_WRITE)
 
+/**
+ * lru_add() - Adds a range of memory to the LRU list
+ * @range:     The memory range being added.
+ *
+ * The range is first added to the end (tail) of the LRU list.
+ * After this, the size of the range is added to @lru_count
+ */
 static inline void lru_add(struct ashmem_range *range)
 {
 	list_add_tail(&range->lru, &ashmem_lru_list);
 	lru_count += range_size(range);
 }
 
+/**
+ * lru_del() - Removes a range of memory from the LRU list
+ * @range:     The memory range being removed
+ *
+ * The range is first deleted from the LRU list.
+ * After this, the size of the range is removed from @lru_count
+ */
 static inline void lru_del(struct ashmem_range *range)
 {
 	list_del(&range->lru);
 	lru_count -= range_size(range);
 }
 
-/*
- * range_alloc - allocate and initialize a new ashmem_range structure
+/**
+ * range_alloc() - Allocates and initializes a new ashmem_range structure
+ * @asma:	   The associated ashmem_area
+ * @prev_range:	   The previous ashmem_range in the sorted asma->unpinned list
+ * @purged:	   Initial purge status (ASMEM_NOT_PURGED or ASHMEM_WAS_PURGED)
+ * @start:	   The starting page (inclusive)
+ * @end:	   The ending page (inclusive)
  *
- * 'asma' - associated ashmem_area
- * 'prev_range' - the previous ashmem_range in the sorted asma->unpinned list
- * 'purged' - initial purge value (ASMEM_NOT_PURGED or ASHMEM_WAS_PURGED)
- * 'start' - starting page, inclusive
- * 'end' - ending page, inclusive
+ * This function is protected by ashmem_mutex.
  *
- * Caller must hold ashmem_mutex.
+ * Return: 0 if successful, or -ENOMEM if there is an error
  */
 static int range_alloc(struct ashmem_area *asma,
 		       struct ashmem_range *prev_range, unsigned int purged,
@@ -151,6 +184,10 @@
 	return 0;
 }
 
+/**
+ * range_del() - Deletes and dealloctes an ashmem_range structure
+ * @range:	 The associated ashmem_range that has previously been allocated
+ */
 static void range_del(struct ashmem_range *range)
 {
 	list_del(&range->unpinned);
@@ -159,10 +196,17 @@
 	kmem_cache_free(ashmem_range_cachep, range);
 }
 
-/*
- * range_shrink - shrinks a range
+/**
+ * range_shrink() - Shrinks an ashmem_range
+ * @range:	    The associated ashmem_range being shrunk
+ * @start:	    The starting byte of the new range
+ * @end:	    The ending byte of the new range
  *
- * Caller must hold ashmem_mutex.
+ * This does not modify the data inside the existing range in any way - It
+ * simply shrinks the boundaries of the range.
+ *
+ * Theoretically, with a little tweaking, this could eventually be changed
+ * to range_resize, and expand the lru_count if the new range is larger.
  */
 static inline void range_shrink(struct ashmem_range *range,
 				size_t start, size_t end)
@@ -176,6 +220,16 @@
 		lru_count -= pre - range_size(range);
 }
 
+/**
+ * ashmem_open() - Opens an Anonymous Shared Memory structure
+ * @inode:	   The backing file's index node(?)
+ * @file:	   The backing file
+ *
+ * Please note that the ashmem_area is not returned by this function - It is
+ * instead written to "file->private_data".
+ *
+ * Return: 0 if successful, or another code if unsuccessful.
+ */
 static int ashmem_open(struct inode *inode, struct file *file)
 {
 	struct ashmem_area *asma;
@@ -197,6 +251,14 @@
 	return 0;
 }
 
+/**
+ * ashmem_release() - Releases an Anonymous Shared Memory structure
+ * @ignored:	      The backing file's Index Node(?) - It is ignored here.
+ * @file:	      The backing file
+ *
+ * Return: 0 if successful. If it is anything else, go have a coffee and
+ * try again.
+ */
 static int ashmem_release(struct inode *ignored, struct file *file)
 {
 	struct ashmem_area *asma = file->private_data;
@@ -214,6 +276,15 @@
 	return 0;
 }
 
+/**
+ * ashmem_read() - Reads a set of bytes from an Ashmem-enabled file
+ * @file:	   The associated backing file.
+ * @buf:	   The buffer of data being written to
+ * @len:	   The number of bytes being read
+ * @pos:	   The position of the first byte to read.
+ *
+ * Return: 0 if successful, or another return code if not.
+ */
 static ssize_t ashmem_read(struct file *file, char __user *buf,
 			   size_t len, loff_t *pos)
 {
@@ -706,7 +777,7 @@
 				.gfp_mask = GFP_KERNEL,
 				.nr_to_scan = LONG_MAX,
 			};
-
+			ret = ashmem_shrink_count(&ashmem_shrinker, &sc);
 			nodes_setall(sc.nodes_to_scan);
 			ashmem_shrink_scan(&ashmem_shrinker, &sc);
 		}
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index 98ac020..eaec1da 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -1700,7 +1700,8 @@
 		thread->return_error = return_error;
 }
 
-int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
+static int binder_thread_write(struct binder_proc *proc,
+			struct binder_thread *thread,
 			void __user *buffer, size_t size, size_t *consumed)
 {
 	uint32_t cmd;
@@ -1773,7 +1774,7 @@
 		case BC_INCREFS_DONE:
 		case BC_ACQUIRE_DONE: {
 			void __user *node_ptr;
-			void *cookie;
+			void __user *cookie;
 			struct binder_node *node;
 
 			if (get_user(node_ptr, (void * __user *)ptr))
@@ -2055,8 +2056,8 @@
 	return 0;
 }
 
-void binder_stat_br(struct binder_proc *proc, struct binder_thread *thread,
-		    uint32_t cmd)
+static void binder_stat_br(struct binder_proc *proc,
+			   struct binder_thread *thread, uint32_t cmd)
 {
 	trace_binder_return(cmd);
 	if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.br)) {
diff --git a/drivers/staging/android/timed_output.h b/drivers/staging/android/timed_output.h
index ec907ab..905c7cc 100644
--- a/drivers/staging/android/timed_output.h
+++ b/drivers/staging/android/timed_output.h
@@ -31,7 +31,7 @@
 	int		state;
 };
 
-extern int timed_output_dev_register(struct timed_output_dev *dev);
-extern void timed_output_dev_unregister(struct timed_output_dev *dev);
+int timed_output_dev_register(struct timed_output_dev *dev);
+void timed_output_dev_unregister(struct timed_output_dev *dev);
 
 #endif
diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h
index 1d8bf08..9cd5987 100644
--- a/drivers/staging/bcm/Adapter.h
+++ b/drivers/staging/bcm/Adapter.h
@@ -35,7 +35,7 @@
 #define MAX_PROTOCOL_LENGTH   32
 #define IPV6_ADDRESS_SIZEINBYTES 0x10
 
-typedef union _U_IP_ADDRESS {
+union u_ip_address {
 	struct {
 		ULONG ulIpv4Addr[MAX_IP_RANGE_LENGTH]; /* Source Ip Address Range */
 		ULONG ulIpv4Mask[MAX_IP_RANGE_LENGTH]; /* Source Ip Mask Address Range */
@@ -52,7 +52,7 @@
 		UCHAR ucIpv6Address[MAX_IP_RANGE_LENGTH * IPV6_ADDRESS_SIZEINBYTES];
 		UCHAR ucIpv6Mask[MAX_IP_RANGE_LENGTH * IPV6_ADDRESS_SIZEINBYTES];
 	};
-} U_IP_ADDRESS;
+};
 
 struct bcm_hdr_suppression_contextinfo {
 	UCHAR ucaHdrSuppressionInBuf[MAX_PHS_LENGTHS]; /* Intermediate buffer to accumulate pkt Header for PHS */
@@ -63,13 +63,13 @@
 	ULONG		ulSFID;
 	UCHAR		ucReserved[2];
 	B_UINT16	uiClassifierRuleIndex;
-	BOOLEAN		bUsed;
+	bool		bUsed;
 	USHORT		usVCID_Value;
 	B_UINT8		u8ClassifierRulePriority; /* This field detemines the Classifier Priority */
-	U_IP_ADDRESS	stSrcIpAddress;
+	union u_ip_address	stSrcIpAddress;
 	UCHAR		ucIPSourceAddressLength; /* Ip Source Address Length */
 
-	U_IP_ADDRESS	stDestIpAddress;
+	union u_ip_address	stDestIpAddress;
 	UCHAR		ucIPDestinationAddressLength; /* Ip Destination Address Length */
 	UCHAR		ucIPTypeOfServiceLength; /* Type of service Length */
 	UCHAR		ucTosLow; /* Tos Low */
@@ -86,14 +86,14 @@
 	USHORT		usDestPortRangeHi[MAX_PORT_RANGE];
 	UCHAR		ucDestPortRangeLength;
 
-	BOOLEAN		bProtocolValid;
-	BOOLEAN		bTOSValid;
-	BOOLEAN		bDestIpValid;
-	BOOLEAN		bSrcIpValid;
+	bool		bProtocolValid;
+	bool		bTOSValid;
+	bool		bDestIpValid;
+	bool		bSrcIpValid;
 
 	/* For IPv6 Addressing */
 	UCHAR		ucDirection;
-	BOOLEAN		bIpv6Protocol;
+	bool		bIpv6Protocol;
 	UINT32		u32PHSRuleID;
 	struct bcm_phs_rule sPhsRule;
 	UCHAR		u8AssociatedPHSI;
@@ -113,11 +113,11 @@
 };
 
 struct bcm_fragmented_packet_info {
-	BOOLEAN			bUsed;
+	bool			bUsed;
 	ULONG			ulSrcIpAddress;
 	USHORT			usIpIdentification;
 	struct bcm_classifier_rule *pstMatchedClassifierEntry;
-	BOOLEAN			bOutOfOrderFragment;
+	bool			bOutOfOrderFragment;
 };
 
 struct bcm_packet_info {
@@ -128,9 +128,9 @@
 	/* This field determines the priority of the SF Queues */
 	B_UINT8		u8TrafficPriority;
 
-	BOOLEAN		bValid;
-	BOOLEAN		bActive;
-	BOOLEAN		bActivateRequestSent;
+	bool		bValid;
+	bool		bActive;
+	bool		bActivateRequestSent;
 
 	B_UINT8		u8QueueType; /* BE or rtPS */
 
@@ -170,17 +170,17 @@
 		};
 	};
 
-	BOOLEAN		bProtocolValid;
-	BOOLEAN		bTOSValid;
-	BOOLEAN		bDestIpValid;
-	BOOLEAN		bSrcIpValid;
+	bool		bProtocolValid;
+	bool		bTOSValid;
+	bool		bDestIpValid;
+	bool		bSrcIpValid;
 
-	BOOLEAN		bActiveSet;
-	BOOLEAN		bAdmittedSet;
-	BOOLEAN		bAuthorizedSet;
-	BOOLEAN		bClassifierPriority;
+	bool		bActiveSet;
+	bool		bAdmittedSet;
+	bool		bAuthorizedSet;
+	bool		bClassifierPriority;
 	UCHAR		ucServiceClassName[MAX_CLASS_NAME_LENGTH];
-	BOOLEAN		bHeaderSuppressionEnabled;
+	bool		bHeaderSuppressionEnabled;
 	spinlock_t	SFQueueLock;
 	void		*pstSFIndication;
 	struct timeval	stLastUpdateTokenAt;
@@ -196,8 +196,8 @@
 	struct sk_buff		*RxAppControlHead;
 	struct sk_buff		*RxAppControlTail;
 	int			AppCtrlQueueLen;
-	BOOLEAN			MacTracingEnabled;
-	BOOLEAN			bApplicationToExit;
+	bool			MacTracingEnabled;
+	bool			bApplicationToExit;
 	struct bcm_mibs_dropped_cntrl_msg stDroppedAppCntrlMsgs;
 	ULONG			RxCntrlMsgBitMask;
 };
@@ -205,7 +205,7 @@
 struct bcm_targetdsx_buffer {
 	ULONG		ulTargetDsxBuffer;
 	B_UINT16	tid;
-	BOOLEAN		valid;
+	bool		valid;
 };
 
 typedef int (*FP_FLASH_WRITE)(struct bcm_mini_adapter *, UINT, PVOID);
@@ -221,11 +221,11 @@
 	u32			msg_enable;
 	CHAR			*caDsxReqResp;
 	atomic_t		ApplicationRunning;
-	BOOLEAN			AppCtrlQueueOverFlow;
+	bool			AppCtrlQueueOverFlow;
 	atomic_t		CurrentApplicationCount;
 	atomic_t		RegisteredApplicationCount;
-	BOOLEAN			LinkUpStatus;
-	BOOLEAN			TimerActive;
+	bool			LinkUpStatus;
+	bool			TimerActive;
 	u32			StatisticsPointer;
 	struct sk_buff		*RxControlHead;
 	struct sk_buff		*RxControlTail;
@@ -249,25 +249,25 @@
 	UINT			u32TotalDSD;
 	struct bcm_packet_info	PackInfo[NO_OF_QUEUES];
 	struct bcm_classifier_rule astClassifierTable[MAX_CLASSIFIERS];
-	BOOLEAN			TransferMode;
+	bool			TransferMode;
 
 	/*************** qos ******************/
-	BOOLEAN			bETHCSEnabled;
+	bool			bETHCSEnabled;
 	ULONG			BEBucketSize;
 	ULONG			rtPSBucketSize;
 	UCHAR			LinkStatus;
-	BOOLEAN			AutoLinkUp;
-	BOOLEAN			AutoSyncup;
+	bool			AutoLinkUp;
+	bool			AutoSyncup;
 
 	int			major;
 	int			minor;
 	wait_queue_head_t	tx_packet_wait_queue;
 	wait_queue_head_t	process_rx_cntrlpkt;
 	atomic_t		process_waiting;
-	BOOLEAN			fw_download_done;
+	bool			fw_download_done;
 
 	char			*txctlpacket[MAX_CNTRL_PKTS];
-	atomic_t		cntrlpktCnt ;
+	atomic_t		cntrlpktCnt;
 	atomic_t		index_app_read_cntrlpkt;
 	atomic_t		index_wr_txcntrlpkt;
 	atomic_t		index_rd_txcntrlpkt;
@@ -280,19 +280,19 @@
 	ULONG			ulTotalTargetBuffersAvailable;
 	unsigned long		chip_id;
 	wait_queue_head_t	lowpower_mode_wait_queue;
-	BOOLEAN			bFlashBoot;
-	BOOLEAN			bBinDownloaded;
-	BOOLEAN			bCfgDownloaded;
-	BOOLEAN			bSyncUpRequestSent;
+	bool			bFlashBoot;
+	bool			bBinDownloaded;
+	bool			bCfgDownloaded;
+	bool			bSyncUpRequestSent;
 	USHORT			usBestEffortQueueIndex;
 	wait_queue_head_t	ioctl_fw_dnld_wait_queue;
-	BOOLEAN			waiting_to_fw_download_done;
+	bool			waiting_to_fw_download_done;
 	pid_t			fw_download_process_pid;
 	struct bcm_target_params *pstargetparams;
-	BOOLEAN			device_removed;
-	BOOLEAN			DeviceAccess;
-	BOOLEAN			bIsAutoCorrectEnabled;
-	BOOLEAN			bDDRInitDone;
+	bool			device_removed;
+	bool			DeviceAccess;
+	bool			bIsAutoCorrectEnabled;
+	bool			bDDRInitDone;
 	int			DDRSetting;
 	ULONG			ulPowerSaveMode;
 	spinlock_t		txtransmitlock;
@@ -324,22 +324,22 @@
 			PVOID,
 			int);
 	int (*interface_transmit)(PVOID, PVOID , UINT);
-	BOOLEAN			IdleMode;
-	BOOLEAN			bDregRequestSentInIdleMode;
-	BOOLEAN			bTriedToWakeUpFromlowPowerMode;
-	BOOLEAN			bShutStatus;
-	BOOLEAN			bWakeUpDevice;
+	bool			IdleMode;
+	bool			bDregRequestSentInIdleMode;
+	bool			bTriedToWakeUpFromlowPowerMode;
+	bool			bShutStatus;
+	bool			bWakeUpDevice;
 	unsigned int		usIdleModePattern;
 	/* BOOLEAN			bTriedToWakeUpFromShutdown; */
-	BOOLEAN			bLinkDownRequested;
+	bool			bLinkDownRequested;
 	int			downloadDDR;
 	struct bcm_phs_extension stBCMPhsContext;
 	struct bcm_hdr_suppression_contextinfo stPhsTxContextInfo;
 	uint8_t			ucaPHSPktRestoreBuf[2048];
 	uint8_t			bPHSEnabled;
-	BOOLEAN			AutoFirmDld;
-	BOOLEAN			bMipsConfig;
-	BOOLEAN			bDPLLConfig;
+	bool			AutoFirmDld;
+	bool			bMipsConfig;
+	bool			bDPLLConfig;
 	UINT32			aTxPktSizeHist[MIBS_MAX_HIST_ENTRIES];
 	UINT32			aRxPktSizeHist[MIBS_MAX_HIST_ENTRIES];
 	struct bcm_fragmented_packet_info astFragmentedPktClassifierTable[MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES];
@@ -348,8 +348,8 @@
 	enum bcm_nvm_type	eNVMType;
 	UINT			uiSectorSize;
 	UINT			uiSectorSizeInCFG;
-	BOOLEAN			bSectorSizeOverride;
-	BOOLEAN			bStatusWrite;
+	bool			bSectorSizeOverride;
+	bool			bStatusWrite;
 	UINT			uiNVMDSDSize;
 	UINT			uiVendorExtnFlag;
 	/* it will always represent chosen DSD at any point of time.
@@ -376,18 +376,18 @@
 	UINT			uiActiveDSDOffsetAtFwDld;  /* For accessing Active DSD chosen before f/w download */
 	UINT			uiFlashLayoutMajorVersion;
 	UINT			uiFlashLayoutMinorVersion;
-	BOOLEAN			bAllDSDWriteAllow;
-	BOOLEAN			bSigCorrupted;
+	bool			bAllDSDWriteAllow;
+	bool			bSigCorrupted;
 	/* this should be set who so ever want to change the Headers. after Wrtie it should be reset immediately. */
-	BOOLEAN			bHeaderChangeAllowed;
+	bool			bHeaderChangeAllowed;
 	int			SelectedChip;
-	BOOLEAN			bEndPointHalted;
+	bool			bEndPointHalted;
 	/* while bFlashRawRead will be true, Driver  ignore map lay out and consider flash as of without any map. */
-	BOOLEAN			bFlashRawRead;
-	BOOLEAN			bPreparingForLowPowerMode;
-	BOOLEAN			bDoSuspend;
+	bool			bFlashRawRead;
+	bool			bPreparingForLowPowerMode;
+	bool			bDoSuspend;
 	UINT			syscfgBefFwDld;
-	BOOLEAN			StopAllXaction;
+	bool			StopAllXaction;
 	UINT32			liTimeSinceLastNetEntry; /* Used to Support extended CAPI requirements from */
 	struct semaphore	LowPowerModeSync;
 	ULONG			liDrainCalculated;
diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c
index f91bc1f..87b74ca 100644
--- a/drivers/staging/bcm/Bcmchar.c
+++ b/drivers/staging/bcm/Bcmchar.c
@@ -49,11 +49,8 @@
 
 	pTarang = (struct bcm_tarang_data *)filp->private_data;
 
-	if (pTarang == NULL) {
-		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
-				"ptarang is null\n");
+	if (pTarang == NULL)
 		return 0;
-	}
 
 	Adapter = pTarang->Adapter;
 
@@ -119,7 +116,7 @@
 		return -ENODEV;
 	}
 
-	if (FALSE == Adapter->fw_download_done)
+	if (false == Adapter->fw_download_done)
 		return -EACCES;
 
 	down(&Adapter->RxAppControlQueuelock);
@@ -180,7 +177,7 @@
 	if (Adapter->device_removed)
 		return -EFAULT;
 
-	if (FALSE == Adapter->fw_download_done) {
+	if (false == Adapter->fw_download_done) {
 		switch (cmd) {
 		case IOCTL_MAC_ADDR_REQ:
 		case IOCTL_LINK_REQ:
@@ -425,7 +422,7 @@
 		uiOperation = gpio_info.uiGpioValue;
 		value = (1<<uiBit);
 
-		if (IsReqGpioIsLedInNVM(Adapter, value) == FALSE) {
+		if (IsReqGpioIsLedInNVM(Adapter, value) == false) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to LED !!!", value);
 			Status = -EINVAL;
 			break;
@@ -572,7 +569,7 @@
 		if (copy_from_user(&gpio_multi_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
 			return -EFAULT;
 
-		if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_info[WIMAX_IDX].uiGPIOMask) == FALSE) {
+		if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_info[WIMAX_IDX].uiGPIOMask) == false) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
 					"Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",
 					pgpio_multi_info[WIMAX_IDX].uiGPIOMask, Adapter->gpioBitMap);
@@ -665,7 +662,7 @@
 		}
 
 		/* Validating the request */
-		if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) == FALSE) {
+		if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) == false) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
 					"Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",
 					pgpio_multi_mode[WIMAX_IDX].uiGPIOMask, Adapter->gpioBitMap);
@@ -768,10 +765,10 @@
 		if (down_trylock(&Adapter->fw_download_sema))
 			return -EBUSY;
 
-		Adapter->bBinDownloaded = FALSE;
+		Adapter->bBinDownloaded = false;
 		Adapter->fw_download_process_pid = current->pid;
-		Adapter->bCfgDownloaded = FALSE;
-		Adapter->fw_download_done = FALSE;
+		Adapter->bCfgDownloaded = false;
+		Adapter->fw_download_done = false;
 		netif_carrier_off(Adapter->dev);
 		netif_stop_queue(Adapter->dev);
 		Status = reset_card_proc(Adapter);
@@ -848,7 +845,7 @@
 
 			if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
 				Adapter->DriverState = DRIVER_INIT;
-				Adapter->LEDInfo.bLedInitDone = FALSE;
+				Adapter->LEDInfo.bLedInitDone = false;
 				wake_up(&Adapter->LEDInfo.notify_led_event);
 			}
 		}
@@ -900,7 +897,7 @@
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Unable to send interrupt...\n");
 
 		timeout = 5*HZ;
-		Adapter->waiting_to_fw_download_done = FALSE;
+		Adapter->waiting_to_fw_download_done = false;
 		wait_event_timeout(Adapter->ioctl_fw_dnld_wait_queue,
 				Adapter->waiting_to_fw_download_done, timeout);
 		Adapter->fw_download_process_pid = INVALID_PID;
@@ -1052,7 +1049,7 @@
 		if (tracing_flag)
 			Adapter->pTarangs->MacTracingEnabled = TRUE;
 		else
-			Adapter->pTarangs->MacTracingEnabled = FALSE;
+			Adapter->pTarangs->MacTracingEnabled = false;
 		break;
 	}
 
@@ -1109,7 +1106,7 @@
 	}
 
 	case IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE:
-		if ((FALSE == Adapter->bTriedToWakeUpFromlowPowerMode) && (TRUE == Adapter->IdleMode)) {
+		if ((false == Adapter->bTriedToWakeUpFromlowPowerMode) && (TRUE == Adapter->IdleMode)) {
 			Adapter->usIdleModePattern = ABORT_IDLE_MODE;
 			Adapter->bWakeUpDevice = TRUE;
 			wake_up(&Adapter->process_rx_cntrlpkt);
@@ -1168,7 +1165,7 @@
 			break;
 		}
 
-		if (pBulkBuffer->SwapEndian == FALSE)
+		if (pBulkBuffer->SwapEndian == false)
 			Status = wrmWithLock(Adapter, (UINT)pBulkBuffer->Register, (PCHAR)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG));
 		else
 			Status = wrmaltWithLock(Adapter, (UINT)pBulkBuffer->Register, (PUINT)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG));
@@ -1387,7 +1384,7 @@
 			if (IsFlash2x(Adapter))
 				BcmFlash2xWriteSig(Adapter, Adapter->eActiveDSD);
 
-			Adapter->bHeaderChangeAllowed = FALSE;
+			Adapter->bHeaderChangeAllowed = false;
 
 			up(&Adapter->NVMRdmWrmLock);
 
@@ -1432,7 +1429,7 @@
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.bVerify :%x\n", sFlash2xRead.bVerify);
 
 		/* This was internal to driver for raw read. now it has ben exposed to user space app. */
-		if (validateFlash2xReadWrite(Adapter, &sFlash2xRead) == FALSE)
+		if (validateFlash2xReadWrite(Adapter, &sFlash2xRead) == false)
 			return STATUS_FAILURE;
 
 		NOB = sFlash2xRead.numOfBytes;
@@ -1510,7 +1507,7 @@
 		}
 
 		/* First make this False so that we can enable the Sector Permission Check in BeceemFlashBulkWrite */
-		Adapter->bAllDSDWriteAllow = FALSE;
+		Adapter->bAllDSDWriteAllow = false;
 
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_WRITE Called");
 
@@ -1531,7 +1528,7 @@
 			return -EINVAL;
 		}
 
-		if (validateFlash2xReadWrite(Adapter, &sFlash2xWrite) == FALSE)
+		if (validateFlash2xReadWrite(Adapter, &sFlash2xWrite) == false)
 			return STATUS_FAILURE;
 
 		InputAddr = sFlash2xWrite.pDataBuff;
@@ -1686,7 +1683,7 @@
 
 	case IOCTL_BCM_IDENTIFY_ACTIVE_SECTION: {
 		/* Right Now we are taking care of only DSD */
-		Adapter->bAllDSDWriteAllow = FALSE;
+		Adapter->bAllDSDWriteAllow = false;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_IDENTIFY_ACTIVE_SECTION called");
 		Status = STATUS_SUCCESS;
 	}
@@ -1697,7 +1694,7 @@
 		Status = STATUS_SUCCESS;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_COPY_SECTION  Called");
 
-		Adapter->bAllDSDWriteAllow = FALSE;
+		Adapter->bAllDSDWriteAllow = false;
 		if (IsFlash2x(Adapter) != TRUE) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
 			return -EINVAL;
@@ -1720,12 +1717,12 @@
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "offset :%x", sCopySectStrut.offset);
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "NOB :%x", sCopySectStrut.numOfBytes);
 
-		if (IsSectionExistInFlash(Adapter, sCopySectStrut.SrcSection) == FALSE) {
+		if (IsSectionExistInFlash(Adapter, sCopySectStrut.SrcSection) == false) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source Section<%x> does not exixt in Flash ", sCopySectStrut.SrcSection);
 			return -EINVAL;
 		}
 
-		if (IsSectionExistInFlash(Adapter, sCopySectStrut.DstSection) == FALSE) {
+		if (IsSectionExistInFlash(Adapter, sCopySectStrut.DstSection) == false) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Destinatio Section<%x> does not exixt in Flash ", sCopySectStrut.DstSection);
 			return -EINVAL;
 		}
@@ -1924,7 +1921,7 @@
 				OutPutBuff = OutPutBuff + ReadBytes;
 			}
 		}
-		Adapter->bFlashRawRead = FALSE;
+		Adapter->bFlashRawRead = false;
 		up(&Adapter->NVMRdmWrmLock);
 		kfree(pReadBuff);
 		break;
@@ -1960,6 +1957,7 @@
 
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n");
 
+		memset(&DevInfo, 0, sizeof(DevInfo));
 		DevInfo.MaxRDMBufferSize = BUFFER_4K;
 		DevInfo.u32DSDStartOffset = EEPROM_CALPARAM_START;
 		DevInfo.u32RxAlignmentCorrection = 0;
diff --git a/drivers/staging/bcm/Bcmnet.c b/drivers/staging/bcm/Bcmnet.c
index 4e470d4..53fee2f 100644
--- a/drivers/staging/bcm/Bcmnet.c
+++ b/drivers/staging/bcm/Bcmnet.c
@@ -6,7 +6,7 @@
 {
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev);
 
-	if (Adapter->fw_download_done == FALSE) {
+	if (Adapter->fw_download_done == false) {
 		pr_notice(PFX "%s: link up failed (download in progress)\n",
 			  dev->name);
 		return -EBUSY;
@@ -142,7 +142,8 @@
 			    struct ethtool_drvinfo *info)
 {
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev);
-	struct bcm_interface_adapter *psIntfAdapter = Adapter->pvInterfaceAdapter;
+	struct bcm_interface_adapter *psIntfAdapter =
+						Adapter->pvInterfaceAdapter;
 	struct usb_device *udev = interface_to_usbdev(psIntfAdapter->interface);
 
 	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c
index 9765145..cc91b5e 100644
--- a/drivers/staging/bcm/CmHost.c
+++ b/drivers/staging/bcm/CmHost.c
@@ -113,7 +113,7 @@
 static inline VOID
 CopyIpAddrToClassifier(struct bcm_classifier_rule *pstClassifierEntry,
 		B_UINT8 u8IpAddressLen, B_UINT8 *pu8IpAddressMaskSrc,
-		BOOLEAN bIpVersion6, enum bcm_ipaddr_context eIpAddrContext)
+		bool bIpVersion6, enum bcm_ipaddr_context eIpAddrContext)
 {
 	int i = 0;
 	UINT nSizeOfIPAddressInBytes = IP_LENGTH_OF_ADDRESS;
@@ -213,7 +213,7 @@
 	}
 }
 
-void ClearTargetDSXBuffer(struct bcm_mini_adapter *Adapter, B_UINT16 TID, BOOLEAN bFreeAll)
+void ClearTargetDSXBuffer(struct bcm_mini_adapter *Adapter, B_UINT16 TID, bool bFreeAll)
 {
 	int i;
 
@@ -256,7 +256,7 @@
 	pstClassifierEntry = &Adapter->astClassifierTable[nClassifierIndex];
 	if (pstClassifierEntry) {
 		/* Store if Ipv6 */
-		pstClassifierEntry->bIpv6Protocol = (Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion == IPV6) ? TRUE : FALSE;
+		pstClassifierEntry->bIpv6Protocol = (Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion == IPV6) ? TRUE : false;
 
 		/* Destinaiton Port */
 		pstClassifierEntry->ucDestPortRangeLength = psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength / 4;
@@ -301,7 +301,7 @@
 				psfCSType->cCPacketClassificationRule.u8IPDestinationAddressLength,
 				psfCSType->cCPacketClassificationRule.u8IPDestinationAddress,
 				(Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion == IPV6) ?
-			TRUE : FALSE, eDestIpAddress);
+			TRUE : false, eDestIpAddress);
 
 		/* Source Ip Address and Mask */
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Ip Source Parameters : ");
@@ -309,7 +309,7 @@
 		CopyIpAddrToClassifier(pstClassifierEntry,
 				psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddressLength,
 				psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddress,
-				(Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion == IPV6) ? TRUE : FALSE,
+				(Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion == IPV6) ? TRUE : false,
 				eSrcIpAddress);
 
 		/* TOS */
@@ -383,7 +383,7 @@
 	u16PacketClassificationRuleIndex = Adapter->astClassifierTable[nClassifierIndex].uiClassifierRuleIndex;
 	pstClassifierEntry = &Adapter->astClassifierTable[nClassifierIndex];
 	if (pstClassifierEntry) {
-		pstClassifierEntry->bUsed = FALSE;
+		pstClassifierEntry->bUsed = false;
 		pstClassifierEntry->uiClassifierRuleIndex = 0;
 		memset(pstClassifierEntry, 0, sizeof(struct bcm_classifier_rule));
 
@@ -685,7 +685,7 @@
 							memcpy(sPhsRule.u8PHSF, psfCSType->cPhsRule.u8PHSF, MAX_PHS_LENGTHS);
 							memcpy(sPhsRule.u8PHSM, psfCSType->cPhsRule.u8PHSM, MAX_PHS_LENGTHS);
 							sPhsRule.u8RefCnt = 0;
-							sPhsRule.bUnclassifiedPHSRule = FALSE;
+							sPhsRule.bUnclassifiedPHSRule = false;
 							sPhsRule.PHSModifiedBytes = 0;
 							sPhsRule.PHSModifiedNumPackets = 0;
 							sPhsRule.PHSErrorNumPackets = 0;
@@ -837,7 +837,7 @@
 	UINT nCurClassifierCnt;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 
-	pstAddIndication = (struct bcm_add_indication_alt *)pvBuffer;
+	pstAddIndication = pvBuffer;
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "======>");
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Type: 0x%X", pstAddIndication->u8Type);
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Direction: 0x%X", pstAddIndication->u8Direction);
@@ -1339,14 +1339,14 @@
 	UINT uiSearchRuleIndex;
 	ULONG ulSFID;
 
-	pstAddIndicationAlt = (struct bcm_add_indication_alt *)(pvBuffer);
+	pstAddIndicationAlt = pvBuffer;
 
 	/*
 	 * In case of DSD Req By MS, we should immediately delete this SF so that
 	 * we can stop the further classifying the pkt for this SF.
 	 */
 	if (pstAddIndicationAlt->u8Type == DSD_REQ) {
-		pstDeletionRequest = (struct bcm_del_request *)pvBuffer;
+		pstDeletionRequest = pvBuffer;
 
 		ulSFID = ntohl(pstDeletionRequest->u32SFID);
 		uiSearchRuleIndex = SearchSfid(Adapter, ulSFID);
@@ -1452,12 +1452,12 @@
 	struct bcm_add_indication *pstAddIndication = NULL;
 	struct bcm_add_indication_alt *pstAddIndicationDest = NULL;
 
-	pstAddIndication = (struct bcm_add_indication *)(pvBuffer);
+	pstAddIndication = pvBuffer;
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "=====>");
 	if ((pstAddIndication->u8Type == DSD_REQ) ||
 		(pstAddIndication->u8Type == DSD_RSP) ||
 		(pstAddIndication->u8Type == DSD_ACK))
-		return (struct bcm_add_indication_alt *)pvBuffer;
+		return pvBuffer;
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Inside RestoreCmControlResponseMessage ");
 	/*
@@ -1577,7 +1577,7 @@
 	ULONG idx, max_try;
 
 	if ((Adapter->ulTotalTargetBuffersAvailable == 0) || (Adapter->ulFreeTargetBufferCnt == 0)) {
-		ClearTargetDSXBuffer(Adapter, tid, FALSE);
+		ClearTargetDSXBuffer(Adapter, tid, false);
 		return 0;
 	}
 
@@ -1590,7 +1590,7 @@
 
 	if (max_try == 0) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "\n GetNextTargetBufferLocation : Error No Free Target DSX Buffers FreeCnt : %lx ", Adapter->ulFreeTargetBufferCnt);
-		ClearTargetDSXBuffer(Adapter, tid, FALSE);
+		ClearTargetDSXBuffer(Adapter, tid, false);
 		return 0;
 	}
 
@@ -1630,7 +1630,7 @@
  * for the Connection Management.
  * @return - Queue index for the free SFID else returns Invalid Index.
  */
-BOOLEAN CmControlResponseMessage(struct bcm_mini_adapter *Adapter,  /* <Pointer to the Adapter structure */
+bool CmControlResponseMessage(struct bcm_mini_adapter *Adapter,  /* <Pointer to the Adapter structure */
 				PVOID pvBuffer /* Starting Address of the Buffer, that contains the AddIndication Data */)
 {
 	struct bcm_connect_mgr_params *psfLocalSet = NULL;
@@ -1644,9 +1644,9 @@
 	 */
 	pstAddIndication = RestoreCmControlResponseMessage(Adapter, pvBuffer);
 	if (pstAddIndication == NULL) {
-		ClearTargetDSXBuffer(Adapter, ((struct bcm_add_indication *)pvBuffer)->u16TID, FALSE);
+		ClearTargetDSXBuffer(Adapter, ((struct bcm_add_indication *)pvBuffer)->u16TID, false);
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Error in restoring Service Flow param structure from DSx message");
-		return FALSE;
+		return false;
 	}
 
 	DumpCmControlPacket(pstAddIndication);
@@ -1656,7 +1656,7 @@
 	pLeader->Status = CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ;
 	pLeader->Vcid = 0;
 
-	ClearTargetDSXBuffer(Adapter, pstAddIndication->u16TID, FALSE);
+	ClearTargetDSXBuffer(Adapter, pstAddIndication->u16TID, false);
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "### TID RECEIVED %d\n", pstAddIndication->u16TID);
 	switch (pstAddIndication->u8Type) {
 	case DSA_REQ:
@@ -1708,9 +1708,9 @@
 			if (pstAddIndication->sfAdmittedSet.bValid == TRUE)
 				Adapter->PackInfo[uiSearchRuleIndex].bAdmittedSet = TRUE;
 
-			if (pstAddIndication->sfActiveSet.bValid == FALSE) {
-				Adapter->PackInfo[uiSearchRuleIndex].bActive = FALSE;
-				Adapter->PackInfo[uiSearchRuleIndex].bActivateRequestSent = FALSE;
+			if (pstAddIndication->sfActiveSet.bValid == false) {
+				Adapter->PackInfo[uiSearchRuleIndex].bActive = false;
+				Adapter->PackInfo[uiSearchRuleIndex].bActivateRequestSent = false;
 				if (pstAddIndication->sfAdmittedSet.bValid)
 					psfLocalSet = &pstAddIndication->sfAdmittedSet;
 				else if (pstAddIndication->sfAuthorizedSet.bValid)
@@ -1722,8 +1722,8 @@
 
 			if (!psfLocalSet) {
 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "No set is valid\n");
-				Adapter->PackInfo[uiSearchRuleIndex].bActive = FALSE;
-				Adapter->PackInfo[uiSearchRuleIndex].bValid = FALSE;
+				Adapter->PackInfo[uiSearchRuleIndex].bActive = false;
+				Adapter->PackInfo[uiSearchRuleIndex].bValid = false;
 				Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value = 0;
 				kfree(pstAddIndication);
 			} else if (psfLocalSet->bValid && (pstAddIndication->u8CC == 0)) {
@@ -1759,15 +1759,15 @@
 					}
 				}
 			} else {
-				Adapter->PackInfo[uiSearchRuleIndex].bActive = FALSE;
-				Adapter->PackInfo[uiSearchRuleIndex].bValid = FALSE;
+				Adapter->PackInfo[uiSearchRuleIndex].bActive = false;
+				Adapter->PackInfo[uiSearchRuleIndex].bValid = false;
 				Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value = 0;
 				kfree(pstAddIndication);
 			}
 		} else {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "DSA ACK did not get valid SFID");
 			kfree(pstAddIndication);
-			return FALSE;
+			return false;
 		}
 	}
 	break;
@@ -1812,9 +1812,9 @@
 			if (pstChangeIndication->sfAdmittedSet.bValid == TRUE)
 				Adapter->PackInfo[uiSearchRuleIndex].bAdmittedSet = TRUE;
 
-			if (pstChangeIndication->sfActiveSet.bValid == FALSE) {
-				Adapter->PackInfo[uiSearchRuleIndex].bActive = FALSE;
-				Adapter->PackInfo[uiSearchRuleIndex].bActivateRequestSent = FALSE;
+			if (pstChangeIndication->sfActiveSet.bValid == false) {
+				Adapter->PackInfo[uiSearchRuleIndex].bActive = false;
+				Adapter->PackInfo[uiSearchRuleIndex].bActivateRequestSent = false;
 
 				if (pstChangeIndication->sfAdmittedSet.bValid)
 					psfLocalSet = &pstChangeIndication->sfAdmittedSet;
@@ -1827,8 +1827,8 @@
 
 			if (!psfLocalSet) {
 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "No set is valid\n");
-				Adapter->PackInfo[uiSearchRuleIndex].bActive = FALSE;
-				Adapter->PackInfo[uiSearchRuleIndex].bValid = FALSE;
+				Adapter->PackInfo[uiSearchRuleIndex].bActive = false;
+				Adapter->PackInfo[uiSearchRuleIndex].bValid = false;
 				Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value = 0;
 				kfree(pstAddIndication);
 			} else if (psfLocalSet->bValid && (pstChangeIndication->u8CC == 0)) {
@@ -1847,7 +1847,7 @@
 		} else {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "DSC ACK did not get valid SFID");
 			kfree(pstAddIndication);
-			return FALSE;
+			return false;
 		}
 	}
 	break;
@@ -1883,7 +1883,7 @@
 		break;
 	default:
 		kfree(pstAddIndication);
-		return FALSE;
+		return false;
 	}
 	return TRUE;
 }
@@ -1934,13 +1934,13 @@
 			continue;
 		}
 
-		if (pHostInfo->RetainSF == FALSE) {
+		if (pHostInfo->RetainSF == false) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Going to Delete SF");
 			deleteSFBySfid(Adapter, uiSearchRuleIndex);
 		} else {
 			Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value = ntohs(pHostInfo->VCID);
 			Adapter->PackInfo[uiSearchRuleIndex].usCID = ntohs(pHostInfo->newCID);
-			Adapter->PackInfo[uiSearchRuleIndex].bActive = FALSE;
+			Adapter->PackInfo[uiSearchRuleIndex].bActive = false;
 
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "pHostInfo->QoSParamSet: 0x%x\n", pHostInfo->QoSParamSet);
 
diff --git a/drivers/staging/bcm/CmHost.h b/drivers/staging/bcm/CmHost.h
index 4ddfc3d4..0887d3f 100644
--- a/drivers/staging/bcm/CmHost.h
+++ b/drivers/staging/bcm/CmHost.h
@@ -55,7 +55,7 @@
 int AllocAdapterDsxBuffer(struct bcm_mini_adapter *Adapter);
 int FreeAdapterDsxBuffer(struct bcm_mini_adapter *Adapter);
 unsigned long SetUpTargetDsxBuffers(struct bcm_mini_adapter *Adapter);
-BOOLEAN CmControlResponseMessage(struct bcm_mini_adapter *Adapter, void *pvBuffer);
+bool CmControlResponseMessage(struct bcm_mini_adapter *Adapter, void *pvBuffer);
 
 #pragma pack(pop)
 
diff --git a/drivers/staging/bcm/DDRInit.c b/drivers/staging/bcm/DDRInit.c
index f5eda96..9f7e30f 100644
--- a/drivers/staging/bcm/DDRInit.c
+++ b/drivers/staging/bcm/DDRInit.c
@@ -1106,7 +1106,7 @@
 	unsigned long ul_ddr_setting_load_addr = DDR_DUMP_INTERNAL_DEVICE_MEMORY;
 	UINT  value = 0;
 	int retval = STATUS_SUCCESS;
-	BOOLEAN bOverrideSelfRefresh = FALSE;
+	bool bOverrideSelfRefresh = false;
 
 	switch (Adapter->chip_id)
 	{
diff --git a/drivers/staging/bcm/HandleControlPacket.c b/drivers/staging/bcm/HandleControlPacket.c
index 1bb53e2..495fe3d 100644
--- a/drivers/staging/bcm/HandleControlPacket.c
+++ b/drivers/staging/bcm/HandleControlPacket.c
@@ -14,10 +14,10 @@
 static VOID handle_rx_control_packet(struct bcm_mini_adapter *Adapter, struct sk_buff *skb)
 {
 	struct bcm_tarang_data *pTarang = NULL;
-	BOOLEAN HighPriorityMessage = FALSE;
+	bool HighPriorityMessage = false;
 	struct sk_buff *newPacket = NULL;
 	CHAR cntrl_msg_mask_bit = 0;
-	BOOLEAN drop_pkt_flag = TRUE;
+	bool drop_pkt_flag = TRUE;
 	USHORT usStatus = *(PUSHORT)(skb->data);
 
 	if (netif_msg_pktdata(Adapter))
@@ -91,13 +91,13 @@
 		 *	cntrl_msg_mask_bit);
 		 */
 		if (pTarang->RxCntrlMsgBitMask & (1 << cntrl_msg_mask_bit))
-			drop_pkt_flag = FALSE;
+			drop_pkt_flag = false;
 
 		if ((drop_pkt_flag == TRUE) ||
 				(pTarang->AppCtrlQueueLen > MAX_APP_QUEUE_LEN)
 				|| ((pTarang->AppCtrlQueueLen >
 					MAX_APP_QUEUE_LEN / 2) &&
-				    (HighPriorityMessage == FALSE))) {
+				    (HighPriorityMessage == false))) {
 			/*
 			 * Assumption:-
 			 * 1. every tarang manages it own dropped pkt
@@ -175,8 +175,8 @@
 			return 0;
 		}
 		if (TRUE == Adapter->bWakeUpDevice) {
-			Adapter->bWakeUpDevice = FALSE;
-			if ((FALSE == Adapter->bTriedToWakeUpFromlowPowerMode)
+			Adapter->bWakeUpDevice = false;
+			if ((false == Adapter->bTriedToWakeUpFromlowPowerMode)
 					&& ((TRUE == Adapter->IdleMode) ||
 					    (TRUE == Adapter->bShutStatus))) {
 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
diff --git a/drivers/staging/bcm/IPv6Protocol.c b/drivers/staging/bcm/IPv6Protocol.c
index 6d803e7..cd16067 100644
--- a/drivers/staging/bcm/IPv6Protocol.c
+++ b/drivers/staging/bcm/IPv6Protocol.c
@@ -1,13 +1,13 @@
 #include "headers.h"
 
-static BOOLEAN MatchSrcIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
+static bool MatchSrcIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
 	struct bcm_ipv6_hdr *pstIpv6Header);
-static BOOLEAN MatchDestIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
+static bool MatchDestIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
 	struct bcm_ipv6_hdr *pstIpv6Header);
 static VOID DumpIpv6Header(struct bcm_ipv6_hdr *pstIpv6Header);
 
 static UCHAR *GetNextIPV6ChainedHeader(UCHAR **ppucPayload,
-	UCHAR *pucNextHeader, BOOLEAN *bParseDone, USHORT *pusPayloadLength)
+	UCHAR *pucNextHeader, bool *bParseDone, USHORT *pusPayloadLength)
 {
 	UCHAR *pucRetHeaderPtr = NULL;
 	UCHAR *pucPayloadPtr = NULL;
@@ -29,7 +29,7 @@
 	}
 
 	/* Get the Nextt Header Type */
-	*bParseDone = FALSE;
+	*bParseDone = false;
 
 
 	switch (*pucNextHeader) {
@@ -124,7 +124,7 @@
 
 	}
 
-	if (*bParseDone == FALSE) {
+	if (*bParseDone == false) {
 		if (*pusPayloadLength <= usNextHeaderOffset) {
 			*bParseDone = TRUE;
 		} else {
@@ -144,7 +144,7 @@
 	USHORT *pusDestPort, USHORT usPayloadLength, UCHAR ucNextHeader)
 {
 	UCHAR *pIpv6HdrScanContext = pucPayload;
-	BOOLEAN bDone = FALSE;
+	bool bDone = false;
 	UCHAR ucHeaderType = 0;
 	UCHAR *pucNextHeader = NULL;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
@@ -187,12 +187,12 @@
 	USHORT	ushSrcPort = 0;
 	UCHAR   ucNextProtocolAboveIP = 0;
 	struct bcm_ipv6_hdr *pstIpv6Header = NULL;
-	BOOLEAN bClassificationSucceed = FALSE;
+	bool bClassificationSucceed = false;
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
 			DBG_LVL_ALL, "IpVersion6 ==========>\n");
 
-	pstIpv6Header = (struct bcm_ipv6_hdr *)pcIpHeader;
+	pstIpv6Header = pcIpHeader;
 
 	DumpIpv6Header(pstIpv6Header);
 
@@ -277,10 +277,10 @@
 		INT iMatchedSFQueueIndex = 0;
 		iMatchedSFQueueIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
 		if (iMatchedSFQueueIndex >= NO_OF_QUEUES) {
-			bClassificationSucceed = FALSE;
+			bClassificationSucceed = false;
 		} else {
-			if (Adapter->PackInfo[iMatchedSFQueueIndex].bActive == FALSE)
-				bClassificationSucceed = FALSE;
+			if (Adapter->PackInfo[iMatchedSFQueueIndex].bActive == false)
+				bClassificationSucceed = false;
 		}
 	}
 
@@ -288,7 +288,7 @@
 }
 
 
-static BOOLEAN MatchSrcIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
+static bool MatchSrcIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
 	struct bcm_ipv6_hdr *pstIpv6Header)
 {
 	UINT uiLoopIndex = 0;
@@ -341,10 +341,10 @@
 			}
 		}
 	}
-	return FALSE;
+	return false;
 }
 
-static BOOLEAN MatchDestIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
+static bool MatchDestIpv6Address(struct bcm_classifier_rule *pstClassifierRule,
 	struct bcm_ipv6_hdr *pstIpv6Header)
 {
 	UINT uiLoopIndex = 0;
@@ -398,7 +398,7 @@
 			}
 		}
 	}
-	return FALSE;
+	return false;
 
 }
 
diff --git a/drivers/staging/bcm/InterfaceDld.c b/drivers/staging/bcm/InterfaceDld.c
index 348ad75..463bdee 100644
--- a/drivers/staging/bcm/InterfaceDld.c
+++ b/drivers/staging/bcm/InterfaceDld.c
@@ -6,7 +6,7 @@
 	mm_segment_t oldfs = {0};
 	int errno = 0, len = 0; /* ,is_config_file = 0 */
 	loff_t pos = 0;
-	struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)arg;
+	struct bcm_interface_adapter *psIntfAdapter = arg;
 	/* struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter; */
 	char *buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
 
@@ -61,7 +61,7 @@
 	loff_t pos = 0;
 	static int fw_down;
 	INT Status = STATUS_SUCCESS;
-	struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)arg;
+	struct bcm_interface_adapter *psIntfAdapter = arg;
 	int bytes;
 
 	buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA);
@@ -166,7 +166,7 @@
 	}
 
 	if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
-		Adapter->LEDInfo.bLedInitDone = FALSE;
+		Adapter->LEDInfo.bLedInitDone = false;
 		Adapter->DriverState = DRIVER_INIT;
 		wake_up(&Adapter->LEDInfo.notify_led_event);
 	}
@@ -214,7 +214,7 @@
 	 * Firmware. Check for the Config file to be first to be sent from the
 	 * Application
 	 */
-	atomic_set(&Adapter->uiMBupdate, FALSE);
+	atomic_set(&Adapter->uiMBupdate, false);
 	if (!Adapter->bCfgDownloaded && psFwInfo->u32StartingAddress != CONFIG_BEGIN_ADDR) {
 		/* Can't Download Firmware. */
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Download the config File first\n");
diff --git a/drivers/staging/bcm/InterfaceIdleMode.c b/drivers/staging/bcm/InterfaceIdleMode.c
index 5347828..5959fbd 100644
--- a/drivers/staging/bcm/InterfaceIdleMode.c
+++ b/drivers/staging/bcm/InterfaceIdleMode.c
@@ -89,8 +89,8 @@
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Device Up from Idle Mode");
 
 			/* Set Idle Mode Flag to False and Clear IdleMode reg. */
-			Adapter->IdleMode = FALSE;
-			Adapter->bTriedToWakeUpFromlowPowerMode = FALSE;
+			Adapter->IdleMode = false;
+			Adapter->bTriedToWakeUpFromlowPowerMode = false;
 
 			wake_up(&Adapter->lowpower_mode_wait_queue);
 
diff --git a/drivers/staging/bcm/InterfaceInit.c b/drivers/staging/bcm/InterfaceInit.c
index 79058ce..3acdb58 100644
--- a/drivers/staging/bcm/InterfaceInit.c
+++ b/drivers/staging/bcm/InterfaceInit.c
@@ -332,7 +332,7 @@
 		 * now register the cntrl interface.
 		 * after downloading the f/w waiting for 5 sec to get the mailbox interrupt.
 		 */
-		psIntfAdapter->psAdapter->waiting_to_fw_download_done = FALSE;
+		psIntfAdapter->psAdapter->waiting_to_fw_download_done = false;
 		value = wait_event_timeout(psIntfAdapter->psAdapter->ioctl_fw_dnld_wait_queue,
 					psIntfAdapter->psAdapter->waiting_to_fw_download_done, 5*HZ);
 
@@ -430,7 +430,7 @@
 	unsigned long value;
 	int retval = 0;
 	int usedIntOutForBulkTransfer = 0 ;
-	BOOLEAN bBcm16 = FALSE;
+	bool bBcm16 = false;
 	UINT uiData = 0;
 	int bytes;
 
@@ -472,7 +472,7 @@
 				retval = usb_set_interface(psIntfAdapter->udev, DEFAULT_SETTING_0, ALTERNATE_SETTING_1);
 			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
 				"BCM16 is applicable on this dongle\n");
-			if (retval || (psIntfAdapter->bHighSpeedDevice == FALSE)) {
+			if (retval || (psIntfAdapter->bHighSpeedDevice == false)) {
 				usedIntOutForBulkTransfer = EP2 ;
 				endpoint = &iface_desc->endpoint[EP2].desc;
 				BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
@@ -481,8 +481,8 @@
 				 * If Modem is high speed device EP2 should be INT OUT End point
 				 * If Mode is FS then EP2 should be bulk end point
 				 */
-				if (((psIntfAdapter->bHighSpeedDevice == TRUE) && (bcm_usb_endpoint_is_int_out(endpoint) == FALSE))
-					|| ((psIntfAdapter->bHighSpeedDevice == FALSE) && (bcm_usb_endpoint_is_bulk_out(endpoint) == FALSE))) {
+				if (((psIntfAdapter->bHighSpeedDevice == TRUE) && (bcm_usb_endpoint_is_int_out(endpoint) == false))
+					|| ((psIntfAdapter->bHighSpeedDevice == false) && (bcm_usb_endpoint_is_bulk_out(endpoint) == false))) {
 					BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
 						"Configuring the EEPROM\n");
 					/* change the EP2, EP4 to INT OUT end point */
@@ -501,7 +501,7 @@
 					}
 
 				}
-				if ((psIntfAdapter->bHighSpeedDevice == FALSE) && bcm_usb_endpoint_is_bulk_out(endpoint)) {
+				if ((psIntfAdapter->bHighSpeedDevice == false) && bcm_usb_endpoint_is_bulk_out(endpoint)) {
 					/* Once BULK is selected in FS mode. Revert it back to INT. Else USB_IF will fail. */
 					UINT _uiData = ntohl(EP2_CFG_INT);
 					BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
@@ -513,7 +513,7 @@
 				endpoint = &iface_desc->endpoint[EP4].desc;
 				BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
 					"Choosing AltSetting as a default setting.\n");
-				if (bcm_usb_endpoint_is_int_out(endpoint) == FALSE) {
+				if (bcm_usb_endpoint_is_int_out(endpoint) == false) {
 					BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,
 						"Dongle does not have BCM16 Fix.\n");
 					/* change the EP2, EP4 to INT OUT end point and use EP4 in altsetting */
@@ -619,7 +619,7 @@
 	psIntfAdapter->bSuspended = TRUE;
 
 	if (TRUE == psIntfAdapter->bPreparingForBusSuspend) {
-		psIntfAdapter->bPreparingForBusSuspend = FALSE;
+		psIntfAdapter->bPreparingForBusSuspend = false;
 
 		if (psIntfAdapter->psAdapter->LinkStatus == LINKUP_DONE) {
 			psIntfAdapter->psAdapter->IdleMode = TRUE ;
@@ -631,7 +631,7 @@
 				"Host Entered in PMU Shutdown Mode.\n");
 		}
 	}
-	psIntfAdapter->psAdapter->bPreparingForLowPowerMode = FALSE;
+	psIntfAdapter->psAdapter->bPreparingForLowPowerMode = false;
 
 	/* Signaling the control pkt path */
 	wake_up(&psIntfAdapter->psAdapter->lowpower_mode_wait_queue);
@@ -644,7 +644,7 @@
 	struct bcm_interface_adapter *psIntfAdapter = usb_get_intfdata(intf);
 
 	mdelay(100);
-	psIntfAdapter->bSuspended = FALSE;
+	psIntfAdapter->bSuspended = false;
 
 	StartInterruptUrb(psIntfAdapter);
 	InterfaceRx(psIntfAdapter);
diff --git a/drivers/staging/bcm/InterfaceIsr.c b/drivers/staging/bcm/InterfaceIsr.c
index 8322f1b..7b39f4f 100644
--- a/drivers/staging/bcm/InterfaceIsr.c
+++ b/drivers/staging/bcm/InterfaceIsr.c
@@ -60,7 +60,7 @@
 				psIntfAdapter->psAdapter->downloadDDR +=1;
 				wake_up(&Adapter->tx_packet_wait_queue);
 			}
-			if(FALSE == Adapter->waiting_to_fw_download_done)
+			if(false == Adapter->waiting_to_fw_download_done)
 			{
 				Adapter->waiting_to_fw_download_done = TRUE;
 				wake_up(&Adapter->ioctl_fw_dnld_wait_queue);
@@ -147,11 +147,11 @@
 {
 	INT status = 0;
 
-	if( FALSE == psIntfAdapter->psAdapter->device_removed &&
-		FALSE == psIntfAdapter->psAdapter->bEndPointHalted &&
-		FALSE == psIntfAdapter->bSuspended &&
-		FALSE == psIntfAdapter->bPreparingForBusSuspend &&
-		FALSE == psIntfAdapter->psAdapter->StopAllXaction)
+	if( false == psIntfAdapter->psAdapter->device_removed &&
+		false == psIntfAdapter->psAdapter->bEndPointHalted &&
+		false == psIntfAdapter->bSuspended &&
+		false == psIntfAdapter->bPreparingForBusSuspend &&
+		false == psIntfAdapter->psAdapter->StopAllXaction)
 	{
 		status = usb_submit_urb(psIntfAdapter->psInterruptUrb, GFP_ATOMIC);
 		if (status)
diff --git a/drivers/staging/bcm/InterfaceMisc.c b/drivers/staging/bcm/InterfaceMisc.c
index afca010..4173fd7 100644
--- a/drivers/staging/bcm/InterfaceMisc.c
+++ b/drivers/staging/bcm/InterfaceMisc.c
@@ -44,7 +44,7 @@
 	else
 		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", bytes);
 
-	psIntfAdapter->psAdapter->DeviceAccess = FALSE;
+	psIntfAdapter->psAdapter->DeviceAccess = false;
 	return bytes;
 }
 
@@ -90,10 +90,10 @@
 
 	if (retval < 0)	{
 		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d", retval);
-		psIntfAdapter->psAdapter->DeviceAccess = FALSE;
+		psIntfAdapter->psAdapter->DeviceAccess = false;
 		return retval;
 	} else {
-		psIntfAdapter->psAdapter->DeviceAccess = FALSE;
+		psIntfAdapter->psAdapter->DeviceAccess = false;
 		BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM sent %d", retval);
 		return STATUS_SUCCESS;
 	}
@@ -104,7 +104,7 @@
 	void *buff,
 	int len)
 {
-	return InterfaceRDM((struct bcm_interface_adapter*)arg, addr, buff, len);
+	return InterfaceRDM((struct bcm_interface_adapter *)arg, addr, buff, len);
 }
 
 int BcmWRM(void *arg,
@@ -211,7 +211,7 @@
 	psIntfAdapter = container_of(work, struct bcm_interface_adapter, usbSuspendWork);
 	intf = psIntfAdapter->interface;
 
-	if (psIntfAdapter->bSuspended == FALSE)
+	if (psIntfAdapter->bSuspended == false)
 		usb_autopm_put_interface(intf);
 }
 
diff --git a/drivers/staging/bcm/InterfaceRx.c b/drivers/staging/bcm/InterfaceRx.c
index 26f5bc7..f2973f5 100644
--- a/drivers/staging/bcm/InterfaceRx.c
+++ b/drivers/staging/bcm/InterfaceRx.c
@@ -19,7 +19,7 @@
 	UINT index = 0;
 
 	if((atomic_read(&psIntfAdapter->uNumRcbUsed) < MAXIMUM_USB_RCB) &&
-		(psIntfAdapter->psAdapter->StopAllXaction == FALSE))
+		(psIntfAdapter->psAdapter->StopAllXaction == false))
 	{
 		index = atomic_read(&psIntfAdapter->uCurrRcb);
 		pRcb = &psIntfAdapter->asUsbRcb[index];
@@ -38,7 +38,7 @@
 static void read_bulk_callback(struct urb *urb)
 {
 	struct sk_buff *skb = NULL;
-	BOOLEAN bHeaderSupressionEnabled = FALSE;
+	bool bHeaderSupressionEnabled = false;
 	int QueueIndex = NO_OF_QUEUES + 1;
 	UINT uiIndex=0;
 	int process_done = 1;
@@ -57,7 +57,7 @@
 		(0 == urb->actual_length)
 		)
 	{
-	 	pRcb->bUsed = FALSE;
+	 	pRcb->bUsed = false;
  		atomic_dec(&psIntfAdapter->uNumRcbUsed);
 		return;
 	}
@@ -73,7 +73,7 @@
 		{
 			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,"Rx URB has got cancelled. status :%d", urb->status);
 		}
-		pRcb->bUsed = FALSE;
+		pRcb->bUsed = false;
  		atomic_dec(&psIntfAdapter->uNumRcbUsed);
 		urb->status = STATUS_SUCCESS ;
 		return ;
@@ -192,7 +192,7 @@
 		}
 	}
  	Adapter->PrevNumRecvDescs++;
-	pRcb->bUsed = FALSE;
+	pRcb->bUsed = false;
 	atomic_dec(&psIntfAdapter->uNumRcbUsed);
 }
 
@@ -205,10 +205,10 @@
 			psIntfAdapter->udev, psIntfAdapter->sBulkIn.bulk_in_endpointAddr),
 		  	urb->transfer_buffer, BCM_USB_MAX_READ_LENGTH, read_bulk_callback,
 			pRcb);
-	if(FALSE == psIntfAdapter->psAdapter->device_removed &&
-	   FALSE == psIntfAdapter->psAdapter->bEndPointHalted &&
-	   FALSE == psIntfAdapter->bSuspended &&
-	   FALSE == psIntfAdapter->bPreparingForBusSuspend)
+	if(false == psIntfAdapter->psAdapter->device_removed &&
+	   false == psIntfAdapter->psAdapter->bEndPointHalted &&
+	   false == psIntfAdapter->bSuspended &&
+	   false == psIntfAdapter->bPreparingForBusSuspend)
 	{
 		retval = usb_submit_urb(urb, GFP_ATOMIC);
 		if (retval)
@@ -240,7 +240,7 @@
 					Other - If an error occurred.
 */
 
-BOOLEAN InterfaceRx (struct bcm_interface_adapter *psIntfAdapter)
+bool InterfaceRx (struct bcm_interface_adapter *psIntfAdapter)
 {
 	USHORT RxDescCount = NUM_RX_DESC - atomic_read(&psIntfAdapter->uNumRcbUsed);
 	struct bcm_usb_rcb *pRcb = NULL;
@@ -253,7 +253,7 @@
 		if(pRcb == NULL)
 		{
 			BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Unable to get Rcb pointer");
-			return FALSE;
+			return false;
 		}
 		//atomic_inc(&psIntfAdapter->uNumRcbUsed);
 		ReceiveRcb(psIntfAdapter, pRcb);
diff --git a/drivers/staging/bcm/InterfaceRx.h b/drivers/staging/bcm/InterfaceRx.h
index 424645e..b4e858b 100644
--- a/drivers/staging/bcm/InterfaceRx.h
+++ b/drivers/staging/bcm/InterfaceRx.h
@@ -1,7 +1,7 @@
 #ifndef _INTERFACE_RX_H
 #define _INTERFACE_RX_H
 
-BOOLEAN InterfaceRx(struct bcm_interface_adapter *Adapter);
+bool InterfaceRx(struct bcm_interface_adapter *Adapter);
 
 #endif
 
diff --git a/drivers/staging/bcm/InterfaceTx.c b/drivers/staging/bcm/InterfaceTx.c
index b8c7855..b9c2784 100644
--- a/drivers/staging/bcm/InterfaceTx.c
+++ b/drivers/staging/bcm/InterfaceTx.c
@@ -7,7 +7,7 @@
 	struct bcm_interface_adapter *psIntfAdapter = pTcb->psIntfAdapter;
 	struct bcm_link_request *pControlMsg = (struct bcm_link_request *)urb->transfer_buffer;
 	struct bcm_mini_adapter *psAdapter = psIntfAdapter->psAdapter ;
-	BOOLEAN bpowerDownMsg = FALSE ;
+	bool bpowerDownMsg = false ;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 
     if (unlikely(netif_msg_tx_done(Adapter)))
@@ -26,7 +26,7 @@
 		}
 	}
 
-	pTcb->bUsed = FALSE;
+	pTcb->bUsed = false;
 	atomic_dec(&psIntfAdapter->uNumTcbUsed);
 
 
@@ -42,7 +42,7 @@
 			//This covers the bus err while Idle Request msg sent down.
 			if(urb->status != STATUS_SUCCESS)
 			{
-				psAdapter->bPreparingForLowPowerMode = FALSE ;
+				psAdapter->bPreparingForLowPowerMode = false ;
 				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"Idle Mode Request msg failed to reach to Modem");
 				//Signalling the cntrl pkt path in Ioctl
 				wake_up(&psAdapter->lowpower_mode_wait_queue);
@@ -50,11 +50,11 @@
 				goto err_exit;
 			}
 
-			if(psAdapter->bDoSuspend == FALSE)
+			if(psAdapter->bDoSuspend == false)
 			{
 				psAdapter->IdleMode = TRUE;
 				//since going in Idle mode completed hence making this var false;
-				psAdapter->bPreparingForLowPowerMode = FALSE ;
+				psAdapter->bPreparingForLowPowerMode = false ;
 
 				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Host Entered in Idle Mode State...");
 				//Signalling the cntrl pkt path in Ioctl
@@ -70,7 +70,7 @@
 			//This covers the bus err while shutdown Request msg sent down.
 			if(urb->status != STATUS_SUCCESS)
 			{
-				psAdapter->bPreparingForLowPowerMode = FALSE ;
+				psAdapter->bPreparingForLowPowerMode = false ;
 				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"Shutdown Request Msg failed to reach to Modem");
 				//Signalling the cntrl pkt path in Ioctl
 				wake_up(&psAdapter->lowpower_mode_wait_queue);
@@ -79,11 +79,11 @@
 			}
 
 			bpowerDownMsg = TRUE ;
-			if(psAdapter->bDoSuspend == FALSE)
+			if(psAdapter->bDoSuspend == false)
 			{
 				psAdapter->bShutStatus = TRUE;
 				//since going in shutdown mode completed hence making this var false;
-				psAdapter->bPreparingForLowPowerMode = FALSE ;
+				psAdapter->bPreparingForLowPowerMode = false ;
 				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"Host Entered in shutdown Mode State...");
 				//Signalling the cntrl pkt path in Ioctl
 				wake_up(&psAdapter->lowpower_mode_wait_queue);
@@ -113,7 +113,7 @@
 	UINT index = 0;
 
 	if((atomic_read(&psIntfAdapter->uNumTcbUsed) < MAXIMUM_USB_TCB) &&
-		(psIntfAdapter->psAdapter->StopAllXaction ==FALSE))
+		(psIntfAdapter->psAdapter->StopAllXaction ==false))
 	{
 		index = atomic_read(&psIntfAdapter->uCurrTcb);
 		pTcb = &psIntfAdapter->asUsbTcb[index];
@@ -161,10 +161,10 @@
 	}
 	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* For DMA transfer */
 
-	if(FALSE == psIntfAdapter->psAdapter->device_removed &&
-	   FALSE == psIntfAdapter->psAdapter->bEndPointHalted &&
-	   FALSE == psIntfAdapter->bSuspended &&
-	   FALSE == psIntfAdapter->bPreparingForBusSuspend)
+	if(false == psIntfAdapter->psAdapter->device_removed &&
+	   false == psIntfAdapter->psAdapter->bEndPointHalted &&
+	   false == psIntfAdapter->bSuspended &&
+	   false == psIntfAdapter->bPreparingForBusSuspend)
 	{
 		retval = usb_submit_urb(urb, GFP_ATOMIC);
 		if (retval)
@@ -184,7 +184,7 @@
 {
 	struct bcm_usb_tcb *pTcb= NULL;
 
-	struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)arg;
+	struct bcm_interface_adapter *psIntfAdapter = arg;
 	pTcb= GetBulkOutTcb(psIntfAdapter);
 	if(pTcb == NULL)
 	{
diff --git a/drivers/staging/bcm/LeakyBucket.c b/drivers/staging/bcm/LeakyBucket.c
index bc48616..f95b067 100644
--- a/drivers/staging/bcm/LeakyBucket.c
+++ b/drivers/staging/bcm/LeakyBucket.c
@@ -82,7 +82,7 @@
 		return 0;
 	}
 
-	if (FALSE != psSF->bValid && psSF->ucDirection) {
+	if (false != psSF->bValid && psSF->ucDirection) {
 		if (0 != psSF->uiCurrentTokenCount) {
 				return psSF->uiCurrentTokenCount;
 		} else {
@@ -188,7 +188,7 @@
 				spin_unlock_bh(&psSF->SFQueueLock);
 
 				Status = SendPacketFromQueue(Adapter, psSF, QueuePacket);
-				psSF->uiPendedLast = FALSE;
+				psSF->uiPendedLast = false;
 			} else {
 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %zd\n", psSF-Adapter->PackInfo);
 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nAvailable Tokens = %d required = %d\n",
@@ -250,7 +250,7 @@
 	UINT uiPrevTotalCount = 0;
 	int iIndex = 0;
 
-	BOOLEAN exit_flag = TRUE;
+	bool exit_flag = TRUE;
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "=====>");
 
@@ -299,7 +299,7 @@
 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex..");
 				CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]);
 				uiPrevTotalCount--;
-				exit_flag = FALSE;
+				exit_flag = false;
 			}
 		}
 
diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c
index 4cfc2c3..7b2fa0f 100644
--- a/drivers/staging/bcm/Misc.c
+++ b/drivers/staging/bcm/Misc.c
@@ -53,7 +53,7 @@
 	init_waitqueue_head(&psAdapter->ioctl_fw_dnld_wait_queue);
 	init_waitqueue_head(&psAdapter->lowpower_mode_wait_queue);
 	psAdapter->waiting_to_fw_download_done = TRUE;
-	psAdapter->fw_download_done = FALSE;
+	psAdapter->fw_download_done = false;
 
 	default_wimax_protocol_initialize(psAdapter);
 	for (i = 0; i < MAX_CNTRL_PKTS; i++) {
@@ -255,7 +255,7 @@
 
 		if (Adapter->bShutStatus == TRUE) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "SYNC UP IN SHUTDOWN..Device WakeUp\n");
-			if (Adapter->bTriedToWakeUpFromlowPowerMode == FALSE) {
+			if (Adapter->bTriedToWakeUpFromlowPowerMode == false) {
 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Waking up for the First Time..\n");
 				Adapter->usIdleModePattern = ABORT_SHUTDOWN_MODE; /* change it to 1 for current support. */
 				Adapter->bWakeUpDevice = TRUE;
@@ -346,7 +346,7 @@
 			pktlen = pLeader->PLength;
 			Status = StoreCmControlResponseMessage(Adapter, pucAddIndication, &pktlen);
 			if (Status != 1) {
-				ClearTargetDSXBuffer(Adapter, ((struct bcm_add_indication_alt *)pucAddIndication)->u16TID, FALSE);
+				ClearTargetDSXBuffer(Adapter, ((struct bcm_add_indication_alt *)pucAddIndication)->u16TID, false);
 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, " Error Restoring The DSX Control Packet. Dsx Buffers on Target may not be Setup Properly ");
 				return STATUS_FAILURE;
 			}
@@ -499,7 +499,7 @@
 			Adapter->bETHCSEnabled = *(pucBuffer+4) & ETH_CS_MASK;
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "PHS Support Status Received In LinkUp Ack : %x\n", Adapter->bPHSEnabled);
 
-			if ((FALSE == Adapter->bShutStatus) && (FALSE == Adapter->IdleMode)) {
+			if ((false == Adapter->bShutStatus) && (false == Adapter->IdleMode)) {
 				if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
 					Adapter->DriverState = NORMAL_OPERATION;
 					wake_up(&Adapter->LEDInfo.notify_led_event);
@@ -517,8 +517,8 @@
 			Adapter->LinkUpStatus = 0;
 			Adapter->LinkStatus = 0;
 			Adapter->usBestEffortQueueIndex = INVALID_QUEUE_INDEX;
-			Adapter->bTriedToWakeUpFromlowPowerMode = FALSE;
-			Adapter->IdleMode = FALSE;
+			Adapter->bTriedToWakeUpFromlowPowerMode = false;
+			Adapter->IdleMode = false;
 			beceem_protocol_reset(Adapter);
 
 			break;
@@ -578,7 +578,7 @@
 
 		stIdleResponse.szData[1] = TARGET_CAN_NOT_GO_TO_IDLE_MODE; /* NACK- device access is going on. */
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "HOST IS NACKING Idle mode To F/W!!!!!!!!");
-		Adapter->bPreparingForLowPowerMode = FALSE;
+		Adapter->bPreparingForLowPowerMode = false;
 	} else {
 		stIdleResponse.szData[1] = TARGET_CAN_GO_TO_IDLE_MODE; /* 2; Idle ACK */
 		Adapter->StatisticsPointer = 0;
@@ -613,7 +613,7 @@
 			if (Adapter->bDoSuspend == TRUE)
 				Bcm_kill_all_URBs((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter));
 		} else {
-			Adapter->bPreparingForLowPowerMode = FALSE;
+			Adapter->bPreparingForLowPowerMode = false;
 		}
 
 		if (!NVMAccess)
@@ -626,7 +626,7 @@
 	status = CopyBufferToControlPacket(Adapter, &stIdleResponse);
 	if ((status != STATUS_SUCCESS)) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "fail to send the Idle mode Request\n");
-		Adapter->bPreparingForLowPowerMode = FALSE;
+		Adapter->bPreparingForLowPowerMode = false;
 		StartInterruptUrb((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter));
 	}
 	do_gettimeofday(&tv);
@@ -651,8 +651,8 @@
 
 	for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "*********** Showing Details Of Queue %d***** ******", uiLoopIndex);
-		if (FALSE == Adapter->PackInfo[uiLoopIndex].bValid) {
-			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bValid is FALSE for %X index\n", uiLoopIndex);
+		if (false == Adapter->PackInfo[uiLoopIndex].bValid) {
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bValid is false for %X index\n", uiLoopIndex);
 			continue;
 		}
 
@@ -783,7 +783,7 @@
 	int bytes;
 
 	psIntfAdapter = ((struct bcm_interface_adapter *)(ps_adapter->pvInterfaceAdapter));
-	ps_adapter->bDDRInitDone = FALSE;
+	ps_adapter->bDDRInitDone = false;
 
 	if (ps_adapter->chip_id >= T3LPB) {
 		/* SYS_CFG register is write protected hence for modifying this reg value, it should be read twice before */
@@ -803,7 +803,7 @@
 	if (ps_adapter->chip_id >= T3LPB) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Resetting UMA-B\n");
 		retval = usb_reset_device(psIntfAdapter->udev);
-		psIntfAdapter->psAdapter->StopAllXaction = FALSE;
+		psIntfAdapter->psAdapter->StopAllXaction = false;
 
 		if (retval != STATUS_SUCCESS) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reset failed with ret value :%d", retval);
@@ -888,7 +888,7 @@
 	wrmalt(ps_adapter, 0x0f01186c, &uiResetValue, sizeof(uiResetValue));
 
 err_exit:
-	psIntfAdapter->psAdapter->StopAllXaction = FALSE;
+	psIntfAdapter->psAdapter->StopAllXaction = false;
 	return retval;
 }
 
@@ -968,7 +968,7 @@
 		return -EIO;
 	}
 
-	if (FALSE == ps_adapter->AutoFirmDld) {
+	if (false == ps_adapter->AutoFirmDld) {
 		BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "AutoFirmDld Disabled in CFG File..\n");
 		/* If Auto f/w download is disable, register the control interface, */
 		/* register the control interface after the mailbox. */
@@ -1094,7 +1094,7 @@
 
 	if (ntohl(Adapter->pstargetparams->m_u32PhyParameter2) & AUTO_SYNC_DISABLE) {
 		pr_info(DRV_NAME ": AutoSyncup is Disabled\n");
-		Adapter->AutoSyncup = FALSE;
+		Adapter->AutoSyncup = false;
 	} else {
 		pr_info(DRV_NAME ": AutoSyncup is Enabled\n");
 		Adapter->AutoSyncup = TRUE;
@@ -1105,7 +1105,7 @@
 		Adapter->AutoLinkUp = TRUE;
 	} else {
 		pr_info(DRV_NAME ": Disabling autolink up");
-		Adapter->AutoLinkUp = FALSE;
+		Adapter->AutoLinkUp = false;
 	}
 	/* Setting the DDR Setting.. */
 	Adapter->DDRSetting = (ntohl(Adapter->pstargetparams->HostDrvrConfig6) >> 8)&0x0F;
@@ -1117,7 +1117,7 @@
 		Adapter->AutoFirmDld = TRUE;
 	} else {
 		pr_info(DRV_NAME ": Disabling Auto Firmware Download\n");
-		Adapter->AutoFirmDld = FALSE;
+		Adapter->AutoFirmDld = false;
 	}
 	uiHostDrvrCfg6 = ntohl(Adapter->pstargetparams->HostDrvrConfig6);
 	Adapter->bMipsConfig = (uiHostDrvrCfg6>>20)&0x01;
@@ -1155,21 +1155,21 @@
 
 	if (reporting_mode == TRUE) {
 		BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "can't do suspen/resume as reporting mode is enable");
-		psAdapter->bDoSuspend = FALSE;
+		psAdapter->bDoSuspend = false;
 	}
 
 	if (psAdapter->bIsAutoCorrectEnabled && (psAdapter->chip_id >= T3LPB)) {
 		/* If reporting mode is enable, switch PMU to PMC */
 		{
 			psAdapter->ulPowerSaveMode = DEVICE_POWERSAVE_MODE_AS_PMU_CLOCK_GATING;
-			psAdapter->bDoSuspend = FALSE;
+			psAdapter->bDoSuspend = false;
 		}
 
 		/* clearing space bit[15..12] */
 		psAdapter->pstargetparams->HostDrvrConfig6 &= ~(htonl((0xF << 12)));
 		/* placing the power save mode option */
 		psAdapter->pstargetparams->HostDrvrConfig6 |= htonl((psAdapter->ulPowerSaveMode << 12));
-	} else if (psAdapter->bIsAutoCorrectEnabled == FALSE) {
+	} else if (psAdapter->bIsAutoCorrectEnabled == false) {
 		/* remove the autocorrect disable bit set before dumping. */
 		psAdapter->ulPowerSaveMode &= ~(1 << 3);
 		psAdapter->pstargetparams->HostDrvrConfig6 &= ~(htonl(1 << 15));
@@ -1302,8 +1302,8 @@
 		wake_up(&Adapter->LEDInfo.notify_led_event);
 	}
 
-	Adapter->bTriedToWakeUpFromlowPowerMode = FALSE;
-	Adapter->bShutStatus = FALSE;
+	Adapter->bTriedToWakeUpFromlowPowerMode = false;
+	Adapter->bShutStatus = false;
 	wake_up(&Adapter->lowpower_mode_wait_queue);
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n");
 }
@@ -1341,7 +1341,7 @@
 
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Device Access is going on NACK the Shut Down MODE\n");
 		stShutdownResponse.szData[2] = SHUTDOWN_NACK_FROM_DRIVER; /* NACK- device access is going on. */
-		Adapter->bPreparingForLowPowerMode = FALSE;
+		Adapter->bPreparingForLowPowerMode = false;
 	} else {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Sending SHUTDOWN MODE ACK\n");
 		stShutdownResponse.szData[2] = SHUTDOWN_ACK_FROM_DRIVER; /* ShutDown ACK */
@@ -1374,7 +1374,7 @@
 			if (Adapter->bDoSuspend == TRUE)
 				Bcm_kill_all_URBs((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter));
 		} else {
-			Adapter->bPreparingForLowPowerMode = FALSE;
+			Adapter->bPreparingForLowPowerMode = false;
 		}
 
 		if (!NVMAccess)
@@ -1387,7 +1387,7 @@
 	Status = CopyBufferToControlPacket(Adapter, &stShutdownResponse);
 	if ((Status != STATUS_SUCCESS)) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "fail to send the Idle mode Request\n");
-		Adapter->bPreparingForLowPowerMode = FALSE;
+		Adapter->bPreparingForLowPowerMode = false;
 		StartInterruptUrb((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter));
 	}
 }
@@ -1430,11 +1430,11 @@
 	Adapter->LinkStatus = 0;
 	atomic_set(&Adapter->cntrlpktCnt, 0);
 	atomic_set(&Adapter->TotalPacketCount, 0);
-	Adapter->fw_download_done = FALSE;
+	Adapter->fw_download_done = false;
 	Adapter->LinkStatus = 0;
-	Adapter->AutoLinkUp = FALSE;
-	Adapter->IdleMode = FALSE;
-	Adapter->bShutStatus = FALSE;
+	Adapter->AutoLinkUp = false;
+	Adapter->IdleMode = false;
+	Adapter->bShutStatus = false;
 }
 
 struct bcm_classifier_rule *GetFragIPClsEntry(struct bcm_mini_adapter *Adapter, USHORT usIpIdentification, ULONG SrcIP)
@@ -1521,7 +1521,7 @@
 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Invalid VCID : %x\n", Adapter->PackInfo[iIndex].usVCID_Value);
 		}
 	}
-	atomic_set(&Adapter->uiMBupdate, FALSE);
+	atomic_set(&Adapter->uiMBupdate, false);
 }
 
 void flush_queue(struct bcm_mini_adapter *Adapter, unsigned int iQIndex)
@@ -1557,8 +1557,8 @@
 	netif_carrier_off(Adapter->dev);
 	netif_stop_queue(Adapter->dev);
 
-	Adapter->IdleMode = FALSE;
-	Adapter->LinkUpStatus = FALSE;
+	Adapter->IdleMode = false;
+	Adapter->LinkUpStatus = false;
 	ClearTargetDSXBuffer(Adapter, 0, TRUE);
 	/* Delete All Classifier Rules */
 
@@ -1568,7 +1568,7 @@
 	flush_all_queues(Adapter);
 
 	if (Adapter->TimerActive == TRUE)
-		Adapter->TimerActive = FALSE;
+		Adapter->TimerActive = false;
 
 	memset(Adapter->astFragmentedPktClassifierTable, 0, sizeof(struct bcm_fragmented_packet_info) * MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES);
 
diff --git a/drivers/staging/bcm/PHSModule.c b/drivers/staging/bcm/PHSModule.c
index af5d22f..892ebc6 100644
--- a/drivers/staging/bcm/PHSModule.c
+++ b/drivers/staging/bcm/PHSModule.c
@@ -8,9 +8,9 @@
 
 static UINT UpdateClassifierPHSRule(B_UINT16 uiClsId, struct bcm_phs_classifier_entry *pstClassifierEntry, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *psPhsRule, B_UINT8 u8AssociatedPHSI);
 
-static BOOLEAN ValidatePHSRuleComplete(struct bcm_phs_rule *psPhsRule);
+static bool ValidatePHSRuleComplete(struct bcm_phs_rule *psPhsRule);
 
-static BOOLEAN DerefPhsRule(B_UINT16 uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *pstPhsRule);
+static bool DerefPhsRule(B_UINT16 uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *pstPhsRule);
 
 static UINT GetClassifierEntry(struct bcm_phs_classifier_table *pstClassifierTable, B_UINT32 uiClsid, enum bcm_phs_classifier_context eClsContext, struct bcm_phs_classifier_entry **ppstClassifierEntry);
 
@@ -67,7 +67,7 @@
 		struct sk_buff **pPacket,
 		USHORT Vcid,
 		B_UINT16 uiClassifierRuleID,
-		BOOLEAN bHeaderSuppressionEnabled,
+		bool bHeaderSuppressionEnabled,
 		UINT *PacketLen,
 		UCHAR bEthCSSupport)
 {
@@ -81,7 +81,7 @@
 	PUCHAR pucPHSPktHdrOutBuf = Adapter->stPhsTxContextInfo.ucaHdrSuppressionOutBuf;
 	UINT usPacketType;
 	UINT BytesToRemove = 0;
-	BOOLEAN bPHSI = 0;
+	bool bPHSI = 0;
 	LONG ulPhsStatus = 0;
 	UINT numBytesCompressed = 0;
 	struct sk_buff *newPacket = NULL;
@@ -569,7 +569,7 @@
 				memset(&pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex], 0, sizeof(struct bcm_phs_classifier_entry));
 			}
 		}
-		pstServiceFlowEntry->bUsed = FALSE;
+		pstServiceFlowEntry->bUsed = false;
 		pstServiceFlowEntry->uiVcid = 0;
 	}
 
@@ -596,7 +596,7 @@
  * 0 if successful,
  * >0 Error.
  */
-ULONG PhsCompress(IN void *pvContext,
+static ULONG PhsCompress(IN void *pvContext,
 		IN B_UINT16 uiVcid,
 		IN B_UINT16 uiClsId,
 		IN void *pvInputBuffer,
@@ -677,7 +677,7 @@
  * 0 if successful,
  * >0 Error.
  */
-ULONG PhsDeCompress(IN void *pvContext,
+static ULONG PhsDeCompress(IN void *pvContext,
 		IN B_UINT16 uiVcid,
 		IN void *pvInputBuffer,
 		OUT void *pvOutputBuffer,
@@ -788,26 +788,26 @@
 	psServiceFlowRulesTable = NULL;
 }
 
-static BOOLEAN ValidatePHSRuleComplete(IN struct bcm_phs_rule *psPhsRule)
+static bool ValidatePHSRuleComplete(IN struct bcm_phs_rule *psPhsRule)
 {
 	if (psPhsRule) {
 		if (!psPhsRule->u8PHSI) {
 			/* PHSI is not valid */
-			return FALSE;
+			return false;
 		}
 
 		if (!psPhsRule->u8PHSS) {
 			/* PHSS Is Undefined */
-			return FALSE;
+			return false;
 		}
 
 		/* Check if PHSF is defines for the PHS Rule */
 		if (!psPhsRule->u8PHSFLength) /* If any part of PHSF is valid then Rule contains valid PHSF */
-			return FALSE;
+			return false;
 
 		return TRUE;
 	} else
-		return FALSE;
+		return false;
 }
 
 UINT GetServiceFlowEntry(IN struct bcm_phs_table *psServiceFlowTable,
@@ -829,7 +829,7 @@
 	return PHS_INVALID_TABLE_INDEX;
 }
 
-UINT GetClassifierEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
+static UINT GetClassifierEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
 			IN B_UINT32 uiClsid, enum bcm_phs_classifier_context eClsContext,
 			OUT struct bcm_phs_classifier_entry **ppstClassifierEntry)
 {
@@ -880,7 +880,7 @@
 	return PHS_INVALID_TABLE_INDEX;
 }
 
-UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid, IN B_UINT16  uiClsId,
+static UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid, IN B_UINT16  uiClsId,
 				IN struct bcm_phs_table *psServiceFlowTable,
 				struct bcm_phs_rule *psPhsRule,
 				B_UINT8 u8AssociatedPHSI)
@@ -888,7 +888,7 @@
 	struct bcm_phs_classifier_table *psaClassifiertable = NULL;
 	UINT uiStatus = 0;
 	int iSfIndex;
-	BOOLEAN bFreeEntryFound = FALSE;
+	bool bFreeEntryFound = false;
 
 	/* Check for a free entry in SFID table */
 	for (iSfIndex = 0; iSfIndex < MAX_SERVICEFLOWS; iSfIndex++) {
@@ -913,7 +913,7 @@
 	return uiStatus;
 }
 
-UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid,
+static UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid,
 				IN B_UINT16 uiClsId,
 				IN struct bcm_phs_entry *pstServiceFlowEntry,
 				struct bcm_phs_rule *psPhsRule,
@@ -1009,7 +1009,7 @@
 				B_UINT8 u8AssociatedPHSI)
 {
 	UINT iClassifierIndex = 0;
-	BOOLEAN bFreeEntryFound = FALSE;
+	bool bFreeEntryFound = false;
 	struct bcm_phs_classifier_entry *psClassifierRules = NULL;
 	UINT nStatus = PHS_SUCCESS;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
@@ -1102,7 +1102,7 @@
 {
 	struct bcm_phs_rule *pstAddPhsRule = NULL;
 	UINT nPhsRuleIndex = 0;
-	BOOLEAN bPHSRuleOrphaned = FALSE;
+	bool bPHSRuleOrphaned = false;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 
 	psPhsRule->u8RefCnt = 0;
@@ -1124,7 +1124,7 @@
 		}
 
 		/* Step 2.a PHS Rule Does Not Exist .Create New PHS Rule for uiClsId */
-		if (FALSE == bPHSRuleOrphaned) {
+		if (false == bPHSRuleOrphaned) {
 
 			pstClassifierEntry->pstPhsRule = kmalloc(sizeof(struct bcm_phs_rule), GFP_KERNEL);
 			if (NULL == pstClassifierEntry->pstPhsRule)
@@ -1150,10 +1150,10 @@
 	return PHS_SUCCESS;
 }
 
-static BOOLEAN DerefPhsRule(IN B_UINT16  uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *pstPhsRule)
+static bool DerefPhsRule(IN B_UINT16  uiClsId, struct bcm_phs_classifier_table *psaClassifiertable, struct bcm_phs_rule *pstPhsRule)
 {
 	if (pstPhsRule == NULL)
-		return FALSE;
+		return false;
 
 	if (pstPhsRule->u8RefCnt)
 		pstPhsRule->u8RefCnt--;
@@ -1166,7 +1166,7 @@
 		 */
 		return TRUE;
 	} else
-		return FALSE;
+		return false;
 }
 
 void DumpPhsRules(struct bcm_phs_extension *pDeviceExtension)
@@ -1239,7 +1239,7 @@
  *			header.
  *	0	-If PHS rule is NULL.If PHSI is 0 indicateing packet as uncompressed.
  */
-int phs_decompress(unsigned char *in_buf,
+static int phs_decompress(unsigned char *in_buf,
 		unsigned char *out_buf,
 		struct bcm_phs_rule *decomp_phs_rules,
 		UINT *header_size)
diff --git a/drivers/staging/bcm/PHSModule.h b/drivers/staging/bcm/PHSModule.h
index 82d8682..d697f9c 100644
--- a/drivers/staging/bcm/PHSModule.h
+++ b/drivers/staging/bcm/PHSModule.h
@@ -5,7 +5,7 @@
 					struct sk_buff **pPacket,
 					 USHORT Vcid,
 					 B_UINT16 uiClassifierRuleID,
-					 BOOLEAN bHeaderSuppressionEnabled,
+					 bool bHeaderSuppressionEnabled,
 					 PUINT PacketLen,
 					 UCHAR bEthCSSupport);
 
@@ -39,7 +39,7 @@
 ULONG PhsDeleteSFRules(void* pvContext,B_UINT16 uiVcid) ;
 
 
-BOOLEAN ValidatePHSRule(struct bcm_phs_rule *psPhsRule);
+bool ValidatePHSRule(struct bcm_phs_rule *psPhsRule);
 
 UINT GetServiceFlowEntry(struct bcm_phs_table *psServiceFlowTable,B_UINT16 uiVcid, struct bcm_phs_entry **ppstServiceFlowEntry);
 
diff --git a/drivers/staging/bcm/Prototypes.h b/drivers/staging/bcm/Prototypes.h
index 2a673b1..fb53a00 100644
--- a/drivers/staging/bcm/Prototypes.h
+++ b/drivers/staging/bcm/Prototypes.h
@@ -111,7 +111,7 @@
 
 void update_per_sf_desc_cnts( struct bcm_mini_adapter *Adapter);
 
-void ClearTargetDSXBuffer(struct bcm_mini_adapter *Adapter,B_UINT16 TID,BOOLEAN bFreeAll);
+void ClearTargetDSXBuffer(struct bcm_mini_adapter *Adapter,B_UINT16 TID,bool bFreeAll);
 
 
 void flush_queue(struct bcm_mini_adapter *Adapter, UINT iQIndex);
@@ -138,7 +138,7 @@
 	PUCHAR pBuffer,
 	UINT uiOffset,
 	UINT uiNumBytes,
-	BOOLEAN bVerify);
+	bool bVerify);
 
 
 INT ReadBeceemEEPROM(struct bcm_mini_adapter *Adapter,UINT dwAddress, UINT *pdwData);
@@ -155,13 +155,13 @@
 	PUINT pBuffer,
 	UINT uiOffset,
 	UINT uiNumBytes,
-	BOOLEAN bVerify);
+	bool bVerify);
 
 
 INT BcmInitNVM(struct bcm_mini_adapter *Adapter);
 
 INT BcmUpdateSectorSize(struct bcm_mini_adapter *Adapter,UINT uiSectorSize);
-BOOLEAN IsSectionExistInFlash(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val section);
+bool IsSectionExistInFlash(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val section);
 
 INT BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_bitmap *psFlash2xBitMap);
 
@@ -198,7 +198,7 @@
 						UINT numOfBytes);
 
 
-BOOLEAN IsNonCDLessDevice(struct bcm_mini_adapter *Adapter);
+bool IsNonCDLessDevice(struct bcm_mini_adapter *Adapter);
 
 
 VOID OverrideServiceFlowParams(struct bcm_mini_adapter *Adapter,PUINT puiBuffer);
@@ -212,7 +212,7 @@
 
 
 VOID putUsbSuspend(struct work_struct *work);
-BOOLEAN IsReqGpioIsLedInNVM(struct bcm_mini_adapter *Adapter, UINT gpios);
+bool IsReqGpioIsLedInNVM(struct bcm_mini_adapter *Adapter, UINT gpios);
 
 
 #endif
diff --git a/drivers/staging/bcm/Qos.c b/drivers/staging/bcm/Qos.c
index 2d4a77c..1609a2b 100644
--- a/drivers/staging/bcm/Qos.c
+++ b/drivers/staging/bcm/Qos.c
@@ -5,7 +5,7 @@
 #include "headers.h"
 
 static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter, PVOID pvEthPayload, struct bcm_eth_packet_info *pstEthCsPktInfo);
-static BOOLEAN EThCSClassifyPkt(struct bcm_mini_adapter *Adapter, struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo, struct bcm_classifier_rule *pstClassifierRule, B_UINT8 EthCSCupport);
+static bool EThCSClassifyPkt(struct bcm_mini_adapter *Adapter, struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo, struct bcm_classifier_rule *pstClassifierRule, B_UINT8 EthCSCupport);
 
 static USHORT	IpVersion4(struct bcm_mini_adapter *Adapter, struct iphdr *iphd,
 			   struct bcm_classifier_rule *pstClassifierRule);
@@ -24,7 +24,7 @@
 *
 * Returns     - TRUE(If address matches) else FAIL .
 *********************************************************************/
-BOOLEAN MatchSrcIpAddress(struct bcm_classifier_rule *pstClassifierRule, ULONG ulSrcIP)
+bool MatchSrcIpAddress(struct bcm_classifier_rule *pstClassifierRule, ULONG ulSrcIP)
 {
 	UCHAR ucLoopIndex = 0;
 
@@ -43,7 +43,7 @@
 		}
 	}
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Not Matched");
-	return FALSE;
+	return false;
 }
 
 
@@ -58,7 +58,7 @@
 *
 * Returns     - TRUE(If address matches) else FAIL .
 *********************************************************************/
-BOOLEAN MatchDestIpAddress(struct bcm_classifier_rule *pstClassifierRule, ULONG ulDestIP)
+bool MatchDestIpAddress(struct bcm_classifier_rule *pstClassifierRule, ULONG ulDestIP)
 {
 	UCHAR ucLoopIndex = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
@@ -77,7 +77,7 @@
 		}
 	}
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address Not Matched");
-	return FALSE;
+	return false;
 }
 
 
@@ -91,7 +91,7 @@
 *
 * Returns     - TRUE(If address matches) else FAIL.
 **************************************************************************/
-BOOLEAN MatchTos(struct bcm_classifier_rule *pstClassifierRule, UCHAR ucTypeOfService)
+bool MatchTos(struct bcm_classifier_rule *pstClassifierRule, UCHAR ucTypeOfService)
 {
 
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
@@ -103,7 +103,7 @@
 		return TRUE;
 	}
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Type Of Service Not Matched");
-	return FALSE;
+	return false;
 }
 
 
@@ -132,7 +132,7 @@
 		}
 	}
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Not Matched");
-	return FALSE;
+	return false;
 }
 
 
@@ -164,7 +164,7 @@
 		}
 	}
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port: %x Not Matched ", ushSrcPort);
-	return FALSE;
+	return false;
 }
 
 
@@ -197,7 +197,7 @@
 		}
 	}
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dest Port: %x Not Matched", ushDestPort);
-	return FALSE;
+	return false;
 }
 /**
 @ingroup tx_functions
@@ -209,7 +209,7 @@
 			   struct bcm_classifier_rule *pstClassifierRule)
 {
 	struct bcm_transport_header *xprt_hdr = NULL;
-	BOOLEAN	bClassificationSucceed = FALSE;
+	bool	bClassificationSucceed = false;
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "========>");
 
@@ -223,7 +223,7 @@
 		//Checking classifier validity
 		if (!pstClassifierRule->bUsed || pstClassifierRule->ucDirection == DOWNLINK_DIR)
 		{
-			bClassificationSucceed = FALSE;
+			bClassificationSucceed = false;
 			break;
 		}
 
@@ -233,17 +233,17 @@
 
 		//**************Checking IP header parameter**************************//
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Trying to match Source IP Address");
-		if (FALSE == (bClassificationSucceed =
+		if (false == (bClassificationSucceed =
 			MatchSrcIpAddress(pstClassifierRule, iphd->saddr)))
 			break;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source IP Address Matched");
 
-		if (FALSE == (bClassificationSucceed =
+		if (false == (bClassificationSucceed =
 			MatchDestIpAddress(pstClassifierRule, iphd->daddr)))
 			break;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination IP Address Matched");
 
-		if (FALSE == (bClassificationSucceed =
+		if (false == (bClassificationSucceed =
 			MatchTos(pstClassifierRule, iphd->tos)))
 		{
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Match failed\n");
@@ -251,7 +251,7 @@
 		}
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Matched");
 
-		if (FALSE == (bClassificationSucceed =
+		if (false == (bClassificationSucceed =
 			MatchProtocol(pstClassifierRule, iphd->protocol)))
 			break;
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Matched");
@@ -263,7 +263,7 @@
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source Port %04x",
 			(iphd->protocol == UDP) ? xprt_hdr->uhdr.source : xprt_hdr->thdr.source);
 
-		if (FALSE == (bClassificationSucceed =
+		if (false == (bClassificationSucceed =
 			MatchSrcPort(pstClassifierRule,
 				ntohs((iphd->protocol == UDP) ?
 				xprt_hdr->uhdr.source : xprt_hdr->thdr.source))))
@@ -273,7 +273,7 @@
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Port %04x",
 			(iphd->protocol == UDP) ? xprt_hdr->uhdr.dest :
 			xprt_hdr->thdr.dest);
-		if (FALSE == (bClassificationSucceed =
+		if (false == (bClassificationSucceed =
 			MatchDestPort(pstClassifierRule,
 			ntohs((iphd->protocol == UDP) ?
 			xprt_hdr->uhdr.dest : xprt_hdr->thdr.dest))))
@@ -286,13 +286,13 @@
 		iMatchedSFQueueIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
 		if (iMatchedSFQueueIndex >= NO_OF_QUEUES)
 		{
-			bClassificationSucceed = FALSE;
+			bClassificationSucceed = false;
 		}
 		else
 		{
-			if (FALSE == Adapter->PackInfo[iMatchedSFQueueIndex].bActive)
+			if (false == Adapter->PackInfo[iMatchedSFQueueIndex].bActive)
 			{
-				bClassificationSucceed = FALSE;
+				bClassificationSucceed = false;
 			}
 		}
 	}
@@ -451,7 +451,7 @@
 	struct iphdr *pIpHeader = NULL;
 	INT	  uiSfIndex = 0;
 	USHORT	usIndex = Adapter->usBestEffortQueueIndex;
-	BOOLEAN	bFragmentedPkt = FALSE, bClassificationSucceed = FALSE;
+	bool	bFragmentedPkt = false, bClassificationSucceed = false;
 	USHORT	usCurrFragment = 0;
 
 	struct bcm_tcp_header *pTcpHeader;
@@ -529,16 +529,16 @@
 		//to classify the packet until match found
 		do
 		{
-			if (FALSE == Adapter->astClassifierTable[uiLoopIndex].bUsed)
+			if (false == Adapter->astClassifierTable[uiLoopIndex].bUsed)
 			{
-				bClassificationSucceed = FALSE;
+				bClassificationSucceed = false;
 				break;
 			}
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "Adapter->PackInfo[%d].bvalid=True\n", uiLoopIndex);
 
 			if (0 == Adapter->astClassifierTable[uiLoopIndex].ucDirection)
 			{
-				bClassificationSucceed = FALSE;//cannot be processed for classification.
+				bClassificationSucceed = false;//cannot be processed for classification.
 				break;						// it is a down link connection
 			}
 
@@ -556,7 +556,7 @@
 				if (eEthUnsupportedFrame == stEthCsPktInfo.eNwpktEthFrameType)
 				{
 					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a Valid Supported Ethernet Frame\n");
-					bClassificationSucceed = FALSE;
+					bClassificationSucceed = false;
 					break;
 				}
 
@@ -577,7 +577,7 @@
 				if (eEthOtherFrame != stEthCsPktInfo.eNwpktEthFrameType)
 				{
 					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a 802.3 Ethernet Frame... hence not allowed over non-ETH CS SF\n");
-					bClassificationSucceed = FALSE;
+					bClassificationSucceed = false;
 					break;
 				}
 			}
@@ -590,7 +590,7 @@
 				if (stEthCsPktInfo.eNwpktIPFrameType == eNonIPPacket)
 				{
 					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet is Not an IP Packet\n");
-					bClassificationSucceed = FALSE;
+					bClassificationSucceed = false;
 					break;
 				}
 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dump IP Header :\n");
@@ -636,7 +636,7 @@
 			stFragPktInfo.ulSrcIpAddress = pIpHeader->saddr;
 			stFragPktInfo.usIpIdentification = pIpHeader->id;
 			stFragPktInfo.pstMatchedClassifierEntry = pstClassifierRule;
-			stFragPktInfo.bOutOfOrderFragment = FALSE;
+			stFragPktInfo.bOutOfOrderFragment = false;
 			AddFragIPClsEntry(Adapter, &stFragPktInfo);
 		}
 
@@ -649,7 +649,7 @@
 		return INVALID_QUEUE_INDEX;
 }
 
-static BOOLEAN EthCSMatchSrcMACAddress(struct bcm_classifier_rule *pstClassifierRule, PUCHAR Mac)
+static bool EthCSMatchSrcMACAddress(struct bcm_classifier_rule *pstClassifierRule, PUCHAR Mac)
 {
 	UINT i = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
@@ -661,12 +661,12 @@
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n", i, Mac[i], pstClassifierRule->au8EThCSSrcMAC[i], pstClassifierRule->au8EThCSSrcMACMask[i]);
 		if ((pstClassifierRule->au8EThCSSrcMAC[i] & pstClassifierRule->au8EThCSSrcMACMask[i]) !=
 			(Mac[i] & pstClassifierRule->au8EThCSSrcMACMask[i]))
-			return FALSE;
+			return false;
 	}
 	return TRUE;
 }
 
-static BOOLEAN EthCSMatchDestMACAddress(struct bcm_classifier_rule *pstClassifierRule, PUCHAR Mac)
+static bool EthCSMatchDestMACAddress(struct bcm_classifier_rule *pstClassifierRule, PUCHAR Mac)
 {
 	UINT i = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
@@ -678,12 +678,12 @@
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n", i, Mac[i], pstClassifierRule->au8EThCSDestMAC[i], pstClassifierRule->au8EThCSDestMACMask[i]);
 		if ((pstClassifierRule->au8EThCSDestMAC[i] & pstClassifierRule->au8EThCSDestMACMask[i]) !=
 			(Mac[i] & pstClassifierRule->au8EThCSDestMACMask[i]))
-			return FALSE;
+			return false;
 	}
 	return TRUE;
 }
 
-static BOOLEAN EthCSMatchEThTypeSAP(struct bcm_classifier_rule *pstClassifierRule, struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo)
+static bool EthCSMatchEThTypeSAP(struct bcm_classifier_rule *pstClassifierRule, struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo)
 {
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
 	if ((pstClassifierRule->ucEtherTypeLen == 0) ||
@@ -698,29 +698,29 @@
 		if (memcmp(&pstEthCsPktInfo->usEtherType, &pstClassifierRule->au8EthCSEtherType[1], 2) == 0)
 			return TRUE;
 		else
-			return FALSE;
+			return false;
 	}
 
 	if (pstClassifierRule->au8EthCSEtherType[0] == 2)
 	{
 		if (eEth802LLCFrame != pstEthCsPktInfo->eNwpktEthFrameType)
-			return FALSE;
+			return false;
 
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s  EthCS DSAP:%x EtherType[2]:%x\n", __FUNCTION__, pstEthCsPktInfo->ucDSAP, pstClassifierRule->au8EthCSEtherType[2]);
 		if (pstEthCsPktInfo->ucDSAP == pstClassifierRule->au8EthCSEtherType[2])
 			return TRUE;
 		else
-			return FALSE;
+			return false;
 
 	}
 
-	return FALSE;
+	return false;
 
 }
 
-static BOOLEAN EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule, struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo)
+static bool EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule, struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo)
 {
-	BOOLEAN bClassificationSucceed = FALSE;
+	bool bClassificationSucceed = false;
 	USHORT usVLANID;
 	B_UINT8 uPriority = 0;
 	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
@@ -731,7 +731,7 @@
 	if (pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_USER_PRIORITY_VALID))
 	{
 		if (pstEthCsPktInfo->eNwpktEthFrameType != eEth802QVLANFrame)
-				return FALSE;
+				return false;
 
 		uPriority = (ntohs(*(USHORT *)(skb->data + sizeof(struct bcm_eth_header))) & 0xF000) >> 13;
 
@@ -739,17 +739,17 @@
 				bClassificationSucceed = TRUE;
 
 		if (!bClassificationSucceed)
-			return FALSE;
+			return false;
 	}
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS 802.1 D  User Priority Rule Matched\n");
 
-	bClassificationSucceed = FALSE;
+	bClassificationSucceed = false;
 
 	if (pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_VLANID_VALID))
 	{
 		if (pstEthCsPktInfo->eNwpktEthFrameType != eEth802QVLANFrame)
-				return FALSE;
+				return false;
 
 		usVLANID = ntohs(*(USHORT *)(skb->data + sizeof(struct bcm_eth_header))) & 0xFFF;
 
@@ -759,7 +759,7 @@
 			bClassificationSucceed = TRUE;
 
 		if (!bClassificationSucceed)
-			return FALSE;
+			return false;
 	}
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS 802.1 Q VLAN ID Rule Matched\n");
@@ -768,26 +768,26 @@
 }
 
 
-static BOOLEAN EThCSClassifyPkt(struct bcm_mini_adapter *Adapter, struct sk_buff* skb,
+static bool EThCSClassifyPkt(struct bcm_mini_adapter *Adapter, struct sk_buff* skb,
 				struct bcm_eth_packet_info *pstEthCsPktInfo,
 				struct bcm_classifier_rule *pstClassifierRule,
 				B_UINT8 EthCSCupport)
 {
-	BOOLEAN bClassificationSucceed = FALSE;
+	bool bClassificationSucceed = false;
 	bClassificationSucceed = EthCSMatchSrcMACAddress(pstClassifierRule, ((struct bcm_eth_header *)(skb->data))->au8SourceAddress);
 	if (!bClassificationSucceed)
-		return FALSE;
+		return false;
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS SrcMAC Matched\n");
 
 	bClassificationSucceed = EthCSMatchDestMACAddress(pstClassifierRule, ((struct bcm_eth_header *)(skb->data))->au8DestinationAddress);
 	if (!bClassificationSucceed)
-		return FALSE;
+		return false;
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS DestMAC Matched\n");
 
 	//classify on ETHType/802.2SAP TLV
 	bClassificationSucceed = EthCSMatchEThTypeSAP(pstClassifierRule, skb, pstEthCsPktInfo);
 	if (!bClassificationSucceed)
-		return FALSE;
+		return false;
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS EthType/802.2SAP Matched\n");
 
@@ -795,7 +795,7 @@
 
 	bClassificationSucceed = EthCSMatchVLANRules(pstClassifierRule, skb, pstEthCsPktInfo);
 	if (!bClassificationSucceed)
-		return FALSE;
+		return false;
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "ETH CS 802.1 VLAN Rules Matched\n");
 
 	return bClassificationSucceed;
diff --git a/drivers/staging/bcm/Transmit.c b/drivers/staging/bcm/Transmit.c
index f8dc3e2..2ed4836 100644
--- a/drivers/staging/bcm/Transmit.c
+++ b/drivers/staging/bcm/Transmit.c
@@ -84,7 +84,7 @@
 int SetupNextSend(struct bcm_mini_adapter *Adapter,  struct sk_buff *Packet, USHORT Vcid)
 {
 	int	status = 0;
-	BOOLEAN	bHeaderSupressionEnabled = FALSE;
+	bool	bHeaderSupressionEnabled = false;
 	B_UINT16 uiClassifierRuleID;
 	u16	QueueIndex = skb_get_queue_mapping(Packet);
 	struct bcm_leader Leader = {0};
@@ -204,7 +204,7 @@
 		/* Check end point for halt/stall. */
 		if (Adapter->bEndPointHalted == TRUE) {
 			Bcm_clear_halt_of_endpoints(Adapter);
-			Adapter->bEndPointHalted = FALSE;
+			Adapter->bEndPointHalted = false;
 			StartInterruptUrb((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter));
 		}
 
diff --git a/drivers/staging/bcm/Typedefs.h b/drivers/staging/bcm/Typedefs.h
index a985abf..832adcf 100644
--- a/drivers/staging/bcm/Typedefs.h
+++ b/drivers/staging/bcm/Typedefs.h
@@ -6,10 +6,10 @@
 #define  STATUS_SUCCESS	0
 #define  STATUS_FAILURE -1
 
-#define	 FALSE		0
+
 #define	 TRUE		1
 
-typedef char BOOLEAN;
+
 typedef char CHAR;
 typedef int INT;
 typedef short SHORT;
diff --git a/drivers/staging/bcm/led_control.c b/drivers/staging/bcm/led_control.c
index 05a948a..eee4f47 100644
--- a/drivers/staging/bcm/led_control.c
+++ b/drivers/staging/bcm/led_control.c
@@ -13,12 +13,12 @@
 	return u16CheckSum;
 }
 
-BOOLEAN IsReqGpioIsLedInNVM(struct bcm_mini_adapter *Adapter, UINT gpios)
+bool IsReqGpioIsLedInNVM(struct bcm_mini_adapter *Adapter, UINT gpios)
 {
 	INT Status;
 	Status = (Adapter->gpioBitMap & gpios) ^ gpios;
 	if (Status)
-		return FALSE;
+		return false;
 	else
 		return TRUE;
 }
@@ -27,7 +27,7 @@
 		ULONG timeout, INT num_of_time, enum bcm_led_events currdriverstate)
 {
 	int Status = STATUS_SUCCESS;
-	BOOLEAN bInfinite = FALSE;
+	bool bInfinite = false;
 
 	/* Check if num_of_time is -ve. If yes, blink led in infinite loop */
 	if (num_of_time < 0) {
@@ -67,7 +67,7 @@
 				currdriverstate != Adapter->DriverState ||
 					kthread_should_stop(),
 				msecs_to_jiffies(timeout));
-		if (bInfinite == FALSE)
+		if (bInfinite == false)
 			num_of_time--;
 	}
 	return Status;
@@ -108,7 +108,7 @@
 	int Status = STATUS_SUCCESS;
 	INT num_of_time = 0, num_of_time_tx = 0, num_of_time_rx = 0;
 	UINT remDelay = 0;
-	BOOLEAN bBlinkBothLED = TRUE;
+	bool bBlinkBothLED = TRUE;
 	/* UINT GPIO_num = DISABLE_GPIO_NUM; */
 	ulong timeout = 0;
 
@@ -120,7 +120,7 @@
 	num_of_time_tx = ScaleRateofTransfer((ULONG)rate_of_transfer_tx);
 	num_of_time_rx = ScaleRateofTransfer((ULONG)rate_of_transfer_rx);
 
-	while ((Adapter->device_removed == FALSE)) {
+	while ((Adapter->device_removed == false)) {
 		timeout = 50;
 		/*
 		 * Blink Tx and Rx LED when both Tx and Rx is
@@ -478,7 +478,7 @@
 
 
 static int ReadConfigFileStructure(struct bcm_mini_adapter *Adapter,
-					BOOLEAN *bEnableThread)
+					bool *bEnableThread)
 {
 	int Status = STATUS_SUCCESS;
 	/* Array to store GPIO numbers from EEPROM */
@@ -499,10 +499,10 @@
 	/* Read the GPIO numbers from EEPROM */
 	Status = ReadLEDInformationFromEEPROM(Adapter, GPIO_Array);
 	if (Status == STATUS_IMAGE_CHECKSUM_MISMATCH) {
-		*bEnableThread = FALSE;
+		*bEnableThread = false;
 		return STATUS_SUCCESS;
 	} else if (Status) {
-		*bEnableThread = FALSE;
+		*bEnableThread = false;
 		return Status;
 	}
 
@@ -561,7 +561,7 @@
 			uiNum_of_LED_Type++;
 	}
 	if (uiNum_of_LED_Type >= NUM_OF_LEDS)
-		*bEnableThread = FALSE;
+		*bEnableThread = false;
 
 	return Status;
 }
@@ -602,7 +602,7 @@
 		BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
 			DBG_LVL_ALL, "LED Thread: WRM Failed\n");
 
-	Adapter->LEDInfo.bIdle_led_off = FALSE;
+	Adapter->LEDInfo.bIdle_led_off = false;
 }
 
 static INT BcmGetGPIOPinInfo(struct bcm_mini_adapter *Adapter, UCHAR *GPIO_num_tx,
@@ -660,7 +660,7 @@
 	UCHAR dummyIndex = 0;
 
 	/* currdriverstate = Adapter->DriverState; */
-	Adapter->LEDInfo.bIdleMode_tx_from_host = FALSE;
+	Adapter->LEDInfo.bIdleMode_tx_from_host = false;
 
 	/*
 	 * Wait till event is triggered
@@ -698,7 +698,7 @@
 		if (GPIO_num != DISABLE_GPIO_NUM)
 			TURN_OFF_LED(1 << GPIO_num, uiLedIndex);
 
-		if (Adapter->LEDInfo.bLedInitDone == FALSE) {
+		if (Adapter->LEDInfo.bLedInitDone == false) {
 			LedGpioInit(Adapter);
 			Adapter->LEDInfo.bLedInitDone = TRUE;
 		}
@@ -757,7 +757,7 @@
 				UCHAR uiLEDTx = 0;
 				UCHAR uiLEDRx = 0;
 				currdriverstate = NORMAL_OPERATION;
-				Adapter->LEDInfo.bIdle_led_off = FALSE;
+				Adapter->LEDInfo.bIdle_led_off = false;
 
 				BcmGetGPIOPinInfo(Adapter, &GPIO_num_tx,
 					&GPIO_num_rx, &uiLEDTx, &uiLEDRx,
@@ -803,7 +803,7 @@
 
 			}
 			/* Turn off LED And WAKE-UP for Sendinf IDLE mode ACK */
-			Adapter->LEDInfo.bLedInitDone = FALSE;
+			Adapter->LEDInfo.bLedInitDone = false;
 			Adapter->LEDInfo.bIdle_led_off = TRUE;
 			wake_up(&Adapter->LEDInfo.idleModeSyncEvent);
 			GPIO_num = DISABLE_GPIO_NUM;
@@ -830,7 +830,7 @@
 			currdriverstate = LED_THREAD_INACTIVE;
 			Adapter->LEDInfo.led_thread_running =
 					BCM_LED_THREAD_RUNNING_INACTIVELY;
-			Adapter->LEDInfo.bLedInitDone = FALSE;
+			Adapter->LEDInfo.bLedInitDone = false;
 			/* disable ALL LED */
 			for (uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
 				if (Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num
@@ -841,7 +841,7 @@
 		case LED_THREAD_ACTIVE:
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LED_DUMP_INFO,
 				DBG_LVL_ALL, "Activating LED thread again...");
-			if (Adapter->LinkUpStatus == FALSE)
+			if (Adapter->LinkUpStatus == false)
 				Adapter->DriverState = NO_NETWORK_ENTRY;
 			else
 				Adapter->DriverState = NORMAL_OPERATION;
@@ -860,7 +860,7 @@
 int InitLedSettings(struct bcm_mini_adapter *Adapter)
 {
 	int Status = STATUS_SUCCESS;
-	BOOLEAN bEnableThread = TRUE;
+	bool bEnableThread = TRUE;
 	UCHAR uiIndex = 0;
 
 	/*
@@ -899,7 +899,7 @@
 		init_waitqueue_head(&Adapter->LEDInfo.idleModeSyncEvent);
 		Adapter->LEDInfo.led_thread_running =
 					BCM_LED_THREAD_RUNNING_ACTIVELY;
-		Adapter->LEDInfo.bIdle_led_off = FALSE;
+		Adapter->LEDInfo.bIdle_led_off = false;
 		Adapter->LEDInfo.led_cntrl_threadid =
 			kthread_run((int (*)(void *)) LEDControlThread,
 			Adapter, "led_control_thread");
diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c
index 91a5715..9e5f955 100644
--- a/drivers/staging/bcm/nvm.c
+++ b/drivers/staging/bcm/nvm.c
@@ -45,7 +45,7 @@
 	PUINT pBuffer,
 	unsigned int uiOffset,
 	unsigned int uiNumBytes,
-	BOOLEAN bVerify);
+	bool bVerify);
 
 static int GetFlashBaseAddr(struct bcm_mini_adapter *Adapter);
 
@@ -103,7 +103,7 @@
 		}
 		if (!(dwRetries%RETRIES_PER_DELAY))
 			udelay(1000);
-		uiStatus = 0 ;
+		uiStatus = 0;
 	}
 	return uiData;
 } /* ReadEEPROMStatusRegister */
@@ -1034,7 +1034,7 @@
 				PUINT pBuffer,
 				unsigned int uiOffset,
 				unsigned int uiNumBytes,
-				BOOLEAN bVerify)
+				bool bVerify)
 {
 	PCHAR pTempBuff			= NULL;
 	PUCHAR pcBuffer			= (PUCHAR)pBuffer;
@@ -1084,18 +1084,18 @@
 	 * for DSD calibration, allow it without checking of sector permission
 	 */
 
-	if (IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == FALSE)) {
+	if (IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == false)) {
 		index = 0;
 		uiTemp = uiNumSectTobeRead;
 		while (uiTemp) {
-			if (IsOffsetWritable(Adapter, uiOffsetFromSectStart + index * Adapter->uiSectorSize) == FALSE) {
+			if (IsOffsetWritable(Adapter, uiOffsetFromSectStart + index * Adapter->uiSectorSize) == false) {
 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Sector Starting at offset <0X%X> is not writable",
 						(uiOffsetFromSectStart + index * Adapter->uiSectorSize));
 				Status = SECTOR_IS_NOT_WRITABLE;
 				goto BeceemFlashBulkWrite_EXIT;
 			}
 			uiTemp = uiTemp - 1;
-			index = index + 1 ;
+			index = index + 1;
 		}
 	}
 	Adapter->SelectedChip = RESET_CHIP_SELECT;
@@ -1222,7 +1222,7 @@
 				PUINT pBuffer,
 				unsigned int uiOffset,
 				unsigned int uiNumBytes,
-				BOOLEAN bVerify)
+				bool bVerify)
 {
 	PCHAR pTempBuff			= NULL;
 	PUCHAR pcBuffer			= (PUCHAR)pBuffer;
@@ -1265,18 +1265,18 @@
 			uiNumSectTobeRead++;
 	}
 
-	if (IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == FALSE)) {
+	if (IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == false)) {
 		index = 0;
 		uiTemp = uiNumSectTobeRead;
 		while (uiTemp) {
-			if (IsOffsetWritable(Adapter, uiOffsetFromSectStart + index * Adapter->uiSectorSize) == FALSE) {
+			if (IsOffsetWritable(Adapter, uiOffsetFromSectStart + index * Adapter->uiSectorSize) == false) {
 				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Sector Starting at offset <0X%x> is not writable",
 						(uiOffsetFromSectStart + index * Adapter->uiSectorSize));
 				Status = SECTOR_IS_NOT_WRITABLE;
 				goto BeceemFlashBulkWriteStatus_EXIT;
 			}
 			uiTemp = uiTemp - 1;
-			index = index + 1 ;
+			index = index + 1;
 		}
 	}
 
@@ -1525,7 +1525,7 @@
 
 			if (memcmp(&pBuffer[uiIndex], &auiData[0], MAX_RW_SIZE)) {
 				/* re-write */
-				BeceemEEPROMBulkWrite(Adapter, (PUCHAR)(pBuffer + uiIndex), uiOffset, MAX_RW_SIZE, FALSE);
+				BeceemEEPROMBulkWrite(Adapter, (PUCHAR)(pBuffer + uiIndex), uiOffset, MAX_RW_SIZE, false);
 				mdelay(3);
 				BeceemEEPROMBulkRead(Adapter, &auiData[0], uiOffset, MAX_RW_SIZE);
 
@@ -1539,7 +1539,7 @@
 			BeceemEEPROMBulkRead(Adapter, &uiData, uiOffset, 4);
 			if (uiData != pBuffer[uiIndex]) {
 				/* re-write */
-				BeceemEEPROMBulkWrite(Adapter, (PUCHAR)(pBuffer + uiIndex), uiOffset, 4, FALSE);
+				BeceemEEPROMBulkWrite(Adapter, (PUCHAR)(pBuffer + uiIndex), uiOffset, 4, false);
 				mdelay(3);
 				BeceemEEPROMBulkRead(Adapter, &uiData, uiOffset, 4);
 				if (uiData != pBuffer[uiIndex])
@@ -1724,7 +1724,7 @@
 			PUCHAR pBuffer,
 			unsigned int uiOffset,
 			unsigned int uiNumBytes,
-			BOOLEAN bVerify)
+			bool bVerify)
 {
 	unsigned int uiBytesToCopy	= uiNumBytes;
 	/* unsigned int uiRdbk		= 0; */
@@ -1819,7 +1819,7 @@
 	#endif
 
 	if (Adapter->eNVMType == NVM_FLASH) {
-		if (Adapter->bFlashRawRead == FALSE) {
+		if (Adapter->bFlashRawRead == false) {
 			if (IsSectionExistInVendorInfo(Adapter, Adapter->eActiveDSD))
 				return vendorextnReadSection(Adapter, (PUCHAR)pBuffer, Adapter->eActiveDSD, uiOffset, uiNumBytes);
 
@@ -1870,7 +1870,7 @@
 		PUINT pBuffer,
 		unsigned int uiOffset,
 		unsigned int uiNumBytes,
-		BOOLEAN bVerify)
+		bool bVerify)
 {
 	int Status = 0;
 	unsigned int uiTemp = 0;
@@ -2425,7 +2425,7 @@
 	B_UINT32 i = 0;
 	unsigned int uiSizeSection = 0;
 
-	Adapter->uiVendorExtnFlag = FALSE;
+	Adapter->uiVendorExtnFlag = false;
 
 	for (i = 0; i < TOTAL_SECTIONS; i++)
 		Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart = UNINIT_PTR_IN_CS;
@@ -2685,12 +2685,12 @@
 	switch (eFlashSectionVal) {
 	case ISO_IMAGE1:
 		if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start != UNINIT_PTR_IN_CS) &&
-			(IsNonCDLessDevice(Adapter) == FALSE))
+			(IsNonCDLessDevice(Adapter) == false))
 			SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start);
 		break;
 	case ISO_IMAGE2:
 		if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start != UNINIT_PTR_IN_CS) &&
-			(IsNonCDLessDevice(Adapter) == FALSE))
+			(IsNonCDLessDevice(Adapter) == false))
 			SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start);
 		break;
 	case DSD0:
@@ -2770,12 +2770,12 @@
 	switch (eFlash2xSectionVal) {
 	case ISO_IMAGE1:
 		if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End != UNINIT_PTR_IN_CS) &&
-			(IsNonCDLessDevice(Adapter) == FALSE))
+			(IsNonCDLessDevice(Adapter) == false))
 			SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End);
 		break;
 	case ISO_IMAGE2:
 		if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End != UNINIT_PTR_IN_CS) &&
-			(IsNonCDLessDevice(Adapter) == FALSE))
+			(IsNonCDLessDevice(Adapter) == false))
 			SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End);
 		break;
 	case DSD0:
@@ -2831,7 +2831,7 @@
 		SectEndOffset = INVALID_OFFSET;
 	}
 
-	return SectEndOffset ;
+	return SectEndOffset;
 }
 
 /*
@@ -3037,7 +3037,7 @@
  *
  * Return Value:-
  * Success:-TRUE ,  offset is writable
- * Failure:-FALSE, offset is RO
+ * Failure:-false, offset is RO
  *
  */
 
@@ -3062,7 +3062,7 @@
 	if (permissionBits == SECTOR_READWRITE_PERMISSION)
 		return TRUE;
 	else
-		return FALSE;
+		return false;
 }
 
 static int BcmDumpFlash2xSectionBitMap(struct bcm_flash2x_bitmap *psFlash2xBitMap)
@@ -3105,13 +3105,13 @@
 	struct bcm_flash2x_cs_info *psFlash2xCSInfo = Adapter->psFlash2xCSInfo;
 	enum bcm_flash2x_section_val uiHighestPriDSD = 0;
 	enum bcm_flash2x_section_val uiHighestPriISO = 0;
-	BOOLEAN SetActiveDSDDone = FALSE;
-	BOOLEAN SetActiveISODone = FALSE;
+	bool SetActiveDSDDone = false;
+	bool SetActiveISODone = false;
 
 	/* For 1.x map all the section except DSD0 will be shown as not present
 	 * This part will be used by calibration tool to detect the number of DSD present in Flash.
 	 */
-	if (IsFlash2x(Adapter) == FALSE) {
+	if (IsFlash2x(Adapter) == false) {
 		psFlash2xBitMap->ISO_IMAGE2 = 0;
 		psFlash2xBitMap->ISO_IMAGE1 = 0;
 		psFlash2xBitMap->DSD0 = FLASH2X_SECTION_VALID | FLASH2X_SECTION_ACT | FLASH2X_SECTION_PRESENT; /* 0xF; 0000(Reseved)1(Active)0(RW)1(valid)1(present) */
@@ -3143,10 +3143,10 @@
 			psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_VALID;
 
 		/* Calculation for extrating the Access permission */
-		if (IsSectionWritable(Adapter, ISO_IMAGE2) == FALSE)
+		if (IsSectionWritable(Adapter, ISO_IMAGE2) == false)
 			psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_RO;
 
-		if (SetActiveISODone == FALSE && uiHighestPriISO == ISO_IMAGE2) {
+		if (SetActiveISODone == false && uiHighestPriISO == ISO_IMAGE2) {
 			psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_ACT;
 			SetActiveISODone = TRUE;
 		}
@@ -3163,10 +3163,10 @@
 			psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_VALID;
 
 		/* Calculation for extrating the Access permission */
-		if (IsSectionWritable(Adapter, ISO_IMAGE1) == FALSE)
+		if (IsSectionWritable(Adapter, ISO_IMAGE1) == false)
 			psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_RO;
 
-		if (SetActiveISODone == FALSE && uiHighestPriISO == ISO_IMAGE1) {
+		if (SetActiveISODone == false && uiHighestPriISO == ISO_IMAGE1) {
 			psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_ACT;
 			SetActiveISODone = TRUE;
 		}
@@ -3183,11 +3183,11 @@
 			psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_VALID;
 
 		/* Calculation for extrating the Access permission */
-		if (IsSectionWritable(Adapter, DSD2) == FALSE) {
+		if (IsSectionWritable(Adapter, DSD2) == false) {
 			psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_RO;
 		} else {
 			/* Means section is writable */
-			if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD2)) {
+			if ((SetActiveDSDDone == false) && (uiHighestPriDSD == DSD2)) {
 				psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_ACT;
 				SetActiveDSDDone = TRUE;
 			}
@@ -3205,11 +3205,11 @@
 			psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_VALID;
 
 		/* Calculation for extrating the Access permission */
-		if (IsSectionWritable(Adapter, DSD1) == FALSE) {
+		if (IsSectionWritable(Adapter, DSD1) == false) {
 			psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_RO;
 		} else {
 			/* Means section is writable */
-			if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD1)) {
+			if ((SetActiveDSDDone == false) && (uiHighestPriDSD == DSD1)) {
 				psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_ACT;
 				SetActiveDSDDone = TRUE;
 			}
@@ -3227,11 +3227,11 @@
 			psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_VALID;
 
 		/* Setting Access permission */
-		if (IsSectionWritable(Adapter, DSD0) == FALSE) {
+		if (IsSectionWritable(Adapter, DSD0) == false) {
 			psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_RO;
 		} else {
 			/* Means section is writable */
-			if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD0)) {
+			if ((SetActiveDSDDone == false) && (uiHighestPriDSD == DSD0)) {
 				psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_ACT;
 				SetActiveDSDDone = TRUE;
 			}
@@ -3249,7 +3249,7 @@
 		psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_VALID;
 
 		/* Calculation for extrating the Access permission */
-		if (IsSectionWritable(Adapter, VSA0) == FALSE)
+		if (IsSectionWritable(Adapter, VSA0) == false)
 			psFlash2xBitMap->VSA0 |=  FLASH2X_SECTION_RO;
 
 		/* By Default section is Active */
@@ -3267,7 +3267,7 @@
 		psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_VALID;
 
 		/* Checking For Access permission */
-		if (IsSectionWritable(Adapter, VSA1) == FALSE)
+		if (IsSectionWritable(Adapter, VSA1) == false)
 			psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_RO;
 
 		/* By Default section is Active */
@@ -3285,7 +3285,7 @@
 		psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_VALID;
 
 		/* Checking For Access permission */
-		if (IsSectionWritable(Adapter, VSA2) == FALSE)
+		if (IsSectionWritable(Adapter, VSA2) == false)
 			psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_RO;
 
 		/* By Default section is Active */
@@ -3303,7 +3303,7 @@
 		psFlash2xBitMap->SCSI |= FLASH2X_SECTION_VALID;
 
 		/* Checking For Access permission */
-		if (IsSectionWritable(Adapter, SCSI) == FALSE)
+		if (IsSectionWritable(Adapter, SCSI) == false)
 			psFlash2xBitMap->SCSI |= FLASH2X_SECTION_RO;
 
 		/* By Default section is Active */
@@ -3321,7 +3321,7 @@
 		psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_VALID;
 
 		/* Checking For Access permission */
-		if (IsSectionWritable(Adapter, CONTROL_SECTION) == FALSE)
+		if (IsSectionWritable(Adapter, CONTROL_SECTION) == false)
 			psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_RO;
 
 		/* By Default section is Active */
@@ -3358,7 +3358,7 @@
 	/* struct bcm_dsd_header sDSD = {0};
 	 * struct bcm_iso_header sISO = {0};
 	 */
-	int HighestPriDSD = 0 ;
+	int HighestPriDSD = 0;
 	int HighestPriISO = 0;
 
 	Status = IsSectionWritable(Adapter, eFlash2xSectVal);
@@ -3517,7 +3517,7 @@
 		break;
 	}
 
-	Adapter->bHeaderChangeAllowed = FALSE;
+	Adapter->bHeaderChangeAllowed = false;
 	return Status;
 }
 
@@ -3536,7 +3536,7 @@
 	enum bcm_flash2x_section_val eISOReadPart = 0, eISOWritePart = 0;
 	unsigned int uiReadOffsetWithinPart = 0, uiWriteOffsetWithinPart = 0;
 	unsigned int uiTotalDataToCopy = 0;
-	BOOLEAN IsThisHeaderSector = FALSE;
+	bool IsThisHeaderSector = false;
 	unsigned int sigOffset = 0;
 	unsigned int ISOLength = 0;
 	unsigned int Status = STATUS_SUCCESS;
@@ -3669,14 +3669,14 @@
 				break;
 			}
 
-			Adapter->bHeaderChangeAllowed = FALSE;
+			Adapter->bHeaderChangeAllowed = false;
 			if (IsThisHeaderSector == TRUE) {
 				WriteToFlashWithoutSectorErase(Adapter,
 							SigBuff,
 							eISOWritePart,
 							sigOffset,
 							MAX_RW_SIZE);
-				IsThisHeaderSector = FALSE;
+				IsThisHeaderSector = false;
 			}
 			/* subtracting the written Data */
 			uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize;
@@ -3782,7 +3782,7 @@
 				break;
 			}
 
-			Adapter->bHeaderChangeAllowed = FALSE;
+			Adapter->bHeaderChangeAllowed = false;
 			if (IsThisHeaderSector == TRUE) {
 				WriteToFlashWithoutSectorErase(Adapter,
 							SigBuff,
@@ -3790,7 +3790,7 @@
 							sigOffset,
 							MAX_RW_SIZE);
 
-				IsThisHeaderSector = FALSE;
+				IsThisHeaderSector = false;
 			}
 
 			/* subtracting the written Data */
@@ -3848,13 +3848,13 @@
 	unsigned int uiOffset = 0;
 
 	/* struct bcm_dsd_header dsdHeader = {0}; */
-	if (Adapter->bSigCorrupted == FALSE) {
+	if (Adapter->bSigCorrupted == false) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is not corrupted by driver, hence not restoring\n");
 		return STATUS_SUCCESS;
 	}
 
-	if (Adapter->bAllDSDWriteAllow == FALSE) {
-		if (IsSectionWritable(Adapter, eFlashSectionVal) == FALSE) {
+	if (Adapter->bAllDSDWriteAllow == false) {
+		if (IsSectionWritable(Adapter, eFlashSectionVal) == false) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Write signature");
 			return SECTOR_IS_NOT_WRITABLE;
 		}
@@ -3886,9 +3886,9 @@
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Restoring the signature");
 
 	Adapter->bHeaderChangeAllowed = TRUE;
-	Adapter->bSigCorrupted = FALSE;
+	Adapter->bSigCorrupted = false;
 	BcmFlash2xBulkWrite(Adapter, &uiSignature, eFlashSectionVal, uiOffset, SIGNATURE_SIZE, TRUE);
-	Adapter->bHeaderChangeAllowed = FALSE;
+	Adapter->bHeaderChangeAllowed = false;
 
 	return STATUS_SUCCESS;
 }
@@ -3899,7 +3899,7 @@
  * @Adapater :- Bcm Driver Private Data Structure
  * @psFlash2xReadWrite :-Flash2x Read/write structure pointer
  *
- * Return values:-Return TRUE is request is valid else FALSE.
+ * Return values:-Return TRUE is request is valid else false.
  */
 
 int validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_readwrite *psFlash2xReadWrite)
@@ -3912,7 +3912,7 @@
 
 	if (IsSectionExistInFlash(Adapter, psFlash2xReadWrite->Section) != TRUE) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section<%x> does not exixt in Flash", psFlash2xReadWrite->Section);
-		return FALSE;
+		return false;
 	}
 	uiSectStartOffset = BcmGetSectionValStartOffset(Adapter, psFlash2xReadWrite->Section);
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Start offset :%x ,section :%d\n", uiSectStartOffset, psFlash2xReadWrite->Section);
@@ -3949,7 +3949,7 @@
 		return TRUE;
 	else {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Invalid Request....");
-		return FALSE;
+		return false;
 	}
 }
 
@@ -3966,7 +3966,7 @@
 	if (Adapter->uiFlashLayoutMajorVersion >= FLASH_2X_MAJOR_NUMBER)
 		return TRUE;
 	else
-		return FALSE;
+		return false;
 }
 
 /*
@@ -3986,7 +3986,7 @@
 		 * For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr
 		 * In case of Raw Read... use the default value
 		 */
-		if (Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == FALSE) &&
+		if (Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == false) &&
 			!((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1)))
 			uiBaseAddr = Adapter->uiFlashBaseAdd;
 		else
@@ -3996,7 +3996,7 @@
 		 * For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr
 		 * In case of Raw Read... use the default value
 		 */
-		if (Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == FALSE) &&
+		if (Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == false) &&
 			!((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1)))
 			uiBaseAddr = Adapter->uiFlashBaseAdd | FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT;
 		else
@@ -4094,7 +4094,7 @@
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed at offset :%d for NOB :%d", SrcSection, BytesToBeCopied);
 			break;
 		}
-		Status = BcmFlash2xBulkWrite(Adapter, (PUINT)pBuff, DstSection, offset, BytesToBeCopied, FALSE);
+		Status = BcmFlash2xBulkWrite(Adapter, (PUINT)pBuff, DstSection, offset, BytesToBeCopied, false);
 		if (Status) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write failed at offset :%d for NOB :%d", DstSection, BytesToBeCopied);
 			break;
@@ -4110,7 +4110,7 @@
 	} while (numOfBytes > 0);
 
 	kfree(pBuff);
-	Adapter->bHeaderChangeAllowed = FALSE;
+	Adapter->bHeaderChangeAllowed = false;
 
 	return Status;
 }
@@ -4129,7 +4129,7 @@
 int SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, unsigned int uiOffset)
 {
 	unsigned int offsetToProtect = 0, HeaderSizeToProtect = 0;
-	BOOLEAN bHasHeader = FALSE;
+	bool bHasHeader = false;
 	PUCHAR pTempBuff = NULL;
 	unsigned int uiSectAlignAddr = 0;
 	unsigned int sig = 0;
@@ -4153,7 +4153,7 @@
 		bHasHeader = TRUE;
 	}
 	/* If Header is present overwrite passed buffer with this */
-	if (bHasHeader && (Adapter->bHeaderChangeAllowed == FALSE)) {
+	if (bHasHeader && (Adapter->bHeaderChangeAllowed == false)) {
 		pTempBuff = kzalloc(HeaderSizeToProtect, GFP_KERNEL);
 		if (!pTempBuff) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed");
@@ -4172,13 +4172,13 @@
 		sig = ntohl(sig);
 		if ((sig & 0xFF000000) != CORRUPTED_PATTERN) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Desired pattern is not at sig offset. Hence won't restore");
-			Adapter->bSigCorrupted = FALSE;
+			Adapter->bSigCorrupted = false;
 			return STATUS_SUCCESS;
 		}
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " Corrupted sig is :%X", sig);
 		*((PUINT)(pBuff + offsetToProtect + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImageMagicNumber))) = htonl(DSD_IMAGE_MAGIC_NUMBER);
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Restoring the signature in Header Write only");
-		Adapter->bSigCorrupted = FALSE;
+		Adapter->bSigCorrupted = false;
 	}
 
 	return STATUS_SUCCESS;
@@ -4450,7 +4450,7 @@
 		BcmDoChipSelect(Adapter, uiOffset);
 		uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter);
 
-		for (i = 0 ; i < uiNumBytes; i += Adapter->ulFlashWriteSize) {
+		for (i = 0; i < uiNumBytes; i += Adapter->ulFlashWriteSize) {
 			if (Adapter->ulFlashWriteSize == BYTE_WRITE_SUPPORT)
 				Status = flashByteWrite(Adapter, uiPartOffset, pcBuff);
 			else
@@ -4469,19 +4469,19 @@
 	return Status;
 }
 
-BOOLEAN IsSectionExistInFlash(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val section)
+bool IsSectionExistInFlash(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val section)
 {
-	BOOLEAN SectionPresent = FALSE;
+	bool SectionPresent = false;
 
 	switch (section) {
 	case ISO_IMAGE1:
 		if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start != UNINIT_PTR_IN_CS) &&
-			(IsNonCDLessDevice(Adapter) == FALSE))
+			(IsNonCDLessDevice(Adapter) == false))
 			SectionPresent = TRUE;
 		break;
 	case ISO_IMAGE2:
 		if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start != UNINIT_PTR_IN_CS) &&
-			(IsNonCDLessDevice(Adapter) == FALSE))
+			(IsNonCDLessDevice(Adapter) == false))
 			SectionPresent = TRUE;
 		break;
 	case DSD0:
@@ -4518,7 +4518,7 @@
 		break;
 	default:
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Does not exist in Flash 2.x");
-		SectionPresent =  FALSE;
+		SectionPresent =  false;
 	}
 
 	return SectionPresent;
@@ -4527,17 +4527,17 @@
 int IsSectionWritable(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val Section)
 {
 	int offset = STATUS_FAILURE;
-	int Status = FALSE;
+	int Status = false;
 
-	if (IsSectionExistInFlash(Adapter, Section) == FALSE) {
+	if (IsSectionExistInFlash(Adapter, Section) == false) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section <%d> does not exixt", Section);
-		return FALSE;
+		return false;
 	}
 
 	offset = BcmGetSectionValStartOffset(Adapter, Section);
 	if (offset == INVALID_OFFSET) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section<%d> does not exixt", Section);
-		return FALSE;
+		return false;
 	}
 
 	if (IsSectionExistInVendorInfo(Adapter, Section))
@@ -4555,8 +4555,8 @@
 	unsigned int BlockStatus = 0;
 	unsigned int uiSectAlignAddr = 0;
 
-	Adapter->bSigCorrupted = FALSE;
-	if (Adapter->bAllDSDWriteAllow == FALSE) {
+	Adapter->bSigCorrupted = false;
+	if (Adapter->bAllDSDWriteAllow == false) {
 		if (IsSectionWritable(Adapter, eFlash2xSectionVal) != TRUE) {
 			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Corrupt signature");
 			return SECTOR_IS_NOT_WRITABLE;
@@ -4615,7 +4615,7 @@
 	unsigned int sig = 0;
 	unsigned int uiOffset = 0;
 
-	Adapter->bSigCorrupted = FALSE;
+	Adapter->bSigCorrupted = false;
 
 	if (IsSectionWritable(Adapter, eFlash2xSectionVal) != TRUE) {
 		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Corrupt signature");
@@ -4656,10 +4656,10 @@
 	return STATUS_SUCCESS;
 }
 
-BOOLEAN IsNonCDLessDevice(struct bcm_mini_adapter *Adapter)
+bool IsNonCDLessDevice(struct bcm_mini_adapter *Adapter)
 {
 	if (Adapter->psFlash2xCSInfo->IsCDLessDeviceBootSig == NON_CDLESS_DEVICE_BOOT_SIG)
 		return TRUE;
 	else
-		return FALSE;
+		return false;
 }
diff --git a/drivers/staging/bcm/vendorspecificextn.c b/drivers/staging/bcm/vendorspecificextn.c
index d38a06f..2c57a16 100644
--- a/drivers/staging/bcm/vendorspecificextn.c
+++ b/drivers/staging/bcm/vendorspecificextn.c
@@ -113,7 +113,7 @@
  *		STATUS_SUCCESS/STATUS_FAILURE
  */
 INT vendorextnWriteSection(PVOID  pContext, PUCHAR pBuffer, enum bcm_flash2x_section_val SectionVal,
-			UINT offset, UINT numOfBytes, BOOLEAN bVerify)
+			UINT offset, UINT numOfBytes, bool bVerify)
 {
 	return STATUS_FAILURE;
 }
diff --git a/drivers/staging/bcm/vendorspecificextn.h b/drivers/staging/bcm/vendorspecificextn.h
index 52890d2..ff57f05 100644
--- a/drivers/staging/bcm/vendorspecificextn.h
+++ b/drivers/staging/bcm/vendorspecificextn.h
@@ -11,7 +11,7 @@
 INT vendorextnReadSection(PVOID  pContext, PUCHAR pBuffer, enum bcm_flash2x_section_val SectionVal,
 			UINT offset, UINT numOfBytes);
 INT vendorextnWriteSection(PVOID  pContext, PUCHAR pBuffer, enum bcm_flash2x_section_val SectionVal,
-			UINT offset, UINT numOfBytes, BOOLEAN bVerify);
+			UINT offset, UINT numOfBytes, bool bVerify);
 INT vendorextnWriteSectionWithoutErase(PVOID  pContext, PUCHAR pBuffer, enum bcm_flash2x_section_val SectionVal,
 			UINT offset, UINT numOfBytes);
 
diff --git a/drivers/staging/btmtk_usb/btmtk_usb.c b/drivers/staging/btmtk_usb/btmtk_usb.c
index 0e783e8..7a9bf3b 100644
--- a/drivers/staging/btmtk_usb/btmtk_usb.c
+++ b/drivers/staging/btmtk_usb/btmtk_usb.c
@@ -16,7 +16,8 @@
  *  You 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
- *  or on the worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *  or on the worldwide web at
+ *  http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
  *
  */
 
@@ -72,8 +73,9 @@
 
 	BT_DBG("%s\n", __func__);
 
-	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01, DEVICE_VENDOR_REQUEST_OUT,
-						  0x01, 0x00, NULL, 0x00, CONTROL_TIMEOUT_JIFFIES);
+	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01,
+			DEVICE_VENDOR_REQUEST_OUT, 0x01, 0x00,
+			NULL, 0x00, CONTROL_TIMEOUT_JIFFIES);
 
 	if (ret < 0) {
 		BT_ERR("%s error(%d)\n", __func__, ret);
@@ -91,20 +93,22 @@
 	u8 request = data->r_request;
 	struct usb_device *udev = data->udev;
 	int ret;
+	__le32 val_le;
 
-	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), request, DEVICE_VENDOR_REQUEST_IN,
-						  0x0, reg, data->io_buf, 4,
-						  CONTROL_TIMEOUT_JIFFIES);
+	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), request,
+			DEVICE_VENDOR_REQUEST_IN, 0x0, reg, data->io_buf,
+			4, CONTROL_TIMEOUT_JIFFIES);
 
 	if (ret < 0) {
 		*val = 0xffffffff;
-		BT_ERR("%s error(%d), reg=%x, value=%x\n", __func__, ret, reg, *val);
+		BT_ERR("%s error(%d), reg=%x, value=%x\n",
+				__func__, ret, reg, *val);
 		return ret;
 	}
 
-	memmove(val, data->io_buf, 4);
+	memmove(&val_le, data->io_buf, 4);
 
-	*val = le32_to_cpu(*val);
+	*val = le32_to_cpu(val_le);
 
 	if (ret > 0)
 		ret = 0;
@@ -122,12 +126,13 @@
 	index = (u16)reg;
 	value = val & 0x0000ffff;
 
-	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), request, DEVICE_VENDOR_REQUEST_OUT,
-						  value, index, NULL, 0,
-						  CONTROL_TIMEOUT_JIFFIES);
+	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), request,
+			DEVICE_VENDOR_REQUEST_OUT, value, index,
+			NULL, 0, CONTROL_TIMEOUT_JIFFIES);
 
 	if (ret < 0) {
-		BT_ERR("%s error(%d), reg=%x, value=%x\n", __func__, ret, reg, val);
+		BT_ERR("%s error(%d), reg=%x, value=%x\n",
+				__func__, ret, reg, val);
 		return ret;
 	}
 
@@ -139,7 +144,8 @@
 				value, index, NULL, 0, CONTROL_TIMEOUT_JIFFIES);
 
 	if (ret < 0) {
-		BT_ERR("%s error(%d), reg=%x, value=%x\n", __func__, ret, reg, val);
+		BT_ERR("%s error(%d), reg=%x, value=%x\n",
+				__func__, ret, reg, val);
 		return ret;
 	}
 
@@ -186,13 +192,15 @@
 		ret = request_firmware(&firmware, MT7650_FIRMWARE, &udev->dev);
 		if (ret < 0) {
 			if (ret == -ENOENT) {
-				BT_ERR("Firmware file \"%s\" not found \n", MT7650_FIRMWARE);
+				BT_ERR("Firmware file \"%s\" not found\n",
+						MT7650_FIRMWARE);
 			} else {
-				BT_ERR("Firmware file \"%s\" request failed (err=%d) \n",
+				BT_ERR("Firmware file \"%s\" request failed (err=%d)\n",
 					MT7650_FIRMWARE, ret);
 			}
 		} else {
-			BT_DBG("Firmware file \"%s\" Found \n", MT7650_FIRMWARE);
+			BT_DBG("Firmware file \"%s\" Found\n",
+					MT7650_FIRMWARE);
 			/* load firmware here */
 			data->firmware = firmware;
 			btmtk_usb_load_fw(data);
@@ -205,7 +213,8 @@
 		ret = request_firmware(&firmware, MT7662_FIRMWARE, &udev->dev);
 		if (ret < 0) {
 			if (ret == -ENOENT) {
-				BT_ERR("Firmware file \"%s\" not found\n", MT7662_FIRMWARE);
+				BT_ERR("Firmware file \"%s\" not found\n",
+						MT7662_FIRMWARE);
 			} else {
 				BT_ERR("Firmware file \"%s\" request failed (err=%d)\n",
 					MT7662_FIRMWARE, ret);
@@ -241,9 +250,8 @@
 	if (len)
 		sum += *((u8 *)pData);
 
-	while (sum >> 16) {
+	while (sum >> 16)
 		sum = (sum & 0xFFFF) + (sum >> 16);
-	}
 
 	return ~sum;
 }
@@ -258,13 +266,12 @@
 	memmove(data->io_buf, &data->rom_patch_offset, 4);
 	memmove(&data->io_buf[4], &checksum_len, 4);
 
-	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x1, DEVICE_VENDOR_REQUEST_IN,
-						  0x20, 0x00, data->io_buf, 8,
-						  CONTROL_TIMEOUT_JIFFIES);
+	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x1,
+			DEVICE_VENDOR_REQUEST_IN, 0x20, 0x00, data->io_buf,
+			8, CONTROL_TIMEOUT_JIFFIES);
 
-	if (ret < 0) {
+	if (ret < 0)
 		BT_ERR("%s error(%d)\n", __func__, ret);
-	}
 
 	return ret;
 }
@@ -274,6 +281,7 @@
 	int ret = 0;
 	struct usb_device *udev = data->udev;
 	u16 crc, count = 0;
+	__le16 crc_le;
 
 	BT_DBG("%s\n", __func__);
 
@@ -288,9 +296,9 @@
 			BT_ERR("%s error(%d)\n", __func__, ret);
 		}
 
-		memmove(&crc, data->io_buf, 2);
+		memmove(&crc_le, data->io_buf, 2);
 
-		crc = le16_to_cpu(crc);
+		crc = le16_to_cpu(crc_le);
 
 		if (crc != 0xFFFF)
 			break;
@@ -318,8 +326,8 @@
 	BT_DBG("%s\n", __func__);
 
 	ret = usb_control_msg(data->udev, usb_sndctrlpipe(data->udev, 0), 0x01,
-				DEVICE_CLASS_REQUEST_OUT, 0x12, 0x00, data->io_buf,
-				8, CONTROL_TIMEOUT_JIFFIES);
+				DEVICE_CLASS_REQUEST_OUT, 0x12, 0x00,
+				data->io_buf, 8, CONTROL_TIMEOUT_JIFFIES);
 
 	if (ret)
 		BT_ERR("%s:(%d)\n", __func__, ret);
@@ -350,7 +358,8 @@
 	unsigned char phase;
 	void *buf;
 	char *pos;
-	unsigned int pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress);
+	unsigned int pipe;
+	pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress);
 
 	if (!data->firmware) {
 		BT_ERR("%s:please assign a rom patch\n", __func__);
@@ -391,7 +400,8 @@
 		goto error0;
 	}
 
-	buf = usb_alloc_coherent(data->udev, UPLOAD_PATCH_UNIT, GFP_ATOMIC, &data_dma);
+	buf = usb_alloc_coherent(data->udev, UPLOAD_PATCH_UNIT,
+			GFP_ATOMIC, &data_dma);
 
 	if (!buf) {
 		ret = -ENOMEM;
@@ -409,78 +419,82 @@
 	/* loading rom patch */
 	while (1) {
 		s32 sent_len_max = UPLOAD_PATCH_UNIT - PATCH_HEADER_SIZE;
-		sent_len = (patch_len - cur_len) >= sent_len_max ? sent_len_max : (patch_len - cur_len);
+		sent_len = min_t(s32, (patch_len - cur_len), sent_len_max);
 
 		BT_DBG("patch_len = %d\n", patch_len);
 		BT_DBG("cur_len = %d\n", cur_len);
 		BT_DBG("sent_len = %d\n", sent_len);
 
-		if (sent_len > 0) {
-			if (first_block == 1) {
-				if (sent_len < sent_len_max)
-					phase = PATCH_PHASE3;
-				else
-					phase = PATCH_PHASE1;
-				first_block = 0;
-			} else if (sent_len == sent_len_max) {
-				phase = PATCH_PHASE2;
-			} else {
-				phase = PATCH_PHASE3;
-			}
-
-			/* prepare HCI header */
-			pos[0] = 0x6F;
-			pos[1] = 0xFC;
-			pos[2] = (sent_len + 5) & 0xFF;
-			pos[3] = ((sent_len + 5) >> 8) & 0xFF;
-
-			/* prepare WMT header */
-			pos[4] = 0x01;
-			pos[5] = 0x01;
-			pos[6] = (sent_len + 1) & 0xFF;
-			pos[7] = ((sent_len + 1) >> 8) & 0xFF;
-
-			pos[8] = phase;
-
-			memcpy(&pos[9], data->firmware->data + PATCH_INFO_SIZE + cur_len, sent_len);
-
-			BT_DBG("sent_len + PATCH_HEADER_SIZE = %d, phase = %d\n",
-					sent_len + PATCH_HEADER_SIZE, phase);
-
-			usb_fill_bulk_urb(urb,
-					data->udev,
-					pipe,
-					buf,
-					sent_len + PATCH_HEADER_SIZE,
-					load_rom_patch_complete,
-					&sent_to_mcu_done);
-
-			urb->transfer_dma = data_dma;
-			urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-			ret = usb_submit_urb(urb, GFP_ATOMIC);
-
-			if (ret)
-				goto error2;
-
-			if (!wait_for_completion_timeout(&sent_to_mcu_done, msecs_to_jiffies(1000))) {
-				usb_kill_urb(urb);
-				BT_ERR("upload rom_patch timeout\n");
-				goto error2;
-			}
-
-			BT_DBG(".");
-
-			mdelay(200);
-
-			cur_len += sent_len;
-
-		} else {
+		if (sent_len <= 0)
 			break;
+
+		if (first_block == 1) {
+			if (sent_len < sent_len_max)
+				phase = PATCH_PHASE3;
+			else
+				phase = PATCH_PHASE1;
+			first_block = 0;
+		} else if (sent_len == sent_len_max) {
+			phase = PATCH_PHASE2;
+		} else {
+			phase = PATCH_PHASE3;
 		}
+
+		/* prepare HCI header */
+		pos[0] = 0x6F;
+		pos[1] = 0xFC;
+		pos[2] = (sent_len + 5) & 0xFF;
+		pos[3] = ((sent_len + 5) >> 8) & 0xFF;
+
+		/* prepare WMT header */
+		pos[4] = 0x01;
+		pos[5] = 0x01;
+		pos[6] = (sent_len + 1) & 0xFF;
+		pos[7] = ((sent_len + 1) >> 8) & 0xFF;
+
+		pos[8] = phase;
+
+		memcpy(&pos[9],
+			data->firmware->data + PATCH_INFO_SIZE + cur_len,
+			sent_len);
+
+		BT_DBG("sent_len + PATCH_HEADER_SIZE = %d, phase = %d\n",
+				sent_len + PATCH_HEADER_SIZE, phase);
+
+		usb_fill_bulk_urb(urb,
+				data->udev,
+				pipe,
+				buf,
+				sent_len + PATCH_HEADER_SIZE,
+				load_rom_patch_complete,
+				&sent_to_mcu_done);
+
+		urb->transfer_dma = data_dma;
+		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+		ret = usb_submit_urb(urb, GFP_ATOMIC);
+
+		if (ret)
+			goto error2;
+
+		if (!wait_for_completion_timeout(&sent_to_mcu_done,
+					msecs_to_jiffies(1000))) {
+			usb_kill_urb(urb);
+			BT_ERR("upload rom_patch timeout\n");
+			goto error2;
+		}
+
+		BT_DBG(".");
+
+		mdelay(200);
+
+		cur_len += sent_len;
+
 	}
 
-	total_checksum = checksume16((u8 *)data->firmware->data + PATCH_INFO_SIZE, patch_len);
+	total_checksum = checksume16(
+			(u8 *)data->firmware->data + PATCH_INFO_SIZE,
+			patch_len);
 
 	BT_DBG("Send checksum req..\n");
 
@@ -520,8 +534,8 @@
 	memmove(buf, data->firmware->data + 32, 64);
 
 	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01,
-						  DEVICE_VENDOR_REQUEST_OUT, 0x12, 0x0, buf, 64,
-						  CONTROL_TIMEOUT_JIFFIES);
+			DEVICE_VENDOR_REQUEST_OUT, 0x12, 0x0, buf, 64,
+			CONTROL_TIMEOUT_JIFFIES);
 
 	if (ret < 0) {
 		BT_ERR("%s error(%d) step4\n", __func__, ret);
@@ -552,6 +566,7 @@
 	void *buf;
 	u32 cur_len = 0;
 	u32 packet_header = 0;
+	__le32 packet_header_le;
 	u32 value;
 	u32 ilm_len = 0, dlm_len = 0;
 	u16 fw_ver, build_ver;
@@ -559,7 +574,8 @@
 	dma_addr_t data_dma;
 	int ret = 0, sent_len;
 	struct completion sent_to_mcu_done;
-	unsigned int pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress);
+	unsigned int pipe;
+	pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress);
 
 	if (!data->firmware) {
 		BT_ERR("%s:please assign a fw\n", __func__);
@@ -598,9 +614,11 @@
 			| (*(data->firmware->data + 5) << 8)
 			| (*(data->firmware->data + 4));
 
-	fw_ver = (*(data->firmware->data + 11) << 8) | (*(data->firmware->data + 10));
+	fw_ver = (*(data->firmware->data + 11) << 8) |
+	      (*(data->firmware->data + 10));
 
-	build_ver = (*(data->firmware->data + 9) << 8) | (*(data->firmware->data + 8));
+	build_ver = (*(data->firmware->data + 9) << 8) |
+		 (*(data->firmware->data + 8));
 
 	BT_DBG("fw version:%d.%d.%02d ",
 			(fw_ver & 0xf000) >> 8,
@@ -657,22 +675,22 @@
 
 	/* Loading ILM */
 	while (1) {
-		sent_len = (ilm_len - cur_len) >= 14336 ? 14336 : (ilm_len - cur_len);
+		sent_len = min_t(s32, (ilm_len - cur_len), 14336);
 
 		if (sent_len > 0) {
 			packet_header &= ~(0xffffffff);
 			packet_header |= (sent_len << 16);
-			packet_header = cpu_to_le32(packet_header);
+			packet_header_le = cpu_to_le32(packet_header);
 
-			memmove(buf, &packet_header, 4);
-			memmove(buf + 4, data->firmware->data + 32 + cur_len, sent_len);
+			memmove(buf, &packet_header_le, 4);
+			memmove(buf + 4, data->firmware->data + 32 + cur_len,
+					sent_len);
 
 			/* U2M_PDMA descriptor */
 			btmtk_usb_io_write32(data, 0x230, cur_len);
 
-			while ((sent_len % 4) != 0) {
+			while ((sent_len % 4) != 0)
 				sent_len++;
-			}
 
 			/* U2M_PDMA length */
 			btmtk_usb_io_write32(data, 0x234, sent_len << 16);
@@ -693,7 +711,8 @@
 			if (ret)
 				goto error3;
 
-			if (!wait_for_completion_timeout(&sent_to_mcu_done, msecs_to_jiffies(1000))) {
+			if (!wait_for_completion_timeout(&sent_to_mcu_done,
+						msecs_to_jiffies(1000))) {
 				usb_kill_urb(urb);
 				BT_ERR("upload ilm fw timeout\n");
 				goto error3;
@@ -714,58 +733,60 @@
 
 	/* Loading DLM */
 	while (1) {
-		sent_len = (dlm_len - cur_len) >= 14336 ? 14336 : (dlm_len - cur_len);
+		sent_len = min_t(s32, (dlm_len - cur_len), 14336);
 
-		if (sent_len > 0) {
-			packet_header &= ~(0xffffffff);
-			packet_header |= (sent_len << 16);
-			packet_header = cpu_to_le32(packet_header);
-
-			memmove(buf, &packet_header, 4);
-			memmove(buf + 4, data->firmware->data + 32 + ilm_len + cur_len, sent_len);
-
-			/* U2M_PDMA descriptor */
-			btmtk_usb_io_write32(data, 0x230, 0x80000 + cur_len);
-
-			while ((sent_len % 4) != 0) {
-				BT_DBG("sent_len is not divided by 4\n");
-				sent_len++;
-			}
-
-			/* U2M_PDMA length */
-			btmtk_usb_io_write32(data, 0x234, sent_len << 16);
-
-			usb_fill_bulk_urb(urb,
-					udev,
-					pipe,
-					buf,
-					sent_len + 4,
-					load_fw_complete,
-					&sent_to_mcu_done);
-
-			urb->transfer_dma = data_dma;
-			urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-			ret = usb_submit_urb(urb, GFP_ATOMIC);
-
-			if (ret)
-				goto error3;
-
-			if (!wait_for_completion_timeout(&sent_to_mcu_done, msecs_to_jiffies(1000))) {
-				usb_kill_urb(urb);
-				BT_ERR("upload dlm fw timeout\n");
-				goto error3;
-			}
-
-			BT_DBG(".");
-
-			mdelay(500);
-
-			cur_len += sent_len;
-
-		} else {
+		if (sent_len <= 0)
 			break;
+
+		packet_header &= ~(0xffffffff);
+		packet_header |= (sent_len << 16);
+		packet_header_le = cpu_to_le32(packet_header);
+
+		memmove(buf, &packet_header_le, 4);
+		memmove(buf + 4,
+			data->firmware->data + 32 + ilm_len + cur_len,
+			sent_len);
+
+		/* U2M_PDMA descriptor */
+		btmtk_usb_io_write32(data, 0x230, 0x80000 + cur_len);
+
+		while ((sent_len % 4) != 0) {
+			BT_DBG("sent_len is not divided by 4\n");
+			sent_len++;
 		}
+
+		/* U2M_PDMA length */
+		btmtk_usb_io_write32(data, 0x234, sent_len << 16);
+
+		usb_fill_bulk_urb(urb,
+				udev,
+				pipe,
+				buf,
+				sent_len + 4,
+				load_fw_complete,
+				&sent_to_mcu_done);
+
+		urb->transfer_dma = data_dma;
+		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+		ret = usb_submit_urb(urb, GFP_ATOMIC);
+
+		if (ret)
+			goto error3;
+
+		if (!wait_for_completion_timeout(&sent_to_mcu_done,
+					msecs_to_jiffies(1000))) {
+			usb_kill_urb(urb);
+			BT_ERR("upload dlm fw timeout\n");
+			goto error3;
+		}
+
+		BT_DBG(".");
+
+		mdelay(500);
+
+		cur_len += sent_len;
+
 	}
 
 	/* upload 64bytes interrupt vector */
@@ -921,9 +942,8 @@
 	BT_DBG("%s:%s urb %p status %d count %d", __func__, hdev->name,
 					urb, urb->status, urb->actual_length);
 
-	if (!test_bit(HCI_RUNNING, &hdev->flags)) {
+	if (!test_bit(HCI_RUNNING, &hdev->flags))
 		return;
-	}
 
 	if (urb->status == 0) {
 		hdev->stat.byte_rx += urb->actual_length;
@@ -978,8 +998,8 @@
 
 	pipe = usb_rcvbulkpipe(data->udev, data->bulk_rx_ep->bEndpointAddress);
 
-	usb_fill_bulk_urb(urb, data->udev, pipe,
-					buf, size, btmtk_usb_bulk_in_complete, hdev);
+	usb_fill_bulk_urb(urb, data->udev, pipe, buf, size,
+			btmtk_usb_bulk_in_complete, hdev);
 
 	urb->transfer_flags |= URB_FREE_BUFFER;
 
@@ -1015,7 +1035,8 @@
 	if (urb->status == 0) {
 		for (i = 0; i < urb->number_of_packets; i++) {
 			unsigned int offset = urb->iso_frame_desc[i].offset;
-			unsigned int length = urb->iso_frame_desc[i].actual_length;
+			unsigned int length;
+			length = urb->iso_frame_desc[i].actual_length;
 
 			if (urb->iso_frame_desc[i].status)
 				continue;
@@ -1096,8 +1117,9 @@
 
 	pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress);
 
-	usb_fill_int_urb(urb, data->udev, pipe, buf, size, btmtk_usb_isoc_in_complete,
-				hdev, data->isoc_rx_ep->bInterval);
+	usb_fill_int_urb(urb, data->udev, pipe, buf, size,
+			btmtk_usb_isoc_in_complete, hdev,
+			data->isoc_rx_ep->bInterval);
 
 	urb->transfer_flags  = URB_FREE_BUFFER | URB_ISO_ASAP;
 
@@ -1306,7 +1328,8 @@
 		}
 
 		usb_fill_control_urb(urb, data->udev, pipe, (void *) dr,
-				skb->data, skb->len, btmtk_usb_tx_complete, skb);
+				skb->data, skb->len,
+				btmtk_usb_tx_complete, skb);
 
 		hdev->stat.cmd_tx++;
 		break;
@@ -1322,8 +1345,8 @@
 		pipe = usb_sndbulkpipe(data->udev,
 					data->bulk_tx_ep->bEndpointAddress);
 
-		usb_fill_bulk_urb(urb, data->udev, pipe,
-				skb->data, skb->len, btmtk_usb_tx_complete, skb);
+		usb_fill_bulk_urb(urb, data->udev, pipe, skb->data,
+				skb->len, btmtk_usb_tx_complete, skb);
 
 		hdev->stat.acl_tx++;
 		BT_DBG("HCI_ACLDATA_PKT:\n");
@@ -1442,7 +1465,8 @@
 
 static void btmtk_usb_work(struct work_struct *work)
 {
-	struct btmtk_usb_data *data = container_of(work, struct btmtk_usb_data, work);
+	struct btmtk_usb_data *data = container_of(work, struct btmtk_usb_data,
+			work);
 	struct hci_dev *hdev = data->hdev;
 	int new_alts;
 	int err;
@@ -1451,7 +1475,8 @@
 
 	if (hdev->conn_hash.sco_num > 0) {
 		if (!test_bit(BTUSB_DID_ISO_RESUME, &data->flags)) {
-			err = usb_autopm_get_interface(data->isoc ? data->isoc : data->intf);
+			err = usb_autopm_get_interface(data->isoc ?
+					data->isoc : data->intf);
 			if (err < 0) {
 				clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
 				usb_kill_anchored_urbs(&data->isoc_anchor);
@@ -1489,13 +1514,15 @@
 		__set_isoc_interface(hdev, 0);
 
 		if (test_and_clear_bit(BTUSB_DID_ISO_RESUME, &data->flags))
-			 usb_autopm_put_interface(data->isoc ? data->isoc : data->intf);
+			usb_autopm_put_interface(data->isoc ?
+					 data->isoc : data->intf);
 	}
 }
 
 static void btmtk_usb_waker(struct work_struct *work)
 {
-	struct btmtk_usb_data *data = container_of(work, struct btmtk_usb_data, waker);
+	struct btmtk_usb_data *data = container_of(work, struct btmtk_usb_data,
+			waker);
 	int err;
 
 	err = usb_autopm_get_interface(data->intf);
diff --git a/drivers/staging/ced1401/ced_ioc.c b/drivers/staging/ced1401/ced_ioc.c
index 2dbaf39e..62efd74 100644
--- a/drivers/staging/ced1401/ced_ioc.c
+++ b/drivers/staging/ced1401/ced_ioc.c
@@ -692,10 +692,7 @@
 		__func__, puBuf, dwLength, bCircular);
 
 	/*  To pin down user pages we must first acquire the mapping semaphore. */
-	down_read(&current->mm->mmap_sem);	/*  get memory map semaphore */
-	nPages = get_user_pages(current, current->mm, ulStart, len, 1, 0,
-				pPages, NULL);
-	up_read(&current->mm->mmap_sem);	/*  release the semaphore */
+	nPages = get_user_pages_fast(ulStart, len, 1, pPages);
 	dev_dbg(&pdx->interface->dev, "%s nPages = %d", __func__, nPages);
 
 	if (nPages > 0) {		/*  if we succeeded */
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
index f73287e..bfa27e7 100644
--- a/drivers/staging/comedi/Kconfig
+++ b/drivers/staging/comedi/Kconfig
@@ -485,6 +485,7 @@
 	tristate "NI AT-MIO E series ISA-PNP card support"
 	select COMEDI_8255
 	select COMEDI_NI_TIO
+	select COMEDI_FC
 	---help---
 	  Enable support for National Instruments AT-MIO E series cards
 	  National Instruments AT-MIO-16E-1 (ni_atmio),
@@ -990,8 +991,6 @@
 
 config COMEDI_NI_6527
 	tristate "NI 6527 support"
-	depends on HAS_DMA
-	select COMEDI_MITE
 	---help---
 	  Enable support for the National Instruments 6527 PCI card
 
diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c
index 94b2385f..4e26bd7 100644
--- a/drivers/staging/comedi/comedi_buf.c
+++ b/drivers/staging/comedi/comedi_buf.c
@@ -344,7 +344,7 @@
 }
 EXPORT_SYMBOL_GPL(comedi_buf_read_free);
 
-int comedi_buf_put(struct comedi_async *async, short x)
+int comedi_buf_put(struct comedi_async *async, unsigned short x)
 {
 	unsigned int n = __comedi_buf_write_alloc(async, sizeof(short), 1);
 
@@ -352,20 +352,20 @@
 		async->events |= COMEDI_CB_ERROR;
 		return 0;
 	}
-	*(short *)(async->prealloc_buf + async->buf_write_ptr) = x;
+	*(unsigned short *)(async->prealloc_buf + async->buf_write_ptr) = x;
 	comedi_buf_write_free(async, sizeof(short));
 	return 1;
 }
 EXPORT_SYMBOL_GPL(comedi_buf_put);
 
-int comedi_buf_get(struct comedi_async *async, short *x)
+int comedi_buf_get(struct comedi_async *async, unsigned short *x)
 {
 	unsigned int n = comedi_buf_read_n_available(async);
 
 	if (n < sizeof(short))
 		return 0;
 	comedi_buf_read_alloc(async, sizeof(short));
-	*x = *(short *)(async->prealloc_buf + async->buf_read_ptr);
+	*x = *(unsigned short *)(async->prealloc_buf + async->buf_read_ptr);
 	comedi_buf_read_free(async, sizeof(short));
 	return 1;
 }
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 1636c7c..f3d59e2 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -543,7 +543,7 @@
 {
 	s->private = kzalloc(size, GFP_KERNEL);
 	if (s->private)
-		comedi_set_subdevice_runflags(s, ~0, SRF_FREE_SPRIV);
+		s->runflags |= SRF_FREE_SPRIV;
 	return s->private;
 }
 EXPORT_SYMBOL_GPL(comedi_alloc_spriv);
@@ -806,7 +806,6 @@
 		} else {
 			us->range_type = 0;	/* XXX */
 		}
-		us->flags = s->flags;
 
 		if (s->busy)
 			us->subd_flags |= SDF_BUSY;
@@ -818,8 +817,6 @@
 			us->subd_flags |= SDF_LOCK_OWNER;
 		if (!s->maxdata && s->maxdata_list)
 			us->subd_flags |= SDF_MAXDATA;
-		if (s->flaglist)
-			us->subd_flags |= SDF_FLAGS;
 		if (s->range_table_list)
 			us->subd_flags |= SDF_RANGETYPE;
 		if (s->do_cmd)
@@ -829,8 +826,6 @@
 			us->insn_bits_support = COMEDI_SUPPORTED;
 		else
 			us->insn_bits_support = COMEDI_UNSUPPORTED;
-
-		us->settling_time_0 = s->settling_time_0;
 	}
 
 	ret = copy_to_user(arg, tmp, dev->n_subdevices * sizeof(*tmp));
@@ -875,13 +870,8 @@
 			return -EFAULT;
 	}
 
-	if (it.flaglist) {
-		if (!s->flaglist)
-			return -EINVAL;
-		if (copy_to_user(it.flaglist, s->flaglist,
-				 s->n_chan * sizeof(unsigned int)))
-			return -EFAULT;
-	}
+	if (it.flaglist)
+		return -EINVAL;	/* flaglist not supported */
 
 	if (it.rangelist) {
 		int i;
@@ -1431,17 +1421,11 @@
 	async->cmd = cmd;
 	async->cmd.data = NULL;
 	/* load channel/gain list */
-	async->cmd.chanlist =
-	    kmalloc(async->cmd.chanlist_len * sizeof(int), GFP_KERNEL);
-	if (!async->cmd.chanlist) {
-		DPRINTK("allocation failed\n");
-		return -ENOMEM;
-	}
-
-	if (copy_from_user(async->cmd.chanlist, user_chanlist,
-			   async->cmd.chanlist_len * sizeof(int))) {
-		DPRINTK("fault reading chanlist\n");
-		ret = -EFAULT;
+	async->cmd.chanlist = memdup_user(user_chanlist,
+					  async->cmd.chanlist_len * sizeof(int));
+	if (IS_ERR(async->cmd.chanlist)) {
+		ret = PTR_ERR(async->cmd.chanlist);
+		DPRINTK("memdup_user failed with code %d\n", ret);
 		goto cleanup;
 	}
 
@@ -1485,7 +1469,8 @@
 	if (async->cmd.flags & TRIG_WAKE_EOS)
 		async->cb_mask |= COMEDI_CB_EOS;
 
-	comedi_set_subdevice_runflags(s, ~0, SRF_USER | SRF_RUNNING);
+	comedi_set_subdevice_runflags(s, SRF_USER | SRF_ERROR | SRF_RUNNING,
+				      SRF_USER | SRF_RUNNING);
 
 	/* set s->busy _after_ setting SRF_RUNNING flag to avoid race with
 	 * comedi_read() or comedi_write() */
@@ -1558,18 +1543,11 @@
 
 	/* load channel/gain list */
 	if (cmd.chanlist) {
-		chanlist =
-		    kmalloc(cmd.chanlist_len * sizeof(int), GFP_KERNEL);
-		if (!chanlist) {
-			DPRINTK("allocation failed\n");
-			ret = -ENOMEM;
-			goto cleanup;
-		}
-
-		if (copy_from_user(chanlist, user_chanlist,
-				   cmd.chanlist_len * sizeof(int))) {
-			DPRINTK("fault reading chanlist\n");
-			ret = -EFAULT;
+		chanlist = memdup_user(user_chanlist,
+				       cmd.chanlist_len * sizeof(int));
+		if (IS_ERR(chanlist)) {
+			ret = PTR_ERR(chanlist);
+			DPRINTK("memdup_user exited with code %d", ret);
 			goto cleanup;
 		}
 
diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
index 2e19f65..143be80 100644
--- a/drivers/staging/comedi/comedidev.h
+++ b/drivers/staging/comedi/comedidev.h
@@ -57,11 +57,6 @@
 	unsigned int maxdata;	/* if maxdata==0, use list */
 	const unsigned int *maxdata_list;	/* list is channel specific */
 
-	unsigned int flags;
-	const unsigned int *flaglist;
-
-	unsigned int settling_time_0;
-
 	const struct comedi_lrange *range_table;
 	const struct comedi_lrange *const *range_table_list;
 
@@ -307,7 +302,26 @@
 	return s->range_table->range[range].min >= 0;
 }
 
-/* some silly little inline functions */
+static inline bool comedi_chan_range_is_bipolar(struct comedi_subdevice *s,
+						unsigned int chan,
+						unsigned int range)
+{
+	return s->range_table_list[chan]->range[range].min < 0;
+}
+
+static inline bool comedi_chan_range_is_unipolar(struct comedi_subdevice *s,
+						 unsigned int chan,
+						 unsigned int range)
+{
+	return s->range_table_list[chan]->range[range].min >= 0;
+}
+
+/* munge between offset binary and two's complement values */
+static inline unsigned int comedi_offset_munge(struct comedi_subdevice *s,
+					       unsigned int val)
+{
+	return val ^ s->maxdata ^ (s->maxdata >> 1);
+}
 
 static inline unsigned int bytes_per_sample(const struct comedi_subdevice *subd)
 {
@@ -332,8 +346,8 @@
 unsigned int comedi_buf_read_alloc(struct comedi_async *, unsigned int);
 unsigned int comedi_buf_read_free(struct comedi_async *, unsigned int);
 
-int comedi_buf_put(struct comedi_async *, short);
-int comedi_buf_get(struct comedi_async *, short *);
+int comedi_buf_put(struct comedi_async *, unsigned short);
+int comedi_buf_get(struct comedi_async *, unsigned short *);
 
 void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset,
 			  const void *source, unsigned int num_bytes);
@@ -345,6 +359,8 @@
 int comedi_dio_insn_config(struct comedi_device *, struct comedi_subdevice *,
 			   struct comedi_insn *, unsigned int *data,
 			   unsigned int mask);
+unsigned int comedi_dio_update_state(struct comedi_subdevice *,
+				     unsigned int *data);
 
 void *comedi_alloc_devpriv(struct comedi_device *, size_t);
 int comedi_alloc_subdevices(struct comedi_device *, int);
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index 317a821..8f02bf6 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -190,6 +190,28 @@
 }
 EXPORT_SYMBOL_GPL(comedi_dio_insn_config);
 
+/**
+ * comedi_dio_update_state() - update the internal state of DIO subdevices.
+ * @s: comedi_subdevice struct
+ * @data: the channel mask and bits to update
+ */
+unsigned int comedi_dio_update_state(struct comedi_subdevice *s,
+				     unsigned int *data)
+{
+	unsigned int chanmask = (s->n_chan < 32) ? ((1 << s->n_chan) - 1)
+						 : 0xffffffff;
+	unsigned int mask = data[0] & chanmask;
+	unsigned int bits = data[1];
+
+	if (mask) {
+		s->state &= ~mask;
+		s->state |= (bits & mask);
+	}
+
+	return mask;
+}
+EXPORT_SYMBOL_GPL(comedi_dio_update_state);
+
 static int insn_rw_emulate_bits(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				struct comedi_insn *insn, unsigned int *data)
@@ -285,6 +307,13 @@
 		if (s->type == COMEDI_SUBD_UNUSED)
 			continue;
 
+		if (s->type == COMEDI_SUBD_DO) {
+			if (s->n_chan < 32)
+				s->io_bits = (1 << s->n_chan) - 1;
+			else
+				s->io_bits = 0xffffffff;
+		}
+
 		if (s->len_chanlist == 0)
 			s->len_chanlist = 1;
 
diff --git a/drivers/staging/comedi/drivers/8253.h b/drivers/staging/comedi/drivers/8253.h
index 3abedcd..e3d737c 100644
--- a/drivers/staging/comedi/drivers/8253.h
+++ b/drivers/staging/comedi/drivers/8253.h
@@ -21,6 +21,15 @@
 
 #include "../comedi.h"
 
+/*
+ * Common oscillator base values in nanoseconds
+ */
+#define I8254_OSC_BASE_10MHZ		100
+#define I8254_OSC_BASE_5MHZ		200
+#define I8254_OSC_BASE_4MHZ		250
+#define I8254_OSC_BASE_2MHZ		500
+#define I8254_OSC_BASE_1MHZ		1000
+
 #define i8253_cascade_ns_to_timer i8253_cascade_ns_to_timer_2div
 
 static inline void i8253_cascade_ns_to_timer_2div_old(int i8253_osc_base,
diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
index 2f070fd..b4009e8 100644
--- a/drivers/staging/comedi/drivers/8255.c
+++ b/drivers/staging/comedi/drivers/8255.c
@@ -112,7 +112,7 @@
 {
 	struct subdev_8255_private *spriv = s->private;
 	unsigned long iobase = spriv->iobase;
-	short d;
+	unsigned short d;
 
 	d = spriv->io(0, _8255_DATA, 0, iobase);
 	d |= (spriv->io(0, _8255_DATA + 1, 0, iobase) << 8);
@@ -126,30 +126,24 @@
 
 static int subdev_8255_insn(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data)
+			    struct comedi_insn *insn,
+			    unsigned int *data)
 {
 	struct subdev_8255_private *spriv = s->private;
 	unsigned long iobase = spriv->iobase;
 	unsigned int mask;
-	unsigned int bits;
 	unsigned int v;
 
-	mask = data[0];
-	bits = data[1];
-
+	mask = comedi_dio_update_state(s, data);
 	if (mask) {
-		v = s->state;
-		v &= ~mask;
-		v |= (bits & mask);
-
 		if (mask & 0xff)
-			spriv->io(1, _8255_DATA, v & 0xff, iobase);
+			spriv->io(1, _8255_DATA, s->state & 0xff, iobase);
 		if (mask & 0xff00)
-			spriv->io(1, _8255_DATA + 1, (v >> 8) & 0xff, iobase);
+			spriv->io(1, _8255_DATA + 1, (s->state >> 8) & 0xff,
+				  iobase);
 		if (mask & 0xff0000)
-			spriv->io(1, _8255_DATA + 2, (v >> 16) & 0xff, iobase);
-
-		s->state = v;
+			spriv->io(1, _8255_DATA + 2, (s->state >> 16) & 0xff,
+				  iobase);
 	}
 
 	v = spriv->io(0, _8255_DATA, 0, iobase);
@@ -288,9 +282,6 @@
 	s->insn_bits	= subdev_8255_insn;
 	s->insn_config	= subdev_8255_insn_config;
 
-	s->state	= 0;
-	s->io_bits	= 0;
-
 	subdev_8255_do_config(dev, s);
 
 	return 0;
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
index 63dff77..dc87df0 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
@@ -204,7 +204,6 @@
 		s->len_chanlist =
 			devpriv->s_EeParameters.i_NbrDiChannel;
 		s->range_table = &range_digital;
-		s->io_bits = 0;	/* all bits input */
 		s->insn_config = this_board->di_config;
 		s->insn_read = this_board->di_read;
 		s->insn_write = this_board->di_write;
@@ -223,7 +222,6 @@
 		s->len_chanlist =
 			devpriv->s_EeParameters.i_NbrDoChannel;
 		s->range_table = &range_digital;
-		s->io_bits = 0xf;	/* all bits output */
 
 		/* insn_config - for digital output memory */
 		s->insn_config = this_board->do_config;
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
index dfd1e66..2ed2da3 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
@@ -133,7 +133,7 @@
 	unsigned short us_UseDma;	/*  To use Dma or not */
 	unsigned char b_DmaDoubleBuffer;	/*  we can use double buffering */
 	unsigned int ui_DmaActualBuffer;	/*  which buffer is used now */
-	short *ul_DmaBufferVirtual[2];	/*  pointers to begin of DMA buffer */
+	unsigned short *ul_DmaBufferVirtual[2];	/*  pointers to DMA buffer */
 	unsigned int ul_DmaBufferHw[2];	/*  hw address of DMA buff */
 	unsigned int ui_DmaBufferSize[2];	/*  size of dma buffer in bytes */
 	unsigned int ui_DmaBufferUsesize[2];	/*  which size we may now used for transfer */
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
index e3cc429..8466854 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
@@ -260,18 +260,13 @@
 				 unsigned int *data)
 {
 	struct addi_private *devpriv = dev->private;
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
 
 	s->state = inl(devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
 			APCI1564_DIGITAL_OP_RW);
-	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
 
+	if (comedi_dio_update_state(s, data))
 		outl(s->state, devpriv->i_IobaseAmcc + APCI1564_DIGITAL_OP +
 			APCI1564_DIGITAL_OP_RW);
-	}
 
 	data[1] = s->state;
 
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
index 1449b92..3c9eec8 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
@@ -1391,7 +1391,7 @@
  */
 static void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,
 						  struct comedi_subdevice *s,
-						  short *dma_buffer,
+						  unsigned short *dma_buffer,
 						  unsigned int num_samples)
 {
 	struct addi_private *devpriv = dev->private;
@@ -2175,21 +2175,16 @@
 				 unsigned int *data)
 {
 	struct addi_private *devpriv = dev->private;
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
-	unsigned int val;
 
-	/* The do channels are bits 7:4 of the do register */
-	val = devpriv->b_DigitalOutputRegister >> 4;
-	if (mask) {
-		val &= ~mask;
-		val |= (bits & mask);
-		devpriv->b_DigitalOutputRegister = val << 4;
+	if (comedi_dio_update_state(s, data)) {
+		/* The do channels are bits 7:4 of the do register */
+		devpriv->b_DigitalOutputRegister = s->state << 4;
 
-		outb(val << 4, devpriv->iobase + APCI3120_DIGITAL_OUTPUT);
+		outb(devpriv->b_DigitalOutputRegister,
+		     devpriv->iobase + APCI3120_DIGITAL_OUTPUT);
 	}
 
-	data[1] = val;
+	data[1] = s->state;
 
 	return insn->n;
 }
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
index 32dce03..dc73d4d 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
@@ -623,16 +623,11 @@
 				 unsigned int *data)
 {
 	struct addi_private *devpriv = dev->private;
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
 
 	s->state = inl(devpriv->i_IobaseAddon) & 0xf;
-	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
 
+	if (comedi_dio_update_state(s, data))
 		outl(s->state, devpriv->i_IobaseAddon);
-	}
 
 	data[1] = s->state;
 
diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c
index 08674c1..9d1b142 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1516.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1516.c
@@ -90,16 +90,10 @@
 				 struct comedi_insn *insn,
 				 unsigned int *data)
 {
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
-
 	s->state = inw(dev->iobase + APCI1516_DO_REG);
-	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
 
+	if (comedi_dio_update_state(s, data))
 		outw(s->state, dev->iobase + APCI1516_DO_REG);
-	}
 
 	data[1] = s->state;
 
diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c
index 9652374..5ee204bc 100644
--- a/drivers/staging/comedi/drivers/addi_apci_16xx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c
@@ -87,17 +87,8 @@
 				  struct comedi_insn *insn,
 				  unsigned int *data)
 {
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
-
-	/* Only update the channels configured as outputs */
-	mask &= s->io_bits;
-	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
-
+	if (comedi_dio_update_state(s, data))
 		outl(s->state, dev->iobase + APCI16XX_OUT_REG(s->index));
-	}
 
 	data[1] = inl(dev->iobase + APCI16XX_IN_REG(s->index));
 
diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c
index 6b0ea16..c77ee87 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2032.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2032.c
@@ -57,16 +57,10 @@
 				 struct comedi_insn *insn,
 				 unsigned int *data)
 {
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
-
 	s->state = inl(dev->iobase + APCI2032_DO_REG);
-	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
 
+	if (comedi_dio_update_state(s, data))
 		outl(s->state, dev->iobase + APCI2032_DO_REG);
-	}
 
 	data[1] = s->state;
 
diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c
index 92ac8ec..7fb32e7 100644
--- a/drivers/staging/comedi/drivers/addi_apci_2200.c
+++ b/drivers/staging/comedi/drivers/addi_apci_2200.c
@@ -50,16 +50,10 @@
 				 struct comedi_insn *insn,
 				 unsigned int *data)
 {
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
-
 	s->state = inw(dev->iobase + APCI2200_DO_REG);
-	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
 
+	if (comedi_dio_update_state(s, data))
 		outw(s->state, dev->iobase + APCI2200_DO_REG);
-	}
 
 	data[1] = s->state;
 
diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c
index d804957..67d09e8 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3120.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3120.c
@@ -164,7 +164,6 @@
 	s->maxdata = 1;
 	s->len_chanlist = this_board->i_NbrDiChannel;
 	s->range_table = &range_digital;
-	s->io_bits = 0;	/* all bits input */
 	s->insn_bits = apci3120_di_insn_bits;
 
 	/*  Allocate and Initialise DO Subdevice Structures */
@@ -176,7 +175,6 @@
 	s->maxdata = this_board->i_DoMaxdata;
 	s->len_chanlist = this_board->i_NbrDoChannel;
 	s->range_table = &range_digital;
-	s->io_bits = 0xf;	/* all bits output */
 	s->insn_bits = apci3120_do_insn_bits;
 
 	/*  Allocate and Initialise Timer Subdevice Structures */
diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c
index d9650ff..6138440 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3501.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3501.c
@@ -161,16 +161,10 @@
 				 struct comedi_insn *insn,
 				 unsigned int *data)
 {
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
-
 	s->state = inl(dev->iobase + APCI3501_DO_REG);
-	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
 
+	if (comedi_dio_update_state(s, data))
 		outl(s->state, dev->iobase + APCI3501_DO_REG);
-	}
 
 	data[1] = s->state;
 
diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
index cf5dd10..761cbf8 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c
@@ -664,16 +664,10 @@
 				 struct comedi_insn *insn,
 				 unsigned int *data)
 {
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
-
 	s->state = inl(dev->iobase + 48) & 0xf;
-	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
 
+	if (comedi_dio_update_state(s, data))
 		outl(s->state, dev->iobase + 48);
-	}
 
 	data[1] = s->state;
 
@@ -717,16 +711,11 @@
 				  struct comedi_insn *insn,
 				  unsigned int *data)
 {
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
+	unsigned int mask;
 	unsigned int val;
 
-	/* only update output channels */
-	mask &= s->io_bits;
+	mask = comedi_dio_update_state(s, data);
 	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
-
 		if (mask & 0xff)
 			outl(s->state & 0xff, dev->iobase + 80);
 		if (mask & 0xff0000)
diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c
index a67ad57..dd092c795 100644
--- a/drivers/staging/comedi/drivers/adl_pci6208.c
+++ b/drivers/staging/comedi/drivers/adl_pci6208.c
@@ -1,44 +1,35 @@
 /*
-    comedi/drivers/adl_pci6208.c
+ * adl_pci6208.c
+ * Comedi driver for ADLink 6208 series cards
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
 
-    Hardware driver for ADLink 6208 series cards:
-	card	     | voltage output    | current output
-	-------------+-------------------+---------------
-	PCI-6208V    |  8 channels       | -
-	PCI-6216V    | 16 channels       | -
-	PCI-6208A    |  8 channels       | 8 channels
-
-    COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 2000 David A. Schleef <ds@schleef.org>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-*/
 /*
-Driver: adl_pci6208
-Description: ADLink PCI-6208/6216 Series Multi-channel Analog Output Cards
-Devices: (ADLink) PCI-6208 [adl_pci6208]
-	 (ADLink) PCI-6216 [adl_pci6216]
-Author: nsyeow <nsyeow@pd.jaring.my>
-Updated: Fri, 30 Jan 2004 14:44:27 +0800
-Status: untested
-
-Configuration Options: not applicable, uses PCI auto config
-
-References:
-	- ni_660x.c
-	- adl_pci9111.c		copied the entire pci setup section
-	- adl_pci9118.c
-*/
+ * Driver: adl_pci6208
+ * Description: ADLink PCI-6208/6216 Series Multi-channel Analog Output Cards
+ * Devices: (ADLink) PCI-6208 [adl_pci6208]
+ *	    (ADLink) PCI-6216 [adl_pci6216]
+ * Author: nsyeow <nsyeow@pd.jaring.my>
+ * Updated: Fri, 30 Jan 2004 14:44:27 +0800
+ * Status: untested
+ *
+ * Configuration Options: not applicable, uses PCI auto config
+ */
 
 #include <linux/module.h>
+#include <linux/delay.h>
 #include <linux/pci.h>
 
 #include "../comedidev.h"
@@ -82,37 +73,56 @@
 	unsigned int ao_readback[PCI6208_MAX_AO_CHANNELS];
 };
 
-static int pci6208_ao_winsn(struct comedi_device *dev,
-			    struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data)
+static int pci6208_ao_wait_for_data_send(struct comedi_device *dev,
+					 unsigned int timeout)
+{
+	unsigned int status;
+
+	while (timeout--) {
+		status = inw(dev->iobase + PCI6208_AO_STATUS);
+		if ((status & PCI6208_AO_STATUS_DATA_SEND) == 0)
+			return 0;
+		udelay(1);
+	}
+
+	return -ETIME;
+}
+
+static int pci6208_ao_insn_write(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
 	struct pci6208_private *devpriv = dev->private;
-	int chan = CR_CHAN(insn->chanspec);
-	unsigned long invert = 1 << (16 - 1);
-	unsigned long value = 0;
-	unsigned short status;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int val = devpriv->ao_readback[chan];
+	int ret;
 	int i;
 
 	for (i = 0; i < insn->n; i++) {
-		value = data[i] ^ invert;
+		val = data[i];
 
-		do {
-			status = inw(dev->iobase + PCI6208_AO_STATUS);
-		} while (status & PCI6208_AO_STATUS_DATA_SEND);
+		/* D/A transfer rate is 2.2us, wait up to 10us */
+		ret = pci6208_ao_wait_for_data_send(dev, 10);
+		if (ret)
+			return ret;
 
-		outw(value, dev->iobase + PCI6208_AO_CONTROL(chan));
+		/* the hardware expects two's complement values */
+		outw(comedi_offset_munge(s, val),
+		     dev->iobase + PCI6208_AO_CONTROL(chan));
 	}
-	devpriv->ao_readback[chan] = value;
+	devpriv->ao_readback[chan] = val;
 
 	return insn->n;
 }
 
-static int pci6208_ao_rinsn(struct comedi_device *dev,
-			    struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data)
+static int pci6208_ao_insn_read(struct comedi_device *dev,
+				struct comedi_subdevice *s,
+				struct comedi_insn *insn,
+				unsigned int *data)
 {
 	struct pci6208_private *devpriv = dev->private;
-	int chan = CR_CHAN(insn->chanspec);
+	unsigned int chan = CR_CHAN(insn->chanspec);
 	int i;
 
 	for (i = 0; i < insn->n; i++)
@@ -141,15 +151,8 @@
 				struct comedi_insn *insn,
 				unsigned int *data)
 {
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
-
-	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
-
+	if (comedi_dio_update_state(s, data))
 		outw(s->state, dev->iobase + PCI6208_DIO);
-	}
 
 	data[1] = s->state;
 
@@ -193,8 +196,8 @@
 	s->n_chan	= boardinfo->ao_chans;
 	s->maxdata	= 0xffff;
 	s->range_table	= &range_bipolar10;
-	s->insn_write	= pci6208_ao_winsn;
-	s->insn_read	= pci6208_ao_rinsn;
+	s->insn_write	= pci6208_ao_insn_write;
+	s->insn_read	= pci6208_ao_insn_read;
 
 	s = &dev->subdevices[1];
 	/* digital input subdevice */
@@ -221,10 +224,6 @@
 	val = inw(dev->iobase + PCI6208_DIO);
 	val = (val & PCI6208_DIO_DO_MASK) >> PCI6208_DIO_DO_SHIFT;
 	s->state	= val;
-	s->io_bits	= 0x0f;
-
-	dev_info(dev->class_dev, "%s: %s, I/O base=0x%04lx\n",
-		dev->driver->driver_name, dev->board_name, dev->iobase);
 
 	return 0;
 }
@@ -259,5 +258,5 @@
 module_comedi_pci_driver(adl_pci6208_driver, adl_pci6208_pci_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for ADLink 6208 series cards");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c
index 81b7203..5617f5c 100644
--- a/drivers/staging/comedi/drivers/adl_pci7x3x.c
+++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c
@@ -112,21 +112,10 @@
 				    unsigned int *data)
 {
 	unsigned long reg = (unsigned long)s->private;
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
 
-	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
-
+	if (comedi_dio_update_state(s, data))
 		outl(s->state, dev->iobase + reg);
-	}
 
-	/*
-	 * NOTE: The output register is not readable.
-	 * This returned state will not be correct until all the
-	 * outputs have been updated.
-	 */
 	data[1] = s->state;
 
 	return insn->n;
diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c
index 78cea19..eab8da2 100644
--- a/drivers/staging/comedi/drivers/adl_pci9111.c
+++ b/drivers/staging/comedi/drivers/adl_pci9111.c
@@ -86,8 +86,6 @@
 #define PCI9111_AI_INSTANT_READ_UDELAY_US	2
 #define PCI9111_AI_INSTANT_READ_TIMEOUT		100
 
-#define PCI9111_8254_CLOCK_PERIOD_NS		500
-
 /*
  * IO address map and bit defines
  */
@@ -153,7 +151,7 @@
 	unsigned int div1;
 	unsigned int div2;
 
-	short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
+	unsigned short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
 };
 
 static void plx9050_interrupt_control(unsigned long io_base,
@@ -393,11 +391,10 @@
 
 	if (cmd->convert_src == TRIG_TIMER) {
 		tmp = cmd->convert_arg;
-		i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
-					       &dev_private->div1,
-					       &dev_private->div2,
-					       &cmd->convert_arg,
-					       cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ,
+					  &dev_private->div1,
+					  &dev_private->div2,
+					  &cmd->convert_arg, cmd->flags);
 		if (tmp != cmd->convert_arg)
 			error++;
 	}
@@ -570,7 +567,7 @@
 			     unsigned int num_bytes,
 			     unsigned int start_chan_index)
 {
-	short *array = data;
+	unsigned short *array = data;
 	unsigned int maxdata = s->maxdata;
 	unsigned int invert = (maxdata + 1) >> 1;
 	unsigned int shift = (maxdata == 0xffff) ? 0 : 4;
@@ -813,15 +810,8 @@
 				struct comedi_insn *insn,
 				unsigned int *data)
 {
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
-
-	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
-
+	if (comedi_dio_update_state(s, data))
 		outw(s->state, dev->iobase + PCI9111_DIO_REG);
-	}
 
 	data[1] = s->state;
 
diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
index 22196ad..9864896 100644
--- a/drivers/staging/comedi/drivers/adl_pci9118.c
+++ b/drivers/staging/comedi/drivers/adl_pci9118.c
@@ -352,12 +352,11 @@
 						 * on external start
 						 */
 	unsigned int ai_data_len;
-	short *ai_data;
-	short ao_data[2];			/* data output buffer */
+	unsigned short ao_data[2];		/* data output buffer */
 	unsigned int ai_scans;			/* number of scans to do */
 	char dma_doublebuf;			/* we can use double buffering */
 	unsigned int dma_actbuf;		/* which buffer is used now */
-	short *dmabuf_virt[2];			/*
+	unsigned short *dmabuf_virt[2];		/*
 						 * pointers to begin of
 						 * DMA buffer
 						 */
@@ -671,13 +670,12 @@
 
 static int pci9118_insn_bits_do(struct comedi_device *dev,
 				struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data)
+				struct comedi_insn *insn,
+				unsigned int *data)
 {
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
+	if (comedi_dio_update_state(s, data))
 		outl(s->state & 0x0f, dev->iobase + PCI9118_DO);
-	}
+
 	data[1] = s->state;
 
 	return insn->n;
@@ -701,7 +699,7 @@
 
 static unsigned int defragment_dma_buffer(struct comedi_device *dev,
 					  struct comedi_subdevice *s,
-					  short *dma_buffer,
+					  unsigned short *dma_buffer,
 					  unsigned int num_samples)
 {
 	struct pci9118_private *devpriv = dev->private;
@@ -725,7 +723,7 @@
 
 static int move_block_from_dma(struct comedi_device *dev,
 					struct comedi_subdevice *s,
-					short *dma_buffer,
+					unsigned short *dma_buffer,
 					unsigned int num_samples)
 {
 	struct pci9118_private *devpriv = dev->private;
@@ -793,7 +791,8 @@
 	case 4:
 		if (*tim2 < this_board->ai_ns_min)
 			*tim2 = this_board->ai_ns_min;
-		i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, div1, div2,
+		i8253_cascade_ns_to_timer(devpriv->i8254_osc_base,
+					  div1, div2,
 					  tim2, flags & TRIG_ROUND_NEAREST);
 		break;
 	case 2:
@@ -925,7 +924,7 @@
 {
 	struct pci9118_private *devpriv = dev->private;
 	unsigned int i, num_samples = num_bytes / sizeof(short);
-	short *array = data;
+	unsigned short *array = data;
 
 	for (i = 0; i < num_samples; i++) {
 		if (devpriv->usedma)
@@ -945,7 +944,7 @@
 					   unsigned short int_daq)
 {
 	struct pci9118_private *devpriv = dev->private;
-	register short sampl;
+	unsigned short sampl;
 
 	s->async->events = 0;
 
@@ -1278,9 +1277,9 @@
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		tmp = cmd->scan_begin_arg;
-		i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
-					  &divisor2, &cmd->scan_begin_arg,
-					  cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(devpriv->i8254_osc_base,
+					  &divisor1, &divisor2,
+					  &cmd->scan_begin_arg, cmd->flags);
 		if (cmd->scan_begin_arg < this_board->ai_ns_min)
 			cmd->scan_begin_arg = this_board->ai_ns_min;
 		if (tmp != cmd->scan_begin_arg)
@@ -1289,9 +1288,9 @@
 
 	if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) {
 		tmp = cmd->convert_arg;
-		i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
-					  &divisor2, &cmd->convert_arg,
-					  cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(devpriv->i8254_osc_base,
+					  &divisor1, &divisor2,
+					  &cmd->convert_arg, cmd->flags);
 		if (cmd->convert_arg < this_board->ai_ns_min)
 			cmd->convert_arg = this_board->ai_ns_min;
 		if (tmp != cmd->convert_arg)
@@ -1613,7 +1612,6 @@
 	devpriv->ai_n_chan = cmd->chanlist_len;
 	devpriv->ai_n_scanlen = cmd->scan_end_arg;
 	devpriv->ai_chanlist = cmd->chanlist;
-	devpriv->ai_data = s->async->prealloc_buf;
 	devpriv->ai_data_len = s->async->prealloc_bufsz;
 	devpriv->ai_timer1 = 0;
 	devpriv->ai_timer2 = 0;
@@ -1987,8 +1985,8 @@
 		for (i = 0; i < 2; i++) {
 			for (pages = 4; pages >= 0; pages--) {
 				devpriv->dmabuf_virt[i] =
-				    (short *)__get_free_pages(GFP_KERNEL,
-							      pages);
+				    (unsigned short *)
+				    __get_free_pages(GFP_KERNEL, pages);
 				if (devpriv->dmabuf_virt[i])
 					break;
 			}
@@ -2075,7 +2073,6 @@
 	s->maxdata = 1;
 	s->len_chanlist = 4;
 	s->range_table = &range_digital;
-	s->io_bits = 0;		/* all bits input */
 	s->insn_bits = pci9118_insn_bits_di;
 
 	s = &dev->subdevices[3];
@@ -2085,11 +2082,10 @@
 	s->maxdata = 1;
 	s->len_chanlist = 4;
 	s->range_table = &range_digital;
-	s->io_bits = 0xf;	/* all bits output */
 	s->insn_bits = pci9118_insn_bits_do;
 
 	devpriv->valid = 1;
-	devpriv->i8254_osc_base = 250;	/* 250ns=4MHz */
+	devpriv->i8254_osc_base = I8254_OSC_BASE_4MHZ;
 	devpriv->ai_maskharderr = 0x10a;
 					/* default measure crash condition */
 	if (hw_err_mask)		/* disable some requested */
diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
index cdf5ba2..8150a67 100644
--- a/drivers/staging/comedi/drivers/adq12b.c
+++ b/drivers/staging/comedi/drivers/adq12b.c
@@ -119,7 +119,6 @@
 	int differential;	/* option 3 of comedi_config */
 	int last_channel;
 	int last_range;
-	unsigned int digital_state;
 };
 
 /*
@@ -186,23 +185,25 @@
 
 static int adq12b_do_insn_bits(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
-	struct adq12b_private *devpriv = dev->private;
-	int channel;
+	unsigned int mask;
+	unsigned int chan;
+	unsigned int val;
 
-	for (channel = 0; channel < 8; channel++)
-		if (((data[0] >> channel) & 0x01) != 0)
-			outb((((data[1] >> channel) & 0x01) << 3) | channel,
-			     dev->iobase + ADQ12B_OUTBR);
-
-	/* store information to retrieve when asked for reading */
-	if (data[0]) {
-		devpriv->digital_state &= ~data[0];
-		devpriv->digital_state |= (data[0] & data[1]);
+	mask = comedi_dio_update_state(s, data);
+	if (mask) {
+		for (chan = 0; chan < 8; chan++) {
+			if ((mask >> chan) & 0x01) {
+				val = (s->state >> chan) & 0x01;
+				outb((val << 3) | chan,
+				     dev->iobase + ADQ12B_OUTBR);
+			}
+		}
 	}
 
-	data[1] = devpriv->digital_state;
+	data[1] = s->state;
 
 	return insn->n;
 }
@@ -223,7 +224,6 @@
 
 	devpriv->unipolar = it->options[1];
 	devpriv->differential = it->options[2];
-	devpriv->digital_state = 0;
 	/*
 	 * initialize channel and range to -1 so we make sure we
 	 * always write at least once to the CTREG in the instruction
diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
index f84df46..c3fdcab 100644
--- a/drivers/staging/comedi/drivers/adv_pci1710.c
+++ b/drivers/staging/comedi/drivers/adv_pci1710.c
@@ -314,10 +314,9 @@
 	unsigned int *ai_chanlist;	/*  actaul chanlist */
 	unsigned int ai_flags;	/*  flaglist */
 	unsigned int ai_data_len;	/*  len of data buffer */
-	short *ai_data;		/*  data buffer */
 	unsigned int ai_timer1;	/*  timers */
 	unsigned int ai_timer2;
-	short ao_data[4];	/*  data output buffer */
+	unsigned short ao_data[4];	/*  data output buffer */
 	unsigned int cnt0_write_wait;	/* after a write, wait for update of the
 					 * internal state */
 };
@@ -544,18 +543,14 @@
 	return insn->n;
 }
 
-/*
-==============================================================================
-*/
 static int pci171x_insn_bits_do(struct comedi_device *dev,
 				struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data)
+				struct comedi_insn *insn,
+				unsigned int *data)
 {
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
+	if (comedi_dio_update_state(s, data))
 		outw(s->state, dev->iobase + PCI171x_DO);
-	}
+
 	data[1] = s->state;
 
 	return insn->n;
@@ -740,7 +735,7 @@
 	int m;
 #ifdef PCI171x_PARANOIDCHECK
 	const struct boardtype *this_board = comedi_board(dev);
-	short sampl;
+	unsigned short sampl;
 #endif
 
 	m = inw(dev->iobase + PCI171x_STATUS);
@@ -821,7 +816,7 @@
 	int i, j;
 #ifdef PCI171x_PARANOIDCHECK
 	const struct boardtype *this_board = comedi_board(dev);
-	int sampl;
+	unsigned short sampl;
 #endif
 
 	j = s->async->cur_chan;
@@ -1009,9 +1004,10 @@
 		} else {
 			devpriv->ai_et = 0;
 		}
-		i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
-					  &divisor2, &devpriv->ai_timer1,
-					  devpriv->ai_flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(devpriv->i8254_osc_base,
+					  &divisor1, &divisor2,
+					  &devpriv->ai_timer1,
+					  devpriv->ai_flags);
 		outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
 		if (mode != 2) {
 			/*  start pacer */
@@ -1090,9 +1086,9 @@
 
 	if (cmd->convert_src == TRIG_TIMER) {
 		tmp = cmd->convert_arg;
-		i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
-					  &divisor2, &cmd->convert_arg,
-					  cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(devpriv->i8254_osc_base,
+					  &divisor1, &divisor2,
+					  &cmd->convert_arg, cmd->flags);
 		if (cmd->convert_arg < this_board->ai_ns_min)
 			cmd->convert_arg = this_board->ai_ns_min;
 		if (tmp != cmd->convert_arg)
@@ -1125,7 +1121,6 @@
 	devpriv->ai_chanlist = cmd->chanlist;
 	devpriv->ai_flags = cmd->flags;
 	devpriv->ai_data_len = s->async->prealloc_bufsz;
-	devpriv->ai_data = s->async->prealloc_buf;
 	devpriv->ai_timer1 = 0;
 	devpriv->ai_timer2 = 0;
 
@@ -1288,7 +1283,7 @@
 			s->do_cmdtest = pci171x_ai_cmdtest;
 			s->do_cmd = pci171x_ai_cmd;
 		}
-		devpriv->i8254_osc_base = 100;	/*  100ns=10MHz */
+		devpriv->i8254_osc_base = I8254_OSC_BASE_10MHZ;
 		subdev++;
 	}
 
@@ -1320,7 +1315,6 @@
 		s->maxdata = 1;
 		s->len_chanlist = this_board->n_dichan;
 		s->range_table = &range_digital;
-		s->io_bits = 0;	/* all bits input */
 		s->insn_bits = pci171x_insn_bits_di;
 		subdev++;
 	}
@@ -1333,9 +1327,6 @@
 		s->maxdata = 1;
 		s->len_chanlist = this_board->n_dochan;
 		s->range_table = &range_digital;
-		/* all bits output */
-		s->io_bits = (1 << this_board->n_dochan) - 1;
-		s->state = 0;
 		s->insn_bits = pci171x_insn_bits_do;
 		subdev++;
 	}
diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c
index b793d69..bd4f781 100644
--- a/drivers/staging/comedi/drivers/adv_pci1723.c
+++ b/drivers/staging/comedi/drivers/adv_pci1723.c
@@ -105,7 +105,7 @@
 
 struct pci1723_private {
 	unsigned char da_range[8];	/* D/A output range for each channel */
-	short ao_data[8];	/* data output buffer */
+	unsigned short ao_data[8];	/* data output buffer */
 };
 
 /*
@@ -205,19 +205,16 @@
 	return insn->n;
 }
 
-/*
-  digital i/o bits read/write
-*/
 static int pci1723_dio_insn_bits(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data)
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
+	if (comedi_dio_update_state(s, data))
 		outw(s->state, dev->iobase + PCI1723_WRITE_DIGITAL_OUTPUT_CMD);
-	}
+
 	data[1] = inw(dev->iobase + PCI1723_READ_DIGITAL_INPUT_DATA);
+
 	return insn->n;
 }
 
diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c
index f091fa0..6bac665 100644
--- a/drivers/staging/comedi/drivers/adv_pci_dio.c
+++ b/drivers/staging/comedi/drivers/adv_pci_dio.c
@@ -448,45 +448,39 @@
 	return insn->n;
 }
 
-/*
-==============================================================================
-*/
 static int pci_dio_insn_bits_do_b(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data)
+				  struct comedi_insn *insn,
+				  unsigned int *data)
 {
 	const struct diosubd_data *d = (const struct diosubd_data *)s->private;
 	int i;
 
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
+	if (comedi_dio_update_state(s, data)) {
 		for (i = 0; i < d->regs; i++)
 			outb((s->state >> (8 * i)) & 0xff,
 			     dev->iobase + d->addr + i);
 	}
+
 	data[1] = s->state;
 
 	return insn->n;
 }
 
-/*
-==============================================================================
-*/
 static int pci_dio_insn_bits_do_w(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data)
+				  struct comedi_insn *insn,
+				  unsigned int *data)
 {
 	const struct diosubd_data *d = (const struct diosubd_data *)s->private;
 	int i;
 
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
+	if (comedi_dio_update_state(s, data)) {
 		for (i = 0; i < d->regs; i++)
 			outw((s->state >> (16 * i)) & 0xffff,
 			     dev->iobase + d->addr + 2 * i);
 	}
+
 	data[1] = s->state;
 
 	return insn->n;
@@ -641,12 +635,10 @@
 	return insn->n;
 }
 
-/*
-==============================================================================
-*/
 static int pci1760_insn_bits_do(struct comedi_device *dev,
 				struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data)
+				struct comedi_insn *insn,
+				unsigned int *data)
 {
 	int ret;
 	unsigned char omb[4] = {
@@ -657,14 +649,13 @@
 	};
 	unsigned char imb[4];
 
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
+	if (comedi_dio_update_state(s, data)) {
 		omb[0] = s->state;
 		ret = pci1760_mbxrequest(dev, omb, imb);
 		if (!ret)
 			return ret;
 	}
+
 	data[1] = s->state;
 
 	return insn->n;
diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
index afe87cc..22b3dda 100644
--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
+++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
@@ -45,9 +45,7 @@
 					   struct comedi_insn *insn,
 					   unsigned int *data)
 {
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= data[0] & data[1];
+	if (comedi_dio_update_state(s, data)) {
 		outb(s->state & 0xff, dev->iobase + AIO_IIRO_16_RELAY_0_7);
 		outb((s->state >> 8) & 0xff,
 		     dev->iobase + AIO_IIRO_16_RELAY_8_15);
diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c
index c1f723e..2e4bf28 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200_common.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c
@@ -941,31 +941,34 @@
 	dio200_write8(dev, subpriv->ofs + 3, config);
 }
 
-/*
- * Handle 'insn_bits' for an '8255' DIO subdevice.
- */
 static int dio200_subdev_8255_bits(struct comedi_device *dev,
 				   struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data)
+				   struct comedi_insn *insn,
+				   unsigned int *data)
 {
 	struct dio200_subdev_8255 *subpriv = s->private;
+	unsigned int mask;
+	unsigned int val;
 
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
-		if (data[0] & 0xff)
+	mask = comedi_dio_update_state(s, data);
+	if (mask) {
+		if (mask & 0xff)
 			dio200_write8(dev, subpriv->ofs, s->state & 0xff);
-		if (data[0] & 0xff00)
+		if (mask & 0xff00)
 			dio200_write8(dev, subpriv->ofs + 1,
 				      (s->state >> 8) & 0xff);
-		if (data[0] & 0xff0000)
+		if (mask & 0xff0000)
 			dio200_write8(dev, subpriv->ofs + 2,
 				      (s->state >> 16) & 0xff);
 	}
-	data[1] = dio200_read8(dev, subpriv->ofs);
-	data[1] |= dio200_read8(dev, subpriv->ofs + 1) << 8;
-	data[1] |= dio200_read8(dev, subpriv->ofs + 2) << 16;
-	return 2;
+
+	val = dio200_read8(dev, subpriv->ofs);
+	val |= dio200_read8(dev, subpriv->ofs + 1) << 8;
+	val |= dio200_read8(dev, subpriv->ofs + 2) << 16;
+
+	data[1] = val;
+
+	return insn->n;
 }
 
 /*
@@ -1022,8 +1025,6 @@
 	s->maxdata = 1;
 	s->insn_bits = dio200_subdev_8255_bits;
 	s->insn_config = dio200_subdev_8255_config;
-	s->state = 0;
-	s->io_bits = 0;
 	dio200_subdev_8255_set_dir(dev, s);
 	return 0;
 }
diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c
index e710804..5b4b5ab 100644
--- a/drivers/staging/comedi/drivers/amplc_pc263.c
+++ b/drivers/staging/comedi/drivers/amplc_pc263.c
@@ -57,17 +57,16 @@
 
 static int pc263_do_insn_bits(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data)
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
-	/* The insn data is a mask in data[0] and the new data
-	 * in data[1], each channel cooresponding to a bit. */
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= data[0] & data[1];
-		/* Write out the new digital output lines */
-		outb(s->state & 0xFF, dev->iobase);
-		outb(s->state >> 8, dev->iobase + 1);
+	if (comedi_dio_update_state(s, data)) {
+		outb(s->state & 0xff, dev->iobase);
+		outb((s->state >> 8) & 0xff, dev->iobase + 1);
 	}
+
+	data[1] = s->state;
+
 	return insn->n;
 }
 
diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
index 179de53..810e397 100644
--- a/drivers/staging/comedi/drivers/amplc_pci224.c
+++ b/drivers/staging/comedi/drivers/amplc_pci224.c
@@ -215,12 +215,6 @@
 #define CLK_EXT		7	/* external clock */
 /* Macro to construct clock input configuration register value. */
 #define CLK_CONFIG(chan, src)	((((chan) & 3) << 3) | ((src) & 7))
-/* Timebases in ns. */
-#define TIMEBASE_10MHZ		100
-#define TIMEBASE_1MHZ		1000
-#define TIMEBASE_100KHZ		10000
-#define TIMEBASE_10KHZ		100000
-#define TIMEBASE_1KHZ		1000000
 
 /*
  * Counter/timer gate input configuration sources.
@@ -379,7 +373,7 @@
 	unsigned long state;
 	spinlock_t ao_spinlock;
 	unsigned int *ao_readback;
-	short *ao_scan_vals;
+	unsigned short *ao_scan_vals;
 	unsigned char *ao_scan_order;
 	int intr_cpuid;
 	short intr_running;
@@ -843,26 +837,26 @@
 		switch (round_mode) {
 		case TRIG_ROUND_NEAREST:
 		default:
-			round = TIMEBASE_10MHZ / 2;
+			round = I8254_OSC_BASE_10MHZ / 2;
 			break;
 		case TRIG_ROUND_DOWN:
 			round = 0;
 			break;
 		case TRIG_ROUND_UP:
-			round = TIMEBASE_10MHZ - 1;
+			round = I8254_OSC_BASE_10MHZ - 1;
 			break;
 		}
 		/* Be careful to avoid overflow! */
-		div2 = cmd->scan_begin_arg / TIMEBASE_10MHZ;
-		div2 += (round + cmd->scan_begin_arg % TIMEBASE_10MHZ) /
-		    TIMEBASE_10MHZ;
+		div2 = cmd->scan_begin_arg / I8254_OSC_BASE_10MHZ;
+		div2 += (round + cmd->scan_begin_arg % I8254_OSC_BASE_10MHZ) /
+			I8254_OSC_BASE_10MHZ;
 		if (div2 <= 0x10000) {
 			/* A single timer will suffice. */
 			if (div2 < 2)
 				div2 = 2;
-			cmd->scan_begin_arg = div2 * TIMEBASE_10MHZ;
+			cmd->scan_begin_arg = div2 * I8254_OSC_BASE_10MHZ;
 			if (cmd->scan_begin_arg < div2 ||
-			    cmd->scan_begin_arg < TIMEBASE_10MHZ) {
+			    cmd->scan_begin_arg < I8254_OSC_BASE_10MHZ) {
 				/* Overflow! */
 				cmd->scan_begin_arg = MAX_SCAN_PERIOD;
 			}
@@ -870,7 +864,8 @@
 			/* Use two timers. */
 			div1 = devpriv->cached_div1;
 			div2 = devpriv->cached_div2;
-			pci224_cascade_ns_to_timer(TIMEBASE_10MHZ, &div1, &div2,
+			pci224_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+						   &div1, &div2,
 						   &cmd->scan_begin_arg,
 						   round_mode);
 			devpriv->cached_div1 = div1;
@@ -1002,19 +997,19 @@
 		switch (round_mode) {
 		case TRIG_ROUND_NEAREST:
 		default:
-			round = TIMEBASE_10MHZ / 2;
+			round = I8254_OSC_BASE_10MHZ / 2;
 			break;
 		case TRIG_ROUND_DOWN:
 			round = 0;
 			break;
 		case TRIG_ROUND_UP:
-			round = TIMEBASE_10MHZ - 1;
+			round = I8254_OSC_BASE_10MHZ - 1;
 			break;
 		}
 		/* Be careful to avoid overflow! */
-		div2 = cmd->scan_begin_arg / TIMEBASE_10MHZ;
-		div2 += (round + cmd->scan_begin_arg % TIMEBASE_10MHZ) /
-		    TIMEBASE_10MHZ;
+		div2 = cmd->scan_begin_arg / I8254_OSC_BASE_10MHZ;
+		div2 += (round + cmd->scan_begin_arg % I8254_OSC_BASE_10MHZ) /
+			I8254_OSC_BASE_10MHZ;
 		if (div2 <= 0x10000) {
 			/* A single timer will suffice. */
 			if (div2 < 2)
@@ -1025,7 +1020,8 @@
 			/* Use two timers. */
 			div1 = devpriv->cached_div1;
 			div2 = devpriv->cached_div2;
-			pci224_cascade_ns_to_timer(TIMEBASE_10MHZ, &div1, &div2,
+			pci224_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+						   &div1, &div2,
 						   &ns, round_mode);
 		}
 
@@ -1116,7 +1112,7 @@
 	const struct pci224_board *thisboard = comedi_board(dev);
 	struct pci224_private *devpriv = dev->private;
 	struct comedi_async *async = s->async;
-	short *array = data;
+	unsigned short *array = data;
 	unsigned int length = num_bytes / sizeof(*array);
 	unsigned int offset;
 	unsigned int shift;
diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
index 43059c2..a97bbd6 100644
--- a/drivers/staging/comedi/drivers/amplc_pci230.c
+++ b/drivers/staging/comedi/drivers/amplc_pci230.c
@@ -573,14 +573,14 @@
 /* PCI230 daccon bipolar flag for each analogue output range. */
 static const unsigned char pci230_ao_bipolar[2] = { 0, 1 };
 
-static short pci230_ai_read(struct comedi_device *dev)
+static unsigned short pci230_ai_read(struct comedi_device *dev)
 {
 	const struct pci230_board *thisboard = comedi_board(dev);
 	struct pci230_private *devpriv = dev->private;
-	short data;
+	unsigned short data;
 
 	/* Read sample. */
-	data = (short)inw(dev->iobase + PCI230_ADCDATA);
+	data = inw(dev->iobase + PCI230_ADCDATA);
 	/* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
 	 * four bits reserved for expansion). */
 	/* PCI230+ is 16 bit AI. */
@@ -595,7 +595,7 @@
 }
 
 static inline unsigned short pci230_ao_mangle_datum(struct comedi_device *dev,
-						    short datum)
+						    unsigned short datum)
 {
 	const struct pci230_board *thisboard = comedi_board(dev);
 	struct pci230_private *devpriv = dev->private;
@@ -609,11 +609,12 @@
 	 * four bits reserved for expansion). */
 	/* PCI230+ is also 12 bit AO. */
 	datum <<= (16 - thisboard->ao_bits);
-	return (unsigned short)datum;
+	return datum;
 }
 
 static inline void pci230_ao_write_nofifo(struct comedi_device *dev,
-					  short datum, unsigned int chan)
+					  unsigned short datum,
+					  unsigned int chan)
 {
 	struct pci230_private *devpriv = dev->private;
 
@@ -627,8 +628,8 @@
 								PCI230_DACOUT2));
 }
 
-static inline void pci230_ao_write_fifo(struct comedi_device *dev, short datum,
-					unsigned int chan)
+static inline void pci230_ao_write_fifo(struct comedi_device *dev,
+					unsigned short datum, unsigned int chan)
 {
 	struct pci230_private *devpriv = dev->private;
 
@@ -1165,7 +1166,7 @@
 				    struct comedi_subdevice *s)
 {
 	struct pci230_private *devpriv = dev->private;
-	short data;
+	unsigned short data;
 	int i, ret;
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
@@ -1258,7 +1259,7 @@
 		/* Process scans. */
 		for (n = 0; n < num_scans; n++) {
 			for (i = 0; i < cmd->chanlist_len; i++) {
-				short datum;
+				unsigned short datum;
 
 				comedi_buf_get(async, &datum);
 				pci230_ao_write_fifo(dev, datum,
diff --git a/drivers/staging/comedi/drivers/amplc_pci263.c b/drivers/staging/comedi/drivers/amplc_pci263.c
index 145bb48..4bd4ef8 100644
--- a/drivers/staging/comedi/drivers/amplc_pci263.c
+++ b/drivers/staging/comedi/drivers/amplc_pci263.c
@@ -44,17 +44,16 @@
 
 static int pci263_do_insn_bits(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
-	/* The insn data is a mask in data[0] and the new data
-	 * in data[1], each channel cooresponding to a bit. */
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= data[0] & data[1];
-		/* Write out the new digital output lines */
-		outb(s->state & 0xFF, dev->iobase);
-		outb(s->state >> 8, dev->iobase + 1);
+	if (comedi_dio_update_state(s, data)) {
+		outb(s->state & 0xff, dev->iobase);
+		outb((s->state >> 8) & 0xff, dev->iobase + 1);
 	}
+
+	data[1] = s->state;
+
 	return insn->n;
 }
 
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index 0ce93da..64d5f29 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -234,9 +234,9 @@
 		unsigned int div1 = 0, div2 = 0;
 
 		tmp = cmd->scan_begin_arg;
-		i8253_cascade_ns_to_timer(100, &div1, &div2,
-					  &cmd->scan_begin_arg,
-					  cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+					  &div1, &div2,
+					  &cmd->scan_begin_arg, cmd->flags);
 		if (tmp != cmd->scan_begin_arg)
 			err++;
 	}
@@ -244,9 +244,9 @@
 		unsigned int div1 = 0, div2 = 0;
 
 		tmp = cmd->convert_arg;
-		i8253_cascade_ns_to_timer(100, &div1, &div2,
-					  &cmd->scan_begin_arg,
-					  cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+					  &div1, &div2,
+					  &cmd->scan_begin_arg, cmd->flags);
 		if (tmp != cmd->convert_arg)
 			err++;
 		if (cmd->scan_begin_src == TRIG_TIMER &&
@@ -325,14 +325,11 @@
 
 static int das16cs_dio_insn_bits(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data)
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= data[0] & data[1];
-
+	if (comedi_dio_update_state(s, data))
 		outw(s->state, dev->iobase + DAS16CS_DIO);
-	}
 
 	data[1] = inw(dev->iobase + DAS16CS_DIO);
 
diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
index 41d89ee..e72a403 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas.c
@@ -73,7 +73,6 @@
 #include "amcc_s5933.h"
 #include "comedi_fc.h"
 
-#define TIMER_BASE		100	/* 10MHz master clock */
 #define AI_BUFFER_SIZE		1024	/* max ai fifo size */
 #define AO_BUFFER_SIZE		1024	/* max ao fifo size */
 #define NUM_CHANNELS_8800	8
@@ -358,15 +357,15 @@
 	unsigned int s5933_intcsr_bits;
 	unsigned int ao_control_bits;
 	/* fifo buffers */
-	short ai_buffer[AI_BUFFER_SIZE];
-	short ao_buffer[AO_BUFFER_SIZE];
+	unsigned short ai_buffer[AI_BUFFER_SIZE];
+	unsigned short ao_buffer[AO_BUFFER_SIZE];
 	/* divisors of master clock for analog output pacing */
 	unsigned int ao_divisor1;
 	unsigned int ao_divisor2;
 	/* number of analog output samples remaining */
 	unsigned int ao_count;
 	/* cached values for readback */
-	int ao_value[2];
+	unsigned short ao_value[2];
 	unsigned int caldac_value[NUM_CHANNELS_8800];
 	unsigned int trimpot_value[NUM_CHANNELS_8402];
 	unsigned int dac08_value;
@@ -880,21 +879,19 @@
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		tmp = cmd->scan_begin_arg;
-		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
-					       &(devpriv->divisor1),
-					       &(devpriv->divisor2),
-					       &(cmd->scan_begin_arg),
-					       cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+					  &devpriv->divisor1,
+					  &devpriv->divisor2,
+					  &cmd->scan_begin_arg, cmd->flags);
 		if (tmp != cmd->scan_begin_arg)
 			err++;
 	}
 	if (cmd->convert_src == TRIG_TIMER) {
 		tmp = cmd->convert_arg;
-		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
-					       &(devpriv->divisor1),
-					       &(devpriv->divisor2),
-					       &(cmd->convert_arg),
-					       cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+					  &devpriv->divisor1,
+					  &devpriv->divisor2,
+					  &cmd->convert_arg, cmd->flags);
 		if (tmp != cmd->convert_arg)
 			err++;
 	}
@@ -932,9 +929,9 @@
 {
 	struct cb_pcidas_private *devpriv = dev->private;
 
-	i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
-				       &(devpriv->divisor2), ns,
-				       rounding_flags & TRIG_ROUND_MASK);
+	i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+				  &devpriv->divisor1, &devpriv->divisor2,
+				  ns, rounding_flags);
 
 	/* Write the values of ctr1 and ctr2 into counters 1 and 2 */
 	i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 1,
@@ -1084,11 +1081,10 @@
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		tmp = cmd->scan_begin_arg;
-		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
-					       &(devpriv->ao_divisor1),
-					       &(devpriv->ao_divisor2),
-					       &(cmd->scan_begin_arg),
-					       cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+					  &devpriv->ao_divisor1,
+					  &devpriv->ao_divisor2,
+					  &cmd->scan_begin_arg, cmd->flags);
 		if (tmp != cmd->scan_begin_arg)
 			err++;
 	}
@@ -1209,11 +1205,10 @@
 
 	/*  load counters */
 	if (cmd->scan_begin_src == TRIG_TIMER) {
-		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
-					       &(devpriv->ao_divisor1),
-					       &(devpriv->ao_divisor2),
-					       &(cmd->scan_begin_arg),
-					       cmd->flags);
+		i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+					  &devpriv->ao_divisor1,
+					  &devpriv->ao_divisor2,
+					  &cmd->scan_begin_arg, cmd->flags);
 
 		/* Write the values of ctr1 and ctr2 into counters 1 and 2 */
 		i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 1,
diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c
index 388dbd7..ff52065 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas64.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas64.c
@@ -1137,7 +1137,7 @@
 	volatile short ai_cmd_running;
 	unsigned int ai_fifo_segment_length;
 	struct ext_clock_info ext_clock;
-	short ao_bounce_buffer[DAC_FIFO_SIZE];
+	unsigned short ao_bounce_buffer[DAC_FIFO_SIZE];
 };
 
 static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev,
@@ -3490,18 +3490,15 @@
 	return insn->n;
 }
 
-static int do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
-		    struct comedi_insn *insn, unsigned int *data)
+static int do_wbits(struct comedi_device *dev,
+		    struct comedi_subdevice *s,
+		    struct comedi_insn *insn,
+		    unsigned int *data)
 {
 	struct pcidas64_private *devpriv = dev->private;
 
-	data[0] &= 0xf;
-	/*  zero bits we are going to change */
-	s->state &= ~data[0];
-	/*  set new bits */
-	s->state |= data[0] & data[1];
-
-	writeb(s->state, devpriv->dio_counter_iobase + DO_REG);
+	if (comedi_dio_update_state(s, data))
+		writeb(s->state, devpriv->dio_counter_iobase + DO_REG);
 
 	data[1] = s->state;
 
@@ -3526,14 +3523,14 @@
 	return insn->n;
 }
 
-static int dio_60xx_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data)
+static int dio_60xx_wbits(struct comedi_device *dev,
+			  struct comedi_subdevice *s,
+			  struct comedi_insn *insn,
+			  unsigned int *data)
 {
 	struct pcidas64_private *devpriv = dev->private;
 
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
+	if (comedi_dio_update_state(s, data)) {
 		writeb(s->state,
 		       devpriv->dio_counter_iobase + DIO_DATA_60XX_REG);
 	}
diff --git a/drivers/staging/comedi/drivers/comedi_fc.h b/drivers/staging/comedi/drivers/comedi_fc.h
index a4dea7c..8558b07 100644
--- a/drivers/staging/comedi/drivers/comedi_fc.h
+++ b/drivers/staging/comedi/drivers/comedi_fc.h
@@ -30,7 +30,7 @@
 					      unsigned int num_bytes);
 
 static inline unsigned int cfc_write_to_buffer(struct comedi_subdevice *subd,
-					       short data)
+					       unsigned short data)
 {
 	return cfc_write_array_to_buffer(subd, &data, sizeof(data));
 };
diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c
index f28a15f..9de81c7 100644
--- a/drivers/staging/comedi/drivers/comedi_parport.c
+++ b/drivers/staging/comedi/drivers/comedi_parport.c
@@ -1,168 +1,153 @@
 /*
-    comedi/drivers/comedi_parport.c
-    hardware driver for standard parallel port
+ * comedi_parport.c
+ * Comedi driver for standard parallel port
+ *
+ * For more information see:
+ *	http://retired.beyondlogic.org/spp/parallel.htm
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1998,2001 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
 
-    COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 1998,2001 David A. Schleef <ds@schleef.org>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-*/
 /*
-Driver: comedi_parport
-Description: Standard PC parallel port
-Author: ds
-Status: works in immediate mode
-Devices: [standard] parallel port (comedi_parport)
-Updated: Tue, 30 Apr 2002 21:11:45 -0700
-
-A cheap and easy way to get a few more digital I/O lines.  Steal
-additional parallel ports from old computers or your neighbors'
-computers.
-
-Option list:
- 0: I/O port base for the parallel port.
- 1: IRQ
-
-Parallel Port Lines:
-
-pin     subdev  chan    aka
----     ------  ----    ---
-1       2       0       strobe
-2       0       0       data 0
-3       0       1       data 1
-4       0       2       data 2
-5       0       3       data 3
-6       0       4       data 4
-7       0       5       data 5
-8       0       6       data 6
-9       0       7       data 7
-10      1       3       acknowledge
-11      1       4       busy
-12      1       2       output
-13      1       1       printer selected
-14      2       1       auto LF
-15      1       0       error
-16      2       2       init
-17      2       3       select printer
-18-25   ground
-
-Notes:
-
-Subdevices 0 is digital I/O, subdevice 1 is digital input, and
-subdevice 2 is digital output.  Unlike other Comedi devices,
-subdevice 0 defaults to output.
-
-Pins 13 and 14 are inverted once by Comedi and once by the
-hardware, thus cancelling the effect.
-
-Pin 1 is a strobe, thus acts like one.  There's no way in software
-to change this, at least on a standard parallel port.
-
-Subdevice 3 pretends to be a digital input subdevice, but it always
-returns 0 when read.  However, if you run a command with
-scan_begin_src=TRIG_EXT, it uses pin 10 as a external triggering
-pin, which can be used to wake up tasks.
-*/
-/*
-   see http://www.beyondlogic.org/ for information.
-   or http://www.linux-magazin.de/ausgabe/1999/10/IO/io.html
+ * Driver: comedi_parport
+ * Description: Standard PC parallel port
+ * Author: ds
+ * Status: works in immediate mode
+ * Devices: (standard) parallel port [comedi_parport]
+ * Updated: Tue, 30 Apr 2002 21:11:45 -0700
+ *
+ * A cheap and easy way to get a few more digital I/O lines. Steal
+ * additional parallel ports from old computers or your neighbors'
+ * computers.
+ *
+ * Option list:
+ *   0: I/O port base for the parallel port.
+ *   1: IRQ (optional)
+ *
+ * Parallel Port Lines:
+ *
+ *	 pin   subdev  chan  type  name
+ *	-----  ------  ----  ----  --------------
+ *	  1      2       0    DO   strobe
+ *	  2      0       0    DIO  data 0
+ *	  3      0       1    DIO  data 1
+ *	  4      0       2    DIO  data 2
+ *	  5      0       3    DIO  data 3
+ *	  6      0       4    DIO  data 4
+ *	  7      0       5    DIO  data 5
+ *	  8      0       6    DIO  data 6
+ *	  9      0       7    DIO  data 7
+ *	 10      1       3    DI   ack
+ *	 11      1       4    DI   busy
+ *	 12      1       2    DI   paper out
+ *	 13      1       1    DI   select in
+ *	 14      2       1    DO   auto LF
+ *	 15      1       0    DI   error
+ *	 16      2       2    DO   init
+ *	 17      2       3    DO   select printer
+ *	18-25                      ground
+ *
+ * When an IRQ is configured subdevice 3 pretends to be a digital
+ * input subdevice, but it always returns 0 when read. However, if
+ * you run a command with scan_begin_src=TRIG_EXT, it uses pin 10
+ * as a external trigger, which can be used to wake up tasks.
  */
 
 #include <linux/module.h>
-#include "../comedidev.h"
 #include <linux/interrupt.h>
 
+#include "../comedidev.h"
+
 #include "comedi_fc.h"
 
-#define PARPORT_SIZE 3
+/*
+ * Register map
+ */
+#define PARPORT_DATA_REG	0x00
+#define PARPORT_STATUS_REG	0x01
+#define PARPORT_CTRL_REG	0x02
+#define PARPORT_CTRL_IRQ_ENA	(1 << 4)
+#define PARPORT_CTRL_BIDIR_ENA	(1 << 5)
 
-#define PARPORT_A 0
-#define PARPORT_B 1
-#define PARPORT_C 2
-
-struct parport_private {
-	unsigned int a_data;
-	unsigned int c_data;
-	int enable_irq;
-};
-
-static int parport_insn_a(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data)
+static int parport_data_reg_insn_bits(struct comedi_device *dev,
+				      struct comedi_subdevice *s,
+				      struct comedi_insn *insn,
+				      unsigned int *data)
 {
-	struct parport_private *devpriv = dev->private;
+	if (comedi_dio_update_state(s, data))
+		outb(s->state, dev->iobase + PARPORT_DATA_REG);
 
-	if (data[0]) {
-		devpriv->a_data &= ~data[0];
-		devpriv->a_data |= (data[0] & data[1]);
-
-		outb(devpriv->a_data, dev->iobase + PARPORT_A);
-	}
-
-	data[1] = inb(dev->iobase + PARPORT_A);
+	data[1] = inb(dev->iobase + PARPORT_DATA_REG);
 
 	return insn->n;
 }
 
-static int parport_insn_config_a(struct comedi_device *dev,
-				 struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data)
+static int parport_data_reg_insn_config(struct comedi_device *dev,
+					struct comedi_subdevice *s,
+					struct comedi_insn *insn,
+					unsigned int *data)
 {
-	struct parport_private *devpriv = dev->private;
+	unsigned int ctrl;
+	int ret;
 
-	if (data[0]) {
-		s->io_bits = 0xff;
-		devpriv->c_data &= ~(1 << 5);
-	} else {
-		s->io_bits = 0;
-		devpriv->c_data |= (1 << 5);
-	}
-	outb(devpriv->c_data, dev->iobase + PARPORT_C);
+	ret = comedi_dio_insn_config(dev, s, insn, data, 0xff);
+	if (ret)
+		return ret;
 
-	return 1;
-}
-
-static int parport_insn_b(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data)
-{
-	if (data[0]) {
-		/* should writes be ignored? */
-		/* anyone??? */
-	}
-
-	data[1] = (inb(dev->iobase + PARPORT_B) >> 3);
+	ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
+	if (s->io_bits)
+		ctrl &= ~PARPORT_CTRL_BIDIR_ENA;
+	else
+		ctrl |= PARPORT_CTRL_BIDIR_ENA;
+	outb(ctrl, dev->iobase + PARPORT_CTRL_REG);
 
 	return insn->n;
 }
 
-static int parport_insn_c(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data)
+static int parport_status_reg_insn_bits(struct comedi_device *dev,
+					struct comedi_subdevice *s,
+					struct comedi_insn *insn,
+					unsigned int *data)
 {
-	struct parport_private *devpriv = dev->private;
-
-	data[0] &= 0x0f;
-	if (data[0]) {
-		devpriv->c_data &= ~data[0];
-		devpriv->c_data |= (data[0] & data[1]);
-
-		outb(devpriv->c_data, dev->iobase + PARPORT_C);
-	}
-
-	data[1] = devpriv->c_data & 0xf;
+	data[1] = inb(dev->iobase + PARPORT_STATUS_REG) >> 3;
 
 	return insn->n;
 }
 
-static int parport_intr_insn(struct comedi_device *dev,
-			     struct comedi_subdevice *s,
-			     struct comedi_insn *insn, unsigned int *data)
+static int parport_ctrl_reg_insn_bits(struct comedi_device *dev,
+				      struct comedi_subdevice *s,
+				      struct comedi_insn *insn,
+				      unsigned int *data)
+{
+	unsigned int ctrl;
+
+	if (comedi_dio_update_state(s, data)) {
+		ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
+		ctrl &= (PARPORT_CTRL_IRQ_ENA | PARPORT_CTRL_BIDIR_ENA);
+		ctrl |= s->state;
+		outb(ctrl, dev->iobase + PARPORT_CTRL_REG);
+	}
+
+	data[1] = s->state;
+
+	return insn->n;
+}
+
+static int parport_intr_insn_bits(struct comedi_device *dev,
+				  struct comedi_subdevice *s,
+				  struct comedi_insn *insn,
+				  unsigned int *data)
 {
 	data[1] = 0;
 	return insn->n;
@@ -213,12 +198,11 @@
 static int parport_intr_cmd(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
-	struct parport_private *devpriv = dev->private;
+	unsigned int ctrl;
 
-	devpriv->c_data |= 0x10;
-	outb(devpriv->c_data, dev->iobase + PARPORT_C);
-
-	devpriv->enable_irq = 1;
+	ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
+	ctrl |= PARPORT_CTRL_IRQ_ENA;
+	outb(ctrl, dev->iobase + PARPORT_CTRL_REG);
 
 	return 0;
 }
@@ -226,12 +210,11 @@
 static int parport_intr_cancel(struct comedi_device *dev,
 			       struct comedi_subdevice *s)
 {
-	struct parport_private *devpriv = dev->private;
+	unsigned int ctrl;
 
-	devpriv->c_data &= ~0x10;
-	outb(devpriv->c_data, dev->iobase + PARPORT_C);
-
-	devpriv->enable_irq = 0;
+	ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
+	ctrl &= ~PARPORT_CTRL_IRQ_ENA;
+	outb(ctrl, dev->iobase + PARPORT_CTRL_REG);
 
 	return 0;
 }
@@ -239,10 +222,11 @@
 static irqreturn_t parport_interrupt(int irq, void *d)
 {
 	struct comedi_device *dev = d;
-	struct parport_private *devpriv = dev->private;
-	struct comedi_subdevice *s = &dev->subdevices[3];
+	struct comedi_subdevice *s = dev->read_subdev;
+	unsigned int ctrl;
 
-	if (!devpriv->enable_irq)
+	ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
+	if (!(ctrl & PARPORT_CTRL_IRQ_ENA))
 		return IRQ_NONE;
 
 	comedi_buf_put(s->async, 0);
@@ -255,79 +239,69 @@
 static int parport_attach(struct comedi_device *dev,
 			  struct comedi_devconfig *it)
 {
-	struct parport_private *devpriv;
 	struct comedi_subdevice *s;
-	unsigned int irq;
 	int ret;
 
-	ret = comedi_request_region(dev, it->options[0], PARPORT_SIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x03);
 	if (ret)
 		return ret;
 
-	irq = it->options[1];
-	if (irq) {
-		ret = request_irq(irq, parport_interrupt, 0, dev->board_name,
-				  dev);
-		if (ret < 0) {
-			dev_err(dev->class_dev, "irq not available\n");
-			return -EINVAL;
-		}
-		dev->irq = irq;
+	if (it->options[1]) {
+		ret = request_irq(it->options[1], parport_interrupt, 0,
+				  dev->board_name, dev);
+		if (ret == 0)
+			dev->irq = it->options[1];
 	}
 
-	ret = comedi_alloc_subdevices(dev, 4);
+	ret = comedi_alloc_subdevices(dev, dev->irq ? 4 : 3);
 	if (ret)
 		return ret;
 
-	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
-	if (!devpriv)
-		return -ENOMEM;
-
+	/* Digial I/O subdevice - Parallel port DATA register */
 	s = &dev->subdevices[0];
-	s->type = COMEDI_SUBD_DIO;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-	s->n_chan = 8;
-	s->maxdata = 1;
-	s->range_table = &range_digital;
-	s->insn_bits = parport_insn_a;
-	s->insn_config = parport_insn_config_a;
+	s->type		= COMEDI_SUBD_DIO;
+	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
+	s->n_chan	= 8;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= parport_data_reg_insn_bits;
+	s->insn_config	= parport_data_reg_insn_config;
 
+	/* Digial Input subdevice - Parallel port STATUS register */
 	s = &dev->subdevices[1];
-	s->type = COMEDI_SUBD_DI;
-	s->subdev_flags = SDF_READABLE;
-	s->n_chan = 5;
-	s->maxdata = 1;
-	s->range_table = &range_digital;
-	s->insn_bits = parport_insn_b;
+	s->type		= COMEDI_SUBD_DI;
+	s->subdev_flags	= SDF_READABLE;
+	s->n_chan	= 5;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= parport_status_reg_insn_bits;
 
+	/* Digial Output subdevice - Parallel port CONTROL register */
 	s = &dev->subdevices[2];
-	s->type = COMEDI_SUBD_DO;
-	s->subdev_flags = SDF_WRITABLE;
-	s->n_chan = 4;
-	s->maxdata = 1;
-	s->range_table = &range_digital;
-	s->insn_bits = parport_insn_c;
+	s->type		= COMEDI_SUBD_DO;
+	s->subdev_flags	= SDF_WRITABLE;
+	s->n_chan	= 4;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= parport_ctrl_reg_insn_bits;
 
-	s = &dev->subdevices[3];
-	if (irq) {
+	if (dev->irq) {
+		/* Digial Input subdevice - Interrupt support */
+		s = &dev->subdevices[3];
 		dev->read_subdev = s;
-		s->type = COMEDI_SUBD_DI;
-		s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
-		s->n_chan = 1;
-		s->maxdata = 1;
-		s->range_table = &range_digital;
-		s->insn_bits = parport_intr_insn;
-		s->do_cmdtest = parport_intr_cmdtest;
-		s->do_cmd = parport_intr_cmd;
-		s->cancel = parport_intr_cancel;
-	} else {
-		s->type = COMEDI_SUBD_UNUSED;
+		s->type		= COMEDI_SUBD_DI;
+		s->subdev_flags	= SDF_READABLE | SDF_CMD_READ;
+		s->n_chan	= 1;
+		s->maxdata	= 1;
+		s->range_table	= &range_digital;
+		s->insn_bits	= parport_intr_insn_bits;
+		s->do_cmdtest	= parport_intr_cmdtest;
+		s->do_cmd	= parport_intr_cmd;
+		s->cancel	= parport_intr_cancel;
 	}
 
-	devpriv->a_data = 0;
-	outb(devpriv->a_data, dev->iobase + PARPORT_A);
-	devpriv->c_data = 0;
-	outb(devpriv->c_data, dev->iobase + PARPORT_C);
+	outb(0, dev->iobase + PARPORT_DATA_REG);
+	outb(0, dev->iobase + PARPORT_CTRL_REG);
 
 	return 0;
 }
@@ -341,5 +315,5 @@
 module_comedi_driver(parport_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi: Standard parallel port driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
index e781716..89836c0 100644
--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
+++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
@@ -40,17 +40,11 @@
 
 static int contec_do_insn_bits(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
-
-	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
-
+	if (comedi_dio_update_state(s, data))
 		outw(s->state, dev->iobase + PIO1616L_DO_REG);
-	}
 
 	data[1] = s->state;
 
diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c
index 5f66970..15dd33e 100644
--- a/drivers/staging/comedi/drivers/das08.c
+++ b/drivers/staging/comedi/drivers/das08.c
@@ -279,27 +279,23 @@
 	return insn->n;
 }
 
-static int das08_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data)
+static int das08_do_wbits(struct comedi_device *dev,
+			  struct comedi_subdevice *s,
+			  struct comedi_insn *insn,
+			  unsigned int *data)
 {
 	struct das08_private_struct *devpriv = dev->private;
-	int wbits;
 
-	/*  get current settings of digital output lines */
-	wbits = (devpriv->do_mux_bits >> 4) & 0xf;
-	/*  null bits we are going to set */
-	wbits &= ~data[0];
-	/*  set new bit values */
-	wbits |= data[0] & data[1];
-	/*  remember digital output bits */
-	/*  prevent race with setting of analog input mux */
-	spin_lock(&dev->spinlock);
-	devpriv->do_mux_bits &= ~DAS08_DO_MASK;
-	devpriv->do_mux_bits |= DAS08_OP(wbits);
-	outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL);
-	spin_unlock(&dev->spinlock);
+	if (comedi_dio_update_state(s, data)) {
+		/* prevent race with setting of analog input mux */
+		spin_lock(&dev->spinlock);
+		devpriv->do_mux_bits &= ~DAS08_DO_MASK;
+		devpriv->do_mux_bits |= DAS08_OP(s->state);
+		outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL);
+		spin_unlock(&dev->spinlock);
+	}
 
-	data[1] = wbits;
+	data[1] = s->state;
 
 	return insn->n;
 }
@@ -316,17 +312,13 @@
 
 static int das08jr_do_wbits(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data)
+			    struct comedi_insn *insn,
+			    unsigned int *data)
 {
-	struct das08_private_struct *devpriv = dev->private;
+	if (comedi_dio_update_state(s, data))
+		outb(s->state, dev->iobase + DAS08JR_DIO);
 
-	/*  null bits we are going to set */
-	devpriv->do_bits &= ~data[0];
-	/*  set new bit values */
-	devpriv->do_bits |= data[0] & data[1];
-	outb(devpriv->do_bits, dev->iobase + DAS08JR_DIO);
-
-	data[1] = devpriv->do_bits;
+	data[1] = s->state;
 
 	return insn->n;
 }
diff --git a/drivers/staging/comedi/drivers/das08.h b/drivers/staging/comedi/drivers/das08.h
index cce1b58..46a314c 100644
--- a/drivers/staging/comedi/drivers/das08.h
+++ b/drivers/staging/comedi/drivers/das08.h
@@ -41,7 +41,6 @@
 
 struct das08_private_struct {
 	unsigned int do_mux_bits;	/*  bits for do/mux register on boards without separate do register */
-	unsigned int do_bits;	/*  bits for do register on boards with register dedicated to digital out only */
 	const unsigned int *pg_gainlist;
 	unsigned int ao_readback[2];	/* assume 2 AO channels */
 };
diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
index 1b0793f..a8446ca 100644
--- a/drivers/staging/comedi/drivers/das16.c
+++ b/drivers/staging/comedi/drivers/das16.c
@@ -675,21 +675,19 @@
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		unsigned int tmp = cmd->scan_begin_arg;
 		/*  set divisors, correct timing arguments */
-		i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
-					       &devpriv->divisor1,
-					       &devpriv->divisor2,
-					       &cmd->scan_begin_arg,
-					       cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(devpriv->clockbase,
+					  &devpriv->divisor1,
+					  &devpriv->divisor2,
+					  &cmd->scan_begin_arg, cmd->flags);
 		err += (tmp != cmd->scan_begin_arg);
 	}
 	if (cmd->convert_src == TRIG_TIMER) {
 		unsigned int tmp = cmd->convert_arg;
 		/*  set divisors, correct timing arguments */
-		i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
-					       &devpriv->divisor1,
-					       &devpriv->divisor2,
-					       &cmd->convert_arg,
-					       cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(devpriv->clockbase,
+					  &devpriv->divisor1,
+					  &devpriv->divisor2,
+					  &cmd->convert_arg, cmd->flags);
 		err += (tmp != cmd->convert_arg);
 	}
 	if (err)
@@ -725,11 +723,9 @@
 	struct das16_private_struct *devpriv = dev->private;
 	unsigned long timer_base = dev->iobase + DAS16_TIMER_BASE_REG;
 
-	i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
-				       &devpriv->divisor1,
-				       &devpriv->divisor2,
-				       &ns,
-				       rounding_flags & TRIG_ROUND_MASK);
+	i8253_cascade_ns_to_timer(devpriv->clockbase,
+				  &devpriv->divisor1, &devpriv->divisor2,
+				  &ns, rounding_flags);
 
 	/* Write the values of ctr1 and ctr2 into counters 1 and 2 */
 	i8254_load(timer_base, 0, 1, devpriv->divisor1, 2);
@@ -850,7 +846,7 @@
 			   unsigned int start_chan_index)
 {
 	unsigned int i, num_samples = num_bytes / sizeof(short);
-	short *data = array;
+	unsigned short *data = array;
 
 	for (i = 0; i < num_samples; i++) {
 		data[i] = le16_to_cpu(data[i]);
@@ -952,15 +948,8 @@
 			      struct comedi_insn *insn,
 			      unsigned int *data)
 {
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
-
-	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
-
+	if (comedi_dio_update_state(s, data))
 		outb(s->state, dev->iobase + DAS16_DIO_REG);
-	}
 
 	data[1] = s->state;
 
@@ -1043,14 +1032,15 @@
 		status = inb(dev->iobase + DAS1600_STATUS_REG);
 
 		if (status & DAS1600_STATUS_CLK_10MHZ)
-			devpriv->clockbase = 100;
+			devpriv->clockbase = I8254_OSC_BASE_10MHZ;
 		else
-			devpriv->clockbase = 1000;
+			devpriv->clockbase = I8254_OSC_BASE_1MHZ;
 	} else {
 		if (it->options[3])
-			devpriv->clockbase = 1000 / it->options[3];
+			devpriv->clockbase = I8254_OSC_BASE_1MHZ /
+					     it->options[3];
 		else
-			devpriv->clockbase = 1000;	/*  1 MHz default */
+			devpriv->clockbase = I8254_OSC_BASE_1MHZ;
 	}
 
 	/* initialize dma */
diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
index b943c44..fce9acf 100644
--- a/drivers/staging/comedi/drivers/das16m1.c
+++ b/drivers/staging/comedi/drivers/das16m1.c
@@ -63,8 +63,6 @@
 #define DAS16M1_SIZE 16
 #define DAS16M1_SIZE2 8
 
-#define DAS16M1_XTAL 100	/* 10 MHz master clock */
-
 #define FIFO_SIZE 1024		/*  1024 sample fifo */
 
 /*
@@ -133,19 +131,18 @@
 	 * needed to keep track of whether new count has been loaded into
 	 * counter yet (loaded by first sample conversion) */
 	u16 initial_hw_count;
-	short ai_buffer[FIFO_SIZE];
-	unsigned int do_bits;	/*  saves status of digital output bits */
+	unsigned short ai_buffer[FIFO_SIZE];
 	unsigned int divisor1;	/*  divides master clock to obtain conversion speed */
 	unsigned int divisor2;	/*  divides master clock to obtain conversion speed */
 	unsigned long extra_iobase;
 };
 
-static inline short munge_sample(short data)
+static inline unsigned short munge_sample(unsigned short data)
 {
 	return (data >> 4) & 0xfff;
 }
 
-static void munge_sample_array(short *array, unsigned int num_elements)
+static void munge_sample_array(unsigned short *array, unsigned int num_elements)
 {
 	unsigned int i;
 
@@ -208,11 +205,10 @@
 	if (cmd->convert_src == TRIG_TIMER) {
 		tmp = cmd->convert_arg;
 		/* calculate counter values that give desired timing */
-		i8253_cascade_ns_to_timer_2div(DAS16M1_XTAL,
-					       &(devpriv->divisor1),
-					       &(devpriv->divisor2),
-					       &(cmd->convert_arg),
-					       cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(I8254_OSC_BASE_10MHZ,
+					  &devpriv->divisor1,
+					  &devpriv->divisor2,
+					  &cmd->convert_arg, cmd->flags);
 		if (tmp != cmd->convert_arg)
 			err++;
 	}
@@ -251,9 +247,10 @@
 {
 	struct das16m1_private_struct *devpriv = dev->private;
 
-	i8253_cascade_ns_to_timer_2div(DAS16M1_XTAL, &(devpriv->divisor1),
-				       &(devpriv->divisor2), &ns,
-				       rounding_flags & TRIG_ROUND_MASK);
+	i8253_cascade_ns_to_timer_2div(I8254_OSC_BASE_10MHZ,
+				       &devpriv->divisor1,
+				       &devpriv->divisor2,
+				       &ns, rounding_flags);
 
 	/* Write the values of ctr1 and ctr2 into counters 1 and 2 */
 	i8254_load(dev->iobase + DAS16M1_8254_SECOND, 0, 1, devpriv->divisor1,
@@ -393,22 +390,13 @@
 
 static int das16m1_do_wbits(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data)
+			    struct comedi_insn *insn,
+			    unsigned int *data)
 {
-	struct das16m1_private_struct *devpriv = dev->private;
-	unsigned int wbits;
+	if (comedi_dio_update_state(s, data))
+		outb(s->state, dev->iobase + DAS16M1_DIO);
 
-	/*  only set bits that have been masked */
-	data[0] &= 0xf;
-	wbits = devpriv->do_bits;
-	/*  zero bits that have been masked */
-	wbits &= ~data[0];
-	/*  set masked bits */
-	wbits |= data[0] & data[1];
-	devpriv->do_bits = wbits;
-	data[1] = wbits;
-
-	outb(devpriv->do_bits, dev->iobase + DAS16M1_DIO);
+	data[1] = s->state;
 
 	return insn->n;
 }
@@ -649,7 +637,7 @@
 	outb(TOTAL_CLEAR, dev->iobase + DAS16M1_8254_FIRST_CNTRL);
 
 	/*  initialize digital output lines */
-	outb(devpriv->do_bits, dev->iobase + DAS16M1_DIO);
+	outb(0, dev->iobase + DAS16M1_DIO);
 
 	/* set the interrupt level */
 	if (dev->irq)
diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
index 5b30029..1880038 100644
--- a/drivers/staging/comedi/drivers/das1800.c
+++ b/drivers/staging/comedi/drivers/das1800.c
@@ -108,7 +108,6 @@
 /* misc. defines */
 #define DAS1800_SIZE           16	/* uses 16 io addresses */
 #define FIFO_SIZE              1024	/*  1024 sample fifo */
-#define TIMER_BASE             200	/*  5 Mhz master clock */
 #define UNIPOLAR               0x4	/*  bit that determines whether input range is uni/bipolar */
 #define DMA_BUF_SIZE           0x1ff00	/*  size in bytes of dma buffers */
 
@@ -427,7 +426,6 @@
 	volatile unsigned int count;	/* number of data points left to be taken */
 	unsigned int divisor1;	/* value to load into board's counter 1 for timed conversions */
 	unsigned int divisor2;	/* value to load into board's counter 2 for timed conversions */
-	int do_bits;		/* digital output bits */
 	int irq_dma_bits;	/* bits for control register b */
 	/* dma bits for control register b, stored so that dma can be
 	 * turned on and off */
@@ -440,7 +438,8 @@
 	uint16_t *dma_current_buf;	/* pointer to dma buffer currently being used */
 	unsigned int dma_transfer_size;	/* size of transfer currently used, in bytes */
 	unsigned long iobase2;	/* secondary io address used for analog out on 'ao' boards */
-	short ao_update_bits;	/* remembers the last write to the 'update' dac */
+	unsigned short ao_update_bits;	/* remembers the last write to the
+					 * 'update' dac */
 };
 
 /* analog out range for 'ao' boards */
@@ -503,7 +502,7 @@
 					  struct comedi_subdevice *s)
 {
 	struct das1800_private *devpriv = dev->private;
-	short dpnt;
+	unsigned short dpnt;
 	int unipolar;
 	struct comedi_cmd *cmd = &s->async->cmd;
 
@@ -840,12 +839,11 @@
 		if (cmd->scan_begin_src == TRIG_FOLLOW) {
 			tmp_arg = cmd->convert_arg;
 			/* calculate counter values that give desired timing */
-			i8253_cascade_ns_to_timer_2div(TIMER_BASE,
-						       &(devpriv->divisor1),
-						       &(devpriv->divisor2),
-						       &(cmd->convert_arg),
-						       cmd->
-						       flags & TRIG_ROUND_MASK);
+			i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
+						  &devpriv->divisor1,
+						  &devpriv->divisor2,
+						  &cmd->convert_arg,
+						  cmd->flags);
 			if (tmp_arg != cmd->convert_arg)
 				err++;
 		}
@@ -870,16 +868,11 @@
 				}
 				tmp_arg = cmd->scan_begin_arg;
 				/* calculate counter values that give desired timing */
-				i8253_cascade_ns_to_timer_2div(TIMER_BASE,
-							       &(devpriv->
-								 divisor1),
-							       &(devpriv->
-								 divisor2),
-							       &(cmd->
-								 scan_begin_arg),
-							       cmd->
-							       flags &
-							       TRIG_ROUND_MASK);
+				i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
+							  &devpriv->divisor1,
+							  &devpriv->divisor2,
+							  &cmd->scan_begin_arg,
+							  cmd->flags);
 				if (tmp_arg != cmd->scan_begin_arg)
 					err++;
 			}
@@ -1011,12 +1004,10 @@
 		if (cmd->convert_src == TRIG_TIMER) {
 			/* set conversion frequency */
 			period = cmd->convert_arg;
-			i8253_cascade_ns_to_timer_2div(TIMER_BASE,
-						       &devpriv->divisor1,
-						       &devpriv->divisor2,
-						       &period,
-						       cmd->flags &
-							TRIG_ROUND_MASK);
+			i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
+						  &devpriv->divisor1,
+						  &devpriv->divisor2,
+						  &period, cmd->flags);
 			if (das1800_set_frequency(dev) < 0)
 				return -1;
 		}
@@ -1024,9 +1015,10 @@
 	case TRIG_TIMER:	/*  in burst mode */
 		/* set scan frequency */
 		period = cmd->scan_begin_arg;
-		i8253_cascade_ns_to_timer_2div(TIMER_BASE, &devpriv->divisor1,
-					       &devpriv->divisor2, &period,
-					       cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
+					  &devpriv->divisor1,
+					  &devpriv->divisor2,
+					  &period, cmd->flags);
 		if (das1800_set_frequency(dev) < 0)
 			return -1;
 		break;
@@ -1220,7 +1212,7 @@
 	int i, n;
 	int chan, range, aref, chan_range;
 	int timeout = 1000;
-	short dpnt;
+	unsigned short dpnt;
 	int conv_flags = 0;
 	unsigned long irq_flags;
 
@@ -1285,7 +1277,7 @@
 	int chan = CR_CHAN(insn->chanspec);
 /* int range = CR_RANGE(insn->chanspec); */
 	int update_chan = thisboard->ao_n_chan - 1;
-	short output;
+	unsigned short output;
 	unsigned long irq_flags;
 
 	/*   card expects two's complement data */
@@ -1319,24 +1311,15 @@
 	return insn->n;
 }
 
-/* writes to digital output channels */
 static int das1800_do_wbits(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data)
+			    struct comedi_insn *insn,
+			    unsigned int *data)
 {
-	struct das1800_private *devpriv = dev->private;
-	unsigned int wbits;
+	if (comedi_dio_update_state(s, data))
+		outb(s->state, dev->iobase + DAS1800_DIGITAL);
 
-	/*  only set bits that have been masked */
-	data[0] &= (1 << s->n_chan) - 1;
-	wbits = devpriv->do_bits;
-	wbits &= ~data[0];
-	wbits |= data[0] & data[1];
-	devpriv->do_bits = wbits;
-
-	outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);
-
-	data[1] = devpriv->do_bits;
+	data[1] = s->state;
 
 	return insn->n;
 }
@@ -1644,7 +1627,7 @@
 	das1800_cancel(dev, dev->read_subdev);
 
 	/*  initialize digital out channels */
-	outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);
+	outb(0, dev->iobase + DAS1800_DIGITAL);
 
 	/*  initialize analog out channels */
 	if (thisboard->ao_ability == 1) {
diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
index 11e1611..5af0a57 100644
--- a/drivers/staging/comedi/drivers/das800.c
+++ b/drivers/staging/comedi/drivers/das800.c
@@ -66,7 +66,6 @@
 #include "comedi_fc.h"
 
 #define DAS800_SIZE           8
-#define TIMER_BASE            1000
 #define N_CHAN_AI             8	/*  number of analog input channels */
 
 /* Registers for the das800 */
@@ -356,11 +355,10 @@
 		int tmp = cmd->convert_arg;
 
 		/* calculate counter values that give desired timing */
-		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
-					       &devpriv->divisor1,
-					       &devpriv->divisor2,
-					       &cmd->convert_arg,
-					       cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(I8254_OSC_BASE_1MHZ,
+					  &devpriv->divisor1,
+					  &devpriv->divisor2,
+					  &cmd->convert_arg, cmd->flags);
 		if (tmp != cmd->convert_arg)
 			err++;
 	}
@@ -630,13 +628,9 @@
 			       unsigned int *data)
 {
 	struct das800_private *devpriv = dev->private;
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
 	unsigned long irq_flags;
 
-	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
+	if (comedi_dio_update_state(s, data)) {
 		devpriv->do_bits = s->state << 4;
 
 		spin_lock_irqsave(&dev->spinlock, irq_flags);
diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
index 118a4fd..b04a5633 100644
--- a/drivers/staging/comedi/drivers/dmm32at.c
+++ b/drivers/staging/comedi/drivers/dmm32at.c
@@ -596,52 +596,40 @@
 
 static int dmm32at_dio_insn_bits(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data)
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
 	struct dmm32at_private *devpriv = dev->private;
-	unsigned char diobits;
+	unsigned int mask;
+	unsigned int val;
 
-	/* The insn data is a mask in data[0] and the new data
-	 * in data[1], each channel cooresponding to a bit. */
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= data[0] & data[1];
-		/* Write out the new digital output lines */
-		/* outw(s->state,dev->iobase + DMM32AT_DIO); */
+	mask = comedi_dio_update_state(s, data);
+	if (mask) {
+		/* get access to the DIO regs */
+		outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL);
+
+		/* if either part of dio is set for output */
+		if (((devpriv->dio_config & DMM32AT_DIRCL) == 0) ||
+		    ((devpriv->dio_config & DMM32AT_DIRCH) == 0)) {
+			val = (s->state & 0x00ff0000) >> 16;
+			outb(val, dev->iobase + DMM32AT_DIOC);
+		}
+		if ((devpriv->dio_config & DMM32AT_DIRB) == 0) {
+			val = (s->state & 0x0000ff00) >> 8;
+			outb(val, dev->iobase + DMM32AT_DIOB);
+		}
+		if ((devpriv->dio_config & DMM32AT_DIRA) == 0) {
+			val = (s->state & 0x000000ff);
+			outb(val, dev->iobase + DMM32AT_DIOA);
+		}
 	}
 
-	/* get access to the DIO regs */
-	outb(DMM32AT_DIOACC, dev->iobase + DMM32AT_CNTRL);
+	val = inb(dev->iobase + DMM32AT_DIOA);
+	val |= inb(dev->iobase + DMM32AT_DIOB) << 8;
+	val |= inb(dev->iobase + DMM32AT_DIOC) << 16;
+	s->state = val;
 
-	/* if either part of dio is set for output */
-	if (((devpriv->dio_config & DMM32AT_DIRCL) == 0) ||
-	    ((devpriv->dio_config & DMM32AT_DIRCH) == 0)) {
-		diobits = (s->state & 0x00ff0000) >> 16;
-		outb(diobits, dev->iobase + DMM32AT_DIOC);
-	}
-	if ((devpriv->dio_config & DMM32AT_DIRB) == 0) {
-		diobits = (s->state & 0x0000ff00) >> 8;
-		outb(diobits, dev->iobase + DMM32AT_DIOB);
-	}
-	if ((devpriv->dio_config & DMM32AT_DIRA) == 0) {
-		diobits = (s->state & 0x000000ff);
-		outb(diobits, dev->iobase + DMM32AT_DIOA);
-	}
-
-	/* now read the state back in */
-	s->state = inb(dev->iobase + DMM32AT_DIOC);
-	s->state <<= 8;
-	s->state |= inb(dev->iobase + DMM32AT_DIOB);
-	s->state <<= 8;
-	s->state |= inb(dev->iobase + DMM32AT_DIOA);
-	data[1] = s->state;
-
-	/* on return, data[1] contains the value of the digital
-	 * input and output lines. */
-	/* data[1]=inw(dev->iobase + DMM32AT_DIO); */
-	/* or we could just return the software copy of the output values if
-	 * it was a purely digital output subdevice */
-	/* data[1]=s->state; */
+	data[1] = val;
 
 	return insn->n;
 }
diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
index 38918a1..811c8c5 100644
--- a/drivers/staging/comedi/drivers/dt2801.c
+++ b/drivers/staging/comedi/drivers/dt2801.c
@@ -260,7 +260,8 @@
 
 static int dt2801_readdata2(struct comedi_device *dev, int *data)
 {
-	int lb, hb;
+	int lb = 0;
+	int hb = 0;
 	int ret;
 
 	ret = dt2801_readdata(dev, &lb);
@@ -528,23 +529,23 @@
 
 static int dt2801_dio_insn_bits(struct comedi_device *dev,
 				struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data)
+				struct comedi_insn *insn,
+				unsigned int *data)
 {
-	int which = 0;
+	int which = (s == &dev->subdevices[3]) ? 1 : 0;
+	unsigned int val = 0;
 
-	if (s == &dev->subdevices[3])
-		which = 1;
-
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
+	if (comedi_dio_update_state(s, data)) {
 		dt2801_writecmd(dev, DT_C_WRITE_DIG);
 		dt2801_writedata(dev, which);
 		dt2801_writedata(dev, s->state);
 	}
+
 	dt2801_writecmd(dev, DT_C_READ_DIG);
 	dt2801_writedata(dev, which);
-	dt2801_readdata(dev, data + 1);
+	dt2801_readdata(dev, &val);
+
+	data[1] = val;
 
 	return insn->n;
 }
diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c
index a41a571..0ca02fa 100644
--- a/drivers/staging/comedi/drivers/dt2811.c
+++ b/drivers/staging/comedi/drivers/dt2811.c
@@ -353,11 +353,11 @@
 
 static int dt2811_do_insn_bits(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
-	s->state &= ~data[0];
-	s->state |= data[0] & data[1];
-	outb(s->state, dev->iobase + DT2811_DIO);
+	if (comedi_dio_update_state(s, data))
+		outb(s->state, dev->iobase + DT2811_DIO);
 
 	data[1] = s->state;
 
diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c
index f4a8529..bf58993 100644
--- a/drivers/staging/comedi/drivers/dt2817.c
+++ b/drivers/staging/comedi/drivers/dt2817.c
@@ -80,36 +80,31 @@
 
 static int dt2817_dio_insn_bits(struct comedi_device *dev,
 				struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data)
+				struct comedi_insn *insn,
+				unsigned int *data)
 {
-	unsigned int changed;
+	unsigned long iobase = dev->iobase + DT2817_DATA;
+	unsigned int mask;
+	unsigned int val;
 
-	/* It's questionable whether it is more important in
-	 * a driver like this to be deterministic or fast.
-	 * We choose fast. */
-
-	if (data[0]) {
-		changed = s->state;
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
-		changed ^= s->state;
-		changed &= s->io_bits;
-		if (changed & 0x000000ff)
-			outb(s->state & 0xff, dev->iobase + DT2817_DATA + 0);
-		if (changed & 0x0000ff00)
-			outb((s->state >> 8) & 0xff,
-			     dev->iobase + DT2817_DATA + 1);
-		if (changed & 0x00ff0000)
-			outb((s->state >> 16) & 0xff,
-			     dev->iobase + DT2817_DATA + 2);
-		if (changed & 0xff000000)
-			outb((s->state >> 24) & 0xff,
-			     dev->iobase + DT2817_DATA + 3);
+	mask = comedi_dio_update_state(s, data);
+	if (mask) {
+		if (mask & 0x000000ff)
+			outb(s->state & 0xff, iobase + 0);
+		if (mask & 0x0000ff00)
+			outb((s->state >> 8) & 0xff, iobase + 1);
+		if (mask & 0x00ff0000)
+			outb((s->state >> 16) & 0xff, iobase + 2);
+		if (mask & 0xff000000)
+			outb((s->state >> 24) & 0xff, iobase + 3);
 	}
-	data[1] = inb(dev->iobase + DT2817_DATA + 0);
-	data[1] |= (inb(dev->iobase + DT2817_DATA + 1) << 8);
-	data[1] |= (inb(dev->iobase + DT2817_DATA + 2) << 16);
-	data[1] |= (inb(dev->iobase + DT2817_DATA + 3) << 24);
+
+	val = inb(iobase + 0);
+	val |= (inb(iobase + 1) << 8);
+	val |= (inb(iobase + 2) << 16);
+	val |= (inb(iobase + 3) << 24);
+
+	data[1] = val;
 
 	return insn->n;
 }
diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c
index da3ee85..a01e6b5 100644
--- a/drivers/staging/comedi/drivers/dt282x.c
+++ b/drivers/staging/comedi/drivers/dt282x.c
@@ -226,7 +226,7 @@
 
 	const struct comedi_lrange *darangelist[2];
 
-	short ao[2];
+	unsigned short ao[2];
 
 	volatile int dacsr;	/* software copies of registers */
 	volatile int adcsr;
@@ -237,7 +237,7 @@
 
 	struct {
 		int chan;
-		short *buf;	/* DMA buffer */
+		unsigned short *buf;	/* DMA buffer */
 		volatile int size;	/* size of current transfer */
 	} dma[2];
 	int dma_maxsize;	/* max size of DMA transfer (in bytes) */
@@ -283,7 +283,7 @@
 
 static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2);
 
-static void dt282x_munge(struct comedi_device *dev, short *buf,
+static void dt282x_munge(struct comedi_device *dev, unsigned short *buf,
 			 unsigned int nbytes)
 {
 	const struct dt282x_board *board = comedi_board(dev);
@@ -496,9 +496,9 @@
 #if 0
 	if (adcsr & DT2821_ADDONE) {
 		int ret;
-		short data;
+		unsigned short data;
 
-		data = (short)inw(dev->iobase + DT2821_ADDAT);
+		data = inw(dev->iobase + DT2821_ADDAT);
 		data &= (1 << board->adbits) - 1;
 
 		if (devpriv->ad_2scomp)
@@ -796,7 +796,7 @@
 {
 	const struct dt282x_board *board = comedi_board(dev);
 	struct dt282x_private *devpriv = dev->private;
-	short d;
+	unsigned short d;
 	unsigned int chan;
 
 	chan = CR_CHAN(insn->chanspec);
@@ -967,14 +967,12 @@
 
 static int dt282x_dio_insn_bits(struct comedi_device *dev,
 				struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data)
+				struct comedi_insn *insn,
+				unsigned int *data)
 {
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
-
+	if (comedi_dio_update_state(s, data))
 		outw(s->state, dev->iobase + DT2821_DIODAT);
-	}
+
 	data[1] = inw(dev->iobase + DT2821_DIODAT);
 
 	return insn->n;
diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c
index 64ef875..292226e 100644
--- a/drivers/staging/comedi/drivers/dt3000.c
+++ b/drivers/staging/comedi/drivers/dt3000.c
@@ -331,7 +331,7 @@
 	int rear;
 	int count;
 	int i;
-	short data;
+	unsigned short data;
 
 	front = readw(devpriv->io_addr + DPR_AD_Buf_Front);
 	count = front - devpriv->ai_front;
@@ -665,13 +665,12 @@
 
 static int dt3k_dio_insn_bits(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data)
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= data[1] & data[0];
+	if (comedi_dio_update_state(s, data))
 		dt3k_writesingle(dev, SUBS_DOUT, 0, s->state);
-	}
+
 	data[1] = dt3k_readsingle(dev, SUBS_DIN, 0, 0);
 
 	return insn->n;
diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
index b5e6f33..73af600 100644
--- a/drivers/staging/comedi/drivers/dt9812.c
+++ b/drivers/staging/comedi/drivers/dt9812.c
@@ -85,13 +85,9 @@
 #define F020_MASK_DACxCN_DACxEN		0x80
 
 enum {
-	/* A/D  D/A  DI  DO  CT */
-	DT9812_DEVID_DT9812_10,	/*  8    2   8   8   1  +/- 10V */
-	DT9812_DEVID_DT9812_2PT5,	/* 8    2   8   8   1  0-2.44V */
-#if 0
-	DT9812_DEVID_DT9813,	/*  16   2   4   4   1  +/- 10V */
-	DT9812_DEVID_DT9814	/*  24   2   0   0   1  +/- 10V */
-#endif
+					/* A/D  D/A  DI  DO  CT */
+	DT9812_DEVID_DT9812_10,		/*  8    2   8   8   1  +/- 10V */
+	DT9812_DEVID_DT9812_2PT5,	/*  8    2   8   8   1  0-2.44V */
 };
 
 enum dt9812_gain {
@@ -580,15 +576,8 @@
 			       struct comedi_insn *insn,
 			       unsigned int *data)
 {
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
-
-	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
-
+	if (comedi_dio_update_state(s, data))
 		dt9812_digital_out(dev, s->state);
-	}
 
 	data[1] = s->state;
 
diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c
index fd525f4..f2a9f1c 100644
--- a/drivers/staging/comedi/drivers/dyna_pci10xx.c
+++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c
@@ -147,33 +147,23 @@
 	return insn->n;
 }
 
-/* digital output bit interface */
 static int dyna_pci10xx_do_insn_bits(struct comedi_device *dev,
-			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data)
+				     struct comedi_subdevice *s,
+				     struct comedi_insn *insn,
+				     unsigned int *data)
 {
 	struct dyna_pci10xx_private *devpriv = dev->private;
 
-	/* The insn data is a mask in data[0] and the new data
-	 * in data[1], each channel cooresponding to a bit.
-	 * s->state contains the previous write data
-	 */
 	mutex_lock(&devpriv->mutex);
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
+	if (comedi_dio_update_state(s, data)) {
 		smp_mb();
 		outw_p(s->state, devpriv->BADR3);
 		udelay(10);
 	}
 
-	/*
-	 * On return, data[1] contains the value of the digital
-	 * input and output lines. We just return the software copy of the
-	 * output values if it was a purely digital output subdevice.
-	 */
 	data[1] = s->state;
 	mutex_unlock(&devpriv->mutex);
+
 	return insn->n;
 }
 
diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
index 8d70f64..e3ff4c4 100644
--- a/drivers/staging/comedi/drivers/fl512.c
+++ b/drivers/staging/comedi/drivers/fl512.c
@@ -25,8 +25,7 @@
 
 #define FL512_SIZE 16		/* the size of the used memory */
 struct fl512_private {
-
-	short ao_readback[2];
+	unsigned short ao_readback[2];
 };
 
 static const struct comedi_lrange range_fl512 = { 4, {
diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
index 3889d23..1e16641 100644
--- a/drivers/staging/comedi/drivers/icp_multi.c
+++ b/drivers/staging/comedi/drivers/icp_multi.c
@@ -118,9 +118,7 @@
 	unsigned char act_chanlist_len;	/*  len of scanlist */
 	unsigned char act_chanlist_pos;	/*  actual position in MUX list */
 	unsigned int *ai_chanlist;	/*  actaul chanlist */
-	short *ai_data;		/*  data buffer */
-	short ao_data[4];	/*  data output buffer */
-	short di_data;		/*  Digital input data */
+	unsigned short ao_data[4];	/*  data output buffer */
 	unsigned int do_data;	/*  Remember digital output data */
 };
 
@@ -348,18 +346,13 @@
 
 static int icp_multi_insn_bits_do(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data)
+				  struct comedi_insn *insn,
+				  unsigned int *data)
 {
 	struct icp_multi_private *devpriv = dev->private;
 
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
-
-		printk(KERN_DEBUG "Digital outputs = %4x \n", s->state);
-
+	if (comedi_dio_update_state(s, data))
 		writew(s->state, devpriv->io_addr + ICP_MULTI_DO);
-	}
 
 	data[1] = readw(devpriv->io_addr + ICP_MULTI_DI);
 
@@ -548,7 +541,6 @@
 	s->maxdata = 1;
 	s->len_chanlist = 16;
 	s->range_table = &range_digital;
-	s->io_bits = 0;
 	s->insn_bits = icp_multi_insn_bits_di;
 
 	s = &dev->subdevices[3];
@@ -558,8 +550,6 @@
 	s->maxdata = 1;
 	s->len_chanlist = 8;
 	s->range_table = &range_digital;
-	s->io_bits = 0xff;
-	s->state = 0;
 	s->insn_bits = icp_multi_insn_bits_do;
 
 	s = &dev->subdevices[4];
diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
index 5c3a318..8577778 100644
--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
+++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
@@ -378,13 +378,10 @@
 			       unsigned int *data)
 {
 	struct ii20k_private *devpriv = dev->private;
-	unsigned int mask = data[0] & s->io_bits;	/* outputs only */
-	unsigned int bits = data[1];
+	unsigned int mask;
 
+	mask = comedi_dio_update_state(s, data);
 	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
-
 		if (mask & 0x000000ff)
 			writeb((s->state >> 0) & 0xff,
 			       devpriv->ioaddr + II20K_DIO0_REG);
diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
index 8f4afad..3d12e91 100644
--- a/drivers/staging/comedi/drivers/me4000.c
+++ b/drivers/staging/comedi/drivers/me4000.c
@@ -427,7 +427,7 @@
 static void me4000_reset(struct comedi_device *dev)
 {
 	struct me4000_info *info = dev->private;
-	unsigned long val;
+	unsigned int val;
 	int chan;
 
 	/* Make a hardware reset */
@@ -480,9 +480,9 @@
 	int rang = CR_RANGE(insn->chanspec);
 	int aref = CR_AREF(insn->chanspec);
 
-	unsigned long entry = 0;
-	unsigned long tmp;
-	long lval;
+	unsigned int entry = 0;
+	unsigned int tmp;
+	unsigned int lval;
 
 	if (insn->n == 0) {
 		return 0;
@@ -586,7 +586,7 @@
 static int me4000_ai_cancel(struct comedi_device *dev,
 			    struct comedi_subdevice *s)
 {
-	unsigned long tmp;
+	unsigned int tmp;
 
 	/* Stop any running conversion */
 	tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
@@ -783,7 +783,7 @@
 		      unsigned int scan_ticks, unsigned int chan_ticks)
 {
 
-	unsigned long tmp = 0;
+	unsigned int tmp = 0;
 
 	/* Write timer arguments */
 	ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks);
@@ -1108,7 +1108,7 @@
 	struct comedi_subdevice *s = &dev->subdevices[0];
 	int i;
 	int c = 0;
-	long lval;
+	unsigned int lval;
 
 	if (!dev->attached)
 		return IRQ_NONE;
@@ -1252,7 +1252,7 @@
 	int chan = CR_CHAN(insn->chanspec);
 	int rang = CR_RANGE(insn->chanspec);
 	int aref = CR_AREF(insn->chanspec);
-	unsigned long tmp;
+	unsigned int tmp;
 
 	if (insn->n == 0) {
 		return 0;
@@ -1313,29 +1313,12 @@
 	return 1;
 }
 
-/*=============================================================================
-  Digital I/O section
-  ===========================================================================*/
-
 static int me4000_dio_insn_bits(struct comedi_device *dev,
 				struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data)
+				struct comedi_insn *insn,
+				unsigned int *data)
 {
-	/*
-	 * The insn data consists of a mask in data[0] and the new data
-	 * in data[1]. The mask defines which bits we are concerning about.
-	 * The new data must be anded with the mask.
-	 * Each channel corresponds to a bit.
-	 */
-	if (data[0]) {
-		/* Check if requested ports are configured for output */
-		if ((s->io_bits & data[0]) != data[0])
-			return -EIO;
-
-		s->state &= ~data[0];
-		s->state |= data[0] & data[1];
-
-		/* Write out the new digital output lines */
+	if (comedi_dio_update_state(s, data)) {
 		outl((s->state >> 0) & 0xFF,
 			    dev->iobase + ME4000_DIO_PORT_0_REG);
 		outl((s->state >> 8) & 0xFF,
@@ -1346,8 +1329,6 @@
 			    dev->iobase + ME4000_DIO_PORT_3_REG);
 	}
 
-	/* On return, data[1] contains the value of
-	   the digital input and output lines. */
 	data[1] = ((inl(dev->iobase + ME4000_DIO_PORT_0_REG) & 0xFF) << 0) |
 		  ((inl(dev->iobase + ME4000_DIO_PORT_1_REG) & 0xFF) << 8) |
 		  ((inl(dev->iobase + ME4000_DIO_PORT_2_REG) & 0xFF) << 16) |
diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
index a6f6d4a..24ec9ef 100644
--- a/drivers/staging/comedi/drivers/me_daq.c
+++ b/drivers/staging/comedi/drivers/me_daq.c
@@ -222,15 +222,11 @@
 	struct me_private_data *dev_private = dev->private;
 	void __iomem *mmio_porta = dev_private->me_regbase + ME_DIO_PORT_A;
 	void __iomem *mmio_portb = dev_private->me_regbase + ME_DIO_PORT_B;
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
+	unsigned int mask;
 	unsigned int val;
 
-	mask &= s->io_bits;	/* only update the COMEDI_OUTPUT channels */
+	mask = comedi_dio_update_state(s, data);
 	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
-
 		if (mask & 0x0000ffff)
 			writew((s->state & 0xffff), mmio_porta);
 		if (mask & 0xffff0000)
@@ -545,7 +541,6 @@
 	s->range_table	= &range_digital;
 	s->insn_bits	= me_dio_insn_bits;
 	s->insn_config	= me_dio_insn_config;
-	s->io_bits	= 0;
 
 	dev_info(dev->class_dev, "%s: %s attached\n",
 		dev->driver->driver_name, dev->board_name);
diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c
index 9d75ea4..3ca755e 100644
--- a/drivers/staging/comedi/drivers/multiq3.c
+++ b/drivers/staging/comedi/drivers/multiq3.c
@@ -163,11 +163,11 @@
 
 static int multiq3_do_insn_bits(struct comedi_device *dev,
 				struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data)
+				struct comedi_insn *insn,
+				unsigned int *data)
 {
-	s->state &= ~data[0];
-	s->state |= (data[0] & data[1]);
-	outw(s->state, dev->iobase + MULTIQ3_DIGOUT_PORT);
+	if (comedi_dio_update_state(s, data))
+		outw(s->state, dev->iobase + MULTIQ3_DIGOUT_PORT);
 
 	data[1] = s->state;
 
diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c
index c2745f2..85aa960 100644
--- a/drivers/staging/comedi/drivers/ni_6527.c
+++ b/drivers/staging/comedi/drivers/ni_6527.c
@@ -1,40 +1,32 @@
 /*
-    comedi/drivers/ni_6527.c
-    driver for National Instruments PCI-6527
-
-    COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 1999,2002,2003 David A. Schleef <ds@schleef.org>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-*/
-/*
-Driver: ni_6527
-Description: National Instruments 6527
-Author: ds
-Status: works
-Devices: [National Instruments] PCI-6527 (ni6527), PXI-6527
-Updated: Sat, 25 Jan 2003 13:24:40 -0800
-
-
-*/
-
-/*
-   Manuals (available from ftp://ftp.natinst.com/support/manuals)
-
-	370106b.pdf	6527 Register Level Programmer Manual
-
+ * ni_6527.c
+ * Comedi driver for National Instruments PCI-6527
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1999,2002,2003 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
-#define DEBUG 1
-#define DEBUG_FLAGS
+/*
+ * Driver: ni_6527
+ * Description: National Instruments 6527
+ * Devices: (National Instruments) PCI-6527 [pci-6527]
+ *          (National Instruments) PXI-6527 [pxi-6527]
+ * Author: David A. Schleef <ds@schleef.org>
+ * Updated: Sat, 25 Jan 2003 13:24:40 -0800
+ * Status: works
+ *
+ * Configuration Options: not applicable, uses PCI auto config
+ */
 
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -43,39 +35,41 @@
 #include "../comedidev.h"
 
 #include "comedi_fc.h"
-#include "mite.h"
 
-#define DRIVER_NAME "ni_6527"
-
-#define NI6527_DIO_SIZE 4096
-#define NI6527_MITE_SIZE 4096
-
-#define Port_Register(x)			(0x00+(x))
-#define ID_Register				0x06
-
-#define Clear_Register				0x07
-#define ClrEdge				0x08
-#define ClrOverflow			0x04
-#define ClrFilter			0x02
-#define ClrInterval			0x01
-
-#define Filter_Interval(x)			(0x08+(x))
-#define Filter_Enable(x)			(0x0c+(x))
-
-#define Change_Status				0x14
-#define MasterInterruptStatus		0x04
-#define Overflow			0x02
-#define EdgeStatus			0x01
-
-#define Master_Interrupt_Control		0x15
-#define FallingEdgeIntEnable		0x10
-#define RisingEdgeIntEnable		0x08
-#define MasterInterruptEnable		0x04
-#define OverflowIntEnable		0x02
-#define EdgeIntEnable			0x01
-
-#define Rising_Edge_Detection_Enable(x)		(0x018+(x))
-#define Falling_Edge_Detection_Enable(x)	(0x020+(x))
+/*
+ * PCI BAR1 - Register memory map
+ *
+ * Manuals (available from ftp://ftp.natinst.com/support/manuals)
+ *	370106b.pdf	6527 Register Level Programmer Manual
+ */
+#define NI6527_DI_REG(x)		(0x00 + (x))
+#define NI6527_DO_REG(x)		(0x03 + (x))
+#define NI6527_ID_REG			0x06
+#define NI6527_CLR_REG			0x07
+#define NI6527_CLR_EDGE			(1 << 3)
+#define NI6527_CLR_OVERFLOW		(1 << 2)
+#define NI6527_CLR_FILT			(1 << 1)
+#define NI6527_CLR_INTERVAL		(1 << 0)
+#define NI6527_CLR_IRQS			(NI6527_CLR_EDGE | NI6527_CLR_OVERFLOW)
+#define NI6527_CLR_RESET_FILT		(NI6527_CLR_FILT | NI6527_CLR_INTERVAL)
+#define NI6527_FILT_INTERVAL_REG(x)	(0x08 + (x))
+#define NI6527_FILT_ENA_REG(x)		(0x0c + (x))
+#define NI6527_STATUS_REG		0x14
+#define NI6527_STATUS_IRQ		(1 << 2)
+#define NI6527_STATUS_OVERFLOW		(1 << 1)
+#define NI6527_STATUS_EDGE		(1 << 0)
+#define NI6527_CTRL_REG			0x15
+#define NI6527_CTRL_FALLING		(1 << 4)
+#define NI6527_CTRL_RISING		(1 << 3)
+#define NI6527_CTRL_IRQ			(1 << 2)
+#define NI6527_CTRL_OVERFLOW		(1 << 1)
+#define NI6527_CTRL_EDGE		(1 << 0)
+#define NI6527_CTRL_DISABLE_IRQS	0
+#define NI6527_CTRL_ENABLE_IRQS		(NI6527_CTRL_FALLING | \
+					 NI6527_CTRL_RISING | \
+					 NI6527_CTRL_IRQ | NI6527_CTRL_EDGE)
+#define NI6527_RISING_EDGE_REG(x)	(0x18 + (x))
+#define NI6527_FALLING_EDGE_REG(x)	(0x20 + (x))
 
 enum ni6527_boardid {
 	BOARD_PCI6527,
@@ -96,96 +90,113 @@
 };
 
 struct ni6527_private {
-	struct mite_struct *mite;
+	void __iomem *mmio_base;
 	unsigned int filter_interval;
 	unsigned int filter_enable;
 };
 
-static int ni6527_di_insn_config(struct comedi_device *dev,
-				 struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data)
+static void ni6527_set_filter_interval(struct comedi_device *dev,
+				       unsigned int val)
 {
 	struct ni6527_private *devpriv = dev->private;
-	int chan = CR_CHAN(insn->chanspec);
+	void __iomem *mmio = devpriv->mmio_base;
+
+	if (val != devpriv->filter_interval) {
+		writeb(val & 0xff, mmio + NI6527_FILT_INTERVAL_REG(0));
+		writeb((val >> 8) & 0xff, mmio + NI6527_FILT_INTERVAL_REG(1));
+		writeb((val >> 16) & 0x0f, mmio + NI6527_FILT_INTERVAL_REG(2));
+
+		writeb(NI6527_CLR_INTERVAL, mmio + NI6527_CLR_REG);
+
+		devpriv->filter_interval = val;
+	}
+}
+
+static void ni6527_set_filter_enable(struct comedi_device *dev,
+				     unsigned int val)
+{
+	struct ni6527_private *devpriv = dev->private;
+	void __iomem *mmio = devpriv->mmio_base;
+
+	writeb(val & 0xff, mmio + NI6527_FILT_ENA_REG(0));
+	writeb((val >> 8) & 0xff, mmio + NI6527_FILT_ENA_REG(1));
+	writeb((val >> 16) & 0xff, mmio + NI6527_FILT_ENA_REG(2));
+}
+
+static int ni6527_di_insn_config(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
+{
+	struct ni6527_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
 	unsigned int interval;
 
-	if (insn->n != 2)
-		return -EINVAL;
-
-	if (data[0] != INSN_CONFIG_FILTER)
-		return -EINVAL;
-
-	if (data[1]) {
+	switch (data[0]) {
+	case INSN_CONFIG_FILTER:
+		/*
+		 * The deglitch filter interval is specified in nanoseconds.
+		 * The hardware supports intervals in 200ns increments. Round
+		 * the user values up and return the actual interval.
+		 */
 		interval = (data[1] + 100) / 200;
 		data[1] = interval * 200;
 
-		if (interval != devpriv->filter_interval) {
-			writeb(interval & 0xff,
-			       devpriv->mite->daq_io_addr + Filter_Interval(0));
-			writeb((interval >> 8) & 0xff,
-			       devpriv->mite->daq_io_addr + Filter_Interval(1));
-			writeb((interval >> 16) & 0x0f,
-			       devpriv->mite->daq_io_addr + Filter_Interval(2));
-
-			writeb(ClrInterval,
-			       devpriv->mite->daq_io_addr + Clear_Register);
-
-			devpriv->filter_interval = interval;
+		if (interval) {
+			ni6527_set_filter_interval(dev, interval);
+			devpriv->filter_enable |= 1 << chan;
+		} else {
+			devpriv->filter_enable &= ~(1 << chan);
 		}
-
-		devpriv->filter_enable |= 1 << chan;
-	} else {
-		devpriv->filter_enable &= ~(1 << chan);
+		ni6527_set_filter_enable(dev, devpriv->filter_enable);
+		break;
+	default:
+		return -EINVAL;
 	}
 
-	writeb(devpriv->filter_enable,
-	       devpriv->mite->daq_io_addr + Filter_Enable(0));
-	writeb(devpriv->filter_enable >> 8,
-	       devpriv->mite->daq_io_addr + Filter_Enable(1));
-	writeb(devpriv->filter_enable >> 16,
-	       devpriv->mite->daq_io_addr + Filter_Enable(2));
-
-	return 2;
+	return insn->n;
 }
 
 static int ni6527_di_insn_bits(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
 	struct ni6527_private *devpriv = dev->private;
+	void __iomem *mmio = devpriv->mmio_base;
+	unsigned int val;
 
-	data[1] = readb(devpriv->mite->daq_io_addr + Port_Register(0));
-	data[1] |= readb(devpriv->mite->daq_io_addr + Port_Register(1)) << 8;
-	data[1] |= readb(devpriv->mite->daq_io_addr + Port_Register(2)) << 16;
+	val = readb(mmio + NI6527_DI_REG(0));
+	val |= (readb(mmio + NI6527_DI_REG(1)) << 8);
+	val |= (readb(mmio + NI6527_DI_REG(2)) << 16);
+
+	data[1] = val;
 
 	return insn->n;
 }
 
 static int ni6527_do_insn_bits(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
 	struct ni6527_private *devpriv = dev->private;
+	void __iomem *mmio = devpriv->mmio_base;
+	unsigned int mask;
 
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
+	mask = comedi_dio_update_state(s, data);
+	if (mask) {
+		/* Outputs are inverted */
+		unsigned int val = s->state ^ 0xffffff;
 
-		/* The open relay state on the board cooresponds to 1,
-		 * but in Comedi, it is represented by 0. */
-		if (data[0] & 0x0000ff) {
-			writeb((s->state ^ 0xff),
-			       devpriv->mite->daq_io_addr + Port_Register(3));
-		}
-		if (data[0] & 0x00ff00) {
-			writeb((s->state >> 8) ^ 0xff,
-			       devpriv->mite->daq_io_addr + Port_Register(4));
-		}
-		if (data[0] & 0xff0000) {
-			writeb((s->state >> 16) ^ 0xff,
-			       devpriv->mite->daq_io_addr + Port_Register(5));
-		}
+		if (mask & 0x0000ff)
+			writeb(val & 0xff, mmio + NI6527_DO_REG(0));
+		if (mask & 0x00ff00)
+			writeb((val >> 8) & 0xff, mmio + NI6527_DO_REG(1));
+		if (mask & 0xff0000)
+			writeb((val >> 16) & 0xff, mmio + NI6527_DO_REG(2));
 	}
+
 	data[1] = s->state;
 
 	return insn->n;
@@ -195,21 +206,22 @@
 {
 	struct comedi_device *dev = d;
 	struct ni6527_private *devpriv = dev->private;
-	struct comedi_subdevice *s = &dev->subdevices[2];
+	struct comedi_subdevice *s = dev->read_subdev;
+	void __iomem *mmio = devpriv->mmio_base;
 	unsigned int status;
 
-	status = readb(devpriv->mite->daq_io_addr + Change_Status);
-	if ((status & MasterInterruptStatus) == 0)
-		return IRQ_NONE;
-	if ((status & EdgeStatus) == 0)
+	status = readb(mmio + NI6527_STATUS_REG);
+	if (!(status & NI6527_STATUS_IRQ))
 		return IRQ_NONE;
 
-	writeb(ClrEdge | ClrOverflow,
-	       devpriv->mite->daq_io_addr + Clear_Register);
+	if (status & NI6527_STATUS_EDGE) {
+		comedi_buf_put(s->async, 0);
+		s->async->events |= COMEDI_CB_EOS;
+		comedi_event(dev, s);
+	}
 
-	comedi_buf_put(s->async, 0);
-	s->async->events |= COMEDI_CB_EOS;
-	comedi_event(dev, s);
+	writeb(NI6527_CLR_IRQS, mmio + NI6527_CLR_REG);
+
 	return IRQ_HANDLED;
 }
 
@@ -259,13 +271,10 @@
 			   struct comedi_subdevice *s)
 {
 	struct ni6527_private *devpriv = dev->private;
-	/* struct comedi_cmd *cmd = &s->async->cmd; */
+	void __iomem *mmio = devpriv->mmio_base;
 
-	writeb(ClrEdge | ClrOverflow,
-	       devpriv->mite->daq_io_addr + Clear_Register);
-	writeb(FallingEdgeIntEnable | RisingEdgeIntEnable |
-	       MasterInterruptEnable | EdgeIntEnable,
-	       devpriv->mite->daq_io_addr + Master_Interrupt_Control);
+	writeb(NI6527_CLR_IRQS, mmio + NI6527_CLR_REG);
+	writeb(NI6527_CTRL_ENABLE_IRQS, mmio + NI6527_CTRL_REG);
 
 	return 0;
 }
@@ -274,8 +283,9 @@
 			      struct comedi_subdevice *s)
 {
 	struct ni6527_private *devpriv = dev->private;
+	void __iomem *mmio = devpriv->mmio_base;
 
-	writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control);
+	writeb(NI6527_CTRL_DISABLE_IRQS, mmio + NI6527_CTRL_REG);
 
 	return 0;
 }
@@ -288,32 +298,54 @@
 	return insn->n;
 }
 
-static int ni6527_intr_insn_config(struct comedi_device *dev,
-				   struct comedi_subdevice *s,
-				   struct comedi_insn *insn, unsigned int *data)
+static void ni6527_set_edge_detection(struct comedi_device *dev,
+				      unsigned int rising,
+				      unsigned int falling)
 {
 	struct ni6527_private *devpriv = dev->private;
+	void __iomem *mmio = devpriv->mmio_base;
 
-	if (insn->n < 1)
+	/* enable rising-edge detection channels */
+	writeb(rising & 0xff, mmio + NI6527_RISING_EDGE_REG(0));
+	writeb((rising >> 8) & 0xff, mmio + NI6527_RISING_EDGE_REG(1));
+	writeb((rising >> 16) & 0xff, mmio + NI6527_RISING_EDGE_REG(2));
+
+	/* enable falling-edge detection channels */
+	writeb(falling & 0xff, mmio + NI6527_FALLING_EDGE_REG(0));
+	writeb((falling >> 8) & 0xff, mmio + NI6527_FALLING_EDGE_REG(1));
+	writeb((falling >> 16) & 0xff, mmio + NI6527_FALLING_EDGE_REG(2));
+}
+
+static int ni6527_intr_insn_config(struct comedi_device *dev,
+				   struct comedi_subdevice *s,
+				   struct comedi_insn *insn,
+				   unsigned int *data)
+{
+	switch (data[0]) {
+	case INSN_CONFIG_CHANGE_NOTIFY:
+		/* check_insn_config_length() does not check this instruction */
+		if (insn->n != 3)
+			return -EINVAL;
+		ni6527_set_edge_detection(dev, data[1], data[2]);
+		break;
+	default:
 		return -EINVAL;
-	if (data[0] != INSN_CONFIG_CHANGE_NOTIFY)
-		return -EINVAL;
+	}
 
-	writeb(data[1],
-	       devpriv->mite->daq_io_addr + Rising_Edge_Detection_Enable(0));
-	writeb(data[1] >> 8,
-	       devpriv->mite->daq_io_addr + Rising_Edge_Detection_Enable(1));
-	writeb(data[1] >> 16,
-	       devpriv->mite->daq_io_addr + Rising_Edge_Detection_Enable(2));
+	return insn->n;
+}
 
-	writeb(data[2],
-	       devpriv->mite->daq_io_addr + Falling_Edge_Detection_Enable(0));
-	writeb(data[2] >> 8,
-	       devpriv->mite->daq_io_addr + Falling_Edge_Detection_Enable(1));
-	writeb(data[2] >> 16,
-	       devpriv->mite->daq_io_addr + Falling_Edge_Detection_Enable(2));
+static void ni6527_reset(struct comedi_device *dev)
+{
+	struct ni6527_private *devpriv = dev->private;
+	void __iomem *mmio = devpriv->mmio_base;
 
-	return 2;
+	/* disable deglitch filters on all channels */
+	ni6527_set_filter_enable(dev, 0);
+
+	writeb(NI6527_CLR_IRQS | NI6527_CLR_RESET_FILT,
+	       mmio + NI6527_CLR_REG);
+	writeb(NI6527_CTRL_DISABLE_IRQS, mmio + NI6527_CTRL_REG);
 }
 
 static int ni6527_auto_attach(struct comedi_device *dev,
@@ -332,75 +364,69 @@
 	dev->board_ptr = board;
 	dev->board_name = board->name;
 
-	ret = comedi_pci_enable(dev);
-	if (ret)
-		return ret;
-
 	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
 
-	devpriv->mite = mite_alloc(pcidev);
-	if (!devpriv->mite)
+	ret = comedi_pci_enable(dev);
+	if (ret)
+		return ret;
+
+	devpriv->mmio_base = pci_ioremap_bar(pcidev, 1);
+	if (!devpriv->mmio_base)
 		return -ENOMEM;
 
-	ret = mite_setup(devpriv->mite);
-	if (ret < 0) {
-		dev_err(dev->class_dev, "error setting up mite\n");
-		return ret;
-	}
+	/* make sure this is actually a 6527 device */
+	if (readb(devpriv->mmio_base + NI6527_ID_REG) != 0x27)
+		return -ENODEV;
 
-	dev_info(dev->class_dev, "board: %s, ID=0x%02x\n", dev->board_name,
-		 readb(devpriv->mite->daq_io_addr + ID_Register));
+	ni6527_reset(dev);
+
+	ret = request_irq(pcidev->irq, ni6527_interrupt, IRQF_SHARED,
+			  dev->board_name, dev);
+	if (ret == 0)
+		dev->irq = pcidev->irq;
 
 	ret = comedi_alloc_subdevices(dev, 3);
 	if (ret)
 		return ret;
 
+	/* Digital Input subdevice */
 	s = &dev->subdevices[0];
-	s->type = COMEDI_SUBD_DI;
-	s->subdev_flags = SDF_READABLE;
-	s->n_chan = 24;
-	s->range_table = &range_digital;
-	s->maxdata = 1;
-	s->insn_config = ni6527_di_insn_config;
-	s->insn_bits = ni6527_di_insn_bits;
+	s->type		= COMEDI_SUBD_DI;
+	s->subdev_flags	= SDF_READABLE;
+	s->n_chan	= 24;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_config	= ni6527_di_insn_config;
+	s->insn_bits	= ni6527_di_insn_bits;
 
+	/* Digital Output subdevice */
 	s = &dev->subdevices[1];
-	s->type = COMEDI_SUBD_DO;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-	s->n_chan = 24;
-	s->range_table = &range_unknown;  /* FIXME: actually conductance */
-	s->maxdata = 1;
-	s->insn_bits = ni6527_do_insn_bits;
+	s->type		= COMEDI_SUBD_DO;
+	s->subdev_flags	= SDF_WRITABLE;
+	s->n_chan	= 24;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= ni6527_do_insn_bits;
 
+	/* Edge detection interrupt subdevice */
 	s = &dev->subdevices[2];
-	dev->read_subdev = s;
-	s->type = COMEDI_SUBD_DI;
-	s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
-	s->n_chan = 1;
-	s->range_table = &range_unknown;
-	s->maxdata = 1;
-	s->do_cmdtest = ni6527_intr_cmdtest;
-	s->do_cmd = ni6527_intr_cmd;
-	s->cancel = ni6527_intr_cancel;
-	s->insn_bits = ni6527_intr_insn_bits;
-	s->insn_config = ni6527_intr_insn_config;
-
-	writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(0));
-	writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(1));
-	writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(2));
-
-	writeb(ClrEdge | ClrOverflow | ClrFilter | ClrInterval,
-	       devpriv->mite->daq_io_addr + Clear_Register);
-	writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control);
-
-	ret = request_irq(mite_irq(devpriv->mite), ni6527_interrupt,
-			  IRQF_SHARED, DRIVER_NAME, dev);
-	if (ret < 0)
-		dev_warn(dev->class_dev, "irq not available\n");
-	else
-		dev->irq = mite_irq(devpriv->mite);
+	if (dev->irq) {
+		dev->read_subdev = s;
+		s->type		= COMEDI_SUBD_DI;
+		s->subdev_flags	= SDF_READABLE | SDF_CMD_READ;
+		s->n_chan	= 1;
+		s->maxdata	= 1;
+		s->range_table	= &range_digital;
+		s->insn_config	= ni6527_intr_insn_config;
+		s->insn_bits	= ni6527_intr_insn_bits;
+		s->do_cmdtest	= ni6527_intr_cmdtest;
+		s->do_cmd	= ni6527_intr_cmd;
+		s->cancel	= ni6527_intr_cancel;
+	} else {
+		s->type = COMEDI_SUBD_UNUSED;
+	}
 
 	return 0;
 }
@@ -409,23 +435,18 @@
 {
 	struct ni6527_private *devpriv = dev->private;
 
-	if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr)
-		writeb(0x00,
-		       devpriv->mite->daq_io_addr + Master_Interrupt_Control);
+	if (devpriv && devpriv->mmio_base)
+		ni6527_reset(dev);
 	if (dev->irq)
 		free_irq(dev->irq, dev);
-	if (devpriv && devpriv->mite) {
-		mite_unsetup(devpriv->mite);
-		mite_free(devpriv->mite);
-	}
 	comedi_pci_disable(dev);
 }
 
 static struct comedi_driver ni6527_driver = {
-	.driver_name = DRIVER_NAME,
-	.module = THIS_MODULE,
-	.auto_attach = ni6527_auto_attach,
-	.detach = ni6527_detach,
+	.driver_name	= "ni_6527",
+	.module		= THIS_MODULE,
+	.auto_attach	= ni6527_auto_attach,
+	.detach		= ni6527_detach,
 };
 
 static int ni6527_pci_probe(struct pci_dev *dev,
@@ -442,7 +463,7 @@
 MODULE_DEVICE_TABLE(pci, ni6527_pci_table);
 
 static struct pci_driver ni6527_pci_driver = {
-	.name		= DRIVER_NAME,
+	.name		= "ni_6527",
 	.id_table	= ni6527_pci_table,
 	.probe		= ni6527_pci_probe,
 	.remove		= comedi_pci_auto_unconfig,
@@ -450,5 +471,5 @@
 module_comedi_pci_driver(ni6527_driver, ni6527_pci_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for National Instruments PCI-6527");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
index 3607336..8a991dc 100644
--- a/drivers/staging/comedi/drivers/ni_660x.c
+++ b/drivers/staging/comedi/drivers/ni_660x.c
@@ -1213,7 +1213,6 @@
 	s->range_table = &range_digital;
 	s->insn_bits = ni_660x_dio_insn_bits;
 	s->insn_config = ni_660x_dio_insn_config;
-	s->io_bits = 0;		/* all bits default to input */
 	/*  we use the ioconfig registers to control dio direction, so zero
 	output enables in stc dio control reg */
 	ni_660x_write_register(dev, 0, 0, STCDIOControl);
diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
index e2926ce..e4414cf1 100644
--- a/drivers/staging/comedi/drivers/ni_670x.c
+++ b/drivers/staging/comedi/drivers/ni_670x.c
@@ -136,20 +136,15 @@
 
 static int ni_670x_dio_insn_bits(struct comedi_device *dev,
 				 struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data)
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
 	struct ni_670x_private *devpriv = dev->private;
 	void __iomem *io_addr = devpriv->mite->daq_io_addr +
 					DIO_PORT0_DATA_OFFSET;
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
 
-	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
-
+	if (comedi_dio_update_state(s, data))
 		writel(s->state, io_addr);
-	}
 
 	data[1] = readl(io_addr);
 
diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
index 2512ce8..63c8479 100644
--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
+++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
@@ -154,7 +154,7 @@
 
 	volatile unsigned int count;	/* number of data points left to be taken */
 	unsigned int dma;	/*  dma channel */
-	s16 *dma_buffer;	/*  dma buffer */
+	uint16_t *dma_buffer;	/*  dma buffer */
 	unsigned int dma_transfer_size;	/*  size in bytes of dma transfers */
 	int irq_dma_bits;	/*  irq/dma register bits */
 	int config_bits;	/*  config register bits */
@@ -192,7 +192,7 @@
 	struct comedi_async *async;
 	struct comedi_cmd *cmd;
 	unsigned int max_points, num_points, residue, leftover;
-	short dpnt;
+	unsigned short dpnt;
 	static const int sample_size = sizeof(devpriv->dma_buffer[0]);
 
 	if (!dev->attached) {
@@ -684,13 +684,12 @@
 		devpriv->config_bits |= CHANNEL_BITS(0x4 | start_channel);
 		break;
 	case 2:
-		if (start_channel == 0) {
+		if (start_channel == 0)
 			devpriv->config_bits |= CHANNEL_BITS(0x2);
-		} else if (start_channel == 2) {
+		else if (start_channel == 2)
 			devpriv->config_bits |= CHANNEL_BITS(0x3);
-		} else {
+		else
 			return -1;
-		}
 		break;
 	case 4:
 		devpriv->config_bits |= CHANNEL_BITS(0x1);
diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c
index b9122fd..10e3e947 100644
--- a/drivers/staging/comedi/drivers/ni_at_ao.c
+++ b/drivers/staging/comedi/drivers/ni_at_ao.c
@@ -1,247 +1,193 @@
 /*
-    comedi/drivers/ni_at_ao.c
-    Driver for NI AT-AO-6/10 boards
+ * ni_at_ao.c
+ * Driver for NI AT-AO-6/10 boards
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000,2002 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
 
-    COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 2000,2002 David A. Schleef <ds@schleef.org>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-*/
 /*
-Driver: ni_at_ao
-Description: National Instruments AT-AO-6/10
-Devices: [National Instruments] AT-AO-6 (at-ao-6), AT-AO-10 (at-ao-10)
-Status: should work
-Author: ds
-Updated: Sun Dec 26 12:26:28 EST 2004
-
-Configuration options:
-  [0] - I/O port base address
-  [1] - IRQ (unused)
-  [2] - DMA (unused)
-  [3] - analog output range, set by jumpers on hardware (0 for -10 to 10V
-	bipolar, 1 for 0V to 10V unipolar)
-
-*/
-/*
- * Register-level programming information can be found in NI
- * document 320379.pdf.
+ * Driver: ni_at_ao
+ * Description: National Instruments AT-AO-6/10
+ * Devices: (National Instruments) AT-AO-6 [at-ao-6]
+ *          (National Instruments) AT-AO-10 [at-ao-10]
+ * Status: should work
+ * Author: David A. Schleef <ds@schleef.org>
+ * Updated: Sun Dec 26 12:26:28 EST 2004
+ *
+ * Configuration options:
+ *   [0] - I/O port base address
+ *   [1] - IRQ (unused)
+ *   [2] - DMA (unused)
+ *   [3] - analog output range, set by jumpers on hardware
+ *         0 for -10 to 10V bipolar
+ *         1 for 0V to 10V unipolar
  */
 
 #include <linux/module.h>
+
 #include "../comedidev.h"
 
-/* board egisters */
-/* registers with _2_ are accessed when GRP2WR is set in CFG1 */
-
-#define ATAO_SIZE 0x20
-
-#define ATAO_2_DMATCCLR		0x00	/* W 16 */
-#define ATAO_DIN		0x00	/* R 16 */
-#define ATAO_DOUT		0x00	/* W 16 */
-
-#define ATAO_CFG2		0x02	/* W 16 */
-#define CALLD1	0x8000
-#define CALLD0	0x4000
-#define FFRTEN	0x2000
-#define DAC2S8	0x1000
-#define DAC2S6	0x0800
-#define DAC2S4	0x0400
-#define DAC2S2	0x0200
-#define DAC2S0	0x0100
-#define LDAC8		0x0080
-#define LDAC6		0x0040
-#define LDAC4		0x0020
-#define LDAC2		0x0010
-#define LDAC0		0x0008
-#define PROMEN	0x0004
-#define SCLK		0x0002
-#define SDATA		0x0001
-
-#define ATAO_2_INT1CLR		0x02	/* W 16 */
-
-#define ATAO_CFG3		0x04	/* W 16 */
-#define DMAMODE	0x0040
-#define CLKOUT	0x0020
-#define RCLKEN	0x0010
-#define DOUTEN2	0x0008
-#define DOUTEN1	0x0004
-#define EN2_5V	0x0002
-#define SCANEN	0x0001
-
-#define ATAO_2_INT2CLR		0x04	/* W 16 */
-
-#define ATAO_82C53_BASE		0x06	/* RW 8 */
-
-#define ATAO_82C53_CNTR1	0x06	/* RW 8 */
-#define ATAO_82C53_CNTR2	0x07	/* RW 8 */
-#define ATAO_82C53_CNTR3	0x08	/* RW 8 */
-#define ATAO_82C53_CNTRCMD	0x09	/* W 8 */
-#define CNTRSEL1	0x80
-#define CNTRSEL0	0x40
-#define RWSEL1	0x20
-#define RWSEL0	0x10
-#define MODESEL2	0x08
-#define MODESEL1	0x04
-#define MODESEL0	0x02
-#define BCDSEL	0x01
-  /* read-back command */
-#define COUNT		0x20
-#define STATUS	0x10
-#define CNTR3		0x08
-#define CNTR2		0x04
-#define CNTR1		0x02
-  /* status */
-#define OUT		0x80
-#define _NULL		0x40
-#define RW1		0x20
-#define RW0		0x10
-#define MODE2		0x08
-#define MODE1		0x04
-#define MODE0		0x02
-#define BCD		0x01
-
-#define ATAO_2_RTSISHFT		0x06	/* W 8 */
-#define RSI		0x01
-
-#define ATAO_2_RTSISTRB		0x07	/* W 8 */
-
-#define ATAO_CFG1		0x0a	/* W 16 */
-#define EXTINT2EN	0x8000
-#define EXTINT1EN	0x4000
-#define CNTINT2EN	0x2000
-#define CNTINT1EN	0x1000
-#define TCINTEN	0x0800
-#define CNT1SRC	0x0400
-#define CNT2SRC	0x0200
-#define FIFOEN	0x0100
-#define GRP2WR	0x0080
-#define EXTUPDEN	0x0040
-#define DMARQ		0x0020
-#define DMAEN		0x0010
-#define CH_mask	0x000f
-#define ATAO_STATUS		0x0a	/* R 16 */
-#define FH		0x0040
-#define FE		0x0020
-#define FF		0x0010
-#define INT2		0x0008
-#define INT1		0x0004
-#define TCINT		0x0002
-#define PROMOUT	0x0001
-
-#define ATAO_FIFO_WRITE		0x0c	/* W 16 */
-#define ATAO_FIFO_CLEAR		0x0c	/* R 16 */
-#define ATAO_DACn(x)		(0x0c + 2*(x))	/* W */
+#include "8253.h"
 
 /*
- * Board descriptions for two imaginary boards.  Describing the
- * boards in this way is optional, and completely driver-dependent.
- * Some drivers use arrays such as this, other do not.
+ * Register map
+ *
+ * Register-level programming information can be found in NI
+ * document 320379.pdf.
  */
+#define ATAO_DIO_REG		0x00
+#define ATAO_CFG2_REG		0x02
+#define ATAO_CFG2_CALLD_NOP	(0 << 14)
+#define ATAO_CFG2_CALLD(x)	((((x) >> 3) + 1) << 14)
+#define ATAO_CFG2_FFRTEN	(1 << 13)
+#define ATAO_CFG2_DACS(x)	(1 << (((x) / 2) + 8))
+#define ATAO_CFG2_LDAC(x)	(1 << (((x) / 2) + 3))
+#define ATAO_CFG2_PROMEN	(1 << 2)
+#define ATAO_CFG2_SCLK		(1 << 1)
+#define ATAO_CFG2_SDATA		(1 << 0)
+#define ATAO_CFG3_REG		0x04
+#define ATAO_CFG3_DMAMODE	(1 << 6)
+#define ATAO_CFG3_CLKOUT	(1 << 5)
+#define ATAO_CFG3_RCLKEN	(1 << 4)
+#define ATAO_CFG3_DOUTEN2	(1 << 3)
+#define ATAO_CFG3_DOUTEN1	(1 << 2)
+#define ATAO_CFG3_EN2_5V	(1 << 1)
+#define ATAO_CFG3_SCANEN	(1 << 0)
+#define ATAO_82C53_BASE		0x06
+#define ATAO_CFG1_REG		0x0a
+#define ATAO_CFG1_EXTINT2EN	(1 << 15)
+#define ATAO_CFG1_EXTINT1EN	(1 << 14)
+#define ATAO_CFG1_CNTINT2EN	(1 << 13)
+#define ATAO_CFG1_CNTINT1EN	(1 << 12)
+#define ATAO_CFG1_TCINTEN	(1 << 11)
+#define ATAO_CFG1_CNT1SRC	(1 << 10)
+#define ATAO_CFG1_CNT2SRC	(1 << 9)
+#define ATAO_CFG1_FIFOEN	(1 << 8)
+#define ATAO_CFG1_GRP2WR	(1 << 7)
+#define ATAO_CFG1_EXTUPDEN	(1 << 6)
+#define ATAO_CFG1_DMARQ		(1 << 5)
+#define ATAO_CFG1_DMAEN		(1 << 4)
+#define ATAO_CFG1_CH(x)		(((x) & 0xf) << 0)
+#define ATAO_STATUS_REG		0x0a
+#define ATAO_STATUS_FH		(1 << 6)
+#define ATAO_STATUS_FE		(1 << 5)
+#define ATAO_STATUS_FF		(1 << 4)
+#define ATAO_STATUS_INT2	(1 << 3)
+#define ATAO_STATUS_INT1	(1 << 2)
+#define ATAO_STATUS_TCINT	(1 << 1)
+#define ATAO_STATUS_PROMOUT	(1 << 0)
+#define ATAO_FIFO_WRITE_REG	0x0c
+#define ATAO_FIFO_CLEAR_REG	0x0c
+#define ATAO_AO_REG(x)		(0x0c + ((x) * 2))
+
+/* registers with _2_ are accessed when GRP2WR is set in CFG1 */
+#define ATAO_2_DMATCCLR_REG	0x00
+#define ATAO_2_INT1CLR_REG	0x02
+#define ATAO_2_INT2CLR_REG	0x04
+#define ATAO_2_RTSISHFT_REG	0x06
+#define ATAO_2_RTSISHFT_RSI	(1 << 0)
+#define ATAO_2_RTSISTRB_REG	0x07
+
 struct atao_board {
 	const char *name;
 	int n_ao_chans;
 };
 
-struct atao_private {
+static const struct atao_board atao_boards[] = {
+	{
+		.name		= "at-ao-6",
+		.n_ao_chans	= 6,
+	}, {
+		.name		= "at-ao-10",
+		.n_ao_chans	= 10,
+	},
+};
 
+struct atao_private {
 	unsigned short cfg1;
-	unsigned short cfg2;
 	unsigned short cfg3;
 
 	/* Used for AO readback */
 	unsigned int ao_readback[10];
+
+	/* Used for caldac readback */
+	unsigned char caldac[21];
 };
 
-static void atao_reset(struct comedi_device *dev)
+static void atao_select_reg_group(struct comedi_device *dev, int group)
 {
 	struct atao_private *devpriv = dev->private;
 
-	/* This is the reset sequence described in the manual */
-
-	devpriv->cfg1 = 0;
-	outw(devpriv->cfg1, dev->iobase + ATAO_CFG1);
-
-	outb(RWSEL0 | MODESEL2, dev->iobase + ATAO_82C53_CNTRCMD);
-	outb(0x03, dev->iobase + ATAO_82C53_CNTR1);
-	outb(CNTRSEL0 | RWSEL0 | MODESEL2, dev->iobase + ATAO_82C53_CNTRCMD);
-
-	devpriv->cfg2 = 0;
-	outw(devpriv->cfg2, dev->iobase + ATAO_CFG2);
-
-	devpriv->cfg3 = 0;
-	outw(devpriv->cfg3, dev->iobase + ATAO_CFG3);
-
-	inw(dev->iobase + ATAO_FIFO_CLEAR);
-
-	devpriv->cfg1 |= GRP2WR;
-	outw(devpriv->cfg1, dev->iobase + ATAO_CFG1);
-
-	outw(0, dev->iobase + ATAO_2_INT1CLR);
-	outw(0, dev->iobase + ATAO_2_INT2CLR);
-	outw(0, dev->iobase + ATAO_2_DMATCCLR);
-
-	devpriv->cfg1 &= ~GRP2WR;
-	outw(devpriv->cfg1, dev->iobase + ATAO_CFG1);
+	if (group)
+		devpriv->cfg1 |= ATAO_CFG1_GRP2WR;
+	else
+		devpriv->cfg1 &= ~ATAO_CFG1_GRP2WR;
+	outw(devpriv->cfg1, dev->iobase + ATAO_CFG1_REG);
 }
 
-static int atao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
-			 struct comedi_insn *insn, unsigned int *data)
+static int atao_ao_insn_write(struct comedi_device *dev,
+			      struct comedi_subdevice *s,
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
 	struct atao_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int val;
 	int i;
-	int chan = CR_CHAN(insn->chanspec);
-	short bits;
+
+	if (chan == 0)
+		atao_select_reg_group(dev, 1);
 
 	for (i = 0; i < insn->n; i++) {
-		bits = data[i] - 0x800;
-		if (chan == 0) {
-			devpriv->cfg1 |= GRP2WR;
-			outw(devpriv->cfg1, dev->iobase + ATAO_CFG1);
-		}
-		outw(bits, dev->iobase + ATAO_DACn(chan));
-		if (chan == 0) {
-			devpriv->cfg1 &= ~GRP2WR;
-			outw(devpriv->cfg1, dev->iobase + ATAO_CFG1);
-		}
-		devpriv->ao_readback[chan] = data[i];
+		val = data[i];
+		devpriv->ao_readback[chan] = val;
+
+		/* munge offset binary (unsigned) to two's complement */
+		val = comedi_offset_munge(s, val);
+		outw(val, dev->iobase + ATAO_AO_REG(chan));
 	}
 
-	return i;
+	if (chan == 0)
+		atao_select_reg_group(dev, 0);
+
+	return insn->n;
 }
 
-static int atao_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
-			 struct comedi_insn *insn, unsigned int *data)
+static int atao_ao_insn_read(struct comedi_device *dev,
+			     struct comedi_subdevice *s,
+			     struct comedi_insn *insn,
+			     unsigned int *data)
 {
 	struct atao_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
 	int i;
-	int chan = CR_CHAN(insn->chanspec);
 
 	for (i = 0; i < insn->n; i++)
 		data[i] = devpriv->ao_readback[chan];
 
-	return i;
+	return insn->n;
 }
 
 static int atao_dio_insn_bits(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data)
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= data[0] & data[1];
-		outw(s->state, dev->iobase + ATAO_DOUT);
-	}
+	if (comedi_dio_update_state(s, data))
+		outw(s->state, dev->iobase + ATAO_DIO_REG);
 
-	data[1] = inw(dev->iobase + ATAO_DIN);
+	data[1] = inw(dev->iobase + ATAO_DIO_REG);
 
 	return insn->n;
 }
@@ -266,70 +212,138 @@
 		return ret;
 
 	if (s->io_bits & 0x0f)
-		devpriv->cfg3 |= DOUTEN1;
+		devpriv->cfg3 |= ATAO_CFG3_DOUTEN1;
 	else
-		devpriv->cfg3 &= ~DOUTEN1;
+		devpriv->cfg3 &= ~ATAO_CFG3_DOUTEN1;
 	if (s->io_bits & 0xf0)
-		devpriv->cfg3 |= DOUTEN2;
+		devpriv->cfg3 |= ATAO_CFG3_DOUTEN2;
 	else
-		devpriv->cfg3 &= ~DOUTEN2;
+		devpriv->cfg3 &= ~ATAO_CFG3_DOUTEN2;
 
-	outw(devpriv->cfg3, dev->iobase + ATAO_CFG3);
+	outw(devpriv->cfg3, dev->iobase + ATAO_CFG3_REG);
 
 	return insn->n;
 }
 
 /*
- * Figure 2-1 in the manual shows 3 chips labeled DAC8800, which
- * are 8-channel 8-bit DACs.  These are most likely the calibration
- * DACs.  It is not explicitly stated in the manual how to access
- * the caldacs, but we can guess.
+ * There are three DAC8800 TrimDACs on the board. These are 8-channel,
+ * 8-bit DACs that are used to calibrate the Analog Output channels.
+ * The factory default calibration values are stored in the EEPROM.
+ * The TrimDACs, and EEPROM addresses, are mapped as:
+ *
+ *        Channel       EEPROM  Description
+ *   -----------------  ------  -----------------------------------
+ *    0 - DAC0 Chan 0    0x30   AO Channel 0 Offset
+ *    1 - DAC0 Chan 1    0x31   AO Channel 0 Gain
+ *    2 - DAC0 Chan 2    0x32   AO Channel 1 Offset
+ *    3 - DAC0 Chan 3    0x33   AO Channel 1 Gain
+ *    4 - DAC0 Chan 4    0x34   AO Channel 2 Offset
+ *    5 - DAC0 Chan 5    0x35   AO Channel 2 Gain
+ *    6 - DAC0 Chan 6    0x36   AO Channel 3 Offset
+ *    7 - DAC0 Chan 7    0x37   AO Channel 3 Gain
+ *    8 - DAC1 Chan 0    0x38   AO Channel 4 Offset
+ *    9 - DAC1 Chan 1    0x39   AO Channel 4 Gain
+ *   10 - DAC1 Chan 2    0x3a   AO Channel 5 Offset
+ *   11 - DAC1 Chan 3    0x3b   AO Channel 5 Gain
+ *   12 - DAC1 Chan 4    0x3c   2.5V Offset
+ *   13 - DAC1 Chan 5    0x3d   AO Channel 6 Offset (at-ao-10 only)
+ *   14 - DAC1 Chan 6    0x3e   AO Channel 6 Gain   (at-ao-10 only)
+ *   15 - DAC1 Chan 7    0x3f   AO Channel 7 Offset (at-ao-10 only)
+ *   16 - DAC2 Chan 0    0x40   AO Channel 7 Gain   (at-ao-10 only)
+ *   17 - DAC2 Chan 1    0x41   AO Channel 8 Offset (at-ao-10 only)
+ *   18 - DAC2 Chan 2    0x42   AO Channel 8 Gain   (at-ao-10 only)
+ *   19 - DAC2 Chan 3    0x43   AO Channel 9 Offset (at-ao-10 only)
+ *   20 - DAC2 Chan 4    0x44   AO Channel 9 Gain   (at-ao-10 only)
+ *        DAC2 Chan 5    0x45   Reserved
+ *        DAC2 Chan 6    0x46   Reserved
+ *        DAC2 Chan 7    0x47   Reserved
  */
-static int atao_calib_insn_read(struct comedi_device *dev,
-				struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data)
+static int atao_calib_insn_write(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
 {
-	int i;
-	for (i = 0; i < insn->n; i++)
-		data[i] = 0;	/* XXX */
+	struct atao_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int bitstring;
+	unsigned int val;
+	int bit;
+
+	if (insn->n == 0)
+		return 0;
+
+	devpriv->caldac[chan] = data[insn->n - 1] & s->maxdata;
+
+	/* write the channel and last data value to the caldac */
+	bitstring = ((chan & 0x7) << 8) | devpriv->caldac[chan];
+
+	/* clock the bitstring to the caldac; MSB -> LSB */
+	for (bit = 1 << 10; bit; bit >>= 1) {
+		val = (bit & bitstring) ? ATAO_CFG2_SDATA : 0;
+
+		outw(val, dev->iobase + ATAO_CFG2_REG);
+		outw(val | ATAO_CFG2_SCLK, dev->iobase + ATAO_CFG2_REG);
+	}
+
+	/* strobe the caldac to load the value */
+	outw(ATAO_CFG2_CALLD(chan), dev->iobase + ATAO_CFG2_REG);
+	outw(ATAO_CFG2_CALLD_NOP, dev->iobase + ATAO_CFG2_REG);
+
 	return insn->n;
 }
 
-static int atao_calib_insn_write(struct comedi_device *dev,
-				 struct comedi_subdevice *s,
-				 struct comedi_insn *insn, unsigned int *data)
+static int atao_calib_insn_read(struct comedi_device *dev,
+				struct comedi_subdevice *s,
+				struct comedi_insn *insn,
+				unsigned int *data)
 {
 	struct atao_private *devpriv = dev->private;
-	unsigned int bitstring, bit;
 	unsigned int chan = CR_CHAN(insn->chanspec);
+	int i;
 
-	bitstring = ((chan & 0x7) << 8) | (data[insn->n - 1] & 0xff);
-
-	for (bit = 1 << (11 - 1); bit; bit >>= 1) {
-		outw(devpriv->cfg2 | ((bit & bitstring) ? SDATA : 0),
-		     dev->iobase + ATAO_CFG2);
-		outw(devpriv->cfg2 | SCLK | ((bit & bitstring) ? SDATA : 0),
-		     dev->iobase + ATAO_CFG2);
-	}
-	/* strobe the appropriate caldac */
-	outw(devpriv->cfg2 | (((chan >> 3) + 1) << 14),
-	     dev->iobase + ATAO_CFG2);
-	outw(devpriv->cfg2, dev->iobase + ATAO_CFG2);
+	for (i = 0; i < insn->n; i++)
+		data[i] = devpriv->caldac[chan];
 
 	return insn->n;
 }
 
+static void atao_reset(struct comedi_device *dev)
+{
+	struct atao_private *devpriv = dev->private;
+
+	/* This is the reset sequence described in the manual */
+
+	devpriv->cfg1 = 0;
+	outw(devpriv->cfg1, dev->iobase + ATAO_CFG1_REG);
+
+	/* Put outputs of counter 1 and counter 2 in a high state */
+	i8254_load(dev->iobase + ATAO_82C53_BASE, 0,
+		   0, 0x0003, I8254_MODE4 | I8254_BINARY);
+	i8254_set_mode(dev->iobase + ATAO_82C53_BASE, 0,
+		   1, I8254_MODE4 | I8254_BINARY);
+
+	outw(ATAO_CFG2_CALLD_NOP, dev->iobase + ATAO_CFG2_REG);
+
+	devpriv->cfg3 = 0;
+	outw(devpriv->cfg3, dev->iobase + ATAO_CFG3_REG);
+
+	inw(dev->iobase + ATAO_FIFO_CLEAR_REG);
+
+	atao_select_reg_group(dev, 1);
+	outw(0, dev->iobase + ATAO_2_INT1CLR_REG);
+	outw(0, dev->iobase + ATAO_2_INT2CLR_REG);
+	outw(0, dev->iobase + ATAO_2_DMATCCLR_REG);
+	atao_select_reg_group(dev, 0);
+}
+
 static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct atao_board *board = comedi_board(dev);
 	struct atao_private *devpriv;
 	struct comedi_subdevice *s;
-	int ao_unipolar;
 	int ret;
 
-	ao_unipolar = it->options[3];
-
-	ret = comedi_request_region(dev, it->options[0], ATAO_SIZE);
+	ret = comedi_request_region(dev, it->options[0], 0x20);
 	if (ret)
 		return ret;
 
@@ -341,60 +355,44 @@
 	if (ret)
 		return ret;
 
+	/* Analog Output subdevice */
 	s = &dev->subdevices[0];
-	/* analog output subdevice */
-	s->type = COMEDI_SUBD_AO;
-	s->subdev_flags = SDF_WRITABLE;
-	s->n_chan = board->n_ao_chans;
-	s->maxdata = (1 << 12) - 1;
-	if (ao_unipolar)
-		s->range_table = &range_unipolar10;
-	else
-		s->range_table = &range_bipolar10;
-	s->insn_write = &atao_ao_winsn;
-	s->insn_read = &atao_ao_rinsn;
+	s->type		= COMEDI_SUBD_AO;
+	s->subdev_flags	= SDF_WRITABLE;
+	s->n_chan	= board->n_ao_chans;
+	s->maxdata	= 0x0fff;
+	s->range_table	= it->options[3] ? &range_unipolar10 : &range_bipolar10;
+	s->insn_write	= atao_ao_insn_write;
+	s->insn_read	= atao_ao_insn_read;
 
+	/* Digital I/O subdevice */
 	s = &dev->subdevices[1];
-	/* digital i/o subdevice */
-	s->type = COMEDI_SUBD_DIO;
-	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-	s->n_chan = 8;
-	s->maxdata = 1;
-	s->range_table = &range_digital;
-	s->insn_bits = atao_dio_insn_bits;
-	s->insn_config = atao_dio_insn_config;
+	s->type		= COMEDI_SUBD_DIO;
+	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
+	s->n_chan	= 8;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= atao_dio_insn_bits;
+	s->insn_config	= atao_dio_insn_config;
 
-	s = &dev->subdevices[2];
 	/* caldac subdevice */
-	s->type = COMEDI_SUBD_CALIB;
-	s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL;
-	s->n_chan = 21;
-	s->maxdata = 0xff;
-	s->insn_read = atao_calib_insn_read;
-	s->insn_write = atao_calib_insn_write;
+	s = &dev->subdevices[2];
+	s->type		= COMEDI_SUBD_CALIB;
+	s->subdev_flags	= SDF_WRITABLE | SDF_INTERNAL;
+	s->n_chan	= (board->n_ao_chans * 2) + 1;
+	s->maxdata	= 0xff;
+	s->insn_read	= atao_calib_insn_read;
+	s->insn_write	= atao_calib_insn_write;
 
+	/* EEPROM subdevice */
 	s = &dev->subdevices[3];
-	/* eeprom subdevice */
-	/* s->type=COMEDI_SUBD_EEPROM; */
-	s->type = COMEDI_SUBD_UNUSED;
+	s->type		= COMEDI_SUBD_UNUSED;
 
 	atao_reset(dev);
 
-	printk(KERN_INFO "\n");
-
 	return 0;
 }
 
-static const struct atao_board atao_boards[] = {
-	{
-		.name		= "ai-ao-6",
-		.n_ao_chans	= 6,
-	}, {
-		.name		= "ai-ao-10",
-		.n_ao_chans	= 10,
-	},
-};
-
 static struct comedi_driver ni_at_ao_driver = {
 	.driver_name	= "ni_at_ao",
 	.module		= THIS_MODULE,
@@ -407,5 +405,5 @@
 module_comedi_driver(ni_at_ao_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for NI AT-AO-6/10 boards");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c
index bb3491f..a9f7d40 100644
--- a/drivers/staging/comedi/drivers/ni_atmio16d.c
+++ b/drivers/staging/comedi/drivers/ni_atmio16d.c
@@ -558,13 +558,12 @@
 
 static int atmio16d_dio_insn_bits(struct comedi_device *dev,
 				  struct comedi_subdevice *s,
-				  struct comedi_insn *insn, unsigned int *data)
+				  struct comedi_insn *insn,
+				  unsigned int *data)
 {
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= (data[0] | data[1]);
+	if (comedi_dio_update_state(s, data))
 		outw(s->state, dev->iobase + MIO_16_DIG_OUT_REG);
-	}
+
 	data[1] = inw(dev->iobase + MIO_16_DIG_IN_REG);
 
 	return insn->n;
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index 404f83d..e4cdca3 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -72,18 +72,22 @@
 
 static int daq700_dio_insn_bits(struct comedi_device *dev,
 				struct comedi_subdevice *s,
-				struct comedi_insn *insn, unsigned int *data)
+				struct comedi_insn *insn,
+				unsigned int *data)
 {
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
+	unsigned int mask;
+	unsigned int val;
 
-		if (data[0] & 0xff)
+	mask = comedi_dio_update_state(s, data);
+	if (mask) {
+		if (mask & 0xff)
 			outb(s->state & 0xff, dev->iobase + DIO_W);
 	}
 
-	data[1] = s->state & 0xff;
-	data[1] |= inb(dev->iobase + DIO_R) << 8;
+	val = s->state & 0xff;
+	val |= inb(dev->iobase + DIO_R) << 8;
+
+	data[1] = val;
 
 	return insn->n;
 }
@@ -212,7 +216,6 @@
 	s->maxdata	= 1;
 	s->insn_bits	= daq700_dio_insn_bits;
 	s->insn_config	= daq700_dio_insn_config;
-	s->state	= 0;
 	s->io_bits	= 0x00ff;
 
 	/* DAQCard-700 ai */
diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
index 1add114..0512445 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.c
+++ b/drivers/staging/comedi/drivers/ni_labpc.c
@@ -73,7 +73,6 @@
 #include "ni_labpc_isadma.h"
 
 #define LABPC_SIZE		0x20	/* size of ISA io region */
-#define LABPC_TIMER_BASE	500	/* 2 MHz master clock */
 #define LABPC_ADC_TIMEOUT	1000
 
 enum scan_mode {
@@ -201,12 +200,6 @@
 		return i8254_set_mode(base_address, 0, counter_number, mode);
 }
 
-static bool labpc_range_is_unipolar(struct comedi_subdevice *s,
-				    unsigned int range)
-{
-	return s->range_table->range[range].min >= 0;
-}
-
 static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct labpc_private *devpriv = dev->private;
@@ -272,7 +265,7 @@
 		devpriv->cmd6 &= ~CMD6_NRSE;
 
 	/* bipolar or unipolar range? */
-	if (labpc_range_is_unipolar(s, range))
+	if (comedi_range_is_unipolar(s, range))
 		devpriv->cmd6 |= CMD6_ADCUNI;
 	else
 		devpriv->cmd6 &= ~CMD6_ADCUNI;
@@ -465,13 +458,13 @@
 		 * clock speed on convert and scan counters)
 		 */
 		devpriv->divisor_b0 = (scan_period - 1) /
-		    (LABPC_TIMER_BASE * max_counter_value) + 1;
+		    (I8254_OSC_BASE_2MHZ * max_counter_value) + 1;
 		if (devpriv->divisor_b0 < min_counter_value)
 			devpriv->divisor_b0 = min_counter_value;
 		if (devpriv->divisor_b0 > max_counter_value)
 			devpriv->divisor_b0 = max_counter_value;
 
-		base_period = LABPC_TIMER_BASE * devpriv->divisor_b0;
+		base_period = I8254_OSC_BASE_2MHZ * devpriv->divisor_b0;
 
 		/*  set a0 for conversion frequency and b1 for scan frequency */
 		switch (cmd->flags & TRIG_ROUND_MASK) {
@@ -516,22 +509,20 @@
 		 * calculate cascaded counter values
 		 * that give desired scan timing
 		 */
-		i8253_cascade_ns_to_timer_2div(LABPC_TIMER_BASE,
-					       &(devpriv->divisor_b1),
-					       &(devpriv->divisor_b0),
-					       &scan_period,
-					       cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ,
+					  &devpriv->divisor_b1,
+					  &devpriv->divisor_b0,
+					  &scan_period, cmd->flags);
 		labpc_set_ai_scan_period(cmd, mode, scan_period);
 	} else if (convert_period) {
 		/*
 		 * calculate cascaded counter values
 		 * that give desired conversion timing
 		 */
-		i8253_cascade_ns_to_timer_2div(LABPC_TIMER_BASE,
-					       &(devpriv->divisor_a0),
-					       &(devpriv->divisor_b0),
-					       &convert_period,
-					       cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ,
+					  &devpriv->divisor_a0,
+					  &devpriv->divisor_b0,
+					  &convert_period, cmd->flags);
 		labpc_set_ai_convert_period(cmd, mode, convert_period);
 	}
 }
@@ -902,7 +893,7 @@
 static int labpc_drain_fifo(struct comedi_device *dev)
 {
 	struct labpc_private *devpriv = dev->private;
-	short data;
+	unsigned short data;
 	struct comedi_async *async = dev->read_subdev->async;
 	const int timeout = 10000;
 	unsigned int i;
@@ -1046,7 +1037,7 @@
 	/* set range */
 	if (board->is_labpc1200) {
 		range = CR_RANGE(insn->chanspec);
-		if (labpc_range_is_unipolar(s, range))
+		if (comedi_range_is_unipolar(s, range))
 			devpriv->cmd6 |= CMD6_DACUNI(channel);
 		else
 			devpriv->cmd6 &= ~CMD6_DACUNI(channel);
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index 4e02770..5113397 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -1292,7 +1292,7 @@
 	struct comedi_cmd *cmd = &async->cmd;
 	int chan;
 	int i;
-	short d;
+	unsigned short d;
 	u32 packed_data;
 	int range;
 	int err = 1;
@@ -1403,7 +1403,7 @@
 	int i;
 
 	if (board->reg_type == ni_reg_611x) {
-		short data[2];
+		unsigned short data[2];
 		u32 dl;
 
 		for (i = 0; i < n / 2; i++) {
@@ -1420,7 +1420,7 @@
 			cfc_write_to_buffer(s, data[0]);
 		}
 	} else if (board->reg_type == ni_reg_6143) {
-		short data[2];
+		unsigned short data[2];
 		u32 dl;
 
 		/*  This just reads the FIFO assuming the data is present, no checks on the FIFO status are performed */
@@ -1511,9 +1511,9 @@
 	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
-	short data[2];
+	unsigned short data[2];
 	u32 dl;
-	short fifo_empty;
+	unsigned short fifo_empty;
 	int i;
 
 	if (board->reg_type == ni_reg_611x) {
@@ -1577,7 +1577,7 @@
 	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv __maybe_unused = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
-	short data;
+	unsigned short data;
 	u32 dl;
 
 	if (board->reg_type != ni_reg_611x)
@@ -1596,7 +1596,7 @@
 	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv __maybe_unused = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV];
-	short data;
+	unsigned short data;
 	u32 dl;
 
 	if (board->reg_type != ni_reg_6143)
@@ -1621,7 +1621,7 @@
 	struct comedi_async *async = s->async;
 	unsigned int i;
 	unsigned int length = num_bytes / bytes_per_sample(s);
-	short *array = data;
+	unsigned short *array = data;
 	unsigned int *larray = data;
 
 	for (i = 0; i < length; i++) {
@@ -2873,7 +2873,7 @@
 	unsigned int i;
 	unsigned int offset;
 	unsigned int length = num_bytes / sizeof(short);
-	short *array = data;
+	unsigned short *array = data;
 
 	offset = 1 << (board->aobits - 1);
 	for (i = 0; i < length; i++) {
@@ -3547,28 +3547,22 @@
 
 static int ni_dio_insn_bits(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data)
+			    struct comedi_insn *insn,
+			    unsigned int *data)
 {
 	struct ni_private *devpriv = dev->private;
 
-#ifdef DEBUG_DIO
-	printk("ni_dio_insn_bits() mask=0x%x bits=0x%x\n", data[0], data[1]);
-#endif
+	/* Make sure we're not using the serial part of the dio */
+	if ((data[0] & (DIO_SDIN | DIO_SDOUT)) && devpriv->serial_interval_ns)
+		return -EBUSY;
 
-	if (data[0]) {
-		/* Perform check to make sure we're not using the
-		   serial part of the dio */
-		if ((data[0] & (DIO_SDIN | DIO_SDOUT))
-		    && devpriv->serial_interval_ns)
-			return -EBUSY;
-
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
+	if (comedi_dio_update_state(s, data)) {
 		devpriv->dio_output &= ~DIO_Parallel_Data_Mask;
 		devpriv->dio_output |= DIO_Parallel_Data_Out(s->state);
 		devpriv->stc_writew(dev, devpriv->dio_output,
 				    DIO_Output_Register);
 	}
+
 	data[1] = devpriv->stc_readw(dev, DIO_Parallel_Input_Register);
 
 	return insn->n;
@@ -3598,16 +3592,9 @@
 {
 	struct ni_private *devpriv __maybe_unused = dev->private;
 
-#ifdef DEBUG_DIO
-	printk("ni_m_series_dio_insn_bits() mask=0x%x bits=0x%x\n", data[0],
-	       data[1]);
-#endif
-
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
+	if (comedi_dio_update_state(s, data))
 		ni_writel(s->state, M_Offset_Static_Digital_Output);
-	}
+
 	data[1] = ni_readl(M_Offset_Static_Digital_Input);
 
 	return insn->n;
@@ -5355,20 +5342,20 @@
 
 static int ni_pfi_insn_bits(struct comedi_device *dev,
 			    struct comedi_subdevice *s,
-			    struct comedi_insn *insn, unsigned int *data)
+			    struct comedi_insn *insn,
+			    unsigned int *data)
 {
 	const struct ni_board_struct *board = comedi_board(dev);
 	struct ni_private *devpriv __maybe_unused = dev->private;
 
-	if ((board->reg_type & ni_reg_m_series_mask) == 0) {
+	if (!(board->reg_type & ni_reg_m_series_mask))
 		return -ENOTSUPP;
-	}
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
+
+	if (comedi_dio_update_state(s, data))
 		ni_writew(s->state, M_Offset_PFI_DO);
-	}
+
 	data[1] = ni_readw(M_Offset_PFI_DI);
+
 	return insn->n;
 }
 
diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
index fad81bc..e3a8fa9 100644
--- a/drivers/staging/comedi/drivers/ni_pcidio.c
+++ b/drivers/staging/comedi/drivers/ni_pcidio.c
@@ -406,9 +406,9 @@
 	struct mite_struct *mite = devpriv->mite;
 
 	/* int i, j; */
-	long int AuxData = 0;
-	short data1 = 0;
-	short data2 = 0;
+	unsigned int auxdata = 0;
+	unsigned short data1 = 0;
+	unsigned short data2 = 0;
 	int flags;
 	int status;
 	int work = 0;
@@ -481,11 +481,11 @@
 					      );
 					goto out;
 				}
-				AuxData =
+				auxdata =
 				    readl(devpriv->mite->daq_io_addr +
 					  Group_1_FIFO);
-				data1 = AuxData & 0xffff;
-				data2 = (AuxData & 0xffff0000) >> 16;
+				data1 = auxdata & 0xffff;
+				data2 = (auxdata & 0xffff0000) >> 16;
 				comedi_buf_put(async, data1);
 				comedi_buf_put(async, data2);
 				/* DPRINTK("read:%d, %d\n",data1,data2); */
@@ -657,15 +657,14 @@
 
 static int ni_pcidio_insn_bits(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
 	struct nidio96_private *devpriv = dev->private;
 
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= (data[0] & data[1]);
+	if (comedi_dio_update_state(s, data))
 		writel(s->state, devpriv->mite->daq_io_addr + Port_IO(0));
-	}
+
 	data[1] = readl(devpriv->mite->daq_io_addr + Port_IO(0));
 
 	return insn->n;
diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h
index 11bf0aa..f0630b78 100644
--- a/drivers/staging/comedi/drivers/ni_stc.h
+++ b/drivers/staging/comedi/drivers/ni_stc.h
@@ -1491,7 +1491,7 @@
 	unsigned short pwm_up_count;	\
 	unsigned short pwm_down_count;	\
 	\
-	short ai_fifo_buffer[0x2000];				\
+	unsigned short ai_fifo_buffer[0x2000];			\
 	uint8_t eeprom_buffer[M_SERIES_EEPROM_SIZE]; \
 	uint32_t serial_number; \
 	\
diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
index e859f85..f0fc123 100644
--- a/drivers/staging/comedi/drivers/pcl711.c
+++ b/drivers/staging/comedi/drivers/pcl711.c
@@ -1,258 +1,295 @@
 /*
-   comedi/drivers/pcl711.c
-   hardware driver for PC-LabCard PCL-711 and AdSys ACL-8112
-   and compatibles
-
-   COMEDI - Linux Control and Measurement Device Interface
-   Copyright (C) 1998 David A. Schleef <ds@schleef.org>
-   Janne Jalkanen <jalkanen@cs.hut.fi>
-   Eric Bunn <ebu@cs.hut.fi>
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
+ * pcl711.c
+ * Comedi driver for PC-LabCard PCL-711 and AdSys ACL-8112 and compatibles
+ * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
+ *		      Janne Jalkanen <jalkanen@cs.hut.fi>
+ *		      Eric Bunn <ebu@cs.hut.fi>
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
-/*
-Driver: pcl711
-Description: Advantech PCL-711 and 711b, ADLink ACL-8112
-Author: ds, Janne Jalkanen <jalkanen@cs.hut.fi>, Eric Bunn <ebu@cs.hut.fi>
-Status: mostly complete
-Devices: [Advantech] PCL-711 (pcl711), PCL-711B (pcl711b),
-  [AdLink] ACL-8112HG (acl8112hg), ACL-8112DG (acl8112dg)
-
-Since these boards do not have DMA or FIFOs, only immediate mode is
-supported.
-
-*/
 
 /*
-   Dave Andruczyk <dave@tech.buffalostate.edu> also wrote a
-   driver for the PCL-711.  I used a few ideas from his driver
-   here.  His driver also has more comments, if you are
-   interested in understanding how this driver works.
-   http://tech.buffalostate.edu/~dave/driver/
-
-   The ACL-8112 driver was hacked from the sources of the PCL-711
-   driver (the 744 chip used on the 8112 is almost the same as
-   the 711b chip, but it has more I/O channels) by
-   Janne Jalkanen (jalkanen@cs.hut.fi) and
-   Erik Bunn (ebu@cs.hut.fi).  Remerged with the PCL-711 driver
-   by ds.
-
-   [acl-8112]
-   This driver supports both TRIGNOW and TRIGCLK,
-   but does not yet support DMA transfers.  It also supports
-   both high (HG) and low (DG) versions of the card, though
-   the HG version has been untested.
-
+ * Driver: pcl711
+ * Description: Advantech PCL-711 and 711b, ADLink ACL-8112
+ * Devices: (Advantech) PCL-711 [pcl711]
+ *	    (Advantech) PCL-711B [pcl711b]
+ *	    (AdLink) ACL-8112HG [acl8112hg]
+ *	    (AdLink) ACL-8112DG [acl8112dg]
+ * Author: David A. Schleef <ds@schleef.org>
+ *	   Janne Jalkanen <jalkanen@cs.hut.fi>
+ *	   Eric Bunn <ebu@cs.hut.fi>
+ * Updated:
+ * Status: mostly complete
+ *
+ * Configuration Options:
+ *   [0] - I/O port base
+ *   [1] - IRQ, optional
  */
 
 #include <linux/module.h>
-#include <linux/interrupt.h>
-#include "../comedidev.h"
-
 #include <linux/delay.h>
+#include <linux/interrupt.h>
+
+#include "../comedidev.h"
 
 #include "comedi_fc.h"
 #include "8253.h"
 
-#define PCL711_SIZE 16
-
-#define PCL711_CTR0 0
-#define PCL711_CTR1 1
-#define PCL711_CTR2 2
-#define PCL711_CTRCTL 3
-#define PCL711_AD_LO 4
-#define PCL711_DA0_LO 4
-#define PCL711_AD_HI 5
-#define PCL711_DA0_HI 5
-#define PCL711_DI_LO 6
-#define PCL711_DA1_LO 6
-#define PCL711_DI_HI 7
-#define PCL711_DA1_HI 7
-#define PCL711_CLRINTR 8
-#define PCL711_GAIN 9
-#define PCL711_MUX 10
-#define PCL711_MODE 11
-#define PCL711_SOFTTRIG 12
-#define PCL711_DO_LO 13
-#define PCL711_DO_HI 14
-
-static const struct comedi_lrange range_pcl711b_ai = { 5, {
-							   BIP_RANGE(5),
-							   BIP_RANGE(2.5),
-							   BIP_RANGE(1.25),
-							   BIP_RANGE(0.625),
-							   BIP_RANGE(0.3125)
-							   }
-};
-
-static const struct comedi_lrange range_acl8112hg_ai = { 12, {
-							      BIP_RANGE(5),
-							      BIP_RANGE(0.5),
-							      BIP_RANGE(0.05),
-							      BIP_RANGE(0.005),
-							      UNI_RANGE(10),
-							      UNI_RANGE(1),
-							      UNI_RANGE(0.1),
-							      UNI_RANGE(0.01),
-							      BIP_RANGE(10),
-							      BIP_RANGE(1),
-							      BIP_RANGE(0.1),
-							      BIP_RANGE(0.01)
-							      }
-};
-
-static const struct comedi_lrange range_acl8112dg_ai = { 9, {
-							     BIP_RANGE(5),
-							     BIP_RANGE(2.5),
-							     BIP_RANGE(1.25),
-							     BIP_RANGE(0.625),
-							     UNI_RANGE(10),
-							     UNI_RANGE(5),
-							     UNI_RANGE(2.5),
-							     UNI_RANGE(1.25),
-							     BIP_RANGE(10)
-							     }
-};
-
 /*
- * flags
+ * I/O port register map
  */
+#define PCL711_TIMER_BASE	0x00
+#define PCL711_AI_LSB_REG	0x04
+#define PCL711_AI_MSB_REG	0x05
+#define PCL711_AI_MSB_DRDY	(1 << 4)
+#define PCL711_AO_LSB_REG(x)	(0x04 + ((x) * 2))
+#define PCL711_AO_MSB_REG(x)	(0x05 + ((x) * 2))
+#define PCL711_DI_LSB_REG	0x06
+#define PCL711_DI_MSB_REG	0x07
+#define PCL711_INT_STAT_REG	0x08
+#define PCL711_INT_STAT_CLR	(0 << 0)  /* any value will work */
+#define PCL711_AI_GAIN_REG	0x09
+#define PCL711_AI_GAIN(x)	(((x) & 0xf) << 0)
+#define PCL711_MUX_REG		0x0a
+#define PCL711_MUX_CHAN(x)	(((x) & 0xf) << 0)
+#define PCL711_MUX_CS0		(1 << 4)
+#define PCL711_MUX_CS1		(1 << 5)
+#define PCL711_MUX_DIFF		(PCL711_MUX_CS0 | PCL711_MUX_CS1)
+#define PCL711_MODE_REG		0x0b
+#define PCL711_MODE_DEFAULT	(0 << 0)
+#define PCL711_MODE_SOFTTRIG	(1 << 0)
+#define PCL711_MODE_EXT		(2 << 0)
+#define PCL711_MODE_EXT_IRQ	(3 << 0)
+#define PCL711_MODE_PACER	(4 << 0)
+#define PCL711_MODE_PACER_IRQ	(6 << 0)
+#define PCL711_MODE_IRQ(x)	(((x) & 0x7) << 4)
+#define PCL711_SOFTTRIG_REG	0x0c
+#define PCL711_SOFTTRIG		(0 << 0)  /* any value will work */
+#define PCL711_DO_LSB_REG	0x0d
+#define PCL711_DO_MSB_REG	0x0e
 
-#define PCL711_TIMEOUT 100
-#define PCL711_DRDY 0x10
+static const struct comedi_lrange range_pcl711b_ai = {
+	5, {
+		BIP_RANGE(5),
+		BIP_RANGE(2.5),
+		BIP_RANGE(1.25),
+		BIP_RANGE(0.625),
+		BIP_RANGE(0.3125)
+	}
+};
 
-static const int i8253_osc_base = 500;	/* 2 Mhz */
+static const struct comedi_lrange range_acl8112hg_ai = {
+	12, {
+		BIP_RANGE(5),
+		BIP_RANGE(0.5),
+		BIP_RANGE(0.05),
+		BIP_RANGE(0.005),
+		UNI_RANGE(10),
+		UNI_RANGE(1),
+		UNI_RANGE(0.1),
+		UNI_RANGE(0.01),
+		BIP_RANGE(10),
+		BIP_RANGE(1),
+		BIP_RANGE(0.1),
+		BIP_RANGE(0.01)
+	}
+};
+
+static const struct comedi_lrange range_acl8112dg_ai = {
+	9, {
+		BIP_RANGE(5),
+		BIP_RANGE(2.5),
+		BIP_RANGE(1.25),
+		BIP_RANGE(0.625),
+		UNI_RANGE(10),
+		UNI_RANGE(5),
+		UNI_RANGE(2.5),
+		UNI_RANGE(1.25),
+		BIP_RANGE(10)
+	}
+};
 
 struct pcl711_board {
-
 	const char *name;
-	int is_pcl711b;
-	int is_8112;
-	int is_dg;
-	int n_ranges;
 	int n_aichan;
 	int n_aochan;
 	int maxirq;
 	const struct comedi_lrange *ai_range_type;
 };
 
-struct pcl711_private {
+static const struct pcl711_board boardtypes[] = {
+	{
+		.name		= "pcl711",
+		.n_aichan	= 8,
+		.n_aochan	= 1,
+		.ai_range_type	= &range_bipolar5,
+	}, {
+		.name		= "pcl711b",
+		.n_aichan	= 8,
+		.n_aochan	= 1,
+		.maxirq		= 7,
+		.ai_range_type	= &range_pcl711b_ai,
+	}, {
+		.name		= "acl8112hg",
+		.n_aichan	= 16,
+		.n_aochan	= 2,
+		.maxirq		= 15,
+		.ai_range_type	= &range_acl8112hg_ai,
+	}, {
+		.name		= "acl8112dg",
+		.n_aichan	= 16,
+		.n_aochan	= 2,
+		.maxirq		= 15,
+		.ai_range_type	= &range_acl8112dg_ai,
+	},
+};
 
-	int board;
-	int adchan;
-	int ntrig;
-	int aip[8];
-	int mode;
+struct pcl711_private {
+	unsigned int ntrig;
 	unsigned int ao_readback[2];
 	unsigned int divisor1;
 	unsigned int divisor2;
 };
 
+static void pcl711_ai_set_mode(struct comedi_device *dev, unsigned int mode)
+{
+	/*
+	 * The pcl711b board uses bits in the mode register to select the
+	 * interrupt. The other boards supported by this driver all use
+	 * jumpers on the board.
+	 *
+	 * Enables the interrupt when needed on the pcl711b board. These
+	 * bits do nothing on the other boards.
+	 */
+	if (mode == PCL711_MODE_EXT_IRQ || mode == PCL711_MODE_PACER_IRQ)
+		mode |= PCL711_MODE_IRQ(dev->irq);
+
+	outb(mode, dev->iobase + PCL711_MODE_REG);
+}
+
+static unsigned int pcl711_ai_get_sample(struct comedi_device *dev,
+					 struct comedi_subdevice *s)
+{
+	unsigned int val;
+
+	val = inb(dev->iobase + PCL711_AI_MSB_REG) << 8;
+	val |= inb(dev->iobase + PCL711_AI_LSB_REG);
+
+	return val & s->maxdata;
+}
+
+static int pcl711_ai_cancel(struct comedi_device *dev,
+			    struct comedi_subdevice *s)
+{
+	outb(PCL711_INT_STAT_CLR, dev->iobase + PCL711_INT_STAT_REG);
+	pcl711_ai_set_mode(dev, PCL711_MODE_SOFTTRIG);
+	return 0;
+}
+
 static irqreturn_t pcl711_interrupt(int irq, void *d)
 {
-	int lo, hi;
-	int data;
 	struct comedi_device *dev = d;
-	const struct pcl711_board *board = comedi_board(dev);
 	struct pcl711_private *devpriv = dev->private;
-	struct comedi_subdevice *s = &dev->subdevices[0];
+	struct comedi_subdevice *s = dev->read_subdev;
+	unsigned int data;
 
 	if (!dev->attached) {
 		comedi_error(dev, "spurious interrupt");
 		return IRQ_HANDLED;
 	}
 
-	hi = inb(dev->iobase + PCL711_AD_HI);
-	lo = inb(dev->iobase + PCL711_AD_LO);
-	outb(0, dev->iobase + PCL711_CLRINTR);
+	data = pcl711_ai_get_sample(dev, s);
 
-	data = (hi << 8) | lo;
+	outb(PCL711_INT_STAT_CLR, dev->iobase + PCL711_INT_STAT_REG);
 
-	/* FIXME! Nothing else sets ntrig! */
-	if (!(--devpriv->ntrig)) {
-		if (board->is_8112)
-			outb(1, dev->iobase + PCL711_MODE);
-		else
-			outb(0, dev->iobase + PCL711_MODE);
-
-		s->async->events |= COMEDI_CB_EOA;
+	if (comedi_buf_put(s->async, data) == 0) {
+		s->async->events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
+	} else {
+		s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
+		if (s->async->cmd.stop_src == TRIG_COUNT &&
+		    !(--devpriv->ntrig)) {
+			pcl711_ai_set_mode(dev, PCL711_MODE_SOFTTRIG);
+			s->async->events |= COMEDI_CB_EOA;
+		}
 	}
 	comedi_event(dev, s);
 	return IRQ_HANDLED;
 }
 
-static void pcl711_set_changain(struct comedi_device *dev, int chan)
+static void pcl711_set_changain(struct comedi_device *dev,
+				struct comedi_subdevice *s,
+				unsigned int chanspec)
 {
-	const struct pcl711_board *board = comedi_board(dev);
-	int chan_register;
+	unsigned int chan = CR_CHAN(chanspec);
+	unsigned int range = CR_RANGE(chanspec);
+	unsigned int aref = CR_AREF(chanspec);
+	unsigned int mux = 0;
 
-	outb(CR_RANGE(chan), dev->iobase + PCL711_GAIN);
+	outb(PCL711_AI_GAIN(range), dev->iobase + PCL711_AI_GAIN_REG);
 
-	chan_register = CR_CHAN(chan);
-
-	if (board->is_8112) {
-
-		/*
-		 *  Set the correct channel.  The two channel banks are switched
-		 *  using the mask value.
-		 *  NB: To use differential channels, you should use
-		 *  mask = 0x30, but I haven't written the support for this
-		 *  yet. /JJ
-		 */
-
-		if (chan_register >= 8)
-			chan_register = 0x20 | (chan_register & 0x7);
-		else
-			chan_register |= 0x10;
-	} else {
-		outb(chan_register, dev->iobase + PCL711_MUX);
+	if (s->n_chan > 8) {
+		/* Select the correct MPC508A chip */
+		if (aref == AREF_DIFF) {
+			chan &= 0x7;
+			mux |= PCL711_MUX_DIFF;
+		} else {
+			if (chan < 8)
+				mux |= PCL711_MUX_CS0;
+			else
+				mux |= PCL711_MUX_CS1;
+		}
 	}
+	outb(mux | PCL711_MUX_CHAN(chan), dev->iobase + PCL711_MUX_REG);
 }
 
-static int pcl711_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data)
+static int pcl711_ai_wait_for_eoc(struct comedi_device *dev,
+				  unsigned int timeout)
 {
-	const struct pcl711_board *board = comedi_board(dev);
-	int i, n;
-	int hi, lo;
+	unsigned int msb;
 
-	pcl711_set_changain(dev, insn->chanspec);
+	while (timeout--) {
+		msb = inb(dev->iobase + PCL711_AI_MSB_REG);
+		if ((msb & PCL711_AI_MSB_DRDY) == 0)
+			return 0;
+		udelay(1);
+	}
+	return -ETIME;
+}
 
-	for (n = 0; n < insn->n; n++) {
-		/*
-		 *  Write the correct mode (software polling) and start polling
-		 *  by writing to the trigger register
-		 */
-		outb(1, dev->iobase + PCL711_MODE);
+static int pcl711_ai_insn_read(struct comedi_device *dev,
+			       struct comedi_subdevice *s,
+			       struct comedi_insn *insn,
+			       unsigned int *data)
+{
+	int ret;
+	int i;
 
-		if (!board->is_8112)
-			outb(0, dev->iobase + PCL711_SOFTTRIG);
+	pcl711_set_changain(dev, s, insn->chanspec);
 
-		i = PCL711_TIMEOUT;
-		while (--i) {
-			hi = inb(dev->iobase + PCL711_AD_HI);
-			if (!(hi & PCL711_DRDY))
-				goto ok;
-			udelay(1);
-		}
-		printk(KERN_ERR "comedi%d: pcl711: A/D timeout\n", dev->minor);
-		return -ETIME;
+	pcl711_ai_set_mode(dev, PCL711_MODE_SOFTTRIG);
 
-ok:
-		lo = inb(dev->iobase + PCL711_AD_LO);
+	for (i = 0; i < insn->n; i++) {
+		outb(PCL711_SOFTTRIG, dev->iobase + PCL711_SOFTTRIG_REG);
 
-		data[n] = ((hi & 0xf) << 8) | lo;
+		ret = pcl711_ai_wait_for_eoc(dev, 100);
+		if (ret)
+			return ret;
+
+		data[i] = pcl711_ai_get_sample(dev, s);
 	}
 
-	return n;
+	return insn->n;
 }
 
 static int pcl711_ai_cmdtest(struct comedi_device *dev,
@@ -292,7 +329,6 @@
 		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 	} else {
 #define MAX_SPEED 1000
-#define TIMER_BASE 100
 		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
 						 MAX_SPEED);
 	}
@@ -313,11 +349,11 @@
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		tmp = cmd->scan_begin_arg;
-		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
-					       &devpriv->divisor1,
-					       &devpriv->divisor2,
-					       &cmd->scan_begin_arg,
-					       cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ,
+					  &devpriv->divisor1,
+					  &devpriv->divisor2,
+					  &cmd->scan_begin_arg,
+					  cmd->flags);
 		if (tmp != cmd->scan_begin_arg)
 			err++;
 	}
@@ -331,110 +367,106 @@
 static int pcl711_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct pcl711_private *devpriv = dev->private;
-	int timer1, timer2;
 	struct comedi_cmd *cmd = &s->async->cmd;
 
-	pcl711_set_changain(dev, cmd->chanlist[0]);
+	pcl711_set_changain(dev, s, cmd->chanlist[0]);
+
+	if (cmd->stop_src == TRIG_COUNT) {
+		if (cmd->stop_arg == 0) {
+			/* an empty acquisition */
+			s->async->events |= COMEDI_CB_EOA;
+			comedi_event(dev, s);
+			return 0;
+		}
+		devpriv->ntrig = cmd->stop_arg;
+	}
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
-		/*
-		 *  Set timers
-		 *      timer chip is an 8253, with timers 1 and 2
-		 *      cascaded
-		 *  0x74 = Select Counter 1 | LSB/MSB | Mode=2 | Binary
-		 *        Mode 2 = Rate generator
-		 *
-		 *  0xb4 = Select Counter 2 | LSB/MSB | Mode=2 | Binary
-		 */
+		i8254_load(dev->iobase + PCL711_TIMER_BASE, 0,
+			   1, devpriv->divisor1, I8254_MODE2 | I8254_BINARY);
+		i8254_load(dev->iobase + PCL711_TIMER_BASE, 0,
+			   2, devpriv->divisor2, I8254_MODE2 | I8254_BINARY);
 
-		timer1 = timer2 = 0;
-		i8253_cascade_ns_to_timer(i8253_osc_base, &timer1, &timer2,
-					  &cmd->scan_begin_arg,
-					  TRIG_ROUND_NEAREST);
+		outb(PCL711_INT_STAT_CLR, dev->iobase + PCL711_INT_STAT_REG);
 
-		outb(0x74, dev->iobase + PCL711_CTRCTL);
-		outb(timer1 & 0xff, dev->iobase + PCL711_CTR1);
-		outb((timer1 >> 8) & 0xff, dev->iobase + PCL711_CTR1);
-		outb(0xb4, dev->iobase + PCL711_CTRCTL);
-		outb(timer2 & 0xff, dev->iobase + PCL711_CTR2);
-		outb((timer2 >> 8) & 0xff, dev->iobase + PCL711_CTR2);
-
-		/* clear pending interrupts (just in case) */
-		outb(0, dev->iobase + PCL711_CLRINTR);
-
-		/*
-		 *  Set mode to IRQ transfer
-		 */
-		outb(devpriv->mode | 6, dev->iobase + PCL711_MODE);
+		pcl711_ai_set_mode(dev, PCL711_MODE_PACER_IRQ);
 	} else {
-		/* external trigger */
-		outb(devpriv->mode | 3, dev->iobase + PCL711_MODE);
+		pcl711_ai_set_mode(dev, PCL711_MODE_EXT_IRQ);
 	}
 
 	return 0;
 }
 
-/*
-   analog output
-*/
-static int pcl711_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data)
+static void pcl711_ao_write(struct comedi_device *dev,
+			    unsigned int chan, unsigned int val)
+{
+	outb(val & 0xff, dev->iobase + PCL711_AO_LSB_REG(chan));
+	outb((val >> 8) & 0xff, dev->iobase + PCL711_AO_MSB_REG(chan));
+}
+
+static int pcl711_ao_insn_write(struct comedi_device *dev,
+				struct comedi_subdevice *s,
+				struct comedi_insn *insn,
+				unsigned int *data)
 {
 	struct pcl711_private *devpriv = dev->private;
-	int n;
-	int chan = CR_CHAN(insn->chanspec);
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int val = devpriv->ao_readback[chan];
+	int i;
 
-	for (n = 0; n < insn->n; n++) {
-		outb((data[n] & 0xff),
-		     dev->iobase + (chan ? PCL711_DA1_LO : PCL711_DA0_LO));
-		outb((data[n] >> 8),
-		     dev->iobase + (chan ? PCL711_DA1_HI : PCL711_DA0_HI));
-
-		devpriv->ao_readback[chan] = data[n];
+	for (i = 0; i < insn->n; i++) {
+		val = data[i];
+		pcl711_ao_write(dev, chan, val);
 	}
-
-	return n;
-}
-
-static int pcl711_ao_insn_read(struct comedi_device *dev,
-			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
-{
-	struct pcl711_private *devpriv = dev->private;
-	int n;
-	int chan = CR_CHAN(insn->chanspec);
-
-	for (n = 0; n < insn->n; n++)
-		data[n] = devpriv->ao_readback[chan];
-
-	return n;
-
-}
-
-/* Digital port read - Untested on 8112 */
-static int pcl711_di_insn_bits(struct comedi_device *dev,
-			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
-{
-	data[1] = inb(dev->iobase + PCL711_DI_LO) |
-	    (inb(dev->iobase + PCL711_DI_HI) << 8);
+	devpriv->ao_readback[chan] = val;
 
 	return insn->n;
 }
 
-/* Digital port write - Untested on 8112 */
+static int pcl711_ao_insn_read(struct comedi_device *dev,
+			       struct comedi_subdevice *s,
+			       struct comedi_insn *insn,
+			       unsigned int *data)
+{
+	struct pcl711_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	int i;
+
+	for (i = 0; i < insn->n; i++)
+		data[i] = devpriv->ao_readback[chan];
+
+	return insn->n;
+}
+
+static int pcl711_di_insn_bits(struct comedi_device *dev,
+			       struct comedi_subdevice *s,
+			       struct comedi_insn *insn,
+			       unsigned int *data)
+{
+	unsigned int val;
+
+	val = inb(dev->iobase + PCL711_DI_LSB_REG);
+	val |= (inb(dev->iobase + PCL711_DI_MSB_REG) << 8);
+
+	data[1] = val;
+
+	return insn->n;
+}
+
 static int pcl711_do_insn_bits(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= data[0] & data[1];
+	unsigned int mask;
+
+	mask = comedi_dio_update_state(s, data);
+	if (mask) {
+		if (mask & 0x00ff)
+			outb(s->state & 0xff, dev->iobase + PCL711_DO_LSB_REG);
+		if (mask & 0xff00)
+			outb((s->state >> 8), dev->iobase + PCL711_DO_MSB_REG);
 	}
-	if (data[0] & 0x00ff)
-		outb(s->state & 0xff, dev->iobase + PCL711_DO_LO);
-	if (data[0] & 0xff00)
-		outb((s->state >> 8), dev->iobase + PCL711_DO_HI);
 
 	data[1] = s->state;
 
@@ -445,112 +477,82 @@
 {
 	const struct pcl711_board *board = comedi_board(dev);
 	struct pcl711_private *devpriv;
-	int ret;
-	unsigned int irq;
 	struct comedi_subdevice *s;
-
-	ret = comedi_request_region(dev, it->options[0], PCL711_SIZE);
-	if (ret)
-		return ret;
-
-	/* grab our IRQ */
-	irq = it->options[1];
-	if (irq > board->maxirq) {
-		printk(KERN_ERR "irq out of range\n");
-		return -EINVAL;
-	}
-	if (irq) {
-		if (request_irq(irq, pcl711_interrupt, 0, dev->board_name,
-			        dev)) {
-			printk(KERN_ERR "unable to allocate irq %u\n", irq);
-			return -EINVAL;
-		} else {
-			printk(KERN_INFO "( irq = %u )\n", irq);
-		}
-	}
-	dev->irq = irq;
-
-	ret = comedi_alloc_subdevices(dev, 4);
-	if (ret)
-		return ret;
+	int ret;
 
 	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 	if (!devpriv)
 		return -ENOMEM;
 
-	s = &dev->subdevices[0];
-	/* AI subdevice */
-	s->type = COMEDI_SUBD_AI;
-	s->subdev_flags = SDF_READABLE | SDF_GROUND;
-	s->n_chan = board->n_aichan;
-	s->maxdata = 0xfff;
-	s->len_chanlist = 1;
-	s->range_table = board->ai_range_type;
-	s->insn_read = pcl711_ai_insn;
-	if (irq) {
-		dev->read_subdev = s;
-		s->subdev_flags |= SDF_CMD_READ;
-		s->do_cmdtest = pcl711_ai_cmdtest;
-		s->do_cmd = pcl711_ai_cmd;
+	ret = comedi_request_region(dev, it->options[0], 0x10);
+	if (ret)
+		return ret;
+
+	if (it->options[1] && it->options[1] <= board->maxirq) {
+		ret = request_irq(it->options[1], pcl711_interrupt, 0,
+				  dev->board_name, dev);
+		if (ret == 0)
+			dev->irq = it->options[1];
 	}
 
+	ret = comedi_alloc_subdevices(dev, 4);
+	if (ret)
+		return ret;
+
+	/* Analog Input subdevice */
+	s = &dev->subdevices[0];
+	s->type		= COMEDI_SUBD_AI;
+	s->subdev_flags	= SDF_READABLE | SDF_GROUND;
+	if (board->n_aichan > 8)
+		s->subdev_flags	|= SDF_DIFF;
+	s->n_chan	= board->n_aichan;
+	s->maxdata	= 0xfff;
+	s->range_table	= board->ai_range_type;
+	s->insn_read	= pcl711_ai_insn_read;
+	if (dev->irq) {
+		dev->read_subdev = s;
+		s->subdev_flags	|= SDF_CMD_READ;
+		s->len_chanlist	= 1;
+		s->do_cmdtest	= pcl711_ai_cmdtest;
+		s->do_cmd	= pcl711_ai_cmd;
+		s->cancel	= pcl711_ai_cancel;
+	}
+
+	/* Analog Output subdevice */
 	s = &dev->subdevices[1];
-	/* AO subdevice */
-	s->type = COMEDI_SUBD_AO;
-	s->subdev_flags = SDF_WRITABLE;
-	s->n_chan = board->n_aochan;
-	s->maxdata = 0xfff;
-	s->len_chanlist = 1;
-	s->range_table = &range_bipolar5;
-	s->insn_write = pcl711_ao_insn;
-	s->insn_read = pcl711_ao_insn_read;
+	s->type		= COMEDI_SUBD_AO;
+	s->subdev_flags	= SDF_WRITABLE;
+	s->n_chan	= board->n_aochan;
+	s->maxdata	= 0xfff;
+	s->range_table	= &range_bipolar5;
+	s->insn_write	= pcl711_ao_insn_write;
+	s->insn_read	= pcl711_ao_insn_read;
 
+	/* Digital Input subdevice */
 	s = &dev->subdevices[2];
-	/* 16-bit digital input */
-	s->type = COMEDI_SUBD_DI;
-	s->subdev_flags = SDF_READABLE;
-	s->n_chan = 16;
-	s->maxdata = 1;
-	s->len_chanlist = 16;
-	s->range_table = &range_digital;
-	s->insn_bits = pcl711_di_insn_bits;
+	s->type		= COMEDI_SUBD_DI;
+	s->subdev_flags	= SDF_READABLE;
+	s->n_chan	= 16;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= pcl711_di_insn_bits;
 
+	/* Digital Output subdevice */
 	s = &dev->subdevices[3];
-	/* 16-bit digital out */
-	s->type = COMEDI_SUBD_DO;
-	s->subdev_flags = SDF_WRITABLE;
-	s->n_chan = 16;
-	s->maxdata = 1;
-	s->len_chanlist = 16;
-	s->range_table = &range_digital;
-	s->state = 0;
-	s->insn_bits = pcl711_do_insn_bits;
-
-	/*
-	   this is the "base value" for the mode register, which is
-	   used for the irq on the PCL711
-	 */
-	if (board->is_pcl711b)
-		devpriv->mode = (dev->irq << 4);
+	s->type		= COMEDI_SUBD_DO;
+	s->subdev_flags	= SDF_WRITABLE;
+	s->n_chan	= 16;
+	s->maxdata	= 1;
+	s->range_table	= &range_digital;
+	s->insn_bits	= pcl711_do_insn_bits;
 
 	/* clear DAC */
-	outb(0, dev->iobase + PCL711_DA0_LO);
-	outb(0, dev->iobase + PCL711_DA0_HI);
-	outb(0, dev->iobase + PCL711_DA1_LO);
-	outb(0, dev->iobase + PCL711_DA1_HI);
-
-	printk(KERN_INFO "\n");
+	pcl711_ao_write(dev, 0, 0x0);
+	pcl711_ao_write(dev, 1, 0x0);
 
 	return 0;
 }
 
-static const struct pcl711_board boardtypes[] = {
-	{ "pcl711", 0, 0, 0, 5, 8, 1, 0, &range_bipolar5 },
-	{ "pcl711b", 1, 0, 0, 5, 8, 1, 7, &range_pcl711b_ai },
-	{ "acl8112hg", 0, 1, 0, 12, 16, 2, 15, &range_acl8112hg_ai },
-	{ "acl8112dg", 0, 1, 1, 9, 16, 2, 15, &range_acl8112dg_ai },
-};
-
 static struct comedi_driver pcl711_driver = {
 	.driver_name	= "pcl711",
 	.module		= THIS_MODULE,
@@ -563,5 +565,5 @@
 module_comedi_driver(pcl711_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for PCL-711 compatible boards");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c
index a4d0bcc..cf9568e 100644
--- a/drivers/staging/comedi/drivers/pcl726.c
+++ b/drivers/staging/comedi/drivers/pcl726.c
@@ -1,230 +1,356 @@
 /*
-    comedi/drivers/pcl726.c
-
-    hardware driver for Advantech cards:
-     card:   PCL-726, PCL-727, PCL-728
-     driver: pcl726,  pcl727,  pcl728
-    and for ADLink cards:
-     card:   ACL-6126, ACL-6128
-     driver: acl6126,  acl6128
-
-    COMEDI - Linux Control and Measurement Device Interface
-    Copyright (C) 1998 David A. Schleef <ds@schleef.org>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-*/
-/*
-Driver: pcl726
-Description: Advantech PCL-726 & compatibles
-Author: ds
-Status: untested
-Devices: [Advantech] PCL-726 (pcl726), PCL-727 (pcl727), PCL-728 (pcl728),
-  [ADLink] ACL-6126 (acl6126), ACL-6128 (acl6128)
-
-Interrupts are not supported.
-
-    Options for PCL-726:
-     [0] - IO Base
-     [2]...[7] - D/A output range for channel 1-6:
-		0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V,
-		4: 4-20mA, 5: unknown (external reference)
-
-    Options for PCL-727:
-     [0] - IO Base
-     [2]...[13] - D/A output range for channel 1-12:
-		0: 0-5V, 1: 0-10V, 2: +/-5V,
-		3: 4-20mA
-
-    Options for PCL-728 and ACL-6128:
-     [0] - IO Base
-     [2], [3] - D/A output range for channel 1 and 2:
-		0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V,
-		4: 4-20mA, 5: 0-20mA
-
-    Options for ACL-6126:
-     [0] - IO Base
-     [1] - IRQ (0=disable, 3, 5, 6, 7, 9, 10, 11, 12, 15) (currently ignored)
-     [2]...[7] - D/A output range for channel 1-6:
-		0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V,
-		4: 4-20mA
-*/
+ * pcl726.c
+ * Comedi driver for 6/12-Channel D/A Output and DIO cards
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
 
 /*
-    Thanks to Circuit Specialists for having programming info (!) on
-    their web page.  (http://www.cir.com/)
-*/
+ * Driver: pcl726
+ * Description: Advantech PCL-726 & compatibles
+ * Author: David A. Schleef <ds@schleef.org>
+ * Status: untested
+ * Devices: (Advantech) PCL-726 [pcl726]
+ *	    (Advantech) PCL-727 [pcl727]
+ *	    (Advantech) PCL-728 [pcl728]
+ *	    (ADLink) ACL-6126 [acl6126]
+ *	    (ADLink) ACL-6128 [acl6128]
+ *
+ * Configuration Options:
+ *   [0]  - IO Base
+ *   [1]  - IRQ (ACL-6126 only)
+ *   [2]  - D/A output range for channel 0
+ *   [3]  - D/A output range for channel 1
+ *
+ * Boards with > 2 analog output channels:
+ *   [4]  - D/A output range for channel 2
+ *   [5]  - D/A output range for channel 3
+ *   [6]  - D/A output range for channel 4
+ *   [7]  - D/A output range for channel 5
+ *
+ * Boards with > 6 analog output channels:
+ *   [8]  - D/A output range for channel 6
+ *   [9]  - D/A output range for channel 7
+ *   [10] - D/A output range for channel 8
+ *   [11] - D/A output range for channel 9
+ *   [12] - D/A output range for channel 10
+ *   [13] - D/A output range for channel 11
+ *
+ * For PCL-726 the D/A output ranges are:
+ *   0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, 4: 4-20mA, 5: unknown
+ *
+ * For PCL-727:
+ *   0: 0-5V, 1: 0-10V, 2: +/-5V, 3: 4-20mA
+ *
+ * For PCL-728 and ACL-6128:
+ *   0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, 4: 4-20mA, 5: 0-20mA
+ *
+ * For ACL-6126:
+ *   0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, 4: 4-20mA
+ */
 
 #include <linux/module.h>
+#include <linux/interrupt.h>
+
 #include "../comedidev.h"
 
-#undef ACL6126_IRQ		/* no interrupt support (yet) */
+#include "comedi_fc.h"
 
-#define PCL726_SIZE 16
-#define PCL727_SIZE 32
-#define PCL728_SIZE 8
+#define PCL726_AO_MSB_REG(x)	(0x00 + ((x) * 2))
+#define PCL726_AO_LSB_REG(x)	(0x01 + ((x) * 2))
+#define PCL726_DO_MSB_REG	0x0c
+#define PCL726_DO_LSB_REG	0x0d
+#define PCL726_DI_MSB_REG	0x0e
+#define PCL726_DI_LSB_REG	0x0f
 
-#define PCL726_DAC0_HI 0
-#define PCL726_DAC0_LO 1
-
-#define PCL726_DO_HI 12
-#define PCL726_DO_LO 13
-#define PCL726_DI_HI 14
-#define PCL726_DI_LO 15
-
-#define PCL727_DO_HI 24
-#define PCL727_DO_LO 25
-#define PCL727_DI_HI  0
-#define PCL727_DI_LO  1
+#define PCL727_DI_MSB_REG	0x00
+#define PCL727_DI_LSB_REG	0x01
+#define PCL727_DO_MSB_REG	0x18
+#define PCL727_DO_LSB_REG	0x19
 
 static const struct comedi_lrange *const rangelist_726[] = {
-	&range_unipolar5, &range_unipolar10,
-	&range_bipolar5, &range_bipolar10,
-	&range_4_20mA, &range_unknown
+	&range_unipolar5,
+	&range_unipolar10,
+	&range_bipolar5,
+	&range_bipolar10,
+	&range_4_20mA,
+	&range_unknown
 };
 
 static const struct comedi_lrange *const rangelist_727[] = {
-	&range_unipolar5, &range_unipolar10,
+	&range_unipolar5,
+	&range_unipolar10,
 	&range_bipolar5,
 	&range_4_20mA
 };
 
 static const struct comedi_lrange *const rangelist_728[] = {
-	&range_unipolar5, &range_unipolar10,
-	&range_bipolar5, &range_bipolar10,
-	&range_4_20mA, &range_0_20mA
+	&range_unipolar5,
+	&range_unipolar10,
+	&range_bipolar5,
+	&range_bipolar10,
+	&range_4_20mA,
+	&range_0_20mA
 };
 
 struct pcl726_board {
-
-	const char *name;	/*  driver name */
-	int n_aochan;		/*  num of D/A chans */
-	int num_of_ranges;	/*  num of ranges */
-	unsigned int IRQbits;	/*  allowed interrupts */
-	unsigned int io_range;	/*  len of IO space */
-	char have_dio;		/*  1=card have DI/DO ports */
-	int di_hi;		/*  ports for DI/DO operations */
-	int di_lo;
-	int do_hi;
-	int do_lo;
-	const struct comedi_lrange *const *range_type_list;
-	/*  list of supported ranges */
+	const char *name;
+	unsigned long io_len;
+	unsigned int irq_mask;
+	const struct comedi_lrange *const *ao_ranges;
+	int ao_num_ranges;
+	int ao_nchan;
+	unsigned int have_dio:1;
+	unsigned int is_pcl727:1;
 };
 
-static const struct pcl726_board boardtypes[] = {
-	{"pcl726", 6, 6, 0x0000, PCL726_SIZE, 1,
-	 PCL726_DI_HI, PCL726_DI_LO, PCL726_DO_HI, PCL726_DO_LO,
-	 &rangelist_726[0],},
-	{"pcl727", 12, 4, 0x0000, PCL727_SIZE, 1,
-	 PCL727_DI_HI, PCL727_DI_LO, PCL727_DO_HI, PCL727_DO_LO,
-	 &rangelist_727[0],},
-	{"pcl728", 2, 6, 0x0000, PCL728_SIZE, 0,
-	 0, 0, 0, 0,
-	 &rangelist_728[0],},
-	{"acl6126", 6, 5, 0x96e8, PCL726_SIZE, 1,
-	 PCL726_DI_HI, PCL726_DI_LO, PCL726_DO_HI, PCL726_DO_LO,
-	 &rangelist_726[0],},
-	{"acl6128", 2, 6, 0x0000, PCL728_SIZE, 0,
-	 0, 0, 0, 0,
-	 &rangelist_728[0],},
+static const struct pcl726_board pcl726_boards[] = {
+	{
+		.name		= "pcl726",
+		.io_len		= 0x10,
+		.ao_ranges	= &rangelist_726[0],
+		.ao_num_ranges	= ARRAY_SIZE(rangelist_726),
+		.ao_nchan	= 6,
+		.have_dio	= 1,
+	}, {
+		.name		= "pcl727",
+		.io_len		= 0x20,
+		.ao_ranges	= &rangelist_727[0],
+		.ao_num_ranges	= ARRAY_SIZE(rangelist_727),
+		.ao_nchan	= 12,
+		.have_dio	= 1,
+		.is_pcl727	= 1,
+	}, {
+		.name		= "pcl728",
+		.io_len		= 0x08,
+		.ao_num_ranges	= ARRAY_SIZE(rangelist_728),
+		.ao_ranges	= &rangelist_728[0],
+		.ao_nchan	= 2,
+	}, {
+		.name		= "acl6126",
+		.io_len		= 0x10,
+		.irq_mask	= 0x96e8,
+		.ao_num_ranges	= ARRAY_SIZE(rangelist_726),
+		.ao_ranges	= &rangelist_726[0],
+		.ao_nchan	= 6,
+		.have_dio	= 1,
+	}, {
+		.name		= "acl6128",
+		.io_len		= 0x08,
+		.ao_num_ranges	= ARRAY_SIZE(rangelist_728),
+		.ao_ranges	= &rangelist_728[0],
+		.ao_nchan	= 2,
+	},
 };
 
 struct pcl726_private {
-
-	int bipolar[12];
 	const struct comedi_lrange *rangelist[12];
 	unsigned int ao_readback[12];
+	unsigned int cmd_running:1;
 };
 
-static int pcl726_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
-			  struct comedi_insn *insn, unsigned int *data)
+static int pcl726_intr_insn_bits(struct comedi_device *dev,
+				 struct comedi_subdevice *s,
+				 struct comedi_insn *insn,
+				 unsigned int *data)
+{
+	data[1] = 0;
+	return insn->n;
+}
+
+static int pcl726_intr_cmdtest(struct comedi_device *dev,
+			       struct comedi_subdevice *s,
+			       struct comedi_cmd *cmd)
+{
+	int err = 0;
+
+	/* Step 1 : check if triggers are trivially valid */
+
+	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+	err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+	err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
+
+	if (err)
+		return 1;
+
+	/* Step 2a : make sure trigger sources are unique */
+	/* Step 2b : and mutually compatible */
+
+	if (err)
+		return 2;
+
+	/* Step 3: check if arguments are trivially valid */
+
+	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, 1);
+	err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+
+	if (err)
+		return 3;
+
+	/* step 4: ignored */
+
+	if (err)
+		return 4;
+
+	return 0;
+}
+
+static int pcl726_intr_cmd(struct comedi_device *dev,
+			   struct comedi_subdevice *s)
 {
 	struct pcl726_private *devpriv = dev->private;
-	int hi, lo;
-	int n;
-	int chan = CR_CHAN(insn->chanspec);
 
-	for (n = 0; n < insn->n; n++) {
-		lo = data[n] & 0xff;
-		hi = (data[n] >> 8) & 0xf;
-		if (devpriv->bipolar[chan])
-			hi ^= 0x8;
-		/*
-		 * the programming info did not say which order
-		 * to write bytes.  switch the order of the next
-		 * two lines if you get glitches.
-		 */
-		outb(hi, dev->iobase + PCL726_DAC0_HI + 2 * chan);
-		outb(lo, dev->iobase + PCL726_DAC0_LO + 2 * chan);
-		devpriv->ao_readback[chan] = data[n];
+	devpriv->cmd_running = 1;
+
+	return 0;
+}
+
+static int pcl726_intr_cancel(struct comedi_device *dev,
+			      struct comedi_subdevice *s)
+{
+	struct pcl726_private *devpriv = dev->private;
+
+	devpriv->cmd_running = 0;
+
+	return 0;
+}
+
+static irqreturn_t pcl726_interrupt(int irq, void *d)
+{
+	struct comedi_device *dev = d;
+	struct comedi_subdevice *s = dev->read_subdev;
+	struct pcl726_private *devpriv = dev->private;
+
+	if (devpriv->cmd_running) {
+		pcl726_intr_cancel(dev, s);
+
+		comedi_buf_put(s->async, 0);
+		s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
+		comedi_event(dev, s);
 	}
 
-	return n;
+	return IRQ_HANDLED;
+}
+
+static int pcl726_ao_insn_write(struct comedi_device *dev,
+				struct comedi_subdevice *s,
+				struct comedi_insn *insn,
+				unsigned int *data)
+{
+	struct pcl726_private *devpriv = dev->private;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int range = CR_RANGE(insn->chanspec);
+	unsigned int val;
+	int i;
+
+	for (i = 0; i < insn->n; i++) {
+		val = data[i];
+		devpriv->ao_readback[chan] = val;
+
+		/* bipolar data to the DAC is two's complement */
+		if (comedi_chan_range_is_bipolar(s, chan, range))
+			val = comedi_offset_munge(s, val);
+
+		/* order is important, MSB then LSB */
+		outb((val >> 8) & 0xff, dev->iobase + PCL726_AO_MSB_REG(chan));
+		outb(val & 0xff, dev->iobase + PCL726_AO_LSB_REG(chan));
+	}
+
+	return insn->n;
 }
 
 static int pcl726_ao_insn_read(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
 	struct pcl726_private *devpriv = dev->private;
-	int chan = CR_CHAN(insn->chanspec);
-	int n;
+	unsigned int chan = CR_CHAN(insn->chanspec);
+	int i;
 
-	for (n = 0; n < insn->n; n++)
-		data[n] = devpriv->ao_readback[chan];
-	return n;
+	for (i = 0; i < insn->n; i++)
+		data[i] = devpriv->ao_readback[chan];
+
+	return insn->n;
 }
 
 static int pcl726_di_insn_bits(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
 	const struct pcl726_board *board = comedi_board(dev);
+	unsigned int val;
 
-	data[1] = inb(dev->iobase + board->di_lo) |
-	    (inb(dev->iobase + board->di_hi) << 8);
+	if (board->is_pcl727) {
+		val = inb(dev->iobase + PCL727_DI_LSB_REG);
+		val |= (inb(dev->iobase + PCL727_DI_MSB_REG) << 8);
+	} else {
+		val = inb(dev->iobase + PCL726_DI_LSB_REG);
+		val |= (inb(dev->iobase + PCL726_DI_MSB_REG) << 8);
+	}
+
+	data[1] = val;
 
 	return insn->n;
 }
 
 static int pcl726_do_insn_bits(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
 	const struct pcl726_board *board = comedi_board(dev);
+	unsigned long io = dev->iobase;
+	unsigned int mask;
 
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= data[0] & data[1];
+	mask = comedi_dio_update_state(s, data);
+	if (mask) {
+		if (board->is_pcl727) {
+			if (mask & 0x00ff)
+				outb(s->state & 0xff, io + PCL727_DO_LSB_REG);
+			if (mask & 0xff00)
+				outb((s->state >> 8), io + PCL727_DO_MSB_REG);
+		} else {
+			if (mask & 0x00ff)
+				outb(s->state & 0xff, io + PCL726_DO_LSB_REG);
+			if (mask & 0xff00)
+				outb((s->state >> 8), io + PCL726_DO_MSB_REG);
+		}
 	}
-	if (data[1] & 0x00ff)
-		outb(s->state & 0xff, dev->iobase + board->do_lo);
-	if (data[1] & 0xff00)
-		outb((s->state >> 8), dev->iobase + board->do_hi);
 
 	data[1] = s->state;
 
 	return insn->n;
 }
 
-static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int pcl726_attach(struct comedi_device *dev,
+			 struct comedi_devconfig *it)
 {
 	const struct pcl726_board *board = comedi_board(dev);
 	struct pcl726_private *devpriv;
 	struct comedi_subdevice *s;
-	int ret, i;
-#ifdef ACL6126_IRQ
-	unsigned int irq;
-#endif
+	int subdev;
+	int ret;
+	int i;
 
-	ret = comedi_request_region(dev, it->options[0], board->io_range);
+	ret = comedi_request_region(dev, it->options[0], board->io_len);
 	if (ret)
 		return ret;
 
@@ -232,97 +358,81 @@
 	if (!devpriv)
 		return -ENOMEM;
 
-	for (i = 0; i < 12; i++) {
-		devpriv->bipolar[i] = 0;
-		devpriv->rangelist[i] = &range_unknown;
-	}
-
-#ifdef ACL6126_IRQ
-	irq = 0;
-	if (boardtypes[board].IRQbits != 0) {	/* board support IRQ */
-		irq = it->options[1];
-		devpriv->first_chan = 2;
-		if (irq) {	/* we want to use IRQ */
-			if (((1 << irq) & boardtypes[board].IRQbits) == 0) {
-				printk(KERN_WARNING
-					", IRQ %d is out of allowed range,"
-					" DISABLING IT", irq);
-				irq = 0;	/* Bad IRQ */
-			} else {
-				if (request_irq(irq, interrupt_pcl818, 0,
-						dev->board_name, dev)) {
-					printk(KERN_WARNING
-						", unable to allocate IRQ %d,"
-						" DISABLING IT", irq);
-					irq = 0;	/* Can't use IRQ */
-				} else {
-					printk(", irq=%d", irq);
-				}
-			}
+	/*
+	 * Hook up the external trigger source interrupt only if the
+	 * user config option is valid and the board supports interrupts.
+	 */
+	if (it->options[1] && (board->irq_mask & (1 << it->options[1]))) {
+		ret = request_irq(it->options[1], pcl726_interrupt, 0,
+				  dev->board_name, dev);
+		if (ret == 0) {
+			/* External trigger source is from Pin-17 of CN3 */
+			dev->irq = it->options[1];
 		}
 	}
 
-	dev->irq = irq;
-#endif
+	/* setup the per-channel analog output range_table_list */
+	for (i = 0; i < 12; i++) {
+		unsigned int opt = it->options[2 + i];
 
-	printk("\n");
+		if (opt < board->ao_num_ranges && i < board->ao_nchan)
+			devpriv->rangelist[i] = board->ao_ranges[opt];
+		else
+			devpriv->rangelist[i] = &range_unknown;
+	}
 
-	ret = comedi_alloc_subdevices(dev, 3);
+	subdev = board->have_dio ? 3 : 1;
+	if (dev->irq)
+		subdev++;
+	ret = comedi_alloc_subdevices(dev, subdev);
 	if (ret)
 		return ret;
 
-	s = &dev->subdevices[0];
-	/* ao */
-	s->type = COMEDI_SUBD_AO;
-	s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
-	s->n_chan = board->n_aochan;
-	s->maxdata = 0xfff;
-	s->len_chanlist = 1;
-	s->insn_write = pcl726_ao_insn;
-	s->insn_read = pcl726_ao_insn_read;
+	subdev = 0;
+
+	/* Analog Output subdevice */
+	s = &dev->subdevices[subdev++];
+	s->type		= COMEDI_SUBD_AO;
+	s->subdev_flags	= SDF_WRITABLE | SDF_GROUND;
+	s->n_chan	= board->ao_nchan;
+	s->maxdata	= 0x0fff;
 	s->range_table_list = devpriv->rangelist;
-	for (i = 0; i < board->n_aochan; i++) {
-		int j;
+	s->insn_write	= pcl726_ao_insn_write;
+	s->insn_read	= pcl726_ao_insn_read;
 
-		j = it->options[2 + 1];
-		if ((j < 0) || (j >= board->num_of_ranges)) {
-			printk
-			    ("Invalid range for channel %d! Must be 0<=%d<%d\n",
-			     i, j, board->num_of_ranges - 1);
-			j = 0;
-		}
-		devpriv->rangelist[i] = board->range_type_list[j];
-		if (devpriv->rangelist[i]->range[0].min ==
-		    -devpriv->rangelist[i]->range[0].max)
-			devpriv->bipolar[i] = 1;	/* bipolar range */
+	if (board->have_dio) {
+		/* Digital Input subdevice */
+		s = &dev->subdevices[subdev++];
+		s->type		= COMEDI_SUBD_DI;
+		s->subdev_flags	= SDF_READABLE;
+		s->n_chan	= 16;
+		s->maxdata	= 1;
+		s->insn_bits	= pcl726_di_insn_bits;
+		s->range_table	= &range_digital;
+
+		/* Digital Output subdevice */
+		s = &dev->subdevices[subdev++];
+		s->type		= COMEDI_SUBD_DO;
+		s->subdev_flags	= SDF_WRITABLE;
+		s->n_chan	= 16;
+		s->maxdata	= 1;
+		s->insn_bits	= pcl726_do_insn_bits;
+		s->range_table	= &range_digital;
 	}
 
-	s = &dev->subdevices[1];
-	/* di */
-	if (!board->have_dio) {
-		s->type = COMEDI_SUBD_UNUSED;
-	} else {
-		s->type = COMEDI_SUBD_DI;
-		s->subdev_flags = SDF_READABLE | SDF_GROUND;
-		s->n_chan = 16;
-		s->maxdata = 1;
-		s->len_chanlist = 1;
-		s->insn_bits = pcl726_di_insn_bits;
-		s->range_table = &range_digital;
-	}
-
-	s = &dev->subdevices[2];
-	/* do */
-	if (!board->have_dio) {
-		s->type = COMEDI_SUBD_UNUSED;
-	} else {
-		s->type = COMEDI_SUBD_DO;
-		s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
-		s->n_chan = 16;
-		s->maxdata = 1;
-		s->len_chanlist = 1;
-		s->insn_bits = pcl726_do_insn_bits;
-		s->range_table = &range_digital;
+	if (dev->irq) {
+		/* Digial Input subdevice - Interrupt support */
+		s = &dev->subdevices[subdev++];
+		dev->read_subdev = s;
+		s->type		= COMEDI_SUBD_DI;
+		s->subdev_flags	= SDF_READABLE | SDF_CMD_READ;
+		s->n_chan	= 1;
+		s->maxdata	= 1;
+		s->range_table	= &range_digital;
+		s->insn_bits	= pcl726_intr_insn_bits;
+		s->do_cmdtest	= pcl726_intr_cmdtest;
+		s->do_cmd	= pcl726_intr_cmd;
+		s->cancel	= pcl726_intr_cancel;
 	}
 
 	return 0;
@@ -333,12 +443,12 @@
 	.module		= THIS_MODULE,
 	.attach		= pcl726_attach,
 	.detach		= comedi_legacy_detach,
-	.board_name	= &boardtypes[0].name,
-	.num_names	= ARRAY_SIZE(boardtypes),
+	.board_name	= &pcl726_boards[0].name,
+	.num_names	= ARRAY_SIZE(pcl726_boards),
 	.offset		= sizeof(struct pcl726_board),
 };
 module_comedi_driver(pcl726_driver);
 
 MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for Advantech PCL-726 & compatibles");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c
index 2a659f2..d041b714 100644
--- a/drivers/staging/comedi/drivers/pcl730.c
+++ b/drivers/staging/comedi/drivers/pcl730.c
@@ -167,20 +167,17 @@
 			       unsigned int *data)
 {
 	unsigned long reg = (unsigned long)s->private;
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
+	unsigned int mask;
 
+	mask = comedi_dio_update_state(s, data);
 	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
-
 		if (mask & 0x00ff)
 			outb(s->state & 0xff, dev->iobase + reg);
-		if ((mask & 0xff00) && (s->n_chan > 8))
+		if ((mask & 0xff00) & (s->n_chan > 8))
 			outb((s->state >> 8) & 0xff, dev->iobase + reg + 1);
-		if ((mask & 0xff0000) && (s->n_chan > 16))
+		if ((mask & 0xff0000) & (s->n_chan > 16))
 			outb((s->state >> 16) & 0xff, dev->iobase + reg + 2);
-		if ((mask & 0xff000000) && (s->n_chan > 24))
+		if ((mask & 0xff000000) & (s->n_chan > 24))
 			outb((s->state >> 24) & 0xff, dev->iobase + reg + 3);
 	}
 
diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
index 03a0989..03315ab 100644
--- a/drivers/staging/comedi/drivers/pcl812.c
+++ b/drivers/staging/comedi/drivers/pcl812.c
@@ -355,7 +355,6 @@
 	unsigned int ai_n_chan;	/*  how many channels is measured */
 	unsigned int ai_flags;	/*  flaglist */
 	unsigned int ai_data_len;	/*  len of data buffer */
-	short *ai_data;		/*  data buffer */
 	unsigned int ai_is16b;	/*  =1 we have 16 bit card */
 	unsigned long dmabuf[2];	/*  PTR to DMA buf */
 	unsigned int dmapages[2];	/*  how many pages we have allocated */
@@ -509,19 +508,16 @@
 	return insn->n;
 }
 
-/*
-==============================================================================
-*/
 static int pcl812_do_insn_bits(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= data[0] & data[1];
+	if (comedi_dio_update_state(s, data)) {
 		outb(s->state & 0xff, dev->iobase + PCL812_DO_LO);
 		outb((s->state >> 8), dev->iobase + PCL812_DO_HI);
 	}
+
 	data[1] = s->state;
 
 	return insn->n;
@@ -592,9 +588,9 @@
 
 	if (cmd->convert_src == TRIG_TIMER) {
 		tmp = cmd->convert_arg;
-		i8253_cascade_ns_to_timer(board->i8254_osc_base, &divisor1,
-					  &divisor2, &cmd->convert_arg,
-					  cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(board->i8254_osc_base,
+					  &divisor1, &divisor2,
+					  &cmd->convert_arg, cmd->flags);
 		if (cmd->convert_arg < board->ai_ns_min)
 			cmd->convert_arg = board->ai_ns_min;
 		if (tmp != cmd->convert_arg)
@@ -640,8 +636,7 @@
 			cmd->convert_arg = board->ai_ns_min;
 		i8253_cascade_ns_to_timer(board->i8254_osc_base,
 					  &divisor1, &divisor2,
-					  &cmd->convert_arg,
-					  cmd->flags & TRIG_ROUND_MASK);
+					  &cmd->convert_arg, cmd->flags);
 	}
 
 	start_pacer(dev, -1, 0, 0);	/*  stop pacer */
@@ -665,7 +660,6 @@
 
 	devpriv->ai_flags = cmd->flags;
 	devpriv->ai_data_len = s->async->prealloc_bufsz;
-	devpriv->ai_data = s->async->prealloc_buf;
 	if (cmd->stop_src == TRIG_COUNT) {
 		devpriv->ai_scans = cmd->stop_arg;
 		devpriv->ai_neverending = 0;
@@ -835,7 +829,8 @@
 ==============================================================================
 */
 static void transfer_from_dma_buf(struct comedi_device *dev,
-				  struct comedi_subdevice *s, short *ptr,
+				  struct comedi_subdevice *s,
+				  unsigned short *ptr,
 				  unsigned int bufptr, unsigned int len)
 {
 	struct pcl812_private *devpriv = dev->private;
@@ -873,9 +868,9 @@
 	struct comedi_subdevice *s = &dev->subdevices[0];
 	unsigned long dma_flags;
 	int len, bufptr;
-	short *ptr;
+	unsigned short *ptr;
 
-	ptr = (short *)devpriv->dmabuf[devpriv->next_dma_buf];
+	ptr = (unsigned short *)devpriv->dmabuf[devpriv->next_dma_buf];
 	len = (devpriv->dmabytestomove[devpriv->next_dma_buf] >> 1) -
 	    devpriv->ai_poll_ptr;
 
@@ -1443,40 +1438,40 @@
 
 static const struct pcl812_board boardtypes[] = {
 	{"pcl812", boardPCL812, 16, 0, 2, 16, 16, 0x0fff,
-	 33000, 500, &range_bipolar10, &range_unipolar5,
+	 33000, I8254_OSC_BASE_2MHZ, &range_bipolar10, &range_unipolar5,
 	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
 	{"pcl812pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff,
-	 33000, 500, &range_pcl812pg_ai, &range_unipolar5,
+	 33000, I8254_OSC_BASE_2MHZ, &range_pcl812pg_ai, &range_unipolar5,
 	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
 	{"acl8112pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff,
-	 10000, 500, &range_pcl812pg_ai, &range_unipolar5,
+	 10000, I8254_OSC_BASE_2MHZ, &range_pcl812pg_ai, &range_unipolar5,
 	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
 	{"acl8112dg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
-	 10000, 500, &range_acl8112dg_ai, &range_unipolar5,
+	 10000, I8254_OSC_BASE_2MHZ, &range_acl8112dg_ai, &range_unipolar5,
 	 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
 	{"acl8112hg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
-	 10000, 500, &range_acl8112hg_ai, &range_unipolar5,
+	 10000, I8254_OSC_BASE_2MHZ, &range_acl8112hg_ai, &range_unipolar5,
 	 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
 	{"a821pgl", boardA821, 16, 8, 1, 16, 16, 0x0fff,
-	 10000, 500, &range_pcl813b_ai, &range_unipolar5,
+	 10000, I8254_OSC_BASE_2MHZ, &range_pcl813b_ai, &range_unipolar5,
 	 0x000c, 0x00, PCLx1x_IORANGE, 0},
 	{"a821pglnda", boardA821, 16, 8, 0, 0, 0, 0x0fff,
-	 10000, 500, &range_pcl813b_ai, NULL,
+	 10000, I8254_OSC_BASE_2MHZ, &range_pcl813b_ai, NULL,
 	 0x000c, 0x00, PCLx1x_IORANGE, 0},
 	{"a821pgh", boardA821, 16, 8, 1, 16, 16, 0x0fff,
-	 10000, 500, &range_a821pgh_ai, &range_unipolar5,
+	 10000, I8254_OSC_BASE_2MHZ, &range_a821pgh_ai, &range_unipolar5,
 	 0x000c, 0x00, PCLx1x_IORANGE, 0},
 	{"a822pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
-	 10000, 500, &range_acl8112dg_ai, &range_unipolar5,
+	 10000, I8254_OSC_BASE_2MHZ, &range_acl8112dg_ai, &range_unipolar5,
 	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
 	{"a822pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
-	 10000, 500, &range_acl8112hg_ai, &range_unipolar5,
+	 10000, I8254_OSC_BASE_2MHZ, &range_acl8112hg_ai, &range_unipolar5,
 	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
 	{"a823pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
-	 8000, 500, &range_acl8112dg_ai, &range_unipolar5,
+	 8000, I8254_OSC_BASE_2MHZ, &range_acl8112dg_ai, &range_unipolar5,
 	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
 	{"a823pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
-	 8000, 500, &range_acl8112hg_ai, &range_unipolar5,
+	 8000, I8254_OSC_BASE_2MHZ, &range_acl8112hg_ai, &range_unipolar5,
 	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
 	{"pcl813", boardPCL813, 32, 0, 0, 0, 0, 0x0fff,
 	 0, 0, &range_pcl813b_ai, NULL,
@@ -1491,10 +1486,10 @@
 	 0, 0, &range_iso813_1_ai, NULL,
 	 0x0000, 0x00, PCLx1x_IORANGE, 0},
 	{"acl8216", boardACL8216, 16, 8, 2, 16, 16, 0xffff,
-	 10000, 500, &range_pcl813b2_ai, &range_unipolar5,
+	 10000, I8254_OSC_BASE_2MHZ, &range_pcl813b2_ai, &range_unipolar5,
 	 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
 	{"a826pg", boardACL8216, 16, 8, 2, 16, 16, 0xffff,
-	 10000, 500, &range_pcl813b2_ai, &range_unipolar5,
+	 10000, I8254_OSC_BASE_2MHZ, &range_pcl813b2_ai, &range_unipolar5,
 	 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
 };
 
diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
index f031349..ab9d2bd 100644
--- a/drivers/staging/comedi/drivers/pcl816.c
+++ b/drivers/staging/comedi/drivers/pcl816.c
@@ -229,7 +229,7 @@
 	struct comedi_device *dev = d;
 	struct pcl816_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[0];
-	int low, hi;
+	unsigned char low, hi;
 	int timeout = 50;	/* wait max 50us */
 
 	while (timeout--) {
@@ -281,7 +281,8 @@
    analog input dma mode 1 & 3, 816 cards
 */
 static void transfer_from_dma_buf(struct comedi_device *dev,
-				  struct comedi_subdevice *s, short *ptr,
+				  struct comedi_subdevice *s,
+				  unsigned short *ptr,
 				  unsigned int bufptr, unsigned int len)
 {
 	struct pcl816_private *devpriv = dev->private;
@@ -324,7 +325,7 @@
 	struct comedi_subdevice *s = &dev->subdevices[0];
 	int len, bufptr, this_dma_buf;
 	unsigned long dma_flags;
-	short *ptr;
+	unsigned short *ptr;
 
 	disable_dma(devpriv->dma);
 	this_dma_buf = devpriv->next_dma_buf;
@@ -352,7 +353,7 @@
 	devpriv->dma_runs_to_end--;
 	outb(0, dev->iobase + PCL816_CLRINT);	/* clear INT request */
 
-	ptr = (short *)devpriv->dmabuf[this_dma_buf];
+	ptr = (unsigned short *)devpriv->dmabuf[this_dma_buf];
 
 	len = (devpriv->hwdmasize[0] >> 1) - devpriv->ai_poll_ptr;
 	bufptr = devpriv->ai_poll_ptr;
@@ -481,8 +482,7 @@
 		tmp = cmd->convert_arg;
 		i8253_cascade_ns_to_timer(board->i8254_osc_base,
 					  &divisor1, &divisor2,
-					  &cmd->convert_arg,
-					  cmd->flags & TRIG_ROUND_MASK);
+					  &cmd->convert_arg, cmd->flags);
 		if (cmd->convert_arg < board->ai_ns_min)
 			cmd->convert_arg = board->ai_ns_min;
 		if (tmp != cmd->convert_arg)
@@ -528,9 +528,9 @@
 		if (cmd->convert_arg < board->ai_ns_min)
 			cmd->convert_arg = board->ai_ns_min;
 
-		i8253_cascade_ns_to_timer(board->i8254_osc_base, &divisor1,
-					  &divisor2, &cmd->convert_arg,
-					  cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(board->i8254_osc_base,
+					  &divisor1, &divisor2,
+					  &cmd->convert_arg, cmd->flags);
 
 		/*  PCL816 crash if any divisor is set to 1 */
 		if (divisor1 == 1) {
@@ -666,7 +666,8 @@
 	}
 
 	transfer_from_dma_buf(dev, s,
-			      (short *)devpriv->dmabuf[devpriv->next_dma_buf],
+			      (unsigned short *)devpriv->dmabuf[devpriv->
+								next_dma_buf],
 			      devpriv->ai_poll_ptr, top2);
 
 	devpriv->ai_poll_ptr = top1;	/*  new buffer position */
@@ -1105,7 +1106,7 @@
 	 0xffff,		/*  D/A maxdata */
 	 1024,
 	 1,			/*  ao chan list */
-	 100},
+	 I8254_OSC_BASE_10MHZ},
 	{"pcl814b", 8, 16, 10000, 1, 16, 16, &range_pcl816,
 	 &range_pcl816, PCLx1x_RANGE,
 	 0x00fc,
@@ -1114,7 +1115,7 @@
 	 0x3fff,
 	 1024,
 	 1,
-	 100},
+	 I8254_OSC_BASE_10MHZ},
 };
 
 static struct comedi_driver pcl816_driver = {
diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
index a52ba82..9e4d7e8 100644
--- a/drivers/staging/comedi/drivers/pcl818.c
+++ b/drivers/staging/comedi/drivers/pcl818.c
@@ -289,7 +289,6 @@
 	unsigned int *ai_chanlist;	/*  actaul chanlist */
 	unsigned int ai_flags;	/*  flaglist */
 	unsigned int ai_data_len;	/*  len of data buffer */
-	short *ai_data;		/*  data buffer */
 	unsigned int ai_timer1;	/*  timers */
 	unsigned int ai_timer2;
 	struct comedi_subdevice *sub_ai;	/*  ptr to AI subdevice */
@@ -418,21 +417,15 @@
 	return insn->n;
 }
 
-/*
-==============================================================================
-   DIGITAL OUTPUT MODE0, 818 cards
-
-   only one sample per call is supported
-*/
 static int pcl818_do_insn_bits(struct comedi_device *dev,
 			       struct comedi_subdevice *s,
-			       struct comedi_insn *insn, unsigned int *data)
+			       struct comedi_insn *insn,
+			       unsigned int *data)
 {
-	s->state &= ~data[0];
-	s->state |= (data[0] & data[1]);
-
-	outb(s->state & 0xff, dev->iobase + PCL818_DO_LO);
-	outb((s->state >> 8), dev->iobase + PCL818_DO_HI);
+	if (comedi_dio_update_state(s, data)) {
+		outb(s->state & 0xff, dev->iobase + PCL818_DO_LO);
+		outb((s->state >> 8), dev->iobase + PCL818_DO_HI);
+	}
 
 	data[1] = s->state;
 
@@ -449,7 +442,7 @@
 	struct comedi_device *dev = d;
 	struct pcl818_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[0];
-	int low;
+	unsigned char low;
 	int timeout = 50;	/* wait max 50us */
 
 	while (timeout--) {
@@ -511,7 +504,7 @@
 	struct comedi_subdevice *s = &dev->subdevices[0];
 	int i, len, bufptr;
 	unsigned long flags;
-	short *ptr;
+	unsigned short *ptr;
 
 	disable_dma(devpriv->dma);
 	devpriv->next_dma_buf = 1 - devpriv->next_dma_buf;
@@ -534,7 +527,7 @@
 
 	devpriv->dma_runs_to_end--;
 	outb(0, dev->iobase + PCL818_CLRINT);	/* clear INT request */
-	ptr = (short *)devpriv->dmabuf[1 - devpriv->next_dma_buf];
+	ptr = (unsigned short *)devpriv->dmabuf[1 - devpriv->next_dma_buf];
 
 	len = devpriv->hwdmasize[0] >> 1;
 	bufptr = 0;
@@ -588,7 +581,8 @@
 	struct comedi_device *dev = d;
 	struct pcl818_private *devpriv = dev->private;
 	struct comedi_subdevice *s = &dev->subdevices[0];
-	int i, len, lo;
+	int i, len;
+	unsigned char lo;
 
 	outb(0, dev->iobase + PCL818_FI_INTCLR);	/*  clear fifo int request */
 
@@ -806,8 +800,9 @@
 		devpriv->neverending_ai = 1;	/* well, user want neverending */
 
 	if (mode == 1) {
-		i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
-					  &divisor2, &cmd->convert_arg,
+		i8253_cascade_ns_to_timer(devpriv->i8253_osc_base,
+					  &divisor1, &divisor2,
+					  &cmd->convert_arg,
 					  TRIG_ROUND_NEAREST);
 		if (divisor1 == 1) {	/* PCL718/818 crash if any divisor is set to 1 */
 			divisor1 = 2;
@@ -1040,9 +1035,9 @@
 
 	if (cmd->convert_src == TRIG_TIMER) {
 		tmp = cmd->convert_arg;
-		i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
-					  &divisor2, &cmd->convert_arg,
-					  cmd->flags & TRIG_ROUND_MASK);
+		i8253_cascade_ns_to_timer(devpriv->i8253_osc_base,
+					  &divisor1, &divisor2,
+					  &cmd->convert_arg, cmd->flags);
 		if (cmd->convert_arg < board->ns_min)
 			cmd->convert_arg = board->ns_min;
 		if (tmp != cmd->convert_arg)
@@ -1077,7 +1072,6 @@
 	devpriv->ai_chanlist = cmd->chanlist;
 	devpriv->ai_flags = cmd->flags;
 	devpriv->ai_data_len = s->async->prealloc_bufsz;
-	devpriv->ai_data = s->async->prealloc_buf;
 	devpriv->ai_timer1 = 0;
 	devpriv->ai_timer2 = 0;
 
@@ -1438,9 +1432,9 @@
 
 	/* select 1/10MHz oscilator */
 	if ((it->options[3] == 0) || (it->options[3] == 10))
-		devpriv->i8253_osc_base = 100;
+		devpriv->i8253_osc_base = I8254_OSC_BASE_10MHZ;
 	else
-		devpriv->i8253_osc_base = 1000;
+		devpriv->i8253_osc_base = I8254_OSC_BASE_1MHZ;
 
 	/* max sampling speed */
 	devpriv->ns_min = board->ns_min;
diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
index 423f236..fe482fd 100644
--- a/drivers/staging/comedi/drivers/pcmad.c
+++ b/drivers/staging/comedi/drivers/pcmad.c
@@ -75,12 +75,6 @@
 	return -ETIME;
 }
 
-static bool pcmad_range_is_bipolar(struct comedi_subdevice *s,
-				   unsigned int range)
-{
-	return s->range_table->range[range].min < 0;
-}
-
 static int pcmad_ai_insn_read(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
 			      struct comedi_insn *insn,
@@ -106,7 +100,7 @@
 		if (s->maxdata == 0x0fff)
 			val >>= 4;
 
-		if (pcmad_range_is_bipolar(s, range)) {
+		if (comedi_range_is_bipolar(s, range)) {
 			/* munge the two's complement value */
 			val ^= ((s->maxdata + 1) >> 1);
 		}
diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
index 574443d..14cee3a 100644
--- a/drivers/staging/comedi/drivers/pcmmio.c
+++ b/drivers/staging/comedi/drivers/pcmmio.c
@@ -553,12 +553,11 @@
 										val |= (1U << n);
 								}
 								/* Write the scan to the buffer. */
-								if (comedi_buf_put(s->async, ((short *)&val)[0])
+								if (comedi_buf_put(s->async, val)
 								    &&
 								    comedi_buf_put
 								    (s->async,
-								     ((short *)
-								      &val)[1])) {
+								     val >> 16)) {
 									s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
 								} else {
 									/* Overflow! Stop acquisition!! */
@@ -846,7 +845,7 @@
 		    CR_RANGE(insn->chanspec), aref = CR_AREF(insn->chanspec);
 		unsigned char command_byte = 0;
 		unsigned iooffset = 0;
-		short sample, adc_adjust = 0;
+		unsigned short sample, adc_adjust = 0;
 
 		if (chan > 7)
 			chan -= 8, iooffset = 4;	/*
diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c
index 67e2bb1..954fa96 100644
--- a/drivers/staging/comedi/drivers/pcmuio.c
+++ b/drivers/staging/comedi/drivers/pcmuio.c
@@ -315,8 +315,8 @@
 	}
 
 	/* Write the scan to the buffer. */
-	if (comedi_buf_put(s->async, ((short *)&val)[0]) &&
-	    comedi_buf_put(s->async, ((short *)&val)[1])) {
+	if (comedi_buf_put(s->async, val) &&
+	    comedi_buf_put(s->async, val >> 16)) {
 		s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
 	} else {
 		/* Overflow! Stop acquisition!! */
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
index 9775d36..96a4695 100644
--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
@@ -208,8 +208,7 @@
 	case buffer:
 		while (!((status = inb(dev->iobase + DAQP_STATUS))
 			 & DAQP_STATUS_FIFO_EMPTY)) {
-
-			short data;
+			unsigned short data;
 
 			if (status & DAQP_STATUS_DATA_LOST) {
 				s->async->events |=
@@ -690,18 +689,12 @@
 			     unsigned int *data)
 {
 	struct daqp_private *devpriv = dev->private;
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
 
 	if (devpriv->stop)
 		return -EIO;
 
-	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
-
+	if (comedi_dio_update_state(s, data))
 		outb(s->state, dev->iobase + DAQP_DIGITAL_IO);
-	}
 
 	data[1] = s->state;
 
diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
index 93c980c..44c8712 100644
--- a/drivers/staging/comedi/drivers/rtd520.c
+++ b/drivers/staging/comedi/drivers/rtd520.c
@@ -394,11 +394,8 @@
 	long ai_count;		/* total transfer size (samples) */
 	int xfer_count;		/* # to transfer data. 0->1/2FIFO */
 	int flags;		/* flag event modes */
-
-	unsigned char chan_is_bipolar[RTD_MAX_CHANLIST / 8];	/* bit array */
-
+	DECLARE_BITMAP(chan_is_bipolar, RTD_MAX_CHANLIST);
 	unsigned int ao_readback[2];
-
 	unsigned fifosz;
 };
 
@@ -407,14 +404,6 @@
 #define DMA0_ACTIVE	0x02	/* DMA0 is active */
 #define DMA1_ACTIVE	0x04	/* DMA1 is active */
 
-/* Macros for accessing channel list bit array */
-#define CHAN_ARRAY_TEST(array, index) \
-	(((array)[(index)/8] >> ((index) & 0x7)) & 0x1)
-#define CHAN_ARRAY_SET(array, index) \
-	(((array)[(index)/8] |= 1 << ((index) & 0x7)))
-#define CHAN_ARRAY_CLEAR(array, index) \
-	(((array)[(index)/8] &= ~(1 << ((index) & 0x7))))
-
 /*
   Given a desired period and the clock period (both in ns),
   return the proper counter value (divider-1).
@@ -478,17 +467,17 @@
 		/* +-5 range */
 		r |= 0x000;
 		r |= (range & 0x7) << 4;
-		CHAN_ARRAY_SET(devpriv->chan_is_bipolar, index);
+		__set_bit(index, devpriv->chan_is_bipolar);
 	} else if (range < board->range_uni10) {
 		/* +-10 range */
 		r |= 0x100;
 		r |= ((range - board->range_bip10) & 0x7) << 4;
-		CHAN_ARRAY_SET(devpriv->chan_is_bipolar, index);
+		__set_bit(index, devpriv->chan_is_bipolar);
 	} else {
 		/* +10 range */
 		r |= 0x200;
 		r |= ((range - board->range_uni10) & 0x7) << 4;
-		CHAN_ARRAY_CLEAR(devpriv->chan_is_bipolar, index);
+		__clear_bit(index, devpriv->chan_is_bipolar);
 	}
 
 	switch (aref) {
@@ -602,7 +591,7 @@
 
 	/* convert n samples */
 	for (n = 0; n < insn->n; n++) {
-		s16 d;
+		unsigned short d;
 		/* trigger conversion */
 		writew(0, devpriv->las0 + LAS0_ADC);
 
@@ -619,11 +608,10 @@
 		d = readw(devpriv->las1 + LAS1_ADC_FIFO);
 		/*printk ("rtd520: Got 0x%x after %d usec\n", d, ii+1); */
 		d = d >> 3;	/* low 3 bits are marker lines */
-		if (CHAN_ARRAY_TEST(devpriv->chan_is_bipolar, 0))
+		if (test_bit(0, devpriv->chan_is_bipolar))
 			/* convert to comedi unsigned data */
-			data[n] = d + 2048;
-		else
-			data[n] = d;
+			d = comedi_offset_munge(s, d);
+		data[n] = d & s->maxdata;
 	}
 
 	/* return the number of samples read/written */
@@ -643,8 +631,7 @@
 	int ii;
 
 	for (ii = 0; ii < count; ii++) {
-		short sample;
-		s16 d;
+		unsigned short d;
 
 		if (0 == devpriv->ai_count) {	/* done */
 			d = readw(devpriv->las1 + LAS1_ADC_FIFO);
@@ -653,14 +640,12 @@
 
 		d = readw(devpriv->las1 + LAS1_ADC_FIFO);
 		d = d >> 3;	/* low 3 bits are marker lines */
-		if (CHAN_ARRAY_TEST(devpriv->chan_is_bipolar,
-				    s->async->cur_chan)) {
+		if (test_bit(s->async->cur_chan, devpriv->chan_is_bipolar))
 			/* convert to comedi unsigned data */
-			sample = d + 2048;
-		} else
-			sample = d;
+			d = comedi_offset_munge(s, d);
+		d &= s->maxdata;
 
-		if (!comedi_buf_put(s->async, sample))
+		if (!comedi_buf_put(s->async, d))
 			return -1;
 
 		if (devpriv->ai_count > 0)	/* < 0, means read forever */
@@ -677,22 +662,19 @@
 	struct rtd_private *devpriv = dev->private;
 
 	while (readl(devpriv->las0 + LAS0_ADC) & FS_ADC_NOT_EMPTY) {
-		short sample;
-		s16 d = readw(devpriv->las1 + LAS1_ADC_FIFO);
+		unsigned short d = readw(devpriv->las1 + LAS1_ADC_FIFO);
 
 		if (0 == devpriv->ai_count) {	/* done */
 			continue;	/* read rest */
 		}
 
 		d = d >> 3;	/* low 3 bits are marker lines */
-		if (CHAN_ARRAY_TEST(devpriv->chan_is_bipolar,
-				    s->async->cur_chan)) {
+		if (test_bit(s->async->cur_chan, devpriv->chan_is_bipolar))
 			/* convert to comedi unsigned data */
-			sample = d + 2048;
-		} else
-			sample = d;
+			d = comedi_offset_munge(s, d);
+		d &= s->maxdata;
 
-		if (!comedi_buf_put(s->async, sample))
+		if (!comedi_buf_put(s->async, d))
 			return -1;
 
 		if (devpriv->ai_count > 0)	/* < 0, means read forever */
@@ -1217,15 +1199,9 @@
 			     unsigned int *data)
 {
 	struct rtd_private *devpriv = dev->private;
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
 
-	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
-
+	if (comedi_dio_update_state(s, data))
 		writew(s->state & 0xff, devpriv->las0 + LAS0_DIO0);
-	}
 
 	data[1] = readw(devpriv->las0 + LAS0_DIO0) & 0xff;
 
diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
index cbb4ba5..e1f3671 100644
--- a/drivers/staging/comedi/drivers/rti800.c
+++ b/drivers/staging/comedi/drivers/rti800.c
@@ -267,13 +267,7 @@
 			       struct comedi_insn *insn,
 			       unsigned int *data)
 {
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
-
-	if (mask) {
-		s->state &= ~mask;
-		s->state |= (bits & mask);
-
+	if (comedi_dio_update_state(s, data)) {
 		/* Outputs are inverted... */
 		outb(s->state ^ 0xff, dev->iobase + RTI800_DO);
 	}
diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
index d629463..9950f59 100644
--- a/drivers/staging/comedi/drivers/s526.c
+++ b/drivers/staging/comedi/drivers/s526.c
@@ -499,14 +499,11 @@
 
 static int s526_dio_insn_bits(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data)
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= data[0] & data[1];
-
+	if (comedi_dio_update_state(s, data))
 		outw(s->state, dev->iobase + REG_DIO);
-	}
 
 	data[1] = inw(dev->iobase + REG_DIO) & 0xff;
 
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index d22b95d..6815cfe 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -1,63 +1,63 @@
 /*
-  comedi/drivers/s626.c
-  Sensoray s626 Comedi driver
-
-  COMEDI - Linux Control and Measurement Device Interface
-  Copyright (C) 2000 David A. Schleef <ds@schleef.org>
-
-  Based on Sensoray Model 626 Linux driver Version 0.2
-  Copyright (C) 2002-2004 Sensoray Co., Inc.
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-*/
+ * comedi/drivers/s626.c
+ * Sensoray s626 Comedi driver
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ *
+ * Based on Sensoray Model 626 Linux driver Version 0.2
+ * Copyright (C) 2002-2004 Sensoray Co., Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
 
 /*
-Driver: s626
-Description: Sensoray 626 driver
-Devices: [Sensoray] 626 (s626)
-Authors: Gianluca Palli <gpalli@deis.unibo.it>,
-Updated: Fri, 15 Feb 2008 10:28:42 +0000
-Status: experimental
+ * Driver: s626
+ * Description: Sensoray 626 driver
+ * Devices: [Sensoray] 626 (s626)
+ * Authors: Gianluca Palli <gpalli@deis.unibo.it>,
+ * Updated: Fri, 15 Feb 2008 10:28:42 +0000
+ * Status: experimental
 
-Configuration options: not applicable, uses PCI auto config
+ * Configuration options: not applicable, uses PCI auto config
 
-INSN_CONFIG instructions:
-  analog input:
-   none
-
-  analog output:
-   none
-
-  digital channel:
-   s626 has 3 dio subdevices (2,3 and 4) each with 16 i/o channels
-   supported configuration options:
-   INSN_CONFIG_DIO_QUERY
-   COMEDI_INPUT
-   COMEDI_OUTPUT
-
-  encoder:
-   Every channel must be configured before reading.
-
-   Example code
-
-   insn.insn=INSN_CONFIG;   //configuration instruction
-   insn.n=1;                //number of operation (must be 1)
-   insn.data=&initialvalue; //initial value loaded into encoder
-				//during configuration
-   insn.subdev=5;           //encoder subdevice
-   insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); //encoder_channel
-							//to configure
-
-   comedi_do_insn(cf,&insn); //executing configuration
-*/
+ * INSN_CONFIG instructions:
+ *   analog input:
+ *    none
+ *
+ *   analog output:
+ *    none
+ *
+ *   digital channel:
+ *    s626 has 3 dio subdevices (2,3 and 4) each with 16 i/o channels
+ *    supported configuration options:
+ *    INSN_CONFIG_DIO_QUERY
+ *    COMEDI_INPUT
+ *    COMEDI_OUTPUT
+ *
+ *   encoder:
+ *    Every channel must be configured before reading.
+ *
+ *   Example code
+ *
+ *    insn.insn=INSN_CONFIG;   //configuration instruction
+ *    insn.n=1;                //number of operation (must be 1)
+ *    insn.data=&initialvalue; //initial value loaded into encoder
+ *                             //during configuration
+ *    insn.subdev=5;           //encoder subdevice
+ *    insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); //encoder_channel
+ *                                                         //to configure
+ *
+ *    comedi_do_insn(cf,&insn); //executing configuration
+ */
 
 #include <linux/module.h>
 #include <linux/delay.h>
@@ -71,68 +71,91 @@
 #include "comedi_fc.h"
 #include "s626.h"
 
-#define PCI_VENDOR_ID_S626 0x1131
-#define PCI_DEVICE_ID_S626 0x7146
-#define PCI_SUBVENDOR_ID_S626 0x6000
-#define PCI_SUBDEVICE_ID_S626 0x0272
+struct s626_buffer_dma {
+	dma_addr_t physical_base;
+	void *logical_base;
+};
 
 struct s626_private {
 	void __iomem *mmio;
-	uint8_t ai_cmd_running;	/*  ai_cmd is running */
-	uint8_t ai_continous;	/*  continous acquisition */
-	int ai_sample_count;	/*  number of samples to acquire */
-	unsigned int ai_sample_timer;
-	/*  time between samples in  units of the timer */
-	int ai_convert_count;	/*  conversion counter */
-	unsigned int ai_convert_timer;
-	/*  time between conversion in  units of the timer */
-	uint16_t CounterIntEnabs;
-	/* Counter interrupt enable  mask for MISC2 register. */
-	uint8_t AdcItems;	/* Number of items in ADC poll  list. */
-	struct bufferDMA RPSBuf;	/* DMA buffer used to hold ADC (RPS1) program. */
-	struct bufferDMA ANABuf;
-	/* DMA buffer used to receive ADC data and hold DAC data. */
-	uint32_t *pDacWBuf;
-	/* Pointer to logical adrs of DMA buffer used to hold DAC  data. */
-	uint16_t Dacpol;	/* Image of DAC polarity register. */
-	uint8_t TrimSetpoint[12];	/* Images of TrimDAC setpoints */
-	/* Charge Enabled (0 or WRMISC2_CHARGE_ENABLE). */
-	uint32_t I2CAdrs;
-	/* I2C device address for onboard EEPROM (board rev dependent). */
-	/*   short         I2Cards; */
+	uint8_t ai_cmd_running;		/* ai_cmd is running */
+	uint8_t ai_continuous;		/* continuous acquisition */
+	int ai_sample_count;		/* number of samples to acquire */
+	unsigned int ai_sample_timer;	/* time between samples in
+					 * units of the timer */
+	int ai_convert_count;		/* conversion counter */
+	unsigned int ai_convert_timer;	/* time between conversion in
+					 * units of the timer */
+	uint16_t counter_int_enabs;	/* counter interrupt enable mask
+					 * for MISC2 register */
+	uint8_t adc_items;		/* number of items in ADC poll list */
+	struct s626_buffer_dma rps_buf;	/* DMA buffer used to hold ADC (RPS1)
+					 * program */
+	struct s626_buffer_dma ana_buf;	/* DMA buffer used to receive ADC data
+					 * and hold DAC data */
+	uint32_t *dac_wbuf;		/* pointer to logical adrs of DMA buffer
+					 * used to hold DAC data */
+	uint16_t dacpol;		/* image of DAC polarity register */
+	uint8_t trim_setpoint[12];	/* images of TrimDAC setpoints */
+	uint32_t i2c_adrs;		/* I2C device address for onboard EEPROM
+					 * (board rev dependent) */
 	unsigned int ao_readback[S626_DAC_CHANNELS];
 };
 
-/*  COUNTER OBJECT ------------------------------------------------ */
-struct enc_private {
-	/*  Pointers to functions that differ for A and B counters: */
-	uint16_t(*GetEnable) (struct comedi_device *dev, struct enc_private *);	/* Return clock enable. */
-	uint16_t(*GetIntSrc) (struct comedi_device *dev, struct enc_private *);	/* Return interrupt source. */
-	uint16_t(*GetLoadTrig) (struct comedi_device *dev, struct enc_private *);	/* Return preload trigger source. */
-	uint16_t(*GetMode) (struct comedi_device *dev, struct enc_private *);	/* Return standardized operating mode. */
-	void (*PulseIndex) (struct comedi_device *dev, struct enc_private *);	/* Generate soft index strobe. */
-	void (*SetEnable) (struct comedi_device *dev, struct enc_private *, uint16_t enab);	/* Program clock enable. */
-	void (*SetIntSrc) (struct comedi_device *dev, struct enc_private *, uint16_t IntSource);	/* Program interrupt source. */
-	void (*SetLoadTrig) (struct comedi_device *dev, struct enc_private *, uint16_t Trig);	/* Program preload trigger source. */
-	void (*SetMode) (struct comedi_device *dev, struct enc_private *, uint16_t Setup, uint16_t DisableIntSrc);	/* Program standardized operating mode. */
-	void (*ResetCapFlags) (struct comedi_device *dev, struct enc_private *);	/* Reset event capture flags. */
+/* COUNTER OBJECT ------------------------------------------------ */
+struct s626_enc_info {
+	/* Pointers to functions that differ for A and B counters: */
+	/* Return clock enable. */
+	uint16_t(*get_enable)(struct comedi_device *dev,
+			      const struct s626_enc_info *k);
+	/* Return interrupt source. */
+	uint16_t(*get_int_src)(struct comedi_device *dev,
+			       const struct s626_enc_info *k);
+	/* Return preload trigger source. */
+	uint16_t(*get_load_trig)(struct comedi_device *dev,
+				 const struct s626_enc_info *k);
+	/* Return standardized operating mode. */
+	uint16_t(*get_mode)(struct comedi_device *dev,
+			    const struct s626_enc_info *k);
+	/* Generate soft index strobe. */
+	void (*pulse_index)(struct comedi_device *dev,
+			    const struct s626_enc_info *k);
+	/* Program clock enable. */
+	void (*set_enable)(struct comedi_device *dev,
+			   const struct s626_enc_info *k, uint16_t enab);
+	/* Program interrupt source. */
+	void (*set_int_src)(struct comedi_device *dev,
+			    const struct s626_enc_info *k, uint16_t int_source);
+	/* Program preload trigger source. */
+	void (*set_load_trig)(struct comedi_device *dev,
+			      const struct s626_enc_info *k, uint16_t trig);
+	/* Program standardized operating mode. */
+	void (*set_mode)(struct comedi_device *dev,
+			 const struct s626_enc_info *k, uint16_t setup,
+			 uint16_t disable_int_src);
+	/* Reset event capture flags. */
+	void (*reset_cap_flags)(struct comedi_device *dev,
+				const struct s626_enc_info *k);
 
-	uint16_t MyCRA;		/*    Address of CRA register. */
-	uint16_t MyCRB;		/*    Address of CRB register. */
-	uint16_t MyLatchLsw;	/*    Address of Latch least-significant-word */
-	/*    register. */
-	uint16_t MyEventBits[4];	/*    Bit translations for IntSrc -->RDMISC2. */
+	uint16_t my_cra;	/* address of CRA register */
+	uint16_t my_crb;	/* address of CRB register */
+	uint16_t my_latch_lsw;	/* address of Latch least-significant-word
+				 * register */
+	uint16_t my_event_bits[4]; /* bit translations for IntSrc -->RDMISC2 */
 };
 
-#define encpriv ((struct enc_private *)(dev->subdevices+5)->private)
+/* Counter overflow/index event flag masks for RDMISC2. */
+#define S626_INDXMASK(C) (1 << (((C) > 2) ? ((C) * 2 - 1) : ((C) * 2 +  4)))
+#define S626_OVERMASK(C) (1 << (((C) > 2) ? ((C) * 2 + 5) : ((C) * 2 + 10)))
+#define S626_EVBITS(C)	{ 0, S626_OVERMASK(C), S626_INDXMASK(C), \
+			  S626_OVERMASK(C) | S626_INDXMASK(C) }
 
-/*  Counter overflow/index event flag masks for RDMISC2. */
-#define INDXMASK(C)		(1 << (((C) > 2) ? ((C) * 2 - 1) : ((C) * 2 +  4)))
-#define OVERMASK(C)		(1 << (((C) > 2) ? ((C) * 2 + 5) : ((C) * 2 + 10)))
-#define EVBITS(C)		{ 0, OVERMASK(C), INDXMASK(C), OVERMASK(C) | INDXMASK(C) }
-
-/*  Translation table to map IntSrc into equivalent RDMISC2 event flag  bits. */
-/* static const uint16_t EventBits[][4] = { EVBITS(0), EVBITS(1), EVBITS(2), EVBITS(3), EVBITS(4), EVBITS(5) }; */
+/*
+ * Translation table to map IntSrc into equivalent RDMISC2 event flag  bits.
+ * static const uint16_t s626_event_bits[][4] =
+ *     { S626_EVBITS(0), S626_EVBITS(1), S626_EVBITS(2), S626_EVBITS(3),
+ *       S626_EVBITS(4), S626_EVBITS(5) };
+ */
 
 /*
  * Enable/disable a function or test status bit(s) that are accessed
@@ -144,6 +167,7 @@
 	struct s626_private *devpriv = dev->private;
 	unsigned int val = (cmd << 16) | cmd;
 
+	mmiowb();
 	writel(val, devpriv->mmio + reg);
 }
 
@@ -153,6 +177,7 @@
 	struct s626_private *devpriv = dev->private;
 
 	writel(cmd << 16 , devpriv->mmio + reg);
+	mmiowb();
 }
 
 static bool s626_mc_test(struct comedi_device *dev,
@@ -166,15 +191,10 @@
 	return (val & cmd) ? true : false;
 }
 
-#define BUGFIX_STREG(REGADRS)   (REGADRS - 4)
+#define S626_BUGFIX_STREG(REGADRS)   ((REGADRS) - 4)
 
-/*  Write a time slot control record to TSL2. */
-#define VECTPORT(VECTNUM)		(P_TSL2 + ((VECTNUM) << 2))
-
-/*  Code macros used for constructing I2C command bytes. */
-#define I2C_B2(ATTR, VAL)	(((ATTR) << 6) | ((VAL) << 24))
-#define I2C_B1(ATTR, VAL)	(((ATTR) << 4) | ((VAL) << 16))
-#define I2C_B0(ATTR, VAL)	(((ATTR) << 2) | ((VAL) <<  8))
+/* Write a time slot control record to TSL2. */
+#define S626_VECTPORT(VECTNUM)		(S626_P_TSL2 + ((VECTNUM) << 2))
 
 static const struct comedi_lrange s626_range_table = {
 	2, {
@@ -183,178 +203,182 @@
 	}
 };
 
-/*  Execute a DEBI transfer.  This must be called from within a */
-/*  critical section. */
-static void DEBItransfer(struct comedi_device *dev)
+/*
+ * Execute a DEBI transfer.  This must be called from within a critical section.
+ */
+static void s626_debi_transfer(struct comedi_device *dev)
 {
 	struct s626_private *devpriv = dev->private;
 
 	/* Initiate upload of shadow RAM to DEBI control register */
-	s626_mc_enable(dev, MC2_UPLD_DEBI, P_MC2);
+	s626_mc_enable(dev, S626_MC2_UPLD_DEBI, S626_P_MC2);
 
 	/*
 	 * Wait for completion of upload from shadow RAM to
 	 * DEBI control register.
 	 */
-	while (!s626_mc_test(dev, MC2_UPLD_DEBI, P_MC2))
+	while (!s626_mc_test(dev, S626_MC2_UPLD_DEBI, S626_P_MC2))
 		;
 
 	/* Wait until DEBI transfer is done */
-	while (readl(devpriv->mmio + P_PSR) & PSR_DEBI_S)
+	while (readl(devpriv->mmio + S626_P_PSR) & S626_PSR_DEBI_S)
 		;
 }
 
-/*  Initialize the DEBI interface for all transfers. */
-
-static uint16_t DEBIread(struct comedi_device *dev, uint16_t addr)
+/*
+ * Read a value from a gate array register.
+ */
+static uint16_t s626_debi_read(struct comedi_device *dev, uint16_t addr)
 {
 	struct s626_private *devpriv = dev->private;
 
 	/* Set up DEBI control register value in shadow RAM */
-	writel(DEBI_CMD_RDWORD | addr, devpriv->mmio + P_DEBICMD);
+	writel(S626_DEBI_CMD_RDWORD | addr, devpriv->mmio + S626_P_DEBICMD);
 
 	/*  Execute the DEBI transfer. */
-	DEBItransfer(dev);
+	s626_debi_transfer(dev);
 
-	return readl(devpriv->mmio + P_DEBIAD);
+	return readl(devpriv->mmio + S626_P_DEBIAD);
 }
 
-/*  Write a value to a gate array register. */
-static void DEBIwrite(struct comedi_device *dev, uint16_t addr, uint16_t wdata)
+/*
+ * Write a value to a gate array register.
+ */
+static void s626_debi_write(struct comedi_device *dev, uint16_t addr,
+			    uint16_t wdata)
 {
 	struct s626_private *devpriv = dev->private;
 
 	/* Set up DEBI control register value in shadow RAM */
-	writel(DEBI_CMD_WRWORD | addr, devpriv->mmio + P_DEBICMD);
-	writel(wdata, devpriv->mmio + P_DEBIAD);
+	writel(S626_DEBI_CMD_WRWORD | addr, devpriv->mmio + S626_P_DEBICMD);
+	writel(wdata, devpriv->mmio + S626_P_DEBIAD);
 
 	/*  Execute the DEBI transfer. */
-	DEBItransfer(dev);
+	s626_debi_transfer(dev);
 }
 
-/* Replace the specified bits in a gate array register.  Imports: mask
+/*
+ * Replace the specified bits in a gate array register.  Imports: mask
  * specifies bits that are to be preserved, wdata is new value to be
  * or'd with the masked original.
  */
-static void DEBIreplace(struct comedi_device *dev, unsigned int addr,
-			unsigned int mask, unsigned int wdata)
+static void s626_debi_replace(struct comedi_device *dev, unsigned int addr,
+			      unsigned int mask, unsigned int wdata)
 {
 	struct s626_private *devpriv = dev->private;
 	unsigned int val;
 
 	addr &= 0xffff;
-	writel(DEBI_CMD_RDWORD | addr, devpriv->mmio + P_DEBICMD);
-	DEBItransfer(dev);
+	writel(S626_DEBI_CMD_RDWORD | addr, devpriv->mmio + S626_P_DEBICMD);
+	s626_debi_transfer(dev);
 
-	writel(DEBI_CMD_WRWORD | addr, devpriv->mmio + P_DEBICMD);
-	val = readl(devpriv->mmio + P_DEBIAD);
+	writel(S626_DEBI_CMD_WRWORD | addr, devpriv->mmio + S626_P_DEBICMD);
+	val = readl(devpriv->mmio + S626_P_DEBIAD);
 	val &= mask;
 	val |= wdata;
-	writel(val & 0xffff, devpriv->mmio + P_DEBIAD);
-	DEBItransfer(dev);
+	writel(val & 0xffff, devpriv->mmio + S626_P_DEBIAD);
+	s626_debi_transfer(dev);
 }
 
 /* **************  EEPROM ACCESS FUNCTIONS  ************** */
 
-static uint32_t I2Chandshake(struct comedi_device *dev, uint32_t val)
+static uint32_t s626_i2c_handshake(struct comedi_device *dev, uint32_t val)
 {
 	struct s626_private *devpriv = dev->private;
 	unsigned int ctrl;
 
 	/* Write I2C command to I2C Transfer Control shadow register */
-	writel(val, devpriv->mmio + P_I2CCTRL);
+	writel(val, devpriv->mmio + S626_P_I2CCTRL);
 
 	/*
 	 * Upload I2C shadow registers into working registers and
 	 * wait for upload confirmation.
 	 */
-	s626_mc_enable(dev, MC2_UPLD_IIC, P_MC2);
-	while (!s626_mc_test(dev, MC2_UPLD_IIC, P_MC2))
+	s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2);
+	while (!s626_mc_test(dev, S626_MC2_UPLD_IIC, S626_P_MC2))
 		;
 
 	/* Wait until I2C bus transfer is finished or an error occurs */
 	do {
-		ctrl = readl(devpriv->mmio + P_I2CCTRL);
-	} while ((ctrl & (I2C_BUSY | I2C_ERR)) == I2C_BUSY);
+		ctrl = readl(devpriv->mmio + S626_P_I2CCTRL);
+	} while ((ctrl & (S626_I2C_BUSY | S626_I2C_ERR)) == S626_I2C_BUSY);
 
 	/* Return non-zero if I2C error occurred */
-	return ctrl & I2C_ERR;
+	return ctrl & S626_I2C_ERR;
 }
 
-/*  Read uint8_t from EEPROM. */
-static uint8_t I2Cread(struct comedi_device *dev, uint8_t addr)
+/* Read uint8_t from EEPROM. */
+static uint8_t s626_i2c_read(struct comedi_device *dev, uint8_t addr)
 {
 	struct s626_private *devpriv = dev->private;
 
-	/*  Send EEPROM target address. */
-	if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CW)
-			 /* Byte2 = I2C command: write to I2C EEPROM  device. */
-			 | I2C_B1(I2C_ATTRSTOP, addr)
-			 /* Byte1 = EEPROM internal target address. */
-			 | I2C_B0(I2C_ATTRNOP, 0))) {	/*  Byte0 = Not sent. */
-		/*  Abort function and declare error if handshake failed. */
+	/*
+	 * Send EEPROM target address:
+	 *  Byte2 = I2C command: write to I2C EEPROM device.
+	 *  Byte1 = EEPROM internal target address.
+	 *  Byte0 = Not sent.
+	 */
+	if (s626_i2c_handshake(dev, S626_I2C_B2(S626_I2C_ATTRSTART,
+						devpriv->i2c_adrs) |
+				    S626_I2C_B1(S626_I2C_ATTRSTOP, addr) |
+				    S626_I2C_B0(S626_I2C_ATTRNOP, 0)))
+		/* Abort function and declare error if handshake failed. */
 		return 0;
-	}
-	/*  Execute EEPROM read. */
-	if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CR)
 
-			 /*  Byte2 = I2C */
-			 /*  command: read */
-			 /*  from I2C EEPROM */
-			 /*  device. */
-			 |I2C_B1(I2C_ATTRSTOP, 0)
-
-			 /*  Byte1 receives */
-			 /*  uint8_t from */
-			 /*  EEPROM. */
-			 |I2C_B0(I2C_ATTRNOP, 0))) {	/*  Byte0 = Not  sent. */
-
-		/*  Abort function and declare error if handshake failed. */
+	/*
+	 * Execute EEPROM read:
+	 *  Byte2 = I2C command: read from I2C EEPROM device.
+	 *  Byte1 receives uint8_t from EEPROM.
+	 *  Byte0 = Not sent.
+	 */
+	if (s626_i2c_handshake(dev, S626_I2C_B2(S626_I2C_ATTRSTART,
+					   (devpriv->i2c_adrs | 1)) |
+				    S626_I2C_B1(S626_I2C_ATTRSTOP, 0) |
+				    S626_I2C_B0(S626_I2C_ATTRNOP, 0)))
+		/* Abort function and declare error if handshake failed. */
 		return 0;
-	}
 
-	return (readl(devpriv->mmio + P_I2CCTRL) >> 16) & 0xff;
+	return (readl(devpriv->mmio + S626_P_I2CCTRL) >> 16) & 0xff;
 }
 
 /* ***********  DAC FUNCTIONS *********** */
 
-/*  Slot 0 base settings. */
-#define VECT0	(XSD2 | RSD3 | SIB_A2)
-/*  Slot 0 always shifts in  0xFF and store it to  FB_BUFFER2. */
+/* TrimDac LogicalChan-to-PhysicalChan mapping table. */
+static const uint8_t s626_trimchan[] = { 10, 9, 8, 3, 2, 7, 6, 1, 0, 5, 4 };
 
-/*  TrimDac LogicalChan-to-PhysicalChan mapping table. */
-static uint8_t trimchan[] = { 10, 9, 8, 3, 2, 7, 6, 1, 0, 5, 4 };
+/* TrimDac LogicalChan-to-EepromAdrs mapping table. */
+static const uint8_t s626_trimadrs[] = {
+	0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x53, 0x60, 0x61, 0x62, 0x63
+};
 
-/*  TrimDac LogicalChan-to-EepromAdrs mapping table. */
-static uint8_t trimadrs[] = { 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x53, 0x60, 0x61, 0x62, 0x63 };
-
-/* Private helper function: Transmit serial data to DAC via Audio
+/*
+ * Private helper function: Transmit serial data to DAC via Audio
  * channel 2.  Assumes: (1) TSL2 slot records initialized, and (2)
- * Dacpol contains valid target image.
+ * dacpol contains valid target image.
  */
-static void SendDAC(struct comedi_device *dev, uint32_t val)
+static void s626_send_dac(struct comedi_device *dev, uint32_t val)
 {
 	struct s626_private *devpriv = dev->private;
 
 	/* START THE SERIAL CLOCK RUNNING ------------- */
 
-	/* Assert DAC polarity control and enable gating of DAC serial clock
+	/*
+	 * Assert DAC polarity control and enable gating of DAC serial clock
 	 * and audio bit stream signals.  At this point in time we must be
 	 * assured of being in time slot 0.  If we are not in slot 0, the
 	 * serial clock and audio stream signals will be disabled; this is
-	 * because the following DEBIwrite statement (which enables signals
-	 * to be passed through the gate array) would execute before the
-	 * trailing edge of WS1/WS3 (which turns off the signals), thus
+	 * because the following s626_debi_write statement (which enables
+	 * signals to be passed through the gate array) would execute before
+	 * the trailing edge of WS1/WS3 (which turns off the signals), thus
 	 * causing the signals to be inactive during the DAC write.
 	 */
-	DEBIwrite(dev, LP_DACPOL, devpriv->Dacpol);
+	s626_debi_write(dev, S626_LP_DACPOL, devpriv->dacpol);
 
 	/* TRANSFER OUTPUT DWORD VALUE INTO A2'S OUTPUT FIFO ---------------- */
 
 	/* Copy DAC setpoint value to DAC's output DMA buffer. */
-
-	/* writel(val, devpriv->mmio + (uint32_t)devpriv->pDacWBuf); */
-	*devpriv->pDacWBuf = val;
+	/* writel(val, devpriv->mmio + (uint32_t)devpriv->dac_wbuf); */
+	*devpriv->dac_wbuf = val;
 
 	/*
 	 * Enable the output DMA transfer. This will cause the DMAC to copy
@@ -362,56 +386,62 @@
 	 * then immediately terminate because the protection address is
 	 * reached upon transfer of the first DWORD value.
 	 */
-	s626_mc_enable(dev, MC1_A2OUT, P_MC1);
+	s626_mc_enable(dev, S626_MC1_A2OUT, S626_P_MC1);
 
-	/*  While the DMA transfer is executing ... */
+	/* While the DMA transfer is executing ... */
 
 	/*
 	 * Reset Audio2 output FIFO's underflow flag (along with any
 	 * other FIFO underflow/overflow flags). When set, this flag
 	 * will indicate that we have emerged from slot 0.
 	 */
-	writel(ISR_AFOU, devpriv->mmio + P_ISR);
+	writel(S626_ISR_AFOU, devpriv->mmio + S626_P_ISR);
 
-	/* Wait for the DMA transfer to finish so that there will be data
+	/*
+	 * Wait for the DMA transfer to finish so that there will be data
 	 * available in the FIFO when time slot 1 tries to transfer a DWORD
 	 * from the FIFO to the output buffer register.  We test for DMA
 	 * Done by polling the DMAC enable flag; this flag is automatically
 	 * cleared when the transfer has finished.
 	 */
-	while (readl(devpriv->mmio + P_MC1) & MC1_A2OUT)
+	while (readl(devpriv->mmio + S626_P_MC1) & S626_MC1_A2OUT)
 		;
 
 	/* START THE OUTPUT STREAM TO THE TARGET DAC -------------------- */
 
-	/* FIFO data is now available, so we enable execution of time slots
+	/*
+	 * FIFO data is now available, so we enable execution of time slots
 	 * 1 and higher by clearing the EOS flag in slot 0.  Note that SD3
 	 * will be shifted in and stored in FB_BUFFER2 for end-of-slot-list
 	 * detection.
 	 */
-	writel(XSD2 | RSD3 | SIB_A2, devpriv->mmio + VECTPORT(0));
+	writel(S626_XSD2 | S626_RSD3 | S626_SIB_A2,
+	       devpriv->mmio + S626_VECTPORT(0));
 
-	/* Wait for slot 1 to execute to ensure that the Packet will be
+	/*
+	 * Wait for slot 1 to execute to ensure that the Packet will be
 	 * transmitted.  This is detected by polling the Audio2 output FIFO
 	 * underflow flag, which will be set when slot 1 execution has
 	 * finished transferring the DAC's data DWORD from the output FIFO
 	 * to the output buffer register.
 	 */
-	while (!(readl(devpriv->mmio + P_SSR) & SSR_AF2_OUT))
+	while (!(readl(devpriv->mmio + S626_P_SSR) & S626_SSR_AF2_OUT))
 		;
 
-	/* Set up to trap execution at slot 0 when the TSL sequencer cycles
+	/*
+	 * Set up to trap execution at slot 0 when the TSL sequencer cycles
 	 * back to slot 0 after executing the EOS in slot 5.  Also,
 	 * simultaneously shift out and in the 0x00 that is ALWAYS the value
 	 * stored in the last byte to be shifted out of the FIFO's DWORD
 	 * buffer register.
 	 */
-	writel(XSD2 | XFIFO_2 | RSD2 | SIB_A2 | EOS,
-	       devpriv->mmio + VECTPORT(0));
+	writel(S626_XSD2 | S626_XFIFO_2 | S626_RSD2 | S626_SIB_A2 | S626_EOS,
+	       devpriv->mmio + S626_VECTPORT(0));
 
 	/* WAIT FOR THE TRANSACTION TO FINISH ----------------------- */
 
-	/* Wait for the TSL to finish executing all time slots before
+	/*
+	 * Wait for the TSL to finish executing all time slots before
 	 * exiting this function.  We must do this so that the next DAC
 	 * write doesn't start, thereby enabling clock/chip select signals:
 	 *
@@ -428,17 +458,19 @@
 	 *    we test for the FB_BUFFER2 MSB contents to be equal to 0xFF.  If
 	 *    the TSL has not yet finished executing slot 5 ...
 	 */
-	if (readl(devpriv->mmio + P_FB_BUFFER2) & 0xff000000) {
-		/* The trap was set on time and we are still executing somewhere
+	if (readl(devpriv->mmio + S626_P_FB_BUFFER2) & 0xff000000) {
+		/*
+		 * The trap was set on time and we are still executing somewhere
 		 * in slots 2-5, so we now wait for slot 0 to execute and trap
 		 * TSL execution.  This is detected when FB_BUFFER2 MSB changes
 		 * from 0xFF to 0x00, which slot 0 causes to happen by shifting
 		 * out/in on SD2 the 0x00 that is always referenced by slot 5.
 		 */
-		while (readl(devpriv->mmio + P_FB_BUFFER2) & 0xff000000)
+		while (readl(devpriv->mmio + S626_P_FB_BUFFER2) & 0xff000000)
 			;
 	}
-	/* Either (1) we were too late setting the slot 0 trap; the TSL
+	/*
+	 * Either (1) we were too late setting the slot 0 trap; the TSL
 	 * sequencer restarted slot 0 before we could set the EOS trap flag,
 	 * or (2) we were not late and execution is now trapped at slot 0.
 	 * In either case, we must now change slot 0 so that it will store
@@ -446,37 +478,46 @@
 	 * In order to do this, we reprogram slot 0 so that it will shift in
 	 * SD3, which is driven only by a pull-up resistor.
 	 */
-	writel(RSD3 | SIB_A2 | EOS, devpriv->mmio + VECTPORT(0));
+	writel(S626_RSD3 | S626_SIB_A2 | S626_EOS,
+	       devpriv->mmio + S626_VECTPORT(0));
 
-	/* Wait for slot 0 to execute, at which time the TSL is setup for
+	/*
+	 * Wait for slot 0 to execute, at which time the TSL is setup for
 	 * the next DAC write.  This is detected when FB_BUFFER2 MSB changes
 	 * from 0x00 to 0xFF.
 	 */
-	while (!(readl(devpriv->mmio + P_FB_BUFFER2) & 0xff000000))
+	while (!(readl(devpriv->mmio + S626_P_FB_BUFFER2) & 0xff000000))
 		;
 }
 
-/*  Private helper function: Write setpoint to an application DAC channel. */
-static void SetDAC(struct comedi_device *dev, uint16_t chan, short dacdata)
+/*
+ * Private helper function: Write setpoint to an application DAC channel.
+ */
+static void s626_set_dac(struct comedi_device *dev, uint16_t chan,
+			 unsigned short dacdata)
 {
 	struct s626_private *devpriv = dev->private;
-	register uint16_t signmask;
-	register uint32_t WSImage;
+	uint16_t signmask;
+	uint32_t ws_image;
+	uint32_t val;
 
-	/*  Adjust DAC data polarity and set up Polarity Control Register */
-	/*  image. */
+	/*
+	 * Adjust DAC data polarity and set up Polarity Control Register image.
+	 */
 	signmask = 1 << chan;
 	if (dacdata < 0) {
 		dacdata = -dacdata;
-		devpriv->Dacpol |= signmask;
-	} else
-		devpriv->Dacpol &= ~signmask;
+		devpriv->dacpol |= signmask;
+	} else {
+		devpriv->dacpol &= ~signmask;
+	}
 
-	/*  Limit DAC setpoint value to valid range. */
-	if ((uint16_t) dacdata > 0x1FFF)
+	/* Limit DAC setpoint value to valid range. */
+	if ((uint16_t)dacdata > 0x1FFF)
 		dacdata = 0x1FFF;
 
-	/* Set up TSL2 records (aka "vectors") for DAC update.  Vectors V2
+	/*
+	 * Set up TSL2 records (aka "vectors") for DAC update.  Vectors V2
 	 * and V3 transmit the setpoint to the target DAC.  V4 and V5 send
 	 * data to a non-existent TrimDac channel just to keep the clock
 	 * running after sending data to the target DAC.  This is necessary
@@ -487,140 +528,792 @@
 	 */
 
 	/* Choose DAC chip select to be asserted */
-	WSImage = (chan & 2) ? WS1 : WS2;
+	ws_image = (chan & 2) ? S626_WS1 : S626_WS2;
 	/* Slot 2: Transmit high data byte to target DAC */
-	writel(XSD2 | XFIFO_1 | WSImage, devpriv->mmio + VECTPORT(2));
+	writel(S626_XSD2 | S626_XFIFO_1 | ws_image,
+	       devpriv->mmio + S626_VECTPORT(2));
 	/* Slot 3: Transmit low data byte to target DAC */
-	writel(XSD2 | XFIFO_0 | WSImage, devpriv->mmio + VECTPORT(3));
+	writel(S626_XSD2 | S626_XFIFO_0 | ws_image,
+	       devpriv->mmio + S626_VECTPORT(3));
 	/* Slot 4: Transmit to non-existent TrimDac channel to keep clock */
-	writel(XSD2 | XFIFO_3 | WS3, devpriv->mmio + VECTPORT(4));
+	writel(S626_XSD2 | S626_XFIFO_3 | S626_WS3,
+	       devpriv->mmio + S626_VECTPORT(4));
 	/* Slot 5: running after writing target DAC's low data byte */
-	writel(XSD2 | XFIFO_2 | WS3 | EOS, devpriv->mmio + VECTPORT(5));
+	writel(S626_XSD2 | S626_XFIFO_2 | S626_WS3 | S626_EOS,
+	       devpriv->mmio + S626_VECTPORT(5));
 
-	/*  Construct and transmit target DAC's serial packet:
-	 * ( A10D DDDD ),( DDDD DDDD ),( 0x0F ),( 0x00 ) where A is chan<0>,
+	/*
+	 * Construct and transmit target DAC's serial packet:
+	 * (A10D DDDD), (DDDD DDDD), (0x0F), (0x00) where A is chan<0>,
 	 * and D<12:0> is the DAC setpoint.  Append a WORD value (that writes
 	 * to a  non-existent TrimDac channel) that serves to keep the clock
 	 * running after the packet has been sent to the target DAC.
 	 */
-	SendDAC(dev, 0x0F000000
-		/* Continue clock after target DAC data (write to non-existent trimdac). */
-		| 0x00004000
-		/* Address the two main dual-DAC devices (TSL's chip select enables
-		 * target device). */
-		| ((uint32_t) (chan & 1) << 15)
-		/*  Address the DAC channel within the  device. */
-		| (uint32_t) dacdata);	/*  Include DAC setpoint data. */
-
+	val = 0x0F000000;	/* Continue clock after target DAC data
+				 * (write to non-existent trimdac). */
+	val |= 0x00004000;	/* Address the two main dual-DAC devices
+				 * (TSL's chip select enables target device). */
+	val |= ((uint32_t)(chan & 1) << 15);	/* Address the DAC channel
+						 * within the device. */
+	val |= (uint32_t)dacdata;	/* Include DAC setpoint data. */
+	s626_send_dac(dev, val);
 }
 
-static void WriteTrimDAC(struct comedi_device *dev, uint8_t LogicalChan,
-			 uint8_t DacData)
+static void s626_write_trim_dac(struct comedi_device *dev, uint8_t logical_chan,
+				uint8_t dac_data)
 {
 	struct s626_private *devpriv = dev->private;
 	uint32_t chan;
 
-	/*  Save the new setpoint in case the application needs to read it back later. */
-	devpriv->TrimSetpoint[LogicalChan] = (uint8_t) DacData;
+	/*
+	 * Save the new setpoint in case the application needs to read it back
+	 * later.
+	 */
+	devpriv->trim_setpoint[logical_chan] = (uint8_t)dac_data;
 
-	/*  Map logical channel number to physical channel number. */
-	chan = (uint32_t) trimchan[LogicalChan];
+	/* Map logical channel number to physical channel number. */
+	chan = s626_trimchan[logical_chan];
 
-	/* Set up TSL2 records for TrimDac write operation.  All slots shift
+	/*
+	 * Set up TSL2 records for TrimDac write operation.  All slots shift
 	 * 0xFF in from pulled-up SD3 so that the end of the slot sequence
 	 * can be detected.
 	 */
 
 	/* Slot 2: Send high uint8_t to target TrimDac */
-	writel(XSD2 | XFIFO_1 | WS3, devpriv->mmio + VECTPORT(2));
+	writel(S626_XSD2 | S626_XFIFO_1 | S626_WS3,
+	       devpriv->mmio + S626_VECTPORT(2));
 	/* Slot 3: Send low uint8_t to target TrimDac */
-	writel(XSD2 | XFIFO_0 | WS3, devpriv->mmio + VECTPORT(3));
+	writel(S626_XSD2 | S626_XFIFO_0 | S626_WS3,
+	       devpriv->mmio + S626_VECTPORT(3));
 	/* Slot 4: Send NOP high uint8_t to DAC0 to keep clock running */
-	writel(XSD2 | XFIFO_3 | WS1, devpriv->mmio + VECTPORT(4));
+	writel(S626_XSD2 | S626_XFIFO_3 | S626_WS1,
+	       devpriv->mmio + S626_VECTPORT(4));
 	/* Slot 5: Send NOP low  uint8_t to DAC0 */
-	writel(XSD2 | XFIFO_2 | WS1 | EOS, devpriv->mmio + VECTPORT(5));
+	writel(S626_XSD2 | S626_XFIFO_2 | S626_WS1 | S626_EOS,
+	       devpriv->mmio + S626_VECTPORT(5));
 
-	/* Construct and transmit target DAC's serial packet:
-	 * ( 0000 AAAA ), ( DDDD DDDD ),( 0x00 ),( 0x00 ) where A<3:0> is the
+	/*
+	 * Construct and transmit target DAC's serial packet:
+	 * (0000 AAAA), (DDDD DDDD), (0x00), (0x00) where A<3:0> is the
 	 * DAC channel's address, and D<7:0> is the DAC setpoint.  Append a
 	 * WORD value (that writes a channel 0 NOP command to a non-existent
 	 * main DAC channel) that serves to keep the clock running after the
 	 * packet has been sent to the target DAC.
 	 */
 
-	/*  Address the DAC channel within the trimdac device. */
-	SendDAC(dev, ((uint32_t) chan << 8)
-		| (uint32_t) DacData);	/*  Include DAC setpoint data. */
+	/*
+	 * Address the DAC channel within the trimdac device.
+	 * Include DAC setpoint data.
+	 */
+	s626_send_dac(dev, (chan << 8) | dac_data);
 }
 
-static void LoadTrimDACs(struct comedi_device *dev)
+static void s626_load_trim_dacs(struct comedi_device *dev)
 {
-	register uint8_t i;
+	uint8_t i;
 
-	/*  Copy TrimDac setpoint values from EEPROM to TrimDacs. */
-	for (i = 0; i < ARRAY_SIZE(trimchan); i++)
-		WriteTrimDAC(dev, i, I2Cread(dev, trimadrs[i]));
+	/* Copy TrimDac setpoint values from EEPROM to TrimDacs. */
+	for (i = 0; i < ARRAY_SIZE(s626_trimchan); i++)
+		s626_write_trim_dac(dev, i,
+				    s626_i2c_read(dev, s626_trimadrs[i]));
 }
 
 /* ******  COUNTER FUNCTIONS  ******* */
-/* All counter functions address a specific counter by means of the
+
+/*
+ * All counter functions address a specific counter by means of the
  * "Counter" argument, which is a logical counter number.  The Counter
  * argument may have any of the following legal values: 0=0A, 1=1A,
  * 2=2A, 3=0B, 4=1B, 5=2B.
  */
 
-/*  Read a counter's output latch. */
-static uint32_t ReadLatch(struct comedi_device *dev, struct enc_private *k)
+/*
+ * Read a counter's output latch.
+ */
+static uint32_t s626_read_latch(struct comedi_device *dev,
+				const struct s626_enc_info *k)
 {
-	register uint32_t value;
+	uint32_t value;
 
-	/*  Latch counts and fetch LSW of latched counts value. */
-	value = (uint32_t) DEBIread(dev, k->MyLatchLsw);
+	/* Latch counts and fetch LSW of latched counts value. */
+	value = s626_debi_read(dev, k->my_latch_lsw);
 
-	/*  Fetch MSW of latched counts and combine with LSW. */
-	value |= ((uint32_t) DEBIread(dev, k->MyLatchLsw + 2) << 16);
+	/* Fetch MSW of latched counts and combine with LSW. */
+	value |= ((uint32_t)s626_debi_read(dev, k->my_latch_lsw + 2) << 16);
 
-	/*  Return latched counts. */
+	/* Return latched counts. */
 	return value;
 }
 
-/* Return/set a counter pair's latch trigger source.  0: On read
+/*
+ * Return/set a counter pair's latch trigger source.  0: On read
  * access, 1: A index latches A, 2: B index latches B, 3: A overflow
  * latches B.
  */
-static void SetLatchSource(struct comedi_device *dev, struct enc_private *k,
-			   uint16_t value)
+static void s626_set_latch_source(struct comedi_device *dev,
+				  const struct s626_enc_info *k, uint16_t value)
 {
-	DEBIreplace(dev, k->MyCRB,
-		    ~(CRBMSK_INTCTRL | CRBMSK_LATCHSRC),
-		    value << CRBBIT_LATCHSRC);
+	s626_debi_replace(dev, k->my_crb,
+			  ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_LATCHSRC),
+			  S626_SET_CRB_LATCHSRC(value));
 }
 
-/*  Write value into counter preload register. */
-static void Preload(struct comedi_device *dev, struct enc_private *k,
-		    uint32_t value)
+/*
+ * Write value into counter preload register.
+ */
+static void s626_preload(struct comedi_device *dev,
+			 const struct s626_enc_info *k, uint32_t value)
 {
-	DEBIwrite(dev, (uint16_t) (k->MyLatchLsw), (uint16_t) value);
-	DEBIwrite(dev, (uint16_t) (k->MyLatchLsw + 2),
-		  (uint16_t) (value >> 16));
+	s626_debi_write(dev, k->my_latch_lsw, value);
+	s626_debi_write(dev, k->my_latch_lsw + 2, value >> 16);
 }
 
-static unsigned int s626_ai_reg_to_uint(int data)
+/* ******  PRIVATE COUNTER FUNCTIONS ****** */
+
+/*
+ * Reset a counter's index and overflow event capture flags.
+ */
+static void s626_reset_cap_flags_a(struct comedi_device *dev,
+				   const struct s626_enc_info *k)
 {
-	unsigned int tempdata;
-
-	tempdata = (data >> 18);
-	if (tempdata & 0x2000)
-		tempdata &= 0x1fff;
-	else
-		tempdata += (1 << 13);
-
-	return tempdata;
+	s626_debi_replace(dev, k->my_crb, ~S626_CRBMSK_INTCTRL,
+			  (S626_SET_CRB_INTRESETCMD(1) |
+			   S626_SET_CRB_INTRESET_A(1)));
 }
 
-/* static unsigned int s626_uint_to_reg(struct comedi_subdevice *s, int data){ */
-/*   return 0; */
-/* } */
+static void s626_reset_cap_flags_b(struct comedi_device *dev,
+				   const struct s626_enc_info *k)
+{
+	s626_debi_replace(dev, k->my_crb, ~S626_CRBMSK_INTCTRL,
+			  (S626_SET_CRB_INTRESETCMD(1) |
+			   S626_SET_CRB_INTRESET_B(1)));
+}
+
+/*
+ * Return counter setup in a format (COUNTER_SETUP) that is consistent
+ * for both A and B counters.
+ */
+static uint16_t s626_get_mode_a(struct comedi_device *dev,
+				const struct s626_enc_info *k)
+{
+	uint16_t cra;
+	uint16_t crb;
+	uint16_t setup;
+	unsigned cntsrc, clkmult, clkpol, encmode;
+
+	/* Fetch CRA and CRB register images. */
+	cra = s626_debi_read(dev, k->my_cra);
+	crb = s626_debi_read(dev, k->my_crb);
+
+	/*
+	 * Populate the standardized counter setup bit fields.
+	 */
+	setup =
+		/* LoadSrc  = LoadSrcA. */
+		S626_SET_STD_LOADSRC(S626_GET_CRA_LOADSRC_A(cra)) |
+		/* LatchSrc = LatchSrcA. */
+		S626_SET_STD_LATCHSRC(S626_GET_CRB_LATCHSRC(crb)) |
+		/* IntSrc   = IntSrcA. */
+		S626_SET_STD_INTSRC(S626_GET_CRA_INTSRC_A(cra)) |
+		/* IndxSrc  = IndxSrcA. */
+		S626_SET_STD_INDXSRC(S626_GET_CRA_INDXSRC_A(cra)) |
+		/* IndxPol  = IndxPolA. */
+		S626_SET_STD_INDXPOL(S626_GET_CRA_INDXPOL_A(cra)) |
+		/* ClkEnab  = ClkEnabA. */
+		S626_SET_STD_CLKENAB(S626_GET_CRB_CLKENAB_A(crb));
+
+	/* Adjust mode-dependent parameters. */
+	cntsrc = S626_GET_CRA_CNTSRC_A(cra);
+	if (cntsrc & S626_CNTSRC_SYSCLK) {
+		/* Timer mode (CntSrcA<1> == 1): */
+		encmode = S626_ENCMODE_TIMER;
+		/* Set ClkPol to indicate count direction (CntSrcA<0>). */
+		clkpol = cntsrc & 1;
+		/* ClkMult must be 1x in Timer mode. */
+		clkmult = S626_CLKMULT_1X;
+	} else {
+		/* Counter mode (CntSrcA<1> == 0): */
+		encmode = S626_ENCMODE_COUNTER;
+		/* Pass through ClkPol. */
+		clkpol = S626_GET_CRA_CLKPOL_A(cra);
+		/* Force ClkMult to 1x if not legal, else pass through. */
+		clkmult = S626_GET_CRA_CLKMULT_A(cra);
+		if (clkmult == S626_CLKMULT_SPECIAL)
+			clkmult = S626_CLKMULT_1X;
+	}
+	setup |= S626_SET_STD_ENCMODE(encmode) | S626_SET_STD_CLKMULT(clkmult) |
+		 S626_SET_STD_CLKPOL(clkpol);
+
+	/* Return adjusted counter setup. */
+	return setup;
+}
+
+static uint16_t s626_get_mode_b(struct comedi_device *dev,
+				const struct s626_enc_info *k)
+{
+	uint16_t cra;
+	uint16_t crb;
+	uint16_t setup;
+	unsigned cntsrc, clkmult, clkpol, encmode;
+
+	/* Fetch CRA and CRB register images. */
+	cra = s626_debi_read(dev, k->my_cra);
+	crb = s626_debi_read(dev, k->my_crb);
+
+	/*
+	 * Populate the standardized counter setup bit fields.
+	 */
+	setup =
+		/* IntSrc   = IntSrcB. */
+		S626_SET_STD_INTSRC(S626_GET_CRB_INTSRC_B(crb)) |
+		/* LatchSrc = LatchSrcB. */
+		S626_SET_STD_LATCHSRC(S626_GET_CRB_LATCHSRC(crb)) |
+		/* LoadSrc  = LoadSrcB. */
+		S626_SET_STD_LOADSRC(S626_GET_CRB_LOADSRC_B(crb)) |
+		/* IndxPol  = IndxPolB. */
+		S626_SET_STD_INDXPOL(S626_GET_CRB_INDXPOL_B(crb)) |
+		/* ClkEnab  = ClkEnabB. */
+		S626_SET_STD_CLKENAB(S626_GET_CRB_CLKENAB_B(crb)) |
+		/* IndxSrc  = IndxSrcB. */
+		S626_SET_STD_INDXSRC(S626_GET_CRA_INDXSRC_B(cra));
+
+	/* Adjust mode-dependent parameters. */
+	cntsrc = S626_GET_CRA_CNTSRC_B(cra);
+	clkmult = S626_GET_CRB_CLKMULT_B(crb);
+	if (clkmult == S626_CLKMULT_SPECIAL) {
+		/* Extender mode (ClkMultB == S626_CLKMULT_SPECIAL): */
+		encmode = S626_ENCMODE_EXTENDER;
+		/* Indicate multiplier is 1x. */
+		clkmult = S626_CLKMULT_1X;
+		/* Set ClkPol equal to Timer count direction (CntSrcB<0>). */
+		clkpol = cntsrc & 1;
+	} else if (cntsrc & S626_CNTSRC_SYSCLK) {
+		/* Timer mode (CntSrcB<1> == 1): */
+		encmode = S626_ENCMODE_TIMER;
+		/* Indicate multiplier is 1x. */
+		clkmult = S626_CLKMULT_1X;
+		/* Set ClkPol equal to Timer count direction (CntSrcB<0>). */
+		clkpol = cntsrc & 1;
+	} else {
+		/* If Counter mode (CntSrcB<1> == 0): */
+		encmode = S626_ENCMODE_COUNTER;
+		/* Clock multiplier is passed through. */
+		/* Clock polarity is passed through. */
+		clkpol = S626_GET_CRB_CLKPOL_B(crb);
+	}
+	setup |= S626_SET_STD_ENCMODE(encmode) | S626_SET_STD_CLKMULT(clkmult) |
+		 S626_SET_STD_CLKPOL(clkpol);
+
+	/* Return adjusted counter setup. */
+	return setup;
+}
+
+/*
+ * Set the operating mode for the specified counter.  The setup
+ * parameter is treated as a COUNTER_SETUP data type.  The following
+ * parameters are programmable (all other parms are ignored): ClkMult,
+ * ClkPol, ClkEnab, IndexSrc, IndexPol, LoadSrc.
+ */
+static void s626_set_mode_a(struct comedi_device *dev,
+			    const struct s626_enc_info *k, uint16_t setup,
+			    uint16_t disable_int_src)
+{
+	struct s626_private *devpriv = dev->private;
+	uint16_t cra;
+	uint16_t crb;
+	unsigned cntsrc, clkmult, clkpol;
+
+	/* Initialize CRA and CRB images. */
+	/* Preload trigger is passed through. */
+	cra = S626_SET_CRA_LOADSRC_A(S626_GET_STD_LOADSRC(setup));
+	/* IndexSrc is passed through. */
+	cra |= S626_SET_CRA_INDXSRC_A(S626_GET_STD_INDXSRC(setup));
+
+	/* Reset any pending CounterA event captures. */
+	crb = S626_SET_CRB_INTRESETCMD(1) | S626_SET_CRB_INTRESET_A(1);
+	/* Clock enable is passed through. */
+	crb |= S626_SET_CRB_CLKENAB_A(S626_GET_STD_CLKENAB(setup));
+
+	/* Force IntSrc to Disabled if disable_int_src is asserted. */
+	if (!disable_int_src)
+		cra |= S626_SET_CRA_INTSRC_A(S626_GET_STD_INTSRC(setup));
+
+	/* Populate all mode-dependent attributes of CRA & CRB images. */
+	clkpol = S626_GET_STD_CLKPOL(setup);
+	switch (S626_GET_STD_ENCMODE(setup)) {
+	case S626_ENCMODE_EXTENDER: /* Extender Mode: */
+		/* Force to Timer mode (Extender valid only for B counters). */
+		/* Fall through to case S626_ENCMODE_TIMER: */
+	case S626_ENCMODE_TIMER:	/* Timer Mode: */
+		/* CntSrcA<1> selects system clock */
+		cntsrc = S626_CNTSRC_SYSCLK;
+		/* Count direction (CntSrcA<0>) obtained from ClkPol. */
+		cntsrc |= clkpol;
+		/* ClkPolA behaves as always-on clock enable. */
+		clkpol = 1;
+		/* ClkMult must be 1x. */
+		clkmult = S626_CLKMULT_1X;
+		break;
+	default:		/* Counter Mode: */
+		/* Select ENC_C and ENC_D as clock/direction inputs. */
+		cntsrc = S626_CNTSRC_ENCODER;
+		/* Clock polarity is passed through. */
+		/* Force multiplier to x1 if not legal, else pass through. */
+		clkmult = S626_GET_STD_CLKMULT(setup);
+		if (clkmult == S626_CLKMULT_SPECIAL)
+			clkmult = S626_CLKMULT_1X;
+		break;
+	}
+	cra |= S626_SET_CRA_CNTSRC_A(cntsrc) | S626_SET_CRA_CLKPOL_A(clkpol) |
+	       S626_SET_CRA_CLKMULT_A(clkmult);
+
+	/*
+	 * Force positive index polarity if IndxSrc is software-driven only,
+	 * otherwise pass it through.
+	 */
+	if (S626_GET_STD_INDXSRC(setup) != S626_INDXSRC_SOFT)
+		cra |= S626_SET_CRA_INDXPOL_A(S626_GET_STD_INDXPOL(setup));
+
+	/*
+	 * If IntSrc has been forced to Disabled, update the MISC2 interrupt
+	 * enable mask to indicate the counter interrupt is disabled.
+	 */
+	if (disable_int_src)
+		devpriv->counter_int_enabs &= ~k->my_event_bits[3];
+
+	/*
+	 * While retaining CounterB and LatchSrc configurations, program the
+	 * new counter operating mode.
+	 */
+	s626_debi_replace(dev, k->my_cra,
+			  S626_CRAMSK_INDXSRC_B | S626_CRAMSK_CNTSRC_B, cra);
+	s626_debi_replace(dev, k->my_crb,
+			  ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_CLKENAB_A), crb);
+}
+
+static void s626_set_mode_b(struct comedi_device *dev,
+			    const struct s626_enc_info *k, uint16_t setup,
+			    uint16_t disable_int_src)
+{
+	struct s626_private *devpriv = dev->private;
+	uint16_t cra;
+	uint16_t crb;
+	unsigned cntsrc, clkmult, clkpol;
+
+	/* Initialize CRA and CRB images. */
+	/* IndexSrc is passed through. */
+	cra = S626_SET_CRA_INDXSRC_B(S626_GET_STD_INDXSRC(setup));
+
+	/* Reset event captures and disable interrupts. */
+	crb = S626_SET_CRB_INTRESETCMD(1) | S626_SET_CRB_INTRESET_B(1);
+	/* Clock enable is passed through. */
+	crb |= S626_SET_CRB_CLKENAB_B(S626_GET_STD_CLKENAB(setup));
+	/* Preload trigger source is passed through. */
+	crb |= S626_SET_CRB_LOADSRC_B(S626_GET_STD_LOADSRC(setup));
+
+	/* Force IntSrc to Disabled if disable_int_src is asserted. */
+	if (!disable_int_src)
+		crb |= S626_SET_CRB_INTSRC_B(S626_GET_STD_INTSRC(setup));
+
+	/* Populate all mode-dependent attributes of CRA & CRB images. */
+	clkpol = S626_GET_STD_CLKPOL(setup);
+	switch (S626_GET_STD_ENCMODE(setup)) {
+	case S626_ENCMODE_TIMER:	/* Timer Mode: */
+		/* CntSrcB<1> selects system clock */
+		cntsrc = S626_CNTSRC_SYSCLK;
+		/* with direction (CntSrcB<0>) obtained from ClkPol. */
+		cntsrc |= clkpol;
+		/* ClkPolB behaves as always-on clock enable. */
+		clkpol = 1;
+		/* ClkMultB must be 1x. */
+		clkmult = S626_CLKMULT_1X;
+		break;
+	case S626_ENCMODE_EXTENDER:	/* Extender Mode: */
+		/* CntSrcB source is OverflowA (same as "timer") */
+		cntsrc = S626_CNTSRC_SYSCLK;
+		/* with direction obtained from ClkPol. */
+		cntsrc |= clkpol;
+		/* ClkPolB controls IndexB -- always set to active. */
+		clkpol = 1;
+		/* ClkMultB selects OverflowA as the clock source. */
+		clkmult = S626_CLKMULT_SPECIAL;
+		break;
+	default:		/* Counter Mode: */
+		/* Select ENC_C and ENC_D as clock/direction inputs. */
+		cntsrc = S626_CNTSRC_ENCODER;
+		/* ClkPol is passed through. */
+		/* Force ClkMult to x1 if not legal, otherwise pass through. */
+		clkmult = S626_GET_STD_CLKMULT(setup);
+		if (clkmult == S626_CLKMULT_SPECIAL)
+			clkmult = S626_CLKMULT_1X;
+		break;
+	}
+	cra |= S626_SET_CRA_CNTSRC_B(cntsrc);
+	crb |= S626_SET_CRB_CLKPOL_B(clkpol) | S626_SET_CRB_CLKMULT_B(clkmult);
+
+	/*
+	 * Force positive index polarity if IndxSrc is software-driven only,
+	 * otherwise pass it through.
+	 */
+	if (S626_GET_STD_INDXSRC(setup) != S626_INDXSRC_SOFT)
+		crb |= S626_SET_CRB_INDXPOL_B(S626_GET_STD_INDXPOL(setup));
+
+	/*
+	 * If IntSrc has been forced to Disabled, update the MISC2 interrupt
+	 * enable mask to indicate the counter interrupt is disabled.
+	 */
+	if (disable_int_src)
+		devpriv->counter_int_enabs &= ~k->my_event_bits[3];
+
+	/*
+	 * While retaining CounterA and LatchSrc configurations, program the
+	 * new counter operating mode.
+	 */
+	s626_debi_replace(dev, k->my_cra,
+			  ~(S626_CRAMSK_INDXSRC_B | S626_CRAMSK_CNTSRC_B), cra);
+	s626_debi_replace(dev, k->my_crb,
+			  S626_CRBMSK_CLKENAB_A | S626_CRBMSK_LATCHSRC, crb);
+}
+
+/*
+ * Return/set a counter's enable.  enab: 0=always enabled, 1=enabled by index.
+ */
+static void s626_set_enable_a(struct comedi_device *dev,
+			      const struct s626_enc_info *k, uint16_t enab)
+{
+	s626_debi_replace(dev, k->my_crb,
+			  ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_CLKENAB_A),
+			  S626_SET_CRB_CLKENAB_A(enab));
+}
+
+static void s626_set_enable_b(struct comedi_device *dev,
+			      const struct s626_enc_info *k, uint16_t enab)
+{
+	s626_debi_replace(dev, k->my_crb,
+			  ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_CLKENAB_B),
+			  S626_SET_CRB_CLKENAB_B(enab));
+}
+
+static uint16_t s626_get_enable_a(struct comedi_device *dev,
+				  const struct s626_enc_info *k)
+{
+	return S626_GET_CRB_CLKENAB_A(s626_debi_read(dev, k->my_crb));
+}
+
+static uint16_t s626_get_enable_b(struct comedi_device *dev,
+				  const struct s626_enc_info *k)
+{
+	return S626_GET_CRB_CLKENAB_B(s626_debi_read(dev, k->my_crb));
+}
+
+#ifdef unused
+static uint16_t s626_get_latch_source(struct comedi_device *dev,
+				      const struct s626_enc_info *k)
+{
+	return S626_GET_CRB_LATCHSRC(s626_debi_read(dev, k->my_crb));
+}
+#endif
+
+/*
+ * Return/set the event that will trigger transfer of the preload
+ * register into the counter.  0=ThisCntr_Index, 1=ThisCntr_Overflow,
+ * 2=OverflowA (B counters only), 3=disabled.
+ */
+static void s626_set_load_trig_a(struct comedi_device *dev,
+				 const struct s626_enc_info *k, uint16_t trig)
+{
+	s626_debi_replace(dev, k->my_cra, ~S626_CRAMSK_LOADSRC_A,
+			  S626_SET_CRA_LOADSRC_A(trig));
+}
+
+static void s626_set_load_trig_b(struct comedi_device *dev,
+				 const struct s626_enc_info *k, uint16_t trig)
+{
+	s626_debi_replace(dev, k->my_crb,
+			  ~(S626_CRBMSK_LOADSRC_B | S626_CRBMSK_INTCTRL),
+			  S626_SET_CRB_LOADSRC_B(trig));
+}
+
+static uint16_t s626_get_load_trig_a(struct comedi_device *dev,
+				     const struct s626_enc_info *k)
+{
+	return S626_GET_CRA_LOADSRC_A(s626_debi_read(dev, k->my_cra));
+}
+
+static uint16_t s626_get_load_trig_b(struct comedi_device *dev,
+				     const struct s626_enc_info *k)
+{
+	return S626_GET_CRB_LOADSRC_B(s626_debi_read(dev, k->my_crb));
+}
+
+/*
+ * Return/set counter interrupt source and clear any captured
+ * index/overflow events.  int_source: 0=Disabled, 1=OverflowOnly,
+ * 2=IndexOnly, 3=IndexAndOverflow.
+ */
+static void s626_set_int_src_a(struct comedi_device *dev,
+			       const struct s626_enc_info *k,
+			       uint16_t int_source)
+{
+	struct s626_private *devpriv = dev->private;
+
+	/* Reset any pending counter overflow or index captures. */
+	s626_debi_replace(dev, k->my_crb, ~S626_CRBMSK_INTCTRL,
+			  (S626_SET_CRB_INTRESETCMD(1) |
+			   S626_SET_CRB_INTRESET_A(1)));
+
+	/* Program counter interrupt source. */
+	s626_debi_replace(dev, k->my_cra, ~S626_CRAMSK_INTSRC_A,
+			  S626_SET_CRA_INTSRC_A(int_source));
+
+	/* Update MISC2 interrupt enable mask. */
+	devpriv->counter_int_enabs =
+	    (devpriv->counter_int_enabs & ~k->my_event_bits[3]) |
+	    k->my_event_bits[int_source];
+}
+
+static void s626_set_int_src_b(struct comedi_device *dev,
+			       const struct s626_enc_info *k,
+			       uint16_t int_source)
+{
+	struct s626_private *devpriv = dev->private;
+	uint16_t crb;
+
+	/* Cache writeable CRB register image. */
+	crb = s626_debi_read(dev, k->my_crb) & ~S626_CRBMSK_INTCTRL;
+
+	/* Reset any pending counter overflow or index captures. */
+	s626_debi_write(dev, k->my_crb, (crb | S626_SET_CRB_INTRESETCMD(1) |
+					 S626_SET_CRB_INTRESET_B(1)));
+
+	/* Program counter interrupt source. */
+	s626_debi_write(dev, k->my_crb, ((crb & ~S626_CRBMSK_INTSRC_B) |
+					 S626_SET_CRB_INTSRC_B(int_source)));
+
+	/* Update MISC2 interrupt enable mask. */
+	devpriv->counter_int_enabs =
+		(devpriv->counter_int_enabs & ~k->my_event_bits[3]) |
+		k->my_event_bits[int_source];
+}
+
+static uint16_t s626_get_int_src_a(struct comedi_device *dev,
+				   const struct s626_enc_info *k)
+{
+	return S626_GET_CRA_INTSRC_A(s626_debi_read(dev, k->my_cra));
+}
+
+static uint16_t s626_get_int_src_b(struct comedi_device *dev,
+				   const struct s626_enc_info *k)
+{
+	return S626_GET_CRB_INTSRC_B(s626_debi_read(dev, k->my_crb));
+}
+
+#ifdef unused
+/*
+ * Return/set the clock multiplier.
+ */
+static void s626_set_clk_mult(struct comedi_device *dev,
+			      const struct s626_enc_info *k, uint16_t value)
+{
+	k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_CLKMULT) |
+			     S626_SET_STD_CLKMULT(value)), false);
+}
+
+static uint16_t s626_get_clk_mult(struct comedi_device *dev,
+				  const struct s626_enc_info *k)
+{
+	return S626_GET_STD_CLKMULT(k->get_mode(dev, k));
+}
+
+/*
+ * Return/set the clock polarity.
+ */
+static void s626_set_clk_pol(struct comedi_device *dev,
+			     const struct s626_enc_info *k, uint16_t value)
+{
+	k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_CLKPOL) |
+			     S626_SET_STD_CLKPOL(value)), false);
+}
+
+static uint16_t s626_get_clk_pol(struct comedi_device *dev,
+				 const struct s626_enc_info *k)
+{
+	return S626_GET_STD_CLKPOL(k->get_mode(dev, k));
+}
+
+/*
+ * Return/set the encoder mode.
+ */
+static void s626_set_enc_mode(struct comedi_device *dev,
+			      const struct s626_enc_info *k, uint16_t value)
+{
+	k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_ENCMODE) |
+			     S626_SET_STD_ENCMODE(value)), false);
+}
+
+static uint16_t s626_get_enc_mode(struct comedi_device *dev,
+				  const struct s626_enc_info *k)
+{
+	return S626_GET_STD_ENCMODE(k->get_mode(dev, k));
+}
+
+/*
+ * Return/set the index polarity.
+ */
+static void s626_set_index_pol(struct comedi_device *dev,
+			       const struct s626_enc_info *k, uint16_t value)
+{
+	k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_INDXPOL) |
+			     S626_SET_STD_INDXPOL(value != 0)), false);
+}
+
+static uint16_t s626_get_index_pol(struct comedi_device *dev,
+				   const struct s626_enc_info *k)
+{
+	return S626_GET_STD_INDXPOL(k->get_mode(dev, k));
+}
+
+/*
+ * Return/set the index source.
+ */
+static void s626_set_index_src(struct comedi_device *dev,
+			       const struct s626_enc_info *k, uint16_t value)
+{
+	k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_INDXSRC) |
+			     S626_SET_STD_INDXSRC(value != 0)), false);
+}
+
+static uint16_t s626_get_index_src(struct comedi_device *dev,
+				   const struct s626_enc_info *k)
+{
+	return S626_GET_STD_INDXSRC(k->get_mode(dev, k));
+}
+#endif
+
+/*
+ * Generate an index pulse.
+ */
+static void s626_pulse_index_a(struct comedi_device *dev,
+			       const struct s626_enc_info *k)
+{
+	uint16_t cra;
+
+	cra = s626_debi_read(dev, k->my_cra);
+	/* Pulse index. */
+	s626_debi_write(dev, k->my_cra, (cra ^ S626_CRAMSK_INDXPOL_A));
+	s626_debi_write(dev, k->my_cra, cra);
+}
+
+static void s626_pulse_index_b(struct comedi_device *dev,
+			       const struct s626_enc_info *k)
+{
+	uint16_t crb;
+
+	crb = s626_debi_read(dev, k->my_crb) & ~S626_CRBMSK_INTCTRL;
+	/* Pulse index. */
+	s626_debi_write(dev, k->my_crb, (crb ^ S626_CRBMSK_INDXPOL_B));
+	s626_debi_write(dev, k->my_crb, crb);
+}
+
+static const struct s626_enc_info s626_enc_chan_info[] = {
+	{
+		.get_enable		= s626_get_enable_a,
+		.get_int_src		= s626_get_int_src_a,
+		.get_load_trig		= s626_get_load_trig_a,
+		.get_mode		= s626_get_mode_a,
+		.pulse_index		= s626_pulse_index_a,
+		.set_enable		= s626_set_enable_a,
+		.set_int_src		= s626_set_int_src_a,
+		.set_load_trig		= s626_set_load_trig_a,
+		.set_mode		= s626_set_mode_a,
+		.reset_cap_flags	= s626_reset_cap_flags_a,
+		.my_cra			= S626_LP_CR0A,
+		.my_crb			= S626_LP_CR0B,
+		.my_latch_lsw		= S626_LP_CNTR0ALSW,
+		.my_event_bits		= S626_EVBITS(0),
+	}, {
+		.get_enable		= s626_get_enable_a,
+		.get_int_src		= s626_get_int_src_a,
+		.get_load_trig		= s626_get_load_trig_a,
+		.get_mode		= s626_get_mode_a,
+		.pulse_index		= s626_pulse_index_a,
+		.set_enable		= s626_set_enable_a,
+		.set_int_src		= s626_set_int_src_a,
+		.set_load_trig		= s626_set_load_trig_a,
+		.set_mode		= s626_set_mode_a,
+		.reset_cap_flags	= s626_reset_cap_flags_a,
+		.my_cra			= S626_LP_CR1A,
+		.my_crb			= S626_LP_CR1B,
+		.my_latch_lsw		= S626_LP_CNTR1ALSW,
+		.my_event_bits		= S626_EVBITS(1),
+	}, {
+		.get_enable		= s626_get_enable_a,
+		.get_int_src		= s626_get_int_src_a,
+		.get_load_trig		= s626_get_load_trig_a,
+		.get_mode		= s626_get_mode_a,
+		.pulse_index		= s626_pulse_index_a,
+		.set_enable		= s626_set_enable_a,
+		.set_int_src		= s626_set_int_src_a,
+		.set_load_trig		= s626_set_load_trig_a,
+		.set_mode		= s626_set_mode_a,
+		.reset_cap_flags	= s626_reset_cap_flags_a,
+		.my_cra			= S626_LP_CR2A,
+		.my_crb			= S626_LP_CR2B,
+		.my_latch_lsw		= S626_LP_CNTR2ALSW,
+		.my_event_bits		= S626_EVBITS(2),
+	}, {
+		.get_enable		= s626_get_enable_b,
+		.get_int_src		= s626_get_int_src_b,
+		.get_load_trig		= s626_get_load_trig_b,
+		.get_mode		= s626_get_mode_b,
+		.pulse_index		= s626_pulse_index_b,
+		.set_enable		= s626_set_enable_b,
+		.set_int_src		= s626_set_int_src_b,
+		.set_load_trig		= s626_set_load_trig_b,
+		.set_mode		= s626_set_mode_b,
+		.reset_cap_flags	= s626_reset_cap_flags_b,
+		.my_cra			= S626_LP_CR0A,
+		.my_crb			= S626_LP_CR0B,
+		.my_latch_lsw		= S626_LP_CNTR0BLSW,
+		.my_event_bits		= S626_EVBITS(3),
+	}, {
+		.get_enable		= s626_get_enable_b,
+		.get_int_src		= s626_get_int_src_b,
+		.get_load_trig		= s626_get_load_trig_b,
+		.get_mode		= s626_get_mode_b,
+		.pulse_index		= s626_pulse_index_b,
+		.set_enable		= s626_set_enable_b,
+		.set_int_src		= s626_set_int_src_b,
+		.set_load_trig		= s626_set_load_trig_b,
+		.set_mode		= s626_set_mode_b,
+		.reset_cap_flags	= s626_reset_cap_flags_b,
+		.my_cra			= S626_LP_CR1A,
+		.my_crb			= S626_LP_CR1B,
+		.my_latch_lsw		= S626_LP_CNTR1BLSW,
+		.my_event_bits		= S626_EVBITS(4),
+	}, {
+		.get_enable		= s626_get_enable_b,
+		.get_int_src		= s626_get_int_src_b,
+		.get_load_trig		= s626_get_load_trig_b,
+		.get_mode		= s626_get_mode_b,
+		.pulse_index		= s626_pulse_index_b,
+		.set_enable		= s626_set_enable_b,
+		.set_int_src		= s626_set_int_src_b,
+		.set_load_trig		= s626_set_load_trig_b,
+		.set_mode		= s626_set_mode_b,
+		.reset_cap_flags	= s626_reset_cap_flags_b,
+		.my_cra			= S626_LP_CR2A,
+		.my_crb			= S626_LP_CR2B,
+		.my_latch_lsw		= S626_LP_CNTR2BLSW,
+		.my_event_bits		= S626_EVBITS(5),
+	},
+};
+
+static unsigned int s626_ai_reg_to_uint(unsigned int data)
+{
+	return ((data >> 18) & 0x3fff) ^ 0x2000;
+}
 
 static int s626_dio_set_irq(struct comedi_device *dev, unsigned int chan)
 {
@@ -629,19 +1322,19 @@
 	unsigned int status;
 
 	/* set channel to capture positive edge */
-	status = DEBIread(dev, LP_RDEDGSEL(group));
-	DEBIwrite(dev, LP_WREDGSEL(group), mask | status);
+	status = s626_debi_read(dev, S626_LP_RDEDGSEL(group));
+	s626_debi_write(dev, S626_LP_WREDGSEL(group), mask | status);
 
 	/* enable interrupt on selected channel */
-	status = DEBIread(dev, LP_RDINTSEL(group));
-	DEBIwrite(dev, LP_WRINTSEL(group), mask | status);
+	status = s626_debi_read(dev, S626_LP_RDINTSEL(group));
+	s626_debi_write(dev, S626_LP_WRINTSEL(group), mask | status);
 
 	/* enable edge capture write command */
-	DEBIwrite(dev, LP_MISC1, MISC1_EDCAP);
+	s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_EDCAP);
 
 	/* enable edge capture on selected channel */
-	status = DEBIread(dev, LP_RDCAPSEL(group));
-	DEBIwrite(dev, LP_WRCAPSEL(group), mask | status);
+	status = s626_debi_read(dev, S626_LP_RDCAPSEL(group));
+	s626_debi_write(dev, S626_LP_WRCAPSEL(group), mask | status);
 
 	return 0;
 }
@@ -650,10 +1343,10 @@
 			      unsigned int mask)
 {
 	/* disable edge capture write command */
-	DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP);
+	s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_NOEDCAP);
 
 	/* enable edge capture on selected channel */
-	DEBIwrite(dev, LP_WRCAPSEL(group), mask);
+	s626_debi_write(dev, S626_LP_WRCAPSEL(group), mask);
 
 	return 0;
 }
@@ -663,17 +1356,17 @@
 	unsigned int group;
 
 	/* disable edge capture write command */
-	DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP);
+	s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_NOEDCAP);
 
 	/* clear all dio pending events and interrupt */
 	for (group = 0; group < S626_DIO_BANKS; group++)
-		DEBIwrite(dev, LP_WRCAPSEL(group), 0xffff);
+		s626_debi_write(dev, S626_LP_WRCAPSEL(group), 0xffff);
 
 	return 0;
 }
 
-static void handle_dio_interrupt(struct comedi_device *dev,
-				 uint16_t irqbit, uint8_t group)
+static void s626_handle_dio_interrupt(struct comedi_device *dev,
+				      uint16_t irqbit, uint8_t group)
 {
 	struct s626_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
@@ -686,7 +1379,7 @@
 		if ((irqbit >> (cmd->start_arg - (16 * group))) == 1 &&
 		    cmd->start_src == TRIG_EXT) {
 			/* Start executing the RPS program */
-			s626_mc_enable(dev, MC1_ERPS1, P_MC1);
+			s626_mc_enable(dev, S626_MC1_ERPS1, S626_P_MC1);
 
 			if (cmd->scan_begin_src == TRIG_EXT)
 				s626_dio_set_irq(dev, cmd->scan_begin_arg);
@@ -694,7 +1387,7 @@
 		if ((irqbit >> (cmd->scan_begin_arg - (16 * group))) == 1 &&
 		    cmd->scan_begin_src == TRIG_EXT) {
 			/* Trigger ADC scan loop start */
-			s626_mc_enable(dev, MC2_ADC_RPS, P_MC2);
+			s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2);
 
 			if (cmd->convert_src == TRIG_EXT) {
 				devpriv->ai_convert_count = cmd->chanlist_len;
@@ -703,16 +1396,17 @@
 			}
 
 			if (cmd->convert_src == TRIG_TIMER) {
-				struct enc_private *k = &encpriv[5];
+				const struct s626_enc_info *k =
+					&s626_enc_chan_info[5];
 
 				devpriv->ai_convert_count = cmd->chanlist_len;
-				k->SetEnable(dev, k, CLKENAB_ALWAYS);
+				k->set_enable(dev, k, S626_CLKENAB_ALWAYS);
 			}
 		}
 		if ((irqbit >> (cmd->convert_arg - (16 * group))) == 1 &&
 		    cmd->convert_src == TRIG_EXT) {
 			/* Trigger ADC scan loop start */
-			s626_mc_enable(dev, MC2_ADC_RPS, P_MC2);
+			s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2);
 
 			devpriv->ai_convert_count--;
 			if (devpriv->ai_convert_count > 0)
@@ -721,7 +1415,7 @@
 	}
 }
 
-static void check_dio_interrupts(struct comedi_device *dev)
+static void s626_check_dio_interrupts(struct comedi_device *dev)
 {
 	uint16_t irqbit;
 	uint8_t group;
@@ -729,90 +1423,91 @@
 	for (group = 0; group < S626_DIO_BANKS; group++) {
 		irqbit = 0;
 		/* read interrupt type */
-		irqbit = DEBIread(dev, LP_RDCAPFLG(group));
+		irqbit = s626_debi_read(dev, S626_LP_RDCAPFLG(group));
 
 		/* check if interrupt is generated from dio channels */
 		if (irqbit) {
-			handle_dio_interrupt(dev, irqbit, group);
+			s626_handle_dio_interrupt(dev, irqbit, group);
 			return;
 		}
 	}
 }
 
-static void check_counter_interrupts(struct comedi_device *dev)
+static void s626_check_counter_interrupts(struct comedi_device *dev)
 {
 	struct s626_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
 	struct comedi_async *async = s->async;
 	struct comedi_cmd *cmd = &async->cmd;
-	struct enc_private *k;
+	const struct s626_enc_info *k;
 	uint16_t irqbit;
 
 	/* read interrupt type */
-	irqbit = DEBIread(dev, LP_RDMISC2);
+	irqbit = s626_debi_read(dev, S626_LP_RDMISC2);
 
 	/* check interrupt on counters */
-	if (irqbit & IRQ_COINT1A) {
-		k = &encpriv[0];
+	if (irqbit & S626_IRQ_COINT1A) {
+		k = &s626_enc_chan_info[0];
 
 		/* clear interrupt capture flag */
-		k->ResetCapFlags(dev, k);
+		k->reset_cap_flags(dev, k);
 	}
-	if (irqbit & IRQ_COINT2A) {
-		k = &encpriv[1];
+	if (irqbit & S626_IRQ_COINT2A) {
+		k = &s626_enc_chan_info[1];
 
 		/* clear interrupt capture flag */
-		k->ResetCapFlags(dev, k);
+		k->reset_cap_flags(dev, k);
 	}
-	if (irqbit & IRQ_COINT3A) {
-		k = &encpriv[2];
+	if (irqbit & S626_IRQ_COINT3A) {
+		k = &s626_enc_chan_info[2];
 
 		/* clear interrupt capture flag */
-		k->ResetCapFlags(dev, k);
+		k->reset_cap_flags(dev, k);
 	}
-	if (irqbit & IRQ_COINT1B) {
-		k = &encpriv[3];
+	if (irqbit & S626_IRQ_COINT1B) {
+		k = &s626_enc_chan_info[3];
 
 		/* clear interrupt capture flag */
-		k->ResetCapFlags(dev, k);
+		k->reset_cap_flags(dev, k);
 	}
-	if (irqbit & IRQ_COINT2B) {
-		k = &encpriv[4];
+	if (irqbit & S626_IRQ_COINT2B) {
+		k = &s626_enc_chan_info[4];
 
 		/* clear interrupt capture flag */
-		k->ResetCapFlags(dev, k);
+		k->reset_cap_flags(dev, k);
 
 		if (devpriv->ai_convert_count > 0) {
 			devpriv->ai_convert_count--;
 			if (devpriv->ai_convert_count == 0)
-				k->SetEnable(dev, k, CLKENAB_INDEX);
+				k->set_enable(dev, k, S626_CLKENAB_INDEX);
 
 			if (cmd->convert_src == TRIG_TIMER) {
 				/* Trigger ADC scan loop start */
-				s626_mc_enable(dev, MC2_ADC_RPS, P_MC2);
+				s626_mc_enable(dev, S626_MC2_ADC_RPS,
+					       S626_P_MC2);
 			}
 		}
 	}
-	if (irqbit & IRQ_COINT3B) {
-		k = &encpriv[5];
+	if (irqbit & S626_IRQ_COINT3B) {
+		k = &s626_enc_chan_info[5];
 
 		/* clear interrupt capture flag */
-		k->ResetCapFlags(dev, k);
+		k->reset_cap_flags(dev, k);
 
 		if (cmd->scan_begin_src == TRIG_TIMER) {
 			/* Trigger ADC scan loop start */
-			s626_mc_enable(dev, MC2_ADC_RPS, P_MC2);
+			s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2);
 		}
 
 		if (cmd->convert_src == TRIG_TIMER) {
-			k = &encpriv[4];
+			k = &s626_enc_chan_info[4];
 			devpriv->ai_convert_count = cmd->chanlist_len;
-			k->SetEnable(dev, k, CLKENAB_ALWAYS);
+			k->set_enable(dev, k, S626_CLKENAB_ALWAYS);
 		}
 	}
 }
 
-static bool handle_eos_interrupt(struct comedi_device *dev)
+static bool s626_handle_eos_interrupt(struct comedi_device *dev)
 {
 	struct s626_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
@@ -823,19 +1518,19 @@
 	 * first uint16_t in the buffer because it contains junk data
 	 * from the final ADC of the previous poll list scan.
 	 */
-	int32_t *readaddr = (int32_t *)devpriv->ANABuf.LogicalBase + 1;
+	uint32_t *readaddr = (uint32_t *)devpriv->ana_buf.logical_base + 1;
 	bool finished = false;
 	int i;
 
 	/* get the data and hand it over to comedi */
 	for (i = 0; i < cmd->chanlist_len; i++) {
-		short tempdata;
+		unsigned short tempdata;
 
 		/*
 		 * Convert ADC data to 16-bit integer values and copy
 		 * to application buffer.
 		 */
-		tempdata = s626_ai_reg_to_uint((int)*readaddr);
+		tempdata = s626_ai_reg_to_uint(*readaddr);
 		readaddr++;
 
 		/* put data into read buffer */
@@ -846,13 +1541,13 @@
 	/* end of scan occurs */
 	async->events |= COMEDI_CB_EOS;
 
-	if (!devpriv->ai_continous)
+	if (!devpriv->ai_continuous)
 		devpriv->ai_sample_count--;
 	if (devpriv->ai_sample_count <= 0) {
 		devpriv->ai_cmd_running = 0;
 
 		/* Stop RPS program */
-		s626_mc_disable(dev, MC1_ERPS1, P_MC1);
+		s626_mc_disable(dev, S626_MC1_ERPS1, S626_P_MC1);
 
 		/* send end of acquisition */
 		async->events |= COMEDI_CB_EOA;
@@ -879,229 +1574,238 @@
 
 	if (!dev->attached)
 		return IRQ_NONE;
-	/*  lock to avoid race with comedi_poll */
+	/* lock to avoid race with comedi_poll */
 	spin_lock_irqsave(&dev->spinlock, flags);
 
 	/* save interrupt enable register state */
-	irqstatus = readl(devpriv->mmio + P_IER);
+	irqstatus = readl(devpriv->mmio + S626_P_IER);
 
 	/* read interrupt type */
-	irqtype = readl(devpriv->mmio + P_ISR);
+	irqtype = readl(devpriv->mmio + S626_P_ISR);
 
 	/* disable master interrupt */
-	writel(0, devpriv->mmio + P_IER);
+	writel(0, devpriv->mmio + S626_P_IER);
 
 	/* clear interrupt */
-	writel(irqtype, devpriv->mmio + P_ISR);
+	writel(irqtype, devpriv->mmio + S626_P_ISR);
 
 	switch (irqtype) {
-	case IRQ_RPS1:		/*  end_of_scan occurs */
-		if (handle_eos_interrupt(dev))
+	case S626_IRQ_RPS1:	/* end_of_scan occurs */
+		if (s626_handle_eos_interrupt(dev))
 			irqstatus = 0;
 		break;
-	case IRQ_GPIO3:	/* check dio and conter interrupt */
+	case S626_IRQ_GPIO3:	/* check dio and counter interrupt */
 		/* s626_dio_clear_irq(dev); */
-		check_dio_interrupts(dev);
-		check_counter_interrupts(dev);
+		s626_check_dio_interrupts(dev);
+		s626_check_counter_interrupts(dev);
 		break;
 	}
 
 	/* enable interrupt */
-	writel(irqstatus, devpriv->mmio + P_IER);
+	writel(irqstatus, devpriv->mmio + S626_P_IER);
 
 	spin_unlock_irqrestore(&dev->spinlock, flags);
 	return IRQ_HANDLED;
 }
 
 /*
- * this functions build the RPS program for hardware driven acquistion
+ * This function builds the RPS program for hardware driven acquisition.
  */
-static void ResetADC(struct comedi_device *dev, uint8_t *ppl)
+static void s626_reset_adc(struct comedi_device *dev, uint8_t *ppl)
 {
 	struct s626_private *devpriv = dev->private;
-	register uint32_t *pRPS;
-	uint32_t JmpAdrs;
+	uint32_t *rps;
+	uint32_t jmp_adrs;
 	uint16_t i;
 	uint16_t n;
-	uint32_t LocalPPL;
-	struct comedi_cmd *cmd = &(dev->subdevices->async->cmd);
+	uint32_t local_ppl;
+	struct comedi_cmd *cmd = &dev->subdevices->async->cmd;
 
 	/* Stop RPS program in case it is currently running */
-	s626_mc_disable(dev, MC1_ERPS1, P_MC1);
+	s626_mc_disable(dev, S626_MC1_ERPS1, S626_P_MC1);
 
-	/*  Set starting logical address to write RPS commands. */
-	pRPS = (uint32_t *) devpriv->RPSBuf.LogicalBase;
+	/* Set starting logical address to write RPS commands. */
+	rps = (uint32_t *)devpriv->rps_buf.logical_base;
 
 	/* Initialize RPS instruction pointer */
-	writel((uint32_t)devpriv->RPSBuf.PhysicalBase,
-	       devpriv->mmio + P_RPSADDR1);
+	writel((uint32_t)devpriv->rps_buf.physical_base,
+	       devpriv->mmio + S626_P_RPSADDR1);
 
-	/*  Construct RPS program in RPSBuf DMA buffer */
-
+	/* Construct RPS program in rps_buf DMA buffer */
 	if (cmd != NULL && cmd->scan_begin_src != TRIG_FOLLOW) {
-		/*  Wait for Start trigger. */
-		*pRPS++ = RPS_PAUSE | RPS_SIGADC;
-		*pRPS++ = RPS_CLRSIGNAL | RPS_SIGADC;
+		/* Wait for Start trigger. */
+		*rps++ = S626_RPS_PAUSE | S626_RPS_SIGADC;
+		*rps++ = S626_RPS_CLRSIGNAL | S626_RPS_SIGADC;
 	}
 
-	/* SAA7146 BUG WORKAROUND Do a dummy DEBI Write.  This is necessary
+	/*
+	 * SAA7146 BUG WORKAROUND Do a dummy DEBI Write.  This is necessary
 	 * because the first RPS DEBI Write following a non-RPS DEBI write
 	 * seems to always fail.  If we don't do this dummy write, the ADC
 	 * gain might not be set to the value required for the first slot in
 	 * the poll list; the ADC gain would instead remain unchanged from
 	 * the previously programmed value.
 	 */
-	*pRPS++ = RPS_LDREG | (P_DEBICMD >> 2);
 	/* Write DEBI Write command and address to shadow RAM. */
+	*rps++ = S626_RPS_LDREG | (S626_P_DEBICMD >> 2);
+	*rps++ = S626_DEBI_CMD_WRWORD | S626_LP_GSEL;
+	*rps++ = S626_RPS_LDREG | (S626_P_DEBIAD >> 2);
+	/* Write DEBI immediate data  to shadow RAM: */
+	*rps++ = S626_GSEL_BIPOLAR5V;	/* arbitrary immediate data  value. */
+	*rps++ = S626_RPS_CLRSIGNAL | S626_RPS_DEBI;
+	/* Reset "shadow RAM  uploaded" flag. */
+	/* Invoke shadow RAM upload. */
+	*rps++ = S626_RPS_UPLOAD | S626_RPS_DEBI;
+	/* Wait for shadow upload to finish. */
+	*rps++ = S626_RPS_PAUSE | S626_RPS_DEBI;
 
-	*pRPS++ = DEBI_CMD_WRWORD | LP_GSEL;
-	*pRPS++ = RPS_LDREG | (P_DEBIAD >> 2);
-	/*  Write DEBI immediate data  to shadow RAM: */
-
-	*pRPS++ = GSEL_BIPOLAR5V;
-	/*  arbitrary immediate data  value. */
-
-	*pRPS++ = RPS_CLRSIGNAL | RPS_DEBI;
-	/*  Reset "shadow RAM  uploaded" flag. */
-	*pRPS++ = RPS_UPLOAD | RPS_DEBI;	/*  Invoke shadow RAM upload. */
-	*pRPS++ = RPS_PAUSE | RPS_DEBI;	/*  Wait for shadow upload to finish. */
-
-	/* Digitize all slots in the poll list. This is implemented as a
+	/*
+	 * Digitize all slots in the poll list. This is implemented as a
 	 * for loop to limit the slot count to 16 in case the application
-	 * forgot to set the EOPL flag in the final slot.
+	 * forgot to set the S626_EOPL flag in the final slot.
 	 */
-	for (devpriv->AdcItems = 0; devpriv->AdcItems < 16; devpriv->AdcItems++) {
-		/* Convert application's poll list item to private board class
+	for (devpriv->adc_items = 0; devpriv->adc_items < 16;
+	     devpriv->adc_items++) {
+		/*
+		 * Convert application's poll list item to private board class
 		 * format.  Each app poll list item is an uint8_t with form
 		 * (EOPL,x,x,RANGE,CHAN<3:0>), where RANGE code indicates 0 =
 		 * +-10V, 1 = +-5V, and EOPL = End of Poll List marker.
 		 */
-		LocalPPL =
-		    (*ppl << 8) | (*ppl & 0x10 ? GSEL_BIPOLAR5V :
-				   GSEL_BIPOLAR10V);
+		local_ppl = (*ppl << 8) | (*ppl & 0x10 ? S626_GSEL_BIPOLAR5V :
+					   S626_GSEL_BIPOLAR10V);
 
-		/*  Switch ADC analog gain. */
-		*pRPS++ = RPS_LDREG | (P_DEBICMD >> 2);	/*  Write DEBI command */
-		/*  and address to */
-		/*  shadow RAM. */
-		*pRPS++ = DEBI_CMD_WRWORD | LP_GSEL;
-		*pRPS++ = RPS_LDREG | (P_DEBIAD >> 2);	/*  Write DEBI */
-		/*  immediate data to */
-		/*  shadow RAM. */
-		*pRPS++ = LocalPPL;
-		*pRPS++ = RPS_CLRSIGNAL | RPS_DEBI;	/*  Reset "shadow RAM uploaded" */
-		/*  flag. */
-		*pRPS++ = RPS_UPLOAD | RPS_DEBI;	/*  Invoke shadow RAM upload. */
-		*pRPS++ = RPS_PAUSE | RPS_DEBI;	/*  Wait for shadow upload to */
-		/*  finish. */
+		/* Switch ADC analog gain. */
+		/* Write DEBI command and address to shadow RAM. */
+		*rps++ = S626_RPS_LDREG | (S626_P_DEBICMD >> 2);
+		*rps++ = S626_DEBI_CMD_WRWORD | S626_LP_GSEL;
+		/* Write DEBI immediate data to shadow RAM. */
+		*rps++ = S626_RPS_LDREG | (S626_P_DEBIAD >> 2);
+		*rps++ = local_ppl;
+		/* Reset "shadow RAM uploaded" flag. */
+		*rps++ = S626_RPS_CLRSIGNAL | S626_RPS_DEBI;
+		/* Invoke shadow RAM upload. */
+		*rps++ = S626_RPS_UPLOAD | S626_RPS_DEBI;
+		/* Wait for shadow upload to finish. */
+		*rps++ = S626_RPS_PAUSE | S626_RPS_DEBI;
+		/* Select ADC analog input channel. */
+		*rps++ = S626_RPS_LDREG | (S626_P_DEBICMD >> 2);
+		/* Write DEBI command and address to shadow RAM. */
+		*rps++ = S626_DEBI_CMD_WRWORD | S626_LP_ISEL;
+		*rps++ = S626_RPS_LDREG | (S626_P_DEBIAD >> 2);
+		/* Write DEBI immediate data to shadow RAM. */
+		*rps++ = local_ppl;
+		/* Reset "shadow RAM uploaded" flag. */
+		*rps++ = S626_RPS_CLRSIGNAL | S626_RPS_DEBI;
+		/* Invoke shadow RAM upload. */
+		*rps++ = S626_RPS_UPLOAD | S626_RPS_DEBI;
+		/* Wait for shadow upload to finish. */
+		*rps++ = S626_RPS_PAUSE | S626_RPS_DEBI;
 
-		/*  Select ADC analog input channel. */
-		*pRPS++ = RPS_LDREG | (P_DEBICMD >> 2);
-		/*  Write DEBI command and address to  shadow RAM. */
-		*pRPS++ = DEBI_CMD_WRWORD | LP_ISEL;
-		*pRPS++ = RPS_LDREG | (P_DEBIAD >> 2);
-		/*  Write DEBI immediate data to shadow RAM. */
-		*pRPS++ = LocalPPL;
-		*pRPS++ = RPS_CLRSIGNAL | RPS_DEBI;
-		/*  Reset "shadow RAM uploaded"  flag. */
-
-		*pRPS++ = RPS_UPLOAD | RPS_DEBI;
-		/*  Invoke shadow RAM upload. */
-
-		*pRPS++ = RPS_PAUSE | RPS_DEBI;
-		/*  Wait for shadow upload to finish. */
-
-		/* Delay at least 10 microseconds for analog input settling.
-		 * Instead of padding with NOPs, we use RPS_JUMP instructions
-		 * here; this allows us to produce a longer delay than is
-		 * possible with NOPs because each RPS_JUMP flushes the RPS'
-		 * instruction prefetch pipeline.
+		/*
+		 * Delay at least 10 microseconds for analog input settling.
+		 * Instead of padding with NOPs, we use S626_RPS_JUMP
+		 * instructions here; this allows us to produce a longer delay
+		 * than is possible with NOPs because each S626_RPS_JUMP
+		 * flushes the RPS' instruction prefetch pipeline.
 		 */
-		JmpAdrs =
-		    (uint32_t) devpriv->RPSBuf.PhysicalBase +
-		    (uint32_t) ((unsigned long)pRPS -
-				(unsigned long)devpriv->RPSBuf.LogicalBase);
-		for (i = 0; i < (10 * RPSCLK_PER_US / 2); i++) {
-			JmpAdrs += 8;	/*  Repeat to implement time delay: */
-			*pRPS++ = RPS_JUMP;	/*  Jump to next RPS instruction. */
-			*pRPS++ = JmpAdrs;
+		jmp_adrs =
+			(uint32_t)devpriv->rps_buf.physical_base +
+			(uint32_t)((unsigned long)rps -
+				   (unsigned long)devpriv->
+						  rps_buf.logical_base);
+		for (i = 0; i < (10 * S626_RPSCLK_PER_US / 2); i++) {
+			jmp_adrs += 8;	/* Repeat to implement time delay: */
+			/* Jump to next RPS instruction. */
+			*rps++ = S626_RPS_JUMP;
+			*rps++ = jmp_adrs;
 		}
 
 		if (cmd != NULL && cmd->convert_src != TRIG_NOW) {
-			/*  Wait for Start trigger. */
-			*pRPS++ = RPS_PAUSE | RPS_SIGADC;
-			*pRPS++ = RPS_CLRSIGNAL | RPS_SIGADC;
+			/* Wait for Start trigger. */
+			*rps++ = S626_RPS_PAUSE | S626_RPS_SIGADC;
+			*rps++ = S626_RPS_CLRSIGNAL | S626_RPS_SIGADC;
 		}
-		/*  Start ADC by pulsing GPIO1. */
-		*pRPS++ = RPS_LDREG | (P_GPIO >> 2);	/*  Begin ADC Start pulse. */
-		*pRPS++ = GPIO_BASE | GPIO1_LO;
-		*pRPS++ = RPS_NOP;
-		/*  VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. */
-		*pRPS++ = RPS_LDREG | (P_GPIO >> 2);	/*  End ADC Start pulse. */
-		*pRPS++ = GPIO_BASE | GPIO1_HI;
-
-		/* Wait for ADC to complete (GPIO2 is asserted high when ADC not
+		/* Start ADC by pulsing GPIO1. */
+		/* Begin ADC Start pulse. */
+		*rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2);
+		*rps++ = S626_GPIO_BASE | S626_GPIO1_LO;
+		*rps++ = S626_RPS_NOP;
+		/* VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. */
+		/* End ADC Start pulse. */
+		*rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2);
+		*rps++ = S626_GPIO_BASE | S626_GPIO1_HI;
+		/*
+		 * Wait for ADC to complete (GPIO2 is asserted high when ADC not
 		 * busy) and for data from previous conversion to shift into FB
 		 * BUFFER 1 register.
 		 */
-		*pRPS++ = RPS_PAUSE | RPS_GPIO2;	/*  Wait for ADC done. */
+		/* Wait for ADC done. */
+		*rps++ = S626_RPS_PAUSE | S626_RPS_GPIO2;
 
-		/*  Transfer ADC data from FB BUFFER 1 register to DMA buffer. */
-		*pRPS++ = RPS_STREG | (BUGFIX_STREG(P_FB_BUFFER1) >> 2);
-		*pRPS++ =
-		    (uint32_t) devpriv->ANABuf.PhysicalBase +
-		    (devpriv->AdcItems << 2);
+		/* Transfer ADC data from FB BUFFER 1 register to DMA buffer. */
+		*rps++ = S626_RPS_STREG |
+			 (S626_BUGFIX_STREG(S626_P_FB_BUFFER1) >> 2);
+		*rps++ = (uint32_t)devpriv->ana_buf.physical_base +
+			 (devpriv->adc_items << 2);
 
-		/*  If this slot's EndOfPollList flag is set, all channels have */
-		/*  now been processed. */
-		if (*ppl++ & EOPL) {
-			devpriv->AdcItems++;	/*  Adjust poll list item count. */
-			break;	/*  Exit poll list processing loop. */
+		/*
+		 * If this slot's EndOfPollList flag is set, all channels have
+		 * now been processed.
+		 */
+		if (*ppl++ & S626_EOPL) {
+			devpriv->adc_items++; /* Adjust poll list item count. */
+			break;	/* Exit poll list processing loop. */
 		}
 	}
 
-	/* VERSION 2.01 CHANGE: DELAY CHANGED FROM 250NS to 2US.  Allow the
+	/*
+	 * VERSION 2.01 CHANGE: DELAY CHANGED FROM 250NS to 2US.  Allow the
 	 * ADC to stabilize for 2 microseconds before starting the final
 	 * (dummy) conversion.  This delay is necessary to allow sufficient
 	 * time between last conversion finished and the start of the dummy
 	 * conversion.  Without this delay, the last conversion's data value
 	 * is sometimes set to the previous conversion's data value.
 	 */
-	for (n = 0; n < (2 * RPSCLK_PER_US); n++)
-		*pRPS++ = RPS_NOP;
+	for (n = 0; n < (2 * S626_RPSCLK_PER_US); n++)
+		*rps++ = S626_RPS_NOP;
 
-	/* Start a dummy conversion to cause the data from the last
+	/*
+	 * Start a dummy conversion to cause the data from the last
 	 * conversion of interest to be shifted in.
 	 */
-	*pRPS++ = RPS_LDREG | (P_GPIO >> 2);	/*  Begin ADC Start pulse. */
-	*pRPS++ = GPIO_BASE | GPIO1_LO;
-	*pRPS++ = RPS_NOP;
+	/* Begin ADC Start pulse. */
+	*rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2);
+	*rps++ = S626_GPIO_BASE | S626_GPIO1_LO;
+	*rps++ = S626_RPS_NOP;
 	/* VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. */
-	*pRPS++ = RPS_LDREG | (P_GPIO >> 2);	/*  End ADC Start pulse. */
-	*pRPS++ = GPIO_BASE | GPIO1_HI;
+	*rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2); /* End ADC Start pulse. */
+	*rps++ = S626_GPIO_BASE | S626_GPIO1_HI;
 
-	/* Wait for the data from the last conversion of interest to arrive
+	/*
+	 * Wait for the data from the last conversion of interest to arrive
 	 * in FB BUFFER 1 register.
 	 */
-	*pRPS++ = RPS_PAUSE | RPS_GPIO2;	/*  Wait for ADC done. */
+	*rps++ = S626_RPS_PAUSE | S626_RPS_GPIO2;	/* Wait for ADC done. */
 
-	/*  Transfer final ADC data from FB BUFFER 1 register to DMA buffer. */
-	*pRPS++ = RPS_STREG | (BUGFIX_STREG(P_FB_BUFFER1) >> 2);	/*  */
-	*pRPS++ =
-	    (uint32_t) devpriv->ANABuf.PhysicalBase + (devpriv->AdcItems << 2);
+	/* Transfer final ADC data from FB BUFFER 1 register to DMA buffer. */
+	*rps++ = S626_RPS_STREG | (S626_BUGFIX_STREG(S626_P_FB_BUFFER1) >> 2);
+	*rps++ = (uint32_t)devpriv->ana_buf.physical_base +
+		 (devpriv->adc_items << 2);
 
-	/*  Indicate ADC scan loop is finished. */
-	/*  *pRPS++= RPS_CLRSIGNAL | RPS_SIGADC ;  // Signal ReadADC() that scan is done. */
+	/* Indicate ADC scan loop is finished. */
+	/* Signal ReadADC() that scan is done. */
+	/* *rps++= S626_RPS_CLRSIGNAL | S626_RPS_SIGADC; */
 
 	/* invoke interrupt */
-	if (devpriv->ai_cmd_running == 1) {
-		*pRPS++ = RPS_IRQ;
-	}
-	/*  Restart RPS program at its beginning. */
-	*pRPS++ = RPS_JUMP;	/*  Branch to start of RPS program. */
-	*pRPS++ = (uint32_t) devpriv->RPSBuf.PhysicalBase;
+	if (devpriv->ai_cmd_running == 1)
+		*rps++ = S626_RPS_IRQ;
 
-	/*  End of RPS program build */
+	/* Restart RPS program at its beginning. */
+	*rps++ = S626_RPS_JUMP;	/* Branch to start of RPS program. */
+	*rps++ = (uint32_t)devpriv->rps_buf.physical_base;
+
+	/* End of RPS program build */
 }
 
 #ifdef unused_code
@@ -1111,14 +1815,14 @@
 			 unsigned int *data)
 {
 	struct s626_private *devpriv = dev->private;
-	register uint8_t i;
-	register int32_t *readaddr;
+	uint8_t i;
+	int32_t *readaddr;
 
 	/* Trigger ADC scan loop start */
-	s626_mc_enable(dev, MC2_ADC_RPS, P_MC2);
+	s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2);
 
 	/* Wait until ADC scan loop is finished (RPS Signal 0 reset) */
-	while (s626_mc_test(dev, MC2_ADC_RPS, P_MC2))
+	while (s626_mc_test(dev, S626_MC2_ADC_RPS, S626_P_MC2))
 		;
 
 	/*
@@ -1126,13 +1830,13 @@
 	 * first uint16_t in the buffer because it contains junk data from
 	 * the final ADC of the previous poll list scan.
 	 */
-	readaddr = (uint32_t *)devpriv->ANABuf.LogicalBase + 1;
+	readaddr = (uint32_t *)devpriv->ana_buf.logical_base + 1;
 
 	/*
 	 * Convert ADC data to 16-bit integer values and
 	 * copy to application buffer.
 	 */
-	for (i = 0; i < devpriv->AdcItems; i++) {
+	for (i = 0; i < devpriv->adc_items; i++) {
 		*data = s626_ai_reg_to_uint(*readaddr++);
 		data++;
 	}
@@ -1148,55 +1852,61 @@
 	struct s626_private *devpriv = dev->private;
 	uint16_t chan = CR_CHAN(insn->chanspec);
 	uint16_t range = CR_RANGE(insn->chanspec);
-	uint16_t AdcSpec = 0;
-	uint32_t GpioImage;
-	int tmp;
+	uint16_t adc_spec = 0;
+	uint32_t gpio_image;
+	uint32_t tmp;
 	int n;
 
-	/* Convert application's ADC specification into form
+	/*
+	 * Convert application's ADC specification into form
 	 *  appropriate for register programming.
 	 */
 	if (range == 0)
-		AdcSpec = (chan << 8) | (GSEL_BIPOLAR5V);
+		adc_spec = (chan << 8) | (S626_GSEL_BIPOLAR5V);
 	else
-		AdcSpec = (chan << 8) | (GSEL_BIPOLAR10V);
+		adc_spec = (chan << 8) | (S626_GSEL_BIPOLAR10V);
 
-	/*  Switch ADC analog gain. */
-	DEBIwrite(dev, LP_GSEL, AdcSpec);	/*  Set gain. */
+	/* Switch ADC analog gain. */
+	s626_debi_write(dev, S626_LP_GSEL, adc_spec);	/* Set gain. */
 
-	/*  Select ADC analog input channel. */
-	DEBIwrite(dev, LP_ISEL, AdcSpec);	/*  Select channel. */
+	/* Select ADC analog input channel. */
+	s626_debi_write(dev, S626_LP_ISEL, adc_spec);	/* Select channel. */
 
 	for (n = 0; n < insn->n; n++) {
-
-		/*  Delay 10 microseconds for analog input settling. */
+		/* Delay 10 microseconds for analog input settling. */
 		udelay(10);
 
 		/* Start ADC by pulsing GPIO1 low */
-		GpioImage = readl(devpriv->mmio + P_GPIO);
+		gpio_image = readl(devpriv->mmio + S626_P_GPIO);
 		/* Assert ADC Start command */
-		writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO);
+		writel(gpio_image & ~S626_GPIO1_HI,
+		       devpriv->mmio + S626_P_GPIO);
 		/* and stretch it out */
-		writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO);
-		writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO);
+		writel(gpio_image & ~S626_GPIO1_HI,
+		       devpriv->mmio + S626_P_GPIO);
+		writel(gpio_image & ~S626_GPIO1_HI,
+		       devpriv->mmio + S626_P_GPIO);
 		/* Negate ADC Start command */
-		writel(GpioImage | GPIO1_HI, devpriv->mmio + P_GPIO);
+		writel(gpio_image | S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO);
 
-		/*  Wait for ADC to complete (GPIO2 is asserted high when */
-		/*  ADC not busy) and for data from previous conversion to */
-		/*  shift into FB BUFFER 1 register. */
+		/*
+		 * Wait for ADC to complete (GPIO2 is asserted high when
+		 * ADC not busy) and for data from previous conversion to
+		 * shift into FB BUFFER 1 register.
+		 */
 
 		/* Wait for ADC done */
-		while (!(readl(devpriv->mmio + P_PSR) & PSR_GPIO2))
+		while (!(readl(devpriv->mmio + S626_P_PSR) & S626_PSR_GPIO2))
 			;
 
 		/* Fetch ADC data */
 		if (n != 0) {
-			tmp = readl(devpriv->mmio + P_FB_BUFFER1);
+			tmp = readl(devpriv->mmio + S626_P_FB_BUFFER1);
 			data[n - 1] = s626_ai_reg_to_uint(tmp);
 		}
 
-		/* Allow the ADC to stabilize for 4 microseconds before
+		/*
+		 * Allow the ADC to stabilize for 4 microseconds before
 		 * starting the next (final) conversion.  This delay is
 		 * necessary to allow sufficient time between last
 		 * conversion finished and the start of the next
@@ -1207,28 +1917,30 @@
 		udelay(4);
 	}
 
-	/* Start a dummy conversion to cause the data from the
-	 * previous conversion to be shifted in. */
-	GpioImage = readl(devpriv->mmio + P_GPIO);
+	/*
+	 * Start a dummy conversion to cause the data from the
+	 * previous conversion to be shifted in.
+	 */
+	gpio_image = readl(devpriv->mmio + S626_P_GPIO);
 	/* Assert ADC Start command */
-	writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO);
+	writel(gpio_image & ~S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO);
 	/* and stretch it out */
-	writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO);
-	writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO);
+	writel(gpio_image & ~S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO);
+	writel(gpio_image & ~S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO);
 	/* Negate ADC Start command */
-	writel(GpioImage | GPIO1_HI, devpriv->mmio + P_GPIO);
+	writel(gpio_image | S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO);
 
-	/*  Wait for the data to arrive in FB BUFFER 1 register. */
+	/* Wait for the data to arrive in FB BUFFER 1 register. */
 
 	/* Wait for ADC done */
-	while (!(readl(devpriv->mmio + P_PSR) & PSR_GPIO2))
+	while (!(readl(devpriv->mmio + S626_P_PSR) & S626_PSR_GPIO2))
 		;
 
-	/*  Fetch ADC data from audio interface's input shift register. */
+	/* Fetch ADC data from audio interface's input shift register. */
 
 	/* Fetch ADC data */
 	if (n != 0) {
-		tmp = readl(devpriv->mmio + P_FB_BUFFER1);
+		tmp = readl(devpriv->mmio + S626_P_FB_BUFFER1);
 		data[n - 1] = s626_ai_reg_to_uint(tmp);
 	}
 
@@ -1237,17 +1949,16 @@
 
 static int s626_ai_load_polllist(uint8_t *ppl, struct comedi_cmd *cmd)
 {
-
 	int n;
 
 	for (n = 0; n < cmd->chanlist_len; n++) {
-		if (CR_RANGE((cmd->chanlist)[n]) == 0)
-			ppl[n] = (CR_CHAN((cmd->chanlist)[n])) | (RANGE_5V);
+		if (CR_RANGE(cmd->chanlist[n]) == 0)
+			ppl[n] = CR_CHAN(cmd->chanlist[n]) | S626_RANGE_5V;
 		else
-			ppl[n] = (CR_CHAN((cmd->chanlist)[n])) | (RANGE_10V);
+			ppl[n] = CR_CHAN(cmd->chanlist[n]) | S626_RANGE_10V;
 	}
 	if (n != 0)
-		ppl[n - 1] |= EOPL;
+		ppl[n - 1] |= S626_EOPL;
 
 	return n;
 }
@@ -1259,18 +1970,20 @@
 		return -EINVAL;
 
 	/* Start executing the RPS program */
-	s626_mc_enable(dev, MC1_ERPS1, P_MC1);
+	s626_mc_enable(dev, S626_MC1_ERPS1, S626_P_MC1);
 
 	s->async->inttrig = NULL;
 
 	return 1;
 }
 
-/* This function doesn't require a particular form, this is just what
+/*
+ * This function doesn't require a particular form, this is just what
  * happens to be used in some of the drivers.  It should convert ns
  * nanoseconds to a counter value suitable for programming the device.
  * Also, it should adjust ns so that it cooresponds to the actual time
- * that the device will use. */
+ * that the device will use.
+ */
 static int s626_ns_to_timer(int *nanosec, int round_mode)
 {
 	int divider, base;
@@ -1294,68 +2007,75 @@
 	return divider - 1;
 }
 
-static void s626_timer_load(struct comedi_device *dev, struct enc_private *k,
-			    int tick)
+static void s626_timer_load(struct comedi_device *dev,
+			    const struct s626_enc_info *k, int tick)
 {
-	uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) |	/*  Preload upon */
-	    /*  index. */
-	    (INDXSRC_SOFT << BF_INDXSRC) |	/*  Disable hardware index. */
-	    (CLKSRC_TIMER << BF_CLKSRC) |	/*  Operating mode is Timer. */
-	    (CLKPOL_POS << BF_CLKPOL) |	/*  Active high clock. */
-	    (CNTDIR_DOWN << BF_CLKPOL) |	/*  Count direction is Down. */
-	    (CLKMULT_1X << BF_CLKMULT) |	/*  Clock multiplier is 1x. */
-	    (CLKENAB_INDEX << BF_CLKENAB);
-	uint16_t valueSrclatch = LATCHSRC_A_INDXA;
-	/*   uint16_t enab=CLKENAB_ALWAYS; */
+	uint16_t setup =
+		/* Preload upon index. */
+		S626_SET_STD_LOADSRC(S626_LOADSRC_INDX) |
+		/* Disable hardware index. */
+		S626_SET_STD_INDXSRC(S626_INDXSRC_SOFT) |
+		/* Operating mode is Timer. */
+		S626_SET_STD_ENCMODE(S626_ENCMODE_TIMER) |
+		/* Count direction is Down. */
+		S626_SET_STD_CLKPOL(S626_CNTDIR_DOWN) |
+		/* Clock multiplier is 1x. */
+		S626_SET_STD_CLKMULT(S626_CLKMULT_1X) |
+		/* Enabled by index */
+		S626_SET_STD_CLKENAB(S626_CLKENAB_INDEX);
+	uint16_t value_latchsrc = S626_LATCHSRC_A_INDXA;
+	/* uint16_t enab = S626_CLKENAB_ALWAYS; */
 
-	k->SetMode(dev, k, Setup, FALSE);
+	k->set_mode(dev, k, setup, false);
 
-	/*  Set the preload register */
-	Preload(dev, k, tick);
+	/* Set the preload register */
+	s626_preload(dev, k, tick);
 
-	/*  Software index pulse forces the preload register to load */
-	/*  into the counter */
-	k->SetLoadTrig(dev, k, 0);
-	k->PulseIndex(dev, k);
+	/*
+	 * Software index pulse forces the preload register to load
+	 * into the counter
+	 */
+	k->set_load_trig(dev, k, 0);
+	k->pulse_index(dev, k);
 
 	/* set reload on counter overflow */
-	k->SetLoadTrig(dev, k, 1);
+	k->set_load_trig(dev, k, 1);
 
 	/* set interrupt on overflow */
-	k->SetIntSrc(dev, k, INTSRC_OVER);
+	k->set_int_src(dev, k, S626_INTSRC_OVER);
 
-	SetLatchSource(dev, k, valueSrclatch);
-	/*   k->SetEnable(dev,k,(uint16_t)(enab != 0)); */
+	s626_set_latch_source(dev, k, value_latchsrc);
+	/* k->set_enable(dev, k, (uint16_t)(enab != 0)); */
 }
 
-/*  TO COMPLETE  */
+/* TO COMPLETE  */
 static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
 	struct s626_private *devpriv = dev->private;
 	uint8_t ppl[16];
 	struct comedi_cmd *cmd = &s->async->cmd;
-	struct enc_private *k;
+	const struct s626_enc_info *k;
 	int tick;
 
 	if (devpriv->ai_cmd_running) {
-		printk(KERN_ERR "s626_ai_cmd: Another ai_cmd is running %d\n",
-		       dev->minor);
+		dev_err(dev->class_dev,
+			"s626_ai_cmd: Another ai_cmd is running\n");
 		return -EBUSY;
 	}
 	/* disable interrupt */
-	writel(0, devpriv->mmio + P_IER);
+	writel(0, devpriv->mmio + S626_P_IER);
 
 	/* clear interrupt request */
-	writel(IRQ_RPS1 | IRQ_GPIO3, devpriv->mmio + P_ISR);
+	writel(S626_IRQ_RPS1 | S626_IRQ_GPIO3, devpriv->mmio + S626_P_ISR);
 
 	/* clear any pending interrupt */
 	s626_dio_clear_irq(dev);
-	/*   s626_enc_clear_irq(dev); */
+	/* s626_enc_clear_irq(dev); */
 
 	/* reset ai_cmd_running flag */
 	devpriv->ai_cmd_running = 0;
 
-	/*  test if cmd is valid */
+	/* test if cmd is valid */
 	if (cmd == NULL)
 		return -EINVAL;
 
@@ -1373,17 +2093,20 @@
 	case TRIG_FOLLOW:
 		break;
 	case TRIG_TIMER:
-		/*  set a conter to generate adc trigger at scan_begin_arg interval */
-		k = &encpriv[5];
+		/*
+		 * set a counter to generate adc trigger at scan_begin_arg
+		 * interval
+		 */
+		k = &s626_enc_chan_info[5];
 		tick = s626_ns_to_timer((int *)&cmd->scan_begin_arg,
 					cmd->flags & TRIG_ROUND_MASK);
 
 		/* load timer value and enable interrupt */
 		s626_timer_load(dev, k, tick);
-		k->SetEnable(dev, k, CLKENAB_ALWAYS);
+		k->set_enable(dev, k, S626_CLKENAB_ALWAYS);
 		break;
 	case TRIG_EXT:
-		/*  set the digital line and interrupt for scan trigger */
+		/* set the digital line and interrupt for scan trigger */
 		if (cmd->start_src != TRIG_EXT)
 			s626_dio_set_irq(dev, cmd->scan_begin_arg);
 		break;
@@ -1393,52 +2116,53 @@
 	case TRIG_NOW:
 		break;
 	case TRIG_TIMER:
-		/*  set a conter to generate adc trigger at convert_arg interval */
-		k = &encpriv[4];
+		/*
+		 * set a counter to generate adc trigger at convert_arg
+		 * interval
+		 */
+		k = &s626_enc_chan_info[4];
 		tick = s626_ns_to_timer((int *)&cmd->convert_arg,
 					cmd->flags & TRIG_ROUND_MASK);
 
 		/* load timer value and enable interrupt */
 		s626_timer_load(dev, k, tick);
-		k->SetEnable(dev, k, CLKENAB_INDEX);
+		k->set_enable(dev, k, S626_CLKENAB_INDEX);
 		break;
 	case TRIG_EXT:
-		/*  set the digital line and interrupt for convert trigger */
-		if (cmd->scan_begin_src != TRIG_EXT
-		    && cmd->start_src == TRIG_EXT)
+		/* set the digital line and interrupt for convert trigger */
+		if (cmd->scan_begin_src != TRIG_EXT &&
+		    cmd->start_src == TRIG_EXT)
 			s626_dio_set_irq(dev, cmd->convert_arg);
 		break;
 	}
 
 	switch (cmd->stop_src) {
 	case TRIG_COUNT:
-		/*  data arrives as one packet */
+		/* data arrives as one packet */
 		devpriv->ai_sample_count = cmd->stop_arg;
-		devpriv->ai_continous = 0;
+		devpriv->ai_continuous = 0;
 		break;
 	case TRIG_NONE:
-		/*  continous acquisition */
-		devpriv->ai_continous = 1;
+		/* continuous acquisition */
+		devpriv->ai_continuous = 1;
 		devpriv->ai_sample_count = 1;
 		break;
 	}
 
-	ResetADC(dev, ppl);
+	s626_reset_adc(dev, ppl);
 
 	switch (cmd->start_src) {
 	case TRIG_NOW:
 		/* Trigger ADC scan loop start */
-		/* s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); */
+		/* s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2); */
 
 		/* Start executing the RPS program */
-		s626_mc_enable(dev, MC1_ERPS1, P_MC1);
-
+		s626_mc_enable(dev, S626_MC1_ERPS1, S626_P_MC1);
 		s->async->inttrig = NULL;
 		break;
 	case TRIG_EXT:
 		/* configure DIO channel for acquisition trigger */
 		s626_dio_set_irq(dev, cmd->start_arg);
-
 		s->async->inttrig = NULL;
 		break;
 	case TRIG_INT:
@@ -1447,7 +2171,7 @@
 	}
 
 	/* enable interrupt */
-	writel(IRQ_GPIO3 | IRQ_RPS1, devpriv->mmio + P_IER);
+	writel(S626_IRQ_GPIO3 | S626_IRQ_RPS1, devpriv->mmio + S626_P_IER);
 
 	return 0;
 }
@@ -1461,11 +2185,11 @@
 	/* Step 1 : check if triggers are trivially valid */
 
 	err |= cfc_check_trigger_src(&cmd->start_src,
-					TRIG_NOW | TRIG_INT | TRIG_EXT);
+				     TRIG_NOW | TRIG_INT | TRIG_EXT);
 	err |= cfc_check_trigger_src(&cmd->scan_begin_src,
-					TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW);
+				     TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW);
 	err |= cfc_check_trigger_src(&cmd->convert_src,
-					TRIG_TIMER | TRIG_EXT | TRIG_NOW);
+				     TRIG_TIMER | TRIG_EXT | TRIG_NOW);
 	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 
@@ -1490,34 +2214,34 @@
 		err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 	if (cmd->start_src == TRIG_EXT)
 		err |= cfc_check_trigger_arg_max(&cmd->start_arg, 39);
-
 	if (cmd->scan_begin_src == TRIG_EXT)
 		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 39);
-
 	if (cmd->convert_src == TRIG_EXT)
 		err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 39);
 
-#define MAX_SPEED	200000	/* in nanoseconds */
-#define MIN_SPEED	2000000000	/* in nanoseconds */
+#define S626_MAX_SPEED	200000	/* in nanoseconds */
+#define S626_MIN_SPEED	2000000000	/* in nanoseconds */
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
 		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
-						 MAX_SPEED);
+						 S626_MAX_SPEED);
 		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
-						 MIN_SPEED);
+						 S626_MIN_SPEED);
 	} else {
 		/* external trigger */
 		/* should be level/edge, hi/lo specification here */
 		/* should specify multiple external triggers */
-/*		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9); */
+		/* err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9); */
 	}
 	if (cmd->convert_src == TRIG_TIMER) {
-		err |= cfc_check_trigger_arg_min(&cmd->convert_arg, MAX_SPEED);
-		err |= cfc_check_trigger_arg_max(&cmd->convert_arg, MIN_SPEED);
+		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
+						 S626_MAX_SPEED);
+		err |= cfc_check_trigger_arg_max(&cmd->convert_arg,
+						 S626_MIN_SPEED);
 	} else {
 		/* external trigger */
 		/* see above */
-/*		err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9); */
+		/* err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9); */
 	}
 
 	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
@@ -1546,10 +2270,10 @@
 		if (tmp != cmd->convert_arg)
 			err++;
 		if (cmd->scan_begin_src == TRIG_TIMER &&
-		    cmd->scan_begin_arg <
-		    cmd->convert_arg * cmd->scan_end_arg) {
-			cmd->scan_begin_arg =
-			    cmd->convert_arg * cmd->scan_end_arg;
+		    cmd->scan_begin_arg < cmd->convert_arg *
+					  cmd->scan_end_arg) {
+			cmd->scan_begin_arg = cmd->convert_arg *
+					      cmd->scan_end_arg;
 			err++;
 		}
 	}
@@ -1565,10 +2289,10 @@
 	struct s626_private *devpriv = dev->private;
 
 	/* Stop RPS program in case it is currently running */
-	s626_mc_disable(dev, MC1_ERPS1, P_MC1);
+	s626_mc_disable(dev, S626_MC1_ERPS1, S626_P_MC1);
 
 	/* disable master interrupt */
-	writel(0, devpriv->mmio + P_IER);
+	writel(0, devpriv->mmio + S626_P_IER);
 
 	devpriv->ai_cmd_running = 0;
 
@@ -1588,7 +2312,7 @@
 		devpriv->ao_readback[CR_CHAN(insn->chanspec)] = data[i];
 		dacdata -= (0x1fff);
 
-		SetDAC(dev, chan, dacdata);
+		s626_set_dac(dev, chan, dacdata);
 	}
 
 	return i;
@@ -1606,7 +2330,9 @@
 	return i;
 }
 
-/* *************** DIGITAL I/O FUNCTIONS ***************
+/* *************** DIGITAL I/O FUNCTIONS *************** */
+
+/*
  * All DIO functions address a group of DIO channels by means of
  * "group" argument.  group may be 0, 1 or 2, which correspond to DIO
  * ports A, B and C, respectively.
@@ -1616,19 +2342,19 @@
 {
 	uint16_t group;
 
-	/*  Prepare to treat writes to WRCapSel as capture disables. */
-	DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP);
+	/* Prepare to treat writes to WRCapSel as capture disables. */
+	s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_NOEDCAP);
 
-	/*  For each group of sixteen channels ... */
+	/* For each group of sixteen channels ... */
 	for (group = 0; group < S626_DIO_BANKS; group++) {
 		/* Disable all interrupts */
-		DEBIwrite(dev, LP_WRINTSEL(group), 0);
+		s626_debi_write(dev, S626_LP_WRINTSEL(group), 0);
 		/* Disable all event captures */
-		DEBIwrite(dev, LP_WRCAPSEL(group), 0xffff);
+		s626_debi_write(dev, S626_LP_WRCAPSEL(group), 0xffff);
 		/* Init all DIOs to default edge polarity */
-		DEBIwrite(dev, LP_WREDGSEL(group), 0);
+		s626_debi_write(dev, S626_LP_WREDGSEL(group), 0);
 		/* Program all outputs to inactive state */
-		DEBIwrite(dev, LP_WRDOUT(group), 0);
+		s626_debi_write(dev, S626_LP_WRDOUT(group), 0);
 	}
 }
 
@@ -1638,20 +2364,11 @@
 			      unsigned int *data)
 {
 	unsigned long group = (unsigned long)s->private;
-	unsigned long mask = data[0];
-	unsigned long bits = data[1];
 
-	if (mask) {
-		/* Check if requested channels are configured for output */
-		if ((s->io_bits & mask) != mask)
-			return -EIO;
+	if (comedi_dio_update_state(s, data))
+		s626_debi_write(dev, S626_LP_WRDOUT(group), s->state);
 
-		s->state &= ~mask;
-		s->state |= (bits & mask);
-
-		DEBIwrite(dev, LP_WRDOUT(group), s->state);
-	}
-	data[1] = DEBIread(dev, LP_RDDIN(group));
+	data[1] = s626_debi_read(dev, S626_LP_RDDIN(group));
 
 	return insn->n;
 }
@@ -1668,42 +2385,51 @@
 	if (ret)
 		return ret;
 
-	DEBIwrite(dev, LP_WRDOUT(group), s->io_bits);
+	s626_debi_write(dev, S626_LP_WRDOUT(group), s->io_bits);
 
 	return insn->n;
 }
 
-/* Now this function initializes the value of the counter (data[0])
-   and set the subdevice. To complete with trigger and interrupt
-   configuration */
-/* FIXME: data[0] is supposed to be an INSN_CONFIG_xxx constant indicating
+/*
+ * Now this function initializes the value of the counter (data[0])
+ * and set the subdevice. To complete with trigger and interrupt
+ * configuration.
+ *
+ * FIXME: data[0] is supposed to be an INSN_CONFIG_xxx constant indicating
  * what is being configured, but this function appears to be using data[0]
- * as a variable. */
+ * as a variable.
+ */
 static int s626_enc_insn_config(struct comedi_device *dev,
 				struct comedi_subdevice *s,
 				struct comedi_insn *insn, unsigned int *data)
 {
-	uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) |	/*  Preload upon */
-	    /*  index. */
-	    (INDXSRC_SOFT << BF_INDXSRC) |	/*  Disable hardware index. */
-	    (CLKSRC_COUNTER << BF_CLKSRC) |	/*  Operating mode is Counter. */
-	    (CLKPOL_POS << BF_CLKPOL) |	/*  Active high clock. */
-	    /* ( CNTDIR_UP << BF_CLKPOL ) |      // Count direction is Down. */
-	    (CLKMULT_1X << BF_CLKMULT) |	/*  Clock multiplier is 1x. */
-	    (CLKENAB_INDEX << BF_CLKENAB);
-	/*   uint16_t DisableIntSrc=TRUE; */
-	/*  uint32_t Preloadvalue;              //Counter initial value */
-	uint16_t valueSrclatch = LATCHSRC_AB_READ;
-	uint16_t enab = CLKENAB_ALWAYS;
-	struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)];
+	uint16_t setup =
+		/* Preload upon index. */
+		S626_SET_STD_LOADSRC(S626_LOADSRC_INDX) |
+		/* Disable hardware index. */
+		S626_SET_STD_INDXSRC(S626_INDXSRC_SOFT) |
+		/* Operating mode is Counter. */
+		S626_SET_STD_ENCMODE(S626_ENCMODE_COUNTER) |
+		/* Active high clock. */
+		S626_SET_STD_CLKPOL(S626_CLKPOL_POS) |
+		/* Clock multiplier is 1x. */
+		S626_SET_STD_CLKMULT(S626_CLKMULT_1X) |
+		/* Enabled by index */
+		S626_SET_STD_CLKENAB(S626_CLKENAB_INDEX);
+	/* uint16_t disable_int_src = true; */
+	/* uint32_t Preloadvalue;              //Counter initial value */
+	uint16_t value_latchsrc = S626_LATCHSRC_AB_READ;
+	uint16_t enab = S626_CLKENAB_ALWAYS;
+	const struct s626_enc_info *k =
+		&s626_enc_chan_info[CR_CHAN(insn->chanspec)];
 
-	/*   (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); */
+	/* (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); */
 
-	k->SetMode(dev, k, Setup, TRUE);
-	Preload(dev, k, data[0]);
-	k->PulseIndex(dev, k);
-	SetLatchSource(dev, k, valueSrclatch);
-	k->SetEnable(dev, k, (uint16_t) (enab != 0));
+	k->set_mode(dev, k, setup, true);
+	s626_preload(dev, k, data[0]);
+	k->pulse_index(dev, k);
+	s626_set_latch_source(dev, k, value_latchsrc);
+	k->set_enable(dev, k, (enab != 0));
 
 	return insn->n;
 }
@@ -1712,12 +2438,12 @@
 			      struct comedi_subdevice *s,
 			      struct comedi_insn *insn, unsigned int *data)
 {
-
 	int n;
-	struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)];
+	const struct s626_enc_info *k =
+		&s626_enc_chan_info[CR_CHAN(insn->chanspec)];
 
 	for (n = 0; n < insn->n; n++)
-		data[n] = ReadLatch(dev, k);
+		data[n] = s626_read_latch(dev, k);
 
 	return n;
 }
@@ -1726,31 +2452,32 @@
 			       struct comedi_subdevice *s,
 			       struct comedi_insn *insn, unsigned int *data)
 {
+	const struct s626_enc_info *k =
+		&s626_enc_chan_info[CR_CHAN(insn->chanspec)];
 
-	struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)];
+	/* Set the preload register */
+	s626_preload(dev, k, data[0]);
 
-	/*  Set the preload register */
-	Preload(dev, k, data[0]);
-
-	/*  Software index pulse forces the preload register to load */
-	/*  into the counter */
-	k->SetLoadTrig(dev, k, 0);
-	k->PulseIndex(dev, k);
-	k->SetLoadTrig(dev, k, 2);
+	/*
+	 * Software index pulse forces the preload register to load
+	 * into the counter
+	 */
+	k->set_load_trig(dev, k, 0);
+	k->pulse_index(dev, k);
+	k->set_load_trig(dev, k, 2);
 
 	return 1;
 }
 
-static void WriteMISC2(struct comedi_device *dev, uint16_t NewImage)
+static void s626_write_misc2(struct comedi_device *dev, uint16_t new_image)
 {
-	DEBIwrite(dev, LP_MISC1, MISC1_WENABLE);	/*  enab writes to */
-	/*  MISC2 register. */
-	DEBIwrite(dev, LP_WRMISC2, NewImage);	/*  Write new image to MISC2. */
-	DEBIwrite(dev, LP_MISC1, MISC1_WDISABLE);	/*  Disable writes to MISC2. */
+	s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_WENABLE);
+	s626_debi_write(dev, S626_LP_WRMISC2, new_image);
+	s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_WDISABLE);
 }
 
-static void CloseDMAB(struct comedi_device *dev, struct bufferDMA *pdma,
-		      size_t bsize)
+static void s626_close_dma_b(struct comedi_device *dev,
+			     struct s626_buffer_dma *pdma, size_t bsize)
 {
 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 	void *vbptr;
@@ -1758,554 +2485,44 @@
 
 	if (pdma == NULL)
 		return;
-	/* find the matching allocation from the board struct */
 
-	vbptr = pdma->LogicalBase;
-	vpptr = pdma->PhysicalBase;
+	/* find the matching allocation from the board struct */
+	vbptr = pdma->logical_base;
+	vpptr = pdma->physical_base;
 	if (vbptr) {
 		pci_free_consistent(pcidev, bsize, vbptr, vpptr);
-		pdma->LogicalBase = NULL;
-		pdma->PhysicalBase = 0;
+		pdma->logical_base = NULL;
+		pdma->physical_base = 0;
 	}
 }
 
-/* ******  PRIVATE COUNTER FUNCTIONS ****** */
-
-/*  Reset a counter's index and overflow event capture flags. */
-
-static void ResetCapFlags_A(struct comedi_device *dev, struct enc_private *k)
-{
-	DEBIreplace(dev, k->MyCRB, ~CRBMSK_INTCTRL,
-		    CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A);
-}
-
-static void ResetCapFlags_B(struct comedi_device *dev, struct enc_private *k)
-{
-	DEBIreplace(dev, k->MyCRB, ~CRBMSK_INTCTRL,
-		    CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B);
-}
-
-/*  Return counter setup in a format (COUNTER_SETUP) that is consistent */
-/*  for both A and B counters. */
-
-static uint16_t GetMode_A(struct comedi_device *dev, struct enc_private *k)
-{
-	register uint16_t cra;
-	register uint16_t crb;
-	register uint16_t setup;
-
-	/*  Fetch CRA and CRB register images. */
-	cra = DEBIread(dev, k->MyCRA);
-	crb = DEBIread(dev, k->MyCRB);
-
-	/*  Populate the standardized counter setup bit fields.  Note: */
-	/*  IndexSrc is restricted to ENC_X or IndxPol. */
-	setup = ((cra & STDMSK_LOADSRC)	/*  LoadSrc  = LoadSrcA. */
-		 |((crb << (STDBIT_LATCHSRC - CRBBIT_LATCHSRC)) & STDMSK_LATCHSRC)	/*  LatchSrc = LatchSrcA. */
-		 |((cra << (STDBIT_INTSRC - CRABIT_INTSRC_A)) & STDMSK_INTSRC)	/*  IntSrc   = IntSrcA. */
-		 |((cra << (STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1))) & STDMSK_INDXSRC)	/*  IndxSrc  = IndxSrcA<1>. */
-		 |((cra >> (CRABIT_INDXPOL_A - STDBIT_INDXPOL)) & STDMSK_INDXPOL)	/*  IndxPol  = IndxPolA. */
-		 |((crb >> (CRBBIT_CLKENAB_A - STDBIT_CLKENAB)) & STDMSK_CLKENAB));	/*  ClkEnab  = ClkEnabA. */
-
-	/*  Adjust mode-dependent parameters. */
-	if (cra & (2 << CRABIT_CLKSRC_A))	/*  If Timer mode (ClkSrcA<1> == 1): */
-		setup |= ((CLKSRC_TIMER << STDBIT_CLKSRC)	/*    Indicate Timer mode. */
-			  |((cra << (STDBIT_CLKPOL - CRABIT_CLKSRC_A)) & STDMSK_CLKPOL)	/*    Set ClkPol to indicate count direction (ClkSrcA<0>). */
-			  |(MULT_X1 << STDBIT_CLKMULT));	/*    ClkMult must be 1x in Timer mode. */
-
-	else			/*  If Counter mode (ClkSrcA<1> == 0): */
-		setup |= ((CLKSRC_COUNTER << STDBIT_CLKSRC)	/*    Indicate Counter mode. */
-			  |((cra >> (CRABIT_CLKPOL_A - STDBIT_CLKPOL)) & STDMSK_CLKPOL)	/*    Pass through ClkPol. */
-			  |(((cra & CRAMSK_CLKMULT_A) == (MULT_X0 << CRABIT_CLKMULT_A)) ?	/*    Force ClkMult to 1x if not legal, else pass through. */
-			    (MULT_X1 << STDBIT_CLKMULT) :
-			    ((cra >> (CRABIT_CLKMULT_A -
-				      STDBIT_CLKMULT)) & STDMSK_CLKMULT)));
-
-	/*  Return adjusted counter setup. */
-	return setup;
-}
-
-static uint16_t GetMode_B(struct comedi_device *dev, struct enc_private *k)
-{
-	register uint16_t cra;
-	register uint16_t crb;
-	register uint16_t setup;
-
-	/*  Fetch CRA and CRB register images. */
-	cra = DEBIread(dev, k->MyCRA);
-	crb = DEBIread(dev, k->MyCRB);
-
-	/*  Populate the standardized counter setup bit fields.  Note: */
-	/*  IndexSrc is restricted to ENC_X or IndxPol. */
-	setup = (((crb << (STDBIT_INTSRC - CRBBIT_INTSRC_B)) & STDMSK_INTSRC)	/*  IntSrc   = IntSrcB. */
-		 |((crb << (STDBIT_LATCHSRC - CRBBIT_LATCHSRC)) & STDMSK_LATCHSRC)	/*  LatchSrc = LatchSrcB. */
-		 |((crb << (STDBIT_LOADSRC - CRBBIT_LOADSRC_B)) & STDMSK_LOADSRC)	/*  LoadSrc  = LoadSrcB. */
-		 |((crb << (STDBIT_INDXPOL - CRBBIT_INDXPOL_B)) & STDMSK_INDXPOL)	/*  IndxPol  = IndxPolB. */
-		 |((crb >> (CRBBIT_CLKENAB_B - STDBIT_CLKENAB)) & STDMSK_CLKENAB)	/*  ClkEnab  = ClkEnabB. */
-		 |((cra >> ((CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC)) & STDMSK_INDXSRC));	/*  IndxSrc  = IndxSrcB<1>. */
-
-	/*  Adjust mode-dependent parameters. */
-	if ((crb & CRBMSK_CLKMULT_B) == (MULT_X0 << CRBBIT_CLKMULT_B))	/*  If Extender mode (ClkMultB == MULT_X0): */
-		setup |= ((CLKSRC_EXTENDER << STDBIT_CLKSRC)	/*    Indicate Extender mode. */
-			  |(MULT_X1 << STDBIT_CLKMULT)	/*    Indicate multiplier is 1x. */
-			  |((cra >> (CRABIT_CLKSRC_B - STDBIT_CLKPOL)) & STDMSK_CLKPOL));	/*    Set ClkPol equal to Timer count direction (ClkSrcB<0>). */
-
-	else if (cra & (2 << CRABIT_CLKSRC_B))	/*  If Timer mode (ClkSrcB<1> == 1): */
-		setup |= ((CLKSRC_TIMER << STDBIT_CLKSRC)	/*    Indicate Timer mode. */
-			  |(MULT_X1 << STDBIT_CLKMULT)	/*    Indicate multiplier is 1x. */
-			  |((cra >> (CRABIT_CLKSRC_B - STDBIT_CLKPOL)) & STDMSK_CLKPOL));	/*    Set ClkPol equal to Timer count direction (ClkSrcB<0>). */
-
-	else			/*  If Counter mode (ClkSrcB<1> == 0): */
-		setup |= ((CLKSRC_COUNTER << STDBIT_CLKSRC)	/*    Indicate Timer mode. */
-			  |((crb >> (CRBBIT_CLKMULT_B - STDBIT_CLKMULT)) & STDMSK_CLKMULT)	/*    Clock multiplier is passed through. */
-			  |((crb << (STDBIT_CLKPOL - CRBBIT_CLKPOL_B)) & STDMSK_CLKPOL));	/*    Clock polarity is passed through. */
-
-	/*  Return adjusted counter setup. */
-	return setup;
-}
-
-/*
- * Set the operating mode for the specified counter.  The setup
- * parameter is treated as a COUNTER_SETUP data type.  The following
- * parameters are programmable (all other parms are ignored): ClkMult,
- * ClkPol, ClkEnab, IndexSrc, IndexPol, LoadSrc.
- */
-
-static void SetMode_A(struct comedi_device *dev, struct enc_private *k,
-		      uint16_t Setup, uint16_t DisableIntSrc)
-{
-	struct s626_private *devpriv = dev->private;
-	register uint16_t cra;
-	register uint16_t crb;
-	register uint16_t setup = Setup;	/*  Cache the Standard Setup. */
-
-	/*  Initialize CRA and CRB images. */
-	cra = ((setup & CRAMSK_LOADSRC_A)	/*  Preload trigger is passed through. */
-	       |((setup & STDMSK_INDXSRC) >> (STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1))));	/*  IndexSrc is restricted to ENC_X or IndxPol. */
-
-	crb = (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A	/*  Reset any pending CounterA event captures. */
-	       | ((setup & STDMSK_CLKENAB) << (CRBBIT_CLKENAB_A - STDBIT_CLKENAB)));	/*  Clock enable is passed through. */
-
-	/*  Force IntSrc to Disabled if DisableIntSrc is asserted. */
-	if (!DisableIntSrc)
-		cra |= ((setup & STDMSK_INTSRC) >> (STDBIT_INTSRC -
-						    CRABIT_INTSRC_A));
-
-	/*  Populate all mode-dependent attributes of CRA & CRB images. */
-	switch ((setup & STDMSK_CLKSRC) >> STDBIT_CLKSRC) {
-	case CLKSRC_EXTENDER:	/*  Extender Mode: Force to Timer mode */
-		/*  (Extender valid only for B counters). */
-
-	case CLKSRC_TIMER:	/*  Timer Mode: */
-		cra |= ((2 << CRABIT_CLKSRC_A)	/*    ClkSrcA<1> selects system clock */
-			|((setup & STDMSK_CLKPOL) >> (STDBIT_CLKPOL - CRABIT_CLKSRC_A))	/*      with count direction (ClkSrcA<0>) obtained from ClkPol. */
-			|(1 << CRABIT_CLKPOL_A)	/*    ClkPolA behaves as always-on clock enable. */
-			|(MULT_X1 << CRABIT_CLKMULT_A));	/*    ClkMult must be 1x. */
-		break;
-
-	default:		/*  Counter Mode: */
-		cra |= (CLKSRC_COUNTER	/*    Select ENC_C and ENC_D as clock/direction inputs. */
-			| ((setup & STDMSK_CLKPOL) << (CRABIT_CLKPOL_A - STDBIT_CLKPOL))	/*    Clock polarity is passed through. */
-			|(((setup & STDMSK_CLKMULT) == (MULT_X0 << STDBIT_CLKMULT)) ?	/*    Force multiplier to x1 if not legal, otherwise pass through. */
-			  (MULT_X1 << CRABIT_CLKMULT_A) :
-			  ((setup & STDMSK_CLKMULT) << (CRABIT_CLKMULT_A -
-							STDBIT_CLKMULT))));
-	}
-
-	/*  Force positive index polarity if IndxSrc is software-driven only, */
-	/*  otherwise pass it through. */
-	if (~setup & STDMSK_INDXSRC)
-		cra |= ((setup & STDMSK_INDXPOL) << (CRABIT_INDXPOL_A -
-						     STDBIT_INDXPOL));
-
-	/*  If IntSrc has been forced to Disabled, update the MISC2 interrupt */
-	/*  enable mask to indicate the counter interrupt is disabled. */
-	if (DisableIntSrc)
-		devpriv->CounterIntEnabs &= ~k->MyEventBits[3];
-
-	/*  While retaining CounterB and LatchSrc configurations, program the */
-	/*  new counter operating mode. */
-	DEBIreplace(dev, k->MyCRA, CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B, cra);
-	DEBIreplace(dev, k->MyCRB, ~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A), crb);
-}
-
-static void SetMode_B(struct comedi_device *dev, struct enc_private *k,
-		      uint16_t Setup, uint16_t DisableIntSrc)
-{
-	struct s626_private *devpriv = dev->private;
-	register uint16_t cra;
-	register uint16_t crb;
-	register uint16_t setup = Setup;	/*  Cache the Standard Setup. */
-
-	/*  Initialize CRA and CRB images. */
-	cra = ((setup & STDMSK_INDXSRC) << ((CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC));	/*  IndexSrc field is restricted to ENC_X or IndxPol. */
-
-	crb = (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B	/*  Reset event captures and disable interrupts. */
-	       | ((setup & STDMSK_CLKENAB) << (CRBBIT_CLKENAB_B - STDBIT_CLKENAB))	/*  Clock enable is passed through. */
-	       |((setup & STDMSK_LOADSRC) >> (STDBIT_LOADSRC - CRBBIT_LOADSRC_B)));	/*  Preload trigger source is passed through. */
-
-	/*  Force IntSrc to Disabled if DisableIntSrc is asserted. */
-	if (!DisableIntSrc)
-		crb |= ((setup & STDMSK_INTSRC) >> (STDBIT_INTSRC -
-						    CRBBIT_INTSRC_B));
-
-	/*  Populate all mode-dependent attributes of CRA & CRB images. */
-	switch ((setup & STDMSK_CLKSRC) >> STDBIT_CLKSRC) {
-	case CLKSRC_TIMER:	/*  Timer Mode: */
-		cra |= ((2 << CRABIT_CLKSRC_B)	/*    ClkSrcB<1> selects system clock */
-			|((setup & STDMSK_CLKPOL) << (CRABIT_CLKSRC_B - STDBIT_CLKPOL)));	/*      with direction (ClkSrcB<0>) obtained from ClkPol. */
-		crb |= ((1 << CRBBIT_CLKPOL_B)	/*    ClkPolB behaves as always-on clock enable. */
-			|(MULT_X1 << CRBBIT_CLKMULT_B));	/*    ClkMultB must be 1x. */
-		break;
-
-	case CLKSRC_EXTENDER:	/*  Extender Mode: */
-		cra |= ((2 << CRABIT_CLKSRC_B)	/*    ClkSrcB source is OverflowA (same as "timer") */
-			|((setup & STDMSK_CLKPOL) << (CRABIT_CLKSRC_B - STDBIT_CLKPOL)));	/*      with direction obtained from ClkPol. */
-		crb |= ((1 << CRBBIT_CLKPOL_B)	/*    ClkPolB controls IndexB -- always set to active. */
-			|(MULT_X0 << CRBBIT_CLKMULT_B));	/*    ClkMultB selects OverflowA as the clock source. */
-		break;
-
-	default:		/*  Counter Mode: */
-		cra |= (CLKSRC_COUNTER << CRABIT_CLKSRC_B);	/*    Select ENC_C and ENC_D as clock/direction inputs. */
-		crb |= (((setup & STDMSK_CLKPOL) >> (STDBIT_CLKPOL - CRBBIT_CLKPOL_B))	/*    ClkPol is passed through. */
-			|(((setup & STDMSK_CLKMULT) == (MULT_X0 << STDBIT_CLKMULT)) ?	/*    Force ClkMult to x1 if not legal, otherwise pass through. */
-			  (MULT_X1 << CRBBIT_CLKMULT_B) :
-			  ((setup & STDMSK_CLKMULT) << (CRBBIT_CLKMULT_B -
-							STDBIT_CLKMULT))));
-	}
-
-	/*  Force positive index polarity if IndxSrc is software-driven only, */
-	/*  otherwise pass it through. */
-	if (~setup & STDMSK_INDXSRC)
-		crb |= ((setup & STDMSK_INDXPOL) >> (STDBIT_INDXPOL -
-						     CRBBIT_INDXPOL_B));
-
-	/*  If IntSrc has been forced to Disabled, update the MISC2 interrupt */
-	/*  enable mask to indicate the counter interrupt is disabled. */
-	if (DisableIntSrc)
-		devpriv->CounterIntEnabs &= ~k->MyEventBits[3];
-
-	/*  While retaining CounterA and LatchSrc configurations, program the */
-	/*  new counter operating mode. */
-	DEBIreplace(dev, k->MyCRA, ~(CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B), cra);
-	DEBIreplace(dev, k->MyCRB, CRBMSK_CLKENAB_A | CRBMSK_LATCHSRC, crb);
-}
-
-/*  Return/set a counter's enable.  enab: 0=always enabled, 1=enabled by index. */
-
-static void SetEnable_A(struct comedi_device *dev, struct enc_private *k,
-			uint16_t enab)
-{
-	DEBIreplace(dev, k->MyCRB, ~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A),
-		    enab << CRBBIT_CLKENAB_A);
-}
-
-static void SetEnable_B(struct comedi_device *dev, struct enc_private *k,
-			uint16_t enab)
-{
-	DEBIreplace(dev, k->MyCRB, ~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_B),
-		    enab << CRBBIT_CLKENAB_B);
-}
-
-static uint16_t GetEnable_A(struct comedi_device *dev, struct enc_private *k)
-{
-	return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_A) & 1;
-}
-
-static uint16_t GetEnable_B(struct comedi_device *dev, struct enc_private *k)
-{
-	return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_B) & 1;
-}
-
-/*
- * static uint16_t GetLatchSource(struct comedi_device *dev, struct enc_private *k )
- * {
- *	return ( DEBIread( dev, k->MyCRB) >> CRBBIT_LATCHSRC ) & 3;
- * }
- */
-
-/*
- * Return/set the event that will trigger transfer of the preload
- * register into the counter.  0=ThisCntr_Index, 1=ThisCntr_Overflow,
- * 2=OverflowA (B counters only), 3=disabled.
- */
-
-static void SetLoadTrig_A(struct comedi_device *dev, struct enc_private *k,
-			  uint16_t Trig)
-{
-	DEBIreplace(dev, k->MyCRA, ~CRAMSK_LOADSRC_A,
-		    Trig << CRABIT_LOADSRC_A);
-}
-
-static void SetLoadTrig_B(struct comedi_device *dev, struct enc_private *k,
-			  uint16_t Trig)
-{
-	DEBIreplace(dev, k->MyCRB, ~(CRBMSK_LOADSRC_B | CRBMSK_INTCTRL),
-		    Trig << CRBBIT_LOADSRC_B);
-}
-
-static uint16_t GetLoadTrig_A(struct comedi_device *dev, struct enc_private *k)
-{
-	return (DEBIread(dev, k->MyCRA) >> CRABIT_LOADSRC_A) & 3;
-}
-
-static uint16_t GetLoadTrig_B(struct comedi_device *dev, struct enc_private *k)
-{
-	return (DEBIread(dev, k->MyCRB) >> CRBBIT_LOADSRC_B) & 3;
-}
-
-/* Return/set counter interrupt source and clear any captured
- * index/overflow events.  IntSource: 0=Disabled, 1=OverflowOnly,
- * 2=IndexOnly, 3=IndexAndOverflow.
- */
-
-static void SetIntSrc_A(struct comedi_device *dev, struct enc_private *k,
-			uint16_t IntSource)
-{
-	struct s626_private *devpriv = dev->private;
-
-	/*  Reset any pending counter overflow or index captures. */
-	DEBIreplace(dev, k->MyCRB, ~CRBMSK_INTCTRL,
-		    CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A);
-
-	/*  Program counter interrupt source. */
-	DEBIreplace(dev, k->MyCRA, ~CRAMSK_INTSRC_A,
-		    IntSource << CRABIT_INTSRC_A);
-
-	/*  Update MISC2 interrupt enable mask. */
-	devpriv->CounterIntEnabs =
-	    (devpriv->CounterIntEnabs & ~k->
-	     MyEventBits[3]) | k->MyEventBits[IntSource];
-}
-
-static void SetIntSrc_B(struct comedi_device *dev, struct enc_private *k,
-			uint16_t IntSource)
-{
-	struct s626_private *devpriv = dev->private;
-	uint16_t crb;
-
-	/*  Cache writeable CRB register image. */
-	crb = DEBIread(dev, k->MyCRB) & ~CRBMSK_INTCTRL;
-
-	/*  Reset any pending counter overflow or index captures. */
-	DEBIwrite(dev, k->MyCRB,
-		  (uint16_t) (crb | CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B));
-
-	/*  Program counter interrupt source. */
-	DEBIwrite(dev, k->MyCRB,
-		  (uint16_t) ((crb & ~CRBMSK_INTSRC_B) | (IntSource <<
-							  CRBBIT_INTSRC_B)));
-
-	/*  Update MISC2 interrupt enable mask. */
-	devpriv->CounterIntEnabs =
-	    (devpriv->CounterIntEnabs & ~k->
-	     MyEventBits[3]) | k->MyEventBits[IntSource];
-}
-
-static uint16_t GetIntSrc_A(struct comedi_device *dev, struct enc_private *k)
-{
-	return (DEBIread(dev, k->MyCRA) >> CRABIT_INTSRC_A) & 3;
-}
-
-static uint16_t GetIntSrc_B(struct comedi_device *dev, struct enc_private *k)
-{
-	return (DEBIread(dev, k->MyCRB) >> CRBBIT_INTSRC_B) & 3;
-}
-
-/*  Return/set the clock multiplier. */
-
-/* static void SetClkMult(struct comedi_device *dev, struct enc_private *k, uint16_t value )  */
-/* { */
-/*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKMULT ) | ( value << STDBIT_CLKMULT ) ), FALSE ); */
-/* } */
-
-/* static uint16_t GetClkMult(struct comedi_device *dev, struct enc_private *k )  */
-/* { */
-/*   return ( k->GetMode(dev, k ) >> STDBIT_CLKMULT ) & 3; */
-/* } */
-
-/* Return/set the clock polarity. */
-
-/* static void SetClkPol( struct comedi_device *dev,struct enc_private *k, uint16_t value )  */
-/* { */
-/*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKPOL ) | ( value << STDBIT_CLKPOL ) ), FALSE ); */
-/* } */
-
-/* static uint16_t GetClkPol(struct comedi_device *dev, struct enc_private *k )  */
-/* { */
-/*   return ( k->GetMode(dev, k ) >> STDBIT_CLKPOL ) & 1; */
-/* } */
-
-/* Return/set the clock source.  */
-
-/* static void SetClkSrc( struct comedi_device *dev,struct enc_private *k, uint16_t value )  */
-/* { */
-/*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKSRC ) | ( value << STDBIT_CLKSRC ) ), FALSE ); */
-/* } */
-
-/* static uint16_t GetClkSrc( struct comedi_device *dev,struct enc_private *k )  */
-/* { */
-/*   return ( k->GetMode(dev, k ) >> STDBIT_CLKSRC ) & 3; */
-/* } */
-
-/* Return/set the index polarity. */
-
-/* static void SetIndexPol(struct comedi_device *dev, struct enc_private *k, uint16_t value )  */
-/* { */
-/*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_INDXPOL ) | ( (value != 0) << STDBIT_INDXPOL ) ), FALSE ); */
-/* } */
-
-/* static uint16_t GetIndexPol(struct comedi_device *dev, struct enc_private *k )  */
-/* { */
-/*   return ( k->GetMode(dev, k ) >> STDBIT_INDXPOL ) & 1; */
-/* } */
-
-/*  Return/set the index source. */
-
-/* static void SetIndexSrc(struct comedi_device *dev, struct enc_private *k, uint16_t value )  */
-/* { */
-/*   k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_INDXSRC ) | ( (value != 0) << STDBIT_INDXSRC ) ), FALSE ); */
-/* } */
-
-/* static uint16_t GetIndexSrc(struct comedi_device *dev, struct enc_private *k )  */
-/* { */
-/*   return ( k->GetMode(dev, k ) >> STDBIT_INDXSRC ) & 1; */
-/* } */
-
-/*  Generate an index pulse. */
-
-static void PulseIndex_A(struct comedi_device *dev, struct enc_private *k)
-{
-	register uint16_t cra;
-
-	cra = DEBIread(dev, k->MyCRA);	/*  Pulse index. */
-	DEBIwrite(dev, k->MyCRA, (uint16_t) (cra ^ CRAMSK_INDXPOL_A));
-	DEBIwrite(dev, k->MyCRA, cra);
-}
-
-static void PulseIndex_B(struct comedi_device *dev, struct enc_private *k)
-{
-	register uint16_t crb;
-
-	crb = DEBIread(dev, k->MyCRB) & ~CRBMSK_INTCTRL;	/*  Pulse index. */
-	DEBIwrite(dev, k->MyCRB, (uint16_t) (crb ^ CRBMSK_INDXPOL_B));
-	DEBIwrite(dev, k->MyCRB, crb);
-}
-
-static struct enc_private enc_private_data[] = {
-	{
-		.GetEnable	= GetEnable_A,
-		.GetIntSrc	= GetIntSrc_A,
-		.GetLoadTrig	= GetLoadTrig_A,
-		.GetMode	= GetMode_A,
-		.PulseIndex	= PulseIndex_A,
-		.SetEnable	= SetEnable_A,
-		.SetIntSrc	= SetIntSrc_A,
-		.SetLoadTrig	= SetLoadTrig_A,
-		.SetMode	= SetMode_A,
-		.ResetCapFlags	= ResetCapFlags_A,
-		.MyCRA		= LP_CR0A,
-		.MyCRB		= LP_CR0B,
-		.MyLatchLsw	= LP_CNTR0ALSW,
-		.MyEventBits	= EVBITS(0),
-	}, {
-		.GetEnable	= GetEnable_A,
-		.GetIntSrc	= GetIntSrc_A,
-		.GetLoadTrig	= GetLoadTrig_A,
-		.GetMode	= GetMode_A,
-		.PulseIndex	= PulseIndex_A,
-		.SetEnable	= SetEnable_A,
-		.SetIntSrc	= SetIntSrc_A,
-		.SetLoadTrig	= SetLoadTrig_A,
-		.SetMode	= SetMode_A,
-		.ResetCapFlags	= ResetCapFlags_A,
-		.MyCRA		= LP_CR1A,
-		.MyCRB		= LP_CR1B,
-		.MyLatchLsw	= LP_CNTR1ALSW,
-		.MyEventBits	= EVBITS(1),
-	}, {
-		.GetEnable	= GetEnable_A,
-		.GetIntSrc	= GetIntSrc_A,
-		.GetLoadTrig	= GetLoadTrig_A,
-		.GetMode	= GetMode_A,
-		.PulseIndex	= PulseIndex_A,
-		.SetEnable	= SetEnable_A,
-		.SetIntSrc	= SetIntSrc_A,
-		.SetLoadTrig	= SetLoadTrig_A,
-		.SetMode	= SetMode_A,
-		.ResetCapFlags	= ResetCapFlags_A,
-		.MyCRA		= LP_CR2A,
-		.MyCRB		= LP_CR2B,
-		.MyLatchLsw	= LP_CNTR2ALSW,
-		.MyEventBits	= EVBITS(2),
-	}, {
-		.GetEnable	= GetEnable_B,
-		.GetIntSrc	= GetIntSrc_B,
-		.GetLoadTrig	= GetLoadTrig_B,
-		.GetMode	= GetMode_B,
-		.PulseIndex	= PulseIndex_B,
-		.SetEnable	= SetEnable_B,
-		.SetIntSrc	= SetIntSrc_B,
-		.SetLoadTrig	= SetLoadTrig_B,
-		.SetMode	= SetMode_B,
-		.ResetCapFlags	= ResetCapFlags_B,
-		.MyCRA		= LP_CR0A,
-		.MyCRB		= LP_CR0B,
-		.MyLatchLsw	= LP_CNTR0BLSW,
-		.MyEventBits	= EVBITS(3),
-	}, {
-		.GetEnable	= GetEnable_B,
-		.GetIntSrc	= GetIntSrc_B,
-		.GetLoadTrig	= GetLoadTrig_B,
-		.GetMode	= GetMode_B,
-		.PulseIndex	= PulseIndex_B,
-		.SetEnable	= SetEnable_B,
-		.SetIntSrc	= SetIntSrc_B,
-		.SetLoadTrig	= SetLoadTrig_B,
-		.SetMode	= SetMode_B,
-		.ResetCapFlags	= ResetCapFlags_B,
-		.MyCRA		= LP_CR1A,
-		.MyCRB		= LP_CR1B,
-		.MyLatchLsw	= LP_CNTR1BLSW,
-		.MyEventBits	= EVBITS(4),
-	}, {
-		.GetEnable	= GetEnable_B,
-		.GetIntSrc	= GetIntSrc_B,
-		.GetLoadTrig	= GetLoadTrig_B,
-		.GetMode	= GetMode_B,
-		.PulseIndex	= PulseIndex_B,
-		.SetEnable	= SetEnable_B,
-		.SetIntSrc	= SetIntSrc_B,
-		.SetLoadTrig	= SetLoadTrig_B,
-		.SetMode	= SetMode_B,
-		.ResetCapFlags	= ResetCapFlags_B,
-		.MyCRA		= LP_CR2A,
-		.MyCRB		= LP_CR2B,
-		.MyLatchLsw	= LP_CNTR2BLSW,
-		.MyEventBits	= EVBITS(5),
-	},
-};
-
-static void CountersInit(struct comedi_device *dev)
+static void s626_counters_init(struct comedi_device *dev)
 {
 	int chan;
-	struct enc_private *k;
-	uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) |	/*  Preload upon */
-	    /*  index. */
-	    (INDXSRC_SOFT << BF_INDXSRC) |	/*  Disable hardware index. */
-	    (CLKSRC_COUNTER << BF_CLKSRC) |	/*  Operating mode is counter. */
-	    (CLKPOL_POS << BF_CLKPOL) |	/*  Active high clock. */
-	    (CNTDIR_UP << BF_CLKPOL) |	/*  Count direction is up. */
-	    (CLKMULT_1X << BF_CLKMULT) |	/*  Clock multiplier is 1x. */
-	    (CLKENAB_INDEX << BF_CLKENAB);	/*  Enabled by index */
+	const struct s626_enc_info *k;
+	uint16_t setup =
+		/* Preload upon index. */
+		S626_SET_STD_LOADSRC(S626_LOADSRC_INDX) |
+		/* Disable hardware index. */
+		S626_SET_STD_INDXSRC(S626_INDXSRC_SOFT) |
+		/* Operating mode is counter. */
+		S626_SET_STD_ENCMODE(S626_ENCMODE_COUNTER) |
+		/* Active high clock. */
+		S626_SET_STD_CLKPOL(S626_CLKPOL_POS) |
+		/* Clock multiplier is 1x. */
+		S626_SET_STD_CLKMULT(S626_CLKMULT_1X) |
+		/* Enabled by index */
+		S626_SET_STD_CLKENAB(S626_CLKENAB_INDEX);
 
-	/*  Disable all counter interrupts and clear any captured counter events. */
+	/*
+	 * Disable all counter interrupts and clear any captured counter events.
+	 */
 	for (chan = 0; chan < S626_ENCODER_CHANNELS; chan++) {
-		k = &encpriv[chan];
-		k->SetMode(dev, k, Setup, TRUE);
-		k->SetIntSrc(dev, k, 0);
-		k->ResetCapFlags(dev, k);
-		k->SetEnable(dev, k, CLKENAB_ALWAYS);
+		k = &s626_enc_chan_info[chan];
+		k->set_mode(dev, k, setup, true);
+		k->set_int_src(dev, k, 0);
+		k->reset_cap_flags(dev, k);
+		k->set_enable(dev, k, S626_CLKENAB_ALWAYS);
 	}
 }
 
@@ -2316,17 +2533,17 @@
 	void *addr;
 	dma_addr_t appdma;
 
-	addr = pci_alloc_consistent(pcidev, DMABUF_SIZE, &appdma);
+	addr = pci_alloc_consistent(pcidev, S626_DMABUF_SIZE, &appdma);
 	if (!addr)
 		return -ENOMEM;
-	devpriv->ANABuf.LogicalBase = addr;
-	devpriv->ANABuf.PhysicalBase = appdma;
+	devpriv->ana_buf.logical_base = addr;
+	devpriv->ana_buf.physical_base = appdma;
 
-	addr = pci_alloc_consistent(pcidev, DMABUF_SIZE, &appdma);
+	addr = pci_alloc_consistent(pcidev, S626_DMABUF_SIZE, &appdma);
 	if (!addr)
 		return -ENOMEM;
-	devpriv->RPSBuf.LogicalBase = addr;
-	devpriv->RPSBuf.PhysicalBase = appdma;
+	devpriv->rps_buf.logical_base = addr;
+	devpriv->rps_buf.physical_base = appdma;
 
 	return 0;
 }
@@ -2334,42 +2551,43 @@
 static void s626_initialize(struct comedi_device *dev)
 {
 	struct s626_private *devpriv = dev->private;
-	dma_addr_t pPhysBuf;
+	dma_addr_t phys_buf;
 	uint16_t chan;
 	int i;
 
 	/* Enable DEBI and audio pins, enable I2C interface */
-	s626_mc_enable(dev, MC1_DEBI | MC1_AUDIO | MC1_I2C, P_MC1);
+	s626_mc_enable(dev, S626_MC1_DEBI | S626_MC1_AUDIO | S626_MC1_I2C,
+		       S626_P_MC1);
 
 	/*
-	 *  Configure DEBI operating mode
+	 * Configure DEBI operating mode
 	 *
-	 *   Local bus is 16 bits wide
-	 *   Declare DEBI transfer timeout interval
-	 *   Set up byte lane steering
-	 *   Intel-compatible local bus (DEBI never times out)
+	 *  Local bus is 16 bits wide
+	 *  Declare DEBI transfer timeout interval
+	 *  Set up byte lane steering
+	 *  Intel-compatible local bus (DEBI never times out)
 	 */
-	writel(DEBI_CFG_SLAVE16 |
-	       (DEBI_TOUT << DEBI_CFG_TOUT_BIT) |
-	       DEBI_SWAP | DEBI_CFG_INTEL,
-	       devpriv->mmio + P_DEBICFG);
+	writel(S626_DEBI_CFG_SLAVE16 |
+	       (S626_DEBI_TOUT << S626_DEBI_CFG_TOUT_BIT) | S626_DEBI_SWAP |
+	       S626_DEBI_CFG_INTEL, devpriv->mmio + S626_P_DEBICFG);
 
 	/* Disable MMU paging */
-	writel(DEBI_PAGE_DISABLE, devpriv->mmio + P_DEBIPAGE);
+	writel(S626_DEBI_PAGE_DISABLE, devpriv->mmio + S626_P_DEBIPAGE);
 
 	/* Init GPIO so that ADC Start* is negated */
-	writel(GPIO_BASE | GPIO1_HI, devpriv->mmio + P_GPIO);
+	writel(S626_GPIO_BASE | S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO);
 
 	/* I2C device address for onboard eeprom (revb) */
-	devpriv->I2CAdrs = 0xA0;
+	devpriv->i2c_adrs = 0xA0;
 
 	/*
 	 * Issue an I2C ABORT command to halt any I2C
 	 * operation in progress and reset BUSY flag.
 	 */
-	writel(I2C_CLKSEL | I2C_ABORT, devpriv->mmio + P_I2CSTAT);
-	s626_mc_enable(dev, MC2_UPLD_IIC, P_MC2);
-	while (!(readl(devpriv->mmio + P_MC2) & MC2_UPLD_IIC))
+	writel(S626_I2C_CLKSEL | S626_I2C_ABORT,
+	       devpriv->mmio + S626_P_I2CSTAT);
+	s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2);
+	while (!(readl(devpriv->mmio + S626_P_MC2) & S626_MC2_UPLD_IIC))
 		;
 
 	/*
@@ -2377,9 +2595,9 @@
 	 * reg twice to reset all  I2C error flags.
 	 */
 	for (i = 0; i < 2; i++) {
-		writel(I2C_CLKSEL, devpriv->mmio + P_I2CSTAT);
-		s626_mc_enable(dev, MC2_UPLD_IIC, P_MC2);
-		while (!s626_mc_test(dev, MC2_UPLD_IIC, P_MC2))
+		writel(S626_I2C_CLKSEL, devpriv->mmio + S626_P_I2CSTAT);
+		s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2);
+		while (!s626_mc_test(dev, S626_MC2_UPLD_IIC, S626_P_MC2))
 			;
 	}
 
@@ -2389,31 +2607,32 @@
 	 * DAC data setup times are satisfied, enable DAC serial
 	 * clock out.
 	 */
-	writel(ACON2_INIT, devpriv->mmio + P_ACON2);
+	writel(S626_ACON2_INIT, devpriv->mmio + S626_P_ACON2);
 
 	/*
 	 * Set up TSL1 slot list, which is used to control the
-	 * accumulation of ADC data: RSD1 = shift data in on SD1.
-	 * SIB_A1  = store data uint8_t at next available location
+	 * accumulation of ADC data: S626_RSD1 = shift data in on SD1.
+	 * S626_SIB_A1  = store data uint8_t at next available location
 	 * in FB BUFFER1 register.
 	 */
-	writel(RSD1 | SIB_A1, devpriv->mmio + P_TSL1);
-	writel(RSD1 | SIB_A1 | EOS, devpriv->mmio + P_TSL1 + 4);
+	writel(S626_RSD1 | S626_SIB_A1, devpriv->mmio + S626_P_TSL1);
+	writel(S626_RSD1 | S626_SIB_A1 | S626_EOS,
+	       devpriv->mmio + S626_P_TSL1 + 4);
 
 	/* Enable TSL1 slot list so that it executes all the time */
-	writel(ACON1_ADCSTART, devpriv->mmio + P_ACON1);
+	writel(S626_ACON1_ADCSTART, devpriv->mmio + S626_P_ACON1);
 
 	/*
 	 * Initialize RPS registers used for ADC
 	 */
 
 	/* Physical start of RPS program */
-	writel((uint32_t)devpriv->RPSBuf.PhysicalBase,
-	       devpriv->mmio + P_RPSADDR1);
+	writel((uint32_t)devpriv->rps_buf.physical_base,
+	       devpriv->mmio + S626_P_RPSADDR1);
 	/* RPS program performs no explicit mem writes */
-	writel(0, devpriv->mmio + P_RPSPAGE1);
+	writel(0, devpriv->mmio + S626_P_RPSPAGE1);
 	/* Disable RPS timeouts */
-	writel(0, devpriv->mmio + P_RPS1_TOUT);
+	writel(0, devpriv->mmio + S626_P_RPS1_TOUT);
 
 #if 0
 	/*
@@ -2425,38 +2644,37 @@
 	 * because the SAA7146 ADC interface does not start up in
 	 * a defined state after a PCI reset.
 	 */
-
 	{
-	uint8_t PollList;
-	uint16_t AdcData;
-	uint16_t StartVal;
-	uint16_t index;
-	unsigned int data[16];
+		uint8_t poll_list;
+		uint16_t adc_data;
+		uint16_t start_val;
+		uint16_t index;
+		unsigned int data[16];
 
-	/* Create a simple polling list for analog input channel 0 */
-	PollList = EOPL;
-	ResetADC(dev, &PollList);
+		/* Create a simple polling list for analog input channel 0 */
+		poll_list = S626_EOPL;
+		s626_reset_adc(dev, &poll_list);
 
-	/* Get initial ADC value */
-	s626_ai_rinsn(dev, dev->subdevices, NULL, data);
-	StartVal = data[0];
-
-	/*
-	 * VERSION 2.01 CHANGE: TIMEOUT ADDED TO PREVENT HANGED EXECUTION.
-	 *
-	 * Invoke ADCs until the new ADC value differs from the initial
-	 * value or a timeout occurs.  The timeout protects against the
-	 * possibility that the driver is restarting and the ADC data is a
-	 * fixed value resulting from the applied ADC analog input being
-	 * unusually quiet or at the rail.
-	 */
-	for (index = 0; index < 500; index++) {
+		/* Get initial ADC value */
 		s626_ai_rinsn(dev, dev->subdevices, NULL, data);
-		AdcData = data[0];
-		if (AdcData != StartVal)
-			break;
-	}
+		start_val = data[0];
 
+		/*
+		 * VERSION 2.01 CHANGE: TIMEOUT ADDED TO PREVENT HANGED
+		 * EXECUTION.
+		 *
+		 * Invoke ADCs until the new ADC value differs from the initial
+		 * value or a timeout occurs.  The timeout protects against the
+		 * possibility that the driver is restarting and the ADC data is
+		 * a fixed value resulting from the applied ADC analog input
+		 * being unusually quiet or at the rail.
+		 */
+		for (index = 0; index < 500; index++) {
+			s626_ai_rinsn(dev, dev->subdevices, NULL, data);
+			adc_data = data[0];
+			if (adc_data != start_val)
+				break;
+		}
 	}
 #endif	/* SAA7146 BUG WORKAROUND */
 
@@ -2469,7 +2687,7 @@
 	 *   burst length = 1 DWORD
 	 *   threshold = 1 DWORD.
 	 */
-	writel(0, devpriv->mmio + P_PCI_BT_A);
+	writel(0, devpriv->mmio + S626_P_PCI_BT_A);
 
 	/*
 	 * Init Audio2's output DMA physical addresses.  The protection
@@ -2477,18 +2695,18 @@
 	 * single DWORD will be transferred each time a DMA transfer is
 	 * enabled.
 	 */
-	pPhysBuf = devpriv->ANABuf.PhysicalBase +
-		   (DAC_WDMABUF_OS * sizeof(uint32_t));
-	writel((uint32_t)pPhysBuf, devpriv->mmio + P_BASEA2_OUT);
-	writel((uint32_t)(pPhysBuf + sizeof(uint32_t)),
-	       devpriv->mmio + P_PROTA2_OUT);
+	phys_buf = devpriv->ana_buf.physical_base +
+		   (S626_DAC_WDMABUF_OS * sizeof(uint32_t));
+	writel((uint32_t)phys_buf, devpriv->mmio + S626_P_BASEA2_OUT);
+	writel((uint32_t)(phys_buf + sizeof(uint32_t)),
+	       devpriv->mmio + S626_P_PROTA2_OUT);
 
 	/*
 	 * Cache Audio2's output DMA buffer logical address.  This is
 	 * where DAC data is buffered for A2 output DMA transfers.
 	 */
-	devpriv->pDacWBuf = (uint32_t *)devpriv->ANABuf.LogicalBase +
-			    DAC_WDMABUF_OS;
+	devpriv->dac_wbuf = (uint32_t *)devpriv->ana_buf.logical_base +
+			    S626_DAC_WDMABUF_OS;
 
 	/*
 	 * Audio2's output channels does not use paging.  The
@@ -2496,7 +2714,7 @@
 	 * DMAC will automatically halt and its PCI address pointer
 	 * will be reset when the protection address is reached.
 	 */
-	writel(8, devpriv->mmio + P_PAGEA2_OUT);
+	writel(8, devpriv->mmio + S626_P_PAGEA2_OUT);
 
 	/*
 	 * Initialize time slot list 2 (TSL2), which is used to control
@@ -2511,7 +2729,8 @@
 	 */
 
 	/* Slot 0: Trap TSL execution, shift 0xFF into FB_BUFFER2 */
-	writel(XSD2 | RSD3 | SIB_A2 | EOS, devpriv->mmio + VECTPORT(0));
+	writel(S626_XSD2 | S626_RSD3 | S626_SIB_A2 | S626_EOS,
+	       devpriv->mmio + S626_VECTPORT(0));
 
 	/*
 	 * Initialize slot 1, which is constant.  Slot 1 causes a
@@ -2523,18 +2742,18 @@
 	 */
 
 	/* Slot 1: Fetch DWORD from Audio2's output FIFO */
-	writel(LF_A2, devpriv->mmio + VECTPORT(1));
+	writel(S626_LF_A2, devpriv->mmio + S626_VECTPORT(1));
 
 	/* Start DAC's audio interface (TSL2) running */
-	writel(ACON1_DACSTART, devpriv->mmio + P_ACON1);
+	writel(S626_ACON1_DACSTART, devpriv->mmio + S626_P_ACON1);
 
 	/*
 	 * Init Trim DACs to calibrated values.  Do it twice because the
 	 * SAA7146 audio channel does not always reset properly and
 	 * sometimes causes the first few TrimDAC writes to malfunction.
 	 */
-	LoadTrimDACs(dev);
-	LoadTrimDACs(dev);
+	s626_load_trim_dacs(dev);
+	s626_load_trim_dacs(dev);
 
 	/*
 	 * Manually init all gate array hardware in case this is a soft
@@ -2549,10 +2768,10 @@
 	 * polarity images.
 	 */
 	for (chan = 0; chan < S626_DAC_CHANNELS; chan++)
-		SetDAC(dev, chan, 0);
+		s626_set_dac(dev, chan, 0);
 
 	/* Init counters */
-	CountersInit(dev);
+	s626_counters_init(dev);
 
 	/*
 	 * Without modifying the state of the Battery Backup enab, disable
@@ -2560,8 +2779,8 @@
 	 * standard DIO (vs. counter overflow) mode, disable the battery
 	 * charger, and reset the watchdog interval selector to zero.
 	 */
-	WriteMISC2(dev, (uint16_t)(DEBIread(dev, LP_RDMISC2) &
-				   MISC2_BATT_ENABLE));
+	s626_write_misc2(dev, (s626_debi_read(dev, S626_LP_RDMISC2) &
+			       S626_MISC2_BATT_ENABLE));
 
 	/* Initialize the digital I/O subsystem */
 	s626_dio_init(dev);
@@ -2588,10 +2807,10 @@
 		return -ENOMEM;
 
 	/* disable master interrupt */
-	writel(0, devpriv->mmio + P_IER);
+	writel(0, devpriv->mmio + S626_P_IER);
 
 	/* soft reset */
-	writel(MC1_SOFT_RESET, devpriv->mmio + P_MC1);
+	writel(S626_MC1_SOFT_RESET, devpriv->mmio + S626_P_MC1);
 
 	/* DMA FIXME DMA// */
 
@@ -2670,7 +2889,7 @@
 	s->io_bits	= 0xffff;
 	s->private	= (void *)2;	/* DIO group 2 */
 	s->range_table	= &range_digital;
-	s->insn_config 	= s626_dio_insn_config;
+	s->insn_config	= s626_dio_insn_config;
 	s->insn_bits	= s626_dio_insn_bits;
 
 	s = &dev->subdevices[5];
@@ -2679,7 +2898,6 @@
 	s->subdev_flags	= SDF_WRITABLE | SDF_READABLE | SDF_LSAMPL;
 	s->n_chan	= S626_ENCODER_CHANNELS;
 	s->maxdata	= 0xffffff;
-	s->private	= enc_private_data;
 	s->range_table	= &range_unknown;
 	s->insn_config	= s626_enc_insn_config;
 	s->insn_read	= s626_enc_insn_read;
@@ -2703,20 +2921,22 @@
 		if (devpriv->mmio) {
 			/* interrupt mask */
 			/* Disable master interrupt */
-			writel(0, devpriv->mmio + P_IER);
+			writel(0, devpriv->mmio + S626_P_IER);
 			/* Clear board's IRQ status flag */
-			writel(IRQ_GPIO3 | IRQ_RPS1,
-			       devpriv->mmio + P_ISR);
+			writel(S626_IRQ_GPIO3 | S626_IRQ_RPS1,
+			       devpriv->mmio + S626_P_ISR);
 
-			/*  Disable the watchdog timer and battery charger. */
-			WriteMISC2(dev, 0);
+			/* Disable the watchdog timer and battery charger. */
+			s626_write_misc2(dev, 0);
 
 			/* Close all interfaces on 7146 device */
-			writel(MC1_SHUTDOWN, devpriv->mmio + P_MC1);
-			writel(ACON1_BASE, devpriv->mmio + P_ACON1);
+			writel(S626_MC1_SHUTDOWN, devpriv->mmio + S626_P_MC1);
+			writel(S626_ACON1_BASE, devpriv->mmio + S626_P_ACON1);
 
-			CloseDMAB(dev, &devpriv->RPSBuf, DMABUF_SIZE);
-			CloseDMAB(dev, &devpriv->ANABuf, DMABUF_SIZE);
+			s626_close_dma_b(dev, &devpriv->rps_buf,
+					 S626_DMABUF_SIZE);
+			s626_close_dma_b(dev, &devpriv->ana_buf,
+					 S626_DMABUF_SIZE);
 		}
 
 		if (dev->irq)
@@ -2746,8 +2966,8 @@
  * Philips SAA7146 media/dvb based cards.
  */
 static DEFINE_PCI_DEVICE_TABLE(s626_pci_table) = {
-	{ PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626,
-		PCI_SUBVENDOR_ID_S626, PCI_SUBDEVICE_ID_S626, 0, 0, 0 },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146,
+			 0x6000, 0x0272) },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, s626_pci_table);
diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h
index a85e6bd..33b7273 100644
--- a/drivers/staging/comedi/drivers/s626.h
+++ b/drivers/staging/comedi/drivers/s626.h
@@ -1,690 +1,774 @@
 /*
-  comedi/drivers/s626.h
-  Sensoray s626 Comedi driver, header file
+ * comedi/drivers/s626.h
+ * Sensoray s626 Comedi driver, header file
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ *
+ * Based on Sensoray Model 626 Linux driver Version 0.2
+ * Copyright (C) 2002-2004 Sensoray Co., Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
 
-  COMEDI - Linux Control and Measurement Device Interface
-  Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+#ifndef S626_H_INCLUDED
+#define S626_H_INCLUDED
 
-  Based on Sensoray Model 626 Linux driver Version 0.2
-  Copyright (C) 2002-2004 Sensoray Co., Inc.
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-*/
-
-/*
-  Driver: s626.o (s626.ko)
-  Description: Sensoray 626 driver
-  Devices: Sensoray s626
-  Authors: Gianluca Palli <gpalli@deis.unibo.it>,
-  Updated: Thu, 12 Jul 2005
-  Status: experimental
-
-  Configuration Options:
-  analog input:
-   none
-
-  analog output:
-   none
-
-  digital channel:
-   s626 has 3 dio subdevices (2,3 and 4) each with 16 i/o channels
-   supported configuration options:
-   INSN_CONFIG_DIO_QUERY
-   COMEDI_INPUT
-   COMEDI_OUTPUT
-
-  encoder:
-   Every channel must be configured before reading.
-
-   Example code
-
-   insn.insn=INSN_CONFIG;   // configuration instruction
-   insn.n=1;                // number of operation (must be 1)
-   insn.data=&initialvalue; // initial value loaded into encoder
-                            // during configuration
-   insn.subdev=5;           // encoder subdevice
-   insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); // encoder_channel
-                                                        // to configure
-
-   comedi_do_insn(cf,&insn); // executing configuration
-*/
-
-#if !defined(TRUE)
-#define TRUE    (1)
-#endif
-
-#if !defined(FALSE)
-#define FALSE   (0)
-#endif
-
-#define S626_SIZE 0x0200
-#define DMABUF_SIZE			4096	/*  4k pages */
+#define S626_DMABUF_SIZE	4096	/* 4k pages */
 
 #define S626_ADC_CHANNELS       16
 #define S626_DAC_CHANNELS       4
 #define S626_ENCODER_CHANNELS   6
 #define S626_DIO_CHANNELS       48
-#define S626_DIO_BANKS		3	/*  Number of DIO groups. */
-#define S626_DIO_EXTCHANS	40	/*  Number of */
-					/*  extended-capability */
-					/*  DIO channels. */
+#define S626_DIO_BANKS		3	/* Number of DIO groups. */
+#define S626_DIO_EXTCHANS	40	/* Number of extended-capability
+					 * DIO channels. */
 
-#define NUM_TRIMDACS	12	/*  Number of valid TrimDAC channels. */
+#define S626_NUM_TRIMDACS	12	/* Number of valid TrimDAC channels. */
 
-/*  PCI bus interface types. */
-#define INTEL				1	/*  Intel bus type. */
-#define MOTOROLA			2	/*  Motorola bus type. */
+/* PCI bus interface types. */
+#define S626_INTEL		1	/* Intel bus type. */
+#define S626_MOTOROLA		2	/* Motorola bus type. */
 
-#define PLATFORM		INTEL	/*  *** SELECT PLATFORM TYPE *** */
+#define S626_PLATFORM		S626_INTEL /* *** SELECT PLATFORM TYPE *** */
 
-#define RANGE_5V                0x10	/*  +/-5V range */
-#define RANGE_10V               0x00	/*  +/-10V range */
+#define S626_RANGE_5V		0x10	/* +/-5V range */
+#define S626_RANGE_10V		0x00	/* +/-10V range */
 
-#define EOPL			0x80	/*  End of ADC poll list marker. */
-#define GSEL_BIPOLAR5V		0x00F0	/*  LP_GSEL setting for 5V bipolar range. */
-#define GSEL_BIPOLAR10V		0x00A0	/*  LP_GSEL setting for 10V bipolar range. */
+#define S626_EOPL		0x80	/* End of ADC poll list marker. */
+#define S626_GSEL_BIPOLAR5V	0x00F0	/* S626_LP_GSEL setting 5V bipolar. */
+#define S626_GSEL_BIPOLAR10V	0x00A0	/* S626_LP_GSEL setting 10V bipolar. */
 
-/*  Error codes that must be visible to this base class. */
-#define ERR_ILLEGAL_PARM	0x00010000	/*  Illegal function parameter value was specified. */
-#define ERR_I2C			0x00020000	/*  I2C error. */
-#define ERR_COUNTERSETUP	0x00200000	/*  Illegal setup specified for counter channel. */
-#define ERR_DEBI_TIMEOUT	0x00400000	/*  DEBI transfer timed out. */
+/* Error codes that must be visible to this base class. */
+#define S626_ERR_ILLEGAL_PARM	0x00010000	/* Illegal function parameter
+						 * value was specified. */
+#define S626_ERR_I2C		0x00020000	/* I2C error. */
+#define S626_ERR_COUNTERSETUP	0x00200000	/* Illegal setup specified for
+						 * counter channel. */
+#define S626_ERR_DEBI_TIMEOUT	0x00400000	/* DEBI transfer timed out. */
 
-/*  Organization (physical order) and size (in DWORDs) of logical DMA buffers contained by ANA_DMABUF. */
-#define ADC_DMABUF_DWORDS	40	/*  ADC DMA buffer must hold 16 samples, plus pre/post garbage samples. */
-#define DAC_WDMABUF_DWORDS	1	/*  DAC output DMA buffer holds a single sample. */
+/*
+ * Organization (physical order) and size (in DWORDs) of logical DMA buffers
+ * contained by ANA_DMABUF.
+ */
+#define S626_ADC_DMABUF_DWORDS	40	/* ADC DMA buffer must hold 16 samples,
+					 * plus pre/post garbage samples. */
+#define S626_DAC_WDMABUF_DWORDS	1	/* DAC output DMA buffer holds a single
+					 * sample. */
 
-/*  All remaining space in 4KB DMA buffer is available for the RPS1 program. */
+/* All remaining space in 4KB DMA buffer is available for the RPS1 program. */
 
-/*  Address offsets, in DWORDS, from base of DMA buffer. */
-#define DAC_WDMABUF_OS		ADC_DMABUF_DWORDS
+/* Address offsets, in DWORDS, from base of DMA buffer. */
+#define S626_DAC_WDMABUF_OS	S626_ADC_DMABUF_DWORDS
 
-/*  Interrupt enab bit in ISR and IER. */
-#define IRQ_GPIO3		0x00000040	/*  IRQ enable for GPIO3. */
-#define IRQ_RPS1                0x10000000
-#define ISR_AFOU		0x00000800
+/*  Interrupt enable bit in ISR and IER. */
+#define S626_IRQ_GPIO3		0x00000040	/* IRQ enable for GPIO3. */
+#define S626_IRQ_RPS1		0x10000000
+#define S626_ISR_AFOU		0x00000800
 /* Audio fifo under/overflow  detected. */
 
-#define IRQ_COINT1A             0x0400	/* conter 1A overflow interrupt mask */
-#define IRQ_COINT1B             0x0800	/* conter 1B overflow interrupt mask */
-#define IRQ_COINT2A             0x1000	/* conter 2A overflow interrupt mask */
-#define IRQ_COINT2B             0x2000	/* conter 2B overflow interrupt mask */
-#define IRQ_COINT3A             0x4000	/* conter 3A overflow interrupt mask */
-#define IRQ_COINT3B             0x8000	/* conter 3B overflow interrupt mask */
+#define S626_IRQ_COINT1A	0x0400	/* counter 1A overflow interrupt mask */
+#define S626_IRQ_COINT1B	0x0800	/* counter 1B overflow interrupt mask */
+#define S626_IRQ_COINT2A	0x1000	/* counter 2A overflow interrupt mask */
+#define S626_IRQ_COINT2B	0x2000	/* counter 2B overflow interrupt mask */
+#define S626_IRQ_COINT3A	0x4000	/* counter 3A overflow interrupt mask */
+#define S626_IRQ_COINT3B	0x8000	/* counter 3B overflow interrupt mask */
 
-/*  RPS command codes. */
-#define RPS_CLRSIGNAL		0x00000000	/*  CLEAR SIGNAL */
-#define RPS_SETSIGNAL		0x10000000	/*  SET SIGNAL */
-#define RPS_NOP			0x00000000	/*  NOP */
-#define RPS_PAUSE		0x20000000	/*  PAUSE */
-#define RPS_UPLOAD		0x40000000	/*  UPLOAD */
-#define RPS_JUMP		0x80000000	/*  JUMP */
-#define RPS_LDREG		0x90000100	/*  LDREG (1 uint32_t only) */
-#define RPS_STREG		0xA0000100	/*  STREG (1 uint32_t only) */
-#define RPS_STOP		0x50000000	/*  STOP */
-#define RPS_IRQ                 0x60000000	/*  IRQ */
+/* RPS command codes. */
+#define S626_RPS_CLRSIGNAL	0x00000000	/* CLEAR SIGNAL */
+#define S626_RPS_SETSIGNAL	0x10000000	/* SET SIGNAL */
+#define S626_RPS_NOP		0x00000000	/* NOP */
+#define S626_RPS_PAUSE		0x20000000	/* PAUSE */
+#define S626_RPS_UPLOAD		0x40000000	/* UPLOAD */
+#define S626_RPS_JUMP		0x80000000	/* JUMP */
+#define S626_RPS_LDREG		0x90000100	/* LDREG (1 uint32_t only) */
+#define S626_RPS_STREG		0xA0000100	/* STREG (1 uint32_t only) */
+#define S626_RPS_STOP		0x50000000	/* STOP */
+#define S626_RPS_IRQ		0x60000000	/* IRQ */
 
-#define RPS_LOGICAL_OR		0x08000000	/*  Logical OR conditionals. */
-#define RPS_INVERT		0x04000000	/*  Test for negated semaphores. */
-#define RPS_DEBI		0x00000002	/*  DEBI done */
+#define S626_RPS_LOGICAL_OR	0x08000000	/* Logical OR conditionals. */
+#define S626_RPS_INVERT		0x04000000	/* Test for negated
+						 * semaphores. */
+#define S626_RPS_DEBI		0x00000002	/* DEBI done */
 
-#define RPS_SIG0		0x00200000	/*  RPS semaphore 0 (used by ADC). */
-#define RPS_SIG1		0x00400000	/*  RPS semaphore 1 (used by DAC). */
-#define RPS_SIG2		0x00800000	/*  RPS semaphore 2 (not used). */
-#define RPS_GPIO2		0x00080000	/*  RPS GPIO2 */
-#define RPS_GPIO3		0x00100000	/*  RPS GPIO3 */
+#define S626_RPS_SIG0		0x00200000	/* RPS semaphore 0
+						 * (used by ADC). */
+#define S626_RPS_SIG1		0x00400000	/* RPS semaphore 1
+						 * (used by DAC). */
+#define S626_RPS_SIG2		0x00800000	/* RPS semaphore 2
+						 * (not used). */
+#define S626_RPS_GPIO2		0x00080000	/* RPS GPIO2 */
+#define S626_RPS_GPIO3		0x00100000	/* RPS GPIO3 */
 
-#define RPS_SIGADC		RPS_SIG0	/*  Trigger/status for ADC's RPS program. */
-#define RPS_SIGDAC		RPS_SIG1	/*  Trigger/status for DAC's RPS program. */
+#define S626_RPS_SIGADC		S626_RPS_SIG0	/* Trigger/status for
+						 * ADC's RPS program. */
+#define S626_RPS_SIGDAC		S626_RPS_SIG1	/* Trigger/status for
+						 * DAC's RPS program. */
 
-/*  RPS clock parameters. */
-#define RPSCLK_SCALAR		8	/*  This is apparent ratio of PCI/RPS clks (undocumented!!). */
-#define RPSCLK_PER_US		(33 / RPSCLK_SCALAR)	/*  Number of RPS clocks in one microsecond. */
+/* RPS clock parameters. */
+#define S626_RPSCLK_SCALAR	8	/* This is apparent ratio of
+					 * PCI/RPS clks (undocumented!!). */
+#define S626_RPSCLK_PER_US	(33 / S626_RPSCLK_SCALAR)
+					/* Number of RPS clocks in one
+					 * microsecond. */
 
-/*  Event counter source addresses. */
-#define SBA_RPS_A0		0x27	/*  Time of RPS0 busy, in PCI clocks. */
+/* Event counter source addresses. */
+#define S626_SBA_RPS_A0		0x27	/* Time of RPS0 busy, in PCI clocks. */
 
-/*  GPIO constants. */
-#define GPIO_BASE		0x10004000	/*  GPIO 0,2,3 = inputs, GPIO3 = IRQ; GPIO1 = out. */
-#define GPIO1_LO		0x00000000	/*  GPIO1 set to LOW. */
-#define GPIO1_HI		0x00001000	/*  GPIO1 set to HIGH. */
+/* GPIO constants. */
+#define S626_GPIO_BASE		0x10004000	/* GPIO 0,2,3 = inputs,
+						 * GPIO3 = IRQ; GPIO1 = out. */
+#define S626_GPIO1_LO		0x00000000	/* GPIO1 set to LOW. */
+#define S626_GPIO1_HI		0x00001000	/* GPIO1 set to HIGH. */
 
-/*  Primary Status Register (PSR) constants. */
-#define PSR_DEBI_E		0x00040000	/*  DEBI event flag. */
-#define PSR_DEBI_S		0x00080000	/*  DEBI status flag. */
-#define PSR_A2_IN		0x00008000	/*  Audio output DMA2 protection address reached. */
-#define PSR_AFOU		0x00000800	/*  Audio FIFO under/overflow detected. */
-#define PSR_GPIO2		0x00000020	/*  GPIO2 input pin: 0=AdcBusy, 1=AdcIdle. */
-#define PSR_EC0S		0x00000001	/*  Event counter 0 threshold reached. */
+/* Primary Status Register (PSR) constants. */
+#define S626_PSR_DEBI_E		0x00040000	/* DEBI event flag. */
+#define S626_PSR_DEBI_S		0x00080000	/* DEBI status flag. */
+#define S626_PSR_A2_IN		0x00008000	/* Audio output DMA2 protection
+						 * address reached. */
+#define S626_PSR_AFOU		0x00000800	/* Audio FIFO under/overflow
+						 * detected. */
+#define S626_PSR_GPIO2		0x00000020	/* GPIO2 input pin: 0=AdcBusy,
+						 * 1=AdcIdle. */
+#define S626_PSR_EC0S		0x00000001	/* Event counter 0 threshold
+						 * reached. */
 
-/*  Secondary Status Register (SSR) constants. */
-#define SSR_AF2_OUT		0x00000200	/*  Audio 2 output FIFO under/overflow detected. */
+/* Secondary Status Register (SSR) constants. */
+#define S626_SSR_AF2_OUT	0x00000200	/* Audio 2 output FIFO
+						 * under/overflow detected. */
 
-/*  Master Control Register 1 (MC1) constants. */
-#define MC1_SOFT_RESET		0x80000000	/*  Invoke 7146 soft reset. */
-#define MC1_SHUTDOWN		0x3FFF0000	/*  Shut down all MC1-controlled enables. */
+/* Master Control Register 1 (MC1) constants. */
+#define S626_MC1_SOFT_RESET	0x80000000	/* Invoke 7146 soft reset. */
+#define S626_MC1_SHUTDOWN	0x3FFF0000	/* Shut down all MC1-controlled
+						 * enables. */
 
-#define MC1_ERPS1		0x2000	/*  enab/disable RPS task 1. */
-#define MC1_ERPS0		0x1000	/*  enab/disable RPS task 0. */
-#define MC1_DEBI		0x0800	/*  enab/disable DEBI pins. */
-#define MC1_AUDIO		0x0200	/*  enab/disable audio port pins. */
-#define MC1_I2C			0x0100	/*  enab/disable I2C interface. */
-#define MC1_A2OUT		0x0008	/*  enab/disable transfer on A2 out. */
-#define MC1_A2IN		0x0004	/*  enab/disable transfer on A2 in. */
-#define MC1_A1IN		0x0001	/*  enab/disable transfer on A1 in. */
+#define S626_MC1_ERPS1		0x2000	/* Enab/disable RPS task 1. */
+#define S626_MC1_ERPS0		0x1000	/* Enab/disable RPS task 0. */
+#define S626_MC1_DEBI		0x0800	/* Enab/disable DEBI pins. */
+#define S626_MC1_AUDIO		0x0200	/* Enab/disable audio port pins. */
+#define S626_MC1_I2C		0x0100	/* Enab/disable I2C interface. */
+#define S626_MC1_A2OUT		0x0008	/* Enab/disable transfer on A2 out. */
+#define S626_MC1_A2IN		0x0004	/* Enab/disable transfer on A2 in. */
+#define S626_MC1_A1IN		0x0001	/* Enab/disable transfer on A1 in. */
 
-/*  Master Control Register 2 (MC2) constants. */
-#define MC2_UPLD_DEBIq		0x00020002	/*  Upload DEBI registers. */
-#define MC2_UPLD_IICq		0x00010001	/*  Upload I2C registers. */
-#define MC2_RPSSIG2_ONq		0x20002000	/*  Assert RPS_SIG2. */
-#define MC2_RPSSIG1_ONq		0x10001000	/*  Assert RPS_SIG1. */
-#define MC2_RPSSIG0_ONq		0x08000800	/*  Assert RPS_SIG0. */
-#define MC2_UPLD_DEBI_MASKq	0x00000002	/*  Upload DEBI mask. */
-#define MC2_UPLD_IIC_MASKq	0x00000001	/*  Upload I2C mask. */
-#define MC2_RPSSIG2_MASKq	0x00002000	/*  RPS_SIG2 bit mask. */
-#define MC2_RPSSIG1_MASKq	0x00001000	/*  RPS_SIG1 bit mask. */
-#define MC2_RPSSIG0_MASKq	0x00000800	/*  RPS_SIG0 bit mask. */
+/* Master Control Register 2 (MC2) constants. */
+#define S626_MC2_UPLD_DEBI	0x0002	/* Upload DEBI. */
+#define S626_MC2_UPLD_IIC	0x0001	/* Upload I2C. */
+#define S626_MC2_RPSSIG2	0x2000	/* RPS signal 2 (not used). */
+#define S626_MC2_RPSSIG1	0x1000	/* RPS signal 1 (DAC RPS busy). */
+#define S626_MC2_RPSSIG0	0x0800	/* RPS signal 0 (ADC RPS busy). */
 
-#define MC2_DELAYTRIG_4USq	MC2_RPSSIG1_ON
-#define MC2_DELAYBUSY_4USq	MC2_RPSSIG1_MASK
+#define S626_MC2_ADC_RPS	S626_MC2_RPSSIG0	/* ADC RPS busy. */
+#define S626_MC2_DAC_RPS	S626_MC2_RPSSIG1	/* DAC RPS busy. */
 
-#define	MC2_DELAYTRIG_6USq	MC2_RPSSIG2_ON
-#define MC2_DELAYBUSY_6USq	MC2_RPSSIG2_MASK
-
-#define MC2_UPLD_DEBI		0x0002	/*  Upload DEBI. */
-#define MC2_UPLD_IIC		0x0001	/*  Upload I2C. */
-#define MC2_RPSSIG2		0x2000	/*  RPS signal 2 (not used). */
-#define MC2_RPSSIG1		0x1000	/*  RPS signal 1 (DAC RPS busy). */
-#define MC2_RPSSIG0		0x0800	/*  RPS signal 0 (ADC RPS busy). */
-
-#define MC2_ADC_RPS		MC2_RPSSIG0	/*  ADC RPS busy. */
-#define MC2_DAC_RPS		MC2_RPSSIG1	/*  DAC RPS busy. */
-
-/* ***** oldies ***** */
-#define MC2_UPLD_DEBIQ		0x00020002	/*  Upload DEBI registers. */
-#define MC2_UPLD_IICQ		0x00010001	/*  Upload I2C registers. */
-
-/*  PCI BUS (SAA7146) REGISTER ADDRESS OFFSETS */
-#define P_PCI_BT_A		0x004C	/* Audio DMA burst/threshold control. */
-#define P_DEBICFG               0x007C	/* DEBI configuration. */
-#define P_DEBICMD               0x0080	/* DEBI command. */
-#define P_DEBIPAGE              0x0084	/* DEBI page. */
-#define P_DEBIAD                0x0088	/* DEBI target address. */
-#define P_I2CCTRL               0x008C	/* I2C control. */
-#define P_I2CSTAT               0x0090	/* I2C status. */
-#define P_BASEA2_IN		0x00AC	/* Audio input 2 base physical DMAbuf
+/* PCI BUS (SAA7146) REGISTER ADDRESS OFFSETS */
+#define S626_P_PCI_BT_A		0x004C	/* Audio DMA burst/threshold control. */
+#define S626_P_DEBICFG		0x007C	/* DEBI configuration. */
+#define S626_P_DEBICMD		0x0080	/* DEBI command. */
+#define S626_P_DEBIPAGE		0x0084	/* DEBI page. */
+#define S626_P_DEBIAD		0x0088	/* DEBI target address. */
+#define S626_P_I2CCTRL		0x008C	/* I2C control. */
+#define S626_P_I2CSTAT		0x0090	/* I2C status. */
+#define S626_P_BASEA2_IN	0x00AC	/* Audio input 2 base physical DMAbuf
 					 * address. */
-#define P_PROTA2_IN		0x00B0	/* Audio input 2 physical DMAbuf
+#define S626_P_PROTA2_IN	0x00B0	/* Audio input 2 physical DMAbuf
 					 * protection address. */
-#define P_PAGEA2_IN		0x00B4	/* Audio input 2 paging attributes. */
-#define P_BASEA2_OUT		0x00B8	/* Audio output 2 base physical DMAbuf
+#define S626_P_PAGEA2_IN	0x00B4	/* Audio input 2 paging attributes. */
+#define S626_P_BASEA2_OUT	0x00B8	/* Audio output 2 base physical DMAbuf
 					 * address. */
-#define P_PROTA2_OUT		0x00BC	/* Audio output 2 physical DMAbuf
+#define S626_P_PROTA2_OUT	0x00BC	/* Audio output 2 physical DMAbuf
 					 * protection address. */
-#define P_PAGEA2_OUT		0x00C0	/* Audio output 2 paging attributes. */
-#define P_RPSPAGE0              0x00C4	/* RPS0 page. */
-#define P_RPSPAGE1              0x00C8	/* RPS1 page. */
-#define P_RPS0_TOUT		0x00D4	/* RPS0 time-out. */
-#define P_RPS1_TOUT		0x00D8	/* RPS1 time-out. */
-#define P_IER                   0x00DC	/* Interrupt enable. */
-#define P_GPIO                  0x00E0	/* General-purpose I/O. */
-#define P_EC1SSR		0x00E4	/* Event counter set 1 source select. */
-#define P_ECT1R			0x00EC	/* Event counter threshold set 1. */
-#define P_ACON1                 0x00F4	/* Audio control 1. */
-#define P_ACON2                 0x00F8	/* Audio control 2. */
-#define P_MC1                   0x00FC	/* Master control 1. */
-#define P_MC2                   0x0100	/* Master control 2. */
-#define P_RPSADDR0              0x0104	/* RPS0 instruction pointer. */
-#define P_RPSADDR1              0x0108	/* RPS1 instruction pointer. */
-#define P_ISR                   0x010C	/* Interrupt status. */
-#define P_PSR                   0x0110	/* Primary status. */
-#define P_SSR                   0x0114	/* Secondary status. */
-#define P_EC1R			0x0118	/* Event counter set 1. */
-#define P_ADP4			0x0138	/* Logical audio DMA pointer of audio
+#define S626_P_PAGEA2_OUT	0x00C0	/* Audio output 2 paging attributes. */
+#define S626_P_RPSPAGE0		0x00C4	/* RPS0 page. */
+#define S626_P_RPSPAGE1		0x00C8	/* RPS1 page. */
+#define S626_P_RPS0_TOUT	0x00D4	/* RPS0 time-out. */
+#define S626_P_RPS1_TOUT	0x00D8	/* RPS1 time-out. */
+#define S626_P_IER		0x00DC	/* Interrupt enable. */
+#define S626_P_GPIO		0x00E0	/* General-purpose I/O. */
+#define S626_P_EC1SSR		0x00E4	/* Event counter set 1 source select. */
+#define S626_P_ECT1R		0x00EC	/* Event counter threshold set 1. */
+#define S626_P_ACON1		0x00F4	/* Audio control 1. */
+#define S626_P_ACON2		0x00F8	/* Audio control 2. */
+#define S626_P_MC1		0x00FC	/* Master control 1. */
+#define S626_P_MC2		0x0100	/* Master control 2. */
+#define S626_P_RPSADDR0		0x0104	/* RPS0 instruction pointer. */
+#define S626_P_RPSADDR1		0x0108	/* RPS1 instruction pointer. */
+#define S626_P_ISR		0x010C	/* Interrupt status. */
+#define S626_P_PSR		0x0110	/* Primary status. */
+#define S626_P_SSR		0x0114	/* Secondary status. */
+#define S626_P_EC1R		0x0118	/* Event counter set 1. */
+#define S626_P_ADP4		0x0138	/* Logical audio DMA pointer of audio
 					 * input FIFO A2_IN. */
-#define P_FB_BUFFER1            0x0144	/* Audio feedback buffer 1. */
-#define P_FB_BUFFER2            0x0148	/* Audio feedback buffer 2. */
-#define P_TSL1                  0x0180	/* Audio time slot list 1. */
-#define P_TSL2                  0x01C0	/* Audio time slot list 2. */
+#define S626_P_FB_BUFFER1	0x0144	/* Audio feedback buffer 1. */
+#define S626_P_FB_BUFFER2	0x0148	/* Audio feedback buffer 2. */
+#define S626_P_TSL1		0x0180	/* Audio time slot list 1. */
+#define S626_P_TSL2		0x01C0	/* Audio time slot list 2. */
 
-/*  LOCAL BUS (GATE ARRAY) REGISTER ADDRESS OFFSETS */
-/*  Analog I/O registers: */
-#define LP_DACPOL		0x0082	/*   Write DAC polarity. */
-#define LP_GSEL			0x0084	/*   Write ADC gain. */
-#define LP_ISEL			0x0086	/*   Write ADC channel select. */
+/* LOCAL BUS (GATE ARRAY) REGISTER ADDRESS OFFSETS */
+/* Analog I/O registers: */
+#define S626_LP_DACPOL		0x0082	/* Write DAC polarity. */
+#define S626_LP_GSEL		0x0084	/* Write ADC gain. */
+#define S626_LP_ISEL		0x0086	/* Write ADC channel select. */
 
 /* Digital I/O registers */
-#define LP_RDDIN(x)		(0x0040 + (x) * 0x10)	/* R: digital input */
-#define LP_WRINTSEL(x)		(0x0042 + (x) * 0x10)	/* W: int enable */
-#define LP_WREDGSEL(x)		(0x0044 + (x) * 0x10)	/* W: edge selection */
-#define LP_WRCAPSEL(x)		(0x0046 + (x) * 0x10)	/* W: capture enable */
-#define LP_RDCAPFLG(x)		(0x0048 + (x) * 0x10)	/* R: edges captured */
-#define LP_WRDOUT(x)		(0x0048 + (x) * 0x10)	/* W: digital output */
-#define LP_RDINTSEL(x)		(0x004a + (x) * 0x10)	/* R: int enable */
-#define LP_RDEDGSEL(x)		(0x004c + (x) * 0x10)	/* R: edge selection */
-#define LP_RDCAPSEL(x)		(0x004e + (x) * 0x10)	/* R: capture enable */
+#define S626_LP_RDDIN(x)	(0x0040 + (x) * 0x10)	/* R: digital input */
+#define S626_LP_WRINTSEL(x)	(0x0042 + (x) * 0x10)	/* W: int enable */
+#define S626_LP_WREDGSEL(x)	(0x0044 + (x) * 0x10)	/* W: edge selection */
+#define S626_LP_WRCAPSEL(x)	(0x0046 + (x) * 0x10)	/* W: capture enable */
+#define S626_LP_RDCAPFLG(x)	(0x0048 + (x) * 0x10)	/* R: edges captured */
+#define S626_LP_WRDOUT(x)	(0x0048 + (x) * 0x10)	/* W: digital output */
+#define S626_LP_RDINTSEL(x)	(0x004a + (x) * 0x10)	/* R: int enable */
+#define S626_LP_RDEDGSEL(x)	(0x004c + (x) * 0x10)	/* R: edge selection */
+#define S626_LP_RDCAPSEL(x)	(0x004e + (x) * 0x10)	/* R: capture enable */
 
-/*  Counter Registers (read/write): */
-#define LP_CR0A			0x0000	/*   0A setup register. */
-#define LP_CR0B			0x0002	/*   0B setup register. */
-#define LP_CR1A			0x0004	/*   1A setup register. */
-#define LP_CR1B			0x0006	/*   1B setup register. */
-#define LP_CR2A			0x0008	/*   2A setup register. */
-#define LP_CR2B			0x000A	/*   2B setup register. */
+/* Counter Registers (read/write): */
+#define S626_LP_CR0A		0x0000	/* 0A setup register. */
+#define S626_LP_CR0B		0x0002	/* 0B setup register. */
+#define S626_LP_CR1A		0x0004	/* 1A setup register. */
+#define S626_LP_CR1B		0x0006	/* 1B setup register. */
+#define S626_LP_CR2A		0x0008	/* 2A setup register. */
+#define S626_LP_CR2B		0x000A	/* 2B setup register. */
 
-/*  Counter PreLoad (write) and Latch (read) Registers: */
-#define	LP_CNTR0ALSW		0x000C	/*   0A lsw. */
-#define	LP_CNTR0AMSW		0x000E	/*   0A msw. */
-#define	LP_CNTR0BLSW		0x0010	/*   0B lsw. */
-#define	LP_CNTR0BMSW		0x0012	/*   0B msw. */
-#define	LP_CNTR1ALSW		0x0014	/*   1A lsw. */
-#define	LP_CNTR1AMSW		0x0016	/*   1A msw. */
-#define	LP_CNTR1BLSW		0x0018	/*   1B lsw. */
-#define	LP_CNTR1BMSW		0x001A	/*   1B msw. */
-#define	LP_CNTR2ALSW		0x001C	/*   2A lsw. */
-#define	LP_CNTR2AMSW		0x001E	/*   2A msw. */
-#define	LP_CNTR2BLSW		0x0020	/*   2B lsw. */
-#define	LP_CNTR2BMSW		0x0022	/*   2B msw. */
+/* Counter PreLoad (write) and Latch (read) Registers: */
+#define	S626_LP_CNTR0ALSW	0x000C	/* 0A lsw. */
+#define	S626_LP_CNTR0AMSW	0x000E	/* 0A msw. */
+#define	S626_LP_CNTR0BLSW	0x0010	/* 0B lsw. */
+#define	S626_LP_CNTR0BMSW	0x0012	/* 0B msw. */
+#define	S626_LP_CNTR1ALSW	0x0014	/* 1A lsw. */
+#define	S626_LP_CNTR1AMSW	0x0016	/* 1A msw. */
+#define	S626_LP_CNTR1BLSW	0x0018	/* 1B lsw. */
+#define	S626_LP_CNTR1BMSW	0x001A	/* 1B msw. */
+#define	S626_LP_CNTR2ALSW	0x001C	/* 2A lsw. */
+#define	S626_LP_CNTR2AMSW	0x001E	/* 2A msw. */
+#define	S626_LP_CNTR2BLSW	0x0020	/* 2B lsw. */
+#define	S626_LP_CNTR2BMSW	0x0022	/* 2B msw. */
 
-/*  Miscellaneous Registers (read/write): */
-#define LP_MISC1		0x0088	/*   Read/write Misc1. */
-#define LP_WRMISC2		0x0090	/*   Write Misc2. */
-#define LP_RDMISC2		0x0082	/*   Read Misc2. */
+/* Miscellaneous Registers (read/write): */
+#define S626_LP_MISC1		0x0088	/* Read/write Misc1. */
+#define S626_LP_WRMISC2		0x0090	/* Write Misc2. */
+#define S626_LP_RDMISC2		0x0082	/* Read Misc2. */
 
-/*  Bit masks for MISC1 register that are the same for reads and writes. */
-#define MISC1_WENABLE		0x8000	/* enab writes to MISC2 (except Clear
+/* Bit masks for MISC1 register that are the same for reads and writes. */
+#define S626_MISC1_WENABLE	0x8000	/* enab writes to MISC2 (except Clear
 					 * Watchdog bit). */
-#define MISC1_WDISABLE		0x0000	/* Disable writes to MISC2. */
-#define MISC1_EDCAP		0x1000	/* enab edge capture on DIO chans
-					 * specified by  LP_WRCAPSELx. */
-#define MISC1_NOEDCAP		0x0000	/* Disable edge capture on specified
+#define S626_MISC1_WDISABLE	0x0000	/* Disable writes to MISC2. */
+#define S626_MISC1_EDCAP	0x1000	/* Enable edge capture on DIO chans
+					 * specified by S626_LP_WRCAPSELx. */
+#define S626_MISC1_NOEDCAP	0x0000	/* Disable edge capture on specified
 					 * DIO chans. */
 
-/*  Bit masks for MISC1 register reads. */
-#define RDMISC1_WDTIMEOUT	0x4000	/*  Watchdog timer timed out. */
+/* Bit masks for MISC1 register reads. */
+#define S626_RDMISC1_WDTIMEOUT	0x4000	/* Watchdog timer timed out. */
 
-/*  Bit masks for MISC2 register writes. */
-#define WRMISC2_WDCLEAR		0x8000	/*  Reset watchdog timer to zero. */
-#define WRMISC2_CHARGE_ENABLE	0x4000	/*  enab battery trickle charging. */
+/* Bit masks for MISC2 register writes. */
+#define S626_WRMISC2_WDCLEAR	0x8000	/* Reset watchdog timer to zero. */
+#define S626_WRMISC2_CHARGE_ENABLE 0x4000 /* Enable battery trickle charging. */
 
-/*  Bit masks for MISC2 register that are the same for reads and writes. */
-#define MISC2_BATT_ENABLE	0x0008	/*  Backup battery enable. */
-#define MISC2_WDENABLE		0x0004	/*  Watchdog timer enable. */
-#define MISC2_WDPERIOD_MASK	0x0003	/*  Watchdog interval */
-						/*  select mask. */
+/* Bit masks for MISC2 register that are the same for reads and writes. */
+#define S626_MISC2_BATT_ENABLE	0x0008	/* Backup battery enable. */
+#define S626_MISC2_WDENABLE	0x0004	/* Watchdog timer enable. */
+#define S626_MISC2_WDPERIOD_MASK 0x0003	/* Watchdog interval select mask. */
 
-/*  Bit masks for ACON1 register. */
-#define A2_RUN			0x40000000	/*  Run A2 based on TSL2. */
-#define A1_RUN			0x20000000	/*  Run A1 based on TSL1. */
-#define A1_SWAP			0x00200000	/*  Use big-endian for A1. */
-#define A2_SWAP			0x00100000	/*  Use big-endian for A2. */
-#define WS_MODES		0x00019999	/*  WS0 = TSL1 trigger */
-						/*  input, WS1-WS4 = */
-						/*  CS* outputs. */
+/* Bit masks for ACON1 register. */
+#define S626_A2_RUN		0x40000000	/* Run A2 based on TSL2. */
+#define S626_A1_RUN		0x20000000	/* Run A1 based on TSL1. */
+#define S626_A1_SWAP		0x00200000	/* Use big-endian for A1. */
+#define S626_A2_SWAP		0x00100000	/* Use big-endian for A2. */
+#define S626_WS_MODES		0x00019999	/* WS0 = TSL1 trigger input,
+						 * WS1-WS4 = CS* outputs. */
 
-#if PLATFORM == INTEL		/* Base ACON1 config: always run A1 based
-				 * on TSL1. */
-#define ACON1_BASE		(WS_MODES | A1_RUN)
-#elif PLATFORM == MOTOROLA
-#define ACON1_BASE		(WS_MODES | A1_RUN | A1_SWAP | A2_SWAP)
+#if S626_PLATFORM == S626_INTEL		/* Base ACON1 config: always run
+					 * A1 based on TSL1. */
+#define S626_ACON1_BASE		(S626_WS_MODES | S626_A1_RUN)
+#elif S626_PLATFORM == S626_MOTOROLA
+#define S626_ACON1_BASE		\
+	(S626_WS_MODES | S626_A1_RUN | S626_A1_SWAP | S626_A2_SWAP)
 #endif
 
-#define ACON1_ADCSTART		ACON1_BASE	/* Start ADC: run A1
-						 *  based on TSL1. */
-#define ACON1_DACSTART		(ACON1_BASE | A2_RUN)
+#define S626_ACON1_ADCSTART	S626_ACON1_BASE	/* Start ADC: run A1
+						 * based on TSL1. */
+#define S626_ACON1_DACSTART	(S626_ACON1_BASE | S626_A2_RUN)
 /* Start transmit to DAC: run A2 based on TSL2. */
-#define ACON1_DACSTOP		ACON1_BASE	/*  Halt A2. */
+#define S626_ACON1_DACSTOP	S626_ACON1_BASE	/* Halt A2. */
 
-/*  Bit masks for ACON2 register. */
-#define A1_CLKSRC_BCLK1		0x00000000	/*  A1 bit rate = BCLK1 (ADC). */
-#define A2_CLKSRC_X1		0x00800000	/*  A2 bit rate = ACLK/1 (DACs). */
-#define A2_CLKSRC_X2		0x00C00000	/*  A2 bit rate = ACLK/2 (DACs). */
-#define A2_CLKSRC_X4		0x01400000	/*  A2 bit rate = ACLK/4 (DACs). */
-#define INVERT_BCLK2		0x00100000	/*  Invert BCLK2 (DACs). */
-#define BCLK2_OE		0x00040000	/*  enab BCLK2 (DACs). */
-#define ACON2_XORMASK		0x000C0000	/*  XOR mask for ACON2 */
-						/*  active-low bits. */
+/* Bit masks for ACON2 register. */
+#define S626_A1_CLKSRC_BCLK1	0x00000000	/* A1 bit rate = BCLK1 (ADC). */
+#define S626_A2_CLKSRC_X1	0x00800000	/* A2 bit rate = ACLK/1
+						 * (DACs). */
+#define S626_A2_CLKSRC_X2	0x00C00000	/* A2 bit rate = ACLK/2
+						 * (DACs). */
+#define S626_A2_CLKSRC_X4	0x01400000	/* A2 bit rate = ACLK/4
+						 * (DACs). */
+#define S626_INVERT_BCLK2	0x00100000	/* Invert BCLK2 (DACs). */
+#define S626_BCLK2_OE		0x00040000	/* Enable BCLK2 (DACs). */
+#define S626_ACON2_XORMASK	0x000C0000	/* XOR mask for ACON2
+						 * active-low bits. */
 
-#define ACON2_INIT		(ACON2_XORMASK ^ (A1_CLKSRC_BCLK1 | A2_CLKSRC_X2 | INVERT_BCLK2 | BCLK2_OE))
+#define S626_ACON2_INIT		(S626_ACON2_XORMASK ^ \
+				 (S626_A1_CLKSRC_BCLK1 | S626_A2_CLKSRC_X2 | \
+				  S626_INVERT_BCLK2 | S626_BCLK2_OE))
 
-/*  Bit masks for timeslot records. */
-#define WS1		     	0x40000000	/*  WS output to assert. */
-#define WS2		     	0x20000000
-#define WS3		     	0x10000000
-#define WS4		     	0x08000000
-#define RSD1			0x01000000	/* Shift A1 data in on SD1. */
-#define SDW_A1			0x00800000	/* Store rcv'd char at next
-						 * char slot of DWORD1 buffer. */
-#define SIB_A1			0x00400000	/* Store rcv'd char at next
+/* Bit masks for timeslot records. */
+#define S626_WS1		0x40000000	/* WS output to assert. */
+#define S626_WS2		0x20000000
+#define S626_WS3		0x10000000
+#define S626_WS4		0x08000000
+#define S626_RSD1		0x01000000	/* Shift A1 data in on SD1. */
+#define S626_SDW_A1		0x00800000	/* Store rcv'd char at next char
+						 * slot of DWORD1 buffer. */
+#define S626_SIB_A1		0x00400000	/* Store rcv'd char at next
 						 * char slot of FB1 buffer. */
-#define SF_A1			0x00200000	/* Write unsigned long
+#define S626_SF_A1		0x00200000	/* Write unsigned long
 						 * buffer to input FIFO. */
 
 /* Select parallel-to-serial converter's data source: */
-#define XFIFO_0			0x00000000	/*    Data fifo byte 0. */
-#define XFIFO_1			0x00000010	/*    Data fifo byte 1. */
-#define XFIFO_2			0x00000020	/*    Data fifo byte 2. */
-#define XFIFO_3			0x00000030	/*    Data fifo byte 3. */
-#define XFB0			0x00000040	/*    FB_BUFFER byte 0. */
-#define XFB1			0x00000050	/*    FB_BUFFER byte 1. */
-#define XFB2			0x00000060	/*    FB_BUFFER byte 2. */
-#define XFB3			0x00000070	/*    FB_BUFFER byte 3. */
-#define SIB_A2			0x00000200	/* Store next dword from A2's
-						 * input shifter to FB2 buffer. */
-#define SF_A2			0x00000100	/* Store next dword from A2's
+#define S626_XFIFO_0		0x00000000	/* Data fifo byte 0. */
+#define S626_XFIFO_1		0x00000010	/* Data fifo byte 1. */
+#define S626_XFIFO_2		0x00000020	/* Data fifo byte 2. */
+#define S626_XFIFO_3		0x00000030	/* Data fifo byte 3. */
+#define S626_XFB0		0x00000040	/* FB_BUFFER byte 0. */
+#define S626_XFB1		0x00000050	/* FB_BUFFER byte 1. */
+#define S626_XFB2		0x00000060	/* FB_BUFFER byte 2. */
+#define S626_XFB3		0x00000070	/* FB_BUFFER byte 3. */
+#define S626_SIB_A2		0x00000200	/* Store next dword from A2's
+						 * input shifter to FB2
+						 * buffer. */
+#define S626_SF_A2		0x00000100	/* Store next dword from A2's
 						 * input shifter to its input
 						 * fifo. */
-#define LF_A2			0x00000080	/* Load next dword from A2's
+#define S626_LF_A2		0x00000080	/* Load next dword from A2's
 						 * output fifo into its
 						 * output dword buffer. */
-#define XSD2			0x00000008	/*  Shift data out on SD2. */
-#define RSD3			0x00001800	/*  Shift data in on SD3. */
-#define RSD2			0x00001000	/*  Shift data in on SD2. */
-#define LOW_A2			0x00000002	/*  Drive last SD low */
-						/*  for 7 clks, then */
-						/*  tri-state. */
-#define EOS		     	0x00000001	/*  End of superframe. */
+#define S626_XSD2		0x00000008	/* Shift data out on SD2. */
+#define S626_RSD3		0x00001800	/* Shift data in on SD3. */
+#define S626_RSD2		0x00001000	/* Shift data in on SD2. */
+#define S626_LOW_A2		0x00000002	/* Drive last SD low for 7 clks,
+						 * then tri-state. */
+#define S626_EOS		0x00000001	/* End of superframe. */
 
-/*  I2C configuration constants. */
-#define I2C_CLKSEL		0x0400
-/* I2C bit rate = PCIclk/480 = 68.75 KHz. */
+/* I2C configuration constants. */
+#define S626_I2C_CLKSEL		0x0400		/* I2C bit rate =
+						 * PCIclk/480 = 68.75 KHz. */
+#define S626_I2C_BITRATE	68.75		/* I2C bus data bit rate
+						 * (determined by
+						 * S626_I2C_CLKSEL) in KHz. */
+#define S626_I2C_WRTIME		15.0		/* Worst case time, in msec,
+						 * for EEPROM internal write
+						 * op. */
 
-#define I2C_BITRATE		68.75
-/* I2C bus data bit rate (determined by I2C_CLKSEL) in KHz. */
+/* I2C manifest constants. */
 
-#define I2C_WRTIME		15.0
-/* Worst case time, in msec, for EEPROM internal write op. */
+/* Max retries to wait for EEPROM write. */
+#define S626_I2C_RETRIES	(S626_I2C_WRTIME * S626_I2C_BITRATE / 9.0)
+#define S626_I2C_ERR		0x0002	/* I2C control/status flag ERROR. */
+#define S626_I2C_BUSY		0x0001	/* I2C control/status flag BUSY. */
+#define S626_I2C_ABORT		0x0080	/* I2C status flag ABORT. */
+#define S626_I2C_ATTRSTART	0x3	/* I2C attribute START. */
+#define S626_I2C_ATTRCONT	0x2	/* I2C attribute CONT. */
+#define S626_I2C_ATTRSTOP	0x1	/* I2C attribute STOP. */
+#define S626_I2C_ATTRNOP	0x0	/* I2C attribute NOP. */
 
-/*  I2C manifest constants. */
+/* Code macros used for constructing I2C command bytes. */
+#define S626_I2C_B2(ATTR, VAL)	(((ATTR) << 6) | ((VAL) << 24))
+#define S626_I2C_B1(ATTR, VAL)	(((ATTR) << 4) | ((VAL) << 16))
+#define S626_I2C_B0(ATTR, VAL)	(((ATTR) << 2) | ((VAL) <<  8))
 
-/*  Max retries to wait for EEPROM write. */
-#define I2C_RETRIES		(I2C_WRTIME * I2C_BITRATE / 9.0)
-#define I2C_ERR			0x0002	/*  I2C control/status */
-						/*  flag ERROR. */
-#define I2C_BUSY		0x0001	/*  I2C control/status */
-						/*  flag BUSY. */
-#define I2C_ABORT		0x0080	/*  I2C status flag ABORT. */
-#define I2C_ATTRSTART		0x3	/*  I2C attribute START. */
-#define I2C_ATTRCONT		0x2	/*  I2C attribute CONT. */
-#define I2C_ATTRSTOP		0x1	/*  I2C attribute STOP. */
-#define I2C_ATTRNOP		0x0	/*  I2C attribute NOP. */
+/* DEBI command constants. */
+#define S626_DEBI_CMD_SIZE16	(2 << 17)	/* Transfer size is always
+						 * 2 bytes. */
+#define S626_DEBI_CMD_READ	0x00010000	/* Read operation. */
+#define S626_DEBI_CMD_WRITE	0x00000000	/* Write operation. */
 
-/*  I2C read command  | EEPROM address. */
-#define I2CR			(devpriv->I2CAdrs | 1)
+/* Read immediate 2 bytes. */
+#define S626_DEBI_CMD_RDWORD	(S626_DEBI_CMD_READ | S626_DEBI_CMD_SIZE16)
 
-/*  I2C write command | EEPROM address. */
-#define I2CW			(devpriv->I2CAdrs)
+/* Write immediate 2 bytes. */
+#define S626_DEBI_CMD_WRWORD	(S626_DEBI_CMD_WRITE | S626_DEBI_CMD_SIZE16)
 
-/*  Code macros used for constructing I2C command bytes. */
-#define I2C_B2(ATTR, VAL)	(((ATTR) << 6) | ((VAL) << 24))
-#define I2C_B1(ATTR, VAL)	(((ATTR) << 4) | ((VAL) << 16))
-#define I2C_B0(ATTR, VAL)	(((ATTR) << 2) | ((VAL) <<  8))
+/* DEBI configuration constants. */
+#define S626_DEBI_CFG_XIRQ_EN	0x80000000	/* Enable external interrupt
+						 * on GPIO3. */
+#define S626_DEBI_CFG_XRESUME	0x40000000	/* Resume block */
+						/* Transfer when XIRQ
+						 * deasserted. */
+#define S626_DEBI_CFG_TOQ	0x03C00000	/* Timeout (15 PCI cycles). */
+#define S626_DEBI_CFG_FAST	0x10000000	/* Fast mode enable. */
 
-/* oldest */
-#define P_DEBICFGq              0x007C	/*  DEBI configuration. */
-#define P_DEBICMDq              0x0080	/*  DEBI command. */
-#define P_DEBIPAGEq             0x0084	/*  DEBI page. */
-#define P_DEBIADq               0x0088	/*  DEBI target address. */
+/* 4-bit field that specifies DEBI timeout value in PCI clock cycles: */
+#define S626_DEBI_CFG_TOUT_BIT	22	/* Finish DEBI cycle after this many
+					 * clocks. */
 
-#define DEBI_CFG_TOQ		0x03C00000	/*  timeout (15 PCI cycles) */
-#define DEBI_CFG_FASTQ		0x10000000	/*  fast mode enable */
-#define DEBI_CFG_16Q		0x00080000	/*  16-bit access enable */
-#define DEBI_CFG_INCQ		0x00040000	/*  enable address increment */
-#define DEBI_CFG_TIMEROFFQ	0x00010000	/*  disable timer */
-#define DEBI_CMD_RDQ		0x00050000	/*  read immediate 2 bytes */
-#define DEBI_CMD_WRQ		0x00040000	/*  write immediate 2 bytes */
-#define DEBI_PAGE_DISABLEQ	0x00000000	/*  paging disable */
+/* 2-bit field that specifies Endian byte lane steering: */
+#define S626_DEBI_CFG_SWAP_NONE	0x00000000	/* Straight - don't swap any
+						 * bytes (Intel). */
+#define S626_DEBI_CFG_SWAP_2	0x00100000	/* 2-byte swap (Motorola). */
+#define S626_DEBI_CFG_SWAP_4	0x00200000	/* 4-byte swap. */
+#define S626_DEBI_CFG_SLAVE16	0x00080000	/* Slave is able to serve
+						 * 16-bit cycles. */
+#define S626_DEBI_CFG_INC	0x00040000	/* Enable address increment
+						 * for block transfers. */
+#define S626_DEBI_CFG_INTEL	0x00020000	/* Intel style local bus. */
+#define S626_DEBI_CFG_TIMEROFF	0x00010000	/* Disable timer. */
 
-/*  DEBI command constants. */
-#define DEBI_CMD_SIZE16		(2 << 17)	/*  Transfer size is */
-						/*  always 2 bytes. */
-#define DEBI_CMD_READ		0x00010000	/*  Read operation. */
-#define DEBI_CMD_WRITE		0x00000000	/*  Write operation. */
+#if S626_PLATFORM == S626_INTEL
 
-/*  Read immediate 2 bytes. */
-#define DEBI_CMD_RDWORD		(DEBI_CMD_READ  | DEBI_CMD_SIZE16)
+#define S626_DEBI_TOUT		7	/* Wait 7 PCI clocks (212 ns) before
+					 * polling RDY. */
 
-/*  Write immediate 2 bytes. */
-#define DEBI_CMD_WRWORD		(DEBI_CMD_WRITE | DEBI_CMD_SIZE16)
+/* Intel byte lane steering (pass through all byte lanes). */
+#define S626_DEBI_SWAP		S626_DEBI_CFG_SWAP_NONE
 
-/*  DEBI configuration constants. */
-#define DEBI_CFG_XIRQ_EN	0x80000000	/*  enab external */
-						/*  interrupt on GPIO3. */
-#define DEBI_CFG_XRESUME	0x40000000	/*  Resume block */
-						/*  transfer when XIRQ */
-						/*  deasserted. */
-#define DEBI_CFG_FAST		0x10000000	/*  Fast mode enable. */
+#elif S626_PLATFORM == S626_MOTOROLA
 
-/*  4-bit field that specifies DEBI timeout value in PCI clock cycles: */
-#define DEBI_CFG_TOUT_BIT	22	/*    Finish DEBI cycle after */
-					/*    this many clocks. */
+#define S626_DEBI_TOUT		15	/* Wait 15 PCI clocks (454 ns) maximum
+					 * before timing out. */
 
-/*  2-bit field that specifies Endian byte lane steering: */
-#define DEBI_CFG_SWAP_NONE	0x00000000	/*    Straight - don't */
-						/*    swap any bytes */
-						/*    (Intel). */
-#define DEBI_CFG_SWAP_2		0x00100000	/*    2-byte swap (Motorola). */
-#define DEBI_CFG_SWAP_4		0x00200000	/*    4-byte swap. */
-#define DEBI_CFG_16		0x00080000	/*  Slave is able to */
-						/*  serve 16-bit */
-						/*  cycles. */
-
-#define DEBI_CFG_SLAVE16	0x00080000	/*  Slave is able to */
-						/*  serve 16-bit */
-						/*  cycles. */
-#define DEBI_CFG_INC		0x00040000	/*  enab address */
-						/*  increment for block */
-						/*  transfers. */
-#define DEBI_CFG_INTEL		0x00020000	/*  Intel style local bus. */
-#define DEBI_CFG_TIMEROFF	0x00010000	/*  Disable timer. */
-
-#if PLATFORM == INTEL
-
-#define DEBI_TOUT		7	/*  Wait 7 PCI clocks */
-						/*  (212 ns) before */
-						/*  polling RDY. */
-
-/*  Intel byte lane steering (pass through all byte lanes). */
-#define DEBI_SWAP		DEBI_CFG_SWAP_NONE
-
-#elif PLATFORM == MOTOROLA
-
-#define DEBI_TOUT		15	/*  Wait 15 PCI clocks (454 ns) */
-					/*  maximum before timing out. */
-#define DEBI_SWAP		DEBI_CFG_SWAP_2	/*  Motorola byte lane steering. */
+/* Motorola byte lane steering. */
+#define S626_DEBI_SWAP		S626_DEBI_CFG_SWAP_2
 
 #endif
 
-/*  DEBI page table constants. */
-#define DEBI_PAGE_DISABLE	0x00000000	/*  Paging disable. */
+/* DEBI page table constants. */
+#define S626_DEBI_PAGE_DISABLE	0x00000000	/* Paging disable. */
 
-/* ******* EXTRA FROM OTHER SANSORAY  * .h  ******* */
+/* ******* EXTRA FROM OTHER SENSORAY  * .h  ******* */
 
-/*  LoadSrc values: */
-#define LOADSRC_INDX		0	/*  Preload core in response to */
-					/*  Index. */
-#define LOADSRC_OVER		1	/*  Preload core in response to */
-					/*  Overflow. */
-#define LOADSRCB_OVERA		2	/*  Preload B core in response */
-					/*  to A Overflow. */
-#define LOADSRC_NONE		3	/*  Never preload core. */
+/* LoadSrc values: */
+#define S626_LOADSRC_INDX	0	/* Preload core in response to Index. */
+#define S626_LOADSRC_OVER	1	/* Preload core in response to
+					 * Overflow. */
+#define S626_LOADSRCB_OVERA	2	/* Preload B core in response to
+					 * A Overflow. */
+#define S626_LOADSRC_NONE	3	/* Never preload core. */
 
-/*  IntSrc values: */
-#define INTSRC_NONE 		0	/*  Interrupts disabled. */
-#define INTSRC_OVER 		1	/*  Interrupt on Overflow. */
-#define INTSRC_INDX 		2	/*  Interrupt on Index. */
-#define INTSRC_BOTH 		3	/*  Interrupt on Index or Overflow. */
+/* IntSrc values: */
+#define S626_INTSRC_NONE	0	/* Interrupts disabled. */
+#define S626_INTSRC_OVER	1	/* Interrupt on Overflow. */
+#define S626_INTSRC_INDX	2	/* Interrupt on Index. */
+#define S626_INTSRC_BOTH	3	/* Interrupt on Index or Overflow. */
 
-/*  LatchSrc values: */
-#define LATCHSRC_AB_READ	0	/*  Latch on read. */
-#define LATCHSRC_A_INDXA	1	/*  Latch A on A Index. */
-#define LATCHSRC_B_INDXB	2	/*  Latch B on B Index. */
-#define LATCHSRC_B_OVERA	3	/*  Latch B on A Overflow. */
+/* LatchSrc values: */
+#define S626_LATCHSRC_AB_READ	0	/* Latch on read. */
+#define S626_LATCHSRC_A_INDXA	1	/* Latch A on A Index. */
+#define S626_LATCHSRC_B_INDXB	2	/* Latch B on B Index. */
+#define S626_LATCHSRC_B_OVERA	3	/* Latch B on A Overflow. */
 
-/*  IndxSrc values: */
-#define INDXSRC_HARD		0	/*  Hardware or software index. */
-#define INDXSRC_SOFT		1	/*  Software index only. */
+/* IndxSrc values: */
+#define S626_INDXSRC_ENCODER	0	/* Encoder. */
+#define S626_INDXSRC_DIGIN	1	/* Digital inputs. */
+#define S626_INDXSRC_SOFT	2	/* S/w controlled by IndxPol bit. */
+#define S626_INDXSRC_DISABLED	3	/* Index disabled. */
 
-/*  IndxPol values: */
-#define INDXPOL_POS 		0	/*  Index input is active high. */
-#define INDXPOL_NEG 		1	/*  Index input is active low. */
+/* IndxPol values: */
+#define S626_INDXPOL_POS	0	/* Index input is active high. */
+#define S626_INDXPOL_NEG	1	/* Index input is active low. */
 
-/*  ClkSrc values: */
-#define CLKSRC_COUNTER		0	/*  Counter mode. */
-#define CLKSRC_TIMER		2	/*  Timer mode. */
-#define CLKSRC_EXTENDER		3	/*  Extender mode. */
+/* Logical encoder mode values: */
+#define S626_ENCMODE_COUNTER	0	/* Counter mode. */
+#define S626_ENCMODE_TIMER	2	/* Timer mode. */
+#define S626_ENCMODE_EXTENDER	3	/* Extender mode. */
 
-/*  ClkPol values: */
-#define CLKPOL_POS		0	/*  Counter/Extender clock is */
-					/*  active high. */
-#define CLKPOL_NEG		1	/*  Counter/Extender clock is */
-					/*  active low. */
-#define CNTDIR_UP		0	/*  Timer counts up. */
-#define CNTDIR_DOWN 		1	/*  Timer counts down. */
+/* Physical CntSrc values (for Counter A source and Counter B source): */
+#define S626_CNTSRC_ENCODER	0	/* Encoder */
+#define S626_CNTSRC_DIGIN	1	/* Digital inputs */
+#define S626_CNTSRC_SYSCLK	2	/* System clock up */
+#define S626_CNTSRC_SYSCLK_DOWN	3	/* System clock down */
 
-/*  ClkEnab values: */
-#define CLKENAB_ALWAYS		0	/*  Clock always enabled. */
-#define CLKENAB_INDEX		1	/*  Clock is enabled by index. */
+/* ClkPol values: */
+#define S626_CLKPOL_POS		0	/* Counter/Extender clock is
+					 * active high. */
+#define S626_CLKPOL_NEG		1	/* Counter/Extender clock is
+					 * active low. */
+#define S626_CNTDIR_UP		0	/* Timer counts up. */
+#define S626_CNTDIR_DOWN	1	/* Timer counts down. */
 
-/*  ClkMult values: */
-#define CLKMULT_4X 		0	/*  4x clock multiplier. */
-#define CLKMULT_2X 		1	/*  2x clock multiplier. */
-#define CLKMULT_1X 		2	/*  1x clock multiplier. */
+/* ClkEnab values: */
+#define S626_CLKENAB_ALWAYS	0	/* Clock always enabled. */
+#define S626_CLKENAB_INDEX	1	/* Clock is enabled by index. */
 
-/*  Bit Field positions in COUNTER_SETUP structure: */
-#define BF_LOADSRC		9	/*  Preload trigger. */
-#define BF_INDXSRC		7	/*  Index source. */
-#define BF_INDXPOL		6	/*  Index polarity. */
-#define BF_CLKSRC		4	/*  Clock source. */
-#define BF_CLKPOL		3	/*  Clock polarity/count direction. */
-#define BF_CLKMULT		1	/*  Clock multiplier. */
-#define BF_CLKENAB		0	/*  Clock enable. */
+/* ClkMult values: */
+#define S626_CLKMULT_4X		0	/* 4x clock multiplier. */
+#define S626_CLKMULT_2X		1	/* 2x clock multiplier. */
+#define S626_CLKMULT_1X		2	/* 1x clock multiplier. */
+#define S626_CLKMULT_SPECIAL	3	/* Special clock multiplier value. */
 
-/*  Enumerated counter operating modes specified by ClkSrc bit field in */
-/*  a COUNTER_SETUP. */
+/* Sanity-check limits for parameters. */
 
-#define CLKSRC_COUNTER		0	/*  Counter: ENC_C clock, ENC_D */
-					/*  direction. */
-#define CLKSRC_TIMER		2	/*  Timer: SYS_C clock, */
-					/*  direction specified by */
-					/*  ClkPol. */
-#define CLKSRC_EXTENDER		3	/*  Extender: OVR_A clock, */
-					/*  ENC_D direction. */
+#define S626_NUM_COUNTERS	6	/* Maximum valid counter
+					 * logical channel number. */
+#define S626_NUM_INTSOURCES	4
+#define S626_NUM_LATCHSOURCES	4
+#define S626_NUM_CLKMULTS	4
+#define S626_NUM_CLKSOURCES	4
+#define S626_NUM_CLKPOLS	2
+#define S626_NUM_INDEXPOLS	2
+#define S626_NUM_INDEXSOURCES	2
+#define S626_NUM_LOADTRIGS	4
 
-/*  Enumerated counter clock multipliers. */
+/* General macros for manipulating bitfields: */
+#define S626_MAKE(x, w, p)	(((x) & ((1 << (w)) - 1)) << (p))
+#define S626_UNMAKE(v, w, p)	(((v) >> (p)) & ((1 << (w)) - 1))
 
-#define MULT_X0			0x0003	/*  Supports no multipliers; */
-					/*  fixed physical multiplier = */
-					/*  3. */
-#define MULT_X1			0x0002	/*  Supports multiplier x1; */
-					/*  fixed physical multiplier = */
-					/*  2. */
-#define MULT_X2			0x0001	/*  Supports multipliers x1, */
-					/*  x2; physical multipliers = */
-					/*  1 or 2. */
-#define MULT_X4			0x0000	/*  Supports multipliers x1, */
-					/*  x2, x4; physical */
-					/*  multipliers = 0, 1 or 2. */
+/* Bit field positions in CRA: */
+#define S626_CRABIT_INDXSRC_B	14	/* B index source. */
+#define S626_CRABIT_CNTSRC_B	12	/* B counter source. */
+#define S626_CRABIT_INDXPOL_A	11	/* A index polarity. */
+#define S626_CRABIT_LOADSRC_A	 9	/* A preload trigger. */
+#define S626_CRABIT_CLKMULT_A	 7	/* A clock multiplier. */
+#define S626_CRABIT_INTSRC_A	 5	/* A interrupt source. */
+#define S626_CRABIT_CLKPOL_A	 4	/* A clock polarity. */
+#define S626_CRABIT_INDXSRC_A	 2	/* A index source. */
+#define S626_CRABIT_CNTSRC_A	 0	/* A counter source. */
 
-/*  Sanity-check limits for parameters. */
+/* Bit field widths in CRA: */
+#define S626_CRAWID_INDXSRC_B	2
+#define S626_CRAWID_CNTSRC_B	2
+#define S626_CRAWID_INDXPOL_A	1
+#define S626_CRAWID_LOADSRC_A	2
+#define S626_CRAWID_CLKMULT_A	2
+#define S626_CRAWID_INTSRC_A	2
+#define S626_CRAWID_CLKPOL_A	1
+#define S626_CRAWID_INDXSRC_A	2
+#define S626_CRAWID_CNTSRC_A	2
 
-#define NUM_COUNTERS		6	/*  Maximum valid counter */
-					/*  logical channel number. */
-#define NUM_INTSOURCES		4
-#define NUM_LATCHSOURCES	4
-#define NUM_CLKMULTS		4
-#define NUM_CLKSOURCES		4
-#define NUM_CLKPOLS		2
-#define NUM_INDEXPOLS		2
-#define NUM_INDEXSOURCES	2
-#define NUM_LOADTRIGS		4
+/* Bit field masks for CRA: */
+#define S626_CRAMSK_INDXSRC_B	S626_SET_CRA_INDXSRC_B(~0)
+#define S626_CRAMSK_CNTSRC_B	S626_SET_CRA_CNTSRC_B(~0)
+#define S626_CRAMSK_INDXPOL_A	S626_SET_CRA_INDXPOL_A(~0)
+#define S626_CRAMSK_LOADSRC_A	S626_SET_CRA_LOADSRC_A(~0)
+#define S626_CRAMSK_CLKMULT_A	S626_SET_CRA_CLKMULT_A(~0)
+#define S626_CRAMSK_INTSRC_A	S626_SET_CRA_INTSRC_A(~0)
+#define S626_CRAMSK_CLKPOL_A	S626_SET_CRA_CLKPOL_A(~0)
+#define S626_CRAMSK_INDXSRC_A	S626_SET_CRA_INDXSRC_A(~0)
+#define S626_CRAMSK_CNTSRC_A	S626_SET_CRA_CNTSRC_A(~0)
 
-/*  Bit field positions in CRA and CRB counter control registers. */
+/* Construct parts of the CRA value: */
+#define S626_SET_CRA_INDXSRC_B(x)	\
+	S626_MAKE((x), S626_CRAWID_INDXSRC_B, S626_CRABIT_INDXSRC_B)
+#define S626_SET_CRA_CNTSRC_B(x)	\
+	S626_MAKE((x), S626_CRAWID_CNTSRC_B, S626_CRABIT_CNTSRC_B)
+#define S626_SET_CRA_INDXPOL_A(x)	\
+	S626_MAKE((x), S626_CRAWID_INDXPOL_A, S626_CRABIT_INDXPOL_A)
+#define S626_SET_CRA_LOADSRC_A(x)	\
+	S626_MAKE((x), S626_CRAWID_LOADSRC_A, S626_CRABIT_LOADSRC_A)
+#define S626_SET_CRA_CLKMULT_A(x)	\
+	S626_MAKE((x), S626_CRAWID_CLKMULT_A, S626_CRABIT_CLKMULT_A)
+#define S626_SET_CRA_INTSRC_A(x)	\
+	S626_MAKE((x), S626_CRAWID_INTSRC_A, S626_CRABIT_INTSRC_A)
+#define S626_SET_CRA_CLKPOL_A(x)	\
+	S626_MAKE((x), S626_CRAWID_CLKPOL_A, S626_CRABIT_CLKPOL_A)
+#define S626_SET_CRA_INDXSRC_A(x)	\
+	S626_MAKE((x), S626_CRAWID_INDXSRC_A, S626_CRABIT_INDXSRC_A)
+#define S626_SET_CRA_CNTSRC_A(x)	\
+	S626_MAKE((x), S626_CRAWID_CNTSRC_A, S626_CRABIT_CNTSRC_A)
 
-/*  Bit field positions in CRA: */
-#define CRABIT_INDXSRC_B	14	/*    B index source. */
-#define CRABIT_CLKSRC_B		12	/*    B clock source. */
-#define CRABIT_INDXPOL_A	11	/*    A index polarity. */
-#define CRABIT_LOADSRC_A	 9	/*    A preload trigger. */
-#define CRABIT_CLKMULT_A	 7	/*    A clock multiplier. */
-#define CRABIT_INTSRC_A		 5	/*    A interrupt source. */
-#define CRABIT_CLKPOL_A		 4	/*    A clock polarity. */
-#define CRABIT_INDXSRC_A	 2	/*    A index source. */
-#define CRABIT_CLKSRC_A		 0	/*    A clock source. */
+/* Extract parts of the CRA value: */
+#define S626_GET_CRA_INDXSRC_B(v)	\
+	S626_UNMAKE((v), S626_CRAWID_INDXSRC_B, S626_CRABIT_INDXSRC_B)
+#define S626_GET_CRA_CNTSRC_B(v)	\
+	S626_UNMAKE((v), S626_CRAWID_CNTSRC_B, S626_CRABIT_CNTSRC_B)
+#define S626_GET_CRA_INDXPOL_A(v)	\
+	S626_UNMAKE((v), S626_CRAWID_INDXPOL_A, S626_CRABIT_INDXPOL_A)
+#define S626_GET_CRA_LOADSRC_A(v)	\
+	S626_UNMAKE((v), S626_CRAWID_LOADSRC_A, S626_CRABIT_LOADSRC_A)
+#define S626_GET_CRA_CLKMULT_A(v)	\
+	S626_UNMAKE((v), S626_CRAWID_CLKMULT_A, S626_CRABIT_CLKMULT_A)
+#define S626_GET_CRA_INTSRC_A(v)	\
+	S626_UNMAKE((v), S626_CRAWID_INTSRC_A, S626_CRABIT_INTSRC_A)
+#define S626_GET_CRA_CLKPOL_A(v)	\
+	S626_UNMAKE((v), S626_CRAWID_CLKPOL_A, S626_CRABIT_CLKPOL_A)
+#define S626_GET_CRA_INDXSRC_A(v)	\
+	S626_UNMAKE((v), S626_CRAWID_INDXSRC_A, S626_CRABIT_INDXSRC_A)
+#define S626_GET_CRA_CNTSRC_A(v)	\
+	S626_UNMAKE((v), S626_CRAWID_CNTSRC_A, S626_CRABIT_CNTSRC_A)
 
-/*  Bit field positions in CRB: */
-#define CRBBIT_INTRESETCMD	15	/*    Interrupt reset command. */
-#define CRBBIT_INTRESET_B	14	/*    B interrupt reset enable. */
-#define CRBBIT_INTRESET_A	13	/*    A interrupt reset enable. */
-#define CRBBIT_CLKENAB_A	12	/*    A clock enable. */
-#define CRBBIT_INTSRC_B		10	/*    B interrupt source. */
-#define CRBBIT_LATCHSRC		 8	/*    A/B latch source. */
-#define CRBBIT_LOADSRC_B	 6	/*    B preload trigger. */
-#define CRBBIT_CLKMULT_B	 3	/*    B clock multiplier. */
-#define CRBBIT_CLKENAB_B	 2	/*    B clock enable. */
-#define CRBBIT_INDXPOL_B	 1	/*    B index polarity. */
-#define CRBBIT_CLKPOL_B		 0	/*    B clock polarity. */
+/* Bit field positions in CRB: */
+#define S626_CRBBIT_INTRESETCMD	15	/* (w) Interrupt reset command. */
+#define S626_CRBBIT_CNTDIR_B	15	/* (r) B counter direction. */
+#define S626_CRBBIT_INTRESET_B	14	/* (w) B interrupt reset enable. */
+#define S626_CRBBIT_OVERDO_A	14	/* (r) A overflow routed to dig. out. */
+#define S626_CRBBIT_INTRESET_A	13	/* (w) A interrupt reset enable. */
+#define S626_CRBBIT_OVERDO_B	13	/* (r) B overflow routed to dig. out. */
+#define S626_CRBBIT_CLKENAB_A	12	/* A clock enable. */
+#define S626_CRBBIT_INTSRC_B	10	/* B interrupt source. */
+#define S626_CRBBIT_LATCHSRC	 8	/* A/B latch source. */
+#define S626_CRBBIT_LOADSRC_B	 6	/* B preload trigger. */
+#define S626_CRBBIT_CLEAR_B	 7	/* B cleared when A overflows. */
+#define S626_CRBBIT_CLKMULT_B	 3	/* B clock multiplier. */
+#define S626_CRBBIT_CLKENAB_B	 2	/* B clock enable. */
+#define S626_CRBBIT_INDXPOL_B	 1	/* B index polarity. */
+#define S626_CRBBIT_CLKPOL_B	 0	/* B clock polarity. */
 
-/*  Bit field masks for CRA and CRB. */
+/* Bit field widths in CRB: */
+#define S626_CRBWID_INTRESETCMD	1
+#define S626_CRBWID_CNTDIR_B	1
+#define S626_CRBWID_INTRESET_B	1
+#define S626_CRBWID_OVERDO_A	1
+#define S626_CRBWID_INTRESET_A	1
+#define S626_CRBWID_OVERDO_B	1
+#define S626_CRBWID_CLKENAB_A	1
+#define S626_CRBWID_INTSRC_B	2
+#define S626_CRBWID_LATCHSRC	2
+#define S626_CRBWID_LOADSRC_B	2
+#define S626_CRBWID_CLEAR_B	1
+#define S626_CRBWID_CLKMULT_B	2
+#define S626_CRBWID_CLKENAB_B	1
+#define S626_CRBWID_INDXPOL_B	1
+#define S626_CRBWID_CLKPOL_B	1
 
-#define CRAMSK_INDXSRC_B	(3 << CRABIT_INDXSRC_B)
-#define CRAMSK_CLKSRC_B		(3 << CRABIT_CLKSRC_B)
-#define CRAMSK_INDXPOL_A	(1 << CRABIT_INDXPOL_A)
-#define CRAMSK_LOADSRC_A	(3 << CRABIT_LOADSRC_A)
-#define CRAMSK_CLKMULT_A	(3 << CRABIT_CLKMULT_A)
-#define CRAMSK_INTSRC_A		(3 << CRABIT_INTSRC_A)
-#define CRAMSK_CLKPOL_A		(3 << CRABIT_CLKPOL_A)
-#define CRAMSK_INDXSRC_A	(3 << CRABIT_INDXSRC_A)
-#define CRAMSK_CLKSRC_A		(3 << CRABIT_CLKSRC_A)
+/* Bit field masks for CRB: */
+#define S626_CRBMSK_INTRESETCMD	S626_SET_CRB_INTRESETCMD(~0)	/* (w) */
+#define S626_CRBMSK_CNTDIR_B	S626_CRBMSK_INTRESETCMD		/* (r) */
+#define S626_CRBMSK_INTRESET_B	S626_SET_CRB_INTRESET_B(~0)	/* (w) */
+#define S626_CRBMSK_OVERDO_A	S626_CRBMSK_INTRESET_B		/* (r) */
+#define S626_CRBMSK_INTRESET_A	S626_SET_CRB_INTRESET_A(~0)	/* (w) */
+#define S626_CRBMSK_OVERDO_B	S626_CRBMSK_INTRESET_A		/* (r) */
+#define S626_CRBMSK_CLKENAB_A	S626_SET_CRB_CLKENAB_A(~0)
+#define S626_CRBMSK_INTSRC_B	S626_SET_CRB_INTSRC_B(~0)
+#define S626_CRBMSK_LATCHSRC	S626_SET_CRB_LATCHSRC(~0)
+#define S626_CRBMSK_LOADSRC_B	S626_SET_CRB_LOADSRC_B(~0)
+#define S626_CRBMSK_CLEAR_B	S626_SET_CRB_CLEAR_B(~0)
+#define S626_CRBMSK_CLKMULT_B	S626_SET_CRB_CLKMULT_B(~0)
+#define S626_CRBMSK_CLKENAB_B	S626_SET_CRB_CLKENAB_B(~0)
+#define S626_CRBMSK_INDXPOL_B	S626_SET_CRB_INDXPOL_B(~0)
+#define S626_CRBMSK_CLKPOL_B	S626_SET_CRB_CLKPOL_B(~0)
 
-#define CRBMSK_INTRESETCMD	(1 << CRBBIT_INTRESETCMD)
-#define CRBMSK_INTRESET_B	(1 << CRBBIT_INTRESET_B)
-#define CRBMSK_INTRESET_A	(1 << CRBBIT_INTRESET_A)
-#define CRBMSK_CLKENAB_A	(1 << CRBBIT_CLKENAB_A)
-#define CRBMSK_INTSRC_B		(3 << CRBBIT_INTSRC_B)
-#define CRBMSK_LATCHSRC		(3 << CRBBIT_LATCHSRC)
-#define CRBMSK_LOADSRC_B	(3 << CRBBIT_LOADSRC_B)
-#define CRBMSK_CLKMULT_B	(3 << CRBBIT_CLKMULT_B)
-#define CRBMSK_CLKENAB_B	(1 << CRBBIT_CLKENAB_B)
-#define CRBMSK_INDXPOL_B	(1 << CRBBIT_INDXPOL_B)
-#define CRBMSK_CLKPOL_B		(1 << CRBBIT_CLKPOL_B)
+/* Interrupt reset control bits. */
+#define S626_CRBMSK_INTCTRL	(S626_CRBMSK_INTRESETCMD | \
+				 S626_CRBMSK_INTRESET_A | \
+				 S626_CRBMSK_INTRESET_B)
 
-#define CRBMSK_INTCTRL		(CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A | CRBMSK_INTRESET_B)	/*  Interrupt reset control bits. */
+/* Construct parts of the CRB value: */
+#define S626_SET_CRB_INTRESETCMD(x)	\
+	S626_MAKE((x), S626_CRBWID_INTRESETCMD, S626_CRBBIT_INTRESETCMD)
+#define S626_SET_CRB_INTRESET_B(x)	\
+	S626_MAKE((x), S626_CRBWID_INTRESET_B, S626_CRBBIT_INTRESET_B)
+#define S626_SET_CRB_INTRESET_A(x)	\
+	S626_MAKE((x), S626_CRBWID_INTRESET_A, S626_CRBBIT_INTRESET_A)
+#define S626_SET_CRB_CLKENAB_A(x)	\
+	S626_MAKE((x), S626_CRBWID_CLKENAB_A, S626_CRBBIT_CLKENAB_A)
+#define S626_SET_CRB_INTSRC_B(x)	\
+	S626_MAKE((x), S626_CRBWID_INTSRC_B, S626_CRBBIT_INTSRC_B)
+#define S626_SET_CRB_LATCHSRC(x)	\
+	S626_MAKE((x), S626_CRBWID_LATCHSRC, S626_CRBBIT_LATCHSRC)
+#define S626_SET_CRB_LOADSRC_B(x)	\
+	S626_MAKE((x), S626_CRBWID_LOADSRC_B, S626_CRBBIT_LOADSRC_B)
+#define S626_SET_CRB_CLEAR_B(x)	\
+	S626_MAKE((x), S626_CRBWID_CLEAR_B, S626_CRBBIT_CLEAR_B)
+#define S626_SET_CRB_CLKMULT_B(x)	\
+	S626_MAKE((x), S626_CRBWID_CLKMULT_B, S626_CRBBIT_CLKMULT_B)
+#define S626_SET_CRB_CLKENAB_B(x)	\
+	S626_MAKE((x), S626_CRBWID_CLKENAB_B, S626_CRBBIT_CLKENAB_B)
+#define S626_SET_CRB_INDXPOL_B(x)	\
+	S626_MAKE((x), S626_CRBWID_INDXPOL_B, S626_CRBBIT_INDXPOL_B)
+#define S626_SET_CRB_CLKPOL_B(x)	\
+	S626_MAKE((x), S626_CRBWID_CLKPOL_B, S626_CRBBIT_CLKPOL_B)
 
-/*  Bit field positions for standardized SETUP structure. */
+/* Extract parts of the CRB value: */
+#define S626_GET_CRB_CNTDIR_B(v)	\
+	S626_UNMAKE((v), S626_CRBWID_CNTDIR_B, S626_CRBBIT_CNTDIR_B)
+#define S626_GET_CRB_OVERDO_A(v)	\
+	S626_UNMAKE((v), S626_CRBWID_OVERDO_A, S626_CRBBIT_OVERDO_A)
+#define S626_GET_CRB_OVERDO_B(v)	\
+	S626_UNMAKE((v), S626_CRBWID_OVERDO_B, S626_CRBBIT_OVERDO_B)
+#define S626_GET_CRB_CLKENAB_A(v)	\
+	S626_UNMAKE((v), S626_CRBWID_CLKENAB_A, S626_CRBBIT_CLKENAB_A)
+#define S626_GET_CRB_INTSRC_B(v)	\
+	S626_UNMAKE((v), S626_CRBWID_INTSRC_B, S626_CRBBIT_INTSRC_B)
+#define S626_GET_CRB_LATCHSRC(v)	\
+	S626_UNMAKE((v), S626_CRBWID_LATCHSRC, S626_CRBBIT_LATCHSRC)
+#define S626_GET_CRB_LOADSRC_B(v)	\
+	S626_UNMAKE((v), S626_CRBWID_LOADSRC_B, S626_CRBBIT_LOADSRC_B)
+#define S626_GET_CRB_CLEAR_B(v)	\
+	S626_UNMAKE((v), S626_CRBWID_CLEAR_B, S626_CRBBIT_CLEAR_B)
+#define S626_GET_CRB_CLKMULT_B(v)	\
+	S626_UNMAKE((v), S626_CRBWID_CLKMULT_B, S626_CRBBIT_CLKMULT_B)
+#define S626_GET_CRB_CLKENAB_B(v)	\
+	S626_UNMAKE((v), S626_CRBWID_CLKENAB_B, S626_CRBBIT_CLKENAB_B)
+#define S626_GET_CRB_INDXPOL_B(v)	\
+	S626_UNMAKE((v), S626_CRBWID_INDXPOL_B, S626_CRBBIT_INDXPOL_B)
+#define S626_GET_CRB_CLKPOL_B(v)	\
+	S626_UNMAKE((v), S626_CRBWID_CLKPOL_B, S626_CRBBIT_CLKPOL_B)
 
-#define STDBIT_INTSRC		13
-#define STDBIT_LATCHSRC		11
-#define STDBIT_LOADSRC		 9
-#define STDBIT_INDXSRC		 7
-#define STDBIT_INDXPOL		 6
-#define STDBIT_CLKSRC		 4
-#define STDBIT_CLKPOL		 3
-#define STDBIT_CLKMULT		 1
-#define STDBIT_CLKENAB		 0
+/* Bit field positions for standardized SETUP structure: */
+#define S626_STDBIT_INTSRC	13
+#define S626_STDBIT_LATCHSRC	11
+#define S626_STDBIT_LOADSRC	 9
+#define S626_STDBIT_INDXSRC	 7
+#define S626_STDBIT_INDXPOL	 6
+#define S626_STDBIT_ENCMODE	 4
+#define S626_STDBIT_CLKPOL	 3
+#define S626_STDBIT_CLKMULT	 1
+#define S626_STDBIT_CLKENAB	 0
 
-/*  Bit field masks for standardized SETUP structure. */
+/* Bit field widths for standardized SETUP structure: */
+#define S626_STDWID_INTSRC	2
+#define S626_STDWID_LATCHSRC	2
+#define S626_STDWID_LOADSRC	2
+#define S626_STDWID_INDXSRC	2
+#define S626_STDWID_INDXPOL	1
+#define S626_STDWID_ENCMODE	2
+#define S626_STDWID_CLKPOL	1
+#define S626_STDWID_CLKMULT	2
+#define S626_STDWID_CLKENAB	1
 
-#define STDMSK_INTSRC		(3 << STDBIT_INTSRC)
-#define STDMSK_LATCHSRC		(3 << STDBIT_LATCHSRC)
-#define STDMSK_LOADSRC		(3 << STDBIT_LOADSRC)
-#define STDMSK_INDXSRC		(1 << STDBIT_INDXSRC)
-#define STDMSK_INDXPOL		(1 << STDBIT_INDXPOL)
-#define STDMSK_CLKSRC		(3 << STDBIT_CLKSRC)
-#define STDMSK_CLKPOL		(1 << STDBIT_CLKPOL)
-#define STDMSK_CLKMULT		(3 << STDBIT_CLKMULT)
-#define STDMSK_CLKENAB		(1 << STDBIT_CLKENAB)
+/* Bit field masks for standardized SETUP structure: */
+#define S626_STDMSK_INTSRC	S626_SET_STD_INTSRC(~0)
+#define S626_STDMSK_LATCHSRC	S626_SET_STD_LATCHSRC(~0)
+#define S626_STDMSK_LOADSRC	S626_SET_STD_LOADSRC(~0)
+#define S626_STDMSK_INDXSRC	S626_SET_STD_INDXSRC(~0)
+#define S626_STDMSK_INDXPOL	S626_SET_STD_INDXPOL(~0)
+#define S626_STDMSK_ENCMODE	S626_SET_STD_ENCMODE(~0)
+#define S626_STDMSK_CLKPOL	S626_SET_STD_CLKPOL(~0)
+#define S626_STDMSK_CLKMULT	S626_SET_STD_CLKMULT(~0)
+#define S626_STDMSK_CLKENAB	S626_SET_STD_CLKENAB(~0)
 
-struct bufferDMA {
-	dma_addr_t PhysicalBase;
-	void *LogicalBase;
-	uint32_t DMAHandle;
-};
+/* Construct parts of standardized SETUP structure: */
+#define S626_SET_STD_INTSRC(x)	\
+	S626_MAKE((x), S626_STDWID_INTSRC, S626_STDBIT_INTSRC)
+#define S626_SET_STD_LATCHSRC(x)	\
+	S626_MAKE((x), S626_STDWID_LATCHSRC, S626_STDBIT_LATCHSRC)
+#define S626_SET_STD_LOADSRC(x)	\
+	S626_MAKE((x), S626_STDWID_LOADSRC, S626_STDBIT_LOADSRC)
+#define S626_SET_STD_INDXSRC(x)	\
+	S626_MAKE((x), S626_STDWID_INDXSRC, S626_STDBIT_INDXSRC)
+#define S626_SET_STD_INDXPOL(x)	\
+	S626_MAKE((x), S626_STDWID_INDXPOL, S626_STDBIT_INDXPOL)
+#define S626_SET_STD_ENCMODE(x)	\
+	S626_MAKE((x), S626_STDWID_ENCMODE, S626_STDBIT_ENCMODE)
+#define S626_SET_STD_CLKPOL(x)	\
+	S626_MAKE((x), S626_STDWID_CLKPOL, S626_STDBIT_CLKPOL)
+#define S626_SET_STD_CLKMULT(x)	\
+	S626_MAKE((x), S626_STDWID_CLKMULT, S626_STDBIT_CLKMULT)
+#define S626_SET_STD_CLKENAB(x)	\
+	S626_MAKE((x), S626_STDWID_CLKENAB, S626_STDBIT_CLKENAB)
+
+/* Extract parts of standardized SETUP structure: */
+#define S626_GET_STD_INTSRC(v)	\
+	S626_UNMAKE((v), S626_STDWID_INTSRC, S626_STDBIT_INTSRC)
+#define S626_GET_STD_LATCHSRC(v)	\
+	S626_UNMAKE((v), S626_STDWID_LATCHSRC, S626_STDBIT_LATCHSRC)
+#define S626_GET_STD_LOADSRC(v)	\
+	S626_UNMAKE((v), S626_STDWID_LOADSRC, S626_STDBIT_LOADSRC)
+#define S626_GET_STD_INDXSRC(v)	\
+	S626_UNMAKE((v), S626_STDWID_INDXSRC, S626_STDBIT_INDXSRC)
+#define S626_GET_STD_INDXPOL(v)	\
+	S626_UNMAKE((v), S626_STDWID_INDXPOL, S626_STDBIT_INDXPOL)
+#define S626_GET_STD_ENCMODE(v)	\
+	S626_UNMAKE((v), S626_STDWID_ENCMODE, S626_STDBIT_ENCMODE)
+#define S626_GET_STD_CLKPOL(v)	\
+	S626_UNMAKE((v), S626_STDWID_CLKPOL, S626_STDBIT_CLKPOL)
+#define S626_GET_STD_CLKMULT(v)	\
+	S626_UNMAKE((v), S626_STDWID_CLKMULT, S626_STDBIT_CLKMULT)
+#define S626_GET_STD_CLKENAB(v)	\
+	S626_UNMAKE((v), S626_STDWID_CLKENAB, S626_STDBIT_CLKENAB)
+
+#endif
diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c
index 9e96495..daee2f4 100644
--- a/drivers/staging/comedi/drivers/skel.c
+++ b/drivers/staging/comedi/drivers/skel.c
@@ -332,30 +332,44 @@
 	return i;
 }
 
-/* DIO devices are slightly special.  Although it is possible to
+/*
+ * DIO devices are slightly special. Although it is possible to
  * implement the insn_read/insn_write interface, it is much more
  * useful to applications if you implement the insn_bits interface.
- * This allows packed reading/writing of the DIO channels.  The
- * comedi core can convert between insn_bits and insn_read/write */
+ * This allows packed reading/writing of the DIO channels. The
+ * comedi core can convert between insn_bits and insn_read/write.
+ */
 static int skel_dio_insn_bits(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
-			      struct comedi_insn *insn, unsigned int *data)
+			      struct comedi_insn *insn,
+			      unsigned int *data)
 {
-	/* The insn data is a mask in data[0] and the new data
-	 * in data[1], each channel cooresponding to a bit. */
-	if (data[0]) {
-		s->state &= ~data[0];
-		s->state |= data[0] & data[1];
+	/*
+	 * The insn data is a mask in data[0] and the new data
+	 * in data[1], each channel cooresponding to a bit.
+	 *
+	 * The core provided comedi_dio_update_state() function can
+	 * be used to handle the internal state update to DIO subdevices
+	 * with <= 32 channels. This function will return '0' if the
+	 * state does not change or the mask of the channels that need
+	 * to be updated.
+	 */
+	if (comedi_dio_update_state(s, data)) {
 		/* Write out the new digital output lines */
-		/* outw(s->state,dev->iobase + SKEL_DIO); */
+		/* outw(s->state, dev->iobase + SKEL_DIO); */
 	}
 
-	/* on return, data[1] contains the value of the digital
-	 * input and output lines. */
-	/* data[1]=inw(dev->iobase + SKEL_DIO); */
-	/* or we could just return the software copy of the output values if
-	 * it was a purely digital output subdevice */
-	/* data[1]=s->state; */
+	/*
+	 * On return, data[1] contains the value of the digital
+	 * input and output lines.
+	 */
+	/* data[1] = inw(dev->iobase + SKEL_DIO); */
+
+	/*
+	 * Or we could just return the software copy of the output
+	 * values if it was a purely digital output subdevice.
+	 */
+	/* data[1] = s->state; */
 
 	return insn->n;
 }
diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
index 11758a5..df22a78 100644
--- a/drivers/staging/comedi/drivers/ssv_dnp.c
+++ b/drivers/staging/comedi/drivers/ssv_dnp.c
@@ -46,51 +46,43 @@
 #define PCMR  0xa3		/* Port C Mode Register                      */
 #define PCDR  0xa7		/* Port C Data Register                      */
 
-/* ------------------------------------------------------------------------- */
-/* The insn_bits interface allows packed reading/writing of DIO channels.    */
-/* The comedi core can convert between insn_bits and insn_read/write, so you */
-/* are able to use these instructions as well.                               */
-/* ------------------------------------------------------------------------- */
-
 static int dnp_dio_insn_bits(struct comedi_device *dev,
 			     struct comedi_subdevice *s,
-			     struct comedi_insn *insn, unsigned int *data)
+			     struct comedi_insn *insn,
+			     unsigned int *data)
 {
-	/* The insn data is a mask in data[0] and the new data in data[1],   */
-	/* each channel cooresponding to a bit.                              */
+	unsigned int mask;
+	unsigned int val;
 
-	/* Ports A and B are straight forward: each bit corresponds to an    */
-	/* output pin with the same order. Port C is different: bits 0...3   */
-	/* correspond to bits 4...7 of the output register (PCDR).           */
+	/*
+	 * Ports A and B are straight forward: each bit corresponds to an
+	 * output pin with the same order. Port C is different: bits 0...3
+	 * correspond to bits 4...7 of the output register (PCDR).
+	 */
 
-	if (data[0]) {
-
+	mask = comedi_dio_update_state(s, data);
+	if (mask) {
 		outb(PADR, CSCIR);
-		outb((inb(CSCDR)
-		      & ~(u8) (data[0] & 0x0000FF))
-		     | (u8) (data[1] & 0x0000FF), CSCDR);
+		outb(s->state & 0xff, CSCDR);
 
 		outb(PBDR, CSCIR);
-		outb((inb(CSCDR)
-		      & ~(u8) ((data[0] & 0x00FF00) >> 8))
-		     | (u8) ((data[1] & 0x00FF00) >> 8), CSCDR);
+		outb((s->state >> 8) & 0xff, CSCDR);
 
 		outb(PCDR, CSCIR);
-		outb((inb(CSCDR)
-		      & ~(u8) ((data[0] & 0x0F0000) >> 12))
-		     | (u8) ((data[1] & 0x0F0000) >> 12), CSCDR);
+		val = inb(CSCDR) & 0x0f;
+		outb(((s->state >> 12) & 0xf0) | val, CSCDR);
 	}
 
-	/* on return, data[1] contains the value of the digital input lines. */
 	outb(PADR, CSCIR);
-	data[0] = inb(CSCDR);
+	val = inb(CSCDR);
 	outb(PBDR, CSCIR);
-	data[0] += inb(CSCDR) << 8;
+	val |= (inb(CSCDR) << 8);
 	outb(PCDR, CSCIR);
-	data[0] += ((inb(CSCDR) & 0xF0) << 12);
+	val |= ((inb(CSCDR) & 0xf0) << 12);
+
+	data[1] = val;
 
 	return insn->n;
-
 }
 
 static int dnp_dio_insn_config(struct comedi_device *dev,
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index 701ad1a..da1d501 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -122,7 +122,7 @@
 #define PWM_DEFAULT_PERIOD ((long)(1E9/100))
 
 /* Size of one A/D value */
-#define SIZEADIN          ((sizeof(int16_t)))
+#define SIZEADIN          ((sizeof(uint16_t)))
 
 /*
  * Size of the input-buffer IN BYTES
@@ -134,7 +134,7 @@
 #define SIZEINSNBUF       16
 
 /* size of one value for the D/A converter: channel and value */
-#define SIZEDAOUT          ((sizeof(int8_t)+sizeof(int16_t)))
+#define SIZEDAOUT          ((sizeof(uint8_t)+sizeof(uint16_t)))
 
 /*
  * Size of the output-buffer in bytes
@@ -195,15 +195,15 @@
 	/* PWM period */
 	unsigned int pwm_period;
 	/* PWM internal delay for the GPIF in the FX2 */
-	int8_t pwm_delay;
+	uint8_t pwm_delay;
 	/* size of the PWM buffer which holds the bit pattern */
 	int pwm_buf_sz;
 	/* input buffer for the ISO-transfer */
-	int16_t *in_buf;
+	uint16_t *in_buf;
 	/* input buffer for single insn */
-	int16_t *insn_buf;
+	uint16_t *insn_buf;
 
-	int8_t ao_chanlist[USBDUX_NUM_AO_CHAN];
+	uint8_t ao_chanlist[USBDUX_NUM_AO_CHAN];
 	unsigned int ao_readback[USBDUX_NUM_AO_CHAN];
 
 	unsigned int high_speed:1;
@@ -225,7 +225,7 @@
 	/* interval in frames/uframes */
 	unsigned int ai_interval;
 	/* commands */
-	int8_t *dux_commands;
+	uint8_t *dux_commands;
 	struct semaphore sem;
 };
 
@@ -367,7 +367,7 @@
 	n = s->async->cmd.chanlist_len;
 	for (i = 0; i < n; i++) {
 		unsigned int range = CR_RANGE(s->async->cmd.chanlist[i]);
-		int16_t val = le16_to_cpu(devpriv->in_buf[i]);
+		uint16_t val = le16_to_cpu(devpriv->in_buf[i]);
 
 		/* bipolar data is two's-complement */
 		if (comedi_range_is_bipolar(s, range))
@@ -415,7 +415,7 @@
 	struct comedi_device *dev = urb->context;
 	struct comedi_subdevice *s = dev->write_subdev;
 	struct usbdux_private *devpriv = dev->private;
-	int8_t *datap;
+	uint8_t *datap;
 	int len;
 	int ret;
 	int i;
@@ -483,7 +483,7 @@
 		*datap++ = len;
 		for (i = 0; i < s->async->cmd.chanlist_len; i++) {
 			unsigned int chan = devpriv->ao_chanlist[i];
-			short val;
+			unsigned short val;
 
 			ret = comedi_buf_get(s->async, &val);
 			if (ret < 0) {
@@ -649,14 +649,15 @@
  * creates the ADC command for the MAX1271
  * range is the range value from comedi
  */
-static int8_t create_adc_command(unsigned int chan, int range)
+static uint8_t create_adc_command(unsigned int chan, unsigned int range)
 {
-	int8_t p = (range <= 1);
-	int8_t r = ((range % 2) == 0);
+	uint8_t p = (range <= 1);
+	uint8_t r = ((range % 2) == 0);
+
 	return (chan << 4) | ((p == 1) << 2) | ((r == 1) << 3);
 }
 
-static int send_dux_commands(struct comedi_device *dev, int cmd_type)
+static int send_dux_commands(struct comedi_device *dev, unsigned int cmd_type)
 {
 	struct usb_device *usb = comedi_to_usb_dev(dev);
 	struct usbdux_private *devpriv = dev->private;
@@ -669,7 +670,7 @@
 			    &nsent, BULK_TIMEOUT);
 }
 
-static int receive_dux_commands(struct comedi_device *dev, int command)
+static int receive_dux_commands(struct comedi_device *dev, unsigned int command)
 {
 	struct usb_device *usb = comedi_to_usb_dev(dev);
 	struct usbdux_private *devpriv = dev->private;
@@ -879,7 +880,7 @@
 	struct usbdux_private *devpriv = dev->private;
 	unsigned int chan = CR_CHAN(insn->chanspec);
 	unsigned int val = devpriv->ao_readback[chan];
-	int16_t *p = (int16_t *)&devpriv->dux_commands[2];
+	uint16_t *p = (uint16_t *)&devpriv->dux_commands[2];
 	int ret = -EBUSY;
 	int i;
 
@@ -1133,15 +1134,13 @@
 {
 
 	struct usbdux_private *devpriv = dev->private;
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
 	int ret;
 
 	down(&devpriv->sem);
 
-	s->state &= ~mask;
-	s->state |= (bits & mask);
+	comedi_dio_update_state(s, data);
 
+	/* Always update the hardware. See the (*insn_config). */
 	devpriv->dux_commands[1] = s->io_bits;
 	devpriv->dux_commands[2] = s->state;
 
@@ -1200,7 +1199,7 @@
 {
 	struct usbdux_private *devpriv = dev->private;
 	unsigned int chan = CR_CHAN(insn->chanspec);
-	int16_t *p = (int16_t *)&devpriv->dux_commands[2];
+	uint16_t *p = (uint16_t *)&devpriv->dux_commands[2];
 	int ret = 0;
 	int i;
 
diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c
index c47f408..a5363de 100644
--- a/drivers/staging/comedi/drivers/usbduxsigma.c
+++ b/drivers/staging/comedi/drivers/usbduxsigma.c
@@ -78,7 +78,7 @@
 #define USBDUXSIGMA_NUM_AO_CHAN		4
 
 /* Size of one A/D value */
-#define SIZEADIN          ((sizeof(int32_t)))
+#define SIZEADIN          ((sizeof(uint32_t)))
 
 /*
  * Size of the async input-buffer IN BYTES, the DIO state is transmitted
@@ -93,7 +93,7 @@
 #define NUMOUTCHANNELS    8
 
 /* size of one value for the D/A converter: channel and value */
-#define SIZEDAOUT          ((sizeof(uint8_t)+sizeof(int16_t)))
+#define SIZEDAOUT          ((sizeof(uint8_t)+sizeof(uint16_t)))
 
 /*
  * Size of the output-buffer in bytes
@@ -157,11 +157,11 @@
 	/* size of the PWM buffer which holds the bit pattern */
 	int pwm_buf_sz;
 	/* input buffer for the ISO-transfer */
-	int32_t *in_buf;
+	uint32_t *in_buf;
 	/* input buffer for single insn */
-	int8_t *insn_buf;
+	uint8_t *insn_buf;
 
-	int8_t ao_chanlist[USBDUXSIGMA_NUM_AO_CHAN];
+	uint8_t ao_chanlist[USBDUXSIGMA_NUM_AO_CHAN];
 	unsigned int ao_readback[USBDUXSIGMA_NUM_AO_CHAN];
 
 	unsigned high_speed:1;
@@ -224,7 +224,7 @@
 	struct usbduxsigma_private *devpriv = dev->private;
 	struct comedi_subdevice *s = dev->read_subdev;
 	unsigned int dio_state;
-	int32_t val;
+	uint32_t val;
 	int ret;
 	int i;
 
@@ -421,7 +421,7 @@
 		*datap++ = len;
 		for (i = 0; i < len; i++) {
 			unsigned int chan = devpriv->ao_chanlist[i];
-			short val;
+			unsigned short val;
 
 			ret = comedi_buf_get(s->async, &val);
 			if (ret < 0) {
@@ -784,7 +784,7 @@
 	}
 
 	for (i = 0; i < insn->n; i++) {
-		int32_t val;
+		uint32_t val;
 
 		ret = usbduxsigma_receive_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD);
 		if (ret < 0) {
@@ -793,7 +793,7 @@
 		}
 
 		/* 32 bits big endian from the A/D converter */
-		val = be32_to_cpu(*((int32_t *)((devpriv->insn_buf) + 1)));
+		val = be32_to_cpu(*((uint32_t *)((devpriv->insn_buf) + 1)));
 		val &= 0x00ffffff;	/* strip status byte */
 		val ^= 0x00800000;	/* convert to unsigned */
 
@@ -1059,15 +1059,13 @@
 				     unsigned int *data)
 {
 	struct usbduxsigma_private *devpriv = dev->private;
-	unsigned int mask = data[0];
-	unsigned int bits = data[1];
 	int ret;
 
 	down(&devpriv->sem);
 
-	s->state &= ~mask;
-	s->state |= (bits & mask);
+	comedi_dio_update_state(s, data);
 
+	/* Always update the hardware. See the (*insn_config). */
 	devpriv->dux_commands[1] = s->io_bits & 0xff;
 	devpriv->dux_commands[4] = s->state & 0xff;
 	devpriv->dux_commands[2] = (s->io_bits >> 8) & 0xff;
@@ -1360,7 +1358,7 @@
 		return ret;
 
 	/* 32 bits big endian from the A/D converter */
-	val = be32_to_cpu(*((int32_t *)((devpriv->insn_buf)+1)));
+	val = be32_to_cpu(*((uint32_t *)((devpriv->insn_buf)+1)));
 	val &= 0x00ffffff;	/* strip status byte */
 	val ^= 0x00800000;	/* convert to unsigned */
 
diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c
index 06efa16..933b01a 100644
--- a/drivers/staging/comedi/drivers/vmk80xx.c
+++ b/drivers/staging/comedi/drivers/vmk80xx.c
@@ -462,9 +462,10 @@
 				unsigned int *data)
 {
 	struct vmk80xx_private *devpriv = dev->private;
-	unsigned char *rx_buf, *tx_buf;
+	unsigned char *rx_buf = devpriv->usb_rx_buf;
+	unsigned char *tx_buf = devpriv->usb_tx_buf;
 	int reg, cmd;
-	int retval;
+	int ret;
 
 	if (devpriv->model == VMK8061_MODEL) {
 		reg = VMK8061_DO_REG;
@@ -476,37 +477,27 @@
 
 	down(&devpriv->limit_sem);
 
-	rx_buf = devpriv->usb_rx_buf;
-	tx_buf = devpriv->usb_tx_buf;
-
-	if (data[0]) {
-		tx_buf[reg] &= ~data[0];
-		tx_buf[reg] |= (data[0] & data[1]);
-
-		retval = vmk80xx_write_packet(dev, cmd);
-
-		if (retval)
+	if (comedi_dio_update_state(s, data)) {
+		tx_buf[reg] = s->state;
+		ret = vmk80xx_write_packet(dev, cmd);
+		if (ret)
 			goto out;
 	}
 
 	if (devpriv->model == VMK8061_MODEL) {
 		tx_buf[0] = VMK8061_CMD_RD_DO;
-
-		retval = vmk80xx_read_packet(dev);
-
-		if (!retval) {
-			data[1] = rx_buf[reg];
-			retval = 2;
-		}
+		ret = vmk80xx_read_packet(dev);
+		if (ret)
+			goto out;
+		data[1] = rx_buf[reg];
 	} else {
-		data[1] = tx_buf[reg];
-		retval = 2;
+		data[1] = s->state;
 	}
 
 out:
 	up(&devpriv->limit_sem);
 
-	return retval;
+	return ret ? ret : insn->n;
 }
 
 static int vmk80xx_cnt_insn_read(struct comedi_device *dev,
diff --git a/drivers/staging/cptm1217/clearpad_tm1217.c b/drivers/staging/cptm1217/clearpad_tm1217.c
index 42a5f5c..ca4c2c6 100644
--- a/drivers/staging/cptm1217/clearpad_tm1217.c
+++ b/drivers/staging/cptm1217/clearpad_tm1217.c
@@ -457,8 +457,6 @@
 	for (i = 0; i < TOUCH_SUPPORTED; i++) {
 		input_dev = input_allocate_device();
 		if (input_dev == NULL) {
-			dev_err(ts->dev,
-				"cp_tm1217:Input Device Struct alloc failed\n");
 			retval = -ENOMEM;
 			goto fail;
 		}
diff --git a/drivers/staging/crystalhd/crystalhd_hw.c b/drivers/staging/crystalhd/crystalhd_hw.c
index 5845e89..043bd49 100644
--- a/drivers/staging/crystalhd/crystalhd_hw.c
+++ b/drivers/staging/crystalhd/crystalhd_hw.c
@@ -1517,7 +1517,7 @@
 	uint32_t i, list_avail = 0;
 	enum BC_STATUS comp_sts = BC_STS_NO_DATA;
 	uint32_t y_err_sts, uv_err_sts, y_dn_sz = 0, uv_dn_sz = 0;
-	bool ret = 0;
+	bool ret = false;
 
 	if (!hw) {
 		BCMLOG_ERR("Invalid Arguments\n");
@@ -1852,7 +1852,7 @@
 {
 	uint32_t intr_sts = 0;
 	uint32_t deco_intr = 0;
-	bool rc = 0;
+	bool rc = false;
 
 	if (!adp || !hw->dev_started)
 		return rc;
@@ -1865,7 +1865,7 @@
 
 	if (intr_sts) {
 		/* let system know we processed interrupt..*/
-		rc = 1;
+		rc = true;
 		hw->stats.dev_interrupts++;
 	}
 
@@ -1886,7 +1886,7 @@
 		/* FIXME: jarod: No udelay? might this be
 		 the real reason mini pci-e cards were stalling out? */
 		bc_dec_reg_wr(adp, Stream2Host_Intr_Sts, 0);
-		rc = 1;
+		rc = true;
 	}
 
 	/* Rx interrupts */
diff --git a/drivers/staging/crystalhd/crystalhd_lnx.c b/drivers/staging/crystalhd/crystalhd_lnx.c
index b17fbf8..190b9b9 100644
--- a/drivers/staging/crystalhd/crystalhd_lnx.c
+++ b/drivers/staging/crystalhd/crystalhd_lnx.c
@@ -75,8 +75,9 @@
 	return 0;
 }
 
-struct crystalhd_ioctl_data *chd_dec_alloc_iodata(struct crystalhd_adp *adp,
-					 bool isr)
+static struct
+crystalhd_ioctl_data *chd_dec_alloc_iodata(struct crystalhd_adp *adp,
+					   bool isr)
 {
 	unsigned long flags = 0;
 	struct crystalhd_ioctl_data *temp;
@@ -96,8 +97,8 @@
 	return temp;
 }
 
-void chd_dec_free_iodata(struct crystalhd_adp *adp,
-			 struct crystalhd_ioctl_data *iodata, bool isr)
+static void chd_dec_free_iodata(struct crystalhd_adp *adp,
+				struct crystalhd_ioctl_data *iodata, bool isr)
 {
 	unsigned long flags = 0;
 
@@ -156,7 +157,7 @@
 	if (rc) {
 		BCMLOG_ERR("failed to pull add_cdata sz:%x ua_off:%x\n",
 			   io->add_cdata_sz, (unsigned int)ua_off);
-		kfree(io->add_cdata);
+		vfree(io->add_cdata);
 		io->add_cdata = NULL;
 		return -ENODATA;
 	}
@@ -627,7 +628,7 @@
 }
 
 #ifdef CONFIG_PM
-int chd_dec_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+static int chd_dec_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct crystalhd_adp *adp;
 	struct crystalhd_ioctl_data *temp;
@@ -661,7 +662,7 @@
 	return 0;
 }
 
-int chd_dec_pci_resume(struct pci_dev *pdev)
+static int chd_dec_pci_resume(struct pci_dev *pdev)
 {
 	struct crystalhd_adp *adp;
 	enum BC_STATUS sts = BC_STS_SUCCESS;
diff --git a/drivers/staging/cxt1e1/comet.c b/drivers/staging/cxt1e1/comet.c
index d71aea5..46a0d92 100644
--- a/drivers/staging/cxt1e1/comet.c
+++ b/drivers/staging/cxt1e1/comet.c
@@ -145,10 +145,8 @@
     /* Enable 8 out of 10 validation */
 	 /* t1RBOC enable(BOC:BitOriented Code) */
 	pci_write_32((u_int32_t *) &comet->t1_rboc_ena, 0x00);
-	if (isT1mode)
-	{
-
-	/* IBCD cfg: aka Inband Code Detection ** loopback code length set to */
+	if (isT1mode) {
+		/* IBCD cfg: aka Inband Code Detection ** loopback code length set to */
 		/* 6 bit down, 5 bit up (assert) */
 		pci_write_32((u_int32_t *) &comet->ibcd_cfg, 0x04);
 		/* line loopback activate pattern */
@@ -353,7 +351,7 @@
 	/* RLPS Configuration Status */
 	pci_write_32((u_int32_t *) &comet->rlps_cfgsts, 0x11);
 	if (isT1mode)
-		 /* ? */
+		/* ? */
 		pci_write_32((u_int32_t *) &comet->rlps_alos_thresh, 0x55);
 	else
 		/* ? */
@@ -452,7 +450,7 @@
 	volatile u_int32_t value;
 
 	for (ramaddr = 0; ramaddr < 256; ramaddr++) {
-	/*** the following lines are per Errata 7, 2.5 ***/
+		/*** the following lines are per Errata 7, 2.5 ***/
 		{
 		/* Set up for a read operation */
 		pci_write_32((u_int32_t *) &comet->rlps_eq_rwsel, 0x80);
diff --git a/drivers/staging/cxt1e1/comet.h b/drivers/staging/cxt1e1/comet.h
index e06da4a..03b9bb7 100644
--- a/drivers/staging/cxt1e1/comet.h
+++ b/drivers/staging/cxt1e1/comet.h
@@ -338,7 +338,7 @@
 
 #ifdef __KERNEL__
 extern void
-init_comet (void *, comet_t *, u_int32_t, int, u_int8_t);
+init_comet(void *, comet_t *, u_int32_t, int, u_int8_t);
 #endif
 
 #endif                          /* _INC_COMET_H_ */
diff --git a/drivers/staging/cxt1e1/hwprobe.c b/drivers/staging/cxt1e1/hwprobe.c
index 53e9237..02b4f8f 100644
--- a/drivers/staging/cxt1e1/hwprobe.c
+++ b/drivers/staging/cxt1e1/hwprobe.c
@@ -157,7 +157,7 @@
         hi->pci_slot = 0xff;
         hi->pci_pin[0] = 0;
         hi->pci_pin[1] = 0;
-        hi->ndev = 0;
+        hi->ndev = NULL;
         hi->addr[0] = 0L;
         hi->addr[1] = 0L;
         hi->addr_mapped[0] = 0L;
@@ -309,7 +309,7 @@
     if (!found)
     {
         pr_warning("No boards found\n");
-        return ENODEV;
+        return -ENODEV;
     }
     /* sanity check for consistent hardware found */
     for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
@@ -318,7 +318,7 @@
         {
             pr_warning("%s: something very wrong with pci_get_device\n",
                        hi->devname);
-            return EIO;
+            return -EIO;
         }
     }
     /* bring board's memory regions on/line */
@@ -328,12 +328,12 @@
             break;
         for (j = 0; j < 2; j++)
         {
-            if (request_mem_region (hi->addr[j], hi->len[j], hi->devname) == 0)
+	    if (!request_mem_region (hi->addr[j], hi->len[j], hi->devname))
             {
                 pr_warning("%s: memory in use, addr=0x%lx, len=0x%lx ?\n",
                            hi->devname, hi->addr[j], hi->len[j]);
                 cleanup_ioremap ();
-                return ENOMEM;
+                return -ENOMEM;
             }
             hi->addr_mapped[j] = (unsigned long) ioremap (hi->addr[j], hi->len[j]);
             if (!hi->addr_mapped[j])
@@ -341,7 +341,7 @@
                 pr_warning("%s: ioremap fails, addr=0x%lx, len=0x%lx ?\n",
                            hi->devname, hi->addr[j], hi->len[j]);
                 cleanup_ioremap ();
-                return ENOMEM;
+                return -ENOMEM;
             }
 #ifdef SBE_MAP_DEBUG
             pr_warning("%s: io remapped from phys %x to virt %x\n",
@@ -365,7 +365,7 @@
                        hi->devname, i, hi->pci_slot);
             cleanup_devs ();
             cleanup_ioremap ();
-            return EIO;
+            return -EIO;
         }
         pci_set_master (hi->pdev[0]);
         pci_set_master (hi->pdev[1]);
diff --git a/drivers/staging/cxt1e1/linux.c b/drivers/staging/cxt1e1/linux.c
index 142691c..9b48373 100644
--- a/drivers/staging/cxt1e1/linux.c
+++ b/drivers/staging/cxt1e1/linux.c
@@ -133,7 +133,7 @@
     mch_t      *ch;
 
     ch = c4_find_chan (channum);
-    return ch ? ch->user : 0;
+    return ch ? ch->user : NULL;
 }
 
 
@@ -230,7 +230,7 @@
             __func__, name, pi->portnum); /* RLD DEBUG */
 #endif
     if (!(pi->wq_port = create_singlethread_workqueue (name)))
-        return ENOMEM;
+        return -ENOMEM;
     return 0;                       /* success */
 }
 
@@ -245,7 +245,7 @@
     {
         destroy_workqueue (pi->wq_port);        /* this also calls
                                                  * flush_workqueue() */
-        pi->wq_port = 0;
+        pi->wq_port = NULL;
     }
 }
 
@@ -420,7 +420,7 @@
     int         ret;
 
     if (c4_find_chan (cp->channum))
-        return 0;                   /* channel already exists */
+        return NULL;                   /* channel already exists */
 
     {
         struct c4_priv *priv;
@@ -430,14 +430,14 @@
         if (!priv)
         {
             pr_warning("%s: no memory for net_device !\n", ci->devname);
-            return 0;
+	    return NULL;
         }
         dev = alloc_hdlcdev (priv);
         if (!dev)
         {
             pr_warning("%s: no memory for hdlc_device !\n", ci->devname);
             OS_kfree (priv);
-            return 0;
+	    return NULL;
         }
         priv->ci = ci;
         priv->channum = cp->channum;
@@ -496,7 +496,7 @@
             pr_info("%s: create_chan[%d] registration error = %d.\n",
                     ci->devname, cp->channum, ret);
         free_netdev (dev);          /* cleanup */
-        return 0;                   /* failed to register */
+	return NULL;		/* failed to register */
     }
     return dev;
 }
@@ -744,7 +744,7 @@
         ch = c4_find_chan (channum);
         if (ch == NULL)
             return -ENOENT;
-        ch->user = 0;               /* will be freed, below */
+	ch->user = NULL;	/* will be freed, below */
     }
 
     if (lockit)
@@ -959,7 +959,7 @@
     {
         pr_warning("%s: no memory for struct net_device !\n", hi->devname);
         error_flag = ENOMEM;
-        return 0;
+	return NULL;
     }
     ci = (ci_t *)(netdev_priv(ndev));
     ndev->irq = irq0;
@@ -970,7 +970,7 @@
     c4_list = ci;
     ci->brdno = ci->next ? ci->next->brdno + 1 : 0;
 
-    if (CI == 0)
+    if (!CI)
         CI = ci;                    /* DEBUG, only board 0 usage */
 
     strcpy (ci->devname, hi->devname);
@@ -996,7 +996,7 @@
         OS_kfree (netdev_priv(ndev));
         OS_kfree (ndev);
         error_flag = ENODEV;
-        return 0;
+	return NULL;
     }
     /*************************************************************
      *  int request_irq(unsigned int irq,
@@ -1022,7 +1022,7 @@
         OS_kfree (netdev_priv(ndev));
         OS_kfree (ndev);
         error_flag = EIO;
-        return 0;
+	return NULL;
     }
 #ifdef CONFIG_SBE_PMCC4_NCOMM
     if (request_irq (irq1, &c4_ebus_interrupt, IRQF_SHARED, ndev->name, ndev))
@@ -1033,7 +1033,7 @@
         OS_kfree (netdev_priv(ndev));
         OS_kfree (ndev);
         error_flag = EIO;
-        return 0;
+	return NULL;
     }
 #endif
 
@@ -1091,7 +1091,7 @@
         free_irq (irq0, ndev);
         OS_kfree (netdev_priv(ndev));
         OS_kfree (ndev);
-        return 0;                   /* failure, error_flag is set */
+	return NULL;		/* failure, error_flag is set */
     }
     return ndev;
 }
diff --git a/drivers/staging/cxt1e1/musycc.c b/drivers/staging/cxt1e1/musycc.c
index 52b6d7f..0ba8c3a 100644
--- a/drivers/staging/cxt1e1/musycc.c
+++ b/drivers/staging/cxt1e1/musycc.c
@@ -745,8 +745,8 @@
 #define INT_QUEUE_BOUNDARY  4
 
     regaddr = OS_kmalloc((INT_QUEUE_SIZE + 1) * sizeof(u_int32_t));
-    if (regaddr == 0)
-	return ENOMEM;
+    if (!regaddr)
+	return -ENOMEM;
     ci->iqd_p_saved = regaddr;      /* save orig value for free's usage */
     ci->iqd_p = (u_int32_t *) ((unsigned long) (regaddr + INT_QUEUE_BOUNDARY - 1) &
 			       (~(INT_QUEUE_BOUNDARY - 1)));    /* this calculates
@@ -766,13 +766,13 @@
 #define GROUP_BOUNDARY   0x800
 
 	regaddr = OS_kmalloc(sizeof(struct musycc_groupr) + GROUP_BOUNDARY);
-	if (regaddr == 0) {
+	if (!regaddr) {
 	    for (gchan = 0; gchan < i; gchan++) {
 		pi = &ci->port[gchan];
 		OS_kfree(pi->reg);
-		pi->reg = 0;
+		pi->reg = NULL;
 	    }
-	    return ENOMEM;
+	    return -ENOMEM;
 	}
 	pi->regram_saved = regaddr; /* save orig value for free's usage */
 	pi->regram = (struct musycc_groupr *) ((unsigned long) (regaddr + GROUP_BOUNDARY - 1) &
@@ -839,12 +839,12 @@
     volatile u_int32_t status;
 
     ch = pi->chan[gchan];
-    if (ch == 0 || ch->state != UP) {
+    if (!ch || ch->state != UP) {
 	if (cxt1e1_log_level >= LOG_ERROR)
 	    pr_info("%s: intr: xmit EOM on uninitialized channel %d\n",
 		    pi->up->devname, gchan);
     }
-    if (ch == 0 || ch->mdt == 0)
+    if (!ch || !ch->mdt)
 	return;                     /* note: mdt==0 implies a malloc()
 				     * failure w/in chan_up() routine */
 
@@ -907,7 +907,7 @@
 	ch->txd_irq_srv = md->snext;
 
 	md->data = 0;
-	if (md->mem_token != 0)	{
+	if (md->mem_token)	{
 	    /* upcount channel */
 	    atomic_sub(OS_mem_token_tlen(md->mem_token), &ch->tx_pending);
 	    /* upcount card */
@@ -931,7 +931,7 @@
 #endif                              /*** CONFIG_SBE_WAN256T3_NCOMM ***/
 
 	    OS_mem_token_free_irq(md->mem_token);
-	    md->mem_token = 0;
+	    md->mem_token = NULL;
 	}
 	md->status = 0;
 #ifdef RLD_TXFULL_DEBUG
@@ -1012,13 +1012,13 @@
     u_int32_t   error;
 
     ch = pi->chan[gchan];
-    if (ch == 0 || ch->state != UP) {
+    if (!ch || ch->state != UP) {
 	if (cxt1e1_log_level > LOG_ERROR)
 	    pr_info("%s: intr: receive EOM on uninitialized channel %d\n",
 		    pi->up->devname, gchan);
 	return;
     }
-    if (ch->mdr == 0)
+    if (!ch->mdr)
 	return;                     /* can this happen ? */
 
     for (;;) {
@@ -1566,18 +1566,18 @@
     pi->regram->rmp[gchan] = 0;
     FLUSH_MEM_WRITE();
     for (i = 0; i < ch->txd_num; i++)
-	if (ch->mdt[i].mem_token != 0)
+	if (ch->mdt[i].mem_token)
 	    OS_mem_token_free(ch->mdt[i].mem_token);
 
     for (i = 0; i < ch->rxd_num; i++)
-	if (ch->mdr[i].mem_token != 0)
+	if (ch->mdr[i].mem_token)
 	    OS_mem_token_free(ch->mdr[i].mem_token);
 
     OS_kfree(ch->mdr);
-    ch->mdr = 0;
+    ch->mdr = NULL;
     ch->rxd_num = 0;
     OS_kfree(ch->mdt);
-    ch->mdt = 0;
+    ch->mdt = NULL;
     ch->txd_num = 0;
 
     musycc_update_timeslots(pi);
@@ -1746,7 +1746,7 @@
 #endif
 	    u |= (PADFILL_ENABLE | (ch->p.pad_fill_count << EXTRA_FLAGS));
 	}
-	md->mem_token = len ? 0 : mem_token;    /* Fill in mds on last
+	md->mem_token = len ? NULL : mem_token;    /* Fill in mds on last
 						 * segment, others set ZERO
 						 * so that entire token is
 						 * removed ONLY when ALL
diff --git a/drivers/staging/cxt1e1/pmcc4_drv.c b/drivers/staging/cxt1e1/pmcc4_drv.c
index 2383c60..4028ea1 100644
--- a/drivers/staging/cxt1e1/pmcc4_drv.c
+++ b/drivers/staging/cxt1e1/pmcc4_drv.c
@@ -70,7 +70,7 @@
 #endif
 
 int         drvr_state = SBE_DRVR_INIT;
-ci_t       *c4_list = 0;
+ci_t       *c4_list = NULL;
 ci_t       *CI;                 /* dummy pointer to board ZEROE's data -
                                  * DEBUG USAGE */
 
@@ -119,7 +119,7 @@
                         return ch;
                 }
             }
-    return 0;
+    return NULL;
 }
 
 
@@ -145,7 +145,7 @@
         pr_warning("failed CI malloc, size %u.\n",
                    (unsigned int) sizeof (ci_t));
 
-    if (CI == 0)
+    if (!CI)
         CI = ci;                    /* DEBUG, only board 0 usage */
     return ci;
 }
@@ -831,7 +831,7 @@
 {
     mpi_t      *pi;
     volatile u_int32_t *dph;    /* hardware implemented register */
-    u_int32_t  *dpr = 0;        /* RAM image of registers for group command
+    u_int32_t *dpr = NULL;	/* RAM image of registers for group command
                                  * usage */
     int         offset = mcp->offset % 0x800;   /* group relative address
                                                  * offset, mcp->portnum is
@@ -1060,7 +1060,7 @@
     }
 
     /* save off interface assignments which bound a board */
-    if (ci->first_if == 0)          /* first channel registered is assumed to
+    if (!ci->first_if)		/* first channel registered is assumed to
                                      * be the lowest channel */
     {
         ci->first_if = ci->last_if = user;
@@ -1392,7 +1392,7 @@
         md->status = HOST_TX_OWNED; /* Host owns TX descriptor ** CODING
                                      * NOTE: HOST_TX_OWNED = 0 so no need to
                                      * byteSwap */
-        md->mem_token = 0;
+        md->mem_token = NULL;
         md->data = 0;
         if (i == (txnum - 1))
         {
@@ -1448,10 +1448,10 @@
         OS_mem_token_free (ch->mdr[i].mem_token);
     }
     OS_kfree (ch->mdt);
-    ch->mdt = 0;
+    ch->mdt = NULL;
     ch->txd_num = 0;
     OS_kfree (ch->mdr);
-    ch->mdr = 0;
+    ch->mdr = NULL;
     ch->rxd_num = 0;
     ch->state = DOWN;
     return ENOBUFS;
diff --git a/drivers/staging/cxt1e1/sbecom_inline_linux.h b/drivers/staging/cxt1e1/sbecom_inline_linux.h
index 3c6d1c0..ba3ff3e 100644
--- a/drivers/staging/cxt1e1/sbecom_inline_linux.h
+++ b/drivers/staging/cxt1e1/sbecom_inline_linux.h
@@ -73,7 +73,7 @@
     if (!skb)
     {
         //pr_warning("no mem in OS_mem_token_alloc !\n");
-        return 0;
+        return NULL;
     }
     return skb;
 }
@@ -103,7 +103,7 @@
 static inline void *
 OS_mem_token_next (void *token)
 {
-    return 0;
+    return NULL;
 }
 
 
diff --git a/drivers/staging/cxt1e1/sbecrc.c b/drivers/staging/cxt1e1/sbecrc.c
index 87512a5..81fa8a3 100644
--- a/drivers/staging/cxt1e1/sbecrc.c
+++ b/drivers/staging/cxt1e1/sbecrc.c
@@ -88,7 +88,7 @@
 	u_int32_t initialCrc,      /* starting CRC */
 	u_int32_t *result)
 {
-	u_int32_t     *tbl = 0;
+	u_int32_t     *tbl = NULL;
 	u_int32_t      temp1, temp2, crc;
 
 	/*
@@ -102,7 +102,7 @@
 		genCrcTable(tbl);
 #else
 		tbl = (u_int32_t *) OS_kmalloc(CRC_TABLE_ENTRIES * sizeof(u_int32_t));
-		if (tbl == 0) {
+		if (!tbl) {
 			*result = 0;   /* dummy up return value due to malloc
 					* failure */
 			return;
diff --git a/drivers/staging/cxt1e1/sbeid.c b/drivers/staging/cxt1e1/sbeid.c
index 791993f..6ec51bc 100644
--- a/drivers/staging/cxt1e1/sbeid.c
+++ b/drivers/staging/cxt1e1/sbeid.c
@@ -22,7 +22,7 @@
 char       *
 sbeid_get_bdname (ci_t *ci)
 {
-    char       *np = 0;
+    char       *np = NULL;
 
     switch (ci->brd_id)
     {
diff --git a/drivers/staging/cxt1e1/sbeproc.c b/drivers/staging/cxt1e1/sbeproc.c
index 9361dd8..353c001 100644
--- a/drivers/staging/cxt1e1/sbeproc.c
+++ b/drivers/staging/cxt1e1/sbeproc.c
@@ -44,7 +44,7 @@
 static void sbecom_proc_get_brdinfo(ci_t *ci, struct sbe_brd_info *bip)
 {
 	hdw_info_t *hi = &hdw_info[ci->brdno];
-	u_int8_t *bsn = 0;
+	u_int8_t *bsn = NULL;
 
 	switch (hi->promfmt)
 	{
diff --git a/drivers/staging/cxt1e1/sbew_ioc.h b/drivers/staging/cxt1e1/sbew_ioc.h
index ce9b15c..e1e5bfc 100644
--- a/drivers/staging/cxt1e1/sbew_ioc.h
+++ b/drivers/staging/cxt1e1/sbew_ioc.h
@@ -39,21 +39,21 @@
  */
 
 #define SBE_IOC_LOGLEVEL       _IOW(SBE_IOC_MAGIC, 0x00, int)
-#define SBE_IOC_CHAN_NEW       _IOW(SBE_IOC_MAGIC, 0x01,int)    /* unused */
-#define SBE_IOC_CHAN_UP        _IOW(SBE_IOC_MAGIC, 0x02,int)    /* unused */
-#define SBE_IOC_CHAN_DOWN      _IOW(SBE_IOC_MAGIC, 0x03,int)    /* unused */
-#define SBE_IOC_CHAN_GET       _IOWR(SBE_IOC_MAGIC,0x04, struct sbecom_chan_param)
+#define SBE_IOC_CHAN_NEW       _IOW(SBE_IOC_MAGIC, 0x01, int)    /* unused */
+#define SBE_IOC_CHAN_UP        _IOW(SBE_IOC_MAGIC, 0x02, int)    /* unused */
+#define SBE_IOC_CHAN_DOWN      _IOW(SBE_IOC_MAGIC, 0x03, int)    /* unused */
+#define SBE_IOC_CHAN_GET       _IOWR(SBE_IOC_MAGIC, 0x04, struct sbecom_chan_param)
 #define SBE_IOC_CHAN_SET       _IOW(SBE_IOC_MAGIC, 0x05, struct sbecom_chan_param)
-#define SBE_IOC_CHAN_GET_STAT  _IOWR(SBE_IOC_MAGIC,0x06, struct sbecom_chan_stats)
+#define SBE_IOC_CHAN_GET_STAT  _IOWR(SBE_IOC_MAGIC, 0x06, struct sbecom_chan_stats)
 #define SBE_IOC_CHAN_DEL_STAT  _IOW(SBE_IOC_MAGIC, 0x07, int)
 #define SBE_IOC_PORTS_ENABLE   _IOW(SBE_IOC_MAGIC, 0x0A, int)
-#define SBE_IOC_PORT_GET       _IOWR(SBE_IOC_MAGIC,0x0C, struct sbecom_port_param)
+#define SBE_IOC_PORT_GET       _IOWR(SBE_IOC_MAGIC, 0x0C, struct sbecom_port_param)
 #define SBE_IOC_PORT_SET       _IOW(SBE_IOC_MAGIC, 0x0D, struct sbecom_port_param)
-#define SBE_IOC_READ_VEC       _IOWR(SBE_IOC_MAGIC,0x10, struct sbecom_wrt_vec)
-#define SBE_IOC_WRITE_VEC      _IOWR(SBE_IOC_MAGIC,0x11, struct sbecom_wrt_vec)
+#define SBE_IOC_READ_VEC       _IOWR(SBE_IOC_MAGIC, 0x10, struct sbecom_wrt_vec)
+#define SBE_IOC_WRITE_VEC      _IOWR(SBE_IOC_MAGIC, 0x11, struct sbecom_wrt_vec)
 #define SBE_IOC_GET_SN         _IOR(SBE_IOC_MAGIC, 0x12, u_int32_t)
 #define SBE_IOC_RESET_DEV      _IOW(SBE_IOC_MAGIC, 0x13, int)
-#define SBE_IOC_FRAMER_GET     _IOWR(SBE_IOC_MAGIC,0x14, struct sbecom_framer_param)
+#define SBE_IOC_FRAMER_GET     _IOWR(SBE_IOC_MAGIC, 0x14, struct sbecom_framer_param)
 #define SBE_IOC_FRAMER_SET     _IOW(SBE_IOC_MAGIC, 0x15, struct sbecom_framer_param)
 #define SBE_IOC_CARD_GET       _IOR(SBE_IOC_MAGIC, 0x20, struct sbecom_card_param)
 #define SBE_IOC_CARD_SET       _IOW(SBE_IOC_MAGIC, 0x21, struct sbecom_card_param)
@@ -61,13 +61,13 @@
 #define SBE_IOC_CARD_DEL_STAT  _IO(SBE_IOC_MAGIC,  0x23)
 #define SBE_IOC_CARD_CHAN_STAT _IOR(SBE_IOC_MAGIC, 0x24, struct sbecom_chan_stats)
 #define SBE_IOC_CARD_BLINK     _IOW(SBE_IOC_MAGIC, 0x30, int)
-#define SBE_IOC_DRVINFO_GET    _IOWR(SBE_IOC_MAGIC,0x31, struct sbe_drv_info)
+#define SBE_IOC_DRVINFO_GET    _IOWR(SBE_IOC_MAGIC, 0x31, struct sbe_drv_info)
 #define SBE_IOC_BRDINFO_GET    _IOR(SBE_IOC_MAGIC, 0x32, struct sbe_brd_info)
-#define SBE_IOC_IID_GET        _IOWR(SBE_IOC_MAGIC,0x33, struct sbe_iid_info)
+#define SBE_IOC_IID_GET        _IOWR(SBE_IOC_MAGIC, 0x33, struct sbe_iid_info)
 #define SBE_IOC_BRDADDR_GET    _IOWR(SBE_IOC_MAGIC, 0x34, struct sbe_brd_addr)
 
 #ifdef NOT_YET_COMMON
-#define SBE_IOC_TSIOC_GET      _IOWR(SBE_IOC_MAGIC,0x16, struct wanc1t3_ts_param)
+#define SBE_IOC_TSIOC_GET      _IOWR(SBE_IOC_MAGIC, 0x16, struct wanc1t3_ts_param)
 #define SBE_IOC_TSIOC_SET      _IOW(SBE_IOC_MAGIC, 0x17, struct wanc1t3_ts_param)
 #endif
 
diff --git a/drivers/staging/dgap/Makefile b/drivers/staging/dgap/Makefile
index 9f1fce1..3abe8d2 100644
--- a/drivers/staging/dgap/Makefile
+++ b/drivers/staging/dgap/Makefile
@@ -1,5 +1,3 @@
-EXTRA_CFLAGS += -DDG_NAME=\"dgap-1.3-16\" -DDG_PART=\"40002347_C\"
-
 obj-$(CONFIG_DGAP) += dgap.o
 
 
diff --git a/drivers/staging/dgap/dgap_downld.h b/drivers/staging/dgap/dgap_downld.h
index f79e65c..271ac19 100644
--- a/drivers/staging/dgap/dgap_downld.h
+++ b/drivers/staging/dgap/dgap_downld.h
@@ -35,7 +35,7 @@
 struct fepimg {
     int type;				/* board type */
     int	len;				/* length of image */
-    char fepimage[1];			/* begining of image */
+    char fepimage[1];			/* beginning of image */
 };
 
 struct downldio {
diff --git a/drivers/staging/dgap/dgap_driver.c b/drivers/staging/dgap/dgap_driver.c
index 40ef785..4c1515e 100644
--- a/drivers/staging/dgap/dgap_driver.c
+++ b/drivers/staging/dgap/dgap_driver.c
@@ -32,16 +32,12 @@
 
 
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>	/* For udelay */
 #include <linux/slab.h>
 #include <asm/uaccess.h>	/* For copy_from_user/copy_to_user */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
 #include <linux/sched.h>
-#endif
 
 #include "dgap_driver.h"
 #include "dgap_pci.h"
@@ -420,8 +416,7 @@
 		unregister_chrdev(DIGI_DGAP_MAJOR, "dgap");
 	}
 
-	if (dgap_config_buf)
-		kfree(dgap_config_buf);
+	kfree(dgap_config_buf);
 
 	for (i = 0; i < dgap_NumBoards; ++i) {
 		dgap_remove_ports_sysfiles(dgap_Board[i]);
@@ -488,10 +483,8 @@
 		}
 	}
 
-	if (brd->flipbuf)
-		kfree(brd->flipbuf);
-	if (brd->flipflagbuf)
-		kfree(brd->flipflagbuf);
+	kfree(brd->flipbuf);
+	kfree(brd->flipflagbuf);
 
 	dgap_Board[brd->boardnum] = NULL;
 
diff --git a/drivers/staging/dgap/dgap_driver.h b/drivers/staging/dgap/dgap_driver.h
index b1cf489..7d631e8 100644
--- a/drivers/staging/dgap/dgap_driver.h
+++ b/drivers/staging/dgap/dgap_driver.h
@@ -46,13 +46,16 @@
 /*
  * Driver identification, error and debugging statments
  *
- * In theory, you can change all occurances of "digi" in the next
+ * In theory, you can change all occurrences of "digi" in the next
  * three lines, and the driver printk's will all automagically change.
  *
  * APR((fmt, args, ...));	Always prints message
  * DPR((fmt, args, ...));	Only prints if DGAP_TRACER is defined at
  *				  compile time and dgap_debug!=0
  */
+#define	DG_NAME		"dgap-1.3-16"
+#define	DG_PART		"40002347_C"
+
 #define	PROCSTR		"dgap"			/* /proc entries	 */
 #define	DEVSTR		"/dev/dg/dgap"		/* /dev entries		 */
 #define	DRVSTR		"dgap"			/* Driver name string 
diff --git a/drivers/staging/dgap/dgap_fep5.c b/drivers/staging/dgap/dgap_fep5.c
index 4464f02..794cf9d 100644
--- a/drivers/staging/dgap/dgap_fep5.c
+++ b/drivers/staging/dgap/dgap_fep5.c
@@ -134,7 +134,7 @@
 		dgap_Board[i]->flipflagbuf = dgap_driver_kzmalloc(MYFLIPLEN, GFP_ATOMIC);
 	}
 
-	return (rc);
+	return rc;
 }
 
 
@@ -150,14 +150,14 @@
 	int n = U2BSIZE;
 
 	if (!brd || brd->magic != DGAP_BOARD_MAGIC)
-		return(-EFAULT);
+		return -EFAULT;
 
 	while (len) {
 		if (n > len)
 			n = len;
 
 		if (copy_from_user((char *) &buf, from_addr, n) == -1 ) {
-			return(-EFAULT);
+			return -EFAULT;
 		}
 
 		/* Copy data from buffer to card memory */
@@ -169,7 +169,7 @@
 		from_addr += n;   
 		n = U2BSIZE;
         }
-	return(0);
+	return 0;
 }
 
 
@@ -1155,20 +1155,20 @@
 	uint value = 0;
 
 	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) {
-		return (0);
+		return 0;
 	}
 
 	if (!ch->ch_bd || ch->ch_bd->magic != DGAP_BOARD_MAGIC) {
-		return (0);
+		return 0;
 	}
 
 	if (!(ch->ch_bd->bd_flags & BD_FEP5PLUS))
-		return (0);
+		return 0;
 
 	vaddr = ch->ch_bd->re_map_membase;
 
 	if (!vaddr)
-		return (0);
+		return 0;
 
 	/*
 	 * Go get from fep mem, what the fep
@@ -1178,7 +1178,7 @@
 		(ch->ch_portnum * 0x28) + LINE_SPEED));
 
 	value = readw(vaddr + offset);
-	return (value);
+	return value;
 }
 
 
@@ -1229,29 +1229,24 @@
 	uchar	mval;
 	uchar	hflow;
 
-	if (!tty || tty->magic != TTY_MAGIC) {
-		return (-ENXIO);
-	}
+	if (!tty || tty->magic != TTY_MAGIC)
+		return -ENXIO;
 
 	un = (struct un_t *) tty->driver_data;
-	if (!un || un->magic != DGAP_UNIT_MAGIC) {
-		return (-ENXIO);
-	}
+	if (!un || un->magic != DGAP_UNIT_MAGIC)
+		return -ENXIO;
 
 	ch = un->un_ch;
-	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) {
-		return (-ENXIO);
-	}
+	if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
+		return -ENXIO;
 
 	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGAP_BOARD_MAGIC) {
-		return (-ENXIO);
-	}
+	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
+		return -ENXIO;
 
         bs = ch->ch_bs;
-	if (bs == 0) {
-		return (-ENXIO);
-	}
+	if (!bs)
+		return -ENXIO;
 
 	DPR_PARAM(("param start: tdev: %x cflags: %x oflags: %x iflags: %x\n",
 		ch->ch_tun.un_dev, ch->ch_c_cflag, ch->ch_c_oflag, ch->ch_c_iflag));
@@ -1558,7 +1553,7 @@
 
 	DPR_PARAM(("param finish\n"));
 
-	return (0);
+	return 0;
 }
 
 
@@ -1675,7 +1670,7 @@
 	int		b1;
 
 	if (!bd || bd->magic != DGAP_BOARD_MAGIC)
-		return (-ENXIO);
+		return -ENXIO;
 
 	DGAP_LOCK(bd->bd_lock, lock_flags);
 
@@ -1683,7 +1678,7 @@
 
 	if (!vaddr) {
 		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return (-ENXIO);
+		return -ENXIO;
 	}
 
 	eaddr = (struct ev_t *) (vaddr + EVBUF);
@@ -1701,7 +1696,7 @@
 		DPR_EVENT(("should be calling xxfail %d\n", __LINE__));
 		/* Let go of board lock */
 		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return (-ENXIO);
+		return -ENXIO;
 	}
 
 	/*
@@ -1949,5 +1944,5 @@
 	writew(tail, &(eaddr->ev_tail));
 	DGAP_UNLOCK(bd->bd_lock, lock_flags);
 
-	return (0);
+	return 0;
 }               
diff --git a/drivers/staging/dgap/dgap_fep5.h b/drivers/staging/dgap/dgap_fep5.h
index 3a12ba5..c9abc40 100644
--- a/drivers/staging/dgap/dgap_fep5.h
+++ b/drivers/staging/dgap/dgap_fep5.h
@@ -211,7 +211,7 @@
 #define SIFLAG		0xea		/* Set UNIX iflags		*/
 #define SFLOWC		0xeb		/* Set flow control characters	*/
 #define STLOW		0xec		/* Set transmit low water mark	*/
-#define RPAUSE		0xee		/* Pause recieve		*/
+#define RPAUSE		0xee		/* Pause receive		*/
 #define RRESUME		0xef		/* Resume receive		*/  
 #define CHRESET		0xf0		/* Reset Channel		*/
 #define BUFSETALL	0xf2		/* Set Tx & Rx buffer size avail*/
diff --git a/drivers/staging/dgap/dgap_kcompat.h b/drivers/staging/dgap/dgap_kcompat.h
index 8ebf4b7..0dc2404 100644
--- a/drivers/staging/dgap/dgap_kcompat.h
+++ b/drivers/staging/dgap/dgap_kcompat.h
@@ -28,11 +28,6 @@
 #ifndef __DGAP_KCOMPAT_H
 #define __DGAP_KCOMPAT_H
 
-# ifndef KERNEL_VERSION
-#  define KERNEL_VERSION(a,b,c)  (((a) << 16) + ((b) << 8) + (c))
-# endif
-
-
 #if !defined(TTY_FLIPBUF_SIZE)
 # define TTY_FLIPBUF_SIZE 512
 #endif
@@ -66,28 +61,4 @@
 		module_param(VAR, long, PERM); \
 		MODULE_PARM_DESC(VAR, DESC);
 
-
-
-
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
-
-
-
-
-/* NOTHING YET */
-
-
-
-
-# else
-
-
-
-# error "this driver does not support anything below the 2.6.27 kernel series."
-
-
-
-# endif
-
 #endif /* ! __DGAP_KCOMPAT_H */
diff --git a/drivers/staging/dgap/dgap_parse.c b/drivers/staging/dgap/dgap_parse.c
index 5497e6d..ff9d194 100644
--- a/drivers/staging/dgap/dgap_parse.c
+++ b/drivers/staging/dgap/dgap_parse.c
@@ -904,7 +904,7 @@
 /*
  * dgap_sindex: much like index(), but it looks for a match of any character in
  * the group, and returns that position.  If the first character is a ^, then
- * this will match the first occurence not in that group.
+ * this will match the first occurrence not in that group.
  */
 static char *dgap_sindex (char *string, char *group)
 {
@@ -1013,8 +1013,10 @@
 static struct cnode *dgap_newnode(int t)
 {
 	struct cnode *n;
-	if ( (n = (struct cnode *) kmalloc(sizeof(struct cnode ), GFP_ATOMIC) ) != NULL) {
-		memset( (char *)n, 0, sizeof(struct cnode ) );
+
+	n = kmalloc(sizeof(struct cnode), GFP_ATOMIC);
+	if (n != NULL) {
+		memset((char *)n, 0, sizeof(struct cnode));
 		n->type = t;
 	}
 	return(n);
@@ -1150,7 +1152,7 @@
 
 /*
  * Given a specific type of board, if found, detached link and 
- * returns the first occurance in the list.
+ * returns the first occurrence in the list.
  */
 struct cnode *dgap_find_config(int type, int bus, int slot)
 {
diff --git a/drivers/staging/dgap/dgap_sysfs.c b/drivers/staging/dgap/dgap_sysfs.c
index 94da06f..7f4ec9a 100644
--- a/drivers/staging/dgap/dgap_sysfs.c
+++ b/drivers/staging/dgap/dgap_sysfs.c
@@ -395,7 +395,7 @@
 
 	if (!d)
 		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGAP_UNIT_MAGIC)
 		return (0);
 	ch = un->un_ch;
@@ -420,7 +420,7 @@
 
 	if (!d)
 		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGAP_UNIT_MAGIC)
 		return (0);
 	ch = un->un_ch;
@@ -445,7 +445,7 @@
 
 	if (!d)
 		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGAP_UNIT_MAGIC)
 		return (0);
 	ch = un->un_ch;
@@ -479,7 +479,7 @@
 
 	if (!d)
 		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGAP_UNIT_MAGIC)
 		return (0);
 	ch = un->un_ch;
@@ -504,7 +504,7 @@
 
 	if (!d)
 		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGAP_UNIT_MAGIC)
 		return (0);
 	ch = un->un_ch;
@@ -529,7 +529,7 @@
 
 	if (!d)
 		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGAP_UNIT_MAGIC)
 		return (0);
 	ch = un->un_ch;
@@ -554,7 +554,7 @@
 
 	if (!d)
 		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGAP_UNIT_MAGIC)
 		return (0);
 	ch = un->un_ch;
@@ -579,7 +579,7 @@
 
 	if (!d)
 		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGAP_UNIT_MAGIC)
 		return (0);
 	ch = un->un_ch;
@@ -604,7 +604,7 @@
 
 	if (!d)
 		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGAP_UNIT_MAGIC)
 		return (0);
 	ch = un->un_ch;
@@ -629,7 +629,7 @@
 
 	if (!d)
 		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGAP_UNIT_MAGIC)
 		return (0);
 	ch = un->un_ch;
@@ -661,7 +661,7 @@
 
 	if (!d)
 		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGAP_UNIT_MAGIC)
 		return (0);
 	ch = un->un_ch;
diff --git a/drivers/staging/dgap/dgap_tty.c b/drivers/staging/dgap/dgap_tty.c
index b906db3..2a7a372 100644
--- a/drivers/staging/dgap/dgap_tty.c
+++ b/drivers/staging/dgap/dgap_tty.c
@@ -249,7 +249,7 @@
 
 	/*
 	 * If we're doing transparent print, we have to do all of the above
-	 * again, seperately so we don't get the LD confused about what major
+	 * again, separately so we don't get the LD confused about what major
 	 * we are when we get into the dgap_tty_open() routine.
 	 */
 	brd->PrintDriver = alloc_tty_driver(MAXPORTS);
@@ -497,10 +497,8 @@
  */
 void dgap_tty_post_uninit(void)
 {
-	if (dgap_TmpWriteBuf) {
-		kfree(dgap_TmpWriteBuf);
-		dgap_TmpWriteBuf = NULL;
-	}
+	kfree(dgap_TmpWriteBuf);
+	dgap_TmpWriteBuf = NULL;
 }
 
 
@@ -522,10 +520,8 @@
 			tty_unregister_device(brd->SerialDriver, i);
 		}
 		tty_unregister_driver(brd->SerialDriver);
-		if (brd->SerialDriver->ttys) {
-			kfree(brd->SerialDriver->ttys);
-			brd->SerialDriver->ttys = NULL;
-		}
+		kfree(brd->SerialDriver->ttys);
+		brd->SerialDriver->ttys = NULL;
 		put_tty_driver(brd->SerialDriver);
 		brd->dgap_Major_Serial_Registered = FALSE;
 	}
@@ -538,10 +534,8 @@
 			tty_unregister_device(brd->PrintDriver, i);
 		}
 		tty_unregister_driver(brd->PrintDriver);
-		if (brd->PrintDriver->ttys) {
-			kfree(brd->PrintDriver->ttys);
-			brd->PrintDriver->ttys = NULL;
-	        }
+		kfree(brd->PrintDriver->ttys);
+		brd->PrintDriver->ttys = NULL;
 		put_tty_driver(brd->PrintDriver);
 		brd->dgap_Major_TransparentPrint_Registered = FALSE;
 	}
@@ -601,7 +595,7 @@
 		/*
 		 *  Loop while data remains.
 		 */
-		while (nbuf > 0 && ch->ch_sniff_buf != 0) {
+		while (nbuf > 0 && ch->ch_sniff_buf) {
 			/*
 			 *  Determine the amount of available space left in the
 			 *  buffer.  If there's none, wait until some appears.
@@ -1069,7 +1063,7 @@
 
 	DGAP_LOCK(brd->bd_lock, lock_flags);
 
-	/* The wait above should guarentee this cannot happen */
+	/* The wait above should guarantee this cannot happen */
 	if (brd->state != BOARD_READY) {
 		DGAP_UNLOCK(brd->bd_lock, lock_flags);
 		return -ENXIO;
@@ -1113,9 +1107,10 @@
 		MAJOR(tty_devnum(tty)), MINOR(tty_devnum(tty)), un, brd->name));
 
 	/*
-	 * Error if channel info pointer is 0.
+	 * Error if channel info pointer is NULL.
 	 */
-	if ((bs = ch->ch_bs) == 0) {
+	bs = ch->ch_bs;
+	if (!bs) {
 		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
 		DGAP_UNLOCK(brd->bd_lock, lock_flags);
 		DPR_OPEN(("%d BS is 0!\n", __LINE__));
@@ -3513,10 +3508,6 @@
 			return(-EINVAL);
 		}
 
-		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-		DGAP_UNLOCK(bd->bd_lock, lock_flags);
-		return(-ENOIOCTLCMD);
-
 	case DIGI_GETA:
 		/* get information for ditty */
 		DGAP_UNLOCK(ch->ch_lock, lock_flags2);
@@ -3586,12 +3577,4 @@
 
 		return(-ENOIOCTLCMD);
 	}
-
-	DGAP_UNLOCK(ch->ch_lock, lock_flags2);
-	DGAP_UNLOCK(bd->bd_lock, lock_flags);
-
-	DPR_IOCTL(("dgap_tty_ioctl end - cmd %s (%x), arg %lx\n", 
-		dgap_ioctl_name(cmd), cmd, arg));
-                        
-	return(0);
 }
diff --git a/drivers/staging/dgap/digi.h b/drivers/staging/dgap/digi.h
index 651e2e5..bcea4f7 100644
--- a/drivers/staging/dgap/digi.h
+++ b/drivers/staging/dgap/digi.h
@@ -203,9 +203,9 @@
 	unsigned long	shrink_buf_vaddr;	/* Virtual address of board */
 	unsigned long	shrink_buf_phys;	/* Physical address of board */
 	unsigned long	shrink_buf_bseg;	/* Amount of board memory */
-	unsigned long	shrink_buf_hseg;	/* '186 Begining of Dual-Port */
+	unsigned long	shrink_buf_hseg;	/* '186 Beginning of Dual-Port */
 
-	unsigned long	shrink_buf_lseg;	/* '186 Begining of freed memory						*/ 
+	unsigned long	shrink_buf_lseg;	/* '186 Beginning of freed memory						*/ 
 	unsigned long	shrink_buf_mseg;	/* Linear address from start of
 						   dual-port were freed memory
 						   begins, host viewpoint. */
diff --git a/drivers/staging/dgap/downld.c b/drivers/staging/dgap/downld.c
index 57dfd6b..638c5da 100644
--- a/drivers/staging/dgap/downld.c
+++ b/drivers/staging/dgap/downld.c
@@ -52,7 +52,7 @@
 void		myperror();
 
 /*
-**  This structure is used to keep track of the diferent images available
+**  This structure is used to keep track of the different images available
 **  to give to the driver.  It is arranged so that the things that are
 **  constants or that have defaults are first inthe strucutre to simplify
 **  the table of initializers.
@@ -789,7 +789,7 @@
 /*
 ** myperror()
 **
-**  Same as normal perror(), but places the program name at the begining
+**  Same as normal perror(), but places the program name at the beginning
 **  of the message.
 */
 void myperror(char *s)
diff --git a/drivers/staging/dgnc/dgnc_cls.c b/drivers/staging/dgnc/dgnc_cls.c
index 117e158..fdc1aab 100644
--- a/drivers/staging/dgnc/dgnc_cls.c
+++ b/drivers/staging/dgnc/dgnc_cls.c
@@ -33,7 +33,7 @@
 #include <linux/sched.h>	/* For jiffies, task states */
 #include <linux/interrupt.h>	/* For tasklet and interrupt structs/defines */
 #include <linux/delay.h>	/* For udelay */
-#include <asm/io.h>		/* For read[bwl]/write[bwl] */
+#include <linux/io.h>		/* For read[bwl]/write[bwl] */
 #include <linux/serial.h>	/* For struct async_serial */
 #include <linux/serial_reg.h>	/* For the various UART offsets */
 #include <linux/pci.h>
@@ -43,7 +43,7 @@
 #include "dgnc_tty.h"
 #include "dgnc_trace.h"
 
-static inline void cls_parse_isr(struct board_t *brd, uint port);
+static inline void cls_parse_isr(struct dgnc_board *brd, uint port);
 static inline void cls_clear_break(struct channel_t *ch, int force);
 static inline void cls_set_cts_flow_control(struct channel_t *ch);
 static inline void cls_set_rts_flow_control(struct channel_t *ch);
@@ -53,7 +53,7 @@
 static inline void cls_set_no_input_flow_control(struct channel_t *ch);
 static void cls_parse_modem(struct channel_t *ch, uchar signals);
 static void cls_tasklet(unsigned long data);
-static void cls_vpd(struct board_t *brd);
+static void cls_vpd(struct dgnc_board *brd);
 static void cls_uart_init(struct channel_t *ch);
 static void cls_uart_off(struct channel_t *ch);
 static int cls_drain(struct tty_struct *tty, uint seconds);
@@ -393,7 +393,7 @@
 
 
 /* Parse the ISR register for the specific port */
-static inline void cls_parse_isr(struct board_t *brd, uint port)
+static inline void cls_parse_isr(struct dgnc_board *brd, uint port)
 {
 	struct channel_t *ch;
 	uchar isr = 0;
@@ -417,9 +417,8 @@
 		isr = readb(&ch->ch_cls_uart->isr_fcr);
 
 		/* Bail if no pending interrupt on port */
-		if (isr & UART_IIR_NO_INT)  {
+		if (isr & UART_IIR_NO_INT)
 			break;
-		}
 
 		DPR_INTR(("%s:%d port: %x isr: %x\n", __FILE__, __LINE__, port, isr));
 
@@ -444,9 +443,8 @@
 		}
 
 		/* Received Xoff signal/Special character */
-		if (isr & UART_IIR_XOFF) {
+		if (isr & UART_IIR_XOFF)
 			/* Empty */
-		}
 
 		/* CTS/RTS change of state */
 		if (isr & UART_IIR_CTSRTS) {
@@ -477,28 +475,24 @@
 	uchar uart_ier = 0;
         uint baud = 9600;
 	int quot = 0;
-        struct board_t *bd;
+        struct dgnc_board *bd;
 	struct channel_t *ch;
         struct un_t   *un;
 
-	if (!tty || tty->magic != TTY_MAGIC) {
+	if (!tty || tty->magic != TTY_MAGIC)
 		return;
-	}
 
 	un = (struct un_t *) tty->driver_data;
-	if (!un || un->magic != DGNC_UNIT_MAGIC) {
+	if (!un || un->magic != DGNC_UNIT_MAGIC)
 		return;
-	}
 
 	ch = un->un_ch;
-	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
+	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
 		return;
-	}
 
 	bd = ch->ch_bd;
-	if (!bd || bd->magic != DGNC_BOARD_MAGIC) {
+	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
 		return;
-	}
 
 	DPR_PARAM(("param start: tdev: %x cflags: %x oflags: %x iflags: %x\n",
 		ch->ch_tun.un_dev, ch->ch_c_cflag, ch->ch_c_oflag, ch->ch_c_iflag));
@@ -725,7 +719,7 @@
  */
 static void cls_tasklet(unsigned long data)
 {
-        struct board_t *bd = (struct board_t *) data;
+        struct dgnc_board *bd = (struct dgnc_board *) data;
 	struct channel_t *ch;
 	ulong  lock_flags;
 	int i;
@@ -802,7 +796,7 @@
  */
 static irqreturn_t cls_intr(int irq, void *voidbrd)
 {
-	struct board_t *brd = (struct board_t *) voidbrd;
+	struct dgnc_board *brd = (struct dgnc_board *) voidbrd;
 	uint i = 0;
 	uchar poll_reg;
 	unsigned long lock_flags;
@@ -976,17 +970,17 @@
 	int rc = 0;
 
 	if (!tty || tty->magic != TTY_MAGIC) {
-		return (-ENXIO);
+		return -ENXIO;
 	}
 
 	un = (struct un_t *) tty->driver_data;
 	if (!un || un->magic != DGNC_UNIT_MAGIC) {
-		return (-ENXIO);
+		return -ENXIO;
 	}
 
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
-		return (-ENXIO);
+		return -ENXIO;
 	}
 
 	DGNC_LOCK(ch->ch_lock, lock_flags);
@@ -1002,7 +996,7 @@
 	if (rc)
 		DPR_IOCTL(("%d Drain - User ctrl c'ed\n", __LINE__));
 
-        return (rc);
+        return rc;
 }
 
 
@@ -1305,9 +1299,8 @@
 
 	/* Determine whether the Transmitter is empty or not */
 	if (!(lsr & UART_LSR_TEMT)) {
-		if (ch->ch_flags & CH_TX_FIFO_EMPTY) {
+		if (ch->ch_flags & CH_TX_FIFO_EMPTY)
 			tasklet_schedule(&ch->ch_bd->helper_tasklet);
-		}
 		left = 1;
 	}
 	else {
@@ -1378,7 +1371,7 @@
 	writeb(c, &ch->ch_cls_uart->txrx);
 }
 
-static void cls_vpd(struct board_t *brd)
+static void cls_vpd(struct dgnc_board *brd)
 {
         ulong           vpdbase;        /* Start of io base of the card */
         u8 __iomem           *re_map_vpdbase;/* Remapped memory of the card */
diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c
index 71d2b83..c204266 100644
--- a/drivers/staging/dgnc/dgnc_driver.c
+++ b/drivers/staging/dgnc/dgnc_driver.c
@@ -31,15 +31,10 @@
 
 
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
 #include <linux/sched.h>
-#endif
-
 #include "dgnc_driver.h"
 #include "dgnc_pci.h"
 #include "dpacompat.h"
@@ -71,16 +66,16 @@
  *
  */
 static int		dgnc_start(void);
-static int		dgnc_finalize_board_init(struct board_t *brd);
+static int		dgnc_finalize_board_init(struct dgnc_board *brd);
 static void		dgnc_init_globals(void);
 static int		dgnc_found_board(struct pci_dev *pdev, int id);
-static void		dgnc_cleanup_board(struct board_t *brd);
+static void		dgnc_cleanup_board(struct dgnc_board *brd);
 static void		dgnc_poll_handler(ulong dummy);
 static int		dgnc_init_pci(void);
 static int		dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
 static void		dgnc_remove_one(struct pci_dev *dev);
 static int		dgnc_probe1(struct pci_dev *pdev, int card_type);
-static void		dgnc_do_remap(struct board_t *brd);
+static void		dgnc_do_remap(struct dgnc_board *brd);
 
 /* Driver load/unload functions */
 int		dgnc_init_module(void);
@@ -106,7 +101,7 @@
  * Globals
  */
 uint			dgnc_NumBoards;
-struct board_t		*dgnc_Board[MAXBOARDS];
+struct dgnc_board		*dgnc_Board[MAXBOARDS];
 DEFINE_SPINLOCK(dgnc_global_lock);
 int			dgnc_driver_state = DRIVER_INITIALIZED;
 ulong			dgnc_poll_counter;
@@ -225,7 +220,7 @@
 	rc = dgnc_start();
 
 	if (rc < 0) {
-		return(rc);
+		return rc;
 	}
 
 	/*
@@ -250,7 +245,7 @@
 	}
 
 	DPR_INIT(("Finished init_module. Returning %d\n", rc));
-	return (rc);
+	return rc;
 }
 
 
@@ -286,21 +281,14 @@
 			if (rc <= 0) {
 				APR(("Can't register dgnc driver device (%d)\n", rc));
 				rc = -ENXIO;
-				return(rc);
+				return rc;
 			}
 			dgnc_Major = rc;
 
 			dgnc_class = class_create(THIS_MODULE, "dgnc_mgmt");
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
-			device_create_drvdata(dgnc_class, NULL,
-				MKDEV(dgnc_Major, 0),
-				NULL, "dgnc_mgmt");
-#else
 			device_create(dgnc_class, NULL,
 				MKDEV(dgnc_Major, 0),
 				NULL, "dgnc_mgmt");
-#endif
-
 			dgnc_Major_Control_Registered = TRUE;
 		}
 
@@ -311,7 +299,7 @@
 
 		if (rc < 0) {
 			APR(("tty preinit - not enough memory (%d)\n", rc));
-			return(rc);
+			return rc;
 		}
 
 		/* Start the poller */
@@ -328,7 +316,7 @@
 		dgnc_driver_state = DRIVER_READY;
 	}
 
-	return(rc);
+	return rc;
 }
 
 /*
@@ -418,7 +406,7 @@
  *
  * Free all the memory associated with a board
  */
-static void dgnc_cleanup_board(struct board_t *brd)
+static void dgnc_cleanup_board(struct dgnc_board *brd)
 {
 	int i = 0;
 
@@ -491,7 +479,7 @@
  */
 static int dgnc_found_board(struct pci_dev *pdev, int id)
 {
-	struct board_t *brd;
+	struct dgnc_board *brd;
 	unsigned int pci_irq;
 	int i = 0;
 	int rc = 0;
@@ -499,19 +487,16 @@
 
 	/* get the board structure and prep it */
 	brd = dgnc_Board[dgnc_NumBoards] =
-	(struct board_t *) kzalloc(sizeof(struct board_t), GFP_KERNEL);
-	if (!brd) {
-		APR(("memory allocation for board structure failed\n"));
-		return(-ENOMEM);
-	}
+		kzalloc(sizeof(*brd), GFP_KERNEL);
+	if (!brd) 
+		return -ENOMEM;
 
 	/* make a temporary message buffer for the boot messages */
 	brd->msgbuf = brd->msgbuf_head =
-		(char *) kzalloc(sizeof(char) * 8192, GFP_KERNEL);
+		kzalloc(sizeof(u8) * 8192, GFP_KERNEL);
 	if (!brd->msgbuf) {
 		kfree(brd);
-		APR(("memory allocation for board msgbuf failed\n"));
-		return(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	/* store the info for the board we've found */
@@ -663,7 +648,7 @@
 
 	default:
 		APR(("Did not find any compatible Neo or Classic PCI boards in system.\n"));
-		return (-ENXIO);
+		return -ENXIO;
 
 	}
 
@@ -725,22 +710,22 @@
 
 	wake_up_interruptible(&brd->state_wait);
 
-	return(0);
+	return 0;
 
 failed:
 
-	return (-ENXIO);
+	return -ENXIO;
 
 }
 
 
-static int dgnc_finalize_board_init(struct board_t *brd) {
+static int dgnc_finalize_board_init(struct dgnc_board *brd) {
 	int rc = 0;
 
 	DPR_INIT(("dgnc_finalize_board_init() - start\n"));
 
 	if (!brd || brd->magic != DGNC_BOARD_MAGIC)
-		return(-ENODEV);
+		return -ENODEV;
 
 	DPR_INIT(("dgnc_finalize_board_init() - start #2\n"));
 
@@ -756,13 +741,13 @@
 			DPR_INIT(("Requested and received usage of IRQ %d\n", brd->irq));
 		}
 	}
-	return(rc);
+	return rc;
 }
 
 /*
  * Remap PCI memory.
  */
-static void dgnc_do_remap(struct board_t *brd)
+static void dgnc_do_remap(struct dgnc_board *brd)
 {
 
 	if (!brd || brd->magic != DGNC_BOARD_MAGIC)
@@ -802,7 +787,7 @@
 
 static void dgnc_poll_handler(ulong dummy)
 {
-	struct board_t *brd;
+	struct dgnc_board *brd;
 	unsigned long lock_flags;
 	int i;
 	unsigned long new_time;
@@ -900,7 +885,7 @@
 {
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout((ms * HZ) / 1000);
-	return (signal_pending(current));
+	return signal_pending(current);
 }
 
 
@@ -912,47 +897,47 @@
 {
 	switch(cmd) {
 
-	case TCGETA:		return("TCGETA");
-	case TCGETS:		return("TCGETS");
-	case TCSETA:		return("TCSETA");
-	case TCSETS:		return("TCSETS");
-	case TCSETAW:		return("TCSETAW");
-	case TCSETSW:		return("TCSETSW");
-	case TCSETAF:		return("TCSETAF");
-	case TCSETSF:		return("TCSETSF");
-	case TCSBRK:		return("TCSBRK");
-	case TCXONC:		return("TCXONC");
-	case TCFLSH:		return("TCFLSH");
-	case TIOCGSID:		return("TIOCGSID");
+	case TCGETA:		return "TCGETA";
+	case TCGETS:		return "TCGETS";
+	case TCSETA:		return "TCSETA";
+	case TCSETS:		return "TCSETS";
+	case TCSETAW:		return "TCSETAW";
+	case TCSETSW:		return "TCSETSW";
+	case TCSETAF:		return "TCSETAF";
+	case TCSETSF:		return "TCSETSF";
+	case TCSBRK:		return "TCSBRK";
+	case TCXONC:		return "TCXONC";
+	case TCFLSH:		return "TCFLSH";
+	case TIOCGSID:		return "TIOCGSID";
 
-	case TIOCGETD:		return("TIOCGETD");
-	case TIOCSETD:		return("TIOCSETD");
-	case TIOCGWINSZ:	return("TIOCGWINSZ");
-	case TIOCSWINSZ:	return("TIOCSWINSZ");
+	case TIOCGETD:		return "TIOCGETD";
+	case TIOCSETD:		return "TIOCSETD";
+	case TIOCGWINSZ:	return "TIOCGWINSZ";
+	case TIOCSWINSZ:	return "TIOCSWINSZ";
 
-	case TIOCMGET:		return("TIOCMGET");
-	case TIOCMSET:		return("TIOCMSET");
-	case TIOCMBIS:		return("TIOCMBIS");
-	case TIOCMBIC:		return("TIOCMBIC");
+	case TIOCMGET:		return "TIOCMGET";
+	case TIOCMSET:		return "TIOCMSET";
+	case TIOCMBIS:		return "TIOCMBIS";
+	case TIOCMBIC:		return "TIOCMBIC";
 
 	/* from digi.h */
-	case DIGI_SETA:		return("DIGI_SETA");
-	case DIGI_SETAW:	return("DIGI_SETAW");
-	case DIGI_SETAF:	return("DIGI_SETAF");
-	case DIGI_SETFLOW:	return("DIGI_SETFLOW");
-	case DIGI_SETAFLOW:	return("DIGI_SETAFLOW");
-	case DIGI_GETFLOW:	return("DIGI_GETFLOW");
-	case DIGI_GETAFLOW:	return("DIGI_GETAFLOW");
-	case DIGI_GETA:		return("DIGI_GETA");
-	case DIGI_GEDELAY:	return("DIGI_GEDELAY");
-	case DIGI_SEDELAY:	return("DIGI_SEDELAY");
-	case DIGI_GETCUSTOMBAUD: return("DIGI_GETCUSTOMBAUD");
-	case DIGI_SETCUSTOMBAUD: return("DIGI_SETCUSTOMBAUD");
-	case TIOCMODG:		return("TIOCMODG");
-	case TIOCMODS:		return("TIOCMODS");
-	case TIOCSDTR:		return("TIOCSDTR");
-	case TIOCCDTR:		return("TIOCCDTR");
+	case DIGI_SETA:		return "DIGI_SETA";
+	case DIGI_SETAW:	return "DIGI_SETAW";
+	case DIGI_SETAF:	return "DIGI_SETAF";
+	case DIGI_SETFLOW:	return "DIGI_SETFLOW";
+	case DIGI_SETAFLOW:	return "DIGI_SETAFLOW";
+	case DIGI_GETFLOW:	return "DIGI_GETFLOW";
+	case DIGI_GETAFLOW:	return "DIGI_GETAFLOW";
+	case DIGI_GETA:		return "DIGI_GETA";
+	case DIGI_GEDELAY:	return "DIGI_GEDELAY";
+	case DIGI_SEDELAY:	return "DIGI_SEDELAY";
+	case DIGI_GETCUSTOMBAUD: return "DIGI_GETCUSTOMBAUD";
+	case DIGI_SETCUSTOMBAUD: return "DIGI_SETCUSTOMBAUD";
+	case TIOCMODG:		return "TIOCMODG";
+	case TIOCMODS:		return "TIOCMODS";
+	case TIOCSDTR:		return "TIOCSDTR";
+	case TIOCCDTR:		return "TIOCCDTR";
 
-	default:		return("unknown");
+	default:		return "unknown";
 	}
 }
diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h
index 218b15d..3519b80 100644
--- a/drivers/staging/dgnc/dgnc_driver.h
+++ b/drivers/staging/dgnc/dgnc_driver.h
@@ -45,7 +45,7 @@
 /*
  * Driver identification, error and debugging statments
  *
- * In theory, you can change all occurances of "digi" in the next
+ * In theory, you can change all occurrences of "digi" in the next
  * three lines, and the driver printk's will all automagically change.
  *
  * APR((fmt, args, ...));	Always prints message
@@ -246,7 +246,7 @@
  *
  *************************************************************************/
 
-struct board_t;
+struct dgnc_board;
 struct channel_t;
 
 /************************************************************************
@@ -259,7 +259,7 @@
 	void (*uart_off) (struct channel_t *ch);
 	int  (*drain) (struct tty_struct *tty, uint seconds);
 	void (*param) (struct tty_struct *tty);
-	void (*vpd) (struct board_t *brd);
+	void (*vpd) (struct dgnc_board *brd);
 	void (*assert_modem_signals) (struct channel_t *ch);
 	void (*flush_uart_write) (struct channel_t *ch);
 	void (*flush_uart_read) (struct channel_t *ch);
@@ -282,7 +282,7 @@
 /*
  *	Per-board information
  */
-struct board_t {
+struct dgnc_board {
 	int		magic;		/* Board Magic number.  */
 	int		boardnum;	/* Board number: 0-32 */
 
@@ -449,7 +449,7 @@
  ************************************************************************/
 struct channel_t {
 	int magic;			/* Channel Magic Number		*/
-	struct board_t	*ch_bd;		/* Board structure pointer      */
+	struct dgnc_board	*ch_bd;		/* Board structure pointer      */
 	struct digi_t	ch_digi;	/* Transparent Print structure  */
 	struct un_t	ch_tun;		/* Terminal unit info	   */
 	struct un_t	ch_pun;		/* Printer unit info	    */
@@ -555,7 +555,7 @@
 extern int		dgnc_trcbuf_size;	/* Size of the ringbuffer	*/
 extern spinlock_t	dgnc_global_lock;	/* Driver global spinlock	*/
 extern uint		dgnc_NumBoards;		/* Total number of boards	*/
-extern struct board_t	*dgnc_Board[MAXBOARDS];	/* Array of board structs	*/
+extern struct dgnc_board	*dgnc_Board[MAXBOARDS];	/* Array of board structs	*/
 extern ulong		dgnc_poll_counter;	/* Times the poller has run	*/
 extern char		*dgnc_state_text[];	/* Array of state text		*/
 extern char		*dgnc_driver_state_text[];/* Array of driver state text */
diff --git a/drivers/staging/dgnc/dgnc_kcompat.h b/drivers/staging/dgnc/dgnc_kcompat.h
index 00f589a..eaec7e6 100644
--- a/drivers/staging/dgnc/dgnc_kcompat.h
+++ b/drivers/staging/dgnc/dgnc_kcompat.h
@@ -28,13 +28,6 @@
 #ifndef __DGNC_KCOMPAT_H
 #define __DGNC_KCOMPAT_H
 
-#include <linux/version.h>
-
-# ifndef KERNEL_VERSION
-#  define KERNEL_VERSION(a,b,c)  (((a) << 16) + ((b) << 8) + (c))
-# endif
-
-
 #if !defined(TTY_FLIPBUF_SIZE)
 # define TTY_FLIPBUF_SIZE 512
 #endif
@@ -68,26 +61,4 @@
 		module_param(VAR, long, PERM); \
 		MODULE_PARM_DESC(VAR, DESC);
 
-
-
-
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
-
-
-
-/* NOTHING YET */
-
-
-
-# else
-
-
-
-# error "this driver does not support anything below the 2.6.27 kernel series."
-
-
-
-# endif
-
 #endif /* ! __DGNC_KCOMPAT_H */
diff --git a/drivers/staging/dgnc/dgnc_mgmt.c b/drivers/staging/dgnc/dgnc_mgmt.c
index c4629d7..1c5ab3d 100644
--- a/drivers/staging/dgnc/dgnc_mgmt.c
+++ b/drivers/staging/dgnc/dgnc_mgmt.c
@@ -74,13 +74,13 @@
 		/* Only allow 1 open at a time on mgmt device */
 		if (dgnc_mgmt_in_use[minor]) {
 			DGNC_UNLOCK(dgnc_global_lock, lock_flags);
-			return (-EBUSY);
+			return -EBUSY;
 		}
 		dgnc_mgmt_in_use[minor]++;
 	}
 	else {
 		DGNC_UNLOCK(dgnc_global_lock, lock_flags);
-		return (-ENXIO);
+		return -ENXIO;
 	}
 
 	DGNC_UNLOCK(dgnc_global_lock, lock_flags);
@@ -154,7 +154,7 @@
 			ddi.dinfo_nboards, ddi.dinfo_version));
 
 		if (copy_to_user(uarg, &ddi, sizeof (ddi)))
-			return(-EFAULT);
+			return -EFAULT;
 
 		break;
 	}
@@ -166,13 +166,13 @@
 		struct digi_info di;
 
 		if (copy_from_user(&brd, uarg, sizeof(int))) {
-			return(-EFAULT);
+			return -EFAULT;
 		}
 
 		DPR_MGMT(("DIGI_GETBD asking about board: %d\n", brd));
 
 		if ((brd < 0) || (brd > dgnc_NumBoards) || (dgnc_NumBoards == 0))
-			return (-ENODEV);
+			return -ENODEV;
 
 		memset(&di, 0, sizeof(di));
 
@@ -196,7 +196,7 @@
 			di.info_bdtype, di.info_bdstate, di.info_nports, di.info_physsize));
 
 		if (copy_to_user(uarg, &di, sizeof (di)))
-			return (-EFAULT);
+			return -EFAULT;
 
 		break;
 	}
@@ -209,8 +209,8 @@
 		uint board = 0;
 		uint channel = 0;
 
-		if (copy_from_user(&ni, uarg, sizeof(struct ni_info))) {
-			return(-EFAULT);
+		if (copy_from_user(&ni, uarg, sizeof(ni))) {
+			return -EFAULT;
 		}
 
 		DPR_MGMT(("DIGI_GETBD asking about board: %d channel: %d\n",
@@ -220,17 +220,17 @@
 		channel = ni.channel;
 
 		/* Verify boundaries on board */
-		if ((board < 0) || (board > dgnc_NumBoards) || (dgnc_NumBoards == 0))
-			return (-ENODEV);
+		if ((board > dgnc_NumBoards) || (dgnc_NumBoards == 0))
+			return -ENODEV;
 
 		/* Verify boundaries on channel */
 		if ((channel < 0) || (channel > dgnc_Board[board]->nasync))
-			return (-ENODEV);
+			return -ENODEV;
 
 		ch = dgnc_Board[board]->channels[channel];
 
 		if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-			return (-ENODEV);
+			return -ENODEV;
 
 		memset(&ni, 0, sizeof(ni));
 		ni.board = board;
@@ -291,7 +291,7 @@
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
 
 		if (copy_to_user(uarg, &ni, sizeof(ni)))
-			return (-EFAULT);
+			return -EFAULT;
 
 		break;
 	}
diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c
index 8b9e09a..dc5a138 100644
--- a/drivers/staging/dgnc/dgnc_neo.c
+++ b/drivers/staging/dgnc/dgnc_neo.c
@@ -43,8 +43,8 @@
 #include "dgnc_tty.h"
 #include "dgnc_trace.h"
 
-static inline void neo_parse_lsr(struct board_t *brd, uint port);
-static inline void neo_parse_isr(struct board_t *brd, uint port);
+static inline void neo_parse_lsr(struct dgnc_board *brd, uint port);
+static inline void neo_parse_isr(struct dgnc_board *brd, uint port);
 static void neo_copy_data_from_uart_to_queue(struct channel_t *ch);
 static inline void neo_clear_break(struct channel_t *ch, int force);
 static inline void neo_set_cts_flow_control(struct channel_t *ch);
@@ -56,7 +56,7 @@
 static inline void neo_set_new_start_stop_chars(struct channel_t *ch);
 static void neo_parse_modem(struct channel_t *ch, uchar signals);
 static void neo_tasklet(unsigned long data);
-static void neo_vpd(struct board_t *brd);
+static void neo_vpd(struct dgnc_board *brd);
 static void neo_uart_init(struct channel_t *ch);
 static void neo_uart_off(struct channel_t *ch);
 static int neo_drain(struct tty_struct *tty, uint seconds);
@@ -107,7 +107,7 @@
  * In this case, we are reading the DVID (Read-only Device Identification)
  * value of the Neo card.
  */
-static inline void neo_pci_posting_flush(struct board_t *bd)
+static inline void neo_pci_posting_flush(struct dgnc_board *bd)
 {
 	readb(bd->re_map_membase + 0x8D);
 }
@@ -411,7 +411,7 @@
 /*
  * Parse the ISR register.
  */
-static inline void neo_parse_isr(struct board_t *brd, uint port)
+static inline void neo_parse_isr(struct dgnc_board *brd, uint port)
 {
 	struct channel_t *ch;
 	uchar isr;
@@ -538,7 +538,7 @@
 }
 
 
-static inline void neo_parse_lsr(struct board_t *brd, uint port)
+static inline void neo_parse_lsr(struct dgnc_board *brd, uint port)
 {
 	struct channel_t *ch;
 	int linestatus;
@@ -650,7 +650,7 @@
 	uchar uart_ier = 0;
 	uint baud = 9600;
 	int quot = 0;
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t   *un;
 
@@ -911,7 +911,7 @@
  */
 static void neo_tasklet(unsigned long data)
 {
-	struct board_t *bd = (struct board_t *) data;
+	struct dgnc_board *bd = (struct dgnc_board *) data;
 	struct channel_t *ch;
 	ulong  lock_flags;
 	int i;
@@ -994,7 +994,7 @@
  */
 static irqreturn_t neo_intr(int irq, void *voidbrd)
 {
-	struct board_t *brd = (struct board_t *) voidbrd;
+	struct dgnc_board *brd = (struct dgnc_board *) voidbrd;
 	struct channel_t *ch;
 	int port = 0;
 	int type = 0;
@@ -1111,7 +1111,7 @@
 			 * Why would I check EVERY possibility of type of
 			 * interrupt, when we know its TXRDY???
 			 * Becuz for some reason, even tho we got triggered for TXRDY,
-			 * it seems to be occassionally wrong. Instead of TX, which
+			 * it seems to be occasionally wrong. Instead of TX, which
 			 * it should be, I was getting things like RXDY too. Weird.
 			 */
 			neo_parse_isr(brd, port);
@@ -1404,17 +1404,17 @@
 	int rc = 0;
 
 	if (!tty || tty->magic != TTY_MAGIC) {
-		return (-ENXIO);
+		return -ENXIO;
 	}
 
 	un = (struct un_t *) tty->driver_data;
 	if (!un || un->magic != DGNC_UNIT_MAGIC) {
-		return (-ENXIO);
+		return -ENXIO;
 	}
 
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) {
-		return (-ENXIO);
+		return -ENXIO;
 	}
 
 	DPR_IOCTL(("%d Drain wait started.\n", __LINE__));
@@ -1439,7 +1439,7 @@
 		DPR_IOCTL(("%d Drain wait finished.\n", __LINE__));
 	}
 
-	return (rc);
+	return rc;
 }
 
 
@@ -1939,7 +1939,7 @@
 }
 
 
-static void neo_vpd(struct board_t *brd)
+static void neo_vpd(struct dgnc_board *brd)
 {
 	unsigned int i = 0;
 	unsigned int a;
@@ -1965,7 +1965,7 @@
 	}
 	else {
 		/* Search for the serial number */
-		for (i = 0; i < NEO_VPD_IMAGESIZE * 2; i++) {
+		for (i = 0; i < NEO_VPD_IMAGEBYTES - 3; i++) {
 			if (brd->vpd[i] == 'S' && brd->vpd[i + 1] == 'N') {
 				strncpy(brd->serial_num, &(brd->vpd[i + 3]), 9);
 			}
diff --git a/drivers/staging/dgnc/dgnc_neo.h b/drivers/staging/dgnc/dgnc_neo.h
index 7ec5710..1a4abb1 100644
--- a/drivers/staging/dgnc/dgnc_neo.h
+++ b/drivers/staging/dgnc/dgnc_neo.h
@@ -47,7 +47,7 @@
 	u8 fctr;		/* WR  FCTR - Feature Control Reg */
 	u8 efr;		/* WR  EFR - Enhanced Function Reg */
 	u8 tfifo;		/* WR  TXCNT/TXTRG - Transmit FIFO Reg */
-	u8 rfifo;		/* WR  RXCNT/RXTRG - Recieve  FIFO Reg */
+	u8 rfifo;		/* WR  RXCNT/RXTRG - Receive  FIFO Reg */
 	u8 xoffchar1;	/* WR  XOFF 1 - XOff Character 1 Reg */
 	u8 xoffchar2;	/* WR  XOFF 2 - XOff Character 2 Reg */
 	u8 xonchar1;	/* WR  XON 1 - Xon Character 1 Reg */
diff --git a/drivers/staging/dgnc/dgnc_sysfs.c b/drivers/staging/dgnc/dgnc_sysfs.c
index 0ea6c80..946230c 100644
--- a/drivers/staging/dgnc/dgnc_sysfs.c
+++ b/drivers/staging/dgnc/dgnc_sysfs.c
@@ -152,19 +152,19 @@
 
 #define DGNC_VERIFY_BOARD(p, bd)			\
 	if (!p)						\
-		return (0);				\
+		return 0;				\
 							\
 	bd = dev_get_drvdata(p);			\
 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)	\
-		return (0);				\
+		return 0;				\
 	if (bd->state != BOARD_READY)			\
-		return (0);				\
+		return 0;				\
 
 
 
 static ssize_t dgnc_vpd_show(struct device *p, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	int count = 0;
 	int i = 0;
 
@@ -184,7 +184,7 @@
 
 static ssize_t dgnc_serial_number_show(struct device *p, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	int count = 0;
 
 	DGNC_VERIFY_BOARD(p, bd);
@@ -201,7 +201,7 @@
 
 static ssize_t dgnc_ports_state_show(struct device *p, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	int count = 0;
 	int i = 0;
 
@@ -219,7 +219,7 @@
 
 static ssize_t dgnc_ports_baud_show(struct device *p, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	int count = 0;
 	int i = 0;
 
@@ -236,7 +236,7 @@
 
 static ssize_t dgnc_ports_msignals_show(struct device *p, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	int count = 0;
 	int i = 0;
 
@@ -264,7 +264,7 @@
 
 static ssize_t dgnc_ports_iflag_show(struct device *p, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	int count = 0;
 	int i = 0;
 
@@ -281,7 +281,7 @@
 
 static ssize_t dgnc_ports_cflag_show(struct device *p, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	int count = 0;
 	int i = 0;
 
@@ -298,7 +298,7 @@
 
 static ssize_t dgnc_ports_oflag_show(struct device *p, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	int count = 0;
 	int i = 0;
 
@@ -315,7 +315,7 @@
 
 static ssize_t dgnc_ports_lflag_show(struct device *p, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	int count = 0;
 	int i = 0;
 
@@ -332,7 +332,7 @@
 
 static ssize_t dgnc_ports_digi_flag_show(struct device *p, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	int count = 0;
 	int i = 0;
 
@@ -349,7 +349,7 @@
 
 static ssize_t dgnc_ports_rxcount_show(struct device *p, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	int count = 0;
 	int i = 0;
 
@@ -366,7 +366,7 @@
 
 static ssize_t dgnc_ports_txcount_show(struct device *p, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	int count = 0;
 	int i = 0;
 
@@ -384,7 +384,7 @@
 /* this function creates the sys files that will export each signal status
  * to sysfs each value will be put in a separate filename
  */
-void dgnc_create_ports_sysfiles(struct board_t *bd)
+void dgnc_create_ports_sysfiles(struct dgnc_board *bd)
 {
 	int rc = 0;
 
@@ -408,7 +408,7 @@
 
 
 /* removes all the sys files created for that port */
-void dgnc_remove_ports_sysfiles(struct board_t *bd)
+void dgnc_remove_ports_sysfiles(struct dgnc_board *bd)
 {
 	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_state);
 	device_remove_file(&(bd->pdev->dev), &dev_attr_ports_baud);
@@ -427,23 +427,23 @@
 
 static ssize_t dgnc_tty_state_show(struct device *d, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 
 	if (!d)
-		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+		return 0;
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGNC_UNIT_MAGIC)
-		return (0);
+		return 0;
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return (0);
+		return 0;
 	bd = ch->ch_bd;
 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
-		return (0);
+		return 0;
 	if (bd->state != BOARD_READY)
-		return (0);
+		return 0;
 
 	return snprintf(buf, PAGE_SIZE, "%s", un->un_open_count ? "Open" : "Closed");
 }
@@ -452,23 +452,23 @@
 
 static ssize_t dgnc_tty_baud_show(struct device *d, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 
 	if (!d)
-		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+		return 0;
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGNC_UNIT_MAGIC)
-		return (0);
+		return 0;
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return (0);
+		return 0;
 	bd = ch->ch_bd;
 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
-		return (0);
+		return 0;
 	if (bd->state != BOARD_READY)
-		return (0);
+		return 0;
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_old_baud);
 }
@@ -477,23 +477,23 @@
 
 static ssize_t dgnc_tty_msignals_show(struct device *d, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 
 	if (!d)
-		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+		return 0;
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGNC_UNIT_MAGIC)
-		return (0);
+		return 0;
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return (0);
+		return 0;
 	bd = ch->ch_bd;
 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
-		return (0);
+		return 0;
 	if (bd->state != BOARD_READY)
-		return (0);
+		return 0;
 
 	if (ch->ch_open_count) {
 		return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
@@ -511,23 +511,23 @@
 
 static ssize_t dgnc_tty_iflag_show(struct device *d, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 
 	if (!d)
-		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+		return 0;
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGNC_UNIT_MAGIC)
-		return (0);
+		return 0;
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return (0);
+		return 0;
 	bd = ch->ch_bd;
 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
-		return (0);
+		return 0;
 	if (bd->state != BOARD_READY)
-		return (0);
+		return 0;
 
 	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag);
 }
@@ -536,23 +536,23 @@
 
 static ssize_t dgnc_tty_cflag_show(struct device *d, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 
 	if (!d)
-		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+		return 0;
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGNC_UNIT_MAGIC)
-		return (0);
+		return 0;
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return (0);
+		return 0;
 	bd = ch->ch_bd;
 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
-		return (0);
+		return 0;
 	if (bd->state != BOARD_READY)
-		return (0);
+		return 0;
 
 	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag);
 }
@@ -561,23 +561,23 @@
 
 static ssize_t dgnc_tty_oflag_show(struct device *d, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 
 	if (!d)
-		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+		return 0;
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGNC_UNIT_MAGIC)
-		return (0);
+		return 0;
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return (0);
+		return 0;
 	bd = ch->ch_bd;
 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
-		return (0);
+		return 0;
 	if (bd->state != BOARD_READY)
-		return (0);
+		return 0;
 
 	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag);
 }
@@ -586,23 +586,23 @@
 
 static ssize_t dgnc_tty_lflag_show(struct device *d, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 
 	if (!d)
-		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+		return 0;
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGNC_UNIT_MAGIC)
-		return (0);
+		return 0;
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return (0);
+		return 0;
 	bd = ch->ch_bd;
 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
-		return (0);
+		return 0;
 	if (bd->state != BOARD_READY)
-		return (0);
+		return 0;
 
 	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag);
 }
@@ -611,23 +611,23 @@
 
 static ssize_t dgnc_tty_digi_flag_show(struct device *d, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 
 	if (!d)
-		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+		return 0;
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGNC_UNIT_MAGIC)
-		return (0);
+		return 0;
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return (0);
+		return 0;
 	bd = ch->ch_bd;
 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
-		return (0);
+		return 0;
 	if (bd->state != BOARD_READY)
-		return (0);
+		return 0;
 
 	return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
 }
@@ -636,23 +636,23 @@
 
 static ssize_t dgnc_tty_rxcount_show(struct device *d, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 
 	if (!d)
-		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+		return 0;
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGNC_UNIT_MAGIC)
-		return (0);
+		return 0;
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return (0);
+		return 0;
 	bd = ch->ch_bd;
 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
-		return (0);
+		return 0;
 	if (bd->state != BOARD_READY)
-		return (0);
+		return 0;
 
 	return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount);
 }
@@ -661,23 +661,23 @@
 
 static ssize_t dgnc_tty_txcount_show(struct device *d, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 
 	if (!d)
-		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+		return 0;
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGNC_UNIT_MAGIC)
-		return (0);
+		return 0;
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return (0);
+		return 0;
 	bd = ch->ch_bd;
 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
-		return (0);
+		return 0;
 	if (bd->state != BOARD_READY)
-		return (0);
+		return 0;
 
 	return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount);
 }
@@ -686,23 +686,23 @@
 
 static ssize_t dgnc_tty_name_show(struct device *d, struct device_attribute *attr, char *buf)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 
 	if (!d)
-		return (0);
-	un = (struct un_t *) dev_get_drvdata(d);
+		return 0;
+	un = dev_get_drvdata(d);
 	if (!un || un->magic != DGNC_UNIT_MAGIC)
-		return (0);
+		return 0;
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return (0);
+		return 0;
 	bd = ch->ch_bd;
 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
-		return (0);
+		return 0;
 	if (bd->state != BOARD_READY)
-		return (0);
+		return 0;
 
 	return snprintf(buf, PAGE_SIZE, "%sn%d%c\n",
 		(un->un_type == DGNC_PRINT) ? "pr" : "tty",
diff --git a/drivers/staging/dgnc/dgnc_sysfs.h b/drivers/staging/dgnc/dgnc_sysfs.h
index 4b87ce1..68c0de5 100644
--- a/drivers/staging/dgnc/dgnc_sysfs.h
+++ b/drivers/staging/dgnc/dgnc_sysfs.h
@@ -26,14 +26,14 @@
 
 #include <linux/device.h>
 
-struct board_t;
+struct dgnc_board;
 struct channel_t;
 struct un_t;
 struct pci_driver;
 struct class_device;
 
-extern void dgnc_create_ports_sysfiles(struct board_t *bd);
-extern void dgnc_remove_ports_sysfiles(struct board_t *bd);
+extern void dgnc_create_ports_sysfiles(struct dgnc_board *bd);
+extern void dgnc_remove_ports_sysfiles(struct dgnc_board *bd);
 
 extern void dgnc_create_driver_sysfiles(struct pci_driver *);
 extern void dgnc_remove_driver_sysfiles(struct pci_driver *);
diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c
index a7bb6bc..a6c6aba 100644
--- a/drivers/staging/dgnc/dgnc_tty.c
+++ b/drivers/staging/dgnc/dgnc_tty.c
@@ -38,7 +38,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/sched.h>	/* For jiffies, task states */
 #include <linux/interrupt.h>	/* For tasklet and interrupt structs/defines */
 #include <linux/module.h>
@@ -60,16 +59,14 @@
 #include "dpacompat.h"
 #include "dgnc_sysfs.h"
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)
 #define init_MUTEX(sem)	 sema_init(sem, 1)
 #define DECLARE_MUTEX(name)     \
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
-#endif
 
 /*
  * internal variables
  */
-static struct board_t	*dgnc_BoardsByMajor[256];
+static struct dgnc_board	*dgnc_BoardsByMajor[256];
 static uchar		*dgnc_TmpWriteBuf = NULL;
 static DECLARE_MUTEX(dgnc_TmpWriteSem);
 
@@ -126,13 +123,8 @@
 static void dgnc_tty_hangup(struct tty_struct *tty);
 static int dgnc_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value);
 static int dgnc_get_modem_info(struct channel_t *ch, unsigned int __user *value);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
 static int dgnc_tty_tiocmget(struct tty_struct *tty);
 static int dgnc_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear);
-#else
-static int dgnc_tty_tiocmget(struct tty_struct *tty, struct file *file);
-static int dgnc_tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear);
-#endif
 static int dgnc_tty_send_break(struct tty_struct *tty, int msec);
 static void dgnc_tty_wait_until_sent(struct tty_struct *tty, int timeout);
 static int dgnc_tty_write(struct tty_struct *tty, const unsigned char *buf, int count);
@@ -190,10 +182,10 @@
 
 	if (!dgnc_TmpWriteBuf) {
 		DPR_INIT(("unable to allocate tmp write buf"));
-		return (-ENOMEM);
+		return -ENOMEM;
 	}
 
-	return(0);
+	return 0;
 }
 
 
@@ -202,14 +194,14 @@
  *
  * Init the tty subsystem for this board.
  */
-int dgnc_tty_register(struct board_t *brd)
+int dgnc_tty_register(struct dgnc_board *brd)
 {
 	int rc = 0;
 
 	DPR_INIT(("tty_register start\n"));
 
-	memset(&brd->SerialDriver, 0, sizeof(struct tty_driver));
-	memset(&brd->PrintDriver, 0, sizeof(struct tty_driver));
+	memset(&brd->SerialDriver, 0, sizeof(brd->SerialDriver));
+	memset(&brd->PrintDriver, 0, sizeof(brd->PrintDriver));
 
 	brd->SerialDriver.magic = TTY_DRIVER_MAGIC;
 
@@ -230,25 +222,15 @@
 	 * The kernel wants space to store pointers to
 	 * tty_struct's and termios's.
 	 */
-	brd->SerialDriver.ttys = kzalloc(brd->maxports * sizeof(struct tty_struct *), GFP_KERNEL);
+	brd->SerialDriver.ttys = kzalloc(brd->maxports * sizeof(*brd->SerialDriver.ttys), GFP_KERNEL);
 	if (!brd->SerialDriver.ttys)
-		return(-ENOMEM);
+		return -ENOMEM;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
-	brd->SerialDriver.refcount = brd->TtyRefCnt;
-#else
 	kref_init(&brd->SerialDriver.kref);
-#endif
-
-	brd->SerialDriver.termios = kzalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL);
+	brd->SerialDriver.termios = kzalloc(brd->maxports * sizeof(*brd->SerialDriver.termios), GFP_KERNEL);
 	if (!brd->SerialDriver.termios)
-		return(-ENOMEM);
+		return -ENOMEM;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
-	brd->SerialDriver.termios_locked = kzalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL);
-	if (!brd->SerialDriver.termios_locked)
-		return(-ENOMEM);
-#endif
 	/*
 	 * Entry points for driver.  Called by the kernel from
 	 * tty_io.c and n_tty.c.
@@ -260,14 +242,14 @@
 		rc = tty_register_driver(&brd->SerialDriver);
 		if (rc < 0) {
 			APR(("Can't register tty device (%d)\n", rc));
-			return(rc);
+			return rc;
 		}
 		brd->dgnc_Major_Serial_Registered = TRUE;
 	}
 
 	/*
 	 * If we're doing transparent print, we have to do all of the above
-	 * again, seperately so we don't get the LD confused about what major
+	 * again, separately so we don't get the LD confused about what major
 	 * we are when we get into the dgnc_tty_open() routine.
 	 */
 	brd->PrintDriver.magic = TTY_DRIVER_MAGIC;
@@ -286,28 +268,16 @@
 
 	/*
 	 * The kernel wants space to store pointers to
-	 * tty_struct's and termios's.  Must be seperate from
+	 * tty_struct's and termios's.  Must be separated from
 	 * the Serial Driver so we don't get confused
 	 */
-	brd->PrintDriver.ttys = kzalloc(brd->maxports * sizeof(struct tty_struct *), GFP_KERNEL);
+	brd->PrintDriver.ttys = kzalloc(brd->maxports * sizeof(*brd->PrintDriver.ttys), GFP_KERNEL);
 	if (!brd->PrintDriver.ttys)
-		return(-ENOMEM);
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
-	brd->PrintDriver.refcount = brd->TtyRefCnt;
-#else
+		return -ENOMEM;
 	kref_init(&brd->PrintDriver.kref);
-#endif
-
-	brd->PrintDriver.termios = kzalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL);
+	brd->PrintDriver.termios = kzalloc(brd->maxports * sizeof(*brd->PrintDriver.termios), GFP_KERNEL);
 	if (!brd->PrintDriver.termios)
-		return(-ENOMEM);
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
-	brd->PrintDriver.termios_locked = kzalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL);
-	if (!brd->PrintDriver.termios_locked)
-		return(-ENOMEM);
-#endif
+		return -ENOMEM;
 
 	/*
 	 * Entry points for driver.  Called by the kernel from
@@ -320,7 +290,7 @@
 		rc = tty_register_driver(&brd->PrintDriver);
 		if (rc < 0) {
 			APR(("Can't register Transparent Print device (%d)\n", rc));
-			return(rc);
+			return rc;
 		}
 		brd->dgnc_Major_TransparentPrint_Registered = TRUE;
 	}
@@ -331,7 +301,7 @@
 
 	DPR_INIT(("DGNC REGISTER TTY: MAJOR: %d\n", brd->SerialDriver.major));
 
-	return (rc);
+	return rc;
 }
 
 
@@ -341,14 +311,14 @@
  * Init the tty subsystem.  Called once per board after board has been
  * downloaded and init'ed.
  */
-int dgnc_tty_init(struct board_t *brd)
+int dgnc_tty_init(struct dgnc_board *brd)
 {
 	int i;
 	void __iomem *vaddr;
 	struct channel_t *ch;
 
 	if (!brd)
-		return (-ENXIO);
+		return -ENXIO;
 
 	DPR_INIT(("dgnc_tty_init start\n"));
 
@@ -371,7 +341,7 @@
 			 * Okay to malloc with GFP_KERNEL, we are not at
 			 * interrupt context, and there are no locks held.
 			 */
-			brd->channels[i] = kzalloc(sizeof(struct channel_t), GFP_KERNEL);
+			brd->channels[i] = kzalloc(sizeof(*brd->channels[i]), GFP_KERNEL);
 			if (!brd->channels[i]) {
 				DPR_CORE(("%s:%d Unable to allocate memory for channel struct\n",
 				    __FILE__, __LINE__));
@@ -436,7 +406,7 @@
 
 	DPR_INIT(("dgnc_tty_init finish\n"));
 
-	return (0);
+	return 0;
 }
 
 
@@ -460,7 +430,7 @@
  * Uninitialize the TTY portion of this driver.  Free all memory and
  * resources.
  */
-void dgnc_tty_uninit(struct board_t *brd)
+void dgnc_tty_uninit(struct dgnc_board *brd)
 {
 	int i = 0;
 
@@ -550,7 +520,7 @@
 		/*
 		 *  Loop while data remains.
 		 */
-		while (nbuf > 0 && ch->ch_sniff_buf != 0) {
+		while (nbuf > 0 && ch->ch_sniff_buf) {
 			/*
 			 *  Determine the amount of available space left in the
 			 *  buffer.  If there's none, wait until some appears.
@@ -671,7 +641,7 @@
  *=======================================================================*/
 void dgnc_input(struct channel_t *ch)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct tty_struct *tp;
 	struct tty_ldisc *ld;
 	uint	rmask;
@@ -867,7 +837,7 @@
  ************************************************************************/
 void dgnc_carrier(struct channel_t *ch)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 
 	int virt_carrier = 0;
 	int phys_carrier = 0;
@@ -1158,7 +1128,6 @@
 	}
 
 	if (ch->ch_tun.un_flags & UN_ISOPEN) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
 		if ((ch->ch_tun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
 			ch->ch_tun.un_tty->ldisc->ops->write_wakeup)
 		{
@@ -1166,15 +1135,6 @@
 			(ch->ch_tun.un_tty->ldisc->ops->write_wakeup)(ch->ch_tun.un_tty);
 			DGNC_LOCK(ch->ch_lock, lock_flags);
 		}
-#else
-		if ((ch->ch_tun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-			ch->ch_tun.un_tty->ldisc.ops->write_wakeup)
-		{
-			DGNC_UNLOCK(ch->ch_lock, lock_flags);
-			(ch->ch_tun.un_tty->ldisc.ops->write_wakeup)(ch->ch_tun.un_tty);
-			DGNC_LOCK(ch->ch_lock, lock_flags);
-		}
-#endif
 
 		wake_up_interruptible(&ch->ch_tun.un_tty->write_wait);
 
@@ -1210,7 +1170,6 @@
 	}
 
 	if (ch->ch_pun.un_flags & UN_ISOPEN) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
 		if ((ch->ch_pun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
 			ch->ch_pun.un_tty->ldisc->ops->write_wakeup)
 		{
@@ -1218,15 +1177,6 @@
 			(ch->ch_pun.un_tty->ldisc->ops->write_wakeup)(ch->ch_pun.un_tty);
 			DGNC_LOCK(ch->ch_lock, lock_flags);
 		}
-#else
-		if ((ch->ch_pun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-			ch->ch_pun.un_tty->ldisc.ops->write_wakeup)
-		{
-			DGNC_UNLOCK(ch->ch_lock, lock_flags);
-			(ch->ch_pun.un_tty->ldisc.ops->write_wakeup)(ch->ch_pun.un_tty);
-			DGNC_LOCK(ch->ch_lock, lock_flags);
-		}
-#endif
 
 		wake_up_interruptible(&ch->ch_pun.un_tty->write_wait);
 
@@ -1260,7 +1210,7 @@
  */
 static int dgnc_tty_open(struct tty_struct *tty, struct file *file)
 {
-	struct board_t	*brd;
+	struct dgnc_board	*brd;
 	struct channel_t *ch;
 	struct un_t	*un;
 	uint		major = 0;
@@ -1473,7 +1423,7 @@
 	DGNC_UNLOCK(ch->ch_lock, lock_flags);
 
 	DPR_OPEN(("dgnc_tty_open finished\n"));
-	return (rc);
+	return rc;
 }
 
 
@@ -1491,12 +1441,12 @@
 	int	sleep_on_un_flags = 0;
 
 	if (!tty || tty->magic != TTY_MAGIC || !file || !ch || ch->magic != DGNC_CHANNEL_MAGIC) {
-		return (-ENXIO);
+		return -ENXIO;
 	}
 
 	un = tty->driver_data;
 	if (!un || un->magic != DGNC_UNIT_MAGIC) {
-		return (-ENXIO);
+		return -ENXIO;
 	}
 
 	DPR_OPEN(("dgnc_block_til_ready - before block.\n"));
@@ -1624,12 +1574,12 @@
 
 	if (retval) {
 		DPR_OPEN(("dgnc_block_til_ready - done. error. retval: %x\n", retval));
-		return(retval);
+		return retval;
 	}
 
 	DPR_OPEN(("dgnc_block_til_ready - done no error. jiffies: %lu\n", jiffies));
 
-	return(0);
+	return 0;
 }
 
 
@@ -1667,7 +1617,7 @@
 static void dgnc_tty_close(struct tty_struct *tty, struct file *file)
 {
 	struct ktermios *ts;
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 	ulong lock_flags;
@@ -1843,15 +1793,15 @@
 	ulong   lock_flags = 0;
 
 	if (tty == NULL)
-		return(0);
+		return 0;
 
 	un = tty->driver_data;
 	if (!un || un->magic != DGNC_UNIT_MAGIC)
-		return (0);
+		return 0;
 
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return (0);
+		return 0;
 
 	DGNC_LOCK(ch->ch_lock, lock_flags);
 
@@ -1873,7 +1823,7 @@
 	DPR_WRITE(("dgnc_tty_chars_in_buffer. Port: %x - %d (head: %d tail: %d)\n",
 		ch->ch_portnum, chars, thead, ttail));
 
-	return(chars);
+	return chars;
 }
 
 
@@ -1891,22 +1841,22 @@
 	struct un_t *un = NULL;
 
 	if (!tty)
-		return (bytes_available);
+		return bytes_available;
 
 	un = tty->driver_data;
 	if (!un || un->magic != DGNC_UNIT_MAGIC)
-		return (bytes_available);
+		return bytes_available;
 
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return (bytes_available);
+		return bytes_available;
 
 	/*
 	 * If its not the Transparent print device, return
 	 * the full data amount.
 	 */
 	if (un->un_type != DGNC_PRINT)
-		return (bytes_available);
+		return bytes_available;
 
 	if (ch->ch_digi.digi_maxcps > 0 && ch->ch_digi.digi_bufsize > 0 ) {
 		int cps_limit = 0;
@@ -1931,7 +1881,7 @@
 		bytes_available = min(cps_limit, bytes_available);
 	}
 
-	return (bytes_available);
+	return bytes_available;
 }
 
 
@@ -1951,15 +1901,15 @@
 	ulong   lock_flags = 0;
 
 	if (tty == NULL || dgnc_TmpWriteBuf == NULL)
-		return(0);
+		return 0;
 
 	un = tty->driver_data;
 	if (!un || un->magic != DGNC_UNIT_MAGIC)
-		return (0);
+		return 0;
 
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return (0);
+		return 0;
 
 	DGNC_LOCK(ch->ch_lock, lock_flags);
 
@@ -1994,7 +1944,7 @@
 
 	DPR_WRITE(("dgnc_tty_write_room - %d tail: %d head: %d\n", ret, tail, head));
 
-	return(ret);
+	return ret;
 }
 
 
@@ -2037,18 +1987,18 @@
 	int from_user = 0;
 
 	if (tty == NULL || dgnc_TmpWriteBuf == NULL)
-		return(0);
+		return 0;
 
 	un = tty->driver_data;
 	if (!un || un->magic != DGNC_UNIT_MAGIC)
-		return(0);
+		return 0;
 
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return(0);
+		return 0;
 
 	if (!count)
-		return(0);
+		return 0;
 
 	DPR_WRITE(("dgnc_tty_write: Port: %x tty=%p user=%d len=%d\n",
 		ch->ch_portnum, tty, from_user, count));
@@ -2090,7 +2040,7 @@
 	 */
 	if (count <= 0) {
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
-		return(0);
+		return 0;
 	}
 
 	/*
@@ -2120,7 +2070,7 @@
 	 */
 	if (count <= 0) {
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
-		return(0);
+		return 0;
 	}
 
 	if (from_user) {
@@ -2136,7 +2086,7 @@
 		 */
 		/* we're allowed to block if it's from_user */
 		if (down_interruptible(&dgnc_TmpWriteSem)) {
-			return (-EINTR);
+			return -EINTR;
 		}
 
 		/*
@@ -2147,7 +2097,7 @@
 
 		if (!count) {
 			up(&dgnc_TmpWriteSem);
-			return(-EFAULT);
+			return -EFAULT;
 		}
 
 		DGNC_LOCK(ch->ch_lock, lock_flags);
@@ -2229,18 +2179,15 @@
 		ch->ch_bd->bd_ops->copy_data_from_queue_to_uart(ch);
 	}
 
-	return (count);
+	return count;
 }
 
 
 /*
  * Return modem signals to ld.
  */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
+
 static int dgnc_tty_tiocmget(struct tty_struct *tty)
-#else
-static int dgnc_tty_tiocmget(struct tty_struct *tty, struct file *file)
-#endif
 {
 	struct channel_t *ch;
 	struct un_t *un;
@@ -2293,15 +2240,11 @@
  *
  * Set modem signals, called by ld.
  */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
+
 static int dgnc_tty_tiocmset(struct tty_struct *tty,
 		unsigned int set, unsigned int clear)
-#else
-static int dgnc_tty_tiocmset(struct tty_struct *tty, struct file *file,
-		unsigned int set, unsigned int clear)
-#endif
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 	int ret = -EIO;
@@ -2349,7 +2292,7 @@
 
 	DPR_IOCTL(("dgnc_tty_tiocmset finish\n"));
 
-	return (0);
+	return 0;
 }
 
 
@@ -2360,7 +2303,7 @@
  */
 static int dgnc_tty_send_break(struct tty_struct *tty, int msec)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 	int ret = -EIO;
@@ -2402,7 +2345,7 @@
 
 	DPR_IOCTL(("dgnc_tty_send_break finish\n"));
 
-	return (0);
+	return 0;
 
 }
 
@@ -2414,7 +2357,7 @@
  */
 static void dgnc_tty_wait_until_sent(struct tty_struct *tty, int timeout)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 	int rc;
@@ -2450,7 +2393,7 @@
  */
 static void dgnc_tty_send_xchar(struct tty_struct *tty, char c)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 	ulong   lock_flags;
@@ -2497,7 +2440,7 @@
 	DPR_IOCTL(("dgnc_getmstat start\n"));
 
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return(-ENXIO);
+		return -ENXIO;
 
 	DGNC_LOCK(ch->ch_lock, lock_flags);
 
@@ -2522,7 +2465,7 @@
 
 	DPR_IOCTL(("dgnc_getmstat finish\n"));
 
-	return(result);
+	return result;
 }
 
 
@@ -2538,17 +2481,17 @@
 	DPR_IOCTL(("dgnc_get_modem_info start\n"));
 
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return(-ENXIO);
+		return -ENXIO;
 
 	result = dgnc_get_mstat(ch);
 
 	if (result < 0)
-		return (-ENXIO);
+		return -ENXIO;
 
 	rc = put_user(result, value);
 
 	DPR_IOCTL(("dgnc_get_modem_info finish\n"));
-	return(rc);
+	return rc;
 }
 
 
@@ -2559,7 +2502,7 @@
  */
 static int dgnc_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 	int ret = -ENXIO;
@@ -2587,7 +2530,7 @@
 
 	ret = get_user(arg, value);
 	if (ret)
-		return(ret);
+		return ret;
 
 	switch (command) {
 	case TIOCMBIS:
@@ -2631,7 +2574,7 @@
 		break;
 
 	default:
-		return(-EINVAL);
+		return -EINVAL;
 	}
 
 	DGNC_LOCK(ch->ch_lock, lock_flags);
@@ -2642,7 +2585,7 @@
 
 	DPR_IOCTL(("dgnc_set_modem_info finish\n"));
 
-	return (0);
+	return 0;
 }
 
 
@@ -2662,18 +2605,18 @@
 	ulong   lock_flags;
 
 	if (!retinfo)
-		return (-EFAULT);
+		return -EFAULT;
 
 	if (!tty || tty->magic != TTY_MAGIC)
-		return (-EFAULT);
+		return -EFAULT;
 
 	un = tty->driver_data;
 	if (!un || un->magic != DGNC_UNIT_MAGIC)
-		return (-EFAULT);
+		return -EFAULT;
 
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return (-EFAULT);
+		return -EFAULT;
 
 	memset(&tmp, 0, sizeof(tmp));
 
@@ -2682,9 +2625,9 @@
 	DGNC_UNLOCK(ch->ch_lock, lock_flags);
 
 	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-		return (-EFAULT);
+		return -EFAULT;
 
-	return (0);
+	return 0;
 }
 
 
@@ -2698,7 +2641,7 @@
  */
 static int dgnc_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 	struct digi_t new_digi;
@@ -2707,23 +2650,23 @@
 	DPR_IOCTL(("DIGI_SETA start\n"));
 
 	if (!tty || tty->magic != TTY_MAGIC)
-		return (-EFAULT);
+		return -EFAULT;
 
 	un = tty->driver_data;
 	if (!un || un->magic != DGNC_UNIT_MAGIC)
-		return (-EFAULT);
+		return -EFAULT;
 
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return (-EFAULT);
+		return -EFAULT;
 
 	bd = ch->ch_bd;
 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
-		return (-EFAULT);
+		return -EFAULT;
 
-	if (copy_from_user(&new_digi, new_info, sizeof(struct digi_t))) {
+	if (copy_from_user(&new_digi, new_info, sizeof(new_digi))) {
 		DPR_IOCTL(("DIGI_SETA failed copy_from_user\n"));
-		return(-EFAULT);
+		return -EFAULT;
 	}
 
 	DGNC_LOCK(ch->ch_lock, lock_flags);
@@ -2744,7 +2687,7 @@
 	if ((ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) && !(new_digi.digi_flags & DIGI_DTR_TOGGLE))
 		ch->ch_mostat |= (UART_MCR_DTR);
 
-	memcpy(&ch->ch_digi, &new_digi, sizeof(struct digi_t));
+	memcpy(&ch->ch_digi, &new_digi, sizeof(new_digi));
 
 	if (ch->ch_digi.digi_maxcps < 1)
 		ch->ch_digi.digi_maxcps = 1;
@@ -2773,7 +2716,7 @@
 
 	DPR_IOCTL(("DIGI_SETA finish\n"));
 
-	return(0);
+	return 0;
 }
 
 
@@ -2782,7 +2725,7 @@
  */
 static void dgnc_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 	unsigned long lock_flags;
@@ -2878,7 +2821,7 @@
 
 static void dgnc_tty_start(struct tty_struct *tty)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 	ulong lock_flags;
@@ -2912,7 +2855,7 @@
 
 static void dgnc_tty_stop(struct tty_struct *tty)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 	ulong lock_flags;
@@ -2959,7 +2902,7 @@
  */
 static void dgnc_tty_flush_chars(struct tty_struct *tty)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 	ulong lock_flags;
@@ -3056,7 +2999,7 @@
 static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
 		unsigned long arg)
 {
-	struct board_t *bd;
+	struct dgnc_board *bd;
 	struct channel_t *ch;
 	struct un_t *un;
 	int rc;
@@ -3064,19 +3007,19 @@
 	void __user *uarg = (void __user *) arg;
 
 	if (!tty || tty->magic != TTY_MAGIC)
-		return (-ENODEV);
+		return -ENODEV;
 
 	un = tty->driver_data;
 	if (!un || un->magic != DGNC_UNIT_MAGIC)
-		return (-ENODEV);
+		return -ENODEV;
 
 	ch = un->un_ch;
 	if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
-		return (-ENODEV);
+		return -ENODEV;
 
 	bd = ch->ch_bd;
 	if (!bd || bd->magic != DGNC_BOARD_MAGIC)
-		return (-ENODEV);
+		return -ENODEV;
 
 	DPR_IOCTL(("dgnc_tty_ioctl start on port %d - cmd %s (%x), arg %lx\n",
 		ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
@@ -3086,7 +3029,7 @@
 	if (un->un_open_count <= 0) {
 		DPR_BASIC(("dgnc_tty_ioctl - unit not open.\n"));
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
-		return(-EIO);
+		return -EIO;
 	}
 
 	switch (cmd) {
@@ -3105,14 +3048,14 @@
 		rc = tty_check_change(tty);
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
 		if (rc) {
-			return(rc);
+			return rc;
 		}
 
 		rc = ch->ch_bd->bd_ops->drain(tty, 0);
 
 		if (rc) {
 			DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
-			return(-EINTR);
+			return -EINTR;
 		}
 
 		DGNC_LOCK(ch->ch_lock, lock_flags);
@@ -3126,7 +3069,7 @@
 		DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
 			ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
 
-		return(0);
+		return 0;
 
 
 	case TCSBRKP:
@@ -3138,13 +3081,13 @@
 		rc = tty_check_change(tty);
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
 		if (rc) {
-			return(rc);
+			return rc;
 		}
 
 		rc = ch->ch_bd->bd_ops->drain(tty, 0);
 		if (rc) {
 			DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
-			return(-EINTR);
+			return -EINTR;
 		}
 
 		DGNC_LOCK(ch->ch_lock, lock_flags);
@@ -3156,19 +3099,19 @@
 		DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
 			ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
 
-		return(0);
+		return 0;
 
 	case TIOCSBRK:
 		rc = tty_check_change(tty);
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
 		if (rc) {
-			return(rc);
+			return rc;
 		}
 
 		rc = ch->ch_bd->bd_ops->drain(tty, 0);
 		if (rc) {
 			DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
-			return(-EINTR);
+			return -EINTR;
 		}
 
 		DGNC_LOCK(ch->ch_lock, lock_flags);
@@ -3180,7 +3123,7 @@
 		DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
 			ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
 
-		return(0);
+		return 0;
 
 	case TIOCCBRK:
 		/* Do Nothing */
@@ -3192,31 +3135,31 @@
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
 
 		rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) arg);
-		return(rc);
+		return rc;
 
 	case TIOCSSOFTCAR:
 
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
 		rc = get_user(arg, (unsigned long __user *) arg);
 		if (rc)
-			return(rc);
+			return rc;
 
 		DGNC_LOCK(ch->ch_lock, lock_flags);
 		tty->termios.c_cflag = ((tty->termios.c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
 		ch->ch_bd->bd_ops->param(tty);
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
 
-		return(0);
+		return 0;
 
 	case TIOCMGET:
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
-		return(dgnc_get_modem_info(ch, uarg));
+		return dgnc_get_modem_info(ch, uarg);
 
 	case TIOCMBIS:
 	case TIOCMBIC:
 	case TIOCMSET:
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
-		return(dgnc_set_modem_info(tty, cmd, uarg));
+		return dgnc_set_modem_info(tty, cmd, uarg);
 
 		/*
 		 * Here are any additional ioctl's that we want to implement
@@ -3235,7 +3178,7 @@
 		rc = tty_check_change(tty);
 		if (rc) {
 			DGNC_UNLOCK(ch->ch_lock, lock_flags);
-			return(rc);
+			return rc;
 		}
 
 		if ((arg == TCIFLUSH) || (arg == TCIOFLUSH)) {
@@ -3265,7 +3208,7 @@
 
 		/* pretend we didn't recognize this IOCTL */
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
-		return(-ENOIOCTLCMD);
+		return -ENOIOCTLCMD;
 	case TCSETSF:
 	case TCSETSW:
 		/*
@@ -3291,14 +3234,14 @@
 		rc = ch->ch_bd->bd_ops->drain(tty, 0);
 		if (rc) {
 			DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d\n", rc));
-			return(-EINTR);
+			return -EINTR;
 		}
 
 		DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n",
 			ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg));
 
 		/* pretend we didn't recognize this */
-		return(-ENOIOCTLCMD);
+		return -ENOIOCTLCMD;
 
 	case TCSETAW:
 
@@ -3306,21 +3249,21 @@
 		rc = ch->ch_bd->bd_ops->drain(tty, 0);
 		if (rc) {
 			DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
-			return(-EINTR);
+			return -EINTR;
 		}
 
 		/* pretend we didn't recognize this */
-		return(-ENOIOCTLCMD);
+		return -ENOIOCTLCMD;
 
 	case TCXONC:
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
 		/* Make the ld do it */
-		return(-ENOIOCTLCMD);
+		return -ENOIOCTLCMD;
 
 	case DIGI_GETA:
 		/* get information for ditty */
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
-		return(dgnc_tty_digigeta(tty, uarg));
+		return dgnc_tty_digigeta(tty, uarg);
 
 	case DIGI_SETAW:
 	case DIGI_SETAF:
@@ -3332,7 +3275,7 @@
 			rc = ch->ch_bd->bd_ops->drain(tty, 0);
 			if (rc) {
 				DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc));
-				return(-EINTR);
+				return -EINTR;
 			}
 			DGNC_LOCK(ch->ch_lock, lock_flags);
 		}
@@ -3343,7 +3286,7 @@
 
 	case DIGI_SETA:
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
-		return(dgnc_tty_digiseta(tty, uarg));
+		return dgnc_tty_digiseta(tty, uarg);
 
 	case DIGI_LOOPBACK:
 		{
@@ -3352,7 +3295,7 @@
 			DGNC_UNLOCK(ch->ch_lock, lock_flags);
 			rc = get_user(loopback, (unsigned int __user *) arg);
 			if (rc)
-				return(rc);
+				return rc;
 			DGNC_LOCK(ch->ch_lock, lock_flags);
 
 			/* Enable/disable internal loopback for this port */
@@ -3363,13 +3306,13 @@
 
 			ch->ch_bd->bd_ops->param(tty);
 			DGNC_UNLOCK(ch->ch_lock, lock_flags);
-			return(0);
+			return 0;
 		}
 
 	case DIGI_GETCUSTOMBAUD:
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
 		rc = put_user(ch->ch_custom_speed, (unsigned int __user *) arg);
-		return(rc);
+		return rc;
 
 	case DIGI_SETCUSTOMBAUD:
 	{
@@ -3378,12 +3321,12 @@
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
 		rc = get_user(new_rate, (unsigned int __user *) arg);
 		if (rc)
-			return(rc);
+			return rc;
 		DGNC_LOCK(ch->ch_lock, lock_flags);
 		dgnc_set_custom_speed(ch, new_rate);
 		ch->ch_bd->bd_ops->param(tty);
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
-		return(0);
+		return 0;
 	}
 
 	/*
@@ -3399,11 +3342,11 @@
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
 		rc = get_user(c, (unsigned char __user *) arg);
 		if (rc)
-			return(rc);
+			return rc;
 		DGNC_LOCK(ch->ch_lock, lock_flags);
 		ch->ch_bd->bd_ops->send_immediate_char(ch, c);
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
-		return(0);
+		return 0;
 	}
 
 	/*
@@ -3426,10 +3369,10 @@
 
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
 
-		if (copy_to_user(uarg, &buf, sizeof(struct digi_getcounter))) {
-			return (-EFAULT);
+		if (copy_to_user(uarg, &buf, sizeof(buf))) {
+			return -EFAULT;
 		}
-		return(0);
+		return 0;
 	}
 
 	/*
@@ -3454,7 +3397,7 @@
 
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
 		rc = put_user(events, (unsigned int __user *) arg);
-		return(rc);
+		return rc;
 	}
 
 	/*
@@ -3474,8 +3417,8 @@
 		/*
 		 * Get data from user first.
 		 */
-		if (copy_from_user(&buf, uarg, sizeof(struct digi_getbuffer))) {
-			return (-EFAULT);
+		if (copy_from_user(&buf, uarg, sizeof(buf))) {
+			return -EFAULT;
 		}
 
 		DGNC_LOCK(ch->ch_lock, lock_flags);
@@ -3520,10 +3463,10 @@
 
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
 
-		if (copy_to_user(uarg, &buf, sizeof(struct digi_getbuffer))) {
-			return (-EFAULT);
+		if (copy_to_user(uarg, &buf, sizeof(buf))) {
+			return -EFAULT;
 		}
-		return(0);
+		return 0;
 	}
 	default:
 		DGNC_UNLOCK(ch->ch_lock, lock_flags);
@@ -3532,7 +3475,7 @@
 		DPR_IOCTL(("dgnc_tty_ioctl end - cmd %s (%x), arg %lx\n",
 			dgnc_ioctl_name(cmd), cmd, arg));
 
-		return(-ENOIOCTLCMD);
+		return -ENOIOCTLCMD;
 	}
 
 	DGNC_UNLOCK(ch->ch_lock, lock_flags);
@@ -3540,5 +3483,5 @@
 	DPR_IOCTL(("dgnc_tty_ioctl end - cmd %s (%x), arg %lx\n",
 		dgnc_ioctl_name(cmd), cmd, arg));
 
-	return(0);
+	return 0;
 }
diff --git a/drivers/staging/dgnc/dgnc_tty.h b/drivers/staging/dgnc/dgnc_tty.h
index deb388d..9d1c284 100644
--- a/drivers/staging/dgnc/dgnc_tty.h
+++ b/drivers/staging/dgnc/dgnc_tty.h
@@ -24,13 +24,13 @@
 
 #include "dgnc_driver.h"
 
-int	dgnc_tty_register(struct board_t *brd);
+int	dgnc_tty_register(struct dgnc_board *brd);
 
 int	dgnc_tty_preinit(void);
-int     dgnc_tty_init(struct board_t *);
+int     dgnc_tty_init(struct dgnc_board *);
 
 void	dgnc_tty_post_uninit(void);
-void	dgnc_tty_uninit(struct board_t *);
+void	dgnc_tty_uninit(struct dgnc_board *);
 
 void	dgnc_input(struct channel_t *ch);
 void	dgnc_carrier(struct channel_t *ch);
diff --git a/drivers/staging/dgnc/digi.h b/drivers/staging/dgnc/digi.h
index eb6e371..6a9adf6 100644
--- a/drivers/staging/dgnc/digi.h
+++ b/drivers/staging/dgnc/digi.h
@@ -201,9 +201,9 @@
 	unsigned int	shrink_buf_vaddr;	/* Virtual address of board */
 	unsigned int	shrink_buf_phys;	/* Physical address of board */
 	unsigned int	shrink_buf_bseg;	/* Amount of board memory */
-	unsigned int	shrink_buf_hseg;	/* '186 Begining of Dual-Port */
+	unsigned int	shrink_buf_hseg;	/* '186 Beginning of Dual-Port */
 
-	unsigned int	shrink_buf_lseg;	/* '186 Begining of freed memory */
+	unsigned int	shrink_buf_lseg;	/* '186 Beginning of freed memory */
 	unsigned int	shrink_buf_mseg;	/* Linear address from start of
 						   dual-port were freed memory
 						   begins, host viewpoint. */
diff --git a/drivers/staging/dgrp/dgrp_sysfs.c b/drivers/staging/dgrp/dgrp_sysfs.c
index 8cee9c8..9a18a2c 100644
--- a/drivers/staging/dgrp/dgrp_sysfs.c
+++ b/drivers/staging/dgrp/dgrp_sysfs.c
@@ -157,7 +157,7 @@
 
 	if (!c)
 		return 0;
-	nd = (struct nd_struct *) dev_get_drvdata(c);
+	nd = dev_get_drvdata(c);
 	if (!nd)
 		return 0;
 
@@ -174,7 +174,7 @@
 
 	if (!c)
 		return 0;
-	nd = (struct nd_struct *) dev_get_drvdata(c);
+	nd = dev_get_drvdata(c);
 	if (!nd)
 		return 0;
 
@@ -192,7 +192,7 @@
 
 	if (!c)
 		return 0;
-	nd = (struct nd_struct *) dev_get_drvdata(c);
+	nd = dev_get_drvdata(c);
 	if (!nd)
 		return 0;
 
@@ -212,7 +212,7 @@
 
 	if (!c)
 		return 0;
-	nd = (struct nd_struct *) dev_get_drvdata(c);
+	nd = dev_get_drvdata(c);
 	if (!nd)
 		return 0;
 
@@ -232,7 +232,7 @@
 	if (!c)
 		return 0;
 
-	nd = (struct nd_struct *) dev_get_drvdata(c);
+	nd = dev_get_drvdata(c);
 	if (!nd)
 		return 0;
 
@@ -311,7 +311,7 @@
 
 	if (!d)
 		return 0;
-	un = (struct un_struct *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un)
 		return 0;
 
@@ -328,7 +328,7 @@
 
 	if (!d)
 		return 0;
-	un = (struct un_struct *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un)
 		return 0;
 	ch = un->un_ch;
@@ -348,7 +348,7 @@
 
 	if (!d)
 		return 0;
-	un = (struct un_struct *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un)
 		return 0;
 	ch = un->un_ch;
@@ -377,7 +377,7 @@
 
 	if (!d)
 		return 0;
-	un = (struct un_struct *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un)
 		return 0;
 	ch = un->un_ch;
@@ -396,7 +396,7 @@
 
 	if (!d)
 		return 0;
-	un = (struct un_struct *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un)
 		return 0;
 	ch = un->un_ch;
@@ -415,7 +415,7 @@
 
 	if (!d)
 		return 0;
-	un = (struct un_struct *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un)
 		return 0;
 	ch = un->un_ch;
@@ -434,7 +434,7 @@
 
 	if (!d)
 		return 0;
-	un = (struct un_struct *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un)
 		return 0;
 	ch = un->un_ch;
@@ -453,7 +453,7 @@
 
 	if (!d)
 		return 0;
-	un = (struct un_struct *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un)
 		return 0;
 	ch = un->un_ch;
@@ -472,7 +472,7 @@
 
 	if (!d)
 		return 0;
-	un = (struct un_struct *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un)
 		return 0;
 	ch = un->un_ch;
@@ -493,7 +493,7 @@
 
 	if (!d)
 		return 0;
-	un = (struct un_struct *) dev_get_drvdata(d);
+	un = dev_get_drvdata(d);
 	if (!un)
 		return 0;
 	ch = un->un_ch;
diff --git a/drivers/staging/dwc2/TODO b/drivers/staging/dwc2/TODO
new file mode 100644
index 0000000..282470d
--- /dev/null
+++ b/drivers/staging/dwc2/TODO
@@ -0,0 +1,33 @@
+TODO:
+	- Dan Carpenter would like to see some cleanups to the microframe
+	  scheduler code:
+	  http://www.mail-archive.com/linux-usb@vger.kernel.org/msg26650.html
+
+	- Should merge the NAK holdoff patch from Raspberry Pi
+	  (http://marc.info/?l=linux-usb&m=137625067103833). But as it stands
+	  that patch is incomplete, it needs more investigation to see if it
+	  can be made to work for non-Raspberry Pi platforms that lack the
+	  special FIQ interrupt that the Pi has. Without this patch, the driver
+	  has a high interrupt rate (8K/sec).
+
+	- The Raspberry Pi platform needs to have support for its FIQ interrupt
+	  added, to get the same level of functionality as the downstream
+	  driver. The raspberrypi.org developers have indicated they are
+	  willing to help with that.
+
+	- Some of the default driver parameters (see 'struct dwc2_core_params'
+	  in core.h) won't work for many platforms. So DT attributes will need
+	  to be added for some of these. But that can be done as-needed as new
+	  platforms are added.
+
+	- Eventually the driver should be merged with the s3c-hsotg peripheral
+	  mode driver, so that both modes of operation can be supported with a
+	  single driver. But I think that can wait till after the driver has
+	  been moved to mainline.
+
+	- After that, OTG support can be added. I'm not sure how much demand
+	  there is for that, though, so I have that as a low priority.
+
+Please send any patches for this driver to Paul Zimmerman <paulz@synopsys.com>
+and Greg Kroah-Hartman <gregkh@linuxfoundation.org>. And please CC linux-usb
+<linux-usb@vger.kernel.org> too.
diff --git a/drivers/staging/dwc2/core.c b/drivers/staging/dwc2/core.c
index 06dae67..6d001b5 100644
--- a/drivers/staging/dwc2/core.c
+++ b/drivers/staging/dwc2/core.c
@@ -564,7 +564,7 @@
 
 	/*
 	 * This bit allows dynamic reloading of the HFIR register during
-	 * runtime. This bit needs to be programmed during inital configuration
+	 * runtime. This bit needs to be programmed during initial configuration
 	 * and its value must not be changed during runtime.
 	 */
 	if (hsotg->core_params->reload_ctl > 0) {
@@ -2205,7 +2205,7 @@
 {
 #ifndef NO_FS_PHY_HW_CHECKS
 	int valid = 0;
-        u32 hs_phy_type, fs_phy_type;
+	u32 hs_phy_type, fs_phy_type;
 #endif
 	int retval = 0;
 
@@ -2553,7 +2553,7 @@
 		hsotg->core_params->ahbcfg = val;
 	else
 		hsotg->core_params->ahbcfg = GAHBCFG_HBSTLEN_INCR4 <<
-                                             GAHBCFG_HBSTLEN_SHIFT;
+						GAHBCFG_HBSTLEN_SHIFT;
 	return 0;
 }
 
@@ -2736,6 +2736,26 @@
 	return 0;
 }
 
+int dwc2_set_param_uframe_sched(struct dwc2_hsotg *hsotg, int val)
+{
+	int retval = 0;
+
+	if (DWC2_PARAM_TEST(val, 0, 1)) {
+		if (val >= 0) {
+			dev_err(hsotg->dev,
+				"'%d' invalid for parameter uframe_sched\n",
+				val);
+			dev_err(hsotg->dev, "uframe_sched must be 0 or 1\n");
+		}
+		val = 1;
+		dev_dbg(hsotg->dev, "Setting uframe_sched to %d\n", val);
+		retval = -EINVAL;
+	}
+
+	hsotg->core_params->uframe_sched = val;
+	return retval;
+}
+
 /*
  * This function is called during module intialization to pass module parameters
  * for the DWC_otg core. It returns non-0 if any parameters are invalid.
@@ -2782,6 +2802,7 @@
 	retval |= dwc2_set_param_reload_ctl(hsotg, params->reload_ctl);
 	retval |= dwc2_set_param_ahbcfg(hsotg, params->ahbcfg);
 	retval |= dwc2_set_param_otg_ver(hsotg, params->otg_ver);
+	retval |= dwc2_set_param_uframe_sched(hsotg, params->uframe_sched);
 
 	return retval;
 }
diff --git a/drivers/staging/dwc2/core.h b/drivers/staging/dwc2/core.h
index 9102f66..fab718d 100644
--- a/drivers/staging/dwc2/core.h
+++ b/drivers/staging/dwc2/core.h
@@ -188,6 +188,7 @@
  *                      bits defined by GAHBCFG_CTRL_MASK are controlled
  *                      by the driver and are ignored in this
  *                      configuration value.
+ * @uframe_sched:       True to enable the microframe scheduler
  *
  * The following parameters may be specified when starting the module. These
  * parameters define how the DWC_otg controller should be configured. A
@@ -224,6 +225,7 @@
 	int ts_dline;
 	int reload_ctl;
 	int ahbcfg;
+	int uframe_sched;
 };
 
 /**
@@ -292,7 +294,7 @@
 	unsigned dev_token_q_depth:5;
 	unsigned max_transfer_size:26;
 	unsigned max_packet_count:11;
-	unsigned host_channels:4;
+	unsigned host_channels:5;
 	unsigned hs_phy_type:2;
 	unsigned fs_phy_type:2;
 	unsigned i2c_enable:1;
@@ -370,6 +372,7 @@
  *                      This value is in microseconds per (micro)frame. The
  *                      assumption is that all periodic transfers may occur in
  *                      the same (micro)frame.
+ * @frame_usecs:        Internal variable used by the microframe scheduler
  * @frame_number:       Frame number read from the core at SOF. The value ranges
  *                      from 0 to HFNUM_MAX_FRNUM.
  * @periodic_qh_count:  Count of periodic QHs, if using several eps. Used for
@@ -382,6 +385,8 @@
  *                      host channel is available for non-periodic transactions.
  * @non_periodic_channels: Number of host channels assigned to non-periodic
  *                      transfers
+ * @available_host_channels Number of host channels available for the microframe
+ *                      scheduler to use
  * @hc_ptr_array:       Array of pointers to the host channel descriptors.
  *                      Allows accessing a host channel descriptor given the
  *                      host channel number. This is useful in interrupt
@@ -436,6 +441,7 @@
 	struct list_head periodic_sched_assigned;
 	struct list_head periodic_sched_queued;
 	u16 periodic_usecs;
+	u16 frame_usecs[8];
 	u16 frame_number;
 	u16 periodic_qh_count;
 
@@ -451,6 +457,7 @@
 	struct list_head free_hc_list;
 	int periodic_channels;
 	int non_periodic_channels;
+	int available_host_channels;
 	struct dwc2_host_chan *hc_ptr_array[MAX_EPS_CHANNELS];
 	u8 *status_buf;
 	dma_addr_t status_buf_dma;
diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c
index da0d35c..3cfd2d5 100644
--- a/drivers/staging/dwc2/hcd.c
+++ b/drivers/staging/dwc2/hcd.c
@@ -537,10 +537,15 @@
 	int i;
 
 	hsotg->flags.d32 = 0;
-
 	hsotg->non_periodic_qh_ptr = &hsotg->non_periodic_sched_active;
-	hsotg->non_periodic_channels = 0;
-	hsotg->periodic_channels = 0;
+
+	if (hsotg->core_params->uframe_sched > 0) {
+		hsotg->available_host_channels =
+			hsotg->core_params->host_channels;
+	} else {
+		hsotg->non_periodic_channels = 0;
+		hsotg->periodic_channels = 0;
+	}
 
 	/*
 	 * Put all channels in the free channel list and clean up channel
@@ -716,8 +721,7 @@
  * @qh:    Transactions from the first QTD for this QH are selected and assigned
  *         to a free host channel
  */
-static void dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg,
-				    struct dwc2_qh *qh)
+static int dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
 {
 	struct dwc2_host_chan *chan;
 	struct dwc2_hcd_urb *urb;
@@ -729,18 +733,18 @@
 
 	if (list_empty(&qh->qtd_list)) {
 		dev_dbg(hsotg->dev, "No QTDs in QH list\n");
-		return;
+		return -ENOMEM;
 	}
 
 	if (list_empty(&hsotg->free_hc_list)) {
 		dev_dbg(hsotg->dev, "No free channel to assign\n");
-		return;
+		return -ENOMEM;
 	}
 
 	chan = list_first_entry(&hsotg->free_hc_list, struct dwc2_host_chan,
 				hc_list_entry);
 
-	/* Remove the host channel from the free list */
+	/* Remove host channel from free list */
 	list_del_init(&chan->hc_list_entry);
 
 	qtd = list_first_entry(&qh->qtd_list, struct dwc2_qtd, qtd_list_entry);
@@ -780,6 +784,10 @@
 	chan->data_pid_start = qh->data_toggle;
 	chan->multi_count = 1;
 
+	if (urb->actual_length > urb->length &&
+		!dwc2_hcd_is_pipe_in(&urb->pipe_info))
+		urb->actual_length = urb->length;
+
 	if (hsotg->core_params->dma_enable > 0) {
 		chan->xfer_dma = urb->dma + urb->actual_length;
 
@@ -817,7 +825,7 @@
 				      &hsotg->free_hc_list);
 			qtd->in_process = 0;
 			qh->channel = NULL;
-			return;
+			return -ENOMEM;
 		}
 	} else {
 		chan->align_buf = 0;
@@ -836,6 +844,8 @@
 
 	dwc2_hc_init(hsotg, chan);
 	chan->qh = qh;
+
+	return 0;
 }
 
 /**
@@ -864,8 +874,14 @@
 	while (qh_ptr != &hsotg->periodic_sched_ready) {
 		if (list_empty(&hsotg->free_hc_list))
 			break;
+		if (hsotg->core_params->uframe_sched > 0) {
+			if (hsotg->available_host_channels <= 1)
+				break;
+			hsotg->available_host_channels--;
+		}
 		qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry);
-		dwc2_assign_and_init_hc(hsotg, qh);
+		if (dwc2_assign_and_init_hc(hsotg, qh))
+			break;
 
 		/*
 		 * Move the QH from the periodic ready schedule to the
@@ -884,13 +900,21 @@
 	num_channels = hsotg->core_params->host_channels;
 	qh_ptr = hsotg->non_periodic_sched_inactive.next;
 	while (qh_ptr != &hsotg->non_periodic_sched_inactive) {
-		if (hsotg->non_periodic_channels >= num_channels -
+		if (hsotg->core_params->uframe_sched <= 0 &&
+		    hsotg->non_periodic_channels >= num_channels -
 						hsotg->periodic_channels)
 			break;
 		if (list_empty(&hsotg->free_hc_list))
 			break;
 		qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry);
-		dwc2_assign_and_init_hc(hsotg, qh);
+		if (hsotg->core_params->uframe_sched > 0) {
+			if (hsotg->available_host_channels < 1)
+				break;
+			hsotg->available_host_channels--;
+		}
+
+		if (dwc2_assign_and_init_hc(hsotg, qh))
+			break;
 
 		/*
 		 * Move the QH from the non-periodic inactive schedule to the
@@ -905,7 +929,8 @@
 		else
 			ret_val = DWC2_TRANSACTION_ALL;
 
-		hsotg->non_periodic_channels++;
+		if (hsotg->core_params->uframe_sched <= 0)
+			hsotg->non_periodic_channels++;
 	}
 
 	return ret_val;
@@ -2848,6 +2873,9 @@
 		hsotg->hc_ptr_array[i] = channel;
 	}
 
+	if (hsotg->core_params->uframe_sched > 0)
+		dwc2_hcd_init_usecs(hsotg);
+
 	/* Initialize hsotg start work */
 	INIT_DELAYED_WORK(&hsotg->start_work, dwc2_hcd_start_func);
 
diff --git a/drivers/staging/dwc2/hcd.h b/drivers/staging/dwc2/hcd.h
index cc0a117..89a5484 100644
--- a/drivers/staging/dwc2/hcd.h
+++ b/drivers/staging/dwc2/hcd.h
@@ -238,6 +238,7 @@
  * @interval:           Interval between transfers in (micro)frames
  * @sched_frame:        (Micro)frame to initialize a periodic transfer.
  *                      The transfer executes in the following (micro)frame.
+ * @frame_usecs:        Internal variable used by the microframe scheduler
  * @start_split_frame:  (Micro)frame at which last start split was initialized
  * @ntd:                Actual number of transfer descriptors in a list
  * @dw_align_buf:       Used instead of original buffer if its physical address
@@ -271,6 +272,7 @@
 	u16 usecs;
 	u16 interval;
 	u16 sched_frame;
+	u16 frame_usecs[8];
 	u16 start_split_frame;
 	u16 ntd;
 	u8 *dw_align_buf;
@@ -463,6 +465,7 @@
 
 /* Schedule Queue Functions */
 /* Implemented in hcd_queue.c */
+extern void dwc2_hcd_init_usecs(struct dwc2_hsotg *hsotg);
 extern void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
 extern int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
 extern void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
diff --git a/drivers/staging/dwc2/hcd_ddma.c b/drivers/staging/dwc2/hcd_ddma.c
index 69070f4..c7d4345 100644
--- a/drivers/staging/dwc2/hcd_ddma.c
+++ b/drivers/staging/dwc2/hcd_ddma.c
@@ -271,10 +271,14 @@
 {
 	struct dwc2_host_chan *chan = qh->channel;
 
-	if (dwc2_qh_is_non_per(qh))
-		hsotg->non_periodic_channels--;
-	else
+	if (dwc2_qh_is_non_per(qh)) {
+		if (hsotg->core_params->uframe_sched > 0)
+			hsotg->available_host_channels++;
+		else
+			hsotg->non_periodic_channels--;
+	} else {
 		dwc2_update_frame_list(hsotg, qh, 0);
+	}
 
 	/*
 	 * The condition is added to prevent double cleanup try in case of
@@ -370,7 +374,8 @@
 
 	if ((qh->ep_type == USB_ENDPOINT_XFER_ISOC ||
 	     qh->ep_type == USB_ENDPOINT_XFER_INT) &&
-	    !hsotg->periodic_channels && hsotg->frame_list) {
+	    (hsotg->core_params->uframe_sched > 0 ||
+	     !hsotg->periodic_channels) && hsotg->frame_list) {
 		dwc2_per_sched_disable(hsotg);
 		dwc2_frame_list_free(hsotg);
 	}
diff --git a/drivers/staging/dwc2/hcd_intr.c b/drivers/staging/dwc2/hcd_intr.c
index e143f69..dda1854 100644
--- a/drivers/staging/dwc2/hcd_intr.c
+++ b/drivers/staging/dwc2/hcd_intr.c
@@ -748,18 +748,23 @@
 	dwc2_hc_cleanup(hsotg, chan);
 	list_add_tail(&chan->hc_list_entry, &hsotg->free_hc_list);
 
-	switch (chan->ep_type) {
-	case USB_ENDPOINT_XFER_CONTROL:
-	case USB_ENDPOINT_XFER_BULK:
-		hsotg->non_periodic_channels--;
-		break;
-	default:
-		/*
-		 * Don't release reservations for periodic channels here.
-		 * That's done when a periodic transfer is descheduled (i.e.
-		 * when the QH is removed from the periodic schedule).
-		 */
-		break;
+	if (hsotg->core_params->uframe_sched > 0) {
+		hsotg->available_host_channels++;
+	} else {
+		switch (chan->ep_type) {
+		case USB_ENDPOINT_XFER_CONTROL:
+		case USB_ENDPOINT_XFER_BULK:
+			hsotg->non_periodic_channels--;
+			break;
+		default:
+			/*
+			 * Don't release reservations for periodic channels
+			 * here. That's done when a periodic transfer is
+			 * descheduled (i.e. when the QH is removed from the
+			 * periodic schedule).
+			 */
+			break;
+		}
 	}
 
 	haintmsk = readl(hsotg->regs + HAINTMSK);
@@ -1927,23 +1932,22 @@
 
 	chan = hsotg->hc_ptr_array[chnum];
 
-	if (dbg_hc(chan))
-		dev_vdbg(hsotg->dev, "--Host Channel Interrupt--, Channel %d\n",
-			 chnum);
-
 	hcint = readl(hsotg->regs + HCINT(chnum));
 	hcintmsk = readl(hsotg->regs + HCINTMSK(chnum));
-	if (dbg_hc(chan))
-		dev_vdbg(hsotg->dev,
-			 "  hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
-			 hcint, hcintmsk, hcint & hcintmsk);
-
 	if (!chan) {
 		dev_err(hsotg->dev, "## hc_ptr_array for channel is NULL ##\n");
 		writel(hcint, hsotg->regs + HCINT(chnum));
 		return;
 	}
 
+	if (dbg_hc(chan)) {
+		dev_vdbg(hsotg->dev, "--Host Channel Interrupt--, Channel %d\n",
+			 chnum);
+		dev_vdbg(hsotg->dev,
+			 "  hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
+			 hcint, hcintmsk, hcint & hcintmsk);
+	}
+
 	writel(hcint, hsotg->regs + HCINT(chnum));
 	chan->hcint = hcint;
 	hcint &= hcintmsk;
diff --git a/drivers/staging/dwc2/hcd_queue.c b/drivers/staging/dwc2/hcd_queue.c
index b1980ef..f200f1f 100644
--- a/drivers/staging/dwc2/hcd_queue.c
+++ b/drivers/staging/dwc2/hcd_queue.c
@@ -251,12 +251,12 @@
  *
  * @hsotg: The HCD state structure for the DWC OTG controller
  *
- * Return: 0 if successful, negative error code otherise
+ * Return: 0 if successful, negative error code otherwise
  */
 static int dwc2_periodic_channel_available(struct dwc2_hsotg *hsotg)
 {
 	/*
-	 * Currently assuming that there is a dedicated host channnel for
+	 * Currently assuming that there is a dedicated host channel for
 	 * each periodic transaction plus at least one host channel for
 	 * non-periodic transactions
 	 */
@@ -324,6 +324,146 @@
 }
 
 /**
+ * Microframe scheduler
+ * track the total use in hsotg->frame_usecs
+ * keep each qh use in qh->frame_usecs
+ * when surrendering the qh then donate the time back
+ */
+static const unsigned short max_uframe_usecs[] = {
+	100, 100, 100, 100, 100, 100, 30, 0
+};
+
+void dwc2_hcd_init_usecs(struct dwc2_hsotg *hsotg)
+{
+	int i;
+
+	for (i = 0; i < 8; i++)
+		hsotg->frame_usecs[i] = max_uframe_usecs[i];
+}
+
+static int dwc2_find_single_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
+{
+	unsigned short utime = qh->usecs;
+	int done = 0;
+	int i = 0;
+	int ret = -1;
+
+	while (!done) {
+		/* At the start hsotg->frame_usecs[i] = max_uframe_usecs[i] */
+		if (utime <= hsotg->frame_usecs[i]) {
+			hsotg->frame_usecs[i] -= utime;
+			qh->frame_usecs[i] += utime;
+			ret = i;
+			done = 1;
+		} else {
+			i++;
+			if (i == 8)
+				done = 1;
+		}
+	}
+
+	return ret;
+}
+
+/*
+ * use this for FS apps that can span multiple uframes
+ */
+static int dwc2_find_multi_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
+{
+	unsigned short utime = qh->usecs;
+	unsigned short xtime;
+	int t_left = utime;
+	int done = 0;
+	int i = 0;
+	int j;
+	int ret = -1;
+
+	while (!done) {
+		if (hsotg->frame_usecs[i] <= 0) {
+			i++;
+			if (i == 8) {
+				ret = -1;
+				done = 1;
+			}
+			continue;
+		}
+
+		/*
+		 * we need n consecutive slots so use j as a start slot
+		 * j plus j+1 must be enough time (for now)
+		 */
+		xtime = hsotg->frame_usecs[i];
+		for (j = i + 1; j < 8; j++) {
+			/*
+			 * if we add this frame remaining time to xtime we may
+			 * be OK, if not we need to test j for a complete frame
+			 */
+			if (xtime + hsotg->frame_usecs[j] < utime) {
+				if (hsotg->frame_usecs[j] <
+							max_uframe_usecs[j]) {
+					ret = -1;
+					break;
+				}
+			}
+			if (xtime >= utime) {
+				ret = i;
+				break;
+			}
+			/* add the frame time to x time */
+			xtime += hsotg->frame_usecs[j];
+			/* we must have a fully available next frame or break */
+			if (xtime < utime &&
+			   hsotg->frame_usecs[j] == max_uframe_usecs[j]) {
+				ret = -1;
+				break;
+			}
+		}
+		if (ret >= 0) {
+			t_left = utime;
+			for (j = i; t_left > 0 && j < 8; j++) {
+				t_left -= hsotg->frame_usecs[j];
+				if (t_left <= 0) {
+					qh->frame_usecs[j] +=
+						hsotg->frame_usecs[j] + t_left;
+					hsotg->frame_usecs[j] = -t_left;
+					ret = i;
+					done = 1;
+				} else {
+					qh->frame_usecs[j] +=
+						hsotg->frame_usecs[j];
+					hsotg->frame_usecs[j] = 0;
+				}
+			}
+		} else {
+			i++;
+			if (i == 8) {
+				ret = -1;
+				done = 1;
+			}
+		}
+	}
+
+	return ret;
+}
+
+static int dwc2_find_uframe(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
+{
+	int ret;
+
+	if (qh->dev_speed == USB_SPEED_HIGH) {
+		/* if this is a hs transaction we need a full frame */
+		ret = dwc2_find_single_uframe(hsotg, qh);
+	} else {
+		/*
+		 * if this is a fs transaction we may need a sequence
+		 * of frames
+		 */
+		ret = dwc2_find_multi_uframe(hsotg, qh);
+	}
+	return ret;
+}
+
+/**
  * dwc2_check_max_xfer_size() - Checks that the max transfer size allowed in a
  * host channel is large enough to handle the maximum data transfer in a single
  * (micro)frame for a periodic transfer
@@ -367,15 +507,35 @@
 {
 	int status;
 
-	status = dwc2_periodic_channel_available(hsotg);
-	if (status) {
-		dev_dbg(hsotg->dev,
-			"%s: No host channel available for periodic transfer\n",
-			__func__);
-		return status;
+	if (hsotg->core_params->uframe_sched > 0) {
+		int frame = -1;
+
+		status = dwc2_find_uframe(hsotg, qh);
+		if (status == 0)
+			frame = 7;
+		else if (status > 0)
+			frame = status - 1;
+
+		/* Set the new frame up */
+		if (frame > -1) {
+			qh->sched_frame &= ~0x7;
+			qh->sched_frame |= (frame & 7);
+		}
+
+		if (status != -1)
+			status = 0;
+	} else {
+		status = dwc2_periodic_channel_available(hsotg);
+		if (status) {
+			dev_info(hsotg->dev,
+				 "%s: No host channel available for periodic transfer\n",
+				 __func__);
+			return status;
+		}
+
+		status = dwc2_check_periodic_bandwidth(hsotg, qh);
 	}
 
-	status = dwc2_check_periodic_bandwidth(hsotg, qh);
 	if (status) {
 		dev_dbg(hsotg->dev,
 			"%s: Insufficient periodic bandwidth for periodic transfer\n",
@@ -399,8 +559,9 @@
 		list_add_tail(&qh->qh_list_entry,
 			      &hsotg->periodic_sched_inactive);
 
-	/* Reserve periodic channel */
-	hsotg->periodic_channels++;
+	if (hsotg->core_params->uframe_sched <= 0)
+		/* Reserve periodic channel */
+		hsotg->periodic_channels++;
 
 	/* Update claimed usecs per (micro)frame */
 	hsotg->periodic_usecs += qh->usecs;
@@ -418,13 +579,22 @@
 static void dwc2_deschedule_periodic(struct dwc2_hsotg *hsotg,
 				     struct dwc2_qh *qh)
 {
-	list_del_init(&qh->qh_list_entry);
+	int i;
 
-	/* Release periodic channel reservation */
-	hsotg->periodic_channels--;
+	list_del_init(&qh->qh_list_entry);
 
 	/* Update claimed usecs per (micro)frame */
 	hsotg->periodic_usecs -= qh->usecs;
+
+	if (hsotg->core_params->uframe_sched > 0) {
+		for (i = 0; i < 8; i++) {
+			hsotg->frame_usecs[i] += qh->frame_usecs[i];
+			qh->frame_usecs[i] = 0;
+		}
+	} else {
+		/* Release periodic channel reservation */
+		hsotg->periodic_channels--;
+	}
 }
 
 /**
@@ -581,7 +751,10 @@
 			 * Remove from periodic_sched_queued and move to
 			 * appropriate queue
 			 */
-			if (qh->sched_frame == frame_number)
+			if ((hsotg->core_params->uframe_sched > 0 &&
+			     dwc2_frame_num_le(qh->sched_frame, frame_number))
+			 || (hsotg->core_params->uframe_sched <= 0 &&
+			     qh->sched_frame == frame_number))
 				list_move(&qh->qh_list_entry,
 					  &hsotg->periodic_sched_ready);
 			else
diff --git a/drivers/staging/dwc2/pci.c b/drivers/staging/dwc2/pci.c
index 9020260..3d14c88 100644
--- a/drivers/staging/dwc2/pci.c
+++ b/drivers/staging/dwc2/pci.c
@@ -84,6 +84,7 @@
 	.ts_dline			= -1,
 	.reload_ctl			= -1,
 	.ahbcfg				= -1,
+	.uframe_sched			= -1,
 };
 
 /**
diff --git a/drivers/staging/dwc2/platform.c b/drivers/staging/dwc2/platform.c
index 44cce2f..76ae6e2 100644
--- a/drivers/staging/dwc2/platform.c
+++ b/drivers/staging/dwc2/platform.c
@@ -106,7 +106,7 @@
 	irq = platform_get_irq(dev, 0);
 	if (irq < 0) {
 		dev_err(&dev->dev, "missing IRQ resource\n");
-		return -EINVAL;
+		return irq;
 	}
 
 	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
diff --git a/drivers/staging/et131x/Module.symvers b/drivers/staging/et131x/Module.symvers
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/drivers/staging/et131x/Module.symvers
diff --git a/drivers/staging/et131x/README b/drivers/staging/et131x/README
index 9272a24..8da96a6 100644
--- a/drivers/staging/et131x/README
+++ b/drivers/staging/et131x/README
@@ -11,7 +11,12 @@
 	- Look at reducing the number of spinlocks
 	- Simplify code in nic_rx_pkts(), when determining multicast_pkts_rcvd
 	- Implement NAPI support
-	- in et131x_tx(), don't return NETDEV_TX_BUSY, just drop the packet with	  kfree_skb().
+	- In et131x_tx(), don't return NETDEV_TX_BUSY, just drop the packet with kfree_skb().
+	- Reduce the number of split lines by careful consideration of variable names etc.
+	- Do this in et131x.c:
+                struct fbr_lookup *fbr;
+                fbr = rx_local->fbr[id];
+	  Then replace all the instances of "rx_local->fbr[id]" with fbr.
 
 Please send patches to:
 	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
diff --git a/drivers/staging/et131x/et131x.c b/drivers/staging/et131x/et131x.c
index f73e58f..d9446c4 100644
--- a/drivers/staging/et131x/et131x.c
+++ b/drivers/staging/et131x/et131x.c
@@ -493,11 +493,8 @@
 	spinlock_t send_hw_lock;
 
 	spinlock_t rcv_lock;
-	spinlock_t rcv_pend_lock;
 	spinlock_t fbr_lock;
 
-	spinlock_t phy_lock;
-
 	/* Packet Filter and look ahead size */
 	u32 packet_filter;
 
@@ -2777,10 +2774,9 @@
 		adapter->net_stats.rx_packets++;
 
 		/* Set the status on the packet, either resources or success */
-		if (adapter->rx_ring.num_ready_recv < RFD_LOW_WATER_MARK) {
-			dev_warn(&adapter->pdev->dev,
-				    "RFD's are running out\n");
-		}
+		if (adapter->rx_ring.num_ready_recv < RFD_LOW_WATER_MARK)
+			dev_warn(&adapter->pdev->dev, "RFD's are running out\n");
+
 		count++;
 	}
 
@@ -2906,8 +2902,9 @@
 	 * number of fragments. If needed, we can call this function,
 	 * although it is less efficient.
 	 */
-	if (nr_frags > 23)
-		return -EIO;
+
+	/* nr_frags should be no more than 18. */
+	BUILD_BUG_ON(MAX_SKB_FRAGS + 1 > 23);
 
 	memset(desc, 0, sizeof(struct tx_desc) * (nr_frags + 1));
 
@@ -3100,11 +3097,10 @@
 		shbufva = (u16 *) skb->data;
 
 		if ((shbufva[0] == 0xffff) &&
-		    (shbufva[1] == 0xffff) && (shbufva[2] == 0xffff)) {
+		    (shbufva[1] == 0xffff) && (shbufva[2] == 0xffff))
 			tcb->flags |= FMP_DEST_BROAD;
-		} else if ((shbufva[0] & 0x3) == 0x0001) {
+		else if ((shbufva[0] & 0x3) == 0x0001)
 			tcb->flags |=  FMP_DEST_MULTI;
-		}
 	}
 
 	tcb->next = NULL;
@@ -3926,9 +3922,7 @@
 	spin_lock_init(&adapter->tcb_ready_qlock);
 	spin_lock_init(&adapter->send_hw_lock);
 	spin_lock_init(&adapter->rcv_lock);
-	spin_lock_init(&adapter->rcv_pend_lock);
 	spin_lock_init(&adapter->fbr_lock);
-	spin_lock_init(&adapter->phy_lock);
 
 	adapter->registry_jumbo_packet = 1514;	/* 1514-9216 */
 
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/boot.h b/drivers/staging/ft1000/ft1000-pcmcia/boot.h
index 1fc4ac1..9dce54e 100644
--- a/drivers/staging/ft1000/ft1000-pcmcia/boot.h
+++ b/drivers/staging/ft1000/ft1000-pcmcia/boot.h
@@ -27,7 +27,7 @@
 #define _BOOTH_
 
 // Official bootloader
-unsigned char bootimage [] = {
+static unsigned char bootimage [] = {
 0x00,0x00,0x01,0x5E,0x00,0x00
 ,0x00,0x00,0x00,0x00,0x02,0xD7
 ,0x00,0x00,0x01,0x5E,0x46,0xB3
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c
index 6311b2f..d44e858 100644
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c
@@ -304,7 +304,7 @@
 	struct dsp_file_hdr *pFileHdr5;
 	struct dsp_image_info *pDspImageInfoV6 = NULL;
 	long requested_version;
-	bool bGoodVersion = 0;
+	bool bGoodVersion = false;
 	struct drv_msg *pMailBoxData;
 	u16 *pUsData = NULL;
 	u16 *pUsFile = NULL;
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
index b2330f1..88f6f9c 100644
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
@@ -32,14 +32,14 @@
 
 #define seq_putx(m, message, size, var) \
 	seq_printf(m, message);	\
-	for(i = 0; i < (size - 1); i++) { \
+	for (i = 0; i < (size - 1); i++) { \
 		seq_printf(m, "%02x:", var[i]); \
 	} \
 	seq_printf(m, "%02x\n", var[i])
 
 #define seq_putd(m, message, size, var) \
 	seq_printf(m, message); \
-	for(i = 0; i < (size - 1); i++) { \
+	for (i = 0; i < (size - 1); i++) { \
 		seq_printf(m, "%d.", var[i]); \
 	} \
 	seq_printf(m, "%d\n", var[i])
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c b/drivers/staging/ft1000/ft1000-usb/ft1000_download.c
index 5190c8a..68ded17 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_download.c
@@ -1,12 +1,8 @@
-//=====================================================
-// CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved.
-//
-//
-// This file is part of Express Card USB Driver
-//
-// $Id:
-//====================================================
-// 20090926; aelias; removed compiler warnings; ubuntu 9.04; 2.6.28-15-generic
+/*
+* CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved.
+*
+* This file is part of Express Card USB Driver
+*/
 
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -111,23 +107,12 @@
 };
 
 
-//---------------------------------------------------------------------------
-// Function:    check_usb_db
-//
-// Parameters:  struct ft1000_usb  - device structure
-//
-// Returns:     0 - success
-//
-// Description: This function checks if the doorbell register is cleared
-//
-// Notes:
-//
-//---------------------------------------------------------------------------
-static u32 check_usb_db (struct ft1000_usb *ft1000dev)
+/* checks if the doorbell register is cleared */
+static int check_usb_db(struct ft1000_usb *ft1000dev)
 {
 	int loopcnt;
 	u16 temp;
-	u32 status;
+	int status;
 
 	loopcnt = 0;
 
@@ -169,25 +154,12 @@
 	return HANDSHAKE_MAG_TIMEOUT_VALUE;
 }
 
-//---------------------------------------------------------------------------
-// Function:    get_handshake
-//
-// Parameters:  struct ft1000_usb  - device structure
-//              u16 expected_value - the handshake value expected
-//
-// Returns:     handshakevalue - success
-//              HANDSHAKE_TIMEOUT_VALUE - failure
-//
-// Description: This function gets the handshake and compare with the expected value
-//
-// Notes:
-//
-//---------------------------------------------------------------------------
+/* gets the handshake and compares it with the expected value */
 static u16 get_handshake(struct ft1000_usb *ft1000dev, u16 expected_value)
 {
 	u16 handshake;
 	int loopcnt;
-	u32 status = 0;
+	int status = 0;
 
 	loopcnt = 0;
 
@@ -229,25 +201,12 @@
 	return HANDSHAKE_TIMEOUT_VALUE;
 }
 
-//---------------------------------------------------------------------------
-// Function:    put_handshake
-//
-// Parameters:  struct ft1000_usb  - device structure
-//              u16 handshake_value - handshake to be written
-//
-// Returns:     none
-//
-// Description: This function write the handshake value to the handshake location
-//              in DPRAM
-//
-// Notes:
-//
-//---------------------------------------------------------------------------
+/* write the handshake value to the handshake location */
 static void put_handshake(struct ft1000_usb *ft1000dev,u16 handshake_value)
 {
 	u32 tempx;
 	u16 tempword;
-	u32 status;
+	int status;
 
 	tempx = (u32)handshake_value;
 	tempx = ntohl(tempx);
@@ -267,7 +226,7 @@
 	u16 handshake;
 	int loopcnt;
 	u16 temp;
-	u32 status = 0;
+	int status = 0;
 
 	loopcnt = 0;
 	handshake = 0;
@@ -316,22 +275,10 @@
         for (i=0; i<1000; i++);
 }
 
-//---------------------------------------------------------------------------
-// Function:    get_request_type
-//
-// Parameters:  struct ft1000_usb  - device structure
-//
-// Returns:     request type - success
-//
-// Description: This function returns the request type
-//
-// Notes:
-//
-//---------------------------------------------------------------------------
 static u16 get_request_type(struct ft1000_usb *ft1000dev)
 {
 	u16 request_type;
-	u32 status;
+	int status;
 	u16 tempword;
 	u32 tempx;
 
@@ -354,7 +301,7 @@
 static u16 get_request_type_usb(struct ft1000_usb *ft1000dev)
 {
 	u16 request_type;
-	u32 status;
+	int status;
 	u16 tempword;
 	u32 tempx;
 
@@ -380,23 +327,11 @@
 	return request_type;
 }
 
-//---------------------------------------------------------------------------
-// Function:    get_request_value
-//
-// Parameters:  struct ft1000_usb  - device structure
-//
-// Returns:     request value - success
-//
-// Description: This function returns the request value
-//
-// Notes:
-//
-//---------------------------------------------------------------------------
 static long get_request_value(struct ft1000_usb *ft1000dev)
 {
 	u32 value;
 	u16 tempword;
-	u32 status;
+	int status;
 
 	if (ft1000dev->bootmode == 1) {
 		status = fix_ft1000_read_dpram32(ft1000dev,
@@ -416,23 +351,11 @@
 }
 
 
-//---------------------------------------------------------------------------
-// Function:    put_request_value
-//
-// Parameters:  struct ft1000_usb  - device structure
-//              long lvalue - value to be put into DPRAM location DWNLD_MAG1_SIZE_LOC
-//
-// Returns:     none
-//
-// Description: This function writes a value to DWNLD_MAG1_SIZE_LOC
-//
-// Notes:
-//
-//---------------------------------------------------------------------------
+/* writes a value to DWNLD_MAG1_SIZE_LOC */
 static void put_request_value(struct ft1000_usb *ft1000dev, long lvalue)
 {
 	u32    tempx;
-	u32    status;
+	int    status;
 
 	tempx = ntohl(lvalue);
 	status = fix_ft1000_write_dpram32(ft1000dev, DWNLD_MAG1_SIZE_LOC,
@@ -441,18 +364,7 @@
 
 
 
-//---------------------------------------------------------------------------
-// Function:    hdr_checksum
-//
-// Parameters:  struct pseudo_hdr *pHdr - Pseudo header pointer
-//
-// Returns:     checksum - success
-//
-// Description: This function returns the checksum of the pseudo header
-//
-// Notes:
-//
-//---------------------------------------------------------------------------
+/* returns the checksum of the pseudo header */
 static u16 hdr_checksum(struct pseudo_hdr *pHdr)
 {
 	u16   *usPtr = (u16 *)pHdr;
@@ -471,144 +383,130 @@
 
 	for (i = 0; i < len; i++) {
 		if (buff_w[i] != buff_r[i + offset])
-			return -1;
+			return -EREMOTEIO;
 	}
 
 	return 0;
 }
 
-//---------------------------------------------------------------------------
-// Function:    write_blk
-//
-// Parameters:  struct ft1000_usb  - device structure
-//              u16 **pUsFile - DSP image file pointer in u16
-//              u8  **pUcFile - DSP image file pointer in u8
-//              long   word_length - length of the buffer to be written
-//                                   to DPRAM
-//
-// Returns:     STATUS_SUCCESS - success
-//              STATUS_FAILURE - failure
-//
-// Description: This function writes a block of DSP image to DPRAM
-//
-// Notes:
-//
-//---------------------------------------------------------------------------
-static u32 write_blk (struct ft1000_usb *ft1000dev, u16 **pUsFile, u8 **pUcFile, long word_length)
+static int write_dpram32_and_check(struct ft1000_usb *ft1000dev,
+		u16 tempbuffer[], u16 dpram)
 {
-   u32 Status = STATUS_SUCCESS;
-   u16 dpram;
-   int loopcnt, i, j;
-   u16 tempword;
-   u16 tempbuffer[64];
-   u16 resultbuffer[64];
+	int status;
+	u16 resultbuffer[64];
+	int i;
 
-   //DEBUG("FT1000:download:start word_length = %d\n",(int)word_length);
-   dpram = (u16)DWNLD_MAG1_PS_HDR_LOC;
-   tempword = *(*pUsFile);
-   (*pUsFile)++;
-   Status = ft1000_write_dpram16(ft1000dev, dpram, tempword, 0);
-   tempword = *(*pUsFile);
-   (*pUsFile)++;
-   Status = ft1000_write_dpram16(ft1000dev, dpram++, tempword, 1);
-
-   *pUcFile = *pUcFile + 4;
-   word_length--;
-   tempword = (u16)word_length;
-   word_length = (word_length / 16) + 1;
-   for (; word_length > 0; word_length--) /* In words */
-   {
-	   loopcnt = 0;
-
-	      for (i=0; i<32; i++)
-	      {
-		       if (tempword != 0)
-		       {
-    		           tempbuffer[i++] = *(*pUsFile);
-			   (*pUsFile)++;
-   	    	           tempbuffer[i] = *(*pUsFile);
-			   (*pUsFile)++;
-			   *pUcFile = *pUcFile + 4;
-			   loopcnt++;
-			   tempword--;
-		       }
-		       else
-		       {
-			   tempbuffer[i++] = 0;
-			   tempbuffer[i] = 0;
-                       }
-	      }
-
-              //DEBUG("write_blk: loopcnt is %d\n", loopcnt);
-              //DEBUG("write_blk: bootmode = %d\n", bootmode);
-              //DEBUG("write_blk: dpram = %x\n", dpram);
-	      if (ft1000dev->bootmode == 0)
-	      {
-		 if (dpram >= 0x3F4)
-                     Status = ft1000_write_dpram32 (ft1000dev, dpram, (u8 *)&tempbuffer[0], 8);
-	         else
-                    Status = ft1000_write_dpram32 (ft1000dev, dpram, (u8 *)&tempbuffer[0], 64);
-	      }
-	      else
-	      {
-                 for (j=0; j<10; j++)
-                 {
-                   Status = ft1000_write_dpram32 (ft1000dev, dpram, (u8 *)&tempbuffer[0], 64);
-		   if (Status == STATUS_SUCCESS)
-		   {
-		       // Work around for ASIC bit stuffing problem.
-		       if ( (tempbuffer[31] & 0xfe00) == 0xfe00)
-		       {
-      		           Status = ft1000_write_dpram32(ft1000dev, dpram+12, (u8 *)&tempbuffer[24], 64);
-		       }
-    		       // Let's check the data written
-	    	       Status = ft1000_read_dpram32 (ft1000dev, dpram, (u8 *)&resultbuffer[0], 64);
-		       if ( (tempbuffer[31] & 0xfe00) == 0xfe00)
-		       {
-				if (check_buffers(tempbuffer, resultbuffer, 28, 0)) {
+	for (i = 0; i < 10; i++) {
+		status = ft1000_write_dpram32(ft1000dev, dpram,
+				(u8 *)&tempbuffer[0], 64);
+		if (status == 0) {
+			/* Work around for ASIC bit stuffing problem. */
+			if ((tempbuffer[31] & 0xfe00) == 0xfe00) {
+				status = ft1000_write_dpram32(ft1000dev,
+						dpram+12, (u8 *)&tempbuffer[24],
+						64);
+			}
+			/* Let's check the data written */
+			status = ft1000_read_dpram32(ft1000dev, dpram,
+					(u8 *)&resultbuffer[0], 64);
+			if ((tempbuffer[31] & 0xfe00) == 0xfe00) {
+				if (check_buffers(tempbuffer, resultbuffer, 28,
+							0)) {
 					DEBUG("FT1000:download:DPRAM write failed 1 during bootloading\n");
-					msleep(10);
-					Status = STATUS_FAILURE;
+					usleep_range(9000, 11000);
 					break;
 				}
-   			   Status = ft1000_read_dpram32 (ft1000dev, dpram+12, (u8 *)&resultbuffer[0], 64);
+				status = ft1000_read_dpram32(ft1000dev,
+						dpram+12,
+						(u8 *)&resultbuffer[0], 64);
 
-				if (check_buffers(tempbuffer, resultbuffer, 16, 24)) {
+				if (check_buffers(tempbuffer, resultbuffer, 16,
+							24)) {
 					DEBUG("FT1000:download:DPRAM write failed 2 during bootloading\n");
-					msleep(10);
-					Status = STATUS_FAILURE;
+					usleep_range(9000, 11000);
 					break;
 				}
-			   
-			}
-			else
-			{
-				if (check_buffers(tempbuffer, resultbuffer, 32, 0)) {
+			} else {
+				if (check_buffers(tempbuffer, resultbuffer, 32,
+							0)) {
 					DEBUG("FT1000:download:DPRAM write failed 3 during bootloading\n");
-					msleep(10);
-					Status = STATUS_FAILURE;
+					usleep_range(9000, 11000);
 					break;
 				}
-			    
 			}
+			if (status == 0)
+				break;
+		}
+	}
+	return status;
+}
 
-			if (Status == STATUS_SUCCESS)
-			    break;
+/* writes a block of DSP image to DPRAM
+ * Parameters:  struct ft1000_usb  - device structure
+ *              u16 **pUsFile - DSP image file pointer in u16
+ *              u8  **pUcFile - DSP image file pointer in u8
+ *              long word_length - length of the buffer to be written to DPRAM
+ */
+static int write_blk(struct ft1000_usb *ft1000dev, u16 **pUsFile, u8 **pUcFile,
+		long word_length)
+{
+	int status = STATUS_SUCCESS;
+	u16 dpram;
+	int loopcnt, i;
+	u16 tempword;
+	u16 tempbuffer[64];
 
-		    }
+	/*DEBUG("FT1000:download:start word_length = %d\n",(int)word_length); */
+	dpram = (u16)DWNLD_MAG1_PS_HDR_LOC;
+	tempword = *(*pUsFile);
+	(*pUsFile)++;
+	status = ft1000_write_dpram16(ft1000dev, dpram, tempword, 0);
+	tempword = *(*pUsFile);
+	(*pUsFile)++;
+	status = ft1000_write_dpram16(ft1000dev, dpram++, tempword, 1);
+
+	*pUcFile = *pUcFile + 4;
+	word_length--;
+	tempword = (u16)word_length;
+	word_length = (word_length / 16) + 1;
+	for (; word_length > 0; word_length--) { /* In words */
+		loopcnt = 0;
+		for (i = 0; i < 32; i++) {
+			if (tempword != 0) {
+				tempbuffer[i++] = *(*pUsFile);
+				(*pUsFile)++;
+				tempbuffer[i] = *(*pUsFile);
+				(*pUsFile)++;
+				*pUcFile = *pUcFile + 4;
+				loopcnt++;
+				tempword--;
+			} else {
+				tempbuffer[i++] = 0;
+				tempbuffer[i] = 0;
+			}
 		}
 
-		if (Status != STATUS_SUCCESS)
-		{
-                    DEBUG("FT1000:download:Write failed tempbuffer[31] = 0x%x\n", tempbuffer[31]);
-		    break;
+		/*DEBUG("write_blk: loopcnt is %d\n", loopcnt); */
+		/*DEBUG("write_blk: bootmode = %d\n", bootmode); */
+		/*DEBUG("write_blk: dpram = %x\n", dpram); */
+		if (ft1000dev->bootmode == 0) {
+			if (dpram >= 0x3F4)
+				status = ft1000_write_dpram32(ft1000dev, dpram,
+						(u8 *)&tempbuffer[0], 8);
+			else
+				status = ft1000_write_dpram32(ft1000dev, dpram,
+						(u8 *)&tempbuffer[0], 64);
+		} else {
+			status = write_dpram32_and_check(ft1000dev, tempbuffer,
+					dpram);
+			if (status != STATUS_SUCCESS) {
+				DEBUG("FT1000:download:Write failed tempbuffer[31] = 0x%x\n", tempbuffer[31]);
+				break;
+			}
 		}
-
-	     }
-   	     dpram = dpram + loopcnt;
-   }
-
-   return Status;
+		dpram = dpram + loopcnt;
+	}
+	return status;
 }
 
 static void usb_dnld_complete (struct urb *urb)
@@ -616,27 +514,16 @@
     //DEBUG("****** usb_dnld_complete\n");
 }
 
-//---------------------------------------------------------------------------
-// Function:    write_blk_fifo
-//
-// Parameters:  struct ft1000_usb  - device structure
-//              u16 **pUsFile - DSP image file pointer in u16
-//              u8  **pUcFile - DSP image file pointer in u8
-//              long   word_length - length of the buffer to be written
-//                                   to DPRAM
-//
-// Returns:     STATUS_SUCCESS - success
-//              STATUS_FAILURE - failure
-//
-// Description: This function writes a block of DSP image to DPRAM
-//
-// Notes:
-//
-//---------------------------------------------------------------------------
-static u32 write_blk_fifo(struct ft1000_usb *ft1000dev, u16 **pUsFile,
+/* writes a block of DSP image to DPRAM
+ * Parameters:  struct ft1000_usb  - device structure
+ *              u16 **pUsFile - DSP image file pointer in u16
+ *              u8  **pUcFile - DSP image file pointer in u8
+ *              long word_length - length of the buffer to be written to DPRAM
+ */
+static int write_blk_fifo(struct ft1000_usb *ft1000dev, u16 **pUsFile,
 			  u8 **pUcFile, long word_length)
 {
-	u32 Status = STATUS_SUCCESS;
+	int Status = STATUS_SUCCESS;
 	int byte_length;
 
 	byte_length = word_length * 4;
@@ -664,22 +551,71 @@
 	return Status;
 }
 
-//---------------------------------------------------------------------------
-//
-//  Function:   scram_dnldr
-//
-//  Synopsis:   Scramble downloader for Harley based ASIC via USB interface
-//
-//  Arguments:  pFileStart              - pointer to start of file
-//              FileLength              - file length
-//
-//  Returns:    status                  - return code
-//---------------------------------------------------------------------------
+static int scram_start_dwnld(struct ft1000_usb *ft1000dev, u16 *hshake,
+		u32 *state)
+{
+	int status = 0;
 
-u16 scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart,
+	DEBUG("FT1000:STATE_START_DWNLD\n");
+	if (ft1000dev->usbboot)
+		*hshake = get_handshake_usb(ft1000dev, HANDSHAKE_DSP_BL_READY);
+	else
+		*hshake = get_handshake(ft1000dev, HANDSHAKE_DSP_BL_READY);
+	if (*hshake == HANDSHAKE_DSP_BL_READY) {
+		DEBUG("scram_dnldr: handshake is HANDSHAKE_DSP_BL_READY, call put_handshake(HANDSHAKE_DRIVER_READY)\n");
+		put_handshake(ft1000dev, HANDSHAKE_DRIVER_READY);
+	} else if (*hshake == HANDSHAKE_TIMEOUT_VALUE) {
+		status = -ETIMEDOUT;
+	} else {
+		DEBUG("FT1000:download:Download error: Handshake failed\n");
+		status = -ENETRESET;
+	}
+	*state = STATE_BOOT_DWNLD;
+	return status;
+}
+
+static int request_code_segment(struct ft1000_usb *ft1000dev, u16 **s_file,
+		 u8 **c_file, const u8 *endpoint, bool boot_case)
+{
+	long word_length;
+	int status;
+
+	/*DEBUG("FT1000:REQUEST_CODE_SEGMENT\n");i*/
+	word_length = get_request_value(ft1000dev);
+	/*DEBUG("FT1000:word_length = 0x%x\n", (int)word_length); */
+	/*NdisMSleep (100); */
+	if (word_length > MAX_LENGTH) {
+		DEBUG("FT1000:download:Download error: Max length exceeded\n");
+		return STATUS_FAILURE;
+	}
+	if ((word_length * 2 + (long)c_file) > (long)endpoint) {
+		/* Error, beyond boot code range.*/
+		DEBUG("FT1000:download:Download error: Requested len=%d exceeds BOOT code boundary.\n", (int)word_length);
+		return STATUS_FAILURE;
+	}
+	if (word_length & 0x1)
+		word_length++;
+	word_length = word_length / 2;
+
+	if (boot_case) {
+		status = write_blk(ft1000dev, s_file, c_file, word_length);
+		/*DEBUG("write_blk returned %d\n", status); */
+	} else {
+		write_blk_fifo(ft1000dev, s_file, c_file, word_length);
+		if (ft1000dev->usbboot == 0)
+			ft1000dev->usbboot++;
+		if (ft1000dev->usbboot == 1)
+			ft1000_write_dpram16(ft1000dev,
+					DWNLD_MAG1_PS_HDR_LOC, 0, 0);
+	}
+	return status;
+}
+
+/* Scramble downloader for Harley based ASIC via USB interface */
+int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart,
 		u32 FileLength)
 {
-	u16 status = STATUS_SUCCESS;
+	int status = STATUS_SUCCESS;
 	u32 state;
 	u16 handshake;
 	struct pseudo_hdr *pseudo_header;
@@ -687,7 +623,6 @@
 	long word_length;
 	u16 request;
 	u16 temp;
-	u16 tempword;
 
 	struct dsp_file_hdr *file_hdr;
 	struct dsp_image_info *dsp_img_info = NULL;
@@ -733,34 +668,13 @@
 
 	loader_code_address = file_hdr->loader_code_address;
 	loader_code_size = file_hdr->loader_code_size;
-	correct_version = FALSE;
+	correct_version = false;
 
 	while ((status == STATUS_SUCCESS) && (state != STATE_DONE_FILE)) {
 		switch (state) {
 		case STATE_START_DWNLD:
-			DEBUG("FT1000:STATE_START_DWNLD\n");
-			if (ft1000dev->usbboot)
-				handshake =
-				    get_handshake_usb(ft1000dev,
-						      HANDSHAKE_DSP_BL_READY);
-			else
-				handshake =
-				    get_handshake(ft1000dev,
-						  HANDSHAKE_DSP_BL_READY);
-
-			if (handshake == HANDSHAKE_DSP_BL_READY) {
-				DEBUG
-				    ("scram_dnldr: handshake is HANDSHAKE_DSP_BL_READY, call put_handshake(HANDSHAKE_DRIVER_READY)\n");
-				put_handshake(ft1000dev,
-					      HANDSHAKE_DRIVER_READY);
-			} else {
-				DEBUG
-				    ("FT1000:download:Download error: Handshake failed\n");
-				status = STATUS_FAILURE;
-			}
-
-			state = STATE_BOOT_DWNLD;
-
+			status = scram_start_dwnld(ft1000dev, &handshake,
+						   &state);
 			break;
 
 		case STATE_BOOT_DWNLD:
@@ -794,41 +708,11 @@
 					ft1000dev->fcodeldr = 1;
 					break;
 				case REQUEST_CODE_SEGMENT:
-					//DEBUG("FT1000:REQUEST_CODE_SEGMENT\n");
-					word_length =
-					    get_request_value(ft1000dev);
-					//DEBUG("FT1000:word_length = 0x%x\n", (int)word_length);
-					//NdisMSleep (100);
-					if (word_length > MAX_LENGTH) {
-						DEBUG
-						    ("FT1000:download:Download error: Max length exceeded\n");
-						status = STATUS_FAILURE;
-						break;
-					}
-					if ((word_length * 2 + c_file) >
-					    boot_end) {
-						/*
-						 * Error, beyond boot code range.
-						 */
-						DEBUG
-						    ("FT1000:download:Download error: Requested len=%d exceeds BOOT code boundary.\n",
-						     (int)word_length);
-						status = STATUS_FAILURE;
-						break;
-					}
-					/*
-					 * Position ASIC DPRAM auto-increment pointer.
-					 */
-					dpram = (u16) DWNLD_MAG1_PS_HDR_LOC;
-					if (word_length & 0x1)
-						word_length++;
-					word_length = word_length / 2;
-
-					status =
-					    write_blk(ft1000dev, &s_file,
-						      &c_file, word_length);
-					//DEBUG("write_blk returned %d\n", status);
-					break;
+					status = request_code_segment(ft1000dev,
+							&s_file, &c_file,
+							(const u8 *)boot_end,
+							true);
+				break;
 				default:
 					DEBUG
 					    ("FT1000:download:Download error: Bad request type=%d in BOOT download state.\n",
@@ -929,45 +813,10 @@
 						break;
 					}
 
-					word_length =
-					    get_request_value(ft1000dev);
-					//DEBUG("FT1000:download:word_length = %d\n", (int)word_length);
-					if (word_length > MAX_LENGTH) {
-						DEBUG
-						    ("FT1000:download:Download error: Max length exceeded\n");
-						status = STATUS_FAILURE;
-						break;
-					}
-					if ((word_length * 2 + c_file) >
-					    code_end) {
-						/*
-						 * Error, beyond boot code range.
-						 */
-						DEBUG
-						    ("FT1000:download:Download error: Requested len=%d exceeds DSP code boundary.\n",
-						     (int)word_length);
-						status = STATUS_FAILURE;
-						break;
-					}
-					/*
-					 * Position ASIC DPRAM auto-increment pointer.
-					 */
-					dpram = (u16) DWNLD_MAG1_PS_HDR_LOC;
-					if (word_length & 0x1)
-						word_length++;
-					word_length = word_length / 2;
-
-					write_blk_fifo(ft1000dev, &s_file,
-						       &c_file, word_length);
-					if (ft1000dev->usbboot == 0)
-						ft1000dev->usbboot++;
-					if (ft1000dev->usbboot == 1) {
-						tempword = 0;
-						ft1000_write_dpram16(ft1000dev,
-								     DWNLD_MAG1_PS_HDR_LOC,
-								     tempword,
-								     0);
-					}
+					status = request_code_segment(ft1000dev,
+							&s_file, &c_file,
+							(const u8 *)code_end,
+							false);
 
 					break;
 
@@ -1036,7 +885,7 @@
 						status =
 						    fix_ft1000_write_dpram32
 						    (ft1000dev, dpram++,
-						     (u8 *) & templong);
+						     (u8 *) &templong);
 
 					}
 					break;
@@ -1044,7 +893,7 @@
 				case REQUEST_CODE_BY_VERSION:
 					DEBUG
 					    ("FT1000:download:REQUEST_CODE_BY_VERSION\n");
-					correct_version = FALSE;
+					correct_version = false;
 					requested_version =
 					    get_request_value(ft1000dev);
 
@@ -1061,7 +910,7 @@
 
 						if (dsp_img_info->version ==
 						    requested_version) {
-							correct_version = TRUE;
+							correct_version = true;
 							DEBUG
 							    ("FT1000:download: correct_version is TRUE\n");
 							s_file =
@@ -1137,13 +986,13 @@
 			if (pseudo_header->checksum ==
 			    hdr_checksum(pseudo_header)) {
 				if (pseudo_header->portdest !=
-				    0x80 /* Dsp OAM */ ) {
+				    0x80 /* Dsp OAM */) {
 					state = STATE_DONE_PROV;
 					break;
 				}
 				pseudo_header_len = ntohs(pseudo_header->length);	/* Byte length for PROV records */
 
-				// Get buffer for provisioning data
+				/* Get buffer for provisioning data */
 				pbuffer =
 				    kmalloc((pseudo_header_len +
 					     sizeof(struct pseudo_hdr)),
@@ -1201,9 +1050,8 @@
 			break;
 		}		/* End Switch */
 
-		if (status != STATUS_SUCCESS) {
+		if (status != STATUS_SUCCESS)
 			break;
-		}
 
 /****
       // Check if Card is present
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
index 9b8fed7..0d4931b 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
@@ -29,12 +29,7 @@
 
 //#define JDEBUG
 
-static int ft1000_reset(void *ft1000dev);
 static int ft1000_submit_rx_urb(struct ft1000_info *info);
-static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static int ft1000_open (struct net_device *dev);
-static struct net_device_stats *ft1000_netdev_stats(struct net_device *dev);
-static int ft1000_chkcard (struct ft1000_usb *dev);
 
 static u8 tempbuffer[1600];
 
@@ -526,7 +521,7 @@
 //-----------------------------------------------------------------------
 int dsp_reload(struct ft1000_usb *ft1000dev)
 {
-	u16 status;
+	int status;
 	u16 tempword;
 	u32 templong;
 
@@ -633,9 +628,9 @@
 
 	DEBUG("ft1000_hw:ft1000_reset_card called.....\n");
 
-	ft1000dev->fCondResetPend = 1;
+	ft1000dev->fCondResetPend = true;
 	info->CardReady = 0;
-	ft1000dev->fProvComplete = 0;
+	ft1000dev->fProvComplete = false;
 
 	/* Make sure we free any memory reserve for provisioning */
 	while (list_empty(&info->prov_list) == 0) {
@@ -666,200 +661,11 @@
 
 	info->CardReady = 1;
 
-	ft1000dev->fCondResetPend = 0;
+	ft1000dev->fCondResetPend = false;
 
 	return TRUE;
 }
 
-static const struct net_device_ops ftnet_ops =
-{
-	.ndo_open = &ft1000_open,
-	.ndo_stop = &ft1000_close,
-	.ndo_start_xmit = &ft1000_start_xmit,
-	.ndo_get_stats = &ft1000_netdev_stats,
-};
-
-
-//---------------------------------------------------------------------------
-// Function:    init_ft1000_netdev
-//
-// Parameters:  ft1000dev  - device structure
-//
-//
-// Returns:     STATUS_SUCCESS - success
-//              STATUS_FAILURE - failure
-//
-// Description: This function initialize the network device
-//
-// Notes:
-//
-//---------------------------------------------------------------------------
-int init_ft1000_netdev(struct ft1000_usb *ft1000dev)
-{
-	struct net_device *netdev;
-	struct ft1000_info *pInfo = NULL;
-	struct dpram_blk *pdpram_blk;
-	int i, ret_val;
-	struct list_head *cur, *tmp;
-	char card_nr[2];
-	u8 gCardIndex = 0;
-
-	DEBUG("Enter init_ft1000_netdev...\n");
-
-	netdev = alloc_etherdev(sizeof(struct ft1000_info));
-	if (!netdev) {
-		DEBUG("init_ft1000_netdev: can not allocate network device\n");
-		return -ENOMEM;
-	}
-
-	pInfo = netdev_priv(netdev);
-
-	memset(pInfo, 0, sizeof(struct ft1000_info));
-
-	dev_alloc_name(netdev, netdev->name);
-
-	DEBUG("init_ft1000_netdev: network device name is %s\n", netdev->name);
-
-	if (strncmp(netdev->name, "eth", 3) == 0) {
-		card_nr[0] = netdev->name[3];
-		card_nr[1] = '\0';
-		ret_val = kstrtou8(card_nr, 10, &gCardIndex);
-		if (ret_val) {
-			printk(KERN_ERR "Can't parse netdev\n");
-			goto err_net;
-		}
-
-		ft1000dev->CardNumber = gCardIndex;
-		DEBUG("card number = %d\n", ft1000dev->CardNumber);
-	} else {
-		printk(KERN_ERR "ft1000: Invalid device name\n");
-		ret_val = -ENXIO;
-		goto err_net;
-	}
-
-	memset(&pInfo->stats, 0, sizeof(struct net_device_stats));
-
-	spin_lock_init(&pInfo->dpram_lock);
-	pInfo->priv = ft1000dev;
-	pInfo->DrvErrNum = 0;
-	pInfo->registered = 1;
-	pInfo->ft1000_reset = ft1000_reset;
-	pInfo->mediastate = 0;
-	pInfo->fifo_cnt = 0;
-	ft1000dev->DeviceCreated = FALSE;
-	pInfo->CardReady = 0;
-	pInfo->DSP_TIME[0] = 0;
-	pInfo->DSP_TIME[1] = 0;
-	pInfo->DSP_TIME[2] = 0;
-	pInfo->DSP_TIME[3] = 0;
-	ft1000dev->fAppMsgPend = 0;
-	ft1000dev->fCondResetPend = 0;
-	ft1000dev->usbboot = 0;
-	ft1000dev->dspalive = 0;
-	memset(&ft1000dev->tempbuf[0], 0, sizeof(ft1000dev->tempbuf));
-
-	INIT_LIST_HEAD(&pInfo->prov_list);
-
-	INIT_LIST_HEAD(&ft1000dev->nodes.list);
-
-	netdev->netdev_ops = &ftnet_ops;
-
-	ft1000dev->net = netdev;
-
-	DEBUG("Initialize free_buff_lock and freercvpool\n");
-	spin_lock_init(&free_buff_lock);
-
-	/* initialize a list of buffers to be use for queuing
-	 * up receive command data
-	 */
-	INIT_LIST_HEAD(&freercvpool);
-
-	/* create list of free buffers */
-	for (i = 0; i < NUM_OF_FREE_BUFFERS; i++) {
-		/* Get memory for DPRAM_DATA link list */
-		pdpram_blk = kmalloc(sizeof(struct dpram_blk), GFP_KERNEL);
-		if (pdpram_blk == NULL) {
-			ret_val = -ENOMEM;
-			goto err_free;
-		}
-		/* Get a block of memory to store command data */
-		pdpram_blk->pbuffer = kmalloc(MAX_CMD_SQSIZE, GFP_KERNEL);
-		if (pdpram_blk->pbuffer == NULL) {
-			ret_val = -ENOMEM;
-			kfree(pdpram_blk);
-			goto err_free;
-		}
-		/* link provisioning data */
-		list_add_tail(&pdpram_blk->list, &freercvpool);
-	}
-	numofmsgbuf = NUM_OF_FREE_BUFFERS;
-
-	return 0;
-
-err_free:
-	list_for_each_safe(cur, tmp, &freercvpool) {
-		pdpram_blk = list_entry(cur, struct dpram_blk, list);
-		list_del(&pdpram_blk->list);
-		kfree(pdpram_blk->pbuffer);
-		kfree(pdpram_blk);
-	}
-err_net:
-	free_netdev(netdev);
-	return ret_val;
-}
-
-//---------------------------------------------------------------------------
-// Function:    reg_ft1000_netdev
-//
-// Parameters:  ft1000dev  - device structure
-//
-//
-// Returns:     STATUS_SUCCESS - success
-//              STATUS_FAILURE - failure
-//
-// Description: This function register the network driver
-//
-// Notes:
-//
-//---------------------------------------------------------------------------
-int reg_ft1000_netdev(struct ft1000_usb *ft1000dev,
-		      struct usb_interface *intf)
-{
-	struct net_device *netdev;
-	struct ft1000_info *pInfo;
-	int rc;
-
-	netdev = ft1000dev->net;
-	pInfo = netdev_priv(ft1000dev->net);
-	DEBUG("Enter reg_ft1000_netdev...\n");
-
-	ft1000_read_register(ft1000dev, &pInfo->AsicID, FT1000_REG_ASIC_ID);
-
-	usb_set_intfdata(intf, pInfo);
-	SET_NETDEV_DEV(netdev, &intf->dev);
-
-	rc = register_netdev(netdev);
-	if (rc) {
-		DEBUG("reg_ft1000_netdev: could not register network device\n");
-		free_netdev(netdev);
-		return rc;
-	}
-
-	ft1000_create_dev(ft1000dev);
-
-	DEBUG("reg_ft1000_netdev returned\n");
-
-	pInfo->CardReady = 1;
-
-	return 0;
-}
-
-int ft1000_reset(void *dev)
-{
-	ft1000_reset_card(dev);
-	return 0;
-}
-
 //---------------------------------------------------------------------------
 // Function:    ft1000_usb_transmit_complete
 //
@@ -963,7 +769,6 @@
 	return 0;
 }
 
-
 //---------------------------------------------------------------------------
 // Function:    ft1000_start_xmit
 //
@@ -1022,6 +827,238 @@
 	return NETDEV_TX_OK;
 }
 
+//---------------------------------------------------------------------------
+// Function:    ft1000_open
+//
+// Parameters:
+//              dev - network device
+//
+//
+// Returns:     none
+//
+// Description: open the network driver
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+static int ft1000_open(struct net_device *dev)
+{
+	struct ft1000_info *pInfo = netdev_priv(dev);
+	struct ft1000_usb *pFt1000Dev = pInfo->priv;
+	struct timeval tv;
+
+	DEBUG("ft1000_open is called for card %d\n", pFt1000Dev->CardNumber);
+
+	pInfo->stats.rx_bytes = 0;
+	pInfo->stats.tx_bytes = 0;
+	pInfo->stats.rx_packets = 0;
+	pInfo->stats.tx_packets = 0;
+	do_gettimeofday(&tv);
+	pInfo->ConTm = tv.tv_sec;
+	pInfo->ProgConStat = 0;
+
+	netif_start_queue(dev);
+
+	netif_carrier_on(dev);
+
+	return ft1000_submit_rx_urb(pInfo);
+}
+
+static struct net_device_stats *ft1000_netdev_stats(struct net_device *dev)
+{
+	struct ft1000_info *info = netdev_priv(dev);
+
+	return &(info->stats);
+}
+
+static const struct net_device_ops ftnet_ops =
+{
+	.ndo_open = &ft1000_open,
+	.ndo_stop = &ft1000_close,
+	.ndo_start_xmit = &ft1000_start_xmit,
+	.ndo_get_stats = &ft1000_netdev_stats,
+};
+
+//---------------------------------------------------------------------------
+// Function:    init_ft1000_netdev
+//
+// Parameters:  ft1000dev  - device structure
+//
+//
+// Returns:     STATUS_SUCCESS - success
+//              STATUS_FAILURE - failure
+//
+// Description: This function initialize the network device
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+static int ft1000_reset(void *dev)
+{
+	ft1000_reset_card(dev);
+	return 0;
+}
+
+int init_ft1000_netdev(struct ft1000_usb *ft1000dev)
+{
+	struct net_device *netdev;
+	struct ft1000_info *pInfo = NULL;
+	struct dpram_blk *pdpram_blk;
+	int i, ret_val;
+	struct list_head *cur, *tmp;
+	char card_nr[2];
+	u8 gCardIndex = 0;
+
+	DEBUG("Enter init_ft1000_netdev...\n");
+
+	netdev = alloc_etherdev(sizeof(struct ft1000_info));
+	if (!netdev) {
+		DEBUG("init_ft1000_netdev: can not allocate network device\n");
+		return -ENOMEM;
+	}
+
+	pInfo = netdev_priv(netdev);
+
+	memset(pInfo, 0, sizeof(struct ft1000_info));
+
+	dev_alloc_name(netdev, netdev->name);
+
+	DEBUG("init_ft1000_netdev: network device name is %s\n", netdev->name);
+
+	if (strncmp(netdev->name, "eth", 3) == 0) {
+		card_nr[0] = netdev->name[3];
+		card_nr[1] = '\0';
+		ret_val = kstrtou8(card_nr, 10, &gCardIndex);
+		if (ret_val) {
+			printk(KERN_ERR "Can't parse netdev\n");
+			goto err_net;
+		}
+
+		ft1000dev->CardNumber = gCardIndex;
+		DEBUG("card number = %d\n", ft1000dev->CardNumber);
+	} else {
+		printk(KERN_ERR "ft1000: Invalid device name\n");
+		ret_val = -ENXIO;
+		goto err_net;
+	}
+
+	memset(&pInfo->stats, 0, sizeof(struct net_device_stats));
+
+	spin_lock_init(&pInfo->dpram_lock);
+	pInfo->priv = ft1000dev;
+	pInfo->DrvErrNum = 0;
+	pInfo->registered = 1;
+	pInfo->ft1000_reset = ft1000_reset;
+	pInfo->mediastate = 0;
+	pInfo->fifo_cnt = 0;
+	ft1000dev->DeviceCreated = FALSE;
+	pInfo->CardReady = 0;
+	pInfo->DSP_TIME[0] = 0;
+	pInfo->DSP_TIME[1] = 0;
+	pInfo->DSP_TIME[2] = 0;
+	pInfo->DSP_TIME[3] = 0;
+	ft1000dev->fAppMsgPend = false;
+	ft1000dev->fCondResetPend = false;
+	ft1000dev->usbboot = 0;
+	ft1000dev->dspalive = 0;
+	memset(&ft1000dev->tempbuf[0], 0, sizeof(ft1000dev->tempbuf));
+
+	INIT_LIST_HEAD(&pInfo->prov_list);
+
+	INIT_LIST_HEAD(&ft1000dev->nodes.list);
+
+	netdev->netdev_ops = &ftnet_ops;
+
+	ft1000dev->net = netdev;
+
+	DEBUG("Initialize free_buff_lock and freercvpool\n");
+	spin_lock_init(&free_buff_lock);
+
+	/* initialize a list of buffers to be use for queuing
+	 * up receive command data
+	 */
+	INIT_LIST_HEAD(&freercvpool);
+
+	/* create list of free buffers */
+	for (i = 0; i < NUM_OF_FREE_BUFFERS; i++) {
+		/* Get memory for DPRAM_DATA link list */
+		pdpram_blk = kmalloc(sizeof(struct dpram_blk), GFP_KERNEL);
+		if (pdpram_blk == NULL) {
+			ret_val = -ENOMEM;
+			goto err_free;
+		}
+		/* Get a block of memory to store command data */
+		pdpram_blk->pbuffer = kmalloc(MAX_CMD_SQSIZE, GFP_KERNEL);
+		if (pdpram_blk->pbuffer == NULL) {
+			ret_val = -ENOMEM;
+			kfree(pdpram_blk);
+			goto err_free;
+		}
+		/* link provisioning data */
+		list_add_tail(&pdpram_blk->list, &freercvpool);
+	}
+	numofmsgbuf = NUM_OF_FREE_BUFFERS;
+
+	return 0;
+
+err_free:
+	list_for_each_safe(cur, tmp, &freercvpool) {
+		pdpram_blk = list_entry(cur, struct dpram_blk, list);
+		list_del(&pdpram_blk->list);
+		kfree(pdpram_blk->pbuffer);
+		kfree(pdpram_blk);
+	}
+err_net:
+	free_netdev(netdev);
+	return ret_val;
+}
+
+//---------------------------------------------------------------------------
+// Function:    reg_ft1000_netdev
+//
+// Parameters:  ft1000dev  - device structure
+//
+//
+// Returns:     STATUS_SUCCESS - success
+//              STATUS_FAILURE - failure
+//
+// Description: This function register the network driver
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+int reg_ft1000_netdev(struct ft1000_usb *ft1000dev,
+		      struct usb_interface *intf)
+{
+	struct net_device *netdev;
+	struct ft1000_info *pInfo;
+	int rc;
+
+	netdev = ft1000dev->net;
+	pInfo = netdev_priv(ft1000dev->net);
+	DEBUG("Enter reg_ft1000_netdev...\n");
+
+	ft1000_read_register(ft1000dev, &pInfo->AsicID, FT1000_REG_ASIC_ID);
+
+	usb_set_intfdata(intf, pInfo);
+	SET_NETDEV_DEV(netdev, &intf->dev);
+
+	rc = register_netdev(netdev);
+	if (rc) {
+		DEBUG("reg_ft1000_netdev: could not register network device\n");
+		free_netdev(netdev);
+		return rc;
+	}
+
+	ft1000_create_dev(ft1000dev);
+
+	DEBUG("reg_ft1000_netdev returned\n");
+
+	pInfo->CardReady = 1;
+
+	return 0;
+}
 
 //---------------------------------------------------------------------------
 //
@@ -1159,44 +1196,6 @@
 	return 0;
 }
 
-
-//---------------------------------------------------------------------------
-// Function:    ft1000_open
-//
-// Parameters:
-//              dev - network device
-//
-//
-// Returns:     none
-//
-// Description: open the network driver
-//
-// Notes:
-//
-//---------------------------------------------------------------------------
-static int ft1000_open(struct net_device *dev)
-{
-	struct ft1000_info *pInfo = netdev_priv(dev);
-	struct ft1000_usb *pFt1000Dev = pInfo->priv;
-	struct timeval tv;
-
-	DEBUG("ft1000_open is called for card %d\n", pFt1000Dev->CardNumber);
-
-	pInfo->stats.rx_bytes = 0;
-	pInfo->stats.tx_bytes = 0;
-	pInfo->stats.rx_packets = 0;
-	pInfo->stats.tx_packets = 0;
-	do_gettimeofday(&tv);
-	pInfo->ConTm = tv.tv_sec;
-	pInfo->ProgConStat = 0;
-
-	netif_start_queue(dev);
-
-	netif_carrier_on(dev);
-
-	return ft1000_submit_rx_urb(pInfo);
-}
-
 //---------------------------------------------------------------------------
 // Function:    ft1000_close
 //
@@ -1228,14 +1227,6 @@
 	return 0;
 }
 
-static struct net_device_stats *ft1000_netdev_stats(struct net_device *dev)
-{
-	struct ft1000_info *info = netdev_priv(dev);
-
-	return &(info->stats);
-}
-
-
 //---------------------------------------------------------------------------
 //
 // Function:   ft1000_chkcard
@@ -1441,7 +1432,7 @@
 
 	msleep(100);
 
-	dev->fProvComplete = 1;
+	dev->fProvComplete = true;
 	info->CardReady = 1;
 
 	return STATUS_SUCCESS;
@@ -1567,12 +1558,12 @@
 			 * Send provisioning data to DSP
 			 */
 			if (list_empty(&info->prov_list) == 0) {
-				dev->fProvComplete = 0;
+				dev->fProvComplete = false;
 				status = ft1000_dsp_prov(dev);
 				if (status != STATUS_SUCCESS)
 					goto out;
 			} else {
-				dev->fProvComplete = 1;
+				dev->fProvComplete = true;
 				status =
 				    ft1000_write_register(dev, FT1000_DB_HB,
 							  FT1000_REG_DOORBELL);
@@ -1921,7 +1912,7 @@
         else if (tempword & FT1000_DB_COND_RESET) {
             DEBUG("ft1000_poll: FT1000_REG_DOORBELL message type:  FT1000_DB_COND_RESET\n");
 
-	    if (dev->fAppMsgPend == 0) {
+	    if (!dev->fAppMsgPend) {
                // Reset ASIC and DSP
 
                 status    = ft1000_read_dpram16(dev, FT1000_MAG_DSP_TIMER0, (u8 *)&(info->DSP_TIME[0]), FT1000_MAG_DSP_TIMER0_INDX);
@@ -1934,8 +1925,8 @@
                 info->ft1000_reset(dev->net);
             }
             else {
-                dev->fProvComplete = 0;
-                dev->fCondResetPend = 1;
+                dev->fProvComplete = false;
+                dev->fCondResetPend = true;
             }
 
             ft1000_write_register(dev, FT1000_DB_COND_RESET, FT1000_REG_DOORBELL);
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c
index 29a7cd2..a8dd1e5 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c
@@ -36,7 +36,7 @@
 
 MODULE_DEVICE_TABLE(usb, id_table);
 
-static bool gPollingfailed = FALSE;
+static bool gPollingfailed = false;
 static int ft1000_poll_thread(void *arg)
 {
 	int ret;
@@ -47,7 +47,7 @@
 			ret = ft1000_poll(arg);
 			if (ret != STATUS_SUCCESS) {
 				DEBUG("ft1000_poll_thread: polling failed\n");
-				gPollingfailed = TRUE;
+				gPollingfailed = true;
 			}
 		}
 	}
@@ -171,7 +171,7 @@
 		goto err_load;
 	}
 
-	gPollingfailed = FALSE;
+	gPollingfailed = false;
 	ft1000dev->pPollThread =
 	    kthread_run(ft1000_poll_thread, ft1000dev, "ft1000_poll");
 
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
index bd1da1f..e8d00a9 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
@@ -125,7 +125,7 @@
 extern int numofmsgbuf;
 
 int ft1000_close(struct net_device *dev);
-u16 scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart,
+int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart,
 		u32  FileLength);
 
 extern struct list_head freercvpool;
diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c
index ff92f34..62df009 100644
--- a/drivers/staging/fwserial/fwserial.c
+++ b/drivers/staging/fwserial/fwserial.c
@@ -2394,7 +2394,8 @@
 
 	list_del_rcu(&serial->list);
 	if (create_loop_dev)
-		tty_unregister_device(fwloop_driver, loop_idx(serial->ports[j]));
+		tty_unregister_device(fwloop_driver,
+				      loop_idx(serial->ports[j]));
 unregister_ttys:
 	for (--j; j >= 0; --j)
 		tty_unregister_device(fwtty_driver, serial->ports[j]->index);
diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c
index bc0d510..c57a6ba 100644
--- a/drivers/staging/gdm724x/gdm_lte.c
+++ b/drivers/staging/gdm724x/gdm_lte.c
@@ -110,7 +110,7 @@
 	return 0;
 }
 
-int gdm_lte_emulate_arp(struct sk_buff *skb_in, u32 nic_type)
+static int gdm_lte_emulate_arp(struct sk_buff *skb_in, u32 nic_type)
 {
 	struct nic *nic = netdev_priv(skb_in->dev);
 	struct sk_buff *skb_out;
@@ -186,7 +186,7 @@
 	return 0;
 }
 
-int icmp6_checksum(struct ipv6hdr *ipv6, u16 *ptr, int len)
+static int icmp6_checksum(struct ipv6hdr *ipv6, u16 *ptr, int len)
 {
 	unsigned short *w = ptr;
 	int sum = 0;
@@ -226,7 +226,7 @@
 	return sum;
 }
 
-int gdm_lte_emulate_ndp(struct sk_buff *skb_in, u32 nic_type)
+static int gdm_lte_emulate_ndp(struct sk_buff *skb_in, u32 nic_type)
 {
 	struct nic *nic = netdev_priv(skb_in->dev);
 	struct sk_buff *skb_out;
diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c
index 5b1ef40..6216367 100644
--- a/drivers/staging/gdm724x/gdm_mux.c
+++ b/drivers/staging/gdm724x/gdm_mux.c
@@ -26,7 +26,7 @@
 
 #include "gdm_mux.h"
 
-struct workqueue_struct *mux_rx_wq;
+static struct workqueue_struct *mux_rx_wq;
 
 static u16 packet_type[TTY_MAX_COUNT] = {0xF011, 0xF010};
 
@@ -51,7 +51,7 @@
 
 MODULE_DEVICE_TABLE(usb, id_table);
 
-int packet_type_to_index(u16 packetType)
+static int packet_type_to_index(u16 packetType)
 {
 	int i;
 
@@ -96,12 +96,12 @@
 {
 	struct mux_rx *r = NULL;
 
-	r = kzalloc(sizeof(struct mux_rx), GFP_ATOMIC);
+	r = kzalloc(sizeof(struct mux_rx), GFP_KERNEL);
 	if (!r)
 		return NULL;
 
-	r->urb = usb_alloc_urb(0, GFP_ATOMIC);
-	r->buf = kmalloc(MUX_RX_MAX_SIZE, GFP_ATOMIC);
+	r->urb = usb_alloc_urb(0, GFP_KERNEL);
+	r->buf = kmalloc(MUX_RX_MAX_SIZE, GFP_KERNEL);
 	if (!r->urb || !r->buf) {
 		usb_free_urb(r->urb);
 		kfree(r->buf);
@@ -541,7 +541,7 @@
 
 	ret = init_usb(mux_dev);
 	if (ret)
-		goto err_free_tty;
+		goto err_free_usb;
 
 	tty_dev->priv_dev = (void *)mux_dev;
 	tty_dev->send_func = gdm_mux_send;
@@ -565,8 +565,8 @@
 
 err_unregister_tty:
 	unregister_lte_tty_device(tty_dev);
+err_free_usb:
 	release_usb(mux_dev);
-err_free_tty:
 	kfree(tty_dev);
 err_free_mux:
 	kfree(mux_dev);
diff --git a/drivers/staging/gdm724x/gdm_tty.c b/drivers/staging/gdm724x/gdm_tty.c
index 0247a20..c0f7cd7 100644
--- a/drivers/staging/gdm724x/gdm_tty.c
+++ b/drivers/staging/gdm724x/gdm_tty.c
@@ -171,7 +171,8 @@
 	tty_port_tty_wakeup(&gdm->port);
 }
 
-static int gdm_tty_write(struct tty_struct *tty, const unsigned char *buf, int len)
+static int gdm_tty_write(struct tty_struct *tty, const unsigned char *buf,
+			 int len)
 {
 	struct gdm *gdm = tty->driver_data;
 	int remain = len;
@@ -185,7 +186,8 @@
 		return 0;
 
 	while (1) {
-		sending_len = remain > MUX_TX_MAX_SIZE ? MUX_TX_MAX_SIZE : remain;
+		sending_len = remain > MUX_TX_MAX_SIZE ? MUX_TX_MAX_SIZE :
+							 remain;
 		gdm_tty_send(gdm,
 			     (void *)(buf+sent_len),
 			     sending_len,
@@ -247,7 +249,8 @@
 		gdm->minor = j;
 		gdm->tty_dev = tty_dev;
 
-		tty_port_register_device(&gdm->port, gdm_driver[i], gdm->minor, device);
+		tty_port_register_device(&gdm->port, gdm_driver[i],
+					 gdm->minor, device);
 	}
 
 	for (i = 0; i < MAX_ISSUE_NUM; i++)
@@ -309,7 +312,8 @@
 		tty_driver->major = GDM_TTY_MAJOR;
 		tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
 		tty_driver->subtype = SERIAL_TYPE_NORMAL;
-		tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+		tty_driver->flags = TTY_DRIVER_REAL_RAW |
+					TTY_DRIVER_DYNAMIC_DEV;
 		tty_driver->init_termios = tty_std_termios;
 		tty_driver->init_termios.c_cflag = B9600 | CS8 | HUPCL | CLOCAL;
 		tty_driver->init_termios.c_lflag = ISIG | ICANON | IEXTEN;
diff --git a/drivers/staging/gdm724x/gdm_usb.c b/drivers/staging/gdm724x/gdm_usb.c
index bdc9637..781134a 100644
--- a/drivers/staging/gdm724x/gdm_usb.c
+++ b/drivers/staging/gdm724x/gdm_usb.c
@@ -88,12 +88,11 @@
 	struct usb_tx *t = NULL;
 	int ret = 0;
 
-	t = kmalloc(sizeof(struct usb_tx), GFP_ATOMIC);
+	t = kzalloc(sizeof(struct usb_tx), GFP_ATOMIC);
 	if (!t) {
 		ret = -ENOMEM;
 		goto out;
 	}
-	memset(t, 0, sizeof(struct usb_tx));
 
 	t->urb = usb_alloc_urb(0, GFP_ATOMIC);
 	if (!(len % 512))
@@ -124,12 +123,11 @@
 	int ret = 0;
 
 
-	t_sdu = kmalloc(sizeof(struct usb_tx_sdu), GFP_ATOMIC);
+	t_sdu = kzalloc(sizeof(struct usb_tx_sdu), GFP_ATOMIC);
 	if (!t_sdu) {
 		ret = -ENOMEM;
 		goto out;
 	}
-	memset(t_sdu, 0, sizeof(struct usb_tx_sdu));
 
 	t_sdu->buf = kmalloc(SDU_BUF_SIZE, GFP_ATOMIC);
 	if (!t_sdu->buf) {
diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h
index cf32ae0..35154d6 100644
--- a/drivers/staging/iio/Documentation/iio_utils.h
+++ b/drivers/staging/iio/Documentation/iio_utils.h
@@ -502,7 +502,7 @@
 
 inline int _write_sysfs_int(char *filename, char *basedir, int val, int verify)
 {
-	int ret;
+	int ret = 0;
 	FILE *sysfsfp;
 	int test;
 	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
diff --git a/drivers/staging/iio/TODO b/drivers/staging/iio/TODO
index 04c2326..c22a0ed 100644
--- a/drivers/staging/iio/TODO
+++ b/drivers/staging/iio/TODO
@@ -13,6 +13,17 @@
 3) Expand device set. Lots of other maxim adc's have very
    similar interfaces.
 
+MXS LRADC driver:
+This is a classic MFD device as it combines the following subdevices
+ - touchscreen controller (input subsystem related device)
+ - general purpose ADC channels
+ - battery voltage monitor (power subsystem related device)
+ - die temperature monitor (thermal management)
+
+At least the battery voltage and die temperature feature is required in-kernel
+by a driver of the SoC's battery charging unit to avoid any damage to the
+silicon and the battery.
+
 TSL2561
 Would be nice
 1) Open question of userspace vs kernel space balance when
diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c
index 5c28961..4c9364b 100644
--- a/drivers/staging/iio/accel/adis16220_core.c
+++ b/drivers/staging/iio/accel/adis16220_core.c
@@ -102,7 +102,6 @@
 					int addr)
 {
 	struct adis16220_state *st = iio_priv(indio_dev);
-	struct spi_message msg;
 	struct spi_transfer xfers[] = {
 		{
 			.tx_buf = st->tx,
@@ -147,10 +146,7 @@
 	}
 	xfers[1].len = count;
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->adis.spi, &msg);
+	ret = spi_sync_transfer(st->adis.spi, xfers, ARRAY_SIZE(xfers));
 	if (ret) {
 
 		mutex_unlock(&st->buf_lock);
diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c
index bb852dc..735c0a3 100644
--- a/drivers/staging/iio/accel/lis3l02dq_core.c
+++ b/drivers/staging/iio/accel/lis3l02dq_core.c
@@ -190,15 +190,26 @@
 };
 
 static int lis3l02dq_read_thresh(struct iio_dev *indio_dev,
-				 u64 e,
-				 int *val)
+				 const struct iio_chan_spec *chan,
+				 enum iio_event_type type,
+				 enum iio_event_direction dir,
+				 enum iio_event_info info,
+				 int *val, int *val2)
 {
-	return lis3l02dq_read_reg_s16(indio_dev, LIS3L02DQ_REG_THS_L_ADDR, val);
+	int ret;
+
+	ret = lis3l02dq_read_reg_s16(indio_dev, LIS3L02DQ_REG_THS_L_ADDR, val);
+	if (ret)
+		return ret;
+	return IIO_VAL_INT;
 }
 
 static int lis3l02dq_write_thresh(struct iio_dev *indio_dev,
-				  u64 event_code,
-				  int val)
+				  const struct iio_chan_spec *chan,
+				  enum iio_event_type type,
+				  enum iio_event_direction dir,
+				  enum iio_event_info info,
+				  int val, int val2)
 {
 	u16 value = val;
 	return lis3l02dq_spi_write_reg_s16(indio_dev,
@@ -503,9 +514,19 @@
 	return IRQ_HANDLED;
 }
 
-#define LIS3L02DQ_EVENT_MASK					\
-	(IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) |	\
-	 IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING))
+static const struct iio_event_spec lis3l02dq_event[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_ENABLE),
+		.mask_shared_by_type = BIT(IIO_EV_INFO_VALUE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_ENABLE),
+		.mask_shared_by_type = BIT(IIO_EV_INFO_VALUE),
+	}
+};
 
 #define LIS3L02DQ_CHAN(index, mod)				\
 	{							\
@@ -523,7 +544,8 @@
 			.realbits = 12,				\
 			.storagebits = 16,			\
 		},						\
-		.event_mask = LIS3L02DQ_EVENT_MASK,		\
+		.event_spec = lis3l02dq_event,			\
+		.num_event_specs = ARRAY_SIZE(lis3l02dq_event),	\
 	 }
 
 static const struct iio_chan_spec lis3l02dq_channels[] = {
@@ -535,14 +557,14 @@
 
 
 static int lis3l02dq_read_event_config(struct iio_dev *indio_dev,
-					   u64 event_code)
+				       const struct iio_chan_spec *chan,
+				       enum iio_event_type type,
+				       enum iio_event_direction dir)
 {
 
 	u8 val;
 	int ret;
-	u8 mask = (1 << (IIO_EVENT_CODE_EXTRACT_MODIFIER(event_code)*2 +
-			 (IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
-			  IIO_EV_DIR_RISING)));
+	u8 mask = (1 << (chan->channel2*2 + (dir == IIO_EV_DIR_RISING)));
 	ret = lis3l02dq_spi_read_reg_8(indio_dev,
 				       LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
 				       &val);
@@ -587,16 +609,16 @@
 }
 
 static int lis3l02dq_write_event_config(struct iio_dev *indio_dev,
-					u64 event_code,
+					const struct iio_chan_spec *chan,
+					enum iio_event_type type,
+					enum iio_event_direction dir,
 					int state)
 {
 	int ret = 0;
 	u8 val, control;
 	u8 currentlyset;
 	bool changed = false;
-	u8 mask = (1 << (IIO_EVENT_CODE_EXTRACT_MODIFIER(event_code)*2 +
-			 (IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
-			  IIO_EV_DIR_RISING)));
+	u8 mask = (1 << (chan->channel2*2 + (dir == IIO_EV_DIR_RISING)));
 
 	mutex_lock(&indio_dev->mlock);
 	/* read current control */
@@ -654,10 +676,10 @@
 static const struct iio_info lis3l02dq_info = {
 	.read_raw = &lis3l02dq_read_raw,
 	.write_raw = &lis3l02dq_write_raw,
-	.read_event_value = &lis3l02dq_read_thresh,
-	.write_event_value = &lis3l02dq_write_thresh,
-	.write_event_config = &lis3l02dq_write_event_config,
-	.read_event_config = &lis3l02dq_read_event_config,
+	.read_event_value_new = &lis3l02dq_read_thresh,
+	.write_event_value_new = &lis3l02dq_write_thresh,
+	.write_event_config_new = &lis3l02dq_write_event_config,
+	.read_event_config_new = &lis3l02dq_read_event_config,
 	.driver_module = THIS_MODULE,
 	.attrs = &lis3l02dq_attribute_group,
 };
@@ -694,7 +716,7 @@
 				  lis3l02dq_channels,
 				  ARRAY_SIZE(lis3l02dq_channels));
 	if (ret) {
-		printk(KERN_ERR "failed to initialize the buffer\n");
+		dev_err(&spi->dev, "failed to initialize the buffer\n");
 		goto error_unreg_buffer_funcs;
 	}
 
diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c
index 5b8f0f6..79cefe0 100644
--- a/drivers/staging/iio/accel/lis3l02dq_ring.c
+++ b/drivers/staging/iio/accel/lis3l02dq_ring.c
@@ -111,7 +111,7 @@
 				u8 *buf)
 {
 	int ret, i;
-	u8 *rx_array ;
+	u8 *rx_array;
 	s16 *data = (s16 *)buf;
 	int scan_count = bitmap_weight(indio_dev->active_scan_mask,
 				       indio_dev->masklength);
@@ -146,11 +146,7 @@
 	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
 		len = lis3l02dq_get_buffer_element(indio_dev, data);
 
-	  /* Guaranteed to be aligned with 8 byte boundary */
-	if (indio_dev->scan_timestamp)
-		*(s64 *)((u8 *)data + ALIGN(len, sizeof(s64)))
-			= pf->timestamp;
-	iio_push_to_buffers(indio_dev, (u8 *)data);
+	iio_push_to_buffers_with_timestamp(indio_dev, data, pf->timestamp);
 
 	kfree(data);
 done:
@@ -264,8 +260,7 @@
 		else
 			break;
 	if (i == 5)
-		printk(KERN_INFO
-		       "Failed to clear the interrupt for lis3l02dq\n");
+		pr_info("Failed to clear the interrupt for lis3l02dq\n");
 
 	/* irq reenabled so success! */
 	return 0;
@@ -387,7 +382,6 @@
 }
 
 static const struct iio_buffer_setup_ops lis3l02dq_buffer_setup_ops = {
-	.preenable = &iio_sw_buffer_preenable,
 	.postenable = &lis3l02dq_buffer_postenable,
 	.predisable = &lis3l02dq_buffer_predisable,
 };
@@ -401,7 +395,7 @@
 	if (!buffer)
 		return -ENOMEM;
 
-	indio_dev->buffer = buffer;
+	iio_device_attach_buffer(indio_dev, buffer);
 
 	buffer->scan_timestamp = true;
 	indio_dev->setup_ops = &lis3l02dq_buffer_setup_ops;
diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c
index 48a25ba..c49e6ef 100644
--- a/drivers/staging/iio/accel/sca3000_core.c
+++ b/drivers/staging/iio/accel/sca3000_core.c
@@ -419,8 +419,11 @@
 
 static IIO_DEVICE_ATTR(revision, S_IRUGO, sca3000_show_rev, NULL, 0);
 
-#define SCA3000_EVENT_MASK					\
-	(IIO_EV_BIT(IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING))
+static const struct iio_event_spec sca3000_event = {
+	.type = IIO_EV_TYPE_MAG,
+	.dir = IIO_EV_DIR_RISING,
+	.mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE),
+};
 
 #define SCA3000_CHAN(index, mod)				\
 	{							\
@@ -437,7 +440,8 @@
 			.storagebits = 16,			\
 			.shift = 5,				\
 		},						\
-		.event_mask = SCA3000_EVENT_MASK,		\
+		.event_spec = &sca3000_event,			\
+		.num_event_specs = 1,				\
 	 }
 
 static const struct iio_chan_spec sca3000_channels[] = {
@@ -624,9 +628,9 @@
 	struct sca3000_state *st = iio_priv(indio_dev);
 	int ret, base_freq = 0;
 	int ctrlval;
-	long val;
+	int val;
 
-	ret = strict_strtol(buf, 10, &val);
+	ret = kstrtoint(buf, 10, &val);
 	if (ret)
 		return ret;
 
@@ -703,12 +707,15 @@
  * sca3000_read_thresh() - query of a threshold
  **/
 static int sca3000_read_thresh(struct iio_dev *indio_dev,
-			       u64 e,
-			       int *val)
+			       const struct iio_chan_spec *chan,
+			       enum iio_event_type type,
+			       enum iio_event_direction dir,
+			       enum iio_event_info info,
+			       int *val, int *val2)
 {
 	int ret, i;
 	struct sca3000_state *st = iio_priv(indio_dev);
-	int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e);
+	int num = chan->channel2;
 	mutex_lock(&st->lock);
 	ret = sca3000_read_ctrl_reg(st, sca3000_addresses[num][1]);
 	mutex_unlock(&st->lock);
@@ -724,18 +731,21 @@
 				 ARRAY_SIZE(st->info->mot_det_mult_xz))
 			*val += st->info->mot_det_mult_xz[i];
 
-	return 0;
+	return IIO_VAL_INT;
 }
 
 /**
  * sca3000_write_thresh() control of threshold
  **/
 static int sca3000_write_thresh(struct iio_dev *indio_dev,
-				u64 e,
-				int val)
+				const struct iio_chan_spec *chan,
+				enum iio_event_type type,
+				enum iio_event_direction dir,
+				enum iio_event_info info,
+				int val, int val2)
 {
 	struct sca3000_state *st = iio_priv(indio_dev);
-	int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e);
+	int num = chan->channel2;
 	int ret;
 	int i;
 	u8 nonlinear = 0;
@@ -866,12 +876,14 @@
  * sca3000_read_event_config() what events are enabled
  **/
 static int sca3000_read_event_config(struct iio_dev *indio_dev,
-				     u64 e)
+				     const struct iio_chan_spec *chan,
+				     enum iio_event_type type,
+				     enum iio_event_direction dir)
 {
 	struct sca3000_state *st = iio_priv(indio_dev);
 	int ret;
 	u8 protect_mask = 0x03;
-	int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e);
+	int num = chan->channel2;
 
 	/* read current value of mode register */
 	mutex_lock(&st->lock);
@@ -931,12 +943,12 @@
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct sca3000_state *st = iio_priv(indio_dev);
-	long val;
+	u8 val;
 	int ret;
 	u8 protect_mask = SCA3000_FREE_FALL_DETECT;
 
 	mutex_lock(&st->lock);
-	ret = strict_strtol(buf, 10, &val);
+	ret = kstrtou8(buf, 10, &val);
 	if (ret)
 		goto error_ret;
 
@@ -969,13 +981,15 @@
  * this mode is disabled.  Currently normal mode is assumed.
  **/
 static int sca3000_write_event_config(struct iio_dev *indio_dev,
-				      u64 e,
+				      const struct iio_chan_spec *chan,
+				      enum iio_event_type type,
+				      enum iio_event_direction dir,
 				      int state)
 {
 	struct sca3000_state *st = iio_priv(indio_dev);
 	int ret, ctrlval;
 	u8 protect_mask = 0x03;
-	int num = IIO_EVENT_CODE_EXTRACT_MODIFIER(e);
+	int num = chan->channel2;
 
 	mutex_lock(&st->lock);
 	/* First read the motion detector config to find out if
@@ -1112,20 +1126,20 @@
 	.attrs = &sca3000_attribute_group,
 	.read_raw = &sca3000_read_raw,
 	.event_attrs = &sca3000_event_attribute_group,
-	.read_event_value = &sca3000_read_thresh,
-	.write_event_value = &sca3000_write_thresh,
-	.read_event_config = &sca3000_read_event_config,
-	.write_event_config = &sca3000_write_event_config,
+	.read_event_value_new = &sca3000_read_thresh,
+	.write_event_value_new = &sca3000_write_thresh,
+	.read_event_config_new = &sca3000_read_event_config,
+	.write_event_config_new = &sca3000_write_event_config,
 	.driver_module = THIS_MODULE,
 };
 
 static const struct iio_info sca3000_info_with_temp = {
 	.attrs = &sca3000_attribute_group_with_temp,
 	.read_raw = &sca3000_read_raw,
-	.read_event_value = &sca3000_read_thresh,
-	.write_event_value = &sca3000_write_thresh,
-	.read_event_config = &sca3000_read_event_config,
-	.write_event_config = &sca3000_write_event_config,
+	.read_event_value_new = &sca3000_read_thresh,
+	.write_event_value_new = &sca3000_write_thresh,
+	.read_event_config_new = &sca3000_read_event_config,
+	.write_event_config_new = &sca3000_write_event_config,
 	.driver_module = THIS_MODULE,
 };
 
diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c
index 3e5e860..ea0af6d 100644
--- a/drivers/staging/iio/accel/sca3000_ring.c
+++ b/drivers/staging/iio/accel/sca3000_ring.c
@@ -177,11 +177,11 @@
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct sca3000_state *st = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-	long val;
+	u8 val;
 	int ret;
 
 	mutex_lock(&st->lock);
-	ret = strict_strtol(buf, 10, &val);
+	ret = kstrtou8(buf, 10, &val);
 	if (ret)
 		goto error_ret;
 	ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1);
@@ -252,7 +252,7 @@
 	struct iio_buffer *buf;
 	struct iio_hw_buffer *ring;
 
-	ring = kzalloc(sizeof *ring, GFP_KERNEL);
+	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
 	if (!ring)
 		return NULL;
 
@@ -265,7 +265,7 @@
 	return buf;
 }
 
-static inline void sca3000_rb_free(struct iio_buffer *r)
+static void sca3000_ring_release(struct iio_buffer *r)
 {
 	kfree(iio_to_hw_buf(r));
 }
@@ -274,23 +274,28 @@
 	.read_first_n = &sca3000_read_first_n_hw_rb,
 	.get_length = &sca3000_ring_get_length,
 	.get_bytes_per_datum = &sca3000_ring_get_bytes_per_datum,
+	.release = sca3000_ring_release,
 };
 
 int sca3000_configure_ring(struct iio_dev *indio_dev)
 {
-	indio_dev->buffer = sca3000_rb_allocate(indio_dev);
-	if (indio_dev->buffer == NULL)
+	struct iio_buffer *buffer;
+
+	buffer = sca3000_rb_allocate(indio_dev);
+	if (buffer == NULL)
 		return -ENOMEM;
 	indio_dev->modes |= INDIO_BUFFER_HARDWARE;
 
 	indio_dev->buffer->access = &sca3000_ring_access_funcs;
 
+	iio_device_attach_buffer(indio_dev, buffer);
+
 	return 0;
 }
 
 void sca3000_unconfigure_ring(struct iio_dev *indio_dev)
 {
-	sca3000_rb_free(indio_dev->buffer);
+	iio_buffer_put(indio_dev->buffer);
 }
 
 static inline
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index cabc7a3..e3d6430 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -102,7 +102,7 @@
 
 config LPC32XX_ADC
 	tristate "NXP LPC32XX ADC"
-	depends on ARCH_LPC32XX
+	depends on ARCH_LPC32XX || COMPILE_TEST
 	help
 	  Say yes here to build support for the integrated ADC inside the
 	  LPC32XX SoC. Note that this feature uses the same hardware as the
@@ -113,7 +113,9 @@
 
 config MXS_LRADC
 	tristate "Freescale i.MX23/i.MX28 LRADC"
-	depends on ARCH_MXS
+	depends on ARCH_MXS || COMPILE_TEST
+	depends on INPUT
+	select STMP_DEVICE
 	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
 	help
@@ -125,7 +127,7 @@
 
 config SPEAR_ADC
 	tristate "ST SPEAr ADC"
-	depends on PLAT_SPEAR
+	depends on PLAT_SPEAR || COMPILE_TEST
 	help
 	  Say yes here to build support for the integrated ADC inside the
 	  ST SPEAr SoC. Provides direct access via sysfs.
diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
index 3283e282..83bb44b 100644
--- a/drivers/staging/iio/adc/ad7192.c
+++ b/drivers/staging/iio/adc/ad7192.c
@@ -623,17 +623,17 @@
 		return -ENODEV;
 	}
 
-	indio_dev = iio_device_alloc(sizeof(*st));
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (indio_dev == NULL)
 		return -ENOMEM;
 
 	st = iio_priv(indio_dev);
 
-	st->reg = regulator_get(&spi->dev, "vcc");
+	st->reg = devm_regulator_get(&spi->dev, "vcc");
 	if (!IS_ERR(st->reg)) {
 		ret = regulator_enable(st->reg);
 		if (ret)
-			goto error_put_reg;
+			return ret;
 
 		voltage_uv = regulator_get_voltage(st->reg);
 	}
@@ -677,11 +677,6 @@
 error_disable_reg:
 	if (!IS_ERR(st->reg))
 		regulator_disable(st->reg);
-error_put_reg:
-	if (!IS_ERR(st->reg))
-		regulator_put(st->reg);
-
-	iio_device_free(indio_dev);
 
 	return ret;
 }
@@ -694,10 +689,8 @@
 	iio_device_unregister(indio_dev);
 	ad_sd_cleanup_buffer_and_trigger(indio_dev);
 
-	if (!IS_ERR(st->reg)) {
+	if (!IS_ERR(st->reg))
 		regulator_disable(st->reg);
-		regulator_put(st->reg);
-	}
 
 	return 0;
 }
diff --git a/drivers/staging/iio/adc/ad7280a.c b/drivers/staging/iio/adc/ad7280a.c
index c19618b..8209fa5 100644
--- a/drivers/staging/iio/adc/ad7280a.c
+++ b/drivers/staging/iio/adc/ad7280a.c
@@ -783,7 +783,6 @@
 			   long m)
 {
 	struct ad7280_state *st = iio_priv(indio_dev);
-	unsigned int scale_uv;
 	int ret;
 
 	switch (m) {
@@ -804,13 +803,12 @@
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
 		if ((chan->address & 0xFF) <= AD7280A_CELL_VOLTAGE_6)
-			scale_uv = (4000 * 1000) >> AD7280A_BITS;
+			*val = 4000;
 		else
-			scale_uv = (5000 * 1000) >> AD7280A_BITS;
+			*val = 5000;
 
-		*val =  scale_uv / 1000;
-		*val2 = (scale_uv % 1000) * 1000;
-		return IIO_VAL_INT_PLUS_MICRO;
+		*val2 = AD7280A_BITS;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	}
 	return -EINVAL;
 }
@@ -835,8 +833,9 @@
 	int ret;
 	const unsigned short tACQ_ns[4] = {465, 1010, 1460, 1890};
 	const unsigned short nAVG[4] = {1, 2, 4, 8};
-	struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
+	struct iio_dev *indio_dev;
 
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (indio_dev == NULL)
 		return -ENOMEM;
 
@@ -860,7 +859,7 @@
 
 	ret = ad7280_chain_setup(st);
 	if (ret < 0)
-		goto error_free_device;
+		return ret;
 
 	st->slave_num = ret;
 	st->scan_cnt = (st->slave_num + 1) * AD7280A_NUM_CH;
@@ -891,7 +890,7 @@
 
 	ret = ad7280_channel_init(st);
 	if (ret < 0)
-		goto error_free_device;
+		return ret;
 
 	indio_dev->num_channels = ret;
 	indio_dev->channels = st->channels;
@@ -940,9 +939,6 @@
 error_free_channels:
 	kfree(st->channels);
 
-error_free_device:
-	iio_device_free(indio_dev);
-
 	return ret;
 }
 
@@ -960,7 +956,6 @@
 
 	kfree(st->channels);
 	kfree(st->iio_attr);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c
index a2e61c2..d13f8ae 100644
--- a/drivers/staging/iio/adc/ad7291.c
+++ b/drivers/staging/iio/adc/ad7291.c
@@ -164,97 +164,14 @@
 	return IRQ_HANDLED;
 }
 
-static inline ssize_t ad7291_show_hyst(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct ad7291_chip_info *chip = iio_priv(indio_dev);
-	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-	u16 data;
-	int ret;
-
-	ret = ad7291_i2c_read(chip, this_attr->address, &data);
-	if (ret < 0)
-		return ret;
-
-	return sprintf(buf, "%d\n", data & AD7291_VALUE_MASK);
-}
-
-static inline ssize_t ad7291_set_hyst(struct device *dev,
-				      struct device_attribute *attr,
-				      const char *buf,
-				      size_t len)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct ad7291_chip_info *chip = iio_priv(indio_dev);
-	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-	u16 data;
-	int ret;
-
-	ret = kstrtou16(buf, 10, &data);
-
-	if (ret < 0)
-		return ret;
-	if (data > AD7291_VALUE_MASK)
-		return -EINVAL;
-
-	ret = ad7291_i2c_write(chip, this_attr->address, data);
-	if (ret < 0)
-		return ret;
-
-	return len;
-}
-
-static IIO_DEVICE_ATTR(in_temp0_thresh_both_hyst_raw,
-		       S_IRUGO | S_IWUSR,
-		       ad7291_show_hyst, ad7291_set_hyst,
-		       AD7291_HYST(8));
-static IIO_DEVICE_ATTR(in_voltage0_thresh_both_hyst_raw,
-		       S_IRUGO | S_IWUSR,
-		       ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(0));
-static IIO_DEVICE_ATTR(in_voltage1_thresh_both_hyst_raw,
-		       S_IRUGO | S_IWUSR,
-		       ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(1));
-static IIO_DEVICE_ATTR(in_voltage2_thresh_both_hyst_raw,
-		       S_IRUGO | S_IWUSR,
-		       ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(2));
-static IIO_DEVICE_ATTR(in_voltage3_thresh_both_hyst_raw,
-		       S_IRUGO | S_IWUSR,
-		       ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(3));
-static IIO_DEVICE_ATTR(in_voltage4_thresh_both_hyst_raw,
-		       S_IRUGO | S_IWUSR,
-		       ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(4));
-static IIO_DEVICE_ATTR(in_voltage5_thresh_both_hyst_raw,
-		       S_IRUGO | S_IWUSR,
-		       ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(5));
-static IIO_DEVICE_ATTR(in_voltage6_thresh_both_hyst_raw,
-		       S_IRUGO | S_IWUSR,
-		       ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(6));
-static IIO_DEVICE_ATTR(in_voltage7_thresh_both_hyst_raw,
-		       S_IRUGO | S_IWUSR,
-		       ad7291_show_hyst, ad7291_set_hyst, AD7291_HYST(7));
-
-static struct attribute *ad7291_event_attributes[] = {
-	&iio_dev_attr_in_temp0_thresh_both_hyst_raw.dev_attr.attr,
-	&iio_dev_attr_in_voltage0_thresh_both_hyst_raw.dev_attr.attr,
-	&iio_dev_attr_in_voltage1_thresh_both_hyst_raw.dev_attr.attr,
-	&iio_dev_attr_in_voltage2_thresh_both_hyst_raw.dev_attr.attr,
-	&iio_dev_attr_in_voltage3_thresh_both_hyst_raw.dev_attr.attr,
-	&iio_dev_attr_in_voltage4_thresh_both_hyst_raw.dev_attr.attr,
-	&iio_dev_attr_in_voltage5_thresh_both_hyst_raw.dev_attr.attr,
-	&iio_dev_attr_in_voltage6_thresh_both_hyst_raw.dev_attr.attr,
-	&iio_dev_attr_in_voltage7_thresh_both_hyst_raw.dev_attr.attr,
-	NULL,
-};
-
-static unsigned int ad7291_threshold_reg(u64 event_code)
+static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan,
+	enum iio_event_direction dir, enum iio_event_info info)
 {
 	unsigned int offset;
 
-	switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
+	switch (chan->type) {
 	case IIO_VOLTAGE:
-		offset = IIO_EVENT_CODE_EXTRACT_CHAN(event_code);
+		offset = chan->channel;
 		break;
 	case IIO_TEMP:
 		offset = 8;
@@ -263,69 +180,78 @@
 	    return 0;
 	}
 
-	if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING)
-		return AD7291_DATA_LOW(offset);
-	else
-		return AD7291_DATA_HIGH(offset);
+	switch (info) {
+	case IIO_EV_INFO_VALUE:
+			if (dir == IIO_EV_DIR_FALLING)
+					return AD7291_DATA_HIGH(offset);
+			else
+					return AD7291_DATA_LOW(offset);
+	case IIO_EV_INFO_HYSTERESIS:
+			return AD7291_HYST(offset);
+	default:
+			break;
+	}
+	return 0;
 }
 
 static int ad7291_read_event_value(struct iio_dev *indio_dev,
-				   u64 event_code,
-				   int *val)
+				   const struct iio_chan_spec *chan,
+				   enum iio_event_type type,
+				   enum iio_event_direction dir,
+				   enum iio_event_info info,
+				   int *val, int *val2)
 {
 	struct ad7291_chip_info *chip = iio_priv(indio_dev);
 	int ret;
 	u16 uval;
 
-	ret = ad7291_i2c_read(chip, ad7291_threshold_reg(event_code), &uval);
+	ret = ad7291_i2c_read(chip, ad7291_threshold_reg(chan, dir, info),
+		&uval);
 	if (ret < 0)
 		return ret;
 
-	switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
-	case IIO_VOLTAGE:
+	if (info == IIO_EV_INFO_HYSTERESIS || chan->type == IIO_VOLTAGE)
 		*val = uval & AD7291_VALUE_MASK;
-		return 0;
-	case IIO_TEMP:
+
+	else
 		*val = sign_extend32(uval, 11);
-		return 0;
-	default:
-		return -EINVAL;
-	};
+
+	return IIO_VAL_INT;
 }
 
 static int ad7291_write_event_value(struct iio_dev *indio_dev,
-				    u64 event_code,
-				    int val)
+				    const struct iio_chan_spec *chan,
+				    enum iio_event_type type,
+				    enum iio_event_direction dir,
+				    enum iio_event_info info,
+				    int val, int val2)
 {
 	struct ad7291_chip_info *chip = iio_priv(indio_dev);
 
-	switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
-	case IIO_VOLTAGE:
+	if (info == IIO_EV_INFO_HYSTERESIS || chan->type == IIO_VOLTAGE) {
 		if (val > AD7291_VALUE_MASK || val < 0)
 			return -EINVAL;
-		break;
-	case IIO_TEMP:
+	} else {
 		if (val > 2047 || val < -2048)
 			return -EINVAL;
-		break;
-	default:
-		return -EINVAL;
 	}
 
-	return ad7291_i2c_write(chip, ad7291_threshold_reg(event_code), val);
+	return ad7291_i2c_write(chip, ad7291_threshold_reg(chan, dir, info),
+		val);
 }
 
 static int ad7291_read_event_config(struct iio_dev *indio_dev,
-				    u64 event_code)
+				    const struct iio_chan_spec *chan,
+				    enum iio_event_type type,
+				    enum iio_event_direction dir)
 {
 	struct ad7291_chip_info *chip = iio_priv(indio_dev);
 	/* To be enabled the channel must simply be on. If any are enabled
 	   we are in continuous sampling mode */
 
-	switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
+	switch (chan->type) {
 	case IIO_VOLTAGE:
-		if (chip->c_mask &
-		    (1 << (15 - IIO_EVENT_CODE_EXTRACT_CHAN(event_code))))
+		if (chip->c_mask & (1 << (15 - chan->channel)))
 			return 1;
 		else
 			return 0;
@@ -339,11 +265,14 @@
 }
 
 static int ad7291_write_event_config(struct iio_dev *indio_dev,
-				     u64 event_code,
+				     const struct iio_chan_spec *chan,
+				     enum iio_event_type type,
+				     enum iio_event_direction dir,
 				     int state)
 {
 	int ret = 0;
 	struct ad7291_chip_info *chip = iio_priv(indio_dev);
+	unsigned int mask;
 	u16 regval;
 
 	mutex_lock(&chip->state_lock);
@@ -354,16 +283,14 @@
 	 * Possible to disable temp as well but that makes single read tricky.
 	 */
 
-	switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) {
+	mask = BIT(15 - chan->channel);
+
+	switch (chan->type) {
 	case IIO_VOLTAGE:
-		if ((!state) && (chip->c_mask & (1 << (15 -
-				IIO_EVENT_CODE_EXTRACT_CHAN(event_code)))))
-			chip->c_mask &= ~(1 << (15 - IIO_EVENT_CODE_EXTRACT_CHAN
-							(event_code)));
-		else if (state && (!(chip->c_mask & (1 << (15 -
-				IIO_EVENT_CODE_EXTRACT_CHAN(event_code))))))
-			chip->c_mask |= (1 << (15 - IIO_EVENT_CODE_EXTRACT_CHAN
-							(event_code)));
+		if ((!state) && (chip->c_mask & mask))
+			chip->c_mask &= ~mask;
+		else if (state && (!(chip->c_mask & mask)))
+			chip->c_mask |= mask;
 		else
 			break;
 
@@ -473,6 +400,24 @@
 	}
 }
 
+static const struct iio_event_spec ad7291_events[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_EITHER,
+		.mask_separate = BIT(IIO_EV_INFO_HYSTERESIS),
+	},
+};
+
 #define AD7291_VOLTAGE_CHAN(_chan)					\
 {									\
 	.type = IIO_VOLTAGE,						\
@@ -480,8 +425,8 @@
 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),		\
 	.indexed = 1,							\
 	.channel = _chan,						\
-	.event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING)|\
-	IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING)		\
+	.event_spec = ad7291_events,					\
+	.num_event_specs = ARRAY_SIZE(ad7291_events),			\
 }
 
 static const struct iio_chan_spec ad7291_channels[] = {
@@ -500,23 +445,17 @@
 				BIT(IIO_CHAN_INFO_SCALE),
 		.indexed = 1,
 		.channel = 0,
-		.event_mask =
-		IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING)|
-		IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING)
+		.event_spec = ad7291_events,
+		.num_event_specs = ARRAY_SIZE(ad7291_events),
 	}
 };
 
-static struct attribute_group ad7291_event_attribute_group = {
-	.attrs = ad7291_event_attributes,
-};
-
 static const struct iio_info ad7291_info = {
 	.read_raw = &ad7291_read_raw,
-	.read_event_config = &ad7291_read_event_config,
-	.write_event_config = &ad7291_write_event_config,
-	.read_event_value = &ad7291_read_event_value,
-	.write_event_value = &ad7291_write_event_value,
-	.event_attrs = &ad7291_event_attribute_group,
+	.read_event_config_new = &ad7291_read_event_config,
+	.write_event_config_new = &ad7291_write_event_config,
+	.read_event_value_new = &ad7291_read_event_value,
+	.write_event_value_new = &ad7291_write_event_value,
 	.driver_module = THIS_MODULE,
 };
 
@@ -528,21 +467,19 @@
 	struct iio_dev *indio_dev;
 	int ret = 0;
 
-	indio_dev = iio_device_alloc(sizeof(*chip));
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
+	if (!indio_dev)
+		return -ENOMEM;
 	chip = iio_priv(indio_dev);
 
 	if (pdata && pdata->use_external_ref) {
-		chip->reg = regulator_get(&client->dev, "vref");
+		chip->reg = devm_regulator_get(&client->dev, "vref");
 		if (IS_ERR(chip->reg))
-			goto error_free;
+			return ret;
 
 		ret = regulator_enable(chip->reg);
 		if (ret)
-			goto error_put_reg;
+			return ret;
 	}
 
 	mutex_init(&chip->state_lock);
@@ -601,12 +538,7 @@
 error_disable_reg:
 	if (chip->reg)
 		regulator_disable(chip->reg);
-error_put_reg:
-	if (chip->reg)
-		regulator_put(chip->reg);
-error_free:
-	iio_device_free(indio_dev);
-error_ret:
+
 	return ret;
 }
 
@@ -620,12 +552,8 @@
 	if (client->irq)
 		free_irq(client->irq, indio_dev);
 
-	if (chip->reg) {
+	if (chip->reg)
 		regulator_disable(chip->reg);
-		regulator_put(chip->reg);
-	}
-
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c
index 72868ce..2083673 100644
--- a/drivers/staging/iio/adc/ad7606_core.c
+++ b/drivers/staging/iio/adc/ad7606_core.c
@@ -85,7 +85,6 @@
 {
 	int ret;
 	struct ad7606_state *st = iio_priv(indio_dev);
-	unsigned int scale_uv;
 
 	switch (m) {
 	case IIO_CHAN_INFO_RAW:
@@ -101,11 +100,9 @@
 		*val = (short) ret;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		scale_uv = (st->range * 1000 * 2)
-			>> st->chip_info->channels[0].scan_type.realbits;
-		*val =  scale_uv / 1000;
-		*val2 = (scale_uv % 1000) * 1000;
-		return IIO_VAL_INT_PLUS_MICRO;
+		*val = st->range * 2;
+		*val2 = st->chip_info->channels[0].scan_type.realbits;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	}
 	return -EINVAL;
 }
@@ -425,8 +422,7 @@
 	struct ad7606_state *st = iio_priv(indio_dev);
 
 	if (iio_buffer_enabled(indio_dev)) {
-		if (!work_pending(&st->poll_work))
-			schedule_work(&st->poll_work);
+		schedule_work(&st->poll_work);
 	} else {
 		st->done = true;
 		wake_up_interruptible(&st->wq_data_avail);
@@ -466,12 +462,11 @@
 	struct ad7606_platform_data *pdata = dev->platform_data;
 	struct ad7606_state *st;
 	int ret;
-	struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
+	struct iio_dev *indio_dev;
 
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
+	if (!indio_dev)
+		return ERR_PTR(-ENOMEM);
 
 	st = iio_priv(indio_dev);
 
@@ -489,11 +484,11 @@
 		st->oversampling = pdata->default_os;
 	}
 
-	st->reg = regulator_get(dev, "vcc");
+	st->reg = devm_regulator_get(dev, "vcc");
 	if (!IS_ERR(st->reg)) {
 		ret = regulator_enable(st->reg);
 		if (ret)
-			goto error_put_reg;
+			return ERR_PTR(ret);
 	}
 
 	st->pdata = pdata;
@@ -554,11 +549,6 @@
 error_disable_reg:
 	if (!IS_ERR(st->reg))
 		regulator_disable(st->reg);
-error_put_reg:
-	if (!IS_ERR(st->reg))
-		regulator_put(st->reg);
-	iio_device_free(indio_dev);
-error_ret:
 	return ERR_PTR(ret);
 }
 
@@ -570,13 +560,10 @@
 	ad7606_ring_cleanup(indio_dev);
 
 	free_irq(irq, indio_dev);
-	if (!IS_ERR(st->reg)) {
+	if (!IS_ERR(st->reg))
 		regulator_disable(st->reg);
-		regulator_put(st->reg);
-	}
 
 	ad7606_free_gpios(st);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c
index 2b25cb0..3bf174c 100644
--- a/drivers/staging/iio/adc/ad7606_ring.c
+++ b/drivers/staging/iio/adc/ad7606_ring.c
@@ -46,7 +46,6 @@
 	struct ad7606_state *st = container_of(work_s, struct ad7606_state,
 						poll_work);
 	struct iio_dev *indio_dev = iio_priv_to_dev(st);
-	s64 time_ns;
 	__u8 *buf;
 	int ret;
 
@@ -78,12 +77,7 @@
 			goto done;
 	}
 
-	time_ns = iio_get_time_ns();
-
-	if (indio_dev->scan_timestamp)
-		*((s64 *)(buf + indio_dev->scan_bytes - sizeof(s64))) = time_ns;
-
-	iio_push_to_buffers(indio_dev, buf);
+	iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns());
 done:
 	gpio_set_value(st->pdata->gpio_convst, 0);
 	iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c
index e1f8860..273add3 100644
--- a/drivers/staging/iio/adc/ad7780.c
+++ b/drivers/staging/iio/adc/ad7780.c
@@ -90,17 +90,14 @@
 			   long m)
 {
 	struct ad7780_state *st = iio_priv(indio_dev);
-	unsigned long scale_uv;
 
 	switch (m) {
 	case IIO_CHAN_INFO_RAW:
 		return ad_sigma_delta_single_conversion(indio_dev, chan, val);
 	case IIO_CHAN_INFO_SCALE:
-		scale_uv = (st->int_vref_mv * 100000 * st->gain)
-			>> (chan->scan_type.realbits - 1);
-		*val =  scale_uv / 100000;
-		*val2 = (scale_uv % 100000) * 10;
-		return IIO_VAL_INT_PLUS_MICRO;
+		*val = st->int_vref_mv * st->gain;
+		*val2 = chan->scan_type.realbits - 1;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	case IIO_CHAN_INFO_OFFSET:
 		*val -= (1 << (chan->scan_type.realbits - 1));
 		return IIO_VAL_INT;
@@ -171,7 +168,7 @@
 	struct iio_dev *indio_dev;
 	int ret, voltage_uv = 0;
 
-	indio_dev = iio_device_alloc(sizeof(*st));
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (indio_dev == NULL)
 		return -ENOMEM;
 
@@ -180,11 +177,11 @@
 
 	ad_sd_init(&st->sd, indio_dev, spi, &ad7780_sigma_delta_info);
 
-	st->reg = regulator_get(&spi->dev, "vcc");
+	st->reg = devm_regulator_get(&spi->dev, "vcc");
 	if (!IS_ERR(st->reg)) {
 		ret = regulator_enable(st->reg);
 		if (ret)
-			goto error_put_reg;
+			return ret;
 
 		voltage_uv = regulator_get_voltage(st->reg);
 	}
@@ -210,8 +207,8 @@
 
 	if (pdata && gpio_is_valid(pdata->gpio_pdrst)) {
 
-		ret = gpio_request_one(pdata->gpio_pdrst, GPIOF_OUT_INIT_LOW,
-			       "AD7780 /PDRST");
+		ret = devm_gpio_request_one(&spi->dev, pdata->gpio_pdrst,
+					GPIOF_OUT_INIT_LOW, "AD7780 /PDRST");
 		if (ret) {
 			dev_err(&spi->dev, "failed to request GPIO PDRST\n");
 			goto error_disable_reg;
@@ -223,7 +220,7 @@
 
 	ret = ad_sd_setup_buffer_and_trigger(indio_dev);
 	if (ret)
-		goto error_free_gpio;
+		goto error_disable_reg;
 
 	ret = iio_device_register(indio_dev);
 	if (ret)
@@ -233,17 +230,9 @@
 
 error_cleanup_buffer_and_trigger:
 	ad_sd_cleanup_buffer_and_trigger(indio_dev);
-error_free_gpio:
-	if (pdata && gpio_is_valid(pdata->gpio_pdrst))
-		gpio_free(pdata->gpio_pdrst);
 error_disable_reg:
 	if (!IS_ERR(st->reg))
 		regulator_disable(st->reg);
-error_put_reg:
-	if (!IS_ERR(st->reg))
-		regulator_put(st->reg);
-
-	iio_device_free(indio_dev);
 
 	return ret;
 }
@@ -256,14 +245,8 @@
 	iio_device_unregister(indio_dev);
 	ad_sd_cleanup_buffer_and_trigger(indio_dev);
 
-	if (gpio_is_valid(st->powerdown_gpio))
-		gpio_free(st->powerdown_gpio);
-
-	if (!IS_ERR(st->reg)) {
+	if (!IS_ERR(st->reg))
 		regulator_disable(st->reg);
-		regulator_put(st->reg);
-	}
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/adc/ad7816.c b/drivers/staging/iio/adc/ad7816.c
index 8470036..9f48e5c 100644
--- a/drivers/staging/iio/adc/ad7816.c
+++ b/drivers/staging/iio/adc/ad7816.c
@@ -356,11 +356,9 @@
 		return -EINVAL;
 	}
 
-	indio_dev = iio_device_alloc(sizeof(*chip));
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	indio_dev = devm_iio_device_alloc(&spi_dev->dev, sizeof(*chip));
+	if (!indio_dev)
+		return -ENOMEM;
 	chip = iio_priv(indio_dev);
 	/* this is only used for device removal purposes */
 	dev_set_drvdata(&spi_dev->dev, indio_dev);
@@ -372,25 +370,28 @@
 	chip->convert_pin = pins[1];
 	chip->busy_pin = pins[2];
 
-	ret = gpio_request(chip->rdwr_pin, spi_get_device_id(spi_dev)->name);
+	ret = devm_gpio_request(&spi_dev->dev, chip->rdwr_pin,
+					spi_get_device_id(spi_dev)->name);
 	if (ret) {
 		dev_err(&spi_dev->dev, "Fail to request rdwr gpio PIN %d.\n",
 			chip->rdwr_pin);
-		goto error_free_device;
+		return ret;
 	}
 	gpio_direction_input(chip->rdwr_pin);
-	ret = gpio_request(chip->convert_pin, spi_get_device_id(spi_dev)->name);
+	ret = devm_gpio_request(&spi_dev->dev, chip->convert_pin,
+					spi_get_device_id(spi_dev)->name);
 	if (ret) {
 		dev_err(&spi_dev->dev, "Fail to request convert gpio PIN %d.\n",
 			chip->convert_pin);
-		goto error_free_gpio_rdwr;
+		return ret;
 	}
 	gpio_direction_input(chip->convert_pin);
-	ret = gpio_request(chip->busy_pin, spi_get_device_id(spi_dev)->name);
+	ret = devm_gpio_request(&spi_dev->dev, chip->busy_pin,
+					spi_get_device_id(spi_dev)->name);
 	if (ret) {
 		dev_err(&spi_dev->dev, "Fail to request busy gpio PIN %d.\n",
 			chip->busy_pin);
-		goto error_free_gpio_convert;
+		return ret;
 	}
 	gpio_direction_input(chip->busy_pin);
 
@@ -401,51 +402,31 @@
 
 	if (spi_dev->irq) {
 		/* Only low trigger is supported in ad7816/7/8 */
-		ret = request_threaded_irq(spi_dev->irq,
-					   NULL,
-					   &ad7816_event_handler,
-					   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-					   indio_dev->name,
-					   indio_dev);
+		ret = devm_request_threaded_irq(&spi_dev->dev, spi_dev->irq,
+						NULL,
+						&ad7816_event_handler,
+						IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+						indio_dev->name,
+						indio_dev);
 		if (ret)
-			goto error_free_gpio;
+			return ret;
 	}
 
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_free_irq;
+		return ret;
 
 	dev_info(&spi_dev->dev, "%s temperature sensor and ADC registered.\n",
 			 indio_dev->name);
 
 	return 0;
-error_free_irq:
-	free_irq(spi_dev->irq, indio_dev);
-error_free_gpio:
-	gpio_free(chip->busy_pin);
-error_free_gpio_convert:
-	gpio_free(chip->convert_pin);
-error_free_gpio_rdwr:
-	gpio_free(chip->rdwr_pin);
-error_free_device:
-	iio_device_free(indio_dev);
-error_ret:
-	return ret;
 }
 
 static int ad7816_remove(struct spi_device *spi_dev)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(&spi_dev->dev);
-	struct ad7816_chip_info *chip = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	dev_set_drvdata(&spi_dev->dev, NULL);
-	if (spi_dev->irq)
-		free_irq(spi_dev->irq, indio_dev);
-	gpio_free(chip->busy_pin);
-	gpio_free(chip->convert_pin);
-	gpio_free(chip->rdwr_pin);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/adc/ad799x.h b/drivers/staging/iio/adc/ad799x.h
index b51680c..a591aa6 100644
--- a/drivers/staging/iio/adc/ad799x.h
+++ b/drivers/staging/iio/adc/ad799x.h
@@ -36,18 +36,10 @@
 #define AD7998_ALERT_STAT_REG			0x1
 #define AD7998_CONF_REG				0x2
 #define AD7998_CYCLE_TMR_REG			0x3
-#define AD7998_DATALOW_CH1_REG			0x4
-#define AD7998_DATAHIGH_CH1_REG			0x5
-#define AD7998_HYST_CH1_REG			0x6
-#define AD7998_DATALOW_CH2_REG			0x7
-#define AD7998_DATAHIGH_CH2_REG			0x8
-#define AD7998_HYST_CH2_REG			0x9
-#define AD7998_DATALOW_CH3_REG			0xA
-#define AD7998_DATAHIGH_CH3_REG			0xB
-#define AD7998_HYST_CH3_REG			0xC
-#define AD7998_DATALOW_CH4_REG			0xD
-#define AD7998_DATAHIGH_CH4_REG			0xE
-#define AD7998_HYST_CH4_REG			0xF
+
+#define AD7998_DATALOW_REG(x)			((x) * 3 + 0x4)
+#define AD7998_DATAHIGH_REG(x)			((x) * 3 + 0x5)
+#define AD7998_HYST_REG(x)			((x) * 3 + 0x6)
 
 #define AD7998_CYC_MASK				0x7
 #define AD7998_CYC_DIS				0x0
diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c
index 2b2049c..9428be8 100644
--- a/drivers/staging/iio/adc/ad799x_core.c
+++ b/drivers/staging/iio/adc/ad799x_core.c
@@ -163,7 +163,6 @@
 {
 	int ret;
 	struct ad799x_state *st = iio_priv(indio_dev);
-	unsigned int scale_uv;
 
 	switch (m) {
 	case IIO_CHAN_INFO_RAW:
@@ -180,10 +179,9 @@
 			RES_MASK(chan->scan_type.realbits);
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		scale_uv = (st->int_vref_mv * 1000) >> chan->scan_type.realbits;
-		*val =  scale_uv / 1000;
-		*val2 = (scale_uv % 1000) * 1000;
-		return IIO_VAL_INT_PLUS_MICRO;
+		*val = st->int_vref_mv;
+		*val2 = chan->scan_type.realbits;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	}
 	return -EINVAL;
 }
@@ -254,98 +252,70 @@
 }
 
 static int ad799x_read_event_config(struct iio_dev *indio_dev,
-				    u64 event_code)
+				    const struct iio_chan_spec *chan,
+				    enum iio_event_type type,
+				    enum iio_event_direction dir)
 {
 	return 1;
 }
 
-static const u8 ad799x_threshold_addresses[][2] = {
-	{ AD7998_DATALOW_CH1_REG, AD7998_DATAHIGH_CH1_REG },
-	{ AD7998_DATALOW_CH2_REG, AD7998_DATAHIGH_CH2_REG },
-	{ AD7998_DATALOW_CH3_REG, AD7998_DATAHIGH_CH3_REG },
-	{ AD7998_DATALOW_CH4_REG, AD7998_DATAHIGH_CH4_REG },
-};
+static unsigned int ad799x_threshold_reg(const struct iio_chan_spec *chan,
+					 enum iio_event_direction dir,
+					 enum iio_event_info info)
+{
+	switch (info) {
+	case IIO_EV_INFO_VALUE:
+		if (dir == IIO_EV_DIR_FALLING)
+			return AD7998_DATALOW_REG(chan->channel);
+		else
+			return AD7998_DATAHIGH_REG(chan->channel);
+	case IIO_EV_INFO_HYSTERESIS:
+		return AD7998_HYST_REG(chan->channel);
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
 
 static int ad799x_write_event_value(struct iio_dev *indio_dev,
-				    u64 event_code,
-				    int val)
+				    const struct iio_chan_spec *chan,
+				    enum iio_event_type type,
+				    enum iio_event_direction dir,
+				    enum iio_event_info info,
+				    int val, int val2)
 {
 	int ret;
 	struct ad799x_state *st = iio_priv(indio_dev);
-	int direction = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
-			   IIO_EV_DIR_FALLING);
-	int number = IIO_EVENT_CODE_EXTRACT_CHAN(event_code);
 
 	mutex_lock(&indio_dev->mlock);
-	ret = ad799x_i2c_write16(st,
-				 ad799x_threshold_addresses[number][direction],
-				 val);
+	ret = ad799x_i2c_write16(st, ad799x_threshold_reg(chan, dir, info),
+		val);
 	mutex_unlock(&indio_dev->mlock);
 
 	return ret;
 }
 
 static int ad799x_read_event_value(struct iio_dev *indio_dev,
-				    u64 event_code,
-				    int *val)
+				    const struct iio_chan_spec *chan,
+				    enum iio_event_type type,
+				    enum iio_event_direction dir,
+				    enum iio_event_info info,
+				    int *val, int *val2)
 {
 	int ret;
 	struct ad799x_state *st = iio_priv(indio_dev);
-	int direction = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
-			   IIO_EV_DIR_FALLING);
-	int number = IIO_EVENT_CODE_EXTRACT_CHAN(event_code);
 	u16 valin;
 
 	mutex_lock(&indio_dev->mlock);
-	ret = ad799x_i2c_read16(st,
-				ad799x_threshold_addresses[number][direction],
-				&valin);
+	ret = ad799x_i2c_read16(st, ad799x_threshold_reg(chan, dir, info),
+		&valin);
 	mutex_unlock(&indio_dev->mlock);
 	if (ret < 0)
 		return ret;
 	*val = valin;
 
-	return 0;
-}
-
-static ssize_t ad799x_read_channel_config(struct device *dev,
-					struct device_attribute *attr,
-					char *buf)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct ad799x_state *st = iio_priv(indio_dev);
-	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
-	int ret;
-	u16 val;
-	ret = ad799x_i2c_read16(st, this_attr->address, &val);
-	if (ret)
-		return ret;
-
-	return sprintf(buf, "%d\n", val);
-}
-
-static ssize_t ad799x_write_channel_config(struct device *dev,
-					 struct device_attribute *attr,
-					 const char *buf,
-					 size_t len)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct ad799x_state *st = iio_priv(indio_dev);
-	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
-	long val;
-	int ret;
-
-	ret = kstrtol(buf, 10, &val);
-	if (ret)
-		return ret;
-
-	mutex_lock(&indio_dev->mlock);
-	ret = ad799x_i2c_write16(st, this_attr->address, val);
-	mutex_unlock(&indio_dev->mlock);
-
-	return ret ? ret : len;
+	return IIO_VAL_INT;
 }
 
 static irqreturn_t ad799x_event_handler(int irq, void *private)
@@ -383,60 +353,19 @@
 	return IRQ_HANDLED;
 }
 
-static IIO_DEVICE_ATTR(in_voltage0_thresh_both_hyst_raw,
-		       S_IRUGO | S_IWUSR,
-		       ad799x_read_channel_config,
-		       ad799x_write_channel_config,
-		       AD7998_HYST_CH1_REG);
-
-static IIO_DEVICE_ATTR(in_voltage1_thresh_both_hyst_raw,
-		       S_IRUGO | S_IWUSR,
-		       ad799x_read_channel_config,
-		       ad799x_write_channel_config,
-		       AD7998_HYST_CH2_REG);
-
-static IIO_DEVICE_ATTR(in_voltage2_thresh_both_hyst_raw,
-		       S_IRUGO | S_IWUSR,
-		       ad799x_read_channel_config,
-		       ad799x_write_channel_config,
-		       AD7998_HYST_CH3_REG);
-
-static IIO_DEVICE_ATTR(in_voltage3_thresh_both_hyst_raw,
-		       S_IRUGO | S_IWUSR,
-		       ad799x_read_channel_config,
-		       ad799x_write_channel_config,
-		       AD7998_HYST_CH4_REG);
-
 static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
 			      ad799x_read_frequency,
 			      ad799x_write_frequency);
 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("15625 7812 3906 1953 976 488 244 0");
 
-static struct attribute *ad7993_4_7_8_event_attributes[] = {
-	&iio_dev_attr_in_voltage0_thresh_both_hyst_raw.dev_attr.attr,
-	&iio_dev_attr_in_voltage1_thresh_both_hyst_raw.dev_attr.attr,
-	&iio_dev_attr_in_voltage2_thresh_both_hyst_raw.dev_attr.attr,
-	&iio_dev_attr_in_voltage3_thresh_both_hyst_raw.dev_attr.attr,
+static struct attribute *ad799x_event_attributes[] = {
 	&iio_dev_attr_sampling_frequency.dev_attr.attr,
 	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
 	NULL,
 };
 
-static struct attribute_group ad7993_4_7_8_event_attrs_group = {
-	.attrs = ad7993_4_7_8_event_attributes,
-	.name = "events",
-};
-
-static struct attribute *ad7992_event_attributes[] = {
-	&iio_dev_attr_in_voltage0_thresh_both_hyst_raw.dev_attr.attr,
-	&iio_dev_attr_in_voltage1_thresh_both_hyst_raw.dev_attr.attr,
-	&iio_dev_attr_sampling_frequency.dev_attr.attr,
-	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
-	NULL,
-};
-
-static struct attribute_group ad7992_event_attrs_group = {
-	.attrs = ad7992_event_attributes,
+static struct attribute_group ad799x_event_attrs_group = {
+	.attrs = ad799x_event_attributes,
 	.name = "events",
 };
 
@@ -445,29 +374,35 @@
 	.driver_module = THIS_MODULE,
 };
 
-static const struct iio_info ad7992_info = {
-	.read_raw = &ad799x_read_raw,
-	.event_attrs = &ad7992_event_attrs_group,
-	.read_event_config = &ad799x_read_event_config,
-	.read_event_value = &ad799x_read_event_value,
-	.write_event_value = &ad799x_write_event_value,
-	.driver_module = THIS_MODULE,
-};
-
 static const struct iio_info ad7993_4_7_8_info = {
 	.read_raw = &ad799x_read_raw,
-	.event_attrs = &ad7993_4_7_8_event_attrs_group,
-	.read_event_config = &ad799x_read_event_config,
-	.read_event_value = &ad799x_read_event_value,
-	.write_event_value = &ad799x_write_event_value,
+	.event_attrs = &ad799x_event_attrs_group,
+	.read_event_config_new = &ad799x_read_event_config,
+	.read_event_value_new = &ad799x_read_event_value,
+	.write_event_value_new = &ad799x_write_event_value,
 	.driver_module = THIS_MODULE,
 	.update_scan_mode = ad7997_8_update_scan_mode,
 };
 
-#define AD799X_EV_MASK (IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | \
-			IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING))
+static const struct iio_event_spec ad799x_events[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE),
+			BIT(IIO_EV_INFO_ENABLE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_EITHER,
+		.mask_separate = BIT(IIO_EV_INFO_HYSTERESIS),
+	},
+};
 
-#define AD799X_CHANNEL(_index, _realbits, _evmask) { \
+#define _AD799X_CHANNEL(_index, _realbits, _ev_spec, _num_ev_spec) { \
 	.type = IIO_VOLTAGE, \
 	.indexed = 1, \
 	.channel = (_index), \
@@ -475,16 +410,24 @@
 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
 	.scan_index = (_index), \
 	.scan_type = IIO_ST('u', _realbits, 16, 12 - (_realbits)), \
-	.event_mask = (_evmask), \
+	.event_spec = _ev_spec, \
+	.num_event_specs = _num_ev_spec, \
 }
 
+#define AD799X_CHANNEL(_index, _realbits) \
+	_AD799X_CHANNEL(_index, _realbits, NULL, 0)
+
+#define AD799X_CHANNEL_WITH_EVENTS(_index, _realbits) \
+	_AD799X_CHANNEL(_index, _realbits, ad799x_events, \
+		ARRAY_SIZE(ad799x_events))
+
 static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
 	[ad7991] = {
 		.channel = {
-			AD799X_CHANNEL(0, 12, 0),
-			AD799X_CHANNEL(1, 12, 0),
-			AD799X_CHANNEL(2, 12, 0),
-			AD799X_CHANNEL(3, 12, 0),
+			AD799X_CHANNEL(0, 12),
+			AD799X_CHANNEL(1, 12),
+			AD799X_CHANNEL(2, 12),
+			AD799X_CHANNEL(3, 12),
 			IIO_CHAN_SOFT_TIMESTAMP(4),
 		},
 		.num_channels = 5,
@@ -492,10 +435,10 @@
 	},
 	[ad7995] = {
 		.channel = {
-			AD799X_CHANNEL(0, 10, 0),
-			AD799X_CHANNEL(1, 10, 0),
-			AD799X_CHANNEL(2, 10, 0),
-			AD799X_CHANNEL(3, 10, 0),
+			AD799X_CHANNEL(0, 10),
+			AD799X_CHANNEL(1, 10),
+			AD799X_CHANNEL(2, 10),
+			AD799X_CHANNEL(3, 10),
 			IIO_CHAN_SOFT_TIMESTAMP(4),
 		},
 		.num_channels = 5,
@@ -503,10 +446,10 @@
 	},
 	[ad7999] = {
 		.channel = {
-			AD799X_CHANNEL(0, 8, 0),
-			AD799X_CHANNEL(1, 8, 0),
-			AD799X_CHANNEL(2, 8, 0),
-			AD799X_CHANNEL(3, 8, 0),
+			AD799X_CHANNEL(0, 8),
+			AD799X_CHANNEL(1, 8),
+			AD799X_CHANNEL(2, 8),
+			AD799X_CHANNEL(3, 8),
 			IIO_CHAN_SOFT_TIMESTAMP(4),
 		},
 		.num_channels = 5,
@@ -514,20 +457,20 @@
 	},
 	[ad7992] = {
 		.channel = {
-			AD799X_CHANNEL(0, 12, AD799X_EV_MASK),
-			AD799X_CHANNEL(1, 12, AD799X_EV_MASK),
+			AD799X_CHANNEL_WITH_EVENTS(0, 12),
+			AD799X_CHANNEL_WITH_EVENTS(1, 12),
 			IIO_CHAN_SOFT_TIMESTAMP(3),
 		},
 		.num_channels = 3,
 		.default_config = AD7998_ALERT_EN,
-		.info = &ad7992_info,
+		.info = &ad7993_4_7_8_info,
 	},
 	[ad7993] = {
 		.channel = {
-			AD799X_CHANNEL(0, 10, AD799X_EV_MASK),
-			AD799X_CHANNEL(1, 10, AD799X_EV_MASK),
-			AD799X_CHANNEL(2, 10, AD799X_EV_MASK),
-			AD799X_CHANNEL(3, 10, AD799X_EV_MASK),
+			AD799X_CHANNEL_WITH_EVENTS(0, 10),
+			AD799X_CHANNEL_WITH_EVENTS(1, 10),
+			AD799X_CHANNEL_WITH_EVENTS(2, 10),
+			AD799X_CHANNEL_WITH_EVENTS(3, 10),
 			IIO_CHAN_SOFT_TIMESTAMP(4),
 		},
 		.num_channels = 5,
@@ -536,10 +479,10 @@
 	},
 	[ad7994] = {
 		.channel = {
-			AD799X_CHANNEL(0, 12, AD799X_EV_MASK),
-			AD799X_CHANNEL(1, 12, AD799X_EV_MASK),
-			AD799X_CHANNEL(2, 12, AD799X_EV_MASK),
-			AD799X_CHANNEL(3, 12, AD799X_EV_MASK),
+			AD799X_CHANNEL_WITH_EVENTS(0, 12),
+			AD799X_CHANNEL_WITH_EVENTS(1, 12),
+			AD799X_CHANNEL_WITH_EVENTS(2, 12),
+			AD799X_CHANNEL_WITH_EVENTS(3, 12),
 			IIO_CHAN_SOFT_TIMESTAMP(4),
 		},
 		.num_channels = 5,
@@ -548,14 +491,14 @@
 	},
 	[ad7997] = {
 		.channel = {
-			AD799X_CHANNEL(0, 10, AD799X_EV_MASK),
-			AD799X_CHANNEL(1, 10, AD799X_EV_MASK),
-			AD799X_CHANNEL(2, 10, AD799X_EV_MASK),
-			AD799X_CHANNEL(3, 10, AD799X_EV_MASK),
-			AD799X_CHANNEL(4, 10, 0),
-			AD799X_CHANNEL(5, 10, 0),
-			AD799X_CHANNEL(6, 10, 0),
-			AD799X_CHANNEL(7, 10, 0),
+			AD799X_CHANNEL_WITH_EVENTS(0, 10),
+			AD799X_CHANNEL_WITH_EVENTS(1, 10),
+			AD799X_CHANNEL_WITH_EVENTS(2, 10),
+			AD799X_CHANNEL_WITH_EVENTS(3, 10),
+			AD799X_CHANNEL(4, 10),
+			AD799X_CHANNEL(5, 10),
+			AD799X_CHANNEL(6, 10),
+			AD799X_CHANNEL(7, 10),
 			IIO_CHAN_SOFT_TIMESTAMP(8),
 		},
 		.num_channels = 9,
@@ -564,14 +507,14 @@
 	},
 	[ad7998] = {
 		.channel = {
-			AD799X_CHANNEL(0, 12, AD799X_EV_MASK),
-			AD799X_CHANNEL(1, 12, AD799X_EV_MASK),
-			AD799X_CHANNEL(2, 12, AD799X_EV_MASK),
-			AD799X_CHANNEL(3, 12, AD799X_EV_MASK),
-			AD799X_CHANNEL(4, 12, 0),
-			AD799X_CHANNEL(5, 12, 0),
-			AD799X_CHANNEL(6, 12, 0),
-			AD799X_CHANNEL(7, 12, 0),
+			AD799X_CHANNEL_WITH_EVENTS(0, 12),
+			AD799X_CHANNEL_WITH_EVENTS(1, 12),
+			AD799X_CHANNEL_WITH_EVENTS(2, 12),
+			AD799X_CHANNEL_WITH_EVENTS(3, 12),
+			AD799X_CHANNEL(4, 12),
+			AD799X_CHANNEL(5, 12),
+			AD799X_CHANNEL(6, 12),
+			AD799X_CHANNEL(7, 12),
 			IIO_CHAN_SOFT_TIMESTAMP(8),
 		},
 		.num_channels = 9,
@@ -586,8 +529,9 @@
 	int ret;
 	struct ad799x_platform_data *pdata = client->dev.platform_data;
 	struct ad799x_state *st;
-	struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
+	struct iio_dev *indio_dev;
 
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
 	if (indio_dev == NULL)
 		return -ENOMEM;
 
@@ -606,11 +550,11 @@
 
 	st->int_vref_mv = pdata->vref_mv;
 
-	st->reg = regulator_get(&client->dev, "vcc");
+	st->reg = devm_regulator_get(&client->dev, "vcc");
 	if (!IS_ERR(st->reg)) {
 		ret = regulator_enable(st->reg);
 		if (ret)
-			goto error_put_reg;
+			return ret;
 	}
 	st->client = client;
 
@@ -650,10 +594,6 @@
 error_disable_reg:
 	if (!IS_ERR(st->reg))
 		regulator_disable(st->reg);
-error_put_reg:
-	if (!IS_ERR(st->reg))
-		regulator_put(st->reg);
-	iio_device_free(indio_dev);
 
 	return ret;
 }
@@ -668,12 +608,9 @@
 		free_irq(client->irq, indio_dev);
 
 	ad799x_ring_cleanup(indio_dev);
-	if (!IS_ERR(st->reg)) {
+	if (!IS_ERR(st->reg))
 		regulator_disable(st->reg);
-		regulator_put(st->reg);
-	}
 	kfree(st->rx_buf);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c
index c2ebae1..0ff6c03 100644
--- a/drivers/staging/iio/adc/ad799x_ring.c
+++ b/drivers/staging/iio/adc/ad799x_ring.c
@@ -35,7 +35,6 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct ad799x_state *st = iio_priv(indio_dev);
-	s64 time_ns;
 	int b_sent;
 	u8 cmd;
 
@@ -65,13 +64,8 @@
 	if (b_sent < 0)
 		goto out;
 
-	time_ns = iio_get_time_ns();
-
-	if (indio_dev->scan_timestamp)
-		memcpy(st->rx_buf + indio_dev->scan_bytes - sizeof(s64),
-			&time_ns, sizeof(time_ns));
-
-	iio_push_to_buffers(indio_dev, st->rx_buf);
+	iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf,
+			iio_get_time_ns());
 out:
 	iio_trigger_notify_done(indio_dev->trig);
 
diff --git a/drivers/staging/iio/adc/lpc32xx_adc.c b/drivers/staging/iio/adc/lpc32xx_adc.c
index 9a4bb09..ef0a21d 100644
--- a/drivers/staging/iio/adc/lpc32xx_adc.c
+++ b/drivers/staging/iio/adc/lpc32xx_adc.c
@@ -137,43 +137,39 @@
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(&pdev->dev, "failed to get platform I/O memory\n");
-		retval = -EBUSY;
-		goto errout1;
+		return -EBUSY;
 	}
 
-	iodev = iio_device_alloc(sizeof(struct lpc32xx_adc_info));
-	if (!iodev) {
-		dev_err(&pdev->dev, "failed allocating iio device\n");
-		retval = -ENOMEM;
-		goto errout1;
-	}
+	iodev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));
+	if (!iodev)
+		return -ENOMEM;
 
 	info = iio_priv(iodev);
 
-	info->adc_base = ioremap(res->start, resource_size(res));
+	info->adc_base = devm_ioremap(&pdev->dev, res->start,
+						resource_size(res));
 	if (!info->adc_base) {
 		dev_err(&pdev->dev, "failed mapping memory\n");
-		retval = -EBUSY;
-		goto errout2;
+		return -EBUSY;
 	}
 
-	info->clk = clk_get(&pdev->dev, NULL);
+	info->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(info->clk)) {
 		dev_err(&pdev->dev, "failed getting clock\n");
-		goto errout3;
+		return PTR_ERR(info->clk);
 	}
 
 	irq = platform_get_irq(pdev, 0);
-	if ((irq < 0) || (irq >= NR_IRQS)) {
+	if (irq <= 0) {
 		dev_err(&pdev->dev, "failed getting interrupt resource\n");
-		retval = -EINVAL;
-		goto errout4;
+		return -EINVAL;
 	}
 
-	retval = request_irq(irq, lpc32xx_adc_isr, 0, MOD_NAME, info);
+	retval = devm_request_irq(&pdev->dev, irq, lpc32xx_adc_isr, 0,
+								MOD_NAME, info);
 	if (retval < 0) {
 		dev_err(&pdev->dev, "failed requesting interrupt\n");
-		goto errout4;
+		return retval;
 	}
 
 	platform_set_drvdata(pdev, iodev);
@@ -189,35 +185,18 @@
 
 	retval = iio_device_register(iodev);
 	if (retval)
-		goto errout5;
+		return retval;
 
 	dev_info(&pdev->dev, "LPC32XX ADC driver loaded, IRQ %d\n", irq);
 
 	return 0;
-
-errout5:
-	free_irq(irq, info);
-errout4:
-	clk_put(info->clk);
-errout3:
-	iounmap(info->adc_base);
-errout2:
-	iio_device_free(iodev);
-errout1:
-	return retval;
 }
 
 static int lpc32xx_adc_remove(struct platform_device *pdev)
 {
 	struct iio_dev *iodev = platform_get_drvdata(pdev);
-	struct lpc32xx_adc_info *info = iio_priv(iodev);
-	int irq = platform_get_irq(pdev, 0);
 
 	iio_device_unregister(iodev);
-	free_irq(irq, info);
-	clk_put(info->clk);
-	iounmap(info->adc_base);
-	iio_device_free(iodev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index a08c173..aeae76b 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -35,6 +35,7 @@
 #include <linux/completion.h>
 #include <linux/delay.h>
 #include <linux/input.h>
+#include <linux/clk.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/buffer.h>
@@ -129,11 +130,24 @@
 	MXS_LRADC_TOUCHSCREEN_5WIRE,
 };
 
+/*
+ * Touchscreen handling
+ */
+enum lradc_ts_plate {
+	LRADC_TOUCH = 0,
+	LRADC_SAMPLE_X,
+	LRADC_SAMPLE_Y,
+	LRADC_SAMPLE_PRESSURE,
+	LRADC_SAMPLE_VALID,
+};
+
 struct mxs_lradc {
 	struct device		*dev;
 	void __iomem		*base;
 	int			irq[13];
 
+	struct clk		*clk;
+
 	uint32_t		*buffer;
 	struct iio_trigger	*trig;
 
@@ -169,32 +183,63 @@
 #define CHAN_MASK_TOUCHSCREEN_4WIRE	(0xf << 2)
 #define CHAN_MASK_TOUCHSCREEN_5WIRE	(0x1f << 2)
 	enum mxs_lradc_ts	use_touchscreen;
-	bool			stop_touchscreen;
 	bool			use_touchbutton;
 
 	struct input_dev	*ts_input;
-	struct work_struct	ts_work;
+
+	enum mxs_lradc_id	soc;
+	enum lradc_ts_plate	cur_plate; /* statemachine */
+	bool			ts_valid;
+	unsigned		ts_x_pos;
+	unsigned		ts_y_pos;
+	unsigned		ts_pressure;
+
+	/* handle touchscreen's physical behaviour */
+	/* samples per coordinate */
+	unsigned		over_sample_cnt;
+	/* time clocks between samples */
+	unsigned		over_sample_delay;
+	/* time in clocks to wait after the plates where switched */
+	unsigned		settling_delay;
 };
 
 #define	LRADC_CTRL0				0x00
-#define	LRADC_CTRL0_TOUCH_DETECT_ENABLE		(1 << 23)
-#define	LRADC_CTRL0_TOUCH_SCREEN_TYPE		(1 << 22)
-#define	LRADC_CTRL0_YNNSW	/* YM */	(1 << 21)
-#define	LRADC_CTRL0_YPNSW	/* YP */	(1 << 20)
-#define	LRADC_CTRL0_YPPSW	/* YP */	(1 << 19)
-#define	LRADC_CTRL0_XNNSW	/* XM */	(1 << 18)
-#define	LRADC_CTRL0_XNPSW	/* XM */	(1 << 17)
-#define	LRADC_CTRL0_XPPSW	/* XP */	(1 << 16)
-#define	LRADC_CTRL0_PLATE_MASK			(0x3f << 16)
+# define LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE	(1 << 23)
+# define LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE	(1 << 22)
+# define LRADC_CTRL0_MX28_YNNSW	/* YM */	(1 << 21)
+# define LRADC_CTRL0_MX28_YPNSW	/* YP */	(1 << 20)
+# define LRADC_CTRL0_MX28_YPPSW	/* YP */	(1 << 19)
+# define LRADC_CTRL0_MX28_XNNSW	/* XM */	(1 << 18)
+# define LRADC_CTRL0_MX28_XNPSW	/* XM */	(1 << 17)
+# define LRADC_CTRL0_MX28_XPPSW	/* XP */	(1 << 16)
+
+# define LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE	(1 << 20)
+# define LRADC_CTRL0_MX23_YM			(1 << 19)
+# define LRADC_CTRL0_MX23_XM			(1 << 18)
+# define LRADC_CTRL0_MX23_YP			(1 << 17)
+# define LRADC_CTRL0_MX23_XP			(1 << 16)
+
+# define LRADC_CTRL0_MX28_PLATE_MASK \
+		(LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE | \
+		LRADC_CTRL0_MX28_YNNSW | LRADC_CTRL0_MX28_YPNSW | \
+		LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW | \
+		LRADC_CTRL0_MX28_XNPSW | LRADC_CTRL0_MX28_XPPSW)
+
+# define LRADC_CTRL0_MX23_PLATE_MASK \
+		(LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE | \
+		LRADC_CTRL0_MX23_YM | LRADC_CTRL0_MX23_XM | \
+		LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_XP)
 
 #define	LRADC_CTRL1				0x10
 #define	LRADC_CTRL1_TOUCH_DETECT_IRQ_EN		(1 << 24)
 #define	LRADC_CTRL1_LRADC_IRQ_EN(n)		(1 << ((n) + 16))
-#define	LRADC_CTRL1_LRADC_IRQ_EN_MASK		(0x1fff << 16)
+#define	LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK	(0x1fff << 16)
+#define	LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK	(0x01ff << 16)
 #define	LRADC_CTRL1_LRADC_IRQ_EN_OFFSET		16
 #define	LRADC_CTRL1_TOUCH_DETECT_IRQ		(1 << 8)
 #define	LRADC_CTRL1_LRADC_IRQ(n)		(1 << (n))
-#define	LRADC_CTRL1_LRADC_IRQ_MASK		0x1fff
+#define	LRADC_CTRL1_MX28_LRADC_IRQ_MASK		0x1fff
+#define	LRADC_CTRL1_MX23_LRADC_IRQ_MASK		0x01ff
 #define	LRADC_CTRL1_LRADC_IRQ_OFFSET		0
 
 #define	LRADC_CTRL2				0x20
@@ -207,19 +252,33 @@
 #define	LRADC_CH_ACCUMULATE			(1 << 29)
 #define	LRADC_CH_NUM_SAMPLES_MASK		(0x1f << 24)
 #define	LRADC_CH_NUM_SAMPLES_OFFSET		24
+#define	LRADC_CH_NUM_SAMPLES(x) \
+				((x) << LRADC_CH_NUM_SAMPLES_OFFSET)
 #define	LRADC_CH_VALUE_MASK			0x3ffff
 #define	LRADC_CH_VALUE_OFFSET			0
 
 #define	LRADC_DELAY(n)				(0xd0 + (0x10 * (n)))
 #define	LRADC_DELAY_TRIGGER_LRADCS_MASK		(0xff << 24)
 #define	LRADC_DELAY_TRIGGER_LRADCS_OFFSET	24
+#define	LRADC_DELAY_TRIGGER(x) \
+				(((x) << LRADC_DELAY_TRIGGER_LRADCS_OFFSET) & \
+				LRADC_DELAY_TRIGGER_LRADCS_MASK)
 #define	LRADC_DELAY_KICK			(1 << 20)
 #define	LRADC_DELAY_TRIGGER_DELAYS_MASK		(0xf << 16)
 #define	LRADC_DELAY_TRIGGER_DELAYS_OFFSET	16
+#define	LRADC_DELAY_TRIGGER_DELAYS(x) \
+				(((x) << LRADC_DELAY_TRIGGER_DELAYS_OFFSET) & \
+				LRADC_DELAY_TRIGGER_DELAYS_MASK)
 #define	LRADC_DELAY_LOOP_COUNT_MASK		(0x1f << 11)
 #define	LRADC_DELAY_LOOP_COUNT_OFFSET		11
+#define	LRADC_DELAY_LOOP(x) \
+				(((x) << LRADC_DELAY_LOOP_COUNT_OFFSET) & \
+				LRADC_DELAY_LOOP_COUNT_MASK)
 #define	LRADC_DELAY_DELAY_MASK			0x7ff
 #define	LRADC_DELAY_DELAY_OFFSET		0
+#define	LRADC_DELAY_DELAY(x) \
+				(((x) << LRADC_DELAY_DELAY_OFFSET) & \
+				LRADC_DELAY_DELAY_MASK)
 
 #define	LRADC_CTRL4				0x140
 #define	LRADC_CTRL4_LRADCSELECT_MASK(n)		(0xf << ((n) * 4))
@@ -228,6 +287,475 @@
 #define LRADC_RESOLUTION			12
 #define LRADC_SINGLE_SAMPLE_MASK		((1 << LRADC_RESOLUTION) - 1)
 
+static void mxs_lradc_reg_set(struct mxs_lradc *lradc, u32 val, u32 reg)
+{
+	writel(val, lradc->base + reg + STMP_OFFSET_REG_SET);
+}
+
+static void mxs_lradc_reg_clear(struct mxs_lradc *lradc, u32 val, u32 reg)
+{
+	writel(val, lradc->base + reg + STMP_OFFSET_REG_CLR);
+}
+
+static void mxs_lradc_reg_wrt(struct mxs_lradc *lradc, u32 val, u32 reg)
+{
+	writel(val, lradc->base + reg);
+}
+
+static u32 mxs_lradc_plate_mask(struct mxs_lradc *lradc)
+{
+	if (lradc->soc == IMX23_LRADC)
+		return LRADC_CTRL0_MX23_PLATE_MASK;
+	else
+		return LRADC_CTRL0_MX28_PLATE_MASK;
+}
+
+static u32 mxs_lradc_irq_en_mask(struct mxs_lradc *lradc)
+{
+	if (lradc->soc == IMX23_LRADC)
+		return LRADC_CTRL1_MX23_LRADC_IRQ_EN_MASK;
+	else
+		return LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK;
+}
+
+static u32 mxs_lradc_irq_mask(struct mxs_lradc *lradc)
+{
+	if (lradc->soc == IMX23_LRADC)
+		return LRADC_CTRL1_MX23_LRADC_IRQ_MASK;
+	else
+		return LRADC_CTRL1_MX28_LRADC_IRQ_MASK;
+}
+
+static u32 mxs_lradc_touch_detect_bit(struct mxs_lradc *lradc)
+{
+	if (lradc->soc == IMX23_LRADC)
+		return LRADC_CTRL0_MX23_TOUCH_DETECT_ENABLE;
+	else
+		return LRADC_CTRL0_MX28_TOUCH_DETECT_ENABLE;
+}
+
+static u32 mxs_lradc_drive_x_plate(struct mxs_lradc *lradc)
+{
+	if (lradc->soc == IMX23_LRADC)
+		return LRADC_CTRL0_MX23_XP | LRADC_CTRL0_MX23_XM;
+	else
+		return LRADC_CTRL0_MX28_XPPSW | LRADC_CTRL0_MX28_XNNSW;
+}
+
+static u32 mxs_lradc_drive_y_plate(struct mxs_lradc *lradc)
+{
+	if (lradc->soc == IMX23_LRADC)
+		return LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_YM;
+	else
+		return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_YNNSW;
+}
+
+static u32 mxs_lradc_drive_pressure(struct mxs_lradc *lradc)
+{
+	if (lradc->soc == IMX23_LRADC)
+		return LRADC_CTRL0_MX23_YP | LRADC_CTRL0_MX23_XM;
+	else
+		return LRADC_CTRL0_MX28_YPPSW | LRADC_CTRL0_MX28_XNNSW;
+}
+
+static bool mxs_lradc_check_touch_event(struct mxs_lradc *lradc)
+{
+	return !!(readl(lradc->base + LRADC_STATUS) &
+					LRADC_STATUS_TOUCH_DETECT_RAW);
+}
+
+static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch)
+{
+	/*
+	 * prepare for oversampling conversion
+	 *
+	 * from the datasheet:
+	 * "The ACCUMULATE bit in the appropriate channel register
+	 * HW_LRADC_CHn must be set to 1 if NUM_SAMPLES is greater then 0;
+	 * otherwise, the IRQs will not fire."
+	 */
+	mxs_lradc_reg_wrt(lradc, LRADC_CH_ACCUMULATE |
+			LRADC_CH_NUM_SAMPLES(lradc->over_sample_cnt - 1),
+			LRADC_CH(ch));
+
+	/* from the datasheet:
+	 * "Software must clear this register in preparation for a
+	 * multi-cycle accumulation.
+	 */
+	mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch));
+
+	/* prepare the delay/loop unit according to the oversampling count */
+	mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << ch) |
+		LRADC_DELAY_TRIGGER_DELAYS(0) |
+		LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) |
+		LRADC_DELAY_DELAY(lradc->over_sample_delay - 1),
+			LRADC_DELAY(3));
+
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) |
+			LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) |
+			LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
+
+	/* wake us again, when the complete conversion is done */
+	mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch), LRADC_CTRL1);
+	/*
+	 * after changing the touchscreen plates setting
+	 * the signals need some initial time to settle. Start the
+	 * SoC's delay unit and start the conversion later
+	 * and automatically.
+	 */
+	mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(0) | /* don't trigger ADC */
+		LRADC_DELAY_TRIGGER_DELAYS(1 << 3) | /* trigger DELAY unit#3 */
+		LRADC_DELAY_KICK |
+		LRADC_DELAY_DELAY(lradc->settling_delay),
+			LRADC_DELAY(2));
+}
+
+/*
+ * Pressure detection is special:
+ * We want to do both required measurements for the pressure detection in
+ * one turn. Use the hardware features to chain both conversions and let the
+ * hardware report one interrupt if both conversions are done
+ */
+static void mxs_lradc_setup_ts_pressure(struct mxs_lradc *lradc, unsigned ch1,
+							unsigned ch2)
+{
+	u32 reg;
+
+	/*
+	 * prepare for oversampling conversion
+	 *
+	 * from the datasheet:
+	 * "The ACCUMULATE bit in the appropriate channel register
+	 * HW_LRADC_CHn must be set to 1 if NUM_SAMPLES is greater then 0;
+	 * otherwise, the IRQs will not fire."
+	 */
+	reg = LRADC_CH_ACCUMULATE |
+		LRADC_CH_NUM_SAMPLES(lradc->over_sample_cnt - 1);
+	mxs_lradc_reg_wrt(lradc, reg, LRADC_CH(ch1));
+	mxs_lradc_reg_wrt(lradc, reg, LRADC_CH(ch2));
+
+	/* from the datasheet:
+	 * "Software must clear this register in preparation for a
+	 * multi-cycle accumulation.
+	 */
+	mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch1));
+	mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch2));
+
+	/* prepare the delay/loop unit according to the oversampling count */
+	mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << ch1) |
+		LRADC_DELAY_TRIGGER(1 << ch2) | /* start both channels */
+		LRADC_DELAY_TRIGGER_DELAYS(0) |
+		LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) |
+		LRADC_DELAY_DELAY(lradc->over_sample_delay - 1),
+					LRADC_DELAY(3));
+
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) |
+			LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) |
+			LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
+
+	/* wake us again, when the conversions are done */
+	mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch2), LRADC_CTRL1);
+	/*
+	 * after changing the touchscreen plates setting
+	 * the signals need some initial time to settle. Start the
+	 * SoC's delay unit and start the conversion later
+	 * and automatically.
+	 */
+	mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(0) | /* don't trigger ADC */
+		LRADC_DELAY_TRIGGER_DELAYS(1 << 3) | /* trigger DELAY unit#3 */
+		LRADC_DELAY_KICK |
+		LRADC_DELAY_DELAY(lradc->settling_delay), LRADC_DELAY(2));
+}
+
+static unsigned mxs_lradc_read_raw_channel(struct mxs_lradc *lradc,
+							unsigned channel)
+{
+	u32 reg;
+	unsigned num_samples, val;
+
+	reg = readl(lradc->base + LRADC_CH(channel));
+	if (reg & LRADC_CH_ACCUMULATE)
+		num_samples = lradc->over_sample_cnt;
+	else
+		num_samples = 1;
+
+	val = (reg & LRADC_CH_VALUE_MASK) >> LRADC_CH_VALUE_OFFSET;
+	return val / num_samples;
+}
+
+static unsigned mxs_lradc_read_ts_pressure(struct mxs_lradc *lradc,
+						unsigned ch1, unsigned ch2)
+{
+	u32 reg, mask;
+	unsigned pressure, m1, m2;
+
+	mask = LRADC_CTRL1_LRADC_IRQ(ch1) | LRADC_CTRL1_LRADC_IRQ(ch2);
+	reg = readl(lradc->base + LRADC_CTRL1) & mask;
+
+	while (reg != mask) {
+		reg = readl(lradc->base + LRADC_CTRL1) & mask;
+		dev_dbg(lradc->dev, "One channel is still busy: %X\n", reg);
+	}
+
+	m1 = mxs_lradc_read_raw_channel(lradc, ch1);
+	m2 = mxs_lradc_read_raw_channel(lradc, ch2);
+
+	if (m2 == 0) {
+		dev_warn(lradc->dev, "Cannot calculate pressure\n");
+		return 1 << (LRADC_RESOLUTION - 1);
+	}
+
+	/* simply scale the value from 0 ... max ADC resolution */
+	pressure = m1;
+	pressure *= (1 << LRADC_RESOLUTION);
+	pressure /= m2;
+
+	dev_dbg(lradc->dev, "Pressure = %u\n", pressure);
+	return pressure;
+}
+
+#define TS_CH_XP 2
+#define TS_CH_YP 3
+#define TS_CH_XM 4
+#define TS_CH_YM 5
+
+static int mxs_lradc_read_ts_channel(struct mxs_lradc *lradc)
+{
+	u32 reg;
+	int val;
+
+	reg = readl(lradc->base + LRADC_CTRL1);
+
+	/* only channels 3 to 5 are of interest here */
+	if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YP)) {
+		mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YP) |
+			LRADC_CTRL1_LRADC_IRQ(TS_CH_YP), LRADC_CTRL1);
+		val = mxs_lradc_read_raw_channel(lradc, TS_CH_YP);
+	} else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_XM)) {
+		mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_XM) |
+			LRADC_CTRL1_LRADC_IRQ(TS_CH_XM), LRADC_CTRL1);
+		val = mxs_lradc_read_raw_channel(lradc, TS_CH_XM);
+	} else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YM)) {
+		mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YM) |
+			LRADC_CTRL1_LRADC_IRQ(TS_CH_YM), LRADC_CTRL1);
+		val = mxs_lradc_read_raw_channel(lradc, TS_CH_YM);
+	} else {
+		return -EIO;
+	}
+
+	mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2));
+	mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3));
+
+	return val;
+}
+
+/*
+ * YP(open)--+-------------+
+ *           |             |--+
+ *           |             |  |
+ *    YM(-)--+-------------+  |
+ *             +--------------+
+ *             |              |
+ *         XP(weak+)        XM(open)
+ *
+ * "weak+" means 200k Ohm VDDIO
+ * (-) means GND
+ */
+static void mxs_lradc_setup_touch_detection(struct mxs_lradc *lradc)
+{
+	/*
+	 * In order to detect a touch event the 'touch detect enable' bit
+	 * enables:
+	 *  - a weak pullup to the X+ connector
+	 *  - a strong ground at the Y- connector
+	 */
+	mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
+	mxs_lradc_reg_set(lradc, mxs_lradc_touch_detect_bit(lradc),
+				LRADC_CTRL0);
+}
+
+/*
+ * YP(meas)--+-------------+
+ *           |             |--+
+ *           |             |  |
+ * YM(open)--+-------------+  |
+ *             +--------------+
+ *             |              |
+ *           XP(+)          XM(-)
+ *
+ * (+) means here 1.85 V
+ * (-) means here GND
+ */
+static void mxs_lradc_prepare_x_pos(struct mxs_lradc *lradc)
+{
+	mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
+	mxs_lradc_reg_set(lradc, mxs_lradc_drive_x_plate(lradc), LRADC_CTRL0);
+
+	lradc->cur_plate = LRADC_SAMPLE_X;
+	mxs_lradc_setup_ts_channel(lradc, TS_CH_YP);
+}
+
+/*
+ *   YP(+)--+-------------+
+ *          |             |--+
+ *          |             |  |
+ *   YM(-)--+-------------+  |
+ *            +--------------+
+ *            |              |
+ *         XP(open)        XM(meas)
+ *
+ * (+) means here 1.85 V
+ * (-) means here GND
+ */
+static void mxs_lradc_prepare_y_pos(struct mxs_lradc *lradc)
+{
+	mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
+	mxs_lradc_reg_set(lradc, mxs_lradc_drive_y_plate(lradc), LRADC_CTRL0);
+
+	lradc->cur_plate = LRADC_SAMPLE_Y;
+	mxs_lradc_setup_ts_channel(lradc, TS_CH_XM);
+}
+
+/*
+ *    YP(+)--+-------------+
+ *           |             |--+
+ *           |             |  |
+ * YM(meas)--+-------------+  |
+ *             +--------------+
+ *             |              |
+ *          XP(meas)        XM(-)
+ *
+ * (+) means here 1.85 V
+ * (-) means here GND
+ */
+static void mxs_lradc_prepare_pressure(struct mxs_lradc *lradc)
+{
+	mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
+	mxs_lradc_reg_set(lradc, mxs_lradc_drive_pressure(lradc), LRADC_CTRL0);
+
+	lradc->cur_plate = LRADC_SAMPLE_PRESSURE;
+	mxs_lradc_setup_ts_pressure(lradc, TS_CH_XP, TS_CH_YM);
+}
+
+static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc)
+{
+	mxs_lradc_setup_touch_detection(lradc);
+
+	lradc->cur_plate = LRADC_TOUCH;
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ |
+				LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
+	mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
+}
+
+static void mxs_lradc_report_ts_event(struct mxs_lradc *lradc)
+{
+	input_report_abs(lradc->ts_input, ABS_X, lradc->ts_x_pos);
+	input_report_abs(lradc->ts_input, ABS_Y, lradc->ts_y_pos);
+	input_report_abs(lradc->ts_input, ABS_PRESSURE, lradc->ts_pressure);
+	input_report_key(lradc->ts_input, BTN_TOUCH, 1);
+	input_sync(lradc->ts_input);
+}
+
+static void mxs_lradc_complete_touch_event(struct mxs_lradc *lradc)
+{
+	mxs_lradc_setup_touch_detection(lradc);
+	lradc->cur_plate = LRADC_SAMPLE_VALID;
+	/*
+	 * start a dummy conversion to burn time to settle the signals
+	 * note: we are not interested in the conversion's value
+	 */
+	mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(5));
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
+	mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(5), LRADC_CTRL1);
+	mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << 5) |
+		LRADC_DELAY_KICK | LRADC_DELAY_DELAY(10), /* waste 5 ms */
+			LRADC_DELAY(2));
+}
+
+/*
+ * in order to avoid false measurements, report only samples where
+ * the surface is still touched after the position measurement
+ */
+static void mxs_lradc_finish_touch_event(struct mxs_lradc *lradc, bool valid)
+{
+	/* if it is still touched, report the sample */
+	if (valid && mxs_lradc_check_touch_event(lradc)) {
+		lradc->ts_valid = true;
+		mxs_lradc_report_ts_event(lradc);
+	}
+
+	/* if it is even still touched, continue with the next measurement */
+	if (mxs_lradc_check_touch_event(lradc)) {
+		mxs_lradc_prepare_y_pos(lradc);
+		return;
+	}
+
+	if (lradc->ts_valid) {
+		/* signal the release */
+		lradc->ts_valid = false;
+		input_report_key(lradc->ts_input, BTN_TOUCH, 0);
+		input_sync(lradc->ts_input);
+	}
+
+	/* if it is released, wait for the next touch via IRQ */
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1);
+	mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
+}
+
+/* touchscreen's state machine */
+static void mxs_lradc_handle_touch(struct mxs_lradc *lradc)
+{
+	int val;
+
+	switch (lradc->cur_plate) {
+	case LRADC_TOUCH:
+		/*
+		 * start with the Y-pos, because it uses nearly the same plate
+		 * settings like the touch detection
+		 */
+		if (mxs_lradc_check_touch_event(lradc)) {
+			mxs_lradc_reg_clear(lradc,
+					LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
+					LRADC_CTRL1);
+			mxs_lradc_prepare_y_pos(lradc);
+		}
+		mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ,
+					LRADC_CTRL1);
+		return;
+
+	case LRADC_SAMPLE_Y:
+		val = mxs_lradc_read_ts_channel(lradc);
+		if (val < 0) {
+			mxs_lradc_enable_touch_detection(lradc); /* re-start */
+			return;
+		}
+		lradc->ts_y_pos = val;
+		mxs_lradc_prepare_x_pos(lradc);
+		return;
+
+	case LRADC_SAMPLE_X:
+		val = mxs_lradc_read_ts_channel(lradc);
+		if (val < 0) {
+			mxs_lradc_enable_touch_detection(lradc); /* re-start */
+			return;
+		}
+		lradc->ts_x_pos = val;
+		mxs_lradc_prepare_pressure(lradc);
+		return;
+
+	case LRADC_SAMPLE_PRESSURE:
+		lradc->ts_pressure =
+			mxs_lradc_read_ts_pressure(lradc, TS_CH_XP, TS_CH_YM);
+		mxs_lradc_complete_touch_event(lradc);
+		return;
+
+	case LRADC_SAMPLE_VALID:
+		val = mxs_lradc_read_ts_channel(lradc); /* ignore the value */
+		mxs_lradc_finish_touch_event(lradc, 1);
+		break;
+	}
+}
+
 /*
  * Raw I/O operations
  */
@@ -262,21 +790,20 @@
 	 * Virtual channel 0 is always used here as the others are always not
 	 * used if doing raw sampling.
 	 */
-	writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
-	writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
+	if (lradc->soc == IMX28_LRADC)
+		mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
+			LRADC_CTRL1);
+	mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
 
 	/* Clean the slot's previous content, then set new one. */
-	writel(LRADC_CTRL4_LRADCSELECT_MASK(0),
-		lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_CLR);
-	writel(chan->channel, lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_SET);
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(0), LRADC_CTRL4);
+	mxs_lradc_reg_set(lradc, chan->channel, LRADC_CTRL4);
 
-	writel(0, lradc->base + LRADC_CH(0));
+	mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(0));
 
 	/* Enable the IRQ and start sampling the channel. */
-	writel(LRADC_CTRL1_LRADC_IRQ_EN(0),
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET);
-	writel(1 << 0, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
+	mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0), LRADC_CTRL1);
+	mxs_lradc_reg_set(lradc, 1 << 0, LRADC_CTRL0);
 
 	/* Wait for completion on the channel, 1 second max. */
 	ret = wait_for_completion_killable_timeout(&lradc->completion, HZ);
@@ -290,8 +817,7 @@
 	ret = IIO_VAL_INT;
 
 err:
-	writel(LRADC_CTRL1_LRADC_IRQ_EN(0),
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0), LRADC_CTRL1);
 
 	mutex_unlock(&lradc->lock);
 
@@ -303,220 +829,33 @@
 	.read_raw		= mxs_lradc_read_raw,
 };
 
-/*
- * Touchscreen handling
- */
-enum lradc_ts_plate {
-	LRADC_SAMPLE_X,
-	LRADC_SAMPLE_Y,
-	LRADC_SAMPLE_PRESSURE,
-};
-
-static int mxs_lradc_ts_touched(struct mxs_lradc *lradc)
-{
-	uint32_t reg;
-
-	/* Enable touch detection. */
-	writel(LRADC_CTRL0_PLATE_MASK,
-		lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
-	writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE,
-		lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
-
-	msleep(LRADC_TS_SAMPLE_DELAY_MS);
-
-	reg = readl(lradc->base + LRADC_STATUS);
-
-	return reg & LRADC_STATUS_TOUCH_DETECT_RAW;
-}
-
-static int32_t mxs_lradc_ts_sample(struct mxs_lradc *lradc,
-				enum lradc_ts_plate plate, int change)
-{
-	unsigned long delay, jiff;
-	uint32_t reg, ctrl0 = 0, chan = 0;
-	/* The touchscreen always uses CTRL4 slot #7. */
-	const uint8_t slot = 7;
-	uint32_t val;
-
-	/*
-	 * There are three correct configurations of the controller sampling
-	 * the touchscreen, each of these configuration provides different
-	 * information from the touchscreen.
-	 *
-	 * The following table describes the sampling configurations:
-	 * +-------------+-------+-------+-------+
-	 * | Wire \ Axis |   X   |   Y   |   Z   |
-	 * +---------------------+-------+-------+
-	 * |   X+ (CH2)  |   HI  |   TS  |   TS  |
-	 * +-------------+-------+-------+-------+
-	 * |   X- (CH4)  |   LO  |   SH  |   HI  |
-	 * +-------------+-------+-------+-------+
-	 * |   Y+ (CH3)  |   SH  |   HI  |   HI  |
-	 * +-------------+-------+-------+-------+
-	 * |   Y- (CH5)  |   TS  |   LO  |   SH  |
-	 * +-------------+-------+-------+-------+
-	 *
-	 * HI ... strong '1'  ; LO ... strong '0'
-	 * SH ... sample here ; TS ... tri-state
-	 *
-	 * There are a few other ways of obtaining the Z coordinate
-	 * (aka. pressure), but the one in the table seems to be the
-	 * most reliable one.
-	 */
-	switch (plate) {
-	case LRADC_SAMPLE_X:
-		ctrl0 = LRADC_CTRL0_XPPSW | LRADC_CTRL0_XNNSW;
-		chan = 3;
-		break;
-	case LRADC_SAMPLE_Y:
-		ctrl0 = LRADC_CTRL0_YPPSW | LRADC_CTRL0_YNNSW;
-		chan = 4;
-		break;
-	case LRADC_SAMPLE_PRESSURE:
-		ctrl0 = LRADC_CTRL0_YPPSW | LRADC_CTRL0_XNNSW;
-		chan = 5;
-		break;
-	}
-
-	if (change) {
-		writel(LRADC_CTRL0_PLATE_MASK,
-			lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
-		writel(ctrl0, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
-
-		writel(LRADC_CTRL4_LRADCSELECT_MASK(slot),
-			lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_CLR);
-		writel(chan << LRADC_CTRL4_LRADCSELECT_OFFSET(slot),
-			lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_SET);
-	}
-
-	writel(0xffffffff, lradc->base + LRADC_CH(slot) + STMP_OFFSET_REG_CLR);
-	writel(1 << slot, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
-
-	delay = jiffies + msecs_to_jiffies(LRADC_TS_SAMPLE_DELAY_MS);
-	do {
-		jiff = jiffies;
-		reg = readl_relaxed(lradc->base + LRADC_CTRL1);
-		if (reg & LRADC_CTRL1_LRADC_IRQ(slot))
-			break;
-	} while (time_before(jiff, delay));
-
-	writel(LRADC_CTRL1_LRADC_IRQ(slot),
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
-
-	if (time_after_eq(jiff, delay))
-		return -ETIMEDOUT;
-
-	val = readl(lradc->base + LRADC_CH(slot));
-	val &= LRADC_CH_VALUE_MASK;
-
-	return val;
-}
-
-static int32_t mxs_lradc_ts_sample_filter(struct mxs_lradc *lradc,
-				enum lradc_ts_plate plate)
-{
-	int32_t val, tot = 0;
-	int i;
-
-	val = mxs_lradc_ts_sample(lradc, plate, 1);
-
-	/* Delay a bit so the touchscreen is stable. */
-	mdelay(2);
-
-	for (i = 0; i < LRADC_TS_SAMPLE_AMOUNT; i++) {
-		val = mxs_lradc_ts_sample(lradc, plate, 0);
-		tot += val;
-	}
-
-	return tot / LRADC_TS_SAMPLE_AMOUNT;
-}
-
-static void mxs_lradc_ts_work(struct work_struct *ts_work)
-{
-	struct mxs_lradc *lradc = container_of(ts_work,
-				struct mxs_lradc, ts_work);
-	int val_x, val_y, val_p;
-	bool valid = false;
-
-	while (mxs_lradc_ts_touched(lradc)) {
-		/* Disable touch detector so we can sample the touchscreen. */
-		writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE,
-			lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
-
-		if (likely(valid)) {
-			input_report_abs(lradc->ts_input, ABS_X, val_x);
-			input_report_abs(lradc->ts_input, ABS_Y, val_y);
-			input_report_abs(lradc->ts_input, ABS_PRESSURE, val_p);
-			input_report_key(lradc->ts_input, BTN_TOUCH, 1);
-			input_sync(lradc->ts_input);
-		}
-
-		valid = false;
-
-		val_x = mxs_lradc_ts_sample_filter(lradc, LRADC_SAMPLE_X);
-		if (val_x < 0)
-			continue;
-		val_y = mxs_lradc_ts_sample_filter(lradc, LRADC_SAMPLE_Y);
-		if (val_y < 0)
-			continue;
-		val_p = mxs_lradc_ts_sample_filter(lradc, LRADC_SAMPLE_PRESSURE);
-		if (val_p < 0)
-			continue;
-
-		valid = true;
-	}
-
-	input_report_abs(lradc->ts_input, ABS_PRESSURE, 0);
-	input_report_key(lradc->ts_input, BTN_TOUCH, 0);
-	input_sync(lradc->ts_input);
-
-	/* Do not restart the TS IRQ if the driver is shutting down. */
-	if (lradc->stop_touchscreen)
-		return;
-
-	/* Restart the touchscreen interrupts. */
-	writel(LRADC_CTRL1_TOUCH_DETECT_IRQ,
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
-	writel(LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET);
-}
-
 static int mxs_lradc_ts_open(struct input_dev *dev)
 {
 	struct mxs_lradc *lradc = input_get_drvdata(dev);
 
-	/* The touchscreen is starting. */
-	lradc->stop_touchscreen = false;
-
 	/* Enable the touch-detect circuitry. */
-	writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE,
-		lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
-
-	/* Enable the touch-detect IRQ. */
-	writel(LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET);
+	mxs_lradc_enable_touch_detection(lradc);
 
 	return 0;
 }
 
+static void mxs_lradc_disable_ts(struct mxs_lradc *lradc)
+{
+	/* stop all interrupts from firing */
+	mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN |
+		LRADC_CTRL1_LRADC_IRQ_EN(2) | LRADC_CTRL1_LRADC_IRQ_EN(3) |
+		LRADC_CTRL1_LRADC_IRQ_EN(4) | LRADC_CTRL1_LRADC_IRQ_EN(5),
+		LRADC_CTRL1);
+
+	/* Power-down touchscreen touch-detect circuitry. */
+	mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
+}
+
 static void mxs_lradc_ts_close(struct input_dev *dev)
 {
 	struct mxs_lradc *lradc = input_get_drvdata(dev);
 
-	/* Indicate the touchscreen is stopping. */
-	lradc->stop_touchscreen = true;
-	mb();
-
-	/* Wait until touchscreen thread finishes any possible remnants. */
-	cancel_work_sync(&lradc->ts_work);
-
-	/* Disable touchscreen touch-detect IRQ. */
-	writel(LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
-
-	/* Power-down touchscreen touch-detect circuitry. */
-	writel(LRADC_CTRL0_TOUCH_DETECT_ENABLE,
-		lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
+	mxs_lradc_disable_ts(lradc);
 }
 
 static int mxs_lradc_ts_register(struct mxs_lradc *lradc)
@@ -529,10 +868,8 @@
 		return 0;
 
 	input = input_allocate_device();
-	if (!input) {
-		dev_err(dev, "Failed to allocate TS device!\n");
+	if (!input)
 		return -ENOMEM;
-	}
 
 	input->name = DRIVER_NAME;
 	input->id.bustype = BUS_HOST;
@@ -562,8 +899,7 @@
 	if (!lradc->use_touchscreen)
 		return;
 
-	cancel_work_sync(&lradc->ts_work);
-
+	mxs_lradc_disable_ts(lradc);
 	input_unregister_device(lradc->ts_input);
 }
 
@@ -576,31 +912,24 @@
 	struct mxs_lradc *lradc = iio_priv(iio);
 	unsigned long reg = readl(lradc->base + LRADC_CTRL1);
 	const uint32_t ts_irq_mask =
-		LRADC_CTRL1_TOUCH_DETECT_IRQ_EN |
-		LRADC_CTRL1_TOUCH_DETECT_IRQ;
+		LRADC_CTRL1_TOUCH_DETECT_IRQ |
+		LRADC_CTRL1_LRADC_IRQ(2) |
+		LRADC_CTRL1_LRADC_IRQ(3) |
+		LRADC_CTRL1_LRADC_IRQ(4) |
+		LRADC_CTRL1_LRADC_IRQ(5);
 
-	if (!(reg & LRADC_CTRL1_LRADC_IRQ_MASK))
+	if (!(reg & mxs_lradc_irq_mask(lradc)))
 		return IRQ_NONE;
 
-	/*
-	 * Touchscreen IRQ handling code has priority and therefore
-	 * is placed here. In case touchscreen IRQ arrives, disable
-	 * it ASAP
-	 */
-	if (reg & LRADC_CTRL1_TOUCH_DETECT_IRQ) {
-		writel(ts_irq_mask,
-			lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
-		if (!lradc->stop_touchscreen)
-			schedule_work(&lradc->ts_work);
-	}
+	if (lradc->use_touchscreen && (reg & ts_irq_mask))
+		mxs_lradc_handle_touch(lradc);
 
 	if (iio_buffer_enabled(iio))
 		iio_trigger_poll(iio->trig, iio_get_time_ns());
 	else if (reg & LRADC_CTRL1_LRADC_IRQ(0))
 		complete(&lradc->completion);
 
-	writel(reg & LRADC_CTRL1_LRADC_IRQ_MASK,
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
+	mxs_lradc_reg_clear(lradc, reg & mxs_lradc_irq_mask(lradc), LRADC_CTRL1);
 
 	return IRQ_HANDLED;
 }
@@ -619,19 +948,13 @@
 
 	for_each_set_bit(i, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) {
 		lradc->buffer[j] = readl(lradc->base + LRADC_CH(j));
-		writel(chan_value, lradc->base + LRADC_CH(j));
+		mxs_lradc_reg_wrt(lradc, chan_value, LRADC_CH(j));
 		lradc->buffer[j] &= LRADC_CH_VALUE_MASK;
 		lradc->buffer[j] /= LRADC_DELAY_TIMER_LOOP;
 		j++;
 	}
 
-	if (iio->scan_timestamp) {
-		s64 *timestamp = (s64 *)((u8 *)lradc->buffer +
-					ALIGN(j, sizeof(s64)));
-		*timestamp = pf->timestamp;
-	}
-
-	iio_push_to_buffers(iio, (u8 *)lradc->buffer);
+	iio_push_to_buffers_with_timestamp(iio, lradc->buffer, pf->timestamp);
 
 	iio_trigger_notify_done(iio->trig);
 
@@ -644,7 +967,7 @@
 	struct mxs_lradc *lradc = iio_priv(iio);
 	const uint32_t st = state ? STMP_OFFSET_REG_SET : STMP_OFFSET_REG_CLR;
 
-	writel(LRADC_DELAY_KICK, lradc->base + LRADC_DELAY(0) + st);
+	mxs_lradc_reg_wrt(lradc, LRADC_DELAY_KICK, LRADC_DELAY(0) + st);
 
 	return 0;
 }
@@ -716,38 +1039,30 @@
 		goto err_mem;
 	}
 
-	ret = iio_sw_buffer_preenable(iio);
-	if (ret < 0)
-		goto err_buf;
-
-	writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
-	writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
+	if (lradc->soc == IMX28_LRADC)
+		mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
+							LRADC_CTRL1);
+	mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
 
 	for_each_set_bit(chan, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) {
 		ctrl4_set |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs);
 		ctrl4_clr |= LRADC_CTRL4_LRADCSELECT_MASK(ofs);
 		ctrl1_irq |= LRADC_CTRL1_LRADC_IRQ_EN(ofs);
-		writel(chan_value, lradc->base + LRADC_CH(ofs));
+		mxs_lradc_reg_wrt(lradc, chan_value, LRADC_CH(ofs));
 		bitmap_set(&enable, ofs, 1);
 		ofs++;
 	}
 
-	writel(LRADC_DELAY_TRIGGER_LRADCS_MASK | LRADC_DELAY_KICK,
-		lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR);
-
-	writel(ctrl4_clr, lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_CLR);
-	writel(ctrl4_set, lradc->base + LRADC_CTRL4 + STMP_OFFSET_REG_SET);
-
-	writel(ctrl1_irq, lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET);
-
-	writel(enable << LRADC_DELAY_TRIGGER_LRADCS_OFFSET,
-		lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_SET);
+	mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK |
+					LRADC_DELAY_KICK, LRADC_DELAY(0));
+	mxs_lradc_reg_clear(lradc, ctrl4_clr, LRADC_CTRL4);
+	mxs_lradc_reg_set(lradc, ctrl4_set, LRADC_CTRL4);
+	mxs_lradc_reg_set(lradc, ctrl1_irq, LRADC_CTRL1);
+	mxs_lradc_reg_set(lradc, enable << LRADC_DELAY_TRIGGER_LRADCS_OFFSET,
+					LRADC_DELAY(0));
 
 	return 0;
 
-err_buf:
-	kfree(lradc->buffer);
 err_mem:
 	mutex_unlock(&lradc->lock);
 	return ret;
@@ -757,12 +1072,13 @@
 {
 	struct mxs_lradc *lradc = iio_priv(iio);
 
-	writel(LRADC_DELAY_TRIGGER_LRADCS_MASK | LRADC_DELAY_KICK,
-		lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR);
+	mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK |
+					LRADC_DELAY_KICK, LRADC_DELAY(0));
 
-	writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
-	writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
+	mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
+	if (lradc->soc == IMX28_LRADC)
+		mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
+					LRADC_CTRL1);
 
 	kfree(lradc->buffer);
 	mutex_unlock(&lradc->lock);
@@ -857,24 +1173,25 @@
 		return ret;
 
 	/* Configure DELAY CHANNEL 0 for generic ADC sampling. */
-	writel(adc_cfg, lradc->base + LRADC_DELAY(0));
+	mxs_lradc_reg_wrt(lradc, adc_cfg, LRADC_DELAY(0));
 
 	/* Disable remaining DELAY CHANNELs */
-	writel(0, lradc->base + LRADC_DELAY(1));
-	writel(0, lradc->base + LRADC_DELAY(2));
-	writel(0, lradc->base + LRADC_DELAY(3));
+	mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(1));
+	mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2));
+	mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3));
 
 	/* Configure the touchscreen type */
-	writel(LRADC_CTRL0_TOUCH_SCREEN_TYPE,
-		lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
+	if (lradc->soc == IMX28_LRADC) {
+		mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
+							LRADC_CTRL0);
 
-	if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE) {
-		writel(LRADC_CTRL0_TOUCH_SCREEN_TYPE,
-			lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
+	if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE)
+		mxs_lradc_reg_set(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
+				LRADC_CTRL0);
 	}
 
 	/* Start internal temperature sensing. */
-	writel(0, lradc->base + LRADC_CTRL2);
+	mxs_lradc_reg_wrt(lradc, 0, LRADC_CTRL2);
 
 	return 0;
 }
@@ -883,11 +1200,10 @@
 {
 	int i;
 
-	writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
-		lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
+	mxs_lradc_reg_clear(lradc, mxs_lradc_irq_en_mask(lradc), LRADC_CTRL1);
 
 	for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++)
-		writel(0, lradc->base + LRADC_DELAY(i));
+		mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(i));
 }
 
 static const struct of_device_id mxs_lradc_dt_ids[] = {
@@ -897,6 +1213,52 @@
 };
 MODULE_DEVICE_TABLE(of, mxs_lradc_dt_ids);
 
+static int mxs_lradc_probe_touchscreen(struct mxs_lradc *lradc,
+						struct device_node *lradc_node)
+{
+	int ret;
+	u32 ts_wires = 0, adapt;
+
+	ret = of_property_read_u32(lradc_node, "fsl,lradc-touchscreen-wires",
+				&ts_wires);
+	if (ret)
+		return -ENODEV; /* touchscreen feature disabled */
+
+	switch (ts_wires) {
+	case 4:
+		lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_4WIRE;
+		break;
+	case 5:
+		if (lradc->soc == IMX28_LRADC) {
+			lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_5WIRE;
+			break;
+		}
+		/* fall through an error message for i.MX23 */
+	default:
+		dev_err(lradc->dev,
+			"Unsupported number of touchscreen wires (%d)\n",
+			ts_wires);
+		return -EINVAL;
+	}
+
+	lradc->over_sample_cnt = 4;
+	ret = of_property_read_u32(lradc_node, "fsl,ave-ctrl", &adapt);
+	if (ret == 0)
+		lradc->over_sample_cnt = adapt;
+
+	lradc->over_sample_delay = 2;
+	ret = of_property_read_u32(lradc_node, "fsl,ave-delay", &adapt);
+	if (ret == 0)
+		lradc->over_sample_delay = adapt;
+
+	lradc->settling_delay = 10;
+	ret = of_property_read_u32(lradc_node, "fsl,settling", &adapt);
+	if (ret == 0)
+		lradc->settling_delay = adapt;
+
+	return 0;
+}
+
 static int mxs_lradc_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *of_id =
@@ -908,8 +1270,7 @@
 	struct mxs_lradc *lradc;
 	struct iio_dev *iio;
 	struct resource *iores;
-	uint32_t ts_wires = 0;
-	int ret = 0;
+	int ret = 0, touch_ret;
 	int i;
 
 	/* Allocate the IIO device. */
@@ -920,6 +1281,7 @@
 	}
 
 	lradc = iio_priv(iio);
+	lradc->soc = (enum mxs_lradc_id)of_id->data;
 
 	/* Grab the memory area */
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -928,20 +1290,18 @@
 	if (IS_ERR(lradc->base))
 		return PTR_ERR(lradc->base);
 
-	INIT_WORK(&lradc->ts_work, mxs_lradc_ts_work);
+	lradc->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(lradc->clk)) {
+		dev_err(dev, "Failed to get the delay unit clock\n");
+		return PTR_ERR(lradc->clk);
+	}
+	ret = clk_prepare_enable(lradc->clk);
+	if (ret != 0) {
+		dev_err(dev, "Failed to enable the delay unit clock\n");
+		return ret;
+	}
 
-	/* Check if touchscreen is enabled in DT. */
-	ret = of_property_read_u32(node, "fsl,lradc-touchscreen-wires",
-				&ts_wires);
-	if (ret)
-		dev_info(dev, "Touchscreen not enabled.\n");
-	else if (ts_wires == 4)
-		lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_4WIRE;
-	else if (ts_wires == 5)
-		lradc->use_touchscreen = MXS_LRADC_TOUCHSCREEN_5WIRE;
-	else
-		dev_warn(dev, "Unsupported number of touchscreen wires (%d)\n",
-				ts_wires);
+	touch_ret = mxs_lradc_probe_touchscreen(lradc, node);
 
 	/* Grab all IRQ sources */
 	for (i = 0; i < of_cfg->irq_count; i++) {
@@ -985,9 +1345,11 @@
 		goto err_dev;
 
 	/* Register the touchscreen input device. */
-	ret = mxs_lradc_ts_register(lradc);
-	if (ret)
-		goto err_dev;
+	if (touch_ret == 0) {
+		ret = mxs_lradc_ts_register(lradc);
+		if (ret)
+			goto err_ts_register;
+	}
 
 	/* Register IIO device. */
 	ret = iio_device_register(iio);
@@ -1000,6 +1362,8 @@
 
 err_ts:
 	mxs_lradc_ts_unregister(lradc);
+err_ts_register:
+	mxs_lradc_hw_stop(lradc);
 err_dev:
 	mxs_lradc_trigger_remove(iio);
 err_trig:
@@ -1012,14 +1376,13 @@
 	struct iio_dev *iio = platform_get_drvdata(pdev);
 	struct mxs_lradc *lradc = iio_priv(iio);
 
-	mxs_lradc_ts_unregister(lradc);
-
-	mxs_lradc_hw_stop(lradc);
-
 	iio_device_unregister(iio);
-	iio_triggered_buffer_cleanup(iio);
+	mxs_lradc_ts_unregister(lradc);
+	mxs_lradc_hw_stop(lradc);
 	mxs_lradc_trigger_remove(iio);
+	iio_triggered_buffer_cleanup(iio);
 
+	clk_disable_unprepare(lradc->clk);
 	return 0;
 }
 
@@ -1038,3 +1401,4 @@
 MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
 MODULE_DESCRIPTION("Freescale i.MX28 LRADC driver");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c
index 20f2d55..970d9ed 100644
--- a/drivers/staging/iio/adc/spear_adc.c
+++ b/drivers/staging/iio/adc/spear_adc.c
@@ -146,7 +146,6 @@
 			  long mask)
 {
 	struct spear_adc_info *info = iio_priv(indio_dev);
-	u32 scale_mv;
 	u32 status;
 
 	switch (mask) {
@@ -168,10 +167,9 @@
 		return IIO_VAL_INT;
 
 	case IIO_CHAN_INFO_SCALE:
-		scale_mv = (info->vref_external * 1000) >> DATA_BITS;
-		*val =  scale_mv / 1000;
-		*val2 = (scale_mv % 1000) * 1000;
-		return IIO_VAL_INT_PLUS_MICRO;
+		*val = info->vref_external;
+		*val2 = DATA_BITS;
+		return IIO_VAL_FRACTIONAL_LOG2;
 	}
 
 	return -EINVAL;
@@ -320,7 +318,7 @@
 		return -ENOMEM;
 	}
 	info->adc_base_spear3xx =
-		(struct adc_regs_spear3xx *)info->adc_base_spear6xx;
+		(struct adc_regs_spear3xx __iomem *)info->adc_base_spear6xx;
 
 	info->clk = clk_get(dev, NULL);
 	if (IS_ERR(info->clk)) {
@@ -335,7 +333,7 @@
 	}
 
 	irq = platform_get_irq(pdev, 0);
-	if ((irq < 0) || (irq >= NR_IRQS)) {
+	if (irq <= 0) {
 		dev_err(dev, "failed getting interrupt resource\n");
 		ret = -EINVAL;
 		goto errout3;
diff --git a/drivers/staging/iio/addac/adt7316-i2c.c b/drivers/staging/iio/addac/adt7316-i2c.c
index ce7d91c..0feea55 100644
--- a/drivers/staging/iio/addac/adt7316-i2c.c
+++ b/drivers/staging/iio/addac/adt7316-i2c.c
@@ -138,6 +138,5 @@
 module_i2c_driver(adt7316_driver);
 
 MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
-MODULE_DESCRIPTION("I2C bus driver for Analog Devices ADT7316/7/9 and"
-			"ADT7516/7/8 digital temperature sensor, ADC and DAC");
+MODULE_DESCRIPTION("I2C bus driver for Analog Devices ADT7316/7/9 and ADT7516/7/8 digital temperature sensor, ADC and DAC");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/addac/adt7316-spi.c b/drivers/staging/iio/addac/adt7316-spi.c
index 0db8ef5..7f4f0a8 100644
--- a/drivers/staging/iio/addac/adt7316-spi.c
+++ b/drivers/staging/iio/addac/adt7316-spi.c
@@ -146,6 +146,5 @@
 module_spi_driver(adt7316_driver);
 
 MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
-MODULE_DESCRIPTION("SPI bus driver for Analog Devices ADT7316/7/8 and"
-			"ADT7516/7/9 digital temperature sensor, ADC and DAC");
+MODULE_DESCRIPTION("SPI bus driver for Analog Devices ADT7316/7/8 and ADT7516/7/9 digital temperature sensor, ADC and DAC");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c
index 1e13568..80266e8 100644
--- a/drivers/staging/iio/addac/adt7316.c
+++ b/drivers/staging/iio/addac/adt7316.c
@@ -412,13 +412,13 @@
 	struct iio_dev *dev_info = dev_to_iio_dev(dev);
 	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 config2;
-	unsigned long data = 0;
+	u8 data;
 	int ret;
 
 	if (!(chip->config2 & ADT7316_AD_SINGLE_CH_MODE))
 		return -EPERM;
 
-	ret = strict_strtoul(buf, 10, &data);
+	ret = kstrtou8(buf, 10, &data);
 	if (ret)
 		return -EINVAL;
 
@@ -823,10 +823,10 @@
 	struct iio_dev *dev_info = dev_to_iio_dev(dev);
 	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 dac_config;
-	unsigned long data = 0;
+	u8 data;
 	int ret;
 
-	ret = strict_strtoul(buf, 16, &data);
+	ret = kstrtou8(buf, 16, &data);
 	if (ret || data > ADT7316_DA_2VREF_CH_MASK)
 		return -EINVAL;
 
@@ -878,13 +878,13 @@
 	struct iio_dev *dev_info = dev_to_iio_dev(dev);
 	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 dac_config;
-	unsigned long data;
+	u8 data;
 	int ret;
 
 	if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA))
 		return -EPERM;
 
-	ret = strict_strtoul(buf, 10, &data);
+	ret = kstrtou8(buf, 10, &data);
 	if (ret || data > ADT7316_DA_EN_MODE_MASK)
 		return -EINVAL;
 
@@ -933,7 +933,7 @@
 	struct iio_dev *dev_info = dev_to_iio_dev(dev);
 	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 ldac_config;
-	unsigned long data;
+	u8 data;
 	int ret;
 
 	if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDCA) {
@@ -941,7 +941,7 @@
 			ADT7316_DA_EN_MODE_LDAC)
 			return -EPERM;
 
-		ret = strict_strtoul(buf, 16, &data);
+		ret = kstrtou8(buf, 16, &data);
 		if (ret || data > ADT7316_LDAC_EN_DA_MASK)
 			return -EINVAL;
 
@@ -1079,11 +1079,11 @@
 	struct iio_dev *dev_info = dev_to_iio_dev(dev);
 	struct adt7316_chip_info *chip = iio_priv(dev_info);
 	u8 ldac_config;
-	unsigned long data;
+	u8 data;
 	int ret;
 
 	if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) {
-		ret = strict_strtoul(buf, 16, &data);
+		ret = kstrtou8(buf, 16, &data);
 		if (ret || data > 3)
 			return -EINVAL;
 
@@ -1093,7 +1093,7 @@
 		else if (data & 0x2)
 			ldac_config |= ADT7516_DAC_CD_IN_VREF;
 	} else {
-		ret = strict_strtoul(buf, 16, &data);
+		ret = kstrtou8(buf, 16, &data);
 		if (ret)
 			return -EINVAL;
 
@@ -1281,11 +1281,11 @@
 static ssize_t adt7316_store_temp_offset(struct adt7316_chip_info *chip,
 		int offset_addr, const char *buf, size_t len)
 {
-	long data;
+	int data;
 	u8 val;
 	int ret;
 
-	ret = strict_strtol(buf, 10, &data);
+	ret = kstrtoint(buf, 10, &data);
 	if (ret || data > 127 || data < -128)
 		return -EINVAL;
 
@@ -1442,7 +1442,7 @@
 		int channel, const char *buf, size_t len)
 {
 	u8 msb, lsb, offset;
-	unsigned long data;
+	u16 data;
 	int ret;
 
 	if (channel >= ADT7316_DA_MSB_DATA_REGS ||
@@ -1454,7 +1454,7 @@
 
 	offset = chip->dac_bits - 8;
 
-	ret = strict_strtoul(buf, 10, &data);
+	ret = kstrtou16(buf, 10, &data);
 	if (ret || data >= (1 << chip->dac_bits))
 		return -EINVAL;
 
@@ -1830,11 +1830,11 @@
 {
 	struct iio_dev *dev_info = dev_to_iio_dev(dev);
 	struct adt7316_chip_info *chip = iio_priv(dev_info);
-	unsigned long data;
+	u16 data;
 	int ret;
 	u8 mask;
 
-	ret = strict_strtoul(buf, 16, &data);
+	ret = kstrtou16(buf, 16, &data);
 	if (ret || data >= ADT7316_VDD_INT_MASK + 1)
 		return -EINVAL;
 
@@ -1901,7 +1901,7 @@
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	struct iio_dev *dev_info = dev_to_iio_dev(dev);
 	struct adt7316_chip_info *chip = iio_priv(dev_info);
-	long data;
+	int data;
 	u8 val;
 	int ret;
 
@@ -1909,7 +1909,7 @@
 		this_attr->address > ADT7316_EX_TEMP_LOW)
 		return -EPERM;
 
-	ret = strict_strtol(buf, 10, &data);
+	ret = kstrtoint(buf, 10, &data);
 	if (ret)
 		return -EINVAL;
 
@@ -2106,11 +2106,9 @@
 	unsigned short *adt7316_platform_data = dev->platform_data;
 	int ret = 0;
 
-	indio_dev = iio_device_alloc(sizeof(*chip));
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*chip));
+	if (!indio_dev)
+		return -ENOMEM;
 	chip = iio_priv(indio_dev);
 	/* this is only used for device removal purposes */
 	dev_set_drvdata(dev, indio_dev);
@@ -2146,58 +2144,44 @@
 		if (adt7316_platform_data[0])
 			chip->bus.irq_flags = adt7316_platform_data[0];
 
-		ret = request_threaded_irq(chip->bus.irq,
-					   NULL,
-					   &adt7316_event_handler,
-					   chip->bus.irq_flags | IRQF_ONESHOT,
-					   indio_dev->name,
-					   indio_dev);
+		ret = devm_request_threaded_irq(dev, chip->bus.irq,
+						NULL,
+						&adt7316_event_handler,
+						chip->bus.irq_flags |
+						IRQF_ONESHOT,
+						indio_dev->name,
+						indio_dev);
 		if (ret)
-			goto error_free_dev;
+			return ret;
 
 		if (chip->bus.irq_flags & IRQF_TRIGGER_HIGH)
 			chip->config1 |= ADT7316_INT_POLARITY;
 	}
 
 	ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG1, chip->config1);
-	if (ret) {
-		ret = -EIO;
-		goto error_unreg_irq;
-	}
+	if (ret)
+		return -EIO;
 
 	ret = chip->bus.write(chip->bus.client, ADT7316_CONFIG3, chip->config3);
-	if (ret) {
-		ret = -EIO;
-		goto error_unreg_irq;
-	}
+	if (ret)
+		return -EIO;
 
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_unreg_irq;
+		return ret;
 
 	dev_info(dev, "%s temperature sensor, ADC and DAC registered.\n",
 			indio_dev->name);
 
 	return 0;
-
-error_unreg_irq:
-	free_irq(chip->bus.irq, indio_dev);
-error_free_dev:
-	iio_device_free(indio_dev);
-error_ret:
-	return ret;
 }
 EXPORT_SYMBOL(adt7316_probe);
 
 int adt7316_remove(struct device *dev)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adt7316_chip_info *chip = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	if (chip->bus.irq)
-		free_irq(chip->bus.irq, indio_dev);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c
index f4a0341..7e7f989 100644
--- a/drivers/staging/iio/cdc/ad7150.c
+++ b/drivers/staging/iio/cdc/ad7150.c
@@ -123,14 +123,14 @@
 	}
 }
 
-static int ad7150_read_event_config(struct iio_dev *indio_dev, u64 event_code)
+static int ad7150_read_event_config(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, enum iio_event_type type,
+	enum iio_event_direction dir)
 {
 	int ret;
 	u8 threshtype;
 	bool adaptive;
 	struct ad7150_chip_info *chip = iio_priv(indio_dev);
-	int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
-			IIO_EV_DIR_RISING);
 
 	ret = i2c_smbus_read_byte_data(chip->client, AD7150_CFG);
 	if (ret < 0)
@@ -139,42 +139,47 @@
 	threshtype = (ret >> 5) & 0x03;
 	adaptive = !!(ret & 0x80);
 
-	switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) {
+	switch (type) {
 	case IIO_EV_TYPE_MAG_ADAPTIVE:
-		if (rising)
+		if (dir == IIO_EV_DIR_RISING)
 			return adaptive && (threshtype == 0x1);
 		else
 			return adaptive && (threshtype == 0x0);
 	case IIO_EV_TYPE_THRESH_ADAPTIVE:
-		if (rising)
+		if (dir == IIO_EV_DIR_RISING)
 			return adaptive && (threshtype == 0x3);
 		else
 			return adaptive && (threshtype == 0x2);
 
 	case IIO_EV_TYPE_THRESH:
-		if (rising)
+		if (dir == IIO_EV_DIR_RISING)
 			return !adaptive && (threshtype == 0x1);
 		else
 			return !adaptive && (threshtype == 0x0);
+	default:
+		break;
 	}
 	return -EINVAL;
 }
 
 /* lock should be held */
-static int ad7150_write_event_params(struct iio_dev *indio_dev, u64 event_code)
+static int ad7150_write_event_params(struct iio_dev *indio_dev,
+	 unsigned int chan, enum iio_event_type type,
+	 enum iio_event_direction dir)
 {
 	int ret;
 	u16 value;
 	u8 sens, timeout;
 	struct ad7150_chip_info *chip = iio_priv(indio_dev);
-	int chan = IIO_EVENT_CODE_EXTRACT_CHAN(event_code);
-	int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
-			IIO_EV_DIR_RISING);
+	int rising = (dir == IIO_EV_DIR_RISING);
+	u64 event_code;
+
+	event_code = IIO_UNMOD_EVENT_CODE(IIO_CAPACITANCE, chan, type, dir);
 
 	if (event_code != chip->current_event)
 		return 0;
 
-	switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) {
+	switch (type) {
 		/* Note completely different from the adaptive versions */
 	case IIO_EV_TYPE_THRESH:
 		value = chip->threshold[rising][chan];
@@ -211,18 +216,20 @@
 }
 
 static int ad7150_write_event_config(struct iio_dev *indio_dev,
-				     u64 event_code, int state)
+	const struct iio_chan_spec *chan, enum iio_event_type type,
+	enum iio_event_direction dir, int state)
 {
 	u8 thresh_type, cfg, adaptive;
 	int ret;
 	struct ad7150_chip_info *chip = iio_priv(indio_dev);
-	int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
-			IIO_EV_DIR_RISING);
+	int rising = (dir == IIO_EV_DIR_RISING);
+	u64 event_code;
 
 	/* Something must always be turned on */
 	if (state == 0)
 		return -EINVAL;
 
+	event_code = IIO_UNMOD_EVENT_CODE(chan->type, chan->channel, type, dir);
 	if (event_code == chip->current_event)
 		return 0;
 	mutex_lock(&chip->state_lock);
@@ -232,7 +239,7 @@
 
 	cfg = ret & ~((0x03 << 5) | (0x1 << 7));
 
-	switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) {
+	switch (type) {
 	case IIO_EV_TYPE_MAG_ADAPTIVE:
 		adaptive = 1;
 		if (rising)
@@ -268,7 +275,7 @@
 	chip->current_event = event_code;
 
 	/* update control attributes */
-	ret = ad7150_write_event_params(indio_dev, event_code);
+	ret = ad7150_write_event_params(indio_dev, chan->channel, type, dir);
 error_ret:
 	mutex_unlock(&chip->state_lock);
 
@@ -276,53 +283,52 @@
 }
 
 static int ad7150_read_event_value(struct iio_dev *indio_dev,
-				   u64 event_code,
-				   int *val)
+				   const struct iio_chan_spec *chan,
+				   enum iio_event_type type,
+				   enum iio_event_direction dir,
+				   enum iio_event_info info,
+				   int *val, int *val2)
 {
-	int chan = IIO_EVENT_CODE_EXTRACT_CHAN(event_code);
 	struct ad7150_chip_info *chip = iio_priv(indio_dev);
-	int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
-			IIO_EV_DIR_RISING);
+	int rising = (dir == IIO_EV_DIR_RISING);
 
 	/* Complex register sharing going on here */
-	switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) {
+	switch (type) {
 	case IIO_EV_TYPE_MAG_ADAPTIVE:
-		*val = chip->mag_sensitivity[rising][chan];
-		return 0;
-
+		*val = chip->mag_sensitivity[rising][chan->channel];
+		return IIO_VAL_INT;
 	case IIO_EV_TYPE_THRESH_ADAPTIVE:
-		*val = chip->thresh_sensitivity[rising][chan];
-		return 0;
-
+		*val = chip->thresh_sensitivity[rising][chan->channel];
+		return IIO_VAL_INT;
 	case IIO_EV_TYPE_THRESH:
-		*val = chip->threshold[rising][chan];
-		return 0;
-
+		*val = chip->threshold[rising][chan->channel];
+		return IIO_VAL_INT;
 	default:
 		return -EINVAL;
-	};
+	}
 }
 
 static int ad7150_write_event_value(struct iio_dev *indio_dev,
-				   u64 event_code,
-				   int val)
+				   const struct iio_chan_spec *chan,
+				   enum iio_event_type type,
+				   enum iio_event_direction dir,
+				   enum iio_event_info info,
+				   int val, int val2)
 {
 	int ret;
 	struct ad7150_chip_info *chip = iio_priv(indio_dev);
-	int chan = IIO_EVENT_CODE_EXTRACT_CHAN(event_code);
-	int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
-			IIO_EV_DIR_RISING);
+	int rising = (dir == IIO_EV_DIR_RISING);
 
 	mutex_lock(&chip->state_lock);
-	switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) {
+	switch (type) {
 	case IIO_EV_TYPE_MAG_ADAPTIVE:
-		chip->mag_sensitivity[rising][chan] = val;
+		chip->mag_sensitivity[rising][chan->channel] = val;
 		break;
 	case IIO_EV_TYPE_THRESH_ADAPTIVE:
-		chip->thresh_sensitivity[rising][chan] = val;
+		chip->thresh_sensitivity[rising][chan->channel] = val;
 		break;
 	case IIO_EV_TYPE_THRESH:
-		chip->threshold[rising][chan] = val;
+		chip->threshold[rising][chan->channel] = val;
 		break;
 	default:
 		ret = -EINVAL;
@@ -330,7 +336,7 @@
 	}
 
 	/* write back if active */
-	ret = ad7150_write_event_params(indio_dev, event_code);
+	ret = ad7150_write_event_params(indio_dev, chan->channel, type, dir);
 
 error_ret:
 	mutex_unlock(&chip->state_lock);
@@ -374,17 +380,22 @@
 	struct ad7150_chip_info *chip = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	int chan = IIO_EVENT_CODE_EXTRACT_CHAN(this_attr->address);
-	int rising = !!(IIO_EVENT_CODE_EXTRACT_DIR(this_attr->address) ==
-			IIO_EV_DIR_RISING);
+	enum iio_event_direction dir;
+	enum iio_event_type type;
+	int rising;
 	u8 data;
 	int ret;
 
+	type = IIO_EVENT_CODE_EXTRACT_TYPE(this_attr->address);
+	dir = IIO_EVENT_CODE_EXTRACT_DIR(this_attr->address);
+	rising = (dir == IIO_EV_DIR_RISING);
+
 	ret = kstrtou8(buf, 10, &data);
 	if (ret < 0)
 		return ret;
 
 	mutex_lock(&chip->state_lock);
-	switch (IIO_EVENT_CODE_EXTRACT_TYPE(this_attr->address)) {
+	switch (type) {
 	case IIO_EV_TYPE_MAG_ADAPTIVE:
 		chip->mag_timeout[rising][chan] = data;
 		break;
@@ -396,7 +407,7 @@
 		goto error_ret;
 	}
 
-	ret = ad7150_write_event_params(indio_dev, this_attr->address);
+	ret = ad7150_write_event_params(indio_dev, chan, type, dir);
 error_ret:
 	mutex_unlock(&chip->state_lock);
 
@@ -424,6 +435,40 @@
 static AD7150_TIMEOUT(1, thresh_adaptive, rising, THRESH_ADAPTIVE, RISING);
 static AD7150_TIMEOUT(1, thresh_adaptive, falling, THRESH_ADAPTIVE, FALLING);
 
+static const struct iio_event_spec ad7150_events[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH_ADAPTIVE,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH_ADAPTIVE,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	}, {
+		.type = IIO_EV_TYPE_MAG_ADAPTIVE,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	}, {
+		.type = IIO_EV_TYPE_MAG_ADAPTIVE,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	},
+};
+
 static const struct iio_chan_spec ad7150_channels[] = {
 	{
 		.type = IIO_CAPACITANCE,
@@ -431,26 +476,16 @@
 		.channel = 0,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 		BIT(IIO_CHAN_INFO_AVERAGE_RAW),
-		.event_mask =
-		IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) |
-		IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING) |
-		IIO_EV_BIT(IIO_EV_TYPE_THRESH_ADAPTIVE, IIO_EV_DIR_RISING) |
-		IIO_EV_BIT(IIO_EV_TYPE_THRESH_ADAPTIVE, IIO_EV_DIR_FALLING) |
-		IIO_EV_BIT(IIO_EV_TYPE_MAG_ADAPTIVE, IIO_EV_DIR_RISING) |
-		IIO_EV_BIT(IIO_EV_TYPE_MAG_ADAPTIVE, IIO_EV_DIR_FALLING)
+		.event_spec = ad7150_events,
+		.num_event_specs = ARRAY_SIZE(ad7150_events),
 	}, {
 		.type = IIO_CAPACITANCE,
 		.indexed = 1,
 		.channel = 1,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 		BIT(IIO_CHAN_INFO_AVERAGE_RAW),
-		.event_mask =
-		IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) |
-		IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING) |
-		IIO_EV_BIT(IIO_EV_TYPE_THRESH_ADAPTIVE, IIO_EV_DIR_RISING) |
-		IIO_EV_BIT(IIO_EV_TYPE_THRESH_ADAPTIVE, IIO_EV_DIR_FALLING) |
-		IIO_EV_BIT(IIO_EV_TYPE_MAG_ADAPTIVE, IIO_EV_DIR_RISING) |
-		IIO_EV_BIT(IIO_EV_TYPE_MAG_ADAPTIVE, IIO_EV_DIR_FALLING)
+		.event_spec = ad7150_events,
+		.num_event_specs = ARRAY_SIZE(ad7150_events),
 	},
 };
 
@@ -541,10 +576,10 @@
 	.event_attrs = &ad7150_event_attribute_group,
 	.driver_module = THIS_MODULE,
 	.read_raw = &ad7150_read_raw,
-	.read_event_config = &ad7150_read_event_config,
-	.write_event_config = &ad7150_write_event_config,
-	.read_event_value = &ad7150_read_event_value,
-	.write_event_value = &ad7150_write_event_value,
+	.read_event_config_new = &ad7150_read_event_config,
+	.write_event_config_new = &ad7150_write_event_config,
+	.read_event_value_new = &ad7150_read_event_value,
+	.write_event_value_new = &ad7150_write_event_value,
 };
 
 /*
diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c
index 75a533b..862d68d 100644
--- a/drivers/staging/iio/cdc/ad7746.c
+++ b/drivers/staging/iio/cdc/ad7746.c
@@ -656,20 +656,21 @@
 		switch (chan->type) {
 		case IIO_CAPACITANCE:
 			/* 8.192pf / 2^24 */
-			*val2 = 488;
 			*val =  0;
+			*val2 = 488;
+			ret = IIO_VAL_INT_PLUS_NANO;
 			break;
 		case IIO_VOLTAGE:
 			/* 1170mV / 2^23 */
-			*val2 = 139475;
-			*val =  0;
+			*val = 1170;
+			*val2 = 23;
+			ret = IIO_VAL_FRACTIONAL_LOG2;
 			break;
 		default:
-			ret =  -EINVAL;
-			goto out;
+			ret = -EINVAL;
+			break;
 		}
 
-		ret = IIO_VAL_INT_PLUS_NANO;
 		break;
 	default:
 		ret = -EINVAL;
diff --git a/drivers/staging/iio/frequency/ad5930.c b/drivers/staging/iio/frequency/ad5930.c
index 69e90e9..a4aeee6 100644
--- a/drivers/staging/iio/frequency/ad5930.c
+++ b/drivers/staging/iio/frequency/ad5930.c
@@ -94,11 +94,9 @@
 	struct iio_dev *idev;
 	int ret = 0;
 
-	idev = iio_device_alloc(sizeof(*st));
-	if (idev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	idev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+	if (!idev)
+		return -ENOMEM;
 	spi_set_drvdata(spi, idev);
 	st = iio_priv(idev);
 
@@ -110,24 +108,18 @@
 
 	ret = iio_device_register(idev);
 	if (ret)
-		goto error_free_dev;
+		return ret;
 	spi->max_speed_hz = 2000000;
 	spi->mode = SPI_MODE_3;
 	spi->bits_per_word = 16;
 	spi_setup(spi);
 
 	return 0;
-
-error_free_dev:
-	iio_device_free(idev);
-error_ret:
-	return ret;
 }
 
 static int ad5930_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
-	iio_device_free(spi_get_drvdata(spi));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/frequency/ad9832.c b/drivers/staging/iio/frequency/ad9832.c
index 4e18380..c7d0307 100644
--- a/drivers/staging/iio/frequency/ad9832.c
+++ b/drivers/staging/iio/frequency/ad9832.c
@@ -81,9 +81,9 @@
 	struct ad9832_state *st = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	int ret;
-	long val;
+	unsigned long val;
 
-	ret = strict_strtoul(buf, 10, &val);
+	ret = kstrtoul(buf, 10, &val);
 	if (ret)
 		goto error_ret;
 
@@ -214,14 +214,14 @@
 		return -ENODEV;
 	}
 
-	reg = regulator_get(&spi->dev, "vcc");
+	reg = devm_regulator_get(&spi->dev, "vcc");
 	if (!IS_ERR(reg)) {
 		ret = regulator_enable(reg);
 		if (ret)
-			goto error_put_reg;
+			return ret;
 	}
 
-	indio_dev = iio_device_alloc(sizeof(*st));
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (indio_dev == NULL) {
 		ret = -ENOMEM;
 		goto error_disable_reg;
@@ -279,47 +279,42 @@
 	ret = spi_sync(st->spi, &st->msg);
 	if (ret) {
 		dev_err(&spi->dev, "device init failed\n");
-		goto error_free_device;
+		goto error_disable_reg;
 	}
 
 	ret = ad9832_write_frequency(st, AD9832_FREQ0HM, pdata->freq0);
 	if (ret)
-		goto error_free_device;
+		goto error_disable_reg;
 
 	ret = ad9832_write_frequency(st, AD9832_FREQ1HM, pdata->freq1);
 	if (ret)
-		goto error_free_device;
+		goto error_disable_reg;
 
 	ret = ad9832_write_phase(st, AD9832_PHASE0H, pdata->phase0);
 	if (ret)
-		goto error_free_device;
+		goto error_disable_reg;
 
 	ret = ad9832_write_phase(st, AD9832_PHASE1H, pdata->phase1);
 	if (ret)
-		goto error_free_device;
+		goto error_disable_reg;
 
 	ret = ad9832_write_phase(st, AD9832_PHASE2H, pdata->phase2);
 	if (ret)
-		goto error_free_device;
+		goto error_disable_reg;
 
 	ret = ad9832_write_phase(st, AD9832_PHASE3H, pdata->phase3);
 	if (ret)
-		goto error_free_device;
+		goto error_disable_reg;
 
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_free_device;
+		goto error_disable_reg;
 
 	return 0;
 
-error_free_device:
-	iio_device_free(indio_dev);
 error_disable_reg:
 	if (!IS_ERR(reg))
 		regulator_disable(reg);
-error_put_reg:
-	if (!IS_ERR(reg))
-		regulator_put(reg);
 
 	return ret;
 }
@@ -330,11 +325,8 @@
 	struct ad9832_state *st = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	if (!IS_ERR(st->reg)) {
+	if (!IS_ERR(st->reg))
 		regulator_disable(st->reg);
-		regulator_put(st->reg);
-	}
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c
index 5cba3c0..86cda61 100644
--- a/drivers/staging/iio/frequency/ad9834.c
+++ b/drivers/staging/iio/frequency/ad9834.c
@@ -70,9 +70,9 @@
 	struct ad9834_state *st = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	int ret;
-	long val;
+	unsigned long val;
 
-	ret = strict_strtoul(buf, 10, &val);
+	ret = kstrtoul(buf, 10, &val);
 	if (ret)
 		goto error_ret;
 
@@ -327,14 +327,14 @@
 		return -ENODEV;
 	}
 
-	reg = regulator_get(&spi->dev, "vcc");
+	reg = devm_regulator_get(&spi->dev, "vcc");
 	if (!IS_ERR(reg)) {
 		ret = regulator_enable(reg);
 		if (ret)
-			goto error_put_reg;
+			return ret;
 	}
 
-	indio_dev = iio_device_alloc(sizeof(*st));
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (indio_dev == NULL) {
 		ret = -ENOMEM;
 		goto error_disable_reg;
@@ -388,39 +388,35 @@
 	ret = spi_sync(st->spi, &st->msg);
 	if (ret) {
 		dev_err(&spi->dev, "device init failed\n");
-		goto error_free_device;
+		goto error_disable_reg;
 	}
 
 	ret = ad9834_write_frequency(st, AD9834_REG_FREQ0, pdata->freq0);
 	if (ret)
-		goto error_free_device;
+		goto error_disable_reg;
 
 	ret = ad9834_write_frequency(st, AD9834_REG_FREQ1, pdata->freq1);
 	if (ret)
-		goto error_free_device;
+		goto error_disable_reg;
 
 	ret = ad9834_write_phase(st, AD9834_REG_PHASE0, pdata->phase0);
 	if (ret)
-		goto error_free_device;
+		goto error_disable_reg;
 
 	ret = ad9834_write_phase(st, AD9834_REG_PHASE1, pdata->phase1);
 	if (ret)
-		goto error_free_device;
+		goto error_disable_reg;
 
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_free_device;
+		goto error_disable_reg;
 
 	return 0;
 
-error_free_device:
-	iio_device_free(indio_dev);
 error_disable_reg:
 	if (!IS_ERR(reg))
 		regulator_disable(reg);
-error_put_reg:
-	if (!IS_ERR(reg))
-		regulator_put(reg);
+
 	return ret;
 }
 
@@ -430,11 +426,8 @@
 	struct ad9834_state *st = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	if (!IS_ERR(st->reg)) {
+	if (!IS_ERR(st->reg))
 		regulator_disable(st->reg);
-		regulator_put(st->reg);
-	}
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/frequency/ad9850.c b/drivers/staging/iio/frequency/ad9850.c
index 01a8a93..af877ff 100644
--- a/drivers/staging/iio/frequency/ad9850.c
+++ b/drivers/staging/iio/frequency/ad9850.c
@@ -80,11 +80,9 @@
 	struct iio_dev *idev;
 	int ret = 0;
 
-	idev = iio_device_alloc(sizeof(*st));
-	if (idev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	idev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+	if (!idev)
+		return -ENOMEM;
 	spi_set_drvdata(spi, idev);
 	st = iio_priv(idev);
 	mutex_init(&st->lock);
@@ -96,24 +94,18 @@
 
 	ret = iio_device_register(idev);
 	if (ret)
-		goto error_free_dev;
+		return ret;
 	spi->max_speed_hz = 2000000;
 	spi->mode = SPI_MODE_3;
 	spi->bits_per_word = 16;
 	spi_setup(spi);
 
 	return 0;
-
-error_free_dev:
-	iio_device_free(idev);
-error_ret:
-	return ret;
 }
 
 static int ad9850_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
-	iio_device_free(spi_get_drvdata(spi));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/frequency/ad9852.c b/drivers/staging/iio/frequency/ad9852.c
index 1344031..11e4367 100644
--- a/drivers/staging/iio/frequency/ad9852.c
+++ b/drivers/staging/iio/frequency/ad9852.c
@@ -67,7 +67,6 @@
 					const char *buf,
 					size_t len)
 {
-	struct spi_message msg;
 	struct spi_transfer xfer;
 	int ret;
 	struct ad9852_config *config = (struct ad9852_config *)buf;
@@ -78,99 +77,77 @@
 	xfer.tx_buf = &config->phajst0[0];
 	mutex_lock(&st->lock);
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 3;
 	xfer.tx_buf = &config->phajst1[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 6;
 	xfer.tx_buf = &config->fretun1[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 6;
 	xfer.tx_buf = &config->fretun2[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 6;
 	xfer.tx_buf = &config->dltafre[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 5;
 	xfer.tx_buf = &config->updtclk[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 4;
 	xfer.tx_buf = &config->ramprat[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 5;
 	xfer.tx_buf = &config->control[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 3;
 	xfer.tx_buf = &config->outpskm[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 2;
 	xfer.tx_buf = &config->outpskr[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 3;
 	xfer.tx_buf = &config->daccntl[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 error_ret:
@@ -229,11 +206,9 @@
 	struct iio_dev *idev;
 	int ret = 0;
 
-	idev = iio_device_alloc(sizeof(*st));
-	if (idev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	idev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+	if (!idev)
+		return -ENOMEM;
 	st = iio_priv(idev);
 	spi_set_drvdata(spi, idev);
 	mutex_init(&st->lock);
@@ -245,7 +220,7 @@
 
 	ret = iio_device_register(idev);
 	if (ret)
-		goto error_free_dev;
+		return ret;
 	spi->max_speed_hz = 2000000;
 	spi->mode = SPI_MODE_3;
 	spi->bits_per_word = 8;
@@ -253,18 +228,11 @@
 	ad9852_init(st);
 
 	return 0;
-
-error_free_dev:
-	iio_device_free(idev);
-
-error_ret:
-	return ret;
 }
 
 static int ad9852_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
-	iio_device_free(spi_get_drvdata(spi));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/frequency/ad9910.c b/drivers/staging/iio/frequency/ad9910.c
index e48f874..755e048 100644
--- a/drivers/staging/iio/frequency/ad9910.c
+++ b/drivers/staging/iio/frequency/ad9910.c
@@ -119,7 +119,6 @@
 					const char *buf,
 					size_t len)
 {
-	struct spi_message msg;
 	struct spi_transfer xfer;
 	int ret;
 	struct ad9910_config *config = (struct ad9910_config *)buf;
@@ -130,152 +129,118 @@
 	xfer.tx_buf = &config->auxdac[0];
 	mutex_lock(&st->lock);
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 5;
 	xfer.tx_buf = &config->ioupd[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 5;
 	xfer.tx_buf = &config->ftw[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 3;
 	xfer.tx_buf = &config->pow[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 5;
 	xfer.tx_buf = &config->asf[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 5;
 	xfer.tx_buf = &config->multc[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 9;
 	xfer.tx_buf = &config->dig_rampl[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 9;
 	xfer.tx_buf = &config->dig_ramps[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 5;
 	xfer.tx_buf = &config->dig_rampr[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 9;
 	xfer.tx_buf = &config->sin_tonep0[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 9;
 	xfer.tx_buf = &config->sin_tonep1[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 9;
 	xfer.tx_buf = &config->sin_tonep2[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 	xfer.len = 9;
 	xfer.tx_buf = &config->sin_tonep3[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 9;
 	xfer.tx_buf = &config->sin_tonep4[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 9;
 	xfer.tx_buf = &config->sin_tonep5[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 9;
 	xfer.tx_buf = &config->sin_tonep6[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 9;
 	xfer.tx_buf = &config->sin_tonep7[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 error_ret:
@@ -288,7 +253,6 @@
 
 static void ad9910_init(struct ad9910_state *st)
 {
-	struct spi_message msg;
 	struct spi_transfer xfer;
 	int ret;
 	u8 cfr[5];
@@ -304,9 +268,7 @@
 	xfer.len = 5;
 	xfer.tx_buf = &cfr;
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
@@ -319,9 +281,7 @@
 	xfer.len = 5;
 	xfer.tx_buf = &cfr;
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
@@ -334,9 +294,7 @@
 	xfer.len = 5;
 	xfer.tx_buf = &cfr;
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
@@ -367,11 +325,9 @@
 	struct iio_dev *idev;
 	int ret = 0;
 
-	idev = iio_device_alloc(sizeof(*st));
-	if (idev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	idev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+	if (!idev)
+		return -ENOMEM;
 	spi_set_drvdata(spi, idev);
 	st = iio_priv(idev);
 	mutex_init(&st->lock);
@@ -383,24 +339,18 @@
 
 	ret = iio_device_register(idev);
 	if (ret)
-		goto error_free_dev;
+		return ret;
 	spi->max_speed_hz = 2000000;
 	spi->mode = SPI_MODE_3;
 	spi->bits_per_word = 8;
 	spi_setup(spi);
 	ad9910_init(st);
 	return 0;
-
-error_free_dev:
-	iio_device_free(idev);
-error_ret:
-	return ret;
 }
 
 static int ad9910_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
-	iio_device_free(spi_get_drvdata(spi));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/frequency/ad9951.c b/drivers/staging/iio/frequency/ad9951.c
index 8234e3c..5e8990a 100644
--- a/drivers/staging/iio/frequency/ad9951.c
+++ b/drivers/staging/iio/frequency/ad9951.c
@@ -60,7 +60,6 @@
 					const char *buf,
 					size_t len)
 {
-	struct spi_message msg;
 	struct spi_transfer xfer;
 	int ret;
 	struct ad9951_config *config = (struct ad9951_config *)buf;
@@ -71,36 +70,28 @@
 	xfer.tx_buf = &config->asf[0];
 	mutex_lock(&st->lock);
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 2;
 	xfer.tx_buf = &config->arr[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 5;
 	xfer.tx_buf = &config->ftw0[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
 	xfer.len = 3;
 	xfer.tx_buf = &config->ftw1[0];
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 error_ret:
@@ -113,7 +104,6 @@
 
 static void ad9951_init(struct ad9951_state *st)
 {
-	struct spi_message msg;
 	struct spi_transfer xfer;
 	int ret;
 	u8 cfr[5];
@@ -129,9 +119,7 @@
 	xfer.len = 5;
 	xfer.tx_buf = &cfr;
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
@@ -143,9 +131,7 @@
 	xfer.len = 4;
 	xfer.tx_buf = &cfr;
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = spi_sync_transfer(st->sdev, &xfer, 1);
 	if (ret)
 		goto error_ret;
 
@@ -176,11 +162,9 @@
 	struct iio_dev *idev;
 	int ret = 0;
 
-	idev = iio_device_alloc(sizeof(*st));
-	if (idev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	idev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+	if (!idev)
+		return -ENOMEM;
 	spi_set_drvdata(spi, idev);
 	st = iio_priv(idev);
 	mutex_init(&st->lock);
@@ -193,25 +177,18 @@
 
 	ret = iio_device_register(idev);
 	if (ret)
-		goto error_free_dev;
+		return ret;
 	spi->max_speed_hz = 2000000;
 	spi->mode = SPI_MODE_3;
 	spi->bits_per_word = 8;
 	spi_setup(spi);
 	ad9951_init(st);
 	return 0;
-
-error_free_dev:
-	iio_device_free(idev);
-
-error_ret:
-	return ret;
 }
 
 static int ad9951_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
-	iio_device_free(spi_get_drvdata(spi));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c
index 0e8e02a..1fac989 100644
--- a/drivers/staging/iio/iio_simple_dummy.c
+++ b/drivers/staging/iio/iio_simple_dummy.c
@@ -57,6 +57,20 @@
 	{ 733, 13, 0x9 }, /* 733.000013 */
 };
 
+#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS
+
+/*
+ * simple event - triggered when value rises above
+ * a threshold
+ */
+static const struct iio_event_spec iio_dummy_event = {
+	.type = IIO_EV_TYPE_THRESH,
+	.dir = IIO_EV_DIR_RISING,
+	.mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE),
+};
+
+#endif
+
 /*
  * iio_dummy_channels - Description of available channels
  *
@@ -90,6 +104,11 @@
 		 * when converting to standard units (microvolts)
 		 */
 		BIT(IIO_CHAN_INFO_SCALE),
+		/*
+		 * sampling_frequency
+		 * The frequency in Hz at which the channels are sampled
+		 */
+		.info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ),
 		/* The ordering of elements in the buffer via an enum */
 		.scan_index = voltage0,
 		.scan_type = { /* Description of storage in buffer */
@@ -99,12 +118,8 @@
 			.shift = 0, /* zero shift */
 		},
 #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS
-		/*
-		 * simple event - triggered when value rises above
-		 * a threshold
-		 */
-		.event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH,
-					 IIO_EV_DIR_RISING),
+		.event_spec = &iio_dummy_event,
+		.num_event_specs = 1,
 #endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */
 	},
 	/* Differential ADC channel in_voltage1-voltage2_raw etc*/
@@ -130,6 +145,10 @@
 		 * input channels of type IIO_VOLTAGE.
 		 */
 		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+		/*
+		 * sampling_frequency
+		 * The frequency in Hz at which the channels are sampled
+		 */
 		.scan_index = diffvoltage1m2,
 		.scan_type = { /* Description of storage in buffer */
 			.sign = 's', /* signed */
@@ -147,6 +166,7 @@
 		.channel2 = 4,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+		.info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ),
 		.scan_index = diffvoltage3m4,
 		.scan_type = {
 			.sign = 's',
@@ -173,6 +193,7 @@
 		 */
 		BIT(IIO_CHAN_INFO_CALIBSCALE) |
 		BIT(IIO_CHAN_INFO_CALIBBIAS),
+		.info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ),
 		.scan_index = accelx,
 		.scan_type = { /* Description of storage in buffer */
 			.sign = 's', /* signed */
@@ -272,6 +293,11 @@
 		*val2 = st->accel_calibscale->val2;
 		ret = IIO_VAL_INT_PLUS_MICRO;
 		break;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val = 3;
+		*val2 = 33;
+		ret = IIO_VAL_INT_PLUS_NANO;
+		break;
 	default:
 		break;
 	}
@@ -344,10 +370,10 @@
 	.read_raw = &iio_dummy_read_raw,
 	.write_raw = &iio_dummy_write_raw,
 #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS
-	.read_event_config = &iio_simple_dummy_read_event_config,
-	.write_event_config = &iio_simple_dummy_write_event_config,
-	.read_event_value = &iio_simple_dummy_read_event_value,
-	.write_event_value = &iio_simple_dummy_write_event_value,
+	.read_event_config_new = &iio_simple_dummy_read_event_config,
+	.write_event_config_new = &iio_simple_dummy_write_event_config,
+	.read_event_value_new = &iio_simple_dummy_read_event_value,
+	.write_event_value_new = &iio_simple_dummy_write_event_value,
 #endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */
 };
 
@@ -454,7 +480,8 @@
 	 * buffer, but avoid the output channel being registered by reducing the
 	 * number of channels by 1.
 	 */
-	ret = iio_simple_dummy_configure_buffer(indio_dev, iio_dummy_channels, 5);
+	ret = iio_simple_dummy_configure_buffer(indio_dev,
+						iio_dummy_channels, 5);
 	if (ret < 0)
 		goto error_unregister_events;
 
diff --git a/drivers/staging/iio/iio_simple_dummy.h b/drivers/staging/iio/iio_simple_dummy.h
index c9e8702..b126196 100644
--- a/drivers/staging/iio/iio_simple_dummy.h
+++ b/drivers/staging/iio/iio_simple_dummy.h
@@ -45,19 +45,29 @@
 struct iio_dev;
 
 int iio_simple_dummy_read_event_config(struct iio_dev *indio_dev,
-				       u64 event_code);
+				       const struct iio_chan_spec *chan,
+				       enum iio_event_type type,
+				       enum iio_event_direction dir);
 
 int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev,
-					u64 event_code,
+					const struct iio_chan_spec *chan,
+					enum iio_event_type type,
+					enum iio_event_direction dir,
 					int state);
 
 int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev,
-				      u64 event_code,
-				      int *val);
+				      const struct iio_chan_spec *chan,
+				      enum iio_event_type type,
+				      enum iio_event_direction dir,
+				      enum iio_event_info info, int *val,
+				      int *val2);
 
 int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev,
-				       u64 event_code,
-				       int val);
+				       const struct iio_chan_spec *chan,
+				       enum iio_event_type type,
+				       enum iio_event_direction dir,
+				       enum iio_event_info info, int val,
+				       int val2);
 
 int iio_simple_dummy_events_register(struct iio_dev *indio_dev);
 int iio_simple_dummy_events_unregister(struct iio_dev *indio_dev);
diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c
index 72f400c..46c134b 100644
--- a/drivers/staging/iio/iio_simple_dummy_buffer.c
+++ b/drivers/staging/iio/iio_simple_dummy_buffer.c
@@ -82,11 +82,8 @@
 			len += 2;
 		}
 	}
-	/* Store the timestamp at an 8 byte aligned offset */
-	if (indio_dev->scan_timestamp)
-		*(s64 *)((u8 *)data + ALIGN(len, sizeof(s64)))
-			= iio_get_time_ns();
-	iio_push_to_buffers(indio_dev, (u8 *)data);
+
+	iio_push_to_buffers_with_timestamp(indio_dev, data, iio_get_time_ns());
 
 	kfree(data);
 
@@ -102,14 +99,6 @@
 
 static const struct iio_buffer_setup_ops iio_simple_dummy_buffer_setup_ops = {
 	/*
-	 * iio_sw_buffer_preenable:
-	 * Generic function for equal sized ring elements + 64 bit timestamp
-	 * Assumes that any combination of channels can be enabled.
-	 * Typically replaced to implement restrictions on what combinations
-	 * can be captured (hardware scan modes).
-	 */
-	.preenable = &iio_sw_buffer_preenable,
-	/*
 	 * iio_triggered_buffer_postenable:
 	 * Generic function that simply attaches the pollfunc to the trigger.
 	 * Replace this to mess with hardware state before we attach the
@@ -138,7 +127,7 @@
 		goto error_ret;
 	}
 
-	indio_dev->buffer = buffer;
+	iio_device_attach_buffer(indio_dev, buffer);
 
 	/* Enable timestamps by default */
 	buffer->scan_timestamp = true;
diff --git a/drivers/staging/iio/iio_simple_dummy_events.c b/drivers/staging/iio/iio_simple_dummy_events.c
index 317b774..812ebd0 100644
--- a/drivers/staging/iio/iio_simple_dummy_events.c
+++ b/drivers/staging/iio/iio_simple_dummy_events.c
@@ -23,13 +23,17 @@
 /**
  * iio_simple_dummy_read_event_config() - is event enabled?
  * @indio_dev: the device instance data
- * @event_code: event code of the event being queried
+ * @chan: channel for the event whose state is being queried
+ * @type: type of the event whose state is being queried
+ * @dir: direction of the vent whose state is being queried
  *
  * This function would normally query the relevant registers or a cache to
  * discover if the event generation is enabled on the device.
  */
 int iio_simple_dummy_read_event_config(struct iio_dev *indio_dev,
-				       u64 event_code)
+				       const struct iio_chan_spec *chan,
+				       enum iio_event_type type,
+				       enum iio_event_direction dir)
 {
 	struct iio_dummy_state *st = iio_priv(indio_dev);
 
@@ -39,7 +43,9 @@
 /**
  * iio_simple_dummy_write_event_config() - set whether event is enabled
  * @indio_dev: the device instance data
- * @event_code: event code of event being enabled/disabled
+ * @chan: channel for the event whose state is being set
+ * @type: type of the event whose state is being set
+ * @dir: direction of the vent whose state is being set
  * @state: whether to enable or disable the device.
  *
  * This function would normally set the relevant registers on the devices
@@ -47,7 +53,9 @@
  * value.
  */
 int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev,
-					u64 event_code,
+					const struct iio_chan_spec *chan,
+					enum iio_event_type type,
+					enum iio_event_direction dir,
 					int state)
 {
 	struct iio_dummy_state *st = iio_priv(indio_dev);
@@ -56,12 +64,11 @@
 	 *  Deliberately over the top code splitting to illustrate
 	 * how this is done when multiple events exist.
 	 */
-	switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) {
+	switch (chan->type) {
 	case IIO_VOLTAGE:
-		switch (IIO_EVENT_CODE_EXTRACT_TYPE(event_code)) {
+		switch (type) {
 		case IIO_EV_TYPE_THRESH:
-			if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
-			    IIO_EV_DIR_RISING)
+			if (dir == IIO_EV_DIR_RISING)
 				st->event_en = state;
 			else
 				return -EINVAL;
@@ -79,7 +86,10 @@
 /**
  * iio_simple_dummy_read_event_value() - get value associated with event
  * @indio_dev: device instance specific data
- * @event_code: event code for the event whose value is being queried
+ * @chan: channel for the event whose value is being read
+ * @type: type of the event whose value is being read
+ * @dir: direction of the vent whose value is being read
+ * @info: info type of the event whose value is being read
  * @val: value for the event code.
  *
  * Many devices provide a large set of events of which only a subset may
@@ -89,25 +99,34 @@
  * the enabled event is changed.
  */
 int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev,
-				      u64 event_code,
-				      int *val)
+				      const struct iio_chan_spec *chan,
+				      enum iio_event_type type,
+				      enum iio_event_direction dir,
+					  enum iio_event_info info,
+				      int *val, int *val2)
 {
 	struct iio_dummy_state *st = iio_priv(indio_dev);
 
 	*val = st->event_val;
 
-	return 0;
+	return IIO_VAL_INT;
 }
 
 /**
  * iio_simple_dummy_write_event_value() - set value associate with event
  * @indio_dev: device instance specific data
- * @event_code: event code for the event whose value is being set
+ * @chan: channel for the event whose value is being set
+ * @type: type of the event whose value is being set
+ * @dir: direction of the vent whose value is being set
+ * @info: info type of the event whose value is being set
  * @val: the value to be set.
  */
 int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev,
-				       u64 event_code,
-				       int val)
+				       const struct iio_chan_spec *chan,
+				       enum iio_event_type type,
+				       enum iio_event_direction dir,
+					   enum iio_event_info info,
+				       int val, int val2)
 {
 	struct iio_dummy_state *st = iio_priv(indio_dev);
 
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
index 6330af6..0a4298b 100644
--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
@@ -323,10 +323,10 @@
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct ad5933_state *st = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-	long val;
+	unsigned long val;
 	int ret;
 
-	ret = strict_strtoul(buf, 10, &val);
+	ret = kstrtoul(buf, 10, &val);
 	if (ret)
 		return ret;
 
@@ -400,12 +400,12 @@
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct ad5933_state *st = iio_priv(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-	long val;
+	u16 val;
 	int i, ret = 0;
 	unsigned short dat;
 
 	if (this_attr->address != AD5933_IN_PGA_GAIN) {
-		ret = strict_strtol(buf, 10, &val);
+		ret = kstrtou16(buf, 10, &val);
 		if (ret)
 			return ret;
 	}
@@ -434,7 +434,7 @@
 		ret = ad5933_cmd(st, 0);
 		break;
 	case AD5933_OUT_SETTLING_CYCLES:
-		val = clamp(val, 0L, 0x7FFL);
+		val = clamp(val, (u16)0, (u16)0x7FF);
 		st->settling_cycles = val;
 
 		/* 2x, 4x handling, see datasheet */
@@ -448,7 +448,7 @@
 				AD5933_REG_SETTLING_CYCLES, 2, (u8 *)&dat);
 		break;
 	case AD5933_FREQ_POINTS:
-		val = clamp(val, 0L, 511L);
+		val = clamp(val, (u16)0, (u16)511);
 		st->freq_points = val;
 
 		dat = cpu_to_be16(val);
@@ -574,10 +574,6 @@
 	if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
 		return -EINVAL;
 
-	ret = iio_sw_buffer_preenable(indio_dev);
-	if (ret < 0)
-		return ret;
-
 	ret = ad5933_reset(st);
 	if (ret < 0)
 		return ret;
@@ -630,10 +626,14 @@
 
 static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev)
 {
-	indio_dev->buffer = iio_kfifo_allocate(indio_dev);
-	if (!indio_dev->buffer)
+	struct iio_buffer *buffer;
+
+	buffer = iio_kfifo_allocate(indio_dev);
+	if (buffer)
 		return -ENOMEM;
 
+	iio_device_attach_buffer(indio_dev, buffer);
+
 	/* Ring buffer functions - here trigger setup related */
 	indio_dev->setup_ops = &ad5933_ring_setup_ops;
 
@@ -676,7 +676,7 @@
 		} else {
 			buf[0] = be16_to_cpu(buf[0]);
 		}
-		iio_push_to_buffers(indio_dev, (u8 *)buf);
+		iio_push_to_buffers(indio_dev, buf);
 	} else {
 		/* no data available - try again later */
 		schedule_delayed_work(&st->work, st->poll_time_jiffies);
@@ -703,7 +703,9 @@
 	int ret, voltage_uv = 0;
 	struct ad5933_platform_data *pdata = client->dev.platform_data;
 	struct ad5933_state *st;
-	struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
+	struct iio_dev *indio_dev;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
 	if (indio_dev == NULL)
 		return -ENOMEM;
 
@@ -716,11 +718,11 @@
 	else
 		st->pdata = pdata;
 
-	st->reg = regulator_get(&client->dev, "vcc");
+	st->reg = devm_regulator_get(&client->dev, "vcc");
 	if (!IS_ERR(st->reg)) {
 		ret = regulator_enable(st->reg);
 		if (ret)
-			goto error_put_reg;
+			return ret;
 		voltage_uv = regulator_get_voltage(st->reg);
 	}
 
@@ -778,11 +780,6 @@
 error_disable_reg:
 	if (!IS_ERR(st->reg))
 		regulator_disable(st->reg);
-error_put_reg:
-	if (!IS_ERR(st->reg))
-		regulator_put(st->reg);
-
-	iio_device_free(indio_dev);
 
 	return ret;
 }
@@ -795,11 +792,8 @@
 	iio_device_unregister(indio_dev);
 	iio_buffer_unregister(indio_dev);
 	iio_kfifo_free(indio_dev->buffer);
-	if (!IS_ERR(st->reg)) {
+	if (!IS_ERR(st->reg))
 		regulator_disable(st->reg);
-		regulator_put(st->reg);
-	}
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c
index e4998e4..488e690 100644
--- a/drivers/staging/iio/light/isl29018.c
+++ b/drivers/staging/iio/light/isl29018.c
@@ -240,7 +240,7 @@
 	unsigned long lval;
 	unsigned int new_range;
 
-	if (strict_strtoul(buf, 10, &lval))
+	if (kstrtoul(buf, 10, &lval))
 		return -EINVAL;
 
 	if (!(lval == 1000UL || lval == 4000UL ||
@@ -279,18 +279,18 @@
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct isl29018_chip *chip = iio_priv(indio_dev);
 	int status;
-	unsigned long lval;
+	unsigned int val;
 	unsigned int new_adc_bit;
 
-	if (strict_strtoul(buf, 10, &lval))
+	if (kstrtouint(buf, 10, &val))
 		return -EINVAL;
-	if (!(lval == 4 || lval == 8 || lval == 12 || lval == 16)) {
+	if (!(val == 4 || val == 8 || val == 12 || val == 16)) {
 		dev_err(dev, "The resolution is not supported\n");
 		return -EINVAL;
 	}
 
 	mutex_lock(&chip->lock);
-	status = isl29018_set_resolution(chip, lval, &new_adc_bit);
+	status = isl29018_set_resolution(chip, val, &new_adc_bit);
 	if (status < 0) {
 		mutex_unlock(&chip->lock);
 		dev_err(dev, "Error in setting resolution\n");
@@ -319,11 +319,11 @@
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct isl29018_chip *chip = iio_priv(indio_dev);
-	unsigned long lval;
+	int val;
 
-	if (strict_strtoul(buf, 10, &lval))
+	if (kstrtoint(buf, 10, &val))
 		return -EINVAL;
-	if (!(lval == 0UL || lval == 1UL)) {
+	if (!(val == 0 || val == 1)) {
 		dev_err(dev, "The mode is not supported\n");
 		return -EINVAL;
 	}
@@ -331,7 +331,7 @@
 	/* get the  "proximity scheme" i.e. if the chip does on chip
 	infrared suppression (1 means perform on chip suppression) */
 	mutex_lock(&chip->lock);
-	chip->prox_scheme = (int)lval;
+	chip->prox_scheme = val;
 	mutex_unlock(&chip->lock);
 
 	return count;
diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c
index b377dd3..f8c6595 100644
--- a/drivers/staging/iio/light/tsl2583.c
+++ b/drivers/staging/iio/light/tsl2583.c
@@ -493,9 +493,9 @@
 	struct device_attribute *attr, const char *buf, size_t len)
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	unsigned long value;
+	int value;
 
-	if (strict_strtoul(buf, 0, &value))
+	if (kstrtoint(buf, 0, &value))
 		return -EINVAL;
 
 	if (value == 0)
@@ -536,9 +536,9 @@
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct tsl2583_chip *chip = iio_priv(indio_dev);
-	unsigned long value;
+	int value;
 
-	if (strict_strtoul(buf, 0, &value))
+	if (kstrtoint(buf, 0, &value))
 		return -EINVAL;
 
 	switch (value) {
@@ -582,9 +582,9 @@
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct tsl2583_chip *chip = iio_priv(indio_dev);
-	unsigned long value;
+	int value;
 
-	if (strict_strtoul(buf, 0, &value))
+	if (kstrtoint(buf, 0, &value))
 		return -EINVAL;
 
 	if ((value < 50) || (value > 650))
@@ -619,9 +619,9 @@
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct tsl2583_chip *chip = iio_priv(indio_dev);
-	unsigned long value;
+	int value;
 
-	if (strict_strtoul(buf, 0, &value))
+	if (kstrtoint(buf, 0, &value))
 		return -EINVAL;
 
 	if (value)
@@ -644,9 +644,9 @@
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct tsl2583_chip *chip = iio_priv(indio_dev);
-	unsigned long value;
+	int value;
 
-	if (strict_strtoul(buf, 0, &value))
+	if (kstrtoint(buf, 0, &value))
 		return -EINVAL;
 
 	if (value)
@@ -671,9 +671,9 @@
 	struct device_attribute *attr, const char *buf, size_t len)
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	unsigned long value;
+	int value;
 
-	if (strict_strtoul(buf, 0, &value))
+	if (kstrtoint(buf, 0, &value))
 		return -EINVAL;
 
 	if (value == 1)
@@ -815,12 +815,9 @@
 		return -EOPNOTSUPP;
 	}
 
-	indio_dev = iio_device_alloc(sizeof(*chip));
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		dev_err(&clientp->dev, "iio allocation failed\n");
-		goto fail1;
-	}
+	indio_dev = devm_iio_device_alloc(&clientp->dev, sizeof(*chip));
+	if (!indio_dev)
+		return -ENOMEM;
 	chip = iio_priv(indio_dev);
 	chip->client = clientp;
 	i2c_set_clientdata(clientp, indio_dev);
@@ -835,14 +832,14 @@
 		if (ret < 0) {
 			dev_err(&clientp->dev, "i2c_smbus_write_bytes() to cmd "
 				"reg failed in taos_probe(), err = %d\n", ret);
-			goto fail2;
+			return ret;
 		}
 		ret = i2c_smbus_read_byte(clientp);
 		if (ret < 0) {
 			dev_err(&clientp->dev, "i2c_smbus_read_byte from "
 				"reg failed in taos_probe(), err = %d\n", ret);
 
-			goto fail2;
+			return ret;
 		}
 		buf[i] = ret;
 	}
@@ -850,14 +847,14 @@
 	if (!taos_tsl258x_device(buf)) {
 		dev_info(&clientp->dev, "i2c device found but does not match "
 			"expected id in taos_probe()\n");
-		goto fail2;
+		return -EINVAL;
 	}
 
 	ret = i2c_smbus_write_byte(clientp, (TSL258X_CMD_REG | TSL258X_CNTRL));
 	if (ret < 0) {
 		dev_err(&clientp->dev, "i2c_smbus_write_byte() to cmd reg "
 			"failed in taos_probe(), err = %d\n", ret);
-		goto fail2;
+		return ret;
 	}
 
 	indio_dev->info = &tsl2583_info;
@@ -867,7 +864,7 @@
 	ret = iio_device_register(indio_dev);
 	if (ret) {
 		dev_err(&clientp->dev, "iio registration failed\n");
-		goto fail2;
+		return ret;
 	}
 
 	/* Load up the V2 defaults (these are hard coded defaults for now) */
@@ -878,10 +875,6 @@
 
 	dev_info(&clientp->dev, "Light sensor found.\n");
 	return 0;
-fail1:
-	iio_device_free(indio_dev);
-fail2:
-	return ret;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -926,7 +919,6 @@
 static int taos_remove(struct i2c_client *client)
 {
 	iio_device_unregister(i2c_get_clientdata(client));
-	iio_device_free(i2c_get_clientdata(client));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c
index c99f890..1880502 100644
--- a/drivers/staging/iio/light/tsl2x7x_core.c
+++ b/drivers/staging/iio/light/tsl2x7x_core.c
@@ -124,11 +124,6 @@
 #define TSL2X7X_mA13                   0xD0
 #define TSL2X7X_MAX_TIMER_CNT          (0xFF)
 
-/*Common device IIO EventMask */
-#define TSL2X7X_EVENT_MASK \
-		(IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | \
-		IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING)),
-
 #define TSL2X7X_MIN_ITIME 3
 
 /* TAOS txx2x7x Device family members */
@@ -550,7 +545,7 @@
 static void tsl2x7x_defaults(struct tsl2X7X_chip *chip)
 {
 	/* If Operational settings defined elsewhere.. */
-	if (chip->pdata && chip->pdata->platform_default_settings != 0)
+	if (chip->pdata && chip->pdata->platform_default_settings)
 		memcpy(&(chip->tsl2x7x_settings),
 			chip->pdata->platform_default_settings,
 			sizeof(tsl2x7x_default_settings));
@@ -951,7 +946,6 @@
 	case tsl2771:
 	case tmd2771:
 		return snprintf(buf, PAGE_SIZE, "%s\n", "1 8 16 128");
-	break;
 	}
 
 	return snprintf(buf, PAGE_SIZE, "%s\n", "1 8 16 120");
@@ -1223,12 +1217,14 @@
 }
 
 static int tsl2x7x_read_interrupt_config(struct iio_dev *indio_dev,
-					 u64 event_code)
+					 const struct iio_chan_spec *chan,
+					 enum iio_event_type type,
+					 enum iio_event_direction dir)
 {
 	struct tsl2X7X_chip *chip = iio_priv(indio_dev);
 	int ret;
 
-	if (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code) == IIO_INTENSITY)
+	if (chan->type == IIO_INTENSITY)
 		ret = !!(chip->tsl2x7x_settings.interrupts_en & 0x10);
 	else
 		ret = !!(chip->tsl2x7x_settings.interrupts_en & 0x20);
@@ -1237,12 +1233,14 @@
 }
 
 static int tsl2x7x_write_interrupt_config(struct iio_dev *indio_dev,
-					  u64 event_code,
+					  const struct iio_chan_spec *chan,
+					  enum iio_event_type type,
+					  enum iio_event_direction dir,
 					  int val)
 {
 	struct tsl2X7X_chip *chip = iio_priv(indio_dev);
 
-	if (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code) == IIO_INTENSITY) {
+	if (chan->type == IIO_INTENSITY) {
 		if (val)
 			chip->tsl2x7x_settings.interrupts_en |= 0x10;
 		else
@@ -1260,13 +1258,16 @@
 }
 
 static int tsl2x7x_write_thresh(struct iio_dev *indio_dev,
-				  u64 event_code,
-				  int val)
+				const struct iio_chan_spec *chan,
+				enum iio_event_type type,
+				enum iio_event_direction dir,
+				enum iio_event_info info,
+				int val, int val2)
 {
 	struct tsl2X7X_chip *chip = iio_priv(indio_dev);
 
-	if (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code) == IIO_INTENSITY) {
-		switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
+	if (chan->type == IIO_INTENSITY) {
+		switch (dir) {
 		case IIO_EV_DIR_RISING:
 			chip->tsl2x7x_settings.als_thresh_high = val;
 			break;
@@ -1277,7 +1278,7 @@
 			return -EINVAL;
 		}
 	} else {
-		switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
+		switch (dir) {
 		case IIO_EV_DIR_RISING:
 			chip->tsl2x7x_settings.prox_thres_high = val;
 			break;
@@ -1295,13 +1296,16 @@
 }
 
 static int tsl2x7x_read_thresh(struct iio_dev *indio_dev,
-			       u64 event_code,
-			       int *val)
+			       const struct iio_chan_spec *chan,
+			       enum iio_event_type type,
+			       enum iio_event_direction dir,
+				   enum iio_event_info info,
+			       int *val, int *val2)
 {
 	struct tsl2X7X_chip *chip = iio_priv(indio_dev);
 
-	if (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code) == IIO_INTENSITY) {
-		switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
+	if (chan->type == IIO_INTENSITY) {
+		switch (dir) {
 		case IIO_EV_DIR_RISING:
 			*val = chip->tsl2x7x_settings.als_thresh_high;
 			break;
@@ -1312,7 +1316,7 @@
 			return -EINVAL;
 		}
 	} else {
-		switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) {
+		switch (dir) {
 		case IIO_EV_DIR_RISING:
 			*val = chip->tsl2x7x_settings.prox_thres_high;
 			break;
@@ -1324,7 +1328,7 @@
 		}
 	}
 
-	return 0;
+	return IIO_VAL_INT;
 }
 
 static int tsl2x7x_read_raw(struct iio_dev *indio_dev,
@@ -1346,7 +1350,6 @@
 			break;
 		default:
 			return -EINVAL;
-			break;
 		}
 		break;
 	case IIO_CHAN_INFO_RAW:
@@ -1366,7 +1369,6 @@
 			break;
 		default:
 			return -EINVAL;
-			break;
 		}
 		break;
 	case IIO_CHAN_INFO_CALIBSCALE:
@@ -1419,7 +1421,6 @@
 				case tsl2772:
 				case tmd2772:
 					return -EINVAL;
-				break;
 				}
 				chip->tsl2x7x_settings.als_gain = 3;
 				break;
@@ -1431,7 +1432,6 @@
 				case tsl2771:
 				case tmd2771:
 					return -EINVAL;
-				break;
 				}
 				chip->tsl2x7x_settings.als_gain = 3;
 				break;
@@ -1508,18 +1508,15 @@
 	case tsl2671:
 	case tsl2771:
 		return ((*id & 0xf0) == TRITON_ID);
-	break;
 	case tmd2671:
 	case tmd2771:
 		return ((*id & 0xf0) == HALIBUT_ID);
-	break;
 	case tsl2572:
 	case tsl2672:
 	case tmd2672:
 	case tsl2772:
 	case tmd2772:
 		return ((*id & 0xf0) == SWORDFISH_ID);
-	break;
 	}
 
 	return -EINVAL;
@@ -1675,10 +1672,10 @@
 		.driver_module = THIS_MODULE,
 		.read_raw = &tsl2x7x_read_raw,
 		.write_raw = &tsl2x7x_write_raw,
-		.read_event_value = &tsl2x7x_read_thresh,
-		.write_event_value = &tsl2x7x_write_thresh,
-		.read_event_config = &tsl2x7x_read_interrupt_config,
-		.write_event_config = &tsl2x7x_write_interrupt_config,
+		.read_event_value_new = &tsl2x7x_read_thresh,
+		.write_event_value_new = &tsl2x7x_write_thresh,
+		.read_event_config_new = &tsl2x7x_read_interrupt_config,
+		.write_event_config_new = &tsl2x7x_write_interrupt_config,
 	},
 	[PRX] = {
 		.attrs = &tsl2X7X_device_attr_group_tbl[PRX],
@@ -1686,10 +1683,10 @@
 		.driver_module = THIS_MODULE,
 		.read_raw = &tsl2x7x_read_raw,
 		.write_raw = &tsl2x7x_write_raw,
-		.read_event_value = &tsl2x7x_read_thresh,
-		.write_event_value = &tsl2x7x_write_thresh,
-		.read_event_config = &tsl2x7x_read_interrupt_config,
-		.write_event_config = &tsl2x7x_write_interrupt_config,
+		.read_event_value_new = &tsl2x7x_read_thresh,
+		.write_event_value_new = &tsl2x7x_write_thresh,
+		.read_event_config_new = &tsl2x7x_read_interrupt_config,
+		.write_event_config_new = &tsl2x7x_write_interrupt_config,
 	},
 	[ALSPRX] = {
 		.attrs = &tsl2X7X_device_attr_group_tbl[ALSPRX],
@@ -1697,10 +1694,10 @@
 		.driver_module = THIS_MODULE,
 		.read_raw = &tsl2x7x_read_raw,
 		.write_raw = &tsl2x7x_write_raw,
-		.read_event_value = &tsl2x7x_read_thresh,
-		.write_event_value = &tsl2x7x_write_thresh,
-		.read_event_config = &tsl2x7x_read_interrupt_config,
-		.write_event_config = &tsl2x7x_write_interrupt_config,
+		.read_event_value_new = &tsl2x7x_read_thresh,
+		.write_event_value_new = &tsl2x7x_write_thresh,
+		.read_event_config_new = &tsl2x7x_read_interrupt_config,
+		.write_event_config_new = &tsl2x7x_write_interrupt_config,
 	},
 	[PRX2] = {
 		.attrs = &tsl2X7X_device_attr_group_tbl[PRX2],
@@ -1708,10 +1705,10 @@
 		.driver_module = THIS_MODULE,
 		.read_raw = &tsl2x7x_read_raw,
 		.write_raw = &tsl2x7x_write_raw,
-		.read_event_value = &tsl2x7x_read_thresh,
-		.write_event_value = &tsl2x7x_write_thresh,
-		.read_event_config = &tsl2x7x_read_interrupt_config,
-		.write_event_config = &tsl2x7x_write_interrupt_config,
+		.read_event_value_new = &tsl2x7x_read_thresh,
+		.write_event_value_new = &tsl2x7x_write_thresh,
+		.read_event_config_new = &tsl2x7x_read_interrupt_config,
+		.write_event_config_new = &tsl2x7x_write_interrupt_config,
 	},
 	[ALSPRX2] = {
 		.attrs = &tsl2X7X_device_attr_group_tbl[ALSPRX2],
@@ -1719,10 +1716,24 @@
 		.driver_module = THIS_MODULE,
 		.read_raw = &tsl2x7x_read_raw,
 		.write_raw = &tsl2x7x_write_raw,
-		.read_event_value = &tsl2x7x_read_thresh,
-		.write_event_value = &tsl2x7x_write_thresh,
-		.read_event_config = &tsl2x7x_read_interrupt_config,
-		.write_event_config = &tsl2x7x_write_interrupt_config,
+		.read_event_value_new = &tsl2x7x_read_thresh,
+		.write_event_value_new = &tsl2x7x_write_thresh,
+		.read_event_config_new = &tsl2x7x_read_interrupt_config,
+		.write_event_config_new = &tsl2x7x_write_interrupt_config,
+	},
+};
+
+static const struct iio_event_spec tsl2x7x_events[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
+			BIT(IIO_EV_INFO_ENABLE),
 	},
 };
 
@@ -1741,7 +1752,8 @@
 			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 				BIT(IIO_CHAN_INFO_CALIBSCALE) |
 				BIT(IIO_CHAN_INFO_CALIBBIAS),
-			.event_mask = TSL2X7X_EVENT_MASK
+			.event_spec = tsl2x7x_events,
+			.num_event_specs = ARRAY_SIZE(tsl2x7x_events),
 			}, {
 			.type = IIO_INTENSITY,
 			.indexed = 1,
@@ -1758,7 +1770,8 @@
 			.indexed = 1,
 			.channel = 0,
 			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-			.event_mask = TSL2X7X_EVENT_MASK
+			.event_spec = tsl2x7x_events,
+			.num_event_specs = ARRAY_SIZE(tsl2x7x_events),
 			},
 		},
 	.chan_table_elements = 1,
@@ -1778,7 +1791,8 @@
 			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 				BIT(IIO_CHAN_INFO_CALIBSCALE) |
 				BIT(IIO_CHAN_INFO_CALIBBIAS),
-			.event_mask = TSL2X7X_EVENT_MASK
+			.event_spec = tsl2x7x_events,
+			.num_event_specs = ARRAY_SIZE(tsl2x7x_events),
 			}, {
 			.type = IIO_INTENSITY,
 			.indexed = 1,
@@ -1789,7 +1803,8 @@
 			.indexed = 1,
 			.channel = 0,
 			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-			.event_mask = TSL2X7X_EVENT_MASK
+			.event_spec = tsl2x7x_events,
+			.num_event_specs = ARRAY_SIZE(tsl2x7x_events),
 			},
 		},
 	.chan_table_elements = 4,
@@ -1803,7 +1818,8 @@
 			.channel = 0,
 			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 				BIT(IIO_CHAN_INFO_CALIBSCALE),
-			.event_mask = TSL2X7X_EVENT_MASK
+			.event_spec = tsl2x7x_events,
+			.num_event_specs = ARRAY_SIZE(tsl2x7x_events),
 			},
 		},
 	.chan_table_elements = 1,
@@ -1823,7 +1839,8 @@
 			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 				BIT(IIO_CHAN_INFO_CALIBSCALE) |
 				BIT(IIO_CHAN_INFO_CALIBBIAS),
-			.event_mask = TSL2X7X_EVENT_MASK
+			.event_spec = tsl2x7x_events,
+			.num_event_specs = ARRAY_SIZE(tsl2x7x_events),
 			}, {
 			.type = IIO_INTENSITY,
 			.indexed = 1,
@@ -1835,7 +1852,8 @@
 			.channel = 0,
 			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 				BIT(IIO_CHAN_INFO_CALIBSCALE),
-			.event_mask = TSL2X7X_EVENT_MASK
+			.event_spec = tsl2x7x_events,
+			.num_event_specs = ARRAY_SIZE(tsl2x7x_events),
 			},
 		},
 	.chan_table_elements = 4,
@@ -1851,7 +1869,7 @@
 	struct iio_dev *indio_dev;
 	struct tsl2X7X_chip *chip;
 
-	indio_dev = iio_device_alloc(sizeof(*chip));
+	indio_dev = devm_iio_device_alloc(&clientp->dev, sizeof(*chip));
 	if (!indio_dev)
 		return -ENOMEM;
 
@@ -1862,22 +1880,21 @@
 	ret = tsl2x7x_i2c_read(chip->client,
 		TSL2X7X_CHIPID, &device_id);
 	if (ret < 0)
-		goto fail1;
+		return ret;
 
 	if ((!tsl2x7x_device_id(&device_id, id->driver_data)) ||
 		(tsl2x7x_device_id(&device_id, id->driver_data) == -EINVAL)) {
 		dev_info(&chip->client->dev,
 				"%s: i2c device found does not match expected id\n",
 				__func__);
-		ret = -EINVAL;
-		goto fail1;
+		return -EINVAL;
 	}
 
 	ret = i2c_smbus_write_byte(clientp, (TSL2X7X_CMD_REG | TSL2X7X_CNTRL));
 	if (ret < 0) {
 		dev_err(&clientp->dev, "%s: write to cmd reg failed. err = %d\n",
 				__func__, ret);
-		goto fail1;
+		return ret;
 	}
 
 	/* ALS and PROX functions can be invoked via user space poll
@@ -1899,16 +1916,17 @@
 	indio_dev->num_channels = chip->chip_info->chan_table_elements;
 
 	if (clientp->irq) {
-		ret = request_threaded_irq(clientp->irq,
-					   NULL,
-					   &tsl2x7x_event_handler,
-					   IRQF_TRIGGER_RISING | IRQF_ONESHOT,
-					   "TSL2X7X_event",
-					   indio_dev);
+		ret = devm_request_threaded_irq(&clientp->dev, clientp->irq,
+						NULL,
+						&tsl2x7x_event_handler,
+						IRQF_TRIGGER_RISING |
+						IRQF_ONESHOT,
+						"TSL2X7X_event",
+						indio_dev);
 		if (ret) {
 			dev_err(&clientp->dev,
 				"%s: irq request failed", __func__);
-			goto fail1;
+			return ret;
 		}
 	}
 
@@ -1921,20 +1939,12 @@
 	if (ret) {
 		dev_err(&clientp->dev,
 			"%s: iio registration failed\n", __func__);
-		goto fail2;
+		return ret;
 	}
 
 	dev_info(&clientp->dev, "%s Light sensor found.\n", id->name);
 
 	return 0;
-
-fail2:
-	if (clientp->irq)
-		free_irq(clientp->irq, indio_dev);
-fail1:
-	iio_device_free(indio_dev);
-
-	return ret;
 }
 
 static int tsl2x7x_suspend(struct device *dev)
@@ -1980,10 +1990,6 @@
 	tsl2x7x_chip_off(indio_dev);
 
 	iio_device_unregister(indio_dev);
-	if (client->irq)
-		free_irq(client->irq, indio_dev);
-
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c
index c3f3f53..99421f9 100644
--- a/drivers/staging/iio/magnetometer/hmc5843.c
+++ b/drivers/staging/iio/magnetometer/hmc5843.c
@@ -23,23 +23,17 @@
 #include <linux/i2c.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/triggered_buffer.h>
 #include <linux/delay.h>
 
 #define HMC5843_CONFIG_REG_A			0x00
 #define HMC5843_CONFIG_REG_B			0x01
 #define HMC5843_MODE_REG			0x02
-#define HMC5843_DATA_OUT_X_MSB_REG		0x03
-#define HMC5843_DATA_OUT_X_LSB_REG		0x04
-#define HMC5843_DATA_OUT_Y_MSB_REG		0x05
-#define HMC5843_DATA_OUT_Y_LSB_REG		0x06
-#define HMC5843_DATA_OUT_Z_MSB_REG		0x07
-#define HMC5843_DATA_OUT_Z_LSB_REG		0x08
-/* Beware: Y and Z are exchanged on HMC5883 */
-#define HMC5883_DATA_OUT_Z_MSB_REG		0x05
-#define HMC5883_DATA_OUT_Z_LSB_REG		0x06
-#define HMC5883_DATA_OUT_Y_MSB_REG		0x07
-#define HMC5883_DATA_OUT_Y_LSB_REG		0x08
+#define HMC5843_DATA_OUT_MSB_REGS		0x03
 #define HMC5843_STATUS_REG			0x09
+#define HMC5843_ID_REG				0x0a
 
 enum hmc5843_ids {
 	HMC5843_ID,
@@ -54,19 +48,13 @@
  */
 #define HMC5843_RANGE_GAIN_OFFSET		0x05
 #define HMC5843_RANGE_GAIN_DEFAULT		0x01
-#define HMC5843_RANGE_GAIN_MAX			0x07
+#define HMC5843_RANGE_GAINS			8
 
-/*
- * Device status
- */
+/* Device status */
 #define HMC5843_DATA_READY			0x01
 #define HMC5843_DATA_OUTPUT_LOCK		0x02
-/* Does not exist on HMC5883, not used */
-#define HMC5843_VOLTAGE_REGULATOR_ENABLED	0x04
 
-/*
- * Mode register configuration
- */
+/* Mode register configuration */
 #define HMC5843_MODE_CONVERSION_CONTINUOUS	0x00
 #define HMC5843_MODE_CONVERSION_SINGLE		0x01
 #define HMC5843_MODE_IDLE			0x02
@@ -78,80 +66,29 @@
  * HMC5883: Typical data output rate
  */
 #define HMC5843_RATE_OFFSET			0x02
-#define HMC5843_RATE_BITMASK			0x1C
-#define HMC5843_RATE_NOT_USED			0x07
+#define HMC5843_RATE_DEFAULT			0x04
+#define HMC5843_RATES				7
 
-/*
- * Device measurement configuration
- */
+/* Device measurement configuration */
 #define HMC5843_MEAS_CONF_NORMAL		0x00
 #define HMC5843_MEAS_CONF_POSITIVE_BIAS		0x01
 #define HMC5843_MEAS_CONF_NEGATIVE_BIAS		0x02
-#define HMC5843_MEAS_CONF_NOT_USED		0x03
 #define HMC5843_MEAS_CONF_MASK			0x03
 
-/*
- * Scaling factors: 10000000/Gain
- */
-static const int hmc5843_regval_to_nanoscale[] = {
+/* Scaling factors: 10000000/Gain */
+static const int hmc5843_regval_to_nanoscale[HMC5843_RANGE_GAINS] = {
 	6173, 7692, 10309, 12821, 18868, 21739, 25641, 35714
 };
 
-static const int hmc5883_regval_to_nanoscale[] = {
+static const int hmc5883_regval_to_nanoscale[HMC5843_RANGE_GAINS] = {
 	7812, 9766, 13021, 16287, 24096, 27701, 32573, 45662
 };
 
-static const int hmc5883l_regval_to_nanoscale[] = {
+static const int hmc5883l_regval_to_nanoscale[HMC5843_RANGE_GAINS] = {
 	7299, 9174, 12195, 15152, 22727, 25641, 30303, 43478
 };
 
 /*
- * From the HMC5843 datasheet:
- * Value	| Sensor input field range (Ga)	| Gain (counts/milli-Gauss)
- * 0		| (+-)0.7			| 1620
- * 1		| (+-)1.0			| 1300
- * 2		| (+-)1.5			| 970
- * 3		| (+-)2.0			| 780
- * 4		| (+-)3.2			| 530
- * 5		| (+-)3.8			| 460
- * 6		| (+-)4.5			| 390
- * 7		| (+-)6.5			| 280
- *
- * From the HMC5883 datasheet:
- * Value	| Recommended sensor field range (Ga)	| Gain (counts/Gauss)
- * 0		| (+-)0.9				| 1280
- * 1		| (+-)1.2				| 1024
- * 2		| (+-)1.9				| 768
- * 3		| (+-)2.5				| 614
- * 4		| (+-)4.0				| 415
- * 5		| (+-)4.6				| 361
- * 6		| (+-)5.5				| 307
- * 7		| (+-)7.9				| 219
- *
- * From the HMC5883L datasheet:
- * Value	| Recommended sensor field range (Ga)	| Gain (LSB/Gauss)
- * 0		| (+-)0.88				| 1370
- * 1		| (+-)1.3				| 1090
- * 2		| (+-)1.9				| 820
- * 3		| (+-)2.5				| 660
- * 4		| (+-)4.0				| 440
- * 5		| (+-)4.7				| 390
- * 6		| (+-)5.6				| 330
- * 7		| (+-)8.1				| 230
- */
-static const int hmc5843_regval_to_input_field_mga[] = {
-	700, 1000, 1500, 2000, 3200, 3800, 4500, 6500
-};
-
-static const int hmc5883_regval_to_input_field_mga[] = {
-	900, 1200, 1900, 2500, 4000, 4600, 5500, 7900
-};
-
-static const int hmc5883l_regval_to_input_field_mga[] = {
-	880, 1300, 1900, 2500, 4000, 4700, 5600, 8100
-};
-
-/*
  * From the datasheet:
  * Value	| HMC5843		| HMC5883/HMC5883L
  *		| Data output rate (Hz)	| Data output rate (Hz)
@@ -164,143 +101,96 @@
  * 6		| 50			| 75
  * 7		| Not used		| Not used
  */
-static const char * const hmc5843_regval_to_sample_freq[] = {
-	"0.5", "1", "2", "5", "10", "20", "50",
+static const int hmc5843_regval_to_samp_freq[7][2] = {
+	{0, 500000}, {1, 0}, {2, 0}, {5, 0}, {10, 0}, {20, 0}, {50, 0}
 };
 
-static const char * const hmc5883_regval_to_sample_freq[] = {
-	"0.75", "1.5", "3", "7.5", "15", "30", "75",
+static const int hmc5883_regval_to_samp_freq[7][2] = {
+	{0, 750000}, {1, 500000}, {3, 0}, {7, 500000}, {15, 0}, {30, 0},
+	{75, 0}
 };
 
 /* Describe chip variants */
 struct hmc5843_chip_info {
 	const struct iio_chan_spec *channels;
-	const char * const *regval_to_sample_freq;
-	const int *regval_to_input_field_mga;
+	const int (*regval_to_samp_freq)[2];
 	const int *regval_to_nanoscale;
 };
 
 /* Each client has this additional data */
 struct hmc5843_data {
+	struct i2c_client *client;
 	struct mutex lock;
 	u8 rate;
 	u8 meas_conf;
 	u8 operating_mode;
 	u8 range;
 	const struct hmc5843_chip_info *variant;
+	__be16 buffer[8]; /* 3x 16-bit channels + padding + 64-bit timestamp */
 };
 
 /* The lower two bits contain the current conversion mode */
-static s32 hmc5843_configure(struct i2c_client *client,
-				       u8 operating_mode)
+static s32 hmc5843_set_mode(struct hmc5843_data *data, u8 operating_mode)
 {
-	return i2c_smbus_write_byte_data(client,
-					HMC5843_MODE_REG,
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = i2c_smbus_write_byte_data(data->client, HMC5843_MODE_REG,
 					operating_mode & HMC5843_MODE_MASK);
+	if (ret >= 0)
+		data->operating_mode = operating_mode;
+	mutex_unlock(&data->lock);
+
+	return ret;
 }
 
-/* Return the measurement value from the specified channel */
-static int hmc5843_read_measurement(struct iio_dev *indio_dev,
-				    int address,
-				    int *val)
+static int hmc5843_wait_measurement(struct hmc5843_data *data)
 {
-	struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
-	struct hmc5843_data *data = iio_priv(indio_dev);
 	s32 result;
 	int tries = 150;
 
-	mutex_lock(&data->lock);
 	while (tries-- > 0) {
-		result = i2c_smbus_read_byte_data(client,
+		result = i2c_smbus_read_byte_data(data->client,
 			HMC5843_STATUS_REG);
+		if (result < 0)
+			return result;
 		if (result & HMC5843_DATA_READY)
 			break;
 		msleep(20);
 	}
 
 	if (tries < 0) {
-		dev_err(&client->dev, "data not ready\n");
-		mutex_unlock(&data->lock);
+		dev_err(&data->client->dev, "data not ready\n");
 		return -EIO;
 	}
 
-	result = i2c_smbus_read_word_swapped(client, address);
+	return 0;
+}
+
+/* Return the measurement value from the specified channel */
+static int hmc5843_read_measurement(struct hmc5843_data *data,
+				    int idx, int *val)
+{
+	s32 result;
+	__be16 values[3];
+
+	mutex_lock(&data->lock);
+	result = hmc5843_wait_measurement(data);
+	if (result < 0) {
+		mutex_unlock(&data->lock);
+		return result;
+	}
+	result = i2c_smbus_read_i2c_block_data(data->client,
+		HMC5843_DATA_OUT_MSB_REGS, sizeof(values), (u8 *) values);
 	mutex_unlock(&data->lock);
 	if (result < 0)
 		return -EINVAL;
 
-	*val = sign_extend32(result, 15);
+	*val = sign_extend32(be16_to_cpu(values[idx]), 15);
 	return IIO_VAL_INT;
 }
 
 /*
- * From the datasheet:
- * 0 - Continuous-Conversion Mode: In continuous-conversion mode, the
- *     device continuously performs conversions and places the result in
- *     the data register.
- *
- * 1 - Single-Conversion Mode : Device performs a single measurement,
- *     sets RDY high and returns to sleep mode.
- *
- * 2 - Idle Mode : Device is placed in idle mode.
- *
- * 3 - Sleep Mode : Device is placed in sleep mode.
- *
- */
-static ssize_t hmc5843_show_operating_mode(struct device *dev,
-					struct device_attribute *attr,
-					char *buf)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct hmc5843_data *data = iio_priv(indio_dev);
-	return sprintf(buf, "%d\n", data->operating_mode);
-}
-
-static ssize_t hmc5843_set_operating_mode(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf,
-				size_t count)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
-	struct hmc5843_data *data = iio_priv(indio_dev);
-	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-	unsigned long operating_mode = 0;
-	s32 status;
-	int error;
-
-	mutex_lock(&data->lock);
-	error = kstrtoul(buf, 10, &operating_mode);
-	if (error) {
-		count = error;
-		goto exit;
-	}
-	dev_dbg(dev, "set conversion mode to %lu\n", operating_mode);
-	if (operating_mode > HMC5843_MODE_SLEEP) {
-		count = -EINVAL;
-		goto exit;
-	}
-
-	status = i2c_smbus_write_byte_data(client, this_attr->address,
-					operating_mode);
-	if (status) {
-		count = -EINVAL;
-		goto exit;
-	}
-	data->operating_mode = operating_mode;
-
-exit:
-	mutex_unlock(&data->lock);
-	return count;
-}
-
-static IIO_DEVICE_ATTR(operating_mode,
-			S_IWUSR | S_IRUGO,
-			hmc5843_show_operating_mode,
-			hmc5843_set_operating_mode,
-			HMC5843_MODE_REG);
-
-/*
  * API for setting the measurement configuration to
  * Normal, Positive bias and Negative bias
  *
@@ -318,23 +208,26 @@
  *     and BN.
  *
  */
-static s32 hmc5843_set_meas_conf(struct i2c_client *client,
-				      u8 meas_conf)
+static s32 hmc5843_set_meas_conf(struct hmc5843_data *data, u8 meas_conf)
 {
-	struct iio_dev *indio_dev = i2c_get_clientdata(client);
-	struct hmc5843_data *data = iio_priv(indio_dev);
-	u8 reg_val;
-	reg_val = (meas_conf & HMC5843_MEAS_CONF_MASK) |
-		(data->rate << HMC5843_RATE_OFFSET);
-	return i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_A, reg_val);
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_A,
+		(meas_conf & HMC5843_MEAS_CONF_MASK) |
+		(data->rate << HMC5843_RATE_OFFSET));
+	if (ret >= 0)
+		data->meas_conf = meas_conf;
+	mutex_unlock(&data->lock);
+
+	return ret;
 }
 
 static ssize_t hmc5843_show_measurement_configuration(struct device *dev,
 						struct device_attribute *attr,
 						char *buf)
 {
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct hmc5843_data *data = iio_priv(indio_dev);
+	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
 	return sprintf(buf, "%d\n", data->meas_conf);
 }
 
@@ -343,29 +236,19 @@
 						const char *buf,
 						size_t count)
 {
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
-	struct hmc5843_data *data = iio_priv(indio_dev);
+	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
 	unsigned long meas_conf = 0;
-	int error;
+	int ret;
 
-	error = kstrtoul(buf, 10, &meas_conf);
-	if (error)
-		return error;
-	if (meas_conf >= HMC5843_MEAS_CONF_NOT_USED)
+	ret = kstrtoul(buf, 10, &meas_conf);
+	if (ret)
+		return ret;
+	if (meas_conf >= HMC5843_MEAS_CONF_MASK)
 		return -EINVAL;
 
-	mutex_lock(&data->lock);
-	dev_dbg(dev, "set measurement configuration to %lu\n", meas_conf);
-	if (hmc5843_set_meas_conf(client, meas_conf)) {
-		count = -EINVAL;
-		goto exit;
-	}
-	data->meas_conf = meas_conf;
+	ret = hmc5843_set_meas_conf(data, meas_conf);
 
-exit:
-	mutex_unlock(&data->lock);
-	return count;
+	return (ret < 0) ? ret : count;
 }
 
 static IIO_DEVICE_ATTR(meas_conf,
@@ -374,211 +257,221 @@
 			hmc5843_set_measurement_configuration,
 			0);
 
-static ssize_t hmc5843_show_sampling_frequencies_available(struct device *dev,
-						struct device_attribute *attr,
-						char *buf)
+static ssize_t hmc5843_show_samp_freq_avail(struct device *dev,
+				struct device_attribute *attr, char *buf)
 {
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct hmc5843_data *data = iio_priv(indio_dev);
-	ssize_t total_n = 0;
+	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
+	size_t len = 0;
 	int i;
 
-	for (i = 0; i < HMC5843_RATE_NOT_USED; i++) {
-		ssize_t n = sprintf(buf, "%s ", data->variant->regval_to_sample_freq[i]);
-		buf += n;
-		total_n += n;
-	}
+	for (i = 0; i < HMC5843_RATES; i++)
+		len += scnprintf(buf + len, PAGE_SIZE - len,
+			"%d.%d ", data->variant->regval_to_samp_freq[i][0],
+			data->variant->regval_to_samp_freq[i][1]);
+
 	/* replace trailing space by newline */
-	buf[-1] = '\n';
+	buf[len - 1] = '\n';
 
-	return total_n;
+	return len;
 }
 
-static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hmc5843_show_sampling_frequencies_available);
+static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hmc5843_show_samp_freq_avail);
 
-static s32 hmc5843_set_rate(struct i2c_client *client,
-				u8 rate)
+static int hmc5843_set_samp_freq(struct hmc5843_data *data, u8 rate)
 {
-	struct iio_dev *indio_dev = i2c_get_clientdata(client);
-	struct hmc5843_data *data = iio_priv(indio_dev);
-	u8 reg_val;
+	int ret;
 
-	if (rate >= HMC5843_RATE_NOT_USED) {
-		dev_err(&client->dev,
-			"data output rate is not supported\n");
-		return -EINVAL;
-	}
+	mutex_lock(&data->lock);
+	ret = i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_A,
+		data->meas_conf | (rate << HMC5843_RATE_OFFSET));
+	if (ret >= 0)
+		data->rate = rate;
+	mutex_unlock(&data->lock);
 
-	reg_val = data->meas_conf | (rate << HMC5843_RATE_OFFSET);
-	return i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_A, reg_val);
+	return ret;
 }
 
-static int hmc5843_check_sampling_frequency(struct hmc5843_data *data,
-						const char *buf)
+static int hmc5843_get_samp_freq_index(struct hmc5843_data *data,
+				   int val, int val2)
 {
-	const char * const *samp_freq = data->variant->regval_to_sample_freq;
 	int i;
 
-	for (i = 0; i < HMC5843_RATE_NOT_USED; i++) {
-		if (sysfs_streq(buf, samp_freq[i]))
+	for (i = 0; i < HMC5843_RATES; i++)
+		if (val == data->variant->regval_to_samp_freq[i][0] &&
+			val2 == data->variant->regval_to_samp_freq[i][1])
 			return i;
-	}
 
 	return -EINVAL;
 }
 
-static ssize_t hmc5843_set_sampling_frequency(struct device *dev,
-					struct device_attribute *attr,
-					const char *buf, size_t count)
+static int hmc5843_set_range_gain(struct hmc5843_data *data, u8 range)
 {
-
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
-	struct hmc5843_data *data = iio_priv(indio_dev);
-	int rate;
-
-	rate = hmc5843_check_sampling_frequency(data, buf);
-	if (rate < 0) {
-		dev_err(&client->dev,
-			"sampling frequency is not supported\n");
-		return rate;
-	}
+	int ret;
 
 	mutex_lock(&data->lock);
-	dev_dbg(dev, "set rate to %d\n", rate);
-	if (hmc5843_set_rate(client, rate)) {
-		count = -EINVAL;
-		goto exit;
-	}
-	data->rate = rate;
-
-exit:
+	ret = i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_B,
+		range << HMC5843_RANGE_GAIN_OFFSET);
+	if (ret >= 0)
+		data->range = range;
 	mutex_unlock(&data->lock);
-	return count;
+
+	return ret;
 }
 
-static ssize_t hmc5843_show_sampling_frequency(struct device *dev,
-			struct device_attribute *attr, char *buf)
+static ssize_t hmc5843_show_scale_avail(struct device *dev,
+				struct device_attribute *attr, char *buf)
 {
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
-	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-	struct hmc5843_data *data = iio_priv(indio_dev);
-	s32 rate;
+	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
 
-	rate = i2c_smbus_read_byte_data(client, this_attr->address);
-	if (rate < 0)
-		return rate;
-	rate = (rate & HMC5843_RATE_BITMASK) >> HMC5843_RATE_OFFSET;
-	return sprintf(buf, "%s\n", data->variant->regval_to_sample_freq[rate]);
+	size_t len = 0;
+	int i;
+
+	for (i = 0; i < HMC5843_RANGE_GAINS; i++)
+		len += scnprintf(buf + len, PAGE_SIZE - len,
+			"0.%09d ", data->variant->regval_to_nanoscale[i]);
+
+	/* replace trailing space by newline */
+	buf[len - 1] = '\n';
+
+	return len;
 }
 
-static IIO_DEVICE_ATTR(sampling_frequency,
-			S_IWUSR | S_IRUGO,
-			hmc5843_show_sampling_frequency,
-			hmc5843_set_sampling_frequency,
-			HMC5843_CONFIG_REG_A);
+static IIO_DEVICE_ATTR(scale_available, S_IRUGO,
+	hmc5843_show_scale_avail, NULL, 0);
 
-static ssize_t hmc5843_show_range_gain(struct device *dev,
-				struct device_attribute *attr,
-				char *buf)
+static int hmc5843_get_scale_index(struct hmc5843_data *data, int val, int val2)
 {
-	u8 range;
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct hmc5843_data *data = iio_priv(indio_dev);
+	int i;
 
-	range = data->range;
-	return sprintf(buf, "%d\n", data->variant->regval_to_input_field_mga[range]);
+	if (val != 0)
+		return -EINVAL;
+
+	for (i = 0; i < HMC5843_RANGE_GAINS; i++)
+		if (val2 == data->variant->regval_to_nanoscale[i])
+			return i;
+
+	return -EINVAL;
 }
 
-static ssize_t hmc5843_set_range_gain(struct device *dev,
-			struct device_attribute *attr,
-			const char *buf,
-			size_t count)
-{
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct i2c_client *client = to_i2c_client(indio_dev->dev.parent);
-	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-	struct hmc5843_data *data = iio_priv(indio_dev);
-	unsigned long range = 0;
-	int error;
-
-	mutex_lock(&data->lock);
-	error = kstrtoul(buf, 10, &range);
-	if (error) {
-		count = error;
-		goto exit;
-	}
-	dev_dbg(dev, "set range to %lu\n", range);
-
-	if (range > HMC5843_RANGE_GAIN_MAX) {
-		count = -EINVAL;
-		goto exit;
-	}
-
-	data->range = range;
-	range = range << HMC5843_RANGE_GAIN_OFFSET;
-	if (i2c_smbus_write_byte_data(client, this_attr->address, range))
-		count = -EINVAL;
-
-exit:
-	mutex_unlock(&data->lock);
-	return count;
-}
-
-static IIO_DEVICE_ATTR(in_magn_range,
-			S_IWUSR | S_IRUGO,
-			hmc5843_show_range_gain,
-			hmc5843_set_range_gain,
-			HMC5843_CONFIG_REG_B);
-
 static int hmc5843_read_raw(struct iio_dev *indio_dev,
 			    struct iio_chan_spec const *chan,
-			    int *val, int *val2,
-			    long mask)
+			    int *val, int *val2, long mask)
 {
 	struct hmc5843_data *data = iio_priv(indio_dev);
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
-		return hmc5843_read_measurement(indio_dev,
-						chan->address,
-						val);
+		return hmc5843_read_measurement(data, chan->scan_index, val);
 	case IIO_CHAN_INFO_SCALE:
 		*val = 0;
 		*val2 = data->variant->regval_to_nanoscale[data->range];
 		return IIO_VAL_INT_PLUS_NANO;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val = data->variant->regval_to_samp_freq[data->rate][0];
+		*val2 = data->variant->regval_to_samp_freq[data->rate][1];
+		return IIO_VAL_INT_PLUS_MICRO;
 	}
 	return -EINVAL;
 }
 
-#define HMC5843_CHANNEL(axis, addr)					\
+static int hmc5843_write_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int val, int val2, long mask)
+{
+	struct hmc5843_data *data = iio_priv(indio_dev);
+	int rate, range;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		rate = hmc5843_get_samp_freq_index(data, val, val2);
+		if (rate < 0)
+			return -EINVAL;
+
+		return hmc5843_set_samp_freq(data, rate);
+	case IIO_CHAN_INFO_SCALE:
+		range = hmc5843_get_scale_index(data, val, val2);
+		if (range < 0)
+			return -EINVAL;
+
+		return hmc5843_set_range_gain(data, range);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int hmc5843_write_raw_get_fmt(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan, long mask)
+{
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		return IIO_VAL_INT_PLUS_MICRO;
+	case IIO_CHAN_INFO_SCALE:
+		return IIO_VAL_INT_PLUS_NANO;
+	default:
+		return -EINVAL;
+	}
+}
+
+static irqreturn_t hmc5843_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct hmc5843_data *data = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = hmc5843_wait_measurement(data);
+	if (ret < 0) {
+		mutex_unlock(&data->lock);
+		goto done;
+	}
+
+	ret = i2c_smbus_read_i2c_block_data(data->client,
+		HMC5843_DATA_OUT_MSB_REGS, 3 * sizeof(__be16),
+			(u8 *) data->buffer);
+	mutex_unlock(&data->lock);
+	if (ret < 0)
+		goto done;
+
+	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+		iio_get_time_ns());
+
+done:
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+#define HMC5843_CHANNEL(axis, idx)					\
 	{								\
 		.type = IIO_MAGN,					\
 		.modified = 1,						\
 		.channel2 = IIO_MOD_##axis,				\
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
-		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
-		.address = addr						\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |	\
+			BIT(IIO_CHAN_INFO_SAMP_FREQ),			\
+		.scan_index = idx,					\
+		.scan_type = IIO_ST('s', 16, 16, IIO_BE),		\
 	}
 
 static const struct iio_chan_spec hmc5843_channels[] = {
-	HMC5843_CHANNEL(X, HMC5843_DATA_OUT_X_MSB_REG),
-	HMC5843_CHANNEL(Y, HMC5843_DATA_OUT_Y_MSB_REG),
-	HMC5843_CHANNEL(Z, HMC5843_DATA_OUT_Z_MSB_REG),
+	HMC5843_CHANNEL(X, 0),
+	HMC5843_CHANNEL(Y, 1),
+	HMC5843_CHANNEL(Z, 2),
+	IIO_CHAN_SOFT_TIMESTAMP(3),
 };
 
+/* Beware: Y and Z are exchanged on HMC5883 */
 static const struct iio_chan_spec hmc5883_channels[] = {
-	HMC5843_CHANNEL(X, HMC5843_DATA_OUT_X_MSB_REG),
-	HMC5843_CHANNEL(Y, HMC5883_DATA_OUT_Y_MSB_REG),
-	HMC5843_CHANNEL(Z, HMC5883_DATA_OUT_Z_MSB_REG),
+	HMC5843_CHANNEL(X, 0),
+	HMC5843_CHANNEL(Z, 1),
+	HMC5843_CHANNEL(Y, 2),
+	IIO_CHAN_SOFT_TIMESTAMP(3),
 };
 
 static struct attribute *hmc5843_attributes[] = {
 	&iio_dev_attr_meas_conf.dev_attr.attr,
-	&iio_dev_attr_operating_mode.dev_attr.attr,
-	&iio_dev_attr_sampling_frequency.dev_attr.attr,
-	&iio_dev_attr_in_magn_range.dev_attr.attr,
+	&iio_dev_attr_scale_available.dev_attr.attr,
 	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
 	NULL
 };
@@ -590,89 +483,101 @@
 static const struct hmc5843_chip_info hmc5843_chip_info_tbl[] = {
 	[HMC5843_ID] = {
 		.channels = hmc5843_channels,
-		.regval_to_sample_freq = hmc5843_regval_to_sample_freq,
-		.regval_to_input_field_mga =
-			hmc5843_regval_to_input_field_mga,
+		.regval_to_samp_freq = hmc5843_regval_to_samp_freq,
 		.regval_to_nanoscale = hmc5843_regval_to_nanoscale,
 	},
 	[HMC5883_ID] = {
 		.channels = hmc5883_channels,
-		.regval_to_sample_freq = hmc5883_regval_to_sample_freq,
-		.regval_to_input_field_mga =
-			hmc5883_regval_to_input_field_mga,
+		.regval_to_samp_freq = hmc5883_regval_to_samp_freq,
 		.regval_to_nanoscale = hmc5883_regval_to_nanoscale,
 	},
 	[HMC5883L_ID] = {
 		.channels = hmc5883_channels,
-		.regval_to_sample_freq = hmc5883_regval_to_sample_freq,
-		.regval_to_input_field_mga =
-			hmc5883l_regval_to_input_field_mga,
+		.regval_to_samp_freq = hmc5883_regval_to_samp_freq,
 		.regval_to_nanoscale = hmc5883l_regval_to_nanoscale,
 	},
 };
 
-/* Called when we have found a new HMC58X3 */
-static void hmc5843_init_client(struct i2c_client *client,
-				const struct i2c_device_id *id)
+static int hmc5843_init(struct hmc5843_data *data)
 {
-	struct iio_dev *indio_dev = i2c_get_clientdata(client);
-	struct hmc5843_data *data = iio_priv(indio_dev);
+	int ret;
+	u8 id[3];
 
-	data->variant = &hmc5843_chip_info_tbl[id->driver_data];
-	indio_dev->channels = data->variant->channels;
-	indio_dev->num_channels = 3;
-	hmc5843_set_meas_conf(client, data->meas_conf);
-	hmc5843_set_rate(client, data->rate);
-	hmc5843_configure(client, data->operating_mode);
-	i2c_smbus_write_byte_data(client, HMC5843_CONFIG_REG_B, data->range);
-	mutex_init(&data->lock);
+	ret = i2c_smbus_read_i2c_block_data(data->client, HMC5843_ID_REG,
+		sizeof(id), id);
+	if (ret < 0)
+		return ret;
+	if (id[0] != 'H' || id[1] != '4' || id[2] != '3') {
+		dev_err(&data->client->dev, "no HMC5843/5883/5883L sensor\n");
+		return -ENODEV;
+	}
 
-	pr_info("%s initialized\n", id->name);
+	ret = hmc5843_set_meas_conf(data, HMC5843_MEAS_CONF_NORMAL);
+	if (ret < 0)
+		return ret;
+	ret = hmc5843_set_samp_freq(data, HMC5843_RATE_DEFAULT);
+	if (ret < 0)
+		return ret;
+	ret = hmc5843_set_range_gain(data, HMC5843_RANGE_GAIN_DEFAULT);
+	if (ret < 0)
+		return ret;
+	return hmc5843_set_mode(data, HMC5843_MODE_CONVERSION_CONTINUOUS);
 }
 
 static const struct iio_info hmc5843_info = {
 	.attrs = &hmc5843_group,
 	.read_raw = &hmc5843_read_raw,
+	.write_raw = &hmc5843_write_raw,
+	.write_raw_get_fmt = &hmc5843_write_raw_get_fmt,
 	.driver_module = THIS_MODULE,
 };
 
+static const unsigned long hmc5843_scan_masks[] = {0x7, 0};
+
 static int hmc5843_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct hmc5843_data *data;
 	struct iio_dev *indio_dev;
-	int err = 0;
+	int ret;
 
-	indio_dev = iio_device_alloc(sizeof(*data));
-	if (indio_dev == NULL) {
-		err = -ENOMEM;
-		goto exit;
-	}
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (indio_dev == NULL)
+		return -ENOMEM;
 
 	/* default settings at probe */
 	data = iio_priv(indio_dev);
-	data->meas_conf = HMC5843_MEAS_CONF_NORMAL;
-	data->range = HMC5843_RANGE_GAIN_DEFAULT;
-	data->operating_mode = HMC5843_MODE_CONVERSION_CONTINUOUS;
+	data->client = client;
+	data->variant = &hmc5843_chip_info_tbl[id->driver_data];
+	mutex_init(&data->lock);
 
 	i2c_set_clientdata(client, indio_dev);
-	hmc5843_init_client(client, id);
-
 	indio_dev->info = &hmc5843_info;
 	indio_dev->name = id->name;
 	indio_dev->dev.parent = &client->dev;
 	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = data->variant->channels;
+	indio_dev->num_channels = 4;
+	indio_dev->available_scan_masks = hmc5843_scan_masks;
 
-	err = iio_device_register(indio_dev);
-	if (err)
-		goto exit_free2;
+	ret = hmc5843_init(data);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+		hmc5843_trigger_handler, NULL);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0)
+		goto buffer_cleanup;
 
 	return 0;
 
-exit_free2:
-	iio_device_free(indio_dev);
-exit:
-	return err;
+buffer_cleanup:
+	iio_triggered_buffer_cleanup(indio_dev);
+	return ret;
 }
 
 static int hmc5843_remove(struct i2c_client *client)
@@ -680,9 +585,10 @@
 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 
 	iio_device_unregister(indio_dev);
-	 /*  sleep mode to save power */
-	hmc5843_configure(client, HMC5843_MODE_SLEEP);
-	iio_device_free(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+
+	/*  sleep mode to save power */
+	hmc5843_set_mode(iio_priv(indio_dev), HMC5843_MODE_SLEEP);
 
 	return 0;
 }
@@ -690,19 +596,18 @@
 #ifdef CONFIG_PM_SLEEP
 static int hmc5843_suspend(struct device *dev)
 {
-	hmc5843_configure(to_i2c_client(dev), HMC5843_MODE_SLEEP);
-	return 0;
+	struct hmc5843_data *data = iio_priv(i2c_get_clientdata(
+		to_i2c_client(dev)));
+
+	return hmc5843_set_mode(data, HMC5843_MODE_SLEEP);
 }
 
 static int hmc5843_resume(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct iio_dev *indio_dev = i2c_get_clientdata(client);
-	struct hmc5843_data *data = iio_priv(indio_dev);
+	struct hmc5843_data *data = iio_priv(i2c_get_clientdata(
+		to_i2c_client(dev)));
 
-	hmc5843_configure(client, data->operating_mode);
-
-	return 0;
+	return hmc5843_set_mode(data, HMC5843_MODE_CONVERSION_CONTINUOUS);
 }
 
 static SIMPLE_DEV_PM_OPS(hmc5843_pm_ops, hmc5843_suspend, hmc5843_resume);
@@ -730,6 +635,6 @@
 };
 module_i2c_driver(hmc5843_driver);
 
-MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti@ti.com");
+MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti@ti.com>");
 MODULE_DESCRIPTION("HMC5843/5883/5883L driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c
index 74025fb..00492ca 100644
--- a/drivers/staging/iio/meter/ade7753.c
+++ b/drivers/staging/iio/meter/ade7753.c
@@ -86,7 +86,7 @@
 	struct ade7753_state *st = iio_priv(indio_dev);
 	ssize_t ret;
 
-	ret = spi_w8r16(st->us, ADE7753_READ_REG(reg_address));
+	ret = spi_w8r16be(st->us, ADE7753_READ_REG(reg_address));
 	if (ret < 0) {
 		dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
 			reg_address);
@@ -94,7 +94,6 @@
 	}
 
 	*val = ret;
-	*val = be16_to_cpup(val);
 
 	return 0;
 }
@@ -186,9 +185,9 @@
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	int ret;
-	long val;
+	u8 val;
 
-	ret = strict_strtol(buf, 10, &val);
+	ret = kstrtou8(buf, 10, &val);
 	if (ret)
 		goto error_ret;
 	ret = ade7753_spi_write_reg_8(dev, this_attr->address, val);
@@ -204,9 +203,9 @@
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	int ret;
-	long val;
+	u16 val;
 
-	ret = strict_strtol(buf, 10, &val);
+	ret = kstrtou16(buf, 10, &val);
 	if (ret)
 		goto error_ret;
 	ret = ade7753_spi_write_reg_16(dev, this_attr->address, val);
@@ -399,11 +398,11 @@
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct ade7753_state *st = iio_priv(indio_dev);
-	unsigned long val;
+	u16 val;
 	int ret;
 	u16 reg, t;
 
-	ret = strict_strtol(buf, 10, &val);
+	ret = kstrtou16(buf, 10, &val);
 	if (ret)
 		return ret;
 	if (val == 0)
@@ -497,11 +496,9 @@
 	struct iio_dev *indio_dev;
 
 	/* setup the industrialio driver allocated elements */
-	indio_dev = iio_device_alloc(sizeof(*st));
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+	if (!indio_dev)
+		return -ENOMEM;
 	/* this is only used for removal purposes */
 	spi_set_drvdata(spi, indio_dev);
 
@@ -517,19 +514,13 @@
 	/* Get the device into a sane initial state */
 	ret = ade7753_initial_setup(indio_dev);
 	if (ret)
-		goto error_free_dev;
+		return ret;
 
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_free_dev;
+		return ret;
 
 	return 0;
-
-error_free_dev:
-	iio_device_free(indio_dev);
-
-error_ret:
-	return ret;
 }
 
 /* fixme, confirm ordering in this function */
@@ -539,7 +530,6 @@
 
 	iio_device_unregister(indio_dev);
 	ade7753_stop_device(&indio_dev->dev);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c
index f649ebe..e0aa13a 100644
--- a/drivers/staging/iio/meter/ade7754.c
+++ b/drivers/staging/iio/meter/ade7754.c
@@ -86,7 +86,7 @@
 	struct ade7754_state *st = iio_priv(indio_dev);
 	int ret;
 
-	ret = spi_w8r16(st->us, ADE7754_READ_REG(reg_address));
+	ret = spi_w8r16be(st->us, ADE7754_READ_REG(reg_address));
 	if (ret < 0) {
 		dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
 			reg_address);
@@ -94,7 +94,6 @@
 	}
 
 	*val = ret;
-	*val = be16_to_cpup(val);
 
 	return 0;
 }
@@ -186,9 +185,9 @@
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	int ret;
-	long val;
+	u8 val;
 
-	ret = strict_strtol(buf, 10, &val);
+	ret = kstrtou8(buf, 10, &val);
 	if (ret)
 		goto error_ret;
 	ret = ade7754_spi_write_reg_8(dev, this_attr->address, val);
@@ -204,9 +203,9 @@
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	int ret;
-	long val;
+	u16 val;
 
-	ret = strict_strtol(buf, 10, &val);
+	ret = kstrtou16(buf, 10, &val);
 	if (ret)
 		goto error_ret;
 	ret = ade7754_spi_write_reg_16(dev, this_attr->address, val);
@@ -419,11 +418,11 @@
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct ade7754_state *st = iio_priv(indio_dev);
-	unsigned long val;
+	u16 val;
 	int ret;
 	u8 reg, t;
 
-	ret = strict_strtol(buf, 10, &val);
+	ret = kstrtou16(buf, 10, &val);
 	if (ret)
 		return ret;
 	if (val == 0)
@@ -520,11 +519,9 @@
 	struct iio_dev *indio_dev;
 
 	/* setup the industrialio driver allocated elements */
-	indio_dev = iio_device_alloc(sizeof(*st));
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+	if (!indio_dev)
+		return -ENOMEM;
 	/* this is only used for removal purposes */
 	spi_set_drvdata(spi, indio_dev);
 
@@ -540,18 +537,12 @@
 	/* Get the device into a sane initial state */
 	ret = ade7754_initial_setup(indio_dev);
 	if (ret)
-		goto error_free_dev;
+		return ret;
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_free_dev;
+		return ret;
 
 	return 0;
-
-error_free_dev:
-	iio_device_free(indio_dev);
-
-error_ret:
-	return ret;
 }
 
 /* fixme, confirm ordering in this function */
@@ -561,7 +552,6 @@
 
 	iio_device_unregister(indio_dev);
 	ade7754_stop_device(&indio_dev->dev);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c
index 6005d4a..cba183e 100644
--- a/drivers/staging/iio/meter/ade7758_core.c
+++ b/drivers/staging/iio/meter/ade7758_core.c
@@ -269,9 +269,9 @@
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	int ret;
-	long val;
+	u8 val;
 
-	ret = strict_strtol(buf, 10, &val);
+	ret = kstrtou8(buf, 10, &val);
 	if (ret)
 		goto error_ret;
 	ret = ade7758_spi_write_reg_8(dev, this_attr->address, val);
@@ -287,9 +287,9 @@
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	int ret;
-	long val;
+	u16 val;
 
-	ret = strict_strtol(buf, 10, &val);
+	ret = kstrtou16(buf, 10, &val);
 	if (ret)
 		goto error_ret;
 	ret = ade7758_spi_write_reg_16(dev, this_attr->address, val);
@@ -502,11 +502,11 @@
 		size_t len)
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	unsigned long val;
+	u16 val;
 	int ret;
 	u8 reg, t;
 
-	ret = strict_strtol(buf, 10, &val);
+	ret = kstrtou16(buf, 10, &val);
 	if (ret)
 		return ret;
 
@@ -849,12 +849,11 @@
 {
 	int ret;
 	struct ade7758_state *st;
-	struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
+	struct iio_dev *indio_dev;
 
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+	if (!indio_dev)
+		return -ENOMEM;
 
 	st = iio_priv(indio_dev);
 	/* this is only used for removal purposes */
@@ -862,10 +861,8 @@
 
 	/* Allocate the comms buffers */
 	st->rx = kcalloc(ADE7758_MAX_RX, sizeof(*st->rx), GFP_KERNEL);
-	if (st->rx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_dev;
-	}
+	if (!st->rx)
+		return -ENOMEM;
 	st->tx = kcalloc(ADE7758_MAX_TX, sizeof(*st->tx), GFP_KERNEL);
 	if (st->tx == NULL) {
 		ret = -ENOMEM;
@@ -920,9 +917,6 @@
 	kfree(st->tx);
 error_free_rx:
 	kfree(st->rx);
-error_free_dev:
-	iio_device_free(indio_dev);
-error_ret:
 	return ret;
 }
 
@@ -939,8 +933,6 @@
 	kfree(st->tx);
 	kfree(st->rx);
 
-	iio_device_free(indio_dev);
-
 	return 0;
 }
 
diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c
index 7d5db71..c0accf8 100644
--- a/drivers/staging/iio/meter/ade7758_ring.c
+++ b/drivers/staging/iio/meter/ade7758_ring.c
@@ -69,11 +69,7 @@
 		if (ade7758_spi_read_burst(indio_dev) >= 0)
 			*dat32 = get_unaligned_be32(&st->rx_buf[5]) & 0xFFFFFF;
 
-	/* Guaranteed to be aligned with 8 byte boundary */
-	if (indio_dev->scan_timestamp)
-		dat64[1] = pf->timestamp;
-
-	iio_push_to_buffers(indio_dev, (u8 *)dat64);
+	iio_push_to_buffers_with_timestamp(indio_dev, dat64, pf->timestamp);
 
 	iio_trigger_notify_done(indio_dev->trig);
 
@@ -91,15 +87,10 @@
 {
 	struct ade7758_state *st = iio_priv(indio_dev);
 	unsigned channel;
-	int ret;
 
 	if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
 		return -EINVAL;
 
-	ret = iio_sw_buffer_preenable(indio_dev);
-	if (ret < 0)
-		return ret;
-
 	channel = find_first_bit(indio_dev->active_scan_mask,
 				 indio_dev->masklength);
 
@@ -125,14 +116,17 @@
 int ade7758_configure_ring(struct iio_dev *indio_dev)
 {
 	struct ade7758_state *st = iio_priv(indio_dev);
+	struct iio_buffer *buffer;
 	int ret = 0;
 
-	indio_dev->buffer = iio_kfifo_allocate(indio_dev);
-	if (!indio_dev->buffer) {
+	buffer = iio_kfifo_allocate(indio_dev);
+	if (!buffer) {
 		ret = -ENOMEM;
 		return ret;
 	}
 
+	iio_device_attach_buffer(indio_dev, buffer);
+
 	indio_dev->setup_ops = &ade7758_ring_setup_ops;
 
 	indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c
index d214ac4..ea0c9de 100644
--- a/drivers/staging/iio/meter/ade7759.c
+++ b/drivers/staging/iio/meter/ade7759.c
@@ -86,7 +86,7 @@
 	struct ade7759_state *st = iio_priv(indio_dev);
 	int ret;
 
-	ret = spi_w8r16(st->us, ADE7759_READ_REG(reg_address));
+	ret = spi_w8r16be(st->us, ADE7759_READ_REG(reg_address));
 	if (ret < 0) {
 		dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
 			reg_address);
@@ -94,7 +94,6 @@
 	}
 
 	*val = ret;
-	*val = be16_to_cpup(val);
 
 	return 0;
 }
@@ -185,9 +184,9 @@
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	int ret;
-	long val;
+	u8 val;
 
-	ret = strict_strtol(buf, 10, &val);
+	ret = kstrtou8(buf, 10, &val);
 	if (ret)
 		goto error_ret;
 	ret = ade7759_spi_write_reg_8(dev, this_attr->address, val);
@@ -203,9 +202,9 @@
 {
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	int ret;
-	long val;
+	u16 val;
 
-	ret = strict_strtol(buf, 10, &val);
+	ret = kstrtou16(buf, 10, &val);
 	if (ret)
 		goto error_ret;
 	ret = ade7759_spi_write_reg_16(dev, this_attr->address, val);
@@ -360,11 +359,11 @@
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct ade7759_state *st = iio_priv(indio_dev);
-	unsigned long val;
+	u16 val;
 	int ret;
 	u16 reg, t;
 
-	ret = strict_strtol(buf, 10, &val);
+	ret = kstrtou16(buf, 10, &val);
 	if (ret)
 		return ret;
 	if (val == 0)
@@ -444,11 +443,9 @@
 	struct iio_dev *indio_dev;
 
 	/* setup the industrialio driver allocated elements */
-	indio_dev = iio_device_alloc(sizeof(*st));
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+	if (!indio_dev)
+		return -ENOMEM;
 	/* this is only used for removal purposes */
 	spi_set_drvdata(spi, indio_dev);
 
@@ -463,18 +460,13 @@
 	/* Get the device into a sane initial state */
 	ret = ade7759_initial_setup(indio_dev);
 	if (ret)
-		goto error_free_dev;
+		return ret;
 
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_free_dev;
+		return ret;
 
 	return 0;
-
-error_free_dev:
-	iio_device_free(indio_dev);
-error_ret:
-	return ret;
 }
 
 /* fixme, confirm ordering in this function */
@@ -484,7 +476,6 @@
 
 	iio_device_unregister(indio_dev);
 	ade7759_stop_device(&indio_dev->dev);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/meter/ade7854-i2c.c b/drivers/staging/iio/meter/ade7854-i2c.c
index db9ef6c..5b33c7f 100644
--- a/drivers/staging/iio/meter/ade7854-i2c.c
+++ b/drivers/staging/iio/meter/ade7854-i2c.c
@@ -208,7 +208,7 @@
 	struct ade7854_state *st;
 	struct iio_dev *indio_dev;
 
-	indio_dev = iio_device_alloc(sizeof(*st));
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
 	if (indio_dev == NULL)
 		return -ENOMEM;
 	st = iio_priv(indio_dev);
@@ -225,8 +225,6 @@
 	st->irq = client->irq;
 
 	ret = ade7854_probe(indio_dev, &client->dev);
-	if (ret)
-		iio_device_free(indio_dev);
 
 	return ret;
 }
diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c
index 4c6d204..94f73bb 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -278,7 +278,7 @@
 	struct ade7854_state *st;
 	struct iio_dev *indio_dev;
 
-	indio_dev = iio_device_alloc(sizeof(*st));
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
 	if (indio_dev == NULL)
 		return -ENOMEM;
 	st = iio_priv(indio_dev);
@@ -296,8 +296,6 @@
 
 
 	ret = ade7854_probe(indio_dev, &spi->dev);
-	if (ret)
-		iio_device_free(indio_dev);
 
 	return ret;
 }
diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c
index e8379c0..d620bbd 100644
--- a/drivers/staging/iio/meter/ade7854.c
+++ b/drivers/staging/iio/meter/ade7854.c
@@ -100,9 +100,9 @@
 	struct ade7854_state *st = iio_priv(indio_dev);
 
 	int ret;
-	long val;
+	u8 val;
 
-	ret = strict_strtol(buf, 10, &val);
+	ret = kstrtou8(buf, 10, &val);
 	if (ret)
 		goto error_ret;
 	ret = st->write_reg_8(dev, this_attr->address, val);
@@ -121,9 +121,9 @@
 	struct ade7854_state *st = iio_priv(indio_dev);
 
 	int ret;
-	long val;
+	u16 val;
 
-	ret = strict_strtol(buf, 10, &val);
+	ret = kstrtou16(buf, 10, &val);
 	if (ret)
 		goto error_ret;
 	ret = st->write_reg_16(dev, this_attr->address, val);
@@ -142,9 +142,9 @@
 	struct ade7854_state *st = iio_priv(indio_dev);
 
 	int ret;
-	long val;
+	u32 val;
 
-	ret = strict_strtol(buf, 10, &val);
+	ret = kstrtou32(buf, 10, &val);
 	if (ret)
 		goto error_ret;
 	ret = st->write_reg_24(dev, this_attr->address, val);
@@ -163,9 +163,9 @@
 	struct ade7854_state *st = iio_priv(indio_dev);
 
 	int ret;
-	long val;
+	u32 val;
 
-	ret = strict_strtol(buf, 10, &val);
+	ret = kstrtou32(buf, 10, &val);
 	if (ret)
 		goto error_ret;
 	ret = st->write_reg_32(dev, this_attr->address, val);
@@ -550,7 +550,7 @@
 
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_free_dev;
+		return ret;
 
 	/* Get the device into a sane initial state */
 	ret = ade7854_initial_setup(indio_dev);
@@ -561,9 +561,6 @@
 
 error_unreg_dev:
 	iio_device_unregister(indio_dev);
-error_free_dev:
-	iio_device_free(indio_dev);
-
 	return ret;
 }
 EXPORT_SYMBOL(ade7854_probe);
@@ -571,7 +568,6 @@
 int ade7854_remove(struct iio_dev *indio_dev)
 {
 	iio_device_unregister(indio_dev);
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/resolver/ad2s1200.c b/drivers/staging/iio/resolver/ad2s1200.c
index 7122116..62d3017 100644
--- a/drivers/staging/iio/resolver/ad2s1200.c
+++ b/drivers/staging/iio/resolver/ad2s1200.c
@@ -107,16 +107,16 @@
 	unsigned short *pins = spi->dev.platform_data;
 
 	for (pn = 0; pn < AD2S1200_PN; pn++)
-		if (gpio_request_one(pins[pn], GPIOF_DIR_OUT, DRV_NAME)) {
-			pr_err("%s: request gpio pin %d failed\n",
-						DRV_NAME, pins[pn]);
-			goto error_ret;
+		ret = devm_gpio_request_one(&spi->dev, pins[pn], GPIOF_DIR_OUT,
+					    DRV_NAME);
+		if (ret) {
+			dev_err(&spi->dev, "request gpio pin %d failed\n",
+							pins[pn]);
+			return ret;
 		}
-	indio_dev = iio_device_alloc(sizeof(*st));
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+	if (!indio_dev)
+		return -ENOMEM;
 	spi_set_drvdata(spi, indio_dev);
 	st = iio_priv(indio_dev);
 	mutex_init(&st->lock);
@@ -133,26 +133,18 @@
 
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_free_dev;
+		return ret;
 
 	spi->max_speed_hz = AD2S1200_HZ;
 	spi->mode = SPI_MODE_3;
 	spi_setup(spi);
 
 	return 0;
-
-error_free_dev:
-	iio_device_free(indio_dev);
-error_ret:
-	for (--pn; pn >= 0; pn--)
-		gpio_free(pins[pn]);
-	return ret;
 }
 
 static int ad2s1200_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
-	iio_device_free(spi_get_drvdata(spi));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c
index dcdadbb..6966d5f 100644
--- a/drivers/staging/iio/resolver/ad2s1210.c
+++ b/drivers/staging/iio/resolver/ad2s1210.c
@@ -206,10 +206,10 @@
 				     size_t len)
 {
 	struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
-	unsigned long fclkin;
+	unsigned int fclkin;
 	int ret;
 
-	ret = strict_strtoul(buf, 10, &fclkin);
+	ret = kstrtouint(buf, 10, &fclkin);
 	if (ret)
 		return ret;
 	if (fclkin < AD2S1210_MIN_CLKIN || fclkin > AD2S1210_MAX_CLKIN) {
@@ -243,10 +243,10 @@
 				     const char *buf, size_t len)
 {
 	struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
-	unsigned long fexcit;
+	unsigned int fexcit;
 	int ret;
 
-	ret = strict_strtoul(buf, 10, &fexcit);
+	ret = kstrtouint(buf, 10, &fexcit);
 	if (ret < 0)
 		return ret;
 	if (fexcit < AD2S1210_MIN_EXCIT || fexcit > AD2S1210_MAX_EXCIT) {
@@ -282,11 +282,11 @@
 			const char *buf, size_t len)
 {
 	struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
-	unsigned long udata;
+	unsigned char udata;
 	unsigned char data;
 	int ret;
 
-	ret = strict_strtoul(buf, 16, &udata);
+	ret = kstrtou8(buf, 16, &udata);
 	if (ret)
 		return -EINVAL;
 
@@ -337,10 +337,10 @@
 {
 	struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
 	unsigned char data;
-	unsigned long udata;
+	unsigned char udata;
 	int ret;
 
-	ret = strict_strtoul(buf, 10, &udata);
+	ret = kstrtou8(buf, 10, &udata);
 	if (ret || udata < 10 || udata > 16) {
 		pr_err("ad2s1210: resolution out of range\n");
 		return -EINVAL;
@@ -438,11 +438,11 @@
 		struct device_attribute *attr, const char *buf, size_t len)
 {
 	struct ad2s1210_state *st = iio_priv(dev_to_iio_dev(dev));
-	unsigned long data;
+	unsigned char data;
 	int ret;
 	struct iio_dev_attr *iattr = to_iio_dev_attr(attr);
 
-	ret = strict_strtoul(buf, 10, &data);
+	ret = kstrtou8(buf, 10, &data);
 	if (ret)
 		return -EINVAL;
 	mutex_lock(&st->lock);
@@ -669,16 +669,14 @@
 	if (spi->dev.platform_data == NULL)
 		return -EINVAL;
 
-	indio_dev = iio_device_alloc(sizeof(*st));
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+	if (!indio_dev)
+		return -ENOMEM;
 	st = iio_priv(indio_dev);
 	st->pdata = spi->dev.platform_data;
 	ret = ad2s1210_setup_gpios(st);
 	if (ret < 0)
-		goto error_free_dev;
+		return ret;
 
 	spi_set_drvdata(spi, indio_dev);
 
@@ -709,9 +707,6 @@
 
 error_free_gpios:
 	ad2s1210_free_gpios(st);
-error_free_dev:
-	iio_device_free(indio_dev);
-error_ret:
 	return ret;
 }
 
@@ -721,7 +716,6 @@
 
 	iio_device_unregister(indio_dev);
 	ad2s1210_free_gpios(iio_priv(indio_dev));
-	iio_device_free(indio_dev);
 
 	return 0;
 }
diff --git a/drivers/staging/iio/resolver/ad2s90.c b/drivers/staging/iio/resolver/ad2s90.c
index 40b8252..e24c589 100644
--- a/drivers/staging/iio/resolver/ad2s90.c
+++ b/drivers/staging/iio/resolver/ad2s90.c
@@ -64,11 +64,9 @@
 	struct ad2s90_state *st;
 	int ret = 0;
 
-	indio_dev = iio_device_alloc(sizeof(*st));
-	if (indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+	if (!indio_dev)
+		return -ENOMEM;
 	st = iio_priv(indio_dev);
 	spi_set_drvdata(spi, indio_dev);
 
@@ -83,7 +81,7 @@
 
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		goto error_free_dev;
+		return ret;
 
 	/* need 600ns between CS and the first falling edge of SCLK */
 	spi->max_speed_hz = 830000;
@@ -91,17 +89,11 @@
 	spi_setup(spi);
 
 	return 0;
-
-error_free_dev:
-	iio_device_free(indio_dev);
-error_ret:
-	return ret;
 }
 
 static int ad2s90_remove(struct spi_device *spi)
 {
 	iio_device_unregister(spi_get_drvdata(spi));
-	iio_device_free(spi_get_drvdata(spi));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
index 38a158b..26e1ca0 100644
--- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
+++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
@@ -83,32 +83,28 @@
 {
 	struct iio_trigger *trig = to_iio_trigger(dev);
 	struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig);
-	unsigned long val;
+	unsigned int val;
 	bool enabled;
 	int ret;
 
-	ret = strict_strtoul(buf, 10, &val);
+	ret = kstrtouint(buf, 10, &val);
 	if (ret)
-		goto error_ret;
+		return ret;
 
-	if (val > 100000) {
-		ret = -EINVAL;
-		goto error_ret;
-	}
+	if (val > 100000)
+		return -EINVAL;
 
 	enabled = get_enabled_gptimers() & st->t->bit;
 
 	if (enabled)
 		disable_gptimers(st->t->bit);
 
-	if (!val)
-		goto error_ret;
+	if (val == 0)
+		return count;
 
 	val = get_sclk() / val;
-	if (val <= 4 || val <= st->duty) {
-		ret = -EINVAL;
-		goto error_ret;
-	}
+	if (val <= 4 || val <= st->duty)
+		return -EINVAL;
 
 	set_gptimer_period(st->t->id, val);
 	set_gptimer_pwidth(st->t->id, val - st->duty);
@@ -116,8 +112,7 @@
 	if (enabled)
 		enable_gptimers(st->t->bit);
 
-error_ret:
-	return ret ? ret : count;
+	return count;
 }
 
 static ssize_t iio_bfin_tmr_frequency_show(struct device *dev,
diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
index 7969597..48a6afa 100644
--- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
+++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
@@ -53,10 +53,10 @@
 {
 	struct iio_trigger *trig = to_iio_trigger(dev);
 	struct iio_prtc_trigger_info *trig_info = iio_trigger_get_drvdata(trig);
-	unsigned long val;
+	int val;
 	int ret;
 
-	ret = strict_strtoul(buf, 10, &val);
+	ret = kstrtoint(buf, 10, &val);
 	if (ret)
 		goto error_ret;
 
diff --git a/drivers/staging/imx-drm/Makefile b/drivers/staging/imx-drm/Makefile
index bfaf693..2c3a9e1 100644
--- a/drivers/staging/imx-drm/Makefile
+++ b/drivers/staging/imx-drm/Makefile
@@ -8,4 +8,4 @@
 obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o
 obj-$(CONFIG_DRM_IMX_FB_HELPER) += imx-fbdev.o
 obj-$(CONFIG_DRM_IMX_IPUV3_CORE) += ipu-v3/
-obj-$(CONFIG_DRM_IMX_IPUV3)	+= ipuv3-crtc.o
+obj-$(CONFIG_DRM_IMX_IPUV3)	+= ipuv3-crtc.o ipuv3-plane.o
diff --git a/drivers/staging/imx-drm/TODO b/drivers/staging/imx-drm/TODO
index 9cfa2a7..6a9da94 100644
--- a/drivers/staging/imx-drm/TODO
+++ b/drivers/staging/imx-drm/TODO
@@ -9,7 +9,6 @@
 
 Missing features (not necessarily for moving out of staging):
 
-- Add KMS plane support for CRTC driver
 - Add i.MX6 HDMI support
 - Add support for IC (Image converter)
 - Add support for CSI (CMOS Sensor interface)
diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
index a2e52a0..4483d47 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -68,6 +68,11 @@
 	struct module				*owner;
 };
 
+int imx_drm_crtc_id(struct imx_drm_crtc *crtc)
+{
+	return crtc->pipe;
+}
+
 static void imx_drm_driver_lastclose(struct drm_device *drm)
 {
 	struct imx_drm_device *imxdrm = drm->dev_private;
@@ -110,18 +115,12 @@
 	struct imx_drm_crtc *imx_crtc;
 	struct imx_drm_crtc_helper_funcs *helper;
 
-	mutex_lock(&imxdrm->mutex);
-
 	list_for_each_entry(imx_crtc, &imxdrm->crtc_list, list)
 		if (imx_crtc->crtc == crtc)
 			goto found;
 
-	mutex_unlock(&imxdrm->mutex);
-
 	return -EINVAL;
 found:
-	mutex_unlock(&imxdrm->mutex);
-
 	helper = &imx_crtc->imx_drm_helper_funcs;
 	if (helper->set_interface_pix_fmt)
 		return helper->set_interface_pix_fmt(crtc,
@@ -191,6 +190,18 @@
 	imx_drm_crtc->imx_drm_helper_funcs.disable_vblank(imx_drm_crtc->crtc);
 }
 
+static void imx_drm_driver_preclose(struct drm_device *drm,
+		struct drm_file *file)
+{
+	int i;
+
+	if (!file->is_master)
+		return;
+
+	for (i = 0; i < 4; i++)
+		imx_drm_disable_vblank(drm , i);
+}
+
 static const struct file_operations imx_drm_driver_fops = {
 	.owner = THIS_MODULE,
 	.open = drm_open,
@@ -647,20 +658,14 @@
 	struct imx_drm_crtc *imx_crtc;
 	int i = 0;
 
-	mutex_lock(&imxdrm->mutex);
-
 	list_for_each_entry(imx_crtc, &imxdrm->crtc_list, list) {
 		if (imx_crtc->crtc == crtc)
 			goto found;
 		i++;
 	}
 
-	mutex_unlock(&imxdrm->mutex);
-
 	return -EINVAL;
 found:
-	mutex_unlock(&imxdrm->mutex);
-
 	return i;
 }
 EXPORT_SYMBOL_GPL(imx_drm_encoder_get_mux_id);
@@ -774,16 +779,26 @@
 };
 
 static struct drm_driver imx_drm_driver = {
-	.driver_features	= DRIVER_MODESET | DRIVER_GEM,
+	.driver_features	= DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
 	.load			= imx_drm_driver_load,
 	.unload			= imx_drm_driver_unload,
 	.lastclose		= imx_drm_driver_lastclose,
+	.preclose		= imx_drm_driver_preclose,
 	.gem_free_object	= drm_gem_cma_free_object,
 	.gem_vm_ops		= &drm_gem_cma_vm_ops,
 	.dumb_create		= drm_gem_cma_dumb_create,
 	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
 	.dumb_destroy		= drm_gem_dumb_destroy,
 
+	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
+	.gem_prime_import	= drm_gem_prime_import,
+	.gem_prime_export	= drm_gem_prime_export,
+	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table,
+	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
+	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
+	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
 	.get_vblank_counter	= drm_vblank_count,
 	.enable_vblank		= imx_drm_enable_vblank,
 	.disable_vblank		= imx_drm_disable_vblank,
@@ -837,8 +852,8 @@
 	INIT_LIST_HEAD(&imx_drm_device->encoder_list);
 
 	imx_drm_pdev = platform_device_register_simple("imx-drm", -1, NULL, 0);
-	if (!imx_drm_pdev) {
-		ret = -EINVAL;
+	if (IS_ERR(imx_drm_pdev)) {
+		ret = PTR_ERR(imx_drm_pdev);
 		goto err_pdev;
 	}
 
diff --git a/drivers/staging/imx-drm/imx-drm.h b/drivers/staging/imx-drm/imx-drm.h
index f2aac91..ae90c9c 100644
--- a/drivers/staging/imx-drm/imx-drm.h
+++ b/drivers/staging/imx-drm/imx-drm.h
@@ -14,6 +14,8 @@
 struct drm_framebuffer;
 struct platform_device;
 
+int imx_drm_crtc_id(struct imx_drm_crtc *crtc);
+
 struct imx_drm_crtc_helper_funcs {
 	int (*enable_vblank)(struct drm_crtc *crtc);
 	void (*disable_vblank)(struct drm_crtc *crtc);
diff --git a/drivers/staging/imx-drm/imx-ldb.c b/drivers/staging/imx-drm/imx-ldb.c
index af733ea..654bf03 100644
--- a/drivers/staging/imx-drm/imx-ldb.c
+++ b/drivers/staging/imx-drm/imx-ldb.c
@@ -359,10 +359,8 @@
 
 	sprintf(clkname, "di%d_pll", chno);
 	ldb->clk_pll[chno] = devm_clk_get(ldb->dev, clkname);
-	if (IS_ERR(ldb->clk_pll[chno]))
-		return PTR_ERR(ldb->clk_pll[chno]);
 
-	return 0;
+	return PTR_ERR_OR_ZERO(ldb->clk_pll[chno]);
 }
 
 static int imx_ldb_register(struct imx_ldb_channel *imx_ldb_ch)
@@ -421,7 +419,7 @@
 	[LVDS_BIT_MAP_JEIDA] = "jeida",
 };
 
-const int of_get_data_mapping(struct device_node *np)
+static const int of_get_data_mapping(struct device_node *np)
 {
 	const char *bm;
 	int ret, i;
@@ -466,8 +464,7 @@
 {
 	struct device_node *np = pdev->dev.of_node;
 	const struct of_device_id *of_id =
-			of_match_device(of_match_ptr(imx_ldb_dt_ids),
-					&pdev->dev);
+			of_match_device(imx_ldb_dt_ids, &pdev->dev);
 	struct device_node *child;
 	const u8 *edidp;
 	struct imx_ldb *imx_ldb;
diff --git a/drivers/staging/imx-drm/imx-tve.c b/drivers/staging/imx-drm/imx-tve.c
index 33d6525..680f4c8 100644
--- a/drivers/staging/imx-drm/imx-tve.c
+++ b/drivers/staging/imx-drm/imx-tve.c
@@ -151,7 +151,7 @@
 
 	spin_lock_irqsave(&tve->enable_lock, flags);
 	if (!tve->enabled) {
-		tve->enabled = 1;
+		tve->enabled = true;
 		clk_prepare_enable(tve->clk);
 		ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG,
 					 TVE_IPU_CLK_EN | TVE_EN,
@@ -180,7 +180,7 @@
 
 	spin_lock_irqsave(&tve->enable_lock, flags);
 	if (tve->enabled) {
-		tve->enabled = 0;
+		tve->enabled = false;
 		ret = regmap_update_bits(tve->regmap, TVE_COM_CONF_REG,
 					 TVE_IPU_CLK_EN | TVE_EN, 0);
 		clk_disable_unprepare(tve->clk);
@@ -696,7 +696,7 @@
 	if (val != 0x00100000) {
 		dev_err(&pdev->dev, "configuration register default value indicates this is not a TVEv2\n");
 		return -ENODEV;
-	};
+	}
 
 	/* disable cable detection for VGA mode */
 	ret = regmap_write(tve->regmap, TVE_CD_CONT_REG, 0);
diff --git a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
index 74c022e..4826b5c 100644
--- a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
+++ b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
@@ -97,6 +97,7 @@
 
 int ipu_idmac_enable_channel(struct ipuv3_channel *channel);
 int ipu_idmac_disable_channel(struct ipuv3_channel *channel);
+int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms);
 
 void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
 		bool doublebuffer);
@@ -283,7 +284,7 @@
 		int width);
 
 int ipu_cpmem_set_format_rgb(struct ipu_ch_param __iomem *,
-		struct ipu_rgb *rgb);
+		const struct ipu_rgb *rgb);
 
 static inline void ipu_cpmem_interlaced_scan(struct ipu_ch_param *p,
 		int stride)
@@ -303,6 +304,7 @@
 int ipu_cpmem_set_image(struct ipu_ch_param __iomem *cpmem,
 		struct ipu_image *image);
 
+enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc);
 enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat);
 
 static inline void ipu_cpmem_set_burstsize(struct ipu_ch_param __iomem *p,
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
index ba464e5..7a22ce6 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
@@ -30,6 +30,8 @@
 #include <linux/irqdomain.h>
 #include <linux/of_device.h>
 
+#include <drm/drm_fourcc.h>
+
 #include "imx-ipu-v3.h"
 #include "ipu-prv.h"
 
@@ -139,7 +141,7 @@
 EXPORT_SYMBOL_GPL(ipu_ch_param_read_field);
 
 int ipu_cpmem_set_format_rgb(struct ipu_ch_param __iomem *p,
-		struct ipu_rgb *rgb)
+		const struct ipu_rgb *rgb)
 {
 	int bpp = 0, npb = 0, ro, go, bo, to;
 
@@ -282,7 +284,7 @@
 }
 EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar);
 
-static struct ipu_rgb def_rgb_32 = {
+static const struct ipu_rgb def_rgb_32 = {
 	.red	= { .offset = 16, .length = 8, },
 	.green	= { .offset =  8, .length = 8, },
 	.blue	= { .offset =  0, .length = 8, },
@@ -290,15 +292,23 @@
 	.bits_per_pixel = 32,
 };
 
-static struct ipu_rgb def_bgr_32 = {
-	.red	= { .offset = 16, .length = 8, },
+static const struct ipu_rgb def_bgr_32 = {
+	.red	= { .offset =  0, .length = 8, },
 	.green	= { .offset =  8, .length = 8, },
-	.blue	= { .offset =  0, .length = 8, },
+	.blue	= { .offset = 16, .length = 8, },
 	.transp = { .offset = 24, .length = 8, },
 	.bits_per_pixel = 32,
 };
 
-static struct ipu_rgb def_rgb_24 = {
+static const struct ipu_rgb def_rgb_24 = {
+	.red	= { .offset = 16, .length = 8, },
+	.green	= { .offset =  8, .length = 8, },
+	.blue	= { .offset =  0, .length = 8, },
+	.transp = { .offset =  0, .length = 0, },
+	.bits_per_pixel = 24,
+};
+
+static const struct ipu_rgb def_bgr_24 = {
 	.red	= { .offset =  0, .length = 8, },
 	.green	= { .offset =  8, .length = 8, },
 	.blue	= { .offset = 16, .length = 8, },
@@ -306,15 +316,7 @@
 	.bits_per_pixel = 24,
 };
 
-static struct ipu_rgb def_bgr_24 = {
-	.red	= { .offset = 16, .length = 8, },
-	.green	= { .offset =  8, .length = 8, },
-	.blue	= { .offset =  0, .length = 8, },
-	.transp = { .offset =  0, .length = 0, },
-	.bits_per_pixel = 24,
-};
-
-static struct ipu_rgb def_rgb_16 = {
+static const struct ipu_rgb def_rgb_16 = {
 	.red	= { .offset = 11, .length = 5, },
 	.green	= { .offset =  5, .length = 6, },
 	.blue	= { .offset =  0, .length = 5, },
@@ -322,6 +324,14 @@
 	.bits_per_pixel = 16,
 };
 
+static const struct ipu_rgb def_bgr_16 = {
+	.red	= { .offset =  0, .length = 5, },
+	.green	= { .offset =  5, .length = 6, },
+	.blue	= { .offset = 11, .length = 5, },
+	.transp = { .offset =  0, .length = 0, },
+	.bits_per_pixel = 16,
+};
+
 #define Y_OFFSET(pix, x, y)	((x) + pix->width * (y))
 #define U_OFFSET(pix, x, y)	((pix->width * pix->height) + \
 					(pix->width * (y) / 4) + (x) / 2)
@@ -329,17 +339,17 @@
 					(pix->width * pix->height / 4) + \
 					(pix->width * (y) / 4) + (x) / 2)
 
-int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat)
+int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 drm_fourcc)
 {
-	switch (pixelformat) {
-	case V4L2_PIX_FMT_YUV420:
-	case V4L2_PIX_FMT_YVU420:
+	switch (drm_fourcc) {
+	case DRM_FORMAT_YUV420:
+	case DRM_FORMAT_YVU420:
 		/* pix format */
 		ipu_ch_param_write_field(cpmem, IPU_FIELD_PFS, 2);
 		/* burst size */
 		ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 63);
 		break;
-	case V4L2_PIX_FMT_UYVY:
+	case DRM_FORMAT_UYVY:
 		/* bits/pixel */
 		ipu_ch_param_write_field(cpmem, IPU_FIELD_BPP, 3);
 		/* pix format */
@@ -347,7 +357,7 @@
 		/* burst size */
 		ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 31);
 		break;
-	case V4L2_PIX_FMT_YUYV:
+	case DRM_FORMAT_YUYV:
 		/* bits/pixel */
 		ipu_ch_param_write_field(cpmem, IPU_FIELD_BPP, 3);
 		/* pix format */
@@ -355,20 +365,25 @@
 		/* burst size */
 		ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 31);
 		break;
-	case V4L2_PIX_FMT_RGB32:
-		ipu_cpmem_set_format_rgb(cpmem, &def_rgb_32);
-		break;
-	case V4L2_PIX_FMT_RGB565:
-		ipu_cpmem_set_format_rgb(cpmem, &def_rgb_16);
-		break;
-	case V4L2_PIX_FMT_BGR32:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_XBGR8888:
 		ipu_cpmem_set_format_rgb(cpmem, &def_bgr_32);
 		break;
-	case V4L2_PIX_FMT_RGB24:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_XRGB8888:
+		ipu_cpmem_set_format_rgb(cpmem, &def_rgb_32);
+		break;
+	case DRM_FORMAT_BGR888:
+		ipu_cpmem_set_format_rgb(cpmem, &def_bgr_24);
+		break;
+	case DRM_FORMAT_RGB888:
 		ipu_cpmem_set_format_rgb(cpmem, &def_rgb_24);
 		break;
-	case V4L2_PIX_FMT_BGR24:
-		ipu_cpmem_set_format_rgb(cpmem, &def_bgr_24);
+	case DRM_FORMAT_RGB565:
+		ipu_cpmem_set_format_rgb(cpmem, &def_rgb_16);
+		break;
+	case DRM_FORMAT_BGR565:
+		ipu_cpmem_set_format_rgb(cpmem, &def_bgr_16);
 		break;
 	default:
 		return -EINVAL;
@@ -378,6 +393,79 @@
 }
 EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt);
 
+/*
+ * The V4L2 spec defines packed RGB formats in memory byte order, which from
+ * point of view of the IPU corresponds to little-endian words with the first
+ * component in the least significant bits.
+ * The DRM pixel formats and IPU internal representation are ordered the other
+ * way around, with the first named component ordered at the most significant
+ * bits. Further, V4L2 formats are not well defined:
+ *     http://linuxtv.org/downloads/v4l-dvb-apis/packed-rgb.html
+ * We choose the interpretation which matches GStreamer behavior.
+ */
+static int v4l2_pix_fmt_to_drm_fourcc(u32 pixelformat)
+{
+	switch (pixelformat) {
+	case V4L2_PIX_FMT_RGB565:
+		/*
+		 * Here we choose the 'corrected' interpretation of RGBP, a
+		 * little-endian 16-bit word with the red component at the most
+		 * significant bits:
+		 * g[2:0]b[4:0] r[4:0]g[5:3] <=> [16:0] R:G:B
+		 */
+		return DRM_FORMAT_RGB565;
+	case V4L2_PIX_FMT_BGR24:
+		/* B G R <=> [24:0] R:G:B */
+		return DRM_FORMAT_RGB888;
+	case V4L2_PIX_FMT_RGB24:
+		/* R G B <=> [24:0] B:G:R */
+		return DRM_FORMAT_BGR888;
+	case V4L2_PIX_FMT_BGR32:
+		/* B G R A <=> [32:0] A:B:G:R */
+		return DRM_FORMAT_XRGB8888;
+	case V4L2_PIX_FMT_RGB32:
+		/* R G B A <=> [32:0] A:B:G:R */
+		return DRM_FORMAT_XBGR8888;
+	case V4L2_PIX_FMT_UYVY:
+		return DRM_FORMAT_UYVY;
+	case V4L2_PIX_FMT_YUYV:
+		return DRM_FORMAT_YUYV;
+	case V4L2_PIX_FMT_YUV420:
+		return DRM_FORMAT_YUV420;
+	case V4L2_PIX_FMT_YVU420:
+		return DRM_FORMAT_YVU420;
+	}
+
+	return -EINVAL;
+}
+
+enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc)
+{
+	switch (drm_fourcc) {
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_BGR565:
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_BGR888:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_RGBX8888:
+	case DRM_FORMAT_BGRX8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_RGBA8888:
+	case DRM_FORMAT_BGRA8888:
+		return IPUV3_COLORSPACE_RGB;
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_YUV420:
+	case DRM_FORMAT_YVU420:
+		return IPUV3_COLORSPACE_YUV;
+	default:
+		return IPUV3_COLORSPACE_UNKNOWN;
+	}
+}
+EXPORT_SYMBOL_GPL(ipu_drm_fourcc_to_colorspace);
+
 int ipu_cpmem_set_image(struct ipu_ch_param __iomem *cpmem,
 		struct ipu_image *image)
 {
@@ -392,7 +480,7 @@
 			image->rect.height);
 	ipu_cpmem_set_stride(cpmem, pix->bytesperline);
 
-	ipu_cpmem_set_fmt(cpmem, pix->pixelformat);
+	ipu_cpmem_set_fmt(cpmem, v4l2_pix_fmt_to_drm_fourcc(pix->pixelformat));
 
 	switch (pix->pixelformat) {
 	case V4L2_PIX_FMT_YUV420:
@@ -476,7 +564,7 @@
 		goto out;
 	}
 
-	channel->busy = 1;
+	channel->busy = true;
 	channel->num = num;
 
 out:
@@ -494,7 +582,7 @@
 
 	mutex_lock(&ipu->channel_lock);
 
-	channel->busy = 0;
+	channel->busy = false;
 
 	mutex_unlock(&ipu->channel_lock);
 }
@@ -610,23 +698,28 @@
 }
 EXPORT_SYMBOL_GPL(ipu_idmac_enable_channel);
 
+int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms)
+{
+	struct ipu_soc *ipu = channel->ipu;
+	unsigned long timeout;
+
+	timeout = jiffies + msecs_to_jiffies(ms);
+	while (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(channel->num)) &
+			idma_mask(channel->num)) {
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+		cpu_relax();
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy);
+
 int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
 {
 	struct ipu_soc *ipu = channel->ipu;
 	u32 val;
 	unsigned long flags;
-	unsigned long timeout;
-
-	timeout = jiffies + msecs_to_jiffies(50);
-	while (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(channel->num)) &
-			idma_mask(channel->num)) {
-		if (time_after(jiffies, timeout)) {
-			dev_warn(ipu->dev, "disabling busy idmac channel %d\n",
-					channel->num);
-			break;
-		}
-		cpu_relax();
-	}
 
 	spin_lock_irqsave(&ipu->lock, flags);
 
@@ -888,7 +981,7 @@
 			.dc = 5,
 			.dp = IPU_DP_FLOW_SYNC_BG,
 			.dma[0] = IPUV3_CHANNEL_MEM_BG_SYNC,
-			.dma[1] = -EINVAL,
+			.dma[1] = IPUV3_CHANNEL_MEM_FG_SYNC,
 		},
 		.name = "imx-ipuv3-crtc",
 	}, {
@@ -913,7 +1006,7 @@
 	pdev = platform_device_register_data(dev, reg->name, ipu_client_id++,
 			&reg->pdata, sizeof(struct ipu_platform_reg));
 
-	return pdev ? 0 : -EINVAL;
+	return PTR_ERR_OR_ZERO(pdev);
 }
 
 static int ipu_add_client_devices(struct ipu_soc *ipu)
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dc.c b/drivers/staging/imx-drm/ipu-v3/ipu-dc.c
index 21bf1c8..d0e3bc3 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-dc.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-dc.c
@@ -91,6 +91,7 @@
 	IPU_DC_MAP_RGB565,
 	IPU_DC_MAP_GBR24, /* TVEv2 */
 	IPU_DC_MAP_BGR666,
+	IPU_DC_MAP_BGR24,
 };
 
 struct ipu_dc {
@@ -152,6 +153,8 @@
 		return IPU_DC_MAP_GBR24;
 	case V4L2_PIX_FMT_BGR666:
 		return IPU_DC_MAP_BGR666;
+	case V4L2_PIX_FMT_BGR24:
+		return IPU_DC_MAP_BGR24;
 	default:
 		return -EINVAL;
 	}
@@ -313,7 +316,7 @@
 		return ERR_PTR(-EBUSY);
 	}
 
-	dc->in_use = 1;
+	dc->in_use = true;
 
 	mutex_unlock(&priv->mutex);
 
@@ -326,7 +329,7 @@
 	struct ipu_dc_priv *priv = dc->priv;
 
 	mutex_lock(&priv->mutex);
-	dc->in_use = 0;
+	dc->in_use = false;
 	mutex_unlock(&priv->mutex);
 }
 EXPORT_SYMBOL_GPL(ipu_dc_put);
@@ -395,6 +398,12 @@
 	ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 1, 11, 0xfc); /* green */
 	ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 2, 17, 0xfc); /* red */
 
+	/* bgr24 */
+	ipu_dc_map_clear(priv, IPU_DC_MAP_BGR24);
+	ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 2, 7, 0xff); /* red */
+	ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 1, 15, 0xff); /* green */
+	ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 0, 23, 0xff); /* blue */
+
 	return 0;
 }
 
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c b/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
index 2e97c33..98070dd 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
@@ -307,13 +307,13 @@
 		goto out;
 	}
 
-	/* Always allocate at least 128*4 bytes (2 slots) */
-	if (slots < 2)
-		slots = 2;
-
 	/* For the MEM_BG channel, first try to allocate twice the slots */
 	if (dmfc->data->ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC)
 		segment = dmfc_find_slots(priv, slots * 2);
+	else if (slots < 2)
+		/* Always allocate at least 128*4 bytes (2 slots) */
+		slots = 2;
+
 	if (segment >= 0)
 		slots *= 2;
 	else
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dp.c b/drivers/staging/imx-drm/ipu-v3/ipu-dp.c
index 231afd6..58f87c8 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-dp.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-dp.c
@@ -325,7 +325,7 @@
 	mutex_init(&priv->mutex);
 
 	for (i = 0; i < IPUV3_NUM_FLOWS; i++) {
-		priv->flow[i].foreground.foreground = 1;
+		priv->flow[i].foreground.foreground = true;
 		priv->flow[i].base = priv->base + ipu_dp_flow_base[i];
 		priv->flow[i].priv = priv;
 	}
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
index 6fd37a7..670a56a 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -25,29 +25,25 @@
 #include <drm/drm_crtc_helper.h>
 #include <linux/fb.h>
 #include <linux/clk.h>
+#include <linux/errno.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
 
 #include "ipu-v3/imx-ipu-v3.h"
 #include "imx-drm.h"
+#include "ipuv3-plane.h"
 
 #define DRIVER_DESC		"i.MX IPUv3 Graphics"
 
-struct ipu_framebuffer {
-	struct drm_framebuffer	base;
-	void			*virt;
-	dma_addr_t		phys;
-	size_t			len;
-};
-
 struct ipu_crtc {
 	struct device		*dev;
 	struct drm_crtc		base;
 	struct imx_drm_crtc	*imx_crtc;
-	struct ipuv3_channel	*ipu_ch;
+
+	/* plane[0] is the full plane, plane[1] is the partial plane */
+	struct ipu_plane	*plane[2];
+
 	struct ipu_dc		*dc;
-	struct ipu_dp		*dp;
-	struct dmfc_channel	*dmfc;
 	struct ipu_di		*di;
 	int			enabled;
 	struct drm_pending_vblank_event *page_flip_event;
@@ -61,35 +57,14 @@
 
 #define to_ipu_crtc(x) container_of(x, struct ipu_crtc, base)
 
-static int calc_vref(struct drm_display_mode *mode)
-{
-	unsigned long htotal, vtotal;
-
-	htotal = mode->htotal;
-	vtotal = mode->vtotal;
-
-	if (!htotal || !vtotal)
-		return 60;
-
-	return mode->clock * 1000 / vtotal / htotal;
-}
-
-static int calc_bandwidth(struct drm_display_mode *mode, unsigned int vref)
-{
-	return mode->hdisplay * mode->vdisplay * vref;
-}
-
 static void ipu_fb_enable(struct ipu_crtc *ipu_crtc)
 {
 	if (ipu_crtc->enabled)
 		return;
 
 	ipu_di_enable(ipu_crtc->di);
-	ipu_dmfc_enable_channel(ipu_crtc->dmfc);
-	ipu_idmac_enable_channel(ipu_crtc->ipu_ch);
 	ipu_dc_enable_channel(ipu_crtc->dc);
-	if (ipu_crtc->dp)
-		ipu_dp_enable_channel(ipu_crtc->dp);
+	ipu_plane_enable(ipu_crtc->plane[0]);
 
 	ipu_crtc->enabled = 1;
 }
@@ -99,11 +74,8 @@
 	if (!ipu_crtc->enabled)
 		return;
 
-	if (ipu_crtc->dp)
-		ipu_dp_disable_channel(ipu_crtc->dp);
+	ipu_plane_disable(ipu_crtc->plane[0]);
 	ipu_dc_disable_channel(ipu_crtc->dc);
-	ipu_idmac_disable_channel(ipu_crtc->ipu_ch);
-	ipu_dmfc_disable_channel(ipu_crtc->dmfc);
 	ipu_di_disable(ipu_crtc->di);
 
 	ipu_crtc->enabled = 0;
@@ -159,33 +131,6 @@
 	.page_flip = ipu_page_flip,
 };
 
-static int ipu_drm_set_base(struct drm_crtc *crtc, int x, int y)
-{
-	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
-	struct drm_gem_cma_object *cma_obj;
-	struct drm_framebuffer *fb = crtc->fb;
-	unsigned long phys;
-
-	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-	if (!cma_obj) {
-		DRM_LOG_KMS("entry is null.\n");
-		return -EFAULT;
-	}
-
-	phys = cma_obj->paddr;
-	phys += x * (fb->bits_per_pixel >> 3);
-	phys += y * fb->pitches[0];
-
-	dev_dbg(ipu_crtc->dev, "%s: phys: 0x%lx\n", __func__, phys);
-	dev_dbg(ipu_crtc->dev, "%s: xy: %dx%d\n", __func__, x, y);
-
-	ipu_cpmem_set_stride(ipu_get_cpmem(ipu_crtc->ipu_ch), fb->pitches[0]);
-	ipu_cpmem_set_buffer(ipu_get_cpmem(ipu_crtc->ipu_ch),
-			  0, phys);
-
-	return 0;
-}
-
 static int ipu_crtc_mode_set(struct drm_crtc *crtc,
 			       struct drm_display_mode *orig_mode,
 			       struct drm_display_mode *mode,
@@ -193,41 +138,15 @@
 			       struct drm_framebuffer *old_fb)
 {
 	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
-	struct drm_framebuffer *fb = ipu_crtc->base.fb;
 	int ret;
 	struct ipu_di_signal_cfg sig_cfg = {};
 	u32 out_pixel_fmt;
-	struct ipu_ch_param __iomem *cpmem = ipu_get_cpmem(ipu_crtc->ipu_ch);
-	int bpp;
-	u32 v4l2_fmt;
 
 	dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__,
 			mode->hdisplay);
 	dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__,
 			mode->vdisplay);
 
-	ipu_ch_param_zero(cpmem);
-
-	switch (fb->pixel_format) {
-	case DRM_FORMAT_XRGB8888:
-	case DRM_FORMAT_ARGB8888:
-		v4l2_fmt = V4L2_PIX_FMT_RGB32;
-		bpp = 32;
-		break;
-	case DRM_FORMAT_RGB565:
-		v4l2_fmt = V4L2_PIX_FMT_RGB565;
-		bpp = 16;
-		break;
-	case DRM_FORMAT_RGB888:
-		v4l2_fmt = V4L2_PIX_FMT_RGB24;
-		bpp = 24;
-		break;
-	default:
-		dev_err(ipu_crtc->dev, "unsupported pixel format 0x%08x\n",
-				fb->pixel_format);
-		return -EINVAL;
-	}
-
 	out_pixel_fmt = ipu_crtc->interface_pix_fmt;
 
 	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
@@ -238,7 +157,7 @@
 		sig_cfg.Vsync_pol = 1;
 
 	sig_cfg.enable_pol = 1;
-	sig_cfg.clk_pol = 0;
+	sig_cfg.clk_pol = 1;
 	sig_cfg.width = mode->hdisplay;
 	sig_cfg.height = mode->vdisplay;
 	sig_cfg.pixel_fmt = out_pixel_fmt;
@@ -257,18 +176,6 @@
 	sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin;
 	sig_cfg.vsync_pin = ipu_crtc->di_vsync_pin;
 
-	if (ipu_crtc->dp) {
-		ret = ipu_dp_setup_channel(ipu_crtc->dp, IPUV3_COLORSPACE_RGB,
-				IPUV3_COLORSPACE_RGB);
-		if (ret) {
-			dev_err(ipu_crtc->dev,
-				"initializing display processor failed with %d\n",
-				ret);
-			return ret;
-		}
-		ipu_dp_set_global_alpha(ipu_crtc->dp, 1, 0, 1);
-	}
-
 	ret = ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di, sig_cfg.interlaced,
 			out_pixel_fmt, mode->hdisplay);
 	if (ret) {
@@ -285,30 +192,9 @@
 		return ret;
 	}
 
-	ipu_cpmem_set_resolution(cpmem, mode->hdisplay, mode->vdisplay);
-	ipu_cpmem_set_fmt(cpmem, v4l2_fmt);
-	ipu_cpmem_set_high_priority(ipu_crtc->ipu_ch);
-
-	ret = ipu_dmfc_init_channel(ipu_crtc->dmfc, mode->hdisplay);
-	if (ret) {
-		dev_err(ipu_crtc->dev,
-				"initializing dmfc channel failed with %d\n",
-				ret);
-		return ret;
-	}
-
-	ret = ipu_dmfc_alloc_bandwidth(ipu_crtc->dmfc,
-			calc_bandwidth(mode, calc_vref(mode)), 64);
-	if (ret) {
-		dev_err(ipu_crtc->dev,
-				"allocating dmfc bandwidth failed with %d\n",
-				ret);
-		return ret;
-	}
-
-	ipu_drm_set_base(crtc, x, y);
-
-	return 0;
+	return ipu_plane_mode_set(ipu_crtc->plane[0], crtc, mode, crtc->fb,
+				  0, 0, mode->hdisplay, mode->vdisplay,
+				  x, y, mode->hdisplay, mode->vdisplay);
 }
 
 static void ipu_crtc_handle_pageflip(struct ipu_crtc *ipu_crtc)
@@ -332,7 +218,7 @@
 
 	if (ipu_crtc->newfb) {
 		ipu_crtc->newfb = NULL;
-		ipu_drm_set_base(&ipu_crtc->base, 0, 0);
+		ipu_plane_set_base(ipu_crtc->plane[0], ipu_crtc->base.fb, 0, 0);
 		ipu_crtc_handle_pageflip(ipu_crtc);
 	}
 
@@ -370,10 +256,6 @@
 
 static int ipu_enable_vblank(struct drm_crtc *crtc)
 {
-	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
-
-	enable_irq(ipu_crtc->irq);
-
 	return 0;
 }
 
@@ -381,7 +263,8 @@
 {
 	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
 
-	disable_irq(ipu_crtc->irq);
+	ipu_crtc->page_flip_event = NULL;
+	ipu_crtc->newfb = NULL;
 }
 
 static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type,
@@ -418,12 +301,8 @@
 
 static void ipu_put_resources(struct ipu_crtc *ipu_crtc)
 {
-	if (!IS_ERR_OR_NULL(ipu_crtc->ipu_ch))
-		ipu_idmac_put(ipu_crtc->ipu_ch);
-	if (!IS_ERR_OR_NULL(ipu_crtc->dmfc))
-		ipu_dmfc_put(ipu_crtc->dmfc);
-	if (!IS_ERR_OR_NULL(ipu_crtc->dp))
-		ipu_dp_put(ipu_crtc->dp);
+	if (!IS_ERR_OR_NULL(ipu_crtc->dc))
+		ipu_dc_put(ipu_crtc->dc);
 	if (!IS_ERR_OR_NULL(ipu_crtc->di))
 		ipu_di_put(ipu_crtc->di);
 }
@@ -434,32 +313,12 @@
 	struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
 	int ret;
 
-	ipu_crtc->ipu_ch = ipu_idmac_get(ipu, pdata->dma[0]);
-	if (IS_ERR(ipu_crtc->ipu_ch)) {
-		ret = PTR_ERR(ipu_crtc->ipu_ch);
-		goto err_out;
-	}
-
 	ipu_crtc->dc = ipu_dc_get(ipu, pdata->dc);
 	if (IS_ERR(ipu_crtc->dc)) {
 		ret = PTR_ERR(ipu_crtc->dc);
 		goto err_out;
 	}
 
-	ipu_crtc->dmfc = ipu_dmfc_get(ipu, pdata->dma[0]);
-	if (IS_ERR(ipu_crtc->dmfc)) {
-		ret = PTR_ERR(ipu_crtc->dmfc);
-		goto err_out;
-	}
-
-	if (pdata->dp >= 0) {
-		ipu_crtc->dp = ipu_dp_get(ipu, pdata->dp);
-		if (IS_ERR(ipu_crtc->dp)) {
-			ret = PTR_ERR(ipu_crtc->dp);
-			goto err_out;
-		}
-	}
-
 	ipu_crtc->di = ipu_di_get(ipu, pdata->di);
 	if (IS_ERR(ipu_crtc->di)) {
 		ret = PTR_ERR(ipu_crtc->di);
@@ -477,7 +336,9 @@
 		struct ipu_client_platformdata *pdata)
 {
 	struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
+	int dp = -EINVAL;
 	int ret;
+	int id;
 
 	ret = ipu_get_resources(ipu_crtc, pdata);
 	if (ret) {
@@ -495,19 +356,42 @@
 		goto err_put_resources;
 	}
 
-	ipu_crtc->irq = ipu_idmac_channel_irq(ipu, ipu_crtc->ipu_ch,
-			IPU_IRQ_EOF);
+	if (pdata->dp >= 0)
+		dp = IPU_DP_FLOW_SYNC_BG;
+	id = imx_drm_crtc_id(ipu_crtc->imx_crtc);
+	ipu_crtc->plane[0] = ipu_plane_init(ipu_crtc->base.dev, ipu,
+					    pdata->dma[0], dp, BIT(id), true);
+	ret = ipu_plane_get_resources(ipu_crtc->plane[0]);
+	if (ret) {
+		dev_err(ipu_crtc->dev, "getting plane 0 resources failed with %d.\n",
+			ret);
+		goto err_remove_crtc;
+	}
+
+	/* If this crtc is using the DP, add an overlay plane */
+	if (pdata->dp >= 0 && pdata->dma[1] > 0) {
+		ipu_crtc->plane[1] = ipu_plane_init(ipu_crtc->base.dev, ipu,
+						    pdata->dma[1],
+						    IPU_DP_FLOW_SYNC_FG,
+						    BIT(id), false);
+		if (IS_ERR(ipu_crtc->plane[1]))
+			ipu_crtc->plane[1] = NULL;
+	}
+
+	ipu_crtc->irq = ipu_plane_irq(ipu_crtc->plane[0]);
 	ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0,
 			"imx_drm", ipu_crtc);
 	if (ret < 0) {
 		dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret);
-		goto err_put_resources;
+		goto err_put_plane_res;
 	}
 
-	disable_irq(ipu_crtc->irq);
-
 	return 0;
 
+err_put_plane_res:
+	ipu_plane_put_resources(ipu_crtc->plane[0]);
+err_remove_crtc:
+	imx_drm_remove_crtc(ipu_crtc->imx_crtc);
 err_put_resources:
 	ipu_put_resources(ipu_crtc);
 
@@ -546,6 +430,7 @@
 
 	imx_drm_remove_crtc(ipu_crtc->imx_crtc);
 
+	ipu_plane_put_resources(ipu_crtc->plane[0]);
 	ipu_put_resources(ipu_crtc);
 
 	return 0;
diff --git a/drivers/staging/imx-drm/ipuv3-plane.c b/drivers/staging/imx-drm/ipuv3-plane.c
new file mode 100644
index 0000000..d97454a
--- /dev/null
+++ b/drivers/staging/imx-drm/ipuv3-plane.c
@@ -0,0 +1,375 @@
+/*
+ * i.MX IPUv3 DP Overlay Planes
+ *
+ * Copyright (C) 2013 Philipp Zabel, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+
+#include "ipu-v3/imx-ipu-v3.h"
+#include "ipuv3-plane.h"
+
+#define to_ipu_plane(x)	container_of(x, struct ipu_plane, base)
+
+static const uint32_t ipu_plane_formats[] = {
+	DRM_FORMAT_XRGB1555,
+	DRM_FORMAT_XBGR1555,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_YUYV,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_YUV420,
+	DRM_FORMAT_YVU420,
+};
+
+int ipu_plane_irq(struct ipu_plane *ipu_plane)
+{
+	return ipu_idmac_channel_irq(ipu_plane->ipu, ipu_plane->ipu_ch,
+				     IPU_IRQ_EOF);
+}
+
+static int calc_vref(struct drm_display_mode *mode)
+{
+	unsigned long htotal, vtotal;
+
+	htotal = mode->htotal;
+	vtotal = mode->vtotal;
+
+	if (!htotal || !vtotal)
+		return 60;
+
+	return DIV_ROUND_UP(mode->clock * 1000, vtotal * htotal);
+}
+
+static inline int calc_bandwidth(int width, int height, unsigned int vref)
+{
+	return width * height * vref;
+}
+
+int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb,
+		       int x, int y)
+{
+	struct ipu_ch_param __iomem *cpmem;
+	struct drm_gem_cma_object *cma_obj;
+
+	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+	if (!cma_obj) {
+		DRM_LOG_KMS("entry is null.\n");
+		return -EFAULT;
+	}
+
+	dev_dbg(ipu_plane->base.dev->dev, "phys = 0x%x, x = %d, y = %d",
+		cma_obj->paddr, x, y);
+
+	cpmem = ipu_get_cpmem(ipu_plane->ipu_ch);
+	ipu_cpmem_set_stride(cpmem, fb->pitches[0]);
+	ipu_cpmem_set_buffer(cpmem, 0, cma_obj->paddr + fb->offsets[0] +
+			     fb->pitches[0] * y + x);
+
+	return 0;
+}
+
+int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc,
+		       struct drm_display_mode *mode,
+		       struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+		       unsigned int crtc_w, unsigned int crtc_h,
+		       uint32_t src_x, uint32_t src_y,
+		       uint32_t src_w, uint32_t src_h)
+{
+	struct ipu_ch_param __iomem *cpmem;
+	struct device *dev = ipu_plane->base.dev->dev;
+	int ret;
+
+	/* no scaling */
+	if (src_w != crtc_w || src_h != crtc_h)
+		return -EINVAL;
+
+	/* clip to crtc bounds */
+	if (crtc_x < 0) {
+		if (-crtc_x > crtc_w)
+			return -EINVAL;
+		src_x += -crtc_x;
+		src_w -= -crtc_x;
+		crtc_w -= -crtc_x;
+		crtc_x = 0;
+	}
+	if (crtc_y < 0) {
+		if (-crtc_y > crtc_h)
+			return -EINVAL;
+		src_y += -crtc_y;
+		src_h -= -crtc_y;
+		crtc_h -= -crtc_y;
+		crtc_y = 0;
+	}
+	if (crtc_x + crtc_w > mode->hdisplay) {
+		if (crtc_x > mode->hdisplay)
+			return -EINVAL;
+		crtc_w = mode->hdisplay - crtc_x;
+		src_w = crtc_w;
+	}
+	if (crtc_y + crtc_h > mode->vdisplay) {
+		if (crtc_y > mode->vdisplay)
+			return -EINVAL;
+		crtc_h = mode->vdisplay - crtc_y;
+		src_h = crtc_h;
+	}
+	/* full plane minimum width is 13 pixels */
+	if (crtc_w < 13 && (ipu_plane->dp_flow != IPU_DP_FLOW_SYNC_FG))
+		return -EINVAL;
+	if (crtc_h < 2)
+		return -EINVAL;
+
+	switch (ipu_plane->dp_flow) {
+	case IPU_DP_FLOW_SYNC_BG:
+		ret = ipu_dp_setup_channel(ipu_plane->dp,
+				IPUV3_COLORSPACE_RGB,
+				IPUV3_COLORSPACE_RGB);
+		if (ret) {
+			dev_err(dev,
+				"initializing display processor failed with %d\n",
+				ret);
+			return ret;
+		}
+		ipu_dp_set_global_alpha(ipu_plane->dp, 1, 0, 1);
+		break;
+	case IPU_DP_FLOW_SYNC_FG:
+		ipu_dp_setup_channel(ipu_plane->dp,
+				ipu_drm_fourcc_to_colorspace(fb->pixel_format),
+				IPUV3_COLORSPACE_UNKNOWN);
+		ipu_dp_set_window_pos(ipu_plane->dp, crtc_x, crtc_y);
+		break;
+	}
+
+	ret = ipu_dmfc_init_channel(ipu_plane->dmfc, crtc_w);
+	if (ret) {
+		dev_err(dev, "initializing dmfc channel failed with %d\n", ret);
+		return ret;
+	}
+
+	ret = ipu_dmfc_alloc_bandwidth(ipu_plane->dmfc,
+			calc_bandwidth(crtc_w, crtc_h,
+				       calc_vref(mode)), 64);
+	if (ret) {
+		dev_err(dev, "allocating dmfc bandwidth failed with %d\n", ret);
+		return ret;
+	}
+
+	cpmem = ipu_get_cpmem(ipu_plane->ipu_ch);
+	ipu_ch_param_zero(cpmem);
+	ipu_cpmem_set_resolution(cpmem, src_w, src_h);
+	ret = ipu_cpmem_set_fmt(cpmem, fb->pixel_format);
+	if (ret < 0) {
+		dev_err(dev, "unsupported pixel format 0x%08x\n",
+			fb->pixel_format);
+		return ret;
+	}
+	ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);
+
+	ret = ipu_plane_set_base(ipu_plane, fb, src_x, src_y);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+void ipu_plane_put_resources(struct ipu_plane *ipu_plane)
+{
+	if (!IS_ERR_OR_NULL(ipu_plane->dp))
+		ipu_dp_put(ipu_plane->dp);
+	if (!IS_ERR_OR_NULL(ipu_plane->dmfc))
+		ipu_dmfc_put(ipu_plane->dmfc);
+	if (!IS_ERR_OR_NULL(ipu_plane->ipu_ch))
+		ipu_idmac_put(ipu_plane->ipu_ch);
+}
+
+int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
+{
+	int ret;
+
+	ipu_plane->ipu_ch = ipu_idmac_get(ipu_plane->ipu, ipu_plane->dma);
+	if (IS_ERR(ipu_plane->ipu_ch)) {
+		ret = PTR_ERR(ipu_plane->ipu_ch);
+		DRM_ERROR("failed to get idmac channel: %d\n", ret);
+		return ret;
+	}
+
+	ipu_plane->dmfc = ipu_dmfc_get(ipu_plane->ipu, ipu_plane->dma);
+	if (IS_ERR(ipu_plane->dmfc)) {
+		ret = PTR_ERR(ipu_plane->dmfc);
+		DRM_ERROR("failed to get dmfc: ret %d\n", ret);
+		goto err_out;
+	}
+
+	if (ipu_plane->dp_flow >= 0) {
+		ipu_plane->dp = ipu_dp_get(ipu_plane->ipu, ipu_plane->dp_flow);
+		if (IS_ERR(ipu_plane->dp)) {
+			ret = PTR_ERR(ipu_plane->dp);
+			DRM_ERROR("failed to get dp flow: %d\n", ret);
+			goto err_out;
+		}
+	}
+
+	return 0;
+err_out:
+	ipu_plane_put_resources(ipu_plane);
+
+	return ret;
+}
+
+void ipu_plane_enable(struct ipu_plane *ipu_plane)
+{
+	ipu_dmfc_enable_channel(ipu_plane->dmfc);
+	ipu_idmac_enable_channel(ipu_plane->ipu_ch);
+	if (ipu_plane->dp)
+		ipu_dp_enable_channel(ipu_plane->dp);
+
+	ipu_plane->enabled = true;
+}
+
+void ipu_plane_disable(struct ipu_plane *ipu_plane)
+{
+	ipu_plane->enabled = false;
+
+	ipu_idmac_wait_busy(ipu_plane->ipu_ch, 50);
+
+	if (ipu_plane->dp)
+		ipu_dp_disable_channel(ipu_plane->dp);
+	ipu_idmac_disable_channel(ipu_plane->ipu_ch);
+	ipu_dmfc_disable_channel(ipu_plane->dmfc);
+}
+
+static void ipu_plane_dpms(struct ipu_plane *ipu_plane, int mode)
+{
+	bool enable;
+
+	DRM_DEBUG_KMS("mode = %d", mode);
+
+	enable = (mode == DRM_MODE_DPMS_ON);
+
+	if (enable == ipu_plane->enabled)
+		return;
+
+	if (enable) {
+		ipu_plane_enable(ipu_plane);
+	} else {
+		ipu_plane_disable(ipu_plane);
+
+		ipu_idmac_put(ipu_plane->ipu_ch);
+		ipu_dmfc_put(ipu_plane->dmfc);
+		ipu_dp_put(ipu_plane->dp);
+	}
+}
+
+/*
+ * drm_plane API
+ */
+
+static int ipu_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+			    struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+			    unsigned int crtc_w, unsigned int crtc_h,
+			    uint32_t src_x, uint32_t src_y,
+			    uint32_t src_w, uint32_t src_h)
+{
+	struct ipu_plane *ipu_plane = to_ipu_plane(plane);
+	int ret = 0;
+
+	DRM_DEBUG_KMS("plane - %p\n", plane);
+
+	if (!ipu_plane->enabled)
+		ret = ipu_plane_get_resources(ipu_plane);
+	if (ret < 0)
+		return ret;
+
+	ret = ipu_plane_mode_set(ipu_plane, crtc, &crtc->hwmode, fb,
+			crtc_x, crtc_y, crtc_w, crtc_h,
+			src_x >> 16, src_y >> 16, src_w >> 16, src_h >> 16);
+	if (ret < 0) {
+		ipu_plane_put_resources(ipu_plane);
+		return ret;
+	}
+
+	if (crtc != plane->crtc)
+		dev_info(plane->dev->dev, "crtc change: %p -> %p\n",
+				plane->crtc, crtc);
+	plane->crtc = crtc;
+
+	ipu_plane_dpms(ipu_plane, DRM_MODE_DPMS_ON);
+
+	return 0;
+}
+
+static int ipu_disable_plane(struct drm_plane *plane)
+{
+	struct ipu_plane *ipu_plane = to_ipu_plane(plane);
+
+	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
+
+	ipu_plane_dpms(ipu_plane, DRM_MODE_DPMS_OFF);
+
+	ipu_plane_put_resources(ipu_plane);
+
+	return 0;
+}
+
+static void ipu_plane_destroy(struct drm_plane *plane)
+{
+	struct ipu_plane *ipu_plane = to_ipu_plane(plane);
+
+	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
+
+	ipu_disable_plane(plane);
+	drm_plane_cleanup(plane);
+	kfree(ipu_plane);
+}
+
+static struct drm_plane_funcs ipu_plane_funcs = {
+	.update_plane	= ipu_update_plane,
+	.disable_plane	= ipu_disable_plane,
+	.destroy	= ipu_plane_destroy,
+};
+
+struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
+				 int dma, int dp, unsigned int possible_crtcs,
+				 bool priv)
+{
+	struct ipu_plane *ipu_plane;
+	int ret;
+
+	DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n",
+		      dma, dp, possible_crtcs);
+
+	ipu_plane = kzalloc(sizeof(*ipu_plane), GFP_KERNEL);
+	if (!ipu_plane) {
+		DRM_ERROR("failed to allocate plane\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	ipu_plane->ipu = ipu;
+	ipu_plane->dma = dma;
+	ipu_plane->dp_flow = dp;
+
+	ret = drm_plane_init(dev, &ipu_plane->base, possible_crtcs,
+			     &ipu_plane_funcs, ipu_plane_formats,
+			     ARRAY_SIZE(ipu_plane_formats),
+			     priv);
+	if (ret) {
+		DRM_ERROR("failed to initialize plane\n");
+		kfree(ipu_plane);
+		return ERR_PTR(ret);
+	}
+
+	return ipu_plane;
+}
diff --git a/drivers/staging/imx-drm/ipuv3-plane.h b/drivers/staging/imx-drm/ipuv3-plane.h
new file mode 100644
index 0000000..c0aae5b
--- /dev/null
+++ b/drivers/staging/imx-drm/ipuv3-plane.h
@@ -0,0 +1,55 @@
+#ifndef __IPUV3_PLANE_H__
+#define __IPUV3_PLANE_H__
+
+#include <drm/drm_crtc.h> /* drm_plane */
+
+struct drm_plane;
+struct drm_device;
+struct ipu_soc;
+struct drm_crtc;
+struct drm_framebuffer;
+
+struct ipuv3_channel;
+struct dmfc_channel;
+struct ipu_dp;
+
+struct ipu_plane {
+	struct drm_plane	base;
+
+	struct ipu_soc		*ipu;
+	struct ipuv3_channel	*ipu_ch;
+	struct dmfc_channel	*dmfc;
+	struct ipu_dp		*dp;
+
+	int			dma;
+	int			dp_flow;
+
+	int			x;
+	int			y;
+
+	bool			enabled;
+};
+
+struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu,
+				 int dma, int dp, unsigned int possible_crtcs,
+				 bool priv);
+
+/* Init IDMAC, DMFC, DP */
+int ipu_plane_mode_set(struct ipu_plane *plane, struct drm_crtc *crtc,
+		       struct drm_display_mode *mode,
+		       struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+		       unsigned int crtc_w, unsigned int crtc_h,
+		       uint32_t src_x, uint32_t src_y, uint32_t src_w,
+		       uint32_t src_h);
+
+void ipu_plane_enable(struct ipu_plane *plane);
+void ipu_plane_disable(struct ipu_plane *plane);
+int ipu_plane_set_base(struct ipu_plane *plane, struct drm_framebuffer *fb,
+		       int x, int y);
+
+int ipu_plane_get_resources(struct ipu_plane *plane);
+void ipu_plane_put_resources(struct ipu_plane *plane);
+
+int ipu_plane_irq(struct ipu_plane *plane);
+
+#endif
diff --git a/drivers/staging/keucr/usb.c b/drivers/staging/keucr/usb.c
index ddd2e73..a84ee63 100644
--- a/drivers/staging/keucr/usb.c
+++ b/drivers/staging/keucr/usb.c
@@ -604,9 +604,7 @@
 	if (!(MiscReg03 & 0x02)) {
 		result = -ENODEV;
 		quiesce_and_remove_host(us);
-		pr_info("keucr: The driver only supports SM/MS card. "
-			"To use SD card, "
-			"please build driver/usb/storage/ums-eneub6250.ko\n");
+		pr_info("keucr: The driver only supports SM/MS card. To use SD card, please build driver/usb/storage/ums-eneub6250.ko\n");
 		goto BadDevice;
 	}
 
diff --git a/drivers/staging/line6/driver.c b/drivers/staging/line6/driver.c
index 471c10c..cc5d62d 100644
--- a/drivers/staging/line6/driver.c
+++ b/drivers/staging/line6/driver.c
@@ -205,7 +205,7 @@
 			__func__, retval);
 		usb_free_urb(urb);
 		kfree(msg);
-		return -EINVAL;
+		return retval;
 	}
 
 	return 0;
@@ -340,7 +340,7 @@
 		line6->message_length = done;
 		line6_midi_receive(line6, line6->buffer_message, done);
 
-		switch (line6->usbdev->descriptor.idProduct) {
+		switch (le16_to_cpu(line6->usbdev->descriptor.idProduct)) {
 		case LINE6_DEVID_BASSPODXT:
 		case LINE6_DEVID_BASSPODXTLIVE:
 		case LINE6_DEVID_BASSPODXTPRO:
@@ -1010,7 +1010,7 @@
 			dev_err(line6->ifcdev,
 				"driver bug: inconsistent usb device\n");
 
-		switch (line6->usbdev->descriptor.idProduct) {
+		switch (le16_to_cpu(line6->usbdev->descriptor.idProduct)) {
 		case LINE6_DEVID_BASSPODXT:
 		case LINE6_DEVID_BASSPODXTLIVE:
 		case LINE6_DEVID_BASSPODXTPRO:
@@ -1114,7 +1114,7 @@
 {
 	struct usb_line6 *line6 = usb_get_intfdata(interface);
 
-	switch (line6->usbdev->descriptor.idProduct) {
+	switch (le16_to_cpu(line6->usbdev->descriptor.idProduct)) {
 	case LINE6_DEVID_PODSTUDIO_GX:
 	case LINE6_DEVID_PODSTUDIO_UX1:
 	case LINE6_DEVID_PODSTUDIO_UX2:
diff --git a/drivers/staging/line6/midi.c b/drivers/staging/line6/midi.c
index e3f9a53..3f6d78c 100644
--- a/drivers/staging/line6/midi.c
+++ b/drivers/staging/line6/midi.c
@@ -144,7 +144,7 @@
 	if (retval < 0) {
 		dev_err(line6->ifcdev, "usb_submit_urb failed\n");
 		usb_free_urb(urb);
-		return -EINVAL;
+		return retval;
 	}
 
 	++line6->line6midi->num_active_send_urbs;
@@ -205,7 +205,7 @@
 	if (up)
 		line6->line6midi->substream_receive = substream;
 	else
-		line6->line6midi->substream_receive = 0;
+		line6->line6midi->substream_receive = NULL;
 }
 
 static struct snd_rawmidi_ops line6_midi_output_ops = {
diff --git a/drivers/staging/line6/playback.c b/drivers/staging/line6/playback.c
index f9135c7..41869ca 100644
--- a/drivers/staging/line6/playback.c
+++ b/drivers/staging/line6/playback.c
@@ -242,13 +242,14 @@
 		if (line6pcm->flags & LINE6_BITS_PCM_IMPULSE) {
 			create_impulse_test_signal(line6pcm, urb_out,
 						   bytes_per_frame);
-			if (line6pcm->flags & LINE6_BIT_PCM_ALSA_CAPTURE_STREAM) {
+			if (line6pcm->flags &
+			    LINE6_BIT_PCM_ALSA_CAPTURE_STREAM) {
 				line6_capture_copy(line6pcm,
 						   urb_out->transfer_buffer,
 						   urb_out->
 						   transfer_buffer_length);
 				line6_capture_check_period(line6pcm,
-							   urb_out->transfer_buffer_length);
+					urb_out->transfer_buffer_length);
 			}
 		} else {
 #endif
diff --git a/drivers/staging/line6/toneport.c b/drivers/staging/line6/toneport.c
index 776d363..af2e7e5 100644
--- a/drivers/staging/line6/toneport.c
+++ b/drivers/staging/line6/toneport.c
@@ -307,6 +307,7 @@
 	int ticks;
 	struct usb_line6 *line6 = &toneport->line6;
 	struct usb_device *usbdev = line6->usbdev;
+	u16 idProduct = le16_to_cpu(usbdev->descriptor.idProduct);
 
 	/* sync time on device with host: */
 	ticks = (int)get_seconds();
@@ -316,7 +317,7 @@
 	toneport_send_cmd(usbdev, 0x0301, 0x0000);
 
 	/* initialize source select: */
-	switch (usbdev->descriptor.idProduct) {
+	switch (le16_to_cpu(usbdev->descriptor.idProduct)) {
 	case LINE6_DEVID_TONEPORT_UX1:
 	case LINE6_DEVID_TONEPORT_UX2:
 	case LINE6_DEVID_PODSTUDIO_UX1:
@@ -326,7 +327,7 @@
 				  0x0000);
 	}
 
-	if (toneport_has_led(usbdev->descriptor.idProduct))
+	if (toneport_has_led(idProduct))
 		toneport_update_led(&usbdev->dev);
 }
 
@@ -339,6 +340,7 @@
 	int err;
 	struct usb_line6 *line6 = &toneport->line6;
 	struct usb_device *usbdev = line6->usbdev;
+	u16 idProduct = le16_to_cpu(usbdev->descriptor.idProduct);
 
 	if ((interface == NULL) || (toneport == NULL))
 		return -ENODEV;
@@ -361,7 +363,7 @@
 		return err;
 
 	/* register source select control: */
-	switch (usbdev->descriptor.idProduct) {
+	switch (le16_to_cpu(usbdev->descriptor.idProduct)) {
 	case LINE6_DEVID_TONEPORT_UX1:
 	case LINE6_DEVID_TONEPORT_UX2:
 	case LINE6_DEVID_PODSTUDIO_UX1:
@@ -382,7 +384,7 @@
 	line6_read_serial_number(line6, &toneport->serial_number);
 	line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1);
 
-	if (toneport_has_led(usbdev->descriptor.idProduct)) {
+	if (toneport_has_led(idProduct)) {
 		CHECK_RETURN(device_create_file
 			     (&interface->dev, &dev_attr_led_red));
 		CHECK_RETURN(device_create_file
@@ -428,14 +430,16 @@
 void line6_toneport_disconnect(struct usb_interface *interface)
 {
 	struct usb_line6_toneport *toneport;
+	u16 idProduct;
 
 	if (interface == NULL)
 		return;
 
 	toneport = usb_get_intfdata(interface);
 	del_timer_sync(&toneport->timer);
+	idProduct = le16_to_cpu(toneport->line6.usbdev->descriptor.idProduct);
 
-	if (toneport_has_led(toneport->line6.usbdev->descriptor.idProduct)) {
+	if (toneport_has_led(idProduct)) {
 		device_remove_file(&interface->dev, &dev_attr_led_red);
 		device_remove_file(&interface->dev, &dev_attr_led_green);
 	}
diff --git a/drivers/staging/lustre/include/linux/libcfs/bitmap.h b/drivers/staging/lustre/include/linux/libcfs/bitmap.h
index f3d4a89..8b13789 100644
--- a/drivers/staging/lustre/include/linux/libcfs/bitmap.h
+++ b/drivers/staging/lustre/include/linux/libcfs/bitmap.h
@@ -1,111 +1 @@
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- */
-#ifndef _LIBCFS_BITMAP_H_
-#define _LIBCFS_BITMAP_H_
 
-
-typedef struct {
-	int	     size;
-	unsigned long   data[0];
-} cfs_bitmap_t;
-
-#define CFS_BITMAP_SIZE(nbits) \
-     (((nbits/BITS_PER_LONG)+1)*sizeof(long)+sizeof(cfs_bitmap_t))
-
-static inline
-cfs_bitmap_t *CFS_ALLOCATE_BITMAP(int size)
-{
-	cfs_bitmap_t *ptr;
-
-	OBD_ALLOC(ptr, CFS_BITMAP_SIZE(size));
-	if (ptr == NULL)
-		return ptr;
-
-	ptr->size = size;
-
-	return ptr;
-}
-
-#define CFS_FREE_BITMAP(ptr)	OBD_FREE(ptr, CFS_BITMAP_SIZE(ptr->size))
-
-static inline
-void cfs_bitmap_set(cfs_bitmap_t *bitmap, int nbit)
-{
-	set_bit(nbit, bitmap->data);
-}
-
-static inline
-void cfs_bitmap_clear(cfs_bitmap_t *bitmap, int nbit)
-{
-	test_and_clear_bit(nbit, bitmap->data);
-}
-
-static inline
-int cfs_bitmap_check(cfs_bitmap_t *bitmap, int nbit)
-{
-	return test_bit(nbit, bitmap->data);
-}
-
-static inline
-int cfs_bitmap_test_and_clear(cfs_bitmap_t *bitmap, int nbit)
-{
-	return test_and_clear_bit(nbit, bitmap->data);
-}
-
-/* return 0 is bitmap has none set bits */
-static inline
-int cfs_bitmap_check_empty(cfs_bitmap_t *bitmap)
-{
-	return find_first_bit(bitmap->data, bitmap->size) == bitmap->size;
-}
-
-static inline
-void cfs_bitmap_copy(cfs_bitmap_t *new, cfs_bitmap_t *old)
-{
-	int newsize;
-
-	LASSERT(new->size >= old->size);
-	newsize = new->size;
-	memcpy(new, old, CFS_BITMAP_SIZE(old->size));
-	new->size = newsize;
-}
-
-#define cfs_foreach_bit(bitmap, pos)					\
-	for ((pos) = find_first_bit((bitmap)->data, bitmap->size);	\
-	     (pos) < (bitmap)->size;					\
-	     (pos) = find_next_bit((bitmap)->data, (bitmap)->size, (pos) + 1))
-
-#endif
diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h
index e6439d1..40282b7 100644
--- a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h
+++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h
@@ -165,11 +165,11 @@
 #define CDEBUG_DEFAULT_MAX_DELAY (cfs_time_seconds(600))	 /* jiffies */
 #define CDEBUG_DEFAULT_MIN_DELAY ((cfs_time_seconds(1) + 1) / 2) /* jiffies */
 #define CDEBUG_DEFAULT_BACKOFF   2
-typedef struct {
+struct cfs_debug_limit_state {
 	cfs_time_t      cdls_next;
 	unsigned int    cdls_delay;
 	int	     cdls_count;
-} cfs_debug_limit_state_t;
+};
 
 struct libcfs_debug_msg_data {
 	const char	       *msg_file;
@@ -177,7 +177,7 @@
 	int		      msg_subsys;
 	int		      msg_line;
 	int		      msg_mask;
-	cfs_debug_limit_state_t  *msg_cdls;
+	struct cfs_debug_limit_state  *msg_cdls;
 };
 
 #define LIBCFS_DEBUG_MSG_DATA_INIT(data, mask, cdls)	\
@@ -226,7 +226,7 @@
 
 #define CDEBUG_LIMIT(mask, format, ...)	 \
 do {					    \
-	static cfs_debug_limit_state_t cdls;    \
+	static struct cfs_debug_limit_state cdls;    \
 						\
 	__CDEBUG(&cdls, mask, format, ## __VA_ARGS__);\
 } while (0)
diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h
index 98f5be2..9d5ee1a 100644
--- a/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h
+++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h
@@ -81,10 +81,10 @@
 struct cfs_hash_lock_ops;
 struct cfs_hash_hlist_ops;
 
-typedef union {
+union cfs_hash_lock {
 	rwlock_t		rw;		/**< rwlock */
 	spinlock_t		spin;		/**< spinlock */
-} cfs_hash_lock_t;
+};
 
 /**
  * cfs_hash_bucket is a container of:
@@ -97,22 +97,22 @@
  *   which depends on requirement of user
  * - some extra bytes (caller can require it while creating hash)
  */
-typedef struct cfs_hash_bucket {
-	cfs_hash_lock_t		hsb_lock;	/**< bucket lock */
+struct cfs_hash_bucket {
+	union cfs_hash_lock	hsb_lock;	/**< bucket lock */
 	__u32			hsb_count;	/**< current entries */
 	__u32			hsb_version;	/**< change version */
 	unsigned int		hsb_index;	/**< index of bucket */
 	int			hsb_depmax;	/**< max depth on bucket */
 	long			hsb_head[0];	/**< hash-head array */
-} cfs_hash_bucket_t;
+};
 
 /**
  * cfs_hash bucket descriptor, it's normally in stack of caller
  */
-typedef struct cfs_hash_bd {
-	cfs_hash_bucket_t	  *bd_bucket;      /**< address of bucket */
+struct cfs_hash_bd {
+	struct cfs_hash_bucket	*bd_bucket;      /**< address of bucket */
 	unsigned int		bd_offset;      /**< offset in bucket */
-} cfs_hash_bd_t;
+};
 
 #define CFS_HASH_NAME_LEN	   16      /**< default name length */
 #define CFS_HASH_BIGNAME_LEN	64      /**< bigname for param tree */
@@ -210,10 +210,10 @@
  * locations; additions must take care to only insert into the new bucket.
  */
 
-typedef struct cfs_hash {
+struct cfs_hash {
 	/** serialize with rehash, or serialize all operations if
 	 * the hash-table has CFS_HASH_NO_BKTLOCK */
-	cfs_hash_lock_t	     hs_lock;
+	union cfs_hash_lock	     hs_lock;
 	/** hash operations */
 	struct cfs_hash_ops	*hs_ops;
 	/** hash lock operations */
@@ -221,7 +221,7 @@
 	/** hash list operations */
 	struct cfs_hash_hlist_ops  *hs_hops;
 	/** hash buckets-table */
-	cfs_hash_bucket_t	 **hs_buckets;
+	struct cfs_hash_bucket	 **hs_buckets;
 	/** total number of items on this hash-table */
 	atomic_t		hs_count;
 	/** hash flags, see cfs_hash_tag for detail */
@@ -255,7 +255,7 @@
 	/** refcount on this hash table */
 	atomic_t		hs_refcount;
 	/** rehash buckets-table */
-	cfs_hash_bucket_t	 **hs_rehash_buckets;
+	struct cfs_hash_bucket	 **hs_rehash_buckets;
 #if CFS_HASH_DEBUG_LEVEL >= CFS_HASH_DEBUG_1
 	/** serialize debug members */
 	spinlock_t			hs_dep_lock;
@@ -272,35 +272,35 @@
 #endif
 	/** name of htable */
 	char			hs_name[0];
-} cfs_hash_t;
+};
 
 typedef struct cfs_hash_lock_ops {
 	/** lock the hash table */
-	void    (*hs_lock)(cfs_hash_lock_t *lock, int exclusive);
+	void    (*hs_lock)(union cfs_hash_lock *lock, int exclusive);
 	/** unlock the hash table */
-	void    (*hs_unlock)(cfs_hash_lock_t *lock, int exclusive);
+	void    (*hs_unlock)(union cfs_hash_lock *lock, int exclusive);
 	/** lock the hash bucket */
-	void    (*hs_bkt_lock)(cfs_hash_lock_t *lock, int exclusive);
+	void    (*hs_bkt_lock)(union cfs_hash_lock *lock, int exclusive);
 	/** unlock the hash bucket */
-	void    (*hs_bkt_unlock)(cfs_hash_lock_t *lock, int exclusive);
+	void    (*hs_bkt_unlock)(union cfs_hash_lock *lock, int exclusive);
 } cfs_hash_lock_ops_t;
 
 typedef struct cfs_hash_hlist_ops {
 	/** return hlist_head of hash-head of @bd */
-	struct hlist_head *(*hop_hhead)(cfs_hash_t *hs, cfs_hash_bd_t *bd);
+	struct hlist_head *(*hop_hhead)(struct cfs_hash *hs, struct cfs_hash_bd *bd);
 	/** return hash-head size */
-	int (*hop_hhead_size)(cfs_hash_t *hs);
+	int (*hop_hhead_size)(struct cfs_hash *hs);
 	/** add @hnode to hash-head of @bd */
-	int (*hop_hnode_add)(cfs_hash_t *hs,
-			     cfs_hash_bd_t *bd, struct hlist_node *hnode);
+	int (*hop_hnode_add)(struct cfs_hash *hs,
+			     struct cfs_hash_bd *bd, struct hlist_node *hnode);
 	/** remove @hnode from hash-head of @bd */
-	int (*hop_hnode_del)(cfs_hash_t *hs,
-			     cfs_hash_bd_t *bd, struct hlist_node *hnode);
+	int (*hop_hnode_del)(struct cfs_hash *hs,
+			     struct cfs_hash_bd *bd, struct hlist_node *hnode);
 } cfs_hash_hlist_ops_t;
 
 typedef struct cfs_hash_ops {
 	/** return hashed value from @key */
-	unsigned (*hs_hash)(cfs_hash_t *hs, const void *key, unsigned mask);
+	unsigned (*hs_hash)(struct cfs_hash *hs, const void *key, unsigned mask);
 	/** return key address of @hnode */
 	void *   (*hs_key)(struct hlist_node *hnode);
 	/** copy key from @hnode to @key */
@@ -313,13 +313,13 @@
 	/** return object address of @hnode, i.e: container_of(...hnode) */
 	void *   (*hs_object)(struct hlist_node *hnode);
 	/** get refcount of item, always called with holding bucket-lock */
-	void     (*hs_get)(cfs_hash_t *hs, struct hlist_node *hnode);
+	void     (*hs_get)(struct cfs_hash *hs, struct hlist_node *hnode);
 	/** release refcount of item */
-	void     (*hs_put)(cfs_hash_t *hs, struct hlist_node *hnode);
+	void     (*hs_put)(struct cfs_hash *hs, struct hlist_node *hnode);
 	/** release refcount of item, always called with holding bucket-lock */
-	void     (*hs_put_locked)(cfs_hash_t *hs, struct hlist_node *hnode);
+	void     (*hs_put_locked)(struct cfs_hash *hs, struct hlist_node *hnode);
 	/** it's called before removing of @hnode */
-	void     (*hs_exit)(cfs_hash_t *hs, struct hlist_node *hnode);
+	void     (*hs_exit)(struct cfs_hash *hs, struct hlist_node *hnode);
 } cfs_hash_ops_t;
 
 /** total number of buckets in @hs */
@@ -340,41 +340,41 @@
 #define CFS_HASH_RH_NHLIST(hs)  (1U << (hs)->hs_rehash_bits)
 
 static inline int
-cfs_hash_with_no_lock(cfs_hash_t *hs)
+cfs_hash_with_no_lock(struct cfs_hash *hs)
 {
 	/* caller will serialize all operations for this hash-table */
 	return (hs->hs_flags & CFS_HASH_NO_LOCK) != 0;
 }
 
 static inline int
-cfs_hash_with_no_bktlock(cfs_hash_t *hs)
+cfs_hash_with_no_bktlock(struct cfs_hash *hs)
 {
 	/* no bucket lock, one single lock to protect the hash-table */
 	return (hs->hs_flags & CFS_HASH_NO_BKTLOCK) != 0;
 }
 
 static inline int
-cfs_hash_with_rw_bktlock(cfs_hash_t *hs)
+cfs_hash_with_rw_bktlock(struct cfs_hash *hs)
 {
 	/* rwlock to protect hash bucket */
 	return (hs->hs_flags & CFS_HASH_RW_BKTLOCK) != 0;
 }
 
 static inline int
-cfs_hash_with_spin_bktlock(cfs_hash_t *hs)
+cfs_hash_with_spin_bktlock(struct cfs_hash *hs)
 {
 	/* spinlock to protect hash bucket */
 	return (hs->hs_flags & CFS_HASH_SPIN_BKTLOCK) != 0;
 }
 
 static inline int
-cfs_hash_with_add_tail(cfs_hash_t *hs)
+cfs_hash_with_add_tail(struct cfs_hash *hs)
 {
 	return (hs->hs_flags & CFS_HASH_ADD_TAIL) != 0;
 }
 
 static inline int
-cfs_hash_with_no_itemref(cfs_hash_t *hs)
+cfs_hash_with_no_itemref(struct cfs_hash *hs)
 {
 	/* hash-table doesn't keep refcount on item,
 	 * item can't be removed from hash unless it's
@@ -383,75 +383,75 @@
 }
 
 static inline int
-cfs_hash_with_bigname(cfs_hash_t *hs)
+cfs_hash_with_bigname(struct cfs_hash *hs)
 {
 	return (hs->hs_flags & CFS_HASH_BIGNAME) != 0;
 }
 
 static inline int
-cfs_hash_with_counter(cfs_hash_t *hs)
+cfs_hash_with_counter(struct cfs_hash *hs)
 {
 	return (hs->hs_flags & CFS_HASH_COUNTER) != 0;
 }
 
 static inline int
-cfs_hash_with_rehash(cfs_hash_t *hs)
+cfs_hash_with_rehash(struct cfs_hash *hs)
 {
 	return (hs->hs_flags & CFS_HASH_REHASH) != 0;
 }
 
 static inline int
-cfs_hash_with_rehash_key(cfs_hash_t *hs)
+cfs_hash_with_rehash_key(struct cfs_hash *hs)
 {
 	return (hs->hs_flags & CFS_HASH_REHASH_KEY) != 0;
 }
 
 static inline int
-cfs_hash_with_shrink(cfs_hash_t *hs)
+cfs_hash_with_shrink(struct cfs_hash *hs)
 {
 	return (hs->hs_flags & CFS_HASH_SHRINK) != 0;
 }
 
 static inline int
-cfs_hash_with_assert_empty(cfs_hash_t *hs)
+cfs_hash_with_assert_empty(struct cfs_hash *hs)
 {
 	return (hs->hs_flags & CFS_HASH_ASSERT_EMPTY) != 0;
 }
 
 static inline int
-cfs_hash_with_depth(cfs_hash_t *hs)
+cfs_hash_with_depth(struct cfs_hash *hs)
 {
 	return (hs->hs_flags & CFS_HASH_DEPTH) != 0;
 }
 
 static inline int
-cfs_hash_with_nblk_change(cfs_hash_t *hs)
+cfs_hash_with_nblk_change(struct cfs_hash *hs)
 {
 	return (hs->hs_flags & CFS_HASH_NBLK_CHANGE) != 0;
 }
 
 static inline int
-cfs_hash_is_exiting(cfs_hash_t *hs)
+cfs_hash_is_exiting(struct cfs_hash *hs)
 {       /* cfs_hash_destroy is called */
 	return hs->hs_exiting;
 }
 
 static inline int
-cfs_hash_is_rehashing(cfs_hash_t *hs)
+cfs_hash_is_rehashing(struct cfs_hash *hs)
 {       /* rehash is launched */
 	return hs->hs_rehash_bits != 0;
 }
 
 static inline int
-cfs_hash_is_iterating(cfs_hash_t *hs)
+cfs_hash_is_iterating(struct cfs_hash *hs)
 {       /* someone is calling cfs_hash_for_each_* */
 	return hs->hs_iterating || hs->hs_iterators != 0;
 }
 
 static inline int
-cfs_hash_bkt_size(cfs_hash_t *hs)
+cfs_hash_bkt_size(struct cfs_hash *hs)
 {
-	return offsetof(cfs_hash_bucket_t, hsb_head[0]) +
+	return offsetof(struct cfs_hash_bucket, hsb_head[0]) +
 	       hs->hs_hops->hop_hhead_size(hs) * CFS_HASH_BKT_NHLIST(hs) +
 	       hs->hs_extra_bytes;
 }
@@ -459,19 +459,19 @@
 #define CFS_HOP(hs, op)	   (hs)->hs_ops->hs_ ## op
 
 static inline unsigned
-cfs_hash_id(cfs_hash_t *hs, const void *key, unsigned mask)
+cfs_hash_id(struct cfs_hash *hs, const void *key, unsigned mask)
 {
 	return CFS_HOP(hs, hash)(hs, key, mask);
 }
 
 static inline void *
-cfs_hash_key(cfs_hash_t *hs, struct hlist_node *hnode)
+cfs_hash_key(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	return CFS_HOP(hs, key)(hnode);
 }
 
 static inline void
-cfs_hash_keycpy(cfs_hash_t *hs, struct hlist_node *hnode, void *key)
+cfs_hash_keycpy(struct cfs_hash *hs, struct hlist_node *hnode, void *key)
 {
 	if (CFS_HOP(hs, keycpy) != NULL)
 		CFS_HOP(hs, keycpy)(hnode, key);
@@ -481,25 +481,25 @@
  * Returns 1 on a match,
  */
 static inline int
-cfs_hash_keycmp(cfs_hash_t *hs, const void *key, struct hlist_node *hnode)
+cfs_hash_keycmp(struct cfs_hash *hs, const void *key, struct hlist_node *hnode)
 {
 	return CFS_HOP(hs, keycmp)(key, hnode);
 }
 
 static inline void *
-cfs_hash_object(cfs_hash_t *hs, struct hlist_node *hnode)
+cfs_hash_object(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	return CFS_HOP(hs, object)(hnode);
 }
 
 static inline void
-cfs_hash_get(cfs_hash_t *hs, struct hlist_node *hnode)
+cfs_hash_get(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	return CFS_HOP(hs, get)(hs, hnode);
 }
 
 static inline void
-cfs_hash_put_locked(cfs_hash_t *hs, struct hlist_node *hnode)
+cfs_hash_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	LASSERT(CFS_HOP(hs, put_locked) != NULL);
 
@@ -507,7 +507,7 @@
 }
 
 static inline void
-cfs_hash_put(cfs_hash_t *hs, struct hlist_node *hnode)
+cfs_hash_put(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	LASSERT(CFS_HOP(hs, put) != NULL);
 
@@ -515,37 +515,37 @@
 }
 
 static inline void
-cfs_hash_exit(cfs_hash_t *hs, struct hlist_node *hnode)
+cfs_hash_exit(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	if (CFS_HOP(hs, exit))
 		CFS_HOP(hs, exit)(hs, hnode);
 }
 
-static inline void cfs_hash_lock(cfs_hash_t *hs, int excl)
+static inline void cfs_hash_lock(struct cfs_hash *hs, int excl)
 {
 	hs->hs_lops->hs_lock(&hs->hs_lock, excl);
 }
 
-static inline void cfs_hash_unlock(cfs_hash_t *hs, int excl)
+static inline void cfs_hash_unlock(struct cfs_hash *hs, int excl)
 {
 	hs->hs_lops->hs_unlock(&hs->hs_lock, excl);
 }
 
-static inline int cfs_hash_dec_and_lock(cfs_hash_t *hs,
+static inline int cfs_hash_dec_and_lock(struct cfs_hash *hs,
 					atomic_t *condition)
 {
 	LASSERT(cfs_hash_with_no_bktlock(hs));
 	return atomic_dec_and_lock(condition, &hs->hs_lock.spin);
 }
 
-static inline void cfs_hash_bd_lock(cfs_hash_t *hs,
-				    cfs_hash_bd_t *bd, int excl)
+static inline void cfs_hash_bd_lock(struct cfs_hash *hs,
+				    struct cfs_hash_bd *bd, int excl)
 {
 	hs->hs_lops->hs_bkt_lock(&bd->bd_bucket->hsb_lock, excl);
 }
 
-static inline void cfs_hash_bd_unlock(cfs_hash_t *hs,
-				      cfs_hash_bd_t *bd, int excl)
+static inline void cfs_hash_bd_unlock(struct cfs_hash *hs,
+				      struct cfs_hash_bd *bd, int excl)
 {
 	hs->hs_lops->hs_bkt_unlock(&bd->bd_bucket->hsb_lock, excl);
 }
@@ -554,56 +554,56 @@
  * operations on cfs_hash bucket (bd: bucket descriptor),
  * they are normally for hash-table without rehash
  */
-void cfs_hash_bd_get(cfs_hash_t *hs, const void *key, cfs_hash_bd_t *bd);
+void cfs_hash_bd_get(struct cfs_hash *hs, const void *key, struct cfs_hash_bd *bd);
 
-static inline void cfs_hash_bd_get_and_lock(cfs_hash_t *hs, const void *key,
-					    cfs_hash_bd_t *bd, int excl)
+static inline void cfs_hash_bd_get_and_lock(struct cfs_hash *hs, const void *key,
+					    struct cfs_hash_bd *bd, int excl)
 {
 	cfs_hash_bd_get(hs, key, bd);
 	cfs_hash_bd_lock(hs, bd, excl);
 }
 
-static inline unsigned cfs_hash_bd_index_get(cfs_hash_t *hs, cfs_hash_bd_t *bd)
+static inline unsigned cfs_hash_bd_index_get(struct cfs_hash *hs, struct cfs_hash_bd *bd)
 {
 	return bd->bd_offset | (bd->bd_bucket->hsb_index << hs->hs_bkt_bits);
 }
 
-static inline void cfs_hash_bd_index_set(cfs_hash_t *hs,
-					 unsigned index, cfs_hash_bd_t *bd)
+static inline void cfs_hash_bd_index_set(struct cfs_hash *hs,
+					 unsigned index, struct cfs_hash_bd *bd)
 {
 	bd->bd_bucket = hs->hs_buckets[index >> hs->hs_bkt_bits];
 	bd->bd_offset = index & (CFS_HASH_BKT_NHLIST(hs) - 1U);
 }
 
 static inline void *
-cfs_hash_bd_extra_get(cfs_hash_t *hs, cfs_hash_bd_t *bd)
+cfs_hash_bd_extra_get(struct cfs_hash *hs, struct cfs_hash_bd *bd)
 {
 	return (void *)bd->bd_bucket +
 	       cfs_hash_bkt_size(hs) - hs->hs_extra_bytes;
 }
 
 static inline __u32
-cfs_hash_bd_version_get(cfs_hash_bd_t *bd)
+cfs_hash_bd_version_get(struct cfs_hash_bd *bd)
 {
 	/* need hold cfs_hash_bd_lock */
 	return bd->bd_bucket->hsb_version;
 }
 
 static inline __u32
-cfs_hash_bd_count_get(cfs_hash_bd_t *bd)
+cfs_hash_bd_count_get(struct cfs_hash_bd *bd)
 {
 	/* need hold cfs_hash_bd_lock */
 	return bd->bd_bucket->hsb_count;
 }
 
 static inline int
-cfs_hash_bd_depmax_get(cfs_hash_bd_t *bd)
+cfs_hash_bd_depmax_get(struct cfs_hash_bd *bd)
 {
 	return bd->bd_bucket->hsb_depmax;
 }
 
 static inline int
-cfs_hash_bd_compare(cfs_hash_bd_t *bd1, cfs_hash_bd_t *bd2)
+cfs_hash_bd_compare(struct cfs_hash_bd *bd1, struct cfs_hash_bd *bd2)
 {
 	if (bd1->bd_bucket->hsb_index != bd2->bd_bucket->hsb_index)
 		return bd1->bd_bucket->hsb_index - bd2->bd_bucket->hsb_index;
@@ -614,14 +614,14 @@
 	return 0;
 }
 
-void cfs_hash_bd_add_locked(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+void cfs_hash_bd_add_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 			    struct hlist_node *hnode);
-void cfs_hash_bd_del_locked(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+void cfs_hash_bd_del_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 			    struct hlist_node *hnode);
-void cfs_hash_bd_move_locked(cfs_hash_t *hs, cfs_hash_bd_t *bd_old,
-			     cfs_hash_bd_t *bd_new, struct hlist_node *hnode);
+void cfs_hash_bd_move_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd_old,
+			     struct cfs_hash_bd *bd_new, struct hlist_node *hnode);
 
-static inline int cfs_hash_bd_dec_and_lock(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+static inline int cfs_hash_bd_dec_and_lock(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 					   atomic_t *condition)
 {
 	LASSERT(cfs_hash_with_spin_bktlock(hs));
@@ -629,109 +629,109 @@
 				       &bd->bd_bucket->hsb_lock.spin);
 }
 
-static inline struct hlist_head *cfs_hash_bd_hhead(cfs_hash_t *hs,
-						  cfs_hash_bd_t *bd)
+static inline struct hlist_head *cfs_hash_bd_hhead(struct cfs_hash *hs,
+						  struct cfs_hash_bd *bd)
 {
 	return hs->hs_hops->hop_hhead(hs, bd);
 }
 
-struct hlist_node *cfs_hash_bd_lookup_locked(cfs_hash_t *hs,
-					    cfs_hash_bd_t *bd, const void *key);
-struct hlist_node *cfs_hash_bd_peek_locked(cfs_hash_t *hs,
-					  cfs_hash_bd_t *bd, const void *key);
-struct hlist_node *cfs_hash_bd_findadd_locked(cfs_hash_t *hs,
-					     cfs_hash_bd_t *bd, const void *key,
+struct hlist_node *cfs_hash_bd_lookup_locked(struct cfs_hash *hs,
+					    struct cfs_hash_bd *bd, const void *key);
+struct hlist_node *cfs_hash_bd_peek_locked(struct cfs_hash *hs,
+					  struct cfs_hash_bd *bd, const void *key);
+struct hlist_node *cfs_hash_bd_findadd_locked(struct cfs_hash *hs,
+					     struct cfs_hash_bd *bd, const void *key,
 					     struct hlist_node *hnode,
 					     int insist_add);
-struct hlist_node *cfs_hash_bd_finddel_locked(cfs_hash_t *hs,
-					     cfs_hash_bd_t *bd, const void *key,
+struct hlist_node *cfs_hash_bd_finddel_locked(struct cfs_hash *hs,
+					     struct cfs_hash_bd *bd, const void *key,
 					     struct hlist_node *hnode);
 
 /**
  * operations on cfs_hash bucket (bd: bucket descriptor),
  * they are safe for hash-table with rehash
  */
-void cfs_hash_dual_bd_get(cfs_hash_t *hs, const void *key, cfs_hash_bd_t *bds);
-void cfs_hash_dual_bd_lock(cfs_hash_t *hs, cfs_hash_bd_t *bds, int excl);
-void cfs_hash_dual_bd_unlock(cfs_hash_t *hs, cfs_hash_bd_t *bds, int excl);
+void cfs_hash_dual_bd_get(struct cfs_hash *hs, const void *key, struct cfs_hash_bd *bds);
+void cfs_hash_dual_bd_lock(struct cfs_hash *hs, struct cfs_hash_bd *bds, int excl);
+void cfs_hash_dual_bd_unlock(struct cfs_hash *hs, struct cfs_hash_bd *bds, int excl);
 
-static inline void cfs_hash_dual_bd_get_and_lock(cfs_hash_t *hs, const void *key,
-						 cfs_hash_bd_t *bds, int excl)
+static inline void cfs_hash_dual_bd_get_and_lock(struct cfs_hash *hs, const void *key,
+						 struct cfs_hash_bd *bds, int excl)
 {
 	cfs_hash_dual_bd_get(hs, key, bds);
 	cfs_hash_dual_bd_lock(hs, bds, excl);
 }
 
-struct hlist_node *cfs_hash_dual_bd_lookup_locked(cfs_hash_t *hs,
-						 cfs_hash_bd_t *bds,
+struct hlist_node *cfs_hash_dual_bd_lookup_locked(struct cfs_hash *hs,
+						 struct cfs_hash_bd *bds,
 						 const void *key);
-struct hlist_node *cfs_hash_dual_bd_findadd_locked(cfs_hash_t *hs,
-						  cfs_hash_bd_t *bds,
+struct hlist_node *cfs_hash_dual_bd_findadd_locked(struct cfs_hash *hs,
+						  struct cfs_hash_bd *bds,
 						  const void *key,
 						  struct hlist_node *hnode,
 						  int insist_add);
-struct hlist_node *cfs_hash_dual_bd_finddel_locked(cfs_hash_t *hs,
-						  cfs_hash_bd_t *bds,
+struct hlist_node *cfs_hash_dual_bd_finddel_locked(struct cfs_hash *hs,
+						  struct cfs_hash_bd *bds,
 						  const void *key,
 						  struct hlist_node *hnode);
 
 /* Hash init/cleanup functions */
-cfs_hash_t *cfs_hash_create(char *name, unsigned cur_bits, unsigned max_bits,
+struct cfs_hash *cfs_hash_create(char *name, unsigned cur_bits, unsigned max_bits,
 			    unsigned bkt_bits, unsigned extra_bytes,
 			    unsigned min_theta, unsigned max_theta,
 			    cfs_hash_ops_t *ops, unsigned flags);
 
-cfs_hash_t *cfs_hash_getref(cfs_hash_t *hs);
-void cfs_hash_putref(cfs_hash_t *hs);
+struct cfs_hash *cfs_hash_getref(struct cfs_hash *hs);
+void cfs_hash_putref(struct cfs_hash *hs);
 
 /* Hash addition functions */
-void cfs_hash_add(cfs_hash_t *hs, const void *key,
+void cfs_hash_add(struct cfs_hash *hs, const void *key,
 		  struct hlist_node *hnode);
-int cfs_hash_add_unique(cfs_hash_t *hs, const void *key,
+int cfs_hash_add_unique(struct cfs_hash *hs, const void *key,
 			struct hlist_node *hnode);
-void *cfs_hash_findadd_unique(cfs_hash_t *hs, const void *key,
+void *cfs_hash_findadd_unique(struct cfs_hash *hs, const void *key,
 			      struct hlist_node *hnode);
 
 /* Hash deletion functions */
-void *cfs_hash_del(cfs_hash_t *hs, const void *key, struct hlist_node *hnode);
-void *cfs_hash_del_key(cfs_hash_t *hs, const void *key);
+void *cfs_hash_del(struct cfs_hash *hs, const void *key, struct hlist_node *hnode);
+void *cfs_hash_del_key(struct cfs_hash *hs, const void *key);
 
 /* Hash lookup/for_each functions */
 #define CFS_HASH_LOOP_HOG       1024
 
-typedef int (*cfs_hash_for_each_cb_t)(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+typedef int (*cfs_hash_for_each_cb_t)(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 				      struct hlist_node *node, void *data);
-void *cfs_hash_lookup(cfs_hash_t *hs, const void *key);
-void cfs_hash_for_each(cfs_hash_t *hs, cfs_hash_for_each_cb_t, void *data);
-void cfs_hash_for_each_safe(cfs_hash_t *hs, cfs_hash_for_each_cb_t, void *data);
-int  cfs_hash_for_each_nolock(cfs_hash_t *hs,
+void *cfs_hash_lookup(struct cfs_hash *hs, const void *key);
+void cfs_hash_for_each(struct cfs_hash *hs, cfs_hash_for_each_cb_t, void *data);
+void cfs_hash_for_each_safe(struct cfs_hash *hs, cfs_hash_for_each_cb_t, void *data);
+int  cfs_hash_for_each_nolock(struct cfs_hash *hs,
 			      cfs_hash_for_each_cb_t, void *data);
-int  cfs_hash_for_each_empty(cfs_hash_t *hs,
+int  cfs_hash_for_each_empty(struct cfs_hash *hs,
 			     cfs_hash_for_each_cb_t, void *data);
-void cfs_hash_for_each_key(cfs_hash_t *hs, const void *key,
+void cfs_hash_for_each_key(struct cfs_hash *hs, const void *key,
 			   cfs_hash_for_each_cb_t, void *data);
 typedef int (*cfs_hash_cond_opt_cb_t)(void *obj, void *data);
-void cfs_hash_cond_del(cfs_hash_t *hs, cfs_hash_cond_opt_cb_t, void *data);
+void cfs_hash_cond_del(struct cfs_hash *hs, cfs_hash_cond_opt_cb_t, void *data);
 
-void cfs_hash_hlist_for_each(cfs_hash_t *hs, unsigned hindex,
+void cfs_hash_hlist_for_each(struct cfs_hash *hs, unsigned hindex,
 			     cfs_hash_for_each_cb_t, void *data);
-int  cfs_hash_is_empty(cfs_hash_t *hs);
-__u64 cfs_hash_size_get(cfs_hash_t *hs);
+int  cfs_hash_is_empty(struct cfs_hash *hs);
+__u64 cfs_hash_size_get(struct cfs_hash *hs);
 
 /*
  * Rehash - Theta is calculated to be the average chained
  * hash depth assuming a perfectly uniform hash function.
  */
-void cfs_hash_rehash_cancel_locked(cfs_hash_t *hs);
-void cfs_hash_rehash_cancel(cfs_hash_t *hs);
-int  cfs_hash_rehash(cfs_hash_t *hs, int do_rehash);
-void cfs_hash_rehash_key(cfs_hash_t *hs, const void *old_key,
+void cfs_hash_rehash_cancel_locked(struct cfs_hash *hs);
+void cfs_hash_rehash_cancel(struct cfs_hash *hs);
+int  cfs_hash_rehash(struct cfs_hash *hs, int do_rehash);
+void cfs_hash_rehash_key(struct cfs_hash *hs, const void *old_key,
 			 void *new_key, struct hlist_node *hnode);
 
 #if CFS_HASH_DEBUG_LEVEL > CFS_HASH_DEBUG_1
 /* Validate hnode references the correct key */
 static inline void
-cfs_hash_key_validate(cfs_hash_t *hs, const void *key,
+cfs_hash_key_validate(struct cfs_hash *hs, const void *key,
 		      struct hlist_node *hnode)
 {
 	LASSERT(cfs_hash_keycmp(hs, key, hnode));
@@ -739,10 +739,10 @@
 
 /* Validate hnode is in the correct bucket */
 static inline void
-cfs_hash_bucket_validate(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+cfs_hash_bucket_validate(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 			 struct hlist_node *hnode)
 {
-	cfs_hash_bd_t   bds[2];
+	struct cfs_hash_bd   bds[2];
 
 	cfs_hash_dual_bd_get(hs, cfs_hash_key(hs, hnode), bds);
 	LASSERT(bds[0].bd_bucket == bd->bd_bucket ||
@@ -752,11 +752,11 @@
 #else /* CFS_HASH_DEBUG_LEVEL > CFS_HASH_DEBUG_1 */
 
 static inline void
-cfs_hash_key_validate(cfs_hash_t *hs, const void *key,
+cfs_hash_key_validate(struct cfs_hash *hs, const void *key,
 		      struct hlist_node *hnode) {}
 
 static inline void
-cfs_hash_bucket_validate(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+cfs_hash_bucket_validate(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 			 struct hlist_node *hnode) {}
 
 #endif /* CFS_HASH_DEBUG_LEVEL */
@@ -778,13 +778,13 @@
 	       (__cfs_hash_theta_int(theta) * 1000);
 }
 
-static inline int __cfs_hash_theta(cfs_hash_t *hs)
+static inline int __cfs_hash_theta(struct cfs_hash *hs)
 {
 	return (atomic_read(&hs->hs_count) <<
 		CFS_HASH_THETA_BITS) >> hs->hs_cur_bits;
 }
 
-static inline void __cfs_hash_set_theta(cfs_hash_t *hs, int min, int max)
+static inline void __cfs_hash_set_theta(struct cfs_hash *hs, int min, int max)
 {
 	LASSERT(min < max);
 	hs->hs_min_theta = (__u16)min;
@@ -794,7 +794,7 @@
 /* Generic debug formatting routines mainly for proc handler */
 struct seq_file;
 int cfs_hash_debug_header(struct seq_file *m);
-int cfs_hash_debug_str(cfs_hash_t *hs, struct seq_file *m);
+int cfs_hash_debug_str(struct cfs_hash *hs, struct seq_file *m);
 
 /*
  * Generic djb2 hash algorithm for character arrays.
@@ -830,7 +830,7 @@
 	return ((unsigned)(key * CFS_GOLDEN_RATIO_PRIME_64) & mask);
 }
 
-/** iterate over all buckets in @bds (array of cfs_hash_bd_t) */
+/** iterate over all buckets in @bds (array of struct cfs_hash_bd) */
 #define cfs_hash_for_each_bd(bds, n, i) \
 	for (i = 0; i < n && (bds)[i].bd_bucket != NULL; i++)
 
diff --git a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h
index 59bff0b..bf30104 100644
--- a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h
+++ b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h
@@ -79,20 +79,20 @@
 /** exclusive lock */
 #define LNET_LOCK_EX	    CFS_PERCPT_LOCK_EX
 
-static inline int lnet_is_wire_handle_none (lnet_handle_wire_t *wh)
+static inline int lnet_is_wire_handle_none(lnet_handle_wire_t *wh)
 {
 	return (wh->wh_interface_cookie == LNET_WIRE_HANDLE_COOKIE_NONE &&
 		wh->wh_object_cookie == LNET_WIRE_HANDLE_COOKIE_NONE);
 }
 
-static inline int lnet_md_exhausted (lnet_libmd_t *md)
+static inline int lnet_md_exhausted(lnet_libmd_t *md)
 {
 	return (md->md_threshold == 0 ||
 		((md->md_options & LNET_MD_MAX_SIZE) != 0 &&
 		 md->md_offset + md->md_max_size > md->md_length));
 }
 
-static inline int lnet_md_unlinkable (lnet_libmd_t *md)
+static inline int lnet_md_unlinkable(lnet_libmd_t *md)
 {
 	/* Should unlink md when its refcount is 0 and either:
 	 *  - md has been flagged for deletion (by auto unlink or LNetM[DE]Unlink,
@@ -193,31 +193,31 @@
 void lnet_freelist_fini(lnet_freelist_t *fl);
 
 static inline void *
-lnet_freelist_alloc (lnet_freelist_t *fl)
+lnet_freelist_alloc(lnet_freelist_t *fl)
 {
 	/* ALWAYS called with liblock held */
 	lnet_freeobj_t *o;
 
-	if (list_empty (&fl->fl_list))
-		return (NULL);
+	if (list_empty(&fl->fl_list))
+		return NULL;
 
-	o = list_entry (fl->fl_list.next, lnet_freeobj_t, fo_list);
-	list_del (&o->fo_list);
-	return ((void *)&o->fo_contents);
+	o = list_entry(fl->fl_list.next, lnet_freeobj_t, fo_list);
+	list_del(&o->fo_list);
+	return (void *)&o->fo_contents;
 }
 
 static inline void
-lnet_freelist_free (lnet_freelist_t *fl, void *obj)
+lnet_freelist_free(lnet_freelist_t *fl, void *obj)
 {
 	/* ALWAYS called with liblock held */
-	lnet_freeobj_t *o = list_entry (obj, lnet_freeobj_t, fo_contents);
+	lnet_freeobj_t *o = list_entry(obj, lnet_freeobj_t, fo_contents);
 
-	list_add (&o->fo_list, &fl->fl_list);
+	list_add(&o->fo_list, &fl->fl_list);
 }
 
 
 static inline lnet_eq_t *
-lnet_eq_alloc (void)
+lnet_eq_alloc(void)
 {
 	/* NEVER called with resource lock held */
 	struct lnet_res_container *rec = &the_lnet.ln_eq_container;
@@ -251,7 +251,7 @@
 }
 
 static inline lnet_libmd_t *
-lnet_md_alloc (lnet_md_t *umd)
+lnet_md_alloc(lnet_md_t *umd)
 {
 	/* NEVER called with resource lock held */
 	struct lnet_res_container *rec = the_lnet.ln_md_containers[0];
@@ -322,7 +322,7 @@
 }
 
 static inline lnet_msg_t *
-lnet_msg_alloc (void)
+lnet_msg_alloc(void)
 {
 	/* NEVER called with network lock held */
 	struct lnet_msg_container *msc = the_lnet.ln_msg_containers[0];
@@ -353,7 +353,7 @@
 }
 
 static inline void
-lnet_msg_free (lnet_msg_t *msg)
+lnet_msg_free(lnet_msg_t *msg)
 {
 	lnet_net_lock(0);
 	lnet_msg_free_locked(msg);
@@ -363,13 +363,13 @@
 #else /* !LNET_USE_LIB_FREELIST */
 
 static inline lnet_eq_t *
-lnet_eq_alloc (void)
+lnet_eq_alloc(void)
 {
 	/* NEVER called with liblock held */
 	lnet_eq_t *eq;
 
 	LIBCFS_ALLOC(eq, sizeof(*eq));
-	return (eq);
+	return eq;
 }
 
 static inline void
@@ -380,7 +380,7 @@
 }
 
 static inline lnet_libmd_t *
-lnet_md_alloc (lnet_md_t *umd)
+lnet_md_alloc(lnet_md_t *umd)
 {
 	/* NEVER called with liblock held */
 	lnet_libmd_t *md;
@@ -405,7 +405,7 @@
 		INIT_LIST_HEAD(&md->md_list);
 	}
 
-	return (md);
+	return md;
 }
 
 static inline void
@@ -423,13 +423,13 @@
 }
 
 static inline lnet_me_t *
-lnet_me_alloc (void)
+lnet_me_alloc(void)
 {
 	/* NEVER called with liblock held */
 	lnet_me_t *me;
 
 	LIBCFS_ALLOC(me, sizeof(*me));
-	return (me);
+	return me;
 }
 
 static inline void
@@ -448,7 +448,7 @@
 	LIBCFS_ALLOC(msg, sizeof(*msg));
 
 	/* no need to zero, LIBCFS_ALLOC does for us */
-	return (msg);
+	return msg;
 }
 
 static inline void
@@ -479,7 +479,7 @@
 }
 
 static inline void
-lnet_eq2handle (lnet_handle_eq_t *handle, lnet_eq_t *eq)
+lnet_eq2handle(lnet_handle_eq_t *handle, lnet_eq_t *eq)
 {
 	if (eq == NULL) {
 		LNetInvalidateHandle(handle);
@@ -503,7 +503,7 @@
 }
 
 static inline void
-lnet_md2handle (lnet_handle_md_t *handle, lnet_libmd_t *md)
+lnet_md2handle(lnet_handle_md_t *handle, lnet_libmd_t *md)
 {
 	handle->cookie = md->md_lh.lh_cookie;
 }
@@ -544,7 +544,7 @@
 }
 
 static inline void
-lnet_me2handle (lnet_handle_me_t *handle, lnet_me_t *me)
+lnet_me2handle(lnet_handle_me_t *handle, lnet_me_t *me)
 {
 	handle->cookie = me->me_lh.lh_cookie;
 }
@@ -568,7 +568,7 @@
 static inline void
 lnet_peer_addref_locked(lnet_peer_t *lp)
 {
-	LASSERT (lp->lp_refcount > 0);
+	LASSERT(lp->lp_refcount > 0);
 	lp->lp_refcount++;
 }
 
@@ -577,7 +577,7 @@
 static inline void
 lnet_peer_decref_locked(lnet_peer_t *lp)
 {
-	LASSERT (lp->lp_refcount > 0);
+	LASSERT(lp->lp_refcount > 0);
 	lp->lp_refcount--;
 	if (lp->lp_refcount == 0)
 		lnet_destroy_peer_locked(lp);
@@ -660,7 +660,7 @@
 void lnet_proc_fini(void);
 int  lnet_rtrpools_alloc(int im_a_router);
 void lnet_rtrpools_free(void);
-lnet_remotenet_t *lnet_find_net_locked (__u32 net);
+lnet_remotenet_t *lnet_find_net_locked(__u32 net);
 
 int lnet_islocalnid(lnet_nid_t nid);
 int lnet_islocalnet(__u32 net);
@@ -733,11 +733,11 @@
 void lnet_portals_destroy(void);
 
 /* message functions */
-int lnet_parse (lnet_ni_t *ni, lnet_hdr_t *hdr,
+int lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr,
 		lnet_nid_t fromnid, void *private, int rdma_req);
 void lnet_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed,
 	       unsigned int offset, unsigned int mlen, unsigned int rlen);
-lnet_msg_t *lnet_create_reply_msg (lnet_ni_t *ni, lnet_msg_t *get_msg);
+lnet_msg_t *lnet_create_reply_msg(lnet_ni_t *ni, lnet_msg_t *get_msg);
 void lnet_set_reply_msg_len(lnet_ni_t *ni, lnet_msg_t *msg, unsigned int len);
 void lnet_finalize(lnet_ni_t *ni, lnet_msg_t *msg, int rc);
 void lnet_drop_delayed_msg_list(struct list_head *head, char *reason);
@@ -748,36 +748,36 @@
 void lnet_msg_containers_destroy(void);
 int lnet_msg_containers_create(void);
 
-char *lnet_msgtyp2str (int type);
-void lnet_print_hdr (lnet_hdr_t * hdr);
+char *lnet_msgtyp2str(int type);
+void lnet_print_hdr(lnet_hdr_t *hdr);
 int lnet_fail_nid(lnet_nid_t nid, unsigned int threshold);
 
 void lnet_counters_get(lnet_counters_t *counters);
 void lnet_counters_reset(void);
 
-unsigned int lnet_iov_nob (unsigned int niov, struct iovec *iov);
-int lnet_extract_iov (int dst_niov, struct iovec *dst,
+unsigned int lnet_iov_nob(unsigned int niov, struct iovec *iov);
+int lnet_extract_iov(int dst_niov, struct iovec *dst,
 		      int src_niov, struct iovec *src,
 		      unsigned int offset, unsigned int len);
 
-unsigned int lnet_kiov_nob (unsigned int niov, lnet_kiov_t *iov);
-int lnet_extract_kiov (int dst_niov, lnet_kiov_t *dst,
+unsigned int lnet_kiov_nob(unsigned int niov, lnet_kiov_t *iov);
+int lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst,
 		      int src_niov, lnet_kiov_t *src,
 		      unsigned int offset, unsigned int len);
 
-void lnet_copy_iov2iov (unsigned int ndiov, struct iovec *diov,
+void lnet_copy_iov2iov(unsigned int ndiov, struct iovec *diov,
 			unsigned int doffset,
 			unsigned int nsiov, struct iovec *siov,
 			unsigned int soffset, unsigned int nob);
-void lnet_copy_kiov2iov (unsigned int niov, struct iovec *iov,
+void lnet_copy_kiov2iov(unsigned int niov, struct iovec *iov,
 			 unsigned int iovoffset,
 			 unsigned int nkiov, lnet_kiov_t *kiov,
 			 unsigned int kiovoffset, unsigned int nob);
-void lnet_copy_iov2kiov (unsigned int nkiov, lnet_kiov_t *kiov,
+void lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov,
 			 unsigned int kiovoffset,
 			 unsigned int niov, struct iovec *iov,
 			 unsigned int iovoffset, unsigned int nob);
-void lnet_copy_kiov2kiov (unsigned int ndkiov, lnet_kiov_t *dkiov,
+void lnet_copy_kiov2kiov(unsigned int ndkiov, lnet_kiov_t *dkiov,
 			  unsigned int doffset,
 			  unsigned int nskiov, lnet_kiov_t *skiov,
 			  unsigned int soffset, unsigned int nob);
@@ -829,7 +829,7 @@
 
 void lnet_register_lnd(lnd_t *lnd);
 void lnet_unregister_lnd(lnd_t *lnd);
-int lnet_set_ip_niaddr (lnet_ni_t *ni);
+int lnet_set_ip_niaddr(lnet_ni_t *ni);
 
 int lnet_connect(socket_t **sockp, lnet_nid_t peer_nid,
 		 __u32 local_ip, __u32 peer_ip, int peer_port);
@@ -858,9 +858,9 @@
 int lnet_ping(lnet_process_id_t id, int timeout_ms,
 	      lnet_process_id_t *ids, int n_ids);
 
-int lnet_parse_ip2nets (char **networksp, char *ip2nets);
-int lnet_parse_routes (char *route_str, int *im_a_router);
-int lnet_parse_networks (struct list_head *nilist, char *networks);
+int lnet_parse_ip2nets(char **networksp, char *ip2nets);
+int lnet_parse_routes(char *route_str, int *im_a_router);
+int lnet_parse_networks(struct list_head *nilist, char *networks);
 
 int lnet_nid2peer_locked(lnet_peer_t **lpp, lnet_nid_t nid, int cpt);
 lnet_peer_t *lnet_find_peer_locked(struct lnet_peer_table *ptable,
diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c
index 6825b45..2ddc3aa 100644
--- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c
+++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c
@@ -1768,7 +1768,10 @@
 	if (id.nid == LNET_NID_ANY || id.pid == LNET_PID_ANY || ipaddr == 0)
 		return (0);
 
-	return (count == 0 ? -ENOENT : 0);
+	if (count == 0)
+		return -ENOENT;
+	else
+		return 0;
 }
 
 void
diff --git a/drivers/staging/lustre/lnet/lnet/acceptor.c b/drivers/staging/lustre/lnet/lnet/acceptor.c
index bb15bde..92c60a7 100644
--- a/drivers/staging/lustre/lnet/lnet/acceptor.c
+++ b/drivers/staging/lustre/lnet/lnet/acceptor.c
@@ -53,6 +53,7 @@
 {
 	return accept_port;
 }
+EXPORT_SYMBOL(lnet_acceptor_port);
 
 static inline int
 lnet_accept_magic(__u32 magic, __u32 constant)
@@ -61,9 +62,6 @@
 		magic == __swab32(constant));
 }
 
-
-EXPORT_SYMBOL(lnet_acceptor_port);
-
 static char *accept = "secure";
 
 CFS_MODULE_PARM(accept, "s", charp, 0444,
@@ -75,7 +73,7 @@
 CFS_MODULE_PARM(accept_timeout, "i", int, 0644,
 		"Acceptor's timeout (seconds)");
 
-static char *accept_type = NULL;
+static char *accept_type;
 
 int
 lnet_acceptor_get_tunables(void)
@@ -95,57 +93,45 @@
 EXPORT_SYMBOL(lnet_acceptor_timeout);
 
 void
-lnet_connect_console_error (int rc, lnet_nid_t peer_nid,
+lnet_connect_console_error(int rc, lnet_nid_t peer_nid,
 			   __u32 peer_ip, int peer_port)
 {
 	switch (rc) {
 	/* "normal" errors */
 	case -ECONNREFUSED:
-		CNETERR("Connection to %s at host %pI4h on port %d was "
-			"refused: check that Lustre is running on that node.\n",
+		CNETERR("Connection to %s at host %pI4h on port %d was refused: check that Lustre is running on that node.\n",
 			libcfs_nid2str(peer_nid),
 			&peer_ip, peer_port);
 		break;
 	case -EHOSTUNREACH:
 	case -ENETUNREACH:
-		CNETERR("Connection to %s at host %pI4h "
-			"was unreachable: the network or that node may "
-			"be down, or Lustre may be misconfigured.\n",
+		CNETERR("Connection to %s at host %pI4h was unreachable: the network or that node may be down, or Lustre may be misconfigured.\n",
 			libcfs_nid2str(peer_nid), &peer_ip);
 		break;
 	case -ETIMEDOUT:
-		CNETERR("Connection to %s at host %pI4h on "
-			"port %d took too long: that node may be hung "
-			"or experiencing high load.\n",
+		CNETERR("Connection to %s at host %pI4h on port %d took too long: that node may be hung or experiencing high load.\n",
 			libcfs_nid2str(peer_nid),
 			&peer_ip, peer_port);
 		break;
 	case -ECONNRESET:
-		LCONSOLE_ERROR_MSG(0x11b, "Connection to %s at host %pI4h"
-				   " on port %d was reset: "
-				   "is it running a compatible version of "
-				   "Lustre and is %s one of its NIDs?\n",
+		LCONSOLE_ERROR_MSG(0x11b, "Connection to %s at host %pI4h on port %d was reset: is it running a compatible version of Lustre and is %s one of its NIDs?\n",
 				   libcfs_nid2str(peer_nid),
 				   &peer_ip, peer_port,
 				   libcfs_nid2str(peer_nid));
 		break;
 	case -EPROTO:
-		LCONSOLE_ERROR_MSG(0x11c, "Protocol error connecting to %s at "
-				   "host %pI4h on port %d: is it running "
-				   "a compatible version of Lustre?\n",
+		LCONSOLE_ERROR_MSG(0x11c, "Protocol error connecting to %s at host %pI4h on port %d: is it running a compatible version of Lustre?\n",
 				   libcfs_nid2str(peer_nid),
 				   &peer_ip, peer_port);
 		break;
 	case -EADDRINUSE:
-		LCONSOLE_ERROR_MSG(0x11d, "No privileged ports available to "
-				   "connect to %s at host %pI4h on port "
-				   "%d\n", libcfs_nid2str(peer_nid),
+		LCONSOLE_ERROR_MSG(0x11d, "No privileged ports available to connect to %s at host %pI4h on port %d\n",
+				   libcfs_nid2str(peer_nid),
 				   &peer_ip, peer_port);
 		break;
 	default:
-		LCONSOLE_ERROR_MSG(0x11e, "Unexpected error %d connecting to %s"
-				   " at host %pI4h on port %d\n", rc,
-				   libcfs_nid2str(peer_nid),
+		LCONSOLE_ERROR_MSG(0x11e, "Unexpected error %d connecting to %s at host %pI4h on port %d\n",
+				   rc, libcfs_nid2str(peer_nid),
 				   &peer_ip, peer_port);
 		break;
 	}
@@ -162,7 +148,7 @@
 	int		     port;
 	int		     fatal;
 
-	CLASSERT (sizeof(cr) <= 16);	    /* not too big to be on the stack */
+	CLASSERT(sizeof(cr) <= 16);	    /* not too big to be on the stack */
 
 	for (port = LNET_ACCEPTOR_MAX_RESERVED_PORT;
 	     port >= LNET_ACCEPTOR_MIN_RESERVED_PORT;
@@ -178,7 +164,7 @@
 			continue;
 		}
 
-		CLASSERT (LNET_PROTO_ACCEPTOR_VERSION == 1);
+		CLASSERT(LNET_PROTO_ACCEPTOR_VERSION == 1);
 
 		cr.acr_magic   = LNET_PROTO_ACCEPTOR_MAGIC;
 		cr.acr_version = LNET_PROTO_ACCEPTOR_VERSION;
@@ -232,10 +218,10 @@
 	lnet_ni_t	      *ni;
 	char		   *str;
 
-	LASSERT (sizeof(cr) <= 16);	     /* not too big for the stack */
+	LASSERT(sizeof(cr) <= 16);	     /* not too big for the stack */
 
 	rc = libcfs_sock_getaddr(sock, 1, &peer_ip, &peer_port);
-	LASSERT (rc == 0);		      /* we succeeded before */
+	LASSERT(rc == 0);		      /* we succeeded before */
 
 	if (!lnet_accept_magic(magic, LNET_PROTO_ACCEPTOR_MAGIC)) {
 
@@ -245,15 +231,14 @@
 			 * thing sent will be a version query.  I send back
 			 * LNET_PROTO_ACCEPTOR_MAGIC to tell her I'm "old" */
 
-			memset (&cr, 0, sizeof(cr));
+			memset(&cr, 0, sizeof(cr));
 			cr.acr_magic = LNET_PROTO_ACCEPTOR_MAGIC;
 			cr.acr_version = LNET_PROTO_ACCEPTOR_VERSION;
 			rc = libcfs_sock_write(sock, &cr, sizeof(cr),
 					       accept_timeout);
 
 			if (rc != 0)
-				CERROR("Error sending magic+version in response"
-				       "to LNET magic from %pI4h: %d\n",
+				CERROR("Error sending magic+version in response to LNET magic from %pI4h: %d\n",
 				       &peer_ip, rc);
 			return -EPROTO;
 		}
@@ -265,8 +250,7 @@
 		else
 			str = "unrecognised";
 
-		LCONSOLE_ERROR_MSG(0x11f, "Refusing connection from %pI4h"
-				   " magic %08x: %s acceptor protocol\n",
+		LCONSOLE_ERROR_MSG(0x11f, "Refusing connection from %pI4h magic %08x: %s acceptor protocol\n",
 				   &peer_ip, magic, str);
 		return -EPROTO;
 	}
@@ -277,8 +261,8 @@
 			      sizeof(cr.acr_version),
 			      accept_timeout);
 	if (rc != 0) {
-		CERROR("Error %d reading connection request version from "
-		       "%pI4h\n", rc, &peer_ip);
+		CERROR("Error %d reading connection request version from %pI4h\n",
+			rc, &peer_ip);
 		return -EIO;
 	}
 
@@ -292,7 +276,7 @@
 		 * "old". */
 		int peer_version = cr.acr_version;
 
-		memset (&cr, 0, sizeof(cr));
+		memset(&cr, 0, sizeof(cr));
 		cr.acr_magic = LNET_PROTO_ACCEPTOR_MAGIC;
 		cr.acr_version = LNET_PROTO_ACCEPTOR_VERSION;
 
@@ -300,8 +284,7 @@
 				       accept_timeout);
 
 		if (rc != 0)
-			CERROR("Error sending magic+version in response"
-			       "to version %d from %pI4h: %d\n",
+			CERROR("Error sending magic+version in response to version %d from %pI4h: %d\n",
 			       peer_version, &peer_ip, rc);
 		return -EPROTO;
 	}
@@ -311,8 +294,8 @@
 			      offsetof(lnet_acceptor_connreq_t, acr_nid),
 			      accept_timeout);
 	if (rc != 0) {
-		CERROR("Error %d reading connection request from "
-		       "%pI4h\n", rc, &peer_ip);
+		CERROR("Error %d reading connection request from %pI4h\n",
+			rc, &peer_ip);
 		return -EIO;
 	}
 
@@ -324,8 +307,7 @@
 	    ni->ni_nid != cr.acr_nid) { /* right NET, wrong NID! */
 		if (ni != NULL)
 			lnet_ni_decref(ni);
-		LCONSOLE_ERROR_MSG(0x120, "Refusing connection from %pI4h"
-				   " for %s: No matching NI\n",
+		LCONSOLE_ERROR_MSG(0x120, "Refusing connection from %pI4h for %s: No matching NI\n",
 				   &peer_ip, libcfs_nid2str(cr.acr_nid));
 		return -EPERM;
 	}
@@ -333,8 +315,7 @@
 	if (ni->ni_lnd->lnd_accept == NULL) {
 		/* This catches a request for the loopback LND */
 		lnet_ni_decref(ni);
-		LCONSOLE_ERROR_MSG(0x121, "Refusing connection from %pI4h"
-				  " for %s: NI doesn not accept IP connections\n",
+		LCONSOLE_ERROR_MSG(0x121, "Refusing connection from %pI4h for %s: NI doesn not accept IP connections\n",
 				  &peer_ip, libcfs_nid2str(cr.acr_nid));
 		return -EPERM;
 	}
@@ -358,7 +339,7 @@
 	int	    peer_port;
 	int	    secure = (int)((long_ptr_t)arg);
 
-	LASSERT (lnet_acceptor_state.pta_sock == NULL);
+	LASSERT(lnet_acceptor_state.pta_sock == NULL);
 
 	cfs_block_allsigs();
 
@@ -366,12 +347,10 @@
 				0, accept_port, accept_backlog);
 	if (rc != 0) {
 		if (rc == -EADDRINUSE)
-			LCONSOLE_ERROR_MSG(0x122, "Can't start acceptor on port"
-					   " %d: port already in use\n",
+			LCONSOLE_ERROR_MSG(0x122, "Can't start acceptor on port %d: port already in use\n",
 					   accept_port);
 		else
-			LCONSOLE_ERROR_MSG(0x123, "Can't start acceptor on port "
-					   "%d: unexpected error %d\n",
+			LCONSOLE_ERROR_MSG(0x123, "Can't start acceptor on port %d: unexpected error %d\n",
 					   accept_port, rc);
 
 		lnet_acceptor_state.pta_sock = NULL;
@@ -410,8 +389,7 @@
 		}
 
 		if (secure && peer_port > LNET_ACCEPTOR_MAX_RESERVED_PORT) {
-			CERROR("Refusing connection from %pI4h: "
-			       "insecure port %d\n",
+			CERROR("Refusing connection from %pI4h: insecure port %d\n",
 			       &peer_ip, peer_port);
 			goto failed;
 		}
@@ -419,8 +397,8 @@
 		rc = libcfs_sock_read(newsock, &magic, sizeof(magic),
 				      accept_timeout);
 		if (rc != 0) {
-			CERROR("Error %d reading connection request from "
-			       "%pI4h\n", rc, &peer_ip);
+			CERROR("Error %d reading connection request from %pI4h\n",
+				rc, &peer_ip);
 			goto failed;
 		}
 
@@ -430,7 +408,7 @@
 
 		continue;
 
-	failed:
+failed:
 		libcfs_sock_release(newsock);
 	}
 
@@ -469,7 +447,7 @@
 	long rc2;
 	long secure;
 
-	LASSERT (lnet_acceptor_state.pta_sock == NULL);
+	LASSERT(lnet_acceptor_state.pta_sock == NULL);
 
 	rc = lnet_acceptor_get_tunables();
 	if (rc != 0)
diff --git a/drivers/staging/lustre/lnet/lnet/config.c b/drivers/staging/lustre/lnet/lnet/config.c
index 28711e6..de323f7 100644
--- a/drivers/staging/lustre/lnet/lnet/config.c
+++ b/drivers/staging/lustre/lnet/lnet/config.c
@@ -43,7 +43,7 @@
 	char	       ltb_text[0];     /* text buffer */
 } lnet_text_buf_t;
 
-static int lnet_tbnob = 0;			/* track text buf allocation */
+static int lnet_tbnob;			/* track text buf allocation */
 #define LNET_MAX_TEXTBUF_NOB     (64<<10)	/* bound allocation */
 #define LNET_SINGLE_TEXTBUF_NOB  (4<<10)
 
@@ -65,7 +65,7 @@
 }
 
 int
-lnet_issep (char c)
+lnet_issep(char c)
 {
 	switch (c) {
 	case '\n':
@@ -83,7 +83,7 @@
 	struct list_head       *tmp;
 	lnet_ni_t	*ni;
 
-	list_for_each (tmp, nilist) {
+	list_for_each(tmp, nilist) {
 		ni = list_entry(tmp, lnet_ni_t, ni_list);
 
 		if (LNET_NIDNET(ni->ni_nid) == net)
@@ -188,8 +188,8 @@
 
 	if (strlen(networks) > LNET_SINGLE_TEXTBUF_NOB) {
 		/* _WAY_ conservative */
-		LCONSOLE_ERROR_MSG(0x112, "Can't parse networks: string too "
-				   "long\n");
+		LCONSOLE_ERROR_MSG(0x112,
+				   "Can't parse networks: string too long\n");
 		return -EINVAL;
 	}
 
@@ -201,7 +201,7 @@
 
 	the_lnet.ln_network_tokens = tokens;
 	the_lnet.ln_network_tokens_nob = tokensize;
-	memcpy (tokens, networks, tokensize);
+	memcpy(tokens, networks, tokensize);
 	str = tmp = tokens;
 
 	/* Add in the loopback network */
@@ -255,8 +255,8 @@
 			net = libcfs_str2net(cfs_trimwhite(str));
 
 			if (net == LNET_NIDNET(LNET_NID_ANY)) {
-				LCONSOLE_ERROR_MSG(0x113, "Unrecognised network"
-						   " type\n");
+				LCONSOLE_ERROR_MSG(0x113,
+						   "Unrecognised network type\n");
 				tmp = str;
 				goto failed_syntax;
 			}
@@ -313,8 +313,8 @@
 			}
 
 			if (niface == LNET_MAX_INTERFACES) {
-				LCONSOLE_ERROR_MSG(0x115, "Too many interfaces "
-						   "for net %s\n",
+				LCONSOLE_ERROR_MSG(0x115,
+						   "Too many interfaces for net %s\n",
 						   libcfs_net2str(net));
 				goto failed;
 			}
@@ -366,7 +366,7 @@
 }
 
 lnet_text_buf_t *
-lnet_new_text_buf (int str_len)
+lnet_new_text_buf(int str_len)
 {
 	lnet_text_buf_t *ltb;
 	int	      nob;
@@ -395,7 +395,7 @@
 }
 
 void
-lnet_free_text_buf (lnet_text_buf_t *ltb)
+lnet_free_text_buf(lnet_text_buf_t *ltb)
 {
 	lnet_tbnob -= ltb->ltb_size;
 	LIBCFS_FREE(ltb, ltb->ltb_size);
@@ -420,7 +420,7 @@
 	struct list_head	*tmp;
 	lnet_text_buf_t   *ltb;
 
-	list_for_each (tmp, tbs) {
+	list_for_each(tmp, tbs) {
 		ltb = list_entry(tmp, lnet_text_buf_t, ltb_list);
 
 		CDEBUG(D_WARNING, "%s\n", ltb->ltb_text);
@@ -430,7 +430,7 @@
 }
 
 int
-lnet_str2tbs_sep (struct list_head *tbs, char *str)
+lnet_str2tbs_sep(struct list_head *tbs, char *str)
 {
 	struct list_head	pending;
 	char	     *sep;
@@ -488,7 +488,7 @@
 }
 
 int
-lnet_expand1tb (struct list_head *list,
+lnet_expand1tb(struct list_head *list,
 	       char *str, char *sep1, char *sep2,
 	       char *item, int itemlen)
 {
@@ -496,8 +496,8 @@
 	int	      len2 = strlen(sep2 + 1);
 	lnet_text_buf_t *ltb;
 
-	LASSERT (*sep1 == '[');
-	LASSERT (*sep2 == ']');
+	LASSERT(*sep1 == '[');
+	LASSERT(*sep2 == ']');
 
 	ltb = lnet_new_text_buf(len1 + itemlen + len2);
 	if (ltb == NULL)
@@ -513,7 +513,7 @@
 }
 
 int
-lnet_str2tbs_expand (struct list_head *tbs, char *str)
+lnet_str2tbs_expand(struct list_head *tbs, char *str)
 {
 	char	      num[16];
 	struct list_head	pending;
@@ -593,7 +593,7 @@
 }
 
 int
-lnet_parse_hops (char *str, unsigned int *hops)
+lnet_parse_hops(char *str, unsigned int *hops)
 {
 	int     len = strlen(str);
 	int     nob = len;
@@ -605,7 +605,7 @@
 
 
 int
-lnet_parse_route (char *str, int *im_a_router)
+lnet_parse_route(char *str, int *im_a_router)
 {
 	/* static scratch buffer OK (single threaded) */
 	static char       cmd[LNET_SINGLE_TEXTBUF_NOB];
@@ -702,28 +702,27 @@
 	if (!got_hops)
 		hops = 1;
 
-	LASSERT (!list_empty(&nets));
-	LASSERT (!list_empty(&gateways));
+	LASSERT(!list_empty(&nets));
+	LASSERT(!list_empty(&gateways));
 
-	list_for_each (tmp1, &nets) {
+	list_for_each(tmp1, &nets) {
 		ltb = list_entry(tmp1, lnet_text_buf_t, ltb_list);
 		net = libcfs_str2net(ltb->ltb_text);
-		LASSERT (net != LNET_NIDNET(LNET_NID_ANY));
+		LASSERT(net != LNET_NIDNET(LNET_NID_ANY));
 
-		list_for_each (tmp2, &gateways) {
+		list_for_each(tmp2, &gateways) {
 			ltb = list_entry(tmp2, lnet_text_buf_t, ltb_list);
 			nid = libcfs_str2nid(ltb->ltb_text);
-			LASSERT (nid != LNET_NID_ANY);
+			LASSERT(nid != LNET_NID_ANY);
 
 			if (lnet_islocalnid(nid)) {
 				*im_a_router = 1;
 				continue;
 			}
 
-			rc = lnet_add_route (net, hops, nid);
+			rc = lnet_add_route(net, hops, nid);
 			if (rc != 0) {
-				CERROR("Can't create route "
-				       "to %s via %s\n",
+				CERROR("Can't create route to %s via %s\n",
 				       libcfs_net2str(net),
 				       libcfs_nid2str(nid));
 				goto out;
@@ -763,7 +762,7 @@
 }
 
 int
-lnet_parse_routes (char *routes, int *im_a_router)
+lnet_parse_routes(char *routes, int *im_a_router)
 {
 	struct list_head	tbs;
 	int	       rc = 0;
@@ -779,14 +778,14 @@
 		rc = lnet_parse_route_tbs(&tbs, im_a_router);
 	}
 
-	LASSERT (lnet_tbnob == 0);
+	LASSERT(lnet_tbnob == 0);
 	return rc;
 }
 
 int
 lnet_match_network_token(char *token, int len, __u32 *ipaddrs, int nip)
 {
-	LIST_HEAD	(list);
+	LIST_HEAD(list);
 	int		rc;
 	int		i;
 
@@ -815,7 +814,7 @@
 	char *token;
 	int   rc;
 
-	LASSERT (strlen(net_entry) < sizeof(tokens));
+	LASSERT(strlen(net_entry) < sizeof(tokens));
 
 	/* work on a copy of the string */
 	strcpy(tokens, net_entry);
@@ -889,8 +888,8 @@
 	char	     *bracket;
 	__u32	     net;
 
-	LASSERT (!list_empty(nets));
-	LASSERT (nets->next == nets->prev);     /* single entry */
+	LASSERT(!list_empty(nets));
+	LASSERT(nets->next == nets->prev);     /* single entry */
 
 	tb = list_entry(nets->next, lnet_text_buf_t, ltb_list);
 
@@ -957,7 +956,7 @@
 }
 
 int
-lnet_match_networks (char **networksp, char *ip2nets, __u32 *ipaddrs, int nip)
+lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip)
 {
 	static char	networks[LNET_SINGLE_TEXTBUF_NOB];
 	static char	source[LNET_SINGLE_TEXTBUF_NOB];
@@ -979,7 +978,7 @@
 	INIT_LIST_HEAD(&raw_entries);
 	if (lnet_str2tbs_sep(&raw_entries, ip2nets) < 0) {
 		CERROR("Error parsing ip2nets\n");
-		LASSERT (lnet_tbnob == 0);
+		LASSERT(lnet_tbnob == 0);
 		return -EINVAL;
 	}
 
@@ -1017,16 +1016,16 @@
 			break;
 
 		dup = 0;
-		list_for_each (t, &current_nets) {
+		list_for_each(t, &current_nets) {
 			tb = list_entry(t, lnet_text_buf_t, ltb_list);
 			net1 = lnet_netspec2net(tb->ltb_text);
-			LASSERT (net1 != LNET_NIDNET(LNET_NID_ANY));
+			LASSERT(net1 != LNET_NIDNET(LNET_NID_ANY));
 
 			list_for_each(t2, &matched_nets) {
 				tb2 = list_entry(t2, lnet_text_buf_t,
 						     ltb_list);
 				net2 = lnet_netspec2net(tb2->ltb_text);
-				LASSERT (net2 != LNET_NIDNET(LNET_NID_ANY));
+				LASSERT(net2 != LNET_NIDNET(LNET_NID_ANY));
 
 				if (net1 == net2) {
 					dup = 1;
@@ -1067,7 +1066,7 @@
 	lnet_free_text_bufs(&raw_entries);
 	lnet_free_text_bufs(&matched_nets);
 	lnet_free_text_bufs(&current_nets);
-	LASSERT (lnet_tbnob == 0);
+	LASSERT(lnet_tbnob == 0);
 
 	if (rc < 0)
 		return rc;
@@ -1083,7 +1082,7 @@
 }
 
 int
-lnet_ipaddr_enumerate (__u32 **ipaddrsp)
+lnet_ipaddr_enumerate(__u32 **ipaddrsp)
 {
 	int	up;
 	__u32      netmask;
@@ -1149,21 +1148,22 @@
 }
 
 int
-lnet_parse_ip2nets (char **networksp, char *ip2nets)
+lnet_parse_ip2nets(char **networksp, char *ip2nets)
 {
 	__u32     *ipaddrs;
 	int	nip = lnet_ipaddr_enumerate(&ipaddrs);
 	int	rc;
 
 	if (nip < 0) {
-		LCONSOLE_ERROR_MSG(0x117, "Error %d enumerating local IP "
-				   "interfaces for ip2nets to match\n", nip);
+		LCONSOLE_ERROR_MSG(0x117,
+				   "Error %d enumerating local IP interfaces for ip2nets to match\n",
+				   nip);
 		return nip;
 	}
 
 	if (nip == 0) {
-		LCONSOLE_ERROR_MSG(0x118, "No local IP interfaces "
-				   "for ip2nets to match\n");
+		LCONSOLE_ERROR_MSG(0x118,
+				   "No local IP interfaces for ip2nets to match\n");
 		return -ENOENT;
 	}
 
@@ -1176,8 +1176,8 @@
 	}
 
 	if (rc == 0) {
-		LCONSOLE_ERROR_MSG(0x11a, "ip2nets does not match "
-				   "any local IP interfaces\n");
+		LCONSOLE_ERROR_MSG(0x11a,
+				   "ip2nets does not match any local IP interfaces\n");
 		return -ENOENT;
 	}
 
@@ -1185,7 +1185,7 @@
 }
 
 int
-lnet_set_ip_niaddr (lnet_ni_t *ni)
+lnet_set_ip_niaddr(lnet_ni_t *ni)
 {
 	__u32  net = LNET_NIDNET(ni->ni_nid);
 	char **names;
@@ -1201,7 +1201,7 @@
 
 	if (ni->ni_interfaces[0] != NULL) {
 
-		CLASSERT (LNET_MAX_INTERFACES > 1);
+		CLASSERT(LNET_MAX_INTERFACES > 1);
 
 		if (ni->ni_interfaces[1] != NULL) {
 			CERROR("Net %s doesn't support multiple interfaces\n",
diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c
index 49b0f12..b6f8ad3 100644
--- a/drivers/staging/lustre/lnet/lnet/lib-move.c
+++ b/drivers/staging/lustre/lnet/lnet/lib-move.c
@@ -47,14 +47,14 @@
 		"Reserved");
 
 int
-lnet_fail_nid (lnet_nid_t nid, unsigned int threshold)
+lnet_fail_nid(lnet_nid_t nid, unsigned int threshold)
 {
 	lnet_test_peer_t  *tp;
 	struct list_head	*el;
 	struct list_head	*next;
 	struct list_head	 cull;
 
-	LASSERT (the_lnet.ln_init);
+	LASSERT(the_lnet.ln_init);
 
 	/* NB: use lnet_net_lock(0) to serialize operations on test peers */
 	if (threshold != 0) {
@@ -77,31 +77,30 @@
 
 	lnet_net_lock(0);
 
-	list_for_each_safe (el, next, &the_lnet.ln_test_peers) {
-		tp = list_entry (el, lnet_test_peer_t, tp_list);
+	list_for_each_safe(el, next, &the_lnet.ln_test_peers) {
+		tp = list_entry(el, lnet_test_peer_t, tp_list);
 
 		if (tp->tp_threshold == 0 ||    /* needs culling anyway */
 		    nid == LNET_NID_ANY ||       /* removing all entries */
-		    tp->tp_nid == nid)	  /* matched this one */
-		{
-			list_del (&tp->tp_list);
-			list_add (&tp->tp_list, &cull);
+		    tp->tp_nid == nid) {	  /* matched this one */
+			list_del(&tp->tp_list);
+			list_add(&tp->tp_list, &cull);
 		}
 	}
 
 	lnet_net_unlock(0);
 
-	while (!list_empty (&cull)) {
-		tp = list_entry (cull.next, lnet_test_peer_t, tp_list);
+	while (!list_empty(&cull)) {
+		tp = list_entry(cull.next, lnet_test_peer_t, tp_list);
 
-		list_del (&tp->tp_list);
-		LIBCFS_FREE(tp, sizeof (*tp));
+		list_del(&tp->tp_list);
+		LIBCFS_FREE(tp, sizeof(*tp));
 	}
 	return 0;
 }
 
 static int
-fail_peer (lnet_nid_t nid, int outgoing)
+fail_peer(lnet_nid_t nid, int outgoing)
 {
 	lnet_test_peer_t *tp;
 	struct list_head       *el;
@@ -109,13 +108,13 @@
 	struct list_head	cull;
 	int	       fail = 0;
 
-	INIT_LIST_HEAD (&cull);
+	INIT_LIST_HEAD(&cull);
 
 	/* NB: use lnet_net_lock(0) to serialize operations on test peers */
 	lnet_net_lock(0);
 
-	list_for_each_safe (el, next, &the_lnet.ln_test_peers) {
-		tp = list_entry (el, lnet_test_peer_t, tp_list);
+	list_for_each_safe(el, next, &the_lnet.ln_test_peers) {
+		tp = list_entry(el, lnet_test_peer_t, tp_list);
 
 		if (tp->tp_threshold == 0) {
 			/* zombie entry */
@@ -123,8 +122,8 @@
 				/* only cull zombies on outgoing tests,
 				 * since we may be at interrupt priority on
 				 * incoming messages. */
-				list_del (&tp->tp_list);
-				list_add (&tp->tp_list, &cull);
+				list_del(&tp->tp_list);
+				list_add(&tp->tp_list, &cull);
 			}
 			continue;
 		}
@@ -138,8 +137,8 @@
 				if (outgoing &&
 				    tp->tp_threshold == 0) {
 					/* see above */
-					list_del (&tp->tp_list);
-					list_add (&tp->tp_list, &cull);
+					list_del(&tp->tp_list);
+					list_add(&tp->tp_list, &cull);
 				}
 			}
 			break;
@@ -148,30 +147,30 @@
 
 	lnet_net_unlock(0);
 
-	while (!list_empty (&cull)) {
-		tp = list_entry (cull.next, lnet_test_peer_t, tp_list);
-		list_del (&tp->tp_list);
+	while (!list_empty(&cull)) {
+		tp = list_entry(cull.next, lnet_test_peer_t, tp_list);
+		list_del(&tp->tp_list);
 
-		LIBCFS_FREE(tp, sizeof (*tp));
+		LIBCFS_FREE(tp, sizeof(*tp));
 	}
 
-	return (fail);
+	return fail;
 }
 
 unsigned int
-lnet_iov_nob (unsigned int niov, struct iovec *iov)
+lnet_iov_nob(unsigned int niov, struct iovec *iov)
 {
 	unsigned int nob = 0;
 
 	while (niov-- > 0)
 		nob += (iov++)->iov_len;
 
-	return (nob);
+	return nob;
 }
 EXPORT_SYMBOL(lnet_iov_nob);
 
 void
-lnet_copy_iov2iov (unsigned int ndiov, struct iovec *diov, unsigned int doffset,
+lnet_copy_iov2iov(unsigned int ndiov, struct iovec *diov, unsigned int doffset,
 		   unsigned int nsiov, struct iovec *siov, unsigned int soffset,
 		   unsigned int nob)
 {
@@ -182,31 +181,31 @@
 		return;
 
 	/* skip complete frags before 'doffset' */
-	LASSERT (ndiov > 0);
+	LASSERT(ndiov > 0);
 	while (doffset >= diov->iov_len) {
 		doffset -= diov->iov_len;
 		diov++;
 		ndiov--;
-		LASSERT (ndiov > 0);
+		LASSERT(ndiov > 0);
 	}
 
 	/* skip complete frags before 'soffset' */
-	LASSERT (nsiov > 0);
+	LASSERT(nsiov > 0);
 	while (soffset >= siov->iov_len) {
 		soffset -= siov->iov_len;
 		siov++;
 		nsiov--;
-		LASSERT (nsiov > 0);
+		LASSERT(nsiov > 0);
 	}
 
 	do {
-		LASSERT (ndiov > 0);
-		LASSERT (nsiov > 0);
+		LASSERT(ndiov > 0);
+		LASSERT(nsiov > 0);
 		this_nob = MIN(diov->iov_len - doffset,
 			       siov->iov_len - soffset);
 		this_nob = MIN(this_nob, nob);
 
-		memcpy ((char *)diov->iov_base + doffset,
+		memcpy((char *)diov->iov_base + doffset,
 			(char *)siov->iov_base + soffset, this_nob);
 		nob -= this_nob;
 
@@ -230,7 +229,7 @@
 EXPORT_SYMBOL(lnet_copy_iov2iov);
 
 int
-lnet_extract_iov (int dst_niov, struct iovec *dst,
+lnet_extract_iov(int dst_niov, struct iovec *dst,
 		  int src_niov, struct iovec *src,
 		  unsigned int offset, unsigned int len)
 {
@@ -241,27 +240,27 @@
 	unsigned int    niov;
 
 	if (len == 0)			   /* no data => */
-		return (0);		     /* no frags */
+		return 0;		     /* no frags */
 
-	LASSERT (src_niov > 0);
+	LASSERT(src_niov > 0);
 	while (offset >= src->iov_len) {      /* skip initial frags */
 		offset -= src->iov_len;
 		src_niov--;
 		src++;
-		LASSERT (src_niov > 0);
+		LASSERT(src_niov > 0);
 	}
 
 	niov = 1;
 	for (;;) {
-		LASSERT (src_niov > 0);
-		LASSERT ((int)niov <= dst_niov);
+		LASSERT(src_niov > 0);
+		LASSERT((int)niov <= dst_niov);
 
 		frag_len = src->iov_len - offset;
 		dst->iov_base = ((char *)src->iov_base) + offset;
 
 		if (len <= frag_len) {
 			dst->iov_len = len;
-			return (niov);
+			return niov;
 		}
 
 		dst->iov_len = frag_len;
@@ -278,21 +277,21 @@
 
 
 unsigned int
-lnet_kiov_nob (unsigned int niov, lnet_kiov_t *kiov)
+lnet_kiov_nob(unsigned int niov, lnet_kiov_t *kiov)
 {
 	unsigned int  nob = 0;
 
 	while (niov-- > 0)
 		nob += (kiov++)->kiov_len;
 
-	return (nob);
+	return nob;
 }
 EXPORT_SYMBOL(lnet_kiov_nob);
 
 void
-lnet_copy_kiov2kiov (unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset,
-		     unsigned int nsiov, lnet_kiov_t *siov, unsigned int soffset,
-		     unsigned int nob)
+lnet_copy_kiov2kiov(unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset,
+		    unsigned int nsiov, lnet_kiov_t *siov, unsigned int soffset,
+		    unsigned int nob)
 {
 	/* NB diov, siov are READ-ONLY */
 	unsigned int    this_nob;
@@ -302,27 +301,27 @@
 	if (nob == 0)
 		return;
 
-	LASSERT (!in_interrupt ());
+	LASSERT(!in_interrupt());
 
-	LASSERT (ndiov > 0);
+	LASSERT(ndiov > 0);
 	while (doffset >= diov->kiov_len) {
 		doffset -= diov->kiov_len;
 		diov++;
 		ndiov--;
-		LASSERT (ndiov > 0);
+		LASSERT(ndiov > 0);
 	}
 
-	LASSERT (nsiov > 0);
+	LASSERT(nsiov > 0);
 	while (soffset >= siov->kiov_len) {
 		soffset -= siov->kiov_len;
 		siov++;
 		nsiov--;
-		LASSERT (nsiov > 0);
+		LASSERT(nsiov > 0);
 	}
 
 	do {
-		LASSERT (ndiov > 0);
-		LASSERT (nsiov > 0);
+		LASSERT(ndiov > 0);
+		LASSERT(nsiov > 0);
 		this_nob = MIN(diov->kiov_len - doffset,
 			       siov->kiov_len - soffset);
 		this_nob = MIN(this_nob, nob);
@@ -338,7 +337,7 @@
 		 * However in practice at least one of the kiovs will be mapped
 		 * kernel pages and the map/unmap will be NOOPs */
 
-		memcpy (daddr, saddr, this_nob);
+		memcpy(daddr, saddr, this_nob);
 		nob -= this_nob;
 
 		if (diov->kiov_len > doffset + this_nob) {
@@ -372,9 +371,9 @@
 EXPORT_SYMBOL(lnet_copy_kiov2kiov);
 
 void
-lnet_copy_kiov2iov (unsigned int niov, struct iovec *iov, unsigned int iovoffset,
-		    unsigned int nkiov, lnet_kiov_t *kiov, unsigned int kiovoffset,
-		    unsigned int nob)
+lnet_copy_kiov2iov(unsigned int niov, struct iovec *iov, unsigned int iovoffset,
+		   unsigned int nkiov, lnet_kiov_t *kiov,
+		   unsigned int kiovoffset, unsigned int nob)
 {
 	/* NB iov, kiov are READ-ONLY */
 	unsigned int    this_nob;
@@ -383,27 +382,27 @@
 	if (nob == 0)
 		return;
 
-	LASSERT (!in_interrupt ());
+	LASSERT(!in_interrupt());
 
-	LASSERT (niov > 0);
+	LASSERT(niov > 0);
 	while (iovoffset >= iov->iov_len) {
 		iovoffset -= iov->iov_len;
 		iov++;
 		niov--;
-		LASSERT (niov > 0);
+		LASSERT(niov > 0);
 	}
 
-	LASSERT (nkiov > 0);
+	LASSERT(nkiov > 0);
 	while (kiovoffset >= kiov->kiov_len) {
 		kiovoffset -= kiov->kiov_len;
 		kiov++;
 		nkiov--;
-		LASSERT (nkiov > 0);
+		LASSERT(nkiov > 0);
 	}
 
 	do {
-		LASSERT (niov > 0);
-		LASSERT (nkiov > 0);
+		LASSERT(niov > 0);
+		LASSERT(nkiov > 0);
 		this_nob = MIN(iov->iov_len - iovoffset,
 			       kiov->kiov_len - kiovoffset);
 		this_nob = MIN(this_nob, nob);
@@ -412,7 +411,7 @@
 			addr = ((char *)kmap(kiov->kiov_page)) +
 				kiov->kiov_offset + kiovoffset;
 
-		memcpy ((char *)iov->iov_base + iovoffset, addr, this_nob);
+		memcpy((char *)iov->iov_base + iovoffset, addr, this_nob);
 		nob -= this_nob;
 
 		if (iov->iov_len > iovoffset + this_nob) {
@@ -442,9 +441,10 @@
 EXPORT_SYMBOL(lnet_copy_kiov2iov);
 
 void
-lnet_copy_iov2kiov (unsigned int nkiov, lnet_kiov_t *kiov, unsigned int kiovoffset,
-		    unsigned int niov, struct iovec *iov, unsigned int iovoffset,
-		    unsigned int nob)
+lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov,
+		   unsigned int kiovoffset, unsigned int niov,
+		   struct iovec *iov, unsigned int iovoffset,
+		   unsigned int nob)
 {
 	/* NB kiov, iov are READ-ONLY */
 	unsigned int    this_nob;
@@ -453,27 +453,27 @@
 	if (nob == 0)
 		return;
 
-	LASSERT (!in_interrupt ());
+	LASSERT(!in_interrupt());
 
-	LASSERT (nkiov > 0);
+	LASSERT(nkiov > 0);
 	while (kiovoffset >= kiov->kiov_len) {
 		kiovoffset -= kiov->kiov_len;
 		kiov++;
 		nkiov--;
-		LASSERT (nkiov > 0);
+		LASSERT(nkiov > 0);
 	}
 
-	LASSERT (niov > 0);
+	LASSERT(niov > 0);
 	while (iovoffset >= iov->iov_len) {
 		iovoffset -= iov->iov_len;
 		iov++;
 		niov--;
-		LASSERT (niov > 0);
+		LASSERT(niov > 0);
 	}
 
 	do {
-		LASSERT (nkiov > 0);
-		LASSERT (niov > 0);
+		LASSERT(nkiov > 0);
+		LASSERT(niov > 0);
 		this_nob = MIN(kiov->kiov_len - kiovoffset,
 			       iov->iov_len - iovoffset);
 		this_nob = MIN(this_nob, nob);
@@ -482,7 +482,7 @@
 			addr = ((char *)kmap(kiov->kiov_page)) +
 				kiov->kiov_offset + kiovoffset;
 
-		memcpy (addr, (char *)iov->iov_base + iovoffset, this_nob);
+		memcpy(addr, (char *)iov->iov_base + iovoffset, this_nob);
 		nob -= this_nob;
 
 		if (kiov->kiov_len > kiovoffset + this_nob) {
@@ -511,7 +511,7 @@
 EXPORT_SYMBOL(lnet_copy_iov2kiov);
 
 int
-lnet_extract_kiov (int dst_niov, lnet_kiov_t *dst,
+lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst,
 		   int src_niov, lnet_kiov_t *src,
 		   unsigned int offset, unsigned int len)
 {
@@ -522,20 +522,20 @@
 	unsigned int    niov;
 
 	if (len == 0)			   /* no data => */
-		return (0);		     /* no frags */
+		return 0;		     /* no frags */
 
-	LASSERT (src_niov > 0);
+	LASSERT(src_niov > 0);
 	while (offset >= src->kiov_len) {      /* skip initial frags */
 		offset -= src->kiov_len;
 		src_niov--;
 		src++;
-		LASSERT (src_niov > 0);
+		LASSERT(src_niov > 0);
 	}
 
 	niov = 1;
 	for (;;) {
-		LASSERT (src_niov > 0);
-		LASSERT ((int)niov <= dst_niov);
+		LASSERT(src_niov > 0);
+		LASSERT((int)niov <= dst_niov);
 
 		frag_len = src->kiov_len - offset;
 		dst->kiov_page = src->kiov_page;
@@ -543,12 +543,13 @@
 
 		if (len <= frag_len) {
 			dst->kiov_len = len;
-			LASSERT (dst->kiov_offset + dst->kiov_len <= PAGE_CACHE_SIZE);
-			return (niov);
+			LASSERT(dst->kiov_offset + dst->kiov_len
+					     <= PAGE_CACHE_SIZE);
+			return niov;
 		}
 
 		dst->kiov_len = frag_len;
-		LASSERT (dst->kiov_offset + dst->kiov_len <= PAGE_CACHE_SIZE);
+		LASSERT(dst->kiov_offset + dst->kiov_len <= PAGE_CACHE_SIZE);
 
 		len -= frag_len;
 		dst++;
@@ -569,8 +570,8 @@
 	lnet_kiov_t  *kiov = NULL;
 	int	   rc;
 
-	LASSERT (!in_interrupt ());
-	LASSERT (mlen == 0 || msg != NULL);
+	LASSERT(!in_interrupt());
+	LASSERT(mlen == 0 || msg != NULL);
 
 	if (msg != NULL) {
 		LASSERT(msg->msg_receiving);
@@ -587,8 +588,8 @@
 			iov  = msg->msg_iov;
 			kiov = msg->msg_kiov;
 
-			LASSERT (niov > 0);
-			LASSERT ((iov == NULL) != (kiov == NULL));
+			LASSERT(niov > 0);
+			LASSERT((iov == NULL) != (kiov == NULL));
 		}
 	}
 
@@ -603,12 +604,12 @@
 {
 	lnet_libmd_t *md = msg->msg_md;
 
-	LASSERT (msg->msg_len > 0);
-	LASSERT (!msg->msg_routing);
-	LASSERT (md != NULL);
-	LASSERT (msg->msg_niov == 0);
-	LASSERT (msg->msg_iov == NULL);
-	LASSERT (msg->msg_kiov == NULL);
+	LASSERT(msg->msg_len > 0);
+	LASSERT(!msg->msg_routing);
+	LASSERT(md != NULL);
+	LASSERT(msg->msg_niov == 0);
+	LASSERT(msg->msg_iov == NULL);
+	LASSERT(msg->msg_kiov == NULL);
 
 	msg->msg_niov = md->md_niov;
 	if ((md->md_options & LNET_MD_KIOV) != 0)
@@ -629,7 +630,7 @@
 	if (len != 0)
 		lnet_setpayloadbuffer(msg);
 
-	memset (&msg->msg_hdr, 0, sizeof (msg->msg_hdr));
+	memset(&msg->msg_hdr, 0, sizeof(msg->msg_hdr));
 	msg->msg_hdr.type	   = cpu_to_le32(type);
 	msg->msg_hdr.dest_nid       = cpu_to_le64(target.nid);
 	msg->msg_hdr.dest_pid       = cpu_to_le32(target.pid);
@@ -644,8 +645,8 @@
 	void   *priv = msg->msg_private;
 	int     rc;
 
-	LASSERT (!in_interrupt ());
-	LASSERT (LNET_NETTYP(LNET_NIDNET(ni->ni_nid)) == LOLND ||
+	LASSERT(!in_interrupt());
+	LASSERT(LNET_NETTYP(LNET_NIDNET(ni->ni_nid)) == LOLND ||
 		 (msg->msg_txcredit && msg->msg_peertxcredit));
 
 	rc = (ni->ni_lnd->lnd_send)(ni, priv, msg);
@@ -698,12 +699,12 @@
 
 /* NB: always called with lnet_net_lock held */
 static inline int
-lnet_peer_is_alive (lnet_peer_t *lp, cfs_time_t now)
+lnet_peer_is_alive(lnet_peer_t *lp, cfs_time_t now)
 {
 	int	alive;
 	cfs_time_t deadline;
 
-	LASSERT (lnet_peer_aliveness_enabled(lp));
+	LASSERT(lnet_peer_aliveness_enabled(lp));
 
 	/* Trust lnet_notify() if it has more recent aliveness news, but
 	 * ignore the initial assumed death (see lnet_peers_start_down()).
@@ -731,7 +732,7 @@
 /* NB: returns 1 when alive, 0 when dead, negative when error;
  *     may drop the lnet_net_lock */
 int
-lnet_peer_alive_locked (lnet_peer_t *lp)
+lnet_peer_alive_locked(lnet_peer_t *lp)
 {
 	cfs_time_t now = cfs_time_current();
 
@@ -809,7 +810,7 @@
 	}
 
 	if (!msg->msg_peertxcredit) {
-		LASSERT ((lp->lp_txcredits < 0) ==
+		LASSERT((lp->lp_txcredits < 0) ==
 			 !list_empty(&lp->lp_txq));
 
 		msg->msg_peertxcredit = 1;
@@ -873,7 +874,7 @@
 }
 
 int
-lnet_post_routed_recv_locked (lnet_msg_t *msg, int do_recv)
+lnet_post_routed_recv_locked(lnet_msg_t *msg, int do_recv)
 {
 	/* lnet_parse is going to lnet_net_unlock immediately after this, so it
 	 * sets do_recv FALSE and I don't do the unlock/send/lock bit.  I
@@ -882,18 +883,18 @@
 	lnet_rtrbufpool_t   *rbp;
 	lnet_rtrbuf_t       *rb;
 
-	LASSERT (msg->msg_iov == NULL);
-	LASSERT (msg->msg_kiov == NULL);
-	LASSERT (msg->msg_niov == 0);
-	LASSERT (msg->msg_routing);
-	LASSERT (msg->msg_receiving);
-	LASSERT (!msg->msg_sending);
+	LASSERT(msg->msg_iov == NULL);
+	LASSERT(msg->msg_kiov == NULL);
+	LASSERT(msg->msg_niov == 0);
+	LASSERT(msg->msg_routing);
+	LASSERT(msg->msg_receiving);
+	LASSERT(!msg->msg_sending);
 
 	/* non-lnet_parse callers only receive delayed messages */
 	LASSERT(!do_recv || msg->msg_rx_delayed);
 
 	if (!msg->msg_peerrtrcredit) {
-		LASSERT ((lp->lp_rtrcredits < 0) ==
+		LASSERT((lp->lp_rtrcredits < 0) ==
 			 !list_empty(&lp->lp_rtrq));
 
 		msg->msg_peerrtrcredit = 1;
@@ -913,7 +914,7 @@
 	rbp = lnet_msg2bufpool(msg);
 
 	if (!msg->msg_rtrcredit) {
-		LASSERT ((rbp->rbp_credits < 0) ==
+		LASSERT((rbp->rbp_credits < 0) ==
 			 !list_empty(&rbp->rbp_msgs));
 
 		msg->msg_rtrcredit = 1;
@@ -930,7 +931,7 @@
 		}
 	}
 
-	LASSERT (!list_empty(&rbp->rbp_bufs));
+	LASSERT(!list_empty(&rbp->rbp_bufs));
 	rb = list_entry(rbp->rbp_bufs.next, lnet_rtrbuf_t, rb_list);
 	list_del(&rb->rb_list);
 
@@ -985,7 +986,7 @@
 			!list_empty(&txpeer->lp_txq));
 
 		txpeer->lp_txqnob -= msg->msg_len + sizeof(lnet_hdr_t);
-		LASSERT (txpeer->lp_txqnob >= 0);
+		LASSERT(txpeer->lp_txqnob >= 0);
 
 		txpeer->lp_txcredits++;
 		if (txpeer->lp_txcredits <= 0) {
@@ -1020,11 +1021,11 @@
 		/* NB If a msg ever blocks for a buffer in rbp_msgs, it stays
 		 * there until it gets one allocated, or aborts the wait
 		 * itself */
-		LASSERT (msg->msg_kiov != NULL);
+		LASSERT(msg->msg_kiov != NULL);
 
 		rb = list_entry(msg->msg_kiov, lnet_rtrbuf_t, rb_kiov[0]);
 		rbp = rb->rb_pool;
-		LASSERT (rbp == lnet_msg2bufpool(msg));
+		LASSERT(rbp == lnet_msg2bufpool(msg));
 
 		msg->msg_kiov = NULL;
 		msg->msg_rtrcredit = 0;
@@ -1172,10 +1173,10 @@
 	 * but we might want to use pre-determined router for ACK/REPLY
 	 * in the future */
 	/* NB: ni != NULL == interface pre-determined (ACK/REPLY) */
-	LASSERT (msg->msg_txpeer == NULL);
-	LASSERT (!msg->msg_sending);
-	LASSERT (!msg->msg_target_is_router);
-	LASSERT (!msg->msg_receiving);
+	LASSERT(msg->msg_txpeer == NULL);
+	LASSERT(!msg->msg_sending);
+	LASSERT(!msg->msg_target_is_router);
+	LASSERT(!msg->msg_receiving);
 
 	msg->msg_sending = 1;
 
@@ -1200,7 +1201,7 @@
 				      libcfs_nid2str(src_nid));
 			return -EINVAL;
 		}
-		LASSERT (!msg->msg_routing);
+		LASSERT(!msg->msg_routing);
 	}
 
 	/* Is this for someone on a local network? */
@@ -1249,7 +1250,7 @@
 			/* ENOMEM or shutting down */
 			return rc;
 		}
-		LASSERT (lp->lp_ni == src_ni);
+		LASSERT(lp->lp_ni == src_ni);
 	} else {
 		/* sending to a remote network */
 		lp = lnet_find_route_locked(src_ni, dst_nid, rtr_nid);
@@ -1290,7 +1291,7 @@
 			src_ni = lp->lp_ni;
 			src_nid = src_ni->ni_nid;
 		} else {
-			LASSERT (src_ni == lp->lp_ni);
+			LASSERT(src_ni == lp->lp_ni);
 			lnet_ni_decref_locked(src_ni, cpt);
 		}
 
@@ -1311,9 +1312,9 @@
 
 	/* 'lp' is our best choice of peer */
 
-	LASSERT (!msg->msg_peertxcredit);
-	LASSERT (!msg->msg_txcredit);
-	LASSERT (msg->msg_txpeer == NULL);
+	LASSERT(!msg->msg_peertxcredit);
+	LASSERT(!msg->msg_txcredit);
+	LASSERT(msg->msg_txpeer == NULL);
 
 	msg->msg_txpeer = lp;		   /* msg takes my ref on lp */
 
@@ -1509,7 +1510,7 @@
 		return ENOENT;		  /* +ve: OK but no match */
 	}
 
-	LASSERT (md->md_offset == 0);
+	LASSERT(md->md_offset == 0);
 
 	rlength = hdr->payload_length;
 	mlength = MIN(rlength, (int)md->md_length);
@@ -1614,31 +1615,31 @@
 }
 
 char *
-lnet_msgtyp2str (int type)
+lnet_msgtyp2str(int type)
 {
 	switch (type) {
 	case LNET_MSG_ACK:
-		return ("ACK");
+		return "ACK";
 	case LNET_MSG_PUT:
-		return ("PUT");
+		return "PUT";
 	case LNET_MSG_GET:
-		return ("GET");
+		return "GET";
 	case LNET_MSG_REPLY:
-		return ("REPLY");
+		return "REPLY";
 	case LNET_MSG_HELLO:
-		return ("HELLO");
+		return "HELLO";
 	default:
-		return ("<UNKNOWN>");
+		return "<UNKNOWN>";
 	}
 }
 EXPORT_SYMBOL(lnet_msgtyp2str);
 
 void
-lnet_print_hdr(lnet_hdr_t * hdr)
+lnet_print_hdr(lnet_hdr_t *hdr)
 {
 	lnet_process_id_t src = {0};
 	lnet_process_id_t dst = {0};
-	char *type_str = lnet_msgtyp2str (hdr->type);
+	char *type_str = lnet_msgtyp2str(hdr->type);
 
 	src.nid = hdr->src_nid;
 	src.pid = hdr->src_pid;
@@ -1709,7 +1710,7 @@
 	__u32	  payload_length;
 	__u32	  type;
 
-	LASSERT (!in_interrupt ());
+	LASSERT(!in_interrupt());
 
 	type = le32_to_cpu(hdr->type);
 	src_nid = le64_to_cpu(hdr->src_nid);
@@ -1734,7 +1735,8 @@
 
 	case LNET_MSG_PUT:
 	case LNET_MSG_REPLY:
-		if (payload_length > (__u32)(for_me ? LNET_MAX_PAYLOAD : LNET_MTU)) {
+		if (payload_length >
+		   (__u32)(for_me ? LNET_MAX_PAYLOAD : LNET_MTU)) {
 			CERROR("%s, src %s: bad %s payload %d "
 			       "(%d max expected)\n",
 			       libcfs_nid2str(from_nid),
@@ -1772,7 +1774,7 @@
 	if (!for_me) {
 		if (LNET_NIDNET(dest_nid) == LNET_NIDNET(ni->ni_nid)) {
 			/* should have gone direct */
-			CERROR ("%s, src %s: Bad dest nid %s "
+			CERROR("%s, src %s: Bad dest nid %s "
 				"(should have been sent direct)\n",
 				libcfs_nid2str(from_nid),
 				libcfs_nid2str(src_nid),
@@ -1783,7 +1785,7 @@
 		if (lnet_islocalnid(dest_nid)) {
 			/* dest is another local NI; sender should have used
 			 * this node's NID on its own network */
-			CERROR ("%s, src %s: Bad dest nid %s "
+			CERROR("%s, src %s: Bad dest nid %s "
 				"(it's my nid but on a different network)\n",
 				libcfs_nid2str(from_nid),
 				libcfs_nid2str(src_nid),
@@ -1792,7 +1794,7 @@
 		}
 
 		if (rdma_req && type == LNET_MSG_GET) {
-			CERROR ("%s, src %s: Bad optimized GET for %s "
+			CERROR("%s, src %s: Bad optimized GET for %s "
 				"(final destination must be me)\n",
 				libcfs_nid2str(from_nid),
 				libcfs_nid2str(src_nid),
@@ -1801,7 +1803,7 @@
 		}
 
 		if (!the_lnet.ln_routing) {
-			CERROR ("%s, src %s: Dropping message for %s "
+			CERROR("%s, src %s: Dropping message for %s "
 				"(routing not enabled)\n",
 				libcfs_nid2str(from_nid),
 				libcfs_nid2str(src_nid),
@@ -1813,9 +1815,8 @@
 	/* Message looks OK; we're not going to return an error, so we MUST
 	 * call back lnd_recv() come what may... */
 
-	if (!list_empty (&the_lnet.ln_test_peers) && /* normally we don't */
-	    fail_peer (src_nid, 0))	     /* shall we now? */
-	{
+	if (!list_empty(&the_lnet.ln_test_peers) && /* normally we don't */
+	    fail_peer(src_nid, 0)) {	     /* shall we now? */
 		CERROR("%s, src %s: Dropping %s to simulate failure\n",
 		       libcfs_nid2str(from_nid), libcfs_nid2str(src_nid),
 		       lnet_msgtyp2str(type));
@@ -1830,7 +1831,9 @@
 		goto drop;
 	}
 
-	/* msg zeroed in lnet_msg_alloc; i.e. flags all clear, pointers NULL etc */
+	/* msg zeroed in lnet_msg_alloc;
+	 * i.e. flags all clear, pointers NULL etc
+	 */
 
 	msg->msg_type = type;
 	msg->msg_private = private;
@@ -1906,7 +1909,7 @@
 	if (rc == 0)
 		return 0;
 
-	LASSERT (rc == ENOENT);
+	LASSERT(rc == ENOENT);
 
  free_drop:
 	LASSERT(msg->msg_md == NULL);
@@ -2047,12 +2050,11 @@
 	int			cpt;
 	int			rc;
 
-	LASSERT (the_lnet.ln_init);
-	LASSERT (the_lnet.ln_refcount > 0);
+	LASSERT(the_lnet.ln_init);
+	LASSERT(the_lnet.ln_refcount > 0);
 
-	if (!list_empty (&the_lnet.ln_test_peers) && /* normally we don't */
-	    fail_peer (target.nid, 1))	  /* shall we now? */
-	{
+	if (!list_empty(&the_lnet.ln_test_peers) && /* normally we don't */
+	    fail_peer(target.nid, 1)) { /* shall we now? */
 		CERROR("Dropping PUT to %s: simulated failure\n",
 		       libcfs_id2str(target));
 		return -EIO;
@@ -2113,9 +2115,9 @@
 
 	rc = lnet_send(self, msg, LNET_NID_ANY);
 	if (rc != 0) {
-		CNETERR( "Error sending PUT to %s: %d\n",
+		CNETERR("Error sending PUT to %s: %d\n",
 		       libcfs_id2str(target), rc);
-		lnet_finalize (NULL, msg, rc);
+		lnet_finalize(NULL, msg, rc);
 	}
 
 	/* completion will be signalled by an event */
@@ -2124,7 +2126,7 @@
 EXPORT_SYMBOL(LNetPut);
 
 lnet_msg_t *
-lnet_create_reply_msg (lnet_ni_t *ni, lnet_msg_t *getmsg)
+lnet_create_reply_msg(lnet_ni_t *ni, lnet_msg_t *getmsg)
 {
 	/* The LND can DMA direct to the GET md (i.e. no REPLY msg).  This
 	 * returns a msg for the LND to pass to lnet_finalize() when the sink
@@ -2144,16 +2146,16 @@
 	cpt = lnet_cpt_of_cookie(getmd->md_lh.lh_cookie);
 	lnet_res_lock(cpt);
 
-	LASSERT (getmd->md_refcount > 0);
+	LASSERT(getmd->md_refcount > 0);
 
 	if (msg == NULL) {
-		CERROR ("%s: Dropping REPLY from %s: can't allocate msg\n",
+		CERROR("%s: Dropping REPLY from %s: can't allocate msg\n",
 			libcfs_nid2str(ni->ni_nid), libcfs_id2str(peer_id));
 		goto drop;
 	}
 
 	if (getmd->md_threshold == 0) {
-		CERROR ("%s: Dropping REPLY from %s for inactive MD %p\n",
+		CERROR("%s: Dropping REPLY from %s for inactive MD %p\n",
 			libcfs_nid2str(ni->ni_nid), libcfs_id2str(peer_id),
 			getmd);
 		lnet_res_unlock(cpt);
@@ -2205,13 +2207,13 @@
 {
 	/* Set the REPLY length, now the RDMA that elides the REPLY message has
 	 * completed and I know it. */
-	LASSERT (reply != NULL);
-	LASSERT (reply->msg_type == LNET_MSG_GET);
-	LASSERT (reply->msg_ev.type == LNET_EVENT_REPLY);
+	LASSERT(reply != NULL);
+	LASSERT(reply->msg_type == LNET_MSG_GET);
+	LASSERT(reply->msg_ev.type == LNET_EVENT_REPLY);
 
 	/* NB I trusted my peer to RDMA.  If she tells me she's written beyond
 	 * the end of my buffer, I might as well be dead. */
-	LASSERT (len <= reply->msg_ev.mlength);
+	LASSERT(len <= reply->msg_ev.mlength);
 
 	reply->msg_ev.mlength = len;
 }
@@ -2229,7 +2231,8 @@
  *
  * \param self,target,portal,match_bits,offset See the discussion in LNetPut().
  * \param mdh A handle for the MD that describes the memory into which the
- * requested data will be received. The MD must be "free floating" (See LNetMDBind()).
+ * requested data will be received. The MD must be "free floating"
+ * (See LNetMDBind()).
  *
  * \retval  0      Success, and only in this case events will be generated
  * and logged to EQ (if it exists) of the MD.
@@ -2247,12 +2250,11 @@
 	int			cpt;
 	int			rc;
 
-	LASSERT (the_lnet.ln_init);
-	LASSERT (the_lnet.ln_refcount > 0);
+	LASSERT(the_lnet.ln_init);
+	LASSERT(the_lnet.ln_refcount > 0);
 
-	if (!list_empty (&the_lnet.ln_test_peers) && /* normally we don't */
-	    fail_peer (target.nid, 1))	  /* shall we now? */
-	{
+	if (!list_empty(&the_lnet.ln_test_peers) && /* normally we don't */
+	    fail_peer(target.nid, 1)) {	  /* shall we now? */
 		CERROR("Dropping GET to %s: simulated failure\n",
 		       libcfs_id2str(target));
 		return -EIO;
@@ -2307,9 +2309,9 @@
 
 	rc = lnet_send(self, msg, LNET_NID_ANY);
 	if (rc < 0) {
-		CNETERR( "Error sending GET to %s: %d\n",
+		CNETERR("Error sending GET to %s: %d\n",
 		       libcfs_id2str(target), rc);
-		lnet_finalize (NULL, msg, rc);
+		lnet_finalize(NULL, msg, rc);
 	}
 
 	/* completion will be signalled by an event */
@@ -2348,12 +2350,12 @@
 	 * keep order 0 free for 0@lo and order 1 free for a local NID
 	 * match */
 
-	LASSERT (the_lnet.ln_init);
-	LASSERT (the_lnet.ln_refcount > 0);
+	LASSERT(the_lnet.ln_init);
+	LASSERT(the_lnet.ln_refcount > 0);
 
 	cpt = lnet_net_lock_current();
 
-	list_for_each (e, &the_lnet.ln_nis) {
+	list_for_each(e, &the_lnet.ln_nis) {
 		ni = list_entry(e, lnet_ni_t, ni_list);
 
 		if (ni->ni_nid == dstnid) {
@@ -2390,7 +2392,7 @@
 			lnet_route_t *route;
 			lnet_route_t *shortest = NULL;
 
-			LASSERT (!list_empty(&rnet->lrn_routes));
+			LASSERT(!list_empty(&rnet->lrn_routes));
 
 			list_for_each_entry(route, &rnet->lrn_routes,
 						lr_list) {
@@ -2399,7 +2401,7 @@
 					shortest = route;
 			}
 
-			LASSERT (shortest != NULL);
+			LASSERT(shortest != NULL);
 			hops = shortest->lr_hops;
 			if (srcnidp != NULL)
 				*srcnidp = shortest->lr_gateway->lp_ni->ni_nid;
diff --git a/drivers/staging/lustre/lnet/lnet/lo.c b/drivers/staging/lustre/lnet/lnet/lo.c
index 670dae3..efc798e 100644
--- a/drivers/staging/lustre/lnet/lnet/lo.c
+++ b/drivers/staging/lustre/lnet/lnet/lo.c
@@ -36,16 +36,16 @@
 #include <linux/lnet/lib-lnet.h>
 
 int
-lolnd_send (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg)
+lolnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg)
 {
-	LASSERT (!lntmsg->msg_routing);
-	LASSERT (!lntmsg->msg_target_is_router);
+	LASSERT(!lntmsg->msg_routing);
+	LASSERT(!lntmsg->msg_target_is_router);
 
 	return lnet_parse(ni, &lntmsg->msg_hdr, ni->ni_nid, lntmsg, 0);
 }
 
 int
-lolnd_recv (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg,
+lolnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg,
 	    int delayed, unsigned int niov,
 	    struct iovec *iov, lnet_kiov_t *kiov,
 	    unsigned int offset, unsigned int mlen, unsigned int rlen)
@@ -89,20 +89,20 @@
 void
 lolnd_shutdown(lnet_ni_t *ni)
 {
-	CDEBUG (D_NET, "shutdown\n");
-	LASSERT (lolnd_instanced);
+	CDEBUG(D_NET, "shutdown\n");
+	LASSERT(lolnd_instanced);
 
 	lolnd_instanced = 0;
 }
 
 int
-lolnd_startup (lnet_ni_t *ni)
+lolnd_startup(lnet_ni_t *ni)
 {
-	LASSERT (ni->ni_lnd == &the_lolnd);
-	LASSERT (!lolnd_instanced);
+	LASSERT(ni->ni_lnd == &the_lolnd);
+	LASSERT(!lolnd_instanced);
 	lolnd_instanced = 1;
 
-	return (0);
+	return 0;
 }
 
 lnd_t the_lolnd = {
diff --git a/drivers/staging/lustre/lnet/lnet/module.c b/drivers/staging/lustre/lnet/lnet/module.c
index afb8175..6db8774 100644
--- a/drivers/staging/lustre/lnet/lnet/module.c
+++ b/drivers/staging/lustre/lnet/lnet/module.c
@@ -37,14 +37,14 @@
 #define DEBUG_SUBSYSTEM S_LNET
 #include <linux/lnet/lib-lnet.h>
 
-static int config_on_load = 0;
+static int config_on_load;
 CFS_MODULE_PARM(config_on_load, "i", int, 0444,
 		"configure network at module load");
 
 static struct mutex lnet_config_mutex;
 
 int
-lnet_configure (void *arg)
+lnet_configure(void *arg)
 {
 	/* 'arg' only there so I can be passed to cfs_create_thread() */
 	int    rc = 0;
@@ -64,7 +64,7 @@
 }
 
 int
-lnet_unconfigure (void)
+lnet_unconfigure(void)
 {
 	int   refcount;
 
@@ -124,7 +124,7 @@
 	}
 
 	rc = libcfs_register_ioctl(&lnet_ioctl_handler);
-	LASSERT (rc == 0);
+	LASSERT(rc == 0);
 
 	if (config_on_load) {
 		/* Have to schedule a separate thread to avoid deadlocking
@@ -141,7 +141,7 @@
 	int rc;
 
 	rc = libcfs_deregister_ioctl(&lnet_ioctl_handler);
-	LASSERT (rc == 0);
+	LASSERT(rc == 0);
 
 	LNetFini();
 }
diff --git a/drivers/staging/lustre/lnet/lnet/router_proc.c b/drivers/staging/lustre/lnet/lnet/router_proc.c
index 931f6ca2..5e47de3 100644
--- a/drivers/staging/lustre/lnet/lnet/router_proc.c
+++ b/drivers/staging/lustre/lnet/lnet/router_proc.c
@@ -30,7 +30,7 @@
 /* This is really lnet_proc.c. You might need to update sanity test 215
  * if any file format is changed. */
 
-static ctl_table_header_t *lnet_table_header = NULL;
+static ctl_table_header_t *lnet_table_header;
 
 #define CTL_LNET	 (0x100)
 enum {
@@ -158,7 +158,7 @@
 	off = LNET_PROC_HOFF_GET(*ppos);
 	ver = LNET_PROC_VER_GET(*ppos);
 
-	LASSERT (!write);
+	LASSERT(!write);
 
 	if (*lenp == 0)
 		return 0;
@@ -172,11 +172,11 @@
 	if (*ppos == 0) {
 		s += snprintf(s, tmpstr + tmpsiz - s, "Routing %s\n",
 			      the_lnet.ln_routing ? "enabled" : "disabled");
-		LASSERT (tmpstr + tmpsiz - s > 0);
+		LASSERT(tmpstr + tmpsiz - s > 0);
 
 		s += snprintf(s, tmpstr + tmpsiz - s, "%-8s %4s %7s %s\n",
 			      "net", "hops", "state", "router");
-		LASSERT (tmpstr + tmpsiz - s > 0);
+		LASSERT(tmpstr + tmpsiz - s > 0);
 
 		lnet_net_lock(0);
 		ver = (unsigned int)the_lnet.ln_remote_nets_version;
@@ -281,7 +281,7 @@
 	off = LNET_PROC_HOFF_GET(*ppos);
 	ver = LNET_PROC_VER_GET(*ppos);
 
-	LASSERT (!write);
+	LASSERT(!write);
 
 	if (*lenp == 0)
 		return 0;
@@ -375,7 +375,7 @@
 					      pingsent,
 					      cfs_duration_sec(cfs_time_sub(deadline, now)),
 					      down_ni, libcfs_nid2str(nid));
-			LASSERT (tmpstr + tmpsiz - s > 0);
+			LASSERT(tmpstr + tmpsiz - s > 0);
 		}
 
 		lnet_net_unlock(0);
@@ -437,7 +437,7 @@
 			      "%-24s %4s %5s %5s %5s %5s %5s %5s %5s %s\n",
 			      "nid", "refs", "state", "last", "max",
 			      "rtr", "min", "tx", "min", "queue");
-		LASSERT (tmpstr + tmpsiz - s > 0);
+		LASSERT(tmpstr + tmpsiz - s > 0);
 
 		hoff++;
 	} else {
@@ -534,7 +534,7 @@
 				      libcfs_nid2str(nid), nrefs, aliveness,
 				      lastalive, maxcr, rtrcr, minrtrcr, txcr,
 				      mintxcr, txqnob);
-			LASSERT (tmpstr + tmpsiz - s > 0);
+			LASSERT(tmpstr + tmpsiz - s > 0);
 
 		} else { /* peer is NULL */
 			lnet_net_unlock(cpt);
@@ -592,7 +592,7 @@
 	s += snprintf(s, tmpstr + tmpsiz - s,
 		      "%5s %5s %7s %7s\n",
 		      "pages", "count", "credits", "min");
-	LASSERT (tmpstr + tmpsiz - s > 0);
+	LASSERT(tmpstr + tmpsiz - s > 0);
 
 	if (the_lnet.ln_rtrpools == NULL)
 		goto out; /* I'm not a router */
@@ -638,7 +638,7 @@
 
 	DECLARE_LL_PROC_PPOS_DECL;
 
-	LASSERT (!write);
+	LASSERT(!write);
 
 	if (*lenp == 0)
 		return 0;
@@ -654,7 +654,7 @@
 			      "%-24s %6s %5s %4s %4s %4s %5s %5s %5s\n",
 			      "nid", "status", "alive", "refs", "peer",
 			      "rtr", "max", "tx", "min");
-		LASSERT (tmpstr + tmpsiz - s > 0);
+		LASSERT(tmpstr + tmpsiz - s > 0);
 	} else {
 		struct list_head	*n;
 		lnet_ni_t	 *ni   = NULL;
diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c
index ef5064e..b7613c8 100644
--- a/drivers/staging/lustre/lnet/selftest/brw_test.c
+++ b/drivers/staging/lustre/lnet/selftest/brw_test.c
@@ -48,16 +48,17 @@
 		"# data errors to inject randomly, zero by default");
 
 static void
-brw_client_fini (sfw_test_instance_t *tsi)
+brw_client_fini(sfw_test_instance_t *tsi)
 {
 	srpc_bulk_t     *bulk;
 	sfw_test_unit_t *tsu;
 
-	LASSERT (tsi->tsi_is_client);
+	LASSERT(tsi->tsi_is_client);
 
-	list_for_each_entry (tsu, &tsi->tsi_units, tsu_list) {
+	list_for_each_entry(tsu, &tsi->tsi_units, tsu_list) {
 		bulk = tsu->tsu_private;
-		if (bulk == NULL) continue;
+		if (bulk == NULL)
+			continue;
 
 		srpc_free_bulk(bulk);
 		tsu->tsu_private = NULL;
@@ -65,7 +66,7 @@
 }
 
 int
-brw_client_init (sfw_test_instance_t *tsi)
+brw_client_init(sfw_test_instance_t *tsi)
 {
 	sfw_session_t	 *sn = tsi->tsi_batch->bat_session;
 	int		  flags;
@@ -130,28 +131,31 @@
 #define BRW_MSIZE       sizeof(__u64)
 
 int
-brw_inject_one_error (void)
+brw_inject_one_error(void)
 {
 	struct timeval tv;
 
-	if (brw_inject_errors <= 0) return 0;
+	if (brw_inject_errors <= 0)
+		return 0;
 
 	do_gettimeofday(&tv);
 
-	if ((tv.tv_usec & 1) == 0) return 0;
+	if ((tv.tv_usec & 1) == 0)
+		return 0;
 
 	return brw_inject_errors--;
 }
 
 void
-brw_fill_page (struct page *pg, int pattern, __u64 magic)
+brw_fill_page(struct page *pg, int pattern, __u64 magic)
 {
 	char *addr = page_address(pg);
 	int   i;
 
-	LASSERT (addr != NULL);
+	LASSERT(addr != NULL);
 
-	if (pattern == LST_BRW_CHECK_NONE) return;
+	if (pattern == LST_BRW_CHECK_NONE)
+		return;
 
 	if (magic == BRW_MAGIC)
 		magic += brw_inject_one_error();
@@ -169,29 +173,31 @@
 		return;
 	}
 
-	LBUG ();
+	LBUG();
 	return;
 }
 
 int
-brw_check_page (struct page *pg, int pattern, __u64 magic)
+brw_check_page(struct page *pg, int pattern, __u64 magic)
 {
 	char  *addr = page_address(pg);
 	__u64  data = 0; /* make compiler happy */
 	int    i;
 
-	LASSERT (addr != NULL);
+	LASSERT(addr != NULL);
 
 	if (pattern == LST_BRW_CHECK_NONE)
 		return 0;
 
 	if (pattern == LST_BRW_CHECK_SIMPLE) {
 		data = *((__u64 *) addr);
-		if (data != magic) goto bad_data;
+		if (data != magic)
+			goto bad_data;
 
 		addr += PAGE_CACHE_SIZE - BRW_MSIZE;
 		data = *((__u64 *) addr);
-		if (data != magic) goto bad_data;
+		if (data != magic)
+			goto bad_data;
 
 		return 0;
 	}
@@ -199,22 +205,23 @@
 	if (pattern == LST_BRW_CHECK_FULL) {
 		for (i = 0; i < PAGE_CACHE_SIZE / BRW_MSIZE; i++) {
 			data = *(((__u64 *) addr) + i);
-			if (data != magic) goto bad_data;
+			if (data != magic)
+				goto bad_data;
 		}
 
 		return 0;
 	}
 
-	LBUG ();
+	LBUG();
 
 bad_data:
-	CERROR ("Bad data in page %p: "LPX64", "LPX64" expected\n",
+	CERROR("Bad data in page %p: "LPX64", "LPX64" expected\n",
 		pg, data, magic);
 	return 1;
 }
 
 void
-brw_fill_bulk (srpc_bulk_t *bk, int pattern, __u64 magic)
+brw_fill_bulk(srpc_bulk_t *bk, int pattern, __u64 magic)
 {
 	int	 i;
 	struct page *pg;
@@ -226,7 +233,7 @@
 }
 
 int
-brw_check_bulk (srpc_bulk_t *bk, int pattern, __u64 magic)
+brw_check_bulk(srpc_bulk_t *bk, int pattern, __u64 magic)
 {
 	int	 i;
 	struct page *pg;
@@ -234,7 +241,7 @@
 	for (i = 0; i < bk->bk_niov; i++) {
 		pg = bk->bk_iovs[i].kiov_page;
 		if (brw_check_page(pg, pattern, magic) != 0) {
-			CERROR ("Bulk page %p (%d/%d) is corrupted!\n",
+			CERROR("Bulk page %p (%d/%d) is corrupted!\n",
 				pg, i, bk->bk_niov);
 			return 1;
 		}
@@ -244,7 +251,7 @@
 }
 
 static int
-brw_client_prep_rpc (sfw_test_unit_t *tsu,
+brw_client_prep_rpc(sfw_test_unit_t *tsu,
 		     lnet_process_id_t dest, srpc_client_rpc_t **rpcpp)
 {
 	srpc_bulk_t	 *bulk = tsu->tsu_private;
@@ -302,7 +309,7 @@
 }
 
 static void
-brw_client_done_rpc (sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc)
+brw_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc)
 {
 	__u64		magic = BRW_MAGIC;
 	sfw_test_instance_t *tsi = tsu->tsu_instance;
@@ -311,10 +318,10 @@
 	srpc_brw_reply_t    *reply = &msg->msg_body.brw_reply;
 	srpc_brw_reqst_t    *reqst = &rpc->crpc_reqstmsg.msg_body.brw_reqst;
 
-	LASSERT (sn != NULL);
+	LASSERT(sn != NULL);
 
 	if (rpc->crpc_status != 0) {
-		CERROR ("BRW RPC to %s failed with %d\n",
+		CERROR("BRW RPC to %s failed with %d\n",
 			libcfs_id2str(rpc->crpc_dest), rpc->crpc_status);
 		if (!tsi->tsi_stopping) /* rpc could have been aborted */
 			atomic_inc(&sn->sn_brw_errors);
@@ -326,7 +333,7 @@
 		__swab32s(&reply->brw_status);
 	}
 
-	CDEBUG (reply->brw_status ? D_WARNING : D_NET,
+	CDEBUG(reply->brw_status ? D_WARNING : D_NET,
 		"BRW RPC to %s finished with brw_status: %d\n",
 		libcfs_id2str(rpc->crpc_dest), reply->brw_status);
 
@@ -336,10 +343,11 @@
 		goto out;
 	}
 
-	if (reqst->brw_rw == LST_BRW_WRITE) goto out;
+	if (reqst->brw_rw == LST_BRW_WRITE)
+		goto out;
 
 	if (brw_check_bulk(&rpc->crpc_bulk, reqst->brw_flags, magic) != 0) {
-		CERROR ("Bulk data from %s is corrupted!\n",
+		CERROR("Bulk data from %s is corrupted!\n",
 			libcfs_id2str(rpc->crpc_dest));
 		atomic_inc(&sn->sn_brw_errors);
 		rpc->crpc_status = -EBADMSG;
@@ -350,18 +358,19 @@
 }
 
 void
-brw_server_rpc_done (srpc_server_rpc_t *rpc)
+brw_server_rpc_done(srpc_server_rpc_t *rpc)
 {
 	srpc_bulk_t *blk = rpc->srpc_bulk;
 
-	if (blk == NULL) return;
+	if (blk == NULL)
+		return;
 
 	if (rpc->srpc_status != 0)
-		CERROR ("Bulk transfer %s %s has failed: %d\n",
+		CERROR("Bulk transfer %s %s has failed: %d\n",
 			blk->bk_sink ? "from" : "to",
 			libcfs_id2str(rpc->srpc_peer), rpc->srpc_status);
 	else
-		CDEBUG (D_NET, "Transferred %d pages bulk data %s %s\n",
+		CDEBUG(D_NET, "Transferred %d pages bulk data %s %s\n",
 			blk->bk_niov, blk->bk_sink ? "from" : "to",
 			libcfs_id2str(rpc->srpc_peer));
 
@@ -369,21 +378,21 @@
 }
 
 int
-brw_bulk_ready (srpc_server_rpc_t *rpc, int status)
+brw_bulk_ready(srpc_server_rpc_t *rpc, int status)
 {
 	__u64	     magic = BRW_MAGIC;
 	srpc_brw_reply_t *reply = &rpc->srpc_replymsg.msg_body.brw_reply;
 	srpc_brw_reqst_t *reqst;
 	srpc_msg_t       *reqstmsg;
 
-	LASSERT (rpc->srpc_bulk != NULL);
-	LASSERT (rpc->srpc_reqstbuf != NULL);
+	LASSERT(rpc->srpc_bulk != NULL);
+	LASSERT(rpc->srpc_reqstbuf != NULL);
 
 	reqstmsg = &rpc->srpc_reqstbuf->buf_msg;
 	reqst = &reqstmsg->msg_body.brw_reqst;
 
 	if (status != 0) {
-		CERROR ("BRW bulk %s failed for RPC from %s: %d\n",
+		CERROR("BRW bulk %s failed for RPC from %s: %d\n",
 			reqst->brw_rw == LST_BRW_READ ? "READ" : "WRITE",
 			libcfs_id2str(rpc->srpc_peer), status);
 		return -EIO;
@@ -396,7 +405,7 @@
 		__swab64s(&magic);
 
 	if (brw_check_bulk(rpc->srpc_bulk, reqst->brw_flags, magic) != 0) {
-		CERROR ("Bulk data from %s is corrupted!\n",
+		CERROR("Bulk data from %s is corrupted!\n",
 			libcfs_id2str(rpc->srpc_peer));
 		reply->brw_status = EBADMSG;
 	}
@@ -415,10 +424,10 @@
 	int		  npg;
 	int	       rc;
 
-	LASSERT (sv->sv_id == SRPC_SERVICE_BRW);
+	LASSERT(sv->sv_id == SRPC_SERVICE_BRW);
 
 	if (reqstmsg->msg_magic != SRPC_MSG_MAGIC) {
-		LASSERT (reqstmsg->msg_magic == __swab32(SRPC_MSG_MAGIC));
+		LASSERT(reqstmsg->msg_magic == __swab32(SRPC_MSG_MAGIC));
 
 		__swab32s(&reqst->brw_rw);
 		__swab32s(&reqst->brw_len);
@@ -426,7 +435,7 @@
 		__swab64s(&reqst->brw_rpyid);
 		__swab64s(&reqst->brw_bulkid);
 	}
-	LASSERT (reqstmsg->msg_type == (__u32)srpc_service2request(sv->sv_id));
+	LASSERT(reqstmsg->msg_type == (__u32)srpc_service2request(sv->sv_id));
 
 	reply->brw_status = 0;
 	rpc->srpc_done = brw_server_rpc_done;
diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c
index cbce662..9a52f25 100644
--- a/drivers/staging/lustre/lnet/selftest/conrpc.c
+++ b/drivers/staging/lustre/lnet/selftest/conrpc.c
@@ -75,7 +75,7 @@
 
 	if (crpc->crp_stamp == 0) {
 		/* not aborted */
-		LASSERT (crpc->crp_status == 0);
+		LASSERT(crpc->crp_status == 0);
 
 		crpc->crp_stamp  = cfs_time_current();
 		crpc->crp_status = rpc->crpc_status;
@@ -153,7 +153,7 @@
 	srpc_bulk_t *bulk = &crpc->crp_rpc->crpc_bulk;
 	int	  i;
 
-	LASSERT (list_empty(&crpc->crp_link));
+	LASSERT(list_empty(&crpc->crp_link));
 
 	for (i = 0; i < bulk->bk_niov; i++) {
 		if (bulk->bk_iovs[i].kiov_page == NULL)
@@ -187,7 +187,7 @@
 {
 	lstcon_rpc_trans_t *trans = crpc->crp_trans;
 
-	LASSERT (trans != NULL);
+	LASSERT(trans != NULL);
 
 	atomic_inc(&trans->tas_remaining);
 	crpc->crp_posted = 1;
@@ -289,7 +289,7 @@
 	lstcon_rpc_t      *crpc;
 	lstcon_node_t     *nd;
 
-	list_for_each_entry (crpc, &trans->tas_rpcs_list, crp_link) {
+	list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) {
 		rpc = crpc->crp_rpc;
 
 		spin_lock(&rpc->crpc_lock);
@@ -330,7 +330,7 @@
 	    !list_empty(&trans->tas_olink)) /* Not an end session RPC */
 		return 1;
 
-	return (atomic_read(&trans->tas_remaining) == 0) ? 1: 0;
+	return (atomic_read(&trans->tas_remaining) == 0) ? 1 : 0;
 }
 
 int
@@ -349,8 +349,8 @@
 	       lstcon_rpc_trans_name(trans->tas_opc));
 
 	/* post all requests */
-	list_for_each_entry (crpc, &trans->tas_rpcs_list, crp_link) {
-		LASSERT (!crpc->crp_posted);
+	list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) {
+		LASSERT(!crpc->crp_posted);
 
 		lstcon_rpc_post(crpc);
 	}
@@ -390,8 +390,8 @@
 	srpc_client_rpc_t    *rpc = crpc->crp_rpc;
 	srpc_generic_reply_t *rep;
 
-	LASSERT (nd != NULL && rpc != NULL);
-	LASSERT (crpc->crp_stamp != 0);
+	LASSERT(nd != NULL && rpc != NULL);
+	LASSERT(crpc->crp_stamp != 0);
 
 	if (crpc->crp_status != 0) {
 		*msgpp = NULL;
@@ -427,14 +427,14 @@
 	srpc_msg_t	*rep;
 	int		error;
 
-	LASSERT (stat != NULL);
+	LASSERT(stat != NULL);
 
 	memset(stat, 0, sizeof(*stat));
 
 	list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) {
 		lstcon_rpc_stat_total(stat, 1);
 
-		LASSERT (crpc->crp_stamp != 0);
+		LASSERT(crpc->crp_stamp != 0);
 
 		error = lstcon_rpc_get_reply(crpc, &rep);
 		if (error != 0) {
@@ -455,8 +455,7 @@
 		      lstcon_session_feats_check(trans->tas_features);
 	}
 
-	CDEBUG(D_NET, "transaction %s : success %d, failure %d, total %d, "
-		      "RPC error(%d), Framework error(%d)\n",
+	CDEBUG(D_NET, "transaction %s : success %d, failure %d, total %d, RPC error(%d), Framework error(%d)\n",
 	       lstcon_rpc_trans_name(trans->tas_opc),
 	       lstcon_rpc_stat_success(stat, 0),
 	       lstcon_rpc_stat_failure(stat, 0),
@@ -482,7 +481,7 @@
 	struct timeval	tv;
 	int		   error;
 
-	LASSERT (head_up != NULL);
+	LASSERT(head_up != NULL);
 
 	next = head_up;
 
@@ -498,7 +497,7 @@
 
 		ent = list_entry(next, lstcon_rpc_ent_t, rpe_link);
 
-		LASSERT (crpc->crp_stamp != 0);
+		LASSERT(crpc->crp_stamp != 0);
 
 		error = lstcon_rpc_get_reply(crpc, &msg);
 
@@ -532,7 +531,9 @@
 		if (readent == NULL)
 			continue;
 
-		if ((error = readent(trans->tas_opc, msg, ent)) != 0)
+		error = readent(trans->tas_opc, msg, ent);
+
+		if (error != 0)
 			return error;
 	}
 
@@ -568,19 +569,19 @@
 		 * user wait for them, just abandon them, they will be recycled
 		 * in callback */
 
-		LASSERT (crpc->crp_status != 0);
+		LASSERT(crpc->crp_status != 0);
 
 		crpc->crp_node  = NULL;
 		crpc->crp_trans = NULL;
 		list_del_init(&crpc->crp_link);
-		count ++;
+		count++;
 
 		spin_unlock(&rpc->crpc_lock);
 
 		atomic_dec(&trans->tas_remaining);
 	}
 
-	LASSERT (atomic_read(&trans->tas_remaining) == 0);
+	LASSERT(atomic_read(&trans->tas_remaining) == 0);
 
 	list_del(&trans->tas_link);
 	if (!list_empty(&trans->tas_olink))
@@ -669,14 +670,14 @@
 	brq->bar_bid     = tsb->tsb_id;
 	brq->bar_testidx = tsb->tsb_index;
 	brq->bar_opc     = transop == LST_TRANS_TSBRUN ? SRPC_BATCH_OPC_RUN :
-			   (transop == LST_TRANS_TSBSTOP ? SRPC_BATCH_OPC_STOP:
+			   (transop == LST_TRANS_TSBSTOP ? SRPC_BATCH_OPC_STOP :
 			    SRPC_BATCH_OPC_QUERY);
 
 	if (transop != LST_TRANS_TSBRUN &&
 	    transop != LST_TRANS_TSBSTOP)
 		return 0;
 
-	LASSERT (tsb->tsb_index == 0);
+	LASSERT(tsb->tsb_index == 0);
 
 	batch = (lstcon_batch_t *)tsb;
 	brq->bar_arg = batch->bat_arg;
@@ -710,7 +711,7 @@
 
 	i = idx / SFW_ID_PER_PAGE;
 
-	LASSERT (i < nkiov);
+	LASSERT(i < nkiov);
 
 	pid = (lnet_process_id_packed_t *)page_address(kiov[i].kiov_page);
 
@@ -728,9 +729,9 @@
 	int		       end;
 	int		       i = 0;
 
-	LASSERT (dist >= 1);
-	LASSERT (span >= 1);
-	LASSERT (grp->grp_nnode >= 1);
+	LASSERT(dist >= 1);
+	LASSERT(span >= 1);
+	LASSERT(grp->grp_nnode >= 1);
 
 	if (span > grp->grp_nnode)
 		return -EINVAL;
@@ -741,11 +742,11 @@
 	list_for_each_entry(ndl, &grp->grp_ndl_list, ndl_link) {
 		nd = ndl->ndl_node;
 		if (i < start) {
-			i ++;
+			i++;
 			continue;
 		}
 
-		if (i > (end >= start ? end: grp->grp_nnode))
+		if (i > (end >= start ? end : grp->grp_nnode))
 			break;
 
 		pid = lstcon_next_id((i - start), nkiov, kiov);
@@ -866,7 +867,7 @@
 
 		bulk->bk_sink = 0;
 
-		LASSERT (transop == LST_TRANS_TSBCLIADD);
+		LASSERT(transop == LST_TRANS_TSBCLIADD);
 
 		rc = lstcon_dstnodes_prep(test->tes_dst_grp,
 					  test->tes_cliidx++,
@@ -942,8 +943,7 @@
 	}
 
 	if (reply->msg_ses_feats != trans->tas_features) {
-		CNETERR("Framework features %x from %s is different with "
-			"features on this transaction: %x\n",
+		CNETERR("Framework features %x from %s is different with features on this transaction: %x\n",
 			 reply->msg_ses_feats, libcfs_nid2str(nd->nd_id.nid),
 			 trans->tas_features);
 		status = mksn_rep->mksn_status = EPROTO;
@@ -1107,8 +1107,8 @@
 			continue;
 
 		if (rc < 0) {
-			CDEBUG(D_NET, "Condition error while creating RPC "
-				      " for transaction %d: %d\n", transop, rc);
+			CDEBUG(D_NET, "Condition error while creating RPC for transaction %d: %d\n",
+					transop, rc);
 			break;
 		}
 
@@ -1193,7 +1193,7 @@
 
 	trans = console_session.ses_ping;
 
-	LASSERT (trans != NULL);
+	LASSERT(trans != NULL);
 
 	list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link) {
 		nd = ndl->ndl_node;
@@ -1219,8 +1219,8 @@
 		crpc = &nd->nd_ping;
 
 		if (crpc->crp_rpc != NULL) {
-			LASSERT (crpc->crp_trans == trans);
-			LASSERT (!list_empty(&crpc->crp_link));
+			LASSERT(crpc->crp_trans == trans);
+			LASSERT(!list_empty(&crpc->crp_link));
 
 			spin_lock(&crpc->crp_rpc->crpc_lock);
 
@@ -1264,7 +1264,7 @@
 		lstcon_rpc_trans_addreq(trans, crpc);
 		lstcon_rpc_post(crpc);
 
-		count ++;
+		count++;
 	}
 
 	if (console_session.ses_expired) {
@@ -1286,8 +1286,8 @@
 	stt_timer_t    *ptimer;
 	int	     rc;
 
-	LASSERT (list_empty(&console_session.ses_rpc_freelist));
-	LASSERT (atomic_read(&console_session.ses_rpc_counter) == 0);
+	LASSERT(list_empty(&console_session.ses_rpc_freelist));
+	LASSERT(atomic_read(&console_session.ses_rpc_counter) == 0);
 
 	rc = lstcon_rpc_trans_prep(NULL, LST_TRANS_SESPING,
 				   &console_session.ses_ping);
@@ -1307,7 +1307,7 @@
 void
 lstcon_rpc_pinger_stop(void)
 {
-	LASSERT (console_session.ses_shutdown);
+	LASSERT(console_session.ses_shutdown);
 
 	stt_del_timer(&console_session.ses_ping_timer);
 
@@ -1330,7 +1330,7 @@
 
 	/* Called with hold of global mutex */
 
-	LASSERT (console_session.ses_shutdown);
+	LASSERT(console_session.ses_shutdown);
 
 	while (!list_empty(&console_session.ses_trans_list)) {
 		list_for_each(pacer, &console_session.ses_trans_list) {
@@ -1345,8 +1345,7 @@
 
 		mutex_unlock(&console_session.ses_mutex);
 
-		CWARN("Session is shutting down, "
-		      "waiting for termination of transactions\n");
+		CWARN("Session is shutting down, waiting for termination of transactions\n");
 		cfs_pause(cfs_time_seconds(1));
 
 		mutex_lock(&console_session.ses_mutex);
@@ -1356,8 +1355,7 @@
 
 	lst_wait_until((atomic_read(&console_session.ses_rpc_counter) == 0),
 		       console_session.ses_rpc_lock,
-		       "Network is not accessible or target is down, "
-		       "waiting for %d console RPCs to being recycled\n",
+		       "Network is not accessible or target is down, waiting for %d console RPCs to being recycled\n",
 		       atomic_read(&console_session.ses_rpc_counter));
 
 	list_add(&zlist, &console_session.ses_rpc_freelist);
@@ -1392,6 +1390,6 @@
 void
 lstcon_rpc_module_fini(void)
 {
-	LASSERT (list_empty(&console_session.ses_rpc_freelist));
-	LASSERT (atomic_read(&console_session.ses_rpc_counter) == 0);
+	LASSERT(list_empty(&console_session.ses_rpc_freelist));
+	LASSERT(atomic_read(&console_session.ses_rpc_counter) == 0);
 }
diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c
index 09e4700..f1152e4 100644
--- a/drivers/staging/lustre/lnet/selftest/console.c
+++ b/drivers/staging/lustre/lnet/selftest/console.c
@@ -797,7 +797,7 @@
 		return rc;
 	}
 
-	if (dents_up != 0) {
+	if (dents_up) {
 		/* verbose query */
 		rc = lstcon_nodes_getent(&grp->grp_ndl_list,
 					 index_p, count_p, dents_up);
diff --git a/drivers/staging/lustre/lnet/selftest/timer.c b/drivers/staging/lustre/lnet/selftest/timer.c
index 3bf4afb..82fd363 100644
--- a/drivers/staging/lustre/lnet/selftest/timer.c
+++ b/drivers/staging/lustre/lnet/selftest/timer.c
@@ -74,14 +74,14 @@
 
 	spin_lock(&stt_data.stt_lock);
 
-	LASSERT (stt_data.stt_nthreads > 0);
-	LASSERT (!stt_data.stt_shuttingdown);
-	LASSERT (timer->stt_func != NULL);
-	LASSERT (list_empty(&timer->stt_list));
-	LASSERT (cfs_time_after(timer->stt_expires, cfs_time_current_sec()));
+	LASSERT(stt_data.stt_nthreads > 0);
+	LASSERT(!stt_data.stt_shuttingdown);
+	LASSERT(timer->stt_func != NULL);
+	LASSERT(list_empty(&timer->stt_list));
+	LASSERT(cfs_time_after(timer->stt_expires, cfs_time_current_sec()));
 
 	/* a simple insertion sort */
-	list_for_each_prev (pos, STTIMER_SLOT(timer->stt_expires)) {
+	list_for_each_prev(pos, STTIMER_SLOT(timer->stt_expires)) {
 		stt_timer_t *old = list_entry(pos, stt_timer_t, stt_list);
 
 		if (cfs_time_aftereq(timer->stt_expires, old->stt_expires))
@@ -102,14 +102,14 @@
  * another CPU.
  */
 int
-stt_del_timer (stt_timer_t *timer)
+stt_del_timer(stt_timer_t *timer)
 {
 	int ret = 0;
 
 	spin_lock(&stt_data.stt_lock);
 
-	LASSERT (stt_data.stt_nthreads > 0);
-	LASSERT (!stt_data.stt_shuttingdown);
+	LASSERT(stt_data.stt_nthreads > 0);
+	LASSERT(!stt_data.stt_shuttingdown);
 
 	if (!list_empty(&timer->stt_list)) {
 		ret = 1;
@@ -122,7 +122,7 @@
 
 /* called with stt_data.stt_lock held */
 int
-stt_expire_list (struct list_head *slot, cfs_time_t now)
+stt_expire_list(struct list_head *slot, cfs_time_t now)
 {
 	int	  expired = 0;
 	stt_timer_t *timer;
@@ -146,7 +146,7 @@
 }
 
 int
-stt_check_timers (cfs_time_t *last)
+stt_check_timers(cfs_time_t *last)
 {
 	int	expired = 0;
 	cfs_time_t now;
@@ -169,7 +169,7 @@
 
 
 int
-stt_timer_main (void *arg)
+stt_timer_main(void *arg)
 {
 	int rc = 0;
 	UNUSED(arg);
@@ -193,7 +193,7 @@
 }
 
 int
-stt_start_timer_thread (void)
+stt_start_timer_thread(void)
 {
 	struct task_struct *task;
 
@@ -211,7 +211,7 @@
 
 
 int
-stt_startup (void)
+stt_startup(void)
 {
 	int rc = 0;
 	int i;
@@ -227,20 +227,20 @@
 	init_waitqueue_head(&stt_data.stt_waitq);
 	rc = stt_start_timer_thread();
 	if (rc != 0)
-		CERROR ("Can't spawn timer thread: %d\n", rc);
+		CERROR("Can't spawn timer thread: %d\n", rc);
 
 	return rc;
 }
 
 void
-stt_shutdown (void)
+stt_shutdown(void)
 {
 	int i;
 
 	spin_lock(&stt_data.stt_lock);
 
 	for (i = 0; i < STTIMER_NSLOTS; i++)
-		LASSERT (list_empty(&stt_data.stt_hash[i]));
+		LASSERT(list_empty(&stt_data.stt_hash[i]));
 
 	stt_data.stt_shuttingdown = 1;
 
diff --git a/drivers/staging/lustre/lustre/Kconfig b/drivers/staging/lustre/lustre/Kconfig
index 2156a44..93d59b6 100644
--- a/drivers/staging/lustre/lustre/Kconfig
+++ b/drivers/staging/lustre/lustre/Kconfig
@@ -16,7 +16,7 @@
 	  this file system support as a module, choose M here: the module will
 	  be called lustre.
 
-	  To mount Lustre file systems , you also need to install the user space
+	  To mount Lustre file systems, you also need to install the user space
 	  mount.lustre and other user space commands which can be found in the
 	  lustre-client package, available from
 	  http://downloads.whamcloud.com/public/lustre/
diff --git a/drivers/staging/lustre/lustre/fid/fid_request.c b/drivers/staging/lustre/lustre/fid/fid_request.c
index 66007b5..79fc2fe 100644
--- a/drivers/staging/lustre/lustre/fid/fid_request.c
+++ b/drivers/staging/lustre/lustre/fid/fid_request.c
@@ -548,9 +548,7 @@
 	seq_type_proc_dir = lprocfs_register(LUSTRE_SEQ_NAME,
 					     proc_lustre_root,
 					     NULL, NULL);
-	if (IS_ERR(seq_type_proc_dir))
-		return PTR_ERR(seq_type_proc_dir);
-	return 0;
+	return PTR_ERR_OR_ZERO(seq_type_proc_dir);
 }
 
 static void __exit fid_mod_exit(void)
diff --git a/drivers/staging/lustre/lustre/fld/fld_cache.c b/drivers/staging/lustre/lustre/fld/fld_cache.c
index 25099cb..4531510 100644
--- a/drivers/staging/lustre/lustre/fld/fld_cache.c
+++ b/drivers/staging/lustre/lustre/fld/fld_cache.c
@@ -267,7 +267,7 @@
 	const seqno_t new_end  = range->lsr_end;
 	struct fld_cache_entry *fldt;
 
-	OBD_ALLOC_GFP(fldt, sizeof *fldt, GFP_ATOMIC);
+	OBD_ALLOC_GFP(fldt, sizeof(*fldt), GFP_ATOMIC);
 	if (!fldt) {
 		OBD_FREE_PTR(f_new);
 		/* overlap is not allowed, so dont mess up list. */
diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c
index 078e98b..e47fd50 100644
--- a/drivers/staging/lustre/lustre/fld/fld_request.c
+++ b/drivers/staging/lustre/lustre/fld/fld_request.c
@@ -59,8 +59,6 @@
 #include <lustre_mdc.h>
 #include "fld_internal.h"
 
-struct lu_context_key fld_thread_key;
-
 /* TODO: these 3 functions are copies of flow-control code from mdc_lib.c
  * It should be common thing. The same about mdc RPC lock */
 static int fld_req_avail(struct client_obd *cli, struct mdc_cache_waiter *mcw)
@@ -509,14 +507,11 @@
 	if (IS_ERR(fld_type_proc_dir))
 		return PTR_ERR(fld_type_proc_dir);
 
-	LU_CONTEXT_KEY_INIT(&fld_thread_key);
-	lu_context_key_register(&fld_thread_key);
 	return 0;
 }
 
 static void __exit fld_mod_exit(void)
 {
-	lu_context_key_degister(&fld_thread_key);
 	if (fld_type_proc_dir != NULL && !IS_ERR(fld_type_proc_dir)) {
 		lprocfs_remove(&fld_type_proc_dir);
 		fld_type_proc_dir = NULL;
diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h
index edb40af..c485206 100644
--- a/drivers/staging/lustre/lustre/include/cl_object.h
+++ b/drivers/staging/lustre/lustre/include/cl_object.h
@@ -3096,13 +3096,13 @@
 void cl_io_print(const struct lu_env *env, void *cookie,
 		 lu_printer_t printer, const struct cl_io *io);
 
-#define CL_IO_SLICE_CLEAN(foo_io, base)				 \
-do {								    \
-	typeof(foo_io) __foo_io = (foo_io);			     \
+#define CL_IO_SLICE_CLEAN(foo_io, base)					\
+do {									\
+	typeof(foo_io) __foo_io = (foo_io);				\
 									\
-	CLASSERT(offsetof(typeof(*__foo_io), base) == 0);	       \
-	memset(&__foo_io->base + 1, 0,				  \
-	       (sizeof *__foo_io) - sizeof __foo_io->base);	     \
+	CLASSERT(offsetof(typeof(*__foo_io), base) == 0);		\
+	memset(&__foo_io->base + 1, 0,					\
+	       sizeof(*__foo_io) - sizeof(__foo_io->base));		\
 } while (0)
 
 /** @} cl_io */
diff --git a/drivers/staging/lustre/lustre/include/lclient.h b/drivers/staging/lustre/lustre/include/lclient.h
index 9d4011f..27316f7 100644
--- a/drivers/staging/lustre/lustre/include/lclient.h
+++ b/drivers/staging/lustre/lustre/include/lclient.h
@@ -388,8 +388,8 @@
 __u64 cl_fid_build_ino(const struct lu_fid *fid, int api32);
 __u32 cl_fid_build_gen(const struct lu_fid *fid);
 
-# define CLOBINVRNT(env, clob, expr)				    \
-	((void)sizeof(env), (void)sizeof(clob), (void)sizeof !!(expr))
+# define CLOBINVRNT(env, clob, expr)					\
+	((void)sizeof(env), (void)sizeof(clob), (void)sizeof(!!(expr)))
 
 int cl_init_ea_size(struct obd_export *md_exp, struct obd_export *dt_exp);
 int cl_ocd_update(struct obd_device *host,
diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h
index 80b019b..eefdb8d 100644
--- a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h
+++ b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h
@@ -232,9 +232,6 @@
 	return flag;
 }
 
-# define ll_mrf_ret void
-# define LL_MRF_RETURN(rc)
-
 #include <linux/fs.h>
 
 # define ll_umode_t	umode_t
diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h
index fa31be8..d5b8225 100644
--- a/drivers/staging/lustre/lustre/include/lu_object.h
+++ b/drivers/staging/lustre/lustre/include/lu_object.h
@@ -622,7 +622,7 @@
 	/**
 	 * objects hash table
 	 */
-	cfs_hash_t	       *ls_obj_hash;
+	struct cfs_hash	       *ls_obj_hash;
 	/**
 	 * index of bucket on hash table while purging
 	 */
@@ -659,7 +659,7 @@
 static inline struct lu_site_bkt_data *
 lu_site_bkt_from_fid(struct lu_site *site, struct lu_fid *fid)
 {
-	cfs_hash_bd_t bd;
+	struct cfs_hash_bd bd;
 
 	cfs_hash_bd_get(site->ls_obj_hash, fid, &bd);
 	return cfs_hash_bd_extra_get(site->ls_obj_hash, &bd);
diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
index 984235c..5ca18d0 100644
--- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
+++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
@@ -831,9 +831,10 @@
 static inline void fid_cpu_to_le(struct lu_fid *dst, const struct lu_fid *src)
 {
 	/* check that all fields are converted */
-	CLASSERT(sizeof *src ==
-		 sizeof fid_seq(src) +
-		 sizeof fid_oid(src) + sizeof fid_ver(src));
+	CLASSERT(sizeof(*src) ==
+		 sizeof(fid_seq(src)) +
+		 sizeof(fid_oid(src)) +
+		 sizeof(fid_ver(src)));
 	dst->f_seq = cpu_to_le64(fid_seq(src));
 	dst->f_oid = cpu_to_le32(fid_oid(src));
 	dst->f_ver = cpu_to_le32(fid_ver(src));
@@ -842,9 +843,10 @@
 static inline void fid_le_to_cpu(struct lu_fid *dst, const struct lu_fid *src)
 {
 	/* check that all fields are converted */
-	CLASSERT(sizeof *src ==
-		 sizeof fid_seq(src) +
-		 sizeof fid_oid(src) + sizeof fid_ver(src));
+	CLASSERT(sizeof(*src) ==
+		 sizeof(fid_seq(src)) +
+		 sizeof(fid_oid(src)) +
+		 sizeof(fid_ver(src)));
 	dst->f_seq = le64_to_cpu(fid_seq(src));
 	dst->f_oid = le32_to_cpu(fid_oid(src));
 	dst->f_ver = le32_to_cpu(fid_ver(src));
@@ -853,9 +855,10 @@
 static inline void fid_cpu_to_be(struct lu_fid *dst, const struct lu_fid *src)
 {
 	/* check that all fields are converted */
-	CLASSERT(sizeof *src ==
-		 sizeof fid_seq(src) +
-		 sizeof fid_oid(src) + sizeof fid_ver(src));
+	CLASSERT(sizeof(*src) ==
+		 sizeof(fid_seq(src)) +
+		 sizeof(fid_oid(src)) +
+		 sizeof(fid_ver(src)));
 	dst->f_seq = cpu_to_be64(fid_seq(src));
 	dst->f_oid = cpu_to_be32(fid_oid(src));
 	dst->f_ver = cpu_to_be32(fid_ver(src));
@@ -864,9 +867,10 @@
 static inline void fid_be_to_cpu(struct lu_fid *dst, const struct lu_fid *src)
 {
 	/* check that all fields are converted */
-	CLASSERT(sizeof *src ==
-		 sizeof fid_seq(src) +
-		 sizeof fid_oid(src) + sizeof fid_ver(src));
+	CLASSERT(sizeof(*src) ==
+		 sizeof(fid_seq(src)) +
+		 sizeof(fid_oid(src)) +
+		 sizeof(fid_ver(src)));
 	dst->f_seq = be64_to_cpu(fid_seq(src));
 	dst->f_oid = be32_to_cpu(fid_oid(src));
 	dst->f_ver = be32_to_cpu(fid_ver(src));
@@ -891,9 +895,11 @@
 static inline int lu_fid_eq(const struct lu_fid *f0, const struct lu_fid *f1)
 {
 	/* Check that there is no alignment padding. */
-	CLASSERT(sizeof *f0 ==
-		 sizeof f0->f_seq + sizeof f0->f_oid + sizeof f0->f_ver);
-	return memcmp(f0, f1, sizeof *f0) == 0;
+	CLASSERT(sizeof(*f0) ==
+		 sizeof(f0->f_seq) +
+		 sizeof(f0->f_oid) +
+		 sizeof(f0->f_ver));
+	return memcmp(f0, f1, sizeof(*f0)) == 0;
 }
 
 #define __diff_normalize(val0, val1)			    \
@@ -1638,8 +1644,10 @@
 
 /* extern void lustre_swab_lov_mds_md(struct lov_mds_md *llm); */
 
-#define MAX_MD_SIZE (sizeof(struct lov_mds_md) + 4 * sizeof(struct lov_ost_data))
-#define MIN_MD_SIZE (sizeof(struct lov_mds_md) + 1 * sizeof(struct lov_ost_data))
+#define MAX_MD_SIZE							\
+	(sizeof(struct lov_mds_md) + 4 * sizeof(struct lov_ost_data))
+#define MIN_MD_SIZE							\
+	(sizeof(struct lov_mds_md) + 1 * sizeof(struct lov_ost_data))
 
 #define XATTR_NAME_ACL_ACCESS   "system.posix_acl_access"
 #define XATTR_NAME_ACL_DEFAULT  "system.posix_acl_default"
diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm.h b/drivers/staging/lustre/lustre/include/lustre_dlm.h
index 7020d9c..bc2b82f 100644
--- a/drivers/staging/lustre/lustre/include/lustre_dlm.h
+++ b/drivers/staging/lustre/lustre/include/lustre_dlm.h
@@ -375,7 +375,7 @@
 	ldlm_side_t		ns_client;
 
 	/** Resource hash table for namespace. */
-	cfs_hash_t		*ns_rs_hash;
+	struct cfs_hash		*ns_rs_hash;
 
 	/** serialize */
 	spinlock_t		ns_lock;
@@ -1083,7 +1083,7 @@
  * Rate-limited version of lock printing function.
  */
 #define LDLM_DEBUG_LIMIT(mask, lock, fmt, a...) do {			 \
-	static cfs_debug_limit_state_t _ldlm_cdls;			   \
+	static struct cfs_debug_limit_state _ldlm_cdls;			   \
 	LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, mask, &_ldlm_cdls);	      \
 	ldlm_lock_debug(&msgdata, mask, &_ldlm_cdls, lock, "### " fmt , ##a);\
 } while (0)
diff --git a/drivers/staging/lustre/lustre/include/lustre_export.h b/drivers/staging/lustre/lustre/include/lustre_export.h
index d61c020..2feb38b 100644
--- a/drivers/staging/lustre/lustre/include/lustre_export.h
+++ b/drivers/staging/lustre/lustre/include/lustre_export.h
@@ -197,12 +197,12 @@
 	/** Connection count value from last succesful reconnect rpc */
 	__u32		     exp_conn_cnt;
 	/** Hash list of all ldlm locks granted on this export */
-	cfs_hash_t	       *exp_lock_hash;
+	struct cfs_hash	       *exp_lock_hash;
 	/**
 	 * Hash list for Posix lock deadlock detection, added with
 	 * ldlm_lock::l_exp_flock_hash.
 	 */
-	cfs_hash_t	       *exp_flock_hash;
+	struct cfs_hash	       *exp_flock_hash;
 	struct list_head		exp_outstanding_replies;
 	struct list_head		exp_uncommitted_replies;
 	spinlock_t		  exp_uncommitted_replies_lock;
diff --git a/drivers/staging/lustre/lustre/include/lustre_fid.h b/drivers/staging/lustre/lustre/include/lustre_fid.h
index d9d5814..ff11953 100644
--- a/drivers/staging/lustre/lustre/include/lustre_fid.h
+++ b/drivers/staging/lustre/lustre/include/lustre_fid.h
@@ -590,7 +590,7 @@
 static inline void ostid_build_res_name(struct ost_id *oi,
 					struct ldlm_res_id *name)
 {
-	memset(name, 0, sizeof *name);
+	memset(name, 0, sizeof(*name));
 	if (fid_seq_is_mdt0(ostid_seq(oi))) {
 		name->name[LUSTRE_RES_ID_SEQ_OFF] = ostid_id(oi);
 		name->name[LUSTRE_RES_ID_VER_OID_OFF] = ostid_seq(oi);
diff --git a/drivers/staging/lustre/lustre/include/lustre_lite.h b/drivers/staging/lustre/lustre/include/lustre_lite.h
index 25f8bfa..beccb5e 100644
--- a/drivers/staging/lustre/lustre/include/lustre_lite.h
+++ b/drivers/staging/lustre/lustre/include/lustre_lite.h
@@ -139,7 +139,11 @@
 {
 	if (BITS_PER_LONG == 32 && hash64)
 		hash >>= 32;
-	return ~0UL - hash;
+	/* save hash 0 as index 0 because otherwise we'll save it at
+	 * page index end (~0UL) and it causes truncate_inode_pages_range()
+	 * to loop forever.
+	 */
+	return ~0UL - (hash + !hash);
 }
 
 /** @} lite */
diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h
index e947002..72edf01 100644
--- a/drivers/staging/lustre/lustre/include/lustre_net.h
+++ b/drivers/staging/lustre/lustre/include/lustre_net.h
@@ -1427,7 +1427,7 @@
 struct nrs_crrn_net {
 	struct ptlrpc_nrs_resource	cn_res;
 	cfs_binheap_t		       *cn_binheap;
-	cfs_hash_t		       *cn_cli_hash;
+	struct cfs_hash		       *cn_cli_hash;
 	/**
 	 * Used when a new scheduling round commences, in order to synchronize
 	 * all clients with the new round number.
@@ -1568,7 +1568,7 @@
 struct nrs_orr_data {
 	struct ptlrpc_nrs_resource	od_res;
 	cfs_binheap_t		       *od_binheap;
-	cfs_hash_t		       *od_obj_hash;
+	struct cfs_hash		       *od_obj_hash;
 	struct kmem_cache		       *od_cache;
 	/**
 	 * Used when a new scheduling round commences, in order to synchronize
@@ -2206,7 +2206,7 @@
 #define DEBUG_REQ(level, req, fmt, args...)				   \
 do {									  \
 	if ((level) & (D_ERROR | D_WARNING)) {				\
-		static cfs_debug_limit_state_t cdls;			  \
+		static struct cfs_debug_limit_state cdls;			  \
 		LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, level, &cdls);	    \
 		debug_req(&msgdata, level, &cdls, req, "@@@ "fmt" ", ## args);\
 	} else {							      \
diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h
index a612255..d0aea15 100644
--- a/drivers/staging/lustre/lustre/include/obd.h
+++ b/drivers/staging/lustre/lustre/include/obd.h
@@ -177,7 +177,7 @@
 	 * ->lsm_wire contains padding, but it should be zeroed out during
 	 * allocation.
 	 */
-	return memcmp(&m1->lsm_wire, &m2->lsm_wire, sizeof m1->lsm_wire);
+	return memcmp(&m1->lsm_wire, &m2->lsm_wire, sizeof(m1->lsm_wire));
 }
 
 static inline int lov_lum_lsm_cmp(struct lov_user_md *lum,
@@ -429,7 +429,7 @@
 	/* ptlrpc work for writeback in ptlrpcd context */
 	void		    *cl_writeback_work;
 	/* hash tables for osc_quota_info */
-	cfs_hash_t	      *cl_quota_hash[MAXQUOTAS];
+	struct cfs_hash	      *cl_quota_hash[MAXQUOTAS];
 };
 #define obd2cli_tgt(obd) ((char *)(obd)->u.cli.cl_target_uuid.uuid)
 
@@ -556,7 +556,7 @@
 	__u32		   lov_tgt_size;   /* size of tgts array */
 	int		     lov_connects;
 	int		     lov_pool_count;
-	cfs_hash_t	     *lov_pools_hash_body; /* used for key access */
+	struct cfs_hash	     *lov_pools_hash_body; /* used for key access */
 	struct list_head	      lov_pool_list; /* used for sequential access */
 	struct proc_dir_entry   *lov_pool_proc_entry;
 	enum lustre_sec_part    lov_sp_me;
@@ -855,11 +855,11 @@
 	 * protection of other bits using _bh lock */
 	unsigned long obd_recovery_expired:1;
 	/* uuid-export hash body */
-	cfs_hash_t	     *obd_uuid_hash;
+	struct cfs_hash	     *obd_uuid_hash;
 	/* nid-export hash body */
-	cfs_hash_t	     *obd_nid_hash;
+	struct cfs_hash	     *obd_nid_hash;
 	/* nid stats body */
-	cfs_hash_t	     *obd_nid_stats_hash;
+	struct cfs_hash	     *obd_nid_stats_hash;
 	struct list_head	      obd_nid_stats;
 	atomic_t	    obd_refcount;
 	wait_queue_head_t	     obd_refcount_waitq;
diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h
index 03e6133..9697e7f 100644
--- a/drivers/staging/lustre/lustre/include/obd_support.h
+++ b/drivers/staging/lustre/lustre/include/obd_support.h
@@ -633,8 +633,8 @@
 
 #define OBD_ALLOC(ptr, size) OBD_ALLOC_GFP(ptr, size, __GFP_IO)
 #define OBD_ALLOC_WAIT(ptr, size) OBD_ALLOC_GFP(ptr, size, GFP_IOFS)
-#define OBD_ALLOC_PTR(ptr) OBD_ALLOC(ptr, sizeof *(ptr))
-#define OBD_ALLOC_PTR_WAIT(ptr) OBD_ALLOC_WAIT(ptr, sizeof *(ptr))
+#define OBD_ALLOC_PTR(ptr) OBD_ALLOC(ptr, sizeof(*(ptr)))
+#define OBD_ALLOC_PTR_WAIT(ptr) OBD_ALLOC_WAIT(ptr, sizeof(*(ptr)))
 
 #define OBD_CPT_ALLOC_GFP(ptr, cptab, cpt, size, gfp_mask)		      \
 	__OBD_MALLOC_VERBOSE(ptr, cptab, cpt, size, gfp_mask)
@@ -643,7 +643,7 @@
 	OBD_CPT_ALLOC_GFP(ptr, cptab, cpt, size, __GFP_IO)
 
 #define OBD_CPT_ALLOC_PTR(ptr, cptab, cpt)				      \
-	OBD_CPT_ALLOC(ptr, cptab, cpt, sizeof *(ptr))
+	OBD_CPT_ALLOC(ptr, cptab, cpt, sizeof(*(ptr)))
 
 # define __OBD_VMALLOC_VEROBSE(ptr, cptab, cpt, size)			      \
 do {									      \
@@ -773,7 +773,7 @@
 #define OBD_SLAB_CPT_ALLOC_GFP(ptr, slab, cptab, cpt, size, flags)	      \
 	__OBD_SLAB_ALLOC_VERBOSE(ptr, slab, cptab, cpt, size, flags)
 
-#define OBD_FREE_PTR(ptr) OBD_FREE(ptr, sizeof *(ptr))
+#define OBD_FREE_PTR(ptr) OBD_FREE(ptr, sizeof(*(ptr)))
 
 #define OBD_SLAB_FREE(ptr, slab, size)					\
 do {									  \
@@ -789,19 +789,19 @@
 	OBD_SLAB_CPT_ALLOC_GFP(ptr, slab, cptab, cpt, size, __GFP_IO)
 
 #define OBD_SLAB_ALLOC_PTR(ptr, slab)					      \
-	OBD_SLAB_ALLOC(ptr, slab, sizeof *(ptr))
+	OBD_SLAB_ALLOC(ptr, slab, sizeof(*(ptr)))
 
 #define OBD_SLAB_CPT_ALLOC_PTR(ptr, slab, cptab, cpt)			      \
-	OBD_SLAB_CPT_ALLOC(ptr, slab, cptab, cpt, sizeof *(ptr))
+	OBD_SLAB_CPT_ALLOC(ptr, slab, cptab, cpt, sizeof(*(ptr)))
 
 #define OBD_SLAB_ALLOC_PTR_GFP(ptr, slab, flags)			      \
-	OBD_SLAB_ALLOC_GFP(ptr, slab, sizeof *(ptr), flags)
+	OBD_SLAB_ALLOC_GFP(ptr, slab, sizeof(*(ptr)), flags)
 
 #define OBD_SLAB_CPT_ALLOC_PTR_GFP(ptr, slab, cptab, cpt, flags)		      \
-	OBD_SLAB_CPT_ALLOC_GFP(ptr, slab, cptab, cpt, sizeof *(ptr), flags)
+	OBD_SLAB_CPT_ALLOC_GFP(ptr, slab, cptab, cpt, sizeof(*(ptr)), flags)
 
 #define OBD_SLAB_FREE_PTR(ptr, slab)					      \
-	OBD_SLAB_FREE((ptr), (slab), sizeof *(ptr))
+	OBD_SLAB_FREE((ptr), (slab), sizeof(*(ptr)))
 
 #define KEY_IS(str) \
 	(keylen >= (sizeof(str)-1) && memcmp(key, str, (sizeof(str)-1)) == 0)
diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c
index 8ff38c6..e60c04d 100644
--- a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c
+++ b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c
@@ -701,7 +701,7 @@
 
 	CDEBUG(D_VFSTRACE, "lock: %d [%lu, %lu]\n", mode, start, end);
 
-	memset(&cio->cui_link, 0, sizeof cio->cui_link);
+	memset(&cio->cui_link, 0, sizeof(cio->cui_link));
 
 	if (cio->cui_fd && (cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) {
 		descr->cld_mode = CLM_GROUP;
diff --git a/drivers/staging/lustre/lustre/ldlm/interval_tree.c b/drivers/staging/lustre/lustre/ldlm/interval_tree.c
index c65b13c..1de1d8e 100644
--- a/drivers/staging/lustre/lustre/ldlm/interval_tree.c
+++ b/drivers/staging/lustre/lustre/ldlm/interval_tree.c
@@ -125,11 +125,11 @@
 
 #define interval_for_each(node, root)		   \
 for (node = interval_first(root); node != NULL;	 \
-     node = interval_next(node))
+	node = interval_next(node))
 
 #define interval_for_each_reverse(node, root)	   \
 for (node = interval_last(root); node != NULL;	  \
-     node = interval_prev(node))
+	node = interval_prev(node))
 
 static struct interval_node *interval_first(struct interval_node *node)
 {
@@ -239,7 +239,7 @@
 	left_max = node->in_left ? node->in_left->in_max_high : 0;
 	right_max = node->in_right ? node->in_right->in_max_high : 0;
 	node->in_max_high  = max_u64(interval_high(node),
-				     max_u64(left_max,right_max));
+				     max_u64(left_max, right_max));
 }
 
 /* The left rotation "pivots" around the link from node to node->right, and
@@ -427,8 +427,9 @@
 			} else {
 				if (node_is_black_or_0(tmp->in_right)) {
 					struct interval_node *o_left;
-					if ((o_left = tmp->in_left))
-					     o_left->in_color = INTERVAL_BLACK;
+					o_left = tmp->in_left;
+					if (o_left)
+						o_left->in_color = INTERVAL_BLACK;
 					tmp->in_color = INTERVAL_RED;
 					__rotate_right(tmp, root);
 					tmp = parent->in_right;
@@ -436,7 +437,7 @@
 				tmp->in_color = parent->in_color;
 				parent->in_color = INTERVAL_BLACK;
 				if (tmp->in_right)
-				    tmp->in_right->in_color = INTERVAL_BLACK;
+					tmp->in_right->in_color = INTERVAL_BLACK;
 				__rotate_left(parent, root);
 				node = *root;
 				break;
@@ -457,8 +458,9 @@
 			} else {
 				if (node_is_black_or_0(tmp->in_left)) {
 					struct interval_node *o_right;
-					if ((o_right = tmp->in_right))
-					    o_right->in_color = INTERVAL_BLACK;
+					o_right = tmp->in_right;
+					if (o_right)
+						o_right->in_color = INTERVAL_BLACK;
 					tmp->in_color = INTERVAL_RED;
 					__rotate_left(tmp, root);
 					tmp = parent->in_left;
@@ -545,7 +547,7 @@
 		update_maxhigh(child ? : parent, node->in_max_high);
 		update_maxhigh(node, old->in_max_high);
 		if (parent == old)
-			 parent = node;
+			parent = node;
 		goto color;
 	}
 	parent = node->in_parent;
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c b/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c
index 7e31663..ac5d66a 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c
@@ -144,7 +144,7 @@
 	l->l_tree_node = NULL;
 	list_del_init(&l->l_sl_policy);
 
-	return (list_empty(&n->li_group) ? n : NULL);
+	return list_empty(&n->li_group) ? n : NULL;
 }
 
 static inline int lock_mode_to_index(ldlm_mode_t mode)
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c
index c68ed27..39fcdac 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c
@@ -745,7 +745,7 @@
  * Export handle<->flock hash operations.
  */
 static unsigned
-ldlm_export_flock_hash(cfs_hash_t *hs, const void *key, unsigned mask)
+ldlm_export_flock_hash(struct cfs_hash *hs, const void *key, unsigned mask)
 {
 	return cfs_hash_u64_hash(*(__u64 *)key, mask);
 }
@@ -772,7 +772,7 @@
 }
 
 static void
-ldlm_export_flock_get(cfs_hash_t *hs, struct hlist_node *hnode)
+ldlm_export_flock_get(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	struct ldlm_lock *lock;
 	struct ldlm_flock *flock;
@@ -787,7 +787,7 @@
 }
 
 static void
-ldlm_export_flock_put(cfs_hash_t *hs, struct hlist_node *hnode)
+ldlm_export_flock_put(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	struct ldlm_lock *lock;
 	struct ldlm_flock *flock;
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c
index 6133b3f..3900a69 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c
@@ -529,7 +529,7 @@
 		lock_res_nested(oldres, LRT_NEW);
 	}
 	LASSERT(memcmp(new_resid, &oldres->lr_name,
-		       sizeof oldres->lr_name) != 0);
+		       sizeof(oldres->lr_name)) != 0);
 	lock->l_resource = newres;
 	unlock_res(oldres);
 	unlock_res_and_lock(lock);
@@ -1891,7 +1891,7 @@
 	return LDLM_ITER_CONTINUE;
 }
 
-static int ldlm_reprocess_res(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+static int ldlm_reprocess_res(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 			      struct hlist_node *hnode, void *arg)
 {
 	struct ldlm_resource *res = cfs_hash_object(hs, hnode);
@@ -2040,7 +2040,7 @@
  * Iterator function for ldlm_cancel_locks_for_export.
  * Cancels passed locks.
  */
-int ldlm_cancel_locks_for_export_cb(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+int ldlm_cancel_locks_for_export_cb(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 				    struct hlist_node *hnode, void *data)
 
 {
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
index a100a0b..fde9bcd 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
@@ -937,7 +937,7 @@
  * Export handle<->lock hash operations.
  */
 static unsigned
-ldlm_export_lock_hash(cfs_hash_t *hs, const void *key, unsigned mask)
+ldlm_export_lock_hash(struct cfs_hash *hs, const void *key, unsigned mask)
 {
 	return cfs_hash_u64_hash(((struct lustre_handle *)key)->cookie, mask);
 }
@@ -973,7 +973,7 @@
 }
 
 static void
-ldlm_export_lock_get(cfs_hash_t *hs, struct hlist_node *hnode)
+ldlm_export_lock_get(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	struct ldlm_lock *lock;
 
@@ -982,7 +982,7 @@
 }
 
 static void
-ldlm_export_lock_put(cfs_hash_t *hs, struct hlist_node *hnode)
+ldlm_export_lock_put(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	struct ldlm_lock *lock;
 
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c
index 21cb523..dcc2784 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c
@@ -1652,7 +1652,7 @@
 
 		LDLM_LOCK_GET(lock);
 		spin_unlock(&ns->ns_lock);
-		lu_ref_add(&lock->l_reference, __FUNCTION__, current);
+		lu_ref_add(&lock->l_reference, __func__, current);
 
 		/* Pass the lock through the policy filter and see if it
 		 * should stay in LRU.
@@ -1670,7 +1670,7 @@
 		result = pf(ns, lock, unused, added, count);
 		if (result == LDLM_POLICY_KEEP_LOCK) {
 			lu_ref_del(&lock->l_reference,
-				   __FUNCTION__, current);
+				   __func__, current);
 			LDLM_LOCK_RELEASE(lock);
 			spin_lock(&ns->ns_lock);
 			break;
@@ -1693,7 +1693,7 @@
 			 * by itself, or the lock is no longer unused. */
 			unlock_res_and_lock(lock);
 			lu_ref_del(&lock->l_reference,
-				   __FUNCTION__, current);
+				   __func__, current);
 			LDLM_LOCK_RELEASE(lock);
 			spin_lock(&ns->ns_lock);
 			continue;
@@ -1724,7 +1724,7 @@
 		LASSERT(list_empty(&lock->l_bl_ast));
 		list_add(&lock->l_bl_ast, cancels);
 		unlock_res_and_lock(lock);
-		lu_ref_del(&lock->l_reference, __FUNCTION__, current);
+		lu_ref_del(&lock->l_reference, __func__, current);
 		spin_lock(&ns->ns_lock);
 		added++;
 		unused--;
@@ -1925,7 +1925,7 @@
 	void   *lc_opaque;
 };
 
-static int ldlm_cli_hash_cancel_unused(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+static int ldlm_cli_hash_cancel_unused(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 				       struct hlist_node *hnode, void *arg)
 {
 	struct ldlm_resource	   *res = cfs_hash_object(hs, hnode);
@@ -2023,7 +2023,7 @@
 	return helper->iter(lock, helper->closure);
 }
 
-static int ldlm_res_iter_helper(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+static int ldlm_res_iter_helper(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 				struct hlist_node *hnode, void *arg)
 
 {
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
index 208751a..77e022b 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
@@ -159,7 +159,7 @@
 {
 	struct ldlm_namespace *ns  = m->private;
 	__u64		  res = 0;
-	cfs_hash_bd_t	  bd;
+	struct cfs_hash_bd	  bd;
 	int		    i;
 
 	/* result is not strictly consistant */
@@ -389,7 +389,7 @@
 
 #endif /* LPROCFS */
 
-static unsigned ldlm_res_hop_hash(cfs_hash_t *hs,
+static unsigned ldlm_res_hop_hash(struct cfs_hash *hs,
 				  const void *key, unsigned mask)
 {
 	const struct ldlm_res_id     *id  = key;
@@ -401,7 +401,7 @@
 	return val & mask;
 }
 
-static unsigned ldlm_res_hop_fid_hash(cfs_hash_t *hs,
+static unsigned ldlm_res_hop_fid_hash(struct cfs_hash *hs,
 				      const void *key, unsigned mask)
 {
 	const struct ldlm_res_id *id = key;
@@ -453,7 +453,7 @@
 	return hlist_entry(hnode, struct ldlm_resource, lr_hash);
 }
 
-static void ldlm_res_hop_get_locked(cfs_hash_t *hs, struct hlist_node *hnode)
+static void ldlm_res_hop_get_locked(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	struct ldlm_resource *res;
 
@@ -461,7 +461,7 @@
 	ldlm_resource_getref(res);
 }
 
-static void ldlm_res_hop_put_locked(cfs_hash_t *hs, struct hlist_node *hnode)
+static void ldlm_res_hop_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	struct ldlm_resource *res;
 
@@ -470,7 +470,7 @@
 	ldlm_resource_putref_locked(res);
 }
 
-static void ldlm_res_hop_put(cfs_hash_t *hs, struct hlist_node *hnode)
+static void ldlm_res_hop_put(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	struct ldlm_resource *res;
 
@@ -564,7 +564,7 @@
 	struct ldlm_namespace *ns = NULL;
 	struct ldlm_ns_bucket *nsb;
 	ldlm_ns_hash_def_t    *nsd;
-	cfs_hash_bd_t	  bd;
+	struct cfs_hash_bd	  bd;
 	int		    idx;
 	int		    rc;
 
@@ -743,7 +743,7 @@
 	} while (1);
 }
 
-static int ldlm_resource_clean(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+static int ldlm_resource_clean(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 			       struct hlist_node *hnode, void *arg)
 {
 	struct ldlm_resource *res = cfs_hash_object(hs, hnode);
@@ -756,7 +756,7 @@
 	return 0;
 }
 
-static int ldlm_resource_complain(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+static int ldlm_resource_complain(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 				  struct hlist_node *hnode, void *arg)
 {
 	struct ldlm_resource  *res = cfs_hash_object(hs, hnode);
@@ -1060,7 +1060,7 @@
 {
 	struct hlist_node     *hnode;
 	struct ldlm_resource *res;
-	cfs_hash_bd_t	 bd;
+	struct cfs_hash_bd	 bd;
 	__u64		 version;
 	int		      ns_refcount = 0;
 
@@ -1115,7 +1115,7 @@
 		lu_ref_fini(&res->lr_reference);
 		/* We have taken lr_lvb_mutex. Drop it. */
 		mutex_unlock(&res->lr_lvb_mutex);
-		OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof *res);
+		OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof(*res));
 
 		res = hlist_entry(hnode, struct ldlm_resource, lr_hash);
 		/* Synchronize with regard to resource creation. */
@@ -1183,7 +1183,7 @@
 	return res;
 }
 
-static void __ldlm_resource_putref_final(cfs_hash_bd_t *bd,
+static void __ldlm_resource_putref_final(struct cfs_hash_bd *bd,
 					 struct ldlm_resource *res)
 {
 	struct ldlm_ns_bucket *nsb = res->lr_ns_bucket;
@@ -1214,7 +1214,7 @@
 int ldlm_resource_putref(struct ldlm_resource *res)
 {
 	struct ldlm_namespace *ns = ldlm_res_to_ns(res);
-	cfs_hash_bd_t   bd;
+	struct cfs_hash_bd   bd;
 
 	LASSERT_ATOMIC_GT_LT(&res->lr_refcount, 0, LI_POISON);
 	CDEBUG(D_INFO, "putref res: %p count: %d\n",
@@ -1226,7 +1226,7 @@
 		cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 1);
 		if (ns->ns_lvbo && ns->ns_lvbo->lvbo_free)
 			ns->ns_lvbo->lvbo_free(res);
-		OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof *res);
+		OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof(*res));
 		return 1;
 	}
 	return 0;
@@ -1243,7 +1243,7 @@
 	       res, atomic_read(&res->lr_refcount) - 1);
 
 	if (atomic_dec_and_test(&res->lr_refcount)) {
-		cfs_hash_bd_t bd;
+		struct cfs_hash_bd bd;
 
 		cfs_hash_bd_get(ldlm_res_to_ns(res)->ns_rs_hash,
 				&res->lr_name, &bd);
@@ -1256,7 +1256,7 @@
 		 */
 		if (ns->ns_lvbo && ns->ns_lvbo->lvbo_free)
 			ns->ns_lvbo->lvbo_free(res);
-		OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof *res);
+		OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof(*res));
 
 		cfs_hash_bd_lock(ns->ns_rs_hash, &bd, 1);
 		return 1;
@@ -1352,7 +1352,7 @@
 }
 EXPORT_SYMBOL(ldlm_dump_all_namespaces);
 
-static int ldlm_res_hash_dump(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+static int ldlm_res_hash_dump(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 			      struct hlist_node *hnode, void *arg)
 {
 	struct ldlm_resource *res = cfs_hash_object(hs, hnode);
diff --git a/drivers/staging/lustre/lustre/libcfs/hash.c b/drivers/staging/lustre/lustre/libcfs/hash.c
index 0dd12c8..e3e0578 100644
--- a/drivers/staging/lustre/lustre/libcfs/hash.c
+++ b/drivers/staging/lustre/lustre/libcfs/hash.c
@@ -119,25 +119,25 @@
 struct cfs_wi_sched *cfs_sched_rehash;
 
 static inline void
-cfs_hash_nl_lock(cfs_hash_lock_t *lock, int exclusive) {}
+cfs_hash_nl_lock(union cfs_hash_lock *lock, int exclusive) {}
 
 static inline void
-cfs_hash_nl_unlock(cfs_hash_lock_t *lock, int exclusive) {}
+cfs_hash_nl_unlock(union cfs_hash_lock *lock, int exclusive) {}
 
 static inline void
-cfs_hash_spin_lock(cfs_hash_lock_t *lock, int exclusive)
+cfs_hash_spin_lock(union cfs_hash_lock *lock, int exclusive)
 {
 	spin_lock(&lock->spin);
 }
 
 static inline void
-cfs_hash_spin_unlock(cfs_hash_lock_t *lock, int exclusive)
+cfs_hash_spin_unlock(union cfs_hash_lock *lock, int exclusive)
 {
 	spin_unlock(&lock->spin);
 }
 
 static inline void
-cfs_hash_rw_lock(cfs_hash_lock_t *lock, int exclusive)
+cfs_hash_rw_lock(union cfs_hash_lock *lock, int exclusive)
 {
 	if (!exclusive)
 		read_lock(&lock->rw);
@@ -146,7 +146,7 @@
 }
 
 static inline void
-cfs_hash_rw_unlock(cfs_hash_lock_t *lock, int exclusive)
+cfs_hash_rw_unlock(union cfs_hash_lock *lock, int exclusive)
 {
 	if (!exclusive)
 		read_unlock(&lock->rw);
@@ -209,7 +209,7 @@
 };
 
 static void
-cfs_hash_lock_setup(cfs_hash_t *hs)
+cfs_hash_lock_setup(struct cfs_hash *hs)
 {
 	if (cfs_hash_with_no_lock(hs)) {
 		hs->hs_lops = &cfs_hash_nl_lops;
@@ -246,13 +246,13 @@
 } cfs_hash_head_t;
 
 static int
-cfs_hash_hh_hhead_size(cfs_hash_t *hs)
+cfs_hash_hh_hhead_size(struct cfs_hash *hs)
 {
 	return sizeof(cfs_hash_head_t);
 }
 
 static struct hlist_head *
-cfs_hash_hh_hhead(cfs_hash_t *hs, cfs_hash_bd_t *bd)
+cfs_hash_hh_hhead(struct cfs_hash *hs, struct cfs_hash_bd *bd)
 {
 	cfs_hash_head_t *head = (cfs_hash_head_t *)&bd->bd_bucket->hsb_head[0];
 
@@ -260,7 +260,7 @@
 }
 
 static int
-cfs_hash_hh_hnode_add(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+cfs_hash_hh_hnode_add(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 		      struct hlist_node *hnode)
 {
 	hlist_add_head(hnode, cfs_hash_hh_hhead(hs, bd));
@@ -268,7 +268,7 @@
 }
 
 static int
-cfs_hash_hh_hnode_del(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+cfs_hash_hh_hnode_del(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 		      struct hlist_node *hnode)
 {
 	hlist_del_init(hnode);
@@ -285,13 +285,13 @@
 } cfs_hash_head_dep_t;
 
 static int
-cfs_hash_hd_hhead_size(cfs_hash_t *hs)
+cfs_hash_hd_hhead_size(struct cfs_hash *hs)
 {
 	return sizeof(cfs_hash_head_dep_t);
 }
 
 static struct hlist_head *
-cfs_hash_hd_hhead(cfs_hash_t *hs, cfs_hash_bd_t *bd)
+cfs_hash_hd_hhead(struct cfs_hash *hs, struct cfs_hash_bd *bd)
 {
 	cfs_hash_head_dep_t   *head;
 
@@ -300,7 +300,7 @@
 }
 
 static int
-cfs_hash_hd_hnode_add(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+cfs_hash_hd_hnode_add(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 		      struct hlist_node *hnode)
 {
 	cfs_hash_head_dep_t *hh = container_of(cfs_hash_hd_hhead(hs, bd),
@@ -310,7 +310,7 @@
 }
 
 static int
-cfs_hash_hd_hnode_del(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+cfs_hash_hd_hnode_del(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 		      struct hlist_node *hnode)
 {
 	cfs_hash_head_dep_t *hh = container_of(cfs_hash_hd_hhead(hs, bd),
@@ -329,13 +329,13 @@
 } cfs_hash_dhead_t;
 
 static int
-cfs_hash_dh_hhead_size(cfs_hash_t *hs)
+cfs_hash_dh_hhead_size(struct cfs_hash *hs)
 {
 	return sizeof(cfs_hash_dhead_t);
 }
 
 static struct hlist_head *
-cfs_hash_dh_hhead(cfs_hash_t *hs, cfs_hash_bd_t *bd)
+cfs_hash_dh_hhead(struct cfs_hash *hs, struct cfs_hash_bd *bd)
 {
 	cfs_hash_dhead_t *head;
 
@@ -344,7 +344,7 @@
 }
 
 static int
-cfs_hash_dh_hnode_add(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+cfs_hash_dh_hnode_add(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 		      struct hlist_node *hnode)
 {
 	cfs_hash_dhead_t *dh = container_of(cfs_hash_dh_hhead(hs, bd),
@@ -359,7 +359,7 @@
 }
 
 static int
-cfs_hash_dh_hnode_del(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+cfs_hash_dh_hnode_del(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 		      struct hlist_node *hnd)
 {
 	cfs_hash_dhead_t *dh = container_of(cfs_hash_dh_hhead(hs, bd),
@@ -384,13 +384,13 @@
 } cfs_hash_dhead_dep_t;
 
 static int
-cfs_hash_dd_hhead_size(cfs_hash_t *hs)
+cfs_hash_dd_hhead_size(struct cfs_hash *hs)
 {
 	return sizeof(cfs_hash_dhead_dep_t);
 }
 
 static struct hlist_head *
-cfs_hash_dd_hhead(cfs_hash_t *hs, cfs_hash_bd_t *bd)
+cfs_hash_dd_hhead(struct cfs_hash *hs, struct cfs_hash_bd *bd)
 {
 	cfs_hash_dhead_dep_t *head;
 
@@ -399,7 +399,7 @@
 }
 
 static int
-cfs_hash_dd_hnode_add(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+cfs_hash_dd_hnode_add(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 		      struct hlist_node *hnode)
 {
 	cfs_hash_dhead_dep_t *dh = container_of(cfs_hash_dd_hhead(hs, bd),
@@ -414,7 +414,7 @@
 }
 
 static int
-cfs_hash_dd_hnode_del(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+cfs_hash_dd_hnode_del(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 		      struct hlist_node *hnd)
 {
 	cfs_hash_dhead_dep_t *dh = container_of(cfs_hash_dd_hhead(hs, bd),
@@ -457,7 +457,7 @@
 };
 
 static void
-cfs_hash_hlist_setup(cfs_hash_t *hs)
+cfs_hash_hlist_setup(struct cfs_hash *hs)
 {
 	if (cfs_hash_with_add_tail(hs)) {
 		hs->hs_hops = cfs_hash_with_depth(hs) ?
@@ -469,8 +469,8 @@
 }
 
 static void
-cfs_hash_bd_from_key(cfs_hash_t *hs, cfs_hash_bucket_t **bkts,
-		     unsigned int bits, const void *key, cfs_hash_bd_t *bd)
+cfs_hash_bd_from_key(struct cfs_hash *hs, struct cfs_hash_bucket **bkts,
+		     unsigned int bits, const void *key, struct cfs_hash_bd *bd)
 {
 	unsigned int index = cfs_hash_id(hs, key, (1U << bits) - 1);
 
@@ -481,7 +481,7 @@
 }
 
 void
-cfs_hash_bd_get(cfs_hash_t *hs, const void *key, cfs_hash_bd_t *bd)
+cfs_hash_bd_get(struct cfs_hash *hs, const void *key, struct cfs_hash_bd *bd)
 {
 	/* NB: caller should hold hs->hs_rwlock if REHASH is set */
 	if (likely(hs->hs_rehash_buckets == NULL)) {
@@ -496,7 +496,7 @@
 EXPORT_SYMBOL(cfs_hash_bd_get);
 
 static inline void
-cfs_hash_bd_dep_record(cfs_hash_t *hs, cfs_hash_bd_t *bd, int dep_cur)
+cfs_hash_bd_dep_record(struct cfs_hash *hs, struct cfs_hash_bd *bd, int dep_cur)
 {
 	if (likely(dep_cur <= bd->bd_bucket->hsb_depmax))
 		return;
@@ -519,7 +519,7 @@
 }
 
 void
-cfs_hash_bd_add_locked(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+cfs_hash_bd_add_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 		       struct hlist_node *hnode)
 {
 	int		rc;
@@ -539,7 +539,7 @@
 EXPORT_SYMBOL(cfs_hash_bd_add_locked);
 
 void
-cfs_hash_bd_del_locked(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+cfs_hash_bd_del_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 		       struct hlist_node *hnode)
 {
 	hs->hs_hops->hop_hnode_del(hs, bd, hnode);
@@ -560,11 +560,11 @@
 EXPORT_SYMBOL(cfs_hash_bd_del_locked);
 
 void
-cfs_hash_bd_move_locked(cfs_hash_t *hs, cfs_hash_bd_t *bd_old,
-			cfs_hash_bd_t *bd_new, struct hlist_node *hnode)
+cfs_hash_bd_move_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd_old,
+			struct cfs_hash_bd *bd_new, struct hlist_node *hnode)
 {
-	cfs_hash_bucket_t *obkt = bd_old->bd_bucket;
-	cfs_hash_bucket_t *nbkt = bd_new->bd_bucket;
+	struct cfs_hash_bucket *obkt = bd_old->bd_bucket;
+	struct cfs_hash_bucket *nbkt = bd_new->bd_bucket;
 	int		rc;
 
 	if (cfs_hash_bd_compare(bd_old, bd_new) == 0)
@@ -617,7 +617,7 @@
 } cfs_hash_lookup_intent_t;
 
 static struct hlist_node *
-cfs_hash_bd_lookup_intent(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+cfs_hash_bd_lookup_intent(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 			  const void *key, struct hlist_node *hnode,
 			  cfs_hash_lookup_intent_t intent)
 
@@ -658,7 +658,7 @@
 }
 
 struct hlist_node *
-cfs_hash_bd_lookup_locked(cfs_hash_t *hs, cfs_hash_bd_t *bd, const void *key)
+cfs_hash_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, const void *key)
 {
 	return cfs_hash_bd_lookup_intent(hs, bd, key, NULL,
 					 CFS_HS_LOOKUP_IT_FIND);
@@ -666,7 +666,7 @@
 EXPORT_SYMBOL(cfs_hash_bd_lookup_locked);
 
 struct hlist_node *
-cfs_hash_bd_peek_locked(cfs_hash_t *hs, cfs_hash_bd_t *bd, const void *key)
+cfs_hash_bd_peek_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd, const void *key)
 {
 	return cfs_hash_bd_lookup_intent(hs, bd, key, NULL,
 					 CFS_HS_LOOKUP_IT_PEEK);
@@ -674,7 +674,7 @@
 EXPORT_SYMBOL(cfs_hash_bd_peek_locked);
 
 struct hlist_node *
-cfs_hash_bd_findadd_locked(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+cfs_hash_bd_findadd_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 			   const void *key, struct hlist_node *hnode,
 			   int noref)
 {
@@ -685,7 +685,7 @@
 EXPORT_SYMBOL(cfs_hash_bd_findadd_locked);
 
 struct hlist_node *
-cfs_hash_bd_finddel_locked(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+cfs_hash_bd_finddel_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 			   const void *key, struct hlist_node *hnode)
 {
 	/* hnode can be NULL, we find the first item with @key */
@@ -695,10 +695,10 @@
 EXPORT_SYMBOL(cfs_hash_bd_finddel_locked);
 
 static void
-cfs_hash_multi_bd_lock(cfs_hash_t *hs, cfs_hash_bd_t *bds,
+cfs_hash_multi_bd_lock(struct cfs_hash *hs, struct cfs_hash_bd *bds,
 		       unsigned n, int excl)
 {
-	cfs_hash_bucket_t *prev = NULL;
+	struct cfs_hash_bucket *prev = NULL;
 	int		i;
 
 	/**
@@ -718,10 +718,10 @@
 }
 
 static void
-cfs_hash_multi_bd_unlock(cfs_hash_t *hs, cfs_hash_bd_t *bds,
+cfs_hash_multi_bd_unlock(struct cfs_hash *hs, struct cfs_hash_bd *bds,
 			 unsigned n, int excl)
 {
-	cfs_hash_bucket_t *prev = NULL;
+	struct cfs_hash_bucket *prev = NULL;
 	int		i;
 
 	cfs_hash_for_each_bd(bds, n, i) {
@@ -733,7 +733,7 @@
 }
 
 static struct hlist_node *
-cfs_hash_multi_bd_lookup_locked(cfs_hash_t *hs, cfs_hash_bd_t *bds,
+cfs_hash_multi_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds,
 				unsigned n, const void *key)
 {
 	struct hlist_node  *ehnode;
@@ -749,8 +749,8 @@
 }
 
 static struct hlist_node *
-cfs_hash_multi_bd_findadd_locked(cfs_hash_t *hs,
-				 cfs_hash_bd_t *bds, unsigned n, const void *key,
+cfs_hash_multi_bd_findadd_locked(struct cfs_hash *hs,
+				 struct cfs_hash_bd *bds, unsigned n, const void *key,
 				 struct hlist_node *hnode, int noref)
 {
 	struct hlist_node  *ehnode;
@@ -770,7 +770,7 @@
 	if (i == 1) { /* only one bucket */
 		cfs_hash_bd_add_locked(hs, &bds[0], hnode);
 	} else {
-		cfs_hash_bd_t      mybd;
+		struct cfs_hash_bd      mybd;
 
 		cfs_hash_bd_get(hs, key, &mybd);
 		cfs_hash_bd_add_locked(hs, &mybd, hnode);
@@ -780,7 +780,7 @@
 }
 
 static struct hlist_node *
-cfs_hash_multi_bd_finddel_locked(cfs_hash_t *hs, cfs_hash_bd_t *bds,
+cfs_hash_multi_bd_finddel_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds,
 				 unsigned n, const void *key,
 				 struct hlist_node *hnode)
 {
@@ -797,7 +797,7 @@
 }
 
 static void
-cfs_hash_bd_order(cfs_hash_bd_t *bd1, cfs_hash_bd_t *bd2)
+cfs_hash_bd_order(struct cfs_hash_bd *bd1, struct cfs_hash_bd *bd2)
 {
 	int     rc;
 
@@ -815,7 +815,7 @@
 		bd2->bd_bucket = NULL;
 
 	} else if (rc > 0) { /* swab bd1 and bd2 */
-		cfs_hash_bd_t tmp;
+		struct cfs_hash_bd tmp;
 
 		tmp = *bd2;
 		*bd2 = *bd1;
@@ -824,7 +824,7 @@
 }
 
 void
-cfs_hash_dual_bd_get(cfs_hash_t *hs, const void *key, cfs_hash_bd_t *bds)
+cfs_hash_dual_bd_get(struct cfs_hash *hs, const void *key, struct cfs_hash_bd *bds)
 {
 	/* NB: caller should hold hs_lock.rw if REHASH is set */
 	cfs_hash_bd_from_key(hs, hs->hs_buckets,
@@ -844,21 +844,21 @@
 EXPORT_SYMBOL(cfs_hash_dual_bd_get);
 
 void
-cfs_hash_dual_bd_lock(cfs_hash_t *hs, cfs_hash_bd_t *bds, int excl)
+cfs_hash_dual_bd_lock(struct cfs_hash *hs, struct cfs_hash_bd *bds, int excl)
 {
 	cfs_hash_multi_bd_lock(hs, bds, 2, excl);
 }
 EXPORT_SYMBOL(cfs_hash_dual_bd_lock);
 
 void
-cfs_hash_dual_bd_unlock(cfs_hash_t *hs, cfs_hash_bd_t *bds, int excl)
+cfs_hash_dual_bd_unlock(struct cfs_hash *hs, struct cfs_hash_bd *bds, int excl)
 {
 	cfs_hash_multi_bd_unlock(hs, bds, 2, excl);
 }
 EXPORT_SYMBOL(cfs_hash_dual_bd_unlock);
 
 struct hlist_node *
-cfs_hash_dual_bd_lookup_locked(cfs_hash_t *hs, cfs_hash_bd_t *bds,
+cfs_hash_dual_bd_lookup_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds,
 			       const void *key)
 {
 	return cfs_hash_multi_bd_lookup_locked(hs, bds, 2, key);
@@ -866,7 +866,7 @@
 EXPORT_SYMBOL(cfs_hash_dual_bd_lookup_locked);
 
 struct hlist_node *
-cfs_hash_dual_bd_findadd_locked(cfs_hash_t *hs, cfs_hash_bd_t *bds,
+cfs_hash_dual_bd_findadd_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds,
 				const void *key, struct hlist_node *hnode,
 				int noref)
 {
@@ -876,7 +876,7 @@
 EXPORT_SYMBOL(cfs_hash_dual_bd_findadd_locked);
 
 struct hlist_node *
-cfs_hash_dual_bd_finddel_locked(cfs_hash_t *hs, cfs_hash_bd_t *bds,
+cfs_hash_dual_bd_finddel_locked(struct cfs_hash *hs, struct cfs_hash_bd *bds,
 				const void *key, struct hlist_node *hnode)
 {
 	return cfs_hash_multi_bd_finddel_locked(hs, bds, 2, key, hnode);
@@ -884,7 +884,7 @@
 EXPORT_SYMBOL(cfs_hash_dual_bd_finddel_locked);
 
 static void
-cfs_hash_buckets_free(cfs_hash_bucket_t **buckets,
+cfs_hash_buckets_free(struct cfs_hash_bucket **buckets,
 		      int bkt_size, int prev_size, int size)
 {
 	int     i;
@@ -902,11 +902,11 @@
  * needed, the newly allocated buckets if allocation was needed and
  * successful, and NULL on error.
  */
-static cfs_hash_bucket_t **
-cfs_hash_buckets_realloc(cfs_hash_t *hs, cfs_hash_bucket_t **old_bkts,
+static struct cfs_hash_bucket **
+cfs_hash_buckets_realloc(struct cfs_hash *hs, struct cfs_hash_bucket **old_bkts,
 			 unsigned int old_size, unsigned int new_size)
 {
-	cfs_hash_bucket_t **new_bkts;
+	struct cfs_hash_bucket **new_bkts;
 	int		 i;
 
 	LASSERT(old_size == 0 || old_bkts != NULL);
@@ -925,7 +925,7 @@
 
 	for (i = old_size; i < new_size; i++) {
 		struct hlist_head *hhead;
-		cfs_hash_bd_t     bd;
+		struct cfs_hash_bd     bd;
 
 		LIBCFS_ALLOC(new_bkts[i], cfs_hash_bkt_size(hs));
 		if (new_bkts[i] == NULL) {
@@ -969,7 +969,7 @@
 #if CFS_HASH_DEBUG_LEVEL >= CFS_HASH_DEBUG_1
 static int cfs_hash_dep_print(cfs_workitem_t *wi)
 {
-	cfs_hash_t *hs = container_of(wi, cfs_hash_t, hs_dep_wi);
+	struct cfs_hash *hs = container_of(wi, struct cfs_hash, hs_dep_wi);
 	int	 dep;
 	int	 bkt;
 	int	 off;
@@ -990,13 +990,13 @@
 	return 0;
 }
 
-static void cfs_hash_depth_wi_init(cfs_hash_t *hs)
+static void cfs_hash_depth_wi_init(struct cfs_hash *hs)
 {
 	spin_lock_init(&hs->hs_dep_lock);
 	cfs_wi_init(&hs->hs_dep_wi, hs, cfs_hash_dep_print);
 }
 
-static void cfs_hash_depth_wi_cancel(cfs_hash_t *hs)
+static void cfs_hash_depth_wi_cancel(struct cfs_hash *hs)
 {
 	if (cfs_wi_deschedule(cfs_sched_rehash, &hs->hs_dep_wi))
 		return;
@@ -1012,18 +1012,18 @@
 
 #else /* CFS_HASH_DEBUG_LEVEL < CFS_HASH_DEBUG_1 */
 
-static inline void cfs_hash_depth_wi_init(cfs_hash_t *hs) {}
-static inline void cfs_hash_depth_wi_cancel(cfs_hash_t *hs) {}
+static inline void cfs_hash_depth_wi_init(struct cfs_hash *hs) {}
+static inline void cfs_hash_depth_wi_cancel(struct cfs_hash *hs) {}
 
 #endif /* CFS_HASH_DEBUG_LEVEL >= CFS_HASH_DEBUG_1 */
 
-cfs_hash_t *
+struct cfs_hash *
 cfs_hash_create(char *name, unsigned cur_bits, unsigned max_bits,
 		unsigned bkt_bits, unsigned extra_bytes,
 		unsigned min_theta, unsigned max_theta,
 		cfs_hash_ops_t *ops, unsigned flags)
 {
-	cfs_hash_t *hs;
+	struct cfs_hash *hs;
 	int	 len;
 
 	CLASSERT(CFS_HASH_THETA_BITS < 15);
@@ -1051,7 +1051,7 @@
 
 	len = (flags & CFS_HASH_BIGNAME) == 0 ?
 	      CFS_HASH_NAME_LEN : CFS_HASH_BIGNAME_LEN;
-	LIBCFS_ALLOC(hs, offsetof(cfs_hash_t, hs_name[len]));
+	LIBCFS_ALLOC(hs, offsetof(struct cfs_hash, hs_name[len]));
 	if (hs == NULL)
 		return NULL;
 
@@ -1084,7 +1084,7 @@
 	if (hs->hs_buckets != NULL)
 		return hs;
 
-	LIBCFS_FREE(hs, offsetof(cfs_hash_t, hs_name[len]));
+	LIBCFS_FREE(hs, offsetof(struct cfs_hash, hs_name[len]));
 	return NULL;
 }
 EXPORT_SYMBOL(cfs_hash_create);
@@ -1093,11 +1093,11 @@
  * Cleanup libcfs hash @hs.
  */
 static void
-cfs_hash_destroy(cfs_hash_t *hs)
+cfs_hash_destroy(struct cfs_hash *hs)
 {
 	struct hlist_node     *hnode;
 	struct hlist_node     *pos;
-	cfs_hash_bd_t	 bd;
+	struct cfs_hash_bd	 bd;
 	int		   i;
 
 	LASSERT(hs != NULL);
@@ -1148,10 +1148,10 @@
 			      0, CFS_HASH_NBKT(hs));
 	i = cfs_hash_with_bigname(hs) ?
 	    CFS_HASH_BIGNAME_LEN : CFS_HASH_NAME_LEN;
-	LIBCFS_FREE(hs, offsetof(cfs_hash_t, hs_name[i]));
+	LIBCFS_FREE(hs, offsetof(struct cfs_hash, hs_name[i]));
 }
 
-cfs_hash_t *cfs_hash_getref(cfs_hash_t *hs)
+struct cfs_hash *cfs_hash_getref(struct cfs_hash *hs)
 {
 	if (atomic_inc_not_zero(&hs->hs_refcount))
 		return hs;
@@ -1159,7 +1159,7 @@
 }
 EXPORT_SYMBOL(cfs_hash_getref);
 
-void cfs_hash_putref(cfs_hash_t *hs)
+void cfs_hash_putref(struct cfs_hash *hs)
 {
 	if (atomic_dec_and_test(&hs->hs_refcount))
 		cfs_hash_destroy(hs);
@@ -1167,7 +1167,7 @@
 EXPORT_SYMBOL(cfs_hash_putref);
 
 static inline int
-cfs_hash_rehash_bits(cfs_hash_t *hs)
+cfs_hash_rehash_bits(struct cfs_hash *hs)
 {
 	if (cfs_hash_with_no_lock(hs) ||
 	    !cfs_hash_with_rehash(hs))
@@ -1204,7 +1204,7 @@
  * - too many elements
  */
 static inline int
-cfs_hash_rehash_inline(cfs_hash_t *hs)
+cfs_hash_rehash_inline(struct cfs_hash *hs)
 {
 	return !cfs_hash_with_nblk_change(hs) &&
 	       atomic_read(&hs->hs_count) < CFS_HASH_LOOP_HOG;
@@ -1215,9 +1215,9 @@
  * ops->hs_get function will be called when the item is added.
  */
 void
-cfs_hash_add(cfs_hash_t *hs, const void *key, struct hlist_node *hnode)
+cfs_hash_add(struct cfs_hash *hs, const void *key, struct hlist_node *hnode)
 {
-	cfs_hash_bd_t   bd;
+	struct cfs_hash_bd   bd;
 	int	     bits;
 
 	LASSERT(hlist_unhashed(hnode));
@@ -1238,11 +1238,11 @@
 EXPORT_SYMBOL(cfs_hash_add);
 
 static struct hlist_node *
-cfs_hash_find_or_add(cfs_hash_t *hs, const void *key,
+cfs_hash_find_or_add(struct cfs_hash *hs, const void *key,
 		     struct hlist_node *hnode, int noref)
 {
 	struct hlist_node *ehnode;
-	cfs_hash_bd_t     bds[2];
+	struct cfs_hash_bd     bds[2];
 	int	       bits = 0;
 
 	LASSERT(hlist_unhashed(hnode));
@@ -1270,7 +1270,7 @@
  * Returns 0 on success or -EALREADY on key collisions.
  */
 int
-cfs_hash_add_unique(cfs_hash_t *hs, const void *key, struct hlist_node *hnode)
+cfs_hash_add_unique(struct cfs_hash *hs, const void *key, struct hlist_node *hnode)
 {
 	return cfs_hash_find_or_add(hs, key, hnode, 1) != hnode ?
 	       -EALREADY : 0;
@@ -1284,7 +1284,7 @@
  * Otherwise ops->hs_get is called on the item which was added.
  */
 void *
-cfs_hash_findadd_unique(cfs_hash_t *hs, const void *key,
+cfs_hash_findadd_unique(struct cfs_hash *hs, const void *key,
 			struct hlist_node *hnode)
 {
 	hnode = cfs_hash_find_or_add(hs, key, hnode, 0);
@@ -1301,11 +1301,11 @@
  * on the removed object.
  */
 void *
-cfs_hash_del(cfs_hash_t *hs, const void *key, struct hlist_node *hnode)
+cfs_hash_del(struct cfs_hash *hs, const void *key, struct hlist_node *hnode)
 {
 	void	   *obj  = NULL;
 	int	     bits = 0;
-	cfs_hash_bd_t   bds[2];
+	struct cfs_hash_bd   bds[2];
 
 	cfs_hash_lock(hs, 0);
 	cfs_hash_dual_bd_get_and_lock(hs, key, bds, 1);
@@ -1341,7 +1341,7 @@
  * will be returned and ops->hs_put is called on the removed object.
  */
 void *
-cfs_hash_del_key(cfs_hash_t *hs, const void *key)
+cfs_hash_del_key(struct cfs_hash *hs, const void *key)
 {
 	return cfs_hash_del(hs, key, NULL);
 }
@@ -1356,11 +1356,11 @@
  * in the hash @hs NULL is returned.
  */
 void *
-cfs_hash_lookup(cfs_hash_t *hs, const void *key)
+cfs_hash_lookup(struct cfs_hash *hs, const void *key)
 {
 	void		 *obj = NULL;
 	struct hlist_node     *hnode;
-	cfs_hash_bd_t	 bds[2];
+	struct cfs_hash_bd	 bds[2];
 
 	cfs_hash_lock(hs, 0);
 	cfs_hash_dual_bd_get_and_lock(hs, key, bds, 0);
@@ -1377,7 +1377,7 @@
 EXPORT_SYMBOL(cfs_hash_lookup);
 
 static void
-cfs_hash_for_each_enter(cfs_hash_t *hs)
+cfs_hash_for_each_enter(struct cfs_hash *hs)
 {
 	LASSERT(!cfs_hash_is_exiting(hs));
 
@@ -1403,7 +1403,7 @@
 }
 
 static void
-cfs_hash_for_each_exit(cfs_hash_t *hs)
+cfs_hash_for_each_exit(struct cfs_hash *hs)
 {
 	int remained;
 	int bits;
@@ -1434,12 +1434,12 @@
  *      cfs_hash_bd_del_locked
  */
 static __u64
-cfs_hash_for_each_tight(cfs_hash_t *hs, cfs_hash_for_each_cb_t func,
+cfs_hash_for_each_tight(struct cfs_hash *hs, cfs_hash_for_each_cb_t func,
 			void *data, int remove_safe)
 {
 	struct hlist_node     *hnode;
 	struct hlist_node     *pos;
-	cfs_hash_bd_t	 bd;
+	struct cfs_hash_bd	 bd;
 	__u64		 count = 0;
 	int		   excl  = !!remove_safe;
 	int		   loop  = 0;
@@ -1492,7 +1492,7 @@
 } cfs_hash_cond_arg_t;
 
 static int
-cfs_hash_cond_del_locked(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+cfs_hash_cond_del_locked(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 			 struct hlist_node *hnode, void *data)
 {
 	cfs_hash_cond_arg_t *cond = data;
@@ -1508,7 +1508,7 @@
  * any object be reference.
  */
 void
-cfs_hash_cond_del(cfs_hash_t *hs, cfs_hash_cond_opt_cb_t func, void *data)
+cfs_hash_cond_del(struct cfs_hash *hs, cfs_hash_cond_opt_cb_t func, void *data)
 {
 	cfs_hash_cond_arg_t arg = {
 		.func   = func,
@@ -1520,7 +1520,7 @@
 EXPORT_SYMBOL(cfs_hash_cond_del);
 
 void
-cfs_hash_for_each(cfs_hash_t *hs,
+cfs_hash_for_each(struct cfs_hash *hs,
 		  cfs_hash_for_each_cb_t func, void *data)
 {
 	cfs_hash_for_each_tight(hs, func, data, 0);
@@ -1528,7 +1528,7 @@
 EXPORT_SYMBOL(cfs_hash_for_each);
 
 void
-cfs_hash_for_each_safe(cfs_hash_t *hs,
+cfs_hash_for_each_safe(struct cfs_hash *hs,
 		       cfs_hash_for_each_cb_t func, void *data)
 {
 	cfs_hash_for_each_tight(hs, func, data, 1);
@@ -1536,7 +1536,7 @@
 EXPORT_SYMBOL(cfs_hash_for_each_safe);
 
 static int
-cfs_hash_peek(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+cfs_hash_peek(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 	      struct hlist_node *hnode, void *data)
 {
 	*(int *)data = 0;
@@ -1544,7 +1544,7 @@
 }
 
 int
-cfs_hash_is_empty(cfs_hash_t *hs)
+cfs_hash_is_empty(struct cfs_hash *hs)
 {
 	int empty = 1;
 
@@ -1554,7 +1554,7 @@
 EXPORT_SYMBOL(cfs_hash_is_empty);
 
 __u64
-cfs_hash_size_get(cfs_hash_t *hs)
+cfs_hash_size_get(struct cfs_hash *hs)
 {
 	return cfs_hash_with_counter(hs) ?
 	       atomic_read(&hs->hs_count) :
@@ -1578,11 +1578,11 @@
  * two cases, so iteration has to be stopped on change.
  */
 static int
-cfs_hash_for_each_relax(cfs_hash_t *hs, cfs_hash_for_each_cb_t func, void *data)
+cfs_hash_for_each_relax(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, void *data)
 {
 	struct hlist_node *hnode;
 	struct hlist_node *tmp;
-	cfs_hash_bd_t     bd;
+	struct cfs_hash_bd     bd;
 	__u32	     version;
 	int	       count = 0;
 	int	       stop_on_change;
@@ -1639,7 +1639,7 @@
 }
 
 int
-cfs_hash_for_each_nolock(cfs_hash_t *hs,
+cfs_hash_for_each_nolock(struct cfs_hash *hs,
 			 cfs_hash_for_each_cb_t func, void *data)
 {
 	if (cfs_hash_with_no_lock(hs) ||
@@ -1672,7 +1672,7 @@
  * the required locking is in place to prevent concurrent insertions.
  */
 int
-cfs_hash_for_each_empty(cfs_hash_t *hs,
+cfs_hash_for_each_empty(struct cfs_hash *hs,
 			cfs_hash_for_each_cb_t func, void *data)
 {
 	unsigned  i = 0;
@@ -1696,12 +1696,12 @@
 EXPORT_SYMBOL(cfs_hash_for_each_empty);
 
 void
-cfs_hash_hlist_for_each(cfs_hash_t *hs, unsigned hindex,
+cfs_hash_hlist_for_each(struct cfs_hash *hs, unsigned hindex,
 			cfs_hash_for_each_cb_t func, void *data)
 {
 	struct hlist_head   *hhead;
 	struct hlist_node   *hnode;
-	cfs_hash_bd_t       bd;
+	struct cfs_hash_bd       bd;
 
 	cfs_hash_for_each_enter(hs);
 	cfs_hash_lock(hs, 0);
@@ -1731,11 +1731,11 @@
  * is held so the callback must never sleep.
    */
 void
-cfs_hash_for_each_key(cfs_hash_t *hs, const void *key,
+cfs_hash_for_each_key(struct cfs_hash *hs, const void *key,
 		      cfs_hash_for_each_cb_t func, void *data)
 {
 	struct hlist_node   *hnode;
-	cfs_hash_bd_t       bds[2];
+	struct cfs_hash_bd       bds[2];
 	unsigned	    i;
 
 	cfs_hash_lock(hs, 0);
@@ -1772,7 +1772,7 @@
  * theta thresholds for @hs are tunable via cfs_hash_set_theta().
  */
 void
-cfs_hash_rehash_cancel_locked(cfs_hash_t *hs)
+cfs_hash_rehash_cancel_locked(struct cfs_hash *hs)
 {
 	int     i;
 
@@ -1801,7 +1801,7 @@
 EXPORT_SYMBOL(cfs_hash_rehash_cancel_locked);
 
 void
-cfs_hash_rehash_cancel(cfs_hash_t *hs)
+cfs_hash_rehash_cancel(struct cfs_hash *hs)
 {
 	cfs_hash_lock(hs, 1);
 	cfs_hash_rehash_cancel_locked(hs);
@@ -1810,7 +1810,7 @@
 EXPORT_SYMBOL(cfs_hash_rehash_cancel);
 
 int
-cfs_hash_rehash(cfs_hash_t *hs, int do_rehash)
+cfs_hash_rehash(struct cfs_hash *hs, int do_rehash)
 {
 	int     rc;
 
@@ -1840,9 +1840,9 @@
 EXPORT_SYMBOL(cfs_hash_rehash);
 
 static int
-cfs_hash_rehash_bd(cfs_hash_t *hs, cfs_hash_bd_t *old)
+cfs_hash_rehash_bd(struct cfs_hash *hs, struct cfs_hash_bd *old)
 {
-	cfs_hash_bd_t      new;
+	struct cfs_hash_bd      new;
 	struct hlist_head  *hhead;
 	struct hlist_node  *hnode;
 	struct hlist_node  *pos;
@@ -1873,9 +1873,9 @@
 static int
 cfs_hash_rehash_worker(cfs_workitem_t *wi)
 {
-	cfs_hash_t	 *hs = container_of(wi, cfs_hash_t, hs_rehash_wi);
-	cfs_hash_bucket_t **bkts;
-	cfs_hash_bd_t       bd;
+	struct cfs_hash	 *hs = container_of(wi, struct cfs_hash, hs_rehash_wi);
+	struct cfs_hash_bucket **bkts;
+	struct cfs_hash_bd       bd;
 	unsigned int	old_size;
 	unsigned int	new_size;
 	int		 bsize;
@@ -1965,7 +1965,7 @@
 	if (bkts != NULL)
 		cfs_hash_buckets_free(bkts, bsize, new_size, old_size);
 	if (rc != 0)
-		CDEBUG(D_INFO, "early quit of of rehashing: %d\n", rc);
+		CDEBUG(D_INFO, "early quit of rehashing: %d\n", rc);
 	/* return 1 only if cfs_wi_exit is called */
 	return rc == -ESRCH;
 }
@@ -1980,12 +1980,12 @@
  * the registered cfs_hash_get() and cfs_hash_put() functions will
  * not be called.
  */
-void cfs_hash_rehash_key(cfs_hash_t *hs, const void *old_key,
+void cfs_hash_rehash_key(struct cfs_hash *hs, const void *old_key,
 			 void *new_key, struct hlist_node *hnode)
 {
-	cfs_hash_bd_t	bds[3];
-	cfs_hash_bd_t	old_bds[2];
-	cfs_hash_bd_t	new_bd;
+	struct cfs_hash_bd	bds[3];
+	struct cfs_hash_bd	old_bds[2];
+	struct cfs_hash_bd	new_bd;
 
 	LASSERT(!hlist_unhashed(hnode));
 
@@ -2028,8 +2028,8 @@
 }
 EXPORT_SYMBOL(cfs_hash_debug_header);
 
-static cfs_hash_bucket_t **
-cfs_hash_full_bkts(cfs_hash_t *hs)
+static struct cfs_hash_bucket **
+cfs_hash_full_bkts(struct cfs_hash *hs)
 {
 	/* NB: caller should hold hs->hs_rwlock if REHASH is set */
 	if (hs->hs_rehash_buckets == NULL)
@@ -2041,7 +2041,7 @@
 }
 
 static unsigned int
-cfs_hash_full_nbkt(cfs_hash_t *hs)
+cfs_hash_full_nbkt(struct cfs_hash *hs)
 {
 	/* NB: caller should hold hs->hs_rwlock if REHASH is set */
 	if (hs->hs_rehash_buckets == NULL)
@@ -2052,7 +2052,7 @@
 	       CFS_HASH_RH_NBKT(hs) : CFS_HASH_NBKT(hs);
 }
 
-int cfs_hash_debug_str(cfs_hash_t *hs, struct seq_file *m)
+int cfs_hash_debug_str(struct cfs_hash *hs, struct seq_file *m)
 {
 	int		    dist[8] = { 0, };
 	int		    maxdep  = -1;
@@ -2089,7 +2089,7 @@
 	 * Non-Uniform hash distribution:  128/125/0/0/0/0/2/1
 	 */
 	for (i = 0; i < cfs_hash_full_nbkt(hs); i++) {
-		cfs_hash_bd_t  bd;
+		struct cfs_hash_bd  bd;
 
 		bd.bd_bucket = cfs_hash_full_bkts(hs)[i];
 		cfs_hash_bd_lock(hs, &bd, 0);
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c
index ea9e949..0bf8e5d 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c
@@ -167,7 +167,7 @@
 		return 0;
 
 	down_read(&mm->mmap_sem);
-	/* ignore errors, just check how much was sucessfully transfered */
+	/* ignore errors, just check how much was successfully transferred */
 	while (len) {
 		int bytes, rc, offset;
 		void *maddr;
@@ -227,8 +227,10 @@
 	 * which is already holding mmap_sem for writes.  If some other
 	 * thread gets the write lock in the meantime, this thread will
 	 * block, but at least it won't deadlock on itself.  LU-1735 */
-	if (down_read_trylock(&mm->mmap_sem) == 0)
+	if (down_read_trylock(&mm->mmap_sem) == 0) {
+		kfree(buffer);
 		return -EDEADLK;
+	}
 	up_read(&mm->mmap_sem);
 
 	addr = mm->env_start;
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c
index ab1e731..cc565b1 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c
@@ -137,7 +137,7 @@
 	char *argv[6];
 	char buf[32];
 
-	snprintf (buf, sizeof buf, "%d", msgdata->msg_line);
+	snprintf(buf, sizeof(buf), "%d", msgdata->msg_line);
 
 	argv[1] = "LBUG";
 	argv[2] = (char *)msgdata->msg_file;
diff --git a/drivers/staging/lustre/lustre/libcfs/prng.c b/drivers/staging/lustre/lustre/libcfs/prng.c
index 69224d8..f87e9e5 100644
--- a/drivers/staging/lustre/lustre/libcfs/prng.c
+++ b/drivers/staging/lustre/lustre/libcfs/prng.c
@@ -70,7 +70,7 @@
  * cfs_rand - creates new seeds
  *
  * First it creates new seeds from the previous seeds. Then it generates a
- * new psuedo random number for use.
+ * new pseudo random number for use.
  *
  * Returns a pseudo-random 32-bit integer
  */
@@ -84,7 +84,7 @@
 EXPORT_SYMBOL(cfs_rand);
 
 /**
- * cfs_srand - sets the inital seed
+ * cfs_srand - sets the initial seed
  * @seed1 : (seed_x) should have the most entropy in the low bits of the word
  * @seed2 : (seed_y) should have the most entropy in the high bits of the word
  *
diff --git a/drivers/staging/lustre/lustre/libcfs/tracefile.c b/drivers/staging/lustre/lustre/libcfs/tracefile.c
index 357f400..f71a3cc 100644
--- a/drivers/staging/lustre/lustre/libcfs/tracefile.c
+++ b/drivers/staging/lustre/lustre/libcfs/tracefile.c
@@ -276,7 +276,7 @@
 	int			remain;
 	int			mask = msgdata->msg_mask;
 	const char		*file = kbasename(msgdata->msg_file);
-	cfs_debug_limit_state_t   *cdls = msgdata->msg_cdls;
+	struct cfs_debug_limit_state   *cdls = msgdata->msg_cdls;
 
 	tcd = cfs_trace_get_tcd();
 
diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c
index 09844be..1f07903 100644
--- a/drivers/staging/lustre/lustre/llite/dir.c
+++ b/drivers/staging/lustre/lustre/llite/dir.c
@@ -743,7 +743,7 @@
 
 	/* In the following we use the fact that LOV_USER_MAGIC_V1 and
 	 LOV_USER_MAGIC_V3 have the same initial fields so we do not
-	 need the make the distiction between the 2 versions */
+	 need to make the distinction between the 2 versions */
 	if (set_default && mgc->u.cli.cl_mgc_mgsexp) {
 		char *param = NULL;
 		char *buf;
diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c
index bc534db..fb85a58 100644
--- a/drivers/staging/lustre/lustre/llite/file.c
+++ b/drivers/staging/lustre/lustre/llite/file.c
@@ -364,7 +364,7 @@
 	   that case that lock is also ok */
 	/* We can also get here if there was cached open handle in revalidate_it
 	 * but it disappeared while we were getting from there to ll_file_open.
-	 * But this means this file was closed and immediatelly opened which
+	 * But this means this file was closed and immediately opened which
 	 * makes a good candidate for using OPEN lock */
 	/* If lmmsize & lmm are not 0, we are just setting stripe info
 	 * parameters. No need for the open lock */
@@ -2456,8 +2456,8 @@
 	if (rc == -ENOENT) {
 		clear_nlink(inode);
 		/* This path cannot be hit for regular files unless in
-		 * case of obscure races, so no need to to validate
-		 * size. */
+		 * case of obscure races, so no need to validate size.
+		 */
 		if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
 			return 0;
 	} else if (rc != 0) {
@@ -3011,7 +3011,7 @@
 
 	/* set layout to file. Unlikely this will fail as old layout was
 	 * surely eliminated */
-	memset(&conf, 0, sizeof conf);
+	memset(&conf, 0, sizeof(conf));
 	conf.coc_opc = OBJECT_CONF_SET;
 	conf.coc_inode = inode;
 	conf.coc_lock = lock;
@@ -3034,7 +3034,7 @@
 			ll_get_fsname(inode->i_sb, NULL, 0),
 			inode, PFID(&lli->lli_fid));
 
-		memset(&conf, 0, sizeof conf);
+		memset(&conf, 0, sizeof(conf));
 		conf.coc_opc = OBJECT_CONF_WAIT;
 		conf.coc_inode = inode;
 		rc = ll_layout_conf(inode, &conf);
diff --git a/drivers/staging/lustre/lustre/llite/llite_close.c b/drivers/staging/lustre/lustre/llite/llite_close.c
index 1f5825c8..e2996c4 100644
--- a/drivers/staging/lustre/lustre/llite/llite_close.c
+++ b/drivers/staging/lustre/lustre/llite/llite_close.c
@@ -159,7 +159,7 @@
 		}
 		if (flags & LLIF_DONE_WRITING) {
 			/* Some pages are still dirty, it is early to send
-			 * DONE_WRITE. Wait untill all pages will be flushed
+			 * DONE_WRITE. Wait until all pages will be flushed
 			 * and try DONE_WRITE again later. */
 			LASSERT(!(lli->lli_flags & LLIF_DONE_WRITING));
 			lli->lli_flags |= LLIF_DONE_WRITING;
diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c
index b868c2b..fd584ff 100644
--- a/drivers/staging/lustre/lustre/llite/llite_lib.c
+++ b/drivers/staging/lustre/lustre/llite/llite_lib.c
@@ -1973,10 +1973,10 @@
 	OBD_ALLOC_PTR(ioc_data);
 	if (ioc_data) {
 		obd_iocontrol(IOC_OSC_SET_ACTIVE, sbi->ll_md_exp,
-			      sizeof *ioc_data, ioc_data, NULL);
+			      sizeof(*ioc_data), ioc_data, NULL);
 
 		obd_iocontrol(IOC_OSC_SET_ACTIVE, sbi->ll_dt_exp,
-			      sizeof *ioc_data, ioc_data, NULL);
+			      sizeof(*ioc_data), ioc_data, NULL);
 
 		OBD_FREE_PTR(ioc_data);
 	}
diff --git a/drivers/staging/lustre/lustre/llite/lloop.c b/drivers/staging/lustre/lustre/llite/lloop.c
index 2340458..e2421ea 100644
--- a/drivers/staging/lustre/lustre/llite/lloop.c
+++ b/drivers/staging/lustre/lustre/llite/lloop.c
@@ -337,8 +337,7 @@
 	return count;
 }
 
-static ll_mrf_ret
-loop_make_request(struct request_queue *q, struct bio *old_bio)
+static void loop_make_request(struct request_queue *q, struct bio *old_bio)
 {
 	struct lloop_device *lo = q->queuedata;
 	int rw = bio_rw(old_bio);
@@ -366,10 +365,9 @@
 		goto err;
 	}
 	loop_add_bio(lo, old_bio);
-	LL_MRF_RETURN(0);
+	return;
 err:
 	cfs_bio_io_error(old_bio, old_bio->bi_size);
-	LL_MRF_RETURN(0);
 }
 
 
diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c
index d4d3c17..4bf09c4 100644
--- a/drivers/staging/lustre/lustre/llite/lproc_llite.c
+++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c
@@ -1063,7 +1063,7 @@
 		return 0;
 	}
 	seq_printf(seq, "snapshot_time:	 %lu.%lu (secs.usecs)\n",
-		   now.tv_sec, now.tv_usec);
+		   now.tv_sec, (unsigned long)now.tv_usec);
 	seq_printf(seq, "%15s %19s       | %20s\n", " ", "read", "write");
 	seq_printf(seq, "%13s   %14s %4s %4s  | %14s %4s %4s\n",
 		   "extents", "calls", "%", "cum%",
@@ -1127,7 +1127,7 @@
 		return 0;
 	}
 	seq_printf(seq, "snapshot_time:	 %lu.%lu (secs.usecs)\n",
-		   now.tv_sec, now.tv_usec);
+		   now.tv_sec, (unsigned long)now.tv_usec);
 
 	seq_printf(seq, "%15s %19s       | %20s\n", " ", "read", "write");
 	seq_printf(seq, "%13s   %14s %4s %4s  | %14s %4s %4s\n",
@@ -1293,7 +1293,7 @@
 	spin_lock(&sbi->ll_process_lock);
 
 	seq_printf(seq, "snapshot_time:	 %lu.%lu (secs.usecs)\n",
-		   now.tv_sec, now.tv_usec);
+		   now.tv_sec, (unsigned long)now.tv_usec);
 	seq_printf(seq, "%3s %10s %14s %14s %17s %17s %14s\n",
 		   "R/W", "PID", "RANGE START", "RANGE END",
 		   "SMALLEST EXTENT", "LARGEST EXTENT", "OFFSET");
diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c
index ae0dc44..e9ba38a 100644
--- a/drivers/staging/lustre/lustre/llite/rw.c
+++ b/drivers/staging/lustre/lustre/llite/rw.c
@@ -717,7 +717,7 @@
 	lli = ll_i2info(inode);
 	clob = lli->lli_clob;
 
-	memset(ria, 0, sizeof *ria);
+	memset(ria, 0, sizeof(*ria));
 
 	cl_object_attr_lock(clob);
 	ret = cl_object_attr_get(env, clob, attr);
diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c
index 96c29ad..7e3e096 100644
--- a/drivers/staging/lustre/lustre/llite/rw26.c
+++ b/drivers/staging/lustre/lustre/llite/rw26.c
@@ -202,11 +202,8 @@
 
 	OBD_ALLOC_LARGE(*pages, *max_pages * sizeof(**pages));
 	if (*pages) {
-		down_read(&current->mm->mmap_sem);
-		result = get_user_pages(current, current->mm, user_addr,
-					*max_pages, (rw == READ), 0, *pages,
-					NULL);
-		up_read(&current->mm->mmap_sem);
+		result = get_user_pages_fast(user_addr, *max_pages,
+					     (rw == READ), *pages);
 		if (unlikely(result <= 0))
 			OBD_FREE_LARGE(*pages, *max_pages * sizeof(**pages));
 	}
diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c
index 8eaa38e9..f6b5f4b9 100644
--- a/drivers/staging/lustre/lustre/llite/statahead.c
+++ b/drivers/staging/lustre/lustre/llite/statahead.c
@@ -647,7 +647,7 @@
 		 */
 		LASSERT(fid_is_zero(&minfo->mi_data.op_fid2));
 
-		/* XXX: No fid in reply, this is probaly cross-ref case.
+		/* XXX: No fid in reply, this is probably cross-ref case.
 		 * SA can't handle it yet. */
 		if (body->valid & OBD_MD_MDS)
 			GOTO(out, rc = -EAGAIN);
diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c
index be125b9..c4d1580 100644
--- a/drivers/staging/lustre/lustre/llite/vvp_dev.c
+++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c
@@ -297,7 +297,7 @@
 		((__u64)id->vpi_bucket << PGC_OBJ_SHIFT);
 }
 
-static int vvp_pgcache_obj_get(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+static int vvp_pgcache_obj_get(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 			       struct hlist_node *hnode, void *data)
 {
 	struct vvp_pgcache_id   *id  = data;
diff --git a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h
index 33d9ce6..4276124 100644
--- a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h
+++ b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h
@@ -564,50 +564,50 @@
 
 extern struct kmem_cache *lov_lock_link_kmem;
 
-int   lov_object_init     (const struct lu_env *env, struct lu_object *obj,
+int   lov_object_init(const struct lu_env *env, struct lu_object *obj,
 			   const struct lu_object_conf *conf);
-int   lovsub_object_init  (const struct lu_env *env, struct lu_object *obj,
+int   lovsub_object_init(const struct lu_env *env, struct lu_object *obj,
 			   const struct lu_object_conf *conf);
-int   lov_lock_init       (const struct lu_env *env, struct cl_object *obj,
+int   lov_lock_init(const struct lu_env *env, struct cl_object *obj,
 			   struct cl_lock *lock, const struct cl_io *io);
-int   lov_io_init	 (const struct lu_env *env, struct cl_object *obj,
+int   lov_io_init(const struct lu_env *env, struct cl_object *obj,
 			   struct cl_io *io);
-int   lovsub_lock_init    (const struct lu_env *env, struct cl_object *obj,
+int   lovsub_lock_init(const struct lu_env *env, struct cl_object *obj,
 			   struct cl_lock *lock, const struct cl_io *io);
 
-int   lov_lock_init_raid0 (const struct lu_env *env, struct cl_object *obj,
+int   lov_lock_init_raid0(const struct lu_env *env, struct cl_object *obj,
 			   struct cl_lock *lock, const struct cl_io *io);
-int   lov_lock_init_empty (const struct lu_env *env, struct cl_object *obj,
+int   lov_lock_init_empty(const struct lu_env *env, struct cl_object *obj,
 			   struct cl_lock *lock, const struct cl_io *io);
-int   lov_io_init_raid0   (const struct lu_env *env, struct cl_object *obj,
+int   lov_io_init_raid0(const struct lu_env *env, struct cl_object *obj,
 			   struct cl_io *io);
-int   lov_io_init_empty   (const struct lu_env *env, struct cl_object *obj,
+int   lov_io_init_empty(const struct lu_env *env, struct cl_object *obj,
 			   struct cl_io *io);
 int   lov_io_init_released(const struct lu_env *env, struct cl_object *obj,
 			   struct cl_io *io);
-void  lov_lock_unlink     (const struct lu_env *env, struct lov_lock_link *link,
+void  lov_lock_unlink(const struct lu_env *env, struct lov_lock_link *link,
 			   struct lovsub_lock *sub);
 
 struct lov_io_sub *lov_sub_get(const struct lu_env *env, struct lov_io *lio,
 			       int stripe);
-void  lov_sub_put	     (struct lov_io_sub *sub);
-int   lov_sublock_modify  (const struct lu_env *env, struct lov_lock *lov,
+void  lov_sub_put(struct lov_io_sub *sub);
+int   lov_sublock_modify(const struct lu_env *env, struct lov_lock *lov,
 			   struct lovsub_lock *sublock,
 			   const struct cl_lock_descr *d, int idx);
 
 
-int   lov_page_init       (const struct lu_env *env, struct cl_object *ob,
+int   lov_page_init(const struct lu_env *env, struct cl_object *ob,
 			   struct cl_page *page, struct page *vmpage);
-int   lovsub_page_init    (const struct lu_env *env, struct cl_object *ob,
+int   lovsub_page_init(const struct lu_env *env, struct cl_object *ob,
 			   struct cl_page *page, struct page *vmpage);
 
-int   lov_page_init_empty (const struct lu_env *env,
+int   lov_page_init_empty(const struct lu_env *env,
 			   struct cl_object *obj,
 			   struct cl_page *page, struct page *vmpage);
-int   lov_page_init_raid0 (const struct lu_env *env,
+int   lov_page_init_raid0(const struct lu_env *env,
 			   struct cl_object *obj,
 			   struct cl_page *page, struct page *vmpage);
-struct lu_object *lov_object_alloc   (const struct lu_env *env,
+struct lu_object *lov_object_alloc(const struct lu_env *env,
 				      const struct lu_object_header *hdr,
 				      struct lu_device *dev);
 struct lu_object *lovsub_object_alloc(const struct lu_env *env,
@@ -617,7 +617,7 @@
 struct lov_lock_link *lov_lock_link_find(const struct lu_env *env,
 					 struct lov_lock *lck,
 					 struct lovsub_lock *sub);
-struct lov_io_sub    *lov_page_subio    (const struct lu_env *env,
+struct lov_io_sub    *lov_page_subio(const struct lu_env *env,
 					 struct lov_io *lio,
 					 const struct cl_page_slice *slice);
 
diff --git a/drivers/staging/lustre/lustre/lov/lov_dev.c b/drivers/staging/lustre/lustre/lov/lov_dev.c
index a4006ef..1f33b04 100644
--- a/drivers/staging/lustre/lustre/lov/lov_dev.c
+++ b/drivers/staging/lustre/lustre/lov/lov_dev.c
@@ -44,6 +44,8 @@
 #include <obd_class.h>
 
 #include "lov_cl_internal.h"
+#include "lov_internal.h"
+
 
 struct kmem_cache *lov_lock_kmem;
 struct kmem_cache *lov_object_kmem;
@@ -64,47 +66,47 @@
 	{
 		.ckd_cache = &lov_lock_kmem,
 		.ckd_name  = "lov_lock_kmem",
-		.ckd_size  = sizeof (struct lov_lock)
+		.ckd_size  = sizeof(struct lov_lock)
 	},
 	{
 		.ckd_cache = &lov_object_kmem,
 		.ckd_name  = "lov_object_kmem",
-		.ckd_size  = sizeof (struct lov_object)
+		.ckd_size  = sizeof(struct lov_object)
 	},
 	{
 		.ckd_cache = &lov_thread_kmem,
 		.ckd_name  = "lov_thread_kmem",
-		.ckd_size  = sizeof (struct lov_thread_info)
+		.ckd_size  = sizeof(struct lov_thread_info)
 	},
 	{
 		.ckd_cache = &lov_session_kmem,
 		.ckd_name  = "lov_session_kmem",
-		.ckd_size  = sizeof (struct lov_session)
+		.ckd_size  = sizeof(struct lov_session)
 	},
 	{
 		.ckd_cache = &lov_req_kmem,
 		.ckd_name  = "lov_req_kmem",
-		.ckd_size  = sizeof (struct lov_req)
+		.ckd_size  = sizeof(struct lov_req)
 	},
 	{
 		.ckd_cache = &lovsub_lock_kmem,
 		.ckd_name  = "lovsub_lock_kmem",
-		.ckd_size  = sizeof (struct lovsub_lock)
+		.ckd_size  = sizeof(struct lovsub_lock)
 	},
 	{
 		.ckd_cache = &lovsub_object_kmem,
 		.ckd_name  = "lovsub_object_kmem",
-		.ckd_size  = sizeof (struct lovsub_object)
+		.ckd_size  = sizeof(struct lovsub_object)
 	},
 	{
 		.ckd_cache = &lovsub_req_kmem,
 		.ckd_name  = "lovsub_req_kmem",
-		.ckd_size  = sizeof (struct lovsub_req)
+		.ckd_size  = sizeof(struct lovsub_req)
 	},
 	{
 		.ckd_cache = &lov_lock_link_kmem,
 		.ckd_name  = "lov_lock_link_kmem",
-		.ckd_size  = sizeof (struct lov_lock_link)
+		.ckd_size  = sizeof(struct lov_lock_link)
 	},
 	{
 		.ckd_cache = NULL
@@ -286,7 +288,7 @@
 			OBD_FREE_PTR(em);
 		}
 	}
-	OBD_FREE(emrg, nr * sizeof emrg[0]);
+	OBD_FREE(emrg, nr * sizeof(emrg[0]));
 }
 
 static struct lu_device *lov_device_free(const struct lu_env *env,
@@ -297,7 +299,7 @@
 
 	cl_device_fini(lu2cl_dev(d));
 	if (ld->ld_target != NULL)
-		OBD_FREE(ld->ld_target, nr * sizeof ld->ld_target[0]);
+		OBD_FREE(ld->ld_target, nr * sizeof(ld->ld_target[0]));
 	if (ld->ld_emrg != NULL)
 		lov_emerg_free(ld->ld_emrg, nr);
 	OBD_FREE_PTR(ld);
@@ -321,7 +323,7 @@
 	int i;
 	int result;
 
-	OBD_ALLOC(emerg, nr * sizeof emerg[0]);
+	OBD_ALLOC(emerg, nr * sizeof(emerg[0]));
 	if (emerg == NULL)
 		return ERR_PTR(-ENOMEM);
 	for (result = i = 0; i < nr && result == 0; i++) {
@@ -361,7 +363,7 @@
 	if (sub_size < tgt_size) {
 		struct lovsub_device    **newd;
 		struct lov_device_emerg **emerg;
-		const size_t	      sz   = sizeof newd[0];
+		const size_t	      sz   = sizeof(newd[0]);
 
 		emerg = lov_emerg_alloc(tgt_size);
 		if (IS_ERR(emerg))
@@ -446,7 +448,7 @@
 	cmd = cfg->lcfg_command;
 	rc = lov_process_config_base(d->ld_obd, cfg, &index, &gen);
 	if (rc == 0) {
-		switch(cmd) {
+		switch (cmd) {
 		case LCFG_LOV_ADD_OBD:
 		case LCFG_LOV_ADD_INA:
 			rc = lov_cl_add_target(env, d, index);
diff --git a/drivers/staging/lustre/lustre/lov/lov_internal.h b/drivers/staging/lustre/lustre/lov/lov_internal.h
index 16770d1..796da89 100644
--- a/drivers/staging/lustre/lustre/lov/lov_internal.h
+++ b/drivers/staging/lustre/lustre/lov/lov_internal.h
@@ -89,6 +89,8 @@
 
 extern struct kmem_cache *lov_oinfo_slab;
 
+extern struct lu_kmem_descr lov_caches[];
+
 void lov_finish_set(struct lov_request_set *set);
 
 static inline void lov_get_reqset(struct lov_request_set *set)
@@ -124,7 +126,7 @@
 		if (atomic_read(&llh->llh_refcount))
 			return;
 
-		OBD_FREE_RCU(llh, sizeof *llh +
+		OBD_FREE_RCU(llh, sizeof(*llh) +
 			     sizeof(*llh->llh_handles) * llh->llh_stripe_count,
 			     &llh->llh_handle);
 	}
diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c
index b611aa4..2792fa5 100644
--- a/drivers/staging/lustre/lustre/lov/lov_io.c
+++ b/drivers/staging/lustre/lustre/lov/lov_io.c
@@ -86,7 +86,7 @@
 	struct lov_stripe_md *lsm    = lio->lis_object->lo_lsm;
 	struct cl_io	 *parent = lio->lis_cl.cis_io;
 
-	switch(io->ci_type) {
+	switch (io->ci_type) {
 	case CIT_SETATTR: {
 		io->u.ci_setattr.sa_attr = parent->u.ci_setattr.sa_attr;
 		io->u.ci_setattr.sa_valid = parent->u.ci_setattr.sa_valid;
@@ -282,7 +282,7 @@
 	 * when writing a page. -jay
 	 */
 	OBD_ALLOC_LARGE(lio->lis_subs,
-			lsm->lsm_stripe_count * sizeof lio->lis_subs[0]);
+			lsm->lsm_stripe_count * sizeof(lio->lis_subs[0]));
 	if (lio->lis_subs != NULL) {
 		lio->lis_nr_subios = lio->lis_stripe_count;
 		lio->lis_single_subio_index = -1;
@@ -356,7 +356,7 @@
 		for (i = 0; i < lio->lis_nr_subios; i++)
 			lov_io_sub_fini(env, lio, &lio->lis_subs[i]);
 		OBD_FREE_LARGE(lio->lis_subs,
-			 lio->lis_nr_subios * sizeof lio->lis_subs[0]);
+			 lio->lis_nr_subios * sizeof(lio->lis_subs[0]));
 		lio->lis_nr_subios = 0;
 	}
 
diff --git a/drivers/staging/lustre/lustre/lov/lov_lock.c b/drivers/staging/lustre/lustre/lov/lov_lock.c
index ec297e8..26bc719 100644
--- a/drivers/staging/lustre/lustre/lov/lov_lock.c
+++ b/drivers/staging/lustre/lustre/lov/lov_lock.c
@@ -88,7 +88,7 @@
 			subenv->lse_io  = sub->sub_io;
 			subenv->lse_sub = sub;
 		} else {
-			subenv = (void*)sub;
+			subenv = (void *)sub;
 		}
 	}
 	return subenv;
@@ -167,7 +167,7 @@
 			lov_sublock_env_put(subenv);
 		} else {
 			/* error occurs. */
-			sublock = (void*)subenv;
+			sublock = (void *)subenv;
 		}
 
 		if (!IS_ERR(sublock))
@@ -313,7 +313,7 @@
 			nr++;
 	}
 	LASSERT(nr > 0);
-	OBD_ALLOC_LARGE(lck->lls_sub, nr * sizeof lck->lls_sub[0]);
+	OBD_ALLOC_LARGE(lck->lls_sub, nr * sizeof(lck->lls_sub[0]));
 	if (lck->lls_sub == NULL)
 		return -ENOMEM;
 
@@ -474,7 +474,7 @@
 			 */
 			LASSERT(lck->lls_sub[i].sub_lock == NULL);
 		OBD_FREE_LARGE(lck->lls_sub,
-			       lck->lls_nr * sizeof lck->lls_sub[0]);
+			       lck->lls_nr * sizeof(lck->lls_sub[0]));
 	}
 	OBD_SLAB_FREE_PTR(lck, lov_lock_kmem);
 }
@@ -742,7 +742,7 @@
 				continue;
 			}
 
-			switch(sublock->cll_state) {
+			switch (sublock->cll_state) {
 			case CLS_HELD:
 				rc = cl_unuse_try(subenv->lse_env, sublock);
 				lov_sublock_release(env, lck, i, 0, 0);
diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c
index 0b47aba..4783450 100644
--- a/drivers/staging/lustre/lustre/lov/lov_obd.c
+++ b/drivers/staging/lustre/lustre/lov/lov_obd.c
@@ -554,7 +554,7 @@
 		struct lov_tgt_desc **newtgts, **old = NULL;
 		__u32 newsize, oldsize = 0;
 
-		newsize = max(lov->lov_tgt_size, (__u32)2);
+		newsize = max_t(__u32, lov->lov_tgt_size, 2);
 		while (newsize < index + 1)
 			newsize = newsize << 1;
 		OBD_ALLOC(newtgts, sizeof(*newtgts) * newsize);
@@ -923,7 +923,7 @@
 	int cmd;
 	int rc = 0;
 
-	switch(cmd = lcfg->lcfg_command) {
+	switch (cmd = lcfg->lcfg_command) {
 	case LCFG_LOV_ADD_OBD:
 	case LCFG_LOV_ADD_INA:
 	case LCFG_LOV_DEL_OBD: {
@@ -1090,7 +1090,7 @@
 	if (rc)
 		GOTO(out, rc);
 
-	list_for_each (pos, &set->set_list) {
+	list_for_each(pos, &set->set_list) {
 		req = list_entry(pos, struct lov_request, rq_link);
 
 		if (oa->o_valid & OBD_MD_FLCOOKIE)
@@ -1141,7 +1141,7 @@
 	if (rc)
 		return rc;
 
-	list_for_each (pos, &set->set_list) {
+	list_for_each(pos, &set->set_list) {
 		req = list_entry(pos, struct lov_request, rq_link);
 
 		CDEBUG(D_INFO, "objid "DOSTID"[%d] has subobj "DOSTID" at idx"
@@ -1227,7 +1227,7 @@
 
 	if (!list_empty(&rqset->set_requests)) {
 		LASSERT(rc == 0);
-		LASSERT (rqset->set_interpret == NULL);
+		LASSERT(rqset->set_interpret == NULL);
 		rqset->set_interpret = lov_getattr_interpret;
 		rqset->set_arg = (void *)lovset;
 		return rc;
@@ -1267,7 +1267,7 @@
 	if (rc)
 		return rc;
 
-	list_for_each (pos, &set->set_list) {
+	list_for_each(pos, &set->set_list) {
 		req = list_entry(pos, struct lov_request, rq_link);
 
 		rc = obd_setattr(env, lov->lov_tgts[req->rq_idx]->ltd_exp,
@@ -1408,7 +1408,7 @@
 	if (rc)
 		return rc;
 
-	list_for_each (pos, &set->set_list) {
+	list_for_each(pos, &set->set_list) {
 		req = list_entry(pos, struct lov_request, rq_link);
 
 		rc = obd_punch(env, lov->lov_tgts[req->rq_idx]->ltd_exp,
@@ -1472,7 +1472,7 @@
 	CDEBUG(D_INFO, "fsync objid "DOSTID" ["LPX64", "LPX64"]\n",
 	       POSTID(&set->set_oi->oi_oa->o_oi), start, end);
 
-	list_for_each (pos, &set->set_list) {
+	list_for_each(pos, &set->set_list) {
 		req = list_entry(pos, struct lov_request, rq_link);
 
 		rc = obd_sync(env, lov->lov_tgts[req->rq_idx]->ltd_exp,
@@ -1557,7 +1557,7 @@
 	if (rc)
 		return rc;
 
-	list_for_each (pos, &set->set_list) {
+	list_for_each(pos, &set->set_list) {
 		struct obd_export *sub_exp;
 		struct brw_page *sub_pga;
 		req = list_entry(pos, struct lov_request, rq_link);
@@ -1612,7 +1612,7 @@
 	if (rc)
 		return rc;
 
-	list_for_each (pos, &set->set_list) {
+	list_for_each(pos, &set->set_list) {
 		req = list_entry(pos, struct lov_request, rq_link);
 
 		rc = obd_enqueue(lov->lov_tgts[req->rq_idx]->ltd_exp,
@@ -1828,7 +1828,7 @@
 	if (rc)
 		return rc;
 
-	list_for_each (pos, &set->set_list) {
+	list_for_each(pos, &set->set_list) {
 		req = list_entry(pos, struct lov_request, rq_link);
 		rc = obd_statfs_async(lov->lov_tgts[req->rq_idx]->ltd_exp,
 				      &req->rq_oi, max_age, rqset);
@@ -1909,7 +1909,7 @@
 					 (int) sizeof(struct obd_uuid))))
 			return -EFAULT;
 
-		flags = uarg ? *(__u32*)uarg : 0;
+		flags = uarg ? *(__u32 *)uarg : 0;
 		/* got statfs data */
 		rc = obd_statfs(NULL, lov->lov_tgts[index]->ltd_exp, &stat_buf,
 				cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
@@ -2495,7 +2495,7 @@
 		GOTO(out, rc);
 	} else if (KEY_IS(KEY_CONNECT_FLAG)) {
 		struct lov_tgt_desc *tgt;
-		__u64 ost_idx = *((__u64*)val);
+		__u64 ost_idx = *((__u64 *)val);
 
 		LASSERT(*vallen == sizeof(__u64));
 		LASSERT(ost_idx < lov->desc.ld_tgt_count);
@@ -2564,7 +2564,7 @@
 
 	for (i = 0; i < count; i++, val = (char *)val + incr) {
 		if (next_id) {
-			tgt = lov->lov_tgts[((struct obd_id_info*)val)->idx];
+			tgt = lov->lov_tgts[((struct obd_id_info *)val)->idx];
 		} else {
 			tgt = lov->lov_tgts[i];
 		}
@@ -2593,9 +2593,9 @@
 		} else if (next_id) {
 			err = obd_set_info_async(env, tgt->ltd_exp,
 					 keylen, key, vallen,
-					 ((struct obd_id_info*)val)->data, set);
+					 ((struct obd_id_info *)val)->data, set);
 		} else if (capa) {
-			struct mds_capa_info *info = (struct mds_capa_info*)val;
+			struct mds_capa_info *info = (struct mds_capa_info *)val;
 
 			LASSERT(vallen == sizeof(*info));
 
@@ -2781,7 +2781,7 @@
 	.o_setup	       = lov_setup,
 	.o_precleanup	  = lov_precleanup,
 	.o_cleanup	     = lov_cleanup,
-	//.o_process_config      = lov_process_config,
+	/*.o_process_config      = lov_process_config,*/
 	.o_connect	     = lov_connect,
 	.o_disconnect	  = lov_disconnect,
 	.o_statfs	      = lov_statfs,
@@ -2823,8 +2823,6 @@
 
 struct kmem_cache *lov_oinfo_slab;
 
-extern struct lu_kmem_descr lov_caches[];
-
 int __init lov_init(void)
 {
 	struct lprocfs_static_vars lvars = { 0 };
diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c
index 84e55ce..cf2fa8a 100644
--- a/drivers/staging/lustre/lustre/lov/lov_object.c
+++ b/drivers/staging/lustre/lustre/lov/lov_object.c
@@ -214,7 +214,7 @@
 	r0->lo_nr  = lsm->lsm_stripe_count;
 	LASSERT(r0->lo_nr <= lov_targets_nr(dev));
 
-	OBD_ALLOC_LARGE(r0->lo_sub, r0->lo_nr * sizeof r0->lo_sub[0]);
+	OBD_ALLOC_LARGE(r0->lo_sub, r0->lo_nr * sizeof(r0->lo_sub[0]));
 	if (r0->lo_sub != NULL) {
 		result = 0;
 		subconf->coc_inode = conf->coc_inode;
@@ -368,7 +368,7 @@
 	struct lov_layout_raid0 *r0 = &state->raid0;
 
 	if (r0->lo_sub != NULL) {
-		OBD_FREE_LARGE(r0->lo_sub, r0->lo_nr * sizeof r0->lo_sub[0]);
+		OBD_FREE_LARGE(r0->lo_sub, r0->lo_nr * sizeof(r0->lo_sub[0]));
 		r0->lo_sub = NULL;
 	}
 
diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c
index 55ec267..ec6f6e05 100644
--- a/drivers/staging/lustre/lustre/lov/lov_pack.c
+++ b/drivers/staging/lustre/lustre/lov/lov_pack.c
@@ -121,7 +121,7 @@
 do {								    \
 	if (!(test)) lov_dump_lmm(D_ERROR, lmm);			\
 	LASSERT(test); /* so we know what assertion failed */	   \
-} while(0)
+} while (0)
 
 /* Pack LOV object metadata for disk storage.  It is packed in LE byte
  * order and is opaque to the networking layer.
@@ -630,22 +630,22 @@
 	/* FIXME: Bug 1185 - copy fields properly when structs change */
 	/* struct lov_user_md_v3 and struct lov_mds_md_v3 must be the same */
 	CLASSERT(sizeof(lum) == sizeof(struct lov_mds_md_v3));
-	CLASSERT(sizeof lum.lmm_objects[0] == sizeof lmmk->lmm_objects[0]);
+	CLASSERT(sizeof(lum.lmm_objects[0]) == sizeof(lmmk->lmm_objects[0]));
 
 	if ((cpu_to_le32(LOV_MAGIC) != LOV_MAGIC) &&
 	    ((lmmk->lmm_magic == cpu_to_le32(LOV_MAGIC_V1)) ||
 	    (lmmk->lmm_magic == cpu_to_le32(LOV_MAGIC_V3)))) {
 		lustre_swab_lov_mds_md(lmmk);
 		lustre_swab_lov_user_md_objects(
-				(struct lov_user_ost_data*)lmmk->lmm_objects,
+				(struct lov_user_ost_data *)lmmk->lmm_objects,
 				lmmk->lmm_stripe_count);
 	}
 	if (lum.lmm_magic == LOV_USER_MAGIC) {
 		/* User request for v1, we need skip lmm_pool_name */
 		if (lmmk->lmm_magic == LOV_MAGIC_V3) {
-			memmove((char*)(&lmmk->lmm_stripe_count) +
+			memmove((char *)(&lmmk->lmm_stripe_count) +
 				sizeof(lmmk->lmm_stripe_count),
-				((struct lov_mds_md_v3*)lmmk)->lmm_objects,
+				((struct lov_mds_md_v3 *)lmmk)->lmm_objects,
 				lmmk->lmm_stripe_count *
 				sizeof(struct lov_ost_data_v1));
 			lmm_size -= LOV_MAXPOOLNAME;
diff --git a/drivers/staging/lustre/lustre/lov/lov_pool.c b/drivers/staging/lustre/lustre/lov/lov_pool.c
index dd3c07d..a1701df 100644
--- a/drivers/staging/lustre/lustre/lov/lov_pool.c
+++ b/drivers/staging/lustre/lustre/lov/lov_pool.c
@@ -86,7 +86,7 @@
  * Chapter 6.4.
  * Addison Wesley, 1973
  */
-static __u32 pool_hashfn(cfs_hash_t *hash_body, const void *key, unsigned mask)
+static __u32 pool_hashfn(struct cfs_hash *hash_body, const void *key, unsigned mask)
 {
 	int i;
 	__u32 result;
@@ -125,7 +125,7 @@
 	return hlist_entry(hnode, struct pool_desc, pool_hash);
 }
 
-static void pool_hashrefcount_get(cfs_hash_t *hs, struct hlist_node *hnode)
+static void pool_hashrefcount_get(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	struct pool_desc *pool;
 
@@ -133,7 +133,7 @@
 	lov_pool_getref(pool);
 }
 
-static void pool_hashrefcount_put_locked(cfs_hash_t *hs,
+static void pool_hashrefcount_put_locked(struct cfs_hash *hs,
 					 struct hlist_node *hnode)
 {
 	struct pool_desc *pool;
diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c
index 61e6d0b..bf324ae 100644
--- a/drivers/staging/lustre/lustre/lov/lov_request.c
+++ b/drivers/staging/lustre/lustre/lov/lov_request.c
@@ -245,7 +245,7 @@
 	osc_update_enqueue(lov_lockhp, loi, oi->oi_flags,
 			   &req->rq_oi.oi_md->lsm_oinfo[0]->loi_lvb, mode, rc);
 	if (rc == ELDLM_LOCK_ABORTED && (oi->oi_flags & LDLM_FL_HAS_INTENT))
-		memset(lov_lockhp, 0, sizeof *lov_lockhp);
+		memset(lov_lockhp, 0, sizeof(*lov_lockhp));
 	rc = lov_update_enqueue_lov(set->set_exp, lov_lockhp, loi, oi->oi_flags,
 				    req->rq_idx, &oi->oi_md->lsm_oi, rc);
 	lov_stripe_unlock(oi->oi_md);
@@ -343,7 +343,7 @@
 {
 	struct lov_lock_handles *llh;
 
-	OBD_ALLOC(llh, sizeof *llh +
+	OBD_ALLOC(llh, sizeof(*llh) +
 		  sizeof(*llh->llh_handles) * lsm->lsm_stripe_count);
 	if (llh == NULL)
 		return NULL;
@@ -630,7 +630,7 @@
 	if (tmp_oa == NULL)
 		GOTO(out, rc = -ENOMEM);
 
-	list_for_each (pos, &set->set_list) {
+	list_for_each(pos, &set->set_list) {
 		req = list_entry(pos, struct lov_request, rq_link);
 
 		if (!req->rq_complete || req->rq_rc)
@@ -669,7 +669,7 @@
 	struct list_head *pos;
 	struct lov_request *req;
 
-	list_for_each (pos, &set->set_list) {
+	list_for_each(pos, &set->set_list) {
 		req = list_entry(pos, struct lov_request, rq_link);
 
 		if (!req->rq_complete || req->rq_rc)
@@ -1315,7 +1315,7 @@
 			(tot) = LOV_U64_MAX;			    \
 		else						    \
 			(tot) += (add);				 \
-	} while(0)
+	} while (0)
 
 int lov_fini_statfs(struct obd_device *obd, struct obd_statfs *osfs,int success)
 {
diff --git a/drivers/staging/lustre/lustre/lvfs/fsfilt.c b/drivers/staging/lustre/lustre/lvfs/fsfilt.c
index e86df73..0d6ed69 100644
--- a/drivers/staging/lustre/lustre/lvfs/fsfilt.c
+++ b/drivers/staging/lustre/lustre/lvfs/fsfilt.c
@@ -50,9 +50,8 @@
 
 	list_for_each(p, &fsfilt_types) {
 		found = list_entry(p, struct fsfilt_operations, fs_list);
-		if (!strcmp(found->fs_type, type)) {
+		if (!strcmp(found->fs_type, type))
 			return found;
-		}
 	}
 	return NULL;
 }
@@ -62,7 +61,8 @@
 	struct fsfilt_operations *found;
 
 	/* lock fsfilt_types list */
-	if ((found = fsfilt_search_type(fs_ops->fs_type))) {
+	found = fsfilt_search_type(fs_ops->fs_type);
+	if (found) {
 		if (found != fs_ops) {
 			CERROR("different operations for type %s\n",
 			       fs_ops->fs_type);
@@ -103,14 +103,16 @@
 	struct fsfilt_operations *fs_ops;
 
 	/* lock fsfilt_types list */
-	if (!(fs_ops = fsfilt_search_type(type))) {
+	fs_ops = fsfilt_search_type(type);
+	if (!fs_ops) {
 		char name[32];
 		int rc;
 
 		snprintf(name, sizeof(name) - 1, "fsfilt_%s", type);
 		name[sizeof(name) - 1] = '\0';
 
-		if (!(rc = request_module("%s", name))) {
+		rc = request_module("%s", name);
+		if (!rc) {
 			fs_ops = fsfilt_search_type(type);
 			CDEBUG(D_INFO, "Loaded module '%s'\n", name);
 			if (!fs_ops)
diff --git a/drivers/staging/lustre/lustre/lvfs/lvfs_lib.c b/drivers/staging/lustre/lustre/lvfs/lvfs_lib.c
index 97a8be2..b21e40c 100644
--- a/drivers/staging/lustre/lustre/lvfs/lvfs_lib.c
+++ b/drivers/staging/lustre/lustre/lvfs/lvfs_lib.c
@@ -154,11 +154,10 @@
 				spin_lock(&stats->ls_lock);
 			if (stats->ls_biggest_alloc_num <= cpuid)
 				stats->ls_biggest_alloc_num = cpuid + 1;
-			if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE) {
+			if (stats->ls_flags & LPROCFS_STATS_FLAG_IRQ_SAFE)
 				spin_unlock_irqrestore(&stats->ls_lock, flags);
-			} else {
+			else
 				spin_unlock(&stats->ls_lock);
-			}
 		}
 		/* initialize the ls_percpu[cpuid] non-zero counter */
 		for (i = 0; i < stats->ls_num; ++i) {
diff --git a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c
index 4ed7c9f..09474e7 100644
--- a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c
+++ b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c
@@ -65,9 +65,9 @@
 					      msg)
 # define ASSERT_KERNEL_CTXT(msg) LASSERTF(segment_eq(get_fs(), get_ds()), msg)
 #else
-# define ASSERT_CTXT_MAGIC(magic) do {} while(0)
-# define ASSERT_NOT_KERNEL_CTXT(msg) do {} while(0)
-# define ASSERT_KERNEL_CTXT(msg) do {} while(0)
+# define ASSERT_CTXT_MAGIC(magic) do {} while (0)
+# define ASSERT_NOT_KERNEL_CTXT(msg) do {} while (0)
+# define ASSERT_KERNEL_CTXT(msg) do {} while (0)
 #endif
 
 static void push_group_info(struct lvfs_run_ctxt *save,
@@ -80,7 +80,8 @@
 		struct cred *cred;
 		task_lock(current);
 		save->group_info = current_cred()->group_info;
-		if ((cred = prepare_creds())) {
+		cred = prepare_creds();
+		if (cred) {
 			cred->group_info = ginfo;
 			commit_creds(cred);
 		}
@@ -96,7 +97,8 @@
 	} else {
 		struct cred *cred;
 		task_lock(current);
-		if ((cred = prepare_creds())) {
+		cred = prepare_creds();
+		if (cred) {
 			cred->group_info = save->group_info;
 			commit_creds(cred);
 		}
@@ -112,7 +114,7 @@
 	if (new_ctx->dt != NULL)
 		return;
 
-	//ASSERT_NOT_KERNEL_CTXT("already in kernel context!\n");
+	/* ASSERT_NOT_KERNEL_CTXT("already in kernel context!\n"); */
 	ASSERT_CTXT_MAGIC(new_ctx->magic);
 	OBD_SET_CTXT_MAGIC(save);
 
@@ -137,7 +139,8 @@
 		save->luc.luc_fsgid = current_fsgid();
 		save->luc.luc_cap = current_cap();
 
-		if ((cred = prepare_creds())) {
+		cred = prepare_creds();
+		if (cred) {
 			cred->uid = uc->luc_uid;
 			cred->gid = uc->luc_gid;
 			cred->fsuid = uc->luc_fsuid;
@@ -180,7 +183,8 @@
 	current->fs->umask = saved->luc.luc_umask;
 	if (uc) {
 		struct cred *cred;
-		if ((cred = prepare_creds())) {
+		cred = prepare_creds();
+		if (cred) {
 			cred->uid = saved->luc.luc_uid;
 			cred->gid = saved->luc.luc_gid;
 			cred->fsuid = saved->luc.luc_fsuid;
@@ -253,32 +257,32 @@
 		return 0;
 
 	switch (field) {
-		case LPROCFS_FIELDS_FLAGS_CONFIG:
-			ret = header->lc_config;
-			break;
-		case LPROCFS_FIELDS_FLAGS_SUM:
-			ret = lc->lc_sum;
-			if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
-				ret += lc->lc_sum_irq;
-			break;
-		case LPROCFS_FIELDS_FLAGS_MIN:
-			ret = lc->lc_min;
-			break;
-		case LPROCFS_FIELDS_FLAGS_MAX:
-			ret = lc->lc_max;
-			break;
-		case LPROCFS_FIELDS_FLAGS_AVG:
-			ret = (lc->lc_max - lc->lc_min) / 2;
-			break;
-		case LPROCFS_FIELDS_FLAGS_SUMSQUARE:
-			ret = lc->lc_sumsquare;
-			break;
-		case LPROCFS_FIELDS_FLAGS_COUNT:
-			ret = lc->lc_count;
-			break;
-		default:
-			break;
-	};
+	case LPROCFS_FIELDS_FLAGS_CONFIG:
+		ret = header->lc_config;
+		break;
+	case LPROCFS_FIELDS_FLAGS_SUM:
+		ret = lc->lc_sum;
+		if ((flags & LPROCFS_STATS_FLAG_IRQ_SAFE) != 0)
+			ret += lc->lc_sum_irq;
+		break;
+	case LPROCFS_FIELDS_FLAGS_MIN:
+		ret = lc->lc_min;
+		break;
+	case LPROCFS_FIELDS_FLAGS_MAX:
+		ret = lc->lc_max;
+		break;
+	case LPROCFS_FIELDS_FLAGS_AVG:
+		ret = (lc->lc_max - lc->lc_min) / 2;
+		break;
+	case LPROCFS_FIELDS_FLAGS_SUMSQUARE:
+		ret = lc->lc_sumsquare;
+		break;
+	case LPROCFS_FIELDS_FLAGS_COUNT:
+		ret = lc->lc_count;
+		break;
+	default:
+		break;
+	}
 
 	return ret;
 }
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c
index 4269793..e048500 100644
--- a/drivers/staging/lustre/lustre/obdclass/cl_io.c
+++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c
@@ -1387,7 +1387,7 @@
 				cl_object_put(env, obj);
 			}
 		}
-		OBD_FREE(req->crq_o, req->crq_nrobjs * sizeof req->crq_o[0]);
+		OBD_FREE(req->crq_o, req->crq_nrobjs * sizeof(req->crq_o[0]));
 	}
 	OBD_FREE_PTR(req);
 }
@@ -1452,7 +1452,7 @@
 	if (req != NULL) {
 		int result;
 
-		OBD_ALLOC(req->crq_o, nr_objects * sizeof req->crq_o[0]);
+		OBD_ALLOC(req->crq_o, nr_objects * sizeof(req->crq_o[0]));
 		if (req->crq_o != NULL) {
 			req->crq_nrobjs = nr_objects;
 			req->crq_type = crt;
@@ -1642,7 +1642,7 @@
 		cpu_relax();
 	}
 
-	POISON(anchor, 0x5a, sizeof *anchor);
+	POISON(anchor, 0x5a, sizeof(*anchor));
 	return rc;
 }
 EXPORT_SYMBOL(cl_sync_io_wait);
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c
index 7b0e9d2..1a92603 100644
--- a/drivers/staging/lustre/lustre/obdclass/cl_object.c
+++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c
@@ -577,9 +577,9 @@
  * The implementation of using hash table to connect cl_env and thread
  */
 
-static cfs_hash_t *cl_env_hash;
+static struct cfs_hash *cl_env_hash;
 
-static unsigned cl_env_hops_hash(cfs_hash_t *lh,
+static unsigned cl_env_hops_hash(struct cfs_hash *lh,
 				 const void *key, unsigned mask)
 {
 #if BITS_PER_LONG == 64
@@ -604,7 +604,7 @@
 	return (key == cle->ce_owner);
 }
 
-static void cl_env_hops_noop(cfs_hash_t *hs, struct hlist_node *hn)
+static void cl_env_hops_noop(struct cfs_hash *hs, struct hlist_node *hn)
 {
 	struct cl_env *cle = hlist_entry(hn, struct cl_env, ce_node);
 	LASSERT(cle->ce_magic == &cl_env_init0);
diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c
index b1024a6..4afd962 100644
--- a/drivers/staging/lustre/lustre/obdclass/class_obd.c
+++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c
@@ -178,7 +178,7 @@
 static inline void obd_data2conn(struct lustre_handle *conn,
 				 struct obd_ioctl_data *data)
 {
-	memset(conn, 0, sizeof *conn);
+	memset(conn, 0, sizeof(*conn));
 	conn->cookie = data->ioc_cookie;
 }
 
diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c
index 68fe71c..f6fae16 100644
--- a/drivers/staging/lustre/lustre/obdclass/genops.c
+++ b/drivers/staging/lustre/lustre/obdclass/genops.c
@@ -816,7 +816,7 @@
 				    struct obd_uuid *cluuid)
 {
 	struct obd_export *export;
-	cfs_hash_t *hash = NULL;
+	struct cfs_hash *hash = NULL;
 	int rc = 0;
 
 	OBD_ALLOC_PTR(export);
@@ -1384,7 +1384,7 @@
 
 int obd_export_evict_by_nid(struct obd_device *obd, const char *nid)
 {
-	cfs_hash_t *nid_hash;
+	struct cfs_hash *nid_hash;
 	struct obd_export *doomed_exp = NULL;
 	int exports_evicted = 0;
 
@@ -1432,7 +1432,7 @@
 
 int obd_export_evict_by_uuid(struct obd_device *obd, const char *uuid)
 {
-	cfs_hash_t *uuid_hash;
+	struct cfs_hash *uuid_hash;
 	struct obd_export *doomed_exp = NULL;
 	struct obd_uuid doomed_uuid;
 	int exports_evicted = 0;
diff --git a/drivers/staging/lustre/lustre/obdclass/llog_test.c b/drivers/staging/lustre/lustre/obdclass/llog_test.c
index d9e6d12..178f89e 100644
--- a/drivers/staging/lustre/lustre/obdclass/llog_test.c
+++ b/drivers/staging/lustre/lustre/obdclass/llog_test.c
@@ -242,7 +242,7 @@
 
 		hdr.lrh_len = 8;
 		hdr.lrh_type = OBD_CFG_REC;
-		memset(buf, 0, sizeof buf);
+		memset(buf, 0, sizeof(buf));
 		rc = llog_write(env, llh, &hdr, NULL, 0, buf, -1);
 		if (rc < 0) {
 			CERROR("3b: write 10 records failed at #%d: %d\n",
@@ -277,8 +277,8 @@
 		char			buf_even[24];
 		char			buf_odd[32];
 
-		memset(buf_odd, 0, sizeof buf_odd);
-		memset(buf_even, 0, sizeof buf_even);
+		memset(buf_odd, 0, sizeof(buf_odd));
+		memset(buf_even, 0, sizeof(buf_even));
 		if ((i % 2) == 0) {
 			hdr.lrh_len = 24;
 			hdr.lrh_type = OBD_CFG_REC;
diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
index a95f60a..02d76f8 100644
--- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
+++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
@@ -898,7 +898,7 @@
 
 void lprocfs_free_per_client_stats(struct obd_device *obd)
 {
-	cfs_hash_t *hash = obd->obd_nid_stats_hash;
+	struct cfs_hash *hash = obd->obd_nid_stats_hash;
 	struct nid_stat *stat;
 
 	/* we need extra list - because hash_exit called to early */
@@ -1069,7 +1069,7 @@
 		struct timeval now;
 		do_gettimeofday(&now);
 		rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n",
-				"snapshot_time", now.tv_sec, now.tv_usec);
+				"snapshot_time", now.tv_sec, (unsigned long)now.tv_usec);
 		if (rc < 0)
 			return rc;
 	}
@@ -1422,7 +1422,7 @@
 }
 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
 
-int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+int lprocfs_exp_print_uuid(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 			   struct hlist_node *hnode, void *data)
 
 {
@@ -1453,7 +1453,7 @@
 	bool		first;
 };
 
-int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+int lprocfs_exp_print_hash(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 			   struct hlist_node *hnode, void *cb_data)
 
 {
diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c
index 3a3d5bc..212823a 100644
--- a/drivers/staging/lustre/lustre/obdclass/lu_object.c
+++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c
@@ -71,7 +71,7 @@
 	struct lu_object_header *top;
 	struct lu_site	  *site;
 	struct lu_object	*orig;
-	cfs_hash_bd_t	    bd;
+	struct cfs_hash_bd	    bd;
 	const struct lu_fid     *fid;
 
 	top  = o->lo_header;
@@ -175,8 +175,8 @@
 	top = o->lo_header;
 	set_bit(LU_OBJECT_HEARD_BANSHEE, &top->loh_flags);
 	if (!test_and_set_bit(LU_OBJECT_UNHASHED, &top->loh_flags)) {
-		cfs_hash_t *obj_hash = o->lo_dev->ld_site->ls_obj_hash;
-		cfs_hash_bd_t bd;
+		struct cfs_hash *obj_hash = o->lo_dev->ld_site->ls_obj_hash;
+		struct cfs_hash_bd bd;
 
 		cfs_hash_bd_get_and_lock(obj_hash, &top->loh_fid, &bd, 1);
 		list_del_init(&top->loh_lru);
@@ -306,8 +306,8 @@
 	struct lu_object_header *h;
 	struct lu_object_header *temp;
 	struct lu_site_bkt_data *bkt;
-	cfs_hash_bd_t	    bd;
-	cfs_hash_bd_t	    bd2;
+	struct cfs_hash_bd	    bd;
+	struct cfs_hash_bd	    bd2;
 	struct list_head	       dispose;
 	int		      did_sth;
 	int		      start;
@@ -526,7 +526,7 @@
 EXPORT_SYMBOL(lu_object_invariant);
 
 static struct lu_object *htable_lookup(struct lu_site *s,
-				       cfs_hash_bd_t *bd,
+				       struct cfs_hash_bd *bd,
 				       const struct lu_fid *f,
 				       wait_queue_t *waiter,
 				       __u64 *version)
@@ -589,8 +589,8 @@
 				       const struct lu_object_conf *conf)
 {
 	struct lu_object	*o;
-	cfs_hash_t	      *hs;
-	cfs_hash_bd_t	    bd;
+	struct cfs_hash	      *hs;
+	struct cfs_hash_bd	    bd;
 	struct lu_site_bkt_data *bkt;
 
 	o = lu_object_alloc(env, dev, f, conf);
@@ -618,8 +618,8 @@
 	struct lu_object      *o;
 	struct lu_object      *shadow;
 	struct lu_site	*s;
-	cfs_hash_t	    *hs;
-	cfs_hash_bd_t	  bd;
+	struct cfs_hash	    *hs;
+	struct cfs_hash_bd	  bd;
 	__u64		  version = 0;
 
 	/*
@@ -788,7 +788,7 @@
 };
 
 static int
-lu_site_obj_print(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+lu_site_obj_print(struct cfs_hash *hs, struct cfs_hash_bd *bd,
 		  struct hlist_node *hnode, void *data)
 {
 	struct lu_site_print_arg *arg = (struct lu_site_print_arg *)data;
@@ -874,7 +874,7 @@
 	return bits;
 }
 
-static unsigned lu_obj_hop_hash(cfs_hash_t *hs,
+static unsigned lu_obj_hop_hash(struct cfs_hash *hs,
 				const void *key, unsigned mask)
 {
 	struct lu_fid  *fid = (struct lu_fid *)key;
@@ -914,14 +914,14 @@
 	return lu_fid_eq(&h->loh_fid, (struct lu_fid *)key);
 }
 
-static void lu_obj_hop_get(cfs_hash_t *hs, struct hlist_node *hnode)
+static void lu_obj_hop_get(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	struct lu_object_header *h;
 
 	h = hlist_entry(hnode, struct lu_object_header, loh_hash);
 	if (atomic_add_return(1, &h->loh_ref) == 1) {
 		struct lu_site_bkt_data *bkt;
-		cfs_hash_bd_t	    bd;
+		struct cfs_hash_bd	    bd;
 
 		cfs_hash_bd_get(hs, &h->loh_fid, &bd);
 		bkt = cfs_hash_bd_extra_get(hs, &bd);
@@ -929,7 +929,7 @@
 	}
 }
 
-static void lu_obj_hop_put_locked(cfs_hash_t *hs, struct hlist_node *hnode)
+static void lu_obj_hop_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	LBUG(); /* we should never called it */
 }
@@ -975,12 +975,12 @@
 int lu_site_init(struct lu_site *s, struct lu_device *top)
 {
 	struct lu_site_bkt_data *bkt;
-	cfs_hash_bd_t bd;
+	struct cfs_hash_bd bd;
 	char name[16];
 	int bits;
 	int i;
 
-	memset(s, 0, sizeof *s);
+	memset(s, 0, sizeof(*s));
 	bits = lu_htable_order();
 	snprintf(name, 16, "lu_site_%s", top->ld_type->ldt_name);
 	for (bits = min(max(LU_SITE_BITS_MIN, bits), LU_SITE_BITS_MAX);
@@ -1110,7 +1110,7 @@
 {
 	if (t->ldt_device_nr++ == 0 && t->ldt_ops->ldto_start != NULL)
 		t->ldt_ops->ldto_start(t);
-	memset(d, 0, sizeof *d);
+	memset(d, 0, sizeof(*d));
 	atomic_set(&d->ld_ref, 0);
 	d->ld_type = t;
 	lu_ref_init(&d->ld_reference);
@@ -1206,7 +1206,7 @@
  */
 int lu_object_header_init(struct lu_object_header *h)
 {
-	memset(h, 0, sizeof *h);
+	memset(h, 0, sizeof(*h));
 	atomic_set(&h->loh_ref, 1);
 	INIT_HLIST_NODE(&h->loh_hash);
 	INIT_LIST_HEAD(&h->loh_lru);
@@ -1525,7 +1525,7 @@
 	for (i = 0; i < ARRAY_SIZE(lu_keys); ++i)
 		key_fini(ctx, i);
 
-	OBD_FREE(ctx->lc_value, ARRAY_SIZE(lu_keys) * sizeof ctx->lc_value[0]);
+	OBD_FREE(ctx->lc_value, ARRAY_SIZE(lu_keys) * sizeof(ctx->lc_value[0]));
 	ctx->lc_value = NULL;
 }
 
@@ -1574,7 +1574,8 @@
 
 static int keys_init(struct lu_context *ctx)
 {
-	OBD_ALLOC(ctx->lc_value, ARRAY_SIZE(lu_keys) * sizeof ctx->lc_value[0]);
+	OBD_ALLOC(ctx->lc_value,
+		  ARRAY_SIZE(lu_keys) * sizeof(ctx->lc_value[0]));
 	if (likely(ctx->lc_value != NULL))
 		return keys_fill(ctx);
 
@@ -1588,7 +1589,7 @@
 {
 	int	rc;
 
-	memset(ctx, 0, sizeof *ctx);
+	memset(ctx, 0, sizeof(*ctx));
 	ctx->lc_state = LCS_INITIALIZED;
 	ctx->lc_tags = tags;
 	if (tags & LCT_REMEMBER) {
@@ -1787,10 +1788,10 @@
 	unsigned	lss_busy;
 } lu_site_stats_t;
 
-static void lu_site_stats_get(cfs_hash_t *hs,
+static void lu_site_stats_get(struct cfs_hash *hs,
 			      lu_site_stats_t *stats, int populated)
 {
-	cfs_hash_bd_t bd;
+	struct cfs_hash_bd bd;
 	int	   i;
 
 	cfs_hash_for_each_bucket(hs, &bd, i) {
@@ -2071,8 +2072,8 @@
 	struct lu_site_bkt_data	*bkt;
 	struct lu_object	*shadow;
 	wait_queue_t		 waiter;
-	cfs_hash_t		*hs;
-	cfs_hash_bd_t		 bd;
+	struct cfs_hash		*hs;
+	struct cfs_hash_bd	 bd;
 	__u64			 version = 0;
 
 	LASSERT(fid_is_zero(old));
diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c
index d0a64ff..362ae54 100644
--- a/drivers/staging/lustre/lustre/obdclass/obd_config.c
+++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c
@@ -417,7 +417,7 @@
 
 	/* do the attach */
 	if (OBP(obd, attach)) {
-		rc = OBP(obd,attach)(obd, sizeof *lcfg, lcfg);
+		rc = OBP(obd, attach)(obd, sizeof(*lcfg), lcfg);
 		if (rc)
 			GOTO(out, rc = -EINVAL);
 	}
@@ -900,7 +900,7 @@
 		OBD_FREE(lprof->lp_dt, strlen(lprof->lp_dt) + 1);
 		if (lprof->lp_md)
 			OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1);
-		OBD_FREE(lprof, sizeof *lprof);
+		OBD_FREE(lprof, sizeof(*lprof));
 	}
 }
 EXPORT_SYMBOL(class_del_profile);
@@ -916,7 +916,7 @@
 		OBD_FREE(lprof->lp_dt, strlen(lprof->lp_dt) + 1);
 		if (lprof->lp_md)
 			OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1);
-		OBD_FREE(lprof, sizeof *lprof);
+		OBD_FREE(lprof, sizeof(*lprof));
 	}
 }
 EXPORT_SYMBOL(class_del_profiles);
@@ -1692,7 +1692,7 @@
  */
 
 static unsigned
-uuid_hash(cfs_hash_t *hs, const void *key, unsigned mask)
+uuid_hash(struct cfs_hash *hs, const void *key, unsigned mask)
 {
 	return cfs_hash_djb2_hash(((struct obd_uuid *)key)->uuid,
 				  sizeof(((struct obd_uuid *)key)->uuid), mask);
@@ -1731,7 +1731,7 @@
 }
 
 static void
-uuid_export_get(cfs_hash_t *hs, struct hlist_node *hnode)
+uuid_export_get(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	struct obd_export *exp;
 
@@ -1740,7 +1740,7 @@
 }
 
 static void
-uuid_export_put_locked(cfs_hash_t *hs, struct hlist_node *hnode)
+uuid_export_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	struct obd_export *exp;
 
@@ -1763,7 +1763,7 @@
  */
 
 static unsigned
-nid_hash(cfs_hash_t *hs, const void *key, unsigned mask)
+nid_hash(struct cfs_hash *hs, const void *key, unsigned mask)
 {
 	return cfs_hash_djb2_hash(key, sizeof(lnet_nid_t), mask);
 }
@@ -1801,7 +1801,7 @@
 }
 
 static void
-nid_export_get(cfs_hash_t *hs, struct hlist_node *hnode)
+nid_export_get(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	struct obd_export *exp;
 
@@ -1810,7 +1810,7 @@
 }
 
 static void
-nid_export_put_locked(cfs_hash_t *hs, struct hlist_node *hnode)
+nid_export_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	struct obd_export *exp;
 
@@ -1855,7 +1855,7 @@
 }
 
 static void
-nidstats_get(cfs_hash_t *hs, struct hlist_node *hnode)
+nidstats_get(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	struct nid_stat *ns;
 
@@ -1864,7 +1864,7 @@
 }
 
 static void
-nidstats_put_locked(cfs_hash_t *hs, struct hlist_node *hnode)
+nidstats_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	struct nid_stat *ns;
 
diff --git a/drivers/staging/lustre/lustre/obdclass/uuid.c b/drivers/staging/lustre/lustre/obdclass/uuid.c
index af5f27f..e87a199 100644
--- a/drivers/staging/lustre/lustre/obdclass/uuid.c
+++ b/drivers/staging/lustre/lustre/obdclass/uuid.c
@@ -48,7 +48,7 @@
 {
 	__u32 value;
 
-	LASSERT(nob <= sizeof value);
+	LASSERT(nob <= sizeof(value));
 
 	for (value = 0; nob > 0; --nob)
 		value = (value << 8) | *((*ptr)++);
@@ -61,7 +61,7 @@
 {
 	__u8 *ptr = in;
 
-	LASSERT(nr * sizeof *uu == sizeof(class_uuid_t));
+	LASSERT(nr * sizeof(*uu) == sizeof(class_uuid_t));
 
 	while (nr-- > 0)
 		CONSUME(uu[nr], &ptr);
diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c
index c8b4344..1fb0ac4 100644
--- a/drivers/staging/lustre/lustre/obdecho/echo_client.c
+++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c
@@ -1089,7 +1089,7 @@
 		} else {
 			struct lustre_md *md;
 			md = &info->eti_md;
-			memset(md, 0, sizeof *md);
+			memset(md, 0, sizeof(*md));
 			md->lsm = lsm;
 			conf->eoc_cl.u.coc_md = md;
 		}
diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c
index 90d24d8..ef10e2a 100644
--- a/drivers/staging/lustre/lustre/osc/lproc_osc.c
+++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c
@@ -571,7 +571,7 @@
 	client_obd_list_lock(&cli->cl_loi_list_lock);
 
 	seq_printf(seq, "snapshot_time:	 %lu.%lu (secs.usecs)\n",
-		   now.tv_sec, now.tv_usec);
+		   now.tv_sec, (unsigned long)now.tv_usec);
 	seq_printf(seq, "read RPCs in flight:  %d\n",
 		   cli->cl_r_in_flight);
 	seq_printf(seq, "write RPCs in flight: %d\n",
@@ -683,7 +683,7 @@
 	do_gettimeofday(&now);
 
 	seq_printf(seq, "snapshot_time:	 %lu.%lu (secs.usecs)\n",
-		   now.tv_sec, now.tv_usec);
+		   now.tv_sec, (unsigned long)now.tv_usec);
 	seq_printf(seq, "lockless_write_bytes\t\t"LPU64"\n",
 		   stats->os_lockless_writes);
 	seq_printf(seq, "lockless_read_bytes\t\t"LPU64"\n",
diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c
index 3aeaf84..681d60a 100644
--- a/drivers/staging/lustre/lustre/osc/osc_io.c
+++ b/drivers/staging/lustre/lustre/osc/osc_io.c
@@ -105,7 +105,7 @@
 	struct osc_object *osc  = NULL; /* to keep gcc happy */
 	struct osc_page   *opg;
 	struct cl_io      *io;
-	LIST_HEAD     (list);
+	LIST_HEAD(list);
 
 	struct cl_page_list *qin      = &queue->c2_qin;
 	struct cl_page_list *qout     = &queue->c2_qout;
diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c
index 5d7bdbf..c90abfb 100644
--- a/drivers/staging/lustre/lustre/osc/osc_lock.c
+++ b/drivers/staging/lustre/lustre/osc/osc_lock.c
@@ -862,7 +862,7 @@
 			cap = &req->rq_pill;
 			req_capsule_extend(cap, &RQF_LDLM_GL_CALLBACK);
 			req_capsule_set_size(cap, &RMF_DLM_LVB, RCL_SERVER,
-					     sizeof *lvb);
+					     sizeof(*lvb));
 			result = req_capsule_server_pack(cap);
 			if (result == 0) {
 				lvb = req_capsule_server_get(cap, &RMF_DLM_LVB);
diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c
index d272322..6c20b8e 100644
--- a/drivers/staging/lustre/lustre/osc/osc_page.c
+++ b/drivers/staging/lustre/lustre/osc/osc_page.c
@@ -245,7 +245,7 @@
 void osc_index2policy(ldlm_policy_data_t *policy, const struct cl_object *obj,
 		      pgoff_t start, pgoff_t end)
 {
-	memset(policy, 0, sizeof *policy);
+	memset(policy, 0, sizeof(*policy));
 	policy->l_extent.start = cl_offset(obj, start);
 	policy->l_extent.end   = cl_offset(obj, end + 1) - 1;
 }
diff --git a/drivers/staging/lustre/lustre/osc/osc_quota.c b/drivers/staging/lustre/lustre/osc/osc_quota.c
index 9720c0e..6045a78 100644
--- a/drivers/staging/lustre/lustre/osc/osc_quota.c
+++ b/drivers/staging/lustre/lustre/osc/osc_quota.c
@@ -139,7 +139,7 @@
  * Hash operations for uid/gid <-> osc_quota_info
  */
 static unsigned
-oqi_hashfn(cfs_hash_t *hs, const void *key, unsigned mask)
+oqi_hashfn(struct cfs_hash *hs, const void *key, unsigned mask)
 {
 	return cfs_hash_u32_hash(*((__u32*)key), mask);
 }
@@ -172,17 +172,17 @@
 }
 
 static void
-oqi_get(cfs_hash_t *hs, struct hlist_node *hnode)
+oqi_get(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 }
 
 static void
-oqi_put_locked(cfs_hash_t *hs, struct hlist_node *hnode)
+oqi_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 }
 
 static void
-oqi_exit(cfs_hash_t *hs, struct hlist_node *hnode)
+oqi_exit(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	struct osc_quota_info *oqi;
 
diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c
index ee6707a..cb19778 100644
--- a/drivers/staging/lustre/lustre/osc/osc_request.c
+++ b/drivers/staging/lustre/lustre/osc/osc_request.c
@@ -2554,7 +2554,7 @@
 		}
 
 		req_capsule_set_size(&req->rq_pill, &RMF_DLM_LVB, RCL_SERVER,
-				     sizeof *lvb);
+				     sizeof(*lvb));
 		ptlrpc_request_set_replen(req);
 	}
 
diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c
index 810a458..c2ab0c8 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/client.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/client.c
@@ -817,7 +817,7 @@
 {
 	struct ptlrpc_request_set *set;
 
-	OBD_ALLOC(set, sizeof *set);
+	OBD_ALLOC(set, sizeof(*set));
 	if (!set)
 		return NULL;
 	atomic_set(&set->set_refcount, 1);
@@ -2690,7 +2690,7 @@
 
 	LASSERT (sizeof (*aa) <= sizeof (req->rq_async_args));
 	aa = ptlrpc_req_async_args(req);
-	memset(aa, 0, sizeof *aa);
+	memset(aa, 0, sizeof(*aa));
 
 	/* Prepare request to be resent with ptlrpcd */
 	aa->praa_old_state = req->rq_send_state;
diff --git a/drivers/staging/lustre/lustre/ptlrpc/connection.c b/drivers/staging/lustre/lustre/ptlrpc/connection.c
index 17ca842..6756356 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/connection.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/connection.c
@@ -41,7 +41,7 @@
 
 #include "ptlrpc_internal.h"
 
-static cfs_hash_t *conn_hash = NULL;
+static struct cfs_hash *conn_hash = NULL;
 static cfs_hash_ops_t conn_hash_ops;
 
 struct ptlrpc_connection *
@@ -161,7 +161,7 @@
  * Hash operations for net_peer<->connection
  */
 static unsigned
-conn_hashfn(cfs_hash_t *hs, const void *key, unsigned mask)
+conn_hashfn(struct cfs_hash *hs, const void *key, unsigned mask)
 {
 	return cfs_hash_djb2_hash(key, sizeof(lnet_process_id_t), mask);
 }
@@ -195,7 +195,7 @@
 }
 
 static void
-conn_get(cfs_hash_t *hs, struct hlist_node *hnode)
+conn_get(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	struct ptlrpc_connection *conn;
 
@@ -204,7 +204,7 @@
 }
 
 static void
-conn_put_locked(cfs_hash_t *hs, struct hlist_node *hnode)
+conn_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	struct ptlrpc_connection *conn;
 
@@ -213,7 +213,7 @@
 }
 
 static void
-conn_exit(cfs_hash_t *hs, struct hlist_node *hnode)
+conn_exit(struct cfs_hash *hs, struct hlist_node *hnode)
 {
 	struct ptlrpc_connection *conn;
 
diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c
index 5ca69ae..7b96a0e 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/import.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/import.c
@@ -682,7 +682,7 @@
 
 	CLASSERT(sizeof (*aa) <= sizeof (request->rq_async_args));
 	aa = ptlrpc_req_async_args(request);
-	memset(aa, 0, sizeof *aa);
+	memset(aa, 0, sizeof(*aa));
 
 	aa->pcaa_peer_committed = committed_before_reconnect;
 	aa->pcaa_initial_connect = initial_connect;
diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c
index 2f55ce2..d0a6e56 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/layout.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c
@@ -1669,7 +1669,7 @@
 	if (req != NULL && pill == &req->rq_pill && req->rq_pill_init)
 		return;
 
-	memset(pill, 0, sizeof *pill);
+	memset(pill, 0, sizeof(*pill));
 	pill->rc_req = req;
 	pill->rc_loc = location;
 	req_capsule_init_area(pill);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
index 6547f46..316103a 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
@@ -207,7 +207,7 @@
 			p_idx++;
 			g_idx = 0;
 		}
-	};
+	}
 
 	/* free unused pools */
 	while (p_idx_max1 < p_idx_max2) {
diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c
index acf75f3..21de868 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/service.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/service.c
@@ -263,7 +263,7 @@
  */
 static void rs_batch_init(struct rs_batch *b)
 {
-	memset(b, 0, sizeof *b);
+	memset(b, 0, sizeof(*b));
 	INIT_LIST_HEAD(&b->rsb_replies);
 }
 
@@ -1306,12 +1306,12 @@
 	}
 	newdl = cfs_time_current_sec() + at_get(&svcpt->scp_at_estimate);
 
-	OBD_ALLOC(reqcopy, sizeof *reqcopy);
+	OBD_ALLOC(reqcopy, sizeof(*reqcopy));
 	if (reqcopy == NULL)
 		return -ENOMEM;
 	OBD_ALLOC_LARGE(reqmsg, req->rq_reqlen);
 	if (!reqmsg) {
-		OBD_FREE(reqcopy, sizeof *reqcopy);
+		OBD_FREE(reqcopy, sizeof(*reqcopy));
 		return -ENOMEM;
 	}
 
@@ -1370,7 +1370,7 @@
 out:
 	sptlrpc_svc_ctx_decref(reqcopy);
 	OBD_FREE_LARGE(reqmsg, req->rq_reqlen);
-	OBD_FREE(reqcopy, sizeof *reqcopy);
+	OBD_FREE(reqcopy, sizeof(*reqcopy));
 	return rc;
 }
 
diff --git a/drivers/staging/media/go7007/go7007-usb.c b/drivers/staging/media/go7007/go7007-usb.c
index 46ed832..58684da 100644
--- a/drivers/staging/media/go7007/go7007-usb.c
+++ b/drivers/staging/media/go7007/go7007-usb.c
@@ -34,10 +34,9 @@
 
 static unsigned int assume_endura;
 module_param(assume_endura, int, 0644);
-MODULE_PARM_DESC(assume_endura, "when probing fails, "
-				"hardware is a Pelco Endura");
+MODULE_PARM_DESC(assume_endura,
+			"when probing fails, hardware is a Pelco Endura");
 
-/* #define GO7007_USB_DEBUG */
 /* #define GO7007_I2C_DEBUG */ /* for debugging the EZ-USB I2C adapter */
 
 #define	HPI_STATUS_ADDR	0xFFF4
@@ -662,9 +661,7 @@
 
 	if (usb->board->flags & GO7007_USB_EZUSB) {
 		/* Reset buffer in EZ-USB */
-#ifdef GO7007_USB_DEBUG
-		printk(KERN_DEBUG "go7007-usb: resetting EZ-USB buffers\n");
-#endif
+		dev_dbg(go->dev, "resetting EZ-USB buffers\n");
 		if (go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0 ||
 		    go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0)
 			return -1;
@@ -678,8 +675,7 @@
 	/* Wait for an interrupt to indicate successful hardware reset */
 	if (go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
 			(intr_val & ~0x1) != 0x55aa) {
-		printk(KERN_ERR
-			"go7007-usb: unable to reset the USB interface\n");
+		dev_err(go->dev, "unable to reset the USB interface\n");
 		return -1;
 	}
 	return 0;
@@ -693,10 +689,7 @@
 	u16 status_reg = 0;
 	int timeout = 500;
 
-#ifdef GO7007_USB_DEBUG
-	printk(KERN_DEBUG
-		"go7007-usb: WriteInterrupt: %04x %04x\n", addr, data);
-#endif
+	dev_dbg(go->dev, "WriteInterrupt: %04x %04x\n", addr, data);
 
 	for (i = 0; i < 100; ++i) {
 		r = usb_control_msg(usb->usbdev,
@@ -714,9 +707,7 @@
 	if (r < 0)
 		goto write_int_error;
 	if (i == 100) {
-		printk(KERN_ERR
-			"go7007-usb: device is hung, status reg = 0x%04x\n",
-			status_reg);
+		dev_err(go->dev, "device is hung, status reg = 0x%04x\n", status_reg);
 		return -1;
 	}
 	r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0), 0x12,
@@ -732,7 +723,7 @@
 	return 0;
 
 write_int_error:
-	printk(KERN_ERR "go7007-usb: error in WriteInterrupt: %d\n", r);
+	dev_err(go->dev, "error in WriteInterrupt: %d\n", r);
 	return r;
 }
 
@@ -743,10 +734,7 @@
 	int r;
 	int timeout = 500;
 
-#ifdef GO7007_USB_DEBUG
-	printk(KERN_DEBUG
-		"go7007-usb: WriteInterrupt: %04x %04x\n", addr, data);
-#endif
+	dev_dbg(go->dev, "WriteInterrupt: %04x %04x\n", addr, data);
 
 	go->usb_buf[0] = data & 0xff;
 	go->usb_buf[1] = data >> 8;
@@ -757,7 +745,7 @@
 			USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0x55aa,
 			0xf0f0, go->usb_buf, 8, timeout);
 	if (r < 0) {
-		printk(KERN_ERR "go7007-usb: error in WriteInterrupt: %d\n", r);
+		dev_err(go->dev, "error in WriteInterrupt: %d\n", r);
 		return r;
 	}
 	return 0;
@@ -772,23 +760,19 @@
 	if (status) {
 		if (status != -ESHUTDOWN &&
 				go->status != STATUS_SHUTDOWN) {
-			printk(KERN_ERR
-				"go7007-usb: error in read interrupt: %d\n",
-				urb->status);
+			dev_err(go->dev, "error in read interrupt: %d\n", urb->status);
 		} else {
 			wake_up(&go->interrupt_waitq);
 			return;
 		}
 	} else if (urb->actual_length != urb->transfer_buffer_length) {
-		printk(KERN_ERR "go7007-usb: short read in interrupt pipe!\n");
+		dev_err(go->dev, "short read in interrupt pipe!\n");
 	} else {
 		go->interrupt_available = 1;
 		go->interrupt_data = __le16_to_cpu(regs[0]);
 		go->interrupt_value = __le16_to_cpu(regs[1]);
-#ifdef GO7007_USB_DEBUG
-		printk(KERN_DEBUG "go7007-usb: ReadInterrupt: %04x %04x\n",
+		dev_dbg(go->dev, "ReadInterrupt: %04x %04x\n",
 				go->interrupt_value, go->interrupt_data);
-#endif
 	}
 
 	wake_up(&go->interrupt_waitq);
@@ -801,8 +785,7 @@
 
 	r = usb_submit_urb(usb->intr_urb, GFP_KERNEL);
 	if (r < 0) {
-		printk(KERN_ERR
-			"go7007-usb: unable to submit interrupt urb: %d\n", r);
+		dev_err(go->dev, "unable to submit interrupt urb: %d\n", r);
 		return r;
 	}
 	return 0;
@@ -818,18 +801,17 @@
 		return;
 	}
 	if (status) {
-		printk(KERN_ERR "go7007-usb: error in video pipe: %d\n",
-			status);
+		dev_err(go->dev, "error in video pipe: %d\n", status);
 		return;
 	}
 	if (urb->actual_length != urb->transfer_buffer_length) {
-		printk(KERN_ERR "go7007-usb: short read in video pipe!\n");
+		dev_err(go->dev, "short read in video pipe!\n");
 		return;
 	}
 	go7007_parse_video_stream(go, urb->transfer_buffer, urb->actual_length);
 	r = usb_submit_urb(urb, GFP_ATOMIC);
 	if (r < 0)
-		printk(KERN_ERR "go7007-usb: error in video pipe: %d\n", r);
+		dev_err(go->dev, "error in video pipe: %d\n", r);
 }
 
 static void go7007_usb_read_audio_pipe_complete(struct urb *urb)
@@ -840,19 +822,19 @@
 	if (!vb2_is_streaming(&go->vidq))
 		return;
 	if (status) {
-		printk(KERN_ERR "go7007-usb: error in audio pipe: %d\n",
+		dev_err(go->dev, "error in audio pipe: %d\n",
 			status);
 		return;
 	}
 	if (urb->actual_length != urb->transfer_buffer_length) {
-		printk(KERN_ERR "go7007-usb: short read in audio pipe!\n");
+		dev_err(go->dev, "short read in audio pipe!\n");
 		return;
 	}
 	if (go->audio_deliver != NULL)
 		go->audio_deliver(go, urb->transfer_buffer, urb->actual_length);
 	r = usb_submit_urb(urb, GFP_ATOMIC);
 	if (r < 0)
-		printk(KERN_ERR "go7007-usb: error in audio pipe: %d\n", r);
+		dev_err(go->dev, "error in audio pipe: %d\n", r);
 }
 
 static int go7007_usb_stream_start(struct go7007 *go)
@@ -863,8 +845,7 @@
 	for (i = 0; i < 8; ++i) {
 		r = usb_submit_urb(usb->video_urbs[i], GFP_KERNEL);
 		if (r < 0) {
-			printk(KERN_ERR "go7007-usb: error submitting video "
-					"urb %d: %d\n", i, r);
+			dev_err(go->dev, "error submitting video urb %d: %d\n", i, r);
 			goto video_submit_failed;
 		}
 	}
@@ -874,8 +855,7 @@
 	for (i = 0; i < 8; ++i) {
 		r = usb_submit_urb(usb->audio_urbs[i], GFP_KERNEL);
 		if (r < 0) {
-			printk(KERN_ERR "go7007-usb: error submitting audio "
-					"urb %d: %d\n", i, r);
+			dev_err(go->dev, "error submitting audio urb %d: %d\n", i, r);
 			goto audio_submit_failed;
 		}
 	}
@@ -911,9 +891,7 @@
 	int transferred, pipe;
 	int timeout = 500;
 
-#ifdef GO7007_USB_DEBUG
-	printk(KERN_DEBUG "go7007-usb: DownloadBuffer sending %d bytes\n", len);
-#endif
+	dev_dbg(go->dev, "DownloadBuffer sending %d bytes\n", len);
 
 	if (usb->board->flags & GO7007_USB_EZUSB)
 		pipe = usb_sndbulkpipe(usb->usbdev, 2);
@@ -999,9 +977,8 @@
 				!(msgs[i].flags & I2C_M_RD) &&
 				(msgs[i + 1].flags & I2C_M_RD)) {
 #ifdef GO7007_I2C_DEBUG
-			printk(KERN_DEBUG "go7007-usb: i2c write/read %d/%d "
-					"bytes on %02x\n", msgs[i].len,
-					msgs[i + 1].len, msgs[i].addr);
+			dev_dbg(go->dev, "i2c write/read %d/%d bytes on %02x\n",
+				msgs[i].len, msgs[i + 1].len, msgs[i].addr);
 #endif
 			buf[0] = 0x01;
 			buf[1] = msgs[i].len + 1;
@@ -1011,9 +988,8 @@
 			buf[buf_len++] = msgs[++i].len;
 		} else if (msgs[i].flags & I2C_M_RD) {
 #ifdef GO7007_I2C_DEBUG
-			printk(KERN_DEBUG "go7007-usb: i2c read %d "
-					"bytes on %02x\n", msgs[i].len,
-					msgs[i].addr);
+			dev_dbg(go->dev, "i2c read %d bytes on %02x\n",
+					msgs[i].len, msgs[i].addr);
 #endif
 			buf[0] = 0x01;
 			buf[1] = 1;
@@ -1022,9 +998,8 @@
 			buf_len = 4;
 		} else {
 #ifdef GO7007_I2C_DEBUG
-			printk(KERN_DEBUG "go7007-usb: i2c write %d "
-					"bytes on %02x\n", msgs[i].len,
-					msgs[i].addr);
+			dev_dbg(go->dev, "i2c write %d bytes on %02x\n",
+					msgs[i].len, msgs[i].addr);
 #endif
 			buf[0] = 0x00;
 			buf[1] = msgs[i].len + 1;
@@ -1082,7 +1057,7 @@
 	char *name;
 	int video_pipe, i, v_urb_len;
 
-	printk(KERN_DEBUG "go7007-usb: probing new GO7007 USB board\n");
+	dev_dbg(go->dev, "probing new GO7007 USB board\n");
 
 	switch (id->driver_info) {
 	case GO7007_BOARDID_MATRIX_II:
@@ -1122,14 +1097,13 @@
 		board = &board_px_tv402u;
 		break;
 	case GO7007_BOARDID_LIFEVIEW_LR192:
-		printk(KERN_ERR "go7007-usb: The Lifeview TV Walker Ultra "
-				"is not supported.  Sorry!\n");
+		dev_err(go->dev, "The Lifeview TV Walker Ultra is not supported. Sorry!\n");
 		return -ENODEV;
 		name = "Lifeview TV Walker Ultra";
 		board = &board_lifeview_lr192;
 		break;
 	case GO7007_BOARDID_SENSORAY_2250:
-		printk(KERN_INFO "Sensoray 2250 found\n");
+		dev_info(go->dev, "Sensoray 2250 found\n");
 		name = "Sensoray 2250/2251";
 		board = &board_sensoray_2250;
 		break;
@@ -1138,7 +1112,7 @@
 		board = &board_ads_usbav_709;
 		break;
 	default:
-		printk(KERN_ERR "go7007-usb: unknown board ID %d!\n",
+		dev_err(go->dev, "unknown board ID %d!\n",
 				(unsigned int)id->driver_info);
 		return -ENODEV;
 	}
@@ -1197,8 +1171,7 @@
 		go->i2c_adapter.dev.parent = go->dev;
 		i2c_set_adapdata(&go->i2c_adapter, go);
 		if (i2c_add_adapter(&go->i2c_adapter) < 0) {
-			printk(KERN_ERR
-				"go7007-usb: error: i2c_add_adapter failed\n");
+			dev_err(go->dev, "error: i2c_add_adapter failed\n");
 			goto allocfail;
 		}
 		go->i2c_adapter_online = 1;
@@ -1248,8 +1221,9 @@
 	/* Probe the tuner model on the TV402U */
 	if (go->board_id == GO7007_BOARDID_PX_TV402U) {
 		/* Board strapping indicates tuner model */
-		if (go7007_usb_vendor_request(go, 0x41, 0, 0, go->usb_buf, 3, 1) < 0) {
-			printk(KERN_ERR "go7007-usb: GPIO read failed!\n");
+		if (go7007_usb_vendor_request(go, 0x41, 0, 0, go->usb_buf, 3,
+					1) < 0) {
+			dev_err(go->dev, "GPIO read failed!\n");
 			goto allocfail;
 		}
 		switch (go->usb_buf[0] >> 6) {
@@ -1273,15 +1247,14 @@
 					sizeof(go->name));
 			break;
 		default:
-			printk(KERN_DEBUG "go7007-usb: unable to detect "
-						"tuner type!\n");
+			dev_dbg(go->dev, "unable to detect tuner type!\n");
 			break;
 		}
 		/* Configure tuner mode selection inputs connected
 		 * to the EZ-USB GPIO output pins */
 		if (go7007_usb_vendor_request(go, 0x40, 0x7f02, 0,
 					NULL, 0, 0) < 0) {
-			printk(KERN_ERR "go7007-usb: GPIO write failed!\n");
+			dev_err(go->dev, "GPIO write failed!\n");
 			goto allocfail;
 		}
 	}
@@ -1290,11 +1263,7 @@
 	 * a USB1.1 port.  There will be silent corruption of the stream. */
 	if ((board->flags & GO7007_USB_EZUSB) &&
 			usbdev->speed != USB_SPEED_HIGH)
-		printk(KERN_ERR "go7007-usb: *** WARNING ***  This device "
-				"must be connected to a USB 2.0 port!  "
-				"Attempting to capture video through a USB 1.1 "
-				"port will result in stream corruption, even "
-				"at low bitrates!\n");
+		dev_err(go->dev, "*** WARNING ***  This device must be connected to a USB 2.0 port! Attempting to capture video through a USB 1.1 port will result in stream corruption, even at low bitrates!\n");
 
 	/* Allocate the URBs and buffers for receiving the video stream */
 	if (board->flags & GO7007_USB_EZUSB) {
diff --git a/drivers/staging/media/lirc/lirc_bt829.c b/drivers/staging/media/lirc/lirc_bt829.c
index fa31ee7..fbbdce4 100644
--- a/drivers/staging/media/lirc/lirc_bt829.c
+++ b/drivers/staging/media/lirc/lirc_bt829.c
@@ -132,7 +132,7 @@
 	atir_driver.minor       = -1;
 	atir_driver.code_length = 8;
 	atir_driver.sample_rate = 10;
-	atir_driver.data        = 0;
+	atir_driver.data        = NULL;
 	atir_driver.add_to_buf  = atir_add_to_buf;
 	atir_driver.set_use_inc = atir_set_use_inc;
 	atir_driver.set_use_dec = atir_set_use_dec;
@@ -159,7 +159,7 @@
 static int atir_init_start(void)
 {
 	pci_addr_lin = ioremap(pci_addr_phys + DATA_PCI_OFF, 0x400);
-	if (pci_addr_lin == 0) {
+	if (!pci_addr_lin) {
 		pr_info("pci mem must be mapped\n");
 		return 0;
 	}
diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c
index 4afa7da..ab2ae11 100644
--- a/drivers/staging/media/lirc/lirc_imon.c
+++ b/drivers/staging/media/lirc/lirc_imon.c
@@ -625,7 +625,7 @@
 	}
 
 	if (debug) {
-		printk(KERN_INFO "raw packet: ");
+		dev_info(dev, "raw packet: ");
 		for (i = 0; i < len; ++i)
 			printk("%02x ", buf[i]);
 		printk("\n");
diff --git a/drivers/staging/media/lirc/lirc_serial.c b/drivers/staging/media/lirc/lirc_serial.c
index af08e67..f6bc4c9 100644
--- a/drivers/staging/media/lirc/lirc_serial.c
+++ b/drivers/staging/media/lirc/lirc_serial.c
@@ -67,7 +67,7 @@
 #include <linux/delay.h>
 #include <linux/poll.h>
 #include <linux/platform_device.h>
-
+#include <linux/gpio.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/fcntl.h>
@@ -321,7 +321,7 @@
 	 * status LED and ground
 	 */
 	if (type == LIRC_NSLU2) {
-		gpio_line_set(NSLU2_LED_GRN, IXP4XX_GPIO_LOW);
+		gpio_set_value(NSLU2_LED_GRN, 0);
 		return;
 	}
 #endif
@@ -335,7 +335,7 @@
 {
 #ifdef CONFIG_LIRC_SERIAL_NSLU2
 	if (type == LIRC_NSLU2) {
-		gpio_line_set(NSLU2_LED_GRN, IXP4XX_GPIO_HIGH);
+		gpio_set_value(NSLU2_LED_GRN, 1);
 		return;
 	}
 #endif
@@ -839,6 +839,16 @@
 {
 	int i, nlow, nhigh, result;
 
+#ifdef CONFIG_LIRC_SERIAL_NSLU2
+	/* This GPIO is used for a LED on the NSLU2 */
+	result = devm_gpio_request(dev, NSLU2_LED_GRN, "lirc-serial");
+	if (result)
+		return result;
+	result = gpio_direction_output(NSLU2_LED_GRN, 0);
+	if (result)
+		return result;
+#endif
+
 	result = request_irq(irq, irq_handler,
 			     (share_irq ? IRQF_SHARED : 0),
 			     LIRC_DRIVER_NAME, (void *)&hardware);
diff --git a/drivers/staging/media/msi3101/Kconfig b/drivers/staging/media/msi3101/Kconfig
index b94a95a..76d5bbd 100644
--- a/drivers/staging/media/msi3101/Kconfig
+++ b/drivers/staging/media/msi3101/Kconfig
@@ -1,3 +1,4 @@
 config USB_MSI3101
 	tristate "Mirics MSi3101 SDR Dongle"
 	depends on USB && VIDEO_DEV && VIDEO_V4L2
+        select VIDEOBUF2_VMALLOC
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/staging/media/msi3101/sdr-msi3101.c
index 24c7b70..4c3bf77 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/staging/media/msi3101/sdr-msi3101.c
@@ -1131,7 +1131,13 @@
 	/* Absolute min and max number of buffers available for mmap() */
 	*nbuffers = 32;
 	*nplanes = 1;
-	sizes[0] = PAGE_ALIGN(3 * 3072); /* 3 * 768 * 4 */
+	/*
+	 *   3, wMaxPacketSize 3x 1024 bytes
+	 * 504, max IQ sample pairs per 1024 frame
+	 *   2, two samples, I and Q
+	 *   4, 32-bit float
+	 */
+	sizes[0] = PAGE_ALIGN(3 * 504 * 2 * 4); /* = 12096 */
 	dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
 			__func__, *nbuffers, sizes[0]);
 	return 0;
@@ -1657,7 +1663,7 @@
 			f->frequency * 625UL / 10UL);
 }
 
-const struct v4l2_ioctl_ops msi3101_ioctl_ops = {
+static const struct v4l2_ioctl_ops msi3101_ioctl_ops = {
 	.vidioc_querycap          = msi3101_querycap,
 
 	.vidioc_enum_input        = msi3101_enum_input,
diff --git a/drivers/staging/mt29f_spinand/Kconfig b/drivers/staging/mt29f_spinand/Kconfig
new file mode 100644
index 0000000..4031748
--- /dev/null
+++ b/drivers/staging/mt29f_spinand/Kconfig
@@ -0,0 +1,16 @@
+config MTD_SPINAND_MT29F
+	tristate "SPINAND Device Support for Micron"
+	depends on MTD_NAND && SPI
+	help
+	  This enables support for accessing Micron SPI NAND flash
+	  devices.
+	  If you have Micron SPI NAND chip say yes.
+
+	  If unsure, say no here.
+
+config MTD_SPINAND_ONDIEECC
+	bool "Use SPINAND internal ECC"
+	depends on MTD_SPINAND_MT29F
+	help
+	  Internel ECC.
+	  Enables Hardware ECC support for Micron SPI NAND.
diff --git a/drivers/staging/mt29f_spinand/Makefile b/drivers/staging/mt29f_spinand/Makefile
new file mode 100644
index 0000000..e47af0f
--- /dev/null
+++ b/drivers/staging/mt29f_spinand/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MTD_SPINAND_MT29F) += mt29f_spinand.o
diff --git a/drivers/staging/mt29f_spinand/TODO b/drivers/staging/mt29f_spinand/TODO
new file mode 100644
index 0000000..a2209b7
--- /dev/null
+++ b/drivers/staging/mt29f_spinand/TODO
@@ -0,0 +1,13 @@
+TODO:
+	- Tested on XLP platform, needs to be tested on other platforms.
+	- Checkpatch.pl cleanups
+	- Sparce fixes.
+	- Clean up coding style to meet kernel standard.
+
+Please send patches
+To:
+Kamlakant Patel <kamlakant.patel@broadcom.com>
+Cc:
+Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Mona Anonuevo <manonuevo@micron.com>
+linux-mtd@lists.infradead.org
diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c
new file mode 100644
index 0000000..51dbc13
--- /dev/null
+++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c
@@ -0,0 +1,947 @@
+/*
+ * Copyright (c) 2003-2013 Broadcom Corporation
+ *
+ * Copyright (c) 2009-2010 Micron Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand.h>
+#include <linux/spi/spi.h>
+
+#include "mt29f_spinand.h"
+
+#define BUFSIZE (10 * 64 * 2048)
+#define CACHE_BUF 2112
+/*
+ * OOB area specification layout:  Total 32 available free bytes.
+ */
+
+static inline struct spinand_state *mtd_to_state(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
+	struct spinand_info *info = (struct spinand_info *)chip->priv;
+	struct spinand_state *state = (struct spinand_state *)info->priv;
+
+	return state;
+}
+
+#ifdef CONFIG_MTD_SPINAND_ONDIEECC
+static int enable_hw_ecc;
+static int enable_read_hw_ecc;
+
+static struct nand_ecclayout spinand_oob_64 = {
+	.eccbytes = 24,
+	.eccpos = {
+		1, 2, 3, 4, 5, 6,
+		17, 18, 19, 20, 21, 22,
+		33, 34, 35, 36, 37, 38,
+		49, 50, 51, 52, 53, 54, },
+	.oobavail = 32,
+	.oobfree = {
+		{.offset = 8,
+			.length = 8},
+		{.offset = 24,
+			.length = 8},
+		{.offset = 40,
+			.length = 8},
+		{.offset = 56,
+			.length = 8},
+	}
+};
+#endif
+
+/*
+ * spinand_cmd - to process a command to send to the SPI Nand
+ * Description:
+ *    Set up the command buffer to send to the SPI controller.
+ *    The command buffer has to initialized to 0.
+ */
+
+static int spinand_cmd(struct spi_device *spi, struct spinand_cmd *cmd)
+{
+	struct spi_message message;
+	struct spi_transfer x[4];
+	u8 dummy = 0xff;
+
+	spi_message_init(&message);
+	memset(x, 0, sizeof(x));
+
+	x[0].len = 1;
+	x[0].tx_buf = &cmd->cmd;
+	spi_message_add_tail(&x[0], &message);
+
+	if (cmd->n_addr) {
+		x[1].len = cmd->n_addr;
+		x[1].tx_buf = cmd->addr;
+		spi_message_add_tail(&x[1], &message);
+	}
+
+	if (cmd->n_dummy) {
+		x[2].len = cmd->n_dummy;
+		x[2].tx_buf = &dummy;
+		spi_message_add_tail(&x[2], &message);
+	}
+
+	if (cmd->n_tx) {
+		x[3].len = cmd->n_tx;
+		x[3].tx_buf = cmd->tx_buf;
+		spi_message_add_tail(&x[3], &message);
+	}
+
+	if (cmd->n_rx) {
+		x[3].len = cmd->n_rx;
+		x[3].rx_buf = cmd->rx_buf;
+		spi_message_add_tail(&x[3], &message);
+	}
+
+	return spi_sync(spi, &message);
+}
+
+/*
+ * spinand_read_id- Read SPI Nand ID
+ * Description:
+ *    Read ID: read two ID bytes from the SPI Nand device
+ */
+static int spinand_read_id(struct spi_device *spi_nand, u8 *id)
+{
+	int retval;
+	u8 nand_id[3];
+	struct spinand_cmd cmd = {0};
+
+	cmd.cmd = CMD_READ_ID;
+	cmd.n_rx = 3;
+	cmd.rx_buf = &nand_id[0];
+
+	retval = spinand_cmd(spi_nand, &cmd);
+	if (retval < 0) {
+		dev_err(&spi_nand->dev, "error %d reading id\n", retval);
+		return retval;
+	}
+	id[0] = nand_id[1];
+	id[1] = nand_id[2];
+	return retval;
+}
+
+/*
+ * spinand_read_status- send command 0xf to the SPI Nand status register
+ * Description:
+ *    After read, write, or erase, the Nand device is expected to set the
+ *    busy status.
+ *    This function is to allow reading the status of the command: read,
+ *    write, and erase.
+ *    Once the status turns to be ready, the other status bits also are
+ *    valid status bits.
+ */
+static int spinand_read_status(struct spi_device *spi_nand, uint8_t *status)
+{
+	struct spinand_cmd cmd = {0};
+	int ret;
+
+	cmd.cmd = CMD_READ_REG;
+	cmd.n_addr = 1;
+	cmd.addr[0] = REG_STATUS;
+	cmd.n_rx = 1;
+	cmd.rx_buf = status;
+
+	ret = spinand_cmd(spi_nand, &cmd);
+	if (ret < 0)
+		dev_err(&spi_nand->dev, "err: %d read status register\n", ret);
+
+	return ret;
+}
+
+#define MAX_WAIT_JIFFIES  (40 * HZ)
+static int wait_till_ready(struct spi_device *spi_nand)
+{
+	unsigned long deadline;
+	int retval;
+	u8 stat = 0;
+
+	deadline = jiffies + MAX_WAIT_JIFFIES;
+	do {
+		retval = spinand_read_status(spi_nand, &stat);
+		if (retval < 0)
+			return -1;
+		else if (!(stat & 0x1))
+			break;
+
+		cond_resched();
+	} while (!time_after_eq(jiffies, deadline));
+
+	if ((stat & 0x1) == 0)
+		return 0;
+
+	return -1;
+}
+/**
+ * spinand_get_otp- send command 0xf to read the SPI Nand OTP register
+ * Description:
+ *   There is one bit( bit 0x10 ) to set or to clear the internal ECC.
+ *   Enable chip internal ECC, set the bit to 1
+ *   Disable chip internal ECC, clear the bit to 0
+ */
+static int spinand_get_otp(struct spi_device *spi_nand, u8 *otp)
+{
+	struct spinand_cmd cmd = {0};
+	int retval;
+
+	cmd.cmd = CMD_READ_REG;
+	cmd.n_addr = 1;
+	cmd.addr[0] = REG_OTP;
+	cmd.n_rx = 1;
+	cmd.rx_buf = otp;
+
+	retval = spinand_cmd(spi_nand, &cmd);
+	if (retval < 0)
+		dev_err(&spi_nand->dev, "error %d get otp\n", retval);
+	return retval;
+}
+
+/**
+ * spinand_set_otp- send command 0x1f to write the SPI Nand OTP register
+ * Description:
+ *   There is one bit( bit 0x10 ) to set or to clear the internal ECC.
+ *   Enable chip internal ECC, set the bit to 1
+ *   Disable chip internal ECC, clear the bit to 0
+ */
+static int spinand_set_otp(struct spi_device *spi_nand, u8 *otp)
+{
+	int retval;
+	struct spinand_cmd cmd = {0};
+
+	cmd.cmd = CMD_WRITE_REG,
+	cmd.n_addr = 1,
+	cmd.addr[0] = REG_OTP,
+	cmd.n_tx = 1,
+	cmd.tx_buf = otp,
+
+	retval = spinand_cmd(spi_nand, &cmd);
+	if (retval < 0)
+		dev_err(&spi_nand->dev, "error %d set otp\n", retval);
+
+	return retval;
+}
+
+#ifdef CONFIG_MTD_SPINAND_ONDIEECC
+/**
+ * spinand_enable_ecc- send command 0x1f to write the SPI Nand OTP register
+ * Description:
+ *   There is one bit( bit 0x10 ) to set or to clear the internal ECC.
+ *   Enable chip internal ECC, set the bit to 1
+ *   Disable chip internal ECC, clear the bit to 0
+ */
+static int spinand_enable_ecc(struct spi_device *spi_nand)
+{
+	int retval;
+	u8 otp = 0;
+
+	retval = spinand_get_otp(spi_nand, &otp);
+	if (retval < 0)
+		return retval;
+
+	if ((otp & OTP_ECC_MASK) == OTP_ECC_MASK) {
+		return 0;
+	} else {
+		otp |= OTP_ECC_MASK;
+		retval = spinand_set_otp(spi_nand, &otp);
+		if (retval < 0)
+			return retval;
+		return spinand_get_otp(spi_nand, &otp);
+	}
+}
+#endif
+
+static int spinand_disable_ecc(struct spi_device *spi_nand)
+{
+	int retval;
+	u8 otp = 0;
+
+	retval = spinand_get_otp(spi_nand, &otp);
+	if (retval < 0)
+		return retval;
+
+	if ((otp & OTP_ECC_MASK) == OTP_ECC_MASK) {
+		otp &= ~OTP_ECC_MASK;
+		retval = spinand_set_otp(spi_nand, &otp);
+		if (retval < 0)
+			return retval;
+		return spinand_get_otp(spi_nand, &otp);
+	} else
+		return 0;
+}
+
+/**
+ * spinand_write_enable- send command 0x06 to enable write or erase the
+ * Nand cells
+ * Description:
+ *   Before write and erase the Nand cells, the write enable has to be set.
+ *   After the write or erase, the write enable bit is automatically
+ *   cleared (status register bit 2)
+ *   Set the bit 2 of the status register has the same effect
+ */
+static int spinand_write_enable(struct spi_device *spi_nand)
+{
+	struct spinand_cmd cmd = {0};
+
+	cmd.cmd = CMD_WR_ENABLE;
+	return spinand_cmd(spi_nand, &cmd);
+}
+
+static int spinand_read_page_to_cache(struct spi_device *spi_nand, u16 page_id)
+{
+	struct spinand_cmd cmd = {0};
+	u16 row;
+
+	row = page_id;
+	cmd.cmd = CMD_READ;
+	cmd.n_addr = 3;
+	cmd.addr[1] = (u8)((row & 0xff00) >> 8);
+	cmd.addr[2] = (u8)(row & 0x00ff);
+
+	return spinand_cmd(spi_nand, &cmd);
+}
+
+/*
+ * spinand_read_from_cache- send command 0x03 to read out the data from the
+ * cache register(2112 bytes max)
+ * Description:
+ *   The read can specify 1 to 2112 bytes of data read at the corresponding
+ *   locations.
+ *   No tRd delay.
+ */
+static int spinand_read_from_cache(struct spi_device *spi_nand, u16 page_id,
+		u16 byte_id, u16 len, u8 *rbuf)
+{
+	struct spinand_cmd cmd = {0};
+	u16 column;
+
+	column = byte_id;
+	cmd.cmd = CMD_READ_RDM;
+	cmd.n_addr = 3;
+	cmd.addr[0] = (u8)((column & 0xff00) >> 8);
+	cmd.addr[0] |= (u8)(((page_id >> 6) & 0x1) << 4);
+	cmd.addr[1] = (u8)(column & 0x00ff);
+	cmd.addr[2] = (u8)(0xff);
+	cmd.n_dummy = 0;
+	cmd.n_rx = len;
+	cmd.rx_buf = rbuf;
+
+	return spinand_cmd(spi_nand, &cmd);
+}
+
+/*
+ * spinand_read_page-to read a page with:
+ * @page_id: the physical page number
+ * @offset:  the location from 0 to 2111
+ * @len:     number of bytes to read
+ * @rbuf:    read buffer to hold @len bytes
+ *
+ * Description:
+ *   The read includes two commands to the Nand: 0x13 and 0x03 commands
+ *   Poll to read status to wait for tRD time.
+ */
+static int spinand_read_page(struct spi_device *spi_nand, u16 page_id,
+		u16 offset, u16 len, u8 *rbuf)
+{
+	int ret;
+	u8 status = 0;
+
+#ifdef CONFIG_MTD_SPINAND_ONDIEECC
+	if (enable_read_hw_ecc) {
+		if (spinand_enable_ecc(spi_nand) < 0)
+			dev_err(&spi_nand->dev, "enable HW ECC failed!");
+	}
+#endif
+	ret = spinand_read_page_to_cache(spi_nand, page_id);
+	if (ret < 0)
+		return ret;
+
+	if (wait_till_ready(spi_nand))
+		dev_err(&spi_nand->dev, "WAIT timedout!!!\n");
+
+	while (1) {
+		ret = spinand_read_status(spi_nand, &status);
+		if (ret < 0) {
+			dev_err(&spi_nand->dev,
+					"err %d read status register\n", ret);
+			return ret;
+		}
+
+		if ((status & STATUS_OIP_MASK) == STATUS_READY) {
+			if ((status & STATUS_ECC_MASK) == STATUS_ECC_ERROR) {
+				dev_err(&spi_nand->dev, "ecc error, page=%d\n",
+						page_id);
+				return 0;
+			}
+			break;
+		}
+	}
+
+	ret = spinand_read_from_cache(spi_nand, page_id, offset, len, rbuf);
+	if (ret < 0) {
+		dev_err(&spi_nand->dev, "read from cache failed!!\n");
+		return ret;
+	}
+
+#ifdef CONFIG_MTD_SPINAND_ONDIEECC
+	if (enable_read_hw_ecc) {
+		ret = spinand_disable_ecc(spi_nand);
+		if (ret < 0) {
+			dev_err(&spi_nand->dev, "disable ecc failed!!\n");
+			return ret;
+		}
+		enable_read_hw_ecc = 0;
+	}
+#endif
+	return ret;
+}
+
+/*
+ * spinand_program_data_to_cache--to write a page to cache with:
+ * @byte_id: the location to write to the cache
+ * @len:     number of bytes to write
+ * @rbuf:    read buffer to hold @len bytes
+ *
+ * Description:
+ *   The write command used here is 0x84--indicating that the cache is
+ *   not cleared first.
+ *   Since it is writing the data to cache, there is no tPROG time.
+ */
+static int spinand_program_data_to_cache(struct spi_device *spi_nand,
+		u16 page_id, u16 byte_id, u16 len, u8 *wbuf)
+{
+	struct spinand_cmd cmd = {0};
+	u16 column;
+
+	column = byte_id;
+	cmd.cmd = CMD_PROG_PAGE_CLRCACHE;
+	cmd.n_addr = 2;
+	cmd.addr[0] = (u8)((column & 0xff00) >> 8);
+	cmd.addr[0] |= (u8)(((page_id >> 6) & 0x1) << 4);
+	cmd.addr[1] = (u8)(column & 0x00ff);
+	cmd.n_tx = len;
+	cmd.tx_buf = wbuf;
+
+	return spinand_cmd(spi_nand, &cmd);
+}
+
+/**
+ * spinand_program_execute--to write a page from cache to the Nand array with
+ * @page_id: the physical page location to write the page.
+ *
+ * Description:
+ *   The write command used here is 0x10--indicating the cache is writing to
+ *   the Nand array.
+ *   Need to wait for tPROG time to finish the transaction.
+ */
+static int spinand_program_execute(struct spi_device *spi_nand, u16 page_id)
+{
+	struct spinand_cmd cmd = {0};
+	u16 row;
+
+	row = page_id;
+	cmd.cmd = CMD_PROG_PAGE_EXC;
+	cmd.n_addr = 3;
+	cmd.addr[1] = (u8)((row & 0xff00) >> 8);
+	cmd.addr[2] = (u8)(row & 0x00ff);
+
+	return spinand_cmd(spi_nand, &cmd);
+}
+
+/**
+ * spinand_program_page--to write a page with:
+ * @page_id: the physical page location to write the page.
+ * @offset:  the location from the cache starting from 0 to 2111
+ * @len:     the number of bytes to write
+ * @wbuf:    the buffer to hold the number of bytes
+ *
+ * Description:
+ *   The commands used here are 0x06, 0x84, and 0x10--indicating that
+ *   the write enable is first sent, the write cache command, and the
+ *   write execute command.
+ *   Poll to wait for the tPROG time to finish the transaction.
+ */
+static int spinand_program_page(struct spi_device *spi_nand,
+		u16 page_id, u16 offset, u16 len, u8 *buf)
+{
+	int retval;
+	u8 status = 0;
+	uint8_t *wbuf;
+#ifdef CONFIG_MTD_SPINAND_ONDIEECC
+	unsigned int i, j;
+
+	enable_read_hw_ecc = 0;
+	wbuf = devm_kzalloc(&spi_nand->dev, CACHE_BUF, GFP_KERNEL);
+	spinand_read_page(spi_nand, page_id, 0, CACHE_BUF, wbuf);
+
+	for (i = offset, j = 0; i < len; i++, j++)
+		wbuf[i] &= buf[j];
+
+	if (enable_hw_ecc) {
+		retval = spinand_enable_ecc(spi_nand);
+		if (retval < 0) {
+			dev_err(&spi_nand->dev, "enable ecc failed!!\n");
+			return retval;
+		}
+	}
+#else
+	wbuf = buf;
+#endif
+	retval = spinand_write_enable(spi_nand);
+	if (retval < 0) {
+		dev_err(&spi_nand->dev, "write enable failed!!\n");
+		return retval;
+	}
+	if (wait_till_ready(spi_nand))
+		dev_err(&spi_nand->dev, "wait timedout!!!\n");
+
+	retval = spinand_program_data_to_cache(spi_nand, page_id,
+			offset, len, wbuf);
+	if (retval < 0)
+		return retval;
+	retval = spinand_program_execute(spi_nand, page_id);
+	if (retval < 0)
+		return retval;
+	while (1) {
+		retval = spinand_read_status(spi_nand, &status);
+		if (retval < 0) {
+			dev_err(&spi_nand->dev,
+					"error %d reading status register\n",
+					retval);
+			return retval;
+		}
+
+		if ((status & STATUS_OIP_MASK) == STATUS_READY) {
+			if ((status & STATUS_P_FAIL_MASK) == STATUS_P_FAIL) {
+				dev_err(&spi_nand->dev,
+					"program error, page %d\n", page_id);
+				return -1;
+			} else
+				break;
+		}
+	}
+#ifdef CONFIG_MTD_SPINAND_ONDIEECC
+	if (enable_hw_ecc) {
+		retval = spinand_disable_ecc(spi_nand);
+		if (retval < 0) {
+			dev_err(&spi_nand->dev, "disable ecc failed!!\n");
+			return retval;
+		}
+		enable_hw_ecc = 0;
+	}
+#endif
+
+	return 0;
+}
+
+/**
+ * spinand_erase_block_erase--to erase a page with:
+ * @block_id: the physical block location to erase.
+ *
+ * Description:
+ *   The command used here is 0xd8--indicating an erase command to erase
+ *   one block--64 pages
+ *   Need to wait for tERS.
+ */
+static int spinand_erase_block_erase(struct spi_device *spi_nand, u16 block_id)
+{
+	struct spinand_cmd cmd = {0};
+	u16 row;
+
+	row = block_id;
+	cmd.cmd = CMD_ERASE_BLK;
+	cmd.n_addr = 3;
+	cmd.addr[1] = (u8)((row & 0xff00) >> 8);
+	cmd.addr[2] = (u8)(row & 0x00ff);
+
+	return spinand_cmd(spi_nand, &cmd);
+}
+
+/**
+ * spinand_erase_block--to erase a page with:
+ * @block_id: the physical block location to erase.
+ *
+ * Description:
+ *   The commands used here are 0x06 and 0xd8--indicating an erase
+ *   command to erase one block--64 pages
+ *   It will first to enable the write enable bit (0x06 command),
+ *   and then send the 0xd8 erase command
+ *   Poll to wait for the tERS time to complete the tranaction.
+ */
+static int spinand_erase_block(struct spi_device *spi_nand, u16 block_id)
+{
+	int retval;
+	u8 status = 0;
+
+	retval = spinand_write_enable(spi_nand);
+	if (wait_till_ready(spi_nand))
+		dev_err(&spi_nand->dev, "wait timedout!!!\n");
+
+	retval = spinand_erase_block_erase(spi_nand, block_id);
+	while (1) {
+		retval = spinand_read_status(spi_nand, &status);
+		if (retval < 0) {
+			dev_err(&spi_nand->dev,
+					"error %d reading status register\n",
+					(int) retval);
+			return retval;
+		}
+
+		if ((status & STATUS_OIP_MASK) == STATUS_READY) {
+			if ((status & STATUS_E_FAIL_MASK) == STATUS_E_FAIL) {
+				dev_err(&spi_nand->dev,
+					"erase error, block %d\n", block_id);
+				return -1;
+			} else
+				break;
+		}
+	}
+	return 0;
+}
+
+#ifdef CONFIG_MTD_SPINAND_ONDIEECC
+static int spinand_write_page_hwecc(struct mtd_info *mtd,
+		struct nand_chip *chip, const uint8_t *buf, int oob_required)
+{
+	const uint8_t *p = buf;
+	int eccsize = chip->ecc.size;
+	int eccsteps = chip->ecc.steps;
+
+	enable_hw_ecc = 1;
+	chip->write_buf(mtd, p, eccsize * eccsteps);
+	return 0;
+}
+
+static int spinand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
+		uint8_t *buf, int oob_required, int page)
+{
+	u8 retval, status;
+	uint8_t *p = buf;
+	int eccsize = chip->ecc.size;
+	int eccsteps = chip->ecc.steps;
+	struct spinand_info *info = (struct spinand_info *)chip->priv;
+
+	enable_read_hw_ecc = 1;
+
+	chip->read_buf(mtd, p, eccsize * eccsteps);
+	if (oob_required)
+		chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+	while (1) {
+		retval = spinand_read_status(info->spi, &status);
+		if ((status & STATUS_OIP_MASK) == STATUS_READY) {
+			if ((status & STATUS_ECC_MASK) == STATUS_ECC_ERROR) {
+				pr_info("spinand: ECC error\n");
+				mtd->ecc_stats.failed++;
+			} else if ((status & STATUS_ECC_MASK) ==
+					STATUS_ECC_1BIT_CORRECTED)
+				mtd->ecc_stats.corrected++;
+			break;
+		}
+	}
+	return 0;
+
+}
+#endif
+
+static void spinand_select_chip(struct mtd_info *mtd, int dev)
+{
+}
+
+static uint8_t spinand_read_byte(struct mtd_info *mtd)
+{
+	struct spinand_state *state = mtd_to_state(mtd);
+	u8 data;
+
+	data = state->buf[state->buf_ptr];
+	state->buf_ptr++;
+	return data;
+}
+
+
+static int spinand_wait(struct mtd_info *mtd, struct nand_chip *chip)
+{
+	struct spinand_info *info = (struct spinand_info *)chip->priv;
+
+	unsigned long timeo = jiffies;
+	int retval, state = chip->state;
+	u8 status;
+
+	if (state == FL_ERASING)
+		timeo += (HZ * 400) / 1000;
+	else
+		timeo += (HZ * 20) / 1000;
+
+	while (time_before(jiffies, timeo)) {
+		retval = spinand_read_status(info->spi, &status);
+		if ((status & STATUS_OIP_MASK) == STATUS_READY)
+			return 0;
+
+		cond_resched();
+	}
+	return 0;
+}
+
+static void spinand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+
+	struct spinand_state *state = mtd_to_state(mtd);
+	memcpy(state->buf + state->buf_ptr, buf, len);
+	state->buf_ptr += len;
+}
+
+static void spinand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+	struct spinand_state *state = mtd_to_state(mtd);
+	memcpy(buf, state->buf + state->buf_ptr, len);
+	state->buf_ptr += len;
+}
+
+/*
+ * spinand_reset- send RESET command "0xff" to the Nand device.
+ */
+static void spinand_reset(struct spi_device *spi_nand)
+{
+	struct spinand_cmd cmd = {0};
+
+	cmd.cmd = CMD_RESET;
+
+	if (spinand_cmd(spi_nand, &cmd) < 0)
+		pr_info("spinand reset failed!\n");
+
+	/* elapse 1ms before issuing any other command */
+	udelay(1000);
+
+	if (wait_till_ready(spi_nand))
+		dev_err(&spi_nand->dev, "wait timedout!\n");
+}
+
+static void spinand_cmdfunc(struct mtd_info *mtd, unsigned int command,
+		int column, int page)
+{
+	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
+	struct spinand_info *info = (struct spinand_info *)chip->priv;
+	struct spinand_state *state = (struct spinand_state *)info->priv;
+
+	switch (command) {
+	/*
+	 * READ0 - read in first  0x800 bytes
+	 */
+	case NAND_CMD_READ1:
+	case NAND_CMD_READ0:
+		state->buf_ptr = 0;
+		spinand_read_page(info->spi, page, 0x0, 0x840, state->buf);
+		break;
+	/* READOOB reads only the OOB because no ECC is performed. */
+	case NAND_CMD_READOOB:
+		state->buf_ptr = 0;
+		spinand_read_page(info->spi, page, 0x800, 0x40, state->buf);
+		break;
+	case NAND_CMD_RNDOUT:
+		state->buf_ptr = column;
+		break;
+	case NAND_CMD_READID:
+		state->buf_ptr = 0;
+		spinand_read_id(info->spi, (u8 *)state->buf);
+		break;
+	case NAND_CMD_PARAM:
+		state->buf_ptr = 0;
+		break;
+	/* ERASE1 stores the block and page address */
+	case NAND_CMD_ERASE1:
+		spinand_erase_block(info->spi, page);
+		break;
+	/* ERASE2 uses the block and page address from ERASE1 */
+	case NAND_CMD_ERASE2:
+		break;
+	/* SEQIN sets up the addr buffer and all registers except the length */
+	case NAND_CMD_SEQIN:
+		state->col = column;
+		state->row = page;
+		state->buf_ptr = 0;
+		break;
+	/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
+	case NAND_CMD_PAGEPROG:
+		spinand_program_page(info->spi, state->row, state->col,
+				state->buf_ptr, state->buf);
+		break;
+	case NAND_CMD_STATUS:
+		spinand_get_otp(info->spi, state->buf);
+		if (!(state->buf[0] & 0x80))
+			state->buf[0] = 0x80;
+		state->buf_ptr = 0;
+		break;
+	/* RESET command */
+	case NAND_CMD_RESET:
+		if (wait_till_ready(info->spi))
+			dev_err(&info->spi->dev, "WAIT timedout!!!\n");
+		/* a minimum of 250us must elapse before issuing RESET cmd*/
+		udelay(250);
+		spinand_reset(info->spi);
+		break;
+	default:
+		dev_err(&mtd->dev, "Unknown CMD: 0x%x\n", command);
+	}
+}
+
+/**
+ * spinand_lock_block- send write register 0x1f command to the Nand device
+ *
+ * Description:
+ *    After power up, all the Nand blocks are locked.  This function allows
+ *    one to unlock the blocks, and so it can be written or erased.
+ */
+static int spinand_lock_block(struct spi_device *spi_nand, u8 lock)
+{
+	struct spinand_cmd cmd = {0};
+	int ret;
+	u8 otp = 0;
+
+	ret = spinand_get_otp(spi_nand, &otp);
+
+	cmd.cmd = CMD_WRITE_REG;
+	cmd.n_addr = 1;
+	cmd.addr[0] = REG_BLOCK_LOCK;
+	cmd.n_tx = 1;
+	cmd.tx_buf = &lock;
+
+	ret = spinand_cmd(spi_nand, &cmd);
+	if (ret < 0)
+		dev_err(&spi_nand->dev, "error %d lock block\n", ret);
+
+	return ret;
+}
+/*
+ * spinand_probe - [spinand Interface]
+ * @spi_nand: registered device driver.
+ *
+ * Description:
+ *   To set up the device driver parameters to make the device available.
+ */
+static int spinand_probe(struct spi_device *spi_nand)
+{
+	struct mtd_info *mtd;
+	struct nand_chip *chip;
+	struct spinand_info *info;
+	struct spinand_state *state;
+	struct mtd_part_parser_data ppdata;
+
+	info  = devm_kzalloc(&spi_nand->dev, sizeof(struct spinand_info),
+			GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->spi = spi_nand;
+
+	spinand_lock_block(spi_nand, BL_ALL_UNLOCKED);
+
+	state = devm_kzalloc(&spi_nand->dev, sizeof(struct spinand_state),
+			GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	info->priv	= state;
+	state->buf_ptr	= 0;
+	state->buf	= devm_kzalloc(&spi_nand->dev, BUFSIZE, GFP_KERNEL);
+	if (!state->buf)
+		return -ENOMEM;
+
+	chip = devm_kzalloc(&spi_nand->dev, sizeof(struct nand_chip),
+			GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+#ifdef CONFIG_MTD_SPINAND_ONDIEECC
+	chip->ecc.mode	= NAND_ECC_HW;
+	chip->ecc.size	= 0x200;
+	chip->ecc.bytes	= 0x6;
+	chip->ecc.steps	= 0x4;
+
+	chip->ecc.strength = 1;
+	chip->ecc.total	= chip->ecc.steps * chip->ecc.bytes;
+	chip->ecc.layout = &spinand_oob_64;
+	chip->ecc.read_page = spinand_read_page_hwecc;
+	chip->ecc.write_page = spinand_write_page_hwecc;
+#else
+	chip->ecc.mode	= NAND_ECC_SOFT;
+	if (spinand_disable_ecc(spi_nand) < 0)
+		pr_info("%s: disable ecc failed!\n", __func__);
+#endif
+
+	chip->priv	= info;
+	chip->read_buf	= spinand_read_buf;
+	chip->write_buf	= spinand_write_buf;
+	chip->read_byte	= spinand_read_byte;
+	chip->cmdfunc	= spinand_cmdfunc;
+	chip->waitfunc	= spinand_wait;
+	chip->options	|= NAND_CACHEPRG;
+	chip->select_chip = spinand_select_chip;
+
+	mtd = devm_kzalloc(&spi_nand->dev, sizeof(struct mtd_info), GFP_KERNEL);
+	if (!mtd)
+		return -ENOMEM;
+
+	dev_set_drvdata(&spi_nand->dev, mtd);
+
+	mtd->priv = chip;
+	mtd->name = dev_name(&spi_nand->dev);
+	mtd->owner = THIS_MODULE;
+	mtd->oobsize = 64;
+
+	if (nand_scan(mtd, 1))
+		return -ENXIO;
+
+	ppdata.of_node = spi_nand->dev.of_node;
+	return mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
+}
+
+/*
+ * spinand_remove: Remove the device driver
+ * @spi: the spi device.
+ *
+ * Description:
+ *   To remove the device driver parameters and free up allocated memories.
+ */
+static int spinand_remove(struct spi_device *spi)
+{
+	mtd_device_unregister(dev_get_drvdata(&spi->dev));
+
+	return 0;
+}
+
+static const struct of_device_id spinand_dt[] = {
+	{ .compatible = "spinand,mt29f", },
+};
+
+/*
+ * Device name structure description
+ */
+static struct spi_driver spinand_driver = {
+	.driver = {
+		.name		= "mt29f",
+		.bus		= &spi_bus_type,
+		.owner		= THIS_MODULE,
+		.of_match_table	= spinand_dt,
+	},
+	.probe		= spinand_probe,
+	.remove		= spinand_remove,
+};
+
+module_spi_driver(spinand_driver);
+
+MODULE_DESCRIPTION("SPI NAND driver for Micron");
+MODULE_AUTHOR("Henry Pan <hspan@micron.com>, Kamlakant Patel <kamlakant.patel@broadcom.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.h b/drivers/staging/mt29f_spinand/mt29f_spinand.h
new file mode 100644
index 0000000..7f2c24d
--- /dev/null
+++ b/drivers/staging/mt29f_spinand/mt29f_spinand.h
@@ -0,0 +1,107 @@
+/*-
+ * Copyright 2013 Broadcom Corporation
+ *
+ * Copyright (c) 2009-2010 Micron Technology, 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.
+ *
+ * Henry Pan <hspan@micron.com>
+ *
+ * based on nand.h
+ */
+#ifndef __LINUX_MTD_SPI_NAND_H
+#define __LINUX_MTD_SPI_NAND_H
+
+#include <linux/wait.h>
+#include <linux/spinlock.h>
+#include <linux/mtd/mtd.h>
+
+/* cmd */
+#define CMD_READ			0x13
+#define CMD_READ_RDM			0x03
+#define CMD_PROG_PAGE_CLRCACHE		0x02
+#define CMD_PROG_PAGE			0x84
+#define CMD_PROG_PAGE_EXC		0x10
+#define CMD_ERASE_BLK			0xd8
+#define CMD_WR_ENABLE			0x06
+#define CMD_WR_DISABLE			0x04
+#define CMD_READ_ID			0x9f
+#define CMD_RESET			0xff
+#define CMD_READ_REG			0x0f
+#define CMD_WRITE_REG			0x1f
+
+/* feature/ status reg */
+#define REG_BLOCK_LOCK			0xa0
+#define REG_OTP				0xb0
+#define REG_STATUS			0xc0/* timing */
+
+/* status */
+#define STATUS_OIP_MASK			0x01
+#define STATUS_READY			(0 << 0)
+#define STATUS_BUSY			(1 << 0)
+
+#define STATUS_E_FAIL_MASK		0x04
+#define STATUS_E_FAIL			(1 << 2)
+
+#define STATUS_P_FAIL_MASK		0x08
+#define STATUS_P_FAIL			(1 << 3)
+
+#define STATUS_ECC_MASK			0x30
+#define STATUS_ECC_1BIT_CORRECTED	(1 << 4)
+#define STATUS_ECC_ERROR		(2 << 4)
+#define STATUS_ECC_RESERVED		(3 << 4)
+
+/*ECC enable defines*/
+#define OTP_ECC_MASK			0x10
+#define OTP_ECC_OFF			0
+#define OTP_ECC_ON			1
+
+#define ECC_DISABLED
+#define ECC_IN_NAND
+#define ECC_SOFT
+
+/* block lock */
+#define BL_ALL_LOCKED      0x38
+#define BL_1_2_LOCKED      0x30
+#define BL_1_4_LOCKED      0x28
+#define BL_1_8_LOCKED      0x20
+#define BL_1_16_LOCKED     0x18
+#define BL_1_32_LOCKED     0x10
+#define BL_1_64_LOCKED     0x08
+#define BL_ALL_UNLOCKED    0
+
+struct spinand_info {
+	struct nand_ecclayout *ecclayout;
+	struct spi_device *spi;
+	void *priv;
+};
+
+struct spinand_state {
+	uint32_t	col;
+	uint32_t	row;
+	int		buf_ptr;
+	u8		*buf;
+};
+
+struct spinand_cmd {
+	u8		cmd;
+	u32		n_addr;		/* Number of address */
+	u8		addr[3];	/* Reg Offset */
+	u32		n_dummy;	/* Dummy use */
+	u32		n_tx;		/* Number of tx bytes */
+	u8		*tx_buf;	/* Tx buf */
+	u32		n_rx;		/* Number of rx bytes */
+	u8		*rx_buf;	/* Rx buf */
+};
+
+extern int spinand_mtd(struct mtd_info *mtd);
+extern void spinand_mtd_release(struct mtd_info *mtd);
+
+#endif /* __LINUX_MTD_SPI_NAND_H */
diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c
index 46eabd0..235d2b1 100644
--- a/drivers/staging/netlogic/xlr_net.c
+++ b/drivers/staging/netlogic/xlr_net.c
@@ -44,8 +44,8 @@
 #include <linux/platform_device.h>
 
 #include <asm/mipsregs.h>
-
-/* fmn.h - For FMN credit configuration and registering fmn_handler.
+/*
+ * fmn.h - For FMN credit configuration and registering fmn_handler.
  * FMN is communication mechanism that allows processing agents within
  * XLR/XLS to communicate each other.
  */
@@ -90,7 +90,8 @@
 {
 	struct sk_buff **back_ptr;
 
-	/* this function should be used only for newly allocated packets.
+	/*
+	 * this function should be used only for newly allocated packets.
 	 * It assumes the first cacheline is for the back pointer related
 	 * book keeping info.
 	 */
@@ -102,7 +103,8 @@
 {
 	struct sk_buff **back_ptr = (struct sk_buff **)skb->data;
 
-	/* this function should be used only for newly allocated packets.
+	/*
+	 * this function should be used only for newly allocated packets.
 	 * It assumes the first cacheline is for the back pointer related
 	 * book keeping info.
 	 */
@@ -500,8 +502,10 @@
 			sizeof(u64));
 }
 
-/* Configure PDE to Round-Robin distribution of packets to the
- * available cpu */
+/*
+ * Configure PDE to Round-Robin distribution of packets to the
+ * available cpu
+ */
 static void xlr_config_pde(struct xlr_net_priv *priv)
 {
 	int i = 0;
@@ -528,8 +532,10 @@
 			((bkt_map >> 32) & 0xffffffff));
 }
 
-/* Setup the Message ring credits, bucket size and other
- * common configuration */
+/*
+ * Setup the Message ring credits, bucket size and other
+ * common configuration
+ */
 static void xlr_config_common(struct xlr_net_priv *priv)
 {
 	struct xlr_fmn_info *gmac = priv->nd->gmac_fmn_info;
@@ -545,8 +551,10 @@
 				bucket_size[i]);
 	}
 
-	/* Setting non-core Credit counter register
-	 * Distributing Gmac's credit to CPU's*/
+	/*
+	 * Setting non-core Credit counter register
+	 * Distributing Gmac's credit to CPU's
+	 */
 	for (i = 0; i < 8; i++) {
 		for (j = 0; j < 8; j++)
 			xlr_nae_wreg(priv->base_addr,
@@ -593,7 +601,8 @@
 	c1 = 3;
 	c2 = 0;
 	for (i = 0; i < 64; i++) {
-		/* On use_bkt set the b0, b1 are used, else
+		/*
+		 * On use_bkt set the b0, b1 are used, else
 		 * the 4 classes are used, here implemented
 		 * a logic to distribute the packets to the
 		 * buckets equally or based on the class
@@ -736,7 +745,8 @@
 	return ret;
 }
 
-/* XLR ports are RGMII. XLS ports are SGMII mostly except the port0,
+/*
+ * XLR ports are RGMII. XLS ports are SGMII mostly except the port0,
  * which can be configured either SGMII or RGMII, considered SGMII
  * by default, if board setup to RGMII the port_type need to set
  * accordingly.Serdes and PCS layer need to configured for SGMII
diff --git a/drivers/staging/netlogic/xlr_net.h b/drivers/staging/netlogic/xlr_net.h
index f91d27e..cea7966 100644
--- a/drivers/staging/netlogic/xlr_net.h
+++ b/drivers/staging/netlogic/xlr_net.h
@@ -1096,4 +1096,4 @@
 	u64 *class_3_spill;
 };
 
-extern void xlr_set_gmac_speed(struct xlr_net_priv *priv);
+void xlr_set_gmac_speed(struct xlr_net_priv *priv);
diff --git a/drivers/staging/nvec/Kconfig b/drivers/staging/nvec/Kconfig
index 7e61ada..9475e20 100644
--- a/drivers/staging/nvec/Kconfig
+++ b/drivers/staging/nvec/Kconfig
@@ -10,7 +10,7 @@
 	tristate "Keyboard on nVidia compliant EC"
 	depends on MFD_NVEC && INPUT
 	help
-	  Say Y here to enable support for a keyboard connected to 
+	  Say Y here to enable support for a keyboard connected to
 	  a nVidia compliant embedded controller.
 
 config SERIO_NVEC_PS2
diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
index 5a5c639..3066ee2 100644
--- a/drivers/staging/nvec/nvec.c
+++ b/drivers/staging/nvec/nvec.c
@@ -802,7 +802,7 @@
 		unmute_speakers[] = { NVEC_OEM0, 0x10, 0x59, 0x95 },
 		enable_event[7] = { NVEC_SYS, CNF_EVENT_REPORTING, true };
 
-	if(!pdev->dev.of_node) {
+	if (!pdev->dev.of_node) {
 		dev_err(&pdev->dev, "must be instantiated using device tree\n");
 		return -ENODEV;
 	}
diff --git a/drivers/staging/octeon-usb/Makefile b/drivers/staging/octeon-usb/Makefile
index 89df1ad..5588be3 100644
--- a/drivers/staging/octeon-usb/Makefile
+++ b/drivers/staging/octeon-usb/Makefile
@@ -1,3 +1 @@
-obj-${CONFIG_OCTEON_USB} := octeon-usb.o
-octeon-usb-y := octeon-hcd.o
-octeon-usb-y += cvmx-usb.o
+obj-${CONFIG_OCTEON_USB} := octeon-hcd.o
diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c
deleted file mode 100644
index 45dfe94..0000000
--- a/drivers/staging/octeon-usb/cvmx-usb.c
+++ /dev/null
@@ -1,3158 +0,0 @@
-/***********************license start***************
- * Copyright (c) 2003-2010  Cavium Networks (support@cavium.com). All rights
- * reserved.
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *   * Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *
- *   * Redistributions in binary form must reproduce the above
- *     copyright notice, this list of conditions and the following
- *     disclaimer in the documentation and/or other materials provided
- *     with the distribution.
-
- *   * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export  control
- * laws, including the U.S. Export Administration Act and its  associated
- * regulations, and may be subject to export or import  regulations in other
- * countries.
-
- * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM  NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
- * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
- * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
- * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
- * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
- * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
- * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
- * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK ARISING OUT OF USE OR
- * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
- ***********************license end**************************************/
-
-
-/**
- * @file
- *
- * "cvmx-usb.c" defines a set of low level USB functions to help
- * developers create Octeon USB drivers for various operating
- * systems. These functions provide a generic API to the Octeon
- * USB blocks, hiding the internal hardware specific
- * operations.
- */
-#include <linux/delay.h>
-#include <asm/octeon/cvmx.h>
-#include <asm/octeon/octeon.h>
-#include <asm/octeon/cvmx-sysinfo.h>
-#include "cvmx-usbnx-defs.h"
-#include "cvmx-usbcx-defs.h"
-#include "cvmx-usb.h"
-#include <asm/octeon/cvmx-helper.h>
-#include <asm/octeon/cvmx-helper-board.h>
-
-#define CVMX_PREFETCH0(address) CVMX_PREFETCH(address, 0)
-#define CVMX_PREFETCH128(address) CVMX_PREFETCH(address, 128)
-// a normal prefetch
-#define CVMX_PREFETCH(address, offset) CVMX_PREFETCH_PREF0(address, offset)
-// normal prefetches that use the pref instruction
-#define CVMX_PREFETCH_PREFX(X, address, offset) asm volatile ("pref %[type], %[off](%[rbase])" : : [rbase] "d" (address), [off] "I" (offset), [type] "n" (X))
-#define CVMX_PREFETCH_PREF0(address, offset) CVMX_PREFETCH_PREFX(0, address, offset)
-#define CVMX_CLZ(result, input) asm ("clz %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input))
-
-#define MAX_RETRIES		3		/* Maximum number of times to retry failed transactions */
-#define MAX_PIPES		32		/* Maximum number of pipes that can be open at once */
-#define MAX_TRANSACTIONS	256		/* Maximum number of outstanding transactions across all pipes */
-#define MAX_CHANNELS		8		/* Maximum number of hardware channels supported by the USB block */
-#define MAX_USB_ADDRESS		127		/* The highest valid USB device address */
-#define MAX_USB_ENDPOINT	15		/* The highest valid USB endpoint number */
-#define MAX_USB_HUB_PORT	15		/* The highest valid port number on a hub */
-#define MAX_TRANSFER_BYTES	((1<<19)-1)	/* The low level hardware can transfer a maximum of this number of bytes in each transfer. The field is 19 bits wide */
-#define MAX_TRANSFER_PACKETS	((1<<10)-1)	/* The low level hardware can transfer a maximum of this number of packets in each transfer. The field is 10 bits wide */
-
-/*
- * These defines disable the normal read and write csr. This is so I can add
- * extra debug stuff to the usb specific version and I won't use the normal
- * version by mistake
- */
-#define cvmx_read_csr use_cvmx_usb_read_csr64_instead_of_cvmx_read_csr
-#define cvmx_write_csr use_cvmx_usb_write_csr64_instead_of_cvmx_write_csr
-
-enum cvmx_usb_transaction_flags {
-	__CVMX_USB_TRANSACTION_FLAGS_IN_USE = 1<<16,
-};
-
-enum {
-	USB_CLOCK_TYPE_REF_12,
-	USB_CLOCK_TYPE_REF_24,
-	USB_CLOCK_TYPE_REF_48,
-	USB_CLOCK_TYPE_CRYSTAL_12,
-};
-
-/**
- * Logical transactions may take numerous low level
- * transactions, especially when splits are concerned. This
- * enum represents all of the possible stages a transaction can
- * be in. Note that split completes are always even. This is so
- * the NAK handler can backup to the previous low level
- * transaction with a simple clearing of bit 0.
- */
-enum cvmx_usb_stage {
-	CVMX_USB_STAGE_NON_CONTROL,
-	CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE,
-	CVMX_USB_STAGE_SETUP,
-	CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE,
-	CVMX_USB_STAGE_DATA,
-	CVMX_USB_STAGE_DATA_SPLIT_COMPLETE,
-	CVMX_USB_STAGE_STATUS,
-	CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE,
-};
-
-/**
- * struct cvmx_usb_transaction - describes each pending USB transaction
- *				 regardless of type. These are linked together
- *				 to form a list of pending requests for a pipe.
- *
- * @prev:		Transaction before this one in the pipe.
- * @next:		Transaction after this one in the pipe.
- * @type:		Type of transaction, duplicated of the pipe.
- * @flags:		State flags for this transaction.
- * @buffer:		User's physical buffer address to read/write.
- * @buffer_length:	Size of the user's buffer in bytes.
- * @control_header:	For control transactions, physical address of the 8
- *			byte standard header.
- * @iso_start_frame:	For ISO transactions, the starting frame number.
- * @iso_number_packets:	For ISO transactions, the number of packets in the
- *			request.
- * @iso_packets:	For ISO transactions, the sub packets in the request.
- * @actual_bytes:	Actual bytes transfer for this transaction.
- * @stage:		For control transactions, the current stage.
- * @callback:		User's callback function when complete.
- * @callback_data:	User's data.
- */
-struct cvmx_usb_transaction {
-	struct cvmx_usb_transaction *prev;
-	struct cvmx_usb_transaction *next;
-	enum cvmx_usb_transfer type;
-	enum cvmx_usb_transaction_flags flags;
-	uint64_t buffer;
-	int buffer_length;
-	uint64_t control_header;
-	int iso_start_frame;
-	int iso_number_packets;
-	struct cvmx_usb_iso_packet *iso_packets;
-	int xfersize;
-	int pktcnt;
-	int retries;
-	int actual_bytes;
-	enum cvmx_usb_stage stage;
-	cvmx_usb_callback_func_t callback;
-	void *callback_data;
-};
-
-/**
- * struct cvmx_usb_pipe - a pipe represents a virtual connection between Octeon
- *			  and some USB device. It contains a list of pending
- *			  request to the device.
- *
- * @prev:		Pipe before this one in the list
- * @next:		Pipe after this one in the list
- * @head:		The first pending transaction
- * @tail:		The last pending transaction
- * @interval:		For periodic pipes, the interval between packets in
- *			frames
- * @next_tx_frame:	The next frame this pipe is allowed to transmit on
- * @flags:		State flags for this pipe
- * @device_speed:	Speed of device connected to this pipe
- * @transfer_type:	Type of transaction supported by this pipe
- * @transfer_dir:	IN or OUT. Ignored for Control
- * @multi_count:	Max packet in a row for the device
- * @max_packet:		The device's maximum packet size in bytes
- * @device_addr:	USB device address at other end of pipe
- * @endpoint_num:	USB endpoint number at other end of pipe
- * @hub_device_addr:	Hub address this device is connected to
- * @hub_port:		Hub port this device is connected to
- * @pid_toggle:		This toggles between 0/1 on every packet send to track
- *			the data pid needed
- * @channel:		Hardware DMA channel for this pipe
- * @split_sc_frame:	The low order bits of the frame number the split
- *			complete should be sent on
- */
-struct cvmx_usb_pipe {
-	struct cvmx_usb_pipe *prev;
-	struct cvmx_usb_pipe *next;
-	struct cvmx_usb_transaction *head;
-	struct cvmx_usb_transaction *tail;
-	uint64_t interval;
-	uint64_t next_tx_frame;
-	enum cvmx_usb_pipe_flags flags;
-	enum cvmx_usb_speed device_speed;
-	enum cvmx_usb_transfer transfer_type;
-	enum cvmx_usb_direction transfer_dir;
-	int multi_count;
-	uint16_t max_packet;
-	uint8_t device_addr;
-	uint8_t endpoint_num;
-	uint8_t hub_device_addr;
-	uint8_t hub_port;
-	uint8_t pid_toggle;
-	uint8_t channel;
-	int8_t split_sc_frame;
-};
-
-/**
- * struct cvmx_usb_pipe_list
- *
- * @head: Head of the list, or NULL if empty.
- * @tail: Tail if the list, or NULL if empty.
- */
-struct cvmx_usb_pipe_list {
-	struct cvmx_usb_pipe *head;
-	struct cvmx_usb_pipe *tail;
-};
-
-struct cvmx_usb_tx_fifo {
-	struct {
-		int channel;
-		int size;
-		uint64_t address;
-	} entry[MAX_CHANNELS+1];
-	int head;
-	int tail;
-};
-
-/**
- * struct cvmx_usb_internal_state - the state of the USB block
- *
- * init_flags:		   Flags passed to initialize.
- * index:		   Which USB block this is for.
- * idle_hardware_channels: Bit set for every idle hardware channel.
- * usbcx_hprt:		   Stored port status so we don't need to read a CSR to
- *			   determine splits.
- * pipe_for_channel:	   Map channels to pipes.
- * free_transaction_head:  List of free transactions head.
- * free_transaction_tail:  List of free transactions tail.
- * pipe:		   Storage for pipes.
- * transaction:		   Storage for transactions.
- * callback:		   User global callbacks.
- * callback_data:	   User data for each callback.
- * indent:		   Used by debug output to indent functions.
- * port_status:		   Last port status used for change notification.
- * free_pipes:		   List of all pipes that are currently closed.
- * idle_pipes:		   List of open pipes that have no transactions.
- * active_pipes:	   Active pipes indexed by transfer type.
- * frame_number:	   Increments every SOF interrupt for time keeping.
- * active_split:	   Points to the current active split, or NULL.
- */
-struct cvmx_usb_internal_state {
-	int init_flags;
-	int index;
-	int idle_hardware_channels;
-	union cvmx_usbcx_hprt usbcx_hprt;
-	struct cvmx_usb_pipe *pipe_for_channel[MAX_CHANNELS];
-	struct cvmx_usb_transaction *free_transaction_head;
-	struct cvmx_usb_transaction *free_transaction_tail;
-	struct cvmx_usb_pipe pipe[MAX_PIPES];
-	struct cvmx_usb_transaction transaction[MAX_TRANSACTIONS];
-	cvmx_usb_callback_func_t callback[__CVMX_USB_CALLBACK_END];
-	void *callback_data[__CVMX_USB_CALLBACK_END];
-	int indent;
-	struct cvmx_usb_port_status port_status;
-	struct cvmx_usb_pipe_list free_pipes;
-	struct cvmx_usb_pipe_list idle_pipes;
-	struct cvmx_usb_pipe_list active_pipes[4];
-	uint64_t frame_number;
-	struct cvmx_usb_transaction *active_split;
-	struct cvmx_usb_tx_fifo periodic;
-	struct cvmx_usb_tx_fifo nonperiodic;
-};
-
-/* This macro spins on a field waiting for it to reach a value */
-#define CVMX_WAIT_FOR_FIELD32(address, type, field, op, value, timeout_usec)\
-	({int result;							    \
-	do {								    \
-		uint64_t done = cvmx_get_cycle() + (uint64_t)timeout_usec * \
-			octeon_get_clock_rate() / 1000000;		    \
-		type c;							    \
-		while (1) {						    \
-			c.u32 = __cvmx_usb_read_csr32(usb, address);	    \
-			if (c.s.field op (value)) {			    \
-				result = 0;				    \
-				break;					    \
-			} else if (cvmx_get_cycle() > done) {		    \
-				result = -1;				    \
-				break;					    \
-			} else						    \
-				cvmx_wait(100);				    \
-		}							    \
-	} while (0);							    \
-	result; })
-
-/*
- * This macro logically sets a single field in a CSR. It does the sequence
- * read, modify, and write
- */
-#define USB_SET_FIELD32(address, type, field, value)		\
-	do {							\
-		type c;						\
-		c.u32 = __cvmx_usb_read_csr32(usb, address);	\
-		c.s.field = value;				\
-		__cvmx_usb_write_csr32(usb, address, c.u32);	\
-	} while (0)
-
-/* Returns the IO address to push/pop stuff data from the FIFOs */
-#define USB_FIFO_ADDRESS(channel, usb_index) (CVMX_USBCX_GOTGCTL(usb_index) + ((channel)+1)*0x1000)
-
-static int octeon_usb_get_clock_type(void)
-{
-	switch (cvmx_sysinfo_get()->board_type) {
-	case CVMX_BOARD_TYPE_BBGW_REF:
-	case CVMX_BOARD_TYPE_LANAI2_A:
-	case CVMX_BOARD_TYPE_LANAI2_U:
-	case CVMX_BOARD_TYPE_LANAI2_G:
-	case CVMX_BOARD_TYPE_UBNT_E100:
-		return USB_CLOCK_TYPE_CRYSTAL_12;
-	}
-	return USB_CLOCK_TYPE_REF_48;
-}
-
-/**
- * Read a USB 32bit CSR. It performs the necessary address swizzle
- * for 32bit CSRs and logs the value in a readable format if
- * debugging is on.
- *
- * @usb:     USB block this access is for
- * @address: 64bit address to read
- *
- * Returns: Result of the read
- */
-static inline uint32_t __cvmx_usb_read_csr32(struct cvmx_usb_internal_state *usb,
-					     uint64_t address)
-{
-	uint32_t result = cvmx_read64_uint32(address ^ 4);
-	return result;
-}
-
-
-/**
- * Write a USB 32bit CSR. It performs the necessary address
- * swizzle for 32bit CSRs and logs the value in a readable format
- * if debugging is on.
- *
- * @usb:     USB block this access is for
- * @address: 64bit address to write
- * @value:   Value to write
- */
-static inline void __cvmx_usb_write_csr32(struct cvmx_usb_internal_state *usb,
-					  uint64_t address, uint32_t value)
-{
-	cvmx_write64_uint32(address ^ 4, value);
-	cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index));
-}
-
-
-/**
- * Read a USB 64bit CSR. It logs the value in a readable format if
- * debugging is on.
- *
- * @usb:     USB block this access is for
- * @address: 64bit address to read
- *
- * Returns: Result of the read
- */
-static inline uint64_t __cvmx_usb_read_csr64(struct cvmx_usb_internal_state *usb,
-					     uint64_t address)
-{
-	uint64_t result = cvmx_read64_uint64(address);
-	return result;
-}
-
-
-/**
- * Write a USB 64bit CSR. It logs the value in a readable format
- * if debugging is on.
- *
- * @usb:     USB block this access is for
- * @address: 64bit address to write
- * @value:   Value to write
- */
-static inline void __cvmx_usb_write_csr64(struct cvmx_usb_internal_state *usb,
-					  uint64_t address, uint64_t value)
-{
-	cvmx_write64_uint64(address, value);
-}
-
-/**
- * Return non zero if this pipe connects to a non HIGH speed
- * device through a high speed hub.
- *
- * @usb:    USB block this access is for
- * @pipe:   Pipe to check
- *
- * Returns: Non zero if we need to do split transactions
- */
-static inline int __cvmx_usb_pipe_needs_split(struct cvmx_usb_internal_state *usb, struct cvmx_usb_pipe *pipe)
-{
-	return ((pipe->device_speed != CVMX_USB_SPEED_HIGH) && (usb->usbcx_hprt.s.prtspd == CVMX_USB_SPEED_HIGH));
-}
-
-
-/**
- * Trivial utility function to return the correct PID for a pipe
- *
- * @pipe:   pipe to check
- *
- * Returns: PID for pipe
- */
-static inline int __cvmx_usb_get_data_pid(struct cvmx_usb_pipe *pipe)
-{
-	if (pipe->pid_toggle)
-		return 2; /* Data1 */
-	else
-		return 0; /* Data0 */
-}
-
-
-/**
- * Return the number of USB ports supported by this Octeon
- * chip. If the chip doesn't support USB, or is not supported
- * by this API, a zero will be returned. Most Octeon chips
- * support one usb port, but some support two ports.
- * cvmx_usb_initialize() must be called on independent
- * struct cvmx_usb_state.
- *
- * Returns: Number of port, zero if usb isn't supported
- */
-int cvmx_usb_get_num_ports(void)
-{
-	int arch_ports = 0;
-
-	if (OCTEON_IS_MODEL(OCTEON_CN56XX))
-		arch_ports = 1;
-	else if (OCTEON_IS_MODEL(OCTEON_CN52XX))
-		arch_ports = 2;
-	else if (OCTEON_IS_MODEL(OCTEON_CN50XX))
-		arch_ports = 1;
-	else if (OCTEON_IS_MODEL(OCTEON_CN31XX))
-		arch_ports = 1;
-	else if (OCTEON_IS_MODEL(OCTEON_CN30XX))
-		arch_ports = 1;
-	else
-		arch_ports = 0;
-
-	return arch_ports;
-}
-
-
-/**
- * Allocate a usb transaction for use
- *
- * @usb:	 USB device state populated by
- *		 cvmx_usb_initialize().
- *
- * Returns: Transaction or NULL
- */
-static inline struct cvmx_usb_transaction *__cvmx_usb_alloc_transaction(struct cvmx_usb_internal_state *usb)
-{
-	struct cvmx_usb_transaction *t;
-	t = usb->free_transaction_head;
-	if (t) {
-		usb->free_transaction_head = t->next;
-		if (!usb->free_transaction_head)
-			usb->free_transaction_tail = NULL;
-	}
-	if (t) {
-		memset(t, 0, sizeof(*t));
-		t->flags = __CVMX_USB_TRANSACTION_FLAGS_IN_USE;
-	}
-	return t;
-}
-
-
-/**
- * Free a usb transaction
- *
- * @usb:	 USB device state populated by
- *		 cvmx_usb_initialize().
- * @transaction:
- *		 Transaction to free
- */
-static inline void __cvmx_usb_free_transaction(struct cvmx_usb_internal_state *usb,
-					       struct cvmx_usb_transaction *transaction)
-{
-	transaction->flags = 0;
-	transaction->prev = NULL;
-	transaction->next = NULL;
-	if (usb->free_transaction_tail)
-		usb->free_transaction_tail->next = transaction;
-	else
-		usb->free_transaction_head = transaction;
-	usb->free_transaction_tail = transaction;
-}
-
-
-/**
- * Add a pipe to the tail of a list
- * @list:   List to add pipe to
- * @pipe:   Pipe to add
- */
-static inline void __cvmx_usb_append_pipe(struct cvmx_usb_pipe_list *list, struct cvmx_usb_pipe *pipe)
-{
-	pipe->next = NULL;
-	pipe->prev = list->tail;
-	if (list->tail)
-		list->tail->next = pipe;
-	else
-		list->head = pipe;
-	list->tail = pipe;
-}
-
-
-/**
- * Remove a pipe from a list
- * @list:   List to remove pipe from
- * @pipe:   Pipe to remove
- */
-static inline void __cvmx_usb_remove_pipe(struct cvmx_usb_pipe_list *list, struct cvmx_usb_pipe *pipe)
-{
-	if (list->head == pipe) {
-		list->head = pipe->next;
-		pipe->next = NULL;
-		if (list->head)
-			list->head->prev = NULL;
-		else
-			list->tail = NULL;
-	} else if (list->tail == pipe) {
-		list->tail = pipe->prev;
-		list->tail->next = NULL;
-		pipe->prev = NULL;
-	} else {
-		pipe->prev->next = pipe->next;
-		pipe->next->prev = pipe->prev;
-		pipe->prev = NULL;
-		pipe->next = NULL;
-	}
-}
-
-
-/**
- * Initialize a USB port for use. This must be called before any
- * other access to the Octeon USB port is made. The port starts
- * off in the disabled state.
- *
- * @state:	 Pointer to an empty struct cvmx_usb_state
- *		 that will be populated by the initialize call.
- *		 This structure is then passed to all other USB
- *		 functions.
- * @usb_port_number:
- *		 Which Octeon USB port to initialize.
- * @flags:	 Flags to control hardware initialization. See
- *		 enum cvmx_usb_initialize_flags for the flag
- *		 definitions. Some flags are mandatory.
- *
- * Returns: 0 or a negative error code.
- */
-int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number,
-			enum cvmx_usb_initialize_flags flags)
-{
-	union cvmx_usbnx_clk_ctl usbn_clk_ctl;
-	union cvmx_usbnx_usbp_ctl_status usbn_usbp_ctl_status;
-	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
-
-	usb->init_flags = flags;
-
-	/* Make sure that state is large enough to store the internal state */
-	if (sizeof(*state) < sizeof(*usb))
-		return -EINVAL;
-	/* At first allow 0-1 for the usb port number */
-	if ((usb_port_number < 0) || (usb_port_number > 1))
-		return -EINVAL;
-	/* For all chips except 52XX there is only one port */
-	if (!OCTEON_IS_MODEL(OCTEON_CN52XX) && (usb_port_number > 0))
-		return -EINVAL;
-	/* Try to determine clock type automatically */
-	if ((flags & (CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI |
-		      CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND)) == 0) {
-		if (octeon_usb_get_clock_type() == USB_CLOCK_TYPE_CRYSTAL_12)
-			flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI;  /* Only 12 MHZ crystals are supported */
-		else
-			flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND;
-	}
-
-	if (flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND) {
-		/* Check for auto ref clock frequency */
-		if (!(flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK))
-			switch (octeon_usb_get_clock_type()) {
-			case USB_CLOCK_TYPE_REF_12:
-				flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ;
-				break;
-			case USB_CLOCK_TYPE_REF_24:
-				flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ;
-				break;
-			case USB_CLOCK_TYPE_REF_48:
-				flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ;
-				break;
-			default:
-				return -EINVAL;
-				break;
-			}
-	}
-
-	memset(usb, 0, sizeof(*usb));
-	usb->init_flags = flags;
-
-	/* Initialize the USB state structure */
-	{
-		int i;
-		usb->index = usb_port_number;
-
-		/* Initialize the transaction double linked list */
-		usb->free_transaction_head = NULL;
-		usb->free_transaction_tail = NULL;
-		for (i = 0; i < MAX_TRANSACTIONS; i++)
-			__cvmx_usb_free_transaction(usb, usb->transaction + i);
-		for (i = 0; i < MAX_PIPES; i++)
-			__cvmx_usb_append_pipe(&usb->free_pipes, usb->pipe + i);
-	}
-
-	/*
-	 * Power On Reset and PHY Initialization
-	 *
-	 * 1. Wait for DCOK to assert (nothing to do)
-	 *
-	 * 2a. Write USBN0/1_CLK_CTL[POR] = 1 and
-	 *     USBN0/1_CLK_CTL[HRST,PRST,HCLK_RST] = 0
-	 */
-	usbn_clk_ctl.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index));
-	usbn_clk_ctl.s.por = 1;
-	usbn_clk_ctl.s.hrst = 0;
-	usbn_clk_ctl.s.prst = 0;
-	usbn_clk_ctl.s.hclk_rst = 0;
-	usbn_clk_ctl.s.enable = 0;
-	/*
-	 * 2b. Select the USB reference clock/crystal parameters by writing
-	 *     appropriate values to USBN0/1_CLK_CTL[P_C_SEL, P_RTYPE, P_COM_ON]
-	 */
-	if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND) {
-		/*
-		 * The USB port uses 12/24/48MHz 2.5V board clock
-		 * source at USB_XO. USB_XI should be tied to GND.
-		 * Most Octeon evaluation boards require this setting
-		 */
-		if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) {
-			usbn_clk_ctl.cn31xx.p_rclk  = 1; /* From CN31XX,CN30XX manual */
-			usbn_clk_ctl.cn31xx.p_xenbn = 0;
-		} else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN50XX))
-			usbn_clk_ctl.cn56xx.p_rtype = 2; /* From CN56XX,CN50XX manual */
-		else
-			usbn_clk_ctl.cn52xx.p_rtype = 1; /* From CN52XX manual */
-
-		switch (flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK) {
-		case CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ:
-			usbn_clk_ctl.s.p_c_sel = 0;
-			break;
-		case CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ:
-			usbn_clk_ctl.s.p_c_sel = 1;
-			break;
-		case CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ:
-			usbn_clk_ctl.s.p_c_sel = 2;
-			break;
-		}
-	} else {
-		/*
-		 * The USB port uses a 12MHz crystal as clock source
-		 * at USB_XO and USB_XI
-		 */
-		if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) {
-			usbn_clk_ctl.cn31xx.p_rclk  = 1; /* From CN31XX,CN30XX manual */
-			usbn_clk_ctl.cn31xx.p_xenbn = 1;
-		} else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN50XX))
-			usbn_clk_ctl.cn56xx.p_rtype = 0; /* From CN56XX,CN50XX manual */
-		else
-			usbn_clk_ctl.cn52xx.p_rtype = 0; /* From CN52XX manual */
-
-		usbn_clk_ctl.s.p_c_sel = 0;
-	}
-	/*
-	 * 2c. Select the HCLK via writing USBN0/1_CLK_CTL[DIVIDE, DIVIDE2] and
-	 *     setting USBN0/1_CLK_CTL[ENABLE] = 1. Divide the core clock down
-	 *     such that USB is as close as possible to 125Mhz
-	 */
-	{
-		int divisor = (octeon_get_clock_rate()+125000000-1)/125000000;
-		if (divisor < 4)  /* Lower than 4 doesn't seem to work properly */
-			divisor = 4;
-		usbn_clk_ctl.s.divide = divisor;
-		usbn_clk_ctl.s.divide2 = 0;
-	}
-	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-			       usbn_clk_ctl.u64);
-	/* 2d. Write USBN0/1_CLK_CTL[HCLK_RST] = 1 */
-	usbn_clk_ctl.s.hclk_rst = 1;
-	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-			       usbn_clk_ctl.u64);
-	/* 2e.  Wait 64 core-clock cycles for HCLK to stabilize */
-	cvmx_wait(64);
-	/*
-	 * 3. Program the power-on reset field in the USBN clock-control
-	 *    register:
-	 *    USBN_CLK_CTL[POR] = 0
-	 */
-	usbn_clk_ctl.s.por = 0;
-	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-			       usbn_clk_ctl.u64);
-	/* 4. Wait 1 ms for PHY clock to start */
-	mdelay(1);
-	/*
-	 * 5. Program the Reset input from automatic test equipment field in the
-	 *    USBP control and status register:
-	 *    USBN_USBP_CTL_STATUS[ATE_RESET] = 1
-	 */
-	usbn_usbp_ctl_status.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index));
-	usbn_usbp_ctl_status.s.ate_reset = 1;
-	__cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index),
-			       usbn_usbp_ctl_status.u64);
-	/* 6. Wait 10 cycles */
-	cvmx_wait(10);
-	/*
-	 * 7. Clear ATE_RESET field in the USBN clock-control register:
-	 *    USBN_USBP_CTL_STATUS[ATE_RESET] = 0
-	 */
-	usbn_usbp_ctl_status.s.ate_reset = 0;
-	__cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index),
-			       usbn_usbp_ctl_status.u64);
-	/*
-	 * 8. Program the PHY reset field in the USBN clock-control register:
-	 *    USBN_CLK_CTL[PRST] = 1
-	 */
-	usbn_clk_ctl.s.prst = 1;
-	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-			       usbn_clk_ctl.u64);
-	/*
-	 * 9. Program the USBP control and status register to select host or
-	 *    device mode. USBN_USBP_CTL_STATUS[HST_MODE] = 0 for host, = 1 for
-	 *    device
-	 */
-	usbn_usbp_ctl_status.s.hst_mode = 0;
-	__cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index),
-			       usbn_usbp_ctl_status.u64);
-	/* 10. Wait 1 us */
-	udelay(1);
-	/*
-	 * 11. Program the hreset_n field in the USBN clock-control register:
-	 *     USBN_CLK_CTL[HRST] = 1
-	 */
-	usbn_clk_ctl.s.hrst = 1;
-	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-			       usbn_clk_ctl.u64);
-	/* 12. Proceed to USB core initialization */
-	usbn_clk_ctl.s.enable = 1;
-	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-			       usbn_clk_ctl.u64);
-	udelay(1);
-
-	/*
-	 * USB Core Initialization
-	 *
-	 * 1. Read USBC_GHWCFG1, USBC_GHWCFG2, USBC_GHWCFG3, USBC_GHWCFG4 to
-	 *    determine USB core configuration parameters.
-	 *
-	 *    Nothing needed
-	 *
-	 * 2. Program the following fields in the global AHB configuration
-	 *    register (USBC_GAHBCFG)
-	 *    DMA mode, USBC_GAHBCFG[DMAEn]: 1 = DMA mode, 0 = slave mode
-	 *    Burst length, USBC_GAHBCFG[HBSTLEN] = 0
-	 *    Nonperiodic TxFIFO empty level (slave mode only),
-	 *    USBC_GAHBCFG[NPTXFEMPLVL]
-	 *    Periodic TxFIFO empty level (slave mode only),
-	 *    USBC_GAHBCFG[PTXFEMPLVL]
-	 *    Global interrupt mask, USBC_GAHBCFG[GLBLINTRMSK] = 1
-	 */
-	{
-		union cvmx_usbcx_gahbcfg usbcx_gahbcfg;
-		/* Due to an errata, CN31XX doesn't support DMA */
-		if (OCTEON_IS_MODEL(OCTEON_CN31XX))
-			usb->init_flags |= CVMX_USB_INITIALIZE_FLAGS_NO_DMA;
-		usbcx_gahbcfg.u32 = 0;
-		usbcx_gahbcfg.s.dmaen = !(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA);
-		if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
-			usb->idle_hardware_channels = 0x1;  /* Only use one channel with non DMA */
-		else if (OCTEON_IS_MODEL(OCTEON_CN5XXX))
-			usb->idle_hardware_channels = 0xf7; /* CN5XXX have an errata with channel 3 */
-		else
-			usb->idle_hardware_channels = 0xff;
-		usbcx_gahbcfg.s.hbstlen = 0;
-		usbcx_gahbcfg.s.nptxfemplvl = 1;
-		usbcx_gahbcfg.s.ptxfemplvl = 1;
-		usbcx_gahbcfg.s.glblintrmsk = 1;
-		__cvmx_usb_write_csr32(usb, CVMX_USBCX_GAHBCFG(usb->index),
-				       usbcx_gahbcfg.u32);
-	}
-	/*
-	 * 3. Program the following fields in USBC_GUSBCFG register.
-	 *    HS/FS timeout calibration, USBC_GUSBCFG[TOUTCAL] = 0
-	 *    ULPI DDR select, USBC_GUSBCFG[DDRSEL] = 0
-	 *    USB turnaround time, USBC_GUSBCFG[USBTRDTIM] = 0x5
-	 *    PHY low-power clock select, USBC_GUSBCFG[PHYLPWRCLKSEL] = 0
-	 */
-	{
-		union cvmx_usbcx_gusbcfg usbcx_gusbcfg;
-		usbcx_gusbcfg.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index));
-		usbcx_gusbcfg.s.toutcal = 0;
-		usbcx_gusbcfg.s.ddrsel = 0;
-		usbcx_gusbcfg.s.usbtrdtim = 0x5;
-		usbcx_gusbcfg.s.phylpwrclksel = 0;
-		__cvmx_usb_write_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index),
-				       usbcx_gusbcfg.u32);
-	}
-	/*
-	 * 4. The software must unmask the following bits in the USBC_GINTMSK
-	 *    register.
-	 *    OTG interrupt mask, USBC_GINTMSK[OTGINTMSK] = 1
-	 *    Mode mismatch interrupt mask, USBC_GINTMSK[MODEMISMSK] = 1
-	 */
-	{
-		union cvmx_usbcx_gintmsk usbcx_gintmsk;
-		int channel;
-
-		usbcx_gintmsk.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GINTMSK(usb->index));
-		usbcx_gintmsk.s.otgintmsk = 1;
-		usbcx_gintmsk.s.modemismsk = 1;
-		usbcx_gintmsk.s.hchintmsk = 1;
-		usbcx_gintmsk.s.sofmsk = 0;
-		/* We need RX FIFO interrupts if we don't have DMA */
-		if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
-			usbcx_gintmsk.s.rxflvlmsk = 1;
-		__cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTMSK(usb->index),
-				       usbcx_gintmsk.u32);
-
-		/* Disable all channel interrupts. We'll enable them per channel later */
-		for (channel = 0; channel < 8; channel++)
-			__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), 0);
-	}
-
-	{
-		/*
-		 * Host Port Initialization
-		 *
-		 * 1. Program the host-port interrupt-mask field to unmask,
-		 *    USBC_GINTMSK[PRTINT] = 1
-		 */
-		USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk,
-				prtintmsk, 1);
-		USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk,
-				disconnintmsk, 1);
-		/*
-		 * 2. Program the USBC_HCFG register to select full-speed host
-		 *    or high-speed host.
-		 */
-		{
-			union cvmx_usbcx_hcfg usbcx_hcfg;
-			usbcx_hcfg.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCFG(usb->index));
-			usbcx_hcfg.s.fslssupp = 0;
-			usbcx_hcfg.s.fslspclksel = 0;
-			__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCFG(usb->index), usbcx_hcfg.u32);
-		}
-		/*
-		 * 3. Program the port power bit to drive VBUS on the USB,
-		 *    USBC_HPRT[PRTPWR] = 1
-		 */
-		USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt, prtpwr, 1);
-
-		/*
-		 * Steps 4-15 from the manual are done later in the port enable
-		 */
-	}
-
-	return 0;
-}
-
-
-/**
- * Shutdown a USB port after a call to cvmx_usb_initialize().
- * The port should be disabled with all pipes closed when this
- * function is called.
- *
- * @state: USB device state populated by
- *	   cvmx_usb_initialize().
- *
- * Returns: 0 or a negative error code.
- */
-int cvmx_usb_shutdown(struct cvmx_usb_state *state)
-{
-	union cvmx_usbnx_clk_ctl usbn_clk_ctl;
-	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
-
-	/* Make sure all pipes are closed */
-	if (usb->idle_pipes.head ||
-		usb->active_pipes[CVMX_USB_TRANSFER_ISOCHRONOUS].head ||
-		usb->active_pipes[CVMX_USB_TRANSFER_INTERRUPT].head ||
-		usb->active_pipes[CVMX_USB_TRANSFER_CONTROL].head ||
-		usb->active_pipes[CVMX_USB_TRANSFER_BULK].head)
-		return -EBUSY;
-
-	/* Disable the clocks and put them in power on reset */
-	usbn_clk_ctl.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index));
-	usbn_clk_ctl.s.enable = 1;
-	usbn_clk_ctl.s.por = 1;
-	usbn_clk_ctl.s.hclk_rst = 1;
-	usbn_clk_ctl.s.prst = 0;
-	usbn_clk_ctl.s.hrst = 0;
-	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
-			       usbn_clk_ctl.u64);
-	return 0;
-}
-
-
-/**
- * Enable a USB port. After this call succeeds, the USB port is
- * online and servicing requests.
- *
- * @state: USB device state populated by
- *	   cvmx_usb_initialize().
- *
- * Returns: 0 or a negative error code.
- */
-int cvmx_usb_enable(struct cvmx_usb_state *state)
-{
-	union cvmx_usbcx_ghwcfg3 usbcx_ghwcfg3;
-	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
-
-	usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
-
-	/*
-	 * If the port is already enabled the just return. We don't need to do
-	 * anything
-	 */
-	if (usb->usbcx_hprt.s.prtena)
-		return 0;
-
-	/* If there is nothing plugged into the port then fail immediately */
-	if (!usb->usbcx_hprt.s.prtconnsts) {
-		return -ETIMEDOUT;
-	}
-
-	/* Program the port reset bit to start the reset process */
-	USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt, prtrst, 1);
-
-	/*
-	 * Wait at least 50ms (high speed), or 10ms (full speed) for the reset
-	 * process to complete.
-	 */
-	mdelay(50);
-
-	/* Program the port reset bit to 0, USBC_HPRT[PRTRST] = 0 */
-	USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt, prtrst, 0);
-
-	/* Wait for the USBC_HPRT[PRTENA]. */
-	if (CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt,
-				  prtena, ==, 1, 100000))
-		return -ETIMEDOUT;
-
-	/* Read the port speed field to get the enumerated speed, USBC_HPRT[PRTSPD]. */
-	usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
-	usbcx_ghwcfg3.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GHWCFG3(usb->index));
-
-	/*
-	 * 13. Program the USBC_GRXFSIZ register to select the size of the
-	 *     receive FIFO (25%).
-	 */
-	USB_SET_FIELD32(CVMX_USBCX_GRXFSIZ(usb->index), union cvmx_usbcx_grxfsiz,
-			rxfdep, usbcx_ghwcfg3.s.dfifodepth / 4);
-	/*
-	 * 14. Program the USBC_GNPTXFSIZ register to select the size and the
-	 *     start address of the non- periodic transmit FIFO for nonperiodic
-	 *     transactions (50%).
-	 */
-	{
-		union cvmx_usbcx_gnptxfsiz siz;
-		siz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index));
-		siz.s.nptxfdep = usbcx_ghwcfg3.s.dfifodepth / 2;
-		siz.s.nptxfstaddr = usbcx_ghwcfg3.s.dfifodepth / 4;
-		__cvmx_usb_write_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index), siz.u32);
-	}
-	/*
-	 * 15. Program the USBC_HPTXFSIZ register to select the size and start
-	 *     address of the periodic transmit FIFO for periodic transactions
-	 *     (25%).
-	 */
-	{
-		union cvmx_usbcx_hptxfsiz siz;
-		siz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index));
-		siz.s.ptxfsize = usbcx_ghwcfg3.s.dfifodepth / 4;
-		siz.s.ptxfstaddr = 3 * usbcx_ghwcfg3.s.dfifodepth / 4;
-		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index), siz.u32);
-	}
-	/* Flush all FIFOs */
-	USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl, txfnum, 0x10);
-	USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl, txfflsh, 1);
-	CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl,
-			      txfflsh, ==, 0, 100);
-	USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl, rxfflsh, 1);
-	CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl,
-			      rxfflsh, ==, 0, 100);
-
-	return 0;
-}
-
-
-/**
- * Disable a USB port. After this call the USB port will not
- * generate data transfers and will not generate events.
- * Transactions in process will fail and call their
- * associated callbacks.
- *
- * @state: USB device state populated by
- *	   cvmx_usb_initialize().
- *
- * Returns: 0 or a negative error code.
- */
-int cvmx_usb_disable(struct cvmx_usb_state *state)
-{
-	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
-
-	/* Disable the port */
-	USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt, prtena, 1);
-	return 0;
-}
-
-
-/**
- * Get the current state of the USB port. Use this call to
- * determine if the usb port has anything connected, is enabled,
- * or has some sort of error condition. The return value of this
- * call has "changed" bits to signal of the value of some fields
- * have changed between calls. These "changed" fields are based
- * on the last call to cvmx_usb_set_status(). In order to clear
- * them, you must update the status through cvmx_usb_set_status().
- *
- * @state: USB device state populated by
- *	   cvmx_usb_initialize().
- *
- * Returns: Port status information
- */
-struct cvmx_usb_port_status cvmx_usb_get_status(struct cvmx_usb_state *state)
-{
-	union cvmx_usbcx_hprt usbc_hprt;
-	struct cvmx_usb_port_status result;
-	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
-
-	memset(&result, 0, sizeof(result));
-
-	usbc_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
-	result.port_enabled = usbc_hprt.s.prtena;
-	result.port_over_current = usbc_hprt.s.prtovrcurract;
-	result.port_powered = usbc_hprt.s.prtpwr;
-	result.port_speed = usbc_hprt.s.prtspd;
-	result.connected = usbc_hprt.s.prtconnsts;
-	result.connect_change = (result.connected != usb->port_status.connected);
-
-	return result;
-}
-
-
-/**
- * Set the current state of the USB port. The status is used as
- * a reference for the "changed" bits returned by
- * cvmx_usb_get_status(). Other than serving as a reference, the
- * status passed to this function is not used. No fields can be
- * changed through this call.
- *
- * @state:	 USB device state populated by
- *		 cvmx_usb_initialize().
- * @port_status:
- *		 Port status to set, most like returned by cvmx_usb_get_status()
- */
-void cvmx_usb_set_status(struct cvmx_usb_state *state, struct cvmx_usb_port_status port_status)
-{
-	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
-	usb->port_status = port_status;
-	return;
-}
-
-
-/**
- * Convert a USB transaction into a handle
- *
- * @usb:	 USB device state populated by
- *		 cvmx_usb_initialize().
- * @transaction:
- *		 Transaction to get handle for
- *
- * Returns: Handle
- */
-static inline int __cvmx_usb_get_submit_handle(struct cvmx_usb_internal_state *usb,
-					       struct cvmx_usb_transaction *transaction)
-{
-	return ((unsigned long)transaction - (unsigned long)usb->transaction) /
-			sizeof(*transaction);
-}
-
-
-/**
- * Convert a USB pipe into a handle
- *
- * @usb:	 USB device state populated by
- *		 cvmx_usb_initialize().
- * @pipe:	 Pipe to get handle for
- *
- * Returns: Handle
- */
-static inline int __cvmx_usb_get_pipe_handle(struct cvmx_usb_internal_state *usb,
-					     struct cvmx_usb_pipe *pipe)
-{
-	return ((unsigned long)pipe - (unsigned long)usb->pipe) / sizeof(*pipe);
-}
-
-
-/**
- * Open a virtual pipe between the host and a USB device. A pipe
- * must be opened before data can be transferred between a device
- * and Octeon.
- *
- * @state:	     USB device state populated by
- *		     cvmx_usb_initialize().
- * @flags:	     Optional pipe flags defined in
- *		     enum cvmx_usb_pipe_flags.
- * @device_addr:
- *		     USB device address to open the pipe to
- *		     (0-127).
- * @endpoint_num:
- *		     USB endpoint number to open the pipe to
- *		     (0-15).
- * @device_speed:
- *		     The speed of the device the pipe is going
- *		     to. This must match the device's speed,
- *		     which may be different than the port speed.
- * @max_packet:	     The maximum packet length the device can
- *		     transmit/receive (low speed=0-8, full
- *		     speed=0-1023, high speed=0-1024). This value
- *		     comes from the standard endpoint descriptor
- *		     field wMaxPacketSize bits <10:0>.
- * @transfer_type:
- *		     The type of transfer this pipe is for.
- * @transfer_dir:
- *		     The direction the pipe is in. This is not
- *		     used for control pipes.
- * @interval:	     For ISOCHRONOUS and INTERRUPT transfers,
- *		     this is how often the transfer is scheduled
- *		     for. All other transfers should specify
- *		     zero. The units are in frames (8000/sec at
- *		     high speed, 1000/sec for full speed).
- * @multi_count:
- *		     For high speed devices, this is the maximum
- *		     allowed number of packet per microframe.
- *		     Specify zero for non high speed devices. This
- *		     value comes from the standard endpoint descriptor
- *		     field wMaxPacketSize bits <12:11>.
- * @hub_device_addr:
- *		     Hub device address this device is connected
- *		     to. Devices connected directly to Octeon
- *		     use zero. This is only used when the device
- *		     is full/low speed behind a high speed hub.
- *		     The address will be of the high speed hub,
- *		     not and full speed hubs after it.
- * @hub_port:	     Which port on the hub the device is
- *		     connected. Use zero for devices connected
- *		     directly to Octeon. Like hub_device_addr,
- *		     this is only used for full/low speed
- *		     devices behind a high speed hub.
- *
- * Returns: A non negative value is a pipe handle. Negative
- *	    values are error codes.
- */
-int cvmx_usb_open_pipe(struct cvmx_usb_state *state, enum cvmx_usb_pipe_flags flags,
-		       int device_addr, int endpoint_num,
-		       enum cvmx_usb_speed device_speed, int max_packet,
-		       enum cvmx_usb_transfer transfer_type,
-		       enum cvmx_usb_direction transfer_dir, int interval,
-		       int multi_count, int hub_device_addr, int hub_port)
-{
-	struct cvmx_usb_pipe *pipe;
-	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
-
-	if (unlikely((device_addr < 0) || (device_addr > MAX_USB_ADDRESS)))
-		return -EINVAL;
-	if (unlikely((endpoint_num < 0) || (endpoint_num > MAX_USB_ENDPOINT)))
-		return -EINVAL;
-	if (unlikely(device_speed > CVMX_USB_SPEED_LOW))
-		return -EINVAL;
-	if (unlikely((max_packet <= 0) || (max_packet > 1024)))
-		return -EINVAL;
-	if (unlikely(transfer_type > CVMX_USB_TRANSFER_INTERRUPT))
-		return -EINVAL;
-	if (unlikely((transfer_dir != CVMX_USB_DIRECTION_OUT) &&
-		(transfer_dir != CVMX_USB_DIRECTION_IN)))
-		return -EINVAL;
-	if (unlikely(interval < 0))
-		return -EINVAL;
-	if (unlikely((transfer_type == CVMX_USB_TRANSFER_CONTROL) && interval))
-		return -EINVAL;
-	if (unlikely(multi_count < 0))
-		return -EINVAL;
-	if (unlikely((device_speed != CVMX_USB_SPEED_HIGH) &&
-		(multi_count != 0)))
-		return -EINVAL;
-	if (unlikely((hub_device_addr < 0) || (hub_device_addr > MAX_USB_ADDRESS)))
-		return -EINVAL;
-	if (unlikely((hub_port < 0) || (hub_port > MAX_USB_HUB_PORT)))
-		return -EINVAL;
-
-	/* Find a free pipe */
-	pipe = usb->free_pipes.head;
-	if (!pipe)
-		return -ENOMEM;
-	__cvmx_usb_remove_pipe(&usb->free_pipes, pipe);
-	pipe->flags = flags | __CVMX_USB_PIPE_FLAGS_OPEN;
-	if ((device_speed == CVMX_USB_SPEED_HIGH) &&
-		(transfer_dir == CVMX_USB_DIRECTION_OUT) &&
-		(transfer_type == CVMX_USB_TRANSFER_BULK))
-		pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING;
-	pipe->device_addr = device_addr;
-	pipe->endpoint_num = endpoint_num;
-	pipe->device_speed = device_speed;
-	pipe->max_packet = max_packet;
-	pipe->transfer_type = transfer_type;
-	pipe->transfer_dir = transfer_dir;
-	/*
-	 * All pipes use interval to rate limit NAK processing. Force an
-	 * interval if one wasn't supplied
-	 */
-	if (!interval)
-		interval = 1;
-	if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
-		pipe->interval = interval*8;
-		/* Force start splits to be schedule on uFrame 0 */
-		pipe->next_tx_frame = ((usb->frame_number+7)&~7) + pipe->interval;
-	} else {
-		pipe->interval = interval;
-		pipe->next_tx_frame = usb->frame_number + pipe->interval;
-	}
-	pipe->multi_count = multi_count;
-	pipe->hub_device_addr = hub_device_addr;
-	pipe->hub_port = hub_port;
-	pipe->pid_toggle = 0;
-	pipe->split_sc_frame = -1;
-	__cvmx_usb_append_pipe(&usb->idle_pipes, pipe);
-
-	/*
-	 * We don't need to tell the hardware about this pipe yet since
-	 * it doesn't have any submitted requests
-	 */
-
-	return __cvmx_usb_get_pipe_handle(usb, pipe);
-}
-
-
-/**
- * Poll the RX FIFOs and remove data as needed. This function is only used
- * in non DMA mode. It is very important that this function be called quickly
- * enough to prevent FIFO overflow.
- *
- * @usb:	USB device state populated by
- *		cvmx_usb_initialize().
- */
-static void __cvmx_usb_poll_rx_fifo(struct cvmx_usb_internal_state *usb)
-{
-	union cvmx_usbcx_grxstsph rx_status;
-	int channel;
-	int bytes;
-	uint64_t address;
-	uint32_t *ptr;
-
-	rx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GRXSTSPH(usb->index));
-	/* Only read data if IN data is there */
-	if (rx_status.s.pktsts != 2)
-		return;
-	/* Check if no data is available */
-	if (!rx_status.s.bcnt)
-		return;
-
-	channel = rx_status.s.chnum;
-	bytes = rx_status.s.bcnt;
-	if (!bytes)
-		return;
-
-	/* Get where the DMA engine would have written this data */
-	address = __cvmx_usb_read_csr64(usb, CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8);
-	ptr = cvmx_phys_to_ptr(address);
-	__cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8, address + bytes);
-
-	/* Loop writing the FIFO data for this packet into memory */
-	while (bytes > 0) {
-		*ptr++ = __cvmx_usb_read_csr32(usb, USB_FIFO_ADDRESS(channel, usb->index));
-		bytes -= 4;
-	}
-	CVMX_SYNCW;
-
-	return;
-}
-
-
-/**
- * Fill the TX hardware fifo with data out of the software
- * fifos
- *
- * @usb:	    USB device state populated by
- *		    cvmx_usb_initialize().
- * @fifo:	    Software fifo to use
- * @available:	    Amount of space in the hardware fifo
- *
- * Returns: Non zero if the hardware fifo was too small and needs
- *	    to be serviced again.
- */
-static int __cvmx_usb_fill_tx_hw(struct cvmx_usb_internal_state *usb, struct cvmx_usb_tx_fifo *fifo, int available)
-{
-	/*
-	 * We're done either when there isn't anymore space or the software FIFO
-	 * is empty
-	 */
-	while (available && (fifo->head != fifo->tail)) {
-		int i = fifo->tail;
-		const uint32_t *ptr = cvmx_phys_to_ptr(fifo->entry[i].address);
-		uint64_t csr_address = USB_FIFO_ADDRESS(fifo->entry[i].channel, usb->index) ^ 4;
-		int words = available;
-
-		/* Limit the amount of data to waht the SW fifo has */
-		if (fifo->entry[i].size <= available) {
-			words = fifo->entry[i].size;
-			fifo->tail++;
-			if (fifo->tail > MAX_CHANNELS)
-				fifo->tail = 0;
-		}
-
-		/* Update the next locations and counts */
-		available -= words;
-		fifo->entry[i].address += words * 4;
-		fifo->entry[i].size -= words;
-
-		/*
-		 * Write the HW fifo data. The read every three writes is due
-		 * to an errata on CN3XXX chips
-		 */
-		while (words > 3) {
-			cvmx_write64_uint32(csr_address, *ptr++);
-			cvmx_write64_uint32(csr_address, *ptr++);
-			cvmx_write64_uint32(csr_address, *ptr++);
-			cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index));
-			words -= 3;
-		}
-		cvmx_write64_uint32(csr_address, *ptr++);
-		if (--words) {
-			cvmx_write64_uint32(csr_address, *ptr++);
-			if (--words)
-				cvmx_write64_uint32(csr_address, *ptr++);
-		}
-		cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index));
-	}
-	return fifo->head != fifo->tail;
-}
-
-
-/**
- * Check the hardware FIFOs and fill them as needed
- *
- * @usb:	USB device state populated by
- *		cvmx_usb_initialize().
- */
-static void __cvmx_usb_poll_tx_fifo(struct cvmx_usb_internal_state *usb)
-{
-	if (usb->periodic.head != usb->periodic.tail) {
-		union cvmx_usbcx_hptxsts tx_status;
-		tx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPTXSTS(usb->index));
-		if (__cvmx_usb_fill_tx_hw(usb, &usb->periodic, tx_status.s.ptxfspcavail))
-			USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, ptxfempmsk, 1);
-		else
-			USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, ptxfempmsk, 0);
-	}
-
-	if (usb->nonperiodic.head != usb->nonperiodic.tail) {
-		union cvmx_usbcx_gnptxsts tx_status;
-		tx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GNPTXSTS(usb->index));
-		if (__cvmx_usb_fill_tx_hw(usb, &usb->nonperiodic, tx_status.s.nptxfspcavail))
-			USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, nptxfempmsk, 1);
-		else
-			USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, nptxfempmsk, 0);
-	}
-
-	return;
-}
-
-
-/**
- * Fill the TX FIFO with an outgoing packet
- *
- * @usb:	  USB device state populated by
- *		  cvmx_usb_initialize().
- * @channel:	  Channel number to get packet from
- */
-static void __cvmx_usb_fill_tx_fifo(struct cvmx_usb_internal_state *usb, int channel)
-{
-	union cvmx_usbcx_hccharx hcchar;
-	union cvmx_usbcx_hcspltx usbc_hcsplt;
-	union cvmx_usbcx_hctsizx usbc_hctsiz;
-	struct cvmx_usb_tx_fifo *fifo;
-
-	/* We only need to fill data on outbound channels */
-	hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index));
-	if (hcchar.s.epdir != CVMX_USB_DIRECTION_OUT)
-		return;
-
-	/* OUT Splits only have data on the start and not the complete */
-	usbc_hcsplt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCSPLTX(channel, usb->index));
-	if (usbc_hcsplt.s.spltena && usbc_hcsplt.s.compsplt)
-		return;
-
-	/* Find out how many bytes we need to fill and convert it into 32bit words */
-	usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index));
-	if (!usbc_hctsiz.s.xfersize)
-		return;
-
-	if ((hcchar.s.eptype == CVMX_USB_TRANSFER_INTERRUPT) ||
-		(hcchar.s.eptype == CVMX_USB_TRANSFER_ISOCHRONOUS))
-		fifo = &usb->periodic;
-	else
-		fifo = &usb->nonperiodic;
-
-	fifo->entry[fifo->head].channel = channel;
-	fifo->entry[fifo->head].address = __cvmx_usb_read_csr64(usb, CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8);
-	fifo->entry[fifo->head].size = (usbc_hctsiz.s.xfersize+3)>>2;
-	fifo->head++;
-	if (fifo->head > MAX_CHANNELS)
-		fifo->head = 0;
-
-	__cvmx_usb_poll_tx_fifo(usb);
-
-	return;
-}
-
-/**
- * Perform channel specific setup for Control transactions. All
- * the generic stuff will already have been done in
- * __cvmx_usb_start_channel()
- *
- * @usb:	  USB device state populated by
- *		  cvmx_usb_initialize().
- * @channel:	  Channel to setup
- * @pipe:	  Pipe for control transaction
- */
-static void __cvmx_usb_start_channel_control(struct cvmx_usb_internal_state *usb,
-					     int channel,
-					     struct cvmx_usb_pipe *pipe)
-{
-	struct cvmx_usb_transaction *transaction = pipe->head;
-	union cvmx_usb_control_header *header =
-		cvmx_phys_to_ptr(transaction->control_header);
-	int bytes_to_transfer = transaction->buffer_length - transaction->actual_bytes;
-	int packets_to_transfer;
-	union cvmx_usbcx_hctsizx usbc_hctsiz;
-
-	usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index));
-
-	switch (transaction->stage) {
-	case CVMX_USB_STAGE_NON_CONTROL:
-	case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE:
-		cvmx_dprintf("%s: ERROR - Non control stage\n", __FUNCTION__);
-		break;
-	case CVMX_USB_STAGE_SETUP:
-		usbc_hctsiz.s.pid = 3; /* Setup */
-		bytes_to_transfer = sizeof(*header);
-		/* All Control operations start with a setup going OUT */
-		USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, epdir, CVMX_USB_DIRECTION_OUT);
-		/*
-		 * Setup send the control header instead of the buffer data. The
-		 * buffer data will be used in the next stage
-		 */
-		__cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8, transaction->control_header);
-		break;
-	case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE:
-		usbc_hctsiz.s.pid = 3; /* Setup */
-		bytes_to_transfer = 0;
-		/* All Control operations start with a setup going OUT */
-		USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, epdir, CVMX_USB_DIRECTION_OUT);
-		USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), union cvmx_usbcx_hcspltx, compsplt, 1);
-		break;
-	case CVMX_USB_STAGE_DATA:
-		usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
-		if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
-			if (header->s.request_type & 0x80)
-				bytes_to_transfer = 0;
-			else if (bytes_to_transfer > pipe->max_packet)
-				bytes_to_transfer = pipe->max_packet;
-		}
-		USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
-				union cvmx_usbcx_hccharx, epdir,
-				((header->s.request_type & 0x80) ?
-					CVMX_USB_DIRECTION_IN :
-					CVMX_USB_DIRECTION_OUT));
-		break;
-	case CVMX_USB_STAGE_DATA_SPLIT_COMPLETE:
-		usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
-		if (!(header->s.request_type & 0x80))
-			bytes_to_transfer = 0;
-		USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
-				union cvmx_usbcx_hccharx, epdir,
-				((header->s.request_type & 0x80) ?
-					CVMX_USB_DIRECTION_IN :
-					CVMX_USB_DIRECTION_OUT));
-		USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), union cvmx_usbcx_hcspltx, compsplt, 1);
-		break;
-	case CVMX_USB_STAGE_STATUS:
-		usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
-		bytes_to_transfer = 0;
-		USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, epdir,
-				((header->s.request_type & 0x80) ?
-					CVMX_USB_DIRECTION_OUT :
-					CVMX_USB_DIRECTION_IN));
-		break;
-	case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE:
-		usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
-		bytes_to_transfer = 0;
-		USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, epdir,
-				((header->s.request_type & 0x80) ?
-					CVMX_USB_DIRECTION_OUT :
-					CVMX_USB_DIRECTION_IN));
-		USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), union cvmx_usbcx_hcspltx, compsplt, 1);
-		break;
-	}
-
-	/*
-	 * Make sure the transfer never exceeds the byte limit of the hardware.
-	 * Further bytes will be sent as continued transactions
-	 */
-	if (bytes_to_transfer > MAX_TRANSFER_BYTES) {
-		/* Round MAX_TRANSFER_BYTES to a multiple of out packet size */
-		bytes_to_transfer = MAX_TRANSFER_BYTES / pipe->max_packet;
-		bytes_to_transfer *= pipe->max_packet;
-	}
-
-	/*
-	 * Calculate the number of packets to transfer. If the length is zero
-	 * we still need to transfer one packet
-	 */
-	packets_to_transfer = (bytes_to_transfer + pipe->max_packet - 1) / pipe->max_packet;
-	if (packets_to_transfer == 0)
-		packets_to_transfer = 1;
-	else if ((packets_to_transfer > 1) && (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)) {
-		/*
-		 * Limit to one packet when not using DMA. Channels must be
-		 * restarted between every packet for IN transactions, so there
-		 * is no reason to do multiple packets in a row
-		 */
-		packets_to_transfer = 1;
-		bytes_to_transfer = packets_to_transfer * pipe->max_packet;
-	} else if (packets_to_transfer > MAX_TRANSFER_PACKETS) {
-		/*
-		 * Limit the number of packet and data transferred to what the
-		 * hardware can handle
-		 */
-		packets_to_transfer = MAX_TRANSFER_PACKETS;
-		bytes_to_transfer = packets_to_transfer * pipe->max_packet;
-	}
-
-	usbc_hctsiz.s.xfersize = bytes_to_transfer;
-	usbc_hctsiz.s.pktcnt = packets_to_transfer;
-
-	__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index), usbc_hctsiz.u32);
-	return;
-}
-
-
-/**
- * Start a channel to perform the pipe's head transaction
- *
- * @usb:	  USB device state populated by
- *		  cvmx_usb_initialize().
- * @channel:	  Channel to setup
- * @pipe:	  Pipe to start
- */
-static void __cvmx_usb_start_channel(struct cvmx_usb_internal_state *usb,
-				     int channel,
-				     struct cvmx_usb_pipe *pipe)
-{
-	struct cvmx_usb_transaction *transaction = pipe->head;
-
-	/* Make sure all writes to the DMA region get flushed */
-	CVMX_SYNCW;
-
-	/* Attach the channel to the pipe */
-	usb->pipe_for_channel[channel] = pipe;
-	pipe->channel = channel;
-	pipe->flags |= __CVMX_USB_PIPE_FLAGS_SCHEDULED;
-
-	/* Mark this channel as in use */
-	usb->idle_hardware_channels &= ~(1<<channel);
-
-	/* Enable the channel interrupt bits */
-	{
-		union cvmx_usbcx_hcintx usbc_hcint;
-		union cvmx_usbcx_hcintmskx usbc_hcintmsk;
-		union cvmx_usbcx_haintmsk usbc_haintmsk;
-
-		/* Clear all channel status bits */
-		usbc_hcint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCINTX(channel, usb->index));
-		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTX(channel, usb->index), usbc_hcint.u32);
-
-		usbc_hcintmsk.u32 = 0;
-		usbc_hcintmsk.s.chhltdmsk = 1;
-		if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) {
-			/* Channels need these extra interrupts when we aren't in DMA mode */
-			usbc_hcintmsk.s.datatglerrmsk = 1;
-			usbc_hcintmsk.s.frmovrunmsk = 1;
-			usbc_hcintmsk.s.bblerrmsk = 1;
-			usbc_hcintmsk.s.xacterrmsk = 1;
-			if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
-				/* Splits don't generate xfercompl, so we need ACK and NYET */
-				usbc_hcintmsk.s.nyetmsk = 1;
-				usbc_hcintmsk.s.ackmsk = 1;
-			}
-			usbc_hcintmsk.s.nakmsk = 1;
-			usbc_hcintmsk.s.stallmsk = 1;
-			usbc_hcintmsk.s.xfercomplmsk = 1;
-		}
-		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), usbc_hcintmsk.u32);
-
-		/* Enable the channel interrupt to propagate */
-		usbc_haintmsk.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HAINTMSK(usb->index));
-		usbc_haintmsk.s.haintmsk |= 1<<channel;
-		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HAINTMSK(usb->index), usbc_haintmsk.u32);
-	}
-
-	/* Setup the locations the DMA engines use  */
-	{
-		uint64_t dma_address = transaction->buffer + transaction->actual_bytes;
-		if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)
-			dma_address = transaction->buffer + transaction->iso_packets[0].offset + transaction->actual_bytes;
-		__cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8, dma_address);
-		__cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8, dma_address);
-	}
-
-	/* Setup both the size of the transfer and the SPLIT characteristics */
-	{
-		union cvmx_usbcx_hcspltx usbc_hcsplt = {.u32 = 0};
-		union cvmx_usbcx_hctsizx usbc_hctsiz = {.u32 = 0};
-		int packets_to_transfer;
-		int bytes_to_transfer = transaction->buffer_length - transaction->actual_bytes;
-
-		/*
-		 * ISOCHRONOUS transactions store each individual transfer size
-		 * in the packet structure, not the global buffer_length
-		 */
-		if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)
-			bytes_to_transfer = transaction->iso_packets[0].length - transaction->actual_bytes;
-
-		/*
-		 * We need to do split transactions when we are talking to non
-		 * high speed devices that are behind a high speed hub
-		 */
-		if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
-			/*
-			 * On the start split phase (stage is even) record the
-			 * frame number we will need to send the split complete.
-			 * We only store the lower two bits since the time ahead
-			 * can only be two frames
-			 */
-			if ((transaction->stage&1) == 0) {
-				if (transaction->type == CVMX_USB_TRANSFER_BULK)
-					pipe->split_sc_frame = (usb->frame_number + 1) & 0x7f;
-				else
-					pipe->split_sc_frame = (usb->frame_number + 2) & 0x7f;
-			} else
-				pipe->split_sc_frame = -1;
-
-			usbc_hcsplt.s.spltena = 1;
-			usbc_hcsplt.s.hubaddr = pipe->hub_device_addr;
-			usbc_hcsplt.s.prtaddr = pipe->hub_port;
-			usbc_hcsplt.s.compsplt = (transaction->stage == CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE);
-
-			/*
-			 * SPLIT transactions can only ever transmit one data
-			 * packet so limit the transfer size to the max packet
-			 * size
-			 */
-			if (bytes_to_transfer > pipe->max_packet)
-				bytes_to_transfer = pipe->max_packet;
-
-			/*
-			 * ISOCHRONOUS OUT splits are unique in that they limit
-			 * data transfers to 188 byte chunks representing the
-			 * begin/middle/end of the data or all
-			 */
-			if (!usbc_hcsplt.s.compsplt &&
-				(pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) &&
-				(pipe->transfer_type == CVMX_USB_TRANSFER_ISOCHRONOUS)) {
-				/*
-				 * Clear the split complete frame number as
-				 * there isn't going to be a split complete
-				 */
-				pipe->split_sc_frame = -1;
-				/*
-				 * See if we've started this transfer and sent
-				 * data
-				 */
-				if (transaction->actual_bytes == 0) {
-					/*
-					 * Nothing sent yet, this is either a
-					 * begin or the entire payload
-					 */
-					if (bytes_to_transfer <= 188)
-						usbc_hcsplt.s.xactpos = 3; /* Entire payload in one go */
-					else
-						usbc_hcsplt.s.xactpos = 2; /* First part of payload */
-				} else {
-					/*
-					 * Continuing the previous data, we must
-					 * either be in the middle or at the end
-					 */
-					if (bytes_to_transfer <= 188)
-						usbc_hcsplt.s.xactpos = 1; /* End of payload */
-					else
-						usbc_hcsplt.s.xactpos = 0; /* Middle of payload */
-				}
-				/*
-				 * Again, the transfer size is limited to 188
-				 * bytes
-				 */
-				if (bytes_to_transfer > 188)
-					bytes_to_transfer = 188;
-			}
-		}
-
-		/*
-		 * Make sure the transfer never exceeds the byte limit of the
-		 * hardware. Further bytes will be sent as continued
-		 * transactions
-		 */
-		if (bytes_to_transfer > MAX_TRANSFER_BYTES) {
-			/*
-			 * Round MAX_TRANSFER_BYTES to a multiple of out packet
-			 * size
-			 */
-			bytes_to_transfer = MAX_TRANSFER_BYTES / pipe->max_packet;
-			bytes_to_transfer *= pipe->max_packet;
-		}
-
-		/*
-		 * Calculate the number of packets to transfer. If the length is
-		 * zero we still need to transfer one packet
-		 */
-		packets_to_transfer = (bytes_to_transfer + pipe->max_packet - 1) / pipe->max_packet;
-		if (packets_to_transfer == 0)
-			packets_to_transfer = 1;
-		else if ((packets_to_transfer > 1) && (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)) {
-			/*
-			 * Limit to one packet when not using DMA. Channels must
-			 * be restarted between every packet for IN
-			 * transactions, so there is no reason to do multiple
-			 * packets in a row
-			 */
-			packets_to_transfer = 1;
-			bytes_to_transfer = packets_to_transfer * pipe->max_packet;
-		} else if (packets_to_transfer > MAX_TRANSFER_PACKETS) {
-			/*
-			 * Limit the number of packet and data transferred to
-			 * what the hardware can handle
-			 */
-			packets_to_transfer = MAX_TRANSFER_PACKETS;
-			bytes_to_transfer = packets_to_transfer * pipe->max_packet;
-		}
-
-		usbc_hctsiz.s.xfersize = bytes_to_transfer;
-		usbc_hctsiz.s.pktcnt = packets_to_transfer;
-
-		/* Update the DATA0/DATA1 toggle */
-		usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
-		/*
-		 * High speed pipes may need a hardware ping before they start
-		 */
-		if (pipe->flags & __CVMX_USB_PIPE_FLAGS_NEED_PING)
-			usbc_hctsiz.s.dopng = 1;
-
-		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCSPLTX(channel, usb->index), usbc_hcsplt.u32);
-		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index), usbc_hctsiz.u32);
-	}
-
-	/* Setup the Host Channel Characteristics Register */
-	{
-		union cvmx_usbcx_hccharx usbc_hcchar = {.u32 = 0};
-
-		/*
-		 * Set the startframe odd/even properly. This is only used for
-		 * periodic
-		 */
-		usbc_hcchar.s.oddfrm = usb->frame_number&1;
-
-		/*
-		 * Set the number of back to back packets allowed by this
-		 * endpoint. Split transactions interpret "ec" as the number of
-		 * immediate retries of failure. These retries happen too
-		 * quickly, so we disable these entirely for splits
-		 */
-		if (__cvmx_usb_pipe_needs_split(usb, pipe))
-			usbc_hcchar.s.ec = 1;
-		else if (pipe->multi_count < 1)
-			usbc_hcchar.s.ec = 1;
-		else if (pipe->multi_count > 3)
-			usbc_hcchar.s.ec = 3;
-		else
-			usbc_hcchar.s.ec = pipe->multi_count;
-
-		/* Set the rest of the endpoint specific settings */
-		usbc_hcchar.s.devaddr = pipe->device_addr;
-		usbc_hcchar.s.eptype = transaction->type;
-		usbc_hcchar.s.lspddev = (pipe->device_speed == CVMX_USB_SPEED_LOW);
-		usbc_hcchar.s.epdir = pipe->transfer_dir;
-		usbc_hcchar.s.epnum = pipe->endpoint_num;
-		usbc_hcchar.s.mps = pipe->max_packet;
-		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32);
-	}
-
-	/* Do transaction type specific fixups as needed */
-	switch (transaction->type) {
-	case CVMX_USB_TRANSFER_CONTROL:
-		__cvmx_usb_start_channel_control(usb, channel, pipe);
-		break;
-	case CVMX_USB_TRANSFER_BULK:
-	case CVMX_USB_TRANSFER_INTERRUPT:
-		break;
-	case CVMX_USB_TRANSFER_ISOCHRONOUS:
-		if (!__cvmx_usb_pipe_needs_split(usb, pipe)) {
-			/*
-			 * ISO transactions require different PIDs depending on
-			 * direction and how many packets are needed
-			 */
-			if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) {
-				if (pipe->multi_count < 2) /* Need DATA0 */
-					USB_SET_FIELD32(CVMX_USBCX_HCTSIZX(channel, usb->index), union cvmx_usbcx_hctsizx, pid, 0);
-				else /* Need MDATA */
-					USB_SET_FIELD32(CVMX_USBCX_HCTSIZX(channel, usb->index), union cvmx_usbcx_hctsizx, pid, 3);
-			}
-		}
-		break;
-	}
-	{
-		union cvmx_usbcx_hctsizx usbc_hctsiz = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index))};
-		transaction->xfersize = usbc_hctsiz.s.xfersize;
-		transaction->pktcnt = usbc_hctsiz.s.pktcnt;
-	}
-	/* Remeber when we start a split transaction */
-	if (__cvmx_usb_pipe_needs_split(usb, pipe))
-		usb->active_split = transaction;
-	USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, chena, 1);
-	if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
-		__cvmx_usb_fill_tx_fifo(usb, channel);
-	return;
-}
-
-
-/**
- * Find a pipe that is ready to be scheduled to hardware.
- * @usb:	 USB device state populated by
- *		 cvmx_usb_initialize().
- * @list:	 Pipe list to search
- * @current_frame:
- *		 Frame counter to use as a time reference.
- *
- * Returns: Pipe or NULL if none are ready
- */
-static struct cvmx_usb_pipe *__cvmx_usb_find_ready_pipe(struct cvmx_usb_internal_state *usb, struct cvmx_usb_pipe_list *list, uint64_t current_frame)
-{
-	struct cvmx_usb_pipe *pipe = list->head;
-	while (pipe) {
-		if (!(pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED) && pipe->head &&
-			(pipe->next_tx_frame <= current_frame) &&
-			((pipe->split_sc_frame == -1) || ((((int)current_frame - (int)pipe->split_sc_frame) & 0x7f) < 0x40)) &&
-			(!usb->active_split || (usb->active_split == pipe->head))) {
-			CVMX_PREFETCH(pipe, 128);
-			CVMX_PREFETCH(pipe->head, 0);
-			return pipe;
-		}
-		pipe = pipe->next;
-	}
-	return NULL;
-}
-
-
-/**
- * Called whenever a pipe might need to be scheduled to the
- * hardware.
- *
- * @usb:	 USB device state populated by
- *		 cvmx_usb_initialize().
- * @is_sof:	 True if this schedule was called on a SOF interrupt.
- */
-static void __cvmx_usb_schedule(struct cvmx_usb_internal_state *usb, int is_sof)
-{
-	int channel;
-	struct cvmx_usb_pipe *pipe;
-	int need_sof;
-	enum cvmx_usb_transfer ttype;
-
-	if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) {
-		/* Without DMA we need to be careful to not schedule something at the end of a frame and cause an overrun */
-		union cvmx_usbcx_hfnum hfnum = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index))};
-		union cvmx_usbcx_hfir hfir = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFIR(usb->index))};
-		if (hfnum.s.frrem < hfir.s.frint/4)
-			goto done;
-	}
-
-	while (usb->idle_hardware_channels) {
-		/* Find an idle channel */
-		CVMX_CLZ(channel, usb->idle_hardware_channels);
-		channel = 31 - channel;
-		if (unlikely(channel > 7))
-			break;
-
-		/* Find a pipe needing service */
-		pipe = NULL;
-		if (is_sof) {
-			/*
-			 * Only process periodic pipes on SOF interrupts. This
-			 * way we are sure that the periodic data is sent in the
-			 * beginning of the frame
-			 */
-			pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_ISOCHRONOUS, usb->frame_number);
-			if (likely(!pipe))
-				pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_INTERRUPT, usb->frame_number);
-		}
-		if (likely(!pipe)) {
-			pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_CONTROL, usb->frame_number);
-			if (likely(!pipe))
-				pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_BULK, usb->frame_number);
-		}
-		if (!pipe)
-			break;
-
-		__cvmx_usb_start_channel(usb, channel, pipe);
-	}
-
-done:
-	/*
-	 * Only enable SOF interrupts when we have transactions pending in the
-	 * future that might need to be scheduled
-	 */
-	need_sof = 0;
-	for (ttype = CVMX_USB_TRANSFER_CONTROL; ttype <= CVMX_USB_TRANSFER_INTERRUPT; ttype++) {
-		pipe = usb->active_pipes[ttype].head;
-		while (pipe) {
-			if (pipe->next_tx_frame > usb->frame_number) {
-				need_sof = 1;
-				break;
-			}
-			pipe = pipe->next;
-		}
-	}
-	USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, sofmsk, need_sof);
-	return;
-}
-
-
-/**
- * Call a user's callback for a specific reason.
- *
- * @usb:	 USB device state populated by
- *		 cvmx_usb_initialize().
- * @pipe:	 Pipe the callback is for or NULL
- * @transaction:
- *		 Transaction the callback is for or NULL
- * @reason:	 Reason this callback is being called
- * @complete_code:
- *		 Completion code for the transaction, if any
- */
-static void __cvmx_usb_perform_callback(struct cvmx_usb_internal_state *usb,
-					struct cvmx_usb_pipe *pipe,
-					struct cvmx_usb_transaction *transaction,
-					enum cvmx_usb_callback reason,
-					enum cvmx_usb_complete complete_code)
-{
-	cvmx_usb_callback_func_t callback = usb->callback[reason];
-	void *user_data = usb->callback_data[reason];
-	int submit_handle = -1;
-	int pipe_handle = -1;
-	int bytes_transferred = 0;
-
-	if (pipe)
-		pipe_handle = __cvmx_usb_get_pipe_handle(usb, pipe);
-
-	if (transaction) {
-		submit_handle = __cvmx_usb_get_submit_handle(usb, transaction);
-		bytes_transferred = transaction->actual_bytes;
-		/* Transactions are allowed to override the default callback */
-		if ((reason == CVMX_USB_CALLBACK_TRANSFER_COMPLETE) && transaction->callback) {
-			callback = transaction->callback;
-			user_data = transaction->callback_data;
-		}
-	}
-
-	if (!callback)
-		return;
-
-	callback((struct cvmx_usb_state *)usb, reason, complete_code, pipe_handle, submit_handle,
-		 bytes_transferred, user_data);
-}
-
-
-/**
- * Signal the completion of a transaction and free it. The
- * transaction will be removed from the pipe transaction list.
- *
- * @usb:	 USB device state populated by
- *		 cvmx_usb_initialize().
- * @pipe:	 Pipe the transaction is on
- * @transaction:
- *		 Transaction that completed
- * @complete_code:
- *		 Completion code
- */
-static void __cvmx_usb_perform_complete(struct cvmx_usb_internal_state *usb,
-					struct cvmx_usb_pipe *pipe,
-					struct cvmx_usb_transaction *transaction,
-					enum cvmx_usb_complete complete_code)
-{
-	/* If this was a split then clear our split in progress marker */
-	if (usb->active_split == transaction)
-		usb->active_split = NULL;
-
-	/*
-	 * Isochronous transactions need extra processing as they might not be
-	 * done after a single data transfer
-	 */
-	if (unlikely(transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)) {
-		/* Update the number of bytes transferred in this ISO packet */
-		transaction->iso_packets[0].length = transaction->actual_bytes;
-		transaction->iso_packets[0].status = complete_code;
-
-		/*
-		 * If there are more ISOs pending and we succeeded, schedule the
-		 * next one
-		 */
-		if ((transaction->iso_number_packets > 1) && (complete_code == CVMX_USB_COMPLETE_SUCCESS)) {
-			transaction->actual_bytes = 0;	   /* No bytes transferred for this packet as of yet */
-			transaction->iso_number_packets--; /* One less ISO waiting to transfer */
-			transaction->iso_packets++;	   /* Increment to the next location in our packet array */
-			transaction->stage = CVMX_USB_STAGE_NON_CONTROL;
-			goto done;
-		}
-	}
-
-	/* Remove the transaction from the pipe list */
-	if (transaction->next)
-		transaction->next->prev = transaction->prev;
-	else
-		pipe->tail = transaction->prev;
-	if (transaction->prev)
-		transaction->prev->next = transaction->next;
-	else
-		pipe->head = transaction->next;
-	if (!pipe->head) {
-		__cvmx_usb_remove_pipe(usb->active_pipes + pipe->transfer_type, pipe);
-		__cvmx_usb_append_pipe(&usb->idle_pipes, pipe);
-
-	}
-	__cvmx_usb_perform_callback(usb, pipe, transaction,
-				    CVMX_USB_CALLBACK_TRANSFER_COMPLETE,
-				    complete_code);
-	__cvmx_usb_free_transaction(usb, transaction);
-done:
-	return;
-}
-
-
-/**
- * Submit a usb transaction to a pipe. Called for all types
- * of transactions.
- *
- * @usb:
- * @pipe_handle:
- *		    Which pipe to submit to. Will be validated in this function.
- * @type:	    Transaction type
- * @flags:	    Flags for the transaction
- * @buffer:	    User buffer for the transaction
- * @buffer_length:
- *		    User buffer's length in bytes
- * @control_header:
- *		    For control transactions, the 8 byte standard header
- * @iso_start_frame:
- *		    For ISO transactions, the start frame
- * @iso_number_packets:
- *		    For ISO, the number of packet in the transaction.
- * @iso_packets:
- *		    A description of each ISO packet
- * @callback:	    User callback to call when the transaction completes
- * @user_data:	    User's data for the callback
- *
- * Returns: Submit handle or negative on failure. Matches the result
- *	    in the external API.
- */
-static int __cvmx_usb_submit_transaction(struct cvmx_usb_internal_state *usb,
-					 int pipe_handle,
-					 enum cvmx_usb_transfer type,
-					 int flags,
-					 uint64_t buffer,
-					 int buffer_length,
-					 uint64_t control_header,
-					 int iso_start_frame,
-					 int iso_number_packets,
-					 struct cvmx_usb_iso_packet *iso_packets,
-					 cvmx_usb_callback_func_t callback,
-					 void *user_data)
-{
-	int submit_handle;
-	struct cvmx_usb_transaction *transaction;
-	struct cvmx_usb_pipe *pipe = usb->pipe + pipe_handle;
-
-	if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES)))
-		return -EINVAL;
-	/* Fail if the pipe isn't open */
-	if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0))
-		return -EINVAL;
-	if (unlikely(pipe->transfer_type != type))
-		return -EINVAL;
-
-	transaction = __cvmx_usb_alloc_transaction(usb);
-	if (unlikely(!transaction))
-		return -ENOMEM;
-
-	transaction->type = type;
-	transaction->flags |= flags;
-	transaction->buffer = buffer;
-	transaction->buffer_length = buffer_length;
-	transaction->control_header = control_header;
-	transaction->iso_start_frame = iso_start_frame; // FIXME: This is not used, implement it
-	transaction->iso_number_packets = iso_number_packets;
-	transaction->iso_packets = iso_packets;
-	transaction->callback = callback;
-	transaction->callback_data = user_data;
-	if (transaction->type == CVMX_USB_TRANSFER_CONTROL)
-		transaction->stage = CVMX_USB_STAGE_SETUP;
-	else
-		transaction->stage = CVMX_USB_STAGE_NON_CONTROL;
-
-	transaction->next = NULL;
-	if (pipe->tail) {
-		transaction->prev = pipe->tail;
-		transaction->prev->next = transaction;
-	} else {
-		if (pipe->next_tx_frame < usb->frame_number)
-			pipe->next_tx_frame = usb->frame_number + pipe->interval -
-				(usb->frame_number - pipe->next_tx_frame) % pipe->interval;
-		transaction->prev = NULL;
-		pipe->head = transaction;
-		__cvmx_usb_remove_pipe(&usb->idle_pipes, pipe);
-		__cvmx_usb_append_pipe(usb->active_pipes + pipe->transfer_type, pipe);
-	}
-	pipe->tail = transaction;
-
-	submit_handle = __cvmx_usb_get_submit_handle(usb, transaction);
-
-	/* We may need to schedule the pipe if this was the head of the pipe */
-	if (!transaction->prev)
-		__cvmx_usb_schedule(usb, 0);
-
-	return submit_handle;
-}
-
-
-/**
- * Call to submit a USB Bulk transfer to a pipe.
- *
- * @state:	    USB device state populated by
- *		    cvmx_usb_initialize().
- * @pipe_handle:
- *		    Handle to the pipe for the transfer.
- * @buffer:	    Physical address of the data buffer in
- *		    memory. Note that this is NOT A POINTER, but
- *		    the full 64bit physical address of the
- *		    buffer. This may be zero if buffer_length is
- *		    zero.
- * @buffer_length:
- *		    Length of buffer in bytes.
- * @callback:	    Function to call when this transaction
- *		    completes. If the return value of this
- *		    function isn't an error, then this function
- *		    is guaranteed to be called when the
- *		    transaction completes. If this parameter is
- *		    NULL, then the generic callback registered
- *		    through cvmx_usb_register_callback is
- *		    called. If both are NULL, then there is no
- *		    way to know when a transaction completes.
- * @user_data:	    User supplied data returned when the
- *		    callback is called. This is only used if
- *		    callback in not NULL.
- *
- * Returns: A submitted transaction handle or negative on
- *	    failure. Negative values are error codes.
- */
-int cvmx_usb_submit_bulk(struct cvmx_usb_state *state, int pipe_handle,
-			 uint64_t buffer, int buffer_length,
-			 cvmx_usb_callback_func_t callback,
-			 void *user_data)
-{
-	int submit_handle;
-	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
-
-	/* Pipe handle checking is done later in a common place */
-	if (unlikely(!buffer))
-		return -EINVAL;
-	if (unlikely(buffer_length < 0))
-		return -EINVAL;
-
-	submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle,
-						      CVMX_USB_TRANSFER_BULK,
-						      0, /* flags */
-						      buffer,
-						      buffer_length,
-						      0, /* control_header */
-						      0, /* iso_start_frame */
-						      0, /* iso_number_packets */
-						      NULL, /* iso_packets */
-						      callback,
-						      user_data);
-	return submit_handle;
-}
-
-
-/**
- * Call to submit a USB Interrupt transfer to a pipe.
- *
- * @state:	    USB device state populated by
- *		    cvmx_usb_initialize().
- * @pipe_handle:
- *		    Handle to the pipe for the transfer.
- * @buffer:	    Physical address of the data buffer in
- *		    memory. Note that this is NOT A POINTER, but
- *		    the full 64bit physical address of the
- *		    buffer. This may be zero if buffer_length is
- *		    zero.
- * @buffer_length:
- *		    Length of buffer in bytes.
- * @callback:	    Function to call when this transaction
- *		    completes. If the return value of this
- *		    function isn't an error, then this function
- *		    is guaranteed to be called when the
- *		    transaction completes. If this parameter is
- *		    NULL, then the generic callback registered
- *		    through cvmx_usb_register_callback is
- *		    called. If both are NULL, then there is no
- *		    way to know when a transaction completes.
- * @user_data:	    User supplied data returned when the
- *		    callback is called. This is only used if
- *		    callback in not NULL.
- *
- * Returns: A submitted transaction handle or negative on
- *	    failure. Negative values are error codes.
- */
-int cvmx_usb_submit_interrupt(struct cvmx_usb_state *state, int pipe_handle,
-			      uint64_t buffer, int buffer_length,
-			      cvmx_usb_callback_func_t callback,
-			      void *user_data)
-{
-	int submit_handle;
-	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
-
-	/* Pipe handle checking is done later in a common place */
-	if (unlikely(!buffer))
-		return -EINVAL;
-	if (unlikely(buffer_length < 0))
-		return -EINVAL;
-
-	submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle,
-						      CVMX_USB_TRANSFER_INTERRUPT,
-						      0, /* flags */
-						      buffer,
-						      buffer_length,
-						      0, /* control_header */
-						      0, /* iso_start_frame */
-						      0, /* iso_number_packets */
-						      NULL, /* iso_packets */
-						      callback,
-						      user_data);
-	return submit_handle;
-}
-
-
-/**
- * Call to submit a USB Control transfer to a pipe.
- *
- * @state:	    USB device state populated by
- *		    cvmx_usb_initialize().
- * @pipe_handle:
- *		    Handle to the pipe for the transfer.
- * @control_header:
- *		    USB 8 byte control header physical address.
- *		    Note that this is NOT A POINTER, but the
- *		    full 64bit physical address of the buffer.
- * @buffer:	    Physical address of the data buffer in
- *		    memory. Note that this is NOT A POINTER, but
- *		    the full 64bit physical address of the
- *		    buffer. This may be zero if buffer_length is
- *		    zero.
- * @buffer_length:
- *		    Length of buffer in bytes.
- * @callback:	    Function to call when this transaction
- *		    completes. If the return value of this
- *		    function isn't an error, then this function
- *		    is guaranteed to be called when the
- *		    transaction completes. If this parameter is
- *		    NULL, then the generic callback registered
- *		    through cvmx_usb_register_callback is
- *		    called. If both are NULL, then there is no
- *		    way to know when a transaction completes.
- * @user_data:	    User supplied data returned when the
- *		    callback is called. This is only used if
- *		    callback in not NULL.
- *
- * Returns: A submitted transaction handle or negative on
- *	    failure. Negative values are error codes.
- */
-int cvmx_usb_submit_control(struct cvmx_usb_state *state, int pipe_handle,
-			    uint64_t control_header,
-			    uint64_t buffer, int buffer_length,
-			    cvmx_usb_callback_func_t callback,
-			    void *user_data)
-{
-	int submit_handle;
-	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
-	union cvmx_usb_control_header *header =
-		cvmx_phys_to_ptr(control_header);
-
-	/* Pipe handle checking is done later in a common place */
-	if (unlikely(!control_header))
-		return -EINVAL;
-	/* Some drivers send a buffer with a zero length. God only knows why */
-	if (unlikely(buffer && (buffer_length < 0)))
-		return -EINVAL;
-	if (unlikely(!buffer && (buffer_length != 0)))
-		return -EINVAL;
-	if ((header->s.request_type & 0x80) == 0)
-		buffer_length = le16_to_cpu(header->s.length);
-
-	submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle,
-						      CVMX_USB_TRANSFER_CONTROL,
-						      0, /* flags */
-						      buffer,
-						      buffer_length,
-						      control_header,
-						      0, /* iso_start_frame */
-						      0, /* iso_number_packets */
-						      NULL, /* iso_packets */
-						      callback,
-						      user_data);
-	return submit_handle;
-}
-
-
-/**
- * Call to submit a USB Isochronous transfer to a pipe.
- *
- * @state:	    USB device state populated by
- *		    cvmx_usb_initialize().
- * @pipe_handle:
- *		    Handle to the pipe for the transfer.
- * @start_frame:
- *		    Number of frames into the future to schedule
- *		    this transaction.
- * @flags:	    Flags to control the transfer. See
- *		    enum cvmx_usb_isochronous_flags for the flag
- *		    definitions.
- * @number_packets:
- *		    Number of sequential packets to transfer.
- *		    "packets" is a pointer to an array of this
- *		    many packet structures.
- * @packets:	    Description of each transfer packet as
- *		    defined by struct cvmx_usb_iso_packet. The array
- *		    pointed to here must stay valid until the
- *		    complete callback is called.
- * @buffer:	    Physical address of the data buffer in
- *		    memory. Note that this is NOT A POINTER, but
- *		    the full 64bit physical address of the
- *		    buffer. This may be zero if buffer_length is
- *		    zero.
- * @buffer_length:
- *		    Length of buffer in bytes.
- * @callback:	    Function to call when this transaction
- *		    completes. If the return value of this
- *		    function isn't an error, then this function
- *		    is guaranteed to be called when the
- *		    transaction completes. If this parameter is
- *		    NULL, then the generic callback registered
- *		    through cvmx_usb_register_callback is
- *		    called. If both are NULL, then there is no
- *		    way to know when a transaction completes.
- * @user_data:	    User supplied data returned when the
- *		    callback is called. This is only used if
- *		    callback in not NULL.
- *
- * Returns: A submitted transaction handle or negative on
- *	    failure. Negative values are error codes.
- */
-int cvmx_usb_submit_isochronous(struct cvmx_usb_state *state, int pipe_handle,
-				int start_frame, int flags,
-				int number_packets,
-				struct cvmx_usb_iso_packet packets[],
-				uint64_t buffer, int buffer_length,
-				cvmx_usb_callback_func_t callback,
-				void *user_data)
-{
-	int submit_handle;
-	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
-
-	/* Pipe handle checking is done later in a common place */
-	if (unlikely(start_frame < 0))
-		return -EINVAL;
-	if (unlikely(flags & ~(CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT | CVMX_USB_ISOCHRONOUS_FLAGS_ASAP)))
-		return -EINVAL;
-	if (unlikely(number_packets < 1))
-		return -EINVAL;
-	if (unlikely(!packets))
-		return -EINVAL;
-	if (unlikely(!buffer))
-		return -EINVAL;
-	if (unlikely(buffer_length < 0))
-		return -EINVAL;
-
-	submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle,
-						      CVMX_USB_TRANSFER_ISOCHRONOUS,
-						      flags,
-						      buffer,
-						      buffer_length,
-						      0, /* control_header */
-						      start_frame,
-						      number_packets,
-						      packets,
-						      callback,
-						      user_data);
-	return submit_handle;
-}
-
-
-/**
- * Cancel one outstanding request in a pipe. Canceling a request
- * can fail if the transaction has already completed before cancel
- * is called. Even after a successful cancel call, it may take
- * a frame or two for the cvmx_usb_poll() function to call the
- * associated callback.
- *
- * @state:	 USB device state populated by
- *		 cvmx_usb_initialize().
- * @pipe_handle:
- *		 Pipe handle to cancel requests in.
- * @submit_handle:
- *		 Handle to transaction to cancel, returned by the submit function.
- *
- * Returns: 0 or a negative error code.
- */
-int cvmx_usb_cancel(struct cvmx_usb_state *state, int pipe_handle, int submit_handle)
-{
-	struct cvmx_usb_transaction *transaction;
-	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
-	struct cvmx_usb_pipe *pipe = usb->pipe + pipe_handle;
-
-	if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES)))
-		return -EINVAL;
-	if (unlikely((submit_handle < 0) || (submit_handle >= MAX_TRANSACTIONS)))
-		return -EINVAL;
-
-	/* Fail if the pipe isn't open */
-	if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0))
-		return -EINVAL;
-
-	transaction = usb->transaction + submit_handle;
-
-	/* Fail if this transaction already completed */
-	if (unlikely((transaction->flags & __CVMX_USB_TRANSACTION_FLAGS_IN_USE) == 0))
-		return -EINVAL;
-
-	/*
-	 * If the transaction is the HEAD of the queue and scheduled. We need to
-	 * treat it special
-	 */
-	if ((pipe->head == transaction) &&
-		(pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED)) {
-		union cvmx_usbcx_hccharx usbc_hcchar;
-
-		usb->pipe_for_channel[pipe->channel] = NULL;
-		pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_SCHEDULED;
-
-		CVMX_SYNCW;
-
-		usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(pipe->channel, usb->index));
-		/* If the channel isn't enabled then the transaction already completed */
-		if (usbc_hcchar.s.chena) {
-			usbc_hcchar.s.chdis = 1;
-			__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(pipe->channel, usb->index), usbc_hcchar.u32);
-		}
-	}
-	__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_CANCEL);
-	return 0;
-}
-
-
-/**
- * Cancel all outstanding requests in a pipe. Logically all this
- * does is call cvmx_usb_cancel() in a loop.
- *
- * @state:	 USB device state populated by
- *		 cvmx_usb_initialize().
- * @pipe_handle:
- *		 Pipe handle to cancel requests in.
- *
- * Returns: 0 or a negative error code.
- */
-int cvmx_usb_cancel_all(struct cvmx_usb_state *state, int pipe_handle)
-{
-	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
-	struct cvmx_usb_pipe *pipe = usb->pipe + pipe_handle;
-
-	if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES)))
-		return -EINVAL;
-
-	/* Fail if the pipe isn't open */
-	if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0))
-		return -EINVAL;
-
-	/* Simply loop through and attempt to cancel each transaction */
-	while (pipe->head) {
-		int result = cvmx_usb_cancel(state, pipe_handle,
-			__cvmx_usb_get_submit_handle(usb, pipe->head));
-		if (unlikely(result != 0))
-			return result;
-	}
-	return 0;
-}
-
-
-/**
- * Close a pipe created with cvmx_usb_open_pipe().
- *
- * @state:	 USB device state populated by
- *		 cvmx_usb_initialize().
- * @pipe_handle:
- *		 Pipe handle to close.
- *
- * Returns: 0 or a negative error code. EBUSY is returned if the pipe has
- *	    outstanding transfers.
- */
-int cvmx_usb_close_pipe(struct cvmx_usb_state *state, int pipe_handle)
-{
-	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
-	struct cvmx_usb_pipe *pipe = usb->pipe + pipe_handle;
-
-	if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES)))
-		return -EINVAL;
-
-	/* Fail if the pipe isn't open */
-	if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0))
-		return -EINVAL;
-
-	/* Fail if the pipe has pending transactions */
-	if (unlikely(pipe->head))
-		return -EBUSY;
-
-	pipe->flags = 0;
-	__cvmx_usb_remove_pipe(&usb->idle_pipes, pipe);
-	__cvmx_usb_append_pipe(&usb->free_pipes, pipe);
-
-	return 0;
-}
-
-
-/**
- * Register a function to be called when various USB events occur.
- *
- * @state:     USB device state populated by
- *	       cvmx_usb_initialize().
- * @reason:    Which event to register for.
- * @callback:  Function to call when the event occurs.
- * @user_data: User data parameter to the function.
- *
- * Returns: 0 or a negative error code.
- */
-int cvmx_usb_register_callback(struct cvmx_usb_state *state,
-			       enum cvmx_usb_callback reason,
-			       cvmx_usb_callback_func_t callback,
-			       void *user_data)
-{
-	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
-
-	if (unlikely(reason >= __CVMX_USB_CALLBACK_END))
-		return -EINVAL;
-	if (unlikely(!callback))
-		return -EINVAL;
-
-	usb->callback[reason] = callback;
-	usb->callback_data[reason] = user_data;
-
-	return 0;
-}
-
-
-/**
- * Get the current USB protocol level frame number. The frame
- * number is always in the range of 0-0x7ff.
- *
- * @state: USB device state populated by
- *	   cvmx_usb_initialize().
- *
- * Returns: USB frame number
- */
-int cvmx_usb_get_frame_number(struct cvmx_usb_state *state)
-{
-	int frame_number;
-	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
-	union cvmx_usbcx_hfnum usbc_hfnum;
-
-	usbc_hfnum.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index));
-	frame_number = usbc_hfnum.s.frnum;
-
-	return frame_number;
-}
-
-
-/**
- * Poll a channel for status
- *
- * @usb:     USB device
- * @channel: Channel to poll
- *
- * Returns: Zero on success
- */
-static int __cvmx_usb_poll_channel(struct cvmx_usb_internal_state *usb, int channel)
-{
-	union cvmx_usbcx_hcintx usbc_hcint;
-	union cvmx_usbcx_hctsizx usbc_hctsiz;
-	union cvmx_usbcx_hccharx usbc_hcchar;
-	struct cvmx_usb_pipe *pipe;
-	struct cvmx_usb_transaction *transaction;
-	int bytes_this_transfer;
-	int bytes_in_last_packet;
-	int packets_processed;
-	int buffer_space_left;
-
-	/* Read the interrupt status bits for the channel */
-	usbc_hcint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCINTX(channel, usb->index));
-
-	if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) {
-		usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index));
-
-		if (usbc_hcchar.s.chena && usbc_hcchar.s.chdis) {
-			/*
-			 * There seems to be a bug in CN31XX which can cause
-			 * interrupt IN transfers to get stuck until we do a
-			 * write of HCCHARX without changing things
-			 */
-			__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32);
-			return 0;
-		}
-
-		/*
-		 * In non DMA mode the channels don't halt themselves. We need
-		 * to manually disable channels that are left running
-		 */
-		if (!usbc_hcint.s.chhltd) {
-			if (usbc_hcchar.s.chena) {
-				union cvmx_usbcx_hcintmskx hcintmsk;
-				/* Disable all interrupts except CHHLTD */
-				hcintmsk.u32 = 0;
-				hcintmsk.s.chhltdmsk = 1;
-				__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), hcintmsk.u32);
-				usbc_hcchar.s.chdis = 1;
-				__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32);
-				return 0;
-			} else if (usbc_hcint.s.xfercompl) {
-				/* Successful IN/OUT with transfer complete. Channel halt isn't needed */
-			} else {
-				cvmx_dprintf("USB%d: Channel %d interrupt without halt\n", usb->index, channel);
-				return 0;
-			}
-		}
-	} else {
-		/*
-		 * There is are no interrupts that we need to process when the
-		 * channel is still running
-		 */
-		if (!usbc_hcint.s.chhltd)
-			return 0;
-	}
-
-	/* Disable the channel interrupts now that it is done */
-	__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), 0);
-	usb->idle_hardware_channels |= (1<<channel);
-
-	/* Make sure this channel is tied to a valid pipe */
-	pipe = usb->pipe_for_channel[channel];
-	CVMX_PREFETCH(pipe, 0);
-	CVMX_PREFETCH(pipe, 128);
-	if (!pipe)
-		return 0;
-	transaction = pipe->head;
-	CVMX_PREFETCH0(transaction);
-
-	/*
-	 * Disconnect this pipe from the HW channel. Later the schedule
-	 * function will figure out which pipe needs to go
-	 */
-	usb->pipe_for_channel[channel] = NULL;
-	pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_SCHEDULED;
-
-	/*
-	 * Read the channel config info so we can figure out how much data
-	 * transfered
-	 */
-	usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index));
-	usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index));
-
-	/*
-	 * Calculating the number of bytes successfully transferred is dependent
-	 * on the transfer direction
-	 */
-	packets_processed = transaction->pktcnt - usbc_hctsiz.s.pktcnt;
-	if (usbc_hcchar.s.epdir) {
-		/*
-		 * IN transactions are easy. For every byte received the
-		 * hardware decrements xfersize. All we need to do is subtract
-		 * the current value of xfersize from its starting value and we
-		 * know how many bytes were written to the buffer
-		 */
-		bytes_this_transfer = transaction->xfersize - usbc_hctsiz.s.xfersize;
-	} else {
-		/*
-		 * OUT transaction don't decrement xfersize. Instead pktcnt is
-		 * decremented on every successful packet send. The hardware
-		 * does this when it receives an ACK, or NYET. If it doesn't
-		 * receive one of these responses pktcnt doesn't change
-		 */
-		bytes_this_transfer = packets_processed * usbc_hcchar.s.mps;
-		/*
-		 * The last packet may not be a full transfer if we didn't have
-		 * enough data
-		 */
-		if (bytes_this_transfer > transaction->xfersize)
-			bytes_this_transfer = transaction->xfersize;
-	}
-	/* Figure out how many bytes were in the last packet of the transfer */
-	if (packets_processed)
-		bytes_in_last_packet = bytes_this_transfer - (packets_processed-1) * usbc_hcchar.s.mps;
-	else
-		bytes_in_last_packet = bytes_this_transfer;
-
-	/*
-	 * As a special case, setup transactions output the setup header, not
-	 * the user's data. For this reason we don't count setup data as bytes
-	 * transferred
-	 */
-	if ((transaction->stage == CVMX_USB_STAGE_SETUP) ||
-		(transaction->stage == CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE))
-		bytes_this_transfer = 0;
-
-	/*
-	 * Add the bytes transferred to the running total. It is important that
-	 * bytes_this_transfer doesn't count any data that needs to be
-	 * retransmitted
-	 */
-	transaction->actual_bytes += bytes_this_transfer;
-	if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)
-		buffer_space_left = transaction->iso_packets[0].length - transaction->actual_bytes;
-	else
-		buffer_space_left = transaction->buffer_length - transaction->actual_bytes;
-
-	/*
-	 * We need to remember the PID toggle state for the next transaction.
-	 * The hardware already updated it for the next transaction
-	 */
-	pipe->pid_toggle = !(usbc_hctsiz.s.pid == 0);
-
-	/*
-	 * For high speed bulk out, assume the next transaction will need to do
-	 * a ping before proceeding. If this isn't true the ACK processing below
-	 * will clear this flag
-	 */
-	if ((pipe->device_speed == CVMX_USB_SPEED_HIGH) &&
-		(pipe->transfer_type == CVMX_USB_TRANSFER_BULK) &&
-		(pipe->transfer_dir == CVMX_USB_DIRECTION_OUT))
-		pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING;
-
-	if (usbc_hcint.s.stall) {
-		/*
-		 * STALL as a response means this transaction cannot be
-		 * completed because the device can't process transactions. Tell
-		 * the user. Any data that was transferred will be counted on
-		 * the actual bytes transferred
-		 */
-		pipe->pid_toggle = 0;
-		__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_STALL);
-	} else if (usbc_hcint.s.xacterr) {
-		/*
-		 * We know at least one packet worked if we get a ACK or NAK.
-		 * Reset the retry counter
-		 */
-		if (usbc_hcint.s.nak || usbc_hcint.s.ack)
-			transaction->retries = 0;
-		transaction->retries++;
-		if (transaction->retries > MAX_RETRIES) {
-			/*
-			 * XactErr as a response means the device signaled
-			 * something wrong with the transfer. For example, PID
-			 * toggle errors cause these
-			 */
-			__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_XACTERR);
-		} else {
-			/*
-			 * If this was a split then clear our split in progress
-			 * marker
-			 */
-			if (usb->active_split == transaction)
-				usb->active_split = NULL;
-			/*
-			 * Rewind to the beginning of the transaction by anding
-			 * off the split complete bit
-			 */
-			transaction->stage &= ~1;
-			pipe->split_sc_frame = -1;
-			pipe->next_tx_frame += pipe->interval;
-			if (pipe->next_tx_frame < usb->frame_number)
-				pipe->next_tx_frame = usb->frame_number + pipe->interval -
-						      (usb->frame_number - pipe->next_tx_frame) % pipe->interval;
-		}
-	} else if (usbc_hcint.s.bblerr) {
-		/* Babble Error (BblErr) */
-		__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_BABBLEERR);
-	} else if (usbc_hcint.s.datatglerr) {
-		/* We'll retry the exact same transaction again */
-		transaction->retries++;
-	} else if (usbc_hcint.s.nyet) {
-		/*
-		 * NYET as a response is only allowed in three cases: as a
-		 * response to a ping, as a response to a split transaction, and
-		 * as a response to a bulk out. The ping case is handled by
-		 * hardware, so we only have splits and bulk out
-		 */
-		if (!__cvmx_usb_pipe_needs_split(usb, pipe)) {
-			transaction->retries = 0;
-			/*
-			 * If there is more data to go then we need to try
-			 * again. Otherwise this transaction is complete
-			 */
-			if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet))
-				__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
-		} else {
-			/*
-			 * Split transactions retry the split complete 4 times
-			 * then rewind to the start split and do the entire
-			 * transactions again
-			 */
-			transaction->retries++;
-			if ((transaction->retries & 0x3) == 0) {
-				/*
-				 * Rewind to the beginning of the transaction by
-				 * anding off the split complete bit
-				 */
-				transaction->stage &= ~1;
-				pipe->split_sc_frame = -1;
-			}
-		}
-	} else if (usbc_hcint.s.ack) {
-		transaction->retries = 0;
-		/*
-		 * The ACK bit can only be checked after the other error bits.
-		 * This is because a multi packet transfer may succeed in a
-		 * number of packets and then get a different response on the
-		 * last packet. In this case both ACK and the last response bit
-		 * will be set. If none of the other response bits is set, then
-		 * the last packet must have been an ACK
-		 *
-		 * Since we got an ACK, we know we don't need to do a ping on
-		 * this pipe
-		 */
-		pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_NEED_PING;
-
-		switch (transaction->type) {
-		case CVMX_USB_TRANSFER_CONTROL:
-			switch (transaction->stage) {
-			case CVMX_USB_STAGE_NON_CONTROL:
-			case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE:
-				/* This should be impossible */
-				__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_ERROR);
-				break;
-			case CVMX_USB_STAGE_SETUP:
-				pipe->pid_toggle = 1;
-				if (__cvmx_usb_pipe_needs_split(usb, pipe))
-					transaction->stage = CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE;
-				else {
-					union cvmx_usb_control_header *header =
-						cvmx_phys_to_ptr(transaction->control_header);
-					if (header->s.length)
-						transaction->stage = CVMX_USB_STAGE_DATA;
-					else
-						transaction->stage = CVMX_USB_STAGE_STATUS;
-				}
-				break;
-			case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE:
-				{
-					union cvmx_usb_control_header *header =
-						cvmx_phys_to_ptr(transaction->control_header);
-					if (header->s.length)
-						transaction->stage = CVMX_USB_STAGE_DATA;
-					else
-						transaction->stage = CVMX_USB_STAGE_STATUS;
-				}
-				break;
-			case CVMX_USB_STAGE_DATA:
-				if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
-					transaction->stage = CVMX_USB_STAGE_DATA_SPLIT_COMPLETE;
-					/*
-					 * For setup OUT data that are splits,
-					 * the hardware doesn't appear to count
-					 * transferred data. Here we manually
-					 * update the data transferred
-					 */
-					if (!usbc_hcchar.s.epdir) {
-						if (buffer_space_left < pipe->max_packet)
-							transaction->actual_bytes += buffer_space_left;
-						else
-							transaction->actual_bytes += pipe->max_packet;
-					}
-				} else if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) {
-					pipe->pid_toggle = 1;
-					transaction->stage = CVMX_USB_STAGE_STATUS;
-				}
-				break;
-			case CVMX_USB_STAGE_DATA_SPLIT_COMPLETE:
-				if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) {
-					pipe->pid_toggle = 1;
-					transaction->stage = CVMX_USB_STAGE_STATUS;
-				} else {
-					transaction->stage = CVMX_USB_STAGE_DATA;
-				}
-				break;
-			case CVMX_USB_STAGE_STATUS:
-				if (__cvmx_usb_pipe_needs_split(usb, pipe))
-					transaction->stage = CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE;
-				else
-					__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
-				break;
-			case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE:
-				__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
-				break;
-			}
-			break;
-		case CVMX_USB_TRANSFER_BULK:
-		case CVMX_USB_TRANSFER_INTERRUPT:
-			/*
-			 * The only time a bulk transfer isn't complete when it
-			 * finishes with an ACK is during a split transaction.
-			 * For splits we need to continue the transfer if more
-			 * data is needed
-			 */
-			if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
-				if (transaction->stage == CVMX_USB_STAGE_NON_CONTROL)
-					transaction->stage = CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE;
-				else {
-					if (buffer_space_left && (bytes_in_last_packet == pipe->max_packet))
-						transaction->stage = CVMX_USB_STAGE_NON_CONTROL;
-					else {
-						if (transaction->type == CVMX_USB_TRANSFER_INTERRUPT)
-							pipe->next_tx_frame += pipe->interval;
-							__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
-					}
-				}
-			} else {
-				if ((pipe->device_speed == CVMX_USB_SPEED_HIGH) &&
-				    (pipe->transfer_type == CVMX_USB_TRANSFER_BULK) &&
-				    (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) &&
-				    (usbc_hcint.s.nak))
-					pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING;
-				if (!buffer_space_left || (bytes_in_last_packet < pipe->max_packet)) {
-					if (transaction->type == CVMX_USB_TRANSFER_INTERRUPT)
-						pipe->next_tx_frame += pipe->interval;
-					__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
-				}
-			}
-			break;
-		case CVMX_USB_TRANSFER_ISOCHRONOUS:
-			if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
-				/*
-				 * ISOCHRONOUS OUT splits don't require a
-				 * complete split stage. Instead they use a
-				 * sequence of begin OUT splits to transfer the
-				 * data 188 bytes at a time. Once the transfer
-				 * is complete, the pipe sleeps until the next
-				 * schedule interval
-				 */
-				if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) {
-					/*
-					 * If no space left or this wasn't a max
-					 * size packet then this transfer is
-					 * complete. Otherwise start it again to
-					 * send the next 188 bytes
-					 */
-					if (!buffer_space_left || (bytes_this_transfer < 188)) {
-						pipe->next_tx_frame += pipe->interval;
-						__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
-					}
-				} else {
-					if (transaction->stage == CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE) {
-						/*
-						 * We are in the incoming data
-						 * phase. Keep getting data
-						 * until we run out of space or
-						 * get a small packet
-						 */
-						if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) {
-							pipe->next_tx_frame += pipe->interval;
-							__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
-						}
-					} else
-						transaction->stage = CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE;
-				}
-			} else {
-				pipe->next_tx_frame += pipe->interval;
-				__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
-			}
-			break;
-		}
-	} else if (usbc_hcint.s.nak) {
-		/* If this was a split then clear our split in progress marker */
-		if (usb->active_split == transaction)
-			usb->active_split = NULL;
-		/*
-		 * NAK as a response means the device couldn't accept the
-		 * transaction, but it should be retried in the future. Rewind
-		 * to the beginning of the transaction by anding off the split
-		 * complete bit. Retry in the next interval
-		 */
-		transaction->retries = 0;
-		transaction->stage &= ~1;
-		pipe->next_tx_frame += pipe->interval;
-		if (pipe->next_tx_frame < usb->frame_number)
-			pipe->next_tx_frame = usb->frame_number + pipe->interval -
-				(usb->frame_number - pipe->next_tx_frame) % pipe->interval;
-	} else {
-		struct cvmx_usb_port_status port;
-		port = cvmx_usb_get_status((struct cvmx_usb_state *)usb);
-		if (port.port_enabled) {
-			/* We'll retry the exact same transaction again */
-			transaction->retries++;
-		} else {
-			/*
-			 * We get channel halted interrupts with no result bits
-			 * sets when the cable is unplugged
-			 */
-			__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_ERROR);
-		}
-	}
-	return 0;
-}
-
-
-/**
- * Poll the USB block for status and call all needed callback
- * handlers. This function is meant to be called in the interrupt
- * handler for the USB controller. It can also be called
- * periodically in a loop for non-interrupt based operation.
- *
- * @state:	USB device state populated by
- *		cvmx_usb_initialize().
- *
- * Returns: 0 or a negative error code.
- */
-int cvmx_usb_poll(struct cvmx_usb_state *state)
-{
-	union cvmx_usbcx_hfnum usbc_hfnum;
-	union cvmx_usbcx_gintsts usbc_gintsts;
-	struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state;
-
-	CVMX_PREFETCH(usb, 0);
-	CVMX_PREFETCH(usb, 1*128);
-	CVMX_PREFETCH(usb, 2*128);
-	CVMX_PREFETCH(usb, 3*128);
-	CVMX_PREFETCH(usb, 4*128);
-
-	/* Update the frame counter */
-	usbc_hfnum.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index));
-	if ((usb->frame_number&0x3fff) > usbc_hfnum.s.frnum)
-		usb->frame_number += 0x4000;
-	usb->frame_number &= ~0x3fffull;
-	usb->frame_number |= usbc_hfnum.s.frnum;
-
-	/* Read the pending interrupts */
-	usbc_gintsts.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GINTSTS(usb->index));
-
-	/* Clear the interrupts now that we know about them */
-	__cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTSTS(usb->index), usbc_gintsts.u32);
-
-	if (usbc_gintsts.s.rxflvl) {
-		/*
-		 * RxFIFO Non-Empty (RxFLvl)
-		 * Indicates that there is at least one packet pending to be
-		 * read from the RxFIFO.
-		 *
-		 * In DMA mode this is handled by hardware
-		 */
-		if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
-			__cvmx_usb_poll_rx_fifo(usb);
-	}
-	if (usbc_gintsts.s.ptxfemp || usbc_gintsts.s.nptxfemp) {
-		/* Fill the Tx FIFOs when not in DMA mode */
-		if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
-			__cvmx_usb_poll_tx_fifo(usb);
-	}
-	if (usbc_gintsts.s.disconnint || usbc_gintsts.s.prtint) {
-		union cvmx_usbcx_hprt usbc_hprt;
-		/*
-		 * Disconnect Detected Interrupt (DisconnInt)
-		 * Asserted when a device disconnect is detected.
-		 *
-		 * Host Port Interrupt (PrtInt)
-		 * The core sets this bit to indicate a change in port status of
-		 * one of the O2P USB core ports in Host mode. The application
-		 * must read the Host Port Control and Status (HPRT) register to
-		 * determine the exact event that caused this interrupt. The
-		 * application must clear the appropriate status bit in the Host
-		 * Port Control and Status register to clear this bit.
-		 *
-		 * Call the user's port callback
-		 */
-		__cvmx_usb_perform_callback(usb, NULL, NULL,
-					    CVMX_USB_CALLBACK_PORT_CHANGED,
-					    CVMX_USB_COMPLETE_SUCCESS);
-		/* Clear the port change bits */
-		usbc_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
-		usbc_hprt.s.prtena = 0;
-		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HPRT(usb->index), usbc_hprt.u32);
-	}
-	if (usbc_gintsts.s.hchint) {
-		/*
-		 * Host Channels Interrupt (HChInt)
-		 * The core sets this bit to indicate that an interrupt is
-		 * pending on one of the channels of the core (in Host mode).
-		 * The application must read the Host All Channels Interrupt
-		 * (HAINT) register to determine the exact number of the channel
-		 * on which the interrupt occurred, and then read the
-		 * corresponding Host Channel-n Interrupt (HCINTn) register to
-		 * determine the exact cause of the interrupt. The application
-		 * must clear the appropriate status bit in the HCINTn register
-		 * to clear this bit.
-		 */
-		union cvmx_usbcx_haint usbc_haint;
-		usbc_haint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HAINT(usb->index));
-		while (usbc_haint.u32) {
-			int channel;
-			CVMX_CLZ(channel, usbc_haint.u32);
-			channel = 31 - channel;
-			__cvmx_usb_poll_channel(usb, channel);
-			usbc_haint.u32 ^= 1<<channel;
-		}
-	}
-
-	__cvmx_usb_schedule(usb, usbc_gintsts.s.sof);
-
-	return 0;
-}
diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h
deleted file mode 100644
index 8bf3696..0000000
--- a/drivers/staging/octeon-usb/cvmx-usb.h
+++ /dev/null
@@ -1,542 +0,0 @@
-/***********************license start***************
- * Copyright (c) 2003-2010  Cavium Networks (support@cavium.com). All rights
- * reserved.
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *   * Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *
- *   * Redistributions in binary form must reproduce the above
- *     copyright notice, this list of conditions and the following
- *     disclaimer in the documentation and/or other materials provided
- *     with the distribution.
-
- *   * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export  control
- * laws, including the U.S. Export Administration Act and its  associated
- * regulations, and may be subject to export or import  regulations in other
- * countries.
-
- * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM  NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
- * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
- * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
- * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
- * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
- * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
- * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
- * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK ARISING OUT OF USE OR
- * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
- ***********************license end**************************************/
-
-
-/**
- * "cvmx-usb.h" defines a set of low level USB functions to help
- * developers create Octeon USB drivers for various operating
- * systems. These functions provide a generic API to the Octeon
- * USB blocks, hiding the internal hardware specific
- * operations.
- *
- * At a high level the device driver needs to:
- *
- * - Call cvmx_usb_get_num_ports() to get the number of
- *   supported ports.
- * - Call cvmx_usb_initialize() for each Octeon USB port.
- * - Enable the port using cvmx_usb_enable().
- * - Either periodically, or in an interrupt handler, call
- *   cvmx_usb_poll() to service USB events.
- * - Manage pipes using cvmx_usb_open_pipe() and
- *   cvmx_usb_close_pipe().
- * - Manage transfers using cvmx_usb_submit_*() and
- *   cvmx_usb_cancel*().
- * - Shutdown USB on unload using cvmx_usb_shutdown().
- *
- * To monitor USB status changes, the device driver must use
- * cvmx_usb_register_callback() to register for events that it
- * is interested in. Below are a few hints on successfully
- * implementing a driver on top of this API.
- *
- * == Initialization ==
- *
- * When a driver is first loaded, it is normally not necessary
- * to bring up the USB port completely. Most operating systems
- * expect to initialize and enable the port in two independent
- * steps. Normally an operating system will probe hardware,
- * initialize anything found, and then enable the hardware.
- *
- * In the probe phase you should:
- * - Use cvmx_usb_get_num_ports() to determine the number of
- *   USB port to be supported.
- * - Allocate space for a struct cvmx_usb_state for each
- *   port.
- * - Tell the operating system about each port
- *
- * In the initialization phase you should:
- * - Use cvmx_usb_initialize() on each port.
- * - Do not call cvmx_usb_enable(). This leaves the USB port in
- *   the disabled state until the operating system is ready.
- *
- * Finally, in the enable phase you should:
- * - Call cvmx_usb_enable() on the appropriate port.
- * - Note that some operating system use a RESET instead of an
- *   enable call. To implement RESET, you should call
- *   cvmx_usb_disable() followed by cvmx_usb_enable().
- *
- * == Locking ==
- *
- * All of the functions in the cvmx-usb API assume exclusive
- * access to the USB hardware and internal data structures. This
- * means that the driver must provide locking as necessary.
- *
- * In the single CPU state it is normally enough to disable
- * interrupts before every call to cvmx_usb*() and enable them
- * again after the call is complete. Keep in mind that it is
- * very common for the callback handlers to make additional
- * calls into cvmx-usb, so the disable/enable must be protected
- * against recursion. As an example, the Linux kernel
- * local_irq_save() and local_irq_restore() are perfect for this
- * in the non SMP case.
- *
- * In the SMP case, locking is more complicated. For SMP you not
- * only need to disable interrupts on the local core, but also
- * take a lock to make sure that another core cannot call
- * cvmx-usb.
- *
- * == Port callback ==
- *
- * The port callback prototype needs to look as follows:
- *
- * void port_callback(struct cvmx_usb_state *usb,
- *                    enum cvmx_usb_callback reason,
- *                    enum cvmx_usb_complete status,
- *                    int pipe_handle,
- *                    int submit_handle,
- *                    int bytes_transferred,
- *                    void *user_data);
- * - "usb" is the struct cvmx_usb_state for the port.
- * - "reason" will always be CVMX_USB_CALLBACK_PORT_CHANGED.
- * - "status" will always be CVMX_USB_COMPLETE_SUCCESS.
- * - "pipe_handle" will always be -1.
- * - "submit_handle" will always be -1.
- * - "bytes_transferred" will always be 0.
- * - "user_data" is the void pointer originally passed along
- *   with the callback. Use this for any state information you
- *   need.
- *
- * The port callback will be called whenever the user plugs /
- * unplugs a device from the port. It will not be called when a
- * device is plugged / unplugged from a hub connected to the
- * root port. Normally all the callback needs to do is tell the
- * operating system to poll the root hub for status. Under
- * Linux, this is performed by calling usb_hcd_poll_rh_status().
- * In the Linux driver we use "user_data". to pass around the
- * Linux "hcd" structure. Once the port callback completes,
- * Linux automatically calls octeon_usb_hub_status_data() which
- * uses cvmx_usb_get_status() to determine the root port status.
- *
- * == Complete callback ==
- *
- * The completion callback prototype needs to look as follows:
- *
- * void complete_callback(struct cvmx_usb_state *usb,
- *                        enum cvmx_usb_callback reason,
- *                        enum cvmx_usb_complete status,
- *                        int pipe_handle,
- *                        int submit_handle,
- *                        int bytes_transferred,
- *                        void *user_data);
- * - "usb" is the struct cvmx_usb_state for the port.
- * - "reason" will always be CVMX_USB_CALLBACK_TRANSFER_COMPLETE.
- * - "status" will be one of the cvmx_usb_complete enumerations.
- * - "pipe_handle" is the handle to the pipe the transaction
- *   was originally submitted on.
- * - "submit_handle" is the handle returned by the original
- *   cvmx_usb_submit_* call.
- * - "bytes_transferred" is the number of bytes successfully
- *   transferred in the transaction. This will be zero on most
- *   error conditions.
- * - "user_data" is the void pointer originally passed along
- *   with the callback. Use this for any state information you
- *   need. For example, the Linux "urb" is stored in here in the
- *   Linux driver.
- *
- * In general your callback handler should use "status" and
- * "bytes_transferred" to tell the operating system the how the
- * transaction completed. Normally the pipe is not changed in
- * this callback.
- *
- * == Canceling transactions ==
- *
- * When a transaction is cancelled using cvmx_usb_cancel*(), the
- * actual length of time until the complete callback is called
- * can vary greatly. It may be called before cvmx_usb_cancel*()
- * returns, or it may be called a number of usb frames in the
- * future once the hardware frees the transaction. In either of
- * these cases, the complete handler will receive
- * CVMX_USB_COMPLETE_CANCEL.
- *
- * == Handling pipes ==
- *
- * USB "pipes" is a software construct created by this API to
- * enable the ordering of usb transactions to a device endpoint.
- * Octeon's underlying hardware doesn't have any concept
- * equivalent to "pipes". The hardware instead has eight
- * channels that can be used simultaneously to have up to eight
- * transaction in process at the same time. In order to maintain
- * ordering in a pipe, the transactions for a pipe will only be
- * active in one hardware channel at a time. From an API user's
- * perspective, this doesn't matter but it can be helpful to
- * keep this in mind when you are probing hardware while
- * debugging.
- *
- * Also keep in mind that usb transactions contain state
- * information about the previous transaction to the same
- * endpoint. Each transaction has a PID toggle that changes 0/1
- * between each sub packet. This is maintained in the pipe data
- * structures. For this reason, you generally cannot create and
- * destroy a pipe for every transaction. A sequence of
- * transaction to the same endpoint must use the same pipe.
- *
- * == Root Hub ==
- *
- * Some operating systems view the usb root port as a normal usb
- * hub. These systems attempt to control the root hub with
- * messages similar to the usb 2.0 spec for hub control and
- * status. For these systems it may be necessary to write
- * function to decode standard usb control messages into
- * equivalent cvmx-usb API calls.
- *
- * == Interrupts ==
- *
- * If you plan on using usb interrupts, cvmx_usb_poll() must be
- * called on every usb interrupt. It will read the usb state,
- * call any needed callbacks, and schedule transactions as
- * needed. Your device driver needs only to hookup an interrupt
- * handler and call cvmx_usb_poll(). Octeon's usb port 0 causes
- * CIU bit CIU_INT*_SUM0[USB] to be set (bit 56). For port 1,
- * CIU bit CIU_INT_SUM1[USB1] is set (bit 17). How these bits
- * are turned into interrupt numbers is operating system
- * specific. For Linux, there are the convenient defines
- * OCTEON_IRQ_USB0 and OCTEON_IRQ_USB1 for the IRQ numbers.
- *
- * If you aren't using interrupts, simple call cvmx_usb_poll()
- * in your main processing loop.
- */
-
-#ifndef __CVMX_USB_H__
-#define __CVMX_USB_H__
-
-/**
- * enum cvmx_usb_speed - the possible USB device speeds
- *
- * @CVMX_USB_SPEED_HIGH: Device is operation at 480Mbps
- * @CVMX_USB_SPEED_FULL: Device is operation at 12Mbps
- * @CVMX_USB_SPEED_LOW:  Device is operation at 1.5Mbps
- */
-enum cvmx_usb_speed {
-	CVMX_USB_SPEED_HIGH = 0,
-	CVMX_USB_SPEED_FULL = 1,
-	CVMX_USB_SPEED_LOW = 2,
-};
-
-/**
- * enum cvmx_usb_transfer - the possible USB transfer types
- *
- * @CVMX_USB_TRANSFER_CONTROL:	   USB transfer type control for hub and status
- *				   transfers
- * @CVMX_USB_TRANSFER_ISOCHRONOUS: USB transfer type isochronous for low
- *				   priority periodic transfers
- * @CVMX_USB_TRANSFER_BULK:	   USB transfer type bulk for large low priority
- *				   transfers
- * @CVMX_USB_TRANSFER_INTERRUPT:   USB transfer type interrupt for high priority
- *				   periodic transfers
- */
-enum cvmx_usb_transfer {
-	CVMX_USB_TRANSFER_CONTROL = 0,
-	CVMX_USB_TRANSFER_ISOCHRONOUS = 1,
-	CVMX_USB_TRANSFER_BULK = 2,
-	CVMX_USB_TRANSFER_INTERRUPT = 3,
-};
-
-/**
- * enum cvmx_usb_direction - the transfer directions
- *
- * @CVMX_USB_DIRECTION_OUT: Data is transferring from Octeon to the device/host
- * @CVMX_USB_DIRECTION_IN:  Data is transferring from the device/host to Octeon
- */
-enum cvmx_usb_direction {
-	CVMX_USB_DIRECTION_OUT,
-	CVMX_USB_DIRECTION_IN,
-};
-
-/**
- * enum cvmx_usb_complete - possible callback function status codes
- *
- * @CVMX_USB_COMPLETE_SUCCESS:	  The transaction / operation finished without
- *				  any errors
- * @CVMX_USB_COMPLETE_SHORT:	  FIXME: This is currently not implemented
- * @CVMX_USB_COMPLETE_CANCEL:	  The transaction was canceled while in flight by
- *				  a user call to cvmx_usb_cancel
- * @CVMX_USB_COMPLETE_ERROR:	  The transaction aborted with an unexpected
- *				  error status
- * @CVMX_USB_COMPLETE_STALL:	  The transaction received a USB STALL response
- *				  from the device
- * @CVMX_USB_COMPLETE_XACTERR:	  The transaction failed with an error from the
- *				  device even after a number of retries
- * @CVMX_USB_COMPLETE_DATATGLERR: The transaction failed with a data toggle
- *				  error even after a number of retries
- * @CVMX_USB_COMPLETE_BABBLEERR:  The transaction failed with a babble error
- * @CVMX_USB_COMPLETE_FRAMEERR:	  The transaction failed with a frame error
- *				  even after a number of retries
- */
-enum cvmx_usb_complete {
-	CVMX_USB_COMPLETE_SUCCESS,
-	CVMX_USB_COMPLETE_SHORT,
-	CVMX_USB_COMPLETE_CANCEL,
-	CVMX_USB_COMPLETE_ERROR,
-	CVMX_USB_COMPLETE_STALL,
-	CVMX_USB_COMPLETE_XACTERR,
-	CVMX_USB_COMPLETE_DATATGLERR,
-	CVMX_USB_COMPLETE_BABBLEERR,
-	CVMX_USB_COMPLETE_FRAMEERR,
-};
-
-/**
- * struct cvmx_usb_port_status - the USB port status information
- *
- * @port_enabled:	1 = Usb port is enabled, 0 = disabled
- * @port_over_current:	1 = Over current detected, 0 = Over current not
- *			detected. Octeon doesn't support over current detection.
- * @port_powered:	1 = Port power is being supplied to the device, 0 =
- *			power is off. Octeon doesn't support turning port power
- *			off.
- * @port_speed:		Current port speed.
- * @connected:		1 = A device is connected to the port, 0 = No device is
- *			connected.
- * @connect_change:	1 = Device connected state changed since the last set
- *			status call.
- */
-struct cvmx_usb_port_status {
-	uint32_t reserved		: 25;
-	uint32_t port_enabled		: 1;
-	uint32_t port_over_current	: 1;
-	uint32_t port_powered		: 1;
-	enum cvmx_usb_speed port_speed	: 2;
-	uint32_t connected		: 1;
-	uint32_t connect_change		: 1;
-};
-
-/**
- * union cvmx_usb_control_header - the structure of a Control packet header
- *
- * @s.request_type:	Bit 7 tells the direction: 1=IN, 0=OUT
- * @s.request		The standard usb request to make
- * @s.value		Value parameter for the request in little endian format
- * @s.index		Index for the request in little endian format
- * @s.length		Length of the data associated with this request in
- *			little endian format
- */
-union cvmx_usb_control_header {
-	uint64_t u64;
-	struct {
-		uint64_t request_type   : 8;
-		uint64_t request        : 8;
-		uint64_t value          : 16;
-		uint64_t index          : 16;
-		uint64_t length         : 16;
-	} s;
-};
-
-/**
- * struct cvmx_usb_iso_packet - descriptor for Isochronous packets
- *
- * @offset:	This is the offset in bytes into the main buffer where this data
- *		is stored.
- * @length:	This is the length in bytes of the data.
- * @status:	This is the status of this individual packet transfer.
- */
-struct cvmx_usb_iso_packet {
-	int offset;
-	int length;
-	enum cvmx_usb_complete status;
-};
-
-/**
- * enum cvmx_usb_callback - possible callback reasons for the USB API
- *
- * @CVMX_USB_CALLBACK_TRANSFER_COMPLETE: A callback of this type is called when
- *					 a submitted transfer completes. The
- *					 completion callback will be called even
- *					 if the transfer fails or is canceled.
- *					 The status parameter will contain
- *					 details of why he callback was called.
- * @CVMX_USB_CALLBACK_PORT_CHANGED:	 The status of the port changed. For
- *					 example, someone may have plugged a
- *					 device in. The status parameter
- *					 contains CVMX_USB_COMPLETE_SUCCESS. Use
- *					 cvmx_usb_get_status() to get the new
- *					 port status.
- * @__CVMX_USB_CALLBACK_END:		 Do not use. Used internally for array
- *					 bounds.
- */
-enum cvmx_usb_callback {
-	CVMX_USB_CALLBACK_TRANSFER_COMPLETE,
-	CVMX_USB_CALLBACK_PORT_CHANGED,
-	__CVMX_USB_CALLBACK_END
-};
-
-/**
- * USB state internal data. The contents of this structure
- * may change in future SDKs. No data in it should be referenced
- * by user's of this API.
- */
-struct cvmx_usb_state {
-	char data[65536];
-};
-
-/**
- * USB callback functions are always of the following type.
- * The parameters are as follows:
- *      - state = USB device state populated by
- *        cvmx_usb_initialize().
- *      - reason = The enum cvmx_usb_callback used to register
- *        the callback.
- *      - status = The enum cvmx_usb_complete representing the
- *        status code of a transaction.
- *      - pipe_handle = The Pipe that caused this callback, or
- *        -1 if this callback wasn't associated with a pipe.
- *      - submit_handle = Transfer submit handle causing this
- *        callback, or -1 if this callback wasn't associated
- *        with a transfer.
- *      - Actual number of bytes transfer.
- *      - user_data = The user pointer supplied to the
- *        function cvmx_usb_submit() or
- *        cvmx_usb_register_callback() */
-typedef void (*cvmx_usb_callback_func_t)(struct cvmx_usb_state *state,
-                                         enum cvmx_usb_callback reason,
-                                         enum cvmx_usb_complete status,
-                                         int pipe_handle, int submit_handle,
-                                         int bytes_transferred, void *user_data);
-
-/**
- * enum cvmx_usb_initialize_flags - flags to pass the initialization function
- *
- * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI:    The USB port uses a 12MHz crystal
- *					      as clock source at USB_XO and
- *					      USB_XI.
- * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND:   The USB port uses 12/24/48MHz 2.5V
- *					      board clock source at USB_XO.
- *					      USB_XI should be tied to GND.
- * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO:     Automatically determine clock type
- *					      based on function in
- *					      cvmx-helper-board.c.
- * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK: Mask for clock speed field
- * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ:    Speed of reference clock or
- *					      crystal
- * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ:    Speed of reference clock
- * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ:    Speed of reference clock
- * @CVMX_USB_INITIALIZE_FLAGS_NO_DMA:	      Disable DMA and used polled IO for
- *					      data transfer use for the USB
- */
-enum cvmx_usb_initialize_flags {
-	CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI		= 1 << 0,
-	CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND		= 1 << 1,
-	CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO		= 0,
-	CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK	= 3 << 3,
-	CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ		= 1 << 3,
-	CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ		= 2 << 3,
-	CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ		= 3 << 3,
-	/* Bits 3-4 used to encode the clock frequency */
-	CVMX_USB_INITIALIZE_FLAGS_NO_DMA		= 1 << 5,
-};
-
-/**
- * enum cvmx_usb_pipe_flags - flags for passing when a pipe is created.
- *			      Currently no flags need to be passed.
- *
- * @__CVMX_USB_PIPE_FLAGS_OPEN:	     Used internally to determine if a pipe is
- *				     open. Do not use.
- * @__CVMX_USB_PIPE_FLAGS_SCHEDULED: Used internally to determine if a pipe is
- *				     actively using hardware. Do not use.
- * @__CVMX_USB_PIPE_FLAGS_NEED_PING: Used internally to determine if a high
- *				     speed pipe is in the ping state. Do not
- *				     use.
- */
-enum cvmx_usb_pipe_flags {
-	__CVMX_USB_PIPE_FLAGS_OPEN	= 1 << 16,
-	__CVMX_USB_PIPE_FLAGS_SCHEDULED	= 1 << 17,
-	__CVMX_USB_PIPE_FLAGS_NEED_PING	= 1 << 18,
-};
-
-extern int cvmx_usb_get_num_ports(void);
-extern int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number,
-			       enum cvmx_usb_initialize_flags flags);
-extern int cvmx_usb_shutdown(struct cvmx_usb_state *state);
-extern int cvmx_usb_enable(struct cvmx_usb_state *state);
-extern int cvmx_usb_disable(struct cvmx_usb_state *state);
-extern struct cvmx_usb_port_status cvmx_usb_get_status(struct cvmx_usb_state *state);
-extern void cvmx_usb_set_status(struct cvmx_usb_state *state, struct cvmx_usb_port_status port_status);
-extern int cvmx_usb_open_pipe(struct cvmx_usb_state *state,
-                              enum cvmx_usb_pipe_flags flags,
-                              int device_addr, int endpoint_num,
-                              enum cvmx_usb_speed device_speed, int max_packet,
-                              enum cvmx_usb_transfer transfer_type,
-                              enum cvmx_usb_direction transfer_dir, int interval,
-                              int multi_count, int hub_device_addr,
-                              int hub_port);
-extern int cvmx_usb_submit_bulk(struct cvmx_usb_state *state, int pipe_handle,
-                                uint64_t buffer, int buffer_length,
-                                cvmx_usb_callback_func_t callback,
-                                void *user_data);
-extern int cvmx_usb_submit_interrupt(struct cvmx_usb_state *state, int pipe_handle,
-                                     uint64_t buffer, int buffer_length,
-                                     cvmx_usb_callback_func_t callback,
-                                     void *user_data);
-extern int cvmx_usb_submit_control(struct cvmx_usb_state *state, int pipe_handle,
-                                   uint64_t control_header,
-                                   uint64_t buffer, int buffer_length,
-                                   cvmx_usb_callback_func_t callback,
-                                   void *user_data);
-
-/**
- * enum cvmx_usb_isochronous_flags - flags to pass the
- *				     cvmx_usb_submit_isochronous() function.
- *
- * @CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT: Do not return an error if a transfer
- *					    is less than the maximum packet size
- *					    of the device.
- * @CVMX_USB_ISOCHRONOUS_FLAGS_ASAP:	    Schedule the transaction as soon as
- *					    possible.
- */
-enum cvmx_usb_isochronous_flags {
-	CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT	= 1 << 0,
-	CVMX_USB_ISOCHRONOUS_FLAGS_ASAP		= 1 << 1,
-};
-
-extern int cvmx_usb_submit_isochronous(struct cvmx_usb_state *state, int pipe_handle,
-                                       int start_frame, int flags,
-                                       int number_packets,
-                                       struct cvmx_usb_iso_packet packets[],
-                                       uint64_t buffer, int buffer_length,
-                                       cvmx_usb_callback_func_t callback,
-                                       void *user_data);
-extern int cvmx_usb_cancel(struct cvmx_usb_state *state, int pipe_handle,
-			   int submit_handle);
-extern int cvmx_usb_cancel_all(struct cvmx_usb_state *state, int pipe_handle);
-extern int cvmx_usb_close_pipe(struct cvmx_usb_state *state, int pipe_handle);
-extern int cvmx_usb_register_callback(struct cvmx_usb_state *state,
-				      enum cvmx_usb_callback reason,
-				      cvmx_usb_callback_func_t callback,
-				      void *user_data);
-extern int cvmx_usb_get_frame_number(struct cvmx_usb_state *state);
-extern int cvmx_usb_poll(struct cvmx_usb_state *state);
-
-#endif  /* __CVMX_USB_H__ */
diff --git a/drivers/staging/octeon-usb/cvmx-usbnx-defs.h b/drivers/staging/octeon-usb/cvmx-usbnx-defs.h
deleted file mode 100644
index e06aafa..0000000
--- a/drivers/staging/octeon-usb/cvmx-usbnx-defs.h
+++ /dev/null
@@ -1,885 +0,0 @@
-/***********************license start***************
- * Copyright (c) 2003-2010  Cavium Networks (support@cavium.com). All rights
- * reserved.
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *   * Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *
- *   * Redistributions in binary form must reproduce the above
- *     copyright notice, this list of conditions and the following
- *     disclaimer in the documentation and/or other materials provided
- *     with the distribution.
-
- *   * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export
- * control laws, including the U.S. Export Administration Act and its associated
- * regulations, and may be subject to export or import  regulations in other
- * countries.
-
- * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
- * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
- * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION
- * OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
- * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
- * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
- * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
- * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK ARISING OUT OF USE OR
- * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
- ***********************license end**************************************/
-
-
-/**
- * cvmx-usbnx-defs.h
- *
- * Configuration and status register (CSR) type definitions for
- * Octeon usbnx.
- *
- */
-#ifndef __CVMX_USBNX_TYPEDEFS_H__
-#define __CVMX_USBNX_TYPEDEFS_H__
-
-#define CVMX_USBNXBID1(bid) (((bid) & 1) * 0x10000000ull)
-#define CVMX_USBNXBID2(bid) (((bid) & 1) * 0x100000000000ull)
-
-#define CVMX_USBNXREG1(reg, bid) \
-	(CVMX_ADD_IO_SEG(0x0001180068000000ull | reg) + CVMX_USBNXBID1(bid))
-#define CVMX_USBNXREG2(reg, bid) \
-	(CVMX_ADD_IO_SEG(0x00016F0000000000ull | reg) + CVMX_USBNXBID2(bid))
-
-#define CVMX_USBNX_CLK_CTL(bid)		CVMX_USBNXREG1(0x10, bid)
-#define CVMX_USBNX_DMA0_INB_CHN0(bid)	CVMX_USBNXREG2(0x818, bid)
-#define CVMX_USBNX_DMA0_OUTB_CHN0(bid)	CVMX_USBNXREG2(0x858, bid)
-#define CVMX_USBNX_USBP_CTL_STATUS(bid)	CVMX_USBNXREG1(0x18, bid)
-
-/**
- * cvmx_usbn#_clk_ctl
- *
- * USBN_CLK_CTL = USBN's Clock Control
- *
- * This register is used to control the frequency of the hclk and the
- * hreset and phy_rst signals.
- */
-union cvmx_usbnx_clk_ctl {
-	uint64_t u64;
-	/**
-	 * struct cvmx_usbnx_clk_ctl_s
-	 * @divide2: The 'hclk' used by the USB subsystem is derived
-	 *	from the eclk.
-	 *	Also see the field DIVIDE. DIVIDE2<1> must currently
-	 *	be zero because it is not implemented, so the maximum
-	 *	ratio of eclk/hclk is currently 16.
-	 *	The actual divide number for hclk is:
-	 *	(DIVIDE2 + 1) * (DIVIDE + 1)
-	 * @hclk_rst: When this field is '0' the HCLK-DIVIDER used to
-	 *	generate the hclk in the USB Subsystem is held
-	 *	in reset. This bit must be set to '0' before
-	 *	changing the value os DIVIDE in this register.
-	 *	The reset to the HCLK_DIVIDERis also asserted
-	 *	when core reset is asserted.
-	 * @p_x_on: Force USB-PHY on during suspend.
-	 *	'1' USB-PHY XO block is powered-down during
-	 *	suspend.
-	 *	'0' USB-PHY XO block is powered-up during
-	 *	suspend.
-	 *	The value of this field must be set while POR is
-	 *	active.
-	 * @p_com_on: '0' Force USB-PHY XO Bias, Bandgap and PLL to
-	 *	remain powered in Suspend Mode.
-	 *	'1' The USB-PHY XO Bias, Bandgap and PLL are
-	 *	powered down in suspend mode.
-	 *	The value of this field must be set while POR is
-	 *	active.
-	 * @p_c_sel: Phy clock speed select.
-	 *	Selects the reference clock / crystal frequency.
-	 *	'11': Reserved
-	 *	'10': 48 MHz (reserved when a crystal is used)
-	 *	'01': 24 MHz (reserved when a crystal is used)
-	 *	'00': 12 MHz
-	 *	The value of this field must be set while POR is
-	 *	active.
-	 *	NOTE: if a crystal is used as a reference clock,
-	 *	this field must be set to 12 MHz.
-	 * @cdiv_byp: Used to enable the bypass input to the USB_CLK_DIV.
-	 * @sd_mode: Scaledown mode for the USBC. Control timing events
-	 *	in the USBC, for normal operation this must be '0'.
-	 * @s_bist: Starts bist on the hclk memories, during the '0'
-	 *	to '1' transition.
-	 * @por: Power On Reset for the PHY.
-	 *	Resets all the PHYS registers and state machines.
-	 * @enable: When '1' allows the generation of the hclk. When
-	 *	'0' the hclk will not be generated. SEE DIVIDE
-	 *	field of this register.
-	 * @prst: When this field is '0' the reset associated with
-	 *	the phy_clk functionality in the USB Subsystem is
-	 *	help in reset. This bit should not be set to '1'
-	 *	until the time it takes 6 clocks (hclk or phy_clk,
-	 *	whichever is slower) has passed. Under normal
-	 *	operation once this bit is set to '1' it should not
-	 *	be set to '0'.
-	 * @hrst: When this field is '0' the reset associated with
-	 *	the hclk functioanlity in the USB Subsystem is
-	 *	held in reset.This bit should not be set to '1'
-	 *	until 12ms after phy_clk is stable. Under normal
-	 *	operation, once this bit is set to '1' it should
-	 *	not be set to '0'.
-	 * @divide: The frequency of 'hclk' used by the USB subsystem
-	 *	is the eclk frequency divided by the value of
-	 *	(DIVIDE2 + 1) * (DIVIDE + 1), also see the field
-	 *	DIVIDE2 of this register.
-	 *	The hclk frequency should be less than 125Mhz.
-	 *	After writing a value to this field the SW should
-	 *	read the field for the value written.
-	 *	The ENABLE field of this register should not be set
-	 *	until AFTER this field is set and then read.
-	 */
-	struct cvmx_usbnx_clk_ctl_s {
-		uint64_t reserved_20_63	: 44;
-		uint64_t divide2	: 2;
-		uint64_t hclk_rst	: 1;
-		uint64_t p_x_on		: 1;
-		uint64_t reserved_14_15	: 2;
-		uint64_t p_com_on	: 1;
-		uint64_t p_c_sel	: 2;
-		uint64_t cdiv_byp	: 1;
-		uint64_t sd_mode	: 2;
-		uint64_t s_bist		: 1;
-		uint64_t por		: 1;
-		uint64_t enable		: 1;
-		uint64_t prst		: 1;
-		uint64_t hrst		: 1;
-		uint64_t divide		: 3;
-	} s;
-	/**
-	 * struct cvmx_usbnx_clk_ctl_cn30xx
-	 * @hclk_rst: When this field is '0' the HCLK-DIVIDER used to
-	 *	generate the hclk in the USB Subsystem is held
-	 *	in reset. This bit must be set to '0' before
-	 *	changing the value os DIVIDE in this register.
-	 *	The reset to the HCLK_DIVIDERis also asserted
-	 *	when core reset is asserted.
-	 * @p_x_on: Force USB-PHY on during suspend.
-	 *	'1' USB-PHY XO block is powered-down during
-	 *	suspend.
-	 *	'0' USB-PHY XO block is powered-up during
-	 *	suspend.
-	 *	The value of this field must be set while POR is
-	 *	active.
-	 * @p_rclk: Phy refrence clock enable.
-	 *	'1' The PHY PLL uses the XO block output as a
-	 *	reference.
-	 *	'0' Reserved.
-	 * @p_xenbn: Phy external clock enable.
-	 *	'1' The XO block uses the clock from a crystal.
-	 *	'0' The XO block uses an external clock supplied
-	 *	on the XO pin. USB_XI should be tied to
-	 *	ground for this usage.
-	 * @p_com_on: '0' Force USB-PHY XO Bias, Bandgap and PLL to
-	 *	remain powered in Suspend Mode.
-	 *	'1' The USB-PHY XO Bias, Bandgap and PLL are
-	 *	powered down in suspend mode.
-	 *	The value of this field must be set while POR is
-	 *	active.
-	 * @p_c_sel: Phy clock speed select.
-	 *	Selects the reference clock / crystal frequency.
-	 *	'11': Reserved
-	 *	'10': 48 MHz
-	 *	'01': 24 MHz
-	 *	'00': 12 MHz
-	 *	The value of this field must be set while POR is
-	 *	active.
-	 * @cdiv_byp: Used to enable the bypass input to the USB_CLK_DIV.
-	 * @sd_mode: Scaledown mode for the USBC. Control timing events
-	 *	in the USBC, for normal operation this must be '0'.
-	 * @s_bist: Starts bist on the hclk memories, during the '0'
-	 *	to '1' transition.
-	 * @por: Power On Reset for the PHY.
-	 *	Resets all the PHYS registers and state machines.
-	 * @enable: When '1' allows the generation of the hclk. When
-	 *	'0' the hclk will not be generated.
-	 * @prst: When this field is '0' the reset associated with
-	 *	the phy_clk functionality in the USB Subsystem is
-	 *	help in reset. This bit should not be set to '1'
-	 *	until the time it takes 6 clocks (hclk or phy_clk,
-	 *	whichever is slower) has passed. Under normal
-	 *	operation once this bit is set to '1' it should not
-	 *	be set to '0'.
-	 * @hrst: When this field is '0' the reset associated with
-	 *	the hclk functioanlity in the USB Subsystem is
-	 *	held in reset.This bit should not be set to '1'
-	 *	until 12ms after phy_clk is stable. Under normal
-	 *	operation, once this bit is set to '1' it should
-	 *	not be set to '0'.
-	 * @divide: The 'hclk' used by the USB subsystem is derived
-	 *	from the eclk. The eclk will be divided by the
-	 *	value of this field +1 to determine the hclk
-	 *	frequency. (Also see HRST of this register).
-	 *	The hclk frequency must be less than 125 MHz.
-	 */
-	struct cvmx_usbnx_clk_ctl_cn30xx {
-		uint64_t reserved_18_63	: 46;
-		uint64_t hclk_rst	: 1;
-		uint64_t p_x_on		: 1;
-		uint64_t p_rclk		: 1;
-		uint64_t p_xenbn	: 1;
-		uint64_t p_com_on	: 1;
-		uint64_t p_c_sel	: 2;
-		uint64_t cdiv_byp	: 1;
-		uint64_t sd_mode	: 2;
-		uint64_t s_bist		: 1;
-		uint64_t por		: 1;
-		uint64_t enable		: 1;
-		uint64_t prst		: 1;
-		uint64_t hrst		: 1;
-		uint64_t divide		: 3;
-	} cn30xx;
-	struct cvmx_usbnx_clk_ctl_cn30xx cn31xx;
-	/**
-	 * struct cvmx_usbnx_clk_ctl_cn50xx
-	 * @divide2: The 'hclk' used by the USB subsystem is derived
-	 *	from the eclk.
-	 *	Also see the field DIVIDE. DIVIDE2<1> must currently
-	 *	be zero because it is not implemented, so the maximum
-	 *	ratio of eclk/hclk is currently 16.
-	 *	The actual divide number for hclk is:
-	 *	(DIVIDE2 + 1) * (DIVIDE + 1)
-	 * @hclk_rst: When this field is '0' the HCLK-DIVIDER used to
-	 *	generate the hclk in the USB Subsystem is held
-	 *	in reset. This bit must be set to '0' before
-	 *	changing the value os DIVIDE in this register.
-	 *	The reset to the HCLK_DIVIDERis also asserted
-	 *	when core reset is asserted.
-	 * @p_rtype: PHY reference clock type
-	 *	'0' The USB-PHY uses a 12MHz crystal as a clock
-	 *	source at the USB_XO and USB_XI pins
-	 *	'1' Reserved
-	 *	'2' The USB_PHY uses 12/24/48MHz 2.5V board clock
-	 *	at the USB_XO pin. USB_XI should be tied to
-	 *	ground in this case.
-	 *	'3' Reserved
-	 *	(bit 14 was P_XENBN on 3xxx)
-	 *	(bit 15 was P_RCLK on 3xxx)
-	 * @p_com_on: '0' Force USB-PHY XO Bias, Bandgap and PLL to
-	 *	remain powered in Suspend Mode.
-	 *	'1' The USB-PHY XO Bias, Bandgap and PLL are
-	 *	powered down in suspend mode.
-	 *	The value of this field must be set while POR is
-	 *	active.
-	 * @p_c_sel: Phy clock speed select.
-	 *	Selects the reference clock / crystal frequency.
-	 *	'11': Reserved
-	 *	'10': 48 MHz (reserved when a crystal is used)
-	 *	'01': 24 MHz (reserved when a crystal is used)
-	 *	'00': 12 MHz
-	 *	The value of this field must be set while POR is
-	 *	active.
-	 *	NOTE: if a crystal is used as a reference clock,
-	 *	this field must be set to 12 MHz.
-	 * @cdiv_byp: Used to enable the bypass input to the USB_CLK_DIV.
-	 * @sd_mode: Scaledown mode for the USBC. Control timing events
-	 *	in the USBC, for normal operation this must be '0'.
-	 * @s_bist: Starts bist on the hclk memories, during the '0'
-	 *	to '1' transition.
-	 * @por: Power On Reset for the PHY.
-	 *	Resets all the PHYS registers and state machines.
-	 * @enable: When '1' allows the generation of the hclk. When
-	 *	'0' the hclk will not be generated. SEE DIVIDE
-	 *	field of this register.
-	 * @prst: When this field is '0' the reset associated with
-	 *	the phy_clk functionality in the USB Subsystem is
-	 *	help in reset. This bit should not be set to '1'
-	 *	until the time it takes 6 clocks (hclk or phy_clk,
-	 *	whichever is slower) has passed. Under normal
-	 *	operation once this bit is set to '1' it should not
-	 *	be set to '0'.
-	 * @hrst: When this field is '0' the reset associated with
-	 *	the hclk functioanlity in the USB Subsystem is
-	 *	held in reset.This bit should not be set to '1'
-	 *	until 12ms after phy_clk is stable. Under normal
-	 *	operation, once this bit is set to '1' it should
-	 *	not be set to '0'.
-	 * @divide: The frequency of 'hclk' used by the USB subsystem
-	 *	is the eclk frequency divided by the value of
-	 *	(DIVIDE2 + 1) * (DIVIDE + 1), also see the field
-	 *	DIVIDE2 of this register.
-	 *	The hclk frequency should be less than 125Mhz.
-	 *	After writing a value to this field the SW should
-	 *	read the field for the value written.
-	 *	The ENABLE field of this register should not be set
-	 *	until AFTER this field is set and then read.
-	 */
-	struct cvmx_usbnx_clk_ctl_cn50xx {
-		uint64_t reserved_20_63	: 44;
-		uint64_t divide2	: 2;
-		uint64_t hclk_rst	: 1;
-		uint64_t reserved_16_16 : 1;
-		uint64_t p_rtype	: 2;
-		uint64_t p_com_on	: 1;
-		uint64_t p_c_sel	: 2;
-		uint64_t cdiv_byp	: 1;
-		uint64_t sd_mode	: 2;
-		uint64_t s_bist		: 1;
-		uint64_t por		: 1;
-		uint64_t enable		: 1;
-		uint64_t prst		: 1;
-		uint64_t hrst		: 1;
-		uint64_t divide		: 3;
-	} cn50xx;
-	struct cvmx_usbnx_clk_ctl_cn50xx cn52xx;
-	struct cvmx_usbnx_clk_ctl_cn50xx cn56xx;
-};
-
-/**
- * cvmx_usbn#_usbp_ctl_status
- *
- * USBN_USBP_CTL_STATUS = USBP Control And Status Register
- *
- * Contains general control and status information for the USBN block.
- */
-union cvmx_usbnx_usbp_ctl_status {
-	uint64_t u64;
-	/**
-	 * struct cvmx_usbnx_usbp_ctl_status_s
-	 * @txrisetune: HS Transmitter Rise/Fall Time Adjustment
-	 * @txvreftune: HS DC Voltage Level Adjustment
-	 * @txfslstune: FS/LS Source Impedence Adjustment
-	 * @txhsxvtune: Transmitter High-Speed Crossover Adjustment
-	 * @sqrxtune: Squelch Threshold Adjustment
-	 * @compdistune: Disconnect Threshold Adjustment
-	 * @otgtune: VBUS Valid Threshold Adjustment
-	 * @otgdisable: OTG Block Disable
-	 * @portreset: Per_Port Reset
-	 * @drvvbus: Drive VBUS
-	 * @lsbist: Low-Speed BIST Enable.
-	 * @fsbist: Full-Speed BIST Enable.
-	 * @hsbist: High-Speed BIST Enable.
-	 * @bist_done: PHY Bist Done.
-	 *	Asserted at the end of the PHY BIST sequence.
-	 * @bist_err: PHY Bist Error.
-	 *	Indicates an internal error was detected during
-	 *	the BIST sequence.
-	 * @tdata_out: PHY Test Data Out.
-	 *	Presents either internaly generated signals or
-	 *	test register contents, based upon the value of
-	 *	test_data_out_sel.
-	 * @siddq: Drives the USBP (USB-PHY) SIDDQ input.
-	 *	Normally should be set to zero.
-	 *	When customers have no intent to use USB PHY
-	 *	interface, they should:
-	 *	- still provide 3.3V to USB_VDD33, and
-	 *	- tie USB_REXT to 3.3V supply, and
-	 *	- set USBN*_USBP_CTL_STATUS[SIDDQ]=1
-	 * @txpreemphasistune: HS Transmitter Pre-Emphasis Enable
-	 * @dma_bmode: When set to 1 the L2C DMA address will be updated
-	 *	with byte-counts between packets. When set to 0
-	 *	the L2C DMA address is incremented to the next
-	 *	4-byte aligned address after adding byte-count.
-	 * @usbc_end: Bigendian input to the USB Core. This should be
-	 *	set to '0' for operation.
-	 * @usbp_bist: PHY, This is cleared '0' to run BIST on the USBP.
-	 * @tclk: PHY Test Clock, used to load TDATA_IN to the USBP.
-	 * @dp_pulld: PHY DP_PULLDOWN input to the USB-PHY.
-	 *	This signal enables the pull-down resistance on
-	 *	the D+ line. '1' pull down-resistance is connected
-	 *	to D+/ '0' pull down resistance is not connected
-	 *	to D+. When an A/B device is acting as a host
-	 *	(downstream-facing port), dp_pulldown and
-	 *	dm_pulldown are enabled. This must not toggle
-	 *	during normal opeartion.
-	 * @dm_pulld: PHY DM_PULLDOWN input to the USB-PHY.
-	 *	This signal enables the pull-down resistance on
-	 *	the D- line. '1' pull down-resistance is connected
-	 *	to D-. '0' pull down resistance is not connected
-	 *	to D-. When an A/B device is acting as a host
-	 *	(downstream-facing port), dp_pulldown and
-	 *	dm_pulldown are enabled. This must not toggle
-	 *	during normal opeartion.
-	 * @hst_mode: When '0' the USB is acting as HOST, when '1'
-	 *	USB is acting as device. This field needs to be
-	 *	set while the USB is in reset.
-	 * @tuning: Transmitter Tuning for High-Speed Operation.
-	 *	Tunes the current supply and rise/fall output
-	 *	times for high-speed operation.
-	 *	[20:19] == 11: Current supply increased
-	 *	approximately 9%
-	 *	[20:19] == 10: Current supply increased
-	 *	approximately 4.5%
-	 *	[20:19] == 01: Design default.
-	 *	[20:19] == 00: Current supply decreased
-	 *	approximately 4.5%
-	 *	[22:21] == 11: Rise and fall times are increased.
-	 *	[22:21] == 10: Design default.
-	 *	[22:21] == 01: Rise and fall times are decreased.
-	 *	[22:21] == 00: Rise and fall times are decreased
-	 *	further as compared to the 01 setting.
-	 * @tx_bs_enh: Transmit Bit Stuffing on [15:8].
-	 *	Enables or disables bit stuffing on data[15:8]
-	 *	when bit-stuffing is enabled.
-	 * @tx_bs_en: Transmit Bit Stuffing on [7:0].
-	 *	Enables or disables bit stuffing on data[7:0]
-	 *	when bit-stuffing is enabled.
-	 * @loop_enb: PHY Loopback Test Enable.
-	 *	'1': During data transmission the receive is
-	 *	enabled.
-	 *	'0': During data transmission the receive is
-	 *	disabled.
-	 *	Must be '0' for normal operation.
-	 * @vtest_enb: Analog Test Pin Enable.
-	 *	'1' The PHY's analog_test pin is enabled for the
-	 *	input and output of applicable analog test signals.
-	 *	'0' THe analog_test pin is disabled.
-	 * @bist_enb: Built-In Self Test Enable.
-	 *	Used to activate BIST in the PHY.
-	 * @tdata_sel: Test Data Out Select.
-	 *	'1' test_data_out[3:0] (PHY) register contents
-	 *	are output. '0' internaly generated signals are
-	 *	output.
-	 * @taddr_in: Mode Address for Test Interface.
-	 *	Specifies the register address for writing to or
-	 *	reading from the PHY test interface register.
-	 * @tdata_in: Internal Testing Register Input Data and Select
-	 *	This is a test bus. Data is present on [3:0],
-	 *	and its corresponding select (enable) is present
-	 *	on bits [7:4].
-	 * @ate_reset: Reset input from automatic test equipment.
-	 *	This is a test signal. When the USB Core is
-	 *	powered up (not in Susned Mode), an automatic
-	 *	tester can use this to disable phy_clock and
-	 *	free_clk, then re-eanable them with an aligned
-	 *	phase.
-	 *	'1': The phy_clk and free_clk outputs are
-	 *	disabled. "0": The phy_clock and free_clk outputs
-	 *	are available within a specific period after the
-	 *	de-assertion.
-	 */
-	struct cvmx_usbnx_usbp_ctl_status_s {
-		uint64_t txrisetune		: 1;
-		uint64_t txvreftune		: 4;
-		uint64_t txfslstune		: 4;
-		uint64_t txhsxvtune		: 2;
-		uint64_t sqrxtune		: 3;
-		uint64_t compdistune		: 3;
-		uint64_t otgtune		: 3;
-		uint64_t otgdisable		: 1;
-		uint64_t portreset		: 1;
-		uint64_t drvvbus		: 1;
-		uint64_t lsbist			: 1;
-		uint64_t fsbist			: 1;
-		uint64_t hsbist			: 1;
-		uint64_t bist_done		: 1;
-		uint64_t bist_err		: 1;
-		uint64_t tdata_out		: 4;
-		uint64_t siddq			: 1;
-		uint64_t txpreemphasistune	: 1;
-		uint64_t dma_bmode		: 1;
-		uint64_t usbc_end		: 1;
-		uint64_t usbp_bist		: 1;
-		uint64_t tclk			: 1;
-		uint64_t dp_pulld		: 1;
-		uint64_t dm_pulld		: 1;
-		uint64_t hst_mode		: 1;
-		uint64_t tuning			: 4;
-		uint64_t tx_bs_enh		: 1;
-		uint64_t tx_bs_en		: 1;
-		uint64_t loop_enb		: 1;
-		uint64_t vtest_enb		: 1;
-		uint64_t bist_enb		: 1;
-		uint64_t tdata_sel		: 1;
-		uint64_t taddr_in		: 4;
-		uint64_t tdata_in		: 8;
-		uint64_t ate_reset		: 1;
-	} s;
-	/**
-	 * struct cvmx_usbnx_usbp_ctl_status_cn30xx
-	 * @bist_done: PHY Bist Done.
-	 *	Asserted at the end of the PHY BIST sequence.
-	 * @bist_err: PHY Bist Error.
-	 *	Indicates an internal error was detected during
-	 *	the BIST sequence.
-	 * @tdata_out: PHY Test Data Out.
-	 *	Presents either internaly generated signals or
-	 *	test register contents, based upon the value of
-	 *	test_data_out_sel.
-	 * @dma_bmode: When set to 1 the L2C DMA address will be updated
-	 *	with byte-counts between packets. When set to 0
-	 *	the L2C DMA address is incremented to the next
-	 *	4-byte aligned address after adding byte-count.
-	 * @usbc_end: Bigendian input to the USB Core. This should be
-	 *	set to '0' for operation.
-	 * @usbp_bist: PHY, This is cleared '0' to run BIST on the USBP.
-	 * @tclk: PHY Test Clock, used to load TDATA_IN to the USBP.
-	 * @dp_pulld: PHY DP_PULLDOWN input to the USB-PHY.
-	 *	This signal enables the pull-down resistance on
-	 *	the D+ line. '1' pull down-resistance is connected
-	 *	to D+/ '0' pull down resistance is not connected
-	 *	to D+. When an A/B device is acting as a host
-	 *	(downstream-facing port), dp_pulldown and
-	 *	dm_pulldown are enabled. This must not toggle
-	 *	during normal opeartion.
-	 * @dm_pulld: PHY DM_PULLDOWN input to the USB-PHY.
-	 *	This signal enables the pull-down resistance on
-	 *	the D- line. '1' pull down-resistance is connected
-	 *	to D-. '0' pull down resistance is not connected
-	 *	to D-. When an A/B device is acting as a host
-	 *	(downstream-facing port), dp_pulldown and
-	 *	dm_pulldown are enabled. This must not toggle
-	 *	during normal opeartion.
-	 * @hst_mode: When '0' the USB is acting as HOST, when '1'
-	 *	USB is acting as device. This field needs to be
-	 *	set while the USB is in reset.
-	 * @tuning: Transmitter Tuning for High-Speed Operation.
-	 *	Tunes the current supply and rise/fall output
-	 *	times for high-speed operation.
-	 *	[20:19] == 11: Current supply increased
-	 *	approximately 9%
-	 *	[20:19] == 10: Current supply increased
-	 *	approximately 4.5%
-	 *	[20:19] == 01: Design default.
-	 *	[20:19] == 00: Current supply decreased
-	 *	approximately 4.5%
-	 *	[22:21] == 11: Rise and fall times are increased.
-	 *	[22:21] == 10: Design default.
-	 *	[22:21] == 01: Rise and fall times are decreased.
-	 *	[22:21] == 00: Rise and fall times are decreased
-	 *	further as compared to the 01 setting.
-	 * @tx_bs_enh: Transmit Bit Stuffing on [15:8].
-	 *	Enables or disables bit stuffing on data[15:8]
-	 *	when bit-stuffing is enabled.
-	 * @tx_bs_en: Transmit Bit Stuffing on [7:0].
-	 *	Enables or disables bit stuffing on data[7:0]
-	 *	when bit-stuffing is enabled.
-	 * @loop_enb: PHY Loopback Test Enable.
-	 *	'1': During data transmission the receive is
-	 *	enabled.
-	 *	'0': During data transmission the receive is
-	 *	disabled.
-	 *	Must be '0' for normal operation.
-	 * @vtest_enb: Analog Test Pin Enable.
-	 *	'1' The PHY's analog_test pin is enabled for the
-	 *	input and output of applicable analog test signals.
-	 *	'0' THe analog_test pin is disabled.
-	 * @bist_enb: Built-In Self Test Enable.
-	 *	Used to activate BIST in the PHY.
-	 * @tdata_sel: Test Data Out Select.
-	 *	'1' test_data_out[3:0] (PHY) register contents
-	 *	are output. '0' internaly generated signals are
-	 *	output.
-	 * @taddr_in: Mode Address for Test Interface.
-	 *	Specifies the register address for writing to or
-	 *	reading from the PHY test interface register.
-	 * @tdata_in: Internal Testing Register Input Data and Select
-	 *	This is a test bus. Data is present on [3:0],
-	 *	and its corresponding select (enable) is present
-	 *	on bits [7:4].
-	 * @ate_reset: Reset input from automatic test equipment.
-	 *	This is a test signal. When the USB Core is
-	 *	powered up (not in Susned Mode), an automatic
-	 *	tester can use this to disable phy_clock and
-	 *	free_clk, then re-eanable them with an aligned
-	 *	phase.
-	 *	'1': The phy_clk and free_clk outputs are
-	 *	disabled. "0": The phy_clock and free_clk outputs
-	 *	are available within a specific period after the
-	 *	de-assertion.
-	 */
-	struct cvmx_usbnx_usbp_ctl_status_cn30xx {
-		uint64_t reserved_38_63	: 26;
-		uint64_t bist_done	: 1;
-		uint64_t bist_err	: 1;
-		uint64_t tdata_out	: 4;
-		uint64_t reserved_30_31	: 2;
-		uint64_t dma_bmode	: 1;
-		uint64_t usbc_end	: 1;
-		uint64_t usbp_bist	: 1;
-		uint64_t tclk		: 1;
-		uint64_t dp_pulld	: 1;
-		uint64_t dm_pulld	: 1;
-		uint64_t hst_mode	: 1;
-		uint64_t tuning		: 4;
-		uint64_t tx_bs_enh	: 1;
-		uint64_t tx_bs_en	: 1;
-		uint64_t loop_enb	: 1;
-		uint64_t vtest_enb	: 1;
-		uint64_t bist_enb	: 1;
-		uint64_t tdata_sel	: 1;
-		uint64_t taddr_in	: 4;
-		uint64_t tdata_in	: 8;
-		uint64_t ate_reset	: 1;
-	} cn30xx;
-	/**
-	 * struct cvmx_usbnx_usbp_ctl_status_cn50xx
-	 * @txrisetune: HS Transmitter Rise/Fall Time Adjustment
-	 * @txvreftune: HS DC Voltage Level Adjustment
-	 * @txfslstune: FS/LS Source Impedence Adjustment
-	 * @txhsxvtune: Transmitter High-Speed Crossover Adjustment
-	 * @sqrxtune: Squelch Threshold Adjustment
-	 * @compdistune: Disconnect Threshold Adjustment
-	 * @otgtune: VBUS Valid Threshold Adjustment
-	 * @otgdisable: OTG Block Disable
-	 * @portreset: Per_Port Reset
-	 * @drvvbus: Drive VBUS
-	 * @lsbist: Low-Speed BIST Enable.
-	 * @fsbist: Full-Speed BIST Enable.
-	 * @hsbist: High-Speed BIST Enable.
-	 * @bist_done: PHY Bist Done.
-	 *	Asserted at the end of the PHY BIST sequence.
-	 * @bist_err: PHY Bist Error.
-	 *	Indicates an internal error was detected during
-	 *	the BIST sequence.
-	 * @tdata_out: PHY Test Data Out.
-	 *	Presents either internaly generated signals or
-	 *	test register contents, based upon the value of
-	 *	test_data_out_sel.
-	 * @txpreemphasistune: HS Transmitter Pre-Emphasis Enable
-	 * @dma_bmode: When set to 1 the L2C DMA address will be updated
-	 *	with byte-counts between packets. When set to 0
-	 *	the L2C DMA address is incremented to the next
-	 *	4-byte aligned address after adding byte-count.
-	 * @usbc_end: Bigendian input to the USB Core. This should be
-	 *	set to '0' for operation.
-	 * @usbp_bist: PHY, This is cleared '0' to run BIST on the USBP.
-	 * @tclk: PHY Test Clock, used to load TDATA_IN to the USBP.
-	 * @dp_pulld: PHY DP_PULLDOWN input to the USB-PHY.
-	 *	This signal enables the pull-down resistance on
-	 *	the D+ line. '1' pull down-resistance is connected
-	 *	to D+/ '0' pull down resistance is not connected
-	 *	to D+. When an A/B device is acting as a host
-	 *	(downstream-facing port), dp_pulldown and
-	 *	dm_pulldown are enabled. This must not toggle
-	 *	during normal opeartion.
-	 * @dm_pulld: PHY DM_PULLDOWN input to the USB-PHY.
-	 *	This signal enables the pull-down resistance on
-	 *	the D- line. '1' pull down-resistance is connected
-	 *	to D-. '0' pull down resistance is not connected
-	 *	to D-. When an A/B device is acting as a host
-	 *	(downstream-facing port), dp_pulldown and
-	 *	dm_pulldown are enabled. This must not toggle
-	 *	during normal opeartion.
-	 * @hst_mode: When '0' the USB is acting as HOST, when '1'
-	 *	USB is acting as device. This field needs to be
-	 *	set while the USB is in reset.
-	 * @tx_bs_enh: Transmit Bit Stuffing on [15:8].
-	 *	Enables or disables bit stuffing on data[15:8]
-	 *	when bit-stuffing is enabled.
-	 * @tx_bs_en: Transmit Bit Stuffing on [7:0].
-	 *	Enables or disables bit stuffing on data[7:0]
-	 *	when bit-stuffing is enabled.
-	 * @loop_enb: PHY Loopback Test Enable.
-	 *	'1': During data transmission the receive is
-	 *	enabled.
-	 *	'0': During data transmission the receive is
-	 *	disabled.
-	 *	Must be '0' for normal operation.
-	 * @vtest_enb: Analog Test Pin Enable.
-	 *	'1' The PHY's analog_test pin is enabled for the
-	 *	input and output of applicable analog test signals.
-	 *	'0' THe analog_test pin is disabled.
-	 * @bist_enb: Built-In Self Test Enable.
-	 *	Used to activate BIST in the PHY.
-	 * @tdata_sel: Test Data Out Select.
-	 *	'1' test_data_out[3:0] (PHY) register contents
-	 *	are output. '0' internaly generated signals are
-	 *	output.
-	 * @taddr_in: Mode Address for Test Interface.
-	 *	Specifies the register address for writing to or
-	 *	reading from the PHY test interface register.
-	 * @tdata_in: Internal Testing Register Input Data and Select
-	 *	This is a test bus. Data is present on [3:0],
-	 *	and its corresponding select (enable) is present
-	 *	on bits [7:4].
-	 * @ate_reset: Reset input from automatic test equipment.
-	 *	This is a test signal. When the USB Core is
-	 *	powered up (not in Susned Mode), an automatic
-	 *	tester can use this to disable phy_clock and
-	 *	free_clk, then re-eanable them with an aligned
-	 *	phase.
-	 *	'1': The phy_clk and free_clk outputs are
-	 *	disabled. "0": The phy_clock and free_clk outputs
-	 *	are available within a specific period after the
-	 *	de-assertion.
-	 */
-	struct cvmx_usbnx_usbp_ctl_status_cn50xx {
-		uint64_t txrisetune		: 1;
-		uint64_t txvreftune		: 4;
-		uint64_t txfslstune		: 4;
-		uint64_t txhsxvtune		: 2;
-		uint64_t sqrxtune		: 3;
-		uint64_t compdistune		: 3;
-		uint64_t otgtune		: 3;
-		uint64_t otgdisable		: 1;
-		uint64_t portreset		: 1;
-		uint64_t drvvbus		: 1;
-		uint64_t lsbist			: 1;
-		uint64_t fsbist			: 1;
-		uint64_t hsbist			: 1;
-		uint64_t bist_done		: 1;
-		uint64_t bist_err		: 1;
-		uint64_t tdata_out		: 4;
-		uint64_t reserved_31_31		: 1;
-		uint64_t txpreemphasistune	: 1;
-		uint64_t dma_bmode		: 1;
-		uint64_t usbc_end		: 1;
-		uint64_t usbp_bist		: 1;
-		uint64_t tclk			: 1;
-		uint64_t dp_pulld		: 1;
-		uint64_t dm_pulld		: 1;
-		uint64_t hst_mode		: 1;
-		uint64_t reserved_19_22		: 4;
-		uint64_t tx_bs_enh		: 1;
-		uint64_t tx_bs_en		: 1;
-		uint64_t loop_enb		: 1;
-		uint64_t vtest_enb		: 1;
-		uint64_t bist_enb		: 1;
-		uint64_t tdata_sel		: 1;
-		uint64_t taddr_in		: 4;
-		uint64_t tdata_in		: 8;
-		uint64_t ate_reset		: 1;
-	} cn50xx;
-	/**
-	 * struct cvmx_usbnx_usbp_ctl_status_cn52xx
-	 * @txrisetune: HS Transmitter Rise/Fall Time Adjustment
-	 * @txvreftune: HS DC Voltage Level Adjustment
-	 * @txfslstune: FS/LS Source Impedence Adjustment
-	 * @txhsxvtune: Transmitter High-Speed Crossover Adjustment
-	 * @sqrxtune: Squelch Threshold Adjustment
-	 * @compdistune: Disconnect Threshold Adjustment
-	 * @otgtune: VBUS Valid Threshold Adjustment
-	 * @otgdisable: OTG Block Disable
-	 * @portreset: Per_Port Reset
-	 * @drvvbus: Drive VBUS
-	 * @lsbist: Low-Speed BIST Enable.
-	 * @fsbist: Full-Speed BIST Enable.
-	 * @hsbist: High-Speed BIST Enable.
-	 * @bist_done: PHY Bist Done.
-	 *	Asserted at the end of the PHY BIST sequence.
-	 * @bist_err: PHY Bist Error.
-	 *	Indicates an internal error was detected during
-	 *	the BIST sequence.
-	 * @tdata_out: PHY Test Data Out.
-	 *	Presents either internaly generated signals or
-	 *	test register contents, based upon the value of
-	 *	test_data_out_sel.
-	 * @siddq: Drives the USBP (USB-PHY) SIDDQ input.
-	 *	Normally should be set to zero.
-	 *	When customers have no intent to use USB PHY
-	 *	interface, they should:
-	 *	- still provide 3.3V to USB_VDD33, and
-	 *	- tie USB_REXT to 3.3V supply, and
-	 *	- set USBN*_USBP_CTL_STATUS[SIDDQ]=1
-	 * @txpreemphasistune: HS Transmitter Pre-Emphasis Enable
-	 * @dma_bmode: When set to 1 the L2C DMA address will be updated
-	 *	with byte-counts between packets. When set to 0
-	 *	the L2C DMA address is incremented to the next
-	 *	4-byte aligned address after adding byte-count.
-	 * @usbc_end: Bigendian input to the USB Core. This should be
-	 *	set to '0' for operation.
-	 * @usbp_bist: PHY, This is cleared '0' to run BIST on the USBP.
-	 * @tclk: PHY Test Clock, used to load TDATA_IN to the USBP.
-	 * @dp_pulld: PHY DP_PULLDOWN input to the USB-PHY.
-	 *	This signal enables the pull-down resistance on
-	 *	the D+ line. '1' pull down-resistance is connected
-	 *	to D+/ '0' pull down resistance is not connected
-	 *	to D+. When an A/B device is acting as a host
-	 *	(downstream-facing port), dp_pulldown and
-	 *	dm_pulldown are enabled. This must not toggle
-	 *	during normal opeartion.
-	 * @dm_pulld: PHY DM_PULLDOWN input to the USB-PHY.
-	 *	This signal enables the pull-down resistance on
-	 *	the D- line. '1' pull down-resistance is connected
-	 *	to D-. '0' pull down resistance is not connected
-	 *	to D-. When an A/B device is acting as a host
-	 *	(downstream-facing port), dp_pulldown and
-	 *	dm_pulldown are enabled. This must not toggle
-	 *	during normal opeartion.
-	 * @hst_mode: When '0' the USB is acting as HOST, when '1'
-	 *	USB is acting as device. This field needs to be
-	 *	set while the USB is in reset.
-	 * @tx_bs_enh: Transmit Bit Stuffing on [15:8].
-	 *	Enables or disables bit stuffing on data[15:8]
-	 *	when bit-stuffing is enabled.
-	 * @tx_bs_en: Transmit Bit Stuffing on [7:0].
-	 *	Enables or disables bit stuffing on data[7:0]
-	 *	when bit-stuffing is enabled.
-	 * @loop_enb: PHY Loopback Test Enable.
-	 *	'1': During data transmission the receive is
-	 *	enabled.
-	 *	'0': During data transmission the receive is
-	 *	disabled.
-	 *	Must be '0' for normal operation.
-	 * @vtest_enb: Analog Test Pin Enable.
-	 *	'1' The PHY's analog_test pin is enabled for the
-	 *	input and output of applicable analog test signals.
-	 *	'0' THe analog_test pin is disabled.
-	 * @bist_enb: Built-In Self Test Enable.
-	 *	Used to activate BIST in the PHY.
-	 * @tdata_sel: Test Data Out Select.
-	 *	'1' test_data_out[3:0] (PHY) register contents
-	 *	are output. '0' internaly generated signals are
-	 *	output.
-	 * @taddr_in: Mode Address for Test Interface.
-	 *	Specifies the register address for writing to or
-	 *	reading from the PHY test interface register.
-	 * @tdata_in: Internal Testing Register Input Data and Select
-	 *	This is a test bus. Data is present on [3:0],
-	 *	and its corresponding select (enable) is present
-	 *	on bits [7:4].
-	 * @ate_reset: Reset input from automatic test equipment.
-	 *	This is a test signal. When the USB Core is
-	 *	powered up (not in Susned Mode), an automatic
-	 *	tester can use this to disable phy_clock and
-	 *	free_clk, then re-eanable them with an aligned
-	 *	phase.
-	 *	'1': The phy_clk and free_clk outputs are
-	 *	disabled. "0": The phy_clock and free_clk outputs
-	 *	are available within a specific period after the
-	 *	de-assertion.
-	 */
-	struct cvmx_usbnx_usbp_ctl_status_cn52xx {
-		uint64_t txrisetune		: 1;
-		uint64_t txvreftune		: 4;
-		uint64_t txfslstune		: 4;
-		uint64_t txhsxvtune		: 2;
-		uint64_t sqrxtune		: 3;
-		uint64_t compdistune		: 3;
-		uint64_t otgtune		: 3;
-		uint64_t otgdisable		: 1;
-		uint64_t portreset		: 1;
-		uint64_t drvvbus		: 1;
-		uint64_t lsbist			: 1;
-		uint64_t fsbist			: 1;
-		uint64_t hsbist			: 1;
-		uint64_t bist_done		: 1;
-		uint64_t bist_err		: 1;
-		uint64_t tdata_out		: 4;
-		uint64_t siddq			: 1;
-		uint64_t txpreemphasistune	: 1;
-		uint64_t dma_bmode		: 1;
-		uint64_t usbc_end		: 1;
-		uint64_t usbp_bist		: 1;
-		uint64_t tclk			: 1;
-		uint64_t dp_pulld		: 1;
-		uint64_t dm_pulld		: 1;
-		uint64_t hst_mode		: 1;
-		uint64_t reserved_19_22		: 4;
-		uint64_t tx_bs_enh		: 1;
-		uint64_t tx_bs_en		: 1;
-		uint64_t loop_enb		: 1;
-		uint64_t vtest_enb		: 1;
-		uint64_t bist_enb		: 1;
-		uint64_t tdata_sel		: 1;
-		uint64_t taddr_in		: 4;
-		uint64_t tdata_in		: 8;
-		uint64_t ate_reset		: 1;
-	} cn52xx;
-};
-
-#endif
diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c
index 5dbbd14..d118952 100644
--- a/drivers/staging/octeon-usb/octeon-hcd.c
+++ b/drivers/staging/octeon-usb/octeon-hcd.c
@@ -4,6 +4,44 @@
  * for more details.
  *
  * Copyright (C) 2008 Cavium Networks
+ *
+ * Some parts of the code were originally released under BSD license:
+ *
+ * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *
+ *   * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export
+ * control laws, including the U.S. Export Administration Act and its associated
+ * regulations, and may be subject to export or import regulations in other
+ * countries.
+ *
+ * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+ * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
+ * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
+ * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION
+ * OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
+ * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
+ * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
+ * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
+ * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
+ * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -17,13 +55,379 @@
 #include <linux/delay.h>
 
 #include <asm/octeon/cvmx.h>
-#include "cvmx-usb.h"
 #include <asm/octeon/cvmx-iob-defs.h>
 
 #include <linux/usb/hcd.h>
 
 #include <linux/err.h>
 
+#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-helper.h>
+#include <asm/octeon/cvmx-sysinfo.h>
+#include <asm/octeon/cvmx-helper-board.h>
+
+#include "octeon-hcd.h"
+
+/**
+ * enum cvmx_usb_speed - the possible USB device speeds
+ *
+ * @CVMX_USB_SPEED_HIGH: Device is operation at 480Mbps
+ * @CVMX_USB_SPEED_FULL: Device is operation at 12Mbps
+ * @CVMX_USB_SPEED_LOW:  Device is operation at 1.5Mbps
+ */
+enum cvmx_usb_speed {
+	CVMX_USB_SPEED_HIGH = 0,
+	CVMX_USB_SPEED_FULL = 1,
+	CVMX_USB_SPEED_LOW = 2,
+};
+
+/**
+ * enum cvmx_usb_transfer - the possible USB transfer types
+ *
+ * @CVMX_USB_TRANSFER_CONTROL:	   USB transfer type control for hub and status
+ *				   transfers
+ * @CVMX_USB_TRANSFER_ISOCHRONOUS: USB transfer type isochronous for low
+ *				   priority periodic transfers
+ * @CVMX_USB_TRANSFER_BULK:	   USB transfer type bulk for large low priority
+ *				   transfers
+ * @CVMX_USB_TRANSFER_INTERRUPT:   USB transfer type interrupt for high priority
+ *				   periodic transfers
+ */
+enum cvmx_usb_transfer {
+	CVMX_USB_TRANSFER_CONTROL = 0,
+	CVMX_USB_TRANSFER_ISOCHRONOUS = 1,
+	CVMX_USB_TRANSFER_BULK = 2,
+	CVMX_USB_TRANSFER_INTERRUPT = 3,
+};
+
+/**
+ * enum cvmx_usb_direction - the transfer directions
+ *
+ * @CVMX_USB_DIRECTION_OUT: Data is transferring from Octeon to the device/host
+ * @CVMX_USB_DIRECTION_IN:  Data is transferring from the device/host to Octeon
+ */
+enum cvmx_usb_direction {
+	CVMX_USB_DIRECTION_OUT,
+	CVMX_USB_DIRECTION_IN,
+};
+
+/**
+ * enum cvmx_usb_complete - possible callback function status codes
+ *
+ * @CVMX_USB_COMPLETE_SUCCESS:	  The transaction / operation finished without
+ *				  any errors
+ * @CVMX_USB_COMPLETE_SHORT:	  FIXME: This is currently not implemented
+ * @CVMX_USB_COMPLETE_CANCEL:	  The transaction was canceled while in flight
+ *				  by a user call to cvmx_usb_cancel
+ * @CVMX_USB_COMPLETE_ERROR:	  The transaction aborted with an unexpected
+ *				  error status
+ * @CVMX_USB_COMPLETE_STALL:	  The transaction received a USB STALL response
+ *				  from the device
+ * @CVMX_USB_COMPLETE_XACTERR:	  The transaction failed with an error from the
+ *				  device even after a number of retries
+ * @CVMX_USB_COMPLETE_DATATGLERR: The transaction failed with a data toggle
+ *				  error even after a number of retries
+ * @CVMX_USB_COMPLETE_BABBLEERR:  The transaction failed with a babble error
+ * @CVMX_USB_COMPLETE_FRAMEERR:	  The transaction failed with a frame error
+ *				  even after a number of retries
+ */
+enum cvmx_usb_complete {
+	CVMX_USB_COMPLETE_SUCCESS,
+	CVMX_USB_COMPLETE_SHORT,
+	CVMX_USB_COMPLETE_CANCEL,
+	CVMX_USB_COMPLETE_ERROR,
+	CVMX_USB_COMPLETE_STALL,
+	CVMX_USB_COMPLETE_XACTERR,
+	CVMX_USB_COMPLETE_DATATGLERR,
+	CVMX_USB_COMPLETE_BABBLEERR,
+	CVMX_USB_COMPLETE_FRAMEERR,
+};
+
+/**
+ * struct cvmx_usb_port_status - the USB port status information
+ *
+ * @port_enabled:	1 = Usb port is enabled, 0 = disabled
+ * @port_over_current:	1 = Over current detected, 0 = Over current not
+ *			detected. Octeon doesn't support over current detection.
+ * @port_powered:	1 = Port power is being supplied to the device, 0 =
+ *			power is off. Octeon doesn't support turning port power
+ *			off.
+ * @port_speed:		Current port speed.
+ * @connected:		1 = A device is connected to the port, 0 = No device is
+ *			connected.
+ * @connect_change:	1 = Device connected state changed since the last set
+ *			status call.
+ */
+struct cvmx_usb_port_status {
+	uint32_t reserved		: 25;
+	uint32_t port_enabled		: 1;
+	uint32_t port_over_current	: 1;
+	uint32_t port_powered		: 1;
+	enum cvmx_usb_speed port_speed	: 2;
+	uint32_t connected		: 1;
+	uint32_t connect_change		: 1;
+};
+
+/**
+ * union cvmx_usb_control_header - the structure of a Control packet header
+ *
+ * @s.request_type:	Bit 7 tells the direction: 1=IN, 0=OUT
+ * @s.request		The standard usb request to make
+ * @s.value		Value parameter for the request in little endian format
+ * @s.index		Index for the request in little endian format
+ * @s.length		Length of the data associated with this request in
+ *			little endian format
+ */
+union cvmx_usb_control_header {
+	uint64_t u64;
+	struct {
+		uint64_t request_type   : 8;
+		uint64_t request        : 8;
+		uint64_t value          : 16;
+		uint64_t index          : 16;
+		uint64_t length         : 16;
+	} s;
+};
+
+/**
+ * struct cvmx_usb_iso_packet - descriptor for Isochronous packets
+ *
+ * @offset:	This is the offset in bytes into the main buffer where this data
+ *		is stored.
+ * @length:	This is the length in bytes of the data.
+ * @status:	This is the status of this individual packet transfer.
+ */
+struct cvmx_usb_iso_packet {
+	int offset;
+	int length;
+	enum cvmx_usb_complete status;
+};
+
+/**
+ * enum cvmx_usb_initialize_flags - flags used by the initialization function
+ *
+ * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI:    The USB port uses a 12MHz crystal
+ *					      as clock source at USB_XO and
+ *					      USB_XI.
+ * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND:   The USB port uses 12/24/48MHz 2.5V
+ *					      board clock source at USB_XO.
+ *					      USB_XI should be tied to GND.
+ * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK: Mask for clock speed field
+ * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ:    Speed of reference clock or
+ *					      crystal
+ * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ:    Speed of reference clock
+ * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ:    Speed of reference clock
+ * @CVMX_USB_INITIALIZE_FLAGS_NO_DMA:	      Disable DMA and used polled IO for
+ *					      data transfer use for the USB
+ */
+enum cvmx_usb_initialize_flags {
+	CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI		= 1 << 0,
+	CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND		= 1 << 1,
+	CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK	= 3 << 3,
+	CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ		= 1 << 3,
+	CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ		= 2 << 3,
+	CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ		= 3 << 3,
+	/* Bits 3-4 used to encode the clock frequency */
+	CVMX_USB_INITIALIZE_FLAGS_NO_DMA		= 1 << 5,
+};
+
+/**
+ * enum cvmx_usb_pipe_flags - internal flags for a pipe.
+ *
+ * @__CVMX_USB_PIPE_FLAGS_SCHEDULED: Used internally to determine if a pipe is
+ *				     actively using hardware. Do not use.
+ * @__CVMX_USB_PIPE_FLAGS_NEED_PING: Used internally to determine if a high
+ *				     speed pipe is in the ping state. Do not
+ *				     use.
+ */
+enum cvmx_usb_pipe_flags {
+	__CVMX_USB_PIPE_FLAGS_SCHEDULED	= 1 << 17,
+	__CVMX_USB_PIPE_FLAGS_NEED_PING	= 1 << 18,
+};
+
+/* Normal prefetch that use the pref instruction. */
+#define CVMX_PREFETCH(address, offset) asm volatile ("pref %[type], %[off](%[rbase])" : : [rbase] "d" (address), [off] "I" (offset), [type] "n" (0))
+
+/* Maximum number of times to retry failed transactions */
+#define MAX_RETRIES		3
+
+/* Maximum number of hardware channels supported by the USB block */
+#define MAX_CHANNELS		8
+
+/* The highest valid USB device address */
+#define MAX_USB_ADDRESS		127
+
+/* The highest valid USB endpoint number */
+#define MAX_USB_ENDPOINT	15
+
+/* The highest valid port number on a hub */
+#define MAX_USB_HUB_PORT	15
+
+/*
+ * The low level hardware can transfer a maximum of this number of bytes in each
+ * transfer. The field is 19 bits wide
+ */
+#define MAX_TRANSFER_BYTES	((1<<19)-1)
+
+/*
+ * The low level hardware can transfer a maximum of this number of packets in
+ * each transfer. The field is 10 bits wide
+ */
+#define MAX_TRANSFER_PACKETS	((1<<10)-1)
+
+enum {
+	USB_CLOCK_TYPE_REF_12,
+	USB_CLOCK_TYPE_REF_24,
+	USB_CLOCK_TYPE_REF_48,
+	USB_CLOCK_TYPE_CRYSTAL_12,
+};
+
+/**
+ * Logical transactions may take numerous low level
+ * transactions, especially when splits are concerned. This
+ * enum represents all of the possible stages a transaction can
+ * be in. Note that split completes are always even. This is so
+ * the NAK handler can backup to the previous low level
+ * transaction with a simple clearing of bit 0.
+ */
+enum cvmx_usb_stage {
+	CVMX_USB_STAGE_NON_CONTROL,
+	CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE,
+	CVMX_USB_STAGE_SETUP,
+	CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE,
+	CVMX_USB_STAGE_DATA,
+	CVMX_USB_STAGE_DATA_SPLIT_COMPLETE,
+	CVMX_USB_STAGE_STATUS,
+	CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE,
+};
+
+/**
+ * struct cvmx_usb_transaction - describes each pending USB transaction
+ *				 regardless of type. These are linked together
+ *				 to form a list of pending requests for a pipe.
+ *
+ * @node:		List node for transactions in the pipe.
+ * @type:		Type of transaction, duplicated of the pipe.
+ * @flags:		State flags for this transaction.
+ * @buffer:		User's physical buffer address to read/write.
+ * @buffer_length:	Size of the user's buffer in bytes.
+ * @control_header:	For control transactions, physical address of the 8
+ *			byte standard header.
+ * @iso_start_frame:	For ISO transactions, the starting frame number.
+ * @iso_number_packets:	For ISO transactions, the number of packets in the
+ *			request.
+ * @iso_packets:	For ISO transactions, the sub packets in the request.
+ * @actual_bytes:	Actual bytes transfer for this transaction.
+ * @stage:		For control transactions, the current stage.
+ * @urb:		URB.
+ */
+struct cvmx_usb_transaction {
+	struct list_head node;
+	enum cvmx_usb_transfer type;
+	uint64_t buffer;
+	int buffer_length;
+	uint64_t control_header;
+	int iso_start_frame;
+	int iso_number_packets;
+	struct cvmx_usb_iso_packet *iso_packets;
+	int xfersize;
+	int pktcnt;
+	int retries;
+	int actual_bytes;
+	enum cvmx_usb_stage stage;
+	struct urb *urb;
+};
+
+/**
+ * struct cvmx_usb_pipe - a pipe represents a virtual connection between Octeon
+ *			  and some USB device. It contains a list of pending
+ *			  request to the device.
+ *
+ * @node:		List node for pipe list
+ * @next:		Pipe after this one in the list
+ * @transactions:	List of pending transactions
+ * @interval:		For periodic pipes, the interval between packets in
+ *			frames
+ * @next_tx_frame:	The next frame this pipe is allowed to transmit on
+ * @flags:		State flags for this pipe
+ * @device_speed:	Speed of device connected to this pipe
+ * @transfer_type:	Type of transaction supported by this pipe
+ * @transfer_dir:	IN or OUT. Ignored for Control
+ * @multi_count:	Max packet in a row for the device
+ * @max_packet:		The device's maximum packet size in bytes
+ * @device_addr:	USB device address at other end of pipe
+ * @endpoint_num:	USB endpoint number at other end of pipe
+ * @hub_device_addr:	Hub address this device is connected to
+ * @hub_port:		Hub port this device is connected to
+ * @pid_toggle:		This toggles between 0/1 on every packet send to track
+ *			the data pid needed
+ * @channel:		Hardware DMA channel for this pipe
+ * @split_sc_frame:	The low order bits of the frame number the split
+ *			complete should be sent on
+ */
+struct cvmx_usb_pipe {
+	struct list_head node;
+	struct list_head transactions;
+	uint64_t interval;
+	uint64_t next_tx_frame;
+	enum cvmx_usb_pipe_flags flags;
+	enum cvmx_usb_speed device_speed;
+	enum cvmx_usb_transfer transfer_type;
+	enum cvmx_usb_direction transfer_dir;
+	int multi_count;
+	uint16_t max_packet;
+	uint8_t device_addr;
+	uint8_t endpoint_num;
+	uint8_t hub_device_addr;
+	uint8_t hub_port;
+	uint8_t pid_toggle;
+	uint8_t channel;
+	int8_t split_sc_frame;
+};
+
+struct cvmx_usb_tx_fifo {
+	struct {
+		int channel;
+		int size;
+		uint64_t address;
+	} entry[MAX_CHANNELS+1];
+	int head;
+	int tail;
+};
+
+/**
+ * struct cvmx_usb_state - the state of the USB block
+ *
+ * init_flags:		   Flags passed to initialize.
+ * index:		   Which USB block this is for.
+ * idle_hardware_channels: Bit set for every idle hardware channel.
+ * usbcx_hprt:		   Stored port status so we don't need to read a CSR to
+ *			   determine splits.
+ * pipe_for_channel:	   Map channels to pipes.
+ * pipe:		   Storage for pipes.
+ * indent:		   Used by debug output to indent functions.
+ * port_status:		   Last port status used for change notification.
+ * idle_pipes:		   List of open pipes that have no transactions.
+ * active_pipes:	   Active pipes indexed by transfer type.
+ * frame_number:	   Increments every SOF interrupt for time keeping.
+ * active_split:	   Points to the current active split, or NULL.
+ */
+struct cvmx_usb_state {
+	int init_flags;
+	int index;
+	int idle_hardware_channels;
+	union cvmx_usbcx_hprt usbcx_hprt;
+	struct cvmx_usb_pipe *pipe_for_channel[MAX_CHANNELS];
+	int indent;
+	struct cvmx_usb_port_status port_status;
+	struct list_head idle_pipes;
+	struct list_head active_pipes[4];
+	uint64_t frame_number;
+	struct cvmx_usb_transaction *active_split;
+	struct cvmx_usb_tx_fifo periodic;
+	struct cvmx_usb_tx_fifo nonperiodic;
+};
+
 struct octeon_hcd {
 	spinlock_t lock;
 	struct cvmx_usb_state usb;
@@ -31,15 +435,1530 @@
 	struct list_head dequeue_list;
 };
 
-/* convert between an HCD pointer and the corresponding struct octeon_hcd */
-static inline struct octeon_hcd *hcd_to_octeon(struct usb_hcd *hcd)
+/* This macro spins on a field waiting for it to reach a value */
+#define CVMX_WAIT_FOR_FIELD32(address, type, field, op, value, timeout_usec)\
+	({int result;							    \
+	do {								    \
+		uint64_t done = cvmx_get_cycle() + (uint64_t)timeout_usec * \
+			octeon_get_clock_rate() / 1000000;		    \
+		type c;							    \
+		while (1) {						    \
+			c.u32 = __cvmx_usb_read_csr32(usb, address);	    \
+			if (c.s.field op (value)) {			    \
+				result = 0;				    \
+				break;					    \
+			} else if (cvmx_get_cycle() > done) {		    \
+				result = -1;				    \
+				break;					    \
+			} else						    \
+				cvmx_wait(100);				    \
+		}							    \
+	} while (0);							    \
+	result; })
+
+/*
+ * This macro logically sets a single field in a CSR. It does the sequence
+ * read, modify, and write
+ */
+#define USB_SET_FIELD32(address, type, field, value)		\
+	do {							\
+		type c;						\
+		c.u32 = __cvmx_usb_read_csr32(usb, address);	\
+		c.s.field = value;				\
+		__cvmx_usb_write_csr32(usb, address, c.u32);	\
+	} while (0)
+
+/* Returns the IO address to push/pop stuff data from the FIFOs */
+#define USB_FIFO_ADDRESS(channel, usb_index) (CVMX_USBCX_GOTGCTL(usb_index) + ((channel)+1)*0x1000)
+
+static int octeon_usb_get_clock_type(void)
 {
-	return (struct octeon_hcd *)(hcd->hcd_priv);
+	switch (cvmx_sysinfo_get()->board_type) {
+	case CVMX_BOARD_TYPE_BBGW_REF:
+	case CVMX_BOARD_TYPE_LANAI2_A:
+	case CVMX_BOARD_TYPE_LANAI2_U:
+	case CVMX_BOARD_TYPE_LANAI2_G:
+	case CVMX_BOARD_TYPE_UBNT_E100:
+		return USB_CLOCK_TYPE_CRYSTAL_12;
+	}
+	return USB_CLOCK_TYPE_REF_48;
 }
 
-static inline struct usb_hcd *octeon_to_hcd(struct octeon_hcd *p)
+/**
+ * Read a USB 32bit CSR. It performs the necessary address swizzle
+ * for 32bit CSRs and logs the value in a readable format if
+ * debugging is on.
+ *
+ * @usb:     USB block this access is for
+ * @address: 64bit address to read
+ *
+ * Returns: Result of the read
+ */
+static inline uint32_t __cvmx_usb_read_csr32(struct cvmx_usb_state *usb,
+					     uint64_t address)
 {
-	return container_of((void *)p, struct usb_hcd, hcd_priv);
+	uint32_t result = cvmx_read64_uint32(address ^ 4);
+	return result;
+}
+
+
+/**
+ * Write a USB 32bit CSR. It performs the necessary address
+ * swizzle for 32bit CSRs and logs the value in a readable format
+ * if debugging is on.
+ *
+ * @usb:     USB block this access is for
+ * @address: 64bit address to write
+ * @value:   Value to write
+ */
+static inline void __cvmx_usb_write_csr32(struct cvmx_usb_state *usb,
+					  uint64_t address, uint32_t value)
+{
+	cvmx_write64_uint32(address ^ 4, value);
+	cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index));
+}
+
+
+/**
+ * Read a USB 64bit CSR. It logs the value in a readable format if
+ * debugging is on.
+ *
+ * @usb:     USB block this access is for
+ * @address: 64bit address to read
+ *
+ * Returns: Result of the read
+ */
+static inline uint64_t __cvmx_usb_read_csr64(struct cvmx_usb_state *usb,
+					     uint64_t address)
+{
+	uint64_t result = cvmx_read64_uint64(address);
+	return result;
+}
+
+
+/**
+ * Write a USB 64bit CSR. It logs the value in a readable format
+ * if debugging is on.
+ *
+ * @usb:     USB block this access is for
+ * @address: 64bit address to write
+ * @value:   Value to write
+ */
+static inline void __cvmx_usb_write_csr64(struct cvmx_usb_state *usb,
+					  uint64_t address, uint64_t value)
+{
+	cvmx_write64_uint64(address, value);
+}
+
+/**
+ * Return non zero if this pipe connects to a non HIGH speed
+ * device through a high speed hub.
+ *
+ * @usb:    USB block this access is for
+ * @pipe:   Pipe to check
+ *
+ * Returns: Non zero if we need to do split transactions
+ */
+static inline int __cvmx_usb_pipe_needs_split(struct cvmx_usb_state *usb,
+					      struct cvmx_usb_pipe *pipe)
+{
+	return pipe->device_speed != CVMX_USB_SPEED_HIGH &&
+	       usb->usbcx_hprt.s.prtspd == CVMX_USB_SPEED_HIGH;
+}
+
+
+/**
+ * Trivial utility function to return the correct PID for a pipe
+ *
+ * @pipe:   pipe to check
+ *
+ * Returns: PID for pipe
+ */
+static inline int __cvmx_usb_get_data_pid(struct cvmx_usb_pipe *pipe)
+{
+	if (pipe->pid_toggle)
+		return 2; /* Data1 */
+	else
+		return 0; /* Data0 */
+}
+
+
+/**
+ * Return the number of USB ports supported by this Octeon
+ * chip. If the chip doesn't support USB, or is not supported
+ * by this API, a zero will be returned. Most Octeon chips
+ * support one usb port, but some support two ports.
+ * cvmx_usb_initialize() must be called on independent
+ * struct cvmx_usb_state.
+ *
+ * Returns: Number of port, zero if usb isn't supported
+ */
+static int cvmx_usb_get_num_ports(void)
+{
+	int arch_ports = 0;
+
+	if (OCTEON_IS_MODEL(OCTEON_CN56XX))
+		arch_ports = 1;
+	else if (OCTEON_IS_MODEL(OCTEON_CN52XX))
+		arch_ports = 2;
+	else if (OCTEON_IS_MODEL(OCTEON_CN50XX))
+		arch_ports = 1;
+	else if (OCTEON_IS_MODEL(OCTEON_CN31XX))
+		arch_ports = 1;
+	else if (OCTEON_IS_MODEL(OCTEON_CN30XX))
+		arch_ports = 1;
+	else
+		arch_ports = 0;
+
+	return arch_ports;
+}
+
+/**
+ * Initialize a USB port for use. This must be called before any
+ * other access to the Octeon USB port is made. The port starts
+ * off in the disabled state.
+ *
+ * @usb:	 Pointer to an empty struct cvmx_usb_state
+ *		 that will be populated by the initialize call.
+ *		 This structure is then passed to all other USB
+ *		 functions.
+ * @usb_port_number:
+ *		 Which Octeon USB port to initialize.
+ *
+ * Returns: 0 or a negative error code.
+ */
+static int cvmx_usb_initialize(struct cvmx_usb_state *usb,
+			       int usb_port_number)
+{
+	union cvmx_usbnx_clk_ctl usbn_clk_ctl;
+	union cvmx_usbnx_usbp_ctl_status usbn_usbp_ctl_status;
+	enum cvmx_usb_initialize_flags flags = 0;
+	int i;
+
+	/* At first allow 0-1 for the usb port number */
+	if ((usb_port_number < 0) || (usb_port_number > 1))
+		return -EINVAL;
+	/* For all chips except 52XX there is only one port */
+	if (!OCTEON_IS_MODEL(OCTEON_CN52XX) && (usb_port_number > 0))
+		return -EINVAL;
+	/* Try to determine clock type automatically */
+	if (octeon_usb_get_clock_type() == USB_CLOCK_TYPE_CRYSTAL_12) {
+		/* Only 12 MHZ crystals are supported */
+		flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI;
+	} else {
+		flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND;
+
+		switch (octeon_usb_get_clock_type()) {
+		case USB_CLOCK_TYPE_REF_12:
+			flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ;
+			break;
+		case USB_CLOCK_TYPE_REF_24:
+			flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ;
+			break;
+		case USB_CLOCK_TYPE_REF_48:
+			flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ;
+			break;
+		default:
+			return -EINVAL;
+			break;
+		}
+	}
+
+	memset(usb, 0, sizeof(*usb));
+	usb->init_flags = flags;
+
+	/* Initialize the USB state structure */
+	usb->index = usb_port_number;
+	INIT_LIST_HEAD(&usb->idle_pipes);
+	for (i = 0; i < ARRAY_SIZE(usb->active_pipes); i++)
+		INIT_LIST_HEAD(&usb->active_pipes[i]);
+
+	/*
+	 * Power On Reset and PHY Initialization
+	 *
+	 * 1. Wait for DCOK to assert (nothing to do)
+	 *
+	 * 2a. Write USBN0/1_CLK_CTL[POR] = 1 and
+	 *     USBN0/1_CLK_CTL[HRST,PRST,HCLK_RST] = 0
+	 */
+	usbn_clk_ctl.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index));
+	usbn_clk_ctl.s.por = 1;
+	usbn_clk_ctl.s.hrst = 0;
+	usbn_clk_ctl.s.prst = 0;
+	usbn_clk_ctl.s.hclk_rst = 0;
+	usbn_clk_ctl.s.enable = 0;
+	/*
+	 * 2b. Select the USB reference clock/crystal parameters by writing
+	 *     appropriate values to USBN0/1_CLK_CTL[P_C_SEL, P_RTYPE, P_COM_ON]
+	 */
+	if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND) {
+		/*
+		 * The USB port uses 12/24/48MHz 2.5V board clock
+		 * source at USB_XO. USB_XI should be tied to GND.
+		 * Most Octeon evaluation boards require this setting
+		 */
+		if (OCTEON_IS_MODEL(OCTEON_CN3XXX) ||
+		    OCTEON_IS_MODEL(OCTEON_CN56XX) ||
+		    OCTEON_IS_MODEL(OCTEON_CN50XX))
+			/* From CN56XX,CN50XX,CN31XX,CN30XX manuals */
+			usbn_clk_ctl.s.p_rtype = 2; /* p_rclk=1 & p_xenbn=0 */
+		else
+			/* From CN52XX manual */
+			usbn_clk_ctl.s.p_rtype = 1;
+
+		switch (flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK) {
+		case CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ:
+			usbn_clk_ctl.s.p_c_sel = 0;
+			break;
+		case CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ:
+			usbn_clk_ctl.s.p_c_sel = 1;
+			break;
+		case CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ:
+			usbn_clk_ctl.s.p_c_sel = 2;
+			break;
+		}
+	} else {
+		/*
+		 * The USB port uses a 12MHz crystal as clock source
+		 * at USB_XO and USB_XI
+		 */
+		if (OCTEON_IS_MODEL(OCTEON_CN3XXX))
+			/* From CN31XX,CN30XX manual */
+			usbn_clk_ctl.s.p_rtype = 3; /* p_rclk=1 & p_xenbn=1 */
+		else
+			/* From CN56XX,CN52XX,CN50XX manuals. */
+			usbn_clk_ctl.s.p_rtype = 0;
+
+		usbn_clk_ctl.s.p_c_sel = 0;
+	}
+	/*
+	 * 2c. Select the HCLK via writing USBN0/1_CLK_CTL[DIVIDE, DIVIDE2] and
+	 *     setting USBN0/1_CLK_CTL[ENABLE] = 1. Divide the core clock down
+	 *     such that USB is as close as possible to 125Mhz
+	 */
+	{
+		int divisor = (octeon_get_clock_rate()+125000000-1)/125000000;
+		/* Lower than 4 doesn't seem to work properly */
+		if (divisor < 4)
+			divisor = 4;
+		usbn_clk_ctl.s.divide = divisor;
+		usbn_clk_ctl.s.divide2 = 0;
+	}
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
+			       usbn_clk_ctl.u64);
+	/* 2d. Write USBN0/1_CLK_CTL[HCLK_RST] = 1 */
+	usbn_clk_ctl.s.hclk_rst = 1;
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
+			       usbn_clk_ctl.u64);
+	/* 2e.  Wait 64 core-clock cycles for HCLK to stabilize */
+	cvmx_wait(64);
+	/*
+	 * 3. Program the power-on reset field in the USBN clock-control
+	 *    register:
+	 *    USBN_CLK_CTL[POR] = 0
+	 */
+	usbn_clk_ctl.s.por = 0;
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
+			       usbn_clk_ctl.u64);
+	/* 4. Wait 1 ms for PHY clock to start */
+	mdelay(1);
+	/*
+	 * 5. Program the Reset input from automatic test equipment field in the
+	 *    USBP control and status register:
+	 *    USBN_USBP_CTL_STATUS[ATE_RESET] = 1
+	 */
+	usbn_usbp_ctl_status.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index));
+	usbn_usbp_ctl_status.s.ate_reset = 1;
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index),
+			       usbn_usbp_ctl_status.u64);
+	/* 6. Wait 10 cycles */
+	cvmx_wait(10);
+	/*
+	 * 7. Clear ATE_RESET field in the USBN clock-control register:
+	 *    USBN_USBP_CTL_STATUS[ATE_RESET] = 0
+	 */
+	usbn_usbp_ctl_status.s.ate_reset = 0;
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index),
+			       usbn_usbp_ctl_status.u64);
+	/*
+	 * 8. Program the PHY reset field in the USBN clock-control register:
+	 *    USBN_CLK_CTL[PRST] = 1
+	 */
+	usbn_clk_ctl.s.prst = 1;
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
+			       usbn_clk_ctl.u64);
+	/*
+	 * 9. Program the USBP control and status register to select host or
+	 *    device mode. USBN_USBP_CTL_STATUS[HST_MODE] = 0 for host, = 1 for
+	 *    device
+	 */
+	usbn_usbp_ctl_status.s.hst_mode = 0;
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index),
+			       usbn_usbp_ctl_status.u64);
+	/* 10. Wait 1 us */
+	udelay(1);
+	/*
+	 * 11. Program the hreset_n field in the USBN clock-control register:
+	 *     USBN_CLK_CTL[HRST] = 1
+	 */
+	usbn_clk_ctl.s.hrst = 1;
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
+			       usbn_clk_ctl.u64);
+	/* 12. Proceed to USB core initialization */
+	usbn_clk_ctl.s.enable = 1;
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
+			       usbn_clk_ctl.u64);
+	udelay(1);
+
+	/*
+	 * USB Core Initialization
+	 *
+	 * 1. Read USBC_GHWCFG1, USBC_GHWCFG2, USBC_GHWCFG3, USBC_GHWCFG4 to
+	 *    determine USB core configuration parameters.
+	 *
+	 *    Nothing needed
+	 *
+	 * 2. Program the following fields in the global AHB configuration
+	 *    register (USBC_GAHBCFG)
+	 *    DMA mode, USBC_GAHBCFG[DMAEn]: 1 = DMA mode, 0 = slave mode
+	 *    Burst length, USBC_GAHBCFG[HBSTLEN] = 0
+	 *    Nonperiodic TxFIFO empty level (slave mode only),
+	 *    USBC_GAHBCFG[NPTXFEMPLVL]
+	 *    Periodic TxFIFO empty level (slave mode only),
+	 *    USBC_GAHBCFG[PTXFEMPLVL]
+	 *    Global interrupt mask, USBC_GAHBCFG[GLBLINTRMSK] = 1
+	 */
+	{
+		union cvmx_usbcx_gahbcfg usbcx_gahbcfg;
+		/* Due to an errata, CN31XX doesn't support DMA */
+		if (OCTEON_IS_MODEL(OCTEON_CN31XX))
+			usb->init_flags |= CVMX_USB_INITIALIZE_FLAGS_NO_DMA;
+		usbcx_gahbcfg.u32 = 0;
+		usbcx_gahbcfg.s.dmaen = !(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA);
+		if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
+			/* Only use one channel with non DMA */
+			usb->idle_hardware_channels = 0x1;
+		else if (OCTEON_IS_MODEL(OCTEON_CN5XXX))
+			/* CN5XXX have an errata with channel 3 */
+			usb->idle_hardware_channels = 0xf7;
+		else
+			usb->idle_hardware_channels = 0xff;
+		usbcx_gahbcfg.s.hbstlen = 0;
+		usbcx_gahbcfg.s.nptxfemplvl = 1;
+		usbcx_gahbcfg.s.ptxfemplvl = 1;
+		usbcx_gahbcfg.s.glblintrmsk = 1;
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_GAHBCFG(usb->index),
+				       usbcx_gahbcfg.u32);
+	}
+	/*
+	 * 3. Program the following fields in USBC_GUSBCFG register.
+	 *    HS/FS timeout calibration, USBC_GUSBCFG[TOUTCAL] = 0
+	 *    ULPI DDR select, USBC_GUSBCFG[DDRSEL] = 0
+	 *    USB turnaround time, USBC_GUSBCFG[USBTRDTIM] = 0x5
+	 *    PHY low-power clock select, USBC_GUSBCFG[PHYLPWRCLKSEL] = 0
+	 */
+	{
+		union cvmx_usbcx_gusbcfg usbcx_gusbcfg;
+		usbcx_gusbcfg.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index));
+		usbcx_gusbcfg.s.toutcal = 0;
+		usbcx_gusbcfg.s.ddrsel = 0;
+		usbcx_gusbcfg.s.usbtrdtim = 0x5;
+		usbcx_gusbcfg.s.phylpwrclksel = 0;
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index),
+				       usbcx_gusbcfg.u32);
+	}
+	/*
+	 * 4. The software must unmask the following bits in the USBC_GINTMSK
+	 *    register.
+	 *    OTG interrupt mask, USBC_GINTMSK[OTGINTMSK] = 1
+	 *    Mode mismatch interrupt mask, USBC_GINTMSK[MODEMISMSK] = 1
+	 */
+	{
+		union cvmx_usbcx_gintmsk usbcx_gintmsk;
+		int channel;
+
+		usbcx_gintmsk.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GINTMSK(usb->index));
+		usbcx_gintmsk.s.otgintmsk = 1;
+		usbcx_gintmsk.s.modemismsk = 1;
+		usbcx_gintmsk.s.hchintmsk = 1;
+		usbcx_gintmsk.s.sofmsk = 0;
+		/* We need RX FIFO interrupts if we don't have DMA */
+		if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
+			usbcx_gintmsk.s.rxflvlmsk = 1;
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTMSK(usb->index),
+				       usbcx_gintmsk.u32);
+
+		/*
+		 * Disable all channel interrupts. We'll enable them per channel
+		 * later.
+		 */
+		for (channel = 0; channel < 8; channel++)
+			__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), 0);
+	}
+
+	{
+		/*
+		 * Host Port Initialization
+		 *
+		 * 1. Program the host-port interrupt-mask field to unmask,
+		 *    USBC_GINTMSK[PRTINT] = 1
+		 */
+		USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk,
+				prtintmsk, 1);
+		USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk,
+				disconnintmsk, 1);
+		/*
+		 * 2. Program the USBC_HCFG register to select full-speed host
+		 *    or high-speed host.
+		 */
+		{
+			union cvmx_usbcx_hcfg usbcx_hcfg;
+			usbcx_hcfg.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCFG(usb->index));
+			usbcx_hcfg.s.fslssupp = 0;
+			usbcx_hcfg.s.fslspclksel = 0;
+			__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCFG(usb->index), usbcx_hcfg.u32);
+		}
+		/*
+		 * 3. Program the port power bit to drive VBUS on the USB,
+		 *    USBC_HPRT[PRTPWR] = 1
+		 */
+		USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt, prtpwr, 1);
+
+		/*
+		 * Steps 4-15 from the manual are done later in the port enable
+		 */
+	}
+
+	return 0;
+}
+
+
+/**
+ * Shutdown a USB port after a call to cvmx_usb_initialize().
+ * The port should be disabled with all pipes closed when this
+ * function is called.
+ *
+ * @usb: USB device state populated by cvmx_usb_initialize().
+ *
+ * Returns: 0 or a negative error code.
+ */
+static int cvmx_usb_shutdown(struct cvmx_usb_state *usb)
+{
+	union cvmx_usbnx_clk_ctl usbn_clk_ctl;
+
+	/* Make sure all pipes are closed */
+	if (!list_empty(&usb->idle_pipes) ||
+	    !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_ISOCHRONOUS]) ||
+	    !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_INTERRUPT]) ||
+	    !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_CONTROL]) ||
+	    !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_BULK]))
+		return -EBUSY;
+
+	/* Disable the clocks and put them in power on reset */
+	usbn_clk_ctl.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index));
+	usbn_clk_ctl.s.enable = 1;
+	usbn_clk_ctl.s.por = 1;
+	usbn_clk_ctl.s.hclk_rst = 1;
+	usbn_clk_ctl.s.prst = 0;
+	usbn_clk_ctl.s.hrst = 0;
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index),
+			       usbn_clk_ctl.u64);
+	return 0;
+}
+
+
+/**
+ * Enable a USB port. After this call succeeds, the USB port is
+ * online and servicing requests.
+ *
+ * @usb: USB device state populated by cvmx_usb_initialize().
+ *
+ * Returns: 0 or a negative error code.
+ */
+static int cvmx_usb_enable(struct cvmx_usb_state *usb)
+{
+	union cvmx_usbcx_ghwcfg3 usbcx_ghwcfg3;
+
+	usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
+
+	/*
+	 * If the port is already enabled the just return. We don't need to do
+	 * anything
+	 */
+	if (usb->usbcx_hprt.s.prtena)
+		return 0;
+
+	/* If there is nothing plugged into the port then fail immediately */
+	if (!usb->usbcx_hprt.s.prtconnsts) {
+		return -ETIMEDOUT;
+	}
+
+	/* Program the port reset bit to start the reset process */
+	USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt, prtrst, 1);
+
+	/*
+	 * Wait at least 50ms (high speed), or 10ms (full speed) for the reset
+	 * process to complete.
+	 */
+	mdelay(50);
+
+	/* Program the port reset bit to 0, USBC_HPRT[PRTRST] = 0 */
+	USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt, prtrst, 0);
+
+	/* Wait for the USBC_HPRT[PRTENA]. */
+	if (CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt,
+				  prtena, ==, 1, 100000))
+		return -ETIMEDOUT;
+
+	/*
+	 * Read the port speed field to get the enumerated speed,
+	 * USBC_HPRT[PRTSPD].
+	 */
+	usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
+	usbcx_ghwcfg3.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GHWCFG3(usb->index));
+
+	/*
+	 * 13. Program the USBC_GRXFSIZ register to select the size of the
+	 *     receive FIFO (25%).
+	 */
+	USB_SET_FIELD32(CVMX_USBCX_GRXFSIZ(usb->index), union cvmx_usbcx_grxfsiz,
+			rxfdep, usbcx_ghwcfg3.s.dfifodepth / 4);
+	/*
+	 * 14. Program the USBC_GNPTXFSIZ register to select the size and the
+	 *     start address of the non- periodic transmit FIFO for nonperiodic
+	 *     transactions (50%).
+	 */
+	{
+		union cvmx_usbcx_gnptxfsiz siz;
+		siz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index));
+		siz.s.nptxfdep = usbcx_ghwcfg3.s.dfifodepth / 2;
+		siz.s.nptxfstaddr = usbcx_ghwcfg3.s.dfifodepth / 4;
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index), siz.u32);
+	}
+	/*
+	 * 15. Program the USBC_HPTXFSIZ register to select the size and start
+	 *     address of the periodic transmit FIFO for periodic transactions
+	 *     (25%).
+	 */
+	{
+		union cvmx_usbcx_hptxfsiz siz;
+		siz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index));
+		siz.s.ptxfsize = usbcx_ghwcfg3.s.dfifodepth / 4;
+		siz.s.ptxfstaddr = 3 * usbcx_ghwcfg3.s.dfifodepth / 4;
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index), siz.u32);
+	}
+	/* Flush all FIFOs */
+	USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl, txfnum, 0x10);
+	USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl, txfflsh, 1);
+	CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl,
+			      txfflsh, ==, 0, 100);
+	USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl, rxfflsh, 1);
+	CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl,
+			      rxfflsh, ==, 0, 100);
+
+	return 0;
+}
+
+
+/**
+ * Disable a USB port. After this call the USB port will not
+ * generate data transfers and will not generate events.
+ * Transactions in process will fail and call their
+ * associated callbacks.
+ *
+ * @usb: USB device state populated by cvmx_usb_initialize().
+ *
+ * Returns: 0 or a negative error code.
+ */
+static int cvmx_usb_disable(struct cvmx_usb_state *usb)
+{
+	/* Disable the port */
+	USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt, prtena, 1);
+	return 0;
+}
+
+
+/**
+ * Get the current state of the USB port. Use this call to
+ * determine if the usb port has anything connected, is enabled,
+ * or has some sort of error condition. The return value of this
+ * call has "changed" bits to signal of the value of some fields
+ * have changed between calls.
+ *
+ * @usb: USB device state populated by cvmx_usb_initialize().
+ *
+ * Returns: Port status information
+ */
+static struct cvmx_usb_port_status cvmx_usb_get_status(struct cvmx_usb_state *usb)
+{
+	union cvmx_usbcx_hprt usbc_hprt;
+	struct cvmx_usb_port_status result;
+
+	memset(&result, 0, sizeof(result));
+
+	usbc_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
+	result.port_enabled = usbc_hprt.s.prtena;
+	result.port_over_current = usbc_hprt.s.prtovrcurract;
+	result.port_powered = usbc_hprt.s.prtpwr;
+	result.port_speed = usbc_hprt.s.prtspd;
+	result.connected = usbc_hprt.s.prtconnsts;
+	result.connect_change = (result.connected != usb->port_status.connected);
+
+	return result;
+}
+
+/**
+ * Open a virtual pipe between the host and a USB device. A pipe
+ * must be opened before data can be transferred between a device
+ * and Octeon.
+ *
+ * @usb:	     USB device state populated by cvmx_usb_initialize().
+ * @device_addr:
+ *		     USB device address to open the pipe to
+ *		     (0-127).
+ * @endpoint_num:
+ *		     USB endpoint number to open the pipe to
+ *		     (0-15).
+ * @device_speed:
+ *		     The speed of the device the pipe is going
+ *		     to. This must match the device's speed,
+ *		     which may be different than the port speed.
+ * @max_packet:	     The maximum packet length the device can
+ *		     transmit/receive (low speed=0-8, full
+ *		     speed=0-1023, high speed=0-1024). This value
+ *		     comes from the standard endpoint descriptor
+ *		     field wMaxPacketSize bits <10:0>.
+ * @transfer_type:
+ *		     The type of transfer this pipe is for.
+ * @transfer_dir:
+ *		     The direction the pipe is in. This is not
+ *		     used for control pipes.
+ * @interval:	     For ISOCHRONOUS and INTERRUPT transfers,
+ *		     this is how often the transfer is scheduled
+ *		     for. All other transfers should specify
+ *		     zero. The units are in frames (8000/sec at
+ *		     high speed, 1000/sec for full speed).
+ * @multi_count:
+ *		     For high speed devices, this is the maximum
+ *		     allowed number of packet per microframe.
+ *		     Specify zero for non high speed devices. This
+ *		     value comes from the standard endpoint descriptor
+ *		     field wMaxPacketSize bits <12:11>.
+ * @hub_device_addr:
+ *		     Hub device address this device is connected
+ *		     to. Devices connected directly to Octeon
+ *		     use zero. This is only used when the device
+ *		     is full/low speed behind a high speed hub.
+ *		     The address will be of the high speed hub,
+ *		     not and full speed hubs after it.
+ * @hub_port:	     Which port on the hub the device is
+ *		     connected. Use zero for devices connected
+ *		     directly to Octeon. Like hub_device_addr,
+ *		     this is only used for full/low speed
+ *		     devices behind a high speed hub.
+ *
+ * Returns: A non-NULL value is a pipe. NULL means an error.
+ */
+static struct cvmx_usb_pipe *cvmx_usb_open_pipe(struct cvmx_usb_state *usb,
+						int device_addr, int
+						endpoint_num,
+						enum cvmx_usb_speed
+							device_speed,
+						int max_packet,
+						enum cvmx_usb_transfer
+							transfer_type,
+						enum cvmx_usb_direction
+							transfer_dir,
+						int interval, int multi_count,
+						int hub_device_addr,
+						int hub_port)
+{
+	struct cvmx_usb_pipe *pipe;
+
+	if (unlikely((device_addr < 0) || (device_addr > MAX_USB_ADDRESS)))
+		return NULL;
+	if (unlikely((endpoint_num < 0) || (endpoint_num > MAX_USB_ENDPOINT)))
+		return NULL;
+	if (unlikely(device_speed > CVMX_USB_SPEED_LOW))
+		return NULL;
+	if (unlikely((max_packet <= 0) || (max_packet > 1024)))
+		return NULL;
+	if (unlikely(transfer_type > CVMX_USB_TRANSFER_INTERRUPT))
+		return NULL;
+	if (unlikely((transfer_dir != CVMX_USB_DIRECTION_OUT) &&
+		(transfer_dir != CVMX_USB_DIRECTION_IN)))
+		return NULL;
+	if (unlikely(interval < 0))
+		return NULL;
+	if (unlikely((transfer_type == CVMX_USB_TRANSFER_CONTROL) && interval))
+		return NULL;
+	if (unlikely(multi_count < 0))
+		return NULL;
+	if (unlikely((device_speed != CVMX_USB_SPEED_HIGH) &&
+		(multi_count != 0)))
+		return NULL;
+	if (unlikely((hub_device_addr < 0) || (hub_device_addr > MAX_USB_ADDRESS)))
+		return NULL;
+	if (unlikely((hub_port < 0) || (hub_port > MAX_USB_HUB_PORT)))
+		return NULL;
+
+	pipe = kzalloc(sizeof(*pipe), GFP_ATOMIC);
+	if (!pipe)
+		return NULL;
+	if ((device_speed == CVMX_USB_SPEED_HIGH) &&
+		(transfer_dir == CVMX_USB_DIRECTION_OUT) &&
+		(transfer_type == CVMX_USB_TRANSFER_BULK))
+		pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING;
+	pipe->device_addr = device_addr;
+	pipe->endpoint_num = endpoint_num;
+	pipe->device_speed = device_speed;
+	pipe->max_packet = max_packet;
+	pipe->transfer_type = transfer_type;
+	pipe->transfer_dir = transfer_dir;
+	INIT_LIST_HEAD(&pipe->transactions);
+
+	/*
+	 * All pipes use interval to rate limit NAK processing. Force an
+	 * interval if one wasn't supplied
+	 */
+	if (!interval)
+		interval = 1;
+	if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+		pipe->interval = interval*8;
+		/* Force start splits to be schedule on uFrame 0 */
+		pipe->next_tx_frame = ((usb->frame_number+7)&~7) + pipe->interval;
+	} else {
+		pipe->interval = interval;
+		pipe->next_tx_frame = usb->frame_number + pipe->interval;
+	}
+	pipe->multi_count = multi_count;
+	pipe->hub_device_addr = hub_device_addr;
+	pipe->hub_port = hub_port;
+	pipe->pid_toggle = 0;
+	pipe->split_sc_frame = -1;
+	list_add_tail(&pipe->node, &usb->idle_pipes);
+
+	/*
+	 * We don't need to tell the hardware about this pipe yet since
+	 * it doesn't have any submitted requests
+	 */
+
+	return pipe;
+}
+
+
+/**
+ * Poll the RX FIFOs and remove data as needed. This function is only used
+ * in non DMA mode. It is very important that this function be called quickly
+ * enough to prevent FIFO overflow.
+ *
+ * @usb:	USB device state populated by cvmx_usb_initialize().
+ */
+static void __cvmx_usb_poll_rx_fifo(struct cvmx_usb_state *usb)
+{
+	union cvmx_usbcx_grxstsph rx_status;
+	int channel;
+	int bytes;
+	uint64_t address;
+	uint32_t *ptr;
+
+	rx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GRXSTSPH(usb->index));
+	/* Only read data if IN data is there */
+	if (rx_status.s.pktsts != 2)
+		return;
+	/* Check if no data is available */
+	if (!rx_status.s.bcnt)
+		return;
+
+	channel = rx_status.s.chnum;
+	bytes = rx_status.s.bcnt;
+	if (!bytes)
+		return;
+
+	/* Get where the DMA engine would have written this data */
+	address = __cvmx_usb_read_csr64(usb, CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8);
+	ptr = cvmx_phys_to_ptr(address);
+	__cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8, address + bytes);
+
+	/* Loop writing the FIFO data for this packet into memory */
+	while (bytes > 0) {
+		*ptr++ = __cvmx_usb_read_csr32(usb, USB_FIFO_ADDRESS(channel, usb->index));
+		bytes -= 4;
+	}
+	CVMX_SYNCW;
+
+	return;
+}
+
+
+/**
+ * Fill the TX hardware fifo with data out of the software
+ * fifos
+ *
+ * @usb:	    USB device state populated by cvmx_usb_initialize().
+ * @fifo:	    Software fifo to use
+ * @available:	    Amount of space in the hardware fifo
+ *
+ * Returns: Non zero if the hardware fifo was too small and needs
+ *	    to be serviced again.
+ */
+static int __cvmx_usb_fill_tx_hw(struct cvmx_usb_state *usb,
+				 struct cvmx_usb_tx_fifo *fifo, int available)
+{
+	/*
+	 * We're done either when there isn't anymore space or the software FIFO
+	 * is empty
+	 */
+	while (available && (fifo->head != fifo->tail)) {
+		int i = fifo->tail;
+		const uint32_t *ptr = cvmx_phys_to_ptr(fifo->entry[i].address);
+		uint64_t csr_address = USB_FIFO_ADDRESS(fifo->entry[i].channel, usb->index) ^ 4;
+		int words = available;
+
+		/* Limit the amount of data to waht the SW fifo has */
+		if (fifo->entry[i].size <= available) {
+			words = fifo->entry[i].size;
+			fifo->tail++;
+			if (fifo->tail > MAX_CHANNELS)
+				fifo->tail = 0;
+		}
+
+		/* Update the next locations and counts */
+		available -= words;
+		fifo->entry[i].address += words * 4;
+		fifo->entry[i].size -= words;
+
+		/*
+		 * Write the HW fifo data. The read every three writes is due
+		 * to an errata on CN3XXX chips
+		 */
+		while (words > 3) {
+			cvmx_write64_uint32(csr_address, *ptr++);
+			cvmx_write64_uint32(csr_address, *ptr++);
+			cvmx_write64_uint32(csr_address, *ptr++);
+			cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index));
+			words -= 3;
+		}
+		cvmx_write64_uint32(csr_address, *ptr++);
+		if (--words) {
+			cvmx_write64_uint32(csr_address, *ptr++);
+			if (--words)
+				cvmx_write64_uint32(csr_address, *ptr++);
+		}
+		cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index));
+	}
+	return fifo->head != fifo->tail;
+}
+
+
+/**
+ * Check the hardware FIFOs and fill them as needed
+ *
+ * @usb:	USB device state populated by cvmx_usb_initialize().
+ */
+static void __cvmx_usb_poll_tx_fifo(struct cvmx_usb_state *usb)
+{
+	if (usb->periodic.head != usb->periodic.tail) {
+		union cvmx_usbcx_hptxsts tx_status;
+		tx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPTXSTS(usb->index));
+		if (__cvmx_usb_fill_tx_hw(usb, &usb->periodic, tx_status.s.ptxfspcavail))
+			USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, ptxfempmsk, 1);
+		else
+			USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, ptxfempmsk, 0);
+	}
+
+	if (usb->nonperiodic.head != usb->nonperiodic.tail) {
+		union cvmx_usbcx_gnptxsts tx_status;
+		tx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GNPTXSTS(usb->index));
+		if (__cvmx_usb_fill_tx_hw(usb, &usb->nonperiodic, tx_status.s.nptxfspcavail))
+			USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, nptxfempmsk, 1);
+		else
+			USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, nptxfempmsk, 0);
+	}
+
+	return;
+}
+
+
+/**
+ * Fill the TX FIFO with an outgoing packet
+ *
+ * @usb:	  USB device state populated by cvmx_usb_initialize().
+ * @channel:	  Channel number to get packet from
+ */
+static void __cvmx_usb_fill_tx_fifo(struct cvmx_usb_state *usb, int channel)
+{
+	union cvmx_usbcx_hccharx hcchar;
+	union cvmx_usbcx_hcspltx usbc_hcsplt;
+	union cvmx_usbcx_hctsizx usbc_hctsiz;
+	struct cvmx_usb_tx_fifo *fifo;
+
+	/* We only need to fill data on outbound channels */
+	hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index));
+	if (hcchar.s.epdir != CVMX_USB_DIRECTION_OUT)
+		return;
+
+	/* OUT Splits only have data on the start and not the complete */
+	usbc_hcsplt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCSPLTX(channel, usb->index));
+	if (usbc_hcsplt.s.spltena && usbc_hcsplt.s.compsplt)
+		return;
+
+	/*
+	 * Find out how many bytes we need to fill and convert it into 32bit
+	 * words.
+	 */
+	usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index));
+	if (!usbc_hctsiz.s.xfersize)
+		return;
+
+	if ((hcchar.s.eptype == CVMX_USB_TRANSFER_INTERRUPT) ||
+		(hcchar.s.eptype == CVMX_USB_TRANSFER_ISOCHRONOUS))
+		fifo = &usb->periodic;
+	else
+		fifo = &usb->nonperiodic;
+
+	fifo->entry[fifo->head].channel = channel;
+	fifo->entry[fifo->head].address = __cvmx_usb_read_csr64(usb, CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8);
+	fifo->entry[fifo->head].size = (usbc_hctsiz.s.xfersize+3)>>2;
+	fifo->head++;
+	if (fifo->head > MAX_CHANNELS)
+		fifo->head = 0;
+
+	__cvmx_usb_poll_tx_fifo(usb);
+
+	return;
+}
+
+/**
+ * Perform channel specific setup for Control transactions. All
+ * the generic stuff will already have been done in
+ * __cvmx_usb_start_channel()
+ *
+ * @usb:	  USB device state populated by cvmx_usb_initialize().
+ * @channel:	  Channel to setup
+ * @pipe:	  Pipe for control transaction
+ */
+static void __cvmx_usb_start_channel_control(struct cvmx_usb_state *usb,
+					     int channel,
+					     struct cvmx_usb_pipe *pipe)
+{
+	struct cvmx_usb_transaction *transaction =
+		list_first_entry(&pipe->transactions, typeof(*transaction),
+				 node);
+	union cvmx_usb_control_header *header =
+		cvmx_phys_to_ptr(transaction->control_header);
+	int bytes_to_transfer = transaction->buffer_length - transaction->actual_bytes;
+	int packets_to_transfer;
+	union cvmx_usbcx_hctsizx usbc_hctsiz;
+
+	usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index));
+
+	switch (transaction->stage) {
+	case CVMX_USB_STAGE_NON_CONTROL:
+	case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE:
+		cvmx_dprintf("%s: ERROR - Non control stage\n", __FUNCTION__);
+		break;
+	case CVMX_USB_STAGE_SETUP:
+		usbc_hctsiz.s.pid = 3; /* Setup */
+		bytes_to_transfer = sizeof(*header);
+		/* All Control operations start with a setup going OUT */
+		USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, epdir, CVMX_USB_DIRECTION_OUT);
+		/*
+		 * Setup send the control header instead of the buffer data. The
+		 * buffer data will be used in the next stage
+		 */
+		__cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8, transaction->control_header);
+		break;
+	case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE:
+		usbc_hctsiz.s.pid = 3; /* Setup */
+		bytes_to_transfer = 0;
+		/* All Control operations start with a setup going OUT */
+		USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, epdir, CVMX_USB_DIRECTION_OUT);
+		USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), union cvmx_usbcx_hcspltx, compsplt, 1);
+		break;
+	case CVMX_USB_STAGE_DATA:
+		usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
+		if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+			if (header->s.request_type & 0x80)
+				bytes_to_transfer = 0;
+			else if (bytes_to_transfer > pipe->max_packet)
+				bytes_to_transfer = pipe->max_packet;
+		}
+		USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
+				union cvmx_usbcx_hccharx, epdir,
+				((header->s.request_type & 0x80) ?
+					CVMX_USB_DIRECTION_IN :
+					CVMX_USB_DIRECTION_OUT));
+		break;
+	case CVMX_USB_STAGE_DATA_SPLIT_COMPLETE:
+		usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
+		if (!(header->s.request_type & 0x80))
+			bytes_to_transfer = 0;
+		USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index),
+				union cvmx_usbcx_hccharx, epdir,
+				((header->s.request_type & 0x80) ?
+					CVMX_USB_DIRECTION_IN :
+					CVMX_USB_DIRECTION_OUT));
+		USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), union cvmx_usbcx_hcspltx, compsplt, 1);
+		break;
+	case CVMX_USB_STAGE_STATUS:
+		usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
+		bytes_to_transfer = 0;
+		USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, epdir,
+				((header->s.request_type & 0x80) ?
+					CVMX_USB_DIRECTION_OUT :
+					CVMX_USB_DIRECTION_IN));
+		break;
+	case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE:
+		usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
+		bytes_to_transfer = 0;
+		USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, epdir,
+				((header->s.request_type & 0x80) ?
+					CVMX_USB_DIRECTION_OUT :
+					CVMX_USB_DIRECTION_IN));
+		USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), union cvmx_usbcx_hcspltx, compsplt, 1);
+		break;
+	}
+
+	/*
+	 * Make sure the transfer never exceeds the byte limit of the hardware.
+	 * Further bytes will be sent as continued transactions
+	 */
+	if (bytes_to_transfer > MAX_TRANSFER_BYTES) {
+		/* Round MAX_TRANSFER_BYTES to a multiple of out packet size */
+		bytes_to_transfer = MAX_TRANSFER_BYTES / pipe->max_packet;
+		bytes_to_transfer *= pipe->max_packet;
+	}
+
+	/*
+	 * Calculate the number of packets to transfer. If the length is zero
+	 * we still need to transfer one packet
+	 */
+	packets_to_transfer = (bytes_to_transfer + pipe->max_packet - 1) / pipe->max_packet;
+	if (packets_to_transfer == 0)
+		packets_to_transfer = 1;
+	else if ((packets_to_transfer > 1) && (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)) {
+		/*
+		 * Limit to one packet when not using DMA. Channels must be
+		 * restarted between every packet for IN transactions, so there
+		 * is no reason to do multiple packets in a row
+		 */
+		packets_to_transfer = 1;
+		bytes_to_transfer = packets_to_transfer * pipe->max_packet;
+	} else if (packets_to_transfer > MAX_TRANSFER_PACKETS) {
+		/*
+		 * Limit the number of packet and data transferred to what the
+		 * hardware can handle
+		 */
+		packets_to_transfer = MAX_TRANSFER_PACKETS;
+		bytes_to_transfer = packets_to_transfer * pipe->max_packet;
+	}
+
+	usbc_hctsiz.s.xfersize = bytes_to_transfer;
+	usbc_hctsiz.s.pktcnt = packets_to_transfer;
+
+	__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index), usbc_hctsiz.u32);
+	return;
+}
+
+
+/**
+ * Start a channel to perform the pipe's head transaction
+ *
+ * @usb:	  USB device state populated by cvmx_usb_initialize().
+ * @channel:	  Channel to setup
+ * @pipe:	  Pipe to start
+ */
+static void __cvmx_usb_start_channel(struct cvmx_usb_state *usb,
+				     int channel,
+				     struct cvmx_usb_pipe *pipe)
+{
+	struct cvmx_usb_transaction *transaction =
+		list_first_entry(&pipe->transactions, typeof(*transaction),
+				 node);
+
+	/* Make sure all writes to the DMA region get flushed */
+	CVMX_SYNCW;
+
+	/* Attach the channel to the pipe */
+	usb->pipe_for_channel[channel] = pipe;
+	pipe->channel = channel;
+	pipe->flags |= __CVMX_USB_PIPE_FLAGS_SCHEDULED;
+
+	/* Mark this channel as in use */
+	usb->idle_hardware_channels &= ~(1<<channel);
+
+	/* Enable the channel interrupt bits */
+	{
+		union cvmx_usbcx_hcintx usbc_hcint;
+		union cvmx_usbcx_hcintmskx usbc_hcintmsk;
+		union cvmx_usbcx_haintmsk usbc_haintmsk;
+
+		/* Clear all channel status bits */
+		usbc_hcint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCINTX(channel, usb->index));
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTX(channel, usb->index), usbc_hcint.u32);
+
+		usbc_hcintmsk.u32 = 0;
+		usbc_hcintmsk.s.chhltdmsk = 1;
+		if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) {
+			/*
+			 * Channels need these extra interrupts when we aren't
+			 * in DMA mode.
+			 */
+			usbc_hcintmsk.s.datatglerrmsk = 1;
+			usbc_hcintmsk.s.frmovrunmsk = 1;
+			usbc_hcintmsk.s.bblerrmsk = 1;
+			usbc_hcintmsk.s.xacterrmsk = 1;
+			if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+				/*
+				 * Splits don't generate xfercompl, so we need
+				 * ACK and NYET.
+				 */
+				usbc_hcintmsk.s.nyetmsk = 1;
+				usbc_hcintmsk.s.ackmsk = 1;
+			}
+			usbc_hcintmsk.s.nakmsk = 1;
+			usbc_hcintmsk.s.stallmsk = 1;
+			usbc_hcintmsk.s.xfercomplmsk = 1;
+		}
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), usbc_hcintmsk.u32);
+
+		/* Enable the channel interrupt to propagate */
+		usbc_haintmsk.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HAINTMSK(usb->index));
+		usbc_haintmsk.s.haintmsk |= 1<<channel;
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HAINTMSK(usb->index), usbc_haintmsk.u32);
+	}
+
+	/* Setup the locations the DMA engines use  */
+	{
+		uint64_t dma_address = transaction->buffer + transaction->actual_bytes;
+		if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)
+			dma_address = transaction->buffer + transaction->iso_packets[0].offset + transaction->actual_bytes;
+		__cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8, dma_address);
+		__cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8, dma_address);
+	}
+
+	/* Setup both the size of the transfer and the SPLIT characteristics */
+	{
+		union cvmx_usbcx_hcspltx usbc_hcsplt = {.u32 = 0};
+		union cvmx_usbcx_hctsizx usbc_hctsiz = {.u32 = 0};
+		int packets_to_transfer;
+		int bytes_to_transfer = transaction->buffer_length - transaction->actual_bytes;
+
+		/*
+		 * ISOCHRONOUS transactions store each individual transfer size
+		 * in the packet structure, not the global buffer_length
+		 */
+		if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)
+			bytes_to_transfer = transaction->iso_packets[0].length - transaction->actual_bytes;
+
+		/*
+		 * We need to do split transactions when we are talking to non
+		 * high speed devices that are behind a high speed hub
+		 */
+		if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+			/*
+			 * On the start split phase (stage is even) record the
+			 * frame number we will need to send the split complete.
+			 * We only store the lower two bits since the time ahead
+			 * can only be two frames
+			 */
+			if ((transaction->stage&1) == 0) {
+				if (transaction->type == CVMX_USB_TRANSFER_BULK)
+					pipe->split_sc_frame = (usb->frame_number + 1) & 0x7f;
+				else
+					pipe->split_sc_frame = (usb->frame_number + 2) & 0x7f;
+			} else
+				pipe->split_sc_frame = -1;
+
+			usbc_hcsplt.s.spltena = 1;
+			usbc_hcsplt.s.hubaddr = pipe->hub_device_addr;
+			usbc_hcsplt.s.prtaddr = pipe->hub_port;
+			usbc_hcsplt.s.compsplt = (transaction->stage == CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE);
+
+			/*
+			 * SPLIT transactions can only ever transmit one data
+			 * packet so limit the transfer size to the max packet
+			 * size
+			 */
+			if (bytes_to_transfer > pipe->max_packet)
+				bytes_to_transfer = pipe->max_packet;
+
+			/*
+			 * ISOCHRONOUS OUT splits are unique in that they limit
+			 * data transfers to 188 byte chunks representing the
+			 * begin/middle/end of the data or all
+			 */
+			if (!usbc_hcsplt.s.compsplt &&
+				(pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) &&
+				(pipe->transfer_type == CVMX_USB_TRANSFER_ISOCHRONOUS)) {
+				/*
+				 * Clear the split complete frame number as
+				 * there isn't going to be a split complete
+				 */
+				pipe->split_sc_frame = -1;
+				/*
+				 * See if we've started this transfer and sent
+				 * data
+				 */
+				if (transaction->actual_bytes == 0) {
+					/*
+					 * Nothing sent yet, this is either a
+					 * begin or the entire payload
+					 */
+					if (bytes_to_transfer <= 188)
+						/* Entire payload in one go */
+						usbc_hcsplt.s.xactpos = 3;
+					else
+						/* First part of payload */
+						usbc_hcsplt.s.xactpos = 2;
+				} else {
+					/*
+					 * Continuing the previous data, we must
+					 * either be in the middle or at the end
+					 */
+					if (bytes_to_transfer <= 188)
+						/* End of payload */
+						usbc_hcsplt.s.xactpos = 1;
+					else
+						/* Middle of payload */
+						usbc_hcsplt.s.xactpos = 0;
+				}
+				/*
+				 * Again, the transfer size is limited to 188
+				 * bytes
+				 */
+				if (bytes_to_transfer > 188)
+					bytes_to_transfer = 188;
+			}
+		}
+
+		/*
+		 * Make sure the transfer never exceeds the byte limit of the
+		 * hardware. Further bytes will be sent as continued
+		 * transactions
+		 */
+		if (bytes_to_transfer > MAX_TRANSFER_BYTES) {
+			/*
+			 * Round MAX_TRANSFER_BYTES to a multiple of out packet
+			 * size
+			 */
+			bytes_to_transfer = MAX_TRANSFER_BYTES / pipe->max_packet;
+			bytes_to_transfer *= pipe->max_packet;
+		}
+
+		/*
+		 * Calculate the number of packets to transfer. If the length is
+		 * zero we still need to transfer one packet
+		 */
+		packets_to_transfer = (bytes_to_transfer + pipe->max_packet - 1) / pipe->max_packet;
+		if (packets_to_transfer == 0)
+			packets_to_transfer = 1;
+		else if ((packets_to_transfer > 1) && (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)) {
+			/*
+			 * Limit to one packet when not using DMA. Channels must
+			 * be restarted between every packet for IN
+			 * transactions, so there is no reason to do multiple
+			 * packets in a row
+			 */
+			packets_to_transfer = 1;
+			bytes_to_transfer = packets_to_transfer * pipe->max_packet;
+		} else if (packets_to_transfer > MAX_TRANSFER_PACKETS) {
+			/*
+			 * Limit the number of packet and data transferred to
+			 * what the hardware can handle
+			 */
+			packets_to_transfer = MAX_TRANSFER_PACKETS;
+			bytes_to_transfer = packets_to_transfer * pipe->max_packet;
+		}
+
+		usbc_hctsiz.s.xfersize = bytes_to_transfer;
+		usbc_hctsiz.s.pktcnt = packets_to_transfer;
+
+		/* Update the DATA0/DATA1 toggle */
+		usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe);
+		/*
+		 * High speed pipes may need a hardware ping before they start
+		 */
+		if (pipe->flags & __CVMX_USB_PIPE_FLAGS_NEED_PING)
+			usbc_hctsiz.s.dopng = 1;
+
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCSPLTX(channel, usb->index), usbc_hcsplt.u32);
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index), usbc_hctsiz.u32);
+	}
+
+	/* Setup the Host Channel Characteristics Register */
+	{
+		union cvmx_usbcx_hccharx usbc_hcchar = {.u32 = 0};
+
+		/*
+		 * Set the startframe odd/even properly. This is only used for
+		 * periodic
+		 */
+		usbc_hcchar.s.oddfrm = usb->frame_number&1;
+
+		/*
+		 * Set the number of back to back packets allowed by this
+		 * endpoint. Split transactions interpret "ec" as the number of
+		 * immediate retries of failure. These retries happen too
+		 * quickly, so we disable these entirely for splits
+		 */
+		if (__cvmx_usb_pipe_needs_split(usb, pipe))
+			usbc_hcchar.s.ec = 1;
+		else if (pipe->multi_count < 1)
+			usbc_hcchar.s.ec = 1;
+		else if (pipe->multi_count > 3)
+			usbc_hcchar.s.ec = 3;
+		else
+			usbc_hcchar.s.ec = pipe->multi_count;
+
+		/* Set the rest of the endpoint specific settings */
+		usbc_hcchar.s.devaddr = pipe->device_addr;
+		usbc_hcchar.s.eptype = transaction->type;
+		usbc_hcchar.s.lspddev = (pipe->device_speed == CVMX_USB_SPEED_LOW);
+		usbc_hcchar.s.epdir = pipe->transfer_dir;
+		usbc_hcchar.s.epnum = pipe->endpoint_num;
+		usbc_hcchar.s.mps = pipe->max_packet;
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32);
+	}
+
+	/* Do transaction type specific fixups as needed */
+	switch (transaction->type) {
+	case CVMX_USB_TRANSFER_CONTROL:
+		__cvmx_usb_start_channel_control(usb, channel, pipe);
+		break;
+	case CVMX_USB_TRANSFER_BULK:
+	case CVMX_USB_TRANSFER_INTERRUPT:
+		break;
+	case CVMX_USB_TRANSFER_ISOCHRONOUS:
+		if (!__cvmx_usb_pipe_needs_split(usb, pipe)) {
+			/*
+			 * ISO transactions require different PIDs depending on
+			 * direction and how many packets are needed
+			 */
+			if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) {
+				if (pipe->multi_count < 2) /* Need DATA0 */
+					USB_SET_FIELD32(CVMX_USBCX_HCTSIZX(channel, usb->index), union cvmx_usbcx_hctsizx, pid, 0);
+				else /* Need MDATA */
+					USB_SET_FIELD32(CVMX_USBCX_HCTSIZX(channel, usb->index), union cvmx_usbcx_hctsizx, pid, 3);
+			}
+		}
+		break;
+	}
+	{
+		union cvmx_usbcx_hctsizx usbc_hctsiz = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index))};
+		transaction->xfersize = usbc_hctsiz.s.xfersize;
+		transaction->pktcnt = usbc_hctsiz.s.pktcnt;
+	}
+	/* Remeber when we start a split transaction */
+	if (__cvmx_usb_pipe_needs_split(usb, pipe))
+		usb->active_split = transaction;
+	USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, chena, 1);
+	if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
+		__cvmx_usb_fill_tx_fifo(usb, channel);
+	return;
+}
+
+
+/**
+ * Find a pipe that is ready to be scheduled to hardware.
+ * @usb:	 USB device state populated by cvmx_usb_initialize().
+ * @list:	 Pipe list to search
+ * @current_frame:
+ *		 Frame counter to use as a time reference.
+ *
+ * Returns: Pipe or NULL if none are ready
+ */
+static struct cvmx_usb_pipe *__cvmx_usb_find_ready_pipe(struct cvmx_usb_state *usb, struct list_head *list, uint64_t current_frame)
+{
+	struct cvmx_usb_pipe *pipe;
+
+	list_for_each_entry(pipe, list, node) {
+		struct cvmx_usb_transaction *t =
+			list_first_entry(&pipe->transactions, typeof(*t), node);
+		if (!(pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED) && t &&
+			(pipe->next_tx_frame <= current_frame) &&
+			((pipe->split_sc_frame == -1) || ((((int)current_frame - (int)pipe->split_sc_frame) & 0x7f) < 0x40)) &&
+			(!usb->active_split || (usb->active_split == t))) {
+			CVMX_PREFETCH(pipe, 128);
+			CVMX_PREFETCH(t, 0);
+			return pipe;
+		}
+	}
+	return NULL;
+}
+
+
+/**
+ * Called whenever a pipe might need to be scheduled to the
+ * hardware.
+ *
+ * @usb:	 USB device state populated by cvmx_usb_initialize().
+ * @is_sof:	 True if this schedule was called on a SOF interrupt.
+ */
+static void __cvmx_usb_schedule(struct cvmx_usb_state *usb, int is_sof)
+{
+	int channel;
+	struct cvmx_usb_pipe *pipe;
+	int need_sof;
+	enum cvmx_usb_transfer ttype;
+
+	if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) {
+		/*
+		 * Without DMA we need to be careful to not schedule something
+		 * at the end of a frame and cause an overrun.
+		 */
+		union cvmx_usbcx_hfnum hfnum = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index))};
+		union cvmx_usbcx_hfir hfir = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFIR(usb->index))};
+		if (hfnum.s.frrem < hfir.s.frint/4)
+			goto done;
+	}
+
+	while (usb->idle_hardware_channels) {
+		/* Find an idle channel */
+		channel = __fls(usb->idle_hardware_channels);
+		if (unlikely(channel > 7))
+			break;
+
+		/* Find a pipe needing service */
+		pipe = NULL;
+		if (is_sof) {
+			/*
+			 * Only process periodic pipes on SOF interrupts. This
+			 * way we are sure that the periodic data is sent in the
+			 * beginning of the frame
+			 */
+			pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_ISOCHRONOUS, usb->frame_number);
+			if (likely(!pipe))
+				pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_INTERRUPT, usb->frame_number);
+		}
+		if (likely(!pipe)) {
+			pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_CONTROL, usb->frame_number);
+			if (likely(!pipe))
+				pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_BULK, usb->frame_number);
+		}
+		if (!pipe)
+			break;
+
+		__cvmx_usb_start_channel(usb, channel, pipe);
+	}
+
+done:
+	/*
+	 * Only enable SOF interrupts when we have transactions pending in the
+	 * future that might need to be scheduled
+	 */
+	need_sof = 0;
+	for (ttype = CVMX_USB_TRANSFER_CONTROL; ttype <= CVMX_USB_TRANSFER_INTERRUPT; ttype++) {
+		list_for_each_entry(pipe, &usb->active_pipes[ttype], node) {
+			if (pipe->next_tx_frame > usb->frame_number) {
+				need_sof = 1;
+				break;
+			}
+		}
+	}
+	USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, sofmsk, need_sof);
+	return;
 }
 
 static inline struct octeon_hcd *cvmx_usb_to_octeon(struct cvmx_usb_state *p)
@@ -47,91 +1966,34 @@
 	return container_of(p, struct octeon_hcd, usb);
 }
 
-static irqreturn_t octeon_usb_irq(struct usb_hcd *hcd)
+static inline struct usb_hcd *octeon_to_hcd(struct octeon_hcd *p)
 {
-	struct octeon_hcd *priv = hcd_to_octeon(hcd);
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	cvmx_usb_poll(&priv->usb);
-	spin_unlock_irqrestore(&priv->lock, flags);
-	return IRQ_HANDLED;
-}
-
-static void octeon_usb_port_callback(struct cvmx_usb_state *usb,
-				     enum cvmx_usb_callback reason,
-				     enum cvmx_usb_complete status,
-				     int pipe_handle,
-				     int submit_handle,
-				     int bytes_transferred,
-				     void *user_data)
-{
-	struct octeon_hcd *priv = cvmx_usb_to_octeon(usb);
-
-	spin_unlock(&priv->lock);
-	usb_hcd_poll_rh_status(octeon_to_hcd(priv));
-	spin_lock(&priv->lock);
-}
-
-static int octeon_usb_start(struct usb_hcd *hcd)
-{
-	struct octeon_hcd *priv = hcd_to_octeon(hcd);
-	unsigned long flags;
-
-	hcd->state = HC_STATE_RUNNING;
-	spin_lock_irqsave(&priv->lock, flags);
-	cvmx_usb_register_callback(&priv->usb, CVMX_USB_CALLBACK_PORT_CHANGED,
-				   octeon_usb_port_callback, NULL);
-	spin_unlock_irqrestore(&priv->lock, flags);
-	return 0;
-}
-
-static void octeon_usb_stop(struct usb_hcd *hcd)
-{
-	struct octeon_hcd *priv = hcd_to_octeon(hcd);
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	cvmx_usb_register_callback(&priv->usb, CVMX_USB_CALLBACK_PORT_CHANGED,
-				   NULL, NULL);
-	spin_unlock_irqrestore(&priv->lock, flags);
-	hcd->state = HC_STATE_HALT;
-}
-
-static int octeon_usb_get_frame_number(struct usb_hcd *hcd)
-{
-	struct octeon_hcd *priv = hcd_to_octeon(hcd);
-
-	return cvmx_usb_get_frame_number(&priv->usb);
+	return container_of((void *)p, struct usb_hcd, hcd_priv);
 }
 
 static void octeon_usb_urb_complete_callback(struct cvmx_usb_state *usb,
-					     enum cvmx_usb_callback reason,
 					     enum cvmx_usb_complete status,
-					     int pipe_handle,
-					     int submit_handle,
+					     struct cvmx_usb_pipe *pipe,
+					     struct cvmx_usb_transaction
+						*transaction,
 					     int bytes_transferred,
-					     void *user_data)
+					     struct urb *urb)
 {
 	struct octeon_hcd *priv = cvmx_usb_to_octeon(usb);
 	struct usb_hcd *hcd = octeon_to_hcd(priv);
 	struct device *dev = hcd->self.controller;
-	struct urb *urb = user_data;
 
 	urb->actual_length = bytes_transferred;
 	urb->hcpriv = NULL;
 
-	if (!list_empty(&urb->urb_list)) {
+	if (!list_empty(&urb->urb_list))
 		/*
 		 * It is on the dequeue_list, but we are going to call
 		 * usb_hcd_giveback_urb(), so we must clear it from
 		 * the list.  We got to it before the
 		 * octeon_usb_urb_dequeue_work() tasklet did.
 		 */
-		list_del(&urb->urb_list);
-		/* No longer on the dequeue_list. */
-		INIT_LIST_HEAD(&urb->urb_list);
-	}
+		list_del_init(&urb->urb_list);
 
 	/* For Isochronous transactions we need to update the URB packet status
 	   list from data in our private copy */
@@ -151,10 +2013,10 @@
 				urb->iso_frame_desc[i].actual_length = iso_packet[i].length;
 				urb->actual_length += urb->iso_frame_desc[i].actual_length;
 			} else {
-				dev_dbg(dev, "ISOCHRONOUS packet=%d of %d status=%d pipe=%d submit=%d size=%d\n",
+				dev_dbg(dev, "ISOCHRONOUS packet=%d of %d status=%d pipe=%p transaction=%p size=%d\n",
 					i, urb->number_of_packets,
-					iso_packet[i].status, pipe_handle,
-					submit_handle, iso_packet[i].length);
+					iso_packet[i].status, pipe,
+					transaction, iso_packet[i].length);
 				urb->iso_frame_desc[i].status = -EREMOTEIO;
 			}
 		}
@@ -172,26 +2034,26 @@
 			urb->status = -ENOENT;
 		break;
 	case CVMX_USB_COMPLETE_STALL:
-		dev_dbg(dev, "status=stall pipe=%d submit=%d size=%d\n",
-			pipe_handle, submit_handle, bytes_transferred);
+		dev_dbg(dev, "status=stall pipe=%p transaction=%p size=%d\n",
+			pipe, transaction, bytes_transferred);
 		urb->status = -EPIPE;
 		break;
 	case CVMX_USB_COMPLETE_BABBLEERR:
-		dev_dbg(dev, "status=babble pipe=%d submit=%d size=%d\n",
-			pipe_handle, submit_handle, bytes_transferred);
+		dev_dbg(dev, "status=babble pipe=%p transaction=%p size=%d\n",
+			pipe, transaction, bytes_transferred);
 		urb->status = -EPIPE;
 		break;
 	case CVMX_USB_COMPLETE_SHORT:
-		dev_dbg(dev, "status=short pipe=%d submit=%d size=%d\n",
-			pipe_handle, submit_handle, bytes_transferred);
+		dev_dbg(dev, "status=short pipe=%p transaction=%p size=%d\n",
+			pipe, transaction, bytes_transferred);
 		urb->status = -EREMOTEIO;
 		break;
 	case CVMX_USB_COMPLETE_ERROR:
 	case CVMX_USB_COMPLETE_XACTERR:
 	case CVMX_USB_COMPLETE_DATATGLERR:
 	case CVMX_USB_COMPLETE_FRAMEERR:
-		dev_dbg(dev, "status=%d pipe=%d submit=%d size=%d\n",
-			status, pipe_handle, submit_handle, bytes_transferred);
+		dev_dbg(dev, "status=%d pipe=%p transaction=%p size=%d\n",
+			status, pipe, transaction, bytes_transferred);
 		urb->status = -EPROTO;
 		break;
 	}
@@ -200,14 +2062,952 @@
 	spin_lock(&priv->lock);
 }
 
+/**
+ * Signal the completion of a transaction and free it. The
+ * transaction will be removed from the pipe transaction list.
+ *
+ * @usb:	 USB device state populated by cvmx_usb_initialize().
+ * @pipe:	 Pipe the transaction is on
+ * @transaction:
+ *		 Transaction that completed
+ * @complete_code:
+ *		 Completion code
+ */
+static void __cvmx_usb_perform_complete(struct cvmx_usb_state *usb,
+					struct cvmx_usb_pipe *pipe,
+					struct cvmx_usb_transaction *transaction,
+					enum cvmx_usb_complete complete_code)
+{
+	/* If this was a split then clear our split in progress marker */
+	if (usb->active_split == transaction)
+		usb->active_split = NULL;
+
+	/*
+	 * Isochronous transactions need extra processing as they might not be
+	 * done after a single data transfer
+	 */
+	if (unlikely(transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)) {
+		/* Update the number of bytes transferred in this ISO packet */
+		transaction->iso_packets[0].length = transaction->actual_bytes;
+		transaction->iso_packets[0].status = complete_code;
+
+		/*
+		 * If there are more ISOs pending and we succeeded, schedule the
+		 * next one
+		 */
+		if ((transaction->iso_number_packets > 1) && (complete_code == CVMX_USB_COMPLETE_SUCCESS)) {
+			/* No bytes transferred for this packet as of yet */
+			transaction->actual_bytes = 0;
+			/* One less ISO waiting to transfer */
+			transaction->iso_number_packets--;
+			/* Increment to the next location in our packet array */
+			transaction->iso_packets++;
+			transaction->stage = CVMX_USB_STAGE_NON_CONTROL;
+			goto done;
+		}
+	}
+
+	/* Remove the transaction from the pipe list */
+	list_del(&transaction->node);
+	if (list_empty(&pipe->transactions))
+		list_move_tail(&pipe->node, &usb->idle_pipes);
+	octeon_usb_urb_complete_callback(usb, complete_code, pipe,
+					 transaction,
+					 transaction->actual_bytes,
+					 transaction->urb);
+	kfree(transaction);
+done:
+	return;
+}
+
+
+/**
+ * Submit a usb transaction to a pipe. Called for all types
+ * of transactions.
+ *
+ * @usb:
+ * @pipe:	    Which pipe to submit to.
+ * @type:	    Transaction type
+ * @buffer:	    User buffer for the transaction
+ * @buffer_length:
+ *		    User buffer's length in bytes
+ * @control_header:
+ *		    For control transactions, the 8 byte standard header
+ * @iso_start_frame:
+ *		    For ISO transactions, the start frame
+ * @iso_number_packets:
+ *		    For ISO, the number of packet in the transaction.
+ * @iso_packets:
+ *		    A description of each ISO packet
+ * @urb:	    URB for the callback
+ *
+ * Returns: Transaction or NULL on failure.
+ */
+static struct cvmx_usb_transaction *__cvmx_usb_submit_transaction(struct cvmx_usb_state *usb,
+								  struct cvmx_usb_pipe *pipe,
+								  enum cvmx_usb_transfer type,
+								  uint64_t buffer,
+								  int buffer_length,
+								  uint64_t control_header,
+								  int iso_start_frame,
+								  int iso_number_packets,
+								  struct cvmx_usb_iso_packet *iso_packets,
+								  struct urb *urb)
+{
+	struct cvmx_usb_transaction *transaction;
+
+	if (unlikely(pipe->transfer_type != type))
+		return NULL;
+
+	transaction = kzalloc(sizeof(*transaction), GFP_ATOMIC);
+	if (unlikely(!transaction))
+		return NULL;
+
+	transaction->type = type;
+	transaction->buffer = buffer;
+	transaction->buffer_length = buffer_length;
+	transaction->control_header = control_header;
+	/* FIXME: This is not used, implement it. */
+	transaction->iso_start_frame = iso_start_frame;
+	transaction->iso_number_packets = iso_number_packets;
+	transaction->iso_packets = iso_packets;
+	transaction->urb = urb;
+	if (transaction->type == CVMX_USB_TRANSFER_CONTROL)
+		transaction->stage = CVMX_USB_STAGE_SETUP;
+	else
+		transaction->stage = CVMX_USB_STAGE_NON_CONTROL;
+
+	if (!list_empty(&pipe->transactions)) {
+		list_add_tail(&transaction->node, &pipe->transactions);
+	} else {
+		list_add_tail(&transaction->node, &pipe->transactions);
+		list_move_tail(&pipe->node,
+			       &usb->active_pipes[pipe->transfer_type]);
+
+		/*
+		 * We may need to schedule the pipe if this was the head of the
+		 * pipe.
+		 */
+		__cvmx_usb_schedule(usb, 0);
+	}
+
+	return transaction;
+}
+
+
+/**
+ * Call to submit a USB Bulk transfer to a pipe.
+ *
+ * @usb:	    USB device state populated by cvmx_usb_initialize().
+ * @pipe:	    Handle to the pipe for the transfer.
+ * @urb:	    URB.
+ *
+ * Returns: A submitted transaction or NULL on failure.
+ */
+static struct cvmx_usb_transaction *cvmx_usb_submit_bulk(struct cvmx_usb_state *usb,
+							 struct cvmx_usb_pipe *pipe,
+							 struct urb *urb)
+{
+	return __cvmx_usb_submit_transaction(usb, pipe, CVMX_USB_TRANSFER_BULK,
+					     urb->transfer_dma,
+					     urb->transfer_buffer_length,
+					     0, /* control_header */
+					     0, /* iso_start_frame */
+					     0, /* iso_number_packets */
+					     NULL, /* iso_packets */
+					     urb);
+}
+
+
+/**
+ * Call to submit a USB Interrupt transfer to a pipe.
+ *
+ * @usb:	    USB device state populated by cvmx_usb_initialize().
+ * @pipe:	    Handle to the pipe for the transfer.
+ * @urb:	    URB returned when the callback is called.
+ *
+ * Returns: A submitted transaction or NULL on failure.
+ */
+static struct cvmx_usb_transaction *cvmx_usb_submit_interrupt(struct cvmx_usb_state *usb,
+							      struct cvmx_usb_pipe *pipe,
+							      struct urb *urb)
+{
+	return __cvmx_usb_submit_transaction(usb, pipe,
+					     CVMX_USB_TRANSFER_INTERRUPT,
+					     urb->transfer_dma,
+					     urb->transfer_buffer_length,
+					     0, /* control_header */
+					     0, /* iso_start_frame */
+					     0, /* iso_number_packets */
+					     NULL, /* iso_packets */
+					     urb);
+}
+
+
+/**
+ * Call to submit a USB Control transfer to a pipe.
+ *
+ * @usb:	    USB device state populated by cvmx_usb_initialize().
+ * @pipe:	    Handle to the pipe for the transfer.
+ * @urb:	    URB.
+ *
+ * Returns: A submitted transaction or NULL on failure.
+ */
+static struct cvmx_usb_transaction *cvmx_usb_submit_control(struct cvmx_usb_state *usb,
+							    struct cvmx_usb_pipe *pipe,
+							    struct urb *urb)
+{
+	int buffer_length = urb->transfer_buffer_length;
+	uint64_t control_header = urb->setup_dma;
+	union cvmx_usb_control_header *header =
+		cvmx_phys_to_ptr(control_header);
+
+	if ((header->s.request_type & 0x80) == 0)
+		buffer_length = le16_to_cpu(header->s.length);
+
+	return __cvmx_usb_submit_transaction(usb, pipe,
+					     CVMX_USB_TRANSFER_CONTROL,
+					     urb->transfer_dma, buffer_length,
+					     control_header,
+					     0, /* iso_start_frame */
+					     0, /* iso_number_packets */
+					     NULL, /* iso_packets */
+					     urb);
+}
+
+
+/**
+ * Call to submit a USB Isochronous transfer to a pipe.
+ *
+ * @usb:	    USB device state populated by cvmx_usb_initialize().
+ * @pipe:	    Handle to the pipe for the transfer.
+ * @urb:	    URB returned when the callback is called.
+ *
+ * Returns: A submitted transaction or NULL on failure.
+ */
+static struct cvmx_usb_transaction *cvmx_usb_submit_isochronous(struct cvmx_usb_state *usb,
+								struct cvmx_usb_pipe *pipe,
+								struct urb *urb)
+{
+	struct cvmx_usb_iso_packet *packets;
+
+	packets = (struct cvmx_usb_iso_packet *) urb->setup_packet;
+	return __cvmx_usb_submit_transaction(usb, pipe,
+					     CVMX_USB_TRANSFER_ISOCHRONOUS,
+					     urb->transfer_dma,
+					     urb->transfer_buffer_length,
+					     0, /* control_header */
+					     urb->start_frame,
+					     urb->number_of_packets,
+					     packets, urb);
+}
+
+
+/**
+ * Cancel one outstanding request in a pipe. Canceling a request
+ * can fail if the transaction has already completed before cancel
+ * is called. Even after a successful cancel call, it may take
+ * a frame or two for the cvmx_usb_poll() function to call the
+ * associated callback.
+ *
+ * @usb:	 USB device state populated by cvmx_usb_initialize().
+ * @pipe:	 Pipe to cancel requests in.
+ * @transaction: Transaction to cancel, returned by the submit function.
+ *
+ * Returns: 0 or a negative error code.
+ */
+static int cvmx_usb_cancel(struct cvmx_usb_state *usb,
+			   struct cvmx_usb_pipe *pipe,
+			   struct cvmx_usb_transaction *transaction)
+{
+	/*
+	 * If the transaction is the HEAD of the queue and scheduled. We need to
+	 * treat it special
+	 */
+	if (list_first_entry(&pipe->transactions, typeof(*transaction), node) ==
+	    transaction && (pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED)) {
+		union cvmx_usbcx_hccharx usbc_hcchar;
+
+		usb->pipe_for_channel[pipe->channel] = NULL;
+		pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_SCHEDULED;
+
+		CVMX_SYNCW;
+
+		usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(pipe->channel, usb->index));
+		/*
+		 * If the channel isn't enabled then the transaction already
+		 * completed.
+		 */
+		if (usbc_hcchar.s.chena) {
+			usbc_hcchar.s.chdis = 1;
+			__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(pipe->channel, usb->index), usbc_hcchar.u32);
+		}
+	}
+	__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_CANCEL);
+	return 0;
+}
+
+
+/**
+ * Cancel all outstanding requests in a pipe. Logically all this
+ * does is call cvmx_usb_cancel() in a loop.
+ *
+ * @usb:	 USB device state populated by cvmx_usb_initialize().
+ * @pipe:	 Pipe to cancel requests in.
+ *
+ * Returns: 0 or a negative error code.
+ */
+static int cvmx_usb_cancel_all(struct cvmx_usb_state *usb,
+			       struct cvmx_usb_pipe *pipe)
+{
+	struct cvmx_usb_transaction *transaction, *next;
+
+	/* Simply loop through and attempt to cancel each transaction */
+	list_for_each_entry_safe(transaction, next, &pipe->transactions, node) {
+		int result = cvmx_usb_cancel(usb, pipe, transaction);
+		if (unlikely(result != 0))
+			return result;
+	}
+	return 0;
+}
+
+
+/**
+ * Close a pipe created with cvmx_usb_open_pipe().
+ *
+ * @usb:	 USB device state populated by cvmx_usb_initialize().
+ * @pipe:	 Pipe to close.
+ *
+ * Returns: 0 or a negative error code. EBUSY is returned if the pipe has
+ *	    outstanding transfers.
+ */
+static int cvmx_usb_close_pipe(struct cvmx_usb_state *usb,
+			       struct cvmx_usb_pipe *pipe)
+{
+	/* Fail if the pipe has pending transactions */
+	if (!list_empty(&pipe->transactions))
+		return -EBUSY;
+
+	list_del(&pipe->node);
+	kfree(pipe);
+
+	return 0;
+}
+
+/**
+ * Get the current USB protocol level frame number. The frame
+ * number is always in the range of 0-0x7ff.
+ *
+ * @usb: USB device state populated by cvmx_usb_initialize().
+ *
+ * Returns: USB frame number
+ */
+static int cvmx_usb_get_frame_number(struct cvmx_usb_state *usb)
+{
+	int frame_number;
+	union cvmx_usbcx_hfnum usbc_hfnum;
+
+	usbc_hfnum.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index));
+	frame_number = usbc_hfnum.s.frnum;
+
+	return frame_number;
+}
+
+
+/**
+ * Poll a channel for status
+ *
+ * @usb:     USB device
+ * @channel: Channel to poll
+ *
+ * Returns: Zero on success
+ */
+static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel)
+{
+	union cvmx_usbcx_hcintx usbc_hcint;
+	union cvmx_usbcx_hctsizx usbc_hctsiz;
+	union cvmx_usbcx_hccharx usbc_hcchar;
+	struct cvmx_usb_pipe *pipe;
+	struct cvmx_usb_transaction *transaction;
+	int bytes_this_transfer;
+	int bytes_in_last_packet;
+	int packets_processed;
+	int buffer_space_left;
+
+	/* Read the interrupt status bits for the channel */
+	usbc_hcint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCINTX(channel, usb->index));
+
+	if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) {
+		usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index));
+
+		if (usbc_hcchar.s.chena && usbc_hcchar.s.chdis) {
+			/*
+			 * There seems to be a bug in CN31XX which can cause
+			 * interrupt IN transfers to get stuck until we do a
+			 * write of HCCHARX without changing things
+			 */
+			__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32);
+			return 0;
+		}
+
+		/*
+		 * In non DMA mode the channels don't halt themselves. We need
+		 * to manually disable channels that are left running
+		 */
+		if (!usbc_hcint.s.chhltd) {
+			if (usbc_hcchar.s.chena) {
+				union cvmx_usbcx_hcintmskx hcintmsk;
+				/* Disable all interrupts except CHHLTD */
+				hcintmsk.u32 = 0;
+				hcintmsk.s.chhltdmsk = 1;
+				__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), hcintmsk.u32);
+				usbc_hcchar.s.chdis = 1;
+				__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32);
+				return 0;
+			} else if (usbc_hcint.s.xfercompl) {
+				/*
+				 * Successful IN/OUT with transfer complete.
+				 * Channel halt isn't needed.
+				 */
+			} else {
+				cvmx_dprintf("USB%d: Channel %d interrupt without halt\n", usb->index, channel);
+				return 0;
+			}
+		}
+	} else {
+		/*
+		 * There is are no interrupts that we need to process when the
+		 * channel is still running
+		 */
+		if (!usbc_hcint.s.chhltd)
+			return 0;
+	}
+
+	/* Disable the channel interrupts now that it is done */
+	__cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), 0);
+	usb->idle_hardware_channels |= (1<<channel);
+
+	/* Make sure this channel is tied to a valid pipe */
+	pipe = usb->pipe_for_channel[channel];
+	CVMX_PREFETCH(pipe, 0);
+	CVMX_PREFETCH(pipe, 128);
+	if (!pipe)
+		return 0;
+	transaction = list_first_entry(&pipe->transactions, typeof(*transaction),
+				       node);
+	CVMX_PREFETCH(transaction, 0);
+
+	/*
+	 * Disconnect this pipe from the HW channel. Later the schedule
+	 * function will figure out which pipe needs to go
+	 */
+	usb->pipe_for_channel[channel] = NULL;
+	pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_SCHEDULED;
+
+	/*
+	 * Read the channel config info so we can figure out how much data
+	 * transfered
+	 */
+	usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index));
+	usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index));
+
+	/*
+	 * Calculating the number of bytes successfully transferred is dependent
+	 * on the transfer direction
+	 */
+	packets_processed = transaction->pktcnt - usbc_hctsiz.s.pktcnt;
+	if (usbc_hcchar.s.epdir) {
+		/*
+		 * IN transactions are easy. For every byte received the
+		 * hardware decrements xfersize. All we need to do is subtract
+		 * the current value of xfersize from its starting value and we
+		 * know how many bytes were written to the buffer
+		 */
+		bytes_this_transfer = transaction->xfersize - usbc_hctsiz.s.xfersize;
+	} else {
+		/*
+		 * OUT transaction don't decrement xfersize. Instead pktcnt is
+		 * decremented on every successful packet send. The hardware
+		 * does this when it receives an ACK, or NYET. If it doesn't
+		 * receive one of these responses pktcnt doesn't change
+		 */
+		bytes_this_transfer = packets_processed * usbc_hcchar.s.mps;
+		/*
+		 * The last packet may not be a full transfer if we didn't have
+		 * enough data
+		 */
+		if (bytes_this_transfer > transaction->xfersize)
+			bytes_this_transfer = transaction->xfersize;
+	}
+	/* Figure out how many bytes were in the last packet of the transfer */
+	if (packets_processed)
+		bytes_in_last_packet = bytes_this_transfer - (packets_processed-1) * usbc_hcchar.s.mps;
+	else
+		bytes_in_last_packet = bytes_this_transfer;
+
+	/*
+	 * As a special case, setup transactions output the setup header, not
+	 * the user's data. For this reason we don't count setup data as bytes
+	 * transferred
+	 */
+	if ((transaction->stage == CVMX_USB_STAGE_SETUP) ||
+		(transaction->stage == CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE))
+		bytes_this_transfer = 0;
+
+	/*
+	 * Add the bytes transferred to the running total. It is important that
+	 * bytes_this_transfer doesn't count any data that needs to be
+	 * retransmitted
+	 */
+	transaction->actual_bytes += bytes_this_transfer;
+	if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)
+		buffer_space_left = transaction->iso_packets[0].length - transaction->actual_bytes;
+	else
+		buffer_space_left = transaction->buffer_length - transaction->actual_bytes;
+
+	/*
+	 * We need to remember the PID toggle state for the next transaction.
+	 * The hardware already updated it for the next transaction
+	 */
+	pipe->pid_toggle = !(usbc_hctsiz.s.pid == 0);
+
+	/*
+	 * For high speed bulk out, assume the next transaction will need to do
+	 * a ping before proceeding. If this isn't true the ACK processing below
+	 * will clear this flag
+	 */
+	if ((pipe->device_speed == CVMX_USB_SPEED_HIGH) &&
+		(pipe->transfer_type == CVMX_USB_TRANSFER_BULK) &&
+		(pipe->transfer_dir == CVMX_USB_DIRECTION_OUT))
+		pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING;
+
+	if (usbc_hcint.s.stall) {
+		/*
+		 * STALL as a response means this transaction cannot be
+		 * completed because the device can't process transactions. Tell
+		 * the user. Any data that was transferred will be counted on
+		 * the actual bytes transferred
+		 */
+		pipe->pid_toggle = 0;
+		__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_STALL);
+	} else if (usbc_hcint.s.xacterr) {
+		/*
+		 * We know at least one packet worked if we get a ACK or NAK.
+		 * Reset the retry counter
+		 */
+		if (usbc_hcint.s.nak || usbc_hcint.s.ack)
+			transaction->retries = 0;
+		transaction->retries++;
+		if (transaction->retries > MAX_RETRIES) {
+			/*
+			 * XactErr as a response means the device signaled
+			 * something wrong with the transfer. For example, PID
+			 * toggle errors cause these
+			 */
+			__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_XACTERR);
+		} else {
+			/*
+			 * If this was a split then clear our split in progress
+			 * marker
+			 */
+			if (usb->active_split == transaction)
+				usb->active_split = NULL;
+			/*
+			 * Rewind to the beginning of the transaction by anding
+			 * off the split complete bit
+			 */
+			transaction->stage &= ~1;
+			pipe->split_sc_frame = -1;
+			pipe->next_tx_frame += pipe->interval;
+			if (pipe->next_tx_frame < usb->frame_number)
+				pipe->next_tx_frame = usb->frame_number + pipe->interval -
+						      (usb->frame_number - pipe->next_tx_frame) % pipe->interval;
+		}
+	} else if (usbc_hcint.s.bblerr) {
+		/* Babble Error (BblErr) */
+		__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_BABBLEERR);
+	} else if (usbc_hcint.s.datatglerr) {
+		/* We'll retry the exact same transaction again */
+		transaction->retries++;
+	} else if (usbc_hcint.s.nyet) {
+		/*
+		 * NYET as a response is only allowed in three cases: as a
+		 * response to a ping, as a response to a split transaction, and
+		 * as a response to a bulk out. The ping case is handled by
+		 * hardware, so we only have splits and bulk out
+		 */
+		if (!__cvmx_usb_pipe_needs_split(usb, pipe)) {
+			transaction->retries = 0;
+			/*
+			 * If there is more data to go then we need to try
+			 * again. Otherwise this transaction is complete
+			 */
+			if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet))
+				__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
+		} else {
+			/*
+			 * Split transactions retry the split complete 4 times
+			 * then rewind to the start split and do the entire
+			 * transactions again
+			 */
+			transaction->retries++;
+			if ((transaction->retries & 0x3) == 0) {
+				/*
+				 * Rewind to the beginning of the transaction by
+				 * anding off the split complete bit
+				 */
+				transaction->stage &= ~1;
+				pipe->split_sc_frame = -1;
+			}
+		}
+	} else if (usbc_hcint.s.ack) {
+		transaction->retries = 0;
+		/*
+		 * The ACK bit can only be checked after the other error bits.
+		 * This is because a multi packet transfer may succeed in a
+		 * number of packets and then get a different response on the
+		 * last packet. In this case both ACK and the last response bit
+		 * will be set. If none of the other response bits is set, then
+		 * the last packet must have been an ACK
+		 *
+		 * Since we got an ACK, we know we don't need to do a ping on
+		 * this pipe
+		 */
+		pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_NEED_PING;
+
+		switch (transaction->type) {
+		case CVMX_USB_TRANSFER_CONTROL:
+			switch (transaction->stage) {
+			case CVMX_USB_STAGE_NON_CONTROL:
+			case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE:
+				/* This should be impossible */
+				__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_ERROR);
+				break;
+			case CVMX_USB_STAGE_SETUP:
+				pipe->pid_toggle = 1;
+				if (__cvmx_usb_pipe_needs_split(usb, pipe))
+					transaction->stage = CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE;
+				else {
+					union cvmx_usb_control_header *header =
+						cvmx_phys_to_ptr(transaction->control_header);
+					if (header->s.length)
+						transaction->stage = CVMX_USB_STAGE_DATA;
+					else
+						transaction->stage = CVMX_USB_STAGE_STATUS;
+				}
+				break;
+			case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE:
+				{
+					union cvmx_usb_control_header *header =
+						cvmx_phys_to_ptr(transaction->control_header);
+					if (header->s.length)
+						transaction->stage = CVMX_USB_STAGE_DATA;
+					else
+						transaction->stage = CVMX_USB_STAGE_STATUS;
+				}
+				break;
+			case CVMX_USB_STAGE_DATA:
+				if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+					transaction->stage = CVMX_USB_STAGE_DATA_SPLIT_COMPLETE;
+					/*
+					 * For setup OUT data that are splits,
+					 * the hardware doesn't appear to count
+					 * transferred data. Here we manually
+					 * update the data transferred
+					 */
+					if (!usbc_hcchar.s.epdir) {
+						if (buffer_space_left < pipe->max_packet)
+							transaction->actual_bytes += buffer_space_left;
+						else
+							transaction->actual_bytes += pipe->max_packet;
+					}
+				} else if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) {
+					pipe->pid_toggle = 1;
+					transaction->stage = CVMX_USB_STAGE_STATUS;
+				}
+				break;
+			case CVMX_USB_STAGE_DATA_SPLIT_COMPLETE:
+				if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) {
+					pipe->pid_toggle = 1;
+					transaction->stage = CVMX_USB_STAGE_STATUS;
+				} else {
+					transaction->stage = CVMX_USB_STAGE_DATA;
+				}
+				break;
+			case CVMX_USB_STAGE_STATUS:
+				if (__cvmx_usb_pipe_needs_split(usb, pipe))
+					transaction->stage = CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE;
+				else
+					__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
+				break;
+			case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE:
+				__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
+				break;
+			}
+			break;
+		case CVMX_USB_TRANSFER_BULK:
+		case CVMX_USB_TRANSFER_INTERRUPT:
+			/*
+			 * The only time a bulk transfer isn't complete when it
+			 * finishes with an ACK is during a split transaction.
+			 * For splits we need to continue the transfer if more
+			 * data is needed
+			 */
+			if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+				if (transaction->stage == CVMX_USB_STAGE_NON_CONTROL)
+					transaction->stage = CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE;
+				else {
+					if (buffer_space_left && (bytes_in_last_packet == pipe->max_packet))
+						transaction->stage = CVMX_USB_STAGE_NON_CONTROL;
+					else {
+						if (transaction->type == CVMX_USB_TRANSFER_INTERRUPT)
+							pipe->next_tx_frame += pipe->interval;
+							__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
+					}
+				}
+			} else {
+				if ((pipe->device_speed == CVMX_USB_SPEED_HIGH) &&
+				    (pipe->transfer_type == CVMX_USB_TRANSFER_BULK) &&
+				    (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) &&
+				    (usbc_hcint.s.nak))
+					pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING;
+				if (!buffer_space_left || (bytes_in_last_packet < pipe->max_packet)) {
+					if (transaction->type == CVMX_USB_TRANSFER_INTERRUPT)
+						pipe->next_tx_frame += pipe->interval;
+					__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
+				}
+			}
+			break;
+		case CVMX_USB_TRANSFER_ISOCHRONOUS:
+			if (__cvmx_usb_pipe_needs_split(usb, pipe)) {
+				/*
+				 * ISOCHRONOUS OUT splits don't require a
+				 * complete split stage. Instead they use a
+				 * sequence of begin OUT splits to transfer the
+				 * data 188 bytes at a time. Once the transfer
+				 * is complete, the pipe sleeps until the next
+				 * schedule interval
+				 */
+				if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) {
+					/*
+					 * If no space left or this wasn't a max
+					 * size packet then this transfer is
+					 * complete. Otherwise start it again to
+					 * send the next 188 bytes
+					 */
+					if (!buffer_space_left || (bytes_this_transfer < 188)) {
+						pipe->next_tx_frame += pipe->interval;
+						__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
+					}
+				} else {
+					if (transaction->stage == CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE) {
+						/*
+						 * We are in the incoming data
+						 * phase. Keep getting data
+						 * until we run out of space or
+						 * get a small packet
+						 */
+						if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) {
+							pipe->next_tx_frame += pipe->interval;
+							__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
+						}
+					} else
+						transaction->stage = CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE;
+				}
+			} else {
+				pipe->next_tx_frame += pipe->interval;
+				__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS);
+			}
+			break;
+		}
+	} else if (usbc_hcint.s.nak) {
+		/*
+		 * If this was a split then clear our split in progress marker.
+		 */
+		if (usb->active_split == transaction)
+			usb->active_split = NULL;
+		/*
+		 * NAK as a response means the device couldn't accept the
+		 * transaction, but it should be retried in the future. Rewind
+		 * to the beginning of the transaction by anding off the split
+		 * complete bit. Retry in the next interval
+		 */
+		transaction->retries = 0;
+		transaction->stage &= ~1;
+		pipe->next_tx_frame += pipe->interval;
+		if (pipe->next_tx_frame < usb->frame_number)
+			pipe->next_tx_frame = usb->frame_number + pipe->interval -
+				(usb->frame_number - pipe->next_tx_frame) % pipe->interval;
+	} else {
+		struct cvmx_usb_port_status port;
+		port = cvmx_usb_get_status(usb);
+		if (port.port_enabled) {
+			/* We'll retry the exact same transaction again */
+			transaction->retries++;
+		} else {
+			/*
+			 * We get channel halted interrupts with no result bits
+			 * sets when the cable is unplugged
+			 */
+			__cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_ERROR);
+		}
+	}
+	return 0;
+}
+
+static void octeon_usb_port_callback(struct cvmx_usb_state *usb)
+{
+	struct octeon_hcd *priv = cvmx_usb_to_octeon(usb);
+
+	spin_unlock(&priv->lock);
+	usb_hcd_poll_rh_status(octeon_to_hcd(priv));
+	spin_lock(&priv->lock);
+}
+
+/**
+ * Poll the USB block for status and call all needed callback
+ * handlers. This function is meant to be called in the interrupt
+ * handler for the USB controller. It can also be called
+ * periodically in a loop for non-interrupt based operation.
+ *
+ * @usb: USB device state populated by cvmx_usb_initialize().
+ *
+ * Returns: 0 or a negative error code.
+ */
+static int cvmx_usb_poll(struct cvmx_usb_state *usb)
+{
+	union cvmx_usbcx_hfnum usbc_hfnum;
+	union cvmx_usbcx_gintsts usbc_gintsts;
+
+	CVMX_PREFETCH(usb, 0);
+	CVMX_PREFETCH(usb, 1*128);
+	CVMX_PREFETCH(usb, 2*128);
+	CVMX_PREFETCH(usb, 3*128);
+	CVMX_PREFETCH(usb, 4*128);
+
+	/* Update the frame counter */
+	usbc_hfnum.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index));
+	if ((usb->frame_number&0x3fff) > usbc_hfnum.s.frnum)
+		usb->frame_number += 0x4000;
+	usb->frame_number &= ~0x3fffull;
+	usb->frame_number |= usbc_hfnum.s.frnum;
+
+	/* Read the pending interrupts */
+	usbc_gintsts.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GINTSTS(usb->index));
+
+	/* Clear the interrupts now that we know about them */
+	__cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTSTS(usb->index), usbc_gintsts.u32);
+
+	if (usbc_gintsts.s.rxflvl) {
+		/*
+		 * RxFIFO Non-Empty (RxFLvl)
+		 * Indicates that there is at least one packet pending to be
+		 * read from the RxFIFO.
+		 *
+		 * In DMA mode this is handled by hardware
+		 */
+		if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
+			__cvmx_usb_poll_rx_fifo(usb);
+	}
+	if (usbc_gintsts.s.ptxfemp || usbc_gintsts.s.nptxfemp) {
+		/* Fill the Tx FIFOs when not in DMA mode */
+		if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)
+			__cvmx_usb_poll_tx_fifo(usb);
+	}
+	if (usbc_gintsts.s.disconnint || usbc_gintsts.s.prtint) {
+		union cvmx_usbcx_hprt usbc_hprt;
+		/*
+		 * Disconnect Detected Interrupt (DisconnInt)
+		 * Asserted when a device disconnect is detected.
+		 *
+		 * Host Port Interrupt (PrtInt)
+		 * The core sets this bit to indicate a change in port status of
+		 * one of the O2P USB core ports in Host mode. The application
+		 * must read the Host Port Control and Status (HPRT) register to
+		 * determine the exact event that caused this interrupt. The
+		 * application must clear the appropriate status bit in the Host
+		 * Port Control and Status register to clear this bit.
+		 *
+		 * Call the user's port callback
+		 */
+		octeon_usb_port_callback(usb);
+		/* Clear the port change bits */
+		usbc_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index));
+		usbc_hprt.s.prtena = 0;
+		__cvmx_usb_write_csr32(usb, CVMX_USBCX_HPRT(usb->index), usbc_hprt.u32);
+	}
+	if (usbc_gintsts.s.hchint) {
+		/*
+		 * Host Channels Interrupt (HChInt)
+		 * The core sets this bit to indicate that an interrupt is
+		 * pending on one of the channels of the core (in Host mode).
+		 * The application must read the Host All Channels Interrupt
+		 * (HAINT) register to determine the exact number of the channel
+		 * on which the interrupt occurred, and then read the
+		 * corresponding Host Channel-n Interrupt (HCINTn) register to
+		 * determine the exact cause of the interrupt. The application
+		 * must clear the appropriate status bit in the HCINTn register
+		 * to clear this bit.
+		 */
+		union cvmx_usbcx_haint usbc_haint;
+		usbc_haint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HAINT(usb->index));
+		while (usbc_haint.u32) {
+			int channel;
+
+			channel = __fls(usbc_haint.u32);
+			__cvmx_usb_poll_channel(usb, channel);
+			usbc_haint.u32 ^= 1<<channel;
+		}
+	}
+
+	__cvmx_usb_schedule(usb, usbc_gintsts.s.sof);
+
+	return 0;
+}
+
+/* convert between an HCD pointer and the corresponding struct octeon_hcd */
+static inline struct octeon_hcd *hcd_to_octeon(struct usb_hcd *hcd)
+{
+	return (struct octeon_hcd *)(hcd->hcd_priv);
+}
+
+static irqreturn_t octeon_usb_irq(struct usb_hcd *hcd)
+{
+	struct octeon_hcd *priv = hcd_to_octeon(hcd);
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	cvmx_usb_poll(&priv->usb);
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return IRQ_HANDLED;
+}
+
+static int octeon_usb_start(struct usb_hcd *hcd)
+{
+	hcd->state = HC_STATE_RUNNING;
+	return 0;
+}
+
+static void octeon_usb_stop(struct usb_hcd *hcd)
+{
+	hcd->state = HC_STATE_HALT;
+}
+
+static int octeon_usb_get_frame_number(struct usb_hcd *hcd)
+{
+	struct octeon_hcd *priv = hcd_to_octeon(hcd);
+
+	return cvmx_usb_get_frame_number(&priv->usb);
+}
+
 static int octeon_usb_urb_enqueue(struct usb_hcd *hcd,
 				  struct urb *urb,
 				  gfp_t mem_flags)
 {
 	struct octeon_hcd *priv = hcd_to_octeon(hcd);
 	struct device *dev = hcd->self.controller;
-	int submit_handle = -1;
-	int pipe_handle;
+	struct cvmx_usb_transaction *transaction = NULL;
+	struct cvmx_usb_pipe *pipe;
 	unsigned long flags;
 	struct cvmx_usb_iso_packet *iso_packet;
 	struct usb_host_endpoint *ep = urb->ep;
@@ -276,26 +3076,24 @@
 				dev = dev->parent;
 			}
 		}
-		pipe_handle = cvmx_usb_open_pipe(&priv->usb,
-						 0,
-						 usb_pipedevice(urb->pipe),
-						 usb_pipeendpoint(urb->pipe),
-						 speed,
-						 le16_to_cpu(ep->desc.wMaxPacketSize) & 0x7ff,
-						 transfer_type,
-						 usb_pipein(urb->pipe) ? CVMX_USB_DIRECTION_IN : CVMX_USB_DIRECTION_OUT,
-						 urb->interval,
-						 (le16_to_cpu(ep->desc.wMaxPacketSize) >> 11) & 0x3,
-						 split_device,
-						 split_port);
-		if (pipe_handle < 0) {
+		pipe = cvmx_usb_open_pipe(&priv->usb, usb_pipedevice(urb->pipe),
+					  usb_pipeendpoint(urb->pipe), speed,
+					  le16_to_cpu(ep->desc.wMaxPacketSize) & 0x7ff,
+					  transfer_type,
+					  usb_pipein(urb->pipe) ?
+						CVMX_USB_DIRECTION_IN :
+						CVMX_USB_DIRECTION_OUT,
+					  urb->interval,
+					  (le16_to_cpu(ep->desc.wMaxPacketSize) >> 11) & 0x3,
+					  split_device, split_port);
+		if (!pipe) {
 			spin_unlock_irqrestore(&priv->lock, flags);
 			dev_dbg(dev, "Failed to create pipe\n");
 			return -ENOMEM;
 		}
-		ep->hcpriv = (void *)(0x10000L + pipe_handle);
+		ep->hcpriv = pipe;
 	} else {
-		pipe_handle = 0xffff & (long)ep->hcpriv;
+		pipe = ep->hcpriv;
 	}
 
 	switch (usb_pipetype(urb->pipe)) {
@@ -323,20 +3121,13 @@
 			 * this saves us a bunch of logic.
 			 */
 			urb->setup_packet = (char *)iso_packet;
-			submit_handle = cvmx_usb_submit_isochronous(&priv->usb, pipe_handle,
-							urb->start_frame,
-							0 /* flags */ ,
-							urb->number_of_packets,
-							iso_packet,
-							urb->transfer_dma,
-							urb->transfer_buffer_length,
-							octeon_usb_urb_complete_callback,
-							urb);
+			transaction = cvmx_usb_submit_isochronous(&priv->usb,
+								  pipe, urb);
 			/*
 			 * If submit failed we need to free our private packet
 			 * list.
 			 */
-			if (submit_handle < 0) {
+			if (!transaction) {
 				urb->setup_packet = NULL;
 				kfree(iso_packet);
 			}
@@ -345,59 +3136,41 @@
 	case PIPE_INTERRUPT:
 		dev_dbg(dev, "Submit interrupt to %d.%d\n",
 			usb_pipedevice(urb->pipe), usb_pipeendpoint(urb->pipe));
-		submit_handle = cvmx_usb_submit_interrupt(&priv->usb, pipe_handle,
-					      urb->transfer_dma,
-					      urb->transfer_buffer_length,
-					      octeon_usb_urb_complete_callback,
-					      urb);
+		transaction = cvmx_usb_submit_interrupt(&priv->usb, pipe, urb);
 		break;
 	case PIPE_CONTROL:
 		dev_dbg(dev, "Submit control to %d.%d\n",
 			usb_pipedevice(urb->pipe), usb_pipeendpoint(urb->pipe));
-		submit_handle = cvmx_usb_submit_control(&priv->usb, pipe_handle,
-					    urb->setup_dma,
-					    urb->transfer_dma,
-					    urb->transfer_buffer_length,
-					    octeon_usb_urb_complete_callback,
-					    urb);
+		transaction = cvmx_usb_submit_control(&priv->usb, pipe, urb);
 		break;
 	case PIPE_BULK:
 		dev_dbg(dev, "Submit bulk to %d.%d\n",
 			usb_pipedevice(urb->pipe), usb_pipeendpoint(urb->pipe));
-		submit_handle = cvmx_usb_submit_bulk(&priv->usb, pipe_handle,
-					 urb->transfer_dma,
-					 urb->transfer_buffer_length,
-					 octeon_usb_urb_complete_callback,
-					 urb);
+		transaction = cvmx_usb_submit_bulk(&priv->usb, pipe, urb);
 		break;
 	}
-	if (submit_handle < 0) {
+	if (!transaction) {
 		spin_unlock_irqrestore(&priv->lock, flags);
 		dev_dbg(dev, "Failed to submit\n");
 		return -ENOMEM;
 	}
-	urb->hcpriv = (void *)(long)(((submit_handle & 0xffff) << 16) | pipe_handle);
+	urb->hcpriv = transaction;
 	spin_unlock_irqrestore(&priv->lock, flags);
 	return 0;
 }
 
 static void octeon_usb_urb_dequeue_work(unsigned long arg)
 {
+	struct urb *urb;
+	struct urb *next;
 	unsigned long flags;
 	struct octeon_hcd *priv = (struct octeon_hcd *)arg;
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	while (!list_empty(&priv->dequeue_list)) {
-		int pipe_handle;
-		int submit_handle;
-		struct urb *urb = container_of(priv->dequeue_list.next, struct urb, urb_list);
-		list_del(&urb->urb_list);
-		/* not enqueued on dequeue_list */
-		INIT_LIST_HEAD(&urb->urb_list);
-		pipe_handle = 0xffff & (long)urb->hcpriv;
-		submit_handle = ((long)urb->hcpriv) >> 16;
-		cvmx_usb_cancel(&priv->usb, pipe_handle, submit_handle);
+	list_for_each_entry_safe(urb, next, &priv->dequeue_list, urb_list) {
+		list_del_init(&urb->urb_list);
+		cvmx_usb_cancel(&priv->usb, urb->ep->hcpriv, urb->hcpriv);
 	}
 
 	spin_unlock_irqrestore(&priv->lock, flags);
@@ -429,12 +3202,12 @@
 
 	if (ep->hcpriv) {
 		struct octeon_hcd *priv = hcd_to_octeon(hcd);
-		int pipe_handle = 0xffff & (long)ep->hcpriv;
+		struct cvmx_usb_pipe *pipe = ep->hcpriv;
 		unsigned long flags;
 		spin_lock_irqsave(&priv->lock, flags);
-		cvmx_usb_cancel_all(&priv->usb, pipe_handle);
-		if (cvmx_usb_close_pipe(&priv->usb, pipe_handle))
-			dev_dbg(dev, "Closing pipe %d failed\n", pipe_handle);
+		cvmx_usb_cancel_all(&priv->usb, pipe);
+		if (cvmx_usb_close_pipe(&priv->usb, pipe))
+			dev_dbg(dev, "Closing pipe %p failed\n", pipe);
 		spin_unlock_irqrestore(&priv->lock, flags);
 		ep->hcpriv = NULL;
 	}
@@ -506,7 +3279,7 @@
 			dev_dbg(dev, " C_CONNECTION\n");
 			/* Clears drivers internal connect status change flag */
 			spin_lock_irqsave(&priv->lock, flags);
-			cvmx_usb_set_status(&priv->usb, cvmx_usb_get_status(&priv->usb));
+			priv->usb.port_status = cvmx_usb_get_status(&priv->usb);
 			spin_unlock_irqrestore(&priv->lock, flags);
 			break;
 		case USB_PORT_FEAT_C_RESET:
@@ -515,7 +3288,7 @@
 			 * Clears the driver's internal Port Reset Change flag.
 			 */
 			spin_lock_irqsave(&priv->lock, flags);
-			cvmx_usb_set_status(&priv->usb, cvmx_usb_get_status(&priv->usb));
+			priv->usb.port_status = cvmx_usb_get_status(&priv->usb);
 			spin_unlock_irqrestore(&priv->lock, flags);
 			break;
 		case USB_PORT_FEAT_C_ENABLE:
@@ -525,7 +3298,7 @@
 			 * Change flag.
 			 */
 			spin_lock_irqsave(&priv->lock, flags);
-			cvmx_usb_set_status(&priv->usb, cvmx_usb_get_status(&priv->usb));
+			priv->usb.port_status = cvmx_usb_get_status(&priv->usb);
 			spin_unlock_irqrestore(&priv->lock, flags);
 			break;
 		case USB_PORT_FEAT_C_SUSPEND:
@@ -540,7 +3313,7 @@
 			dev_dbg(dev, " C_OVER_CURRENT\n");
 			/* Clears the driver's overcurrent Change flag */
 			spin_lock_irqsave(&priv->lock, flags);
-			cvmx_usb_set_status(&priv->usb, cvmx_usb_get_status(&priv->usb));
+			priv->usb.port_status = cvmx_usb_get_status(&priv->usb);
 			spin_unlock_irqrestore(&priv->lock, flags);
 			break;
 		default:
@@ -705,7 +3478,7 @@
 	tasklet_init(&priv->dequeue_tasklet, octeon_usb_urb_dequeue_work, (unsigned long)priv);
 	INIT_LIST_HEAD(&priv->dequeue_list);
 
-	status = cvmx_usb_initialize(&priv->usb, usb_num, CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO);
+	status = cvmx_usb_initialize(&priv->usb, usb_num);
 	if (status) {
 		dev_dbg(dev, "USB initialization failed with %d\n", status);
 		kfree(hcd);
diff --git a/drivers/staging/octeon-usb/cvmx-usbcx-defs.h b/drivers/staging/octeon-usb/octeon-hcd.h
similarity index 82%
rename from drivers/staging/octeon-usb/cvmx-usbcx-defs.h
rename to drivers/staging/octeon-usb/octeon-hcd.h
index d349d77..42fe4fe 100644
--- a/drivers/staging/octeon-usb/cvmx-usbcx-defs.h
+++ b/drivers/staging/octeon-usb/octeon-hcd.h
@@ -1,7 +1,14 @@
-/***********************license start***************
- * Copyright (c) 2003-2010  Cavium Networks (support@cavium.com). All rights
- * reserved.
+/*
+ * Octeon HCD hardware register definitions.
  *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Some parts of the code were originally released under BSD license:
+ *
+ * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights
+ * reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -14,17 +21,17 @@
  *     copyright notice, this list of conditions and the following
  *     disclaimer in the documentation and/or other materials provided
  *     with the distribution.
-
+ *
  *   * Neither the name of Cavium Networks 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, including technical data, may be subject to U.S. export
  * control laws, including the U.S. Export Administration Act and its associated
- * regulations, and may be subject to export or import  regulations in other
+ * regulations, and may be subject to export or import regulations in other
  * countries.
-
+ *
  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
  * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
  * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
@@ -33,20 +40,12 @@
  * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
  * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
  * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
- * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK ARISING OUT OF USE OR
+ * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
  * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
- ***********************license end**************************************/
-
-
-/**
- * cvmx-usbcx-defs.h
- *
- * Configuration and status register (CSR) type definitions for
- * Octeon usbcx.
- *
  */
-#ifndef __CVMX_USBCX_TYPEDEFS_H__
-#define __CVMX_USBCX_TYPEDEFS_H__
+
+#ifndef __OCTEON_HCD_H__
+#define __OCTEON_HCD_H__
 
 #define CVMX_USBCXBASE 0x00016F0010000000ull
 #define CVMX_USBCXREG1(reg, bid) \
@@ -81,6 +80,19 @@
 #define CVMX_USBCX_HPTXFSIZ(bid)	CVMX_USBCXREG1(0x100, bid)
 #define CVMX_USBCX_HPTXSTS(bid)		CVMX_USBCXREG1(0x410, bid)
 
+#define CVMX_USBNXBID1(bid) (((bid) & 1) * 0x10000000ull)
+#define CVMX_USBNXBID2(bid) (((bid) & 1) * 0x100000000000ull)
+
+#define CVMX_USBNXREG1(reg, bid) \
+	(CVMX_ADD_IO_SEG(0x0001180068000000ull | reg) + CVMX_USBNXBID1(bid))
+#define CVMX_USBNXREG2(reg, bid) \
+	(CVMX_ADD_IO_SEG(0x00016F0000000000ull | reg) + CVMX_USBNXBID2(bid))
+
+#define CVMX_USBNX_CLK_CTL(bid)		CVMX_USBNXREG1(0x10, bid)
+#define CVMX_USBNX_DMA0_INB_CHN0(bid)	CVMX_USBNXREG2(0x818, bid)
+#define CVMX_USBNX_DMA0_OUTB_CHN0(bid)	CVMX_USBNXREG2(0x858, bid)
+#define CVMX_USBNX_USBP_CTL_STATUS(bid)	CVMX_USBNXREG1(0x18, bid)
+
 /**
  * cvmx_usbc#_gahbcfg
  *
@@ -1525,4 +1537,283 @@
 	} s;
 };
 
-#endif
+/**
+ * cvmx_usbn#_clk_ctl
+ *
+ * USBN_CLK_CTL = USBN's Clock Control
+ *
+ * This register is used to control the frequency of the hclk and the
+ * hreset and phy_rst signals.
+ */
+union cvmx_usbnx_clk_ctl {
+	uint64_t u64;
+	/**
+	 * struct cvmx_usbnx_clk_ctl_s
+	 * @divide2: The 'hclk' used by the USB subsystem is derived
+	 *	from the eclk.
+	 *	Also see the field DIVIDE. DIVIDE2<1> must currently
+	 *	be zero because it is not implemented, so the maximum
+	 *	ratio of eclk/hclk is currently 16.
+	 *	The actual divide number for hclk is:
+	 *	(DIVIDE2 + 1) * (DIVIDE + 1)
+	 * @hclk_rst: When this field is '0' the HCLK-DIVIDER used to
+	 *	generate the hclk in the USB Subsystem is held
+	 *	in reset. This bit must be set to '0' before
+	 *	changing the value os DIVIDE in this register.
+	 *	The reset to the HCLK_DIVIDERis also asserted
+	 *	when core reset is asserted.
+	 * @p_x_on: Force USB-PHY on during suspend.
+	 *	'1' USB-PHY XO block is powered-down during
+	 *	suspend.
+	 *	'0' USB-PHY XO block is powered-up during
+	 *	suspend.
+	 *	The value of this field must be set while POR is
+	 *	active.
+	 * @p_rtype: PHY reference clock type
+	 *	On CN50XX/CN52XX/CN56XX the values are:
+	 *		'0' The USB-PHY uses a 12MHz crystal as a clock source
+	 *		    at the USB_XO and USB_XI pins.
+	 *		'1' Reserved.
+	 *		'2' The USB_PHY uses 12/24/48MHz 2.5V board clock at the
+	 *		    USB_XO pin. USB_XI should be tied to ground in this
+	 *		    case.
+	 *		'3' Reserved.
+	 *	On CN3xxx bits 14 and 15 are p_xenbn and p_rclk and values are:
+	 *		'0' Reserved.
+	 *		'1' Reserved.
+	 *		'2' The PHY PLL uses the XO block output as a reference.
+	 *		    The XO block uses an external clock supplied on the
+	 *		    XO pin. USB_XI should be tied to ground for this
+	 *		    usage.
+	 *		'3' The XO block uses the clock from a crystal.
+	 * @p_com_on: '0' Force USB-PHY XO Bias, Bandgap and PLL to
+	 *	remain powered in Suspend Mode.
+	 *	'1' The USB-PHY XO Bias, Bandgap and PLL are
+	 *	powered down in suspend mode.
+	 *	The value of this field must be set while POR is
+	 *	active.
+	 * @p_c_sel: Phy clock speed select.
+	 *	Selects the reference clock / crystal frequency.
+	 *	'11': Reserved
+	 *	'10': 48 MHz (reserved when a crystal is used)
+	 *	'01': 24 MHz (reserved when a crystal is used)
+	 *	'00': 12 MHz
+	 *	The value of this field must be set while POR is
+	 *	active.
+	 *	NOTE: if a crystal is used as a reference clock,
+	 *	this field must be set to 12 MHz.
+	 * @cdiv_byp: Used to enable the bypass input to the USB_CLK_DIV.
+	 * @sd_mode: Scaledown mode for the USBC. Control timing events
+	 *	in the USBC, for normal operation this must be '0'.
+	 * @s_bist: Starts bist on the hclk memories, during the '0'
+	 *	to '1' transition.
+	 * @por: Power On Reset for the PHY.
+	 *	Resets all the PHYS registers and state machines.
+	 * @enable: When '1' allows the generation of the hclk. When
+	 *	'0' the hclk will not be generated. SEE DIVIDE
+	 *	field of this register.
+	 * @prst: When this field is '0' the reset associated with
+	 *	the phy_clk functionality in the USB Subsystem is
+	 *	help in reset. This bit should not be set to '1'
+	 *	until the time it takes 6 clocks (hclk or phy_clk,
+	 *	whichever is slower) has passed. Under normal
+	 *	operation once this bit is set to '1' it should not
+	 *	be set to '0'.
+	 * @hrst: When this field is '0' the reset associated with
+	 *	the hclk functioanlity in the USB Subsystem is
+	 *	held in reset.This bit should not be set to '1'
+	 *	until 12ms after phy_clk is stable. Under normal
+	 *	operation, once this bit is set to '1' it should
+	 *	not be set to '0'.
+	 * @divide: The frequency of 'hclk' used by the USB subsystem
+	 *	is the eclk frequency divided by the value of
+	 *	(DIVIDE2 + 1) * (DIVIDE + 1), also see the field
+	 *	DIVIDE2 of this register.
+	 *	The hclk frequency should be less than 125Mhz.
+	 *	After writing a value to this field the SW should
+	 *	read the field for the value written.
+	 *	The ENABLE field of this register should not be set
+	 *	until AFTER this field is set and then read.
+	 */
+	struct cvmx_usbnx_clk_ctl_s {
+		uint64_t reserved_20_63	: 44;
+		uint64_t divide2	: 2;
+		uint64_t hclk_rst	: 1;
+		uint64_t p_x_on		: 1;
+		uint64_t p_rtype	: 2;
+		uint64_t p_com_on	: 1;
+		uint64_t p_c_sel	: 2;
+		uint64_t cdiv_byp	: 1;
+		uint64_t sd_mode	: 2;
+		uint64_t s_bist		: 1;
+		uint64_t por		: 1;
+		uint64_t enable		: 1;
+		uint64_t prst		: 1;
+		uint64_t hrst		: 1;
+		uint64_t divide		: 3;
+	} s;
+};
+
+/**
+ * cvmx_usbn#_usbp_ctl_status
+ *
+ * USBN_USBP_CTL_STATUS = USBP Control And Status Register
+ *
+ * Contains general control and status information for the USBN block.
+ */
+union cvmx_usbnx_usbp_ctl_status {
+	uint64_t u64;
+	/**
+	 * struct cvmx_usbnx_usbp_ctl_status_s
+	 * @txrisetune: HS Transmitter Rise/Fall Time Adjustment
+	 * @txvreftune: HS DC Voltage Level Adjustment
+	 * @txfslstune: FS/LS Source Impedence Adjustment
+	 * @txhsxvtune: Transmitter High-Speed Crossover Adjustment
+	 * @sqrxtune: Squelch Threshold Adjustment
+	 * @compdistune: Disconnect Threshold Adjustment
+	 * @otgtune: VBUS Valid Threshold Adjustment
+	 * @otgdisable: OTG Block Disable
+	 * @portreset: Per_Port Reset
+	 * @drvvbus: Drive VBUS
+	 * @lsbist: Low-Speed BIST Enable.
+	 * @fsbist: Full-Speed BIST Enable.
+	 * @hsbist: High-Speed BIST Enable.
+	 * @bist_done: PHY Bist Done.
+	 *	Asserted at the end of the PHY BIST sequence.
+	 * @bist_err: PHY Bist Error.
+	 *	Indicates an internal error was detected during
+	 *	the BIST sequence.
+	 * @tdata_out: PHY Test Data Out.
+	 *	Presents either internaly generated signals or
+	 *	test register contents, based upon the value of
+	 *	test_data_out_sel.
+	 * @siddq: Drives the USBP (USB-PHY) SIDDQ input.
+	 *	Normally should be set to zero.
+	 *	When customers have no intent to use USB PHY
+	 *	interface, they should:
+	 *	- still provide 3.3V to USB_VDD33, and
+	 *	- tie USB_REXT to 3.3V supply, and
+	 *	- set USBN*_USBP_CTL_STATUS[SIDDQ]=1
+	 * @txpreemphasistune: HS Transmitter Pre-Emphasis Enable
+	 * @dma_bmode: When set to 1 the L2C DMA address will be updated
+	 *	with byte-counts between packets. When set to 0
+	 *	the L2C DMA address is incremented to the next
+	 *	4-byte aligned address after adding byte-count.
+	 * @usbc_end: Bigendian input to the USB Core. This should be
+	 *	set to '0' for operation.
+	 * @usbp_bist: PHY, This is cleared '0' to run BIST on the USBP.
+	 * @tclk: PHY Test Clock, used to load TDATA_IN to the USBP.
+	 * @dp_pulld: PHY DP_PULLDOWN input to the USB-PHY.
+	 *	This signal enables the pull-down resistance on
+	 *	the D+ line. '1' pull down-resistance is connected
+	 *	to D+/ '0' pull down resistance is not connected
+	 *	to D+. When an A/B device is acting as a host
+	 *	(downstream-facing port), dp_pulldown and
+	 *	dm_pulldown are enabled. This must not toggle
+	 *	during normal opeartion.
+	 * @dm_pulld: PHY DM_PULLDOWN input to the USB-PHY.
+	 *	This signal enables the pull-down resistance on
+	 *	the D- line. '1' pull down-resistance is connected
+	 *	to D-. '0' pull down resistance is not connected
+	 *	to D-. When an A/B device is acting as a host
+	 *	(downstream-facing port), dp_pulldown and
+	 *	dm_pulldown are enabled. This must not toggle
+	 *	during normal opeartion.
+	 * @hst_mode: When '0' the USB is acting as HOST, when '1'
+	 *	USB is acting as device. This field needs to be
+	 *	set while the USB is in reset.
+	 * @tuning: Transmitter Tuning for High-Speed Operation.
+	 *	Tunes the current supply and rise/fall output
+	 *	times for high-speed operation.
+	 *	[20:19] == 11: Current supply increased
+	 *	approximately 9%
+	 *	[20:19] == 10: Current supply increased
+	 *	approximately 4.5%
+	 *	[20:19] == 01: Design default.
+	 *	[20:19] == 00: Current supply decreased
+	 *	approximately 4.5%
+	 *	[22:21] == 11: Rise and fall times are increased.
+	 *	[22:21] == 10: Design default.
+	 *	[22:21] == 01: Rise and fall times are decreased.
+	 *	[22:21] == 00: Rise and fall times are decreased
+	 *	further as compared to the 01 setting.
+	 * @tx_bs_enh: Transmit Bit Stuffing on [15:8].
+	 *	Enables or disables bit stuffing on data[15:8]
+	 *	when bit-stuffing is enabled.
+	 * @tx_bs_en: Transmit Bit Stuffing on [7:0].
+	 *	Enables or disables bit stuffing on data[7:0]
+	 *	when bit-stuffing is enabled.
+	 * @loop_enb: PHY Loopback Test Enable.
+	 *	'1': During data transmission the receive is
+	 *	enabled.
+	 *	'0': During data transmission the receive is
+	 *	disabled.
+	 *	Must be '0' for normal operation.
+	 * @vtest_enb: Analog Test Pin Enable.
+	 *	'1' The PHY's analog_test pin is enabled for the
+	 *	input and output of applicable analog test signals.
+	 *	'0' THe analog_test pin is disabled.
+	 * @bist_enb: Built-In Self Test Enable.
+	 *	Used to activate BIST in the PHY.
+	 * @tdata_sel: Test Data Out Select.
+	 *	'1' test_data_out[3:0] (PHY) register contents
+	 *	are output. '0' internaly generated signals are
+	 *	output.
+	 * @taddr_in: Mode Address for Test Interface.
+	 *	Specifies the register address for writing to or
+	 *	reading from the PHY test interface register.
+	 * @tdata_in: Internal Testing Register Input Data and Select
+	 *	This is a test bus. Data is present on [3:0],
+	 *	and its corresponding select (enable) is present
+	 *	on bits [7:4].
+	 * @ate_reset: Reset input from automatic test equipment.
+	 *	This is a test signal. When the USB Core is
+	 *	powered up (not in Susned Mode), an automatic
+	 *	tester can use this to disable phy_clock and
+	 *	free_clk, then re-eanable them with an aligned
+	 *	phase.
+	 *	'1': The phy_clk and free_clk outputs are
+	 *	disabled. "0": The phy_clock and free_clk outputs
+	 *	are available within a specific period after the
+	 *	de-assertion.
+	 */
+	struct cvmx_usbnx_usbp_ctl_status_s {
+		uint64_t txrisetune		: 1;
+		uint64_t txvreftune		: 4;
+		uint64_t txfslstune		: 4;
+		uint64_t txhsxvtune		: 2;
+		uint64_t sqrxtune		: 3;
+		uint64_t compdistune		: 3;
+		uint64_t otgtune		: 3;
+		uint64_t otgdisable		: 1;
+		uint64_t portreset		: 1;
+		uint64_t drvvbus		: 1;
+		uint64_t lsbist			: 1;
+		uint64_t fsbist			: 1;
+		uint64_t hsbist			: 1;
+		uint64_t bist_done		: 1;
+		uint64_t bist_err		: 1;
+		uint64_t tdata_out		: 4;
+		uint64_t siddq			: 1;
+		uint64_t txpreemphasistune	: 1;
+		uint64_t dma_bmode		: 1;
+		uint64_t usbc_end		: 1;
+		uint64_t usbp_bist		: 1;
+		uint64_t tclk			: 1;
+		uint64_t dp_pulld		: 1;
+		uint64_t dm_pulld		: 1;
+		uint64_t hst_mode		: 1;
+		uint64_t tuning			: 4;
+		uint64_t tx_bs_enh		: 1;
+		uint64_t tx_bs_en		: 1;
+		uint64_t loop_enb		: 1;
+		uint64_t vtest_enb		: 1;
+		uint64_t bist_enb		: 1;
+		uint64_t tdata_sel		: 1;
+		uint64_t taddr_in		: 4;
+		uint64_t tdata_in		: 8;
+		uint64_t ate_reset		: 1;
+	} s;
+};
+
+#endif /* __OCTEON_HCD_H__ */
diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c
index e14a1bb..0315f60 100644
--- a/drivers/staging/octeon/ethernet-rx.c
+++ b/drivers/staging/octeon/ethernet-rx.c
@@ -72,7 +72,7 @@
 	int baseline_cores;
 	/*
 	 * The number of additional cores that could be processing
-	 * input packtes.
+	 * input packets.
 	 */
 	atomic_t available_cores;
 	cpumask_t cpu_state;
@@ -80,6 +80,8 @@
 
 static struct cvm_oct_core_state core_state __cacheline_aligned_in_smp;
 
+static int cvm_irq_cpu;
+
 static void cvm_oct_enable_napi(void *_)
 {
 	int cpu = smp_processor_id();
@@ -112,11 +114,7 @@
 {
 	int cpu = smp_processor_id();
 
-	/*
-	 * CPU zero is special.  It always has the irq enabled when
-	 * waiting for incoming packets.
-	 */
-	if (cpu == 0) {
+	if (cpu == cvm_irq_cpu) {
 		enable_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group);
 		return;
 	}
@@ -135,6 +133,7 @@
 {
 	/* Disable the IRQ and start napi_poll. */
 	disable_irq_nosync(OCTEON_IRQ_WORKQ0 + pow_receive_group);
+	cvm_irq_cpu = smp_processor_id();
 	cvm_oct_enable_napi(NULL);
 
 	return IRQ_HANDLED;
@@ -514,7 +513,7 @@
 	if (NULL == dev_for_napi)
 		panic("No net_devices were allocated.");
 
-	if (max_rx_cpus > 1  && max_rx_cpus < num_online_cpus())
+	if (max_rx_cpus >= 1 && max_rx_cpus < num_online_cpus())
 		atomic_set(&core_state.available_cores, max_rx_cpus);
 	else
 		atomic_set(&core_state.available_cores, num_online_cpus());
@@ -526,7 +525,7 @@
 			       cvm_oct_napi_poll, rx_napi_weight);
 		napi_enable(&cvm_oct_napi[i].napi);
 	}
-	/* Register an IRQ hander for to receive POW interrupts */
+	/* Register an IRQ handler to receive POW interrupts */
 	i = request_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group,
 			cvm_oct_do_interrupt, 0, "Ethernet", cvm_oct_device);
 
diff --git a/drivers/staging/octeon/ethernet-spi.c b/drivers/staging/octeon/ethernet-spi.c
index af8d628..5108bc0 100644
--- a/drivers/staging/octeon/ethernet-spi.c
+++ b/drivers/staging/octeon/ethernet-spi.c
@@ -64,31 +64,23 @@
 			if (spx_int_reg.s.spf)
 				pr_err("SPI1: SRX Spi4 interface down\n");
 			if (spx_int_reg.s.calerr)
-				pr_err("SPI1: SRX Spi4 Calendar table "
-				       "parity error\n");
+				pr_err("SPI1: SRX Spi4 Calendar table parity error\n");
 			if (spx_int_reg.s.syncerr)
-				pr_err("SPI1: SRX Consecutive Spi4 DIP4 "
-				       "errors have exceeded "
-				       "SPX_ERR_CTL[ERRCNT]\n");
+				pr_err("SPI1: SRX Consecutive Spi4 DIP4 errors have exceeded SPX_ERR_CTL[ERRCNT]\n");
 			if (spx_int_reg.s.diperr)
 				pr_err("SPI1: SRX Spi4 DIP4 error\n");
 			if (spx_int_reg.s.tpaovr)
-				pr_err("SPI1: SRX Selected port has hit "
-				       "TPA overflow\n");
+				pr_err("SPI1: SRX Selected port has hit TPA overflow\n");
 			if (spx_int_reg.s.rsverr)
-				pr_err("SPI1: SRX Spi4 reserved control "
-				       "word detected\n");
+				pr_err("SPI1: SRX Spi4 reserved control word detected\n");
 			if (spx_int_reg.s.drwnng)
-				pr_err("SPI1: SRX Spi4 receive FIFO "
-				       "drowning/overflow\n");
+				pr_err("SPI1: SRX Spi4 receive FIFO drowning/overflow\n");
 			if (spx_int_reg.s.clserr)
-				pr_err("SPI1: SRX Spi4 packet closed on "
-				       "non-16B alignment without EOP\n");
+				pr_err("SPI1: SRX Spi4 packet closed on non-16B alignment without EOP\n");
 			if (spx_int_reg.s.spiovr)
 				pr_err("SPI1: SRX Spi4 async FIFO overflow\n");
 			if (spx_int_reg.s.abnorm)
-				pr_err("SPI1: SRX Abnormal packet "
-				       "termination (ERR bit)\n");
+				pr_err("SPI1: SRX Abnormal packet termination (ERR bit)\n");
 			if (spx_int_reg.s.prtnxa)
 				pr_err("SPI1: SRX Port out of range\n");
 		}
@@ -99,31 +91,23 @@
 
 			stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(1));
 			if (stx_int_reg.s.syncerr)
-				pr_err("SPI1: STX Interface encountered a "
-				       "fatal error\n");
+				pr_err("SPI1: STX Interface encountered a fatal error\n");
 			if (stx_int_reg.s.frmerr)
-				pr_err("SPI1: STX FRMCNT has exceeded "
-				       "STX_DIP_CNT[MAXFRM]\n");
+				pr_err("SPI1: STX FRMCNT has exceeded STX_DIP_CNT[MAXFRM]\n");
 			if (stx_int_reg.s.unxfrm)
-				pr_err("SPI1: STX Unexpected framing "
-				       "sequence\n");
+				pr_err("SPI1: STX Unexpected framing sequence\n");
 			if (stx_int_reg.s.nosync)
-				pr_err("SPI1: STX ERRCNT has exceeded "
-				       "STX_DIP_CNT[MAXDIP]\n");
+				pr_err("SPI1: STX ERRCNT has exceeded STX_DIP_CNT[MAXDIP]\n");
 			if (stx_int_reg.s.diperr)
-				pr_err("SPI1: STX DIP2 error on the Spi4 "
-				       "Status channel\n");
+				pr_err("SPI1: STX DIP2 error on the Spi4 Status channel\n");
 			if (stx_int_reg.s.datovr)
 				pr_err("SPI1: STX Spi4 FIFO overflow error\n");
 			if (stx_int_reg.s.ovrbst)
-				pr_err("SPI1: STX Transmit packet burst "
-				       "too big\n");
+				pr_err("SPI1: STX Transmit packet burst too big\n");
 			if (stx_int_reg.s.calpar1)
-				pr_err("SPI1: STX Calendar Table Parity "
-				       "Error Bank1\n");
+				pr_err("SPI1: STX Calendar Table Parity Error Bank1\n");
 			if (stx_int_reg.s.calpar0)
-				pr_err("SPI1: STX Calendar Table Parity "
-				       "Error Bank0\n");
+				pr_err("SPI1: STX Calendar Table Parity Error Bank0\n");
 		}
 
 		cvmx_write_csr(CVMX_SPXX_INT_MSK(1), 0);
@@ -144,31 +128,23 @@
 			if (spx_int_reg.s.spf)
 				pr_err("SPI0: SRX Spi4 interface down\n");
 			if (spx_int_reg.s.calerr)
-				pr_err("SPI0: SRX Spi4 Calendar table "
-				       "parity error\n");
+				pr_err("SPI0: SRX Spi4 Calendar table parity error\n");
 			if (spx_int_reg.s.syncerr)
-				pr_err("SPI0: SRX Consecutive Spi4 DIP4 "
-				       "errors have exceeded "
-				       "SPX_ERR_CTL[ERRCNT]\n");
+				pr_err("SPI0: SRX Consecutive Spi4 DIP4 errors have exceeded SPX_ERR_CTL[ERRCNT]\n");
 			if (spx_int_reg.s.diperr)
 				pr_err("SPI0: SRX Spi4 DIP4 error\n");
 			if (spx_int_reg.s.tpaovr)
-				pr_err("SPI0: SRX Selected port has hit "
-				       "TPA overflow\n");
+				pr_err("SPI0: SRX Selected port has hit TPA overflow\n");
 			if (spx_int_reg.s.rsverr)
-				pr_err("SPI0: SRX Spi4 reserved control "
-				       "word detected\n");
+				pr_err("SPI0: SRX Spi4 reserved control word detected\n");
 			if (spx_int_reg.s.drwnng)
-				pr_err("SPI0: SRX Spi4 receive FIFO "
-				       "drowning/overflow\n");
+				pr_err("SPI0: SRX Spi4 receive FIFO drowning/overflow\n");
 			if (spx_int_reg.s.clserr)
-				pr_err("SPI0: SRX Spi4 packet closed on "
-				       "non-16B alignment without EOP\n");
+				pr_err("SPI0: SRX Spi4 packet closed on non-16B alignment without EOP\n");
 			if (spx_int_reg.s.spiovr)
 				pr_err("SPI0: SRX Spi4 async FIFO overflow\n");
 			if (spx_int_reg.s.abnorm)
-				pr_err("SPI0: SRX Abnormal packet "
-				       "termination (ERR bit)\n");
+				pr_err("SPI0: SRX Abnormal packet termination (ERR bit)\n");
 			if (spx_int_reg.s.prtnxa)
 				pr_err("SPI0: SRX Port out of range\n");
 		}
@@ -179,31 +155,23 @@
 
 			stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(0));
 			if (stx_int_reg.s.syncerr)
-				pr_err("SPI0: STX Interface encountered a "
-				       "fatal error\n");
+				pr_err("SPI0: STX Interface encountered a fatal error\n");
 			if (stx_int_reg.s.frmerr)
-				pr_err("SPI0: STX FRMCNT has exceeded "
-				       "STX_DIP_CNT[MAXFRM]\n");
+				pr_err("SPI0: STX FRMCNT has exceeded STX_DIP_CNT[MAXFRM]\n");
 			if (stx_int_reg.s.unxfrm)
-				pr_err("SPI0: STX Unexpected framing "
-				       "sequence\n");
+				pr_err("SPI0: STX Unexpected framing sequence\n");
 			if (stx_int_reg.s.nosync)
-				pr_err("SPI0: STX ERRCNT has exceeded "
-				       "STX_DIP_CNT[MAXDIP]\n");
+				pr_err("SPI0: STX ERRCNT has exceeded STX_DIP_CNT[MAXDIP]\n");
 			if (stx_int_reg.s.diperr)
-				pr_err("SPI0: STX DIP2 error on the Spi4 "
-				       "Status channel\n");
+				pr_err("SPI0: STX DIP2 error on the Spi4 Status channel\n");
 			if (stx_int_reg.s.datovr)
 				pr_err("SPI0: STX Spi4 FIFO overflow error\n");
 			if (stx_int_reg.s.ovrbst)
-				pr_err("SPI0: STX Transmit packet burst "
-				       "too big\n");
+				pr_err("SPI0: STX Transmit packet burst too big\n");
 			if (stx_int_reg.s.calpar1)
-				pr_err("SPI0: STX Calendar Table Parity "
-				       "Error Bank1\n");
+				pr_err("SPI0: STX Calendar Table Parity Error Bank1\n");
 			if (stx_int_reg.s.calpar0)
-				pr_err("SPI0: STX Calendar Table Parity "
-				       "Error Bank0\n");
+				pr_err("SPI0: STX Calendar Table Parity Error Bank0\n");
 		}
 
 		cvmx_write_csr(CVMX_SPXX_INT_MSK(0), 0);
diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c
index 5631dd9..9b4d0b5 100644
--- a/drivers/staging/octeon/ethernet-tx.c
+++ b/drivers/staging/octeon/ethernet-tx.c
@@ -78,10 +78,12 @@
 static inline int32_t cvm_oct_adjust_skb_to_free(int32_t skb_to_free, int fau)
 {
 	int32_t undo;
-	undo = skb_to_free > 0 ? MAX_SKB_TO_FREE : skb_to_free + MAX_SKB_TO_FREE;
+	undo = skb_to_free > 0 ? MAX_SKB_TO_FREE : skb_to_free +
+						   MAX_SKB_TO_FREE;
 	if (undo > 0)
 		cvmx_fau_atomic_add32(fau, -undo);
-	skb_to_free = -skb_to_free > MAX_SKB_TO_FREE ? MAX_SKB_TO_FREE : -skb_to_free;
+	skb_to_free = -skb_to_free > MAX_SKB_TO_FREE ? MAX_SKB_TO_FREE :
+						       -skb_to_free;
 	return skb_to_free;
 }
 
@@ -108,8 +110,10 @@
 	for (qos = 0; qos < queues_per_port; qos++) {
 		if (skb_queue_len(&priv->tx_free_list[qos]) == 0)
 			continue;
-		skb_to_free = cvmx_fau_fetch_and_add32(priv->fau+qos*4, MAX_SKB_TO_FREE);
-		skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, priv->fau+qos*4);
+		skb_to_free = cvmx_fau_fetch_and_add32(priv->fau+qos*4,
+						       MAX_SKB_TO_FREE);
+		skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free,
+							 priv->fau+qos*4);
 
 
 		total_freed += skb_to_free;
@@ -117,12 +121,14 @@
 			struct sk_buff *to_free_list = NULL;
 			spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags);
 			while (skb_to_free > 0) {
-				struct sk_buff *t = __skb_dequeue(&priv->tx_free_list[qos]);
+				struct sk_buff *t;
+				t = __skb_dequeue(&priv->tx_free_list[qos]);
 				t->next = to_free_list;
 				to_free_list = t;
 				skb_to_free--;
 			}
-			spin_unlock_irqrestore(&priv->tx_free_list[qos].lock, flags);
+			spin_unlock_irqrestore(&priv->tx_free_list[qos].lock,
+					       flags);
 			/* Do the actual freeing outside of the lock. */
 			while (to_free_list) {
 				struct sk_buff *t = to_free_list;
@@ -211,15 +217,23 @@
 		if (unlikely(__skb_linearize(skb))) {
 			queue_type = QUEUE_DROP;
 			if (USE_ASYNC_IOBDMA) {
-				/* Get the number of skbuffs in use by the hardware */
+				/*
+				 * Get the number of skbuffs in use
+				 * by the hardware
+				 */
 				CVMX_SYNCIOBDMA;
-				skb_to_free = cvmx_scratch_read64(CVMX_SCR_SCRATCH);
+				skb_to_free =
+					cvmx_scratch_read64(CVMX_SCR_SCRATCH);
 			} else {
-				/* Get the number of skbuffs in use by the hardware */
-				skb_to_free = cvmx_fau_fetch_and_add32(priv->fau + qos * 4,
-								       MAX_SKB_TO_FREE);
+				/*
+				 * Get the number of skbuffs in use
+				 * by the hardware
+				 */
+				skb_to_free = cvmx_fau_fetch_and_add32(
+					priv->fau + qos * 4, MAX_SKB_TO_FREE);
 			}
-			skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, priv->fau + qos * 4);
+			skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free,
+							priv->fau + qos * 4);
 			spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags);
 			goto skip_xmit;
 		}
@@ -276,7 +290,9 @@
 		CVM_OCT_SKB_CB(skb)[0] = hw_buffer.u64;
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 			struct skb_frag_struct *fs = skb_shinfo(skb)->frags + i;
-			hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)(page_address(fs->page.p) + fs->page_offset));
+			hw_buffer.s.addr = XKPHYS_TO_PHYS(
+				(u64)(page_address(fs->page.p) +
+				fs->page_offset));
 			hw_buffer.s.size = fs->size;
 			CVM_OCT_SKB_CB(skb)[i + 1] = hw_buffer.u64;
 		}
@@ -358,7 +374,9 @@
 	 */
 	pko_command.s.dontfree = 0;
 
-	hw_buffer.s.back = ((unsigned long)skb->data >> 7) - ((unsigned long)fpa_head >> 7);
+	hw_buffer.s.back = ((unsigned long)skb->data >> 7) -
+			   ((unsigned long)fpa_head >> 7);
+
 	*(struct sk_buff **)(fpa_head - sizeof(void *)) = skb;
 
 	/*
@@ -422,17 +440,22 @@
 		queue_type = QUEUE_HW;
 	}
 	if (USE_ASYNC_IOBDMA)
-		cvmx_fau_async_fetch_and_add32(CVMX_SCR_SCRATCH, FAU_TOTAL_TX_TO_CLEAN, 1);
+		cvmx_fau_async_fetch_and_add32(
+				CVMX_SCR_SCRATCH, FAU_TOTAL_TX_TO_CLEAN, 1);
 
 	spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags);
 
 	/* Drop this packet if we have too many already queued to the HW */
-	if (unlikely(skb_queue_len(&priv->tx_free_list[qos]) >= MAX_OUT_QUEUE_DEPTH)) {
+	if (unlikely(skb_queue_len(&priv->tx_free_list[qos]) >=
+		     MAX_OUT_QUEUE_DEPTH)) {
+
 		if (dev->tx_queue_len != 0) {
 			/* Drop the lock when notifying the core.  */
-			spin_unlock_irqrestore(&priv->tx_free_list[qos].lock, flags);
+			spin_unlock_irqrestore(&priv->tx_free_list[qos].lock,
+					       flags);
 			netif_stop_queue(dev);
-			spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags);
+			spin_lock_irqsave(&priv->tx_free_list[qos].lock,
+					  flags);
 		} else {
 			/* If not using normal queueing.  */
 			queue_type = QUEUE_DROP;
@@ -448,7 +471,8 @@
 						 priv->queue + qos,
 						 pko_command, hw_buffer,
 						 CVMX_PKO_LOCK_NONE))) {
-		printk_ratelimited("%s: Failed to send the packet\n", dev->name);
+		printk_ratelimited("%s: Failed to send the packet\n",
+				   dev->name);
 		queue_type = QUEUE_DROP;
 	}
 skip_xmit:
@@ -493,7 +517,8 @@
 		cvmx_scratch_write64(CVMX_SCR_SCRATCH, old_scratch);
 		cvmx_scratch_write64(CVMX_SCR_SCRATCH + 8, old_scratch2);
 	} else {
-		total_to_clean = cvmx_fau_fetch_and_add32(FAU_TOTAL_TX_TO_CLEAN, 1);
+		total_to_clean = cvmx_fau_fetch_and_add32(
+						FAU_TOTAL_TX_TO_CLEAN, 1);
 	}
 
 	if (total_to_clean & 0x3ff) {
@@ -527,8 +552,8 @@
 	/* Get a work queue entry */
 	cvmx_wqe_t *work = cvmx_fpa_alloc(CVMX_FPA_WQE_POOL);
 	if (unlikely(work == NULL)) {
-		printk_ratelimited("%s: Failed to allocate a work "
-				   "queue entry\n", dev->name);
+		printk_ratelimited("%s: Failed to allocate a work queue entry\n",
+				   dev->name);
 		priv->stats.tx_dropped++;
 		dev_kfree_skb(skb);
 		return 0;
@@ -709,7 +734,7 @@
 
 	/* Disable the interrupt.  */
 	cvmx_write_csr(CVMX_CIU_TIMX(1), 0);
-	/* Register an IRQ hander for to receive CIU_TIMX(1) interrupts */
+	/* Register an IRQ handler to receive CIU_TIMX(1) interrupts */
 	i = request_irq(OCTEON_IRQ_TIMER1,
 			cvm_oct_tx_cleanup_watchdog, 0,
 			"Ethernet", cvm_oct_device);
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index c3a90e7..bd6ca71 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -163,11 +163,13 @@
 	if (priv->poll)
 		priv->poll(cvm_oct_device[priv->port]);
 
-	cvm_oct_device[priv->port]->netdev_ops->ndo_get_stats(cvm_oct_device[priv->port]);
+	cvm_oct_device[priv->port]->netdev_ops->ndo_get_stats(
+						cvm_oct_device[priv->port]);
 
 	if (!atomic_read(&cvm_oct_poll_queue_stopping))
-		queue_delayed_work(cvm_oct_poll_queue, &priv->port_periodic_work, HZ);
- }
+		queue_delayed_work(cvm_oct_poll_queue,
+						&priv->port_periodic_work, HZ);
+}
 
 static void cvm_oct_configure_common_hw(void)
 {
@@ -453,7 +455,7 @@
 	if (priv->of_node)
 		mac = of_get_mac_address(priv->of_node);
 
-	if (mac && is_valid_ether_addr(mac))
+	if (mac)
 		memcpy(dev->dev_addr, mac, ETH_ALEN);
 	else
 		eth_hw_addr_random(dev);
@@ -584,8 +586,8 @@
 
 extern void octeon_mdiobus_force_mod_depencency(void);
 
-static struct device_node *cvm_oct_of_get_child(const struct device_node *parent,
-							   int reg_val)
+static struct device_node *cvm_oct_of_get_child(
+				const struct device_node *parent, int reg_val)
 {
 	struct device_node *node = NULL;
 	int size;
@@ -603,7 +605,7 @@
 }
 
 static struct device_node *cvm_oct_node_for_port(struct device_node *pip,
-							    int interface, int port)
+							int interface, int port)
 {
 	struct device_node *ni, *np;
 
@@ -713,7 +715,8 @@
 		int port;
 		int port_index;
 
-		for (port_index = 0, port = cvmx_helper_get_ipd_port(interface, 0);
+		for (port_index = 0,
+		     port = cvmx_helper_get_ipd_port(interface, 0);
 		     port < cvmx_helper_get_ipd_port(interface, num_ports);
 		     port_index++, port++) {
 			struct octeon_ethernet *priv;
@@ -726,7 +729,8 @@
 
 			/* Initialize the device private structure. */
 			priv = netdev_priv(dev);
-			priv->of_node = cvm_oct_node_for_port(pip, interface, port_index);
+			priv->of_node = cvm_oct_node_for_port(pip, interface,
+								port_index);
 
 			INIT_DELAYED_WORK(&priv->port_periodic_work,
 					  cvm_oct_periodic_worker);
@@ -793,7 +797,7 @@
 				    cvmx_pko_get_num_queues(priv->port) *
 				    sizeof(uint32_t);
 				queue_delayed_work(cvm_oct_poll_queue,
-						   &priv->port_periodic_work, HZ);
+						&priv->port_periodic_work, HZ);
 			}
 		}
 	}
diff --git a/drivers/staging/olpc_dcon/Kconfig b/drivers/staging/olpc_dcon/Kconfig
index 2ff015d..d277f04 100644
--- a/drivers/staging/olpc_dcon/Kconfig
+++ b/drivers/staging/olpc_dcon/Kconfig
@@ -1,7 +1,8 @@
 config FB_OLPC_DCON
 	tristate "One Laptop Per Child Display CONtroller support"
 	depends on OLPC && FB
-	select I2C
+	depends on I2C
+	depends on (GPIO_CS5535 || GPIO_CS5535=n)
 	select BACKLIGHT_CLASS_DEVICE
 	---help---
 	  In order to support very low power operation, the XO laptop uses a
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c
index 198595e..92b0289 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon.c
+++ b/drivers/staging/olpc_dcon/olpc_dcon.c
@@ -383,7 +383,7 @@
 
 	dcon->pending_src = arg;
 
-	if ((dcon->curr_src != arg) && !work_pending(&dcon->switch_source))
+	if (dcon->curr_src != arg)
 		schedule_work(&dcon->switch_source);
 }
 
diff --git a/drivers/staging/ozwpan/ozcdev.c b/drivers/staging/ozwpan/ozcdev.c
index 6ccb64f..6ce0af9 100644
--- a/drivers/staging/ozwpan/ozcdev.c
+++ b/drivers/staging/ozwpan/ozcdev.c
@@ -155,6 +155,9 @@
 	struct oz_app_hdr *app_hdr;
 	struct oz_serial_ctx *ctx;
 
+	if (count > sizeof(ei->data) - sizeof(*elt) - sizeof(*app_hdr))
+		return -EINVAL;
+
 	spin_lock_bh(&g_cdev.lock);
 	pd = g_cdev.active_pd;
 	if (pd)
diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c
index 4247d60..9f6ebdb 100644
--- a/drivers/staging/quickstart/quickstart.c
+++ b/drivers/staging/quickstart/quickstart.c
@@ -390,10 +390,6 @@
 {
 	int ret;
 
-	/* ACPI Check */
-	if (acpi_disabled)
-		return -ENODEV;
-
 	/* ACPI driver register */
 	ret = acpi_bus_register_driver(&quickstart_acpi_driver);
 	if (ret)
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
index 10b2210..3045790 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
@@ -858,7 +858,7 @@
 
 }
 
-int
+static int
 ieee80211_TranslateToDbm(
 	unsigned char SignalStrengthIndex	// 0-100 index.
 	)
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
index b65db54..0290706 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
@@ -887,7 +887,8 @@
 	return skb;
 }
 
-struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest)
+static struct sk_buff *ieee80211_assoc_resp(struct ieee80211_device *ieee,
+					    u8 *dest)
 {
 	struct sk_buff *skb;
 	u8* tag;
@@ -940,7 +941,8 @@
 	return skb;
 }
 
-struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8 *dest)
+static struct sk_buff *ieee80211_auth_resp(struct ieee80211_device *ieee,
+					   int status, u8 *dest)
 {
 	struct sk_buff *skb;
 	struct ieee80211_authentication *auth;
@@ -2942,14 +2944,9 @@
 		goto out;
 	}
 
-	param = kmalloc(p->length, GFP_KERNEL);
-	if (param == NULL){
-		ret = -ENOMEM;
-		goto out;
-	}
-	if (copy_from_user(param, p->pointer, p->length)) {
-		kfree(param);
-		ret = -EFAULT;
+	param = memdup_user(p->pointer, p->length);
+	if (IS_ERR(param)) {
+		ret = PTR_ERR(param);
 		goto out;
 	}
 
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
index b346653..f5a5219 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
@@ -32,7 +32,6 @@
 ******************************************************************************/
 
 #include <linux/compiler.h>
-//#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/if_arp.h>
 #include <linux/in6.h>
@@ -186,9 +185,12 @@
 	struct ieee80211_crypt_data* crypt = ieee->crypt[ieee->tx_keyidx];
 	int res;
 
- /*added to care about null crypt condition, to solve that system hangs when shared keys error*/
-        if (!crypt || !crypt->ops)
-        return -1;
+	/*
+	 * added to care about null crypt condition, to solve that system hangs
+	 * when shared keys error
+	 */
+	if (!crypt || !crypt->ops)
+		return -1;
 
 #ifdef CONFIG_IEEE80211_CRYPT_TKIP
 	struct ieee80211_hdr_4addr *header;
@@ -197,19 +199,22 @@
 	    crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
 		header = (struct ieee80211_hdr_4addr *)frag->data;
 		if (net_ratelimit()) {
-			printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
-			       "TX packet to %pM\n",
-			       ieee->dev->name, header->addr1);
+			netdev_dbg(ieee->dev, "TKIP countermeasures: dropped "
+			       "TX packet to %pM\n", header->addr1);
 		}
 		return -1;
 	}
 #endif
-	/* To encrypt, frame format is:
-	 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
-
-	// PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption.
-	/* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
-	 * call both MSDU and MPDU encryption functions from here. */
+	/*
+	 * To encrypt, frame format is:
+	 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes)
+	 *
+	 * PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU
+	 * encryption.
+	 *
+	 * Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
+	 * call both MSDU and MPDU encryption functions from here.
+	 */
 	atomic_inc(&crypt->refcnt);
 	res = 0;
 	if (crypt->ops->encrypt_msdu)
@@ -219,8 +224,7 @@
 
 	atomic_dec(&crypt->refcnt);
 	if (res < 0) {
-		printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
-		       ieee->dev->name, frag->len);
+		netdev_info(ieee->dev, "Encryption failed: len=%d.\n", frag->len);
 		ieee->ieee_stats.tx_discards++;
 		return -1;
 	}
@@ -229,7 +233,8 @@
 }
 
 
-void ieee80211_txb_free(struct ieee80211_txb *txb) {
+void ieee80211_txb_free(struct ieee80211_txb *txb)
+{
 	int i;
 	if (unlikely(!txb))
 		return;
@@ -239,13 +244,13 @@
 	kfree(txb);
 }
 
-struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
-					  int gfp_mask)
+static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
+						 gfp_t gfp_mask)
 {
 	struct ieee80211_txb *txb;
 	int i;
 	txb = kmalloc(
-		sizeof(struct ieee80211_txb) + (sizeof(u8*) * nr_frags),
+		sizeof(struct ieee80211_txb) + (sizeof(u8 *) * nr_frags),
 		gfp_mask);
 	if (!txb)
 		return NULL;
@@ -270,42 +275,43 @@
 	return txb;
 }
 
-// Classify the to-be send data packet
-// Need to acquire the sent queue index.
+/*
+ * Classify the to-be send data packet
+ * Need to acquire the sent queue index.
+ */
 static int
 ieee80211_classify(struct sk_buff *skb, struct ieee80211_network *network)
 {
-  struct ether_header *eh = (struct ether_header*)skb->data;
-  unsigned int wme_UP = 0;
+	struct ether_header *eh = (struct ether_header *)skb->data;
+	unsigned int wme_UP = 0;
 
-  if(!network->QoS_Enable) {
-     skb->priority = 0;
-     return(wme_UP);
-  }
+	if (!network->QoS_Enable) {
+		skb->priority = 0;
+		return(wme_UP);
+	}
 
-  if(eh->ether_type == __constant_htons(ETHERTYPE_IP)) {
-    const struct iphdr *ih = (struct iphdr*)(skb->data + \
+	if (eh->ether_type == __constant_htons(ETHERTYPE_IP)) {
+		const struct iphdr *ih = (struct iphdr *)(skb->data +
 		    sizeof(struct ether_header));
-    wme_UP = (ih->tos >> 5)&0x07;
-  } else if (vlan_tx_tag_present(skb)) {//vtag packet
+		wme_UP = (ih->tos >> 5)&0x07;
+	} else if (vlan_tx_tag_present(skb)) {/* vtag packet */
 #ifndef VLAN_PRI_SHIFT
 #define VLAN_PRI_SHIFT  13              /* Shift to find VLAN user priority */
 #define VLAN_PRI_MASK   7               /* Mask for user priority bits in VLAN */
 #endif
-	u32 tag = vlan_tx_tag_get(skb);
-	wme_UP = (tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
-  } else if(ETH_P_PAE ==  ntohs(((struct ethhdr *)skb->data)->h_proto)) {
-    //printk(KERN_WARNING "type = normal packet\n");
-    wme_UP = 7;
-  }
+		u32 tag = vlan_tx_tag_get(skb);
+		wme_UP = (tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
+	} else if (ETH_P_PAE ==  ntohs(((struct ethhdr *)skb->data)->h_proto)) {
+		wme_UP = 7;
+	}
 
-  skb->priority = wme_UP;
-  return(wme_UP);
+	skb->priority = wme_UP;
+	return(wme_UP);
 }
 
 /* SKBs are added to the ieee->tx_queue. */
 int ieee80211_rtl_xmit(struct sk_buff *skb,
-		   struct net_device *dev)
+		       struct net_device *dev)
 {
 	struct ieee80211_device *ieee = netdev_priv(dev);
 	struct ieee80211_txb *txb = NULL;
@@ -325,24 +331,25 @@
 
 	struct ieee80211_crypt_data* crypt;
 
-	//printk(KERN_WARNING "upper layer packet!\n");
 	spin_lock_irqsave(&ieee->lock, flags);
 
-	/* If there is no driver handler to take the TXB, don't bother
-	 * creating it... */
-	if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))||
-	   ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
-		printk(KERN_WARNING "%s: No xmit handler.\n",
-		       ieee->dev->name);
+	/*
+	 * If there is no driver handler to take the TXB, don't bother
+	 * creating it...
+	 */
+	if ((!ieee->hard_start_xmit &&
+	     !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)) ||
+	    ((!ieee->softmac_data_hard_start_xmit &&
+	      (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
+		netdev_warn(ieee->dev, "No xmit handler.\n");
 		goto success;
 	}
 
 	ieee80211_classify(skb,&ieee->current_network);
-	if(likely(ieee->raw_tx == 0)){
+	if (likely(ieee->raw_tx == 0)){
 
 		if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
-			printk(KERN_WARNING "%s: skb too small (%d).\n",
-			ieee->dev->name, skb->len);
+			netdev_warn(ieee->dev, "skb too small (%d).\n", skb->len);
 			goto success;
 		}
 
@@ -378,7 +385,7 @@
 		/* Determine total amount of storage required for TXB packets */
 		bytes = skb->len + SNAP_SIZE + sizeof(u16);
 
-		if(ieee->current_network.QoS_Enable) {
+		if (ieee->current_network.QoS_Enable) {
 			if (encrypt)
 				fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA |
 					IEEE80211_FCTL_WEP;
@@ -395,31 +402,31 @@
 
 		if (ieee->iw_mode == IW_MODE_INFRA) {
 			fc |= IEEE80211_FCTL_TODS;
-			/* To DS: Addr1 = BSSID, Addr2 = SA,
-			Addr3 = DA */
+			/* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */
 			memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN);
 			memcpy(&header.addr2, &src, ETH_ALEN);
 			memcpy(&header.addr3, &dest, ETH_ALEN);
 		} else if (ieee->iw_mode == IW_MODE_ADHOC) {
-			/* not From/To DS: Addr1 = DA, Addr2 = SA,
-			Addr3 = BSSID */
+			/*
+			 * not From/To DS: Addr1 = DA, Addr2 = SA,
+			 * Addr3 = BSSID
+			 */
 			memcpy(&header.addr1, dest, ETH_ALEN);
 			memcpy(&header.addr2, src, ETH_ALEN);
 			memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN);
 		}
-	//	printk(KERN_WARNING "essid MAC address is %pM", &header.addr1);
 		header.frame_ctl = cpu_to_le16(fc);
-		//hdr_len = IEEE80211_3ADDR_LEN;
 
-		/* Determine fragmentation size based on destination (multicast
-		* and broadcast are not fragmented) */
+		/*
+		 * Determine fragmentation size based on destination (multicast
+		 * and broadcast are not fragmented)
+		 */
 		if (is_multicast_ether_addr(header.addr1)) {
 			frag_size = MAX_FRAG_THRESHOLD;
 			qos_ctl = QOS_CTL_NOTCONTAIN_ACK;
-		}
-		else {
-			//printk(KERN_WARNING "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&frag_size = %d\n", frag_size);
-			frag_size = ieee->fts;//default:392
+		} else {
+			/* default:392 */
+			frag_size = ieee->fts;
 			qos_ctl = 0;
 		}
 
@@ -432,11 +439,12 @@
 			hdr_len = IEEE80211_3ADDR_LEN;
 		}
 
-		/* Determine amount of payload per fragment.  Regardless of if
-		* this stack is providing the full 802.11 header, one will
-		* eventually be affixed to this fragment -- so we must account for
-		* it when determining the amount of payload space. */
-		//bytes_per_frag = frag_size - (IEEE80211_3ADDR_LEN + (ieee->current_network->QoS_Enable ? 2:0));
+		/*
+		 * Determine amount of payload per fragment.  Regardless of if
+		 * this stack is providing the full 802.11 header, one will
+		 * eventually be affixed to this fragment -- so we must account
+		 * for it when determining the amount of payload space.
+		 */
 		bytes_per_frag = frag_size - hdr_len;
 		if (ieee->config &
 		(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
@@ -447,8 +455,10 @@
 			bytes_per_frag -= crypt->ops->extra_prefix_len +
 				crypt->ops->extra_postfix_len;
 
-		/* Number of fragments is the total bytes_per_frag /
-		* payload_per_fragment */
+		/*
+		 * Number of fragments is the total bytes_per_frag /
+		 * payload_per_fragment
+		 */
 		nr_frags = bytes / bytes_per_frag;
 		bytes_last_frag = bytes % bytes_per_frag;
 		if (bytes_last_frag)
@@ -456,13 +466,14 @@
 		else
 			bytes_last_frag = bytes_per_frag;
 
-		/* When we allocate the TXB we allocate enough space for the reserve
-		* and full fragment bytes (bytes_per_frag doesn't include prefix,
-		* postfix, header, FCS, etc.) */
+		/*
+		 * When we allocate the TXB we allocate enough space for the 
+		 * reserve and full fragment bytes (bytes_per_frag doesn't
+		 * include prefix, postfix, header, FCS, etc.)
+		 */
 		txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC);
 		if (unlikely(!txb)) {
-			printk(KERN_WARNING "%s: Could not allocate TXB\n",
-			ieee->dev->name);
+			netdev_warn(ieee->dev, "Could not allocate TXB\n");
 			goto failed;
 		}
 		txb->encrypted = encrypt;
@@ -474,11 +485,14 @@
 			if (encrypt)
 				skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
 
-			frag_hdr = (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
+			frag_hdr = (struct ieee80211_hdr_3addrqos *)skb_put(
+				skb_frag, hdr_len);
 			memcpy(frag_hdr, &header, hdr_len);
 
-			/* If this is not the last fragment, then add the MOREFRAGS
-			* bit to the frame control */
+			/*
+			 * If this is not the last fragment, then add the MOREFRAGS
+			 * bit to the frame control
+			 */
 			if (i != nr_frags - 1) {
 				frag_hdr->frame_ctl = cpu_to_le16(
 					fc | IEEE80211_FCTL_MOREFRAGS);
@@ -488,16 +502,17 @@
 				/* The last fragment takes the remaining length */
 				bytes = bytes_last_frag;
 			}
-			if(ieee->current_network.QoS_Enable) {
-			  // add 1 only indicate to corresponding seq number control 2006/7/12
-			  frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i);
-			  //printk(KERN_WARNING "skb->priority = %d,", skb->priority);
-			  //printk(KERN_WARNING "type:%d: seq = %d\n",UP2AC(skb->priority),ieee->seq_ctrl[UP2AC(skb->priority)+1]);
+			if (ieee->current_network.QoS_Enable) {
+				/*
+				 * add 1 only indicate to corresponding seq
+				 * number control 2006/7/12
+				 */
+				frag_hdr->seq_ctl = cpu_to_le16(
+					ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i);
 			} else {
-			  frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i);
+				frag_hdr->seq_ctl = cpu_to_le16(
+					ieee->seq_ctrl[0]<<4 | i);
 			}
-			//frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl<<4 | i);
-			//
 
 			/* Put a SNAP header on the first fragment */
 			if (i == 0) {
@@ -512,54 +527,53 @@
 			/* Advance the SKB... */
 			skb_pull(skb, bytes);
 
-			/* Encryption routine will move the header forward in order
-			* to insert the IV between the header and the payload */
+			/*
+			 * Encryption routine will move the header forward in
+			 * order to insert the IV between the header and the
+			 * payload
+			 */
 			if (encrypt)
 				ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
 			if (ieee->config &
 			(CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
 				skb_put(skb_frag, 4);
 		}
-		// Advance sequence number in data frame.
-		//printk(KERN_WARNING "QoS Enalbed? %s\n", ieee->current_network.QoS_Enable?"Y":"N");
+		/* Advance sequence number in data frame. */
 		if (ieee->current_network.QoS_Enable) {
-		  if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF)
-			ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0;
-		  else
-			ieee->seq_ctrl[UP2AC(skb->priority) + 1]++;
+			if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF)
+				ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0;
+			else
+				ieee->seq_ctrl[UP2AC(skb->priority) + 1]++;
 		} else {
-  		  if (ieee->seq_ctrl[0] == 0xFFF)
-			ieee->seq_ctrl[0] = 0;
-		  else
-			ieee->seq_ctrl[0]++;
+			if (ieee->seq_ctrl[0] == 0xFFF)
+				ieee->seq_ctrl[0] = 0;
+			else
+				ieee->seq_ctrl[0]++;
 		}
-		//---
-	}else{
+	} else {
 		if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) {
-			printk(KERN_WARNING "%s: skb too small (%d).\n",
-			ieee->dev->name, skb->len);
+			netdev_warn(ieee->dev, "skb too small (%d).\n", skb->len);
 			goto success;
 		}
 
 		txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC);
-		if(!txb){
-			printk(KERN_WARNING "%s: Could not allocate TXB\n",
-			ieee->dev->name);
+		if (!txb) {
+			netdev_warn(ieee->dev, "Could not allocate TXB\n");
 			goto failed;
 		}
 
 		txb->encrypted = 0;
 		txb->payload_size = skb->len;
-		memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len);
+		memcpy(skb_put(txb->fragments[0], skb->len), skb->data, skb->len);
 	}
 
  success:
 	spin_unlock_irqrestore(&ieee->lock, flags);
 		dev_kfree_skb_any(skb);
 	if (txb) {
-		if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){
+		if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) {
 			ieee80211_softmac_xmit(txb, ieee);
-		}else{
+		} else {
 			if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
 				stats->tx_packets++;
 				stats->tx_bytes += txb->payload_size;
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
index e014f7e..24d39cc 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
@@ -145,7 +145,8 @@
 	/* Add quality statistics */
 	/* TODO: Fix these values... */
 	if (network->stats.signal == 0 || network->stats.rssi == 0)
-	printk("========>signal:%d, rssi:%d\n", network->stats.signal, network->stats.rssi);
+		printk("========>signal:%d, rssi:%d\n", network->stats.signal,
+		       network->stats.rssi);
 	iwe.cmd = IWEVQUAL;
 //	printk("SIGNAL: %d,RSSI: %d,NOISE: %d\n",network->stats.signal,network->stats.rssi,network->stats.noise);
 	iwe.u.qual.qual = network->stats.signalstrength;
@@ -622,7 +623,7 @@
 	if (ieee->set_security)
 		ieee->set_security(ieee->dev, &sec);
 
-	 if (ieee->reset_on_keychange &&
+	if (ieee->reset_on_keychange &&
 	    ieee->iw_mode != IW_MODE_INFRA &&
 	    ieee->reset_port && ieee->reset_port(dev)) {
 		IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
index 5947a6f..76a6738 100644
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ b/drivers/staging/rtl8187se/r8180_core.c
@@ -160,34 +160,34 @@
 
 u8 read_nic_byte(struct net_device *dev, int x)
 {
-	return 0xff&readb((u8 *)dev->mem_start + x);
+	return 0xff&readb((u8 __iomem *)dev->mem_start + x);
 }
 
 u32 read_nic_dword(struct net_device *dev, int x)
 {
-	return readl((u8 *)dev->mem_start + x);
+	return readl((u8 __iomem *)dev->mem_start + x);
 }
 
 u16 read_nic_word(struct net_device *dev, int x)
 {
-	return readw((u8 *)dev->mem_start + x);
+	return readw((u8 __iomem *)dev->mem_start + x);
 }
 
 void write_nic_byte(struct net_device *dev, int x, u8 y)
 {
-	writeb(y, (u8 *)dev->mem_start + x);
+	writeb(y, (u8 __iomem *)dev->mem_start + x);
 	udelay(20);
 }
 
 void write_nic_dword(struct net_device *dev, int x, u32 y)
 {
-	writel(y, (u8 *)dev->mem_start + x);
+	writel(y, (u8 __iomem *)dev->mem_start + x);
 	udelay(20);
 }
 
 void write_nic_word(struct net_device *dev, int x, u16 y)
 {
-	writew(y, (u8 *)dev->mem_start + x);
+	writew(y, (u8 __iomem *)dev->mem_start + x);
 	udelay(20);
 }
 
@@ -275,18 +275,18 @@
 	return 0;
 }
 
-void rtl8180_proc_module_init(void)
+static void rtl8180_proc_module_init(void)
 {
 	DMESG("Initializing proc filesystem");
 	rtl8180_proc = proc_mkdir(RTL8180_MODULE_NAME, init_net.proc_net);
 }
 
-void rtl8180_proc_module_remove(void)
+static void rtl8180_proc_module_remove(void)
 {
 	remove_proc_entry(RTL8180_MODULE_NAME, init_net.proc_net);
 }
 
-void rtl8180_proc_remove_one(struct net_device *dev)
+static void rtl8180_proc_remove_one(struct net_device *dev)
 {
 	remove_proc_subtree(dev->name, rtl8180_proc);
 }
@@ -325,7 +325,7 @@
 	{ "" }
 };
 
-void rtl8180_proc_init_one(struct net_device *dev)
+static void rtl8180_proc_init_one(struct net_device *dev)
 {
 	const struct rtl8180_proc_file *f;
 	struct proc_dir_entry *dir;
@@ -351,8 +351,8 @@
   data type+functions in kernel
 */
 
-short buffer_add(struct buffer **buffer, u32 *buf, dma_addr_t dma,
-		struct buffer **bufferhead)
+static short buffer_add(struct buffer **buffer, u32 *buf, dma_addr_t dma,
+			struct buffer **bufferhead)
 {
 	struct buffer *tmp;
 
@@ -463,7 +463,7 @@
 	return ret;
 }
 
-short check_nic_enought_desc(struct net_device *dev, int priority)
+static short check_nic_enought_desc(struct net_device *dev, int priority)
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
 	struct ieee80211_device *ieee = netdev_priv(dev);
@@ -589,7 +589,7 @@
 	set_nic_rxring(dev);
 }
 
-void rtl8180_irq_disable(struct net_device *dev)
+static void rtl8180_irq_disable(struct net_device *dev)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 
@@ -705,8 +705,8 @@
 		dev_kfree_skb_any(priv->rx_skb);
 }
 
-short alloc_tx_desc_ring(struct net_device *dev, int bufsize, int count,
-			 int addr)
+static short alloc_tx_desc_ring(struct net_device *dev, int bufsize, int count,
+				int addr)
 {
 	int i;
 	u32 *desc;
@@ -830,7 +830,7 @@
 	return 0;
 }
 
-void free_tx_desc_rings(struct net_device *dev)
+static void free_tx_desc_rings(struct net_device *dev)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	struct pci_dev *pdev = priv->pdev;
@@ -866,7 +866,7 @@
 	buffer_free(dev, &(priv->txbeaconbufs), priv->txbuffsize, 1);
 }
 
-void free_rx_desc_ring(struct net_device *dev)
+static void free_rx_desc_ring(struct net_device *dev)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	struct pci_dev *pdev = priv->pdev;
@@ -878,7 +878,7 @@
 	buffer_free(dev, &(priv->rxbuffer), priv->rxbuffersize, 0);
 }
 
-short alloc_rx_desc_ring(struct net_device *dev, u16 bufsize, int count)
+static short alloc_rx_desc_ring(struct net_device *dev, u16 bufsize, int count)
 {
 	int i;
 	u32 *desc;
@@ -1092,7 +1092,7 @@
 /*
  * For Netgear case, they want good-looking signal strength.
  */
-long NetgearSignalStrengthTranslate(long LastSS, long CurrSS)
+static long NetgearSignalStrengthTranslate(long LastSS, long CurrSS)
 {
 	long RetSS;
 
@@ -1128,7 +1128,7 @@
 /*
  * Translate 0-100 signal strength index into dBm.
  */
-long TranslateToDbm8185(u8 SignalStrengthIndex)
+static long TranslateToDbm8185(u8 SignalStrengthIndex)
 {
 	long SignalPower;
 
@@ -1145,8 +1145,8 @@
  * No dramatic adjustion is apply because dynamic mechanism need some degree
  * of correctness. Ported from 8187B.
  */
-void PerformUndecoratedSignalSmoothing8185(struct r8180_priv *priv,
-					   bool bCckRate)
+static void PerformUndecoratedSignalSmoothing8185(struct r8180_priv *priv,
+						  bool bCckRate)
 {
 	/* Determin the current packet is CCK rate. */
 	priv->bCurCCKPkt = bCckRate;
@@ -1170,7 +1170,7 @@
 /*
  * This is rough RX isr handling routine
  */
-void rtl8180_rx(struct net_device *dev)
+static void rtl8180_rx(struct net_device *dev)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	struct sk_buff *tmp_skb;
@@ -1496,7 +1496,7 @@
 }
 
 
-void rtl8180_dma_kick(struct net_device *dev, int priority)
+static void rtl8180_dma_kick(struct net_device *dev, int priority)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 
@@ -1508,7 +1508,7 @@
 	force_pci_posting(dev);
 }
 
-void rtl8180_data_hard_stop(struct net_device *dev)
+static void rtl8180_data_hard_stop(struct net_device *dev)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 
@@ -1518,7 +1518,7 @@
 	rtl8180_set_mode(dev, EPROM_CMD_NORMAL);
 }
 
-void rtl8180_data_hard_resume(struct net_device *dev)
+static void rtl8180_data_hard_resume(struct net_device *dev)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 
@@ -1532,8 +1532,9 @@
  * This function TX data frames when the ieee80211 stack requires this.
  * It checks also if we need to stop the ieee tx queue, eventually do it
  */
-void rtl8180_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int
-rate) {
+static void rtl8180_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
+				   int rate)
+{
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	int mode;
 	struct ieee80211_hdr_3addr *h = (struct ieee80211_hdr_3addr *) skb->data;
@@ -1584,7 +1585,7 @@
  * might use a different lock than tx_lock (for example mgmt_tx_lock)
  */
 /* these function may loop if invoked with 0 descriptors or 0 len buffer */
-int rtl8180_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static int rtl8180_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	unsigned long flags;
@@ -1660,7 +1661,7 @@
 	return duration;
 }
 
-void rtl8180_prepare_beacon(struct net_device *dev)
+static void rtl8180_prepare_beacon(struct net_device *dev)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	struct sk_buff *skb;
@@ -1704,7 +1705,7 @@
 	u16			RtsDur = 0;
 	u16			ThisFrameTime = 0;
 	u16			TxDescDuration = 0;
-	u8			ownbit_flag = false;
+	bool			ownbit_flag = false;
 
 	switch (priority) {
 	case MANAGE_PRIORITY:
@@ -1953,7 +1954,7 @@
 
 void rtl8180_irq_rx_tasklet(struct r8180_priv *priv);
 
-void rtl8180_link_change(struct net_device *dev)
+static void rtl8180_link_change(struct net_device *dev)
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
 	u16 beacon_interval;
@@ -1976,7 +1977,7 @@
 	rtl8180_set_chan(dev, priv->chan);
 }
 
-void rtl8180_rq_tx_ack(struct net_device *dev)
+static void rtl8180_rq_tx_ack(struct net_device *dev)
 {
 
 	struct r8180_priv *priv = ieee80211_priv(dev);
@@ -1985,7 +1986,7 @@
 	priv->ack_tx_to_ieee = 1;
 }
 
-short rtl8180_is_tx_queue_empty(struct net_device *dev)
+static short rtl8180_is_tx_queue_empty(struct net_device *dev)
 {
 
 	struct r8180_priv *priv = ieee80211_priv(dev);
@@ -2023,7 +2024,7 @@
 	return 1;
 }
 
-void rtl8180_hw_wakeup(struct net_device *dev)
+static void rtl8180_hw_wakeup(struct net_device *dev)
 {
 	unsigned long flags;
 	struct r8180_priv *priv = ieee80211_priv(dev);
@@ -2035,7 +2036,7 @@
 	spin_unlock_irqrestore(&priv->ps_lock, flags);
 }
 
-void rtl8180_hw_sleep_down(struct net_device *dev)
+static void rtl8180_hw_sleep_down(struct net_device *dev)
 {
 	unsigned long flags;
 	struct r8180_priv *priv = ieee80211_priv(dev);
@@ -2046,7 +2047,7 @@
 	spin_unlock_irqrestore(&priv->ps_lock, flags);
 }
 
-void rtl8180_hw_sleep(struct net_device *dev, u32 th, u32 tl)
+static void rtl8180_hw_sleep(struct net_device *dev, u32 th, u32 tl)
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
 	u32 rb = jiffies;
@@ -2093,7 +2094,7 @@
 	spin_unlock_irqrestore(&priv->ps_lock, flags);
 }
 
-void rtl8180_wmm_param_update(struct work_struct *work)
+static void rtl8180_wmm_param_update(struct work_struct *work)
 {
 	struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, wmm_param_update_wq);
 	struct net_device *dev = ieee->dev;
@@ -2195,7 +2196,7 @@
 void rtl8180_sw_antenna_wq(struct work_struct *work);
 void rtl8180_watch_dog(struct net_device *dev);
 
-void watch_dog_adaptive(unsigned long data)
+static void watch_dog_adaptive(unsigned long data)
 {
 	struct r8180_priv *priv = ieee80211_priv((struct net_device *)data);
 
@@ -2213,7 +2214,7 @@
 		TxPwrTracking87SE((struct net_device *)data);
 
 	/* Perform DIG immediately. */
-	if (CheckDig((struct net_device *)data) == true)
+	if (CheckDig((struct net_device *)data))
 		queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->hw_dig_wq);
 	rtl8180_watch_dog((struct net_device *)data);
 
@@ -2271,7 +2272,7 @@
 		}
 	case COUNTRY_CODE_GLOBAL_DOMAIN:
 		{
-			GET_DOT11D_INFO(ieee)->bEnabled = 0;
+			GET_DOT11D_INFO(ieee)->bEnabled = false;
 			Dot11d_Reset(ieee);
 			ieee->bGlobalDomain = true;
 			break;
@@ -2429,7 +2430,7 @@
 	init_timer(&priv->SwAntennaDiversityTimer);
 	priv->SwAntennaDiversityTimer.data = (unsigned long)dev;
 	priv->SwAntennaDiversityTimer.function = (void *)SwAntennaDiversityTimerCallback;
-	priv->bDigMechanism = 1;
+	priv->bDigMechanism = true;
 	priv->InitialGain = 6;
 	priv->bXtalCalibration = false;
 	priv->XtalCal_Xin = 0;
@@ -2548,7 +2549,7 @@
 				(priv->EarlyRxThreshold == 7 ?
 					 RCR_ONLYERLPKT : 0);
 
-	priv->IntrMask		= IMR_TMGDOK | IMR_TBDER | IMR_THPDER |
+	priv->IntrMask		= IMR_TMGDOK | IMR_TBDER |
 				  IMR_THPDER | IMR_THPDOK |
 				  IMR_TVODER | IMR_TVODOK |
 				  IMR_TVIDER | IMR_TVIDOK |
@@ -2757,7 +2758,7 @@
 	mdelay(1);
 }
 
-void rtl8185_write_phy(struct net_device *dev, u8 adr, u32 data)
+static void rtl8185_write_phy(struct net_device *dev, u8 adr, u32 data)
 {
 	u32 phyw;
 
@@ -2969,7 +2970,7 @@
 	priv->ieee80211->NumRxBcnInPeriod = 0;
 }
 
-int _rtl8180_up(struct net_device *dev)
+static int _rtl8180_up(struct net_device *dev)
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
 
@@ -2991,7 +2992,7 @@
 	return 0;
 }
 
-int rtl8180_open(struct net_device *dev)
+static int rtl8180_open(struct net_device *dev)
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
 	int ret;
@@ -3012,7 +3013,7 @@
 	return _rtl8180_up(dev);
 }
 
-int rtl8180_close(struct net_device *dev)
+static int rtl8180_close(struct net_device *dev)
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
 	int ret;
@@ -3065,7 +3066,7 @@
 	up(&priv->wx_sem);
 }
 
-void rtl8180_restart(struct net_device *dev)
+static void rtl8180_restart(struct net_device *dev)
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
 
@@ -3106,7 +3107,7 @@
 	priv->promisc = promisc;
 }
 
-int r8180_set_mac_adr(struct net_device *dev, void *mac)
+static int r8180_set_mac_adr(struct net_device *dev, void *mac)
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
 	struct sockaddr *addr = mac;
@@ -3129,7 +3130,7 @@
 }
 
 /* based on ipw2200 driver */
-int rtl8180_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int rtl8180_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	struct iwreq *wrq = (struct iwreq *) rq;
@@ -3251,7 +3252,7 @@
 	return 0;
 fail1:
 	if (dev->mem_start != (unsigned long)NULL) {
-		iounmap((void *)dev->mem_start);
+		iounmap((void __iomem *)dev->mem_start);
 		release_mem_region(pci_resource_start(pdev, 1),
 				   pci_resource_len(pdev, 1));
 	}
@@ -3268,7 +3269,6 @@
 	pci_disable_device(pdev);
 
 	DMESG("wlan driver load failed\n");
-	pci_set_drvdata(pdev, NULL);
 	return ret;
 }
 
@@ -3298,7 +3298,7 @@
 		free_tx_desc_rings(dev);
 
 		if (dev->mem_start != (unsigned long)NULL) {
-			iounmap((void *)dev->mem_start);
+			iounmap((void __iomem *)dev->mem_start);
 			release_mem_region(pci_resource_start(pdev, 1),
 					   pci_resource_len(pdev, 1));
 		}
@@ -3369,7 +3369,7 @@
 	DMESG("Exiting");
 }
 
-void rtl8180_try_wake_queue(struct net_device *dev, int pri)
+static void rtl8180_try_wake_queue(struct net_device *dev, int pri)
 {
 	unsigned long flags;
 	short enough_desc;
@@ -3383,7 +3383,7 @@
 		ieee80211_rtl_wake_queue(priv->ieee80211);
 }
 
-void rtl8180_tx_isr(struct net_device *dev, int pri, short error)
+static void rtl8180_tx_isr(struct net_device *dev, int pri, short error)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	u32 *tail; /* tail virtual addr */
diff --git a/drivers/staging/rtl8187se/r8180_dm.c b/drivers/staging/rtl8187se/r8180_dm.c
index b8f2ba0..2ccd2cb 100644
--- a/drivers/staging/rtl8187se/r8180_dm.c
+++ b/drivers/staging/rtl8187se/r8180_dm.c
@@ -10,10 +10,10 @@
 	struct r8180_priv *priv = ieee80211_priv(dev);
 	struct ieee80211_device *ieee = priv->ieee80211;
 
-	if(!priv->bRegHighPowerMechanism)
+	if (!priv->bRegHighPowerMechanism)
 		return false;
 
-	if(ieee->state == IEEE80211_LINKED_SCANNING)
+	if (ieee->state == IEEE80211_LINKED_SCANNING)
 		return false;
 
 	return true;
@@ -30,7 +30,7 @@
  *		and they are related to OFDM and MAC registers.
  *		So, we don't want to update it so frequently in per-Rx packet base.
  */
-void DoTxHighPower(struct net_device *dev)
+static void DoTxHighPower(struct net_device *dev)
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
 	u16			HiPwrUpperTh = 0;
@@ -57,15 +57,15 @@
 		/* Stevenl suggested that degrade 8dbm in high power sate. 2007-12-04 Isaiah */
 
 		priv->bToUpdateTxPwr = true;
-		u1bTmp= read_nic_byte(dev, CCK_TXAGC);
+		u1bTmp = read_nic_byte(dev, CCK_TXAGC);
 
 		/* If it never enter High Power. */
 		if (CckTxPwrIdx == u1bTmp) {
-			u1bTmp = (u1bTmp > 16) ? (u1bTmp -16): 0;  /* 8dbm */
+			u1bTmp = (u1bTmp > 16) ? (u1bTmp - 16) : 0;  /* 8dbm */
 			write_nic_byte(dev, CCK_TXAGC, u1bTmp);
 
-			u1bTmp= read_nic_byte(dev, OFDM_TXAGC);
-			u1bTmp = (u1bTmp > 16) ? (u1bTmp -16): 0;  /* 8dbm */
+			u1bTmp = read_nic_byte(dev, OFDM_TXAGC);
+			u1bTmp = (u1bTmp > 16) ? (u1bTmp - 16) : 0;  /* 8dbm */
 			write_nic_byte(dev, OFDM_TXAGC, u1bTmp);
 		}
 
@@ -74,12 +74,12 @@
 		if (priv->bToUpdateTxPwr) {
 			priv->bToUpdateTxPwr = false;
 			/* SD3 required. */
-			u1bTmp= read_nic_byte(dev, CCK_TXAGC);
+			u1bTmp = read_nic_byte(dev, CCK_TXAGC);
 			if (u1bTmp < CckTxPwrIdx) {
 				write_nic_byte(dev, CCK_TXAGC, CckTxPwrIdx);
 			}
 
-			u1bTmp= read_nic_byte(dev, OFDM_TXAGC);
+			u1bTmp = read_nic_byte(dev, OFDM_TXAGC);
 			if (u1bTmp < OfdmTxPwrIdx) {
 				write_nic_byte(dev, OFDM_TXAGC, OfdmTxPwrIdx);
 			}
@@ -97,7 +97,7 @@
 void rtl8180_tx_pw_wq(struct work_struct *work)
 {
 	struct delayed_work *dwork = to_delayed_work(work);
-	struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,tx_pw_wq);
+	struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, tx_pw_wq);
 	struct net_device *dev = ieee->dev;
 
 	DoTxHighPower(dev);
@@ -125,7 +125,7 @@
 /*
  *	Implementation of DIG for Zebra and Zebra2.
  */
-void DIG_Zebra(struct net_device *dev)
+static void DIG_Zebra(struct net_device *dev)
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
 	u16			CCKFalseAlarm, OFDMFalseAlarm;
@@ -149,11 +149,11 @@
 
 #if 1 /* lzm reserved 080826 */
 	AwakePeriodIn2Sec = (2000 - priv->DozePeriodInPast2Sec);
-	priv ->DozePeriodInPast2Sec = 0;
+	priv->DozePeriodInPast2Sec = 0;
 
 	if (AwakePeriodIn2Sec) {
-		OfdmFA1 = (u16)((OfdmFA1 * AwakePeriodIn2Sec) / 2000) ;
-		OfdmFA2 = (u16)((OfdmFA2 * AwakePeriodIn2Sec) / 2000) ;
+		OfdmFA1 = (u16)((OfdmFA1 * AwakePeriodIn2Sec) / 2000);
+		OfdmFA2 = (u16)((OfdmFA2 * AwakePeriodIn2Sec) / 2000);
 	} else {
 		;
 	}
@@ -202,7 +202,7 @@
 /*
  *	Dispatch DIG implementation according to RF.
  */
-void DynamicInitGain(struct net_device *dev)
+static void DynamicInitGain(struct net_device *dev)
 {
 	DIG_Zebra(dev);
 }
@@ -210,7 +210,7 @@
 void rtl8180_hw_dig_wq(struct work_struct *work)
 {
 	struct delayed_work *dwork = to_delayed_work(work);
-	struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,hw_dig_wq);
+	struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, hw_dig_wq);
 	struct net_device *dev = ieee->dev;
 	struct r8180_priv *priv = ieee80211_priv(dev);
 
@@ -223,7 +223,7 @@
 
 }
 
-int IncludedInSupportedRates(struct r8180_priv *priv, u8 TxRate)
+static int IncludedInSupportedRates(struct r8180_priv *priv, u8 TxRate)
 {
 	u8 rate_len;
 	u8 rate_ex_len;
@@ -234,7 +234,7 @@
 
 	rate_len = priv->ieee80211->current_network.rates_len;
 	rate_ex_len = priv->ieee80211->current_network.rates_ex_len;
-	for (idx=0; idx < rate_len; idx++) {
+	for (idx = 0; idx < rate_len; idx++) {
 		if ((priv->ieee80211->current_network.rates[idx] & RateMask) == NaiveTxRate) {
 			Found = 1;
 			goto found_rate;
@@ -247,7 +247,7 @@
 		}
 	}
 	return Found;
-	found_rate:
+found_rate:
 	return Found;
 }
 
@@ -255,7 +255,7 @@
  *	Get the Tx rate one degree up form the input rate in the supported rates.
  *	Return the upgrade rate if it is successed, otherwise return the input rate.
  */
-u8 GetUpgradeTxRate(struct net_device *dev, u8 rate)
+static u8 GetUpgradeTxRate(struct net_device *dev, u8 rate)
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
 	u8                      UpRate;
@@ -315,7 +315,7 @@
  *	Return the degrade rate if it is successed, otherwise return the input rate.
  */
 
-u8 GetDegradeTxRate(struct net_device *dev, u8 rate)
+static u8 GetDegradeTxRate(struct net_device *dev, u8 rate)
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
 	u8                      DownRate;
@@ -375,7 +375,7 @@
  *      CCK rate.
  */
 
-bool MgntIsCckRate(u16 rate)
+static bool MgntIsCckRate(u16 rate)
 {
 	bool bReturn = false;
 
@@ -397,7 +397,7 @@
 
 	tmpu1Byte = read_nic_byte(dev, EN_LPF_CAL);
 	CurrentThermal = (tmpu1Byte & 0xf0) >> 4; /*[ 7:4]: thermal meter indication. */
-	CurrentThermal = (CurrentThermal > 0x0c) ? 0x0c:CurrentThermal;/* lzm add 080826 */
+	CurrentThermal = (CurrentThermal > 0x0c) ? 0x0c : CurrentThermal;/* lzm add 080826 */
 
 	if (CurrentThermal != priv->ThermalMeter) {
 		/* Update Tx Power level on each channel. */
@@ -435,7 +435,7 @@
 	}
 	priv->ThermalMeter = CurrentThermal;
 }
-void StaRateAdaptive87SE(struct net_device *dev)
+static void StaRateAdaptive87SE(struct net_device *dev)
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	unsigned long	CurrTxokCnt;
@@ -513,7 +513,7 @@
 	 */
 
 	/*
- 	 *  11Mbps or 36Mbps
+	 * 11Mbps or 36Mbps
 	 * Check more times in these rate(key rates).
 	 */
 	if (priv->CurrentOperaRate == 22 || priv->CurrentOperaRate == 72)
@@ -542,7 +542,7 @@
 		}
 	} else if (CurrSignalStrength > -47 && (CurrRetryRate < 50)) {
 		/*
- 		 * 2For High Power
+		 * 2For High Power
 		 *
 		 * Return to highest data rate, if signal strength is good enough.
 		 * SignalStrength threshold(-50dbm) is for RTL8186.
@@ -577,8 +577,7 @@
 
 		if (bTryDown && (CurrSignalStrength < -75)) /* cable link */
 			priv->TryDownCountLowData += TryDownTh;
-	}
-	else if (priv->CurrentOperaRate == 96) {
+	} else if (priv->CurrentOperaRate == 96) {
 		/* 2For 48Mbps */
 		/* Air Link */
 		if (((CurrRetryRate > 48) && (priv->LastRetryRate > 47))) {
@@ -593,7 +592,7 @@
 			bTryUp = true;
 		}
 
-		if (bTryDown && (CurrSignalStrength < -75)){
+		if (bTryDown && (CurrSignalStrength < -75)) {
 			priv->TryDownCountLowData += TryDownTh;
 		}
 	} else if (priv->CurrentOperaRate == 72) {
@@ -618,7 +617,7 @@
 			bTryDown = true;
 		} else if (((CurrRetryRate > 33) && (priv->LastRetryRate > 32)) && (CurrSignalStrength > -82)) { /* Cable Link */
 			bTryDown = true;
-		} else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2 )) {
+		} else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) {
 			bTryDown = true;
 			priv->TryDownCountLowData += TryDownTh;
 		} else if ((CurrRetryRate < 20) && (priv->LastRetryRate < 21)) { /* TO DO: need to consider (RSSI) */
@@ -641,8 +640,7 @@
 		/* 2For 11Mbps */
 		if (CurrRetryRate > 95) {
 			bTryDown = true;
-		}
-		else if ((CurrRetryRate < 29) && (priv->LastRetryRate < 30)) { /*TO DO: need to consider (RSSI) */
+		} else if ((CurrRetryRate < 29) && (priv->LastRetryRate < 30)) { /*TO DO: need to consider (RSSI) */
 			bTryUp = true;
 		}
 	} else if (priv->CurrentOperaRate == 11) {
@@ -667,12 +665,12 @@
 	}
 
 	if (bTryUp && bTryDown)
-	printk("StaRateAdaptive87B(): Tx Rate tried upping and downing simultaneously!\n");
+		printk("StaRateAdaptive87B(): Tx Rate tried upping and downing simultaneously!\n");
 
 	/* 1 Test Upgrading Tx Rate
 	 * Sometimes the cause of the low throughput (high retry rate) is the compatibility between the AP and NIC.
 	 * To test if the upper rate may cause lower retry rate, this mechanism randomly occurs to test upgrading tx rate.
-	 */ 
+	 */
 	if (!bTryUp && !bTryDown && (priv->TryupingCount == 0) && (priv->TryDownCountLowData == 0)
 		&& priv->CurrentOperaRate != priv->ieee80211->current_network.HighestOperaRate && priv->FailTxRateCount < 2) {
 		if (jiffies % (CurrRetryRate + 101) == 0) {
@@ -702,7 +700,7 @@
 			if (priv->CurrentOperaRate == 22)
 				bUpdateInitialGain = true;
 
-			/* 
+			/*
 			 * The difference in throughput between 48Mbps and 36Mbps is 8M.
 			 * So, we must be careful in this rate scale. Isaiah 2008-02-15.
 			 */
@@ -718,7 +716,7 @@
 			if (priv->CurrentOperaRate == 36) {
 				priv->bUpdateARFR = true;
 				write_nic_word(dev, ARFR, 0x0F8F); /* bypass 12/9/6 */
-			} else if(priv->bUpdateARFR) {
+			} else if (priv->bUpdateARFR) {
 				priv->bUpdateARFR = false;
 				write_nic_word(dev, ARFR, 0x0FFF); /* set 1M ~ 54Mbps. */
 			}
@@ -732,7 +730,7 @@
 		}
 	} else {
 		if (priv->TryupingCount > 0)
-			priv->TryupingCount --;
+			priv->TryupingCount--;
 	}
 
 	if (bTryDown) {
@@ -757,7 +755,7 @@
 			priv->CurrentOperaRate = GetDegradeTxRate(dev, priv->CurrentOperaRate);
 
 			/* Reduce chariot training time at weak signal strength situation. SD3 ED demand. */
-			if ((CurrSignalStrength < -80) && (priv->CurrentOperaRate > 72 )) {
+			if ((CurrSignalStrength < -80) && (priv->CurrentOperaRate > 72)) {
 				priv->CurrentOperaRate = 72;
 			}
 
@@ -781,8 +779,8 @@
 			priv->TryDownCountLowData--;
 	}
 
-	/* 
- 	 * Keep the Tx fail rate count to equal to 0x15 at most. 
+	/*
+	 * Keep the Tx fail rate count to equal to 0x15 at most.
 	 * Reduce the fail count at least to 10 sec if tx rate is tending stable.
 	 */
 	if (priv->FailTxRateCount >= 0x15 ||
@@ -803,14 +801,14 @@
 		if (u1bCck == CckTxPwrIdx) {
 			if (u1bOfdm != (OfdmTxPwrIdx + 2)) {
 			priv->bEnhanceTxPwr = true;
-			u1bOfdm = ((u1bOfdm + 2) > 35) ? 35: (u1bOfdm + 2);
+			u1bOfdm = ((u1bOfdm + 2) > 35) ? 35 : (u1bOfdm + 2);
 			write_nic_byte(dev, OFDM_TXAGC, u1bOfdm);
 			}
 		} else if (u1bCck < CckTxPwrIdx) {
 		/* case 2: enter high power */
 			if (!priv->bEnhanceTxPwr) {
 				priv->bEnhanceTxPwr = true;
-				u1bOfdm = ((u1bOfdm + 2) > 35) ? 35: (u1bOfdm + 2);
+				u1bOfdm = ((u1bOfdm + 2) > 35) ? 35 : (u1bOfdm + 2);
 				write_nic_byte(dev, OFDM_TXAGC, u1bOfdm);
 			}
 		}
@@ -826,7 +824,7 @@
 		/* case 2: enter high power */
 		else if (u1bCck < CckTxPwrIdx) {
 			priv->bEnhanceTxPwr = false;
-			u1bOfdm = ((u1bOfdm - 2) > 0) ? (u1bOfdm - 2): 0;
+			u1bOfdm = ((u1bOfdm - 2) > 0) ? (u1bOfdm - 2) : 0;
 			write_nic_byte(dev, OFDM_TXAGC, u1bOfdm);
 		}
 	}
@@ -851,7 +849,7 @@
 				else
 					priv->InitialGain--;
 
-				printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n",priv->InitialGain, priv->CurrentOperaRate);
+				printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n", priv->InitialGain, priv->CurrentOperaRate);
 				UpdateInitialGain(dev);
 			}
 		} else { /* OFDM */
@@ -859,7 +857,7 @@
 				priv->InitialGainBackUp = priv->InitialGain;
 
 				priv->InitialGain++;
-				printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n",priv->InitialGain, priv->CurrentOperaRate);
+				printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n", priv->InitialGain, priv->CurrentOperaRate);
 				UpdateInitialGain(dev);
 			}
 		}
@@ -904,7 +902,7 @@
 	} else { /* Initialization case. */
 		priv->AdRxSignalStrength = SignalStrength;
 	}
-	
+
 	if (priv->LastRxPktAntenna) /* Main antenna. */
 		priv->AdMainAntennaRxOkCnt++;
 	else	 /* Aux antenna. */
@@ -943,7 +941,7 @@
 		break;
 	}
 
-	if(bAntennaSwitched)
+	if (bAntennaSwitched)
 		priv->CurrAntennaIndex = u1bAntennaIndex;
 
 	return bAntennaSwitched;
@@ -1000,8 +998,8 @@
 		priv->AdRxSsThreshold = (priv->AdRxSignalStrength + priv->AdRxSsBeforeSwitched) / 2;
 
 		priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ?
-					priv->AdMaxRxSsThreshold: priv->AdRxSsThreshold;
-		if(priv->AdRxSignalStrength < priv->AdRxSsBeforeSwitched) {
+					priv->AdMaxRxSsThreshold : priv->AdRxSsThreshold;
+		if (priv->AdRxSignalStrength < priv->AdRxSsBeforeSwitched) {
 		/* Rx signal strength is not improved after we swtiched antenna. => Swich back. */
 			/* Increase Antenna Diversity checking period due to bad decision. */
 			priv->AdCheckPeriod *= 2;
@@ -1083,7 +1081,7 @@
 
 					priv->AdRxSsThreshold = (priv->AdRxSsThreshold + priv->AdRxSignalStrength) / 2;
 					priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ?
-								priv->AdMaxRxSsThreshold: priv->AdRxSsThreshold;/* +by amy 080312 */
+								priv->AdMaxRxSsThreshold : priv->AdRxSsThreshold;/* +by amy 080312 */
 				}
 
 				/* Reduce Antenna Diversity checking period if possible. */
diff --git a/drivers/staging/rtl8187se/r8180_rtl8225z2.c b/drivers/staging/rtl8187se/r8180_rtl8225z2.c
index 9ae96b7..7c9a8bf 100644
--- a/drivers/staging/rtl8187se/r8180_rtl8225z2.c
+++ b/drivers/staging/rtl8187se/r8180_rtl8225z2.c
@@ -136,7 +136,7 @@
 
 };
 
-void rtl8225z2_set_gain(struct net_device *dev, short gain)
+static void rtl8225z2_set_gain(struct net_device *dev, short gain)
 {
 	const u8 *rtl8225_gain;
 	struct r8180_priv *priv = ieee80211_priv(dev);
@@ -279,8 +279,8 @@
  * Map dBm into Tx power index according to current HW model, for example,
  * RF and PA, and current wireless mode.
  */
-s8 DbmToTxPwrIdx(struct r8180_priv *priv, WIRELESS_MODE WirelessMode,
-		 s32 PowerInDbm)
+static s8 DbmToTxPwrIdx(struct r8180_priv *priv, WIRELESS_MODE WirelessMode,
+			s32 PowerInDbm)
 {
 	bool bUseDefault = true;
 	s8 TxPwrIdx = 0;
diff --git a/drivers/staging/rtl8187se/r8180_wx.c b/drivers/staging/rtl8187se/r8180_wx.c
index dab7875..4e01653 100644
--- a/drivers/staging/rtl8187se/r8180_wx.c
+++ b/drivers/staging/rtl8187se/r8180_wx.c
@@ -50,8 +50,9 @@
 }
 
 
-int r8180_wx_set_key(struct net_device *dev, struct iw_request_info *info,
-		     union iwreq_data *wrqu, char *key)
+static int r8180_wx_set_key(struct net_device *dev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu, char *key)
 {
 	struct r8180_priv *priv = ieee80211_priv(dev);
 	struct iw_point *erq = &(wrqu->encoding);
@@ -1146,12 +1147,12 @@
 	if (priv->ieee80211->bHwRadioOff)
 		return 0;
 
-		down(&priv->wx_sem);
+	down(&priv->wx_sem);
 #if 1
-		ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, wrqu->data.length);
+	ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, wrqu->data.length);
 #endif
-		up(&priv->wx_sem);
-		return ret;
+	up(&priv->wx_sem);
+	return ret;
 
 
 }
diff --git a/drivers/staging/rtl8187se/r8185b_init.c b/drivers/staging/rtl8187se/r8185b_init.c
index 978dc5f..dc52a3e 100644
--- a/drivers/staging/rtl8187se/r8185b_init.c
+++ b/drivers/staging/rtl8187se/r8185b_init.c
@@ -30,10 +30,13 @@
 #define TC_3W_POLL_MAX_TRY_CNT 5
 
 static u8 MAC_REG_TABLE[][2] =	{
-	/*PAGA 0:	*/
-	/* 0x34(BRSR), 0xBE(RATE_FALLBACK_CTL), 0x1E0(ARFR) would set in HwConfigureRTL8185() */
-	/* 0x272(RFSW_CTRL), 0x1CE(AESMSK_QC) set in InitializeAdapter8185(). */
-	/* 0x1F0~0x1F8  set in MacConfig_85BASIC() */
+	/*
+	 * PAGE 0:
+	 * 0x34(BRSR), 0xBE(RATE_FALLBACK_CTL), 0x1E0(ARFR) would set in
+	 * HwConfigureRTL8185()
+	 * 0x272(RFSW_CTRL), 0x1CE(AESMSK_QC) set in InitializeAdapter8185().
+	 * 0x1F0~0x1F8  set in MacConfig_85BASIC()
+	 */
 	{0x08, 0xae}, {0x0a, 0x72}, {0x5b, 0x42},
 	{0x84, 0x88}, {0x85, 0x24}, {0x88, 0x54}, {0x8b, 0xb8}, {0x8c, 0x03},
 	{0x8d, 0x40}, {0x8e, 0x00}, {0x8f, 0x00}, {0x5b, 0x18}, {0x91, 0x03},
@@ -44,15 +47,20 @@
 	{0xfa, 0x00}, {0xfb, 0x00}, {0xfc, 0x96}, {0xfd, 0xa4}, {0xfe, 0x00},
 	{0xff, 0x00},
 
-	/*PAGE 1: */
-	/* For Flextronics system Logo PCIHCT failure: */
-	/* 0x1C4~0x1CD set no-zero value to avoid PCI configuration space 0x45[7]=1 */
+	/*
+	 * PAGE 1:
+	 * For Flextronics system Logo PCIHCT failure:
+	 * 0x1C4~0x1CD set no-zero value to avoid PCI configuration
+	 * space 0x45[7]=1
+	 */
 	{0x5e, 0x01},
 	{0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x04}, {0x5b, 0x00}, {0x60, 0x24},
 	{0x61, 0x97}, {0x62, 0xF0}, {0x63, 0x09}, {0x80, 0x0F}, {0x81, 0xFF},
 	{0x82, 0xFF}, {0x83, 0x03},
-	{0xC4, 0x22}, {0xC5, 0x22}, {0xC6, 0x22}, {0xC7, 0x22}, {0xC8, 0x22}, /* lzm add 080826 */
-	{0xC9, 0x22}, {0xCA, 0x22}, {0xCB, 0x22}, {0xCC, 0x22}, {0xCD, 0x22}, /* lzm add 080826 */
+	/* lzm add 080826 */
+	{0xC4, 0x22}, {0xC5, 0x22}, {0xC6, 0x22}, {0xC7, 0x22}, {0xC8, 0x22},
+	/* lzm add 080826 */
+	{0xC9, 0x22}, {0xCA, 0x22}, {0xCB, 0x22}, {0xCC, 0x22}, {0xCD, 0x22},
 	{0xe2, 0x00},
 
 
@@ -66,21 +74,24 @@
 	{0x8f, 0x3f}, {0xc4, 0xff}, {0xc5, 0xff}, {0xc6, 0xff}, {0xc7, 0xff},
 	{0xc8, 0x00}, {0xc9, 0x00}, {0xca, 0x80}, {0xcb, 0x00},
 
-	/* PAGA 0: */
+	/* PAGE 0: */
 	{0x5e, 0x00}, {0x9f, 0x03}
 	};
 
 
 static u8  ZEBRA_AGC[] = {
 	0,
-	0x7E, 0x7E, 0x7E, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72,
-	0x71, 0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62,
-	0x48, 0x47, 0x46, 0x45, 0x44, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x08, 0x07,
-	0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x15, 0x16,
-	0x17, 0x17, 0x18, 0x18, 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e,
-	0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x24,
-	0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F
+	0x7E, 0x7E, 0x7E, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76,
+	0x75, 0x74, 0x73, 0x72, 0x71, 0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A,
+	0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x48, 0x47, 0x46, 0x45,
+	0x44, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x08, 0x07,
+	0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+	0x0f, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x15, 0x16, 0x17, 0x17, 0x18, 0x18,
+	0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e,
+	0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22,
+	0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
+	0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F
 	};
 
 static u32 ZEBRA_RF_RX_GAIN_TABLE[] = {
@@ -123,19 +134,27 @@
 static void PlatformIOWrite1Byte(struct net_device *dev, u32 offset, u8 data)
 {
 	write_nic_byte(dev, offset, data);
-	read_nic_byte(dev, offset); /* To make sure write operation is completed, 2005.11.09, by rcnjko. */
+	/*
+	 * To make sure write operation is completed,
+	 * 2005.11.09, by rcnjko.
+	 */
+	read_nic_byte(dev, offset);
 }
 
 static void PlatformIOWrite2Byte(struct net_device *dev, u32 offset, u16 data)
 {
 	write_nic_word(dev, offset, data);
-	read_nic_word(dev, offset); /* To make sure write operation is completed, 2005.11.09, by rcnjko. */
+	/*
+	 * To make sure write operation is completed,
+	 *  2005.11.09, by rcnjko.
+	 */
+	read_nic_word(dev, offset);
 }
 
 static void PlatformIOWrite4Byte(struct net_device *dev, u32 offset, u32 data)
 {
 	if (offset == PhyAddr) {
-	/* For Base Band configuration. */
+		/* For Base Band configuration. */
 		unsigned char	cmdByte;
 		unsigned long	dataBytes;
 		unsigned char	idx;
@@ -146,16 +165,17 @@
 
 		/*
 		 *	071010, rcnjko:
-		 *	The critical section is only BB read/write race condition.
-		 *	Assumption:
-		 *	1. We assume NO one will access BB at DIRQL, otherwise, system will crash for
+		 *	The critical section is only BB read/write race
+		 *	condition. Assumption:
+		 *	1. We assume NO one will access BB at DIRQL, otherwise,
+		 *	system will crash for
 		 *	acquiring the spinlock in such context.
 		 *	2. PlatformIOWrite4Byte() MUST NOT be recursive.
 		 */
 		/* NdisAcquireSpinLock( &(pDevice->IoSpinLock) ); */
 
 		for (idx = 0; idx < 30; idx++) {
-		/* Make sure command bit is clear before access it. */
+			/* Make sure command bit is clear before access it. */
 			u1bTmp = PlatformIORead1Byte(dev, PhyAddr);
 			if ((u1bTmp & BIT7) == 0)
 				break;
@@ -164,14 +184,19 @@
 		}
 
 		for (idx = 0; idx < 3; idx++)
-			PlatformIOWrite1Byte(dev, offset+1+idx, ((u8 *)&dataBytes)[idx]);
+			PlatformIOWrite1Byte(dev, offset+1+idx,
+					     ((u8 *)&dataBytes)[idx]);
 
 		write_nic_byte(dev, offset, cmdByte);
 
 		/* NdisReleaseSpinLock( &(pDevice->IoSpinLock) ); */
 	} else {
 		write_nic_dword(dev, offset, data);
-		read_nic_dword(dev, offset); /* To make sure write operation is completed, 2005.11.09, by rcnjko. */
+		/*
+		 * To make sure write operation is completed, 2005.11.09,
+		 *  by rcnjko.
+		 */
+		read_nic_dword(dev, offset);
 	}
 }
 
@@ -284,9 +309,13 @@
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	bool   bAntennaSwitched = true;
-	u8	ant_diversity_offset = 0x00; /* 0x00 = disabled, 0x80 = enabled */
+	/* 0x00 = disabled, 0x80 = enabled */
+	u8	ant_diversity_offset = 0x00;
 
-	/* printk("SetAntennaConfig87SE(): DefaultAnt(%d), bAntDiversity(%d)\n", DefaultAnt, bAntDiversity); */
+	/*
+	 * printk("SetAntennaConfig87SE(): DefaultAnt(%d), bAntDiversity(%d)\n",
+	 * DefaultAnt, bAntDiversity);
+	 */
 
 	/* Threshold for antenna diversity. */
 	write_phy_cck(dev, 0x0c, 0x09); /* Reg0c : 09 */
@@ -300,22 +329,27 @@
 
 		/* Config CCK RX antenna. */
 		write_phy_cck(dev, 0x11, 0xbb); /* Reg11 : bb */
-		write_phy_cck(dev, 0x01, 0x47|ant_diversity_offset); /* Reg01 : 47 | ant_diversity_offset */
+
+		/* Reg01 : 47 | ant_diversity_offset */
+		write_phy_cck(dev, 0x01, 0x47|ant_diversity_offset);
 
 		/* Config OFDM RX antenna. */
 		write_phy_ofdm(dev, 0x0D, 0x54);	/* Reg0d : 54 */
-		write_phy_ofdm(dev, 0x18, 0x32|ant_diversity_offset);	/* Reg18 : 32 */
+		/* Reg18 : 32 */
+		write_phy_ofdm(dev, 0x18, 0x32|ant_diversity_offset);
 	} else { /* main Antenna */
 		/* Mac register, main antenna */
 		write_nic_byte(dev, ANTSEL, 0x03);
 
 		/* Config CCK RX antenna.	*/
 		write_phy_cck(dev, 0x11, 0x9b); /* Reg11 : 9b */
-		write_phy_cck(dev, 0x01, 0x47|ant_diversity_offset); /* Reg01 : 47 */
+		/* Reg01 : 47 */
+		write_phy_cck(dev, 0x01, 0x47|ant_diversity_offset);
 
 		/* Config OFDM RX antenna. */
 		write_phy_ofdm(dev, 0x0D, 0x5c); /* Reg0d : 5c */
-		write_phy_ofdm(dev, 0x18, 0x32|ant_diversity_offset); /*Reg18 : 32 */
+		/*Reg18 : 32 */
+		write_phy_ofdm(dev, 0x18, 0x32|ant_diversity_offset);
 	}
 	priv->CurrAntennaIndex = DefaultAnt; /* Update default settings. */
 	return	bAntennaSwitched;
@@ -382,18 +416,23 @@
 	RF_WriteReg(dev, 0x05, 0x059b);		mdelay(1);
 	RF_WriteReg(dev, 0x06, 0x0081);		mdelay(1);
 	RF_WriteReg(dev, 0x07, 0x01A0);		mdelay(1);
-/* Don't write RF23/RF24 to make a difference between 87S C cut and D cut. asked by SD3 stevenl. */
+/*
+ * Don't write RF23/RF24 to make a difference between 87S C cut and D cut.
+ * asked by SD3 stevenl.
+ */
 	RF_WriteReg(dev, 0x0a, 0x0001);		mdelay(1);
 	RF_WriteReg(dev, 0x0b, 0x0418);		mdelay(1);
 
 	if (d_cut) {
 		RF_WriteReg(dev, 0x0c, 0x0fbe);		mdelay(1);
 		RF_WriteReg(dev, 0x0d, 0x0008);		mdelay(1);
-		RF_WriteReg(dev, 0x0e, 0x0807);		mdelay(1); /* RX LO buffer */
+		/* RX LO buffer */
+		RF_WriteReg(dev, 0x0e, 0x0807);		mdelay(1);
 	} else {
 		RF_WriteReg(dev, 0x0c, 0x0fbe);		mdelay(1);
 		RF_WriteReg(dev, 0x0d, 0x0008);		mdelay(1);
-		RF_WriteReg(dev, 0x0e, 0x0806);		mdelay(1); /* RX LO buffer */
+		/* RX LO buffer */
+		RF_WriteReg(dev, 0x0e, 0x0806);		mdelay(1);
 	}
 
 	RF_WriteReg(dev, 0x0f, 0x0acc);		mdelay(1);
@@ -408,19 +447,24 @@
 
 	RF_WriteReg(dev, 0x05, 0x0203);		mdelay(1); /* 203, 343 */
 	RF_WriteReg(dev, 0x06, 0x0200);		mdelay(1); /* 400 */
-	RF_WriteReg(dev, 0x00, 0x0137);		mdelay(1); /* switch to reg16-reg30, and HSSI disable 137 */
+	/* switch to reg16-reg30, and HSSI disable 137 */
+	RF_WriteReg(dev, 0x00, 0x0137);		mdelay(1);
 	mdelay(10); /* Deay 10 ms. */		/* 0xfd */
 
-	RF_WriteReg(dev, 0x0d, 0x0008);		mdelay(1); /* Z4 synthesizer loop filter setting, 392 */
+	/* Z4 synthesizer loop filter setting, 392 */
+	RF_WriteReg(dev, 0x0d, 0x0008);		mdelay(1);
 	mdelay(10); /* Deay 10 ms. */		/* 0xfd */
 
-	RF_WriteReg(dev, 0x00, 0x0037);		mdelay(1); /* switch to reg0-reg15, and HSSI disable */
+	/* switch to reg0-reg15, and HSSI disable */
+	RF_WriteReg(dev, 0x00, 0x0037);		mdelay(1);
 	mdelay(10); /* Deay 10 ms. */		/* 0xfd	*/
 
-	RF_WriteReg(dev, 0x04, 0x0160);		mdelay(1); /* CBC on, Tx Rx disable, High gain */
+	/* CBC on, Tx Rx disable, High gain */
+	RF_WriteReg(dev, 0x04, 0x0160);		mdelay(1);
 	mdelay(10); /* Deay 10 ms. */		/* 0xfd	*/
 
-	RF_WriteReg(dev, 0x07, 0x0080);		mdelay(1); /* Z4 setted channel 1 */
+	/* Z4 setted channel 1 */
+	RF_WriteReg(dev, 0x07, 0x0080);		mdelay(1);
 	mdelay(10); /* Deay 10 ms. */		/* 0xfd	*/
 
 	RF_WriteReg(dev, 0x02, 0x088D);		mdelay(1); /* LC calibration */
@@ -428,7 +472,8 @@
 	mdelay(10);  /* Deay 10 ms. */		/* 0xfd	*/
 	mdelay(10);  /* Deay 10 ms. */		/* 0xfd	*/
 
-	RF_WriteReg(dev, 0x00, 0x0137);		mdelay(1); /* switch to reg16-reg30 137, and HSSI disable 137 */
+	/* switch to reg16-reg30 137, and HSSI disable 137 */
+	RF_WriteReg(dev, 0x00, 0x0137);		mdelay(1);
 	mdelay(10); /* Deay 10 ms. */		/* 0xfd	*/
 
 	RF_WriteReg(dev, 0x07, 0x0000);		mdelay(1);
@@ -442,46 +487,58 @@
 	/* For crystal calibration, added by Roger, 2007.12.11. */
 	if (priv->bXtalCalibration) { /* reg 30.	*/
 	 /*
- 	  *  enable crystal calibration.
-	  *		RF Reg[30], (1)Xin:[12:9], Xout:[8:5],  addr[4:0].
-	  *		(2)PA Pwr delay timer[15:14], default: 2.4us, set BIT15=0
-	  *		(3)RF signal on/off when calibration[13], default: on, set BIT13=0.
-	  *		So we should minus 4 BITs offset. 
+	  *	enable crystal calibration.
+	  *	RF Reg[30], (1)Xin:[12:9], Xout:[8:5],  addr[4:0].
+	  *	(2)PA Pwr delay timer[15:14], default: 2.4us,
+	  *	set BIT15=0
+	  *	(3)RF signal on/off when calibration[13], default: on,
+	  *	set BIT13=0.
+	  *	So we should minus 4 BITs offset.
 	  */
-		RF_WriteReg(dev, 0x0f, (priv->XtalCal_Xin<<5) | (priv->XtalCal_Xout<<1) | BIT11 | BIT9); mdelay(1);
+		RF_WriteReg(dev, 0x0f, (priv->XtalCal_Xin<<5) |
+			    (priv->XtalCal_Xout<<1) | BIT11 | BIT9); mdelay(1);
 		printk("ZEBRA_Config_85BASIC_HardCode(): (%02x)\n",
-		      (priv->XtalCal_Xin<<5) | (priv->XtalCal_Xout<<1) | BIT11 | BIT9);
+		      (priv->XtalCal_Xin<<5) | (priv->XtalCal_Xout<<1) |
+		       BIT11 | BIT9);
 	} else {
 		/* using default value. Xin=6, Xout=6.	*/
 		RF_WriteReg(dev, 0x0f, 0x0acc);		mdelay(1);
 	}
-
-	RF_WriteReg(dev, 0x00, 0x00bf);		mdelay(1); /* switch to reg0-reg15, and HSSI enable */
-	RF_WriteReg(dev, 0x0d, 0x08df);		mdelay(1); /* Rx BB start calibration, 00c//+edward */
-	RF_WriteReg(dev, 0x02, 0x004d);		mdelay(1); /* temperature meter off */
+	/* switch to reg0-reg15, and HSSI enable */
+	RF_WriteReg(dev, 0x00, 0x00bf);		mdelay(1);
+	/* Rx BB start calibration, 00c//+edward */
+	RF_WriteReg(dev, 0x0d, 0x08df);		mdelay(1);
+	/* temperature meter off */
+	RF_WriteReg(dev, 0x02, 0x004d);		mdelay(1);
 	RF_WriteReg(dev, 0x04, 0x0975);		mdelay(1); /* Rx mode */
 	mdelay(10);	/* Deay 10 ms.*/	/* 0xfe	*/
 	mdelay(10);	/* Deay 10 ms.*/	/* 0xfe	*/
 	mdelay(10);	/* Deay 10 ms.*/	/* 0xfe	*/
-	RF_WriteReg(dev, 0x00, 0x0197);		mdelay(1); /* Rx mode*/	/*+edward */
-	RF_WriteReg(dev, 0x05, 0x05ab);		mdelay(1); /* Rx mode*/	/*+edward */
-	RF_WriteReg(dev, 0x00, 0x009f);		mdelay(1); /* Rx mode*/	/*+edward */
-	RF_WriteReg(dev, 0x01, 0x0000);		mdelay(1); /* Rx mode*/	/*+edward */
-	RF_WriteReg(dev, 0x02, 0x0000);		mdelay(1); /* Rx mode*/	/*+edward */
+	/* Rx mode*/	/*+edward */
+	RF_WriteReg(dev, 0x00, 0x0197);		mdelay(1);
+	/* Rx mode*/	/*+edward */
+	RF_WriteReg(dev, 0x05, 0x05ab);		mdelay(1);
+	/* Rx mode*/	/*+edward */
+	RF_WriteReg(dev, 0x00, 0x009f);		mdelay(1);
+	/* Rx mode*/	/*+edward */
+	RF_WriteReg(dev, 0x01, 0x0000);		mdelay(1);
+	/* Rx mode*/	/*+edward */
+	RF_WriteReg(dev, 0x02, 0x0000);		mdelay(1);
 	/* power save parameters. */
 	u1b24E = read_nic_byte(dev, 0x24E);
 	write_nic_byte(dev, 0x24E, (u1b24E & (~(BIT5|BIT6))));
 
-	/*=============================================================================
+	/*======================================================================
 	 *
-	 *===========================================================================
+	 *======================================================================
 	 * CCKCONF.TXT
-	 *===========================================================================
+	 *======================================================================
 	 *
 	 *	[POWER SAVE] Power Saving Parameters by jong. 2007-11-27
 	 *	CCK reg0x00[7]=1'b1 :power saving for TX (default)
 	 *	CCK reg0x00[6]=1'b1: power saving for RX (default)
-	 *	CCK reg0x06[4]=1'b1: turn off channel estimation related circuits if not doing channel estimation.
+	 *	CCK reg0x06[4]=1'b1: turn off channel estimation related
+	 *	circuits if not doing channel estimation.
 	 *	CCK reg0x06[3]=1'b1: turn off unused circuits before cca = 1
 	 *	CCK reg0x06[2]=1'b1: turn off cck's circuit if macrst =0
 	 */
@@ -501,9 +558,9 @@
 
 
 	/*
-	 *===========================================================================
+	 *======================================================================
 	 *	AGC.txt
-	 *===========================================================================
+	 *======================================================================
 	 */
 
 	write_phy_ofdm(dev, 0x00, 0x12);
@@ -526,11 +583,11 @@
 	PlatformIOWrite4Byte(dev, PhyAddr, 0x00001080);	/* Annie, 2006-05-05 */
 
 	/*
-	 *===========================================================================
+	 *======================================================================
 	 *
-	 *===========================================================================
+	 *======================================================================
 	 * OFDMCONF.TXT
-	 *===========================================================================
+	 *======================================================================
 	 */
 
 	for (i = 0; i < 60; i++) {
@@ -544,12 +601,16 @@
 	}
 
 	/*
-	 *===========================================================================
+	 *======================================================================
 	 * by amy for antenna
-	 *===========================================================================
+	 *======================================================================
 	 */
-	/* Config Sw/Hw  Combinational Antenna Diversity. Added by Roger, 2008.02.26.	*/
-	SetAntennaConfig87SE(dev, priv->bDefaultAntenna1, priv->bSwAntennaDiverity);
+	/*
+	 * Config Sw/Hw  Combinational Antenna Diversity. Added by Roger,
+	 * 2008.02.26.
+	 */
+	SetAntennaConfig87SE(dev, priv->bDefaultAntenna1,
+			     priv->bSwAntennaDiverity);
 }
 
 
@@ -560,7 +621,8 @@
 	/* lzm add 080826 */
 	if (priv->eRFPowerState != eRfOn) {
 		/*	Don't access BB/RF under disable PLL situation.
-		 *	RT_TRACE(COMP_DIG, DBG_LOUD, ("UpdateInitialGain - pHalData->eRFPowerState!=eRfOn\n"));
+		 *	RT_TRACE(COMP_DIG, DBG_LOUD, ("UpdateInitialGain -
+		 *	pHalData->eRFPowerState!=eRfOn\n"));
 		 *	Back to the original state
 		 */
 		priv->InitialGain = priv->InitialGainBackUp;
@@ -635,7 +697,7 @@
 	u4bRfReg = RF_ReadReg(dev, 0x02);
 
 	/* Enable Thermal meter indication.	*/
-	RF_WriteReg(dev, 0x02, u4bRfReg|PWR_METER_EN);			mdelay(1);
+	RF_WriteReg(dev, 0x02, u4bRfReg|PWR_METER_EN);		mdelay(1);
 }
 
 static void PhyConfig8185(struct net_device *dev)
@@ -645,16 +707,18 @@
 	   priv->RFProgType = read_nic_byte(dev, CONFIG4) & 0x03;
 	/*  RF config */
 	ZEBRA_Config_85BASIC_HardCode(dev);
-	/* Set default initial gain state to 4, approved by SD3 DZ, by Bruce, 2007-06-06. */
+	/* Set default initial gain state to 4, approved by SD3 DZ, by Bruce,
+	 * 2007-06-06.
+	 */
 	if (priv->bDigMechanism) {
 		if (priv->InitialGain == 0)
 			priv->InitialGain = 4;
 	}
 
 	/*
-	 *	Enable thermal meter indication to implement TxPower tracking on 87SE.
-	 *	We initialize thermal meter here to avoid unsuccessful configuration.
-	 *	Added by Roger, 2007.12.11.
+	 *	Enable thermal meter indication to implement TxPower tracking
+	 *	on 87SE. We initialize thermal meter here to avoid unsuccessful
+	 *	configuration. Added by Roger, 2007.12.11.
 	 */
 	if (priv->bTxPowerTrack)
 		InitTxPwrTracking87SE(dev);
@@ -667,7 +731,10 @@
 
 static void HwConfigureRTL8185(struct net_device *dev)
 {
-	/* RTL8185_TODO: Determine Retrylimit, TxAGC, AutoRateFallback control. */
+	/*
+	 * RTL8185_TODO: Determine Retrylimit, TxAGC,
+	 * AutoRateFallback control.
+	 */
 	u8 bUNIVERSAL_CONTROL_RL = 0;
 	u8 bUNIVERSAL_CONTROL_AGC = 1;
 	u8 bUNIVERSAL_CONTROL_ANT = 1;
@@ -691,7 +758,7 @@
 		write_nic_byte(dev, OFDM_TXAGC, 128);
 		val8 = val8 & 0xfe;
 	} else {
-		val8 = val8 | 0x01 ;
+		val8 = val8 | 0x01;
 	}
 
 
@@ -715,7 +782,9 @@
 	if (bAUTO_RATE_FALLBACK_CTL) {
 		val8 |= RATE_FALLBACK_CTL_ENABLE | RATE_FALLBACK_CTL_AUTO_STEP1;
 
-		/* <RJ_TODO_8185B> We shall set up the ARFR according to user's setting. */
+		/* <RJ_TODO_8185B> We shall set up the ARFR according
+		 * to user's setting.
+		 */
 		PlatformIOWrite2Byte(dev, ARFR, 0x0fff); /* set 1M ~ 54Mbps. */
 	}
 	write_nic_byte(dev, RATE_FALLBACK, val8);
@@ -724,9 +793,9 @@
 static void MacConfig_85BASIC_HardCode(struct net_device *dev)
 {
 	/*
-	 *==========================================================================
+	 *======================================================================
 	 * MACREG.TXT
-	 *==========================================================================
+	 *======================================================================
 	 */
 	int nLinesRead = 0;
 	u32 u4bRegOffset, u4bRegValue, u4bPageIndex = 0;
@@ -745,7 +814,7 @@
 
 		write_nic_byte(dev, u4bRegOffset, (u8)u4bRegValue);
 	}
-	/* ============================================================================ */
+	/* ================================================================= */
 }
 
 static void MacConfig_85BASIC(struct net_device *dev)
@@ -754,12 +823,14 @@
 	u8			u1DA;
 	MacConfig_85BASIC_HardCode(dev);
 
-	/* ============================================================================ */
+	/* ================================================================= */
 
 	/* Follow TID_AC_MAP of WMac. */
 	write_nic_word(dev, TID_AC_MAP, 0xfa50);
 
-	/* Interrupt Migration, Jong suggested we use set 0x0000 first, 2005.12.14, by rcnjko. */
+	/* Interrupt Migration, Jong suggested we use set 0x0000 first,
+	 * 2005.12.14, by rcnjko.
+	 */
 	write_nic_word(dev, IntMig, 0x0000);
 
 	/* Prevent TPC to cause CRC error. Added by Annie, 2006-06-10. */
@@ -768,7 +839,11 @@
 	PlatformIOWrite1Byte(dev, 0x1F8, 0x00);
 
 	/* Asked for by SD3 CM Lin, 2006.06.27, by rcnjko. */
-	/* power save parameter based on "87SE power save parameters 20071127.doc", as follow. */
+
+	/*
+	 *  power save parameter based on
+	 * "87SE power save parameters 20071127.doc", as follow.
+	 */
 
 	/* Enable DA10 TX power saving */
 	u1DA = read_nic_byte(dev, PHYPR);
@@ -803,31 +878,45 @@
 
 	/*
 	 *	<RJ_TODO_8185B>
-	 *	TODO: We still don't know how to set up these registers, just follow WMAC to
-	 *	verify 8185B FPAG.
+	 *	TODO: We still don't know how to set up these registers,
+	 *	just follow WMAC to verify 8185B FPAG.
 	 *
 	 *	<RJ_TODO_8185B>
 	 *	Jong said CWmin/CWmax register are not functional in 8185B,
-	 *	so we shall fill channel access realted register into AC parameter registers,
+	 *	so we shall fill channel access realted register into AC
+	 *	parameter registers,
 	 *	even in nQBss.
 	 */
-	ChnlAccessSetting->SIFS_Timer = 0x22; /* Suggested by Jong, 2005.12.08. */
+
+	/* Suggested by Jong, 2005.12.08. */
+	ChnlAccessSetting->SIFS_Timer = 0x22;
 	ChnlAccessSetting->DIFS_Timer = 0x1C; /* 2006.06.02, by rcnjko. */
 	ChnlAccessSetting->SlotTimeTimer = 9; /* 2006.06.02, by rcnjko. */
-	ChnlAccessSetting->EIFS_Timer = 0x5B; /* Suggested by wcchu, it is the default value of EIFS register, 2005.12.08. */
+	/*
+	 * Suggested by wcchu, it is the default value of EIFS register,
+	 * 2005.12.08.
+	 */
+	ChnlAccessSetting->EIFS_Timer = 0x5B;
 	ChnlAccessSetting->CWminIndex = 3; /* 2006.06.02, by rcnjko. */
 	ChnlAccessSetting->CWmaxIndex = 7; /* 2006.06.02, by rcnjko. */
 
 	write_nic_byte(dev, SIFS, ChnlAccessSetting->SIFS_Timer);
-	write_nic_byte(dev, SLOT, ChnlAccessSetting->SlotTimeTimer); /* Rewrited from directly use PlatformEFIOWrite1Byte(), by Annie, 2006-03-29. */
+	/*
+	 * Rewrited from directly use PlatformEFIOWrite1Byte(),
+	 * by Annie, 2006-03-29.
+	 */
+	write_nic_byte(dev, SLOT, ChnlAccessSetting->SlotTimeTimer);
 
 	write_nic_byte(dev, EIFS, ChnlAccessSetting->EIFS_Timer);
 
-	write_nic_byte(dev, AckTimeOutReg, 0x5B); /* <RJ_EXPR_QOS> Suggested by wcchu, it is the default value of EIFS register, 2005.12.08. */
+	/*
+	 * <RJ_EXPR_QOS> Suggested by wcchu, it is the default value of EIFS
+	 * register, 2005.12.08.
+	 */
+	write_nic_byte(dev, AckTimeOutReg, 0x5B);
 
-	for (eACI = 0; eACI < AC_MAX; eACI++) {
+	for (eACI = 0; eACI < AC_MAX; eACI++)
 		write_nic_byte(dev, ACM_CONTROL, 0);
-	}
 }
 
 static void ActSetWirelessMode8185(struct net_device *dev, u8 btWirelessMode)
@@ -837,7 +926,10 @@
 	u8	btSupportedWirelessMode = GetSupportedWirelessMode8185(dev);
 
 	if ((btWirelessMode & btSupportedWirelessMode) == 0)	{
-		/* Don't switch to unsupported wireless mode, 2006.02.15, by rcnjko. */
+		/*
+		 * Don't switch to unsupported wireless mode, 2006.02.15,
+		 * by rcnjko.
+		 */
 		DMESGW("ActSetWirelessMode8185(): WirelessMode(%d) is not supported (%d)!\n",
 			btWirelessMode, btSupportedWirelessMode);
 		return;
@@ -859,11 +951,11 @@
 		}
 	}
 
-	/* 
- 	 * 2. Swtich band: RF or BB specific actions,
-	 * for example, refresh tables in omc8255, or change initial gain if necessary.
-	 * Nothing to do for Zebra to switch band.
-	 * Update current wireless mode if we switch to specified band successfully. 
+	/*
+	 * 2. Swtich band: RF or BB specific actions,
+	 * for example, refresh tables in omc8255, or change initial gain if
+	 * necessary. Nothing to do for Zebra to switch band. Update current
+	 * wireless mode if we switch to specified band successfully.
 	 */
 
 	ieee->mode = (WIRELESS_MODE)btWirelessMode;
@@ -876,7 +968,8 @@
 	else if (ieee->mode == WIRELESS_MODE_G)
 		DMESG("WIRELESS_MODE_G\n");
 
-	ActUpdateChannelAccessSetting( dev, ieee->mode, &priv->ChannelAccessSetting);
+	ActUpdateChannelAccessSetting(dev, ieee->mode,
+				      &priv->ChannelAccessSetting);
 }
 
 void rtl8185b_irq_enable(struct net_device *dev)
@@ -892,7 +985,7 @@
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	u8 i;
 
-	for (i = 0; i < 6 ; i++)
+	for (i = 0; i < 6; i++)
 		priv->ieee80211->current_network.bssid[i] = 0x55;
 
 
@@ -901,11 +994,12 @@
 	/*
 	 *	Stop Beacon.
 	 *
-	 *	Vista add a Adhoc profile, HW radio off until OID_DOT11_RESET_REQUEST
-	 *	Driver would set MSR=NO_LINK, then HW Radio ON, MgntQueue Stuck.
-	 *	Because Bcn DMA isn't complete, mgnt queue would stuck until Bcn packet send.
+	 *	Vista add a Adhoc profile, HW radio off until
+	 *	OID_DOT11_RESET_REQUEST Driver would set MSR=NO_LINK,
+	 *	then HW Radio ON, MgntQueue Stuck. Because Bcn DMA isn't
+	 *	complete, mgnt queue would stuck until Bcn packet send.
 	 *
-	 *	Disable Beacon Queue Own bit, suggested by jong	
+	 *	Disable Beacon Queue Own bit, suggested by jong
 	 */
 	ieee80211_stop_send_beacons(priv->ieee80211);
 
@@ -938,12 +1032,14 @@
 	 * Commented out by rcnjko, 2005.01.27:
 	 * I move SecClearAllKeys() to MgntActSet_802_11_DISASSOCIATE().
 	 *
-	 *	2004/09/15, kcwu, the key should be cleared, or the new handshaking will not success
+	 *	2004/09/15, kcwu, the key should be cleared, or the new
+	 *	handshaking will not success
 	 *
-	 *	In WPA WPA2 need to Clear all key ... because new key will set after new handshaking.
-	 *	2004.10.11, by rcnjko. 
+	 *	In WPA WPA2 need to Clear all key ... because new key will set
+	 *	after new handshaking. 2004.10.11, by rcnjko.
 	 */
-	MlmeDisassociateRequest(dev, priv->ieee80211->current_network.bssid, asRsn);
+	MlmeDisassociateRequest(dev, priv->ieee80211->current_network.bssid,
+				asRsn);
 
 	priv->ieee80211->state = IEEE80211_NOLINK;
 }
@@ -964,11 +1060,13 @@
 
 		if (priv->ieee80211->iw_mode == IW_MODE_INFRA) {
 			/*
- 			 * 	We clear key here instead of MgntDisconnectAP() because that
-			 *	MgntActSet_802_11_DISASSOCIATE() is an interface called by OS,
-			 *	e.g. OID_802_11_DISASSOCIATE in Windows while as MgntDisconnectAP() is
-			 *	used to handle disassociation related things to AP, e.g. send Disassoc
-			 *	frame to AP.  2005.01.27, by rcnjko. 
+			 *	We clear key here instead of MgntDisconnectAP()
+			 *	because that MgntActSet_802_11_DISASSOCIATE()
+			 *	is an interface called by OS, e.g.
+			 *	OID_802_11_DISASSOCIATE in Windows while as
+			 *	MgntDisconnectAP() is used to handle
+			 *	disassociation related things to AP, e.g. send
+			 *	Disassoc frame to AP.  2005.01.27, by rcnjko.
 			 */
 			MgntDisconnectAP(dev, asRsn);
 		}
@@ -979,12 +1077,14 @@
 /*
  *	Description:
  *		Chang RF Power State.
- *		Note that, only MgntActSet_RF_State() is allowed to set HW_VAR_RF_STATE.
+ *		Note that, only MgntActSet_RF_State() is allowed to set
+ *		HW_VAR_RF_STATE.
  *
  *	Assumption:
  *		PASSIVE LEVEL.
  */
-static bool SetRFPowerState(struct net_device *dev, RT_RF_POWER_STATE eRFPowerState)
+static bool SetRFPowerState(struct net_device *dev,
+		RT_RF_POWER_STATE eRFPowerState)
 {
 	struct	r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	bool	bResult = false;
@@ -997,7 +1097,8 @@
 	return bResult;
 }
 
-bool MgntActSet_RF_State(struct net_device *dev, RT_RF_POWER_STATE StateToSet, u32 ChangeSource)
+bool MgntActSet_RF_State(struct net_device *dev,
+		RT_RF_POWER_STATE StateToSet, u32 ChangeSource)
 {
 	struct	r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	bool	bActionAllowed = false;
@@ -1006,8 +1107,9 @@
 	u16	RFWaitCounter = 0;
 	unsigned long flag;
 	/*
-	 *	Prevent the race condition of RF state change. By Bruce, 2007-11-28.
-	 *	Only one thread can change the RF state at one time, and others should wait to be executed.
+	 *	Prevent the race condition of RF state change. By Bruce,
+	 *	2007-11-28. Only one thread can change the RF state at one time,
+	 *	and others should wait to be executed.
 	 */
 	while (true) {
 		spin_lock_irqsave(&priv->rf_ps_lock, flag);
@@ -1018,7 +1120,10 @@
 				RFWaitCounter++;
 				udelay(1000); /* 1 ms	*/
 
-				/* Wait too long, return FALSE to avoid to be stuck here. */
+				/*
+				 *	Wait too long, return FALSE to avoid
+				 *	to be stuck here.
+				 */
 				if (RFWaitCounter > 1000) { /* 1sec */
 					printk("MgntActSet_RF_State(): Wait too long to set RF\n");
 					/* TODO: Reset RF state? */
@@ -1036,8 +1141,10 @@
 	switch (StateToSet) {
 	case eRfOn:
 		/*
-		 *	Turn On RF no matter the IPS setting because we need to update the RF state to Ndis under Vista, or
-		 *	the Windows does not allow the driver to perform site survey any more. By Bruce, 2007-10-02.
+		 *	Turn On RF no matter the IPS setting because we need to
+		 *	update the RF state to Ndis under Vista, or the Windows
+		 *	does not allow the driver to perform site survey any
+		 *	more. By Bruce, 2007-10-02.
 		 */
 		priv->RfOffReason &= (~ChangeSource);
 
@@ -1045,7 +1152,8 @@
 			priv->RfOffReason = 0;
 			bActionAllowed = true;
 
-			if (rtState == eRfOff && ChangeSource >= RF_CHANGE_BY_HW)
+			if (rtState == eRfOff &&
+			    ChangeSource >= RF_CHANGE_BY_HW)
 				bConnectBySSID = true;
 		}
 		break;
@@ -1056,13 +1164,18 @@
 		if (priv->RfOffReason > RF_CHANGE_BY_IPS) {
 			/*
 			 *	060808, Annie:
-			 *	Disconnect to current BSS when radio off. Asked by QuanTa.
+			 *	Disconnect to current BSS when radio off.
+			 *	Asked by QuanTa.
 			 *
-			 *	Calling MgntDisconnect() instead of MgntActSet_802_11_DISASSOCIATE(),
-			 *	because we do NOT need to set ssid to dummy ones.
+			 *	Calling MgntDisconnect() instead of
+			 *	MgntActSet_802_11_DISASSOCIATE(), because
+			 *	we do NOT need to set ssid to dummy ones.
 			 */
 			MgntDisconnect(dev, disas_lv_ss);
-			/* Clear content of bssDesc[] and bssDesc4Query[] to avoid reporting old bss to UI. */
+			/*
+			 *	Clear content of bssDesc[] and bssDesc4Query[]
+			 *	to avoid reporting old bss to UI.
+			 */
 		}
 
 		priv->RfOffReason |= ChangeSource;
@@ -1092,18 +1205,21 @@
 {
 	struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 	/*
-	 *	This flag "bSwRfProcessing", indicates the status of IPS procedure, should be set if the IPS workitem
-	 *	is really scheduled.
-	 *	The old code, sets this flag before scheduling the IPS workitem and however, at the same time the
-	 *	previous IPS workitem did not end yet, fails to schedule the current workitem. Thus, bSwRfProcessing
-	 *	blocks the IPS procedure of switching RF.
+	 *	This flag "bSwRfProcessing", indicates the status of IPS
+	 *	procedure, should be set if the IPS workitem is really
+	 *	scheduled. The old code, sets this flag before scheduling the
+	 *	IPS workitem and however, at the same time the previous IPS
+	 *	workitem did not end yet, fails to schedule the current
+	 *	workitem. Thus, bSwRfProcessing blocks the IPS procedure of
+	 *	switching RF.
 	 */
 	priv->bSwRfProcessing = true;
 
 	MgntActSet_RF_State(dev, priv->eInactivePowerState, RF_CHANGE_BY_IPS);
 
 	/*
-	 *	To solve CAM values miss in RF OFF, rewrite CAM values after RF ON. By Bruce, 2007-09-20.
+	 *	To solve CAM values miss in RF OFF, rewrite CAM values after
+	 *	RF ON. By Bruce, 2007-09-20.
 	 */
 
 	priv->bSwRfProcessing = false;
@@ -1122,10 +1238,10 @@
 
 		/*
 		 *	Do not enter IPS in the following conditions:
-		 *	(1) RF is already OFF or Sleep
-		 *	(2) bSwRfProcessing (indicates the IPS is still under going)
-		 *	(3) Connected (only disconnected can trigger IPS)
-		 *	(4) IBSS (send Beacon)
+		 *	(1) RF is already OFF or
+		 *	Sleep (2) bSwRfProcessing (indicates the IPS is still
+		 *	under going) (3) Connected (only disconnected can
+		 *	trigger IPS)(4) IBSS (send Beacon)
 		 *	(5) AP mode (send Beacon)
 		 */
 		if (rtState == eRfOn && !priv->bSwRfProcessing
@@ -1141,7 +1257,9 @@
 	RT_RF_POWER_STATE rtState;
 	if (priv->bInactivePs) {
 		rtState = priv->eRFPowerState;
-		if ((rtState == eRfOff || rtState == eRfSleep) && (!priv->bSwRfProcessing) && priv->RfOffReason <= RF_CHANGE_BY_IPS) {
+		if ((rtState == eRfOff || rtState == eRfSleep) &&
+		    !priv->bSwRfProcessing
+		    && priv->RfOffReason <= RF_CHANGE_BY_IPS) {
 			priv->eInactivePowerState = eRfOn;
 			InactivePowerSave(dev);
 		}
@@ -1170,27 +1288,32 @@
 	HwConfigureRTL8185(dev);
 	write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
 	write_nic_word(dev, MAC4, ((u32 *)dev->dev_addr)[1] & 0xffff);
-	write_nic_byte(dev, MSR, read_nic_byte(dev, MSR) & 0xf3); /* default network type to 'No Link' */
+	/* default network type to 'No Link' */
+	write_nic_byte(dev, MSR, read_nic_byte(dev, MSR) & 0xf3);
 	write_nic_word(dev, BcnItv, 100);
 	write_nic_word(dev, AtimWnd, 2);
 	PlatformIOWrite2Byte(dev, FEMR, 0xFFFF);
 	write_nic_byte(dev, WPA_CONFIG, 0);
 	MacConfig_85BASIC(dev);
-	/* Override the RFSW_CTRL (MAC offset 0x272-0x273), 2006.06.07, by rcnjko. */
+	/* Override the RFSW_CTRL (MAC offset 0x272-0x273), 2006.06.07,
+	 * by rcnjko.
+	 */
 	/* BT_DEMO_BOARD type */
 	PlatformIOWrite2Byte(dev, RFSW_CTRL, 0x569a);
 
 	/*
-	 *---------------------------------------------------------------------------
+	 *---------------------------------------------------------------------
 	 *	Set up PHY related.
-	 *---------------------------------------------------------------------------
+	 *---------------------------------------------------------------------
 	 */
 	/* Enable Config3.PARAM_En to revise AnaaParm. */
 	write_nic_byte(dev, CR9346, 0xc0); /* enable config register write */
 	tmpu8 = read_nic_byte(dev, CONFIG3);
 	write_nic_byte(dev, CONFIG3, (tmpu8 | CONFIG3_PARM_En));
 	/* Turn on Analog power. */
-	/* Asked for by William, otherwise, MAC 3-wire can't work, 2006.06.27, by rcnjko. */
+	/* Asked for by William, otherwise, MAC 3-wire can't work,
+	 * 2006.06.27, by rcnjko.
+	 */
 	write_nic_dword(dev, ANAPARAM2, ANAPARM2_ASIC_ON);
 	write_nic_dword(dev, ANAPARAM, ANAPARM_ASIC_ON);
 	write_nic_word(dev, ANAPARAM3, 0x0010);
@@ -1225,7 +1348,8 @@
 	/*
 	 *	We assume RegWirelessMode has already been initialized before,
 	 *	however, we has to validate the wireless mode here and provide a
-	 *	reasonable initialized value if necessary. 2005.01.13, by rcnjko.
+	 *	reasonable initialized value if necessary. 2005.01.13,
+	 *	by rcnjko.
 	 */
 	SupportedWirelessMode = GetSupportedWirelessMode8185(dev);
 	if ((ieee->mode != WIRELESS_MODE_B) &&
@@ -1272,14 +1396,15 @@
 		MgntActSet_RF_State(dev, eRfOn, 0);
 	}
 		/*
-		 *	If inactive power mode is enabled, disable rf while in disconnected state.
+		 * If inactive power mode is enabled, disable rf while in
+		 * disconnected state.
 		 */
 	if (priv->bInactivePs)
 		MgntActSet_RF_State(dev , eRfOff, RF_CHANGE_BY_IPS);
 
 	ActSetWirelessMode8185(dev, (u8)(InitWirelessMode));
 
-	/* ----------------------------------------------------------------------------- */
+	/* ----------------------------------------------------------------- */
 
 	rtl8185b_irq_enable(dev);
 
@@ -1296,14 +1421,15 @@
 	if (dev->flags & IFF_PROMISC)
 		DMESG("NIC in promisc mode");
 
-	if (priv->ieee80211->iw_mode == IW_MODE_MONITOR || \
-	   dev->flags & IFF_PROMISC) {
+	if (priv->ieee80211->iw_mode == IW_MODE_MONITOR || dev->flags &
+	    IFF_PROMISC) {
 		priv->ReceiveConfig = priv->ReceiveConfig & (~RCR_APM);
 		priv->ReceiveConfig = priv->ReceiveConfig | RCR_AAP;
 	}
 
 	if (priv->ieee80211->iw_mode == IW_MODE_MONITOR)
-		priv->ReceiveConfig = priv->ReceiveConfig | RCR_ACF | RCR_APWRMGT | RCR_AICV;
+		priv->ReceiveConfig = priv->ReceiveConfig | RCR_ACF |
+				      RCR_APWRMGT | RCR_AICV;
 
 
 	if (priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR)
diff --git a/drivers/staging/rtl8188eu/Makefile b/drivers/staging/rtl8188eu/Makefile
index 1639a45..0a617b4 100644
--- a/drivers/staging/rtl8188eu/Makefile
+++ b/drivers/staging/rtl8188eu/Makefile
@@ -1,5 +1,3 @@
-EXTRA_CFLAGS += -I$(src)/include
-
 r8188eu-y :=				\
 		core/rtw_ap.o		\
 		core/rtw_br_ext.o	\
@@ -30,7 +28,6 @@
 		hal/HalPhyRf.o		\
 		hal/HalPhyRf_8188e.o	\
 		hal/HalPwrSeqCmd.o	\
-		hal/Hal8188EFWImg_CE.o	\
 		hal/Hal8188EPwrSeq.o	\
 		hal/Hal8188ERateAdaptive.o\
 		hal/hal_intf.o		\
@@ -67,4 +64,4 @@
 
 obj-$(CONFIG_R8188EU)	:= r8188eu.o
 
-ccflags-y += -D__CHECK_ENDIAN__
+ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/include
diff --git a/drivers/staging/rtl8188eu/TODO b/drivers/staging/rtl8188eu/TODO
index e50aa50..f7f389c 100644
--- a/drivers/staging/rtl8188eu/TODO
+++ b/drivers/staging/rtl8188eu/TODO
@@ -2,7 +2,6 @@
 - find and remove remaining code valid only for 5 HGz. Most of the obvious
   ones have been removed, but things like channel > 14 still exist.
 - find and remove any code for other chips that is left over
-- convert to external firmware
 - convert any remaining unusual variable types
 - find codes that can use %pM and %Nph formatting
 - checkpatch.pl fixes - most of the remaining ones are lines too long. Many
diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c
index 2c73823..2c678f4 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ap.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ap.c
@@ -348,7 +348,7 @@
 
 			if (psta->state & WIFI_SLEEP_STATE) {
 				if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
-					/* to check if alive by another methods if staion is at ps mode. */
+					/* to check if alive by another methods if station is at ps mode. */
 					psta->expire_to = pstapriv->expire_to;
 					psta->state |= WIFI_STA_ALIVE_CHK_STATE;
 
diff --git a/drivers/staging/rtl8188eu/core/rtw_br_ext.c b/drivers/staging/rtl8188eu/core/rtw_br_ext.c
index fbca394..9f40742 100644
--- a/drivers/staging/rtl8188eu/core/rtw_br_ext.c
+++ b/drivers/staging/rtl8188eu/core/rtw_br_ext.c
@@ -527,7 +527,7 @@
 		case NAT25_CHECK:
 			return -1;
 		case NAT25_INSERT:
-			/* some muticast with source IP is all zero, maybe other case is illegal */
+			/* some multicast with source IP is all zero, maybe other case is illegal */
 			/* in class A, B, C, host address is all zero or all one is illegal */
 			if (iph->saddr == 0)
 				return 0;
@@ -677,9 +677,8 @@
 			switch (method) {
 			case NAT25_CHECK:
 				if (!memcmp(skb->data+ETH_ALEN, ipx->ipx_source.node, ETH_ALEN))
-				DEBUG_INFO("NAT25: Check IPX skb_copy\n");
+					DEBUG_INFO("NAT25: Check IPX skb_copy\n");
 				return 0;
-				return -1;
 			case NAT25_INSERT:
 				DEBUG_INFO("NAT25: Insert IPX, Dest =%08x,%02x%02x%02x%02x%02x%02x,%04x Source =%08x,%02x%02x%02x%02x%02x%02x,%04x\n",
 					ipx->ipx_dest.net,
diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c
index 9632ef4..f45f4ed 100644
--- a/drivers/staging/rtl8188eu/core/rtw_cmd.c
+++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c
@@ -218,7 +218,7 @@
 _func_exit_;
 }
 
-int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
+static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
 {
 	u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */
 
@@ -1162,7 +1162,7 @@
 	else
 		memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16);
 
-	/* jeff: set this becasue at least sw key is ready */
+	/* jeff: set this because at least sw key is ready */
 	padapter->securitypriv.busetkipkey = true;
 
 	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
@@ -1667,7 +1667,7 @@
 	pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
 }
 
-void dynamic_chk_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz)
+static void dynamic_chk_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz)
 {
 	struct mlme_priv *pmlmepriv;
 
diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c
index 869434c..806f56f 100644
--- a/drivers/staging/rtl8188eu/core/rtw_efuse.c
+++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c
@@ -159,7 +159,7 @@
 /*  */
 /* 	Description: */
 /* 		Execute E-Fuse read byte operation. */
-/* 		Refered from SD1 Richard. */
+/* 		Referred from SD1 Richard. */
 /*  */
 /* 	Assumption: */
 /* 		1. Boot from E-Fuse and successfully auto-load. */
@@ -214,7 +214,7 @@
 /* 	Description: */
 /* 		1. Execute E-Fuse read byte operation according as map offset and */
 /* 		    save to E-Fuse table. */
-/* 		2. Refered from SD1 Richard. */
+/* 		2. Referred from SD1 Richard. */
 /*  */
 /* 	Assumption: */
 /* 		1. Boot from E-Fuse and successfully auto-load. */
@@ -542,7 +542,7 @@
 {
 	u8 offset, word_en;
 	u8 *map;
-	u8 newdata[PGPKT_DATA_SIZE];
+	u8 newdata[PGPKT_DATA_SIZE + 1];
 	s32	i, idx;
 	u8 ret = _SUCCESS;
 	u16 mapLen = 0;
@@ -564,7 +564,7 @@
 
 	offset = (addr >> 3);
 	word_en = 0xF;
-	_rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE);
+	_rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
 	i = addr & 0x7;	/*  index of one package */
 	idx = 0;	/*  data index */
 
@@ -634,7 +634,7 @@
 {
 	u8 offset, word_en;
 	u8 *map;
-	u8 newdata[PGPKT_DATA_SIZE];
+	u8 newdata[PGPKT_DATA_SIZE + 1];
 	s32	i, idx;
 	u8 ret = _SUCCESS;
 	u16 mapLen = 0;
@@ -656,7 +656,7 @@
 
 	offset = (addr >> 3);
 	word_en = 0xF;
-	_rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE);
+	_rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
 	i = addr & 0x7;	/*  index of one package */
 	idx = 0;	/*  data index */
 
diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
index 6fc7742..e6f98fb 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
@@ -1129,7 +1129,7 @@
 		mac[3] = 0x87;
 		mac[4] = 0x00;
 		mac[5] = 0x00;
-		/*  use default mac addresss */
+		/*  use default mac address */
 		memcpy(mac_addr, mac, ETH_ALEN);
 		DBG_88E("MAC Address from efuse error, assign default one !!!\n");
 	}
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c
index ea66071..ac3535d 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mlme.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c
@@ -557,7 +557,7 @@
 			sq_final = ((u32)(src->PhyInfo.SignalQuality)+(u32)(dst->PhyInfo.SignalQuality)*4)/5;
 			rssi_final = (src->Rssi+dst->Rssi*4)/5;
 		} else {
-			/* bss info not receving from the right channel, use the original RX signal infos */
+			/* bss info not receiving from the right channel, use the original RX signal infos */
 			ss_final = dst->PhyInfo.SignalStrength;
 			sq_final = dst->PhyInfo.SignalQuality;
 			rssi_final = dst->Rssi;
@@ -636,7 +636,7 @@
 			pnetwork->aid = 0;
 			pnetwork->join_res = 0;
 
-			/* bss info not receving from the right channel */
+			/* bss info not receiving from the right channel */
 			if (pnetwork->network.PhyInfo.SignalQuality == 101)
 				pnetwork->network.PhyInfo.SignalQuality = 0;
 		} else {
@@ -656,7 +656,7 @@
 
 			pnetwork->last_scanned = rtw_get_current_time();
 
-			/* bss info not receving from the right channel */
+			/* bss info not receiving from the right channel */
 			if (pnetwork->network.PhyInfo.SignalQuality == 101)
 				pnetwork->network.PhyInfo.SignalQuality = 0;
 			rtw_list_insert_tail(&(pnetwork->list), &(queue->queue));
@@ -670,7 +670,7 @@
 
 		pnetwork->last_scanned = rtw_get_current_time();
 
-		/* target.Reserved[0]== 1, means that scaned network is a bcn frame. */
+		/* target.Reserved[0]== 1, means that scanned network is a bcn frame. */
 		if ((pnetwork->network.IELength > target->IELength) && (target->Reserved[0] == 1))
 			update_ie = false;
 
@@ -1130,7 +1130,7 @@
 			padapter->securitypriv.wps_ie_len = 0;
 		}
 		/* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info */
-		/* if A-MPDU Rx is enabled, reseting  rx_ordering_ctrl wstart_b(indicate_seq) to default value = 0xffff */
+		/* if A-MPDU Rx is enabled, resetting  rx_ordering_ctrl wstart_b(indicate_seq) to default value = 0xffff */
 		/* todo: check if AP can send A-MPDU packets */
 		for (i = 0; i < 16; i++) {
 			/* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
@@ -1210,7 +1210,7 @@
 	rtw_update_ht_cap(padapter, cur_network->network.IEs, cur_network->network.IELength);
 }
 
-/* Notes: the fucntion could be > passive_level (the same context as Rx tasklet) */
+/* Notes: the function could be > passive_level (the same context as Rx tasklet) */
 /* pnetwork: returns from rtw_joinbss_event_callback */
 /* ptarget_wlan: found from scanned_queue */
 /* if join_res > 0, for (fw_state == WIFI_STATION_STATE), we check if  "ptarget_sta" & "ptarget_wlan" exist. */
@@ -2177,7 +2177,7 @@
 _func_exit_;
 }
 
-/* the fucntion is at passive_level */
+/* the function is at passive_level */
 void rtw_joinbss_reset(struct adapter *padapter)
 {
 	u8	threshold;
@@ -2205,7 +2205,7 @@
 	}
 }
 
-/* the fucntion is >= passive_level */
+/* the function is >= passive_level */
 unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ie, uint in_len, uint *pout_len)
 {
 	u32 ielen, out_len;
@@ -2273,7 +2273,7 @@
 	return phtpriv->ht_option;
 }
 
-/* the fucntion is > passive_level (in critical_section) */
+/* the function is > passive_level (in critical_section) */
 void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len)
 {
 	u8 *p, max_ampdu_sz;
@@ -2332,7 +2332,7 @@
 			else
 				pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_2R[i];
 		}
-		/* switch to the 40M Hz mode accoring to the AP */
+		/* switch to the 40M Hz mode according to the AP */
 		pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
 		switch ((pmlmeinfo->HT_info.infos[0] & 0x3)) {
 		case HT_EXTCHNL_OFFSET_UPPER:
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
index 4b2eb8e..7ab5ff0 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
@@ -1852,7 +1852,7 @@
 	struct pkt_attrib *pattrib;
 	unsigned char *pframe;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short *fctrl;
+	__le16 *fctrl;
 	struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
 	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
@@ -2199,7 +2199,7 @@
 	struct pkt_attrib			*pattrib;
 	unsigned char					*pframe;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short				*fctrl;
+	__le16 *fctrl;
 	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
 	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
@@ -2349,7 +2349,7 @@
 	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
 		/*	Commented by Albert 2011/03/08 */
 		/*	According to the P2P specification */
-		/*	if the sending device will be client, the P2P Capability should be reserved of group negotation response frame */
+		/*	if the sending device will be client, the P2P Capability should be reserved of group negotiation response frame */
 		p2pie[p2pielen++] = 0;
 	} else {
 		/*	Be group owner or meet the error case */
@@ -2561,7 +2561,7 @@
 	struct pkt_attrib			*pattrib;
 	unsigned char					*pframe;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short				*fctrl;
+	__le16 *fctrl;
 	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
 	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
@@ -2729,7 +2729,7 @@
 	struct pkt_attrib			*pattrib;
 	unsigned char					*pframe;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short				*fctrl;
+	__le16 *fctrl;
 	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
 	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
@@ -2981,7 +2981,7 @@
 	struct pkt_attrib			*pattrib;
 	unsigned char					*pframe;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short				*fctrl;
+	__le16 *fctrl;
 	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
 	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
@@ -3175,7 +3175,7 @@
 	struct pkt_attrib			*pattrib;
 	unsigned char					*pframe;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short				*fctrl;
+	__le16 *fctrl;
 	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
 	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
@@ -3283,7 +3283,7 @@
 	struct pkt_attrib			*pattrib;
 	unsigned char					*pframe;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short				*fctrl;
+	__le16 *fctrl;
 	unsigned char					*mac;
 	struct xmit_priv	*pxmitpriv = &(padapter->xmitpriv);
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
@@ -3534,7 +3534,7 @@
 	struct pkt_attrib		*pattrib;
 	unsigned char			*pframe;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short		*fctrl;
+	__le16 *fctrl;
 	unsigned char			*mac;
 	struct xmit_priv		*pxmitpriv = &(padapter->xmitpriv);
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
@@ -4484,7 +4484,7 @@
 	struct pkt_attrib	*pattrib;
 	unsigned char	*pframe;
 	struct rtw_ieee80211_hdr *pwlanhdr;
-	unsigned short *fctrl;
+	__le16 *fctrl;
 	unsigned int	rate_len;
 	struct xmit_priv	*pxmitpriv = &(padapter->xmitpriv);
 #if defined(CONFIG_88EU_AP_MODE)
@@ -4713,7 +4713,7 @@
 	struct pkt_attrib			*pattrib;
 	unsigned char					*pframe;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short				*fctrl;
+	__le16 *fctrl;
 	unsigned char					*mac, *bssid;
 	struct xmit_priv	*pxmitpriv = &(padapter->xmitpriv);
 #if defined (CONFIG_88EU_AP_MODE)
@@ -4876,7 +4876,7 @@
 	struct pkt_attrib		*pattrib;
 	unsigned char			*pframe;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short		*fctrl;
+	__le16 *fctrl;
 	unsigned char			*mac;
 	unsigned char			bssrate[NumRates];
 	struct xmit_priv		*pxmitpriv = &(padapter->xmitpriv);
@@ -5013,7 +5013,7 @@
 	struct pkt_attrib *pattrib;
 	unsigned char *pframe;
 	struct rtw_ieee80211_hdr *pwlanhdr;
-	unsigned short *fctrl;
+	__le16 *fctrl;
 	unsigned int val32;
 	u16 val16;
 #ifdef CONFIG_88EU_AP_MODE
@@ -5153,7 +5153,7 @@
 	struct pkt_attrib *pattrib;
 	unsigned char	*pbuf, *pframe;
 	unsigned short val;
-	unsigned short *fctrl;
+	__le16 *fctrl;
 	struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
@@ -5290,7 +5290,7 @@
 	struct pkt_attrib	*pattrib;
 	unsigned char		*pframe, *p;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short	*fctrl;
+	__le16 *fctrl;
 	__le16		le_tmp;
 	unsigned int	i, j, ie_len, index = 0;
 	unsigned char	rf_type, bssrate[NumRates], sta_bssrate[NumRates];
@@ -5625,7 +5625,7 @@
 	struct pkt_attrib			*pattrib;
 	unsigned char					*pframe;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short				*fctrl;
+	__le16 *fctrl;
 	struct xmit_priv	*pxmitpriv;
 	struct mlme_ext_priv	*pmlmeext;
 	struct mlme_ext_info	*pmlmeinfo;
@@ -5740,7 +5740,8 @@
 	struct pkt_attrib			*pattrib;
 	unsigned char					*pframe;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short				*fctrl, *qc;
+	__le16 *fctrl;
+	unsigned short *qc;
 	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
@@ -5860,7 +5861,7 @@
 	struct pkt_attrib			*pattrib;
 	unsigned char					*pframe;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short				*fctrl;
+	__le16 *fctrl;
 	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
@@ -5972,7 +5973,7 @@
 	struct pkt_attrib			*pattrib;
 	unsigned char				*pframe;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short			*fctrl;
+	__le16 *fctrl;
 	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
 
@@ -6040,7 +6041,7 @@
 	struct pkt_attrib *pattrib;
 	u8 *pframe;
 	struct rtw_ieee80211_hdr *pwlanhdr;
-	u16 *fctrl;
+	__le16 *fctrl;
 	struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
 	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
 	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
@@ -6162,7 +6163,7 @@
 	struct pkt_attrib			*pattrib;
 	unsigned char				*pframe;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short			*fctrl;
+	__le16 *fctrl;
 	struct	wlan_network	*pnetwork = NULL;
 	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
@@ -6698,7 +6699,7 @@
 		}
 	}
 
-	/*  mark bss info receving from nearby channel as SignalQuality 101 */
+	/*  mark bss info receiving from nearby channel as SignalQuality 101 */
 	if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
 		bssid->PhyInfo.SignalQuality = 101;
 	return _SUCCESS;
@@ -8110,7 +8111,7 @@
 		Save_DM_Func_Flag(padapter);
 		Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
 
-		/* config the initial gain under scaning, need to write the BB registers */
+		/* config the initial gain under scanning, need to write the BB registers */
 #ifdef CONFIG_88EU_P2P
 		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
 			initialgain = 0x1E;
diff --git a/drivers/staging/rtl8188eu/core/rtw_p2p.c b/drivers/staging/rtl8188eu/core/rtw_p2p.c
index 8cf915f..f46cab1 100644
--- a/drivers/staging/rtl8188eu/core/rtw_p2p.c
+++ b/drivers/staging/rtl8188eu/core/rtw_p2p.c
@@ -135,7 +135,7 @@
 	struct pkt_attrib			*pattrib;
 	unsigned char					*pframe;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short				*fctrl;
+	__le16 *fctrl;
 	struct adapter *padapter = pwdinfo->padapter;
 	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
@@ -192,7 +192,7 @@
 	struct pkt_attrib			*pattrib;
 	unsigned char					*pframe;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short				*fctrl;
+	__le16 *fctrl;
 	struct adapter *padapter = pwdinfo->padapter;
 	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
@@ -272,7 +272,7 @@
 	struct pkt_attrib			*pattrib;
 	unsigned char					*pframe;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short				*fctrl;
+	__le16 *fctrl;
 	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
 
@@ -342,7 +342,7 @@
 	struct pkt_attrib			*pattrib;
 	unsigned char					*pframe;
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	unsigned short				*fctrl;
+	__le16 *fctrl;
 	struct adapter *padapter = pwdinfo->padapter;
 	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
 	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
diff --git a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
index 58a1661..b45461f 100644
--- a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
+++ b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
@@ -193,7 +193,7 @@
 	if (pwrpriv->ips_mode_req == IPS_NONE)
 		goto exit;
 
-	if (rtw_pwr_unassociated_idle(padapter) == false)
+	if (!rtw_pwr_unassociated_idle(padapter))
 		goto exit;
 
 	if ((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts%4) == 0)) {
diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c
index 2011657..9f0f30f7 100644
--- a/drivers/staging/rtl8188eu/core/rtw_recv.c
+++ b/drivers/staging/rtl8188eu/core/rtw_recv.c
@@ -204,11 +204,14 @@
 int rtw_free_recvframe(union recv_frame *precvframe, struct __queue *pfree_recv_queue)
 {
 	unsigned long irqL;
-	struct adapter *padapter = precvframe->u.hdr.adapter;
-	struct recv_priv *precvpriv = &padapter->recvpriv;
+	struct adapter *padapter;
+	struct recv_priv *precvpriv;
 
 _func_enter_;
-
+	if (!precvframe)
+		return _FAIL;
+	padapter = precvframe->u.hdr.adapter;
+	precvpriv = &padapter->recvpriv;
 	if (precvframe->u.hdr.pkt) {
 		dev_kfree_skb_any(precvframe->u.hdr.pkt);/* free skb by driver */
 		precvframe->u.hdr.pkt = NULL;
@@ -1583,7 +1586,7 @@
 
 		pfhdr->attrib.icv_len = pnfhdr->attrib.icv_len;
 		plist = get_next(plist);
-	};
+	}
 
 	/* free the defrag_q queue and return the prframe */
 	rtw_free_recvframe_queue(defrag_q, pfree_recv_queue);
@@ -1798,16 +1801,14 @@
 			memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst, ETH_ALEN);
 		}
 
-		/* Indicat the packets to upper layer */
-		if (sub_skb) {
-			/*  Insert NAT2.5 RX here! */
-			sub_skb->protocol = eth_type_trans(sub_skb, padapter->pnetdev);
-			sub_skb->dev = padapter->pnetdev;
+		/* Indicate the packets to upper layer */
+		/*  Insert NAT2.5 RX here! */
+		sub_skb->protocol = eth_type_trans(sub_skb, padapter->pnetdev);
+		sub_skb->dev = padapter->pnetdev;
 
-			sub_skb->ip_summed = CHECKSUM_NONE;
+		sub_skb->ip_summed = CHECKSUM_NONE;
 
-			netif_rx(sub_skb);
-		}
+		netif_rx(sub_skb);
 	}
 
 exit:
diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c
index 0f076d0..e088457 100644
--- a/drivers/staging/rtl8188eu/core/rtw_security.c
+++ b/drivers/staging/rtl8188eu/core/rtw_security.c
@@ -916,7 +916,7 @@
 			add1b[i] = 0x00;
 	}
 
-	swap_halfs[0] = in[2];    /* Swap halfs */
+	swap_halfs[0] = in[2];    /* Swap halves */
 	swap_halfs[1] = in[3];
 	swap_halfs[2] = in[0];
 	swap_halfs[3] = in[1];
diff --git a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c
index c2977be..cd3c9a7 100644
--- a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c
+++ b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c
@@ -267,9 +267,8 @@
 
 		rtw_mfree_sta_priv_lock(pstapriv);
 
-		if (pstapriv->pallocated_stainfo_buf) {
+		if (pstapriv->pallocated_stainfo_buf)
 			rtw_vmfree(pstapriv->pallocated_stainfo_buf, sizeof(struct sta_info)*NUM_STA+4);
-		}
 	}
 
 _func_exit_;
@@ -315,7 +314,7 @@
 
 		rtw_list_insert_tail(&psta->hash_list, phash_list);
 
-		pstapriv->asoc_sta_count++ ;
+		pstapriv->asoc_sta_count++;
 
 		_exit_critical_bh(&(pstapriv->sta_hash_lock), &irql2);
 
@@ -419,7 +418,7 @@
 	_cancel_timer_ex(&psta->addba_retry_timer);
 
 	/* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */
-	for (i = 0; i < 16 ; i++) {
+	for (i = 0; i < 16; i++) {
 		unsigned long irql;
 		struct list_head *phead, *plist;
 		union recv_frame *prframe;
diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
index 8018edd..153ec61 100644
--- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
+++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
@@ -80,7 +80,7 @@
 	for (i = 0; i < ratelen; i++) {
 		if  ((((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
 			   (((rate[i]) & 0x7f) != 11)  && (((rate[i]) & 0x7f) != 22))
-		return false;
+			return false;
 	}
 
 	return true;
@@ -766,7 +766,7 @@
 
 	for (i = 0; i < (pIE->Length); i++) {
 		if (i != 2) {
-			/* 	Got the endian issue here. */
+			/*	Got the endian issue here. */
 			pmlmeinfo->HT_caps.u.HT_cap[i] &= (pIE->data[i]);
 		} else {
 			/* modify from  fw by Thomas 2010/11/17 */
@@ -1096,13 +1096,13 @@
 	}
 
 	kfree(bssid);
+	_func_exit_;
 	return _SUCCESS;
 
 _mismatch:
 	kfree(bssid);
-	return _FAIL;
-
 	_func_exit_;
+	return _FAIL;
 }
 
 void update_beacon_info(struct adapter *padapter, u8 *pframe, uint pkt_len, struct sta_info *psta)
@@ -1186,7 +1186,7 @@
 			case _RSN_IE_2_:
 				if  ((_rtw_memcmp((pIE->data + 8), RSN_CIPHER_SUITE_CCMP, 4))  ||
 				       (_rtw_memcmp((pIE->data + 12), RSN_CIPHER_SUITE_CCMP, 4)))
-				return false;
+					return false;
 			default:
 				break;
 			}
@@ -1368,21 +1368,21 @@
 #ifdef CONFIG_88EU_P2P
 	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
 
-	/* 	Added by Albert 2011/03/22 */
-	/* 	In the P2P mode, the driver should not support the b mode. */
-	/* 	So, the Tx packet shouldn't use the CCK rate */
+	/*	Added by Albert 2011/03/22 */
+	/*	In the P2P mode, the driver should not support the b mode. */
+	/*	So, the Tx packet shouldn't use the CCK rate */
 	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
 		return;
 #endif /* CONFIG_88EU_P2P */
 	_rtw_memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
 
-	if ((wirelessmode & WIRELESS_11B) && (wirelessmode == WIRELESS_11B)) {
+	if ((wirelessmode & WIRELESS_11B) && (wirelessmode == WIRELESS_11B))
 		memcpy(supported_rates, rtw_basic_rate_cck, 4);
-	} else if (wirelessmode & WIRELESS_11B) {
+	else if (wirelessmode & WIRELESS_11B)
 		memcpy(supported_rates, rtw_basic_rate_mix, 7);
-	} else {
+	else
 		memcpy(supported_rates, rtw_basic_rate_ofdm, 3);
-	}
+
 
 	if (wirelessmode & WIRELESS_11B)
 		update_mgnt_tx_rate(padapter, IEEE80211_CCK_RATE_1MB);
@@ -1435,7 +1435,7 @@
 				DBG_88E("link to Airgo Cap\n");
 				return HT_IOT_PEER_AIRGO;
 			} else if (_rtw_memcmp(pIE->data, EPIGRAM_OUI, 3)) {
-				 epigram_vendor_flag = 1;
+				epigram_vendor_flag = 1;
 				if (ralink_vendor_flag) {
 					DBG_88E("link to Tenda W311R AP\n");
 					 return HT_IOT_PEER_TENDA;
diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c
index bb5cd95..a594e51 100644
--- a/drivers/staging/rtl8188eu/core/rtw_xmit.c
+++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c
@@ -1556,7 +1556,7 @@
 	xmitframe_phead = get_list_head(pframe_queue);
 	xmitframe_plist = get_next(xmitframe_phead);
 
-	while (!rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
+	if (!rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
 		pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
 
 		xmitframe_plist = get_next(xmitframe_plist);
@@ -1564,12 +1564,7 @@
 		rtw_list_delete(&pxmitframe->list);
 
 		ptxservq->qcnt--;
-
-		break;
-
-		pxmitframe = NULL;
 	}
-
 	return pxmitframe;
 }
 
diff --git a/drivers/staging/rtl8188eu/hal/Hal8188EFWImg_CE.c b/drivers/staging/rtl8188eu/hal/Hal8188EFWImg_CE.c
deleted file mode 100644
index 95759be..0000000
--- a/drivers/staging/rtl8188eu/hal/Hal8188EFWImg_CE.c
+++ /dev/null
@@ -1,1761 +0,0 @@
-/******************************************************************************
-*
-* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
-*
-* This program is free software; you can redistribute it and/or modify it
-* under the terms of version 2 of the GNU General Public License as
-* published by the Free Software Foundation.
-*
-* This program is distributed in the hope that it will be useful, but WITHOUT
-* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-* more details.
-*
-* You should have received a copy of the GNU General Public License along with
-* this program; if not, write to the Free Software Foundation, Inc.,
-* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-*
-*
-******************************************************************************/
-#include "odm_precomp.h"
-
-const u8 Rtl8188EFwImgArray[Rtl8188EFWImgArrayLength] = {
-	0xE1, 0x88, 0x10, 0x00, 0x0B, 0x00, 0x01, 0x00,
-	0x01, 0x21, 0x11, 0x27, 0x30, 0x36, 0x00, 0x00,
-	0x2D, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x02, 0x45, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0xC1, 0x6F, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0xA1, 0xE6, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x02, 0x56, 0xF7, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0xC2, 0xAF, 0x80, 0xFE, 0x32, 0x12, 0x42, 0x04,
-	0x85, 0xD0, 0x0B, 0x75, 0xD0, 0x08, 0xAA, 0xE0,
-	0xC2, 0x8C, 0xE5, 0x8A, 0x24, 0x67, 0xF5, 0x8A,
-	0xE5, 0x8C, 0x34, 0x79, 0xF5, 0x8C, 0xD2, 0x8C,
-	0xEC, 0x24, 0x89, 0xF8, 0xE6, 0xBC, 0x03, 0x02,
-	0x74, 0xFF, 0xC3, 0x95, 0x81, 0xB4, 0x40, 0x00,
-	0x40, 0xCE, 0x79, 0x04, 0x78, 0x80, 0x16, 0xE6,
-	0x08, 0x70, 0x0B, 0xC2, 0xAF, 0xE6, 0x30, 0xE1,
-	0x03, 0x44, 0x18, 0xF6, 0xD2, 0xAF, 0x08, 0xD9,
-	0xED, 0xEA, 0x8B, 0xD0, 0x22, 0xE5, 0x0C, 0xFF,
-	0x23, 0x24, 0x81, 0xF8, 0x0F, 0x08, 0x08, 0xBF,
-	0x04, 0x04, 0x7F, 0x00, 0x78, 0x81, 0xE6, 0x30,
-	0xE4, 0xF2, 0x00, 0xE5, 0x0C, 0xC3, 0x9F, 0x50,
-	0x20, 0x05, 0x0C, 0x74, 0x88, 0x25, 0x0C, 0xF8,
-	0xE6, 0xFD, 0xA6, 0x81, 0x08, 0xE6, 0xAE, 0x0C,
-	0xBE, 0x03, 0x02, 0x74, 0xFF, 0xCD, 0xF8, 0xE8,
-	0x6D, 0x60, 0xE0, 0x08, 0xE6, 0xC0, 0xE0, 0x80,
-	0xF6, 0xE5, 0x0C, 0xD3, 0x9F, 0x40, 0x27, 0xE5,
-	0x0C, 0x24, 0x89, 0xF8, 0xE6, 0xAE, 0x0C, 0xBE,
-	0x03, 0x02, 0x74, 0xFF, 0xFD, 0x18, 0xE6, 0xCD,
-	0xF8, 0xE5, 0x81, 0x6D, 0x60, 0x06, 0xD0, 0xE0,
-	0xF6, 0x18, 0x80, 0xF5, 0xE5, 0x0C, 0x24, 0x88,
-	0xC8, 0xF6, 0x15, 0x0C, 0x80, 0xD3, 0xE5, 0x0C,
-	0x23, 0x24, 0x81, 0xF8, 0x7F, 0x04, 0xC2, 0xAF,
-	0xE6, 0x30, 0xE0, 0x03, 0x10, 0xE2, 0x0C, 0x7F,
-	0x00, 0x30, 0xE1, 0x07, 0x30, 0xE3, 0x04, 0x7F,
-	0x08, 0x54, 0xF4, 0x54, 0x7C, 0xC6, 0xD2, 0xAF,
-	0x54, 0x80, 0x42, 0x07, 0x22, 0x78, 0x88, 0xA6,
-	0x81, 0x74, 0x03, 0x60, 0x06, 0xFF, 0x08, 0x76,
-	0xFF, 0xDF, 0xFB, 0x7F, 0x04, 0xE4, 0x78, 0x80,
-	0xF6, 0x08, 0xF6, 0x08, 0xDF, 0xFA, 0x78, 0x81,
-	0x76, 0x30, 0x90, 0x45, 0xDE, 0x74, 0x01, 0x93,
-	0xC0, 0xE0, 0xE4, 0x93, 0xC0, 0xE0, 0x43, 0x89,
-	0x01, 0x75, 0x8A, 0x60, 0x75, 0x8C, 0x79, 0xD2,
-	0x8C, 0xD2, 0xAF, 0x22, 0x03, 0xEF, 0xD3, 0x94,
-	0x03, 0x40, 0x03, 0x7F, 0xFF, 0x22, 0x74, 0x81,
-	0x2F, 0x2F, 0xF8, 0xE6, 0x20, 0xE5, 0xF4, 0xC2,
-	0xAF, 0xE6, 0x44, 0x30, 0xF6, 0xD2, 0xAF, 0xAE,
-	0x0C, 0xEE, 0xC3, 0x9F, 0x50, 0x21, 0x0E, 0x74,
-	0x88, 0x2E, 0xF8, 0xE6, 0xF9, 0x08, 0xE6, 0x18,
-	0xBE, 0x03, 0x02, 0x74, 0xFF, 0xFD, 0xED, 0x69,
-	0x60, 0x09, 0x09, 0xE7, 0x19, 0x19, 0xF7, 0x09,
-	0x09, 0x80, 0xF3, 0x16, 0x16, 0x80, 0xDA, 0xEE,
-	0xD3, 0x9F, 0x40, 0x04, 0x05, 0x81, 0x05, 0x81,
-	0xEE, 0xD3, 0x9F, 0x40, 0x22, 0x74, 0x88, 0x2E,
-	0xF8, 0x08, 0xE6, 0xF9, 0xEE, 0xB5, 0x0C, 0x02,
-	0xA9, 0x81, 0x18, 0x06, 0x06, 0xE6, 0xFD, 0xED,
-	0x69, 0x60, 0x09, 0x19, 0x19, 0xE7, 0x09, 0x09,
-	0xF7, 0x19, 0x80, 0xF3, 0x1E, 0x80, 0xD9, 0xEF,
-	0x24, 0x88, 0xF8, 0xE6, 0x04, 0xF8, 0xEF, 0x2F,
-	0x04, 0x90, 0x45, 0xDE, 0x93, 0xF6, 0x08, 0xEF,
-	0x2F, 0x93, 0xF6, 0x7F, 0x00, 0x22, 0xEF, 0xD3,
-	0x94, 0x03, 0x40, 0x03, 0x7F, 0xFF, 0x22, 0xEF,
-	0x23, 0x24, 0x81, 0xF8, 0xE6, 0x30, 0xE5, 0xF4,
-	0xC2, 0xAF, 0xE6, 0x54, 0x8C, 0xF6, 0xD2, 0xAF,
-	0xE5, 0x0C, 0xB5, 0x07, 0x0A, 0x74, 0x88, 0x2F,
-	0xF8, 0xE6, 0xF5, 0x81, 0x02, 0x42, 0x4D, 0x50,
-	0x2E, 0x74, 0x89, 0x2F, 0xF8, 0xE6, 0xBF, 0x03,
-	0x02, 0x74, 0xFF, 0xFD, 0x18, 0xE6, 0xF9, 0x74,
-	0x88, 0x2F, 0xF8, 0xFB, 0xE6, 0xFC, 0xE9, 0x6C,
-	0x60, 0x08, 0xA8, 0x05, 0xE7, 0xF6, 0x1D, 0x19,
-	0x80, 0xF4, 0xA8, 0x03, 0xA6, 0x05, 0x1F, 0xE5,
-	0x0C, 0xB5, 0x07, 0xE3, 0x7F, 0x00, 0x22, 0x74,
-	0x89, 0x2F, 0xF8, 0xE6, 0xFD, 0x18, 0x86, 0x01,
-	0x0F, 0x74, 0x88, 0x2F, 0xF8, 0xA6, 0x01, 0x08,
-	0x86, 0x04, 0xE5, 0x0C, 0xB5, 0x07, 0x02, 0xAC,
-	0x81, 0xED, 0x6C, 0x60, 0x08, 0x0D, 0x09, 0xA8,
-	0x05, 0xE6, 0xF7, 0x80, 0xF4, 0xE5, 0x0C, 0xB5,
-	0x07, 0xDE, 0x89, 0x81, 0x7F, 0x00, 0x22, 0xEF,
-	0xD3, 0x94, 0x03, 0x40, 0x03, 0x7F, 0xFF, 0x22,
-	0xEF, 0x23, 0x24, 0x81, 0xF8, 0xC2, 0xAF, 0xE6,
-	0x30, 0xE5, 0x05, 0x30, 0xE0, 0x02, 0xD2, 0xE4,
-	0xD2, 0xE2, 0xC6, 0xD2, 0xAF, 0x7F, 0x00, 0x30,
-	0xE2, 0x01, 0x0F, 0x02, 0x42, 0x4C, 0x8F, 0xF0,
-	0xE4, 0xFF, 0xFE, 0xE5, 0x0C, 0x23, 0x24, 0x80,
-	0xF8, 0xC2, 0xA9, 0x30, 0xF7, 0x0D, 0x7F, 0x08,
-	0xE6, 0x60, 0x0B, 0x2D, 0xF6, 0x60, 0x30, 0x50,
-	0x2E, 0x80, 0x07, 0x30, 0xF1, 0x06, 0xED, 0xF6,
-	0x60, 0x25, 0x7E, 0x02, 0x08, 0x30, 0xF0, 0x10,
-	0xC2, 0xAF, 0xE6, 0x10, 0xE7, 0x23, 0x0E, 0x30,
-	0xE2, 0x0C, 0xD2, 0xAF, 0x7F, 0x04, 0x80, 0x12,
-	0xC2, 0xAF, 0xE6, 0x10, 0xE7, 0x13, 0x54, 0xEC,
-	0x4E, 0xF6, 0xD2, 0xAF, 0x02, 0x42, 0x4D, 0x7F,
-	0x08, 0x08, 0xEF, 0x44, 0x83, 0xF4, 0xC2, 0xAF,
-	0x56, 0xC6, 0xD2, 0xAF, 0x54, 0x80, 0x4F, 0xFF,
-	0x22, 0xC5, 0xF0, 0xF8, 0xA3, 0xE0, 0x28, 0xF0,
-	0xC5, 0xF0, 0xF8, 0xE5, 0x82, 0x15, 0x82, 0x70,
-	0x02, 0x15, 0x83, 0xE0, 0x38, 0xF0, 0x22, 0xEF,
-	0x5B, 0xFF, 0xEE, 0x5A, 0xFE, 0xED, 0x59, 0xFD,
-	0xEC, 0x58, 0xFC, 0x22, 0xEF, 0x4B, 0xFF, 0xEE,
-	0x4A, 0xFE, 0xED, 0x49, 0xFD, 0xEC, 0x48, 0xFC,
-	0x22, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0,
-	0xFE, 0xA3, 0xE0, 0xFF, 0x22, 0xE2, 0xFC, 0x08,
-	0xE2, 0xFD, 0x08, 0xE2, 0xFE, 0x08, 0xE2, 0xFF,
-	0x22, 0xE2, 0xFB, 0x08, 0xE2, 0xF9, 0x08, 0xE2,
-	0xFA, 0x08, 0xE2, 0xCB, 0xF8, 0x22, 0xEC, 0xF2,
-	0x08, 0xED, 0xF2, 0x08, 0xEE, 0xF2, 0x08, 0xEF,
-	0xF2, 0x22, 0xA4, 0x25, 0x82, 0xF5, 0x82, 0xE5,
-	0xF0, 0x35, 0x83, 0xF5, 0x83, 0x22, 0xE0, 0xFB,
-	0xA3, 0xE0, 0xFA, 0xA3, 0xE0, 0xF9, 0x22, 0xEB,
-	0xF0, 0xA3, 0xEA, 0xF0, 0xA3, 0xE9, 0xF0, 0x22,
-	0xD0, 0x83, 0xD0, 0x82, 0xF8, 0xE4, 0x93, 0x70,
-	0x12, 0x74, 0x01, 0x93, 0x70, 0x0D, 0xA3, 0xA3,
-	0x93, 0xF8, 0x74, 0x01, 0x93, 0xF5, 0x82, 0x88,
-	0x83, 0xE4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60,
-	0xEF, 0xA3, 0xA3, 0xA3, 0x80, 0xDF, 0x02, 0x45,
-	0x8C, 0x02, 0x42, 0xDD, 0xE4, 0x93, 0xA3, 0xF8,
-	0xE4, 0x93, 0xA3, 0x40, 0x03, 0xF6, 0x80, 0x01,
-	0xF2, 0x08, 0xDF, 0xF4, 0x80, 0x29, 0xE4, 0x93,
-	0xA3, 0xF8, 0x54, 0x07, 0x24, 0x0C, 0xC8, 0xC3,
-	0x33, 0xC4, 0x54, 0x0F, 0x44, 0x20, 0xC8, 0x83,
-	0x40, 0x04, 0xF4, 0x56, 0x80, 0x01, 0x46, 0xF6,
-	0xDF, 0xE4, 0x80, 0x0B, 0x01, 0x02, 0x04, 0x08,
-	0x10, 0x20, 0x40, 0x80, 0x90, 0x45, 0xD1, 0xE4,
-	0x7E, 0x01, 0x93, 0x60, 0xBC, 0xA3, 0xFF, 0x54,
-	0x3F, 0x30, 0xE5, 0x09, 0x54, 0x1F, 0xFE, 0xE4,
-	0x93, 0xA3, 0x60, 0x01, 0x0E, 0xCF, 0x54, 0xC0,
-	0x25, 0xE0, 0x60, 0xA8, 0x40, 0xB8, 0xE4, 0x93,
-	0xA3, 0xFA, 0xE4, 0x93, 0xA3, 0xF8, 0xE4, 0x93,
-	0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCA, 0xC5, 0x83,
-	0xCA, 0xF0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCA,
-	0xC5, 0x83, 0xCA, 0xDF, 0xE9, 0xDE, 0xE7, 0x80,
-	0xBE, 0x00, 0x41, 0x82, 0x09, 0x00, 0x41, 0x82,
-	0x0A, 0x00, 0x41, 0x82, 0x17, 0x00, 0x59, 0xE2,
-	0x5C, 0x24, 0x5E, 0x5D, 0x5F, 0xA1, 0xC0, 0xE0,
-	0xC0, 0xF0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, 0xD0,
-	0x75, 0xD0, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0,
-	0x02, 0xC0, 0x03, 0xC0, 0x04, 0xC0, 0x05, 0xC0,
-	0x06, 0xC0, 0x07, 0x90, 0x01, 0xC4, 0x74, 0xE6,
-	0xF0, 0x74, 0x45, 0xA3, 0xF0, 0xD1, 0x35, 0x74,
-	0xE6, 0x04, 0x90, 0x01, 0xC4, 0xF0, 0x74, 0x45,
-	0xA3, 0xF0, 0xD0, 0x07, 0xD0, 0x06, 0xD0, 0x05,
-	0xD0, 0x04, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01,
-	0xD0, 0x00, 0xD0, 0xD0, 0xD0, 0x82, 0xD0, 0x83,
-	0xD0, 0xF0, 0xD0, 0xE0, 0x32, 0x90, 0x00, 0x54,
-	0xE0, 0x55, 0x35, 0xF5, 0x39, 0xA3, 0xE0, 0x55,
-	0x36, 0xF5, 0x3A, 0xA3, 0xE0, 0x55, 0x37, 0xF5,
-	0x3B, 0xA3, 0xE0, 0x55, 0x38, 0xF5, 0x3C, 0xAD,
-	0x39, 0x7F, 0x54, 0x12, 0x32, 0x1E, 0xAD, 0x3A,
-	0x7F, 0x55, 0x12, 0x32, 0x1E, 0xAD, 0x3B, 0x7F,
-	0x56, 0x12, 0x32, 0x1E, 0xAD, 0x3C, 0x7F, 0x57,
-	0x12, 0x32, 0x1E, 0x53, 0x91, 0xEF, 0x22, 0xC0,
-	0xE0, 0xC0, 0xF0, 0xC0, 0x83, 0xC0, 0x82, 0xC0,
-	0xD0, 0x75, 0xD0, 0x00, 0xC0, 0x00, 0xC0, 0x01,
-	0xC0, 0x02, 0xC0, 0x03, 0xC0, 0x04, 0xC0, 0x05,
-	0xC0, 0x06, 0xC0, 0x07, 0x90, 0x01, 0xC4, 0x74,
-	0x6F, 0xF0, 0x74, 0x46, 0xA3, 0xF0, 0x12, 0x6C,
-	0x78, 0xE5, 0x41, 0x30, 0xE4, 0x04, 0x7F, 0x02,
-	0x91, 0x27, 0xE5, 0x41, 0x30, 0xE6, 0x03, 0x12,
-	0x6C, 0xD5, 0xE5, 0x43, 0x30, 0xE0, 0x03, 0x12,
-	0x51, 0xC2, 0xE5, 0x43, 0x30, 0xE1, 0x03, 0x12,
-	0x4D, 0x0C, 0xE5, 0x43, 0x30, 0xE2, 0x03, 0x12,
-	0x4C, 0xC1, 0xE5, 0x43, 0x30, 0xE3, 0x03, 0x12,
-	0x6C, 0xE2, 0xE5, 0x43, 0x30, 0xE4, 0x03, 0x12,
-	0x6D, 0x04, 0xE5, 0x43, 0x30, 0xE5, 0x03, 0x12,
-	0x6D, 0x33, 0xE5, 0x43, 0x30, 0xE6, 0x02, 0xF1,
-	0x0F, 0xE5, 0x44, 0x30, 0xE1, 0x03, 0x12, 0x51,
-	0x7F, 0x74, 0x6F, 0x04, 0x90, 0x01, 0xC4, 0xF0,
-	0x74, 0x46, 0xA3, 0xF0, 0xD0, 0x07, 0xD0, 0x06,
-	0xD0, 0x05, 0xD0, 0x04, 0xD0, 0x03, 0xD0, 0x02,
-	0xD0, 0x01, 0xD0, 0x00, 0xD0, 0xD0, 0xD0, 0x82,
-	0xD0, 0x83, 0xD0, 0xF0, 0xD0, 0xE0, 0x32, 0x90,
-	0x80, 0xDE, 0xE0, 0xB4, 0x01, 0x13, 0x90, 0x81,
-	0x27, 0xE0, 0x60, 0x0D, 0x90, 0x81, 0x2B, 0xE0,
-	0x54, 0xFE, 0xF0, 0x54, 0x07, 0x70, 0x02, 0xF1,
-	0x2A, 0x22, 0x90, 0x81, 0x1F, 0xE0, 0x90, 0x81,
-	0x29, 0x30, 0xE0, 0x05, 0xE0, 0xFF, 0x02, 0x74,
-	0x8F, 0xE0, 0xFF, 0x7D, 0x01, 0xD3, 0x10, 0xAF,
-	0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x82, 0x13, 0xED,
-	0xF0, 0x90, 0x81, 0x2A, 0xE0, 0x90, 0x82, 0x14,
-	0xF0, 0x90, 0x81, 0x24, 0xE0, 0xFE, 0xC4, 0x13,
-	0x13, 0x54, 0x03, 0x30, 0xE0, 0x03, 0x02, 0x48,
-	0xA0, 0xEE, 0xC4, 0x13, 0x13, 0x13, 0x54, 0x01,
-	0x30, 0xE0, 0x03, 0x02, 0x48, 0xA0, 0x90, 0x82,
-	0x14, 0xE0, 0xFE, 0x6F, 0x70, 0x03, 0x02, 0x48,
-	0xA0, 0xEF, 0x70, 0x03, 0x02, 0x48, 0x17, 0x24,
-	0xFE, 0x70, 0x03, 0x02, 0x48, 0x50, 0x24, 0xFE,
-	0x60, 0x51, 0x24, 0xFC, 0x70, 0x03, 0x02, 0x48,
-	0x8B, 0x24, 0xFC, 0x60, 0x03, 0x02, 0x48, 0xA0,
-	0xEE, 0xB4, 0x0E, 0x03, 0x12, 0x49, 0x5E, 0x90,
-	0x82, 0x14, 0xE0, 0x70, 0x05, 0x7F, 0x01, 0x12,
-	0x49, 0x93, 0x90, 0x82, 0x14, 0xE0, 0xB4, 0x06,
-	0x03, 0x12, 0x49, 0x34, 0x90, 0x82, 0x14, 0xE0,
-	0xB4, 0x04, 0x0F, 0x90, 0x82, 0x13, 0xE0, 0xFF,
-	0x60, 0x05, 0x12, 0x73, 0x75, 0x80, 0x03, 0x12,
-	0x66, 0x26, 0x90, 0x82, 0x14, 0xE0, 0x64, 0x08,
-	0x60, 0x03, 0x02, 0x48, 0xA0, 0x12, 0x73, 0xD3,
-	0x02, 0x48, 0xA0, 0x90, 0x82, 0x14, 0xE0, 0x70,
-	0x05, 0x7F, 0x01, 0x12, 0x49, 0x93, 0x90, 0x82,
-	0x14, 0xE0, 0xB4, 0x06, 0x03, 0x12, 0x49, 0x34,
-	0x90, 0x82, 0x14, 0xE0, 0xB4, 0x0E, 0x09, 0x12,
-	0x48, 0xA5, 0xBF, 0x01, 0x03, 0x12, 0x49, 0x5E,
-	0x90, 0x82, 0x14, 0xE0, 0x64, 0x0C, 0x60, 0x02,
-	0x01, 0xA0, 0x11, 0xA5, 0xEF, 0x64, 0x01, 0x60,
-	0x02, 0x01, 0xA0, 0x11, 0xFA, 0x01, 0xA0, 0x90,
-	0x82, 0x14, 0xE0, 0xB4, 0x0E, 0x07, 0x11, 0xA5,
-	0xBF, 0x01, 0x02, 0x31, 0x5E, 0x90, 0x82, 0x14,
-	0xE0, 0xB4, 0x06, 0x02, 0x31, 0x34, 0x90, 0x82,
-	0x14, 0xE0, 0xB4, 0x0C, 0x07, 0x11, 0xA5, 0xBF,
-	0x01, 0x02, 0x11, 0xFA, 0x90, 0x82, 0x14, 0xE0,
-	0x64, 0x04, 0x70, 0x5C, 0x12, 0x72, 0xF5, 0xEF,
-	0x64, 0x01, 0x70, 0x54, 0x31, 0xBE, 0x80, 0x50,
-	0x90, 0x82, 0x14, 0xE0, 0xB4, 0x0E, 0x07, 0x11,
-	0xA5, 0xBF, 0x01, 0x02, 0x31, 0x5E, 0x90, 0x82,
-	0x14, 0xE0, 0xB4, 0x06, 0x02, 0x31, 0x34, 0x90,
-	0x82, 0x14, 0xE0, 0xB4, 0x0C, 0x07, 0x11, 0xA5,
-	0xBF, 0x01, 0x02, 0x11, 0xFA, 0x90, 0x82, 0x14,
-	0xE0, 0x70, 0x04, 0x7F, 0x01, 0x31, 0x93, 0x90,
-	0x82, 0x14, 0xE0, 0xB4, 0x04, 0x1A, 0x12, 0x73,
-	0xBB, 0x80, 0x15, 0x90, 0x82, 0x14, 0xE0, 0xB4,
-	0x0C, 0x0E, 0x90, 0x81, 0x25, 0xE0, 0xFF, 0x13,
-	0x13, 0x54, 0x3F, 0x30, 0xE0, 0x02, 0x31, 0xB1,
-	0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD1, 0xAB, 0xEF,
-	0x64, 0x01, 0x60, 0x08, 0x90, 0x01, 0xB8, 0x74,
-	0x01, 0xF0, 0x80, 0x3D, 0x90, 0x81, 0x24, 0xE0,
-	0xFF, 0x13, 0x13, 0x13, 0x54, 0x1F, 0x30, 0xE0,
-	0x08, 0x90, 0x01, 0xB8, 0x74, 0x02, 0xF0, 0x80,
-	0x28, 0xEF, 0xC4, 0x54, 0x0F, 0x30, 0xE0, 0x08,
-	0x90, 0x01, 0xB8, 0x74, 0x04, 0xF0, 0x80, 0x19,
-	0x90, 0x81, 0x29, 0xE0, 0xD3, 0x94, 0x04, 0x40,
-	0x08, 0x90, 0x01, 0xB8, 0x74, 0x08, 0xF0, 0x80,
-	0x08, 0x90, 0x01, 0xB8, 0xE4, 0xF0, 0x7F, 0x01,
-	0x22, 0x90, 0x01, 0xB9, 0x74, 0x02, 0xF0, 0x7F,
-	0x00, 0x22, 0x90, 0x80, 0xDE, 0xE0, 0x64, 0x01,
-	0x70, 0x31, 0x90, 0x81, 0x25, 0xE0, 0x54, 0xFD,
-	0xF0, 0x90, 0x05, 0x22, 0x74, 0x6F, 0xF0, 0x7F,
-	0x01, 0xF1, 0x0D, 0xBF, 0x01, 0x12, 0x90, 0x81,
-	0x24, 0xE0, 0x44, 0x80, 0xF0, 0x90, 0x81, 0x2A,
-	0x74, 0x0E, 0xF0, 0x90, 0x81, 0x23, 0xF0, 0x22,
-	0x90, 0x01, 0xB9, 0x74, 0x01, 0xF0, 0x90, 0x01,
-	0xB8, 0x04, 0xF0, 0x22, 0x90, 0x81, 0x25, 0xE0,
-	0x90, 0x06, 0x04, 0x20, 0xE0, 0x0C, 0xE0, 0x44,
-	0x40, 0xF0, 0x90, 0x81, 0x2A, 0x74, 0x04, 0xF0,
-	0x80, 0x0E, 0xE0, 0x54, 0x7F, 0xF0, 0x90, 0x81,
-	0x2A, 0x74, 0x0C, 0xF0, 0x90, 0x81, 0x23, 0xF0,
-	0x90, 0x05, 0x22, 0xE4, 0xF0, 0x22, 0x90, 0x81,
-	0x25, 0xE0, 0xC3, 0x13, 0x20, 0xE0, 0x08, 0x90,
-	0x81, 0x2A, 0x74, 0x0C, 0xF0, 0x80, 0x1E, 0x90,
-	0x06, 0x04, 0xE0, 0x44, 0x40, 0xF0, 0xE0, 0x44,
-	0x80, 0xF0, 0x90, 0x81, 0x2A, 0x74, 0x04, 0xF0,
-	0x90, 0x05, 0x27, 0xE0, 0x44, 0x80, 0xF0, 0x90,
-	0x81, 0x23, 0x74, 0x04, 0xF0, 0x90, 0x05, 0x22,
-	0xE4, 0xF0, 0x22, 0x90, 0x82, 0x15, 0xEF, 0xF0,
-	0x12, 0x54, 0x65, 0x90, 0x82, 0x15, 0xE0, 0x60,
-	0x05, 0x90, 0x05, 0x22, 0xE4, 0xF0, 0x90, 0x81,
-	0x2A, 0x74, 0x04, 0xF0, 0x90, 0x81, 0x23, 0xF0,
-	0x22, 0x31, 0xE3, 0x90, 0x81, 0x2A, 0x74, 0x08,
-	0xF0, 0x90, 0x81, 0x23, 0xF0, 0x22, 0x90, 0x05,
-	0x22, 0x74, 0xFF, 0xF0, 0xF1, 0x3A, 0x90, 0x01,
-	0x37, 0x74, 0x02, 0xF0, 0xFD, 0x7F, 0x03, 0x51,
-	0x57, 0x31, 0xE3, 0xE4, 0x90, 0x81, 0x2A, 0xF0,
-	0x90, 0x81, 0x23, 0xF0, 0x22, 0x90, 0x05, 0x22,
-	0x74, 0xFF, 0xF0, 0xF1, 0x3A, 0x90, 0x85, 0xBB,
-	0x12, 0x20, 0xDA, 0xCC, 0xF0, 0x00, 0xC0, 0x7F,
-	0x8C, 0x7E, 0x08, 0x12, 0x2E, 0xA2, 0x90, 0x85,
-	0xBB, 0x12, 0x20, 0xDA, 0x00, 0x00, 0x00, 0x14,
-	0x7F, 0x70, 0x7E, 0x0E, 0x12, 0x2E, 0xA2, 0x90,
-	0x81, 0xF9, 0x12, 0x20, 0xDA, 0x00, 0x00, 0x00,
-	0x00, 0xE4, 0xFD, 0xFF, 0x12, 0x55, 0x1C, 0x7F,
-	0x7C, 0x7E, 0x08, 0x12, 0x2D, 0x5C, 0xEC, 0x44,
-	0x80, 0xFC, 0x90, 0x82, 0x05, 0x12, 0x20, 0xCE,
-	0x90, 0x82, 0x05, 0x12, 0x44, 0xD9, 0x90, 0x85,
-	0xBB, 0x12, 0x20, 0xCE, 0x7F, 0x7C, 0x7E, 0x08,
-	0x12, 0x2E, 0xA2, 0x90, 0x01, 0x00, 0x74, 0x3F,
-	0xF0, 0xA3, 0xE0, 0x54, 0xFD, 0xF0, 0x90, 0x05,
-	0x53, 0xE0, 0x44, 0x20, 0xF0, 0x22, 0x90, 0x01,
-	0x34, 0x74, 0x40, 0xF0, 0xFD, 0xE4, 0xFF, 0x74,
-	0x3D, 0x2F, 0xF8, 0xE6, 0x4D, 0xFE, 0xF6, 0x74,
-	0x30, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x01, 0xF5,
-	0x83, 0xEE, 0xF0, 0x22, 0xD3, 0x10, 0xAF, 0x01,
-	0xC3, 0xC0, 0xD0, 0xE4, 0x90, 0x81, 0xCB, 0xF0,
-	0x12, 0x1F, 0xA4, 0xFF, 0x54, 0x01, 0xFE, 0x90,
-	0x81, 0x1F, 0xE0, 0x54, 0xFE, 0x4E, 0xFE, 0xF0,
-	0xEF, 0x54, 0x02, 0xFF, 0xEE, 0x54, 0xFD, 0x4F,
-	0xFF, 0xF0, 0x12, 0x1F, 0xA4, 0xFE, 0x54, 0x04,
-	0xFD, 0xEF, 0x54, 0xFB, 0x4D, 0xFF, 0x90, 0x81,
-	0x1F, 0xF0, 0xEE, 0x54, 0x08, 0xFE, 0xEF, 0x54,
-	0xF7, 0x4E, 0xFF, 0xF0, 0x12, 0x1F, 0xA4, 0xFE,
-	0x54, 0x10, 0xFD, 0xEF, 0x54, 0xEF, 0x4D, 0xFF,
-	0x90, 0x81, 0x1F, 0xF0, 0xEE, 0x54, 0x20, 0xFE,
-	0xEF, 0x54, 0xDF, 0x4E, 0xF0, 0x12, 0x1F, 0xA4,
-	0xC3, 0x13, 0x20, 0xE0, 0x02, 0x61, 0x5E, 0x90,
-	0x81, 0x1F, 0xE0, 0xFF, 0x30, 0xE0, 0x6D, 0x90,
-	0x81, 0xCB, 0x74, 0x21, 0xF0, 0xEF, 0x13, 0x13,
-	0x54, 0x3F, 0x30, 0xE0, 0x0B, 0x51, 0x4E, 0x90,
-	0x81, 0xCB, 0xE0, 0x44, 0x08, 0xF0, 0x80, 0x0C,
-	0xE4, 0x90, 0x81, 0x20, 0xF0, 0xA3, 0xF0, 0x7D,
-	0x40, 0xFF, 0x91, 0x26, 0x90, 0x81, 0x1F, 0xE0,
-	0xFD, 0x13, 0x13, 0x13, 0x54, 0x1F, 0x30, 0xE0,
-	0x07, 0x90, 0x81, 0xCB, 0xE0, 0x44, 0x12, 0xF0,
-	0xED, 0xC4, 0x54, 0x0F, 0x30, 0xE0, 0x07, 0x90,
-	0x81, 0xCB, 0xE0, 0x44, 0x14, 0xF0, 0x90, 0x81,
-	0x1F, 0xE0, 0xC4, 0x13, 0x54, 0x07, 0x30, 0xE0,
-	0x07, 0x90, 0x81, 0xCB, 0xE0, 0x44, 0x80, 0xF0,
-	0x90, 0x81, 0xCB, 0xE0, 0x90, 0x05, 0x27, 0xF0,
-	0x90, 0x81, 0x22, 0xE0, 0x60, 0x02, 0x81, 0x17,
-	0x7F, 0x01, 0x80, 0x15, 0x90, 0x81, 0xCB, 0x74,
-	0x01, 0xF0, 0x90, 0x05, 0x27, 0xF0, 0x90, 0x81,
-	0x22, 0xE0, 0x64, 0x04, 0x60, 0x02, 0x81, 0x17,
-	0xFF, 0x12, 0x53, 0x0E, 0x81, 0x17, 0x90, 0x81,
-	0x1F, 0xE0, 0xFF, 0x20, 0xE0, 0x02, 0x61, 0xE7,
-	0x90, 0x81, 0xCB, 0x74, 0x31, 0xF0, 0xEF, 0x13,
-	0x13, 0x54, 0x3F, 0x30, 0xE0, 0x0B, 0x51, 0x4E,
-	0x90, 0x81, 0xCB, 0xE0, 0x44, 0x08, 0xF0, 0x80,
-	0x06, 0x7D, 0x40, 0xE4, 0xFF, 0x91, 0x26, 0x90,
-	0x81, 0x1F, 0xE0, 0xFD, 0x13, 0x13, 0x13, 0x54,
-	0x1F, 0x30, 0xE0, 0x07, 0x90, 0x81, 0xCB, 0xE0,
-	0x44, 0x02, 0xF0, 0xED, 0xC4, 0x54, 0x0F, 0x30,
-	0xE0, 0x07, 0x90, 0x81, 0xCB, 0xE0, 0x44, 0x04,
-	0xF0, 0x90, 0x81, 0xCB, 0xE0, 0x90, 0x05, 0x27,
-	0xF0, 0x90, 0x81, 0x23, 0xE0, 0x64, 0x02, 0x70,
-	0x1D, 0xFD, 0x7F, 0x04, 0x12, 0x47, 0x3D, 0x12,
-	0x51, 0x73, 0xBF, 0x01, 0x09, 0x90, 0x81, 0x29,
-	0xE0, 0xFF, 0x7D, 0x01, 0x80, 0x03, 0xE4, 0xFD,
-	0xFF, 0x12, 0x47, 0x3D, 0x80, 0x41, 0x90, 0x81,
-	0x2A, 0xE0, 0x90, 0x81, 0x23, 0xF0, 0x90, 0x05,
-	0x27, 0xE0, 0x44, 0x40, 0xF0, 0x80, 0x30, 0x90,
-	0x81, 0xCB, 0x74, 0x01, 0xF0, 0x90, 0x05, 0x27,
-	0xF0, 0x90, 0x81, 0x23, 0xE0, 0xB4, 0x02, 0x06,
-	0x7D, 0x01, 0x7F, 0x04, 0x80, 0x0B, 0x90, 0x81,
-	0x23, 0xE0, 0xB4, 0x08, 0x07, 0x7D, 0x01, 0x7F,
-	0x0C, 0x12, 0x47, 0x3D, 0xD1, 0x34, 0x90, 0x81,
-	0x29, 0x12, 0x47, 0x39, 0x12, 0x5A, 0xA7, 0xD0,
-	0xD0, 0x92, 0xAF, 0x22, 0x7D, 0x02, 0x7F, 0x02,
-	0x91, 0x26, 0x7D, 0x01, 0x7F, 0x02, 0x74, 0x3D,
-	0x2F, 0xF8, 0xE6, 0xFE, 0xED, 0xF4, 0x5E, 0xFE,
-	0xF6, 0x74, 0x30, 0x2F, 0xF5, 0x82, 0xE4, 0x34,
-	0x01, 0xF5, 0x83, 0xEE, 0xF0, 0x22, 0xEF, 0x70,
-	0x37, 0x7D, 0x78, 0x7F, 0x02, 0x91, 0x26, 0x7D,
-	0x02, 0x7F, 0x03, 0x91, 0x26, 0x7D, 0xC8, 0x7F,
-	0x02, 0x12, 0x71, 0x8F, 0x90, 0x01, 0x57, 0xE4,
-	0xF0, 0x90, 0x01, 0x3C, 0x74, 0x02, 0xF0, 0x7D,
-	0x01, 0x7F, 0x0C, 0x12, 0x47, 0x3D, 0x90, 0x81,
-	0x24, 0xE0, 0x54, 0xF7, 0xF0, 0x54, 0xEF, 0xF0,
-	0x90, 0x06, 0x0A, 0xE0, 0x54, 0xF8, 0xF0, 0x22,
-	0x90, 0x01, 0x36, 0x74, 0x78, 0xF0, 0xA3, 0x74,
-	0x02, 0xF0, 0x7D, 0x78, 0xFF, 0x51, 0x57, 0x7D,
-	0x02, 0x7F, 0x03, 0x51, 0x57, 0x90, 0x06, 0x0A,
-	0xE0, 0x44, 0x07, 0xF0, 0x90, 0x81, 0x32, 0xA3,
-	0xE0, 0x90, 0x05, 0x58, 0xF0, 0x90, 0x80, 0xDE,
-	0xE0, 0xB4, 0x01, 0x15, 0x90, 0x81, 0x25, 0xE0,
-	0x54, 0xFB, 0xF0, 0x90, 0x81, 0x2A, 0xE0, 0x20,
-	0xE2, 0x0E, 0x7D, 0x01, 0x7F, 0x04, 0x02, 0x47,
-	0x3D, 0x90, 0x81, 0x25, 0xE0, 0x44, 0x04, 0xF0,
-	0x22, 0x90, 0x81, 0x1F, 0xE0, 0xFF, 0x30, 0xE0,
-	0x08, 0x90, 0x81, 0x23, 0xE0, 0x64, 0x02, 0x60,
-	0x3A, 0x90, 0x81, 0x27, 0xE0, 0x70, 0x04, 0xEF,
-	0x30, 0xE0, 0x0A, 0x90, 0x81, 0x2A, 0xE0, 0x64,
-	0x02, 0x60, 0x28, 0xB1, 0x83, 0x90, 0x81, 0x25,
-	0xE0, 0x13, 0x13, 0x13, 0x54, 0x1F, 0x30, 0xE0,
-	0x14, 0x90, 0x81, 0x2D, 0xE0, 0xFF, 0xA3, 0xE0,
-	0x6F, 0x70, 0x0A, 0xF1, 0xCD, 0x91, 0x1C, 0x90,
-	0x81, 0x2E, 0xE0, 0x14, 0xF0, 0x90, 0x01, 0xE6,
-	0xE0, 0x04, 0xF0, 0x22, 0x90, 0x81, 0x1F, 0xE0,
-	0x30, 0xE0, 0x06, 0x90, 0x81, 0x21, 0x74, 0x01,
-	0xF0, 0x90, 0x81, 0x27, 0xE0, 0x60, 0x45, 0x90,
-	0x81, 0x25, 0xE0, 0xFF, 0x13, 0x13, 0x13, 0x54,
-	0x1F, 0x30, 0xE0, 0x12, 0x90, 0x01, 0x3B, 0xE0,
-	0x30, 0xE4, 0x0B, 0x91, 0x1C, 0x90, 0x81, 0x2D,
-	0xE0, 0x14, 0x90, 0x05, 0x73, 0xF0, 0x90, 0x82,
-	0x0B, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x44, 0xA9,
-	0xC3, 0x90, 0x82, 0x0C, 0xE0, 0x94, 0x80, 0x90,
-	0x82, 0x0B, 0xE0, 0x64, 0x80, 0x94, 0x80, 0x40,
-	0x0B, 0x90, 0x01, 0x98, 0xE0, 0x54, 0xFE, 0xF0,
-	0xE0, 0x44, 0x01, 0xF0, 0x12, 0x75, 0xF8, 0xD1,
-	0xD6, 0x90, 0x81, 0x3F, 0xE0, 0x30, 0xE0, 0x0C,
-	0xE4, 0xF5, 0x1D, 0xA3, 0xF1, 0xFB, 0x90, 0x01,
-	0x57, 0x74, 0x05, 0xF0, 0x90, 0x01, 0xBE, 0xE0,
-	0x04, 0xF0, 0x22, 0x90, 0x80, 0xDE, 0xE0, 0x64,
-	0x01, 0x60, 0x02, 0xC1, 0x23, 0x90, 0x81, 0x27,
-	0xE0, 0x70, 0x02, 0xC1, 0x23, 0x90, 0x81, 0x26,
-	0xE0, 0xC4, 0x54, 0x0F, 0x64, 0x01, 0x70, 0x22,
-	0x90, 0x06, 0xAB, 0xE0, 0x90, 0x81, 0x2E, 0xF0,
-	0x90, 0x06, 0xAA, 0xE0, 0x90, 0x81, 0x2D, 0xF0,
-	0xA3, 0xE0, 0xFF, 0x70, 0x08, 0x90, 0x81, 0x2D,
-	0xE0, 0xFE, 0xFF, 0x80, 0x00, 0x90, 0x81, 0x2E,
-	0xEF, 0xF0, 0x90, 0x81, 0x25, 0xE0, 0x44, 0x04,
-	0xF0, 0xE4, 0x90, 0x81, 0x30, 0xF0, 0x90, 0x81,
-	0x32, 0xA3, 0xE0, 0x90, 0x05, 0x58, 0xF0, 0x90,
-	0x01, 0x57, 0xE4, 0xF0, 0x90, 0x01, 0x3C, 0x74,
-	0x02, 0xF0, 0x90, 0x81, 0x2B, 0xE0, 0x54, 0xFD,
-	0xF0, 0x54, 0xEF, 0xF0, 0x90, 0x81, 0x26, 0xE0,
-	0xFF, 0xC4, 0x54, 0x0F, 0x24, 0xFD, 0x50, 0x02,
-	0x80, 0x0F, 0x90, 0x81, 0x1F, 0xE0, 0x30, 0xE0,
-	0x05, 0x12, 0x6D, 0xF2, 0x80, 0x03, 0x12, 0x6E,
-	0xC9, 0x90, 0x81, 0x25, 0xE0, 0x13, 0x13, 0x13,
-	0x54, 0x1F, 0x30, 0xE0, 0x0E, 0x90, 0x81, 0x2D,
-	0xE0, 0xFF, 0xA3, 0xE0, 0xB5, 0x07, 0x04, 0xF1,
-	0xCD, 0x91, 0x22, 0x90, 0x81, 0x1F, 0xE0, 0xC3,
-	0x13, 0x20, 0xE0, 0x07, 0x90, 0x81, 0x25, 0xE0,
-	0x44, 0x04, 0xF0, 0x22, 0xD1, 0xAB, 0xEF, 0x70,
-	0x02, 0xD1, 0x3C, 0x22, 0x90, 0x81, 0x27, 0xE0,
-	0x64, 0x01, 0x70, 0x66, 0x90, 0x81, 0x26, 0xE0,
-	0x54, 0x0F, 0x60, 0x51, 0x90, 0x81, 0x2A, 0xE0,
-	0x70, 0x03, 0xFF, 0x31, 0x93, 0x90, 0x81, 0x2A,
-	0xE0, 0x64, 0x0C, 0x60, 0x03, 0x12, 0x66, 0x26,
-	0x90, 0x01, 0x5B, 0xE4, 0xF0, 0x90, 0x01, 0x3C,
-	0x74, 0x04, 0xF0, 0xD1, 0xAB, 0xEF, 0x64, 0x01,
-	0x60, 0x38, 0xE4, 0xF5, 0x1D, 0x90, 0x81, 0x3A,
-	0xE0, 0xC3, 0x13, 0x54, 0x7F, 0xF5, 0x1E, 0xE4,
-	0xFB, 0xFD, 0x7F, 0x58, 0x7E, 0x01, 0x12, 0x50,
-	0x05, 0x90, 0x01, 0x5B, 0x74, 0x05, 0xF0, 0x90,
-	0x06, 0x92, 0x74, 0x01, 0xF0, 0x90, 0x81, 0x24,
-	0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90, 0x81, 0x2A,
-	0xE0, 0x70, 0x07, 0x7D, 0x01, 0x7F, 0x04, 0x12,
-	0x47, 0x3D, 0x22, 0x90, 0x04, 0x1A, 0xE0, 0xF4,
-	0x60, 0x03, 0x7F, 0x00, 0x22, 0x90, 0x04, 0x1B,
-	0xE0, 0x54, 0x07, 0x64, 0x07, 0x7F, 0x01, 0x60,
-	0x02, 0x7F, 0x00, 0x22, 0x12, 0x50, 0x60, 0x90,
-	0x81, 0x2D, 0xE0, 0x14, 0x90, 0x05, 0x73, 0xF0,
-	0x7D, 0x02, 0x7F, 0x02, 0x51, 0x57, 0x90, 0x81,
-	0x42, 0xE0, 0x30, 0xE0, 0x2D, 0x90, 0x80, 0xDE,
-	0xE0, 0xB4, 0x01, 0x26, 0x90, 0x82, 0x17, 0xE0,
-	0x04, 0xF0, 0xE0, 0xB4, 0x0A, 0x0B, 0x90, 0x81,
-	0x44, 0xE0, 0x04, 0xF0, 0xE4, 0x90, 0x82, 0x17,
-	0xF0, 0x90, 0x81, 0x44, 0xE0, 0xFF, 0x90, 0x81,
-	0x43, 0xE0, 0xB5, 0x07, 0x05, 0xE4, 0xA3, 0xF0,
-	0xF1, 0x0B, 0x22, 0xE4, 0xFF, 0x8F, 0x53, 0x90,
-	0x04, 0x1D, 0xE0, 0x60, 0x19, 0x90, 0x05, 0x22,
-	0xE0, 0xF5, 0x56, 0x74, 0xFF, 0xF0, 0xF1, 0x3A,
-	0xBF, 0x01, 0x03, 0x12, 0x74, 0xFB, 0x90, 0x05,
-	0x22, 0xE5, 0x56, 0xF0, 0x80, 0x03, 0x12, 0x74,
-	0xFB, 0x90, 0x04, 0x1F, 0x74, 0x20, 0xF0, 0x7F,
-	0x01, 0x22, 0xE4, 0x90, 0x82, 0x0F, 0xF0, 0xA3,
-	0xF0, 0x90, 0x05, 0xF8, 0xE0, 0x70, 0x0F, 0xA3,
-	0xE0, 0x70, 0x0B, 0xA3, 0xE0, 0x70, 0x07, 0xA3,
-	0xE0, 0x70, 0x03, 0x7F, 0x01, 0x22, 0xD3, 0x90,
-	0x82, 0x10, 0xE0, 0x94, 0xE8, 0x90, 0x82, 0x0F,
-	0xE0, 0x94, 0x03, 0x40, 0x0A, 0x90, 0x01, 0xC0,
-	0xE0, 0x44, 0x20, 0xF0, 0x7F, 0x00, 0x22, 0x7F,
-	0x32, 0x7E, 0x00, 0x12, 0x32, 0xAA, 0x90, 0x82,
-	0x0F, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x44, 0xA9,
-	0x80, 0xBF, 0x74, 0x1F, 0x2D, 0xF5, 0x82, 0xE4,
-	0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x54, 0x3F, 0xF0,
-	0xEF, 0x60, 0x1D, 0x74, 0x21, 0x2D, 0xF5, 0x82,
-	0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x44, 0x10,
-	0xF0, 0x74, 0x1F, 0x2D, 0xF5, 0x82, 0xE4, 0x34,
-	0xFC, 0xF5, 0x83, 0xE0, 0x44, 0x80, 0xF0, 0x22,
-	0x74, 0x21, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0xFC,
-	0xF5, 0x83, 0xE0, 0x54, 0xEF, 0xF0, 0x74, 0x1F,
-	0x2D, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83,
-	0xE0, 0x44, 0x40, 0xF0, 0x22, 0xEF, 0x14, 0x90,
-	0x05, 0x73, 0xF0, 0x90, 0x01, 0x3F, 0x74, 0x10,
-	0xF0, 0xFD, 0x7F, 0x03, 0x74, 0x45, 0x2F, 0xF8,
-	0xE6, 0x4D, 0xFE, 0xF6, 0x74, 0x38, 0x2F, 0xF5,
-	0x82, 0xE4, 0x34, 0x01, 0xF5, 0x83, 0xEE, 0xF0,
-	0x22, 0xE0, 0x44, 0x02, 0xF0, 0xE4, 0xF5, 0x1D,
-	0x90, 0x81, 0x39, 0xE0, 0xF5, 0x1E, 0xE4, 0xFB,
-	0xFD, 0x7F, 0x54, 0x7E, 0x01, 0x8E, 0x19, 0x8F,
-	0x1A, 0xE5, 0x1E, 0x54, 0x07, 0xC4, 0x33, 0x54,
-	0xE0, 0x85, 0x19, 0x83, 0x85, 0x1A, 0x82, 0xF0,
-	0xE5, 0x1D, 0x54, 0x07, 0xC4, 0x33, 0x54, 0xE0,
-	0xFF, 0xE5, 0x1E, 0x13, 0x13, 0x13, 0x54, 0x1F,
-	0x4F, 0xA3, 0xF0, 0xEB, 0x54, 0x07, 0xC4, 0x33,
-	0x54, 0xE0, 0xFF, 0xE5, 0x1D, 0x13, 0x13, 0x13,
-	0x54, 0x1F, 0x4F, 0x85, 0x1A, 0x82, 0x85, 0x19,
-	0x83, 0xA3, 0xA3, 0xF0, 0xBD, 0x01, 0x0C, 0x85,
-	0x1A, 0x82, 0x8E, 0x83, 0xA3, 0xA3, 0xA3, 0x74,
-	0x03, 0xF0, 0x22, 0x85, 0x1A, 0x82, 0x85, 0x19,
-	0x83, 0xA3, 0xA3, 0xA3, 0x74, 0x01, 0xF0, 0x22,
-	0xE4, 0x90, 0x81, 0x4D, 0xF0, 0x90, 0x81, 0x27,
-	0xE0, 0x60, 0x58, 0x90, 0x80, 0xDE, 0xE0, 0x64,
-	0x01, 0x70, 0x50, 0x90, 0x81, 0x4D, 0x04, 0xF0,
-	0xE4, 0x90, 0x81, 0x2E, 0xF0, 0x90, 0x81, 0x1F,
-	0xE0, 0x30, 0xE0, 0x15, 0x90, 0x81, 0x23, 0xE0,
-	0xB4, 0x02, 0x05, 0xE4, 0x90, 0x81, 0x4D, 0xF0,
-	0x31, 0x73, 0xEF, 0x70, 0x04, 0x90, 0x81, 0x4D,
-	0xF0, 0x90, 0x81, 0x4D, 0xE0, 0x60, 0x24, 0x90,
-	0x81, 0x2B, 0xE0, 0x44, 0x10, 0xF0, 0xE4, 0xF5,
-	0x1D, 0x90, 0x81, 0x2F, 0x12, 0x4F, 0xFB, 0x90,
-	0x01, 0x57, 0x74, 0x05, 0xF0, 0x90, 0x81, 0x2A,
-	0xE0, 0x20, 0xE2, 0x07, 0x7D, 0x01, 0x7F, 0x04,
-	0x12, 0x47, 0x3D, 0x22, 0xE4, 0x90, 0x81, 0x4C,
-	0xF0, 0x90, 0x81, 0x27, 0xE0, 0x70, 0x02, 0x21,
-	0x72, 0x90, 0x80, 0xDE, 0xE0, 0x64, 0x01, 0x60,
-	0x02, 0x21, 0x72, 0x90, 0x81, 0x26, 0xE0, 0xFF,
-	0xC4, 0x54, 0x0F, 0x60, 0x22, 0x24, 0xFE, 0x60,
-	0x03, 0x04, 0x70, 0x21, 0x90, 0x81, 0x2E, 0xE0,
-	0x14, 0xF0, 0xE0, 0xFF, 0x60, 0x06, 0x90, 0x81,
-	0x30, 0xE0, 0x60, 0x11, 0xEF, 0x70, 0x08, 0x90,
-	0x81, 0x2D, 0xE0, 0xA3, 0xF0, 0x80, 0x00, 0x90,
-	0x81, 0x4C, 0x74, 0x01, 0xF0, 0x90, 0x81, 0x1F,
-	0xE0, 0x30, 0xE0, 0x15, 0x90, 0x81, 0x23, 0xE0,
-	0xB4, 0x02, 0x05, 0xE4, 0x90, 0x81, 0x4C, 0xF0,
-	0x31, 0x73, 0xEF, 0x70, 0x04, 0x90, 0x81, 0x4C,
-	0xF0, 0x90, 0x81, 0x4C, 0xE0, 0x60, 0x43, 0x90,
-	0x81, 0x2B, 0xE0, 0x44, 0x10, 0xF0, 0x90, 0x81,
-	0x30, 0xE0, 0x60, 0x03, 0xB4, 0x01, 0x09, 0xE4,
-	0xF5, 0x1D, 0x90, 0x81, 0x30, 0xE0, 0x80, 0x0D,
-	0xE4, 0xF5, 0x1D, 0x90, 0x81, 0x30, 0xE0, 0x75,
-	0xF0, 0x03, 0xA4, 0x24, 0xFE, 0xFF, 0x90, 0x81,
-	0x2F, 0xE0, 0x2F, 0x12, 0x4F, 0xFC, 0x90, 0x01,
-	0x57, 0x74, 0x05, 0xF0, 0x90, 0x81, 0x2A, 0xE0,
-	0x20, 0xE2, 0x07, 0x7D, 0x01, 0x7F, 0x04, 0x12,
-	0x47, 0x3D, 0x22, 0x90, 0x05, 0x43, 0xE0, 0x7F,
-	0x00, 0x30, 0xE7, 0x02, 0x7F, 0x01, 0x22, 0x90,
-	0x81, 0x27, 0xE0, 0x70, 0x07, 0x90, 0x81, 0x1F,
-	0xE0, 0x30, 0xE0, 0x11, 0x90, 0x81, 0x1F, 0xE0,
-	0x30, 0xE0, 0x07, 0x31, 0x73, 0xBF, 0x01, 0x05,
-	0x41, 0x5B, 0x12, 0x4E, 0x3C, 0x22, 0xD3, 0x10,
-	0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x81, 0x1E,
-	0xE0, 0xB4, 0x01, 0x04, 0x7F, 0x04, 0x80, 0x0B,
-	0x31, 0x73, 0xBF, 0x01, 0x04, 0x7F, 0x01, 0x80,
-	0x02, 0x7F, 0x02, 0x71, 0x0E, 0xD0, 0xD0, 0x92,
-	0xAF, 0x22, 0x90, 0x81, 0x4B, 0xE0, 0x60, 0x0F,
-	0xE4, 0xF0, 0x90, 0x05, 0x53, 0xE0, 0x44, 0x02,
-	0xF0, 0x90, 0x05, 0xFC, 0xE0, 0x04, 0xF0, 0x90,
-	0x81, 0x1F, 0xE0, 0x30, 0xE0, 0x10, 0xA3, 0x74,
-	0x01, 0xF0, 0x90, 0x81, 0x1F, 0xE0, 0xFF, 0xC3,
-	0x13, 0x30, 0xE0, 0x02, 0x31, 0x9E, 0x11, 0xC4,
-	0x90, 0x81, 0x3F, 0xE0, 0x30, 0xE0, 0x07, 0x91,
-	0x65, 0x90, 0x05, 0x22, 0xE4, 0xF0, 0x22, 0x90,
-	0x81, 0x1F, 0xE0, 0xFF, 0x30, 0xE0, 0x3D, 0x90,
-	0x81, 0x23, 0xE0, 0x7E, 0x00, 0xB4, 0x02, 0x02,
-	0x7E, 0x01, 0x90, 0x81, 0x22, 0xE0, 0x7D, 0x00,
-	0xB4, 0x04, 0x02, 0x7D, 0x01, 0xED, 0x4E, 0x70,
-	0x23, 0xEF, 0xC3, 0x13, 0x30, 0xE0, 0x02, 0x21,
-	0x9E, 0x51, 0x45, 0x90, 0x81, 0x23, 0xE0, 0xB4,
-	0x08, 0x06, 0xE4, 0xFD, 0x7F, 0x0C, 0x80, 0x09,
-	0x90, 0x81, 0x23, 0xE0, 0x70, 0x06, 0xFD, 0x7F,
-	0x04, 0x12, 0x47, 0x3D, 0x22, 0x90, 0x81, 0x1E,
-	0xE0, 0xB4, 0x01, 0x0F, 0x90, 0x81, 0x23, 0xE0,
-	0x64, 0x02, 0x60, 0x07, 0x7D, 0x01, 0x7F, 0x02,
-	0x12, 0x47, 0x3D, 0x90, 0x81, 0x27, 0xE0, 0x64,
-	0x02, 0x60, 0x14, 0x90, 0x81, 0x26, 0xE0, 0x54,
-	0x0F, 0x60, 0x0C, 0x12, 0x4E, 0xAB, 0xEF, 0x70,
-	0x06, 0xFD, 0x7F, 0x0C, 0x12, 0x47, 0x3D, 0x22,
-	0x90, 0x81, 0x1F, 0xE0, 0xFF, 0x30, 0xE0, 0x3F,
-	0x90, 0x81, 0x23, 0xE0, 0x7E, 0x00, 0xB4, 0x02,
-	0x02, 0x7E, 0x01, 0x90, 0x81, 0x22, 0xE0, 0x7D,
-	0x00, 0xB4, 0x04, 0x02, 0x7D, 0x01, 0xED, 0x4E,
-	0x70, 0x25, 0xEF, 0xC3, 0x13, 0x30, 0xE0, 0x02,
-	0x21, 0x9E, 0x12, 0x74, 0xAC, 0x90, 0x81, 0x23,
-	0xE0, 0xB4, 0x0C, 0x06, 0xE4, 0xFD, 0x7F, 0x08,
-	0x80, 0x0A, 0x90, 0x81, 0x23, 0xE0, 0xB4, 0x04,
-	0x06, 0xE4, 0xFD, 0xFF, 0x12, 0x47, 0x3D, 0x22,
-	0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90,
-	0x81, 0xCB, 0x12, 0x45, 0x1F, 0x12, 0x1F, 0xA4,
-	0xFF, 0x90, 0x81, 0x1E, 0xF0, 0xBF, 0x01, 0x12,
-	0x90, 0x81, 0xCB, 0x12, 0x45, 0x16, 0x90, 0x00,
-	0x01, 0x12, 0x1F, 0xBD, 0x64, 0x01, 0x60, 0x21,
-	0x80, 0x1D, 0x90, 0x81, 0xCB, 0x12, 0x45, 0x16,
-	0x90, 0x00, 0x01, 0x12, 0x1F, 0xBD, 0x64, 0x01,
-	0x60, 0x0F, 0x90, 0x81, 0x1F, 0xE0, 0x20, 0xE0,
-	0x06, 0xE4, 0xFF, 0x71, 0x0E, 0x80, 0x02, 0x31,
-	0x9E, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10,
-	0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x81, 0x22,
-	0xE0, 0x90, 0x82, 0x16, 0xF0, 0x6F, 0x70, 0x02,
-	0x81, 0x04, 0xEF, 0x14, 0x60, 0x3E, 0x14, 0x60,
-	0x62, 0x14, 0x70, 0x02, 0x61, 0xB8, 0x14, 0x70,
-	0x02, 0x61, 0xDF, 0x24, 0x04, 0x60, 0x02, 0x81,
-	0x04, 0x90, 0x82, 0x16, 0xE0, 0xFF, 0xB4, 0x04,
-	0x04, 0x91, 0x41, 0x81, 0x04, 0xEF, 0xB4, 0x02,
-	0x04, 0x91, 0x50, 0x81, 0x04, 0x90, 0x82, 0x16,
-	0xE0, 0xFF, 0xB4, 0x03, 0x04, 0x91, 0x54, 0x81,
-	0x04, 0xEF, 0x64, 0x01, 0x60, 0x02, 0x81, 0x04,
-	0x91, 0x43, 0x81, 0x04, 0x90, 0x82, 0x16, 0xE0,
-	0xFF, 0xB4, 0x04, 0x04, 0x91, 0xF3, 0x81, 0x04,
-	0xEF, 0xB4, 0x02, 0x04, 0x91, 0x58, 0x81, 0x04,
-	0x90, 0x82, 0x16, 0xE0, 0xFF, 0xB4, 0x03, 0x04,
-	0x91, 0xE8, 0x81, 0x04, 0xEF, 0x70, 0x7D, 0x91,
-	0x2B, 0x80, 0x79, 0x90, 0x82, 0x16, 0xE0, 0xB4,
-	0x04, 0x05, 0x12, 0x74, 0x60, 0x80, 0x6D, 0x90,
-	0x82, 0x16, 0xE0, 0xB4, 0x01, 0x04, 0x91, 0x21,
-	0x80, 0x62, 0x90, 0x82, 0x16, 0xE0, 0xB4, 0x03,
-	0x05, 0x12, 0x74, 0x71, 0x80, 0x56, 0x90, 0x82,
-	0x16, 0xE0, 0x70, 0x50, 0x91, 0x1F, 0x80, 0x4C,
-	0x90, 0x82, 0x16, 0xE0, 0xFF, 0xB4, 0x04, 0x05,
-	0x12, 0x74, 0x4C, 0x80, 0x3F, 0xEF, 0xB4, 0x01,
-	0x04, 0x91, 0x34, 0x80, 0x37, 0xEF, 0xB4, 0x02,
-	0x04, 0x91, 0xDF, 0x80, 0x2F, 0x90, 0x82, 0x16,
-	0xE0, 0x70, 0x29, 0x91, 0x32, 0x80, 0x25, 0x90,
-	0x82, 0x16, 0xE0, 0xFF, 0xB4, 0x03, 0x05, 0x12,
-	0x74, 0x7B, 0x80, 0x18, 0xEF, 0xB4, 0x01, 0x04,
-	0x91, 0x0B, 0x80, 0x10, 0xEF, 0xB4, 0x02, 0x04,
-	0xB1, 0x06, 0x80, 0x08, 0x90, 0x82, 0x16, 0xE0,
-	0x70, 0x02, 0x91, 0x09, 0xD0, 0xD0, 0x92, 0xAF,
-	0x22, 0x91, 0x2B, 0x90, 0x05, 0x22, 0x74, 0x6F,
-	0xF0, 0x90, 0x05, 0x27, 0xE0, 0x54, 0xBF, 0xF0,
-	0x90, 0x81, 0x22, 0x74, 0x04, 0xF0, 0x22, 0x91,
-	0x2B, 0x12, 0x49, 0xDD, 0x90, 0x81, 0x22, 0x74,
-	0x02, 0xF0, 0x22, 0x90, 0x81, 0x22, 0x74, 0x01,
-	0xF0, 0x22, 0x91, 0x2B, 0x90, 0x05, 0x22, 0x74,
-	0xFF, 0xF0, 0x90, 0x81, 0x22, 0x74, 0x03, 0xF0,
-	0x22, 0x91, 0xF3, 0x90, 0x05, 0x27, 0xE0, 0x54,
-	0xBF, 0xF0, 0xE4, 0x90, 0x81, 0x22, 0xF0, 0x22,
-	0x91, 0x58, 0x80, 0xEF, 0x91, 0xE8, 0x80, 0xEB,
-	0x91, 0x65, 0x90, 0x05, 0x22, 0xE4, 0xF0, 0x90,
-	0x81, 0x22, 0x04, 0xF0, 0x22, 0xD3, 0x10, 0xAF,
-	0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x01, 0x01, 0xE0,
-	0x44, 0x02, 0xF0, 0x90, 0x01, 0x00, 0x74, 0xFF,
-	0xF0, 0x90, 0x06, 0xB7, 0x74, 0x09, 0xF0, 0x90,
-	0x06, 0xB4, 0x74, 0x86, 0xF0, 0x7F, 0x7C, 0x7E,
-	0x08, 0x12, 0x2D, 0x5C, 0xEC, 0x54, 0x7F, 0xFC,
-	0x90, 0x82, 0x01, 0x12, 0x20, 0xCE, 0x90, 0x82,
-	0x01, 0x12, 0x44, 0xD9, 0x90, 0x85, 0xBB, 0x12,
-	0x20, 0xCE, 0x7F, 0x7C, 0x7E, 0x08, 0x12, 0x2E,
-	0xA2, 0x90, 0x85, 0xBB, 0x12, 0x20, 0xDA, 0xCC,
-	0xC0, 0x00, 0xC0, 0x7F, 0x8C, 0x7E, 0x08, 0x12,
-	0x2E, 0xA2, 0x90, 0x85, 0xBB, 0x12, 0x20, 0xDA,
-	0x00, 0xC0, 0x00, 0x14, 0x7F, 0x70, 0x7E, 0x0E,
-	0x12, 0x2E, 0xA2, 0x90, 0x81, 0xF9, 0x12, 0x20,
-	0xDA, 0x00, 0x03, 0x3E, 0x60, 0xE4, 0xFD, 0xFF,
-	0xB1, 0x1C, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x91,
-	0x65, 0x90, 0x81, 0x22, 0x74, 0x03, 0xF0, 0x22,
-	0x90, 0x05, 0x22, 0xE4, 0xF0, 0x90, 0x81, 0x22,
-	0x04, 0xF0, 0x22, 0x90, 0x05, 0x22, 0xE4, 0xF0,
-	0x90, 0x05, 0x27, 0xE0, 0x44, 0x40, 0xF0, 0x90,
-	0x81, 0x22, 0x74, 0x01, 0xF0, 0x22, 0x91, 0x65,
-	0x90, 0x05, 0x22, 0x74, 0x6F, 0xF0, 0x90, 0x05,
-	0x27, 0xE0, 0x54, 0xBF, 0xF0, 0x90, 0x81, 0x22,
-	0x74, 0x04, 0xF0, 0x22, 0xD3, 0x10, 0xAF, 0x01,
-	0xC3, 0xC0, 0xD0, 0xC0, 0x07, 0xC0, 0x05, 0x90,
-	0x81, 0xF9, 0x12, 0x44, 0xD9, 0x90, 0x81, 0xE5,
-	0x12, 0x20, 0xCE, 0xD0, 0x05, 0xD0, 0x07, 0x12,
-	0x60, 0xF5, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90,
-	0x81, 0xC8, 0x12, 0x45, 0x1F, 0xEF, 0x12, 0x45,
-	0x28, 0x55, 0x71, 0x00, 0x55, 0x7A, 0x01, 0x55,
-	0x83, 0x02, 0x55, 0x8B, 0x03, 0x55, 0x94, 0x04,
-	0x55, 0x9C, 0x20, 0x55, 0xA4, 0x21, 0x55, 0xAD,
-	0x23, 0x55, 0xB5, 0x24, 0x55, 0xBE, 0x25, 0x55,
-	0xC7, 0x26, 0x55, 0xCF, 0xC0, 0x00, 0x00, 0x55,
-	0xD8, 0x90, 0x81, 0xC8, 0x12, 0x45, 0x16, 0x02,
-	0x6A, 0xB0, 0x90, 0x81, 0xC8, 0x12, 0x45, 0x16,
-	0x02, 0x65, 0x81, 0x90, 0x81, 0xC8, 0x12, 0x45,
-	0x16, 0x41, 0xC0, 0x90, 0x81, 0xC8, 0x12, 0x45,
-	0x16, 0x02, 0x75, 0xD8, 0x90, 0x81, 0xC8, 0x12,
-	0x45, 0x16, 0x80, 0x44, 0x90, 0x81, 0xC8, 0x12,
-	0x45, 0x16, 0xC1, 0x4B, 0x90, 0x81, 0xC8, 0x12,
-	0x45, 0x16, 0x02, 0x6A, 0xF8, 0x90, 0x81, 0xC8,
-	0x12, 0x45, 0x16, 0xE1, 0xE1, 0x90, 0x81, 0xC8,
-	0x12, 0x45, 0x16, 0x02, 0x4A, 0x6C, 0x90, 0x81,
-	0xC8, 0x12, 0x45, 0x16, 0x02, 0x6B, 0x3E, 0x90,
-	0x81, 0xC8, 0x12, 0x45, 0x16, 0x80, 0x3E, 0x90,
-	0x81, 0xC8, 0x12, 0x45, 0x16, 0x02, 0x6B, 0x4E,
-	0x90, 0x01, 0xC0, 0xE0, 0x44, 0x01, 0xF0, 0x22,
-	0x12, 0x5A, 0x4B, 0x12, 0x1F, 0xA4, 0xFF, 0x54,
-	0x01, 0xFE, 0x90, 0x81, 0x45, 0xE0, 0x54, 0xFE,
-	0x4E, 0xF0, 0xEF, 0xC3, 0x13, 0x30, 0xE0, 0x14,
-	0x90, 0x00, 0x01, 0x12, 0x1F, 0xBD, 0x90, 0x81,
-	0x46, 0xF0, 0x90, 0x00, 0x02, 0x12, 0x1F, 0xBD,
-	0x90, 0x81, 0x47, 0xF0, 0x22, 0x12, 0x1F, 0xA4,
-	0xFF, 0x54, 0x01, 0xFE, 0x90, 0x81, 0x3F, 0xE0,
-	0x54, 0xFE, 0x4E, 0xF0, 0x90, 0x00, 0x01, 0x12,
-	0x1F, 0xBD, 0xFE, 0x90, 0x05, 0x54, 0xE0, 0xC3,
-	0x9E, 0x90, 0x81, 0x40, 0xF0, 0xEF, 0x20, 0xE0,
-	0x07, 0x91, 0x65, 0x90, 0x05, 0x22, 0xE4, 0xF0,
-	0x90, 0x81, 0x3F, 0xE0, 0x54, 0x01, 0x90, 0x01,
-	0xBC, 0xF0, 0x90, 0x81, 0x40, 0xE0, 0x90, 0x01,
-	0xBD, 0xF0, 0x22, 0x12, 0x1F, 0xA4, 0xFF, 0x54,
-	0x7F, 0x90, 0x81, 0x27, 0xF0, 0xEF, 0xC4, 0x13,
-	0x13, 0x13, 0x54, 0x01, 0xA3, 0xF0, 0x90, 0x00,
-	0x01, 0x12, 0x1F, 0xBD, 0xFF, 0x54, 0xF0, 0xC4,
-	0x54, 0x0F, 0xFE, 0x90, 0x81, 0x26, 0xE0, 0x54,
-	0xF0, 0x4E, 0xF0, 0x90, 0x00, 0x03, 0x12, 0x1F,
-	0xBD, 0x54, 0x01, 0x25, 0xE0, 0xFE, 0x90, 0x81,
-	0x24, 0xE0, 0x54, 0xFD, 0x4E, 0xF0, 0xEF, 0x54,
-	0x0F, 0xC4, 0x54, 0xF0, 0xFF, 0x90, 0x81, 0x26,
-	0xE0, 0x54, 0x0F, 0x4F, 0xF0, 0x90, 0x00, 0x04,
-	0x12, 0x1F, 0xBD, 0x90, 0x81, 0x29, 0xF0, 0xD1,
-	0xC6, 0x90, 0x01, 0xB9, 0x74, 0x01, 0xF0, 0x90,
-	0x01, 0xB8, 0xF0, 0x90, 0x81, 0x27, 0xE0, 0x90,
-	0x01, 0xBA, 0xF0, 0x90, 0x81, 0x29, 0xE0, 0x90,
-	0x01, 0xBB, 0xF0, 0x90, 0x81, 0x26, 0xE0, 0x54,
-	0x0F, 0x90, 0x01, 0xBE, 0xF0, 0x22, 0x90, 0x81,
-	0xCB, 0x12, 0x45, 0x1F, 0x12, 0x72, 0xB3, 0x90,
-	0x81, 0x27, 0xE0, 0xFF, 0x12, 0x4C, 0x3E, 0x90,
-	0x81, 0x27, 0xE0, 0x60, 0x19, 0x90, 0x81, 0xCB,
-	0x12, 0x45, 0x16, 0x90, 0x00, 0x01, 0x12, 0x1F,
-	0xBD, 0x54, 0x0F, 0xFF, 0x90, 0x00, 0x02, 0x12,
-	0x1F, 0xBD, 0xFD, 0x12, 0x72, 0xC4, 0x22, 0xC0,
-	0xE0, 0xC0, 0xF0, 0xC0, 0x83, 0xC0, 0x82, 0xC0,
-	0xD0, 0x75, 0xD0, 0x00, 0xC0, 0x00, 0xC0, 0x01,
-	0xC0, 0x02, 0xC0, 0x03, 0xC0, 0x04, 0xC0, 0x05,
-	0xC0, 0x06, 0xC0, 0x07, 0x90, 0x01, 0xC4, 0x74,
-	0xF7, 0xF0, 0x74, 0x56, 0xA3, 0xF0, 0x12, 0x6C,
-	0xA5, 0xE5, 0x49, 0x30, 0xE1, 0x03, 0x12, 0x6F,
-	0x79, 0xE5, 0x49, 0x30, 0xE2, 0x02, 0xF1, 0xA5,
-	0xE5, 0x49, 0x30, 0xE3, 0x03, 0x12, 0x6F, 0x8D,
-	0xE5, 0x4A, 0x30, 0xE0, 0x03, 0x12, 0x6F, 0xC9,
-	0xE5, 0x4A, 0x30, 0xE4, 0x03, 0x12, 0x70, 0x22,
-	0xE5, 0x4B, 0x30, 0xE1, 0x02, 0x51, 0x78, 0xE5,
-	0x4B, 0x30, 0xE0, 0x02, 0x31, 0xFF, 0xE5, 0x4B,
-	0x30, 0xE3, 0x02, 0xF1, 0xE0, 0xE5, 0x4C, 0x30,
-	0xE1, 0x05, 0x7F, 0x03, 0x12, 0x44, 0x27, 0xE5,
-	0x4C, 0x30, 0xE4, 0x03, 0x12, 0x4E, 0xC4, 0xE5,
-	0x4C, 0x30, 0xE5, 0x03, 0x12, 0x70, 0x38, 0xE5,
-	0x4C, 0x30, 0xE6, 0x03, 0x12, 0x70, 0xCE, 0x74,
-	0xF7, 0x04, 0x90, 0x01, 0xC4, 0xF0, 0x74, 0x56,
-	0xA3, 0xF0, 0xD0, 0x07, 0xD0, 0x06, 0xD0, 0x05,
-	0xD0, 0x04, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01,
-	0xD0, 0x00, 0xD0, 0xD0, 0xD0, 0x82, 0xD0, 0x83,
-	0xD0, 0xF0, 0xD0, 0xE0, 0x32, 0x90, 0x81, 0x27,
-	0xE0, 0x60, 0x34, 0x90, 0x06, 0x92, 0xE0, 0x30,
-	0xE0, 0x23, 0xE4, 0xF5, 0x1D, 0x90, 0x81, 0x3A,
-	0xE0, 0xC3, 0x13, 0x54, 0x7F, 0xF5, 0x1E, 0xE4,
-	0xFB, 0xFD, 0x7F, 0x58, 0x7E, 0x01, 0x11, 0x05,
-	0x90, 0x01, 0x5B, 0x74, 0x05, 0xF0, 0x90, 0x06,
-	0x92, 0x74, 0x01, 0xF0, 0x22, 0x90, 0x81, 0x24,
-	0xE0, 0x54, 0xF7, 0xF0, 0x12, 0x47, 0x2A, 0x22,
-	0x22, 0x12, 0x1F, 0xA4, 0x90, 0x81, 0x31, 0xF0,
-	0x22, 0x90, 0x01, 0xC8, 0xE4, 0xF0, 0xA3, 0xF0,
-	0xA3, 0xF0, 0x7B, 0x01, 0x7A, 0x81, 0x79, 0x51,
-	0x7F, 0xFF, 0xFE, 0x12, 0x2B, 0x27, 0xBF, 0x01,
-	0x09, 0x90, 0x81, 0x51, 0xE0, 0x64, 0x03, 0x60,
-	0x03, 0x22, 0x01, 0xAB, 0xE4, 0x90, 0x81, 0x56,
-	0xF0, 0x90, 0x81, 0x56, 0xE0, 0xFF, 0xC3, 0x94,
-	0x02, 0x40, 0x02, 0x01, 0xE6, 0xC3, 0x74, 0xFE,
-	0x9F, 0xFF, 0xE4, 0x94, 0x00, 0xFE, 0x7B, 0x01,
-	0x7A, 0x81, 0x79, 0x52, 0x12, 0x2B, 0x27, 0xEF,
-	0x64, 0x01, 0x70, 0x77, 0x90, 0x81, 0x52, 0xE0,
-	0xFF, 0x54, 0xC0, 0xFE, 0x60, 0x05, 0xEF, 0x54,
-	0x0C, 0x70, 0x16, 0x90, 0x81, 0x52, 0xE0, 0xFF,
-	0x54, 0x30, 0x60, 0x67, 0xEF, 0x54, 0x03, 0x60,
-	0x62, 0x90, 0x81, 0x53, 0x74, 0x01, 0xF0, 0x80,
-	0x05, 0xE4, 0x90, 0x81, 0x53, 0xF0, 0x90, 0x81,
-	0x53, 0xE0, 0x90, 0x81, 0x52, 0x70, 0x16, 0xE0,
-	0xFF, 0xEE, 0x13, 0x13, 0x54, 0x3F, 0x90, 0x81,
-	0x54, 0xF0, 0xEF, 0x54, 0x0C, 0x13, 0x13, 0x54,
-	0x3F, 0xA3, 0xF0, 0x80, 0x0D, 0xE0, 0xFE, 0x54,
-	0x30, 0x90, 0x81, 0x54, 0xF0, 0xEE, 0x54, 0x03,
-	0xA3, 0xF0, 0x90, 0x81, 0x54, 0xE0, 0x64, 0x30,
-	0x70, 0x54, 0xA3, 0xE0, 0x64, 0x02, 0x70, 0x4E,
-	0x90, 0x00, 0xF5, 0xE0, 0x54, 0x40, 0x90, 0x81,
-	0x57, 0xF0, 0xE0, 0x70, 0x41, 0xA3, 0x74, 0x02,
-	0xF0, 0x80, 0x10, 0x90, 0x81, 0x58, 0x74, 0x01,
-	0xF0, 0x80, 0x08, 0x90, 0x81, 0x56, 0xE0, 0x04,
-	0xF0, 0x01, 0x11, 0x90, 0x01, 0xC4, 0x74, 0xE9,
-	0xF0, 0x74, 0x57, 0xA3, 0xF0, 0x90, 0x81, 0x58,
-	0xE0, 0x90, 0x01, 0xC8, 0xF0, 0x90, 0x81, 0x52,
-	0xE0, 0x90, 0x01, 0xC9, 0xF0, 0x90, 0x81, 0x53,
-	0xE0, 0x90, 0x01, 0xCA, 0xF0, 0xE4, 0xFD, 0x7F,
-	0x1F, 0x12, 0x32, 0x1E, 0x80, 0xD5, 0x22, 0x90,
-	0x00, 0xF7, 0xE0, 0x20, 0xE7, 0x09, 0xE0, 0x7F,
-	0x01, 0x20, 0xE6, 0x0C, 0x7F, 0x02, 0x22, 0x90,
-	0x00, 0xF7, 0xE0, 0x30, 0xE6, 0x02, 0x7F, 0x03,
-	0x22, 0x11, 0xE7, 0x90, 0x80, 0x3C, 0xEF, 0xF0,
-	0x31, 0x13, 0x90, 0x01, 0x64, 0x74, 0x01, 0xF0,
-	0x02, 0x2D, 0xA7, 0x31, 0x81, 0x31, 0xB1, 0x31,
-	0x40, 0x31, 0x5F, 0xE4, 0xF5, 0x35, 0xF5, 0x36,
-	0xF5, 0x37, 0xF5, 0x38, 0xAD, 0x35, 0x7F, 0x50,
-	0x12, 0x32, 0x1E, 0xAD, 0x36, 0x7F, 0x51, 0x12,
-	0x32, 0x1E, 0xAD, 0x37, 0x7F, 0x52, 0x12, 0x32,
-	0x1E, 0xAD, 0x38, 0x7F, 0x53, 0x02, 0x32, 0x1E,
-	0x75, 0x3D, 0x10, 0xE4, 0xF5, 0x3E, 0x75, 0x3F,
-	0x07, 0x75, 0x40, 0x02, 0x90, 0x01, 0x30, 0xE5,
-	0x3D, 0xF0, 0xA3, 0xE5, 0x3E, 0xF0, 0xA3, 0xE5,
-	0x3F, 0xF0, 0xA3, 0xE5, 0x40, 0xF0, 0x22, 0x75,
-	0x45, 0x0E, 0x75, 0x46, 0x01, 0x43, 0x46, 0x10,
-	0x75, 0x47, 0x03, 0x75, 0x48, 0x62, 0x90, 0x01,
-	0x38, 0xE5, 0x45, 0xF0, 0xA3, 0xE5, 0x46, 0xF0,
-	0xA3, 0xE5, 0x47, 0xF0, 0xA3, 0xE5, 0x48, 0xF0,
-	0x22, 0x90, 0x01, 0x30, 0xE4, 0xF0, 0xA3, 0xF0,
-	0xA3, 0xF0, 0xA3, 0xF0, 0x90, 0x01, 0x38, 0xF0,
-	0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xFD, 0x7F,
-	0x50, 0x12, 0x32, 0x1E, 0xE4, 0xFD, 0x7F, 0x51,
-	0x12, 0x32, 0x1E, 0xE4, 0xFD, 0x7F, 0x52, 0x12,
-	0x32, 0x1E, 0xE4, 0xFD, 0x7F, 0x53, 0x02, 0x32,
-	0x1E, 0x90, 0x01, 0x34, 0x74, 0xFF, 0xF0, 0xA3,
-	0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0x90, 0x01, 0x3C,
-	0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xFD,
-	0x7F, 0x54, 0x12, 0x32, 0x1E, 0x7D, 0xFF, 0x7F,
-	0x55, 0x12, 0x32, 0x1E, 0x7D, 0xFF, 0x7F, 0x56,
-	0x12, 0x32, 0x1E, 0x7D, 0xFF, 0x7F, 0x57, 0x02,
-	0x32, 0x1E, 0x90, 0x00, 0x80, 0xE0, 0x44, 0x80,
-	0xFD, 0x7F, 0x80, 0x12, 0x32, 0x1E, 0x90, 0xFD,
-	0x00, 0xE0, 0x54, 0xBF, 0xF0, 0x12, 0x57, 0xE9,
-	0x51, 0x77, 0x12, 0x32, 0x77, 0x51, 0xC9, 0x51,
-	0x5E, 0x7F, 0x01, 0x12, 0x43, 0x15, 0x90, 0x81,
-	0x41, 0x74, 0x02, 0xF0, 0xFF, 0x12, 0x43, 0x15,
-	0x90, 0x81, 0x41, 0xE0, 0x04, 0xF0, 0x7F, 0x03,
-	0x12, 0x43, 0x15, 0x90, 0x81, 0x41, 0xE0, 0x04,
-	0xF0, 0x31, 0x01, 0x51, 0x3F, 0x90, 0x00, 0x80,
-	0xE0, 0x44, 0x40, 0xFD, 0x7F, 0x80, 0x12, 0x32,
-	0x1E, 0x75, 0x20, 0xFF, 0x51, 0x68, 0x51, 0xF9,
-	0x51, 0x7F, 0xE4, 0xFF, 0x02, 0x43, 0x9E, 0x51,
-	0x62, 0x51, 0x6F, 0x51, 0xA7, 0x71, 0x4F, 0x51,
-	0x8A, 0x51, 0x95, 0x90, 0x81, 0x45, 0xE0, 0x54,
-	0xFE, 0xF0, 0xA3, 0x74, 0x03, 0xF0, 0xA3, 0xF0,
-	0xE4, 0xA3, 0xF0, 0xA3, 0xF0, 0x22, 0xE4, 0xF5,
-	0x4D, 0x22, 0xE4, 0x90, 0x80, 0xDE, 0xF0, 0x22,
-	0x75, 0xE8, 0x03, 0x75, 0xA8, 0x84, 0x22, 0xE4,
-	0x90, 0x80, 0xD8, 0xF0, 0xA3, 0xF0, 0x22, 0x90,
-	0x01, 0x94, 0xE0, 0x44, 0x01, 0xF0, 0x22, 0x90,
-	0x01, 0xE4, 0x74, 0x0B, 0xF0, 0xA3, 0x74, 0x01,
-	0xF0, 0x22, 0x90, 0x81, 0x3F, 0xE0, 0x54, 0xFE,
-	0xF0, 0xE4, 0xA3, 0xF0, 0x22, 0x90, 0x81, 0x42,
-	0xE0, 0x54, 0xFE, 0xF0, 0x54, 0x7F, 0xF0, 0xA3,
-	0x74, 0x0A, 0xF0, 0xE4, 0xA3, 0xF0, 0x22, 0x90,
-	0x81, 0x1F, 0xE0, 0x54, 0xFE, 0xF0, 0x54, 0xFD,
-	0xF0, 0x54, 0xFB, 0xF0, 0x54, 0xF7, 0xF0, 0x54,
-	0xEF, 0xF0, 0x54, 0xDF, 0xF0, 0xE4, 0xA3, 0xF0,
-	0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0x74, 0x0C, 0xF0,
-	0x22, 0x90, 0x01, 0x01, 0xE0, 0x44, 0x04, 0xF0,
-	0x90, 0x01, 0x9C, 0x74, 0x7E, 0xF0, 0xA3, 0x74,
-	0x92, 0xF0, 0xA3, 0x74, 0xA0, 0xF0, 0xA3, 0x74,
-	0x24, 0xF0, 0x90, 0x01, 0x9B, 0x74, 0x49, 0xF0,
-	0x90, 0x01, 0x9A, 0x74, 0xE0, 0xF0, 0x90, 0x01,
-	0x99, 0xE4, 0xF0, 0x90, 0x01, 0x98, 0x04, 0xF0,
-	0x22, 0xE4, 0x90, 0x81, 0x51, 0xF0, 0xA3, 0xF0,
-	0x90, 0x01, 0x98, 0xE0, 0x7F, 0x00, 0x30, 0xE4,
-	0x02, 0x7F, 0x01, 0xEF, 0x64, 0x01, 0x60, 0x3E,
-	0xC3, 0x90, 0x81, 0x52, 0xE0, 0x94, 0x88, 0x90,
-	0x81, 0x51, 0xE0, 0x94, 0x13, 0x40, 0x08, 0x90,
-	0x01, 0xC1, 0xE0, 0x44, 0x10, 0xF0, 0x22, 0x90,
-	0x81, 0x51, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x44,
-	0xA9, 0x7F, 0x14, 0x7E, 0x00, 0x12, 0x32, 0xAA,
-	0xD3, 0x90, 0x81, 0x52, 0xE0, 0x94, 0x32, 0x90,
-	0x81, 0x51, 0xE0, 0x94, 0x00, 0x40, 0xB9, 0x90,
-	0x01, 0xC6, 0xE0, 0x30, 0xE3, 0xB2, 0x22, 0xE4,
-	0x90, 0x81, 0x27, 0xF0, 0xA3, 0xF0, 0x90, 0x81,
-	0x26, 0xE0, 0x54, 0x0F, 0xF0, 0x54, 0xF0, 0xF0,
-	0x90, 0x81, 0x24, 0xE0, 0x54, 0xFD, 0xF0, 0x54,
-	0xF7, 0xF0, 0x54, 0xEF, 0xF0, 0x90, 0x81, 0x2D,
-	0x74, 0x01, 0xF0, 0xA3, 0xF0, 0x90, 0x81, 0x24,
-	0xE0, 0x54, 0xFB, 0xF0, 0xA3, 0xE0, 0x54, 0xFB,
-	0xF0, 0xE4, 0x90, 0x81, 0x30, 0xF0, 0x90, 0x81,
-	0x2F, 0x74, 0x07, 0xF0, 0x90, 0x81, 0x32, 0xE4,
-	0xF0, 0xA3, 0x74, 0x02, 0xF0, 0xE4, 0x90, 0x81,
-	0x2B, 0xF0, 0x90, 0x81, 0x24, 0xE0, 0x54, 0xFE,
-	0xF0, 0x90, 0x81, 0x29, 0x74, 0x0C, 0xF0, 0x90,
-	0x81, 0x24, 0xE0, 0x54, 0xDF, 0xF0, 0x90, 0x81,
-	0x2A, 0x74, 0x0C, 0xF0, 0x90, 0x81, 0x24, 0xE0,
-	0x54, 0xBF, 0xF0, 0x54, 0x7F, 0xF0, 0xA3, 0xE0,
-	0x54, 0xFE, 0xF0, 0x54, 0xFD, 0xF0, 0x54, 0xF7,
-	0xF0, 0x90, 0x81, 0x34, 0x12, 0x20, 0xDA, 0x00,
-	0x00, 0x00, 0x00, 0x90, 0x80, 0x3C, 0xE0, 0xB4,
-	0x01, 0x08, 0x90, 0x81, 0x31, 0x74, 0x99, 0xF0,
-	0x80, 0x12, 0x90, 0x80, 0x3C, 0xE0, 0x90, 0x81,
-	0x31, 0xB4, 0x03, 0x05, 0x74, 0x90, 0xF0, 0x80,
-	0x03, 0x74, 0x40, 0xF0, 0x90, 0x81, 0x38, 0x74,
-	0x01, 0xF0, 0xA3, 0x74, 0x05, 0xF0, 0xA3, 0xE0,
-	0x54, 0x01, 0x44, 0x28, 0xF0, 0xA3, 0x74, 0x05,
-	0xF0, 0xE4, 0xA3, 0xF0, 0xA3, 0xE0, 0x54, 0xFD,
-	0xF0, 0x54, 0xFB, 0xF0, 0x54, 0xF7, 0xF0, 0x54,
-	0xEF, 0xF0, 0x54, 0xDF, 0xF0, 0x54, 0xBF, 0xF0,
-	0xE4, 0xA3, 0xF0, 0x22, 0xE4, 0x90, 0x81, 0x59,
-	0xF0, 0x90, 0x81, 0x59, 0xE0, 0x64, 0x01, 0xF0,
-	0x24, 0x24, 0x90, 0x01, 0xC4, 0xF0, 0x74, 0x5C,
-	0xA3, 0xF0, 0x90, 0x81, 0x2A, 0xE0, 0xFF, 0x90,
-	0x81, 0x29, 0xE0, 0x6F, 0x60, 0x03, 0x12, 0x47,
-	0x2A, 0xD1, 0x08, 0xBF, 0x01, 0x02, 0x91, 0x5F,
-	0xB1, 0xF2, 0x12, 0x32, 0x9E, 0xBF, 0x01, 0x02,
-	0xB1, 0x67, 0x12, 0x42, 0x4D, 0x80, 0xCA, 0xD3,
-	0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x81,
-	0x24, 0xE0, 0x30, 0xE0, 0x24, 0x90, 0x81, 0x1F,
-	0xE0, 0xFF, 0x30, 0xE0, 0x1A, 0xC3, 0x13, 0x30,
-	0xE0, 0x07, 0xB1, 0xFB, 0xBF, 0x01, 0x12, 0x80,
-	0x0A, 0x90, 0x81, 0x23, 0xE0, 0xFF, 0x60, 0x03,
-	0xB4, 0x08, 0x06, 0x91, 0x96, 0x80, 0x02, 0x91,
-	0xA6, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10,
-	0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xB1, 0x22, 0x91,
-	0xBA, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x81,
-	0x2A, 0xE0, 0x70, 0x0D, 0xD1, 0x2F, 0xBF, 0x01,
-	0x08, 0x91, 0x96, 0x90, 0x01, 0xE5, 0xE0, 0x04,
-	0xF0, 0x22, 0xB1, 0xF3, 0x90, 0x00, 0x08, 0xE0,
-	0x54, 0xEF, 0xFD, 0x7F, 0x08, 0x12, 0x32, 0x1E,
-	0xE4, 0xFF, 0x8F, 0x50, 0xE4, 0x90, 0x81, 0x5A,
-	0xF0, 0xA3, 0xF0, 0x90, 0x01, 0x09, 0xE0, 0x7F,
-	0x00, 0x30, 0xE7, 0x02, 0x7F, 0x01, 0xEF, 0x65,
-	0x50, 0x60, 0x3E, 0xC3, 0x90, 0x81, 0x5B, 0xE0,
-	0x94, 0x88, 0x90, 0x81, 0x5A, 0xE0, 0x94, 0x13,
-	0x40, 0x08, 0x90, 0x01, 0xC0, 0xE0, 0x44, 0x10,
-	0xF0, 0x22, 0x90, 0x81, 0x5A, 0xE4, 0x75, 0xF0,
-	0x01, 0x12, 0x44, 0xA9, 0x7F, 0x14, 0x7E, 0x00,
-	0x12, 0x32, 0xAA, 0xD3, 0x90, 0x81, 0x5B, 0xE0,
-	0x94, 0x32, 0x90, 0x81, 0x5A, 0xE0, 0x94, 0x00,
-	0x40, 0xB9, 0x90, 0x01, 0xC6, 0xE0, 0x30, 0xE0,
-	0xB2, 0x22, 0x90, 0x81, 0x31, 0xE0, 0xFD, 0x7F,
-	0x93, 0x12, 0x32, 0x1E, 0x90, 0x81, 0x28, 0xE0,
-	0x60, 0x12, 0x90, 0x01, 0x2F, 0xE0, 0x30, 0xE7,
-	0x05, 0x74, 0x10, 0xF0, 0x80, 0x06, 0x90, 0x01,
-	0x2F, 0x74, 0x90, 0xF0, 0x90, 0x00, 0x08, 0xE0,
-	0x44, 0x10, 0xFD, 0x7F, 0x08, 0x12, 0x32, 0x1E,
-	0x7F, 0x01, 0x91, 0xCA, 0x90, 0x00, 0x90, 0xE0,
-	0x44, 0x01, 0xFD, 0x7F, 0x90, 0x12, 0x32, 0x1E,
-	0x7F, 0x14, 0x7E, 0x00, 0x02, 0x32, 0xAA, 0xD3,
-	0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x12, 0x2D,
-	0xA7, 0xE4, 0xF5, 0x52, 0x12, 0x32, 0x9E, 0xEF,
-	0x60, 0x73, 0x63, 0x52, 0x01, 0xE5, 0x52, 0x24,
-	0x67, 0x90, 0x01, 0xC4, 0xF0, 0x74, 0x5D, 0xA3,
-	0xF0, 0x90, 0x00, 0x88, 0xE0, 0xF5, 0x50, 0xF5,
-	0x51, 0x54, 0x0F, 0x60, 0xDF, 0xE5, 0x50, 0x30,
-	0xE0, 0x0B, 0x20, 0xE4, 0x03, 0x12, 0x29, 0xC5,
-	0x53, 0x51, 0xEE, 0x80, 0x3F, 0xE5, 0x50, 0x30,
-	0xE1, 0x16, 0x20, 0xE5, 0x0E, 0x12, 0x11, 0xBD,
-	0xEF, 0x70, 0x03, 0x43, 0x51, 0x20, 0x90, 0x01,
-	0x06, 0xE4, 0xF0, 0x53, 0x51, 0xFD, 0x80, 0x24,
-	0xE5, 0x50, 0x30, 0xE2, 0x0B, 0x20, 0xE6, 0x03,
-	0x12, 0x67, 0x06, 0x53, 0x51, 0xFB, 0x80, 0x14,
-	0xE5, 0x50, 0x30, 0xE3, 0x0F, 0x20, 0xE7, 0x09,
-	0x12, 0x61, 0x6E, 0xEF, 0x70, 0x03, 0x43, 0x51,
-	0x80, 0x53, 0x51, 0xF7, 0xAD, 0x51, 0x7F, 0x88,
-	0x12, 0x32, 0x1E, 0x80, 0x87, 0xD0, 0xD0, 0x92,
-	0xAF, 0x22, 0x22, 0x90, 0x00, 0x90, 0xE0, 0x20,
-	0xE0, 0xF9, 0x22, 0x90, 0x81, 0x22, 0xE0, 0x64,
-	0x02, 0x7F, 0x01, 0x60, 0x02, 0x7F, 0x00, 0x22,
-	0x7F, 0x02, 0x90, 0x81, 0x41, 0xE0, 0xFE, 0xEF,
-	0xC3, 0x9E, 0x50, 0x18, 0xEF, 0x25, 0xE0, 0x24,
-	0x81, 0xF8, 0xE6, 0x30, 0xE4, 0x0B, 0x90, 0x01,
-	0xB8, 0x74, 0x08, 0xF0, 0xA3, 0xF0, 0x7F, 0x00,
-	0x22, 0x0F, 0x80, 0xDE, 0x7F, 0x01, 0x22, 0x90,
-	0x02, 0x87, 0xE0, 0x60, 0x08, 0x90, 0x01, 0xB8,
-	0x74, 0x01, 0xF0, 0x80, 0x17, 0x90, 0x02, 0x86,
-	0xE0, 0x20, 0xE1, 0x08, 0x90, 0x01, 0xB8, 0x74,
-	0x04, 0xF0, 0x80, 0x08, 0x90, 0x01, 0xB8, 0xE4,
-	0xF0, 0x7F, 0x01, 0x22, 0x90, 0x01, 0xB9, 0x74,
-	0x08, 0xF0, 0x7F, 0x00, 0x22, 0xE4, 0xFB, 0xFA,
-	0xFD, 0x7F, 0x01, 0x12, 0x44, 0x4E, 0x90, 0x81,
-	0xBD, 0xEF, 0xF0, 0x60, 0xF0, 0xD1, 0x71, 0x80,
-	0xEC, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0,
-	0x90, 0x01, 0xCC, 0xE0, 0x54, 0x0F, 0x90, 0x81,
-	0xBE, 0xF0, 0x90, 0x81, 0xBE, 0xE0, 0xFD, 0x70,
-	0x02, 0xE1, 0x9C, 0x90, 0x82, 0x09, 0xE0, 0xFF,
-	0x74, 0x01, 0x7E, 0x00, 0xA8, 0x07, 0x08, 0x80,
-	0x05, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9,
-	0xFF, 0xEF, 0x5D, 0x70, 0x02, 0xE1, 0x95, 0x90,
-	0x82, 0x09, 0xE0, 0x75, 0xF0, 0x04, 0x90, 0x01,
-	0xD0, 0x12, 0x45, 0x0A, 0xE0, 0x90, 0x81, 0xBF,
-	0xF0, 0x75, 0x13, 0x01, 0x75, 0x14, 0x81, 0x75,
-	0x15, 0xBF, 0x75, 0x16, 0x01, 0x7B, 0x01, 0x7A,
-	0x81, 0x79, 0xC0, 0x12, 0x2B, 0xED, 0x90, 0x82,
-	0x09, 0xE0, 0x75, 0xF0, 0x04, 0x90, 0x01, 0xD1,
-	0x12, 0x45, 0x0A, 0xE0, 0x90, 0x81, 0xC1, 0xF0,
-	0x90, 0x82, 0x09, 0xE0, 0x75, 0xF0, 0x04, 0x90,
-	0x01, 0xD2, 0x12, 0x45, 0x0A, 0xE0, 0x90, 0x81,
-	0xC2, 0xF0, 0x90, 0x82, 0x09, 0xE0, 0x75, 0xF0,
-	0x04, 0x90, 0x01, 0xD3, 0x12, 0x45, 0x0A, 0xE0,
-	0x90, 0x81, 0xC3, 0xF0, 0x90, 0x82, 0x09, 0xE0,
-	0x75, 0xF0, 0x04, 0x90, 0x01, 0xF0, 0x12, 0x45,
-	0x0A, 0xE0, 0x90, 0x81, 0xC4, 0xF0, 0x90, 0x82,
-	0x09, 0xE0, 0x75, 0xF0, 0x04, 0x90, 0x01, 0xF1,
-	0x12, 0x45, 0x0A, 0xE0, 0x90, 0x81, 0xC5, 0xF0,
-	0x90, 0x82, 0x09, 0xE0, 0x75, 0xF0, 0x04, 0x90,
-	0x01, 0xF2, 0x12, 0x45, 0x0A, 0xE0, 0x90, 0x81,
-	0xC6, 0xF0, 0x90, 0x82, 0x09, 0xE0, 0x75, 0xF0,
-	0x04, 0x90, 0x01, 0xF3, 0x12, 0x45, 0x0A, 0xE0,
-	0x90, 0x81, 0xC7, 0xF0, 0x90, 0x81, 0xBE, 0xE0,
-	0xFF, 0x90, 0x82, 0x09, 0xE0, 0xFE, 0x74, 0x01,
-	0xA8, 0x06, 0x08, 0x80, 0x02, 0xC3, 0x33, 0xD8,
-	0xFC, 0xF4, 0x5F, 0x90, 0x81, 0xBE, 0xF0, 0x90,
-	0x82, 0x09, 0xE0, 0xFF, 0x74, 0x01, 0xA8, 0x07,
-	0x08, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0x90,
-	0x01, 0xCC, 0xF0, 0x90, 0x81, 0xC0, 0xE0, 0xFF,
-	0x7B, 0x01, 0x7A, 0x81, 0x79, 0xC1, 0x12, 0x55,
-	0x3F, 0x90, 0x82, 0x09, 0xE0, 0x04, 0xF0, 0xE0,
-	0x54, 0x03, 0xF0, 0xC1, 0x82, 0x90, 0x01, 0xC0,
-	0xE0, 0x44, 0x02, 0xF0, 0xD0, 0xD0, 0x92, 0xAF,
-	0x22, 0xE4, 0xFB, 0xFA, 0xFD, 0x7F, 0x01, 0x12,
-	0x44, 0x4E, 0x90, 0x81, 0xD0, 0xEF, 0xF0, 0x60,
-	0xF0, 0x12, 0x6C, 0x19, 0x80, 0xEB, 0x90, 0x81,
-	0xD4, 0xEF, 0xF0, 0xA3, 0xED, 0xF0, 0xA3, 0x12,
-	0x20, 0xDA, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x90,
-	0x81, 0xE2, 0xF0, 0x7F, 0x24, 0x7E, 0x08, 0x12,
-	0x2D, 0x5C, 0x90, 0x81, 0xDA, 0x12, 0x20, 0xCE,
-	0x90, 0x81, 0xD4, 0xE0, 0xFB, 0x70, 0x08, 0x90,
-	0x81, 0xDA, 0x12, 0x44, 0xD9, 0x80, 0x16, 0xEB,
-	0x75, 0xF0, 0x08, 0xA4, 0x24, 0x62, 0xF5, 0x82,
-	0xE4, 0x34, 0x87, 0xF5, 0x83, 0xE0, 0xFE, 0xA3,
-	0xE0, 0xFF, 0x12, 0x2D, 0x5C, 0x90, 0x81, 0xDE,
-	0x12, 0x20, 0xCE, 0x90, 0x81, 0xD5, 0xE0, 0xFF,
-	0xE4, 0xFC, 0xFD, 0xFE, 0x78, 0x17, 0x12, 0x20,
-	0xBB, 0xA8, 0x04, 0xA9, 0x05, 0xAA, 0x06, 0xAB,
-	0x07, 0x90, 0x81, 0xDE, 0x12, 0x44, 0xD9, 0xED,
-	0x54, 0x7F, 0xFD, 0xEC, 0x54, 0x80, 0xFC, 0x12,
-	0x44, 0xCC, 0xEC, 0x44, 0x80, 0xFC, 0x90, 0x81,
-	0xDE, 0x12, 0x20, 0xCE, 0x90, 0x81, 0xDA, 0x12,
-	0x44, 0xD9, 0xEC, 0x54, 0x7F, 0xFC, 0x90, 0x85,
-	0xBB, 0x12, 0x20, 0xCE, 0x7F, 0x24, 0x7E, 0x08,
-	0x12, 0x2E, 0xA2, 0x90, 0x81, 0xD4, 0xE0, 0x75,
-	0xF0, 0x08, 0xA4, 0x24, 0x62, 0xF5, 0x82, 0xE4,
-	0x34, 0x87, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0,
-	0xFF, 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x81, 0xDE,
-	0x12, 0x44, 0xD9, 0x90, 0x85, 0xBB, 0x12, 0x20,
-	0xCE, 0xD0, 0x07, 0xD0, 0x06, 0x12, 0x2E, 0xA2,
-	0x90, 0x81, 0xDA, 0x12, 0x44, 0xD9, 0xEC, 0x44,
-	0x80, 0xFC, 0x90, 0x85, 0xBB, 0x12, 0x20, 0xCE,
-	0x7F, 0x24, 0x7E, 0x08, 0x12, 0x2E, 0xA2, 0x90,
-	0x81, 0xD4, 0xE0, 0x70, 0x04, 0x7F, 0x20, 0x80,
-	0x09, 0x90, 0x81, 0xD4, 0xE0, 0xB4, 0x01, 0x16,
-	0x7F, 0x28, 0x7E, 0x08, 0x12, 0x2D, 0x5C, 0x78,
-	0x08, 0x12, 0x20, 0xA8, 0xEF, 0x54, 0x01, 0xFF,
-	0xE4, 0x90, 0x81, 0xE2, 0xEF, 0xF0, 0x90, 0x81,
-	0xE2, 0xE0, 0x90, 0x81, 0xD4, 0x60, 0x0E, 0xE0,
-	0x75, 0xF0, 0x08, 0xA4, 0x24, 0x66, 0xF5, 0x82,
-	0xE4, 0x34, 0x87, 0x80, 0x0C, 0xE0, 0x75, 0xF0,
-	0x08, 0xA4, 0x24, 0x64, 0xF5, 0x82, 0xE4, 0x34,
-	0x87, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,
-	0x12, 0x2D, 0x5C, 0xED, 0x54, 0x0F, 0xFD, 0xE4,
-	0xFC, 0x90, 0x81, 0xD6, 0x12, 0x20, 0xCE, 0x90,
-	0x81, 0xD6, 0x02, 0x44, 0xD9, 0x90, 0x81, 0xE3,
-	0xEF, 0xF0, 0xAB, 0x05, 0x90, 0x81, 0xE9, 0x12,
-	0x20, 0xDA, 0x00, 0x00, 0x00, 0x00, 0xAF, 0x03,
-	0xE4, 0xFC, 0xFD, 0xFE, 0x78, 0x14, 0x12, 0x20,
-	0xBB, 0xA8, 0x04, 0xA9, 0x05, 0xAA, 0x06, 0xAB,
-	0x07, 0x90, 0x81, 0xE5, 0x12, 0x44, 0xD9, 0xED,
-	0x54, 0x0F, 0xFD, 0xE4, 0xFC, 0x12, 0x44, 0xCC,
-	0xEC, 0x54, 0x0F, 0xFC, 0x90, 0x81, 0xE9, 0x12,
-	0x20, 0xCE, 0x90, 0x81, 0xE3, 0xE0, 0x75, 0xF0,
-	0x08, 0xA4, 0x24, 0x60, 0xF5, 0x82, 0xE4, 0x34,
-	0x87, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,
-	0xC0, 0x06, 0xC0, 0x07, 0x90, 0x81, 0xE9, 0x12,
-	0x44, 0xD9, 0x90, 0x85, 0xBB, 0x12, 0x20, 0xCE,
-	0xD0, 0x07, 0xD0, 0x06, 0x02, 0x2E, 0xA2, 0xD3,
-	0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x12, 0x5F,
-	0xB6, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x78, 0x10,
-	0x74, 0x01, 0xF2, 0x90, 0x02, 0x09, 0xE0, 0x78,
-	0x00, 0xF2, 0x08, 0x74, 0x20, 0xF2, 0x18, 0xE2,
-	0xFF, 0x30, 0xE0, 0x05, 0x08, 0xE2, 0x24, 0x80,
-	0xF2, 0xEF, 0xC3, 0x13, 0x90, 0xFD, 0x10, 0xF0,
-	0x78, 0x01, 0xE2, 0x24, 0x00, 0xF5, 0x82, 0xE4,
-	0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x78, 0x03, 0xF2,
-	0x64, 0x04, 0x60, 0x0D, 0xE2, 0xFF, 0x64, 0x08,
-	0x60, 0x07, 0xEF, 0x64, 0x0C, 0x60, 0x02, 0x61,
-	0xDE, 0xE4, 0x78, 0x02, 0xF2, 0x78, 0x03, 0xE2,
-	0xFF, 0x18, 0xE2, 0xC3, 0x9F, 0x50, 0x2D, 0xE2,
-	0xFD, 0x18, 0xE2, 0x2D, 0x90, 0x81, 0x5A, 0xF0,
-	0xE0, 0xFF, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34,
-	0xFC, 0xF5, 0x83, 0xE0, 0xFE, 0x74, 0x04, 0x2D,
-	0xF8, 0xEE, 0xF2, 0xEF, 0xB4, 0xFF, 0x06, 0x90,
-	0xFD, 0x10, 0xE0, 0x04, 0xF0, 0x78, 0x02, 0xE2,
-	0x04, 0xF2, 0x80, 0xC9, 0x78, 0x04, 0xE2, 0x78,
-	0x12, 0xF2, 0xFF, 0x78, 0x05, 0xE2, 0x78, 0x11,
-	0xF2, 0x78, 0x06, 0xE2, 0x78, 0x13, 0xF2, 0x78,
-	0x07, 0xE2, 0x78, 0x14, 0xF2, 0x78, 0x08, 0xE2,
-	0x78, 0x33, 0xF2, 0x78, 0x09, 0xE2, 0x78, 0x34,
-	0xF2, 0x78, 0x0A, 0xE2, 0x78, 0x35, 0xF2, 0x78,
-	0x0B, 0xE2, 0x78, 0x36, 0xF2, 0x78, 0x0C, 0xE2,
-	0x78, 0x37, 0xF2, 0x78, 0x0D, 0xE2, 0x78, 0x38,
-	0xF2, 0x78, 0x0E, 0xE2, 0x78, 0x39, 0xF2, 0x78,
-	0x0F, 0xE2, 0x78, 0x3A, 0xF2, 0xE4, 0x78, 0x15,
-	0xF2, 0xEF, 0x24, 0xF8, 0x60, 0x75, 0x24, 0xFC,
-	0x60, 0x6C, 0x24, 0x08, 0x60, 0x02, 0x61, 0xC0,
-	0x78, 0x11, 0xE2, 0xB4, 0x01, 0x05, 0x12, 0x29,
-	0xC5, 0x61, 0xC5, 0x78, 0x11, 0xE2, 0xB4, 0x02,
-	0x05, 0x12, 0x11, 0xBD, 0x61, 0xC5, 0x78, 0x11,
-	0xE2, 0xB4, 0x03, 0x04, 0xF1, 0x06, 0x61, 0xC5,
-	0x78, 0x11, 0xE2, 0xB4, 0x10, 0x17, 0x78, 0x14,
-	0xE2, 0xFE, 0x18, 0xE2, 0xFD, 0xED, 0xFF, 0x78,
-	0x16, 0xEE, 0xF2, 0xFE, 0x08, 0xEF, 0xF2, 0xFF,
-	0x12, 0x32, 0xAA, 0x61, 0xC5, 0x78, 0x11, 0xE2,
-	0xB4, 0x11, 0x17, 0x78, 0x14, 0xE2, 0xFE, 0x18,
-	0xE2, 0xFD, 0xED, 0xFF, 0x78, 0x16, 0xEE, 0xF2,
-	0xFE, 0x08, 0xEF, 0xF2, 0xFF, 0x12, 0x32, 0x06,
-	0x61, 0xC5, 0x78, 0x11, 0xE2, 0xF4, 0x60, 0x02,
-	0x61, 0xC5, 0x18, 0xF2, 0x61, 0xC5, 0x78, 0x15,
-	0x74, 0x01, 0xF2, 0x78, 0x11, 0xE2, 0x64, 0x07,
-	0x60, 0x02, 0x61, 0xAA, 0x78, 0x34, 0xE2, 0xFF,
-	0xE4, 0xFC, 0xFD, 0xFE, 0x78, 0x08, 0x12, 0x20,
-	0xBB, 0xC0, 0x04, 0xA9, 0x05, 0xAA, 0x06, 0xAB,
-	0x07, 0x78, 0x33, 0xE2, 0xFF, 0xE4, 0xFC, 0xFD,
-	0xFE, 0xD0, 0x00, 0x12, 0x44, 0xCC, 0xC0, 0x04,
-	0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, 0x78, 0x35,
-	0xE2, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, 0x78, 0x10,
-	0x12, 0x20, 0xBB, 0xD0, 0x03, 0xD0, 0x02, 0xD0,
-	0x01, 0xD0, 0x00, 0x12, 0x44, 0xCC, 0x78, 0x18,
-	0x12, 0x44, 0xFE, 0x78, 0x15, 0xE2, 0x70, 0x02,
-	0x61, 0x93, 0x18, 0xE2, 0xFF, 0x18, 0xE2, 0xFD,
-	0x31, 0x5F, 0x78, 0x1C, 0x12, 0x44, 0xFE, 0x78,
-	0x38, 0xE2, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, 0x78,
-	0x08, 0x12, 0x20, 0xBB, 0xC0, 0x04, 0xA9, 0x05,
-	0xAA, 0x06, 0xAB, 0x07, 0x78, 0x37, 0xE2, 0xFF,
-	0xE4, 0xFC, 0xFD, 0xFE, 0xD0, 0x00, 0x12, 0x44,
-	0xCC, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0,
-	0x07, 0x78, 0x39, 0xE2, 0xFF, 0xE4, 0xFC, 0xFD,
-	0xFE, 0x78, 0x10, 0x12, 0x20, 0xBB, 0xD0, 0x03,
-	0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0x12, 0x44,
-	0xCC, 0x78, 0x20, 0x12, 0x44, 0xFE, 0x78, 0x20,
-	0x12, 0x44, 0xE5, 0x12, 0x20, 0x9B, 0x78, 0x1C,
-	0x12, 0x44, 0xF1, 0x12, 0x44, 0xBF, 0xC0, 0x04,
-	0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, 0x78, 0x18,
-	0x12, 0x44, 0xE5, 0x78, 0x20, 0x12, 0x44, 0xF1,
-	0x12, 0x44, 0xBF, 0xD0, 0x03, 0xD0, 0x02, 0xD0,
-	0x01, 0xD0, 0x00, 0x12, 0x44, 0xCC, 0x78, 0x18,
-	0x12, 0x44, 0xFE, 0x78, 0x18, 0x12, 0x44, 0xE5,
-	0x90, 0x81, 0xF9, 0x12, 0x20, 0xCE, 0x78, 0x13,
-	0xE2, 0xFD, 0x08, 0xE2, 0xFF, 0x12, 0x55, 0x1C,
-	0x80, 0x1B, 0x78, 0x13, 0xE2, 0xFF, 0x08, 0xE2,
-	0xFD, 0x78, 0x11, 0xE2, 0xFB, 0x78, 0x15, 0xE2,
-	0x90, 0x81, 0xBC, 0xF0, 0x71, 0xE1, 0x80, 0x05,
-	0x78, 0x10, 0x74, 0x02, 0xF2, 0x78, 0x10, 0xE2,
-	0xFF, 0xC3, 0x94, 0x02, 0x50, 0x10, 0xEF, 0x60,
-	0x0A, 0x78, 0x02, 0xE2, 0xFF, 0x18, 0xE2, 0x2F,
-	0xF2, 0x21, 0x90, 0x7F, 0x01, 0x22, 0x7F, 0x00,
-	0x22, 0xAC, 0x07, 0xED, 0xAD, 0x04, 0x78, 0x24,
-	0xF2, 0xED, 0x08, 0xF2, 0xEB, 0xB4, 0x04, 0x07,
-	0x78, 0x27, 0x74, 0x01, 0xF2, 0x80, 0x0E, 0xEB,
-	0x78, 0x27, 0xB4, 0x05, 0x05, 0x74, 0x02, 0xF2,
-	0x80, 0x03, 0x74, 0x04, 0xF2, 0xD3, 0x78, 0x25,
-	0xE2, 0x94, 0xFF, 0x18, 0xE2, 0x94, 0x00, 0x50,
-	0x63, 0xE4, 0x78, 0x26, 0xF2, 0x78, 0x27, 0xE2,
-	0xFF, 0x18, 0xE2, 0xFE, 0xC3, 0x9F, 0x40, 0x02,
-	0xA1, 0x7F, 0x74, 0x33, 0x2E, 0xF8, 0xE2, 0x78,
-	0x28, 0xF2, 0x90, 0x81, 0xBC, 0xE0, 0x60, 0x2D,
-	0x74, 0x37, 0x2E, 0xF8, 0xE2, 0x78, 0x32, 0xF2,
-	0xEE, 0xFF, 0x78, 0x25, 0xE2, 0x2F, 0xFF, 0x18,
-	0xE2, 0x34, 0x00, 0x8F, 0x82, 0xF5, 0x83, 0xE0,
-	0x78, 0x29, 0xF2, 0x78, 0x32, 0xE2, 0xFF, 0xF4,
-	0xFE, 0x78, 0x29, 0xE2, 0x5E, 0xFE, 0x18, 0xE2,
-	0xFD, 0xEF, 0x5D, 0x4E, 0xF2, 0x78, 0x24, 0x08,
-	0xE2, 0xFF, 0x08, 0xE2, 0x2F, 0xFF, 0x78, 0x28,
-	0xE2, 0xFD, 0x12, 0x32, 0x1E, 0x78, 0x26, 0xE2,
-	0x04, 0xF2, 0x80, 0xA1, 0xD3, 0x78, 0x25, 0xE2,
-	0x94, 0xFF, 0x18, 0xE2, 0x94, 0x07, 0x50, 0x69,
-	0xE4, 0x78, 0x26, 0xF2, 0x78, 0x27, 0xE2, 0xFF,
-	0x18, 0xE2, 0xFE, 0xC3, 0x9F, 0x40, 0x02, 0xA1,
-	0x7F, 0x74, 0x33, 0x2E, 0xF8, 0xE2, 0x78, 0x28,
-	0xF2, 0x90, 0x81, 0xBC, 0xE0, 0x60, 0x2D, 0x78,
-	0x26, 0xE2, 0xFF, 0xFD, 0x18, 0xE2, 0x2D, 0xFD,
-	0x18, 0xE2, 0x34, 0x00, 0x8D, 0x82, 0xF5, 0x83,
-	0xE0, 0x78, 0x29, 0xF2, 0x74, 0x37, 0x2F, 0xF8,
-	0xE2, 0x78, 0x32, 0xF2, 0xE2, 0xFF, 0xF4, 0xFE,
-	0x78, 0x29, 0xE2, 0x5E, 0xFE, 0x18, 0xE2, 0xFD,
-	0xEF, 0x5D, 0x4E, 0xF2, 0x78, 0x28, 0xE2, 0xFF,
-	0x78, 0x26, 0xE2, 0xFD, 0x18, 0xE2, 0x2D, 0xFD,
-	0x18, 0xE2, 0x34, 0x00, 0x8D, 0x82, 0xF5, 0x83,
-	0xEF, 0xF0, 0x78, 0x26, 0xE2, 0x04, 0xF2, 0x80,
-	0x9B, 0x90, 0x81, 0xBC, 0xE0, 0x60, 0x0F, 0x78,
-	0x24, 0xE2, 0xFE, 0x08, 0xE2, 0xFF, 0x12, 0x2D,
-	0x5C, 0x78, 0x2E, 0x12, 0x44, 0xFE, 0xE4, 0x78,
-	0x26, 0xF2, 0x78, 0x27, 0xE2, 0xFF, 0x18, 0xE2,
-	0xFE, 0xC3, 0x9F, 0x50, 0x5D, 0x74, 0x33, 0x2E,
-	0xF8, 0xE2, 0x78, 0x28, 0xF2, 0x90, 0x81, 0xBC,
-	0xE0, 0x60, 0x2B, 0x78, 0x2E, 0x12, 0x44, 0xE5,
-	0x78, 0x26, 0xE2, 0xFB, 0x75, 0xF0, 0x08, 0xA4,
-	0xF9, 0xF8, 0x12, 0x20, 0xA8, 0x78, 0x29, 0xEF,
-	0xF2, 0x74, 0x37, 0x2B, 0xF8, 0xE2, 0x78, 0x32,
-	0xF2, 0xE2, 0xFE, 0xF4, 0x5F, 0xFF, 0x78, 0x28,
-	0xE2, 0xFD, 0xEE, 0x5D, 0x4F, 0xF2, 0x78, 0x28,
-	0xE2, 0xFF, 0x78, 0x26, 0xE2, 0xFD, 0xC3, 0x74,
-	0x03, 0x9D, 0xFD, 0xE4, 0x94, 0x00, 0xFC, 0x7B,
-	0xFE, 0x74, 0x2A, 0x2D, 0xF9, 0x74, 0x80, 0x3C,
-	0xFA, 0xEF, 0x12, 0x1F, 0xEA, 0xE2, 0x04, 0xF2,
-	0x80, 0x98, 0x78, 0x2A, 0x12, 0x44, 0xE5, 0x90,
-	0x85, 0xBB, 0x12, 0x20, 0xCE, 0x78, 0x24, 0xE2,
-	0xFE, 0x08, 0xE2, 0xFF, 0x12, 0x2E, 0xA2, 0x22,
-	0x22, 0x90, 0x81, 0xCB, 0x12, 0x45, 0x1F, 0x90,
-	0x00, 0x01, 0x12, 0x1F, 0xBD, 0xFF, 0xFE, 0x12,
-	0x1F, 0xA4, 0xFD, 0xC3, 0x13, 0x30, 0xE0, 0x12,
-	0x90, 0x81, 0xCB, 0x12, 0x45, 0x16, 0x90, 0x00,
-	0x02, 0x12, 0x1F, 0xBD, 0x90, 0x81, 0xCF, 0xF0,
-	0x80, 0x05, 0x90, 0x81, 0xCF, 0xEF, 0xF0, 0x90,
-	0x81, 0xCE, 0xEE, 0xF0, 0x90, 0x81, 0xCF, 0xE0,
-	0xFE, 0x90, 0x81, 0xCE, 0xE0, 0xFF, 0xD3, 0x9E,
-	0x50, 0x38, 0x90, 0x81, 0xCB, 0x12, 0x45, 0x16,
-	0x12, 0x1F, 0xA4, 0x54, 0x01, 0xFE, 0x74, 0xDE,
-	0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x80, 0xF5, 0x83,
-	0xEE, 0xF0, 0x74, 0xDE, 0x2F, 0xF5, 0x82, 0xE4,
-	0x34, 0x80, 0xF5, 0x83, 0xE0, 0x70, 0x04, 0xD1,
-	0x25, 0x80, 0x07, 0x90, 0x81, 0xCE, 0xE0, 0xFF,
-	0xB1, 0x80, 0x90, 0x81, 0xCE, 0xE0, 0x04, 0xF0,
-	0x80, 0xBA, 0x90, 0x80, 0xDE, 0xE0, 0x70, 0x24,
-	0x90, 0x81, 0x2A, 0xE0, 0x70, 0x04, 0xFF, 0x12,
-	0x49, 0x93, 0x90, 0x81, 0x2A, 0xE0, 0x64, 0x0C,
-	0x60, 0x02, 0xD1, 0x26, 0x90, 0x81, 0x24, 0xE0,
-	0x54, 0xF7, 0xF0, 0x54, 0xEF, 0xF0, 0x54, 0xBF,
-	0xF0, 0x54, 0x7F, 0xF0, 0x22, 0x22, 0x90, 0x06,
-	0x04, 0xE0, 0x54, 0x7F, 0xF0, 0x90, 0x05, 0x22,
-	0xE4, 0xF0, 0x90, 0x81, 0x2A, 0x74, 0x0C, 0xF0,
-	0x22, 0x90, 0x81, 0xED, 0xEF, 0xF0, 0xA3, 0xED,
-	0xF0, 0xAD, 0x03, 0xAC, 0x02, 0xE4, 0x90, 0x81,
-	0xF5, 0xF0, 0xA3, 0xF0, 0x90, 0x01, 0xC4, 0x74,
-	0x39, 0xF0, 0x74, 0x66, 0xA3, 0xF0, 0xEC, 0x54,
-	0x3F, 0xFC, 0x90, 0x01, 0x40, 0xED, 0xF0, 0xAE,
-	0x04, 0xEE, 0xA3, 0xF0, 0x90, 0x81, 0xED, 0xE0,
-	0x24, 0x81, 0x60, 0x34, 0x24, 0xDA, 0x60, 0x1C,
-	0x24, 0x3C, 0x70, 0x41, 0x90, 0x81, 0xEE, 0xE0,
-	0xC4, 0x33, 0x33, 0x33, 0x54, 0x80, 0x90, 0x81,
-	0xF2, 0xF0, 0xA3, 0x74, 0x69, 0xF0, 0xA3, 0x74,
-	0x80, 0xF0, 0x80, 0x2C, 0x90, 0x81, 0xEE, 0xE0,
-	0x54, 0x01, 0x90, 0x81, 0xF2, 0xF0, 0xA3, 0x74,
-	0xA5, 0xF0, 0xA3, 0x74, 0x01, 0xF0, 0x80, 0x18,
-	0x90, 0x81, 0xEE, 0xE0, 0xC4, 0x54, 0x10, 0x90,
-	0x81, 0xF2, 0xF0, 0xA3, 0x74, 0x7F, 0xF0, 0xA3,
-	0x74, 0x10, 0xF0, 0x80, 0x03, 0x7F, 0x00, 0x22,
-	0x90, 0x81, 0xF3, 0xE0, 0x90, 0x01, 0x06, 0xF0,
-	0x90, 0x81, 0xF2, 0xE0, 0x60, 0x0E, 0x90, 0x01,
-	0x42, 0xF0, 0x90, 0x81, 0xF1, 0xE0, 0x90, 0x01,
-	0x43, 0xF0, 0x80, 0x0D, 0x90, 0x01, 0x43, 0xE4,
-	0xF0, 0x90, 0x81, 0xF2, 0xE0, 0x90, 0x01, 0x42,
-	0xF0, 0x90, 0x81, 0xF4, 0xE0, 0xFF, 0x90, 0x01,
-	0x42, 0xE0, 0x5F, 0xFF, 0x90, 0x81, 0xF2, 0xE0,
-	0x6F, 0x60, 0xEE, 0x74, 0x39, 0x04, 0x90, 0x01,
-	0xC4, 0xF0, 0x74, 0x66, 0xA3, 0xF0, 0x90, 0x01,
-	0x43, 0xE4, 0xF0, 0x7F, 0x01, 0x22, 0xE4, 0x90,
-	0x81, 0x6A, 0xF0, 0x90, 0x87, 0x5F, 0xE0, 0x90,
-	0x81, 0x69, 0xF0, 0xE4, 0x90, 0x81, 0x76, 0xF0,
-	0x90, 0x81, 0x66, 0xF0, 0x90, 0x81, 0x66, 0xE0,
-	0xFF, 0xC3, 0x94, 0x40, 0x50, 0x15, 0x74, 0x79,
-	0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83,
-	0x74, 0xFF, 0xF0, 0x90, 0x81, 0x66, 0xE0, 0x04,
-	0xF0, 0x80, 0xE1, 0xE4, 0x90, 0x81, 0x66, 0xF0,
-	0x90, 0x81, 0x69, 0xE0, 0xFF, 0x90, 0x81, 0x66,
-	0xE0, 0xFE, 0xC3, 0x9F, 0x40, 0x03, 0x02, 0x68,
-	0x12, 0x74, 0xDF, 0x2E, 0xF9, 0xE4, 0x34, 0x86,
-	0x75, 0x13, 0x01, 0xF5, 0x14, 0x89, 0x15, 0x75,
-	0x16, 0x0A, 0x7B, 0x01, 0x7A, 0x81, 0x79, 0x5B,
-	0x12, 0x2B, 0xED, 0x90, 0x81, 0x5C, 0xE0, 0xFF,
-	0x12, 0x2F, 0x27, 0xEF, 0x04, 0x90, 0x81, 0x76,
-	0xF0, 0x90, 0x81, 0x5B, 0xE0, 0xFF, 0xA3, 0xE0,
-	0xFD, 0x12, 0x31, 0xEA, 0xEF, 0x24, 0xC8, 0x90,
-	0x81, 0x78, 0xF0, 0x75, 0xF0, 0x08, 0xA4, 0xF0,
-	0x90, 0x81, 0x5C, 0xE0, 0x54, 0x0F, 0x90, 0x81,
-	0x77, 0xF0, 0xE4, 0x90, 0x81, 0x65, 0xF0, 0x90,
-	0x81, 0x67, 0xF0, 0x90, 0x81, 0x67, 0xE0, 0xFF,
-	0xC3, 0x94, 0x04, 0x50, 0x57, 0x90, 0x81, 0x77,
-	0xE0, 0xFE, 0xA8, 0x07, 0x08, 0x80, 0x02, 0xC3,
-	0x13, 0xD8, 0xFC, 0x20, 0xE0, 0x3E, 0x90, 0x81,
-	0x67, 0xE0, 0x25, 0xE0, 0xFF, 0x90, 0x81, 0x78,
-	0xE0, 0x2F, 0x24, 0x79, 0xF9, 0xE4, 0x34, 0x81,
-	0xFA, 0x7B, 0x01, 0xC0, 0x03, 0xC0, 0x01, 0x90,
-	0x81, 0x65, 0xE0, 0x75, 0xF0, 0x02, 0xA4, 0x24,
-	0x5D, 0xF9, 0x74, 0x81, 0x35, 0xF0, 0x8B, 0x13,
-	0xF5, 0x14, 0x89, 0x15, 0x75, 0x16, 0x02, 0xD0,
-	0x01, 0xD0, 0x03, 0x12, 0x2B, 0xED, 0x90, 0x81,
-	0x65, 0xE0, 0x04, 0xF0, 0x90, 0x81, 0x67, 0xE0,
-	0x04, 0xF0, 0x80, 0x9F, 0x90, 0x81, 0x76, 0xE0,
-	0xFF, 0x90, 0x81, 0x66, 0xE0, 0x2F, 0xF0, 0x02,
-	0x67, 0x40, 0xE4, 0x90, 0x81, 0x6A, 0xF0, 0x90,
-	0x81, 0x6A, 0xE0, 0xC3, 0x94, 0x40, 0x40, 0x02,
-	0x41, 0xAF, 0xE0, 0xFF, 0x24, 0x79, 0xF5, 0x82,
-	0xE4, 0x34, 0x81, 0xF5, 0x83, 0xE0, 0x90, 0x81,
-	0x6C, 0xF0, 0xE0, 0xFE, 0x54, 0xF0, 0xC4, 0x54,
-	0x0F, 0xFD, 0x90, 0x81, 0x6B, 0xF0, 0xEE, 0x54,
-	0x0F, 0xFE, 0xA3, 0xF0, 0x74, 0x7A, 0x2F, 0xF5,
-	0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83, 0xE0, 0x90,
-	0x81, 0x6D, 0xF0, 0xFC, 0xEE, 0xFE, 0xEC, 0xFB,
-	0xEB, 0xFF, 0x90, 0x81, 0x72, 0xEE, 0xF0, 0xA3,
-	0xEF, 0xF0, 0xED, 0x12, 0x45, 0x28, 0x68, 0x8B,
-	0x00, 0x68, 0xC2, 0x01, 0x69, 0x73, 0x02, 0x6A,
-	0xA0, 0x03, 0x69, 0x8E, 0x04, 0x69, 0xAF, 0x05,
-	0x69, 0xAF, 0x06, 0x69, 0xAF, 0x07, 0x69, 0xAF,
-	0x08, 0x6A, 0x33, 0x09, 0x6A, 0x69, 0x0A, 0x00,
-	0x00, 0x6A, 0xAF, 0x90, 0x81, 0x6A, 0xE0, 0xFD,
-	0x24, 0x7C, 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5,
-	0x83, 0xE0, 0xFE, 0x74, 0x7B, 0x2D, 0xF5, 0x82,
-	0xE4, 0x34, 0x81, 0xF5, 0x83, 0xE0, 0xFD, 0xED,
-	0xFF, 0x90, 0x81, 0x74, 0xEE, 0xF0, 0xFC, 0xA3,
-	0xEF, 0xF0, 0x90, 0x81, 0x6D, 0xE0, 0xFF, 0x12,
-	0x2F, 0x96, 0x90, 0x81, 0x68, 0x74, 0x02, 0xF0,
-	0x41, 0xA0, 0x90, 0x81, 0x6A, 0xE0, 0x24, 0x7C,
-	0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83, 0xE0,
-	0xFF, 0xE4, 0xFC, 0xFD, 0xFE, 0x78, 0x08, 0x12,
-	0x20, 0xBB, 0xA8, 0x04, 0xA9, 0x05, 0xAA, 0x06,
-	0xAB, 0x07, 0x90, 0x81, 0x6A, 0xE0, 0x24, 0x7B,
-	0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83, 0xE0,
-	0xFF, 0xE4, 0xFC, 0xFD, 0xFE, 0x12, 0x44, 0xCC,
-	0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07,
-	0x90, 0x81, 0x6A, 0xE0, 0x24, 0x7D, 0xF5, 0x82,
-	0xE4, 0x34, 0x81, 0xF5, 0x83, 0xE0, 0xFF, 0xE4,
-	0xFC, 0xFD, 0xFE, 0x78, 0x10, 0x12, 0x20, 0xBB,
-	0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00,
-	0x12, 0x44, 0xCC, 0xC0, 0x04, 0xC0, 0x05, 0xC0,
-	0x06, 0xC0, 0x07, 0x90, 0x81, 0x6A, 0xE0, 0x24,
-	0x7E, 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83,
-	0xE0, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, 0x78, 0x18,
-	0x12, 0x20, 0xBB, 0xD0, 0x03, 0xD0, 0x02, 0xD0,
-	0x01, 0xD0, 0x00, 0x12, 0x44, 0xCC, 0x90, 0x81,
-	0x6E, 0x12, 0x20, 0xCE, 0x90, 0x81, 0x6E, 0x12,
-	0x44, 0xD9, 0x90, 0x85, 0x96, 0x12, 0x20, 0xCE,
-	0x90, 0x81, 0x72, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF,
-	0x12, 0x2E, 0xE4, 0x90, 0x81, 0x68, 0x74, 0x04,
-	0xF0, 0x41, 0xA0, 0x90, 0x81, 0x6D, 0xE0, 0xFD,
-	0x90, 0x81, 0x6A, 0xE0, 0x24, 0x7B, 0xF5, 0x82,
-	0xE4, 0x34, 0x81, 0xF5, 0x83, 0xE0, 0xFB, 0xE4,
-	0xFF, 0x12, 0x30, 0xC7, 0x80, 0x19, 0x90, 0x81,
-	0x6D, 0xE0, 0xFD, 0x90, 0x81, 0x6A, 0xE0, 0x24,
-	0x7B, 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83,
-	0xE0, 0xFB, 0xE4, 0xFF, 0x12, 0x30, 0x6A, 0x90,
-	0x81, 0x68, 0x74, 0x01, 0xF0, 0x41, 0xA0, 0x90,
-	0x81, 0x68, 0x74, 0x02, 0xF0, 0x90, 0x81, 0x6A,
-	0xE0, 0x24, 0x7C, 0xF5, 0x82, 0xE4, 0x34, 0x81,
-	0xF5, 0x83, 0xE0, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE,
-	0x78, 0x08, 0x12, 0x20, 0xBB, 0xA8, 0x04, 0xA9,
-	0x05, 0xAA, 0x06, 0xAB, 0x07, 0x90, 0x81, 0x6A,
-	0xE0, 0x24, 0x7B, 0xF5, 0x82, 0xE4, 0x34, 0x81,
-	0xF5, 0x83, 0xE0, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE,
-	0x12, 0x44, 0xCC, 0xC0, 0x04, 0xC0, 0x05, 0xC0,
-	0x06, 0xC0, 0x07, 0x90, 0x81, 0x6C, 0xE0, 0xFF,
-	0xE4, 0xFC, 0xFD, 0xFE, 0x78, 0x10, 0x12, 0x20,
-	0xBB, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0,
-	0x00, 0x12, 0x44, 0xCC, 0x90, 0x81, 0x6E, 0x12,
-	0x20, 0xCE, 0x90, 0x81, 0x6B, 0xE0, 0x24, 0xFB,
-	0xFF, 0xC0, 0x07, 0x90, 0x81, 0x6E, 0x12, 0x44,
-	0xD9, 0x90, 0x81, 0xF9, 0x12, 0x20, 0xCE, 0x90,
-	0x81, 0x6D, 0xE0, 0xFD, 0xD0, 0x07, 0x12, 0x55,
-	0x1C, 0x80, 0x6D, 0x90, 0x81, 0x68, 0x74, 0x01,
-	0xF0, 0x90, 0x81, 0x6A, 0xE0, 0x24, 0x7B, 0xF9,
-	0xE4, 0x34, 0x81, 0x75, 0x13, 0x01, 0xF5, 0x14,
-	0x89, 0x15, 0x75, 0x16, 0x01, 0x7B, 0xFE, 0x7A,
-	0x80, 0x79, 0x33, 0x12, 0x2B, 0xED, 0x90, 0x81,
-	0x6D, 0xE0, 0xFF, 0x90, 0x81, 0x6C, 0xE0, 0xFD,
-	0xE4, 0x90, 0x81, 0xBC, 0xF0, 0x7B, 0x04, 0x80,
-	0x34, 0x90, 0x81, 0x68, 0x74, 0x04, 0xF0, 0x90,
-	0x81, 0x6A, 0xE0, 0x24, 0x7B, 0xF9, 0xE4, 0x34,
-	0x81, 0x75, 0x13, 0x01, 0xF5, 0x14, 0x89, 0x15,
-	0x75, 0x16, 0x04, 0x7B, 0xFE, 0x7A, 0x80, 0x79,
-	0x33, 0x12, 0x2B, 0xED, 0x90, 0x81, 0x6D, 0xE0,
-	0xFF, 0x90, 0x81, 0x6C, 0xE0, 0xFD, 0xE4, 0x90,
-	0x81, 0xBC, 0xF0, 0x7B, 0x06, 0x12, 0x63, 0xE1,
-	0x90, 0x81, 0x68, 0xE0, 0x24, 0x02, 0xFF, 0x90,
-	0x81, 0x6A, 0xE0, 0x2F, 0xF0, 0x01, 0x17, 0x22,
-	0x90, 0x02, 0x09, 0xE0, 0xFD, 0x12, 0x1F, 0xA4,
-	0xFE, 0xAF, 0x05, 0xED, 0x2E, 0x90, 0x80, 0x3D,
-	0xF0, 0x90, 0x00, 0x01, 0x12, 0x1F, 0xBD, 0xFF,
-	0xED, 0x2F, 0x90, 0x80, 0x3E, 0xF0, 0x90, 0x00,
-	0x02, 0x12, 0x1F, 0xBD, 0xFF, 0xED, 0x2F, 0x90,
-	0x80, 0x3F, 0xF0, 0x90, 0x00, 0x03, 0x12, 0x1F,
-	0xBD, 0xFF, 0xED, 0x2F, 0x90, 0x80, 0x40, 0xF0,
-	0x90, 0x00, 0x04, 0x12, 0x1F, 0xBD, 0xFF, 0xAE,
-	0x05, 0xED, 0x2F, 0x90, 0x80, 0x41, 0xF0, 0x22,
-	0x90, 0x00, 0x02, 0x12, 0x1F, 0xBD, 0xFF, 0x30,
-	0xE0, 0x26, 0x12, 0x1F, 0xA4, 0x90, 0x81, 0x38,
-	0xF0, 0x90, 0x00, 0x01, 0x12, 0x1F, 0xBD, 0x90,
-	0x81, 0x39, 0xF0, 0xEF, 0x54, 0xFE, 0xFF, 0xA3,
-	0xE0, 0x54, 0x01, 0x4F, 0xF0, 0x90, 0x00, 0x03,
-	0x12, 0x1F, 0xBD, 0x90, 0x81, 0x3B, 0xF0, 0x22,
-	0x90, 0x81, 0x38, 0x74, 0x01, 0xF0, 0xA3, 0x74,
-	0x05, 0xF0, 0xA3, 0xE0, 0x54, 0x01, 0x44, 0x28,
-	0xF0, 0xA3, 0x74, 0x05, 0xF0, 0x22, 0x12, 0x1F,
-	0xA4, 0x90, 0x81, 0x3E, 0xF0, 0x90, 0x81, 0x3E,
-	0xE0, 0x90, 0x01, 0xE7, 0xF0, 0x22, 0x12, 0x1F,
-	0xA4, 0x90, 0x81, 0x4A, 0xF0, 0x90, 0x00, 0x01,
-	0x12, 0x1F, 0xBD, 0x90, 0x81, 0x4B, 0xF0, 0x22,
-	0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90,
-	0x81, 0xFD, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0xE4,
-	0xA3, 0xF0, 0xA3, 0xF0, 0x90, 0x81, 0xFD, 0xE0,
-	0xFE, 0xA3, 0xE0, 0xF5, 0x82, 0x8E, 0x83, 0xE0,
-	0x60, 0x2D, 0xC3, 0x90, 0x82, 0x00, 0xE0, 0x94,
-	0xE8, 0x90, 0x81, 0xFF, 0xE0, 0x94, 0x03, 0x40,
-	0x0B, 0x90, 0x01, 0xC0, 0xE0, 0x44, 0x80, 0xF0,
-	0x7F, 0x00, 0x80, 0x15, 0x90, 0x81, 0xFF, 0xE4,
-	0x75, 0xF0, 0x01, 0x12, 0x44, 0xA9, 0x7F, 0x0A,
-	0x7E, 0x00, 0x12, 0x32, 0xAA, 0x80, 0xC5, 0x7F,
-	0x01, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10,
-	0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x81, 0xD1,
-	0x12, 0x45, 0x1F, 0x90, 0x82, 0x0A, 0xE0, 0xFF,
-	0x04, 0xF0, 0x90, 0x00, 0x01, 0xEF, 0x12, 0x1F,
-	0xFC, 0x7F, 0xAF, 0x7E, 0x01, 0x71, 0x60, 0xEF,
-	0x60, 0x3A, 0x90, 0x81, 0xD1, 0x12, 0x45, 0x16,
-	0x8B, 0x13, 0x8A, 0x14, 0x89, 0x15, 0x90, 0x00,
-	0x0E, 0x12, 0x1F, 0xBD, 0x24, 0x02, 0xF5, 0x16,
-	0x7B, 0x01, 0x7A, 0x01, 0x79, 0xA0, 0x12, 0x2B,
-	0xED, 0x90, 0x81, 0xD1, 0x12, 0x45, 0x16, 0x90,
-	0x00, 0x0E, 0x12, 0x1F, 0xBD, 0x90, 0x01, 0xAE,
-	0xF0, 0xA3, 0x74, 0xFF, 0xF0, 0x90, 0x01, 0xCB,
-	0xE0, 0x64, 0x80, 0xF0, 0xD0, 0xD0, 0x92, 0xAF,
-	0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0,
-	0xE4, 0xFF, 0x90, 0x80, 0xD9, 0xE0, 0xFE, 0x90,
-	0x80, 0xD8, 0xE0, 0xFD, 0xB5, 0x06, 0x04, 0x7E,
-	0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x64, 0x01,
-	0x60, 0x32, 0x90, 0x01, 0xAF, 0xE0, 0x70, 0x13,
-	0xED, 0x75, 0xF0, 0x0F, 0xA4, 0x24, 0x42, 0xF9,
-	0x74, 0x80, 0x35, 0xF0, 0xFA, 0x7B, 0x01, 0x71,
-	0xB6, 0x7F, 0x01, 0xEF, 0x60, 0x16, 0x90, 0x80,
-	0xD8, 0xE0, 0x04, 0xF0, 0xE0, 0x7F, 0x00, 0xB4,
-	0x0A, 0x02, 0x7F, 0x01, 0xEF, 0x60, 0x05, 0xE4,
-	0x90, 0x80, 0xD8, 0xF0, 0xD0, 0xD0, 0x92, 0xAF,
-	0x22, 0x8F, 0x0D, 0x22, 0x8F, 0x0E, 0x22, 0x22,
-	0x90, 0x01, 0x34, 0xE0, 0x55, 0x3D, 0xF5, 0x41,
-	0xA3, 0xE0, 0x55, 0x3E, 0xF5, 0x42, 0xA3, 0xE0,
-	0x55, 0x3F, 0xF5, 0x43, 0xA3, 0xE0, 0x55, 0x40,
-	0xF5, 0x44, 0x90, 0x01, 0x34, 0xE5, 0x41, 0xF0,
-	0xA3, 0xE5, 0x42, 0xF0, 0xA3, 0xE5, 0x43, 0xF0,
-	0xA3, 0xE5, 0x44, 0xF0, 0x22, 0x90, 0x01, 0x3C,
-	0xE0, 0x55, 0x45, 0xF5, 0x49, 0xA3, 0xE0, 0x55,
-	0x46, 0xF5, 0x4A, 0xA3, 0xE0, 0x55, 0x47, 0xF5,
-	0x4B, 0xA3, 0xE0, 0x55, 0x48, 0xF5, 0x4C, 0x90,
-	0x01, 0x3C, 0xE5, 0x49, 0xF0, 0xA3, 0xE5, 0x4A,
-	0xF0, 0xA3, 0xE5, 0x4B, 0xF0, 0xA3, 0xE5, 0x4C,
-	0xF0, 0x53, 0x91, 0xDF, 0x22, 0x90, 0x81, 0x1F,
-	0xE0, 0x30, 0xE0, 0x05, 0xE4, 0xA3, 0xF0, 0xA3,
-	0xF0, 0x22, 0x90, 0x80, 0xDE, 0xE0, 0x64, 0x01,
-	0x70, 0x19, 0x90, 0x81, 0x27, 0xE0, 0x60, 0x13,
-	0x90, 0x01, 0x57, 0xE4, 0xF0, 0x90, 0x01, 0x3C,
-	0x74, 0x02, 0x12, 0x4F, 0xF4, 0x90, 0x01, 0x57,
-	0x74, 0x05, 0xF0, 0x22, 0x90, 0x80, 0xDE, 0xE0,
-	0x64, 0x01, 0x70, 0x26, 0x90, 0x81, 0x27, 0xE0,
-	0x60, 0x20, 0x90, 0x01, 0x57, 0xE4, 0xF0, 0x90,
-	0x01, 0x3C, 0x74, 0x02, 0xF0, 0x90, 0x81, 0x24,
-	0xE0, 0x54, 0xFB, 0xF0, 0x90, 0x81, 0x2B, 0xE0,
-	0x54, 0xFD, 0xF0, 0x54, 0x07, 0x70, 0x03, 0x12,
-	0x47, 0x2A, 0x22, 0x90, 0x80, 0xDE, 0xE0, 0xB4,
-	0x01, 0x14, 0x90, 0x81, 0x27, 0xE0, 0x60, 0x0E,
-	0x90, 0x81, 0x26, 0xE0, 0x54, 0x0F, 0x64, 0x02,
-	0x60, 0x02, 0x80, 0x03, 0xD1, 0x7F, 0x22, 0x90,
-	0x04, 0x1D, 0xE0, 0x70, 0x13, 0x90, 0x80, 0x3E,
-	0xE0, 0xFF, 0xE4, 0xFD, 0xB1, 0x69, 0x8E, 0x4E,
-	0x8F, 0x4F, 0x90, 0x04, 0x1F, 0x74, 0x20, 0xF0,
-	0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0,
-	0x90, 0x82, 0x0E, 0xED, 0xF0, 0x90, 0x82, 0x0D,
-	0xEF, 0xF0, 0xE4, 0xFD, 0xFC, 0xF1, 0x37, 0x7C,
-	0x00, 0xAD, 0x07, 0x90, 0x82, 0x0D, 0xE0, 0x90,
-	0x04, 0x25, 0xF0, 0x90, 0x82, 0x0E, 0xE0, 0x60,
-	0x0E, 0x74, 0x0F, 0x2F, 0xF5, 0x82, 0xE4, 0x34,
-	0xFC, 0xF5, 0x83, 0xE0, 0x44, 0x80, 0xF0, 0xAF,
-	0x05, 0x74, 0x08, 0x2F, 0xF5, 0x82, 0xE4, 0x34,
-	0xFC, 0xF5, 0x83, 0xE4, 0xF0, 0x74, 0x09, 0x2F,
-	0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0,
-	0x54, 0xF0, 0xF0, 0x74, 0x21, 0x2D, 0xF5, 0x82,
-	0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x54, 0xF7,
-	0xF0, 0xAE, 0x04, 0xAF, 0x05, 0xD0, 0xD0, 0x92,
-	0xAF, 0x22, 0x8F, 0x4E, 0xF1, 0x4B, 0xBF, 0x01,
-	0x18, 0x90, 0x80, 0x40, 0xE0, 0xFF, 0x7D, 0x01,
-	0xB1, 0x69, 0xAD, 0x07, 0xAC, 0x06, 0xAF, 0x4E,
-	0x12, 0x4F, 0x82, 0x90, 0x04, 0x1F, 0x74, 0x20,
-	0xF0, 0x22, 0x90, 0x06, 0xA9, 0xE0, 0x90, 0x81,
-	0x4C, 0xF0, 0xE0, 0xFD, 0x54, 0xC0, 0x70, 0x09,
-	0x90, 0x81, 0x2B, 0xE0, 0x54, 0xFE, 0xF0, 0x80,
-	0x72, 0xED, 0x30, 0xE6, 0x4B, 0x90, 0x81, 0x27,
-	0xE0, 0x64, 0x02, 0x70, 0x2A, 0x90, 0x81, 0x24,
-	0xE0, 0xFF, 0xC3, 0x13, 0x20, 0xE0, 0x09, 0x90,
-	0x81, 0x2B, 0xE0, 0x44, 0x01, 0xF0, 0x80, 0x28,
-	0x90, 0x81, 0x26, 0xE0, 0x54, 0x0F, 0x64, 0x01,
-	0x70, 0x2D, 0x90, 0x81, 0x2B, 0xE0, 0x44, 0x04,
-	0xF0, 0x7F, 0x01, 0xB1, 0xD2, 0x80, 0x20, 0x90,
-	0x81, 0x2B, 0xE0, 0x44, 0x01, 0xF0, 0x90, 0x81,
-	0x26, 0xE0, 0x54, 0x0F, 0x64, 0x02, 0x60, 0x04,
-	0xB1, 0x4F, 0x80, 0x0B, 0xD1, 0x7F, 0x80, 0x07,
-	0x90, 0x81, 0x2B, 0xE0, 0x54, 0xFE, 0xF0, 0x90,
-	0x81, 0x4C, 0xE0, 0x90, 0x81, 0x2B, 0x30, 0xE7,
-	0x11, 0x12, 0x4F, 0xF1, 0x90, 0x01, 0x57, 0x74,
-	0x05, 0xF0, 0x90, 0x81, 0x24, 0xE0, 0x44, 0x04,
-	0xF0, 0x22, 0xE0, 0x54, 0xFD, 0xF0, 0x22, 0x90,
-	0x01, 0x5F, 0xE4, 0xF0, 0x90, 0x01, 0x3C, 0x74,
-	0x08, 0xF0, 0xE4, 0xF5, 0x1D, 0x90, 0x81, 0x3A,
-	0xE0, 0xC3, 0x13, 0x54, 0x7F, 0xF5, 0x1E, 0xE4,
-	0xFB, 0xFD, 0x7F, 0x5C, 0x7E, 0x01, 0x12, 0x50,
-	0x05, 0x90, 0x01, 0x5F, 0x74, 0x05, 0xF0, 0x90,
-	0x06, 0x92, 0x74, 0x02, 0xF0, 0x90, 0x81, 0x24,
-	0xE0, 0x44, 0x10, 0xF0, 0x90, 0x81, 0x2A, 0xE0,
-	0x64, 0x0C, 0x60, 0x0C, 0xE4, 0xFD, 0x7F, 0x0C,
-	0x12, 0x47, 0x3D, 0xE4, 0xFF, 0x12, 0x4F, 0x0D,
-	0x22, 0xE4, 0x90, 0x81, 0x4C, 0xF0, 0x90, 0x06,
-	0xA9, 0xE0, 0x90, 0x81, 0x4C, 0xF0, 0xE0, 0x54,
-	0xC0, 0x70, 0x0D, 0x90, 0x81, 0x2B, 0xE0, 0x54,
-	0xFE, 0xF0, 0x54, 0xFD, 0xF0, 0x02, 0x47, 0x2A,
-	0x90, 0x81, 0x4C, 0xE0, 0x30, 0xE6, 0x21, 0x90,
-	0x81, 0x27, 0xE0, 0x64, 0x01, 0x70, 0x20, 0x90,
-	0x81, 0x2B, 0xE0, 0x44, 0x01, 0xF0, 0x90, 0x81,
-	0x26, 0xE0, 0x54, 0x0F, 0x64, 0x02, 0x60, 0x04,
-	0xB1, 0x4F, 0x80, 0x0B, 0xD1, 0x7F, 0x80, 0x07,
-	0x90, 0x81, 0x2B, 0xE0, 0x54, 0xFE, 0xF0, 0x90,
-	0x81, 0x4C, 0xE0, 0x90, 0x81, 0x2B, 0x30, 0xE7,
-	0x11, 0x12, 0x4F, 0xF1, 0x90, 0x01, 0x57, 0x74,
-	0x05, 0xF0, 0x90, 0x81, 0x24, 0xE0, 0x44, 0x04,
-	0xF0, 0x22, 0xE0, 0x54, 0xFD, 0xF0, 0x22, 0xE4,
-	0xFE, 0xEF, 0xC3, 0x13, 0xFD, 0xEF, 0x30, 0xE0,
-	0x02, 0x7E, 0x80, 0x90, 0xFD, 0x10, 0xED, 0xF0,
-	0xAF, 0x06, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3,
-	0xC0, 0xD0, 0x90, 0x04, 0x1D, 0xE0, 0x60, 0x1A,
-	0x90, 0x05, 0x22, 0xE0, 0x54, 0x90, 0x60, 0x07,
-	0x90, 0x01, 0xC0, 0xE0, 0x44, 0x08, 0xF0, 0x90,
-	0x01, 0xC6, 0xE0, 0x30, 0xE1, 0xE4, 0x7F, 0x00,
-	0x80, 0x02, 0x7F, 0x01, 0xD0, 0xD0, 0x92, 0xAF,
-	0x22, 0x90, 0x81, 0x27, 0xE0, 0x60, 0x03, 0x12,
-	0x73, 0xE1, 0x90, 0x81, 0x3F, 0xE0, 0x30, 0xE0,
-	0x03, 0x12, 0x49, 0xDD, 0x22, 0x90, 0x81, 0x27,
-	0xE0, 0x60, 0x35, 0x90, 0x06, 0x92, 0xE0, 0x30,
-	0xE1, 0x24, 0xE4, 0xF5, 0x1D, 0x90, 0x81, 0x3A,
-	0xE0, 0xC3, 0x13, 0x54, 0x7F, 0xF5, 0x1E, 0xE4,
-	0xFB, 0xFD, 0x7F, 0x5C, 0x7E, 0x01, 0x12, 0x50,
-	0x05, 0x90, 0x01, 0x5F, 0x74, 0x05, 0xF0, 0x90,
-	0x06, 0x92, 0x74, 0x02, 0xF0, 0x22, 0x90, 0x81,
-	0x24, 0xE0, 0x54, 0xEF, 0xF0, 0x12, 0x47, 0x2A,
-	0x22, 0x12, 0x71, 0x48, 0x90, 0x81, 0x4D, 0xEF,
-	0xF0, 0x90, 0x81, 0x24, 0x30, 0xE0, 0x06, 0xE0,
-	0x44, 0x01, 0xF0, 0x80, 0x04, 0xE0, 0x54, 0xFE,
-	0xF0, 0x90, 0x81, 0x4D, 0xE0, 0x30, 0xE6, 0x11,
-	0x90, 0x01, 0x2F, 0xE0, 0x30, 0xE7, 0x04, 0xE4,
-	0xF0, 0x80, 0x06, 0x90, 0x01, 0x2F, 0x74, 0x80,
-	0xF0, 0x90, 0x81, 0x24, 0xE0, 0x30, 0xE0, 0x1A,
-	0x90, 0x81, 0x32, 0xE4, 0xF0, 0xA3, 0x74, 0x07,
-	0xF0, 0x90, 0x81, 0x32, 0xA3, 0xE0, 0x90, 0x05,
-	0x58, 0xF0, 0x90, 0x04, 0xEC, 0xE0, 0x54, 0xDD,
-	0xF0, 0x22, 0x90, 0x04, 0xEC, 0xE0, 0x44, 0x22,
-	0xF0, 0x22, 0x90, 0x81, 0x4A, 0xE0, 0x60, 0x0F,
-	0xE4, 0xF0, 0x90, 0x05, 0x53, 0xE0, 0x44, 0x01,
-	0xF0, 0x90, 0x05, 0xFD, 0xE0, 0x04, 0xF0, 0x22,
-	0x90, 0x81, 0x24, 0xE0, 0xFF, 0xC4, 0x13, 0x13,
-	0x54, 0x03, 0x30, 0xE0, 0x27, 0xEF, 0x54, 0xBF,
-	0xF0, 0x90, 0x04, 0xE0, 0xE0, 0x90, 0x81, 0x25,
-	0x30, 0xE0, 0x06, 0xE0, 0x44, 0x01, 0xF0, 0x80,
-	0x10, 0xE0, 0x54, 0xFE, 0xF0, 0x90, 0x01, 0xB9,
-	0x74, 0x01, 0xF0, 0x90, 0x01, 0xB8, 0x74, 0x04,
-	0xF0, 0x12, 0x47, 0x2A, 0xE4, 0xFF, 0x90, 0x81,
-	0x45, 0xE0, 0x30, 0xE0, 0x48, 0x90, 0x81, 0x49,
-	0xE0, 0xFD, 0x60, 0x41, 0x74, 0x01, 0x7E, 0x00,
-	0xA8, 0x07, 0x08, 0x80, 0x05, 0xC3, 0x33, 0xCE,
-	0x33, 0xCE, 0xD8, 0xF9, 0xFF, 0x90, 0x04, 0xE0,
-	0xE0, 0xFB, 0xEF, 0x5B, 0x60, 0x06, 0xE4, 0x90,
-	0x81, 0x49, 0xF0, 0x22, 0x90, 0x81, 0x47, 0xE0,
-	0xD3, 0x9D, 0x50, 0x10, 0x90, 0x01, 0xC7, 0x74,
-	0x10, 0xF0, 0x11, 0xBE, 0x90, 0x81, 0x45, 0xE0,
-	0x54, 0xFE, 0xF0, 0x22, 0x12, 0x4F, 0x0B, 0x90,
-	0x81, 0x49, 0xE0, 0x04, 0xF0, 0x22, 0x90, 0x80,
-	0x3C, 0xE0, 0x64, 0x02, 0x60, 0x07, 0x90, 0x06,
-	0x90, 0xE0, 0x44, 0x01, 0xF0, 0x22, 0x90, 0x81,
-	0x24, 0xE0, 0xFF, 0xC4, 0x13, 0x13, 0x13, 0x54,
-	0x01, 0x30, 0xE0, 0x2C, 0xEF, 0x54, 0x7F, 0xF0,
-	0x90, 0x04, 0xE0, 0xE0, 0x90, 0x81, 0x25, 0x30,
-	0xE1, 0x06, 0xE0, 0x44, 0x02, 0xF0, 0x80, 0x0F,
-	0xE0, 0x54, 0xFD, 0xF0, 0x90, 0x01, 0xB9, 0x74,
-	0x01, 0xF0, 0x90, 0x01, 0xB8, 0x04, 0xF0, 0x90,
-	0x81, 0x27, 0xE0, 0x60, 0x03, 0x12, 0x47, 0x2A,
-	0x7F, 0x01, 0x01, 0x6E, 0xC3, 0xEE, 0x94, 0x01,
-	0x40, 0x0A, 0x0D, 0xED, 0x13, 0x90, 0xFD, 0x10,
-	0xF0, 0xE4, 0x2F, 0xFF, 0x22, 0xC3, 0xEE, 0x94,
-	0x01, 0x40, 0x24, 0x90, 0xFD, 0x11, 0xE0, 0x6D,
-	0x70, 0x1A, 0x90, 0x01, 0x17, 0xE0, 0xB5, 0x05,
-	0x0D, 0x90, 0x01, 0xE4, 0x74, 0x77, 0xF0, 0x90,
-	0xFD, 0x11, 0xE4, 0xF0, 0x80, 0x06, 0xED, 0x04,
-	0x90, 0xFD, 0x11, 0xF0, 0xE4, 0x2F, 0xFF, 0x22,
-	0xE4, 0x90, 0x81, 0x4E, 0xF0, 0xA3, 0xF0, 0xA3,
-	0xF0, 0x90, 0x00, 0x83, 0xE0, 0x90, 0x81, 0x4E,
-	0xF0, 0x90, 0x00, 0x83, 0xE0, 0xFE, 0x90, 0x81,
-	0x4E, 0xE0, 0xFF, 0xB5, 0x06, 0x01, 0x22, 0xC3,
-	0x90, 0x81, 0x50, 0xE0, 0x94, 0x64, 0x90, 0x81,
-	0x4F, 0xE0, 0x94, 0x00, 0x40, 0x0D, 0x90, 0x01,
-	0xC0, 0xE0, 0x44, 0x40, 0xF0, 0x90, 0x81, 0x4E,
-	0xE0, 0xFF, 0x22, 0x90, 0x81, 0x4F, 0xE4, 0x75,
-	0xF0, 0x01, 0x12, 0x44, 0xA9, 0x80, 0xC2, 0x74,
-	0x45, 0x2F, 0xF8, 0xE6, 0xFE, 0xED, 0xF4, 0x5E,
-	0xFE, 0xF6, 0x74, 0x38, 0x2F, 0xF5, 0x82, 0xE4,
-	0x34, 0x01, 0xF5, 0x83, 0xEE, 0xF0, 0x22, 0xD3,
-	0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x82,
-	0x12, 0xED, 0xF0, 0x90, 0x82, 0x11, 0xEF, 0xF0,
-	0xD3, 0x94, 0x07, 0x50, 0x70, 0xE0, 0xFF, 0x74,
-	0x01, 0xA8, 0x07, 0x08, 0x80, 0x02, 0xC3, 0x33,
-	0xD8, 0xFC, 0xF4, 0xFF, 0x90, 0x00, 0x47, 0xE0,
-	0x5F, 0xFD, 0x7F, 0x47, 0x12, 0x32, 0x1E, 0x90,
-	0x82, 0x11, 0xE0, 0xFF, 0x74, 0x01, 0xA8, 0x07,
-	0x08, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xFF,
-	0x90, 0x00, 0x46, 0xE0, 0x4F, 0xFD, 0x7F, 0x46,
-	0x12, 0x32, 0x1E, 0x90, 0x82, 0x12, 0xE0, 0x60,
-	0x18, 0x90, 0x82, 0x11, 0xE0, 0xFF, 0x74, 0x01,
-	0xA8, 0x07, 0x08, 0x80, 0x02, 0xC3, 0x33, 0xD8,
-	0xFC, 0xFF, 0x90, 0x00, 0x45, 0xE0, 0x4F, 0x80,
-	0x17, 0x90, 0x82, 0x11, 0xE0, 0xFF, 0x74, 0x01,
-	0xA8, 0x07, 0x08, 0x80, 0x02, 0xC3, 0x33, 0xD8,
-	0xFC, 0xF4, 0xFF, 0x90, 0x00, 0x45, 0xE0, 0x5F,
-	0xFD, 0x7F, 0x45, 0x80, 0x7E, 0x90, 0x82, 0x11,
-	0xE0, 0x24, 0xF8, 0xF0, 0xE0, 0x24, 0x04, 0xFF,
-	0x74, 0x01, 0xA8, 0x07, 0x08, 0x80, 0x02, 0xC3,
-	0x33, 0xD8, 0xFC, 0xF4, 0xFF, 0x90, 0x00, 0x43,
-	0xE0, 0x5F, 0xFD, 0x7F, 0x43, 0x12, 0x32, 0x1E,
-	0x90, 0x82, 0x11, 0xE0, 0xFF, 0x74, 0x01, 0xA8,
-	0x07, 0x08, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC,
-	0xFF, 0x90, 0x00, 0x43, 0xE0, 0x4F, 0xFD, 0x7F,
-	0x43, 0x12, 0x32, 0x1E, 0x90, 0x82, 0x12, 0xE0,
-	0x60, 0x1D, 0x90, 0x82, 0x11, 0xE0, 0x24, 0x04,
-	0xFF, 0x74, 0x01, 0xA8, 0x07, 0x08, 0x80, 0x02,
-	0xC3, 0x33, 0xD8, 0xFC, 0xFF, 0x90, 0x00, 0x42,
-	0xE0, 0x4F, 0xFD, 0x7F, 0x42, 0x80, 0x1C, 0x90,
-	0x82, 0x11, 0xE0, 0x24, 0x04, 0xFF, 0x74, 0x01,
-	0xA8, 0x07, 0x08, 0x80, 0x02, 0xC3, 0x33, 0xD8,
-	0xFC, 0xF4, 0xFF, 0x90, 0x00, 0x42, 0xE0, 0x5F,
-	0xFD, 0x7F, 0x42, 0x12, 0x32, 0x1E, 0xD0, 0xD0,
-	0x92, 0xAF, 0x22, 0x90, 0x81, 0x24, 0xE0, 0x54,
-	0xFB, 0xF0, 0xE4, 0x90, 0x81, 0x30, 0xF0, 0x90,
-	0x81, 0x2B, 0xF0, 0x22, 0xEF, 0x24, 0xFE, 0x60,
-	0x0C, 0x04, 0x70, 0x28, 0x90, 0x81, 0x2D, 0x74,
-	0x01, 0xF0, 0xA3, 0xF0, 0x22, 0xED, 0x70, 0x0A,
-	0x90, 0x81, 0x3B, 0xE0, 0x90, 0x81, 0x2D, 0xF0,
-	0x80, 0x05, 0x90, 0x81, 0x2D, 0xED, 0xF0, 0x90,
-	0x81, 0x2D, 0xE0, 0xA3, 0xF0, 0x90, 0x81, 0x25,
-	0xE0, 0x44, 0x08, 0xF0, 0x22, 0x12, 0x4E, 0xAB,
-	0xEF, 0x64, 0x01, 0x60, 0x08, 0x90, 0x01, 0xB8,
-	0x74, 0x01, 0xF0, 0x80, 0x67, 0x90, 0x81, 0x2B,
-	0xE0, 0xFF, 0x54, 0x03, 0x60, 0x08, 0x90, 0x01,
-	0xB8, 0x74, 0x02, 0xF0, 0x80, 0x56, 0x90, 0x81,
-	0x29, 0xE0, 0xFE, 0xE4, 0xC3, 0x9E, 0x50, 0x08,
-	0x90, 0x01, 0xB8, 0x74, 0x04, 0xF0, 0x80, 0x44,
-	0xEF, 0x30, 0xE2, 0x08, 0x90, 0x01, 0xB8, 0x74,
-	0x08, 0xF0, 0x80, 0x38, 0x90, 0x81, 0x2B, 0xE0,
-	0x30, 0xE4, 0x08, 0x90, 0x01, 0xB8, 0x74, 0x10,
-	0xF0, 0x80, 0x29, 0x90, 0x81, 0x25, 0xE0, 0x13,
-	0x13, 0x54, 0x3F, 0x20, 0xE0, 0x08, 0x90, 0x01,
-	0xB8, 0x74, 0x20, 0xF0, 0x80, 0x16, 0x90, 0x81,
-	0x3E, 0xE0, 0x60, 0x08, 0x90, 0x01, 0xB8, 0x74,
-	0x80, 0xF0, 0x80, 0x08, 0x90, 0x01, 0xB8, 0xE4,
-	0xF0, 0x7F, 0x01, 0x22, 0x90, 0x01, 0xB9, 0x74,
-	0x04, 0xF0, 0x7F, 0x00, 0x22, 0xEF, 0x60, 0x42,
-	0x90, 0x80, 0xDE, 0xE0, 0x64, 0x01, 0x70, 0x3A,
-	0x90, 0x81, 0x25, 0xE0, 0x54, 0xFE, 0xF0, 0x90,
-	0x05, 0x22, 0x74, 0x0F, 0xF0, 0x90, 0x06, 0x04,
-	0xE0, 0x54, 0xBF, 0xF0, 0xE4, 0xFF, 0x12, 0x4F,
-	0x0D, 0xBF, 0x01, 0x12, 0x90, 0x81, 0x24, 0xE0,
-	0x44, 0x40, 0xF0, 0x90, 0x81, 0x2A, 0x74, 0x06,
-	0xF0, 0x90, 0x81, 0x23, 0xF0, 0x22, 0x90, 0x01,
-	0xB9, 0x74, 0x01, 0xF0, 0x90, 0x01, 0xB8, 0x74,
-	0x08, 0xF0, 0x22, 0x90, 0x05, 0x22, 0x74, 0x6F,
-	0xF0, 0x90, 0x05, 0x27, 0xE0, 0x54, 0xBF, 0xF0,
-	0x90, 0x81, 0x2A, 0x74, 0x02, 0xF0, 0x90, 0x81,
-	0x23, 0xF0, 0x22, 0x12, 0x54, 0x65, 0x90, 0x81,
-	0x2A, 0x74, 0x0C, 0xF0, 0x90, 0x81, 0x23, 0xF0,
-	0x22, 0x90, 0x81, 0x24, 0xE0, 0xFF, 0x13, 0x13,
-	0x54, 0x3F, 0x30, 0xE0, 0x11, 0xEF, 0x54, 0xFB,
-	0xF0, 0x90, 0x81, 0x2B, 0xE0, 0x54, 0xFD, 0xF0,
-	0x54, 0x07, 0x70, 0x42, 0x80, 0x3D, 0x90, 0x81,
-	0x30, 0xE0, 0x04, 0xF0, 0x90, 0x81, 0x2B, 0xE0,
-	0x54, 0xEF, 0xF0, 0x90, 0x81, 0x30, 0xE0, 0xFF,
-	0xB4, 0x01, 0x02, 0x80, 0x04, 0xEF, 0xB4, 0x02,
-	0x06, 0x90, 0x05, 0x58, 0xE0, 0x04, 0xF0, 0x90,
-	0x81, 0x38, 0xE0, 0xFF, 0x90, 0x81, 0x30, 0xE0,
-	0xD3, 0x9F, 0x40, 0x0F, 0x90, 0x80, 0xDE, 0xE0,
-	0xB4, 0x01, 0x0B, 0x90, 0x81, 0x25, 0xE0, 0x54,
-	0xFB, 0xF0, 0x22, 0x12, 0x47, 0x2A, 0x22, 0x22,
-	0x90, 0x05, 0x2B, 0xE0, 0x7F, 0x00, 0x30, 0xE7,
-	0x02, 0x7F, 0x01, 0x22, 0x90, 0x05, 0x22, 0x74,
-	0xFF, 0xF0, 0x90, 0x05, 0x27, 0xE0, 0x44, 0x40,
-	0xF0, 0x90, 0x81, 0x22, 0x74, 0x03, 0xF0, 0x22,
-	0x90, 0x05, 0x27, 0xE0, 0x44, 0x40, 0xF0, 0x12,
-	0x49, 0xDD, 0x90, 0x81, 0x22, 0x74, 0x02, 0xF0,
-	0x22, 0x12, 0x49, 0xE3, 0x90, 0x81, 0x22, 0x74,
-	0x02, 0xF0, 0x22, 0x90, 0x05, 0x22, 0x74, 0x6F,
-	0xF0, 0x90, 0x05, 0x27, 0xE0, 0x54, 0xBF, 0xF0,
-	0x90, 0x81, 0x22, 0x74, 0x04, 0xF0, 0x22, 0xAE,
-	0x07, 0x12, 0x51, 0x73, 0xBF, 0x01, 0x12, 0x90,
-	0x81, 0x23, 0xE0, 0x64, 0x02, 0x60, 0x0A, 0xAF,
-	0x06, 0x7D, 0x01, 0x12, 0x47, 0x3D, 0x7F, 0x01,
-	0x22, 0x7F, 0x00, 0x22, 0x90, 0x01, 0x57, 0xE0,
-	0x60, 0x48, 0xE4, 0xF0, 0x90, 0x01, 0x3C, 0x74,
-	0x02, 0xF0, 0x90, 0x81, 0x24, 0xE0, 0xFF, 0x13,
-	0x13, 0x54, 0x3F, 0x30, 0xE0, 0x0C, 0xEF, 0x54,
-	0xFB, 0xF0, 0x90, 0x81, 0x2B, 0xE0, 0x54, 0xFD,
-	0xF0, 0x22, 0x90, 0x81, 0x30, 0xE0, 0x04, 0xF0,
-	0x90, 0x81, 0x2B, 0xE0, 0x54, 0xEF, 0xF0, 0x90,
-	0x81, 0x38, 0xE0, 0xFF, 0x90, 0x81, 0x30, 0xE0,
-	0xD3, 0x9F, 0x40, 0x0E, 0x90, 0x80, 0xDE, 0xE0,
-	0xB4, 0x01, 0x07, 0x90, 0x81, 0x25, 0xE0, 0x54,
-	0xFB, 0xF0, 0x22, 0x90, 0x80, 0x3F, 0xE0, 0xFF,
-	0x7D, 0x01, 0x12, 0x6D, 0x69, 0x8E, 0x54, 0x8F,
-	0x55, 0xAD, 0x55, 0xAC, 0x54, 0xAF, 0x53, 0x12,
-	0x4F, 0x82, 0xAF, 0x55, 0xAE, 0x54, 0x90, 0x04,
-	0x80, 0xE0, 0x54, 0x0F, 0xFD, 0xAC, 0x07, 0x74,
-	0x11, 0x2C, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5,
-	0x83, 0xE0, 0x44, 0x01, 0xF0, 0x74, 0x11, 0x2C,
-	0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0,
-	0x54, 0xFB, 0xF0, 0xAC, 0x07, 0x74, 0x16, 0x2C,
-	0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0,
-	0x44, 0xFA, 0xF0, 0x74, 0x15, 0x2C, 0xF5, 0x82,
-	0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x44, 0x1F,
-	0xF0, 0xAC, 0x07, 0x74, 0x06, 0x2C, 0xF5, 0x82,
-	0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x44, 0x0F,
-	0xF0, 0x90, 0x04, 0x53, 0xE4, 0xF0, 0x90, 0x04,
-	0x52, 0xF0, 0x90, 0x04, 0x51, 0x74, 0xFF, 0xF0,
-	0x90, 0x04, 0x50, 0x74, 0xFD, 0xF0, 0x74, 0x14,
-	0x2C, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83,
-	0xE0, 0x54, 0xC0, 0x4D, 0xFD, 0x74, 0x14, 0x2F,
-	0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xED,
-	0xF0, 0x22, 0xAB, 0x07, 0xAA, 0x06, 0xED, 0x2B,
-	0xFB, 0xE4, 0x3A, 0xFA, 0xC3, 0x90, 0x80, 0xDB,
-	0xE0, 0x9B, 0x90, 0x80, 0xDA, 0xE0, 0x9A, 0x50,
-	0x13, 0xA3, 0xE0, 0x24, 0x01, 0xFF, 0x90, 0x80,
-	0xDA, 0xE0, 0x34, 0x00, 0xFE, 0xC3, 0xEB, 0x9F,
-	0xFB, 0xEA, 0x9E, 0xFA, 0xEA, 0x90, 0xFD, 0x11,
-	0xF0, 0xAF, 0x03, 0x74, 0x00, 0x2F, 0xF5, 0x82,
-	0xE4, 0x34, 0xFB, 0xF5, 0x83, 0xE0, 0xFF, 0x22,
-	0x12, 0x1F, 0xA4, 0xFF, 0x54, 0x01, 0xFE, 0x90,
-	0x81, 0x42, 0xE0, 0x54, 0xFE, 0x4E, 0xF0, 0xEF,
-	0xC3, 0x13, 0x30, 0xE0, 0x0A, 0x90, 0x00, 0x01,
-	0x12, 0x1F, 0xBD, 0x90, 0x81, 0x43, 0xF0, 0x22,
-	0x90, 0x81, 0x45, 0xE0, 0x30, 0xE0, 0x2D, 0x90,
-	0x81, 0x48, 0xE0, 0x04, 0xF0, 0xE0, 0xFF, 0x90,
-	0x81, 0x46, 0xE0, 0xB5, 0x07, 0x1E, 0x90, 0x06,
-	0x92, 0xE0, 0x54, 0x1C, 0x70, 0x0B, 0x12, 0x4F,
-	0x0B, 0x90, 0x81, 0x49, 0xE0, 0x04, 0xF0, 0x80,
-	0x06, 0x90, 0x06, 0x92, 0x74, 0x1C, 0xF0, 0xE4,
-	0x90, 0x81, 0x48, 0xF0, 0x22, 0x00, 0xBB, 0x8E,
-};
diff --git a/drivers/staging/rtl8188eu/hal/HalPhyRf_8188e.c b/drivers/staging/rtl8188eu/hal/HalPhyRf_8188e.c
index e4f20da..8a7947d 100644
--- a/drivers/staging/rtl8188eu/hal/HalPhyRf_8188e.c
+++ b/drivers/staging/rtl8188eu/hal/HalPhyRf_8188e.c
@@ -819,7 +819,7 @@
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(adapt);
 	struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
 
-	if (ODM_CheckPowerStatus(adapt) == false)
+	if (!ODM_CheckPowerStatus(adapt))
 		return;
 
 	ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("Save ADDA parameters.\n"));
@@ -888,7 +888,7 @@
 	ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("ADDA ON.\n"));
 
 	pathOn = isPathAOn ? 0x04db25a4 : 0x0b1b25a4;
-	if (false == is2t) {
+	if (!is2t) {
 		pathOn = 0x0bdb25a0;
 		ODM_SetBBReg(dm_odm, ADDAReg[0], bMaskDWord, 0x0b1b25a0);
 	} else {
@@ -1276,407 +1276,6 @@
 	}
 }
 
-/* Analog Pre-distortion calibration */
-#define		APK_BB_REG_NUM	8
-#define		APK_CURVE_REG_NUM 4
-#define		PATH_NUM		2
-
-static void phy_APCalibrate_8188E(struct adapter *adapt, s8 delta, bool is2t)
-{
-	struct hal_data_8188e	*pHalData = GET_HAL_DATA(adapt);
-	struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
-	u32 regD[PATH_NUM];
-	u32 tmpreg, index, offset,  apkbound;
-	u8 path, i, pathbound = PATH_NUM;
-	u32 BB_backup[APK_BB_REG_NUM];
-	u32 BB_REG[APK_BB_REG_NUM] = {
-		rFPGA1_TxBlock, 	rOFDM0_TRxPathEnable,
-		rFPGA0_RFMOD, rOFDM0_TRMuxPar,
-		rFPGA0_XCD_RFInterfaceSW, rFPGA0_XAB_RFInterfaceSW,
-		rFPGA0_XA_RFInterfaceOE, rFPGA0_XB_RFInterfaceOE	};
-	u32 BB_AP_MODE[APK_BB_REG_NUM] = {
-		0x00000020, 0x00a05430, 0x02040000,
-		0x000800e4, 0x00204000 };
-	u32 BB_normal_AP_MODE[APK_BB_REG_NUM] = {
-		0x00000020, 0x00a05430, 0x02040000,
-		0x000800e4, 0x22204000 };
-
-	u32 AFE_backup[IQK_ADDA_REG_NUM];
-	u32 AFE_REG[IQK_ADDA_REG_NUM] = {
-		rFPGA0_XCD_SwitchControl, rBlue_Tooth,
-		rRx_Wait_CCA, 	rTx_CCK_RFON,
-		rTx_CCK_BBON, rTx_OFDM_RFON,
-		rTx_OFDM_BBON, rTx_To_Rx,
-		rTx_To_Tx, 	rRx_CCK,
-		rRx_OFDM, 	rRx_Wait_RIFS,
-		rRx_TO_Rx, 	rStandby,
-		rSleep, 			rPMPD_ANAEN };
-
-	u32 MAC_backup[IQK_MAC_REG_NUM];
-	u32 MAC_REG[IQK_MAC_REG_NUM] = {
-		REG_TXPAUSE, 	REG_BCN_CTRL,
-		REG_BCN_CTRL_1, REG_GPIO_MUXCFG};
-
-	u32 APK_RF_init_value[PATH_NUM][APK_BB_REG_NUM] = {
-		{0x0852c, 0x1852c, 0x5852c, 0x1852c, 0x5852c},
-		{0x2852e, 0x0852e, 0x3852e, 0x0852e, 0x0852e}
-	};
-
-	u32 APK_normal_RF_init_value[PATH_NUM][APK_BB_REG_NUM] = {
-		{0x0852c, 0x0a52c, 0x3a52c, 0x5a52c, 0x5a52c}, /* path settings equal to path b settings */
-		{0x0852c, 0x0a52c, 0x5a52c, 0x5a52c, 0x5a52c}
-	};
-
-	u32 APK_RF_value_0[PATH_NUM][APK_BB_REG_NUM] = {
-		{0x52019, 0x52014, 0x52013, 0x5200f, 0x5208d},
-		{0x5201a, 0x52019, 0x52016, 0x52033, 0x52050}
-	};
-
-	u32 APK_normal_RF_value_0[PATH_NUM][APK_BB_REG_NUM] = {
-		{0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a}, /* path settings equal to path b settings */
-		{0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a}
-	};
-
-	u32 AFE_on_off[PATH_NUM] = {
-		0x04db25a4, 0x0b1b25a4};	/* path A on path B off / path A off path B on */
-
-	u32 APK_offset[PATH_NUM] = {
-		rConfig_AntA, rConfig_AntB};
-
-	u32 APK_normal_offset[PATH_NUM] = {
-		rConfig_Pmpd_AntA, rConfig_Pmpd_AntB};
-
-	u32 APK_value[PATH_NUM] = {
-		0x92fc0000, 0x12fc0000};
-
-	u32 APK_normal_value[PATH_NUM] = {
-		0x92680000, 0x12680000};
-
-	s8 APK_delta_mapping[APK_BB_REG_NUM][13] = {
-		{-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
-		{-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
-		{-6, -4, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
-		{-1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6},
-		{-11, -9, -7, -5, -3, -1, 0, 0, 0, 0, 0, 0, 0}
-	};
-
-	u32 APK_normal_setting_value_1[13] = {
-		0x01017018, 0xf7ed8f84, 0x1b1a1816, 0x2522201e, 0x322e2b28,
-		0x433f3a36, 0x5b544e49, 0x7b726a62, 0xa69a8f84, 0xdfcfc0b3,
-		0x12680000, 0x00880000, 0x00880000
-	};
-
-	u32 APK_normal_setting_value_2[16] = {
-		0x01c7021d, 0x01670183, 0x01000123, 0x00bf00e2, 0x008d00a3,
-		0x0068007b, 0x004d0059, 0x003a0042, 0x002b0031, 0x001f0025,
-		0x0017001b, 0x00110014, 0x000c000f, 0x0009000b, 0x00070008,
-		0x00050006
-	};
-
-	u32 APK_result[PATH_NUM][APK_BB_REG_NUM];	/* val_1_1a, val_1_2a, val_2a, val_3a, val_4a */
-	s32 BB_offset, delta_V, delta_offset;
-
-	if (*(dm_odm->mp_mode) == 1) {
-		struct mpt_context *pMptCtx = &(adapt->mppriv.MptCtx);
-		pMptCtx->APK_bound[0] = 45;
-		pMptCtx->APK_bound[1] = 52;
-	}
-
-	ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("==>phy_APCalibrate_8188E() delta %d\n", delta));
-	ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,  ("AP Calibration for %s\n", (is2t ? "2T2R" : "1T1R")));
-	if (!is2t)
-		pathbound = 1;
-
-	/* 2 FOR NORMAL CHIP SETTINGS */
-
-/*  Temporarily do not allow normal driver to do the following settings
- *  because these offset and value will cause RF internal PA to be
- *  unpredictably disabled by HW, such that RF Tx signal  will disappear
- *  after disable/enable card many times on 88CU. RF SD and DD have not
- *  find the root cause, so we remove these actions temporarily.
- */
-	if (*(dm_odm->mp_mode) != 1)
-		return;
-	/* settings adjust for normal chip */
-	for (index = 0; index < PATH_NUM; index++) {
-		APK_offset[index] = APK_normal_offset[index];
-		APK_value[index] = APK_normal_value[index];
-		AFE_on_off[index] = 0x6fdb25a4;
-	}
-
-	for (index = 0; index < APK_BB_REG_NUM; index++) {
-		for (path = 0; path < pathbound; path++) {
-			APK_RF_init_value[path][index] = APK_normal_RF_init_value[path][index];
-			APK_RF_value_0[path][index] = APK_normal_RF_value_0[path][index];
-		}
-		BB_AP_MODE[index] = BB_normal_AP_MODE[index];
-	}
-
-	apkbound = 6;
-
-	/* save BB default value */
-	for (index = 0; index < APK_BB_REG_NUM; index++) {
-		if (index == 0)		/* skip */
-			continue;
-		BB_backup[index] = ODM_GetBBReg(dm_odm, BB_REG[index], bMaskDWord);
-	}
-
-	/* save MAC default value */
-	_PHY_SaveMACRegisters(adapt, MAC_REG, MAC_backup);
-
-	/* save AFE default value */
-	_PHY_SaveADDARegisters(adapt, AFE_REG, AFE_backup, IQK_ADDA_REG_NUM);
-
-	for (path = 0; path < pathbound; path++) {
-		if (path == RF_PATH_A) {
-			/* path A APK */
-			/* load APK setting */
-			/* path-A */
-			offset = rPdp_AntA;
-			for (index = 0; index < 11; index++) {
-				ODM_SetBBReg(dm_odm, offset, bMaskDWord, APK_normal_setting_value_1[index]);
-				ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
-					     ("phy_APCalibrate_8188E() offset 0x%x value 0x%x\n",
-					     offset, ODM_GetBBReg(dm_odm, offset, bMaskDWord)));
-				offset += 0x04;
-			}
-
-			ODM_SetBBReg(dm_odm, rConfig_Pmpd_AntB, bMaskDWord, 0x12680000);
-
-			offset = rConfig_AntA;
-			for (; index < 13; index++) {
-				ODM_SetBBReg(dm_odm, offset, bMaskDWord, APK_normal_setting_value_1[index]);
-				ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
-					     ("phy_APCalibrate_8188E() offset 0x%x value 0x%x\n",
-					     offset, ODM_GetBBReg(dm_odm, offset, bMaskDWord)));
-				offset += 0x04;
-			}
-
-			/* page-B1 */
-			ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0x40000000);
-
-			/* path A */
-			offset = rPdp_AntA;
-			for (index = 0; index < 16; index++) {
-				ODM_SetBBReg(dm_odm, offset, bMaskDWord, APK_normal_setting_value_2[index]);
-				ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
-					     ("phy_APCalibrate_8188E() offset 0x%x value 0x%x\n",
-					     offset, ODM_GetBBReg(dm_odm, offset, bMaskDWord)));
-
-				offset += 0x04;
-			}
-			ODM_SetBBReg(dm_odm,  rFPGA0_IQK, bMaskDWord, 0x00000000);
-		} else if (path == RF_PATH_B) {
-			/* path B APK */
-			/* load APK setting */
-			/* path-B */
-			offset = rPdp_AntB;
-			for (index = 0; index < 10; index++) {
-				ODM_SetBBReg(dm_odm, offset, bMaskDWord, APK_normal_setting_value_1[index]);
-				ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
-					     ("phy_APCalibrate_8188E() offset 0x%x value 0x%x\n",
-					     offset, ODM_GetBBReg(dm_odm, offset, bMaskDWord)));
-
-				offset += 0x04;
-			}
-			ODM_SetBBReg(dm_odm, rConfig_Pmpd_AntA, bMaskDWord, 0x12680000);
-			PHY_SetBBReg(adapt, rConfig_Pmpd_AntB, bMaskDWord, 0x12680000);
-
-			offset = rConfig_AntA;
-			index = 11;
-			for (; index < 13; index++) { /* offset 0xb68, 0xb6c */
-				ODM_SetBBReg(dm_odm, offset, bMaskDWord, APK_normal_setting_value_1[index]);
-				ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
-					     ("phy_APCalibrate_8188E() offset 0x%x value 0x%x\n",
-					     offset, ODM_GetBBReg(dm_odm, offset, bMaskDWord)));
-				offset += 0x04;
-			}
-
-			/* page-B1 */
-			ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0x40000000);
-
-			/* path B */
-			offset = 0xb60;
-			for (index = 0; index < 16; index++) {
-				ODM_SetBBReg(dm_odm, offset, bMaskDWord, APK_normal_setting_value_2[index]);
-				ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
-					     ("phy_APCalibrate_8188E() offset 0x%x value 0x%x\n",
-					     offset, ODM_GetBBReg(dm_odm, offset, bMaskDWord)));
-
-				offset += 0x04;
-			}
-			ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0);
-		}
-
-		/* save RF default value */
-		regD[path] = PHY_QueryRFReg(adapt, path, RF_TXBIAS_A, bMaskDWord);
-
-		/* Path A AFE all on, path B AFE All off or vise versa */
-		for (index = 0; index < IQK_ADDA_REG_NUM; index++)
-			ODM_SetBBReg(dm_odm, AFE_REG[index], bMaskDWord, AFE_on_off[path]);
-		ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
-			     ("phy_APCalibrate_8188E() offset 0xe70 %x\n",
-			     ODM_GetBBReg(dm_odm, rRx_Wait_CCA, bMaskDWord)));
-
-		/* BB to AP mode */
-		if (path == 0) {
-			for (index = 0; index < APK_BB_REG_NUM; index++) {
-				if (index == 0)		/* skip */
-					continue;
-				else if (index < 5)
-				ODM_SetBBReg(dm_odm, BB_REG[index], bMaskDWord, BB_AP_MODE[index]);
-				else if (BB_REG[index] == 0x870)
-					ODM_SetBBReg(dm_odm, BB_REG[index], bMaskDWord, BB_backup[index]|BIT10|BIT26);
-				else
-					ODM_SetBBReg(dm_odm, BB_REG[index], BIT10, 0x0);
-			}
-
-			ODM_SetBBReg(dm_odm, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
-			ODM_SetBBReg(dm_odm, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
-		} else {
-			/* path B */
-			ODM_SetBBReg(dm_odm, rTx_IQK_Tone_B, bMaskDWord, 0x01008c00);
-			ODM_SetBBReg(dm_odm, rRx_IQK_Tone_B, bMaskDWord, 0x01008c00);
-		}
-
-		ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
-			     ("phy_APCalibrate_8188E() offset 0x800 %x\n",
-			     ODM_GetBBReg(dm_odm, 0x800, bMaskDWord)));
-
-		/* MAC settings */
-		_PHY_MACSettingCalibration(adapt, MAC_REG, MAC_backup);
-
-		if (path == RF_PATH_A) {
-			/* Path B to standby mode */
-			ODM_SetRFReg(dm_odm, RF_PATH_B, RF_AC, bMaskDWord, 0x10000);
-		} else {
-			/* Path A to standby mode */
-			ODM_SetRFReg(dm_odm, RF_PATH_A, RF_AC, bMaskDWord, 0x10000);
-			ODM_SetRFReg(dm_odm, RF_PATH_A, RF_MODE1, bMaskDWord, 0x1000f);
-			ODM_SetRFReg(dm_odm, RF_PATH_A, RF_MODE2, bMaskDWord, 0x20103);
-		}
-
-		delta_offset = ((delta+14)/2);
-		if (delta_offset < 0)
-			delta_offset = 0;
-		else if (delta_offset > 12)
-			delta_offset = 12;
-
-		/* AP calibration */
-		for (index = 0; index < APK_BB_REG_NUM; index++) {
-			if (index != 1)	/* only DO PA11+PAD01001, AP RF setting */
-				continue;
-
-			tmpreg = APK_RF_init_value[path][index];
-			if (!dm_odm->RFCalibrateInfo.bAPKThermalMeterIgnore) {
-				BB_offset = (tmpreg & 0xF0000) >> 16;
-
-				if (!(tmpreg & BIT15)) /* sign bit 0 */
-					BB_offset = -BB_offset;
-
-				delta_V = APK_delta_mapping[index][delta_offset];
-
-				BB_offset += delta_V;
-
-				ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
-					     ("phy_APCalibrate_8188E() APK index %d tmpreg 0x%x delta_V %d delta_offset %d\n",
-					     index, tmpreg, delta_V, delta_offset));
-
-				if (BB_offset < 0) {
-					tmpreg = tmpreg & (~BIT15);
-					BB_offset = -BB_offset;
-				} else {
-					tmpreg = tmpreg | BIT15;
-				}
-				tmpreg = (tmpreg & 0xFFF0FFFF) | (BB_offset << 16);
-			}
-
-			ODM_SetRFReg(dm_odm, path, RF_IPA_A, bMaskDWord, 0x8992e);
-			ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("phy_APCalibrate_8188E() offset 0xc %x\n", PHY_QueryRFReg(adapt, path, RF_IPA_A, bMaskDWord)));
-			ODM_SetRFReg(dm_odm, path, RF_AC, bMaskDWord, APK_RF_value_0[path][index]);
-			ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,  ("phy_APCalibrate_8188E() offset 0x0 %x\n", PHY_QueryRFReg(adapt, path, RF_AC, bMaskDWord)));
-			ODM_SetRFReg(dm_odm, path, RF_TXBIAS_A, bMaskDWord, tmpreg);
-			ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("phy_APCalibrate_8188E() offset 0xd %x\n", PHY_QueryRFReg(adapt, path, RF_TXBIAS_A, bMaskDWord)));
-			/*  PA11+PAD01111, one shot */
-			i = 0;
-			do {
-				ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0x80000000);
-				ODM_SetBBReg(dm_odm, APK_offset[path], bMaskDWord, APK_value[0]);
-				ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("phy_APCalibrate_8188E() offset 0x%x value 0x%x\n", APK_offset[path], ODM_GetBBReg(dm_odm, APK_offset[path], bMaskDWord)));
-				ODM_delay_ms(3);
-				ODM_SetBBReg(dm_odm, APK_offset[path], bMaskDWord, APK_value[1]);
-				ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("phy_APCalibrate_8188E() offset 0x%x value 0x%x\n", APK_offset[path], ODM_GetBBReg(dm_odm, APK_offset[path], bMaskDWord)));
-
-				ODM_delay_ms(20);
-				ODM_SetBBReg(dm_odm, rFPGA0_IQK, bMaskDWord, 0x00000000);
-
-				if (path == RF_PATH_A)
-					tmpreg = ODM_GetBBReg(dm_odm, rAPK, 0x03E00000);
-				else
-					tmpreg = ODM_GetBBReg(dm_odm, rAPK, 0xF8000000);
-				ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("phy_APCalibrate_8188E() offset 0xbd8[25:21] %x\n", tmpreg));
-
-				i++;
-			} while (tmpreg > apkbound && i < 4);
-
-			APK_result[path][index] = tmpreg;
-		}
-	}
-
-	/* reload MAC default value */
-	_PHY_ReloadMACRegisters(adapt, MAC_REG, MAC_backup);
-
-	/* reload BB default value */
-	for (index = 0; index < APK_BB_REG_NUM; index++) {
-		if (index == 0)		/* skip */
-			continue;
-		ODM_SetBBReg(dm_odm, BB_REG[index], bMaskDWord, BB_backup[index]);
-	}
-
-	/* reload AFE default value */
-	reload_adda_reg(adapt, AFE_REG, AFE_backup, IQK_ADDA_REG_NUM);
-
-	/* reload RF path default value */
-	for (path = 0; path < pathbound; path++) {
-		ODM_SetRFReg(dm_odm, path, 0xd, bMaskDWord, regD[path]);
-		if (path == RF_PATH_B) {
-			ODM_SetRFReg(dm_odm, RF_PATH_A, RF_MODE1, bMaskDWord, 0x1000f);
-			ODM_SetRFReg(dm_odm, RF_PATH_A, RF_MODE2, bMaskDWord, 0x20101);
-		}
-
-		/* note no index == 0 */
-		if (APK_result[path][1] > 6)
-			APK_result[path][1] = 6;
-		ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("apk path %d result %d 0x%x \t", path, 1, APK_result[path][1]));
-	}
-
-	ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,  ("\n"));
-
-	for (path = 0; path < pathbound; path++) {
-		ODM_SetRFReg(dm_odm, path, 0x3, bMaskDWord,
-			     ((APK_result[path][1] << 15) | (APK_result[path][1] << 10) | (APK_result[path][1] << 5) | APK_result[path][1]));
-		if (path == RF_PATH_A)
-			ODM_SetRFReg(dm_odm, path, 0x4, bMaskDWord,
-				     ((APK_result[path][1] << 15) | (APK_result[path][1] << 10) | (0x00 << 5) | 0x05));
-		else
-			ODM_SetRFReg(dm_odm, path, 0x4, bMaskDWord,
-				     ((APK_result[path][1] << 15) | (APK_result[path][1] << 10) | (0x02 << 5) | 0x05));
-		ODM_SetRFReg(dm_odm, path, RF_BS_PA_APSET_G9_G11, bMaskDWord,
-			     ((0x08 << 15) | (0x08 << 10) | (0x08 << 5) | 0x08));
-	}
-
-	dm_odm->RFCalibrateInfo.bAPKdone = true;
-
-	ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD, ("<==phy_APCalibrate_8188E()\n"));
-}
-
-#define		DP_BB_REG_NUM		7
-#define		DP_RF_REG_NUM		1
-#define		DP_RETRY_LIMIT		10
-#define		DP_PATH_NUM		2
-#define		DP_DPK_NUM			3
-#define		DP_DPK_VALUE_NUM	2
-
 void PHY_IQCalibrate_8188E(struct adapter *adapt, bool recovery)
 {
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(adapt);
@@ -1697,7 +1296,7 @@
 	bool is2t;
 
 	is2t = (dm_odm->RFType == ODM_2T2R) ? true : false;
-	if (ODM_CheckPowerStatus(adapt) == false)
+	if (!ODM_CheckPowerStatus(adapt))
 		return;
 
 	if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
@@ -1867,28 +1466,6 @@
 		     ("LCK:Finish!!!interface %d\n", dm_odm->InterfaceIndex));
 }
 
-void PHY_APCalibrate_8188E(struct adapter *adapt, s8 delta)
-{
-	struct hal_data_8188e	*pHalData = GET_HAL_DATA(adapt);
-	struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
-
-	return;
-	if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
-		return;
-
-#if FOR_BRAZIL_PRETEST != 1
-	if (dm_odm->RFCalibrateInfo.bAPKdone)
-#endif
-		return;
-
-	if (dm_odm->RFType == ODM_2T2R) {
-		phy_APCalibrate_8188E(adapt, delta, true);
-	} else {
-		/*  For 88C 1T1R */
-		phy_APCalibrate_8188E(adapt, delta, false);
-	}
-}
-
 static void phy_setrfpathswitch_8188e(struct adapter *adapt, bool main, bool is2t)
 {
 	struct hal_data_8188e	*pHalData = GET_HAL_DATA(adapt);
diff --git a/drivers/staging/rtl8188eu/hal/HalPwrSeqCmd.c b/drivers/staging/rtl8188eu/hal/HalPwrSeqCmd.c
index e913a22..5700dbc 100644
--- a/drivers/staging/rtl8188eu/hal/HalPwrSeqCmd.c
+++ b/drivers/staging/rtl8188eu/hal/HalPwrSeqCmd.c
@@ -85,7 +85,7 @@
 				value &= ~(GET_PWR_CFG_MASK(pwrcfgcmd));
 				value |= (GET_PWR_CFG_VALUE(pwrcfgcmd) & GET_PWR_CFG_MASK(pwrcfgcmd));
 
-				/*  Write the value back to sytem register */
+				/*  Write the value back to system register */
 				rtw_write8(padapter, offset, value);
 				break;
 			case PWR_CMD_POLLING:
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
index 8c858775..8be2ad7 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
@@ -273,7 +273,7 @@
 static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength)
 {
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	u16 *fctrl;
+	__le16 *fctrl;
 	u32 rate_len, pktlen;
 	struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv);
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
@@ -360,7 +360,7 @@
 	struct rtw_ieee80211_hdr	*pwlanhdr;
 	struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv);
 	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
-	u16 *fctrl;
+	__le16 *fctrl;
 
 	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
 
@@ -391,7 +391,7 @@
 	u8 bForcePowerSave)
 {
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	u16 *fctrl;
+	__le16 *fctrl;
 	u32 pktlen;
 	struct mlme_priv *pmlmepriv = &adapt->mlmepriv;
 	struct wlan_network		*cur_network = &pmlmepriv->cur_network;
@@ -450,7 +450,7 @@
 static void ConstructProbeRsp(struct adapter *adapt, u8 *pframe, u32 *pLength, u8 *StaAddr, bool bHideSSID)
 {
 	struct rtw_ieee80211_hdr	*pwlanhdr;
-	u16 *fctrl;
+	__le16 *fctrl;
 	u8 *mac, *bssid;
 	u32 pktlen;
 	struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv);
@@ -484,7 +484,7 @@
 	*pLength = pktlen;
 }
 
-/*  To check if reserved page content is destroyed by beacon beacuse beacon is too large. */
+/*  To check if reserved page content is destroyed by beacon because beacon is too large. */
 /*  2010.06.23. Added by tynli. */
 void CheckFwRsvdPageContent(struct adapter *Adapter)
 {
@@ -496,9 +496,9 @@
 /*			(1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp. */
 /*	Input: */
 /*	    bDLFinished - false: At the first time we will send all the packets as a large packet to Hw, */
-/*						so we need to set the packet length to total lengh. */
+/*						so we need to set the packet length to total length. */
 /*			      true: At the second time, we should send the first packet (default:beacon) */
-/*						to Hw again and set the lengh in descriptor to the real beacon lengh. */
+/*						to Hw again and set the length in descriptor to the real beacon length. */
 /*  2009.10.15 by tynli. */
 static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished)
 {
@@ -671,7 +671,7 @@
 			DBG_88E("%s: 1 Download RSVD success! DLBcnCount:%u, poll:%u\n", __func__, DLBcnCount, poll);
 		/*  */
 		/*  We just can send the reserved page twice during the time that Tx thread is stopped (e.g. pnpsetpower) */
-		/*  becuase we need to free the Tx BCN Desc which is used by the first reserved page packet. */
+		/*  because we need to free the Tx BCN Desc which is used by the first reserved page packet. */
 		/*  At run time, we cannot get the Tx Desc until it is released in TxHandleInterrupt() so we will return */
 		/*  the beacon TCB in the following code. 2011.11.23. by tynli. */
 		/*  */
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
index 292ba62..52b3fba 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
@@ -19,6 +19,7 @@
  ******************************************************************************/
 #define _HAL_INIT_C_
 
+#include <linux/firmware.h>
 #include <drv_types.h>
 #include <rtw_efuse.h>
 
@@ -588,13 +589,15 @@
 	u8 writeFW_retry = 0;
 	u32 fwdl_start_time;
 	struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter);
-
-	u8 *FwImage;
-	u32			FwImageLen;
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct device *device = dvobj_to_dev(dvobj);
 	struct rt_firmware *pFirmware = NULL;
+	const struct firmware *fw;
 	struct rt_firmware_hdr *pFwHdr = NULL;
 	u8 *pFirmwareBuf;
-	u32			FirmwareLen;
+	u32 FirmwareLen;
+	char fw_name[] = "rtlwifi/rtl8188eufw.bin";
+	static int log_version;
 
 	RT_TRACE(_module_hal_init_c_, _drv_info_, ("+%s\n", __func__));
 	pFirmware = (struct rt_firmware *)rtw_zmalloc(sizeof(struct rt_firmware));
@@ -603,27 +606,32 @@
 		goto Exit;
 	}
 
-	FwImage = (u8 *)Rtl8188E_FwImageArray;
-	FwImageLen = Rtl8188E_FWImgArrayLength;
-
-	pFirmware->eFWSource = FW_SOURCE_HEADER_FILE;
-
-	switch (pFirmware->eFWSource) {
-	case FW_SOURCE_IMG_FILE:
-		break;
-	case FW_SOURCE_HEADER_FILE:
-		if (FwImageLen > FW_8188E_SIZE) {
-			rtStatus = _FAIL;
-			RT_TRACE(_module_hal_init_c_, _drv_err_, ("Firmware size exceed 0x%X. Check it.\n", FW_8188E_SIZE));
-			goto Exit;
-		}
-
-		pFirmware->szFwBuffer = FwImage;
-		pFirmware->ulFwLength = FwImageLen;
-		break;
+	if (request_firmware(&fw, fw_name, device)) {
+		rtStatus = _FAIL;
+		goto Exit;
 	}
+	if (!fw) {
+		pr_err("Firmware %s not available\n", fw_name);
+		rtStatus = _FAIL;
+		goto Exit;
+	}
+	if (fw->size > FW_8188E_SIZE) {
+		rtStatus = _FAIL;
+		RT_TRACE(_module_hal_init_c_, _drv_err_, ("Firmware size exceed 0x%X. Check it.\n", FW_8188E_SIZE));
+		goto Exit;
+	}
+
+	pFirmware->szFwBuffer = kzalloc(FW_8188E_SIZE, GFP_KERNEL);
+	if (!pFirmware->szFwBuffer) {
+		rtStatus = _FAIL;
+		goto Exit;
+	}
+	memcpy(pFirmware->szFwBuffer, fw->data, fw->size);
+	pFirmware->ulFwLength = fw->size;
 	pFirmwareBuf = pFirmware->szFwBuffer;
 	FirmwareLen = pFirmware->ulFwLength;
+	release_firmware(fw);
+
 	DBG_88E_LEVEL(_drv_info_, "+%s: !bUsedWoWLANFw, FmrmwareLen:%d+\n", __func__, FirmwareLen);
 
 	/*  To Check Fw header. Added by tynli. 2009.12.04. */
@@ -633,8 +641,10 @@
 	pHalData->FirmwareSubVersion = pFwHdr->Subversion;
 	pHalData->FirmwareSignature = le16_to_cpu(pFwHdr->Signature);
 
-	DBG_88E("%s: fw_ver =%d fw_subver =%d sig = 0x%x\n",
-		__func__, pHalData->FirmwareVersion, pHalData->FirmwareSubVersion, pHalData->FirmwareSignature);
+	if (!log_version++)
+		pr_info("%sFirmware Version %d, SubVersion %d, Signature 0x%x\n",
+			DRIVER_PREFIX, pHalData->FirmwareVersion,
+			pHalData->FirmwareSubVersion, pHalData->FirmwareSignature);
 
 	if (IS_FW_HEADER_EXIST(pFwHdr)) {
 		/*  Shift 32 bytes for FW header */
@@ -677,7 +687,7 @@
 		goto Exit;
 	}
 	RT_TRACE(_module_hal_init_c_, _drv_info_, ("Firmware is ready to run!\n"));
-
+	kfree(pFirmware->szFwBuffer);
 Exit:
 
 	kfree(pFirmware);
@@ -1479,7 +1489,6 @@
 
 static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt, bool bPseudoTest)
 {
-	bool bRet = false;
 	u16	efuse_addr = *pAddr;
 	u8 badworden = 0;
 	u32	PgWriteSuccess = 0;
@@ -1497,7 +1506,6 @@
 		else
 			return true;
 	}
-	return bRet;
 }
 
 static bool
@@ -1653,7 +1661,7 @@
 {
 	u16	efuse_max_available_len = 0;
 
-	/* Change to check TYPE_EFUSE_MAP_LEN , beacuse 8188E raw 256, logic map over 256. */
+	/* Change to check TYPE_EFUSE_MAP_LEN , because 8188E raw 256, logic map over 256. */
 	EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&efuse_max_available_len, false);
 
 	if (Efuse_GetCurrentSize(pAdapter, efuseType, bPseudoTest) >= efuse_max_available_len)
@@ -2100,7 +2108,7 @@
 	if (chnl <= 14) {
 		bIn24G = true;
 
-		if (chnl < 3)			/*  Chanel 1-2 */
+		if (chnl < 3)			/*  Channel 1-2 */
 			*pGroup = 0;
 		else if (chnl < 6)		/*  Channel 3-5 */
 			*pGroup = 1;
@@ -2182,7 +2190,7 @@
 		pHalData->bTXPowerDataReadFromEEPORM = true;
 
 	for (rfPath = 0; rfPath < pHalData->NumTotalRFPath; rfPath++) {
-		for (ch = 0; ch <= CHANNEL_MAX_NUMBER; ch++) {
+		for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
 			bIn24G = Hal_GetChnlGroup88E(ch, &group);
 			if (bIn24G) {
 				pHalData->Index24G_CCK_Base[rfPath][ch] = pwrInfo24G.IndexCCK_Base[rfPath][group];
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_phycfg.c b/drivers/staging/rtl8188eu/hal/rtl8188e_phycfg.c
index ff468a6..68bb96d 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_phycfg.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_phycfg.c
@@ -559,7 +559,7 @@
 
 	/*  */
 	/*  1. Read PHY_REG.TXT BB INIT!! */
-	/*  We will seperate as 88C / 92C according to chip version */
+	/*  We will separate as 88C / 92C according to chip version */
 	/*  */
 	if (HAL_STATUS_FAILURE == ODM_ConfigBBWithHeaderFile(&pHalData->odmpriv, CONFIG_BB_PHY_REG))
 		rtStatus = _FAIL;
@@ -685,7 +685,7 @@
 
 	/*  */
 	/*  Tested by MP, we found that CCK Index 0 equals to 8dbm, OFDM legacy equals to */
-	/*  3dbm, and OFDM HT equals to 0dbm repectively. */
+	/*  3dbm, and OFDM HT equals to 0dbm respectively. */
 	/*  Note: */
 	/*	The mapping may be different by different NICs. Do not use this formula for what needs accurate result. */
 	/*  By Bruce, 2008-01-29. */
@@ -1006,12 +1006,12 @@
 	switch (pHalData->CurrentChannelBW) {
 	case HT_CHANNEL_WIDTH_20:
 		regBwOpMode |= BW_OPMODE_20MHZ;
-		/*  2007/02/07 Mark by Emily becasue we have not verify whether this register works */
+		/*  2007/02/07 Mark by Emily because we have not verify whether this register works */
 		rtw_write8(Adapter, REG_BWOPMODE, regBwOpMode);
 		break;
 	case HT_CHANNEL_WIDTH_40:
 		regBwOpMode &= ~BW_OPMODE_20MHZ;
-		/*  2007/02/07 Mark by Emily becasue we have not verify whether this register works */
+		/*  2007/02/07 Mark by Emily because we have not verify whether this register works */
 		rtw_write8(Adapter, REG_BWOPMODE, regBwOpMode);
 		regRRSR_RSC = (regRRSR_RSC&0x90) | (pHalData->nCur40MhzPrimeSC<<5);
 		rtw_write8(Adapter, REG_RRSR+2, regRRSR_RSC);
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_rf6052.c b/drivers/staging/rtl8188eu/hal/rtl8188e_rf6052.c
index bfdf9b3..299e03e 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_rf6052.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_rf6052.c
@@ -181,7 +181,7 @@
 		 * tx power mechanism because it is referenced by BT
 		 * coexist mechanism.
 		 * In the future, two mechanism shall be separated from
-		 * each other and maintained independantly. */
+		 * each other and maintained independently. */
 		if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1) {
 			TxAGC[RF_PATH_A] = 0x10101010;
 			TxAGC[RF_PATH_B] = 0x10101010;
@@ -216,11 +216,11 @@
 	ODM_TxPwrTrackAdjust88E(&pHalData->odmpriv, 1, &direction, &pwrtrac_value);
 
 	if (direction == 1) {
-		/*  Increase TX pwoer */
+		/*  Increase TX power */
 		TxAGC[0] += pwrtrac_value;
 		TxAGC[1] += pwrtrac_value;
 	} else if (direction == 2) {
-		/*  Decrease TX pwoer */
+		/*  Decrease TX power */
 		TxAGC[0] -=  pwrtrac_value;
 		TxAGC[1] -=  pwrtrac_value;
 	}
@@ -292,7 +292,7 @@
 			if (pHalData->pwrGroupCnt == 1)
 				chnlGroup = 0;
 			if (pHalData->pwrGroupCnt >= pHalData->PGMaxGroup) {
-				if (Channel < 3)			/*  Chanel 1-2 */
+				if (Channel < 3)			/*  Channel 1-2 */
 					chnlGroup = 0;
 				else if (Channel < 6)		/*  Channel 3-5 */
 					chnlGroup = 1;
@@ -349,7 +349,7 @@
 		}
 /*  20100427 Joseph: Driver dynamic Tx power shall not affect Tx power. It shall be determined by power training mechanism. */
 /*  Currently, we cannot fully disable driver dynamic tx power mechanism because it is referenced by BT coexist mechanism. */
-/*  In the future, two mechanism shall be separated from each other and maintained independantly. Thanks for Lanhsin's reminder. */
+/*  In the future, two mechanism shall be separated from each other and maintained independently. Thanks for Lanhsin's reminder. */
 		/* 92d do not need this */
 		if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1)
 			writeVal = 0x14141414;
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c
index bd8a9ae..8f43f49 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c
@@ -332,7 +332,7 @@
 
 	/*  2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. */
 	/*  (1) The sequence number of each non-Qos frame / broadcast / multicast / */
-	/*  mgnt frame should be controled by Hw because Fw will also send null data */
+	/*  mgnt frame should be controlled by Hw because Fw will also send null data */
 	/*  which we cannot control when Fw LPS enable. */
 	/*  --> default enable non-Qos data sequense number. 2010.06.23. by tynli. */
 	/*  (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. */
diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c
index 5e656ce..cca9732 100644
--- a/drivers/staging/rtl8188eu/hal/usb_halinit.c
+++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c
@@ -464,7 +464,7 @@
 /*-----------------------------------------------------------------------------
  * Function:	usb_AggSettingTxUpdate()
  *
- * Overview:	Seperate TX/RX parameters update independent for TP detection and
+ * Overview:	Separate TX/RX parameters update independent for TP detection and
  *			dynamic TX/RX aggreagtion parameters update.
  *
  * Input:			struct adapter *
@@ -473,7 +473,7 @@
  *
  * Revised History:
  *	When		Who		Remark
- *	12/10/2010	MHC		Seperate to smaller function.
+ *	12/10/2010	MHC		Separate to smaller function.
  *
  *---------------------------------------------------------------------------*/
 static void usb_AggSettingTxUpdate(struct adapter *Adapter)
@@ -496,7 +496,7 @@
 /*-----------------------------------------------------------------------------
  * Function:	usb_AggSettingRxUpdate()
  *
- * Overview:	Seperate TX/RX parameters update independent for TP detection and
+ * Overview:	Separate TX/RX parameters update independent for TP detection and
  *			dynamic TX/RX aggreagtion parameters update.
  *
  * Input:			struct adapter *
@@ -505,7 +505,7 @@
  *
  * Revised History:
  *	When		Who		Remark
- *	12/10/2010	MHC		Seperate to smaller function.
+ *	12/10/2010	MHC		Separate to smaller function.
  *
  *---------------------------------------------------------------------------*/
 static void
@@ -847,7 +847,7 @@
 
 	/*  */
 	/*  Init CR MACTXEN, MACRXEN after setting RxFF boundary REG_TRXFF_BNDY to patch */
-	/*  Hw bug which Hw initials RxFF boundry size to a value which is larger than the real Rx buffer size in 88E. */
+	/*  Hw bug which Hw initials RxFF boundary size to a value which is larger than the real Rx buffer size in 88E. */
 	/*  */
 	/*  Enable MACTXEN/MACRXEN block */
 	value16 = rtw_read16(Adapter, REG_CR);
diff --git a/drivers/staging/rtl8188eu/hal/usb_ops_linux.c b/drivers/staging/rtl8188eu/hal/usb_ops_linux.c
index bc56416..787763e 100644
--- a/drivers/staging/rtl8188eu/hal/usb_ops_linux.c
+++ b/drivers/staging/rtl8188eu/hal/usb_ops_linux.c
@@ -547,6 +547,8 @@
 		RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete : purb->status(%d) != 0\n", purb->status));
 
 		DBG_88E("###=> usb_read_port_complete => urb status(%d)\n", purb->status);
+		skb_put(precvbuf->pskb, purb->actual_length);
+		precvbuf->pskb = NULL;
 
 		if (rtw_inc_and_chk_continual_urb_error(adapter_to_dvobj(adapt)))
 			adapt->bSurpriseRemoved = true;
@@ -605,68 +607,68 @@
 		return _FAIL;
 	}
 
+	if (!precvbuf) {
+		RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+			 ("usb_read_port:precvbuf==NULL\n"));
+		return _FAIL;
+	}
+
 	if ((!precvbuf->reuse) || (precvbuf->pskb == NULL)) {
 		precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
 		if (NULL != precvbuf->pskb)
 			precvbuf->reuse = true;
 	}
 
-	if (precvbuf != NULL) {
-		rtl8188eu_init_recvbuf(adapter, precvbuf);
+	rtl8188eu_init_recvbuf(adapter, precvbuf);
 
-		/* re-assign for linux based on skb */
-		if ((!precvbuf->reuse) || (precvbuf->pskb == NULL)) {
-			precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
-			if (precvbuf->pskb == NULL) {
-				RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("init_recvbuf(): alloc_skb fail!\n"));
-				DBG_88E("#### usb_read_port() alloc_skb fail!#####\n");
-				return _FAIL;
-			}
-
-			tmpaddr = (size_t)precvbuf->pskb->data;
-			alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
-			skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
-
-			precvbuf->phead = precvbuf->pskb->head;
-			precvbuf->pdata = precvbuf->pskb->data;
-			precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
-			precvbuf->pend = skb_end_pointer(precvbuf->pskb);
-			precvbuf->pbuf = precvbuf->pskb->data;
-		} else { /* reuse skb */
-			precvbuf->phead = precvbuf->pskb->head;
-			precvbuf->pdata = precvbuf->pskb->data;
-			precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
-			precvbuf->pend = skb_end_pointer(precvbuf->pskb);
-			precvbuf->pbuf = precvbuf->pskb->data;
-
-			precvbuf->reuse = false;
+	/* re-assign for linux based on skb */
+	if ((!precvbuf->reuse) || (precvbuf->pskb == NULL)) {
+		precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
+		if (precvbuf->pskb == NULL) {
+			RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("init_recvbuf(): alloc_skb fail!\n"));
+			DBG_88E("#### usb_read_port() alloc_skb fail!#####\n");
+			return _FAIL;
 		}
 
-		precvpriv->rx_pending_cnt++;
+		tmpaddr = (size_t)precvbuf->pskb->data;
+		alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
+		skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
 
-		purb = precvbuf->purb;
+		precvbuf->phead = precvbuf->pskb->head;
+		precvbuf->pdata = precvbuf->pskb->data;
+		precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
+		precvbuf->pend = skb_end_pointer(precvbuf->pskb);
+		precvbuf->pbuf = precvbuf->pskb->data;
+	} else { /* reuse skb */
+		precvbuf->phead = precvbuf->pskb->head;
+		precvbuf->pdata = precvbuf->pskb->data;
+		precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
+		precvbuf->pend = skb_end_pointer(precvbuf->pskb);
+		precvbuf->pbuf = precvbuf->pskb->data;
 
-		/* translate DMA FIFO addr to pipehandle */
-		pipe = ffaddr2pipehdl(pdvobj, addr);
+		precvbuf->reuse = false;
+	}
 
-		usb_fill_bulk_urb(purb, pusbd, pipe,
-				  precvbuf->pbuf,
-				  MAX_RECVBUF_SZ,
-				  usb_read_port_complete,
-				  precvbuf);/* context is precvbuf */
+	precvpriv->rx_pending_cnt++;
 
-		err = usb_submit_urb(purb, GFP_ATOMIC);
-		if ((err) && (err != (-EPERM))) {
-			RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-				 ("cannot submit rx in-token(err=0x%.8x), URB_STATUS =0x%.8x",
-				 err, purb->status));
-			DBG_88E("cannot submit rx in-token(err = 0x%08x),urb_status = %d\n",
-				err, purb->status);
-			ret = _FAIL;
-		}
-	} else {
+	purb = precvbuf->purb;
+
+	/* translate DMA FIFO addr to pipehandle */
+	pipe = ffaddr2pipehdl(pdvobj, addr);
+
+	usb_fill_bulk_urb(purb, pusbd, pipe,
+			  precvbuf->pbuf,
+			  MAX_RECVBUF_SZ,
+			  usb_read_port_complete,
+			  precvbuf);/* context is precvbuf */
+
+	err = usb_submit_urb(purb, GFP_ATOMIC);
+	if ((err) && (err != (-EPERM))) {
 		RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
-			 ("usb_read_port:precvbuf ==NULL\n"));
+			 ("cannot submit rx in-token(err=0x%.8x), URB_STATUS =0x%.8x",
+			 err, purb->status));
+		DBG_88E("cannot submit rx in-token(err = 0x%08x),urb_status = %d\n",
+			err, purb->status);
 		ret = _FAIL;
 	}
 
diff --git a/drivers/staging/rtl8188eu/include/Hal8188EFWImg_CE.h b/drivers/staging/rtl8188eu/include/Hal8188EFWImg_CE.h
deleted file mode 100644
index 949c33b..0000000
--- a/drivers/staging/rtl8188eu/include/Hal8188EFWImg_CE.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/******************************************************************************
-*
-* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
-*
-* This program is free software; you can redistribute it and/or modify it
-* under the terms of version 2 of the GNU General Public License as
-* published by the Free Software Foundation.
-*
-* This program is distributed in the hope that it will be useful, but WITHOUT
-* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-* more details.
-*
-* You should have received a copy of the GNU General Public License along with
-* this program; if not, write to the Free Software Foundation, Inc.,
-* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-*
-*
-******************************************************************************/
-#ifndef __INC_HAL8188E_FW_IMG_H
-#define __INC_HAL8188E_FW_IMG_H
-
-/* V10(1641) */
-#define Rtl8188EFWImgArrayLength 13904
-
-extern const u8 Rtl8188EFwImgArray[Rtl8188EFWImgArrayLength];
-
-#endif /* __INC_HAL8188E_FW_IMG_H */
diff --git a/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h b/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h
index c4769e2..25cae81 100644
--- a/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h
+++ b/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h
@@ -75,7 +75,7 @@
 
 #define MAX_PG_GROUP 13
 
-#define	RF_PATH_MAX			2
+#define	RF_PATH_MAX			3
 #define		MAX_RF_PATH		RF_PATH_MAX
 #define		MAX_TX_COUNT		4 /* path numbers */
 
diff --git a/drivers/staging/rtl8188eu/include/Hal8188EPhyReg.h b/drivers/staging/rtl8188eu/include/Hal8188EPhyReg.h
index 0e06d29..9f2969b 100644
--- a/drivers/staging/rtl8188eu/include/Hal8188EPhyReg.h
+++ b/drivers/staging/rtl8188eu/include/Hal8188EPhyReg.h
@@ -26,7 +26,7 @@
 /*  2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00 */
 /*  3. RF register 0x00-2E */
 /*  4. Bit Mask for BB/RF register */
-/*  5. Other defintion for BB/RF R/W */
+/*  5. Other definition for BB/RF R/W */
 /*  */
 
 
diff --git a/drivers/staging/rtl8188eu/include/HalPhyRf_8188e.h b/drivers/staging/rtl8188eu/include/HalPhyRf_8188e.h
index fa583f2..287e9f9 100644
--- a/drivers/staging/rtl8188eu/include/HalPhyRf_8188e.h
+++ b/drivers/staging/rtl8188eu/include/HalPhyRf_8188e.h
@@ -45,8 +45,6 @@
 void PHY_LCCalibrate_8188E(struct adapter *pAdapter);
 
 /*  AP calibrate */
-void PHY_APCalibrate_8188E(struct adapter *pAdapter, s8 delta);
-
 void PHY_DigitalPredistortion_8188E(struct adapter *pAdapter);
 
 void _PHY_SaveADDARegisters(struct adapter *pAdapter, u32 *ADDAReg,
diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h
index cd37ea4..c4d38d1 100644
--- a/drivers/staging/rtl8188eu/include/ieee80211.h
+++ b/drivers/staging/rtl8188eu/include/ieee80211.h
@@ -306,8 +306,8 @@
 };
 
 struct rtw_ieee80211_hdr {
-	u16 frame_ctl;
-	u16 duration_id;
+	__le16 frame_ctl;
+	__le16 duration_id;
 	u8 addr1[ETH_ALEN];
 	u8 addr2[ETH_ALEN];
 	u8 addr3[ETH_ALEN];
@@ -316,8 +316,8 @@
 } __packed;
 
 struct rtw_ieee80211_hdr_3addr {
-	u16 frame_ctl;
-	u16 duration_id;
+	__le16 frame_ctl;
+	__le16 duration_id;
 	u8 addr1[ETH_ALEN];
 	u8 addr2[ETH_ALEN];
 	u8 addr3[ETH_ALEN];
@@ -325,8 +325,8 @@
 } __packed;
 
 struct rtw_ieee80211_hdr_qos {
-	u16 frame_ctl;
-	u16 duration_id;
+	__le16 frame_ctl;
+	__le16 duration_id;
 	u8 addr1[ETH_ALEN];
 	u8 addr2[ETH_ALEN];
 	u8 addr3[ETH_ALEN];
@@ -336,8 +336,8 @@
 }  __packed;
 
 struct rtw_ieee80211_hdr_3addr_qos {
-	u16 frame_ctl;
-	u16 duration_id;
+	__le16 frame_ctl;
+	__le16 duration_id;
 	u8 addr1[ETH_ALEN];
 	u8 addr2[ETH_ALEN];
 	u8 addr3[ETH_ALEN];
diff --git a/drivers/staging/rtl8188eu/include/odm.h b/drivers/staging/rtl8188eu/include/odm.h
index 4787bac..eaa4bc1 100644
--- a/drivers/staging/rtl8188eu/include/odm.h
+++ b/drivers/staging/rtl8188eu/include/odm.h
@@ -283,8 +283,6 @@
 
 /*  Declare for common info */
 
-#define MAX_PATH_NUM_92CS	2
-
 struct odm_phy_status_info {
 	u8	RxPWDBAll;
 	u8	SignalQuality;	 /*  in 0-100 index. */
@@ -950,7 +948,7 @@
 	struct timer_list FastAntTrainingTimer;
 };		/*  DM_Dynamic_Mechanism_Structure */
 
-#define ODM_RF_PATH_MAX 2
+#define ODM_RF_PATH_MAX 3
 
 enum ODM_RF_RADIO_PATH {
 	ODM_RF_PATH_A = 0,   /* Radio Path A */
diff --git a/drivers/staging/rtl8188eu/include/odm_HWConfig.h b/drivers/staging/rtl8188eu/include/odm_HWConfig.h
index 63779f5..df52722 100644
--- a/drivers/staging/rtl8188eu/include/odm_HWConfig.h
+++ b/drivers/staging/rtl8188eu/include/odm_HWConfig.h
@@ -69,7 +69,7 @@
 };
 
 struct phy_status_rpt {
-	struct phy_rx_agc_info path_agc[2];
+	struct phy_rx_agc_info path_agc[3];
 	u8	ch_corr[2];
 	u8	cck_sig_qual_ofdm_pwdb_all;
 	u8	cck_agc_rpt_ofdm_cfosho_a;
@@ -79,7 +79,7 @@
 	u8	path_cfotail[2];
 	u8	pcts_mask[2];
 	s8	stream_rxevm[2];
-	u8	path_rxsnr[2];
+	u8	path_rxsnr[3];
 	u8	noise_power_db_lsb;
 	u8	rsvd_2[3];
 	u8	stream_csi[2];
diff --git a/drivers/staging/rtl8188eu/include/odm_debug.h b/drivers/staging/rtl8188eu/include/odm_debug.h
index a9ba6df..622f4c1 100644
--- a/drivers/staging/rtl8188eu/include/odm_debug.h
+++ b/drivers/staging/rtl8188eu/include/odm_debug.h
@@ -27,7 +27,7 @@
 /*	Define the debug levels */
 /*  */
 /*	1. DBG_TRACE and DBG_LOUD are used for normal cases. */
-/*	They can help SW engineer to develope or trace states changed */
+/*	They can help SW engineer to develop or trace states changed */
 /*	and also help HW enginner to trace every operation to and from HW, */
 /*	e.g IO, Tx, Rx. */
 /*  */
diff --git a/drivers/staging/rtl8188eu/include/odm_precomp.h b/drivers/staging/rtl8188eu/include/odm_precomp.h
index 520cbba..d1d95f4 100644
--- a/drivers/staging/rtl8188eu/include/odm_precomp.h
+++ b/drivers/staging/rtl8188eu/include/odm_precomp.h
@@ -31,11 +31,6 @@
 #include <drv_types.h>
 #include <hal_intf.h>
 
-/* 2 Hardware Parameter Files */
-
-#include "Hal8188EFWImg_CE.h"
-
-
 /* 2 OutSrc Header Files */
 
 #include "odm.h"
diff --git a/drivers/staging/rtl8188eu/include/rtw_cmd.h b/drivers/staging/rtl8188eu/include/rtw_cmd.h
index 819285b..8cafd7a 100644
--- a/drivers/staging/rtl8188eu/include/rtw_cmd.h
+++ b/drivers/staging/rtl8188eu/include/rtw_cmd.h
@@ -745,7 +745,7 @@
 
 Result:
 0x00: success
-0x01: sucess, and check Response.
+0x01: success, and check Response.
 0x02: cmd ignored due to duplicated sequcne number
 0x03: cmd dropped due to invalid cmd code
 0x04: reserved.
diff --git a/drivers/staging/rtl8188eu/include/rtw_led.h b/drivers/staging/rtl8188eu/include/rtw_led.h
index 2e61804..d0da4fd 100644
--- a/drivers/staging/rtl8188eu/include/rtw_led.h
+++ b/drivers/staging/rtl8188eu/include/rtw_led.h
@@ -163,14 +163,14 @@
 void LedControl8188eu(struct adapter *padapter, enum LED_CTL_MODE	LedAction);
 
 struct led_priv{
-	/* add for led controll */
+	/* add for led control */
 	struct LED_871x			SwLed0;
 	struct LED_871x			SwLed1;
 	enum LED_STRATEGY_871x	LedStrategy;
 	u8	bRegUseLed;
 	void (*LedControlHandler)(struct adapter *padapter,
 				  enum LED_CTL_MODE LedAction);
-	/* add for led controll */
+	/* add for led control */
 };
 
 #define rtw_led_control(adapt, action) \
diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme.h b/drivers/staging/rtl8188eu/include/rtw_mlme.h
index 22538e6..4a7143e 100644
--- a/drivers/staging/rtl8188eu/include/rtw_mlme.h
+++ b/drivers/staging/rtl8188eu/include/rtw_mlme.h
@@ -53,11 +53,11 @@
 #define	WIFI_SITE_MONITOR		0x00000800	/* to indicate the station is under site surveying */
 
 #define	WIFI_MP_STATE			0x00010000
-#define	WIFI_MP_CTX_BACKGROUND		0x00020000	/*  in continous tx background */
-#define	WIFI_MP_CTX_ST			0x00040000	/*  in continous tx with single-tone */
-#define	WIFI_MP_CTX_BACKGROUND_PENDING	0x00080000	/*  pending in continous tx background due to out of skb */
-#define	WIFI_MP_CTX_CCK_HW		0x00100000	/*  in continous tx */
-#define	WIFI_MP_CTX_CCK_CS		0x00200000	/*  in continous tx with carrier suppression */
+#define	WIFI_MP_CTX_BACKGROUND		0x00020000	/*  in continuous tx background */
+#define	WIFI_MP_CTX_ST			0x00040000	/*  in continuous tx with single-tone */
+#define	WIFI_MP_CTX_BACKGROUND_PENDING	0x00080000	/*  pending in continuous tx background due to out of skb */
+#define	WIFI_MP_CTX_CCK_HW		0x00100000	/*  in continuous tx */
+#define	WIFI_MP_CTX_CCK_CS		0x00200000	/*  in continuous tx with carrier suppression */
 #define WIFI_MP_LPBK_STATE		0x00400000
 
 #define _FW_UNDER_LINKING	WIFI_UNDER_LINKING
@@ -239,7 +239,7 @@
 	u8 profileindex; /* Used to point to the index of profileinfo array */
 	u8 peer_operating_ch;
 	u8 find_phase_state_exchange_cnt;
-	/* The device password ID for group negotation */
+	/* The device password ID for group negotiation */
 	u16 device_password_id_for_nego;
 	u8 negotiation_dialog_token;
 	/* SSID information for group negotitation */
diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h
index 853ab80..b1bfa2e 100644
--- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h
+++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h
@@ -107,7 +107,7 @@
 /*  Note: */
 /*	We just add new channel plan when the new channel plan is different
  *      from any of the following channel plan. */
-/*	If you just wnat to customize the acitions(scan period or join actions)
+/*	If you just want to customize the actions(scan period or join actions)
  *      about one of the channel plan, */
 /*	customize them in struct rt_channel_info in the RT_CHANNEL_LIST. */
 enum RT_CHANNEL_DOMAIN {
diff --git a/drivers/staging/rtl8188eu/include/rtw_mp_phy_regdef.h b/drivers/staging/rtl8188eu/include/rtw_mp_phy_regdef.h
index 3ad2207..30fd17f 100644
--- a/drivers/staging/rtl8188eu/include/rtw_mp_phy_regdef.h
+++ b/drivers/staging/rtl8188eu/include/rtw_mp_phy_regdef.h
@@ -56,7 +56,7 @@
 /*  2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00 */
 /*  3. RF register 0x00-2E */
 /*  4. Bit Mask for BB/RF register */
-/*  5. Other defintion for BB/RF R/W */
+/*  5. Other definition for BB/RF R/W */
 /*  */
 
 
diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h
index bae8885..be9c30c 100644
--- a/drivers/staging/rtl8188eu/include/rtw_recv.h
+++ b/drivers/staging/rtl8188eu/include/rtw_recv.h
@@ -83,7 +83,7 @@
 	u32	total_num;		/* num of valid elements */
 	u32	total_val;		/* sum of valid elements */
 };
-#define MAX_PATH_NUM_92CS		2
+#define MAX_PATH_NUM_92CS		3
 struct phy_info {
 	u8	RxPWDBAll;
 	u8	SignalQuality;	 /*  in 0-100 index. */
diff --git a/drivers/staging/rtl8188eu/include/rtw_rf.h b/drivers/staging/rtl8188eu/include/rtw_rf.h
index 089ecee..2df8837 100644
--- a/drivers/staging/rtl8188eu/include/rtw_rf.h
+++ b/drivers/staging/rtl8188eu/include/rtw_rf.h
@@ -119,7 +119,7 @@
 };
 
 /*  */
-/*  Represent Extention Channel Offset in HT Capabilities */
+/*  Represent Extension Channel Offset in HT Capabilities */
 /*  This is available only in 40Mhz mode. */
 /*  */
 enum ht_extchnl_offset {
diff --git a/drivers/staging/rtl8188eu/include/sta_info.h b/drivers/staging/rtl8188eu/include/sta_info.h
index 3ed2a39..3e909db 100644
--- a/drivers/staging/rtl8188eu/include/sta_info.h
+++ b/drivers/staging/rtl8188eu/include/sta_info.h
@@ -338,7 +338,7 @@
 	 */
 	struct sta_info *sta_aid[NUM_STA];
 
-	u16 sta_dz_bitmap;/* only support 15 stations, staion aid bitmap
+	u16 sta_dz_bitmap;/* only support 15 stations, station aid bitmap
 			   * for sleeping sta. */
 	u16 tim_bitmap;	/* only support 15 stations, aid=0~15 mapping
 			 * bit0~bit15 */
diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h
index a615659..84e5199 100644
--- a/drivers/staging/rtl8188eu/include/wifi.h
+++ b/drivers/staging/rtl8188eu/include/wifi.h
@@ -984,7 +984,7 @@
 #define	P2P_PROVISION_TIMEOUT		5000
 /* 3 seconds timeout for sending the prov disc request concurrent mode */
 #define	P2P_CONCURRENT_PROVISION_TIME	3000
-/* 5 seconds timeout for receiving the group negotation response */
+/* 5 seconds timeout for receiving the group negotiation response */
 #define	P2P_GO_NEGO_TIMEOUT		5000
 /* 3 seconds timeout for sending the negotiation request under concurrent mode */
 #define	P2P_CONCURRENT_GO_NEGO_TIME	3000
diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
index 95953eb..ae54587 100644
--- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
@@ -938,7 +938,7 @@
 	memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
 	if (pPMK->cmd == IW_PMKSA_ADD) {
 		DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_ADD!\n");
-		if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN) == true)
+		if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
 			return ret;
 		else
 			ret = true;
@@ -1039,7 +1039,7 @@
 
 	range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
 	/* TODO: Find real 'good' to 'bad' threshol value for RSSI */
-	range->avg_qual.level = 20 + -98;
+	range->avg_qual.level = 178; /* -78 dBm */
 	range->avg_qual.noise = 0;
 	range->avg_qual.updated = 7; /* Updated all three */
 
@@ -1074,7 +1074,7 @@
 
 /*  The following code will proivde the security capability to network manager. */
 /*  If the driver doesn't provide this capability to network manager, */
-/*  the WPA/WPA2 routers can't be choosen in the network manager. */
+/*  the WPA/WPA2 routers can't be chosen in the network manager. */
 
 /*
 #define IW_SCAN_CAPA_NONE		0x00
@@ -1373,7 +1373,7 @@
 				}
 			}
 
-			/* it has still some scan paramater to parse, we only do this now... */
+			/* it has still some scan parameter to parse, we only do this now... */
 			_status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
 		} else {
 			_status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
@@ -2626,7 +2626,7 @@
 			return -EINVAL;
 		}
 
-		if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN) == true) {
+		if (!memcmp(bssid, pnetwork->network.MacAddress, ETH_ALEN)) {
 			/* BSSID match, then check if supporting wpa/wpa2 */
 			DBG_88E("BSSID:%pM\n", (bssid));
 
@@ -2961,7 +2961,7 @@
 
 /*	Commented by Albert 20110520 */
 /*	This function will return the config method description */
-/*	This config method description will show us which config method the remote P2P device is intented to use */
+/*	This config method description will show us which config method the remote P2P device is intended to use */
 /*	by sending the provisioning discovery request frame. */
 
 static int rtw_p2p_get_req_cm(struct net_device *dev,
@@ -3413,7 +3413,7 @@
 	/*  +8 is for the str "InvProc =", we have to clear it at wrqu->data.pointer */
 
 	/*	Commented by Ouden 20121226 */
-	/*	The application wants to know P2P initation procedure is support or not. */
+	/*	The application wants to know P2P initiation procedure is supported or not. */
 	/*	Format: iwpriv wlanx p2p_get2 InvProc = 00:E0:4C:00:00:05 */
 
 	DBG_88E("[%s] data = %s\n", __func__, (char *)extra);
@@ -4040,7 +4040,7 @@
 	if (0 != ret)
 		goto exit;
 
-	if (!memcmp(rereg_priv->old_ifname, "disable%d", 9) == true) {
+	if (!memcmp(rereg_priv->old_ifname, "disable%d", 9)) {
 		padapter->ledpriv.bRegUseLed = rereg_priv->old_bRegUseLed;
 		rtw_hal_sw_led_init(padapter);
 		rtw_ips_mode_req(&padapter->pwrctrlpriv, rereg_priv->old_ips_mode);
@@ -4049,7 +4049,7 @@
 	strncpy(rereg_priv->old_ifname, new_ifname, IFNAMSIZ);
 	rereg_priv->old_ifname[IFNAMSIZ-1] = 0;
 
-	if (!memcmp(new_ifname, "disable%d", 9) == true) {
+	if (!memcmp(new_ifname, "disable%d", 9)) {
 		DBG_88E("%s disable\n", __func__);
 		/*  free network queue for Android's timming issue */
 		rtw_free_network_queue(padapter, true);
@@ -4884,7 +4884,6 @@
 	case _TKIP_:
 	case _TKIP_WTMIC_:
 	case _AES_:
-		keylen = 16;
 	default:
 		keylen = 16;
 	}
@@ -6146,7 +6145,7 @@
 
 		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
 			setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
-		/* Change to check TYPE_EFUSE_MAP_LEN, beacuse 8188E raw 256, logic map over 256. */
+		/* Change to check TYPE_EFUSE_MAP_LEN, because 8188E raw 256, logic map over 256. */
 		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_size, false);
 		if ((addr+cnts) > max_available_size) {
 			DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
@@ -6221,7 +6220,7 @@
 
 		for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
 			setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]);
-		/* Change to check TYPE_EFUSE_MAP_LEN, beacuse 8188E raw 256, logic map over 256. */
+		/* Change to check TYPE_EFUSE_MAP_LEN, because 8188E raw 256, logic map over 256. */
 		EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&max_available_size, false);
 		if ((addr+cnts) > max_available_size) {
 			DBG_88E("%s: addr(0x%X)+cnts(%d) parameter error!\n", __func__, addr, cnts);
diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
index 63bc913..17659bb 100644
--- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c
+++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
@@ -85,7 +85,7 @@
 static int rtw_uapsd_acvo_en;
 
 int rtw_ht_enable = 1;
-int rtw_cbw40_enable = 3; /*  0 :diable, bit(0): enable 2.4g, bit(1): enable 5g */
+int rtw_cbw40_enable = 3; /*  0 :disable, bit(0): enable 2.4g, bit(1): enable 5g */
 int rtw_ampdu_enable = 1;/* for enable tx_ampdu */
 static int rtw_rx_stbc = 1;/*  0: disable, bit(0):enable 2.4g, bit(1):enable 5g, default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ */
 static int rtw_ampdu_amsdu;/*  0: disabled, 1:enabled, 2:auto */
@@ -707,6 +707,10 @@
 	return 0;
 }
 
+static const struct device_type wlan_type = {
+	.name = "wlan",
+};
+
 struct net_device *rtw_init_netdev(struct adapter *old_padapter)
 {
 	struct adapter *padapter;
@@ -722,6 +726,7 @@
 	if (!pnetdev)
 		return NULL;
 
+	pnetdev->dev.type = &wlan_type;
 	padapter = rtw_netdev_priv(pnetdev);
 	padapter->pnetdev = pnetdev;
 	DBG_88E("register rtw_netdev_ops to netdev_ops\n");
diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c
index 4aedb85..a1ae727 100644
--- a/drivers/staging/rtl8188eu/os_dep/osdep_service.c
+++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c
@@ -419,13 +419,14 @@
 int rtw_change_ifname(struct adapter *padapter, const char *ifname)
 {
 	struct net_device *pnetdev;
-	struct net_device *cur_pnetdev = padapter->pnetdev;
+	struct net_device *cur_pnetdev;
 	struct rereg_nd_name_data *rereg_priv;
 	int ret;
 
 	if (!padapter)
 		goto error;
 
+	cur_pnetdev = padapter->pnetdev;
 	rereg_priv = &padapter->rereg_nd_name_priv;
 
 	/* free the old_pnetdev */
@@ -586,7 +587,7 @@
 }
 
 /**
- * rtw_cbuf_alloc - allocte a rtw_cbuf with given size and do initialization
+ * rtw_cbuf_alloc - allocate a rtw_cbuf with given size and do initialization
  * @size: size of pointer
  *
  * Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure
diff --git a/drivers/staging/rtl8188eu/os_dep/recv_linux.c b/drivers/staging/rtl8188eu/os_dep/recv_linux.c
index e2f4e7d..3852ff4 100644
--- a/drivers/staging/rtl8188eu/os_dep/recv_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/recv_linux.c
@@ -77,8 +77,7 @@
 int rtw_os_recvbuf_resource_free(struct adapter *padapter,
 				 struct recv_buf *precvbuf)
 {
-	if (precvbuf->purb)
-		usb_free_urb(precvbuf->purb);
+	usb_free_urb(precvbuf->purb);
 	return _SUCCESS;
 }
 
@@ -224,8 +223,7 @@
 _recv_indicatepkt_drop:
 
 	 /* enqueue back to free_recv_queue */
-	if (precv_frame)
-		rtw_free_recvframe(precv_frame, pfree_recv_queue);
+	rtw_free_recvframe(precv_frame, pfree_recv_queue);
 
 _func_exit_;
 	 return _FAIL;
diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
index 9ca3180..7d14779 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
@@ -737,7 +737,7 @@
 	status = _SUCCESS;
 
 free_hal_data:
-	if (status != _SUCCESS && padapter->HalData)
+	if (status != _SUCCESS)
 		kfree(padapter->HalData);
 handle_dualmac:
 	if (status != _SUCCESS)
diff --git a/drivers/staging/rtl8192e/dot11d.c b/drivers/staging/rtl8192e/dot11d.c
index f7b14f8b..1260f10 100644
--- a/drivers/staging/rtl8192e/dot11d.c
+++ b/drivers/staging/rtl8192e/dot11d.c
@@ -151,7 +151,7 @@
 			MaxChnlNum = pTriple->FirstChnl + j;
 		}
 
-		pTriple = (struct chnl_txpow_triple *)((u8*)pTriple + 3);
+		pTriple = (struct chnl_txpow_triple *)((u8 *)pTriple + 3);
 	}
 
 	UPDATE_CIE_SRC(dev, pTaddr);
diff --git a/drivers/staging/rtl8192e/dot11d.h b/drivers/staging/rtl8192e/dot11d.h
index 71f4549..fb7683f 100644
--- a/drivers/staging/rtl8192e/dot11d.h
+++ b/drivers/staging/rtl8192e/dot11d.h
@@ -38,7 +38,7 @@
 /**
  * struct rt_dot11d_info * @CountryIeLen: value greater than 0 if @CountryIeBuf contains
  *		  valid country information element.
- * @chanell_map: holds channel values
+ * @channel_map: holds channel values
  *		0 - invalid,
  *		1 - valid (active scan),
  *		2 - valid (passive scan)
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c
index 0da56c8..5af1c19 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c
@@ -140,7 +140,7 @@
 
 		rtStatus = rtl8192_phy_checkBBAndRF(dev, HW90_BLOCK_RF,
 						(enum rf90_radio_path)eRFPath);
-		if (rtStatus != true) {
+		if (!rtStatus) {
 			RT_TRACE(COMP_ERR, "PHY_RF8256_Config():Check "
 				 "Radio[%d] Fail!!\n", eRFPath);
 			goto phy_RF8256_Config_ParaFile_Fail;
@@ -245,7 +245,7 @@
 	struct r8192_priv *priv = rtllib_priv(dev);
 
 	TxAGC = powerlevel;
-	if (priv->bDynamicTxLowPower == true) {
+	if (priv->bDynamicTxLowPower) {
 		if (priv->CustomerID == RT_CID_819x_Netcore)
 			TxAGC = 0x22;
 		else
@@ -294,7 +294,7 @@
 			priv->Pwr_Track = writeVal_tmp;
 		}
 
-		if (priv->bDynamicTxHighPower == true)
+		if (priv->bDynamicTxHighPower)
 			writeVal = 0x03030303;
 		else
 			writeVal = (byte3 << 24) | (byte2 << 16) |
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
index 74fbd70..2cace9a 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
@@ -720,7 +720,7 @@
 	}
 	priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
 
-	if (priv->RegRfOff == true)
+	if (priv->RegRfOff)
 		priv->rtllib->eRFPowerState = eRfOff;
 
 	ulRegRead = read_nic_dword(dev, CPU_GEN);
@@ -745,7 +745,7 @@
 	}
 	RT_TRACE(COMP_INIT, "BB Config Start!\n");
 	rtStatus = rtl8192_BBConfig(dev);
-	if (rtStatus != true) {
+	if (!rtStatus) {
 		RT_TRACE(COMP_ERR, "BB Config failed\n");
 		return rtStatus;
 	}
@@ -856,7 +856,7 @@
 	if (priv->ResetProgress == RESET_TYPE_NORESET) {
 		RT_TRACE(COMP_INIT, "RF Config Started!\n");
 		rtStatus = rtl8192_phy_RFConfig(dev);
-		if (rtStatus != true) {
+		if (!rtStatus) {
 			RT_TRACE(COMP_ERR, "RF Config failed\n");
 			return rtStatus;
 		}
@@ -869,7 +869,7 @@
 
 	write_nic_byte(dev, 0x87, 0x0);
 
-	if (priv->RegRfOff == true) {
+	if (priv->RegRfOff) {
 		RT_TRACE((COMP_INIT | COMP_RF | COMP_POWER),
 			  "%s(): Turn off RF for RegRfOff ----------\n",
 			  __func__);
@@ -1184,7 +1184,7 @@
 						cb_desc);
 
 	if (pci_dma_mapping_error(priv->pdev, mapping))
-		RT_TRACE(COMP_ERR, "DMA Mapping error\n");;
+		RT_TRACE(COMP_ERR, "DMA Mapping error\n");
 	if (cb_desc->bAMPDUEnable) {
 		pTxFwInfo->AllowAggregation = 1;
 		pTxFwInfo->RxMF = cb_desc->ampdu_factor;
@@ -1283,7 +1283,7 @@
 			 PCI_DMA_TODEVICE);
 
 	if (pci_dma_mapping_error(priv->pdev, mapping))
-		RT_TRACE(COMP_ERR, "DMA Mapping error\n");;
+		RT_TRACE(COMP_ERR, "DMA Mapping error\n");
 	memset(entry, 0, 12);
 	entry->LINIP = cb_desc->bLastIniPkt;
 	entry->FirstSeg = 1;
@@ -1866,15 +1866,15 @@
 	type = WLAN_FC_GET_TYPE(fc);
 	praddr = hdr->addr1;
 
-	bpacket_match_bssid = ((RTLLIB_FTYPE_CTL != type) &&
-			(!compare_ether_addr(priv->rtllib->
-			current_network.bssid,
-			   (fc & RTLLIB_FCTL_TODS) ? hdr->addr1 :
-			   (fc & RTLLIB_FCTL_FROMDS) ? hdr->addr2 : hdr->addr3))
-		&& (!pstats->bHwError) && (!pstats->bCRC) && (!pstats->bICV));
-	bpacket_toself =  bpacket_match_bssid &&	/* check this */
-			  (!compare_ether_addr(praddr,
-			  priv->rtllib->dev->dev_addr));
+	bpacket_match_bssid =
+		((RTLLIB_FTYPE_CTL != type) &&
+		 ether_addr_equal(priv->rtllib->current_network.bssid,
+				  (fc & RTLLIB_FCTL_TODS) ? hdr->addr1 :
+				  (fc & RTLLIB_FCTL_FROMDS) ? hdr->addr2 :
+				  hdr->addr3) &&
+		 (!pstats->bHwError) && (!pstats->bCRC) && (!pstats->bICV));
+	bpacket_toself = bpacket_match_bssid &&		/* check this */
+			 ether_addr_equal(praddr, priv->rtllib->dev->dev_addr);
 	if (WLAN_FC_GET_FRAMETYPE(fc) == RTLLIB_STYPE_BEACON)
 		bPacketBeacon = true;
 	if (bpacket_match_bssid)
@@ -2213,7 +2213,7 @@
 	priv->MidHighPwrTHR_L2 = 0x40;
 	priv->PwrDomainProtect = false;
 
-	priv->bfirst_after_down = 0;
+	priv->bfirst_after_down = false;
 }
 
 void rtl8192_EnableInterrupt(struct net_device *dev)
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c
index dd2a96b..abcd22f 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c
@@ -329,7 +329,7 @@
 		}
 
 		rt_status = fw_download_code(dev, mapped_file, file_length);
-		if (rt_status != true) {
+		if (!rt_status) {
 			goto download_firmware_fail;
 		}
 
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
index 9676c59..21e6ddd 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
@@ -567,7 +567,7 @@
 		rtStatus  = rtl8192_phy_checkBBAndRF(dev,
 					 (enum hw90_block)eCheckItem,
 					 (enum rf90_radio_path)0);
-		if (rtStatus != true) {
+		if (!rtStatus) {
 			RT_TRACE((COMP_ERR | COMP_PHY), "PHY_RF8256_Config():"
 				 "Check PHY%d Fail!!\n", eCheckItem-1);
 			return rtStatus;
@@ -1425,7 +1425,7 @@
 	u8	i = 0, QueueID = 0;
 	struct rtl8192_tx_ring  *ring = NULL;
 
-	if (priv->SetRFPowerStateInProgress == true)
+	if (priv->SetRFPowerStateInProgress)
 		return false;
 	RT_TRACE(COMP_PS, "===========> SetRFPowerState8190()!\n");
 	priv->SetRFPowerStateInProgress = true;
@@ -1443,10 +1443,9 @@
 					InitilizeCount--;
 					priv->RegRfOff = false;
 					rtstatus = NicIFEnableNIC(dev);
-				} while ((rtstatus != true) &&
-					 (InitilizeCount > 0));
+				} while (!rtstatus && (InitilizeCount > 0));
 
-				if (rtstatus != true) {
+				if (!rtstatus) {
 					RT_TRACE(COMP_ERR, "%s():Initialize Ada"
 						 "pter fail,return\n",
 						 __func__);
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
index e068443..d93caca 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
@@ -370,8 +370,7 @@
 	case eRfOn:
 		priv->rtllib->RfOffReason &= (~ChangeSource);
 
-		if ((ChangeSource == RF_CHANGE_BY_HW) &&
-		    (priv->bHwRadioOff == true))
+		if ((ChangeSource == RF_CHANGE_BY_HW) && priv->bHwRadioOff)
 			priv->bHwRadioOff = false;
 
 		if (!priv->rtllib->RfOffReason) {
@@ -405,8 +404,7 @@
 						      disas_lv_ss);
 			}
 		}
-		if ((ChangeSource == RF_CHANGE_BY_HW) &&
-		     (priv->bHwRadioOff == false))
+		if ((ChangeSource == RF_CHANGE_BY_HW) && !priv->bHwRadioOff)
 			priv->bHwRadioOff = true;
 		priv->rtllib->RfOffReason |= ChangeSource;
 		bActionAllowed = true;
@@ -428,7 +426,7 @@
 		PHY_SetRFPowerState(dev, StateToSet);
 		if (StateToSet == eRfOn) {
 
-			if (bConnectBySSID && (priv->blinked_ingpio == true)) {
+			if (bConnectBySSID && priv->blinked_ingpio) {
 				queue_delayed_work_rsl(ieee->wq,
 					 &ieee->associate_procedure_wq, 0);
 				priv->blinked_ingpio = false;
@@ -955,7 +953,7 @@
 	RT_TRACE(COMP_INIT, "Bringing up iface");
 	priv->bfirst_init = true;
 	init_status = priv->ops->initialize_adapter(dev);
-	if (init_status != true) {
+	if (!init_status) {
 		RT_TRACE(COMP_ERR, "ERR!!! %s(): initialization is failed!\n",
 			 __func__);
 		priv->bfirst_init = false;
@@ -1000,7 +998,7 @@
 	priv->bDriverIsGoingToUnload = true;
 	priv->up = 0;
 	priv->rtllib->ieee_up = 0;
-	priv->bfirst_after_down = 1;
+	priv->bfirst_after_down = true;
 	RT_TRACE(COMP_DOWN, "==========>%s()\n", __func__);
 	if (!netif_queue_stopped(dev))
 		netif_stop_queue(dev);
@@ -1119,8 +1117,8 @@
 	priv->rtllib->hwscan_sem_up = 1;
 	priv->rtllib->status = 0;
 	priv->H2CTxCmdSeq = 0;
-	priv->bDisableFrameBursting = 0;
-	priv->bDMInitialGainEnable = 1;
+	priv->bDisableFrameBursting = false;
+	priv->bDMInitialGainEnable = true;
 	priv->polling_timer_on = 0;
 	priv->up_first_time = 1;
 	priv->blinked_ingpio = false;
@@ -1162,7 +1160,7 @@
 	priv->CckPwEnl = 6;
 	priv->ScanDelay = 50;
 	priv->ResetProgress = RESET_TYPE_NORESET;
-	priv->bForcedSilentReset = 0;
+	priv->bForcedSilentReset = false;
 	priv->bDisableNormalResetCheck = false;
 	priv->force_reset = false;
 	memset(priv->rtllib->swcamtable, 0, sizeof(struct sw_cam_table) * 32);
@@ -1171,7 +1169,7 @@
 	priv->RxCounter = 0;
 	priv->rtllib->wx_set_enc = 0;
 	priv->bHwRadioOff = false;
-	priv->RegRfOff = 0;
+	priv->RegRfOff = false;
 	priv->isRFOff = false;
 	priv->bInPowerSaveMode = false;
 	priv->rtllib->RfOffReason = 0;
@@ -1647,7 +1645,7 @@
 	bool	bHigherBusyRxTraffic = false;
 	bool bEnterPS = false;
 
-	if (IS_NIC_DOWN(priv) || (priv->bHwRadioOff == true))
+	if (IS_NIC_DOWN(priv) || priv->bHwRadioOff)
 		return;
 
 	if (priv->rtllib->state >= RTLLIB_LINKED) {
@@ -1888,9 +1886,8 @@
 	memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
 	skb_push(skb, priv->rtllib->tx_headroom);
 	ret = rtl8192_tx(dev, skb);
-	if (ret != 0) {
+	if (ret != 0)
 		kfree_skb(skb);
-	};
 
 	if (queue_index != MGNT_QUEUE) {
 		priv->rtllib->stats.tx_bytes += (skb->len -
@@ -1898,7 +1895,6 @@
 		priv->rtllib->stats.tx_packets++;
 	}
 
-
 	return;
 }
 
@@ -1930,15 +1926,11 @@
 		tcb_desc->bTxEnableFwCalcDur = 1;
 		skb_push(skb, priv->rtllib->tx_headroom);
 		ret = rtl8192_tx(dev, skb);
-		if (ret != 0) {
+		if (ret != 0)
 			kfree_skb(skb);
-		};
 	}
 
-
-
 	return ret;
-
 }
 
 static void rtl8192_tx_isr(struct net_device *dev, int prio)
@@ -2601,14 +2593,9 @@
 			goto out;
 		}
 
-		ipw = kmalloc(p->length, GFP_KERNEL);
-		if (ipw == NULL) {
-			ret = -ENOMEM;
-			goto out;
-		}
-		if (copy_from_user(ipw, p->pointer, p->length)) {
-			kfree(ipw);
-			ret = -EFAULT;
+		ipw = memdup_user(p->pointer, p->length);
+		if (IS_ERR(ipw)) {
+			ret = PTR_ERR(ipw);
 			goto out;
 		}
 
@@ -2982,7 +2969,6 @@
 	free_rtllib(dev);
 
 	DMESG("wlan driver load failed\n");
-	pci_set_drvdata(pdev, NULL);
 err_pci_disable:
 	pci_disable_device(pdev);
 	return err;
@@ -3052,7 +3038,7 @@
 	RT_TRACE(COMP_PS, "===========>%s()\n", __func__);
 	priv->bfirst_init = true;
 	init_status = priv->ops->initialize_adapter(dev);
-	if (init_status != true) {
+	if (!init_status) {
 		RT_TRACE(COMP_ERR, "ERR!!! %s(): initialization is failed!\n",
 			 __func__);
 		priv->bdisable_nic = false;
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
index 1853665..2297fc2 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
@@ -535,7 +535,7 @@
 				}
 			}
 
-			if (viviflag == true) {
+			if (viviflag) {
 				write_nic_byte(dev, Pw_Track_Flag, 0);
 				viviflag = false;
 				RT_TRACE(COMP_POWER_TRACKING, "we filted this data\n");
@@ -2265,7 +2265,7 @@
 		return;
 
 	if (priv->bfirst_after_down) {
-		priv->bfirst_after_down = 1;
+		priv->bfirst_after_down = true;
 		return;
 	}
 
@@ -2273,12 +2273,12 @@
 
 	eRfPowerStateToSet = (tmp1byte&BIT1) ?  eRfOn : eRfOff;
 
-	if ((priv->bHwRadioOff == true) && (eRfPowerStateToSet == eRfOn)) {
+	if (priv->bHwRadioOff && (eRfPowerStateToSet == eRfOn)) {
 		RT_TRACE(COMP_RF, "gpiochangeRF  - HW Radio ON\n");
 		printk(KERN_INFO "gpiochangeRF  - HW Radio ON\n");
 		priv->bHwRadioOff = false;
 		bActuallySet = true;
-	} else if ((priv->bHwRadioOff == false) && (eRfPowerStateToSet == eRfOff)) {
+	} else if (!priv->bHwRadioOff && (eRfPowerStateToSet == eRfOff)) {
 		RT_TRACE(COMP_RF, "gpiochangeRF  - HW Radio OFF\n");
 		printk(KERN_INFO "gpiochangeRF  - HW Radio OFF\n");
 		priv->bHwRadioOff = true;
@@ -2289,7 +2289,7 @@
 		mdelay(1000);
 		priv->bHwRfOffAction = 1;
 		MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW, true);
-		if (priv->bHwRadioOff == true)
+		if (priv->bHwRadioOff)
 			argv[1] = "RFOFF";
 		else
 			argv[1] = "RFON";
@@ -2312,9 +2312,9 @@
 
 	for (i = 0; i < RF90_PATH_MAX; i++) {
 		if (rfpath & (0x01<<i))
-			priv->brfpath_rxenable[i] = 1;
+			priv->brfpath_rxenable[i] = true;
 		else
-			priv->brfpath_rxenable[i] = 0;
+			priv->brfpath_rxenable[i] = false;
 	}
 	if (!DM_RxPathSelTable.Enable)
 		return;
@@ -2946,8 +2946,7 @@
 			priv->bDynamicTxLowPower = false;
 		} else {
 			if (priv->undecorated_smoothed_pwdb <
-			    txlowpower_threshold &&
-			    priv->bDynamicTxHighPower == true)
+			    txlowpower_threshold && priv->bDynamicTxHighPower)
 				priv->bDynamicTxHighPower = false;
 			if (priv->undecorated_smoothed_pwdb < 35)
 				priv->bDynamicTxLowPower = true;
diff --git a/drivers/staging/rtl8192e/rtl819x_TSProc.c b/drivers/staging/rtl8192e/rtl819x_TSProc.c
index 658e875..29608e5 100644
--- a/drivers/staging/rtl8192e/rtl819x_TSProc.c
+++ b/drivers/staging/rtl8192e/rtl819x_TSProc.c
@@ -264,7 +264,7 @@
 		psearch_list = &ieee->Rx_TS_Admit_List;
 
 	for (dir = 0; dir <= DIR_BI_DIR; dir++) {
-		if (search_dir[dir] == false)
+		if (!search_dir[dir])
 			continue;
 		list_for_each_entry(pRet, psearch_list, List) {
 			if (memcmp(pRet->Addr, Addr, 6) == 0)
@@ -348,7 +348,7 @@
 	if (*ppTS != NULL) {
 		return true;
 	} else {
-		if (bAddNewTs == false) {
+		if (!bAddNewTs) {
 			RTLLIB_DEBUG(RTLLIB_DL_TS, "add new TS failed"
 				     "(tid:%d)\n", UP);
 			return false;
diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c
index 8aeaed5..1a011b9 100644
--- a/drivers/staging/rtl8192e/rtllib_rx.c
+++ b/drivers/staging/rtl8192e/rtllib_rx.c
@@ -873,11 +873,11 @@
 		if (net_ratelimit())
 			printk(KERN_INFO "%s: find HTCControl!\n", __func__);
 		hdrlen += 4;
-		rx_stats->bContainHTC = 1;
+		rx_stats->bContainHTC = true;
 	}
 
 	 if (RTLLIB_QOS_HAS_SEQ(fc))
-		rx_stats->bIsQosData = 1;
+		rx_stats->bIsQosData = true;
 
 	return hdrlen;
 }
@@ -957,16 +957,15 @@
 static int rtllib_rx_data_filter(struct rtllib_device *ieee, u16 fc,
 				 u8 *dst, u8 *src, u8 *bssid, u8 *addr2)
 {
-	u8 zero_addr[ETH_ALEN] = {0};
 	u8 type, stype;
 
 	type = WLAN_FC_GET_TYPE(fc);
 	stype = WLAN_FC_GET_STYPE(fc);
 
 	/* Filter frames from different BSS */
-	if (((fc & RTLLIB_FCTL_DSTODS) != RTLLIB_FCTL_DSTODS)
-		&& (compare_ether_addr(ieee->current_network.bssid, bssid) != 0)
-		&& memcmp(ieee->current_network.bssid, zero_addr, ETH_ALEN)) {
+	if (((fc & RTLLIB_FCTL_DSTODS) != RTLLIB_FCTL_DSTODS) &&
+	    !ether_addr_equal(ieee->current_network.bssid, bssid) &&
+	    !is_zero_ether_addr(ieee->current_network.bssid)) {
 		return -1;
 	}
 
@@ -974,8 +973,8 @@
 	if (ieee->IntelPromiscuousModeInfo.bPromiscuousOn  &&
 		ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame) {
 		if ((fc & RTLLIB_FCTL_TODS) && !(fc & RTLLIB_FCTL_FROMDS) &&
-			(compare_ether_addr(dst, ieee->current_network.bssid) != 0) &&
-			(compare_ether_addr(bssid, ieee->current_network.bssid) == 0)) {
+		    !ether_addr_equal(dst, ieee->current_network.bssid) &&
+		    ether_addr_equal(bssid, ieee->current_network.bssid)) {
 			return -1;
 		}
 	}
@@ -1275,7 +1274,7 @@
 	/*Filter pkt not to me*/
 	multicast = is_multicast_ether_addr(hdr->addr1);
 	unicast = !multicast;
-	if (unicast && (compare_ether_addr(dev->dev_addr, hdr->addr1) != 0)) {
+	if (unicast && !ether_addr_equal(dev->dev_addr, hdr->addr1)) {
 		if (ieee->bNetPromiscuousMode)
 			bToOtherSTA = true;
 		else
@@ -1730,7 +1729,7 @@
 			network->CountryIeLen = info_element->len;
 
 			if (!IS_COUNTRY_IE_VALID(ieee)) {
-				if ((rtllib_act_scanning(ieee, false) == true) && (ieee->FirstIe_InScan == 1))
+				if (rtllib_act_scanning(ieee, false) && ieee->FirstIe_InScan)
 					printk(KERN_INFO "Received beacon ContryIE, SSID: <%s>\n", network->ssid);
 				Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data);
 			}
diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c
index 0cbf6f5..933bd6d 100644
--- a/drivers/staging/rtl8192e/rtllib_softmac.c
+++ b/drivers/staging/rtl8192e/rtllib_softmac.c
@@ -604,7 +604,7 @@
 
 	if (!ieee->ieee_up)
 		return;
-	if (rtllib_act_scanning(ieee, true) == true)
+	if (rtllib_act_scanning(ieee, true))
 		return;
 
 	down(&ieee->scan_sem);
@@ -705,7 +705,7 @@
 	ieee->scan_watch_dog = 0;
 	if (ieee->scanning_continue == 1) {
 		ieee->scanning_continue = 0;
-		ieee->actscanning = 0;
+		ieee->actscanning = false;
 
 		cancel_delayed_work(&ieee->softmac_scan_wq);
 	}
@@ -1202,7 +1202,7 @@
 
 	if ((ieee->rtllib_ap_sec_type &&
 	    (ieee->rtllib_ap_sec_type(ieee) & SEC_ALG_TKIP)) ||
-	    (ieee->bForcedBgMode == true)) {
+	    ieee->bForcedBgMode) {
 		ieee->pHTInfo->bEnableHT = 0;
 		ieee->mode = WIRELESS_MODE_G;
 	}
@@ -1535,7 +1535,7 @@
 	struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
 					(&(ieee->PowerSaveControl));
 	printk(KERN_INFO "Associated successfully\n");
-	if (ieee->is_silent_reset == 0) {
+	if (!ieee->is_silent_reset) {
 		printk(KERN_INFO "normal associate\n");
 		notify_wx_assoc_event(ieee);
 	}
@@ -1572,9 +1572,9 @@
 	pPSC->LpsIdleCount = 0;
 	ieee->link_change(ieee->dev);
 
-	if (ieee->is_silent_reset == 1) {
+	if (ieee->is_silent_reset) {
 		printk(KERN_INFO "silent reset associate\n");
-		ieee->is_silent_reset = 0;
+		ieee->is_silent_reset = false;
 	}
 
 	if (ieee->data_hard_resume)
@@ -2005,7 +2005,7 @@
 		return 0;
 
 	if (time) {
-		if (ieee->bAwakePktSent == true) {
+		if (ieee->bAwakePktSent) {
 			pPSC->LPSAwakeIntvl = 1;
 		} else {
 			u8		MaxPeriod = 1;
@@ -2338,8 +2338,7 @@
 					}
 
 					if (ieee->current_network.mode ==
-					    IEEE_N_24G &&
-					    bHalfSupportNmode == true) {
+					    IEEE_N_24G && bHalfSupportNmode) {
 						printk(KERN_INFO "======>enter "
 						       "half N mode\n");
 						ieee->bHalfWirelessN24GMode =
@@ -3098,7 +3097,7 @@
 	ieee->sta_edca_param[2] = 0x005E4342;
 	ieee->sta_edca_param[3] = 0x002F3262;
 	ieee->aggregation = true;
-	ieee->enable_rx_imm_BA = 1;
+	ieee->enable_rx_imm_BA = true;
 	ieee->tx_pending.txb = NULL;
 
 	_setup_timer(&ieee->associate_timer,
@@ -3591,14 +3590,9 @@
 		goto out;
 	}
 
-	param = kmalloc(p->length, GFP_KERNEL);
-	if (param == NULL) {
-		ret = -ENOMEM;
-		goto out;
-	}
-	if (copy_from_user(param, p->pointer, p->length)) {
-		kfree(param);
-		ret = -EFAULT;
+	param = memdup_user(p->pointer, p->length);
+	if (IS_ERR(param)) {
+		ret = PTR_ERR(param);
 		goto out;
 	}
 
diff --git a/drivers/staging/rtl8192e/rtllib_tx.c b/drivers/staging/rtl8192e/rtllib_tx.c
index 1cc6a9d..3183627 100644
--- a/drivers/staging/rtl8192e/rtllib_tx.c
+++ b/drivers/staging/rtl8192e/rtllib_tx.c
@@ -908,7 +908,7 @@
 				tcb_desc->data_rate = CURRENT_RATE(ieee->mode,
 					ieee->rate, ieee->HTCurrentOperaRate);
 
-			if (bdhcp == true) {
+			if (bdhcp) {
 				if (ieee->pHTInfo->IOTAction &
 				    HT_IOT_ACT_WA_IOT_Broadcom) {
 					tcb_desc->data_rate =
diff --git a/drivers/staging/rtl8192e/rtllib_wx.c b/drivers/staging/rtl8192e/rtllib_wx.c
index c7e8d4d8..13af43b 100644
--- a/drivers/staging/rtl8192e/rtllib_wx.c
+++ b/drivers/staging/rtl8192e/rtllib_wx.c
@@ -753,7 +753,7 @@
 		/* leave break out intentionly */
 
 	case IW_MLME_DISASSOC:
-		if (deauth == true)
+		if (deauth)
 			printk(KERN_INFO "disauth packet !\n");
 		else
 			printk(KERN_INFO "dis associate packet!\n");
diff --git a/drivers/staging/rtl8192u/dot11d.h b/drivers/staging/rtl8192u/dot11d.h
deleted file mode 100644
index 92e7a00..0000000
--- a/drivers/staging/rtl8192u/dot11d.h
+++ /dev/null
@@ -1,100 +0,0 @@
-#ifndef __INC_DOT11D_H
-#define __INC_DOT11D_H
-
-#include "ieee80211/ieee80211.h"
-
-
-typedef struct _CHNL_TXPOWER_TRIPLE {
-	u8 FirstChnl;
-	u8  NumChnls;
-	u8  MaxTxPowerInDbm;
-} CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE;
-
-typedef enum _DOT11D_STATE {
-	DOT11D_STATE_NONE = 0,
-	DOT11D_STATE_LEARNED,
-	DOT11D_STATE_DONE,
-} DOT11D_STATE;
-
-typedef struct _RT_DOT11D_INFO {
-	/* DECLARE_RT_OBJECT(RT_DOT11D_INFO); */
-
-	bool bEnabled; /* dot11MultiDomainCapabilityEnabled */
-
-	u16 CountryIeLen; /* > 0 if CountryIeBuf[] contains valid country information element. */
-	u8  CountryIeBuf[MAX_IE_LEN];
-	u8  CountryIeSrcAddr[6]; /* Source AP of the country IE. */
-	u8  CountryIeWatchdog;
-
-	u8  channel_map[MAX_CHANNEL_NUMBER+1];  /* !Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) */
-	u8  MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1];
-
-	DOT11D_STATE State;
-} RT_DOT11D_INFO, *PRT_DOT11D_INFO;
-#define eqMacAddr(a, b)		(((a)[0] == (b)[0] && \
-	(a)[1] == (b)[1] && (a)[2] == (b)[2] && (a)[3] == (b)[3] && \
-	(a)[4] == (b)[4] && (a)[5] == (b)[5]) ? 1 : 0)
-#define cpMacAddr(des, src)	      ((des)[0] = (src)[0], \
-	(des)[1] = (src)[1], (des)[2] = (src)[2], \
-	(des)[3] = (src)[3], (des)[4] = (src)[4], \
-	(des)[5] = (src)[5])
-#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo))
-
-#define IS_DOT11D_ENABLE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->bEnabled)
-#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0)
-
-#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
-#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
-
-#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \
-	(((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \
-	FALSE : \
-	(!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length)))
-
-#define CIE_WATCHDOG_TH 1
-#define GET_CIE_WATCHDOG(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog)
-#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0
-#define UPDATE_CIE_WATCHDOG(__pIeeeDev) (++GET_CIE_WATCHDOG(__pIeeeDev))
-
-#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
-
-
-void
-Dot11d_Init(
-	struct ieee80211_device *dev
-	);
-
-void
-Dot11d_Reset(
-	struct ieee80211_device *dev
-	);
-
-void
-Dot11d_UpdateCountryIe(
-	struct ieee80211_device *dev,
-	u8 *pTaddr,
-	u16 CoutryIeLen,
-	u8 *pCoutryIe
-	);
-
-u8
-DOT11D_GetMaxTxPwrInDbm(
-	struct ieee80211_device *dev,
-	u8 Channel
-	);
-
-void
-DOT11D_ScanComplete(
-	struct ieee80211_device *dev
-	);
-
-int IsLegalChannel(
-	struct ieee80211_device *dev,
-	u8 channel
-);
-
-int ToLegalChannel(
-	struct ieee80211_device *dev,
-	u8 channel
-);
-#endif /* #ifndef __INC_DOT11D_H */
diff --git a/drivers/staging/rtl8192u/ieee80211/dot11d.h b/drivers/staging/rtl8192u/ieee80211/dot11d.h
index 6aa8c15..bd75e29 100644
--- a/drivers/staging/rtl8192u/ieee80211/dot11d.h
+++ b/drivers/staging/rtl8192u/ieee80211/dot11d.h
@@ -4,42 +4,43 @@
 #include "ieee80211.h"
 
 
-//#define DOT11D_MAX_CHNL_NUM 83
-
 typedef struct _CHNL_TXPOWER_TRIPLE {
 	u8 FirstChnl;
 	u8  NumChnls;
 	u8  MaxTxPowerInDbm;
-}CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE;
+} CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE;
 
 typedef enum _DOT11D_STATE {
 	DOT11D_STATE_NONE = 0,
 	DOT11D_STATE_LEARNED,
 	DOT11D_STATE_DONE,
-}DOT11D_STATE;
+} DOT11D_STATE;
 
 typedef struct _RT_DOT11D_INFO {
-	//DECLARE_RT_OBJECT(RT_DOT11D_INFO);
+	/* DECLARE_RT_OBJECT(RT_DOT11D_INFO); */
 
-	bool bEnabled; // dot11MultiDomainCapabilityEnabled
+	bool bEnabled; /* dot11MultiDomainCapabilityEnabled */
 
-	u16 CountryIeLen; // > 0 if CountryIeBuf[] contains valid country information element.
+	u16 CountryIeLen; /* > 0 if CountryIeBuf[] contains valid country information element. */
 	u8  CountryIeBuf[MAX_IE_LEN];
-	u8  CountryIeSrcAddr[6]; // Source AP of the country IE.
+	u8  CountryIeSrcAddr[6]; /* Source AP of the country IE. */
 	u8  CountryIeWatchdog;
 
-	u8  channel_map[MAX_CHANNEL_NUMBER+1];  //!!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan)
-	//u8  ChnlListLen; // #Bytes valid in ChnlList[].
-	//u8  ChnlList[DOT11D_MAX_CHNL_NUM];
+	u8  channel_map[MAX_CHANNEL_NUMBER+1];  /* !Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) */
 	u8  MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1];
 
 	DOT11D_STATE State;
-}RT_DOT11D_INFO, *PRT_DOT11D_INFO;
-#define eqMacAddr(a,b)		( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 )
-#define cpMacAddr(des,src)	      ((des)[0]=(src)[0],(des)[1]=(src)[1],(des)[2]=(src)[2],(des)[3]=(src)[3],(des)[4]=(src)[4],(des)[5]=(src)[5])
+} RT_DOT11D_INFO, *PRT_DOT11D_INFO;
+#define eqMacAddr(a, b)		(((a)[0] == (b)[0] && \
+	(a)[1] == (b)[1] && (a)[2] == (b)[2] && (a)[3] == (b)[3] && \
+	(a)[4] == (b)[4] && (a)[5] == (b)[5]) ? 1 : 0)
+#define cpMacAddr(des, src)	      ((des)[0] = (src)[0], \
+	(des)[1] = (src)[1], (des)[2] = (src)[2], \
+	(des)[3] = (src)[3], (des)[4] = (src)[4], \
+	(des)[5] = (src)[5])
 #define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo))
 
-#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled
+#define IS_DOT11D_ENABLE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->bEnabled)
 #define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0)
 
 #define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
@@ -51,9 +52,9 @@
 	(!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length)))
 
 #define CIE_WATCHDOG_TH 1
-#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog
+#define GET_CIE_WATCHDOG(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog)
 #define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0
-#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev)
+#define UPDATE_CIE_WATCHDOG(__pIeeeDev) (++GET_CIE_WATCHDOG(__pIeeeDev))
 
 #define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
 
@@ -72,7 +73,7 @@
 Dot11d_UpdateCountryIe(
 	struct ieee80211_device *dev,
 	u8 *pTaddr,
-	u16	CoutryIeLen,
+	u16 CoutryIeLen,
 	u8 *pCoutryIe
 	);
 
@@ -96,4 +97,4 @@
 	struct ieee80211_device *dev,
 	u8 channel
 );
-#endif // #ifndef __INC_DOT11D_H
+#endif /* #ifndef __INC_DOT11D_H */
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
index 434c431..4b036a8 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
@@ -241,7 +241,7 @@
 			    //IEEE80211_DL_DATA	|
 			    IEEE80211_DL_ERR	  //awayls open this flags to show error out
 			    ;
-struct proc_dir_entry *ieee80211_proc;
+static struct proc_dir_entry *ieee80211_proc;
 
 static int show_debug_level(struct seq_file *m, void *v)
 {
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
index 59900bf..e730ed6 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
@@ -2166,7 +2166,8 @@
 	return RetSS;
 }
 
-long ieee80211_translate_todbm(u8 signal_strength_index	)// 0-100 index.
+/* 0-100 index */
+static long ieee80211_translate_todbm(u8 signal_strength_index)
 {
 	long	signal_power; // in dBm.
 
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
index 5fd6969..662c7e4 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
@@ -3150,14 +3150,9 @@
 		goto out;
 	}
 
-	param = kmalloc(p->length, GFP_KERNEL);
-	if (param == NULL){
-		ret = -ENOMEM;
-		goto out;
-	}
-	if (copy_from_user(param, p->pointer, p->length)) {
-		kfree(param);
-		ret = -EFAULT;
+	param = memdup_user(p->pointer, p->length);
+	if (IS_ERR(param)) {
+		ret = PTR_ERR(param);
 		goto out;
 	}
 
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
index a7bcc64f..157b2d7 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
@@ -237,8 +237,8 @@
 	kfree(txb);
 }
 
-struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
-					  int gfp_mask)
+static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
+						 gfp_t gfp_mask)
 {
 	struct ieee80211_txb *txb;
 	int i;
@@ -303,7 +303,8 @@
 }
 
 #define SN_LESS(a, b)		(((a-b)&0x800)!=0)
-void ieee80211_tx_query_agg_cap(struct ieee80211_device *ieee, struct sk_buff *skb, cb_desc *tcb_desc)
+static void ieee80211_tx_query_agg_cap(struct ieee80211_device *ieee,
+				       struct sk_buff *skb, cb_desc *tcb_desc)
 {
 	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
 	PTX_TS_RECORD			pTxTs = NULL;
@@ -412,7 +413,8 @@
 		tcb_desc->bUseShortGI = true;
 }
 
-void ieee80211_query_BandwidthMode(struct ieee80211_device *ieee, cb_desc *tcb_desc)
+static void ieee80211_query_BandwidthMode(struct ieee80211_device *ieee,
+					  cb_desc *tcb_desc)
 {
 	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
 
@@ -432,7 +434,9 @@
 	return;
 }
 
-void ieee80211_query_protectionmode(struct ieee80211_device *ieee, cb_desc *tcb_desc, struct sk_buff *skb)
+static void ieee80211_query_protectionmode(struct ieee80211_device *ieee,
+					   cb_desc *tcb_desc,
+					   struct sk_buff *skb)
 {
 	// Common Settings
 	tcb_desc->bRTSSTBC			= false;
@@ -543,7 +547,8 @@
 }
 
 
-void ieee80211_txrate_selectmode(struct ieee80211_device *ieee, cb_desc *tcb_desc)
+static void ieee80211_txrate_selectmode(struct ieee80211_device *ieee,
+					cb_desc *tcb_desc)
 {
 #ifdef TO_DO_LIST
 	if(!IsDataFrame(pFrame))
@@ -573,7 +578,8 @@
 	}
 }
 
-void ieee80211_query_seqnum(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *dst)
+static void ieee80211_query_seqnum(struct ieee80211_device *ieee,
+				   struct sk_buff *skb, u8 *dst)
 {
 	if (is_multicast_ether_addr(dst))
 		return;
diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c
index db0db93..3684da3 100644
--- a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c
+++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c
@@ -251,7 +251,8 @@
  *  output:  none
  *  notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
 ********************************************************************************************************************/
-void ieee80211_send_ADDBAReq(struct ieee80211_device *ieee, u8 *dst, PBA_RECORD	pBA)
+static void ieee80211_send_ADDBAReq(struct ieee80211_device *ieee,
+				    u8 *dst, PBA_RECORD pBA)
 {
 	struct sk_buff *skb = NULL;
 	skb = ieee80211_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); //construct ACT_ADDBAREQ frames so set statuscode zero.
@@ -278,7 +279,8 @@
  *  output:  none
  *  notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
 ********************************************************************************************************************/
-void ieee80211_send_ADDBARsp(struct ieee80211_device *ieee, u8 *dst, PBA_RECORD pBA, u16 StatusCode)
+static void ieee80211_send_ADDBARsp(struct ieee80211_device *ieee, u8 *dst,
+				    PBA_RECORD pBA, u16 StatusCode)
 {
 	struct sk_buff *skb = NULL;
 	skb = ieee80211_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP); //construct ACT_ADDBARSP frames
diff --git a/drivers/staging/rtl8192u/ieee80211_crypt.h b/drivers/staging/rtl8192u/ieee80211_crypt.h
deleted file mode 100644
index 0b4ea43..0000000
--- a/drivers/staging/rtl8192u/ieee80211_crypt.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Original code based on Host AP (software wireless LAN access point) driver
- * for Intersil Prism2/2.5/3.
- *
- * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
- * <jkmaline@cc.hut.fi>
- * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
- *
- * Adaption to a generic IEEE 802.11 stack by James Ketrenos
- * <jketreno@linux.intel.com>
- *
- * Copyright (c) 2004, Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. See README and COPYING for
- * more details.
- */
-
-/*
- * This file defines the interface to the ieee80211 crypto module.
- */
-#ifndef IEEE80211_CRYPT_H
-#define IEEE80211_CRYPT_H
-
-#include <linux/skbuff.h>
-
-struct ieee80211_crypto_ops {
-	const char *name;
-
-	/* init new crypto context (e.g., allocate private data space,
-	 * select IV, etc.); returns NULL on failure or pointer to allocated
-	 * private data on success */
-	void * (*init)(int keyidx);
-
-	/* deinitialize crypto context and free allocated private data */
-	void (*deinit)(void *priv);
-
-	/* encrypt/decrypt return < 0 on error or >= 0 on success. The return
-	 * value from decrypt_mpdu is passed as the keyidx value for
-	 * decrypt_msdu. skb must have enough head and tail room for the
-	 * encryption; if not, error will be returned; these functions are
-	 * called for all MPDUs (i.e., fragments).
-	 */
-	int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
-	int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
-
-	/* These functions are called for full MSDUs, i.e. full frames.
-	 * These can be NULL if full MSDU operations are not needed. */
-	int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv);
-	int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len,
-			    void *priv);
-
-	int (*set_key)(void *key, int len, u8 *seq, void *priv);
-	int (*get_key)(void *key, int len, u8 *seq, void *priv);
-
-	/* procfs handler for printing out key information and possible
-	 * statistics */
-	char * (*print_stats)(char *p, void *priv);
-
-	/* maximum number of bytes added by encryption; encrypt buf is
-	 * allocated with extra_prefix_len bytes, copy of in_buf, and
-	 * extra_postfix_len; encrypt need not use all this space, but
-	 * the result must start at the beginning of the buffer and correct
-	 * length must be returned */
-	int extra_prefix_len, extra_postfix_len;
-
-	struct module *owner;
-};
-
-struct ieee80211_crypt_data {
-	struct list_head list; /* delayed deletion list */
-	struct ieee80211_crypto_ops *ops;
-	void *priv;
-	atomic_t refcnt;
-};
-
-int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops);
-int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops);
-struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name);
-void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int);
-void ieee80211_crypt_deinit_handler(unsigned long);
-void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
-				    struct ieee80211_crypt_data **crypt);
-
-#endif
diff --git a/drivers/staging/rtl8192u/r8180_pm.c b/drivers/staging/rtl8192u/r8180_pm.c
deleted file mode 100644
index 999968d..0000000
--- a/drivers/staging/rtl8192u/r8180_pm.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-   Power management interface routines.
-   Written by Mariusz Matuszek.
-   This code is currently just a placeholder for later work and
-   does not do anything useful.
-
-   This is part of rtl8180 OpenSource driver.
-   Copyright (C) Andrea Merello 2004  <andrea.merello@gmail.com>
-   Released under the terms of GPL (General Public Licence)
-*/
-
-#ifdef CONFIG_RTL8180_PM
-
-
-#include "r8180_hw.h"
-#include "r8180_pm.h"
-
-int rtl8180_save_state (struct pci_dev *dev, u32 state)
-{
-	printk(KERN_NOTICE "r8180 save state call (state %u).\n", state);
-	return(-EAGAIN);
-}
-
-
-int rtl8180_suspend (struct pci_dev *dev, u32 state)
-{
-	printk(KERN_NOTICE "r8180 suspend call (state %u).\n", state);
-	return(-EAGAIN);
-}
-
-
-int rtl8180_resume (struct pci_dev *dev)
-{
-	printk(KERN_NOTICE "r8180 resume call.\n");
-	return(-EAGAIN);
-}
-
-
-int rtl8180_enable_wake (struct pci_dev *dev, u32 state, int enable)
-{
-	printk(KERN_NOTICE "r8180 enable wake call (state %u, enable %d).\n",
-	       state, enable);
-	return(-EAGAIN);
-}
-
-
-
-#endif //CONFIG_RTL8180_PM
diff --git a/drivers/staging/rtl8192u/r8180_pm.h b/drivers/staging/rtl8192u/r8180_pm.h
deleted file mode 100644
index 4be63da..0000000
--- a/drivers/staging/rtl8192u/r8180_pm.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-	Power management interface routines.
-	Written by Mariusz Matuszek.
-	This code is currently just a placeholder for later work and
-	does not do anything useful.
-
-	This is part of rtl8180 OpenSource driver.
-	Copyright (C) Andrea Merello 2004  <andrea.merello@gmail.com>
-	Released under the terms of GPL (General Public Licence)
-
-*/
-
-#ifdef CONFIG_RTL8180_PM
-
-#ifndef R8180_PM_H
-#define R8180_PM_H
-
-#include <linux/types.h>
-#include <linux/pci.h>
-
-int rtl8180_save_state (struct pci_dev *dev, u32 state);
-int rtl8180_suspend (struct pci_dev *dev, u32 state);
-int rtl8180_resume (struct pci_dev *dev);
-int rtl8180_enable_wake (struct pci_dev *dev, u32 state, int enable);
-
-#endif //R8180_PM_H
-
-#endif // CONFIG_RTL8180_PM
diff --git a/drivers/staging/rtl8192u/r8190_rtl8256.h b/drivers/staging/rtl8192u/r8190_rtl8256.h
index 592e780..fa6dd37 100644
--- a/drivers/staging/rtl8192u/r8190_rtl8256.h
+++ b/drivers/staging/rtl8192u/r8190_rtl8256.h
@@ -13,11 +13,7 @@
 #ifndef RTL8225H
 #define RTL8225H
 
-#ifdef RTL8190P
-#define RTL819X_TOTAL_RF_PATH 4 //for 90P
-#else
 #define RTL819X_TOTAL_RF_PATH 2 //for 8192U
-#endif
 extern void PHY_SetRF8256Bandwidth(struct net_device *dev , HT_CHANNEL_WIDTH Bandwidth);
 extern void PHY_RF8256_Config(struct net_device *dev);
 extern void phy_RF8256_Config_ParaFile(struct net_device *dev);
diff --git a/drivers/staging/rtl8192u/r8192U.h b/drivers/staging/rtl8192u/r8192U.h
index b484ee1..ad3bc56 100644
--- a/drivers/staging/rtl8192u/r8192U.h
+++ b/drivers/staging/rtl8192u/r8192U.h
@@ -409,15 +409,11 @@
 #define	USB_HWDESC_HEADER_LEN		sizeof(tx_desc_819x_usb)
 #define TX_PACKET_SHIFT_BYTES		(USB_HWDESC_HEADER_LEN + sizeof(tx_fwinfo_819x_usb))
 #define MAX_FRAGMENT_COUNT		8
-#ifdef RTL8192U
 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
 #define MAX_TRANSMIT_BUFFER_SIZE			32000
 #else
 #define MAX_TRANSMIT_BUFFER_SIZE			8000
 #endif
-#else
-#define MAX_TRANSMIT_BUFFER_SIZE	(1600+(MAX_802_11_HEADER_LENGTH+ENCRYPTION_MAX_OVERHEAD)*MAX_FRAGMENT_COUNT)
-#endif
 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
 #define TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES (sizeof(tx_desc_819x_usb_aggr_subframe) + sizeof(tx_fwinfo_819x_usb))
 #endif
@@ -1158,14 +1154,6 @@
 	NIC_8192E = 3,
 } nic_t;
 
-
-#ifdef JOHN_HWSEC
-struct ssid_thread {
-	struct net_device *dev;
-	u8 name[IW_ESSID_MAX_SIZE + 1];
-};
-#endif
-
 bool init_firmware(struct net_device *dev);
 short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb);
 short rtl8192_tx(struct net_device *dev, struct sk_buff *skb);
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index cd0946d..c2bcbe2 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -392,7 +392,7 @@
 	return 0;
 }
 
-int read_nic_word_E(struct net_device *dev, int indx, u16 *data)
+static int read_nic_word_E(struct net_device *dev, int indx, u16 *data)
 {
 	int status;
 	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
@@ -585,7 +585,7 @@
 	return 0;
 }
 
-void rtl8192_proc_module_init(void)
+static void rtl8192_proc_module_init(void)
 {
 	RT_TRACE(COMP_INIT, "Initializing proc filesystem");
 	rtl8192_proc = proc_mkdir(RTL819xU_MODULE_NAME, init_net.proc_net);
@@ -631,7 +631,7 @@
 	{ "" }
 };
 
-void rtl8192_proc_init_one(struct net_device *dev)
+static void rtl8192_proc_init_one(struct net_device *dev)
 {
 	const struct rtl8192_proc_file *f;
 	struct proc_dir_entry *dir;
@@ -656,7 +656,7 @@
 	}
 }
 
-void rtl8192_proc_remove_one(struct net_device *dev)
+static void rtl8192_proc_remove_one(struct net_device *dev)
 {
 	remove_proc_subtree(dev->name, rtl8192_proc);
 }
@@ -755,7 +755,7 @@
 
 static void rtl8192_rx_isr(struct urb *urb);
 
-u32 get_rxpacket_shiftbytes_819xusb(struct ieee80211_rx_stats *pstats)
+static u32 get_rxpacket_shiftbytes_819xusb(struct ieee80211_rx_stats *pstats)
 {
 
 #ifdef USB_RX_AGGREGATION_SUPPORT
@@ -998,8 +998,8 @@
 		netdev_err(dev, "can not submit rxurb, err is %x, URB status is %x\n", err, urb->status);
 }
 
-u32 rtl819xusb_rx_command_packet(struct net_device *dev,
-				 struct ieee80211_rx_stats *pstats)
+static u32 rtl819xusb_rx_command_packet(struct net_device *dev,
+					struct ieee80211_rx_stats *pstats)
 {
 	u32	status;
 
@@ -1609,13 +1609,6 @@
 #else
 	idx_pipe = 0x04;
 #endif
-#ifdef JOHN_DUMP_TXDESC
-	int i;
-	printk("<Tx descriptor>--rate %x---", rate);
-	for (i = 0; i < 8; i++)
-		printk("%8x ", tx[i]);
-	printk("\n");
-#endif
 	usb_fill_bulk_urb(tx_urb, priv->udev, usb_sndbulkpipe(priv->udev, idx_pipe),
 			  skb->data, skb->len, rtl8192_tx_isr, skb);
 
@@ -1636,7 +1629,7 @@
  *
  * \param QUEUEID       Software Queue
 */
-u8 MapHwQueueToFirmwareQueue(u8 QueueID)
+static u8 MapHwQueueToFirmwareQueue(u8 QueueID)
 {
 	u8 QueueSelect = 0x0;       //defualt set to
 
@@ -1723,7 +1716,7 @@
 }
 
 
-u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc)
+static u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc)
 {
 	u8   tmp_Short;
 
@@ -1934,7 +1927,7 @@
 	}
 }
 
-short rtl8192_usb_initendpoints(struct net_device *dev)
+static short rtl8192_usb_initendpoints(struct net_device *dev)
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
 
@@ -1992,7 +1985,7 @@
 
 }
 #ifdef THOMAS_BEACON
-void rtl8192_usb_deleteendpoints(struct net_device *dev)
+static void rtl8192_usb_deleteendpoints(struct net_device *dev)
 {
 	int i;
 	struct r8192_priv *priv = ieee80211_priv(dev);
@@ -2009,7 +2002,7 @@
 	priv->oldaddr = NULL;
 	if (priv->pp_rxskb) {
 		kfree(priv->pp_rxskb);
-		priv->pp_rxskb = 0;
+		priv->pp_rxskb = NULL;
 	}
 }
 #else
@@ -2292,7 +2285,7 @@
 
 static u8 ccmp_ie[4] = {0x00, 0x50, 0xf2, 0x04};
 static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
-bool GetNmodeSupportBySecCfg8192(struct net_device *dev)
+static bool GetNmodeSupportBySecCfg8192(struct net_device *dev)
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
 	struct ieee80211_device *ieee = priv->ieee80211;
@@ -3167,7 +3160,7 @@
 	return &priv->ieee80211->stats;
 }
 
-bool HalTxCheckStuck819xUsb(struct net_device *dev)
+static bool HalTxCheckStuck819xUsb(struct net_device *dev)
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
 	u16		RegTxCounter;
@@ -3217,7 +3210,7 @@
 	return RESET_TYPE_NORESET;
 }
 
-bool HalRxCheckStuck819xUsb(struct net_device *dev)
+static bool HalRxCheckStuck819xUsb(struct net_device *dev)
 {
 	u16	RegRxCounter;
 	struct r8192_priv *priv = ieee80211_priv(dev);
@@ -3259,7 +3252,7 @@
 	return bStuck;
 }
 
-RESET_TYPE RxCheckStuck(struct net_device *dev)
+static RESET_TYPE RxCheckStuck(struct net_device *dev)
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
 	bool        bRxCheck = FALSE;
@@ -3796,14 +3789,9 @@
 		goto out;
 	}
 
-	ipw = kmalloc(p->length, GFP_KERNEL);
-	if (ipw == NULL) {
-		ret = -ENOMEM;
-		goto out;
-	}
-	if (copy_from_user(ipw, p->pointer, p->length)) {
-		kfree(ipw);
-		ret = -EFAULT;
+	ipw = memdup_user(p->pointer, p->length);
+	if (IS_ERR(ipw)) {
+		ret = PTR_ERR(ipw);
 		goto out;
 	}
 
@@ -3859,15 +3847,6 @@
 				}
 			}
 		}
-#ifdef JOHN_HWSEC_DEBUG
-		//john's test 0711
-		printk("@@ wrq->u pointer = ");
-		for (i = 0; i < wrq->u.data.length; i++) {
-			if (i%10 == 0) printk("\n");
-			printk("%8x|", ((u32 *)wrq->u.data.pointer)[i]);
-		}
-		printk("\n");
-#endif /*JOHN_HWSEC_DEBUG*/
 		ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data);
 		break;
 
@@ -3952,7 +3931,8 @@
  * Return:
  *               None
  */
-void UpdateRxPktTimeStamp8190(struct net_device *dev, struct ieee80211_rx_stats *stats)
+static void UpdateRxPktTimeStamp8190(struct net_device *dev,
+				     struct ieee80211_rx_stats *stats)
 {
 	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
 
@@ -4209,7 +4189,7 @@
 //	We want good-looking for signal strength/quality
 //	2007/7/19 01:09, by cosa.
 //
-long rtl819x_signal_scale_mapping(long currsig)
+static long rtl819x_signal_scale_mapping(long currsig)
 {
 	long retsig;
 
@@ -4478,9 +4458,9 @@
 }
 
 
-void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
-				   struct ieee80211_rx_stats *pstats,
-				   rx_drvinfo_819x_usb  *pdrvinfo)
+static void TranslateRxSignalStuff819xUsb(struct sk_buff *skb,
+					  struct ieee80211_rx_stats *pstats,
+					  rx_drvinfo_819x_usb  *pdrvinfo)
 {
 	// TODO: We must only check packet for current MAC address. Not finish
 	rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
@@ -4549,8 +4529,9 @@
 * Return:
 *		None
 */
-void UpdateReceivedRateHistogramStatistics8190(struct net_device *dev,
-					       struct ieee80211_rx_stats *stats)
+static void
+UpdateReceivedRateHistogramStatistics8190(struct net_device *dev,
+					  struct ieee80211_rx_stats *stats)
 {
 	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
 	u32 rcvType = 1;   //0: Total, 1:OK, 2:CRC, 3:ICV
@@ -4614,7 +4595,9 @@
 }
 
 
-void query_rxdesc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats, bool bIsRxAggrSubframe)
+static void query_rxdesc_status(struct sk_buff *skb,
+				struct ieee80211_rx_stats *stats,
+				bool bIsRxAggrSubframe)
 {
 	rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb;
 	struct net_device *dev = info->dev;
@@ -4930,7 +4913,8 @@
 
 }
 
-void query_rx_cmdpkt_desc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats)
+static void query_rx_cmdpkt_desc_status(struct sk_buff *skb,
+					struct ieee80211_rx_stats *stats)
 {
 	rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data;
 
diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c
index a6e4c37..41fb67b 100644
--- a/drivers/staging/rtl8192u/r8192U_dm.c
+++ b/drivers/staging/rtl8192u/r8192U_dm.c
@@ -100,14 +100,6 @@
 //static	void	dm_txpower_reset_recovery(struct net_device *dev);
 
 
-// DM --> BB init gain restore
-#ifndef RTL8192U
-static	void	dm_bb_initialgain_restore(struct net_device *dev);
-
-
-// DM --> BB init gain backup
-static	void	dm_bb_initialgain_backup(struct net_device *dev);
-#endif
 // DM --> Dynamic Init Gain by RSSI
 static	void	dm_dig_init(struct net_device *dev);
 static	void	dm_ctrl_initgain_byrssi(struct net_device *dev);
@@ -122,12 +114,7 @@
 // DM --> EDCA turbo mode control
 static	void	dm_check_edca_turbo(struct net_device *dev);
 
-// DM --> HW RF control
-static	void	dm_check_rfctrl_gpio(struct net_device *dev);
-
-#ifndef RTL8190P
 //static	void	dm_gpio_change_rf(struct net_device *dev);
-#endif
 // DM --> Check PBC
 static	void dm_check_pbc_gpio(struct net_device *dev);
 
@@ -269,7 +256,6 @@
 	dm_ctrl_initgain_byrssi(dev);
 	dm_check_edca_turbo(dev);
 	dm_bandwidth_autoswitch(dev);
-	dm_check_rfctrl_gpio(dev);
 	dm_check_rx_path_selection(dev);
 	dm_check_fsync(dev);
 
@@ -620,16 +606,11 @@
 	tx_cmd.Op		= TXCMD_SET_TX_PWR_TRACKING;
 	tx_cmd.Length	= 4;
 	tx_cmd.Value		= Value;
-#ifdef RTL8192U
 	rtStatus = SendTxCommandPacket(dev, &tx_cmd, 12);
 	if (rtStatus == RT_STATUS_FAILURE)
 	{
 		RT_TRACE(COMP_POWER_TRACKING, "Set configuration with tx cmd queue fail!\n");
 	}
-#else
-	cmpk_message_handle_tx(dev, (u8 *)&tx_cmd,
-								DESC_PACKET_TYPE_INIT, sizeof(DCMD_TXCMD_T));
-#endif
 	mdelay(1);
 	//DbgPrint("hi, vivi, strange\n");
 	for(i = 0;i <= 30; i++)
@@ -641,11 +622,7 @@
 			mdelay(1);
 			continue;
 		}
-#ifdef RTL8190P
-		read_nic_word(dev, 0x1bc, &Avg_TSSI_Meas);
-#else
 		read_nic_word(dev, 0x13c, &Avg_TSSI_Meas);
-#endif
 		if(Avg_TSSI_Meas == 0)
 		{
 			write_nic_byte(dev, 0x1ba, 0);
@@ -654,14 +631,10 @@
 
 		for(k = 0;k < 5; k++)
 		{
-#ifdef RTL8190P
-			read_nic_byte(dev, 0x1d8+k, &tmp_report[k]);
-#else
 			if(k !=4)
 				read_nic_byte(dev, 0x134+k, &tmp_report[k]);
 			else
 				read_nic_byte(dev, 0x13e, &tmp_report[k]);
-#endif
 			RT_TRACE(COMP_POWER_TRACKING, "TSSI_report_value = %d\n", tmp_report[k]);
 		}
 
@@ -708,10 +681,6 @@
 			RT_TRACE(COMP_POWER_TRACKING, "tx power track is done\n");
 			RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex);
 			RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real);
-#ifdef RTL8190P
-			RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex = %d\n", priv->rfc_txpowertrackingindex);
-			RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex_real = %d\n", priv->rfc_txpowertrackingindex_real);
-#endif
 			RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation_difference = %d\n", priv->cck_present_attentuation_difference);
 			RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation);
 			return;
@@ -720,11 +689,7 @@
 		{
 			if(Avg_TSSI_Meas_from_driver < TSSI_13dBm - E_FOR_TX_POWER_TRACK)
 			{
-				if((priv->rfa_txpowertrackingindex > 0)
-#ifdef RTL8190P
-					&&(priv->rfc_txpowertrackingindex > 0)
-#endif
-				)
+				if (priv->rfa_txpowertrackingindex > 0)
 				{
 					priv->rfa_txpowertrackingindex--;
 					if(priv->rfa_txpowertrackingindex_real > 4)
@@ -732,33 +697,16 @@
 						priv->rfa_txpowertrackingindex_real--;
 						rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
 					}
-#ifdef RTL8190P
-					priv->rfc_txpowertrackingindex--;
-					if(priv->rfc_txpowertrackingindex_real > 4)
-					{
-						priv->rfc_txpowertrackingindex_real--;
-						rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
-					}
-#endif
 				}
 			}
 			else
 			{
-				if((priv->rfa_txpowertrackingindex < 36)
-#ifdef RTL8190P
-					&&(priv->rfc_txpowertrackingindex < 36)
-#endif
-					)
+				if (priv->rfa_txpowertrackingindex < 36)
 				{
 					priv->rfa_txpowertrackingindex++;
 					priv->rfa_txpowertrackingindex_real++;
 					rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
 
-#ifdef RTL8190P
-					priv->rfc_txpowertrackingindex++;
-					priv->rfc_txpowertrackingindex_real++;
-					rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
-#endif
 				}
 			}
 			priv->cck_present_attentuation_difference
@@ -788,10 +736,6 @@
 			}
 		RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex);
 		RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real);
-#ifdef RTL8190P
-		RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex = %d\n", priv->rfc_txpowertrackingindex);
-		RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex_real = %d\n", priv->rfc_txpowertrackingindex_real);
-#endif
 		RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation_difference = %d\n", priv->cck_present_attentuation_difference);
 		RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation);
 
@@ -937,14 +881,10 @@
        struct r8192_priv *priv = container_of(dwork,struct r8192_priv,txpower_tracking_wq);
        struct net_device *dev = priv->ieee80211->dev;
 
-#ifdef RTL8190P
-	dm_TXPowerTrackingCallback_TSSI(dev);
-#else
 	if(priv->bDcut == TRUE)
 		dm_TXPowerTrackingCallback_TSSI(dev);
 	else
 		dm_TXPowerTrackingCallback_ThermalMeter(dev);
-#endif
 }
 
 
@@ -1472,14 +1412,10 @@
 void dm_initialize_txpower_tracking(struct net_device *dev)
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
-#ifdef RTL8190P
-	dm_InitializeTXPowerTracking_TSSI(dev);
-#else
 	if(priv->bDcut == TRUE)
 		dm_InitializeTXPowerTracking_TSSI(dev);
 	else
 		dm_InitializeTXPowerTracking_ThermalMeter(dev);
-#endif
 }// dm_InitializeTXPowerTracking
 
 
@@ -1677,14 +1613,10 @@
 {	// dm_CCKTxPowerAdjust
 
 	struct r8192_priv *priv = ieee80211_priv(dev);
-#ifdef RTL8190P
-	dm_CCKTxPowerAdjust_TSSI(dev, binch14);
-#else
 	if(priv->bDcut == TRUE)
 		dm_CCKTxPowerAdjust_TSSI(dev, binch14);
 	else
 		dm_CCKTxPowerAdjust_ThermalMeter(dev, binch14);
-#endif
 }
 
 
@@ -2194,11 +2126,7 @@
 		{
 			/* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
 			// 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
-			#ifdef RTL8190P
-				write_nic_byte(dev, rOFDM0_RxDetector1, 0x40);
-			#else
-				write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
-			#endif
+			write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
 			/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
 				write_nic_byte(pAdapter, rOFDM0_RxDetector1, 0x40);
 			*/
@@ -2265,11 +2193,7 @@
 		{
 			/* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
 			// 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
-			#ifdef RTL8190P
-				write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
-			#else
-				write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
-			#endif
+			write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
 			/*
 			else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
 				write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
@@ -2342,11 +2266,7 @@
 		// 3.1 Higher PD_TH for OFDM for high power state.
 		if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
 		{
-			#ifdef RTL8190P
-				write_nic_byte(dev, rOFDM0_RxDetector1, 0x41);
-			#else
-				write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
-			#endif
+			write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
 
 			/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
 				write_nic_byte(dev, rOFDM0_RxDetector1, 0x41);
@@ -2370,11 +2290,7 @@
 			// 3.2 Recover PD_TH for OFDM for normal power region.
 			if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
 			{
-				#ifdef RTL8190P
-					write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
-				#else
-					write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
-				#endif
+				write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
 				/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
 					write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
 				*/
@@ -2516,11 +2432,7 @@
 				{
 					/* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
 					// 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
-					#ifdef RTL8190P
-						write_nic_byte(dev, rOFDM0_RxDetector1, 0x40);
-					#else
-						write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
-					#endif
+					write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
 					/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
 						write_nic_byte(dev, rOFDM0_RxDetector1, 0x40);
 					*/
@@ -2535,11 +2447,7 @@
 				{
 					/* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
 					// 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
-					#ifdef RTL8190P
-						write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
-					#else
-						write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
-					#endif
+					write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
 					/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
 						write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
 					*/
@@ -2552,11 +2460,7 @@
 				// Higher PD_TH for OFDM for high power state.
 				if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
 				{
-					#ifdef RTL8190P
-						write_nic_byte(dev, rOFDM0_RxDetector1, 0x41);
-					#else
-						write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
-					#endif
+					write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
 					/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
 						write_nic_byte(dev, rOFDM0_RxDetector1, 0x41);
 					*/
@@ -2823,44 +2727,6 @@
 	}
 }
 
-
-/*-----------------------------------------------------------------------------
- * Function:	dm_check_rfctrl_gpio()
- *
- * Overview:	Copy 8187B template for 9xseries.
- *
- * Input:		NONE
- *
- * Output:		NONE
- *
- * Return:		NONE
- *
- * Revised History:
- *	When		Who		Remark
- *	05/28/2008	amy		Create Version 0 porting from windows code.
- *
- *---------------------------------------------------------------------------*/
-static void dm_check_rfctrl_gpio(struct net_device *dev)
-{
-	//struct r8192_priv *priv = ieee80211_priv(dev);
-
-	// Work around for DTM test, we will not enable HW - radio on/off because r/w
-	// page 1 register before extra bus is enabled causing system failures when resuming
-	// from S4. 20080218, Emily
-
-	// Stop to execute workitem to prevent S3/S4 bug.
-#ifdef RTL8190P
-	return;
-#endif
-#ifdef RTL8192U
-	return;
-#endif
-#ifdef RTL8192E
-		queue_delayed_work(priv->priv_wq,&priv->gpio_change_rf_wq,0);
-#endif
-
-}	/* dm_CheckRfCtrlGPIO */
-
 /*-----------------------------------------------------------------------------
  * Function:	dm_check_pbc_gpio()
  *
@@ -2879,7 +2745,6 @@
  *---------------------------------------------------------------------------*/
 static	void	dm_check_pbc_gpio(struct net_device *dev)
 {
-#ifdef RTL8192U
 	struct r8192_priv *priv = ieee80211_priv(dev);
 	u8 tmp1byte;
 
@@ -2895,83 +2760,9 @@
 		RT_TRACE(COMP_IO, "CheckPbcGPIO - PBC is pressed\n");
 		priv->bpbc_pressed = true;
 	}
-#endif
 
 }
 
-#ifdef RTL8192E
-
-/*-----------------------------------------------------------------------------
- * Function:	dm_GPIOChangeRF
- * Overview:	PCI will not support workitem call back HW radio on-off control.
- *
- * Input:		NONE
- *
- * Output:		NONE
- *
- * Return:		NONE
- *
- * Revised History:
- *	When		Who		Remark
- *	02/21/2008	MHC		Create Version 0.
- *
- *---------------------------------------------------------------------------*/
-extern	void	dm_gpio_change_rf_callback(struct work_struct *work)
-{
-	struct delayed_work *dwork = container_of(work,struct delayed_work,work);
-       struct r8192_priv *priv = container_of(dwork,struct r8192_priv,gpio_change_rf_wq);
-       struct net_device *dev = priv->ieee80211->dev;
-	u8 tmp1byte;
-	RT_RF_POWER_STATE	eRfPowerStateToSet;
-	bool bActuallySet = false;
-
-	do{
-		bActuallySet=false;
-
-		if(!priv->up)
-		{
-			RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF),"dm_gpio_change_rf_callback(): Callback function breaks out!!\n");
-		}
-		else
-		{
-			// 0x108 GPIO input register is read only
-			//set 0x108 B1= 1: RF-ON; 0: RF-OFF.
-			read_nic_byte(dev, GPI, &tmp1byte);
-
-			eRfPowerStateToSet = (tmp1byte&BIT1) ?  eRfOn : eRfOff;
-
-			if((priv->bHwRadioOff == true) && (eRfPowerStateToSet == eRfOn))
-			{
-				RT_TRACE(COMP_RF, "gpiochangeRF  - HW Radio ON\n");
-
-				priv->bHwRadioOff = false;
-				bActuallySet = true;
-			}
-			else if ((priv->bHwRadioOff == false) && (eRfPowerStateToSet == eRfOff))
-			{
-				RT_TRACE(COMP_RF, "gpiochangeRF  - HW Radio OFF\n");
-				priv->bHwRadioOff = true;
-				bActuallySet = true;
-			}
-
-			if(bActuallySet)
-			{
-				#ifdef TO_DO
-				MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW);
-				//DrvIFIndicateCurrentPhyStatus(pAdapter);
-				#endif
-			}
-			else
-			{
-				msleep(2000);
-			}
-
-		}
-	}while(TRUE)
-
-}	/* dm_GPIOChangeRF */
-
-#endif
 /*-----------------------------------------------------------------------------
  * Function:	DM_RFPathCheckWorkItemCallBack()
  *
@@ -3329,11 +3120,7 @@
 	priv->ieee80211->fsync_time_interval = 500;
 	priv->ieee80211->fsync_rate_bitmap = 0x0f000800;
 	priv->ieee80211->fsync_rssi_threshold = 30;
-#ifdef RTL8190P
-	priv->ieee80211->bfsync_enable = true;
-#else
 	priv->ieee80211->bfsync_enable = false;
-#endif
 	priv->ieee80211->fsync_multiple_timeinterval = 3;
 	priv->ieee80211->fsync_firstdiff_ratethreshold= 100;
 	priv->ieee80211->fsync_seconddiff_ratethreshold= 200;
@@ -3416,20 +3203,12 @@
 			priv->bswitch_fsync = !priv->bswitch_fsync;
 			if(priv->bswitch_fsync)
 			{
-			#ifdef RTL8190P
-				write_nic_byte(dev, 0xC36, 0x00);
-			#else
 				write_nic_byte(dev,0xC36, 0x1c);
-			#endif
 				write_nic_byte(dev, 0xC3e, 0x90);
 			}
 			else
 			{
-			#ifdef RTL8190P
-				write_nic_byte(dev, 0xC36, 0x40);
-			#else
 				write_nic_byte(dev, 0xC36, 0x5c);
-			#endif
 				write_nic_byte(dev, 0xC3e, 0x96);
 			}
 		}
@@ -3438,11 +3217,7 @@
 			if(priv->bswitch_fsync)
 			{
 				priv->bswitch_fsync  = false;
-			#ifdef RTL8190P
-				write_nic_byte(dev, 0xC36, 0x40);
-			#else
 				write_nic_byte(dev, 0xC36, 0x5c);
-			#endif
 				write_nic_byte(dev, 0xC3e, 0x96);
 			}
 		}
@@ -3465,19 +3240,11 @@
 		if(priv->bswitch_fsync)
 		{
 			priv->bswitch_fsync  = false;
-		#ifdef RTL8190P
-			write_nic_byte(dev, 0xC36, 0x40);
-		#else
 			write_nic_byte(dev, 0xC36, 0x5c);
-		#endif
 			write_nic_byte(dev, 0xC3e, 0x96);
 		}
 		priv->ContinueDiffCount = 0;
-	#ifdef RTL8190P
-		write_nic_dword(dev, rOFDM0_RxDetector2, 0x164052cd);
-	#else
 		write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
-	#endif
 	}
 	RT_TRACE(COMP_HALDM, "ContinueDiffCount %d\n", priv->ContinueDiffCount);
 	RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync);
@@ -3502,19 +3269,13 @@
 	{
 		priv->bswitch_fsync  = false;
 
-		#ifdef RTL8190P
-			write_nic_byte(dev, 0xC36, 0x40);
-		#else
-			write_nic_byte(dev, 0xC36, 0x5c);
-		#endif
+		write_nic_byte(dev, 0xC36, 0x5c);
 
 		write_nic_byte(dev, 0xC3e, 0x96);
 	}
 
 	priv->ContinueDiffCount = 0;
-#ifndef RTL8190P
 	write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
-#endif
 
 }
 
@@ -3553,9 +3314,7 @@
 	priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval);
 	add_timer(&priv->fsync_timer);
 
-#ifndef RTL8190P
 	write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cd);
-#endif
 
 }
 
@@ -3624,11 +3383,7 @@
 		{
 			if(reg_c38_State != RegC38_Fsync_AP_BCM)
 			{	//For broadcom AP we write different default value
-				#ifdef RTL8190P
-					write_nic_byte(dev, rOFDM0_RxDetector3, 0x15);
-				#else
-					write_nic_byte(dev, rOFDM0_RxDetector3, 0x95);
-				#endif
+				write_nic_byte(dev, rOFDM0_RxDetector3, 0x95);
 
 				reg_c38_State = RegC38_Fsync_AP_BCM;
 			}
@@ -3659,11 +3414,7 @@
 				{
 					if(reg_c38_State != RegC38_NonFsync_Other_AP)
 					{
-						#ifdef RTL8190P
-							write_nic_byte(dev, rOFDM0_RxDetector3, 0x10);
-						#else
-							write_nic_byte(dev, rOFDM0_RxDetector3, 0x90);
-						#endif
+						write_nic_byte(dev, rOFDM0_RxDetector3, 0x90);
 
 						reg_c38_State = RegC38_NonFsync_Other_AP;
 					}
@@ -3845,10 +3596,8 @@
 		SetTxPowerLevel8190(Adapter,pHalData->CurrentChannel);
 #endif
 
-#ifdef RTL8192U
 		rtl8192_phy_setTxPower(dev,priv->ieee80211->current_network.channel);
 		//pHalData->bStartTxCtrlByTPCNFR = FALSE;    //Clear th flag of Set TX Power from Sitesurvey
-#endif
 	}
 	priv->bLastDTPFlag_High = priv->bDynamicTxHighPower;
 	priv->bLastDTPFlag_Low = priv->bDynamicTxLowPower;
@@ -3885,9 +3634,6 @@
 	tx_cmd.Op		= TXCMD_SET_RX_RSSI;
 	tx_cmd.Length	= 4;
 	tx_cmd.Value		= priv->undecorated_smoothed_pwdb;
-
-	cmpk_message_handle_tx(dev, (u8 *)&tx_cmd,
-								DESC_PACKET_TYPE_INIT, sizeof(DCMD_TXCMD_T));
 }
 
 /*---------------------------Define function prototype------------------------*/
diff --git a/drivers/staging/rtl8192u/r8192U_wx.c b/drivers/staging/rtl8192u/r8192U_wx.c
index 61f6620..c70af01 100644
--- a/drivers/staging/rtl8192u/r8192U_wx.c
+++ b/drivers/staging/rtl8192u/r8192U_wx.c
@@ -127,156 +127,6 @@
 	return ieee80211_wx_get_power(priv->ieee80211,info,wrqu,extra);
 }
 
-#ifdef JOHN_IOCTL
-u16 read_rtl8225(struct net_device *dev, u8 addr);
-void write_rtl8225(struct net_device *dev, u8 adr, u16 data);
-u32 john_read_rtl8225(struct net_device *dev, u8 adr);
-void _write_rtl8225(struct net_device *dev, u8 adr, u16 data);
-
-static int r8192_wx_read_regs(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	u8 addr;
-	u16 data1;
-
-	down(&priv->wx_sem);
-
-
-	get_user(addr,(u8 *)wrqu->data.pointer);
-	data1 = read_rtl8225(dev, addr);
-	wrqu->data.length = data1;
-
-	up(&priv->wx_sem);
-	return 0;
-
-}
-
-static int r8192_wx_write_regs(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	u8 addr;
-
-	down(&priv->wx_sem);
-
-	get_user(addr, (u8 *)wrqu->data.pointer);
-	write_rtl8225(dev, addr, wrqu->data.length);
-
-	up(&priv->wx_sem);
-	return 0;
-
-}
-
-void rtl8187_write_phy(struct net_device *dev, u8 adr, u32 data);
-u8 rtl8187_read_phy(struct net_device *dev,u8 adr, u32 data);
-
-static int r8192_wx_read_bb(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	u8 databb;
-
-	down(&priv->wx_sem);
-
-	databb = rtl8187_read_phy(dev, (u8)wrqu->data.length, 0x00000000);
-	wrqu->data.length = databb;
-
-	up(&priv->wx_sem);
-	return 0;
-}
-
-void rtl8187_write_phy(struct net_device *dev, u8 adr, u32 data);
-static int r8192_wx_write_bb(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	u8 databb;
-
-	down(&priv->wx_sem);
-
-	get_user(databb, (u8 *)wrqu->data.pointer);
-	rtl8187_write_phy(dev, wrqu->data.length, databb);
-
-	up(&priv->wx_sem);
-	return 0;
-
-}
-
-
-static int r8192_wx_write_nicb(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	u32 addr;
-
-	down(&priv->wx_sem);
-
-	get_user(addr, (u32 *)wrqu->data.pointer);
-	write_nic_byte(dev, addr, wrqu->data.length);
-
-	up(&priv->wx_sem);
-	return 0;
-
-}
-static int r8192_wx_read_nicb(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	u32 addr;
-	u16 data1;
-
-	down(&priv->wx_sem);
-
-	get_user(addr,(u32 *)wrqu->data.pointer);
-	read_nic_byte(dev, addr, &data1);
-	wrqu->data.length = data1;
-
-	up(&priv->wx_sem);
-	return 0;
-}
-
-static int r8192_wx_get_ap_status(struct net_device *dev,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	struct ieee80211_device *ieee = priv->ieee80211;
-	struct ieee80211_network *target;
-	int name_len;
-
-	down(&priv->wx_sem);
-
-	//count the length of input ssid
-	for(name_len=0 ; ((char *)wrqu->data.pointer)[name_len]!='\0' ; name_len++);
-
-	//search for the corresponding info which is received
-	list_for_each_entry(target, &ieee->network_list, list) {
-		if ( (target->ssid_len == name_len) &&
-		     (strncmp(target->ssid, (char *)wrqu->data.pointer, name_len)==0)){
-			if(target->wpa_ie_len>0 || target->rsn_ie_len>0 )
-				//set flags=1 to indicate this ap is WPA
-				wrqu->data.flags = 1;
-			else wrqu->data.flags = 0;
-
-
-		break;
-		}
-	}
-
-	up(&priv->wx_sem);
-	return 0;
-}
-
-
-
-#endif
 static int r8192_wx_force_reset(struct net_device *dev,
 		struct iw_request_info *info,
 		union iwreq_data *wrqu, char *extra)
@@ -1106,46 +956,7 @@
 	{
 		SIOCIWFIRSTPRIV + 0x2,
 		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
-	}
-#ifdef JOHN_IOCTL
-	,
-	{
-		SIOCIWFIRSTPRIV + 0x3,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readRF"
-	}
-	,
-	{
-		SIOCIWFIRSTPRIV + 0x4,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeRF"
-	}
-	,
-	{
-		SIOCIWFIRSTPRIV + 0x5,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readBB"
-	}
-	,
-	{
-		SIOCIWFIRSTPRIV + 0x6,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeBB"
-	}
-	,
-	{
-		SIOCIWFIRSTPRIV + 0x7,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readnicb"
-	}
-	,
-	{
-		SIOCIWFIRSTPRIV + 0x8,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writenicb"
-	}
-	,
-	{
-		SIOCIWFIRSTPRIV + 0x9,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
-	}
-
-#endif
-	,
+	},
 	{
 		SIOCIWFIRSTPRIV + 0x3,
 		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
@@ -1163,15 +974,6 @@
 //	r8192_wx_set_monitor_type,
 	r8192_wx_set_scan_type,
 	r8192_wx_set_rawtx,
-#ifdef JOHN_IOCTL
-	r8192_wx_read_regs,
-	r8192_wx_write_regs,
-	r8192_wx_read_bb,
-	r8192_wx_write_bb,
-	r8192_wx_read_nicb,
-	r8192_wx_write_nicb,
-	r8192_wx_get_ap_status,
-#endif
 	//r8192_wx_null,
 	r8192_wx_force_reset,
 };
diff --git a/drivers/staging/rtl8192u/r819xU_HTType.h b/drivers/staging/rtl8192u/r819xU_HTType.h
index 19a7bdd..2cbb8e6 100644
--- a/drivers/staging/rtl8192u/r819xU_HTType.h
+++ b/drivers/staging/rtl8192u/r819xU_HTType.h
@@ -2,41 +2,36 @@
 #define _R819XU_HTTYPE_H_
 
 
-//------------------------------------------------------------
-// The HT Capability element is present in beacons, association request,
-//	reassociation request and probe response frames
-//------------------------------------------------------------
+/*----------------------------------------------------------------------
+ * The HT Capability element is present in beacons, association request,
+ * reassociation request and probe response frames
+ *----------------------------------------------------------------------*/
 
-//
-// Operation mode value
-//
+/* Operation mode value */
 #define HT_OPMODE_NO_PROTECT		0
 #define HT_OPMODE_OPTIONAL		1
-#define HT_OPMODE_40MHZ_PROTECT	2
+#define HT_OPMODE_40MHZ_PROTECT		2
 #define HT_OPMODE_MIXED			3
 
-//
-// MIMO Power Save Settings
-//
-#define MIMO_PS_STATIC				0
+/* MIMO Power Save Settings */
+#define MIMO_PS_STATIC			0
 #define MIMO_PS_DYNAMIC			1
 #define MIMO_PS_NOLIMIT			3
 
 
-//
-//	There should be 128 bits to cover all of the MCS rates. However, since
-//	8190 does not support too much rates, one integer is quite enough.
-//
+/* There should be 128 bits to cover all of the MCS rates. However, since
+ * 8190 does not support too much rates, one integer is quite enough. */
 
-#define sHTCLng	4
+#define sHTCLng				4
 
 
-#define HT_SUPPORTED_MCS_1SS_BITMAP					0x000000ff
-#define HT_SUPPORTED_MCS_2SS_BITMAP					0x0000ff00
-#define HT_SUPPORTED_MCS_1SS_2SS_BITMAP			HT_MCS_1SS_BITMAP|HT_MCS_1SS_2SS_BITMAP
+#define HT_SUPPORTED_MCS_1SS_BITMAP	0x000000ff
+#define HT_SUPPORTED_MCS_2SS_BITMAP	0x0000ff00
+#define HT_SUPPORTED_MCS_1SS_2SS_BITMAP	\
+		(HT_MCS_1SS_BITMAP | HT_MCS_1SS_2SS_BITMAP)
 
 
-typedef enum _HT_MCS_RATE{
+typedef enum _HT_MCS_RATE {
 	HT_MCS0   = 0x00000001,
 	HT_MCS1   = 0x00000002,
 	HT_MCS2   = 0x00000004,
@@ -47,71 +42,67 @@
 	HT_MCS7   = 0x00000080,
 	HT_MCS8   = 0x00000100,
 	HT_MCS9   = 0x00000200,
-	HT_MCS10 = 0x00000400,
-	HT_MCS11 = 0x00000800,
-	HT_MCS12 = 0x00001000,
-	HT_MCS13 = 0x00002000,
-	HT_MCS14 = 0x00004000,
-	HT_MCS15 = 0x00008000,
-	// Do not define MCS32 here although 8190 support MCS32
-}HT_MCS_RATE,*PHT_MCS_RATE;
+	HT_MCS10  = 0x00000400,
+	HT_MCS11  = 0x00000800,
+	HT_MCS12  = 0x00001000,
+	HT_MCS13  = 0x00002000,
+	HT_MCS14  = 0x00004000,
+	HT_MCS15  = 0x00008000,
+	/* Do not define MCS32 here although 8190 support MCS32 */
+} HT_MCS_RATE, *PHT_MCS_RATE;
 
-//
-// Represent Channel Width in HT Capabilities
-//
-typedef enum _HT_CHANNEL_WIDTH{
-	HT_CHANNEL_WIDTH_20 = 0,
+/* Represent Channel Width in HT Capabilities */
+typedef enum _HT_CHANNEL_WIDTH {
+	HT_CHANNEL_WIDTH_20    = 0,
 	HT_CHANNEL_WIDTH_20_40 = 1,
-}HT_CHANNEL_WIDTH, *PHT_CHANNEL_WIDTH;
+} HT_CHANNEL_WIDTH, *PHT_CHANNEL_WIDTH;
 
-//
-// Represent Extension Channel Offset in HT Capabilities
-// This is available only in 40Mhz mode.
-//
-typedef enum _HT_EXTCHNL_OFFSET{
+/* Represent Extension Channel Offset in HT Capabilities
+ * This is available only in 40Mhz mode. */
+typedef enum _HT_EXTCHNL_OFFSET {
 	HT_EXTCHNL_OFFSET_NO_EXT = 0,
-	HT_EXTCHNL_OFFSET_UPPER = 1,
+	HT_EXTCHNL_OFFSET_UPPER  = 1,
 	HT_EXTCHNL_OFFSET_NO_DEF = 2,
-	HT_EXTCHNL_OFFSET_LOWER = 3,
-}HT_EXTCHNL_OFFSET, *PHT_EXTCHNL_OFFSET;
+	HT_EXTCHNL_OFFSET_LOWER  = 3,
+} HT_EXTCHNL_OFFSET, *PHT_EXTCHNL_OFFSET;
 
-typedef enum _CHNLOP{
-	CHNLOP_NONE = 0, // No Action now
-	CHNLOP_SCAN = 1, // Scan in progress
-	CHNLOP_SWBW = 2, // Bandwidth switching in progress
-	CHNLOP_SWCHNL = 3, // Software Channel switching in progress
+typedef enum _CHNLOP {
+	CHNLOP_NONE   = 0,	/* No Action now */
+	CHNLOP_SCAN   = 1,	/* Scan in progress */
+	CHNLOP_SWBW   = 2,	/* Bandwidth switching in progress */
+	CHNLOP_SWCHNL = 3,	/* Software Channel switching in progress */
 } CHNLOP, *PCHNLOP;
 
-// Determine if the Channel Operation is in progress
+/* Determine if the Channel Operation is in progress */
 #define CHHLOP_IN_PROGRESS(_pHTInfo)	\
-		((_pHTInfo)->ChnlOp > CHNLOP_NONE) ? TRUE : FALSE
+		(((_pHTInfo)->ChnlOp > CHNLOP_NONE) ? TRUE : FALSE)
 
 
-typedef enum _HT_ACTION{
+typedef enum _HT_ACTION {
 	ACT_RECOMMAND_WIDTH		= 0,
 	ACT_MIMO_PWR_SAVE		= 1,
-	ACT_PSMP					= 2,
+	ACT_PSMP			= 2,
 	ACT_SET_PCO_PHASE		= 3,
-	ACT_MIMO_CHL_MEASURE	= 4,
-	ACT_RECIPROCITY_CORRECT	= 5,
+	ACT_MIMO_CHL_MEASURE		= 4,
+	ACT_RECIPROCITY_CORRECT		= 5,
 	ACT_MIMO_CSI_MATRICS		= 6,
-	ACT_MIMO_NOCOMPR_STEER	= 7,
+	ACT_MIMO_NOCOMPR_STEER		= 7,
 	ACT_MIMO_COMPR_STEER		= 8,
 	ACT_ANTENNA_SELECT		= 9,
 } HT_ACTION, *PHT_ACTION;
 
 
-/* 2007/06/07 MH Define sub-carrier mode for 40MHZ. */
-typedef enum _HT_Bandwidth_40MHZ_Sub_Carrier{
+/* Define sub-carrier mode for 40MHZ. */
+typedef enum _HT_Bandwidth_40MHZ_Sub_Carrier {
 	SC_MODE_DUPLICATE = 0,
-	SC_MODE_LOWER = 1,
-	SC_MODE_UPPER = 2,
+	SC_MODE_LOWER     = 1,
+	SC_MODE_UPPER     = 2,
 	SC_MODE_FULL40MHZ = 3,
-}HT_BW40_SC_E;
+} HT_BW40_SC_E;
 
-typedef	struct _HT_CAPABILITY_ELE{
+typedef	struct _HT_CAPABILITY_ELE {
 
-	//HT capability info
+	/* HT capability info */
 	u8	AdvCoding:1;
 	u8	ChlWidth:1;
 	u8	MimoPwrSave:2;
@@ -127,32 +118,32 @@
 	u8	Rsvd1:1;
 	u8	LSigTxopProtect:1;
 
-	//MAC HT parameters info
+	/* MAC HT parameters info */
 	u8	MaxRxAMPDUFactor:2;
 	u8	MPDUDensity:3;
 	u8	Rsvd2:3;
 
-	//Supported MCS set
+	/* Supported MCS set */
 	u8	MCS[16];
 
 
-	//Extended HT Capability Info
+	/* Extended HT Capability Info */
 	u16	ExtHTCapInfo;
 
-	//TXBF Capabilities
+	/* TXBF Capabilities */
 	u8	TxBFCap[4];
 
-	//Antenna Selection Capabilities
+	/* Antenna Selection Capabilities */
 	u8	ASCap;
 
-}__attribute__((packed)) HT_CAPABILITY_ELE, *PHT_CAPABILITY_ELE;
+} __packed HT_CAPABILITY_ELE, *PHT_CAPABILITY_ELE;
 
-//------------------------------------------------------------
-// The HT Information element is present in beacons
-// Only AP is required to include this element
-//------------------------------------------------------------
+/*------------------------------------------------------------
+ * The HT Information element is present in beacons
+ * Only AP is required to include this element
+ *------------------------------------------------------------*/
 
-typedef struct _HT_INFORMATION_ELE{
+typedef struct _HT_INFORMATION_ELE {
 	u8	ControlChl;
 
 	u8	ExtChlOffset:2;
@@ -177,146 +168,146 @@
 	u8	Rsvd4:4;
 
 	u8	BasicMSC[16];
-}__attribute__((packed)) HT_INFORMATION_ELE, *PHT_INFORMATION_ELE;
+} __packed HT_INFORMATION_ELE, *PHT_INFORMATION_ELE;
 
-//
-// MIMO Power Save control field.
-// This is appear in MIMO Power Save Action Frame
-//
-typedef struct _MIMOPS_CTRL{
+/* MIMO Power Save control field.
+ * This is appear in MIMO Power Save Action Frame */
+typedef struct _MIMOPS_CTRL {
 	u8	MimoPsEnable:1;
 	u8	MimoPsMode:1;
 	u8	Reserved:6;
 } MIMOPS_CTRL, *PMIMOPS_CTRL;
 
-typedef enum _HT_SPEC_VER{
+typedef enum _HT_SPEC_VER {
 	HT_SPEC_VER_IEEE = 0,
 	HT_SPEC_VER_EWC = 1,
-}HT_SPEC_VER, *PHT_SPEC_VER;
+} HT_SPEC_VER, *PHT_SPEC_VER;
 
-typedef enum _HT_AGGRE_MODE_E{
+typedef enum _HT_AGGRE_MODE_E {
 	HT_AGG_AUTO = 0,
 	HT_AGG_FORCE_ENABLE = 1,
 	HT_AGG_FORCE_DISABLE = 2,
-}HT_AGGRE_MODE_E, *PHT_AGGRE_MODE_E;
+} HT_AGGRE_MODE_E, *PHT_AGGRE_MODE_E;
 
-//------------------------------------------------------------
-//  The Data structure is used to keep HT related variables when card is
-//  configured as non-AP STA mode.  **Note**  Current_xxx should be set
-//	to default value in HTInitializeHTInfo()
-//------------------------------------------------------------
+/*----------------------------------------------------------------------------
+ *  The Data structure is used to keep HT related variables when card is
+ *  configured as non-AP STA mode.
+ *  **Note** Current_xxx should be set to default value in HTInitializeHTInfo()
+ *----------------------------------------------------------------------------*/
 
-typedef struct _RT_HIGH_THROUGHPUT{
-//	DECLARE_RT_OBJECT(_RT_HIGH_THROUGHPUT);
-	u8				bEnableHT;
-	u8				bCurrentHTSupport;
+typedef struct _RT_HIGH_THROUGHPUT {
+	u8			bEnableHT;
+	u8			bCurrentHTSupport;
+	/* Tx 40MHz channel capability */
+	u8			bRegBW40MHz;
+	u8			bCurBW40MHz;
+	/* Tx Short GI for 40Mhz */
+	u8			bRegShortGI40MHz;
+	u8			bCurShortGI40MHz;
+	/* Tx Short GI for 20MHz */
+	u8			bRegShortGI20MHz;
+	u8			bCurShortGI20MHz;
+	/* Tx CCK rate capability */
+	u8			bRegSuppCCK;
+	u8			bCurSuppCCK;
 
-	u8				bRegBW40MHz;				// Tx 40MHz channel capability
-	u8				bCurBW40MHz;				// Tx 40MHz channel capability
-
-	u8				bRegShortGI40MHz;			// Tx Short GI for 40Mhz
-	u8				bCurShortGI40MHz;			// Tx Short GI for 40MHz
-
-	u8				bRegShortGI20MHz;			// Tx Short GI for 20MHz
-	u8				bCurShortGI20MHz;			// Tx Short GI for 20MHz
-
-	u8				bRegSuppCCK;				// Tx CCK rate capability
-	u8				bCurSuppCCK;				// Tx CCK rate capability
-
-	// 802.11n spec version for "peer"
-	HT_SPEC_VER			ePeerHTSpecVer;
+	/* 802.11n spec version for "peer" */
+	HT_SPEC_VER		ePeerHTSpecVer;
 
 
-	// HT related information for "Self"
-	HT_CAPABILITY_ELE	SelfHTCap;					// This is HT cap element sent to peer STA, which also indicate HT Rx capabilities.
-	HT_INFORMATION_ELE	SelfHTInfo;					// This is HT info element sent to peer STA, which also indicate HT Rx capabilities.
+	/* HT related information for "Self" */
+	/* This is HT cap element sent to peer STA, which also indicate
+	 * HT Rx capabilities. */
+	HT_CAPABILITY_ELE	SelfHTCap;
+	HT_INFORMATION_ELE	SelfHTInfo;
 
-	// HT related information for "Peer"
-	u8				PeerHTCapBuf[32];
-	u8				PeerHTInfoBuf[32];
+	/* HT related information for "Peer" */
+	u8			PeerHTCapBuf[32];
+	u8			PeerHTInfoBuf[32];
 
 
-	// A-MSDU related
-	u8				bAMSDU_Support;			// This indicates Tx A-MSDU capability
-	u16				nAMSDU_MaxSize;			// This indicates Tx A-MSDU capability
-	u8				bCurrent_AMSDU_Support;	// This indicates Tx A-MSDU capability
-	u16				nCurrent_AMSDU_MaxSize;	// This indicates Tx A-MSDU capability
+	/* A-MSDU related */
+	/* This indicates Tx A-MSDU capability */
+	u8			bAMSDU_Support;
+	u16			nAMSDU_MaxSize;
+	u8			bCurrent_AMSDU_Support;
+	u16			nCurrent_AMSDU_MaxSize;
 
 
-	// AMPDU  related <2006.08.10 Emily>
-	u8				bAMPDUEnable;				// This indicate Tx A-MPDU capability
-	u8				bCurrentAMPDUEnable;		// This indicate Tx A-MPDU capability
-	u8				AMPDU_Factor;				// This indicate Tx A-MPDU capability
-	u8				CurrentAMPDUFactor;		// This indicate Tx A-MPDU capability
-	u8				MPDU_Density;				// This indicate Tx A-MPDU capability
-	u8				CurrentMPDUDensity;			// This indicate Tx A-MPDU capability
+	/* A-MPDU related */
+	/* This indicate Tx A-MPDU capability */
+	u8			bAMPDUEnable;
+	u8			bCurrentAMPDUEnable;
+	u8			AMPDU_Factor;
+	u8			CurrentAMPDUFactor;
+	u8			MPDU_Density;
+	u8			CurrentMPDUDensity;
 
-	// Forced A-MPDU enable
-	HT_AGGRE_MODE_E	ForcedAMPDUMode;
-	u8				ForcedAMPDUFactor;
-	u8				ForcedMPDUDensity;
+	/* Forced A-MPDU enable */
+	HT_AGGRE_MODE_E		ForcedAMPDUMode;
+	u8			ForcedAMPDUFactor;
+	u8			ForcedMPDUDensity;
 
-	// Forced A-MSDU enable
-	HT_AGGRE_MODE_E	ForcedAMSDUMode;
-	u16				ForcedAMSDUMaxSize;
+	/* Forced A-MSDU enable */
+	HT_AGGRE_MODE_E		ForcedAMSDUMode;
+	u16			ForcedAMSDUMaxSize;
 
-	u8				bForcedShortGI;
+	u8			bForcedShortGI;
 
-	u8				CurrentOpMode;
+	u8			CurrentOpMode;
 
-	// MIMO PS related
-	u8				SelfMimoPs;
-	u8				PeerMimoPs;
+	/* MIMO PS related */
+	u8			SelfMimoPs;
+	u8			PeerMimoPs;
 
-	// 40MHz Channel Offset settings.
+	/* 40MHz Channel Offset settings. */
 	HT_EXTCHNL_OFFSET	CurSTAExtChnlOffset;
-	u8				bCurTxBW40MHz;	// If we use 40 MHz to Tx
-	u8				PeerBandwidth;
+	u8			bCurTxBW40MHz;	/* If we use 40 MHz to Tx */
+	u8			PeerBandwidth;
 
-	// For Bandwidth Switching
-	u8				bSwBwInProgress;
-	CHNLOP				ChnlOp; // software switching channel in progress. By Bruce, 2008-02-15.
-	u8				SwBwStep;
-	//RT_TIMER			SwBwTimer;
-	struct timer_list		SwBwTimer;
+	/* For Bandwidth Switching */
+	u8			bSwBwInProgress;
+	CHNLOP			ChnlOp; /* sw switching channel in progress. */
+	u8			SwBwStep;
+	struct timer_list	SwBwTimer;
 
-	// For Realtek proprietary A-MPDU factor for aggregation
-	u8				bRegRT2RTAggregation;
-	u8				bCurrentRT2RTAggregation;
-	u8				bCurrentRT2RTLongSlotTime;
-	u8				szRT2RTAggBuffer[10];
+	/* For Realtek proprietary A-MPDU factor for aggregation */
+	u8			bRegRT2RTAggregation;
+	u8			bCurrentRT2RTAggregation;
+	u8			bCurrentRT2RTLongSlotTime;
+	u8			szRT2RTAggBuffer[10];
 
-	// Rx Reorder control
-	u8				bRegRxReorderEnable;
-	u8				bCurRxReorderEnable;
-	u8				RxReorderWinSize;
-	u8				RxReorderPendingTime;
-	u16				RxReorderDropCounter;
+	/* Rx Reorder control */
+	u8			bRegRxReorderEnable;
+	u8			bCurRxReorderEnable;
+	u8			RxReorderWinSize;
+	u8			RxReorderPendingTime;
+	u16			RxReorderDropCounter;
 
 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
-	u8				UsbTxAggrNum;
+	u8			UsbTxAggrNum;
 #endif
 #ifdef USB_RX_AGGREGATION_SUPPORT
-	u8				UsbRxFwAggrEn;
-	u8				UsbRxFwAggrPageNum;
-	u8				UsbRxFwAggrPacketNum;
-	u8				UsbRxFwAggrTimeout;
+	u8			UsbRxFwAggrEn;
+	u8			UsbRxFwAggrPageNum;
+	u8			UsbRxFwAggrPacketNum;
+	u8			UsbRxFwAggrTimeout;
 #endif
 
-	// Add for Broadcom(Linksys) IOT. Joseph
-	u8				bIsPeerBcm;
+	/* Add for Broadcom(Linksys) IOT. */
+	u8			bIsPeerBcm;
 
-	// For IOT issue.
-	u32					IOTAction;
-}RT_HIGH_THROUGHPUT, *PRT_HIGH_THROUGHPUT;
+	/* For IOT issue. */
+	u32			IOTAction;
+} RT_HIGH_THROUGHPUT, *PRT_HIGH_THROUGHPUT;
 
 
-//------------------------------------------------------------
-// The Data structure is used to keep HT related variable for "each Sta"
-// when card is configured as "AP mode"
-//------------------------------------------------------------
+/*----------------------------------------------------------------------
+ * The Data structure is used to keep HT related variable for "each Sta"
+ * when card is configured as "AP mode"
+ *----------------------------------------------------------------------*/
 
-typedef struct _RT_HTINFO_STA_ENTRY{
+typedef struct _RT_HTINFO_STA_ENTRY {
 	u8			bEnableHT;
 
 	u8			bSupportCck;
@@ -335,56 +326,54 @@
 	u8			McsRateSet[16];
 
 
-}RT_HTINFO_STA_ENTRY, *PRT_HTINFO_STA_ENTRY;
+} RT_HTINFO_STA_ENTRY, *PRT_HTINFO_STA_ENTRY;
 
 
 
 
 
-//------------------------------------------------------------
-// The Data structure is used to keep HT related variable for "each AP"
-// when card is configured as "STA mode"
-//------------------------------------------------------------
+/*---------------------------------------------------------------------
+ * The Data structure is used to keep HT related variable for "each AP"
+ * when card is configured as "STA mode"
+ *---------------------------------------------------------------------*/
 
-typedef struct _BSS_HT{
+typedef struct _BSS_HT {
 
 	u8				bdSupportHT;
 
-	// HT related elements
-	u8					bdHTCapBuf[32];
-	u16					bdHTCapLen;
-	u8					bdHTInfoBuf[32];
-	u16					bdHTInfoLen;
+	/* HT related elements */
+	u8				bdHTCapBuf[32];
+	u16				bdHTCapLen;
+	u8				bdHTInfoBuf[32];
+	u16				bdHTInfoLen;
 
-	HT_SPEC_VER				bdHTSpecVer;
-	//HT_CAPABILITY_ELE			bdHTCapEle;
-	//HT_INFORMATION_ELE		bdHTInfoEle;
+	HT_SPEC_VER			bdHTSpecVer;
 
-	u8					bdRT2RTAggregation;
-	u8					bdRT2RTLongSlotTime;
-}BSS_HT, *PBSS_HT;
+	u8				bdRT2RTAggregation;
+	u8				bdRT2RTLongSlotTime;
+} BSS_HT, *PBSS_HT;
 
-typedef struct _MIMO_RSSI{
+typedef struct _MIMO_RSSI {
 	u32	EnableAntenna;
 	u32	AntennaA;
 	u32	AntennaB;
 	u32	AntennaC;
 	u32	AntennaD;
 	u32	Average;
-}MIMO_RSSI, *PMIMO_RSSI;
+} MIMO_RSSI, *PMIMO_RSSI;
 
-typedef struct _MIMO_EVM{
+typedef struct _MIMO_EVM {
 	u32	EVM1;
-	u32    EVM2;
-}MIMO_EVM, *PMIMO_EVM;
+	u32	EVM2;
+} MIMO_EVM, *PMIMO_EVM;
 
-typedef struct _FALSE_ALARM_STATISTICS{
+typedef struct _FALSE_ALARM_STATISTICS {
 	u32	Cnt_Parity_Fail;
-	u32    Cnt_Rate_Illegal;
+	u32	Cnt_Rate_Illegal;
 	u32	Cnt_Crc8_fail;
 	u32	Cnt_all;
-}FALSE_ALARM_STATISTICS, *PFALSE_ALARM_STATISTICS;
+} FALSE_ALARM_STATISTICS, *PFALSE_ALARM_STATISTICS;
 
 
 
-#endif //__INC_HTTYPE_H
+#endif
diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.c b/drivers/staging/rtl8192u/r819xU_cmdpkt.c
index 5614401..7bdcbd3 100644
--- a/drivers/staging/rtl8192u/r819xU_cmdpkt.c
+++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.c
@@ -62,105 +62,6 @@
 }
 
 /*-----------------------------------------------------------------------------
- * Function:	cmpk_message_handle_tx()
- *
- * Overview:	Driver internal module can call the API to send message to
- *		firmware side. For example, you can send a debug command packet.
- *		Or you can send a request for FW to modify RLX4181 LBUS HW bank.
- *		Otherwise, you can change MAC/PHT/RF register by firmware at
- *		run time. We do not support message more than one segment now.
- *
- * Input:	NONE
- *
- * Output:	NONE
- *
- * Return:	NONE
- *
- * Revised History:
- *	When		Who		Remark
- *	05/06/2008	amy		porting from windows code.
- *
- *---------------------------------------------------------------------------*/
-extern rt_status cmpk_message_handle_tx(struct net_device *dev,
-					u8 *codevirtualaddress,
-					u32 packettype, u32 buffer_len)
-{
-
-	bool	    rt_status = true;
-#ifdef RTL8192U
-	return rt_status;
-#else
-	struct r8192_priv   *priv = ieee80211_priv(dev);
-	u16		    frag_threshold;
-	u16		    frag_length, frag_offset = 0;
-
-	rt_firmware	    *pfirmware = priv->pFirmware;
-	struct sk_buff	    *skb;
-	unsigned char	    *seg_ptr;
-	cb_desc		    *tcb_desc;
-	u8                  bLastIniPkt;
-
-	firmware_init_param(dev);
-	/* Fragmentation might be required */
-	frag_threshold = pfirmware->cmdpacket_frag_thresold;
-	do {
-		if ((buffer_len - frag_offset) > frag_threshold) {
-			frag_length = frag_threshold;
-			bLastIniPkt = 0;
-
-		} else {
-			frag_length = buffer_len - frag_offset;
-			bLastIniPkt = 1;
-
-		}
-
-		/* Allocate skb buffer to contain firmware info and tx
-		   descriptor info add 4 to avoid packet appending overflow. */
-#ifdef RTL8192U
-		skb  = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4);
-#else
-		skb  = dev_alloc_skb(frag_length + 4);
-#endif
-		memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
-		tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
-		tcb_desc->queue_index = TXCMD_QUEUE;
-		tcb_desc->bCmdOrInit = packettype;
-		tcb_desc->bLastIniPkt = bLastIniPkt;
-
-#ifdef RTL8192U
-		skb_reserve(skb, USB_HWDESC_HEADER_LEN);
-#endif
-
-		seg_ptr = skb_put(skb, buffer_len);
-		/*
-		 * Transform from little endian to big endian
-		 * and pending zero
-		 */
-		memcpy(seg_ptr, codevirtualaddress, buffer_len);
-		tcb_desc->txbuf_size = (u16)buffer_len;
-
-
-		if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) ||
-		    (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) ||
-		    (priv->ieee80211->queue_stop)) {
-			RT_TRACE(COMP_FIRMWARE, "======> tx full!\n");
-			skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
-		} else {
-			priv->ieee80211->softmac_hard_start_xmit(skb, dev);
-		}
-
-		codevirtualaddress += frag_length;
-		frag_offset += frag_length;
-
-	} while (frag_offset < buffer_len);
-
-	return rt_status;
-
-
-#endif
-}
-
-/*-----------------------------------------------------------------------------
  * Function:    cmpk_counttxstatistic()
  *
  * Overview:
@@ -593,8 +494,8 @@
  *  05/06/2008		amy	Create Version 0 porting from windows code.
  *
  *---------------------------------------------------------------------------*/
-extern u32 cmpk_message_handle_rx(struct net_device *dev,
-				  struct ieee80211_rx_stats *pstats)
+u32 cmpk_message_handle_rx(struct net_device *dev,
+			   struct ieee80211_rx_stats *pstats)
 {
 	int			total_length;
 	u8			cmd_length, exe_cnt = 0;
diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.h b/drivers/staging/rtl8192u/r819xU_cmdpkt.h
index ebe4032..52cd437 100644
--- a/drivers/staging/rtl8192u/r819xU_cmdpkt.h
+++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.h
@@ -1,17 +1,17 @@
 #ifndef R819XUSB_CMDPKT_H
 #define R819XUSB_CMDPKT_H
 /* Different command packet have dedicated message length and definition. */
-#define		CMPK_RX_TX_FB_SIZE					sizeof(cmpk_txfb_t)		//20
-#define		CMPK_TX_SET_CONFIG_SIZE				sizeof(cmpk_set_cfg_t)	//16
-#define		CMPK_BOTH_QUERY_CONFIG_SIZE			sizeof(cmpk_set_cfg_t)	//16
-#define		CMPK_RX_TX_STS_SIZE					sizeof(cmpk_tx_status_t)//
-#define		CMPK_RX_DBG_MSG_SIZE			sizeof(cmpk_rx_dbginfo_t)//
-#define		CMPK_TX_RAHIS_SIZE			sizeof(cmpk_tx_rahis_t)
+#define		CMPK_RX_TX_FB_SIZE		sizeof(cmpk_txfb_t)	/* 20 */
+#define		CMPK_TX_SET_CONFIG_SIZE		sizeof(cmpk_set_cfg_t)	/* 16 */
+#define		CMPK_BOTH_QUERY_CONFIG_SIZE	sizeof(cmpk_set_cfg_t)	/* 16 */
+#define		CMPK_RX_TX_STS_SIZE		sizeof(cmpk_tx_status_t)
+#define		CMPK_RX_DBG_MSG_SIZE		sizeof(cmpk_rx_dbginfo_t)
+#define		CMPK_TX_RAHIS_SIZE		sizeof(cmpk_tx_rahis_t)
 
 /* 2008/05/08 amy For USB constant. */
-#define ISR_TxBcnOk					BIT27			// Transmit Beacon OK
-#define ISR_TxBcnErr				BIT26			// Transmit Beacon Error
-#define ISR_BcnTimerIntr			BIT13			// Beacon Timer Interrupt
+#define ISR_TxBcnOk		BIT27		/* Transmit Beacon OK */
+#define ISR_TxBcnErr		BIT26		/* Transmit Beacon Error */
+#define ISR_BcnTimerIntr	BIT13		/* Beacon Timer Interrupt */
 
 
 /* Define element ID of command packet. */
@@ -20,182 +20,172 @@
 /* Define different command packet structure. */
 /* 1. RX side: TX feedback packet. */
 typedef struct tag_cmd_pkt_tx_feedback {
-	// DWORD 0
+	/* DWORD 0 */
 	u8	element_id;			/* Command packet type. */
 	u8	length;				/* Command packet length. */
-	/* 2007/07/05 MH Change tx feedback info field. */
+	/* Change tx feedback info field. */
 	/*------TX Feedback Info Field */
-	u8	TID:4;				/* */
-	u8	fail_reason:3;		/* */
+	u8	TID:4;
+	u8	fail_reason:3;
 	u8	tok:1;				/* Transmit ok. */
-	u8	reserve1:4;			/* */
-	u8	pkt_type:2;		/* */
-	u8	bandwidth:1;		/* */
-	u8	qos_pkt:1;			/* */
+	u8	reserve1:4;
+	u8	pkt_type:2;
+	u8	bandwidth:1;
+	u8	qos_pkt:1;
 
-	// DWORD 1
-	u8	reserve2;			/* */
+	/* DWORD 1 */
+	u8	reserve2;
 	/*------TX Feedback Info Field */
-	u8	retry_cnt;			/* */
-	u16	pkt_id;				/* */
+	u8	retry_cnt;
+	u16	pkt_id;
 
-	// DWORD 3
-	u16	seq_num;			/* */
+	/* DWORD 3 */
+	u16	seq_num;
 	u8	s_rate;				/* Start rate. */
 	u8	f_rate;				/* Final rate. */
 
-	// DWORD 4
-	u8	s_rts_rate;			/* */
-	u8	f_rts_rate;			/* */
-	u16	pkt_length;			/* */
+	/* DWORD 4 */
+	u8	s_rts_rate;
+	u8	f_rts_rate;
+	u16	pkt_length;
 
-	// DWORD 5
-	u16	reserve3;			/* */
-	u16	duration;			/* */
-}cmpk_txfb_t;
+	/* DWORD 5 */
+	u16	reserve3;
+	u16	duration;
+} cmpk_txfb_t;
 
 /* 2. RX side: Interrupt status packet. It includes Beacon State,
-	  Beacon Timer Interrupt and other useful informations in MAC ISR Reg. */
+ * Beacon Timer Interrupt and other useful informations in MAC ISR Reg. */
 typedef struct tag_cmd_pkt_interrupt_status {
 	u8	element_id;			/* Command packet type. */
 	u8	length;				/* Command packet length. */
 	u16	reserve;
-	u32	interrupt_status;				/* Interrupt Status. */
-}cmpk_intr_sta_t;
+	u32	interrupt_status;		/* Interrupt Status. */
+} cmpk_intr_sta_t;
 
 
 /* 3. TX side: Set configuration packet. */
 typedef struct tag_cmd_pkt_set_configuration {
 	u8	element_id;			/* Command packet type. */
 	u8	length;				/* Command packet length. */
-	u16	reserve1;			/* */
+	u16	reserve1;
+	/* Configuration info. */
 	u8	cfg_reserve1:3;
-	u8	cfg_size:2;			/* Configuration info. */
-	u8	cfg_type:2;			/* Configuration info. */
-	u8	cfg_action:1;		/* Configuration info. */
-	u8	cfg_reserve2;		/* Configuration info. */
-	u8	cfg_page:4;			/* Configuration info. */
-	u8	cfg_reserve3:4;		/* Configuration info. */
-	u8	cfg_offset;			/* Configuration info. */
-	u32	value;				/* */
-	u32	mask;				/* */
-}cmpk_set_cfg_t;
+	u8	cfg_size:2;
+	u8	cfg_type:2;
+	u8	cfg_action:1;
+	u8	cfg_reserve2;
+	u8	cfg_page:4;
+	u8	cfg_reserve3:4;
+	u8	cfg_offset;
+	u32	value;
+	u32	mask;
+} cmpk_set_cfg_t;
 
 /* 4. Both side : TX/RX query configuraton packet. The query structure is the
       same as set configuration. */
 #define		cmpk_query_cfg_t	cmpk_set_cfg_t
 
 /* 5. Multi packet feedback status. */
-typedef struct tag_tx_stats_feedback { // PJ quick rxcmd 09042007
-	// For endian transfer --> Driver will not the same as firmware structure.
-	// DW 0
+typedef struct tag_tx_stats_feedback {
+	/* For endian transfer --> Driver will not the same as
+	   firmware structure. */
+	/* DW 0 */
 	u16	reserve1;
-	u8	length;				// Command packet length
-	u8	element_id;			// Command packet type
+	u8	length;				/* Command packet length */
+	u8	element_id;			/* Command packet type */
 
-	// DW 1
-	u16	txfail;				// Tx Fail count
-	u16	txok;				// Tx ok count
+	/* DW 1 */
+	u16	txfail;				/* Tx fail count */
+	u16	txok;				/* Tx ok count */
 
-	// DW 2
-	u16	txmcok;				// tx multicast
-	u16	txretry;			// Tx Retry count
+	/* DW 2 */
+	u16	txmcok;				/* Tx multicast */
+	u16	txretry;			/* Tx retry count */
 
-	// DW 3
-	u16  txucok;				// tx unicast
-	u16	txbcok;				// tx broadcast
+	/* DW 3 */
+	u16	txucok;				/* Tx unicast */
+	u16	txbcok;				/* Tx broadcast */
 
-	// DW 4
-	u16	txbcfail;			//
-	u16	txmcfail;			//
+	/* DW 4 */
+	u16	txbcfail;
+	u16	txmcfail;
 
-	// DW 5
-	u16	reserve2;			//
-	u16	txucfail;			//
+	/* DW 5 */
+	u16	reserve2;
+	u16	txucfail;
 
-	// DW 6-8
+	/* DW 6-8 */
 	u32	txmclength;
 	u32	txbclength;
 	u32	txuclength;
 
-	// DW 9
+	/* DW 9 */
 	u16	reserve3_23;
 	u8	reserve3_1;
 	u8	rate;
-}__attribute__((packed)) cmpk_tx_status_t;
+} __packed cmpk_tx_status_t;
 
 /* 6. Debug feedback message. */
-/* 2007/10/23 MH Define RX debug message  */
+/* Define RX debug message  */
 typedef struct tag_rx_debug_message_feedback {
-	// For endian transfer --> for driver
-	// DW 0
+	/* For endian transfer --> for driver */
+	/* DW 0 */
 	u16	reserve1;
-	u8	length;				// Command packet length
-	u8	element_id;			// Command packet type
+	u8	length;				/* Command packet length */
+	u8	element_id;			/* Command packet type */
 
-	// DW 1-??
-	// Variable debug message.
+	/* DW 1-?? */
+	/* Variable debug message. */
 
-}cmpk_rx_dbginfo_t;
+} cmpk_rx_dbginfo_t;
 
-/* 2008/03/20 MH Define transmit rate history. For big endian format. */
+/* Define transmit rate history. For big endian format. */
 typedef struct tag_tx_rate_history {
-	// For endian transfer --> for driver
-	// DW 0
-	u8	element_id;			// Command packet type
-	u8	length;				// Command packet length
+	/* For endian transfer --> for driver */
+	/* DW 0 */
+	u8	element_id;			/* Command packet type */
+	u8	length;				/* Command packet length */
 	u16	reserved1;
 
-	// DW 1-2	CCK rate counter
+	/* DW 1-2	CCK rate counter */
 	u16	cck[4];
 
-	// DW 3-6
+	/* DW 3-6 */
 	u16	ofdm[8];
 
-	// DW 7-14
-	//UINT16	MCS_BW0_SG0[16];
-
-	// DW 15-22
-	//UINT16	MCS_BW1_SG0[16];
-
-	// DW 23-30
-	//UINT16	MCS_BW0_SG1[16];
-
-	// DW 31-38
-	//UINT16	MCS_BW1_SG1[16];
-
-	// DW 7-14	BW=0 SG=0
-	// DW 15-22	BW=1 SG=0
-	// DW 23-30	BW=0 SG=1
-	// DW 31-38	BW=1 SG=1
+	/* DW 7-14	BW=0 SG=0
+	 * DW 15-22	BW=1 SG=0
+	 * DW 23-30	BW=0 SG=1
+	 * DW 31-38	BW=1 SG=1
+	 */
 	u16	ht_mcs[4][16];
 
-}__attribute__((packed)) cmpk_tx_rahis_t;
+} __packed cmpk_tx_rahis_t;
 
-typedef enum tag_command_packet_directories
-{
-    RX_TX_FEEDBACK = 0,
-    RX_INTERRUPT_STATUS		= 1,
-    TX_SET_CONFIG				= 2,
-    BOTH_QUERY_CONFIG			= 3,
-    RX_TX_STATUS				= 4,
-    RX_DBGINFO_FEEDBACK		= 5,
-    RX_TX_PER_PKT_FEEDBACK		= 6,
-    RX_TX_RATE_HISTORY		= 7,
-    RX_CMD_ELE_MAX
-}cmpk_element_e;
+typedef enum tag_command_packet_directories {
+	RX_TX_FEEDBACK			= 0,
+	RX_INTERRUPT_STATUS		= 1,
+	TX_SET_CONFIG			= 2,
+	BOTH_QUERY_CONFIG		= 3,
+	RX_TX_STATUS			= 4,
+	RX_DBGINFO_FEEDBACK		= 5,
+	RX_TX_PER_PKT_FEEDBACK		= 6,
+	RX_TX_RATE_HISTORY		= 7,
+	RX_CMD_ELE_MAX
+} cmpk_element_e;
 
-typedef enum _rt_status{
+typedef enum _rt_status {
 	RT_STATUS_SUCCESS,
 	RT_STATUS_FAILURE,
 	RT_STATUS_PENDING,
 	RT_STATUS_RESOURCE
-}rt_status,*prt_status;
+} rt_status, *prt_status;
 
-extern rt_status cmpk_message_handle_tx(struct net_device *dev, u8 *codevirtualaddress, u32 packettype, u32 buffer_len);
-
-extern  u32 cmpk_message_handle_rx(struct net_device *dev, struct ieee80211_rx_stats *pstats);
-extern rt_status SendTxCommandPacket( struct net_device *dev, void *pData, u32 DataLen);
+extern u32 cmpk_message_handle_rx(struct net_device *dev,
+		struct ieee80211_rx_stats *pstats);
+extern rt_status SendTxCommandPacket(struct net_device *dev,
+		void *pData, u32 DataLen);
 
 
 #endif
diff --git a/drivers/staging/rtl8192u/r819xU_firmware.c b/drivers/staging/rtl8192u/r819xU_firmware.c
index bb924ac..d6a6de3 100644
--- a/drivers/staging/rtl8192u/r819xU_firmware.c
+++ b/drivers/staging/rtl8192u/r819xU_firmware.c
@@ -61,20 +61,16 @@
 		/* Allocate skb buffer to contain firmware info and tx descriptor info
 		 * add 4 to avoid packet appending overflow.
 		 * */
-		#ifdef RTL8192U
 		skb  = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4);
-		#else
-		skb  = dev_alloc_skb(frag_length + 4);
-		#endif
+		if (!skb)
+			return false;
 		memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
 		tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
 		tcb_desc->queue_index = TXCMD_QUEUE;
 		tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
 		tcb_desc->bLastIniPkt = bLastIniPkt;
 
-		#ifdef RTL8192U
 		skb_reserve(skb, USB_HWDESC_HEADER_LEN);
-		#endif
 		seg_ptr = skb->data;
 		/*
 		 * Transform from little endian to big endian
@@ -299,16 +295,10 @@
 				mapped_file = pfirmware->firmware_buf;
 				file_length = fw_entry->size;
 			} else {
-#ifdef RTL8190P
-				memcpy(pfirmware->firmware_buf,fw_entry->data,fw_entry->size);
-				mapped_file = pfirmware->firmware_buf;
-				file_length = fw_entry->size;
-#else
 				memset(pfirmware->firmware_buf,0,128);
 				memcpy(&pfirmware->firmware_buf[128],fw_entry->data,fw_entry->size);
 				mapped_file = pfirmware->firmware_buf;
 				file_length = fw_entry->size + 128;
-#endif
 			}
 			pfirmware->firmware_buf_size = file_length;
 		}else if (rst_opt == OPT_FIRMWARE_RESET ) {
@@ -340,15 +330,6 @@
 			 * will set polling bit when firmware code is also configured
 			 */
 			pfirmware->firmware_status = FW_STATUS_1_MOVE_BOOT_CODE;
-#ifdef RTL8190P
-			// To initialize IMEM, CPU move code  from 0x80000080, hence, we send 0x80 byte packet
-			rt_status = fwSendNullPacket(dev, RTL8190_CPU_START_OFFSET);
-			if (rt_status != true)
-			{
-				RT_TRACE(COMP_INIT, "fwSendNullPacket() fail ! \n");
-				goto  download_firmware_fail;
-			}
-#endif
 			//mdelay(1000);
 			/*
 			 * To initialize IMEM, CPU move code  from 0x80000080,
diff --git a/drivers/staging/rtl8192u/r819xU_phy.c b/drivers/staging/rtl8192u/r819xU_phy.c
index a6fac08..39cd426 100644
--- a/drivers/staging/rtl8192u/r819xU_phy.c
+++ b/drivers/staging/rtl8192u/r819xU_phy.c
@@ -1713,7 +1713,7 @@
 		queue_delayed_work(priv->priv_wq, &priv->initialgain_operate_wq, 0);
 }
 
-extern void InitialGainOperateWorkItemCallBack(struct work_struct *work)
+void InitialGainOperateWorkItemCallBack(struct work_struct *work)
 {
 	struct delayed_work *dwork = container_of(work, struct delayed_work,
 						  work);
@@ -1799,12 +1799,6 @@
 		RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xa0a is %x\n",
 			 priv->initgain_backup.cca);
 
-#ifdef RTL8190P
-		SetTxPowerLevel8190(Adapter, priv->CurrentChannel);
-#endif
-#ifdef RTL8192E
-		SetTxPowerLevel8190(Adapter, priv->CurrentChannel);
-#endif
 		rtl8192_phy_setTxPower(dev, priv->ieee80211->current_network.channel);
 
 		if (dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM)
diff --git a/drivers/staging/rtl8192u/r819xU_phy.h b/drivers/staging/rtl8192u/r819xU_phy.h
index f3c352a..66cbe3f 100644
--- a/drivers/staging/rtl8192u/r819xU_phy.h
+++ b/drivers/staging/rtl8192u/r819xU_phy.h
@@ -23,7 +23,7 @@
 	u32		Para1;
 	u32		Para2;
 	u32		msDelay;
-} __attribute__ ((packed)) SwChnlCmd;
+} __packed SwChnlCmd;
 
 extern u32 rtl819XMACPHY_Array_PG[];
 extern u32 rtl819XPHY_REG_1T2RArray[];
diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c
index 6e81ba0..82a77b4 100644
--- a/drivers/staging/rtl8712/os_intfs.c
+++ b/drivers/staging/rtl8712/os_intfs.c
@@ -141,7 +141,7 @@
 	registry_par->ssid.SsidLength = 3;
 	registry_par->channel = (u8)channel;
 	registry_par->wireless_mode = (u8)wireless_mode;
-	registry_par->vrtl_carrier_sense = (u8)vrtl_carrier_sense ;
+	registry_par->vrtl_carrier_sense = (u8)vrtl_carrier_sense;
 	registry_par->vcs_type = (u8)vcs_type;
 	registry_par->frag_thresh = (u16)frag_thresh;
 	registry_par->preamble = (u8)preamble;
diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c
index 088647c..5b6a96e 100644
--- a/drivers/staging/rtl8712/rtl8712_cmd.c
+++ b/drivers/staging/rtl8712/rtl8712_cmd.c
@@ -62,7 +62,7 @@
 	r8712_write8(padapter, GPIO_IO_SEL, tmp1byte);
 	tmp1byte = r8712_read8(padapter, GPIO_CTRL);
 	if (tmp1byte == 0xff)
-		return ;
+		return;
 	if (tmp1byte&HAL_8192S_HW_GPIO_WPS_BIT) {
 		/* Here we only set bPbcPressed to true
 		 * After trigger PBC, the variable will be set to false */
@@ -381,7 +381,7 @@
 			*pcmdbuf = cpu_to_le32((cmdsz & 0x0000ffff) |
 					       (pcmd->cmdcode << 16) |
 					       (pcmdpriv->cmd_seq << 24));
-			pcmdbuf += 2 ; /* 8 bytes alignment */
+			pcmdbuf += 2; /* 8 bytes alignment */
 			memcpy((u8 *)pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
 			while (check_cmd_fifo(padapter, wr_sz) == _FAIL) {
 				if ((padapter->bDriverStopped == true) ||
@@ -471,11 +471,9 @@
 	if (pevt_priv->event_seq > 127)
 		pevt_priv->event_seq = 0;
 	peventbuf = peventbuf + 2; /* move to event content, 8 bytes alignment */
-	if (peventbuf) {
-		event_callback = wlanevents[evt_code].event_callback;
-		if (event_callback)
-			event_callback(padapter, (u8 *)peventbuf);
-	}
+	event_callback = wlanevents[evt_code].event_callback;
+	if (event_callback)
+		event_callback(padapter, (u8 *)peventbuf);
 	pevt_priv->evt_done_cnt++;
 _abort_event_:
 	return;
diff --git a/drivers/staging/rtl8712/rtl8712_efuse.c b/drivers/staging/rtl8712/rtl8712_efuse.c
index 377fca9..c9eeb42 100644
--- a/drivers/staging/rtl8712/rtl8712_efuse.c
+++ b/drivers/staging/rtl8712/rtl8712_efuse.c
@@ -231,7 +231,7 @@
 			/* read next header */
 			efuse_addr = efuse_addr + (word_cnts * 2) + 1;
 		} else
-			bContinual = false ;
+			bContinual = false;
 	}
 	return efuse_addr;
 }
diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c
index d59a74a..ea96537 100644
--- a/drivers/staging/rtl8712/rtl8712_recv.c
+++ b/drivers/staging/rtl8712/rtl8712_recv.c
@@ -108,7 +108,7 @@
 	struct _adapter *padapter = precvpriv->adapter;
 
 	precvbuf = (struct recv_buf *)precvpriv->precv_buf;
-	for (i = 0; i < NR_RECVBUFF ; i++) {
+	for (i = 0; i < NR_RECVBUFF; i++) {
 		r8712_os_recvbuf_resource_free(padapter, precvbuf);
 		precvbuf++;
 	}
@@ -268,7 +268,7 @@
 	u8   *psta_addr;
 	struct recv_frame_hdr *pfhdr;
 	struct sta_info *psta;
-	struct	sta_priv *pstapriv ;
+	struct	sta_priv *pstapriv;
 	struct list_head *phead;
 	union recv_frame *prtnframe = NULL;
 	struct  __queue *pfree_recv_queue, *pdefrag_q;
@@ -849,7 +849,7 @@
 	} else {
 		/* (1)Get RSSI for HT rate */
 		for (i = 0; i < ((padapter->registrypriv.rf_config) &
-			    0x0f) ; i++) {
+			    0x0f); i++) {
 			rf_rx_num++;
 			rx_pwr[i] = ((pphy_head[PHY_STAT_GAIN_TRSW_SHT + i]
 				    & 0x3F) * 2) - 110;
diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c
index f16307f..7e32431 100644
--- a/drivers/staging/rtl8712/rtl871x_cmd.c
+++ b/drivers/staging/rtl8712/rtl871x_cmd.c
@@ -965,7 +965,7 @@
 			psta = r8712_alloc_stainfo(&padapter->stapriv,
 						   pnetwork->MacAddress);
 			if (psta == NULL)
-				goto createbss_cmd_fail ;
+				goto createbss_cmd_fail;
 		}
 		r8712_indicate_connect(padapter);
 	} else {
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
index d58aa7e..9fec6ed 100644
--- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
+++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
@@ -820,7 +820,7 @@
 			intReturn = true;
 		blInserted = false;
 		/* overwrite PMKID */
-		for (j = 0 ; j < NUM_PMKID_CACHE; j++) {
+		for (j = 0; j < NUM_PMKID_CACHE; j++) {
 			if (!memcmp(psecuritypriv->PMKIDList[j].Bssid,
 			    strIssueBssid, ETH_ALEN)) {
 				/* BSSID is matched, the same AP => rewrite
@@ -845,7 +845,7 @@
 				PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
 			psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
 				bUsed = true;
-			psecuritypriv->PMKIDIndex++ ;
+			psecuritypriv->PMKIDIndex++;
 			if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
 				psecuritypriv->PMKIDIndex = 0;
 		}
@@ -1598,7 +1598,7 @@
 		wep.Length = wep.KeyLength +
 			     FIELD_OFFSET(struct NDIS_802_11_WEP, KeyMaterial);
 	} else {
-		wep.KeyLength = 0 ;
+		wep.KeyLength = 0;
 		if (keyindex_provided == 1) { /* set key_id only, no given
 					       * KeyMaterial(erq->length==0).*/
 			padapter->securitypriv.PrivacyKeyIndex = key;
@@ -1880,7 +1880,7 @@
 	u32 data32;
 
 	get_user(addr, (u32 __user *)wrqu->data.pointer);
-	data32 = ((u32)wrqu->data.length<<16) | (u32)wrqu->data.flags ;
+	data32 = ((u32)wrqu->data.length<<16) | (u32)wrqu->data.flags;
 	r8712_write32(padapter, addr, data32);
 	return 0;
 }
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_rtl.c b/drivers/staging/rtl8712/rtl871x_ioctl_rtl.c
index 5d6d55e..ac0baff 100644
--- a/drivers/staging/rtl8712/rtl871x_ioctl_rtl.c
+++ b/drivers/staging/rtl8712/rtl871x_ioctl_rtl.c
@@ -153,7 +153,7 @@
 					 padapter->recvpriv.rx_icv_err;
 		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
 	} else
-		return RNDIS_STATUS_INVALID_LENGTH ;
+		return RNDIS_STATUS_INVALID_LENGTH;
 	return RNDIS_STATUS_SUCCESS;
 }
 
@@ -169,7 +169,7 @@
 {
 	struct _adapter *padapter = (struct _adapter *)
 				    (poid_par_priv->adapter_context);
-	u32 preamblemode = 0 ;
+	u32 preamblemode = 0;
 
 	if (poid_par_priv->type_of_oid != QUERY_OID)
 		return RNDIS_STATUS_NOT_ACCEPTED;
@@ -522,7 +522,7 @@
 	else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)
 		ulInfo = ADHOCMODE;
 	else
-		ulInfo = NOTASSOCIATED ;
+		ulInfo = NOTASSOCIATED;
 	*(u32 *)poid_par_priv->information_buf = ulInfo;
 	*poid_par_priv->bytes_rw =  poid_par_priv->information_buf_len;
 	return RNDIS_STATUS_SUCCESS;
diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c
index 6596154..8fa0f9d 100644
--- a/drivers/staging/rtl8712/rtl871x_mlme.c
+++ b/drivers/staging/rtl8712/rtl871x_mlme.c
@@ -1641,7 +1641,7 @@
 	struct wlan_network	*cur_network = &adapter->mlmepriv.cur_network;
 
 	pdev_network->Privacy = cpu_to_le32(psecuritypriv->PrivacyAlgrthm
-					    > 0 ? 1 : 0) ; /* adhoc no 802.1x */
+					    > 0 ? 1 : 0); /* adhoc no 802.1x */
 	pdev_network->Rssi = 0;
 	switch (pregistrypriv->wireless_mode) {
 	case WIRELESS_11B:
@@ -1786,7 +1786,7 @@
 	psta = r8712_get_stainfo(&padapter->stapriv,
 				 pcur_network->network.MacAddress);
 	if (psta) {
-		for (i = 0; i < 16 ; i++) {
+		for (i = 0; i < 16; i++) {
 			preorder_ctrl = &psta->recvreorder_ctrl[i];
 			preorder_ctrl->indicate_seq = 0xffff;
 			preorder_ctrl->wend_b = 0xffff;
diff --git a/drivers/staging/rtl8712/rtl871x_mp.c b/drivers/staging/rtl8712/rtl871x_mp.c
index 5638d5e..0563318 100644
--- a/drivers/staging/rtl8712/rtl871x_mp.c
+++ b/drivers/staging/rtl8712/rtl871x_mp.c
@@ -110,7 +110,7 @@
 	u16 iocmd_value	= iocmd.value;
 	u8 iocmd_idx	= iocmd.index;
 
-	cmd32 = (iocmd_class << 24) | (iocmd_value << 8) | iocmd_idx ;
+	cmd32 = (iocmd_class << 24) | (iocmd_value << 8) | iocmd_idx;
 	if (r8712_fw_cmd(pAdapter, cmd32))
 		r8712_fw_cmd_data(pAdapter, &val32, 1);
 	else
@@ -128,7 +128,7 @@
 
 	r8712_fw_cmd_data(pAdapter, &value, 0);
 	msleep(100);
-	cmd32 = (iocmd_class << 24) | (iocmd_value << 8) | iocmd_idx ;
+	cmd32 = (iocmd_class << 24) | (iocmd_value << 8) | iocmd_idx;
 	return r8712_fw_cmd(pAdapter, cmd32);
 }
 
@@ -189,8 +189,8 @@
 	u32 rf_data;
 	struct IOCMD_STRUCT iocmd;
 
-	iocmd.cmdclass	= IOCMD_CLASS_BB_RF ;
-	iocmd.value	= rf_addr ;
+	iocmd.cmdclass	= IOCMD_CLASS_BB_RF;
+	iocmd.value	= rf_addr;
 	iocmd.index	= IOCMD_RF_READ_IDX;
 	rf_data = fw_iocmd_read(pAdapter, iocmd);
 	return rf_data;
diff --git a/drivers/staging/rtl8712/rtl871x_security.c b/drivers/staging/rtl8712/rtl871x_security.c
index e33fd6d..5349669 100644
--- a/drivers/staging/rtl8712/rtl871x_security.c
+++ b/drivers/staging/rtl8712/rtl871x_security.c
@@ -835,7 +835,7 @@
 	u8 temp[4];
 	u8 tempb[4];
 
-	for (i = 0 ; i < 4; i++) {
+	for (i = 0; i < 4; i++) {
 		if ((in[i] & 0x80) == 0x80)
 			add1b[i] = 0x1b;
 		else
@@ -1187,7 +1187,7 @@
 					length = pxmitpriv->frag_len -
 						 pattrib->hdrlen -
 						 pattrib->iv_len -
-						 pattrib->icv_len ;
+						 pattrib->icv_len;
 					aes_cipher(prwskey, pattrib->
 						   hdrlen, pframe, length);
 					pframe += pxmitpriv->frag_len;
@@ -1315,7 +1315,7 @@
 		bitwise_xor(aes_out, padded_buffer, chain_buffer);
 		aes128k128d(key, chain_buffer, aes_out);
 	}
-	for (j = 0 ; j < 8; j++)
+	for (j = 0; j < 8; j++)
 		mic[j] = aes_out[j];
 	/* Insert MIC into payload */
 	for (j = 0; j < 8; j++)
diff --git a/drivers/staging/rtl8712/rtl871x_sta_mgt.c b/drivers/staging/rtl8712/rtl871x_sta_mgt.c
index 1247b3d..8db6849 100644
--- a/drivers/staging/rtl8712/rtl871x_sta_mgt.c
+++ b/drivers/staging/rtl8712/rtl871x_sta_mgt.c
@@ -138,7 +138,7 @@
 		}
 		phash_list = &(pstapriv->sta_hash[index]);
 		list_insert_tail(&psta->hash_list, phash_list);
-		pstapriv->asoc_sta_count++ ;
+		pstapriv->asoc_sta_count++;
 
 /* For the SMC router, the sequence number of first packet of WPS handshake
  * will be 0. In this case, this packet will be dropped by recv_decache function
@@ -149,7 +149,7 @@
 			memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i],
 				&wRxSeqInitialValue, 2);
 		/* for A-MPDU Rx reordering buffer control */
-		for (i = 0; i < 16 ; i++) {
+		for (i = 0; i < 16; i++) {
 			preorder_ctrl = &psta->recvreorder_ctrl[i];
 			preorder_ctrl->padapter = pstapriv->padapter;
 			preorder_ctrl->indicate_seq = 0xffff;
diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c
index c812d6c7..dbefa43 100644
--- a/drivers/staging/rtl8712/usb_intf.c
+++ b/drivers/staging/rtl8712/usb_intf.c
@@ -353,11 +353,6 @@
 	}
 }
 
-static u8 key_2char2num(u8 hch, u8 lch)
-{
-	return (hex_to_bin(hch) << 4) | hex_to_bin(lch);
-}
-
 /*
  * drv_init() - a device potentially for us
  *
@@ -465,16 +460,7 @@
 				r8712_efuse_pg_packet_read(padapter, offset,
 						     &pdata[i]);
 
-			if (r8712_initmac) {
-				/* Users specify the mac address */
-				int jj, kk;
-
-				for (jj = 0, kk = 0; jj < ETH_ALEN;
-				     jj++, kk += 3)
-					mac[jj] =
-					   key_2char2num(r8712_initmac[kk],
-					   r8712_initmac[kk + 1]);
-			} else {
+			if (!r8712_initmac || !mac_pton(r8712_initmac, mac)) {
 				/* Use the mac address stored in the Efuse
 				 * offset = 0x12 for usb in efuse
 				 */
diff --git a/drivers/staging/rtl8712/xmit_linux.c b/drivers/staging/rtl8712/xmit_linux.c
index 4d22bb7..0ac9130 100644
--- a/drivers/staging/rtl8712/xmit_linux.c
+++ b/drivers/staging/rtl8712/xmit_linux.c
@@ -51,7 +51,7 @@
 	pfile->pkt = pktptr;
 	pfile->cur_addr = pfile->buf_start = pktptr->data;
 	pfile->pkt_len = pfile->buf_len = pktptr->len;
-	pfile->cur_buffer = pfile->buf_start ;
+	pfile->cur_buffer = pfile->buf_start;
 }
 
 uint _r8712_pktfile_read(struct pkt_file *pfile, u8 *rmem, uint rlen)
diff --git a/drivers/staging/rts5139/rts51x_scsi.c b/drivers/staging/rts5139/rts51x_scsi.c
index 6108705..a474eed 100644
--- a/drivers/staging/rts5139/rts51x_scsi.c
+++ b/drivers/staging/rts5139/rts51x_scsi.c
@@ -973,7 +973,7 @@
 
 	rts51x_pp_status(chip, lun, status, 32);
 
-	buf_len = min(scsi_bufflen(srb), (unsigned int)sizeof(status));
+	buf_len = min_t(unsigned int, scsi_bufflen(srb), sizeof(status));
 	rts51x_set_xfer_buf(status, buf_len, srb);
 	scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
 
@@ -988,7 +988,7 @@
 
 	rts51x_read_status(chip, lun, rts51x_status, 16);
 
-	buf_len = min(scsi_bufflen(srb), (unsigned int)sizeof(rts51x_status));
+	buf_len = min_t(unsigned int, scsi_bufflen(srb), sizeof(rts51x_status));
 	rts51x_set_xfer_buf(rts51x_status, buf_len, srb);
 	scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
 
diff --git a/drivers/staging/sb105x/sb_mp_register.h b/drivers/staging/sb105x/sb_mp_register.h
index 304e1bc..16de497 100644
--- a/drivers/staging/sb105x/sb_mp_register.h
+++ b/drivers/staging/sb105x/sb_mp_register.h
@@ -15,8 +15,8 @@
 #ifndef UART_SB105X_H
 #define UART_SB105X_H
 
-/* 
- * option register 
+/*
+ * option register
  */
 
 /* Device Information Register */
diff --git a/drivers/staging/sb105x/sb_pci_mp.c b/drivers/staging/sb105x/sb_pci_mp.c
index 23db32f..5cd3eff 100644
--- a/drivers/staging/sb105x/sb_pci_mp.c
+++ b/drivers/staging/sb105x/sb_pci_mp.c
@@ -543,14 +543,14 @@
 		if (init_hw) {
 			mp_change_speed(state, NULL);
 
-			if (info->tty->termios.c_cflag & CBAUD)
+			if (info->tty && (info->tty->termios.c_cflag & CBAUD))
 				uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR);
 		}
 
 		info->flags |= UIF_INITIALIZED;
 
-
-		clear_bit(TTY_IO_ERROR, &info->tty->flags);
+		if (info->tty)
+			clear_bit(TTY_IO_ERROR, &info->tty->flags);
 	}
 
 	if (retval && capable(CAP_SYS_ADMIN))
@@ -1063,7 +1063,7 @@
 
 static int mp_get_count(struct sb_uart_state *state, struct serial_icounter_struct *icnt)
 {
-	struct serial_icounter_struct icount;
+	struct serial_icounter_struct icount = {};
 	struct sb_uart_icount cnow;
 	struct sb_uart_port *port = state->port;
 
@@ -1216,7 +1216,7 @@
 				return (inb(mp_devs[arg].option_reg_addr+MP_OPTR_IIR0+(state->port->line/8)));
 			}
 		case TIOCGGETPORTTYPE:
-			ret = get_device_type(arg);;
+			ret = get_device_type(arg);
 			return ret;
 		case TIOCSMULTIECHO: /* set to multi-drop mode(RS422) or echo mode(RS485)*/
 			outb( ( inb(info->interface_config_addr) & ~0x03 ) | 0x01 ,  
@@ -1808,10 +1808,7 @@
     drv->tty_driver = NULL;
 
 
-    if (drv->state)
-    {
-        kfree(drv->state);
-    }
+    kfree(drv->state);
 
 }
 
diff --git a/drivers/staging/sbe-2t3e3/cpld.c b/drivers/staging/sbe-2t3e3/cpld.c
index 27365f9..c6370d3 100644
--- a/drivers/staging/sbe-2t3e3/cpld.c
+++ b/drivers/staging/sbe-2t3e3/cpld.c
@@ -240,7 +240,7 @@
 }
 
 
-extern void cpld_set_clock(struct channel *sc, u32 mode)
+void cpld_set_clock(struct channel *sc, u32 mode)
 {
 	if (sc->p.clock_source == mode)
 		return;
diff --git a/drivers/staging/sep/sep_crypto.c b/drivers/staging/sep/sep_crypto.c
index 490a31e..b9262a7 100644
--- a/drivers/staging/sep/sep_crypto.c
+++ b/drivers/staging/sep/sep_crypto.c
@@ -1134,7 +1134,7 @@
 
 	if (int_error < 0) {
 		dev_warn(&ta_ctx->sep_used->pdev->dev, "oddball page error\n");
-		return -ENOMEM;
+		return int_error;
 	} else if (int_error == 1) {
 		ta_ctx->src_sg = new_sg;
 		ta_ctx->src_sg_hold = new_sg;
@@ -1149,7 +1149,7 @@
 	if (int_error < 0) {
 		dev_warn(&ta_ctx->sep_used->pdev->dev, "walk phys error %x\n",
 			int_error);
-		return -ENOMEM;
+		return int_error;
 	} else if (int_error == 1) {
 		ta_ctx->dst_sg = new_sg;
 		ta_ctx->dst_sg_hold = new_sg;
diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c
index 6a98a20..1e80a40 100644
--- a/drivers/staging/sep/sep_main.c
+++ b/drivers/staging/sep/sep_main.c
@@ -493,8 +493,7 @@
 		 * then we skip this step altogether as restricted
 		 * memory is not available to the o/s at all.
 		 */
-		if (((*dma_ctx)->secure_dma == false) &&
-			(dma->out_map_array)) {
+		if (!(*dma_ctx)->secure_dma && dma->out_map_array) {
 
 			for (count = 0; count < dma->out_num_pages; count++) {
 				dma_unmap_page(&sep->pdev->dev,
@@ -515,8 +514,7 @@
 		}
 
 		/* Again, we do this only for non secure dma */
-		if (((*dma_ctx)->secure_dma == false) &&
-			(dma->out_page_array)) {
+		if (!(*dma_ctx)->secure_dma && dma->out_page_array) {
 
 			for (count = 0; count < dma->out_num_pages; count++) {
 				if (!PageReserved(dma->out_page_array[count]))
@@ -1263,13 +1261,8 @@
 	}
 
 	/* Convert the application virtual address into a set of physical */
-	down_read(&current->mm->mmap_sem);
-	result = get_user_pages(current, current->mm, app_virt_addr,
-		num_pages,
-		((in_out_flag == SEP_DRIVER_IN_FLAG) ? 0 : 1),
-		0, page_array, NULL);
-
-	up_read(&current->mm->mmap_sem);
+	result = get_user_pages_fast(app_virt_addr, num_pages,
+		((in_out_flag == SEP_DRIVER_IN_FLAG) ? 0 : 1), page_array);
 
 	/* Check the number of pages locked - if not all then exit with error */
 	if (result != num_pages) {
@@ -1952,7 +1945,7 @@
 	}
 
 	/* Check if the pages are in Kernel Virtual Address layout */
-	if (is_kva == true)
+	if (is_kva)
 		error = sep_lock_kernel_pages(sep, app_virt_addr,
 			data_size, &lli_array_ptr, SEP_DRIVER_IN_FLAG,
 			dma_ctx);
@@ -2446,7 +2439,7 @@
 	dma_ctx->dma_res_arr[dma_ctx->nr_dcb_creat].out_page_array = NULL;
 
 	/* Lock the pages of the buffer and translate them to pages */
-	if (is_kva == true) {
+	if (is_kva) {
 		dev_dbg(&sep->pdev->dev, "[PID%d] Locking kernel input pages\n",
 						current->pid);
 		error = sep_lock_kernel_pages(sep, app_virt_in_addr,
@@ -2490,7 +2483,7 @@
 			goto end_function;
 		}
 
-		if (dma_ctx->secure_dma == true) {
+		if (dma_ctx->secure_dma) {
 			/* secure_dma requires use of non accessible memory */
 			dev_dbg(&sep->pdev->dev, "[PID%d] in secure_dma\n",
 				current->pid);
@@ -2727,11 +2720,11 @@
 	dcb_table_ptr->tail_data_size = 0;
 	dcb_table_ptr->out_vr_tail_pt = 0;
 
-	if (isapplet == true) {
+	if (isapplet) {
 
 		/* Check if there is enough data for DMA operation */
 		if (data_in_size < SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE) {
-			if (is_kva == true) {
+			if (is_kva) {
 				error = -ENODEV;
 				goto end_function_error;
 			} else {
@@ -2772,7 +2765,7 @@
 		if (tail_size) {
 			if (tail_size > sizeof(dcb_table_ptr->tail_data))
 				return -EINVAL;
-			if (is_kva == true) {
+			if (is_kva) {
 				error = -ENODEV;
 				goto end_function_error;
 			} else {
@@ -2883,7 +2876,7 @@
 	if (!dma_ctx || !*dma_ctx) /* nothing to be done here*/
 		return 0;
 
-	if (((*dma_ctx)->secure_dma == false) && (isapplet == true)) {
+	if (!(*dma_ctx)->secure_dma && isapplet) {
 		dev_dbg(&sep->pdev->dev, "[PID%d] handling applet\n",
 			current->pid);
 
@@ -2902,7 +2895,7 @@
 				pt_hold = (unsigned long)dcb_table_ptr->
 					out_vr_tail_pt;
 				tail_pt = (void *)pt_hold;
-				if (is_kva == true) {
+				if (is_kva) {
 					error = -ENODEV;
 					break;
 				} else {
@@ -4080,6 +4073,7 @@
 	if (ret_val) {
 		dev_warn(&sep->pdev->dev, "sysfs attribute1 fails for SEP %x\n",
 			ret_val);
+		misc_deregister(&sep->miscdev_sep);
 		return ret_val;
 	}
 
diff --git a/drivers/staging/silicom/bp_mod.h b/drivers/staging/silicom/bp_mod.h
index cfa1f43..8154a7b 100644
--- a/drivers/staging/silicom/bp_mod.h
+++ b/drivers/staging/silicom/bp_mod.h
@@ -22,7 +22,7 @@
 	int  i;					\
 	if (1) {				\
 		for (i = 0; i < 1000; i++) {	\
-			udelay(x) ;		\
+			udelay(x);		\
 		}				\
 	} else {				\
 		msleep(x);			\
diff --git a/drivers/staging/silicom/bpctl_mod.c b/drivers/staging/silicom/bpctl_mod.c
index 495272d..39dc92a 100644
--- a/drivers/staging/silicom/bpctl_mod.c
+++ b/drivers/staging/silicom/bpctl_mod.c
@@ -1,11 +1,11 @@
 /******************************************************************************/
 /*                                                                            */
-/* Bypass Control utility, Copyright (c) 2005-20011 Silicom                   */
+/* Bypass Control utility, Copyright (c) 2005-2011 Silicom                    */
 /*                                                                            */
 /* This program is free software; you can redistribute it and/or modify       */
 /* it under the terms of the GNU General Public License as published by       */
 /* the Free Software Foundation, located in the file LICENSE.                 */
-/*  Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved.          */
+/* Copyright(c) 2007 - 2009, 2013 Intel Corporation. All rights reserved.     */
 /*                                                                            */
 /*                                                                            */
 /******************************************************************************/
@@ -124,80 +124,60 @@
 int is_bypass_fn(struct bpctl_dev *pbpctl_dev);
 int get_dev_idx_bsf(int bus, int slot, int func);
 
-static unsigned long str_to_hex(char *p);
+static int bp_get_dev_idx_bsf(struct net_device *dev, int *index)
+{
+	struct ethtool_drvinfo drvinfo = {0};
+	char *buf;
+	int bus, slot, func;
+
+	if (dev->ethtool_ops && dev->ethtool_ops->get_drvinfo)
+		dev->ethtool_ops->get_drvinfo(dev, &drvinfo);
+	else
+		return -EOPNOTSUPP;
+
+	if (!drvinfo.bus_info)
+		return -ENODATA;
+	if (!strcmp(drvinfo.bus_info, "N/A"))
+		return -ENODATA;
+
+	buf = strchr(drvinfo.bus_info, ':');
+	if (!buf)
+		return -EINVAL;
+	buf++;
+	if (sscanf(buf, "%x:%x.%x", &bus, &slot, &func) != 3)
+		return -EINVAL;
+
+	*index = get_dev_idx_bsf(bus, slot, func);
+	return 0;
+}
+
 static int bp_device_event(struct notifier_block *unused,
 			   unsigned long event, void *ptr)
 {
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 	static struct bpctl_dev *pbpctl_dev, *pbpctl_dev_m;
 	int dev_num = 0, ret = 0, ret_d = 0, time_left = 0;
+
 	/* printk("BP_PROC_SUPPORT event =%d %s %d\n", event,dev->name, dev->ifindex ); */
 	/* return NOTIFY_DONE; */
 	if (!dev)
 		return NOTIFY_DONE;
+
 	if (event == NETDEV_REGISTER) {
-		{
-			struct ethtool_drvinfo drvinfo;
-			char cbuf[32];
-			char *buf = NULL;
-			char res[10];
-			int i = 0, ifindex, idx_dev = 0;
-			int bus = 0, slot = 0, func = 0;
-			ifindex = dev->ifindex;
+		int idx_dev;
 
-			memset(res, 0, 10);
-			memset(&drvinfo, 0, sizeof(struct ethtool_drvinfo));
+		if (bp_get_dev_idx_bsf(dev, &idx_dev))
+			return NOTIFY_DONE;
 
-			if (dev->ethtool_ops && dev->ethtool_ops->get_drvinfo) {
-				memset(&drvinfo, 0, sizeof(drvinfo));
-				dev->ethtool_ops->get_drvinfo(dev, &drvinfo);
-			} else
-				return NOTIFY_DONE;
-			if (!drvinfo.bus_info)
-				return NOTIFY_DONE;
-			if (!strcmp(drvinfo.bus_info, "N/A"))
-				return NOTIFY_DONE;
-			memcpy(&cbuf, drvinfo.bus_info, 32);
-			buf = &cbuf[0];
+		if (idx_dev == -1)
+			return NOTIFY_DONE;
 
-			while (*buf++ != ':')
-				;
-			for (i = 0; i < 10; i++, buf++) {
-				if (*buf == ':')
-					break;
-				res[i] = *buf;
+		bpctl_dev_arr[idx_dev].ifindex = dev->ifindex;
+		bpctl_dev_arr[idx_dev].ndev = dev;
 
-			}
-			buf++;
-			bus = str_to_hex(res);
-			memset(res, 0, 10);
-
-			for (i = 0; i < 10; i++, buf++) {
-				if (*buf == '.')
-					break;
-				res[i] = *buf;
-
-			}
-			buf++;
-			slot = str_to_hex(res);
-			func = str_to_hex(buf);
-			idx_dev = get_dev_idx_bsf(bus, slot, func);
-
-			if (idx_dev != -1) {
-
-				bpctl_dev_arr[idx_dev].ifindex = ifindex;
-				bpctl_dev_arr[idx_dev].ndev = dev;
-
-				bypass_proc_remove_dev_sd(&bpctl_dev_arr
-							  [idx_dev]);
-				bypass_proc_create_dev_sd(&bpctl_dev_arr
-							  [idx_dev]);
-
-			}
-
-		}
+		bypass_proc_remove_dev_sd(&bpctl_dev_arr[idx_dev]);
+		bypass_proc_create_dev_sd(&bpctl_dev_arr[idx_dev]);
 		return NOTIFY_DONE;
-
 	}
 	if (event == NETDEV_UNREGISTER) {
 		int idx_dev = 0;
@@ -5269,36 +5249,6 @@
 	return -1;
 }
 
-static void str_low(char *str)
-{
-	int i;
-
-	for (i = 0; i < strlen(str); i++)
-		if ((str[i] >= 65) && (str[i] <= 90))
-			str[i] += 32;
-}
-
-static unsigned long str_to_hex(char *p)
-{
-	unsigned long hex = 0;
-	unsigned long length = strlen(p), shift = 0;
-	unsigned char dig = 0;
-
-	str_low(p);
-	length = strlen(p);
-
-	if (length == 0)
-		return 0;
-
-	do {
-		dig = p[--length];
-		dig = dig < 'a' ? (dig - '0') : (dig - 'a' + 0xa);
-		hex |= (dig << shift);
-		shift += 4;
-	} while (length);
-	return hex;
-}
-
 static int get_dev_idx(int ifindex)
 {
 	int idx_dev = 0;
@@ -5329,70 +5279,26 @@
 
 static void if_scan_init(void)
 {
-	int idx_dev = 0;
 	struct net_device *dev;
-	int ifindex;
+
 	/* rcu_read_lock(); */
 	/* rtnl_lock();     */
 	/* rcu_read_lock(); */
 
 	for_each_netdev(&init_net, dev) {
+		int idx_dev;
 
-		struct ethtool_drvinfo drvinfo;
-		char cbuf[32];
-		char *buf = NULL;
-		char res[10];
-		int i = 0;
-		int bus = 0, slot = 0, func = 0;
-		ifindex = dev->ifindex;
-
-		memset(res, 0, 10);
-		memset(&drvinfo, 0, sizeof(struct ethtool_drvinfo));
-
-		if (dev->ethtool_ops && dev->ethtool_ops->get_drvinfo) {
-			memset(&drvinfo, 0, sizeof(drvinfo));
-			dev->ethtool_ops->get_drvinfo(dev, &drvinfo);
-		} else
+		if (bp_get_dev_idx_bsf(dev, &idx_dev))
 			continue;
-		if (!strcmp(drvinfo.bus_info, "N/A"))
+
+		if (idx_dev == -1)
 			continue;
-		memcpy(&cbuf, drvinfo.bus_info, 32);
-		buf = &cbuf[0];
 
-		while (*buf++ != ':')
-			;
-		for (i = 0; i < 10; i++, buf++) {
-			if (*buf == ':')
-				break;
-			res[i] = *buf;
-
-		}
-		buf++;
-		bus = str_to_hex(res);
-		memset(res, 0, 10);
-
-		for (i = 0; i < 10; i++, buf++) {
-			if (*buf == '.')
-				break;
-			res[i] = *buf;
-
-		}
-		buf++;
-		slot = str_to_hex(res);
-		func = str_to_hex(buf);
-		idx_dev = get_dev_idx_bsf(bus, slot, func);
-
-		if (idx_dev != -1) {
-
-			bpctl_dev_arr[idx_dev].ifindex = ifindex;
-			bpctl_dev_arr[idx_dev].ndev = dev;
-
-		}
-
+		bpctl_dev_arr[idx_dev].ifindex = dev->ifindex;
+		bpctl_dev_arr[idx_dev].ndev = dev;
 	}
 	/* rtnl_unlock();     */
 	/* rcu_read_unlock(); */
-
 }
 
 static long device_ioctl(struct file *file,	/* see include/linux/fs.h */
diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
index 869dcd3..652272b 100644
--- a/drivers/staging/slicoss/slicoss.c
+++ b/drivers/staging/slicoss/slicoss.c
@@ -62,6 +62,7 @@
 #define SLIC_OFFLOAD_IP_CHECKSUM		1
 #define STATS_TIMER_INTERVAL			2
 #define PING_TIMER_INTERVAL			    1
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -791,8 +792,8 @@
 			struct mcast_address *mcaddr = adapter->mcastaddrs;
 
 			while (mcaddr) {
-				if (!compare_ether_addr(mcaddr->address,
-							ether_frame->ether_dhost)) {
+				if (ether_addr_equal(mcaddr->address,
+						     ether_frame->ether_dhost)) {
 					adapter->rcv_multicasts++;
 					netdev->stats.multicast++;
 					return true;
@@ -1834,7 +1835,7 @@
 #endif
 
 	seq_printf(seq, "driver_version           : %s\n", slic_proc_version);
-	seq_printf(seq, "Microcode versions:           \n");
+	seq_puts(seq, "Microcode versions:           \n");
 	seq_printf(seq, "    Gigabit (gb)         : %s %s\n",
 		    MOJAVE_UCODE_VERS_STRING, MOJAVE_UCODE_VERS_DATE);
 	seq_printf(seq, "    Gigabit Receiver     : %s %s\n",
@@ -1865,8 +1866,8 @@
 			   config->macinfo[i].macaddrA[4],
 			   config->macinfo[i].macaddrA[5]);
 	}
-	seq_printf(seq, "     IF  Init State Duplex/Speed irq\n");
-	seq_printf(seq, "     -------------------------------\n");
+	seq_puts(seq, "     IF  Init State Duplex/Speed irq\n");
+	seq_puts(seq, "     -------------------------------\n");
 	for (i = 0; i < card->adapters_allocated; i++) {
 		struct adapter *adapter;
 
@@ -1909,7 +1910,7 @@
 	switch (config->FruFormat) {
 	case ATK_FRU_FORMAT:
 		{
-			seq_printf(seq,
+			seq_puts(seq,
 			    "Vendor                   : Alacritech, Inc.\n");
 			seq_printf(seq,
 			    "Assembly #               : %c%c%c%c%c%c\n",
@@ -1942,9 +1943,9 @@
 
 	default:
 		{
-			seq_printf(seq,
+			seq_puts(seq,
 			    "Vendor                   : Alacritech, Inc.\n");
-			seq_printf(seq,
+			seq_puts(seq,
 			    "Serial   #               : Empty FRU\n");
 			break;
 		}
@@ -1953,7 +1954,7 @@
 	switch (config->OEMFruFormat) {
 	case VENDOR1_FRU_FORMAT:
 		{
-			seq_printf(seq, "FRU Information:\n");
+			seq_puts(seq, "FRU Information:\n");
 			seq_printf(seq, "    Commodity #          : %c\n",
 				    oemfru[0]);
 			seq_printf(seq,
@@ -1976,7 +1977,7 @@
 
 	case VENDOR2_FRU_FORMAT:
 		{
-			seq_printf(seq, "FRU Information:\n");
+			seq_puts(seq, "FRU Information:\n");
 			seq_printf(seq,
 				    "    Part     #           : "
 				    "%c%c%c%c%c%c%c%c\n",
@@ -1999,12 +2000,12 @@
 
 	case VENDOR3_FRU_FORMAT:
 		{
-			seq_printf(seq, "FRU Information:\n");
+			seq_puts(seq, "FRU Information:\n");
 		}
 
 	case VENDOR4_FRU_FORMAT:
 		{
-			seq_printf(seq, "FRU Information:\n");
+			seq_puts(seq, "FRU Information:\n");
 			seq_printf(seq,
 				    "    FRU Number           : "
 				    "%c%c%c%c%c%c%c%c\n",
@@ -2231,14 +2232,8 @@
 		if (adapter)
 			slic_debug_adapter_destroy(adapter);
 	}
-	if (card->debugfs_cardinfo) {
-		debugfs_remove(card->debugfs_cardinfo);
-		card->debugfs_cardinfo = NULL;
-	}
-	if (card->debugfs_dir) {
-		debugfs_remove(card->debugfs_dir);
-		card->debugfs_dir = NULL;
-	}
+	debugfs_remove(card->debugfs_cardinfo);
+	debugfs_remove(card->debugfs_dir);
 }
 
 static void slic_debug_init(void)
@@ -2256,10 +2251,7 @@
 
 static void slic_debug_cleanup(void)
 {
-	if (slic_debugfs) {
-		debugfs_remove(slic_debugfs);
-		slic_debugfs = NULL;
-	}
+	debugfs_remove(slic_debugfs);
 }
 
 /*
@@ -2333,7 +2325,7 @@
 	/* Check to see if it already exists */
 	mlist = adapter->mcastaddrs;
 	while (mlist) {
-		if (!compare_ether_addr(mlist->address, address))
+		if (ether_addr_equal(mlist->address, address))
 			return 0;
 		mlist = mlist->next;
 	}
@@ -2627,6 +2619,67 @@
 	adapter->max_isr_xmits = max(adapter->max_isr_xmits, frames);
 }
 
+static void slic_interrupt_card_up(u32 isr, struct adapter *adapter,
+			struct net_device *dev)
+{
+	if (isr & ~ISR_IO) {
+		if (isr & ISR_ERR) {
+			adapter->error_interrupts++;
+			if (isr & ISR_RMISS) {
+				int count;
+				int pre_count;
+				int errors;
+
+				struct slic_rcvqueue *rcvq =
+					&adapter->rcvqueue;
+
+				adapter->error_rmiss_interrupts++;
+
+				if (!rcvq->errors)
+					rcv_count = rcvq->count;
+				pre_count = rcvq->count;
+				errors = rcvq->errors;
+
+				while (rcvq->count < SLIC_RCVQ_FILLTHRESH) {
+					count = slic_rcvqueue_fill(adapter);
+					if (!count)
+						break;
+				}
+			} else if (isr & ISR_XDROP) {
+				dev_err(&dev->dev,
+						"isr & ISR_ERR [%x] "
+						"ISR_XDROP \n", isr);
+			} else {
+				dev_err(&dev->dev,
+						"isr & ISR_ERR [%x]\n",
+						isr);
+			}
+		}
+
+		if (isr & ISR_LEVENT) {
+			adapter->linkevent_interrupts++;
+			slic_link_event_handler(adapter);
+		}
+
+		if ((isr & ISR_UPC) || (isr & ISR_UPCERR) ||
+		    (isr & ISR_UPCBSY)) {
+			adapter->upr_interrupts++;
+			slic_upr_request_complete(adapter, isr);
+		}
+	}
+
+	if (isr & ISR_RCV) {
+		adapter->rcv_interrupts++;
+		slic_rcv_handler(adapter);
+	}
+
+	if (isr & ISR_CMD) {
+		adapter->xmit_interrupts++;
+		slic_xmit_complete(adapter);
+	}
+}
+
+
 static irqreturn_t slic_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
@@ -2641,64 +2694,7 @@
 		adapter->num_isrs++;
 		switch (adapter->card->state) {
 		case CARD_UP:
-			if (isr & ~ISR_IO) {
-				if (isr & ISR_ERR) {
-					adapter->error_interrupts++;
-					if (isr & ISR_RMISS) {
-						int count;
-						int pre_count;
-						int errors;
-
-						struct slic_rcvqueue *rcvq =
-						    &adapter->rcvqueue;
-
-						adapter->
-						    error_rmiss_interrupts++;
-						if (!rcvq->errors)
-							rcv_count = rcvq->count;
-						pre_count = rcvq->count;
-						errors = rcvq->errors;
-
-						while (rcvq->count <
-						       SLIC_RCVQ_FILLTHRESH) {
-							count =
-							    slic_rcvqueue_fill
-							    (adapter);
-							if (!count)
-								break;
-						}
-					} else if (isr & ISR_XDROP) {
-						dev_err(&dev->dev,
-							"isr & ISR_ERR [%x] "
-							"ISR_XDROP \n", isr);
-					} else {
-						dev_err(&dev->dev,
-							"isr & ISR_ERR [%x]\n",
-							isr);
-					}
-				}
-
-				if (isr & ISR_LEVENT) {
-					adapter->linkevent_interrupts++;
-					slic_link_event_handler(adapter);
-				}
-
-				if ((isr & ISR_UPC) ||
-				    (isr & ISR_UPCERR) || (isr & ISR_UPCBSY)) {
-					adapter->upr_interrupts++;
-					slic_upr_request_complete(adapter, isr);
-				}
-			}
-
-			if (isr & ISR_RCV) {
-				adapter->rcv_interrupts++;
-				slic_rcv_handler(adapter);
-			}
-
-			if (isr & ISR_CMD) {
-				adapter->xmit_interrupts++;
-				slic_xmit_complete(adapter);
-			}
+			slic_interrupt_card_up(isr, adapter, dev);
 			break;
 
 		case CARD_DOWN:
@@ -3645,16 +3641,15 @@
 		return err;
 
 	if (slic_debug > 0 && did_version++ == 0) {
-		printk(KERN_DEBUG "%s\n", slic_banner);
-		printk(KERN_DEBUG "%s\n", slic_proc_version);
+		dev_dbg(&pcidev->dev, "%s\n", slic_banner);
+		dev_dbg(&pcidev->dev, "%s\n", slic_proc_version);
 	}
 
 	if (!pci_set_dma_mask(pcidev, DMA_BIT_MASK(64))) {
 		pci_using_dac = 1;
 		err = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64));
 		if (err) {
-			dev_err(&pcidev->dev, "unable to obtain 64-bit DMA for "
-					"consistent allocations\n");
+			dev_err(&pcidev->dev, "unable to obtain 64-bit DMA for consistent allocations\n");
 			goto err_out_disable_pci;
 		}
 	} else {
@@ -3776,8 +3771,7 @@
 	slic_init_driver();
 
 	if (debug >= 0 && slic_debug != debug)
-		printk(KERN_DEBUG KBUILD_MODNAME ": debug level is %d.\n",
-		       debug);
+		pr_debug("debug level is %d.\n", debug);
 	if (debug >= 0)
 		slic_debug = debug;
 
diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c
index 8add64b..ba199ff 100644
--- a/drivers/staging/sm7xxfb/sm7xxfb.c
+++ b/drivers/staging/sm7xxfb/sm7xxfb.c
@@ -130,7 +130,8 @@
 	for (i = 0; i < ARRAY_SIZE(vesa_mode_table); i++) {
 		if (strstr(options, vesa_mode_table[i].index)) {
 			smtc_scr_info.lfb_width  = vesa_mode_table[i].lfb_width;
-			smtc_scr_info.lfb_height = vesa_mode_table[i].lfb_height;
+			smtc_scr_info.lfb_height =
+						vesa_mode_table[i].lfb_height;
 			smtc_scr_info.lfb_depth  = vesa_mode_table[i].lfb_depth;
 			return 0;
 		}
@@ -259,8 +260,7 @@
 			if (sfb->fb.var.bits_per_pixel == 16) {
 				u32 *pal = sfb->fb.pseudo_palette;
 				val = chan_to_field(red, &sfb->fb.var.red);
-				val |= chan_to_field(green, \
-						&sfb->fb.var.green);
+				val |= chan_to_field(green, &sfb->fb.var.green);
 				val |= chan_to_field(blue, &sfb->fb.var.blue);
 #ifdef __BIG_ENDIAN
 				pal[regno] =
@@ -274,8 +274,7 @@
 			} else {
 				u32 *pal = sfb->fb.pseudo_palette;
 				val = chan_to_field(red, &sfb->fb.var.red);
-				val |= chan_to_field(green, \
-						&sfb->fb.var.green);
+				val |= chan_to_field(green, &sfb->fb.var.green);
 				val |= chan_to_field(blue, &sfb->fb.var.blue);
 #ifdef __BIG_ENDIAN
 				val =
@@ -508,9 +507,9 @@
 
 			/* init SEQ register SR30 - SR75 */
 			for (i = 0; i < SIZE_SR30_SR75; i++)
-				if (((i + 0x30) != 0x62) \
-					&& ((i + 0x30) != 0x6a) \
-					&& ((i + 0x30) != 0x6b))
+				if ((i + 0x30) != 0x62 &&
+				    (i + 0x30) != 0x6a &&
+				    (i + 0x30) != 0x6b)
 					smtc_seqw(i + 0x30,
 						VGAMode[j].Init_SR30_SR75[i]);
 
@@ -933,7 +932,6 @@
 	struct smtcfb_info *sfb;
 
 	sfb = pci_get_drvdata(pdev);
-	pci_set_drvdata(pdev, NULL);
 	smtc_unmap_smem(sfb);
 	smtc_unmap_mmio(sfb);
 	unregister_framebuffer(&sfb->fb);
diff --git a/drivers/staging/speakup/Kconfig b/drivers/staging/speakup/Kconfig
index 8c3e7a6..efd6f45 100644
--- a/drivers/staging/speakup/Kconfig
+++ b/drivers/staging/speakup/Kconfig
@@ -51,6 +51,7 @@
 
 config SPEAKUP_SYNTH_ACNTPC
 	tristate "Accent PC synthesizer support"
+	depends on ISA || COMPILE_TEST
 	---help---
 		This is the Speakup driver for the accent pc
 		synthesizer.  You can say y to build it into the kernel,
@@ -102,6 +103,7 @@
 
 config SPEAKUP_SYNTH_DECPC
 	depends on m
+	depends on ISA || COMPILE_TEST
 	tristate "DECtalk PC (big ISA card) synthesizer support"
 	---help---
 
@@ -124,6 +126,7 @@
 
 config SPEAKUP_SYNTH_DTLK
 	tristate "DoubleTalk PC synthesizer support"
+	depends on ISA || COMPILE_TEST
 	---help---
 
 		This is the Speakup driver for the internal DoubleTalk
@@ -134,6 +137,7 @@
 
 config SPEAKUP_SYNTH_KEYPC
 	tristate "Keynote Gold PC synthesizer support"
+	depends on ISA || COMPILE_TEST
 	---help---
 
 		This is the Speakup driver for the Keynote Gold
diff --git a/drivers/staging/speakup/kobjects.c b/drivers/staging/speakup/kobjects.c
index 51bdea3..e2f597e 100644
--- a/drivers/staging/speakup/kobjects.c
+++ b/drivers/staging/speakup/kobjects.c
@@ -586,6 +586,25 @@
 EXPORT_SYMBOL_GPL(spk_var_show);
 
 /*
+ * Used to reset either default_pitch or default_vol.
+ */
+static inline void spk_reset_default_value(char *header_name,
+					int *synth_default_value, int idx)
+{
+	struct st_var_header *param;
+
+	if (synth && synth_default_value) {
+		param = spk_var_header_by_name(header_name);
+		if (param)  {
+			spk_set_num_var(synth_default_value[idx],
+					param, E_NEW_DEFAULT);
+			spk_set_num_var(0, param, E_DEFAULT);
+			pr_info("%s reset to default value\n", param->name);
+		}
+	}
+}
+
+/*
  * This function is called when a user echos a value to one of the
  * variable parameters.
  */
@@ -597,7 +616,7 @@
 	int len;
 	char *cp;
 	struct var_t *var_data;
-	int value;
+	long value;
 	unsigned long flags;
 
 	param = spk_var_header_by_name(attr->attr.name);
@@ -619,61 +638,54 @@
 			len = E_INC;
 		else
 			len = E_SET;
-		value = simple_strtol(cp, NULL, 10);
-		ret = spk_set_num_var(value, param, len);
+		if (kstrtol(cp, 10, &value) == 0)
+			ret = spk_set_num_var(value, param, len);
+		else
+			pr_warn("overflow or parsing error has occured");
 		if (ret == -ERANGE) {
 			var_data = param->data;
 			pr_warn("value for %s out of range, expect %d to %d\n",
-				attr->attr.name,
+				param->name,
 				var_data->u.n.low, var_data->u.n.high);
 		}
+
+	       /*
+		* If voice was just changed, we might need to reset our default
+		* pitch and volume.
+		*/
+		if (param->var_id == VOICE && synth &&
+		    (ret == 0 || ret == -ERESTART)) {
+			var_data = param->data;
+			value = var_data->u.n.value;
+			spk_reset_default_value("pitch", synth->default_pitch,
+				value);
+			spk_reset_default_value("vol", synth->default_vol,
+				value);
+		}
 		break;
 	case VAR_STRING:
-		len = strlen(buf);
-		if ((len >= 1) && (buf[len - 1] == '\n'))
+		len = strlen(cp);
+		if ((len >= 1) && (cp[len - 1] == '\n'))
 			--len;
-		if ((len >= 2) && (buf[0] == '"') && (buf[len - 1] == '"')) {
-			++buf;
+		if ((len >= 2) && (cp[0] == '"') && (cp[len - 1] == '"')) {
+			++cp;
 			len -= 2;
 		}
-		cp = (char *) buf;
 		cp[len] = '\0';
-		ret = spk_set_string_var(buf, param, len);
+		ret = spk_set_string_var(cp, param, len);
 		if (ret == -E2BIG)
 			pr_warn("value too long for %s\n",
-					attr->attr.name);
+					param->name);
 		break;
 	default:
 		pr_warn("%s unknown type %d\n",
 			param->name, (int)param->var_type);
 	break;
 	}
-	/*
-	 * If voice was just changed, we might need to reset our default
-	 * pitch and volume.
-	 */
-	if (strcmp(attr->attr.name, "voice") == 0) {
-		if (synth && synth->default_pitch) {
-			param = spk_var_header_by_name("pitch");
-			if (param)  {
-				spk_set_num_var(synth->default_pitch[value],
-						param, E_NEW_DEFAULT);
-				spk_set_num_var(0, param, E_DEFAULT);
-			}
-		}
-		if (synth && synth->default_vol) {
-			param = spk_var_header_by_name("vol");
-			if (param)  {
-				spk_set_num_var(synth->default_vol[value],
-						param, E_NEW_DEFAULT);
-				spk_set_num_var(0, param, E_DEFAULT);
-			}
-		}
-	}
 	spin_unlock_irqrestore(&speakup_info.spinlock, flags);
 
 	if (ret == -ERESTART)
-		pr_info("%s reset to default value\n", attr->attr.name);
+		pr_info("%s reset to default value\n", param->name);
 	return count;
 }
 EXPORT_SYMBOL_GPL(spk_var_store);
diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c
index 14079c4..47502fa 100644
--- a/drivers/staging/speakup/main.c
+++ b/drivers/staging/speakup/main.c
@@ -90,7 +90,7 @@
 	{"repeats", "()", CH_RPT},
 	{"extended numeric", "", B_EXNUM},
 	{"symbols", "", B_SYM},
-	{0, 0}
+	{NULL, NULL}
 };
 
 static char mark_cut_flag;
diff --git a/drivers/staging/speakup/speakup_acntpc.c b/drivers/staging/speakup/speakup_acntpc.c
index 80141ac..1c8a7f4 100644
--- a/drivers/staging/speakup/speakup_acntpc.c
+++ b/drivers/staging/speakup/speakup_acntpc.c
@@ -223,7 +223,7 @@
 		if (ch == '\n')
 			ch = PROCSPEECH;
 		outb_p(ch, speakup_info.port_tts);
-		if (jiffies >= jiff_max && ch == SPACE) {
+		if (time_after_eq(jiffies, jiff_max) && ch == SPACE) {
 			timeout = SPK_XMITR_TIMEOUT;
 			while (synth_writable()) {
 				if (!--timeout)
diff --git a/drivers/staging/speakup/speakup_apollo.c b/drivers/staging/speakup/speakup_apollo.c
index 95d3132..70cf159 100644
--- a/drivers/staging/speakup/speakup_apollo.c
+++ b/drivers/staging/speakup/speakup_apollo.c
@@ -179,7 +179,7 @@
 			schedule_timeout(msecs_to_jiffies(full_time_val));
 			continue;
 		}
-		if ((jiffies >= jiff_max) && (ch == SPACE)) {
+		if (time_after_eq(jiffies, jiff_max) && (ch == SPACE)) {
 			spin_lock_irqsave(&speakup_info.spinlock, flags);
 			jiffy_delta_val = jiffy_delta->u.n.value;
 			full_time_val = full_time->u.n.value;
diff --git a/drivers/staging/speakup/speakup_audptr.c b/drivers/staging/speakup/speakup_audptr.c
index 3508aee..61a3cee 100644
--- a/drivers/staging/speakup/speakup_audptr.c
+++ b/drivers/staging/speakup/speakup_audptr.c
@@ -39,7 +39,7 @@
 	{ RATE, .u.n = {"\x05[r%d]", 10, 0, 20, 100, -10, NULL } },
 	{ PITCH, .u.n = {"\x05[f%d]", 80, 39, 4500, 0, 0, NULL } },
 	{ VOL, .u.n = {"\x05[g%d]", 21, 0, 40, 0, 0, NULL } },
-	{ TONE, .u.n = {"\x05[s%d]", 9, 0, 63, 0, 0, 0 } },
+	{ TONE, .u.n = {"\x05[s%d]", 9, 0, 63, 0, 0, NULL } },
 	{ PUNCT, .u.n = {"\x05[A%c]", 0, 0, 3, 0, 0, "nmsa" } },
 	{ DIRECT, .u.n = {NULL, 0, 0, 1, 0, 0, NULL } },
 	V_LAST_VAR
diff --git a/drivers/staging/speakup/varhandlers.c b/drivers/staging/speakup/varhandlers.c
index 9aa2a78..445a3fd 100644
--- a/drivers/staging/speakup/varhandlers.c
+++ b/drivers/staging/speakup/varhandlers.c
@@ -46,7 +46,7 @@
 	{ "direct", DIRECT, VAR_NUM, NULL, NULL },
 };
 
-static struct st_var_header *var_ptrs[MAXVARS] = { 0, 0, 0 };
+static struct st_var_header *var_ptrs[MAXVARS] = { NULL, NULL, NULL };
 
 static struct punc_var_t punc_vars[] = {
 	{ PUNC_SOME, 1 },
@@ -280,7 +280,7 @@
 	if (!cp)
 		cp = spk_punc_info[which].value;
 	else {
-		for ( ; *cp; cp++) {
+		for (; *cp; cp++) {
 			if (*cp < SPACE)
 				break;
 			if (mask < PUNC) {
@@ -294,11 +294,11 @@
 		cp = (u_char *)input;
 	}
 	if (how&2) {
-		for ( ; *cp; cp++)
+		for (; *cp; cp++)
 			if (*cp > SPACE)
 				spk_chartab[*cp] |= mask;
 	} else {
-		for ( ; *cp; cp++)
+		for (; *cp; cp++)
 			if (*cp > SPACE)
 				spk_chartab[*cp] &= ~mask;
 	}
diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
index 386362c..28b3930 100644
--- a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
+++ b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
@@ -911,8 +911,6 @@
 
 	rmi4_data->input_dev = input_allocate_device();
 	if (rmi4_data->input_dev == NULL) {
-		dev_err(&client->dev, "%s:input device alloc failed\n",
-						__func__);
 		retval = -ENOMEM;
 		goto err_input;
 	}
diff --git a/drivers/staging/tidspbridge/rmgr/dspdrv.c b/drivers/staging/tidspbridge/rmgr/dspdrv.c
index d460f58..012e4a3 100644
--- a/drivers/staging/tidspbridge/rmgr/dspdrv.c
+++ b/drivers/staging/tidspbridge/rmgr/dspdrv.c
@@ -36,7 +36,7 @@
 
 /*
  *  ======== dsp_init ========
- *  	Allocates bridge resources. Loads a base image onto DSP, if specified.
+ *  Allocates bridge resources. Loads a base image onto DSP, if specified.
  */
 u32 dsp_init(u32 *init_status)
 {
@@ -106,7 +106,7 @@
 
 /*
  *  ======== dsp_deinit ========
- *  	Frees the resources allocated for bridge.
+ *  Frees the resources allocated for bridge.
  */
 bool dsp_deinit(u32 device_context)
 {
diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c
index d8957a5..76a1ff0 100644
--- a/drivers/staging/usbip/stub_dev.c
+++ b/drivers/staging/usbip/stub_dev.c
@@ -357,8 +357,9 @@
 	busid_priv = get_busid_priv(udev_busid);
 	if (!busid_priv || (busid_priv->status == STUB_BUSID_REMOV) ||
 	    (busid_priv->status == STUB_BUSID_OTHER)) {
-		dev_info(&interface->dev, "%s is not in match_busid table... "
-			 "skip!\n", udev_busid);
+		dev_info(&interface->dev,
+			"%s is not in match_busid table... skip!\n",
+			udev_busid);
 
 		/*
 		 * Return value should be ENODEV or ENOXIO to continue trying
@@ -375,8 +376,10 @@
 	}
 
 	if (!strcmp(udev->bus->bus_name, "vhci_hcd")) {
-		dev_dbg(&udev->dev, "%s is attached on vhci_hcd... skip!\n",
-			 udev_busid);
+		dev_dbg(&udev->dev,
+			"%s is attached on vhci_hcd... skip!\n",
+			udev_busid);
+
 		return -ENODEV;
 	}
 
@@ -386,10 +389,10 @@
 			return -ENODEV;
 
 		busid_priv->interf_count++;
-		dev_info(&interface->dev, "usbip-host: register new interface "
-			 "(bus %u dev %u ifn %u)\n",
-			 udev->bus->busnum, udev->devnum,
-			 interface->cur_altsetting->desc.bInterfaceNumber);
+		dev_info(&interface->dev,
+			"usbip-host: register new interface (bus %u dev %u ifn %u)\n",
+			udev->bus->busnum, udev->devnum,
+			interface->cur_altsetting->desc.bInterfaceNumber);
 
 		/* set private data to usb_interface */
 		usb_set_intfdata(interface, sdev);
@@ -412,9 +415,10 @@
 	if (!sdev)
 		return -ENOMEM;
 
-	dev_info(&interface->dev, "usbip-host: register new device "
-		 "(bus %u dev %u ifn %u)\n", udev->bus->busnum, udev->devnum,
-		 interface->cur_altsetting->desc.bInterfaceNumber);
+	dev_info(&interface->dev,
+		"usbip-host: register new device (bus %u dev %u ifn %u)\n",
+		udev->bus->busnum, udev->devnum,
+		interface->cur_altsetting->desc.bInterfaceNumber);
 
 	busid_priv->interf_count = 0;
 	busid_priv->shutdown_busid = 0;
diff --git a/drivers/staging/usbip/stub_main.c b/drivers/staging/usbip/stub_main.c
index 33027cc..baf857f 100644
--- a/drivers/staging/usbip/stub_main.c
+++ b/drivers/staging/usbip/stub_main.c
@@ -255,14 +255,14 @@
 	}
 
 	ret = usb_register(&stub_driver);
-	if (ret < 0) {
+	if (ret) {
 		pr_err("usb_register failed %d\n", ret);
 		goto err_usb_register;
 	}
 
 	ret = driver_create_file(&stub_driver.drvwrap.driver,
 				 &driver_attr_match_busid);
-	if (ret < 0) {
+	if (ret) {
 		pr_err("driver_create_file failed\n");
 		goto err_create_file;
 	}
diff --git a/drivers/staging/usbip/userspace/configure.ac b/drivers/staging/usbip/userspace/configure.ac
index 2be4060..0ee5d92 100644
--- a/drivers/staging/usbip/userspace/configure.ac
+++ b/drivers/staging/usbip/userspace/configure.ac
@@ -70,7 +70,6 @@
 		       [AC_MSG_RESULT([not found]); exit 1])
 	     else
 		     AC_MSG_RESULT([no]);
-		     LIBS="$saved_LIBS"
 	     fi],
 	    dnl [ACTION-IF-NOT-GIVEN]
 	    [AC_MSG_RESULT([(default)])
diff --git a/drivers/staging/usbip/userspace/doc/usbip.8 b/drivers/staging/usbip/userspace/doc/usbip.8
index ccdadc8..a6097be 100644
--- a/drivers/staging/usbip/userspace/doc/usbip.8
+++ b/drivers/staging/usbip/userspace/doc/usbip.8
@@ -3,7 +3,7 @@
 usbip \- manage USB/IP devices
 .SH SYNOPSIS
 .B usbip
-[\foptions\R] <\fIcommand\fR> <\fIargs\fR>
+[\fIoptions\fR] <\fIcommand\fR> <\fIargs\fR>
 
 .SH DESCRIPTION
 On a USB/IP server, devices can be listed, bound, and unbound using
@@ -23,6 +23,12 @@
 Log to syslog.
 .PP
 
+.HP
+\fB\-\-tcp-port PORT\fR
+.IP
+Connect to PORT on remote host (used for attach and list --remote).
+.PP
+
 .SH COMMANDS
 .HP
 \fBversion\fR
diff --git a/drivers/staging/usbip/userspace/doc/usbipd.8 b/drivers/staging/usbip/userspace/doc/usbipd.8
index d896936..ac4635d 100644
--- a/drivers/staging/usbip/userspace/doc/usbipd.8
+++ b/drivers/staging/usbip/userspace/doc/usbipd.8
@@ -14,10 +14,22 @@
 before usbipd makes them available to other hosts.
 
 The daemon accepts connections from USB/IP clients
-on TCP port 3240.
+on TCP port 3240 by default.
 
 .SH OPTIONS
 .HP
+\fB\-4\fR, \fB\-\-ipv4\fR
+.IP
+Bind to IPv4. Default is both.
+.PP
+
+.HP
+\fB\-6\fR, \fB\-\-ipv6\fR
+.IP
+Bind to IPv6. Default is both.
+.PP
+
+.HP
 \fB\-D\fR, \fB\-\-daemon\fR
 .IP
 Run as a daemon process.
@@ -29,6 +41,19 @@
 Print debugging information.
 .PP
 
+.HP
+\fB\-PFILE\fR, \fB\-\-pid FILE\fR
+.IP
+Write process id to FILE.
+.br
+If no FILE specified, use /var/run/usbipd.pid
+.PP
+
+\fB\-tPORT\fR, \fB\-\-tcp\-port PORT\fR
+.IP
+Listen on TCP/IP port PORT.
+.PP
+
 \fB\-h\fR, \fB\-\-help\fR
 .IP
 Print the program help message and exit.
diff --git a/drivers/staging/usbip/userspace/src/usbip_network.c b/drivers/staging/usbip/userspace/src/usbip_network.c
index c39a07f..b4c37e7 100644
--- a/drivers/staging/usbip/userspace/src/usbip_network.c
+++ b/drivers/staging/usbip/userspace/src/usbip_network.c
@@ -25,6 +25,10 @@
 #include <netinet/tcp.h>
 #include <unistd.h>
 
+#ifdef HAVE_LIBWRAP
+#include <tcpd.h>
+#endif
+
 #include "usbip_common.h"
 #include "usbip_network.h"
 
@@ -239,6 +243,18 @@
 	return ret;
 }
 
+int usbip_net_set_v6only(int sockfd)
+{
+	const int val = 1;
+	int ret;
+
+	ret = setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val));
+	if (ret < 0)
+		dbg("setsockopt: IPV6_V6ONLY");
+
+	return ret;
+}
+
 /*
  * IPv6 Ready
  */
diff --git a/drivers/staging/usbip/userspace/src/usbip_network.h b/drivers/staging/usbip/userspace/src/usbip_network.h
index 2d0e427..f19ae19 100644
--- a/drivers/staging/usbip/userspace/src/usbip_network.h
+++ b/drivers/staging/usbip/userspace/src/usbip_network.h
@@ -180,6 +180,7 @@
 int usbip_net_set_reuseaddr(int sockfd);
 int usbip_net_set_nodelay(int sockfd);
 int usbip_net_set_keepalive(int sockfd);
+int usbip_net_set_v6only(int sockfd);
 int usbip_net_tcp_connect(char *hostname, char *port);
 
 #endif /* __USBIP_NETWORK_H */
diff --git a/drivers/staging/usbip/userspace/src/usbipd.c b/drivers/staging/usbip/userspace/src/usbipd.c
index 1c76cfd..7980f8b 100644
--- a/drivers/staging/usbip/userspace/src/usbipd.c
+++ b/drivers/staging/usbip/userspace/src/usbipd.c
@@ -56,6 +56,13 @@
 
 static const char usbipd_help_string[] =
 	"usage: usbipd [options]\n"
+	"\n"
+	"	-4, --ipv4\n"
+	"		Bind to IPv4. Default is both.\n"
+	"\n"
+	"	-6, --ipv6\n"
+	"		Bind to IPv6. Default is both.\n"
+	"\n"
 	"	-D, --daemon\n"
 	"		Run as a daemon process.\n"
 	"\n"
@@ -354,14 +361,15 @@
 	snprintf(buf, buf_size, "%s:%s", hbuf, sbuf);
 }
 
-static int listen_all_addrinfo(struct addrinfo *ai_head, int sockfdlist[])
+static int listen_all_addrinfo(struct addrinfo *ai_head, int sockfdlist[],
+			     int maxsockfd)
 {
 	struct addrinfo *ai;
 	int ret, nsockfd = 0;
 	const size_t ai_buf_size = NI_MAXHOST + NI_MAXSERV + 2;
 	char ai_buf[ai_buf_size];
 
-	for (ai = ai_head; ai && nsockfd < MAXSOCKFD; ai = ai->ai_next) {
+	for (ai = ai_head; ai && nsockfd < maxsockfd; ai = ai->ai_next) {
 		int sock;
 		addrinfo_to_text(ai, ai_buf, ai_buf_size);
 		dbg("opening %s", ai_buf);
@@ -374,6 +382,9 @@
 
 		usbip_net_set_reuseaddr(sock);
 		usbip_net_set_nodelay(sock);
+		/* We use seperate sockets for IPv4 and IPv6
+		 * (see do_standalone_mode()) */
+		usbip_net_set_v6only(sock);
 
 		if (sock >= FD_SETSIZE) {
 			err("FD_SETSIZE: %s: sock=%d, max=%d",
@@ -402,11 +413,6 @@
 		sockfdlist[nsockfd++] = sock;
 	}
 
-	if (nsockfd == 0)
-		return -1;
-
-	dbg("listening on %d address%s", nsockfd, (nsockfd == 1) ? "" : "es");
-
 	return nsockfd;
 }
 
@@ -473,11 +479,11 @@
 	}
 }
 
-static int do_standalone_mode(int daemonize)
+static int do_standalone_mode(int daemonize, int ipv4, int ipv6)
 {
 	struct addrinfo *ai_head;
 	int sockfdlist[MAXSOCKFD];
-	int nsockfd;
+	int nsockfd, family;
 	int i, terminate;
 	struct pollfd *fds;
 	struct timespec timeout;
@@ -501,21 +507,36 @@
 	set_signal();
 	write_pid_file();
 
-	ai_head = do_getaddrinfo(NULL, PF_UNSPEC);
+	info("starting " PROGNAME " (%s)", usbip_version_string);
+
+	/*
+	 * To suppress warnings on systems with bindv6only disabled
+	 * (default), we use seperate sockets for IPv6 and IPv4 and set
+	 * IPV6_V6ONLY on the IPv6 sockets.
+	 */
+	if (ipv4 && ipv6)
+		family = AF_UNSPEC;
+	else if (ipv4)
+		family = AF_INET;
+	else
+		family = AF_INET6;
+
+	ai_head = do_getaddrinfo(NULL, family);
 	if (!ai_head) {
 		usbip_host_driver_close();
 		return -1;
 	}
-
-	info("starting " PROGNAME " (%s)", usbip_version_string);
-
-	nsockfd = listen_all_addrinfo(ai_head, sockfdlist);
+	nsockfd = listen_all_addrinfo(ai_head, sockfdlist,
+		sizeof(sockfdlist) / sizeof(*sockfdlist));
+	freeaddrinfo(ai_head);
 	if (nsockfd <= 0) {
 		err("failed to open a listening socket");
-		freeaddrinfo(ai_head);
 		usbip_host_driver_close();
 		return -1;
 	}
+
+	dbg("listening on %d address%s", nsockfd, (nsockfd == 1) ? "" : "es");
+
 	fds = calloc(nsockfd, sizeof(struct pollfd));
 	for (i = 0; i < nsockfd; i++) {
 		fds[i].fd = sockfdlist[i];
@@ -551,7 +572,6 @@
 
 	info("shutting down " PROGNAME);
 	free(fds);
-	freeaddrinfo(ai_head);
 	usbip_host_driver_close();
 
 	return 0;
@@ -560,6 +580,9 @@
 int main(int argc, char *argv[])
 {
 	static const struct option longopts[] = {
+		{ "ipv4",     no_argument,       NULL, '4' },
+		{ "ipv6",     no_argument,       NULL, '6' },
+		{ "daemon",   no_argument,       NULL, 'D' },
 		{ "daemon",   no_argument,       NULL, 'D' },
 		{ "debug",    no_argument,       NULL, 'd' },
 		{ "pid",      optional_argument, NULL, 'P' },
@@ -576,6 +599,7 @@
 	} cmd;
 
 	int daemonize = 0;
+	int ipv4 = 0, ipv6 = 0;
 	int opt, rc = -1;
 	pid_file = NULL;
 
@@ -587,12 +611,18 @@
 
 	cmd = cmd_standalone_mode;
 	for (;;) {
-		opt = getopt_long(argc, argv, "DdP::t:hv", longopts, NULL);
+		opt = getopt_long(argc, argv, "46DdP::t:hv", longopts, NULL);
 
 		if (opt == -1)
 			break;
 
 		switch (opt) {
+		case '4':
+			ipv4 = 1;
+			break;
+		case '6':
+			ipv6 = 1;
+			break;
 		case 'D':
 			daemonize = 1;
 			break;
@@ -618,9 +648,12 @@
 		}
 	}
 
+	if (!ipv4 && !ipv6)
+		ipv4 = ipv6 = 1;
+
 	switch (cmd) {
 	case cmd_standalone_mode:
-		rc = do_standalone_mode(daemonize);
+		rc = do_standalone_mode(daemonize, ipv4, ipv6);
 		remove_pid_file();
 		break;
 	case cmd_version:
diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c
index d7974cb..e810ad5 100644
--- a/drivers/staging/usbip/vhci_hcd.c
+++ b/drivers/staging/usbip/vhci_hcd.c
@@ -999,12 +999,6 @@
 
 	usbip_dbg_vhci_hc("name %s id %d\n", pdev->name, pdev->id);
 
-	/* will be removed */
-	if (pdev->dev.dma_mask) {
-		dev_info(&pdev->dev, "vhci_hcd DMA not supported\n");
-		return -EINVAL;
-	}
-
 	/*
 	 * Allocate and initialize hcd.
 	 * Our private data is also allocated automatically.
@@ -1146,11 +1140,11 @@
 		return -ENODEV;
 
 	ret = platform_driver_register(&vhci_driver);
-	if (ret < 0)
+	if (ret)
 		goto err_driver_register;
 
 	ret = platform_device_register(&the_pdev);
-	if (ret < 0)
+	if (ret)
 		goto err_platform_device_register;
 
 	pr_info(DRIVER_DESC " v" USBIP_VERSION "\n");
diff --git a/drivers/staging/vt6655/80211mgr.c b/drivers/staging/vt6655/80211mgr.c
index 76c8490..7949d58 100644
--- a/drivers/staging/vt6655/80211mgr.c
+++ b/drivers/staging/vt6655/80211mgr.c
@@ -165,9 +165,8 @@
 			break;
 
 		case WLAN_EID_RSN:
-			if (pFrame->pRSN == NULL) {
+			if (pFrame->pRSN == NULL)
 				pFrame->pRSN = (PWLAN_IE_RSN)pItem;
-			}
 			break;
 		case WLAN_EID_RSN_WPA:
 			if (pFrame->pRSNWPA == NULL) {
@@ -382,9 +381,8 @@
 			break;
 
 		case WLAN_EID_RSN:
-			if (pFrame->pRSN == NULL) {
+			if (pFrame->pRSN == NULL)
 				pFrame->pRSN = (PWLAN_IE_RSN)pItem;
-			}
 			break;
 		case WLAN_EID_RSN_WPA:
 			if (pFrame->pRSNWPA == NULL) {
@@ -556,9 +554,8 @@
 			break;
 
 		case WLAN_EID_RSN:
-			if (pFrame->pRSN == NULL) {
+			if (pFrame->pRSN == NULL)
 				pFrame->pRSN = (PWLAN_IE_RSN)pItem;
-			}
 			break;
 		case WLAN_EID_RSN_WPA:
 			if (pFrame->pRSNWPA == NULL) {
@@ -742,9 +739,8 @@
 			break;
 
 		case WLAN_EID_RSN:
-			if (pFrame->pRSN == NULL) {
+			if (pFrame->pRSN == NULL)
 				pFrame->pRSN = (PWLAN_IE_RSN)pItem;
-			}
 			break;
 		case WLAN_EID_RSN_WPA:
 			if (pFrame->pRSNWPA == NULL) {
@@ -858,9 +854,9 @@
 	pItem = (PWLAN_IE)(WLAN_HDR_A3_DATA_PTR(&(pFrame->pHdr->sA3))
 			   + WLAN_AUTHEN_OFF_CHALLENGE);
 
-	if ((((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len)) && (pItem->byElementID == WLAN_EID_CHALLENGE)) {
+	if (((unsigned char *)pItem) < (pFrame->pBuf + pFrame->len) &&
+	    pItem->byElementID == WLAN_EID_CHALLENGE)
 		pFrame->pChallenge = (PWLAN_IE_CHALLENGE)pItem;
-	}
 
 	return;
 }
diff --git a/drivers/staging/vt6655/aes_ccmp.c b/drivers/staging/vt6655/aes_ccmp.c
index fc056fc..82b0bd1 100644
--- a/drivers/staging/vt6655/aes_ccmp.c
+++ b/drivers/staging/vt6655/aes_ccmp.c
@@ -46,7 +46,7 @@
  * SBOX Table
  */
 
-unsigned char sbox_table[256] =
+static unsigned char sbox_table[256] =
 {
 	0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
 	0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
@@ -66,7 +66,7 @@
 	0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
 };
 
-unsigned char dot2_table[256] = {
+static unsigned char dot2_table[256] = {
 	0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
 	0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
 	0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
@@ -85,7 +85,7 @@
 	0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5
 };
 
-unsigned char dot3_table[256] = {
+static unsigned char dot3_table[256] = {
 	0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11,
 	0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21,
 	0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
@@ -110,7 +110,7 @@
 
 /*---------------------  Export Functions  --------------------------*/
 
-void xor_128(unsigned char *a, unsigned char *b, unsigned char *out)
+static void xor_128(unsigned char *a, unsigned char *b, unsigned char *out)
 {
 	unsigned long *dwPtrA = (unsigned long *)a;
 	unsigned long *dwPtrB = (unsigned long *)b;
@@ -122,7 +122,7 @@
 	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
 }
 
-void xor_32(unsigned char *a, unsigned char *b, unsigned char *out)
+static void xor_32(unsigned char *a, unsigned char *b, unsigned char *out)
 {
 	unsigned long *dwPtrA = (unsigned long *)a;
 	unsigned long *dwPtrB = (unsigned long *)b;
@@ -131,7 +131,7 @@
 	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
 }
 
-void AddRoundKey(unsigned char *key, int round)
+static void AddRoundKey(unsigned char *key, int round)
 {
 	unsigned char sbox_key[4];
 	unsigned char rcon_table[10] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
@@ -149,7 +149,7 @@
 	xor_32(&key[12], &key[8], &key[12]);
 }
 
-void SubBytes(unsigned char *in, unsigned char *out)
+static void SubBytes(unsigned char *in, unsigned char *out)
 {
 	int i;
 
@@ -158,7 +158,7 @@
 	}
 }
 
-void ShiftRows(unsigned char *in, unsigned char *out)
+static void ShiftRows(unsigned char *in, unsigned char *out)
 {
 	out[0]  = in[0];
 	out[1]  = in[5];
@@ -178,7 +178,7 @@
 	out[15] = in[11];
 }
 
-void MixColumns(unsigned char *in, unsigned char *out)
+static void MixColumns(unsigned char *in, unsigned char *out)
 {
 	out[0] = dot2_table[in[0]] ^ dot3_table[in[1]] ^ in[2] ^ in[3];
 	out[1] = in[0] ^ dot2_table[in[1]] ^ dot3_table[in[2]] ^ in[3];
@@ -186,7 +186,7 @@
 	out[3] = dot3_table[in[0]] ^ in[1] ^ in[2] ^ dot2_table[in[3]];
 }
 
-void AESv128(unsigned char *key, unsigned char *data, unsigned char *ciphertext)
+static void AESv128(unsigned char *key, unsigned char *data, unsigned char *ciphertext)
 {
 	int  i;
 	int  round;
diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c
index c26418d..959568a 100644
--- a/drivers/staging/vt6655/baseband.c
+++ b/drivers/staging/vt6655/baseband.c
@@ -2434,13 +2434,12 @@
 
 	BBbReadEmbedded(pDevice->PortOffset, 0x0A, &byBBRxConf);//CR10
 	// patch for 3253B0 Baseband with Cardbus module
-	if (byData == pDevice->abyBBVGA[0]) {
+	if (byData == pDevice->abyBBVGA[0])
 		byBBRxConf |= 0x20;//0010 0000
-	} else if (pDevice->bShortSlotTime) {
+	else if (pDevice->bShortSlotTime)
 		byBBRxConf &= 0xDF;//1101 1111
-	} else {
+	else
 		byBBRxConf |= 0x20;//0010 0000
-	}
 	pDevice->byBBVGACurrent = byData;
 	BBbWriteEmbedded(pDevice->PortOffset, 0x0A, byBBRxConf);//CR10
 }
diff --git a/drivers/staging/vt6655/bssdb.c b/drivers/staging/vt6655/bssdb.c
index f983915..a23b591 100644
--- a/drivers/staging/vt6655/bssdb.c
+++ b/drivers/staging/vt6655/bssdb.c
@@ -148,7 +148,8 @@
 			if (pDevice->bLinkPass == false) pCurrBSS->bSelected = false;
 			if ((pCurrBSS->bActive) &&
 			    (pCurrBSS->bSelected == false)) {
-				if (!compare_ether_addr(pCurrBSS->abyBSSID, pbyBSSID)) {
+				if (ether_addr_equal(pCurrBSS->abyBSSID,
+						     pbyBSSID)) {
 					if (pSSID != NULL) {
 						// compare ssid
 						if (!memcmp(pSSID->abySSID,
@@ -275,7 +276,8 @@
 	for (ii = 0; ii < MAX_BSS_NUM; ii++) {
 		if (bKeepCurrBSSID) {
 			if (pMgmt->sBSSList[ii].bActive &&
-			    !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, pMgmt->abyCurrBSSID)) {
+			    ether_addr_equal(pMgmt->sBSSList[ii].abyBSSID,
+					     pMgmt->abyCurrBSSID)) {
 				// bKeepCurrBSSID = false;
 				continue;
 			}
@@ -318,7 +320,7 @@
 	for (ii = 0; ii < MAX_BSS_NUM; ii++) {
 		pBSSList = &(pMgmt->sBSSList[ii]);
 		if (pBSSList->bActive) {
-			if (!compare_ether_addr(pBSSList->abyBSSID, abyBSSID)) {
+			if (ether_addr_equal(pBSSList->abyBSSID, abyBSSID)) {
 				if (pSSID->len == ((PWLAN_IE_SSID)pBSSList->abySSID)->len) {
 					if (memcmp(pSSID->abySSID,
 						   ((PWLAN_IE_SSID)pBSSList->abySSID)->abySSID,
@@ -733,7 +735,8 @@
 	// Index = 0 reserved for AP Node
 	for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) {
 		if (pMgmt->sNodeDBTable[ii].bActive) {
-			if (!compare_ether_addr(abyDstAddr, pMgmt->sNodeDBTable[ii].abyMACAddr)) {
+			if (ether_addr_equal(abyDstAddr,
+					     pMgmt->sNodeDBTable[ii].abyMACAddr)) {
 				*puNodeIndex = ii;
 				return true;
 			}
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index 7f36a71..e93fdc8 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -1153,10 +1153,6 @@
 		pci_release_regions(pDevice->pcid);
 	if (dev)
 		free_netdev(dev);
-
-	if (pDevice->pcid) {
-		pci_set_drvdata(pDevice->pcid, NULL);
-	}
 }
 
 static bool device_init_rings(PSDevice pDevice) {
diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c
index a9533f3..0ff51cb 100644
--- a/drivers/staging/vt6655/dpc.c
+++ b/drivers/staging/vt6655/dpc.c
@@ -172,9 +172,9 @@
 	};
 
 	pbyRxBuffer = (unsigned char *)(pbyRxBufferAddr + cbHeaderSize);
-	if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_Bridgetunnel[0])) {
+	if (ether_addr_equal(pbyRxBuffer, pDevice->abySNAP_Bridgetunnel)) {
 		cbHeaderSize += 6;
-	} else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) {
+	} else if (ether_addr_equal(pbyRxBuffer, pDevice->abySNAP_RFC1042)) {
 		cbHeaderSize += 6;
 		pwType = (unsigned short *)(pbyRxBufferAddr + cbHeaderSize);
 		if ((*pwType != TYPE_PKT_IPX) && (*pwType != cpu_to_le16(0xF380))) {
@@ -420,7 +420,8 @@
 	s_vGetDASA(skb->data+4, &cbHeaderSize, &pDevice->sRxEthHeader);
 
 	// filter packet send from myself
-	if (!compare_ether_addr((unsigned char *)&(pDevice->sRxEthHeader.abySrcAddr[0]), pDevice->abyCurrentNetAddr))
+	if (ether_addr_equal(pDevice->sRxEthHeader.abySrcAddr,
+			     pDevice->abyCurrentNetAddr))
 		return false;
 
 	if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) {
diff --git a/drivers/staging/vt6655/hostap.c b/drivers/staging/vt6655/hostap.c
index 8acff44..aab0012 100644
--- a/drivers/staging/vt6655/hostap.c
+++ b/drivers/staging/vt6655/hostap.c
@@ -720,7 +720,6 @@
  * Return Value:
  *
  */
-
 int vt6655_hostap_ioctl(PSDevice pDevice, struct iw_point *p)
 {
 	struct viawget_hostapd_param *param;
@@ -731,7 +730,7 @@
 	    p->length > VIAWGET_HOSTAPD_MAX_BUF_SIZE || !p->pointer)
 		return -EINVAL;
 
-	param = kmalloc((int)p->length, (int)GFP_KERNEL);
+	param = kmalloc((int)p->length, GFP_KERNEL);
 	if (param == NULL)
 		return -ENOMEM;
 
@@ -755,8 +754,8 @@
 		break;
 	case VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR:
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR \n");
-		return -EOPNOTSUPP;
-		break;
+		ret = -EOPNOTSUPP;
+		goto out;
 	case VIAWGET_HOSTAPD_FLUSH:
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_FLUSH \n");
 		spin_lock_irq(&pDevice->lock);
@@ -790,40 +789,36 @@
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_FLAGS_STA \n");
 		ret = hostap_set_flags_sta(pDevice, param);
 		break;
-
 	case VIAWGET_HOSTAPD_MLME:
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_MLME \n");
-		return -EOPNOTSUPP;
-
+		ret = -EOPNOTSUPP;
+		goto out;
 	case VIAWGET_HOSTAPD_SET_GENERIC_ELEMENT:
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_GENERIC_ELEMENT \n");
 		ret = hostap_set_generic_element(pDevice, param);
 		break;
-
 	case VIAWGET_HOSTAPD_SCAN_REQ:
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SCAN_REQ \n");
-		return -EOPNOTSUPP;
-
+		ret = -EOPNOTSUPP;
+		goto out;
 	case VIAWGET_HOSTAPD_STA_CLEAR_STATS:
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_STA_CLEAR_STATS \n");
-		return -EOPNOTSUPP;
-
+		ret = -EOPNOTSUPP;
+		goto out;
 	default:
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "vt6655_hostap_ioctl: unknown cmd=%d\n",
 			(int)param->cmd);
-		return -EOPNOTSUPP;
-		break;
+		ret = -EOPNOTSUPP;
+		goto out;
 	}
 
 	if ((ret == 0) && ap_ioctl) {
 		if (copy_to_user(p->pointer, param, p->length)) {
 			ret = -EFAULT;
-			goto out;
 		}
 	}
 
 out:
 	kfree(param);
-
 	return ret;
 }
diff --git a/drivers/staging/vt6655/iwctl.c b/drivers/staging/vt6655/iwctl.c
index 9de698e..4bff8aa 100644
--- a/drivers/staging/vt6655/iwctl.c
+++ b/drivers/staging/vt6655/iwctl.c
@@ -663,7 +663,8 @@
 			unsigned int ii, uSameBssidNum = 0;
 			for (ii = 0; ii < MAX_BSS_NUM; ii++) {
 				if (pMgmt->sBSSList[ii].bActive &&
-				    !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, pMgmt->abyDesireBSSID)) {
+				    ether_addr_equal(pMgmt->sBSSList[ii].abyBSSID,
+						     pMgmt->abyDesireBSSID)) {
 					uSameBssidNum++;
 				}
 			}
@@ -840,7 +841,8 @@
 					//         by means of judging if there are two same BSSID exist in list ?
 					for (ii = 0; ii < MAX_BSS_NUM; ii++) {
 						if (pMgmt->sBSSList[ii].bActive &&
-						    !compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID, pCurr->abyBSSID)) {
+						    ether_addr_equal(pMgmt->sBSSList[ii].abyBSSID,
+								     pCurr->abyBSSID)) {
 							uSameBssidNum++;
 						}
 					}
diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c
index 92b84b5..04c1304 100644
--- a/drivers/staging/vt6655/key.c
+++ b/drivers/staging/vt6655/key.c
@@ -141,7 +141,7 @@
 	*pKey = NULL;
 	for (i = 0; i < MAX_KEY_TABLE; i++) {
 		if ((pTable->KeyTable[i].bInUse == true) &&
-		    !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+		    ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
 			if (dwKeyIndex == 0xFFFFFFFF) {
 				if (pTable->KeyTable[i].PairwiseKey.bKeyValid == true) {
 					*pKey = &(pTable->KeyTable[i].PairwiseKey);
@@ -208,7 +208,7 @@
 			j = i;
 		}
 		if ((pTable->KeyTable[i].bInUse == true) &&
-		    !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+		    ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
 			// found table already exist
 			if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
 				// Pairwise key
@@ -385,7 +385,7 @@
 
 	for (i = 0; i < MAX_KEY_TABLE; i++) {
 		if ((pTable->KeyTable[i].bInUse == true) &&
-		    !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+		    ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
 			if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
 				pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
 				s_vCheckKeyTableValid(pTable, dwIoBase);
@@ -429,7 +429,7 @@
 
 	for (i = 0; i < MAX_KEY_TABLE; i++) {
 		if ((pTable->KeyTable[i].bInUse == true) &&
-		    !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+		    ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
 			pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
 			for (u = 0; u < MAX_GROUP_KEY; u++) {
 				pTable->KeyTable[i].GroupKey[u].bKeyValid = false;
@@ -512,7 +512,7 @@
 	*pKey = NULL;
 	for (i = 0; i < MAX_KEY_TABLE; i++) {
 		if ((pTable->KeyTable[i].bInUse == true) &&
-		    !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+		    ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
 			if (dwKeyType == PAIRWISE_KEY) {
 				if (pTable->KeyTable[i].PairwiseKey.bKeyValid == true) {
 					*pKey = &(pTable->KeyTable[i].PairwiseKey);
diff --git a/drivers/staging/vt6655/michael.h b/drivers/staging/vt6655/michael.h
index 0828d18..387d206 100644
--- a/drivers/staging/vt6655/michael.h
+++ b/drivers/staging/vt6655/michael.h
@@ -39,18 +39,18 @@
 
 void MIC_vUnInit(void);
 
-// Append bytes to the message to be MICed
+/* Append bytes to the message to be MICed */
 void MIC_vAppend(unsigned char *src, unsigned int nBytes);
 
-// Get the MIC result. Destination should accept 8 bytes of result.
-// This also resets the message to empty.
+/* Get the MIC result. Destination should accept 8 bytes of result. */
+/* This also resets the message to empty. */
 void MIC_vGetMIC(unsigned long *pdwL, unsigned long *pdwR);
 
 /*---------------------  Export Macros ------------------------------*/
 
-// Rotation functions on 32 bit values
+/* Rotation functions on 32 bit values */
 #define ROL32(A, n)							\
 	(((A) << (n)) | (((A)>>(32-(n)))  & ((1UL << (n)) - 1)))
 #define ROR32(A, n) ROL32((A), 32-(n))
 
-#endif //__MICHAEL_H__
+#endif /*__MICHAEL_H__ */
diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c
index 6948984..ce173cc 100644
--- a/drivers/staging/vt6655/rf.c
+++ b/drivers/staging/vt6655/rf.c
@@ -55,7 +55,7 @@
 
 /*---------------------  Static Variables  --------------------------*/
 
-const unsigned long dwAL2230InitTable[CB_AL2230_INIT_SEQ] = {
+static const unsigned long dwAL2230InitTable[CB_AL2230_INIT_SEQ] = {
 	0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
 	0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
 	0x01A00200+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
@@ -73,7 +73,7 @@
 	0x00580F00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW
 };
 
-const unsigned long dwAL2230ChannelTable0[CB_MAX_CHANNEL] = {
+static const unsigned long dwAL2230ChannelTable0[CB_MAX_CHANNEL] = {
 	0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz
 	0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz
 	0x03E79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz
@@ -90,7 +90,7 @@
 	0x03E7C000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW  // channel = 14, Tf = 2412M
 };
 
-const unsigned long dwAL2230ChannelTable1[CB_MAX_CHANNEL] = {
+static const unsigned long dwAL2230ChannelTable1[CB_MAX_CHANNEL] = {
 	0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz
 	0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz
 	0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz
@@ -107,7 +107,7 @@
 	0x06666100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW  // channel = 14, Tf = 2412M
 };
 
-unsigned long dwAL2230PowerTable[AL2230_PWR_IDX_LEN] = {
+static unsigned long dwAL2230PowerTable[AL2230_PWR_IDX_LEN] = {
 	0x04040900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
 	0x04041900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
 	0x04042900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
@@ -177,7 +177,7 @@
 //{{ RobertYu:20050104
 // 40MHz reference frequency
 // Need to Pull PLLON(PE3) low when writing channel registers through 3-wire.
-const unsigned long dwAL7230InitTable[CB_AL7230_INIT_SEQ] = {
+static const unsigned long dwAL7230InitTable[CB_AL7230_INIT_SEQ] = {
 	0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel1 // Need modify for 11a
 	0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel1 // Need modify for 11a
 	0x841FF200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 451FE2
@@ -200,7 +200,7 @@
 	0x1ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  // Need modify for 11a: 12BACF
 };
 
-const unsigned long dwAL7230InitTableAMode[CB_AL7230_INIT_SEQ] = {
+static const unsigned long dwAL7230InitTableAMode[CB_AL7230_INIT_SEQ] = {
 	0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel184 // Need modify for 11b/g
 	0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel184 // Need modify for 11b/g
 	0x451FE200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
@@ -219,7 +219,7 @@
 	0x12BACF00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  // Need modify for 11b/g
 };
 
-const unsigned long dwAL7230ChannelTable0[CB_MAX_CHANNEL] = {
+static const unsigned long dwAL7230ChannelTable0[CB_MAX_CHANNEL] = {
 	0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  1, Tf = 2412MHz
 	0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  2, Tf = 2417MHz
 	0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  3, Tf = 2422MHz
@@ -285,7 +285,7 @@
 	0x0FF61000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  // channel = 165, Tf = 5825MHz (56)
 };
 
-const unsigned long dwAL7230ChannelTable1[CB_MAX_CHANNEL] = {
+static const unsigned long dwAL7230ChannelTable1[CB_MAX_CHANNEL] = {
 	0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  1, Tf = 2412MHz
 	0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  2, Tf = 2417MHz
 	0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  3, Tf = 2422MHz
@@ -349,7 +349,7 @@
 	0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW  // channel = 165, Tf = 5825MHz (56)
 };
 
-const unsigned long dwAL7230ChannelTable2[CB_MAX_CHANNEL] = {
+static const unsigned long dwAL7230ChannelTable2[CB_MAX_CHANNEL] = {
 	0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  1, Tf = 2412MHz
 	0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  2, Tf = 2417MHz
 	0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel =  3, Tf = 2422MHz
@@ -428,7 +428,7 @@
  * Return Value: true if succeeded; false if failed.
  *
  */
-bool s_bAL7230Init(unsigned long dwIoBase)
+static bool s_bAL7230Init(unsigned long dwIoBase)
 {
 	int     ii;
 	bool bResult;
@@ -471,7 +471,7 @@
 }
 
 // Need to Pull PLLON low when writing channel registers through 3-wire interface
-bool s_bAL7230SelectChannel(unsigned long dwIoBase, unsigned char byChannel)
+static bool s_bAL7230SelectChannel(unsigned long dwIoBase, unsigned char byChannel)
 {
 	bool bResult;
 
@@ -631,7 +631,7 @@
  * Return Value: true if succeeded; false if failed.
  *
  */
-bool RFbAL2230Init(unsigned long dwIoBase)
+static bool RFbAL2230Init(unsigned long dwIoBase)
 {
 	int     ii;
 	bool bResult;
@@ -678,7 +678,7 @@
 	return bResult;
 }
 
-bool RFbAL2230SelectChannel(unsigned long dwIoBase, unsigned char byChannel)
+static bool RFbAL2230SelectChannel(unsigned long dwIoBase, unsigned char byChannel)
 {
 	bool bResult;
 
@@ -776,36 +776,6 @@
 }
 
 /*
- * Description: RF ShutDown function
- *
- * Parameters:
- *  In:
- *      byBBType
- *      byRFType
- *  Out:
- *      none
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-bool RFbShutDown(
-	PSDevice  pDevice
-)
-{
-	bool bResult = true;
-
-	switch (pDevice->byRFType) {
-	case RF_AIROHA7230:
-		bResult = IFRFbWriteEmbedded(pDevice->PortOffset, 0x1ABAEF00 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW);
-		break;
-	default:
-		bResult = true;
-		break;
-	}
-	return bResult;
-}
-
-/*
  * Description: Select channel
  *
  * Parameters:
diff --git a/drivers/staging/vt6655/tkip.c b/drivers/staging/vt6655/tkip.c
index b3e087e..e7c17c6 100644
--- a/drivers/staging/vt6655/tkip.c
+++ b/drivers/staging/vt6655/tkip.c
@@ -55,7 +55,7 @@
 /* The 2nd table is the same as the 1st but with the upper and lower   */
 /* bytes swapped. To allow an endian tolerant implementation, the byte */
 /* halves have been expressed independently here.                      */
-const unsigned char TKIP_Sbox_Lower[256] = {
+static const unsigned char TKIP_Sbox_Lower[256] = {
 	0xA5, 0x84, 0x99, 0x8D, 0x0D, 0xBD, 0xB1, 0x54,
 	0x50, 0x03, 0xA9, 0x7D, 0x19, 0x62, 0xE6, 0x9A,
 	0x45, 0x9D, 0x40, 0x87, 0x15, 0xEB, 0xC9, 0x0B,
@@ -90,7 +90,7 @@
 	0xC3, 0xB0, 0x77, 0x11, 0xCB, 0xFC, 0xD6, 0x3A
 };
 
-const unsigned char TKIP_Sbox_Upper[256] = {
+static const unsigned char TKIP_Sbox_Upper[256] = {
 	0xC6, 0xF8, 0xEE, 0xF6, 0xFF, 0xD6, 0xDE, 0x91,
 	0x60, 0x02, 0xCE, 0x56, 0xE7, 0xB5, 0x4D, 0xEC,
 	0x8F, 0x1F, 0x89, 0xFA, 0xEF, 0xB2, 0x8E, 0xFB,
diff --git a/drivers/staging/vt6655/vntwifi.c b/drivers/staging/vt6655/vntwifi.c
index d8f4f8e..d2bdb71 100644
--- a/drivers/staging/vt6655/vntwifi.c
+++ b/drivers/staging/vt6655/vntwifi.c
@@ -752,25 +752,3 @@
 	//spin_unlock_irq(&pDevice->lock);
 	return true;
 }
-
-/*
-  bool
-  VNTWIFIbRadarPresent(
-  void *pMgmtObject,
-  unsigned char byChannel
-) {
-  PSMgmtObject    pMgmt = (PSMgmtObject) pMgmtObject;
-  if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) &&
-  (byChannel == (unsigned char) pMgmt->uCurrChannel) &&
-  (pMgmt->bSwitchChannel != true) &&
-  (pMgmt->b11hEnable == true)) {
-  if (!compare_ether_addr(pMgmt->abyIBSSDFSOwner, CARDpGetCurrentAddress(pMgmt->pAdapter))) {
-  pMgmt->byNewChannel = CARDbyAutoChannelSelect(pMgmt->pAdapter,(unsigned char) pMgmt->uCurrChannel);
-  pMgmt->bSwitchChannel = true;
-  }
-  BEACONbSendBeacon(pMgmt);
-  CARDbChannelSwitch(pMgmt->pAdapter, 0, pMgmt->byNewChannel, 10);
-  }
-  return true;
-  }
-*/
diff --git a/drivers/staging/vt6655/wcmd.c b/drivers/staging/vt6655/wcmd.c
index d551653..9c57eef 100644
--- a/drivers/staging/vt6655/wcmd.c
+++ b/drivers/staging/vt6655/wcmd.c
@@ -233,7 +233,7 @@
  *
  *
  * Return Value:
- *    A ptr to Tx frame or NULL on allocation failue
+ *    A ptr to Tx frame or NULL on allocation failure
  *
  -*/
 
diff --git a/drivers/staging/vt6655/wctl.c b/drivers/staging/vt6655/wctl.c
index 9eb81b4..f05f9f5 100644
--- a/drivers/staging/vt6655/wctl.c
+++ b/drivers/staging/vt6655/wctl.c
@@ -75,8 +75,8 @@
 		for (ii = 0; ii < DUPLICATE_RX_CACHE_LENGTH; ii++) {
 			pCacheEntry = &(pCache->asCacheEntry[uIndex]);
 			if ((pCacheEntry->wFmSequence == pMACHeader->wSeqCtl) &&
-			    (!compare_ether_addr(&(pCacheEntry->abyAddr2[0]), &(pMACHeader->abyAddr2[0])))
-) {
+			    ether_addr_equal(pCacheEntry->abyAddr2,
+					     pMACHeader->abyAddr2)) {
 				/* Duplicate match */
 				return true;
 			}
@@ -111,8 +111,8 @@
 
 	for (ii = 0; ii < pDevice->cbDFCB; ii++) {
 		if ((pDevice->sRxDFCB[ii].bInUse == true) &&
-		    (!compare_ether_addr(&(pDevice->sRxDFCB[ii].abyAddr2[0]), &(pMACHeader->abyAddr2[0])))
-) {
+		    ether_addr_equal(pDevice->sRxDFCB[ii].abyAddr2,
+				     pMACHeader->abyAddr2)) {
 			//
 			return ii;
 		}
diff --git a/drivers/staging/vt6655/wmgr.c b/drivers/staging/vt6655/wmgr.c
index 9938813..ed4b32b 100644
--- a/drivers/staging/vt6655/wmgr.c
+++ b/drivers/staging/vt6655/wmgr.c
@@ -1680,7 +1680,8 @@
 			vMgrDecodeDeauthen(&sFrame);
 			DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO  "AP deauthed me, reason=%d.\n", cpu_to_le16((*(sFrame.pwReason))));
 			// TODO: update BSS list for specific BSSID if pre-authentication case
-			if (!compare_ether_addr(sFrame.pHdr->sA3.abyAddr3, pMgmt->abyCurrBSSID)) {
+			if (ether_addr_equal(sFrame.pHdr->sA3.abyAddr3,
+					     pMgmt->abyCurrBSSID)) {
 				if (pMgmt->eCurrState >= WMAC_STATE_AUTHPENDING) {
 					pMgmt->sNodeDBTable[0].bActive = false;
 					pMgmt->eCurrMode = WMAC_MODE_STANDBY;
diff --git a/drivers/staging/vt6655/wpa.c b/drivers/staging/vt6655/wpa.c
index c5293bb..b697fa6 100644
--- a/drivers/staging/vt6655/wpa.c
+++ b/drivers/staging/vt6655/wpa.c
@@ -45,12 +45,12 @@
 /*---------------------  Static Variables  --------------------------*/
 static int msglevel = MSG_LEVEL_INFO;
 
-const unsigned char abyOUI00[4] = { 0x00, 0x50, 0xf2, 0x00 };
-const unsigned char abyOUI01[4] = { 0x00, 0x50, 0xf2, 0x01 };
-const unsigned char abyOUI02[4] = { 0x00, 0x50, 0xf2, 0x02 };
-const unsigned char abyOUI03[4] = { 0x00, 0x50, 0xf2, 0x03 };
-const unsigned char abyOUI04[4] = { 0x00, 0x50, 0xf2, 0x04 };
-const unsigned char abyOUI05[4] = { 0x00, 0x50, 0xf2, 0x05 };
+static const unsigned char abyOUI00[4] = { 0x00, 0x50, 0xf2, 0x00 };
+static const unsigned char abyOUI01[4] = { 0x00, 0x50, 0xf2, 0x01 };
+static const unsigned char abyOUI02[4] = { 0x00, 0x50, 0xf2, 0x02 };
+static const unsigned char abyOUI03[4] = { 0x00, 0x50, 0xf2, 0x03 };
+static const unsigned char abyOUI04[4] = { 0x00, 0x50, 0xf2, 0x04 };
+static const unsigned char abyOUI05[4] = { 0x00, 0x50, 0xf2, 0x05 };
 
 /*+
  *
diff --git a/drivers/staging/vt6655/wpactl.c b/drivers/staging/vt6655/wpactl.c
index e8d9ecd..044368a 100644
--- a/drivers/staging/vt6655/wpactl.c
+++ b/drivers/staging/vt6655/wpactl.c
@@ -394,7 +394,7 @@
 
 		} else {
 			// Key Table Full
-			if (!compare_ether_addr(&param->addr[0], pDevice->abyBSSID)) {
+			if (ether_addr_equal(param->addr, pDevice->abyBSSID)) {
 				//DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n"));
 				//spin_unlock_irq(&pDevice->lock);
 				return -EINVAL;
diff --git a/drivers/staging/vt6655/wroute.c b/drivers/staging/vt6655/wroute.c
index b61328f..85302c5 100644
--- a/drivers/staging/vt6655/wroute.c
+++ b/drivers/staging/vt6655/wroute.c
@@ -179,7 +179,7 @@
 		pHeadTD = pHeadTD->next;
 	}
 
-	pLastTD->pTDInfo->skb = 0;
+	pLastTD->pTDInfo->skb = NULL;
 	pLastTD->pTDInfo->byFlags = 0;
 
 	pDevice->apCurrTD[TYPE_AC0DMA] = pHeadTD;
diff --git a/drivers/staging/vt6655/wroute.h b/drivers/staging/vt6655/wroute.h
index 5ecc190..3abc1d3 100644
--- a/drivers/staging/vt6655/wroute.h
+++ b/drivers/staging/vt6655/wroute.h
@@ -41,4 +41,4 @@
 
 bool ROUTEbRelay(PSDevice pDevice, unsigned char *pbySkbData, unsigned int uDataLen, unsigned int uNodeIndex);
 
-#endif // __WROUTE_H__
+#endif /* __WROUTE_H__ */
diff --git a/drivers/staging/vt6656/aes_ccmp.c b/drivers/staging/vt6656/aes_ccmp.c
index 28a4c4c..6c76939 100644
--- a/drivers/staging/vt6656/aes_ccmp.c
+++ b/drivers/staging/vt6656/aes_ccmp.c
@@ -96,9 +96,9 @@
 
 static void xor_128(u8 *a, u8 *b, u8 *out)
 {
-	u32 * dwPtrA = (u32 *) a;
-	u32 * dwPtrB = (u32 *) b;
-	u32 * dwPtrOut = (u32 *) out;
+	u32 *dwPtrA = (u32 *) a;
+	u32 *dwPtrB = (u32 *) b;
+	u32 *dwPtrOut = (u32 *) out;
 
 	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
 	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
@@ -108,9 +108,9 @@
 
 static void xor_32(u8 *a, u8 *b, u8 *out)
 {
-	u32 * dwPtrA = (u32 *) a;
-	u32 * dwPtrB = (u32 *) b;
-	u32 * dwPtrOut = (u32 *) out;
+	u32 *dwPtrA = (u32 *) a;
+	u32 *dwPtrB = (u32 *) b;
+	u32 *dwPtrOut = (u32 *) out;
 
 	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
 }
@@ -218,7 +218,7 @@
  *
  */
 
-bool AESbGenCCMP(u8 * pbyRxKey, u8 * pbyFrame, u16 wFrameSize)
+bool AESbGenCCMP(u8 *pbyRxKey, u8 *pbyFrame, u16 wFrameSize)
 {
 	u8            abyNonce[13];
 	u8            MIC_IV[16];
@@ -231,8 +231,8 @@
 	u8            abyLastCipher[16];
 
 	struct ieee80211_hdr *pMACHeader = (struct ieee80211_hdr *) pbyFrame;
-	u8 *           pbyIV;
-	u8 *           pbyPayload;
+	u8 *pbyIV;
+	u8 *pbyPayload;
 	u16            wHLen = 22;
 	/* 8 is IV, 8 is MIC, 4 is CRC */
 	u16            wPayloadSize = wFrameSize - 8 - 8 - 4 - WLAN_HDR_ADDR3_LEN;
diff --git a/drivers/staging/vt6656/bssdb.c b/drivers/staging/vt6656/bssdb.c
index ee79bbd..dad3f8c 100644
--- a/drivers/staging/vt6656/bssdb.c
+++ b/drivers/staging/vt6656/bssdb.c
@@ -57,6 +57,7 @@
 #include "control.h"
 #include "rndis.h"
 #include "iowpa.h"
+#include "power.h"
 
 static int          msglevel                =MSG_LEVEL_INFO;
 //static int          msglevel                =MSG_LEVEL_DEBUG;
@@ -126,7 +127,7 @@
 
             if ((pCurrBSS->bActive) &&
                 (pCurrBSS->bSelected == false)) {
-		    if (!compare_ether_addr(pCurrBSS->abyBSSID, pbyBSSID)) {
+		    if (ether_addr_equal(pCurrBSS->abyBSSID, pbyBSSID)) {
                     if (pSSID != NULL) {
                         // compare ssid
                         if ( !memcmp(pSSID->abySSID,
@@ -242,8 +243,8 @@
     for (ii = 0; ii < MAX_BSS_NUM; ii++) {
         if (bKeepCurrBSSID) {
             if (pMgmt->sBSSList[ii].bActive &&
-		!compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID,
-				    pMgmt->abyCurrBSSID)) {
+		ether_addr_equal(pMgmt->sBSSList[ii].abyBSSID,
+				 pMgmt->abyCurrBSSID)) {
  //mike mark: there are two BSSID's in list. If that AP is in hidden ssid mode, one SSID is null,
  //                 but other's might not be obvious, so if it associate's with your STA,
  //                 you must keep the two of them!!
@@ -277,7 +278,7 @@
     for (ii = 0; ii < MAX_BSS_NUM; ii++) {
         pBSSList = &(pMgmt->sBSSList[ii]);
         if (pBSSList->bActive) {
-		if (!compare_ether_addr(pBSSList->abyBSSID, abyBSSID)) {
+		if (ether_addr_equal(pBSSList->abyBSSID, abyBSSID)) {
                 if (pSSID->len == ((PWLAN_IE_SSID)pBSSList->abySSID)->len){
                     if (memcmp(pSSID->abySSID,
                             ((PWLAN_IE_SSID)pBSSList->abySSID)->abySSID,
@@ -623,8 +624,8 @@
     // Index = 0 reserved for AP Node
     for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) {
         if (pMgmt->sNodeDBTable[ii].bActive) {
-		if (!compare_ether_addr(abyDstAddr,
-					pMgmt->sNodeDBTable[ii].abyMACAddr)) {
+		if (ether_addr_equal(abyDstAddr,
+				     pMgmt->sNodeDBTable[ii].abyMACAddr)) {
                 *puNodeIndex = ii;
                 return true;
             }
@@ -813,8 +814,10 @@
  *
 -*/
 
-void BSSvSecondCallBack(struct vnt_private *pDevice)
+void BSSvSecondCallBack(struct work_struct *work)
 {
+	struct vnt_private *pDevice = container_of(work,
+			struct vnt_private, second_callback_work.work);
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
 	int ii;
 	PWLAN_IE_SSID pItemSSID, pCurrSSID;
@@ -822,6 +825,9 @@
 	u32 uNonShortSlotSTACnt = 0;
 	u32 uLongPreambleSTACnt = 0;
 
+	if (pDevice->Flags & fMP_DISCONNECTED)
+		return;
+
     spin_lock_irq(&pDevice->lock);
 
     pDevice->uAssocCount = 0;
@@ -1119,15 +1125,26 @@
         }
     }
 
-    if (pDevice->bLinkPass == true) {
-        if (netif_queue_stopped(pDevice->dev))
-            netif_wake_queue(pDevice->dev);
-    }
+	if (pDevice->bLinkPass == true) {
+		if (pMgmt->eAuthenMode < WMAC_AUTH_WPA ||
+			pDevice->fWPA_Authened == true) {
+			if (++pDevice->tx_data_time_out > 40) {
+				pDevice->tx_trigger = true;
+
+				PSbSendNullPacket(pDevice);
+
+				pDevice->tx_trigger = false;
+				pDevice->tx_data_time_out = 0;
+			}
+		}
+
+		if (netif_queue_stopped(pDevice->dev))
+			netif_wake_queue(pDevice->dev);
+	}
 
     spin_unlock_irq(&pDevice->lock);
 
-    pMgmt->sTimerSecondCallback.expires = RUN_AT(HZ);
-    add_timer(&pMgmt->sTimerSecondCallback);
+	schedule_delayed_work(&pDevice->second_callback_work, HZ);
 }
 
 /*+
diff --git a/drivers/staging/vt6656/bssdb.h b/drivers/staging/vt6656/bssdb.h
index bce3b46..fc41855 100644
--- a/drivers/staging/vt6656/bssdb.h
+++ b/drivers/staging/vt6656/bssdb.h
@@ -262,7 +262,7 @@
 void BSSvUpdateAPNode(struct vnt_private *, u16 *pwCapInfo,
 	PWLAN_IE_SUPP_RATES pItemRates, PWLAN_IE_SUPP_RATES pExtSuppRates);
 
-void BSSvSecondCallBack(struct vnt_private *);
+void BSSvSecondCallBack(struct work_struct *work);
 
 void BSSvUpdateNodeTxCounter(struct vnt_private *, PSStatCounter pStatistic,
 	u8 byTSR, u8 byPktNO);
diff --git a/drivers/staging/vt6656/channel.c b/drivers/staging/vt6656/channel.c
index 5158ff4..e430b35 100644
--- a/drivers/staging/vt6656/channel.c
+++ b/drivers/staging/vt6656/channel.c
@@ -403,7 +403,7 @@
 
 void CHvInitChannelTable(struct vnt_private *pDevice)
 {
-	int bMultiBand = false;
+	bool bMultiBand = false;
 	int ii;
 
     for (ii = 1; ii <= CB_MAX_CHANNEL; ii++)
diff --git a/drivers/staging/vt6656/datarate.c b/drivers/staging/vt6656/datarate.c
index 17fbc35..af9eab0 100644
--- a/drivers/staging/vt6656/datarate.c
+++ b/drivers/staging/vt6656/datarate.c
@@ -44,9 +44,9 @@
 #include "rf.h"
 
 /* static int msglevel = MSG_LEVEL_DEBUG; */
-static int          msglevel                =MSG_LEVEL_INFO;
-const u8 acbyIERate[MAX_RATE] =
-{0x02, 0x04, 0x0B, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C};
+static int msglevel = MSG_LEVEL_INFO;
+const u8 acbyIERate[MAX_RATE] = {0x02, 0x04, 0x0B, 0x16, 0x0C, 0x12, 0x18,
+	0x24, 0x30, 0x48, 0x60, 0x6C};
 
 #define AUTORATE_TXOK_CNT       0x0400
 #define AUTORATE_TXFAIL_CNT     0x0064
@@ -56,13 +56,13 @@
 
 void s_vResetCounter(PKnownNodeDB psNodeDBTable)
 {
-    u8            ii;
+	u8 ii;
 
-    /* clear statistics counter for auto_rate */
-    for (ii = 0; ii <= MAX_RATE; ii++) {
-        psNodeDBTable->uTxOk[ii] = 0;
-        psNodeDBTable->uTxFail[ii] = 0;
-    }
+	/* clear statistics counter for auto_rate */
+	for (ii = 0; ii <= MAX_RATE; ii++) {
+		psNodeDBTable->uTxOk[ii] = 0;
+		psNodeDBTable->uTxFail[ii] = 0;
+	}
 }
 
 /*+
@@ -97,21 +97,18 @@
  * Return Value: RateIdx
  *
 -*/
-u16
-RATEwGetRateIdx(
-     u8 byRate
-    )
+u16 RATEwGetRateIdx(u8 byRate)
 {
-    u16    ii;
+	u16 ii;
 
-    /* erase BasicRate flag */
-    byRate = byRate & 0x7F;
+	/* erase BasicRate flag */
+	byRate = byRate & 0x7F;
 
-    for (ii = 0; ii < MAX_RATE; ii ++) {
-        if (acbyIERate[ii] == byRate)
-            return ii;
-    }
-    return 0;
+	for (ii = 0; ii < MAX_RATE; ii++) {
+		if (acbyIERate[ii] == byRate)
+			return ii;
+	}
+	return 0;
 }
 
 /*+
@@ -139,7 +136,7 @@
 	int bUpdateBasicRate, u16 *pwMaxBasicRate, u16 *pwMaxSuppRate,
 	u16 *pwSuppRate, u8 *pbyTopCCKRate, u8 *pbyTopOFDMRate)
 {
-	int  ii;
+	int ii;
 	u8 byHighSuppRate = 0, byRate = 0;
 	u16 wOldBasicRate = pDevice->wBasicRate;
 	u32 uRateLen;
@@ -147,83 +144,88 @@
 	if (pItemRates == NULL)
 		return;
 
-    *pwSuppRate = 0;
-    uRateLen = pItemRates->len;
+	*pwSuppRate = 0;
+	uRateLen = pItemRates->len;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate Len: %d\n", uRateLen);
-    if (pDevice->byBBType != BB_TYPE_11B) {
-        if (uRateLen > WLAN_RATES_MAXLEN)
-            uRateLen = WLAN_RATES_MAXLEN;
-    } else {
-        if (uRateLen > WLAN_RATES_MAXLEN_11B)
-            uRateLen = WLAN_RATES_MAXLEN_11B;
-    }
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate Len: %d\n", uRateLen);
+	if (pDevice->byBBType != BB_TYPE_11B) {
+		if (uRateLen > WLAN_RATES_MAXLEN)
+			uRateLen = WLAN_RATES_MAXLEN;
+	} else {
+		if (uRateLen > WLAN_RATES_MAXLEN_11B)
+			uRateLen = WLAN_RATES_MAXLEN_11B;
+	}
 
-    for (ii = 0; ii < uRateLen; ii++) {
-    	byRate = (u8)(pItemRates->abyRates[ii]);
-        if (WLAN_MGMT_IS_BASICRATE(byRate) &&
-            (bUpdateBasicRate == true))  {
-	  /*
-	   * add to basic rate set, update pDevice->byTopCCKBasicRate and
-	   * pDevice->byTopOFDMBasicRate
-	   */
-		CARDbAddBasicRate((void *)pDevice, RATEwGetRateIdx(byRate));
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate AddBasicRate: %d\n", RATEwGetRateIdx(byRate));
-        }
-        byRate = (u8)(pItemRates->abyRates[ii]&0x7F);
-        if (byHighSuppRate == 0)
-            byHighSuppRate = byRate;
-        if (byRate > byHighSuppRate)
-            byHighSuppRate = byRate;
-        *pwSuppRate |= (1<<RATEwGetRateIdx(byRate));
-    }
-    if ((pItemExtRates != NULL) && (pItemExtRates->byElementID == WLAN_EID_EXTSUPP_RATES) &&
-        (pDevice->byBBType != BB_TYPE_11B)) {
+	for (ii = 0; ii < uRateLen; ii++) {
+		byRate = (u8)(pItemRates->abyRates[ii]);
+		if (WLAN_MGMT_IS_BASICRATE(byRate) &&
+				(bUpdateBasicRate == true)) {
+			/*
+			 * add to basic rate set, update pDevice->byTopCCKBasicRate and
+			 * pDevice->byTopOFDMBasicRate
+			 */
+			CARDbAddBasicRate((void *)pDevice, RATEwGetRateIdx(byRate));
+			DBG_PRT(MSG_LEVEL_DEBUG,
+				KERN_INFO"ParseMaxRate AddBasicRate: %d\n",
+				RATEwGetRateIdx(byRate));
+		}
+		byRate = (u8)(pItemRates->abyRates[ii]&0x7F);
+		if (byHighSuppRate == 0)
+			byHighSuppRate = byRate;
+		if (byRate > byHighSuppRate)
+			byHighSuppRate = byRate;
+		*pwSuppRate |= (1<<RATEwGetRateIdx(byRate));
+	}
+	if ((pItemExtRates != NULL) && (pItemExtRates->byElementID == WLAN_EID_EXTSUPP_RATES) &&
+			(pDevice->byBBType != BB_TYPE_11B)) {
 
-	unsigned int uExtRateLen = pItemExtRates->len;
+		unsigned int uExtRateLen = pItemExtRates->len;
 
-        if (uExtRateLen > WLAN_RATES_MAXLEN)
-            uExtRateLen = WLAN_RATES_MAXLEN;
+		if (uExtRateLen > WLAN_RATES_MAXLEN)
+			uExtRateLen = WLAN_RATES_MAXLEN;
 
-        for (ii = 0; ii < uExtRateLen ; ii++) {
-            byRate = (u8)(pItemExtRates->abyRates[ii]);
-	    /* select highest basic rate */
-            if (WLAN_MGMT_IS_BASICRATE(pItemExtRates->abyRates[ii])) {
-	      /*
-	       * add to basic rate set, update pDevice->byTopCCKBasicRate and
-	       * pDevice->byTopOFDMBasicRate
-	       */
-		    CARDbAddBasicRate((void *)pDevice, RATEwGetRateIdx(byRate));
-                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ParseMaxRate AddBasicRate: %d\n", RATEwGetRateIdx(byRate));
-            }
-            byRate = (u8)(pItemExtRates->abyRates[ii]&0x7F);
-            if (byHighSuppRate == 0)
-                byHighSuppRate = byRate;
-            if (byRate > byHighSuppRate)
-                byHighSuppRate = byRate;
-            *pwSuppRate |= (1<<RATEwGetRateIdx(byRate));
+		for (ii = 0; ii < uExtRateLen; ii++) {
+			byRate = (u8)(pItemExtRates->abyRates[ii]);
+			/* select highest basic rate */
+			if (WLAN_MGMT_IS_BASICRATE(pItemExtRates->abyRates[ii])) {
+				/*
+				 * add to basic rate set, update pDevice->byTopCCKBasicRate and
+				 * pDevice->byTopOFDMBasicRate
+				 */
+				CARDbAddBasicRate((void *)pDevice, RATEwGetRateIdx(byRate));
+				DBG_PRT(MSG_LEVEL_DEBUG,
+						KERN_INFO"ParseMaxRate AddBasicRate: %d\n",
+						RATEwGetRateIdx(byRate));
+			}
+			byRate = (u8)(pItemExtRates->abyRates[ii]&0x7F);
+			if (byHighSuppRate == 0)
+				byHighSuppRate = byRate;
+			if (byRate > byHighSuppRate)
+				byHighSuppRate = byRate;
+			*pwSuppRate |= (1<<RATEwGetRateIdx(byRate));
 
-	    /* DBG_PRN_GRP09(("ParseMaxRate : HighSuppRate: %d, %X\n",
-	       RATEwGetRateIdx(byRate), byRate)); */
-        }
-    }
+			/* DBG_PRN_GRP09(("ParseMaxRate : HighSuppRate: %d, %X\n",
+			 * RATEwGetRateIdx(byRate), byRate));
+			 */
+		}
+	}
 
-    if ((pDevice->byPacketType == PK_TYPE_11GB)
-	&& CARDbIsOFDMinBasicRate((void *)pDevice)) {
-        pDevice->byPacketType = PK_TYPE_11GA;
-    }
+	if ((pDevice->byPacketType == PK_TYPE_11GB)
+			&& CARDbIsOFDMinBasicRate((void *)pDevice)) {
+		pDevice->byPacketType = PK_TYPE_11GA;
+	}
 
-    *pbyTopCCKRate = pDevice->byTopCCKBasicRate;
-    *pbyTopOFDMRate = pDevice->byTopOFDMBasicRate;
-    *pwMaxSuppRate = RATEwGetRateIdx(byHighSuppRate);
-    if ((pDevice->byPacketType==PK_TYPE_11B) || (pDevice->byPacketType==PK_TYPE_11GB))
-       *pwMaxBasicRate = pDevice->byTopCCKBasicRate;
-    else
-       *pwMaxBasicRate = pDevice->byTopOFDMBasicRate;
-    if (wOldBasicRate != pDevice->wBasicRate)
-	CARDvSetRSPINF((void *)pDevice, pDevice->byBBType);
+	*pbyTopCCKRate = pDevice->byTopCCKBasicRate;
+	*pbyTopOFDMRate = pDevice->byTopOFDMBasicRate;
+	*pwMaxSuppRate = RATEwGetRateIdx(byHighSuppRate);
+	if ((pDevice->byPacketType == PK_TYPE_11B) || (pDevice->byPacketType == PK_TYPE_11GB))
+		*pwMaxBasicRate = pDevice->byTopCCKBasicRate;
+	else
+		*pwMaxBasicRate = pDevice->byTopOFDMBasicRate;
+	if (wOldBasicRate != pDevice->wBasicRate)
+		CARDvSetRSPINF((void *)pDevice, pDevice->byBBType);
 
-     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Exit ParseMaxRate\n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Exit ParseMaxRate\n");
 }
 
 /*+
@@ -263,71 +265,68 @@
 
 	psNodeDBTable->uTimeCount++;
 
-    if (psNodeDBTable->uTxFail[MAX_RATE] > psNodeDBTable->uTxOk[MAX_RATE])
-        dwTxDiff = psNodeDBTable->uTxFail[MAX_RATE] - psNodeDBTable->uTxOk[MAX_RATE];
+	if (psNodeDBTable->uTxFail[MAX_RATE] > psNodeDBTable->uTxOk[MAX_RATE])
+		dwTxDiff = psNodeDBTable->uTxFail[MAX_RATE] - psNodeDBTable->uTxOk[MAX_RATE];
 
-    if ((psNodeDBTable->uTxOk[MAX_RATE] < AUTORATE_TXOK_CNT) &&
-        (dwTxDiff < AUTORATE_TXFAIL_CNT) &&
-        (psNodeDBTable->uTimeCount < AUTORATE_TIMEOUT)) {
-        return;
-    }
+	if ((psNodeDBTable->uTxOk[MAX_RATE] < AUTORATE_TXOK_CNT) &&
+			(dwTxDiff < AUTORATE_TXFAIL_CNT) &&
+			(psNodeDBTable->uTimeCount < AUTORATE_TIMEOUT)) {
+		return;
+	}
 
-    if (psNodeDBTable->uTimeCount >= AUTORATE_TIMEOUT) {
-        psNodeDBTable->uTimeCount = 0;
-    }
+	if (psNodeDBTable->uTimeCount >= AUTORATE_TIMEOUT)
+		psNodeDBTable->uTimeCount = 0;
 
-    for (ii = 0; ii < MAX_RATE; ii++) {
-        if (psNodeDBTable->wSuppRate & (0x0001<<ii)) {
-            if (bAutoRate[ii] == true) {
-                wIdxUpRate = (u16) ii;
-            }
-        } else {
-            bAutoRate[ii] = false;
-        }
-    }
+	for (ii = 0; ii < MAX_RATE; ii++) {
+		if (psNodeDBTable->wSuppRate & (0x0001<<ii)) {
+			if (bAutoRate[ii] == true)
+				wIdxUpRate = (u16) ii;
+		} else {
+			bAutoRate[ii] = false;
+		}
+	}
 
-    for (ii = 0; ii <= psNodeDBTable->wTxDataRate; ii++) {
-        if ( (psNodeDBTable->uTxOk[ii] != 0) ||
-             (psNodeDBTable->uTxFail[ii] != 0) ) {
-            dwThroughputTbl[ii] *= psNodeDBTable->uTxOk[ii];
-            if (ii < RATE_11M) {
-                psNodeDBTable->uTxFail[ii] *= 4;
-            }
-            dwThroughputTbl[ii] /= (psNodeDBTable->uTxOk[ii] + psNodeDBTable->uTxFail[ii]);
-        }
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate %d,Ok: %d, Fail:%d, Throughput:%d\n",
-                       ii, (int)psNodeDBTable->uTxOk[ii], (int)psNodeDBTable->uTxFail[ii], (int)dwThroughputTbl[ii]);
-    }
-    dwThroughput = dwThroughputTbl[psNodeDBTable->wTxDataRate];
+	for (ii = 0; ii <= psNodeDBTable->wTxDataRate; ii++) {
+		if ((psNodeDBTable->uTxOk[ii] != 0) ||
+				(psNodeDBTable->uTxFail[ii] != 0)) {
+			dwThroughputTbl[ii] *= psNodeDBTable->uTxOk[ii];
+			if (ii < RATE_11M)
+				psNodeDBTable->uTxFail[ii] *= 4;
+			dwThroughputTbl[ii] /= (psNodeDBTable->uTxOk[ii] + psNodeDBTable->uTxFail[ii]);
+		}
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate %d,Ok: %d, Fail:%d, Throughput:%d\n",
+				ii, (int)psNodeDBTable->uTxOk[ii], (int)psNodeDBTable->uTxFail[ii], (int)dwThroughputTbl[ii]);
+	}
+	dwThroughput = dwThroughputTbl[psNodeDBTable->wTxDataRate];
 
-    wIdxDownRate = psNodeDBTable->wTxDataRate;
-    for (ii = psNodeDBTable->wTxDataRate; ii > 0;) {
-        ii--;
-        if ( (dwThroughputTbl[ii] > dwThroughput) &&
-             (bAutoRate[ii]==true) ) {
-            dwThroughput = dwThroughputTbl[ii];
-            wIdxDownRate = (u16) ii;
-        }
-    }
-    psNodeDBTable->wTxDataRate = wIdxDownRate;
-    if (psNodeDBTable->uTxOk[MAX_RATE]) {
-        if (psNodeDBTable->uTxOk[MAX_RATE] >
-           (psNodeDBTable->uTxFail[MAX_RATE] * 4) ) {
-            psNodeDBTable->wTxDataRate = wIdxUpRate;
-        }
-    } else { /* adhoc, if uTxOk(total) == 0 & uTxFail(total) == 0 */
-        if (psNodeDBTable->uTxFail[MAX_RATE] == 0)
-            psNodeDBTable->wTxDataRate = wIdxUpRate;
-    }
+	wIdxDownRate = psNodeDBTable->wTxDataRate;
+	for (ii = psNodeDBTable->wTxDataRate; ii > 0;) {
+		ii--;
+		if ((dwThroughputTbl[ii] > dwThroughput) &&
+				(bAutoRate[ii] == true)) {
+			dwThroughput = dwThroughputTbl[ii];
+			wIdxDownRate = (u16) ii;
+		}
+	}
+	psNodeDBTable->wTxDataRate = wIdxDownRate;
+	if (psNodeDBTable->uTxOk[MAX_RATE]) {
+		if (psNodeDBTable->uTxOk[MAX_RATE] >
+				(psNodeDBTable->uTxFail[MAX_RATE] * 4)) {
+			psNodeDBTable->wTxDataRate = wIdxUpRate;
+		}
+	} else { /* adhoc, if uTxOk(total) == 0 & uTxFail(total) == 0 */
+		if (psNodeDBTable->uTxFail[MAX_RATE] == 0)
+			psNodeDBTable->wTxDataRate = wIdxUpRate;
+	}
 
-    if (pDevice->byBBType == BB_TYPE_11A) {
-        if (psNodeDBTable->wTxDataRate <= RATE_11M)
-            psNodeDBTable->wTxDataRate = RATE_6M;
-    }
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uTxOk[MAX_RATE] %d, uTxFail[MAX_RATE]:%d\n",(int)psNodeDBTable->uTxOk[MAX_RATE], (int)psNodeDBTable->uTxFail[MAX_RATE]);
-    s_vResetCounter(psNodeDBTable);
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate: %d, U:%d, D:%d\n", (int)psNodeDBTable->wTxDataRate, (int)wIdxUpRate, (int)wIdxDownRate);
-    return;
+	if (pDevice->byBBType == BB_TYPE_11A) {
+		if (psNodeDBTable->wTxDataRate <= RATE_11M)
+			psNodeDBTable->wTxDataRate = RATE_6M;
+	}
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uTxOk[MAX_RATE] %d, uTxFail[MAX_RATE]:%d\n", (int)psNodeDBTable->uTxOk[MAX_RATE], (int)psNodeDBTable->uTxFail[MAX_RATE]);
+	s_vResetCounter(psNodeDBTable);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Rate: %d, U:%d, D:%d\n", (int)psNodeDBTable->wTxDataRate, (int)wIdxUpRate, (int)wIdxDownRate);
+	return;
 }
 
 /*+
@@ -343,29 +342,24 @@
  * Return Value: None
  *
 -*/
-u8
-RATEuSetIE (
-     PWLAN_IE_SUPP_RATES pSrcRates,
-     PWLAN_IE_SUPP_RATES pDstRates,
-     unsigned int                uRateLen
-    )
+u8 RATEuSetIE(PWLAN_IE_SUPP_RATES pSrcRates, PWLAN_IE_SUPP_RATES pDstRates,
+		unsigned int uRateLen)
 {
-    unsigned int ii, uu, uRateCnt = 0;
+	unsigned int ii, uu, uRateCnt = 0;
 
-    if ((pSrcRates == NULL) || (pDstRates == NULL))
-        return 0;
+	if ((pSrcRates == NULL) || (pDstRates == NULL))
+		return 0;
 
-    if (pSrcRates->len == 0)
-        return 0;
+	if (pSrcRates->len == 0)
+		return 0;
 
-    for (ii = 0; ii < uRateLen; ii++) {
-        for (uu = 0; uu < pSrcRates->len; uu++) {
-            if ((pSrcRates->abyRates[uu] & 0x7F) == acbyIERate[ii]) {
-                pDstRates->abyRates[uRateCnt ++] = pSrcRates->abyRates[uu];
-                break;
-            }
-        }
-    }
-    return (u8)uRateCnt;
+	for (ii = 0; ii < uRateLen; ii++) {
+		for (uu = 0; uu < pSrcRates->len; uu++) {
+			if ((pSrcRates->abyRates[uu] & 0x7F) == acbyIERate[ii]) {
+				pDstRates->abyRates[uRateCnt++] = pSrcRates->abyRates[uu];
+				break;
+			}
+		}
+	}
+	return (u8)uRateCnt;
 }
-
diff --git a/drivers/staging/vt6656/desc.h b/drivers/staging/vt6656/desc.h
index 4675135..afe7074 100644
--- a/drivers/staging/vt6656/desc.h
+++ b/drivers/staging/vt6656/desc.h
@@ -146,15 +146,6 @@
 /*
  * TX FIFO header
  */
-typedef struct tagSTxBufHead {
-	u32 adwTxKey[4];
-    u16    wFIFOCtl;
-    u16    wTimeStamp;
-    u16    wFragCtl;
-    u16    wReserved;
-} __attribute__ ((__packed__))
-STxBufHead, *PSTxBufHead;
-typedef const STxBufHead *PCSTxBufHead;
 
 typedef struct tagSTxShortBufHead {
     u16    wFIFOCtl;
diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h
index 8e39634..62b7de1 100644
--- a/drivers/staging/vt6656/device.h
+++ b/drivers/staging/vt6656/device.h
@@ -384,8 +384,8 @@
 
 	struct tasklet_struct CmdWorkItem;
 	struct tasklet_struct EventWorkItem;
-	struct tasklet_struct ReadWorkItem;
-	struct tasklet_struct RxMngWorkItem;
+	struct work_struct read_work_item;
+	struct work_struct rx_mng_work_item;
 
 	u32 rx_buf_sz;
 	int multicast_limit;
@@ -579,6 +579,9 @@
 	u8 abyOFDMAPwrTbl[42];
 
 	u16 wCurrentRate;
+	u16 tx_rate_fb0;
+	u16 tx_rate_fb1;
+
 	u16 wRTSThreshold;
 	u16 wFragmentationThreshold;
 	u8 byShortRetryLimit;
@@ -707,13 +710,12 @@
 	u8 byBBCR09;
 
 	/* command timer */
-	struct timer_list sTimerCommand;
+	struct delayed_work run_command_work;
+	/* One second callback */
+	struct delayed_work second_callback_work;
 
-	struct timer_list sTimerTxData;
-	unsigned long nTxDataTimeCout;
-	int fTxDataInSleep;
-	int IsTxDataTrigger;
-
+	u8 tx_data_time_out;
+	bool tx_trigger;
 	int fWPA_Authened; /*is WPA/WPA-PSK or WPA2/WPA2-PSK authen?? */
 	u8 byReAssocCount;
 	u8 byLinkWaitCount;
diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c
index ea7d443..75dc92d 100644
--- a/drivers/staging/vt6656/dpc.c
+++ b/drivers/staging/vt6656/dpc.c
@@ -136,9 +136,9 @@
     };
 
     pbyRxBuffer = (u8 *) (pbyRxBufferAddr + cbHeaderSize);
-    if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_Bridgetunnel[0])) {
+    if (ether_addr_equal(pbyRxBuffer, pDevice->abySNAP_Bridgetunnel)) {
         cbHeaderSize += 6;
-    } else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) {
+    } else if (ether_addr_equal(pbyRxBuffer, pDevice->abySNAP_RFC1042)) {
         cbHeaderSize += 6;
         pwType = (u16 *) (pbyRxBufferAddr + cbHeaderSize);
 	if ((*pwType == cpu_to_be16(ETH_P_IPX)) ||
@@ -361,7 +361,7 @@
     if ((pMgmt->eCurrMode == WMAC_MODE_STANDBY) ||
         (pMgmt->eCurrMode == WMAC_MODE_ESS_STA)) {
        if (pMgmt->sNodeDBTable[0].bActive) {
-	 if (!compare_ether_addr(pMgmt->abyCurrBSSID, pMACHeader->addr2)) {
+	 if (ether_addr_equal(pMgmt->abyCurrBSSID, pMACHeader->addr2)) {
 	    if (pMgmt->sNodeDBTable[0].uInActiveCount != 0)
                   pMgmt->sNodeDBTable[0].uInActiveCount = 0;
            }
@@ -374,8 +374,7 @@
             return false;
         }
 
-	if (compare_ether_addr(pDevice->abyCurrentNetAddr,
-			       pMACHeader->addr1)) {
+	if (!ether_addr_equal(pDevice->abyCurrentNetAddr, pMACHeader->addr1)) {
 		return false;
         }
     }
@@ -383,8 +382,8 @@
     // Use for TKIP MIC
     s_vGetDASA(pbyFrame, &cbHeaderSize, &pDevice->sRxEthHeader);
 
-    if (!compare_ether_addr((u8 *)&(pDevice->sRxEthHeader.h_source[0]),
-			    pDevice->abyCurrentNetAddr))
+    if (ether_addr_equal((u8 *)pDevice->sRxEthHeader.h_source,
+			 pDevice->abyCurrentNetAddr))
         return false;
 
     if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) {
@@ -560,7 +559,7 @@
             }
             if (pDevice->bIsRxMngWorkItemQueued == false) {
                 pDevice->bIsRxMngWorkItemQueued = true;
-                tasklet_schedule(&pDevice->RxMngWorkItem);
+		schedule_work(&pDevice->rx_mng_work_item);
             }
 
         }
@@ -1333,11 +1332,16 @@
     return true;
 }
 
-void RXvWorkItem(struct vnt_private *pDevice)
+void RXvWorkItem(struct work_struct *work)
 {
+	struct vnt_private *pDevice =
+		container_of(work, struct vnt_private, read_work_item);
 	int ntStatus;
 	struct vnt_rcb *pRCB = NULL;
 
+	if (pDevice->Flags & fMP_DISCONNECTED)
+		return;
+
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Rx Polling Thread\n");
     spin_lock_irq(&pDevice->lock);
 
@@ -1384,17 +1388,22 @@
         (pDevice->bIsRxWorkItemQueued == false) ) {
 
         pDevice->bIsRxWorkItemQueued = true;
-        tasklet_schedule(&pDevice->ReadWorkItem);
+	schedule_work(&pDevice->read_work_item);
     }
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----RXFreeRCB %d %d\n",pDevice->NumRecvFreeList, pDevice->NumRecvMngList);
 }
 
-void RXvMngWorkItem(struct vnt_private *pDevice)
+void RXvMngWorkItem(struct work_struct *work)
 {
+	struct vnt_private *pDevice =
+		container_of(work, struct vnt_private, rx_mng_work_item);
 	struct vnt_rcb *pRCB = NULL;
 	struct vnt_rx_mgmt *pRxPacket;
 	int bReAllocSkb = false;
 
+	if (pDevice->Flags & fMP_DISCONNECTED)
+		return;
+
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Rx Mng Thread\n");
 
     spin_lock_irq(&pDevice->lock);
diff --git a/drivers/staging/vt6656/dpc.h b/drivers/staging/vt6656/dpc.h
index 95388dc..8d52434 100644
--- a/drivers/staging/vt6656/dpc.h
+++ b/drivers/staging/vt6656/dpc.h
@@ -32,9 +32,9 @@
 #include "device.h"
 #include "wcmd.h"
 
-void RXvWorkItem(void *Context);
+void RXvWorkItem(struct work_struct *work);
 
-void RXvMngWorkItem(void *Context);
+void RXvMngWorkItem(struct work_struct *work);
 
 void RXvFreeRCB(struct vnt_rcb *pRCB, int bReAllocSkb);
 
diff --git a/drivers/staging/vt6656/firmware.c b/drivers/staging/vt6656/firmware.c
index a1dc3a4..cd2ea76 100644
--- a/drivers/staging/vt6656/firmware.c
+++ b/drivers/staging/vt6656/firmware.c
@@ -35,8 +35,8 @@
 #include "control.h"
 #include "rndis.h"
 
-static int          msglevel                =MSG_LEVEL_INFO;
-//static int          msglevel                =MSG_LEVEL_DEBUG;
+static int msglevel = MSG_LEVEL_INFO;
+/* static int msglevel = MSG_LEVEL_DEBUG; */
 
 #define FIRMWARE_VERSION	0x133		/* version 1.51 */
 #define FIRMWARE_NAME		"vntwusb.fw"
@@ -72,18 +72,17 @@
 		memcpy(pBuffer, fw->data + ii, wLength);
 
 		NdisStatus = CONTROLnsRequestOutAsyn(pDevice,
-                                            0,
-                                            0x1200+ii,
-                                            0x0000,
-                                            wLength,
-                                            pBuffer
-                                            );
+						0,
+						0x1200+ii,
+						0x0000,
+						wLength,
+						pBuffer);
 
 		DBG_PRT(MSG_LEVEL_DEBUG,
 			KERN_INFO"Download firmware...%d %zu\n", ii, fw->size);
 		if (NdisStatus != STATUS_SUCCESS)
 			goto free_fw;
-        }
+	}
 
 	result = true;
 free_fw:
@@ -101,48 +100,47 @@
 {
 	int NdisStatus;
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Branch to Sram\n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Branch to Sram\n");
 
-    NdisStatus = CONTROLnsRequestOut(pDevice,
-                                    1,
-                                    0x1200,
-                                    0x0000,
-                                    0,
-                                    NULL
-                                    );
-
-    if (NdisStatus != STATUS_SUCCESS) {
-        return (false);
-    } else {
-        return (true);
-    }
+	NdisStatus = CONTROLnsRequestOut(pDevice,
+					1,
+					0x1200,
+					0x0000,
+					0,
+					NULL);
+	if (NdisStatus != STATUS_SUCCESS)
+		return false;
+	else
+		return true;
 }
 
 int FIRMWAREbCheckVersion(struct vnt_private *pDevice)
 {
 	int ntStatus;
 
-    ntStatus = CONTROLnsRequestIn(pDevice,
-                                    MESSAGE_TYPE_READ,
-                                    0,
-                                    MESSAGE_REQUEST_VERSION,
-                                    2,
-                                    (u8 *) &(pDevice->wFirmwareVersion));
+	ntStatus = CONTROLnsRequestIn(pDevice,
+					MESSAGE_TYPE_READ,
+					0,
+					MESSAGE_REQUEST_VERSION,
+					2,
+					(u8 *) &(pDevice->wFirmwareVersion));
 
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Version [%04x]\n", pDevice->wFirmwareVersion);
-    if (ntStatus != STATUS_SUCCESS) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Invalid.\n");
-        return false;
-    }
-    if (pDevice->wFirmwareVersion == 0xFFFF) {
-        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"In Loader.\n");
-        return false;
-    }
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Version [%04x]\n", pDevice->wFirmwareVersion);
-    if (pDevice->wFirmwareVersion < FIRMWARE_VERSION) {
-        // branch to loader for download new firmware
-        FIRMWAREbBrach2Sram(pDevice);
-        return false;
-    }
-    return true;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Version [%04x]\n",
+						pDevice->wFirmwareVersion);
+	if (ntStatus != STATUS_SUCCESS) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Invalid.\n");
+		return false;
+	}
+	if (pDevice->wFirmwareVersion == 0xFFFF) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"In Loader.\n");
+		return false;
+	}
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Version [%04x]\n",
+						pDevice->wFirmwareVersion);
+	if (pDevice->wFirmwareVersion < FIRMWARE_VERSION) {
+		/* branch to loader for download new firmware */
+		FIRMWAREbBrach2Sram(pDevice);
+		return false;
+	}
+	return true;
 }
diff --git a/drivers/staging/vt6656/hostap.c b/drivers/staging/vt6656/hostap.c
index c699a30..ae1676d 100644
--- a/drivers/staging/vt6656/hostap.c
+++ b/drivers/staging/vt6656/hostap.c
@@ -414,7 +414,7 @@
 	int ret = 0;
 	s32 iNodeIndex = -1;
 	int ii;
-	int bKeyTableFull = false;
+	bool bKeyTableFull = false;
 	u16 wKeyCtl = 0;
 
 	param->u.crypt.err = 0;
@@ -685,7 +685,7 @@
 	    p->length > VIAWGET_HOSTAPD_MAX_BUF_SIZE || !p->pointer)
 		return -EINVAL;
 
-	param = kmalloc((int)p->length, (int)GFP_KERNEL);
+	param = kmalloc((int)p->length, GFP_KERNEL);
 	if (param == NULL)
 		return -ENOMEM;
 
diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c
index 8872e0f..63917ab 100644
--- a/drivers/staging/vt6656/iwctl.c
+++ b/drivers/staging/vt6656/iwctl.c
@@ -60,7 +60,7 @@
 	pDevice->wstats.status = pDevice->eOPMode;
 	if (pDevice->scStatistic.LinkQuality > 100)
 		pDevice->scStatistic.LinkQuality = 100;
-	pDevice->wstats.qual.qual =(u8)pDevice->scStatistic.LinkQuality;
+	pDevice->wstats.qual.qual = (u8)pDevice->scStatistic.LinkQuality;
 	RFvRSSITodBm(pDevice, (u8)(pDevice->uCurrRSSI), &ldBm);
 	pDevice->wstats.qual.level = ldBm;
 	pDevice->wstats.qual.noise = 0;
@@ -190,7 +190,7 @@
 		return -EAGAIN;
 	}
 	pBSS = &(pMgmt->sBSSList[0]);
-	for (ii = 0, jj = 0; jj < MAX_BSS_NUM ; jj++) {
+	for (ii = 0, jj = 0; jj < MAX_BSS_NUM; jj++) {
 		if (current_ev >= end_buf)
 			break;
 		pBSS = &(pMgmt->sBSSList[jj]);
@@ -225,7 +225,7 @@
 			iwe.u.freq.m = pBSS->uChannel;
 			iwe.u.freq.e = 0;
 			iwe.u.freq.i = 0;
-			current_ev = iwe_stream_add_event(info, current_ev,end_buf, &iwe, IW_EV_FREQ_LEN);
+			current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
 			{
 				int f = (int)pBSS->uChannel - 1;
 				if (f < 0)
@@ -400,7 +400,7 @@
 			if (pDevice->flags & DEVICE_FLAGS_OPENED)
 				pDevice->bCommit = true;
 		}
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to ad-hoc \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to ad-hoc\n");
 		break;
 	case IW_MODE_AUTO:
 	case IW_MODE_INFRA:
@@ -409,7 +409,7 @@
 			if (pDevice->flags & DEVICE_FLAGS_OPENED)
 				pDevice->bCommit = true;
 		}
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to infrastructure \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to infrastructure\n");
 		break;
 	case IW_MODE_MASTER:
 
@@ -422,7 +422,7 @@
 			if (pDevice->flags & DEVICE_FLAGS_OPENED)
 				pDevice->bCommit = true;
 		}
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to Access Point \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to Access Point\n");
 		break;
 
 	case IW_MODE_REPEAT:
@@ -657,8 +657,8 @@
 			unsigned uSameBssidNum = 0;
 			for (ii = 0; ii < MAX_BSS_NUM; ii++) {
 				if (pMgmt->sBSSList[ii].bActive &&
-					!compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID,
-							pMgmt->abyDesireBSSID)) {
+					ether_addr_equal(pMgmt->sBSSList[ii].abyBSSID,
+							 pMgmt->abyDesireBSSID)) {
 					uSameBssidNum++;
 				}
 			}
@@ -786,8 +786,8 @@
 	if (wrq->flags == 0) {
 		// Just send an empty SSID list
 		memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
-		memset(pMgmt->abyDesireBSSID, 0xFF,6);
-		PRINT_K("set essid to 'any' \n");
+		memset(pMgmt->abyDesireBSSID, 0xFF, 6);
+		PRINT_K("set essid to 'any'\n");
 		// Unknown desired AP, so here need not associate??
 		return 0;
 	} else {
@@ -798,15 +798,15 @@
 
 		memcpy(pItemSSID->abySSID, extra, wrq->length);
 		if (pItemSSID->abySSID[wrq->length] == '\0') {
-			if (wrq->length>0)
+			if (wrq->length > 0)
 				pItemSSID->len = wrq->length;
 		} else {
 			pItemSSID->len = wrq->length;
 		}
-		PRINT_K("set essid to %s \n", pItemSSID->abySSID);
+		PRINT_K("set essid to %s\n", pItemSSID->abySSID);
 
 		// mike: need clear desiredBSSID
-		if (pItemSSID->len==0) {
+		if (pItemSSID->len == 0) {
 			memset(pMgmt->abyDesireBSSID, 0xFF, 6);
 			return 0;
 		}
@@ -840,8 +840,8 @@
 				// are two same BSSID exist in list ?
 				for (ii = 0; ii < MAX_BSS_NUM; ii++) {
 					if (pMgmt->sBSSList[ii].bActive &&
-						!compare_ether_addr(pMgmt->sBSSList[ii].abyBSSID,
-								pCurr->abyBSSID)) {
+						ether_addr_equal(pMgmt->sBSSList[ii].abyBSSID,
+								 pCurr->abyBSSID)) {
 						uSameBssidNum++;
 					}
 				}
@@ -860,7 +860,7 @@
 			return 0;
 		}
 
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set essid = %s \n", pItemSSID->abySSID);
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set essid = %s\n", pItemSSID->abySSID);
 	}
 
 	if (pDevice->flags & DEVICE_FLAGS_OPENED)
@@ -893,7 +893,7 @@
 	memcpy(extra, pItemSSID->abySSID, pItemSSID->len);
 	extra[pItemSSID->len] = '\0';
 
-        wrq->length = pItemSSID->len;
+	wrq->length = pItemSSID->len;
 	wrq->flags = 1; // active
 
 	return 0;
@@ -915,7 +915,7 @@
 		0x60, 0x6C, 0x90
 	};
 
-	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRATE \n");
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRATE\n");
 	if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) {
 		rc = -EINVAL;
 		return rc;
@@ -953,7 +953,7 @@
 	}
 	// Check that it is valid
 	// brate is index of abySupportedRates[]
-	if (brate > 13 ) {
+	if (brate > 13) {
 		rc = -EINVAL;
 		return rc;
 	}
@@ -967,7 +967,7 @@
 			pDevice->uConnectionRate = 3;
 		} else {
 			pDevice->uConnectionRate = brate;
-			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Fixed to Rate %d \n", pDevice->uConnectionRate);
+			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Fixed to Rate %d\n", pDevice->uConnectionRate);
 		}
 	} else {
 		pDevice->bFixRate = false;
@@ -1017,7 +1017,7 @@
 			if (pDevice->byBBType == BB_TYPE_11A)
 				brate = 0x6C;
 		}
-    		if (pDevice->uConnectionRate == 13)
+		if (pDevice->uConnectionRate == 13)
 			brate = abySupportedRates[pDevice->wCurrentRate];
 		wrq->value = brate * 500000;
 		// If more than one rate, set auto
@@ -1286,7 +1286,7 @@
 	if (index < 1) { // get default key
 		if (pDevice->byKeyIndex < WLAN_WEP_NKEYS)
 			index = pDevice->byKeyIndex;
-         	else
+		else
 			index = 0;
 	} else {
 		index--;
@@ -1366,14 +1366,14 @@
 
 	switch (wrq->flags & IW_POWER_MODE) {
 	case IW_POWER_UNICAST_R:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_UNICAST_R \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_UNICAST_R\n");
 		rc = -EINVAL;
 		break;
 	case IW_POWER_ALL_R:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_ALL_R \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_ALL_R\n");
 		rc = -EINVAL;
 	case IW_POWER_ON:
-		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_ON \n");
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_ON\n");
 		break;
 	default:
 		rc = -EINVAL;
@@ -1465,7 +1465,7 @@
 	case IW_AUTH_CIPHER_PAIRWISE:
 		pairwise = wrq->value;
 		PRINT_K("iwctl_siwauth:set pairwise=%d\n", pairwise);
-		if (pairwise == IW_AUTH_CIPHER_CCMP){
+		if (pairwise == IW_AUTH_CIPHER_CCMP) {
 			pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
 		} else if (pairwise == IW_AUTH_CIPHER_TKIP) {
 			pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
@@ -1490,13 +1490,13 @@
 		}
 		break;
 	case IW_AUTH_KEY_MGMT:
-		PRINT_K("iwctl_siwauth(wpa_version=%d):set KEY_MGMT=%d\n", wpa_version,wrq->value);
-		if (wpa_version == IW_AUTH_WPA_VERSION_WPA2){
+		PRINT_K("iwctl_siwauth(wpa_version=%d):set KEY_MGMT=%d\n", wpa_version, wrq->value);
+		if (wpa_version == IW_AUTH_WPA_VERSION_WPA2) {
 			if (wrq->value == IW_AUTH_KEY_MGMT_PSK)
 				pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK;
 			else pMgmt->eAuthenMode = WMAC_AUTH_WPA2;
 		} else if (wpa_version == IW_AUTH_WPA_VERSION_WPA) {
-			if (wrq->value == 0){
+			if (wrq->value == 0) {
 				pMgmt->eAuthenMode = WMAC_AUTH_WPANONE;
 			} else if (wrq->value == IW_AUTH_KEY_MGMT_PSK)
 				pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK;
@@ -1558,17 +1558,17 @@
 	if (pMgmt == NULL)
 		return -EFAULT;
 
-	if (wrq->length){
+	if (wrq->length) {
 		if ((wrq->length < 2) || (extra[1] + 2 != wrq->length)) {
 			ret = -EINVAL;
 			goto out;
 		}
-		if (wrq->length > MAX_WPA_IE_LEN){
+		if (wrq->length > MAX_WPA_IE_LEN) {
 			ret = -ENOMEM;
 			goto out;
 		}
 		memset(pMgmt->abyWPAIE, 0, MAX_WPA_IE_LEN);
-		if (copy_from_user(pMgmt->abyWPAIE, extra, wrq->length)){
+		if (copy_from_user(pMgmt->abyWPAIE, extra, wrq->length)) {
 			ret = -EFAULT;
 			goto out;
 		}
@@ -1615,7 +1615,7 @@
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
 	struct iw_point *wrq = &wrqu->encoding;
 	struct iw_encode_ext *ext = (struct iw_encode_ext*)extra;
-	struct viawget_wpa_param *param=NULL;
+	struct viawget_wpa_param *param = NULL;
 // original member
 	wpa_alg alg_name;
 	u8 addr[6];
@@ -1658,8 +1658,8 @@
 		alg_name = WPA_ALG_CCMP;
 		break;
 	default:
-		PRINT_K("Unknown alg = %d\n",ext->alg);
-		ret= -ENOMEM;
+		PRINT_K("Unknown alg = %d\n", ext->alg);
+		ret = -ENOMEM;
 		goto error;
 	}
 // recover addr
@@ -1671,7 +1671,7 @@
 		set_tx = 1;
 // recover seq,seq_len
 	if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
-		seq_len=IW_ENCODE_SEQ_MAX_SIZE;
+		seq_len = IW_ENCODE_SEQ_MAX_SIZE;
 		memcpy(seq, ext->rx_seq, seq_len);
 	}
 // recover key,key_len
@@ -1702,7 +1702,7 @@
 /****set if current action is Network Manager count?? */
 /****this method is so foolish,but there is no other way??? */
 	if (param->u.wpa_key.alg_name == WPA_ALG_NONE) {
-		if (param->u.wpa_key.key_index ==0) {
+		if (param->u.wpa_key.key_index == 0) {
 			pDevice->bwextstep0 = true;
 		}
 		if ((pDevice->bwextstep0 == true) && (param->u.wpa_key.key_index == 1)) {
@@ -1761,7 +1761,7 @@
 		ret = -EINVAL;
 		return ret;
 	}
-	switch (mlme->cmd){
+	switch (mlme->cmd) {
 	case IW_MLME_DEAUTH:
 	case IW_MLME_DISASSOC:
 		if (pDevice->bLinkPass == true) {
@@ -1815,7 +1815,6 @@
 	IW_HANDLER(SIOCGIWPOWER, iwctl_giwpower),
 	IW_HANDLER(SIOCSIWGENIE, iwctl_siwgenie),
 	IW_HANDLER(SIOCGIWGENIE, iwctl_giwgenie),
-	IW_HANDLER(SIOCSIWMLME, iwctl_siwmlme),
 	IW_HANDLER(SIOCSIWAUTH, iwctl_siwauth),
 	IW_HANDLER(SIOCGIWAUTH, iwctl_giwauth),
 	IW_HANDLER(SIOCSIWENCODEEXT, iwctl_siwencodeext),
diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c
index 205590b..be92c04 100644
--- a/drivers/staging/vt6656/key.c
+++ b/drivers/staging/vt6656/key.c
@@ -151,7 +151,7 @@
     *pKey = NULL;
     for (i=0;i<MAX_KEY_TABLE;i++) {
         if ((pTable->KeyTable[i].bInUse == true) &&
-	    !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+	    ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
             if (dwKeyIndex == 0xFFFFFFFF) {
                 if (pTable->KeyTable[i].PairwiseKey.bKeyValid == true) {
                     *pKey = &(pTable->KeyTable[i].PairwiseKey);
@@ -213,7 +213,7 @@
             j = i;
         }
         if ((pTable->KeyTable[i].bInUse == true) &&
-	    !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+	    ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
             // found table already exist
             if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
                 // Pairwise key
@@ -395,7 +395,7 @@
     } else {
         for (i=0;i<MAX_KEY_TABLE;i++) {
             if ( (pTable->KeyTable[i].bInUse == true) &&
-		 !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+		 ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
 
                 if ((dwKeyIndex & PAIRWISE_KEY) != 0) {
                     pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
@@ -445,7 +445,7 @@
 
     for (i=0;i<MAX_KEY_TABLE;i++) {
         if ((pTable->KeyTable[i].bInUse == true) &&
-	    !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+	    ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
             pTable->KeyTable[i].PairwiseKey.bKeyValid = false;
 	    for (u = 0; u < MAX_GROUP_KEY; u++)
 		pTable->KeyTable[i].GroupKey[u].bKeyValid = false;
@@ -480,7 +480,7 @@
 
     for (i = 0; i < MAX_KEY_TABLE; i++) {
         if ((pTable->KeyTable[i].bInUse == true) &&
-	    !compare_ether_addr(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
+	    ether_addr_equal(pTable->KeyTable[i].abyBSSID, pbyBSSID)) {
 
             if (dwKeyType == PAIRWISE_KEY) {
 
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index 6f9d281..aae228c 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -702,6 +702,16 @@
 
 	device_set_options(pDevice);
 	spin_lock_init(&pDevice->lock);
+	INIT_DELAYED_WORK(&pDevice->run_command_work, vRunCommand);
+	INIT_DELAYED_WORK(&pDevice->second_callback_work, BSSvSecondCallBack);
+	INIT_WORK(&pDevice->read_work_item, RXvWorkItem);
+	INIT_WORK(&pDevice->rx_mng_work_item, RXvMngWorkItem);
+
+	pDevice->pControlURB = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!pDevice->pControlURB) {
+		DBG_PRT(MSG_LEVEL_ERR, KERN_ERR"Failed to alloc control urb\n");
+		goto err_netdev;
+	}
 
 	pDevice->tx_80211 = device_dma0_tx_80211;
 	pDevice->vnt_mgmt.pAdapter = (void *) pDevice;
@@ -713,14 +723,15 @@
 	usb_set_intfdata(intf, pDevice);
 	SET_NETDEV_DEV(netdev, &intf->dev);
 	memcpy(pDevice->dev->dev_addr, fake_mac, ETH_ALEN);
+
+	usb_device_reset(pDevice);
+
 	rc = register_netdev(netdev);
 	if (rc) {
 		printk(KERN_ERR DEVICE_NAME " Failed to register netdev\n");
 		goto err_netdev;
 	}
 
-	usb_device_reset(pDevice);
-
 	return 0;
 
 err_netdev:
@@ -849,23 +860,15 @@
         pRCB++;
     }
 
-	pDevice->pControlURB = usb_alloc_urb(0, GFP_ATOMIC);
-	if (pDevice->pControlURB == NULL) {
-	    DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc control urb\n");
-	    goto free_rx_tx;
-	}
-
 	pDevice->pInterruptURB = usb_alloc_urb(0, GFP_ATOMIC);
 	if (pDevice->pInterruptURB == NULL) {
 	    DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc int urb\n");
-	    usb_free_urb(pDevice->pControlURB);
 	    goto free_rx_tx;
 	}
 
     pDevice->intBuf.pDataBuf = kmalloc(MAX_INTERRUPT_SIZE, GFP_KERNEL);
 	if (pDevice->intBuf.pDataBuf == NULL) {
 	    DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc int buf\n");
-	    usb_free_urb(pDevice->pControlURB);
 	    usb_free_urb(pDevice->pInterruptURB);
 	    goto free_rx_tx;
 	}
@@ -981,10 +984,11 @@
     }
 
     vMgrObjectInit(pDevice);
-    tasklet_init(&pDevice->RxMngWorkItem, (void *)RXvMngWorkItem, (unsigned long)pDevice);
-    tasklet_init(&pDevice->ReadWorkItem, (void *)RXvWorkItem, (unsigned long)pDevice);
+
     tasklet_init(&pDevice->EventWorkItem, (void *)INTvWorkItem, (unsigned long)pDevice);
-	add_timer(&pDevice->vnt_mgmt.sTimerSecondCallback);
+
+	schedule_delayed_work(&pDevice->second_callback_work, HZ);
+
 	pDevice->int_interval = 100;  /* max 100 microframes */
     pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
 
@@ -1000,7 +1004,7 @@
      pDevice->bWPASuppWextEnabled = false;
     pDevice->byReAssocCount = 0;
 
-    RXvWorkItem(pDevice);
+	schedule_work(&pDevice->read_work_item);
     INTvWorkItem(pDevice);
 
     /* if WEP key already set by iwconfig but device not yet open */
@@ -1035,9 +1039,7 @@
     device_free_rx_bufs(pDevice);
     device_free_tx_bufs(pDevice);
     device_free_int_bufs(pDevice);
-	usb_kill_urb(pDevice->pControlURB);
 	usb_kill_urb(pDevice->pInterruptURB);
-    usb_free_urb(pDevice->pControlURB);
     usb_free_urb(pDevice->pInterruptURB);
 
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_open fail.. \n");
@@ -1076,18 +1078,19 @@
     MP_CLEAR_FLAG(pDevice, fMP_POST_WRITES);
     MP_CLEAR_FLAG(pDevice, fMP_POST_READS);
     pDevice->fKillEventPollingThread = true;
-    del_timer(&pDevice->sTimerCommand);
-    del_timer(&pMgmt->sTimerSecondCallback);
 
-    del_timer(&pDevice->sTimerTxData);
+	cancel_delayed_work_sync(&pDevice->run_command_work);
+	cancel_delayed_work_sync(&pDevice->second_callback_work);
 
     if (pDevice->bDiversityRegCtlON) {
         del_timer(&pDevice->TimerSQ3Tmax1);
         del_timer(&pDevice->TimerSQ3Tmax2);
         del_timer(&pDevice->TimerSQ3Tmax3);
     }
-    tasklet_kill(&pDevice->RxMngWorkItem);
-    tasklet_kill(&pDevice->ReadWorkItem);
+
+	cancel_work_sync(&pDevice->rx_mng_work_item);
+	cancel_work_sync(&pDevice->read_work_item);
+
     tasklet_kill(&pDevice->EventWorkItem);
 
    pDevice->bRoaming = false;
@@ -1105,9 +1108,7 @@
     device_free_int_bufs(pDevice);
     device_free_frag_bufs(pDevice);
 
-	usb_kill_urb(pDevice->pControlURB);
 	usb_kill_urb(pDevice->pInterruptURB);
-    usb_free_urb(pDevice->pControlURB);
     usb_free_urb(pDevice->pInterruptURB);
 
     BSSvClearNodeDBTable(pDevice, 0);
@@ -1131,9 +1132,12 @@
 
 	if (device->dev) {
 		unregister_netdev(device->dev);
+
+		usb_kill_urb(device->pControlURB);
+		usb_free_urb(device->pControlURB);
+
 		free_netdev(device->dev);
 	}
-
 }
 
 static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev)
diff --git a/drivers/staging/vt6656/power.c b/drivers/staging/vt6656/power.c
index edc8975..e7d5487 100644
--- a/drivers/staging/vt6656/power.c
+++ b/drivers/staging/vt6656/power.c
@@ -233,9 +233,8 @@
 	pTxPacket->cbPayloadLen = 0;
 
 	/* log failure if sending failed */
-	if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) {
+	if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING)
 		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send PS-Poll packet failed..\n");
-	}
 }
 
 /*
@@ -257,10 +256,8 @@
 	if (pDevice->bLinkPass == false)
 		return false;
 
-	if ((pDevice->bEnablePSMode == false) &&
-		(pDevice->fTxDataInSleep == false)) {
-			return false;
-	}
+	if (pDevice->bEnablePSMode == false && pDevice->tx_trigger == false)
+		return false;
 
 	memset(pMgmt->pbyPSPacketPool, 0, sizeof(struct vnt_tx_mgmt)
 		+ WLAN_NULLDATA_FR_MAXLEN);
@@ -269,7 +266,7 @@
 		+ sizeof(struct vnt_tx_mgmt));
 
 	flags = WLAN_SET_FC_FTYPE(WLAN_TYPE_DATA) |
-                        WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_NULL);
+			WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_NULL);
 
 	if (pDevice->bEnablePSMode)
 		flags |= WLAN_SET_FC_PWRMGT(1);
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index 14f3e85..35a3ddb 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -98,21 +98,18 @@
 
 static void *s_vGetFreeContext(struct vnt_private *pDevice);
 
-static void s_vGenerateTxParameter(struct vnt_private *pDevice,
-	u8 byPktType, u16 wCurrentRate,	void *pTxBufHead, void *pvRrvTime,
-	void *rts_cts, u32 cbFrameSize, int bNeedACK, u32 uDMAIdx,
-	struct ethhdr *psEthHeader, bool need_rts);
-
-static u32 s_uFillDataHead(struct vnt_private *pDevice,
-	u8 byPktType, u16 wCurrentRate, void *pTxDataHead, u32 cbFrameLength,
-	u32 uDMAIdx, int bNeedAck, u8 byFBOption);
+static u16 s_vGenerateTxParameter(struct vnt_private *pDevice,
+	u8 byPktType, u16 wCurrentRate,	struct vnt_tx_buffer *tx_buffer,
+	struct vnt_mic_hdr **mic_hdr, u32 need_mic, u32 cbFrameSize,
+	int bNeedACK, u32 uDMAIdx, struct ethhdr *psEthHeader, bool need_rts);
 
 static void s_vGenerateMACHeader(struct vnt_private *pDevice,
 	u8 *pbyBufferAddr, u16 wDuration, struct ethhdr *psEthHeader,
 	int bNeedEncrypt, u16 wFragType, u32 uDMAIdx, u32 uFragIdx);
 
-static void s_vFillTxKey(struct vnt_private *pDevice, u8 *pbyBuf,
-	u8 *pbyIVHead, PSKeyItem pTransmitKey, u8 *pbyHdrBuf, u16 wPayloadLen,
+static void s_vFillTxKey(struct vnt_private *pDevice,
+	struct vnt_tx_fifo_head *fifo_head, u8 *pbyIVHead,
+	PSKeyItem pTransmitKey, u8 *pbyHdrBuf, u16 wPayloadLen,
 	struct vnt_mic_hdr *mic_hdr);
 
 static void s_vSWencryption(struct vnt_private *pDevice,
@@ -124,11 +121,11 @@
 static u16 s_uGetRTSCTSRsvTime(struct vnt_private *pDevice, u8 byRTSRsvType,
 	u8 byPktType, u32 cbFrameLength, u16 wCurrentRate);
 
-static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
+static u16 s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
 	u8 byPktType, union vnt_tx_data_head *head, u32 cbFrameLength,
 	int bNeedAck, u16 wCurrentRate, u8 byFBOption);
 
-static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
+static u16 s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 	union vnt_tx_data_head *head, u32 cbFrameLength, int bNeedAck,
 	struct ethhdr *psEthHeader, u16 wCurrentRate, u8 byFBOption);
 
@@ -183,10 +180,12 @@
 	   ETH_ALEN);
 }
 
-static void s_vFillTxKey(struct vnt_private *pDevice, u8 *pbyBuf,
-	u8 *pbyIVHead, PSKeyItem pTransmitKey, u8 *pbyHdrBuf,
-	u16 wPayloadLen, struct vnt_mic_hdr *mic_hdr)
+static void s_vFillTxKey(struct vnt_private *pDevice,
+	struct vnt_tx_fifo_head *fifo_head, u8 *pbyIVHead,
+	PSKeyItem pTransmitKey, u8 *pbyHdrBuf, u16 wPayloadLen,
+	struct vnt_mic_hdr *mic_hdr)
 {
+	u8 *pbyBuf = (u8 *)&fifo_head->adwTxKey[0];
 	u32 *pdwIV = (u32 *)pbyIVHead;
 	u32 *pdwExtIV = (u32 *)((u8 *)pbyIVHead + 4);
 	struct ieee80211_hdr *pMACHeader = (struct ieee80211_hdr *)pbyHdrBuf;
@@ -431,185 +430,114 @@
 {
 	u32 uCTSTime = 0, uDurTime = 0;
 
-    switch (byDurType) {
+	switch (byDurType) {
+	case RTSDUR_BB:
+	case RTSDUR_BA:
+	case RTSDUR_BA_F0:
+	case RTSDUR_BA_F1:
+		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType,
+			14, pDevice->byTopCCKBasicRate);
+		uDurTime = uCTSTime + 2 * pDevice->uSIFS +
+			s_uGetTxRsvTime(pDevice, byPktType,
+						cbFrameLength, wRate, bNeedAck);
+		break;
 
-    case RTSDUR_BB:    //RTSDuration_bb
-        uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
-        uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
-        break;
+	case RTSDUR_AA:
+	case RTSDUR_AA_F0:
+	case RTSDUR_AA_F1:
+		uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType,
+			14, pDevice->byTopOFDMBasicRate);
+		uDurTime = uCTSTime + 2 * pDevice->uSIFS +
+			s_uGetTxRsvTime(pDevice, byPktType,
+						cbFrameLength, wRate, bNeedAck);
+		break;
 
-    case RTSDUR_BA:    //RTSDuration_ba
-        uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
-        uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
-        break;
+	case CTSDUR_BA:
+	case CTSDUR_BA_F0:
+	case CTSDUR_BA_F1:
+		uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice,
+				byPktType, cbFrameLength, wRate, bNeedAck);
+		break;
 
-    case RTSDUR_AA:    //RTSDuration_aa
-        uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
-        uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
-        break;
-
-    case CTSDUR_BA:    //CTSDuration_ba
-        uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
-        break;
-
-    case RTSDUR_BA_F0: //RTSDuration_ba_f0
-        uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
-        if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
-        } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);
-        }
-        break;
-
-    case RTSDUR_AA_F0: //RTSDuration_aa_f0
-        uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
-        if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
-        } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);
-        }
-        break;
-
-    case RTSDUR_BA_F1: //RTSDuration_ba_f1
-        uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate);
-        if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
-        } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
-        }
-        break;
-
-    case RTSDUR_AA_F1: //RTSDuration_aa_f1
-        uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate);
-        if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
-        } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
-        }
-        break;
-
-    case CTSDUR_BA_F0: //CTSDuration_ba_f0
-        if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck);
-        } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck);
-        }
-        break;
-
-    case CTSDUR_BA_F1: //CTSDuration_ba_f1
-        if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck);
-        } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) {
-            uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck);
-        }
-        break;
-
-    default:
-        break;
-    }
+	default:
+		break;
+	}
 
 	return cpu_to_le16((u16)uDurTime);
 }
 
-static u32 s_uFillDataHead(struct vnt_private *pDevice,
-	u8 byPktType, u16 wCurrentRate, void *pTxDataHead, u32 cbFrameLength,
-	u32 uDMAIdx, int bNeedAck, u8 byFBOption)
+static u16 vnt_rxtx_datahead_g(struct vnt_private *priv, u8 pkt_type, u16 rate,
+		struct vnt_tx_datahead_g *buf, u32 frame_len, int need_ack)
 {
+	/* Get SignalField,ServiceField,Length */
+	BBvCalculateParameter(priv, frame_len, rate, pkt_type, &buf->a);
+	BBvCalculateParameter(priv, frame_len, priv->byTopCCKBasicRate,
+							PK_TYPE_11B, &buf->b);
 
-    if (pTxDataHead == NULL) {
-        return 0;
-    }
+	/* Get Duration and TimeStamp */
+	buf->wDuration_a = s_uGetDataDuration(priv, pkt_type, need_ack);
+	buf->wDuration_b = s_uGetDataDuration(priv, PK_TYPE_11B, need_ack);
 
-    if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
-            if (byFBOption == AUTO_FB_NONE) {
-		struct vnt_tx_datahead_g *pBuf =
-				(struct vnt_tx_datahead_g *)pTxDataHead;
-                //Get SignalField,ServiceField,Length
-		BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
-			byPktType, &pBuf->a);
-		BBvCalculateParameter(pDevice, cbFrameLength,
-			pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b);
-                //Get Duration and TimeStamp
-		pBuf->wDuration_a = s_uGetDataDuration(pDevice,
-							byPktType, bNeedAck);
-		pBuf->wDuration_b = s_uGetDataDuration(pDevice,
-							PK_TYPE_11B, bNeedAck);
+	buf->wTimeStampOff_a = vnt_time_stamp_off(priv, rate);
+	buf->wTimeStampOff_b = vnt_time_stamp_off(priv,
+					priv->byTopCCKBasicRate);
 
-		pBuf->wTimeStampOff_a =	vnt_time_stamp_off(pDevice,
-								wCurrentRate);
-		pBuf->wTimeStampOff_b = vnt_time_stamp_off(pDevice,
-						pDevice->byTopCCKBasicRate);
-                return (pBuf->wDuration_a);
-             } else {
-                // Auto Fallback
-		struct vnt_tx_datahead_g_fb *pBuf =
-			(struct vnt_tx_datahead_g_fb *)pTxDataHead;
-                //Get SignalField,ServiceField,Length
-		BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
-			byPktType, &pBuf->a);
-		BBvCalculateParameter(pDevice, cbFrameLength,
-			pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b);
-                //Get Duration and TimeStamp
-		pBuf->wDuration_a = s_uGetDataDuration(pDevice,
-							byPktType, bNeedAck);
-		pBuf->wDuration_b = s_uGetDataDuration(pDevice,
-							PK_TYPE_11B, bNeedAck);
-		pBuf->wDuration_a_f0 = s_uGetDataDuration(pDevice,
-							byPktType, bNeedAck);
-		pBuf->wDuration_a_f1 = s_uGetDataDuration(pDevice,
-							byPktType, bNeedAck);
-		pBuf->wTimeStampOff_a = vnt_time_stamp_off(pDevice,
-								wCurrentRate);
-		pBuf->wTimeStampOff_b = vnt_time_stamp_off(pDevice,
-						pDevice->byTopCCKBasicRate);
-                return (pBuf->wDuration_a);
-            } //if (byFBOption == AUTO_FB_NONE)
-    }
-    else if (byPktType == PK_TYPE_11A) {
-	if (byFBOption != AUTO_FB_NONE) {
-		struct vnt_tx_datahead_a_fb *pBuf =
-			(struct vnt_tx_datahead_a_fb *)pTxDataHead;
-            //Get SignalField,ServiceField,Length
-		BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
-			byPktType, &pBuf->a);
-            //Get Duration and TimeStampOff
-		pBuf->wDuration = s_uGetDataDuration(pDevice,
-					byPktType, bNeedAck);
-		pBuf->wDuration_f0 = s_uGetDataDuration(pDevice,
-					byPktType, bNeedAck);
-		pBuf->wDuration_f1 = s_uGetDataDuration(pDevice,
-							byPktType, bNeedAck);
-		pBuf->wTimeStampOff = vnt_time_stamp_off(pDevice,
-								wCurrentRate);
-            return (pBuf->wDuration);
-        } else {
-		struct vnt_tx_datahead_ab *pBuf =
-			(struct vnt_tx_datahead_ab *)pTxDataHead;
-            //Get SignalField,ServiceField,Length
-		BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
-			byPktType, &pBuf->ab);
-            //Get Duration and TimeStampOff
-		pBuf->wDuration = s_uGetDataDuration(pDevice,
-				byPktType, bNeedAck);
-		pBuf->wTimeStampOff = vnt_time_stamp_off(pDevice,
-								wCurrentRate);
-            return (pBuf->wDuration);
-        }
-    }
-    else if (byPktType == PK_TYPE_11B) {
-		struct vnt_tx_datahead_ab *pBuf =
-			(struct vnt_tx_datahead_ab *)pTxDataHead;
-            //Get SignalField,ServiceField,Length
-		BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
-			byPktType, &pBuf->ab);
-            //Get Duration and TimeStampOff
-		pBuf->wDuration = s_uGetDataDuration(pDevice,
-				byPktType, bNeedAck);
-		pBuf->wTimeStampOff = vnt_time_stamp_off(pDevice,
-								wCurrentRate);
-            return (pBuf->wDuration);
-    }
-    return 0;
+	return buf->wDuration_a;
+}
+
+static u16 vnt_rxtx_datahead_g_fb(struct vnt_private *priv, u8 pkt_type,
+		u16 rate, struct vnt_tx_datahead_g_fb *buf,
+		u32 frame_len, int need_ack)
+{
+	/* Get SignalField,ServiceField,Length */
+	BBvCalculateParameter(priv, frame_len, rate, pkt_type, &buf->a);
+
+	BBvCalculateParameter(priv, frame_len, priv->byTopCCKBasicRate,
+						PK_TYPE_11B, &buf->b);
+
+	/* Get Duration and TimeStamp */
+	buf->wDuration_a = s_uGetDataDuration(priv, pkt_type, need_ack);
+	buf->wDuration_b = s_uGetDataDuration(priv, PK_TYPE_11B, need_ack);
+
+	buf->wDuration_a_f0 = s_uGetDataDuration(priv, pkt_type, need_ack);
+	buf->wDuration_a_f1 = s_uGetDataDuration(priv, pkt_type, need_ack);
+
+	buf->wTimeStampOff_a = vnt_time_stamp_off(priv, rate);
+	buf->wTimeStampOff_b = vnt_time_stamp_off(priv,
+						priv->byTopCCKBasicRate);
+
+	return buf->wDuration_a;
+}
+
+static u16 vnt_rxtx_datahead_a_fb(struct vnt_private *priv, u8 pkt_type,
+		u16 rate, struct vnt_tx_datahead_a_fb *buf,
+		u32 frame_len, int need_ack)
+{
+	/* Get SignalField,ServiceField,Length */
+	BBvCalculateParameter(priv, frame_len, rate, pkt_type, &buf->a);
+	/* Get Duration and TimeStampOff */
+	buf->wDuration = s_uGetDataDuration(priv, pkt_type, need_ack);
+
+	buf->wDuration_f0 = s_uGetDataDuration(priv, pkt_type, need_ack);
+	buf->wDuration_f1 = s_uGetDataDuration(priv, pkt_type, need_ack);
+
+	buf->wTimeStampOff = vnt_time_stamp_off(priv, rate);
+
+	return buf->wDuration;
+}
+
+static u16 vnt_rxtx_datahead_ab(struct vnt_private *priv, u8 pkt_type,
+		u16 rate, struct vnt_tx_datahead_ab *buf,
+		u32 frame_len, int need_ack)
+{
+	/* Get SignalField,ServiceField,Length */
+	BBvCalculateParameter(priv, frame_len, rate, pkt_type, &buf->ab);
+	/* Get Duration and TimeStampOff */
+	buf->wDuration = s_uGetDataDuration(priv, pkt_type, need_ack);
+
+	buf->wTimeStampOff = vnt_time_stamp_off(priv, rate);
+
+	return buf->wDuration;
 }
 
 static int vnt_fill_ieee80211_rts(struct vnt_private *priv,
@@ -632,7 +560,7 @@
 	return 0;
 }
 
-static int vnt_rxtx_rts_g_head(struct vnt_private *priv,
+static u16 vnt_rxtx_rts_g_head(struct vnt_private *priv,
 	struct vnt_rts_g *buf, struct ethhdr *eth_hdr,
 	u8 pkt_type, u32 frame_len, int need_ack,
 	u16 current_rate, u8 fb_option)
@@ -653,10 +581,11 @@
 
 	vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->wDuration_aa);
 
-	return 0;
+	return vnt_rxtx_datahead_g(priv, pkt_type, current_rate,
+			&buf->data_head, frame_len, need_ack);
 }
 
-static int vnt_rxtx_rts_g_fb_head(struct vnt_private *priv,
+static u16 vnt_rxtx_rts_g_fb_head(struct vnt_private *priv,
 	struct vnt_rts_g_fb *buf, struct ethhdr *eth_hdr,
 	u8 pkt_type, u32 frame_len, int need_ack,
 	u16 current_rate, u8 fb_option)
@@ -678,20 +607,21 @@
 
 
 	buf->wRTSDuration_ba_f0 = s_uGetRTSCTSDuration(priv, RTSDUR_BA_F0,
-		frame_len, pkt_type, current_rate, need_ack, fb_option);
+		frame_len, pkt_type, priv->tx_rate_fb0, need_ack, fb_option);
 	buf->wRTSDuration_aa_f0 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F0,
-		frame_len, pkt_type, current_rate, need_ack, fb_option);
+		frame_len, pkt_type, priv->tx_rate_fb0, need_ack, fb_option);
 	buf->wRTSDuration_ba_f1 = s_uGetRTSCTSDuration(priv, RTSDUR_BA_F1,
-		frame_len, pkt_type, current_rate, need_ack, fb_option);
+		frame_len, pkt_type, priv->tx_rate_fb1, need_ack, fb_option);
 	buf->wRTSDuration_aa_f1 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F1,
-		frame_len, pkt_type, current_rate, need_ack, fb_option);
+		frame_len, pkt_type, priv->tx_rate_fb1, need_ack, fb_option);
 
 	vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->wDuration_aa);
 
-	return 0;
+	return vnt_rxtx_datahead_g_fb(priv, pkt_type, current_rate,
+			&buf->data_head, frame_len, need_ack);
 }
 
-static int vnt_rxtx_rts_ab_head(struct vnt_private *priv,
+static u16 vnt_rxtx_rts_ab_head(struct vnt_private *priv,
 	struct vnt_rts_ab *buf, struct ethhdr *eth_hdr,
 	u8 pkt_type, u32 frame_len, int need_ack,
 	u16 current_rate, u8 fb_option)
@@ -706,10 +636,11 @@
 
 	vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->wDuration);
 
-	return 0;
+	return vnt_rxtx_datahead_ab(priv, pkt_type, current_rate,
+			&buf->data_head, frame_len, need_ack);
 }
 
-static int vnt_rxtx_rts_a_fb_head(struct vnt_private *priv,
+static u16 vnt_rxtx_rts_a_fb_head(struct vnt_private *priv,
 	struct vnt_rts_a_fb *buf, struct ethhdr *eth_hdr,
 	u8 pkt_type, u32 frame_len, int need_ack,
 	u16 current_rate, u8 fb_option)
@@ -723,23 +654,24 @@
 		pkt_type, current_rate, need_ack, fb_option);
 
 	buf->wRTSDuration_f0 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F0,
-		frame_len, pkt_type, current_rate, need_ack, fb_option);
+		frame_len, pkt_type, priv->tx_rate_fb0, need_ack, fb_option);
 
 	buf->wRTSDuration_f1 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F1,
-		frame_len, pkt_type, current_rate, need_ack, fb_option);
+		frame_len, pkt_type, priv->tx_rate_fb1, need_ack, fb_option);
 
 	vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->wDuration);
 
-	return 0;
+	return vnt_rxtx_datahead_a_fb(priv, pkt_type, current_rate,
+			&buf->data_head, frame_len, need_ack);
 }
 
-static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
+static u16 s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 	union vnt_tx_data_head *head, u32 cbFrameLength, int bNeedAck,
 	struct ethhdr *psEthHeader, u16 wCurrentRate, u8 byFBOption)
 {
 
 	if (!head)
-		return;
+		return 0;
 
 	/* Note: So far RTSHead doesn't appear in ATIM
 	*	& Beacom DMA, so we don't need to take them
@@ -750,36 +682,38 @@
 	case PK_TYPE_11GB:
 	case PK_TYPE_11GA:
 		if (byFBOption == AUTO_FB_NONE)
-			vnt_rxtx_rts_g_head(pDevice, &head->rts_g,
+			return vnt_rxtx_rts_g_head(pDevice, &head->rts_g,
 				psEthHeader, byPktType, cbFrameLength,
 				bNeedAck, wCurrentRate, byFBOption);
 		else
-			vnt_rxtx_rts_g_fb_head(pDevice, &head->rts_g_fb,
+			return vnt_rxtx_rts_g_fb_head(pDevice, &head->rts_g_fb,
 				psEthHeader, byPktType, cbFrameLength,
 				bNeedAck, wCurrentRate, byFBOption);
 		break;
 	case PK_TYPE_11A:
 		if (byFBOption) {
-			vnt_rxtx_rts_a_fb_head(pDevice, &head->rts_a_fb,
+			return vnt_rxtx_rts_a_fb_head(pDevice, &head->rts_a_fb,
 				psEthHeader, byPktType, cbFrameLength,
 				bNeedAck, wCurrentRate, byFBOption);
 			break;
 		}
 	case PK_TYPE_11B:
-		vnt_rxtx_rts_ab_head(pDevice, &head->rts_ab,
+		return vnt_rxtx_rts_ab_head(pDevice, &head->rts_ab,
 			psEthHeader, byPktType, cbFrameLength,
 			bNeedAck, wCurrentRate, byFBOption);
 	}
+
+	return 0;
 }
 
-static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
+static u16 s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
 	u8 byPktType, union vnt_tx_data_head *head, u32 cbFrameLength,
 	int bNeedAck, u16 wCurrentRate, u8 byFBOption)
 {
 	u32 uCTSFrameLen = 14;
 
 	if (!head)
-		return;
+		return 0;
 
 	if (byFBOption != AUTO_FB_NONE) {
 		/* Auto Fall back */
@@ -792,16 +726,19 @@
 			wCurrentRate, bNeedAck, byFBOption);
 		/* Get CTSDuration_ba_f0 */
 		pBuf->wCTSDuration_ba_f0 = s_uGetRTSCTSDuration(pDevice,
-			CTSDUR_BA_F0, cbFrameLength, byPktType, wCurrentRate,
-			bNeedAck, byFBOption);
+			CTSDUR_BA_F0, cbFrameLength, byPktType,
+			pDevice->tx_rate_fb0, bNeedAck, byFBOption);
 		/* Get CTSDuration_ba_f1 */
 		pBuf->wCTSDuration_ba_f1 = s_uGetRTSCTSDuration(pDevice,
-			CTSDUR_BA_F1, cbFrameLength, byPktType, wCurrentRate,
-			bNeedAck, byFBOption);
+			CTSDUR_BA_F1, cbFrameLength, byPktType,
+			pDevice->tx_rate_fb1, bNeedAck, byFBOption);
 		/* Get CTS Frame body */
 		pBuf->data.duration = pBuf->wDuration_ba;
 		pBuf->data.frame_control = TYPE_CTL_CTS;
 		memcpy(pBuf->data.ra, pDevice->abyCurrentNetAddr, ETH_ALEN);
+
+		return vnt_rxtx_datahead_g_fb(pDevice, byPktType, wCurrentRate,
+				&pBuf->data_head, cbFrameLength, bNeedAck);
 	} else {
 		struct vnt_cts *pBuf = &head->cts_g;
 		/* Get SignalField,ServiceField,Length */
@@ -815,7 +752,12 @@
 		pBuf->data.duration = pBuf->wDuration_ba;
 		pBuf->data.frame_control = TYPE_CTL_CTS;
 		memcpy(pBuf->data.ra, pDevice->abyCurrentNetAddr, ETH_ALEN);
+
+		return vnt_rxtx_datahead_g(pDevice, byPktType, wCurrentRate,
+				&pBuf->data_head, cbFrameLength, bNeedAck);
         }
+
+	return 0;
 }
 
 /*+
@@ -841,112 +783,160 @@
  *
 -*/
 
-static void s_vGenerateTxParameter(struct vnt_private *pDevice,
-	u8 byPktType, u16 wCurrentRate,	void *pTxBufHead, void *pvRrvTime,
-	void *rts_cts, u32 cbFrameSize, int bNeedACK, u32 uDMAIdx,
-	struct ethhdr *psEthHeader, bool need_rts)
+static u16 s_vGenerateTxParameter(struct vnt_private *pDevice,
+	u8 byPktType, u16 wCurrentRate,	struct vnt_tx_buffer *tx_buffer,
+	struct vnt_mic_hdr **mic_hdr, u32 need_mic, u32 cbFrameSize,
+	int bNeedACK, u32 uDMAIdx, struct ethhdr *psEthHeader, bool need_rts)
 {
-	union vnt_tx_data_head *head = rts_cts;
+	struct vnt_tx_fifo_head *pFifoHead = &tx_buffer->fifo_head;
+	union vnt_tx_data_head *head = NULL;
 	u32 cbMACHdLen = WLAN_HDR_ADDR3_LEN; /* 24 */
 	u16 wFifoCtl;
 	u8 byFBOption = AUTO_FB_NONE;
 
-    //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vGenerateTxParameter...\n");
-    PSTxBufHead pFifoHead = (PSTxBufHead)pTxBufHead;
-    pFifoHead->wReserved = wCurrentRate;
-    wFifoCtl = pFifoHead->wFIFOCtl;
+	pFifoHead->wReserved = wCurrentRate;
+	wFifoCtl = pFifoHead->wFIFOCtl;
 
-    if (wFifoCtl & FIFOCTL_AUTO_FB_0) {
-        byFBOption = AUTO_FB_0;
-    }
-    else if (wFifoCtl & FIFOCTL_AUTO_FB_1) {
-        byFBOption = AUTO_FB_1;
-    }
+	if (wFifoCtl & FIFOCTL_AUTO_FB_0)
+		byFBOption = AUTO_FB_0;
+	else if (wFifoCtl & FIFOCTL_AUTO_FB_1)
+		byFBOption = AUTO_FB_1;
 
-	if (!pvRrvTime)
-		return;
+	if (!pFifoHead)
+		return 0;
 
-    if (pDevice->bLongHeader)
-        cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6;
+	if (pDevice->bLongHeader)
+		cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6;
 
-    if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
-	if (need_rts) {
-            //Fill RsvTime
-		struct vnt_rrv_time_rts *pBuf =
-			(struct vnt_rrv_time_rts *)pvRrvTime;
-		pBuf->wRTSTxRrvTime_aa = s_uGetRTSCTSRsvTime(pDevice, 2,
+	if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
+		if (need_rts) {
+			struct vnt_rrv_time_rts *pBuf =
+					&tx_buffer->tx_head.tx_rts.rts;
+
+			pBuf->wRTSTxRrvTime_aa = s_uGetRTSCTSRsvTime(pDevice, 2,
+					byPktType, cbFrameSize, wCurrentRate);
+			pBuf->wRTSTxRrvTime_ba = s_uGetRTSCTSRsvTime(pDevice, 1,
+					byPktType, cbFrameSize, wCurrentRate);
+			pBuf->wRTSTxRrvTime_bb = s_uGetRTSCTSRsvTime(pDevice, 0,
 				byPktType, cbFrameSize, wCurrentRate);
-		pBuf->wRTSTxRrvTime_ba = s_uGetRTSCTSRsvTime(pDevice, 1,
+
+			pBuf->wTxRrvTime_a = vnt_rxtx_rsvtime_le16(pDevice,
+				byPktType, cbFrameSize, wCurrentRate, bNeedACK);
+			pBuf->wTxRrvTime_b = vnt_rxtx_rsvtime_le16(pDevice,
+					PK_TYPE_11B, cbFrameSize,
+					pDevice->byTopCCKBasicRate, bNeedACK);
+
+			if (need_mic) {
+				*mic_hdr = &tx_buffer->
+						tx_head.tx_rts.tx.mic.hdr;
+				head = &tx_buffer->tx_head.tx_rts.tx.mic.head;
+			} else {
+				head = &tx_buffer->tx_head.tx_rts.tx.head;
+			}
+
+			/* Fill RTS */
+			return s_vFillRTSHead(pDevice, byPktType, head,
+					cbFrameSize, bNeedACK, psEthHeader,
+						wCurrentRate, byFBOption);
+
+		} else {
+			struct vnt_rrv_time_cts *pBuf = &tx_buffer->
+							tx_head.tx_cts.cts;
+
+			pBuf->wTxRrvTime_a = vnt_rxtx_rsvtime_le16(pDevice,
+				byPktType, cbFrameSize, wCurrentRate, bNeedACK);
+			pBuf->wTxRrvTime_b = vnt_rxtx_rsvtime_le16(pDevice,
+				PK_TYPE_11B, cbFrameSize,
+					pDevice->byTopCCKBasicRate, bNeedACK);
+
+			pBuf->wCTSTxRrvTime_ba = s_uGetRTSCTSRsvTime(pDevice, 3,
+					byPktType, cbFrameSize, wCurrentRate);
+
+			if (need_mic) {
+				*mic_hdr = &tx_buffer->
+						tx_head.tx_cts.tx.mic.hdr;
+				head = &tx_buffer->tx_head.tx_cts.tx.mic.head;
+			} else {
+				head = &tx_buffer->tx_head.tx_cts.tx.head;
+			}
+
+			/* Fill CTS */
+			return s_vFillCTSHead(pDevice, uDMAIdx, byPktType,
+				head, cbFrameSize, bNeedACK, wCurrentRate,
+					byFBOption);
+		}
+	} else if (byPktType == PK_TYPE_11A) {
+		if (need_mic) {
+			*mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
+			head = &tx_buffer->tx_head.tx_ab.tx.mic.head;
+		} else {
+			head = &tx_buffer->tx_head.tx_ab.tx.head;
+		}
+
+		if (need_rts) {
+			struct vnt_rrv_time_ab *pBuf = &tx_buffer->
+							tx_head.tx_ab.ab;
+
+			pBuf->wRTSTxRrvTime = s_uGetRTSCTSRsvTime(pDevice, 2,
 				byPktType, cbFrameSize, wCurrentRate);
-		pBuf->wRTSTxRrvTime_bb = s_uGetRTSCTSRsvTime(pDevice, 0,
+
+			pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice,
+				byPktType, cbFrameSize, wCurrentRate, bNeedACK);
+
+			/* Fill RTS */
+			return s_vFillRTSHead(pDevice, byPktType, head,
+				cbFrameSize, bNeedACK, psEthHeader,
+					wCurrentRate, byFBOption);
+		} else {
+			struct vnt_rrv_time_ab *pBuf = &tx_buffer->
+							tx_head.tx_ab.ab;
+
+			pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice,
+				PK_TYPE_11A, cbFrameSize,
+					wCurrentRate, bNeedACK);
+
+			return vnt_rxtx_datahead_a_fb(pDevice, byPktType,
+				wCurrentRate, &head->data_head_a_fb,
+						cbFrameSize, bNeedACK);
+		}
+	} else if (byPktType == PK_TYPE_11B) {
+		if (need_mic) {
+			*mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
+			head = &tx_buffer->tx_head.tx_ab.tx.mic.head;
+		} else {
+			head = &tx_buffer->tx_head.tx_ab.tx.head;
+		}
+
+		if (need_rts) {
+			struct vnt_rrv_time_ab *pBuf = &tx_buffer->
+							tx_head.tx_ab.ab;
+
+			pBuf->wRTSTxRrvTime = s_uGetRTSCTSRsvTime(pDevice, 0,
 				byPktType, cbFrameSize, wCurrentRate);
-		pBuf->wTxRrvTime_a = vnt_rxtx_rsvtime_le16(pDevice,
-			byPktType, cbFrameSize, wCurrentRate, bNeedACK);
-		pBuf->wTxRrvTime_b = vnt_rxtx_rsvtime_le16(pDevice,
-			PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate,
-				bNeedACK);
-		/* Fill RTS */
-		s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
+
+			pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice,
+				PK_TYPE_11B, cbFrameSize, wCurrentRate,
+								bNeedACK);
+
+			/* Fill RTS */
+			return s_vFillRTSHead(pDevice, byPktType, head,
+				cbFrameSize,
 			bNeedACK, psEthHeader, wCurrentRate, byFBOption);
-        }
-        else {//RTS_needless, PCF mode
-            //Fill RsvTime
-		struct vnt_rrv_time_cts *pBuf =
-				(struct vnt_rrv_time_cts *)pvRrvTime;
-		pBuf->wTxRrvTime_a = vnt_rxtx_rsvtime_le16(pDevice, byPktType,
-			cbFrameSize, wCurrentRate, bNeedACK);
-		pBuf->wTxRrvTime_b = vnt_rxtx_rsvtime_le16(pDevice,
-			PK_TYPE_11B, cbFrameSize,
-			pDevice->byTopCCKBasicRate, bNeedACK);
-		pBuf->wCTSTxRrvTime_ba = s_uGetRTSCTSRsvTime(pDevice, 3,
-				byPktType, cbFrameSize, wCurrentRate);
-		/* Fill CTS */
-		s_vFillCTSHead(pDevice, uDMAIdx, byPktType, head,
-			cbFrameSize, bNeedACK, wCurrentRate, byFBOption);
-        }
-    }
-    else if (byPktType == PK_TYPE_11A) {
-	if (need_rts) {
-            //Fill RsvTime
-		struct vnt_rrv_time_ab *pBuf =
-				(struct vnt_rrv_time_ab *)pvRrvTime;
-		pBuf->wRTSTxRrvTime = s_uGetRTSCTSRsvTime(pDevice, 2,
-				byPktType, cbFrameSize, wCurrentRate);
-		pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, byPktType,
-				cbFrameSize, wCurrentRate, bNeedACK);
-		/* Fill RTS */
-		s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
-			bNeedACK, psEthHeader, wCurrentRate, byFBOption);
-	} else {
-            //Fill RsvTime
-		struct vnt_rrv_time_ab *pBuf =
-				(struct vnt_rrv_time_ab *)pvRrvTime;
-		pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11A,
-			cbFrameSize, wCurrentRate, bNeedACK);
-        }
-    }
-    else if (byPktType == PK_TYPE_11B) {
-	if (need_rts) {
-            //Fill RsvTime
-		struct vnt_rrv_time_ab *pBuf =
-				(struct vnt_rrv_time_ab *)pvRrvTime;
-		pBuf->wRTSTxRrvTime = s_uGetRTSCTSRsvTime(pDevice, 0,
-				byPktType, cbFrameSize, wCurrentRate);
-		pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B,
-				cbFrameSize, wCurrentRate, bNeedACK);
-		/* Fill RTS */
-		s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize,
-			bNeedACK, psEthHeader, wCurrentRate, byFBOption);
-        }
-        else { //RTS_needless, non PCF mode
-            //Fill RsvTime
-		struct vnt_rrv_time_ab *pBuf =
-				(struct vnt_rrv_time_ab *)pvRrvTime;
-		pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B,
-			cbFrameSize, wCurrentRate, bNeedACK);
-        }
-    }
-    //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vGenerateTxParameter END.\n");
+		} else {
+			struct vnt_rrv_time_ab *pBuf = &tx_buffer->
+							tx_head.tx_ab.ab;
+
+			pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice,
+				PK_TYPE_11B, cbFrameSize,
+					wCurrentRate, bNeedACK);
+
+			return vnt_rxtx_datahead_ab(pDevice, byPktType,
+				wCurrentRate, &head->data_head_ab,
+					cbFrameSize, bNeedACK);
+		}
+	}
+
+	return 0;
 }
 /*
     u8 * pbyBuffer,//point to pTxBufHead
@@ -955,11 +945,12 @@
 */
 
 static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType,
-	struct vnt_tx_buffer *pTxBufHead, int bNeedEncryption,
+	struct vnt_tx_buffer *tx_buffer, int bNeedEncryption,
 	u32 uSkbPacketLen, u32 uDMAIdx,	struct ethhdr *psEthHeader,
 	u8 *pPacket, PSKeyItem pTransmitKey, u32 uNodeIndex, u16 wCurrentRate,
 	u32 *pcbHeaderLen, u32 *pcbTotalLen)
 {
+	struct vnt_tx_fifo_head *pTxBufHead = &tx_buffer->fifo_head;
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
 	u32 cbFrameSize, cbFrameBodySize;
 	u32 cb802_1_H_len;
@@ -973,17 +964,14 @@
 		= {0xAA, 0xAA, 0x03, 0x00, 0x00, 0xF8};
 	u32 uDuration;
 	u32 cbHeaderLength = 0, uPadding = 0;
-	void *pvRrvTime;
 	struct vnt_mic_hdr *pMICHDR;
-	void *rts_cts = NULL;
-	void *pvTxDataHd;
 	u8 byFBOption = AUTO_FB_NONE, byFragType;
 	u16 wTxBufSize;
 	u32 dwMICKey0, dwMICKey1, dwMIC_Priority;
 	u32 *pdwMIC_L, *pdwMIC_R;
 	int bSoftWEP = false;
 
-	pvRrvTime = pMICHDR = pvTxDataHd = NULL;
+	pMICHDR = NULL;
 
 	if (bNeedEncryption && pTransmitKey->pvKeyTable) {
 		if (((PSKeyTable)pTransmitKey->pvKeyTable)->bSoftWEP == true)
@@ -1047,16 +1035,27 @@
         pTxBufHead->wFIFOCtl |=	FIFOCTL_GRPACK;
     }
 
-    //Set Auto Fallback Ctl
-    if (wCurrentRate >= RATE_18M) {
-        if (pDevice->byAutoFBCtrl == AUTO_FB_0) {
-            pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_0;
-            byFBOption = AUTO_FB_0;
-        } else if (pDevice->byAutoFBCtrl == AUTO_FB_1) {
-            pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_1;
-            byFBOption = AUTO_FB_1;
-        }
-    }
+	/* Set Auto Fallback Ctl */
+	if (wCurrentRate >= RATE_18M) {
+		if (pDevice->byAutoFBCtrl == AUTO_FB_0) {
+			pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_0;
+
+			pDevice->tx_rate_fb0 =
+				wFB_Opt0[FB_RATE0][wCurrentRate - RATE_18M];
+			pDevice->tx_rate_fb1 =
+				wFB_Opt0[FB_RATE1][wCurrentRate - RATE_18M];
+
+			byFBOption = AUTO_FB_0;
+		} else if (pDevice->byAutoFBCtrl == AUTO_FB_1) {
+			pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_1;
+			pDevice->tx_rate_fb0 =
+				wFB_Opt1[FB_RATE0][wCurrentRate - RATE_18M];
+			pDevice->tx_rate_fb1 =
+				wFB_Opt1[FB_RATE1][wCurrentRate - RATE_18M];
+
+			byFBOption = AUTO_FB_1;
+		}
+	}
 
     if (bSoftWEP != true) {
         if ((bNeedEncryption) && (pTransmitKey != NULL))  { //WEP enabled
@@ -1105,118 +1104,47 @@
     }
 
     pbyTxBufferAddr = (u8 *) &(pTxBufHead->adwTxKey[0]);
-    wTxBufSize = sizeof(STxBufHead);
+	wTxBufSize = sizeof(struct vnt_tx_fifo_head);
+
     if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
         if (byFBOption == AUTO_FB_NONE) {
             if (bRTS == true) {//RTS_need
-		pvRrvTime = (struct vnt_rrv_time_rts *)
-					(pbyTxBufferAddr + wTxBufSize);
-		pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize +
-					sizeof(struct vnt_rrv_time_rts));
-		rts_cts = (struct vnt_rts_g *) (pbyTxBufferAddr + wTxBufSize +
-				sizeof(struct vnt_rrv_time_rts) + cbMICHDR);
-		pvTxDataHd = (struct vnt_tx_datahead_g *) (pbyTxBufferAddr +
-			wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
-				cbMICHDR + sizeof(struct vnt_rts_g));
 		cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
-			cbMICHDR + sizeof(struct vnt_rts_g) +
-				sizeof(struct vnt_tx_datahead_g);
+			cbMICHDR + sizeof(struct vnt_rts_g);
             }
             else { //RTS_needless
-		pvRrvTime = (struct vnt_rrv_time_cts *)
-				(pbyTxBufferAddr + wTxBufSize);
-		pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize +
-			sizeof(struct vnt_rrv_time_cts));
-		rts_cts = (struct vnt_cts *) (pbyTxBufferAddr + wTxBufSize +
-				sizeof(struct vnt_rrv_time_cts) + cbMICHDR);
-		pvTxDataHd = (struct vnt_tx_datahead_g *)(pbyTxBufferAddr +
-			wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
-				cbMICHDR + sizeof(struct vnt_cts));
 		cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
-			cbMICHDR + sizeof(struct vnt_cts) +
-				sizeof(struct vnt_tx_datahead_g);
+			cbMICHDR + sizeof(struct vnt_cts);
             }
         } else {
             // Auto Fall Back
             if (bRTS == true) {//RTS_need
-		pvRrvTime = (struct vnt_rrv_time_rts *)(pbyTxBufferAddr +
-								wTxBufSize);
-		pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize +
-					sizeof(struct vnt_rrv_time_rts));
-		rts_cts = (struct vnt_rts_g_fb *)(pbyTxBufferAddr + wTxBufSize +
-				sizeof(struct vnt_rrv_time_rts) + cbMICHDR);
-		pvTxDataHd = (struct vnt_tx_datahead_g_fb *) (pbyTxBufferAddr +
-			wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
-				cbMICHDR + sizeof(struct vnt_rts_g_fb));
 		cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
-			cbMICHDR + sizeof(struct vnt_rts_g_fb) +
-				sizeof(struct vnt_tx_datahead_g_fb);
+			cbMICHDR + sizeof(struct vnt_rts_g_fb);
             }
             else if (bRTS == false) { //RTS_needless
-		pvRrvTime = (struct vnt_rrv_time_cts *)
-				(pbyTxBufferAddr + wTxBufSize);
-		pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize +
-				sizeof(struct vnt_rrv_time_cts));
-		rts_cts = (struct vnt_cts_fb *) (pbyTxBufferAddr + wTxBufSize +
-			sizeof(struct vnt_rrv_time_cts) + cbMICHDR);
-		pvTxDataHd = (struct vnt_tx_datahead_g_fb *) (pbyTxBufferAddr +
-			wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
-				cbMICHDR + sizeof(struct vnt_cts_fb));
 		cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
-				cbMICHDR + sizeof(struct vnt_cts_fb) +
-					sizeof(struct vnt_tx_datahead_g_fb);
+				cbMICHDR + sizeof(struct vnt_cts_fb);
             }
         } // Auto Fall Back
     }
     else {//802.11a/b packet
         if (byFBOption == AUTO_FB_NONE) {
             if (bRTS == true) {//RTS_need
-		pvRrvTime = (struct vnt_rrv_time_ab *) (pbyTxBufferAddr +
-								wTxBufSize);
-		pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize +
-						sizeof(struct vnt_rrv_time_ab));
-		rts_cts = (struct vnt_rts_ab *) (pbyTxBufferAddr + wTxBufSize +
-				sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
-		pvTxDataHd = (struct vnt_tx_datahead_ab *)(pbyTxBufferAddr +
-			wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR +
-						sizeof(struct vnt_rts_ab));
 		cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
-			cbMICHDR + sizeof(struct vnt_rts_ab) +
-				sizeof(struct vnt_tx_datahead_ab);
+			cbMICHDR + sizeof(struct vnt_rts_ab);
             }
             else if (bRTS == false) { //RTS_needless, no MICHDR
-		pvRrvTime = (struct vnt_rrv_time_ab *)(pbyTxBufferAddr +
-								wTxBufSize);
-		pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize +
-						sizeof(struct vnt_rrv_time_ab));
-		pvTxDataHd = (struct vnt_tx_datahead_ab *)(pbyTxBufferAddr +
-			wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
 		cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
 				cbMICHDR + sizeof(struct vnt_tx_datahead_ab);
             }
         } else {
             // Auto Fall Back
             if (bRTS == true) {//RTS_need
-		pvRrvTime = (struct vnt_rrv_time_ab *)(pbyTxBufferAddr +
-						wTxBufSize);
-		pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize +
-			sizeof(struct vnt_rrv_time_ab));
-		rts_cts = (struct vnt_rts_a_fb *)(pbyTxBufferAddr + wTxBufSize +
-				sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
-		pvTxDataHd = (struct vnt_tx_datahead_a_fb *)(pbyTxBufferAddr +
-			wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR +
-					sizeof(struct vnt_rts_a_fb));
 		cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
-			cbMICHDR + sizeof(struct vnt_rts_a_fb) +
-					sizeof(struct vnt_tx_datahead_a_fb);
+			cbMICHDR + sizeof(struct vnt_rts_a_fb);
             }
             else if (bRTS == false) { //RTS_needless
-		pvRrvTime = (struct vnt_rrv_time_ab *)(pbyTxBufferAddr +
-								wTxBufSize);
-		pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize +
-						sizeof(struct vnt_rrv_time_ab));
-		pvTxDataHd = (struct vnt_tx_datahead_a_fb *)(pbyTxBufferAddr +
-			wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
 		cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
 			cbMICHDR + sizeof(struct vnt_tx_datahead_a_fb);
             }
@@ -1235,20 +1163,18 @@
     //uDMAIdx = TYPE_AC0DMA;
     //pTxBufHead = (PSTxBufHead) &(pTxBufHead->adwTxKey[0]);
 
-    //Fill FIFO,RrvTime,RTS,and CTS
-    s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
-		(void *)pbyTxBufferAddr, pvRrvTime, rts_cts,
-		cbFrameSize, bNeedACK, uDMAIdx, psEthHeader, bRTS);
-    //Fill DataHead
-    uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK,
-				byFBOption);
+	/* Fill FIFO, RrvTime, RTS and CTS */
+	uDuration = s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
+			tx_buffer, &pMICHDR, cbMICHDR,
+			cbFrameSize, bNeedACK, uDMAIdx, psEthHeader, bRTS);
+
     // Generate TX MAC Header
     s_vGenerateMACHeader(pDevice, pbyMacHdr, (u16)uDuration, psEthHeader, bNeedEncryption,
                            byFragType, uDMAIdx, 0);
 
     if (bNeedEncryption == true) {
         //Fill TXKEY
-        s_vFillTxKey(pDevice, (u8 *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey,
+	s_vFillTxKey(pDevice, pTxBufHead, pbyIVHead, pTransmitKey,
 		pbyMacHdr, (u16)cbFrameBodySize, pMICHDR);
 
         if (pDevice->bEnableHostWEP) {
@@ -1469,13 +1395,12 @@
 {
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
 	struct vnt_tx_buffer *pTX_Buffer;
-	PSTxBufHead pTxBufHead;
 	struct vnt_usb_send_context *pContext;
+	struct vnt_tx_fifo_head *pTxBufHead;
 	struct ieee80211_hdr *pMACHeader;
 	struct ethhdr sEthHeader;
 	u8 byPktType, *pbyTxBufferAddr;
-	void *rts_cts = NULL;
-	void *pvTxDataHd, *pvRrvTime, *pMICHDR;
+	struct vnt_mic_hdr *pMICHDR = NULL;
 	u32 uDuration, cbReqCount, cbHeaderSize, cbFrameBodySize, cbFrameSize;
 	int bNeedACK, bIsPSPOLL = false;
 	u32 cbIVlen = 0, cbICVlen = 0, cbMIClen = 0, cbFCSlen = 4;
@@ -1492,10 +1417,10 @@
     }
 
 	pTX_Buffer = (struct vnt_tx_buffer *)&pContext->Data[0];
-    pbyTxBufferAddr = (u8 *)&(pTX_Buffer->adwTxKey[0]);
     cbFrameBodySize = pPacket->cbPayloadLen;
-    pTxBufHead = (PSTxBufHead) pbyTxBufferAddr;
-    wTxBufSize = sizeof(STxBufHead);
+	pTxBufHead = &pTX_Buffer->fifo_head;
+	pbyTxBufferAddr = (u8 *)&pTxBufHead->adwTxKey[0];
+	wTxBufSize = sizeof(struct vnt_tx_fifo_head);
 
     if (pDevice->byBBType == BB_TYPE_11A) {
         wCurrentRate = RATE_6M;
@@ -1607,21 +1532,10 @@
 
     //Set RrvTime/RTS/CTS Buffer
     if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
-
-	pvRrvTime = (struct vnt_rrv_time_cts *) (pbyTxBufferAddr + wTxBufSize);
-        pMICHDR = NULL;
-	rts_cts = (struct vnt_cts *) (pbyTxBufferAddr + wTxBufSize +
-					sizeof(struct vnt_rrv_time_cts));
-	pvTxDataHd = (struct vnt_tx_datahead_g *)(pbyTxBufferAddr + wTxBufSize +
-		sizeof(struct vnt_rrv_time_cts) + sizeof(struct vnt_cts));
 	cbHeaderSize = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
-		sizeof(struct vnt_cts) + sizeof(struct vnt_tx_datahead_g);
+		sizeof(struct vnt_cts);
     }
     else { // 802.11a/b packet
-	pvRrvTime = (struct vnt_rrv_time_ab *) (pbyTxBufferAddr + wTxBufSize);
-        pMICHDR = NULL;
-	pvTxDataHd = (struct vnt_tx_datahead_ab *) (pbyTxBufferAddr +
-		wTxBufSize + sizeof(struct vnt_rrv_time_ab));
 	cbHeaderSize = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
 		sizeof(struct vnt_tx_datahead_ab);
     }
@@ -1638,14 +1552,10 @@
     pTxBufHead->wFragCtl |= (u16)FRAGCTL_NONFRAG;
 
 	/* Fill FIFO,RrvTime,RTS,and CTS */
-	s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
-		pbyTxBufferAddr, pvRrvTime, rts_cts,
+	uDuration = s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
+		pTX_Buffer, &pMICHDR, 0,
 		cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, false);
 
-    //Fill DataHead
-    uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK,
-				AUTO_FB_NONE);
-
     pMACHeader = (struct ieee80211_hdr *) (pbyTxBufferAddr + cbHeaderSize);
 
     cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + cbFrameBodySize;
@@ -1684,7 +1594,7 @@
             }
         } while(false);
         //Fill TXKEY
-        s_vFillTxKey(pDevice, (u8 *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey,
+	s_vFillTxKey(pDevice, pTxBufHead, pbyIVHead, pTransmitKey,
                      (u8 *)pMACHeader, (u16)cbFrameBodySize, NULL);
 
         memcpy(pMACHeader, pPacket->p80211Header, cbMacHdLen);
@@ -1708,12 +1618,16 @@
         // in the same place of other packet's Duration-field).
         // And it will cause Cisco-AP to issue Disassociation-packet
 	if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
-		((struct vnt_tx_datahead_g *)pvTxDataHd)->wDuration_a =
+		struct vnt_tx_datahead_g *data_head = &pTX_Buffer->tx_head.
+						tx_cts.tx.head.cts_g.data_head;
+		data_head->wDuration_a =
 			cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
-		((struct vnt_tx_datahead_g *)pvTxDataHd)->wDuration_b =
+		data_head->wDuration_b =
 			cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
 	} else {
-		((struct vnt_tx_datahead_ab *)pvTxDataHd)->wDuration =
+		struct vnt_tx_datahead_ab *data_head = &pTX_Buffer->tx_head.
+					tx_ab.tx.head.data_head_ab;
+		data_head->wDuration =
 			cpu_to_le16(pPacket->p80211Header->sA2.wDurationID);
 	}
     }
@@ -1727,10 +1641,14 @@
     pContext->uBufLen = (u16)cbReqCount + 4;  //USB header
 
     if (WLAN_GET_FC_TODS(pMACHeader->frame_control) == 0) {
-        s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr1[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl);
+	s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
+			&pMACHeader->addr1[0], (u16)cbFrameSize,
+			pTxBufHead->wFIFOCtl);
     }
     else {
-        s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr3[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl);
+	s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
+			&pMACHeader->addr3[0], (u16)cbFrameSize,
+			pTxBufHead->wFIFOCtl);
     }
 
     PIPEnsSendBulkOut(pDevice,pContext);
@@ -1825,15 +1743,13 @@
 {
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
 	struct vnt_tx_buffer *pTX_Buffer;
+	struct vnt_tx_fifo_head *pTxBufHead;
 	u8 byPktType;
 	u8 *pbyTxBufferAddr;
-	void *rts_cts = NULL;
-	void *pvTxDataHd;
 	u32 uDuration, cbReqCount;
 	struct ieee80211_hdr *pMACHeader;
 	u32 cbHeaderSize, cbFrameBodySize;
 	int bNeedACK, bIsPSPOLL = false;
-	PSTxBufHead pTxBufHead;
 	u32 cbFrameSize;
 	u32 cbIVlen = 0, cbICVlen = 0, cbMIClen = 0, cbFCSlen = 4;
 	u32 uPadding = 0;
@@ -1844,7 +1760,7 @@
 	u16 wTxBufSize;
 	u32 cbMacHdLen;
 	struct ethhdr sEthHeader;
-	void *pvRrvTime, *pMICHDR;
+	struct vnt_mic_hdr *pMICHDR;
 	u32 wCurrentRate = RATE_1M;
 	PUWLAN_80211HDR  p80211Header;
 	u32 uNodeIndex = 0;
@@ -1855,7 +1771,7 @@
 	u32 cbExtSuppRate = 0;
 	struct vnt_usb_send_context *pContext;
 
-	pvRrvTime = pMICHDR = pvTxDataHd = NULL;
+	pMICHDR = NULL;
 
     if(skb->len <= WLAN_HDR_ADDR3_LEN) {
        cbFrameBodySize = 0;
@@ -1874,9 +1790,9 @@
     }
 
 	pTX_Buffer = (struct vnt_tx_buffer *)&pContext->Data[0];
-    pbyTxBufferAddr = (u8 *)(&pTX_Buffer->adwTxKey[0]);
-    pTxBufHead = (PSTxBufHead) pbyTxBufferAddr;
-    wTxBufSize = sizeof(STxBufHead);
+	pTxBufHead = &pTX_Buffer->fifo_head;
+	pbyTxBufferAddr = (u8 *)&pTxBufHead->adwTxKey[0];
+	wTxBufSize = sizeof(struct vnt_tx_fifo_head);
 
     if (pDevice->byBBType == BB_TYPE_11A) {
         wCurrentRate = RATE_6M;
@@ -2014,25 +1930,11 @@
     //the rest of pTxBufHead->wFragCtl:FragTyp will be set later in s_vFillFragParameter()
 
     if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {//802.11g packet
-	pvRrvTime = (struct vnt_rrv_time_cts *) (pbyTxBufferAddr + wTxBufSize);
-	pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize +
-					sizeof(struct vnt_rrv_time_cts));
-	rts_cts = (struct vnt_cts *) (pbyTxBufferAddr + wTxBufSize +
-			sizeof(struct vnt_rrv_time_cts) + cbMICHDR);
-	pvTxDataHd = (struct vnt_tx_datahead_g *) (pbyTxBufferAddr +
-		wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR +
-					sizeof(struct vnt_cts));
 	cbHeaderSize = wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR +
-		sizeof(struct vnt_cts) + sizeof(struct vnt_tx_datahead_g);
+		sizeof(struct vnt_cts);
 
     }
     else {//802.11a/b packet
-
-	pvRrvTime = (struct vnt_rrv_time_ab *) (pbyTxBufferAddr + wTxBufSize);
-	pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize +
-		sizeof(struct vnt_rrv_time_ab));
-	pvTxDataHd = (struct vnt_tx_datahead_ab *)(pbyTxBufferAddr +
-		wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
 	cbHeaderSize = wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR +
 					sizeof(struct vnt_tx_datahead_ab);
     }
@@ -2048,15 +1950,11 @@
     pTxBufHead->wFragCtl |= (u16)FRAGCTL_NONFRAG;
 
 	/* Fill FIFO,RrvTime,RTS,and CTS */
-	s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
-		pbyTxBufferAddr, pvRrvTime, rts_cts,
+	uDuration = s_vGenerateTxParameter(pDevice, byPktType, wCurrentRate,
+		pTX_Buffer, &pMICHDR, cbMICHDR,
 		cbFrameSize, bNeedACK, TYPE_TXDMA0, &sEthHeader, false);
 
-    //Fill DataHead
-    uDuration = s_uFillDataHead(pDevice, byPktType, wCurrentRate, pvTxDataHd, cbFrameSize, TYPE_TXDMA0, bNeedACK,
-				AUTO_FB_NONE);
-
-    pMACHeader = (struct ieee80211_hdr *) (pbyTxBufferAddr + cbHeaderSize);
+	pMACHeader = (struct ieee80211_hdr *) (pbyTxBufferAddr + cbHeaderSize);
 
     cbReqCount = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen + (cbFrameBodySize + cbMIClen) + cbExtSuppRate;
 
@@ -2139,7 +2037,7 @@
 
         }
 
-        s_vFillTxKey(pDevice, (u8 *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey,
+	s_vFillTxKey(pDevice, pTxBufHead, pbyIVHead, pTransmitKey,
 		pbyMacHdr, (u16)cbFrameBodySize, pMICHDR);
 
         if (pDevice->bEnableHostWEP) {
@@ -2164,12 +2062,16 @@
         // in the same place of other packet's Duration-field).
         // And it will cause Cisco-AP to issue Disassociation-packet
 	if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
-		((struct vnt_tx_datahead_g *)pvTxDataHd)->wDuration_a =
+		struct vnt_tx_datahead_g *data_head = &pTX_Buffer->tx_head.
+						tx_cts.tx.head.cts_g.data_head;
+		data_head->wDuration_a =
 			cpu_to_le16(p80211Header->sA2.wDurationID);
-		((struct vnt_tx_datahead_g *)pvTxDataHd)->wDuration_b =
+		data_head->wDuration_b =
 			cpu_to_le16(p80211Header->sA2.wDurationID);
 	} else {
-		((struct vnt_tx_datahead_ab *)pvTxDataHd)->wDuration =
+		struct vnt_tx_datahead_ab *data_head = &pTX_Buffer->tx_head.
+					tx_ab.tx.head.data_head_ab;
+		data_head->wDuration =
 			cpu_to_le16(p80211Header->sA2.wDurationID);
 	}
     }
@@ -2183,10 +2085,14 @@
     pContext->uBufLen = (u16)cbReqCount + 4;  //USB header
 
     if (WLAN_GET_FC_TODS(pMACHeader->frame_control) == 0) {
-        s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr1[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl);
+	s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
+			&pMACHeader->addr1[0], (u16)cbFrameSize,
+			pTxBufHead->wFIFOCtl);
     }
     else {
-        s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pMACHeader->addr3[0]), (u16)cbFrameSize, pTX_Buffer->wFIFOCtl);
+	s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
+			&pMACHeader->addr3[0], (u16)cbFrameSize,
+			pTxBufHead->wFIFOCtl);
     }
     PIPEnsSendBulkOut(pDevice,pContext);
     return ;
@@ -2568,7 +2474,10 @@
     pContext->Type = CONTEXT_DATA_PACKET;
     pContext->uBufLen = (u16)BytesToWrite + 4 ; //USB header
 
-    s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pContext->sEthHeader.h_dest[0]), (u16) (BytesToWrite-uHeaderLen), pTX_Buffer->wFIFOCtl);
+    s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
+			&pContext->sEthHeader.h_dest[0],
+			(u16)(BytesToWrite-uHeaderLen),
+			pTX_Buffer->fifo_head.wFIFOCtl);
 
     status = PIPEnsSendBulkOut(pDevice,pContext);
 
@@ -2719,7 +2628,10 @@
     pContext->Type = CONTEXT_DATA_PACKET;
     pContext->uBufLen = (u16)BytesToWrite + 4 ; //USB header
 
-    s_vSaveTxPktInfo(pDevice, (u8) (pTX_Buffer->byPKTNO & 0x0F), &(pContext->sEthHeader.h_dest[0]), (u16) (BytesToWrite-uHeaderLen), pTX_Buffer->wFIFOCtl);
+    s_vSaveTxPktInfo(pDevice, (u8)(pTX_Buffer->byPKTNO & 0x0F),
+		&pContext->sEthHeader.h_dest[0],
+		(u16)(BytesToWrite - uHeaderLen),
+		pTX_Buffer->fifo_head.wFIFOCtl);
 
     status = PIPEnsSendBulkOut(pDevice,pContext);
 
diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h
index 4bbee1c..eecbe89 100644
--- a/drivers/staging/vt6656/rxtx.h
+++ b/drivers/staging/vt6656/rxtx.h
@@ -117,6 +117,7 @@
 	u16 wDuration_bb;
 	u16 wReserved;
 	struct ieee80211_rts data;
+	struct vnt_tx_datahead_g data_head;
 } __packed;
 
 struct vnt_rts_g_fb {
@@ -131,6 +132,7 @@
 	u16 wRTSDuration_ba_f1;
 	u16 wRTSDuration_aa_f1;
 	struct ieee80211_rts data;
+	struct vnt_tx_datahead_g_fb data_head;
 } __packed;
 
 struct vnt_rts_ab {
@@ -138,6 +140,7 @@
 	u16 wDuration;
 	u16 wReserved;
 	struct ieee80211_rts data;
+	struct vnt_tx_datahead_ab data_head;
 } __packed;
 
 struct vnt_rts_a_fb {
@@ -147,6 +150,7 @@
 	u16 wRTSDuration_f0;
 	u16 wRTSDuration_f1;
 	struct ieee80211_rts data;
+	struct vnt_tx_datahead_a_fb data_head;
 } __packed;
 
 /* CTS buffer header */
@@ -156,6 +160,7 @@
 	u16 wReserved;
 	struct ieee80211_cts data;
 	u16 reserved2;
+	struct vnt_tx_datahead_g data_head;
 } __packed;
 
 struct vnt_cts_fb {
@@ -166,6 +171,7 @@
 	u16 wCTSDuration_ba_f1;
 	struct ieee80211_cts data;
 	u16 reserved2;
+	struct vnt_tx_datahead_g_fb data_head;
 } __packed;
 
 union vnt_tx_data_head {
@@ -178,12 +184,37 @@
 	/* cts g */
 	struct vnt_cts cts_g;
 	struct vnt_cts_fb cts_g_fb;
+	/* no rts/cts */
+	struct vnt_tx_datahead_a_fb data_head_a_fb;
+	struct vnt_tx_datahead_ab data_head_ab;
 };
 
-struct vnt_tx_buffer {
-	u8 byType;
-	u8 byPKTNO;
-	u16 wTxByteCount;
+struct vnt_tx_mic_hdr {
+	struct vnt_mic_hdr hdr;
+	union vnt_tx_data_head head;
+} __packed;
+
+union vnt_tx {
+	struct vnt_tx_mic_hdr mic;
+	union vnt_tx_data_head head;
+};
+
+union vnt_tx_head {
+	struct {
+		struct vnt_rrv_time_rts rts;
+		union vnt_tx tx;
+	} __packed tx_rts;
+	struct {
+		struct vnt_rrv_time_cts cts;
+		union vnt_tx tx;
+	} __packed tx_cts;
+	struct {
+		struct vnt_rrv_time_ab ab;
+		union vnt_tx tx;
+	} __packed tx_ab;
+};
+
+struct vnt_tx_fifo_head {
 	u32 adwTxKey[4];
 	u16 wFIFOCtl;
 	u16 wTimeStamp;
@@ -191,6 +222,14 @@
 	u16 wReserved;
 } __packed;
 
+struct vnt_tx_buffer {
+	u8 byType;
+	u8 byPKTNO;
+	u16 wTxByteCount;
+	struct vnt_tx_fifo_head fifo_head;
+	union vnt_tx_head tx_head;
+} __packed;
+
 struct vnt_beacon_buffer {
 	u8 byType;
 	u8 byPKTNO;
diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c
index 3a03f1d..5fc18ad 100644
--- a/drivers/staging/vt6656/usbpipe.c
+++ b/drivers/staging/vt6656/usbpipe.c
@@ -118,6 +118,9 @@
 	if (pDevice->Flags & fMP_CONTROL_READS)
 		return STATUS_FAILURE;
 
+	if (pDevice->pControlURB->hcpriv)
+		return STATUS_FAILURE;
+
 	MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES);
 
 	pDevice->sUsbCtlRequest.bRequestType = 0x40;
@@ -177,6 +180,9 @@
 	if (pDevice->Flags & fMP_CONTROL_WRITES)
 		return STATUS_FAILURE;
 
+	if (pDevice->pControlURB->hcpriv)
+		return STATUS_FAILURE;
+
 	MP_SET_FLAG(pDevice, fMP_CONTROL_READS);
 
 	pDevice->sUsbCtlRequest.bRequestType = 0xC0;
@@ -656,8 +662,6 @@
         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Write %d bytes\n",(int)ulBufLen);
         pDevice->ulBulkOutBytesWrite += ulBufLen;
         pDevice->ulBulkOutContCRCError = 0;
-	pDevice->nTxDataTimeCout = 0;
-
     } else {
         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK Out failed %d\n", status);
         pDevice->ulBulkOutError++;
diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c
index 0013cb7..2f8e2a8 100644
--- a/drivers/staging/vt6656/wcmd.c
+++ b/drivers/staging/vt6656/wcmd.c
@@ -268,20 +268,14 @@
 
 void vCommandTimerWait(struct vnt_private *pDevice, unsigned long MSecond)
 {
-
-	init_timer(&pDevice->sTimerCommand);
-
-	pDevice->sTimerCommand.data = (unsigned long)pDevice;
-	pDevice->sTimerCommand.function = (TimerFunction)vRunCommand;
-	pDevice->sTimerCommand.expires = RUN_AT((MSecond * HZ) / 1000);
-
-	add_timer(&pDevice->sTimerCommand);
-
-	return;
+	schedule_delayed_work(&pDevice->run_command_work,
+						msecs_to_jiffies(MSecond));
 }
 
-void vRunCommand(struct vnt_private *pDevice)
+void vRunCommand(struct work_struct *work)
 {
+	struct vnt_private *pDevice =
+		container_of(work, struct vnt_private, run_command_work.work);
 	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
 	PWLAN_IE_SSID pItemSSID;
 	PWLAN_IE_SSID pItemSSIDCurr;
@@ -292,6 +286,9 @@
 	u8 byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
 	u8 byData;
 
+	if (pDevice->Flags & fMP_DISCONNECTED)
+		return;
+
     if (pDevice->dwDiagRefCount != 0)
         return;
     if (pDevice->bCmdRunning != true)
@@ -660,22 +657,6 @@
                     netif_wake_queue(pDevice->dev);
                 }
 
-		 if(pDevice->IsTxDataTrigger != false)   {    //TxDataTimer is not triggered at the first time
-                     // printk("Re-initial TxDataTimer****\n");
-		    del_timer(&pDevice->sTimerTxData);
-                      init_timer(&pDevice->sTimerTxData);
-			pDevice->sTimerTxData.data = (unsigned long) pDevice;
-                      pDevice->sTimerTxData.function = (TimerFunction)BSSvSecondTxData;
-                      pDevice->sTimerTxData.expires = RUN_AT(10*HZ);      //10s callback
-                      pDevice->fTxDataInSleep = false;
-                      pDevice->nTxDataTimeCout = 0;
-		 }
-		 else {
-		   // printk("mike:-->First time trigger TimerTxData InSleep\n");
-		 }
-		pDevice->IsTxDataTrigger = true;
-                add_timer(&pDevice->sTimerTxData);
-
             }
 	   else if(pMgmt->eCurrState < WMAC_STATE_ASSOCPENDING) {
                printk("WLAN_ASSOCIATE_WAIT:Association Fail???\n");
@@ -687,7 +668,6 @@
 	       vCommandTimerWait((void *) pDevice, ASSOCIATE_TIMEOUT/2);
 	       return;
 	   }
-	          pDevice->byLinkWaitCount = 0;
 
             s_bCommandComplete(pDevice);
             break;
@@ -696,7 +676,7 @@
             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"eCommandState == WLAN_CMD_AP_MODE_START\n");
 
             if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
-                del_timer(&pMgmt->sTimerSecondCallback);
+		cancel_delayed_work_sync(&pDevice->second_callback_work);
                 pMgmt->eCurrState = WMAC_STATE_IDLE;
                 pMgmt->eCurrMode = WMAC_MODE_STANDBY;
                 pDevice->bLinkPass = false;
@@ -724,7 +704,7 @@
                 }
                 pDevice->bLinkPass = true;
                 ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_INTER);
-                add_timer(&pMgmt->sTimerSecondCallback);
+		schedule_delayed_work(&pDevice->second_callback_work, HZ);
             }
             s_bCommandComplete(pDevice);
             break;
@@ -1156,14 +1136,8 @@
 //mike add:reset command timer
 void vResetCommandTimer(struct vnt_private *pDevice)
 {
+	cancel_delayed_work_sync(&pDevice->run_command_work);
 
-	//delete timer
-	del_timer(&pDevice->sTimerCommand);
-	//init timer
-	init_timer(&pDevice->sTimerCommand);
-	pDevice->sTimerCommand.data = (unsigned long)pDevice;
-	pDevice->sTimerCommand.function = (TimerFunction)vRunCommand;
-	pDevice->sTimerCommand.expires = RUN_AT(HZ);
 	pDevice->cbFreeCmdQueue = CMD_Q_SIZE;
 	pDevice->uCmdDequeueIdx = 0;
 	pDevice->uCmdEnqueueIdx = 0;
@@ -1171,33 +1145,3 @@
 	pDevice->bCmdRunning = false;
 	pDevice->bCmdClear = false;
 }
-
-void BSSvSecondTxData(struct vnt_private *pDevice)
-{
-	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
-
-	pDevice->nTxDataTimeCout++;
-
-	if (pDevice->nTxDataTimeCout < 4) {   //don't tx data if timer less than 40s
-		// printk("mike:%s-->no data Tx not exceed the desired Time as %d\n",__FUNCTION__,
-		//  	(int)pDevice->nTxDataTimeCout);
-		pDevice->sTimerTxData.expires = RUN_AT(10 * HZ);      //10s callback
-		add_timer(&pDevice->sTimerTxData);
-		return;
-	}
-
-	spin_lock_irq(&pDevice->lock);
-	//is wap_supplicant running successful OR only open && sharekey mode!
-	if (((pDevice->bLinkPass == true) &&
-		(pMgmt->eAuthenMode < WMAC_AUTH_WPA)) ||  //open && sharekey linking
-		(pDevice->fWPA_Authened == true)) {   //wpa linking
-		//   printk("mike:%s-->InSleep Tx Data Procedure\n",__FUNCTION__);
-		pDevice->fTxDataInSleep = true;
-		PSbSendNullPacket(pDevice);      //send null packet
-		pDevice->fTxDataInSleep = false;
-	}
-	spin_unlock_irq(&pDevice->lock);
-
-	pDevice->sTimerTxData.expires = RUN_AT(10 * HZ);      //10s callback
-	add_timer(&pDevice->sTimerTxData);
-}
diff --git a/drivers/staging/vt6656/wcmd.h b/drivers/staging/vt6656/wcmd.h
index db8b4cf..caf2684 100644
--- a/drivers/staging/vt6656/wcmd.h
+++ b/drivers/staging/vt6656/wcmd.h
@@ -105,15 +105,6 @@
 
 int bScheduleCommand(struct vnt_private *, CMD_CODE eCommand, u8 *pbyItem0);
 
-void vRunCommand(struct vnt_private *);
-
-/*
-void
-WCMDvCommandThread(
-    void * Context
-    );
-*/
-
-void BSSvSecondTxData(struct vnt_private *);
+void vRunCommand(struct work_struct *work);
 
 #endif /* __WCMD_H__ */
diff --git a/drivers/staging/vt6656/wctl.c b/drivers/staging/vt6656/wctl.c
index 47a655d..814342c 100644
--- a/drivers/staging/vt6656/wctl.c
+++ b/drivers/staging/vt6656/wctl.c
@@ -69,8 +69,7 @@
         for (ii = 0; ii < DUPLICATE_RX_CACHE_LENGTH; ii++) {
             pCacheEntry = &(pCache->asCacheEntry[uIndex]);
             if ((pCacheEntry->wFmSequence == pMACHeader->seq_ctrl) &&
-		(!compare_ether_addr(&(pCacheEntry->abyAddr2[0]),
-				     &(pMACHeader->addr2[0]))) &&
+		ether_addr_equal(pCacheEntry->abyAddr2, pMACHeader->addr2) &&
                 (LOBYTE(pCacheEntry->wFrameCtl) == LOBYTE(pMACHeader->frame_control))
                 ) {
                 /* Duplicate match */
@@ -110,8 +109,8 @@
 
 	for (ii = 0; ii < pDevice->cbDFCB; ii++) {
 		if ((pDevice->sRxDFCB[ii].bInUse == true) &&
-		    (!compare_ether_addr(&(pDevice->sRxDFCB[ii].abyAddr2[0]),
-					  &(pMACHeader->addr2[0])))) {
+		    ether_addr_equal(pDevice->sRxDFCB[ii].abyAddr2,
+				     pMACHeader->addr2)) {
 			return ii;
 		}
 	}
diff --git a/drivers/staging/vt6656/wmgr.c b/drivers/staging/vt6656/wmgr.c
index b6cbd13..e26c415 100644
--- a/drivers/staging/vt6656/wmgr.c
+++ b/drivers/staging/vt6656/wmgr.c
@@ -81,7 +81,7 @@
 #include "control.h"
 #include "rndis.h"
 
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 //static int          msglevel                =MSG_LEVEL_DEBUG;
 
 static int ChannelExceedZoneType(struct vnt_private *, u8 byCurrChannel);
@@ -213,24 +213,6 @@
     pMgmt->wIBSSBeaconPeriod = DEFAULT_IBSS_BI;
     BSSvClearBSSList((void *) pDevice, false);
 
-    init_timer(&pMgmt->sTimerSecondCallback);
-    pMgmt->sTimerSecondCallback.data = (unsigned long)pDevice;
-    pMgmt->sTimerSecondCallback.function = (TimerFunction)BSSvSecondCallBack;
-    pMgmt->sTimerSecondCallback.expires = RUN_AT(HZ);
-
-    init_timer(&pDevice->sTimerCommand);
-    pDevice->sTimerCommand.data = (unsigned long)pDevice;
-    pDevice->sTimerCommand.function = (TimerFunction)vRunCommand;
-    pDevice->sTimerCommand.expires = RUN_AT(HZ);
-
-    init_timer(&pDevice->sTimerTxData);
-    pDevice->sTimerTxData.data = (unsigned long)pDevice;
-    pDevice->sTimerTxData.function = (TimerFunction)BSSvSecondTxData;
-    pDevice->sTimerTxData.expires = RUN_AT(10*HZ);      //10s callback
-    pDevice->fTxDataInSleep = false;
-    pDevice->IsTxDataTrigger = false;
-    pDevice->nTxDataTimeCout = 0;
-
     pDevice->cbFreeCmdQueue = CMD_Q_SIZE;
     pDevice->uCmdDequeueIdx = 0;
     pDevice->uCmdEnqueueIdx = 0;
@@ -844,8 +826,8 @@
               pDevice->bwextstep3 = false;
               pDevice->bWPASuppWextEnabled = false;
 
-if(pMgmt->eCurrState == WMAC_STATE_ASSOC)
-      timer_expire(pDevice->sTimerCommand, 0);
+	if (pMgmt->eCurrState == WMAC_STATE_ASSOC)
+		schedule_delayed_work(&pDevice->run_command_work, 0);
 
     return;
 }
@@ -1127,7 +1109,7 @@
             if ( cpu_to_le16((*(pFrame->pwStatus))) == WLAN_MGMT_STATUS_SUCCESS ){
                 DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (OPEN) Successful.\n");
                 pMgmt->eCurrState = WMAC_STATE_AUTH;
-	       timer_expire(pDevice->sTimerCommand, 0);
+		schedule_delayed_work(&pDevice->run_command_work, 0);
             }
             else {
                 DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (OPEN) Failed.\n");
@@ -1302,7 +1284,7 @@
     if ( cpu_to_le16((*(pFrame->pwStatus))) == WLAN_MGMT_STATUS_SUCCESS ){
         DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (SHAREDKEY) Successful.\n");
         pMgmt->eCurrState = WMAC_STATE_AUTH;
-        timer_expire(pDevice->sTimerCommand, 0);
+	schedule_delayed_work(&pDevice->run_command_work, 0);
     }
     else{
         DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "802.11 Authen (SHAREDKEY) Failed.\n");
@@ -1422,8 +1404,8 @@
 	   pDevice->fWPA_Authened = false;
             DBG_PRT(MSG_LEVEL_NOTICE, KERN_INFO  "AP deauthed me, reason=%d.\n", cpu_to_le16((*(sFrame.pwReason))));
             // TODO: update BSS list for specific BSSID if pre-authentication case
-	    if (!compare_ether_addr(sFrame.pHdr->sA3.abyAddr3,
-				    pMgmt->abyCurrBSSID)) {
+	    if (ether_addr_equal(sFrame.pHdr->sA3.abyAddr3,
+				 pMgmt->abyCurrBSSID)) {
                 if (pMgmt->eCurrState >= WMAC_STATE_AUTHPENDING) {
                     pMgmt->sNodeDBTable[0].bActive = false;
                     pMgmt->eCurrMode = WMAC_MODE_STANDBY;
@@ -3095,7 +3077,7 @@
  *
  *
  * Return Value:
- *    A ptr to frame or NULL on allocation failue
+ *    A ptr to frame or NULL on allocation failure
  *
 -*/
 
diff --git a/drivers/staging/vt6656/wmgr.h b/drivers/staging/vt6656/wmgr.h
index 5424c7f..26ba47d 100644
--- a/drivers/staging/vt6656/wmgr.h
+++ b/drivers/staging/vt6656/wmgr.h
@@ -310,9 +310,6 @@
 	u8 byMgmtPacketPool[sizeof(struct vnt_tx_mgmt)
 		+ WLAN_A3FR_MAXLEN];
 
-	/* One second callback timer */
-	struct timer_list sTimerSecondCallback;
-
 	/* Temporarily Rx Mgmt Packet Descriptor */
 	struct vnt_rx_mgmt sRxPacket;
 
diff --git a/drivers/staging/vt6656/wpactl.c b/drivers/staging/vt6656/wpactl.c
index 9f1b413..003bd7c 100644
--- a/drivers/staging/vt6656/wpactl.c
+++ b/drivers/staging/vt6656/wpactl.c
@@ -227,7 +227,7 @@
 			DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n");
 		} else {
 			// Key Table Full
-			if (!compare_ether_addr(&param->addr[0], pDevice->abyBSSID)) {
+			if (ether_addr_equal(param->addr, pDevice->abyBSSID)) {
 				//DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n"));
 				return -EINVAL;
 			} else {
diff --git a/drivers/staging/winbond/core.h b/drivers/staging/winbond/core.h
index 6160b2f..fc0ef24 100644
--- a/drivers/staging/winbond/core.h
+++ b/drivers/staging/winbond/core.h
@@ -18,8 +18,8 @@
 struct mlme_frame {
 	s8		*pMMPDU;
 	u16		len;
-	u8		DataType;
-	u8		IsInUsed;
+	u8		data_type;
+	u8		is_in_used;
 
 	u8		TxMMPDU[MAX_NUM_TX_MMPDU][MAX_MMPDU_SIZE];
 	u8		TxMMPDUInUse[(MAX_NUM_TX_MMPDU + 3) & ~0x03];
@@ -52,13 +52,9 @@
 	struct hw_data sHwData;	/*For HAL */
 	struct wb35_mds Mds;
 
-	atomic_t ThreadCount;
-
 	u32 RxByteCount;
 	u32 TxByteCount;
 
-	u8 LinkName[WB_MAX_LINK_NAME_LEN];
-
 	bool enabled;
 };
 
diff --git a/drivers/staging/winbond/mds.c b/drivers/staging/winbond/mds.c
index fcc3d21..cac7720 100644
--- a/drivers/staging/winbond/mds.c
+++ b/drivers/staging/winbond/mds.c
@@ -412,7 +412,7 @@
 	desc->buffer_size[desc->InternalUsed] = adapter->sMlmeFrame.len;
 	desc->buffer_total_size += adapter->sMlmeFrame.len;
 	desc->buffer_number++;
-	desc->Type = adapter->sMlmeFrame.DataType;
+	desc->Type = adapter->sMlmeFrame.data_type;
 }
 
 static void MLMEfreeMMPDUBuffer(struct wbsoft_priv *adapter, s8 *pData)
@@ -440,7 +440,7 @@
 	MLMEfreeMMPDUBuffer(adapter, adapter->sMlmeFrame.pMMPDU);
 
 	/* Return resource */
-	adapter->sMlmeFrame.IsInUsed = PACKET_FREE_TO_USE;
+	adapter->sMlmeFrame.is_in_used = PACKET_FREE_TO_USE;
 }
 
 void
diff --git a/drivers/staging/winbond/mto.c b/drivers/staging/winbond/mto.c
index 560c0ab..b031ecd 100644
--- a/drivers/staging/winbond/mto.c
+++ b/drivers/staging/winbond/mto.c
@@ -21,6 +21,7 @@
 #include "wbhal.h"
 #include "wb35reg_f.h"
 #include "core.h"
+#include "mto.h"
 
 /* Declare SQ3 to rate and fragmentation threshold table */
 /* Declare fragmentation threshold table */
@@ -45,12 +46,6 @@
 
 static u8 boSparseTxTraffic;
 
-void MTO_Init(struct wbsoft_priv *adapter);
-void TxRateReductionCtrl(struct wbsoft_priv *adapter);
-void MTO_SetTxCount(struct wbsoft_priv *adapter, u8 t0, u8 index);
-void MTO_TxFailed(struct wbsoft_priv *adapter);
-void hal_get_dto_para(struct wbsoft_priv *adapter, char *buffer);
-
 /*
  * ===========================================================================
  * MTO_Init --
diff --git a/drivers/staging/winbond/mto.h b/drivers/staging/winbond/mto.h
index a0f659c..8d41eed 100644
--- a/drivers/staging/winbond/mto.h
+++ b/drivers/staging/winbond/mto.h
@@ -127,12 +127,8 @@
 #define MTO_DATA_RATE()			MTO_Data_Rate_Tbl[MTO_RATE_LEVEL()]
 #define MTO_FRAG_TH()			MTO_Frag_Th_Tbl[MTO_FRAG_TH_LEVEL()]
 
-extern void MTO_Init(struct wbsoft_priv *);
-extern void MTO_PeriodicTimerExpired(struct wbsoft_priv *);
-extern void MTO_SetDTORateRange(struct wbsoft_priv *, u8 *, u8);
-extern u8 MTO_GetTxRate(struct wbsoft_priv *adapter, u32 fpdu_len);
-extern u8 MTO_GetTxFallbackRate(struct wbsoft_priv *adapter);
-extern void MTO_SetTxCount(struct wbsoft_priv *adapter, u8 t0, u8 index);
+void MTO_Init(struct wbsoft_priv *);
+void MTO_SetTxCount(struct wbsoft_priv *adapter, u8 t0, u8 index);
 
 #endif /* __MTO_H__ */
 
diff --git a/drivers/staging/winbond/phy_calibration.c b/drivers/staging/winbond/phy_calibration.c
index cfbfbbb..8aecced 100644
--- a/drivers/staging/winbond/phy_calibration.c
+++ b/drivers/staging/winbond/phy_calibration.c
@@ -27,10 +27,12 @@
 #define DEG2RAD(X)      (0.017453 * (X))
 
 static const s32 Angles[] = {
-	FIXED(DEG2RAD(45.0)),     FIXED(DEG2RAD(26.565)),   FIXED(DEG2RAD(14.0362)),
-	FIXED(DEG2RAD(7.12502)),  FIXED(DEG2RAD(3.57633)),  FIXED(DEG2RAD(1.78991)),
-	FIXED(DEG2RAD(0.895174)), FIXED(DEG2RAD(0.447614)), FIXED(DEG2RAD(0.223811)),
-	FIXED(DEG2RAD(0.111906)), FIXED(DEG2RAD(0.055953)), FIXED(DEG2RAD(0.027977))
+	FIXED(DEG2RAD(45.0)),     FIXED(DEG2RAD(26.565)),
+	FIXED(DEG2RAD(14.0362)),  FIXED(DEG2RAD(7.12502)),
+	FIXED(DEG2RAD(3.57633)),  FIXED(DEG2RAD(1.78991)),
+	FIXED(DEG2RAD(0.895174)), FIXED(DEG2RAD(0.447614)),
+	FIXED(DEG2RAD(0.223811)), FIXED(DEG2RAD(0.111906)),
+	FIXED(DEG2RAD(0.055953)), FIXED(DEG2RAD(0.027977))
 };
 
 /****************** LOCAL FUNCTION DECLARATION SECTION **********************/
@@ -42,7 +44,7 @@
 
 /****************** FUNCTION DEFINITION SECTION *****************************/
 
-s32 _s13_to_s32(u32 data)
+static s32 _s13_to_s32(u32 data)
 {
 	u32     val;
 
@@ -54,22 +56,8 @@
 	return (s32) val;
 }
 
-u32 _s32_to_s13(s32 data)
-{
-	u32     val;
-
-	if (data > 4095)
-		data = 4095;
-	else if (data < -4096)
-		data = -4096;
-
-	val = data & 0x1FFF;
-
-	return val;
-}
-
 /****************************************************************************/
-s32 _s4_to_s32(u32 data)
+static s32 _s4_to_s32(u32 data)
 {
 	s32     val;
 
@@ -81,7 +69,7 @@
 	return val;
 }
 
-u32 _s32_to_s4(s32 data)
+static u32 _s32_to_s4(s32 data)
 {
 	u32     val;
 
@@ -96,7 +84,7 @@
 }
 
 /****************************************************************************/
-s32 _s5_to_s32(u32 data)
+static s32 _s5_to_s32(u32 data)
 {
 	s32     val;
 
@@ -108,7 +96,7 @@
 	return val;
 }
 
-u32 _s32_to_s5(s32 data)
+static u32 _s32_to_s5(s32 data)
 {
 	u32     val;
 
@@ -123,7 +111,7 @@
 }
 
 /****************************************************************************/
-s32 _s6_to_s32(u32 data)
+static s32 _s6_to_s32(u32 data)
 {
 	s32     val;
 
@@ -135,7 +123,7 @@
 	return val;
 }
 
-u32 _s32_to_s6(s32 data)
+static u32 _s32_to_s6(s32 data)
 {
 	u32     val;
 
@@ -150,34 +138,7 @@
 }
 
 /****************************************************************************/
-s32 _s9_to_s32(u32 data)
-{
-	s32     val;
-
-	val = data & 0x00FF;
-
-	if ((data & BIT(8)) != 0)
-		val |= 0xFFFFFF00;
-
-	return val;
-}
-
-u32 _s32_to_s9(s32 data)
-{
-	u32     val;
-
-	if (data > 255)
-		data = 255;
-	else if (data < -256)
-		data = -256;
-
-	val = data & 0x01FF;
-
-	return val;
-}
-
-/****************************************************************************/
-s32 _floor(s32 n)
+static s32 _floor(s32 n)
 {
 	if (n > 0)
 		n += 5;
@@ -193,7 +154,7 @@
  * sqsum is the input and the output is sq_rt;
  * The maximum of sqsum = 2^27 -1;
  */
-u32 _sqrt(u32 sqsum)
+static u32 _sqrt(u32 sqsum)
 {
 	u32     sq_rt;
 
@@ -261,7 +222,7 @@
 }
 
 /****************************************************************************/
-void _sin_cos(s32 angle, s32 *sin, s32 *cos)
+static void _sin_cos(s32 angle, s32 *sin, s32 *cos)
 {
 	s32 X, Y, TargetAngle, CurrAngle;
 	unsigned    Step;
@@ -296,7 +257,8 @@
 	}
 }
 
-static unsigned char hal_get_dxx_reg(struct hw_data *pHwData, u16 number, u32 *pValue)
+static unsigned char hal_get_dxx_reg(struct hw_data *pHwData, u16 number,
+				     u32 *pValue)
 {
 	if (number < 0x1000)
 		number += 0x1000;
@@ -304,7 +266,8 @@
 }
 #define hw_get_dxx_reg(_A, _B, _C) hal_get_dxx_reg(_A, _B, (u32 *)_C)
 
-static unsigned char hal_set_dxx_reg(struct hw_data *pHwData, u16 number, u32 value)
+static unsigned char hal_set_dxx_reg(struct hw_data *pHwData, u16 number,
+				     u32 value)
 {
 	unsigned char ret;
 
@@ -316,7 +279,7 @@
 #define hw_set_dxx_reg(_A, _B, _C) hal_set_dxx_reg(_A, _B, (u32)_C)
 
 
-void _reset_rx_cal(struct hw_data *phw_data)
+static void _reset_rx_cal(struct hw_data *phw_data)
 {
 	u32     val;
 
@@ -336,7 +299,7 @@
 
 
 /**********************************************/
-void _rxadc_dc_offset_cancellation_winbond(struct hw_data *phw_data, u32 frequency)
+static void _rxadc_dc_offset_cancellation_winbond(struct hw_data *phw_data, u32 frequency)
 {
 	u32     reg_agc_ctrl3;
 	u32     reg_a_acq_ctrl;
@@ -407,7 +370,8 @@
 	PHY_DEBUG(("[CAL]    ** adc_dc_cal_i = %d (0x%04X)\n",
 			   _s9_to_s32(val&0x000001FF), val&0x000001FF));
 	PHY_DEBUG(("[CAL]    ** adc_dc_cal_q = %d (0x%04X)\n",
-			   _s9_to_s32((val&0x0003FE00)>>9), (val&0x0003FE00)>>9));
+			   _s9_to_s32((val&0x0003FE00)>>9),
+			   (val&0x0003FE00)>>9));
 #endif
 
 	hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &val);
@@ -430,249 +394,8 @@
 	hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3);
 }
 
-/****************************************************************/
-void _txidac_dc_offset_cancellation_winbond(struct hw_data *phw_data)
-{
-	u32     reg_agc_ctrl3;
-	u32     reg_mode_ctrl;
-	u32     reg_dc_cancel;
-	s32     iqcal_image_i;
-	s32     iqcal_image_q;
-	u32     sqsum;
-	s32     mag_0;
-	s32     mag_1;
-	s32     fix_cancel_dc_i = 0;
-	u32     val;
-	int     loop;
-
-	PHY_DEBUG(("[CAL] -> [2]_txidac_dc_offset_cancellation()\n"));
-
-	/* a. Set to "TX calibration mode" */
-
-	/* 0x01 0xEE3FC2  ; 3B8FF  ; Calibration (6a). enable TX IQ calibration loop circuits */
-	phy_set_rf_data(phw_data, 1, (1<<24)|0xEE3FC2);
-	/* 0x0B 0x1905D6  ; 06417  ; Calibration (6b). enable TX I/Q cal loop squaring circuit */
-	phy_set_rf_data(phw_data, 11, (11<<24)|0x1901D6);
-	/* 0x05 0x24C60A  ; 09318  ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized */
-	phy_set_rf_data(phw_data, 5, (5<<24)|0x24C48A);
-	/* 0x06 0x06880C  ; 01A20  ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */
-	phy_set_rf_data(phw_data, 6, (6<<24)|0x06890C);
-	/* 0x00 0xFDF1C0  ; 3F7C7  ; Calibration (6e). turn on IQ imbalance/Test mode */
-	phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0);
-
-	hw_set_dxx_reg(phw_data, 0x58, 0x30303030); /* IQ_Alpha Changed */
-
-	/* a. Disable AGC */
-	hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &reg_agc_ctrl3);
-	reg_agc_ctrl3 &= ~BIT(2);
-	reg_agc_ctrl3 |= (MASK_LNA_FIX_GAIN|MASK_AGC_FIX);
-	hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3);
-
-	hw_get_dxx_reg(phw_data, REG_AGC_CTRL5, &val);
-	val |= MASK_AGC_FIX_GAIN;
-	hw_set_dxx_reg(phw_data, REG_AGC_CTRL5, val);
-
-	/* b. set iqcal_mode[1:0] to 0x2 and set iqcal_tone[3:2] to 0 */
-	hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl);
-
-	PHY_DEBUG(("[CAL]    MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl));
-	reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE);
-
-	/* mode=2, tone=0 */
-	/* reg_mode_ctrl |= (MASK_CALIB_START|2); */
-
-	/* mode=2, tone=1 */
-	/* reg_mode_ctrl |= (MASK_CALIB_START|2|(1<<2)); */
-
-	/* mode=2, tone=2 */
-	reg_mode_ctrl |= (MASK_CALIB_START|2|(2<<2));
-	hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
-	PHY_DEBUG(("[CAL]    MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
-
-	hw_get_dxx_reg(phw_data, 0x5C, &reg_dc_cancel);
-	PHY_DEBUG(("[CAL]    DC_CANCEL (read) = 0x%08X\n", reg_dc_cancel));
-
-	for (loop = 0; loop < LOOP_TIMES; loop++) {
-		PHY_DEBUG(("[CAL] [%d.] ==================================\n", loop));
-
-		/* c. reset cancel_dc_i[9:5] and cancel_dc_q[4:0] in register DC_Cancel */
-		reg_dc_cancel &= ~(0x03FF);
-		PHY_DEBUG(("[CAL]    DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel));
-		hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel);
-
-		hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val);
-		PHY_DEBUG(("[CAL]    CALIB_READ2 = 0x%08X\n", val));
-
-		iqcal_image_i = _s13_to_s32(val & 0x00001FFF);
-		iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13);
-		sqsum = iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q;
-		mag_0 = (s32) _sqrt(sqsum);
-		PHY_DEBUG(("[CAL]    mag_0=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n",
-				   mag_0, iqcal_image_i, iqcal_image_q));
-
-		/* d. */
-		reg_dc_cancel |= (1 << CANCEL_DC_I_SHIFT);
-		PHY_DEBUG(("[CAL]    DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel));
-		hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel);
-
-		hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val);
-		PHY_DEBUG(("[CAL]    CALIB_READ2 = 0x%08X\n", val));
-
-		iqcal_image_i = _s13_to_s32(val & 0x00001FFF);
-		iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13);
-		sqsum = iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q;
-		mag_1 = (s32) _sqrt(sqsum);
-		PHY_DEBUG(("[CAL]    mag_1=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n",
-				   mag_1, iqcal_image_i, iqcal_image_q));
-
-		/* e. Calculate the correct DC offset cancellation value for I */
-		if (mag_0 != mag_1)
-			fix_cancel_dc_i = (mag_0*10000) / (mag_0*10000 - mag_1*10000);
-		else {
-			if (mag_0 == mag_1)
-				PHY_DEBUG(("[CAL]   ***** mag_0 = mag_1 !!\n"));
-			fix_cancel_dc_i = 0;
-		}
-
-		PHY_DEBUG(("[CAL]    ** fix_cancel_dc_i = %d (0x%04X)\n",
-				   fix_cancel_dc_i, _s32_to_s5(fix_cancel_dc_i)));
-
-		if ((abs(mag_1-mag_0)*6) > mag_0)
-			break;
-	}
-
-	if (loop >= 19)
-		fix_cancel_dc_i = 0;
-
-	reg_dc_cancel &= ~(0x03FF);
-	reg_dc_cancel |= (_s32_to_s5(fix_cancel_dc_i) << CANCEL_DC_I_SHIFT);
-	hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel);
-	PHY_DEBUG(("[CAL]    DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel));
-
-	/* g. */
-	reg_mode_ctrl &= ~MASK_CALIB_START;
-	hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
-	PHY_DEBUG(("[CAL]    MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
-}
-
-/*****************************************************/
-void _txqdac_dc_offset_cacellation_winbond(struct hw_data *phw_data)
-{
-	u32     reg_agc_ctrl3;
-	u32     reg_mode_ctrl;
-	u32     reg_dc_cancel;
-	s32     iqcal_image_i;
-	s32     iqcal_image_q;
-	u32     sqsum;
-	s32     mag_0;
-	s32     mag_1;
-	s32     fix_cancel_dc_q = 0;
-	u32     val;
-	int     loop;
-
-	PHY_DEBUG(("[CAL] -> [3]_txqdac_dc_offset_cacellation()\n"));
-	/*0x01 0xEE3FC2  ; 3B8FF  ; Calibration (6a). enable TX IQ calibration loop circuits */
-	phy_set_rf_data(phw_data, 1, (1<<24)|0xEE3FC2);
-	/* 0x0B 0x1905D6  ; 06417  ; Calibration (6b). enable TX I/Q cal loop squaring circuit */
-	phy_set_rf_data(phw_data, 11, (11<<24)|0x1901D6);
-	/* 0x05 0x24C60A  ; 09318  ; Calibration (6c). setting TX-VGA gain: TXGCH=2 & GPK=110 --> to be optimized */
-	phy_set_rf_data(phw_data, 5, (5<<24)|0x24C48A);
-	/* 0x06 0x06880C  ; 01A20  ; Calibration (6d). RXGCH=00; RXGCL=100 000 (RXVGA=32) --> to be optimized */
-	phy_set_rf_data(phw_data, 6, (6<<24)|0x06890C);
-	/* 0x00 0xFDF1C0  ; 3F7C7  ; Calibration (6e). turn on IQ imbalance/Test mode */
-	phy_set_rf_data(phw_data, 0, (0<<24)|0xFDF1C0);
-
-	hw_set_dxx_reg(phw_data, 0x58, 0x30303030); /* IQ_Alpha Changed */
-
-	/* a. Disable AGC */
-	hw_get_dxx_reg(phw_data, REG_AGC_CTRL3, &reg_agc_ctrl3);
-	reg_agc_ctrl3 &= ~BIT(2);
-	reg_agc_ctrl3 |= (MASK_LNA_FIX_GAIN|MASK_AGC_FIX);
-	hw_set_dxx_reg(phw_data, REG_AGC_CTRL3, reg_agc_ctrl3);
-
-	hw_get_dxx_reg(phw_data, REG_AGC_CTRL5, &val);
-	val |= MASK_AGC_FIX_GAIN;
-	hw_set_dxx_reg(phw_data, REG_AGC_CTRL5, val);
-
-	/* a. set iqcal_mode[1:0] to 0x3 and set iqcal_tone[3:2] to 0 */
-	hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl);
-	PHY_DEBUG(("[CAL]    MODE_CTRL (read) = 0x%08X\n", reg_mode_ctrl));
-
-	/* reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE); */
-	reg_mode_ctrl &= ~(MASK_IQCAL_MODE);
-	reg_mode_ctrl |= (MASK_CALIB_START|3);
-	hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
-	PHY_DEBUG(("[CAL]    MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
-
-	hw_get_dxx_reg(phw_data, 0x5C, &reg_dc_cancel);
-	PHY_DEBUG(("[CAL]    DC_CANCEL (read) = 0x%08X\n", reg_dc_cancel));
-
-	for (loop = 0; loop < LOOP_TIMES; loop++) {
-		PHY_DEBUG(("[CAL] [%d.] ==================================\n", loop));
-
-		/* b. reset cancel_dc_q[4:0] in register DC_Cancel */
-		reg_dc_cancel &= ~(0x001F);
-		PHY_DEBUG(("[CAL]    DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel));
-		hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel);
-
-		hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val);
-		PHY_DEBUG(("[CAL]    CALIB_READ2 = 0x%08X\n", val));
-
-		iqcal_image_i = _s13_to_s32(val & 0x00001FFF);
-		iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13);
-		sqsum = iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q;
-		mag_0 = _sqrt(sqsum);
-		PHY_DEBUG(("[CAL]    mag_0=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n",
-				   mag_0, iqcal_image_i, iqcal_image_q));
-
-		/* c. */
-		reg_dc_cancel |= (1 << CANCEL_DC_Q_SHIFT);
-		PHY_DEBUG(("[CAL]    DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel));
-		hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel);
-
-		hw_get_dxx_reg(phw_data, REG_CALIB_READ2, &val);
-		PHY_DEBUG(("[CAL]    CALIB_READ2 = 0x%08X\n", val));
-
-		iqcal_image_i = _s13_to_s32(val & 0x00001FFF);
-		iqcal_image_q = _s13_to_s32((val & 0x03FFE000) >> 13);
-		sqsum = iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q;
-		mag_1 = _sqrt(sqsum);
-		PHY_DEBUG(("[CAL]    mag_1=%d (iqcal_image_i=%d, iqcal_image_q=%d)\n",
-				   mag_1, iqcal_image_i, iqcal_image_q));
-
-		/* d. Calculate the correct DC offset cancellation value for I */
-		if (mag_0 != mag_1)
-			fix_cancel_dc_q = (mag_0*10000) / (mag_0*10000 - mag_1*10000);
-		else {
-			if (mag_0 == mag_1)
-				PHY_DEBUG(("[CAL]   ***** mag_0 = mag_1 !!\n"));
-			fix_cancel_dc_q = 0;
-		}
-
-		PHY_DEBUG(("[CAL]    ** fix_cancel_dc_q = %d (0x%04X)\n",
-				   fix_cancel_dc_q, _s32_to_s5(fix_cancel_dc_q)));
-
-		if ((abs(mag_1-mag_0)*6) > mag_0)
-			break;
-	}
-
-	if (loop >= 19)
-		fix_cancel_dc_q = 0;
-
-	reg_dc_cancel &= ~(0x001F);
-	reg_dc_cancel |= (_s32_to_s5(fix_cancel_dc_q) << CANCEL_DC_Q_SHIFT);
-	hw_set_dxx_reg(phw_data, 0x5C, reg_dc_cancel);
-	PHY_DEBUG(("[CAL]    DC_CANCEL (write) = 0x%08X\n", reg_dc_cancel));
-
-
-	/* f. */
-	reg_mode_ctrl &= ~MASK_CALIB_START;
-	hw_set_dxx_reg(phw_data, REG_MODE_CTRL, reg_mode_ctrl);
-	PHY_DEBUG(("[CAL]    MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
-}
-
 /* 20060612.1.a 20060718.1 Modify */
-u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data,
+static u8 _tx_iq_calibration_loop_winbond(struct hw_data *phw_data,
 						   s32 a_2_threshold,
 						   s32 b_2_threshold)
 {
@@ -711,7 +434,8 @@
 	loop = LOOP_TIMES;
 
 	while (loop > 0) {
-		PHY_DEBUG(("[CAL] [%d.] <_tx_iq_calibration_loop>\n", (LOOP_TIMES-loop+1)));
+		PHY_DEBUG(("[CAL] [%d.] <_tx_iq_calibration_loop>\n",
+				   (LOOP_TIMES-loop+1)));
 
 		iqcal_tone_i_avg = 0;
 		iqcal_tone_q_avg = 0;
@@ -719,8 +443,8 @@
 			return 0;
 		for (capture_time = 0; capture_time < 10; capture_time++) {
 			/*
-			 * a. Set iqcal_mode[1:0] to 0x2 and set "calib_start" to 0x1 to
-			 *    enable "IQ calibration Mode II"
+			 * a. Set iqcal_mode[1:0] to 0x2 and set "calib_start"
+			 *    to 0x1 to enable "IQ calibration Mode II"
 			 */
 			reg_mode_ctrl &= ~(MASK_IQCAL_TONE_SEL|MASK_IQCAL_MODE);
 			reg_mode_ctrl &= ~MASK_IQCAL_MODE;
@@ -749,8 +473,8 @@
 			PHY_DEBUG(("[CAL]    MODE_CTRL (write) = 0x%08X\n", reg_mode_ctrl));
 
 			/*
-			 * d. Set iqcal_mode[1:0] to 0x3 and set "calib_start" to 0x1 to
-			 *    enable "IQ calibration Mode II"
+			 * d. Set iqcal_mode[1:0] to 0x3 and set "calib_start"
+			 *    to 0x1 to enable "IQ calibration Mode II"
 			 */
 			/* hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &val); */
 			hw_get_dxx_reg(phw_data, REG_MODE_CTRL, &reg_mode_ctrl);
@@ -766,7 +490,7 @@
 			iqcal_tone_i = _s13_to_s32(val & 0x00001FFF);
 			iqcal_tone_q = _s13_to_s32((val & 0x03FFE000) >> 13);
 			PHY_DEBUG(("[CAL]    ** iqcal_tone_i = %d, iqcal_tone_q = %d\n",
-			iqcal_tone_i, iqcal_tone_q));
+					   iqcal_tone_i, iqcal_tone_q));
 			if (capture_time == 0)
 				continue;
 			else {
@@ -955,7 +679,7 @@
 	return 1;
 }
 
-void _tx_iq_calibration_winbond(struct hw_data *phw_data)
+static void _tx_iq_calibration_winbond(struct hw_data *phw_data)
 {
 	u32     reg_agc_ctrl3;
 #ifdef _DEBUG
@@ -1101,7 +825,7 @@
 }
 
 /*****************************************************/
-u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 frequency)
+static u8 _rx_iq_calibration_loop_winbond(struct hw_data *phw_data, u16 factor, u32 frequency)
 {
 	u32     reg_mode_ctrl;
 	s32     iqcal_tone_i;
@@ -1146,7 +870,8 @@
 	/* for (loop = 0; loop < LOOP_TIMES; loop++) */
 	loop = LOOP_TIMES;
 	while (loop > 0) {
-		PHY_DEBUG(("[CAL] [%d.] <_rx_iq_calibration_loop>\n", (LOOP_TIMES-loop+1)));
+		PHY_DEBUG(("[CAL] [%d.] <_rx_iq_calibration_loop>\n",
+				   (LOOP_TIMES-loop+1)));
 		iqcal_tone_i_avg = 0;
 		iqcal_tone_q_avg = 0;
 		iqcal_image_i_avg = 0;
@@ -1199,13 +924,13 @@
 
 		/* d. */
 		rot_tone_i_b = (iqcal_tone_i * iqcal_tone_i +
-						iqcal_tone_q * iqcal_tone_q) / 1024;
+					iqcal_tone_q * iqcal_tone_q) / 1024;
 		rot_tone_q_b = (iqcal_tone_i * iqcal_tone_q * (-1) +
-						iqcal_tone_q * iqcal_tone_i) / 1024;
+					iqcal_tone_q * iqcal_tone_i) / 1024;
 		rot_image_i_b = (iqcal_image_i * iqcal_tone_i -
-						 iqcal_image_q * iqcal_tone_q) / 1024;
+					iqcal_image_q * iqcal_tone_q) / 1024;
 		rot_image_q_b = (iqcal_image_i * iqcal_tone_q +
-						 iqcal_image_q * iqcal_tone_i) / 1024;
+					iqcal_image_q * iqcal_tone_i) / 1024;
 
 		PHY_DEBUG(("[CAL]    ** rot_tone_i_b  = %d\n", rot_tone_i_b));
 		PHY_DEBUG(("[CAL]    ** rot_tone_q_b  = %d\n", rot_tone_q_b));
@@ -1225,8 +950,10 @@
 		b_2 = (rot_image_q_b * 32768) / rot_tone_i_b -
 			phw_data->iq_rsdl_phase_tx_d2;
 
-		PHY_DEBUG(("[CAL]    ** iq_rsdl_gain_tx_d2 = %d\n", phw_data->iq_rsdl_gain_tx_d2));
-		PHY_DEBUG(("[CAL]    ** iq_rsdl_phase_tx_d2= %d\n", phw_data->iq_rsdl_phase_tx_d2));
+		PHY_DEBUG(("[CAL]    ** iq_rsdl_gain_tx_d2 = %d\n",
+			   phw_data->iq_rsdl_gain_tx_d2));
+		PHY_DEBUG(("[CAL]    ** iq_rsdl_phase_tx_d2= %d\n",
+			   phw_data->iq_rsdl_phase_tx_d2));
 		PHY_DEBUG(("[CAL]    ***** EPSILON/2 = %d\n", a_2));
 		PHY_DEBUG(("[CAL]    ***** THETA/2   = %d\n", b_2));
 
@@ -1272,7 +999,8 @@
 
 		/* e. */
 		pwr_tone = (iqcal_tone_i*iqcal_tone_i + iqcal_tone_q*iqcal_tone_q);
-		pwr_image = (iqcal_image_i*iqcal_image_i + iqcal_image_q*iqcal_image_q)*factor;
+		pwr_image = (iqcal_image_i*iqcal_image_i +
+			     iqcal_image_q*iqcal_image_q)*factor;
 
 		PHY_DEBUG(("[CAL]    ** pwr_tone  = %d\n", pwr_tone));
 		PHY_DEBUG(("[CAL]    ** pwr_image  = %d\n", pwr_image));
@@ -1371,7 +1099,7 @@
 /*************************************************/
 
 /***************************************************************/
-void _rx_iq_calibration_winbond(struct hw_data *phw_data, u32 frequency)
+static void _rx_iq_calibration_winbond(struct hw_data *phw_data, u32 frequency)
 {
 /* figo 20050523 marked this flag for can't compile for release */
 #ifdef _DEBUG
@@ -1569,7 +1297,8 @@
 
 		sqsum = iqcal_tone_i0*iqcal_tone_i0 + iqcal_tone_q0*iqcal_tone_q0;
 		iq_mag_0_tx = (s32) _sqrt(sqsum);
-		PHY_DEBUG(("[CAL]    ** auto_adjust_txvga_for_iq_mag_0_tx=%d\n", iq_mag_0_tx));
+		PHY_DEBUG(("[CAL]    ** auto_adjust_txvga_for_iq_mag_0_tx=%d\n",
+			   iq_mag_0_tx));
 
 		if (iq_mag_0_tx >= 700 && iq_mag_0_tx <= 1750)
 			break;
diff --git a/drivers/staging/winbond/reg.c b/drivers/staging/winbond/reg.c
index 75b7752..5fd4c4a 100644
--- a/drivers/staging/winbond/reg.c
+++ b/drivers/staging/winbond/reg.c
@@ -43,7 +43,7 @@
  */
 
 /* MAX2825 (pure b/g) */
-u32 max2825_rf_data[] = {
+static u32 max2825_rf_data[] = {
 	(0x00<<18) | 0x000a2,
 	(0x01<<18) | 0x21cc0,
 	(0x02<<18) | 0x13806,
@@ -59,7 +59,7 @@
 	(0x0C<<18) | 0x0c100   /* 11a: 0x0c300, 11g: 0x0c100 */
 };
 
-u32 max2825_channel_data_24[][3] = {
+static u32 max2825_channel_data_24[][3] = {
 	{(0x03 << 18) | 0x30142, (0x04 << 18) | 0x0b333, (0x05 << 18) | 0x289A6}, /* channel 01 */
 	{(0x03 << 18) | 0x32141, (0x04 << 18) | 0x08444, (0x05 << 18) | 0x289A6}, /* channel 02 */
 	{(0x03 << 18) | 0x32143, (0x04 << 18) | 0x0aeee, (0x05 << 18) | 0x289A6}, /* channel 03 */
@@ -76,11 +76,11 @@
 	{(0x03 << 18) | 0x32941, (0x04 << 18) | 0x09999, (0x05 << 18) | 0x289A6}  /* channel 14 (2484MHz) */
 };
 
-u32 max2825_power_data_24[] = {(0x0C << 18) | 0x0c000, (0x0C << 18) | 0x0c100};
+static u32 max2825_power_data_24[] = {(0x0C << 18) | 0x0c000, (0x0C << 18) | 0x0c100};
 
 /* ========================================== */
 /* MAX2827 (a/b/g) */
-u32 max2827_rf_data[] = {
+static u32 max2827_rf_data[] = {
 	(0x00 << 18) | 0x000a2,
 	(0x01 << 18) | 0x21cc0,
 	(0x02 << 18) | 0x13806,
@@ -96,7 +96,7 @@
 	(0x0C << 18) | 0x0c100   /* 11a: 0x0c300, 11g: 0x0c100 */
 };
 
-u32 max2827_channel_data_24[][3] = {
+static u32 max2827_channel_data_24[][3] = {
 	{(0x03 << 18) | 0x30142, (0x04 << 18) | 0x0b333, (0x05 << 18) | 0x289A6}, /* channe1 01 */
 	{(0x03 << 18) | 0x32141, (0x04 << 18) | 0x08444, (0x05 << 18) | 0x289A6}, /* channe1 02 */
 	{(0x03 << 18) | 0x32143, (0x04 << 18) | 0x0aeee, (0x05 << 18) | 0x289A6}, /* channe1 03 */
@@ -113,7 +113,7 @@
 	{(0x03 << 18) | 0x32941, (0x04 << 18) | 0x09999, (0x05 << 18) | 0x289A6}  /* channel 14 (2484MHz) */
 };
 
-u32 max2827_channel_data_50[][3] = {
+static u32 max2827_channel_data_50[][3] = {
 	{(0x03 << 18) | 0x33cc3, (0x04 << 18) | 0x08ccc, (0x05 << 18) | 0x2A9A6}, /* channel 36 */
 	{(0x03 << 18) | 0x302c0, (0x04 << 18) | 0x08000, (0x05 << 18) | 0x2A9A6}, /* channel 40 */
 	{(0x03 << 18) | 0x302c2, (0x04 << 18) | 0x0b333, (0x05 << 18) | 0x2A9A6}, /* channel 44 */
@@ -124,12 +124,12 @@
 	{(0x03 << 18) | 0x30ac2, (0x04 << 18) | 0x0b333, (0x05 << 18) | 0x2A9A6}  /* channel 64 */
 };
 
-u32 max2827_power_data_24[] = {(0x0C << 18) | 0x0C000, (0x0C << 18) | 0x0D600, (0x0C << 18) | 0x0C100};
-u32 max2827_power_data_50[] = {(0x0C << 18) | 0x0C400, (0x0C << 18) | 0x0D500, (0x0C << 18) | 0x0C300};
+static u32 max2827_power_data_24[] = {(0x0C << 18) | 0x0C000, (0x0C << 18) | 0x0D600, (0x0C << 18) | 0x0C100};
+static u32 max2827_power_data_50[] = {(0x0C << 18) | 0x0C400, (0x0C << 18) | 0x0D500, (0x0C << 18) | 0x0C300};
 
 /* ======================================================= */
 /* MAX2828 (a/b/g) */
-u32 max2828_rf_data[] = {
+static u32 max2828_rf_data[] = {
 	(0x00 << 18) | 0x000a2,
 	(0x01 << 18) | 0x21cc0,
 	(0x02 << 18) | 0x13806,
@@ -145,7 +145,7 @@
 	(0x0C << 18) | 0x0c100   /* 11a: 0x0c300, 11g: 0x0c100 */
 };
 
-u32 max2828_channel_data_24[][3] = {
+static u32 max2828_channel_data_24[][3] = {
 	{(0x03 << 18) | 0x30142, (0x04 << 18) | 0x0b333, (0x05 << 18) | 0x289A6}, /* channe1 01 */
 	{(0x03 << 18) | 0x32141, (0x04 << 18) | 0x08444, (0x05 << 18) | 0x289A6}, /* channe1 02 */
 	{(0x03 << 18) | 0x32143, (0x04 << 18) | 0x0aeee, (0x05 << 18) | 0x289A6}, /* channe1 03 */
@@ -162,7 +162,7 @@
 	{(0x03 << 18) | 0x32941, (0x04 << 18) | 0x09999, (0x05 << 18) | 0x289A6}  /* channel 14 (2484MHz) */
 };
 
-u32 max2828_channel_data_50[][3] = {
+static u32 max2828_channel_data_50[][3] = {
 	{(0x03 << 18) | 0x33cc3, (0x04 << 18) | 0x08ccc, (0x05 << 18) | 0x289A6}, /* channel 36 */
 	{(0x03 << 18) | 0x302c0, (0x04 << 18) | 0x08000, (0x05 << 18) | 0x289A6}, /* channel 40 */
 	{(0x03 << 18) | 0x302c2, (0x04 << 18) | 0x0b333, (0x05 << 18) | 0x289A6}, /* channel 44 */
@@ -173,12 +173,12 @@
 	{(0x03 << 18) | 0x30ac2, (0x04 << 18) | 0x0b333, (0x05 << 18) | 0x289A6}  /* channel 64 */
 };
 
-u32 max2828_power_data_24[] = {(0x0C << 18) | 0x0c000, (0x0C << 18) | 0x0c100};
-u32 max2828_power_data_50[] = {(0x0C << 18) | 0x0c000, (0x0C << 18) | 0x0c100};
+static u32 max2828_power_data_24[] = {(0x0C << 18) | 0x0c000, (0x0C << 18) | 0x0c100};
+static u32 max2828_power_data_50[] = {(0x0C << 18) | 0x0c000, (0x0C << 18) | 0x0c100};
 
 /* ========================================================== */
 /* MAX2829 (a/b/g) */
-u32 max2829_rf_data[] = {
+static u32 max2829_rf_data[] = {
 	(0x00 << 18) | 0x000a2,
 	(0x01 << 18) | 0x23520,
 	(0x02 << 18) | 0x13802,
@@ -194,7 +194,7 @@
 	(0x0C << 18) | 0x0F300 /* TXVGA=51, (MAX-6 dB) */
 };
 
-u32 max2829_channel_data_24[][3] = {
+static u32 max2829_channel_data_24[][3] = {
 	{(3 << 18) | 0x30142, (4 << 18) | 0x0b333, (5 << 18) | 0x289C6},  /* 01 (2412MHz) */
 	{(3 << 18) | 0x32141, (4 << 18) | 0x08444, (5 << 18) | 0x289C6},  /* 02 (2417MHz) */
 	{(3 << 18) | 0x32143, (4 << 18) | 0x0aeee, (5 << 18) | 0x289C6},  /* 03 (2422MHz) */
@@ -211,7 +211,7 @@
 	{(3 << 18) | 0x32941, (4 << 18) | 0x09999, (5 << 18) | 0x289C6},  /* 14 (2484MHz) */
 };
 
-u32 max2829_channel_data_50[][4] = {
+static u32 max2829_channel_data_50[][4] = {
 	{36, (3 << 18) | 0x33cc3, (4 << 18) | 0x08ccc, (5 << 18) | 0x2A946}, /* 36 (5.180GHz) */
 	{40, (3 << 18) | 0x302c0, (4 << 18) | 0x08000, (5 << 18) | 0x2A946}, /* 40 (5.200GHz) */
 	{44, (3 << 18) | 0x302c2, (4 << 18) | 0x0b333, (5 << 18) | 0x2A946}, /* 44 (5.220GHz) */
@@ -296,51 +296,6 @@
  * 0x0c 0x0c000
  * ====================================================================
  */
-u32 maxim_317_rf_data[] = {
-	(0x00 << 18) | 0x000a2,
-	(0x01 << 18) | 0x214c0,
-	(0x02 << 18) | 0x13802,
-	(0x03 << 18) | 0x30143,
-	(0x04 << 18) | 0x0accc,
-	(0x05 << 18) | 0x28986,
-	(0x06 << 18) | 0x18008,
-	(0x07 << 18) | 0x38400,
-	(0x08 << 18) | 0x05108,
-	(0x09 << 18) | 0x27ff8,
-	(0x0A << 18) | 0x14000,
-	(0x0B << 18) | 0x37f99,
-	(0x0C << 18) | 0x0c000
-};
-
-u32 maxim_317_channel_data_24[][3] = {
-	{(0x03 << 18) | 0x30143, (0x04 << 18) | 0x0accc, (0x05 << 18) | 0x28986}, /* channe1 01 */
-	{(0x03 << 18) | 0x32140, (0x04 << 18) | 0x09111, (0x05 << 18) | 0x28986}, /* channe1 02 */
-	{(0x03 << 18) | 0x32142, (0x04 << 18) | 0x0bbbb, (0x05 << 18) | 0x28986}, /* channe1 03 */
-	{(0x03 << 18) | 0x32143, (0x04 << 18) | 0x0accc, (0x05 << 18) | 0x28986}, /* channe1 04 */
-	{(0x03 << 18) | 0x31140, (0x04 << 18) | 0x09111, (0x05 << 18) | 0x28986}, /* channe1 05 */
-	{(0x03 << 18) | 0x31142, (0x04 << 18) | 0x0bbbb, (0x05 << 18) | 0x28986}, /* channe1 06 */
-	{(0x03 << 18) | 0x31143, (0x04 << 18) | 0x0accc, (0x05 << 18) | 0x28986}, /* channe1 07 */
-	{(0x03 << 18) | 0x33140, (0x04 << 18) | 0x09111, (0x05 << 18) | 0x28986}, /* channe1 08 */
-	{(0x03 << 18) | 0x33142, (0x04 << 18) | 0x0bbbb, (0x05 << 18) | 0x28986}, /* channe1 09 */
-	{(0x03 << 18) | 0x33143, (0x04 << 18) | 0x0accc, (0x05 << 18) | 0x28986}, /* channe1 10 */
-	{(0x03 << 18) | 0x30940, (0x04 << 18) | 0x09111, (0x05 << 18) | 0x28986}, /* channe1 11 */
-	{(0x03 << 18) | 0x30942, (0x04 << 18) | 0x0bbbb, (0x05 << 18) | 0x28986}, /* channe1 12 */
-	{(0x03 << 18) | 0x30943, (0x04 << 18) | 0x0accc, (0x05 << 18) | 0x28986}  /* channe1 13 */
-};
-
-u32 maxim_317_channel_data_50[][3] = {
-	{(0x03 << 18) | 0x33cc0, (0x04 << 18) | 0x0b333, (0x05 << 18) | 0x2a986}, /* channel 36 */
-	{(0x03 << 18) | 0x302c0, (0x04 << 18) | 0x08000, (0x05 << 18) | 0x2a986}, /* channel 40 */
-	{(0x03 << 18) | 0x302c3, (0x04 << 18) | 0x0accc, (0x05 << 18) | 0x2a986}, /* channel 44 */
-	{(0x03 << 18) | 0x322c1, (0x04 << 18) | 0x09666, (0x05 << 18) | 0x2a986}, /* channel 48 */
-	{(0x03 << 18) | 0x312c2, (0x04 << 18) | 0x09999, (0x05 << 18) | 0x2a986}, /* channel 52 */
-	{(0x03 << 18) | 0x332c0, (0x04 << 18) | 0x0b333, (0x05 << 18) | 0x2a99e}, /* channel 56 */
-	{(0x03 << 18) | 0x30ac0, (0x04 << 18) | 0x08000, (0x05 << 18) | 0x2a99e}, /* channel 60 */
-	{(0x03 << 18) | 0x30ac3, (0x04 << 18) | 0x0accc, (0x05 << 18) | 0x2a99e}  /* channel 64 */
-};
-
-u32 maxim_317_power_data_24[] = {(0x0C << 18) | 0x0c000, (0x0C << 18) | 0x0c100};
-u32 maxim_317_power_data_50[] = {(0x0C << 18) | 0x0c000, (0x0C << 18) | 0x0c100};
 
 /*
  * ===================================================================
@@ -388,7 +343,7 @@
  * 0x0f 0xf00a0 ; Restore Initial Setting
  * ==================================================================
  */
-u32 al2230_rf_data[] = {
+static u32 al2230_rf_data[] = {
 	(0x00 << 20) | 0x09EFC,
 	(0x01 << 20) | 0x8CCCC,
 	(0x02 << 20) | 0x40058,
@@ -406,7 +361,7 @@
 	(0x0F << 20) | 0xF01A0
 };
 
-u32 al2230s_rf_data[] = {
+static u32 al2230s_rf_data[] = {
 	(0x00 << 20) | 0x09EFC,
 	(0x01 << 20) | 0x8CCCC,
 	(0x02 << 20) | 0x40058,
@@ -424,7 +379,7 @@
 	(0x0F << 20) | 0xF01A0
 };
 
-u32 al2230_channel_data_24[][2] = {
+static u32 al2230_channel_data_24[][2] = {
 	{(0x00 << 20) | 0x09EFC, (0x01 << 20) | 0x8CCCC}, /* channe1 01 */
 	{(0x00 << 20) | 0x09EFC, (0x01 << 20) | 0x8CCCD}, /* channe1 02 */
 	{(0x00 << 20) | 0x09E7C, (0x01 << 20) | 0x8CCCC}, /* channe1 03 */
@@ -446,7 +401,7 @@
 #define AIROHA_TXVGA_MIDDLE_INDEX	12	/* Index for 0x96602 */
 #define AIROHA_TXVGA_HIGH_INDEX		8	/* Index for 0x97602 1.0.24.0 1.0.28.0 */
 
-u32 al2230_txvga_data[][2] = {
+static u32 al2230_txvga_data[][2] = {
 	/* value , index */
 	{0x090202, 0},
 	{0x094202, 2},
@@ -497,7 +452,7 @@
  */
 
 /* channel independent registers: */
-u32 al7230_rf_data_24[]	= {
+static u32 al7230_rf_data_24[]	= {
 	(0x00 << 24) | 0x003790,
 	(0x01 << 24) | 0x133331,
 	(0x02 << 24) | 0x841FF2,
@@ -516,7 +471,7 @@
 	(0x0F << 24) | 0x1ABA8F
 };
 
-u32 al7230_channel_data_24[][2] = {
+static u32 al7230_channel_data_24[][2] = {
 	{(0x00 << 24) | 0x003790, (0x01 << 24) | 0x133331}, /* channe1 01 */
 	{(0x00 << 24) | 0x003790, (0x01 << 24) | 0x1B3331}, /* channe1 02 */
 	{(0x00 << 24) | 0x003790, (0x01 << 24) | 0x033331}, /* channe1 03 */
@@ -534,7 +489,7 @@
 };
 
 /* channel independent registers: */
-u32 al7230_rf_data_50[]	= {
+static u32 al7230_rf_data_50[]	= {
 	(0x00 << 24) | 0x0FF520,
 	(0x01 << 24) | 0x000001,
 	(0x02 << 24) | 0x451FE2,
@@ -553,7 +508,7 @@
 	(0x0F << 24) | 0x12BACF  /* 5Ghz default state */
 };
 
-u32 al7230_channel_data_5[][4] = {
+static u32 al7230_channel_data_5[][4] = {
 	/* channel dependent registers: 0x00, 0x01 and 0x04 */
 	/* 11J =========== */
 	{184, (0x00 << 24) | 0x0FF520, (0x01 << 24) | 0x000001, (0x04 << 24) | 0x67F784}, /* channel 184 */
@@ -603,7 +558,7 @@
  */
 
 /* TXVGA Mapping Table <=== Register 0x0B */
-u32 al7230_txvga_data[][2] = {
+static u32 al7230_txvga_data[][2] = {
 	{0x08040B, 0}, /* TXVGA = 0; */
 	{0x08041B, 1}, /* TXVGA = 1; */
 	{0x08042B, 2}, /* TXVGA = 2; */
@@ -675,7 +630,7 @@
  * W89RF242 RFIC SPI programming initial data
  * Winbond WLAN 11g RFIC BB-SPI register -- version FA5976A rev 1.3b
  */
-u32 w89rf242_rf_data[] = {
+static u32 w89rf242_rf_data[] = {
 	(0x00 << 24) | 0xF86100, /* 3E184; MODA  (0x00) -- Normal mode ; calibration off */
 	(0x01 << 24) | 0xEFFFC2, /* 3BFFF; MODB  (0x01) -- turn off RSSI, and other circuits are turned on */
 	(0x02 << 24) | 0x102504, /* 04094; FSET  (0x02) -- default 20MHz crystal ; Icmp=1.5mA */
@@ -696,7 +651,7 @@
 	(0x12 << 24) | 0x000024  /* TMODC (0x12) -- Turn OFF Temperature sensor */
 };
 
-u32 w89rf242_channel_data_24[][2] = {
+static u32 w89rf242_channel_data_24[][2] = {
 	{(0x03 << 24) | 0x025B06, (0x04 << 24) | 0x080408}, /* channe1 01 */
 	{(0x03 << 24) | 0x025C46, (0x04 << 24) | 0x080408}, /* channe1 02 */
 	{(0x03 << 24) | 0x025D86, (0x04 << 24) | 0x080408}, /* channe1 03 */
@@ -713,9 +668,7 @@
 	{(0x03 << 24) | 0x026D06, (0x04 << 24) | 0x080408}  /* channe1 14 */
 };
 
-u32 w89rf242_power_data_24[] = {(0x05 << 24) | 0x24C48A, (0x05 << 24) | 0x24C48A, (0x05 << 24) | 0x24C48A};
-
-u32 w89rf242_txvga_old_mapping[][2] = {
+static u32 w89rf242_txvga_old_mapping[][2] = {
 	{0, 0} , /* New <-> Old */
 	{1, 1} ,
 	{2, 2} ,
@@ -738,7 +691,7 @@
 	{34, 19},
 };
 
-u32 w89rf242_txvga_data[][5] = {
+static u32 w89rf242_txvga_data[][5] = {
 	/* low gain mode */
 	{(0x05 << 24) | 0x24C00A, 0, 0x00292315, 0x0800FEFF, 0x52523131}, /* min gain */
 	{(0x05 << 24) | 0x24C80A, 1, 0x00292315, 0x0800FEFF, 0x52523131},
@@ -920,7 +873,7 @@
 	Wb35Reg_WriteSync(pHwData, 0x03f8, 0x7ff);
 }
 
-static void Set_ChanIndep_RfData_al7230_24(struct hw_data *pHwData, u32 *pltmp, 
+static void Set_ChanIndep_RfData_al7230_24(struct hw_data *pHwData, u32 *pltmp,
 					char number)
 {
 	u8	i;
@@ -930,7 +883,7 @@
 	}
 }
 
-static void Set_ChanIndep_RfData_al7230_50(struct hw_data *pHwData, u32 *pltmp, 
+static void Set_ChanIndep_RfData_al7230_50(struct hw_data *pHwData, u32 *pltmp,
 					char number)
 {
 	u8	i;
@@ -1088,7 +1041,7 @@
 		msleep(5);
 
 		ltmp = (1 << 31) | (0 << 30) | (20 << 24) | BitReverse((0x0F << 20) | 0xF01A0, 20);
-		Wb35Reg_WriteSync(pHwData, 0x0864, ltmp) ;
+		Wb35Reg_WriteSync(pHwData, 0x0864, ltmp);
 
 		Wb35Reg_WriteSync(pHwData, 0x105c, pHwData->reg.BB5C);
 		pHwData->reg.BB50 &= ~0x13; /* (MASK_IQCAL_MODE|MASK_CALIB_START); */
@@ -1620,13 +1573,13 @@
 		reg->SQ3_filter[i] = 0x2f; /* half of Bit 0 ~ 6 */
 }
 
-static inline void set_tx_power_per_channel_max2829(struct hw_data *pHwData,  
+static inline void set_tx_power_per_channel_max2829(struct hw_data *pHwData,
 						struct chan_info Channel)
 {
 	RFSynthesizer_SetPowerIndex(pHwData, 100);
 }
 
-static void set_tx_power_per_channel_al2230(struct hw_data *pHwData,  
+static void set_tx_power_per_channel_al2230(struct hw_data *pHwData,
 					struct chan_info Channel)
 {
 	u8	index = 100;
@@ -1636,7 +1589,7 @@
 	RFSynthesizer_SetPowerIndex(pHwData, index);
 }
 
-static void set_tx_power_per_channel_al7230(struct hw_data *pHwData,  
+static void set_tx_power_per_channel_al7230(struct hw_data *pHwData,
 					struct chan_info Channel)
 {
 	u8	i, index = 100;
@@ -1660,7 +1613,7 @@
 	RFSynthesizer_SetPowerIndex(pHwData, index);
 }
 
-static void set_tx_power_per_channel_wb242(struct hw_data *pHwData,  
+static void set_tx_power_per_channel_wb242(struct hw_data *pHwData,
 					struct chan_info Channel)
 {
 	u8	index = 100;
@@ -2096,7 +2049,7 @@
 	pltmp[5] = reg->M38_MacControl;
 
 	/* M3C */
-	tmp = (DEFAULT_PIFST << 26) | (DEFAULT_EIFST << 16) | (DEFAULT_DIFST << 8) | (DEFAULT_SIFST << 4) | DEFAULT_OSIFST ;
+	tmp = (DEFAULT_PIFST << 26) | (DEFAULT_EIFST << 16) | (DEFAULT_DIFST << 8) | (DEFAULT_SIFST << 4) | DEFAULT_OSIFST;
 	reg->M3C_MacControl = tmp;
 	pltmp[6] = tmp;
 
diff --git a/drivers/staging/winbond/wb35tx.c b/drivers/staging/winbond/wb35tx.c
index 30a77cc..708c5b0 100644
--- a/drivers/staging/winbond/wb35tx.c
+++ b/drivers/staging/winbond/wb35tx.c
@@ -180,7 +180,7 @@
 {
 	struct hw_data *pHwData = &adapter->sHwData;
 	struct wb35_tx *pWb35Tx = &pHwData->Wb35Tx;
-	unsigned char Trigger = false;
+	bool Trigger = false;
 
 	if (pWb35Tx->TxTimer > TimeCount)
 		Trigger = true;
diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c
index 3fa1ae4..07891a3 100644
--- a/drivers/staging/winbond/wbusb.c
+++ b/drivers/staging/winbond/wbusb.c
@@ -122,16 +122,16 @@
 {
 	struct wbsoft_priv *priv = dev->priv;
 
-	if (priv->sMlmeFrame.IsInUsed != PACKET_FREE_TO_USE) {
+	if (priv->sMlmeFrame.is_in_used != PACKET_FREE_TO_USE) {
 		priv->sMlmeFrame.wNumTxMMPDUDiscarded++;
 		kfree_skb(skb);
 		return;
 	}
 
-	priv->sMlmeFrame.IsInUsed = PACKET_COME_FROM_MLME;
+	priv->sMlmeFrame.is_in_used = PACKET_COME_FROM_MLME;
 
 	priv->sMlmeFrame.pMMPDU		= skb->data;
-	priv->sMlmeFrame.DataType	= FRAME_TYPE_802_11_MANAGEMENT;
+	priv->sMlmeFrame.data_type	= FRAME_TYPE_802_11_MANAGEMENT;
 	priv->sMlmeFrame.len		= skb->len;
 	priv->sMlmeFrame.wNumTxMMPDU++;
 
diff --git a/drivers/staging/wlags49_h2/hcf.h b/drivers/staging/wlags49_h2/hcf.h
index 2abeaa1..71b4465 100644
--- a/drivers/staging/wlags49_h2/hcf.h
+++ b/drivers/staging/wlags49_h2/hcf.h
@@ -372,22 +372,22 @@
 /**********************   W C I    F U N C T I O N S    P R O T O T Y P E S   ******************************/
 /***********************************************************************************************************/
 
-EXTERN_C int		 hcf_action			(IFBP ifbp, hcf_16 cmd );
-EXTERN_C int		 hcf_connect		(IFBP ifbp, hcf_io io_base );
-EXTERN_C int		 hcf_get_info		(IFBP ifbp, LTVP ltvp );
-EXTERN_C int		 hcf_service_nic	(IFBP ifbp, wci_bufp bufp, unsigned int len );
-EXTERN_C int		 hcf_cntl			(IFBP ifbp, hcf_16 cmd );
-EXTERN_C int		 hcf_put_info		(IFBP ifbp, LTVP ltvp );
-EXTERN_C int		 hcf_rcv_msg		(IFBP ifbp, DESC_STRCT *descp, unsigned int offset );
-EXTERN_C int		 hcf_send_msg       (IFBP ifbp, DESC_STRCT *dp, hcf_16 tx_cntl );
+EXTERN_C int hcf_action(IFBP ifbp, hcf_16 cmd);
+EXTERN_C int hcf_connect(IFBP ifbp, hcf_io io_base);
+EXTERN_C int hcf_get_info(IFBP ifbp, LTVP ltvp);
+EXTERN_C int hcf_service_nic(IFBP ifbp, wci_bufp bufp, unsigned int len);
+EXTERN_C int hcf_cntl(IFBP ifbp, hcf_16 cmd);
+EXTERN_C int hcf_put_info(IFBP ifbp, LTVP ltvp);
+EXTERN_C int hcf_rcv_msg(IFBP ifbp, DESC_STRCT *descp, unsigned int offset);
+EXTERN_C int hcf_send_msg(IFBP ifbp, DESC_STRCT *dp, hcf_16 tx_cntl);
 #if HCF_DMA
-EXTERN_C void		 hcf_dma_tx_put 	(IFBP ifbp, DESC_STRCT *d, hcf_16 tx_cntl );
+EXTERN_C void hcf_dma_tx_put(IFBP ifbp, DESC_STRCT *d, hcf_16 tx_cntl);
 EXTERN_C DESC_STRCT* hcf_dma_tx_get		(IFBP ifbp );
 EXTERN_C DESC_STRCT* hcf_dma_rx_get		(IFBP ifbp );
-EXTERN_C void		 hcf_dma_rx_put		(IFBP ifbp, DESC_STRCT *d );
+EXTERN_C void hcf_dma_rx_put(IFBP ifbp, DESC_STRCT *d);
 #endif // HCF_DMA
 #if (HCF_ASSERT) & HCF_ASSERT_LNK_MSF_RTN
-EXTERN_C void		 msf_assert	 		(unsigned int line_number, hcf_16 trace, hcf_32 qual );
+EXTERN_C void msf_assert(unsigned int line_number, hcf_16 trace, hcf_32 qual);
 #endif // HCF_ASSERT_LNK_MSF_RTN
 
 #endif  // HCF_H
diff --git a/drivers/staging/wlags49_h2/sta_h2.c b/drivers/staging/wlags49_h2/sta_h2.c
index 19bed81..25ac76f 100644
--- a/drivers/staging/wlags49_h2/sta_h2.c
+++ b/drivers/staging/wlags49_h2/sta_h2.c
@@ -4472,8 +4472,8 @@
 	"FUPU7D37dhfwci\001C",			/* signature, <format number>, C/Bin type */
 	(CFG_PROG_STRCT *) fw_image_code,
 	0x000F368E,
-	00000000,					/* (dummy) pdaplug */
-	00000000,					/* (dummy) priplug */
+	NULL,					/* (dummy) pdaplug */
+	NULL,					/* (dummy) priplug */
 	(CFG_RANGE20_STRCT *) fw_image_infocompat,
 	(CFG_IDENTITY_STRCT *) fw_image_infoidentity,
 };
diff --git a/drivers/staging/wlags49_h2/wl_priv.c b/drivers/staging/wlags49_h2/wl_priv.c
index c97e0e1..7e10dcd 100644
--- a/drivers/staging/wlags49_h2/wl_priv.c
+++ b/drivers/staging/wlags49_h2/wl_priv.c
@@ -570,6 +570,7 @@
 	ltv_t                   *pLtv;
 	bool_t                  ltvAllocated = FALSE;
 	ENCSTRCT                sEncryption;
+	size_t			len;
 
 #ifdef USE_WDS
 	hcf_16                  hcfPort  = HCF_PORT_0;
@@ -686,7 +687,8 @@
 					break;
 				case CFG_CNF_OWN_NAME:
 					memset(lp->StationName, 0, sizeof(lp->StationName));
-					memcpy((void *)lp->StationName, (void *)&pLtv->u.u8[2], (size_t)pLtv->u.u16[0]);
+					len = min_t(size_t, pLtv->u.u16[0], sizeof(lp->StationName));
+					strlcpy(lp->StationName, &pLtv->u.u8[2], len);
 					pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 					break;
 				case CFG_CNF_LOAD_BALANCING:
@@ -1783,6 +1785,7 @@
 {
 	struct wl_private *lp = wl_priv(dev);
 	unsigned long flags;
+	size_t len;
 	int         ret = 0;
 	/*------------------------------------------------------------------------*/
 
@@ -1793,8 +1796,8 @@
 	wl_lock(lp, &flags);
 
 	memset(lp->StationName, 0, sizeof(lp->StationName));
-
-	memcpy(lp->StationName, extra, wrqu->data.length);
+	len = min_t(size_t, wrqu->data.length, sizeof(lp->StationName));
+	strlcpy(lp->StationName, extra, len);
 
 	/* Commit the adapter parameters */
 	wl_apply(lp);
diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c
index f1bce18..a4fd5c4 100644
--- a/drivers/staging/wlan-ng/cfg80211.c
+++ b/drivers/staging/wlan-ng/cfg80211.c
@@ -98,10 +98,10 @@
 
 
 /* The interface functions, called by the cfg80211 layer */
-int prism2_change_virtual_intf(struct wiphy *wiphy,
-			       struct net_device *dev,
-			       enum nl80211_iftype type, u32 *flags,
-			       struct vif_params *params)
+static int prism2_change_virtual_intf(struct wiphy *wiphy,
+				      struct net_device *dev,
+				      enum nl80211_iftype type, u32 *flags,
+				      struct vif_params *params)
 {
 	wlandevice_t *wlandev = dev->ml_priv;
 	u32 data;
@@ -122,7 +122,7 @@
 		data = 1;
 		break;
 	default:
-		printk(KERN_WARNING "Operation mode: %d not support\n", type);
+		netdev_warn(dev, "Operation mode: %d not support\n", type);
 		return -EOPNOTSUPP;
 	}
 
@@ -140,9 +140,9 @@
 	return err;
 }
 
-int prism2_add_key(struct wiphy *wiphy, struct net_device *dev,
-		   u8 key_index, bool pairwise, const u8 *mac_addr,
-		   struct key_params *params)
+static int prism2_add_key(struct wiphy *wiphy, struct net_device *dev,
+			  u8 key_index, bool pairwise, const u8 *mac_addr,
+			  struct key_params *params)
 {
 	wlandevice_t *wlandev = dev->ml_priv;
 	u32 did;
@@ -199,9 +199,10 @@
 	return err;
 }
 
-int prism2_get_key(struct wiphy *wiphy, struct net_device *dev,
-		   u8 key_index, bool pairwise, const u8 *mac_addr, void *cookie,
-		   void (*callback)(void *cookie, struct key_params*))
+static int prism2_get_key(struct wiphy *wiphy, struct net_device *dev,
+			  u8 key_index, bool pairwise,
+			  const u8 *mac_addr, void *cookie,
+			  void (*callback)(void *cookie, struct key_params*))
 {
 	wlandevice_t *wlandev = dev->ml_priv;
 	struct key_params params;
@@ -228,8 +229,8 @@
 	return 0;
 }
 
-int prism2_del_key(struct wiphy *wiphy, struct net_device *dev,
-		   u8 key_index, bool pairwise, const u8 *mac_addr)
+static int prism2_del_key(struct wiphy *wiphy, struct net_device *dev,
+			  u8 key_index, bool pairwise, const u8 *mac_addr)
 {
 	wlandevice_t *wlandev = dev->ml_priv;
 	u32 did;
@@ -274,8 +275,8 @@
 	return err;
 }
 
-int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev,
-			   u8 key_index, bool unicast, bool multicast)
+static int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev,
+				  u8 key_index, bool unicast, bool multicast)
 {
 	wlandevice_t *wlandev = dev->ml_priv;
 
@@ -293,8 +294,8 @@
 }
 
 
-int prism2_get_station(struct wiphy *wiphy, struct net_device *dev,
-		       u8 *mac, struct station_info *sinfo)
+static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev,
+			      u8 *mac, struct station_info *sinfo)
 {
 	wlandevice_t *wlandev = dev->ml_priv;
 	struct p80211msg_lnxreq_commsquality quality;
@@ -327,7 +328,7 @@
 	return result;
 }
 
-int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
+static int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
 {
 	struct net_device *dev;
 	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
@@ -352,7 +353,7 @@
 		return -EBUSY;
 
 	if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
-		printk(KERN_ERR "Can't scan in AP mode\n");
+		netdev_err(dev, "Can't scan in AP mode\n");
 		return -EOPNOTSUPP;
 	}
 
@@ -436,7 +437,7 @@
 	return err;
 }
 
-int prism2_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+static int prism2_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 {
 	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
 	wlandevice_t *wlandev = priv->wlandev;
@@ -478,8 +479,8 @@
 	return err;
 }
 
-int prism2_connect(struct wiphy *wiphy, struct net_device *dev,
-		   struct cfg80211_connect_params *sme)
+static int prism2_connect(struct wiphy *wiphy, struct net_device *dev,
+			  struct cfg80211_connect_params *sme)
 {
 	wlandevice_t *wlandev = dev->ml_priv;
 	struct ieee80211_channel *channel = sme->channel;
@@ -510,7 +511,7 @@
 		((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && is_wep))
 			msg_join.authtype.data = P80211ENUM_authalg_sharedkey;
 	else
-		printk(KERN_WARNING
+		netdev_warn(dev,
 			"Unhandled authorisation type for connect (%d)\n",
 			sme->auth_type);
 
@@ -602,8 +603,8 @@
 	return err;
 }
 
-int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev,
-		      u16 reason_code)
+static int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev,
+			     u16 reason_code)
 {
 	wlandevice_t *wlandev = dev->ml_priv;
 	struct p80211msg_lnxreq_autojoin msg_join;
@@ -626,20 +627,20 @@
 }
 
 
-int prism2_join_ibss(struct wiphy *wiphy, struct net_device *dev,
-		     struct cfg80211_ibss_params *params)
+static int prism2_join_ibss(struct wiphy *wiphy, struct net_device *dev,
+			    struct cfg80211_ibss_params *params)
 {
 	return -EOPNOTSUPP;
 }
 
-int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
+static int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 {
 	return -EOPNOTSUPP;
 }
 
 
-int prism2_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
-			enum nl80211_tx_power_setting type, int mbm)
+static int prism2_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+			       enum nl80211_tx_power_setting type, int mbm)
 {
 	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
 	wlandevice_t *wlandev = priv->wlandev;
@@ -665,8 +666,8 @@
 	return err;
 }
 
-int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
-			int *dbm)
+static int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+			       int *dbm)
 {
 	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
 	wlandevice_t *wlandev = priv->wlandev;
diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c
index c1a8cb6..5b8b094 100644
--- a/drivers/staging/wlan-ng/hfa384x_usb.c
+++ b/drivers/staging/wlan-ng/hfa384x_usb.c
@@ -355,7 +355,7 @@
 
 		/* Check whether we need to reset the RX pipe */
 		if (result == -EPIPE) {
-			printk(KERN_WARNING
+			netdev_warn(hw->wlandev->netdev,
 			       "%s rx pipe stalled: requesting reset\n",
 			       hw->wlandev->netdev->name);
 			if (!test_and_set_bit(WORK_RX_HALT, &hw->usb_flags))
@@ -405,7 +405,7 @@
 
 			/* Test whether we need to reset the TX pipe */
 			if (result == -EPIPE) {
-				printk(KERN_WARNING
+				netdev_warn(hw->wlandev->netdev,
 				       "%s tx pipe stalled: requesting reset\n",
 				       netdev->name);
 				set_bit(WORK_TX_HALT, &hw->usb_flags);
@@ -454,11 +454,11 @@
 
 		ret = usb_clear_halt(hw->usb, hw->endp_in);
 		if (ret != 0) {
-			printk(KERN_ERR
+			netdev_err(hw->wlandev->netdev,
 			       "Failed to clear rx pipe for %s: err=%d\n",
 			       netdev->name, ret);
 		} else {
-			printk(KERN_INFO "%s rx pipe reset complete.\n",
+			netdev_info(hw->wlandev->netdev, "%s rx pipe reset complete.\n",
 			       netdev->name);
 			clear_bit(WORK_RX_HALT, &hw->usb_flags);
 			set_bit(WORK_RX_RESUME, &hw->usb_flags);
@@ -471,7 +471,7 @@
 
 		ret = submit_rx_urb(hw, GFP_KERNEL);
 		if (ret != 0) {
-			printk(KERN_ERR
+			netdev_err(hw->wlandev->netdev,
 			       "Failed to resume %s rx pipe.\n", netdev->name);
 		} else {
 			clear_bit(WORK_RX_RESUME, &hw->usb_flags);
@@ -485,11 +485,11 @@
 		usb_kill_urb(&hw->tx_urb);
 		ret = usb_clear_halt(hw->usb, hw->endp_out);
 		if (ret != 0) {
-			printk(KERN_ERR
+			netdev_err(hw->wlandev->netdev,
 			       "Failed to clear tx pipe for %s: err=%d\n",
 			       netdev->name, ret);
 		} else {
-			printk(KERN_INFO "%s tx pipe reset complete.\n",
+			netdev_info(hw->wlandev->netdev, "%s tx pipe reset complete.\n",
 			       netdev->name);
 			clear_bit(WORK_TX_HALT, &hw->usb_flags);
 			set_bit(WORK_TX_RESUME, &hw->usb_flags);
@@ -1211,7 +1211,7 @@
 
 	result = usb_reset_device(hw->usb);
 	if (result < 0) {
-		printk(KERN_ERR "usb_reset_device() failed, result=%d.\n",
+		netdev_err(hw->wlandev->netdev, "usb_reset_device() failed, result=%d.\n",
 		       result);
 	}
 
@@ -1311,7 +1311,7 @@
 		if (ctlx->state == CTLX_COMPLETE) {
 			result = completor->complete(completor);
 		} else {
-			printk(KERN_WARNING "CTLX[%d] error: state(%s)\n",
+			netdev_warn(hw->wlandev->netdev, "CTLX[%d] error: state(%s)\n",
 			       le16_to_cpu(ctlx->outbuf.type),
 			       ctlxstr(ctlx->state));
 			result = -EIO;
@@ -2018,7 +2018,7 @@
 	if (hw->dlstate != HFA384x_DLSTATE_FLASHENABLED)
 		return -EINVAL;
 
-	printk(KERN_INFO "Download %d bytes to flash @0x%06x\n", len, daddr);
+	netdev_info(hw->wlandev->netdev, "Download %d bytes to flash @0x%06x\n", len, daddr);
 
 	/* Convert to flat address for arithmetic */
 	/* NOTE: dlbuffer RID stores the address in AUX format */
@@ -2028,7 +2028,7 @@
 		 hw->bufinfo.page, hw->bufinfo.offset, dlbufaddr);
 
 #if 0
-	printk(KERN_WARNING "dlbuf@0x%06lx len=%d to=%d\n", dlbufaddr,
+	netdev_warn(hw->wlandev->netdev, "dlbuf@0x%06lx len=%d to=%d\n", dlbufaddr,
 	       hw->bufinfo.len, hw->dltimeout);
 #endif
 	/* Calculations to determine how many fills of the dlbuffer to do
@@ -2055,14 +2055,14 @@
 		burnlo = HFA384x_ADDR_CMD_MKOFF(burndaddr);
 		burnhi = HFA384x_ADDR_CMD_MKPAGE(burndaddr);
 
-		printk(KERN_INFO "Writing %d bytes to flash @0x%06x\n",
+		netdev_info(hw->wlandev->netdev, "Writing %d bytes to flash @0x%06x\n",
 		       burnlen, burndaddr);
 
 		/* Set the download mode */
 		result = hfa384x_cmd_download(hw, HFA384x_PROGMODE_NV,
 					      burnlo, burnhi, burnlen);
 		if (result) {
-			printk(KERN_ERR "download(NV,lo=%x,hi=%x,len=%x) "
+			netdev_err(hw->wlandev->netdev, "download(NV,lo=%x,hi=%x,len=%x) "
 			       "cmd failed, result=%d. Aborting d/l\n",
 			       burnlo, burnhi, burnlen, result);
 			goto exit_proc;
@@ -2094,7 +2094,7 @@
 					      HFA384x_PROGMODE_NVWRITE,
 					      0, 0, 0);
 		if (result) {
-			printk(KERN_ERR
+			netdev_err(hw->wlandev->netdev,
 			       "download(NVWRITE,lo=%x,hi=%x,len=%x) "
 			       "cmd failed, result=%d. Aborting d/l\n",
 			       burnlo, burnhi, burnlen, result);
@@ -2279,7 +2279,7 @@
 	/* Check that a port isn't active */
 	for (i = 0; i < HFA384x_PORTID_MAX; i++) {
 		if (hw->port_enabled[i]) {
-			printk(KERN_ERR
+			netdev_err(hw->wlandev->netdev,
 			       "Can't download with a macport enabled.\n");
 			return -EINVAL;
 		}
@@ -2287,7 +2287,7 @@
 
 	/* Check that we're not already in a download state */
 	if (hw->dlstate != HFA384x_DLSTATE_DISABLED) {
-		printk(KERN_ERR "Download state not disabled.\n");
+		netdev_err(hw->wlandev->netdev, "Download state not disabled.\n");
 		return -EINVAL;
 	}
 
@@ -2352,7 +2352,7 @@
 	if (hw->dlstate != HFA384x_DLSTATE_RAMENABLED)
 		return -EINVAL;
 
-	printk(KERN_INFO "Writing %d bytes to ram @0x%06x\n", len, daddr);
+	netdev_info(hw->wlandev->netdev, "Writing %d bytes to ram @0x%06x\n", len, daddr);
 
 	/* How many dowmem calls?  */
 	nwrites = len / HFA384x_USB_RWMEM_MAXLEN;
@@ -2449,7 +2449,7 @@
 						len);
 
 		if (result) {
-			printk(KERN_WARNING
+			netdev_warn(hw->wlandev->netdev,
 			       "Read from index %zd failed, continuing\n", i);
 			continue;
 		}
@@ -2462,13 +2462,13 @@
 			pdrcode = le16_to_cpu(pda[currpdr + 1]);
 			/* Test the record length */
 			if (pdrlen > HFA384x_PDR_LEN_MAX || pdrlen == 0) {
-				printk(KERN_ERR "pdrlen invalid=%d\n", pdrlen);
+				netdev_err(hw->wlandev->netdev, "pdrlen invalid=%d\n", pdrlen);
 				pdaok = 0;
 				break;
 			}
 			/* Test the code */
 			if (!hfa384x_isgood_pdrcode(pdrcode)) {
-				printk(KERN_ERR "pdrcode invalid=%d\n",
+				netdev_err(hw->wlandev->netdev, "pdrcode invalid=%d\n",
 				       pdrcode);
 				pdaok = 0;
 				break;
@@ -2484,7 +2484,7 @@
 			}
 		}
 		if (pdaok) {
-			printk(KERN_INFO
+			netdev_info(hw->wlandev->netdev,
 			       "PDA Read from 0x%08x in %s space.\n",
 			       pdaloc[i].cardaddr,
 			       pdaloc[i].auxctl == 0 ? "EXTDS" :
@@ -2564,20 +2564,20 @@
 	result =
 	    usb_get_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_in, &status);
 	if (result < 0) {
-		printk(KERN_ERR "Cannot get bulk in endpoint status.\n");
+		netdev_err(hw->wlandev->netdev, "Cannot get bulk in endpoint status.\n");
 		goto done;
 	}
 	if ((status == 1) && usb_clear_halt(hw->usb, hw->endp_in))
-		printk(KERN_ERR "Failed to reset bulk in endpoint.\n");
+		netdev_err(hw->wlandev->netdev, "Failed to reset bulk in endpoint.\n");
 
 	result =
 	    usb_get_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_out, &status);
 	if (result < 0) {
-		printk(KERN_ERR "Cannot get bulk out endpoint status.\n");
+		netdev_err(hw->wlandev->netdev, "Cannot get bulk out endpoint status.\n");
 		goto done;
 	}
 	if ((status == 1) && usb_clear_halt(hw->usb, hw->endp_out))
-		printk(KERN_ERR "Failed to reset bulk out endpoint.\n");
+		netdev_err(hw->wlandev->netdev, "Failed to reset bulk out endpoint.\n");
 
 	/* Synchronous unlink, in case we're trying to restart the driver */
 	usb_kill_urb(&hw->rx_urb);
@@ -2585,7 +2585,7 @@
 	/* Post the IN urb */
 	result = submit_rx_urb(hw, GFP_KERNEL);
 	if (result != 0) {
-		printk(KERN_ERR
+		netdev_err(hw->wlandev->netdev,
 		       "Fatal, failed to submit RX URB, result=%d\n", result);
 		goto done;
 	}
@@ -2605,7 +2605,7 @@
 	result = result2 = hfa384x_cmd_initialize(hw);
 	if (result1 != 0) {
 		if (result2 != 0) {
-			printk(KERN_ERR
+			netdev_err(hw->wlandev->netdev,
 				"cmd_initialize() failed on two attempts, results %d and %d\n",
 				result1, result2);
 			usb_kill_urb(&hw->rx_urb);
@@ -2616,9 +2616,9 @@
 			pr_debug("but second attempt succeeded. All should be ok\n");
 		}
 	} else if (result2 != 0) {
-		printk(KERN_WARNING "First cmd_initialize() succeeded, but second attempt failed (result=%d)\n",
+		netdev_warn(hw->wlandev->netdev, "First cmd_initialize() succeeded, but second attempt failed (result=%d)\n",
 			result2);
-		printk(KERN_WARNING
+		netdev_warn(hw->wlandev->netdev,
 		       "Most likely the card will be functional\n");
 		goto done;
 	}
@@ -2709,7 +2709,7 @@
 	char *ptr;
 
 	if (hw->tx_urb.status == -EINPROGRESS) {
-		printk(KERN_WARNING "TX URB already in use\n");
+		netdev_warn(hw->wlandev->netdev, "TX URB already in use\n");
 		result = 3;
 		goto exit;
 	}
@@ -2784,7 +2784,7 @@
 	result = 1;
 	ret = submit_tx_urb(hw, &hw->tx_urb, GFP_ATOMIC);
 	if (ret != 0) {
-		printk(KERN_ERR "submit_tx_urb() failed, error=%d\n", ret);
+		netdev_err(hw->wlandev->netdev, "submit_tx_urb() failed, error=%d\n", ret);
 		result = 3;
 	}
 
@@ -3009,7 +3009,7 @@
 		break;
 
 	default:
-		printk(KERN_ERR "CTLX[%d] not in a terminating state(%s)\n",
+		netdev_err(hw->wlandev->netdev, "CTLX[%d] not in a terminating state(%s)\n",
 		       le16_to_cpu(ctlx->outbuf.type), ctlxstr(ctlx->state));
 		break;
 	}			/* switch */
@@ -3091,7 +3091,7 @@
 			 * this CTLX back in the "pending" queue
 			 * and schedule a reset ...
 			 */
-			printk(KERN_WARNING
+			netdev_warn(hw->wlandev->netdev,
 			       "%s tx pipe stalled: requesting reset\n",
 			       hw->wlandev->netdev->name);
 			list_move(&head->list, &hw->ctlxq.pending);
@@ -3101,12 +3101,12 @@
 		}
 
 		if (result == -ESHUTDOWN) {
-			printk(KERN_WARNING "%s urb shutdown!\n",
+			netdev_warn(hw->wlandev->netdev, "%s urb shutdown!\n",
 			       hw->wlandev->netdev->name);
 			break;
 		}
 
-		printk(KERN_ERR "Failed to submit CTLX[%d]: error=%d\n",
+		netdev_err(hw->wlandev->netdev, "Failed to submit CTLX[%d]: error=%d\n",
 		       le16_to_cpu(head->outbuf.type), result);
 		unlocked_usbctlx_complete(hw, head);
 	}			/* while */
@@ -3173,7 +3173,7 @@
 		break;
 
 	case -EPIPE:
-		printk(KERN_WARNING "%s rx pipe stalled: requesting reset\n",
+		netdev_warn(hw->wlandev->netdev, "%s rx pipe stalled: requesting reset\n",
 		       wlandev->netdev->name);
 		if (!test_and_set_bit(WORK_RX_HALT, &hw->usb_flags))
 			schedule_work(&hw->usb_work);
@@ -3224,7 +3224,7 @@
 		result = submit_rx_urb(hw, GFP_ATOMIC);
 
 		if (result != 0) {
-			printk(KERN_ERR
+			netdev_err(hw->wlandev->netdev,
 			       "Fatal, failed to resubmit rx_urb. error=%d\n",
 			       result);
 		}
@@ -3360,7 +3360,7 @@
 		 * Check that our message is what we're expecting ...
 		 */
 		if (ctlx->outbuf.type != intype) {
-			printk(KERN_WARNING
+			netdev_warn(hw->wlandev->netdev,
 			       "Expected IN[%d], received IN[%d] - ignored.\n",
 			       le16_to_cpu(ctlx->outbuf.type),
 			       le16_to_cpu(intype));
@@ -3396,7 +3396,7 @@
 			/*
 			 * Throw this CTLX away ...
 			 */
-			printk(KERN_ERR
+			netdev_err(hw->wlandev->netdev,
 			       "Matched IN URB, CTLX[%d] in invalid state(%s)."
 			       " Discarded.\n",
 			       le16_to_cpu(ctlx->outbuf.type),
@@ -3534,7 +3534,7 @@
 		break;
 
 	default:
-		printk(KERN_WARNING "Received frame on unsupported port=%d\n",
+		netdev_warn(hw->wlandev->netdev, "Received frame on unsupported port=%d\n",
 		       HFA384x_RXSTATUS_MACPORT_GET(usbin->rxfrm.desc.status));
 		goto done;
 		break;
@@ -3596,7 +3596,7 @@
 
 	skb = dev_alloc_skb(skblen);
 	if (skb == NULL) {
-		printk(KERN_ERR
+		netdev_err(hw->wlandev->netdev,
 		       "alloc_skb failed trying to allocate %d bytes\n",
 		       skblen);
 		return;
@@ -3714,7 +3714,7 @@
 		case -EPIPE:
 			{
 				hfa384x_t *hw = wlandev->priv;
-				printk(KERN_WARNING
+				netdev_warn(hw->wlandev->netdev,
 				       "%s tx pipe stalled: requesting reset\n",
 				       wlandev->netdev->name);
 				if (!test_and_set_bit
@@ -3747,7 +3747,7 @@
 			break;
 
 		default:
-			printk(KERN_INFO "unknown urb->status=%d\n",
+			netdev_info(wlandev->netdev, "unknown urb->status=%d\n",
 			       urb->status);
 			++(wlandev->linux_stats.tx_errors);
 			break;
@@ -3841,7 +3841,7 @@
 
 		default:
 			/* This is NOT a valid CTLX "success" state! */
-			printk(KERN_ERR
+			netdev_err(hw->wlandev->netdev,
 				"Illegal CTLX[%d] success state(%s, %d) in OUT URB\n",
 				le16_to_cpu(ctlx->outbuf.type),
 				ctlxstr(ctlx->state), urb->status);
@@ -3851,7 +3851,7 @@
 		/* If the pipe has stalled then we need to reset it */
 		if ((urb->status == -EPIPE) &&
 		    !test_and_set_bit(WORK_TX_HALT, &hw->usb_flags)) {
-			printk(KERN_WARNING
+			netdev_warn(hw->wlandev->netdev,
 			       "%s tx pipe stalled: requesting reset\n",
 			       hw->wlandev->netdev->name);
 			schedule_work(&hw->usb_work);
diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h
index 2fecca2..2e0bd24 100644
--- a/drivers/staging/wlan-ng/p80211netdev.h
+++ b/drivers/staging/wlan-ng/p80211netdev.h
@@ -138,7 +138,7 @@
 } p80211_frmrx_t;
 
 /* called by /proc/net/wireless */
-struct iw_statistics *p80211wext_get_wireless_stats(netdevice_t * dev);
+struct iw_statistics *p80211wext_get_wireless_stats(netdevice_t *dev);
 /* wireless extensions' ioctls */
 extern struct iw_handler_def p80211wext_handler_def;
 int p80211wext_event_associated(struct wlandevice *wlandev, int assoc);
diff --git a/drivers/staging/wlan-ng/p80211wep.c b/drivers/staging/wlan-ng/p80211wep.c
index 77e50a4..c4fabad 100644
--- a/drivers/staging/wlan-ng/p80211wep.c
+++ b/drivers/staging/wlan-ng/p80211wep.c
@@ -134,7 +134,7 @@
 		return -1;
 
 #ifdef WEP_DEBUG
-	printk(KERN_DEBUG "WEP key %d len %d = %*phC\n", keynum, keylen,
+	pr_debug("WEP key %d len %d = %*phC\n", keynum, keylen,
 			  8, key);
 #endif
 
@@ -182,7 +182,7 @@
 	keylen += 3;		/* add in IV bytes */
 
 #ifdef WEP_DEBUG
-	printk(KERN_DEBUG "D %d: %*ph (%d %d) %*phC\n", len, 3, key,
+	pr_debug("D %d: %*ph (%d %d) %*phC\n", len, 3, key,
 			  keyidx, keylen, 5, key + 3);
 #endif
 
@@ -259,7 +259,7 @@
 	keylen += 3;		/* add in IV bytes */
 
 #ifdef WEP_DEBUG
-	printk(KERN_DEBUG "E %d (%d/%d %d) %*ph %*phC\n", len,
+	pr_debug("E %d (%d/%d %d) %*ph %*phC\n", len,
 			  iv[3], keynum, keylen, 3, key, 5, key + 3);
 #endif
 
diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
index 3b3e17d..b3ff603 100644
--- a/drivers/staging/xgifb/XGI_main_26.c
+++ b/drivers/staging/xgifb/XGI_main_26.c
@@ -2070,7 +2070,6 @@
 	release_mem_region(xgifb_info->video_base, xgifb_info->video_size);
 	pci_disable_device(pdev);
 	framebuffer_release(fb_info);
-	pci_set_drvdata(pdev, NULL);
 }
 
 static struct pci_driver xgifb_driver = {
diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
index 46dea3f..400c726 100644
--- a/drivers/staging/xgifb/vb_setmode.c
+++ b/drivers/staging/xgifb/vb_setmode.c
@@ -845,11 +845,10 @@
 			VCLKIndex = TVCLKBASE_315_25 + HiTVVCLK;
 
 		if (pVBInfo->SetFlag & TVSimuMode) {
-			if (modeflag & Charx8Dot) {
+			if (modeflag & Charx8Dot)
 				VCLKIndex = TVCLKBASE_315_25 + HiTVSimuVCLK;
-			} else {
+			else
 				VCLKIndex = TVCLKBASE_315_25 + HiTVTextVCLK;
-			}
 		}
 
 		/* 301lv */
@@ -5274,9 +5273,8 @@
 
 	outb(0x00, pVBInfo->P3c8);
 
-	for (i = 0; i < 256 * 3; i++) {
+	for (i = 0; i < 256 * 3; i++)
 		outb(0x0F, (pVBInfo->P3c8 + 1)); /* DAC_TEST_PARMS */
-	}
 
 	mdelay(1);
 
@@ -5291,9 +5289,8 @@
 	/* avoid display something, set BLACK DAC if not restore DAC */
 	outb(0x00, pVBInfo->P3c8);
 
-	for (i = 0; i < 256 * 3; i++) {
+	for (i = 0; i < 256 * 3; i++)
 		outb(0, (pVBInfo->P3c8 + 1));
-	}
 
 	xgifb_reg_set(pVBInfo->P3c4, 0x01, SR01);
 	xgifb_reg_set(pVBInfo->P3d4, 0x63, CR63);
diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h
index 7168eed..f17e5b9 100644
--- a/drivers/staging/xgifb/vb_table.h
+++ b/drivers/staging/xgifb/vb_table.h
@@ -1284,7 +1284,7 @@
 	{0, 1048,   0, 771}, /* 04 (640x480x60Hz) */
 	{0, 1048,   0, 771}, /* 05 (800x600x60Hz) */
 	{0, 1048, 805, 770}  /* 06 (1024x768x60Hz) */
-} ;
+};
 
 static const struct SiS_LVDSData XGI_LVDS1024x768Des_2[] = {
 	{1142,  856, 622, 587}, /* 00 (320x200,320x400,640x200,640x400) */
diff --git a/drivers/staging/xillybus/Kconfig b/drivers/staging/xillybus/Kconfig
index 8a4181f..b15f778 100644
--- a/drivers/staging/xillybus/Kconfig
+++ b/drivers/staging/xillybus/Kconfig
@@ -16,14 +16,14 @@
 
 config XILLYBUS_PCIE
 	tristate "Xillybus over PCIe"
-	depends on XILLYBUS && PCI
+	depends on PCI
 	help
 	  Set to M if you want Xillybus to use PCI Express for communicating
 	  with the FPGA.
 
 config XILLYBUS_OF
 	tristate "Xillybus over Device Tree"
-	depends on XILLYBUS && OF_ADDRESS && OF_IRQ
+	depends on OF_ADDRESS && OF_IRQ
 	help
 	  Set to M if you want Xillybus to find its resources from the
 	  Open Firmware Flattened Device Tree. If the target is an embedded
diff --git a/drivers/staging/xillybus/xillybus_core.c b/drivers/staging/xillybus/xillybus_core.c
index 7db6f03..2ebaf16 100644
--- a/drivers/staging/xillybus/xillybus_core.c
+++ b/drivers/staging/xillybus/xillybus_core.c
@@ -101,7 +101,7 @@
  * wr_mutex -> rd_mutex -> register_mutex -> wr_spinlock -> rd_spinlock
  */
 
-static void malformed_message(u32 *buf)
+static void malformed_message(struct xilly_endpoint *endpoint, u32 *buf)
 {
 	int opcode;
 	int msg_channel, msg_bufno, msg_data, msg_dir;
@@ -112,9 +112,9 @@
 	msg_bufno = (buf[0] >> 12) & 0x3ff;
 	msg_data = buf[1] & 0xfffffff;
 
-	pr_warn("xillybus: Malformed message (skipping): "
-		"opcode=%d, channel=%03x, dir=%d, bufno=%03x, data=%07x\n",
-		opcode, msg_channel, msg_dir, msg_bufno, msg_data);
+	dev_warn(endpoint->dev,
+		 "Malformed message (skipping): opcode=%d, channel=%03x, dir=%d, bufno=%03x, data=%07x\n",
+		 opcode, msg_channel, msg_dir, msg_bufno, msg_data);
 }
 
 /*
@@ -152,16 +152,16 @@
 
 	for (i = 0; i < buf_size; i += 2)
 		if (((buf[i+1] >> 28) & 0xf) != ep->msg_counter) {
-			malformed_message(&buf[i]);
-			pr_warn("xillybus: Sending a NACK on "
-				"counter %x (instead of %x) on entry %d\n",
+			malformed_message(ep, &buf[i]);
+			dev_warn(ep->dev,
+				 "Sending a NACK on counter %x (instead of %x) on entry %d\n",
 				((buf[i+1] >> 28) & 0xf),
 				ep->msg_counter,
 				i/2);
 
 			if (++ep->failed_messages > 10)
-				pr_err("xillybus: Lost sync with "
-				       "interrupt messages. Stopping.\n");
+				dev_err(ep->dev,
+					"Lost sync with interrupt messages. Stopping.\n");
 			else {
 				ep->ephw->hw_sync_sgl_for_device(
 					ep,
@@ -177,7 +177,7 @@
 			break;
 
 	if (i >= buf_size) {
-		pr_err("xillybus: Bad interrupt message. Stopping.\n");
+		dev_err(ep->dev, "Bad interrupt message. Stopping.\n");
 		return IRQ_HANDLED;
 	}
 
@@ -196,7 +196,7 @@
 
 			if ((msg_channel > ep->num_channels) ||
 			    (msg_channel == 0)) {
-				malformed_message(&buf[i]);
+				malformed_message(ep, &buf[i]);
 				break;
 			}
 
@@ -204,7 +204,7 @@
 
 			if (msg_dir) { /* Write channel */
 				if (msg_bufno >= channel->num_wr_buffers) {
-					malformed_message(&buf[i]);
+					malformed_message(ep, &buf[i]);
 					break;
 				}
 				spin_lock(&channel->wr_spinlock);
@@ -221,7 +221,7 @@
 				/* Read channel */
 
 				if (msg_bufno >= channel->num_rd_buffers) {
-					malformed_message(&buf[i]);
+					malformed_message(ep, &buf[i]);
 					break;
 				}
 
@@ -243,14 +243,14 @@
 			if ((msg_channel > ep->num_channels) ||
 			    (msg_channel == 0) || (!msg_dir) ||
 			    !ep->channels[msg_channel]->wr_supports_nonempty) {
-				malformed_message(&buf[i]);
+				malformed_message(ep, &buf[i]);
 				break;
 			}
 
 			channel = ep->channels[msg_channel];
 
 			if (msg_bufno >= channel->num_wr_buffers) {
-				malformed_message(&buf[i]);
+				malformed_message(ep, &buf[i]);
 				break;
 			}
 			spin_lock(&channel->wr_spinlock);
@@ -283,16 +283,11 @@
 		case XILLYMSG_OPCODE_FATAL_ERROR:
 			ep->fatal_error = 1;
 			wake_up_interruptible(&ep->ep_wait); /* For select() */
-			pr_err("xillybus: FPGA reported a fatal "
-			       "error. This means that the low-level "
-			       "communication with the device has failed. "
-			       "This hardware problem is most likely "
-			       "unrelated to xillybus (neither kernel "
-			       "module nor FPGA core), but reports are "
-			       "still welcome. All I/O is aborted.\n");
+			dev_err(ep->dev,
+				"FPGA reported a fatal error. This means that the low-level communication with the device has failed. This hardware problem is most likely unrelated to Xillybus (neither kernel module nor FPGA core), but reports are still welcome. All I/O is aborted.\n");
 			break;
 		default:
-			malformed_message(&buf[i]);
+			malformed_message(ep, &buf[i]);
 			break;
 		}
 	}
@@ -486,8 +481,8 @@
 
 		if ((channelnum > ep->num_channels) ||
 		    ((channelnum == 0) && !is_writebuf)) {
-			pr_err("xillybus: IDT requests channel out "
-			       "of range. Aborting.\n");
+			dev_err(ep->dev,
+				"IDT requests channel out of range. Aborting.\n");
 			return -ENODEV;
 		}
 
@@ -565,9 +560,8 @@
 				 */
 				if ((left_of_wr_salami < bytebufsize) &&
 				    (left_of_wr_salami > 0)) {
-					pr_err("xillybus: "
-					       "Corrupt buffer allocation "
-					       "in IDT. Aborting.\n");
+					dev_err(ep->dev,
+						"Corrupt buffer allocation in IDT. Aborting.\n");
 					return -ENODEV;
 				}
 
@@ -644,9 +638,8 @@
 				 */
 				if ((left_of_rd_salami < bytebufsize) &&
 				    (left_of_rd_salami > 0)) {
-					pr_err("xillybus: "
-					       "Corrupt buffer allocation "
-					       "in IDT. Aborting.\n");
+					dev_err(ep->dev,
+						"Corrupt buffer allocation in IDT. Aborting.\n");
 					return -ENODEV;
 				}
 
@@ -706,19 +699,19 @@
 	}
 
 	if (!msg_buf_done) {
-		pr_err("xillybus: Corrupt IDT: No message buffer. "
-		       "Aborting.\n");
+		dev_err(ep->dev,
+			"Corrupt IDT: No message buffer. Aborting.\n");
 		return -ENODEV;
 	}
 
 	return 0;
 
 memfail:
-	pr_err("xillybus: Failed to allocate write buffer memory. "
-	       "Aborting.\n");
+	dev_err(ep->dev,
+		"Failed to allocate write buffer memory. Aborting.\n");
 	return -ENOMEM;
 dmafail:
-	pr_err("xillybus: Failed to map DMA memory!. Aborting.\n");
+	dev_err(ep->dev, "Failed to map DMA memory!. Aborting.\n");
 	return -ENOMEM;
 }
 
@@ -745,8 +738,8 @@
 	scan++;
 
 	if (scan > end_of_idt) {
-		pr_err("xillybus: IDT device name list overflow. "
-		       "Aborting.\n");
+		dev_err(endpoint->dev,
+			"IDT device name list overflow. Aborting.\n");
 		idt_handle->chandesc = NULL;
 		return;
 	} else
@@ -757,8 +750,8 @@
 	if (len & 0x03) {
 		idt_handle->chandesc = NULL;
 
-		pr_err("xillybus: Corrupt IDT device name list. "
-		       "Aborting.\n");
+		dev_err(endpoint->dev,
+			"Corrupt IDT device name list. Aborting.\n");
 	}
 
 	idt_handle->entries = len >> 2;
@@ -787,7 +780,7 @@
 					 XILLY_TIMEOUT);
 
 	if (channel->wr_sleepy) {
-		pr_err("xillybus: Failed to obtain IDT. Aborting.\n");
+		dev_err(endpoint->dev, "Failed to obtain IDT. Aborting.\n");
 
 		if (endpoint->fatal_error)
 			return -EIO;
@@ -803,8 +796,8 @@
 		DMA_FROM_DEVICE);
 
 	if (channel->wr_buffers[0]->end_offset != endpoint->idtlen) {
-		pr_err("xillybus: IDT length mismatch (%d != %d). "
-		       "Aborting.\n",
+		dev_err(endpoint->dev,
+			"IDT length mismatch (%d != %d). Aborting.\n",
 		       channel->wr_buffers[0]->end_offset, endpoint->idtlen);
 		rc = -ENODEV;
 		return rc;
@@ -812,7 +805,7 @@
 
 	if (crc32_le(~0, channel->wr_buffers[0]->addr,
 		     endpoint->idtlen+1) != 0) {
-		pr_err("xillybus: IDT failed CRC check. Aborting.\n");
+		dev_err(endpoint->dev, "IDT failed CRC check. Aborting.\n");
 		rc = -ENODEV;
 		return rc;
 	}
@@ -821,9 +814,8 @@
 
 	/* Check version number. Accept anything below 0x82 for now. */
 	if (*version > 0x82) {
-		pr_err("xillybus: No support for IDT version 0x%02x. "
-		       "Maybe the xillybus driver needs an upgarde. "
-		       "Aborting.\n",
+		dev_err(endpoint->dev,
+			"No support for IDT version 0x%02x. Maybe the xillybus driver needs an upgarde. Aborting.\n",
 		       (int) *version);
 		rc = -ENODEV;
 		return rc;
@@ -1312,9 +1304,8 @@
 				 channel->rd_wait,
 				 (!channel->rd_full),
 				 timeout) == 0) {
-			pr_warn("xillybus: "
-				"Timed out while flushing. "
-				"Output data may be lost.\n");
+			dev_warn(channel->endpoint->dev,
+				"Timed out while flushing. Output data may be lost.\n");
 
 			rc = -ETIMEDOUT;
 			break;
@@ -1354,12 +1345,11 @@
 	rc = xillybus_myflush(channel, -1);
 
 	if (rc == -EINTR)
-		pr_warn("xillybus: Autoflush failed because "
-			"work queue thread got a signal.\n");
+		dev_warn(channel->endpoint->dev,
+			 "Autoflush failed because work queue thread got a signal.\n");
 	else if (rc)
-		pr_err("xillybus: Autoflush failed under "
-		       "weird circumstances.\n");
-
+		dev_err(channel->endpoint->dev,
+			"Autoflush failed under weird circumstances.\n");
 }
 
 static ssize_t xillybus_write(struct file *filp, const char __user *userbuf,
@@ -1615,8 +1605,8 @@
 	mutex_unlock(&ep_list_lock);
 
 	if (!endpoint) {
-		pr_err("xillybus: open() failed to find a device "
-		       "for major=%d and minor=%d\n", major, minor);
+		pr_err("xillybus: open() failed to find a device for major=%d and minor=%d\n",
+		       major, minor);
 		return -ENODEV;
 	}
 
@@ -1642,15 +1632,15 @@
 	if ((filp->f_mode & FMODE_READ) && (filp->f_flags & O_NONBLOCK) &&
 	    (channel->wr_synchronous || !channel->wr_allow_partial ||
 	     !channel->wr_supports_nonempty)) {
-		pr_err("xillybus: open() failed: "
-		       "O_NONBLOCK not allowed for read on this device\n");
+		dev_err(endpoint->dev,
+			"open() failed: O_NONBLOCK not allowed for read on this device\n");
 		return -ENODEV;
 	}
 
 	if ((filp->f_mode & FMODE_WRITE) && (filp->f_flags & O_NONBLOCK) &&
 	    (channel->rd_synchronous || !channel->rd_allow_partial)) {
-		pr_err("xillybus: open() failed: "
-		       "O_NONBLOCK not allowed for write on this device\n");
+		dev_err(endpoint->dev,
+			"open() failed: O_NONBLOCK not allowed for write on this device\n");
 		return -ENODEV;
 	}
 
@@ -1765,8 +1755,8 @@
 		rc = mutex_lock_interruptible(&channel->rd_mutex);
 
 		if (rc) {
-			pr_warn("xillybus: Failed to close file. "
-				"Hardware left in messy state.\n");
+			dev_warn(channel->endpoint->dev,
+				 "Failed to close file. Hardware left in messy state.\n");
 			return rc;
 		}
 
@@ -1791,8 +1781,8 @@
 	if (filp->f_mode & FMODE_READ) {
 		rc = mutex_lock_interruptible(&channel->wr_mutex);
 		if (rc) {
-			pr_warn("xillybus: Failed to close file. "
-				"Hardware left in messy state.\n");
+			dev_warn(channel->endpoint->dev,
+				 "Failed to close file. Hardware left in messy state.\n");
 			return rc;
 		}
 
@@ -1853,10 +1843,8 @@
 
 				if (channel->wr_sleepy) {
 					mutex_unlock(&channel->wr_mutex);
-					pr_warn("xillybus: Hardware failed to "
-						"respond to close command, "
-						"therefore left in "
-						"messy state.\n");
+					dev_warn(channel->endpoint->dev,
+						 "Hardware failed to respond to close command, therefore left in messy state.\n");
 					return -EINTR;
 				}
 			}
@@ -2022,7 +2010,7 @@
 				 xillyname);
 
 	if (rc) {
-		pr_warn("xillybus: Failed to obtain major/minors");
+		dev_warn(endpoint->dev, "Failed to obtain major/minors");
 		goto error1;
 	}
 
@@ -2034,7 +2022,7 @@
 	rc = cdev_add(&endpoint->cdev, MKDEV(major, minor),
 		      endpoint->num_channels);
 	if (rc) {
-		pr_warn("xillybus: Failed to add cdev. Aborting.\n");
+		dev_warn(endpoint->dev, "Failed to add cdev. Aborting.\n");
 		goto error2;
 	}
 
@@ -2057,14 +2045,15 @@
 				       "%s", devname);
 
 		if (IS_ERR(device)) {
-			pr_warn("xillybus: Failed to create %s "
-				"device. Aborting.\n", devname);
+			dev_warn(endpoint->dev,
+				 "Failed to create %s device. Aborting.\n",
+				 devname);
 			goto error3;
 		}
 	}
 
-	pr_info("xillybus: Created %d device files.\n",
-		endpoint->num_channels);
+	dev_info(endpoint->dev, "Created %d device files.\n",
+		 endpoint->num_channels);
 	return 0; /* succeed */
 
 error3:
@@ -2093,8 +2082,8 @@
 				       endpoint->lowest_minor),
 				 endpoint->num_channels);
 
-	pr_info("xillybus: Removed %d device files.\n",
-		endpoint->num_channels);
+	dev_info(endpoint->dev, "Removed %d device files.\n",
+		 endpoint->num_channels);
 }
 
 
@@ -2107,7 +2096,7 @@
 
 	endpoint = kzalloc(sizeof(*endpoint), GFP_KERNEL);
 	if (!endpoint) {
-		pr_err("xillybus: Failed to allocate memory. Aborting.\n");
+		dev_err(dev, "Failed to allocate memory. Aborting.\n");
 		return NULL;
 	}
 
@@ -2141,8 +2130,8 @@
 					 XILLY_TIMEOUT);
 
 	if (endpoint->idtlen < 0) {
-		pr_err("xillybus: Failed to quiesce the device on "
-		       "exit. Quitting while leaving a mess.\n");
+		dev_err(endpoint->dev,
+			"Failed to quiesce the device on exit. Quitting while leaving a mess.\n");
 		return -ENODEV;
 	}
 	return 0; /* Success */
@@ -2209,7 +2198,7 @@
 					 XILLY_TIMEOUT);
 
 	if (endpoint->idtlen < 0) {
-		pr_err("xillybus: No response from FPGA. Aborting.\n");
+		dev_err(endpoint->dev, "No response from FPGA. Aborting.\n");
 		rc = -ENODEV;
 		goto failed_quiesce;
 	}
@@ -2323,7 +2312,7 @@
 	xillybus_class = class_create(THIS_MODULE, xillyname);
 	if (IS_ERR(xillybus_class)) {
 		rc = PTR_ERR(xillybus_class);
-		pr_warn("xillybus: Failed to register class xillybus\n");
+		pr_warn("Failed to register class xillybus\n");
 
 		return rc;
 	}
diff --git a/drivers/staging/xillybus/xillybus_of.c b/drivers/staging/xillybus/xillybus_of.c
index 92c2931..394bfea 100644
--- a/drivers/staging/xillybus/xillybus_of.c
+++ b/drivers/staging/xillybus/xillybus_of.c
@@ -117,14 +117,15 @@
 
 	rc = of_address_to_resource(dev->of_node, 0, &endpoint->res);
 	if (rc) {
-		pr_warn("xillybus: Failed to obtain device tree "
-			"resource\n");
+		dev_warn(endpoint->dev,
+			 "Failed to obtain device tree resource\n");
 		goto failed_request_regions;
 	}
 
 	if  (!request_mem_region(endpoint->res.start,
 				 resource_size(&endpoint->res), xillyname)) {
-		pr_err("xillybus: request_mem_region failed. Aborting.\n");
+		dev_err(endpoint->dev,
+			"request_mem_region failed. Aborting.\n");
 		rc = -EBUSY;
 		goto failed_request_regions;
 	}
@@ -132,7 +133,8 @@
 	endpoint->registers = of_iomap(dev->of_node, 0);
 
 	if (!endpoint->registers) {
-		pr_err("xillybus: Failed to map I/O memory. Aborting.\n");
+		dev_err(endpoint->dev,
+			"Failed to map I/O memory. Aborting.\n");
 		goto failed_iomap0;
 	}
 
@@ -141,8 +143,8 @@
 	rc = request_irq(irq, xillybus_isr, 0, xillyname, endpoint);
 
 	if (rc) {
-		pr_err("xillybus: Failed to register IRQ handler. "
-		       "Aborting.\n");
+		dev_err(endpoint->dev,
+			"Failed to register IRQ handler. Aborting.\n");
 		rc = -ENODEV;
 		goto failed_register_irq;
 	}
@@ -198,15 +200,4 @@
 	},
 };
 
-static int __init xillybus_of_init(void)
-{
-	return platform_driver_register(&xillybus_platform_driver);
-}
-
-static void __exit xillybus_of_exit(void)
-{
-	platform_driver_unregister(&xillybus_platform_driver);
-}
-
-module_init(xillybus_of_init);
-module_exit(xillybus_of_exit);
+module_platform_driver(xillybus_platform_driver);
diff --git a/drivers/staging/xillybus/xillybus_pcie.c b/drivers/staging/xillybus/xillybus_pcie.c
index 6701365..1811aa7 100644
--- a/drivers/staging/xillybus/xillybus_pcie.c
+++ b/drivers/staging/xillybus/xillybus_pcie.c
@@ -134,7 +134,7 @@
 	struct xilly_endpoint *endpoint;
 	int rc = 0;
 
-	endpoint = xillybus_init_endpoint(pdev, NULL, &pci_hw);
+	endpoint = xillybus_init_endpoint(pdev, &pdev->dev, &pci_hw);
 
 	if (!endpoint)
 		return -ENOMEM;
@@ -148,29 +148,29 @@
 	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S);
 
 	if (rc) {
-		pr_err("xillybus: pci_enable_device() failed. "
-		       "Aborting.\n");
+		dev_err(endpoint->dev,
+			"pci_enable_device() failed. Aborting.\n");
 		goto no_enable;
 	}
 
 	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
-		pr_err("xillybus: Incorrect BAR configuration. "
-		       "Aborting.\n");
+		dev_err(endpoint->dev,
+			"Incorrect BAR configuration. Aborting.\n");
 		rc = -ENODEV;
 		goto bad_bar;
 	}
 
 	rc = pci_request_regions(pdev, xillyname);
 	if (rc) {
-		pr_err("xillybus: pci_request_regions() failed. "
-		       "Aborting.\n");
+		dev_err(endpoint->dev,
+			"pci_request_regions() failed. Aborting.\n");
 		goto failed_request_regions;
 	}
 
 	endpoint->registers = pci_iomap(pdev, 0, 128);
 
 	if (!endpoint->registers) {
-		pr_err("xillybus: Failed to map BAR 0. Aborting.\n");
+		dev_err(endpoint->dev, "Failed to map BAR 0. Aborting.\n");
 		goto failed_iomap0;
 	}
 
@@ -178,16 +178,16 @@
 
 	/* Set up a single MSI interrupt */
 	if (pci_enable_msi(pdev)) {
-		pr_err("xillybus: Failed to enable MSI interrupts. "
-		       "Aborting.\n");
+		dev_err(endpoint->dev,
+			"Failed to enable MSI interrupts. Aborting.\n");
 		rc = -ENODEV;
 		goto failed_enable_msi;
 	}
 	rc = request_irq(pdev->irq, xillybus_isr, 0, xillyname, endpoint);
 
 	if (rc) {
-		pr_err("xillybus: Failed to register MSI handler. "
-		       "Aborting.\n");
+		dev_err(endpoint->dev,
+			"Failed to register MSI handler. Aborting.\n");
 		rc = -ENODEV;
 		goto failed_register_msi;
 	}
@@ -202,8 +202,7 @@
 	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))
 		endpoint->dma_using_dac = 0;
 	else {
-		pr_err("xillybus: Failed to set DMA mask. "
-		       "Aborting.\n");
+		dev_err(endpoint->dev, "Failed to set DMA mask. Aborting.\n");
 		rc = -ENODEV;
 		goto failed_dmamask;
 	}
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c
index 2c4ed52..79ce363 100644
--- a/drivers/staging/zram/zram_drv.c
+++ b/drivers/staging/zram/zram_drv.c
@@ -648,6 +648,9 @@
 	zram = dev_to_zram(dev);
 	bdev = bdget_disk(zram->disk, 0);
 
+	if (!bdev)
+		return -ENOMEM;
+
 	/* Do not reset an active device! */
 	if (bdev->bd_holders)
 		return -EBUSY;
@@ -660,8 +663,7 @@
 		return -EINVAL;
 
 	/* Make sure all pending I/O is finished */
-	if (bdev)
-		fsync_bdev(bdev);
+	fsync_bdev(bdev);
 
 	zram_reset_device(zram, true);
 	return len;
@@ -896,13 +898,10 @@
 	sysfs_remove_group(&disk_to_dev(zram->disk)->kobj,
 			&zram_disk_attr_group);
 
-	if (zram->disk) {
-		del_gendisk(zram->disk);
-		put_disk(zram->disk);
-	}
+	del_gendisk(zram->disk);
+	put_disk(zram->disk);
 
-	if (zram->queue)
-		blk_cleanup_queue(zram->queue);
+	blk_cleanup_queue(zram->queue);
 }
 
 static int __init zram_init(void)
diff --git a/drivers/staging/zsmalloc/Kconfig b/drivers/staging/zsmalloc/Kconfig
index 7fab032..0ae13cd 100644
--- a/drivers/staging/zsmalloc/Kconfig
+++ b/drivers/staging/zsmalloc/Kconfig
@@ -1,5 +1,6 @@
 config ZSMALLOC
 	bool "Memory allocator for compressed pages"
+	depends on MMU
 	default n
 	help
 	  zsmalloc is a slab-based memory allocator designed to store
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index 551c96c..0f199f6 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -134,10 +134,10 @@
 	 * pSCSI Host ID and enable for phba mode
 	 */
 	sh = scsi_host_lookup(phv->phv_host_id);
-	if (IS_ERR(sh)) {
+	if (!sh) {
 		pr_err("pSCSI: Unable to locate SCSI Host for"
 			" phv_host_id: %d\n", phv->phv_host_id);
-		return PTR_ERR(sh);
+		return -EINVAL;
 	}
 
 	phv->phv_lld_host = sh;
@@ -515,10 +515,10 @@
 			sh = phv->phv_lld_host;
 		} else {
 			sh = scsi_host_lookup(pdv->pdv_host_id);
-			if (IS_ERR(sh)) {
+			if (!sh) {
 				pr_err("pSCSI: Unable to locate"
 					" pdv_host_id: %d\n", pdv->pdv_host_id);
-				return PTR_ERR(sh);
+				return -EINVAL;
 			}
 		}
 	} else {
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index 4714c6f..d9b92b2 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -263,6 +263,11 @@
 			sectors, cmd->se_dev->dev_attrib.max_write_same_len);
 		return TCM_INVALID_CDB_FIELD;
 	}
+	/* We always have ANC_SUP == 0 so setting ANCHOR is always an error */
+	if (flags[0] & 0x10) {
+		pr_warn("WRITE SAME with ANCHOR not supported\n");
+		return TCM_INVALID_CDB_FIELD;
+	}
 	/*
 	 * Special case for WRITE_SAME w/ UNMAP=1 that ends up getting
 	 * translated into block discard requests within backend code.
diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c
index 3da4fd1..474cd44 100644
--- a/drivers/target/target_core_xcopy.c
+++ b/drivers/target/target_core_xcopy.c
@@ -82,6 +82,9 @@
 	mutex_lock(&g_device_mutex);
 	list_for_each_entry(se_dev, &g_device_list, g_dev_node) {
 
+		if (!se_dev->dev_attrib.emulate_3pc)
+			continue;
+
 		memset(&tmp_dev_wwn[0], 0, XCOPY_NAA_IEEE_REGEX_LEN);
 		target_xcopy_gen_naa_ieee(se_dev, &tmp_dev_wwn[0]);
 
@@ -357,6 +360,7 @@
 	struct se_cmd se_cmd;
 	struct xcopy_op *xcopy_op;
 	struct completion xpt_passthrough_sem;
+	unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER];
 };
 
 static struct se_port xcopy_pt_port;
@@ -675,7 +679,8 @@
 
 	pr_debug("target_xcopy_issue_pt_cmd(): SCSI status: 0x%02x\n",
 			se_cmd->scsi_status);
-	return 0;
+
+	return (se_cmd->scsi_status) ? -EINVAL : 0;
 }
 
 static int target_xcopy_read_source(
@@ -708,7 +713,7 @@
 		(unsigned long long)src_lba, src_sectors, length);
 
 	transport_init_se_cmd(se_cmd, &xcopy_pt_tfo, NULL, length,
-				DMA_FROM_DEVICE, 0, NULL);
+			      DMA_FROM_DEVICE, 0, &xpt_cmd->sense_buffer[0]);
 	xop->src_pt_cmd = xpt_cmd;
 
 	rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, src_dev, &cdb[0],
@@ -768,7 +773,7 @@
 		(unsigned long long)dst_lba, dst_sectors, length);
 
 	transport_init_se_cmd(se_cmd, &xcopy_pt_tfo, NULL, length,
-				DMA_TO_DEVICE, 0, NULL);
+			      DMA_TO_DEVICE, 0, &xpt_cmd->sense_buffer[0]);
 	xop->dst_pt_cmd = xpt_cmd;
 
 	rc = target_xcopy_setup_pt_cmd(xpt_cmd, xop, dst_dev, &cdb[0],
@@ -884,30 +889,42 @@
 
 sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
 {
+	struct se_device *dev = se_cmd->se_dev;
 	struct xcopy_op *xop = NULL;
 	unsigned char *p = NULL, *seg_desc;
 	unsigned int list_id, list_id_usage, sdll, inline_dl, sa;
+	sense_reason_t ret = TCM_INVALID_PARAMETER_LIST;
 	int rc;
 	unsigned short tdll;
 
+	if (!dev->dev_attrib.emulate_3pc) {
+		pr_err("EXTENDED_COPY operation explicitly disabled\n");
+		return TCM_UNSUPPORTED_SCSI_OPCODE;
+	}
+
 	sa = se_cmd->t_task_cdb[1] & 0x1f;
 	if (sa != 0x00) {
 		pr_err("EXTENDED_COPY(LID4) not supported\n");
 		return TCM_UNSUPPORTED_SCSI_OPCODE;
 	}
 
+	xop = kzalloc(sizeof(struct xcopy_op), GFP_KERNEL);
+	if (!xop) {
+		pr_err("Unable to allocate xcopy_op\n");
+		return TCM_OUT_OF_RESOURCES;
+	}
+	xop->xop_se_cmd = se_cmd;
+
 	p = transport_kmap_data_sg(se_cmd);
 	if (!p) {
 		pr_err("transport_kmap_data_sg() failed in target_do_xcopy\n");
+		kfree(xop);
 		return TCM_OUT_OF_RESOURCES;
 	}
 
 	list_id = p[0];
-	if (list_id != 0x00) {
-		pr_err("XCOPY with non zero list_id: 0x%02x\n", list_id);
-		goto out;
-	}
-	list_id_usage = (p[1] & 0x18);
+	list_id_usage = (p[1] & 0x18) >> 3;
+
 	/*
 	 * Determine TARGET DESCRIPTOR LIST LENGTH + SEGMENT DESCRIPTOR LIST LENGTH
 	 */
@@ -920,13 +937,6 @@
 		goto out;
 	}
 
-	xop = kzalloc(sizeof(struct xcopy_op), GFP_KERNEL);
-	if (!xop) {
-		pr_err("Unable to allocate xcopy_op\n");
-		goto out;
-	}
-	xop->xop_se_cmd = se_cmd;
-
 	pr_debug("Processing XCOPY with list_id: 0x%02x list_id_usage: 0x%02x"
 		" tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage,
 		tdll, sdll, inline_dl);
@@ -935,6 +945,17 @@
 	if (rc <= 0)
 		goto out;
 
+	if (xop->src_dev->dev_attrib.block_size !=
+	    xop->dst_dev->dev_attrib.block_size) {
+		pr_err("XCOPY: Non matching src_dev block_size: %u + dst_dev"
+		       " block_size: %u currently unsupported\n",
+			xop->src_dev->dev_attrib.block_size,
+			xop->dst_dev->dev_attrib.block_size);
+		xcopy_pt_undepend_remotedev(xop);
+		ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+		goto out;
+	}
+
 	pr_debug("XCOPY: Processed %d target descriptors, length: %u\n", rc,
 				rc * XCOPY_TARGET_DESC_LEN);
 	seg_desc = &p[16];
@@ -957,7 +978,7 @@
 	if (p)
 		transport_kunmap_data_sg(se_cmd);
 	kfree(xop);
-	return TCM_INVALID_CDB_FIELD;
+	return ret;
 }
 
 static sense_reason_t target_rcr_operating_parameters(struct se_cmd *se_cmd)
diff --git a/drivers/thermal/samsung/exynos_thermal_common.c b/drivers/thermal/samsung/exynos_thermal_common.c
index f10a6ad..c2301da 100644
--- a/drivers/thermal/samsung/exynos_thermal_common.c
+++ b/drivers/thermal/samsung/exynos_thermal_common.c
@@ -310,8 +310,6 @@
 	}
 
 	th_zone = conf->pzone_data;
-	if (th_zone->therm_dev)
-		return;
 
 	if (th_zone->bind == false) {
 		for (i = 0; i < th_zone->cool_dev_size; i++) {
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index b43afda..32f38b9 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -317,6 +317,9 @@
 
 	con = readl(data->base + reg->tmu_ctrl);
 
+	if (pdata->test_mux)
+		con |= (pdata->test_mux << reg->test_mux_addr_shift);
+
 	if (pdata->reference_voltage) {
 		con &= ~(reg->buf_vref_sel_mask << reg->buf_vref_sel_shift);
 		con |= pdata->reference_voltage << reg->buf_vref_sel_shift;
@@ -488,7 +491,7 @@
 	},
 	{
 		.compatible = "samsung,exynos4412-tmu",
-		.data = (void *)EXYNOS5250_TMU_DRV_DATA,
+		.data = (void *)EXYNOS4412_TMU_DRV_DATA,
 	},
 	{
 		.compatible = "samsung,exynos5250-tmu",
@@ -629,9 +632,10 @@
 	if (ret)
 		return ret;
 
-	if (pdata->type == SOC_ARCH_EXYNOS ||
-		pdata->type == SOC_ARCH_EXYNOS4210 ||
-				pdata->type == SOC_ARCH_EXYNOS5440)
+	if (pdata->type == SOC_ARCH_EXYNOS4210 ||
+	    pdata->type == SOC_ARCH_EXYNOS4412 ||
+	    pdata->type == SOC_ARCH_EXYNOS5250 ||
+	    pdata->type == SOC_ARCH_EXYNOS5440)
 		data->soc = pdata->type;
 	else {
 		ret = -EINVAL;
diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
index b364c9e..3fb6554 100644
--- a/drivers/thermal/samsung/exynos_tmu.h
+++ b/drivers/thermal/samsung/exynos_tmu.h
@@ -41,7 +41,8 @@
 
 enum soc_type {
 	SOC_ARCH_EXYNOS4210 = 1,
-	SOC_ARCH_EXYNOS,
+	SOC_ARCH_EXYNOS4412,
+	SOC_ARCH_EXYNOS5250,
 	SOC_ARCH_EXYNOS5440,
 };
 
@@ -84,6 +85,7 @@
  * @triminfo_reload_shift: shift of triminfo reload enable bit in triminfo_ctrl
 	reg.
  * @tmu_ctrl: TMU main controller register.
+ * @test_mux_addr_shift: shift bits of test mux address.
  * @buf_vref_sel_shift: shift bits of reference voltage in tmu_ctrl register.
  * @buf_vref_sel_mask: mask bits of reference voltage in tmu_ctrl register.
  * @therm_trip_mode_shift: shift bits of tripping mode in tmu_ctrl register.
@@ -150,6 +152,7 @@
 	u32	triminfo_reload_shift;
 
 	u32	tmu_ctrl;
+	u32     test_mux_addr_shift;
 	u32	buf_vref_sel_shift;
 	u32	buf_vref_sel_mask;
 	u32	therm_trip_mode_shift;
@@ -257,6 +260,7 @@
  * @first_point_trim: temp value of the first point trimming
  * @second_point_trim: temp value of the second point trimming
  * @default_temp_offset: default temperature offset in case of no trimming
+ * @test_mux; information if SoC supports test MUX
  * @cal_type: calibration type for temperature
  * @cal_mode: calibration mode for temperature
  * @freq_clip_table: Table representing frequency reduction percentage.
@@ -286,6 +290,7 @@
 	u8 first_point_trim;
 	u8 second_point_trim;
 	u8 default_temp_offset;
+	u8 test_mux;
 
 	enum calibration_type cal_type;
 	enum calibration_mode cal_mode;
diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
index 9002499..073c292 100644
--- a/drivers/thermal/samsung/exynos_tmu_data.c
+++ b/drivers/thermal/samsung/exynos_tmu_data.c
@@ -90,14 +90,15 @@
 };
 #endif
 
-#if defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412)
-static const struct exynos_tmu_registers exynos5250_tmu_registers = {
+#if defined(CONFIG_SOC_EXYNOS4412) || defined(CONFIG_SOC_EXYNOS5250)
+static const struct exynos_tmu_registers exynos4412_tmu_registers = {
 	.triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
 	.triminfo_25_shift = EXYNOS_TRIMINFO_25_SHIFT,
 	.triminfo_85_shift = EXYNOS_TRIMINFO_85_SHIFT,
 	.triminfo_ctrl = EXYNOS_TMU_TRIMINFO_CON,
 	.triminfo_reload_shift = EXYNOS_TRIMINFO_RELOAD_SHIFT,
 	.tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
+	.test_mux_addr_shift = EXYNOS4412_MUX_ADDR_SHIFT,
 	.buf_vref_sel_shift = EXYNOS_TMU_REF_VOLTAGE_SHIFT,
 	.buf_vref_sel_mask = EXYNOS_TMU_REF_VOLTAGE_MASK,
 	.therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
@@ -128,7 +129,7 @@
 	.emul_time_mask = EXYNOS_EMUL_TIME_MASK,
 };
 
-#define EXYNOS5250_TMU_DATA \
+#define EXYNOS4412_TMU_DATA \
 	.threshold_falling = 10, \
 	.trigger_levels[0] = 85, \
 	.trigger_levels[1] = 103, \
@@ -162,15 +163,32 @@
 		.temp_level = 103, \
 	}, \
 	.freq_tab_count = 2, \
-	.type = SOC_ARCH_EXYNOS, \
-	.registers = &exynos5250_tmu_registers, \
+	.registers = &exynos4412_tmu_registers, \
 	.features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_TRIM_RELOAD | \
 			TMU_SUPPORT_FALLING_TRIP | TMU_SUPPORT_READY_STATUS | \
 			TMU_SUPPORT_EMUL_TIME)
+#endif
 
+#if defined(CONFIG_SOC_EXYNOS4412)
+struct exynos_tmu_init_data const exynos4412_default_tmu_data = {
+	.tmu_data = {
+		{
+			EXYNOS4412_TMU_DATA,
+			.type = SOC_ARCH_EXYNOS4412,
+			.test_mux = EXYNOS4412_MUX_ADDR_VALUE,
+		},
+	},
+	.tmu_count = 1,
+};
+#endif
+
+#if defined(CONFIG_SOC_EXYNOS5250)
 struct exynos_tmu_init_data const exynos5250_default_tmu_data = {
 	.tmu_data = {
-		{ EXYNOS5250_TMU_DATA },
+		{
+			EXYNOS4412_TMU_DATA,
+			.type = SOC_ARCH_EXYNOS5250,
+		},
 	},
 	.tmu_count = 1,
 };
diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
index dc7feb5..a1ea19d 100644
--- a/drivers/thermal/samsung/exynos_tmu_data.h
+++ b/drivers/thermal/samsung/exynos_tmu_data.h
@@ -95,6 +95,10 @@
 
 #define EXYNOS_MAX_TRIGGER_PER_REG	4
 
+/* Exynos4412 specific */
+#define EXYNOS4412_MUX_ADDR_VALUE          6
+#define EXYNOS4412_MUX_ADDR_SHIFT          20
+
 /*exynos5440 specific registers*/
 #define EXYNOS5440_TMU_S0_7_TRIM		0x000
 #define EXYNOS5440_TMU_S0_7_CTRL		0x020
@@ -138,7 +142,14 @@
 #define EXYNOS4210_TMU_DRV_DATA (NULL)
 #endif
 
-#if (defined(CONFIG_SOC_EXYNOS5250) || defined(CONFIG_SOC_EXYNOS4412))
+#if defined(CONFIG_SOC_EXYNOS4412)
+extern struct exynos_tmu_init_data const exynos4412_default_tmu_data;
+#define EXYNOS4412_TMU_DRV_DATA (&exynos4412_default_tmu_data)
+#else
+#define EXYNOS4412_TMU_DRV_DATA (NULL)
+#endif
+
+#if defined(CONFIG_SOC_EXYNOS5250)
 extern struct exynos_tmu_init_data const exynos5250_default_tmu_data;
 #define EXYNOS5250_TMU_DRV_DATA (&exynos5250_default_tmu_data)
 #else
diff --git a/drivers/thermal/thermal_hwmon.c b/drivers/thermal/thermal_hwmon.c
index eeef0e2..fdb0719 100644
--- a/drivers/thermal/thermal_hwmon.c
+++ b/drivers/thermal/thermal_hwmon.c
@@ -159,7 +159,7 @@
 
 	INIT_LIST_HEAD(&hwmon->tz_list);
 	strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH);
-	hwmon->device = hwmon_device_register(&tz->device);
+	hwmon->device = hwmon_device_register(NULL);
 	if (IS_ERR(hwmon->device)) {
 		result = PTR_ERR(hwmon->device);
 		goto free_mem;
diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
index 4f8b9af..5a47cc8 100644
--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
@@ -110,6 +110,7 @@
 		} else {
 			dev_err(bgp->dev,
 				"Failed to read PCB state. Using defaults\n");
+			ret = 0;
 		}
 	}
 	*temp = ti_thermal_hotspot_temperature(tmp, slope, constant);
diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c
index f36950e..7722cb9 100644
--- a/drivers/thermal/x86_pkg_temp_thermal.c
+++ b/drivers/thermal/x86_pkg_temp_thermal.c
@@ -316,18 +316,19 @@
 	int phy_id = topology_physical_package_id(cpu);
 	struct phy_dev_entry *phdev = pkg_temp_thermal_get_phy_entry(cpu);
 	bool notify = false;
+	unsigned long flags;
 
 	if (!phdev)
 		return;
 
-	spin_lock(&pkg_work_lock);
+	spin_lock_irqsave(&pkg_work_lock, flags);
 	++pkg_work_cnt;
 	if (unlikely(phy_id > max_phy_id)) {
-		spin_unlock(&pkg_work_lock);
+		spin_unlock_irqrestore(&pkg_work_lock, flags);
 		return;
 	}
 	pkg_work_scheduled[phy_id] = 0;
-	spin_unlock(&pkg_work_lock);
+	spin_unlock_irqrestore(&pkg_work_lock, flags);
 
 	enable_pkg_thres_interrupt();
 	rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val);
@@ -397,6 +398,7 @@
 	int thres_count;
 	u32 eax, ebx, ecx, edx;
 	u8 *temp;
+	unsigned long flags;
 
 	cpuid(6, &eax, &ebx, &ecx, &edx);
 	thres_count = ebx & 0x07;
@@ -420,19 +422,19 @@
 		goto err_ret_unlock;
 	}
 
-	spin_lock(&pkg_work_lock);
+	spin_lock_irqsave(&pkg_work_lock, flags);
 	if (topology_physical_package_id(cpu) > max_phy_id)
 		max_phy_id = topology_physical_package_id(cpu);
 	temp = krealloc(pkg_work_scheduled,
 			(max_phy_id+1) * sizeof(u8), GFP_ATOMIC);
 	if (!temp) {
-		spin_unlock(&pkg_work_lock);
+		spin_unlock_irqrestore(&pkg_work_lock, flags);
 		err = -ENOMEM;
 		goto err_ret_free;
 	}
 	pkg_work_scheduled = temp;
 	pkg_work_scheduled[topology_physical_package_id(cpu)] = 0;
-	spin_unlock(&pkg_work_lock);
+	spin_unlock_irqrestore(&pkg_work_lock, flags);
 
 	phy_dev_entry->phys_proc_id = topology_physical_package_id(cpu);
 	phy_dev_entry->first_cpu = cpu;
diff --git a/drivers/tty/bfin_jtag_comm.c b/drivers/tty/bfin_jtag_comm.c
index a93a424..8096fcb 100644
--- a/drivers/tty/bfin_jtag_comm.c
+++ b/drivers/tty/bfin_jtag_comm.c
@@ -349,7 +349,7 @@
 	bfin_jc_straight_buffer_write(buf, count);
 }
 
-static struct __initdata console bfin_jc_early_console = {
+static struct console bfin_jc_early_console __initdata = {
 	.name   = "early_BFJC",
 	.write   = bfin_jc_early_write,
 	.flags   = CON_ANYTIME | CON_PRINTBUFFER,
diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c
index 9bffcec..0419b69 100644
--- a/drivers/tty/ehv_bytechan.c
+++ b/drivers/tty/ehv_bytechan.c
@@ -32,6 +32,7 @@
 #include <linux/poll.h>
 #include <asm/epapr_hcalls.h>
 #include <linux/of.h>
+#include <linux/of_irq.h>
 #include <linux/platform_device.h>
 #include <linux/cdev.h>
 #include <linux/console.h>
diff --git a/drivers/tty/hvc/hvc_dcc.c b/drivers/tty/hvc/hvc_dcc.c
index 44fbeba..3502a7b 100644
--- a/drivers/tty/hvc/hvc_dcc.c
+++ b/drivers/tty/hvc/hvc_dcc.c
@@ -86,6 +86,21 @@
 	return i;
 }
 
+static bool hvc_dcc_check(void)
+{
+	unsigned long time = jiffies + (HZ / 10);
+
+	/* Write a test character to check if it is handled */
+	__dcc_putchar('\n');
+
+	while (time_is_after_jiffies(time)) {
+		if (!(__dcc_getstatus() & DCC_STATUS_TX))
+			return true;
+	}
+
+	return false;
+}
+
 static const struct hv_ops hvc_dcc_get_put_ops = {
 	.get_chars = hvc_dcc_get_chars,
 	.put_chars = hvc_dcc_put_chars,
@@ -93,6 +108,9 @@
 
 static int __init hvc_dcc_console_init(void)
 {
+	if (!hvc_dcc_check())
+		return -ENODEV;
+
 	hvc_instantiate(0, 0, &hvc_dcc_get_put_ops);
 	return 0;
 }
@@ -100,6 +118,9 @@
 
 static int __init hvc_dcc_init(void)
 {
+	if (!hvc_dcc_check())
+		return -ENODEV;
+
 	hvc_alloc(0, 0, &hvc_dcc_get_put_ops, 128);
 	return 0;
 }
diff --git a/drivers/tty/hvc/hvc_iucv.c b/drivers/tty/hvc/hvc_iucv.c
index fd17a9b..db19a38 100644
--- a/drivers/tty/hvc/hvc_iucv.c
+++ b/drivers/tty/hvc/hvc_iucv.c
@@ -1354,8 +1354,7 @@
 	mempool_destroy(hvc_iucv_mempool);
 	kmem_cache_destroy(hvc_iucv_buffer_cache);
 out_error:
-	if (hvc_iucv_filter)
-		kfree(hvc_iucv_filter);
+	kfree(hvc_iucv_filter);
 	hvc_iucv_devices = 0; /* ensure that we do not provide any device */
 	return rc;
 }
diff --git a/drivers/tty/hvc/hvc_opal.c b/drivers/tty/hvc/hvc_opal.c
index cd69b48..6496872 100644
--- a/drivers/tty/hvc/hvc_opal.c
+++ b/drivers/tty/hvc/hvc_opal.c
@@ -329,7 +329,7 @@
 void __init hvc_opal_init_early(void)
 {
 	struct device_node *stdout_node = NULL;
-	const u32 *termno;
+	const __be32 *termno;
 	const char *name = NULL;
 	const struct hv_ops *ops;
 	u32 index;
@@ -371,7 +371,7 @@
 	if (!stdout_node)
 		return;
 	termno = of_get_property(stdout_node, "reg", NULL);
-	index = termno ? *termno : 0;
+	index = termno ? be32_to_cpup(termno) : 0;
 	if (index >= MAX_NR_HVC_CONSOLES)
 		return;
 	hvc_opal_privs[index] = &hvc_opal_boot_priv;
diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c
index c791b18..b594abf 100644
--- a/drivers/tty/hvc/hvc_vio.c
+++ b/drivers/tty/hvc/hvc_vio.c
@@ -48,6 +48,7 @@
 #include <asm/prom.h>
 #include <asm/hvsi.h>
 #include <asm/udbg.h>
+#include <asm/machdep.h>
 
 #include "hvc_console.h"
 
@@ -457,7 +458,9 @@
 	if (hvterm_priv0.proto == HV_PROTOCOL_HVSI)
 		goto out;
 #endif
-	add_preferred_console("hvc", 0, NULL);
+	/* Check whether the user has requested a different console. */
+	if (!strstr(cmd_line, "console="))
+		add_preferred_console("hvc", 0, NULL);
 	hvc_instantiate(0, 0, ops);
 out:
 	of_node_put(stdout_node);
diff --git a/drivers/tty/hvc/hvsi_lib.c b/drivers/tty/hvc/hvsi_lib.c
index ac27671..347050e 100644
--- a/drivers/tty/hvc/hvsi_lib.c
+++ b/drivers/tty/hvc/hvsi_lib.c
@@ -9,7 +9,7 @@
 
 static int hvsi_send_packet(struct hvsi_priv *pv, struct hvsi_header *packet)
 {
-	packet->seqno = atomic_inc_return(&pv->seqno);
+	packet->seqno = cpu_to_be16(atomic_inc_return(&pv->seqno));
 
 	/* Assumes that always succeeds, works in practice */
 	return pv->put_chars(pv->termno, (char *)packet, packet->len);
@@ -28,7 +28,7 @@
 	/* Send version query */
 	q.hdr.type = VS_QUERY_PACKET_HEADER;
 	q.hdr.len = sizeof(struct hvsi_query);
-	q.verb = VSV_SEND_VERSION_NUMBER;
+	q.verb = cpu_to_be16(VSV_SEND_VERSION_NUMBER);
 	hvsi_send_packet(pv, &q.hdr);
 }
 
@@ -40,7 +40,7 @@
 
 	ctrl.hdr.type = VS_CONTROL_PACKET_HEADER;
 	ctrl.hdr.len = sizeof(struct hvsi_control);
-	ctrl.verb = VSV_CLOSE_PROTOCOL;
+	ctrl.verb = cpu_to_be16(VSV_CLOSE_PROTOCOL);
 	return hvsi_send_packet(pv, &ctrl.hdr);
 }
 
@@ -69,14 +69,14 @@
 {
 	struct hvsi_control *pkt = (struct hvsi_control *)pv->inbuf;
 
-	switch (pkt->verb) {
+	switch (be16_to_cpu(pkt->verb)) {
 	case VSV_CLOSE_PROTOCOL:
 		/* We restart the handshaking */
 		hvsi_start_handshake(pv);
 		break;
 	case VSV_MODEM_CTL_UPDATE:
 		/* Transition of carrier detect */
-		hvsi_cd_change(pv, pkt->word & HVSI_TSCD);
+		hvsi_cd_change(pv, be32_to_cpu(pkt->word) & HVSI_TSCD);
 		break;
 	}
 }
@@ -87,7 +87,7 @@
 	struct hvsi_query_response r;
 
 	/* We only handle version queries */
-	if (pkt->verb != VSV_SEND_VERSION_NUMBER)
+	if (be16_to_cpu(pkt->verb) != VSV_SEND_VERSION_NUMBER)
 		return;
 
 	pr_devel("HVSI@%x: Got version query, sending response...\n",
@@ -96,7 +96,7 @@
 	/* Send version response */
 	r.hdr.type = VS_QUERY_RESPONSE_PACKET_HEADER;
 	r.hdr.len = sizeof(struct hvsi_query_response);
-	r.verb = VSV_SEND_VERSION_NUMBER;
+	r.verb = cpu_to_be16(VSV_SEND_VERSION_NUMBER);
 	r.u.version = HVSI_VERSION;
 	r.query_seqno = pkt->hdr.seqno;
 	hvsi_send_packet(pv, &r.hdr);
@@ -112,7 +112,7 @@
 
 	switch(r->verb) {
 	case VSV_SEND_MODEM_CTL_STATUS:
-		hvsi_cd_change(pv, r->u.mctrl_word & HVSI_TSCD);
+		hvsi_cd_change(pv, be32_to_cpu(r->u.mctrl_word) & HVSI_TSCD);
 		pv->mctrl_update = 1;
 		break;
 	}
@@ -265,8 +265,7 @@
 	pv->mctrl_update = 0;
 	q.hdr.type = VS_QUERY_PACKET_HEADER;
 	q.hdr.len = sizeof(struct hvsi_query);
-	q.hdr.seqno = atomic_inc_return(&pv->seqno);
-	q.verb = VSV_SEND_MODEM_CTL_STATUS;
+	q.verb = cpu_to_be16(VSV_SEND_MODEM_CTL_STATUS);
 	rc = hvsi_send_packet(pv, &q.hdr);
 	if (rc <= 0) {
 		pr_devel("HVSI@%x: Error %d...\n", pv->termno, rc);
@@ -304,9 +303,9 @@
 
 	ctrl.hdr.type = VS_CONTROL_PACKET_HEADER,
 	ctrl.hdr.len = sizeof(struct hvsi_control);
-	ctrl.verb = VSV_SET_MODEM_CTL;
-	ctrl.mask = HVSI_TSDTR;
-	ctrl.word = dtr ? HVSI_TSDTR : 0;
+	ctrl.verb = cpu_to_be16(VSV_SET_MODEM_CTL);
+	ctrl.mask = cpu_to_be32(HVSI_TSDTR);
+	ctrl.word = cpu_to_be32(dtr ? HVSI_TSDTR : 0);
 	return hvsi_send_packet(pv, &ctrl.hdr);
 }
 
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 7a744b6..7cdd1eb 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -767,7 +767,7 @@
 	 * of echo overrun before the next commit), then discard enough
 	 * data at the tail to prevent a subsequent overrun */
 	while (ldata->echo_commit - tail >= ECHO_DISCARD_WATERMARK) {
-		if (echo_buf(ldata, tail == ECHO_OP_START)) {
+		if (echo_buf(ldata, tail) == ECHO_OP_START) {
 			if (echo_buf(ldata, tail) == ECHO_OP_ERASE_TAB)
 				tail += 3;
 			else
@@ -1752,20 +1752,14 @@
 static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
 {
 	struct n_tty_data *ldata = tty->disc_data;
-	int canon_change = 1;
 
-	if (old)
-		canon_change = (old->c_lflag ^ tty->termios.c_lflag) & ICANON;
-	if (canon_change) {
+	if (!old || (old->c_lflag ^ tty->termios.c_lflag) & ICANON) {
 		bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
 		ldata->line_start = ldata->canon_head = ldata->read_tail;
 		ldata->erasing = 0;
 		ldata->lnext = 0;
 	}
 
-	if (canon_change && !L_ICANON(tty) && read_cnt(ldata))
-		wake_up_interruptible(&tty->read_wait);
-
 	ldata->icanon = (L_ICANON(tty) != 0);
 
 	if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) ||
@@ -1820,9 +1814,8 @@
 	 * Fix tty hang when I_IXON(tty) is cleared, but the tty
 	 * been stopped by STOP_CHAR(tty) before it.
 	 */
-	if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped) {
+	if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped)
 		start_tty(tty);
-	}
 
 	/* The termios change make the tty ready for I/O */
 	wake_up_interruptible(&tty->write_wait);
diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
index d6080c3..cd04293 100644
--- a/drivers/tty/nozomi.c
+++ b/drivers/tty/nozomi.c
@@ -959,7 +959,7 @@
 		dev_err(&dc->pdev->dev,
 			"ERROR: flow control received for non-existing port\n");
 		return 0;
-	};
+	}
 
 	DBG1("0x%04X->0x%04X", *((u16 *)&dc->port[port].ctrl_dl),
 	   *((u16 *)&ctrl_dl));
@@ -1025,7 +1025,7 @@
 		dev_err(&dc->pdev->dev,
 			"ERROR: send flow control " \
 			"received for non-existing port\n");
-	};
+	}
 	return CTRL_ERROR;
 }
 
@@ -1805,7 +1805,7 @@
 	default:
 		DBG1("ERR: 0x%08X, %d", cmd, cmd);
 		break;
-	};
+	}
 
 	return rval;
 }
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 570df9d..e33d38c 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -2322,7 +2322,7 @@
 
 	if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
 		fcr = uart_config[port->type].fcr;
-		if (baud < 2400 || fifo_bug) {
+		if ((baud < 2400 && !up->dma) || fifo_bug) {
 			fcr &= ~UART_FCR_TRIGGER_MASK;
 			fcr |= UART_FCR_TRIGGER_1;
 		}
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index daf710f..4658e3e 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -56,11 +56,11 @@
 
 
 struct dw8250_data {
-	int		last_lcr;
-	int		last_mcr;
-	int		line;
-	struct clk	*clk;
-	u8		usr_reg;
+	u8			usr_reg;
+	int			last_mcr;
+	int			line;
+	struct clk		*clk;
+	struct uart_8250_dma	dma;
 };
 
 static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
@@ -76,17 +76,33 @@
 	return value;
 }
 
+static void dw8250_force_idle(struct uart_port *p)
+{
+	serial8250_clear_and_reinit_fifos(container_of
+					  (p, struct uart_8250_port, port));
+	(void)p->serial_in(p, UART_RX);
+}
+
 static void dw8250_serial_out(struct uart_port *p, int offset, int value)
 {
 	struct dw8250_data *d = p->private_data;
 
-	if (offset == UART_LCR)
-		d->last_lcr = value;
-
 	if (offset == UART_MCR)
 		d->last_mcr = value;
 
 	writeb(value, p->membase + (offset << p->regshift));
+
+	/* Make sure LCR write wasn't ignored */
+	if (offset == UART_LCR) {
+		int tries = 1000;
+		while (tries--) {
+			if (value == p->serial_in(p, UART_LCR))
+				return;
+			dw8250_force_idle(p);
+			writeb(value, p->membase + (UART_LCR << p->regshift));
+		}
+		dev_err(p->dev, "Couldn't set LCR to %d\n", value);
+	}
 }
 
 static unsigned int dw8250_serial_in(struct uart_port *p, int offset)
@@ -107,13 +123,22 @@
 {
 	struct dw8250_data *d = p->private_data;
 
-	if (offset == UART_LCR)
-		d->last_lcr = value;
-
 	if (offset == UART_MCR)
 		d->last_mcr = value;
 
 	writel(value, p->membase + (offset << p->regshift));
+
+	/* Make sure LCR write wasn't ignored */
+	if (offset == UART_LCR) {
+		int tries = 1000;
+		while (tries--) {
+			if (value == p->serial_in(p, UART_LCR))
+				return;
+			dw8250_force_idle(p);
+			writel(value, p->membase + (UART_LCR << p->regshift));
+		}
+		dev_err(p->dev, "Couldn't set LCR to %d\n", value);
+	}
 }
 
 static unsigned int dw8250_serial_in32(struct uart_port *p, int offset)
@@ -131,9 +156,8 @@
 	if (serial8250_handle_irq(p, iir)) {
 		return 1;
 	} else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
-		/* Clear the USR and write the LCR again. */
+		/* Clear the USR */
 		(void)p->serial_in(p, d->usr_reg);
-		p->serial_out(p, UART_LCR, d->last_lcr);
 
 		return 1;
 	}
@@ -153,6 +177,14 @@
 		pm_runtime_put_sync_suspend(port->dev);
 }
 
+static bool dw8250_dma_filter(struct dma_chan *chan, void *param)
+{
+	struct dw8250_data *data = param;
+
+	return chan->chan_id == data->dma.tx_chan_id ||
+	       chan->chan_id == data->dma.rx_chan_id;
+}
+
 static void dw8250_setup_port(struct uart_8250_port *up)
 {
 	struct uart_port	*p = &up->port;
@@ -241,7 +273,8 @@
 }
 
 #ifdef CONFIG_ACPI
-static int dw8250_probe_acpi(struct uart_8250_port *up)
+static int dw8250_probe_acpi(struct uart_8250_port *up,
+			     struct dw8250_data *data)
 {
 	const struct acpi_device_id *id;
 	struct uart_port *p = &up->port;
@@ -260,9 +293,7 @@
 	if (!p->uartclk)
 		p->uartclk = (unsigned int)id->driver_data;
 
-	up->dma = devm_kzalloc(p->dev, sizeof(*up->dma), GFP_KERNEL);
-	if (!up->dma)
-		return -ENOMEM;
+	up->dma = &data->dma;
 
 	up->dma->rxconf.src_maxburst = p->fifosize / 4;
 	up->dma->txconf.dst_maxburst = p->fifosize / 4;
@@ -270,7 +301,8 @@
 	return 0;
 }
 #else
-static inline int dw8250_probe_acpi(struct uart_8250_port *up)
+static inline int dw8250_probe_acpi(struct uart_8250_port *up,
+				    struct dw8250_data *data)
 {
 	return -ENODEV;
 }
@@ -314,6 +346,12 @@
 		uart.port.uartclk = clk_get_rate(data->clk);
 	}
 
+	data->dma.rx_chan_id = -1;
+	data->dma.tx_chan_id = -1;
+	data->dma.rx_param = data;
+	data->dma.tx_param = data;
+	data->dma.fn = dw8250_dma_filter;
+
 	uart.port.iotype = UPIO_MEM;
 	uart.port.serial_in = dw8250_serial_in;
 	uart.port.serial_out = dw8250_serial_out;
@@ -324,7 +362,7 @@
 		if (err)
 			return err;
 	} else if (ACPI_HANDLE(&pdev->dev)) {
-		err = dw8250_probe_acpi(&uart);
+		err = dw8250_probe_acpi(&uart, data);
 		if (err)
 			return err;
 	} else {
diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
index 5f3bba1..d1a9078 100644
--- a/drivers/tty/serial/8250/8250_em.c
+++ b/drivers/tty/serial/8250/8250_em.c
@@ -122,7 +122,7 @@
 	up.port.dev = &pdev->dev;
 	up.port.private_data = priv;
 
-	clk_enable(priv->sclk);
+	clk_prepare_enable(priv->sclk);
 	up.port.uartclk = clk_get_rate(priv->sclk);
 
 	up.port.iotype = UPIO_MEM32;
@@ -134,7 +134,7 @@
 	ret = serial8250_register_8250_port(&up);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "unable to register 8250 port\n");
-		clk_disable(priv->sclk);
+		clk_disable_unprepare(priv->sclk);
 		return ret;
 	}
 
@@ -148,7 +148,7 @@
 	struct serial8250_em_priv *priv = platform_get_drvdata(pdev);
 
 	serial8250_unregister_port(priv->line);
-	clk_disable(priv->sclk);
+	clk_disable_unprepare(priv->sclk);
 	return 0;
 }
 
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index c810da7..4697a51 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -9,6 +9,7 @@
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License.
  */
+#undef DEBUG
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
@@ -27,8 +28,6 @@
 
 #include "8250.h"
 
-#undef SERIAL_DEBUG_PCI
-
 /*
  * init function returns:
  *  > 0 - number of ports
@@ -63,7 +62,7 @@
 
 static void moan_device(const char *str, struct pci_dev *dev)
 {
-	printk(KERN_WARNING
+	dev_err(&dev->dev,
 	       "%s: %s\n"
 	       "Please send the output of lspci -vv, this\n"
 	       "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
@@ -233,7 +232,7 @@
 	/* is firmware started? */
 	pci_read_config_dword(dev, 0x44, (void *)&oldval);
 	if (oldval == 0x00001000L) { /* RESET value */
-		printk(KERN_DEBUG "Local i960 firmware missing");
+		dev_dbg(&dev->dev, "Local i960 firmware missing\n");
 		return -ENODEV;
 	}
 	return 0;
@@ -827,7 +826,7 @@
 		if (sub_serports > 0) {
 			return sub_serports;
 		} else {
-			printk(KERN_NOTICE "NetMos/Mostech serial driver ignoring port on ambiguous config.\n");
+			dev_err(&dev->dev, "NetMos/Mostech serial driver ignoring port on ambiguous config.\n");
 			return 0;
 		}
 	}
@@ -931,7 +930,7 @@
 	}
 
 	if (!inta_addr[i]) {
-		printk(KERN_ERR "ite887x: could not find iobase\n");
+		dev_err(&dev->dev, "ite887x: could not find iobase\n");
 		return -ENODEV;
 	}
 
@@ -1024,9 +1023,9 @@
 	/* Tornado device */
 	if (deviceID == 0x07000200) {
 		number_uarts = ioread8(p + 4);
-		printk(KERN_DEBUG
+		dev_dbg(&dev->dev,
 			"%d ports detected on Oxford PCI Express device\n",
-								number_uarts);
+			number_uarts);
 	}
 	pci_iounmap(dev, p);
 	return number_uarts;
@@ -1308,6 +1307,29 @@
 	return setup_port(priv, port, bar, offset, board->reg_shift);
 }
 
+static int pci_pericom_setup(struct serial_private *priv,
+		  const struct pciserial_board *board,
+		  struct uart_8250_port *port, int idx)
+{
+	unsigned int bar, offset = board->first_offset, maxnr;
+
+	bar = FL_GET_BASE(board->flags);
+	if (board->flags & FL_BASE_BARS)
+		bar += idx;
+	else
+		offset += idx * board->uart_offset;
+
+	maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >>
+		(board->reg_shift + 3);
+
+	if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
+		return 1;
+
+	port->port.uartclk = 14745600;
+
+	return setup_port(priv, port, bar, offset, board->reg_shift);
+}
+
 static int
 ce4100_serial_setup(struct serial_private *priv,
 		  const struct pciserial_board *board,
@@ -1324,6 +1346,120 @@
 	return ret;
 }
 
+#define PCI_DEVICE_ID_INTEL_BYT_UART1	0x0f0a
+#define PCI_DEVICE_ID_INTEL_BYT_UART2	0x0f0c
+
+#define BYT_PRV_CLK			0x800
+#define BYT_PRV_CLK_EN			(1 << 0)
+#define BYT_PRV_CLK_M_VAL_SHIFT		1
+#define BYT_PRV_CLK_N_VAL_SHIFT		16
+#define BYT_PRV_CLK_UPDATE		(1 << 31)
+
+#define BYT_GENERAL_REG			0x808
+#define BYT_GENERAL_DIS_RTS_N_OVERRIDE	(1 << 3)
+
+#define BYT_TX_OVF_INT			0x820
+#define BYT_TX_OVF_INT_MASK		(1 << 1)
+
+static void
+byt_set_termios(struct uart_port *p, struct ktermios *termios,
+		struct ktermios *old)
+{
+	unsigned int baud = tty_termios_baud_rate(termios);
+	unsigned int m = 6912;
+	unsigned int n = 15625;
+	u32 reg;
+
+	/* For baud rates 1M, 2M, 3M and 4M the dividers must be adjusted. */
+	if (baud == 1000000 || baud == 2000000 || baud == 4000000) {
+		m = 64;
+		n = 100;
+
+		p->uartclk = 64000000;
+	} else if (baud == 3000000) {
+		m = 48;
+		n = 100;
+
+		p->uartclk = 48000000;
+	} else {
+		p->uartclk = 44236800;
+	}
+
+	/* Reset the clock */
+	reg = (m << BYT_PRV_CLK_M_VAL_SHIFT) | (n << BYT_PRV_CLK_N_VAL_SHIFT);
+	writel(reg, p->membase + BYT_PRV_CLK);
+	reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
+	writel(reg, p->membase + BYT_PRV_CLK);
+
+	/*
+	 * If auto-handshake mechanism is not enabled,
+	 * disable rts_n override
+	 */
+	reg = readl(p->membase + BYT_GENERAL_REG);
+	reg &= ~BYT_GENERAL_DIS_RTS_N_OVERRIDE;
+	if (termios->c_cflag & CRTSCTS)
+		reg |= BYT_GENERAL_DIS_RTS_N_OVERRIDE;
+	writel(reg, p->membase + BYT_GENERAL_REG);
+
+	serial8250_do_set_termios(p, termios, old);
+}
+
+static bool byt_dma_filter(struct dma_chan *chan, void *param)
+{
+	return chan->chan_id == *(int *)param;
+}
+
+static int
+byt_serial_setup(struct serial_private *priv,
+		 const struct pciserial_board *board,
+		 struct uart_8250_port *port, int idx)
+{
+	struct uart_8250_dma *dma;
+	int ret;
+
+	dma = devm_kzalloc(port->port.dev, sizeof(*dma), GFP_KERNEL);
+	if (!dma)
+		return -ENOMEM;
+
+	switch (priv->dev->device) {
+	case PCI_DEVICE_ID_INTEL_BYT_UART1:
+		dma->rx_chan_id = 3;
+		dma->tx_chan_id = 2;
+		break;
+	case PCI_DEVICE_ID_INTEL_BYT_UART2:
+		dma->rx_chan_id = 5;
+		dma->tx_chan_id = 4;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	dma->rxconf.slave_id = dma->rx_chan_id;
+	dma->rxconf.src_maxburst = 16;
+
+	dma->txconf.slave_id = dma->tx_chan_id;
+	dma->txconf.dst_maxburst = 16;
+
+	dma->fn = byt_dma_filter;
+	dma->rx_param = &dma->rx_chan_id;
+	dma->tx_param = &dma->tx_chan_id;
+
+	ret = pci_default_setup(priv, board, port, idx);
+	port->port.iotype = UPIO_MEM;
+	port->port.type = PORT_16550A;
+	port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
+	port->port.set_termios = byt_set_termios;
+	port->port.fifosize = 64;
+	port->tx_loadsz = 64;
+	port->dma = dma;
+	port->capabilities = UART_CAP_FIFO | UART_CAP_AFE;
+
+	/* Disable Tx counter interrupts */
+	writel(BYT_TX_OVF_INT_MASK, port->port.membase + BYT_TX_OVF_INT);
+
+	return ret;
+}
+
 static int
 pci_omegapci_setup(struct serial_private *priv,
 		      const struct pciserial_board *board,
@@ -1344,17 +1480,80 @@
 	return ret;
 }
 
+static int pci_fintek_setup(struct serial_private *priv,
+			    const struct pciserial_board *board,
+			    struct uart_8250_port *port, int idx)
+{
+	struct pci_dev *pdev = priv->dev;
+	unsigned long base;
+	unsigned long iobase;
+	unsigned long ciobase = 0;
+	u8 config_base;
+
+	/*
+	 * We are supposed to be able to read these from the PCI config space,
+	 * but the values there don't seem to match what we need to use, so
+	 * just use these hard-coded values for now, as they are correct.
+	 */
+	switch (idx) {
+	case 0: iobase = 0xe000; config_base = 0x40; break;
+	case 1: iobase = 0xe008; config_base = 0x48; break;
+	case 2: iobase = 0xe010; config_base = 0x50; break;
+	case 3: iobase = 0xe018; config_base = 0x58; break;
+	case 4: iobase = 0xe020; config_base = 0x60; break;
+	case 5: iobase = 0xe028; config_base = 0x68; break;
+	case 6: iobase = 0xe030; config_base = 0x70; break;
+	case 7: iobase = 0xe038; config_base = 0x78; break;
+	case 8: iobase = 0xe040; config_base = 0x80; break;
+	case 9: iobase = 0xe048; config_base = 0x88; break;
+	case 10: iobase = 0xe050; config_base = 0x90; break;
+	case 11: iobase = 0xe058; config_base = 0x98; break;
+	default:
+		/* Unknown number of ports, get out of here */
+		return -EINVAL;
+	}
+
+	if (idx < 4) {
+		base = pci_resource_start(priv->dev, 3);
+		ciobase = (int)(base + (0x8 * idx));
+	}
+
+	dev_dbg(&pdev->dev, "%s: idx=%d iobase=0x%lx ciobase=0x%lx config_base=0x%2x\n",
+		__func__, idx, iobase, ciobase, config_base);
+
+	/* Enable UART I/O port */
+	pci_write_config_byte(pdev, config_base + 0x00, 0x01);
+
+	/* Select 128-byte FIFO and 8x FIFO threshold */
+	pci_write_config_byte(pdev, config_base + 0x01, 0x33);
+
+	/* LSB UART */
+	pci_write_config_byte(pdev, config_base + 0x04, (u8)(iobase & 0xff));
+
+	/* MSB UART */
+	pci_write_config_byte(pdev, config_base + 0x05, (u8)((iobase & 0xff00) >> 8));
+
+	/* irq number, this usually fails, but the spec says to do it anyway. */
+	pci_write_config_byte(pdev, config_base + 0x06, pdev->irq);
+
+	port->port.iotype = UPIO_PORT;
+	port->port.iobase = iobase;
+	port->port.mapbase = 0;
+	port->port.membase = NULL;
+	port->port.regshift = 0;
+
+	return 0;
+}
+
 static int skip_tx_en_setup(struct serial_private *priv,
 			const struct pciserial_board *board,
 			struct uart_8250_port *port, int idx)
 {
 	port->port.flags |= UPF_NO_TXEN_TEST;
-	printk(KERN_DEBUG "serial8250: skipping TxEn test for device "
-			  "[%04x:%04x] subsystem [%04x:%04x]\n",
-			  priv->dev->vendor,
-			  priv->dev->device,
-			  priv->dev->subsystem_vendor,
-			  priv->dev->subsystem_device);
+	dev_dbg(&priv->dev->dev,
+		"serial8250: skipping TxEn test for device [%04x:%04x] subsystem [%04x:%04x]\n",
+		priv->dev->vendor, priv->dev->device,
+		priv->dev->subsystem_vendor, priv->dev->subsystem_device);
 
 	return pci_default_setup(priv, board, port, idx);
 }
@@ -1662,6 +1861,20 @@
 		.subdevice	= PCI_ANY_ID,
 		.setup		= kt_serial_setup,
 	},
+	{
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_BYT_UART1,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= byt_serial_setup,
+	},
+	{
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_BYT_UART2,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= byt_serial_setup,
+	},
 	/*
 	 * ITE
 	 */
@@ -1826,6 +2039,31 @@
 		.exit		= pci_plx9050_exit,
 	},
 	/*
+	 * Pericom
+	 */
+	{
+		.vendor		= 0x12d8,
+		.device		= 0x7952,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_pericom_setup,
+	},
+	{
+		.vendor		= 0x12d8,
+		.device		= 0x7954,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_pericom_setup,
+	},
+	{
+		.vendor		= 0x12d8,
+		.device		= 0x7958,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_pericom_setup,
+	},
+
+	/*
 	 * PLX
 	 */
 	{
@@ -2255,6 +2493,27 @@
 		.subdevice	= PCI_ANY_ID,
 		.setup		= pci_brcm_trumanage_setup,
 	},
+	{
+		.vendor		= 0x1c29,
+		.device		= 0x1104,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_fintek_setup,
+	},
+	{
+		.vendor		= 0x1c29,
+		.device		= 0x1108,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_fintek_setup,
+	},
+	{
+		.vendor		= 0x1c29,
+		.device		= 0x1112,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_fintek_setup,
+	},
 
 	/*
 	 * Default "match everything" terminator entry
@@ -2449,9 +2708,13 @@
 	pbn_ADDIDATA_PCIe_4_3906250,
 	pbn_ADDIDATA_PCIe_8_3906250,
 	pbn_ce4100_1_115200,
+	pbn_byt,
 	pbn_omegapci,
 	pbn_NETMOS9900_2s_115200,
 	pbn_brcm_trumanage,
+	pbn_fintek_4,
+	pbn_fintek_8,
+	pbn_fintek_12,
 };
 
 /*
@@ -3185,6 +3448,13 @@
 		.base_baud	= 921600,
 		.reg_shift      = 2,
 	},
+	[pbn_byt] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 1,
+		.base_baud	= 2764800,
+		.uart_offset	= 0x80,
+		.reg_shift      = 2,
+	},
 	[pbn_omegapci] = {
 		.flags		= FL_BASE0,
 		.num_ports	= 8,
@@ -3202,6 +3472,24 @@
 		.reg_shift	= 2,
 		.base_baud	= 115200,
 	},
+	[pbn_fintek_4] = {
+		.num_ports	= 4,
+		.uart_offset	= 8,
+		.base_baud	= 115200,
+		.first_offset	= 0x40,
+	},
+	[pbn_fintek_8] = {
+		.num_ports	= 8,
+		.uart_offset	= 8,
+		.base_baud	= 115200,
+		.first_offset	= 0x40,
+	},
+	[pbn_fintek_12] = {
+		.num_ports	= 12,
+		.uart_offset	= 8,
+		.base_baud	= 115200,
+		.first_offset	= 0x40,
+	},
 };
 
 static const struct pci_device_id blacklist[] = {
@@ -3362,14 +3650,15 @@
 		if (quirk->setup(priv, board, &uart, i))
 			break;
 
-#ifdef SERIAL_DEBUG_PCI
-		printk(KERN_DEBUG "Setup PCI port: port %lx, irq %d, type %d\n",
-		       uart.port.iobase, uart.port.irq, uart.port.iotype);
-#endif
+		dev_dbg(&dev->dev, "Setup PCI port: port %lx, irq %d, type %d\n",
+			uart.port.iobase, uart.port.irq, uart.port.iotype);
 
 		priv->line[i] = serial8250_register_8250_port(&uart);
 		if (priv->line[i] < 0) {
-			printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]);
+			dev_err(&dev->dev,
+				"Couldn't register serial port %lx, irq %d, type %d, error %d\n",
+				uart.port.iobase, uart.port.irq,
+				uart.port.iotype, priv->line[i]);
 			break;
 		}
 	}
@@ -3462,7 +3751,7 @@
 	}
 
 	if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
-		printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n",
+		dev_err(&dev->dev, "invalid driver_data: %ld\n",
 			ent->driver_data);
 		return -EINVAL;
 	}
@@ -3520,8 +3809,6 @@
 {
 	struct serial_private *priv = pci_get_drvdata(dev);
 
-	pci_set_drvdata(dev, NULL);
-
 	pciserial_remove_ports(priv);
 
 	pci_disable_device(dev);
@@ -3555,7 +3842,7 @@
 		err = pci_enable_device(dev);
 		/* FIXME: We cannot simply error out here */
 		if (err)
-			printk(KERN_ERR "pciserial: Unable to re-enable ports, trying to continue.\n");
+			dev_err(&dev->dev, "Unable to re-enable ports, trying to continue.\n");
 		pciserial_resume_ports(priv);
 	}
 	return 0;
@@ -4848,6 +5135,15 @@
 	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100_UART,
 		PCI_ANY_ID,  PCI_ANY_ID, 0, 0,
 		pbn_ce4100_1_115200 },
+	/* Intel BayTrail */
+	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_UART1,
+		PCI_ANY_ID,  PCI_ANY_ID,
+		PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
+		pbn_byt },
+	{	PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_UART2,
+		PCI_ANY_ID,  PCI_ANY_ID,
+		PCI_CLASS_COMMUNICATION_SERIAL << 8, 0xff0000,
+		pbn_byt },
 
 	/*
 	 * Cronyx Omega PCI
@@ -4918,6 +5214,11 @@
 		0,
 		0, pbn_exar_XR17V358 },
 
+	/* Fintek PCI serial cards */
+	{ PCI_DEVICE(0x1c29, 0x1104), .driver_data = pbn_fintek_4 },
+	{ PCI_DEVICE(0x1c29, 0x1108), .driver_data = pbn_fintek_8 },
+	{ PCI_DEVICE(0x1c29, 0x1112), .driver_data = pbn_fintek_12 },
+
 	/*
 	 * These entries match devices with class COMMUNICATION_SERIAL,
 	 * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index febd45c..a3817ab 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -709,7 +709,7 @@
 
 config SERIAL_SH_SCI
 	tristate "SuperH SCI(F) serial port support"
-	depends on HAVE_CLK && (SUPERH || ARCH_SHMOBILE)
+	depends on HAVE_CLK && (SUPERH || ARM || COMPILE_TEST)
 	select SERIAL_CORE
 
 config SERIAL_SH_SCI_NR_UARTS
@@ -1512,6 +1512,7 @@
 config SERIAL_ST_ASC
 	tristate "ST ASC serial port support"
 	select SERIAL_CORE
+	depends on ARM || COMPILE_TEST
 	help
 	  This driver is for the on-chip Asychronous Serial Controller on
 	  STMicroelectronics STi SoCs.
diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c
index 8b90f0b..33bd860 100644
--- a/drivers/tty/serial/amba-pl010.c
+++ b/drivers/tty/serial/amba-pl010.c
@@ -728,7 +728,6 @@
 	amba_set_drvdata(dev, uap);
 	ret = uart_add_one_port(&amba_reg, &uap->port);
 	if (ret) {
-		amba_set_drvdata(dev, NULL);
 		amba_ports[i] = NULL;
 		clk_put(uap->clk);
  unmap:
@@ -745,8 +744,6 @@
 	struct uart_amba_port *uap = amba_get_drvdata(dev);
 	int i;
 
-	amba_set_drvdata(dev, NULL);
-
 	uart_remove_one_port(&amba_reg, &uap->port);
 
 	for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index aaa2286..7203864 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -2147,7 +2147,6 @@
 	amba_set_drvdata(dev, uap);
 	ret = uart_add_one_port(&amba_reg, &uap->port);
 	if (ret) {
-		amba_set_drvdata(dev, NULL);
 		amba_ports[i] = NULL;
 		pl011_dma_remove(uap);
 	}
@@ -2160,8 +2159,6 @@
 	struct uart_amba_port *uap = amba_get_drvdata(dev);
 	int i;
 
-	amba_set_drvdata(dev, NULL);
-
 	uart_remove_one_port(&amba_reg, &uap->port);
 
 	for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
index 569872f..c9f5c9d 100644
--- a/drivers/tty/serial/arc_uart.c
+++ b/drivers/tty/serial/arc_uart.c
@@ -533,7 +533,7 @@
 	unsigned long *plat_data;
 	struct arc_uart_port *uart = &arc_uart_ports[dev_id];
 
-	plat_data = (unsigned long *)dev_get_platdata(&pdev->dev);
+	plat_data = dev_get_platdata(&pdev->dev);
 	if (!plat_data)
 		return -ENODEV;
 
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index d067285..c7d99af 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -99,6 +99,7 @@
 #define UART_PUT_RTOR(port,v)	__raw_writel(v, (port)->membase + ATMEL_US_RTOR)
 #define UART_PUT_TTGR(port, v)	__raw_writel(v, (port)->membase + ATMEL_US_TTGR)
 #define UART_GET_IP_NAME(port)	__raw_readl((port)->membase + ATMEL_US_NAME)
+#define UART_GET_IP_VERSION(port) __raw_readl((port)->membase + ATMEL_US_VERSION)
 
  /* PDC registers */
 #define UART_PUT_PTCR(port,v)	__raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
@@ -1499,10 +1500,11 @@
 /*
  * Get ip name usart or uart
  */
-static int atmel_get_ip_name(struct uart_port *port)
+static void atmel_get_ip_name(struct uart_port *port)
 {
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	int name = UART_GET_IP_NAME(port);
+	u32 version;
 	int usart, uart;
 	/* usart and uart ascii */
 	usart = 0x55534152;
@@ -1517,11 +1519,23 @@
 		dev_dbg(port->dev, "This is uart\n");
 		atmel_port->is_usart = false;
 	} else {
-		dev_err(port->dev, "Not supported ip name, set to uart\n");
-		return -EINVAL;
+		/* fallback for older SoCs: use version field */
+		version = UART_GET_IP_VERSION(port);
+		switch (version) {
+		case 0x302:
+		case 0x10213:
+			dev_dbg(port->dev, "This version is usart\n");
+			atmel_port->is_usart = true;
+			break;
+		case 0x203:
+		case 0x10202:
+			dev_dbg(port->dev, "This version is uart\n");
+			atmel_port->is_usart = false;
+			break;
+		default:
+			dev_err(port->dev, "Not supported ip name nor version, set to uart\n");
+		}
 	}
-
-	return 0;
 }
 
 /*
@@ -2405,9 +2419,7 @@
 	/*
 	 * Get port name of usart or uart
 	 */
-	ret = atmel_get_ip_name(&port->uart);
-	if (ret < 0)
-		goto err_add_port;
+	atmel_get_ip_name(&port->uart);
 
 	return 0;
 
diff --git a/drivers/tty/serial/bfin_sport_uart.c b/drivers/tty/serial/bfin_sport_uart.c
index 87636cc..4f22970 100644
--- a/drivers/tty/serial/bfin_sport_uart.c
+++ b/drivers/tty/serial/bfin_sport_uart.c
@@ -766,9 +766,8 @@
 			return -ENOMEM;
 		}
 
-		ret = peripheral_request_list(
-			(unsigned short *)dev_get_platdata(&pdev->dev),
-			DRV_NAME);
+		ret = peripheral_request_list(dev_get_platdata(&pdev->dev),
+						DRV_NAME);
 		if (ret) {
 			dev_err(&pdev->dev,
 				"Fail to request SPORT peripherals\n");
@@ -844,8 +843,7 @@
 out_error_unmap:
 		iounmap(sport->port.membase);
 out_error_free_peripherals:
-		peripheral_free_list(
-			(unsigned short *)dev_get_platdata(&pdev->dev));
+		peripheral_free_list(dev_get_platdata(&pdev->dev));
 out_error_free_mem:
 		kfree(sport);
 		bfin_sport_uart_ports[pdev->id] = NULL;
@@ -864,8 +862,7 @@
 	if (sport) {
 		uart_remove_one_port(&sport_uart_reg, &sport->port);
 		iounmap(sport->port.membase);
-		peripheral_free_list(
-			(unsigned short *)dev_get_platdata(&pdev->dev));
+		peripheral_free_list(dev_get_platdata(&pdev->dev));
 		kfree(sport);
 		bfin_sport_uart_ports[pdev->id] = NULL;
 	}
diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c
index 3c75e8e..869ceba 100644
--- a/drivers/tty/serial/bfin_uart.c
+++ b/drivers/tty/serial/bfin_uart.c
@@ -680,7 +680,7 @@
 		default:
 			uart_dma_ch_rx = uart_dma_ch_tx = 0;
 			break;
-		};
+		}
 
 		if (uart_dma_ch_rx &&
 			request_dma(uart_dma_ch_rx, "BFIN_UART_RX") < 0) {
@@ -726,7 +726,7 @@
 #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
 	if (uart->cts_pin >= 0) {
 		if (request_irq(uart->status_irq, bfin_serial_mctrl_cts_int,
-			IRQF_DISABLED, "BFIN_UART_MODEM_STATUS", uart)) {
+			0, "BFIN_UART_MODEM_STATUS", uart)) {
 			uart->cts_pin = -1;
 			dev_info(port->dev, "Unable to attach BlackFin UART Modem Status interrupt.\n");
 		}
@@ -765,7 +765,7 @@
 		break;
 	default:
 		break;
-	};
+	}
 #endif
 	free_irq(uart->rx_irq, uart);
 	free_irq(uart->tx_irq, uart);
@@ -1240,7 +1240,7 @@
 			 */
 #endif
 		ret = peripheral_request_list(
-			(unsigned short *)dev_get_platdata(&pdev->dev),
+			dev_get_platdata(&pdev->dev),
 			DRIVER_NAME);
 		if (ret) {
 			dev_err(&pdev->dev,
@@ -1358,8 +1358,7 @@
 out_error_unmap:
 		iounmap(uart->port.membase);
 out_error_free_peripherals:
-		peripheral_free_list(
-			(unsigned short *)dev_get_platdata(&pdev->dev));
+		peripheral_free_list(dev_get_platdata(&pdev->dev));
 out_error_free_mem:
 		kfree(uart);
 		bfin_serial_ports[pdev->id] = NULL;
@@ -1377,8 +1376,7 @@
 	if (uart) {
 		uart_remove_one_port(&bfin_serial_reg, &uart->port);
 		iounmap(uart->port.membase);
-		peripheral_free_list(
-			(unsigned short *)dev_get_platdata(&pdev->dev));
+		peripheral_free_list(dev_get_platdata(&pdev->dev));
 		kfree(uart);
 		bfin_serial_ports[pdev->id] = NULL;
 	}
@@ -1432,8 +1430,8 @@
 		return -ENOENT;
 	}
 
-	ret = peripheral_request_list(
-		(unsigned short *)dev_get_platdata(&pdev->dev), DRIVER_NAME);
+	ret = peripheral_request_list(dev_get_platdata(&pdev->dev),
+					DRIVER_NAME);
 	if (ret) {
 		dev_err(&pdev->dev,
 				"fail to request bfin serial peripherals\n");
@@ -1463,8 +1461,7 @@
 	return 0;
 
 out_error_free_peripherals:
-	peripheral_free_list(
-		(unsigned short *)dev_get_platdata(&pdev->dev));
+	peripheral_free_list(dev_get_platdata(&pdev->dev));
 
 	return ret;
 }
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index 7e4e408..8d0b994 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -459,7 +459,6 @@
 	ret = uart_register_driver(&s->uart);
 	if (ret) {
 		dev_err(&pdev->dev, "Registering UART driver failed\n");
-		devm_clk_put(&pdev->dev, s->uart_clk);
 		return ret;
 	}
 
@@ -487,7 +486,6 @@
 	for (i = 0; i < UART_CLPS711X_NR; i++)
 		uart_remove_one_port(&s->uart, &s->port[i]);
 
-	devm_clk_put(&pdev->dev, s->uart_clk);
 	uart_unregister_driver(&s->uart);
 
 	return 0;
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
index 1a535f7..7d76214 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
@@ -41,6 +41,8 @@
 #include <linux/bootmem.h>
 #include <linux/dma-mapping.h>
 #include <linux/fs_uart_pd.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
@@ -1207,7 +1209,7 @@
 	pinfo->port.fifosize = pinfo->tx_nrfifos * pinfo->tx_fifosize;
 	spin_lock_init(&pinfo->port.lock);
 
-	pinfo->port.irq = of_irq_to_resource(np, 0, NULL);
+	pinfo->port.irq = irq_of_parse_and_map(np, 0);
 	if (pinfo->port.irq == NO_IRQ) {
 		ret = -EINVAL;
 		goto out_pram;
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c
index 18f7957..527a969 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_cpm1.c
@@ -45,6 +45,7 @@
 #include <linux/kernel.h>
 
 #include <linux/of.h>
+#include <linux/of_address.h>
 
 #include "cpm_uart.h"
 
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index af286e6..5903909 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -1008,7 +1008,7 @@
 		return -ENODEV;
 	}
 
-	pl_data = (struct ifx_modem_platform_data *)dev_get_platdata(&spi->dev);
+	pl_data = dev_get_platdata(&spi->dev);
 	if (!pl_data) {
 		dev_err(&spi->dev, "missing platform data!");
 		return -ENODEV;
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index a0ebbc9..b2cfdb6 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -223,8 +223,7 @@
 	struct dma_chan		*dma_chan_rx, *dma_chan_tx;
 	struct scatterlist	rx_sgl, tx_sgl[2];
 	void			*rx_buf;
-	unsigned int		rx_bytes, tx_bytes;
-	struct work_struct	tsk_dma_rx, tsk_dma_tx;
+	unsigned int		tx_bytes;
 	unsigned int		dma_tx_nents;
 	wait_queue_head_t	dma_wait;
 };
@@ -505,34 +504,25 @@
 		dev_dbg(sport->port.dev, "exit in %s.\n", __func__);
 		return;
 	}
-
-	schedule_work(&sport->tsk_dma_tx);
 }
 
-static void dma_tx_work(struct work_struct *w)
+static void imx_dma_tx(struct imx_port *sport)
 {
-	struct imx_port *sport = container_of(w, struct imx_port, tsk_dma_tx);
 	struct circ_buf *xmit = &sport->port.state->xmit;
 	struct scatterlist *sgl = sport->tx_sgl;
 	struct dma_async_tx_descriptor *desc;
 	struct dma_chan	*chan = sport->dma_chan_tx;
 	struct device *dev = sport->port.dev;
 	enum dma_status status;
-	unsigned long flags;
 	int ret;
 
-	status = chan->device->device_tx_status(chan, (dma_cookie_t)0, NULL);
+	status = dmaengine_tx_status(chan, (dma_cookie_t)0, NULL);
 	if (DMA_IN_PROGRESS == status)
 		return;
 
-	spin_lock_irqsave(&sport->port.lock, flags);
 	sport->tx_bytes = uart_circ_chars_pending(xmit);
-	if (sport->tx_bytes == 0) {
-		spin_unlock_irqrestore(&sport->port.lock, flags);
-		return;
-	}
 
-	if (xmit->tail > xmit->head) {
+	if (xmit->tail > xmit->head && xmit->head > 0) {
 		sport->dma_tx_nents = 2;
 		sg_init_table(sgl, 2);
 		sg_set_buf(sgl, xmit->buf + xmit->tail,
@@ -542,7 +532,6 @@
 		sport->dma_tx_nents = 1;
 		sg_init_one(sgl, xmit->buf + xmit->tail, sport->tx_bytes);
 	}
-	spin_unlock_irqrestore(&sport->port.lock, flags);
 
 	ret = dma_map_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
 	if (ret == 0) {
@@ -609,11 +598,7 @@
 	}
 
 	if (sport->dma_is_enabled) {
-		/*
-		 * We may in the interrupt context, so arise a work_struct to
-		 * do the real job.
-		 */
-		schedule_work(&sport->tsk_dma_tx);
+		imx_dma_tx(sport);
 		return;
 	}
 
@@ -732,6 +717,7 @@
 	return IRQ_HANDLED;
 }
 
+static int start_rx_dma(struct imx_port *sport);
 /*
  * If the RXFIFO is filled with some data, and then we
  * arise a DMA operation to receive them.
@@ -750,7 +736,7 @@
 		writel(temp, sport->port.membase + UCR1);
 
 		/* tell the DMA to receive the data. */
-		schedule_work(&sport->tsk_dma_rx);
+		start_rx_dma(sport);
 	}
 }
 
@@ -795,8 +781,15 @@
 static unsigned int imx_tx_empty(struct uart_port *port)
 {
 	struct imx_port *sport = (struct imx_port *)port;
+	unsigned int ret;
 
-	return (readl(sport->port.membase + USR2) & USR2_TXDC) ?  TIOCSER_TEMT : 0;
+	ret = (readl(sport->port.membase + USR2) & USR2_TXDC) ?  TIOCSER_TEMT : 0;
+
+	/* If the TX DMA is working, return 0. */
+	if (sport->dma_is_enabled && sport->dma_is_txing)
+		ret = 0;
+
+	return ret;
 }
 
 /*
@@ -865,22 +858,6 @@
 }
 
 #define RX_BUF_SIZE	(PAGE_SIZE)
-static int start_rx_dma(struct imx_port *sport);
-static void dma_rx_work(struct work_struct *w)
-{
-	struct imx_port *sport = container_of(w, struct imx_port, tsk_dma_rx);
-	struct tty_port *port = &sport->port.state->port;
-
-	if (sport->rx_bytes) {
-		tty_insert_flip_string(port, sport->rx_buf, sport->rx_bytes);
-		tty_flip_buffer_push(port);
-		sport->rx_bytes = 0;
-	}
-
-	if (sport->dma_is_rxing)
-		start_rx_dma(sport);
-}
-
 static void imx_rx_dma_done(struct imx_port *sport)
 {
 	unsigned long temp;
@@ -912,6 +889,7 @@
 	struct imx_port *sport = data;
 	struct dma_chan	*chan = sport->dma_chan_rx;
 	struct scatterlist *sgl = &sport->rx_sgl;
+	struct tty_port *port = &sport->port.state->port;
 	struct dma_tx_state state;
 	enum dma_status status;
 	unsigned int count;
@@ -919,13 +897,15 @@
 	/* unmap it first */
 	dma_unmap_sg(sport->port.dev, sgl, 1, DMA_FROM_DEVICE);
 
-	status = chan->device->device_tx_status(chan, (dma_cookie_t)0, &state);
+	status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state);
 	count = RX_BUF_SIZE - state.residue;
 	dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
 
 	if (count) {
-		sport->rx_bytes = count;
-		schedule_work(&sport->tsk_dma_rx);
+		tty_insert_flip_string(port, sport->rx_buf, count);
+		tty_flip_buffer_push(port);
+
+		start_rx_dma(sport);
 	} else
 		imx_rx_dma_done(sport);
 }
@@ -1007,7 +987,6 @@
 		ret = -ENOMEM;
 		goto err;
 	}
-	sport->rx_bytes = 0;
 
 	/* Prepare for TX : */
 	sport->dma_chan_tx = dma_request_slave_channel(dev, "tx");
@@ -1038,11 +1017,7 @@
 static void imx_enable_dma(struct imx_port *sport)
 {
 	unsigned long temp;
-	struct tty_port *port = &sport->port.state->port;
 
-	port->low_latency = 1;
-	INIT_WORK(&sport->tsk_dma_tx, dma_tx_work);
-	INIT_WORK(&sport->tsk_dma_rx, dma_rx_work);
 	init_waitqueue_head(&sport->dma_wait);
 
 	/* set UCR1 */
@@ -1063,7 +1038,6 @@
 static void imx_disable_dma(struct imx_port *sport)
 {
 	unsigned long temp;
-	struct tty_port *port = &sport->port.state->port;
 
 	/* clear UCR1 */
 	temp = readl(sport->port.membase + UCR1);
@@ -1081,7 +1055,6 @@
 	writel(temp, sport->port.membase + UCR4);
 
 	sport->dma_is_enabled = 0;
-	port->low_latency = 0;
 }
 
 /* half the RX buffer size */
@@ -1303,6 +1276,16 @@
 	clk_disable_unprepare(sport->clk_ipg);
 }
 
+static void imx_flush_buffer(struct uart_port *port)
+{
+	struct imx_port *sport = (struct imx_port *)port;
+
+	if (sport->dma_is_enabled) {
+		sport->tx_bytes = 0;
+		dmaengine_terminate_all(sport->dma_chan_tx);
+	}
+}
+
 static void
 imx_set_termios(struct uart_port *port, struct ktermios *termios,
 		   struct ktermios *old)
@@ -1539,7 +1522,7 @@
 		ret = -EINVAL;
 	if (sport->port.uartclk / 16 != ser->baud_base)
 		ret = -EINVAL;
-	if ((void *)sport->port.mapbase != ser->iomem_base)
+	if (sport->port.mapbase != (unsigned long)ser->iomem_base)
 		ret = -EINVAL;
 	if (sport->port.iobase != ser->port)
 		ret = -EINVAL;
@@ -1623,6 +1606,7 @@
 	.break_ctl	= imx_break_ctl,
 	.startup	= imx_startup,
 	.shutdown	= imx_shutdown,
+	.flush_buffer	= imx_flush_buffer,
 	.set_termios	= imx_set_termios,
 	.type		= imx_type,
 	.release_port	= imx_release_port,
@@ -1912,9 +1896,6 @@
 
 	sport->devdata = of_id->data;
 
-	if (of_device_is_stdout_path(np))
-		add_preferred_console(imx_reg.cons->name, sport->port.line, 0);
-
 	return 0;
 }
 #else
diff --git a/drivers/tty/serial/ip22zilog.c b/drivers/tty/serial/ip22zilog.c
index cb3c81e..1d94205 100644
--- a/drivers/tty/serial/ip22zilog.c
+++ b/drivers/tty/serial/ip22zilog.c
@@ -832,7 +832,7 @@
 		up->curregs[5] |= Tx8;
 		up->parity_mask = 0xff;
 		break;
-	};
+	}
 	up->curregs[4] &= ~0x0c;
 	if (cflag & CSTOPB)
 		up->curregs[4] |= SB2;
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
index b2e707aa..8d71e40 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -690,7 +690,7 @@
 			max310x_port_write(port, MAX310X_THR_REG,
 					   xmit->buf[xmit->tail]);
 			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		};
+		}
 	}
 
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c
index d3db042..52c930f 100644
--- a/drivers/tty/serial/mfd.c
+++ b/drivers/tty/serial/mfd.c
@@ -293,7 +293,7 @@
 	serial_out(up, UART_IER, up->ier);
 }
 
-void hsu_dma_tx(struct uart_hsu_port *up)
+static void hsu_dma_tx(struct uart_hsu_port *up)
 {
 	struct circ_buf *xmit = &up->port.state->xmit;
 	struct hsu_dma_buffer *dbuf = &up->txbuf;
@@ -340,7 +340,8 @@
 }
 
 /* The buffer is already cache coherent */
-void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, struct hsu_dma_buffer *dbuf)
+static void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc,
+					struct hsu_dma_buffer *dbuf)
 {
 	dbuf->ofs = 0;
 
@@ -386,7 +387,8 @@
 
 /* This is always called in spinlock protected mode, so
  * modify timeout timer is safe here */
-void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts, unsigned long *flags)
+static void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts,
+			unsigned long *flags)
 {
 	struct hsu_dma_buffer *dbuf = &up->rxbuf;
 	struct hsu_dma_chan *chan = up->rxc;
@@ -1183,7 +1185,7 @@
 #define SERIAL_HSU_CONSOLE	NULL
 #endif
 
-struct uart_ops serial_hsu_pops = {
+static struct uart_ops serial_hsu_pops = {
 	.tx_empty	= serial_hsu_tx_empty,
 	.set_mctrl	= serial_hsu_set_mctrl,
 	.get_mctrl	= serial_hsu_get_mctrl,
@@ -1451,7 +1453,6 @@
 		uart_remove_one_port(&serial_hsu_reg, &up->port);
 	}
 
-	pci_set_drvdata(pdev, NULL);
 	free_irq(pdev->irq, priv);
 	pci_disable_device(pdev);
 }
@@ -1504,4 +1505,4 @@
 module_exit(hsu_pci_exit);
 
 MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:medfield-hsu");
+MODULE_DEVICE_TABLE(pci, pci_ids);
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 5be1df3..ec06505 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -1301,7 +1301,6 @@
 	.shutdown	= mpc52xx_uart_shutdown,
 	.set_termios	= mpc52xx_uart_set_termios,
 /*	.pm		= mpc52xx_uart_pm,		Not supported yet */
-/*	.set_wake	= mpc52xx_uart_set_wake,	Not supported yet */
 	.type		= mpc52xx_uart_type,
 	.release_port	= mpc52xx_uart_release_port,
 	.request_port	= mpc52xx_uart_request_port,
@@ -1766,7 +1765,7 @@
 static int
 mpc52xx_uart_of_suspend(struct platform_device *op, pm_message_t state)
 {
-	struct uart_port *port = (struct uart_port *) platform_get_drvdata(op);
+	struct uart_port *port = platform_get_drvdata(op);
 
 	if (port)
 		uart_suspend_port(&mpc52xx_uart_driver, port);
@@ -1777,7 +1776,7 @@
 static int
 mpc52xx_uart_of_resume(struct platform_device *op)
 {
-	struct uart_port *port = (struct uart_port *) platform_get_drvdata(op);
+	struct uart_port *port = platform_get_drvdata(op);
 
 	if (port)
 		uart_resume_port(&mpc52xx_uart_driver, port);
diff --git a/drivers/tty/serial/mpsc.c b/drivers/tty/serial/mpsc.c
index 8d70267..e30a3ca 100644
--- a/drivers/tty/serial/mpsc.c
+++ b/drivers/tty/serial/mpsc.c
@@ -2030,7 +2030,7 @@
 {
 	struct mpsc_pdata	*pdata;
 
-	pdata = (struct mpsc_pdata *)dev_get_platdata(&pd->dev);
+	pdata = dev_get_platdata(&pd->dev);
 
 	pi->port.uartclk = pdata->brg_clk_freq;
 	pi->port.iotype = UPIO_MEM;
diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c
index a67e708..db0448a 100644
--- a/drivers/tty/serial/mrst_max3110.c
+++ b/drivers/tty/serial/mrst_max3110.c
@@ -43,6 +43,7 @@
 
 #include <linux/kthread.h>
 #include <linux/spi/spi.h>
+#include <linux/pm.h>
 
 #include "mrst_max3110.h"
 
@@ -61,6 +62,7 @@
 	struct task_struct *main_thread;
 	struct task_struct *read_thread;
 	struct mutex thread_mutex;
+	struct mutex io_mutex;
 
 	u32 baud;
 	u16 cur_conf;
@@ -90,6 +92,7 @@
 	struct spi_transfer	x;
 	int ret;
 
+	mutex_lock(&max->io_mutex);
 	spi_message_init(&message);
 	memset(&x, 0, sizeof x);
 	x.len = len;
@@ -104,6 +107,7 @@
 
 	/* Do the i/o */
 	ret = spi_sync(spi, &message);
+	mutex_unlock(&max->io_mutex);
 	return ret;
 }
 
@@ -491,19 +495,9 @@
 	port->state->port.low_latency = 1;
 
 	if (max->irq) {
-		max->read_thread = NULL;
-		ret = request_irq(max->irq, serial_m3110_irq,
-				IRQ_TYPE_EDGE_FALLING, "max3110", max);
-		if (ret) {
-			max->irq = 0;
-			pr_err(PR_FMT "unable to allocate IRQ, polling\n");
-		}  else {
-			/* Enable RX IRQ only */
-			config |= WC_RXA_IRQ_ENABLE;
-		}
-	}
-
-	if (max->irq == 0) {
+		/* Enable RX IRQ only */
+		config |= WC_RXA_IRQ_ENABLE;
+	} else {
 		/* If IRQ is disabled, start a read thread for input data */
 		max->read_thread =
 			kthread_run(max3110_read_thread, max, "max3110_read");
@@ -517,8 +511,6 @@
 
 	ret = max3110_out(max, config);
 	if (ret) {
-		if (max->irq)
-			free_irq(max->irq, max);
 		if (max->read_thread)
 			kthread_stop(max->read_thread);
 		max->read_thread = NULL;
@@ -540,9 +532,6 @@
 		max->read_thread = NULL;
 	}
 
-	if (max->irq)
-		free_irq(max->irq, max);
-
 	/* Disable interrupts from this port */
 	config = WC_TAG | WC_SW_SHDI;
 	max3110_out(max, config);
@@ -749,7 +738,8 @@
 	struct spi_device *spi = to_spi_device(dev);
 	struct uart_max3110 *max = spi_get_drvdata(spi);
 
-	disable_irq(max->irq);
+	if (max->irq > 0)
+		disable_irq(max->irq);
 	uart_suspend_port(&serial_m3110_reg, &max->port);
 	max3110_out(max, max->cur_conf | WC_SW_SHDI);
 	return 0;
@@ -762,7 +752,8 @@
 
 	max3110_out(max, max->cur_conf);
 	uart_resume_port(&serial_m3110_reg, &max->port);
-	enable_irq(max->irq);
+	if (max->irq > 0)
+		enable_irq(max->irq);
 	return 0;
 }
 
@@ -803,6 +794,7 @@
 	max->irq = (u16)spi->irq;
 
 	mutex_init(&max->thread_mutex);
+	mutex_init(&max->io_mutex);
 
 	max->word_7bits = 0;
 	max->parity = 0;
@@ -840,6 +832,16 @@
 		goto err_kthread;
 	}
 
+	if (max->irq) {
+		ret = request_irq(max->irq, serial_m3110_irq,
+				IRQ_TYPE_EDGE_FALLING, "max3110", max);
+		if (ret) {
+			max->irq = 0;
+			dev_warn(&spi->dev,
+			"unable to allocate IRQ, will use polling method\n");
+		}
+	}
+
 	spi_set_drvdata(spi, max);
 	pmax = max;
 
@@ -867,6 +869,9 @@
 
 	free_page((unsigned long)max->con_xmit.buf);
 
+	if (max->irq)
+		free_irq(max->irq, max);
+
 	if (max->main_thread)
 		kthread_stop(max->main_thread);
 
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 10e9d70..d8b6fee 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -39,6 +39,7 @@
 #include <asm/cacheflush.h>
 
 #define MXS_AUART_PORTS 5
+#define MXS_AUART_FIFO_SIZE		16
 
 #define AUART_CTRL0			0x00000000
 #define AUART_CTRL0_SET			0x00000004
@@ -548,6 +549,9 @@
 	s->flags |= MXS_AUART_DMA_ENABLED;
 	dev_dbg(s->dev, "enabled the DMA support.");
 
+	/* The DMA buffer is now the FIFO the TTY subsystem can use */
+	s->port.fifosize = UART_XMIT_SIZE;
+
 	return 0;
 
 err_out:
@@ -741,6 +745,9 @@
 	writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
 			u->membase + AUART_INTR);
 
+	/* Reset FIFO size (it could have changed if DMA was enabled) */
+	u->fifosize = MXS_AUART_FIFO_SIZE;
+
 	/*
 	 * Enable fifo so all four bytes of a DMA word are written to
 	 * output (otherwise, only the LSB is written, ie. 1 in 4 bytes)
@@ -1056,7 +1063,7 @@
 	s->port.membase = ioremap(r->start, resource_size(r));
 	s->port.ops = &mxs_auart_ops;
 	s->port.iotype = UPIO_MEM;
-	s->port.fifosize = 16;
+	s->port.fifosize = MXS_AUART_FIFO_SIZE;
 	s->port.uartclk = clk_get_rate(s->clk);
 	s->port.type = PORT_IMX;
 	s->port.dev = s->dev = &pdev->dev;
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 816d1a2..fa511eb 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -39,6 +39,7 @@
 #include <linux/irq.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
+#include <linux/of_irq.h>
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
 #include <linux/platform_data/serial-omap.h>
@@ -134,6 +135,7 @@
 	struct uart_port	port;
 	struct uart_omap_dma	uart_dma;
 	struct device		*dev;
+	int			wakeirq;
 
 	unsigned char		ier;
 	unsigned char		lcr;
@@ -175,7 +177,7 @@
 	bool			is_suspending;
 };
 
-#define to_uart_omap_port(p)	((container_of((p), struct uart_omap_port, port)))
+#define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port)))
 
 static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
 
@@ -214,10 +216,23 @@
 	return pdata->get_context_loss_count(up->dev);
 }
 
+static inline void serial_omap_enable_wakeirq(struct uart_omap_port *up,
+				       bool enable)
+{
+	if (!up->wakeirq)
+		return;
+
+	if (enable)
+		enable_irq(up->wakeirq);
+	else
+		disable_irq(up->wakeirq);
+}
+
 static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
 {
 	struct omap_uart_port_info *pdata = dev_get_platdata(up->dev);
 
+	serial_omap_enable_wakeirq(up, enable);
 	if (!pdata || !pdata->enable_wakeup)
 		return;
 
@@ -242,12 +257,12 @@
 	unsigned int n16 = port->uartclk / (16 * baud);
 	int baudAbsDiff13 = baud - (port->uartclk / (13 * n13));
 	int baudAbsDiff16 = baud - (port->uartclk / (16 * n16));
-	if(baudAbsDiff13 < 0)
+	if (baudAbsDiff13 < 0)
 		baudAbsDiff13 = -baudAbsDiff13;
-	if(baudAbsDiff16 < 0)
+	if (baudAbsDiff16 < 0)
 		baudAbsDiff16 = -baudAbsDiff16;
 
-	return (baudAbsDiff13 > baudAbsDiff16);
+	return (baudAbsDiff13 >= baudAbsDiff16);
 }
 
 /*
@@ -258,13 +273,13 @@
 static unsigned int
 serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
 {
-	unsigned int divisor;
+	unsigned int mode;
 
 	if (!serial_omap_baud_is_mode16(port, baud))
-		divisor = 13;
+		mode = 13;
 	else
-		divisor = 16;
-	return port->uartclk/(baud * divisor);
+		mode = 16;
+	return port->uartclk/(mode * baud);
 }
 
 static void serial_omap_enable_ms(struct uart_port *port)
@@ -283,28 +298,40 @@
 static void serial_omap_stop_tx(struct uart_port *port)
 {
 	struct uart_omap_port *up = to_uart_omap_port(port);
-	struct circ_buf *xmit = &up->port.state->xmit;
 	int res;
 
 	pm_runtime_get_sync(up->dev);
 
-	/* handle rs485 */
+	/* Handle RS-485 */
 	if (up->rs485.flags & SER_RS485_ENABLED) {
-		/* do nothing if current tx not yet completed */
-		res = serial_in(up, UART_LSR) & UART_LSR_TEMT;
-		if (!res)
-			return;
-
-		/* if there's no more data to send, turn off rts */
-		if (uart_circ_empty(xmit)) {
-			/* if rts not already disabled */
+		if (up->scr & OMAP_UART_SCR_TX_EMPTY) {
+			/* THR interrupt is fired when both TX FIFO and TX
+			 * shift register are empty. This means there's nothing
+			 * left to transmit now, so make sure the THR interrupt
+			 * is fired when TX FIFO is below the trigger level,
+			 * disable THR interrupts and toggle the RS-485 GPIO
+			 * data direction pin if needed.
+			 */
+			up->scr &= ~OMAP_UART_SCR_TX_EMPTY;
+			serial_out(up, UART_OMAP_SCR, up->scr);
 			res = (up->rs485.flags & SER_RS485_RTS_AFTER_SEND) ? 1 : 0;
 			if (gpio_get_value(up->rts_gpio) != res) {
-				if (up->rs485.delay_rts_after_send > 0) {
+				if (up->rs485.delay_rts_after_send > 0)
 					mdelay(up->rs485.delay_rts_after_send);
-				}
 				gpio_set_value(up->rts_gpio, res);
 			}
+		} else {
+			/* We're asked to stop, but there's still stuff in the
+			 * UART FIFO, so make sure the THR interrupt is fired
+			 * when both TX FIFO and TX shift register are empty.
+			 * The next THR interrupt (if no transmission is started
+			 * in the meantime) will indicate the end of a
+			 * transmission. Therefore we _don't_ disable THR
+			 * interrupts in this situation.
+			 */
+			up->scr |= OMAP_UART_SCR_TX_EMPTY;
+			serial_out(up, UART_OMAP_SCR, up->scr);
+			return;
 		}
 	}
 
@@ -384,15 +411,18 @@
 
 	pm_runtime_get_sync(up->dev);
 
-	/* handle rs485 */
+	/* Handle RS-485 */
 	if (up->rs485.flags & SER_RS485_ENABLED) {
+		/* Fire THR interrupts when FIFO is below trigger level */
+		up->scr &= ~OMAP_UART_SCR_TX_EMPTY;
+		serial_out(up, UART_OMAP_SCR, up->scr);
+
 		/* if rts not already enabled */
 		res = (up->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0;
 		if (gpio_get_value(up->rts_gpio) != res) {
 			gpio_set_value(up->rts_gpio, res);
-			if (up->rs485.delay_rts_before_send > 0) {
+			if (up->rs485.delay_rts_before_send > 0)
 				mdelay(up->rs485.delay_rts_before_send);
-			}
 		}
 	}
 
@@ -699,6 +729,20 @@
 	if (retval)
 		return retval;
 
+	/* Optional wake-up IRQ */
+	if (up->wakeirq) {
+		retval = request_irq(up->wakeirq, serial_omap_irq,
+				     up->port.irqflags, up->name, up);
+		if (retval) {
+			free_irq(up->port.irq, up);
+			return retval;
+		}
+		disable_irq(up->wakeirq);
+	} else {
+		dev_info(up->port.dev, "no wakeirq for uart%d\n",
+			 up->port.line);
+	}
+
 	dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->port.line);
 
 	pm_runtime_get_sync(up->dev);
@@ -787,6 +831,8 @@
 	pm_runtime_mark_last_busy(up->dev);
 	pm_runtime_put_autosuspend(up->dev);
 	free_irq(up->port.irq, up);
+	if (up->wakeirq)
+		free_irq(up->wakeirq, up);
 }
 
 static void serial_omap_uart_qos_work(struct work_struct *work)
@@ -938,7 +984,7 @@
 	 */
 
 	/* Set receive FIFO threshold to 16 characters and
-	 * transmit FIFO threshold to 16 spaces
+	 * transmit FIFO threshold to 32 spaces
 	 */
 	up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK;
 	up->fcr &= ~OMAP_UART_FCR_TX_FIFO_TRIG_MASK;
@@ -1060,15 +1106,6 @@
 	dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line);
 }
 
-static int serial_omap_set_wake(struct uart_port *port, unsigned int state)
-{
-	struct uart_omap_port *up = to_uart_omap_port(port);
-
-	serial_omap_enable_wakeup(up, state);
-
-	return 0;
-}
-
 static void
 serial_omap_pm(struct uart_port *port, unsigned int state,
 	       unsigned int oldstate)
@@ -1353,6 +1390,15 @@
 	up->ier = mode;
 	serial_out(up, UART_IER, up->ier);
 
+	/* If RS-485 is disabled, make sure the THR interrupt is fired when
+	 * TX FIFO is below the trigger level.
+	 */
+	if (!(up->rs485.flags & SER_RS485_ENABLED) &&
+	    (up->scr & OMAP_UART_SCR_TX_EMPTY)) {
+		up->scr &= ~OMAP_UART_SCR_TX_EMPTY;
+		serial_out(up, UART_OMAP_SCR, up->scr);
+	}
+
 	spin_unlock_irqrestore(&up->port.lock, flags);
 	pm_runtime_mark_last_busy(up->dev);
 	pm_runtime_put_autosuspend(up->dev);
@@ -1401,7 +1447,6 @@
 	.shutdown	= serial_omap_shutdown,
 	.set_termios	= serial_omap_set_termios,
 	.pm		= serial_omap_pm,
-	.set_wake	= serial_omap_set_wake,
 	.type		= serial_omap_type,
 	.release_port	= serial_omap_release_port,
 	.request_port	= serial_omap_request_port,
@@ -1582,11 +1627,23 @@
 	struct uart_omap_port	*up;
 	struct resource		*mem, *irq;
 	struct omap_uart_port_info *omap_up_info = dev_get_platdata(&pdev->dev);
-	int ret;
+	int ret, uartirq = 0, wakeirq = 0;
 
+	/* The optional wakeirq may be specified in the board dts file */
 	if (pdev->dev.of_node) {
+		uartirq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+		if (!uartirq)
+			return -EPROBE_DEFER;
+		wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1);
 		omap_up_info = of_get_uart_port_info(&pdev->dev);
 		pdev->dev.platform_data = omap_up_info;
+	} else {
+		irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+		if (!irq) {
+			dev_err(&pdev->dev, "no irq resource?\n");
+			return -ENODEV;
+		}
+		uartirq = irq->start;
 	}
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1595,12 +1652,6 @@
 		return -ENODEV;
 	}
 
-	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!irq) {
-		dev_err(&pdev->dev, "no irq resource?\n");
-		return -ENODEV;
-	}
-
 	if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
 				pdev->dev.driver->name)) {
 		dev_err(&pdev->dev, "memory region already claimed\n");
@@ -1634,7 +1685,8 @@
 	up->port.dev = &pdev->dev;
 	up->port.type = PORT_OMAP;
 	up->port.iotype = UPIO_MEM;
-	up->port.irq = irq->start;
+	up->port.irq = uartirq;
+	up->wakeirq = wakeirq;
 
 	up->port.regshift = 2;
 	up->port.fifosize = 64;
@@ -1670,8 +1722,9 @@
 	up->port.uartclk = omap_up_info->uartclk;
 	if (!up->port.uartclk) {
 		up->port.uartclk = DEFAULT_CLK_SPEED;
-		dev_warn(&pdev->dev, "No clock speed specified: using default:"
-						"%d\n", DEFAULT_CLK_SPEED);
+		dev_warn(&pdev->dev,
+			 "No clock speed specified: using default: %d\n",
+			 DEFAULT_CLK_SPEED);
 	}
 
 	up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 44077c0..0aa2b52 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -1614,7 +1614,6 @@
 	.shutdown = pch_uart_shutdown,
 	.set_termios = pch_uart_set_termios,
 /*	.pm		= pch_uart_pm,		Not supported yet */
-/*	.set_wake	= pch_uart_set_wake,	Not supported yet */
 	.type = pch_uart_type,
 	.release_port = pch_uart_release_port,
 	.request_port = pch_uart_request_port,
@@ -1996,6 +1995,8 @@
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("Intel EG20T PCH UART PCI Driver");
+MODULE_DEVICE_TABLE(pci, pch_uart_pci_id);
+
 module_param(default_baud, uint, S_IRUGO);
 MODULE_PARM_DESC(default_baud,
                  "Default BAUD for initial driver state and console (default 9600)");
diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c
index f87f1a0..481b781 100644
--- a/drivers/tty/serial/pmac_zilog.c
+++ b/drivers/tty/serial/pmac_zilog.c
@@ -57,6 +57,8 @@
 #include <linux/bitops.h>
 #include <linux/sysrq.h>
 #include <linux/mutex.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <asm/sections.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -1072,7 +1074,7 @@
 		uap->curregs[5] |= Tx8;
 		uap->parity_mask = 0xff;
 		break;
-	};
+	}
 	uap->curregs[4] &= ~(SB_MASK);
 	if (cflag & CSTOPB)
 		uap->curregs[4] |= SB2;
diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c
index ba25722..753d452 100644
--- a/drivers/tty/serial/sa1100.c
+++ b/drivers/tty/serial/sa1100.c
@@ -647,7 +647,10 @@
 		sa1100_pops.set_mctrl = fns->set_mctrl;
 
 	sa1100_pops.pm       = fns->pm;
-	sa1100_pops.set_wake = fns->set_wake;
+	/*
+	 * FIXME: fns->set_wake is unused - this should be called from
+	 * the suspend() callback if device_may_wakeup(dev)) is set.
+	 */
 }
 
 void __init sa1100_register_uart(int idx, int port)
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index f3dfa19..c1af04d 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -407,7 +407,14 @@
 
 static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
-	/* todo - possibly remove AFC and do manual CTS */
+	unsigned int umcon = rd_regl(port, S3C2410_UMCON);
+
+	if (mctrl & TIOCM_RTS)
+		umcon |= S3C2410_UMCOM_RTS_LOW;
+	else
+		umcon &= ~S3C2410_UMCOM_RTS_LOW;
+
+	wr_regl(port, S3C2410_UMCON, umcon);
 }
 
 static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
@@ -774,8 +781,6 @@
 	if (termios->c_cflag & CSTOPB)
 		ulcon |= S3C2410_LCON_STOPB;
 
-	umcon = (termios->c_cflag & CRTSCTS) ? S3C2410_UMCOM_AFC : 0;
-
 	if (termios->c_cflag & PARENB) {
 		if (termios->c_cflag & PARODD)
 			ulcon |= S3C2410_LCON_PODD;
@@ -792,6 +797,15 @@
 
 	wr_regl(port, S3C2410_ULCON, ulcon);
 	wr_regl(port, S3C2410_UBRDIV, quot);
+
+	umcon = rd_regl(port, S3C2410_UMCON);
+	if (termios->c_cflag & CRTSCTS) {
+		umcon |= S3C2410_UMCOM_AFC;
+		/* Disable RTS when RX FIFO contains 63 bytes */
+		umcon &= ~S3C2412_UMCON_AFC_8;
+	} else {
+		umcon &= ~S3C2410_UMCOM_AFC;
+	}
 	wr_regl(port, S3C2410_UMCON, umcon);
 
 	if (ourport->info->has_divslot)
@@ -1254,7 +1268,7 @@
 	ourport->baudclk = ERR_PTR(-EINVAL);
 	ourport->info = ourport->drv_data->info;
 	ourport->cfg = (dev_get_platdata(&pdev->dev)) ?
-			(struct s3c2410_uartcfg *)dev_get_platdata(&pdev->dev) :
+			dev_get_platdata(&pdev->dev) :
 			ourport->drv_data->def_cfg;
 
 	ourport->port.fifosize = (ourport->info->fifosize) ?
diff --git a/drivers/tty/serial/samsung.h b/drivers/tty/serial/samsung.h
index aaa617a..8827e54 100644
--- a/drivers/tty/serial/samsung.h
+++ b/drivers/tty/serial/samsung.h
@@ -63,7 +63,7 @@
 
 /* conversion functions */
 
-#define s3c24xx_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev)
+#define s3c24xx_dev_to_port(__dev) dev_get_drvdata(__dev)
 
 /* register access controls */
 
diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c
index 49e9bbf..a447f71 100644
--- a/drivers/tty/serial/sccnxp.c
+++ b/drivers/tty/serial/sccnxp.c
@@ -986,6 +986,7 @@
 		return 0;
 	}
 
+	uart_unregister_driver(&s->uart);
 err_out:
 	if (!IS_ERR(s->regulator))
 		return regulator_disable(s->regulator);
diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c
index 0489a2b..dfe79cc 100644
--- a/drivers/tty/serial/serial-tegra.c
+++ b/drivers/tty/serial/serial-tegra.c
@@ -1018,7 +1018,7 @@
 		goto fail_hw_init;
 	}
 
-	ret = request_irq(u->irq, tegra_uart_isr, IRQF_DISABLED,
+	ret = request_irq(u->irq, tegra_uart_isr, 0,
 				dev_name(u->dev), tup);
 	if (ret < 0) {
 		dev_err(u->dev, "Failed to register ISR for IRQ %d\n", u->irq);
diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c
index 440a962..90a080b 100644
--- a/drivers/tty/serial/serial_txx9.c
+++ b/drivers/tty/serial/serial_txx9.c
@@ -1220,8 +1220,6 @@
 {
 	struct uart_txx9_port *up = pci_get_drvdata(dev);
 
-	pci_set_drvdata(dev, NULL);
-
 	if (up) {
 		serial_txx9_unregister_port(up->port.line);
 		pci_disable_device(dev);
diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c
index 61c1ad0..f186a8f 100644
--- a/drivers/tty/serial/sirfsoc_uart.c
+++ b/drivers/tty/serial/sirfsoc_uart.c
@@ -529,7 +529,7 @@
 	while (sirfport->rx_completed != sirfport->rx_issued) {
 		sirfsoc_uart_insert_rx_buf_to_tty(sirfport,
 					SIRFSOC_RX_DMA_BUF_SIZE);
-		sirfsoc_rx_submit_one_dma_desc(port, sirfport->rx_completed++);
+		sirfport->rx_completed++;
 		sirfport->rx_completed %= SIRFSOC_RX_LOOP_BUF_CNT;
 	}
 	count = CIRC_CNT(sirfport->rx_dma_items[sirfport->rx_issued].xmit.head,
@@ -706,12 +706,19 @@
 {
 	struct sirfsoc_uart_port *sirfport = (struct sirfsoc_uart_port *)param;
 	struct uart_port *port = &sirfport->port;
+	struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
+	struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
 	unsigned long flags;
 	spin_lock_irqsave(&sirfport->rx_lock, flags);
 	while (sirfport->rx_completed != sirfport->rx_issued) {
 		sirfsoc_uart_insert_rx_buf_to_tty(sirfport,
 					SIRFSOC_RX_DMA_BUF_SIZE);
-		sirfsoc_rx_submit_one_dma_desc(port, sirfport->rx_completed++);
+		if (rd_regl(port, ureg->sirfsoc_int_en_reg) &
+				uint_en->sirfsoc_rx_timeout_en)
+			sirfsoc_rx_submit_one_dma_desc(port,
+					sirfport->rx_completed++);
+		else
+			sirfport->rx_completed++;
 		sirfport->rx_completed %= SIRFSOC_RX_LOOP_BUF_CNT;
 	}
 	spin_unlock_irqrestore(&sirfport->rx_lock, flags);
diff --git a/drivers/tty/serial/sirfsoc_uart.h b/drivers/tty/serial/sirfsoc_uart.h
index fb8d0a0..b7d679c 100644
--- a/drivers/tty/serial/sirfsoc_uart.h
+++ b/drivers/tty/serial/sirfsoc_uart.h
@@ -368,15 +368,6 @@
 #define SIRFSOC_UART_NR				6
 #define SIRFSOC_PORT_TYPE			0xa5
 
-/* Baud Rate Calculation */
-#define SIRF_MIN_SAMPLE_DIV			0xf
-#define SIRF_MAX_SAMPLE_DIV			0x3f
-#define SIRF_IOCLK_DIV_MAX			0xffff
-#define SIRF_SAMPLE_DIV_SHIFT			16
-#define SIRF_IOCLK_DIV_MASK			0xffff
-#define SIRF_SAMPLE_DIV_MASK			0x3f0000
-#define SIRF_BAUD_RATE_SUPPORT_NR		18
-
 /* Uart Common Use Macro*/
 #define SIRFSOC_RX_DMA_BUF_SIZE	256
 #define BYTES_TO_ALIGN(dma_addr)	((unsigned long)(dma_addr) & 0x3)
@@ -453,9 +444,6 @@
 	int				rx_issued;
 };
 
-/* Hardware Flow Control */
-#define SIRFUART_AFC_CTRL_RX_THD	0x70
-
 /* Register Access Control */
 #define portaddr(port, reg)		((port)->membase + (reg))
 #define rd_regb(port, reg)		(__raw_readb(portaddr(port, reg)))
diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c
index 5d6136b2..380fb53 100644
--- a/drivers/tty/serial/sunsab.c
+++ b/drivers/tty/serial/sunsab.c
@@ -894,7 +894,7 @@
 	case B115200: baud = 115200; break;
 	case B230400: baud = 230400; break;
 	case B460800: baud = 460800; break;
-	};
+	}
 
 	/*
 	 * Temporary fix.
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
index 699cc1b..db79b76 100644
--- a/drivers/tty/serial/sunsu.c
+++ b/drivers/tty/serial/sunsu.c
@@ -522,7 +522,7 @@
 				serio_interrupt(&up->serio, ch, 0);
 #endif
 				break;
-			};
+			}
 		}
 	} while (serial_in(up, UART_LSR) & UART_LSR_DR);
 }
diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c
index 135a152..45a8c6a 100644
--- a/drivers/tty/serial/sunzilog.c
+++ b/drivers/tty/serial/sunzilog.c
@@ -319,7 +319,7 @@
 				serio_interrupt(&up->serio, ch, 0);
 #endif
 			break;
-		};
+		}
 	}
 }
 
@@ -897,7 +897,7 @@
 		up->curregs[R5] |= Tx8;
 		up->parity_mask = 0xff;
 		break;
-	};
+	}
 	up->curregs[R4] &= ~0x0c;
 	if (cflag & CSTOPB)
 		up->curregs[R4] |= SB2;
@@ -1239,7 +1239,7 @@
 	default: case B9600: baud = 9600; break;
 	case B19200: baud = 19200; break;
 	case B38400: baud = 38400; break;
-	};
+	}
 
 	brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
 
diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c
index 8831748..d569ca5 100644
--- a/drivers/tty/serial/ucc_uart.c
+++ b/drivers/tty/serial/ucc_uart.c
@@ -25,6 +25,8 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/dma-mapping.h>
 
@@ -269,7 +271,7 @@
 			return 1;
 
 		bdp++;
-	};
+	}
 }
 
 /*
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c
index 93b697a..15ad6fc 100644
--- a/drivers/tty/serial/vt8500_serial.c
+++ b/drivers/tty/serial/vt8500_serial.c
@@ -561,12 +561,13 @@
 	if (!mmres || !irqres)
 		return -ENODEV;
 
-	if (np)
+	if (np) {
 		port = of_alias_get_id(np, "serial");
 		if (port >= VT8500_MAX_PORTS)
 			port = -1;
-	else
+	} else {
 		port = -1;
+	}
 
 	if (port < 0) {
 		/* calculate the port id */
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index 7e4150a..e46e9f3 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -1,7 +1,7 @@
 /*
  * Xilinx PS UART driver
  *
- * 2011 (c) Xilinx Inc.
+ * 2011 - 2013 (C) Xilinx Inc.
  *
  * This program is free software; you can redistribute it
  * and/or modify it under the terms of the GNU General Public
@@ -11,13 +11,17 @@
  *
  */
 
+#if defined(CONFIG_SERIAL_XILINX_PS_UART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
 #include <linux/platform_device.h>
 #include <linux/serial.h>
+#include <linux/console.h>
 #include <linux/serial_core.h>
 #include <linux/slab.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
-#include <linux/console.h>
 #include <linux/clk.h>
 #include <linux/irq.h>
 #include <linux/io.h>
@@ -29,12 +33,22 @@
 #define XUARTPS_MAJOR		0	/* use dynamic node allocation */
 #define XUARTPS_MINOR		0	/* works best with devtmpfs */
 #define XUARTPS_NR_PORTS	2
-#define XUARTPS_FIFO_SIZE	16	/* FIFO size */
+#define XUARTPS_FIFO_SIZE	64	/* FIFO size */
 #define XUARTPS_REGISTER_SPACE	0xFFF
 
 #define xuartps_readl(offset)		ioread32(port->membase + offset)
 #define xuartps_writel(val, offset)	iowrite32(val, port->membase + offset)
 
+/* Rx Trigger level */
+static int rx_trigger_level = 56;
+module_param(rx_trigger_level, uint, S_IRUGO);
+MODULE_PARM_DESC(rx_trigger_level, "Rx trigger level, 1-63 bytes");
+
+/* Rx Timeout */
+static int rx_timeout = 10;
+module_param(rx_timeout, uint, S_IRUGO);
+MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255");
+
 /********************************Register Map********************************/
 /** UART
  *
@@ -128,6 +142,9 @@
 #define XUARTPS_IXR_RXEMPTY	0x00000002 /* RX FIFO empty interrupt. */
 #define XUARTPS_IXR_MASK	0x00001FFF /* Valid bit mask */
 
+/* Goes in read_status_mask for break detection as the HW doesn't do it*/
+#define XUARTPS_IXR_BRK		0x80000000
+
 /** Channel Status Register
  *
  * The channel status register (CSR) is provided to enable the control logic
@@ -139,15 +156,27 @@
 #define XUARTPS_SR_TXFULL	0x00000010 /* TX FIFO full */
 #define XUARTPS_SR_RXTRIG	0x00000001 /* Rx Trigger */
 
+/* baud dividers min/max values */
+#define XUARTPS_BDIV_MIN	4
+#define XUARTPS_BDIV_MAX	255
+#define XUARTPS_CD_MAX		65535
+
 /**
  * struct xuartps - device data
- * @refclk	Reference clock
- * @aperclk	APB clock
+ * @port		Pointer to the UART port
+ * @refclk		Reference clock
+ * @aperclk		APB clock
+ * @baud		Current baud rate
+ * @clk_rate_change_nb	Notifier block for clock changes
  */
 struct xuartps {
+	struct uart_port	*port;
 	struct clk		*refclk;
 	struct clk		*aperclk;
+	unsigned int		baud;
+	struct notifier_block	clk_rate_change_nb;
 };
+#define to_xuartps(_nb) container_of(_nb, struct xuartps, clk_rate_change_nb);
 
 /**
  * xuartps_isr - Interrupt handler
@@ -171,6 +200,23 @@
 	 */
 	isrstatus = xuartps_readl(XUARTPS_ISR_OFFSET);
 
+	/*
+	 * There is no hardware break detection, so we interpret framing
+	 * error with all-zeros data as a break sequence. Most of the time,
+	 * there's another non-zero byte at the end of the sequence.
+	 */
+
+	if (isrstatus & XUARTPS_IXR_FRAMING) {
+		while (!(xuartps_readl(XUARTPS_SR_OFFSET) &
+					XUARTPS_SR_RXEMPTY)) {
+			if (!xuartps_readl(XUARTPS_FIFO_OFFSET)) {
+				port->read_status_mask |= XUARTPS_IXR_BRK;
+				isrstatus &= ~XUARTPS_IXR_FRAMING;
+			}
+		}
+		xuartps_writel(XUARTPS_IXR_FRAMING, XUARTPS_ISR_OFFSET);
+	}
+
 	/* drop byte with parity error if IGNPAR specified */
 	if (isrstatus & port->ignore_status_mask & XUARTPS_IXR_PARITY)
 		isrstatus &= ~(XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT);
@@ -184,6 +230,30 @@
 		while ((xuartps_readl(XUARTPS_SR_OFFSET) &
 			XUARTPS_SR_RXEMPTY) != XUARTPS_SR_RXEMPTY) {
 			data = xuartps_readl(XUARTPS_FIFO_OFFSET);
+
+			/* Non-NULL byte after BREAK is garbage (99%) */
+			if (data && (port->read_status_mask &
+						XUARTPS_IXR_BRK)) {
+				port->read_status_mask &= ~XUARTPS_IXR_BRK;
+				port->icount.brk++;
+				if (uart_handle_break(port))
+					continue;
+			}
+
+			/*
+			 * uart_handle_sysrq_char() doesn't work if
+			 * spinlocked, for some reason
+			 */
+			 if (port->sysrq) {
+				spin_unlock(&port->lock);
+				if (uart_handle_sysrq_char(port,
+							(unsigned char)data)) {
+					spin_lock(&port->lock);
+					continue;
+				}
+				spin_lock(&port->lock);
+			}
+
 			port->icount.rx++;
 
 			if (isrstatus & XUARTPS_IXR_PARITY) {
@@ -247,63 +317,196 @@
 }
 
 /**
- * xuartps_set_baud_rate - Calculate and set the baud rate
- * @port: Handle to the uart port structure
- * @baud: Baud rate to set
- *
+ * xuartps_calc_baud_divs - Calculate baud rate divisors
+ * @clk: UART module input clock
+ * @baud: Desired baud rate
+ * @rbdiv: BDIV value (return value)
+ * @rcd: CD value (return value)
+ * @div8: Value for clk_sel bit in mod (return value)
  * Returns baud rate, requested baud when possible, or actual baud when there
- *	was too much error
- **/
-static unsigned int xuartps_set_baud_rate(struct uart_port *port,
-						unsigned int baud)
+ *	was too much error, zero if no valid divisors are found.
+ *
+ * Formula to obtain baud rate is
+ *	baud_tx/rx rate = clk/CD * (BDIV + 1)
+ *	input_clk = (Uart User Defined Clock or Apb Clock)
+ *		depends on UCLKEN in MR Reg
+ *	clk = input_clk or input_clk/8;
+ *		depends on CLKS in MR reg
+ *	CD and BDIV depends on values in
+ *			baud rate generate register
+ *			baud rate clock divisor register
+ */
+static unsigned int xuartps_calc_baud_divs(unsigned int clk, unsigned int baud,
+		u32 *rbdiv, u32 *rcd, int *div8)
 {
-	unsigned int sel_clk;
-	unsigned int calc_baud = 0;
-	unsigned int brgr_val, brdiv_val;
+	u32 cd, bdiv;
+	unsigned int calc_baud;
+	unsigned int bestbaud = 0;
 	unsigned int bauderror;
+	unsigned int besterror = ~0;
 
-	/* Formula to obtain baud rate is
-	 *	baud_tx/rx rate = sel_clk/CD * (BDIV + 1)
-	 *	input_clk = (Uart User Defined Clock or Apb Clock)
-	 *		depends on UCLKEN in MR Reg
-	 *	sel_clk = input_clk or input_clk/8;
-	 *		depends on CLKS in MR reg
-	 *	CD and BDIV depends on values in
-	 *			baud rate generate register
-	 *			baud rate clock divisor register
-	 */
-	sel_clk = port->uartclk;
-	if (xuartps_readl(XUARTPS_MR_OFFSET) & XUARTPS_MR_CLKSEL)
-		sel_clk = sel_clk / 8;
+	if (baud < clk / ((XUARTPS_BDIV_MAX + 1) * XUARTPS_CD_MAX)) {
+		*div8 = 1;
+		clk /= 8;
+	} else {
+		*div8 = 0;
+	}
 
-	/* Find the best values for baud generation */
-	for (brdiv_val = 4; brdiv_val < 255; brdiv_val++) {
-
-		brgr_val = sel_clk / (baud * (brdiv_val + 1));
-		if (brgr_val < 2 || brgr_val > 65535)
+	for (bdiv = XUARTPS_BDIV_MIN; bdiv <= XUARTPS_BDIV_MAX; bdiv++) {
+		cd = DIV_ROUND_CLOSEST(clk, baud * (bdiv + 1));
+		if (cd < 1 || cd > XUARTPS_CD_MAX)
 			continue;
 
-		calc_baud = sel_clk / (brgr_val * (brdiv_val + 1));
+		calc_baud = clk / (cd * (bdiv + 1));
 
 		if (baud > calc_baud)
 			bauderror = baud - calc_baud;
 		else
 			bauderror = calc_baud - baud;
 
-		/* use the values when percent error is acceptable */
-		if (((bauderror * 100) / baud) < 3) {
-			calc_baud = baud;
-			break;
+		if (besterror > bauderror) {
+			*rbdiv = bdiv;
+			*rcd = cd;
+			bestbaud = calc_baud;
+			besterror = bauderror;
 		}
 	}
+	/* use the values when percent error is acceptable */
+	if (((besterror * 100) / baud) < 3)
+		bestbaud = baud;
 
-	/* Set the values for the new baud rate */
-	xuartps_writel(brgr_val, XUARTPS_BAUDGEN_OFFSET);
-	xuartps_writel(brdiv_val, XUARTPS_BAUDDIV_OFFSET);
+	return bestbaud;
+}
+
+/**
+ * xuartps_set_baud_rate - Calculate and set the baud rate
+ * @port: Handle to the uart port structure
+ * @baud: Baud rate to set
+ * Returns baud rate, requested baud when possible, or actual baud when there
+ *	   was too much error, zero if no valid divisors are found.
+ */
+static unsigned int xuartps_set_baud_rate(struct uart_port *port,
+		unsigned int baud)
+{
+	unsigned int calc_baud;
+	u32 cd = 0, bdiv = 0;
+	u32 mreg;
+	int div8;
+	struct xuartps *xuartps = port->private_data;
+
+	calc_baud = xuartps_calc_baud_divs(port->uartclk, baud, &bdiv, &cd,
+			&div8);
+
+	/* Write new divisors to hardware */
+	mreg = xuartps_readl(XUARTPS_MR_OFFSET);
+	if (div8)
+		mreg |= XUARTPS_MR_CLKSEL;
+	else
+		mreg &= ~XUARTPS_MR_CLKSEL;
+	xuartps_writel(mreg, XUARTPS_MR_OFFSET);
+	xuartps_writel(cd, XUARTPS_BAUDGEN_OFFSET);
+	xuartps_writel(bdiv, XUARTPS_BAUDDIV_OFFSET);
+	xuartps->baud = baud;
 
 	return calc_baud;
 }
 
+#ifdef CONFIG_COMMON_CLK
+/**
+ * xuartps_clk_notitifer_cb - Clock notifier callback
+ * @nb:		Notifier block
+ * @event:	Notify event
+ * @data:	Notifier data
+ * Returns NOTIFY_OK on success, NOTIFY_BAD on error.
+ */
+static int xuartps_clk_notifier_cb(struct notifier_block *nb,
+		unsigned long event, void *data)
+{
+	u32 ctrl_reg;
+	struct uart_port *port;
+	int locked = 0;
+	struct clk_notifier_data *ndata = data;
+	unsigned long flags = 0;
+	struct xuartps *xuartps = to_xuartps(nb);
+
+	port = xuartps->port;
+	if (port->suspended)
+		return NOTIFY_OK;
+
+	switch (event) {
+	case PRE_RATE_CHANGE:
+	{
+		u32 bdiv;
+		u32 cd;
+		int div8;
+
+		/*
+		 * Find out if current baud-rate can be achieved with new clock
+		 * frequency.
+		 */
+		if (!xuartps_calc_baud_divs(ndata->new_rate, xuartps->baud,
+					&bdiv, &cd, &div8))
+			return NOTIFY_BAD;
+
+		spin_lock_irqsave(&xuartps->port->lock, flags);
+
+		/* Disable the TX and RX to set baud rate */
+		xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) |
+				(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS),
+				XUARTPS_CR_OFFSET);
+
+		spin_unlock_irqrestore(&xuartps->port->lock, flags);
+
+		return NOTIFY_OK;
+	}
+	case POST_RATE_CHANGE:
+		/*
+		 * Set clk dividers to generate correct baud with new clock
+		 * frequency.
+		 */
+
+		spin_lock_irqsave(&xuartps->port->lock, flags);
+
+		locked = 1;
+		port->uartclk = ndata->new_rate;
+
+		xuartps->baud = xuartps_set_baud_rate(xuartps->port,
+				xuartps->baud);
+		/* fall through */
+	case ABORT_RATE_CHANGE:
+		if (!locked)
+			spin_lock_irqsave(&xuartps->port->lock, flags);
+
+		/* Set TX/RX Reset */
+		xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) |
+				(XUARTPS_CR_TXRST | XUARTPS_CR_RXRST),
+				XUARTPS_CR_OFFSET);
+
+		while (xuartps_readl(XUARTPS_CR_OFFSET) &
+				(XUARTPS_CR_TXRST | XUARTPS_CR_RXRST))
+			cpu_relax();
+
+		/*
+		 * Clear the RX disable and TX disable bits and then set the TX
+		 * enable bit and RX enable bit to enable the transmitter and
+		 * receiver.
+		 */
+		xuartps_writel(rx_timeout, XUARTPS_RXTOUT_OFFSET);
+		ctrl_reg = xuartps_readl(XUARTPS_CR_OFFSET);
+		xuartps_writel(
+			(ctrl_reg & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS)) |
+			(XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN),
+			XUARTPS_CR_OFFSET);
+
+		spin_unlock_irqrestore(&xuartps->port->lock, flags);
+
+		return NOTIFY_OK;
+	default:
+		return NOTIFY_DONE;
+	}
+}
+#endif
+
 /*----------------------Uart Operations---------------------------*/
 
 /**
@@ -346,7 +549,7 @@
 		port->state->xmit.tail = (port->state->xmit.tail + 1) &
 					(UART_XMIT_SIZE - 1);
 	}
-
+	xuartps_writel(XUARTPS_IXR_TXEMPTY, XUARTPS_ISR_OFFSET);
 	/* Enable the TX Empty interrupt */
 	xuartps_writel(XUARTPS_IXR_TXEMPTY, XUARTPS_IER_OFFSET);
 
@@ -437,7 +640,7 @@
 				struct ktermios *termios, struct ktermios *old)
 {
 	unsigned int cval = 0;
-	unsigned int baud;
+	unsigned int baud, minbaud, maxbaud;
 	unsigned long flags;
 	unsigned int ctrl_reg, mode_reg;
 
@@ -454,8 +657,14 @@
 			(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS),
 			XUARTPS_CR_OFFSET);
 
-	/* Min baud rate = 6bps and Max Baud Rate is 10Mbps for 100Mhz clk */
-	baud = uart_get_baud_rate(port, termios, old, 0, 10000000);
+	/*
+	 * Min baud rate = 6bps and Max Baud Rate is 10Mbps for 100Mhz clk
+	 * min and max baud should be calculated here based on port->uartclk.
+	 * this way we get a valid baud and can safely call set_baud()
+	 */
+	minbaud = port->uartclk / ((XUARTPS_BDIV_MAX + 1) * XUARTPS_CD_MAX * 8);
+	maxbaud = port->uartclk / (XUARTPS_BDIV_MIN + 1);
+	baud = uart_get_baud_rate(port, termios, old, minbaud, maxbaud);
 	baud = xuartps_set_baud_rate(port, baud);
 	if (tty_termios_baud_rate(termios))
 		tty_termios_encode_baud_rate(termios, baud, baud);
@@ -480,7 +689,7 @@
 			| (XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN),
 			XUARTPS_CR_OFFSET);
 
-	xuartps_writel(10, XUARTPS_RXTOUT_OFFSET);
+	xuartps_writel(rx_timeout, XUARTPS_RXTOUT_OFFSET);
 
 	port->read_status_mask = XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXTRIG |
 			XUARTPS_IXR_OVERRUN | XUARTPS_IXR_TOUT;
@@ -531,13 +740,17 @@
 				cval |= XUARTPS_MR_PARITY_MARK;
 			else
 				cval |= XUARTPS_MR_PARITY_SPACE;
-		} else if (termios->c_cflag & PARODD)
+		} else {
+			if (termios->c_cflag & PARODD)
 				cval |= XUARTPS_MR_PARITY_ODD;
 			else
 				cval |= XUARTPS_MR_PARITY_EVEN;
-	} else
+		}
+	} else {
 		cval |= XUARTPS_MR_PARITY_NONE;
-	xuartps_writel(cval , XUARTPS_MR_OFFSET);
+	}
+	cval |= mode_reg & 1;
+	xuartps_writel(cval, XUARTPS_MR_OFFSET);
 
 	spin_unlock_irqrestore(&port->lock, flags);
 }
@@ -583,11 +796,17 @@
 		| XUARTPS_MR_PARITY_NONE | XUARTPS_MR_CHARLEN_8_BIT,
 		 XUARTPS_MR_OFFSET);
 
-	/* Set the RX FIFO Trigger level to 14 assuming FIFO size as 16 */
-	xuartps_writel(14, XUARTPS_RXWM_OFFSET);
+	/*
+	 * Set the RX FIFO Trigger level to use most of the FIFO, but it
+	 * can be tuned with a module parameter
+	 */
+	xuartps_writel(rx_trigger_level, XUARTPS_RXWM_OFFSET);
 
-	/* Receive Timeout register is enabled with value of 10 */
-	xuartps_writel(10, XUARTPS_RXTOUT_OFFSET);
+	/*
+	 * Receive Timeout register is enabled but it
+	 * can be tuned with a module parameter
+	 */
+	xuartps_writel(rx_timeout, XUARTPS_RXTOUT_OFFSET);
 
 	/* Clear out any pending interrupts before enabling them */
 	xuartps_writel(xuartps_readl(XUARTPS_ISR_OFFSET), XUARTPS_ISR_OFFSET);
@@ -727,6 +946,54 @@
 	/* N/A */
 }
 
+#ifdef CONFIG_CONSOLE_POLL
+static int xuartps_poll_get_char(struct uart_port *port)
+{
+	u32 imr;
+	int c;
+
+	/* Disable all interrupts */
+	imr = xuartps_readl(XUARTPS_IMR_OFFSET);
+	xuartps_writel(imr, XUARTPS_IDR_OFFSET);
+
+	/* Check if FIFO is empty */
+	if (xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_RXEMPTY)
+		c = NO_POLL_CHAR;
+	else /* Read a character */
+		c = (unsigned char) xuartps_readl(XUARTPS_FIFO_OFFSET);
+
+	/* Enable interrupts */
+	xuartps_writel(imr, XUARTPS_IER_OFFSET);
+
+	return c;
+}
+
+static void xuartps_poll_put_char(struct uart_port *port, unsigned char c)
+{
+	u32 imr;
+
+	/* Disable all interrupts */
+	imr = xuartps_readl(XUARTPS_IMR_OFFSET);
+	xuartps_writel(imr, XUARTPS_IDR_OFFSET);
+
+	/* Wait until FIFO is empty */
+	while (!(xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_TXEMPTY))
+		cpu_relax();
+
+	/* Write a character */
+	xuartps_writel(c, XUARTPS_FIFO_OFFSET);
+
+	/* Wait until FIFO is empty */
+	while (!(xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_TXEMPTY))
+		cpu_relax();
+
+	/* Enable interrupts */
+	xuartps_writel(imr, XUARTPS_IER_OFFSET);
+
+	return;
+}
+#endif
+
 /** The UART operations structure
  */
 static struct uart_ops xuartps_ops = {
@@ -759,6 +1026,10 @@
 	.config_port	= xuartps_config_port,	/* Configure when driver
 						 * adds a xuartps port
 						 */
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_get_char	= xuartps_poll_get_char,
+	.poll_put_char	= xuartps_poll_put_char,
+#endif
 };
 
 static struct uart_port xuartps_port[2];
@@ -837,7 +1108,7 @@
 {
 	struct uart_port *port = &xuartps_port[co->index];
 	unsigned long flags;
-	unsigned int imr;
+	unsigned int imr, ctrl;
 	int locked = 1;
 
 	if (oops_in_progress)
@@ -849,9 +1120,19 @@
 	imr = xuartps_readl(XUARTPS_IMR_OFFSET);
 	xuartps_writel(imr, XUARTPS_IDR_OFFSET);
 
+	/*
+	 * Make sure that the tx part is enabled. Set the TX enable bit and
+	 * clear the TX disable bit to enable the transmitter.
+	 */
+	ctrl = xuartps_readl(XUARTPS_CR_OFFSET);
+	xuartps_writel((ctrl & ~XUARTPS_CR_TX_DIS) | XUARTPS_CR_TX_EN,
+		XUARTPS_CR_OFFSET);
+
 	uart_console_write(port, s, count, xuartps_console_putchar);
 	xuartps_console_wait_tx(port);
 
+	xuartps_writel(ctrl, XUARTPS_CR_OFFSET);
+
 	/* restore interrupt state, it seems like there may be a h/w bug
 	 * in that the interrupt enable register should not need to be
 	 * written based on the data sheet
@@ -933,6 +1214,119 @@
 #endif
 };
 
+#ifdef CONFIG_PM_SLEEP
+/**
+ * xuartps_suspend - suspend event
+ * @device: Pointer to the device structure
+ *
+ * Returns 0
+ */
+static int xuartps_suspend(struct device *device)
+{
+	struct uart_port *port = dev_get_drvdata(device);
+	struct tty_struct *tty;
+	struct device *tty_dev;
+	int may_wake = 0;
+
+	/* Get the tty which could be NULL so don't assume it's valid */
+	tty = tty_port_tty_get(&port->state->port);
+	if (tty) {
+		tty_dev = tty->dev;
+		may_wake = device_may_wakeup(tty_dev);
+		tty_kref_put(tty);
+	}
+
+	/*
+	 * Call the API provided in serial_core.c file which handles
+	 * the suspend.
+	 */
+	uart_suspend_port(&xuartps_uart_driver, port);
+	if (console_suspend_enabled && !may_wake) {
+		struct xuartps *xuartps = port->private_data;
+
+		clk_disable(xuartps->refclk);
+		clk_disable(xuartps->aperclk);
+	} else {
+		unsigned long flags = 0;
+
+		spin_lock_irqsave(&port->lock, flags);
+		/* Empty the receive FIFO 1st before making changes */
+		while (!(xuartps_readl(XUARTPS_SR_OFFSET) & XUARTPS_SR_RXEMPTY))
+			xuartps_readl(XUARTPS_FIFO_OFFSET);
+		/* set RX trigger level to 1 */
+		xuartps_writel(1, XUARTPS_RXWM_OFFSET);
+		/* disable RX timeout interrups */
+		xuartps_writel(XUARTPS_IXR_TOUT, XUARTPS_IDR_OFFSET);
+		spin_unlock_irqrestore(&port->lock, flags);
+	}
+
+	return 0;
+}
+
+/**
+ * xuartps_resume - Resume after a previous suspend
+ * @device: Pointer to the device structure
+ *
+ * Returns 0
+ */
+static int xuartps_resume(struct device *device)
+{
+	struct uart_port *port = dev_get_drvdata(device);
+	unsigned long flags = 0;
+	u32 ctrl_reg;
+	struct tty_struct *tty;
+	struct device *tty_dev;
+	int may_wake = 0;
+
+	/* Get the tty which could be NULL so don't assume it's valid */
+	tty = tty_port_tty_get(&port->state->port);
+	if (tty) {
+		tty_dev = tty->dev;
+		may_wake = device_may_wakeup(tty_dev);
+		tty_kref_put(tty);
+	}
+
+	if (console_suspend_enabled && !may_wake) {
+		struct xuartps *xuartps = port->private_data;
+
+		clk_enable(xuartps->aperclk);
+		clk_enable(xuartps->refclk);
+
+		spin_lock_irqsave(&port->lock, flags);
+
+		/* Set TX/RX Reset */
+		xuartps_writel(xuartps_readl(XUARTPS_CR_OFFSET) |
+				(XUARTPS_CR_TXRST | XUARTPS_CR_RXRST),
+				XUARTPS_CR_OFFSET);
+		while (xuartps_readl(XUARTPS_CR_OFFSET) &
+				(XUARTPS_CR_TXRST | XUARTPS_CR_RXRST))
+			cpu_relax();
+
+		/* restore rx timeout value */
+		xuartps_writel(rx_timeout, XUARTPS_RXTOUT_OFFSET);
+		/* Enable Tx/Rx */
+		ctrl_reg = xuartps_readl(XUARTPS_CR_OFFSET);
+		xuartps_writel(
+			(ctrl_reg & ~(XUARTPS_CR_TX_DIS | XUARTPS_CR_RX_DIS)) |
+			(XUARTPS_CR_TX_EN | XUARTPS_CR_RX_EN),
+			XUARTPS_CR_OFFSET);
+
+		spin_unlock_irqrestore(&port->lock, flags);
+	} else {
+		spin_lock_irqsave(&port->lock, flags);
+		/* restore original rx trigger level */
+		xuartps_writel(rx_trigger_level, XUARTPS_RXWM_OFFSET);
+		/* enable RX timeout interrupt */
+		xuartps_writel(XUARTPS_IXR_TOUT, XUARTPS_IER_OFFSET);
+		spin_unlock_irqrestore(&port->lock, flags);
+	}
+
+	return uart_resume_port(&xuartps_uart_driver, port);
+}
+#endif /* ! CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(xuartps_dev_pm_ops, xuartps_suspend, xuartps_resume);
+
 /* ---------------------------------------------------------------------
  * Platform bus binding
  */
@@ -949,27 +1343,26 @@
 	struct resource *res, *res2;
 	struct xuartps *xuartps_data;
 
-	xuartps_data = kzalloc(sizeof(*xuartps_data), GFP_KERNEL);
+	xuartps_data = devm_kzalloc(&pdev->dev, sizeof(*xuartps_data),
+			GFP_KERNEL);
 	if (!xuartps_data)
 		return -ENOMEM;
 
-	xuartps_data->aperclk = clk_get(&pdev->dev, "aper_clk");
+	xuartps_data->aperclk = devm_clk_get(&pdev->dev, "aper_clk");
 	if (IS_ERR(xuartps_data->aperclk)) {
 		dev_err(&pdev->dev, "aper_clk clock not found.\n");
-		rc = PTR_ERR(xuartps_data->aperclk);
-		goto err_out_free;
+		return PTR_ERR(xuartps_data->aperclk);
 	}
-	xuartps_data->refclk = clk_get(&pdev->dev, "ref_clk");
+	xuartps_data->refclk = devm_clk_get(&pdev->dev, "ref_clk");
 	if (IS_ERR(xuartps_data->refclk)) {
 		dev_err(&pdev->dev, "ref_clk clock not found.\n");
-		rc = PTR_ERR(xuartps_data->refclk);
-		goto err_out_clk_put_aper;
+		return PTR_ERR(xuartps_data->refclk);
 	}
 
 	rc = clk_prepare_enable(xuartps_data->aperclk);
 	if (rc) {
 		dev_err(&pdev->dev, "Unable to enable APER clock.\n");
-		goto err_out_clk_put;
+		return rc;
 	}
 	rc = clk_prepare_enable(xuartps_data->refclk);
 	if (rc) {
@@ -989,13 +1382,21 @@
 		goto err_out_clk_disable;
 	}
 
+#ifdef CONFIG_COMMON_CLK
+	xuartps_data->clk_rate_change_nb.notifier_call =
+			xuartps_clk_notifier_cb;
+	if (clk_notifier_register(xuartps_data->refclk,
+				&xuartps_data->clk_rate_change_nb))
+		dev_warn(&pdev->dev, "Unable to register clock notifier.\n");
+#endif
+
 	/* Initialize the port structure */
 	port = xuartps_get_port();
 
 	if (!port) {
 		dev_err(&pdev->dev, "Cannot get uart_port structure\n");
 		rc = -ENODEV;
-		goto err_out_clk_disable;
+		goto err_out_notif_unreg;
 	} else {
 		/* Register the port.
 		 * This function also registers this device with the tty layer
@@ -1006,26 +1407,26 @@
 		port->dev = &pdev->dev;
 		port->uartclk = clk_get_rate(xuartps_data->refclk);
 		port->private_data = xuartps_data;
+		xuartps_data->port = port;
 		platform_set_drvdata(pdev, port);
 		rc = uart_add_one_port(&xuartps_uart_driver, port);
 		if (rc) {
 			dev_err(&pdev->dev,
 				"uart_add_one_port() failed; err=%i\n", rc);
-			goto err_out_clk_disable;
+			goto err_out_notif_unreg;
 		}
 		return 0;
 	}
 
+err_out_notif_unreg:
+#ifdef CONFIG_COMMON_CLK
+	clk_notifier_unregister(xuartps_data->refclk,
+			&xuartps_data->clk_rate_change_nb);
+#endif
 err_out_clk_disable:
 	clk_disable_unprepare(xuartps_data->refclk);
 err_out_clk_dis_aper:
 	clk_disable_unprepare(xuartps_data->aperclk);
-err_out_clk_put:
-	clk_put(xuartps_data->refclk);
-err_out_clk_put_aper:
-	clk_put(xuartps_data->aperclk);
-err_out_free:
-	kfree(xuartps_data);
 
 	return rc;
 }
@@ -1043,13 +1444,14 @@
 	int rc;
 
 	/* Remove the xuartps port from the serial core */
+#ifdef CONFIG_COMMON_CLK
+	clk_notifier_unregister(xuartps_data->refclk,
+			&xuartps_data->clk_rate_change_nb);
+#endif
 	rc = uart_remove_one_port(&xuartps_uart_driver, port);
 	port->mapbase = 0;
 	clk_disable_unprepare(xuartps_data->refclk);
 	clk_disable_unprepare(xuartps_data->aperclk);
-	clk_put(xuartps_data->refclk);
-	clk_put(xuartps_data->aperclk);
-	kfree(xuartps_data);
 	return rc;
 }
 
@@ -1067,6 +1469,7 @@
 		.owner = THIS_MODULE,
 		.name = XUARTPS_NAME,		/* Driver name */
 		.of_match_table = xuartps_of_match,
+		.pm = &xuartps_dev_pm_ops,
 		},
 };
 
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 40a9fe9..ce396ec 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -51,7 +51,7 @@
 #include <asm/irq_regs.h>
 
 /* Whether we react on sysrq keys or just ignore them */
-static int __read_mostly sysrq_enabled = SYSRQ_DEFAULT_ENABLE;
+static int __read_mostly sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE;
 static bool __read_mostly sysrq_always_enabled;
 
 unsigned short platform_sysrq_reset_seq[] __weak = { KEY_RESERVED };
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index f597e88..c94d234 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -140,6 +140,10 @@
 static void tty_port_destructor(struct kref *kref)
 {
 	struct tty_port *port = container_of(kref, struct tty_port, kref);
+
+	/* check if last port ref was dropped before tty release */
+	if (WARN_ON(port->itty))
+		return;
 	if (port->xmit_buf)
 		free_page((unsigned long)port->xmit_buf);
 	tty_port_destroy(port);
@@ -480,8 +484,6 @@
 
 	if (port->count) {
 		spin_unlock_irqrestore(&port->lock, flags);
-		if (port->ops->drop)
-			port->ops->drop(port);
 		return 0;
 	}
 	set_bit(ASYNCB_CLOSING, &port->flags);
@@ -500,9 +502,7 @@
 	/* Flush the ldisc buffering */
 	tty_ldisc_flush(tty);
 
-	/* Don't call port->drop for the last reference. Callers will want
-	   to drop the last active reference in ->shutdown() or the tty
-	   shutdown path */
+	/* Report to caller this is the last port reference */
 	return 1;
 }
 EXPORT_SYMBOL(tty_port_close_start);
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 9a8e8c5..61b1137 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -1300,21 +1300,30 @@
 			case 27:
 				vc->vc_reverse = 0;
 				break;
-			case 38: /* ANSI X3.64-1979 (SCO-ish?)
-				  * Enables underscore, white foreground
-				  * with white underscore (Linux - use
-				  * default foreground).
+			case 38:
+			case 48: /* ITU T.416
+				  * Higher colour modes.
+				  * They break the usual properties of SGR codes
+				  * and thus need to be detected and ignored by
+				  * hand.  Strictly speaking, that standard also
+				  * wants : rather than ; as separators, contrary
+				  * to ECMA-48, but no one produces such codes
+				  * and almost no one accepts them.
 				  */
-				vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0);
-				vc->vc_underline = 1;
+				i++;
+				if (i > vc->vc_npar)
+					break;
+				if (vc->vc_par[i] == 5)      /* 256 colours */
+					i++;                 /* ubiquitous */
+				else if (vc->vc_par[i] == 2) /* 24 bit colours */
+					i += 3;              /* extremely rare */
+				/* Subcommands 3 (CMY) and 4 (CMYK) are so insane
+				 * that detecting them is not worth the few extra
+				 * bytes of kernel's size.
+				 */
 				break;
-			case 39: /* ANSI X3.64-1979 (SCO-ish?)
-				  * Disable underline option.
-				  * Reset colour to default? It did this
-				  * before...
-				  */
+			case 39:
 				vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0);
-				vc->vc_underline = 0;
 				break;
 			case 49:
 				vc->vc_color = (vc->vc_def_color & 0xf0) | (vc->vc_color & 0x0f);
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index ba47563..67beb84 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -288,13 +288,13 @@
 		}
 		map = kzalloc(sizeof(*map), GFP_KERNEL);
 		if (!map)
-			goto err_map;
+			goto err_map_kobj;
 		kobject_init(&map->kobj, &map_attr_type);
 		map->mem = mem;
 		mem->map = map;
 		ret = kobject_add(&map->kobj, idev->map_dir, "map%d", mi);
 		if (ret)
-			goto err_map;
+			goto err_map_kobj;
 		ret = kobject_uevent(&map->kobj, KOBJ_ADD);
 		if (ret)
 			goto err_map;
@@ -313,14 +313,14 @@
 		}
 		portio = kzalloc(sizeof(*portio), GFP_KERNEL);
 		if (!portio)
-			goto err_portio;
+			goto err_portio_kobj;
 		kobject_init(&portio->kobj, &portio_attr_type);
 		portio->port = port;
 		port->portio = portio;
 		ret = kobject_add(&portio->kobj, idev->portio_dir,
 							"port%d", pi);
 		if (ret)
-			goto err_portio;
+			goto err_portio_kobj;
 		ret = kobject_uevent(&portio->kobj, KOBJ_ADD);
 		if (ret)
 			goto err_portio;
@@ -329,14 +329,18 @@
 	return 0;
 
 err_portio:
-	for (pi--; pi >= 0; pi--) {
+	pi--;
+err_portio_kobj:
+	for (; pi >= 0; pi--) {
 		port = &idev->info->port[pi];
 		portio = port->portio;
 		kobject_put(&portio->kobj);
 	}
 	kobject_put(idev->portio_dir);
 err_map:
-	for (mi--; mi>=0; mi--) {
+	mi--;
+err_map_kobj:
+	for (; mi >= 0; mi--) {
 		mem = &idev->info->mem[mi];
 		map = mem->map;
 		kobject_put(&map->kobj);
@@ -601,6 +605,7 @@
 	struct uio_device *idev = vma->vm_private_data;
 	struct page *page;
 	unsigned long offset;
+	void *addr;
 
 	int mi = uio_find_mem_index(vma);
 	if (mi < 0)
@@ -612,10 +617,11 @@
 	 */
 	offset = (vmf->pgoff - mi) << PAGE_SHIFT;
 
+	addr = (void *)(unsigned long)idev->info->mem[mi].addr + offset;
 	if (idev->info->mem[mi].memtype == UIO_MEM_LOGICAL)
-		page = virt_to_page(idev->info->mem[mi].addr + offset);
+		page = virt_to_page(addr);
 	else
-		page = vmalloc_to_page((void *)(unsigned long)idev->info->mem[mi].addr + offset);
+		page = vmalloc_to_page(addr);
 	get_page(page);
 	vmf->page = page;
 	return 0;
@@ -642,16 +648,29 @@
 {
 	struct uio_device *idev = vma->vm_private_data;
 	int mi = uio_find_mem_index(vma);
+	struct uio_mem *mem;
 	if (mi < 0)
 		return -EINVAL;
+	mem = idev->info->mem + mi;
+
+	if (vma->vm_end - vma->vm_start > mem->size)
+		return -EINVAL;
 
 	vma->vm_ops = &uio_physical_vm_ops;
-
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
+	/*
+	 * We cannot use the vm_iomap_memory() helper here,
+	 * because vma->vm_pgoff is the map index we looked
+	 * up above in uio_find_mem_index(), rather than an
+	 * actual page offset into the mmap.
+	 *
+	 * So we just do the physical mmap without a page
+	 * offset.
+	 */
 	return remap_pfn_range(vma,
 			       vma->vm_start,
-			       idev->info->mem[mi].addr >> PAGE_SHIFT,
+			       mem->addr >> PAGE_SHIFT,
 			       vma->vm_end - vma->vm_start,
 			       vma->vm_page_prot);
 }
@@ -796,10 +815,9 @@
 
 	info->uio_dev = NULL;
 
-	idev = kzalloc(sizeof(*idev), GFP_KERNEL);
+	idev = devm_kzalloc(parent, sizeof(*idev), GFP_KERNEL);
 	if (!idev) {
-		ret = -ENOMEM;
-		goto err_kzalloc;
+		return -ENOMEM;
 	}
 
 	idev->owner = owner;
@@ -809,7 +827,7 @@
 
 	ret = uio_get_minor(idev);
 	if (ret)
-		goto err_get_minor;
+		return ret;
 
 	idev->dev = device_create(&uio_class, parent,
 				  MKDEV(uio_major, idev->minor), idev,
@@ -827,7 +845,7 @@
 	info->uio_dev = idev;
 
 	if (info->irq && (info->irq != UIO_IRQ_CUSTOM)) {
-		ret = request_irq(info->irq, uio_interrupt,
+		ret = devm_request_irq(parent, info->irq, uio_interrupt,
 				  info->irq_flags, info->name, idev);
 		if (ret)
 			goto err_request_irq;
@@ -841,9 +859,6 @@
 	device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
 err_device_create:
 	uio_free_minor(idev);
-err_get_minor:
-	kfree(idev);
-err_kzalloc:
 	return ret;
 }
 EXPORT_SYMBOL_GPL(__uio_register_device);
@@ -864,13 +879,9 @@
 
 	uio_free_minor(idev);
 
-	if (info->irq && (info->irq != UIO_IRQ_CUSTOM))
-		free_irq(info->irq, idev);
-
 	uio_dev_del_attributes(idev);
 
 	device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
-	kfree(idev);
 
 	return;
 }
diff --git a/drivers/uio/uio_aec.c b/drivers/uio/uio_aec.c
index f3611c2..1549fab 100644
--- a/drivers/uio/uio_aec.c
+++ b/drivers/uio/uio_aec.c
@@ -147,7 +147,6 @@
 	uio_unregister_device(info);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
 	iounmap(info->priv);
 
 	kfree(info);
diff --git a/drivers/uio/uio_cif.c b/drivers/uio/uio_cif.c
index 22cdf38..30f533c 100644
--- a/drivers/uio/uio_cif.c
+++ b/drivers/uio/uio_cif.c
@@ -106,7 +106,6 @@
 	uio_unregister_device(info);
 	pci_release_regions(dev);
 	pci_disable_device(dev);
-	pci_set_drvdata(dev, NULL);
 	iounmap(info->mem[0].internal_addr);
 
 	kfree (info);
diff --git a/drivers/uio/uio_mf624.c b/drivers/uio/uio_mf624.c
index a1768b2..f764adb 100644
--- a/drivers/uio/uio_mf624.c
+++ b/drivers/uio/uio_mf624.c
@@ -42,7 +42,7 @@
 
 enum mf624_interrupt_source {ADC, CTR4, ALL};
 
-void mf624_disable_interrupt(enum mf624_interrupt_source source,
+static void mf624_disable_interrupt(enum mf624_interrupt_source source,
 			     struct uio_info *info)
 {
 	void __iomem *INTCSR_reg = info->mem[0].internal_addr + INTCSR;
@@ -70,7 +70,7 @@
 	}
 }
 
-void mf624_enable_interrupt(enum mf624_interrupt_source source,
+static void mf624_enable_interrupt(enum mf624_interrupt_source source,
 			    struct uio_info *info)
 {
 	void __iomem *INTCSR_reg = info->mem[0].internal_addr + INTCSR;
@@ -220,7 +220,6 @@
 	uio_unregister_device(info);
 	pci_release_regions(dev);
 	pci_disable_device(dev);
-	pci_set_drvdata(dev, NULL);
 
 	iounmap(info->mem[0].internal_addr);
 	iounmap(info->mem[1].internal_addr);
diff --git a/drivers/uio/uio_netx.c b/drivers/uio/uio_netx.c
index 28a766b..4c345db 100644
--- a/drivers/uio/uio_netx.c
+++ b/drivers/uio/uio_netx.c
@@ -127,7 +127,6 @@
 	uio_unregister_device(info);
 	pci_release_regions(dev);
 	pci_disable_device(dev);
-	pci_set_drvdata(dev, NULL);
 	iounmap(info->mem[0].internal_addr);
 
 	kfree(info);
diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c
index 90ff17a..7666931 100644
--- a/drivers/uio/uio_pdrv_genirq.c
+++ b/drivers/uio/uio_pdrv_genirq.c
@@ -112,11 +112,11 @@
 
 	if (pdev->dev.of_node) {
 		/* alloc uioinfo for one device */
-		uioinfo = kzalloc(sizeof(*uioinfo), GFP_KERNEL);
+		uioinfo = devm_kzalloc(&pdev->dev, sizeof(*uioinfo),
+				       GFP_KERNEL);
 		if (!uioinfo) {
-			ret = -ENOMEM;
 			dev_err(&pdev->dev, "unable to kmalloc\n");
-			return ret;
+			return -ENOMEM;
 		}
 		uioinfo->name = pdev->dev.of_node->name;
 		uioinfo->version = "devicetree";
@@ -125,20 +125,19 @@
 
 	if (!uioinfo || !uioinfo->name || !uioinfo->version) {
 		dev_err(&pdev->dev, "missing platform_data\n");
-		goto bad0;
+		return ret;
 	}
 
 	if (uioinfo->handler || uioinfo->irqcontrol ||
 	    uioinfo->irq_flags & IRQF_SHARED) {
 		dev_err(&pdev->dev, "interrupt configuration error\n");
-		goto bad0;
+		return ret;
 	}
 
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv) {
-		ret = -ENOMEM;
 		dev_err(&pdev->dev, "unable to kmalloc\n");
-		goto bad0;
+		return -ENOMEM;
 	}
 
 	priv->uioinfo = uioinfo;
@@ -153,7 +152,7 @@
 			uioinfo->irq = UIO_IRQ_NONE;
 		else if (ret < 0) {
 			dev_err(&pdev->dev, "failed to get IRQ\n");
-			goto bad1;
+			return ret;
 		}
 	}
 
@@ -209,20 +208,12 @@
 	ret = uio_register_device(&pdev->dev, priv->uioinfo);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to register uio device\n");
-		goto bad2;
+		pm_runtime_disable(&pdev->dev);
+		return ret;
 	}
 
 	platform_set_drvdata(pdev, priv);
 	return 0;
- bad2:
-	pm_runtime_disable(&pdev->dev);
- bad1:
-	kfree(priv);
- bad0:
-	/* kfree uioinfo for OF */
-	if (pdev->dev.of_node)
-		kfree(uioinfo);
-	return ret;
 }
 
 static int uio_pdrv_genirq_remove(struct platform_device *pdev)
@@ -235,11 +226,6 @@
 	priv->uioinfo->handler = NULL;
 	priv->uioinfo->irqcontrol = NULL;
 
-	/* kfree uioinfo for OF */
-	if (pdev->dev.of_node)
-		kfree(priv->uioinfo);
-
-	kfree(priv);
 	return 0;
 }
 
diff --git a/drivers/uio/uio_sercos3.c b/drivers/uio/uio_sercos3.c
index 5419832..9cfdfca 100644
--- a/drivers/uio/uio_sercos3.c
+++ b/drivers/uio/uio_sercos3.c
@@ -188,7 +188,6 @@
 	uio_unregister_device(info);
 	pci_release_regions(dev);
 	pci_disable_device(dev);
-	pci_set_drvdata(dev, NULL);
 	for (i = 0; i < 5; i++) {
 		if (info->mem[i].internal_addr)
 			iounmap(info->mem[i].internal_addr);
diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h
index 5651231..f3eecd9 100644
--- a/drivers/usb/atm/usbatm.h
+++ b/drivers/usb/atm/usbatm.h
@@ -34,6 +34,7 @@
 #include <linux/stringify.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
+#include <linux/ratelimit.h>
 
 /*
 #define VERBOSE_DEBUG
@@ -59,13 +60,12 @@
 	atm_printk(KERN_INFO, instance , format , ## arg)
 #define atm_warn(instance, format, arg...)	\
 	atm_printk(KERN_WARNING, instance , format , ## arg)
-#define atm_dbg(instance, format, arg...)		\
-	dynamic_pr_debug("ATM dev %d: " format ,	\
-	(instance)->atm_dev->number , ## arg)
-#define atm_rldbg(instance, format, arg...)		\
-	if (printk_ratelimit())				\
-		atm_dbg(instance , format , ## arg)
-
+#define atm_dbg(instance, format, ...)					\
+	pr_debug("ATM dev %d: " format,					\
+		 (instance)->atm_dev->number, ##__VA_ARGS__)
+#define atm_rldbg(instance, format, ...)				\
+	pr_debug_ratelimited("ATM dev %d: " format,			\
+			     (instance)->atm_dev->number, ##__VA_ARGS__)
 
 /* flags, set by mini-driver in bind() */
 
diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
index 464584c..a857131 100644
--- a/drivers/usb/chipidea/bits.h
+++ b/drivers/usb/chipidea/bits.h
@@ -48,6 +48,7 @@
 #define PORTSC_SUSP           BIT(7)
 #define PORTSC_HSP            BIT(9)
 #define PORTSC_PTC            (0x0FUL << 16)
+#define PORTSC_PHCD(d)	      ((d) ? BIT(22) : BIT(23))
 /* PTS and PTW for non lpm version only */
 #define PORTSC_PTS(d)						\
 	(u32)((((d) & 0x3) << 30) | (((d) & 0x4) ? BIT(25) : 0))
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index be822a2..023d3cb 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -108,14 +108,8 @@
 	}
 
 	data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0);
-	if (!IS_ERR(data->phy)) {
-		ret = usb_phy_init(data->phy);
-		if (ret) {
-			dev_err(&pdev->dev, "unable to init phy: %d\n", ret);
-			goto err_clk;
-		}
-	} else if (PTR_ERR(data->phy) == -EPROBE_DEFER) {
-		ret = -EPROBE_DEFER;
+	if (IS_ERR(data->phy)) {
+		ret = PTR_ERR(data->phy);
 		goto err_clk;
 	}
 
@@ -131,7 +125,7 @@
 		if (ret) {
 			dev_err(&pdev->dev, "usbmisc init failed, ret=%d\n",
 					ret);
-			goto err_phy;
+			goto err_clk;
 		}
 	}
 
@@ -143,7 +137,7 @@
 		dev_err(&pdev->dev,
 			"Can't register ci_hdrc platform device, err=%d\n",
 			ret);
-		goto err_phy;
+		goto err_clk;
 	}
 
 	if (data->usbmisc_data) {
@@ -164,9 +158,6 @@
 
 disable_device:
 	ci_hdrc_remove_device(data->ci_pdev);
-err_phy:
-	if (data->phy)
-		usb_phy_shutdown(data->phy);
 err_clk:
 	clk_disable_unprepare(data->clk);
 	return ret;
@@ -178,10 +169,6 @@
 
 	pm_runtime_disable(&pdev->dev);
 	ci_hdrc_remove_device(data->ci_pdev);
-
-	if (data->phy)
-		usb_phy_shutdown(data->phy);
-
 	clk_disable_unprepare(data->clk);
 
 	return 0;
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 23763dc..5d8981c 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -172,6 +172,27 @@
 	return hw_read(ci, OP_PORTSC, PORTSC_PTC) >> __ffs(PORTSC_PTC);
 }
 
+/* The PHY enters/leaves low power mode */
+static void ci_hdrc_enter_lpm(struct ci_hdrc *ci, bool enable)
+{
+	enum ci_hw_regs reg = ci->hw_bank.lpm ? OP_DEVLC : OP_PORTSC;
+	bool lpm = !!(hw_read(ci, reg, PORTSC_PHCD(ci->hw_bank.lpm)));
+
+	if (enable && !lpm) {
+		hw_write(ci, reg, PORTSC_PHCD(ci->hw_bank.lpm),
+				PORTSC_PHCD(ci->hw_bank.lpm));
+	} else  if (!enable && lpm) {
+		hw_write(ci, reg, PORTSC_PHCD(ci->hw_bank.lpm),
+				0);
+		/* 
+		 * The controller needs at least 1ms to reflect
+		 * PHY's status, the PHY also needs some time (less
+		 * than 1ms) to leave low power mode.
+		 */
+		usleep_range(1500, 2000);
+	}
+}
+
 static int hw_device_init(struct ci_hdrc *ci, void __iomem *base)
 {
 	u32 reg;
@@ -199,6 +220,8 @@
 	if (ci->hw_ep_max > ENDPT_MAX)
 		return -ENODEV;
 
+	ci_hdrc_enter_lpm(ci, false);
+
 	/* Disable all interrupts bits */
 	hw_write(ci, OP_USBINTR, 0xffffffff, 0);
 
@@ -369,16 +392,28 @@
 static int ci_get_platdata(struct device *dev,
 		struct ci_hdrc_platform_data *platdata)
 {
-	/* Get the vbus regulator */
-	platdata->reg_vbus = devm_regulator_get(dev, "vbus");
-	if (PTR_ERR(platdata->reg_vbus) == -EPROBE_DEFER) {
-		return -EPROBE_DEFER;
-	} else if (PTR_ERR(platdata->reg_vbus) == -ENODEV) {
-		platdata->reg_vbus = NULL; /* no vbus regualator is needed */
-	} else if (IS_ERR(platdata->reg_vbus)) {
-		dev_err(dev, "Getting regulator error: %ld\n",
-			PTR_ERR(platdata->reg_vbus));
-		return PTR_ERR(platdata->reg_vbus);
+	if (!platdata->phy_mode)
+		platdata->phy_mode = of_usb_get_phy_mode(dev->of_node);
+
+	if (!platdata->dr_mode)
+		platdata->dr_mode = of_usb_get_dr_mode(dev->of_node);
+
+	if (platdata->dr_mode == USB_DR_MODE_UNKNOWN)
+		platdata->dr_mode = USB_DR_MODE_OTG;
+
+	if (platdata->dr_mode != USB_DR_MODE_PERIPHERAL) {
+		/* Get the vbus regulator */
+		platdata->reg_vbus = devm_regulator_get(dev, "vbus");
+		if (PTR_ERR(platdata->reg_vbus) == -EPROBE_DEFER) {
+			return -EPROBE_DEFER;
+		} else if (PTR_ERR(platdata->reg_vbus) == -ENODEV) {
+			/* no vbus regualator is needed */
+			platdata->reg_vbus = NULL;
+		} else if (IS_ERR(platdata->reg_vbus)) {
+			dev_err(dev, "Getting regulator error: %ld\n",
+				PTR_ERR(platdata->reg_vbus));
+			return PTR_ERR(platdata->reg_vbus);
+		}
 	}
 
 	return 0;
@@ -465,6 +500,33 @@
 	}
 }
 
+static int ci_usb_phy_init(struct ci_hdrc *ci)
+{
+	if (ci->platdata->phy) {
+		ci->transceiver = ci->platdata->phy;
+		return usb_phy_init(ci->transceiver);
+	} else {
+		ci->global_phy = true;
+		ci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
+		if (IS_ERR(ci->transceiver))
+			ci->transceiver = NULL;
+
+		return 0;
+	}
+}
+
+static void ci_usb_phy_destroy(struct ci_hdrc *ci)
+{
+	if (!ci->transceiver)
+		return;
+
+	otg_set_peripheral(ci->transceiver->otg, NULL);
+	if (ci->global_phy)
+		usb_put_phy(ci->transceiver);
+	else
+		usb_phy_shutdown(ci->transceiver);
+}
+
 static int ci_hdrc_probe(struct platform_device *pdev)
 {
 	struct device	*dev = &pdev->dev;
@@ -473,7 +535,6 @@
 	void __iomem	*base;
 	int		ret;
 	enum usb_dr_mode dr_mode;
-	struct device_node *of_node = dev->of_node ?: dev->parent->of_node;
 
 	if (!dev->platform_data) {
 		dev_err(dev, "platform data missing\n");
@@ -493,10 +554,6 @@
 
 	ci->dev = dev;
 	ci->platdata = dev->platform_data;
-	if (ci->platdata->phy)
-		ci->transceiver = ci->platdata->phy;
-	else
-		ci->global_phy = true;
 
 	ret = hw_device_init(ci, base);
 	if (ret < 0) {
@@ -504,27 +561,25 @@
 		return -ENODEV;
 	}
 
+	ret = ci_usb_phy_init(ci);
+	if (ret) {
+		dev_err(dev, "unable to init phy: %d\n", ret);
+		return ret;
+	}
+
 	ci->hw_bank.phys = res->start;
 
 	ci->irq = platform_get_irq(pdev, 0);
 	if (ci->irq < 0) {
 		dev_err(dev, "missing IRQ\n");
-		return -ENODEV;
+		ret = -ENODEV;
+		goto destroy_phy;
 	}
 
 	ci_get_otg_capable(ci);
 
-	if (!ci->platdata->phy_mode)
-		ci->platdata->phy_mode = of_usb_get_phy_mode(of_node);
-
 	hw_phymode_configure(ci);
 
-	if (!ci->platdata->dr_mode)
-		ci->platdata->dr_mode = of_usb_get_dr_mode(of_node);
-
-	if (ci->platdata->dr_mode == USB_DR_MODE_UNKNOWN)
-		ci->platdata->dr_mode = USB_DR_MODE_OTG;
-
 	dr_mode = ci->platdata->dr_mode;
 	/* initialize role(s) before the interrupt is requested */
 	if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) {
@@ -537,11 +592,23 @@
 		ret = ci_hdrc_gadget_init(ci);
 		if (ret)
 			dev_info(dev, "doesn't support gadget\n");
+		if (!ret && ci->transceiver) {
+			ret = otg_set_peripheral(ci->transceiver->otg,
+							&ci->gadget);
+			/*
+			 * If we implement all USB functions using chipidea drivers,
+			 * it doesn't need to call above API, meanwhile, if we only
+			 * use gadget function, calling above API is useless.
+			 */
+			if (ret && ret != -ENOTSUPP)
+				goto destroy_phy;
+		}
 	}
 
 	if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) {
 		dev_err(dev, "no supported roles\n");
-		return -ENODEV;
+		ret = -ENODEV;
+		goto destroy_phy;
 	}
 
 	if (ci->is_otg) {
@@ -594,6 +661,8 @@
 	free_irq(ci->irq, ci);
 stop:
 	ci_role_destroy(ci);
+destroy_phy:
+	ci_usb_phy_destroy(ci);
 
 	return ret;
 }
@@ -605,6 +674,8 @@
 	dbg_remove_files(ci);
 	free_irq(ci->irq, ci);
 	ci_role_destroy(ci);
+	ci_hdrc_enter_lpm(ci, true);
+	ci_usb_phy_destroy(ci);
 	kfree(ci->hw_bank.regmap);
 
 	return 0;
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index 6f96795..59e6020 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -100,16 +100,18 @@
 {
 	struct usb_hcd *hcd = ci->hcd;
 
-	usb_remove_hcd(hcd);
-	usb_put_hcd(hcd);
-	if (ci->platdata->reg_vbus)
-		regulator_disable(ci->platdata->reg_vbus);
+	if (hcd) {
+		usb_remove_hcd(hcd);
+		usb_put_hcd(hcd);
+		if (ci->platdata->reg_vbus)
+			regulator_disable(ci->platdata->reg_vbus);
+	}
 }
 
 
 void ci_hdrc_host_destroy(struct ci_hdrc *ci)
 {
-	if (ci->role == CI_ROLE_HOST)
+	if (ci->role == CI_ROLE_HOST && ci->hcd)
 		host_stop(ci);
 }
 
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 9333083..b34c819 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -20,7 +20,6 @@
 #include <linux/pm_runtime.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
-#include <linux/usb/otg.h>
 #include <linux/usb/chipidea.h>
 
 #include "ci.h"
@@ -686,9 +685,6 @@
 	usb_ep_fifo_flush(&ci->ep0out->ep);
 	usb_ep_fifo_flush(&ci->ep0in->ep);
 
-	if (ci->driver)
-		ci->driver->disconnect(gadget);
-
 	/* make sure to disable all endpoints */
 	gadget_for_each_ep(ep, gadget) {
 		usb_ep_disable(ep);
@@ -718,6 +714,11 @@
 	int retval;
 
 	spin_unlock(&ci->lock);
+	if (ci->gadget.speed != USB_SPEED_UNKNOWN) {
+		if (ci->driver)
+			ci->driver->disconnect(&ci->gadget);
+	}
+
 	retval = _gadget_stop_activity(&ci->gadget);
 	if (retval)
 		goto done;
@@ -1461,6 +1462,8 @@
 			hw_device_state(ci, ci->ep0out->qh.dma);
 			dev_dbg(ci->dev, "Connected to host\n");
 		} else {
+			if (ci->driver)
+				ci->driver->disconnect(&ci->gadget);
 			hw_device_state(ci, 0);
 			if (ci->platdata->notify_event)
 				ci->platdata->notify_event(ci,
@@ -1633,23 +1636,22 @@
 	retval = usb_ep_enable(&ci->ep0in->ep);
 	if (retval)
 		return retval;
-	spin_lock_irqsave(&ci->lock, flags);
 
 	ci->driver = driver;
 	pm_runtime_get_sync(&ci->gadget.dev);
 	if (ci->vbus_active) {
+		spin_lock_irqsave(&ci->lock, flags);
 		hw_device_reset(ci, USBMODE_CM_DC);
 	} else {
 		pm_runtime_put_sync(&ci->gadget.dev);
-		goto done;
+		return retval;
 	}
 
 	retval = hw_device_state(ci, ci->ep0out->qh.dma);
+	spin_unlock_irqrestore(&ci->lock, flags);
 	if (retval)
 		pm_runtime_put_sync(&ci->gadget.dev);
 
- done:
-	spin_unlock_irqrestore(&ci->lock, flags);
 	return retval;
 }
 
@@ -1786,34 +1788,9 @@
 
 	ci->gadget.ep0 = &ci->ep0in->ep;
 
-	if (ci->global_phy) {
-		ci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
-		if (IS_ERR(ci->transceiver))
-			ci->transceiver = NULL;
-	}
-
-	if (ci->platdata->flags & CI_HDRC_REQUIRE_TRANSCEIVER) {
-		if (ci->transceiver == NULL) {
-			retval = -ENODEV;
-			goto destroy_eps;
-		}
-	}
-
-	if (ci->transceiver) {
-		retval = otg_set_peripheral(ci->transceiver->otg,
-						&ci->gadget);
-		/*
-		 * If we implement all USB functions using chipidea drivers,
-		 * it doesn't need to call above API, meanwhile, if we only
-		 * use gadget function, calling above API is useless.
-		 */
-		if (retval && retval != -ENOTSUPP)
-			goto put_transceiver;
-	}
-
 	retval = usb_add_gadget_udc(dev, &ci->gadget);
 	if (retval)
-		goto remove_trans;
+		goto destroy_eps;
 
 	pm_runtime_no_callbacks(&ci->gadget.dev);
 	pm_runtime_enable(&ci->gadget.dev);
@@ -1823,17 +1800,6 @@
 
 	return retval;
 
-remove_trans:
-	if (ci->transceiver) {
-		otg_set_peripheral(ci->transceiver->otg, NULL);
-		if (ci->global_phy)
-			usb_put_phy(ci->transceiver);
-	}
-
-	dev_err(dev, "error = %i\n", retval);
-put_transceiver:
-	if (ci->transceiver && ci->global_phy)
-		usb_put_phy(ci->transceiver);
 destroy_eps:
 	destroy_eps(ci);
 free_pools:
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index d3318a0..4d38759 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -101,6 +101,7 @@
 	struct work_struct	rxwork;
 	int			werr;
 	int			rerr;
+	int                     resp_count;
 
 	struct list_head	device_list;
 	int			(*manage_power)(struct usb_interface *, int);
@@ -253,6 +254,10 @@
 			"NOTIFY_NETWORK_CONNECTION %s network",
 			dr->wValue ? "connected to" : "disconnected from");
 		goto exit;
+	case USB_CDC_NOTIFY_SPEED_CHANGE:
+		dev_dbg(&desc->intf->dev, "SPEED_CHANGE received (len %u)",
+			urb->actual_length);
+		goto exit;
 	default:
 		clear_bit(WDM_POLL_RUNNING, &desc->flags);
 		dev_err(&desc->intf->dev,
@@ -262,9 +267,9 @@
 	}
 
 	spin_lock(&desc->iuspin);
-	clear_bit(WDM_READ, &desc->flags);
 	responding = test_and_set_bit(WDM_RESPONDING, &desc->flags);
-	if (!responding && !test_bit(WDM_DISCONNECTING, &desc->flags)
+	if (!desc->resp_count++ && !responding
+		&& !test_bit(WDM_DISCONNECTING, &desc->flags)
 		&& !test_bit(WDM_SUSPENDING, &desc->flags)) {
 		rv = usb_submit_urb(desc->response, GFP_ATOMIC);
 		dev_dbg(&desc->intf->dev, "%s: usb_submit_urb %d",
@@ -521,10 +526,36 @@
 
 	desc->length -= cntr;
 	/* in case we had outstanding data */
-	if (!desc->length)
+	if (!desc->length) {
 		clear_bit(WDM_READ, &desc->flags);
 
-	spin_unlock_irq(&desc->iuspin);
+		if (--desc->resp_count) {
+			set_bit(WDM_RESPONDING, &desc->flags);
+			spin_unlock_irq(&desc->iuspin);
+
+			rv = usb_submit_urb(desc->response, GFP_KERNEL);
+			if (rv) {
+				dev_err(&desc->intf->dev,
+					"%s: usb_submit_urb failed with result %d\n",
+					__func__, rv);
+				spin_lock_irq(&desc->iuspin);
+				clear_bit(WDM_RESPONDING, &desc->flags);
+				spin_unlock_irq(&desc->iuspin);
+
+				if (rv == -ENOMEM) {
+					rv = schedule_work(&desc->rxwork);
+					if (rv)
+						dev_err(&desc->intf->dev, "Cannot schedule work\n");
+				} else {
+					spin_lock_irq(&desc->iuspin);
+					desc->resp_count = 0;
+					spin_unlock_irq(&desc->iuspin);
+				}
+			}
+		} else
+			spin_unlock_irq(&desc->iuspin);
+	} else
+		spin_unlock_irq(&desc->iuspin);
 
 	rv = cntr;
 
@@ -635,6 +666,9 @@
 		if (!test_bit(WDM_DISCONNECTING, &desc->flags)) {
 			dev_dbg(&desc->intf->dev, "wdm_release: cleanup");
 			kill_urbs(desc);
+			spin_lock_irq(&desc->iuspin);
+			desc->resp_count = 0;
+			spin_unlock_irq(&desc->iuspin);
 			desc->manage_power(desc->intf, 0);
 		} else {
 			/* must avoid dev_printk here as desc->intf is invalid */
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 71dc5d7..967152a 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -914,10 +914,8 @@
 	snoop(&dev->dev, "control urb: bRequestType=%02x "
 		"bRequest=%02x wValue=%04x "
 		"wIndex=%04x wLength=%04x\n",
-		ctrl.bRequestType, ctrl.bRequest,
-		__le16_to_cpup(&ctrl.wValue),
-		__le16_to_cpup(&ctrl.wIndex),
-		__le16_to_cpup(&ctrl.wLength));
+		ctrl.bRequestType, ctrl.bRequest, ctrl.wValue,
+		ctrl.wIndex, ctrl.wLength);
 	if (ctrl.bRequestType & 0x80) {
 		if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data,
 					       ctrl.wLength)) {
@@ -1636,32 +1634,32 @@
 static int proc_control_compat(struct dev_state *ps,
 				struct usbdevfs_ctrltransfer32 __user *p32)
 {
-        struct usbdevfs_ctrltransfer __user *p;
-        __u32 udata;
-        p = compat_alloc_user_space(sizeof(*p));
-        if (copy_in_user(p, p32, (sizeof(*p32) - sizeof(compat_caddr_t))) ||
-            get_user(udata, &p32->data) ||
+	struct usbdevfs_ctrltransfer __user *p;
+	__u32 udata;
+	p = compat_alloc_user_space(sizeof(*p));
+	if (copy_in_user(p, p32, (sizeof(*p32) - sizeof(compat_caddr_t))) ||
+	    get_user(udata, &p32->data) ||
 	    put_user(compat_ptr(udata), &p->data))
 		return -EFAULT;
-        return proc_control(ps, p);
+	return proc_control(ps, p);
 }
 
 static int proc_bulk_compat(struct dev_state *ps,
 			struct usbdevfs_bulktransfer32 __user *p32)
 {
-        struct usbdevfs_bulktransfer __user *p;
-        compat_uint_t n;
-        compat_caddr_t addr;
+	struct usbdevfs_bulktransfer __user *p;
+	compat_uint_t n;
+	compat_caddr_t addr;
 
-        p = compat_alloc_user_space(sizeof(*p));
+	p = compat_alloc_user_space(sizeof(*p));
 
-        if (get_user(n, &p32->ep) || put_user(n, &p->ep) ||
-            get_user(n, &p32->len) || put_user(n, &p->len) ||
-            get_user(n, &p32->timeout) || put_user(n, &p->timeout) ||
-            get_user(addr, &p32->data) || put_user(compat_ptr(addr), &p->data))
-                return -EFAULT;
+	if (get_user(n, &p32->ep) || put_user(n, &p->ep) ||
+	    get_user(n, &p32->len) || put_user(n, &p->len) ||
+	    get_user(n, &p32->timeout) || put_user(n, &p->timeout) ||
+	    get_user(addr, &p32->data) || put_user(compat_ptr(addr), &p->data))
+		return -EFAULT;
 
-        return proc_bulk(ps, p);
+	return proc_bulk(ps, p);
 }
 static int proc_disconnectsignal_compat(struct dev_state *ps, void __user *arg)
 {
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index f7841d4..47aade2 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1179,8 +1179,8 @@
 						"reset_resume", status);
 		} else {
 			intf->needs_binding = 1;
-			dev_warn(&intf->dev, "no %s for driver %s?\n",
-					"reset_resume", driver->name);
+			dev_dbg(&intf->dev, "no reset_resume for driver %s?\n",
+					driver->name);
 		}
 	} else {
 		status = driver->resume(intf);
@@ -1790,6 +1790,9 @@
 	struct usb_hcd *hcd = bus_to_hcd(udev->bus);
 	int ret = -EPERM;
 
+	if (enable && !udev->usb2_hw_lpm_allowed)
+		return 0;
+
 	if (hcd->driver->set_usb2_hw_lpm) {
 		ret = hcd->driver->set_usb2_hw_lpm(hcd, udev, enable);
 		if (!ret)
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index fe0d836..ea337a7 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -8,7 +8,7 @@
  * (C) Copyright Deti Fliegl 1999 (new USB architecture)
  * (C) Copyright Randy Dunlap 2000
  * (C) Copyright David Brownell 2000-2001 (kernel hotplug, usb_device_id,
- 	more docs, etc)
+ *	more docs, etc)
  * (C) Copyright Yggdrasil Computing, Inc. 2000
  *     (usb_device_id matching changes by Adam J. Richter)
  * (C) Copyright Greg Kroah-Hartman 2002-2003
@@ -27,7 +27,7 @@
 static const struct file_operations *usb_minors[MAX_USB_MINORS];
 static DECLARE_RWSEM(minor_rwsem);
 
-static int usb_open(struct inode * inode, struct file * file)
+static int usb_open(struct inode *inode, struct file *file)
 {
 	int err = -ENODEV;
 	const struct file_operations *new_fops;
@@ -41,7 +41,7 @@
 	replace_fops(file, new_fops);
 	/* Curiouser and curiouser... NULL ->open() as "no device" ? */
 	if (file->f_op->open)
-		err = file->f_op->open(inode,file);
+		err = file->f_op->open(inode, file);
  done:
 	up_read(&minor_rwsem);
 	return err;
@@ -158,7 +158,7 @@
 	char *temp;
 
 #ifdef CONFIG_USB_DYNAMIC_MINORS
-	/* 
+	/*
 	 * We don't care what the device tries to start at, we want to start
 	 * at zero to pack the devices into the smallest available space with
 	 * no holes in the minor range.
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index b9d3c43..dfe9d0f 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -215,6 +215,9 @@
 		goto disable_pci;
 	}
 
+	hcd->amd_resume_bug = (usb_hcd_amd_remote_wakeup_quirk(dev) &&
+			driver->flags & (HCD_USB11 | HCD_USB3)) ? 1 : 0;
+
 	if (driver->flags & HCD_MEMORY) {
 		/* EHCI, OHCI */
 		hcd->rsrc_start = pci_resource_start(dev, 0);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index d6a8d23..6bffb8c 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -6,7 +6,7 @@
  * (C) Copyright Deti Fliegl 1999
  * (C) Copyright Randy Dunlap 2000
  * (C) Copyright David Brownell 2000-2002
- * 
+ *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  * Free Software Foundation; either version 2 of the License, or (at your
@@ -40,6 +40,7 @@
 #include <linux/platform_device.h>
 #include <linux/workqueue.h>
 #include <linux/pm_runtime.h>
+#include <linux/types.h>
 
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
@@ -92,10 +93,7 @@
 
 /* used when allocating bus numbers */
 #define USB_MAXBUS		64
-struct usb_busmap {
-	unsigned long busmap [USB_MAXBUS / (8*sizeof (unsigned long))];
-};
-static struct usb_busmap busmap;
+static DECLARE_BITMAP(busmap, USB_MAXBUS);
 
 /* used when updating list of hcds */
 DEFINE_MUTEX(usb_bus_list_lock);	/* exported only for usbfs */
@@ -171,7 +169,7 @@
 };
 
 /* usb 2.0 root hub device descriptor */
-static const u8 usb2_rh_dev_descriptor [18] = {
+static const u8 usb2_rh_dev_descriptor[18] = {
 	0x12,       /*  __u8  bLength; */
 	0x01,       /*  __u8  bDescriptorType; Device */
 	0x00, 0x02, /*  __le16 bcdUSB; v2.0 */
@@ -194,7 +192,7 @@
 /* no usb 2.0 root hub "device qualifier" descriptor: one speed only */
 
 /* usb 1.1 root hub device descriptor */
-static const u8 usb11_rh_dev_descriptor [18] = {
+static const u8 usb11_rh_dev_descriptor[18] = {
 	0x12,       /*  __u8  bLength; */
 	0x01,       /*  __u8  bDescriptorType; Device */
 	0x10, 0x01, /*  __le16 bcdUSB; v1.1 */
@@ -219,7 +217,7 @@
 
 /* Configuration descriptors for our root hubs */
 
-static const u8 fs_rh_config_descriptor [] = {
+static const u8 fs_rh_config_descriptor[] = {
 
 	/* one configuration */
 	0x09,       /*  __u8  bLength; */
@@ -228,13 +226,13 @@
 	0x01,       /*  __u8  bNumInterfaces; (1) */
 	0x01,       /*  __u8  bConfigurationValue; */
 	0x00,       /*  __u8  iConfiguration; */
-	0xc0,       /*  __u8  bmAttributes; 
+	0xc0,       /*  __u8  bmAttributes;
 				 Bit 7: must be set,
 				     6: Self-powered,
 				     5: Remote wakeup,
 				     4..0: resvd */
 	0x00,       /*  __u8  MaxPower; */
-      
+
 	/* USB 1.1:
 	 * USB 2.0, single TT organization (mandatory):
 	 *	one interface, protocol 0
@@ -256,17 +254,17 @@
 	0x00,       /*  __u8  if_bInterfaceSubClass; */
 	0x00,       /*  __u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
 	0x00,       /*  __u8  if_iInterface; */
-     
+
 	/* one endpoint (status change endpoint) */
 	0x07,       /*  __u8  ep_bLength; */
 	0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
 	0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
- 	0x03,       /*  __u8  ep_bmAttributes; Interrupt */
- 	0x02, 0x00, /*  __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
+	0x03,       /*  __u8  ep_bmAttributes; Interrupt */
+	0x02, 0x00, /*  __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
 	0xff        /*  __u8  ep_bInterval; (255ms -- usb 2.0 spec) */
 };
 
-static const u8 hs_rh_config_descriptor [] = {
+static const u8 hs_rh_config_descriptor[] = {
 
 	/* one configuration */
 	0x09,       /*  __u8  bLength; */
@@ -275,13 +273,13 @@
 	0x01,       /*  __u8  bNumInterfaces; (1) */
 	0x01,       /*  __u8  bConfigurationValue; */
 	0x00,       /*  __u8  iConfiguration; */
-	0xc0,       /*  __u8  bmAttributes; 
+	0xc0,       /*  __u8  bmAttributes;
 				 Bit 7: must be set,
 				     6: Self-powered,
 				     5: Remote wakeup,
 				     4..0: resvd */
 	0x00,       /*  __u8  MaxPower; */
-      
+
 	/* USB 1.1:
 	 * USB 2.0, single TT organization (mandatory):
 	 *	one interface, protocol 0
@@ -303,12 +301,12 @@
 	0x00,       /*  __u8  if_bInterfaceSubClass; */
 	0x00,       /*  __u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
 	0x00,       /*  __u8  if_iInterface; */
-     
+
 	/* one endpoint (status change endpoint) */
 	0x07,       /*  __u8  ep_bLength; */
 	0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
 	0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
- 	0x03,       /*  __u8  ep_bmAttributes; Interrupt */
+	0x03,       /*  __u8  ep_bmAttributes; Interrupt */
 		    /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8)
 		     * see hub.c:hub_configure() for details. */
 	(USB_MAXCHILDREN + 1 + 7) / 8, 0x00,
@@ -428,7 +426,7 @@
 	char const *s;
 	static char const langids[4] = {4, USB_DT_STRING, 0x09, 0x04};
 
-	// language ids
+	/* language ids */
 	switch (id) {
 	case 0:
 		/* Array of LANGID codes (0x0409 is MSFT-speak for "en-us") */
@@ -464,7 +462,7 @@
 static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
 {
 	struct usb_ctrlrequest *cmd;
- 	u16		typeReq, wValue, wIndex, wLength;
+	u16		typeReq, wValue, wIndex, wLength;
 	u8		*ubuf = urb->transfer_buffer;
 	unsigned	len = 0;
 	int		status;
@@ -526,10 +524,10 @@
 	 */
 
 	case DeviceRequest | USB_REQ_GET_STATUS:
-		tbuf [0] = (device_may_wakeup(&hcd->self.root_hub->dev)
+		tbuf[0] = (device_may_wakeup(&hcd->self.root_hub->dev)
 					<< USB_DEVICE_REMOTE_WAKEUP)
 				| (1 << USB_DEVICE_SELF_POWERED);
-		tbuf [1] = 0;
+		tbuf[1] = 0;
 		len = 2;
 		break;
 	case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
@@ -546,7 +544,7 @@
 			goto error;
 		break;
 	case DeviceRequest | USB_REQ_GET_CONFIGURATION:
-		tbuf [0] = 1;
+		tbuf[0] = 1;
 		len = 1;
 			/* FALLTHROUGH */
 	case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
@@ -609,13 +607,13 @@
 		}
 		break;
 	case DeviceRequest | USB_REQ_GET_INTERFACE:
-		tbuf [0] = 0;
+		tbuf[0] = 0;
 		len = 1;
 			/* FALLTHROUGH */
 	case DeviceOutRequest | USB_REQ_SET_INTERFACE:
 		break;
 	case DeviceOutRequest | USB_REQ_SET_ADDRESS:
-		// wValue == urb->dev->devaddr
+		/* wValue == urb->dev->devaddr */
 		dev_dbg (hcd->self.controller, "root hub device address %d\n",
 			wValue);
 		break;
@@ -625,9 +623,9 @@
 	/* ENDPOINT REQUESTS */
 
 	case EndpointRequest | USB_REQ_GET_STATUS:
-		// ENDPOINT_HALT flag
-		tbuf [0] = 0;
-		tbuf [1] = 0;
+		/* ENDPOINT_HALT flag */
+		tbuf[0] = 0;
+		tbuf[1] = 0;
 		len = 2;
 			/* FALLTHROUGH */
 	case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
@@ -683,7 +681,7 @@
 		if (urb->transfer_buffer_length < len)
 			len = urb->transfer_buffer_length;
 		urb->actual_length = len;
-		// always USB_DIR_IN, toward host
+		/* always USB_DIR_IN, toward host */
 		memcpy (ubuf, bufp, len);
 
 		/* report whether RH hardware supports remote wakeup */
@@ -877,11 +875,11 @@
 	usb_hcd = bus_to_hcd(usb_bus);
 	result = sscanf(buf, "%u\n", &val);
 	if (result == 1) {
-		usb_hcd->authorized_default = val? 1 : 0;
+		usb_hcd->authorized_default = val ? 1 : 0;
 		result = size;
-	}
-	else
+	} else {
 		result = -EINVAL;
+	}
 	return result;
 }
 static DEVICE_ATTR_RW(authorized_default);
@@ -941,12 +939,12 @@
 	int busnum;
 
 	mutex_lock(&usb_bus_list_lock);
-	busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1);
+	busnum = find_next_zero_bit(busmap, USB_MAXBUS, 1);
 	if (busnum >= USB_MAXBUS) {
 		printk (KERN_ERR "%s: too many buses\n", usbcore_name);
 		goto error_find_busnum;
 	}
-	set_bit (busnum, busmap.busmap);
+	set_bit(busnum, busmap);
 	bus->busnum = busnum;
 
 	/* Add it to the local list of buses */
@@ -987,7 +985,7 @@
 
 	usb_notify_remove_bus(bus);
 
-	clear_bit (bus->busnum, busmap.busmap);
+	clear_bit(bus->busnum, busmap);
 }
 
 /**
@@ -1033,6 +1031,7 @@
 					dev_name(&usb_dev->dev), retval);
 			return retval;
 		}
+		usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev);
 	}
 
 	retval = usb_new_device (usb_dev);
@@ -1120,21 +1119,21 @@
 	case USB_SPEED_LOW: 	/* INTR only */
 		if (is_input) {
 			tmp = (67667L * (31L + 10L * BitTime (bytecount))) / 1000L;
-			return (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);
+			return 64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp;
 		} else {
 			tmp = (66700L * (31L + 10L * BitTime (bytecount))) / 1000L;
-			return (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp);
+			return 64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp;
 		}
 	case USB_SPEED_FULL:	/* ISOC or INTR */
 		if (isoc) {
 			tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L;
-			return (((is_input) ? 7268L : 6265L) + BW_HOST_DELAY + tmp);
+			return ((is_input) ? 7268L : 6265L) + BW_HOST_DELAY + tmp;
 		} else {
 			tmp = (8354L * (31L + 10L * BitTime (bytecount))) / 1000L;
-			return (9107L + BW_HOST_DELAY + tmp);
+			return 9107L + BW_HOST_DELAY + tmp;
 		}
 	case USB_SPEED_HIGH:	/* ISOC or INTR */
-		// FIXME adjust for input vs output
+		/* FIXME adjust for input vs output */
 		if (isoc)
 			tmp = HS_NSECS_ISO (bytecount);
 		else
@@ -1651,6 +1650,7 @@
 static void __usb_hcd_giveback_urb(struct urb *urb)
 {
 	struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus);
+	struct usb_anchor *anchor = urb->anchor;
 	int status = urb->unlinked;
 	unsigned long flags;
 
@@ -1662,6 +1662,7 @@
 
 	unmap_urb_for_dma(hcd, urb);
 	usbmon_urb_complete(&hcd->self, urb, status);
+	usb_anchor_suspend_wakeups(anchor);
 	usb_unanchor_urb(urb);
 
 	/* pass ownership to the completion handler */
@@ -1681,6 +1682,7 @@
 	urb->complete(urb);
 	local_irq_restore(flags);
 
+	usb_anchor_resume_wakeups(anchor);
 	atomic_dec(&urb->use_count);
 	if (unlikely(atomic_read(&urb->reject)))
 		wake_up(&usb_kill_urb_queue);
@@ -1703,7 +1705,9 @@
 
 		urb = list_entry(local_list.next, struct urb, urb_list);
 		list_del_init(&urb->urb_list);
+		bh->completing_ep = urb->ep;
 		__usb_hcd_giveback_urb(urb);
+		bh->completing_ep = NULL;
 	}
 
 	/* check if there are new URBs to giveback */
@@ -1812,7 +1816,7 @@
 				 case USB_ENDPOINT_XFER_INT:
 					s = "-intr"; break;
 				 default:
-			 		s = "-iso"; break;
+					s = "-iso"; break;
 				};
 				s;
 			}));
@@ -2073,8 +2077,11 @@
  *
  * Reverts a group of bulk endpoints back to not using stream IDs.
  * Can fail if we are given bad arguments, or HCD is broken.
+ *
+ * Return: On success, the number of allocated streams. On failure, a negative
+ * error code.
  */
-void usb_free_streams(struct usb_interface *interface,
+int usb_free_streams(struct usb_interface *interface,
 		struct usb_host_endpoint **eps, unsigned int num_eps,
 		gfp_t mem_flags)
 {
@@ -2085,14 +2092,14 @@
 	dev = interface_to_usbdev(interface);
 	hcd = bus_to_hcd(dev->bus);
 	if (dev->speed != USB_SPEED_SUPER)
-		return;
+		return -EINVAL;
 
 	/* Streams only apply to bulk endpoints. */
 	for (i = 0; i < num_eps; i++)
 		if (!eps[i] || !usb_endpoint_xfer_bulk(&eps[i]->desc))
-			return;
+			return -EINVAL;
 
-	hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags);
+	return hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags);
 }
 EXPORT_SYMBOL_GPL(usb_free_streams);
 
@@ -2245,7 +2252,7 @@
 }
 
 /**
- * usb_hcd_resume_root_hub - called by HCD to resume its root hub 
+ * usb_hcd_resume_root_hub - called by HCD to resume its root hub
  * @hcd: host controller for this root hub
  *
  * The USB host controller calls this function when its root hub is
@@ -2324,15 +2331,8 @@
 irqreturn_t usb_hcd_irq (int irq, void *__hcd)
 {
 	struct usb_hcd		*hcd = __hcd;
-	unsigned long		flags;
 	irqreturn_t		rc;
 
-	/* IRQF_DISABLED doesn't work correctly with shared IRQs
-	 * when the first handler doesn't use it.  So let's just
-	 * assume it's never used.
-	 */
-	local_irq_save(flags);
-
 	if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd)))
 		rc = IRQ_NONE;
 	else if (hcd->driver->irq(hcd) == IRQ_NONE)
@@ -2340,7 +2340,6 @@
 	else
 		rc = IRQ_HANDLED;
 
-	local_irq_restore(flags);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(usb_hcd_irq);
@@ -2547,13 +2546,6 @@
 
 	if (hcd->driver->irq) {
 
-		/* IRQF_DISABLED doesn't work as advertised when used together
-		 * with IRQF_SHARED. As usb_hcd_irq() will always disable
-		 * interrupts we can remove it here.
-		 */
-		if (irqflags & IRQF_SHARED)
-			irqflags &= ~IRQF_DISABLED;
-
 		snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
 				hcd->driver->description, hcd->self.busnum);
 		retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
@@ -2600,7 +2592,7 @@
 
 	/* Keep old behaviour if authorized_default is not in [0, 1]. */
 	if (authorized_default < 0 || authorized_default > 1)
-		hcd->authorized_default = hcd->wireless? 0 : 1;
+		hcd->authorized_default = hcd->wireless ? 0 : 1;
 	else
 		hcd->authorized_default = authorized_default;
 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
@@ -2743,7 +2735,7 @@
 err_register_bus:
 	hcd_buffer_destroy(hcd);
 	return retval;
-} 
+}
 EXPORT_SYMBOL_GPL(usb_add_hcd);
 
 /**
@@ -2818,7 +2810,7 @@
 EXPORT_SYMBOL_GPL(usb_remove_hcd);
 
 void
-usb_hcd_platform_shutdown(struct platform_device* dev)
+usb_hcd_platform_shutdown(struct platform_device *dev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(dev);
 
@@ -2840,7 +2832,7 @@
  * Notice that the code is minimally error-proof. Because usbmon needs
  * symbols from usbcore, usbcore gets referenced and cannot be unloaded first.
  */
- 
+
 int usb_mon_register (struct usb_mon_operations *ops)
 {
 
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index e6b682c..06cec635 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -120,7 +120,7 @@
 	if (hub_is_superspeed(hub->hdev))
 		return "5.0 Gb/s";
 	if (portstatus & USB_PORT_STAT_HIGH_SPEED)
-    		return "480 Mb/s";
+		return "480 Mb/s";
 	else if (portstatus & USB_PORT_STAT_LOW_SPEED)
 		return "1.5 Mb/s";
 	else
@@ -135,7 +135,7 @@
 	return usb_get_intfdata(hdev->actconfig->interface[0]);
 }
 
-static int usb_device_supports_lpm(struct usb_device *udev)
+int usb_device_supports_lpm(struct usb_device *udev)
 {
 	/* USB 2.1 (and greater) devices indicate LPM support through
 	 * their USB 2.0 Extended Capabilities BOS descriptor.
@@ -156,6 +156,11 @@
 				"Power management will be impacted.\n");
 		return 0;
 	}
+
+	/* udev is root hub */
+	if (!udev->parent)
+		return 1;
+
 	if (udev->parent->lpm_capable)
 		return 1;
 
@@ -310,9 +315,9 @@
 		return;
 
 	udev_u1_del = udev->bos->ss_cap->bU1devExitLat;
-	udev_u2_del = udev->bos->ss_cap->bU2DevExitLat;
+	udev_u2_del = le16_to_cpu(udev->bos->ss_cap->bU2DevExitLat);
 	hub_u1_del = udev->parent->bos->ss_cap->bU1devExitLat;
-	hub_u2_del = udev->parent->bos->ss_cap->bU2DevExitLat;
+	hub_u2_del = le16_to_cpu(udev->parent->bos->ss_cap->bU2DevExitLat);
 
 	usb_set_lpm_mel(udev, &udev->u1_params, udev_u1_del,
 			hub, &udev->parent->u1_params, hub_u1_del);
@@ -433,7 +438,7 @@
 			case HUB_LED_OFF: s = "off"; break;
 			case HUB_LED_AUTO: s = "auto"; break;
 			default: s = "??"; break;
-			}; s; }),
+			} s; }),
 			status);
 }
 
@@ -857,7 +862,7 @@
 				"%s failed (err = %d)\n", __func__, ret);
 	} else {
 		*status = le16_to_cpu(hub->status->hub.wHubStatus);
-		*change = le16_to_cpu(hub->status->hub.wHubChange); 
+		*change = le16_to_cpu(hub->status->hub.wHubChange);
 		ret = 0;
 	}
 	mutex_unlock(&hub->status_mutex);
@@ -956,7 +961,7 @@
 	 */
 
 	set_bit(port1, hub->change_bits);
- 	kick_khubd(hub);
+	kick_khubd(hub);
 }
 
 /**
@@ -1107,16 +1112,13 @@
 			/*
 			 * USB3 protocol ports will automatically transition
 			 * to Enabled state when detect an USB3.0 device attach.
-			 * Do not disable USB3 protocol ports.
+			 * Do not disable USB3 protocol ports, just pretend
+			 * power was lost
 			 */
-			if (!hub_is_superspeed(hdev)) {
+			portstatus &= ~USB_PORT_STAT_ENABLE;
+			if (!hub_is_superspeed(hdev))
 				usb_clear_port_feature(hdev, port1,
 						   USB_PORT_FEAT_ENABLE);
-				portstatus &= ~USB_PORT_STAT_ENABLE;
-			} else {
-				/* Pretend that power was lost for USB3 devs */
-				portstatus &= ~USB_PORT_STAT_ENABLE;
-			}
 		}
 
 		/* Clear status-change flags; we'll debounce later */
@@ -1130,6 +1132,11 @@
 			usb_clear_port_feature(hub->hdev, port1,
 					USB_PORT_FEAT_C_ENABLE);
 		}
+		if (portchange & USB_PORT_STAT_C_RESET) {
+			need_debounce_delay = true;
+			usb_clear_port_feature(hub->hdev, port1,
+					USB_PORT_FEAT_C_RESET);
+		}
 		if ((portchange & USB_PORT_STAT_C_BH_RESET) &&
 				hub_is_superspeed(hub->hdev)) {
 			need_debounce_delay = true;
@@ -1361,7 +1368,7 @@
 	if ((wHubCharacteristics & HUB_CHAR_COMPOUND) &&
 			!(hub_is_superspeed(hdev))) {
 		int	i;
-		char	portstr [USB_MAXCHILDREN + 1];
+		char	portstr[USB_MAXCHILDREN + 1];
 
 		for (i = 0; i < hdev->maxchild; i++)
 			portstr[i] = hub->descriptor->u.hs.DeviceRemovable
@@ -1429,32 +1436,32 @@
 
 	/* Note 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns */
 	switch (wHubCharacteristics & HUB_CHAR_TTTT) {
-		case HUB_TTTT_8_BITS:
-			if (hdev->descriptor.bDeviceProtocol != 0) {
-				hub->tt.think_time = 666;
-				dev_dbg(hub_dev, "TT requires at most %d "
-						"FS bit times (%d ns)\n",
-					8, hub->tt.think_time);
-			}
-			break;
-		case HUB_TTTT_16_BITS:
-			hub->tt.think_time = 666 * 2;
+	case HUB_TTTT_8_BITS:
+		if (hdev->descriptor.bDeviceProtocol != 0) {
+			hub->tt.think_time = 666;
 			dev_dbg(hub_dev, "TT requires at most %d "
 					"FS bit times (%d ns)\n",
-				16, hub->tt.think_time);
-			break;
-		case HUB_TTTT_24_BITS:
-			hub->tt.think_time = 666 * 3;
-			dev_dbg(hub_dev, "TT requires at most %d "
-					"FS bit times (%d ns)\n",
-				24, hub->tt.think_time);
-			break;
-		case HUB_TTTT_32_BITS:
-			hub->tt.think_time = 666 * 4;
-			dev_dbg(hub_dev, "TT requires at most %d "
-					"FS bit times (%d ns)\n",
-				32, hub->tt.think_time);
-			break;
+				8, hub->tt.think_time);
+		}
+		break;
+	case HUB_TTTT_16_BITS:
+		hub->tt.think_time = 666 * 2;
+		dev_dbg(hub_dev, "TT requires at most %d "
+				"FS bit times (%d ns)\n",
+			16, hub->tt.think_time);
+		break;
+	case HUB_TTTT_24_BITS:
+		hub->tt.think_time = 666 * 3;
+		dev_dbg(hub_dev, "TT requires at most %d "
+				"FS bit times (%d ns)\n",
+			24, hub->tt.think_time);
+		break;
+	case HUB_TTTT_32_BITS:
+		hub->tt.think_time = 666 * 4;
+		dev_dbg(hub_dev, "TT requires at most %d "
+				"FS bit times (%d ns)\n",
+			32, hub->tt.think_time);
+		break;
 	}
 
 	/* probe() zeroes hub->indicator[] */
@@ -1560,7 +1567,7 @@
 
 	/* maybe cycle the hub leds */
 	if (hub->has_indicators && blinkenlights)
-		hub->indicator [0] = INDICATOR_CYCLE;
+		hub->indicator[0] = INDICATOR_CYCLE;
 
 	for (i = 0; i < hdev->maxchild; i++) {
 		ret = usb_hub_create_port_device(hub, i + 1);
@@ -1978,7 +1985,7 @@
 		if (devnum >= 128)
 			devnum = find_next_zero_bit(bus->devmap.devicemap,
 						    128, 1);
-		bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);
+		bus->devnum_next = (devnum >= 127 ? 1 : devnum + 1);
 	}
 	if (devnum < 128) {
 		set_bit(devnum, bus->devmap.devicemap);
@@ -2018,8 +2025,8 @@
  * Something got disconnected. Get rid of it and all of its children.
  *
  * If *pdev is a normal device then the parent hub must already be locked.
- * If *pdev is a root hub then this routine will acquire the
- * usb_bus_list_lock on behalf of the caller.
+ * If *pdev is a root hub then the caller must hold the usb_bus_list_lock,
+ * which protects the set of root hubs as well as the list of buses.
  *
  * Only hub drivers (including virtual root hub drivers for host
  * controllers) should ever call this.
@@ -2232,8 +2239,7 @@
 		udev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL);
 		udev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL);
 		udev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL);
-	}
-	else {
+	} else {
 		/* read the standard strings and cache them if present */
 		udev->product = usb_cache_string(udev, udev->descriptor.iProduct);
 		udev->manufacturer = usb_cache_string(udev,
@@ -2489,7 +2495,7 @@
 	usb_autosuspend_device(usb_dev);
 error_autoresume:
 out_authorized:
-	usb_unlock_device(usb_dev);	// complements locktree
+	usb_unlock_device(usb_dev);	/* complements locktree */
 	return result;
 }
 
@@ -3108,8 +3114,8 @@
  retry_reset_resume:
 		status = usb_reset_and_verify_device(udev);
 
- 	/* 10.5.4.5 says be sure devices in the tree are still there.
- 	 * For now let's assume the device didn't go crazy on resume,
+	/* 10.5.4.5 says be sure devices in the tree are still there.
+	 * For now let's assume the device didn't go crazy on resume,
 	 * and device drivers will know about any resume quirks.
 	 */
 	if (status == 0) {
@@ -3211,7 +3217,7 @@
 	if (status == 0 && !port_is_suspended(hub, portstatus))
 		goto SuspendCleared;
 
-	// dev_dbg(hub->intfdev, "resume port %d\n", port1);
+	/* dev_dbg(hub->intfdev, "resume port %d\n", port1); */
 
 	set_bit(port1, hub->busy_bits);
 
@@ -3855,7 +3861,7 @@
  * Between connect detection and reset signaling there must be a delay
  * of 100ms at least for debounce and power-settling.  The corresponding
  * timer shall restart whenever the downstream port detects a disconnect.
- * 
+ *
  * Apparently there are some bluetooth and irda-dongles and a number of
  * low-speed devices for which this debounce period may last over a second.
  * Not covered by the spec - but easy to deal with.
@@ -3949,6 +3955,32 @@
 	return retval;
 }
 
+/*
+ * There are reports of USB 3.0 devices that say they support USB 2.0 Link PM
+ * when they're plugged into a USB 2.0 port, but they don't work when LPM is
+ * enabled.
+ *
+ * Only enable USB 2.0 Link PM if the port is internal (hardwired), or the
+ * device says it supports the new USB 2.0 Link PM errata by setting the BESL
+ * support bit in the BOS descriptor.
+ */
+static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev)
+{
+	int connect_type;
+
+	if (!udev->usb2_hw_lpm_capable)
+		return;
+
+	connect_type = usb_get_hub_port_connect_type(udev->parent,
+			udev->portnum);
+
+	if ((udev->bos->ext_cap->bmAttributes & USB_BESL_SUPPORT) ||
+			connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) {
+		udev->usb2_hw_lpm_allowed = 1;
+		usb_set_usb2_hardware_lpm(udev, 1);
+	}
+}
+
 /* Reset device, (re)assign address, get device descriptor.
  * Device connection must be stable, no more debouncing needed.
  * Returns device in USB_STATE_ADDRESS, except on error.
@@ -4055,7 +4087,7 @@
 		udev->tt = &hub->tt;
 		udev->ttport = port1;
 	}
- 
+
 	/* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way?
 	 * Because device hardware and firmware is sometimes buggy in
 	 * this area, and this is how Linux has done it for ages.
@@ -4130,11 +4162,11 @@
 #undef GET_DESCRIPTOR_BUFSIZE
 		}
 
- 		/*
- 		 * If device is WUSB, we already assigned an
- 		 * unauthorized address in the Connect Ack sequence;
- 		 * authorization will assign the final address.
- 		 */
+		/*
+		 * If device is WUSB, we already assigned an
+		 * unauthorized address in the Connect Ack sequence;
+		 * authorization will assign the final address.
+		 */
 		if (udev->wusb == 0) {
 			for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
 				retval = hub_set_address(udev, devnum);
@@ -4163,7 +4195,7 @@
 			msleep(10);
 			if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3))
 				break;
-  		}
+		}
 
 		retval = usb_get_device_descriptor(udev, 8);
 		if (retval < 8) {
@@ -4219,7 +4251,7 @@
 		udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);
 		usb_ep0_reinit(udev);
 	}
-  
+
 	retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
 	if (retval < (signed)sizeof(udev->descriptor)) {
 		if (retval != -ENODEV)
@@ -4242,6 +4274,7 @@
 	/* notify HCD that we have a device connected and addressed */
 	if (hcd->driver->update_device)
 		hcd->driver->update_device(hcd, udev);
+	hub_set_initial_usb2_lpm_policy(udev);
 fail:
 	if (retval) {
 		hub_port_disable(hub, port1, 0);
@@ -4316,7 +4349,7 @@
 	}
 	if (remaining < 0) {
 		dev_warn(hub->intfdev, "%dmA over power budget!\n",
-			- remaining);
+			-remaining);
 		remaining = 0;
 	}
 	return remaining;
@@ -4427,7 +4460,7 @@
 			set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
 
 		if (portstatus & USB_PORT_STAT_ENABLE)
-  			goto done;
+			goto done;
 		return;
 	}
 	if (hub_is_superspeed(hub->hdev))
@@ -4450,7 +4483,7 @@
 		}
 
 		usb_set_device_state(udev, USB_STATE_POWERED);
- 		udev->bus_mA = hub->mA_per_port;
+		udev->bus_mA = hub->mA_per_port;
 		udev->level = hdev->level + 1;
 		udev->wusb = hub_is_wusb(hub);
 
@@ -4504,7 +4537,7 @@
 				goto loop_disable;
 			}
 		}
- 
+
 		/* check for devices running slower than they could */
 		if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0200
 				&& udev->speed == USB_SPEED_FULL
@@ -4564,7 +4597,7 @@
 			dev_err(hub_dev, "unable to enumerate USB device on port %d\n",
 					port1);
 	}
- 
+
 done:
 	hub_port_disable(hub, port1, 1);
 	if (hcd->driver->relinquish_port && !hub->hdev->parent)
@@ -4729,7 +4762,7 @@
 				 * EM interference sometimes causes badly
 				 * shielded USB devices to be shutdown by
 				 * the hub, this hack enables them again.
-				 * Works at least with mouse driver. 
+				 * Works at least with mouse driver.
 				 */
 				if (!(portstatus & USB_PORT_STAT_ENABLE)
 				    && !connect_change
@@ -4841,7 +4874,7 @@
 				dev_dbg(hub_dev, "over-current change\n");
 				clear_hub_feature(hdev, C_HUB_OVER_CURRENT);
 				msleep(500);	/* Cool down */
-                        	hub_power_on(hub, true);
+				hub_power_on(hub, true);
 				hub_hub_status(hub, &status, &unused);
 				if (status & HUB_STATUS_OVERCURRENT)
 					dev_err(hub_dev, "over-current "
@@ -4861,7 +4894,7 @@
 		usb_unlock_device(hdev);
 		kref_put(&hub->kref, hub_release);
 
-        } /* end while (1) */
+	} /* end while (1) */
 }
 
 static int hub_thread(void *__unused)
@@ -4886,7 +4919,7 @@
 
 static const struct usb_device_id hub_id_table[] = {
     { .match_flags = USB_DEVICE_ID_MATCH_VENDOR
-	           | USB_DEVICE_ID_MATCH_INT_CLASS,
+			| USB_DEVICE_ID_MATCH_INT_CLASS,
       .idVendor = USB_VENDOR_GENESYS_LOGIC,
       .bInterfaceClass = USB_CLASS_HUB,
       .driver_info = HUB_QUIRK_CHECK_PORT_AUTOSUSPEND},
@@ -5086,6 +5119,12 @@
 	}
 	parent_hub = usb_hub_to_struct_hub(parent_hdev);
 
+	/* Disable USB2 hardware LPM.
+	 * It will be re-enabled by the enumeration process.
+	 */
+	if (udev->usb2_hw_lpm_enabled == 1)
+		usb_set_usb2_hardware_lpm(udev, 0);
+
 	bos = udev->bos;
 	udev->bos = NULL;
 
@@ -5120,13 +5159,13 @@
 
 	if (ret < 0)
 		goto re_enumerate;
- 
+
 	/* Device might have changed firmware (DFU or similar) */
 	if (descriptors_changed(udev, &descriptor, bos)) {
 		dev_info(&udev->dev, "device firmware changed\n");
 		udev->descriptor = descriptor;	/* for disconnect() calls */
 		goto re_enumerate;
-  	}
+	}
 
 	/* Restore the device's previous configuration */
 	if (!udev->actconfig)
@@ -5151,7 +5190,7 @@
 			udev->actconfig->desc.bConfigurationValue, ret);
 		mutex_unlock(hcd->bandwidth_mutex);
 		goto re_enumerate;
-  	}
+	}
 	mutex_unlock(hcd->bandwidth_mutex);
 	usb_set_device_state(udev, USB_STATE_CONFIGURED);
 
@@ -5193,12 +5232,13 @@
 
 done:
 	/* Now that the alt settings are re-installed, enable LTM and LPM. */
+	usb_set_usb2_hardware_lpm(udev, 1);
 	usb_unlocked_enable_lpm(udev);
 	usb_enable_ltm(udev);
 	usb_release_bos_descriptor(udev);
 	udev->bos = bos;
 	return 0;
- 
+
 re_enumerate:
 	/* LPM state doesn't matter when we're about to destroy the device. */
 	hub_port_logical_disconnect(parent_hub, port1);
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 82927e1..bb31597 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1182,8 +1182,12 @@
 			put_device(&dev->actconfig->interface[i]->dev);
 			dev->actconfig->interface[i] = NULL;
 		}
+
+		if (dev->usb2_hw_lpm_enabled == 1)
+			usb_set_usb2_hardware_lpm(dev, 0);
 		usb_unlocked_disable_lpm(dev);
 		usb_disable_ltm(dev);
+
 		dev->actconfig = NULL;
 		if (dev->state == USB_STATE_CONFIGURED)
 			usb_set_device_state(dev, USB_STATE_ADDRESS);
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 5b44cd4..12924db 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -13,6 +13,7 @@
 
 #include <linux/usb.h>
 #include <linux/usb/quirks.h>
+#include <linux/usb/hcd.h>
 #include "usb.h"
 
 /* Lists of quirky USB devices, split in device quirks and interface quirks.
@@ -97,6 +98,9 @@
 	/* Alcor Micro Corp. Hub */
 	{ USB_DEVICE(0x058f, 0x9254), .driver_info = USB_QUIRK_RESET_RESUME },
 
+	/* MicroTouch Systems touchscreen */
+	{ USB_DEVICE(0x0596, 0x051e), .driver_info = USB_QUIRK_RESET_RESUME },
+
 	/* appletouch */
 	{ USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME },
 
@@ -130,6 +134,9 @@
 	/* Broadcom BCM92035DGROM BT dongle */
 	{ USB_DEVICE(0x0a5c, 0x2021), .driver_info = USB_QUIRK_RESET_RESUME },
 
+	/* MAYA44USB sound device */
+	{ USB_DEVICE(0x0a92, 0x0091), .driver_info = USB_QUIRK_RESET_RESUME },
+
 	/* Action Semiconductor flash disk */
 	{ USB_DEVICE(0x10d6, 0x2200), .driver_info =
 			USB_QUIRK_STRING_FETCH_255 },
@@ -155,6 +162,21 @@
 	{ }  /* terminating entry must be last */
 };
 
+static const struct usb_device_id usb_amd_resume_quirk_list[] = {
+	/* Lenovo Mouse with Pixart controller */
+	{ USB_DEVICE(0x17ef, 0x602e), .driver_info = USB_QUIRK_RESET_RESUME },
+
+	/* Pixart Mouse */
+	{ USB_DEVICE(0x093a, 0x2500), .driver_info = USB_QUIRK_RESET_RESUME },
+	{ USB_DEVICE(0x093a, 0x2510), .driver_info = USB_QUIRK_RESET_RESUME },
+	{ USB_DEVICE(0x093a, 0x2521), .driver_info = USB_QUIRK_RESET_RESUME },
+
+	/* Logitech Optical Mouse M90/M100 */
+	{ USB_DEVICE(0x046d, 0xc05a), .driver_info = USB_QUIRK_RESET_RESUME },
+
+	{ }  /* terminating entry must be last */
+};
+
 static bool usb_match_any_interface(struct usb_device *udev,
 				    const struct usb_device_id *id)
 {
@@ -181,6 +203,18 @@
 	return false;
 }
 
+static int usb_amd_resume_quirk(struct usb_device *udev)
+{
+	struct usb_hcd *hcd;
+
+	hcd = bus_to_hcd(udev->bus);
+	/* The device should be attached directly to root hub */
+	if (udev->level == 1 && hcd->amd_resume_bug == 1)
+		return 1;
+
+	return 0;
+}
+
 static u32 __usb_detect_quirks(struct usb_device *udev,
 			       const struct usb_device_id *id)
 {
@@ -206,6 +240,15 @@
 void usb_detect_quirks(struct usb_device *udev)
 {
 	udev->quirks = __usb_detect_quirks(udev, usb_quirk_list);
+
+	/*
+	 * Pixart-based mice would trigger remote wakeup issue on AMD
+	 * Yangtze chipset, so set them as RESET_RESUME flag.
+	 */
+	if (usb_amd_resume_quirk(udev))
+		udev->quirks |= __usb_detect_quirks(udev,
+				usb_amd_resume_quirk_list);
+
 	if (udev->quirks)
 		dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
 			udev->quirks);
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 6d2c8ed..52a97ad 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -23,14 +23,16 @@
 {									\
 	struct usb_device *udev;					\
 	struct usb_host_config *actconfig;				\
+	ssize_t rc = 0;							\
 									\
 	udev = to_usb_device(dev);					\
+	usb_lock_device(udev);						\
 	actconfig = udev->actconfig;					\
 	if (actconfig)							\
-		return sprintf(buf, format_string,			\
+		rc = sprintf(buf, format_string,			\
 				actconfig->desc.field);			\
-	else								\
-		return 0;						\
+	usb_unlock_device(udev);					\
+	return rc;							\
 }									\
 
 #define usb_actconfig_attr(field, format_string)		\
@@ -45,12 +47,15 @@
 {
 	struct usb_device *udev;
 	struct usb_host_config *actconfig;
+	ssize_t rc = 0;
 
 	udev = to_usb_device(dev);
+	usb_lock_device(udev);
 	actconfig = udev->actconfig;
-	if (!actconfig)
-		return 0;
-	return sprintf(buf, "%dmA\n", usb_get_max_power(udev, actconfig));
+	if (actconfig)
+		rc = sprintf(buf, "%dmA\n", usb_get_max_power(udev, actconfig));
+	usb_unlock_device(udev);
+	return rc;
 }
 static DEVICE_ATTR_RO(bMaxPower);
 
@@ -59,12 +64,15 @@
 {
 	struct usb_device *udev;
 	struct usb_host_config *actconfig;
+	ssize_t rc = 0;
 
 	udev = to_usb_device(dev);
+	usb_lock_device(udev);
 	actconfig = udev->actconfig;
-	if ((!actconfig) || (!actconfig->string))
-		return 0;
-	return sprintf(buf, "%s\n", actconfig->string);
+	if (actconfig && actconfig->string)
+		rc = sprintf(buf, "%s\n", actconfig->string);
+	usb_unlock_device(udev);
+	return rc;
 }
 static DEVICE_ATTR_RO(configuration);
 
@@ -390,7 +398,8 @@
 static const char on_string[] = "on";
 static const char auto_string[] = "auto";
 
-static void warn_level(void) {
+static void warn_level(void)
+{
 	static int level_warned;
 
 	if (!level_warned) {
@@ -449,7 +458,7 @@
 	struct usb_device *udev = to_usb_device(dev);
 	const char *p;
 
-	if (udev->usb2_hw_lpm_enabled == 1)
+	if (udev->usb2_hw_lpm_allowed == 1)
 		p = "enabled";
 	else
 		p = "disabled";
@@ -469,8 +478,10 @@
 
 	ret = strtobool(buf, &value);
 
-	if (!ret)
+	if (!ret) {
+		udev->usb2_hw_lpm_allowed = value;
 		ret = usb_set_usb2_hardware_lpm(udev, value);
+	}
 
 	usb_unlock_device(udev);
 
@@ -644,7 +655,7 @@
 		result = usb_deauthorize_device(usb_dev);
 	else
 		result = usb_authorize_device(usb_dev);
-	return result < 0? result : size;
+	return result < 0 ? result : size;
 }
 static DEVICE_ATTR_IGNORE_LOCKDEP(authorized, S_IRUGO | S_IWUSR,
 				  authorized_show, authorized_store);
@@ -764,6 +775,7 @@
 	 * Following that are the raw descriptor entries for all the
 	 * configurations (config plus subsidiary descriptors).
 	 */
+	usb_lock_device(udev);
 	for (cfgno = -1; cfgno < udev->descriptor.bNumConfigurations &&
 			nleft > 0; ++cfgno) {
 		if (cfgno < 0) {
@@ -784,6 +796,7 @@
 			off -= srclen;
 		}
 	}
+	usb_unlock_device(udev);
 	return count - nleft;
 }
 
@@ -870,9 +883,7 @@
 	char *string;
 
 	intf = to_usb_interface(dev);
-	string = intf->cur_altsetting->string;
-	barrier();		/* The altsetting might change! */
-
+	string = ACCESS_ONCE(intf->cur_altsetting->string);
 	if (!string)
 		return 0;
 	return sprintf(buf, "%s\n", string);
@@ -888,7 +899,7 @@
 
 	intf = to_usb_interface(dev);
 	udev = interface_to_usbdev(intf);
-	alt = intf->cur_altsetting;
+	alt = ACCESS_ONCE(intf->cur_altsetting);
 
 	return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X"
 			"ic%02Xisc%02Xip%02Xin%02X\n",
@@ -909,23 +920,14 @@
 					 struct device_attribute *attr,
 					 char *buf)
 {
-	struct usb_interface *intf;
-	struct usb_device *udev;
-	int ret;
+	int s;
 
-	intf = to_usb_interface(dev);
-	udev = interface_to_usbdev(intf);
-
-	usb_lock_device(udev);
+	device_lock(dev);
 	/* Devices will be autosuspended even when an interface isn't claimed */
-	if (!intf->dev.driver ||
-			to_usb_driver(intf->dev.driver)->supports_autosuspend)
-		ret = sprintf(buf, "%u\n", 1);
-	else
-		ret = sprintf(buf, "%u\n", 0);
-	usb_unlock_device(udev);
+	s = (!dev->driver || to_usb_driver(dev->driver)->supports_autosuspend);
+	device_unlock(dev);
 
-	return ret;
+	return sprintf(buf, "%u\n", s);
 }
 static DEVICE_ATTR_RO(supports_autosuspend);
 
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index c12bc79..e622083 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -138,13 +138,19 @@
 }
 EXPORT_SYMBOL_GPL(usb_anchor_urb);
 
+static int usb_anchor_check_wakeup(struct usb_anchor *anchor)
+{
+	return atomic_read(&anchor->suspend_wakeups) == 0 &&
+		list_empty(&anchor->urb_list);
+}
+
 /* Callers must hold anchor->lock */
 static void __usb_unanchor_urb(struct urb *urb, struct usb_anchor *anchor)
 {
 	urb->anchor = NULL;
 	list_del(&urb->anchor_list);
 	usb_put_urb(urb);
-	if (list_empty(&anchor->urb_list))
+	if (usb_anchor_check_wakeup(anchor))
 		wake_up(&anchor->wait);
 }
 
@@ -846,6 +852,39 @@
 EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs);
 
 /**
+ * usb_anchor_suspend_wakeups
+ * @anchor: the anchor you want to suspend wakeups on
+ *
+ * Call this to stop the last urb being unanchored from waking up any
+ * usb_wait_anchor_empty_timeout waiters. This is used in the hcd urb give-
+ * back path to delay waking up until after the completion handler has run.
+ */
+void usb_anchor_suspend_wakeups(struct usb_anchor *anchor)
+{
+	if (anchor)
+		atomic_inc(&anchor->suspend_wakeups);
+}
+EXPORT_SYMBOL_GPL(usb_anchor_suspend_wakeups);
+
+/**
+ * usb_anchor_resume_wakeups
+ * @anchor: the anchor you want to resume wakeups on
+ *
+ * Allow usb_wait_anchor_empty_timeout waiters to be woken up again, and
+ * wake up any current waiters if the anchor is empty.
+ */
+void usb_anchor_resume_wakeups(struct usb_anchor *anchor)
+{
+	if (!anchor)
+		return;
+
+	atomic_dec(&anchor->suspend_wakeups);
+	if (usb_anchor_check_wakeup(anchor))
+		wake_up(&anchor->wait);
+}
+EXPORT_SYMBOL_GPL(usb_anchor_resume_wakeups);
+
+/**
  * usb_wait_anchor_empty_timeout - wait for an anchor to be unused
  * @anchor: the anchor you want to become unused
  * @timeout: how long you are willing to wait in milliseconds
@@ -858,7 +897,8 @@
 int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
 				  unsigned int timeout)
 {
-	return wait_event_timeout(anchor->wait, list_empty(&anchor->urb_list),
+	return wait_event_timeout(anchor->wait,
+				  usb_anchor_check_wakeup(anchor),
 				  msecs_to_jiffies(timeout));
 }
 EXPORT_SYMBOL_GPL(usb_wait_anchor_empty_timeout);
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 0a6ee2e..4d11449 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -497,7 +497,7 @@
 		dev->authorized = 1;
 	else {
 		dev->authorized = usb_hcd->authorized_default;
-		dev->wusb = usb_bus_is_wusb(bus)? 1 : 0;
+		dev->wusb = usb_bus_is_wusb(bus) ? 1 : 0;
 	}
 	return dev;
 }
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 8238577..c493836 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -35,6 +35,7 @@
 		unsigned int size);
 extern int usb_get_bos_descriptor(struct usb_device *dev);
 extern void usb_release_bos_descriptor(struct usb_device *dev);
+extern int usb_device_supports_lpm(struct usb_device *udev);
 extern char *usb_cache_string(struct usb_device *udev, int index);
 extern int usb_set_configuration(struct usb_device *dev, int configuration);
 extern int usb_choose_configuration(struct usb_device *udev);
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 474162e..74f9cf0 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -584,7 +584,7 @@
 	usb_phy_set_suspend(dwc->usb2_phy, 1);
 	usb_phy_set_suspend(dwc->usb3_phy, 1);
 
-	pm_runtime_put(&pdev->dev);
+	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 
 	dwc3_debugfs_exit(dwc);
@@ -691,7 +691,6 @@
 
 	usb_phy_init(dwc->usb3_phy);
 	usb_phy_init(dwc->usb2_phy);
-	msleep(100);
 
 	spin_lock_irqsave(&dwc->lock, flags);
 
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index 2e252aa..31443ae 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -165,7 +165,6 @@
 	return 0;
 
 err3:
-	pci_set_drvdata(pci, NULL);
 	platform_device_put(dwc3);
 err1:
 	pci_disable_device(pci);
@@ -180,7 +179,6 @@
 	platform_device_unregister(glue->dwc3);
 	platform_device_unregister(glue->usb2_phy);
 	platform_device_unregister(glue->usb3_phy);
-	pci_set_drvdata(pci, NULL);
 	pci_disable_device(pci);
 }
 
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 7fa93f4..95f7649 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -352,7 +352,7 @@
 		break;
 	default:
 		return -EINVAL;
-	};
+	}
 
 	response_pkt = (__le16 *) dwc->setup_buf;
 	*response_pkt = cpu_to_le16(usb_status);
@@ -470,7 +470,7 @@
 
 	default:
 		return -EINVAL;
-	};
+	}
 
 	return 0;
 }
@@ -709,7 +709,7 @@
 		dev_vdbg(dwc->dev, "Forwarding to gadget driver\n");
 		ret = dwc3_ep0_delegate_req(dwc, ctrl);
 		break;
-	};
+	}
 
 	return ret;
 }
diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c
index 5e29dde..8cfc319 100644
--- a/drivers/usb/early/ehci-dbgp.c
+++ b/drivers/usb/early/ehci-dbgp.c
@@ -568,10 +568,6 @@
 		dbgp_printk("Could not find attached debug device\n");
 		goto err;
 	}
-	if (ret < 0) {
-		dbgp_printk("Attached device is not a debug device\n");
-		goto err;
-	}
 	dbgp_endpoint_out = dbgp_desc.bDebugOutEndpoint;
 	dbgp_endpoint_in = dbgp_desc.bDebugInEndpoint;
 
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 48cddf3..a91e642 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -58,6 +58,20 @@
 	   trying to track down.  Never enable these messages for a
 	   production build.
 
+config USB_GADGET_VERBOSE
+	bool "Verbose debugging Messages (DEVELOPMENT)"
+	depends on USB_GADGET_DEBUG
+	help
+	   Many controller and gadget drivers will print verbose debugging
+	   messages if you use this option to ask for those messages.
+
+	   Avoid enabling these messages, even if you're actively
+	   debugging such a driver.  Many drivers will emit so many
+	   messages that the driver timings are affected, which will
+	   either create new failure modes or remove the one you're
+	   trying to track down.  Never enable these messages for a
+	   production build.
+
 config USB_GADGET_DEBUG_FILES
 	boolean "Debugging information files (DEVELOPMENT)"
 	depends on PROC_FS
@@ -525,6 +539,9 @@
 config USB_F_RNDIS
 	tristate
 
+config USB_F_MASS_STORAGE
+	tristate
+
 choice
 	tristate "USB Gadget Drivers"
 	default USB_ETH
@@ -662,6 +679,16 @@
 	help
 	  The Phonet protocol implementation for USB device.
 
+config USB_CONFIGFS_MASS_STORAGE
+	boolean "Mass storage"
+	depends on USB_CONFIGFS
+	select USB_F_MASS_STORAGE
+	help
+	  The Mass Storage Gadget acts as a USB Mass Storage disk drive.
+	  As its storage repository it can use a regular file or a block
+	  device (in much the same way as the "loop" device driver),
+	  specified as a module parameter or sysfs option.
+
 config USB_ZERO
 	tristate "Gadget Zero (DEVELOPMENT)"
 	select USB_LIBCOMPOSITE
@@ -878,6 +905,7 @@
 	tristate "Mass Storage Gadget"
 	depends on BLOCK
 	select USB_LIBCOMPOSITE
+	select USB_F_MASS_STORAGE
 	help
 	  The Mass Storage Gadget acts as a USB Mass Storage disk drive.
 	  As its storage repository it can use a regular file or a block
@@ -1001,6 +1029,7 @@
 	select USB_LIBCOMPOSITE
 	select USB_U_SERIAL
 	select USB_F_ACM
+	select USB_F_MASS_STORAGE
 	help
 	  This driver provides two functions in one configuration:
 	  a mass storage, and a CDC ACM (serial port) link.
@@ -1015,8 +1044,8 @@
 	select USB_LIBCOMPOSITE
 	select USB_U_SERIAL
 	select USB_U_ETHER
-	select USB_U_RNDIS
 	select USB_F_ACM
+	select USB_F_MASS_STORAGE
 	help
 	  The Multifunction Composite Gadget provides Ethernet (RNDIS
 	  and/or CDC Ethernet), mass storage and ACM serial link
@@ -1035,6 +1064,8 @@
 config USB_G_MULTI_RNDIS
 	bool "RNDIS + CDC Serial + Storage configuration"
 	depends on USB_G_MULTI
+	select USB_U_RNDIS
+	select USB_F_RNDIS
 	default y
 	help
 	  This option enables a configuration with RNDIS, CDC Serial and
@@ -1048,6 +1079,7 @@
 	bool "CDC Ethernet + CDC Serial + Storage configuration"
 	depends on USB_G_MULTI
 	default n
+	select USB_F_ECM
 	help
 	  This option enables a configuration with CDC Ethernet (ECM), CDC
 	  Serial and Mass Storage functions available in the Multifunction
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 386db9d..f1af396 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -1,7 +1,8 @@
 #
 # USB peripheral controller drivers
 #
-ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
+ccflags-$(CONFIG_USB_GADGET_DEBUG)	:= -DDEBUG
+ccflags-$(CONFIG_USB_GADGET_VERBOSE)	+= -DVERBOSE_DEBUG
 
 obj-$(CONFIG_USB_GADGET)	+= udc-core.o
 obj-$(CONFIG_USB_LIBCOMPOSITE)	+= libcomposite.o
@@ -60,6 +61,8 @@
 obj-$(CONFIG_USB_F_SUBSET)	+= usb_f_ecm_subset.o
 usb_f_rndis-y			:= f_rndis.o
 obj-$(CONFIG_USB_F_RNDIS)	+= usb_f_rndis.o
+usb_f_mass_storage-y		:= f_mass_storage.o storage_common.o
+obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
 
 #
 # USB gadget drivers
diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/acm_ms.c
index 4b947bb..7bfa134 100644
--- a/drivers/usb/gadget/acm_ms.c
+++ b/drivers/usb/gadget/acm_ms.c
@@ -31,16 +31,7 @@
 #define ACM_MS_VENDOR_NUM	0x1d6b	/* Linux Foundation */
 #define ACM_MS_PRODUCT_NUM	0x0106	/* Composite Gadget: ACM + MS*/
 
-/*-------------------------------------------------------------------------*/
-
-/*
- * Kbuild is not very cooperative with respect to linking separately
- * compiled library objects into one module.  So for now we won't use
- * separate compilation ... ensuring init/exit sections work to shrink
- * the runtime footprint, and giving us at least some parts of what
- * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
- */
-#include "f_mass_storage.c"
+#include "f_mass_storage.h"
 
 /*-------------------------------------------------------------------------*/
 USB_GADGET_COMPOSITE_OPTIONS();
@@ -104,18 +95,35 @@
 /****************************** Configurations ******************************/
 
 static struct fsg_module_parameters fsg_mod_data = { .stall = 1 };
-FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
 
-static struct fsg_common fsg_common;
+static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
+
+#else
+
+/*
+ * Number of buffers we will use.
+ * 2 is usually enough for good buffering pipeline
+ */
+#define fsg_num_buffers	CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
+
+#endif /* CONFIG_USB_DEBUG */
+
+FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
 
 /*-------------------------------------------------------------------------*/
 static struct usb_function *f_acm;
 static struct usb_function_instance *f_acm_inst;
+
+static struct usb_function_instance *fi_msg;
+static struct usb_function *f_msg;
+
 /*
  * We _always_ have both ACM and mass storage functions.
  */
 static int __init acm_ms_do_config(struct usb_configuration *c)
 {
+	struct fsg_opts *opts;
 	int	status;
 
 	if (gadget_is_otg(c->cdev->gadget)) {
@@ -123,31 +131,37 @@
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	f_acm_inst = usb_get_function_instance("acm");
-	if (IS_ERR(f_acm_inst))
-		return PTR_ERR(f_acm_inst);
+	opts = fsg_opts_from_func_inst(fi_msg);
 
 	f_acm = usb_get_function(f_acm_inst);
-	if (IS_ERR(f_acm)) {
-		status = PTR_ERR(f_acm);
-		goto err_func;
+	if (IS_ERR(f_acm))
+		return PTR_ERR(f_acm);
+
+	f_msg = usb_get_function(fi_msg);
+	if (IS_ERR(f_msg)) {
+		status = PTR_ERR(f_msg);
+		goto put_acm;
 	}
 
 	status = usb_add_function(c, f_acm);
 	if (status < 0)
-		goto err_conf;
+		goto put_msg;
 
-	status = fsg_bind_config(c->cdev, c, &fsg_common);
-	if (status < 0)
-		goto err_fsg;
+	status = fsg_common_run_thread(opts->common);
+	if (status)
+		goto remove_acm;
+
+	status = usb_add_function(c, f_msg);
+	if (status)
+		goto remove_acm;
 
 	return 0;
-err_fsg:
+remove_acm:
 	usb_remove_function(c, f_acm);
-err_conf:
+put_msg:
+	usb_put_function(f_msg);
+put_acm:
 	usb_put_function(f_acm);
-err_func:
-	usb_put_function_instance(f_acm_inst);
 	return status;
 }
 
@@ -163,45 +177,82 @@
 static int __init acm_ms_bind(struct usb_composite_dev *cdev)
 {
 	struct usb_gadget	*gadget = cdev->gadget;
+	struct fsg_opts		*opts;
+	struct fsg_config	config;
 	int			status;
-	void			*retp;
 
-	/* set up mass storage function */
-	retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data);
-	if (IS_ERR(retp)) {
-		status = PTR_ERR(retp);
-		return PTR_ERR(retp);
+	f_acm_inst = usb_get_function_instance("acm");
+	if (IS_ERR(f_acm_inst))
+		return PTR_ERR(f_acm_inst);
+
+	fi_msg = usb_get_function_instance("mass_storage");
+	if (IS_ERR(fi_msg)) {
+		status = PTR_ERR(fi_msg);
+		goto fail_get_msg;
 	}
 
+	/* set up mass storage function */
+	fsg_config_from_params(&config, &fsg_mod_data, fsg_num_buffers);
+	opts = fsg_opts_from_func_inst(fi_msg);
+
+	opts->no_configfs = true;
+	status = fsg_common_set_num_buffers(opts->common, fsg_num_buffers);
+	if (status)
+		goto fail;
+
+	status = fsg_common_set_nluns(opts->common, config.nluns);
+	if (status)
+		goto fail_set_nluns;
+
+	status = fsg_common_set_cdev(opts->common, cdev, config.can_stall);
+	if (status)
+		goto fail_set_cdev;
+
+	fsg_common_set_sysfs(opts->common, true);
+	status = fsg_common_create_luns(opts->common, &config);
+	if (status)
+		goto fail_set_cdev;
+
+	fsg_common_set_inquiry_string(opts->common, config.vendor_name,
+				      config.product_name);
 	/*
 	 * Allocate string descriptor numbers ... note that string
 	 * contents can be overridden by the composite_dev glue.
 	 */
 	status = usb_string_ids_tab(cdev, strings_dev);
 	if (status < 0)
-		goto fail1;
+		goto fail_string_ids;
 	device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
 	device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
 
 	/* register our configuration */
 	status = usb_add_config(cdev, &acm_ms_config_driver, acm_ms_do_config);
 	if (status < 0)
-		goto fail1;
+		goto fail_string_ids;
 
 	usb_composite_overwrite_options(cdev, &coverwrite);
 	dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
 			DRIVER_DESC);
-	fsg_common_put(&fsg_common);
 	return 0;
 
 	/* error recovery */
-fail1:
-	fsg_common_put(&fsg_common);
+fail_string_ids:
+	fsg_common_remove_luns(opts->common);
+fail_set_cdev:
+	fsg_common_free_luns(opts->common);
+fail_set_nluns:
+	fsg_common_free_buffers(opts->common);
+fail:
+	usb_put_function_instance(fi_msg);
+fail_get_msg:
+	usb_put_function_instance(f_acm_inst);
 	return status;
 }
 
 static int __exit acm_ms_unbind(struct usb_composite_dev *cdev)
 {
+	usb_put_function(f_msg);
+	usb_put_function_instance(fi_msg);
 	usb_put_function(f_acm);
 	usb_put_function_instance(f_acm_inst);
 	return 0;
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index a9a4346..54a1e29 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -3078,8 +3078,6 @@
 	if (dev->active)
 		pci_disable_device(pdev);
 
-	pci_set_drvdata(pdev, NULL);
-
 	udc_remove(dev);
 }
 
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index d4f0f33..3e7ae70 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -354,7 +354,7 @@
 		return DIV_ROUND_UP(val, 8);
 	default:
 		return DIV_ROUND_UP(val, 2);
-	};
+	}
 }
 
 static int config_buf(struct usb_configuration *config,
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 8f0d614..2588511 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -557,7 +557,7 @@
 
 	fi = usb_get_function_instance(func_name);
 	if (IS_ERR(fi))
-		return ERR_PTR(PTR_ERR(fi));
+		return ERR_CAST(fi);
 
 	ret = config_item_set_name(&fi->group.cg_item, name);
 	if (ret) {
@@ -991,6 +991,14 @@
 	.su_mutex = __MUTEX_INITIALIZER(gadget_subsys.su_mutex),
 };
 
+void unregister_gadget_item(struct config_item *item)
+{
+	struct gadget_info *gi = to_gadget_info(item);
+
+	unregister_gadget(gi);
+}
+EXPORT_SYMBOL(unregister_gadget_item);
+
 static int __init gadget_cfs_init(void)
 {
 	int ret;
diff --git a/drivers/usb/gadget/configfs.h b/drivers/usb/gadget/configfs.h
new file mode 100644
index 0000000..a7b564a
--- /dev/null
+++ b/drivers/usb/gadget/configfs.h
@@ -0,0 +1,6 @@
+#ifndef USB__GADGET__CONFIGFS__H
+#define USB__GADGET__CONFIGFS__H
+
+void unregister_gadget_item(struct config_item *item);
+
+#endif /*  USB__GADGET__CONFIGFS__H */
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index b8a2376..8f4dae3 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -544,7 +544,7 @@
 		 default:
 			 val = "ctrl";
 			 break;
-		 }; val; }),
+		 } val; }),
 		max, ep->stream_en ? "enabled" : "disabled");
 
 	/* at this point real hardware should be NAKing transfers
@@ -2271,7 +2271,7 @@
 		default:
 			s = "?";
 			break;
-		 }; s; }),
+		 } s; }),
 		ep, ep ? (usb_pipein(urb->pipe) ? "in" : "out") : "",
 		({ char *s; \
 		switch (usb_pipetype(urb->pipe)) { \
@@ -2287,7 +2287,7 @@
 		default: \
 			s = "-iso"; \
 			break; \
-		}; s; }),
+		} s; }),
 		urb->actual_length, urb->transfer_buffer_length);
 }
 
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index a01d7d3..a03ba2c 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -213,12 +213,14 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/freezer.h>
+#include <linux/module.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/composite.h>
 
 #include "gadget_chips.h"
+#include "configfs.h"
 
 
 /*------------------------------------------------------------------------*/
@@ -228,26 +230,30 @@
 
 static const char fsg_string_interface[] = "Mass Storage";
 
-#include "storage_common.c"
+#include "storage_common.h"
+#include "f_mass_storage.h"
 
+/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
+static struct usb_string		fsg_strings[] = {
+	{FSG_STRING_INTERFACE,		fsg_string_interface},
+	{}
+};
+
+static struct usb_gadget_strings	fsg_stringtab = {
+	.language	= 0x0409,		/* en-us */
+	.strings	= fsg_strings,
+};
+
+static struct usb_gadget_strings *fsg_strings_array[] = {
+	&fsg_stringtab,
+	NULL,
+};
 
 /*-------------------------------------------------------------------------*/
 
 struct fsg_dev;
 struct fsg_common;
 
-/* FSF callback functions */
-struct fsg_operations {
-	/*
-	 * Callback function to call when thread exits.  If no
-	 * callback is set or it returns value lower then zero MSF
-	 * will force eject all LUNs it operates on (including those
-	 * marked as non-removable or with prevent_medium_removal flag
-	 * set).
-	 */
-	int (*thread_exits)(struct fsg_common *common);
-};
-
 /* Data shared by all the FSG instances. */
 struct fsg_common {
 	struct usb_gadget	*gadget;
@@ -268,13 +274,14 @@
 	struct fsg_buffhd	*next_buffhd_to_fill;
 	struct fsg_buffhd	*next_buffhd_to_drain;
 	struct fsg_buffhd	*buffhds;
+	unsigned int		fsg_num_buffers;
 
 	int			cmnd_size;
 	u8			cmnd[MAX_COMMAND_SIZE];
 
 	unsigned int		nluns;
 	unsigned int		lun;
-	struct fsg_lun		*luns;
+	struct fsg_lun		**luns;
 	struct fsg_lun		*curlun;
 
 	unsigned int		bulk_out_maxpacket;
@@ -294,6 +301,7 @@
 	unsigned int		short_packet_received:1;
 	unsigned int		bad_lun_okay:1;
 	unsigned int		running:1;
+	unsigned int		sysfs:1;
 
 	int			thread_wakeup_needed;
 	struct completion	thread_notifier;
@@ -313,27 +321,6 @@
 	struct kref		ref;
 };
 
-struct fsg_config {
-	unsigned nluns;
-	struct fsg_lun_config {
-		const char *filename;
-		char ro;
-		char removable;
-		char cdrom;
-		char nofua;
-	} luns[FSG_MAX_LUNS];
-
-	/* Callback functions. */
-	const struct fsg_operations	*ops;
-	/* Gadget's private data. */
-	void			*private_data;
-
-	const char *vendor_name;		/*  8 characters or less */
-	const char *product_name;		/* 16 characters or less */
-
-	char			can_stall;
-};
-
 struct fsg_dev {
 	struct usb_function	function;
 	struct usb_gadget	*gadget;	/* Copy of cdev->gadget */
@@ -2172,7 +2159,7 @@
 		common->data_dir = DATA_DIR_NONE;
 	common->lun = cbw->Lun;
 	if (common->lun < common->nluns)
-		common->curlun = &common->luns[common->lun];
+		common->curlun = common->luns[common->lun];
 	else
 		common->curlun = NULL;
 	common->tag = cbw->Tag;
@@ -2244,7 +2231,7 @@
 	if (common->fsg) {
 		fsg = common->fsg;
 
-		for (i = 0; i < fsg_num_buffers; ++i) {
+		for (i = 0; i < common->fsg_num_buffers; ++i) {
 			struct fsg_buffhd *bh = &common->buffhds[i];
 
 			if (bh->inreq) {
@@ -2303,7 +2290,7 @@
 	clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
 
 	/* Allocate the requests */
-	for (i = 0; i < fsg_num_buffers; ++i) {
+	for (i = 0; i < common->fsg_num_buffers; ++i) {
 		struct fsg_buffhd	*bh = &common->buffhds[i];
 
 		rc = alloc_request(common, fsg->bulk_in, &bh->inreq);
@@ -2320,7 +2307,9 @@
 
 	common->running = 1;
 	for (i = 0; i < common->nluns; ++i)
-		common->luns[i].unit_attention_data = SS_RESET_OCCURRED;
+		if (common->luns[i])
+			common->luns[i]->unit_attention_data =
+				SS_RESET_OCCURRED;
 	return rc;
 }
 
@@ -2372,7 +2361,7 @@
 
 	/* Cancel all the pending transfers */
 	if (likely(common->fsg)) {
-		for (i = 0; i < fsg_num_buffers; ++i) {
+		for (i = 0; i < common->fsg_num_buffers; ++i) {
 			bh = &common->buffhds[i];
 			if (bh->inreq_busy)
 				usb_ep_dequeue(common->fsg->bulk_in, bh->inreq);
@@ -2384,7 +2373,7 @@
 		/* Wait until everything is idle */
 		for (;;) {
 			int num_active = 0;
-			for (i = 0; i < fsg_num_buffers; ++i) {
+			for (i = 0; i < common->fsg_num_buffers; ++i) {
 				bh = &common->buffhds[i];
 				num_active += bh->inreq_busy + bh->outreq_busy;
 			}
@@ -2407,7 +2396,7 @@
 	 */
 	spin_lock_irq(&common->lock);
 
-	for (i = 0; i < fsg_num_buffers; ++i) {
+	for (i = 0; i < common->fsg_num_buffers; ++i) {
 		bh = &common->buffhds[i];
 		bh->state = BUF_STATE_EMPTY;
 	}
@@ -2420,7 +2409,9 @@
 		common->state = FSG_STATE_STATUS_PHASE;
 	else {
 		for (i = 0; i < common->nluns; ++i) {
-			curlun = &common->luns[i];
+			curlun = common->luns[i];
+			if (!curlun)
+				continue;
 			curlun->prevent_medium_removal = 0;
 			curlun->sense_data = SS_NO_SENSE;
 			curlun->unit_attention_data = SS_NO_SENSE;
@@ -2462,8 +2453,9 @@
 		 * CONFIG_CHANGE cases.
 		 */
 		/* for (i = 0; i < common->nluns; ++i) */
-		/*	common->luns[i].unit_attention_data = */
-		/*		SS_RESET_OCCURRED;  */
+		/*	if (common->luns[i]) */
+		/*		common->luns[i]->unit_attention_data = */
+		/*			SS_RESET_OCCURRED;  */
 		break;
 
 	case FSG_STATE_CONFIG_CHANGE:
@@ -2559,12 +2551,13 @@
 
 	if (!common->ops || !common->ops->thread_exits
 	 || common->ops->thread_exits(common) < 0) {
-		struct fsg_lun *curlun = common->luns;
+		struct fsg_lun **curlun_it = common->luns;
 		unsigned i = common->nluns;
 
 		down_write(&common->filesem);
-		for (; i--; ++curlun) {
-			if (!fsg_lun_is_open(curlun))
+		for (; i--; ++curlun_it) {
+			struct fsg_lun *curlun = *curlun_it;
+			if (!curlun || !fsg_lun_is_open(curlun))
 				continue;
 
 			fsg_lun_close(curlun);
@@ -2580,6 +2573,56 @@
 
 /*************************** DEVICE ATTRIBUTES ***************************/
 
+static ssize_t ro_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct fsg_lun		*curlun = fsg_lun_from_dev(dev);
+
+	return fsg_show_ro(curlun, buf);
+}
+
+static ssize_t nofua_show(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	struct fsg_lun		*curlun = fsg_lun_from_dev(dev);
+
+	return fsg_show_nofua(curlun, buf);
+}
+
+static ssize_t file_show(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct fsg_lun		*curlun = fsg_lun_from_dev(dev);
+	struct rw_semaphore	*filesem = dev_get_drvdata(dev);
+
+	return fsg_show_file(curlun, filesem, buf);
+}
+
+static ssize_t ro_store(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct fsg_lun		*curlun = fsg_lun_from_dev(dev);
+	struct rw_semaphore	*filesem = dev_get_drvdata(dev);
+
+	return fsg_store_ro(curlun, filesem, buf, count);
+}
+
+static ssize_t nofua_store(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	struct fsg_lun		*curlun = fsg_lun_from_dev(dev);
+
+	return fsg_store_nofua(curlun, buf, count);
+}
+
+static ssize_t file_store(struct device *dev, struct device_attribute *attr,
+			  const char *buf, size_t count)
+{
+	struct fsg_lun		*curlun = fsg_lun_from_dev(dev);
+	struct rw_semaphore	*filesem = dev_get_drvdata(dev);
+
+	return fsg_store_file(curlun, filesem, buf, count);
+}
+
 static DEVICE_ATTR_RW(ro);
 static DEVICE_ATTR_RW(nofua);
 static DEVICE_ATTR_RW(file);
@@ -2597,221 +2640,422 @@
 	/* Nothing needs to be done */
 }
 
-static inline void fsg_common_get(struct fsg_common *common)
+void fsg_common_get(struct fsg_common *common)
 {
 	kref_get(&common->ref);
 }
+EXPORT_SYMBOL_GPL(fsg_common_get);
 
-static inline void fsg_common_put(struct fsg_common *common)
+void fsg_common_put(struct fsg_common *common)
 {
 	kref_put(&common->ref, fsg_common_release);
 }
+EXPORT_SYMBOL_GPL(fsg_common_put);
 
-static struct fsg_common *fsg_common_init(struct fsg_common *common,
-					  struct usb_composite_dev *cdev,
-					  struct fsg_config *cfg)
+/* check if fsg_num_buffers is within a valid range */
+static inline int fsg_num_buffers_validate(unsigned int fsg_num_buffers)
 {
-	struct usb_gadget *gadget = cdev->gadget;
-	struct fsg_buffhd *bh;
-	struct fsg_lun *curlun;
-	struct fsg_lun_config *lcfg;
-	int nluns, i, rc;
-	char *pathbuf;
+	if (fsg_num_buffers >= 2 && fsg_num_buffers <= 4)
+		return 0;
+	pr_err("fsg_num_buffers %u is out of range (%d to %d)\n",
+	       fsg_num_buffers, 2, 4);
+	return -EINVAL;
+}
 
-	rc = fsg_num_buffers_validate();
-	if (rc != 0)
-		return ERR_PTR(rc);
-
-	/* Find out how many LUNs there should be */
-	nluns = cfg->nluns;
-	if (nluns < 1 || nluns > FSG_MAX_LUNS) {
-		dev_err(&gadget->dev, "invalid number of LUNs: %u\n", nluns);
-		return ERR_PTR(-EINVAL);
-	}
-
-	/* Allocate? */
+static struct fsg_common *fsg_common_setup(struct fsg_common *common)
+{
 	if (!common) {
-		common = kzalloc(sizeof *common, GFP_KERNEL);
+		common = kzalloc(sizeof(*common), GFP_KERNEL);
 		if (!common)
 			return ERR_PTR(-ENOMEM);
 		common->free_storage_on_release = 1;
 	} else {
-		memset(common, 0, sizeof *common);
 		common->free_storage_on_release = 0;
 	}
-
-	common->buffhds = kcalloc(fsg_num_buffers,
-				  sizeof *(common->buffhds), GFP_KERNEL);
-	if (!common->buffhds) {
-		if (common->free_storage_on_release)
-			kfree(common);
-		return ERR_PTR(-ENOMEM);
-	}
-
-	common->ops = cfg->ops;
-	common->private_data = cfg->private_data;
-
-	common->gadget = gadget;
-	common->ep0 = gadget->ep0;
-	common->ep0req = cdev->req;
-	common->cdev = cdev;
-
-	/* Maybe allocate device-global string IDs, and patch descriptors */
-	if (fsg_strings[FSG_STRING_INTERFACE].id == 0) {
-		rc = usb_string_id(cdev);
-		if (unlikely(rc < 0))
-			goto error_release;
-		fsg_strings[FSG_STRING_INTERFACE].id = rc;
-		fsg_intf_desc.iInterface = rc;
-	}
-
-	/*
-	 * Create the LUNs, open their backing files, and register the
-	 * LUN devices in sysfs.
-	 */
-	curlun = kcalloc(nluns, sizeof(*curlun), GFP_KERNEL);
-	if (unlikely(!curlun)) {
-		rc = -ENOMEM;
-		goto error_release;
-	}
-	common->luns = curlun;
-
 	init_rwsem(&common->filesem);
+	spin_lock_init(&common->lock);
+	kref_init(&common->ref);
+	init_completion(&common->thread_notifier);
+	init_waitqueue_head(&common->fsg_wait);
+	common->state = FSG_STATE_TERMINATED;
 
-	for (i = 0, lcfg = cfg->luns; i < nluns; ++i, ++curlun, ++lcfg) {
-		curlun->cdrom = !!lcfg->cdrom;
-		curlun->ro = lcfg->cdrom || lcfg->ro;
-		curlun->initially_ro = curlun->ro;
-		curlun->removable = lcfg->removable;
-		curlun->dev.release = fsg_lun_release;
-		curlun->dev.parent = &gadget->dev;
-		/* curlun->dev.driver = &fsg_driver.driver; XXX */
-		dev_set_drvdata(&curlun->dev, &common->filesem);
-		dev_set_name(&curlun->dev, "lun%d", i);
+	return common;
+}
 
-		rc = device_register(&curlun->dev);
-		if (rc) {
-			INFO(common, "failed to register LUN%d: %d\n", i, rc);
-			common->nluns = i;
-			put_device(&curlun->dev);
-			goto error_release;
+void fsg_common_set_sysfs(struct fsg_common *common, bool sysfs)
+{
+	common->sysfs = sysfs;
+}
+EXPORT_SYMBOL_GPL(fsg_common_set_sysfs);
+
+static void _fsg_common_free_buffers(struct fsg_buffhd *buffhds, unsigned n)
+{
+	if (buffhds) {
+		struct fsg_buffhd *bh = buffhds;
+		while (n--) {
+			kfree(bh->buf);
+			++bh;
 		}
-
-		rc = device_create_file(&curlun->dev,
-					curlun->cdrom
-				      ? &dev_attr_ro_cdrom
-				      : &dev_attr_ro);
-		if (rc)
-			goto error_luns;
-		rc = device_create_file(&curlun->dev,
-					curlun->removable
-				      ? &dev_attr_file
-				      : &dev_attr_file_nonremovable);
-		if (rc)
-			goto error_luns;
-		rc = device_create_file(&curlun->dev, &dev_attr_nofua);
-		if (rc)
-			goto error_luns;
-
-		if (lcfg->filename) {
-			rc = fsg_lun_open(curlun, lcfg->filename);
-			if (rc)
-				goto error_luns;
-		} else if (!curlun->removable) {
-			ERROR(common, "no file given for LUN%d\n", i);
-			rc = -EINVAL;
-			goto error_luns;
-		}
+		kfree(buffhds);
 	}
-	common->nluns = nluns;
+}
+
+int fsg_common_set_num_buffers(struct fsg_common *common, unsigned int n)
+{
+	struct fsg_buffhd *bh, *buffhds;
+	int i, rc;
+
+	rc = fsg_num_buffers_validate(n);
+	if (rc != 0)
+		return rc;
+
+	buffhds = kcalloc(n, sizeof(*buffhds), GFP_KERNEL);
+	if (!buffhds)
+		return -ENOMEM;
 
 	/* Data buffers cyclic list */
-	bh = common->buffhds;
-	i = fsg_num_buffers;
+	bh = buffhds;
+	i = n;
 	goto buffhds_first_it;
 	do {
 		bh->next = bh + 1;
 		++bh;
 buffhds_first_it:
 		bh->buf = kmalloc(FSG_BUFLEN, GFP_KERNEL);
-		if (unlikely(!bh->buf)) {
-			rc = -ENOMEM;
+		if (unlikely(!bh->buf))
 			goto error_release;
-		}
 	} while (--i);
-	bh->next = common->buffhds;
+	bh->next = buffhds;
 
-	/* Prepare inquiryString */
-	i = get_default_bcdDevice();
-	snprintf(common->inquiry_string, sizeof common->inquiry_string,
-		 "%-8s%-16s%04x", cfg->vendor_name ?: "Linux",
-		 /* Assume product name dependent on the first LUN */
-		 cfg->product_name ?: (common->luns->cdrom
-				     ? "File-CD Gadget"
-				     : "File-Stor Gadget"),
-		 i);
+	_fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers);
+	common->fsg_num_buffers = n;
+	common->buffhds = buffhds;
+
+	return 0;
+
+error_release:
+	/*
+	 * "buf"s pointed to by heads after n - i are NULL
+	 * so releasing them won't hurt
+	 */
+	_fsg_common_free_buffers(buffhds, n);
+
+	return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(fsg_common_set_num_buffers);
+
+static inline void fsg_common_remove_sysfs(struct fsg_lun *lun)
+{
+	device_remove_file(&lun->dev, &dev_attr_nofua);
+	/*
+	 * device_remove_file() =>
+	 *
+	 * here the attr (e.g. dev_attr_ro) is only used to be passed to:
+	 *
+	 *	sysfs_remove_file() =>
+	 *
+	 *	here e.g. both dev_attr_ro_cdrom and dev_attr_ro are in
+	 *	the same namespace and
+	 *	from here only attr->name is passed to:
+	 *
+	 *		sysfs_hash_and_remove()
+	 *
+	 *		attr->name is the same for dev_attr_ro_cdrom and
+	 *		dev_attr_ro
+	 *		attr->name is the same for dev_attr_file and
+	 *		dev_attr_file_nonremovable
+	 *
+	 * so we don't differentiate between removing e.g. dev_attr_ro_cdrom
+	 * and dev_attr_ro
+	 */
+	device_remove_file(&lun->dev, &dev_attr_ro);
+	device_remove_file(&lun->dev, &dev_attr_file);
+}
+
+void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs)
+{
+	if (sysfs) {
+		fsg_common_remove_sysfs(lun);
+		device_unregister(&lun->dev);
+	}
+	fsg_lun_close(lun);
+	kfree(lun);
+}
+EXPORT_SYMBOL_GPL(fsg_common_remove_lun);
+
+static void _fsg_common_remove_luns(struct fsg_common *common, int n)
+{
+	int i;
+
+	for (i = 0; i < n; ++i)
+		if (common->luns[i]) {
+			fsg_common_remove_lun(common->luns[i], common->sysfs);
+			common->luns[i] = NULL;
+		}
+}
+EXPORT_SYMBOL_GPL(fsg_common_remove_luns);
+
+void fsg_common_remove_luns(struct fsg_common *common)
+{
+	_fsg_common_remove_luns(common, common->nluns);
+}
+
+void fsg_common_free_luns(struct fsg_common *common)
+{
+	fsg_common_remove_luns(common);
+	kfree(common->luns);
+	common->luns = NULL;
+}
+EXPORT_SYMBOL_GPL(fsg_common_free_luns);
+
+int fsg_common_set_nluns(struct fsg_common *common, int nluns)
+{
+	struct fsg_lun **curlun;
+
+	/* Find out how many LUNs there should be */
+	if (nluns < 1 || nluns > FSG_MAX_LUNS) {
+		pr_err("invalid number of LUNs: %u\n", nluns);
+		return -EINVAL;
+	}
+
+	curlun = kcalloc(nluns, sizeof(*curlun), GFP_KERNEL);
+	if (unlikely(!curlun))
+		return -ENOMEM;
+
+	if (common->luns)
+		fsg_common_free_luns(common);
+
+	common->luns = curlun;
+	common->nluns = nluns;
+
+	pr_info("Number of LUNs=%d\n", common->nluns);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fsg_common_set_nluns);
+
+void fsg_common_set_ops(struct fsg_common *common,
+			const struct fsg_operations *ops)
+{
+	common->ops = ops;
+}
+EXPORT_SYMBOL_GPL(fsg_common_set_ops);
+
+void fsg_common_free_buffers(struct fsg_common *common)
+{
+	_fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers);
+	common->buffhds = NULL;
+}
+EXPORT_SYMBOL_GPL(fsg_common_free_buffers);
+
+int fsg_common_set_cdev(struct fsg_common *common,
+			 struct usb_composite_dev *cdev, bool can_stall)
+{
+	struct usb_string *us;
+
+	common->gadget = cdev->gadget;
+	common->ep0 = cdev->gadget->ep0;
+	common->ep0req = cdev->req;
+	common->cdev = cdev;
+
+	us = usb_gstrings_attach(cdev, fsg_strings_array,
+				 ARRAY_SIZE(fsg_strings));
+	if (IS_ERR(us))
+		return PTR_ERR(us);
+
+	fsg_intf_desc.iInterface = us[FSG_STRING_INTERFACE].id;
 
 	/*
 	 * Some peripheral controllers are known not to be able to
 	 * halt bulk endpoints correctly.  If one of them is present,
 	 * disable stalls.
 	 */
-	common->can_stall = cfg->can_stall &&
-		!(gadget_is_at91(common->gadget));
+	common->can_stall = can_stall && !(gadget_is_at91(common->gadget));
 
-	spin_lock_init(&common->lock);
-	kref_init(&common->ref);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fsg_common_set_cdev);
 
+static inline int fsg_common_add_sysfs(struct fsg_common *common,
+				       struct fsg_lun *lun)
+{
+	int rc;
+
+	rc = device_register(&lun->dev);
+	if (rc) {
+		put_device(&lun->dev);
+		return rc;
+	}
+
+	rc = device_create_file(&lun->dev,
+				lun->cdrom
+			      ? &dev_attr_ro_cdrom
+			      : &dev_attr_ro);
+	if (rc)
+		goto error;
+	rc = device_create_file(&lun->dev,
+				lun->removable
+			      ? &dev_attr_file
+			      : &dev_attr_file_nonremovable);
+	if (rc)
+		goto error;
+	rc = device_create_file(&lun->dev, &dev_attr_nofua);
+	if (rc)
+		goto error;
+
+	return 0;
+
+error:
+	/* removing nonexistent files is a no-op */
+	fsg_common_remove_sysfs(lun);
+	device_unregister(&lun->dev);
+	return rc;
+}
+
+int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
+			  unsigned int id, const char *name,
+			  const char **name_pfx)
+{
+	struct fsg_lun *lun;
+	char *pathbuf, *p;
+	int rc = -ENOMEM;
+
+	if (!common->nluns || !common->luns)
+		return -ENODEV;
+
+	if (common->luns[id])
+		return -EBUSY;
+
+	if (!cfg->filename && !cfg->removable) {
+		pr_err("no file given for LUN%d\n", id);
+		return -EINVAL;
+	}
+
+	lun = kzalloc(sizeof(*lun), GFP_KERNEL);
+	if (!lun)
+		return -ENOMEM;
+
+	lun->name_pfx = name_pfx;
+
+	lun->cdrom = !!cfg->cdrom;
+	lun->ro = cfg->cdrom || cfg->ro;
+	lun->initially_ro = lun->ro;
+	lun->removable = !!cfg->removable;
+
+	if (!common->sysfs) {
+		/* we DON'T own the name!*/
+		lun->name = name;
+	} else {
+		lun->dev.release = fsg_lun_release;
+		lun->dev.parent = &common->gadget->dev;
+		dev_set_drvdata(&lun->dev, &common->filesem);
+		dev_set_name(&lun->dev, "%s", name);
+		lun->name = dev_name(&lun->dev);
+
+		rc = fsg_common_add_sysfs(common, lun);
+		if (rc) {
+			pr_info("failed to register LUN%d: %d\n", id, rc);
+			goto error_sysfs;
+		}
+	}
+
+	common->luns[id] = lun;
+
+	if (cfg->filename) {
+		rc = fsg_lun_open(lun, cfg->filename);
+		if (rc)
+			goto error_lun;
+	}
+
+	pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
+	p = "(no medium)";
+	if (fsg_lun_is_open(lun)) {
+		p = "(error)";
+		if (pathbuf) {
+			p = d_path(&lun->filp->f_path, pathbuf, PATH_MAX);
+			if (IS_ERR(p))
+				p = "(error)";
+		}
+	}
+	pr_info("LUN: %s%s%sfile: %s\n",
+	      lun->removable ? "removable " : "",
+	      lun->ro ? "read only " : "",
+	      lun->cdrom ? "CD-ROM " : "",
+	      p);
+	kfree(pathbuf);
+
+	return 0;
+
+error_lun:
+	if (common->sysfs) {
+		fsg_common_remove_sysfs(lun);
+		device_unregister(&lun->dev);
+	}
+	fsg_lun_close(lun);
+	common->luns[id] = NULL;
+error_sysfs:
+	kfree(lun);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(fsg_common_create_lun);
+
+int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg)
+{
+	char buf[8]; /* enough for 100000000 different numbers, decimal */
+	int i, rc;
+
+	for (i = 0; i < common->nluns; ++i) {
+		snprintf(buf, sizeof(buf), "lun%d", i);
+		rc = fsg_common_create_lun(common, &cfg->luns[i], i, buf, NULL);
+		if (rc)
+			goto fail;
+	}
+
+	pr_info("Number of LUNs=%d\n", common->nluns);
+
+	return 0;
+
+fail:
+	_fsg_common_remove_luns(common, i);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(fsg_common_create_luns);
+
+void fsg_common_set_inquiry_string(struct fsg_common *common, const char *vn,
+				   const char *pn)
+{
+	int i;
+
+	/* Prepare inquiryString */
+	i = get_default_bcdDevice();
+	snprintf(common->inquiry_string, sizeof(common->inquiry_string),
+		 "%-8s%-16s%04x", vn ?: "Linux",
+		 /* Assume product name dependent on the first LUN */
+		 pn ?: ((*common->luns)->cdrom
+		     ? "File-CD Gadget"
+		     : "File-Stor Gadget"),
+		 i);
+}
+EXPORT_SYMBOL_GPL(fsg_common_set_inquiry_string);
+
+int fsg_common_run_thread(struct fsg_common *common)
+{
+	common->state = FSG_STATE_IDLE;
 	/* Tell the thread to start working */
 	common->thread_task =
 		kthread_create(fsg_main_thread, common, "file-storage");
 	if (IS_ERR(common->thread_task)) {
-		rc = PTR_ERR(common->thread_task);
-		goto error_release;
+		common->state = FSG_STATE_TERMINATED;
+		return PTR_ERR(common->thread_task);
 	}
-	init_completion(&common->thread_notifier);
-	init_waitqueue_head(&common->fsg_wait);
-
-	/* Information */
-	INFO(common, FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n");
-	INFO(common, "Number of LUNs=%d\n", common->nluns);
-
-	pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
-	for (i = 0, nluns = common->nluns, curlun = common->luns;
-	     i < nluns;
-	     ++curlun, ++i) {
-		char *p = "(no medium)";
-		if (fsg_lun_is_open(curlun)) {
-			p = "(error)";
-			if (pathbuf) {
-				p = d_path(&curlun->filp->f_path,
-					   pathbuf, PATH_MAX);
-				if (IS_ERR(p))
-					p = "(error)";
-			}
-		}
-		LINFO(curlun, "LUN: %s%s%sfile: %s\n",
-		      curlun->removable ? "removable " : "",
-		      curlun->ro ? "read only " : "",
-		      curlun->cdrom ? "CD-ROM " : "",
-		      p);
-	}
-	kfree(pathbuf);
 
 	DBG(common, "I/O thread pid: %d\n", task_pid_nr(common->thread_task));
 
 	wake_up_process(common->thread_task);
 
-	return common;
-
-error_luns:
-	common->nluns = i + 1;
-error_release:
-	common->state = FSG_STATE_TERMINATED;	/* The thread is dead */
-	/* Call fsg_common_release() directly, ref might be not initialised. */
-	fsg_common_release(&common->ref);
-	return ERR_PTR(rc);
+	return 0;
 }
+EXPORT_SYMBOL_GPL(fsg_common_run_thread);
 
 static void fsg_common_release(struct kref *ref)
 {
@@ -2824,36 +3068,26 @@
 	}
 
 	if (likely(common->luns)) {
-		struct fsg_lun *lun = common->luns;
+		struct fsg_lun **lun_it = common->luns;
 		unsigned i = common->nluns;
 
 		/* In error recovery common->nluns may be zero. */
-		for (; i; --i, ++lun) {
-			device_remove_file(&lun->dev, &dev_attr_nofua);
-			device_remove_file(&lun->dev,
-					   lun->cdrom
-					 ? &dev_attr_ro_cdrom
-					 : &dev_attr_ro);
-			device_remove_file(&lun->dev,
-					   lun->removable
-					 ? &dev_attr_file
-					 : &dev_attr_file_nonremovable);
+		for (; i; --i, ++lun_it) {
+			struct fsg_lun *lun = *lun_it;
+			if (!lun)
+				continue;
+			if (common->sysfs)
+				fsg_common_remove_sysfs(lun);
 			fsg_lun_close(lun);
-			device_unregister(&lun->dev);
+			if (common->sysfs)
+				device_unregister(&lun->dev);
+			kfree(lun);
 		}
 
 		kfree(common->luns);
 	}
 
-	{
-		struct fsg_buffhd *bh = common->buffhds;
-		unsigned i = fsg_num_buffers;
-		do {
-			kfree(bh->buf);
-		} while (++bh, --i);
-	}
-
-	kfree(common->buffhds);
+	_fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers);
 	if (common->free_storage_on_release)
 		kfree(common);
 }
@@ -2861,24 +3095,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
-{
-	struct fsg_dev		*fsg = fsg_from_func(f);
-	struct fsg_common	*common = fsg->common;
-
-	DBG(fsg, "unbind\n");
-	if (fsg->common->fsg == fsg) {
-		fsg->common->new_fsg = NULL;
-		raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
-		/* FIXME: make interruptible or killable somehow? */
-		wait_event(common->fsg_wait, common->fsg != fsg);
-	}
-
-	fsg_common_put(common);
-	usb_free_all_descriptors(&fsg->function);
-	kfree(fsg);
-}
-
 static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
 {
 	struct fsg_dev		*fsg = fsg_from_func(f);
@@ -2887,6 +3103,19 @@
 	struct usb_ep		*ep;
 	unsigned		max_burst;
 	int			ret;
+	struct fsg_opts		*opts;
+
+	opts = fsg_opts_from_func_inst(f->fi);
+	if (!opts->no_configfs) {
+		ret = fsg_common_set_cdev(fsg->common, c->cdev,
+					  fsg->common->can_stall);
+		if (ret)
+			return ret;
+		fsg_common_set_inquiry_string(fsg->common, 0, 0);
+		ret = fsg_common_run_thread(fsg->common);
+		if (ret)
+			return ret;
+	}
 
 	fsg->gadget = gadget;
 
@@ -2939,95 +3168,472 @@
 	return -ENOTSUPP;
 }
 
-/****************************** ADD FUNCTION ******************************/
+/****************************** ALLOCATE FUNCTION *************************/
 
-static struct usb_gadget_strings *fsg_strings_array[] = {
-	&fsg_stringtab,
+static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct fsg_dev		*fsg = fsg_from_func(f);
+	struct fsg_common	*common = fsg->common;
+
+	DBG(fsg, "unbind\n");
+	if (fsg->common->fsg == fsg) {
+		fsg->common->new_fsg = NULL;
+		raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
+		/* FIXME: make interruptible or killable somehow? */
+		wait_event(common->fsg_wait, common->fsg != fsg);
+	}
+
+	usb_free_all_descriptors(&fsg->function);
+}
+
+static inline struct fsg_lun_opts *to_fsg_lun_opts(struct config_item *item)
+{
+	return container_of(to_config_group(item), struct fsg_lun_opts, group);
+}
+
+static inline struct fsg_opts *to_fsg_opts(struct config_item *item)
+{
+	return container_of(to_config_group(item), struct fsg_opts,
+			    func_inst.group);
+}
+
+CONFIGFS_ATTR_STRUCT(fsg_lun_opts);
+CONFIGFS_ATTR_OPS(fsg_lun_opts);
+
+static void fsg_lun_attr_release(struct config_item *item)
+{
+	struct fsg_lun_opts *lun_opts;
+
+	lun_opts = to_fsg_lun_opts(item);
+	kfree(lun_opts);
+}
+
+static struct configfs_item_operations fsg_lun_item_ops = {
+	.release		= fsg_lun_attr_release,
+	.show_attribute		= fsg_lun_opts_attr_show,
+	.store_attribute	= fsg_lun_opts_attr_store,
+};
+
+static ssize_t fsg_lun_opts_file_show(struct fsg_lun_opts *opts, char *page)
+{
+	struct fsg_opts *fsg_opts;
+
+	fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
+
+	return fsg_show_file(opts->lun, &fsg_opts->common->filesem, page);
+}
+
+static ssize_t fsg_lun_opts_file_store(struct fsg_lun_opts *opts,
+				       const char *page, size_t len)
+{
+	struct fsg_opts *fsg_opts;
+
+	fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
+
+	return fsg_store_file(opts->lun, &fsg_opts->common->filesem, page, len);
+}
+
+static struct fsg_lun_opts_attribute fsg_lun_opts_file =
+	__CONFIGFS_ATTR(file, S_IRUGO | S_IWUSR, fsg_lun_opts_file_show,
+			fsg_lun_opts_file_store);
+
+static ssize_t fsg_lun_opts_ro_show(struct fsg_lun_opts *opts, char *page)
+{
+	return fsg_show_ro(opts->lun, page);
+}
+
+static ssize_t fsg_lun_opts_ro_store(struct fsg_lun_opts *opts,
+				       const char *page, size_t len)
+{
+	struct fsg_opts *fsg_opts;
+
+	fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
+
+	return fsg_store_ro(opts->lun, &fsg_opts->common->filesem, page, len);
+}
+
+static struct fsg_lun_opts_attribute fsg_lun_opts_ro =
+	__CONFIGFS_ATTR(ro, S_IRUGO | S_IWUSR, fsg_lun_opts_ro_show,
+			fsg_lun_opts_ro_store);
+
+static ssize_t fsg_lun_opts_removable_show(struct fsg_lun_opts *opts,
+					   char *page)
+{
+	return fsg_show_removable(opts->lun, page);
+}
+
+static ssize_t fsg_lun_opts_removable_store(struct fsg_lun_opts *opts,
+				       const char *page, size_t len)
+{
+	return fsg_store_removable(opts->lun, page, len);
+}
+
+static struct fsg_lun_opts_attribute fsg_lun_opts_removable =
+	__CONFIGFS_ATTR(removable, S_IRUGO | S_IWUSR,
+			fsg_lun_opts_removable_show,
+			fsg_lun_opts_removable_store);
+
+static ssize_t fsg_lun_opts_cdrom_show(struct fsg_lun_opts *opts, char *page)
+{
+	return fsg_show_cdrom(opts->lun, page);
+}
+
+static ssize_t fsg_lun_opts_cdrom_store(struct fsg_lun_opts *opts,
+				       const char *page, size_t len)
+{
+	struct fsg_opts *fsg_opts;
+
+	fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
+
+	return fsg_store_cdrom(opts->lun, &fsg_opts->common->filesem, page,
+			       len);
+}
+
+static struct fsg_lun_opts_attribute fsg_lun_opts_cdrom =
+	__CONFIGFS_ATTR(cdrom, S_IRUGO | S_IWUSR, fsg_lun_opts_cdrom_show,
+			fsg_lun_opts_cdrom_store);
+
+static ssize_t fsg_lun_opts_nofua_show(struct fsg_lun_opts *opts, char *page)
+{
+	return fsg_show_nofua(opts->lun, page);
+}
+
+static ssize_t fsg_lun_opts_nofua_store(struct fsg_lun_opts *opts,
+				       const char *page, size_t len)
+{
+	return fsg_store_nofua(opts->lun, page, len);
+}
+
+static struct fsg_lun_opts_attribute fsg_lun_opts_nofua =
+	__CONFIGFS_ATTR(nofua, S_IRUGO | S_IWUSR, fsg_lun_opts_nofua_show,
+			fsg_lun_opts_nofua_store);
+
+static struct configfs_attribute *fsg_lun_attrs[] = {
+	&fsg_lun_opts_file.attr,
+	&fsg_lun_opts_ro.attr,
+	&fsg_lun_opts_removable.attr,
+	&fsg_lun_opts_cdrom.attr,
+	&fsg_lun_opts_nofua.attr,
 	NULL,
 };
 
-static int fsg_bind_config(struct usb_composite_dev *cdev,
-			   struct usb_configuration *c,
-			   struct fsg_common *common)
+static struct config_item_type fsg_lun_type = {
+	.ct_item_ops	= &fsg_lun_item_ops,
+	.ct_attrs	= fsg_lun_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct config_group *fsg_lun_make(struct config_group *group,
+					 const char *name)
 {
-	struct fsg_dev *fsg;
-	int rc;
+	struct fsg_lun_opts *opts;
+	struct fsg_opts *fsg_opts;
+	struct fsg_lun_config config;
+	char *num_str;
+	u8 num;
+	int ret;
 
-	fsg = kzalloc(sizeof *fsg, GFP_KERNEL);
-	if (unlikely(!fsg))
-		return -ENOMEM;
+	num_str = strchr(name, '.');
+	if (!num_str) {
+		pr_err("Unable to locate . in LUN.NUMBER\n");
+		return ERR_PTR(-EINVAL);
+	}
+	num_str++;
 
-	fsg->function.name        = FSG_DRIVER_DESC;
-	fsg->function.strings     = fsg_strings_array;
-	fsg->function.bind        = fsg_bind;
-	fsg->function.unbind      = fsg_unbind;
-	fsg->function.setup       = fsg_setup;
-	fsg->function.set_alt     = fsg_set_alt;
-	fsg->function.disable     = fsg_disable;
+	ret = kstrtou8(num_str, 0, &num);
+	if (ret)
+		return ERR_PTR(ret);
 
-	fsg->common               = common;
-	/*
-	 * Our caller holds a reference to common structure so we
-	 * don't have to be worry about it being freed until we return
-	 * from this function.  So instead of incrementing counter now
-	 * and decrement in error recovery we increment it only when
-	 * call to usb_add_function() was successful.
-	 */
+	fsg_opts = to_fsg_opts(&group->cg_item);
+	if (num >= FSG_MAX_LUNS)
+		return ERR_PTR(-ERANGE);
 
-	rc = usb_add_function(c, &fsg->function);
-	if (unlikely(rc))
-		kfree(fsg);
-	else
-		fsg_common_get(fsg->common);
-	return rc;
+	mutex_lock(&fsg_opts->lock);
+	if (fsg_opts->refcnt || fsg_opts->common->luns[num]) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+	if (!opts) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	memset(&config, 0, sizeof(config));
+	config.removable = true;
+
+	ret = fsg_common_create_lun(fsg_opts->common, &config, num, name,
+				    (const char **)&group->cg_item.ci_name);
+	if (ret) {
+		kfree(opts);
+		goto out;
+	}
+	opts->lun = fsg_opts->common->luns[num];
+	opts->lun_id = num;
+	mutex_unlock(&fsg_opts->lock);
+
+	config_group_init_type_name(&opts->group, name, &fsg_lun_type);
+
+	return &opts->group;
+out:
+	mutex_unlock(&fsg_opts->lock);
+	return ERR_PTR(ret);
 }
 
+static void fsg_lun_drop(struct config_group *group, struct config_item *item)
+{
+	struct fsg_lun_opts *lun_opts;
+	struct fsg_opts *fsg_opts;
+
+	lun_opts = to_fsg_lun_opts(item);
+	fsg_opts = to_fsg_opts(&group->cg_item);
+
+	mutex_lock(&fsg_opts->lock);
+	if (fsg_opts->refcnt) {
+		struct config_item *gadget;
+
+		gadget = group->cg_item.ci_parent->ci_parent;
+		unregister_gadget_item(gadget);
+	}
+
+	fsg_common_remove_lun(lun_opts->lun, fsg_opts->common->sysfs);
+	fsg_opts->common->luns[lun_opts->lun_id] = NULL;
+	lun_opts->lun_id = 0;
+	mutex_unlock(&fsg_opts->lock);
+
+	config_item_put(item);
+}
+
+CONFIGFS_ATTR_STRUCT(fsg_opts);
+CONFIGFS_ATTR_OPS(fsg_opts);
+
+static void fsg_attr_release(struct config_item *item)
+{
+	struct fsg_opts *opts = to_fsg_opts(item);
+
+	usb_put_function_instance(&opts->func_inst);
+}
+
+static struct configfs_item_operations fsg_item_ops = {
+	.release		= fsg_attr_release,
+	.show_attribute		= fsg_opts_attr_show,
+	.store_attribute	= fsg_opts_attr_store,
+};
+
+static ssize_t fsg_opts_stall_show(struct fsg_opts *opts, char *page)
+{
+	int result;
+
+	mutex_lock(&opts->lock);
+	result = sprintf(page, "%d", opts->common->can_stall);
+	mutex_unlock(&opts->lock);
+
+	return result;
+}
+
+static ssize_t fsg_opts_stall_store(struct fsg_opts *opts, const char *page,
+				    size_t len)
+{
+	int ret;
+	bool stall;
+
+	mutex_lock(&opts->lock);
+
+	if (opts->refcnt) {
+		mutex_unlock(&opts->lock);
+		return -EBUSY;
+	}
+
+	ret = strtobool(page, &stall);
+	if (!ret) {
+		opts->common->can_stall = stall;
+		ret = len;
+	}
+
+	mutex_unlock(&opts->lock);
+
+	return ret;
+}
+
+static struct fsg_opts_attribute fsg_opts_stall =
+	__CONFIGFS_ATTR(stall, S_IRUGO | S_IWUSR, fsg_opts_stall_show,
+			fsg_opts_stall_store);
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+static ssize_t fsg_opts_num_buffers_show(struct fsg_opts *opts, char *page)
+{
+	int result;
+
+	mutex_lock(&opts->lock);
+	result = sprintf(page, "%d", opts->common->fsg_num_buffers);
+	mutex_unlock(&opts->lock);
+
+	return result;
+}
+
+static ssize_t fsg_opts_num_buffers_store(struct fsg_opts *opts,
+					  const char *page, size_t len)
+{
+	int ret;
+	u8 num;
+
+	mutex_lock(&opts->lock);
+	if (opts->refcnt) {
+		ret = -EBUSY;
+		goto end;
+	}
+	ret = kstrtou8(page, 0, &num);
+	if (ret)
+		goto end;
+
+	ret = fsg_num_buffers_validate(num);
+	if (ret)
+		goto end;
+
+	fsg_common_set_num_buffers(opts->common, num);
+	ret = len;
+
+end:
+	mutex_unlock(&opts->lock);
+	return ret;
+}
+
+static struct fsg_opts_attribute fsg_opts_num_buffers =
+	__CONFIGFS_ATTR(num_buffers, S_IRUGO | S_IWUSR,
+			fsg_opts_num_buffers_show,
+			fsg_opts_num_buffers_store);
+
+#endif
+
+static struct configfs_attribute *fsg_attrs[] = {
+	&fsg_opts_stall.attr,
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+	&fsg_opts_num_buffers.attr,
+#endif
+	NULL,
+};
+
+static struct configfs_group_operations fsg_group_ops = {
+	.make_group	= fsg_lun_make,
+	.drop_item	= fsg_lun_drop,
+};
+
+static struct config_item_type fsg_func_type = {
+	.ct_item_ops	= &fsg_item_ops,
+	.ct_group_ops	= &fsg_group_ops,
+	.ct_attrs	= fsg_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static void fsg_free_inst(struct usb_function_instance *fi)
+{
+	struct fsg_opts *opts;
+
+	opts = fsg_opts_from_func_inst(fi);
+	fsg_common_put(opts->common);
+	kfree(opts);
+}
+
+static struct usb_function_instance *fsg_alloc_inst(void)
+{
+	struct fsg_opts *opts;
+	struct fsg_lun_config config;
+	int rc;
+
+	opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+	if (!opts)
+		return ERR_PTR(-ENOMEM);
+	mutex_init(&opts->lock);
+	opts->func_inst.free_func_inst = fsg_free_inst;
+	opts->common = fsg_common_setup(opts->common);
+	if (IS_ERR(opts->common)) {
+		rc = PTR_ERR(opts->common);
+		goto release_opts;
+	}
+	rc = fsg_common_set_nluns(opts->common, FSG_MAX_LUNS);
+	if (rc)
+		goto release_opts;
+
+	rc = fsg_common_set_num_buffers(opts->common,
+					CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS);
+	if (rc)
+		goto release_luns;
+
+	pr_info(FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n");
+
+	memset(&config, 0, sizeof(config));
+	config.removable = true;
+	rc = fsg_common_create_lun(opts->common, &config, 0, "lun.0",
+			(const char **)&opts->func_inst.group.cg_item.ci_name);
+	opts->lun0.lun = opts->common->luns[0];
+	opts->lun0.lun_id = 0;
+	config_group_init_type_name(&opts->lun0.group, "lun.0", &fsg_lun_type);
+	opts->default_groups[0] = &opts->lun0.group;
+	opts->func_inst.group.default_groups = opts->default_groups;
+
+	config_group_init_type_name(&opts->func_inst.group, "", &fsg_func_type);
+
+	return &opts->func_inst;
+
+release_luns:
+	kfree(opts->common->luns);
+release_opts:
+	kfree(opts);
+	return ERR_PTR(rc);
+}
+
+static void fsg_free(struct usb_function *f)
+{
+	struct fsg_dev *fsg;
+	struct fsg_opts *opts;
+
+	fsg = container_of(f, struct fsg_dev, function);
+	opts = container_of(f->fi, struct fsg_opts, func_inst);
+
+	mutex_lock(&opts->lock);
+	opts->refcnt--;
+	mutex_unlock(&opts->lock);
+
+	kfree(fsg);
+}
+
+static struct usb_function *fsg_alloc(struct usb_function_instance *fi)
+{
+	struct fsg_opts *opts = fsg_opts_from_func_inst(fi);
+	struct fsg_common *common = opts->common;
+	struct fsg_dev *fsg;
+
+	fsg = kzalloc(sizeof(*fsg), GFP_KERNEL);
+	if (unlikely(!fsg))
+		return ERR_PTR(-ENOMEM);
+
+	mutex_lock(&opts->lock);
+	opts->refcnt++;
+	mutex_unlock(&opts->lock);
+	fsg->function.name	= FSG_DRIVER_DESC;
+	fsg->function.bind	= fsg_bind;
+	fsg->function.unbind	= fsg_unbind;
+	fsg->function.setup	= fsg_setup;
+	fsg->function.set_alt	= fsg_set_alt;
+	fsg->function.disable	= fsg_disable;
+	fsg->function.free_func	= fsg_free;
+
+	fsg->common               = common;
+
+	return &fsg->function;
+}
+
+DECLARE_USB_FUNCTION_INIT(mass_storage, fsg_alloc_inst, fsg_alloc);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michal Nazarewicz");
 
 /************************* Module parameters *************************/
 
-struct fsg_module_parameters {
-	char		*file[FSG_MAX_LUNS];
-	bool		ro[FSG_MAX_LUNS];
-	bool		removable[FSG_MAX_LUNS];
-	bool		cdrom[FSG_MAX_LUNS];
-	bool		nofua[FSG_MAX_LUNS];
 
-	unsigned int	file_count, ro_count, removable_count, cdrom_count;
-	unsigned int	nofua_count;
-	unsigned int	luns;	/* nluns */
-	bool		stall;	/* can_stall */
-};
-
-#define _FSG_MODULE_PARAM_ARRAY(prefix, params, name, type, desc)	\
-	module_param_array_named(prefix ## name, params.name, type,	\
-				 &prefix ## params.name ## _count,	\
-				 S_IRUGO);				\
-	MODULE_PARM_DESC(prefix ## name, desc)
-
-#define _FSG_MODULE_PARAM(prefix, params, name, type, desc)		\
-	module_param_named(prefix ## name, params.name, type,		\
-			   S_IRUGO);					\
-	MODULE_PARM_DESC(prefix ## name, desc)
-
-#define FSG_MODULE_PARAMETERS(prefix, params)				\
-	_FSG_MODULE_PARAM_ARRAY(prefix, params, file, charp,		\
-				"names of backing files or devices");	\
-	_FSG_MODULE_PARAM_ARRAY(prefix, params, ro, bool,		\
-				"true to force read-only");		\
-	_FSG_MODULE_PARAM_ARRAY(prefix, params, removable, bool,	\
-				"true to simulate removable media");	\
-	_FSG_MODULE_PARAM_ARRAY(prefix, params, cdrom, bool,		\
-				"true to simulate CD-ROM instead of disk"); \
-	_FSG_MODULE_PARAM_ARRAY(prefix, params, nofua, bool,		\
-				"true to ignore SCSI WRITE(10,12) FUA bit"); \
-	_FSG_MODULE_PARAM(prefix, params, luns, uint,			\
-			  "number of LUNs");				\
-	_FSG_MODULE_PARAM(prefix, params, stall, bool,			\
-			  "false to prevent bulk stalls")
-
-static void
-fsg_config_from_params(struct fsg_config *cfg,
-		       const struct fsg_module_parameters *params)
+void fsg_config_from_params(struct fsg_config *cfg,
+		       const struct fsg_module_parameters *params,
+		       unsigned int fsg_num_buffers)
 {
 	struct fsg_lun_config *lun;
 	unsigned i;
@@ -3055,19 +3661,7 @@
 
 	/* Finalise */
 	cfg->can_stall = params->stall;
+	cfg->fsg_num_buffers = fsg_num_buffers;
 }
+EXPORT_SYMBOL_GPL(fsg_config_from_params);
 
-static inline struct fsg_common *
-fsg_common_from_params(struct fsg_common *common,
-		       struct usb_composite_dev *cdev,
-		       const struct fsg_module_parameters *params)
-	__attribute__((unused));
-static inline struct fsg_common *
-fsg_common_from_params(struct fsg_common *common,
-		       struct usb_composite_dev *cdev,
-		       const struct fsg_module_parameters *params)
-{
-	struct fsg_config cfg;
-	fsg_config_from_params(&cfg, params);
-	return fsg_common_init(common, cdev, &cfg);
-}
diff --git a/drivers/usb/gadget/f_mass_storage.h b/drivers/usb/gadget/f_mass_storage.h
new file mode 100644
index 0000000..b4866fc
--- /dev/null
+++ b/drivers/usb/gadget/f_mass_storage.h
@@ -0,0 +1,166 @@
+#ifndef USB_F_MASS_STORAGE_H
+#define USB_F_MASS_STORAGE_H
+
+#include <linux/usb/composite.h>
+#include "storage_common.h"
+
+struct fsg_module_parameters {
+	char		*file[FSG_MAX_LUNS];
+	bool		ro[FSG_MAX_LUNS];
+	bool		removable[FSG_MAX_LUNS];
+	bool		cdrom[FSG_MAX_LUNS];
+	bool		nofua[FSG_MAX_LUNS];
+
+	unsigned int	file_count, ro_count, removable_count, cdrom_count;
+	unsigned int	nofua_count;
+	unsigned int	luns;	/* nluns */
+	bool		stall;	/* can_stall */
+};
+
+#define _FSG_MODULE_PARAM_ARRAY(prefix, params, name, type, desc)	\
+	module_param_array_named(prefix ## name, params.name, type,	\
+				 &prefix ## params.name ## _count,	\
+				 S_IRUGO);				\
+	MODULE_PARM_DESC(prefix ## name, desc)
+
+#define _FSG_MODULE_PARAM(prefix, params, name, type, desc)		\
+	module_param_named(prefix ## name, params.name, type,		\
+			   S_IRUGO);					\
+	MODULE_PARM_DESC(prefix ## name, desc)
+
+#define __FSG_MODULE_PARAMETERS(prefix, params)				\
+	_FSG_MODULE_PARAM_ARRAY(prefix, params, file, charp,		\
+				"names of backing files or devices");	\
+	_FSG_MODULE_PARAM_ARRAY(prefix, params, ro, bool,		\
+				"true to force read-only");		\
+	_FSG_MODULE_PARAM_ARRAY(prefix, params, removable, bool,	\
+				"true to simulate removable media");	\
+	_FSG_MODULE_PARAM_ARRAY(prefix, params, cdrom, bool,		\
+				"true to simulate CD-ROM instead of disk"); \
+	_FSG_MODULE_PARAM_ARRAY(prefix, params, nofua, bool,		\
+				"true to ignore SCSI WRITE(10,12) FUA bit"); \
+	_FSG_MODULE_PARAM(prefix, params, luns, uint,			\
+			  "number of LUNs");				\
+	_FSG_MODULE_PARAM(prefix, params, stall, bool,			\
+			  "false to prevent bulk stalls")
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+#define FSG_MODULE_PARAMETERS(prefix, params)				\
+	__FSG_MODULE_PARAMETERS(prefix, params);			\
+	module_param_named(num_buffers, fsg_num_buffers, uint, S_IRUGO);\
+	MODULE_PARM_DESC(num_buffers, "Number of pipeline buffers")
+#else
+
+#define FSG_MODULE_PARAMETERS(prefix, params)				\
+	__FSG_MODULE_PARAMETERS(prefix, params)
+
+#endif
+
+struct fsg_common;
+
+/* FSF callback functions */
+struct fsg_operations {
+	/*
+	 * Callback function to call when thread exits.  If no
+	 * callback is set or it returns value lower then zero MSF
+	 * will force eject all LUNs it operates on (including those
+	 * marked as non-removable or with prevent_medium_removal flag
+	 * set).
+	 */
+	int (*thread_exits)(struct fsg_common *common);
+};
+
+struct fsg_lun_opts {
+	struct config_group group;
+	struct fsg_lun *lun;
+	int lun_id;
+};
+
+struct fsg_opts {
+	struct fsg_common *common;
+	struct usb_function_instance func_inst;
+	struct fsg_lun_opts lun0;
+	struct config_group *default_groups[2];
+	bool no_configfs; /* for legacy gadgets */
+
+	/*
+	 * Read/write access to configfs attributes is handled by configfs.
+	 *
+	 * This is to protect the data from concurrent access by read/write
+	 * and create symlink/remove symlink.
+	 */
+	struct mutex			lock;
+	int				refcnt;
+};
+
+struct fsg_lun_config {
+	const char *filename;
+	char ro;
+	char removable;
+	char cdrom;
+	char nofua;
+};
+
+struct fsg_config {
+	unsigned nluns;
+	struct fsg_lun_config luns[FSG_MAX_LUNS];
+
+	/* Callback functions. */
+	const struct fsg_operations	*ops;
+	/* Gadget's private data. */
+	void			*private_data;
+
+	const char *vendor_name;		/*  8 characters or less */
+	const char *product_name;		/* 16 characters or less */
+
+	char			can_stall;
+	unsigned int		fsg_num_buffers;
+};
+
+static inline struct fsg_opts *
+fsg_opts_from_func_inst(const struct usb_function_instance *fi)
+{
+	return container_of(fi, struct fsg_opts, func_inst);
+}
+
+void fsg_common_get(struct fsg_common *common);
+
+void fsg_common_put(struct fsg_common *common);
+
+void fsg_common_set_sysfs(struct fsg_common *common, bool sysfs);
+
+int fsg_common_set_num_buffers(struct fsg_common *common, unsigned int n);
+
+void fsg_common_free_buffers(struct fsg_common *common);
+
+int fsg_common_set_cdev(struct fsg_common *common,
+			struct usb_composite_dev *cdev, bool can_stall);
+
+void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs);
+
+void fsg_common_remove_luns(struct fsg_common *common);
+
+void fsg_common_free_luns(struct fsg_common *common);
+
+int fsg_common_set_nluns(struct fsg_common *common, int nluns);
+
+void fsg_common_set_ops(struct fsg_common *common,
+			const struct fsg_operations *ops);
+
+int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
+			  unsigned int id, const char *name,
+			  const char **name_pfx);
+
+int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg);
+
+void fsg_common_set_inquiry_string(struct fsg_common *common, const char *vn,
+				   const char *pn);
+
+int fsg_common_run_thread(struct fsg_common *common);
+
+void fsg_config_from_params(struct fsg_config *cfg,
+			    const struct fsg_module_parameters *params,
+			    unsigned int fsg_num_buffers);
+
+#endif /* USB_F_MASS_STORAGE_H */
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index f3bb363..807127d 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -33,6 +33,7 @@
 #include <linux/io.h>
 #include <linux/moduleparam.h>
 #include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/dma-mapping.h>
 #include <linux/usb/ch9.h>
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c
index 5327c82..2344efe 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/g_ffs.c
@@ -76,7 +76,9 @@
 
 USB_GADGET_COMPOSITE_OPTIONS();
 
+#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
 USB_ETHERNET_MODULE_PARAMETERS();
+#endif
 
 static struct usb_device_descriptor gfs_dev_desc = {
 	.bLength		= sizeof gfs_dev_desc,
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index c64deb9..f827680 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1165,7 +1165,7 @@
 				s = "invalid"; break;
 			default:
 				s = "?"; break;
-			}; s; }),
+			} s; }),
 			(tmp & EPxSTATUS_TOGGLE) ? "data1" : "data0",
 			(tmp & EPxSTATUS_SUSPEND) ? " suspend" : "",
 			(tmp & EPxSTATUS_FIFO_DISABLE) ? " disable" : "",
@@ -1701,7 +1701,6 @@
 	if (dev->enabled)
 		pci_disable_device(pdev);
 
-	pci_set_drvdata(pdev, NULL);
 	dev->regs = NULL;
 
 	INFO(dev, "unbind\n");
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c
index 080e577..8e27a8c 100644
--- a/drivers/usb/gadget/mass_storage.c
+++ b/drivers/usb/gadget/mass_storage.c
@@ -37,16 +37,16 @@
 #define DRIVER_DESC		"Mass Storage Gadget"
 #define DRIVER_VERSION		"2009/09/11"
 
-/*-------------------------------------------------------------------------*/
-
 /*
- * kbuild is not very cooperative with respect to linking separately
- * compiled library objects into one module.  So for now we won't use
- * separate compilation ... ensuring init/exit sections work to shrink
- * the runtime footprint, and giving us at least some parts of what
- * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
+ * Thanks to NetChip Technologies for donating this product ID.
+ *
+ * DO NOT REUSE THESE IDs with any other driver!!  Ever!!
+ * Instead:  allocate your own, using normal USB-IF procedures.
  */
-#include "f_mass_storage.c"
+#define FSG_VENDOR_ID	0x0525	/* NetChip */
+#define FSG_PRODUCT_ID	0xa4a5	/* Linux-USB File-backed Storage Gadget */
+
+#include "f_mass_storage.h"
 
 /*-------------------------------------------------------------------------*/
 USB_GADGET_COMPOSITE_OPTIONS();
@@ -97,11 +97,28 @@
 	NULL,
 };
 
+static struct usb_function_instance *fi_msg;
+static struct usb_function *f_msg;
+
 /****************************** Configurations ******************************/
 
 static struct fsg_module_parameters mod_data = {
 	.stall = 1
 };
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
+
+#else
+
+/*
+ * Number of buffers we will use.
+ * 2 is usually enough for good buffering pipeline
+ */
+#define fsg_num_buffers	CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
+
+#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
+
 FSG_MODULE_PARAMETERS(/* no prefix */, mod_data);
 
 static unsigned long msg_registered;
@@ -115,13 +132,7 @@
 
 static int __init msg_do_config(struct usb_configuration *c)
 {
-	static const struct fsg_operations ops = {
-		.thread_exits = msg_thread_exits,
-	};
-	static struct fsg_common common;
-
-	struct fsg_common *retp;
-	struct fsg_config config;
+	struct fsg_opts *opts;
 	int ret;
 
 	if (gadget_is_otg(c->cdev->gadget)) {
@@ -129,15 +140,24 @@
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	fsg_config_from_params(&config, &mod_data);
-	config.ops = &ops;
+	opts = fsg_opts_from_func_inst(fi_msg);
 
-	retp = fsg_common_init(&common, c->cdev, &config);
-	if (IS_ERR(retp))
-		return PTR_ERR(retp);
+	f_msg = usb_get_function(fi_msg);
+	if (IS_ERR(f_msg))
+		return PTR_ERR(f_msg);
 
-	ret = fsg_bind_config(c->cdev, c, &common);
-	fsg_common_put(&common);
+	ret = fsg_common_run_thread(opts->common);
+	if (ret)
+		goto put_func;
+
+	ret = usb_add_function(c, f_msg);
+	if (ret)
+		goto put_func;
+
+	return 0;
+
+put_func:
+	usb_put_function(f_msg);
 	return ret;
 }
 
@@ -152,23 +172,79 @@
 
 static int __init msg_bind(struct usb_composite_dev *cdev)
 {
+	static const struct fsg_operations ops = {
+		.thread_exits = msg_thread_exits,
+	};
+	struct fsg_opts *opts;
+	struct fsg_config config;
 	int status;
 
+	fi_msg = usb_get_function_instance("mass_storage");
+	if (IS_ERR(fi_msg))
+		return PTR_ERR(fi_msg);
+
+	fsg_config_from_params(&config, &mod_data, fsg_num_buffers);
+	opts = fsg_opts_from_func_inst(fi_msg);
+
+	opts->no_configfs = true;
+	status = fsg_common_set_num_buffers(opts->common, fsg_num_buffers);
+	if (status)
+		goto fail;
+
+	status = fsg_common_set_nluns(opts->common, config.nluns);
+	if (status)
+		goto fail_set_nluns;
+
+	fsg_common_set_ops(opts->common, &ops);
+
+	status = fsg_common_set_cdev(opts->common, cdev, config.can_stall);
+	if (status)
+		goto fail_set_cdev;
+
+	fsg_common_set_sysfs(opts->common, true);
+	status = fsg_common_create_luns(opts->common, &config);
+	if (status)
+		goto fail_set_cdev;
+
+	fsg_common_set_inquiry_string(opts->common, config.vendor_name,
+				      config.product_name);
+
 	status = usb_string_ids_tab(cdev, strings_dev);
 	if (status < 0)
-		return status;
+		goto fail_string_ids;
 	msg_device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
 
 	status = usb_add_config(cdev, &msg_config_driver, msg_do_config);
 	if (status < 0)
-		return status;
+		goto fail_string_ids;
+
 	usb_composite_overwrite_options(cdev, &coverwrite);
 	dev_info(&cdev->gadget->dev,
 		 DRIVER_DESC ", version: " DRIVER_VERSION "\n");
 	set_bit(0, &msg_registered);
 	return 0;
+
+fail_string_ids:
+	fsg_common_remove_luns(opts->common);
+fail_set_cdev:
+	fsg_common_free_luns(opts->common);
+fail_set_nluns:
+	fsg_common_free_buffers(opts->common);
+fail:
+	usb_put_function_instance(fi_msg);
+	return status;
 }
 
+static int msg_unbind(struct usb_composite_dev *cdev)
+{
+	if (!IS_ERR(f_msg))
+		usb_put_function(f_msg);
+
+	if (!IS_ERR(fi_msg))
+		usb_put_function_instance(fi_msg);
+
+	return 0;
+}
 
 /****************************** Some noise ******************************/
 
@@ -179,6 +255,7 @@
 	.needs_serial	= 1,
 	.strings	= dev_strings,
 	.bind		= msg_bind,
+	.unbind		= msg_unbind,
 };
 
 MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c
index 2339325..4fdaa54 100644
--- a/drivers/usb/gadget/multi.c
+++ b/drivers/usb/gadget/multi.c
@@ -15,6 +15,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/netdevice.h>
 
 #include "u_serial.h"
 #if defined USB_ETH_RNDIS
@@ -32,22 +33,11 @@
 MODULE_LICENSE("GPL");
 
 
-/***************************** All the files... *****************************/
+#include "f_mass_storage.h"
 
-/*
- * kbuild is not very cooperative with respect to linking separately
- * compiled library objects into one module.  So for now we won't use
- * separate compilation ... ensuring init/exit sections work to shrink
- * the runtime footprint, and giving us at least some parts of what
- * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
- */
-#include "f_mass_storage.c"
-
-#define USBF_ECM_INCLUDED
-#include "f_ecm.c"
+#include "u_ecm.h"
 #ifdef USB_ETH_RNDIS
-#  define USB_FRNDIS_INCLUDED
-#  include "f_rndis.c"
+#  include "u_rndis.h"
 #  include "rndis.h"
 #endif
 #include "u_ether.h"
@@ -132,22 +122,36 @@
 /****************************** Configurations ******************************/
 
 static struct fsg_module_parameters fsg_mod_data = { .stall = 1 };
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
+
+#else
+
+/*
+ * Number of buffers we will use.
+ * 2 is usually enough for good buffering pipeline
+ */
+#define fsg_num_buffers	CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
+
+#endif /* CONFIG_USB_DEBUG */
+
 FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
 
-static struct fsg_common fsg_common;
-
-static u8 host_mac[ETH_ALEN];
-
 static struct usb_function_instance *fi_acm;
-static struct eth_dev *the_dev;
+static struct usb_function_instance *fi_msg;
 
 /********** RNDIS **********/
 
 #ifdef USB_ETH_RNDIS
+static struct usb_function_instance *fi_rndis;
 static struct usb_function *f_acm_rndis;
+static struct usb_function *f_rndis;
+static struct usb_function *f_msg_rndis;
 
 static __init int rndis_do_config(struct usb_configuration *c)
 {
+	struct fsg_opts *fsg_opts;
 	int ret;
 
 	if (gadget_is_otg(c->cdev->gadget)) {
@@ -155,27 +159,50 @@
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	ret = rndis_bind_config(c, host_mac, the_dev);
+	f_rndis = usb_get_function(fi_rndis);
+	if (IS_ERR(f_rndis))
+		return PTR_ERR(f_rndis);
+
+	ret = usb_add_function(c, f_rndis);
 	if (ret < 0)
-		return ret;
+		goto err_func_rndis;
 
 	f_acm_rndis = usb_get_function(fi_acm);
-	if (IS_ERR(f_acm_rndis))
-		return PTR_ERR(f_acm_rndis);
+	if (IS_ERR(f_acm_rndis)) {
+		ret = PTR_ERR(f_acm_rndis);
+		goto err_func_acm;
+	}
 
 	ret = usb_add_function(c, f_acm_rndis);
 	if (ret)
 		goto err_conf;
 
-	ret = fsg_bind_config(c->cdev, c, &fsg_common);
-	if (ret < 0)
+	f_msg_rndis = usb_get_function(fi_msg);
+	if (IS_ERR(f_msg_rndis)) {
+		ret = PTR_ERR(f_msg_rndis);
 		goto err_fsg;
+	}
+
+	fsg_opts = fsg_opts_from_func_inst(fi_msg);
+	ret = fsg_common_run_thread(fsg_opts->common);
+	if (ret)
+		goto err_run;
+
+	ret = usb_add_function(c, f_msg_rndis);
+	if (ret)
+		goto err_run;
 
 	return 0;
+err_run:
+	usb_put_function(f_msg_rndis);
 err_fsg:
 	usb_remove_function(c, f_acm_rndis);
 err_conf:
 	usb_put_function(f_acm_rndis);
+err_func_acm:
+	usb_remove_function(c, f_rndis);
+err_func_rndis:
+	usb_put_function(f_rndis);
 	return ret;
 }
 
@@ -205,10 +232,14 @@
 /********** CDC ECM **********/
 
 #ifdef CONFIG_USB_G_MULTI_CDC
+static struct usb_function_instance *fi_ecm;
 static struct usb_function *f_acm_multi;
+static struct usb_function *f_ecm;
+static struct usb_function *f_msg_multi;
 
 static __init int cdc_do_config(struct usb_configuration *c)
 {
+	struct fsg_opts *fsg_opts;
 	int ret;
 
 	if (gadget_is_otg(c->cdev->gadget)) {
@@ -216,28 +247,51 @@
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	ret = ecm_bind_config(c, host_mac, the_dev);
+	f_ecm = usb_get_function(fi_ecm);
+	if (IS_ERR(f_ecm))
+		return PTR_ERR(f_ecm);
+
+	ret = usb_add_function(c, f_ecm);
 	if (ret < 0)
-		return ret;
+		goto err_func_ecm;
 
 	/* implicit port_num is zero */
 	f_acm_multi = usb_get_function(fi_acm);
-	if (IS_ERR(f_acm_multi))
-		return PTR_ERR(f_acm_multi);
+	if (IS_ERR(f_acm_multi)) {
+		ret = PTR_ERR(f_acm_multi);
+		goto err_func_acm;
+	}
 
 	ret = usb_add_function(c, f_acm_multi);
 	if (ret)
 		goto err_conf;
 
-	ret = fsg_bind_config(c->cdev, c, &fsg_common);
-	if (ret < 0)
+	f_msg_multi = usb_get_function(fi_msg);
+	if (IS_ERR(f_msg_multi)) {
+		ret = PTR_ERR(f_msg_multi);
 		goto err_fsg;
+	}
+
+	fsg_opts = fsg_opts_from_func_inst(fi_msg);
+	ret = fsg_common_run_thread(fsg_opts->common);
+	if (ret)
+		goto err_run;
+
+	ret = usb_add_function(c, f_msg_multi);
+	if (ret)
+		goto err_run;
 
 	return 0;
+err_run:
+	usb_put_function(f_msg_multi);
 err_fsg:
 	usb_remove_function(c, f_acm_multi);
 err_conf:
 	usb_put_function(f_acm_multi);
+err_func_acm:
+	usb_remove_function(c, f_ecm);
+err_func_ecm:
+	usb_put_function(f_ecm);
 	return ret;
 }
 
@@ -270,19 +324,67 @@
 static int __ref multi_bind(struct usb_composite_dev *cdev)
 {
 	struct usb_gadget *gadget = cdev->gadget;
+#ifdef CONFIG_USB_G_MULTI_CDC
+	struct f_ecm_opts *ecm_opts;
+#endif
+#ifdef USB_ETH_RNDIS
+	struct f_rndis_opts *rndis_opts;
+#endif
+	struct fsg_opts *fsg_opts;
+	struct fsg_config config;
 	int status;
 
 	if (!can_support_ecm(cdev->gadget)) {
 		dev_err(&gadget->dev, "controller '%s' not usable\n",
-		        gadget->name);
+			gadget->name);
 		return -EINVAL;
 	}
 
-	/* set up network link layer */
-	the_dev = gether_setup(cdev->gadget, dev_addr, host_addr, host_mac,
-			       qmult);
-	if (IS_ERR(the_dev))
-		return PTR_ERR(the_dev);
+#ifdef CONFIG_USB_G_MULTI_CDC
+	fi_ecm = usb_get_function_instance("ecm");
+	if (IS_ERR(fi_ecm))
+		return PTR_ERR(fi_ecm);
+
+	ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst);
+
+	gether_set_qmult(ecm_opts->net, qmult);
+	if (!gether_set_host_addr(ecm_opts->net, host_addr))
+		pr_info("using host ethernet address: %s", host_addr);
+	if (!gether_set_dev_addr(ecm_opts->net, dev_addr))
+		pr_info("using self ethernet address: %s", dev_addr);
+#endif
+
+#ifdef USB_ETH_RNDIS
+	fi_rndis = usb_get_function_instance("rndis");
+	if (IS_ERR(fi_rndis)) {
+		status = PTR_ERR(fi_rndis);
+		goto fail;
+	}
+
+	rndis_opts = container_of(fi_rndis, struct f_rndis_opts, func_inst);
+
+	gether_set_qmult(rndis_opts->net, qmult);
+	if (!gether_set_host_addr(rndis_opts->net, host_addr))
+		pr_info("using host ethernet address: %s", host_addr);
+	if (!gether_set_dev_addr(rndis_opts->net, dev_addr))
+		pr_info("using self ethernet address: %s", dev_addr);
+#endif
+
+#if (defined CONFIG_USB_G_MULTI_CDC && defined USB_ETH_RNDIS)
+	/*
+	 * If both ecm and rndis are selected then:
+	 *	1) rndis borrows the net interface from ecm
+	 *	2) since the interface is shared it must not be bound
+	 *	twice - in ecm's _and_ rndis' binds, so do it here.
+	 */
+	gether_set_gadget(ecm_opts->net, cdev->gadget);
+	status = gether_register_netdev(ecm_opts->net);
+	if (status)
+		goto fail0;
+
+	rndis_borrow_net(fi_rndis, ecm_opts->net);
+	ecm_opts->bound = true;
+#endif
 
 	/* set up serial link layer */
 	fi_acm = usb_get_function_instance("acm");
@@ -292,57 +394,102 @@
 	}
 
 	/* set up mass storage function */
-	{
-		void *retp;
-		retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data);
-		if (IS_ERR(retp)) {
-			status = PTR_ERR(retp);
-			goto fail1;
-		}
+	fi_msg = usb_get_function_instance("mass_storage");
+	if (IS_ERR(fi_msg)) {
+		status = PTR_ERR(fi_msg);
+		goto fail1;
 	}
+	fsg_config_from_params(&config, &fsg_mod_data, fsg_num_buffers);
+	fsg_opts = fsg_opts_from_func_inst(fi_msg);
+
+	fsg_opts->no_configfs = true;
+	status = fsg_common_set_num_buffers(fsg_opts->common, fsg_num_buffers);
+	if (status)
+		goto fail2;
+
+	status = fsg_common_set_nluns(fsg_opts->common, config.nluns);
+	if (status)
+		goto fail_set_nluns;
+
+	status = fsg_common_set_cdev(fsg_opts->common, cdev, config.can_stall);
+	if (status)
+		goto fail_set_cdev;
+
+	fsg_common_set_sysfs(fsg_opts->common, true);
+	status = fsg_common_create_luns(fsg_opts->common, &config);
+	if (status)
+		goto fail_set_cdev;
+
+	fsg_common_set_inquiry_string(fsg_opts->common, config.vendor_name,
+				      config.product_name);
 
 	/* allocate string IDs */
 	status = usb_string_ids_tab(cdev, strings_dev);
 	if (unlikely(status < 0))
-		goto fail2;
+		goto fail_string_ids;
 	device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
 
 	/* register configurations */
 	status = rndis_config_register(cdev);
 	if (unlikely(status < 0))
-		goto fail2;
+		goto fail_string_ids;
 
 	status = cdc_config_register(cdev);
 	if (unlikely(status < 0))
-		goto fail2;
+		goto fail_string_ids;
 	usb_composite_overwrite_options(cdev, &coverwrite);
 
 	/* we're done */
 	dev_info(&gadget->dev, DRIVER_DESC "\n");
-	fsg_common_put(&fsg_common);
 	return 0;
 
 
 	/* error recovery */
+fail_string_ids:
+	fsg_common_remove_luns(fsg_opts->common);
+fail_set_cdev:
+	fsg_common_free_luns(fsg_opts->common);
+fail_set_nluns:
+	fsg_common_free_buffers(fsg_opts->common);
 fail2:
-	fsg_common_put(&fsg_common);
+	usb_put_function_instance(fi_msg);
 fail1:
 	usb_put_function_instance(fi_acm);
 fail0:
-	gether_cleanup(the_dev);
+#ifdef USB_ETH_RNDIS
+	usb_put_function_instance(fi_rndis);
+fail:
+#endif
+#ifdef CONFIG_USB_G_MULTI_CDC
+	usb_put_function_instance(fi_ecm);
+#endif
 	return status;
 }
 
 static int __exit multi_unbind(struct usb_composite_dev *cdev)
 {
 #ifdef CONFIG_USB_G_MULTI_CDC
+	usb_put_function(f_msg_multi);
+#endif
+#ifdef USB_ETH_RNDIS
+	usb_put_function(f_msg_rndis);
+#endif
+	usb_put_function_instance(fi_msg);
+#ifdef CONFIG_USB_G_MULTI_CDC
 	usb_put_function(f_acm_multi);
 #endif
 #ifdef USB_ETH_RNDIS
 	usb_put_function(f_acm_rndis);
 #endif
 	usb_put_function_instance(fi_acm);
-	gether_cleanup(the_dev);
+#ifdef USB_ETH_RNDIS
+	usb_put_function(f_rndis);
+	usb_put_function_instance(fi_rndis);
+#endif
+#ifdef CONFIG_USB_G_MULTI_CDC
+	usb_put_function(f_ecm);
+	usb_put_function_instance(fi_ecm);
+#endif
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c
index 561b30e..234711e 100644
--- a/drivers/usb/gadget/mv_u3d_core.c
+++ b/drivers/usb/gadget/mv_u3d_core.c
@@ -310,6 +310,7 @@
 	 */
 	trb_hw = dma_pool_alloc(u3d->trb_pool, GFP_ATOMIC, dma);
 	if (!trb_hw) {
+		kfree(trb);
 		dev_err(u3d->dev,
 			"%s, dma_pool_alloc fail\n", __func__);
 		return NULL;
@@ -454,6 +455,7 @@
 
 		trb_hw = kcalloc(trb_num, sizeof(*trb_hw), GFP_ATOMIC);
 		if (!trb_hw) {
+			kfree(trb);
 			dev_err(u3d->dev,
 					"%s, trb_hw alloc fail\n", __func__);
 			return -ENOMEM;
@@ -1936,7 +1938,7 @@
 	}
 	u3d->irq = r->start;
 	if (request_irq(u3d->irq, mv_u3d_irq,
-		IRQF_DISABLED | IRQF_SHARED, driver_name, u3d)) {
+		IRQF_SHARED, driver_name, u3d)) {
 		u3d->irq = 0;
 		dev_err(&dev->dev, "Request irq %d for u3d failed\n",
 			u3d->irq);
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 0781bff..fc85217 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -129,7 +129,7 @@
 	case USB_ENDPOINT_XFER_BULK:	return "bulk";
 	case USB_ENDPOINT_XFER_ISOC:	return "iso";
 	case USB_ENDPOINT_XFER_INT:	return "intr";
-	};
+	}
 	return "control";
 }
 #endif
@@ -1630,7 +1630,7 @@
 					val = "intr"; break;
 				 default:
 					val = "iso"; break;
-				 }; val; }),
+				 } val; }),
 				usb_endpoint_maxp (d) & 0x1fff,
 				ep->dma ? "dma" : "pio", ep->fifo_size
 				);
@@ -2680,7 +2680,6 @@
 	if (dev->enabled)
 		pci_disable_device (pdev);
 	device_remove_file (&pdev->dev, &dev_attr_registers);
-	pci_set_drvdata (pdev, NULL);
 
 	INFO (dev, "unbind\n");
 }
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index 24174e1..32d5e92 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -3080,7 +3080,6 @@
 	if (dev->active)
 		pci_disable_device(pdev);
 	kfree(dev);
-	pci_set_drvdata(pdev, NULL);
 }
 
 #ifdef CONFIG_PM
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index 9575085..a3ad732 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -1068,7 +1068,7 @@
 				s = "RNDIS_INITIALIZED"; break;
 			 case RNDIS_DATA_INITIALIZED:
 				s = "RNDIS_DATA_INITIALIZED"; break;
-			}; s; }),
+			} s; }),
 			 param->medium,
 			 (param->media_state) ? 0 : param->speed*100,
 			 (param->media_state) ? "disconnected" : "connected",
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index a8a99e4..9875d9c 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -83,9 +83,12 @@
  * @dir_in: Set to true if this endpoint is of the IN direction, which
  *	    means that it is sending data to the Host.
  * @index: The index for the endpoint registers.
+ * @mc: Multi Count - number of transactions per microframe
+ * @interval - Interval for periodic endpoints
  * @name: The name array passed to the USB core.
  * @halted: Set if the endpoint has been halted.
  * @periodic: Set if this is a periodic ep, such as Interrupt
+ * @isochronous: Set if this is a isochronous ep
  * @sent_zlp: Set if we've sent a zero-length packet.
  * @total_data: The total number of data bytes done.
  * @fifo_size: The size of the FIFO (for periodic IN endpoints)
@@ -121,9 +124,12 @@
 
 	unsigned char		dir_in;
 	unsigned char		index;
+	unsigned char		mc;
+	unsigned char		interval;
 
 	unsigned int		halted:1;
 	unsigned int		periodic:1;
+	unsigned int		isochronous:1;
 	unsigned int		sent_zlp:1;
 
 	char			name[10];
@@ -468,6 +474,7 @@
 	void *data;
 	int can_write;
 	int pkt_round;
+	int max_transfer;
 
 	to_write -= (buf_pos - hs_ep->last_load);
 
@@ -535,8 +542,10 @@
 		can_write *= 4;	/* fifo size is in 32bit quantities. */
 	}
 
-	dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, mps %d\n",
-		 __func__, gnptxsts, can_write, to_write, hs_ep->ep.maxpacket);
+	max_transfer = hs_ep->ep.maxpacket * hs_ep->mc;
+
+	dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, max_transfer %d\n",
+		 __func__, gnptxsts, can_write, to_write, max_transfer);
 
 	/*
 	 * limit to 512 bytes of data, it seems at least on the non-periodic
@@ -551,19 +560,21 @@
 	 * the transfer to return that it did not run out of fifo space
 	 * doing it.
 	 */
-	if (to_write > hs_ep->ep.maxpacket) {
-		to_write = hs_ep->ep.maxpacket;
+	if (to_write > max_transfer) {
+		to_write = max_transfer;
 
-		s3c_hsotg_en_gsint(hsotg,
-				   periodic ? GINTSTS_PTxFEmp :
-				   GINTSTS_NPTxFEmp);
+		/* it's needed only when we do not use dedicated fifos */
+		if (!hsotg->dedicated_fifos)
+			s3c_hsotg_en_gsint(hsotg,
+					   periodic ? GINTSTS_PTxFEmp :
+					   GINTSTS_NPTxFEmp);
 	}
 
 	/* see if we can write data */
 
 	if (to_write > can_write) {
 		to_write = can_write;
-		pkt_round = to_write % hs_ep->ep.maxpacket;
+		pkt_round = to_write % max_transfer;
 
 		/*
 		 * Round the write down to an
@@ -581,9 +592,11 @@
 		 * is more room left.
 		 */
 
-		s3c_hsotg_en_gsint(hsotg,
-				   periodic ? GINTSTS_PTxFEmp :
-				   GINTSTS_NPTxFEmp);
+		/* it's needed only when we do not use dedicated fifos */
+		if (!hsotg->dedicated_fifos)
+			s3c_hsotg_en_gsint(hsotg,
+					   periodic ? GINTSTS_PTxFEmp :
+					   GINTSTS_NPTxFEmp);
 	}
 
 	dev_dbg(hsotg->dev, "write %d/%d, can_write %d, done %d\n",
@@ -727,8 +740,16 @@
 	else
 		packets = 1;	/* send one packet if length is zero. */
 
+	if (hs_ep->isochronous && length > (hs_ep->mc * hs_ep->ep.maxpacket)) {
+		dev_err(hsotg->dev, "req length > maxpacket*mc\n");
+		return;
+	}
+
 	if (dir_in && index != 0)
-		epsize = DxEPTSIZ_MC(1);
+		if (hs_ep->isochronous)
+			epsize = DxEPTSIZ_MC(packets);
+		else
+			epsize = DxEPTSIZ_MC(1);
 	else
 		epsize = 0;
 
@@ -820,6 +841,9 @@
 
 	dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n",
 		__func__, readl(hsotg->regs + epctrl_reg));
+
+	/* enable ep interrupts */
+	s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 1);
 }
 
 /**
@@ -1091,6 +1115,7 @@
 	bool set = (ctrl->bRequest == USB_REQ_SET_FEATURE);
 	struct s3c_hsotg_ep *ep;
 	int ret;
+	bool halted;
 
 	dev_dbg(hsotg->dev, "%s: %s_FEATURE\n",
 		__func__, set ? "SET" : "CLEAR");
@@ -1105,6 +1130,8 @@
 
 		switch (le16_to_cpu(ctrl->wValue)) {
 		case USB_ENDPOINT_HALT:
+			halted = ep->halted;
+
 			s3c_hsotg_ep_sethalt(&ep->ep, set);
 
 			ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0);
@@ -1114,7 +1141,12 @@
 				return ret;
 			}
 
-			if (!set) {
+			/*
+			 * we have to complete all requests for ep if it was
+			 * halted, and the halt was cleared by CLEAR_FEATURE
+			 */
+
+			if (!set && halted) {
 				/*
 				 * If we have request in progress,
 				 * then complete it
@@ -1147,6 +1179,8 @@
 	return 1;
 }
 
+static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg);
+
 /**
  * s3c_hsotg_process_control - process a control request
  * @hsotg: The device state
@@ -1246,11 +1280,15 @@
 		 * don't believe we need to anything more to get the EP
 		 * to reply with a STALL packet
 		 */
+
+		 /*
+		  * complete won't be called, so we enqueue
+		  * setup request here
+		  */
+		 s3c_hsotg_enqueue_setup(hsotg);
 	}
 }
 
-static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg);
-
 /**
  * s3c_hsotg_complete_setup - completion of a setup transfer
  * @ep: The endpoint the request was on.
@@ -1698,6 +1736,7 @@
 	struct s3c_hsotg_ep *hs_ep = &hsotg->eps[ep];
 	void __iomem *regs = hsotg->regs;
 	u32 mpsval;
+	u32 mcval;
 	u32 reg;
 
 	if (ep == 0) {
@@ -1705,15 +1744,19 @@
 		mpsval = s3c_hsotg_ep0_mps(mps);
 		if (mpsval > 3)
 			goto bad_mps;
+		hs_ep->ep.maxpacket = mps;
+		hs_ep->mc = 1;
 	} else {
-		if (mps >= DxEPCTL_MPS_LIMIT+1)
+		mpsval = mps & DxEPCTL_MPS_MASK;
+		if (mpsval > 1024)
 			goto bad_mps;
-
-		mpsval = mps;
+		mcval = ((mps >> 11) & 0x3) + 1;
+		hs_ep->mc = mcval;
+		if (mcval > 3)
+			goto bad_mps;
+		hs_ep->ep.maxpacket = mpsval;
 	}
 
-	hs_ep->ep.maxpacket = mps;
-
 	/*
 	 * update both the in and out endpoint controldir_ registers, even
 	 * if one of the directions may not be in use.
@@ -1782,8 +1825,16 @@
 {
 	struct s3c_hsotg_req *hs_req = hs_ep->req;
 
-	if (!hs_ep->dir_in || !hs_req)
+	if (!hs_ep->dir_in || !hs_req) {
+		/**
+		 * if request is not enqueued, we disable interrupts
+		 * for endpoints, excepting ep0
+		 */
+		if (hs_ep->index != 0)
+			s3c_hsotg_ctrl_epint(hsotg, hs_ep->index,
+					     hs_ep->dir_in, 0);
 		return 0;
+	}
 
 	if (hs_req->req.actual < hs_req->req.length) {
 		dev_dbg(hsotg->dev, "trying to write more for ep%d\n",
@@ -1887,8 +1938,10 @@
 	u32 epctl_reg = dir_in ? DIEPCTL(idx) : DOEPCTL(idx);
 	u32 epsiz_reg = dir_in ? DIEPTSIZ(idx) : DOEPTSIZ(idx);
 	u32 ints;
+	u32 ctrl;
 
 	ints = readl(hsotg->regs + epint_reg);
+	ctrl = readl(hsotg->regs + epctl_reg);
 
 	/* Clear endpoint interrupts */
 	writel(ints, hsotg->regs + epint_reg);
@@ -1897,6 +1950,14 @@
 		__func__, idx, dir_in ? "in" : "out", ints);
 
 	if (ints & DxEPINT_XferCompl) {
+		if (hs_ep->isochronous && hs_ep->interval == 1) {
+			if (ctrl & DxEPCTL_EOFrNum)
+				ctrl |= DxEPCTL_SetEvenFr;
+			else
+				ctrl |= DxEPCTL_SetOddFr;
+			writel(ctrl, hsotg->regs + epctl_reg);
+		}
+
 		dev_dbg(hsotg->dev,
 			"%s: XferCompl: DxEPCTL=0x%08x, DxEPTSIZ=%08x\n",
 			__func__, readl(hsotg->regs + epctl_reg),
@@ -1963,7 +2024,7 @@
 	if (ints & DxEPINT_Back2BackSetup)
 		dev_dbg(hsotg->dev, "%s: B2BSetup/INEPNakEff\n", __func__);
 
-	if (dir_in) {
+	if (dir_in && !hs_ep->isochronous) {
 		/* not sure if this is important, but we'll clear it anyway */
 		if (ints & DIEPMSK_INTknTXFEmpMsk) {
 			dev_dbg(hsotg->dev, "%s: ep%d: INTknTXFEmpMsk\n",
@@ -2092,12 +2153,14 @@
 }
 
 #define call_gadget(_hs, _entry) \
+do { \
 	if ((_hs)->gadget.speed != USB_SPEED_UNKNOWN &&	\
 	    (_hs)->driver && (_hs)->driver->_entry) { \
 		spin_unlock(&_hs->lock); \
 		(_hs)->driver->_entry(&(_hs)->gadget); \
 		spin_lock(&_hs->lock); \
-		}
+	} \
+} while (0)
 
 /**
  * s3c_hsotg_disconnect - disconnect service
@@ -2241,15 +2304,19 @@
 		       GAHBCFG_HBstLen_Incr4,
 		       hsotg->regs + GAHBCFG);
 	else
-		writel(GAHBCFG_GlblIntrEn, hsotg->regs + GAHBCFG);
+		writel(((hsotg->dedicated_fifos) ? (GAHBCFG_NPTxFEmpLvl |
+						    GAHBCFG_PTxFEmpLvl) : 0) |
+		       GAHBCFG_GlblIntrEn,
+		       hsotg->regs + GAHBCFG);
 
 	/*
-	 * Enabling INTknTXFEmpMsk here seems to be a big mistake, we end
-	 * up being flooded with interrupts if the host is polling the
-	 * endpoint to try and read data.
+	 * If INTknTXFEmpMsk is enabled, it's important to disable ep interrupts
+	 * when we have no data to transfer. Otherwise we get being flooded by
+	 * interrupts.
 	 */
 
-	writel(((hsotg->dedicated_fifos) ? DIEPMSK_TxFIFOEmpty : 0) |
+	writel(((hsotg->dedicated_fifos) ? DIEPMSK_TxFIFOEmpty |
+	       DIEPMSK_INTknTXFEmpMsk : 0) |
 	       DIEPMSK_EPDisbldMsk | DIEPMSK_XferComplMsk |
 	       DIEPMSK_TimeOUTMsk | DIEPMSK_AHBErrMsk |
 	       DIEPMSK_INTknEPMisMsk,
@@ -2378,10 +2445,14 @@
 
 	if (gintsts & (GINTSTS_OEPInt | GINTSTS_IEPInt)) {
 		u32 daint = readl(hsotg->regs + DAINT);
-		u32 daint_out = daint >> DAINT_OutEP_SHIFT;
-		u32 daint_in = daint & ~(daint_out << DAINT_OutEP_SHIFT);
+		u32 daintmsk = readl(hsotg->regs + DAINTMSK);
+		u32 daint_out, daint_in;
 		int ep;
 
+		daint &= daintmsk;
+		daint_out = daint >> DAINT_OutEP_SHIFT;
+		daint_in = daint & ~(daint_out << DAINT_OutEP_SHIFT);
+
 		dev_dbg(hsotg->dev, "%s: daint=%08x\n", __func__, daint);
 
 		for (ep = 0; ep < 15 && daint_out; ep++, daint_out >>= 1) {
@@ -2577,16 +2648,25 @@
 	epctrl |= DxEPCTL_SNAK;
 
 	/* update the endpoint state */
-	hs_ep->ep.maxpacket = mps;
+	s3c_hsotg_set_ep_maxpacket(hsotg, hs_ep->index, mps);
 
 	/* default, set to non-periodic */
+	hs_ep->isochronous = 0;
 	hs_ep->periodic = 0;
+	hs_ep->halted = 0;
+	hs_ep->interval = desc->bInterval;
+
+	if (hs_ep->interval > 1 && hs_ep->mc > 1)
+		dev_err(hsotg->dev, "MC > 1 when interval is not 1\n");
 
 	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
 	case USB_ENDPOINT_XFER_ISOC:
-		dev_err(hsotg->dev, "no current ISOC support\n");
-		ret = -EINVAL;
-		goto out;
+		epctrl |= DxEPCTL_EPType_Iso;
+		epctrl |= DxEPCTL_SetEvenFr;
+		hs_ep->isochronous = 1;
+		if (dir_in)
+			hs_ep->periodic = 1;
+		break;
 
 	case USB_ENDPOINT_XFER_BULK:
 		epctrl |= DxEPCTL_EPType_Bulk;
@@ -2634,7 +2714,6 @@
 	/* enable the endpoint interrupt */
 	s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1);
 
-out:
 	spin_unlock_irqrestore(&hsotg->lock, flags);
 	return ret;
 }
@@ -2776,6 +2855,8 @@
 
 	writel(epctl, hs->regs + epreg);
 
+	hs_ep->halted = value;
+
 	return 0;
 }
 
@@ -2903,7 +2984,7 @@
 	int ret;
 
 	if (!hsotg) {
-		printk(KERN_ERR "%s: called with no device\n", __func__);
+		pr_err("%s: called with no device\n", __func__);
 		return -ENODEV;
 	}
 
@@ -3066,7 +3147,7 @@
 
 	hs_ep->parent = hsotg;
 	hs_ep->ep.name = hs_ep->name;
-	hs_ep->ep.maxpacket = epnum ? 512 : EP0_MPS_LIMIT;
+	hs_ep->ep.maxpacket = epnum ? 1024 : EP0_MPS_LIMIT;
 	hs_ep->ep.ops = &s3c_hsotg_ep_ops;
 
 	/*
@@ -3200,7 +3281,7 @@
 		   readl(regs + GNPTXSTS),
 		   readl(regs + GRXSTSR));
 
-	seq_printf(seq, "\nEndpoint status:\n");
+	seq_puts(seq, "\nEndpoint status:\n");
 
 	for (idx = 0; idx < 15; idx++) {
 		u32 in, out;
@@ -3217,7 +3298,7 @@
 		seq_printf(seq, ", DIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x",
 			   in, out);
 
-		seq_printf(seq, "\n");
+		seq_puts(seq, "\n");
 	}
 
 	return 0;
@@ -3251,7 +3332,7 @@
 	u32 val;
 	int idx;
 
-	seq_printf(seq, "Non-periodic FIFOs:\n");
+	seq_puts(seq, "Non-periodic FIFOs:\n");
 	seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + GRXFSIZ));
 
 	val = readl(regs + GNPTXFSIZ);
@@ -3259,7 +3340,7 @@
 		   val >> GNPTXFSIZ_NPTxFDep_SHIFT,
 		   val & GNPTXFSIZ_NPTxFStAddr_MASK);
 
-	seq_printf(seq, "\nPeriodic TXFIFOs:\n");
+	seq_puts(seq, "\nPeriodic TXFIFOs:\n");
 
 	for (idx = 1; idx <= 15; idx++) {
 		val = readl(regs + DPTXFSIZn(idx));
@@ -3330,7 +3411,7 @@
 		   readl(regs + DIEPTSIZ(index)),
 		   readl(regs + DOEPTSIZ(index)));
 
-	seq_printf(seq, "\n");
+	seq_puts(seq, "\n");
 	seq_printf(seq, "mps %d\n", ep->ep.maxpacket);
 	seq_printf(seq, "total_data=%ld\n", ep->total_data);
 
@@ -3341,7 +3422,7 @@
 
 	list_for_each_entry(req, &ep->queue, queue) {
 		if (--show_limit < 0) {
-			seq_printf(seq, "not showing more requests...\n");
+			seq_puts(seq, "not showing more requests...\n");
 			break;
 		}
 
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index 08a1a32..ec20a1f 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -23,242 +23,17 @@
  * The valid range of num_buffers is: num >= 2 && num <= 4.
  */
 
+#include <linux/module.h>
+#include <linux/blkdev.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/usb/composite.h>
 
-#include <linux/usb/storage.h>
-#include <scsi/scsi.h>
-#include <asm/unaligned.h>
-
-
-/*
- * Thanks to NetChip Technologies for donating this product ID.
- *
- * DO NOT REUSE THESE IDs with any other driver!!  Ever!!
- * Instead:  allocate your own, using normal USB-IF procedures.
- */
-#define FSG_VENDOR_ID	0x0525	/* NetChip */
-#define FSG_PRODUCT_ID	0xa4a5	/* Linux-USB File-backed Storage Gadget */
-
-
-/*-------------------------------------------------------------------------*/
-
-
-#ifndef DEBUG
-#undef VERBOSE_DEBUG
-#undef DUMP_MSGS
-#endif /* !DEBUG */
-
-#ifdef VERBOSE_DEBUG
-#define VLDBG	LDBG
-#else
-#define VLDBG(lun, fmt, args...) do { } while (0)
-#endif /* VERBOSE_DEBUG */
-
-#define LDBG(lun, fmt, args...)   dev_dbg (&(lun)->dev, fmt, ## args)
-#define LERROR(lun, fmt, args...) dev_err (&(lun)->dev, fmt, ## args)
-#define LWARN(lun, fmt, args...)  dev_warn(&(lun)->dev, fmt, ## args)
-#define LINFO(lun, fmt, args...)  dev_info(&(lun)->dev, fmt, ## args)
-
-
-#ifdef DUMP_MSGS
-
-#  define dump_msg(fsg, /* const char * */ label,			\
-		   /* const u8 * */ buf, /* unsigned */ length) do {	\
-	if (length < 512) {						\
-		DBG(fsg, "%s, length %u:\n", label, length);		\
-		print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET,	\
-			       16, 1, buf, length, 0);			\
-	}								\
-} while (0)
-
-#  define dump_cdb(fsg) do { } while (0)
-
-#else
-
-#  define dump_msg(fsg, /* const char * */ label, \
-		   /* const u8 * */ buf, /* unsigned */ length) do { } while (0)
-
-#  ifdef VERBOSE_DEBUG
-
-#    define dump_cdb(fsg)						\
-	print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE,	\
-		       16, 1, (fsg)->cmnd, (fsg)->cmnd_size, 0)		\
-
-#  else
-
-#    define dump_cdb(fsg) do { } while (0)
-
-#  endif /* VERBOSE_DEBUG */
-
-#endif /* DUMP_MSGS */
-
-/*-------------------------------------------------------------------------*/
-
-/* Length of a SCSI Command Data Block */
-#define MAX_COMMAND_SIZE	16
-
-/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
-#define SS_NO_SENSE				0
-#define SS_COMMUNICATION_FAILURE		0x040800
-#define SS_INVALID_COMMAND			0x052000
-#define SS_INVALID_FIELD_IN_CDB			0x052400
-#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE	0x052100
-#define SS_LOGICAL_UNIT_NOT_SUPPORTED		0x052500
-#define SS_MEDIUM_NOT_PRESENT			0x023a00
-#define SS_MEDIUM_REMOVAL_PREVENTED		0x055302
-#define SS_NOT_READY_TO_READY_TRANSITION	0x062800
-#define SS_RESET_OCCURRED			0x062900
-#define SS_SAVING_PARAMETERS_NOT_SUPPORTED	0x053900
-#define SS_UNRECOVERED_READ_ERROR		0x031100
-#define SS_WRITE_ERROR				0x030c02
-#define SS_WRITE_PROTECTED			0x072700
-
-#define SK(x)		((u8) ((x) >> 16))	/* Sense Key byte, etc. */
-#define ASC(x)		((u8) ((x) >> 8))
-#define ASCQ(x)		((u8) (x))
-
-
-/*-------------------------------------------------------------------------*/
-
-
-struct fsg_lun {
-	struct file	*filp;
-	loff_t		file_length;
-	loff_t		num_sectors;
-
-	unsigned int	initially_ro:1;
-	unsigned int	ro:1;
-	unsigned int	removable:1;
-	unsigned int	cdrom:1;
-	unsigned int	prevent_medium_removal:1;
-	unsigned int	registered:1;
-	unsigned int	info_valid:1;
-	unsigned int	nofua:1;
-
-	u32		sense_data;
-	u32		sense_data_info;
-	u32		unit_attention_data;
-
-	unsigned int	blkbits;	/* Bits of logical block size of bound block device */
-	unsigned int	blksize;	/* logical block size of bound block device */
-	struct device	dev;
-};
-
-static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
-{
-	return curlun->filp != NULL;
-}
-
-static inline struct fsg_lun *fsg_lun_from_dev(struct device *dev)
-{
-	return container_of(dev, struct fsg_lun, dev);
-}
-
-
-/* Big enough to hold our biggest descriptor */
-#define EP0_BUFSIZE	256
-#define DELAYED_STATUS	(EP0_BUFSIZE + 999)	/* An impossibly large value */
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-
-static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
-module_param_named(num_buffers, fsg_num_buffers, uint, S_IRUGO);
-MODULE_PARM_DESC(num_buffers, "Number of pipeline buffers");
-
-#else
-
-/*
- * Number of buffers we will use.
- * 2 is usually enough for good buffering pipeline
- */
-#define fsg_num_buffers	CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
-
-#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
-
-/* check if fsg_num_buffers is within a valid range */
-static inline int fsg_num_buffers_validate(void)
-{
-	if (fsg_num_buffers >= 2 && fsg_num_buffers <= 4)
-		return 0;
-	pr_err("fsg_num_buffers %u is out of range (%d to %d)\n",
-	       fsg_num_buffers, 2 ,4);
-	return -EINVAL;
-}
-
-/* Default size of buffer length. */
-#define FSG_BUFLEN	((u32)16384)
-
-/* Maximal number of LUNs supported in mass storage function */
-#define FSG_MAX_LUNS	8
-
-enum fsg_buffer_state {
-	BUF_STATE_EMPTY = 0,
-	BUF_STATE_FULL,
-	BUF_STATE_BUSY
-};
-
-struct fsg_buffhd {
-	void				*buf;
-	enum fsg_buffer_state		state;
-	struct fsg_buffhd		*next;
-
-	/*
-	 * The NetChip 2280 is faster, and handles some protocol faults
-	 * better, if we don't submit any short bulk-out read requests.
-	 * So we will record the intended request length here.
-	 */
-	unsigned int			bulk_out_intended_length;
-
-	struct usb_request		*inreq;
-	int				inreq_busy;
-	struct usb_request		*outreq;
-	int				outreq_busy;
-};
-
-enum fsg_state {
-	/* This one isn't used anywhere */
-	FSG_STATE_COMMAND_PHASE = -10,
-	FSG_STATE_DATA_PHASE,
-	FSG_STATE_STATUS_PHASE,
-
-	FSG_STATE_IDLE = 0,
-	FSG_STATE_ABORT_BULK_OUT,
-	FSG_STATE_RESET,
-	FSG_STATE_INTERFACE_CHANGE,
-	FSG_STATE_CONFIG_CHANGE,
-	FSG_STATE_DISCONNECT,
-	FSG_STATE_EXIT,
-	FSG_STATE_TERMINATED
-};
-
-enum data_direction {
-	DATA_DIR_UNKNOWN = 0,
-	DATA_DIR_FROM_HOST,
-	DATA_DIR_TO_HOST,
-	DATA_DIR_NONE
-};
-
-
-/*-------------------------------------------------------------------------*/
-
-
-static inline u32 get_unaligned_be24(u8 *buf)
-{
-	return 0xffffff & (u32) get_unaligned_be32(buf - 1);
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-
-enum {
-	FSG_STRING_INTERFACE
-};
-
+#include "storage_common.h"
 
 /* There is only one interface. */
 
-static struct usb_interface_descriptor
-fsg_intf_desc = {
+struct usb_interface_descriptor fsg_intf_desc = {
 	.bLength =		sizeof fsg_intf_desc,
 	.bDescriptorType =	USB_DT_INTERFACE,
 
@@ -268,14 +43,14 @@
 	.bInterfaceProtocol =	USB_PR_BULK,	/* Adjusted during fsg_bind() */
 	.iInterface =		FSG_STRING_INTERFACE,
 };
+EXPORT_SYMBOL(fsg_intf_desc);
 
 /*
  * Three full-speed endpoint descriptors: bulk-in, bulk-out, and
  * interrupt-in.
  */
 
-static struct usb_endpoint_descriptor
-fsg_fs_bulk_in_desc = {
+struct usb_endpoint_descriptor fsg_fs_bulk_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -283,9 +58,9 @@
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	/* wMaxPacketSize set by autoconfiguration */
 };
+EXPORT_SYMBOL(fsg_fs_bulk_in_desc);
 
-static struct usb_endpoint_descriptor
-fsg_fs_bulk_out_desc = {
+struct usb_endpoint_descriptor fsg_fs_bulk_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -293,13 +68,15 @@
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	/* wMaxPacketSize set by autoconfiguration */
 };
+EXPORT_SYMBOL(fsg_fs_bulk_out_desc);
 
-static struct usb_descriptor_header *fsg_fs_function[] = {
+struct usb_descriptor_header *fsg_fs_function[] = {
 	(struct usb_descriptor_header *) &fsg_intf_desc,
 	(struct usb_descriptor_header *) &fsg_fs_bulk_in_desc,
 	(struct usb_descriptor_header *) &fsg_fs_bulk_out_desc,
 	NULL,
 };
+EXPORT_SYMBOL(fsg_fs_function);
 
 
 /*
@@ -310,8 +87,7 @@
  * and a "device qualifier" ... plus more construction options
  * for the configuration descriptor.
  */
-static struct usb_endpoint_descriptor
-fsg_hs_bulk_in_desc = {
+struct usb_endpoint_descriptor fsg_hs_bulk_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -319,9 +95,9 @@
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	cpu_to_le16(512),
 };
+EXPORT_SYMBOL(fsg_hs_bulk_in_desc);
 
-static struct usb_endpoint_descriptor
-fsg_hs_bulk_out_desc = {
+struct usb_endpoint_descriptor fsg_hs_bulk_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -330,17 +106,18 @@
 	.wMaxPacketSize =	cpu_to_le16(512),
 	.bInterval =		1,	/* NAK every 1 uframe */
 };
+EXPORT_SYMBOL(fsg_hs_bulk_out_desc);
 
 
-static struct usb_descriptor_header *fsg_hs_function[] = {
+struct usb_descriptor_header *fsg_hs_function[] = {
 	(struct usb_descriptor_header *) &fsg_intf_desc,
 	(struct usb_descriptor_header *) &fsg_hs_bulk_in_desc,
 	(struct usb_descriptor_header *) &fsg_hs_bulk_out_desc,
 	NULL,
 };
+EXPORT_SYMBOL(fsg_hs_function);
 
-static struct usb_endpoint_descriptor
-fsg_ss_bulk_in_desc = {
+struct usb_endpoint_descriptor fsg_ss_bulk_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -348,16 +125,17 @@
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	cpu_to_le16(1024),
 };
+EXPORT_SYMBOL(fsg_ss_bulk_in_desc);
 
-static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = {
+struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = {
 	.bLength =		sizeof(fsg_ss_bulk_in_comp_desc),
 	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
 
 	/*.bMaxBurst =		DYNAMIC, */
 };
+EXPORT_SYMBOL(fsg_ss_bulk_in_comp_desc);
 
-static struct usb_endpoint_descriptor
-fsg_ss_bulk_out_desc = {
+struct usb_endpoint_descriptor fsg_ss_bulk_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
@@ -365,15 +143,17 @@
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	cpu_to_le16(1024),
 };
+EXPORT_SYMBOL(fsg_ss_bulk_out_desc);
 
-static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = {
+struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = {
 	.bLength =		sizeof(fsg_ss_bulk_in_comp_desc),
 	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
 
 	/*.bMaxBurst =		DYNAMIC, */
 };
+EXPORT_SYMBOL(fsg_ss_bulk_out_comp_desc);
 
-static struct usb_descriptor_header *fsg_ss_function[] = {
+struct usb_descriptor_header *fsg_ss_function[] = {
 	(struct usb_descriptor_header *) &fsg_intf_desc,
 	(struct usb_descriptor_header *) &fsg_ss_bulk_in_desc,
 	(struct usb_descriptor_header *) &fsg_ss_bulk_in_comp_desc,
@@ -381,17 +161,7 @@
 	(struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc,
 	NULL,
 };
-
-/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
-static struct usb_string		fsg_strings[] = {
-	{FSG_STRING_INTERFACE,		fsg_string_interface},
-	{}
-};
-
-static struct usb_gadget_strings	fsg_stringtab = {
-	.language	= 0x0409,		/* en-us */
-	.strings	= fsg_strings,
-};
+EXPORT_SYMBOL(fsg_ss_function);
 
 
  /*-------------------------------------------------------------------------*/
@@ -401,7 +171,7 @@
  * the caller must own fsg->filesem for writing.
  */
 
-static void fsg_lun_close(struct fsg_lun *curlun)
+void fsg_lun_close(struct fsg_lun *curlun)
 {
 	if (curlun->filp) {
 		LDBG(curlun, "close backing file\n");
@@ -409,9 +179,9 @@
 		curlun->filp = NULL;
 	}
 }
+EXPORT_SYMBOL(fsg_lun_close);
 
-
-static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
+int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
 {
 	int				ro;
 	struct file			*filp = NULL;
@@ -508,6 +278,7 @@
 	fput(filp);
 	return rc;
 }
+EXPORT_SYMBOL(fsg_lun_open);
 
 
 /*-------------------------------------------------------------------------*/
@@ -516,7 +287,7 @@
  * Sync the file data, don't bother with the metadata.
  * This code was copied from fs/buffer.c:sys_fdatasync().
  */
-static int fsg_lun_fsync_sub(struct fsg_lun *curlun)
+int fsg_lun_fsync_sub(struct fsg_lun *curlun)
 {
 	struct file	*filp = curlun->filp;
 
@@ -524,8 +295,9 @@
 		return 0;
 	return vfs_fsync(filp, 1);
 }
+EXPORT_SYMBOL(fsg_lun_fsync_sub);
 
-static void store_cdrom_address(u8 *dest, int msf, u32 addr)
+void store_cdrom_address(u8 *dest, int msf, u32 addr)
 {
 	if (msf) {
 		/* Convert to Minutes-Seconds-Frames */
@@ -542,34 +314,28 @@
 		put_unaligned_be32(addr, dest);
 	}
 }
-
+EXPORT_SYMBOL(store_cdrom_address);
 
 /*-------------------------------------------------------------------------*/
 
 
-static ssize_t ro_show(struct device *dev, struct device_attribute *attr,
-		       char *buf)
+ssize_t fsg_show_ro(struct fsg_lun *curlun, char *buf)
 {
-	struct fsg_lun	*curlun = fsg_lun_from_dev(dev);
-
 	return sprintf(buf, "%d\n", fsg_lun_is_open(curlun)
 				  ? curlun->ro
 				  : curlun->initially_ro);
 }
+EXPORT_SYMBOL(fsg_show_ro);
 
-static ssize_t nofua_show(struct device *dev, struct device_attribute *attr,
-			  char *buf)
+ssize_t fsg_show_nofua(struct fsg_lun *curlun, char *buf)
 {
-	struct fsg_lun	*curlun = fsg_lun_from_dev(dev);
-
 	return sprintf(buf, "%u\n", curlun->nofua);
 }
+EXPORT_SYMBOL(fsg_show_nofua);
 
-static ssize_t file_show(struct device *dev, struct device_attribute *attr,
-			 char *buf)
+ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
+		      char *buf)
 {
-	struct fsg_lun	*curlun = fsg_lun_from_dev(dev);
-	struct rw_semaphore	*filesem = dev_get_drvdata(dev);
 	char		*p;
 	ssize_t		rc;
 
@@ -591,17 +357,44 @@
 	up_read(filesem);
 	return rc;
 }
+EXPORT_SYMBOL(fsg_show_file);
 
+ssize_t fsg_show_cdrom(struct fsg_lun *curlun, char *buf)
+{
+	return sprintf(buf, "%u\n", curlun->cdrom);
+}
+EXPORT_SYMBOL(fsg_show_cdrom);
 
-static ssize_t ro_store(struct device *dev, struct device_attribute *attr,
-			const char *buf, size_t count)
+ssize_t fsg_show_removable(struct fsg_lun *curlun, char *buf)
+{
+	return sprintf(buf, "%u\n", curlun->removable);
+}
+EXPORT_SYMBOL(fsg_show_removable);
+
+/*
+ * The caller must hold fsg->filesem for reading when calling this function.
+ */
+static ssize_t _fsg_store_ro(struct fsg_lun *curlun, bool ro)
+{
+	if (fsg_lun_is_open(curlun)) {
+		LDBG(curlun, "read-only status change prevented\n");
+		return -EBUSY;
+	}
+
+	curlun->ro = ro;
+	curlun->initially_ro = ro;
+	LDBG(curlun, "read-only status set to %d\n", curlun->ro);
+
+	return 0;
+}
+
+ssize_t fsg_store_ro(struct fsg_lun *curlun, struct rw_semaphore *filesem,
+		     const char *buf, size_t count)
 {
 	ssize_t		rc;
-	struct fsg_lun	*curlun = fsg_lun_from_dev(dev);
-	struct rw_semaphore	*filesem = dev_get_drvdata(dev);
-	unsigned	ro;
+	bool		ro;
 
-	rc = kstrtouint(buf, 2, &ro);
+	rc = strtobool(buf, &ro);
 	if (rc)
 		return rc;
 
@@ -610,27 +403,21 @@
 	 * backing file is closed.
 	 */
 	down_read(filesem);
-	if (fsg_lun_is_open(curlun)) {
-		LDBG(curlun, "read-only status change prevented\n");
-		rc = -EBUSY;
-	} else {
-		curlun->ro = ro;
-		curlun->initially_ro = ro;
-		LDBG(curlun, "read-only status set to %d\n", curlun->ro);
+	rc = _fsg_store_ro(curlun, ro);
+	if (!rc)
 		rc = count;
-	}
 	up_read(filesem);
+
 	return rc;
 }
+EXPORT_SYMBOL(fsg_store_ro);
 
-static ssize_t nofua_store(struct device *dev, struct device_attribute *attr,
-			   const char *buf, size_t count)
+ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count)
 {
-	struct fsg_lun	*curlun = fsg_lun_from_dev(dev);
-	unsigned	nofua;
+	bool		nofua;
 	int		ret;
 
-	ret = kstrtouint(buf, 2, &nofua);
+	ret = strtobool(buf, &nofua);
 	if (ret)
 		return ret;
 
@@ -642,12 +429,11 @@
 
 	return count;
 }
+EXPORT_SYMBOL(fsg_store_nofua);
 
-static ssize_t file_store(struct device *dev, struct device_attribute *attr,
-			  const char *buf, size_t count)
+ssize_t fsg_store_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
+		       const char *buf, size_t count)
 {
-	struct fsg_lun	*curlun = fsg_lun_from_dev(dev);
-	struct rw_semaphore	*filesem = dev_get_drvdata(dev);
 	int		rc = 0;
 
 	if (curlun->prevent_medium_removal && fsg_lun_is_open(curlun)) {
@@ -674,3 +460,45 @@
 	up_write(filesem);
 	return (rc < 0 ? rc : count);
 }
+EXPORT_SYMBOL(fsg_store_file);
+
+ssize_t fsg_store_cdrom(struct fsg_lun *curlun, struct rw_semaphore *filesem,
+			const char *buf, size_t count)
+{
+	bool		cdrom;
+	int		ret;
+
+	ret = strtobool(buf, &cdrom);
+	if (ret)
+		return ret;
+
+	down_read(filesem);
+	ret = cdrom ? _fsg_store_ro(curlun, true) : 0;
+
+	if (!ret) {
+		curlun->cdrom = cdrom;
+		ret = count;
+	}
+	up_read(filesem);
+
+	return ret;
+}
+EXPORT_SYMBOL(fsg_store_cdrom);
+
+ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf,
+			    size_t count)
+{
+	bool		removable;
+	int		ret;
+
+	ret = strtobool(buf, &removable);
+	if (ret)
+		return ret;
+
+	curlun->removable = removable;
+
+	return count;
+}
+EXPORT_SYMBOL(fsg_store_removable);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/storage_common.h b/drivers/usb/gadget/storage_common.h
new file mode 100644
index 0000000..c74c2fd
--- /dev/null
+++ b/drivers/usb/gadget/storage_common.h
@@ -0,0 +1,229 @@
+#ifndef USB_STORAGE_COMMON_H
+#define USB_STORAGE_COMMON_H
+
+#include <linux/device.h>
+#include <linux/usb/storage.h>
+#include <scsi/scsi.h>
+#include <asm/unaligned.h>
+
+#ifndef DEBUG
+#undef VERBOSE_DEBUG
+#undef DUMP_MSGS
+#endif /* !DEBUG */
+
+#ifdef VERBOSE_DEBUG
+#define VLDBG	LDBG
+#else
+#define VLDBG(lun, fmt, args...) do { } while (0)
+#endif /* VERBOSE_DEBUG */
+
+#define _LMSG(func, lun, fmt, args...)					\
+	do {								\
+		if ((lun)->name_pfx && *(lun)->name_pfx)		\
+			func("%s/%s: " fmt, *(lun)->name_pfx,		\
+				 (lun)->name, ## args);			\
+		else							\
+			func("%s: " fmt, (lun)->name, ## args);		\
+	} while (0)
+
+#define LDBG(lun, fmt, args...)		_LMSG(pr_debug, lun, fmt, ## args)
+#define LERROR(lun, fmt, args...)	_LMSG(pr_err, lun, fmt, ## args)
+#define LWARN(lun, fmt, args...)	_LMSG(pr_warn, lun, fmt, ## args)
+#define LINFO(lun, fmt, args...)	_LMSG(pr_info, lun, fmt, ## args)
+
+
+#ifdef DUMP_MSGS
+
+#  define dump_msg(fsg, /* const char * */ label,			\
+		   /* const u8 * */ buf, /* unsigned */ length)		\
+do {									\
+	if (length < 512) {						\
+		DBG(fsg, "%s, length %u:\n", label, length);		\
+		print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET,	\
+			       16, 1, buf, length, 0);			\
+	}								\
+} while (0)
+
+#  define dump_cdb(fsg) do { } while (0)
+
+#else
+
+#  define dump_msg(fsg, /* const char * */ label, \
+		   /* const u8 * */ buf, /* unsigned */ length) do { } while (0)
+
+#  ifdef VERBOSE_DEBUG
+
+#    define dump_cdb(fsg)						\
+	print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE,	\
+		       16, 1, (fsg)->cmnd, (fsg)->cmnd_size, 0)		\
+
+#  else
+
+#    define dump_cdb(fsg) do { } while (0)
+
+#  endif /* VERBOSE_DEBUG */
+
+#endif /* DUMP_MSGS */
+
+/* Length of a SCSI Command Data Block */
+#define MAX_COMMAND_SIZE	16
+
+/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
+#define SS_NO_SENSE				0
+#define SS_COMMUNICATION_FAILURE		0x040800
+#define SS_INVALID_COMMAND			0x052000
+#define SS_INVALID_FIELD_IN_CDB			0x052400
+#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE	0x052100
+#define SS_LOGICAL_UNIT_NOT_SUPPORTED		0x052500
+#define SS_MEDIUM_NOT_PRESENT			0x023a00
+#define SS_MEDIUM_REMOVAL_PREVENTED		0x055302
+#define SS_NOT_READY_TO_READY_TRANSITION	0x062800
+#define SS_RESET_OCCURRED			0x062900
+#define SS_SAVING_PARAMETERS_NOT_SUPPORTED	0x053900
+#define SS_UNRECOVERED_READ_ERROR		0x031100
+#define SS_WRITE_ERROR				0x030c02
+#define SS_WRITE_PROTECTED			0x072700
+
+#define SK(x)		((u8) ((x) >> 16))	/* Sense Key byte, etc. */
+#define ASC(x)		((u8) ((x) >> 8))
+#define ASCQ(x)		((u8) (x))
+
+struct fsg_lun {
+	struct file	*filp;
+	loff_t		file_length;
+	loff_t		num_sectors;
+
+	unsigned int	initially_ro:1;
+	unsigned int	ro:1;
+	unsigned int	removable:1;
+	unsigned int	cdrom:1;
+	unsigned int	prevent_medium_removal:1;
+	unsigned int	registered:1;
+	unsigned int	info_valid:1;
+	unsigned int	nofua:1;
+
+	u32		sense_data;
+	u32		sense_data_info;
+	u32		unit_attention_data;
+
+	unsigned int	blkbits; /* Bits of logical block size
+						       of bound block device */
+	unsigned int	blksize; /* logical block size of bound block device */
+	struct device	dev;
+	const char	*name;		/* "lun.name" */
+	const char	**name_pfx;	/* "function.name" */
+};
+
+static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
+{
+	return curlun->filp != NULL;
+}
+
+/* Big enough to hold our biggest descriptor */
+#define EP0_BUFSIZE	256
+#define DELAYED_STATUS	(EP0_BUFSIZE + 999)	/* An impossibly large value */
+
+/* Default size of buffer length. */
+#define FSG_BUFLEN	((u32)16384)
+
+/* Maximal number of LUNs supported in mass storage function */
+#define FSG_MAX_LUNS	8
+
+enum fsg_buffer_state {
+	BUF_STATE_EMPTY = 0,
+	BUF_STATE_FULL,
+	BUF_STATE_BUSY
+};
+
+struct fsg_buffhd {
+	void				*buf;
+	enum fsg_buffer_state		state;
+	struct fsg_buffhd		*next;
+
+	/*
+	 * The NetChip 2280 is faster, and handles some protocol faults
+	 * better, if we don't submit any short bulk-out read requests.
+	 * So we will record the intended request length here.
+	 */
+	unsigned int			bulk_out_intended_length;
+
+	struct usb_request		*inreq;
+	int				inreq_busy;
+	struct usb_request		*outreq;
+	int				outreq_busy;
+};
+
+enum fsg_state {
+	/* This one isn't used anywhere */
+	FSG_STATE_COMMAND_PHASE = -10,
+	FSG_STATE_DATA_PHASE,
+	FSG_STATE_STATUS_PHASE,
+
+	FSG_STATE_IDLE = 0,
+	FSG_STATE_ABORT_BULK_OUT,
+	FSG_STATE_RESET,
+	FSG_STATE_INTERFACE_CHANGE,
+	FSG_STATE_CONFIG_CHANGE,
+	FSG_STATE_DISCONNECT,
+	FSG_STATE_EXIT,
+	FSG_STATE_TERMINATED
+};
+
+enum data_direction {
+	DATA_DIR_UNKNOWN = 0,
+	DATA_DIR_FROM_HOST,
+	DATA_DIR_TO_HOST,
+	DATA_DIR_NONE
+};
+
+static inline u32 get_unaligned_be24(u8 *buf)
+{
+	return 0xffffff & (u32) get_unaligned_be32(buf - 1);
+}
+
+static inline struct fsg_lun *fsg_lun_from_dev(struct device *dev)
+{
+	return container_of(dev, struct fsg_lun, dev);
+}
+
+enum {
+	FSG_STRING_INTERFACE
+};
+
+extern struct usb_interface_descriptor fsg_intf_desc;
+
+extern struct usb_endpoint_descriptor fsg_fs_bulk_in_desc;
+extern struct usb_endpoint_descriptor fsg_fs_bulk_out_desc;
+extern struct usb_descriptor_header *fsg_fs_function[];
+
+extern struct usb_endpoint_descriptor fsg_hs_bulk_in_desc;
+extern struct usb_endpoint_descriptor fsg_hs_bulk_out_desc;
+extern struct usb_descriptor_header *fsg_hs_function[];
+
+extern struct usb_endpoint_descriptor fsg_ss_bulk_in_desc;
+extern struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc;
+extern struct usb_endpoint_descriptor fsg_ss_bulk_out_desc;
+extern struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc;
+extern struct usb_descriptor_header *fsg_ss_function[];
+
+void fsg_lun_close(struct fsg_lun *curlun);
+int fsg_lun_open(struct fsg_lun *curlun, const char *filename);
+int fsg_lun_fsync_sub(struct fsg_lun *curlun);
+void store_cdrom_address(u8 *dest, int msf, u32 addr);
+ssize_t fsg_show_ro(struct fsg_lun *curlun, char *buf);
+ssize_t fsg_show_nofua(struct fsg_lun *curlun, char *buf);
+ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
+		      char *buf);
+ssize_t fsg_show_cdrom(struct fsg_lun *curlun, char *buf);
+ssize_t fsg_show_removable(struct fsg_lun *curlun, char *buf);
+ssize_t fsg_store_ro(struct fsg_lun *curlun, struct rw_semaphore *filesem,
+		     const char *buf, size_t count);
+ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count);
+ssize_t fsg_store_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
+		       const char *buf, size_t count);
+ssize_t fsg_store_cdrom(struct fsg_lun *curlun, struct rw_semaphore *filesem,
+			const char *buf, size_t count);
+ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf,
+			    size_t count);
+
+#endif /* USB_STORAGE_COMMON_H */
diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c
index 0ff3339..eccea1d 100644
--- a/drivers/usb/gadget/tcm_usb_gadget.c
+++ b/drivers/usb/gadget/tcm_usb_gadget.c
@@ -472,7 +472,7 @@
 		bot_enqueue_cmd_cbw(fu);
 		return 0;
 		break;
-	};
+	}
 	return -ENOTSUPP;
 }
 
@@ -617,7 +617,7 @@
 
 	default:
 		BUG();
-	};
+	}
 	return;
 
 cleanup:
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
index 59891b1..27768a7 100644
--- a/drivers/usb/gadget/udc-core.c
+++ b/drivers/usb/gadget/udc-core.c
@@ -356,7 +356,8 @@
 	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
 	return 0;
 err1:
-	dev_err(&udc->dev, "failed to start %s: %d\n",
+	if (ret != -EISNAM)
+		dev_err(&udc->dev, "failed to start %s: %d\n",
 			udc->driver->function, ret);
 	udc->driver = NULL;
 	udc->dev.driver = NULL;
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 0deb9d6..0dd07ae 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -95,6 +95,18 @@
 module_param(autoresume, uint, S_IRUGO);
 MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup");
 
+/* Maximum Autoresume time */
+unsigned max_autoresume;
+module_param(max_autoresume, uint, S_IRUGO);
+MODULE_PARM_DESC(max_autoresume, "maximum seconds before remote wakeup");
+
+/* Interval between two remote wakeups */
+unsigned autoresume_interval_ms;
+module_param(autoresume_interval_ms, uint, S_IRUGO);
+MODULE_PARM_DESC(autoresume_interval_ms,
+		"milliseconds to increase successive wakeup delays");
+
+static unsigned autoresume_step_ms;
 /*-------------------------------------------------------------------------*/
 
 static struct usb_device_descriptor device_desc = {
@@ -183,8 +195,16 @@
 		return;
 
 	if (autoresume) {
-		mod_timer(&autoresume_timer, jiffies + (HZ * autoresume));
-		DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume);
+		if (max_autoresume &&
+			(autoresume_step_ms > max_autoresume * 1000))
+				autoresume_step_ms = autoresume * 1000;
+
+		mod_timer(&autoresume_timer, jiffies +
+			msecs_to_jiffies(autoresume_step_ms));
+		DBG(cdev, "suspend, wakeup in %d milliseconds\n",
+			autoresume_step_ms);
+
+		autoresume_step_ms += autoresume_interval_ms;
 	} else
 		DBG(cdev, "%s\n", __func__);
 }
@@ -316,6 +336,7 @@
 	if (autoresume) {
 		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 		loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+		autoresume_step_ms = autoresume * 1000;
 	}
 
 	/* support OTG systems */
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index b3f20d7..a9707da 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -54,7 +54,7 @@
 
 config USB_EHCI_ROOT_HUB_TT
 	bool "Root Hub Transaction Translators"
-	depends on USB_EHCI_HCD || USB_CHIPIDEA_HOST
+	depends on USB_EHCI_HCD
 	---help---
 	  Some EHCI chips have vendor-specific extensions to integrate
 	  transaction translators, so that no OHCI or UHCI companion
@@ -66,7 +66,7 @@
 
 config USB_EHCI_TT_NEWSCHED
 	bool "Improved Transaction Translator scheduling"
-	depends on USB_EHCI_HCD || USB_CHIPIDEA_HOST
+	depends on USB_EHCI_HCD
 	default y
 	---help---
 	  This changes the periodic scheduling code to fill more of the low
@@ -203,12 +203,11 @@
 	  Enables support for the on-chip EHCI controller on the SuperH.
 	  If you use the PCI EHCI controller, this option is not necessary.
 
-config USB_EHCI_S5P
+config USB_EHCI_EXYNOS
        tristate "EHCI support for Samsung S5P/EXYNOS SoC Series"
        depends on PLAT_S5P || ARCH_EXYNOS
        help
-	Enable support for the Samsung S5Pxxxx and Exynos3/4/5 SOC's
-	on-chip EHCI controller.
+	Enable support for the Samsung Exynos SOC's on-chip EHCI controller.
 
 config USB_EHCI_MV
 	bool "EHCI support for Marvell PXA/MMP USB controller"
@@ -224,7 +223,7 @@
 	  on-chip EHCI USB controller" for those.
 
 config USB_W90X900_EHCI
-	bool "W90X900(W90P910) EHCI support"
+	tristate "W90X900(W90P910) EHCI support"
 	depends on ARCH_W90X900
 	---help---
 		Enables support for the W90X900 USB controller
@@ -367,14 +366,54 @@
 if USB_OHCI_HCD
 
 config USB_OHCI_HCD_OMAP1
-	bool "OHCI support for OMAP1/2 chips"
+	tristate "OHCI support for OMAP1/2 chips"
 	depends on ARCH_OMAP1
 	default y
 	---help---
 	  Enables support for the OHCI controller on OMAP1/2 chips.
 
+config USB_OHCI_HCD_SPEAR
+        tristate "Support for ST SPEAr on-chip OHCI USB controller"
+        depends on USB_OHCI_HCD && PLAT_SPEAR
+        default y
+        ---help---
+          Enables support for the on-chip OHCI controller on
+          ST SPEAr chips.
+
+config USB_OHCI_HCD_S3C2410
+        tristate "OHCI support for Samsung S3C24xx/S3C64xx SoC series"
+        depends on USB_OHCI_HCD && (ARCH_S3C24XX || ARCH_S3C64XX)
+        default y
+        ---help---
+          Enables support for the on-chip OHCI controller on
+          S3C24xx/S3C64xx chips.
+
+config USB_OHCI_HCD_LPC32XX
+	tristate "Support for LPC on-chip OHCI USB controller"
+	depends on USB_OHCI_HCD && ARCH_LPC32XX
+	default y
+	---help---
+          Enables support for the on-chip OHCI controller on
+          NXP chips.
+
+config USB_OHCI_HCD_PXA27X
+	tristate "Support for PXA27X/PXA3XX on-chip OHCI USB controller"
+	depends on USB_OHCI_HCD && (PXA27x || PXA3xx)
+	default y
+	---help---
+	  Enables support for the on-chip OHCI controller on
+	  PXA27x/PXA3xx chips.
+
+config USB_OHCI_HCD_AT91
+        tristate "Support for Atmel on-chip OHCI USB controller"
+        depends on USB_OHCI_HCD && ARCH_AT91
+        default y
+        ---help---
+          Enables support for the on-chip OHCI controller on
+          Atmel chips.
+
 config USB_OHCI_HCD_OMAP3
-	bool "OHCI support for OMAP3 and later chips"
+	tristate "OHCI support for OMAP3 and later chips"
 	depends on (ARCH_OMAP3 || ARCH_OMAP4)
 	default y
 	---help---
@@ -454,8 +493,8 @@
 	  If you use the PCI OHCI controller, this option is not necessary.
 
 config USB_OHCI_EXYNOS
-	boolean "OHCI support for Samsung EXYNOS SoC Series"
-	depends on ARCH_EXYNOS
+	tristate "OHCI support for Samsung S5P/EXYNOS SoC Series"
+	depends on PLAT_S5P || ARCH_EXYNOS
 	help
 	 Enable support for the Samsung Exynos SOC's on-chip OHCI controller.
 
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 50b0041..01e879e 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -34,10 +34,11 @@
 obj-$(CONFIG_USB_EHCI_HCD_OMAP)	+= ehci-omap.o
 obj-$(CONFIG_USB_EHCI_HCD_ORION)	+= ehci-orion.o
 obj-$(CONFIG_USB_EHCI_HCD_SPEAR)	+= ehci-spear.o
-obj-$(CONFIG_USB_EHCI_S5P)	+= ehci-s5p.o
+obj-$(CONFIG_USB_EHCI_EXYNOS)	+= ehci-exynos.o
 obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
 obj-$(CONFIG_USB_EHCI_MSM)	+= ehci-msm.o
 obj-$(CONFIG_USB_EHCI_TEGRA)	+= ehci-tegra.o
+obj-$(CONFIG_USB_W90X900_EHCI)	+= ehci-w90x900.o
 
 obj-$(CONFIG_USB_OXU210HP_HCD)	+= oxu210hp-hcd.o
 obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o
@@ -46,6 +47,14 @@
 obj-$(CONFIG_USB_OHCI_HCD)	+= ohci-hcd.o
 obj-$(CONFIG_USB_OHCI_HCD_PCI)	+= ohci-pci.o
 obj-$(CONFIG_USB_OHCI_HCD_PLATFORM)	+= ohci-platform.o
+obj-$(CONFIG_USB_OHCI_EXYNOS)	+= ohci-exynos.o
+obj-$(CONFIG_USB_OHCI_HCD_OMAP1)	+= ohci-omap.o
+obj-$(CONFIG_USB_OHCI_HCD_OMAP3)	+= ohci-omap3.o
+obj-$(CONFIG_USB_OHCI_HCD_SPEAR)	+= ohci-spear.o
+obj-$(CONFIG_USB_OHCI_HCD_AT91)	+= ohci-at91.o
+obj-$(CONFIG_USB_OHCI_HCD_S3C2410)	+= ohci-s3c2410.o
+obj-$(CONFIG_USB_OHCI_HCD_LPC32XX)	+= ohci-nxp.o
+obj-$(CONFIG_USB_OHCI_HCD_PXA27X)	+= ohci-pxa27x.o
 
 obj-$(CONFIG_USB_UHCI_HCD)	+= uhci-hcd.o
 obj-$(CONFIG_USB_FHCI_HCD)	+= fhci.o
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index 3b645ff..f417526 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -30,13 +30,17 @@
 static struct hc_driver __read_mostly ehci_atmel_hc_driver;
 
 /* interface and function clocks */
-static struct clk *iclk, *fclk;
+static struct clk *iclk, *fclk, *uclk;
 static int clocked;
 
 /*-------------------------------------------------------------------------*/
 
 static void atmel_start_clock(void)
 {
+	if (IS_ENABLED(CONFIG_COMMON_CLK)) {
+		clk_set_rate(uclk, 48000000);
+		clk_prepare_enable(uclk);
+	}
 	clk_prepare_enable(iclk);
 	clk_prepare_enable(fclk);
 	clocked = 1;
@@ -46,6 +50,8 @@
 {
 	clk_disable_unprepare(fclk);
 	clk_disable_unprepare(iclk);
+	if (IS_ENABLED(CONFIG_COMMON_CLK))
+		clk_disable_unprepare(uclk);
 	clocked = 0;
 }
 
@@ -130,6 +136,14 @@
 		retval = -ENOENT;
 		goto fail_request_resource;
 	}
+	if (IS_ENABLED(CONFIG_COMMON_CLK)) {
+		uclk = devm_clk_get(&pdev->dev, "usb_clk");
+		if (IS_ERR(uclk)) {
+			dev_err(&pdev->dev, "failed to get uclk\n");
+			retval = PTR_ERR(uclk);
+			goto fail_request_resource;
+		}
+	}
 
 	ehci = hcd_to_ehci(hcd);
 	/* registers start at offset 0x0 */
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index aa5b603..4a9c2ed 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -334,6 +334,7 @@
 /* troubleshooting help: expose state in debugfs */
 
 static int debug_async_open(struct inode *, struct file *);
+static int debug_bandwidth_open(struct inode *, struct file *);
 static int debug_periodic_open(struct inode *, struct file *);
 static int debug_registers_open(struct inode *, struct file *);
 
@@ -347,6 +348,13 @@
 	.release	= debug_close,
 	.llseek		= default_llseek,
 };
+static const struct file_operations debug_bandwidth_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debug_bandwidth_open,
+	.read		= debug_output,
+	.release	= debug_close,
+	.llseek		= default_llseek,
+};
 static const struct file_operations debug_periodic_fops = {
 	.owner		= THIS_MODULE,
 	.open		= debug_periodic_open,
@@ -379,7 +387,7 @@
 		case QH_LOW_SPEED:  tmp = 'l'; break; \
 		case QH_HIGH_SPEED: tmp = 'h'; break; \
 		default: tmp = '?'; break; \
-		}; tmp; })
+		} tmp; })
 
 static inline char token_mark(struct ehci_hcd *ehci, __hc32 token)
 {
@@ -525,6 +533,89 @@
 	return strlen(buf->output_buf);
 }
 
+static ssize_t fill_bandwidth_buffer(struct debug_buffer *buf)
+{
+	struct ehci_hcd		*ehci;
+	struct ehci_tt		*tt;
+	struct ehci_per_sched	*ps;
+	unsigned		temp, size;
+	char			*next;
+	unsigned		i;
+	u8			*bw;
+	u16			*bf;
+	u8			budget[EHCI_BANDWIDTH_SIZE];
+
+	ehci = hcd_to_ehci(bus_to_hcd(buf->bus));
+	next = buf->output_buf;
+	size = buf->alloc_size;
+
+	*next = 0;
+
+	spin_lock_irq(&ehci->lock);
+
+	/* Dump the HS bandwidth table */
+	temp = scnprintf(next, size,
+			"HS bandwidth allocation (us per microframe)\n");
+	size -= temp;
+	next += temp;
+	for (i = 0; i < EHCI_BANDWIDTH_SIZE; i += 8) {
+		bw = &ehci->bandwidth[i];
+		temp = scnprintf(next, size,
+				"%2u: %4u%4u%4u%4u%4u%4u%4u%4u\n",
+				i, bw[0], bw[1], bw[2], bw[3],
+					bw[4], bw[5], bw[6], bw[7]);
+		size -= temp;
+		next += temp;
+	}
+
+	/* Dump all the FS/LS tables */
+	list_for_each_entry(tt, &ehci->tt_list, tt_list) {
+		temp = scnprintf(next, size,
+				"\nTT %s port %d  FS/LS bandwidth allocation (us per frame)\n",
+				dev_name(&tt->usb_tt->hub->dev),
+				tt->tt_port + !!tt->usb_tt->multi);
+		size -= temp;
+		next += temp;
+
+		bf = tt->bandwidth;
+		temp = scnprintf(next, size,
+				"  %5u%5u%5u%5u%5u%5u%5u%5u\n",
+				bf[0], bf[1], bf[2], bf[3],
+					bf[4], bf[5], bf[6], bf[7]);
+		size -= temp;
+		next += temp;
+
+		temp = scnprintf(next, size,
+				"FS/LS budget (us per microframe)\n");
+		size -= temp;
+		next += temp;
+		compute_tt_budget(budget, tt);
+		for (i = 0; i < EHCI_BANDWIDTH_SIZE; i += 8) {
+			bw = &budget[i];
+			temp = scnprintf(next, size,
+					"%2u: %4u%4u%4u%4u%4u%4u%4u%4u\n",
+					i, bw[0], bw[1], bw[2], bw[3],
+						bw[4], bw[5], bw[6], bw[7]);
+			size -= temp;
+			next += temp;
+		}
+		list_for_each_entry(ps, &tt->ps_list, ps_list) {
+			temp = scnprintf(next, size,
+					"%s ep %02x:  %4u @ %2u.%u+%u mask %04x\n",
+					dev_name(&ps->udev->dev),
+					ps->ep->desc.bEndpointAddress,
+					ps->tt_usecs,
+					ps->bw_phase, ps->phase_uf,
+					ps->bw_period, ps->cs_mask);
+			size -= temp;
+			next += temp;
+		}
+	}
+	spin_unlock_irq(&ehci->lock);
+
+	return next - buf->output_buf;
+}
+
 #define DBG_SCHED_LIMIT 64
 static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
 {
@@ -571,7 +662,7 @@
 			case Q_TYPE_QH:
 				hw = p.qh->hw;
 				temp = scnprintf (next, size, " qh%d-%04x/%p",
-						p.qh->period,
+						p.qh->ps.period,
 						hc32_to_cpup(ehci,
 							&hw->hw_info2)
 							/* uframe masks */
@@ -618,7 +709,8 @@
 						speed_char (scratch),
 						scratch & 0x007f,
 						(scratch >> 8) & 0x000f, type,
-						p.qh->usecs, p.qh->c_usecs,
+						p.qh->ps.usecs,
+						p.qh->ps.c_usecs,
 						temp,
 						0x7ff & (scratch >> 16));
 
@@ -645,7 +737,7 @@
 			case Q_TYPE_SITD:
 				temp = scnprintf (next, size,
 					" sitd%d-%04x/%p",
-					p.sitd->stream->interval,
+					p.sitd->stream->ps.period,
 					hc32_to_cpup(ehci, &p.sitd->hw_uframe)
 						& 0x0000ffff,
 					p.sitd);
@@ -918,6 +1010,7 @@
 
 	return 0;
 }
+
 static int debug_async_open(struct inode *inode, struct file *file)
 {
 	file->private_data = alloc_buffer(inode->i_private, fill_async_buffer);
@@ -925,6 +1018,14 @@
 	return file->private_data ? 0 : -ENOMEM;
 }
 
+static int debug_bandwidth_open(struct inode *inode, struct file *file)
+{
+	file->private_data = alloc_buffer(inode->i_private,
+			fill_bandwidth_buffer);
+
+	return file->private_data ? 0 : -ENOMEM;
+}
+
 static int debug_periodic_open(struct inode *inode, struct file *file)
 {
 	struct debug_buffer *buf;
@@ -957,6 +1058,10 @@
 						&debug_async_fops))
 		goto file_error;
 
+	if (!debugfs_create_file("bandwidth", S_IRUGO, ehci->debug_dir, bus,
+						&debug_bandwidth_fops))
+		goto file_error;
+
 	if (!debugfs_create_file("periodic", S_IRUGO, ehci->debug_dir, bus,
 						&debug_periodic_fops))
 		goto file_error;
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
new file mode 100644
index 0000000..016352e
--- /dev/null
+++ b/drivers/usb/host/ehci-exynos.c
@@ -0,0 +1,301 @@
+/*
+ * SAMSUNG EXYNOS USB HOST EHCI Controller
+ *
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ * Author: Jingoo Han <jg1.han@samsung.com>
+ * Author: Joonyoung Shim <jy0922.shim@samsung.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/usb/phy.h>
+#include <linux/usb/samsung_usb_phy.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/otg.h>
+
+#include "ehci.h"
+
+#define DRIVER_DESC "EHCI EXYNOS driver"
+
+#define EHCI_INSNREG00(base)			(base + 0x90)
+#define EHCI_INSNREG00_ENA_INCR16		(0x1 << 25)
+#define EHCI_INSNREG00_ENA_INCR8		(0x1 << 24)
+#define EHCI_INSNREG00_ENA_INCR4		(0x1 << 23)
+#define EHCI_INSNREG00_ENA_INCRX_ALIGN		(0x1 << 22)
+#define EHCI_INSNREG00_ENABLE_DMA_BURST	\
+	(EHCI_INSNREG00_ENA_INCR16 | EHCI_INSNREG00_ENA_INCR8 |	\
+	 EHCI_INSNREG00_ENA_INCR4 | EHCI_INSNREG00_ENA_INCRX_ALIGN)
+
+static const char hcd_name[] = "ehci-exynos";
+static struct hc_driver __read_mostly exynos_ehci_hc_driver;
+
+struct exynos_ehci_hcd {
+	struct clk *clk;
+	struct usb_phy *phy;
+	struct usb_otg *otg;
+};
+
+#define to_exynos_ehci(hcd) (struct exynos_ehci_hcd *)(hcd_to_ehci(hcd)->priv)
+
+static void exynos_setup_vbus_gpio(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	int err;
+	int gpio;
+
+	if (!dev->of_node)
+		return;
+
+	gpio = of_get_named_gpio(dev->of_node, "samsung,vbus-gpio", 0);
+	if (!gpio_is_valid(gpio))
+		return;
+
+	err = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_HIGH,
+				    "ehci_vbus_gpio");
+	if (err)
+		dev_err(dev, "can't request ehci vbus gpio %d", gpio);
+}
+
+static int exynos_ehci_probe(struct platform_device *pdev)
+{
+	struct exynos_ehci_hcd *exynos_ehci;
+	struct usb_hcd *hcd;
+	struct ehci_hcd *ehci;
+	struct resource *res;
+	struct usb_phy *phy;
+	int irq;
+	int err;
+
+	/*
+	 * Right now device-tree probed devices don't get dma_mask set.
+	 * Since shared usb code relies on it, set it here for now.
+	 * Once we move to full device tree support this will vanish off.
+	 */
+	if (!pdev->dev.dma_mask)
+		pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+	if (!pdev->dev.coherent_dma_mask)
+		pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
+	exynos_setup_vbus_gpio(pdev);
+
+	hcd = usb_create_hcd(&exynos_ehci_hc_driver,
+			     &pdev->dev, dev_name(&pdev->dev));
+	if (!hcd) {
+		dev_err(&pdev->dev, "Unable to create HCD\n");
+		return -ENOMEM;
+	}
+	exynos_ehci = to_exynos_ehci(hcd);
+
+	if (of_device_is_compatible(pdev->dev.of_node,
+					"samsung,exynos5440-ehci"))
+		goto skip_phy;
+
+	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
+	if (IS_ERR(phy)) {
+		usb_put_hcd(hcd);
+		dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
+		return -EPROBE_DEFER;
+	} else {
+		exynos_ehci->phy = phy;
+		exynos_ehci->otg = phy->otg;
+	}
+
+skip_phy:
+
+	exynos_ehci->clk = devm_clk_get(&pdev->dev, "usbhost");
+
+	if (IS_ERR(exynos_ehci->clk)) {
+		dev_err(&pdev->dev, "Failed to get usbhost clock\n");
+		err = PTR_ERR(exynos_ehci->clk);
+		goto fail_clk;
+	}
+
+	err = clk_prepare_enable(exynos_ehci->clk);
+	if (err)
+		goto fail_clk;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get I/O memory\n");
+		err = -ENXIO;
+		goto fail_io;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+	hcd->regs = devm_ioremap(&pdev->dev, res->start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		dev_err(&pdev->dev, "Failed to remap I/O memory\n");
+		err = -ENOMEM;
+		goto fail_io;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (!irq) {
+		dev_err(&pdev->dev, "Failed to get IRQ\n");
+		err = -ENODEV;
+		goto fail_io;
+	}
+
+	if (exynos_ehci->otg)
+		exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self);
+
+	if (exynos_ehci->phy)
+		usb_phy_init(exynos_ehci->phy);
+
+	ehci = hcd_to_ehci(hcd);
+	ehci->caps = hcd->regs;
+
+	/* DMA burst Enable */
+	writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
+
+	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to add USB HCD\n");
+		goto fail_add_hcd;
+	}
+
+	platform_set_drvdata(pdev, hcd);
+
+	return 0;
+
+fail_add_hcd:
+	if (exynos_ehci->phy)
+		usb_phy_shutdown(exynos_ehci->phy);
+fail_io:
+	clk_disable_unprepare(exynos_ehci->clk);
+fail_clk:
+	usb_put_hcd(hcd);
+	return err;
+}
+
+static int exynos_ehci_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd);
+
+	usb_remove_hcd(hcd);
+
+	if (exynos_ehci->otg)
+		exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self);
+
+	if (exynos_ehci->phy)
+		usb_phy_shutdown(exynos_ehci->phy);
+
+	clk_disable_unprepare(exynos_ehci->clk);
+
+	usb_put_hcd(hcd);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int exynos_ehci_suspend(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd);
+
+	bool do_wakeup = device_may_wakeup(dev);
+	int rc;
+
+	rc = ehci_suspend(hcd, do_wakeup);
+
+	if (exynos_ehci->otg)
+		exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self);
+
+	if (exynos_ehci->phy)
+		usb_phy_shutdown(exynos_ehci->phy);
+
+	clk_disable_unprepare(exynos_ehci->clk);
+
+	return rc;
+}
+
+static int exynos_ehci_resume(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd);
+
+	clk_prepare_enable(exynos_ehci->clk);
+
+	if (exynos_ehci->otg)
+		exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self);
+
+	if (exynos_ehci->phy)
+		usb_phy_init(exynos_ehci->phy);
+
+	/* DMA burst Enable */
+	writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
+
+	ehci_resume(hcd, false);
+	return 0;
+}
+#else
+#define exynos_ehci_suspend	NULL
+#define exynos_ehci_resume	NULL
+#endif
+
+static const struct dev_pm_ops exynos_ehci_pm_ops = {
+	.suspend	= exynos_ehci_suspend,
+	.resume		= exynos_ehci_resume,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id exynos_ehci_match[] = {
+	{ .compatible = "samsung,exynos4210-ehci" },
+	{ .compatible = "samsung,exynos5440-ehci" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, exynos_ehci_match);
+#endif
+
+static struct platform_driver exynos_ehci_driver = {
+	.probe		= exynos_ehci_probe,
+	.remove		= exynos_ehci_remove,
+	.shutdown	= usb_hcd_platform_shutdown,
+	.driver = {
+		.name	= "exynos-ehci",
+		.owner	= THIS_MODULE,
+		.pm	= &exynos_ehci_pm_ops,
+		.of_match_table = of_match_ptr(exynos_ehci_match),
+	}
+};
+static const struct ehci_driver_overrides exynos_overrides __initdata = {
+	.extra_priv_size = sizeof(struct exynos_ehci_hcd),
+};
+
+static int __init ehci_exynos_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+	ehci_init_driver(&exynos_ehci_hc_driver, &exynos_overrides);
+	return platform_driver_register(&exynos_ehci_driver);
+}
+module_init(ehci_exynos_init);
+
+static void __exit ehci_exynos_cleanup(void)
+{
+	platform_driver_unregister(&exynos_ehci_driver);
+}
+module_exit(ehci_exynos_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_ALIAS("platform:exynos-ehci");
+MODULE_AUTHOR("Jingoo Han");
+MODULE_AUTHOR("Joonyoung Shim");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index f2407b2..a06d501 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -57,7 +57,7 @@
 	pr_debug("initializing FSL-SOC USB Controller\n");
 
 	/* Need platform data for setup */
-	pdata = (struct fsl_usb2_platform_data *)dev_get_platdata(&pdev->dev);
+	pdata = dev_get_platdata(&pdev->dev);
 	if (!pdata) {
 		dev_err(&pdev->dev,
 			"No platform data for %s.\n", dev_name(&pdev->dev));
@@ -664,7 +664,7 @@
 	 * generic hardware linkage
 	 */
 	.irq = ehci_irq,
-	.flags = HCD_USB2 | HCD_MEMORY,
+	.flags = HCD_USB2 | HCD_MEMORY | HCD_BH,
 
 	/*
 	 * basic lifecycle operations
diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c
index 83ab51a..b52a66c 100644
--- a/drivers/usb/host/ehci-grlib.c
+++ b/drivers/usb/host/ehci-grlib.c
@@ -43,7 +43,7 @@
 	 * generic hardware linkage
 	 */
 	.irq			= ehci_irq,
-	.flags			= HCD_MEMORY | HCD_USB2,
+	.flags			= HCD_MEMORY | HCD_USB2 | HCD_BH,
 
 	/*
 	 * basic lifecycle operations
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 86ab9fd..e8ba4c4 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -110,6 +110,9 @@
 #include "ehci.h"
 #include "pci-quirks.h"
 
+static void compute_tt_budget(u8 budget_table[EHCI_BANDWIDTH_SIZE],
+		struct ehci_tt *tt);
+
 /*
  * The MosChip MCS9990 controller updates its microframe counter
  * a little before the frame counter, and occasionally we will read
@@ -484,6 +487,7 @@
 	INIT_LIST_HEAD(&ehci->intr_qh_list);
 	INIT_LIST_HEAD(&ehci->cached_itd_list);
 	INIT_LIST_HEAD(&ehci->cached_sitd_list);
+	INIT_LIST_HEAD(&ehci->tt_list);
 
 	if (HCC_PGM_FRAMELISTLEN(hcc_params)) {
 		/* periodic schedule size can be smaller than default */
@@ -956,6 +960,7 @@
 			goto idle_timeout;
 
 		/* BUG_ON(!list_empty(&stream->free_list)); */
+		reserve_release_iso_bandwidth(ehci, stream, -1);
 		kfree(stream);
 		goto done;
 	}
@@ -982,6 +987,8 @@
 		if (qh->clearing_tt)
 			goto idle_timeout;
 		if (list_empty (&qh->qtd_list)) {
+			if (qh->ps.bw_uperiod)
+				reserve_release_intr_bandwidth(ehci, qh, -1);
 			qh_destroy(ehci, qh);
 			break;
 		}
@@ -1022,7 +1029,6 @@
 	 * the toggle bit in the QH.
 	 */
 	if (qh) {
-		usb_settoggle(qh->dev, epnum, is_out, 0);
 		if (!list_empty(&qh->qtd_list)) {
 			WARN_ONCE(1, "clear_halt for a busy endpoint\n");
 		} else {
@@ -1030,6 +1036,7 @@
 			 * while the QH is active.  Unlink it now;
 			 * re-linking will call qh_refresh().
 			 */
+			usb_settoggle(qh->ps.udev, epnum, is_out, 0);
 			qh->exception = 1;
 			if (eptype == USB_ENDPOINT_XFER_BULK)
 				start_unlink_async(ehci, qh);
@@ -1048,6 +1055,19 @@
 
 /*-------------------------------------------------------------------------*/
 
+/* Device addition and removal */
+
+static void ehci_remove_device(struct usb_hcd *hcd, struct usb_device *udev)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+
+	spin_lock_irq(&ehci->lock);
+	drop_tt(udev);
+	spin_unlock_irq(&ehci->lock);
+}
+
+/*-------------------------------------------------------------------------*/
+
 #ifdef	CONFIG_PM
 
 /* suspend/resume, section 4.3 */
@@ -1075,6 +1095,14 @@
 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 	spin_unlock_irq(&ehci->lock);
 
+	synchronize_irq(hcd->irq);
+
+	/* Check for race with a wakeup request */
+	if (do_wakeup && HCD_WAKEUP_PENDING(hcd)) {
+		ehci_resume(hcd, false);
+		return -EBUSY;
+	}
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(ehci_suspend);
@@ -1158,7 +1186,7 @@
 	 * generic hardware linkage
 	 */
 	.irq =			ehci_irq,
-	.flags =		HCD_MEMORY | HCD_USB2,
+	.flags =		HCD_MEMORY | HCD_USB2 | HCD_BH,
 
 	/*
 	 * basic lifecycle operations
@@ -1191,6 +1219,11 @@
 	.bus_resume =		ehci_bus_resume,
 	.relinquish_port =	ehci_relinquish_port,
 	.port_handed_over =	ehci_port_handed_over,
+
+	/*
+	 * device support
+	 */
+	.free_dev =		ehci_remove_device,
 };
 
 void ehci_init_driver(struct hc_driver *drv,
@@ -1238,11 +1271,6 @@
 #define XILINX_OF_PLATFORM_DRIVER	ehci_hcd_xilinx_of_driver
 #endif
 
-#ifdef CONFIG_USB_W90X900_EHCI
-#include "ehci-w90x900.c"
-#define	PLATFORM_DRIVER		ehci_hcd_w90x900_driver
-#endif
-
 #ifdef CONFIG_USB_OCTEON_EHCI
 #include "ehci-octeon.c"
 #define PLATFORM_DRIVER		ehci_octeon_driver
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index 52a7773..c0fb6a8 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -224,11 +224,11 @@
 		hw->hw_next = EHCI_LIST_END(ehci);
 		hw->hw_qtd_next = EHCI_LIST_END(ehci);
 		hw->hw_alt_next = EHCI_LIST_END(ehci);
-		hw->hw_token &= ~QTD_STS_ACTIVE;
 		ehci->dummy->hw = hw;
 
 		for (i = 0; i < ehci->periodic_size; i++)
-			ehci->periodic[i] = ehci->dummy->qh_dma;
+			ehci->periodic[i] = cpu_to_hc32(ehci,
+					ehci->dummy->qh_dma);
 	} else {
 		for (i = 0; i < ehci->periodic_size; i++)
 			ehci->periodic[i] = EHCI_LIST_END(ehci);
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 0f717dc..f341651 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -42,7 +42,6 @@
 
 static const char hcd_name[] = "ehci-msm";
 static struct hc_driver __read_mostly msm_hc_driver;
-static struct usb_phy *phy;
 
 static int ehci_msm_reset(struct usb_hcd *hcd)
 {
@@ -70,6 +69,7 @@
 {
 	struct usb_hcd *hcd;
 	struct resource *res;
+	struct usb_phy *phy;
 	int ret;
 
 	dev_dbg(&pdev->dev, "ehci_msm proble\n");
@@ -108,10 +108,14 @@
 	 * powering up VBUS, mapping of registers address space and power
 	 * management.
 	 */
-	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
+	if (pdev->dev.of_node)
+		phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0);
+	else
+		phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
+
 	if (IS_ERR(phy)) {
 		dev_err(&pdev->dev, "unable to find transceiver\n");
-		ret = -ENODEV;
+		ret = -EPROBE_DEFER;
 		goto put_hcd;
 	}
 
@@ -121,6 +125,7 @@
 		goto put_hcd;
 	}
 
+	hcd->phy = phy;
 	device_init_wakeup(&pdev->dev, 1);
 	/*
 	 * OTG device parent of HCD takes care of putting
@@ -147,7 +152,7 @@
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
 
-	otg_set_host(phy->otg, NULL);
+	otg_set_host(hcd->phy->otg, NULL);
 
 	/* FIXME: need to call usb_remove_hcd() here? */
 
@@ -186,12 +191,19 @@
 	.resume          = ehci_msm_pm_resume,
 };
 
+static struct of_device_id msm_ehci_dt_match[] = {
+	{ .compatible = "qcom,ehci-host", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, msm_ehci_dt_match);
+
 static struct platform_driver ehci_msm_driver = {
 	.probe	= ehci_msm_probe,
 	.remove	= ehci_msm_remove,
 	.driver = {
 		   .name = "msm_hsusb_host",
 		   .pm = &ehci_msm_dev_pm_ops,
+		   .of_match_table = msm_ehci_dt_match,
 	},
 };
 
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
index 35cdbd8..417c10d 100644
--- a/drivers/usb/host/ehci-mv.c
+++ b/drivers/usb/host/ehci-mv.c
@@ -96,7 +96,7 @@
 	 * generic hardware linkage
 	 */
 	.irq = ehci_irq,
-	.flags = HCD_MEMORY | HCD_USB2,
+	.flags = HCD_MEMORY | HCD_USB2 | HCD_BH,
 
 	/*
 	 * basic lifecycle operations
diff --git a/drivers/usb/host/ehci-octeon.c b/drivers/usb/host/ehci-octeon.c
index 45cc001..ab0397e 100644
--- a/drivers/usb/host/ehci-octeon.c
+++ b/drivers/usb/host/ehci-octeon.c
@@ -51,7 +51,7 @@
 	 * generic hardware linkage
 	 */
 	.irq			= ehci_irq,
-	.flags			= HCD_MEMORY | HCD_USB2,
+	.flags			= HCD_MEMORY | HCD_USB2 | HCD_BH,
 
 	/*
 	 * basic lifecycle operations
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 854c2ec..3e86bf4 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -58,8 +58,6 @@
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
 	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
-	struct pci_dev		*p_smbus;
-	u8			rev;
 	u32			temp;
 	int			retval;
 
@@ -175,22 +173,12 @@
 		/* SB600 and old version of SB700 have a bug in EHCI controller,
 		 * which causes usb devices lose response in some cases.
 		 */
-		if ((pdev->device == 0x4386) || (pdev->device == 0x4396)) {
-			p_smbus = pci_get_device(PCI_VENDOR_ID_ATI,
-						 PCI_DEVICE_ID_ATI_SBX00_SMBUS,
-						 NULL);
-			if (!p_smbus)
-				break;
-			rev = p_smbus->revision;
-			if ((pdev->device == 0x4386) || (rev == 0x3a)
-			    || (rev == 0x3b)) {
-				u8 tmp;
-				ehci_info(ehci, "applying AMD SB600/SB700 USB "
-					"freeze workaround\n");
-				pci_read_config_byte(pdev, 0x53, &tmp);
-				pci_write_config_byte(pdev, 0x53, tmp | (1<<3));
-			}
-			pci_dev_put(p_smbus);
+		if ((pdev->device == 0x4386 || pdev->device == 0x4396) &&
+				usb_amd_hang_symptom_quirk()) {
+			u8 tmp;
+			ehci_info(ehci, "applying AMD SB600/SB700 USB freeze workaround\n");
+			pci_read_config_byte(pdev, 0x53, &tmp);
+			pci_write_config_byte(pdev, 0x53, tmp | (1<<3));
 		}
 		break;
 	case PCI_VENDOR_ID_NETMOS:
diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c
index 601e208..893b707 100644
--- a/drivers/usb/host/ehci-pmcmsp.c
+++ b/drivers/usb/host/ehci-pmcmsp.c
@@ -286,7 +286,7 @@
 #else
 	.irq =			ehci_irq,
 #endif
-	.flags =		HCD_MEMORY | HCD_USB2,
+	.flags =		HCD_MEMORY | HCD_USB2 | HCD_BH,
 
 	/*
 	 * basic lifecycle operations
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
index 932293f..875d2fc 100644
--- a/drivers/usb/host/ehci-ppc-of.c
+++ b/drivers/usb/host/ehci-ppc-of.c
@@ -16,6 +16,8 @@
 #include <linux/signal.h>
 
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
 
@@ -28,7 +30,7 @@
 	 * generic hardware linkage
 	 */
 	.irq			= ehci_irq,
-	.flags			= HCD_MEMORY | HCD_USB2,
+	.flags			= HCD_MEMORY | HCD_USB2 | HCD_BH,
 
 	/*
 	 * basic lifecycle operations
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
index fd98377..8188542 100644
--- a/drivers/usb/host/ehci-ps3.c
+++ b/drivers/usb/host/ehci-ps3.c
@@ -71,7 +71,7 @@
 	.product_desc		= "PS3 EHCI Host Controller",
 	.hcd_priv_size		= sizeof(struct ehci_hcd),
 	.irq			= ehci_irq,
-	.flags			= HCD_MEMORY | HCD_USB2,
+	.flags			= HCD_MEMORY | HCD_USB2 | HCD_BH,
 	.reset			= ps3_ehci_hc_reset,
 	.start			= ehci_run,
 	.stop			= ehci_stop,
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index a7f776a..db05bd8 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -105,9 +105,9 @@
 
 		is_out = qh->is_out;
 		epnum = (hc32_to_cpup(ehci, &hw->hw_info1) >> 8) & 0x0f;
-		if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
+		if (unlikely(!usb_gettoggle(qh->ps.udev, epnum, is_out))) {
 			hw->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
-			usb_settoggle (qh->dev, epnum, is_out, 1);
+			usb_settoggle(qh->ps.udev, epnum, is_out, 1);
 		}
 	}
 
@@ -247,8 +247,6 @@
 
 static void
 ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status)
-__releases(ehci->lock)
-__acquires(ehci->lock)
 {
 	if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
 		/* ... update hc-wide periodic stats */
@@ -274,11 +272,8 @@
 		urb->actual_length, urb->transfer_buffer_length);
 #endif
 
-	/* complete() can reenter this HCD */
 	usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
-	spin_unlock (&ehci->lock);
 	usb_hcd_giveback_urb(ehci_to_hcd(ehci), urb, status);
-	spin_lock (&ehci->lock);
 }
 
 static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
@@ -802,26 +797,35 @@
 	 * For control/bulk requests, the HC or TT handles these.
 	 */
 	if (type == PIPE_INTERRUPT) {
-		qh->usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH,
+		unsigned	tmp;
+
+		qh->ps.usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH,
 				is_input, 0,
 				hb_mult(maxp) * max_packet(maxp)));
-		qh->start = NO_FRAME;
+		qh->ps.phase = NO_FRAME;
 
 		if (urb->dev->speed == USB_SPEED_HIGH) {
-			qh->c_usecs = 0;
+			qh->ps.c_usecs = 0;
 			qh->gap_uf = 0;
 
-			qh->period = urb->interval >> 3;
-			if (qh->period == 0 && urb->interval != 1) {
+			if (urb->interval > 1 && urb->interval < 8) {
 				/* NOTE interval 2 or 4 uframes could work.
 				 * But interval 1 scheduling is simpler, and
 				 * includes high bandwidth.
 				 */
 				urb->interval = 1;
-			} else if (qh->period > ehci->periodic_size) {
-				qh->period = ehci->periodic_size;
-				urb->interval = qh->period << 3;
+			} else if (urb->interval > ehci->periodic_size << 3) {
+				urb->interval = ehci->periodic_size << 3;
 			}
+			qh->ps.period = urb->interval >> 3;
+
+			/* period for bandwidth allocation */
+			tmp = min_t(unsigned, EHCI_BANDWIDTH_SIZE,
+					1 << (urb->ep->desc.bInterval - 1));
+
+			/* Allow urb->interval to override */
+			qh->ps.bw_uperiod = min_t(unsigned, tmp, urb->interval);
+			qh->ps.bw_period = qh->ps.bw_uperiod >> 3;
 		} else {
 			int		think_time;
 
@@ -831,27 +835,35 @@
 
 			/* FIXME this just approximates SPLIT/CSPLIT times */
 			if (is_input) {		// SPLIT, gap, CSPLIT+DATA
-				qh->c_usecs = qh->usecs + HS_USECS (0);
-				qh->usecs = HS_USECS (1);
+				qh->ps.c_usecs = qh->ps.usecs + HS_USECS(0);
+				qh->ps.usecs = HS_USECS(1);
 			} else {		// SPLIT+DATA, gap, CSPLIT
-				qh->usecs += HS_USECS (1);
-				qh->c_usecs = HS_USECS (0);
+				qh->ps.usecs += HS_USECS(1);
+				qh->ps.c_usecs = HS_USECS(0);
 			}
 
 			think_time = tt ? tt->think_time : 0;
-			qh->tt_usecs = NS_TO_US (think_time +
+			qh->ps.tt_usecs = NS_TO_US(think_time +
 					usb_calc_bus_time (urb->dev->speed,
 					is_input, 0, max_packet (maxp)));
-			qh->period = urb->interval;
-			if (qh->period > ehci->periodic_size) {
-				qh->period = ehci->periodic_size;
-				urb->interval = qh->period;
-			}
+			if (urb->interval > ehci->periodic_size)
+				urb->interval = ehci->periodic_size;
+			qh->ps.period = urb->interval;
+
+			/* period for bandwidth allocation */
+			tmp = min_t(unsigned, EHCI_BANDWIDTH_FRAMES,
+					urb->ep->desc.bInterval);
+			tmp = rounddown_pow_of_two(tmp);
+
+			/* Allow urb->interval to override */
+			qh->ps.bw_period = min_t(unsigned, tmp, urb->interval);
+			qh->ps.bw_uperiod = qh->ps.bw_period << 3;
 		}
 	}
 
 	/* support for tt scheduling, and access to toggles */
-	qh->dev = urb->dev;
+	qh->ps.udev = urb->dev;
+	qh->ps.ep = urb->ep;
 
 	/* using TT? */
 	switch (urb->dev->speed) {
diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
deleted file mode 100644
index 7c3de95..0000000
--- a/drivers/usb/host/ehci-s5p.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * SAMSUNG S5P USB HOST EHCI Controller
- *
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Author: Jingoo Han <jg1.han@samsung.com>
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- */
-
-#include <linux/clk.h>
-#include <linux/dma-mapping.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-#include <linux/platform_device.h>
-#include <linux/platform_data/usb-ehci-s5p.h>
-#include <linux/usb/phy.h>
-#include <linux/usb/samsung_usb_phy.h>
-#include <linux/usb.h>
-#include <linux/usb/hcd.h>
-#include <linux/usb/otg.h>
-
-#include "ehci.h"
-
-#define DRIVER_DESC "EHCI s5p driver"
-
-#define EHCI_INSNREG00(base)			(base + 0x90)
-#define EHCI_INSNREG00_ENA_INCR16		(0x1 << 25)
-#define EHCI_INSNREG00_ENA_INCR8		(0x1 << 24)
-#define EHCI_INSNREG00_ENA_INCR4		(0x1 << 23)
-#define EHCI_INSNREG00_ENA_INCRX_ALIGN		(0x1 << 22)
-#define EHCI_INSNREG00_ENABLE_DMA_BURST	\
-	(EHCI_INSNREG00_ENA_INCR16 | EHCI_INSNREG00_ENA_INCR8 |	\
-	 EHCI_INSNREG00_ENA_INCR4 | EHCI_INSNREG00_ENA_INCRX_ALIGN)
-
-static const char hcd_name[] = "ehci-s5p";
-static struct hc_driver __read_mostly s5p_ehci_hc_driver;
-
-struct s5p_ehci_hcd {
-	struct clk *clk;
-	struct usb_phy *phy;
-	struct usb_otg *otg;
-	struct s5p_ehci_platdata *pdata;
-};
-
-static struct s5p_ehci_platdata empty_platdata;
-
-#define to_s5p_ehci(hcd)      (struct s5p_ehci_hcd *)(hcd_to_ehci(hcd)->priv)
-
-static void s5p_setup_vbus_gpio(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	int err;
-	int gpio;
-
-	if (!dev->of_node)
-		return;
-
-	gpio = of_get_named_gpio(dev->of_node, "samsung,vbus-gpio", 0);
-	if (!gpio_is_valid(gpio))
-		return;
-
-	err = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_HIGH,
-				    "ehci_vbus_gpio");
-	if (err)
-		dev_err(dev, "can't request ehci vbus gpio %d", gpio);
-}
-
-static int s5p_ehci_probe(struct platform_device *pdev)
-{
-	struct s5p_ehci_platdata *pdata = dev_get_platdata(&pdev->dev);
-	struct s5p_ehci_hcd *s5p_ehci;
-	struct usb_hcd *hcd;
-	struct ehci_hcd *ehci;
-	struct resource *res;
-	struct usb_phy *phy;
-	int irq;
-	int err;
-
-	/*
-	 * Right now device-tree probed devices don't get dma_mask set.
-	 * Since shared usb code relies on it, set it here for now.
-	 * Once we move to full device tree support this will vanish off.
-	 */
-	if (!pdev->dev.dma_mask)
-		pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
-	if (!pdev->dev.coherent_dma_mask)
-		pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-
-	s5p_setup_vbus_gpio(pdev);
-
-	hcd = usb_create_hcd(&s5p_ehci_hc_driver,
-			     &pdev->dev, dev_name(&pdev->dev));
-	if (!hcd) {
-		dev_err(&pdev->dev, "Unable to create HCD\n");
-		return -ENOMEM;
-	}
-	s5p_ehci = to_s5p_ehci(hcd);
-
-	if (of_device_is_compatible(pdev->dev.of_node,
-					"samsung,exynos5440-ehci")) {
-		s5p_ehci->pdata = &empty_platdata;
-		goto skip_phy;
-	}
-
-	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
-	if (IS_ERR(phy)) {
-		/* Fallback to pdata */
-		if (!pdata) {
-			usb_put_hcd(hcd);
-			dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
-			return -EPROBE_DEFER;
-		} else {
-			s5p_ehci->pdata = pdata;
-		}
-	} else {
-		s5p_ehci->phy = phy;
-		s5p_ehci->otg = phy->otg;
-	}
-
-skip_phy:
-
-	s5p_ehci->clk = devm_clk_get(&pdev->dev, "usbhost");
-
-	if (IS_ERR(s5p_ehci->clk)) {
-		dev_err(&pdev->dev, "Failed to get usbhost clock\n");
-		err = PTR_ERR(s5p_ehci->clk);
-		goto fail_clk;
-	}
-
-	err = clk_prepare_enable(s5p_ehci->clk);
-	if (err)
-		goto fail_clk;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "Failed to get I/O memory\n");
-		err = -ENXIO;
-		goto fail_io;
-	}
-
-	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = resource_size(res);
-	hcd->regs = devm_ioremap(&pdev->dev, res->start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		dev_err(&pdev->dev, "Failed to remap I/O memory\n");
-		err = -ENOMEM;
-		goto fail_io;
-	}
-
-	irq = platform_get_irq(pdev, 0);
-	if (!irq) {
-		dev_err(&pdev->dev, "Failed to get IRQ\n");
-		err = -ENODEV;
-		goto fail_io;
-	}
-
-	if (s5p_ehci->otg)
-		s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self);
-
-	if (s5p_ehci->phy)
-		usb_phy_init(s5p_ehci->phy);
-	else if (s5p_ehci->pdata->phy_init)
-		s5p_ehci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);
-
-	ehci = hcd_to_ehci(hcd);
-	ehci->caps = hcd->regs;
-
-	/* DMA burst Enable */
-	writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
-
-	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
-	if (err) {
-		dev_err(&pdev->dev, "Failed to add USB HCD\n");
-		goto fail_add_hcd;
-	}
-
-	platform_set_drvdata(pdev, hcd);
-
-	return 0;
-
-fail_add_hcd:
-	if (s5p_ehci->phy)
-		usb_phy_shutdown(s5p_ehci->phy);
-	else if (s5p_ehci->pdata->phy_exit)
-		s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
-fail_io:
-	clk_disable_unprepare(s5p_ehci->clk);
-fail_clk:
-	usb_put_hcd(hcd);
-	return err;
-}
-
-static int s5p_ehci_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-	struct s5p_ehci_hcd *s5p_ehci = to_s5p_ehci(hcd);
-
-	usb_remove_hcd(hcd);
-
-	if (s5p_ehci->otg)
-		s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self);
-
-	if (s5p_ehci->phy)
-		usb_phy_shutdown(s5p_ehci->phy);
-	else if (s5p_ehci->pdata->phy_exit)
-		s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
-
-	clk_disable_unprepare(s5p_ehci->clk);
-
-	usb_put_hcd(hcd);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int s5p_ehci_suspend(struct device *dev)
-{
-	struct usb_hcd *hcd = dev_get_drvdata(dev);
-	struct s5p_ehci_hcd *s5p_ehci = to_s5p_ehci(hcd);
-	struct platform_device *pdev = to_platform_device(dev);
-
-	bool do_wakeup = device_may_wakeup(dev);
-	int rc;
-
-	rc = ehci_suspend(hcd, do_wakeup);
-
-	if (s5p_ehci->otg)
-		s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self);
-
-	if (s5p_ehci->phy)
-		usb_phy_shutdown(s5p_ehci->phy);
-	else if (s5p_ehci->pdata->phy_exit)
-		s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
-
-	clk_disable_unprepare(s5p_ehci->clk);
-
-	return rc;
-}
-
-static int s5p_ehci_resume(struct device *dev)
-{
-	struct usb_hcd *hcd = dev_get_drvdata(dev);
-	struct  s5p_ehci_hcd *s5p_ehci = to_s5p_ehci(hcd);
-	struct platform_device *pdev = to_platform_device(dev);
-
-	clk_prepare_enable(s5p_ehci->clk);
-
-	if (s5p_ehci->otg)
-		s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self);
-
-	if (s5p_ehci->phy)
-		usb_phy_init(s5p_ehci->phy);
-	else if (s5p_ehci->pdata->phy_init)
-		s5p_ehci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);
-
-	/* DMA burst Enable */
-	writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
-
-	ehci_resume(hcd, false);
-	return 0;
-}
-#else
-#define s5p_ehci_suspend	NULL
-#define s5p_ehci_resume		NULL
-#endif
-
-static const struct dev_pm_ops s5p_ehci_pm_ops = {
-	.suspend	= s5p_ehci_suspend,
-	.resume		= s5p_ehci_resume,
-};
-
-#ifdef CONFIG_OF
-static const struct of_device_id exynos_ehci_match[] = {
-	{ .compatible = "samsung,exynos4210-ehci" },
-	{ .compatible = "samsung,exynos5440-ehci" },
-	{},
-};
-MODULE_DEVICE_TABLE(of, exynos_ehci_match);
-#endif
-
-static struct platform_driver s5p_ehci_driver = {
-	.probe		= s5p_ehci_probe,
-	.remove		= s5p_ehci_remove,
-	.shutdown	= usb_hcd_platform_shutdown,
-	.driver = {
-		.name	= "s5p-ehci",
-		.owner	= THIS_MODULE,
-		.pm	= &s5p_ehci_pm_ops,
-		.of_match_table = of_match_ptr(exynos_ehci_match),
-	}
-};
-static const struct ehci_driver_overrides s5p_overrides __initdata = {
-	.extra_priv_size = sizeof(struct s5p_ehci_hcd),
-};
-
-static int __init ehci_s5p_init(void)
-{
-	if (usb_disabled())
-		return -ENODEV;
-
-	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
-	ehci_init_driver(&s5p_ehci_hc_driver, &s5p_overrides);
-	return platform_driver_register(&s5p_ehci_driver);
-}
-module_init(ehci_s5p_init);
-
-static void __exit ehci_s5p_cleanup(void)
-{
-	platform_driver_unregister(&s5p_ehci_driver);
-}
-module_exit(ehci_s5p_cleanup);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_ALIAS("platform:s5p-ehci");
-MODULE_AUTHOR("Jingoo Han");
-MODULE_AUTHOR("Joonyoung Shim");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 85dd24e..e113fd7 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -103,83 +103,210 @@
 		*hw_p = *shadow_next_periodic(ehci, &here,
 				Q_NEXT_TYPE(ehci, *hw_p));
 	else
-		*hw_p = ehci->dummy->qh_dma;
-}
-
-/* how many of the uframe's 125 usecs are allocated? */
-static unsigned short
-periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
-{
-	__hc32			*hw_p = &ehci->periodic [frame];
-	union ehci_shadow	*q = &ehci->pshadow [frame];
-	unsigned		usecs = 0;
-	struct ehci_qh_hw	*hw;
-
-	while (q->ptr) {
-		switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) {
-		case Q_TYPE_QH:
-			hw = q->qh->hw;
-			/* is it in the S-mask? */
-			if (hw->hw_info2 & cpu_to_hc32(ehci, 1 << uframe))
-				usecs += q->qh->usecs;
-			/* ... or C-mask? */
-			if (hw->hw_info2 & cpu_to_hc32(ehci,
-					1 << (8 + uframe)))
-				usecs += q->qh->c_usecs;
-			hw_p = &hw->hw_next;
-			q = &q->qh->qh_next;
-			break;
-		// case Q_TYPE_FSTN:
-		default:
-			/* for "save place" FSTNs, count the relevant INTR
-			 * bandwidth from the previous frame
-			 */
-			if (q->fstn->hw_prev != EHCI_LIST_END(ehci)) {
-				ehci_dbg (ehci, "ignoring FSTN cost ...\n");
-			}
-			hw_p = &q->fstn->hw_next;
-			q = &q->fstn->fstn_next;
-			break;
-		case Q_TYPE_ITD:
-			if (q->itd->hw_transaction[uframe])
-				usecs += q->itd->stream->usecs;
-			hw_p = &q->itd->hw_next;
-			q = &q->itd->itd_next;
-			break;
-		case Q_TYPE_SITD:
-			/* is it in the S-mask?  (count SPLIT, DATA) */
-			if (q->sitd->hw_uframe & cpu_to_hc32(ehci,
-					1 << uframe)) {
-				if (q->sitd->hw_fullspeed_ep &
-						cpu_to_hc32(ehci, 1<<31))
-					usecs += q->sitd->stream->usecs;
-				else	/* worst case for OUT start-split */
-					usecs += HS_USECS_ISO (188);
-			}
-
-			/* ... C-mask?  (count CSPLIT, DATA) */
-			if (q->sitd->hw_uframe &
-					cpu_to_hc32(ehci, 1 << (8 + uframe))) {
-				/* worst case for IN complete-split */
-				usecs += q->sitd->stream->c_usecs;
-			}
-
-			hw_p = &q->sitd->hw_next;
-			q = &q->sitd->sitd_next;
-			break;
-		}
-	}
-#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
-	if (usecs > ehci->uframe_periodic_max)
-		ehci_err (ehci, "uframe %d sched overrun: %d usecs\n",
-			frame * 8 + uframe, usecs);
-#endif
-	return usecs;
+		*hw_p = cpu_to_hc32(ehci, ehci->dummy->qh_dma);
 }
 
 /*-------------------------------------------------------------------------*/
 
-static int same_tt (struct usb_device *dev1, struct usb_device *dev2)
+/* Bandwidth and TT management */
+
+/* Find the TT data structure for this device; create it if necessary */
+static struct ehci_tt *find_tt(struct usb_device *udev)
+{
+	struct usb_tt		*utt = udev->tt;
+	struct ehci_tt		*tt, **tt_index, **ptt;
+	unsigned		port;
+	bool			allocated_index = false;
+
+	if (!utt)
+		return NULL;		/* Not below a TT */
+
+	/*
+	 * Find/create our data structure.
+	 * For hubs with a single TT, we get it directly.
+	 * For hubs with multiple TTs, there's an extra level of pointers.
+	 */
+	tt_index = NULL;
+	if (utt->multi) {
+		tt_index = utt->hcpriv;
+		if (!tt_index) {		/* Create the index array */
+			tt_index = kzalloc(utt->hub->maxchild *
+					sizeof(*tt_index), GFP_ATOMIC);
+			if (!tt_index)
+				return ERR_PTR(-ENOMEM);
+			utt->hcpriv = tt_index;
+			allocated_index = true;
+		}
+		port = udev->ttport - 1;
+		ptt = &tt_index[port];
+	} else {
+		port = 0;
+		ptt = (struct ehci_tt **) &utt->hcpriv;
+	}
+
+	tt = *ptt;
+	if (!tt) {				/* Create the ehci_tt */
+		struct ehci_hcd		*ehci =
+				hcd_to_ehci(bus_to_hcd(udev->bus));
+
+		tt = kzalloc(sizeof(*tt), GFP_ATOMIC);
+		if (!tt) {
+			if (allocated_index) {
+				utt->hcpriv = NULL;
+				kfree(tt_index);
+			}
+			return ERR_PTR(-ENOMEM);
+		}
+		list_add_tail(&tt->tt_list, &ehci->tt_list);
+		INIT_LIST_HEAD(&tt->ps_list);
+		tt->usb_tt = utt;
+		tt->tt_port = port;
+		*ptt = tt;
+	}
+
+	return tt;
+}
+
+/* Release the TT above udev, if it's not in use */
+static void drop_tt(struct usb_device *udev)
+{
+	struct usb_tt		*utt = udev->tt;
+	struct ehci_tt		*tt, **tt_index, **ptt;
+	int			cnt, i;
+
+	if (!utt || !utt->hcpriv)
+		return;		/* Not below a TT, or never allocated */
+
+	cnt = 0;
+	if (utt->multi) {
+		tt_index = utt->hcpriv;
+		ptt = &tt_index[udev->ttport - 1];
+
+		/* How many entries are left in tt_index? */
+		for (i = 0; i < utt->hub->maxchild; ++i)
+			cnt += !!tt_index[i];
+	} else {
+		tt_index = NULL;
+		ptt = (struct ehci_tt **) &utt->hcpriv;
+	}
+
+	tt = *ptt;
+	if (!tt || !list_empty(&tt->ps_list))
+		return;		/* never allocated, or still in use */
+
+	list_del(&tt->tt_list);
+	*ptt = NULL;
+	kfree(tt);
+	if (cnt == 1) {
+		utt->hcpriv = NULL;
+		kfree(tt_index);
+	}
+}
+
+static void bandwidth_dbg(struct ehci_hcd *ehci, int sign, char *type,
+		struct ehci_per_sched *ps)
+{
+	dev_dbg(&ps->udev->dev,
+			"ep %02x: %s %s @ %u+%u (%u.%u+%u) [%u/%u us] mask %04x\n",
+			ps->ep->desc.bEndpointAddress,
+			(sign >= 0 ? "reserve" : "release"), type,
+			(ps->bw_phase << 3) + ps->phase_uf, ps->bw_uperiod,
+			ps->phase, ps->phase_uf, ps->period,
+			ps->usecs, ps->c_usecs, ps->cs_mask);
+}
+
+static void reserve_release_intr_bandwidth(struct ehci_hcd *ehci,
+		struct ehci_qh *qh, int sign)
+{
+	unsigned		start_uf;
+	unsigned		i, j, m;
+	int			usecs = qh->ps.usecs;
+	int			c_usecs = qh->ps.c_usecs;
+	int			tt_usecs = qh->ps.tt_usecs;
+	struct ehci_tt		*tt;
+
+	if (qh->ps.phase == NO_FRAME)	/* Bandwidth wasn't reserved */
+		return;
+	start_uf = qh->ps.bw_phase << 3;
+
+	bandwidth_dbg(ehci, sign, "intr", &qh->ps);
+
+	if (sign < 0) {		/* Release bandwidth */
+		usecs = -usecs;
+		c_usecs = -c_usecs;
+		tt_usecs = -tt_usecs;
+	}
+
+	/* Entire transaction (high speed) or start-split (full/low speed) */
+	for (i = start_uf + qh->ps.phase_uf; i < EHCI_BANDWIDTH_SIZE;
+			i += qh->ps.bw_uperiod)
+		ehci->bandwidth[i] += usecs;
+
+	/* Complete-split (full/low speed) */
+	if (qh->ps.c_usecs) {
+		/* NOTE: adjustments needed for FSTN */
+		for (i = start_uf; i < EHCI_BANDWIDTH_SIZE;
+				i += qh->ps.bw_uperiod) {
+			for ((j = 2, m = 1 << (j+8)); j < 8; (++j, m <<= 1)) {
+				if (qh->ps.cs_mask & m)
+					ehci->bandwidth[i+j] += c_usecs;
+			}
+		}
+	}
+
+	/* FS/LS bus bandwidth */
+	if (tt_usecs) {
+		tt = find_tt(qh->ps.udev);
+		if (sign > 0)
+			list_add_tail(&qh->ps.ps_list, &tt->ps_list);
+		else
+			list_del(&qh->ps.ps_list);
+
+		for (i = start_uf >> 3; i < EHCI_BANDWIDTH_FRAMES;
+				i += qh->ps.bw_period)
+			tt->bandwidth[i] += tt_usecs;
+	}
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void compute_tt_budget(u8 budget_table[EHCI_BANDWIDTH_SIZE],
+		struct ehci_tt *tt)
+{
+	struct ehci_per_sched	*ps;
+	unsigned		uframe, uf, x;
+	u8			*budget_line;
+
+	if (!tt)
+		return;
+	memset(budget_table, 0, EHCI_BANDWIDTH_SIZE);
+
+	/* Add up the contributions from all the endpoints using this TT */
+	list_for_each_entry(ps, &tt->ps_list, ps_list) {
+		for (uframe = ps->bw_phase << 3; uframe < EHCI_BANDWIDTH_SIZE;
+				uframe += ps->bw_uperiod) {
+			budget_line = &budget_table[uframe];
+			x = ps->tt_usecs;
+
+			/* propagate the time forward */
+			for (uf = ps->phase_uf; uf < 8; ++uf) {
+				x += budget_line[uf];
+
+				/* Each microframe lasts 125 us */
+				if (x <= 125) {
+					budget_line[uf] = x;
+					break;
+				} else {
+					budget_line[uf] = 125;
+					x -= 125;
+				}
+			}
+		}
+	}
+}
+
+static int __maybe_unused same_tt(struct usb_device *dev1,
+		struct usb_device *dev2)
 {
 	if (!dev1->tt || !dev2->tt)
 		return 0;
@@ -227,68 +354,6 @@
 	}
 }
 
-/* How many of the tt's periodic downstream 1000 usecs are allocated?
- *
- * While this measures the bandwidth in terms of usecs/uframe,
- * the low/fullspeed bus has no notion of uframes, so any particular
- * low/fullspeed transfer can "carry over" from one uframe to the next,
- * since the TT just performs downstream transfers in sequence.
- *
- * For example two separate 100 usec transfers can start in the same uframe,
- * and the second one would "carry over" 75 usecs into the next uframe.
- */
-static void
-periodic_tt_usecs (
-	struct ehci_hcd *ehci,
-	struct usb_device *dev,
-	unsigned frame,
-	unsigned short tt_usecs[8]
-)
-{
-	__hc32			*hw_p = &ehci->periodic [frame];
-	union ehci_shadow	*q = &ehci->pshadow [frame];
-	unsigned char		uf;
-
-	memset(tt_usecs, 0, 16);
-
-	while (q->ptr) {
-		switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) {
-		case Q_TYPE_ITD:
-			hw_p = &q->itd->hw_next;
-			q = &q->itd->itd_next;
-			continue;
-		case Q_TYPE_QH:
-			if (same_tt(dev, q->qh->dev)) {
-				uf = tt_start_uframe(ehci, q->qh->hw->hw_info2);
-				tt_usecs[uf] += q->qh->tt_usecs;
-			}
-			hw_p = &q->qh->hw->hw_next;
-			q = &q->qh->qh_next;
-			continue;
-		case Q_TYPE_SITD:
-			if (same_tt(dev, q->sitd->urb->dev)) {
-				uf = tt_start_uframe(ehci, q->sitd->hw_uframe);
-				tt_usecs[uf] += q->sitd->stream->tt_usecs;
-			}
-			hw_p = &q->sitd->hw_next;
-			q = &q->sitd->sitd_next;
-			continue;
-		// case Q_TYPE_FSTN:
-		default:
-			ehci_dbg(ehci, "ignoring periodic frame %d FSTN\n",
-					frame);
-			hw_p = &q->fstn->hw_next;
-			q = &q->fstn->fstn_next;
-		}
-	}
-
-	carryover_tt_bandwidth(tt_usecs);
-
-	if (max_tt_usecs[7] < tt_usecs[7])
-		ehci_err(ehci, "frame %d tt sched overrun: %d usecs\n",
-			frame, tt_usecs[7] - max_tt_usecs[7]);
-}
-
 /*
  * Return true if the device's tt's downstream bus is available for a
  * periodic transfer of the specified length (usecs), starting at the
@@ -312,20 +377,29 @@
  */
 static int tt_available (
 	struct ehci_hcd		*ehci,
-	unsigned		period,
-	struct usb_device	*dev,
+	struct ehci_per_sched	*ps,
+	struct ehci_tt		*tt,
 	unsigned		frame,
-	unsigned		uframe,
-	u16			usecs
+	unsigned		uframe
 )
 {
+	unsigned		period = ps->bw_period;
+	unsigned		usecs = ps->tt_usecs;
+
 	if ((period == 0) || (uframe >= 7))	/* error */
 		return 0;
 
-	for (; frame < ehci->periodic_size; frame += period) {
-		unsigned short tt_usecs[8];
+	for (frame &= period - 1; frame < EHCI_BANDWIDTH_FRAMES;
+			frame += period) {
+		unsigned	i, uf;
+		unsigned short	tt_usecs[8];
 
-		periodic_tt_usecs (ehci, dev, frame, tt_usecs);
+		if (tt->bandwidth[frame] + usecs > 900)
+			return 0;
+
+		uf = frame << 3;
+		for (i = 0; i < 8; (++i, ++uf))
+			tt_usecs[i] = ehci->tt_budget[uf];
 
 		if (max_tt_usecs[uframe] <= tt_usecs[uframe])
 			return 0;
@@ -337,7 +411,7 @@
 		 */
 		if (125 < usecs) {
 			int ufs = (usecs / 125);
-			int i;
+
 			for (i = uframe; i < (uframe + ufs) && i < 8; i++)
 				if (0 < tt_usecs[i])
 					return 0;
@@ -391,7 +465,7 @@
 				continue;
 			case Q_TYPE_QH:
 				hw = here.qh->hw;
-				if (same_tt (dev, here.qh->dev)) {
+				if (same_tt(dev, here.qh->ps.udev)) {
 					u32		mask;
 
 					mask = hc32_to_cpu(ehci,
@@ -471,19 +545,19 @@
 static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
 	unsigned	i;
-	unsigned	period = qh->period;
+	unsigned	period = qh->ps.period;
 
-	dev_dbg (&qh->dev->dev,
+	dev_dbg(&qh->ps.udev->dev,
 		"link qh%d-%04x/%p start %d [%d/%d us]\n",
 		period, hc32_to_cpup(ehci, &qh->hw->hw_info2)
 			& (QH_CMASK | QH_SMASK),
-		qh, qh->start, qh->usecs, qh->c_usecs);
+		qh, qh->ps.phase, qh->ps.usecs, qh->ps.c_usecs);
 
 	/* high bandwidth, or otherwise every microframe */
 	if (period == 0)
 		period = 1;
 
-	for (i = qh->start; i < ehci->periodic_size; i += period) {
+	for (i = qh->ps.phase; i < ehci->periodic_size; i += period) {
 		union ehci_shadow	*prev = &ehci->pshadow[i];
 		__hc32			*hw_p = &ehci->periodic[i];
 		union ehci_shadow	here = *prev;
@@ -503,7 +577,7 @@
 		 * enables sharing interior tree nodes
 		 */
 		while (here.ptr && qh != here.qh) {
-			if (qh->period > here.qh->period)
+			if (qh->ps.period > here.qh->ps.period)
 				break;
 			prev = &here.qh->qh_next;
 			hw_p = &here.qh->hw->hw_next;
@@ -523,10 +597,10 @@
 	qh->xacterrs = 0;
 	qh->exception = 0;
 
-	/* update per-qh bandwidth for usbfs */
-	ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->period
-		? ((qh->usecs + qh->c_usecs) / qh->period)
-		: (qh->usecs * 8);
+	/* update per-qh bandwidth for debugfs */
+	ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->ps.bw_period
+		? ((qh->ps.usecs + qh->ps.c_usecs) / qh->ps.bw_period)
+		: (qh->ps.usecs * 8);
 
 	list_add(&qh->intr_node, &ehci->intr_qh_list);
 
@@ -556,22 +630,21 @@
 	 */
 
 	/* high bandwidth, or otherwise part of every microframe */
-	if ((period = qh->period) == 0)
-		period = 1;
+	period = qh->ps.period ? : 1;
 
-	for (i = qh->start; i < ehci->periodic_size; i += period)
+	for (i = qh->ps.phase; i < ehci->periodic_size; i += period)
 		periodic_unlink (ehci, i, qh);
 
-	/* update per-qh bandwidth for usbfs */
-	ehci_to_hcd(ehci)->self.bandwidth_allocated -= qh->period
-		? ((qh->usecs + qh->c_usecs) / qh->period)
-		: (qh->usecs * 8);
+	/* update per-qh bandwidth for debugfs */
+	ehci_to_hcd(ehci)->self.bandwidth_allocated -= qh->ps.bw_period
+		? ((qh->ps.usecs + qh->ps.c_usecs) / qh->ps.bw_period)
+		: (qh->ps.usecs * 8);
 
-	dev_dbg (&qh->dev->dev,
+	dev_dbg(&qh->ps.udev->dev,
 		"unlink qh%d-%04x/%p start %d [%d/%d us]\n",
-		qh->period,
+		qh->ps.period,
 		hc32_to_cpup(ehci, &qh->hw->hw_info2) & (QH_CMASK | QH_SMASK),
-		qh, qh->start, qh->usecs, qh->c_usecs);
+		qh, qh->ps.phase, qh->ps.usecs, qh->ps.c_usecs);
 
 	/* qh->qh_next still "live" to HC */
 	qh->qh_state = QH_STATE_UNLINK;
@@ -694,11 +767,9 @@
 	struct ehci_hcd *ehci,
 	unsigned	frame,
 	unsigned	uframe,
-	unsigned	period,
+	unsigned	uperiod,
 	unsigned	usecs
 ) {
-	int		claimed;
-
 	/* complete split running into next frame?
 	 * given FSTN support, we could sometimes check...
 	 */
@@ -708,25 +779,10 @@
 	/* convert "usecs we need" to "max already claimed" */
 	usecs = ehci->uframe_periodic_max - usecs;
 
-	/* we "know" 2 and 4 uframe intervals were rejected; so
-	 * for period 0, check _every_ microframe in the schedule.
-	 */
-	if (unlikely (period == 0)) {
-		do {
-			for (uframe = 0; uframe < 7; uframe++) {
-				claimed = periodic_usecs (ehci, frame, uframe);
-				if (claimed > usecs)
-					return 0;
-			}
-		} while ((frame += 1) < ehci->periodic_size);
-
-	/* just check the specified uframe, at that period */
-	} else {
-		do {
-			claimed = periodic_usecs (ehci, frame, uframe);
-			if (claimed > usecs)
-				return 0;
-		} while ((frame += period) < ehci->periodic_size);
+	for (uframe += frame << 3; uframe < EHCI_BANDWIDTH_SIZE;
+			uframe += uperiod) {
+		if (ehci->bandwidth[uframe] > usecs)
+			return 0;
 	}
 
 	// success!
@@ -737,40 +793,40 @@
 	struct ehci_hcd		*ehci,
 	unsigned		frame,
 	unsigned		uframe,
-	const struct ehci_qh	*qh,
-	__hc32			*c_maskp
+	struct ehci_qh		*qh,
+	unsigned		*c_maskp,
+	struct ehci_tt		*tt
 )
 {
 	int		retval = -ENOSPC;
 	u8		mask = 0;
 
-	if (qh->c_usecs && uframe >= 6)		/* FSTN territory? */
+	if (qh->ps.c_usecs && uframe >= 6)	/* FSTN territory? */
 		goto done;
 
-	if (!check_period (ehci, frame, uframe, qh->period, qh->usecs))
+	if (!check_period(ehci, frame, uframe, qh->ps.bw_uperiod, qh->ps.usecs))
 		goto done;
-	if (!qh->c_usecs) {
+	if (!qh->ps.c_usecs) {
 		retval = 0;
 		*c_maskp = 0;
 		goto done;
 	}
 
 #ifdef CONFIG_USB_EHCI_TT_NEWSCHED
-	if (tt_available (ehci, qh->period, qh->dev, frame, uframe,
-				qh->tt_usecs)) {
+	if (tt_available(ehci, &qh->ps, tt, frame, uframe)) {
 		unsigned i;
 
 		/* TODO : this may need FSTN for SSPLIT in uframe 5. */
-		for (i=uframe+1; i<8 && i<uframe+4; i++)
-			if (!check_period (ehci, frame, i,
-						qh->period, qh->c_usecs))
+		for (i = uframe+2; i < 8 && i <= uframe+4; i++)
+			if (!check_period(ehci, frame, i,
+					qh->ps.bw_uperiod, qh->ps.c_usecs))
 				goto done;
 			else
 				mask |= 1 << i;
 
 		retval = 0;
 
-		*c_maskp = cpu_to_hc32(ehci, mask << 8);
+		*c_maskp = mask;
 	}
 #else
 	/* Make sure this tt's buffer is also available for CSPLITs.
@@ -781,15 +837,15 @@
 	 * one smart pass...
 	 */
 	mask = 0x03 << (uframe + qh->gap_uf);
-	*c_maskp = cpu_to_hc32(ehci, mask << 8);
+	*c_maskp = mask;
 
 	mask |= 1 << uframe;
-	if (tt_no_collision (ehci, qh->period, qh->dev, frame, mask)) {
-		if (!check_period (ehci, frame, uframe + qh->gap_uf + 1,
-					qh->period, qh->c_usecs))
+	if (tt_no_collision(ehci, qh->ps.bw_period, qh->ps.udev, frame, mask)) {
+		if (!check_period(ehci, frame, uframe + qh->gap_uf + 1,
+				qh->ps.bw_uperiod, qh->ps.c_usecs))
 			goto done;
-		if (!check_period (ehci, frame, uframe + qh->gap_uf,
-					qh->period, qh->c_usecs))
+		if (!check_period(ehci, frame, uframe + qh->gap_uf,
+				qh->ps.bw_uperiod, qh->ps.c_usecs))
 			goto done;
 		retval = 0;
 	}
@@ -803,62 +859,67 @@
  */
 static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-	int		status;
+	int		status = 0;
 	unsigned	uframe;
-	__hc32		c_mask;
-	unsigned	frame;		/* 0..(qh->period - 1), or NO_FRAME */
+	unsigned	c_mask;
 	struct ehci_qh_hw	*hw = qh->hw;
+	struct ehci_tt		*tt;
 
 	hw->hw_next = EHCI_LIST_END(ehci);
-	frame = qh->start;
 
 	/* reuse the previous schedule slots, if we can */
-	if (frame < qh->period) {
-		uframe = ffs(hc32_to_cpup(ehci, &hw->hw_info2) & QH_SMASK);
-		status = check_intr_schedule (ehci, frame, --uframe,
-				qh, &c_mask);
-	} else {
-		uframe = 0;
-		c_mask = 0;
-		status = -ENOSPC;
+	if (qh->ps.phase != NO_FRAME) {
+		ehci_dbg(ehci, "reused qh %p schedule\n", qh);
+		return 0;
 	}
 
+	uframe = 0;
+	c_mask = 0;
+	tt = find_tt(qh->ps.udev);
+	if (IS_ERR(tt)) {
+		status = PTR_ERR(tt);
+		goto done;
+	}
+	compute_tt_budget(ehci->tt_budget, tt);
+
 	/* else scan the schedule to find a group of slots such that all
 	 * uframes have enough periodic bandwidth available.
 	 */
-	if (status) {
-		/* "normal" case, uframing flexible except with splits */
-		if (qh->period) {
-			int		i;
+	/* "normal" case, uframing flexible except with splits */
+	if (qh->ps.bw_period) {
+		int		i;
+		unsigned	frame;
 
-			for (i = qh->period; status && i > 0; --i) {
-				frame = ++ehci->random_frame % qh->period;
-				for (uframe = 0; uframe < 8; uframe++) {
-					status = check_intr_schedule (ehci,
-							frame, uframe, qh,
-							&c_mask);
-					if (status == 0)
-						break;
-				}
+		for (i = qh->ps.bw_period; i > 0; --i) {
+			frame = ++ehci->random_frame & (qh->ps.bw_period - 1);
+			for (uframe = 0; uframe < 8; uframe++) {
+				status = check_intr_schedule(ehci,
+						frame, uframe, qh, &c_mask, tt);
+				if (status == 0)
+					goto got_it;
 			}
-
-		/* qh->period == 0 means every uframe */
-		} else {
-			frame = 0;
-			status = check_intr_schedule (ehci, 0, 0, qh, &c_mask);
 		}
-		if (status)
-			goto done;
-		qh->start = frame;
 
-		/* reset S-frame and (maybe) C-frame masks */
-		hw->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK));
-		hw->hw_info2 |= qh->period
-			? cpu_to_hc32(ehci, 1 << uframe)
-			: cpu_to_hc32(ehci, QH_SMASK);
-		hw->hw_info2 |= c_mask;
-	} else
-		ehci_dbg (ehci, "reused qh %p schedule\n", qh);
+	/* qh->ps.bw_period == 0 means every uframe */
+	} else {
+		status = check_intr_schedule(ehci, 0, 0, qh, &c_mask, tt);
+	}
+	if (status)
+		goto done;
+
+ got_it:
+	qh->ps.phase = (qh->ps.period ? ehci->random_frame &
+			(qh->ps.period - 1) : 0);
+	qh->ps.bw_phase = qh->ps.phase & (qh->ps.bw_period - 1);
+	qh->ps.phase_uf = uframe;
+	qh->ps.cs_mask = qh->ps.period ?
+			(c_mask << 8) | (1 << uframe) :
+			QH_SMASK;
+
+	/* reset S-frame and (maybe) C-frame masks */
+	hw->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK));
+	hw->hw_info2 |= cpu_to_hc32(ehci, qh->ps.cs_mask);
+	reserve_release_intr_bandwidth(ehci, qh, 1);
 
 done:
 	return status;
@@ -969,7 +1030,8 @@
 	if (likely (stream != NULL)) {
 		INIT_LIST_HEAD(&stream->td_list);
 		INIT_LIST_HEAD(&stream->free_list);
-		stream->next_uframe = -1;
+		stream->next_uframe = NO_FRAME;
+		stream->ps.phase = NO_FRAME;
 	}
 	return stream;
 }
@@ -978,25 +1040,24 @@
 iso_stream_init (
 	struct ehci_hcd		*ehci,
 	struct ehci_iso_stream	*stream,
-	struct usb_device	*dev,
-	int			pipe,
-	unsigned		interval
+	struct urb		*urb
 )
 {
 	static const u8 smask_out [] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f };
 
+	struct usb_device	*dev = urb->dev;
 	u32			buf1;
 	unsigned		epnum, maxp;
 	int			is_input;
-	long			bandwidth;
+	unsigned		tmp;
 
 	/*
 	 * this might be a "high bandwidth" highspeed endpoint,
 	 * as encoded in the ep descriptor's wMaxPacket field
 	 */
-	epnum = usb_pipeendpoint (pipe);
-	is_input = usb_pipein (pipe) ? USB_DIR_IN : 0;
-	maxp = usb_maxpacket(dev, pipe, !is_input);
+	epnum = usb_pipeendpoint(urb->pipe);
+	is_input = usb_pipein(urb->pipe) ? USB_DIR_IN : 0;
+	maxp = usb_endpoint_maxp(&urb->ep->desc);
 	if (is_input) {
 		buf1 = (1 << 11);
 	} else {
@@ -1020,9 +1081,19 @@
 		/* usbfs wants to report the average usecs per frame tied up
 		 * when transfers on this endpoint are scheduled ...
 		 */
-		stream->usecs = HS_USECS_ISO (maxp);
-		bandwidth = stream->usecs * 8;
-		bandwidth /= interval;
+		stream->ps.usecs = HS_USECS_ISO(maxp);
+
+		/* period for bandwidth allocation */
+		tmp = min_t(unsigned, EHCI_BANDWIDTH_SIZE,
+				1 << (urb->ep->desc.bInterval - 1));
+
+		/* Allow urb->interval to override */
+		stream->ps.bw_uperiod = min_t(unsigned, tmp, urb->interval);
+
+		stream->uperiod = urb->interval;
+		stream->ps.period = urb->interval >> 3;
+		stream->bandwidth = stream->ps.usecs * 8 /
+				stream->ps.bw_uperiod;
 
 	} else {
 		u32		addr;
@@ -1036,36 +1107,46 @@
 			addr |= dev->tt->hub->devnum << 16;
 		addr |= epnum << 8;
 		addr |= dev->devnum;
-		stream->usecs = HS_USECS_ISO (maxp);
+		stream->ps.usecs = HS_USECS_ISO(maxp);
 		think_time = dev->tt ? dev->tt->think_time : 0;
-		stream->tt_usecs = NS_TO_US (think_time + usb_calc_bus_time (
+		stream->ps.tt_usecs = NS_TO_US(think_time + usb_calc_bus_time(
 				dev->speed, is_input, 1, maxp));
 		hs_transfers = max (1u, (maxp + 187) / 188);
 		if (is_input) {
 			u32	tmp;
 
 			addr |= 1 << 31;
-			stream->c_usecs = stream->usecs;
-			stream->usecs = HS_USECS_ISO (1);
-			stream->raw_mask = 1;
+			stream->ps.c_usecs = stream->ps.usecs;
+			stream->ps.usecs = HS_USECS_ISO(1);
+			stream->ps.cs_mask = 1;
 
 			/* c-mask as specified in USB 2.0 11.18.4 3.c */
 			tmp = (1 << (hs_transfers + 2)) - 1;
-			stream->raw_mask |= tmp << (8 + 2);
+			stream->ps.cs_mask |= tmp << (8 + 2);
 		} else
-			stream->raw_mask = smask_out [hs_transfers - 1];
-		bandwidth = stream->usecs + stream->c_usecs;
-		bandwidth /= interval << 3;
+			stream->ps.cs_mask = smask_out[hs_transfers - 1];
 
-		/* stream->splits gets created from raw_mask later */
+		/* period for bandwidth allocation */
+		tmp = min_t(unsigned, EHCI_BANDWIDTH_FRAMES,
+				1 << (urb->ep->desc.bInterval - 1));
+
+		/* Allow urb->interval to override */
+		stream->ps.bw_period = min_t(unsigned, tmp, urb->interval);
+		stream->ps.bw_uperiod = stream->ps.bw_period << 3;
+
+		stream->ps.period = urb->interval;
+		stream->uperiod = urb->interval << 3;
+		stream->bandwidth = (stream->ps.usecs + stream->ps.c_usecs) /
+				stream->ps.bw_period;
+
+		/* stream->splits gets created from cs_mask later */
 		stream->address = cpu_to_hc32(ehci, addr);
 	}
-	stream->bandwidth = bandwidth;
 
-	stream->udev = dev;
+	stream->ps.udev = dev;
+	stream->ps.ep = urb->ep;
 
 	stream->bEndpointAddress = is_input | epnum;
-	stream->interval = interval;
 	stream->maxp = maxp;
 }
 
@@ -1090,9 +1171,7 @@
 		stream = iso_stream_alloc(GFP_ATOMIC);
 		if (likely (stream != NULL)) {
 			ep->hcpriv = stream;
-			stream->ep = ep;
-			iso_stream_init(ehci, stream, urb->dev, urb->pipe,
-					urb->interval);
+			iso_stream_init(ehci, stream, urb);
 		}
 
 	/* if dev->ep [epnum] is a QH, hw is set */
@@ -1137,7 +1216,7 @@
 	dma_addr_t	dma = urb->transfer_dma;
 
 	/* how many uframes are needed for these transfers */
-	iso_sched->span = urb->number_of_packets * stream->interval;
+	iso_sched->span = urb->number_of_packets * stream->uperiod;
 
 	/* figure out per-uframe itd fields that we'll need later
 	 * when we fit new itds into the schedule.
@@ -1236,7 +1315,7 @@
 
 		memset (itd, 0, sizeof *itd);
 		itd->itd_dma = itd_dma;
-		itd->frame = 9999;		/* an invalid value */
+		itd->frame = NO_FRAME;
 		list_add (&itd->itd_list, &sched->td_list);
 	}
 	spin_unlock_irqrestore (&ehci->lock, flags);
@@ -1249,49 +1328,106 @@
 
 /*-------------------------------------------------------------------------*/
 
+static void reserve_release_iso_bandwidth(struct ehci_hcd *ehci,
+		struct ehci_iso_stream *stream, int sign)
+{
+	unsigned		uframe;
+	unsigned		i, j;
+	unsigned		s_mask, c_mask, m;
+	int			usecs = stream->ps.usecs;
+	int			c_usecs = stream->ps.c_usecs;
+	int			tt_usecs = stream->ps.tt_usecs;
+	struct ehci_tt		*tt;
+
+	if (stream->ps.phase == NO_FRAME)	/* Bandwidth wasn't reserved */
+		return;
+	uframe = stream->ps.bw_phase << 3;
+
+	bandwidth_dbg(ehci, sign, "iso", &stream->ps);
+
+	if (sign < 0) {		/* Release bandwidth */
+		usecs = -usecs;
+		c_usecs = -c_usecs;
+		tt_usecs = -tt_usecs;
+	}
+
+	if (!stream->splits) {		/* High speed */
+		for (i = uframe + stream->ps.phase_uf; i < EHCI_BANDWIDTH_SIZE;
+				i += stream->ps.bw_uperiod)
+			ehci->bandwidth[i] += usecs;
+
+	} else {			/* Full speed */
+		s_mask = stream->ps.cs_mask;
+		c_mask = s_mask >> 8;
+
+		/* NOTE: adjustment needed for frame overflow */
+		for (i = uframe; i < EHCI_BANDWIDTH_SIZE;
+				i += stream->ps.bw_uperiod) {
+			for ((j = stream->ps.phase_uf, m = 1 << j); j < 8;
+					(++j, m <<= 1)) {
+				if (s_mask & m)
+					ehci->bandwidth[i+j] += usecs;
+				else if (c_mask & m)
+					ehci->bandwidth[i+j] += c_usecs;
+			}
+		}
+
+		tt = find_tt(stream->ps.udev);
+		if (sign > 0)
+			list_add_tail(&stream->ps.ps_list, &tt->ps_list);
+		else
+			list_del(&stream->ps.ps_list);
+
+		for (i = uframe >> 3; i < EHCI_BANDWIDTH_FRAMES;
+				i += stream->ps.bw_period)
+			tt->bandwidth[i] += tt_usecs;
+	}
+}
+
 static inline int
 itd_slot_ok (
 	struct ehci_hcd		*ehci,
-	u32			mod,
-	u32			uframe,
-	u8			usecs,
-	u32			period
+	struct ehci_iso_stream	*stream,
+	unsigned		uframe
 )
 {
-	uframe %= period;
-	do {
-		/* can't commit more than uframe_periodic_max usec */
-		if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7)
-				> (ehci->uframe_periodic_max - usecs))
-			return 0;
+	unsigned		usecs;
 
-		/* we know urb->interval is 2^N uframes */
-		uframe += period;
-	} while (uframe < mod);
+	/* convert "usecs we need" to "max already claimed" */
+	usecs = ehci->uframe_periodic_max - stream->ps.usecs;
+
+	for (uframe &= stream->ps.bw_uperiod - 1; uframe < EHCI_BANDWIDTH_SIZE;
+			uframe += stream->ps.bw_uperiod) {
+		if (ehci->bandwidth[uframe] > usecs)
+			return 0;
+	}
 	return 1;
 }
 
 static inline int
 sitd_slot_ok (
 	struct ehci_hcd		*ehci,
-	u32			mod,
 	struct ehci_iso_stream	*stream,
-	u32			uframe,
+	unsigned		uframe,
 	struct ehci_iso_sched	*sched,
-	u32			period_uframes
+	struct ehci_tt		*tt
 )
 {
-	u32			mask, tmp;
-	u32			frame, uf;
+	unsigned		mask, tmp;
+	unsigned		frame, uf;
 
-	mask = stream->raw_mask << (uframe & 7);
+	mask = stream->ps.cs_mask << (uframe & 7);
+
+	/* for OUT, don't wrap SSPLIT into H-microframe 7 */
+	if (((stream->ps.cs_mask & 0xff) << (uframe & 7)) >= (1 << 7))
+		return 0;
 
 	/* for IN, don't wrap CSPLIT into the next frame */
 	if (mask & ~0xffff)
 		return 0;
 
 	/* check bandwidth */
-	uframe %= period_uframes;
+	uframe &= stream->ps.bw_uperiod - 1;
 	frame = uframe >> 3;
 
 #ifdef CONFIG_USB_EHCI_TT_NEWSCHED
@@ -1299,54 +1435,48 @@
 	 * tt_available scheduling guarantees 10+% for control/bulk.
 	 */
 	uf = uframe & 7;
-	if (!tt_available(ehci, period_uframes >> 3,
-			stream->udev, frame, uf, stream->tt_usecs))
+	if (!tt_available(ehci, &stream->ps, tt, frame, uf))
 		return 0;
 #else
 	/* tt must be idle for start(s), any gap, and csplit.
 	 * assume scheduling slop leaves 10+% for control/bulk.
 	 */
-	if (!tt_no_collision(ehci, period_uframes >> 3,
-			stream->udev, frame, mask))
+	if (!tt_no_collision(ehci, stream->ps.bw_period,
+			stream->ps.udev, frame, mask))
 		return 0;
 #endif
 
-	/* this multi-pass logic is simple, but performance may
-	 * suffer when the schedule data isn't cached.
-	 */
 	do {
-		u32		max_used;
-
-		frame = uframe >> 3;
-		uf = uframe & 7;
+		unsigned	max_used;
+		unsigned	i;
 
 		/* check starts (OUT uses more than one) */
-		max_used = ehci->uframe_periodic_max - stream->usecs;
-		for (tmp = stream->raw_mask & 0xff; tmp; tmp >>= 1, uf++) {
-			if (periodic_usecs (ehci, frame, uf) > max_used)
+		uf = uframe;
+		max_used = ehci->uframe_periodic_max - stream->ps.usecs;
+		for (tmp = stream->ps.cs_mask & 0xff; tmp; tmp >>= 1, uf++) {
+			if (ehci->bandwidth[uf] > max_used)
 				return 0;
 		}
 
 		/* for IN, check CSPLIT */
-		if (stream->c_usecs) {
-			uf = uframe & 7;
-			max_used = ehci->uframe_periodic_max - stream->c_usecs;
-			do {
-				tmp = 1 << uf;
-				tmp <<= 8;
-				if ((stream->raw_mask & tmp) == 0)
+		if (stream->ps.c_usecs) {
+			max_used = ehci->uframe_periodic_max -
+					stream->ps.c_usecs;
+			uf = uframe & ~7;
+			tmp = 1 << (2+8);
+			for (i = (uframe & 7) + 2; i < 8; (++i, tmp <<= 1)) {
+				if ((stream->ps.cs_mask & tmp) == 0)
 					continue;
-				if (periodic_usecs (ehci, frame, uf)
-						> max_used)
+				if (ehci->bandwidth[uf+i] > max_used)
 					return 0;
-			} while (++uf < 8);
+			}
 		}
 
-		/* we know urb->interval is 2^N uframes */
-		uframe += period_uframes;
-	} while (uframe < mod);
+		uframe += stream->ps.bw_uperiod;
+	} while (uframe < EHCI_BANDWIDTH_SIZE);
 
-	stream->splits = cpu_to_hc32(ehci, stream->raw_mask << (uframe & 7));
+	stream->ps.cs_mask <<= uframe & 7;
+	stream->splits = cpu_to_hc32(ehci, stream->ps.cs_mask);
 	return 1;
 }
 
@@ -1361,8 +1491,6 @@
  * given EHCI_TUNE_FLS and the slop).  Or, write a smarter scheduler!
  */
 
-#define SCHEDULING_DELAY	40	/* microframes */
-
 static int
 iso_stream_schedule (
 	struct ehci_hcd		*ehci,
@@ -1370,134 +1498,184 @@
 	struct ehci_iso_stream	*stream
 )
 {
-	u32			now, base, next, start, period, span;
-	int			status;
+	u32			now, base, next, start, period, span, now2;
+	u32			wrap = 0, skip = 0;
+	int			status = 0;
 	unsigned		mod = ehci->periodic_size << 3;
 	struct ehci_iso_sched	*sched = urb->hcpriv;
+	bool			empty = list_empty(&stream->td_list);
+	bool			new_stream = false;
 
-	period = urb->interval;
+	period = stream->uperiod;
 	span = sched->span;
-	if (!stream->highspeed) {
-		period <<= 3;
+	if (!stream->highspeed)
 		span <<= 3;
+
+	/* Start a new isochronous stream? */
+	if (unlikely(empty && !hcd_periodic_completion_in_progress(
+			ehci_to_hcd(ehci), urb->ep))) {
+
+		/* Schedule the endpoint */
+		if (stream->ps.phase == NO_FRAME) {
+			int		done = 0;
+			struct ehci_tt	*tt = find_tt(stream->ps.udev);
+
+			if (IS_ERR(tt)) {
+				status = PTR_ERR(tt);
+				goto fail;
+			}
+			compute_tt_budget(ehci->tt_budget, tt);
+
+			start = ((-(++ehci->random_frame)) << 3) & (period - 1);
+
+			/* find a uframe slot with enough bandwidth.
+			 * Early uframes are more precious because full-speed
+			 * iso IN transfers can't use late uframes,
+			 * and therefore they should be allocated last.
+			 */
+			next = start;
+			start += period;
+			do {
+				start--;
+				/* check schedule: enough space? */
+				if (stream->highspeed) {
+					if (itd_slot_ok(ehci, stream, start))
+						done = 1;
+				} else {
+					if ((start % 8) >= 6)
+						continue;
+					if (sitd_slot_ok(ehci, stream, start,
+							sched, tt))
+						done = 1;
+				}
+			} while (start > next && !done);
+
+			/* no room in the schedule */
+			if (!done) {
+				ehci_dbg(ehci, "iso sched full %p", urb);
+				status = -ENOSPC;
+				goto fail;
+			}
+			stream->ps.phase = (start >> 3) &
+					(stream->ps.period - 1);
+			stream->ps.bw_phase = stream->ps.phase &
+					(stream->ps.bw_period - 1);
+			stream->ps.phase_uf = start & 7;
+			reserve_release_iso_bandwidth(ehci, stream, 1);
+		}
+
+		/* New stream is already scheduled; use the upcoming slot */
+		else {
+			start = (stream->ps.phase << 3) + stream->ps.phase_uf;
+		}
+
+		stream->next_uframe = start;
+		new_stream = true;
 	}
 
 	now = ehci_read_frame_index(ehci) & (mod - 1);
 
-	/* Typical case: reuse current schedule, stream is still active.
+	/* Take the isochronous scheduling threshold into account */
+	if (ehci->i_thresh)
+		next = now + ehci->i_thresh;	/* uframe cache */
+	else
+		next = (now + 2 + 7) & ~0x07;	/* full frame cache */
+
+	/*
+	 * Use ehci->last_iso_frame as the base.  There can't be any
+	 * TDs scheduled for earlier than that.
+	 */
+	base = ehci->last_iso_frame << 3;
+	next = (next - base) & (mod - 1);
+	start = (stream->next_uframe - base) & (mod - 1);
+
+	if (unlikely(new_stream))
+		goto do_ASAP;
+
+	/*
+	 * Typical case: reuse current schedule, stream may still be active.
 	 * Hopefully there are no gaps from the host falling behind
 	 * (irq delays etc).  If there are, the behavior depends on
 	 * whether URB_ISO_ASAP is set.
 	 */
-	if (likely (!list_empty (&stream->td_list))) {
+	now2 = (now - base) & (mod - 1);
 
-		/* Take the isochronous scheduling threshold into account */
-		if (ehci->i_thresh)
-			next = now + ehci->i_thresh;	/* uframe cache */
-		else
-			next = (now + 2 + 7) & ~0x07;	/* full frame cache */
-
-		/*
-		 * Use ehci->last_iso_frame as the base.  There can't be any
-		 * TDs scheduled for earlier than that.
-		 */
-		base = ehci->last_iso_frame << 3;
-		next = (next - base) & (mod - 1);
-		start = (stream->next_uframe - base) & (mod - 1);
-
-		/* Is the schedule already full? */
-		if (unlikely(start < period)) {
-			ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n",
-					urb, stream->next_uframe, base,
-					period, mod);
-			status = -ENOSPC;
-			goto fail;
-		}
-
-		/* Behind the scheduling threshold? */
-		if (unlikely(start < next)) {
-			unsigned now2 = (now - base) & (mod - 1);
-
-			/* USB_ISO_ASAP: Round up to the first available slot */
-			if (urb->transfer_flags & URB_ISO_ASAP)
-				start += (next - start + period - 1) & -period;
-
-			/*
-			 * Not ASAP: Use the next slot in the stream,
-			 * no matter what.
-			 */
-			else if (start + span - period < now2) {
-				ehci_dbg(ehci, "iso underrun %p (%u+%u < %u)\n",
-						urb, start + base,
-						span - period, now2 + base);
-			}
-		}
-
-		start += base;
+	/* Is the schedule already full? */
+	if (unlikely(!empty && start < period)) {
+		ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n",
+				urb, stream->next_uframe, base, period, mod);
+		status = -ENOSPC;
+		goto fail;
 	}
 
-	/* need to schedule; when's the next (u)frame we could start?
-	 * this is bigger than ehci->i_thresh allows; scheduling itself
-	 * isn't free, the delay should handle reasonably slow cpus.  it
-	 * can also help high bandwidth if the dma and irq loads don't
-	 * jump until after the queue is primed.
-	 */
-	else {
-		int done = 0;
+	/* Is the next packet scheduled after the base time? */
+	if (likely(!empty || start <= now2 + period)) {
 
-		base = now & ~0x07;
-		start = base + SCHEDULING_DELAY;
+		/* URB_ISO_ASAP: make sure that start >= next */
+		if (unlikely(start < next &&
+				(urb->transfer_flags & URB_ISO_ASAP)))
+			goto do_ASAP;
 
-		/* find a uframe slot with enough bandwidth.
-		 * Early uframes are more precious because full-speed
-		 * iso IN transfers can't use late uframes,
-		 * and therefore they should be allocated last.
-		 */
-		next = start;
-		start += period;
-		do {
-			start--;
-			/* check schedule: enough space? */
-			if (stream->highspeed) {
-				if (itd_slot_ok(ehci, mod, start,
-						stream->usecs, period))
-					done = 1;
-			} else {
-				if ((start % 8) >= 6)
-					continue;
-				if (sitd_slot_ok(ehci, mod, stream,
-						start, sched, period))
-					done = 1;
-			}
-		} while (start > next && !done);
+		/* Otherwise use start, if it's not in the past */
+		if (likely(start >= now2))
+			goto use_start;
 
-		/* no room in the schedule */
-		if (!done) {
-			ehci_dbg(ehci, "iso sched full %p", urb);
-			status = -ENOSPC;
-			goto fail;
-		}
+	/* Otherwise we got an underrun while the queue was empty */
+	} else {
+		if (urb->transfer_flags & URB_ISO_ASAP)
+			goto do_ASAP;
+		wrap = mod;
+		now2 += mod;
 	}
 
+	/* How many uframes and packets do we need to skip? */
+	skip = (now2 - start + period - 1) & -period;
+	if (skip >= span) {		/* Entirely in the past? */
+		ehci_dbg(ehci, "iso underrun %p (%u+%u < %u) [%u]\n",
+				urb, start + base, span - period, now2 + base,
+				base);
+
+		/* Try to keep the last TD intact for scanning later */
+		skip = span - period;
+
+		/* Will it come before the current scan position? */
+		if (empty) {
+			skip = span;	/* Skip the entire URB */
+			status = 1;	/* and give it back immediately */
+			iso_sched_free(stream, sched);
+			sched = NULL;
+		}
+	}
+	urb->error_count = skip / period;
+	if (sched)
+		sched->first_packet = urb->error_count;
+	goto use_start;
+
+ do_ASAP:
+	/* Use the first slot after "next" */
+	start = next + ((start - next) & (period - 1));
+
+ use_start:
 	/* Tried to schedule too far into the future? */
-	if (unlikely(start - base + span - period >= mod)) {
+	if (unlikely(start + span - period >= mod + wrap)) {
 		ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n",
-				urb, start - base, span - period, mod);
+				urb, start, span - period, mod + wrap);
 		status = -EFBIG;
 		goto fail;
 	}
 
-	stream->next_uframe = start & (mod - 1);
+	start += base;
+	stream->next_uframe = (start + skip) & (mod - 1);
 
 	/* report high speed start in uframes; full speed, in frames */
-	urb->start_frame = stream->next_uframe;
+	urb->start_frame = start & (mod - 1);
 	if (!stream->highspeed)
 		urb->start_frame >>= 3;
 
 	/* Make sure scan_isoc() sees these */
 	if (ehci->isoc_count == 0)
 		ehci->last_iso_frame = now >> 3;
-	return 0;
+	return status;
 
  fail:
 	iso_sched_free(stream, sched);
@@ -1610,7 +1788,8 @@
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
 
 	/* fill iTDs uframe by uframe */
-	for (packet = 0, itd = NULL; packet < urb->number_of_packets; ) {
+	for (packet = iso_sched->first_packet, itd = NULL;
+			packet < urb->number_of_packets;) {
 		if (itd == NULL) {
 			/* ASSERT:  we have all necessary itds */
 			// BUG_ON (list_empty (&iso_sched->td_list));
@@ -1630,7 +1809,7 @@
 
 		itd_patch(ehci, itd, iso_sched, packet, uframe);
 
-		next_uframe += stream->interval;
+		next_uframe += stream->uperiod;
 		next_uframe &= mod - 1;
 		packet++;
 
@@ -1770,9 +1949,9 @@
 		ehci_dbg (ehci, "can't get iso stream\n");
 		return -ENOMEM;
 	}
-	if (unlikely (urb->interval != stream->interval)) {
+	if (unlikely(urb->interval != stream->uperiod)) {
 		ehci_dbg (ehci, "can't change iso interval %d --> %d\n",
-			stream->interval, urb->interval);
+			stream->uperiod, urb->interval);
 		goto done;
 	}
 
@@ -1804,10 +1983,14 @@
 	if (unlikely(status))
 		goto done_not_linked;
 	status = iso_stream_schedule(ehci, urb, stream);
-	if (likely (status == 0))
+	if (likely(status == 0)) {
 		itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
-	else
+	} else if (status > 0) {
+		status = 0;
+		ehci_urb_done(ehci, urb, 0);
+	} else {
 		usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
+	}
  done_not_linked:
 	spin_unlock_irqrestore (&ehci->lock, flags);
  done:
@@ -1833,7 +2016,7 @@
 	dma_addr_t	dma = urb->transfer_dma;
 
 	/* how many frames are needed for these transfers */
-	iso_sched->span = urb->number_of_packets * stream->interval;
+	iso_sched->span = urb->number_of_packets * stream->ps.period;
 
 	/* figure out per-frame sitd fields that we'll need later
 	 * when we fit new sitds into the schedule.
@@ -1925,7 +2108,7 @@
 
 		memset (sitd, 0, sizeof *sitd);
 		sitd->sitd_dma = sitd_dma;
-		sitd->frame = 9999;		/* an invalid value */
+		sitd->frame = NO_FRAME;
 		list_add (&sitd->sitd_list, &iso_sched->td_list);
 	}
 
@@ -2008,7 +2191,7 @@
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
 
 	/* fill sITDs frame by frame */
-	for (packet = 0, sitd = NULL;
+	for (packet = sched->first_packet, sitd = NULL;
 			packet < urb->number_of_packets;
 			packet++) {
 
@@ -2027,7 +2210,7 @@
 		sitd_link(ehci, (next_uframe >> 3) & (ehci->periodic_size - 1),
 				sitd);
 
-		next_uframe += stream->interval << 3;
+		next_uframe += stream->uperiod;
 	}
 	stream->next_uframe = next_uframe & (mod - 1);
 
@@ -2146,9 +2329,9 @@
 		ehci_dbg (ehci, "can't get iso stream\n");
 		return -ENOMEM;
 	}
-	if (urb->interval != stream->interval) {
+	if (urb->interval != stream->ps.period) {
 		ehci_dbg (ehci, "can't change iso interval %d --> %d\n",
-			stream->interval, urb->interval);
+			stream->ps.period, urb->interval);
 		goto done;
 	}
 
@@ -2178,10 +2361,14 @@
 	if (unlikely(status))
 		goto done_not_linked;
 	status = iso_stream_schedule(ehci, urb, stream);
-	if (status == 0)
+	if (likely(status == 0)) {
 		sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
-	else
+	} else if (status > 0) {
+		status = 0;
+		ehci_urb_done(ehci, urb, 0);
+	} else {
 		usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
+	}
  done_not_linked:
 	spin_unlock_irqrestore (&ehci->lock, flags);
  done:
@@ -2259,7 +2446,8 @@
 				    q.itd->hw_next != EHCI_LIST_END(ehci))
 					*hw_p = q.itd->hw_next;
 				else
-					*hw_p = ehci->dummy->qh_dma;
+					*hw_p = cpu_to_hc32(ehci,
+							ehci->dummy->qh_dma);
 				type = Q_NEXT_TYPE(ehci, q.itd->hw_next);
 				wmb();
 				modified = itd_complete (ehci, q.itd);
@@ -2294,7 +2482,8 @@
 				    q.sitd->hw_next != EHCI_LIST_END(ehci))
 					*hw_p = q.sitd->hw_next;
 				else
-					*hw_p = ehci->dummy->qh_dma;
+					*hw_p = cpu_to_hc32(ehci,
+							ehci->dummy->qh_dma);
 				type = Q_NEXT_TYPE(ehci, q.sitd->hw_next);
 				wmb();
 				modified = sitd_complete (ehci, q.sitd);
diff --git a/drivers/usb/host/ehci-sead3.c b/drivers/usb/host/ehci-sead3.c
index b2de52d..8a73449 100644
--- a/drivers/usb/host/ehci-sead3.c
+++ b/drivers/usb/host/ehci-sead3.c
@@ -55,7 +55,7 @@
 	 * generic hardware linkage
 	 */
 	.irq			= ehci_irq,
-	.flags			= HCD_MEMORY | HCD_USB2,
+	.flags			= HCD_MEMORY | HCD_USB2 | HCD_BH,
 
 	/*
 	 * basic lifecycle operations
diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c
index 93e59a1..dc899eb 100644
--- a/drivers/usb/host/ehci-sh.c
+++ b/drivers/usb/host/ehci-sh.c
@@ -36,7 +36,7 @@
 	 * generic hardware linkage
 	 */
 	.irq				= ehci_irq,
-	.flags				= HCD_USB2 | HCD_MEMORY,
+	.flags				= HCD_USB2 | HCD_MEMORY | HCD_BH,
 
 	/*
 	 * basic lifecycle operations
diff --git a/drivers/usb/host/ehci-sysfs.c b/drivers/usb/host/ehci-sysfs.c
index 14ced00..f6459df 100644
--- a/drivers/usb/host/ehci-sysfs.c
+++ b/drivers/usb/host/ehci-sysfs.c
@@ -97,8 +97,7 @@
 {
 	struct ehci_hcd		*ehci;
 	unsigned		uframe_periodic_max;
-	unsigned		frame, uframe;
-	unsigned short		allocated_max;
+	unsigned		uframe;
 	unsigned long		flags;
 	ssize_t			ret;
 
@@ -122,16 +121,14 @@
 
 	/*
 	 * for request to decrease max periodic bandwidth, we have to check
-	 * every microframe in the schedule to see whether the decrease is
-	 * possible.
+	 * to see whether the decrease is possible.
 	 */
 	if (uframe_periodic_max < ehci->uframe_periodic_max) {
-		allocated_max = 0;
+		u8		allocated_max = 0;
 
-		for (frame = 0; frame < ehci->periodic_size; ++frame)
-			for (uframe = 0; uframe < 7; ++uframe)
-				allocated_max = max(allocated_max,
-						    periodic_usecs (ehci, frame, uframe));
+		for (uframe = 0; uframe < EHCI_BANDWIDTH_SIZE; ++uframe)
+			allocated_max = max(allocated_max,
+					ehci->bandwidth[uframe]);
 
 		if (allocated_max > uframe_periodic_max) {
 			ehci_info(ehci,
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 78fa76d..e6d8e26 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -388,7 +388,7 @@
 
 	err = clk_prepare_enable(tegra->clk);
 	if (err)
-		goto cleanup_clk_get;
+		goto cleanup_hcd_create;
 
 	tegra_periph_reset_assert(tegra->clk);
 	udelay(1);
@@ -465,8 +465,6 @@
 	usb_phy_shutdown(hcd->phy);
 cleanup_clk_en:
 	clk_disable_unprepare(tegra->clk);
-cleanup_clk_get:
-	clk_put(tegra->clk);
 cleanup_hcd_create:
 	usb_put_hcd(hcd);
 	return err;
diff --git a/drivers/usb/host/ehci-tilegx.c b/drivers/usb/host/ehci-tilegx.c
index cca4be9..67026ff 100644
--- a/drivers/usb/host/ehci-tilegx.c
+++ b/drivers/usb/host/ehci-tilegx.c
@@ -61,7 +61,7 @@
 	 * Generic hardware linkage.
 	 */
 	.irq			= ehci_irq,
-	.flags			= HCD_MEMORY | HCD_USB2,
+	.flags			= HCD_MEMORY | HCD_USB2 | HCD_BH,
 
 	/*
 	 * Basic lifecycle operations.
diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c
index 59e0e24..cdad843 100644
--- a/drivers/usb/host/ehci-w90x900.c
+++ b/drivers/usb/host/ehci-w90x900.c
@@ -11,13 +11,28 @@
  *
  */
 
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ehci.h"
 
 /* enable phy0 and phy1 for w90p910 */
 #define	ENPHY		(0x01<<8)
 #define PHY0_CTR	(0xA4)
 #define PHY1_CTR	(0xA8)
 
+#define DRIVER_DESC "EHCI w90x900 driver"
+
+static const char hcd_name[] = "ehci-w90x900 ";
+
+static struct hc_driver __read_mostly ehci_w90x900_hc_driver;
+
 static int usb_w90x900_probe(const struct hc_driver *driver,
 		      struct platform_device *pdev)
 {
@@ -90,8 +105,8 @@
 	return retval;
 }
 
-static
-void usb_w90x900_remove(struct usb_hcd *hcd, struct platform_device *pdev)
+static void usb_w90x900_remove(struct usb_hcd *hcd,
+			struct platform_device *pdev)
 {
 	usb_remove_hcd(hcd);
 	iounmap(hcd->regs);
@@ -99,54 +114,6 @@
 	usb_put_hcd(hcd);
 }
 
-static const struct hc_driver ehci_w90x900_hc_driver = {
-	.description = hcd_name,
-	.product_desc = "Nuvoton w90x900 EHCI Host Controller",
-	.hcd_priv_size = sizeof(struct ehci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq = ehci_irq,
-	.flags = HCD_USB2|HCD_MEMORY,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.reset = ehci_setup,
-	.start = ehci_run,
-
-	.stop = ehci_stop,
-	.shutdown = ehci_shutdown,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue = ehci_urb_enqueue,
-	.urb_dequeue = ehci_urb_dequeue,
-	.endpoint_disable = ehci_endpoint_disable,
-	.endpoint_reset = ehci_endpoint_reset,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number = ehci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data = ehci_hub_status_data,
-	.hub_control = ehci_hub_control,
-#ifdef	CONFIG_PM
-	.bus_suspend = ehci_bus_suspend,
-	.bus_resume = ehci_bus_resume,
-#endif
-	.relinquish_port	= ehci_relinquish_port,
-	.port_handed_over	= ehci_port_handed_over,
-
-	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
 static int ehci_w90x900_probe(struct platform_device *pdev)
 {
 	if (usb_disabled())
@@ -173,7 +140,25 @@
 	},
 };
 
+static int __init ehci_w90X900_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+	ehci_init_driver(&ehci_w90x900_hc_driver, NULL);
+	return platform_driver_register(&ehci_hcd_w90x900_driver);
+}
+module_init(ehci_w90X900_init);
+
+static void __exit ehci_w90X900_cleanup(void)
+{
+	platform_driver_unregister(&ehci_hcd_w90x900_driver);
+}
+module_exit(ehci_w90X900_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
-MODULE_DESCRIPTION("w90p910 usb ehci driver!");
-MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:w90p910-ehci");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c
index eba962e..95979f9 100644
--- a/drivers/usb/host/ehci-xilinx-of.c
+++ b/drivers/usb/host/ehci-xilinx-of.c
@@ -79,7 +79,7 @@
 	 * generic hardware linkage
 	 */
 	.irq			= ehci_irq,
-	.flags			= HCD_MEMORY | HCD_USB2,
+	.flags			= HCD_MEMORY | HCD_USB2 | HCD_BH,
 
 	/*
 	 * basic lifecycle operations
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 291db7d..e8f41c5 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -54,6 +54,28 @@
 	unsigned long		unlink;
 };
 
+/*
+ * Scheduling and budgeting information for periodic transfers, for both
+ * high-speed devices and full/low-speed devices lying behind a TT.
+ */
+struct ehci_per_sched {
+	struct usb_device	*udev;		/* access to the TT */
+	struct usb_host_endpoint *ep;
+	struct list_head	ps_list;	/* node on ehci_tt's ps_list */
+	u16			tt_usecs;	/* time on the FS/LS bus */
+	u16			cs_mask;	/* C-mask and S-mask bytes */
+	u16			period;		/* actual period in frames */
+	u16			phase;		/* actual phase, frame part */
+	u8			bw_phase;	/* same, for bandwidth
+						   reservation */
+	u8			phase_uf;	/* uframe part of the phase */
+	u8			usecs, c_usecs;	/* times on the HS bus */
+	u8			bw_uperiod;	/* period in microframes, for
+						   bandwidth reservation */
+	u8			bw_period;	/* same, in frames */
+};
+#define NO_FRAME	29999			/* frame not assigned yet */
+
 /* ehci_hcd->lock guards shared data against other CPUs:
  *   ehci_hcd:	async, unlink, periodic (and shadow), ...
  *   usb_host_endpoint: hcpriv
@@ -230,6 +252,15 @@
 	struct dentry		*debug_dir;
 #endif
 
+	/* bandwidth usage */
+#define EHCI_BANDWIDTH_SIZE	64
+#define EHCI_BANDWIDTH_FRAMES	(EHCI_BANDWIDTH_SIZE >> 3)
+	u8			bandwidth[EHCI_BANDWIDTH_SIZE];
+						/* us allocated per uframe */
+	u8			tt_budget[EHCI_BANDWIDTH_SIZE];
+						/* us budgeted per uframe */
+	struct list_head	tt_list;
+
 	/* platform-specific data -- must come last */
 	unsigned long		priv[0] __aligned(sizeof(s64));
 };
@@ -385,6 +416,7 @@
 	struct list_head	intr_node;	/* list of intr QHs */
 	struct ehci_qtd		*dummy;
 	struct list_head	unlink_node;
+	struct ehci_per_sched	ps;		/* scheduling info */
 
 	unsigned		unlink_cycle;
 
@@ -398,16 +430,8 @@
 	u8			xacterrs;	/* XactErr retry counter */
 #define	QH_XACTERR_MAX		32		/* XactErr retry limit */
 
-	/* periodic schedule info */
-	u8			usecs;		/* intr bandwidth */
 	u8			gap_uf;		/* uframes split/csplit gap */
-	u8			c_usecs;	/* ... split completion bw */
-	u16			tt_usecs;	/* tt downstream bandwidth */
-	unsigned short		period;		/* polling interval */
-	unsigned short		start;		/* where polling starts */
-#define NO_FRAME ((unsigned short)~0)			/* pick new start */
 
-	struct usb_device	*dev;		/* access to TT */
 	unsigned		is_out:1;	/* bulk or intr OUT */
 	unsigned		clearing_tt:1;	/* Clear-TT-Buf in progress */
 	unsigned		dequeue_during_giveback:1;
@@ -434,6 +458,7 @@
 struct ehci_iso_sched {
 	struct list_head	td_list;
 	unsigned		span;
+	unsigned		first_packet;
 	struct ehci_iso_packet	packet [0];
 };
 
@@ -449,22 +474,17 @@
 	u8			highspeed;
 	struct list_head	td_list;	/* queued itds/sitds */
 	struct list_head	free_list;	/* list of unused itds/sitds */
-	struct usb_device	*udev;
-	struct usb_host_endpoint *ep;
 
 	/* output of (re)scheduling */
-	int			next_uframe;
+	struct ehci_per_sched	ps;		/* scheduling info */
+	unsigned		next_uframe;
 	__hc32			splits;
 
 	/* the rest is derived from the endpoint descriptor,
-	 * trusting urb->interval == f(epdesc->bInterval) and
 	 * including the extra info for hw_bufp[0..2]
 	 */
-	u8			usecs, c_usecs;
-	u16			interval;
-	u16			tt_usecs;
+	u16			uperiod;	/* period in uframes */
 	u16			maxp;
-	u16			raw_mask;
 	unsigned		bandwidth;
 
 	/* This is used to initialize iTD's hw_bufp fields */
@@ -579,6 +599,35 @@
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * USB-2.0 Specification Sections 11.14 and 11.18
+ * Scheduling and budgeting split transactions using TTs
+ *
+ * A hub can have a single TT for all its ports, or multiple TTs (one for each
+ * port).  The bandwidth and budgeting information for the full/low-speed bus
+ * below each TT is self-contained and independent of the other TTs or the
+ * high-speed bus.
+ *
+ * "Bandwidth" refers to the number of microseconds on the FS/LS bus allocated
+ * to an interrupt or isochronous endpoint for each frame.  "Budget" refers to
+ * the best-case estimate of the number of full-speed bytes allocated to an
+ * endpoint for each microframe within an allocated frame.
+ *
+ * Removal of an endpoint invalidates a TT's budget.  Instead of trying to
+ * keep an up-to-date record, we recompute the budget when it is needed.
+ */
+
+struct ehci_tt {
+	u16			bandwidth[EHCI_BANDWIDTH_FRAMES];
+
+	struct list_head	tt_list;	/* List of all ehci_tt's */
+	struct list_head	ps_list;	/* Items using this TT */
+	struct usb_tt		*usb_tt;
+	int			tt_port;	/* TT port number */
+};
+
+/*-------------------------------------------------------------------------*/
+
 /* Prepare the PORTSC wakeup flags during controller suspend/resume */
 
 #define ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup)	\
diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c
index 0b4654259..0551c0a 100644
--- a/drivers/usb/host/fhci-hcd.c
+++ b/drivers/usb/host/fhci-hcd.c
@@ -26,6 +26,8 @@
 #include <linux/io.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
 #include <linux/slab.h>
diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c
index fce13bc..55486bd 100644
--- a/drivers/usb/host/fotg210-hcd.c
+++ b/drivers/usb/host/fotg210-hcd.c
@@ -412,7 +412,7 @@
 			tmp = 'h'; break; \
 		default:		\
 			tmp = '?'; break; \
-		}; tmp; })
+		} tmp; })
 
 static inline char token_mark(struct fotg210_hcd *fotg210, __hc32 token)
 {
diff --git a/drivers/usb/host/fusbh200-hcd.c b/drivers/usb/host/fusbh200-hcd.c
index 299253c..e1c6d85 100644
--- a/drivers/usb/host/fusbh200-hcd.c
+++ b/drivers/usb/host/fusbh200-hcd.c
@@ -402,7 +402,7 @@
 		case QH_LOW_SPEED:  tmp = 'l'; break; \
 		case QH_HIGH_SPEED: tmp = 'h'; break; \
 		default: tmp = '?'; break; \
-		}; tmp; })
+		} tmp; })
 
 static inline char token_mark(struct fusbh200_hcd *fusbh200, __hc32 token)
 {
diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c
index 5b86ffb..ada0a52 100644
--- a/drivers/usb/host/hwa-hc.c
+++ b/drivers/usb/host/hwa-hc.c
@@ -199,10 +199,14 @@
 {
 	struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd);
 	struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc);
+	struct wahc *wa = &hwahc->wa;
 
-	dev_err(wusbhc->dev, "%s (%p [%p]) UNIMPLEMENTED\n", __func__,
-		usb_hcd, hwahc);
-	return -ENOSYS;
+	/*
+	 * We cannot query the HWA for the WUSB time since that requires sending
+	 * a synchronous URB and this function can be called in_interrupt.
+	 * Instead, query the USB frame number for our parent and use that.
+	 */
+	return usb_get_current_frame_number(wa->usb_dev);
 }
 
 static int hwahc_op_urb_enqueue(struct usb_hcd *usb_hcd, struct urb *urb,
@@ -566,14 +570,10 @@
 		goto error;
 	}
 	wa->wa_descr = wa_descr = (struct usb_wa_descriptor *) hdr;
-	/* Make LE fields CPU order */
-	wa_descr->bcdWAVersion = le16_to_cpu(wa_descr->bcdWAVersion);
-	wa_descr->wNumRPipes = le16_to_cpu(wa_descr->wNumRPipes);
-	wa_descr->wRPipeMaxBlock = le16_to_cpu(wa_descr->wRPipeMaxBlock);
-	if (wa_descr->bcdWAVersion > 0x0100)
+	if (le16_to_cpu(wa_descr->bcdWAVersion) > 0x0100)
 		dev_warn(dev, "Wire Adapter v%d.%d newer than groked v1.0\n",
-			 wa_descr->bcdWAVersion & 0xff00 >> 8,
-			 wa_descr->bcdWAVersion & 0x00ff);
+			 le16_to_cpu(wa_descr->bcdWAVersion) & 0xff00 >> 8,
+			 le16_to_cpu(wa_descr->bcdWAVersion) & 0x00ff);
 	result = 0;
 error:
 	return result;
@@ -679,7 +679,8 @@
 	/* nothing to do here so far... */
 }
 
-static int hwahc_create(struct hwahc *hwahc, struct usb_interface *iface)
+static int hwahc_create(struct hwahc *hwahc, struct usb_interface *iface,
+	kernel_ulong_t quirks)
 {
 	int result;
 	struct device *dev = &iface->dev;
@@ -724,7 +725,7 @@
 		dev_err(dev, "Can't create WUSB HC structures: %d\n", result);
 		goto error_wusbhc_create;
 	}
-	result = wa_create(&hwahc->wa, iface);
+	result = wa_create(&hwahc->wa, iface, quirks);
 	if (result < 0)
 		goto error_wa_create;
 	return 0;
@@ -780,7 +781,7 @@
 	wusbhc = usb_hcd_to_wusbhc(usb_hcd);
 	hwahc = container_of(wusbhc, struct hwahc, wusbhc);
 	hwahc_init(hwahc);
-	result = hwahc_create(hwahc, usb_iface);
+	result = hwahc_create(hwahc, usb_iface, id->driver_info);
 	if (result < 0) {
 		dev_err(dev, "Cannot initialize internals: %d\n", result);
 		goto error_hwahc_create;
@@ -824,6 +825,12 @@
 }
 
 static struct usb_device_id hwahc_id_table[] = {
+	/* Alereon 5310 */
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x13dc, 0x5310, 0xe0, 0x02, 0x01),
+	  .driver_info = WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC },
+	/* Alereon 5611 */
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x13dc, 0x5611, 0xe0, 0x02, 0x01),
+	  .driver_info = WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC },
 	/* FIXME: use class labels for this */
 	{ USB_INTERFACE_INFO(0xe0, 0x02, 0x01), },
 	{},
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index 6f29aba..935a2dd 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -2108,7 +2108,7 @@
 				   default:
 					   s = "?";
 					   break;
-				   };
+				   }
 				   s;}), ep->maxpacket) ;
 		list_for_each_entry(urb, &ep->hep->urb_list, urb_list) {
 			seq_printf(s, "  urb%p, %d/%d\n", urb,
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index caa3764..476b5a5 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -13,19 +13,24 @@
  */
 
 #include <linux/clk.h>
-#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
+#include <linux/platform_device.h>
 #include <linux/platform_data/atmel.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
 
 #include <mach/hardware.h>
 #include <asm/gpio.h>
 
 #include <mach/cpu.h>
 
-#ifndef CONFIG_ARCH_AT91
-#error "CONFIG_ARCH_AT91 must be defined."
-#endif
+
+#include "ohci.h"
 
 #define valid_port(index)	((index) >= 0 && (index) < AT91_MAX_USBH_PORTS)
 #define at91_for_each_port(index)	\
@@ -33,7 +38,17 @@
 
 /* interface, function and usb clocks; sometimes also an AHB clock */
 static struct clk *iclk, *fclk, *uclk, *hclk;
+/* interface and function clocks; sometimes also an AHB clock */
+
+#define DRIVER_DESC "OHCI Atmel driver"
+
+static const char hcd_name[] = "ohci-atmel";
+
+static struct hc_driver __read_mostly ohci_at91_hc_driver;
 static int clocked;
+static int (*orig_ohci_hub_control)(struct usb_hcd  *hcd, u16 typeReq,
+			u16 wValue, u16 wIndex, char *buf, u16 wLength);
+static int (*orig_ohci_hub_status_data)(struct usb_hcd *hcd, char *buf);
 
 extern int usb_disabled(void);
 
@@ -117,6 +132,8 @@
 static int usb_hcd_at91_probe(const struct hc_driver *driver,
 			struct platform_device *pdev)
 {
+	struct at91_usbh_data *board;
+	struct ohci_hcd *ohci;
 	int retval;
 	struct usb_hcd *hcd = NULL;
 
@@ -177,8 +194,10 @@
 		}
 	}
 
+	board = hcd->self.controller->platform_data;
+	ohci = hcd_to_ohci(hcd);
+	ohci->num_ports = board->ports;
 	at91_start_hc(pdev);
-	ohci_hcd_init(hcd_to_ohci(hcd));
 
 	retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED);
 	if (retval == 0)
@@ -238,36 +257,6 @@
 }
 
 /*-------------------------------------------------------------------------*/
-
-static int
-ohci_at91_reset (struct usb_hcd *hcd)
-{
-	struct at91_usbh_data	*board = dev_get_platdata(hcd->self.controller);
-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
-	int			ret;
-
-	if ((ret = ohci_init(ohci)) < 0)
-		return ret;
-
-	ohci->num_ports = board->ports;
-	return 0;
-}
-
-static int
-ohci_at91_start (struct usb_hcd *hcd)
-{
-	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
-	int			ret;
-
-	if ((ret = ohci_run(ohci)) < 0) {
-		dev_err(hcd->self.controller, "can't start %s\n",
-			hcd->self.bus_name);
-		ohci_stop(hcd);
-		return ret;
-	}
-	return 0;
-}
-
 static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int enable)
 {
 	if (!valid_port(port))
@@ -297,8 +286,8 @@
  */
 static int ohci_at91_hub_status_data(struct usb_hcd *hcd, char *buf)
 {
-	struct at91_usbh_data *pdata = dev_get_platdata(hcd->self.controller);
-	int length = ohci_hub_status_data(hcd, buf);
+	struct at91_usbh_data *pdata = hcd->self.controller->platform_data;
+	int length = orig_ohci_hub_status_data(hcd, buf);
 	int port;
 
 	at91_for_each_port(port) {
@@ -376,7 +365,8 @@
 		break;
 	}
 
-	ret = ohci_hub_control(hcd, typeReq, wValue, wIndex + 1, buf, wLength);
+	ret = orig_ohci_hub_control(hcd, typeReq, wValue, wIndex + 1,
+				buf, wLength);
 	if (ret)
 		goto out;
 
@@ -430,51 +420,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-static const struct hc_driver ohci_at91_hc_driver = {
-	.description =		hcd_name,
-	.product_desc =		"AT91 OHCI",
-	.hcd_priv_size =	sizeof(struct ohci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq =			ohci_irq,
-	.flags =		HCD_USB11 | HCD_MEMORY,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.reset =		ohci_at91_reset,
-	.start =		ohci_at91_start,
-	.stop =			ohci_stop,
-	.shutdown =		ohci_shutdown,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue =		ohci_urb_enqueue,
-	.urb_dequeue =		ohci_urb_dequeue,
-	.endpoint_disable =	ohci_endpoint_disable,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number =	ohci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data =	ohci_at91_hub_status_data,
-	.hub_control =		ohci_at91_hub_control,
-#ifdef CONFIG_PM
-	.bus_suspend =		ohci_bus_suspend,
-	.bus_resume =		ohci_bus_resume,
-#endif
-	.start_port_reset =	ohci_start_port_reset,
-};
-
-/*-------------------------------------------------------------------------*/
-
 static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data)
 {
 	struct platform_device *pdev = data;
@@ -703,7 +648,11 @@
 	 * REVISIT: some boards will be able to turn VBUS off...
 	 */
 	if (at91_suspend_entering_slow_clock()) {
-		ohci_usb_reset (ohci);
+		ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
+		ohci->hc_control &= OHCI_CTRL_RWC;
+		ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
+		ohci->rh_state = OHCI_RH_HALTED;
+
 		/* flush the writes */
 		(void) ohci_readl (ohci, &ohci->regs->control);
 		at91_stop_clock();
@@ -730,8 +679,6 @@
 #define ohci_hcd_at91_drv_resume  NULL
 #endif
 
-MODULE_ALIAS("platform:at91_ohci");
-
 static struct platform_driver ohci_hcd_at91_driver = {
 	.probe		= ohci_hcd_at91_drv_probe,
 	.remove		= ohci_hcd_at91_drv_remove,
@@ -744,3 +691,40 @@
 		.of_match_table	= of_match_ptr(at91_ohci_dt_ids),
 	},
 };
+
+static int __init ohci_at91_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+	ohci_init_driver(&ohci_at91_hc_driver, NULL);
+
+	/*
+	 * The Atmel HW has some unusual quirks, which require Atmel-specific
+	 * workarounds. We override certain hc_driver functions here to
+	 * achieve that. We explicitly do not enhance ohci_driver_overrides to
+	 * allow this more easily, since this is an unusual case, and we don't
+	 * want to encourage others to override these functions by making it
+	 * too easy.
+	 */
+
+	orig_ohci_hub_control = ohci_at91_hc_driver.hub_control;
+	orig_ohci_hub_status_data = ohci_at91_hc_driver.hub_status_data;
+
+	ohci_at91_hc_driver.hub_status_data	= ohci_at91_hub_status_data;
+	ohci_at91_hc_driver.hub_control		= ohci_at91_hub_control;
+
+	return platform_driver_register(&ohci_hcd_at91_driver);
+}
+module_init(ohci_at91_init);
+
+static void __exit ohci_at91_cleanup(void)
+{
+	platform_driver_unregister(&ohci_hcd_at91_driver);
+}
+module_exit(ohci_at91_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:at91_ohci");
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 31b81f9..3fca52e 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -17,7 +17,7 @@
 	case PIPE_BULK:		temp = "bulk"; break; \
 	case PIPE_INTERRUPT:	temp = "intr"; break; \
 	default:		temp = "isoc"; break; \
-	}; temp;})
+	} temp;})
 #define pipestring(pipe) edstring(usb_pipetype(pipe))
 
 /* debug| print the main components of an URB
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
deleted file mode 100644
index 84a20d5..0000000
--- a/drivers/usb/host/ohci-ep93xx.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- * (C) Copyright 2002 Hewlett-Packard Company
- *
- * Bus Glue for ep93xx.
- *
- * Written by Christopher Hoover <ch@hpl.hp.com>
- * Based on fragments of previous driver by Russell King et al.
- *
- * Modified for LH7A404 from ohci-sa1111.c
- *  by Durgesh Pattamatta <pattamattad@sharpsec.com>
- *
- * Modified for pxa27x from ohci-lh7a404.c
- *  by Nick Bane <nick@cecomputing.co.uk> 26-8-2004
- *
- * Modified for ep93xx from ohci-pxa27x.c
- *  by Lennert Buytenhek <buytenh@wantstofly.org> 28-2-2006
- *  Based on an earlier driver by Ray Lehtiniemi
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/signal.h>
-#include <linux/platform_device.h>
-
-static struct clk *usb_host_clock;
-
-static int ohci_ep93xx_start(struct usb_hcd *hcd)
-{
-	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-	int ret;
-
-	if ((ret = ohci_init(ohci)) < 0)
-		return ret;
-
-	if ((ret = ohci_run(ohci)) < 0) {
-		dev_err(hcd->self.controller, "can't start %s\n",
-			hcd->self.bus_name);
-		ohci_stop(hcd);
-		return ret;
-	}
-
-	return 0;
-}
-
-static struct hc_driver ohci_ep93xx_hc_driver = {
-	.description		= hcd_name,
-	.product_desc		= "EP93xx OHCI",
-	.hcd_priv_size		= sizeof(struct ohci_hcd),
-	.irq			= ohci_irq,
-	.flags			= HCD_USB11 | HCD_MEMORY,
-	.start			= ohci_ep93xx_start,
-	.stop			= ohci_stop,
-	.shutdown		= ohci_shutdown,
-	.urb_enqueue		= ohci_urb_enqueue,
-	.urb_dequeue		= ohci_urb_dequeue,
-	.endpoint_disable	= ohci_endpoint_disable,
-	.get_frame_number	= ohci_get_frame,
-	.hub_status_data	= ohci_hub_status_data,
-	.hub_control		= ohci_hub_control,
-#ifdef CONFIG_PM
-	.bus_suspend		= ohci_bus_suspend,
-	.bus_resume		= ohci_bus_resume,
-#endif
-	.start_port_reset	= ohci_start_port_reset,
-};
-
-static int ohci_hcd_ep93xx_drv_probe(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd;
-	struct resource *res;
-	int irq;
-	int ret;
-
-	if (usb_disabled())
-		return -ENODEV;
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENXIO;
-
-	hcd = usb_create_hcd(&ohci_ep93xx_hc_driver, &pdev->dev, "ep93xx");
-	if (!hcd)
-		return -ENOMEM;
-
-	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = resource_size(res);
-
-	hcd->regs = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(hcd->regs)) {
-		ret = PTR_ERR(hcd->regs);
-		goto err_put_hcd;
-	}
-
-	usb_host_clock = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(usb_host_clock)) {
-		ret = PTR_ERR(usb_host_clock);
-		goto err_put_hcd;
-	}
-
-	clk_enable(usb_host_clock);
-
-	ohci_hcd_init(hcd_to_ohci(hcd));
-
-	ret = usb_add_hcd(hcd, irq, 0);
-	if (ret)
-		goto err_clk_disable;
-
-	return 0;
-
-err_clk_disable:
-	clk_disable(usb_host_clock);
-err_put_hcd:
-	usb_put_hcd(hcd);
-
-	return ret;
-}
-
-static int ohci_hcd_ep93xx_drv_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-	usb_remove_hcd(hcd);
-	clk_disable(usb_host_clock);
-	usb_put_hcd(hcd);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int ohci_hcd_ep93xx_drv_suspend(struct platform_device *pdev, pm_message_t state)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-
-	if (time_before(jiffies, ohci->next_statechange))
-		msleep(5);
-	ohci->next_statechange = jiffies;
-
-	clk_disable(usb_host_clock);
-	return 0;
-}
-
-static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-
-	if (time_before(jiffies, ohci->next_statechange))
-		msleep(5);
-	ohci->next_statechange = jiffies;
-
-	clk_enable(usb_host_clock);
-
-	ohci_resume(hcd, false);
-	return 0;
-}
-#endif
-
-
-static struct platform_driver ohci_hcd_ep93xx_driver = {
-	.probe		= ohci_hcd_ep93xx_drv_probe,
-	.remove		= ohci_hcd_ep93xx_drv_remove,
-	.shutdown	= usb_hcd_platform_shutdown,
-#ifdef CONFIG_PM
-	.suspend	= ohci_hcd_ep93xx_drv_suspend,
-	.resume		= ohci_hcd_ep93xx_drv_resume,
-#endif
-	.driver		= {
-		.name	= "ep93xx-ohci",
-		.owner	= THIS_MODULE,
-	},
-};
-
-MODULE_ALIAS("platform:ep93xx-ohci");
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index dc6ee9a..a87baed 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -12,98 +12,55 @@
  */
 
 #include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
-#include <linux/platform_data/usb-ohci-exynos.h>
 #include <linux/usb/phy.h>
 #include <linux/usb/samsung_usb_phy.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/otg.h>
+
+#include "ohci.h"
+
+#define DRIVER_DESC "OHCI EXYNOS driver"
+
+static const char hcd_name[] = "ohci-exynos";
+static struct hc_driver __read_mostly exynos_ohci_hc_driver;
+
+#define to_exynos_ohci(hcd) (struct exynos_ohci_hcd *)(hcd_to_ohci(hcd)->priv)
 
 struct exynos_ohci_hcd {
-	struct device *dev;
-	struct usb_hcd *hcd;
 	struct clk *clk;
 	struct usb_phy *phy;
 	struct usb_otg *otg;
-	struct exynos4_ohci_platdata *pdata;
 };
 
-static void exynos_ohci_phy_enable(struct exynos_ohci_hcd *exynos_ohci)
+static void exynos_ohci_phy_enable(struct platform_device *pdev)
 {
-	struct platform_device *pdev = to_platform_device(exynos_ohci->dev);
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
 
 	if (exynos_ohci->phy)
 		usb_phy_init(exynos_ohci->phy);
-	else if (exynos_ohci->pdata && exynos_ohci->pdata->phy_init)
-		exynos_ohci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);
 }
 
-static void exynos_ohci_phy_disable(struct exynos_ohci_hcd *exynos_ohci)
+static void exynos_ohci_phy_disable(struct platform_device *pdev)
 {
-	struct platform_device *pdev = to_platform_device(exynos_ohci->dev);
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
 
 	if (exynos_ohci->phy)
 		usb_phy_shutdown(exynos_ohci->phy);
-	else if (exynos_ohci->pdata && exynos_ohci->pdata->phy_exit)
-		exynos_ohci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
 }
 
-static int ohci_exynos_reset(struct usb_hcd *hcd)
-{
-	return ohci_init(hcd_to_ohci(hcd));
-}
-
-static int ohci_exynos_start(struct usb_hcd *hcd)
-{
-	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-	int ret;
-
-	ohci_dbg(ohci, "ohci_exynos_start, ohci:%p", ohci);
-
-	ret = ohci_run(ohci);
-	if (ret < 0) {
-		dev_err(hcd->self.controller, "can't start %s\n",
-			hcd->self.bus_name);
-		ohci_stop(hcd);
-		return ret;
-	}
-
-	return 0;
-}
-
-static const struct hc_driver exynos_ohci_hc_driver = {
-	.description		= hcd_name,
-	.product_desc		= "EXYNOS OHCI Host Controller",
-	.hcd_priv_size		= sizeof(struct ohci_hcd),
-
-	.irq			= ohci_irq,
-	.flags			= HCD_MEMORY|HCD_USB11,
-
-	.reset			= ohci_exynos_reset,
-	.start			= ohci_exynos_start,
-	.stop			= ohci_stop,
-	.shutdown		= ohci_shutdown,
-
-	.get_frame_number	= ohci_get_frame,
-
-	.urb_enqueue		= ohci_urb_enqueue,
-	.urb_dequeue		= ohci_urb_dequeue,
-	.endpoint_disable	= ohci_endpoint_disable,
-
-	.hub_status_data	= ohci_hub_status_data,
-	.hub_control		= ohci_hub_control,
-#ifdef	CONFIG_PM
-	.bus_suspend		= ohci_bus_suspend,
-	.bus_resume		= ohci_bus_resume,
-#endif
-	.start_port_reset	= ohci_start_port_reset,
-};
-
 static int exynos_ohci_probe(struct platform_device *pdev)
 {
-	struct exynos4_ohci_platdata *pdata = dev_get_platdata(&pdev->dev);
 	struct exynos_ohci_hcd *exynos_ohci;
 	struct usb_hcd *hcd;
-	struct ohci_hcd *ohci;
 	struct resource *res;
 	struct usb_phy *phy;
 	int irq;
@@ -119,10 +76,14 @@
 	if (!pdev->dev.coherent_dma_mask)
 		pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 
-	exynos_ohci = devm_kzalloc(&pdev->dev, sizeof(struct exynos_ohci_hcd),
-					GFP_KERNEL);
-	if (!exynos_ohci)
+	hcd = usb_create_hcd(&exynos_ohci_hc_driver,
+				&pdev->dev, dev_name(&pdev->dev));
+	if (!hcd) {
+		dev_err(&pdev->dev, "Unable to create HCD\n");
 		return -ENOMEM;
+	}
+
+	exynos_ohci = to_exynos_ohci(hcd);
 
 	if (of_device_is_compatible(pdev->dev.of_node,
 					"samsung,exynos5440-ohci"))
@@ -130,30 +91,15 @@
 
 	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 	if (IS_ERR(phy)) {
-		/* Fallback to pdata */
-		if (!pdata) {
-			dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
-			return -EPROBE_DEFER;
-		} else {
-			exynos_ohci->pdata = pdata;
-		}
+		usb_put_hcd(hcd);
+		dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
+		return -EPROBE_DEFER;
 	} else {
 		exynos_ohci->phy = phy;
 		exynos_ohci->otg = phy->otg;
 	}
 
 skip_phy:
-
-	exynos_ohci->dev = &pdev->dev;
-
-	hcd = usb_create_hcd(&exynos_ohci_hc_driver, &pdev->dev,
-					dev_name(&pdev->dev));
-	if (!hcd) {
-		dev_err(&pdev->dev, "Unable to create HCD\n");
-		return -ENOMEM;
-	}
-
-	exynos_ohci->hcd = hcd;
 	exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost");
 
 	if (IS_ERR(exynos_ohci->clk)) {
@@ -190,26 +136,21 @@
 	}
 
 	if (exynos_ohci->otg)
-		exynos_ohci->otg->set_host(exynos_ohci->otg,
-					&exynos_ohci->hcd->self);
+		exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
 
-	exynos_ohci_phy_enable(exynos_ohci);
+	platform_set_drvdata(pdev, hcd);
 
-	ohci = hcd_to_ohci(hcd);
-	ohci_hcd_init(ohci);
+	exynos_ohci_phy_enable(pdev);
 
 	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	if (err) {
 		dev_err(&pdev->dev, "Failed to add USB HCD\n");
 		goto fail_add_hcd;
 	}
-
-	platform_set_drvdata(pdev, exynos_ohci);
-
 	return 0;
 
 fail_add_hcd:
-	exynos_ohci_phy_disable(exynos_ohci);
+	exynos_ohci_phy_disable(pdev);
 fail_io:
 	clk_disable_unprepare(exynos_ohci->clk);
 fail_clk:
@@ -219,16 +160,15 @@
 
 static int exynos_ohci_remove(struct platform_device *pdev)
 {
-	struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev);
-	struct usb_hcd *hcd = exynos_ohci->hcd;
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
 
 	usb_remove_hcd(hcd);
 
 	if (exynos_ohci->otg)
-		exynos_ohci->otg->set_host(exynos_ohci->otg,
-					&exynos_ohci->hcd->self);
+		exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
 
-	exynos_ohci_phy_disable(exynos_ohci);
+	exynos_ohci_phy_disable(pdev);
 
 	clk_disable_unprepare(exynos_ohci->clk);
 
@@ -239,8 +179,7 @@
 
 static void exynos_ohci_shutdown(struct platform_device *pdev)
 {
-	struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev);
-	struct usb_hcd *hcd = exynos_ohci->hcd;
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
 	if (hcd->driver->shutdown)
 		hcd->driver->shutdown(hcd);
@@ -249,9 +188,10 @@
 #ifdef CONFIG_PM
 static int exynos_ohci_suspend(struct device *dev)
 {
-	struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev);
-	struct usb_hcd *hcd = exynos_ohci->hcd;
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd);
 	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+	struct platform_device *pdev = to_platform_device(dev);
 	unsigned long flags;
 	int rc = 0;
 
@@ -271,10 +211,9 @@
 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 
 	if (exynos_ohci->otg)
-		exynos_ohci->otg->set_host(exynos_ohci->otg,
-					&exynos_ohci->hcd->self);
+		exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
 
-	exynos_ohci_phy_disable(exynos_ohci);
+	exynos_ohci_phy_disable(pdev);
 
 	clk_disable_unprepare(exynos_ohci->clk);
 
@@ -286,16 +225,16 @@
 
 static int exynos_ohci_resume(struct device *dev)
 {
-	struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev);
-	struct usb_hcd *hcd = exynos_ohci->hcd;
+	struct usb_hcd *hcd			= dev_get_drvdata(dev);
+	struct exynos_ohci_hcd *exynos_ohci	= to_exynos_ohci(hcd);
+	struct platform_device *pdev		= to_platform_device(dev);
 
 	clk_prepare_enable(exynos_ohci->clk);
 
 	if (exynos_ohci->otg)
-		exynos_ohci->otg->set_host(exynos_ohci->otg,
-					&exynos_ohci->hcd->self);
+		exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self);
 
-	exynos_ohci_phy_enable(exynos_ohci);
+	exynos_ohci_phy_enable(pdev);
 
 	ohci_resume(hcd, false);
 
@@ -306,6 +245,10 @@
 #define exynos_ohci_resume	NULL
 #endif
 
+static const struct ohci_driver_overrides exynos_overrides __initconst = {
+	.extra_priv_size =	sizeof(struct exynos_ohci_hcd),
+};
+
 static const struct dev_pm_ops exynos_ohci_pm_ops = {
 	.suspend	= exynos_ohci_suspend,
 	.resume		= exynos_ohci_resume,
@@ -331,6 +274,23 @@
 		.of_match_table	= of_match_ptr(exynos_ohci_match),
 	}
 };
+static int __init ohci_exynos_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+	ohci_init_driver(&exynos_ohci_hc_driver, &exynos_overrides);
+	return platform_driver_register(&exynos_ohci_driver);
+}
+module_init(ohci_exynos_init);
+
+static void __exit ohci_exynos_cleanup(void)
+{
+	platform_driver_unregister(&exynos_ohci_driver);
+}
+module_exit(ohci_exynos_cleanup);
 
 MODULE_ALIAS("platform:exynos-ohci");
 MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 604cad1..8ada13f 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -1161,10 +1161,12 @@
 	/* Copy the generic table to drv and then apply the overrides */
 	*drv = ohci_hc_driver;
 
-	drv->product_desc = over->product_desc;
-	drv->hcd_priv_size += over->extra_priv_size;
-	if (over->reset)
-		drv->reset = over->reset;
+	if (over) {
+		drv->product_desc = over->product_desc;
+		drv->hcd_priv_size += over->extra_priv_size;
+		if (over->reset)
+			drv->reset = over->reset;
+	}
 }
 EXPORT_SYMBOL_GPL(ohci_init_driver);
 
@@ -1179,46 +1181,6 @@
 #define SA1111_DRIVER		ohci_hcd_sa1111_driver
 #endif
 
-#if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S3C64XX)
-#include "ohci-s3c2410.c"
-#define S3C2410_PLATFORM_DRIVER	ohci_hcd_s3c2410_driver
-#endif
-
-#ifdef CONFIG_USB_OHCI_EXYNOS
-#include "ohci-exynos.c"
-#define EXYNOS_PLATFORM_DRIVER	exynos_ohci_driver
-#endif
-
-#ifdef CONFIG_USB_OHCI_HCD_OMAP1
-#include "ohci-omap.c"
-#define OMAP1_PLATFORM_DRIVER	ohci_hcd_omap_driver
-#endif
-
-#ifdef CONFIG_USB_OHCI_HCD_OMAP3
-#include "ohci-omap3.c"
-#define OMAP3_PLATFORM_DRIVER	ohci_hcd_omap3_driver
-#endif
-
-#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
-#include "ohci-pxa27x.c"
-#define PLATFORM_DRIVER		ohci_hcd_pxa27x_driver
-#endif
-
-#ifdef CONFIG_ARCH_EP93XX
-#include "ohci-ep93xx.c"
-#define EP93XX_PLATFORM_DRIVER	ohci_hcd_ep93xx_driver
-#endif
-
-#ifdef CONFIG_ARCH_AT91
-#include "ohci-at91.c"
-#define AT91_PLATFORM_DRIVER	ohci_hcd_at91_driver
-#endif
-
-#ifdef CONFIG_ARCH_LPC32XX
-#include "ohci-nxp.c"
-#define NXP_PLATFORM_DRIVER	usb_hcd_nxp_driver
-#endif
-
 #ifdef CONFIG_ARCH_DAVINCI_DA8XX
 #include "ohci-da8xx.c"
 #define DAVINCI_PLATFORM_DRIVER	ohci_hcd_da8xx_driver
@@ -1229,11 +1191,6 @@
 #define OF_PLATFORM_DRIVER	ohci_hcd_ppc_of_driver
 #endif
 
-#ifdef CONFIG_PLAT_SPEAR
-#include "ohci-spear.c"
-#define SPEAR_PLATFORM_DRIVER	spear_ohci_hcd_driver
-#endif
-
 #ifdef CONFIG_PPC_PS3
 #include "ohci-ps3.c"
 #define PS3_SYSTEM_BUS_DRIVER	ps3_ohci_driver
@@ -1296,18 +1253,6 @@
 		goto error_platform;
 #endif
 
-#ifdef OMAP1_PLATFORM_DRIVER
-	retval = platform_driver_register(&OMAP1_PLATFORM_DRIVER);
-	if (retval < 0)
-		goto error_omap1_platform;
-#endif
-
-#ifdef OMAP3_PLATFORM_DRIVER
-	retval = platform_driver_register(&OMAP3_PLATFORM_DRIVER);
-	if (retval < 0)
-		goto error_omap3_platform;
-#endif
-
 #ifdef OF_PLATFORM_DRIVER
 	retval = platform_driver_register(&OF_PLATFORM_DRIVER);
 	if (retval < 0)
@@ -1332,79 +1277,19 @@
 		goto error_tmio;
 #endif
 
-#ifdef S3C2410_PLATFORM_DRIVER
-	retval = platform_driver_register(&S3C2410_PLATFORM_DRIVER);
-	if (retval < 0)
-		goto error_s3c2410;
-#endif
-
-#ifdef EXYNOS_PLATFORM_DRIVER
-	retval = platform_driver_register(&EXYNOS_PLATFORM_DRIVER);
-	if (retval < 0)
-		goto error_exynos;
-#endif
-
-#ifdef EP93XX_PLATFORM_DRIVER
-	retval = platform_driver_register(&EP93XX_PLATFORM_DRIVER);
-	if (retval < 0)
-		goto error_ep93xx;
-#endif
-
-#ifdef AT91_PLATFORM_DRIVER
-	retval = platform_driver_register(&AT91_PLATFORM_DRIVER);
-	if (retval < 0)
-		goto error_at91;
-#endif
-
-#ifdef NXP_PLATFORM_DRIVER
-	retval = platform_driver_register(&NXP_PLATFORM_DRIVER);
-	if (retval < 0)
-		goto error_nxp;
-#endif
-
 #ifdef DAVINCI_PLATFORM_DRIVER
 	retval = platform_driver_register(&DAVINCI_PLATFORM_DRIVER);
 	if (retval < 0)
 		goto error_davinci;
 #endif
 
-#ifdef SPEAR_PLATFORM_DRIVER
-	retval = platform_driver_register(&SPEAR_PLATFORM_DRIVER);
-	if (retval < 0)
-		goto error_spear;
-#endif
-
 	return retval;
 
 	/* Error path */
-#ifdef SPEAR_PLATFORM_DRIVER
-	platform_driver_unregister(&SPEAR_PLATFORM_DRIVER);
- error_spear:
-#endif
 #ifdef DAVINCI_PLATFORM_DRIVER
 	platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER);
  error_davinci:
 #endif
-#ifdef NXP_PLATFORM_DRIVER
-	platform_driver_unregister(&NXP_PLATFORM_DRIVER);
- error_nxp:
-#endif
-#ifdef AT91_PLATFORM_DRIVER
-	platform_driver_unregister(&AT91_PLATFORM_DRIVER);
- error_at91:
-#endif
-#ifdef EP93XX_PLATFORM_DRIVER
-	platform_driver_unregister(&EP93XX_PLATFORM_DRIVER);
- error_ep93xx:
-#endif
-#ifdef EXYNOS_PLATFORM_DRIVER
-	platform_driver_unregister(&EXYNOS_PLATFORM_DRIVER);
- error_exynos:
-#endif
-#ifdef S3C2410_PLATFORM_DRIVER
-	platform_driver_unregister(&S3C2410_PLATFORM_DRIVER);
- error_s3c2410:
-#endif
 #ifdef TMIO_OHCI_DRIVER
 	platform_driver_unregister(&TMIO_OHCI_DRIVER);
  error_tmio:
@@ -1421,14 +1306,6 @@
 	platform_driver_unregister(&OF_PLATFORM_DRIVER);
  error_of_platform:
 #endif
-#ifdef OMAP3_PLATFORM_DRIVER
-	platform_driver_unregister(&OMAP3_PLATFORM_DRIVER);
- error_omap3_platform:
-#endif
-#ifdef OMAP1_PLATFORM_DRIVER
-	platform_driver_unregister(&OMAP1_PLATFORM_DRIVER);
- error_omap1_platform:
-#endif
 #ifdef PLATFORM_DRIVER
 	platform_driver_unregister(&PLATFORM_DRIVER);
  error_platform:
@@ -1450,27 +1327,9 @@
 
 static void __exit ohci_hcd_mod_exit(void)
 {
-#ifdef SPEAR_PLATFORM_DRIVER
-	platform_driver_unregister(&SPEAR_PLATFORM_DRIVER);
-#endif
 #ifdef DAVINCI_PLATFORM_DRIVER
 	platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER);
 #endif
-#ifdef NXP_PLATFORM_DRIVER
-	platform_driver_unregister(&NXP_PLATFORM_DRIVER);
-#endif
-#ifdef AT91_PLATFORM_DRIVER
-	platform_driver_unregister(&AT91_PLATFORM_DRIVER);
-#endif
-#ifdef EP93XX_PLATFORM_DRIVER
-	platform_driver_unregister(&EP93XX_PLATFORM_DRIVER);
-#endif
-#ifdef EXYNOS_PLATFORM_DRIVER
-	platform_driver_unregister(&EXYNOS_PLATFORM_DRIVER);
-#endif
-#ifdef S3C2410_PLATFORM_DRIVER
-	platform_driver_unregister(&S3C2410_PLATFORM_DRIVER);
-#endif
 #ifdef TMIO_OHCI_DRIVER
 	platform_driver_unregister(&TMIO_OHCI_DRIVER);
 #endif
@@ -1483,12 +1342,6 @@
 #ifdef OF_PLATFORM_DRIVER
 	platform_driver_unregister(&OF_PLATFORM_DRIVER);
 #endif
-#ifdef OMAP3_PLATFORM_DRIVER
-	platform_driver_unregister(&OMAP3_PLATFORM_DRIVER);
-#endif
-#ifdef OMAP1_PLATFORM_DRIVER
-	platform_driver_unregister(&OMAP1_PLATFORM_DRIVER);
-#endif
 #ifdef PLATFORM_DRIVER
 	platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 2347ab8..61705a7 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -212,10 +212,11 @@
 	/* Sometimes PCI D3 suspend trashes frame timings ... */
 	periodic_reinit (ohci);
 
-	/* the following code is executed with ohci->lock held and
-	 * irqs disabled if and only if autostopped is true
+	/*
+	 * The following code is executed with ohci->lock held and
+	 * irqs disabled if and only if autostopped is true.  This
+	 * will cause sparse to warn about a "context imbalance".
 	 */
-
 skip_resume:
 	/* interrupts might have been disabled */
 	ohci_writel (ohci, OHCI_INTR_INIT, &ohci->regs->intrenable);
@@ -531,7 +532,7 @@
 	    temp |= 0x0010;
 	else if (rh & RH_A_OCPM)	/* per-port overcurrent reporting? */
 	    temp |= 0x0008;
-	desc->wHubCharacteristics = (__force __u16)cpu_to_hc16(ohci, temp);
+	desc->wHubCharacteristics = cpu_to_le16(temp);
 
 	/* ports removable, and usb 1.0 legacy PortPwrCtrlMask */
 	rh = roothub_b (ohci);
diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c
index 7d7d507..9ab7e24 100644
--- a/drivers/usb/host/ohci-nxp.c
+++ b/drivers/usb/host/ohci-nxp.c
@@ -19,10 +19,19 @@
  * or implied.
  */
 #include <linux/clk.h>
-#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
 #include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/of.h>
+#include <linux/platform_device.h>
 #include <linux/usb/isp1301.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ohci.h"
+
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -57,6 +66,11 @@
 #define start_int_umask(irq)
 #endif
 
+#define DRIVER_DESC "OHCI NXP driver"
+
+static const char hcd_name[] = "ohci-nxp";
+static struct hc_driver __read_mostly ohci_nxp_hc_driver;
+
 static struct i2c_client *isp1301_i2c_client;
 
 extern int usb_disabled(void);
@@ -132,14 +146,14 @@
 		OTG1_VBUS_DRV);
 }
 
-static void nxp_start_hc(void)
+static void ohci_nxp_start_hc(void)
 {
 	unsigned long tmp = __raw_readl(USB_OTG_STAT_CONTROL) | HOST_EN;
 	__raw_writel(tmp, USB_OTG_STAT_CONTROL);
 	isp1301_vbus_on();
 }
 
-static void nxp_stop_hc(void)
+static void ohci_nxp_stop_hc(void)
 {
 	unsigned long tmp;
 	isp1301_vbus_off();
@@ -147,68 +161,9 @@
 	__raw_writel(tmp, USB_OTG_STAT_CONTROL);
 }
 
-static int ohci_nxp_start(struct usb_hcd *hcd)
-{
-	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-	int ret;
-
-	if ((ret = ohci_init(ohci)) < 0)
-		return ret;
-
-	if ((ret = ohci_run(ohci)) < 0) {
-		dev_err(hcd->self.controller, "can't start\n");
-		ohci_stop(hcd);
-		return ret;
-	}
-	return 0;
-}
-
-static const struct hc_driver ohci_nxp_hc_driver = {
-	.description = hcd_name,
-	.product_desc =		"nxp OHCI",
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq = ohci_irq,
-	.flags = HCD_USB11 | HCD_MEMORY,
-
-	.hcd_priv_size =	sizeof(struct ohci_hcd),
-	/*
-	 * basic lifecycle operations
-	 */
-	.start = ohci_nxp_start,
-	.stop = ohci_stop,
-	.shutdown = ohci_shutdown,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue = ohci_urb_enqueue,
-	.urb_dequeue = ohci_urb_dequeue,
-	.endpoint_disable = ohci_endpoint_disable,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number = ohci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data = ohci_hub_status_data,
-	.hub_control = ohci_hub_control,
-#ifdef	CONFIG_PM
-	.bus_suspend = ohci_bus_suspend,
-	.bus_resume = ohci_bus_resume,
-#endif
-	.start_port_reset = ohci_start_port_reset,
-};
-
-static int usb_hcd_nxp_probe(struct platform_device *pdev)
+static int ohci_hcd_nxp_probe(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = 0;
-	struct ohci_hcd *ohci;
 	const struct hc_driver *driver = &ohci_nxp_hc_driver;
 	struct resource *res;
 	int ret = 0, irq;
@@ -313,17 +268,15 @@
 		goto fail_resource;
 	}
 
-	nxp_start_hc();
+	ohci_nxp_start_hc();
 	platform_set_drvdata(pdev, hcd);
-	ohci = hcd_to_ohci(hcd);
-	ohci_hcd_init(ohci);
 
 	dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq);
 	ret = usb_add_hcd(hcd, irq, 0);
 	if (ret == 0)
 		return ret;
 
-	nxp_stop_hc();
+	ohci_nxp_stop_hc();
 fail_resource:
 	usb_put_hcd(hcd);
 fail_hcd:
@@ -345,12 +298,12 @@
 	return ret;
 }
 
-static int usb_hcd_nxp_remove(struct platform_device *pdev)
+static int ohci_hcd_nxp_remove(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
 	usb_remove_hcd(hcd);
-	nxp_stop_hc();
+	ohci_nxp_stop_hc();
 	usb_put_hcd(hcd);
 	clk_disable(usb_pll_clk);
 	clk_put(usb_pll_clk);
@@ -366,20 +319,40 @@
 MODULE_ALIAS("platform:usb-ohci");
 
 #ifdef CONFIG_OF
-static const struct of_device_id usb_hcd_nxp_match[] = {
+static const struct of_device_id ohci_hcd_nxp_match[] = {
 	{ .compatible = "nxp,ohci-nxp" },
 	{},
 };
-MODULE_DEVICE_TABLE(of, usb_hcd_nxp_match);
+MODULE_DEVICE_TABLE(of, ohci_hcd_nxp_match);
 #endif
 
-static struct platform_driver usb_hcd_nxp_driver = {
+static struct platform_driver ohci_hcd_nxp_driver = {
 	.driver = {
 		.name = "usb-ohci",
 		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(usb_hcd_nxp_match),
+		.of_match_table = of_match_ptr(ohci_hcd_nxp_match),
 	},
-	.probe = usb_hcd_nxp_probe,
-	.remove = usb_hcd_nxp_remove,
+	.probe = ohci_hcd_nxp_probe,
+	.remove = ohci_hcd_nxp_remove,
 };
 
+static int __init ohci_nxp_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+	ohci_init_driver(&ohci_nxp_hc_driver, NULL);
+	return platform_driver_register(&ohci_hcd_nxp_driver);
+}
+module_init(ohci_nxp_init);
+
+static void __exit ohci_nxp_cleanup(void)
+{
+	platform_driver_unregister(&ohci_hcd_nxp_driver);
+}
+module_exit(ohci_nxp_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 31d3a12..f253214 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -14,12 +14,21 @@
  * This file is licenced under the GPL.
  */
 
-#include <linux/signal.h>
-#include <linux/jiffies.h>
-#include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb/otg.h>
+#include <linux/platform_device.h>
+#include <linux/signal.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ohci.h"
 
 #include <asm/io.h>
 #include <asm/mach-types.h>
@@ -42,10 +51,7 @@
 #define OMAP1510_LB_MMU_RAM_H	0xfffec234
 #define OMAP1510_LB_MMU_RAM_L	0xfffec238
 
-
-#ifndef CONFIG_ARCH_OMAP
-#error "This file is OMAP bus glue.  CONFIG_OMAP must be defined."
-#endif
+#define DRIVER_DESC "OHCI OMAP driver"
 
 #ifdef CONFIG_TPS65010
 #include <linux/i2c/tps65010.h>
@@ -68,8 +74,9 @@
 
 static struct clk *usb_host_ck;
 static struct clk *usb_dc_ck;
-static int host_enabled;
-static int host_initialized;
+
+static const char hcd_name[] = "ohci-omap";
+static struct hc_driver __read_mostly ohci_omap_hc_driver;
 
 static void omap_ohci_clock_power(int on)
 {
@@ -188,7 +195,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int ohci_omap_init(struct usb_hcd *hcd)
+static int ohci_omap_reset(struct usb_hcd *hcd)
 {
 	struct ohci_hcd		*ohci = hcd_to_ohci(hcd);
 	struct omap_usb_config	*config = dev_get_platdata(hcd->self.controller);
@@ -198,9 +205,9 @@
 	dev_dbg(hcd->self.controller, "starting USB Controller\n");
 
 	if (config->otg) {
-		ohci_to_hcd(ohci)->self.otg_port = config->otg;
+		hcd->self.otg_port = config->otg;
 		/* default/minimum OTG power budget:  8 mA */
-		ohci_to_hcd(ohci)->power_budget = 8;
+		hcd->power_budget = 8;
 	}
 
 	/* boards can use OTG transceivers in non-OTG modes */
@@ -238,9 +245,15 @@
 		omap_1510_local_bus_init();
 	}
 
-	if ((ret = ohci_init(ohci)) < 0)
+	ret = ohci_setup(hcd);
+	if (ret < 0)
 		return ret;
 
+	if (config->otg || config->rwc) {
+		ohci->hc_control = OHCI_CTRL_RWC;
+		writel(OHCI_CTRL_RWC, &ohci->regs->control);
+	}
+
 	/* board-specific power switching and overcurrent support */
 	if (machine_is_omap_osk() || machine_is_omap_innovator()) {
 		u32	rh = roothub_a (ohci);
@@ -281,14 +294,6 @@
 	return 0;
 }
 
-static void ohci_omap_stop(struct usb_hcd *hcd)
-{
-	dev_dbg(hcd->self.controller, "stopping USB Controller\n");
-	ohci_stop(hcd);
-	omap_ohci_clock_power(0);
-}
-
-
 /*-------------------------------------------------------------------------*/
 
 /**
@@ -304,7 +309,6 @@
 {
 	int retval, irq;
 	struct usb_hcd *hcd = 0;
-	struct ohci_hcd *ohci;
 
 	if (pdev->num_resources != 2) {
 		printk(KERN_ERR "hcd probe: invalid num_resources: %i\n",
@@ -354,12 +358,6 @@
 		goto err2;
 	}
 
-	ohci = hcd_to_ohci(hcd);
-	ohci_hcd_init(ohci);
-
-	host_initialized = 0;
-	host_enabled = 1;
-
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 		retval = -ENXIO;
@@ -369,11 +367,6 @@
 	if (retval)
 		goto err3;
 
-	host_initialized = 1;
-
-	if (!host_enabled)
-		omap_ohci_clock_power(0);
-
 	return 0;
 err3:
 	iounmap(hcd->regs);
@@ -402,7 +395,9 @@
 static inline void
 usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
 {
+	dev_dbg(hcd->self.controller, "stopping USB Controller\n");
 	usb_remove_hcd(hcd);
+	omap_ohci_clock_power(0);
 	if (!IS_ERR_OR_NULL(hcd->phy)) {
 		(void) otg_set_host(hcd->phy->otg, 0);
 		usb_put_phy(hcd->phy);
@@ -418,76 +413,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int
-ohci_omap_start (struct usb_hcd *hcd)
-{
-	struct omap_usb_config *config;
-	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
-	int		ret;
-
-	if (!host_enabled)
-		return 0;
-	config = dev_get_platdata(hcd->self.controller);
-	if (config->otg || config->rwc) {
-		ohci->hc_control = OHCI_CTRL_RWC;
-		writel(OHCI_CTRL_RWC, &ohci->regs->control);
-	}
-
-	if ((ret = ohci_run (ohci)) < 0) {
-		dev_err(hcd->self.controller, "can't start\n");
-		ohci_stop (hcd);
-		return ret;
-	}
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static const struct hc_driver ohci_omap_hc_driver = {
-	.description =		hcd_name,
-	.product_desc =		"OMAP OHCI",
-	.hcd_priv_size =	sizeof(struct ohci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq =			ohci_irq,
-	.flags =		HCD_USB11 | HCD_MEMORY,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.reset =		ohci_omap_init,
-	.start =		ohci_omap_start,
-	.stop =			ohci_omap_stop,
-	.shutdown =		ohci_shutdown,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue =		ohci_urb_enqueue,
-	.urb_dequeue =		ohci_urb_dequeue,
-	.endpoint_disable =	ohci_endpoint_disable,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number =	ohci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data =	ohci_hub_status_data,
-	.hub_control =		ohci_hub_control,
-#ifdef	CONFIG_PM
-	.bus_suspend =		ohci_bus_suspend,
-	.bus_resume =		ohci_bus_resume,
-#endif
-	.start_port_reset =	ohci_start_port_reset,
-};
-
-/*-------------------------------------------------------------------------*/
-
 static int ohci_hcd_omap_drv_probe(struct platform_device *dev)
 {
 	return usb_hcd_omap_probe(&ohci_omap_hc_driver, dev);
@@ -506,16 +431,23 @@
 
 #ifdef	CONFIG_PM
 
-static int ohci_omap_suspend(struct platform_device *dev, pm_message_t message)
+static int ohci_omap_suspend(struct platform_device *pdev, pm_message_t message)
 {
-	struct ohci_hcd	*ohci = hcd_to_ohci(platform_get_drvdata(dev));
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+	bool do_wakeup = device_may_wakeup(&pdev->dev);
+	int ret;
 
 	if (time_before(jiffies, ohci->next_statechange))
 		msleep(5);
 	ohci->next_statechange = jiffies;
 
+	ret = ohci_suspend(hcd, do_wakeup);
+	if (ret)
+		return ret;
+
 	omap_ohci_clock_power(0);
-	return 0;
+	return ret;
 }
 
 static int ohci_omap_resume(struct platform_device *dev)
@@ -553,4 +485,29 @@
 	},
 };
 
+static const struct ohci_driver_overrides omap_overrides __initconst = {
+	.product_desc	= "OMAP OHCI",
+	.reset		= ohci_omap_reset
+};
+
+static int __init ohci_omap_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+	ohci_init_driver(&ohci_omap_hc_driver, &omap_overrides);
+	return platform_driver_register(&ohci_hcd_omap_driver);
+}
+module_init(ohci_omap_init);
+
+static void __exit ohci_omap_cleanup(void)
+{
+	platform_driver_unregister(&ohci_hcd_omap_driver);
+}
+module_exit(ohci_omap_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_ALIAS("platform:ohci");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
index a09af26..408d06a 100644
--- a/drivers/usb/host/ohci-omap3.c
+++ b/drivers/usb/host/ohci-omap3.c
@@ -29,90 +29,22 @@
  *	- add kernel-doc
  */
 
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/usb/otg.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
-#include <linux/of.h>
-#include <linux/dma-mapping.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
 
-/*-------------------------------------------------------------------------*/
+#include "ohci.h"
 
-static int ohci_omap3_init(struct usb_hcd *hcd)
-{
-	dev_dbg(hcd->self.controller, "starting OHCI controller\n");
+#define DRIVER_DESC "OHCI OMAP3 driver"
 
-	return ohci_init(hcd_to_ohci(hcd));
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int ohci_omap3_start(struct usb_hcd *hcd)
-{
-	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-	int ret;
-
-	/*
-	 * RemoteWakeupConnected has to be set explicitly before
-	 * calling ohci_run. The reset value of RWC is 0.
-	 */
-	ohci->hc_control = OHCI_CTRL_RWC;
-	writel(OHCI_CTRL_RWC, &ohci->regs->control);
-
-	ret = ohci_run(ohci);
-
-	if (ret < 0) {
-		dev_err(hcd->self.controller, "can't start\n");
-		ohci_stop(hcd);
-	}
-
-	return ret;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static const struct hc_driver ohci_omap3_hc_driver = {
-	.description =		hcd_name,
-	.product_desc =		"OMAP3 OHCI Host Controller",
-	.hcd_priv_size =	sizeof(struct ohci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq =			ohci_irq,
-	.flags =		HCD_USB11 | HCD_MEMORY,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.reset =		ohci_omap3_init,
-	.start =		ohci_omap3_start,
-	.stop =			ohci_stop,
-	.shutdown =		ohci_shutdown,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue =		ohci_urb_enqueue,
-	.urb_dequeue =		ohci_urb_dequeue,
-	.endpoint_disable =	ohci_endpoint_disable,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number =	ohci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data =	ohci_hub_status_data,
-	.hub_control =		ohci_hub_control,
-#ifdef	CONFIG_PM
-	.bus_suspend =		ohci_bus_suspend,
-	.bus_resume =		ohci_bus_resume,
-#endif
-	.start_port_reset =	ohci_start_port_reset,
-};
-
-/*-------------------------------------------------------------------------*/
+static const char hcd_name[] = "ohci-omap3";
+static struct hc_driver __read_mostly ohci_omap3_hc_driver;
 
 /*
  * configure so an HC device and id are always provided
@@ -129,6 +61,7 @@
 static int ohci_hcd_omap3_probe(struct platform_device *pdev)
 {
 	struct device		*dev = &pdev->dev;
+	struct ohci_hcd		*ohci;
 	struct usb_hcd		*hcd = NULL;
 	void __iomem		*regs = NULL;
 	struct resource		*res;
@@ -185,7 +118,12 @@
 	pm_runtime_enable(dev);
 	pm_runtime_get_sync(dev);
 
-	ohci_hcd_init(hcd_to_ohci(hcd));
+	ohci = hcd_to_ohci(hcd);
+	/*
+	 * RemoteWakeupConnected has to be set explicitly before
+	 * calling ohci_run. The reset value of RWC is 0.
+	 */
+	ohci->hc_control = OHCI_CTRL_RWC;
 
 	ret = usb_add_hcd(hcd, irq, 0);
 	if (ret) {
@@ -248,5 +186,25 @@
 	},
 };
 
+static int __init ohci_omap3_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+	ohci_init_driver(&ohci_omap3_hc_driver, NULL);
+	return platform_driver_register(&ohci_hcd_omap3_driver);
+}
+module_init(ohci_omap3_init);
+
+static void __exit ohci_omap3_cleanup(void)
+{
+	platform_driver_unregister(&ohci_hcd_omap3_driver);
+}
+module_exit(ohci_omap3_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_ALIAS("platform:ohci-omap3");
 MODULE_AUTHOR("Anand Gadiyar <gadiyar@ti.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index ec337c2..90879e9 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -150,28 +150,16 @@
 static int ohci_quirk_amd700(struct usb_hcd *hcd)
 {
 	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-	struct pci_dev *amd_smbus_dev;
-	u8 rev;
 
 	if (usb_amd_find_chipset_info())
 		ohci->flags |= OHCI_QUIRK_AMD_PLL;
 
-	amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI,
-			PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL);
-	if (!amd_smbus_dev)
-		return 0;
-
-	rev = amd_smbus_dev->revision;
-
 	/* SB800 needs pre-fetch fix */
-	if ((rev >= 0x40) && (rev <= 0x4f)) {
+	if (usb_amd_prefetch_quirk()) {
 		ohci->flags |= OHCI_QUIRK_AMD_PREFETCH;
 		ohci_dbg(ohci, "enabled AMD prefetch quirk\n");
 	}
 
-	pci_dev_put(amd_smbus_dev);
-	amd_smbus_dev = NULL;
-
 	return 0;
 }
 
@@ -323,3 +311,4 @@
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
+MODULE_SOFTDEP("pre: ehci_pci");
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index a4c6410..f351ff5 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -139,14 +139,21 @@
 
 static int ohci_platform_suspend(struct device *dev)
 {
-	struct usb_ohci_pdata *pdata = dev_get_platdata(dev);
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct usb_ohci_pdata *pdata = dev->platform_data;
 	struct platform_device *pdev =
 		container_of(dev, struct platform_device, dev);
+	bool do_wakeup = device_may_wakeup(dev);
+	int ret;
+
+	ret = ohci_suspend(hcd, do_wakeup);
+	if (ret)
+		return ret;
 
 	if (pdata->power_suspend)
 		pdata->power_suspend(pdev);
 
-	return 0;
+	return ret;
 }
 
 static int ohci_platform_resume(struct device *dev)
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
index 75f5a1e..81f3eba 100644
--- a/drivers/usb/host/ohci-ppc-of.c
+++ b/drivers/usb/host/ohci-ppc-of.c
@@ -14,6 +14,8 @@
  */
 
 #include <linux/signal.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
 #include <asm/prom.h>
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 93371a2..deea5d1 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -19,15 +19,26 @@
  * This file is licenced under the GPL.
  */
 
-#include <linux/device.h>
-#include <linux/signal.h>
-#include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/of_platform.h>
 #include <linux/of_gpio.h>
-#include <mach/hardware.h>
 #include <linux/platform_data/usb-ohci-pxa27x.h>
 #include <linux/platform_data/usb-pxa3xx-ulpi.h>
+#include <linux/platform_device.h>
+#include <linux/signal.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/otg.h>
+
+#include <mach/hardware.h>
+
+#include "ohci.h"
+
+#define DRIVER_DESC "OHCI PXA27x/PXA3x driver"
 
 /*
  * UHC: USB Host Controller (OHCI-like) register definitions
@@ -101,16 +112,16 @@
 
 #define PXA_UHC_MAX_PORTNUM    3
 
-struct pxa27x_ohci {
-	/* must be 1st member here for hcd_to_ohci() to work */
-	struct ohci_hcd ohci;
+static const char hcd_name[] = "ohci-pxa27x";
 
-	struct device	*dev;
+static struct hc_driver __read_mostly ohci_pxa27x_hc_driver;
+
+struct pxa27x_ohci {
 	struct clk	*clk;
 	void __iomem	*mmio_base;
 };
 
-#define to_pxa27x_ohci(hcd)	(struct pxa27x_ohci *)hcd_to_ohci(hcd)
+#define to_pxa27x_ohci(hcd)	(struct pxa27x_ohci *)(hcd_to_ohci(hcd)->priv)
 
 /*
   PMM_NPS_MODE -- PMM Non-power switching mode
@@ -122,10 +133,10 @@
   PMM_PERPORT_MODE -- PMM per port switching mode
       Ports are powered individually.
  */
-static int pxa27x_ohci_select_pmm(struct pxa27x_ohci *ohci, int mode)
+static int pxa27x_ohci_select_pmm(struct pxa27x_ohci *pxa_ohci, int mode)
 {
-	uint32_t uhcrhda = __raw_readl(ohci->mmio_base + UHCRHDA);
-	uint32_t uhcrhdb = __raw_readl(ohci->mmio_base + UHCRHDB);
+	uint32_t uhcrhda = __raw_readl(pxa_ohci->mmio_base + UHCRHDA);
+	uint32_t uhcrhdb = __raw_readl(pxa_ohci->mmio_base + UHCRHDB);
 
 	switch (mode) {
 	case PMM_NPS_MODE:
@@ -149,20 +160,18 @@
 		uhcrhda |= RH_A_NPS;
 	}
 
-	__raw_writel(uhcrhda, ohci->mmio_base + UHCRHDA);
-	__raw_writel(uhcrhdb, ohci->mmio_base + UHCRHDB);
+	__raw_writel(uhcrhda, pxa_ohci->mmio_base + UHCRHDA);
+	__raw_writel(uhcrhdb, pxa_ohci->mmio_base + UHCRHDB);
 	return 0;
 }
 
-extern int usb_disabled(void);
-
 /*-------------------------------------------------------------------------*/
 
-static inline void pxa27x_setup_hc(struct pxa27x_ohci *ohci,
+static inline void pxa27x_setup_hc(struct pxa27x_ohci *pxa_ohci,
 				   struct pxaohci_platform_data *inf)
 {
-	uint32_t uhchr = __raw_readl(ohci->mmio_base + UHCHR);
-	uint32_t uhcrhda = __raw_readl(ohci->mmio_base + UHCRHDA);
+	uint32_t uhchr = __raw_readl(pxa_ohci->mmio_base + UHCHR);
+	uint32_t uhcrhda = __raw_readl(pxa_ohci->mmio_base + UHCRHDA);
 
 	if (inf->flags & ENABLE_PORT1)
 		uhchr &= ~UHCHR_SSEP1;
@@ -194,17 +203,17 @@
 		uhcrhda |= UHCRHDA_POTPGT(inf->power_on_delay / 2);
 	}
 
-	__raw_writel(uhchr, ohci->mmio_base + UHCHR);
-	__raw_writel(uhcrhda, ohci->mmio_base + UHCRHDA);
+	__raw_writel(uhchr, pxa_ohci->mmio_base + UHCHR);
+	__raw_writel(uhcrhda, pxa_ohci->mmio_base + UHCRHDA);
 }
 
-static inline void pxa27x_reset_hc(struct pxa27x_ohci *ohci)
+static inline void pxa27x_reset_hc(struct pxa27x_ohci *pxa_ohci)
 {
-	uint32_t uhchr = __raw_readl(ohci->mmio_base + UHCHR);
+	uint32_t uhchr = __raw_readl(pxa_ohci->mmio_base + UHCHR);
 
-	__raw_writel(uhchr | UHCHR_FHR, ohci->mmio_base + UHCHR);
+	__raw_writel(uhchr | UHCHR_FHR, pxa_ohci->mmio_base + UHCHR);
 	udelay(11);
-	__raw_writel(uhchr & ~UHCHR_FHR, ohci->mmio_base + UHCHR);
+	__raw_writel(uhchr & ~UHCHR_FHR, pxa_ohci->mmio_base + UHCHR);
 }
 
 #ifdef CONFIG_PXA27x
@@ -213,25 +222,26 @@
 #define pxa27x_clear_otgph()	do {} while (0)
 #endif
 
-static int pxa27x_start_hc(struct pxa27x_ohci *ohci, struct device *dev)
+static int pxa27x_start_hc(struct pxa27x_ohci *pxa_ohci, struct device *dev)
 {
 	int retval = 0;
 	struct pxaohci_platform_data *inf;
 	uint32_t uhchr;
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
 
 	inf = dev_get_platdata(dev);
 
-	clk_prepare_enable(ohci->clk);
+	clk_prepare_enable(pxa_ohci->clk);
 
-	pxa27x_reset_hc(ohci);
+	pxa27x_reset_hc(pxa_ohci);
 
-	uhchr = __raw_readl(ohci->mmio_base + UHCHR) | UHCHR_FSBIR;
-	__raw_writel(uhchr, ohci->mmio_base + UHCHR);
+	uhchr = __raw_readl(pxa_ohci->mmio_base + UHCHR) | UHCHR_FSBIR;
+	__raw_writel(uhchr, pxa_ohci->mmio_base + UHCHR);
 
-	while (__raw_readl(ohci->mmio_base + UHCHR) & UHCHR_FSBIR)
+	while (__raw_readl(pxa_ohci->mmio_base + UHCHR) & UHCHR_FSBIR)
 		cpu_relax();
 
-	pxa27x_setup_hc(ohci, inf);
+	pxa27x_setup_hc(pxa_ohci, inf);
 
 	if (inf->init)
 		retval = inf->init(dev);
@@ -240,38 +250,39 @@
 		return retval;
 
 	if (cpu_is_pxa3xx())
-		pxa3xx_u2d_start_hc(&ohci_to_hcd(&ohci->ohci)->self);
+		pxa3xx_u2d_start_hc(&hcd->self);
 
-	uhchr = __raw_readl(ohci->mmio_base + UHCHR) & ~UHCHR_SSE;
-	__raw_writel(uhchr, ohci->mmio_base + UHCHR);
-	__raw_writel(UHCHIE_UPRIE | UHCHIE_RWIE, ohci->mmio_base + UHCHIE);
+	uhchr = __raw_readl(pxa_ohci->mmio_base + UHCHR) & ~UHCHR_SSE;
+	__raw_writel(uhchr, pxa_ohci->mmio_base + UHCHR);
+	__raw_writel(UHCHIE_UPRIE | UHCHIE_RWIE, pxa_ohci->mmio_base + UHCHIE);
 
 	/* Clear any OTG Pin Hold */
 	pxa27x_clear_otgph();
 	return 0;
 }
 
-static void pxa27x_stop_hc(struct pxa27x_ohci *ohci, struct device *dev)
+static void pxa27x_stop_hc(struct pxa27x_ohci *pxa_ohci, struct device *dev)
 {
 	struct pxaohci_platform_data *inf;
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
 	uint32_t uhccoms;
 
 	inf = dev_get_platdata(dev);
 
 	if (cpu_is_pxa3xx())
-		pxa3xx_u2d_stop_hc(&ohci_to_hcd(&ohci->ohci)->self);
+		pxa3xx_u2d_stop_hc(&hcd->self);
 
 	if (inf->exit)
 		inf->exit(dev);
 
-	pxa27x_reset_hc(ohci);
+	pxa27x_reset_hc(pxa_ohci);
 
 	/* Host Controller Reset */
-	uhccoms = __raw_readl(ohci->mmio_base + UHCCOMS) | 0x01;
-	__raw_writel(uhccoms, ohci->mmio_base + UHCCOMS);
+	uhccoms = __raw_readl(pxa_ohci->mmio_base + UHCCOMS) | 0x01;
+	__raw_writel(uhccoms, pxa_ohci->mmio_base + UHCCOMS);
 	udelay(10);
 
-	clk_disable_unprepare(ohci->clk);
+	clk_disable_unprepare(pxa_ohci->clk);
 }
 
 #ifdef CONFIG_OF
@@ -356,7 +367,8 @@
 	int retval, irq;
 	struct usb_hcd *hcd;
 	struct pxaohci_platform_data *inf;
-	struct pxa27x_ohci *ohci;
+	struct pxa27x_ohci *pxa_ohci;
+	struct ohci_hcd *ohci;
 	struct resource *r;
 	struct clk *usb_clk;
 
@@ -409,29 +421,31 @@
 	}
 
 	/* initialize "struct pxa27x_ohci" */
-	ohci = (struct pxa27x_ohci *)hcd_to_ohci(hcd);
-	ohci->dev = &pdev->dev;
-	ohci->clk = usb_clk;
-	ohci->mmio_base = (void __iomem *)hcd->regs;
+	pxa_ohci = to_pxa27x_ohci(hcd);
+	pxa_ohci->clk = usb_clk;
+	pxa_ohci->mmio_base = (void __iomem *)hcd->regs;
 
-	if ((retval = pxa27x_start_hc(ohci, &pdev->dev)) < 0) {
+	retval = pxa27x_start_hc(pxa_ohci, &pdev->dev);
+	if (retval < 0) {
 		pr_debug("pxa27x_start_hc failed");
 		goto err3;
 	}
 
 	/* Select Power Management Mode */
-	pxa27x_ohci_select_pmm(ohci, inf->port_mode);
+	pxa27x_ohci_select_pmm(pxa_ohci, inf->port_mode);
 
 	if (inf->power_budget)
 		hcd->power_budget = inf->power_budget;
 
-	ohci_hcd_init(hcd_to_ohci(hcd));
+	/* The value of NDP in roothub_a is incorrect on this hardware */
+	ohci = hcd_to_ohci(hcd);
+	ohci->num_ports = 3;
 
 	retval = usb_add_hcd(hcd, irq, 0);
 	if (retval == 0)
 		return retval;
 
-	pxa27x_stop_hc(ohci, &pdev->dev);
+	pxa27x_stop_hc(pxa_ohci, &pdev->dev);
  err3:
 	iounmap(hcd->regs);
  err2:
@@ -459,88 +473,18 @@
  */
 void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev)
 {
-	struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd);
+	struct pxa27x_ohci *pxa_ohci = to_pxa27x_ohci(hcd);
 
 	usb_remove_hcd(hcd);
-	pxa27x_stop_hc(ohci, &pdev->dev);
+	pxa27x_stop_hc(pxa_ohci, &pdev->dev);
 	iounmap(hcd->regs);
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	clk_put(pxa_ohci->clk);
 	usb_put_hcd(hcd);
-	clk_put(ohci->clk);
 }
 
 /*-------------------------------------------------------------------------*/
 
-static int
-ohci_pxa27x_start (struct usb_hcd *hcd)
-{
-	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
-	int		ret;
-
-	ohci_dbg (ohci, "ohci_pxa27x_start, ohci:%p", ohci);
-
-	/* The value of NDP in roothub_a is incorrect on this hardware */
-	ohci->num_ports = 3;
-
-	if ((ret = ohci_init(ohci)) < 0)
-		return ret;
-
-	if ((ret = ohci_run (ohci)) < 0) {
-		dev_err(hcd->self.controller, "can't start %s",
-			hcd->self.bus_name);
-		ohci_stop (hcd);
-		return ret;
-	}
-
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static const struct hc_driver ohci_pxa27x_hc_driver = {
-	.description =		hcd_name,
-	.product_desc =		"PXA27x OHCI",
-	.hcd_priv_size =	sizeof(struct pxa27x_ohci),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq =			ohci_irq,
-	.flags =		HCD_USB11 | HCD_MEMORY,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.start =		ohci_pxa27x_start,
-	.stop =			ohci_stop,
-	.shutdown =		ohci_shutdown,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue =		ohci_urb_enqueue,
-	.urb_dequeue =		ohci_urb_dequeue,
-	.endpoint_disable =	ohci_endpoint_disable,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number =	ohci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data =	ohci_hub_status_data,
-	.hub_control =		ohci_hub_control,
-#ifdef  CONFIG_PM
-	.bus_suspend =		ohci_bus_suspend,
-	.bus_resume =		ohci_bus_resume,
-#endif
-	.start_port_reset =	ohci_start_port_reset,
-};
-
-/*-------------------------------------------------------------------------*/
-
 static int ohci_hcd_pxa27x_drv_probe(struct platform_device *pdev)
 {
 	pr_debug ("In ohci_hcd_pxa27x_drv_probe");
@@ -563,32 +507,42 @@
 static int ohci_hcd_pxa27x_drv_suspend(struct device *dev)
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
-	struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd);
+	struct pxa27x_ohci *pxa_ohci = to_pxa27x_ohci(hcd);
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+	bool do_wakeup = device_may_wakeup(dev);
+	int ret;
 
-	if (time_before(jiffies, ohci->ohci.next_statechange))
+
+	if (time_before(jiffies, ohci->next_statechange))
 		msleep(5);
-	ohci->ohci.next_statechange = jiffies;
+	ohci->next_statechange = jiffies;
 
-	pxa27x_stop_hc(ohci, dev);
-	return 0;
+	ret = ohci_suspend(hcd, do_wakeup);
+	if (ret)
+		return ret;
+
+	pxa27x_stop_hc(pxa_ohci, dev);
+	return ret;
 }
 
 static int ohci_hcd_pxa27x_drv_resume(struct device *dev)
 {
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
-	struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd);
+	struct pxa27x_ohci *pxa_ohci = to_pxa27x_ohci(hcd);
 	struct pxaohci_platform_data *inf = dev_get_platdata(dev);
+	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
 	int status;
 
-	if (time_before(jiffies, ohci->ohci.next_statechange))
+	if (time_before(jiffies, ohci->next_statechange))
 		msleep(5);
-	ohci->ohci.next_statechange = jiffies;
+	ohci->next_statechange = jiffies;
 
-	if ((status = pxa27x_start_hc(ohci, dev)) < 0)
+	status = pxa27x_start_hc(pxa_ohci, dev);
+	if (status < 0)
 		return status;
 
 	/* Select Power Management Mode */
-	pxa27x_ohci_select_pmm(ohci, inf->port_mode);
+	pxa27x_ohci_select_pmm(pxa_ohci, inf->port_mode);
 
 	ohci_resume(hcd, false);
 	return 0;
@@ -600,9 +554,6 @@
 };
 #endif
 
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:pxa27x-ohci");
-
 static struct platform_driver ohci_hcd_pxa27x_driver = {
 	.probe		= ohci_hcd_pxa27x_drv_probe,
 	.remove		= ohci_hcd_pxa27x_drv_remove,
@@ -617,3 +568,27 @@
 	},
 };
 
+static const struct ohci_driver_overrides pxa27x_overrides __initconst = {
+	.extra_priv_size =      sizeof(struct pxa27x_ohci),
+};
+
+static int __init ohci_pxa27x_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+	ohci_init_driver(&ohci_pxa27x_hc_driver, &pxa27x_overrides);
+	return platform_driver_register(&ohci_hcd_pxa27x_driver);
+}
+module_init(ohci_pxa27x_init);
+
+static void __exit ohci_pxa27x_cleanup(void)
+{
+	platform_driver_unregister(&ohci_hcd_pxa27x_driver);
+}
+module_exit(ohci_pxa27x_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa27x-ohci");
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 4919afa..f90101b 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -19,19 +19,36 @@
  * This file is licenced under the GPL.
 */
 
-#include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/platform_data/usb-ohci-s3c2410.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ohci.h"
+
 
 #define valid_port(idx) ((idx) == 1 || (idx) == 2)
 
 /* clock device associated with the hcd */
 
+
+#define DRIVER_DESC "OHCI S3C2410 driver"
+
+static const char hcd_name[] = "ohci-s3c2410";
+
 static struct clk *clk;
 static struct clk *usb_clk;
 
 /* forward definitions */
 
+static int (*orig_ohci_hub_control)(struct usb_hcd  *hcd, u16 typeReq,
+			u16 wValue, u16 wIndex, char *buf, u16 wLength);
+static int (*orig_ohci_hub_status_data)(struct usb_hcd *hcd, char *buf);
+
 static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc);
 
 /* conversion functions */
@@ -47,10 +64,10 @@
 
 	dev_dbg(&dev->dev, "s3c2410_start_hc:\n");
 
-	clk_enable(usb_clk);
+	clk_prepare_enable(usb_clk);
 	mdelay(2);			/* let the bus clock stabilise */
 
-	clk_enable(clk);
+	clk_prepare_enable(clk);
 
 	if (info != NULL) {
 		info->hcd	= hcd;
@@ -75,8 +92,8 @@
 			(info->enable_oc)(info, 0);
 	}
 
-	clk_disable(clk);
-	clk_disable(usb_clk);
+	clk_disable_unprepare(clk);
+	clk_disable_unprepare(usb_clk);
 }
 
 /* ohci_s3c2410_hub_status_data
@@ -93,7 +110,7 @@
 	int orig;
 	int portno;
 
-	orig  = ohci_hub_status_data(hcd, buf);
+	orig = orig_ohci_hub_status_data(hcd, buf);
 
 	if (info == NULL)
 		return orig;
@@ -164,7 +181,7 @@
 	 * process the request straight away and exit */
 
 	if (info == NULL) {
-		ret = ohci_hub_control(hcd, typeReq, wValue,
+		ret = orig_ohci_hub_control(hcd, typeReq, wValue,
 				       wIndex, buf, wLength);
 		goto out;
 	}
@@ -214,7 +231,7 @@
 		break;
 	}
 
-	ret = ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
+	ret = orig_ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
 	if (ret)
 		goto out;
 
@@ -374,8 +391,6 @@
 
 	s3c2410_start_hc(dev, hcd);
 
-	ohci_hcd_init(hcd_to_ohci(hcd));
-
 	retval = usb_add_hcd(hcd, dev->resource[1].start, 0);
 	if (retval != 0)
 		goto err_ioremap;
@@ -392,71 +407,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int
-ohci_s3c2410_start(struct usb_hcd *hcd)
-{
-	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
-	int ret;
-
-	ret = ohci_init(ohci);
-	if (ret < 0)
-		return ret;
-
-	ret = ohci_run(ohci);
-	if (ret < 0) {
-		dev_err(hcd->self.controller, "can't start %s\n",
-			hcd->self.bus_name);
-		ohci_stop(hcd);
-		return ret;
-	}
-
-	return 0;
-}
-
-
-static const struct hc_driver ohci_s3c2410_hc_driver = {
-	.description =		hcd_name,
-	.product_desc =		"S3C24XX OHCI",
-	.hcd_priv_size =	sizeof(struct ohci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq =			ohci_irq,
-	.flags =		HCD_USB11 | HCD_MEMORY,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.start =		ohci_s3c2410_start,
-	.stop =			ohci_stop,
-	.shutdown =		ohci_shutdown,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue =		ohci_urb_enqueue,
-	.urb_dequeue =		ohci_urb_dequeue,
-	.endpoint_disable =	ohci_endpoint_disable,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number =	ohci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data =	ohci_s3c2410_hub_status_data,
-	.hub_control =		ohci_s3c2410_hub_control,
-#ifdef	CONFIG_PM
-	.bus_suspend =		ohci_bus_suspend,
-	.bus_resume =		ohci_bus_resume,
-#endif
-	.start_port_reset =	ohci_start_port_reset,
-};
-
-/* device driver */
+static struct hc_driver __read_mostly ohci_s3c2410_hc_driver;
 
 static int ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev)
 {
@@ -533,4 +484,39 @@
 	},
 };
 
+static int __init ohci_s3c2410_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+	ohci_init_driver(&ohci_s3c2410_hc_driver, NULL);
+
+	/*
+	 * The Samsung HW has some unusual quirks, which require
+	 * Sumsung-specific workarounds. We override certain hc_driver
+	 * functions here to achieve that. We explicitly do not enhance
+	 * ohci_driver_overrides to allow this more easily, since this
+	 * is an unusual case, and we don't want to encourage others to
+	 * override these functions by making it too easy.
+	 */
+
+	orig_ohci_hub_control = ohci_s3c2410_hc_driver.hub_control;
+	orig_ohci_hub_status_data = ohci_s3c2410_hc_driver.hub_status_data;
+
+	ohci_s3c2410_hc_driver.hub_status_data	= ohci_s3c2410_hub_status_data;
+	ohci_s3c2410_hc_driver.hub_control	= ohci_s3c2410_hub_control;
+
+	return platform_driver_register(&ohci_hcd_s3c2410_driver);
+}
+module_init(ohci_s3c2410_init);
+
+static void __exit ohci_s3c2410_cleanup(void)
+{
+	platform_driver_unregister(&ohci_hcd_s3c2410_driver);
+}
+module_exit(ohci_s3c2410_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:s3c2410-ohci");
diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
index d479d5d..2a5de5f 100644
--- a/drivers/usb/host/ohci-sm501.c
+++ b/drivers/usb/host/ohci-sm501.c
@@ -216,14 +216,21 @@
 static int ohci_sm501_suspend(struct platform_device *pdev, pm_message_t msg)
 {
 	struct device *dev = &pdev->dev;
-	struct ohci_hcd	*ohci = hcd_to_ohci(platform_get_drvdata(pdev));
+	struct usb_hcd  *hcd = platform_get_drvdata(pdev);
+	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+	bool do_wakeup = device_may_wakeup(dev);
+	int ret;
 
 	if (time_before(jiffies, ohci->next_statechange))
 		msleep(5);
 	ohci->next_statechange = jiffies;
 
+	ret = ohci_suspend(hcd, do_wakeup);
+	if (ret)
+		return ret;
+
 	sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 0);
-	return 0;
+	return ret;
 }
 
 static int ohci_sm501_resume(struct platform_device *pdev)
diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c
index cc9dd9e..31ff3fc 100644
--- a/drivers/usb/host/ohci-spear.c
+++ b/drivers/usb/host/ohci-spear.c
@@ -11,92 +11,37 @@
 * warranty of any kind, whether express or implied.
 */
 
-#include <linux/signal.h>
-#include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/signal.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
 
+#include "ohci.h"
+
+#define DRIVER_DESC "OHCI SPEAr driver"
+
+static const char hcd_name[] = "SPEAr-ohci";
 struct spear_ohci {
-	struct ohci_hcd ohci;
 	struct clk *clk;
 };
 
-#define to_spear_ohci(hcd)	(struct spear_ohci *)hcd_to_ohci(hcd)
+#define to_spear_ohci(hcd)     (struct spear_ohci *)(hcd_to_ohci(hcd)->priv)
 
-static void spear_start_ohci(struct spear_ohci *ohci)
-{
-	clk_prepare_enable(ohci->clk);
-}
-
-static void spear_stop_ohci(struct spear_ohci *ohci)
-{
-	clk_disable_unprepare(ohci->clk);
-}
-
-static int ohci_spear_start(struct usb_hcd *hcd)
-{
-	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-	int ret;
-
-	ret = ohci_init(ohci);
-	if (ret < 0)
-		return ret;
-	ohci->regs = hcd->regs;
-
-	ret = ohci_run(ohci);
-	if (ret < 0) {
-		dev_err(hcd->self.controller, "can't start\n");
-		ohci_stop(hcd);
-		return ret;
-	}
-
-	create_debug_files(ohci);
-
-#ifdef DEBUG
-	ohci_dump(ohci, 1);
-#endif
-	return 0;
-}
-
-static const struct hc_driver ohci_spear_hc_driver = {
-	.description		= hcd_name,
-	.product_desc		= "SPEAr OHCI",
-	.hcd_priv_size		= sizeof(struct spear_ohci),
-
-	/* generic hardware linkage */
-	.irq			= ohci_irq,
-	.flags			= HCD_USB11 | HCD_MEMORY,
-
-	/* basic lifecycle operations */
-	.start			= ohci_spear_start,
-	.stop			= ohci_stop,
-	.shutdown		= ohci_shutdown,
-#ifdef	CONFIG_PM
-	.bus_suspend		= ohci_bus_suspend,
-	.bus_resume		= ohci_bus_resume,
-#endif
-
-	/* managing i/o requests and associated device resources */
-	.urb_enqueue		= ohci_urb_enqueue,
-	.urb_dequeue		= ohci_urb_dequeue,
-	.endpoint_disable	= ohci_endpoint_disable,
-
-	/* scheduling support */
-	.get_frame_number	= ohci_get_frame,
-
-	/* root hub support */
-	.hub_status_data	= ohci_hub_status_data,
-	.hub_control		= ohci_hub_control,
-
-	.start_port_reset	= ohci_start_port_reset,
-};
+static struct hc_driver __read_mostly ohci_spear_hc_driver;
 
 static int spear_ohci_hcd_drv_probe(struct platform_device *pdev)
 {
 	const struct hc_driver *driver = &ohci_spear_hc_driver;
+	struct ohci_hcd *ohci;
 	struct usb_hcd *hcd = NULL;
 	struct clk *usbh_clk;
-	struct spear_ohci *ohci_p;
+	struct spear_ohci *sohci_p;
 	struct resource *res;
 	int retval, irq;
 
@@ -151,16 +96,18 @@
 		goto err_put_hcd;
 	}
 
-	ohci_p = (struct spear_ohci *)hcd_to_ohci(hcd);
-	ohci_p->clk = usbh_clk;
-	spear_start_ohci(ohci_p);
-	ohci_hcd_init(hcd_to_ohci(hcd));
+	sohci_p = to_spear_ohci(hcd);
+	sohci_p->clk = usbh_clk;
+
+	clk_prepare_enable(sohci_p->clk);
+
+	ohci = hcd_to_ohci(hcd);
 
 	retval = usb_add_hcd(hcd, platform_get_irq(pdev, 0), 0);
 	if (retval == 0)
 		return retval;
 
-	spear_stop_ohci(ohci_p);
+	clk_disable_unprepare(sohci_p->clk);
 err_put_hcd:
 	usb_put_hcd(hcd);
 fail:
@@ -172,11 +119,11 @@
 static int spear_ohci_hcd_drv_remove(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-	struct spear_ohci *ohci_p = to_spear_ohci(hcd);
+	struct spear_ohci *sohci_p = to_spear_ohci(hcd);
 
 	usb_remove_hcd(hcd);
-	if (ohci_p->clk)
-		spear_stop_ohci(ohci_p);
+	if (sohci_p->clk)
+		clk_disable_unprepare(sohci_p->clk);
 
 	usb_put_hcd(hcd);
 	return 0;
@@ -188,13 +135,14 @@
 {
 	struct usb_hcd *hcd = platform_get_drvdata(dev);
 	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
-	struct spear_ohci *ohci_p = to_spear_ohci(hcd);
+	struct spear_ohci *sohci_p = to_spear_ohci(hcd);
 
 	if (time_before(jiffies, ohci->next_statechange))
 		msleep(5);
 	ohci->next_statechange = jiffies;
 
-	spear_stop_ohci(ohci_p);
+	clk_disable_unprepare(sohci_p->clk);
+
 	return 0;
 }
 
@@ -202,13 +150,13 @@
 {
 	struct usb_hcd *hcd = platform_get_drvdata(dev);
 	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
-	struct spear_ohci *ohci_p = to_spear_ohci(hcd);
+	struct spear_ohci *sohci_p = to_spear_ohci(hcd);
 
 	if (time_before(jiffies, ohci->next_statechange))
 		msleep(5);
 	ohci->next_statechange = jiffies;
 
-	spear_start_ohci(ohci_p);
+	clk_prepare_enable(sohci_p->clk);
 	ohci_resume(hcd, false);
 	return 0;
 }
@@ -234,4 +182,28 @@
 	},
 };
 
+static const struct ohci_driver_overrides spear_overrides __initconst = {
+	.extra_priv_size = sizeof(struct spear_ohci),
+};
+static int __init ohci_spear_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+	ohci_init_driver(&ohci_spear_hc_driver, &spear_overrides);
+	return platform_driver_register(&spear_ohci_hcd_driver);
+}
+module_init(ohci_spear_init);
+
+static void __exit ohci_spear_cleanup(void)
+{
+	platform_driver_unregister(&spear_ohci_hcd_driver);
+}
+module_exit(ohci_spear_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Deepak Sikri");
+MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("platform:spear-ohci");
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 2c76ef1..dfbdd3a 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -79,11 +79,30 @@
 #define USB_INTEL_USB3_PSSEN   0xD8
 #define USB_INTEL_USB3PRM      0xDC
 
+/*
+ * amd_chipset_gen values represent AMD different chipset generations
+ */
+enum amd_chipset_gen {
+	NOT_AMD_CHIPSET = 0,
+	AMD_CHIPSET_SB600,
+	AMD_CHIPSET_SB700,
+	AMD_CHIPSET_SB800,
+	AMD_CHIPSET_HUDSON2,
+	AMD_CHIPSET_BOLTON,
+	AMD_CHIPSET_YANGTZE,
+	AMD_CHIPSET_UNKNOWN,
+};
+
+struct amd_chipset_type {
+	enum amd_chipset_gen gen;
+	u8 rev;
+};
+
 static struct amd_chipset_info {
 	struct pci_dev	*nb_dev;
 	struct pci_dev	*smbus_dev;
 	int nb_type;
-	int sb_type;
+	struct amd_chipset_type sb_type;
 	int isoc_reqs;
 	int probe_count;
 	int probe_result;
@@ -91,6 +110,51 @@
 
 static DEFINE_SPINLOCK(amd_lock);
 
+/*
+ * amd_chipset_sb_type_init - initialize amd chipset southbridge type
+ *
+ * AMD FCH/SB generation and revision is identified by SMBus controller
+ * vendor, device and revision IDs.
+ *
+ * Returns: 1 if it is an AMD chipset, 0 otherwise.
+ */
+static int amd_chipset_sb_type_init(struct amd_chipset_info *pinfo)
+{
+	u8 rev = 0;
+	pinfo->sb_type.gen = AMD_CHIPSET_UNKNOWN;
+
+	pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI,
+			PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL);
+	if (pinfo->smbus_dev) {
+		rev = pinfo->smbus_dev->revision;
+		if (rev >= 0x10 && rev <= 0x1f)
+			pinfo->sb_type.gen = AMD_CHIPSET_SB600;
+		else if (rev >= 0x30 && rev <= 0x3f)
+			pinfo->sb_type.gen = AMD_CHIPSET_SB700;
+		else if (rev >= 0x40 && rev <= 0x4f)
+			pinfo->sb_type.gen = AMD_CHIPSET_SB800;
+	} else {
+		pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+				PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, NULL);
+
+		if (!pinfo->smbus_dev) {
+			pinfo->sb_type.gen = NOT_AMD_CHIPSET;
+			return 0;
+		}
+
+		rev = pinfo->smbus_dev->revision;
+		if (rev >= 0x11 && rev <= 0x14)
+			pinfo->sb_type.gen = AMD_CHIPSET_HUDSON2;
+		else if (rev >= 0x15 && rev <= 0x18)
+			pinfo->sb_type.gen = AMD_CHIPSET_BOLTON;
+		else if (rev >= 0x39 && rev <= 0x3a)
+			pinfo->sb_type.gen = AMD_CHIPSET_YANGTZE;
+	}
+
+	pinfo->sb_type.rev = rev;
+	return 1;
+}
+
 void sb800_prefetch(struct device *dev, int on)
 {
 	u16 misc;
@@ -106,7 +170,6 @@
 
 int usb_amd_find_chipset_info(void)
 {
-	u8 rev = 0;
 	unsigned long flags;
 	struct amd_chipset_info info;
 	int ret;
@@ -122,27 +185,17 @@
 	memset(&info, 0, sizeof(info));
 	spin_unlock_irqrestore(&amd_lock, flags);
 
-	info.smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL);
-	if (info.smbus_dev) {
-		rev = info.smbus_dev->revision;
-		if (rev >= 0x40)
-			info.sb_type = 1;
-		else if (rev >= 0x30 && rev <= 0x3b)
-			info.sb_type = 3;
-	} else {
-		info.smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
-						0x780b, NULL);
-		if (!info.smbus_dev) {
-			ret = 0;
-			goto commit;
-		}
-
-		rev = info.smbus_dev->revision;
-		if (rev >= 0x11 && rev <= 0x18)
-			info.sb_type = 2;
+	if (!amd_chipset_sb_type_init(&info)) {
+		ret = 0;
+		goto commit;
 	}
 
-	if (info.sb_type == 0) {
+	/* Below chipset generations needn't enable AMD PLL quirk */
+	if (info.sb_type.gen == AMD_CHIPSET_UNKNOWN ||
+			info.sb_type.gen == AMD_CHIPSET_SB600 ||
+			info.sb_type.gen == AMD_CHIPSET_YANGTZE ||
+			(info.sb_type.gen == AMD_CHIPSET_SB700 &&
+			info.sb_type.rev > 0x3b)) {
 		if (info.smbus_dev) {
 			pci_dev_put(info.smbus_dev);
 			info.smbus_dev = NULL;
@@ -197,6 +250,39 @@
 }
 EXPORT_SYMBOL_GPL(usb_amd_find_chipset_info);
 
+int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev)
+{
+	/* Make sure amd chipset type has already been initialized */
+	usb_amd_find_chipset_info();
+	if (amd_chipset.sb_type.gen != AMD_CHIPSET_YANGTZE)
+		return 0;
+
+	dev_dbg(&pdev->dev, "QUIRK: Enable AMD remote wakeup fix\n");
+	return 1;
+}
+EXPORT_SYMBOL_GPL(usb_hcd_amd_remote_wakeup_quirk);
+
+bool usb_amd_hang_symptom_quirk(void)
+{
+	u8 rev;
+
+	usb_amd_find_chipset_info();
+	rev = amd_chipset.sb_type.rev;
+	/* SB600 and old version of SB700 have hang symptom bug */
+	return amd_chipset.sb_type.gen == AMD_CHIPSET_SB600 ||
+			(amd_chipset.sb_type.gen == AMD_CHIPSET_SB700 &&
+			 rev >= 0x3a && rev <= 0x3b);
+}
+EXPORT_SYMBOL_GPL(usb_amd_hang_symptom_quirk);
+
+bool usb_amd_prefetch_quirk(void)
+{
+	usb_amd_find_chipset_info();
+	/* SB800 needs pre-fetch fix */
+	return amd_chipset.sb_type.gen == AMD_CHIPSET_SB800;
+}
+EXPORT_SYMBOL_GPL(usb_amd_prefetch_quirk);
+
 /*
  * The hardware normally enables the A-link power management feature, which
  * lets the system lower the power consumption in idle states.
@@ -229,7 +315,9 @@
 		}
 	}
 
-	if (amd_chipset.sb_type == 1 || amd_chipset.sb_type == 2) {
+	if (amd_chipset.sb_type.gen == AMD_CHIPSET_SB800 ||
+			amd_chipset.sb_type.gen == AMD_CHIPSET_HUDSON2 ||
+			amd_chipset.sb_type.gen == AMD_CHIPSET_BOLTON) {
 		outb_p(AB_REG_BAR_LOW, 0xcd6);
 		addr_low = inb_p(0xcd7);
 		outb_p(AB_REG_BAR_HIGH, 0xcd6);
@@ -240,7 +328,8 @@
 		outl_p(0x40, AB_DATA(addr));
 		outl_p(0x34, AB_INDX(addr));
 		val = inl_p(AB_DATA(addr));
-	} else if (amd_chipset.sb_type == 3) {
+	} else if (amd_chipset.sb_type.gen == AMD_CHIPSET_SB700 &&
+			amd_chipset.sb_type.rev <= 0x3b) {
 		pci_read_config_dword(amd_chipset.smbus_dev,
 					AB_REG_BAR_SB700, &addr);
 		outl(AX_INDXC, AB_INDX(addr));
@@ -353,7 +442,7 @@
 	amd_chipset.nb_dev = NULL;
 	amd_chipset.smbus_dev = NULL;
 	amd_chipset.nb_type = 0;
-	amd_chipset.sb_type = 0;
+	memset(&amd_chipset.sb_type, 0, sizeof(amd_chipset.sb_type));
 	amd_chipset.isoc_reqs = 0;
 	amd_chipset.probe_result = 0;
 
@@ -799,7 +888,7 @@
 	 * switchable ports.
 	 */
 	pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN,
-			cpu_to_le32(ports_available));
+			ports_available);
 
 	pci_read_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN,
 			&ports_available);
@@ -821,7 +910,7 @@
 	 * host.
 	 */
 	pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,
-			cpu_to_le32(ports_available));
+			ports_available);
 
 	pci_read_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,
 			&ports_available);
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
index ed6700d..638e88f 100644
--- a/drivers/usb/host/pci-quirks.h
+++ b/drivers/usb/host/pci-quirks.h
@@ -5,6 +5,8 @@
 void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
 int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
 int usb_amd_find_chipset_info(void);
+bool usb_amd_hang_symptom_quirk(void);
+bool usb_amd_prefetch_quirk(void);
 void usb_amd_dev_put(void);
 void usb_amd_quirk_pll_disable(void);
 void usb_amd_quirk_pll_enable(void);
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 5477bf5..79620c3 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -1413,7 +1413,7 @@
 			case SL11H_CTL1MASK_SE0: s = " se0/reset"; break;
 			case SL11H_CTL1MASK_K: s = " k/resume"; break;
 			default: s = "j"; break;
-			}; s; }),
+			} s; }),
 			(t & SL11H_CTL1MASK_LSPD) ? " lowspeed" : "",
 			(t & SL11H_CTL1MASK_SUSPEND) ? " suspend" : "");
 
@@ -1446,7 +1446,7 @@
 			case USB_PID_SETUP: s = "setup"; break;
 			case USB_PID_ACK: s = "status"; break;
 			default: s = "?"; break;
-			}; s;}),
+			} s;}),
 			ep->maxpacket,
 			ep->nak_count, ep->error_count);
 		list_for_each_entry (urb, &ep->hep->urb_list, urb_list) {
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index 4557375..8e239cd 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -310,14 +310,14 @@
 	unsigned short portsc1, portsc2;
 
 
-	usbcmd    = uhci_readw(uhci, 0);
-	usbstat   = uhci_readw(uhci, 2);
-	usbint    = uhci_readw(uhci, 4);
-	usbfrnum  = uhci_readw(uhci, 6);
-	flbaseadd = uhci_readl(uhci, 8);
-	sof       = uhci_readb(uhci, 12);
-	portsc1   = uhci_readw(uhci, 16);
-	portsc2   = uhci_readw(uhci, 18);
+	usbcmd    = uhci_readw(uhci, USBCMD);
+	usbstat   = uhci_readw(uhci, USBSTS);
+	usbint    = uhci_readw(uhci, USBINTR);
+	usbfrnum  = uhci_readw(uhci, USBFRNUM);
+	flbaseadd = uhci_readl(uhci, USBFLBASEADD);
+	sof       = uhci_readb(uhci, USBSOF);
+	portsc1   = uhci_readw(uhci, USBPORTSC1);
+	portsc2   = uhci_readw(uhci, USBPORTSC2);
 
 	out += sprintf(out, "  usbcmd    =     %04x   %s%s%s%s%s%s%s%s\n",
 		usbcmd,
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 9189bc9..93e17b1 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -75,8 +75,6 @@
 	return !!*buf;
 }
 
-#define OK(x)			len = (x); break
-
 #define CLR_RH_PORTSTAT(x) \
 	status = uhci_readw(uhci, port_addr);	\
 	status &= ~(RWC_BITS|WZ_BITS); \
@@ -244,7 +242,7 @@
 			u16 wIndex, char *buf, u16 wLength)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-	int status, lstatus, retval = 0, len = 0;
+	int status, lstatus, retval = 0;
 	unsigned int port = wIndex - 1;
 	unsigned long port_addr = USBPORTSC1 + 2 * port;
 	u16 wPortChange, wPortStatus;
@@ -258,7 +256,8 @@
 
 	case GetHubStatus:
 		*(__le32 *)buf = cpu_to_le32(0);
-		OK(4);		/* hub power */
+		retval = 4; /* hub power */
+		break;
 	case GetPortStatus:
 		if (port >= uhci->rh_numports)
 			goto err;
@@ -311,13 +310,14 @@
 
 		*(__le16 *)buf = cpu_to_le16(wPortStatus);
 		*(__le16 *)(buf + 2) = cpu_to_le16(wPortChange);
-		OK(4);
+		retval = 4;
+		break;
 	case SetHubFeature:		/* We don't implement these */
 	case ClearHubFeature:
 		switch (wValue) {
 		case C_HUB_OVER_CURRENT:
 		case C_HUB_LOCAL_POWER:
-			OK(0);
+			break;
 		default:
 			goto err;
 		}
@@ -329,7 +329,7 @@
 		switch (wValue) {
 		case USB_PORT_FEAT_SUSPEND:
 			SET_RH_PORTSTAT(USBPORTSC_SUSP);
-			OK(0);
+			break;
 		case USB_PORT_FEAT_RESET:
 			SET_RH_PORTSTAT(USBPORTSC_PR);
 
@@ -338,10 +338,10 @@
 
 			/* USB v2.0 7.1.7.5 */
 			uhci->ports_timeout = jiffies + msecs_to_jiffies(50);
-			OK(0);
+			break;
 		case USB_PORT_FEAT_POWER:
 			/* UHCI has no power switching */
-			OK(0);
+			break;
 		default:
 			goto err;
 		}
@@ -356,10 +356,10 @@
 
 			/* Disable terminates Resume signalling */
 			uhci_finish_suspend(uhci, port, port_addr);
-			OK(0);
+			break;
 		case USB_PORT_FEAT_C_ENABLE:
 			CLR_RH_PORTSTAT(USBPORTSC_PEC);
-			OK(0);
+			break;
 		case USB_PORT_FEAT_SUSPEND:
 			if (!(uhci_readw(uhci, port_addr) & USBPORTSC_SUSP)) {
 
@@ -382,32 +382,32 @@
 					uhci->ports_timeout = jiffies +
 						msecs_to_jiffies(20);
 			}
-			OK(0);
+			break;
 		case USB_PORT_FEAT_C_SUSPEND:
 			clear_bit(port, &uhci->port_c_suspend);
-			OK(0);
+			break;
 		case USB_PORT_FEAT_POWER:
 			/* UHCI has no power switching */
 			goto err;
 		case USB_PORT_FEAT_C_CONNECTION:
 			CLR_RH_PORTSTAT(USBPORTSC_CSC);
-			OK(0);
+			break;
 		case USB_PORT_FEAT_C_OVER_CURRENT:
 			CLR_RH_PORTSTAT(USBPORTSC_OCC);
-			OK(0);
+			break;
 		case USB_PORT_FEAT_C_RESET:
 			/* this driver won't report these */
-			OK(0);
+			break;
 		default:
 			goto err;
 		}
 		break;
 	case GetHubDescriptor:
-		len = min_t(unsigned int, sizeof(root_hub_hub_des), wLength);
-		memcpy(buf, root_hub_hub_des, len);
-		if (len > 2)
+		retval = min_t(unsigned int, sizeof(root_hub_hub_des), wLength);
+		memcpy(buf, root_hub_hub_des, retval);
+		if (retval > 2)
 			buf[2] = uhci->rh_numports;
-		OK(len);
+		break;
 	default:
 err:
 		retval = -EPIPE;
diff --git a/drivers/usb/host/uhci-pci.c b/drivers/usb/host/uhci-pci.c
index 0f228c4..4cd7988 100644
--- a/drivers/usb/host/uhci-pci.c
+++ b/drivers/usb/host/uhci-pci.c
@@ -162,6 +162,8 @@
 
 #ifdef CONFIG_PM
 
+static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated);
+
 static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
@@ -174,12 +176,6 @@
 	if (!HCD_HW_ACCESSIBLE(hcd) || uhci->dead)
 		goto done_okay;		/* Already suspended or dead */
 
-	if (uhci->rh_state > UHCI_RH_SUSPENDED) {
-		dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n");
-		rc = -EBUSY;
-		goto done;
-	};
-
 	/* All PCI host controllers are required to disable IRQ generation
 	 * at the source, so we must turn off PIRQ.
 	 */
@@ -195,8 +191,15 @@
 
 done_okay:
 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-done:
 	spin_unlock_irq(&uhci->lock);
+
+	synchronize_irq(hcd->irq);
+
+	/* Check for race with a wakeup request */
+	if (do_wakeup && HCD_WAKEUP_PENDING(hcd)) {
+		uhci_pci_resume(hcd, false);
+		rc = -EBUSY;
+	}
 	return rc;
 }
 
@@ -299,3 +302,5 @@
 	},
 #endif
 };
+
+MODULE_SOFTDEP("pre: ehci_pci");
diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c
index d033a0e..ded842b 100644
--- a/drivers/usb/host/uhci-platform.c
+++ b/drivers/usb/host/uhci-platform.c
@@ -105,8 +105,7 @@
 
 	uhci->regs = hcd->regs;
 
-	ret = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_DISABLED |
-								IRQF_SHARED);
+	ret = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED);
 	if (ret)
 		goto err_uhci;
 
diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c
index ecc88db..1b0888f 100644
--- a/drivers/usb/host/whci/hcd.c
+++ b/drivers/usb/host/whci/hcd.c
@@ -134,7 +134,7 @@
 	default:
 		ret = asl_urb_enqueue(whc, urb, mem_flags);
 		break;
-	};
+	}
 
 	return ret;
 }
@@ -160,7 +160,7 @@
 	default:
 		ret = asl_urb_dequeue(whc, urb, status);
 		break;
-	};
+	}
 
 	return ret;
 }
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 773a6b2..805f234 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -296,7 +296,7 @@
 	/* Wait for last stop endpoint command to finish */
 	timeleft = wait_for_completion_interruptible_timeout(
 			cmd->completion,
-			USB_CTRL_SET_TIMEOUT);
+			XHCI_CMD_DEFAULT_TIMEOUT);
 	if (timeleft <= 0) {
 		xhci_warn(xhci, "%s while waiting for stop endpoint command\n",
 				timeleft == 0 ? "Timeout" : "Signal");
@@ -524,7 +524,8 @@
  * the compliance mode timer is deleted. A port won't enter
  * compliance mode if it has previously entered U0.
  */
-void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, u16 wIndex)
+static void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status,
+				    u16 wIndex)
 {
 	u32 all_ports_seen_u0 = ((1 << xhci->num_usb3_ports)-1);
 	bool port_in_u0 = ((status & PORT_PLS_MASK) == XDEV_U0);
@@ -1157,18 +1158,6 @@
 		t1 = xhci_port_state_to_neutral(t1);
 		if (t1 != t2)
 			xhci_writel(xhci, t2, port_array[port_index]);
-
-		if (hcd->speed != HCD_USB3) {
-			/* enable remote wake up for USB 2.0 */
-			__le32 __iomem *addr;
-			u32 tmp;
-
-			/* Get the port power control register address. */
-			addr = port_array[port_index] + PORTPMSC;
-			tmp = xhci_readl(xhci, addr);
-			tmp |= PORT_RWE;
-			xhci_writel(xhci, tmp, addr);
-		}
 	}
 	hcd->state = HC_STATE_SUSPENDED;
 	bus_state->next_statechange = jiffies + msecs_to_jiffies(10);
@@ -1247,20 +1236,6 @@
 				xhci_ring_device(xhci, slot_id);
 		} else
 			xhci_writel(xhci, temp, port_array[port_index]);
-
-		if (hcd->speed != HCD_USB3) {
-			/* disable remote wake up for USB 2.0 */
-			__le32 __iomem *addr;
-			u32 tmp;
-
-			/* Add one to the port status register address to get
-			 * the port power control register address.
-			 */
-			addr = port_array[port_index] + PORTPMSC;
-			tmp = xhci_readl(xhci, addr);
-			tmp &= ~PORT_RWE;
-			xhci_writel(xhci, tmp, addr);
-		}
 	}
 
 	(void) xhci_readl(xhci, &xhci->op_regs->command);
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 83bcd13..49b8bd0 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1693,9 +1693,7 @@
 void xhci_mem_cleanup(struct xhci_hcd *xhci)
 {
 	struct pci_dev	*pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
-	struct dev_info	*dev_info, *next;
 	struct xhci_cd  *cur_cd, *next_cd;
-	unsigned long	flags;
 	int size;
 	int i, j, num_ports;
 
@@ -1756,13 +1754,6 @@
 
 	scratchpad_free(xhci);
 
-	spin_lock_irqsave(&xhci->lock, flags);
-	list_for_each_entry_safe(dev_info, next, &xhci->lpm_failed_devs, list) {
-		list_del(&dev_info->list);
-		kfree(dev_info);
-	}
-	spin_unlock_irqrestore(&xhci->lock, flags);
-
 	if (!xhci->rh_bw)
 		goto no_bw;
 
@@ -2231,7 +2222,6 @@
 	u32 page_size, temp;
 	int i;
 
-	INIT_LIST_HEAD(&xhci->lpm_failed_devs);
 	INIT_LIST_HEAD(&xhci->cancel_cmd_list);
 
 	page_size = xhci_readl(xhci, &xhci->op_regs->page_size);
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 236c3aa..b8dffd5 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -35,6 +35,9 @@
 #define PCI_VENDOR_ID_ETRON		0x1b6f
 #define PCI_DEVICE_ID_ASROCK_P67	0x7023
 
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI	0x8c31
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI	0x9c31
+
 static const char hcd_name[] = "xhci_hcd";
 
 /* called after powerup, by probe or system-pm "wakeup" */
@@ -69,6 +72,14 @@
 				"QUIRK: Fresco Logic xHC needs configure"
 				" endpoint cmd after reset endpoint");
 		}
+		if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
+				pdev->revision == 0x4) {
+			xhci->quirks |= XHCI_SLOW_SUSPEND;
+			xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
+				"QUIRK: Fresco Logic xHC revision %u"
+				"must be suspended extra slowly",
+				pdev->revision);
+		}
 		/* Fresco Logic confirms: all revisions of this chip do not
 		 * support MSI, even though some of them claim to in their PCI
 		 * capabilities.
@@ -110,6 +121,15 @@
 		xhci->quirks |= XHCI_SPURIOUS_REBOOT;
 		xhci->quirks |= XHCI_AVOID_BEI;
 	}
+	if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+	    (pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI ||
+	     pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI)) {
+		/* Workaround for occasional spurious wakeups from S5 (or
+		 * any other sleep) on Haswell machines with LPT and LPT-LP
+		 * with the new Intel BIOS
+		 */
+		xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
+	}
 	if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
 			pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
 		xhci->quirks |= XHCI_RESET_ON_RESUME;
@@ -217,6 +237,11 @@
 		usb_put_hcd(xhci->shared_hcd);
 	}
 	usb_hcd_pci_remove(dev);
+
+	/* Workaround for spurious wakeups at shutdown with HSW */
+	if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
+		pci_set_power_state(dev, PCI_D3hot);
+
 	kfree(xhci);
 }
 
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 6bfbd80..1e2f3f4 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -178,7 +178,7 @@
 			if (ring->type == TYPE_EVENT &&
 					last_trb_on_last_seg(xhci, ring,
 						ring->deq_seg, ring->dequeue)) {
-				ring->cycle_state = (ring->cycle_state ? 0 : 1);
+				ring->cycle_state ^= 1;
 			}
 			ring->deq_seg = ring->deq_seg->next;
 			ring->dequeue = ring->deq_seg->trbs;
@@ -726,7 +726,7 @@
 
 /* Must be called with xhci->lock held in interrupt context */
 static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci,
-		struct xhci_td *cur_td, int status, char *adjective)
+		struct xhci_td *cur_td, int status)
 {
 	struct usb_hcd *hcd;
 	struct urb	*urb;
@@ -765,10 +765,9 @@
  *  2. Otherwise, we turn all the TRBs in the TD into No-op TRBs (with the chain
  *     bit cleared) so that the HW will skip over them.
  */
-static void handle_stopped_endpoint(struct xhci_hcd *xhci,
+static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
 		union xhci_trb *trb, struct xhci_event_cmd *event)
 {
-	unsigned int slot_id;
 	unsigned int ep_index;
 	struct xhci_virt_device *virt_dev;
 	struct xhci_ring *ep_ring;
@@ -779,10 +778,7 @@
 
 	struct xhci_dequeue_state deq_state;
 
-	if (unlikely(TRB_TO_SUSPEND_PORT(
-			     le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3])))) {
-		slot_id = TRB_TO_SLOT_ID(
-			le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3]));
+	if (unlikely(TRB_TO_SUSPEND_PORT(le32_to_cpu(trb->generic.field[3])))) {
 		virt_dev = xhci->devs[slot_id];
 		if (virt_dev)
 			handle_cmd_in_cmd_wait_list(xhci, virt_dev,
@@ -795,7 +791,6 @@
 	}
 
 	memset(&deq_state, 0, sizeof(deq_state));
-	slot_id = TRB_TO_SLOT_ID(le32_to_cpu(trb->generic.field[3]));
 	ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3]));
 	ep = &xhci->devs[slot_id]->eps[ep_index];
 
@@ -891,7 +886,7 @@
 		/* Doesn't matter what we pass for status, since the core will
 		 * just overwrite it (because the URB has been unlinked).
 		 */
-		xhci_giveback_urb_in_irq(xhci, cur_td, 0, "cancelled");
+		xhci_giveback_urb_in_irq(xhci, cur_td, 0);
 
 		/* Stop processing the cancelled list if the watchdog timer is
 		 * running.
@@ -1001,7 +996,7 @@
 				if (!list_empty(&cur_td->cancelled_td_list))
 					list_del_init(&cur_td->cancelled_td_list);
 				xhci_giveback_urb_in_irq(xhci, cur_td,
-						-ESHUTDOWN, "killed");
+						-ESHUTDOWN);
 			}
 			while (!list_empty(&temp_ep->cancelled_td_list)) {
 				cur_td = list_first_entry(
@@ -1010,7 +1005,7 @@
 						cancelled_td_list);
 				list_del_init(&cur_td->cancelled_td_list);
 				xhci_giveback_urb_in_irq(xhci, cur_td,
-						-ESHUTDOWN, "killed");
+						-ESHUTDOWN);
 			}
 		}
 	}
@@ -1077,11 +1072,9 @@
  * endpoint doorbell to restart the ring, but only if there aren't more
  * cancellations pending.
  */
-static void handle_set_deq_completion(struct xhci_hcd *xhci,
-		struct xhci_event_cmd *event,
-		union xhci_trb *trb)
+static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
+		union xhci_trb *trb, u32 cmd_comp_code)
 {
-	unsigned int slot_id;
 	unsigned int ep_index;
 	unsigned int stream_id;
 	struct xhci_ring *ep_ring;
@@ -1089,7 +1082,6 @@
 	struct xhci_ep_ctx *ep_ctx;
 	struct xhci_slot_ctx *slot_ctx;
 
-	slot_id = TRB_TO_SLOT_ID(le32_to_cpu(trb->generic.field[3]));
 	ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3]));
 	stream_id = TRB_TO_STREAM_ID(le32_to_cpu(trb->generic.field[2]));
 	dev = xhci->devs[slot_id];
@@ -1107,11 +1099,11 @@
 	ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
 	slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx);
 
-	if (GET_COMP_CODE(le32_to_cpu(event->status)) != COMP_SUCCESS) {
+	if (cmd_comp_code != COMP_SUCCESS) {
 		unsigned int ep_state;
 		unsigned int slot_state;
 
-		switch (GET_COMP_CODE(le32_to_cpu(event->status))) {
+		switch (cmd_comp_code) {
 		case COMP_TRB_ERR:
 			xhci_warn(xhci, "WARN Set TR Deq Ptr cmd invalid because "
 					"of stream ID configuration\n");
@@ -1134,7 +1126,7 @@
 		default:
 			xhci_warn(xhci, "WARN Set TR Deq Ptr cmd with unknown "
 					"completion code of %u.\n",
-				  GET_COMP_CODE(le32_to_cpu(event->status)));
+				  cmd_comp_code);
 			break;
 		}
 		/* OK what do we do now?  The endpoint state is hosed, and we
@@ -1171,21 +1163,17 @@
 	ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
 }
 
-static void handle_reset_ep_completion(struct xhci_hcd *xhci,
-		struct xhci_event_cmd *event,
-		union xhci_trb *trb)
+static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id,
+		union xhci_trb *trb, u32 cmd_comp_code)
 {
-	int slot_id;
 	unsigned int ep_index;
 
-	slot_id = TRB_TO_SLOT_ID(le32_to_cpu(trb->generic.field[3]));
 	ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3]));
 	/* This command will only fail if the endpoint wasn't halted,
 	 * but we don't care.
 	 */
 	xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep,
-		"Ignoring reset ep completion code of %u",
-		 GET_COMP_CODE(le32_to_cpu(event->status)));
+		"Ignoring reset ep completion code of %u", cmd_comp_code);
 
 	/* HW with the reset endpoint quirk needs to have a configure endpoint
 	 * command complete before the endpoint can be used.  Queue that here
@@ -1386,21 +1374,149 @@
 	return cur_trb_is_good;
 }
 
+static void xhci_handle_cmd_enable_slot(struct xhci_hcd *xhci, int slot_id,
+		u32 cmd_comp_code)
+{
+	if (cmd_comp_code == COMP_SUCCESS)
+		xhci->slot_id = slot_id;
+	else
+		xhci->slot_id = 0;
+	complete(&xhci->addr_dev);
+}
+
+static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id)
+{
+	struct xhci_virt_device *virt_dev;
+
+	virt_dev = xhci->devs[slot_id];
+	if (!virt_dev)
+		return;
+	if (xhci->quirks & XHCI_EP_LIMIT_QUIRK)
+		/* Delete default control endpoint resources */
+		xhci_free_device_endpoint_resources(xhci, virt_dev, true);
+	xhci_free_virt_device(xhci, slot_id);
+}
+
+static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id,
+		struct xhci_event_cmd *event, u32 cmd_comp_code)
+{
+	struct xhci_virt_device *virt_dev;
+	struct xhci_input_control_ctx *ctrl_ctx;
+	unsigned int ep_index;
+	unsigned int ep_state;
+	u32 add_flags, drop_flags;
+
+	virt_dev = xhci->devs[slot_id];
+	if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event))
+		return;
+	/*
+	 * Configure endpoint commands can come from the USB core
+	 * configuration or alt setting changes, or because the HW
+	 * needed an extra configure endpoint command after a reset
+	 * endpoint command or streams were being configured.
+	 * If the command was for a halted endpoint, the xHCI driver
+	 * is not waiting on the configure endpoint command.
+	 */
+	ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
+	if (!ctrl_ctx) {
+		xhci_warn(xhci, "Could not get input context, bad type.\n");
+		return;
+	}
+
+	add_flags = le32_to_cpu(ctrl_ctx->add_flags);
+	drop_flags = le32_to_cpu(ctrl_ctx->drop_flags);
+	/* Input ctx add_flags are the endpoint index plus one */
+	ep_index = xhci_last_valid_endpoint(add_flags) - 1;
+
+	/* A usb_set_interface() call directly after clearing a halted
+	 * condition may race on this quirky hardware.  Not worth
+	 * worrying about, since this is prototype hardware.  Not sure
+	 * if this will work for streams, but streams support was
+	 * untested on this prototype.
+	 */
+	if (xhci->quirks & XHCI_RESET_EP_QUIRK &&
+			ep_index != (unsigned int) -1 &&
+			add_flags - SLOT_FLAG == drop_flags) {
+		ep_state = virt_dev->eps[ep_index].ep_state;
+		if (!(ep_state & EP_HALTED))
+			goto bandwidth_change;
+		xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
+				"Completed config ep cmd - "
+				"last ep index = %d, state = %d",
+				ep_index, ep_state);
+		/* Clear internal halted state and restart ring(s) */
+		virt_dev->eps[ep_index].ep_state &= ~EP_HALTED;
+		ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
+		return;
+	}
+bandwidth_change:
+	xhci_dbg_trace(xhci,  trace_xhci_dbg_context_change,
+			"Completed config ep cmd");
+	virt_dev->cmd_status = cmd_comp_code;
+	complete(&virt_dev->cmd_completion);
+	return;
+}
+
+static void xhci_handle_cmd_eval_ctx(struct xhci_hcd *xhci, int slot_id,
+		struct xhci_event_cmd *event, u32 cmd_comp_code)
+{
+	struct xhci_virt_device *virt_dev;
+
+	virt_dev = xhci->devs[slot_id];
+	if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event))
+		return;
+	virt_dev->cmd_status = cmd_comp_code;
+	complete(&virt_dev->cmd_completion);
+}
+
+static void xhci_handle_cmd_addr_dev(struct xhci_hcd *xhci, int slot_id,
+		u32 cmd_comp_code)
+{
+	xhci->devs[slot_id]->cmd_status = cmd_comp_code;
+	complete(&xhci->addr_dev);
+}
+
+static void xhci_handle_cmd_reset_dev(struct xhci_hcd *xhci, int slot_id,
+		struct xhci_event_cmd *event)
+{
+	struct xhci_virt_device *virt_dev;
+
+	xhci_dbg(xhci, "Completed reset device command.\n");
+	virt_dev = xhci->devs[slot_id];
+	if (virt_dev)
+		handle_cmd_in_cmd_wait_list(xhci, virt_dev, event);
+	else
+		xhci_warn(xhci, "Reset device command completion "
+				"for disabled slot %u\n", slot_id);
+}
+
+static void xhci_handle_cmd_nec_get_fw(struct xhci_hcd *xhci,
+		struct xhci_event_cmd *event)
+{
+	if (!(xhci->quirks & XHCI_NEC_HOST)) {
+		xhci->error_bitmask |= 1 << 6;
+		return;
+	}
+	xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
+			"NEC firmware version %2x.%02x",
+			NEC_FW_MAJOR(le32_to_cpu(event->status)),
+			NEC_FW_MINOR(le32_to_cpu(event->status)));
+}
+
 static void handle_cmd_completion(struct xhci_hcd *xhci,
 		struct xhci_event_cmd *event)
 {
 	int slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
 	u64 cmd_dma;
 	dma_addr_t cmd_dequeue_dma;
-	struct xhci_input_control_ctx *ctrl_ctx;
-	struct xhci_virt_device *virt_dev;
-	unsigned int ep_index;
-	struct xhci_ring *ep_ring;
-	unsigned int ep_state;
+	u32 cmd_comp_code;
+	union xhci_trb *cmd_trb;
+	u32 cmd_type;
 
 	cmd_dma = le64_to_cpu(event->cmd_trb);
+	cmd_trb = xhci->cmd_ring->dequeue;
 	cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
-			xhci->cmd_ring->dequeue);
+			cmd_trb);
 	/* Is the command ring deq ptr out of sync with the deq seg ptr? */
 	if (cmd_dequeue_dma == 0) {
 		xhci->error_bitmask |= 1 << 4;
@@ -1412,19 +1528,17 @@
 		return;
 	}
 
-	trace_xhci_cmd_completion(&xhci->cmd_ring->dequeue->generic,
-					(struct xhci_generic_trb *) event);
+	trace_xhci_cmd_completion(cmd_trb, (struct xhci_generic_trb *) event);
 
-	if ((GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_CMD_ABORT) ||
-		(GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_CMD_STOP)) {
+	cmd_comp_code = GET_COMP_CODE(le32_to_cpu(event->status));
+	if (cmd_comp_code == COMP_CMD_ABORT || cmd_comp_code == COMP_CMD_STOP) {
 		/* If the return value is 0, we think the trb pointed by
 		 * command ring dequeue pointer is a good trb. The good
 		 * trb means we don't want to cancel the trb, but it have
 		 * been stopped by host. So we should handle it normally.
 		 * Otherwise, driver should invoke inc_deq() and return.
 		 */
-		if (handle_stopped_cmd_ring(xhci,
-				GET_COMP_CODE(le32_to_cpu(event->status)))) {
+		if (handle_stopped_cmd_ring(xhci, cmd_comp_code)) {
 			inc_deq(xhci, xhci->cmd_ring);
 			return;
 		}
@@ -1436,117 +1550,47 @@
 			return;
 	}
 
-	switch (le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3])
-		& TRB_TYPE_BITMASK) {
-	case TRB_TYPE(TRB_ENABLE_SLOT):
-		if (GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_SUCCESS)
-			xhci->slot_id = slot_id;
-		else
-			xhci->slot_id = 0;
-		complete(&xhci->addr_dev);
+	cmd_type = TRB_FIELD_TO_TYPE(le32_to_cpu(cmd_trb->generic.field[3]));
+	switch (cmd_type) {
+	case TRB_ENABLE_SLOT:
+		xhci_handle_cmd_enable_slot(xhci, slot_id, cmd_comp_code);
 		break;
-	case TRB_TYPE(TRB_DISABLE_SLOT):
-		if (xhci->devs[slot_id]) {
-			if (xhci->quirks & XHCI_EP_LIMIT_QUIRK)
-				/* Delete default control endpoint resources */
-				xhci_free_device_endpoint_resources(xhci,
-						xhci->devs[slot_id], true);
-			xhci_free_virt_device(xhci, slot_id);
-		}
+	case TRB_DISABLE_SLOT:
+		xhci_handle_cmd_disable_slot(xhci, slot_id);
 		break;
-	case TRB_TYPE(TRB_CONFIG_EP):
-		virt_dev = xhci->devs[slot_id];
-		if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event))
-			break;
-		/*
-		 * Configure endpoint commands can come from the USB core
-		 * configuration or alt setting changes, or because the HW
-		 * needed an extra configure endpoint command after a reset
-		 * endpoint command or streams were being configured.
-		 * If the command was for a halted endpoint, the xHCI driver
-		 * is not waiting on the configure endpoint command.
-		 */
-		ctrl_ctx = xhci_get_input_control_ctx(xhci,
-				virt_dev->in_ctx);
-		if (!ctrl_ctx) {
-			xhci_warn(xhci, "Could not get input context, bad type.\n");
-			break;
-		}
-		/* Input ctx add_flags are the endpoint index plus one */
-		ep_index = xhci_last_valid_endpoint(le32_to_cpu(ctrl_ctx->add_flags)) - 1;
-		/* A usb_set_interface() call directly after clearing a halted
-		 * condition may race on this quirky hardware.  Not worth
-		 * worrying about, since this is prototype hardware.  Not sure
-		 * if this will work for streams, but streams support was
-		 * untested on this prototype.
-		 */
-		if (xhci->quirks & XHCI_RESET_EP_QUIRK &&
-				ep_index != (unsigned int) -1 &&
-		    le32_to_cpu(ctrl_ctx->add_flags) - SLOT_FLAG ==
-		    le32_to_cpu(ctrl_ctx->drop_flags)) {
-			ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
-			ep_state = xhci->devs[slot_id]->eps[ep_index].ep_state;
-			if (!(ep_state & EP_HALTED))
-				goto bandwidth_change;
-			xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
-					"Completed config ep cmd - "
-					"last ep index = %d, state = %d",
-					ep_index, ep_state);
-			/* Clear internal halted state and restart ring(s) */
-			xhci->devs[slot_id]->eps[ep_index].ep_state &=
-				~EP_HALTED;
-			ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
-			break;
-		}
-bandwidth_change:
-		xhci_dbg_trace(xhci,  trace_xhci_dbg_context_change,
-				"Completed config ep cmd");
-		xhci->devs[slot_id]->cmd_status =
-			GET_COMP_CODE(le32_to_cpu(event->status));
-		complete(&xhci->devs[slot_id]->cmd_completion);
+	case TRB_CONFIG_EP:
+		xhci_handle_cmd_config_ep(xhci, slot_id, event, cmd_comp_code);
 		break;
-	case TRB_TYPE(TRB_EVAL_CONTEXT):
-		virt_dev = xhci->devs[slot_id];
-		if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event))
-			break;
-		xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(le32_to_cpu(event->status));
-		complete(&xhci->devs[slot_id]->cmd_completion);
+	case TRB_EVAL_CONTEXT:
+		xhci_handle_cmd_eval_ctx(xhci, slot_id, event, cmd_comp_code);
 		break;
-	case TRB_TYPE(TRB_ADDR_DEV):
-		xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(le32_to_cpu(event->status));
-		complete(&xhci->addr_dev);
+	case TRB_ADDR_DEV:
+		xhci_handle_cmd_addr_dev(xhci, slot_id, cmd_comp_code);
 		break;
-	case TRB_TYPE(TRB_STOP_RING):
-		handle_stopped_endpoint(xhci, xhci->cmd_ring->dequeue, event);
+	case TRB_STOP_RING:
+		WARN_ON(slot_id != TRB_TO_SLOT_ID(
+				le32_to_cpu(cmd_trb->generic.field[3])));
+		xhci_handle_cmd_stop_ep(xhci, slot_id, cmd_trb, event);
 		break;
-	case TRB_TYPE(TRB_SET_DEQ):
-		handle_set_deq_completion(xhci, event, xhci->cmd_ring->dequeue);
+	case TRB_SET_DEQ:
+		WARN_ON(slot_id != TRB_TO_SLOT_ID(
+				le32_to_cpu(cmd_trb->generic.field[3])));
+		xhci_handle_cmd_set_deq(xhci, slot_id, cmd_trb, cmd_comp_code);
 		break;
-	case TRB_TYPE(TRB_CMD_NOOP):
+	case TRB_CMD_NOOP:
 		break;
-	case TRB_TYPE(TRB_RESET_EP):
-		handle_reset_ep_completion(xhci, event, xhci->cmd_ring->dequeue);
+	case TRB_RESET_EP:
+		WARN_ON(slot_id != TRB_TO_SLOT_ID(
+				le32_to_cpu(cmd_trb->generic.field[3])));
+		xhci_handle_cmd_reset_ep(xhci, slot_id, cmd_trb, cmd_comp_code);
 		break;
-	case TRB_TYPE(TRB_RESET_DEV):
-		xhci_dbg(xhci, "Completed reset device command.\n");
-		slot_id = TRB_TO_SLOT_ID(
-			le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3]));
-		virt_dev = xhci->devs[slot_id];
-		if (virt_dev)
-			handle_cmd_in_cmd_wait_list(xhci, virt_dev, event);
-		else
-			xhci_warn(xhci, "Reset device command completion "
-					"for disabled slot %u\n", slot_id);
+	case TRB_RESET_DEV:
+		WARN_ON(slot_id != TRB_TO_SLOT_ID(
+				le32_to_cpu(cmd_trb->generic.field[3])));
+		xhci_handle_cmd_reset_dev(xhci, slot_id, event);
 		break;
-	case TRB_TYPE(TRB_NEC_GET_FW):
-		if (!(xhci->quirks & XHCI_NEC_HOST)) {
-			xhci->error_bitmask |= 1 << 6;
-			break;
-		}
-		xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
-			"NEC firmware version %2x.%02x",
-			 NEC_FW_MAJOR(le32_to_cpu(event->status)),
-			 NEC_FW_MINOR(le32_to_cpu(event->status)));
+	case TRB_NEC_GET_FW:
+		xhci_handle_cmd_nec_get_fw(xhci, event);
 		break;
 	default:
 		/* Skip over unknown commands on the event ring */
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 1e36dbb..4265b48 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -730,6 +730,9 @@
 
 	spin_lock_irq(&xhci->lock);
 	xhci_halt(xhci);
+	/* Workaround for spurious wakeups at shutdown with HSW */
+	if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
+		xhci_reset(xhci);
 	spin_unlock_irq(&xhci->lock);
 
 	xhci_cleanup_msix(xhci);
@@ -737,6 +740,10 @@
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
 			"xhci_shutdown completed - status = %x",
 			xhci_readl(xhci, &xhci->op_regs->status));
+
+	/* Yet another workaround for spurious wakeups at shutdown with HSW */
+	if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
+		pci_set_power_state(to_pci_dev(hcd->self.controller), PCI_D3hot);
 }
 
 #ifdef CONFIG_PM
@@ -839,6 +846,7 @@
 int xhci_suspend(struct xhci_hcd *xhci)
 {
 	int			rc = 0;
+	unsigned int		delay = XHCI_MAX_HALT_USEC;
 	struct usb_hcd		*hcd = xhci_to_hcd(xhci);
 	u32			command;
 
@@ -861,8 +869,12 @@
 	command = xhci_readl(xhci, &xhci->op_regs->command);
 	command &= ~CMD_RUN;
 	xhci_writel(xhci, command, &xhci->op_regs->command);
+
+	/* Some chips from Fresco Logic need an extraordinary delay */
+	delay *= (xhci->quirks & XHCI_SLOW_SUSPEND) ? 10 : 1;
+
 	if (xhci_handshake(xhci, &xhci->op_regs->status,
-		      STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC)) {
+		      STS_HALT, STS_HALT, delay)) {
 		xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n");
 		spin_unlock_irq(&xhci->lock);
 		return -ETIMEDOUT;
@@ -3447,7 +3459,7 @@
 	/* Wait for the Reset Device command to finish */
 	timeleft = wait_for_completion_interruptible_timeout(
 			reset_device_cmd->completion,
-			USB_CTRL_SET_TIMEOUT);
+			XHCI_CMD_DEFAULT_TIMEOUT);
 	if (timeleft <= 0) {
 		xhci_warn(xhci, "%s while waiting for reset device command\n",
 				timeleft == 0 ? "Timeout" : "Signal");
@@ -3571,11 +3583,6 @@
 		del_timer_sync(&virt_dev->eps[i].stop_cmd_timer);
 	}
 
-	if (udev->usb2_hw_lpm_enabled) {
-		xhci_set_usb2_hardware_lpm(hcd, udev, 0);
-		udev->usb2_hw_lpm_enabled = 0;
-	}
-
 	spin_lock_irqsave(&xhci->lock, flags);
 	/* Don't disable the slot if the host controller is dead. */
 	state = xhci_readl(xhci, &xhci->op_regs->status);
@@ -3709,9 +3716,6 @@
  * the device).
  * We should be protected by the usb_address0_mutex in khubd's hub_port_init, so
  * we should only issue and wait on one address command at the same time.
- *
- * We add one to the device address issued by the hardware because the USB core
- * uses address 1 for the root hubs (even though they're not really devices).
  */
 int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
 {
@@ -3856,16 +3860,13 @@
 	slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
 	trace_xhci_address_ctx(xhci, virt_dev->out_ctx,
 				slot_ctx->dev_info >> 27);
-	/* Use kernel assigned address for devices; store xHC assigned
-	 * address locally. */
-	virt_dev->address = (le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK)
-		+ 1;
 	/* Zero the input context control for later use */
 	ctrl_ctx->add_flags = 0;
 	ctrl_ctx->drop_flags = 0;
 
 	xhci_dbg_trace(xhci, trace_xhci_dbg_address,
-			"Internal device address = %d", virt_dev->address);
+		       "Internal device address = %d",
+		       le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK);
 
 	return 0;
 }
@@ -4013,133 +4014,6 @@
 	return PORT_BESLD(besld) | PORT_L1_TIMEOUT(l1) | PORT_HIRDM(hirdm);
 }
 
-static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd,
-					struct usb_device *udev)
-{
-	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
-	struct dev_info	*dev_info;
-	__le32 __iomem	**port_array;
-	__le32 __iomem	*addr, *pm_addr;
-	u32		temp, dev_id;
-	unsigned int	port_num;
-	unsigned long	flags;
-	int		hird;
-	int		ret;
-
-	if (hcd->speed == HCD_USB3 || !xhci->sw_lpm_support ||
-			!udev->lpm_capable)
-		return -EINVAL;
-
-	/* we only support lpm for non-hub device connected to root hub yet */
-	if (!udev->parent || udev->parent->parent ||
-			udev->descriptor.bDeviceClass == USB_CLASS_HUB)
-		return -EINVAL;
-
-	spin_lock_irqsave(&xhci->lock, flags);
-
-	/* Look for devices in lpm_failed_devs list */
-	dev_id = le16_to_cpu(udev->descriptor.idVendor) << 16 |
-			le16_to_cpu(udev->descriptor.idProduct);
-	list_for_each_entry(dev_info, &xhci->lpm_failed_devs, list) {
-		if (dev_info->dev_id == dev_id) {
-			ret = -EINVAL;
-			goto finish;
-		}
-	}
-
-	port_array = xhci->usb2_ports;
-	port_num = udev->portnum - 1;
-
-	if (port_num > HCS_MAX_PORTS(xhci->hcs_params1)) {
-		xhci_dbg(xhci, "invalid port number %d\n", udev->portnum);
-		ret = -EINVAL;
-		goto finish;
-	}
-
-	/*
-	 * Test USB 2.0 software LPM.
-	 * FIXME: some xHCI 1.0 hosts may implement a new register to set up
-	 * hardware-controlled USB 2.0 LPM. See section 5.4.11 and 4.23.5.1.1.1
-	 * in the June 2011 errata release.
-	 */
-	xhci_dbg(xhci, "test port %d software LPM\n", port_num);
-	/*
-	 * Set L1 Device Slot and HIRD/BESL.
-	 * Check device's USB 2.0 extension descriptor to determine whether
-	 * HIRD or BESL shoule be used. See USB2.0 LPM errata.
-	 */
-	pm_addr = port_array[port_num] + PORTPMSC;
-	hird = xhci_calculate_hird_besl(xhci, udev);
-	temp = PORT_L1DS(udev->slot_id) | PORT_HIRD(hird);
-	xhci_writel(xhci, temp, pm_addr);
-
-	/* Set port link state to U2(L1) */
-	addr = port_array[port_num];
-	xhci_set_link_state(xhci, port_array, port_num, XDEV_U2);
-
-	/* wait for ACK */
-	spin_unlock_irqrestore(&xhci->lock, flags);
-	msleep(10);
-	spin_lock_irqsave(&xhci->lock, flags);
-
-	/* Check L1 Status */
-	ret = xhci_handshake(xhci, pm_addr,
-			PORT_L1S_MASK, PORT_L1S_SUCCESS, 125);
-	if (ret != -ETIMEDOUT) {
-		/* enter L1 successfully */
-		temp = xhci_readl(xhci, addr);
-		xhci_dbg(xhci, "port %d entered L1 state, port status 0x%x\n",
-				port_num, temp);
-		ret = 0;
-	} else {
-		temp = xhci_readl(xhci, pm_addr);
-		xhci_dbg(xhci, "port %d software lpm failed, L1 status %d\n",
-				port_num, temp & PORT_L1S_MASK);
-		ret = -EINVAL;
-	}
-
-	/* Resume the port */
-	xhci_set_link_state(xhci, port_array, port_num, XDEV_U0);
-
-	spin_unlock_irqrestore(&xhci->lock, flags);
-	msleep(10);
-	spin_lock_irqsave(&xhci->lock, flags);
-
-	/* Clear PLC */
-	xhci_test_and_clear_bit(xhci, port_array, port_num, PORT_PLC);
-
-	/* Check PORTSC to make sure the device is in the right state */
-	if (!ret) {
-		temp = xhci_readl(xhci, addr);
-		xhci_dbg(xhci, "resumed port %d status 0x%x\n",	port_num, temp);
-		if (!(temp & PORT_CONNECT) || !(temp & PORT_PE) ||
-				(temp & PORT_PLS_MASK) != XDEV_U0) {
-			xhci_dbg(xhci, "port L1 resume fail\n");
-			ret = -EINVAL;
-		}
-	}
-
-	if (ret) {
-		/* Insert dev to lpm_failed_devs list */
-		xhci_warn(xhci, "device LPM test failed, may disconnect and "
-				"re-enumerate\n");
-		dev_info = kzalloc(sizeof(struct dev_info), GFP_ATOMIC);
-		if (!dev_info) {
-			ret = -ENOMEM;
-			goto finish;
-		}
-		dev_info->dev_id = dev_id;
-		INIT_LIST_HEAD(&dev_info->list);
-		list_add(&dev_info->list, &xhci->lpm_failed_devs);
-	} else {
-		xhci_ring_device(xhci, udev->slot_id);
-	}
-
-finish:
-	spin_unlock_irqrestore(&xhci->lock, flags);
-	return ret;
-}
-
 int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
 			struct usb_device *udev, int enable)
 {
@@ -4216,7 +4090,7 @@
 		}
 
 		pm_val &= ~PORT_HIRD_MASK;
-		pm_val |= PORT_HIRD(hird) | PORT_RWE;
+		pm_val |= PORT_HIRD(hird) | PORT_RWE | PORT_L1DS(udev->slot_id);
 		xhci_writel(xhci, pm_val, pm_addr);
 		pm_val = xhci_readl(xhci, pm_addr);
 		pm_val |= PORT_HLE;
@@ -4224,7 +4098,7 @@
 		/* flush write */
 		xhci_readl(xhci, pm_addr);
 	} else {
-		pm_val &= ~(PORT_HLE | PORT_RWE | PORT_HIRD_MASK);
+		pm_val &= ~(PORT_HLE | PORT_RWE | PORT_HIRD_MASK | PORT_L1DS_MASK);
 		xhci_writel(xhci, pm_val, pm_addr);
 		/* flush write */
 		xhci_readl(xhci, pm_addr);
@@ -4267,24 +4141,26 @@
 int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
 {
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
-	int		ret;
 	int		portnum = udev->portnum - 1;
 
-	ret = xhci_usb2_software_lpm_test(hcd, udev);
-	if (!ret) {
-		xhci_dbg(xhci, "software LPM test succeed\n");
-		if (xhci->hw_lpm_support == 1 &&
-		    xhci_check_usb2_port_capability(xhci, portnum, XHCI_HLC)) {
-			udev->usb2_hw_lpm_capable = 1;
-			udev->l1_params.timeout = XHCI_L1_TIMEOUT;
-			udev->l1_params.besl = XHCI_DEFAULT_BESL;
-			if (xhci_check_usb2_port_capability(xhci, portnum,
-							    XHCI_BLC))
-				udev->usb2_hw_lpm_besl_capable = 1;
-			ret = xhci_set_usb2_hardware_lpm(hcd, udev, 1);
-			if (!ret)
-				udev->usb2_hw_lpm_enabled = 1;
-		}
+	if (hcd->speed == HCD_USB3 || !xhci->sw_lpm_support ||
+			!udev->lpm_capable)
+		return 0;
+
+	/* we only support lpm for non-hub device connected to root hub yet */
+	if (!udev->parent || udev->parent->parent ||
+			udev->descriptor.bDeviceClass == USB_CLASS_HUB)
+		return 0;
+
+	if (xhci->hw_lpm_support == 1 &&
+			xhci_check_usb2_port_capability(
+				xhci, portnum, XHCI_HLC)) {
+		udev->usb2_hw_lpm_capable = 1;
+		udev->l1_params.timeout = XHCI_L1_TIMEOUT;
+		udev->l1_params.besl = XHCI_DEFAULT_BESL;
+		if (xhci_check_usb2_port_capability(xhci, portnum,
+					XHCI_BLC))
+			udev->usb2_hw_lpm_besl_capable = 1;
 	}
 
 	return 0;
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 289fbfb..03c74b7 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -383,6 +383,7 @@
 #define	PORT_RWE		(1 << 3)
 #define	PORT_HIRD(p)		(((p) & 0xf) << 4)
 #define	PORT_HIRD_MASK		(0xf << 4)
+#define	PORT_L1DS_MASK		(0xff << 8)
 #define	PORT_L1DS(p)		(((p) & 0xff) << 8)
 #define	PORT_HLE		(1 << 16)
 
@@ -934,8 +935,6 @@
 	/* Rings saved to ensure old alt settings can be re-instated */
 	struct xhci_ring		**ring_cache;
 	int				num_rings_cached;
-	/* Store xHC assigned device address */
-	int				address;
 #define	XHCI_MAX_RINGS_CACHED	31
 	struct xhci_virt_ep		eps[31];
 	struct completion		cmd_completion;
@@ -1548,6 +1547,8 @@
 #define XHCI_COMP_MODE_QUIRK	(1 << 14)
 #define XHCI_AVOID_BEI		(1 << 15)
 #define XHCI_PLAT		(1 << 16)
+#define XHCI_SLOW_SUSPEND	(1 << 17)
+#define XHCI_SPURIOUS_WAKEUP	(1 << 18)
 	unsigned int		num_active_eps;
 	unsigned int		limit_active_eps;
 	/* There are two roothubs to keep track of bus suspend info for */
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index e2b21c1..ba5f70f 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -246,6 +246,6 @@
 config USB_HSIC_USB3503
        tristate "USB3503 HSIC to USB20 Driver"
        depends on I2C
-       select REGMAP
+       select REGMAP_I2C
        help
          This option enables support for SMSC USB3503 HSIC to USB 2.0 Driver.
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index aa28ac8..b415282 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -120,7 +120,7 @@
 			struct usb_host_endpoint	*e;
 
 			e = alt->endpoint + ep;
-			switch (e->desc.bmAttributes) {
+			switch (usb_endpoint_type(&e->desc)) {
 			case USB_ENDPOINT_XFER_BULK:
 				break;
 			case USB_ENDPOINT_XFER_ISOC:
@@ -437,7 +437,7 @@
 	if (max == 0)
 		return NULL;
 
-	sg = kmalloc_array(nents, sizeof *sg, GFP_KERNEL);
+	sg = kmalloc_array(nents, sizeof(*sg), GFP_KERNEL);
 	if (!sg)
 		return NULL;
 	sg_init_table(sg, nents);
@@ -573,7 +573,7 @@
 {
 	struct usb_config_descriptor	*config;
 
-	if (len < sizeof *config)
+	if (len < sizeof(*config))
 		return 0;
 	config = (struct usb_config_descriptor *) tdev->buf;
 
@@ -606,6 +606,76 @@
 	return 0;
 }
 
+static int is_good_ext(struct usbtest_dev *tdev, u8 *buf)
+{
+	struct usb_ext_cap_descriptor *ext;
+	u32 attr;
+
+	ext = (struct usb_ext_cap_descriptor *) buf;
+
+	if (ext->bLength != USB_DT_USB_EXT_CAP_SIZE) {
+		ERROR(tdev, "bogus usb 2.0 extension descriptor length\n");
+		return 0;
+	}
+
+	attr = le32_to_cpu(ext->bmAttributes);
+	/* bits[1:4] is used and others are reserved */
+	if (attr & ~0x1e) {	/* reserved == 0 */
+		ERROR(tdev, "reserved bits set\n");
+		return 0;
+	}
+
+	return 1;
+}
+
+static int is_good_ss_cap(struct usbtest_dev *tdev, u8 *buf)
+{
+	struct usb_ss_cap_descriptor *ss;
+
+	ss = (struct usb_ss_cap_descriptor *) buf;
+
+	if (ss->bLength != USB_DT_USB_SS_CAP_SIZE) {
+		ERROR(tdev, "bogus superspeed device capability descriptor length\n");
+		return 0;
+	}
+
+	/*
+	 * only bit[1] of bmAttributes is used for LTM and others are
+	 * reserved
+	 */
+	if (ss->bmAttributes & ~0x02) {	/* reserved == 0 */
+		ERROR(tdev, "reserved bits set in bmAttributes\n");
+		return 0;
+	}
+
+	/* bits[0:3] of wSpeedSupported is used and others are reserved */
+	if (le16_to_cpu(ss->wSpeedSupported) & ~0x0f) {	/* reserved == 0 */
+		ERROR(tdev, "reserved bits set in wSpeedSupported\n");
+		return 0;
+	}
+
+	return 1;
+}
+
+static int is_good_con_id(struct usbtest_dev *tdev, u8 *buf)
+{
+	struct usb_ss_container_id_descriptor *con_id;
+
+	con_id = (struct usb_ss_container_id_descriptor *) buf;
+
+	if (con_id->bLength != USB_DT_USB_SS_CONTN_ID_SIZE) {
+		ERROR(tdev, "bogus container id descriptor length\n");
+		return 0;
+	}
+
+	if (con_id->bReserved) {	/* reserved == 0 */
+		ERROR(tdev, "reserved bits set\n");
+		return 0;
+	}
+
+	return 1;
+}
+
 /* sanity test for standard requests working with usb_control_mesg() and some
  * of the utility functions which use it.
  *
@@ -683,12 +753,96 @@
 
 	/* there's always [9.4.3] a device descriptor [9.6.1] */
 	retval = usb_get_descriptor(udev, USB_DT_DEVICE, 0,
-			dev->buf, sizeof udev->descriptor);
-	if (retval != sizeof udev->descriptor) {
+			dev->buf, sizeof(udev->descriptor));
+	if (retval != sizeof(udev->descriptor)) {
 		dev_err(&iface->dev, "dev descriptor --> %d\n", retval);
 		return (retval < 0) ? retval : -EDOM;
 	}
 
+	/*
+	 * there's always [9.4.3] a bos device descriptor [9.6.2] in USB
+	 * 3.0 spec
+	 */
+	if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0300) {
+		struct usb_bos_descriptor *bos = NULL;
+		struct usb_dev_cap_header *header = NULL;
+		unsigned total, num, length;
+		u8 *buf;
+
+		retval = usb_get_descriptor(udev, USB_DT_BOS, 0, dev->buf,
+				sizeof(*udev->bos->desc));
+		if (retval != sizeof(*udev->bos->desc)) {
+			dev_err(&iface->dev, "bos descriptor --> %d\n", retval);
+			return (retval < 0) ? retval : -EDOM;
+		}
+
+		bos = (struct usb_bos_descriptor *)dev->buf;
+		total = le16_to_cpu(bos->wTotalLength);
+		num = bos->bNumDeviceCaps;
+
+		if (total > TBUF_SIZE)
+			total = TBUF_SIZE;
+
+		/*
+		 * get generic device-level capability descriptors [9.6.2]
+		 * in USB 3.0 spec
+		 */
+		retval = usb_get_descriptor(udev, USB_DT_BOS, 0, dev->buf,
+				total);
+		if (retval != total) {
+			dev_err(&iface->dev, "bos descriptor set --> %d\n",
+					retval);
+			return (retval < 0) ? retval : -EDOM;
+		}
+
+		length = sizeof(*udev->bos->desc);
+		buf = dev->buf;
+		for (i = 0; i < num; i++) {
+			buf += length;
+			if (buf + sizeof(struct usb_dev_cap_header) >
+					dev->buf + total)
+				break;
+
+			header = (struct usb_dev_cap_header *)buf;
+			length = header->bLength;
+
+			if (header->bDescriptorType !=
+					USB_DT_DEVICE_CAPABILITY) {
+				dev_warn(&udev->dev, "not device capability descriptor, skip\n");
+				continue;
+			}
+
+			switch (header->bDevCapabilityType) {
+			case USB_CAP_TYPE_EXT:
+				if (buf + USB_DT_USB_EXT_CAP_SIZE >
+						dev->buf + total ||
+						!is_good_ext(dev, buf)) {
+					dev_err(&iface->dev, "bogus usb 2.0 extension descriptor\n");
+					return -EDOM;
+				}
+				break;
+			case USB_SS_CAP_TYPE:
+				if (buf + USB_DT_USB_SS_CAP_SIZE >
+						dev->buf + total ||
+						!is_good_ss_cap(dev, buf)) {
+					dev_err(&iface->dev, "bogus superspeed device capability descriptor\n");
+					return -EDOM;
+				}
+				break;
+			case CONTAINER_ID_TYPE:
+				if (buf + USB_DT_USB_SS_CONTN_ID_SIZE >
+						dev->buf + total ||
+						!is_good_con_id(dev, buf)) {
+					dev_err(&iface->dev, "bogus container id descriptor\n");
+					return -EDOM;
+				}
+				break;
+			default:
+				break;
+			}
+		}
+	}
+
 	/* there's always [9.4.3] at least one config descriptor [9.6.3] */
 	for (i = 0; i < udev->descriptor.bNumConfigurations; i++) {
 		retval = usb_get_descriptor(udev, USB_DT_CONFIG, i,
@@ -954,7 +1108,7 @@
 		 * device, but some are chosen to trigger protocol stalls
 		 * or short reads.
 		 */
-		memset(&req, 0, sizeof req);
+		memset(&req, 0, sizeof(req));
 		req.bRequest = USB_REQ_GET_DESCRIPTOR;
 		req.bRequestType = USB_DIR_IN|USB_RECIP_DEVICE;
 
@@ -1074,7 +1228,7 @@
 		if (!u)
 			goto cleanup;
 
-		reqp = kmalloc(sizeof *reqp, GFP_KERNEL);
+		reqp = kmalloc(sizeof(*reqp), GFP_KERNEL);
 		if (!reqp)
 			goto cleanup;
 		reqp->setup = req;
@@ -1667,13 +1821,13 @@
 	if (param->sglen > 10)
 		return -EDOM;
 
-	memset(&context, 0, sizeof context);
+	memset(&context, 0, sizeof(context));
 	context.count = param->iterations * param->sglen;
 	context.dev = dev;
 	init_completion(&context.done);
 	spin_lock_init(&context.lock);
 
-	memset(urbs, 0, sizeof urbs);
+	memset(urbs, 0, sizeof(urbs));
 	udev = testdev_to_usbdev(dev);
 	dev_info(&dev->intf->dev,
 		"... iso period %d %sframes, wMaxPacket %04x\n",
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index c258a97..57dfc0c 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -75,6 +75,7 @@
 config USB_MUSB_OMAP2PLUS
 	tristate "OMAP2430 and onwards"
 	depends on ARCH_OMAP2PLUS
+	select GENERIC_PHY
 
 config USB_MUSB_AM35X
 	tristate "AM35x"
@@ -90,7 +91,7 @@
 	depends on (BF54x && !BF544) || (BF52x && ! BF522 && !BF523)
 
 config USB_MUSB_UX500
-	tristate "U8500 and U5500"
+	tristate "Ux500 platforms"
 
 endchoice
 
@@ -112,7 +113,7 @@
 	  allow using DMA on multiplatform kernels.
 
 config USB_UX500_DMA
-	bool 'ST Ericsson U8500 and U5500'
+	bool 'ST Ericsson Ux500'
 	depends on USB_MUSB_UX500
 	help
 	  Enable DMA transfers on UX500 platforms.
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
index 5c310c6..ca45b39 100644
--- a/drivers/usb/musb/am35x.c
+++ b/drivers/usb/musb/am35x.c
@@ -89,7 +89,6 @@
 	struct clk		*phy_clk;
 	struct clk		*clk;
 };
-#define glue_to_musb(g)		platform_get_drvdata(g->musb)
 
 /*
  * am35x_musb_enable - enable interrupts
@@ -452,14 +451,18 @@
 	.set_vbus	= am35x_musb_set_vbus,
 };
 
-static u64 am35x_dmamask = DMA_BIT_MASK(32);
+static const struct platform_device_info am35x_dev_info = {
+	.name		= "musb-hdrc",
+	.id		= PLATFORM_DEVID_AUTO,
+	.dma_mask	= DMA_BIT_MASK(32),
+};
 
 static int am35x_probe(struct platform_device *pdev)
 {
 	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
 	struct platform_device		*musb;
 	struct am35x_glue		*glue;
-
+	struct platform_device_info	pinfo;
 	struct clk			*phy_clk;
 	struct clk			*clk;
 
@@ -471,12 +474,6 @@
 		goto err0;
 	}
 
-	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
-	if (!musb) {
-		dev_err(&pdev->dev, "failed to allocate musb device\n");
-		goto err1;
-	}
-
 	phy_clk = clk_get(&pdev->dev, "fck");
 	if (IS_ERR(phy_clk)) {
 		dev_err(&pdev->dev, "failed to get PHY clock\n");
@@ -503,12 +500,7 @@
 		goto err6;
 	}
 
-	musb->dev.parent		= &pdev->dev;
-	musb->dev.dma_mask		= &am35x_dmamask;
-	musb->dev.coherent_dma_mask	= am35x_dmamask;
-
 	glue->dev			= &pdev->dev;
-	glue->musb			= musb;
 	glue->phy_clk			= phy_clk;
 	glue->clk			= clk;
 
@@ -516,22 +508,17 @@
 
 	platform_set_drvdata(pdev, glue);
 
-	ret = platform_device_add_resources(musb, pdev->resource,
-			pdev->num_resources);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to add resources\n");
-		goto err7;
-	}
+	pinfo = am35x_dev_info;
+	pinfo.parent = &pdev->dev;
+	pinfo.res = pdev->resource;
+	pinfo.num_res = pdev->num_resources;
+	pinfo.data = pdata;
+	pinfo.size_data = sizeof(*pdata);
 
-	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
-	if (ret) {
-		dev_err(&pdev->dev, "failed to add platform_data\n");
-		goto err7;
-	}
-
-	ret = platform_device_add(musb);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to register musb device\n");
+	glue->musb = musb = platform_device_register_full(&pinfo);
+	if (IS_ERR(musb)) {
+		ret = PTR_ERR(musb);
+		dev_err(&pdev->dev, "failed to register musb device: %d\n", ret);
 		goto err7;
 	}
 
@@ -550,9 +537,6 @@
 	clk_put(phy_clk);
 
 err3:
-	platform_device_put(musb);
-
-err1:
 	kfree(glue);
 
 err0:
@@ -615,23 +599,16 @@
 
 	return 0;
 }
-
-static struct dev_pm_ops am35x_pm_ops = {
-	.suspend	= am35x_suspend,
-	.resume		= am35x_resume,
-};
-
-#define DEV_PM_OPS	&am35x_pm_ops
-#else
-#define DEV_PM_OPS	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(am35x_pm_ops, am35x_suspend, am35x_resume);
+
 static struct platform_driver am35x_driver = {
 	.probe		= am35x_probe,
 	.remove		= am35x_remove,
 	.driver		= {
 		.name	= "musb-am35x",
-		.pm	= DEV_PM_OPS,
+		.pm	= &am35x_pm_ops,
 	},
 };
 
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index 72e2056..d9692f7 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -561,23 +561,16 @@
 
 	return 0;
 }
-
-static struct dev_pm_ops bfin_pm_ops = {
-	.suspend	= bfin_suspend,
-	.resume		= bfin_resume,
-};
-
-#define DEV_PM_OPS	&bfin_pm_ops
-#else
-#define DEV_PM_OPS	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(bfin_pm_ops, bfin_suspend, bfin_resume);
+
 static struct platform_driver bfin_driver = {
 	.probe		= bfin_probe,
 	.remove		= __exit_p(bfin_remove),
 	.driver		= {
 		.name	= "musb-blackfin",
-		.pm	= DEV_PM_OPS,
+		.pm	= &bfin_pm_ops,
 	},
 };
 
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index d9ddf41..2f2c1cb 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -472,7 +472,11 @@
 	.set_vbus	= da8xx_musb_set_vbus,
 };
 
-static u64 da8xx_dmamask = DMA_BIT_MASK(32);
+static const struct platform_device_info da8xx_dev_info = {
+	.name		= "musb-hdrc",
+	.id		= PLATFORM_DEVID_AUTO,
+	.dma_mask	= DMA_BIT_MASK(32),
+};
 
 static int da8xx_probe(struct platform_device *pdev)
 {
@@ -480,7 +484,7 @@
 	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
 	struct platform_device		*musb;
 	struct da8xx_glue		*glue;
-
+	struct platform_device_info	pinfo;
 	struct clk			*clk;
 
 	int				ret = -ENOMEM;
@@ -491,12 +495,6 @@
 		goto err0;
 	}
 
-	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
-	if (!musb) {
-		dev_err(&pdev->dev, "failed to allocate musb device\n");
-		goto err1;
-	}
-
 	clk = clk_get(&pdev->dev, "usb20");
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clock\n");
@@ -510,12 +508,7 @@
 		goto err4;
 	}
 
-	musb->dev.parent		= &pdev->dev;
-	musb->dev.dma_mask		= &da8xx_dmamask;
-	musb->dev.coherent_dma_mask	= da8xx_dmamask;
-
 	glue->dev			= &pdev->dev;
-	glue->musb			= musb;
 	glue->clk			= clk;
 
 	pdata->platform_ops		= &da8xx_ops;
@@ -535,22 +528,17 @@
 	musb_resources[1].end = pdev->resource[1].end;
 	musb_resources[1].flags = pdev->resource[1].flags;
 
-	ret = platform_device_add_resources(musb, musb_resources,
-			ARRAY_SIZE(musb_resources));
-	if (ret) {
-		dev_err(&pdev->dev, "failed to add resources\n");
-		goto err5;
-	}
+	pinfo = da8xx_dev_info;
+	pinfo.parent = &pdev->dev;
+	pinfo.res = musb_resources;
+	pinfo.num_res = ARRAY_SIZE(musb_resources);
+	pinfo.data = pdata;
+	pinfo.size_data = sizeof(*pdata);
 
-	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
-	if (ret) {
-		dev_err(&pdev->dev, "failed to add platform_data\n");
-		goto err5;
-	}
-
-	ret = platform_device_add(musb);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to register musb device\n");
+	glue->musb = musb = platform_device_register_full(&pinfo);
+	if (IS_ERR(musb)) {
+		ret = PTR_ERR(musb);
+		dev_err(&pdev->dev, "failed to register musb device: %d\n", ret);
 		goto err5;
 	}
 
@@ -563,9 +551,6 @@
 	clk_put(clk);
 
 err3:
-	platform_device_put(musb);
-
-err1:
 	kfree(glue);
 
 err0:
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index ed0834e..1121fd7 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -505,14 +505,19 @@
 	.set_vbus	= davinci_musb_set_vbus,
 };
 
-static u64 davinci_dmamask = DMA_BIT_MASK(32);
+static const struct platform_device_info davinci_dev_info = {
+	.name		= "musb-hdrc",
+	.id		= PLATFORM_DEVID_AUTO,
+	.dma_mask	= DMA_BIT_MASK(32),
+};
 
 static int davinci_probe(struct platform_device *pdev)
 {
-	struct resource musb_resources[2];
+	struct resource			musb_resources[3];
 	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
 	struct platform_device		*musb;
 	struct davinci_glue		*glue;
+	struct platform_device_info	pinfo;
 	struct clk			*clk;
 
 	int				ret = -ENOMEM;
@@ -523,12 +528,6 @@
 		goto err0;
 	}
 
-	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
-	if (!musb) {
-		dev_err(&pdev->dev, "failed to allocate musb device\n");
-		goto err1;
-	}
-
 	clk = clk_get(&pdev->dev, "usb");
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clock\n");
@@ -542,12 +541,7 @@
 		goto err4;
 	}
 
-	musb->dev.parent		= &pdev->dev;
-	musb->dev.dma_mask		= &davinci_dmamask;
-	musb->dev.coherent_dma_mask	= davinci_dmamask;
-
 	glue->dev			= &pdev->dev;
-	glue->musb			= musb;
 	glue->clk			= clk;
 
 	pdata->platform_ops		= &davinci_ops;
@@ -567,22 +561,26 @@
 	musb_resources[1].end = pdev->resource[1].end;
 	musb_resources[1].flags = pdev->resource[1].flags;
 
-	ret = platform_device_add_resources(musb, musb_resources,
-			ARRAY_SIZE(musb_resources));
-	if (ret) {
-		dev_err(&pdev->dev, "failed to add resources\n");
-		goto err5;
-	}
+	/*
+	 * For DM6467 3 resources are passed. A placeholder for the 3rd
+	 * resource is always there, so it's safe to always copy it...
+	 */
+	musb_resources[2].name = pdev->resource[2].name;
+	musb_resources[2].start = pdev->resource[2].start;
+	musb_resources[2].end = pdev->resource[2].end;
+	musb_resources[2].flags = pdev->resource[2].flags;
 
-	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
-	if (ret) {
-		dev_err(&pdev->dev, "failed to add platform_data\n");
-		goto err5;
-	}
+	pinfo = davinci_dev_info;
+	pinfo.parent = &pdev->dev;
+	pinfo.res = musb_resources;
+	pinfo.num_res = ARRAY_SIZE(musb_resources);
+	pinfo.data = pdata;
+	pinfo.size_data = sizeof(*pdata);
 
-	ret = platform_device_add(musb);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to register musb device\n");
+	glue->musb = musb = platform_device_register_full(&pinfo);
+	if (IS_ERR(musb)) {
+		ret = PTR_ERR(musb);
+		dev_err(&pdev->dev, "failed to register musb device: %d\n", ret);
 		goto err5;
 	}
 
@@ -595,9 +593,6 @@
 	clk_put(clk);
 
 err3:
-	platform_device_put(musb);
-
-err1:
 	kfree(glue);
 
 err0:
diff --git a/drivers/usb/musb/musb_am335x.c b/drivers/usb/musb/musb_am335x.c
index 41ac5b5..8be9b02 100644
--- a/drivers/usb/musb/musb_am335x.c
+++ b/drivers/usb/musb/musb_am335x.c
@@ -46,7 +46,7 @@
 	.remove         = am335x_child_remove,
 	.driver         = {
 		.name   = "am335x-usb-childs",
-		.of_match_table	= of_match_ptr(am335x_child_of_match),
+		.of_match_table	= am335x_child_of_match,
 	},
 };
 
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 18e877f..0a43329 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -617,7 +617,7 @@
 				/* case 3 << MUSB_DEVCTL_VBUS_SHIFT: */
 				default:
 					s = "VALID"; break;
-				}; s; }),
+				} s; }),
 				VBUSERR_RETRY_COUNT - musb->vbuserr_retry,
 				musb->port1_status);
 
@@ -922,6 +922,52 @@
 }
 
 /*
+ * Program the HDRC to start (enable interrupts, dma, etc.).
+ */
+void musb_start(struct musb *musb)
+{
+	void __iomem    *regs = musb->mregs;
+	u8              devctl = musb_readb(regs, MUSB_DEVCTL);
+
+	dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
+
+	/*  Set INT enable registers, enable interrupts */
+	musb->intrtxe = musb->epmask;
+	musb_writew(regs, MUSB_INTRTXE, musb->intrtxe);
+	musb->intrrxe = musb->epmask & 0xfffe;
+	musb_writew(regs, MUSB_INTRRXE, musb->intrrxe);
+	musb_writeb(regs, MUSB_INTRUSBE, 0xf7);
+
+	musb_writeb(regs, MUSB_TESTMODE, 0);
+
+	/* put into basic highspeed mode and start session */
+	musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
+			| MUSB_POWER_HSENAB
+			/* ENSUSPEND wedges tusb */
+			/* | MUSB_POWER_ENSUSPEND */
+		   );
+
+	musb->is_active = 0;
+	devctl = musb_readb(regs, MUSB_DEVCTL);
+	devctl &= ~MUSB_DEVCTL_SESSION;
+
+	/* session started after:
+	 * (a) ID-grounded irq, host mode;
+	 * (b) vbus present/connect IRQ, peripheral mode;
+	 * (c) peripheral initiates, using SRP
+	 */
+	if (musb->port_mode != MUSB_PORT_MODE_HOST &&
+			(devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) {
+		musb->is_active = 1;
+	} else {
+		devctl |= MUSB_DEVCTL_SESSION;
+	}
+
+	musb_platform_enable(musb);
+	musb_writeb(regs, MUSB_DEVCTL, devctl);
+}
+
+/*
  * Make the HDRC stop (disable interrupts, etc.);
  * reversible by musb_start
  * called on gadget driver unregister
@@ -1763,8 +1809,7 @@
 			disable_irq_wake(musb->nIrq);
 		free_irq(musb->nIrq, musb);
 	}
-	if (musb->dma_controller)
-		dma_controller_destroy(musb->dma_controller);
+	cancel_work_sync(&musb->irq_work);
 
 	musb_host_free(musb);
 }
@@ -1839,8 +1884,13 @@
 
 	pm_runtime_get_sync(musb->controller);
 
-	if (use_dma && dev->dma_mask)
+	if (use_dma && dev->dma_mask) {
 		musb->dma_controller = dma_controller_create(musb, musb->mregs);
+		if (IS_ERR(musb->dma_controller)) {
+			status = PTR_ERR(musb->dma_controller);
+			goto fail2_5;
+		}
+	}
 
 	/* be sure interrupts are disabled before connecting ISR */
 	musb_platform_disable(musb);
@@ -1900,6 +1950,8 @@
 		if (status < 0)
 			goto fail3;
 		status = musb_gadget_setup(musb);
+		if (status)
+			musb_host_cleanup(musb);
 		break;
 	default:
 		dev_err(dev, "unsupported port mode %d\n", musb->port_mode);
@@ -1926,10 +1978,12 @@
 
 fail4:
 	musb_gadget_cleanup(musb);
+	musb_host_cleanup(musb);
 
 fail3:
 	if (musb->dma_controller)
 		dma_controller_destroy(musb->dma_controller);
+fail2_5:
 	pm_runtime_put_sync(musb->controller);
 
 fail2:
@@ -1986,6 +2040,9 @@
 	musb_exit_debugfs(musb);
 	musb_shutdown(pdev);
 
+	if (musb->dma_controller)
+		dma_controller_destroy(musb->dma_controller);
+
 	musb_free(musb);
 	device_init_wakeup(dev, 0);
 	return 0;
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 65f3917..29f7cd7 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -46,6 +46,7 @@
 #include <linux/usb.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/musb.h>
+#include <linux/phy/phy.h>
 
 struct musb;
 struct musb_hw_ep;
@@ -341,6 +342,7 @@
 	u16			int_tx;
 
 	struct usb_phy		*xceiv;
+	struct phy		*phy;
 
 	int nIrq;
 	unsigned		irq_wake:1;
@@ -503,6 +505,7 @@
 extern const char musb_driver_name[];
 
 extern void musb_stop(struct musb *musb);
+extern void musb_start(struct musb *musb);
 
 extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src);
 extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst);
diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c
index ae95974..ff9d6de 100644
--- a/drivers/usb/musb/musb_cppi41.c
+++ b/drivers/usb/musb/musb_cppi41.c
@@ -484,6 +484,7 @@
 		if (ret)
 			goto err;
 
+		ret = -EINVAL;
 		if (port > MUSB_DMA_NUM_CHANNELS || !port)
 			goto err;
 		if (is_tx)
@@ -503,6 +504,7 @@
 		dc = dma_request_slave_channel(dev, str);
 		if (!dc) {
 			dev_err(dev, "Falied to request %s.\n", str);
+			ret = -EPROBE_DEFER;
 			goto err;
 		}
 		cppi41_channel->dc = dc;
@@ -510,7 +512,7 @@
 	return 0;
 err:
 	cppi41_release_all_dma_chans(controller);
-	return -EINVAL;
+	return ret;
 }
 
 void dma_controller_destroy(struct dma_controller *c)
@@ -526,7 +528,7 @@
 					void __iomem *base)
 {
 	struct cppi41_dma_controller *controller;
-	int ret;
+	int ret = 0;
 
 	if (!musb->controller->of_node) {
 		dev_err(musb->controller, "Need DT for the DMA engine.\n");
@@ -553,5 +555,7 @@
 plat_get_fail:
 	kfree(controller);
 kzalloc_fail:
+	if (ret == -EPROBE_DEFER)
+		return ERR_PTR(ret);
 	return NULL;
 }
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index bd4138d..1901f6f 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -121,6 +121,43 @@
 	unsigned long last_timer;    /* last timer data for each instance */
 };
 
+static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
+{
+	struct device *dev = musb->controller;
+	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
+
+	if (timeout == 0)
+		timeout = jiffies + msecs_to_jiffies(3);
+
+	/* Never idle if active, or when VBUS timeout is not set as host */
+	if (musb->is_active || (musb->a_wait_bcon == 0 &&
+				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
+		dev_dbg(musb->controller, "%s active, deleting timer\n",
+				usb_otg_state_string(musb->xceiv->state));
+		del_timer(&glue->timer);
+		glue->last_timer = jiffies;
+		return;
+	}
+	if (musb->port_mode != MUSB_PORT_MODE_DUAL_ROLE)
+		return;
+
+	if (!musb->g.dev.driver)
+		return;
+
+	if (time_after(glue->last_timer, timeout) &&
+				timer_pending(&glue->timer)) {
+		dev_dbg(musb->controller,
+			"Longer idle timer already pending, ignoring...\n");
+		return;
+	}
+	glue->last_timer = timeout;
+
+	dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
+		usb_otg_state_string(musb->xceiv->state),
+			jiffies_to_msecs(timeout - jiffies));
+	mod_timer(&glue->timer, timeout);
+}
+
 /**
  * dsps_musb_enable - enable interrupts
  */
@@ -143,6 +180,7 @@
 	/* Force the DRVVBUS IRQ so we can start polling for ID change. */
 	dsps_writel(reg_base, wrp->coreintr_set,
 		    (1 << wrp->drvvbus) << wrp->usb_shift);
+	dsps_musb_try_idle(musb, 0);
 }
 
 /**
@@ -171,6 +209,7 @@
 	const struct dsps_musb_wrapper *wrp = glue->wrp;
 	u8 devctl;
 	unsigned long flags;
+	int skip_session = 0;
 
 	/*
 	 * We poll because DSPS IP's won't expose several OTG-critical
@@ -183,10 +222,12 @@
 	spin_lock_irqsave(&musb->lock, flags);
 	switch (musb->xceiv->state) {
 	case OTG_STATE_A_WAIT_BCON:
-		devctl &= ~MUSB_DEVCTL_SESSION;
-		dsps_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+		dsps_writeb(musb->mregs, MUSB_DEVCTL, 0);
+		skip_session = 1;
+		/* fall */
 
-		devctl = dsps_readb(musb->mregs, MUSB_DEVCTL);
+	case OTG_STATE_A_IDLE:
+	case OTG_STATE_B_IDLE:
 		if (devctl & MUSB_DEVCTL_BDEVICE) {
 			musb->xceiv->state = OTG_STATE_B_IDLE;
 			MUSB_DEV_MODE(musb);
@@ -194,60 +235,21 @@
 			musb->xceiv->state = OTG_STATE_A_IDLE;
 			MUSB_HST_MODE(musb);
 		}
+		if (!(devctl & MUSB_DEVCTL_SESSION) && !skip_session)
+			dsps_writeb(mregs, MUSB_DEVCTL, MUSB_DEVCTL_SESSION);
+		mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
 		break;
 	case OTG_STATE_A_WAIT_VFALL:
 		musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
 		dsps_writel(musb->ctrl_base, wrp->coreintr_set,
 			    MUSB_INTR_VBUSERROR << wrp->usb_shift);
 		break;
-	case OTG_STATE_B_IDLE:
-		devctl = dsps_readb(mregs, MUSB_DEVCTL);
-		if (devctl & MUSB_DEVCTL_BDEVICE)
-			mod_timer(&glue->timer,
-					jiffies + wrp->poll_seconds * HZ);
-		else
-			musb->xceiv->state = OTG_STATE_A_IDLE;
-		break;
 	default:
 		break;
 	}
 	spin_unlock_irqrestore(&musb->lock, flags);
 }
 
-static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
-{
-	struct device *dev = musb->controller;
-	struct dsps_glue *glue = dev_get_drvdata(dev->parent);
-
-	if (timeout == 0)
-		timeout = jiffies + msecs_to_jiffies(3);
-
-	/* Never idle if active, or when VBUS timeout is not set as host */
-	if (musb->is_active || (musb->a_wait_bcon == 0 &&
-				musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
-		dev_dbg(musb->controller, "%s active, deleting timer\n",
-				usb_otg_state_string(musb->xceiv->state));
-		del_timer(&glue->timer);
-		glue->last_timer = jiffies;
-		return;
-	}
-	if (musb->port_mode == MUSB_PORT_MODE_HOST)
-		return;
-
-	if (time_after(glue->last_timer, timeout) &&
-				timer_pending(&glue->timer)) {
-		dev_dbg(musb->controller,
-			"Longer idle timer already pending, ignoring...\n");
-		return;
-	}
-	glue->last_timer = timeout;
-
-	dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
-		usb_otg_state_string(musb->xceiv->state),
-			jiffies_to_msecs(timeout - jiffies));
-	mod_timer(&glue->timer, timeout);
-}
-
 static irqreturn_t dsps_interrupt(int irq, void *hci)
 {
 	struct musb  *musb = hci;
@@ -443,7 +445,7 @@
 	case USB_DR_MODE_OTG:
 	default:
 		return MUSB_PORT_MODE_DUAL_ROLE;
-	};
+	}
 }
 
 static int dsps_create_musb_pdev(struct dsps_glue *glue,
@@ -631,7 +633,7 @@
 	.remove         = dsps_remove,
 	.driver         = {
 		.name   = "musb-dsps",
-		.of_match_table	= of_match_ptr(musb_dsps_of_match),
+		.of_match_table	= musb_dsps_of_match,
 	},
 };
 
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index b19ed21..d2d3a17 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -1121,7 +1121,7 @@
 			case USB_ENDPOINT_XFER_BULK:	s = "bulk"; break;
 			case USB_ENDPOINT_XFER_INT:	s = "int"; break;
 			default:			s = "iso"; break;
-			}; s; }),
+			} s; }),
 			musb_ep->is_in ? "IN" : "OUT",
 			musb_ep->dma ? "dma, " : "",
 			musb_ep->packet_sz);
@@ -1853,11 +1853,14 @@
 	musb->gadget_driver = driver;
 
 	spin_lock_irqsave(&musb->lock, flags);
+	musb->is_active = 1;
 
 	otg_set_peripheral(otg, &musb->g);
 	musb->xceiv->state = OTG_STATE_B_IDLE;
 	spin_unlock_irqrestore(&musb->lock, flags);
 
+	musb_start(musb);
+
 	/* REVISIT:  funcall to other code, which also
 	 * handles power budgeting ... this way also
 	 * ensures HdrcStart is indirectly called.
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 9a2b8c8..6582a20 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -253,7 +253,7 @@
 			case USB_ENDPOINT_XFER_BULK:	s = "-bulk"; break;
 			case USB_ENDPOINT_XFER_ISOC:	s = "-iso"; break;
 			default:			s = "-intr"; break;
-			}; s; }),
+			} s; }),
 			epnum, buf + offset, len);
 
 	/* Configure endpoint */
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
index a523950..9af6bba 100644
--- a/drivers/usb/musb/musb_virthub.c
+++ b/drivers/usb/musb/musb_virthub.c
@@ -44,52 +44,6 @@
 
 #include "musb_core.h"
 
-/*
-* Program the HDRC to start (enable interrupts, dma, etc.).
-*/
-static void musb_start(struct musb *musb)
-{
-	void __iomem	*regs = musb->mregs;
-	u8		devctl = musb_readb(regs, MUSB_DEVCTL);
-
-	dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
-
-	/*  Set INT enable registers, enable interrupts */
-	musb->intrtxe = musb->epmask;
-	musb_writew(regs, MUSB_INTRTXE, musb->intrtxe);
-	musb->intrrxe = musb->epmask & 0xfffe;
-	musb_writew(regs, MUSB_INTRRXE, musb->intrrxe);
-	musb_writeb(regs, MUSB_INTRUSBE, 0xf7);
-
-	musb_writeb(regs, MUSB_TESTMODE, 0);
-
-	/* put into basic highspeed mode and start session */
-	musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
-						| MUSB_POWER_HSENAB
-						/* ENSUSPEND wedges tusb */
-						/* | MUSB_POWER_ENSUSPEND */
-						);
-
-	musb->is_active = 0;
-	devctl = musb_readb(regs, MUSB_DEVCTL);
-	devctl &= ~MUSB_DEVCTL_SESSION;
-
-	/* session started after:
-	 * (a) ID-grounded irq, host mode;
-	 * (b) vbus present/connect IRQ, peripheral mode;
-	 * (c) peripheral initiates, using SRP
-	 */
-	if (musb->port_mode != MUSB_PORT_MODE_HOST &&
-	    (devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) {
-		musb->is_active = 1;
-	} else {
-		devctl |= MUSB_DEVCTL_SESSION;
-	}
-
-	musb_platform_enable(musb);
-	musb_writeb(regs, MUSB_DEVCTL, devctl);
-}
-
 static void musb_port_suspend(struct musb *musb, bool do_suspend)
 {
 	struct usb_otg	*otg = musb->xceiv->otg;
@@ -266,6 +220,23 @@
 	return retval;
 }
 
+static int musb_has_gadget(struct musb *musb)
+{
+	/*
+	 * In host-only mode we start a connection right away. In OTG mode
+	 * we have to wait until we loaded a gadget. We don't really need a
+	 * gadget if we operate as a host but we should not start a session
+	 * as a device without a gadget or else we explode.
+	 */
+#ifdef CONFIG_USB_MUSB_HOST
+	return 1;
+#else
+	if (musb->port_mode == MUSB_PORT_MODE_HOST)
+		return 1;
+	return musb->g.dev.driver != NULL;
+#endif
+}
+
 int musb_hub_control(
 	struct usb_hcd	*hcd,
 	u16		typeReq,
@@ -408,7 +379,7 @@
 			 * initialization logic, e.g. for OTG, or change any
 			 * logic relating to VBUS power-up.
 			 */
-			if (!hcd->self.is_b_host)
+			if (!hcd->self.is_b_host && musb_has_gadget(musb))
 				musb_start(musb);
 			break;
 		case USB_PORT_FEAT_RESET:
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 59d2245..2a408cd 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -38,6 +38,7 @@
 #include <linux/delay.h>
 #include <linux/usb/musb-omap.h>
 #include <linux/usb/omap_control_usb.h>
+#include <linux/of_platform.h>
 
 #include "musb_core.h"
 #include "omap2430.h"
@@ -305,6 +306,9 @@
 	default:
 		dev_dbg(dev, "ID float\n");
 	}
+
+	atomic_notifier_call_chain(&musb->xceiv->notifier,
+			musb->xceiv->last_event, NULL);
 }
 
 
@@ -348,11 +352,21 @@
 	 * up through ULPI.  TWL4030-family PMICs include one,
 	 * which needs a driver, drivers aren't always needed.
 	 */
-	if (dev->parent->of_node)
+	if (dev->parent->of_node) {
+		musb->phy = devm_phy_get(dev->parent, "usb2-phy");
+
+		/* We can't totally remove musb->xceiv as of now because
+		 * musb core uses xceiv.state and xceiv.otg. Once we have
+		 * a separate state machine to handle otg, these can be moved
+		 * out of xceiv and then we can start using the generic PHY
+		 * framework
+		 */
 		musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent,
 		    "usb-phy", 0);
-	else
+	} else {
 		musb->xceiv = devm_usb_get_phy_dev(dev, 0);
+		musb->phy = devm_phy_get(dev, "usb");
+	}
 
 	if (IS_ERR(musb->xceiv)) {
 		status = PTR_ERR(musb->xceiv);
@@ -364,6 +378,10 @@
 		return -EPROBE_DEFER;
 	}
 
+	if (IS_ERR(musb->phy)) {
+		pr_err("HS USB OTG: no PHY configured\n");
+		return PTR_ERR(musb->phy);
+	}
 	musb->isr = omap2430_musb_interrupt;
 
 	status = pm_runtime_get_sync(dev);
@@ -397,7 +415,7 @@
 	if (glue->status != OMAP_MUSB_UNKNOWN)
 		omap_musb_set_mailbox(glue);
 
-	usb_phy_init(musb->xceiv);
+	phy_init(musb->phy);
 
 	pm_runtime_put_noidle(musb->controller);
 	return 0;
@@ -460,6 +478,7 @@
 	del_timer_sync(&musb_idle_timer);
 
 	omap2430_low_level_exit(musb);
+	phy_exit(musb->phy);
 
 	return 0;
 }
@@ -509,8 +528,12 @@
 	glue->dev			= &pdev->dev;
 	glue->musb			= musb;
 	glue->status			= OMAP_MUSB_UNKNOWN;
+	glue->control_otghs = ERR_PTR(-ENODEV);
 
 	if (np) {
+		struct device_node *control_node;
+		struct platform_device *control_pdev;
+
 		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 		if (!pdata) {
 			dev_err(&pdev->dev,
@@ -539,22 +562,20 @@
 		of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);
 		of_property_read_u32(np, "power", (u32 *)&pdata->power);
 		config->multipoint = of_property_read_bool(np, "multipoint");
-		pdata->has_mailbox = of_property_read_bool(np,
-		    "ti,has-mailbox");
 
 		pdata->board_data	= data;
 		pdata->config		= config;
-	}
 
-	if (pdata->has_mailbox) {
-		glue->control_otghs = omap_get_control_dev();
-		if (IS_ERR(glue->control_otghs)) {
-			dev_vdbg(&pdev->dev, "Failed to get control device\n");
-			ret = PTR_ERR(glue->control_otghs);
-			goto err2;
+		control_node = of_parse_phandle(np, "ctrl-module", 0);
+		if (control_node) {
+			control_pdev = of_find_device_by_node(control_node);
+			if (!control_pdev) {
+				dev_err(&pdev->dev, "Failed to get control device\n");
+				ret = -EINVAL;
+				goto err2;
+			}
+			glue->control_otghs = &control_pdev->dev;
 		}
-	} else {
-		glue->control_otghs = ERR_PTR(-ENODEV);
 	}
 	pdata->platform_ops		= &omap2430_ops;
 
@@ -638,7 +659,7 @@
 				OTG_INTERFSEL);
 
 		omap2430_low_level_exit(musb);
-		usb_phy_set_suspend(musb->xceiv, 1);
+		phy_power_off(musb->phy);
 	}
 
 	return 0;
@@ -653,8 +674,7 @@
 		omap2430_low_level_init(musb);
 		musb_writel(musb->mregs, OTG_INTERFSEL,
 				musb->context.otg_interfsel);
-
-		usb_phy_set_suspend(musb->xceiv, 0);
+		phy_power_on(musb->phy);
 	}
 
 	return 0;
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index b3b3ed7..4432314 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -1152,7 +1152,11 @@
 	.set_vbus	= tusb_musb_set_vbus,
 };
 
-static u64 tusb_dmamask = DMA_BIT_MASK(32);
+static const struct platform_device_info tusb_dev_info = {
+	.name		= "musb-hdrc",
+	.id		= PLATFORM_DEVID_AUTO,
+	.dma_mask	= DMA_BIT_MASK(32),
+};
 
 static int tusb_probe(struct platform_device *pdev)
 {
@@ -1160,7 +1164,7 @@
 	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
 	struct platform_device		*musb;
 	struct tusb6010_glue		*glue;
-
+	struct platform_device_info	pinfo;
 	int				ret = -ENOMEM;
 
 	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
@@ -1169,18 +1173,7 @@
 		goto err0;
 	}
 
-	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
-	if (!musb) {
-		dev_err(&pdev->dev, "failed to allocate musb device\n");
-		goto err1;
-	}
-
-	musb->dev.parent		= &pdev->dev;
-	musb->dev.dma_mask		= &tusb_dmamask;
-	musb->dev.coherent_dma_mask	= tusb_dmamask;
-
 	glue->dev			= &pdev->dev;
-	glue->musb			= musb;
 
 	pdata->platform_ops		= &tusb_ops;
 
@@ -1204,31 +1197,23 @@
 	musb_resources[2].end = pdev->resource[2].end;
 	musb_resources[2].flags = pdev->resource[2].flags;
 
-	ret = platform_device_add_resources(musb, musb_resources,
-			ARRAY_SIZE(musb_resources));
-	if (ret) {
-		dev_err(&pdev->dev, "failed to add resources\n");
-		goto err3;
-	}
+	pinfo = tusb_dev_info;
+	pinfo.parent = &pdev->dev;
+	pinfo.res = musb_resources;
+	pinfo.num_res = ARRAY_SIZE(musb_resources);
+	pinfo.data = pdata;
+	pinfo.size_data = sizeof(*pdata);
 
-	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
-	if (ret) {
-		dev_err(&pdev->dev, "failed to add platform_data\n");
-		goto err3;
-	}
-
-	ret = platform_device_add(musb);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to register musb device\n");
+	glue->musb = musb = platform_device_register_full(&pinfo);
+	if (IS_ERR(musb)) {
+		ret = PTR_ERR(musb);
+		dev_err(&pdev->dev, "failed to register musb device: %d\n", ret);
 		goto err3;
 	}
 
 	return 0;
 
 err3:
-	platform_device_put(musb);
-
-err1:
 	kfree(glue);
 
 err0:
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index 59256b1..122446b 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -259,7 +259,7 @@
 		goto err1;
 	}
 
-	clk = clk_get(&pdev->dev, "usb");
+	clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clock\n");
 		ret = PTR_ERR(clk);
@@ -376,17 +376,10 @@
 
 	return 0;
 }
-
-static const struct dev_pm_ops ux500_pm_ops = {
-	.suspend	= ux500_suspend,
-	.resume		= ux500_resume,
-};
-
-#define DEV_PM_OPS	(&ux500_pm_ops)
-#else
-#define DEV_PM_OPS	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(ux500_pm_ops, ux500_suspend, ux500_resume);
+
 static const struct of_device_id ux500_match[] = {
         { .compatible = "stericsson,db8500-musb", },
         {}
@@ -397,7 +390,7 @@
 	.remove		= ux500_remove,
 	.driver		= {
 		.name	= "musb-ux500",
-		.pm	= DEV_PM_OPS,
+		.pm	= &ux500_pm_ops,
 		.of_match_table = ux500_match,
 	},
 };
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index d5589f9..08e2f39 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -66,17 +66,6 @@
 	  power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an
 	  additional register to power on USB3 PHY.
 
-config OMAP_USB2
-	tristate "OMAP USB2 PHY Driver"
-	depends on ARCH_OMAP2PLUS
-	select OMAP_CONTROL_USB
-	select USB_PHY
-	help
-	  Enable this to support the transceiver that is part of SOC. This
-	  driver takes care of all the PHY functionality apart from comparator.
-	  The USB OTG controller communicates with the comparator using this
-	  driver.
-
 config OMAP_USB3
 	tristate "OMAP USB3 PHY Driver"
 	depends on ARCH_OMAP2PLUS || COMPILE_TEST
@@ -93,6 +82,7 @@
 
 config AM335X_PHY_USB
 	tristate "AM335x USB PHY Driver"
+	depends on ARM || COMPILE_TEST
 	select USB_PHY
 	select AM335X_CONTROL_USB
 	select NOP_USB_XCEIV
@@ -123,16 +113,6 @@
 	  Enable this to support Samsung USB 3.0 (Super Speed) phy controller
 	  for samsung SoCs.
 
-config TWL4030_USB
-	tristate "TWL4030 USB Transceiver Driver"
-	depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
-	select USB_PHY
-	help
-	  Enable this to support the USB OTG transceiver on TWL4030
-	  family chips (including the TWL5030 and TPS659x0 devices).
-	  This transceiver supports high and full speed devices plus,
-	  in host mode, low speed.
-
 config TWL6030_USB
 	tristate "TWL6030 USB Transceiver Driver"
 	depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS
@@ -214,6 +194,19 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called phy-rcar-usb.
 
+config USB_RCAR_GEN2_PHY
+	tristate "Renesas R-Car Gen2 USB PHY support"
+	depends on ARCH_R8A7790 || ARCH_R8A7791 || COMPILE_TEST
+	select USB_PHY
+	help
+	  Say Y here to add support for the Renesas R-Car Gen2 USB PHY driver.
+	  It is typically used to control internal USB PHY for USBHS,
+	  and to configure shared USB channels 0 and 2.
+	  This driver supports R8A7790 and R8A7791.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called phy-rcar-gen2-usb.
+
 config USB_ULPI
 	bool "Generic ULPI Transceiver Driver"
 	depends on ARM
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index 2135e85..022c1da 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -15,12 +15,10 @@
 obj-$(CONFIG_OMAP_CONTROL_USB)		+= phy-omap-control.o
 obj-$(CONFIG_AM335X_CONTROL_USB)	+= phy-am335x-control.o
 obj-$(CONFIG_AM335X_PHY_USB)		+= phy-am335x.o
-obj-$(CONFIG_OMAP_USB2)			+= phy-omap-usb2.o
 obj-$(CONFIG_OMAP_USB3)			+= phy-omap-usb3.o
 obj-$(CONFIG_SAMSUNG_USBPHY)		+= phy-samsung-usb.o
 obj-$(CONFIG_SAMSUNG_USB2PHY)		+= phy-samsung-usb2.o
 obj-$(CONFIG_SAMSUNG_USB3PHY)		+= phy-samsung-usb3.o
-obj-$(CONFIG_TWL4030_USB)		+= phy-twl4030-usb.o
 obj-$(CONFIG_TWL6030_USB)		+= phy-twl6030-usb.o
 obj-$(CONFIG_USB_EHCI_TEGRA)		+= phy-tegra-usb.o
 obj-$(CONFIG_USB_GPIO_VBUS)		+= phy-gpio-vbus-usb.o
@@ -29,5 +27,6 @@
 obj-$(CONFIG_USB_MV_OTG)		+= phy-mv-usb.o
 obj-$(CONFIG_USB_MXS_PHY)		+= phy-mxs-usb.o
 obj-$(CONFIG_USB_RCAR_PHY)		+= phy-rcar-usb.o
+obj-$(CONFIG_USB_RCAR_GEN2_PHY)		+= phy-rcar-gen2-usb.o
 obj-$(CONFIG_USB_ULPI)			+= phy-ulpi.o
 obj-$(CONFIG_USB_ULPI_VIEWPORT)		+= phy-ulpi-viewport.o
diff --git a/drivers/usb/phy/phy-am335x-control.c b/drivers/usb/phy/phy-am335x-control.c
index 22cf07d..634f49a 100644
--- a/drivers/usb/phy/phy-am335x-control.c
+++ b/drivers/usb/phy/phy-am335x-control.c
@@ -26,6 +26,41 @@
 #define USBPHY_OTGVDET_EN	(1 << 19)
 #define USBPHY_OTGSESSEND_EN	(1 << 20)
 
+#define AM335X_PHY0_WK_EN	(1 << 0)
+#define AM335X_PHY1_WK_EN	(1 << 8)
+
+static void am335x_phy_wkup(struct  phy_control *phy_ctrl, u32 id, bool on)
+{
+	struct am335x_control_usb *usb_ctrl;
+	u32 val;
+	u32 reg;
+
+	usb_ctrl = container_of(phy_ctrl, struct am335x_control_usb, phy_ctrl);
+
+	switch (id) {
+	case 0:
+		reg = AM335X_PHY0_WK_EN;
+		break;
+	case 1:
+		reg = AM335X_PHY1_WK_EN;
+		break;
+	default:
+		WARN_ON(1);
+		return;
+	}
+
+	spin_lock(&usb_ctrl->lock);
+	val = readl(usb_ctrl->wkup);
+
+	if (on)
+		val |= reg;
+	else
+		val &= ~reg;
+
+	writel(val, usb_ctrl->wkup);
+	spin_unlock(&usb_ctrl->lock);
+}
+
 static void am335x_phy_power(struct phy_control *phy_ctrl, u32 id, bool on)
 {
 	struct am335x_control_usb *usb_ctrl;
@@ -59,6 +94,7 @@
 
 static const struct phy_control ctrl_am335x = {
 	.phy_power = am335x_phy_power,
+	.phy_wkup = am335x_phy_wkup,
 };
 
 static const struct of_device_id omap_control_usb_id_table[] = {
@@ -117,6 +153,12 @@
 	ctrl_usb->phy_reg = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(ctrl_usb->phy_reg))
 		return PTR_ERR(ctrl_usb->phy_reg);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wakeup");
+	ctrl_usb->wkup = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(ctrl_usb->wkup))
+		return PTR_ERR(ctrl_usb->wkup);
+
 	spin_lock_init(&ctrl_usb->lock);
 	ctrl_usb->phy_ctrl = *phy_ctrl;
 
@@ -129,7 +171,7 @@
 	.driver		= {
 		.name	= "am335x-control-usb",
 		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(omap_control_usb_id_table),
+		.of_match_table = omap_control_usb_id_table,
 	},
 };
 
diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c
index c4d614d..6370e50 100644
--- a/drivers/usb/phy/phy-am335x.c
+++ b/drivers/usb/phy/phy-am335x.c
@@ -53,21 +53,20 @@
 	}
 
 	ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen,
-			USB_PHY_TYPE_USB2, 0, false, false);
+			USB_PHY_TYPE_USB2, 0, false);
 	if (ret)
 		return ret;
 
 	ret = usb_add_phy_dev(&am_phy->usb_phy_gen.phy);
 	if (ret)
-		goto err_add;
+		return ret;
 	am_phy->usb_phy_gen.phy.init = am335x_init;
 	am_phy->usb_phy_gen.phy.shutdown = am335x_shutdown;
 
 	platform_set_drvdata(pdev, am_phy);
+
 	return 0;
 
-err_add:
-	usb_phy_gen_cleanup_phy(&am_phy->usb_phy_gen);
 	return ret;
 }
 
@@ -79,6 +78,40 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM_RUNTIME
+
+static int am335x_phy_runtime_suspend(struct device *dev)
+{
+	struct platform_device	*pdev = to_platform_device(dev);
+	struct am335x_phy *am_phy = platform_get_drvdata(pdev);
+
+	if (device_may_wakeup(dev))
+		phy_ctrl_wkup(am_phy->phy_ctrl, am_phy->id, true);
+	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, false);
+	return 0;
+}
+
+static int am335x_phy_runtime_resume(struct device *dev)
+{
+	struct platform_device	*pdev = to_platform_device(dev);
+	struct am335x_phy	*am_phy = platform_get_drvdata(pdev);
+
+	phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, true);
+	if (device_may_wakeup(dev))
+		phy_ctrl_wkup(am_phy->phy_ctrl, am_phy->id, false);
+	return 0;
+}
+
+static const struct dev_pm_ops am335x_pm_ops = {
+	SET_RUNTIME_PM_OPS(am335x_phy_runtime_suspend,
+			am335x_phy_runtime_resume, NULL)
+};
+
+#define DEV_PM_OPS	(&am335x_pm_ops)
+#else
+#define DEV_PM_OPS	NULL
+#endif
+
 static const struct of_device_id am335x_phy_ids[] = {
 	{ .compatible = "ti,am335x-usb-phy" },
 	{ }
@@ -91,7 +124,8 @@
 	.driver         = {
 		.name   = "am335x-phy-driver",
 		.owner  = THIS_MODULE,
-		.of_match_table = of_match_ptr(am335x_phy_ids),
+		.pm = DEV_PM_OPS,
+		.of_match_table = am335x_phy_ids,
 	},
 };
 
diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c
index fa7c9f9..7f3c73b 100644
--- a/drivers/usb/phy/phy-fsl-usb.c
+++ b/drivers/usb/phy/phy-fsl-usb.c
@@ -134,7 +134,7 @@
 /* Operations that will be called from OTG Finite State Machine */
 
 /* Charge vbus for vbus pulsing in SRP */
-void fsl_otg_chrg_vbus(int on)
+void fsl_otg_chrg_vbus(struct otg_fsm *fsm, int on)
 {
 	u32 tmp;
 
@@ -170,7 +170,7 @@
 }
 
 /* A-device driver vbus, controlled through PP bit in PORTSC */
-void fsl_otg_drv_vbus(int on)
+void fsl_otg_drv_vbus(struct otg_fsm *fsm, int on)
 {
 	u32 tmp;
 
@@ -188,7 +188,7 @@
  * Pull-up D+, signalling connect by periperal. Also used in
  * data-line pulsing in SRP
  */
-void fsl_otg_loc_conn(int on)
+void fsl_otg_loc_conn(struct otg_fsm *fsm, int on)
 {
 	u32 tmp;
 
@@ -207,7 +207,7 @@
  * port.  In host mode, controller will automatically send SOF.
  * Suspend will block the data on the port.
  */
-void fsl_otg_loc_sof(int on)
+void fsl_otg_loc_sof(struct otg_fsm *fsm, int on)
 {
 	u32 tmp;
 
@@ -222,7 +222,7 @@
 }
 
 /* Start SRP pulsing by data-line pulsing, followed with v-bus pulsing. */
-void fsl_otg_start_pulse(void)
+void fsl_otg_start_pulse(struct otg_fsm *fsm)
 {
 	u32 tmp;
 
@@ -235,7 +235,7 @@
 	fsl_otg_loc_conn(1);
 #endif
 
-	fsl_otg_add_timer(b_data_pulse_tmr);
+	fsl_otg_add_timer(fsm, b_data_pulse_tmr);
 }
 
 void b_data_pulse_end(unsigned long foo)
@@ -252,14 +252,14 @@
 void fsl_otg_pulse_vbus(void)
 {
 	srp_wait_done = 0;
-	fsl_otg_chrg_vbus(1);
+	fsl_otg_chrg_vbus(&fsl_otg_dev->fsm, 1);
 	/* start the timer to end vbus charge */
-	fsl_otg_add_timer(b_vbus_pulse_tmr);
+	fsl_otg_add_timer(&fsl_otg_dev->fsm, b_vbus_pulse_tmr);
 }
 
 void b_vbus_pulse_end(unsigned long foo)
 {
-	fsl_otg_chrg_vbus(0);
+	fsl_otg_chrg_vbus(&fsl_otg_dev->fsm, 0);
 
 	/*
 	 * As USB3300 using the same a_sess_vld and b_sess_vld voltage
@@ -267,7 +267,7 @@
 	 * residual voltage of vbus pulsing and A device pull up
 	 */
 	fsl_otg_dischrg_vbus(1);
-	fsl_otg_add_timer(b_srp_wait_tmr);
+	fsl_otg_add_timer(&fsl_otg_dev->fsm, b_srp_wait_tmr);
 }
 
 void b_srp_end(unsigned long foo)
@@ -289,7 +289,7 @@
 {
 	VDBG("a_wait_enum timeout\n");
 	if (!fsl_otg_dev->phy.otg->host->b_hnp_enable)
-		fsl_otg_add_timer(a_wait_enum_tmr);
+		fsl_otg_add_timer(&fsl_otg_dev->fsm, a_wait_enum_tmr);
 	else
 		otg_statemachine(&fsl_otg_dev->fsm);
 }
@@ -375,8 +375,42 @@
 	kfree(b_vbus_pulse_tmr);
 }
 
+static struct fsl_otg_timer *fsl_otg_get_timer(enum otg_fsm_timer t)
+{
+	struct fsl_otg_timer *timer;
+
+	/* REVISIT: use array of pointers to timers instead */
+	switch (t) {
+	case A_WAIT_VRISE:
+		timer = a_wait_vrise_tmr;
+		break;
+	case A_WAIT_BCON:
+		timer = a_wait_vrise_tmr;
+		break;
+	case A_AIDL_BDIS:
+		timer = a_wait_vrise_tmr;
+		break;
+	case B_ASE0_BRST:
+		timer = a_wait_vrise_tmr;
+		break;
+	case B_SE0_SRP:
+		timer = a_wait_vrise_tmr;
+		break;
+	case B_SRP_FAIL:
+		timer = a_wait_vrise_tmr;
+		break;
+	case A_WAIT_ENUM:
+		timer = a_wait_vrise_tmr;
+		break;
+	default:
+		timer = NULL;
+	}
+
+	return timer;
+}
+
 /* Add timer to timer list */
-void fsl_otg_add_timer(void *gtimer)
+void fsl_otg_add_timer(struct otg_fsm *fsm, void *gtimer)
 {
 	struct fsl_otg_timer *timer = gtimer;
 	struct fsl_otg_timer *tmp_timer;
@@ -394,8 +428,19 @@
 	list_add_tail(&timer->list, &active_timers);
 }
 
+static void fsl_otg_fsm_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer t)
+{
+	struct fsl_otg_timer *timer;
+
+	timer = fsl_otg_get_timer(t);
+	if (!timer)
+		return;
+
+	fsl_otg_add_timer(fsm, timer);
+}
+
 /* Remove timer from the timer list; clear timeout status */
-void fsl_otg_del_timer(void *gtimer)
+void fsl_otg_del_timer(struct otg_fsm *fsm, void *gtimer)
 {
 	struct fsl_otg_timer *timer = gtimer;
 	struct fsl_otg_timer *tmp_timer, *del_tmp;
@@ -405,6 +450,17 @@
 			list_del(&timer->list);
 }
 
+static void fsl_otg_fsm_del_timer(struct otg_fsm *fsm, enum otg_fsm_timer t)
+{
+	struct fsl_otg_timer *timer;
+
+	timer = fsl_otg_get_timer(t);
+	if (!timer)
+		return;
+
+	fsl_otg_del_timer(fsm, timer);
+}
+
 /*
  * Reduce timer count by 1, and find timeout conditions.
  * Called by fsl_otg 1ms timer interrupt
@@ -468,7 +524,7 @@
 				retval = dev->driver->pm->resume(dev);
 				if (fsm->id) {
 					/* default-b */
-					fsl_otg_drv_vbus(1);
+					fsl_otg_drv_vbus(fsm, 1);
 					/*
 					 * Workaround: b_host can't driver
 					 * vbus, but PP in PORTSC needs to
@@ -493,7 +549,7 @@
 					retval = dev->driver->pm->suspend(dev);
 				if (fsm->id)
 					/* default-b */
-					fsl_otg_drv_vbus(0);
+					fsl_otg_drv_vbus(fsm, 0);
 			}
 			otg_dev->host_working = 0;
 		}
@@ -757,8 +813,8 @@
 	.loc_sof = fsl_otg_loc_sof,
 	.start_pulse = fsl_otg_start_pulse,
 
-	.add_timer = fsl_otg_add_timer,
-	.del_timer = fsl_otg_del_timer,
+	.add_timer = fsl_otg_fsm_add_timer,
+	.del_timer = fsl_otg_fsm_del_timer,
 
 	.start_host = fsl_otg_start_host,
 	.start_gadget = fsl_otg_start_gadget,
@@ -1011,7 +1067,7 @@
 			"b_bus_suspend: %d\n"
 			"b_conn: %d\n"
 			"b_se0_srp: %d\n"
-			"b_sess_end: %d\n"
+			"b_ssend_srp: %d\n"
 			"b_sess_vld: %d\n"
 			"id: %d\n",
 			fsm->a_bus_req,
@@ -1026,7 +1082,7 @@
 			fsm->b_bus_suspend,
 			fsm->b_conn,
 			fsm->b_se0_srp,
-			fsm->b_sess_end,
+			fsm->b_ssend_srp,
 			fsm->b_sess_vld,
 			fsm->id);
 	size -= t;
@@ -1057,7 +1113,7 @@
 		break;
 
 	case SET_A_SUSPEND_REQ:
-		fsl_otg_dev->fsm.a_suspend_req = arg;
+		fsl_otg_dev->fsm.a_suspend_req_inf = arg;
 		break;
 
 	case SET_A_BUS_DROP:
diff --git a/drivers/usb/phy/phy-fsl-usb.h b/drivers/usb/phy/phy-fsl-usb.h
index e1859b8..7365170 100644
--- a/drivers/usb/phy/phy-fsl-usb.h
+++ b/drivers/usb/phy/phy-fsl-usb.h
@@ -401,6 +401,6 @@
 #define GET_A_BUS_REQ		_IOR(OTG_IOCTL_MAGIC, 8, int)
 #define GET_B_BUS_REQ		_IOR(OTG_IOCTL_MAGIC, 9, int)
 
-void fsl_otg_add_timer(void *timer);
-void fsl_otg_del_timer(void *timer);
+void fsl_otg_add_timer(struct otg_fsm *fsm, void *timer);
+void fsl_otg_del_timer(struct otg_fsm *fsm, void *timer);
 void fsl_otg_pulse_vbus(void);
diff --git a/drivers/usb/phy/phy-fsm-usb.c b/drivers/usb/phy/phy-fsm-usb.c
index 7f45966..329c2d2 100644
--- a/drivers/usb/phy/phy-fsm-usb.c
+++ b/drivers/usb/phy/phy-fsm-usb.c
@@ -41,17 +41,17 @@
 			fsm->protocol, protocol);
 		/* stop old protocol */
 		if (fsm->protocol == PROTO_HOST)
-			ret = fsm->ops->start_host(fsm, 0);
+			ret = otg_start_host(fsm, 0);
 		else if (fsm->protocol == PROTO_GADGET)
-			ret = fsm->ops->start_gadget(fsm, 0);
+			ret = otg_start_gadget(fsm, 0);
 		if (ret)
 			return ret;
 
 		/* start new protocol */
 		if (protocol == PROTO_HOST)
-			ret = fsm->ops->start_host(fsm, 1);
+			ret = otg_start_host(fsm, 1);
 		else if (protocol == PROTO_GADGET)
-			ret = fsm->ops->start_gadget(fsm, 1);
+			ret = otg_start_gadget(fsm, 1);
 		if (ret)
 			return ret;
 
@@ -69,42 +69,50 @@
 {
 	switch (old_state) {
 	case OTG_STATE_B_IDLE:
-		otg_del_timer(fsm, b_se0_srp_tmr);
+		otg_del_timer(fsm, B_SE0_SRP);
 		fsm->b_se0_srp = 0;
+		fsm->adp_sns = 0;
+		fsm->adp_prb = 0;
 		break;
 	case OTG_STATE_B_SRP_INIT:
+		fsm->data_pulse = 0;
 		fsm->b_srp_done = 0;
 		break;
 	case OTG_STATE_B_PERIPHERAL:
 		break;
 	case OTG_STATE_B_WAIT_ACON:
-		otg_del_timer(fsm, b_ase0_brst_tmr);
+		otg_del_timer(fsm, B_ASE0_BRST);
 		fsm->b_ase0_brst_tmout = 0;
 		break;
 	case OTG_STATE_B_HOST:
 		break;
 	case OTG_STATE_A_IDLE:
+		fsm->adp_prb = 0;
 		break;
 	case OTG_STATE_A_WAIT_VRISE:
-		otg_del_timer(fsm, a_wait_vrise_tmr);
+		otg_del_timer(fsm, A_WAIT_VRISE);
 		fsm->a_wait_vrise_tmout = 0;
 		break;
 	case OTG_STATE_A_WAIT_BCON:
-		otg_del_timer(fsm, a_wait_bcon_tmr);
+		otg_del_timer(fsm, A_WAIT_BCON);
 		fsm->a_wait_bcon_tmout = 0;
 		break;
 	case OTG_STATE_A_HOST:
-		otg_del_timer(fsm, a_wait_enum_tmr);
+		otg_del_timer(fsm, A_WAIT_ENUM);
 		break;
 	case OTG_STATE_A_SUSPEND:
-		otg_del_timer(fsm, a_aidl_bdis_tmr);
+		otg_del_timer(fsm, A_AIDL_BDIS);
 		fsm->a_aidl_bdis_tmout = 0;
-		fsm->a_suspend_req = 0;
+		fsm->a_suspend_req_inf = 0;
 		break;
 	case OTG_STATE_A_PERIPHERAL:
+		otg_del_timer(fsm, A_BIDL_ADIS);
+		fsm->a_bidl_adis_tmout = 0;
 		break;
 	case OTG_STATE_A_WAIT_VFALL:
-		otg_del_timer(fsm, a_wait_vrise_tmr);
+		otg_del_timer(fsm, A_WAIT_VFALL);
+		fsm->a_wait_vfall_tmout = 0;
+		otg_del_timer(fsm, A_WAIT_VRISE);
 		break;
 	case OTG_STATE_A_VBUS_ERR:
 		break;
@@ -127,14 +135,19 @@
 		otg_chrg_vbus(fsm, 0);
 		otg_loc_conn(fsm, 0);
 		otg_loc_sof(fsm, 0);
+		/*
+		 * Driver is responsible for starting ADP probing
+		 * if ADP sensing times out.
+		 */
+		otg_start_adp_sns(fsm);
 		otg_set_protocol(fsm, PROTO_UNDEF);
-		otg_add_timer(fsm, b_se0_srp_tmr);
+		otg_add_timer(fsm, B_SE0_SRP);
 		break;
 	case OTG_STATE_B_SRP_INIT:
 		otg_start_pulse(fsm);
 		otg_loc_sof(fsm, 0);
 		otg_set_protocol(fsm, PROTO_UNDEF);
-		otg_add_timer(fsm, b_srp_fail_tmr);
+		otg_add_timer(fsm, B_SRP_FAIL);
 		break;
 	case OTG_STATE_B_PERIPHERAL:
 		otg_chrg_vbus(fsm, 0);
@@ -147,7 +160,7 @@
 		otg_loc_conn(fsm, 0);
 		otg_loc_sof(fsm, 0);
 		otg_set_protocol(fsm, PROTO_HOST);
-		otg_add_timer(fsm, b_ase0_brst_tmr);
+		otg_add_timer(fsm, B_ASE0_BRST);
 		fsm->a_bus_suspend = 0;
 		break;
 	case OTG_STATE_B_HOST:
@@ -163,6 +176,7 @@
 		otg_chrg_vbus(fsm, 0);
 		otg_loc_conn(fsm, 0);
 		otg_loc_sof(fsm, 0);
+		otg_start_adp_prb(fsm);
 		otg_set_protocol(fsm, PROTO_HOST);
 		break;
 	case OTG_STATE_A_WAIT_VRISE:
@@ -170,14 +184,14 @@
 		otg_loc_conn(fsm, 0);
 		otg_loc_sof(fsm, 0);
 		otg_set_protocol(fsm, PROTO_HOST);
-		otg_add_timer(fsm, a_wait_vrise_tmr);
+		otg_add_timer(fsm, A_WAIT_VRISE);
 		break;
 	case OTG_STATE_A_WAIT_BCON:
 		otg_drv_vbus(fsm, 1);
 		otg_loc_conn(fsm, 0);
 		otg_loc_sof(fsm, 0);
 		otg_set_protocol(fsm, PROTO_HOST);
-		otg_add_timer(fsm, a_wait_bcon_tmr);
+		otg_add_timer(fsm, A_WAIT_BCON);
 		break;
 	case OTG_STATE_A_HOST:
 		otg_drv_vbus(fsm, 1);
@@ -188,15 +202,15 @@
 		 * When HNP is triggered while a_bus_req = 0, a_host will
 		 * suspend too fast to complete a_set_b_hnp_en
 		 */
-		if (!fsm->a_bus_req || fsm->a_suspend_req)
-			otg_add_timer(fsm, a_wait_enum_tmr);
+		if (!fsm->a_bus_req || fsm->a_suspend_req_inf)
+			otg_add_timer(fsm, A_WAIT_ENUM);
 		break;
 	case OTG_STATE_A_SUSPEND:
 		otg_drv_vbus(fsm, 1);
 		otg_loc_conn(fsm, 0);
 		otg_loc_sof(fsm, 0);
 		otg_set_protocol(fsm, PROTO_HOST);
-		otg_add_timer(fsm, a_aidl_bdis_tmr);
+		otg_add_timer(fsm, A_AIDL_BDIS);
 
 		break;
 	case OTG_STATE_A_PERIPHERAL:
@@ -204,12 +218,14 @@
 		otg_loc_sof(fsm, 0);
 		otg_set_protocol(fsm, PROTO_GADGET);
 		otg_drv_vbus(fsm, 1);
+		otg_add_timer(fsm, A_BIDL_ADIS);
 		break;
 	case OTG_STATE_A_WAIT_VFALL:
 		otg_drv_vbus(fsm, 0);
 		otg_loc_conn(fsm, 0);
 		otg_loc_sof(fsm, 0);
 		otg_set_protocol(fsm, PROTO_HOST);
+		otg_add_timer(fsm, A_WAIT_VFALL);
 		break;
 	case OTG_STATE_A_VBUS_ERR:
 		otg_drv_vbus(fsm, 0);
@@ -250,7 +266,8 @@
 			otg_set_state(fsm, OTG_STATE_A_IDLE);
 		else if (fsm->b_sess_vld && fsm->otg->gadget)
 			otg_set_state(fsm, OTG_STATE_B_PERIPHERAL);
-		else if (fsm->b_bus_req && fsm->b_sess_end && fsm->b_se0_srp)
+		else if ((fsm->b_bus_req || fsm->adp_change || fsm->power_up) &&
+				fsm->b_ssend_srp && fsm->b_se0_srp)
 			otg_set_state(fsm, OTG_STATE_B_SRP_INIT);
 		break;
 	case OTG_STATE_B_SRP_INIT:
@@ -277,13 +294,14 @@
 	case OTG_STATE_B_HOST:
 		if (!fsm->id || !fsm->b_sess_vld)
 			otg_set_state(fsm, OTG_STATE_B_IDLE);
-		else if (!fsm->b_bus_req || !fsm->a_conn)
+		else if (!fsm->b_bus_req || !fsm->a_conn || fsm->test_device)
 			otg_set_state(fsm, OTG_STATE_B_PERIPHERAL);
 		break;
 	case OTG_STATE_A_IDLE:
 		if (fsm->id)
 			otg_set_state(fsm, OTG_STATE_B_IDLE);
-		else if (!fsm->a_bus_drop && (fsm->a_bus_req || fsm->a_srp_det))
+		else if (!fsm->a_bus_drop && (fsm->a_bus_req ||
+			  fsm->a_srp_det || fsm->adp_change || fsm->power_up))
 			otg_set_state(fsm, OTG_STATE_A_WAIT_VRISE);
 		break;
 	case OTG_STATE_A_WAIT_VRISE:
@@ -301,7 +319,7 @@
 			otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
 		break;
 	case OTG_STATE_A_HOST:
-		if ((!fsm->a_bus_req || fsm->a_suspend_req) &&
+		if ((!fsm->a_bus_req || fsm->a_suspend_req_inf) &&
 				fsm->otg->host->b_hnp_enable)
 			otg_set_state(fsm, OTG_STATE_A_SUSPEND);
 		else if (fsm->id || !fsm->b_conn || fsm->a_bus_drop)
@@ -324,14 +342,14 @@
 	case OTG_STATE_A_PERIPHERAL:
 		if (fsm->id || fsm->a_bus_drop)
 			otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
-		else if (fsm->b_bus_suspend)
+		else if (fsm->a_bidl_adis_tmout || fsm->b_bus_suspend)
 			otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
 		else if (!fsm->a_vbus_vld)
 			otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
 		break;
 	case OTG_STATE_A_WAIT_VFALL:
-		if (fsm->id || fsm->a_bus_req || (!fsm->a_sess_vld &&
-					!fsm->b_conn))
+		if (fsm->a_wait_vfall_tmout || fsm->id || fsm->a_bus_req ||
+				(!fsm->a_sess_vld && !fsm->b_conn))
 			otg_set_state(fsm, OTG_STATE_A_IDLE);
 		break;
 	case OTG_STATE_A_VBUS_ERR:
diff --git a/drivers/usb/phy/phy-fsm-usb.h b/drivers/usb/phy/phy-fsm-usb.h
index fbe5862..7441b46 100644
--- a/drivers/usb/phy/phy-fsm-usb.h
+++ b/drivers/usb/phy/phy-fsm-usb.h
@@ -34,45 +34,76 @@
 #define PROTO_HOST	(1)
 #define PROTO_GADGET	(2)
 
+enum otg_fsm_timer {
+	/* Standard OTG timers */
+	A_WAIT_VRISE,
+	A_WAIT_VFALL,
+	A_WAIT_BCON,
+	A_AIDL_BDIS,
+	B_ASE0_BRST,
+	A_BIDL_ADIS,
+
+	/* Auxiliary timers */
+	B_SE0_SRP,
+	B_SRP_FAIL,
+	A_WAIT_ENUM,
+
+	NUM_OTG_FSM_TIMERS,
+};
+
 /* OTG state machine according to the OTG spec */
 struct otg_fsm {
 	/* Input */
+	int id;
+	int adp_change;
+	int power_up;
+	int test_device;
+	int a_bus_drop;
+	int a_bus_req;
+	int a_srp_det;
+	int a_vbus_vld;
+	int b_conn;
 	int a_bus_resume;
 	int a_bus_suspend;
 	int a_conn;
+	int b_bus_req;
+	int b_se0_srp;
+	int b_ssend_srp;
+	int b_sess_vld;
+	/* Auxilary inputs */
 	int a_sess_vld;
-	int a_srp_det;
-	int a_vbus_vld;
 	int b_bus_resume;
 	int b_bus_suspend;
-	int b_conn;
-	int b_se0_srp;
-	int b_sess_end;
-	int b_sess_vld;
-	int id;
+
+	/* Output */
+	int data_pulse;
+	int drv_vbus;
+	int loc_conn;
+	int loc_sof;
+	int adp_prb;
+	int adp_sns;
 
 	/* Internal variables */
 	int a_set_b_hnp_en;
 	int b_srp_done;
 	int b_hnp_enable;
+	int a_clr_err;
+
+	/* Informative variables */
+	int a_bus_drop_inf;
+	int a_bus_req_inf;
+	int a_clr_err_inf;
+	int b_bus_req_inf;
+	/* Auxilary informative variables */
+	int a_suspend_req_inf;
 
 	/* Timeout indicator for timers */
 	int a_wait_vrise_tmout;
+	int a_wait_vfall_tmout;
 	int a_wait_bcon_tmout;
 	int a_aidl_bdis_tmout;
 	int b_ase0_brst_tmout;
-
-	/* Informative variables */
-	int a_bus_drop;
-	int a_bus_req;
-	int a_clr_err;
-	int a_suspend_req;
-	int b_bus_req;
-
-	/* Output */
-	int drv_vbus;
-	int loc_conn;
-	int loc_sof;
+	int a_bidl_adis_tmout;
 
 	struct otg_fsm_ops *ops;
 	struct usb_otg *otg;
@@ -83,65 +114,123 @@
 };
 
 struct otg_fsm_ops {
-	void	(*chrg_vbus)(int on);
-	void	(*drv_vbus)(int on);
-	void	(*loc_conn)(int on);
-	void	(*loc_sof)(int on);
-	void	(*start_pulse)(void);
-	void	(*add_timer)(void *timer);
-	void	(*del_timer)(void *timer);
+	void	(*chrg_vbus)(struct otg_fsm *fsm, int on);
+	void	(*drv_vbus)(struct otg_fsm *fsm, int on);
+	void	(*loc_conn)(struct otg_fsm *fsm, int on);
+	void	(*loc_sof)(struct otg_fsm *fsm, int on);
+	void	(*start_pulse)(struct otg_fsm *fsm);
+	void	(*start_adp_prb)(struct otg_fsm *fsm);
+	void	(*start_adp_sns)(struct otg_fsm *fsm);
+	void	(*add_timer)(struct otg_fsm *fsm, enum otg_fsm_timer timer);
+	void	(*del_timer)(struct otg_fsm *fsm, enum otg_fsm_timer timer);
 	int	(*start_host)(struct otg_fsm *fsm, int on);
 	int	(*start_gadget)(struct otg_fsm *fsm, int on);
 };
 
 
-static inline void otg_chrg_vbus(struct otg_fsm *fsm, int on)
+static inline int otg_chrg_vbus(struct otg_fsm *fsm, int on)
 {
-	fsm->ops->chrg_vbus(on);
+	if (!fsm->ops->chrg_vbus)
+		return -EOPNOTSUPP;
+	fsm->ops->chrg_vbus(fsm, on);
+	return 0;
 }
 
-static inline void otg_drv_vbus(struct otg_fsm *fsm, int on)
+static inline int otg_drv_vbus(struct otg_fsm *fsm, int on)
 {
+	if (!fsm->ops->drv_vbus)
+		return -EOPNOTSUPP;
 	if (fsm->drv_vbus != on) {
 		fsm->drv_vbus = on;
-		fsm->ops->drv_vbus(on);
+		fsm->ops->drv_vbus(fsm, on);
 	}
+	return 0;
 }
 
-static inline void otg_loc_conn(struct otg_fsm *fsm, int on)
+static inline int otg_loc_conn(struct otg_fsm *fsm, int on)
 {
+	if (!fsm->ops->loc_conn)
+		return -EOPNOTSUPP;
 	if (fsm->loc_conn != on) {
 		fsm->loc_conn = on;
-		fsm->ops->loc_conn(on);
+		fsm->ops->loc_conn(fsm, on);
 	}
+	return 0;
 }
 
-static inline void otg_loc_sof(struct otg_fsm *fsm, int on)
+static inline int otg_loc_sof(struct otg_fsm *fsm, int on)
 {
+	if (!fsm->ops->loc_sof)
+		return -EOPNOTSUPP;
 	if (fsm->loc_sof != on) {
 		fsm->loc_sof = on;
-		fsm->ops->loc_sof(on);
+		fsm->ops->loc_sof(fsm, on);
 	}
+	return 0;
 }
 
-static inline void otg_start_pulse(struct otg_fsm *fsm)
+static inline int otg_start_pulse(struct otg_fsm *fsm)
 {
-	fsm->ops->start_pulse();
+	if (!fsm->ops->start_pulse)
+		return -EOPNOTSUPP;
+	if (!fsm->data_pulse) {
+		fsm->data_pulse = 1;
+		fsm->ops->start_pulse(fsm);
+	}
+	return 0;
 }
 
-static inline void otg_add_timer(struct otg_fsm *fsm, void *timer)
+static inline int otg_start_adp_prb(struct otg_fsm *fsm)
 {
-	fsm->ops->add_timer(timer);
+	if (!fsm->ops->start_adp_prb)
+		return -EOPNOTSUPP;
+	if (!fsm->adp_prb) {
+		fsm->adp_sns = 0;
+		fsm->adp_prb = 1;
+		fsm->ops->start_adp_prb(fsm);
+	}
+	return 0;
 }
 
-static inline void otg_del_timer(struct otg_fsm *fsm, void *timer)
+static inline int otg_start_adp_sns(struct otg_fsm *fsm)
 {
-	fsm->ops->del_timer(timer);
+	if (!fsm->ops->start_adp_sns)
+		return -EOPNOTSUPP;
+	if (!fsm->adp_sns) {
+		fsm->adp_sns = 1;
+		fsm->ops->start_adp_sns(fsm);
+	}
+	return 0;
+}
+
+static inline int otg_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer timer)
+{
+	if (!fsm->ops->add_timer)
+		return -EOPNOTSUPP;
+	fsm->ops->add_timer(fsm, timer);
+	return 0;
+}
+
+static inline int otg_del_timer(struct otg_fsm *fsm, enum otg_fsm_timer timer)
+{
+	if (!fsm->ops->del_timer)
+		return -EOPNOTSUPP;
+	fsm->ops->del_timer(fsm, timer);
+	return 0;
+}
+
+static inline int otg_start_host(struct otg_fsm *fsm, int on)
+{
+	if (!fsm->ops->start_host)
+		return -EOPNOTSUPP;
+	return fsm->ops->start_host(fsm, on);
+}
+
+static inline int otg_start_gadget(struct otg_fsm *fsm, int on)
+{
+	if (!fsm->ops->start_gadget)
+		return -EOPNOTSUPP;
+	return fsm->ops->start_gadget(fsm, on);
 }
 
 int otg_statemachine(struct otg_fsm *fsm);
-
-/* Defined by device specific driver, for different timer implementation */
-extern struct fsl_otg_timer *a_wait_vrise_tmr, *a_wait_bcon_tmr,
-	*a_aidl_bdis_tmr, *b_ase0_brst_tmr, *b_se0_srp_tmr, *b_srp_fail_tmr,
-	*a_wait_enum_tmr;
diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
index efe59f3..fce3a9e 100644
--- a/drivers/usb/phy/phy-generic.c
+++ b/drivers/usb/phy/phy-generic.c
@@ -35,6 +35,9 @@
 #include <linux/clk.h>
 #include <linux/regulator/consumer.h>
 #include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
 
 #include "phy-generic.h"
 
@@ -64,6 +67,23 @@
 	return 0;
 }
 
+static void nop_reset_set(struct usb_phy_gen_xceiv *nop, int asserted)
+{
+	int value;
+
+	if (!gpio_is_valid(nop->gpio_reset))
+		return;
+
+	value = asserted;
+	if (nop->reset_active_low)
+		value = !value;
+
+	gpio_set_value_cansleep(nop->gpio_reset, value);
+
+	if (!asserted)
+		usleep_range(10000, 20000);
+}
+
 int usb_gen_phy_init(struct usb_phy *phy)
 {
 	struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev);
@@ -74,13 +94,10 @@
 	}
 
 	if (!IS_ERR(nop->clk))
-		clk_enable(nop->clk);
+		clk_prepare_enable(nop->clk);
 
-	if (!IS_ERR(nop->reset)) {
-		/* De-assert RESET */
-		if (regulator_enable(nop->reset))
-			dev_err(phy->dev, "Failed to de-assert reset\n");
-	}
+	/* De-assert RESET */
+	nop_reset_set(nop, 0);
 
 	return 0;
 }
@@ -90,14 +107,11 @@
 {
 	struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev);
 
-	if (!IS_ERR(nop->reset)) {
-		/* Assert RESET */
-		if (regulator_disable(nop->reset))
-			dev_err(phy->dev, "Failed to assert reset\n");
-	}
+	/* Assert RESET */
+	nop_reset_set(nop, 1);
 
 	if (!IS_ERR(nop->clk))
-		clk_disable(nop->clk);
+		clk_disable_unprepare(nop->clk);
 
 	if (!IS_ERR(nop->vcc)) {
 		if (regulator_disable(nop->vcc))
@@ -136,8 +150,7 @@
 }
 
 int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
-		enum usb_phy_type type, u32 clk_rate, bool needs_vcc,
-		bool needs_reset)
+		enum usb_phy_type type, u32 clk_rate, bool needs_vcc)
 {
 	int err;
 
@@ -160,14 +173,6 @@
 		}
 	}
 
-	if (!IS_ERR(nop->clk)) {
-		err = clk_prepare(nop->clk);
-		if (err) {
-			dev_err(dev, "Error preparing clock\n");
-			return err;
-		}
-	}
-
 	nop->vcc = devm_regulator_get(dev, "vcc");
 	if (IS_ERR(nop->vcc)) {
 		dev_dbg(dev, "Error getting vcc regulator: %ld\n",
@@ -176,12 +181,22 @@
 			return -EPROBE_DEFER;
 	}
 
-	nop->reset = devm_regulator_get(dev, "reset");
-	if (IS_ERR(nop->reset)) {
-		dev_dbg(dev, "Error getting reset regulator: %ld\n",
-					PTR_ERR(nop->reset));
-		if (needs_reset)
-			return -EPROBE_DEFER;
+	if (gpio_is_valid(nop->gpio_reset)) {
+		unsigned long gpio_flags;
+
+		/* Assert RESET */
+		if (nop->reset_active_low)
+			gpio_flags = GPIOF_OUT_INIT_LOW;
+		else
+			gpio_flags = GPIOF_OUT_INIT_HIGH;
+
+		err = devm_gpio_request_one(dev, nop->gpio_reset,
+						gpio_flags, dev_name(dev));
+		if (err) {
+			dev_err(dev, "Error requesting RESET GPIO %d\n",
+					nop->gpio_reset);
+			return err;
+		}
 	}
 
 	nop->dev		= dev;
@@ -200,13 +215,6 @@
 }
 EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy);
 
-void usb_phy_gen_cleanup_phy(struct usb_phy_gen_xceiv *nop)
-{
-	if (!IS_ERR(nop->clk))
-		clk_unprepare(nop->clk);
-}
-EXPORT_SYMBOL_GPL(usb_phy_gen_cleanup_phy);
-
 static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -217,31 +225,36 @@
 	int err;
 	u32 clk_rate = 0;
 	bool needs_vcc = false;
-	bool needs_reset = false;
-
-	if (dev->of_node) {
-		struct device_node *node = dev->of_node;
-
-		if (of_property_read_u32(node, "clock-frequency", &clk_rate))
-			clk_rate = 0;
-
-		needs_vcc = of_property_read_bool(node, "vcc-supply");
-		needs_reset = of_property_read_bool(node, "reset-supply");
-
-	} else if (pdata) {
-		type = pdata->type;
-		clk_rate = pdata->clk_rate;
-		needs_vcc = pdata->needs_vcc;
-		needs_reset = pdata->needs_reset;
-	}
 
 	nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL);
 	if (!nop)
 		return -ENOMEM;
 
+	nop->reset_active_low = true;	/* default behaviour */
 
-	err = usb_phy_gen_create_phy(dev, nop, type, clk_rate, needs_vcc,
-			needs_reset);
+	if (dev->of_node) {
+		struct device_node *node = dev->of_node;
+		enum of_gpio_flags flags;
+
+		if (of_property_read_u32(node, "clock-frequency", &clk_rate))
+			clk_rate = 0;
+
+		needs_vcc = of_property_read_bool(node, "vcc-supply");
+		nop->gpio_reset = of_get_named_gpio_flags(node, "reset-gpios",
+								0, &flags);
+		if (nop->gpio_reset == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+
+		nop->reset_active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+	} else if (pdata) {
+		type = pdata->type;
+		clk_rate = pdata->clk_rate;
+		needs_vcc = pdata->needs_vcc;
+		nop->gpio_reset = pdata->gpio_reset;
+	}
+
+	err = usb_phy_gen_create_phy(dev, nop, type, clk_rate, needs_vcc);
 	if (err)
 		return err;
 
@@ -252,15 +265,13 @@
 	if (err) {
 		dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
 			err);
-		goto err_add;
+		return err;
 	}
 
 	platform_set_drvdata(pdev, nop);
 
 	return 0;
 
-err_add:
-	usb_phy_gen_cleanup_phy(nop);
 	return err;
 }
 
@@ -268,7 +279,6 @@
 {
 	struct usb_phy_gen_xceiv *nop = platform_get_drvdata(pdev);
 
-	usb_phy_gen_cleanup_phy(nop);
 	usb_remove_phy(&nop->phy);
 
 	return 0;
diff --git a/drivers/usb/phy/phy-generic.h b/drivers/usb/phy/phy-generic.h
index 61687d5..d2a220d 100644
--- a/drivers/usb/phy/phy-generic.h
+++ b/drivers/usb/phy/phy-generic.h
@@ -6,15 +6,14 @@
 	struct device *dev;
 	struct clk *clk;
 	struct regulator *vcc;
-	struct regulator *reset;
+	int gpio_reset;
+	bool reset_active_low;
 };
 
 int usb_gen_phy_init(struct usb_phy *phy);
 void usb_gen_phy_shutdown(struct usb_phy *phy);
 
 int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
-		enum usb_phy_type type, u32 clk_rate, bool needs_vcc,
-		bool needs_reset);
-void usb_phy_gen_cleanup_phy(struct usb_phy_gen_xceiv *nop);
+		enum usb_phy_type type, u32 clk_rate, bool needs_vcc);
 
 #endif
diff --git a/drivers/usb/phy/phy-omap-control.c b/drivers/usb/phy/phy-omap-control.c
index a4dda8e..09c5ace 100644
--- a/drivers/usb/phy/phy-omap-control.c
+++ b/drivers/usb/phy/phy-omap-control.c
@@ -20,69 +20,12 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/usb/omap_control_usb.h>
 
-static struct omap_control_usb *control_usb;
-
-/**
- * omap_get_control_dev - returns the device pointer for this control device
- *
- * This API should be called to get the device pointer for this control
- * module device. This device pointer should be used for called other
- * exported API's in this driver.
- *
- * To be used by PHY driver and glue driver.
- */
-struct device *omap_get_control_dev(void)
-{
-	if (!control_usb)
-		return ERR_PTR(-ENODEV);
-
-	return control_usb->dev;
-}
-EXPORT_SYMBOL_GPL(omap_get_control_dev);
-
-/**
- * omap_control_usb3_phy_power - power on/off the serializer using control
- *	module
- * @dev: the control module device
- * @on: 0 to off and 1 to on based on powering on or off the PHY
- *
- * usb3 PHY driver should call this API to power on or off the PHY.
- */
-void omap_control_usb3_phy_power(struct device *dev, bool on)
-{
-	u32 val;
-	unsigned long rate;
-	struct omap_control_usb	*control_usb = dev_get_drvdata(dev);
-
-	if (control_usb->type != OMAP_CTRL_DEV_TYPE2)
-		return;
-
-	rate = clk_get_rate(control_usb->sys_clk);
-	rate = rate/1000000;
-
-	val = readl(control_usb->phy_power);
-
-	if (on) {
-		val &= ~(OMAP_CTRL_USB_PWRCTL_CLK_CMD_MASK |
-			OMAP_CTRL_USB_PWRCTL_CLK_FREQ_MASK);
-		val |= OMAP_CTRL_USB3_PHY_TX_RX_POWERON <<
-			OMAP_CTRL_USB_PWRCTL_CLK_CMD_SHIFT;
-		val |= rate << OMAP_CTRL_USB_PWRCTL_CLK_FREQ_SHIFT;
-	} else {
-		val &= ~OMAP_CTRL_USB_PWRCTL_CLK_CMD_MASK;
-		val |= OMAP_CTRL_USB3_PHY_TX_RX_POWEROFF <<
-			OMAP_CTRL_USB_PWRCTL_CLK_CMD_SHIFT;
-	}
-
-	writel(val, control_usb->phy_power);
-}
-EXPORT_SYMBOL_GPL(omap_control_usb3_phy_power);
-
 /**
  * omap_control_usb_phy_power - power on/off the phy using control module reg
  * @dev: the control module device
@@ -91,16 +34,63 @@
 void omap_control_usb_phy_power(struct device *dev, int on)
 {
 	u32 val;
-	struct omap_control_usb	*control_usb = dev_get_drvdata(dev);
+	unsigned long rate;
+	struct omap_control_usb	*control_usb;
 
-	val = readl(control_usb->dev_conf);
+	if (IS_ERR(dev) || !dev) {
+		pr_err("%s: invalid device\n", __func__);
+		return;
+	}
 
-	if (on)
-		val &= ~OMAP_CTRL_DEV_PHY_PD;
-	else
-		val |= OMAP_CTRL_DEV_PHY_PD;
+	control_usb = dev_get_drvdata(dev);
+	if (!control_usb) {
+		dev_err(dev, "%s: invalid control usb device\n", __func__);
+		return;
+	}
 
-	writel(val, control_usb->dev_conf);
+	if (control_usb->type == OMAP_CTRL_TYPE_OTGHS)
+		return;
+
+	val = readl(control_usb->power);
+
+	switch (control_usb->type) {
+	case OMAP_CTRL_TYPE_USB2:
+		if (on)
+			val &= ~OMAP_CTRL_DEV_PHY_PD;
+		else
+			val |= OMAP_CTRL_DEV_PHY_PD;
+		break;
+
+	case OMAP_CTRL_TYPE_PIPE3:
+		rate = clk_get_rate(control_usb->sys_clk);
+		rate = rate/1000000;
+
+		if (on) {
+			val &= ~(OMAP_CTRL_USB_PWRCTL_CLK_CMD_MASK |
+					OMAP_CTRL_USB_PWRCTL_CLK_FREQ_MASK);
+			val |= OMAP_CTRL_USB3_PHY_TX_RX_POWERON <<
+				OMAP_CTRL_USB_PWRCTL_CLK_CMD_SHIFT;
+			val |= rate << OMAP_CTRL_USB_PWRCTL_CLK_FREQ_SHIFT;
+		} else {
+			val &= ~OMAP_CTRL_USB_PWRCTL_CLK_CMD_MASK;
+			val |= OMAP_CTRL_USB3_PHY_TX_RX_POWEROFF <<
+				OMAP_CTRL_USB_PWRCTL_CLK_CMD_SHIFT;
+		}
+		break;
+
+	case OMAP_CTRL_TYPE_DRA7USB2:
+		if (on)
+			val &= ~OMAP_CTRL_USB2_PHY_PD;
+		else
+			val |= OMAP_CTRL_USB2_PHY_PD;
+		break;
+	default:
+		dev_err(dev, "%s: type %d not recognized\n",
+					__func__, control_usb->type);
+		break;
+	}
+
+	writel(val, control_usb->power);
 }
 EXPORT_SYMBOL_GPL(omap_control_usb_phy_power);
 
@@ -172,11 +162,19 @@
 {
 	struct omap_control_usb	*ctrl_usb;
 
-	if (IS_ERR(dev) || control_usb->type != OMAP_CTRL_DEV_TYPE1)
+	if (IS_ERR(dev) || !dev)
 		return;
 
 	ctrl_usb = dev_get_drvdata(dev);
 
+	if (!ctrl_usb) {
+		dev_err(dev, "Invalid control usb device\n");
+		return;
+	}
+
+	if (ctrl_usb->type != OMAP_CTRL_TYPE_OTGHS)
+		return;
+
 	switch (mode) {
 	case USB_MODE_HOST:
 		omap_control_usb_host_mode(ctrl_usb);
@@ -193,12 +191,46 @@
 }
 EXPORT_SYMBOL_GPL(omap_control_usb_set_mode);
 
+#ifdef CONFIG_OF
+
+static const enum omap_control_usb_type otghs_data = OMAP_CTRL_TYPE_OTGHS;
+static const enum omap_control_usb_type usb2_data = OMAP_CTRL_TYPE_USB2;
+static const enum omap_control_usb_type pipe3_data = OMAP_CTRL_TYPE_PIPE3;
+static const enum omap_control_usb_type dra7usb2_data = OMAP_CTRL_TYPE_DRA7USB2;
+
+static const struct of_device_id omap_control_usb_id_table[] = {
+	{
+		.compatible = "ti,control-phy-otghs",
+		.data = &otghs_data,
+	},
+	{
+		.compatible = "ti,control-phy-usb2",
+		.data = &usb2_data,
+	},
+	{
+		.compatible = "ti,control-phy-pipe3",
+		.data = &pipe3_data,
+	},
+	{
+		.compatible = "ti,control-phy-dra7usb2",
+		.data = &dra7usb2_data,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, omap_control_usb_id_table);
+#endif
+
+
 static int omap_control_usb_probe(struct platform_device *pdev)
 {
 	struct resource	*res;
-	struct device_node *np = pdev->dev.of_node;
-	struct omap_control_usb_platform_data *pdata =
-			dev_get_platdata(&pdev->dev);
+	const struct of_device_id *of_id;
+	struct omap_control_usb *control_usb;
+
+	of_id = of_match_device(of_match_ptr(omap_control_usb_id_table),
+								&pdev->dev);
+	if (!of_id)
+		return -EINVAL;
 
 	control_usb = devm_kzalloc(&pdev->dev, sizeof(*control_usb),
 		GFP_KERNEL);
@@ -207,40 +239,27 @@
 		return -ENOMEM;
 	}
 
-	if (np) {
-		of_property_read_u32(np, "ti,type", &control_usb->type);
-	} else if (pdata) {
-		control_usb->type = pdata->type;
-	} else {
-		dev_err(&pdev->dev, "no pdata present\n");
-		return -EINVAL;
-	}
+	control_usb->dev = &pdev->dev;
+	control_usb->type = *(enum omap_control_usb_type *)of_id->data;
 
-	control_usb->dev	= &pdev->dev;
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-		"control_dev_conf");
-	control_usb->dev_conf = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(control_usb->dev_conf))
-		return PTR_ERR(control_usb->dev_conf);
-
-	if (control_usb->type == OMAP_CTRL_DEV_TYPE1) {
+	if (control_usb->type == OMAP_CTRL_TYPE_OTGHS) {
 		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 			"otghs_control");
 		control_usb->otghs_control = devm_ioremap_resource(
 			&pdev->dev, res);
 		if (IS_ERR(control_usb->otghs_control))
 			return PTR_ERR(control_usb->otghs_control);
+	} else {
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+				"power");
+		control_usb->power = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(control_usb->power)) {
+			dev_err(&pdev->dev, "Couldn't get power register\n");
+			return PTR_ERR(control_usb->power);
+		}
 	}
 
-	if (control_usb->type == OMAP_CTRL_DEV_TYPE2) {
-		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-			"phy_power_usb");
-		control_usb->phy_power = devm_ioremap_resource(
-			&pdev->dev, res);
-		if (IS_ERR(control_usb->phy_power))
-			return PTR_ERR(control_usb->phy_power);
-
+	if (control_usb->type == OMAP_CTRL_TYPE_PIPE3) {
 		control_usb->sys_clk = devm_clk_get(control_usb->dev,
 			"sys_clkin");
 		if (IS_ERR(control_usb->sys_clk)) {
@@ -249,20 +268,11 @@
 		}
 	}
 
-
 	dev_set_drvdata(control_usb->dev, control_usb);
 
 	return 0;
 }
 
-#ifdef CONFIG_OF
-static const struct of_device_id omap_control_usb_id_table[] = {
-	{ .compatible = "ti,omap-control-usb" },
-	{}
-};
-MODULE_DEVICE_TABLE(of, omap_control_usb_id_table);
-#endif
-
 static struct platform_driver omap_control_usb_driver = {
 	.probe		= omap_control_usb_probe,
 	.driver		= {
diff --git a/drivers/usb/phy/phy-omap-usb3.c b/drivers/usb/phy/phy-omap-usb3.c
index 4e8a040..0c6ba29 100644
--- a/drivers/usb/phy/phy-omap-usb3.c
+++ b/drivers/usb/phy/phy-omap-usb3.c
@@ -26,6 +26,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/delay.h>
 #include <linux/usb/omap_control_usb.h>
+#include <linux/of_platform.h>
 
 #define	PLL_STATUS		0x00000004
 #define	PLL_GO			0x00000008
@@ -100,7 +101,7 @@
 			udelay(1);
 		} while (--timeout);
 
-		omap_control_usb3_phy_power(phy->control_dev, 0);
+		omap_control_usb_phy_power(phy->control_dev, 0);
 
 		phy->is_suspended	= 1;
 	} else if (!suspend && phy->is_suspended) {
@@ -189,15 +190,21 @@
 	if (ret)
 		return ret;
 
-	omap_control_usb3_phy_power(phy->control_dev, 1);
+	omap_control_usb_phy_power(phy->control_dev, 1);
 
 	return 0;
 }
 
 static int omap_usb3_probe(struct platform_device *pdev)
 {
-	struct omap_usb			*phy;
-	struct resource			*res;
+	struct omap_usb *phy;
+	struct resource *res;
+	struct device_node *node = pdev->dev.of_node;
+	struct device_node *control_node;
+	struct platform_device *control_pdev;
+
+	if (!node)
+		return -EINVAL;
 
 	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
 	if (!phy) {
@@ -239,13 +246,20 @@
 		return -EINVAL;
 	}
 
-	phy->control_dev = omap_get_control_dev();
-	if (IS_ERR(phy->control_dev)) {
-		dev_dbg(&pdev->dev, "Failed to get control device\n");
-		return -ENODEV;
+	control_node = of_parse_phandle(node, "ctrl-module", 0);
+	if (!control_node) {
+		dev_err(&pdev->dev, "Failed to get control device phandle\n");
+		return -EINVAL;
+	}
+	control_pdev = of_find_device_by_node(control_node);
+	if (!control_pdev) {
+		dev_err(&pdev->dev, "Failed to get control device\n");
+		return -EINVAL;
 	}
 
-	omap_control_usb3_phy_power(phy->control_dev, 0);
+	phy->control_dev = &control_pdev->dev;
+
+	omap_control_usb_phy_power(phy->control_dev, 0);
 	usb_add_phy_dev(&phy->phy);
 
 	platform_set_drvdata(pdev, phy);
diff --git a/drivers/usb/phy/phy-rcar-gen2-usb.c b/drivers/usb/phy/phy-rcar-gen2-usb.c
new file mode 100644
index 0000000..a99a695
--- /dev/null
+++ b/drivers/usb/phy/phy-rcar-gen2-usb.c
@@ -0,0 +1,248 @@
+/*
+ * Renesas R-Car Gen2 USB phy driver
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Cogent Embedded, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_data/usb-rcar-gen2-phy.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/usb/otg.h>
+
+struct rcar_gen2_usb_phy_priv {
+	struct usb_phy phy;
+	void __iomem *base;
+	struct clk *clk;
+	spinlock_t lock;
+	int usecount;
+	u32 ugctrl2;
+};
+
+#define usb_phy_to_priv(p) container_of(p, struct rcar_gen2_usb_phy_priv, phy)
+
+/* Low Power Status register */
+#define USBHS_LPSTS_REG			0x02
+#define USBHS_LPSTS_SUSPM		(1 << 14)
+
+/* USB General control register */
+#define USBHS_UGCTRL_REG		0x80
+#define USBHS_UGCTRL_CONNECT		(1 << 2)
+#define USBHS_UGCTRL_PLLRESET		(1 << 0)
+
+/* USB General control register 2 */
+#define USBHS_UGCTRL2_REG		0x84
+#define USBHS_UGCTRL2_USB0_PCI		(1 << 4)
+#define USBHS_UGCTRL2_USB0_HS		(3 << 4)
+#define USBHS_UGCTRL2_USB2_PCI		(0 << 31)
+#define USBHS_UGCTRL2_USB2_SS		(1 << 31)
+
+/* USB General status register */
+#define USBHS_UGSTS_REG			0x88
+#define USBHS_UGSTS_LOCK		(3 << 8)
+
+/* Enable USBHS internal phy */
+static int __rcar_gen2_usbhs_phy_enable(void __iomem *base)
+{
+	u32 val;
+	int i;
+
+	/* USBHS PHY power on */
+	val = ioread32(base + USBHS_UGCTRL_REG);
+	val &= ~USBHS_UGCTRL_PLLRESET;
+	iowrite32(val, base + USBHS_UGCTRL_REG);
+
+	val = ioread16(base + USBHS_LPSTS_REG);
+	val |= USBHS_LPSTS_SUSPM;
+	iowrite16(val, base + USBHS_LPSTS_REG);
+
+	for (i = 0; i < 20; i++) {
+		val = ioread32(base + USBHS_UGSTS_REG);
+		if ((val & USBHS_UGSTS_LOCK) == USBHS_UGSTS_LOCK) {
+			val = ioread32(base + USBHS_UGCTRL_REG);
+			val |= USBHS_UGCTRL_CONNECT;
+			iowrite32(val, base + USBHS_UGCTRL_REG);
+			return 0;
+		}
+		udelay(1);
+	}
+
+	/* Timed out waiting for the PLL lock */
+	return -ETIMEDOUT;
+}
+
+/* Disable USBHS internal phy */
+static int __rcar_gen2_usbhs_phy_disable(void __iomem *base)
+{
+	u32 val;
+
+	/* USBHS PHY power off */
+	val = ioread32(base + USBHS_UGCTRL_REG);
+	val &= ~USBHS_UGCTRL_CONNECT;
+	iowrite32(val, base + USBHS_UGCTRL_REG);
+
+	val = ioread16(base + USBHS_LPSTS_REG);
+	val &= ~USBHS_LPSTS_SUSPM;
+	iowrite16(val, base + USBHS_LPSTS_REG);
+
+	val = ioread32(base + USBHS_UGCTRL_REG);
+	val |= USBHS_UGCTRL_PLLRESET;
+	iowrite32(val, base + USBHS_UGCTRL_REG);
+	return 0;
+}
+
+/* Setup USB channels */
+static void __rcar_gen2_usb_phy_init(struct rcar_gen2_usb_phy_priv *priv)
+{
+	u32 val;
+
+	clk_prepare_enable(priv->clk);
+
+	/* Set USB channels in the USBHS UGCTRL2 register */
+	val = ioread32(priv->base);
+	val &= ~(USBHS_UGCTRL2_USB0_HS | USBHS_UGCTRL2_USB2_SS);
+	val |= priv->ugctrl2;
+	iowrite32(val, priv->base);
+}
+
+/* Shutdown USB channels */
+static void __rcar_gen2_usb_phy_shutdown(struct rcar_gen2_usb_phy_priv *priv)
+{
+	__rcar_gen2_usbhs_phy_disable(priv->base);
+	clk_disable_unprepare(priv->clk);
+}
+
+static int rcar_gen2_usb_phy_set_suspend(struct usb_phy *phy, int suspend)
+{
+	struct rcar_gen2_usb_phy_priv *priv = usb_phy_to_priv(phy);
+	unsigned long flags;
+	int retval;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	retval = suspend ? __rcar_gen2_usbhs_phy_disable(priv->base) :
+			   __rcar_gen2_usbhs_phy_enable(priv->base);
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return retval;
+}
+
+static int rcar_gen2_usb_phy_init(struct usb_phy *phy)
+{
+	struct rcar_gen2_usb_phy_priv *priv = usb_phy_to_priv(phy);
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	/*
+	 * Enable the clock and setup USB channels
+	 * if it's the first user
+	 */
+	if (!priv->usecount++)
+		__rcar_gen2_usb_phy_init(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return 0;
+}
+
+static void rcar_gen2_usb_phy_shutdown(struct usb_phy *phy)
+{
+	struct rcar_gen2_usb_phy_priv *priv = usb_phy_to_priv(phy);
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (!priv->usecount) {
+		dev_warn(phy->dev, "Trying to disable phy with 0 usecount\n");
+		goto out;
+	}
+
+	/* Disable everything if it's the last user */
+	if (!--priv->usecount)
+		__rcar_gen2_usb_phy_shutdown(priv);
+out:
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static int rcar_gen2_usb_phy_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct rcar_gen2_phy_platform_data *pdata;
+	struct rcar_gen2_usb_phy_priv *priv;
+	struct resource *res;
+	void __iomem *base;
+	struct clk *clk;
+	int retval;
+
+	pdata = dev_get_platdata(&pdev->dev);
+	if (!pdata) {
+		dev_err(dev, "No platform data\n");
+		return -EINVAL;
+	}
+
+	clk = devm_clk_get(&pdev->dev, "usbhs");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "Can't get the clock\n");
+		return PTR_ERR(clk);
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(dev, "Memory allocation failed\n");
+		return -ENOMEM;
+	}
+
+	spin_lock_init(&priv->lock);
+	priv->clk = clk;
+	priv->base = base;
+	priv->ugctrl2 = pdata->chan0_pci ?
+			USBHS_UGCTRL2_USB0_PCI : USBHS_UGCTRL2_USB0_HS;
+	priv->ugctrl2 |= pdata->chan2_pci ?
+			USBHS_UGCTRL2_USB2_PCI : USBHS_UGCTRL2_USB2_SS;
+	priv->phy.dev = dev;
+	priv->phy.label = dev_name(dev);
+	priv->phy.init = rcar_gen2_usb_phy_init;
+	priv->phy.shutdown = rcar_gen2_usb_phy_shutdown;
+	priv->phy.set_suspend = rcar_gen2_usb_phy_set_suspend;
+
+	retval = usb_add_phy(&priv->phy, USB_PHY_TYPE_USB2);
+	if (retval < 0) {
+		dev_err(dev, "Failed to add USB phy\n");
+		return retval;
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	return retval;
+}
+
+static int rcar_gen2_usb_phy_remove(struct platform_device *pdev)
+{
+	struct rcar_gen2_usb_phy_priv *priv = platform_get_drvdata(pdev);
+
+	usb_remove_phy(&priv->phy);
+
+	return 0;
+}
+
+static struct platform_driver rcar_gen2_usb_phy_driver = {
+	.driver = {
+		.name = "usb_phy_rcar_gen2",
+	},
+	.probe = rcar_gen2_usb_phy_probe,
+	.remove = rcar_gen2_usb_phy_remove,
+};
+
+module_platform_driver(rcar_gen2_usb_phy_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Renesas R-Car Gen2 USB phy");
+MODULE_AUTHOR("Valentine Barshak <valentine.barshak@cogentembedded.com>");
diff --git a/drivers/usb/phy/phy-samsung-usb2.c b/drivers/usb/phy/phy-samsung-usb2.c
index ff70e4b..b3ba866 100644
--- a/drivers/usb/phy/phy-samsung-usb2.c
+++ b/drivers/usb/phy/phy-samsung-usb2.c
@@ -411,6 +411,7 @@
 	sphy->drv_data		= drv_data;
 	sphy->phy.dev		= sphy->dev;
 	sphy->phy.label		= "samsung-usb2phy";
+	sphy->phy.type		= USB_PHY_TYPE_USB2;
 	sphy->phy.init		= samsung_usb2phy_init;
 	sphy->phy.shutdown	= samsung_usb2phy_shutdown;
 
@@ -426,7 +427,7 @@
 
 	platform_set_drvdata(pdev, sphy);
 
-	return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2);
+	return usb_add_phy_dev(&sphy->phy);
 }
 
 static int samsung_usb2phy_remove(struct platform_device *pdev)
diff --git a/drivers/usb/phy/phy-samsung-usb3.c b/drivers/usb/phy/phy-samsung-usb3.c
index c6eb222..cc08192 100644
--- a/drivers/usb/phy/phy-samsung-usb3.c
+++ b/drivers/usb/phy/phy-samsung-usb3.c
@@ -271,6 +271,7 @@
 	sphy->clk		= clk;
 	sphy->phy.dev		= sphy->dev;
 	sphy->phy.label		= "samsung-usb3phy";
+	sphy->phy.type		= USB_PHY_TYPE_USB3;
 	sphy->phy.init		= samsung_usb3phy_init;
 	sphy->phy.shutdown	= samsung_usb3phy_shutdown;
 	sphy->drv_data		= samsung_usbphy_get_driver_data(pdev);
@@ -283,7 +284,7 @@
 
 	platform_set_drvdata(pdev, sphy);
 
-	return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB3);
+	return usb_add_phy_dev(&sphy->phy);
 }
 
 static int samsung_usb3phy_remove(struct platform_device *pdev)
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index e9cb1cb..82232ac 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -1090,7 +1090,7 @@
 	.driver		= {
 		.name	= "tegra-phy",
 		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(tegra_usb_phy_id_table),
+		.of_match_table = tegra_usb_phy_id_table,
 	},
 };
 module_platform_driver(tegra_usb_phy_driver);
diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c
index 16dbc93..30e8a61 100644
--- a/drivers/usb/phy/phy-twl6030-usb.c
+++ b/drivers/usb/phy/phy-twl6030-usb.c
@@ -33,6 +33,7 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/of.h>
 
 /* usb register definitions */
 #define USB_VENDOR_ID_LSB		0x00
diff --git a/drivers/usb/phy/phy-ulpi-viewport.c b/drivers/usb/phy/phy-ulpi-viewport.c
index 7c22a539..18bb826 100644
--- a/drivers/usb/phy/phy-ulpi-viewport.c
+++ b/drivers/usb/phy/phy-ulpi-viewport.c
@@ -36,7 +36,7 @@
 			return 0;
 
 		udelay(1);
-	};
+	}
 
 	return -ETIMEDOUT;
 }
diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c
index a9984c7..1b74523 100644
--- a/drivers/usb/phy/phy.c
+++ b/drivers/usb/phy/phy.c
@@ -98,7 +98,7 @@
 
 	ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
 	if (!ptr)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	phy = usb_get_phy(type);
 	if (!IS_ERR(phy)) {
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 7814262..6e1b69d 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -279,7 +279,7 @@
 
 		old_rdtodo = priv->rdtodo;
 
-		if (old_rdtodo + size < old_rdtodo) {
+		if (old_rdtodo > SHRT_MAX - size) {
 			dev_dbg(dev, "To many bulk_in urbs to do.\n");
 			spin_unlock(&priv->lock);
 			goto resubmit;
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index c45f9c0..9ced893 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -904,6 +904,7 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) },
 	/* Crucible Devices */
 	{ USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_Z3X_PID) },
 	{ }					/* Terminating entry */
 };
 
@@ -1966,8 +1967,16 @@
 			port->icount.dsr++;
 		if (diff_status & FTDI_RS0_RI)
 			port->icount.rng++;
-		if (diff_status & FTDI_RS0_RLSD)
+		if (diff_status & FTDI_RS0_RLSD) {
+			struct tty_struct *tty;
+
 			port->icount.dcd++;
+			tty = tty_port_tty_get(&port->port);
+			if (tty)
+				usb_serial_handle_dcd_change(port, tty,
+						status & FTDI_RS0_RLSD);
+			tty_kref_put(tty);
+		}
 
 		wake_up_interruptible(&port->port.delta_msr_wait);
 		priv->prev_status = status;
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 1b8af46..a7019d1 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -1307,3 +1307,9 @@
  * Manufacturer: Crucible Technologies
  */
 #define FTDI_CT_COMET_PID	0x8e08
+
+/*
+ * Product: Z3X Box
+ * Manufacturer: Smart GSM Team
+ */
+#define FTDI_Z3X_PID		0x0011
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 1f31e6b..2b01ec8 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -7,7 +7,6 @@
  *	This program is free software; you can redistribute it 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>
@@ -37,7 +36,6 @@
 
 static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */
 
-/* All of the device info needed for the Generic Serial Converter */
 struct usb_serial_driver usb_serial_generic_device = {
 	.driver = {
 		.owner =	THIS_MODULE,
@@ -66,7 +64,6 @@
 	generic_device_ids[0].match_flags =
 		USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
 
-	/* register our generic driver with ourselves */
 	retval = usb_serial_register_drivers(serial_drivers,
 			"usbserial_generic", generic_device_ids);
 #endif
@@ -76,7 +73,6 @@
 void usb_serial_generic_deregister(void)
 {
 #ifdef CONFIG_USB_SERIAL_GENERIC
-	/* remove our generic driver */
 	usb_serial_deregister_drivers(serial_drivers);
 #endif
 }
@@ -86,13 +82,11 @@
 	int result = 0;
 	unsigned long flags;
 
-	/* clear the throttle flags */
 	spin_lock_irqsave(&port->lock, flags);
 	port->throttled = 0;
 	port->throttle_req = 0;
 	spin_unlock_irqrestore(&port->lock, flags);
 
-	/* if we have a bulk endpoint, start reading from it */
 	if (port->bulk_in_size)
 		result = usb_serial_generic_submit_read_urbs(port, GFP_KERNEL);
 
@@ -127,12 +121,16 @@
 }
 
 /**
- * usb_serial_generic_write_start - kick off an URB write
- * @port:	Pointer to the &struct usb_serial_port data
+ * usb_serial_generic_write_start - start writing buffered data
+ * @port: usb-serial port
+ * @mem_flags: flags to use for memory allocations
  *
- * Returns zero on success, or a negative errno value
+ * Serialised using USB_SERIAL_WRITE_BUSY flag.
+ *
+ * Return: Zero on success or if busy, otherwise a negative errno value.
  */
-static int usb_serial_generic_write_start(struct usb_serial_port *port)
+int usb_serial_generic_write_start(struct usb_serial_port *port,
+							gfp_t mem_flags)
 {
 	struct urb *urb;
 	int count, result;
@@ -163,7 +161,7 @@
 	spin_unlock_irqrestore(&port->lock, flags);
 
 	clear_bit(i, &port->write_urbs_free);
-	result = usb_submit_urb(urb, GFP_ATOMIC);
+	result = usb_submit_urb(urb, mem_flags);
 	if (result) {
 		dev_err_console(port, "%s - error submitting urb: %d\n",
 						__func__, result);
@@ -175,34 +173,34 @@
 		clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags);
 		return result;
 	}
-
-	/* Try sending off another urb, unless in irq context (in which case
-	 * there will be no free urb). */
-	if (!in_irq())
+	/*
+	 * Try sending off another urb, unless called from completion handler
+	 * (in which case there will be no free urb or no data).
+	 */
+	if (mem_flags != GFP_ATOMIC)
 		goto retry;
 
 	clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags);
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(usb_serial_generic_write_start);
 
 /**
- * usb_serial_generic_write - generic write function for serial USB devices
- * @tty:	Pointer to &struct tty_struct for the device
- * @port:	Pointer to the &usb_serial_port structure for the device
- * @buf:	Pointer to the data to write
- * @count:	Number of bytes to write
+ * usb_serial_generic_write - generic write function
+ * @tty: tty for the port
+ * @port: usb-serial port
+ * @buf: data to write
+ * @count: number of bytes to write
  *
- * Returns the number of characters actually written, which may be anything
- * from zero to @count. If an error occurs, it returns the negative errno
- * value.
+ * Return: The number of characters buffered, which may be anything from
+ * zero to @count, or a negative errno value.
  */
 int usb_serial_generic_write(struct tty_struct *tty,
 	struct usb_serial_port *port, const unsigned char *buf, int count)
 {
 	int result;
 
-	/* only do something if we have a bulk out endpoint */
 	if (!port->bulk_out_size)
 		return -ENODEV;
 
@@ -210,7 +208,7 @@
 		return 0;
 
 	count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock);
-	result = usb_serial_generic_write_start(port);
+	result = usb_serial_generic_write_start(port, GFP_KERNEL);
 	if (result)
 		return result;
 
@@ -337,10 +335,11 @@
 
 	if (!urb->actual_length)
 		return;
-
-	/* The per character mucking around with sysrq path it too slow for
-	   stuff like 3G modems, so shortcircuit it in the 99.9999999% of cases
-	   where the USB serial is not a console anyway */
+	/*
+	 * The per character mucking around with sysrq path it too slow for
+	 * stuff like 3G modems, so shortcircuit it in the 99.9999999% of
+	 * cases where the USB serial is not a console anyway.
+	 */
 	if (!port->port.console || !port->sysrq)
 		tty_insert_flip_string(&port->port, ch, urb->actual_length);
 	else {
@@ -413,7 +412,7 @@
 		kfifo_reset_out(&port->write_fifo);
 		spin_unlock_irqrestore(&port->lock, flags);
 	} else {
-		usb_serial_generic_write_start(port);
+		usb_serial_generic_write_start(port, GFP_ATOMIC);
 	}
 
 	usb_serial_port_softint(port);
@@ -425,8 +424,6 @@
 	struct usb_serial_port *port = tty->driver_data;
 	unsigned long flags;
 
-	/* Set the throttle request flag. It will be picked up
-	 * by usb_serial_generic_read_bulk_callback(). */
 	spin_lock_irqsave(&port->lock, flags);
 	port->throttle_req = 1;
 	spin_unlock_irqrestore(&port->lock, flags);
@@ -438,7 +435,6 @@
 	struct usb_serial_port *port = tty->driver_data;
 	int was_throttled;
 
-	/* Clear the throttle flags */
 	spin_lock_irq(&port->lock);
 	was_throttled = port->throttled;
 	port->throttled = port->throttle_req = 0;
@@ -558,10 +554,10 @@
 EXPORT_SYMBOL_GPL(usb_serial_handle_break);
 
 /**
- *	usb_serial_handle_dcd_change - handle a change of carrier detect state
- *	@port: usb_serial_port structure for the open port
- *	@tty: tty_struct structure for the port
- *	@status: new carrier detect status, nonzero if active
+ * usb_serial_handle_dcd_change - handle a change of carrier detect state
+ * @port: usb-serial port
+ * @tty: tty for the port
+ * @status: new carrier detect status, nonzero if active
  */
 void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port,
 				struct tty_struct *tty, unsigned int status)
@@ -570,6 +566,16 @@
 
 	dev_dbg(&usb_port->dev, "%s - status %d\n", __func__, status);
 
+	if (tty) {
+		struct tty_ldisc *ld = tty_ldisc_ref(tty);
+
+		if (ld) {
+			if (ld->ops->dcd_change)
+				ld->ops->dcd_change(tty, status);
+			tty_ldisc_deref(ld);
+		}
+	}
+
 	if (status)
 		wake_up_interruptible(&port->open_wait);
 	else if (tty && !C_CLOCAL(tty))
@@ -595,7 +601,7 @@
 		}
 
 		if (port->bulk_out_size) {
-			r = usb_serial_generic_write_start(port);
+			r = usb_serial_generic_write_start(port, GFP_NOIO);
 			if (r < 0)
 				c++;
 		}
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index fdf9535..e5bdd98 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -1532,7 +1532,11 @@
 		return -ENODEV;
 
 	status = mos7840_get_uart_reg(port, MODEM_STATUS_REGISTER, &msr);
+	if (status != 1)
+		return -EIO;
 	status = mos7840_get_uart_reg(port, MODEM_CONTROL_REGISTER, &mcr);
+	if (status != 1)
+		return -EIO;
 	result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0)
 	    | ((mcr & MCR_RTS) ? TIOCM_RTS : 0)
 	    | ((mcr & MCR_LOOPBACK) ? TIOCM_LOOP : 0)
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 80a7104..c3d9485 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -451,6 +451,10 @@
 #define CHANGHONG_VENDOR_ID			0x2077
 #define CHANGHONG_PRODUCT_CH690			0x7001
 
+/* Inovia */
+#define INOVIA_VENDOR_ID			0x20a6
+#define INOVIA_SEW858				0x1105
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
 		OPTION_BLACKLIST_NONE = 0,
@@ -689,6 +693,222 @@
 	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) },
 	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7B) },
 	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7C) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x01) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x02) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x03) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x04) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x05) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x06) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0D) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0E) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0F) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x10) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x12) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x13) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x14) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x15) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x17) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x18) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x19) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x1A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x1B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x1C) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x31) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x32) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x33) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x34) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x35) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x36) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3D) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3E) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3F) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x48) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x49) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x4A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x4B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x4C) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x61) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x62) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x63) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x64) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x65) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x66) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6D) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6E) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6F) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x78) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x79) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7C) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x01) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x02) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x03) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x04) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x05) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x06) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0D) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0E) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0F) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x10) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x12) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x13) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x14) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x15) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x17) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x18) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x19) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x1A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x1B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x1C) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x31) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x32) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x33) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x34) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x35) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x36) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3D) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3E) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3F) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x48) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x49) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x4A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x4B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x4C) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x61) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x62) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x63) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x64) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x65) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x66) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6D) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6E) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6F) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x78) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x79) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7C) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x01) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x02) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x03) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x04) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x05) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x06) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0D) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0E) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0F) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x10) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x12) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x13) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x14) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x15) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x17) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x18) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x19) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x1A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x1B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x1C) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x31) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x32) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x33) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x34) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x35) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x36) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3D) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3E) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3F) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x48) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x49) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x4A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x4B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x4C) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x61) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x62) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x63) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x64) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x65) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x66) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6D) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6E) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6F) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x78) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x79) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7C) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x01) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x02) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x03) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x04) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x05) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x06) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0D) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0E) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0F) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x10) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x12) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x13) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x14) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x15) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x17) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x18) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x19) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x1A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x1B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x1C) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x31) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x32) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x33) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x34) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x35) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x36) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3D) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3E) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3F) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x48) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x49) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x4A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x4B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x4C) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x61) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x62) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x63) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x64) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x65) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x66) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6D) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6E) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6F) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x78) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x79) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7A) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7B) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7C) },
 
 
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) },
@@ -1156,6 +1376,23 @@
 		.driver_info = (kernel_ulong_t)&net_intf2_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1426, 0xff, 0xff, 0xff),  /* ZTE MF91 */
 		.driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1533, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1534, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1535, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1545, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1546, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1547, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1565, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1566, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1567, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1589, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1590, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1591, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1592, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1594, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1596, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1598, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1600, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff,
 	  0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
@@ -1257,7 +1494,9 @@
 
 	{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
 	{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD145) },
-	{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD200) },
+	{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD200),
+		.driver_info = (kernel_ulong_t)&net_intf6_blacklist
+	},
 	{ USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
 	{ USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/
 	{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM600) },
@@ -1345,6 +1584,7 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */
+	{ USB_DEVICE(INOVIA_VENDOR_ID, INOVIA_SEW858) },
 	{ } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index bedf8e4..1e6de4c 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -4,11 +4,6 @@
  * Copyright (C) 2001-2007 Greg Kroah-Hartman (greg@kroah.com)
  * Copyright (C) 2003 IBM Corp.
  *
- * Copyright (C) 2009, 2013 Frank Schäfer <fschaefer.oss@googlemail.com>
- *  - fixes, improvements and documentation for the baud rate encoding methods
- * Copyright (C) 2013 Reinhard Max <max@suse.de>
- *  - fixes and improvements for the divisor based baud rate encoding method
- *
  * Original driver for 2.2.x by anonymous
  *
  *	This program is free software; you can redistribute it and/or
@@ -134,18 +129,10 @@
 
 
 enum pl2303_type {
-	type_0,		/* H version ? */
-	type_1,		/* H version ? */
-	HX_TA,		/* HX(A) / X(A) / TA version  */ /* TODO: improve */
-	HXD_EA_RA_SA,	/* HXD / EA / RA / SA version */ /* TODO: improve */
-	TB,		/* TB version */
-	HX_CLONE,	/* Cheap and less functional clone of the HX chip */
+	type_0,		/* don't know the difference between type 0 and */
+	type_1,		/* type 1, until someone from prolific tells us... */
+	HX,		/* HX version of the pl2303 chip */
 };
-/*
- * NOTE: don't know the difference between type 0 and type 1,
- * until someone from Prolific tells us...
- * TODO: distinguish between X/HX, TA and HXD, EA, RA, SA variants
- */
 
 struct pl2303_serial_private {
 	enum pl2303_type type;
@@ -185,7 +172,6 @@
 {
 	struct pl2303_serial_private *spriv;
 	enum pl2303_type type = type_0;
-	char *type_str = "unknown (treating as type_0)";
 	unsigned char *buf;
 
 	spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
@@ -198,53 +184,15 @@
 		return -ENOMEM;
 	}
 
-	if (serial->dev->descriptor.bDeviceClass == 0x02) {
+	if (serial->dev->descriptor.bDeviceClass == 0x02)
 		type = type_0;
-		type_str = "type_0";
-	} else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40) {
-		/*
-		 * NOTE: The bcdDevice version is the only difference between
-		 * the device descriptors of the X/HX, HXD, EA, RA, SA, TA, TB
-		 */
-		if (le16_to_cpu(serial->dev->descriptor.bcdDevice) == 0x300) {
-			/* Check if the device is a clone */
-			pl2303_vendor_read(0x9494, 0, serial, buf);
-			/*
-			 * NOTE: Not sure if this read is really needed.
-			 * The HX returns 0x00, the clone 0x02, but the Windows
-			 * driver seems to ignore the value and continues.
-			 */
-			pl2303_vendor_write(0x0606, 0xaa, serial);
-			pl2303_vendor_read(0x8686, 0, serial, buf);
-			if (buf[0] != 0xaa) {
-				type = HX_CLONE;
-				type_str = "X/HX clone (limited functionality)";
-			} else {
-				type = HX_TA;
-				type_str = "X/HX/TA";
-			}
-			pl2303_vendor_write(0x0606, 0x00, serial);
-		} else if (le16_to_cpu(serial->dev->descriptor.bcdDevice)
-								     == 0x400) {
-			type = HXD_EA_RA_SA;
-			type_str = "HXD/EA/RA/SA";
-		} else if (le16_to_cpu(serial->dev->descriptor.bcdDevice)
-								     == 0x500) {
-			type = TB;
-			type_str = "TB";
-		} else {
-			dev_info(&serial->interface->dev,
-					   "unknown/unsupported device type\n");
-			kfree(spriv);
-			kfree(buf);
-			return -ENODEV;
-		}
-	} else if (serial->dev->descriptor.bDeviceClass == 0x00
-		   || serial->dev->descriptor.bDeviceClass == 0xFF) {
+	else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40)
+		type = HX;
+	else if (serial->dev->descriptor.bDeviceClass == 0x00)
 		type = type_1;
-		type_str = "type_1";
-	}
-	dev_dbg(&serial->interface->dev, "device type: %s\n", type_str);
+	else if (serial->dev->descriptor.bDeviceClass == 0xFF)
+		type = type_1;
+	dev_dbg(&serial->interface->dev, "device type: %d\n", type);
 
 	spriv->type = type;
 	usb_set_serial_data(serial, spriv);
@@ -259,10 +207,10 @@
 	pl2303_vendor_read(0x8383, 0, serial, buf);
 	pl2303_vendor_write(0, 1, serial);
 	pl2303_vendor_write(1, 0, serial);
-	if (type == type_0 || type == type_1)
-		pl2303_vendor_write(2, 0x24, serial);
-	else
+	if (type == HX)
 		pl2303_vendor_write(2, 0x44, serial);
+	else
+		pl2303_vendor_write(2, 0x24, serial);
 
 	kfree(buf);
 	return 0;
@@ -316,174 +264,65 @@
 	return retval;
 }
 
-static int pl2303_baudrate_encode_direct(int baud, enum pl2303_type type,
-								      u8 buf[4])
+static void pl2303_encode_baudrate(struct tty_struct *tty,
+					struct usb_serial_port *port,
+					u8 buf[4])
 {
-	/*
-	 * NOTE: Only the values defined in baud_sup are supported !
-	 * => if unsupported values are set, the PL2303 uses 9600 baud instead
-	 * => HX clones just don't work at unsupported baud rates < 115200 baud,
-	 *    for baud rates > 115200 they run at 115200 baud
-	 */
 	const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600,
-				 4800, 7200, 9600, 14400, 19200, 28800, 38400,
-				 57600, 115200, 230400, 460800, 614400, 921600,
-				 1228800, 2457600, 3000000, 6000000, 12000000 };
-	/*
-	 * NOTE: With the exception of type_0/1 devices, the following
-	 * additional baud rates are supported (tested with HX rev. 3A only):
-	 * 110*, 56000*, 128000, 134400, 161280, 201600, 256000*, 268800,
-	 * 403200, 806400.	(*: not HX and HX clones)
-	 *
-	 * Maximum values: HXD, TB: 12000000; HX, TA: 6000000;
-	 *                 type_0+1: 1228800; RA: 921600; HX clones, SA: 115200
-	 *
-	 * As long as we are not using this encoding method for anything else
-	 * than the type_0+1, HX and HX clone chips, there is no point in
-	 * complicating the code to support them.
-	 */
+	                         4800, 7200, 9600, 14400, 19200, 28800, 38400,
+	                         57600, 115200, 230400, 460800, 500000, 614400,
+	                         921600, 1228800, 2457600, 3000000, 6000000 };
+
+	struct usb_serial *serial = port->serial;
+	struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
+	int baud;
 	int i;
 
+	/*
+	 * NOTE: Only the values defined in baud_sup are supported!
+	 *       => if unsupported values are set, the PL2303 seems to use
+	 *          9600 baud (at least my PL2303X always does)
+	 */
+	baud = tty_get_baud_rate(tty);
+	dev_dbg(&port->dev, "baud requested = %d\n", baud);
+	if (!baud)
+		return;
+
 	/* Set baudrate to nearest supported value */
 	for (i = 0; i < ARRAY_SIZE(baud_sup); ++i) {
 		if (baud_sup[i] > baud)
 			break;
 	}
+
 	if (i == ARRAY_SIZE(baud_sup))
 		baud = baud_sup[i - 1];
 	else if (i > 0 && (baud_sup[i] - baud) > (baud - baud_sup[i - 1]))
 		baud = baud_sup[i - 1];
 	else
 		baud = baud_sup[i];
-	/* Respect the chip type specific baud rate limits */
-	/*
-	 * FIXME: as long as we don't know how to distinguish between the
-	 * HXD, EA, RA, and SA chip variants, allow the max. value of 12M.
-	 */
-	if (type == HX_TA)
-		baud = min_t(int, baud, 6000000);
-	else if (type == type_0 || type == type_1)
+
+	/* type_0, type_1 only support up to 1228800 baud */
+	if (spriv->type != HX)
 		baud = min_t(int, baud, 1228800);
-	else if (type == HX_CLONE)
-		baud = min_t(int, baud, 115200);
-	/* Direct (standard) baud rate encoding method */
-	put_unaligned_le32(baud, buf);
 
-	return baud;
-}
-
-static int pl2303_baudrate_encode_divisor(int baud, enum pl2303_type type,
-								      u8 buf[4])
-{
-	/*
-	 * Divisor based baud rate encoding method
-	 *
-	 * NOTE: HX clones do NOT support this method.
-	 * It's not clear if the type_0/1 chips support it.
-	 *
-	 * divisor = 12MHz * 32 / baudrate = 2^A * B
-	 *
-	 * with
-	 *
-	 * A = buf[1] & 0x0e
-	 * B = buf[0]  +  (buf[1] & 0x01) << 8
-	 *
-	 * Special cases:
-	 * => 8 < B < 16: device seems to work not properly
-	 * => B <= 8: device uses the max. value B = 512 instead
-	 */
-	unsigned int A, B;
-
-	/*
-	 * NOTE: The Windows driver allows maximum baud rates of 110% of the
-	 * specified maximium value.
-	 * Quick tests with early (2004) HX (rev. A) chips suggest, that even
-	 * higher baud rates (up to the maximum of 24M baud !) are working fine,
-	 * but that should really be tested carefully in "real life" scenarios
-	 * before removing the upper limit completely.
-	 * Baud rates smaller than the specified 75 baud are definitely working
-	 * fine.
-	 */
-	if (type == type_0 || type == type_1)
-		baud = min_t(int, baud, 1228800 * 1.1);
-	else if (type == HX_TA)
-		baud = min_t(int, baud, 6000000 * 1.1);
-	else if (type == HXD_EA_RA_SA)
-		/* HXD, EA: 12Mbps; RA: 1Mbps; SA: 115200 bps */
-		/*
-		 * FIXME: as long as we don't know how to distinguish between
-		 * these chip variants, allow the max. of these values
-		 */
-		baud = min_t(int, baud, 12000000 * 1.1);
-	else if (type == TB)
-		baud = min_t(int, baud, 12000000 * 1.1);
-	/* Determine factors A and B */
-	A = 0;
-	B = 12000000 * 32 / baud;  /* 12MHz */
-	B <<= 1; /* Add one bit for rounding */
-	while (B > (512 << 1) && A <= 14) {
-		A += 2;
-		B >>= 2;
-	}
-	if (A > 14) { /* max. divisor = min. baudrate reached */
-		A = 14;
-		B = 512;
-		/* => ~45.78 baud */
+	if (baud <= 115200) {
+		put_unaligned_le32(baud, buf);
 	} else {
-		B = (B + 1) >> 1; /* Round the last bit */
-	}
-	/* Handle special cases */
-	if (B == 512)
-		B = 0; /* also: 1 to 8 */
-	else if (B < 16)
 		/*
-		 * NOTE: With the current algorithm this happens
-		 * only for A=0 and means that the min. divisor
-		 * (respectively: the max. baudrate) is reached.
+		 * Apparently the formula for higher speeds is:
+		 * baudrate = 12M * 32 / (2^buf[1]) / buf[0]
 		 */
-		B = 16;		/* => 24 MBaud */
-	/* Encode the baud rate */
-	buf[3] = 0x80;     /* Select divisor encoding method */
-	buf[2] = 0;
-	buf[1] = (A & 0x0e);		/* A */
-	buf[1] |= ((B & 0x100) >> 8);	/* MSB of B */
-	buf[0] = B & 0xff;		/* 8 LSBs of B */
-	/* Calculate the actual/resulting baud rate */
-	if (B <= 8)
-		B = 512;
-	baud = 12000000 * 32 / ((1 << A) * B);
+		unsigned tmp = 12000000 * 32 / baud;
+		buf[3] = 0x80;
+		buf[2] = 0;
+		buf[1] = (tmp >= 256);
+		while (tmp >= 256) {
+			tmp >>= 2;
+			buf[1] <<= 1;
+		}
+		buf[0] = tmp;
+	}
 
-	return baud;
-}
-
-static void pl2303_encode_baudrate(struct tty_struct *tty,
-					struct usb_serial_port *port,
-					enum pl2303_type type,
-					u8 buf[4])
-{
-	int baud;
-
-	baud = tty_get_baud_rate(tty);
-	dev_dbg(&port->dev, "baud requested = %d\n", baud);
-	if (!baud)
-		return;
-	/*
-	 * There are two methods for setting/encoding the baud rate
-	 * 1) Direct method: encodes the baud rate value directly
-	 *    => supported by all chip types
-	 * 2) Divisor based method: encodes a divisor to a base value (12MHz*32)
-	 *    => not supported by HX clones (and likely type_0/1 chips)
-	 *
-	 * NOTE: Although the divisor based baud rate encoding method is much
-	 * more flexible, some of the standard baud rate values can not be
-	 * realized exactly. But the difference is very small (max. 0.2%) and
-	 * the device likely uses the same baud rate generator for both methods
-	 * so that there is likley no difference.
-	 */
-	if (type == type_0 || type == type_1 || type == HX_CLONE)
-		baud = pl2303_baudrate_encode_direct(baud, type, buf);
-	else
-		baud = pl2303_baudrate_encode_divisor(baud, type, buf);
 	/* Save resulting baud rate */
 	tty_encode_baud_rate(tty, baud, baud);
 	dev_dbg(&port->dev, "baud set = %d\n", baud);
@@ -540,8 +379,8 @@
 		dev_dbg(&port->dev, "data bits = %d\n", buf[6]);
 	}
 
-	/* For reference:   buf[0]:buf[3] baud rate value */
-	pl2303_encode_baudrate(tty, port, spriv->type, buf);
+	/* For reference buf[0]:buf[3] baud rate value */
+	pl2303_encode_baudrate(tty, port, &buf[0]);
 
 	/* For reference buf[4]=0 is 1 stop bits */
 	/* For reference buf[4]=1 is 1.5 stop bits */
@@ -618,10 +457,10 @@
 	dev_dbg(&port->dev, "0xa1:0x21:0:0  %d - %7ph\n", i, buf);
 
 	if (C_CRTSCTS(tty)) {
-		if (spriv->type == type_0 || spriv->type == type_1)
-			pl2303_vendor_write(0x0, 0x41, serial);
-		else
+		if (spriv->type == HX)
 			pl2303_vendor_write(0x0, 0x61, serial);
+		else
+			pl2303_vendor_write(0x0, 0x41, serial);
 	} else {
 		pl2303_vendor_write(0x0, 0x0, serial);
 	}
@@ -658,7 +497,7 @@
 	struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
 	int result;
 
-	if (spriv->type == type_0 || spriv->type == type_1) {
+	if (spriv->type != HX) {
 		usb_clear_halt(serial->dev, port->write_urb->pipe);
 		usb_clear_halt(serial->dev, port->read_urb->pipe);
 	} else {
@@ -833,7 +672,6 @@
 	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 				 BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
 				 0, NULL, 0, 100);
-	/* NOTE: HX clones don't support sending breaks, -EPIPE is returned */
 	if (result)
 		dev_err(&port->dev, "error sending break = %d\n", result);
 }
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 760b785..c9a3569 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -190,6 +190,7 @@
 	{ USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) },
 	{ USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) },
 	{ USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) },
+	{ USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) },
 	{ USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) },
 	{ }	/* terminator */
 };
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 94d75ed..18509e6 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -211,8 +211,11 @@
 		/*
 		 * Many devices do not respond properly to READ_CAPACITY_16.
 		 * Tell the SCSI layer to try READ_CAPACITY_10 first.
+		 * However some USB 3.0 drive enclosures return capacity
+		 * modulo 2TB. Those must use READ_CAPACITY_16
 		 */
-		sdev->try_rc_10_first = 1;
+		if (!(us->fflags & US_FL_NEEDS_CAP16))
+			sdev->try_rc_10_first = 1;
 
 		/* assume SPC3 or latter devices support sense size > 18 */
 		if (sdev->scsi_level > SCSI_SPC_2)
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index c015f2c..de32cfa 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1925,6 +1925,13 @@
 		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
+/* Reported by Oliver Neukum <oneukum@suse.com> */
+UNUSUAL_DEV(  0x174c, 0x55aa, 0x0100, 0x0100,
+		"ASMedia",
+		"AS2105",
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+		US_FL_NEEDS_CAP16),
+
 /* Reported by Jesse Feddema <jdfeddema@gmail.com> */
 UNUSUAL_DEV(  0x177f, 0x0400, 0x0000, 0x0000,
 		"Yarvik",
diff --git a/drivers/usb/wusbcore/cbaf.c b/drivers/usb/wusbcore/cbaf.c
index 7f78f30..f06ed82 100644
--- a/drivers/usb/wusbcore/cbaf.c
+++ b/drivers/usb/wusbcore/cbaf.c
@@ -208,9 +208,9 @@
 				ar_name = "ASSOCIATE";
 				ar_assoc = 1;
 				break;
-			};
+			}
 			break;
-		};
+		}
 
 		dev_dbg(dev, "Association request #%02u: 0x%04x/%04x "
 			 "(%zu bytes): %s\n",
@@ -623,6 +623,8 @@
 
 error_create_group:
 error_check:
+	usb_put_intf(iface);
+	usb_put_dev(cbaf->usb_dev);
 	kfree(cbaf->buffer);
 error_kmalloc_buffer:
 	kfree(cbaf);
@@ -637,6 +639,7 @@
 	sysfs_remove_group(&dev->kobj, &cbaf_dev_attr_group);
 	usb_set_intfdata(iface, NULL);
 	usb_put_intf(iface);
+	usb_put_dev(cbaf->usb_dev);
 	kfree(cbaf->buffer);
 	/* paranoia: clean up crypto keys */
 	kzfree(cbaf);
diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c
index 33a1278..e538b72 100644
--- a/drivers/usb/wusbcore/devconnect.c
+++ b/drivers/usb/wusbcore/devconnect.c
@@ -973,7 +973,7 @@
 	default:
 		WARN_ON(1);
 		result = NOTIFY_BAD;
-	};
+	}
 	return result;
 }
 
diff --git a/drivers/usb/wusbcore/wa-hc.c b/drivers/usb/wusbcore/wa-hc.c
index a09b65e..368360f 100644
--- a/drivers/usb/wusbcore/wa-hc.c
+++ b/drivers/usb/wusbcore/wa-hc.c
@@ -33,7 +33,8 @@
  * wa->usb_dev and wa->usb_iface initialized and refcounted,
  * wa->wa_descr initialized.
  */
-int wa_create(struct wahc *wa, struct usb_interface *iface)
+int wa_create(struct wahc *wa, struct usb_interface *iface,
+	kernel_ulong_t quirks)
 {
 	int result;
 	struct device *dev = &iface->dev;
@@ -41,14 +42,15 @@
 	result = wa_rpipes_create(wa);
 	if (result < 0)
 		goto error_rpipes_create;
+	wa->quirks = quirks;
 	/* Fill up Data Transfer EP pointers */
 	wa->dti_epd = &iface->cur_altsetting->endpoint[1].desc;
 	wa->dto_epd = &iface->cur_altsetting->endpoint[2].desc;
-	wa->xfer_result_size = usb_endpoint_maxp(wa->dti_epd);
-	wa->xfer_result = kmalloc(wa->xfer_result_size, GFP_KERNEL);
-	if (wa->xfer_result == NULL) {
+	wa->dti_buf_size = usb_endpoint_maxp(wa->dti_epd);
+	wa->dti_buf = kmalloc(wa->dti_buf_size, GFP_KERNEL);
+	if (wa->dti_buf == NULL) {
 		result = -ENOMEM;
-		goto error_xfer_result_alloc;
+		goto error_dti_buf_alloc;
 	}
 	result = wa_nep_create(wa, iface);
 	if (result < 0) {
@@ -59,8 +61,8 @@
 	return 0;
 
 error_nep_create:
-	kfree(wa->xfer_result);
-error_xfer_result_alloc:
+	kfree(wa->dti_buf);
+error_dti_buf_alloc:
 	wa_rpipes_destroy(wa);
 error_rpipes_create:
 	return result;
@@ -76,7 +78,7 @@
 		usb_kill_urb(wa->buf_in_urb);
 		usb_put_urb(wa->buf_in_urb);
 	}
-	kfree(wa->xfer_result);
+	kfree(wa->dti_buf);
 	wa_nep_destroy(wa);
 	wa_rpipes_destroy(wa);
 }
diff --git a/drivers/usb/wusbcore/wa-hc.h b/drivers/usb/wusbcore/wa-hc.h
index cf250c2..e614f02 100644
--- a/drivers/usb/wusbcore/wa-hc.h
+++ b/drivers/usb/wusbcore/wa-hc.h
@@ -117,11 +117,25 @@
 	struct wahc *wa;
 	spinlock_t seg_lock;
 	struct list_head seg_list;
+	struct list_head list_node;
 	atomic_t segs_available;
 	u8 buffer[1];	/* For reads/writes on USB */
 };
 
 
+enum wa_dti_state {
+	WA_DTI_TRANSFER_RESULT_PENDING,
+	WA_DTI_ISOC_PACKET_STATUS_PENDING
+};
+
+enum wa_quirks {
+	/*
+	 * The Alereon HWA expects the data frames in isochronous transfer
+	 * requests to be concatenated and not sent as separate packets.
+	 */
+	WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC	= 0x01,
+};
+
 /**
  * Instance of a HWA Host Controller
  *
@@ -178,14 +192,26 @@
 
 	u16 rpipes;
 	unsigned long *rpipe_bm;	/* rpipe usage bitmap */
-	spinlock_t rpipe_bm_lock;	/* protect rpipe_bm */
+	struct list_head rpipe_delayed_list;	/* delayed RPIPES. */
+	spinlock_t rpipe_lock;	/* protect rpipe_bm and delayed list */
 	struct mutex rpipe_mutex;	/* assigning resources to endpoints */
 
+	/*
+	 * dti_state is used to track the state of the dti_urb.  When dti_state
+	 * is WA_DTI_ISOC_PACKET_STATUS_PENDING, dti_isoc_xfer_in_progress and
+	 * dti_isoc_xfer_seg identify which xfer the incoming isoc packet status
+	 * refers to.
+	 */
+	enum wa_dti_state dti_state;
+	u32 dti_isoc_xfer_in_progress;
+	u8  dti_isoc_xfer_seg;
 	struct urb *dti_urb;		/* URB for reading xfer results */
 	struct urb *buf_in_urb;		/* URB for reading data in */
 	struct edc dti_edc;		/* DTI error density counter */
-	struct wa_xfer_result *xfer_result; /* real size = dti_ep maxpktsize */
-	size_t xfer_result_size;
+	void *dti_buf;
+	size_t dti_buf_size;
+
+	unsigned long dto_in_use;	/* protect dto endoint serialization. */
 
 	s32 status;			/* For reading status */
 
@@ -200,10 +226,13 @@
 	struct work_struct xfer_enqueue_work;
 	struct work_struct xfer_error_work;
 	atomic_t xfer_id_count;
+
+	kernel_ulong_t	quirks;
 };
 
 
-extern int wa_create(struct wahc *wa, struct usb_interface *iface);
+extern int wa_create(struct wahc *wa, struct usb_interface *iface,
+	kernel_ulong_t);
 extern void __wa_destroy(struct wahc *wa);
 void wa_reset_all(struct wahc *wa);
 
@@ -239,7 +268,8 @@
 /* RPipes */
 static inline void wa_rpipe_init(struct wahc *wa)
 {
-	spin_lock_init(&wa->rpipe_bm_lock);
+	INIT_LIST_HEAD(&wa->rpipe_delayed_list);
+	spin_lock_init(&wa->rpipe_lock);
 	mutex_init(&wa->rpipe_mutex);
 }
 
@@ -247,6 +277,7 @@
 {
 	edc_init(&wa->nep_edc);
 	atomic_set(&wa->notifs_queued, 0);
+	wa->dti_state = WA_DTI_TRANSFER_RESULT_PENDING;
 	wa_rpipe_init(wa);
 	edc_init(&wa->dti_edc);
 	INIT_LIST_HEAD(&wa->xfer_list);
@@ -255,6 +286,7 @@
 	spin_lock_init(&wa->xfer_list_lock);
 	INIT_WORK(&wa->xfer_enqueue_work, wa_urb_enqueue_run);
 	INIT_WORK(&wa->xfer_error_work, wa_process_errored_transfers_run);
+	wa->dto_in_use = 0;
 	atomic_set(&wa->xfer_id_count, 1);
 }
 
diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c
index fd4f1ce..b48e74c 100644
--- a/drivers/usb/wusbcore/wa-rpipe.c
+++ b/drivers/usb/wusbcore/wa-rpipe.c
@@ -143,17 +143,18 @@
 	kref_init(&rpipe->refcnt);
 	spin_lock_init(&rpipe->seg_lock);
 	INIT_LIST_HEAD(&rpipe->seg_list);
+	INIT_LIST_HEAD(&rpipe->list_node);
 }
 
 static unsigned rpipe_get_idx(struct wahc *wa, unsigned rpipe_idx)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&wa->rpipe_bm_lock, flags);
+	spin_lock_irqsave(&wa->rpipe_lock, flags);
 	rpipe_idx = find_next_zero_bit(wa->rpipe_bm, wa->rpipes, rpipe_idx);
 	if (rpipe_idx < wa->rpipes)
 		set_bit(rpipe_idx, wa->rpipe_bm);
-	spin_unlock_irqrestore(&wa->rpipe_bm_lock, flags);
+	spin_unlock_irqrestore(&wa->rpipe_lock, flags);
 
 	return rpipe_idx;
 }
@@ -162,9 +163,9 @@
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&wa->rpipe_bm_lock, flags);
+	spin_lock_irqsave(&wa->rpipe_lock, flags);
 	clear_bit(rpipe_idx, wa->rpipe_bm);
-	spin_unlock_irqrestore(&wa->rpipe_bm_lock, flags);
+	spin_unlock_irqrestore(&wa->rpipe_lock, flags);
 }
 
 void rpipe_destroy(struct kref *_rpipe)
@@ -333,7 +334,10 @@
 	/* FIXME: compute so seg_size > ep->maxpktsize */
 	rpipe->descr.wBlocks = cpu_to_le16(16);		/* given */
 	/* ep0 maxpktsize is 0x200 (WUSB1.0[4.8.1]) */
-	rpipe->descr.wMaxPacketSize = cpu_to_le16(ep->desc.wMaxPacketSize);
+	if (usb_endpoint_xfer_isoc(&ep->desc))
+		rpipe->descr.wMaxPacketSize = epcd->wOverTheAirPacketSize;
+	else
+		rpipe->descr.wMaxPacketSize = ep->desc.wMaxPacketSize;
 
 	rpipe->descr.hwa_bMaxBurst = max(min_t(unsigned int,
 				epcd->bMaxBurst, 16U), 1U);
@@ -361,8 +365,10 @@
 			epcd->bMaxSequence, 32U), 2U);
 	rpipe->descr.bMaxDataSequence = epcd_max_sequence - 1;
 	rpipe->descr.bInterval = ep->desc.bInterval;
-	/* FIXME: bOverTheAirInterval */
-	rpipe->descr.bOverTheAirInterval = 0;	/* 0 if not isoc */
+	if (usb_endpoint_xfer_isoc(&ep->desc))
+		rpipe->descr.bOverTheAirInterval = epcd->bOverTheAirInterval;
+	else
+		rpipe->descr.bOverTheAirInterval = 0;	/* 0 if not isoc */
 	/* FIXME: xmit power & preamble blah blah */
 	rpipe->descr.bmAttribute = (ep->desc.bmAttributes &
 					USB_ENDPOINT_XFERTYPE_MASK);
@@ -477,7 +483,7 @@
  */
 int wa_rpipes_create(struct wahc *wa)
 {
-	wa->rpipes = wa->wa_descr->wNumRPipes;
+	wa->rpipes = le16_to_cpu(wa->wa_descr->wNumRPipes);
 	wa->rpipe_bm = kzalloc(BITS_TO_LONGS(wa->rpipes)*sizeof(unsigned long),
 			       GFP_KERNEL);
 	if (wa->rpipe_bm == NULL)
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index 6ad02f5..ed5abe8 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -91,7 +91,8 @@
 #include "wusbhc.h"
 
 enum {
-	WA_SEGS_MAX = 255,
+	/* [WUSB] section 8.3.3 allocates 7 bits for the segment index. */
+	WA_SEGS_MAX = 128,
 };
 
 enum wa_seg_status {
@@ -107,6 +108,7 @@
 };
 
 static void wa_xfer_delayed_run(struct wa_rpipe *);
+static int __wa_xfer_delayed_run(struct wa_rpipe *rpipe, int *dto_waiting);
 
 /*
  * Life cycle governed by 'struct urb' (the refcount of the struct is
@@ -114,24 +116,27 @@
  * struct).
  */
 struct wa_seg {
-	struct urb urb;
-	struct urb *dto_urb;		/* for data output? */
+	struct urb tr_urb;		/* transfer request urb. */
+	struct urb *isoc_pack_desc_urb;	/* for isoc packet descriptor. */
+	struct urb *dto_urb;		/* for data output. */
 	struct list_head list_node;	/* for rpipe->req_list */
 	struct wa_xfer *xfer;		/* out xfer */
 	u8 index;			/* which segment we are */
+	int isoc_frame_count;	/* number of isoc frames in this segment. */
+	int isoc_frame_offset;	/* starting frame offset in the xfer URB. */
+	int isoc_size;	/* size of all isoc frames sent by this seg. */
 	enum wa_seg_status status;
 	ssize_t result;			/* bytes xfered or error */
 	struct wa_xfer_hdr xfer_hdr;
-	u8 xfer_extra[];		/* xtra space for xfer_hdr_ctl */
 };
 
 static inline void wa_seg_init(struct wa_seg *seg)
 {
-	usb_init_urb(&seg->urb);
+	usb_init_urb(&seg->tr_urb);
 
 	/* set the remaining memory to 0. */
-	memset(((void *)seg) + sizeof(seg->urb), 0,
-		sizeof(*seg) - sizeof(seg->urb));
+	memset(((void *)seg) + sizeof(seg->tr_urb), 0,
+		sizeof(*seg) - sizeof(seg->tr_urb));
 }
 
 /*
@@ -153,12 +158,17 @@
 	unsigned is_dma:1;
 	size_t seg_size;
 	int result;
+	/* Isoc frame that the current transfer buffer corresponds to. */
+	int dto_isoc_frame_index;
 
 	gfp_t gfp;			/* allocation mask */
 
 	struct wusb_dev *wusb_dev;	/* for activity timestamps */
 };
 
+static void __wa_populate_dto_urb_isoc(struct wa_xfer *xfer,
+	struct wa_seg *seg, int curr_iso_frame);
+
 static inline void wa_xfer_init(struct wa_xfer *xfer)
 {
 	kref_init(&xfer->refcnt);
@@ -169,7 +179,7 @@
 /*
  * Destroy a transfer structure
  *
- * Note that freeing xfer->seg[cnt]->urb will free the containing
+ * Note that freeing xfer->seg[cnt]->tr_urb will free the containing
  * xfer->seg[cnt] memory that was allocated by __wa_xfer_setup_segs.
  */
 static void wa_xfer_destroy(struct kref *_xfer)
@@ -178,9 +188,17 @@
 	if (xfer->seg) {
 		unsigned cnt;
 		for (cnt = 0; cnt < xfer->segs; cnt++) {
-			usb_free_urb(xfer->seg[cnt]->dto_urb);
-			usb_free_urb(&xfer->seg[cnt]->urb);
+			struct wa_seg *seg = xfer->seg[cnt];
+			if (seg) {
+				usb_free_urb(seg->isoc_pack_desc_urb);
+				if (seg->dto_urb) {
+					kfree(seg->dto_urb->sg);
+					usb_free_urb(seg->dto_urb);
+				}
+				usb_free_urb(&seg->tr_urb);
+			}
 		}
+		kfree(xfer->seg);
 	}
 	kfree(xfer);
 }
@@ -196,6 +214,59 @@
 }
 
 /*
+ * Try to get exclusive access to the DTO endpoint resource.  Return true
+ * if successful.
+ */
+static inline int __wa_dto_try_get(struct wahc *wa)
+{
+	return (test_and_set_bit(0, &wa->dto_in_use) == 0);
+}
+
+/* Release the DTO endpoint resource. */
+static inline void __wa_dto_put(struct wahc *wa)
+{
+	clear_bit_unlock(0, &wa->dto_in_use);
+}
+
+/* Service RPIPEs that are waiting on the DTO resource. */
+static void wa_check_for_delayed_rpipes(struct wahc *wa)
+{
+	unsigned long flags;
+	int dto_waiting = 0;
+	struct wa_rpipe *rpipe;
+
+	spin_lock_irqsave(&wa->rpipe_lock, flags);
+	while (!list_empty(&wa->rpipe_delayed_list) && !dto_waiting) {
+		rpipe = list_first_entry(&wa->rpipe_delayed_list,
+				struct wa_rpipe, list_node);
+		__wa_xfer_delayed_run(rpipe, &dto_waiting);
+		/* remove this RPIPE from the list if it is not waiting. */
+		if (!dto_waiting) {
+			pr_debug("%s: RPIPE %d serviced and removed from delayed list.\n",
+				__func__,
+				le16_to_cpu(rpipe->descr.wRPipeIndex));
+			list_del_init(&rpipe->list_node);
+		}
+	}
+	spin_unlock_irqrestore(&wa->rpipe_lock, flags);
+}
+
+/* add this RPIPE to the end of the delayed RPIPE list. */
+static void wa_add_delayed_rpipe(struct wahc *wa, struct wa_rpipe *rpipe)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&wa->rpipe_lock, flags);
+	/* add rpipe to the list if it is not already on it. */
+	if (list_empty(&rpipe->list_node)) {
+		pr_debug("%s: adding RPIPE %d to the delayed list.\n",
+			__func__, le16_to_cpu(rpipe->descr.wRPipeIndex));
+		list_add_tail(&rpipe->list_node, &wa->rpipe_delayed_list);
+	}
+	spin_unlock_irqrestore(&wa->rpipe_lock, flags);
+}
+
+/*
  * xfer is referenced
  *
  * xfer->lock has to be unlocked
@@ -232,6 +303,31 @@
 }
 
 /*
+ * Initialize a transfer's ID
+ *
+ * We need to use a sequential number; if we use the pointer or the
+ * hash of the pointer, it can repeat over sequential transfers and
+ * then it will confuse the HWA....wonder why in hell they put a 32
+ * bit handle in there then.
+ */
+static void wa_xfer_id_init(struct wa_xfer *xfer)
+{
+	xfer->id = atomic_add_return(1, &xfer->wa->xfer_id_count);
+}
+
+/* Return the xfer's ID. */
+static inline u32 wa_xfer_id(struct wa_xfer *xfer)
+{
+	return xfer->id;
+}
+
+/* Return the xfer's ID in transport format (little endian). */
+static inline __le32 wa_xfer_id_le32(struct wa_xfer *xfer)
+{
+	return cpu_to_le32(xfer->id);
+}
+
+/*
  * If transfer is done, wrap it up and return true
  *
  * xfer->lock has to be locked
@@ -253,33 +349,37 @@
 		switch (seg->status) {
 		case WA_SEG_DONE:
 			if (found_short && seg->result > 0) {
-				dev_dbg(dev, "xfer %p#%u: bad short segments (%zu)\n",
-					xfer, cnt, seg->result);
+				dev_dbg(dev, "xfer %p ID %08X#%u: bad short segments (%zu)\n",
+					xfer, wa_xfer_id(xfer), cnt,
+					seg->result);
 				urb->status = -EINVAL;
 				goto out;
 			}
 			urb->actual_length += seg->result;
-			if (seg->result < xfer->seg_size
+			if (!(usb_pipeisoc(xfer->urb->pipe))
+				&& seg->result < xfer->seg_size
 			    && cnt != xfer->segs-1)
 				found_short = 1;
-			dev_dbg(dev, "xfer %p#%u: DONE short %d "
+			dev_dbg(dev, "xfer %p ID %08X#%u: DONE short %d "
 				"result %zu urb->actual_length %d\n",
-				xfer, seg->index, found_short, seg->result,
-				urb->actual_length);
+				xfer, wa_xfer_id(xfer), seg->index, found_short,
+				seg->result, urb->actual_length);
 			break;
 		case WA_SEG_ERROR:
 			xfer->result = seg->result;
-			dev_dbg(dev, "xfer %p#%u: ERROR result %zu\n",
-				xfer, seg->index, seg->result);
+			dev_dbg(dev, "xfer %p ID %08X#%u: ERROR result %zu(0x%08zX)\n",
+				xfer, wa_xfer_id(xfer), seg->index, seg->result,
+				seg->result);
 			goto out;
 		case WA_SEG_ABORTED:
-			dev_dbg(dev, "xfer %p#%u ABORTED: result %d\n",
-				xfer, seg->index, urb->status);
+			dev_dbg(dev, "xfer %p ID %08X#%u ABORTED: result %d\n",
+				xfer, wa_xfer_id(xfer), seg->index,
+				urb->status);
 			xfer->result = urb->status;
 			goto out;
 		default:
-			dev_warn(dev, "xfer %p#%u: is_done bad state %d\n",
-				 xfer, cnt, seg->status);
+			dev_warn(dev, "xfer %p ID %08X#%u: is_done bad state %d\n",
+				 xfer, wa_xfer_id(xfer), cnt, seg->status);
 			xfer->result = -EINVAL;
 			goto out;
 		}
@@ -290,29 +390,6 @@
 }
 
 /*
- * Initialize a transfer's ID
- *
- * We need to use a sequential number; if we use the pointer or the
- * hash of the pointer, it can repeat over sequential transfers and
- * then it will confuse the HWA....wonder why in hell they put a 32
- * bit handle in there then.
- */
-static void wa_xfer_id_init(struct wa_xfer *xfer)
-{
-	xfer->id = atomic_add_return(1, &xfer->wa->xfer_id_count);
-}
-
-/*
- * Return the xfer's ID associated with xfer
- *
- * Need to generate a
- */
-static u32 wa_xfer_id(struct wa_xfer *xfer)
-{
-	return xfer->id;
-}
-
-/*
  * Search for a transfer list ID on the HCD's URB list
  *
  * For 32 bit architectures, we use the pointer itself; for 64 bits, a
@@ -356,15 +433,11 @@
  *
  * The callback (see above) does nothing but freeing up the data by
  * putting the URB. Because the URB is allocated at the head of the
- * struct, the whole space we allocated is kfreed.
- *
- * We'll get an 'aborted transaction' xfer result on DTI, that'll
- * politely ignore because at this point the transaction has been
- * marked as aborted already.
+ * struct, the whole space we allocated is kfreed. *
  */
-static void __wa_xfer_abort(struct wa_xfer *xfer)
+static int __wa_xfer_abort(struct wa_xfer *xfer)
 {
-	int result;
+	int result = -ENOMEM;
 	struct device *dev = &xfer->wa->usb_iface->dev;
 	struct wa_xfer_abort_buffer *b;
 	struct wa_rpipe *rpipe = xfer->ep->hcpriv;
@@ -375,7 +448,7 @@
 	b->cmd.bLength =  sizeof(b->cmd);
 	b->cmd.bRequestType = WA_XFER_ABORT;
 	b->cmd.wRPipe = rpipe->descr.wRPipeIndex;
-	b->cmd.dwTransferID = wa_xfer_id(xfer);
+	b->cmd.dwTransferID = wa_xfer_id_le32(xfer);
 
 	usb_init_urb(&b->urb);
 	usb_fill_bulk_urb(&b->urb, xfer->wa->usb_dev,
@@ -385,7 +458,7 @@
 	result = usb_submit_urb(&b->urb, GFP_ATOMIC);
 	if (result < 0)
 		goto error_submit;
-	return;				/* callback frees! */
+	return result;				/* callback frees! */
 
 
 error_submit:
@@ -394,11 +467,52 @@
 			xfer, result);
 	kfree(b);
 error_kmalloc:
-	return;
+	return result;
 
 }
 
 /*
+ * Calculate the number of isoc frames starting from isoc_frame_offset
+ * that will fit a in transfer segment.
+ */
+static int __wa_seg_calculate_isoc_frame_count(struct wa_xfer *xfer,
+	int isoc_frame_offset, int *total_size)
+{
+	int segment_size = 0, frame_count = 0;
+	int index = isoc_frame_offset;
+	struct usb_iso_packet_descriptor *iso_frame_desc =
+		xfer->urb->iso_frame_desc;
+
+	while ((index < xfer->urb->number_of_packets)
+		&& ((segment_size + iso_frame_desc[index].length)
+				<= xfer->seg_size)) {
+		/*
+		 * For Alereon HWA devices, only include an isoc frame in a
+		 * segment if it is physically contiguous with the previous
+		 * frame.  This is required because those devices expect
+		 * the isoc frames to be sent as a single USB transaction as
+		 * opposed to one transaction per frame with standard HWA.
+		 */
+		if ((xfer->wa->quirks & WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC)
+			&& (index > isoc_frame_offset)
+			&& ((iso_frame_desc[index - 1].offset +
+				iso_frame_desc[index - 1].length) !=
+				iso_frame_desc[index].offset))
+			break;
+
+		/* this frame fits. count it. */
+		++frame_count;
+		segment_size += iso_frame_desc[index].length;
+
+		/* move to the next isoc frame. */
+		++index;
+	}
+
+	*total_size = segment_size;
+	return frame_count;
+}
+
+/*
  *
  * @returns < 0 on error, transfer segment request size if ok
  */
@@ -422,43 +536,92 @@
 		result = sizeof(struct wa_xfer_bi);
 		break;
 	case USB_ENDPOINT_XFER_ISOC:
-		dev_err(dev, "FIXME: ISOC not implemented\n");
-		result = -ENOSYS;
-		goto error;
+		if (usb_pipeout(urb->pipe)) {
+			*pxfer_type = WA_XFER_TYPE_ISO;
+			result = sizeof(struct wa_xfer_hwaiso);
+		} else {
+			dev_err(dev, "FIXME: ISOC IN not implemented\n");
+			result = -ENOSYS;
+			goto error;
+		}
+		break;
 	default:
 		/* never happens */
 		BUG();
 		result = -EINVAL;	/* shut gcc up */
-	};
+	}
 	xfer->is_inbound = urb->pipe & USB_DIR_IN ? 1 : 0;
 	xfer->is_dma = urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP ? 1 : 0;
-	xfer->seg_size = le16_to_cpu(rpipe->descr.wBlocks)
-		* 1 << (xfer->wa->wa_descr->bRPipeBlockSize - 1);
-	/* Compute the segment size and make sure it is a multiple of
-	 * the maxpktsize (WUSB1.0[8.3.3.1])...not really too much of
-	 * a check (FIXME) */
+
 	maxpktsize = le16_to_cpu(rpipe->descr.wMaxPacketSize);
-	if (xfer->seg_size < maxpktsize) {
-		dev_err(dev, "HW BUG? seg_size %zu smaller than maxpktsize "
-			"%zu\n", xfer->seg_size, maxpktsize);
-		result = -EINVAL;
-		goto error;
+	if ((rpipe->descr.bmAttribute & 0x3) == USB_ENDPOINT_XFER_ISOC) {
+		int index = 0;
+
+		xfer->seg_size = maxpktsize;
+		xfer->segs = 0;
+		/*
+		 * loop over urb->number_of_packets to determine how many
+		 * xfer segments will be needed to send the isoc frames.
+		 */
+		while (index < urb->number_of_packets) {
+			int seg_size; /* don't care. */
+			index += __wa_seg_calculate_isoc_frame_count(xfer,
+					index, &seg_size);
+			++xfer->segs;
+		}
+	} else {
+		xfer->seg_size = le16_to_cpu(rpipe->descr.wBlocks)
+			* 1 << (xfer->wa->wa_descr->bRPipeBlockSize - 1);
+		/* Compute the segment size and make sure it is a multiple of
+		 * the maxpktsize (WUSB1.0[8.3.3.1])...not really too much of
+		 * a check (FIXME) */
+		if (xfer->seg_size < maxpktsize) {
+			dev_err(dev,
+				"HW BUG? seg_size %zu smaller than maxpktsize %zu\n",
+				xfer->seg_size, maxpktsize);
+			result = -EINVAL;
+			goto error;
+		}
+		xfer->seg_size = (xfer->seg_size / maxpktsize) * maxpktsize;
+		xfer->segs = DIV_ROUND_UP(urb->transfer_buffer_length,
+						xfer->seg_size);
+		if (xfer->segs == 0 && *pxfer_type == WA_XFER_TYPE_CTL)
+			xfer->segs = 1;
 	}
-	xfer->seg_size = (xfer->seg_size / maxpktsize) * maxpktsize;
-	xfer->segs = DIV_ROUND_UP(urb->transfer_buffer_length, xfer->seg_size);
-	if (xfer->segs >= WA_SEGS_MAX) {
-		dev_err(dev, "BUG? ops, number of segments %d bigger than %d\n",
-			(int)(urb->transfer_buffer_length / xfer->seg_size),
+
+	if (xfer->segs > WA_SEGS_MAX) {
+		dev_err(dev, "BUG? oops, number of segments %zu bigger than %d\n",
+			(urb->transfer_buffer_length/xfer->seg_size),
 			WA_SEGS_MAX);
 		result = -EINVAL;
 		goto error;
 	}
-	if (xfer->segs == 0 && *pxfer_type == WA_XFER_TYPE_CTL)
-		xfer->segs = 1;
 error:
 	return result;
 }
 
+static void __wa_setup_isoc_packet_descr(
+		struct wa_xfer_packet_info_hwaiso *packet_desc,
+		struct wa_xfer *xfer,
+		struct wa_seg *seg) {
+	struct usb_iso_packet_descriptor *iso_frame_desc =
+		xfer->urb->iso_frame_desc;
+	int frame_index;
+
+	/* populate isoc packet descriptor. */
+	packet_desc->bPacketType = WA_XFER_ISO_PACKET_INFO;
+	packet_desc->wLength = cpu_to_le16(sizeof(*packet_desc) +
+		(sizeof(packet_desc->PacketLength[0]) *
+			seg->isoc_frame_count));
+	for (frame_index = 0; frame_index < seg->isoc_frame_count;
+		++frame_index) {
+		int offset_index = frame_index + seg->isoc_frame_offset;
+		packet_desc->PacketLength[frame_index] =
+			cpu_to_le16(iso_frame_desc[offset_index].length);
+	}
+}
+
+
 /* Fill in the common request header and xfer-type specific data. */
 static void __wa_xfer_setup_hdr0(struct wa_xfer *xfer,
 				 struct wa_xfer_hdr *xfer_hdr0,
@@ -466,12 +629,13 @@
 				 size_t xfer_hdr_size)
 {
 	struct wa_rpipe *rpipe = xfer->ep->hcpriv;
+	struct wa_seg *seg = xfer->seg[0];
 
-	xfer_hdr0 = &xfer->seg[0]->xfer_hdr;
+	xfer_hdr0 = &seg->xfer_hdr;
 	xfer_hdr0->bLength = xfer_hdr_size;
 	xfer_hdr0->bRequestType = xfer_type;
 	xfer_hdr0->wRPipe = rpipe->descr.wRPipeIndex;
-	xfer_hdr0->dwTransferID = wa_xfer_id(xfer);
+	xfer_hdr0->dwTransferID = wa_xfer_id_le32(xfer);
 	xfer_hdr0->bTransferSegment = 0;
 	switch (xfer_type) {
 	case WA_XFER_TYPE_CTL: {
@@ -484,8 +648,18 @@
 	}
 	case WA_XFER_TYPE_BI:
 		break;
-	case WA_XFER_TYPE_ISO:
-		printk(KERN_ERR "FIXME: ISOC not implemented\n");
+	case WA_XFER_TYPE_ISO: {
+		struct wa_xfer_hwaiso *xfer_iso =
+			container_of(xfer_hdr0, struct wa_xfer_hwaiso, hdr);
+		struct wa_xfer_packet_info_hwaiso *packet_desc =
+			((void *)xfer_iso) + xfer_hdr_size;
+
+		/* populate the isoc section of the transfer request. */
+		xfer_iso->dwNumOfPackets = cpu_to_le32(seg->isoc_frame_count);
+		/* populate isoc packet descriptor. */
+		__wa_setup_isoc_packet_descr(packet_desc, xfer, seg);
+		break;
+	}
 	default:
 		BUG();
 	};
@@ -494,12 +668,12 @@
 /*
  * Callback for the OUT data phase of the segment request
  *
- * Check wa_seg_cb(); most comments also apply here because this
+ * Check wa_seg_tr_cb(); most comments also apply here because this
  * function does almost the same thing and they work closely
  * together.
  *
  * If the seg request has failed but this DTO phase has succeeded,
- * wa_seg_cb() has already failed the segment and moved the
+ * wa_seg_tr_cb() has already failed the segment and moved the
  * status to WA_SEG_ERROR, so this will go through 'case 0' and
  * effectively do nothing.
  */
@@ -512,6 +686,139 @@
 	struct wa_rpipe *rpipe;
 	unsigned long flags;
 	unsigned rpipe_ready = 0;
+	int data_send_done = 1, release_dto = 0, holding_dto = 0;
+	u8 done = 0;
+	int result;
+
+	/* free the sg if it was used. */
+	kfree(urb->sg);
+	urb->sg = NULL;
+
+	spin_lock_irqsave(&xfer->lock, flags);
+	wa = xfer->wa;
+	dev = &wa->usb_iface->dev;
+	if (usb_pipeisoc(xfer->urb->pipe)) {
+		/* Alereon HWA sends all isoc frames in a single transfer. */
+		if (wa->quirks & WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC)
+			xfer->dto_isoc_frame_index += seg->isoc_frame_count;
+		else
+			xfer->dto_isoc_frame_index += 1;
+		if (xfer->dto_isoc_frame_index < seg->isoc_frame_count) {
+			data_send_done = 0;
+			holding_dto = 1; /* checked in error cases. */
+			/*
+			 * if this is the last isoc frame of the segment, we
+			 * can release DTO after sending this frame.
+			 */
+			if ((xfer->dto_isoc_frame_index + 1) >=
+				seg->isoc_frame_count)
+				release_dto = 1;
+		}
+		dev_dbg(dev, "xfer 0x%08X#%u: isoc frame = %d, holding_dto = %d, release_dto = %d.\n",
+			wa_xfer_id(xfer), seg->index,
+			xfer->dto_isoc_frame_index, holding_dto, release_dto);
+	}
+	spin_unlock_irqrestore(&xfer->lock, flags);
+
+	switch (urb->status) {
+	case 0:
+		spin_lock_irqsave(&xfer->lock, flags);
+		seg->result += urb->actual_length;
+		if (data_send_done) {
+			dev_dbg(dev, "xfer 0x%08X#%u: data out done (%zu bytes)\n",
+				wa_xfer_id(xfer), seg->index, seg->result);
+			if (seg->status < WA_SEG_PENDING)
+				seg->status = WA_SEG_PENDING;
+		} else {
+			/* should only hit this for isoc xfers. */
+			/*
+			 * Populate the dto URB with the next isoc frame buffer,
+			 * send the URB and release DTO if we no longer need it.
+			 */
+			 __wa_populate_dto_urb_isoc(xfer, seg,
+				seg->isoc_frame_offset +
+				xfer->dto_isoc_frame_index);
+
+			/* resubmit the URB with the next isoc frame. */
+			result = usb_submit_urb(seg->dto_urb, GFP_ATOMIC);
+			if (result < 0) {
+				dev_err(dev, "xfer 0x%08X#%u: DTO submit failed: %d\n",
+				       wa_xfer_id(xfer), seg->index, result);
+				spin_unlock_irqrestore(&xfer->lock, flags);
+				goto error_dto_submit;
+			}
+		}
+		spin_unlock_irqrestore(&xfer->lock, flags);
+		if (release_dto) {
+			__wa_dto_put(wa);
+			wa_check_for_delayed_rpipes(wa);
+		}
+		break;
+	case -ECONNRESET:	/* URB unlinked; no need to do anything */
+	case -ENOENT:		/* as it was done by the who unlinked us */
+		if (holding_dto) {
+			__wa_dto_put(wa);
+			wa_check_for_delayed_rpipes(wa);
+		}
+		break;
+	default:		/* Other errors ... */
+		dev_err(dev, "xfer 0x%08X#%u: data out error %d\n",
+			wa_xfer_id(xfer), seg->index, urb->status);
+		goto error_default;
+	}
+
+	return;
+
+error_dto_submit:
+error_default:
+	spin_lock_irqsave(&xfer->lock, flags);
+	rpipe = xfer->ep->hcpriv;
+	if (edc_inc(&wa->nep_edc, EDC_MAX_ERRORS,
+		    EDC_ERROR_TIMEFRAME)){
+		dev_err(dev, "DTO: URB max acceptable errors exceeded, resetting device\n");
+		wa_reset_all(wa);
+	}
+	if (seg->status != WA_SEG_ERROR) {
+		seg->status = WA_SEG_ERROR;
+		seg->result = urb->status;
+		xfer->segs_done++;
+		__wa_xfer_abort(xfer);
+		rpipe_ready = rpipe_avail_inc(rpipe);
+		done = __wa_xfer_is_done(xfer);
+	}
+	spin_unlock_irqrestore(&xfer->lock, flags);
+	if (holding_dto) {
+		__wa_dto_put(wa);
+		wa_check_for_delayed_rpipes(wa);
+	}
+	if (done)
+		wa_xfer_completion(xfer);
+	if (rpipe_ready)
+		wa_xfer_delayed_run(rpipe);
+
+}
+
+/*
+ * Callback for the isoc packet descriptor phase of the segment request
+ *
+ * Check wa_seg_tr_cb(); most comments also apply here because this
+ * function does almost the same thing and they work closely
+ * together.
+ *
+ * If the seg request has failed but this phase has succeeded,
+ * wa_seg_tr_cb() has already failed the segment and moved the
+ * status to WA_SEG_ERROR, so this will go through 'case 0' and
+ * effectively do nothing.
+ */
+static void wa_seg_iso_pack_desc_cb(struct urb *urb)
+{
+	struct wa_seg *seg = urb->context;
+	struct wa_xfer *xfer = seg->xfer;
+	struct wahc *wa;
+	struct device *dev;
+	struct wa_rpipe *rpipe;
+	unsigned long flags;
+	unsigned rpipe_ready = 0;
 	u8 done = 0;
 
 	switch (urb->status) {
@@ -519,11 +826,10 @@
 		spin_lock_irqsave(&xfer->lock, flags);
 		wa = xfer->wa;
 		dev = &wa->usb_iface->dev;
-		dev_dbg(dev, "xfer %p#%u: data out done (%d bytes)\n",
-			xfer, seg->index, urb->actual_length);
-		if (seg->status < WA_SEG_PENDING)
+		dev_dbg(dev, "iso xfer %08X#%u: packet descriptor done\n",
+			wa_xfer_id(xfer), seg->index);
+		if (xfer->is_inbound && seg->status < WA_SEG_PENDING)
 			seg->status = WA_SEG_PENDING;
-		seg->result = urb->actual_length;
 		spin_unlock_irqrestore(&xfer->lock, flags);
 		break;
 	case -ECONNRESET:	/* URB unlinked; no need to do anything */
@@ -534,15 +840,15 @@
 		wa = xfer->wa;
 		dev = &wa->usb_iface->dev;
 		rpipe = xfer->ep->hcpriv;
-		dev_dbg(dev, "xfer %p#%u: data out error %d\n",
-			xfer, seg->index, urb->status);
+		pr_err_ratelimited("iso xfer %08X#%u: packet descriptor error %d\n",
+				wa_xfer_id(xfer), seg->index, urb->status);
 		if (edc_inc(&wa->nep_edc, EDC_MAX_ERRORS,
 			    EDC_ERROR_TIMEFRAME)){
-			dev_err(dev, "DTO: URB max acceptable errors "
-				"exceeded, resetting device\n");
+			dev_err(dev, "DTO: URB max acceptable errors exceeded, resetting device\n");
 			wa_reset_all(wa);
 		}
 		if (seg->status != WA_SEG_ERROR) {
+			usb_unlink_urb(seg->dto_urb);
 			seg->status = WA_SEG_ERROR;
 			seg->result = urb->status;
 			xfer->segs_done++;
@@ -572,11 +878,11 @@
  * We have to check before setting the status to WA_SEG_PENDING
  * because sometimes the xfer result callback arrives before this
  * callback (geeeeeeze), so it might happen that we are already in
- * another state. As well, we don't set it if the transfer is inbound,
+ * another state. As well, we don't set it if the transfer is not inbound,
  * as in that case, wa_seg_dto_cb will do it when the OUT data phase
  * finishes.
  */
-static void wa_seg_cb(struct urb *urb)
+static void wa_seg_tr_cb(struct urb *urb)
 {
 	struct wa_seg *seg = urb->context;
 	struct wa_xfer *xfer = seg->xfer;
@@ -592,8 +898,11 @@
 		spin_lock_irqsave(&xfer->lock, flags);
 		wa = xfer->wa;
 		dev = &wa->usb_iface->dev;
-		dev_dbg(dev, "xfer %p#%u: request done\n", xfer, seg->index);
-		if (xfer->is_inbound && seg->status < WA_SEG_PENDING)
+		dev_dbg(dev, "xfer %p ID 0x%08X#%u: request done\n",
+			xfer, wa_xfer_id(xfer), seg->index);
+		if (xfer->is_inbound &&
+			seg->status < WA_SEG_PENDING &&
+			!(usb_pipeisoc(xfer->urb->pipe)))
 			seg->status = WA_SEG_PENDING;
 		spin_unlock_irqrestore(&xfer->lock, flags);
 		break;
@@ -606,14 +915,16 @@
 		dev = &wa->usb_iface->dev;
 		rpipe = xfer->ep->hcpriv;
 		if (printk_ratelimit())
-			dev_err(dev, "xfer %p#%u: request error %d\n",
-				xfer, seg->index, urb->status);
+			dev_err(dev, "xfer %p ID 0x%08X#%u: request error %d\n",
+				xfer, wa_xfer_id(xfer), seg->index,
+				urb->status);
 		if (edc_inc(&wa->nep_edc, EDC_MAX_ERRORS,
 			    EDC_ERROR_TIMEFRAME)){
 			dev_err(dev, "DTO: URB max acceptable errors "
 				"exceeded, resetting device\n");
 			wa_reset_all(wa);
 		}
+		usb_unlink_urb(seg->isoc_pack_desc_urb);
 		usb_unlink_urb(seg->dto_urb);
 		seg->status = WA_SEG_ERROR;
 		seg->result = urb->status;
@@ -629,9 +940,11 @@
 	}
 }
 
-/* allocate an SG list to store bytes_to_transfer bytes and copy the
+/*
+ * Allocate an SG list to store bytes_to_transfer bytes and copy the
  * subset of the in_sg that matches the buffer subset
- * we are about to transfer. */
+ * we are about to transfer.
+ */
 static struct scatterlist *wa_xfer_create_subset_sg(struct scatterlist *in_sg,
 	const unsigned int bytes_transferred,
 	const unsigned int bytes_to_transfer, unsigned int *out_num_sgs)
@@ -710,6 +1023,75 @@
 }
 
 /*
+ * Populate DMA buffer info for the isoc dto urb.
+ */
+static void __wa_populate_dto_urb_isoc(struct wa_xfer *xfer,
+	struct wa_seg *seg, int curr_iso_frame)
+{
+	seg->dto_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+	seg->dto_urb->sg = NULL;
+	seg->dto_urb->num_sgs = 0;
+	/* dto urb buffer address pulled from iso_frame_desc. */
+	seg->dto_urb->transfer_dma = xfer->urb->transfer_dma +
+		xfer->urb->iso_frame_desc[curr_iso_frame].offset;
+	/* The Alereon HWA sends a single URB with all isoc segs. */
+	if (xfer->wa->quirks & WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC)
+		seg->dto_urb->transfer_buffer_length = seg->isoc_size;
+	else
+		seg->dto_urb->transfer_buffer_length =
+			xfer->urb->iso_frame_desc[curr_iso_frame].length;
+}
+
+/*
+ * Populate buffer ptr and size, DMA buffer or SG list for the dto urb.
+ */
+static int __wa_populate_dto_urb(struct wa_xfer *xfer,
+	struct wa_seg *seg, size_t buf_itr_offset, size_t buf_itr_size)
+{
+	int result = 0;
+
+	if (xfer->is_dma) {
+		seg->dto_urb->transfer_dma =
+			xfer->urb->transfer_dma + buf_itr_offset;
+		seg->dto_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+		seg->dto_urb->sg = NULL;
+		seg->dto_urb->num_sgs = 0;
+	} else {
+		/* do buffer or SG processing. */
+		seg->dto_urb->transfer_flags &=
+			~URB_NO_TRANSFER_DMA_MAP;
+		/* this should always be 0 before a resubmit. */
+		seg->dto_urb->num_mapped_sgs = 0;
+
+		if (xfer->urb->transfer_buffer) {
+			seg->dto_urb->transfer_buffer =
+				xfer->urb->transfer_buffer +
+				buf_itr_offset;
+			seg->dto_urb->sg = NULL;
+			seg->dto_urb->num_sgs = 0;
+		} else {
+			seg->dto_urb->transfer_buffer = NULL;
+
+			/*
+			 * allocate an SG list to store seg_size bytes
+			 * and copy the subset of the xfer->urb->sg that
+			 * matches the buffer subset we are about to
+			 * read.
+			 */
+			seg->dto_urb->sg = wa_xfer_create_subset_sg(
+				xfer->urb->sg,
+				buf_itr_offset, buf_itr_size,
+				&(seg->dto_urb->num_sgs));
+			if (!(seg->dto_urb->sg))
+				result = -ENOMEM;
+		}
+	}
+	seg->dto_urb->transfer_buffer_length = buf_itr_size;
+
+	return result;
+}
+
+/*
  * Allocate the segs array and initialize each of them
  *
  * The segments are freed by wa_xfer_destroy() when the xfer use count
@@ -719,13 +1101,14 @@
  */
 static int __wa_xfer_setup_segs(struct wa_xfer *xfer, size_t xfer_hdr_size)
 {
-	int result, cnt;
+	int result, cnt, iso_frame_offset;
 	size_t alloc_size = sizeof(*xfer->seg[0])
 		- sizeof(xfer->seg[0]->xfer_hdr) + xfer_hdr_size;
 	struct usb_device *usb_dev = xfer->wa->usb_dev;
 	const struct usb_endpoint_descriptor *dto_epd = xfer->wa->dto_epd;
 	struct wa_seg *seg;
 	size_t buf_itr, buf_size, buf_itr_size;
+	int xfer_isoc_frame_offset = 0;
 
 	result = -ENOMEM;
 	xfer->seg = kcalloc(xfer->segs, sizeof(xfer->seg[0]), GFP_ATOMIC);
@@ -733,18 +1116,35 @@
 		goto error_segs_kzalloc;
 	buf_itr = 0;
 	buf_size = xfer->urb->transfer_buffer_length;
+	iso_frame_offset = 0;
 	for (cnt = 0; cnt < xfer->segs; cnt++) {
-		seg = xfer->seg[cnt] = kmalloc(alloc_size, GFP_ATOMIC);
+		size_t iso_pkt_descr_size = 0;
+		int seg_isoc_frame_count = 0, seg_isoc_size = 0;
+
+		if (usb_pipeisoc(xfer->urb->pipe)) {
+			seg_isoc_frame_count =
+				__wa_seg_calculate_isoc_frame_count(xfer,
+					xfer_isoc_frame_offset, &seg_isoc_size);
+
+			iso_pkt_descr_size =
+				sizeof(struct wa_xfer_packet_info_hwaiso) +
+				(seg_isoc_frame_count * sizeof(__le16));
+		}
+		seg = xfer->seg[cnt] = kmalloc(alloc_size + iso_pkt_descr_size,
+						GFP_ATOMIC);
 		if (seg == NULL)
 			goto error_seg_kmalloc;
 		wa_seg_init(seg);
 		seg->xfer = xfer;
 		seg->index = cnt;
-		usb_fill_bulk_urb(&seg->urb, usb_dev,
+		seg->isoc_frame_count = seg_isoc_frame_count;
+		seg->isoc_frame_offset = xfer_isoc_frame_offset;
+		seg->isoc_size = seg_isoc_size;
+		usb_fill_bulk_urb(&seg->tr_urb, usb_dev,
 				  usb_sndbulkpipe(usb_dev,
 						  dto_epd->bEndpointAddress),
 				  &seg->xfer_hdr, xfer_hdr_size,
-				  wa_seg_cb, seg);
+				  wa_seg_tr_cb, seg);
 		buf_itr_size = min(buf_size, xfer->seg_size);
 		if (xfer->is_inbound == 0 && buf_size > 0) {
 			/* outbound data. */
@@ -756,69 +1156,64 @@
 				usb_sndbulkpipe(usb_dev,
 						dto_epd->bEndpointAddress),
 				NULL, 0, wa_seg_dto_cb, seg);
-			if (xfer->is_dma) {
-				seg->dto_urb->transfer_dma =
-					xfer->urb->transfer_dma + buf_itr;
-				seg->dto_urb->transfer_flags |=
-					URB_NO_TRANSFER_DMA_MAP;
-				seg->dto_urb->transfer_buffer = NULL;
-				seg->dto_urb->sg = NULL;
-				seg->dto_urb->num_sgs = 0;
+
+			if (usb_pipeisoc(xfer->urb->pipe)) {
+				/* iso packet descriptor. */
+				seg->isoc_pack_desc_urb =
+						usb_alloc_urb(0, GFP_ATOMIC);
+				if (seg->isoc_pack_desc_urb == NULL)
+					goto error_iso_pack_desc_alloc;
+				/*
+				 * The buffer for the isoc packet descriptor
+				 * after the transfer request header in the
+				 * segment object memory buffer.
+				 */
+				usb_fill_bulk_urb(
+					seg->isoc_pack_desc_urb, usb_dev,
+					usb_sndbulkpipe(usb_dev,
+						dto_epd->bEndpointAddress),
+					(void *)(&seg->xfer_hdr) +
+						xfer_hdr_size,
+					iso_pkt_descr_size,
+					wa_seg_iso_pack_desc_cb, seg);
+
+				/*
+				 * Fill in the xfer buffer information for the
+				 * first isoc frame.  Subsequent frames in this
+				 * segment will be filled in and sent from the
+				 * DTO completion routine, if needed.
+				 */
+				__wa_populate_dto_urb_isoc(xfer, seg,
+					xfer_isoc_frame_offset);
+				/* adjust starting frame offset for next seg. */
+				xfer_isoc_frame_offset += seg_isoc_frame_count;
 			} else {
-				/* do buffer or SG processing. */
-				seg->dto_urb->transfer_flags &=
-					~URB_NO_TRANSFER_DMA_MAP;
-				/* this should always be 0 before a resubmit. */
-				seg->dto_urb->num_mapped_sgs = 0;
+				/* fill in the xfer buffer information. */
+				result = __wa_populate_dto_urb(xfer, seg,
+							buf_itr, buf_itr_size);
+				if (result < 0)
+					goto error_seg_outbound_populate;
 
-				if (xfer->urb->transfer_buffer) {
-					seg->dto_urb->transfer_buffer =
-						xfer->urb->transfer_buffer +
-						buf_itr;
-					seg->dto_urb->sg = NULL;
-					seg->dto_urb->num_sgs = 0;
-				} else {
-					/* allocate an SG list to store seg_size
-					    bytes and copy the subset of the
-					    xfer->urb->sg that matches the
-					    buffer subset we are about to read.
-					*/
-					seg->dto_urb->sg =
-						wa_xfer_create_subset_sg(
-						xfer->urb->sg,
-						buf_itr, buf_itr_size,
-						&(seg->dto_urb->num_sgs));
-
-					if (!(seg->dto_urb->sg)) {
-						seg->dto_urb->num_sgs	= 0;
-						goto error_sg_alloc;
-					}
-
-					seg->dto_urb->transfer_buffer = NULL;
-				}
+				buf_itr += buf_itr_size;
+				buf_size -= buf_itr_size;
 			}
-			seg->dto_urb->transfer_buffer_length = buf_itr_size;
 		}
 		seg->status = WA_SEG_READY;
-		buf_itr += buf_itr_size;
-		buf_size -= buf_itr_size;
 	}
 	return 0;
 
-error_sg_alloc:
+	/*
+	 * Free the memory for the current segment which failed to init.
+	 * Use the fact that cnt is left at were it failed.  The remaining
+	 * segments will be cleaned up by wa_xfer_destroy.
+	 */
+error_iso_pack_desc_alloc:
+error_seg_outbound_populate:
 	usb_free_urb(xfer->seg[cnt]->dto_urb);
 error_dto_alloc:
 	kfree(xfer->seg[cnt]);
-	cnt--;
+	xfer->seg[cnt] = NULL;
 error_seg_kmalloc:
-	/* use the fact that cnt is left at were it failed */
-	for (; cnt >= 0; cnt--) {
-		if (xfer->seg[cnt] && xfer->is_inbound == 0) {
-			usb_free_urb(xfer->seg[cnt]->dto_urb);
-			kfree(xfer->seg[cnt]->dto_urb->sg);
-		}
-		kfree(xfer->seg[cnt]);
-	}
 error_segs_kzalloc:
 	return result;
 }
@@ -856,21 +1251,45 @@
 	wa_xfer_id_init(xfer);
 	__wa_xfer_setup_hdr0(xfer, xfer_hdr0, xfer_type, xfer_hdr_size);
 
-	/* Fill remainig headers */
+	/* Fill remaining headers */
 	xfer_hdr = xfer_hdr0;
-	transfer_size = urb->transfer_buffer_length;
-	xfer_hdr0->dwTransferLength = transfer_size > xfer->seg_size ?
-		xfer->seg_size : transfer_size;
-	transfer_size -=  xfer->seg_size;
-	for (cnt = 1; cnt < xfer->segs; cnt++) {
-		xfer_hdr = &xfer->seg[cnt]->xfer_hdr;
-		memcpy(xfer_hdr, xfer_hdr0, xfer_hdr_size);
-		xfer_hdr->bTransferSegment = cnt;
-		xfer_hdr->dwTransferLength = transfer_size > xfer->seg_size ?
-			cpu_to_le32(xfer->seg_size)
-			: cpu_to_le32(transfer_size);
-		xfer->seg[cnt]->status = WA_SEG_READY;
+	if (xfer_type == WA_XFER_TYPE_ISO) {
+		xfer_hdr0->dwTransferLength =
+			cpu_to_le32(xfer->seg[0]->isoc_size);
+		for (cnt = 1; cnt < xfer->segs; cnt++) {
+			struct wa_xfer_packet_info_hwaiso *packet_desc;
+			struct wa_seg *seg = xfer->seg[cnt];
+
+			xfer_hdr = &seg->xfer_hdr;
+			packet_desc = ((void *)xfer_hdr) + xfer_hdr_size;
+			/*
+			 * Copy values from the 0th header. Segment specific
+			 * values are set below.
+			 */
+			memcpy(xfer_hdr, xfer_hdr0, xfer_hdr_size);
+			xfer_hdr->bTransferSegment = cnt;
+			xfer_hdr->dwTransferLength =
+				cpu_to_le32(seg->isoc_size);
+			__wa_setup_isoc_packet_descr(packet_desc, xfer, seg);
+			seg->status = WA_SEG_READY;
+		}
+	} else {
+		transfer_size = urb->transfer_buffer_length;
+		xfer_hdr0->dwTransferLength = transfer_size > xfer->seg_size ?
+			cpu_to_le32(xfer->seg_size) :
+			cpu_to_le32(transfer_size);
 		transfer_size -=  xfer->seg_size;
+		for (cnt = 1; cnt < xfer->segs; cnt++) {
+			xfer_hdr = &xfer->seg[cnt]->xfer_hdr;
+			memcpy(xfer_hdr, xfer_hdr0, xfer_hdr_size);
+			xfer_hdr->bTransferSegment = cnt;
+			xfer_hdr->dwTransferLength =
+				transfer_size > xfer->seg_size ?
+					cpu_to_le32(xfer->seg_size)
+					: cpu_to_le32(transfer_size);
+			xfer->seg[cnt]->status = WA_SEG_READY;
+			transfer_size -=  xfer->seg_size;
+		}
 	}
 	xfer_hdr->bTransferSegment |= 0x80;	/* this is the last segment */
 	result = 0;
@@ -885,20 +1304,46 @@
  * rpipe->seg_lock is held!
  */
 static int __wa_seg_submit(struct wa_rpipe *rpipe, struct wa_xfer *xfer,
-			   struct wa_seg *seg)
+			   struct wa_seg *seg, int *dto_done)
 {
 	int result;
-	result = usb_submit_urb(&seg->urb, GFP_ATOMIC);
+
+	/* default to done unless we encounter a multi-frame isoc segment. */
+	*dto_done = 1;
+
+	/* submit the transfer request. */
+	result = usb_submit_urb(&seg->tr_urb, GFP_ATOMIC);
 	if (result < 0) {
-		printk(KERN_ERR "xfer %p#%u: REQ submit failed: %d\n",
-		       xfer, seg->index, result);
+		pr_err("%s: xfer %p#%u: REQ submit failed: %d\n",
+		       __func__, xfer, seg->index, result);
 		goto error_seg_submit;
 	}
+	/* submit the isoc packet descriptor if present. */
+	if (seg->isoc_pack_desc_urb) {
+		struct wahc *wa = xfer->wa;
+
+		result = usb_submit_urb(seg->isoc_pack_desc_urb, GFP_ATOMIC);
+		if (result < 0) {
+			pr_err("%s: xfer %p#%u: ISO packet descriptor submit failed: %d\n",
+			       __func__, xfer, seg->index, result);
+			goto error_iso_pack_desc_submit;
+		}
+		xfer->dto_isoc_frame_index = 0;
+		/*
+		 * If this segment contains more than one isoc frame, hold
+		 * onto the dto resource until we send all frames.
+		 * Only applies to non-Alereon devices.
+		 */
+		if (((wa->quirks & WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC) == 0)
+			&& (seg->isoc_frame_count > 1))
+			*dto_done = 0;
+	}
+	/* submit the out data if this is an out request. */
 	if (seg->dto_urb) {
 		result = usb_submit_urb(seg->dto_urb, GFP_ATOMIC);
 		if (result < 0) {
-			printk(KERN_ERR "xfer %p#%u: DTO submit failed: %d\n",
-			       xfer, seg->index, result);
+			pr_err("%s: xfer %p#%u: DTO submit failed: %d\n",
+			       __func__, xfer, seg->index, result);
 			goto error_dto_submit;
 		}
 	}
@@ -907,38 +1352,48 @@
 	return 0;
 
 error_dto_submit:
-	usb_unlink_urb(&seg->urb);
+	usb_unlink_urb(seg->isoc_pack_desc_urb);
+error_iso_pack_desc_submit:
+	usb_unlink_urb(&seg->tr_urb);
 error_seg_submit:
 	seg->status = WA_SEG_ERROR;
 	seg->result = result;
+	*dto_done = 1;
 	return result;
 }
 
 /*
- * Execute more queued request segments until the maximum concurrent allowed
+ * Execute more queued request segments until the maximum concurrent allowed.
+ * Return true if the DTO resource was acquired and released.
  *
  * The ugly unlock/lock sequence on the error path is needed as the
  * xfer->lock normally nests the seg_lock and not viceversa.
- *
  */
-static void wa_xfer_delayed_run(struct wa_rpipe *rpipe)
+static int __wa_xfer_delayed_run(struct wa_rpipe *rpipe, int *dto_waiting)
 {
-	int result;
+	int result, dto_acquired = 0, dto_done = 0;
 	struct device *dev = &rpipe->wa->usb_iface->dev;
 	struct wa_seg *seg;
 	struct wa_xfer *xfer;
 	unsigned long flags;
 
+	*dto_waiting = 0;
+
 	spin_lock_irqsave(&rpipe->seg_lock, flags);
 	while (atomic_read(&rpipe->segs_available) > 0
-	      && !list_empty(&rpipe->seg_list)) {
+	      && !list_empty(&rpipe->seg_list)
+	      && (dto_acquired = __wa_dto_try_get(rpipe->wa))) {
 		seg = list_first_entry(&(rpipe->seg_list), struct wa_seg,
 				 list_node);
 		list_del(&seg->list_node);
 		xfer = seg->xfer;
-		result = __wa_seg_submit(rpipe, xfer, seg);
-		dev_dbg(dev, "xfer %p#%u submitted from delayed [%d segments available] %d\n",
-			xfer, seg->index, atomic_read(&rpipe->segs_available), result);
+		result = __wa_seg_submit(rpipe, xfer, seg, &dto_done);
+		/* release the dto resource if this RPIPE is done with it. */
+		if (dto_done)
+			__wa_dto_put(rpipe->wa);
+		dev_dbg(dev, "xfer %p ID %08X#%u submitted from delayed [%d segments available] %d\n",
+			xfer, wa_xfer_id(xfer), seg->index,
+			atomic_read(&rpipe->segs_available), result);
 		if (unlikely(result < 0)) {
 			spin_unlock_irqrestore(&rpipe->seg_lock, flags);
 			spin_lock_irqsave(&xfer->lock, flags);
@@ -948,7 +1403,37 @@
 			spin_lock_irqsave(&rpipe->seg_lock, flags);
 		}
 	}
+	/*
+	 * Mark this RPIPE as waiting if dto was not acquired, there are
+	 * delayed segs and no active transfers to wake us up later.
+	 */
+	if (!dto_acquired && !list_empty(&rpipe->seg_list)
+		&& (atomic_read(&rpipe->segs_available) ==
+			le16_to_cpu(rpipe->descr.wRequests)))
+		*dto_waiting = 1;
+
 	spin_unlock_irqrestore(&rpipe->seg_lock, flags);
+
+	return dto_done;
+}
+
+static void wa_xfer_delayed_run(struct wa_rpipe *rpipe)
+{
+	int dto_waiting;
+	int dto_done = __wa_xfer_delayed_run(rpipe, &dto_waiting);
+
+	/*
+	 * If this RPIPE is waiting on the DTO resource, add it to the tail of
+	 * the waiting list.
+	 * Otherwise, if the WA DTO resource was acquired and released by
+	 *  __wa_xfer_delayed_run, another RPIPE may have attempted to acquire
+	 * DTO and failed during that time.  Check the delayed list and process
+	 * any waiters.  Start searching from the next RPIPE index.
+	 */
+	if (dto_waiting)
+		wa_add_delayed_rpipe(rpipe->wa, rpipe);
+	else if (dto_done)
+		wa_check_for_delayed_rpipes(rpipe->wa);
 }
 
 /*
@@ -960,7 +1445,7 @@
  */
 static int __wa_xfer_submit(struct wa_xfer *xfer)
 {
-	int result;
+	int result, dto_acquired = 0, dto_done = 0, dto_waiting = 0;
 	struct wahc *wa = xfer->wa;
 	struct device *dev = &wa->usb_iface->dev;
 	unsigned cnt;
@@ -979,27 +1464,58 @@
 	result = 0;
 	spin_lock_irqsave(&rpipe->seg_lock, flags);
 	for (cnt = 0; cnt < xfer->segs; cnt++) {
+		int delay_seg = 1;
+
 		available = atomic_read(&rpipe->segs_available);
 		empty = list_empty(&rpipe->seg_list);
 		seg = xfer->seg[cnt];
-		dev_dbg(dev, "xfer %p#%u: available %u empty %u (%s)\n",
-			xfer, cnt, available, empty,
-			available == 0 || !empty ? "delayed" : "submitted");
-		if (available == 0 || !empty) {
-			dev_dbg(dev, "xfer %p#%u: delayed\n", xfer, cnt);
+		if (available && empty) {
+			/*
+			 * Only attempt to acquire DTO if we have a segment
+			 * to send.
+			 */
+			dto_acquired = __wa_dto_try_get(rpipe->wa);
+			if (dto_acquired) {
+				delay_seg = 0;
+				result = __wa_seg_submit(rpipe, xfer, seg,
+							&dto_done);
+				dev_dbg(dev, "xfer %p ID 0x%08X#%u: available %u empty %u submitted\n",
+					xfer, wa_xfer_id(xfer), cnt, available,
+					empty);
+				if (dto_done)
+					__wa_dto_put(rpipe->wa);
+
+				if (result < 0) {
+					__wa_xfer_abort(xfer);
+					goto error_seg_submit;
+				}
+			}
+		}
+
+		if (delay_seg) {
+			dev_dbg(dev, "xfer %p ID 0x%08X#%u: available %u empty %u delayed\n",
+				xfer, wa_xfer_id(xfer), cnt, available,  empty);
 			seg->status = WA_SEG_DELAYED;
 			list_add_tail(&seg->list_node, &rpipe->seg_list);
-		} else {
-			result = __wa_seg_submit(rpipe, xfer, seg);
-			if (result < 0) {
-				__wa_xfer_abort(xfer);
-				goto error_seg_submit;
-			}
 		}
 		xfer->segs_submitted++;
 	}
 error_seg_submit:
+	/*
+	 * Mark this RPIPE as waiting if dto was not acquired, there are
+	 * delayed segs and no active transfers to wake us up later.
+	 */
+	if (!dto_acquired && !list_empty(&rpipe->seg_list)
+		&& (atomic_read(&rpipe->segs_available) ==
+			le16_to_cpu(rpipe->descr.wRequests)))
+		dto_waiting = 1;
 	spin_unlock_irqrestore(&rpipe->seg_lock, flags);
+
+	if (dto_waiting)
+		wa_add_delayed_rpipe(rpipe->wa, rpipe);
+	else if (dto_done)
+		wa_check_for_delayed_rpipes(rpipe->wa);
+
 	return result;
 }
 
@@ -1025,7 +1541,7 @@
  * result never kicks in, the xfer will timeout from the USB code and
  * dequeue() will be called.
  */
-static void wa_urb_enqueue_b(struct wa_xfer *xfer)
+static int wa_urb_enqueue_b(struct wa_xfer *xfer)
 {
 	int result;
 	unsigned long flags;
@@ -1036,18 +1552,22 @@
 	unsigned done;
 
 	result = rpipe_get_by_ep(wa, xfer->ep, urb, xfer->gfp);
-	if (result < 0)
+	if (result < 0) {
+		pr_err("%s: error_rpipe_get\n", __func__);
 		goto error_rpipe_get;
+	}
 	result = -ENODEV;
 	/* FIXME: segmentation broken -- kills DWA */
 	mutex_lock(&wusbhc->mutex);		/* get a WUSB dev */
 	if (urb->dev == NULL) {
 		mutex_unlock(&wusbhc->mutex);
+		pr_err("%s: error usb dev gone\n", __func__);
 		goto error_dev_gone;
 	}
 	wusb_dev = __wusb_dev_get_by_usb_dev(wusbhc, urb->dev);
 	if (wusb_dev == NULL) {
 		mutex_unlock(&wusbhc->mutex);
+		pr_err("%s: error wusb dev gone\n", __func__);
 		goto error_dev_gone;
 	}
 	mutex_unlock(&wusbhc->mutex);
@@ -1055,21 +1575,28 @@
 	spin_lock_irqsave(&xfer->lock, flags);
 	xfer->wusb_dev = wusb_dev;
 	result = urb->status;
-	if (urb->status != -EINPROGRESS)
+	if (urb->status != -EINPROGRESS) {
+		pr_err("%s: error_dequeued\n", __func__);
 		goto error_dequeued;
+	}
 
 	result = __wa_xfer_setup(xfer, urb);
-	if (result < 0)
+	if (result < 0) {
+		pr_err("%s: error_xfer_setup\n", __func__);
 		goto error_xfer_setup;
+	}
 	result = __wa_xfer_submit(xfer);
-	if (result < 0)
+	if (result < 0) {
+		pr_err("%s: error_xfer_submit\n", __func__);
 		goto error_xfer_submit;
+	}
 	spin_unlock_irqrestore(&xfer->lock, flags);
-	return;
+	return 0;
 
-	/* this is basically wa_xfer_completion() broken up wa_xfer_giveback()
-	 * does a wa_xfer_put() that will call wa_xfer_destroy() and clean
-	 * upundo setup().
+	/*
+	 * this is basically wa_xfer_completion() broken up wa_xfer_giveback()
+	 * does a wa_xfer_put() that will call wa_xfer_destroy() and undo
+	 * setup().
 	 */
 error_xfer_setup:
 error_dequeued:
@@ -1081,8 +1608,7 @@
 	rpipe_put(xfer->ep->hcpriv);
 error_rpipe_get:
 	xfer->result = result;
-	wa_xfer_giveback(xfer);
-	return;
+	return result;
 
 error_xfer_submit:
 	done = __wa_xfer_is_done(xfer);
@@ -1090,6 +1616,8 @@
 	spin_unlock_irqrestore(&xfer->lock, flags);
 	if (done)
 		wa_xfer_completion(xfer);
+	/* return success since the completion routine will run. */
+	return 0;
 }
 
 /*
@@ -1123,7 +1651,8 @@
 		list_del_init(&xfer->list_node);
 
 		urb = xfer->urb;
-		wa_urb_enqueue_b(xfer);
+		if (wa_urb_enqueue_b(xfer) < 0)
+			wa_xfer_giveback(xfer);
 		usb_put_urb(urb);	/* taken when queuing */
 	}
 }
@@ -1229,7 +1758,19 @@
 		spin_unlock_irqrestore(&wa->xfer_list_lock, my_flags);
 		queue_work(wusbd, &wa->xfer_enqueue_work);
 	} else {
-		wa_urb_enqueue_b(xfer);
+		result = wa_urb_enqueue_b(xfer);
+		if (result < 0) {
+			/*
+			 * URB submit/enqueue failed.  Clean up, return an
+			 * error and do not run the callback.  This avoids
+			 * an infinite submit/complete loop.
+			 */
+			dev_err(dev, "%s: URB enqueue failed: %d\n",
+			   __func__, result);
+			wa_put(xfer->wa);
+			wa_xfer_put(xfer);
+			return result;
+		}
 	}
 	return 0;
 
@@ -1264,7 +1805,7 @@
 	struct wa_xfer *xfer;
 	struct wa_seg *seg;
 	struct wa_rpipe *rpipe;
-	unsigned cnt;
+	unsigned cnt, done = 0, xfer_abort_pending;
 	unsigned rpipe_ready = 0;
 
 	xfer = urb->hcpriv;
@@ -1278,6 +1819,7 @@
 		goto out;
 	}
 	spin_lock_irqsave(&xfer->lock, flags);
+	pr_debug("%s: DEQUEUE xfer id 0x%08X\n", __func__, wa_xfer_id(xfer));
 	rpipe = xfer->ep->hcpriv;
 	if (rpipe == NULL) {
 		pr_debug("%s: xfer id 0x%08X has no RPIPE.  %s",
@@ -1293,9 +1835,11 @@
 	if (xfer->seg == NULL)  	/* still hasn't reached */
 		goto out_unlock;	/* setup(), enqueue_b() completes */
 	/* Ok, the xfer is in flight already, it's been setup and submitted.*/
-	__wa_xfer_abort(xfer);
+	xfer_abort_pending = __wa_xfer_abort(xfer) >= 0;
 	for (cnt = 0; cnt < xfer->segs; cnt++) {
 		seg = xfer->seg[cnt];
+		pr_debug("%s: xfer id 0x%08X#%d status = %d\n",
+			__func__, wa_xfer_id(xfer), cnt, seg->status);
 		switch (seg->status) {
 		case WA_SEG_NOTREADY:
 		case WA_SEG_READY:
@@ -1304,42 +1848,50 @@
 			WARN_ON(1);
 			break;
 		case WA_SEG_DELAYED:
+			/*
+			 * delete from rpipe delayed list.  If no segments on
+			 * this xfer have been submitted, __wa_xfer_is_done will
+			 * trigger a giveback below.  Otherwise, the submitted
+			 * segments will be completed in the DTI interrupt.
+			 */
 			seg->status = WA_SEG_ABORTED;
 			spin_lock_irqsave(&rpipe->seg_lock, flags2);
 			list_del(&seg->list_node);
 			xfer->segs_done++;
-			rpipe_ready = rpipe_avail_inc(rpipe);
 			spin_unlock_irqrestore(&rpipe->seg_lock, flags2);
 			break;
-		case WA_SEG_SUBMITTED:
-			seg->status = WA_SEG_ABORTED;
-			usb_unlink_urb(&seg->urb);
-			if (xfer->is_inbound == 0)
-				usb_unlink_urb(seg->dto_urb);
-			xfer->segs_done++;
-			rpipe_ready = rpipe_avail_inc(rpipe);
-			break;
-		case WA_SEG_PENDING:
-			seg->status = WA_SEG_ABORTED;
-			xfer->segs_done++;
-			rpipe_ready = rpipe_avail_inc(rpipe);
-			break;
-		case WA_SEG_DTI_PENDING:
-			usb_unlink_urb(wa->dti_urb);
-			seg->status = WA_SEG_ABORTED;
-			xfer->segs_done++;
-			rpipe_ready = rpipe_avail_inc(rpipe);
-			break;
 		case WA_SEG_DONE:
 		case WA_SEG_ERROR:
 		case WA_SEG_ABORTED:
 			break;
+			/*
+			 * In the states below, the HWA device already knows
+			 * about the transfer.  If an abort request was sent,
+			 * allow the HWA to process it and wait for the
+			 * results.  Otherwise, the DTI state and seg completed
+			 * counts can get out of sync.
+			 */
+		case WA_SEG_SUBMITTED:
+		case WA_SEG_PENDING:
+		case WA_SEG_DTI_PENDING:
+			/*
+			 * Check if the abort was successfully sent.  This could
+			 * be false if the HWA has been removed but we haven't
+			 * gotten the disconnect notification yet.
+			 */
+			if (!xfer_abort_pending) {
+				seg->status = WA_SEG_ABORTED;
+				rpipe_ready = rpipe_avail_inc(rpipe);
+				xfer->segs_done++;
+			}
+			break;
 		}
 	}
 	xfer->result = urb->status;	/* -ENOENT or -ECONNRESET */
-	__wa_xfer_is_done(xfer);
+	done = __wa_xfer_is_done(xfer);
 	spin_unlock_irqrestore(&xfer->lock, flags);
-	wa_xfer_completion(xfer);
+	if (done)
+		wa_xfer_completion(xfer);
 	if (rpipe_ready)
 		wa_xfer_delayed_run(rpipe);
 	return 0;
@@ -1410,13 +1962,56 @@
 }
 
 /*
+ * If a last segment flag and/or a transfer result error is encountered,
+ * no other segment transfer results will be returned from the device.
+ * Mark the remaining submitted or pending xfers as completed so that
+ * the xfer will complete cleanly.
+ */
+static void wa_complete_remaining_xfer_segs(struct wa_xfer *xfer,
+		struct wa_seg *incoming_seg)
+{
+	int index;
+	struct wa_rpipe *rpipe = xfer->ep->hcpriv;
+
+	for (index = incoming_seg->index + 1; index < xfer->segs_submitted;
+		index++) {
+		struct wa_seg *current_seg = xfer->seg[index];
+
+		BUG_ON(current_seg == NULL);
+
+		switch (current_seg->status) {
+		case WA_SEG_SUBMITTED:
+		case WA_SEG_PENDING:
+		case WA_SEG_DTI_PENDING:
+			rpipe_avail_inc(rpipe);
+		/*
+		 * do not increment RPIPE avail for the WA_SEG_DELAYED case
+		 * since it has not been submitted to the RPIPE.
+		 */
+		case WA_SEG_DELAYED:
+			xfer->segs_done++;
+			current_seg->status = incoming_seg->status;
+			break;
+		case WA_SEG_ABORTED:
+			break;
+		default:
+			WARN(1, "%s: xfer 0x%08X#%d. bad seg status = %d\n",
+				__func__, wa_xfer_id(xfer), index,
+				current_seg->status);
+			break;
+		}
+	}
+}
+
+/*
  * Process a xfer result completion message
  *
- * inbound transfers: need to schedule a DTI read
+ * inbound transfers: need to schedule a buf_in_urb read
  *
  * FIXME: this function needs to be broken up in parts
  */
-static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer)
+static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer,
+		struct wa_xfer_result *xfer_result)
 {
 	int result;
 	struct device *dev = &wa->usb_iface->dev;
@@ -1424,8 +2019,7 @@
 	u8 seg_idx;
 	struct wa_seg *seg;
 	struct wa_rpipe *rpipe;
-	struct wa_xfer_result *xfer_result = wa->xfer_result;
-	u8 done = 0;
+	unsigned done = 0;
 	u8 usb_status;
 	unsigned rpipe_ready = 0;
 
@@ -1436,8 +2030,8 @@
 	seg = xfer->seg[seg_idx];
 	rpipe = xfer->ep->hcpriv;
 	usb_status = xfer_result->bTransferStatus;
-	dev_dbg(dev, "xfer %p#%u: bTransferStatus 0x%02x (seg status %u)\n",
-		xfer, seg_idx, usb_status, seg->status);
+	dev_dbg(dev, "xfer %p ID 0x%08X#%u: bTransferStatus 0x%02x (seg status %u)\n",
+		xfer, wa_xfer_id(xfer), seg_idx, usb_status, seg->status);
 	if (seg->status == WA_SEG_ABORTED
 	    || seg->status == WA_SEG_ERROR)	/* already handled */
 		goto segment_aborted;
@@ -1453,12 +2047,19 @@
 		seg->result = wa_xfer_status_to_errno(usb_status);
 		dev_err(dev, "DTI: xfer %p#:%08X:%u failed (0x%02x)\n",
 			xfer, xfer->id, seg->index, usb_status);
+		seg->status = ((usb_status & 0x7F) == WA_XFER_STATUS_ABORTED) ?
+			WA_SEG_ABORTED : WA_SEG_ERROR;
 		goto error_complete;
 	}
 	/* FIXME: we ignore warnings, tally them for stats */
 	if (usb_status & 0x40) 		/* Warning?... */
 		usb_status = 0;		/* ... pass */
-	if (xfer->is_inbound) {	/* IN data phase: read to buffer */
+	if (usb_pipeisoc(xfer->urb->pipe)) {
+		/* set up WA state to read the isoc packet status next. */
+		wa->dti_isoc_xfer_in_progress = wa_xfer_id(xfer);
+		wa->dti_isoc_xfer_seg = seg_idx;
+		wa->dti_state = WA_DTI_ISOC_PACKET_STATUS_PENDING;
+	} else if (xfer->is_inbound) {	/* IN data phase: read to buffer */
 		seg->status = WA_SEG_DTI_PENDING;
 		BUG_ON(wa->buf_in_urb->status == -EINPROGRESS);
 		/* this should always be 0 before a resubmit. */
@@ -1535,12 +2136,14 @@
 			xfer, seg_idx, result);
 	seg->result = result;
 	kfree(wa->buf_in_urb->sg);
+	wa->buf_in_urb->sg = NULL;
 error_sg_alloc:
 	__wa_xfer_abort(xfer);
-error_complete:
 	seg->status = WA_SEG_ERROR;
+error_complete:
 	xfer->segs_done++;
 	rpipe_ready = rpipe_avail_inc(rpipe);
+	wa_complete_remaining_xfer_segs(xfer, seg);
 	done = __wa_xfer_is_done(xfer);
 	/*
 	 * queue work item to clear STALL for control endpoints.
@@ -1552,10 +2155,8 @@
 
 		dev_info(dev, "Control EP stall.  Queue delayed work.\n");
 		spin_lock_irq(&wa->xfer_list_lock);
-		/* remove xfer from xfer_list. */
-		list_del(&xfer->list_node);
-		/* add xfer to xfer_errored_list. */
-		list_add_tail(&xfer->list_node, &wa->xfer_errored_list);
+		/* move xfer from xfer_list to xfer_errored_list. */
+		list_move_tail(&xfer->list_node, &wa->xfer_errored_list);
 		spin_unlock_irq(&wa->xfer_list_lock);
 		spin_unlock_irqrestore(&xfer->lock, flags);
 		queue_work(wusbd, &wa->xfer_error_work);
@@ -1587,6 +2188,90 @@
 }
 
 /*
+ * Process a isochronous packet status message
+ *
+ * inbound transfers: need to schedule a buf_in_urb read
+ */
+static void wa_process_iso_packet_status(struct wahc *wa, struct urb *urb)
+{
+	struct device *dev = &wa->usb_iface->dev;
+	struct wa_xfer_packet_status_hwaiso *packet_status;
+	struct wa_xfer_packet_status_len_hwaiso *status_array;
+	struct wa_xfer *xfer;
+	unsigned long flags;
+	struct wa_seg *seg;
+	struct wa_rpipe *rpipe;
+	unsigned done = 0;
+	unsigned rpipe_ready = 0, seg_index;
+	int expected_size;
+
+	/* We have a xfer result buffer; check it */
+	dev_dbg(dev, "DTI: isoc packet status %d bytes at %p\n",
+		urb->actual_length, urb->transfer_buffer);
+	packet_status = (struct wa_xfer_packet_status_hwaiso *)(wa->dti_buf);
+	if (packet_status->bPacketType != WA_XFER_ISO_PACKET_STATUS) {
+		dev_err(dev, "DTI Error: isoc packet status--bad type 0x%02x\n",
+			packet_status->bPacketType);
+		goto error_parse_buffer;
+	}
+	xfer = wa_xfer_get_by_id(wa, wa->dti_isoc_xfer_in_progress);
+	if (xfer == NULL) {
+		dev_err(dev, "DTI Error: isoc packet status--unknown xfer 0x%08x\n",
+			wa->dti_isoc_xfer_in_progress);
+		goto error_parse_buffer;
+	}
+	spin_lock_irqsave(&xfer->lock, flags);
+	if (unlikely(wa->dti_isoc_xfer_seg >= xfer->segs))
+		goto error_bad_seg;
+	seg = xfer->seg[wa->dti_isoc_xfer_seg];
+	rpipe = xfer->ep->hcpriv;
+	expected_size = sizeof(*packet_status) +
+			(sizeof(packet_status->PacketStatus[0]) *
+			seg->isoc_frame_count);
+	if (urb->actual_length != expected_size) {
+		dev_err(dev, "DTI Error: isoc packet status--bad urb length (%d bytes vs %d needed)\n",
+			urb->actual_length, expected_size);
+		goto error_bad_seg;
+	}
+	if (le16_to_cpu(packet_status->wLength) != expected_size) {
+		dev_err(dev, "DTI Error: isoc packet status--bad length %u\n",
+			le16_to_cpu(packet_status->wLength));
+		goto error_bad_seg;
+	}
+	/* isoc packet status and lengths back xfer urb. */
+	status_array = packet_status->PacketStatus;
+	for (seg_index = 0; seg_index < seg->isoc_frame_count; ++seg_index) {
+		xfer->urb->iso_frame_desc[seg->index].status =
+			wa_xfer_status_to_errno(
+			le16_to_cpu(status_array[seg_index].PacketStatus));
+		xfer->urb->iso_frame_desc[seg->index].actual_length =
+			le16_to_cpu(status_array[seg_index].PacketLength);
+	}
+
+	if (!xfer->is_inbound) {
+		/* OUT transfer, complete it -- */
+		seg->status = WA_SEG_DONE;
+		xfer->segs_done++;
+		rpipe_ready = rpipe_avail_inc(rpipe);
+		done = __wa_xfer_is_done(xfer);
+	}
+	spin_unlock_irqrestore(&xfer->lock, flags);
+	wa->dti_state = WA_DTI_TRANSFER_RESULT_PENDING;
+	if (done)
+		wa_xfer_completion(xfer);
+	if (rpipe_ready)
+		wa_xfer_delayed_run(rpipe);
+	wa_xfer_put(xfer);
+	return;
+
+error_bad_seg:
+	spin_unlock_irqrestore(&xfer->lock, flags);
+	wa_xfer_put(xfer);
+error_parse_buffer:
+	return;
+}
+
+/*
  * Callback for the IN data phase
  *
  * If successful transition state; otherwise, take a note of the
@@ -1687,56 +2372,61 @@
  * We go back to OFF when we detect a ENOENT or ESHUTDOWN (or too many
  * errors) in the URBs.
  */
-static void wa_xfer_result_cb(struct urb *urb)
+static void wa_dti_cb(struct urb *urb)
 {
 	int result;
 	struct wahc *wa = urb->context;
 	struct device *dev = &wa->usb_iface->dev;
-	struct wa_xfer_result *xfer_result;
 	u32 xfer_id;
-	struct wa_xfer *xfer;
 	u8 usb_status;
 
 	BUG_ON(wa->dti_urb != urb);
 	switch (wa->dti_urb->status) {
 	case 0:
-		/* We have a xfer result buffer; check it */
-		dev_dbg(dev, "DTI: xfer result %d bytes at %p\n",
-			urb->actual_length, urb->transfer_buffer);
-		if (wa->dti_urb->actual_length != sizeof(*xfer_result)) {
-			dev_err(dev, "DTI Error: xfer result--bad size "
-				"xfer result (%d bytes vs %zu needed)\n",
-				urb->actual_length, sizeof(*xfer_result));
-			break;
+		if (wa->dti_state == WA_DTI_TRANSFER_RESULT_PENDING) {
+			struct wa_xfer_result *xfer_result;
+			struct wa_xfer *xfer;
+
+			/* We have a xfer result buffer; check it */
+			dev_dbg(dev, "DTI: xfer result %d bytes at %p\n",
+				urb->actual_length, urb->transfer_buffer);
+			if (urb->actual_length != sizeof(*xfer_result)) {
+				dev_err(dev, "DTI Error: xfer result--bad size xfer result (%d bytes vs %zu needed)\n",
+					urb->actual_length,
+					sizeof(*xfer_result));
+				break;
+			}
+			xfer_result = (struct wa_xfer_result *)(wa->dti_buf);
+			if (xfer_result->hdr.bLength != sizeof(*xfer_result)) {
+				dev_err(dev, "DTI Error: xfer result--bad header length %u\n",
+					xfer_result->hdr.bLength);
+				break;
+			}
+			if (xfer_result->hdr.bNotifyType != WA_XFER_RESULT) {
+				dev_err(dev, "DTI Error: xfer result--bad header type 0x%02x\n",
+					xfer_result->hdr.bNotifyType);
+				break;
+			}
+			usb_status = xfer_result->bTransferStatus & 0x3f;
+			if (usb_status == WA_XFER_STATUS_NOT_FOUND)
+				/* taken care of already */
+				break;
+			xfer_id = le32_to_cpu(xfer_result->dwTransferID);
+			xfer = wa_xfer_get_by_id(wa, xfer_id);
+			if (xfer == NULL) {
+				/* FIXME: transaction not found. */
+				dev_err(dev, "DTI Error: xfer result--unknown xfer 0x%08x (status 0x%02x)\n",
+					xfer_id, usb_status);
+				break;
+			}
+			wa_xfer_result_chew(wa, xfer, xfer_result);
+			wa_xfer_put(xfer);
+		} else if (wa->dti_state == WA_DTI_ISOC_PACKET_STATUS_PENDING) {
+			wa_process_iso_packet_status(wa, urb);
+		} else {
+			dev_err(dev, "DTI Error: unexpected EP state = %d\n",
+				wa->dti_state);
 		}
-		xfer_result = wa->xfer_result;
-		if (xfer_result->hdr.bLength != sizeof(*xfer_result)) {
-			dev_err(dev, "DTI Error: xfer result--"
-				"bad header length %u\n",
-				xfer_result->hdr.bLength);
-			break;
-		}
-		if (xfer_result->hdr.bNotifyType != WA_XFER_RESULT) {
-			dev_err(dev, "DTI Error: xfer result--"
-				"bad header type 0x%02x\n",
-				xfer_result->hdr.bNotifyType);
-			break;
-		}
-		usb_status = xfer_result->bTransferStatus & 0x3f;
-		if (usb_status == WA_XFER_STATUS_NOT_FOUND)
-			/* taken care of already */
-			break;
-		xfer_id = xfer_result->dwTransferID;
-		xfer = wa_xfer_get_by_id(wa, xfer_id);
-		if (xfer == NULL) {
-			/* FIXME: transaction might have been cancelled */
-			dev_err(dev, "DTI Error: xfer result--"
-				"unknown xfer 0x%08x (status 0x%02x)\n",
-				xfer_id, usb_status);
-			break;
-		}
-		wa_xfer_result_chew(wa, xfer);
-		wa_xfer_put(xfer);
 		break;
 	case -ENOENT:		/* (we killed the URB)...so, no broadcast */
 	case -ESHUTDOWN:	/* going away! */
@@ -1777,7 +2467,7 @@
  * don't really set it up and start it until the first xfer complete
  * notification arrives, which is what we do here.
  *
- * Follow up in wa_xfer_result_cb(), as that's where the whole state
+ * Follow up in wa_dti_cb(), as that's where the whole state
  * machine starts.
  *
  * So here we just initialize the DTI URB for reading transfer result
@@ -1813,8 +2503,8 @@
 	usb_fill_bulk_urb(
 		wa->dti_urb, wa->usb_dev,
 		usb_rcvbulkpipe(wa->usb_dev, 0x80 | notif_xfer->bEndpoint),
-		wa->xfer_result, wa->xfer_result_size,
-		wa_xfer_result_cb, wa);
+		wa->dti_buf, wa->dti_buf_size,
+		wa_dti_cb, wa);
 
 	wa->buf_in_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (wa->buf_in_urb == NULL) {
@@ -1836,6 +2526,7 @@
 
 error_dti_urb_submit:
 	usb_put_urb(wa->buf_in_urb);
+	wa->buf_in_urb = NULL;
 error_buf_in_urb_alloc:
 	usb_put_urb(wa->dti_urb);
 	wa->dti_urb = NULL;
diff --git a/drivers/uwb/lc-dev.c b/drivers/uwb/lc-dev.c
index 9209eaf..80079b8 100644
--- a/drivers/uwb/lc-dev.c
+++ b/drivers/uwb/lc-dev.c
@@ -244,7 +244,7 @@
 static DEVICE_ATTR(RSSI, S_IRUGO | S_IWUSR, uwb_dev_RSSI_show, uwb_dev_RSSI_store);
 
 
-static struct attribute *dev_attrs[] = {
+static struct attribute *uwb_dev_attrs[] = {
 	&dev_attr_EUI_48.attr,
 	&dev_attr_DevAddr.attr,
 	&dev_attr_BPST.attr,
@@ -253,20 +253,10 @@
 	&dev_attr_RSSI.attr,
 	NULL,
 };
-
-static struct attribute_group dev_attr_group = {
-	.attrs = dev_attrs,
-};
-
-static const struct attribute_group *groups[] = {
-	&dev_attr_group,
-	NULL,
-};
+ATTRIBUTE_GROUPS(uwb_dev);
 
 /**
  * Device SYSFS registration
- *
- *
  */
 static int __uwb_dev_sys_add(struct uwb_dev *uwb_dev, struct device *parent_dev)
 {
@@ -276,7 +266,7 @@
 	/* Device sysfs files are only useful for neighbor devices not
 	   local radio controllers. */
 	if (&uwb_dev->rc->uwb_dev != uwb_dev)
-		dev->groups = groups;
+		dev->groups = uwb_dev_groups;
 	dev->parent = parent_dev;
 	dev_set_drvdata(dev, uwb_dev);
 
diff --git a/drivers/uwb/umc-bus.c b/drivers/uwb/umc-bus.c
index 5c5b3fc..e3ed6ff 100644
--- a/drivers/uwb/umc-bus.c
+++ b/drivers/uwb/umc-bus.c
@@ -201,6 +201,7 @@
 
 	return sprintf(buf, "0x%02x\n", umc->cap_id);
 }
+static DEVICE_ATTR_RO(capability_id);
 
 static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -208,12 +209,14 @@
 
 	return sprintf(buf, "0x%04x\n", umc->version);
 }
+static DEVICE_ATTR_RO(version);
 
-static struct device_attribute umc_dev_attrs[] = {
-	__ATTR_RO(capability_id),
-	__ATTR_RO(version),
-	__ATTR_NULL,
+static struct attribute *umc_dev_attrs[] = {
+	&dev_attr_capability_id.attr,
+	&dev_attr_version.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(umc_dev);
 
 struct bus_type umc_bus_type = {
 	.name		= "umc",
@@ -222,7 +225,7 @@
 	.remove		= umc_device_remove,
 	.suspend        = umc_device_suspend,
 	.resume         = umc_device_resume,
-	.dev_attrs	= umc_dev_attrs,
+	.dev_groups	= umc_dev_groups,
 };
 EXPORT_SYMBOL_GPL(umc_bus_type);
 
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index a9807de..4fb7a8f 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -545,6 +545,8 @@
 	long npage;
 	int ret = 0, prot = 0;
 	uint64_t mask;
+	struct vfio_dma *dma = NULL;
+	unsigned long pfn;
 
 	end = map->iova + map->size;
 
@@ -587,8 +589,6 @@
 	}
 
 	for (iova = map->iova; iova < end; iova += size, vaddr += size) {
-		struct vfio_dma *dma = NULL;
-		unsigned long pfn;
 		long i;
 
 		/* Pin a contiguous chunk of memory */
@@ -597,16 +597,15 @@
 		if (npage <= 0) {
 			WARN_ON(!npage);
 			ret = (int)npage;
-			break;
+			goto out;
 		}
 
 		/* Verify pages are not already mapped */
 		for (i = 0; i < npage; i++) {
 			if (iommu_iova_to_phys(iommu->domain,
 					       iova + (i << PAGE_SHIFT))) {
-				vfio_unpin_pages(pfn, npage, prot, true);
 				ret = -EBUSY;
-				break;
+				goto out_unpin;
 			}
 		}
 
@@ -616,8 +615,7 @@
 		if (ret) {
 			if (ret != -EBUSY ||
 			    map_try_harder(iommu, iova, pfn, npage, prot)) {
-				vfio_unpin_pages(pfn, npage, prot, true);
-				break;
+				goto out_unpin;
 			}
 		}
 
@@ -672,9 +670,8 @@
 			dma = kzalloc(sizeof(*dma), GFP_KERNEL);
 			if (!dma) {
 				iommu_unmap(iommu->domain, iova, size);
-				vfio_unpin_pages(pfn, npage, prot, true);
 				ret = -ENOMEM;
-				break;
+				goto out_unpin;
 			}
 
 			dma->size = size;
@@ -685,16 +682,21 @@
 		}
 	}
 
-	if (ret) {
-		struct vfio_dma *tmp;
-		iova = map->iova;
-		size = map->size;
-		while ((tmp = vfio_find_dma(iommu, iova, size))) {
-			int r = vfio_remove_dma_overlap(iommu, iova,
-							&size, tmp);
-			if (WARN_ON(r || !size))
-				break;
-		}
+	WARN_ON(ret);
+	mutex_unlock(&iommu->lock);
+	return ret;
+
+out_unpin:
+	vfio_unpin_pages(pfn, npage, prot, true);
+
+out:
+	iova = map->iova;
+	size = map->size;
+	while ((dma = vfio_find_dma(iommu, iova, size))) {
+		int r = vfio_remove_dma_overlap(iommu, iova,
+						&size, dma);
+		if (WARN_ON(r || !size))
+			break;
 	}
 
 	mutex_unlock(&iommu->lock);
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index ce5221f..e663921 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -1056,7 +1056,7 @@
 		if (data_direction != DMA_NONE) {
 			ret = vhost_scsi_map_iov_to_sgl(cmd,
 					&vq->iov[data_first], data_num,
-					data_direction == DMA_TO_DEVICE);
+					data_direction == DMA_FROM_DEVICE);
 			if (unlikely(ret)) {
 				vq_err(vq, "Failed to map iov to sgl\n");
 				goto err_free;
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index a54ccdc..22ad8524 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -361,37 +361,13 @@
 int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
 {
 	struct au1100fb_device *fbdev;
-	unsigned int len;
-	unsigned long start=0, off;
 
 	fbdev = to_au1100fb_device(fbi);
 
-	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
-		return -EINVAL;
-	}
-
-	start = fbdev->fb_phys & PAGE_MASK;
-	len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len);
-
-	off = vma->vm_pgoff << PAGE_SHIFT;
-
-	if ((vma->vm_end - vma->vm_start + off) > len) {
-		return -EINVAL;
-	}
-
-	off += start;
-	vma->vm_pgoff = off >> PAGE_SHIFT;
-
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 	pgprot_val(vma->vm_page_prot) |= (6 << 9); //CCA=6
 
-	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
-				vma->vm_end - vma->vm_start,
-				vma->vm_page_prot)) {
-		return -EAGAIN;
-	}
-
-	return 0;
+	return vm_iomap_memory(vma, fbdev->fb_phys, fbdev->fb_len);
 }
 
 static struct fb_ops au1100fb_ops =
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
index 301224e..1d02897 100644
--- a/drivers/video/au1200fb.c
+++ b/drivers/video/au1200fb.c
@@ -1233,34 +1233,13 @@
  * method mainly to allow the use of the TLB streaming flag (CCA=6)
  */
 static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-
 {
-	unsigned int len;
-	unsigned long start=0, off;
 	struct au1200fb_device *fbdev = info->par;
 
-	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
-		return -EINVAL;
-	}
-
-	start = fbdev->fb_phys & PAGE_MASK;
-	len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len);
-
-	off = vma->vm_pgoff << PAGE_SHIFT;
-
-	if ((vma->vm_end - vma->vm_start + off) > len) {
-		return -EINVAL;
-	}
-
-	off += start;
-	vma->vm_pgoff = off >> PAGE_SHIFT;
-
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 	pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */
 
-	return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
-				  vma->vm_end - vma->vm_start,
-				  vma->vm_page_prot);
+	return vm_iomap_memory(vma, fbdev->fb_phys, fbdev->fb_len);
 }
 
 static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c
index 0393d82..f7447f7 100644
--- a/drivers/video/backlight/atmel-pwm-bl.c
+++ b/drivers/video/backlight/atmel-pwm-bl.c
@@ -118,7 +118,7 @@
 	.update_status  = atmel_pwm_bl_set_intensity,
 };
 
-static int __init atmel_pwm_bl_probe(struct platform_device *pdev)
+static int atmel_pwm_bl_probe(struct platform_device *pdev)
 {
 	struct backlight_properties props;
 	const struct atmel_pwm_bl_platform_data *pdata;
@@ -202,7 +202,7 @@
 	return retval;
 }
 
-static int __exit atmel_pwm_bl_remove(struct platform_device *pdev)
+static int atmel_pwm_bl_remove(struct platform_device *pdev)
 {
 	struct atmel_pwm_bl *pwmbl = platform_get_drvdata(pdev);
 
@@ -220,10 +220,11 @@
 		.name = "atmel-pwm-bl",
 	},
 	/* REVISIT add suspend() and resume() */
-	.remove = __exit_p(atmel_pwm_bl_remove),
+	.probe = atmel_pwm_bl_probe,
+	.remove = atmel_pwm_bl_remove,
 };
 
-module_platform_driver_probe(atmel_pwm_bl_driver, atmel_pwm_bl_probe);
+module_platform_driver(atmel_pwm_bl_driver);
 
 MODULE_AUTHOR("Hans-Christian egtvedt <hans-christian.egtvedt@atmel.com>");
 MODULE_DESCRIPTION("Atmel PWM backlight driver");
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index 35687fd..4ad24f2 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -3,7 +3,7 @@
  *	core code for console driver using HP's STI firmware
  *
  *	Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
- *	Copyright (C) 2001-2003 Helge Deller <deller@gmx.de>
+ *	Copyright (C) 2001-2013 Helge Deller <deller@gmx.de>
  *	Copyright (C) 2001-2002 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
  * 
  * TODO:
@@ -30,7 +30,7 @@
 
 #include "../sticore.h"
 
-#define STI_DRIVERVERSION "Version 0.9a"
+#define STI_DRIVERVERSION "Version 0.9b"
 
 static struct sti_struct *default_sti __read_mostly;
 
@@ -73,28 +73,34 @@
 
 static int sti_init_graph(struct sti_struct *sti)
 {
-	struct sti_init_inptr_ext inptr_ext = { 0, };
-	struct sti_init_inptr inptr = {
-		.text_planes	= 3, /* # of text planes (max 3 for STI) */
-		.ext_ptr	= STI_PTR(&inptr_ext)
-	};
-	struct sti_init_outptr outptr = { 0, };
+	struct sti_init_inptr *inptr = &sti->sti_data->init_inptr;
+	struct sti_init_inptr_ext *inptr_ext = &sti->sti_data->init_inptr_ext;
+	struct sti_init_outptr *outptr = &sti->sti_data->init_outptr;
 	unsigned long flags;
-	int ret;
+	int ret, err;
 
 	spin_lock_irqsave(&sti->lock, flags);
 
-	ret = STI_CALL(sti->init_graph, &default_init_flags, &inptr,
-		&outptr, sti->glob_cfg);
+	memset(inptr, 0, sizeof(*inptr));
+	inptr->text_planes = 3; /* # of text planes (max 3 for STI) */
+	memset(inptr_ext, 0, sizeof(*inptr_ext));
+	inptr->ext_ptr = STI_PTR(inptr_ext);
+	outptr->errno = 0;
+
+	ret = sti_call(sti, sti->init_graph, &default_init_flags, inptr,
+		outptr, sti->glob_cfg);
+
+	if (ret >= 0)
+		sti->text_planes = outptr->text_planes;
+	err = outptr->errno;
 
 	spin_unlock_irqrestore(&sti->lock, flags);
 
 	if (ret < 0) {
-		printk(KERN_ERR "STI init_graph failed (ret %d, errno %d)\n",ret,outptr.errno);
+		pr_err("STI init_graph failed (ret %d, errno %d)\n", ret, err);
 		return -1;
 	}
 	
-	sti->text_planes = outptr.text_planes;
 	return 0;
 }
 
@@ -104,16 +110,18 @@
 
 static void sti_inq_conf(struct sti_struct *sti)
 {
-	struct sti_conf_inptr inptr = { 0, };
+	struct sti_conf_inptr *inptr = &sti->sti_data->inq_inptr;
+	struct sti_conf_outptr *outptr = &sti->sti_data->inq_outptr;
 	unsigned long flags;
 	s32 ret;
 
-	sti->outptr.ext_ptr = STI_PTR(&sti->outptr_ext);
+	outptr->ext_ptr = STI_PTR(&sti->sti_data->inq_outptr_ext);
 	
 	do {
 		spin_lock_irqsave(&sti->lock, flags);
-		ret = STI_CALL(sti->inq_conf, &default_conf_flags,
-			&inptr, &sti->outptr, sti->glob_cfg);
+		memset(inptr, 0, sizeof(*inptr));
+		ret = sti_call(sti, sti->inq_conf, &default_conf_flags,
+			inptr, outptr, sti->glob_cfg);
 		spin_unlock_irqrestore(&sti->lock, flags);
 	} while (ret == 1);
 }
@@ -126,7 +134,8 @@
 void
 sti_putc(struct sti_struct *sti, int c, int y, int x)
 {
-	struct sti_font_inptr inptr = {
+	struct sti_font_inptr *inptr = &sti->sti_data->font_inptr;
+	struct sti_font_inptr inptr_default = {
 		.font_start_addr= STI_PTR(sti->font->raw),
 		.index		= c_index(sti, c),
 		.fg_color	= c_fg(sti, c),
@@ -134,14 +143,15 @@
 		.dest_x		= x * sti->font_width,
 		.dest_y		= y * sti->font_height,
 	};
-	struct sti_font_outptr outptr = { 0, };
+	struct sti_font_outptr *outptr = &sti->sti_data->font_outptr;
 	s32 ret;
 	unsigned long flags;
 
 	do {
 		spin_lock_irqsave(&sti->lock, flags);
-		ret = STI_CALL(sti->font_unpmv, &default_font_flags,
-			&inptr, &outptr, sti->glob_cfg);
+		*inptr = inptr_default;
+		ret = sti_call(sti, sti->font_unpmv, &default_font_flags,
+			inptr, outptr, sti->glob_cfg);
 		spin_unlock_irqrestore(&sti->lock, flags);
 	} while (ret == 1);
 }
@@ -156,7 +166,8 @@
 sti_set(struct sti_struct *sti, int src_y, int src_x,
 	int height, int width, u8 color)
 {
-	struct sti_blkmv_inptr inptr = {
+	struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr;
+	struct sti_blkmv_inptr inptr_default = {
 		.fg_color	= color,
 		.bg_color	= color,
 		.src_x		= src_x,
@@ -166,14 +177,15 @@
 		.width		= width,
 		.height		= height,
 	};
-	struct sti_blkmv_outptr outptr = { 0, };
+	struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr;
 	s32 ret;
 	unsigned long flags;
 	
 	do {
 		spin_lock_irqsave(&sti->lock, flags);
-		ret = STI_CALL(sti->block_move, &clear_blkmv_flags,
-			&inptr, &outptr, sti->glob_cfg);
+		*inptr = inptr_default;
+		ret = sti_call(sti, sti->block_move, &clear_blkmv_flags,
+			inptr, outptr, sti->glob_cfg);
 		spin_unlock_irqrestore(&sti->lock, flags);
 	} while (ret == 1);
 }
@@ -182,7 +194,8 @@
 sti_clear(struct sti_struct *sti, int src_y, int src_x,
 	  int height, int width, int c)
 {
-	struct sti_blkmv_inptr inptr = {
+	struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr;
+	struct sti_blkmv_inptr inptr_default = {
 		.fg_color	= c_fg(sti, c),
 		.bg_color	= c_bg(sti, c),
 		.src_x		= src_x * sti->font_width,
@@ -192,14 +205,15 @@
 		.width		= width * sti->font_width,
 		.height		= height* sti->font_height,
 	};
-	struct sti_blkmv_outptr outptr = { 0, };
+	struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr;
 	s32 ret;
 	unsigned long flags;
 
 	do {
 		spin_lock_irqsave(&sti->lock, flags);
-		ret = STI_CALL(sti->block_move, &clear_blkmv_flags,
-			&inptr, &outptr, sti->glob_cfg);
+		*inptr = inptr_default;
+		ret = sti_call(sti, sti->block_move, &clear_blkmv_flags,
+			inptr, outptr, sti->glob_cfg);
 		spin_unlock_irqrestore(&sti->lock, flags);
 	} while (ret == 1);
 }
@@ -212,7 +226,8 @@
 sti_bmove(struct sti_struct *sti, int src_y, int src_x,
 	  int dst_y, int dst_x, int height, int width)
 {
-	struct sti_blkmv_inptr inptr = {
+	struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr;
+	struct sti_blkmv_inptr inptr_default = {
 		.src_x		= src_x * sti->font_width,
 		.src_y		= src_y * sti->font_height,
 		.dest_x		= dst_x * sti->font_width,
@@ -220,14 +235,15 @@
 		.width		= width * sti->font_width,
 		.height		= height* sti->font_height,
 	};
-	struct sti_blkmv_outptr outptr = { 0, };
+	struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr;
 	s32 ret;
 	unsigned long flags;
 
 	do {
 		spin_lock_irqsave(&sti->lock, flags);
-		ret = STI_CALL(sti->block_move, &default_blkmv_flags,
-			&inptr, &outptr, sti->glob_cfg);
+		*inptr = inptr_default;
+		ret = sti_call(sti, sti->block_move, &default_blkmv_flags,
+			inptr, outptr, sti->glob_cfg);
 		spin_unlock_irqrestore(&sti->lock, flags);
 	} while (ret == 1);
 }
@@ -284,7 +300,7 @@
 
 
 
-static char *font_name[MAX_STI_ROMS] = { "VGA8x16", };
+static char *font_name[MAX_STI_ROMS];
 static int font_index[MAX_STI_ROMS],
 	   font_height[MAX_STI_ROMS],
 	   font_width[MAX_STI_ROMS];
@@ -389,10 +405,10 @@
 		"%d used bits\n"
 		"%d planes\n"
 		"attributes %08x\n",
-		 sti->outptr.bits_per_pixel,
-		 sti->outptr.bits_used,
-		 sti->outptr.planes,
-		 sti->outptr.attributes));
+		 sti->sti_data->inq_outptr.bits_per_pixel,
+		 sti->sti_data->inq_outptr.bits_used,
+		 sti->sti_data->inq_outptr.planes,
+		 sti->sti_data->inq_outptr.attributes));
 }
 
 static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address,
@@ -402,24 +418,21 @@
 	struct sti_glob_cfg_ext *glob_cfg_ext;
 	void *save_addr;
 	void *sti_mem_addr;
-	const int save_addr_size = 1024;	/* XXX */
-	int i;
+	int i, size;
 
-	if (!sti->sti_mem_request)
+	if (sti->sti_mem_request < 256)
 		sti->sti_mem_request = 256; /* STI default */
 
-	glob_cfg = kzalloc(sizeof(*sti->glob_cfg), GFP_KERNEL);
-	glob_cfg_ext = kzalloc(sizeof(*glob_cfg_ext), GFP_KERNEL);
-	save_addr = kzalloc(save_addr_size, GFP_KERNEL);
-	sti_mem_addr = kzalloc(sti->sti_mem_request, GFP_KERNEL);
+	size = sizeof(struct sti_all_data) + sti->sti_mem_request - 256;
 
-	if (!(glob_cfg && glob_cfg_ext && save_addr && sti_mem_addr)) {
-		kfree(glob_cfg);
-		kfree(glob_cfg_ext);
-		kfree(save_addr);
-		kfree(sti_mem_addr);
+	sti->sti_data = kzalloc(size, STI_LOWMEM);
+	if (!sti->sti_data)
 		return -ENOMEM;
-	}
+
+	glob_cfg	= &sti->sti_data->glob_cfg;
+	glob_cfg_ext	= &sti->sti_data->glob_cfg_ext;
+	save_addr	= &sti->sti_data->save_addr;
+	sti_mem_addr	= &sti->sti_data->sti_mem_addr;
 
 	glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext);
 	glob_cfg->save_addr = STI_PTR(save_addr);
@@ -475,32 +488,31 @@
 	return 0;
 }
 
-#ifdef CONFIG_FB
+#ifdef CONFIG_FONTS
 static struct sti_cooked_font *
 sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
 {
-	const struct font_desc *fbfont;
+	const struct font_desc *fbfont = NULL;
 	unsigned int size, bpc;
 	void *dest;
 	struct sti_rom_font *nf;
 	struct sti_cooked_font *cooked_font;
 	
-	if (!fbfont_name || !strlen(fbfont_name))
-		return NULL;
-	fbfont = find_font(fbfont_name);
+	if (fbfont_name && strlen(fbfont_name))
+		fbfont = find_font(fbfont_name);
 	if (!fbfont)
 		fbfont = get_default_font(1024,768, ~(u32)0, ~(u32)0);
 	if (!fbfont)
 		return NULL;
 
-	DPRINTK((KERN_DEBUG "selected %dx%d fb-font %s\n",
-			fbfont->width, fbfont->height, fbfont->name));
+	pr_info("STI selected %dx%d framebuffer font %s for sticon\n",
+			fbfont->width, fbfont->height, fbfont->name);
 			
 	bpc = ((fbfont->width+7)/8) * fbfont->height; 
 	size = bpc * 256;
 	size += sizeof(struct sti_rom_font);
 
-	nf = kzalloc(size, GFP_KERNEL);
+	nf = kzalloc(size, STI_LOWMEM);
 	if (!nf)
 		return NULL;
 
@@ -637,7 +649,7 @@
 	unsigned char *n, *p, *q;
 	int size = f->raw->bytes_per_char*256+sizeof(struct sti_rom_font);
 	
-	n = kzalloc (4*size, GFP_KERNEL);
+	n = kzalloc(4*size, STI_LOWMEM);
 	if (!n)
 		return NULL;
 	p = n + 3;
@@ -673,7 +685,7 @@
 	sti_bmode_rom_copy(address + BMODE_LAST_ADDR_OFFS, sizeof(size), &size);
 
 	size = (size+3) / 4;
-	raw = kmalloc(size, GFP_KERNEL);
+	raw = kmalloc(size, STI_LOWMEM);
 	if (raw) {
 		sti_bmode_rom_copy(address, size, raw);
 		memmove (&raw->res004, &raw->type[0], 0x3c);
@@ -707,7 +719,7 @@
 	/* read the ROM size directly from the struct in ROM */ 
 	size = gsc_readl(address + offsetof(struct sti_rom,last_addr));
 
-	raw = kmalloc(size, GFP_KERNEL);
+	raw = kmalloc(size, STI_LOWMEM);
 	if (raw)
 		sti_rom_copy(address, size, raw);
 
@@ -743,6 +755,10 @@
 
 	address = (unsigned long) STI_PTR(raw);
 
+	pr_info("STI ROM supports 32 %sbit firmware functions.\n",
+		raw->alt_code_type == ALT_CODE_TYPE_PA_RISC_64
+		? "and 64 " : "");
+
 	sti->font_unpmv = address + (raw->font_unpmv & 0x03ffffff);
 	sti->block_move = address + (raw->block_move & 0x03ffffff);
 	sti->init_graph = address + (raw->init_graph & 0x03ffffff);
@@ -901,7 +917,8 @@
 	sti_dump_globcfg(sti->glob_cfg, sti->sti_mem_request);
 	sti_dump_outptr(sti);
 	
-	printk(KERN_INFO "    graphics card name: %s\n", sti->outptr.dev_name );
+	pr_info("    graphics card name: %s\n",
+		sti->sti_data->inq_outptr.dev_name);
 
 	sti_roms[num_sti_roms] = sti;
 	num_sti_roms++;
@@ -1073,6 +1090,29 @@
 }
 EXPORT_SYMBOL(sti_get_rom);
 
+
+int sti_call(const struct sti_struct *sti, unsigned long func,
+		const void *flags, void *inptr, void *outptr,
+		struct sti_glob_cfg *glob_cfg)
+{
+	unsigned long _flags = STI_PTR(flags);
+	unsigned long _inptr = STI_PTR(inptr);
+	unsigned long _outptr = STI_PTR(outptr);
+	unsigned long _glob_cfg = STI_PTR(glob_cfg);
+	int ret;
+
+#ifdef CONFIG_64BIT
+	/* Check for overflow when using 32bit STI on 64bit kernel. */
+	if (WARN_ONCE(_flags>>32 || _inptr>>32 || _outptr>>32 || _glob_cfg>>32,
+			"Out of 32bit-range pointers!"))
+		return -1;
+#endif
+
+	ret = pdc_sti_call(func, _flags, _inptr, _outptr, _glob_cfg);
+
+	return ret;
+}
+
 MODULE_AUTHOR("Philipp Rumpf, Helge Deller, Thomas Bogendoerfer");
 MODULE_DESCRIPTION("Core STI driver for HP's NGLE series graphics cards in HP PARISC machines");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index 5788678..1c446bc 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -1641,67 +1641,6 @@
 	cyber2000fb_set_par(&cfb->fb);
 }
 
-#ifdef CONFIG_ARCH_SHARK
-
-#include <mach/framebuffer.h>
-
-static int cyberpro_vl_probe(void)
-{
-	struct cfb_info *cfb;
-	int err = -ENOMEM;
-
-	if (!request_mem_region(FB_START, FB_SIZE, "CyberPro2010"))
-		return err;
-
-	cfb = cyberpro_alloc_fb_info(ID_CYBERPRO_2010, "CyberPro2010");
-	if (!cfb)
-		goto failed_release;
-
-	cfb->irq = -1;
-	cfb->region = ioremap(FB_START, FB_SIZE);
-	if (!cfb->region)
-		goto failed_ioremap;
-
-	cfb->regs = cfb->region + MMIO_OFFSET;
-	cfb->fb.device = NULL;
-	cfb->fb.fix.mmio_start = FB_START + MMIO_OFFSET;
-	cfb->fb.fix.smem_start = FB_START;
-
-	/*
-	 * Bring up the hardware.  This is expected to enable access
-	 * to the linear memory region, and allow access to the memory
-	 * mapped registers.  Also, mem_ctl1 and mem_ctl2 must be
-	 * initialised.
-	 */
-	cyber2000fb_writeb(0x18, 0x46e8, cfb);
-	cyber2000fb_writeb(0x01, 0x102, cfb);
-	cyber2000fb_writeb(0x08, 0x46e8, cfb);
-	cyber2000fb_writeb(EXT_BIU_MISC, 0x3ce, cfb);
-	cyber2000fb_writeb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf, cfb);
-
-	cfb->mclk_mult = 0xdb;
-	cfb->mclk_div  = 0x54;
-
-	err = cyberpro_common_probe(cfb);
-	if (err)
-		goto failed;
-
-	if (int_cfb_info == NULL)
-		int_cfb_info = cfb;
-
-	return 0;
-
-failed:
-	iounmap(cfb->region);
-failed_ioremap:
-	cyberpro_free_fb_info(cfb);
-failed_release:
-	release_mem_region(FB_START, FB_SIZE);
-
-	return err;
-}
-#endif /* CONFIG_ARCH_SHARK */
-
 /*
  * PCI specific support.
  */
@@ -1948,28 +1887,19 @@
 	cyber2000fb_setup(option);
 #endif
 
-#ifdef CONFIG_ARCH_SHARK
-	err = cyberpro_vl_probe();
-	if (!err)
-		ret = 0;
-#endif
-#ifdef CONFIG_PCI
 	err = pci_register_driver(&cyberpro_driver);
 	if (!err)
 		ret = 0;
-#endif
 
 	return ret ? err : 0;
 }
 module_init(cyber2000fb_init);
 
-#ifndef CONFIG_ARCH_SHARK
 static void __exit cyberpro_exit(void)
 {
 	pci_unregister_driver(&cyberpro_driver);
 }
 module_exit(cyberpro_exit);
-#endif
 
 MODULE_AUTHOR("Russell King");
 MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver");
diff --git a/drivers/video/exynos/Kconfig b/drivers/video/exynos/Kconfig
index 1b035b2e..1129d0e 100644
--- a/drivers/video/exynos/Kconfig
+++ b/drivers/video/exynos/Kconfig
@@ -16,6 +16,7 @@
 config EXYNOS_MIPI_DSI
 	bool "EXYNOS MIPI DSI driver support."
 	depends on ARCH_S5PV210 || ARCH_EXYNOS
+	select GENERIC_PHY
 	help
 	  This enables support for MIPI-DSI device.
 
@@ -29,7 +30,7 @@
 
 config EXYNOS_DP
 	bool "EXYNOS DP driver support"
-	depends on ARCH_EXYNOS
+	depends on OF && ARCH_EXYNOS
 	default n
 	help
 	  This enables support for DP device.
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
index 12bbede..5e1a715 100644
--- a/drivers/video/exynos/exynos_dp_core.c
+++ b/drivers/video/exynos/exynos_dp_core.c
@@ -19,8 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/of.h>
-
-#include <video/exynos_dp.h>
+#include <linux/phy/phy.h>
 
 #include "exynos_dp_core.h"
 
@@ -894,26 +893,17 @@
 		dev_err(dp->dev, "unable to config video\n");
 }
 
-#ifdef CONFIG_OF
-static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
+static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev)
 {
 	struct device_node *dp_node = dev->of_node;
-	struct exynos_dp_platdata *pd;
 	struct video_info *dp_video_config;
 
-	pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
-	if (!pd) {
-		dev_err(dev, "memory allocation for pdata failed\n");
-		return ERR_PTR(-ENOMEM);
-	}
 	dp_video_config = devm_kzalloc(dev,
 				sizeof(*dp_video_config), GFP_KERNEL);
-
 	if (!dp_video_config) {
 		dev_err(dev, "memory allocation for video config failed\n");
 		return ERR_PTR(-ENOMEM);
 	}
-	pd->video_info = dp_video_config;
 
 	dp_video_config->h_sync_polarity =
 		of_property_read_bool(dp_node, "hsync-active-high");
@@ -960,7 +950,7 @@
 		return ERR_PTR(-EINVAL);
 	}
 
-	return pd;
+	return dp_video_config;
 }
 
 static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
@@ -971,8 +961,11 @@
 
 	dp_phy_node = of_find_node_by_name(dp_phy_node, "dptx-phy");
 	if (!dp_phy_node) {
-		dev_err(dp->dev, "could not find dptx-phy node\n");
-		return -ENODEV;
+		dp->phy = devm_phy_get(dp->dev, "dp");
+		if (IS_ERR(dp->phy))
+			return PTR_ERR(dp->phy);
+		else
+			return 0;
 	}
 
 	if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
@@ -1003,48 +996,34 @@
 
 static void exynos_dp_phy_init(struct exynos_dp_device *dp)
 {
-	u32 reg;
+	if (dp->phy) {
+		phy_power_on(dp->phy);
+	} else if (dp->phy_addr) {
+		u32 reg;
 
-	reg = __raw_readl(dp->phy_addr);
-	reg |= dp->enable_mask;
-	__raw_writel(reg, dp->phy_addr);
+		reg = __raw_readl(dp->phy_addr);
+		reg |= dp->enable_mask;
+		__raw_writel(reg, dp->phy_addr);
+	}
 }
 
 static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
 {
-	u32 reg;
+	if (dp->phy) {
+		phy_power_off(dp->phy);
+	} else if (dp->phy_addr) {
+		u32 reg;
 
-	reg = __raw_readl(dp->phy_addr);
-	reg &= ~(dp->enable_mask);
-	__raw_writel(reg, dp->phy_addr);
+		reg = __raw_readl(dp->phy_addr);
+		reg &= ~(dp->enable_mask);
+		__raw_writel(reg, dp->phy_addr);
+	}
 }
-#else
-static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
-{
-	return NULL;
-}
-
-static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
-{
-	return -EINVAL;
-}
-
-static void exynos_dp_phy_init(struct exynos_dp_device *dp)
-{
-	return;
-}
-
-static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
-{
-	return;
-}
-#endif /* CONFIG_OF */
 
 static int exynos_dp_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	struct exynos_dp_device *dp;
-	struct exynos_dp_platdata *pdata;
 
 	int ret = 0;
 
@@ -1057,21 +1036,13 @@
 
 	dp->dev = &pdev->dev;
 
-	if (pdev->dev.of_node) {
-		pdata = exynos_dp_dt_parse_pdata(&pdev->dev);
-		if (IS_ERR(pdata))
-			return PTR_ERR(pdata);
+	dp->video_info = exynos_dp_dt_parse_pdata(&pdev->dev);
+	if (IS_ERR(dp->video_info))
+		return PTR_ERR(dp->video_info);
 
-		ret = exynos_dp_dt_parse_phydata(dp);
-		if (ret)
-			return ret;
-	} else {
-		pdata = pdev->dev.platform_data;
-		if (!pdata) {
-			dev_err(&pdev->dev, "no platform data\n");
-			return -EINVAL;
-		}
-	}
+	ret = exynos_dp_dt_parse_phydata(dp);
+	if (ret)
+		return ret;
 
 	dp->clock = devm_clk_get(&pdev->dev, "dp");
 	if (IS_ERR(dp->clock)) {
@@ -1095,15 +1066,7 @@
 
 	INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
 
-	dp->video_info = pdata->video_info;
-
-	if (pdev->dev.of_node) {
-		if (dp->phy_addr)
-			exynos_dp_phy_init(dp);
-	} else {
-		if (pdata->phy_init)
-			pdata->phy_init();
-	}
+	exynos_dp_phy_init(dp);
 
 	exynos_dp_init_dp(dp);
 
@@ -1121,18 +1084,11 @@
 
 static int exynos_dp_remove(struct platform_device *pdev)
 {
-	struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
 	struct exynos_dp_device *dp = platform_get_drvdata(pdev);
 
 	flush_work(&dp->hotplug_work);
 
-	if (pdev->dev.of_node) {
-		if (dp->phy_addr)
-			exynos_dp_phy_exit(dp);
-	} else {
-		if (pdata->phy_exit)
-			pdata->phy_exit();
-	}
+	exynos_dp_phy_exit(dp);
 
 	clk_disable_unprepare(dp->clock);
 
@@ -1143,20 +1099,13 @@
 #ifdef CONFIG_PM_SLEEP
 static int exynos_dp_suspend(struct device *dev)
 {
-	struct exynos_dp_platdata *pdata = dev->platform_data;
 	struct exynos_dp_device *dp = dev_get_drvdata(dev);
 
 	disable_irq(dp->irq);
 
 	flush_work(&dp->hotplug_work);
 
-	if (dev->of_node) {
-		if (dp->phy_addr)
-			exynos_dp_phy_exit(dp);
-	} else {
-		if (pdata->phy_exit)
-			pdata->phy_exit();
-	}
+	exynos_dp_phy_exit(dp);
 
 	clk_disable_unprepare(dp->clock);
 
@@ -1165,16 +1114,9 @@
 
 static int exynos_dp_resume(struct device *dev)
 {
-	struct exynos_dp_platdata *pdata = dev->platform_data;
 	struct exynos_dp_device *dp = dev_get_drvdata(dev);
 
-	if (dev->of_node) {
-		if (dp->phy_addr)
-			exynos_dp_phy_init(dp);
-	} else {
-		if (pdata->phy_init)
-			pdata->phy_init();
-	}
+	exynos_dp_phy_init(dp);
 
 	clk_prepare_enable(dp->clock);
 
@@ -1203,7 +1145,7 @@
 		.name	= "exynos-dp",
 		.owner	= THIS_MODULE,
 		.pm	= &exynos_dp_pm_ops,
-		.of_match_table = of_match_ptr(exynos_dp_match),
+		.of_match_table = exynos_dp_match,
 	},
 };
 
diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h
index 6c567bbf..607e36d 100644
--- a/drivers/video/exynos/exynos_dp_core.h
+++ b/drivers/video/exynos/exynos_dp_core.h
@@ -13,6 +13,99 @@
 #ifndef _EXYNOS_DP_CORE_H
 #define _EXYNOS_DP_CORE_H
 
+#define DP_TIMEOUT_LOOP_COUNT 100
+#define MAX_CR_LOOP 5
+#define MAX_EQ_LOOP 5
+
+enum link_rate_type {
+	LINK_RATE_1_62GBPS = 0x06,
+	LINK_RATE_2_70GBPS = 0x0a
+};
+
+enum link_lane_count_type {
+	LANE_COUNT1 = 1,
+	LANE_COUNT2 = 2,
+	LANE_COUNT4 = 4
+};
+
+enum link_training_state {
+	START,
+	CLOCK_RECOVERY,
+	EQUALIZER_TRAINING,
+	FINISHED,
+	FAILED
+};
+
+enum voltage_swing_level {
+	VOLTAGE_LEVEL_0,
+	VOLTAGE_LEVEL_1,
+	VOLTAGE_LEVEL_2,
+	VOLTAGE_LEVEL_3,
+};
+
+enum pre_emphasis_level {
+	PRE_EMPHASIS_LEVEL_0,
+	PRE_EMPHASIS_LEVEL_1,
+	PRE_EMPHASIS_LEVEL_2,
+	PRE_EMPHASIS_LEVEL_3,
+};
+
+enum pattern_set {
+	PRBS7,
+	D10_2,
+	TRAINING_PTN1,
+	TRAINING_PTN2,
+	DP_NONE
+};
+
+enum color_space {
+	COLOR_RGB,
+	COLOR_YCBCR422,
+	COLOR_YCBCR444
+};
+
+enum color_depth {
+	COLOR_6,
+	COLOR_8,
+	COLOR_10,
+	COLOR_12
+};
+
+enum color_coefficient {
+	COLOR_YCBCR601,
+	COLOR_YCBCR709
+};
+
+enum dynamic_range {
+	VESA,
+	CEA
+};
+
+enum pll_status {
+	PLL_UNLOCKED,
+	PLL_LOCKED
+};
+
+enum clock_recovery_m_value_type {
+	CALCULATED_M,
+	REGISTER_M
+};
+
+enum video_timing_recognition_type {
+	VIDEO_TIMING_FROM_CAPTURE,
+	VIDEO_TIMING_FROM_REGISTER
+};
+
+enum analog_power_block {
+	AUX_BLOCK,
+	CH0_BLOCK,
+	CH1_BLOCK,
+	CH2_BLOCK,
+	CH3_BLOCK,
+	ANALOG_TOTAL,
+	POWER_ALL
+};
+
 enum dp_irq_type {
 	DP_IRQ_TYPE_HP_CABLE_IN,
 	DP_IRQ_TYPE_HP_CABLE_OUT,
@@ -20,6 +113,22 @@
 	DP_IRQ_TYPE_UNKNOWN,
 };
 
+struct video_info {
+	char *name;
+
+	bool h_sync_polarity;
+	bool v_sync_polarity;
+	bool interlaced;
+
+	enum color_space color_space;
+	enum dynamic_range dynamic_range;
+	enum color_coefficient ycbcr_coeff;
+	enum color_depth color_depth;
+
+	enum link_rate_type link_rate;
+	enum link_lane_count_type lane_count;
+};
+
 struct link_train {
 	int eq_loop;
 	int cr_loop[4];
@@ -42,6 +151,7 @@
 	struct video_info	*video_info;
 	struct link_train	link_train;
 	struct work_struct	hotplug_work;
+	struct phy		*phy;
 };
 
 /* exynos_dp_reg.c */
diff --git a/drivers/video/exynos/exynos_dp_reg.c b/drivers/video/exynos/exynos_dp_reg.c
index 29d9d03..b70da50 100644
--- a/drivers/video/exynos/exynos_dp_reg.c
+++ b/drivers/video/exynos/exynos_dp_reg.c
@@ -14,8 +14,6 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 
-#include <video/exynos_dp.h>
-
 #include "exynos_dp_core.h"
 #include "exynos_dp_reg.h"
 
diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c
index 32e5406..00b3a52 100644
--- a/drivers/video/exynos/exynos_mipi_dsi.c
+++ b/drivers/video/exynos/exynos_mipi_dsi.c
@@ -30,6 +30,7 @@
 #include <linux/interrupt.h>
 #include <linux/kthread.h>
 #include <linux/notifier.h>
+#include <linux/phy/phy.h>
 #include <linux/regulator/consumer.h>
 #include <linux/pm_runtime.h>
 #include <linux/err.h>
@@ -156,8 +157,7 @@
 		exynos_mipi_regulator_enable(dsim);
 
 		/* enable MIPI-DSI PHY. */
-		if (dsim->pd->phy_enable)
-			dsim->pd->phy_enable(pdev, true);
+		phy_power_on(dsim->phy);
 
 		clk_enable(dsim->clock);
 
@@ -373,6 +373,10 @@
 		return ret;
 	}
 
+	dsim->phy = devm_phy_get(&pdev->dev, "dsim");
+	if (IS_ERR(dsim->phy))
+		return PTR_ERR(dsim->phy);
+
 	dsim->clock = devm_clk_get(&pdev->dev, "dsim0");
 	if (IS_ERR(dsim->clock)) {
 		dev_err(&pdev->dev, "failed to get dsim clock source\n");
@@ -439,8 +443,7 @@
 	exynos_mipi_regulator_enable(dsim);
 
 	/* enable MIPI-DSI PHY. */
-	if (dsim->pd->phy_enable)
-		dsim->pd->phy_enable(pdev, true);
+	phy_power_on(dsim->phy);
 
 	exynos_mipi_update_cfg(dsim);
 
@@ -504,9 +507,8 @@
 	if (client_drv && client_drv->suspend)
 		client_drv->suspend(client_dev);
 
-	/* enable MIPI-DSI PHY. */
-	if (dsim->pd->phy_enable)
-		dsim->pd->phy_enable(pdev, false);
+	/* disable MIPI-DSI PHY. */
+	phy_power_off(dsim->phy);
 
 	clk_disable(dsim->clock);
 
@@ -536,8 +538,7 @@
 	exynos_mipi_regulator_enable(dsim);
 
 	/* enable MIPI-DSI PHY. */
-	if (dsim->pd->phy_enable)
-		dsim->pd->phy_enable(pdev, true);
+	phy_power_on(dsim->phy);
 
 	clk_enable(dsim->clock);
 
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 6dd7225..b047ec5 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -31,6 +31,8 @@
 #include <linux/uaccess.h>
 #include <linux/vmalloc.h>
 #include <linux/spinlock.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <sysdev/fsl_soc.h>
 #include <linux/fsl-diu-fb.h>
diff --git a/drivers/video/sis/init.c b/drivers/video/sis/init.c
index f082ae5..4f26bc2 100644
--- a/drivers/video/sis/init.c
+++ b/drivers/video/sis/init.c
@@ -3320,9 +3320,8 @@
 }
 
 #ifndef GETBITSTR
-#define BITMASK(h,l)    	(((unsigned)(1U << ((h)-(l)+1))-1)<<(l))
-#define GENMASK(mask)   	BITMASK(1?mask,0?mask)
-#define GETBITS(var,mask)   	(((var) & GENMASK(mask)) >> (0?mask))
+#define GENBITSMASK(mask)   	GENMASK(1?mask,0?mask)
+#define GETBITS(var,mask)   	(((var) & GENBITSMASK(mask)) >> (0?mask))
 #define GETBITSTR(val,from,to)  ((GETBITS(val,from)) << (0?to))
 #endif
 
diff --git a/drivers/video/sticore.h b/drivers/video/sticore.h
index addf7b6..af16195 100644
--- a/drivers/video/sticore.h
+++ b/drivers/video/sticore.h
@@ -18,6 +18,9 @@
 #define STI_FONT_HPROMAN8 1
 #define STI_FONT_KANA8 2
 
+#define ALT_CODE_TYPE_UNKNOWN 0x00	/* alt code type values */
+#define ALT_CODE_TYPE_PA_RISC_64 0x01
+
 /* The latency of the STI functions cannot really be reduced by setting
  * this to 0;  STI doesn't seem to be designed to allow calling a different
  * function (or the same function with different arguments) after a
@@ -40,14 +43,6 @@
 
 #define STI_PTR(p)	( virt_to_phys(p) )
 #define PTR_STI(p)	( phys_to_virt((unsigned long)p) )
-#define STI_CALL(func, flags, inptr, outptr, glob_cfg)	\
-       ({						\
-               pdc_sti_call( func, STI_PTR(flags),	\
-				   STI_PTR(inptr),	\
-				   STI_PTR(outptr),	\
-				   STI_PTR(glob_cfg));	\
-       })
-
 
 #define sti_onscreen_x(sti) (sti->glob_cfg->onscreen_x)
 #define sti_onscreen_y(sti) (sti->glob_cfg->onscreen_y)
@@ -56,6 +51,12 @@
 #define sti_font_x(sti) (PTR_STI(sti->font)->width)
 #define sti_font_y(sti) (PTR_STI(sti->font)->height)
 
+#ifdef CONFIG_64BIT
+#define STI_LOWMEM	(GFP_KERNEL | GFP_DMA)
+#else
+#define STI_LOWMEM	(GFP_KERNEL)
+#endif
+
 
 /* STI function configuration structs */
 
@@ -306,6 +307,34 @@
 };
 
 
+/* sti_all_data is an internal struct which needs to be allocated in
+ * low memory (< 4GB) if STI is used with 32bit STI on a 64bit kernel */
+
+struct sti_all_data {
+	struct sti_glob_cfg glob_cfg;
+	struct sti_glob_cfg_ext glob_cfg_ext;
+
+	struct sti_conf_inptr		inq_inptr;
+	struct sti_conf_outptr		inq_outptr; /* configuration */
+	struct sti_conf_outptr_ext	inq_outptr_ext;
+
+	struct sti_init_inptr_ext	init_inptr_ext;
+	struct sti_init_inptr		init_inptr;
+	struct sti_init_outptr		init_outptr;
+
+	struct sti_blkmv_inptr		blkmv_inptr;
+	struct sti_blkmv_outptr		blkmv_outptr;
+
+	struct sti_font_inptr		font_inptr;
+	struct sti_font_outptr		font_outptr;
+
+	/* leave as last entries */
+	unsigned long save_addr[1024 / sizeof(unsigned long)];
+	   /* min 256 bytes which is STI default, max sti->sti_mem_request */
+	unsigned long sti_mem_addr[256 / sizeof(unsigned long)];
+	/* do not add something below here ! */
+};
+
 /* internal generic STI struct */
 
 struct sti_struct {
@@ -330,11 +359,9 @@
 	region_t regions[STI_REGION_MAX];
 	unsigned long regions_phys[STI_REGION_MAX];
 
-	struct sti_glob_cfg *glob_cfg;
-	struct sti_cooked_font *font;	/* ptr to selected font (cooked) */
+	struct sti_glob_cfg *glob_cfg;	/* points into sti_all_data */
 
-	struct sti_conf_outptr outptr; /* configuration */
-	struct sti_conf_outptr_ext outptr_ext;
+	struct sti_cooked_font *font;	/* ptr to selected font (cooked) */
 
 	struct pci_dev *pd;
 
@@ -343,6 +370,9 @@
 
 	/* pointer to the fb_info where this STI device is used */
 	struct fb_info *info;
+
+	/* pointer to all internal data */
+	struct sti_all_data *sti_data;
 };
 
 
@@ -350,6 +380,14 @@
 
 struct sti_struct *sti_get_rom(unsigned int index); /* 0: default sti */
 
+
+/* sticore main function to call STI firmware */
+
+int sti_call(const struct sti_struct *sti, unsigned long func,
+		const void *flags, void *inptr, void *outptr,
+		struct sti_glob_cfg *glob_cfg);
+
+
 /* functions to call the STI ROM directly */
 
 void sti_putc(struct sti_struct *sti, int c, int y, int x);
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c
index 876648e..019a1fe 100644
--- a/drivers/video/stifb.c
+++ b/drivers/video/stifb.c
@@ -1101,6 +1101,7 @@
 	var = &info->var;
 
 	fb->sti = sti;
+	dev_name = sti->sti_data->inq_outptr.dev_name;
 	/* store upper 32bits of the graphics id */
 	fb->id = fb->sti->graphics_id[0];
 
@@ -1114,11 +1115,11 @@
 		  Since this driver only supports standard mode, we check
 		  if the device name contains the string "DX" and tell the
 		  user how to reconfigure the card. */
-		if (strstr(sti->outptr.dev_name, "DX")) {
+		if (strstr(dev_name, "DX")) {
 		   printk(KERN_WARNING
 "WARNING: stifb framebuffer driver does not support '%s' in double-buffer mode.\n"
 "WARNING: Please disable the double-buffer mode in IPL menu (the PARISC-BIOS).\n",
-			sti->outptr.dev_name);
+			dev_name);
 		   goto out_err0;
 		}
 		/* fall though */
@@ -1130,7 +1131,7 @@
 		break;
 	default:
 		printk(KERN_WARNING "stifb: '%s' (id: 0x%08x) not supported.\n",
-			sti->outptr.dev_name, fb->id);
+			dev_name, fb->id);
 		goto out_err0;
 	}
 	
@@ -1154,7 +1155,6 @@
 		fb->id = S9000_ID_A1659A;
 		break;
 	case S9000_ID_TIMBER:	/* HP9000/710 Any (may be a grayscale device) */
-		dev_name = fb->sti->outptr.dev_name;
 		if (strstr(dev_name, "GRAYSCALE") || 
 		    strstr(dev_name, "Grayscale") ||
 		    strstr(dev_name, "grayscale"))
@@ -1290,7 +1290,7 @@
 		var->xres, 
 		var->yres,
 		var->bits_per_pixel,
-		sti->outptr.dev_name,
+		dev_name,
 		fb->id, 
 		fix->mmio_start);
 
diff --git a/drivers/virt/fsl_hypervisor.c b/drivers/virt/fsl_hypervisor.c
index d294f67..32c8fc5 100644
--- a/drivers/virt/fsl_hypervisor.c
+++ b/drivers/virt/fsl_hypervisor.c
@@ -34,6 +34,7 @@
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/of.h>
+#include <linux/of_irq.h>
 #include <linux/reboot.h>
 #include <linux/uaccess.h>
 #include <linux/notifier.h>
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index ee59b74..fed0ce1 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -13,18 +13,24 @@
 	struct virtio_device *dev = dev_to_virtio(_d);
 	return sprintf(buf, "0x%04x\n", dev->id.device);
 }
+static DEVICE_ATTR_RO(device);
+
 static ssize_t vendor_show(struct device *_d,
 			   struct device_attribute *attr, char *buf)
 {
 	struct virtio_device *dev = dev_to_virtio(_d);
 	return sprintf(buf, "0x%04x\n", dev->id.vendor);
 }
+static DEVICE_ATTR_RO(vendor);
+
 static ssize_t status_show(struct device *_d,
 			   struct device_attribute *attr, char *buf)
 {
 	struct virtio_device *dev = dev_to_virtio(_d);
 	return sprintf(buf, "0x%08x\n", dev->config->get_status(dev));
 }
+static DEVICE_ATTR_RO(status);
+
 static ssize_t modalias_show(struct device *_d,
 			     struct device_attribute *attr, char *buf)
 {
@@ -32,6 +38,8 @@
 	return sprintf(buf, "virtio:d%08Xv%08X\n",
 		       dev->id.device, dev->id.vendor);
 }
+static DEVICE_ATTR_RO(modalias);
+
 static ssize_t features_show(struct device *_d,
 			     struct device_attribute *attr, char *buf)
 {
@@ -47,14 +55,17 @@
 	len += sprintf(buf+len, "\n");
 	return len;
 }
-static struct device_attribute virtio_dev_attrs[] = {
-	__ATTR_RO(device),
-	__ATTR_RO(vendor),
-	__ATTR_RO(status),
-	__ATTR_RO(modalias),
-	__ATTR_RO(features),
-	__ATTR_NULL
+static DEVICE_ATTR_RO(features);
+
+static struct attribute *virtio_dev_attrs[] = {
+	&dev_attr_device.attr,
+	&dev_attr_vendor.attr,
+	&dev_attr_status.attr,
+	&dev_attr_modalias.attr,
+	&dev_attr_features.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(virtio_dev);
 
 static inline int virtio_id_match(const struct virtio_device *dev,
 				  const struct virtio_device_id *id)
@@ -165,7 +176,7 @@
 static struct bus_type virtio_bus = {
 	.name  = "virtio",
 	.match = virtio_dev_match,
-	.dev_attrs = virtio_dev_attrs,
+	.dev_groups = virtio_dev_groups,
 	.uevent = virtio_uevent,
 	.probe = virtio_dev_probe,
 	.remove = virtio_dev_remove,
diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c
index 96cab6a..41613f9 100644
--- a/drivers/w1/masters/ds1wm.c
+++ b/drivers/w1/masters/ds1wm.c
@@ -498,7 +498,7 @@
 		irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_FALLING);
 
 	ret = devm_request_irq(&pdev->dev, ds1wm_data->irq, ds1wm_isr,
-			IRQF_DISABLED | IRQF_SHARED, "ds1wm", ds1wm_data);
+			IRQF_SHARED, "ds1wm", ds1wm_data);
 	if (ret)
 		return ret;
 
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
index 6e94d8dd..9900e8e 100644
--- a/drivers/w1/masters/omap_hdq.c
+++ b/drivers/w1/masters/omap_hdq.c
@@ -577,8 +577,7 @@
 		goto err_irq;
 	}
 
-	ret = devm_request_irq(dev, irq, hdq_isr, IRQF_DISABLED,
-			"omap_hdq", hdq_data);
+	ret = devm_request_irq(dev, irq, hdq_isr, 0, "omap_hdq", hdq_data);
 	if (ret < 0) {
 		dev_dbg(&pdev->dev, "could not request irq\n");
 		goto err_irq;
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
index f54ece2..264ad1c 100644
--- a/drivers/w1/masters/w1-gpio.c
+++ b/drivers/w1/masters/w1-gpio.c
@@ -58,6 +58,7 @@
 {
 	struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
 	struct device_node *np = pdev->dev.of_node;
+	int gpio;
 
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
@@ -66,7 +67,11 @@
 	if (of_get_property(np, "linux,open-drain", NULL))
 		pdata->is_open_drain = 1;
 
-	pdata->pin = of_get_gpio(np, 0);
+	gpio = of_get_gpio(np, 0);
+	if (gpio < 0)
+		return gpio;
+	pdata->pin = gpio;
+
 	pdata->ext_pullup_enable_pin = of_get_gpio(np, 1);
 	pdev->dev.platform_data = pdata;
 
@@ -94,25 +99,27 @@
 		return -ENXIO;
 	}
 
-	master = kzalloc(sizeof(struct w1_bus_master), GFP_KERNEL);
+	master = devm_kzalloc(&pdev->dev, sizeof(struct w1_bus_master),
+			GFP_KERNEL);
 	if (!master) {
 		dev_err(&pdev->dev, "Out of memory\n");
 		return -ENOMEM;
 	}
 
-	err = gpio_request(pdata->pin, "w1");
+	err = devm_gpio_request(&pdev->dev, pdata->pin, "w1");
 	if (err) {
 		dev_err(&pdev->dev, "gpio_request (pin) failed\n");
-		goto free_master;
+		return err;
 	}
 
 	if (gpio_is_valid(pdata->ext_pullup_enable_pin)) {
-		err = gpio_request_one(pdata->ext_pullup_enable_pin,
-				       GPIOF_INIT_LOW, "w1 pullup");
+		err = devm_gpio_request_one(&pdev->dev,
+				pdata->ext_pullup_enable_pin, GPIOF_INIT_LOW,
+				"w1 pullup");
 		if (err < 0) {
 			dev_err(&pdev->dev, "gpio_request_one "
 					"(ext_pullup_enable_pin) failed\n");
-			goto free_gpio;
+			return err;
 		}
 	}
 
@@ -130,7 +137,7 @@
 	err = w1_add_master_device(master);
 	if (err) {
 		dev_err(&pdev->dev, "w1_add_master device failed\n");
-		goto free_gpio_ext_pu;
+		return err;
 	}
 
 	if (pdata->enable_external_pullup)
@@ -142,16 +149,6 @@
 	platform_set_drvdata(pdev, master);
 
 	return 0;
-
- free_gpio_ext_pu:
-	if (gpio_is_valid(pdata->ext_pullup_enable_pin))
-		gpio_free(pdata->ext_pullup_enable_pin);
- free_gpio:
-	gpio_free(pdata->pin);
- free_master:
-	kfree(master);
-
-	return err;
 }
 
 static int w1_gpio_remove(struct platform_device *pdev)
@@ -166,8 +163,6 @@
 		gpio_set_value(pdata->ext_pullup_enable_pin, 0);
 
 	w1_remove_master_device(master);
-	gpio_free(pdata->pin);
-	kfree(master);
 
 	return 0;
 }
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index c7c64f1..fa932c2 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -613,6 +613,9 @@
 	sl = dev_to_w1_slave(dev);
 	fops = sl->family->fops;
 
+	if (!fops)
+		return 0;
+
 	switch (action) {
 	case BUS_NOTIFY_ADD_DEVICE:
 		/* if the family driver needs to initialize something... */
@@ -713,7 +716,10 @@
 	atomic_set(&sl->refcnt, 0);
 	init_completion(&sl->released);
 
+	/* slave modules need to be loaded in a context with unlocked mutex */
+	mutex_unlock(&dev->mutex);
 	request_module("w1-family-0x%0x", rn->family);
+	mutex_lock(&dev->mutex);
 
 	spin_lock(&w1_flock);
 	f = w1_family_registered(rn->family);
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index d1d53f3..6df632e 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -418,8 +418,6 @@
 
 # FRV Architecture
 
-# H8300 Architecture
-
 # X86 (i386 + ia64 + x86_64) Architecture
 
 config ACQUIRE_WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 6c5bb27..8c7b8bc 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -66,8 +66,6 @@
 
 # FRV Architecture
 
-# H8300 Architecture
-
 # X86 (i386 + ia64 + x86_64) Architecture
 obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
 obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c
index 257cfba..3755833 100644
--- a/drivers/watchdog/gef_wdt.c
+++ b/drivers/watchdog/gef_wdt.c
@@ -34,6 +34,7 @@
 #include <linux/watchdog.h>
 #include <linux/fs.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index 5be5e3d..19f3c3f 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -802,6 +802,12 @@
 		return -ENODEV;
 	}
 
+	/*
+	 * Ignore all auxilary iLO devices with the following PCI ID
+	 */
+	if (dev->subsystem_device == 0x1979)
+		return -ENODEV;
+
 	if (pci_enable_device(dev)) {
 		dev_warn(&dev->dev,
 			"Not possible to enable PCI Device: 0x%x:0x%x.\n",
diff --git a/drivers/watchdog/intel_scu_watchdog.c b/drivers/watchdog/intel_scu_watchdog.c
index 9dda2d0..8ced256 100644
--- a/drivers/watchdog/intel_scu_watchdog.c
+++ b/drivers/watchdog/intel_scu_watchdog.c
@@ -48,7 +48,7 @@
 #include <linux/atomic.h>
 #include <asm/intel_scu_ipc.h>
 #include <asm/apb_timer.h>
-#include <asm/mrst.h>
+#include <asm/intel-mid.h>
 
 #include "intel_scu_watchdog.h"
 
@@ -445,7 +445,7 @@
 	 *
 	 * If it isn't an intel MID device then it doesn't have this watchdog
 	 */
-	if (!mrst_identify_cpu())
+	if (!intel_mid_identify_cpu())
 		return -ENODEV;
 
 	/* Check boot parameters to verify that their initial values */
diff --git a/drivers/watchdog/kempld_wdt.c b/drivers/watchdog/kempld_wdt.c
index 491419e..5c3d4df 100644
--- a/drivers/watchdog/kempld_wdt.c
+++ b/drivers/watchdog/kempld_wdt.c
@@ -35,7 +35,7 @@
 #define KEMPLD_WDT_STAGE_TIMEOUT(x)	(0x1b + (x) * 4)
 #define KEMPLD_WDT_STAGE_CFG(x)		(0x18 + (x))
 #define STAGE_CFG_GET_PRESCALER(x)	(((x) & 0x30) >> 4)
-#define STAGE_CFG_SET_PRESCALER(x)	(((x) & 0x30) << 4)
+#define STAGE_CFG_SET_PRESCALER(x)	(((x) & 0x3) << 4)
 #define STAGE_CFG_PRESCALER_MASK	0x30
 #define STAGE_CFG_ACTION_MASK		0x7
 #define STAGE_CFG_ASSERT		(1 << 3)
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
index da27520..d0ebeba 100644
--- a/drivers/watchdog/mpc8xxx_wdt.c
+++ b/drivers/watchdog/mpc8xxx_wdt.c
@@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/timer.h>
 #include <linux/miscdevice.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/module.h>
 #include <linux/watchdog.h>
diff --git a/drivers/watchdog/pika_wdt.c b/drivers/watchdog/pika_wdt.c
index 7d3d471..329bc60 100644
--- a/drivers/watchdog/pika_wdt.c
+++ b/drivers/watchdog/pika_wdt.c
@@ -22,6 +22,7 @@
 #include <linux/bitops.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 
 #define DRV_NAME "PIKA-WDT"
diff --git a/drivers/watchdog/sunxi_wdt.c b/drivers/watchdog/sunxi_wdt.c
index 1f94b42..f6caa77 100644
--- a/drivers/watchdog/sunxi_wdt.c
+++ b/drivers/watchdog/sunxi_wdt.c
@@ -146,7 +146,7 @@
 	.set_timeout	= sunxi_wdt_set_timeout,
 };
 
-static int __init sunxi_wdt_probe(struct platform_device *pdev)
+static int sunxi_wdt_probe(struct platform_device *pdev)
 {
 	struct sunxi_wdt_dev *sunxi_wdt;
 	struct resource *res;
@@ -187,7 +187,7 @@
 	return 0;
 }
 
-static int __exit sunxi_wdt_remove(struct platform_device *pdev)
+static int sunxi_wdt_remove(struct platform_device *pdev)
 {
 	struct sunxi_wdt_dev *sunxi_wdt = platform_get_drvdata(pdev);
 
diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c
index 42913f1..c9b0c62 100644
--- a/drivers/watchdog/ts72xx_wdt.c
+++ b/drivers/watchdog/ts72xx_wdt.c
@@ -310,7 +310,8 @@
 
 	case WDIOC_GETSTATUS:
 	case WDIOC_GETBOOTSTATUS:
-		return put_user(0, p);
+		error = put_user(0, p);
+		break;
 
 	case WDIOC_KEEPALIVE:
 		ts72xx_wdt_kick(wdt);
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
index 38e92b7..3c0a74b 100644
--- a/drivers/xen/xenbus/xenbus_probe.c
+++ b/drivers/xen/xenbus/xenbus_probe.c
@@ -384,12 +384,14 @@
 {
 	return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename);
 }
+static DEVICE_ATTR_RO(nodename);
 
 static ssize_t devtype_show(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype);
 }
+static DEVICE_ATTR_RO(devtype);
 
 static ssize_t modalias_show(struct device *dev,
 			     struct device_attribute *attr, char *buf)
@@ -397,14 +399,24 @@
 	return sprintf(buf, "%s:%s\n", dev->bus->name,
 		       to_xenbus_device(dev)->devicetype);
 }
+static DEVICE_ATTR_RO(modalias);
 
-struct device_attribute xenbus_dev_attrs[] = {
-	__ATTR_RO(nodename),
-	__ATTR_RO(devtype),
-	__ATTR_RO(modalias),
-	__ATTR_NULL
+static struct attribute *xenbus_dev_attrs[] = {
+	&dev_attr_nodename.attr,
+	&dev_attr_devtype.attr,
+	&dev_attr_modalias.attr,
+	NULL,
 };
-EXPORT_SYMBOL_GPL(xenbus_dev_attrs);
+
+static const struct attribute_group xenbus_dev_group = {
+	.attrs = xenbus_dev_attrs,
+};
+
+const struct attribute_group *xenbus_dev_groups[] = {
+	&xenbus_dev_group,
+	NULL,
+};
+EXPORT_SYMBOL_GPL(xenbus_dev_groups);
 
 int xenbus_probe_node(struct xen_bus_type *bus,
 		      const char *type,
diff --git a/drivers/xen/xenbus/xenbus_probe.h b/drivers/xen/xenbus/xenbus_probe.h
index 146f857..1085ec2 100644
--- a/drivers/xen/xenbus/xenbus_probe.h
+++ b/drivers/xen/xenbus/xenbus_probe.h
@@ -54,7 +54,7 @@
 	XS_LOCAL,
 };
 
-extern struct device_attribute xenbus_dev_attrs[];
+extern const struct attribute_group *xenbus_dev_groups[];
 
 extern int xenbus_match(struct device *_dev, struct device_driver *_drv);
 extern int xenbus_dev_probe(struct device *_dev);
diff --git a/drivers/xen/xenbus/xenbus_probe_backend.c b/drivers/xen/xenbus/xenbus_probe_backend.c
index 998bbba..5125dce 100644
--- a/drivers/xen/xenbus/xenbus_probe_backend.c
+++ b/drivers/xen/xenbus/xenbus_probe_backend.c
@@ -200,7 +200,7 @@
 		.probe		= xenbus_dev_probe,
 		.remove		= xenbus_dev_remove,
 		.shutdown	= xenbus_dev_shutdown,
-		.dev_attrs	= xenbus_dev_attrs,
+		.dev_groups	= xenbus_dev_groups,
 	},
 };
 
diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c
index 34b20bf..129bf84 100644
--- a/drivers/xen/xenbus/xenbus_probe_frontend.c
+++ b/drivers/xen/xenbus/xenbus_probe_frontend.c
@@ -154,7 +154,7 @@
 		.probe		= xenbus_frontend_dev_probe,
 		.remove		= xenbus_dev_remove,
 		.shutdown	= xenbus_dev_shutdown,
-		.dev_attrs	= xenbus_dev_attrs,
+		.dev_groups	= xenbus_dev_groups,
 
 		.pm		= &xenbus_pm_ops,
 	},
diff --git a/fs/9p/cache.c b/fs/9p/cache.c
index a9ea73d..2b7a032 100644
--- a/fs/9p/cache.c
+++ b/fs/9p/cache.c
@@ -90,7 +90,7 @@
 
 	v9ses->fscache = fscache_acquire_cookie(v9fs_cache_netfs.primary_index,
 						&v9fs_cache_session_index_def,
-						v9ses);
+						v9ses, true);
 	p9_debug(P9_DEBUG_FSC, "session %p get cookie %p\n",
 		 v9ses, v9ses->fscache);
 }
@@ -204,7 +204,7 @@
 	v9ses = v9fs_inode2v9ses(inode);
 	v9inode->fscache = fscache_acquire_cookie(v9ses->fscache,
 						  &v9fs_cache_inode_index_def,
-						  v9inode);
+						  v9inode, true);
 
 	p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p\n",
 		 inode, v9inode->fscache);
@@ -271,7 +271,7 @@
 	v9ses = v9fs_inode2v9ses(inode);
 	v9inode->fscache = fscache_acquire_cookie(v9ses->fscache,
 						  &v9fs_cache_inode_index_def,
-						  v9inode);
+						  v9inode, true);
 	p9_debug(P9_DEBUG_FSC, "inode %p revalidating cookie old %p new %p\n",
 		 inode, old, v9inode->fscache);
 
diff --git a/fs/afs/cell.c b/fs/afs/cell.c
index 3c090b7..ca0a3cf 100644
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -179,7 +179,7 @@
 	/* put it up for caching (this never returns an error) */
 	cell->cache = fscache_acquire_cookie(afs_cache_netfs.primary_index,
 					     &afs_cell_cache_index_def,
-					     cell);
+					     cell, true);
 #endif
 
 	/* add to the cell lists */
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 789bc25..ce25d75 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -259,7 +259,7 @@
 #ifdef CONFIG_AFS_FSCACHE
 	vnode->cache = fscache_acquire_cookie(vnode->volume->cache,
 					      &afs_vnode_cache_index_def,
-					      vnode);
+					      vnode, true);
 #endif
 
 	ret = afs_inode_map_status(vnode, key);
diff --git a/fs/afs/vlocation.c b/fs/afs/vlocation.c
index 57bcb15..b6df2e8 100644
--- a/fs/afs/vlocation.c
+++ b/fs/afs/vlocation.c
@@ -308,7 +308,8 @@
 	/* see if we have an in-cache copy (will set vl->valid if there is) */
 #ifdef CONFIG_AFS_FSCACHE
 	vl->cache = fscache_acquire_cookie(vl->cell->cache,
-					   &afs_vlocation_cache_index_def, vl);
+					   &afs_vlocation_cache_index_def, vl,
+					   true);
 #endif
 
 	if (vl->valid) {
diff --git a/fs/afs/volume.c b/fs/afs/volume.c
index 401eeb2..2b60725 100644
--- a/fs/afs/volume.c
+++ b/fs/afs/volume.c
@@ -131,7 +131,7 @@
 #ifdef CONFIG_AFS_FSCACHE
 	volume->cache = fscache_acquire_cookie(vlocation->cache,
 					       &afs_volume_cache_index_def,
-					       volume);
+					       volume, true);
 #endif
 	afs_get_vlocation(vlocation);
 	volume->vlocation = vlocation;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 4ae17ed..62176ad 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1561,8 +1561,9 @@
 	return ret;
 }
 
-struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
-					      struct btrfs_key *location)
+struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info,
+				     struct btrfs_key *location,
+				     bool check_ref)
 {
 	struct btrfs_root *root;
 	int ret;
@@ -1586,7 +1587,7 @@
 again:
 	root = btrfs_lookup_fs_root(fs_info, location->objectid);
 	if (root) {
-		if (btrfs_root_refs(&root->root_item) == 0)
+		if (check_ref && btrfs_root_refs(&root->root_item) == 0)
 			return ERR_PTR(-ENOENT);
 		return root;
 	}
@@ -1595,7 +1596,7 @@
 	if (IS_ERR(root))
 		return root;
 
-	if (btrfs_root_refs(&root->root_item) == 0) {
+	if (check_ref && btrfs_root_refs(&root->root_item) == 0) {
 		ret = -ENOENT;
 		goto fail;
 	}
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index b71acd6e..5ce2a7d 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -68,8 +68,17 @@
 int btrfs_init_fs_root(struct btrfs_root *root);
 int btrfs_insert_fs_root(struct btrfs_fs_info *fs_info,
 			 struct btrfs_root *root);
-struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
-					      struct btrfs_key *location);
+
+struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info,
+				     struct btrfs_key *key,
+				     bool check_ref);
+static inline struct btrfs_root *
+btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
+			   struct btrfs_key *location)
+{
+	return btrfs_get_fs_root(fs_info, location, true);
+}
+
 int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info);
 void btrfs_btree_balance_dirty(struct btrfs_root *root);
 void btrfs_btree_balance_dirty_nodelay(struct btrfs_root *root);
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 22bda32..51731b7 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -1490,10 +1490,8 @@
 		cur_start = state->end + 1;
 		node = rb_next(node);
 		total_bytes += state->end - state->start + 1;
-		if (total_bytes >= max_bytes) {
-			*end = *start + max_bytes - 1;
+		if (total_bytes >= max_bytes)
 			break;
-		}
 		if (!node)
 			break;
 	}
@@ -1635,10 +1633,9 @@
 
 	/*
 	 * make sure to limit the number of pages we try to lock down
-	 * if we're looping.
 	 */
-	if (delalloc_end + 1 - delalloc_start > max_bytes && loops)
-		delalloc_end = delalloc_start + PAGE_CACHE_SIZE - 1;
+	if (delalloc_end + 1 - delalloc_start > max_bytes)
+		delalloc_end = delalloc_start + max_bytes - 1;
 
 	/* step two, lock all the pages after the page that has start */
 	ret = lock_delalloc_pages(inode, locked_page,
@@ -1649,8 +1646,7 @@
 		 */
 		free_extent_state(cached_state);
 		if (!loops) {
-			unsigned long offset = (*start) & (PAGE_CACHE_SIZE - 1);
-			max_bytes = PAGE_CACHE_SIZE - offset;
+			max_bytes = PAGE_CACHE_SIZE;
 			loops = 1;
 			goto again;
 		} else {
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 22ebc13..51e3afa 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -6437,6 +6437,7 @@
 
 	if (btrfs_extent_readonly(root, disk_bytenr))
 		goto out;
+	btrfs_release_path(path);
 
 	/*
 	 * look for other files referencing this extent, if we
@@ -7986,7 +7987,7 @@
 
 
 	/* check for collisions, even if the  name isn't there */
-	ret = btrfs_check_dir_item_collision(root, new_dir->i_ino,
+	ret = btrfs_check_dir_item_collision(dest, new_dir->i_ino,
 			     new_dentry->d_name.name,
 			     new_dentry->d_name.len);
 
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index a5a2632..4a35572 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -588,7 +588,7 @@
 	else
 		key.offset = (u64)-1;
 
-	return btrfs_read_fs_root_no_name(fs_info, &key);
+	return btrfs_get_fs_root(fs_info, &key, false);
 }
 
 #ifdef BTRFS_COMPAT_EXTENT_TREE_V0
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c
index 0b1f4ef..ec71ea4 100644
--- a/fs/btrfs/root-tree.c
+++ b/fs/btrfs/root-tree.c
@@ -299,11 +299,6 @@
 			continue;
 		}
 
-		if (btrfs_root_refs(&root->root_item) == 0) {
-			btrfs_add_dead_root(root);
-			continue;
-		}
-
 		err = btrfs_init_fs_root(root);
 		if (err) {
 			btrfs_free_fs_root(root);
@@ -318,6 +313,9 @@
 			btrfs_free_fs_root(root);
 			break;
 		}
+
+		if (btrfs_root_refs(&root->root_item) == 0)
+			btrfs_add_dead_root(root);
 	}
 
 	btrfs_free_path(path);
diff --git a/fs/buffer.c b/fs/buffer.c
index 4d74335..6024877 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1005,9 +1005,19 @@
 	struct buffer_head *bh;
 	sector_t end_block;
 	int ret = 0;		/* Will call free_more_memory() */
+	gfp_t gfp_mask;
 
-	page = find_or_create_page(inode->i_mapping, index,
-		(mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)|__GFP_MOVABLE);
+	gfp_mask = mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS;
+	gfp_mask |= __GFP_MOVABLE;
+	/*
+	 * XXX: __getblk_slow() can not really deal with failure and
+	 * will endlessly loop on improvised global reclaim.  Prefer
+	 * looping in the allocator rather than here, at least that
+	 * code knows what it's doing.
+	 */
+	gfp_mask |= __GFP_NOFAIL;
+
+	page = find_or_create_page(inode->i_mapping, index, gfp_mask);
 	if (!page)
 		return ret;
 
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c
index 5088a41..57e17fe 100644
--- a/fs/cachefiles/interface.c
+++ b/fs/cachefiles/interface.c
@@ -270,7 +270,7 @@
 #endif
 
 	/* delete retired objects */
-	if (test_bit(FSCACHE_COOKIE_RETIRED, &object->fscache.cookie->flags) &&
+	if (test_bit(FSCACHE_OBJECT_RETIRED, &object->fscache.flags) &&
 	    _object != cache->cache.fsdef
 	    ) {
 		_debug("- retire object OBJ%x", object->fscache.debug_id);
diff --git a/fs/ceph/cache.c b/fs/ceph/cache.c
index 6bfe65e..7db2e6c 100644
--- a/fs/ceph/cache.c
+++ b/fs/ceph/cache.c
@@ -68,7 +68,7 @@
 {
 	fsc->fscache = fscache_acquire_cookie(ceph_cache_netfs.primary_index,
 					      &ceph_fscache_fsid_object_def,
-					      fsc);
+					      fsc, true);
 
 	if (fsc->fscache == NULL) {
 		pr_err("Unable to resgister fsid: %p fscache cookie", fsc);
@@ -204,7 +204,7 @@
 
 	ci->fscache = fscache_acquire_cookie(fsc->fscache,
 					     &ceph_fscache_inode_object_def,
-					     ci);
+					     ci, true);
 done:
 	mutex_unlock(&inode->i_mutex);
 
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 801975c..849f613 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -120,14 +120,16 @@
 {
 	struct inode *inode;
 	struct cifs_sb_info *cifs_sb;
+	struct cifs_tcon *tcon;
 	int rc = 0;
 
 	cifs_sb = CIFS_SB(sb);
+	tcon = cifs_sb_master_tcon(cifs_sb);
 
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL)
 		sb->s_flags |= MS_POSIXACL;
 
-	if (cifs_sb_master_tcon(cifs_sb)->ses->capabilities & CAP_LARGE_FILES)
+	if (tcon->ses->capabilities & tcon->ses->server->vals->cap_large_files)
 		sb->s_maxbytes = MAX_LFS_FILESIZE;
 	else
 		sb->s_maxbytes = MAX_NON_LFS;
@@ -147,7 +149,7 @@
 		goto out_no_root;
 	}
 
-	if (cifs_sb_master_tcon(cifs_sb)->nocase)
+	if (tcon->nocase)
 		sb->s_d_op = &cifs_ci_dentry_ops;
 	else
 		sb->s_d_op = &cifs_dentry_ops;
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 52b6f6c..26b1c1d 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -278,6 +278,8 @@
 	/* set attributes */
 	int (*set_file_info)(struct inode *, const char *, FILE_BASIC_INFO *,
 			     const unsigned int);
+	int (*set_compression)(const unsigned int, struct cifs_tcon *,
+			       struct cifsFileInfo *);
 	/* check if we can send an echo or nor */
 	bool (*can_echo)(struct TCP_Server_Info *);
 	/* send echo request */
@@ -620,11 +622,34 @@
 }
 
 static inline __u64
-get_next_mid(struct TCP_Server_Info *server)
+get_next_mid64(struct TCP_Server_Info *server)
 {
 	return server->ops->get_next_mid(server);
 }
 
+static inline __le16
+get_next_mid(struct TCP_Server_Info *server)
+{
+	__u16 mid = get_next_mid64(server);
+	/*
+	 * The value in the SMB header should be little endian for easy
+	 * on-the-wire decoding.
+	 */
+	return cpu_to_le16(mid);
+}
+
+static inline __u16
+get_mid(const struct smb_hdr *smb)
+{
+	return le16_to_cpu(smb->Mid);
+}
+
+static inline bool
+compare_mid(__u16 mid, const struct smb_hdr *smb)
+{
+	return mid == le16_to_cpu(smb->Mid);
+}
+
 /*
  * When the server supports very large reads and writes via POSIX extensions,
  * we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not
@@ -828,6 +853,8 @@
 	__u32 maximal_access;
 	__u32 vol_serial_number;
 	__le64 vol_create_time;
+	__u32 ss_flags;		/* sector size flags */
+	__u32 perf_sector_size; /* best sector size for perf */
 #endif /* CONFIG_CIFS_SMB2 */
 #ifdef CONFIG_CIFS_FSCACHE
 	u64 resource_id;		/* server resource id */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index a630475..9e5ee34 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -428,7 +428,7 @@
 	__u16 Tid;
 	__le16 Pid;
 	__u16 Uid;
-	__u16 Mid;
+	__le16 Mid;
 	__u8 WordCount;
 } __attribute__((packed));
 
@@ -1352,6 +1352,35 @@
 	__u8 Data[1];
 } __attribute__((packed)) TRANSACT_IOCTL_REQ;
 
+typedef struct smb_com_transaction_compr_ioctl_req {
+	struct smb_hdr hdr;	/* wct = 23 */
+	__u8 MaxSetupCount;
+	__u16 Reserved;
+	__le32 TotalParameterCount;
+	__le32 TotalDataCount;
+	__le32 MaxParameterCount;
+	__le32 MaxDataCount;
+	__le32 ParameterCount;
+	__le32 ParameterOffset;
+	__le32 DataCount;
+	__le32 DataOffset;
+	__u8 SetupCount; /* four setup words follow subcommand */
+	/* SNIA spec incorrectly included spurious pad here */
+	__le16 SubCommand; /* 2 = IOCTL/FSCTL */
+	__le32 FunctionCode;
+	__u16 Fid;
+	__u8 IsFsctl;  /* 1 = File System Control 0 = device control (IOCTL) */
+	__u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS) */
+	__le16 ByteCount;
+	__u8 Pad[3];
+	__le16 compression_state;  /* See below for valid flags */
+} __attribute__((packed)) TRANSACT_COMPR_IOCTL_REQ;
+
+/* compression state flags */
+#define COMPRESSION_FORMAT_NONE		0x0000
+#define COMPRESSION_FORMAT_DEFAULT	0x0001
+#define COMPRESSION_FORMAT_LZNT1	0x0002
+
 typedef struct smb_com_transaction_ioctl_rsp {
 	struct smb_hdr hdr;	/* wct = 19 */
 	__u8 Reserved[3];
@@ -1491,15 +1520,30 @@
 	__u8  FileName[0];
 } __attribute__((packed));
 
-struct reparse_data {
-	__u32	ReparseTag;
-	__u16	ReparseDataLength;
+/* For IO_REPARSE_TAG_SYMLINK */
+struct reparse_symlink_data {
+	__le32	ReparseTag;
+	__le16	ReparseDataLength;
 	__u16	Reserved;
-	__u16	SubstituteNameOffset;
-	__u16	SubstituteNameLength;
-	__u16	PrintNameOffset;
-	__u16	PrintNameLength;
-	__u32	Flags;
+	__le16	SubstituteNameOffset;
+	__le16	SubstituteNameLength;
+	__le16	PrintNameOffset;
+	__le16	PrintNameLength;
+	__le32	Flags;
+	char	PathBuffer[0];
+} __attribute__((packed));
+
+/* For IO_REPARSE_TAG_NFS */
+#define NFS_SPECFILE_LNK	0x00000000014B4E4C
+#define NFS_SPECFILE_CHR	0x0000000000524843
+#define NFS_SPECFILE_BLK	0x00000000004B4C42
+#define NFS_SPECFILE_FIFO	0x000000004F464946
+#define NFS_SPECFILE_SOCK	0x000000004B434F53
+struct reparse_posix_data {
+	__le32	ReparseTag;
+	__le16	ReparseDataLength;
+	__u16	Reserved;
+	__le64	InodeType; /* LNK, FIFO, CHR etc. */
 	char	PathBuffer[0];
 } __attribute__((packed));
 
@@ -2200,6 +2244,9 @@
 	__le32 DeviceCharacteristics;
 } __attribute__((packed)) FILE_SYSTEM_DEVICE_INFO; /* device info level 0x104 */
 
+/* minimum includes first three fields, and empty FS Name */
+#define MIN_FS_ATTR_INFO_SIZE 12
+
 typedef struct {
 	__le32 Attributes;
 	__le32 MaxPathNameComponentLength;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index b5ec2a2..aa33976 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -360,6 +360,8 @@
 extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
 			       __u16 fid, char **symlinkinfo,
 			       const struct nls_table *nls_codepage);
+extern int CIFSSMB_set_compression(const unsigned int xid,
+				   struct cifs_tcon *tcon, __u16 fid);
 extern int CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon,
 			const char *fileName, const int disposition,
 			const int access_flags, const int omode,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 4baf359..93b2947 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -3088,7 +3088,8 @@
 	bool is_unicode;
 	unsigned int sub_len;
 	char *sub_start;
-	struct reparse_data *reparse_buf;
+	struct reparse_symlink_data *reparse_buf;
+	struct reparse_posix_data *posix_buf;
 	__u32 data_offset, data_count;
 	char *end_of_smb;
 
@@ -3137,20 +3138,47 @@
 		goto qreparse_out;
 	}
 	end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
-	reparse_buf = (struct reparse_data *)
+	reparse_buf = (struct reparse_symlink_data *)
 				((char *)&pSMBr->hdr.Protocol + data_offset);
 	if ((char *)reparse_buf >= end_of_smb) {
 		rc = -EIO;
 		goto qreparse_out;
 	}
-	if ((reparse_buf->PathBuffer + reparse_buf->PrintNameOffset +
-				reparse_buf->PrintNameLength) > end_of_smb) {
+	if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
+		cifs_dbg(FYI, "NFS style reparse tag\n");
+		posix_buf =  (struct reparse_posix_data *)reparse_buf;
+
+		if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
+			cifs_dbg(FYI, "unsupported file type 0x%llx\n",
+				 le64_to_cpu(posix_buf->InodeType));
+			rc = -EOPNOTSUPP;
+			goto qreparse_out;
+		}
+		is_unicode = true;
+		sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
+		if (posix_buf->PathBuffer + sub_len > end_of_smb) {
+			cifs_dbg(FYI, "reparse buf beyond SMB\n");
+			rc = -EIO;
+			goto qreparse_out;
+		}
+		*symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
+				sub_len, is_unicode, nls_codepage);
+		goto qreparse_out;
+	} else if (reparse_buf->ReparseTag !=
+			cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
+		rc = -EOPNOTSUPP;
+		goto qreparse_out;
+	}
+
+	/* Reparse tag is NTFS symlink */
+	sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
+				reparse_buf->PathBuffer;
+	sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
+	if (sub_start + sub_len > end_of_smb) {
 		cifs_dbg(FYI, "reparse buf beyond SMB\n");
 		rc = -EIO;
 		goto qreparse_out;
 	}
-	sub_start = reparse_buf->SubstituteNameOffset + reparse_buf->PathBuffer;
-	sub_len = reparse_buf->SubstituteNameLength;
 	if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
 		is_unicode = true;
 	else
@@ -3171,6 +3199,60 @@
 	return rc;
 }
 
+int
+CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
+		    __u16 fid)
+{
+	int rc = 0;
+	int bytes_returned;
+	struct smb_com_transaction_compr_ioctl_req *pSMB;
+	struct smb_com_transaction_ioctl_rsp *pSMBr;
+
+	cifs_dbg(FYI, "Set compression for %u\n", fid);
+	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	pSMB->compression_state = cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
+
+	pSMB->TotalParameterCount = 0;
+	pSMB->TotalDataCount = __constant_cpu_to_le32(2);
+	pSMB->MaxParameterCount = 0;
+	pSMB->MaxDataCount = 0;
+	pSMB->MaxSetupCount = 4;
+	pSMB->Reserved = 0;
+	pSMB->ParameterOffset = 0;
+	pSMB->DataCount = __constant_cpu_to_le32(2);
+	pSMB->DataOffset =
+		cpu_to_le32(offsetof(struct smb_com_transaction_compr_ioctl_req,
+				compression_state) - 4);  /* 84 */
+	pSMB->SetupCount = 4;
+	pSMB->SubCommand = __constant_cpu_to_le16(NT_TRANSACT_IOCTL);
+	pSMB->ParameterCount = 0;
+	pSMB->FunctionCode = __constant_cpu_to_le32(FSCTL_SET_COMPRESSION);
+	pSMB->IsFsctl = 1; /* FSCTL */
+	pSMB->IsRootFlag = 0;
+	pSMB->Fid = fid; /* file handle always le */
+	/* 3 byte pad, followed by 2 byte compress state */
+	pSMB->ByteCount = __constant_cpu_to_le16(5);
+	inc_rfc1001_len(pSMB, 5);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc)
+		cifs_dbg(FYI, "Send error in SetCompression = %d\n", rc);
+
+	cifs_buf_release(pSMB);
+
+	/*
+	 * Note: On -EAGAIN error only caller can retry on handle based calls
+	 * since file handle passed in no longer valid.
+	 */
+	return rc;
+}
+
+
 #ifdef CONFIG_CIFS_POSIX
 
 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 886db8b..8813ff7 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2242,6 +2242,8 @@
 
 	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
+		if (ses->status == CifsExiting)
+			continue;
 		if (!match_session(ses, vol))
 			continue;
 		++ses->ses_count;
@@ -2255,24 +2257,37 @@
 static void
 cifs_put_smb_ses(struct cifs_ses *ses)
 {
-	unsigned int xid;
+	unsigned int rc, xid;
 	struct TCP_Server_Info *server = ses->server;
 
 	cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
+
 	spin_lock(&cifs_tcp_ses_lock);
+	if (ses->status == CifsExiting) {
+		spin_unlock(&cifs_tcp_ses_lock);
+		return;
+	}
 	if (--ses->ses_count > 0) {
 		spin_unlock(&cifs_tcp_ses_lock);
 		return;
 	}
+	if (ses->status == CifsGood)
+		ses->status = CifsExiting;
+	spin_unlock(&cifs_tcp_ses_lock);
 
+	if (ses->status == CifsExiting && server->ops->logoff) {
+		xid = get_xid();
+		rc = server->ops->logoff(xid, ses);
+		if (rc)
+			cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
+				__func__, rc);
+		_free_xid(xid);
+	}
+
+	spin_lock(&cifs_tcp_ses_lock);
 	list_del_init(&ses->smb_ses_list);
 	spin_unlock(&cifs_tcp_ses_lock);
 
-	if (ses->status == CifsGood && server->ops->logoff) {
-		xid = get_xid();
-		server->ops->logoff(xid, ses);
-		_free_xid(xid);
-	}
 	sesInfoFree(ses);
 	cifs_put_tcp_session(server);
 }
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c
index b3258f3..8d4b7bc 100644
--- a/fs/cifs/fscache.c
+++ b/fs/cifs/fscache.c
@@ -27,7 +27,7 @@
 {
 	server->fscache =
 		fscache_acquire_cookie(cifs_fscache_netfs.primary_index,
-				&cifs_fscache_server_index_def, server);
+				&cifs_fscache_server_index_def, server, true);
 	cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
 		 __func__, server, server->fscache);
 }
@@ -46,7 +46,7 @@
 
 	tcon->fscache =
 		fscache_acquire_cookie(server->fscache,
-				&cifs_fscache_super_index_def, tcon);
+				&cifs_fscache_super_index_def, tcon, true);
 	cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
 		 __func__, server->fscache, tcon->fscache);
 }
@@ -69,7 +69,7 @@
 
 	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) {
 		cifsi->fscache = fscache_acquire_cookie(tcon->fscache,
-				&cifs_fscache_inode_object_def, cifsi);
+				&cifs_fscache_inode_object_def, cifsi, true);
 		cifs_dbg(FYI, "%s: got FH cookie (0x%p/0x%p)\n",
 			 __func__, tcon->fscache, cifsi->fscache);
 	}
@@ -119,7 +119,7 @@
 		cifsi->fscache = fscache_acquire_cookie(
 					cifs_sb_master_tcon(cifs_sb)->fscache,
 					&cifs_fscache_inode_object_def,
-					cifsi);
+					cifsi, true);
 		cifs_dbg(FYI, "%s: new cookie 0x%p oldcookie 0x%p\n",
 			 __func__, cifsi->fscache, old);
 	}
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index 3e08455..ba54bf6 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -3,7 +3,7 @@
  *
  *   vfs operations that deal with io control
  *
- *   Copyright (C) International Business Machines  Corp., 2005,2007
+ *   Copyright (C) International Business Machines  Corp., 2005,2013
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -34,13 +34,10 @@
 	int rc = -ENOTTY; /* strange error - but the precedent */
 	unsigned int xid;
 	struct cifs_sb_info *cifs_sb;
-#ifdef CONFIG_CIFS_POSIX
 	struct cifsFileInfo *pSMBFile = filep->private_data;
 	struct cifs_tcon *tcon;
 	__u64	ExtAttrBits = 0;
-	__u64	ExtAttrMask = 0;
 	__u64   caps;
-#endif /* CONFIG_CIFS_POSIX */
 
 	xid = get_xid();
 
@@ -49,13 +46,14 @@
 	cifs_sb = CIFS_SB(inode->i_sb);
 
 	switch (command) {
-#ifdef CONFIG_CIFS_POSIX
 		case FS_IOC_GETFLAGS:
 			if (pSMBFile == NULL)
 				break;
 			tcon = tlink_tcon(pSMBFile->tlink);
 			caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
+#ifdef CONFIG_CIFS_POSIX
 			if (CIFS_UNIX_EXTATTR_CAP & caps) {
+				__u64	ExtAttrMask = 0;
 				rc = CIFSGetExtAttr(xid, tcon,
 						    pSMBFile->fid.netfid,
 						    &ExtAttrBits, &ExtAttrMask);
@@ -63,29 +61,50 @@
 					rc = put_user(ExtAttrBits &
 						FS_FL_USER_VISIBLE,
 						(int __user *)arg);
+				if (rc != EOPNOTSUPP)
+					break;
+			}
+#endif /* CONFIG_CIFS_POSIX */
+			rc = 0;
+			if (CIFS_I(inode)->cifsAttrs & ATTR_COMPRESSED) {
+				/* add in the compressed bit */
+				ExtAttrBits = FS_COMPR_FL;
+				rc = put_user(ExtAttrBits & FS_FL_USER_VISIBLE,
+					      (int __user *)arg);
 			}
 			break;
-
 		case FS_IOC_SETFLAGS:
 			if (pSMBFile == NULL)
 				break;
 			tcon = tlink_tcon(pSMBFile->tlink);
 			caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
-			if (CIFS_UNIX_EXTATTR_CAP & caps) {
-				if (get_user(ExtAttrBits, (int __user *)arg)) {
-					rc = -EFAULT;
-					break;
-				}
-				/*
-				 * rc = CIFSGetExtAttr(xid, tcon,
-				 *		       pSMBFile->fid.netfid,
-				 *		       extAttrBits,
-				 *		       &ExtAttrMask);
-				 */
+
+			if (get_user(ExtAttrBits, (int __user *)arg)) {
+				rc = -EFAULT;
+				break;
 			}
-			cifs_dbg(FYI, "set flags not implemented yet\n");
+
+			/*
+			 * if (CIFS_UNIX_EXTATTR_CAP & caps)
+			 *	rc = CIFSSetExtAttr(xid, tcon,
+			 *		       pSMBFile->fid.netfid,
+			 *		       extAttrBits,
+			 *		       &ExtAttrMask);
+			 * if (rc != EOPNOTSUPP)
+			 *	break;
+			 */
+
+			/* Currently only flag we can set is compressed flag */
+			if ((ExtAttrBits & FS_COMPR_FL) == 0)
+				break;
+
+			/* Try to set compress flag */
+			if (tcon->ses->server->ops->set_compression) {
+				rc = tcon->ses->server->ops->set_compression(
+							xid, tcon, pSMBFile);
+				cifs_dbg(FYI, "set compress flag rc %d\n", rc);
+			}
 			break;
-#endif /* CONFIG_CIFS_POSIX */
 		default:
 			cifs_dbg(FYI, "unsupported ioctl\n");
 			break;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 138a011..2f9f379 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -278,7 +278,7 @@
 }
 
 static int
-check_smb_hdr(struct smb_hdr *smb, __u16 mid)
+check_smb_hdr(struct smb_hdr *smb)
 {
 	/* does it have the right SMB "signature" ? */
 	if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) {
@@ -287,13 +287,6 @@
 		return 1;
 	}
 
-	/* Make sure that message ids match */
-	if (mid != smb->Mid) {
-		cifs_dbg(VFS, "Mids do not match. received=%u expected=%u\n",
-			 smb->Mid, mid);
-		return 1;
-	}
-
 	/* if it's a response then accept */
 	if (smb->Flags & SMBFLG_RESPONSE)
 		return 0;
@@ -302,7 +295,8 @@
 	if (smb->Command == SMB_COM_LOCKING_ANDX)
 		return 0;
 
-	cifs_dbg(VFS, "Server sent request, not response. mid=%u\n", smb->Mid);
+	cifs_dbg(VFS, "Server sent request, not response. mid=%u\n",
+		 get_mid(smb));
 	return 1;
 }
 
@@ -310,7 +304,6 @@
 checkSMB(char *buf, unsigned int total_read)
 {
 	struct smb_hdr *smb = (struct smb_hdr *)buf;
-	__u16 mid = smb->Mid;
 	__u32 rfclen = be32_to_cpu(smb->smb_buf_length);
 	__u32 clc_len;  /* calculated length */
 	cifs_dbg(FYI, "checkSMB Length: 0x%x, smb_buf_length: 0x%x\n",
@@ -348,7 +341,7 @@
 	}
 
 	/* otherwise, there is enough to get to the BCC */
-	if (check_smb_hdr(smb, mid))
+	if (check_smb_hdr(smb))
 		return -EIO;
 	clc_len = smbCalcSize(smb);
 
@@ -359,6 +352,7 @@
 	}
 
 	if (4 + rfclen != clc_len) {
+		__u16 mid = get_mid(smb);
 		/* check if bcc wrapped around for large read responses */
 		if ((rfclen > 64 * 1024) && (rfclen > clc_len)) {
 			/* check if lengths match mod 64K */
@@ -366,11 +360,11 @@
 				return 0; /* bcc wrapped */
 		}
 		cifs_dbg(FYI, "Calculated size %u vs length %u mismatch for mid=%u\n",
-			 clc_len, 4 + rfclen, smb->Mid);
+			 clc_len, 4 + rfclen, mid);
 
 		if (4 + rfclen < clc_len) {
 			cifs_dbg(VFS, "RFC1001 size %u smaller than SMB for mid=%u\n",
-				 rfclen, smb->Mid);
+				 rfclen, mid);
 			return -EIO;
 		} else if (rfclen > clc_len + 512) {
 			/*
@@ -383,7 +377,7 @@
 			 * data to 512 bytes.
 			 */
 			cifs_dbg(VFS, "RFC1001 size %u more than 512 bytes larger than SMB for mid=%u\n",
-				 rfclen, smb->Mid);
+				 rfclen, mid);
 			return -EIO;
 		}
 	}
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index af847e1..651a527 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -780,7 +780,9 @@
 	ERRDOS, ERRnoaccess, 0xc0000290}, {
 	ERRDOS, ERRbadfunc, 0xc000029c}, {
 	ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, {
-	ERRDOS, ERRinvlevel, 0x007c0001}, };
+	ERRDOS, ERRinvlevel, 0x007c0001}, {
+	0, 0, 0 }
+};
 
 /*****************************************************************************
  Print an error message from the status code
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 352358d..e87387d 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -500,9 +500,9 @@
 				return NTLMv2;
 			if (global_secflags & CIFSSEC_MAY_NTLM)
 				return NTLM;
-			/* Fallthrough */
 		default:
-			return Unspecified;
+			/* Fallthrough to attempt LANMAN authentication next */
+			break;
 		}
 	case CIFS_NEGFLAVOR_LANMAN:
 		switch (requested) {
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 8233b17..384cffe 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -67,7 +67,7 @@
 	mutex_unlock(&server->srv_mutex);
 
 	cifs_dbg(FYI, "issued NT_CANCEL for mid %u, rc = %d\n",
-		 in_buf->Mid, rc);
+		 get_mid(in_buf), rc);
 
 	return rc;
 }
@@ -101,7 +101,7 @@
 
 	spin_lock(&GlobalMid_Lock);
 	list_for_each_entry(mid, &server->pending_mid_q, qhead) {
-		if (mid->mid == buf->Mid &&
+		if (compare_mid(mid->mid, buf) &&
 		    mid->mid_state == MID_REQUEST_SUBMITTED &&
 		    le16_to_cpu(mid->command) == buf->Command) {
 			spin_unlock(&GlobalMid_Lock);
@@ -807,6 +807,13 @@
 }
 
 static int
+cifs_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
+		   struct cifsFileInfo *cfile)
+{
+	return CIFSSMB_set_compression(xid, tcon, cfile->fid.netfid);
+}
+
+static int
 cifs_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
 		     const char *path, struct cifs_sb_info *cifs_sb,
 		     struct cifs_fid *fid, __u16 search_flags,
@@ -956,6 +963,7 @@
 	.set_path_size = CIFSSMBSetEOF,
 	.set_file_size = CIFSSMBSetFileSize,
 	.set_file_info = smb_set_file_info,
+	.set_compression = cifs_set_compression,
 	.echo = CIFSSMBEcho,
 	.mkdir = CIFSSMBMkDir,
 	.mkdir_setinfo = cifs_mkdir_setinfo,
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 861b332..c571be8 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -209,6 +209,94 @@
 	return rsize;
 }
 
+#ifdef CONFIG_CIFS_STATS2
+static int
+SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon)
+{
+	int rc;
+	unsigned int ret_data_len = 0;
+	struct network_interface_info_ioctl_rsp *out_buf;
+
+	rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
+			FSCTL_QUERY_NETWORK_INTERFACE_INFO, true /* is_fsctl */,
+			NULL /* no data input */, 0 /* no data input */,
+			(char **)&out_buf, &ret_data_len);
+
+	if ((rc == 0)  && (ret_data_len > 0)) {
+		/* Dump info on first interface */
+		cifs_dbg(FYI, "Adapter Capability 0x%x\t",
+			le32_to_cpu(out_buf->Capability));
+		cifs_dbg(FYI, "Link Speed %lld\n",
+			le64_to_cpu(out_buf->LinkSpeed));
+	} else
+		cifs_dbg(VFS, "error %d on ioctl to get interface list\n", rc);
+
+	return rc;
+}
+#endif /* STATS2 */
+
+static void
+smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
+{
+	int rc;
+	__le16 srch_path = 0; /* Null - open root of share */
+	u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+	struct cifs_open_parms oparms;
+	struct cifs_fid fid;
+
+	oparms.tcon = tcon;
+	oparms.desired_access = FILE_READ_ATTRIBUTES;
+	oparms.disposition = FILE_OPEN;
+	oparms.create_options = 0;
+	oparms.fid = &fid;
+	oparms.reconnect = false;
+
+	rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);
+	if (rc)
+		return;
+
+#ifdef CONFIG_CIFS_STATS2
+	SMB3_request_interfaces(xid, tcon);
+#endif /* STATS2 */
+
+	SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
+			FS_ATTRIBUTE_INFORMATION);
+	SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
+			FS_DEVICE_INFORMATION);
+	SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
+			FS_SECTOR_SIZE_INFORMATION); /* SMB3 specific */
+	SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
+	return;
+}
+
+static void
+smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
+{
+	int rc;
+	__le16 srch_path = 0; /* Null - open root of share */
+	u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+	struct cifs_open_parms oparms;
+	struct cifs_fid fid;
+
+	oparms.tcon = tcon;
+	oparms.desired_access = FILE_READ_ATTRIBUTES;
+	oparms.disposition = FILE_OPEN;
+	oparms.create_options = 0;
+	oparms.fid = &fid;
+	oparms.reconnect = false;
+
+	rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);
+	if (rc)
+		return;
+
+	SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
+			FS_ATTRIBUTE_INFORMATION);
+	SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
+			FS_DEVICE_INFORMATION);
+	SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
+	return;
+}
+
 static int
 smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
 			struct cifs_sb_info *cifs_sb, const char *full_path)
@@ -304,7 +392,19 @@
 		seq_puts(m, " ASYMMETRIC,");
 	if (tcon->capabilities == 0)
 		seq_puts(m, " None");
+	if (tcon->ss_flags & SSINFO_FLAGS_ALIGNED_DEVICE)
+		seq_puts(m, " Aligned,");
+	if (tcon->ss_flags & SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE)
+		seq_puts(m, " Partition Aligned,");
+	if (tcon->ss_flags & SSINFO_FLAGS_NO_SEEK_PENALTY)
+		seq_puts(m, " SSD,");
+	if (tcon->ss_flags & SSINFO_FLAGS_TRIM_ENABLED)
+		seq_puts(m, " TRIM-support,");
+
 	seq_printf(m, "\tShare Flags: 0x%x", tcon->share_flags);
+	if (tcon->perf_sector_size)
+		seq_printf(m, "\tOptimal sector size: 0x%x",
+			   tcon->perf_sector_size);
 }
 
 static void
@@ -446,6 +546,14 @@
 }
 
 static int
+smb2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
+		   struct cifsFileInfo *cfile)
+{
+	return SMB2_set_compression(xid, tcon, cfile->fid.persistent_fid,
+			    cfile->fid.volatile_fid);
+}
+
+static int
 smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
 		     const char *path, struct cifs_sb_info *cifs_sb,
 		     struct cifs_fid *fid, __u16 search_flags,
@@ -865,6 +973,7 @@
 	.logoff = SMB2_logoff,
 	.tree_connect = SMB2_tcon,
 	.tree_disconnect = SMB2_tdis,
+	.qfs_tcon = smb2_qfs_tcon,
 	.is_path_accessible = smb2_is_path_accessible,
 	.can_echo = smb2_can_echo,
 	.echo = SMB2_echo,
@@ -874,6 +983,7 @@
 	.set_path_size = smb2_set_path_size,
 	.set_file_size = smb2_set_file_size,
 	.set_file_info = smb2_set_file_info,
+	.set_compression = smb2_set_compression,
 	.mkdir = smb2_mkdir,
 	.mkdir_setinfo = smb2_mkdir_setinfo,
 	.rmdir = smb2_rmdir,
@@ -936,6 +1046,7 @@
 	.logoff = SMB2_logoff,
 	.tree_connect = SMB2_tcon,
 	.tree_disconnect = SMB2_tdis,
+	.qfs_tcon = smb2_qfs_tcon,
 	.is_path_accessible = smb2_is_path_accessible,
 	.can_echo = smb2_can_echo,
 	.echo = SMB2_echo,
@@ -945,6 +1056,7 @@
 	.set_path_size = smb2_set_path_size,
 	.set_file_size = smb2_set_file_size,
 	.set_file_info = smb2_set_file_info,
+	.set_compression = smb2_set_compression,
 	.mkdir = smb2_mkdir,
 	.mkdir_setinfo = smb2_mkdir_setinfo,
 	.rmdir = smb2_rmdir,
@@ -1008,6 +1120,7 @@
 	.logoff = SMB2_logoff,
 	.tree_connect = SMB2_tcon,
 	.tree_disconnect = SMB2_tdis,
+	.qfs_tcon = smb3_qfs_tcon,
 	.is_path_accessible = smb2_is_path_accessible,
 	.can_echo = smb2_can_echo,
 	.echo = SMB2_echo,
@@ -1017,6 +1130,7 @@
 	.set_path_size = smb2_set_path_size,
 	.set_file_size = smb2_set_file_size,
 	.set_file_info = smb2_set_file_info,
+	.set_compression = smb2_set_compression,
 	.mkdir = smb2_mkdir,
 	.mkdir_setinfo = smb2_mkdir_setinfo,
 	.rmdir = smb2_rmdir,
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index eba0efd..8ab05b0 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -687,6 +687,10 @@
 	else
 		return -EIO;
 
+	/* no need to send SMB logoff if uid already closed due to reconnect */
+	if (ses->need_reconnect)
+		goto smb2_session_already_dead;
+
 	rc = small_smb2_init(SMB2_LOGOFF, NULL, (void **) &req);
 	if (rc)
 		return rc;
@@ -701,6 +705,8 @@
 	 * No tcon so can't do
 	 * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
 	 */
+
+smb2_session_already_dead:
 	return rc;
 }
 
@@ -1131,6 +1137,7 @@
 
 	cifs_dbg(FYI, "SMB2 IOCTL\n");
 
+	*out_data = NULL;
 	/* zero out returned data len, in case of error */
 	if (plen)
 		*plen = 0;
@@ -1176,11 +1183,23 @@
 		req->Flags = 0;
 
 	iov[0].iov_base = (char *)req;
-	/* 4 for rfc1002 length field */
-	iov[0].iov_len = get_rfc1002_length(req) + 4;
 
-	if (indatalen)
-		inc_rfc1001_len(req, indatalen);
+	/*
+	 * If no input data, the size of ioctl struct in
+	 * protocol spec still includes a 1 byte data buffer,
+	 * but if input data passed to ioctl, we do not
+	 * want to double count this, so we do not send
+	 * the dummy one byte of data in iovec[0] if sending
+	 * input data (in iovec[1]). We also must add 4 bytes
+	 * in first iovec to allow for rfc1002 length field.
+	 */
+
+	if (indatalen) {
+		iov[0].iov_len = get_rfc1002_length(req) + 4 - 1;
+		inc_rfc1001_len(req, indatalen - 1);
+	} else
+		iov[0].iov_len = get_rfc1002_length(req) + 4;
+
 
 	rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0);
 	rsp = (struct smb2_ioctl_rsp *)iov[0].iov_base;
@@ -1228,6 +1247,33 @@
 	return rc;
 }
 
+/*
+ *   Individual callers to ioctl worker function follow
+ */
+
+int
+SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
+		     u64 persistent_fid, u64 volatile_fid)
+{
+	int rc;
+	char *res_key = NULL;
+	struct  compress_ioctl fsctl_input;
+	char *ret_data = NULL;
+
+	fsctl_input.CompressionState =
+			__constant_cpu_to_le16(COMPRESSION_FORMAT_DEFAULT);
+
+	rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
+			FSCTL_SET_COMPRESSION, true /* is_fsctl */,
+			(char *)&fsctl_input /* data input */,
+			2 /* in data len */, &ret_data /* out data */, NULL);
+
+	cifs_dbg(FYI, "set compression rc %d\n", rc);
+	kfree(res_key);
+
+	return rc;
+}
+
 int
 SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
 	   u64 persistent_fid, u64 volatile_fid)
@@ -2293,7 +2339,7 @@
 	rc = SendReceive2(xid, ses, &iov, 1, &resp_buftype, 0);
 	if (rc) {
 		cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
-		goto qinf_exit;
+		goto qfsinf_exit;
 	}
 	rsp = (struct smb2_query_info_rsp *)iov.iov_base;
 
@@ -2305,7 +2351,70 @@
 	if (!rc)
 		copy_fs_info_to_kstatfs(info, fsdata);
 
-qinf_exit:
+qfsinf_exit:
+	free_rsp_buf(resp_buftype, iov.iov_base);
+	return rc;
+}
+
+int
+SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
+	      u64 persistent_fid, u64 volatile_fid, int level)
+{
+	struct smb2_query_info_rsp *rsp = NULL;
+	struct kvec iov;
+	int rc = 0;
+	int resp_buftype, max_len, min_len;
+	struct cifs_ses *ses = tcon->ses;
+	unsigned int rsp_len, offset;
+
+	if (level == FS_DEVICE_INFORMATION) {
+		max_len = sizeof(FILE_SYSTEM_DEVICE_INFO);
+		min_len = sizeof(FILE_SYSTEM_DEVICE_INFO);
+	} else if (level == FS_ATTRIBUTE_INFORMATION) {
+		max_len = sizeof(FILE_SYSTEM_ATTRIBUTE_INFO);
+		min_len = MIN_FS_ATTR_INFO_SIZE;
+	} else if (level == FS_SECTOR_SIZE_INFORMATION) {
+		max_len = sizeof(struct smb3_fs_ss_info);
+		min_len = sizeof(struct smb3_fs_ss_info);
+	} else {
+		cifs_dbg(FYI, "Invalid qfsinfo level %d\n", level);
+		return -EINVAL;
+	}
+
+	rc = build_qfs_info_req(&iov, tcon, level, max_len,
+				persistent_fid, volatile_fid);
+	if (rc)
+		return rc;
+
+	rc = SendReceive2(xid, ses, &iov, 1, &resp_buftype, 0);
+	if (rc) {
+		cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
+		goto qfsattr_exit;
+	}
+	rsp = (struct smb2_query_info_rsp *)iov.iov_base;
+
+	rsp_len = le32_to_cpu(rsp->OutputBufferLength);
+	offset = le16_to_cpu(rsp->OutputBufferOffset);
+	rc = validate_buf(offset, rsp_len, &rsp->hdr, min_len);
+	if (rc)
+		goto qfsattr_exit;
+
+	if (level == FS_ATTRIBUTE_INFORMATION)
+		memcpy(&tcon->fsAttrInfo, 4 /* RFC1001 len */ + offset
+			+ (char *)&rsp->hdr, min_t(unsigned int,
+			rsp_len, max_len));
+	else if (level == FS_DEVICE_INFORMATION)
+		memcpy(&tcon->fsDevInfo, 4 /* RFC1001 len */ + offset
+			+ (char *)&rsp->hdr, sizeof(FILE_SYSTEM_DEVICE_INFO));
+	else if (level == FS_SECTOR_SIZE_INFORMATION) {
+		struct smb3_fs_ss_info *ss_info = (struct smb3_fs_ss_info *)
+			(4 /* RFC1001 len */ + offset + (char *)&rsp->hdr);
+		tcon->ss_flags = le32_to_cpu(ss_info->Flags);
+		tcon->perf_sector_size =
+			le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf);
+	}
+
+qfsattr_exit:
 	free_rsp_buf(resp_buftype, iov.iov_base);
 	return rc;
 }
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index b83d011..6183b1b 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -569,6 +569,10 @@
 
 #define NO_FILE_ID 0xFFFFFFFFFFFFFFFFULL /* general ioctls to srv not to file */
 
+struct compress_ioctl {
+	__le16 CompressionState; /* See cifspdu.h for possible flag values */
+} __packed;
+
 struct smb2_ioctl_req {
 	struct smb2_hdr hdr;
 	__le16 StructureSize;	/* Must be 57 */
@@ -584,7 +588,7 @@
 	__le32 MaxOutputResponse;
 	__le32 Flags;
 	__u32  Reserved2;
-	char   Buffer[0];
+	__u8   Buffer[0];
 } __packed;
 
 struct smb2_ioctl_rsp {
@@ -870,14 +874,16 @@
 
 /* File System Information Classes */
 #define FS_VOLUME_INFORMATION		1 /* Query */
-#define FS_LABEL_INFORMATION		2 /* Set */
+#define FS_LABEL_INFORMATION		2 /* Local only */
 #define FS_SIZE_INFORMATION		3 /* Query */
 #define FS_DEVICE_INFORMATION		4 /* Query */
 #define FS_ATTRIBUTE_INFORMATION	5 /* Query */
 #define FS_CONTROL_INFORMATION		6 /* Query, Set */
 #define FS_FULL_SIZE_INFORMATION	7 /* Query */
 #define FS_OBJECT_ID_INFORMATION	8 /* Query, Set */
-#define FS_DRIVER_PATH_INFORMATION	9 /* Query */
+#define FS_DRIVER_PATH_INFORMATION	9 /* Local only */
+#define FS_VOLUME_FLAGS_INFORMATION	10 /* Local only */
+#define FS_SECTOR_SIZE_INFORMATION	11 /* SMB3 or later. Query */
 
 struct smb2_fs_full_size_info {
 	__le64 TotalAllocationUnits;
@@ -887,6 +893,22 @@
 	__le32 BytesPerSector;
 } __packed;
 
+#define SSINFO_FLAGS_ALIGNED_DEVICE		0x00000001
+#define SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE 0x00000002
+#define SSINFO_FLAGS_NO_SEEK_PENALTY		0x00000004
+#define SSINFO_FLAGS_TRIM_ENABLED		0x00000008
+
+/* sector size info struct */
+struct smb3_fs_ss_info {
+	__le32 LogicalBytesPerSector;
+	__le32 PhysicalBytesPerSectorForAtomicity;
+	__le32 PhysicalBytesPerSectorForPerf;
+	__le32 FileSystemEffectivePhysicalBytesPerSectorForAtomicity;
+	__le32 Flags;
+	__le32 ByteOffsetForSectorAlignment;
+	__le32 ByteOffsetForPartitionAlignment;
+} __packed;
+
 /* partial list of QUERY INFO levels */
 #define FILE_DIRECTORY_INFORMATION	1
 #define FILE_FULL_DIRECTORY_INFORMATION 2
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index e3fb480..313813e 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -142,12 +142,16 @@
 extern int SMB2_set_info(const unsigned int xid, struct cifs_tcon *tcon,
 			 u64 persistent_fid, u64 volatile_fid,
 			 FILE_BASIC_INFO *buf);
+extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
+				u64 persistent_fid, u64 volatile_fid);
 extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
 			     const u64 persistent_fid, const u64 volatile_fid,
 			     const __u8 oplock_level);
 extern int SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
 			 u64 persistent_file_id, u64 volatile_file_id,
 			 struct kstatfs *FSData);
+extern int SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
+			 u64 persistent_file_id, u64 volatile_file_id, int lvl);
 extern int SMB2_lock(const unsigned int xid, struct cifs_tcon *tcon,
 		     const __u64 persist_fid, const __u64 volatile_fid,
 		     const __u32 pid, const __u64 length, const __u64 offset,
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
index 340abca..59c748c 100644
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -466,7 +466,7 @@
 static inline void
 smb2_seq_num_into_buf(struct TCP_Server_Info *server, struct smb2_hdr *hdr)
 {
-	hdr->MessageId = get_next_mid(server);
+	hdr->MessageId = get_next_mid64(server);
 }
 
 static struct mid_q_entry *
@@ -516,13 +516,19 @@
 		return -EAGAIN;
 	}
 
-	if (ses->status != CifsGood) {
-		/* check if SMB2 session is bad because we are setting it up */
+	if (ses->status == CifsNew) {
 		if ((buf->Command != SMB2_SESSION_SETUP) &&
 		    (buf->Command != SMB2_NEGOTIATE))
 			return -EAGAIN;
 		/* else ok - we are setting up session */
 	}
+
+	if (ses->status == CifsExiting) {
+		if (buf->Command != SMB2_LOGOFF)
+			return -EAGAIN;
+		/* else ok - we are shutting down the session */
+	}
+
 	*mid = smb2_mid_entry_alloc(buf, ses->server);
 	if (*mid == NULL)
 		return -ENOMEM;
diff --git a/fs/cifs/smbfsctl.h b/fs/cifs/smbfsctl.h
index d952ee4..a4b2391f 100644
--- a/fs/cifs/smbfsctl.h
+++ b/fs/cifs/smbfsctl.h
@@ -97,9 +97,23 @@
 #define FSCTL_QUERY_NETWORK_INTERFACE_INFO 0x001401FC /* BB add struct */
 #define FSCTL_SRV_READ_HASH          0x001441BB /* BB add struct */
 
+/* See FSCC 2.1.2.5 */
 #define IO_REPARSE_TAG_MOUNT_POINT   0xA0000003
 #define IO_REPARSE_TAG_HSM           0xC0000004
 #define IO_REPARSE_TAG_SIS           0x80000007
+#define IO_REPARSE_TAG_HSM2          0x80000006
+#define IO_REPARSE_TAG_DRIVER_EXTENDER 0x80000005
+/* Used by the DFS filter. See MS-DFSC */
+#define IO_REPARSE_TAG_DFS           0x8000000A
+/* Used by the DFS filter See MS-DFSC */
+#define IO_REPARSE_TAG_DFSR          0x80000012
+#define IO_REPARSE_TAG_FILTER_MANAGER 0x8000000B
+/* See section MS-FSCC 2.1.2.4 */
+#define IO_REPARSE_TAG_SYMLINK       0xA000000C
+#define IO_REPARSE_TAG_DEDUP         0x80000013
+#define IO_REPARSE_APPXSTREAM	     0xC0000014
+/* NFS symlinks, Win 8/SMB3 and later */
+#define IO_REPARSE_TAG_NFS           0x80000014
 
 /* fsctl flags */
 /* If Flags is set to this value, the request is an FSCTL not ioctl request */
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 6fdcb1b..b375709 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -58,7 +58,7 @@
 		return temp;
 	else {
 		memset(temp, 0, sizeof(struct mid_q_entry));
-		temp->mid = smb_buffer->Mid;	/* always LE */
+		temp->mid = get_mid(smb_buffer);
 		temp->pid = current->pid;
 		temp->command = cpu_to_le16(smb_buffer->Command);
 		cifs_dbg(FYI, "For smb_command %d\n", smb_buffer->Command);
@@ -410,8 +410,13 @@
 wait_for_free_request(struct TCP_Server_Info *server, const int timeout,
 		      const int optype)
 {
-	return wait_for_free_credits(server, timeout,
-				server->ops->get_credits_field(server, optype));
+	int *val;
+
+	val = server->ops->get_credits_field(server, optype);
+	/* Since an echo is already inflight, no need to wait to send another */
+	if (*val <= 0 && optype == CIFS_ECHO_OP)
+		return -EAGAIN;
+	return wait_for_free_credits(server, timeout, val);
 }
 
 static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
@@ -426,13 +431,20 @@
 		return -EAGAIN;
 	}
 
-	if (ses->status != CifsGood) {
-		/* check if SMB session is bad because we are setting it up */
+	if (ses->status == CifsNew) {
 		if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
 			(in_buf->Command != SMB_COM_NEGOTIATE))
 			return -EAGAIN;
 		/* else ok - we are setting up session */
 	}
+
+	if (ses->status == CifsExiting) {
+		/* check if SMB session is bad because we are setting it up */
+		if (in_buf->Command != SMB_COM_LOGOFF_ANDX)
+			return -EAGAIN;
+		/* else ok - we are shutting down session */
+	}
+
 	*ppmidQ = AllocMidQEntry(in_buf, ses->server);
 	if (*ppmidQ == NULL)
 		return -ENOMEM;
diff --git a/fs/dcache.c b/fs/dcache.c
index 72c99b8..1f24cd6 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -536,7 +536,7 @@
  * If ref is non-zero, then decrement the refcount too.
  * Returns dentry requiring refcount drop, or NULL if we're done.
  */
-static inline struct dentry *
+static struct dentry *
 dentry_kill(struct dentry *dentry, int unlock_on_failure)
 	__releases(dentry->d_lock)
 {
@@ -624,7 +624,8 @@
 			goto kill_it;
 	}
 
-	dentry->d_flags |= DCACHE_REFERENCED;
+	if (!(dentry->d_flags & DCACHE_REFERENCED))
+		dentry->d_flags |= DCACHE_REFERENCED;
 	dentry_lru_add(dentry);
 
 	dentry->d_lockref.count--;
@@ -1215,14 +1216,6 @@
  * list is non-empty and continue searching.
  */
 
-/**
- * have_submounts - check for mounts over a dentry
- * @parent: dentry to check.
- *
- * Return true if the parent or its subdirectories contain
- * a mount point
- */
-
 static enum d_walk_ret check_mount(void *data, struct dentry *dentry)
 {
 	int *ret = data;
@@ -1233,6 +1226,13 @@
 	return D_WALK_CONTINUE;
 }
 
+/**
+ * have_submounts - check for mounts over a dentry
+ * @parent: dentry to check.
+ *
+ * Return true if the parent or its subdirectories contain
+ * a mount point
+ */
 int have_submounts(struct dentry *parent)
 {
 	int ret = 0;
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index 88556dc..d5abafd 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -706,9 +706,7 @@
 {
 	struct dlm_lkb *lkb = p;
 
-	if (!lkb->lkb_nodeid)
-		return 1;
-	return 0;
+	return lkb->lkb_nodeid == 0 && lkb->lkb_grmode != DLM_LOCK_IV;
 }
 
 static int lkb_idr_is_any(int id, void *p, void *data)
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index c88e355..000eae2 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -408,7 +408,7 @@
 				    struct page *page)
 {
 	return ecryptfs_lower_header_size(crypt_stat) +
-	       (page->index << PAGE_CACHE_SHIFT);
+	       ((loff_t)page->index << PAGE_CACHE_SHIFT);
 }
 
 /**
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index 7d52806..4725a07 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -1149,7 +1149,7 @@
 	struct ecryptfs_msg_ctx *msg_ctx;
 	struct ecryptfs_message *msg = NULL;
 	char *auth_tok_sig;
-	char *payload;
+	char *payload = NULL;
 	size_t payload_len = 0;
 	int rc;
 
@@ -1203,6 +1203,7 @@
 	}
 out:
 	kfree(msg);
+	kfree(payload);
 	return rc;
 }
 
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 31fd77c..983e396 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -34,7 +34,6 @@
 #include <linux/mutex.h>
 #include <linux/anon_inodes.h>
 #include <linux/device.h>
-#include <linux/freezer.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/mman.h>
@@ -1605,8 +1604,7 @@
 			}
 
 			spin_unlock_irqrestore(&ep->lock, flags);
-			if (!freezable_schedule_hrtimeout_range(to, slack,
-								HRTIMER_MODE_ABS))
+			if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS))
 				timed_out = 1;
 
 			spin_lock_irqsave(&ep->lock, flags);
diff --git a/fs/exec.c b/fs/exec.c
index 351440f..be4c81c 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1542,6 +1542,7 @@
 	current->fs->in_exec = 0;
 	current->in_execve = 0;
 	acct_update_integrals(current);
+	task_numa_free(current);
 	free_bprm(bprm);
 	if (displaced)
 		put_files_struct(displaced);
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index c260de6..8a33764 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -632,6 +632,8 @@
 	int count = 0;
 	ext2_fsblk_t first_block = 0;
 
+	BUG_ON(maxblocks == 0);
+
 	depth = ext2_block_to_path(inode,iblock,offsets,&blocks_to_boundary);
 
 	if (depth == 0)
diff --git a/fs/ext2/xip.c b/fs/ext2/xip.c
index 1c33128..e98171a 100644
--- a/fs/ext2/xip.c
+++ b/fs/ext2/xip.c
@@ -35,6 +35,7 @@
 	int rc;
 
 	memset(&tmp, 0, sizeof(struct buffer_head));
+	tmp.b_size = 1 << inode->i_blkbits;
 	rc = ext2_get_block(inode, pgoff, &tmp, create);
 	*result = tmp.b_blocknr;
 
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 1194b1f..f8cde46 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1783,7 +1783,7 @@
 		d_tmpfile(dentry, inode);
 		err = ext3_orphan_add(handle, inode);
 		if (err)
-			goto err_drop_inode;
+			goto err_unlock_inode;
 		mark_inode_dirty(inode);
 		unlock_new_inode(inode);
 	}
@@ -1791,10 +1791,9 @@
 	if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries))
 		goto retry;
 	return err;
-err_drop_inode:
+err_unlock_inode:
 	ext3_journal_stop(handle);
 	unlock_new_inode(inode);
-	iput(inode);
 	return err;
 }
 
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index c50c761..37fd31e 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -2825,6 +2825,10 @@
 		 * bitmap, and an inode table.
 		 */
 		overhead += ngroups * (2 + sbi->s_itb_per_group);
+
+		/* Add the journal blocks as well */
+                overhead += sbi->s_journal->j_maxlen;
+
 		sbi->s_overhead_last = overhead;
 		smp_wmb();
 		sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 0d424d7..e274e9c 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2563,7 +2563,7 @@
 			break;
 	}
 	blk_finish_plug(&plug);
-	if (!ret && !cycled) {
+	if (!ret && !cycled && wbc->nr_to_write > 0) {
 		cycled = 1;
 		mpd.last_page = writeback_index - 1;
 		mpd.first_page = 0;
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 1bec5a5..5a0408d 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2319,7 +2319,7 @@
 		d_tmpfile(dentry, inode);
 		err = ext4_orphan_add(handle, inode);
 		if (err)
-			goto err_drop_inode;
+			goto err_unlock_inode;
 		mark_inode_dirty(inode);
 		unlock_new_inode(inode);
 	}
@@ -2328,10 +2328,9 @@
 	if (err == -ENOSPC && ext4_should_retry_alloc(dir->i_sb, &retries))
 		goto retry;
 	return err;
-err_drop_inode:
+err_unlock_inode:
 	ext4_journal_stop(handle);
 	unlock_new_inode(inode);
-	iput(inode);
 	return err;
 }
 
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index c081e34..03e9beb 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -1350,6 +1350,8 @@
 				    s_min_extra_isize) {
 					tried_min_extra_isize++;
 					new_extra_isize = s_min_extra_isize;
+					kfree(is); is = NULL;
+					kfree(bs); bs = NULL;
 					goto retry;
 				}
 				error = -1;
diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig
index e06e099..214fe10 100644
--- a/fs/f2fs/Kconfig
+++ b/fs/f2fs/Kconfig
@@ -63,3 +63,11 @@
 	  the extended attribute support in advance.
 
 	  If you are not using a security module, say N.
+
+config F2FS_CHECK_FS
+	bool "F2FS consistency checking feature"
+	depends on F2FS_FS
+	help
+	  Enables BUG_ONs which check the file system consistency in runtime.
+
+	  If you want to improve the performance, say N.
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index b7826ec..d0fc287 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -205,7 +205,8 @@
 	return acl;
 }
 
-static int f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+static int f2fs_set_acl(struct inode *inode, int type,
+			struct posix_acl *acl, struct page *ipage)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 	struct f2fs_inode_info *fi = F2FS_I(inode);
@@ -250,7 +251,7 @@
 		}
 	}
 
-	error = f2fs_setxattr(inode, name_index, "", value, size, NULL);
+	error = f2fs_setxattr(inode, name_index, "", value, size, ipage);
 
 	kfree(value);
 	if (!error)
@@ -260,10 +261,10 @@
 	return error;
 }
 
-int f2fs_init_acl(struct inode *inode, struct inode *dir)
+int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage)
 {
-	struct posix_acl *acl = NULL;
 	struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
+	struct posix_acl *acl = NULL;
 	int error = 0;
 
 	if (!S_ISLNK(inode->i_mode)) {
@@ -276,19 +277,19 @@
 			inode->i_mode &= ~current_umask();
 	}
 
-	if (test_opt(sbi, POSIX_ACL) && acl) {
+	if (!test_opt(sbi, POSIX_ACL) || !acl)
+		goto cleanup;
 
-		if (S_ISDIR(inode->i_mode)) {
-			error = f2fs_set_acl(inode, ACL_TYPE_DEFAULT, acl);
-			if (error)
-				goto cleanup;
-		}
-		error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
-		if (error < 0)
-			return error;
-		if (error > 0)
-			error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl);
+	if (S_ISDIR(inode->i_mode)) {
+		error = f2fs_set_acl(inode, ACL_TYPE_DEFAULT, acl, ipage);
+		if (error)
+			goto cleanup;
 	}
+	error = posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode);
+	if (error < 0)
+		return error;
+	if (error > 0)
+		error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl, ipage);
 cleanup:
 	posix_acl_release(acl);
 	return error;
@@ -313,7 +314,8 @@
 	error = posix_acl_chmod(&acl, GFP_KERNEL, mode);
 	if (error)
 		return error;
-	error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl);
+
+	error = f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl, NULL);
 	posix_acl_release(acl);
 	return error;
 }
@@ -388,7 +390,7 @@
 		acl = NULL;
 	}
 
-	error = f2fs_set_acl(inode, type, acl);
+	error = f2fs_set_acl(inode, type, acl, NULL);
 
 release_and_out:
 	posix_acl_release(acl);
diff --git a/fs/f2fs/acl.h b/fs/f2fs/acl.h
index 80f4306..4963313 100644
--- a/fs/f2fs/acl.h
+++ b/fs/f2fs/acl.h
@@ -36,9 +36,9 @@
 
 #ifdef CONFIG_F2FS_FS_POSIX_ACL
 
-extern struct posix_acl *f2fs_get_acl(struct inode *inode, int type);
-extern int f2fs_acl_chmod(struct inode *inode);
-extern int f2fs_init_acl(struct inode *inode, struct inode *dir);
+extern struct posix_acl *f2fs_get_acl(struct inode *, int);
+extern int f2fs_acl_chmod(struct inode *);
+extern int f2fs_init_acl(struct inode *, struct inode *, struct page *);
 #else
 #define f2fs_check_acl	NULL
 #define f2fs_get_acl	NULL
@@ -49,7 +49,8 @@
 	return 0;
 }
 
-static inline int f2fs_init_acl(struct inode *inode, struct inode *dir)
+static inline int f2fs_init_acl(struct inode *inode, struct inode *dir,
+							struct page *page)
 {
 	return 0;
 }
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index bb31220..5716e5e 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -81,7 +81,7 @@
 	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 
 	/* Should not write any meta pages, if any IO error was occurred */
-	if (wbc->for_reclaim ||
+	if (wbc->for_reclaim || sbi->por_doing ||
 			is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG)) {
 		dec_page_count(sbi, F2FS_DIRTY_META);
 		wbc->pages_skipped++;
@@ -142,8 +142,8 @@
 		for (i = 0; i < nr_pages; i++) {
 			struct page *page = pvec.pages[i];
 			lock_page(page);
-			BUG_ON(page->mapping != mapping);
-			BUG_ON(!PageDirty(page));
+			f2fs_bug_on(page->mapping != mapping);
+			f2fs_bug_on(!PageDirty(page));
 			clear_page_dirty_for_io(page);
 			if (f2fs_write_meta_page(page, &wbc)) {
 				unlock_page(page);
@@ -167,6 +167,8 @@
 	struct address_space *mapping = page->mapping;
 	struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
 
+	trace_f2fs_set_page_dirty(page, META);
+
 	SetPageUptodate(page);
 	if (!PageDirty(page)) {
 		__set_page_dirty_nobuffers(page);
@@ -206,6 +208,7 @@
 void release_orphan_inode(struct f2fs_sb_info *sbi)
 {
 	mutex_lock(&sbi->orphan_inode_mutex);
+	f2fs_bug_on(sbi->n_orphans == 0);
 	sbi->n_orphans--;
 	mutex_unlock(&sbi->orphan_inode_mutex);
 }
@@ -225,12 +228,8 @@
 			break;
 		orphan = NULL;
 	}
-retry:
-	new = kmem_cache_alloc(orphan_entry_slab, GFP_ATOMIC);
-	if (!new) {
-		cond_resched();
-		goto retry;
-	}
+
+	new = f2fs_kmem_cache_alloc(orphan_entry_slab, GFP_ATOMIC);
 	new->ino = ino;
 
 	/* add new_oentry into list which is sorted by inode number */
@@ -253,6 +252,7 @@
 		if (orphan->ino == ino) {
 			list_del(&orphan->list);
 			kmem_cache_free(orphan_entry_slab, orphan);
+			f2fs_bug_on(sbi->n_orphans == 0);
 			sbi->n_orphans--;
 			break;
 		}
@@ -263,7 +263,7 @@
 static void recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
 {
 	struct inode *inode = f2fs_iget(sbi->sb, ino);
-	BUG_ON(IS_ERR(inode));
+	f2fs_bug_on(IS_ERR(inode));
 	clear_nlink(inode);
 
 	/* truncate all the data during iput */
@@ -277,7 +277,7 @@
 	if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG))
 		return 0;
 
-	sbi->por_doing = 1;
+	sbi->por_doing = true;
 	start_blk = __start_cp_addr(sbi) + 1;
 	orphan_blkaddr = __start_sum_addr(sbi) - 1;
 
@@ -294,7 +294,7 @@
 	}
 	/* clear Orphan Flag */
 	clear_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG);
-	sbi->por_doing = 0;
+	sbi->por_doing = false;
 	return 0;
 }
 
@@ -469,9 +469,7 @@
 			return -EEXIST;
 	}
 	list_add_tail(&new->list, head);
-#ifdef CONFIG_F2FS_STAT_FS
-	sbi->n_dirty_dirs++;
-#endif
+	stat_inc_dirty_dir(sbi);
 	return 0;
 }
 
@@ -482,12 +480,8 @@
 
 	if (!S_ISDIR(inode->i_mode))
 		return;
-retry:
-	new = kmem_cache_alloc(inode_entry_slab, GFP_NOFS);
-	if (!new) {
-		cond_resched();
-		goto retry;
-	}
+
+	new = f2fs_kmem_cache_alloc(inode_entry_slab, GFP_NOFS);
 	new->inode = inode;
 	INIT_LIST_HEAD(&new->list);
 
@@ -504,13 +498,9 @@
 void add_dirty_dir_inode(struct inode *inode)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
-	struct dir_inode_entry *new;
-retry:
-	new = kmem_cache_alloc(inode_entry_slab, GFP_NOFS);
-	if (!new) {
-		cond_resched();
-		goto retry;
-	}
+	struct dir_inode_entry *new =
+			f2fs_kmem_cache_alloc(inode_entry_slab, GFP_NOFS);
+
 	new->inode = inode;
 	INIT_LIST_HEAD(&new->list);
 
@@ -541,9 +531,7 @@
 		if (entry->inode == inode) {
 			list_del(&entry->list);
 			kmem_cache_free(inode_entry_slab, entry);
-#ifdef CONFIG_F2FS_STAT_FS
-			sbi->n_dirty_dirs--;
-#endif
+			stat_dec_dirty_dir(sbi);
 			break;
 		}
 	}
@@ -617,11 +605,10 @@
 	blk_start_plug(&plug);
 
 retry_flush_dents:
-	mutex_lock_all(sbi);
-
+	f2fs_lock_all(sbi);
 	/* write all the dirty dentry pages */
 	if (get_pages(sbi, F2FS_DIRTY_DENTS)) {
-		mutex_unlock_all(sbi);
+		f2fs_unlock_all(sbi);
 		sync_dirty_dir_inodes(sbi);
 		goto retry_flush_dents;
 	}
@@ -644,7 +631,22 @@
 static void unblock_operations(struct f2fs_sb_info *sbi)
 {
 	mutex_unlock(&sbi->node_write);
-	mutex_unlock_all(sbi);
+	f2fs_unlock_all(sbi);
+}
+
+static void wait_on_all_pages_writeback(struct f2fs_sb_info *sbi)
+{
+	DEFINE_WAIT(wait);
+
+	for (;;) {
+		prepare_to_wait(&sbi->cp_wait, &wait, TASK_UNINTERRUPTIBLE);
+
+		if (!get_pages(sbi, F2FS_WRITEBACK))
+			break;
+
+		io_schedule();
+	}
+	finish_wait(&sbi->cp_wait, &wait);
 }
 
 static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
@@ -756,8 +758,7 @@
 	f2fs_put_page(cp_page, 1);
 
 	/* wait for previous submitted node/meta pages writeback */
-	while (get_pages(sbi, F2FS_WRITEBACK))
-		congestion_wait(BLK_RW_ASYNC, HZ / 50);
+	wait_on_all_pages_writeback(sbi);
 
 	filemap_fdatawait_range(sbi->node_inode->i_mapping, 0, LONG_MAX);
 	filemap_fdatawait_range(sbi->meta_inode->i_mapping, 0, LONG_MAX);
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 941f9b9..aa3438c 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -68,9 +68,6 @@
 					struct buffer_head *bh_result)
 {
 	struct f2fs_inode_info *fi = F2FS_I(inode);
-#ifdef CONFIG_F2FS_STAT_FS
-	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
-#endif
 	pgoff_t start_fofs, end_fofs;
 	block_t start_blkaddr;
 
@@ -80,9 +77,8 @@
 		return 0;
 	}
 
-#ifdef CONFIG_F2FS_STAT_FS
-	sbi->total_hit_ext++;
-#endif
+	stat_inc_total_hit(inode->i_sb);
+
 	start_fofs = fi->ext.fofs;
 	end_fofs = fi->ext.fofs + fi->ext.len - 1;
 	start_blkaddr = fi->ext.blk_addr;
@@ -100,9 +96,7 @@
 		else
 			bh_result->b_size = UINT_MAX;
 
-#ifdef CONFIG_F2FS_STAT_FS
-		sbi->read_hit_ext++;
-#endif
+		stat_inc_read_hit(inode->i_sb);
 		read_unlock(&fi->ext.ext_lock);
 		return 1;
 	}
@@ -116,7 +110,7 @@
 	pgoff_t fofs, start_fofs, end_fofs;
 	block_t start_blkaddr, end_blkaddr;
 
-	BUG_ON(blk_addr == NEW_ADDR);
+	f2fs_bug_on(blk_addr == NEW_ADDR);
 	fofs = start_bidx_of_node(ofs_of_node(dn->node_page), fi) +
 							dn->ofs_in_node;
 
@@ -442,7 +436,7 @@
 	}
 
 	/* It does not support data allocation */
-	BUG_ON(create);
+	f2fs_bug_on(create);
 
 	if (dn.data_blkaddr != NEW_ADDR && dn.data_blkaddr != NULL_ADDR) {
 		int i;
@@ -560,9 +554,9 @@
 		inode_dec_dirty_dents(inode);
 		err = do_write_data_page(page);
 	} else {
-		int ilock = mutex_lock_op(sbi);
+		f2fs_lock_op(sbi);
 		err = do_write_data_page(page);
-		mutex_unlock_op(sbi, ilock);
+		f2fs_unlock_op(sbi);
 		need_balance_fs = true;
 	}
 	if (err == -ENOENT)
@@ -641,7 +635,6 @@
 	pgoff_t index = ((unsigned long long) pos) >> PAGE_CACHE_SHIFT;
 	struct dnode_of_data dn;
 	int err = 0;
-	int ilock;
 
 	f2fs_balance_fs(sbi);
 repeat:
@@ -650,7 +643,7 @@
 		return -ENOMEM;
 	*pagep = page;
 
-	ilock = mutex_lock_op(sbi);
+	f2fs_lock_op(sbi);
 
 	set_new_dnode(&dn, inode, NULL, NULL, 0);
 	err = get_dnode_of_data(&dn, index, ALLOC_NODE);
@@ -664,7 +657,7 @@
 	if (err)
 		goto err;
 
-	mutex_unlock_op(sbi, ilock);
+	f2fs_unlock_op(sbi);
 
 	if ((len == PAGE_CACHE_SIZE) || PageUptodate(page))
 		return 0;
@@ -700,7 +693,7 @@
 	return 0;
 
 err:
-	mutex_unlock_op(sbi, ilock);
+	f2fs_unlock_op(sbi);
 	f2fs_put_page(page, 1);
 	return err;
 }
@@ -763,6 +756,8 @@
 	struct address_space *mapping = page->mapping;
 	struct inode *inode = mapping->host;
 
+	trace_f2fs_set_page_dirty(page, DATA);
+
 	SetPageUptodate(page);
 	if (!PageDirty(page)) {
 		__set_page_dirty_nobuffers(page);
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 384c6da..594fc1b 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -139,7 +139,7 @@
 	bool room = false;
 	int max_slots = 0;
 
-	BUG_ON(level > MAX_DIR_HASH_DEPTH);
+	f2fs_bug_on(level > MAX_DIR_HASH_DEPTH);
 
 	nbucket = dir_buckets(level);
 	nblock = bucket_blocks(level);
@@ -346,7 +346,7 @@
 				goto error;
 		}
 
-		err = f2fs_init_acl(inode, dir);
+		err = f2fs_init_acl(inode, dir, page);
 		if (err)
 			goto error;
 
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 608f0df..89dc750 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -18,6 +18,13 @@
 #include <linux/crc32.h>
 #include <linux/magic.h>
 #include <linux/kobject.h>
+#include <linux/sched.h>
+
+#ifdef CONFIG_F2FS_CHECK_FS
+#define f2fs_bug_on(condition)	BUG_ON(condition)
+#else
+#define f2fs_bug_on(condition)
+#endif
 
 /*
  * For mount options
@@ -298,6 +305,9 @@
 	unsigned int main_segments;	/* # of segments in main area */
 	unsigned int reserved_segments;	/* # of reserved segments */
 	unsigned int ovp_segments;	/* # of overprovision segments */
+
+	/* a threshold to reclaim prefree segments */
+	unsigned int rec_prefree_segments;
 };
 
 /*
@@ -318,14 +328,6 @@
 };
 
 /*
- * Uses as sbi->fs_lock[NR_GLOBAL_LOCKS].
- * The checkpoint procedure blocks all the locks in this fs_lock array.
- * Some FS operations grab free locks, and if there is no free lock,
- * then wait to grab a lock in a round-robin manner.
- */
-#define NR_GLOBAL_LOCKS	8
-
-/*
  * The below are the page types of bios used in submti_bio().
  * The available types are:
  * DATA			User data pages. It operates as async mode.
@@ -365,12 +367,12 @@
 	struct f2fs_checkpoint *ckpt;		/* raw checkpoint pointer */
 	struct inode *meta_inode;		/* cache meta blocks */
 	struct mutex cp_mutex;			/* checkpoint procedure lock */
-	struct mutex fs_lock[NR_GLOBAL_LOCKS];	/* blocking FS operations */
+	struct rw_semaphore cp_rwsem;		/* blocking FS operations */
 	struct mutex node_write;		/* locking node writes */
 	struct mutex writepages;		/* mutex for writepages() */
-	unsigned char next_lock_num;		/* round-robin global locks */
-	int por_doing;				/* recovery is doing or not */
-	int on_build_free_nids;			/* build_free_nids is doing */
+	bool por_doing;				/* recovery is doing or not */
+	bool on_build_free_nids;		/* build_free_nids is doing */
+	wait_queue_head_t cp_wait;
 
 	/* for orphan inode management */
 	struct list_head orphan_inode_list;	/* orphan inode list */
@@ -520,48 +522,24 @@
 	cp->ckpt_flags = cpu_to_le32(ckpt_flags);
 }
 
-static inline void mutex_lock_all(struct f2fs_sb_info *sbi)
+static inline void f2fs_lock_op(struct f2fs_sb_info *sbi)
 {
-	int i;
-
-	for (i = 0; i < NR_GLOBAL_LOCKS; i++) {
-		/*
-		 * This is the only time we take multiple fs_lock[]
-		 * instances; the order is immaterial since we
-		 * always hold cp_mutex, which serializes multiple
-		 * such operations.
-		 */
-		mutex_lock_nest_lock(&sbi->fs_lock[i], &sbi->cp_mutex);
-	}
+	down_read(&sbi->cp_rwsem);
 }
 
-static inline void mutex_unlock_all(struct f2fs_sb_info *sbi)
+static inline void f2fs_unlock_op(struct f2fs_sb_info *sbi)
 {
-	int i = 0;
-	for (; i < NR_GLOBAL_LOCKS; i++)
-		mutex_unlock(&sbi->fs_lock[i]);
+	up_read(&sbi->cp_rwsem);
 }
 
-static inline int mutex_lock_op(struct f2fs_sb_info *sbi)
+static inline void f2fs_lock_all(struct f2fs_sb_info *sbi)
 {
-	unsigned char next_lock = sbi->next_lock_num % NR_GLOBAL_LOCKS;
-	int i = 0;
-
-	for (; i < NR_GLOBAL_LOCKS; i++)
-		if (mutex_trylock(&sbi->fs_lock[i]))
-			return i;
-
-	mutex_lock(&sbi->fs_lock[next_lock]);
-	sbi->next_lock_num++;
-	return next_lock;
+	down_write_nest_lock(&sbi->cp_rwsem, &sbi->cp_mutex);
 }
 
-static inline void mutex_unlock_op(struct f2fs_sb_info *sbi, int ilock)
+static inline void f2fs_unlock_all(struct f2fs_sb_info *sbi)
 {
-	if (ilock < 0)
-		return;
-	BUG_ON(ilock >= NR_GLOBAL_LOCKS);
-	mutex_unlock(&sbi->fs_lock[ilock]);
+	up_write(&sbi->cp_rwsem);
 }
 
 /*
@@ -612,8 +590,8 @@
 						blkcnt_t count)
 {
 	spin_lock(&sbi->stat_lock);
-	BUG_ON(sbi->total_valid_block_count < (block_t) count);
-	BUG_ON(inode->i_blocks < count);
+	f2fs_bug_on(sbi->total_valid_block_count < (block_t) count);
+	f2fs_bug_on(inode->i_blocks < count);
 	inode->i_blocks -= count;
 	sbi->total_valid_block_count -= (block_t)count;
 	spin_unlock(&sbi->stat_lock);
@@ -745,9 +723,9 @@
 {
 	spin_lock(&sbi->stat_lock);
 
-	BUG_ON(sbi->total_valid_block_count < count);
-	BUG_ON(sbi->total_valid_node_count < count);
-	BUG_ON(inode->i_blocks < count);
+	f2fs_bug_on(sbi->total_valid_block_count < count);
+	f2fs_bug_on(sbi->total_valid_node_count < count);
+	f2fs_bug_on(inode->i_blocks < count);
 
 	inode->i_blocks -= count;
 	sbi->total_valid_node_count -= count;
@@ -768,7 +746,7 @@
 static inline void inc_valid_inode_count(struct f2fs_sb_info *sbi)
 {
 	spin_lock(&sbi->stat_lock);
-	BUG_ON(sbi->total_valid_inode_count == sbi->total_node_count);
+	f2fs_bug_on(sbi->total_valid_inode_count == sbi->total_node_count);
 	sbi->total_valid_inode_count++;
 	spin_unlock(&sbi->stat_lock);
 }
@@ -776,7 +754,7 @@
 static inline int dec_valid_inode_count(struct f2fs_sb_info *sbi)
 {
 	spin_lock(&sbi->stat_lock);
-	BUG_ON(!sbi->total_valid_inode_count);
+	f2fs_bug_on(!sbi->total_valid_inode_count);
 	sbi->total_valid_inode_count--;
 	spin_unlock(&sbi->stat_lock);
 	return 0;
@@ -797,7 +775,7 @@
 		return;
 
 	if (unlock) {
-		BUG_ON(!PageLocked(page));
+		f2fs_bug_on(!PageLocked(page));
 		unlock_page(page);
 	}
 	page_cache_release(page);
@@ -819,6 +797,20 @@
 	return kmem_cache_create(name, size, 0, SLAB_RECLAIM_ACCOUNT, ctor);
 }
 
+static inline void *f2fs_kmem_cache_alloc(struct kmem_cache *cachep,
+						gfp_t flags)
+{
+	void *entry;
+retry:
+	entry = kmem_cache_alloc(cachep, flags);
+	if (!entry) {
+		cond_resched();
+		goto retry;
+	}
+
+	return entry;
+}
+
 #define RAW_IS_INODE(p)	((p)->footer.nid == (p)->footer.ino)
 
 static inline bool IS_INODE(struct page *page)
@@ -979,6 +971,7 @@
  */
 void f2fs_set_inode_flags(struct inode *);
 struct inode *f2fs_iget(struct super_block *, unsigned long);
+int try_to_free_nats(struct f2fs_sb_info *, int);
 void update_inode(struct inode *, struct page *);
 int update_inode_page(struct inode *);
 int f2fs_write_inode(struct inode *, struct writeback_control *);
@@ -1033,6 +1026,7 @@
 int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int);
 int truncate_inode_blocks(struct inode *, pgoff_t);
 int truncate_xattr_node(struct inode *, struct page *);
+int wait_on_node_pages_writeback(struct f2fs_sb_info *, nid_t);
 int remove_inode_page(struct inode *);
 struct page *new_inode_page(struct inode *, const struct qstr *);
 struct page *new_node_page(struct dnode_of_data *, unsigned int, struct page *);
@@ -1059,6 +1053,7 @@
  * segment.c
  */
 void f2fs_balance_fs(struct f2fs_sb_info *);
+void f2fs_balance_fs_bg(struct f2fs_sb_info *);
 void invalidate_blocks(struct f2fs_sb_info *, block_t);
 void clear_prefree_segments(struct f2fs_sb_info *);
 int npages_for_summary_flush(struct f2fs_sb_info *);
@@ -1172,7 +1167,16 @@
 	return (struct f2fs_stat_info*)sbi->stat_info;
 }
 
-#define stat_inc_call_count(si)	((si)->call_count++)
+#define stat_inc_call_count(si)		((si)->call_count++)
+#define stat_inc_bggc_count(sbi)	((sbi)->bg_gc++)
+#define stat_inc_dirty_dir(sbi)		((sbi)->n_dirty_dirs++)
+#define stat_dec_dirty_dir(sbi)		((sbi)->n_dirty_dirs--)
+#define stat_inc_total_hit(sb)		((F2FS_SB(sb))->total_hit_ext++)
+#define stat_inc_read_hit(sb)		((F2FS_SB(sb))->read_hit_ext++)
+#define stat_inc_seg_type(sbi, curseg)					\
+		((sbi)->segment_count[(curseg)->alloc_type]++)
+#define stat_inc_block_count(sbi, curseg)				\
+		((sbi)->block_count[(curseg)->alloc_type]++)
 
 #define stat_inc_seg_count(sbi, type)					\
 	do {								\
@@ -1207,6 +1211,13 @@
 void f2fs_destroy_root_stats(void);
 #else
 #define stat_inc_call_count(si)
+#define stat_inc_bggc_count(si)
+#define stat_inc_dirty_dir(sbi)
+#define stat_dec_dirty_dir(sbi)
+#define stat_inc_total_hit(sb)
+#define stat_inc_read_hit(sb)
+#define stat_inc_seg_type(sbi, curseg)
+#define stat_inc_block_count(sbi, curseg)
 #define stat_inc_seg_count(si, type)
 #define stat_inc_tot_blk_count(si, blks)
 #define stat_inc_data_blk_count(si, blks)
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 02c9069..7d714f4 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -35,18 +35,18 @@
 	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 	block_t old_blk_addr;
 	struct dnode_of_data dn;
-	int err, ilock;
+	int err;
 
 	f2fs_balance_fs(sbi);
 
 	sb_start_pagefault(inode->i_sb);
 
 	/* block allocation */
-	ilock = mutex_lock_op(sbi);
+	f2fs_lock_op(sbi);
 	set_new_dnode(&dn, inode, NULL, NULL, 0);
 	err = get_dnode_of_data(&dn, page->index, ALLOC_NODE);
 	if (err) {
-		mutex_unlock_op(sbi, ilock);
+		f2fs_unlock_op(sbi);
 		goto out;
 	}
 
@@ -56,12 +56,12 @@
 		err = reserve_new_block(&dn);
 		if (err) {
 			f2fs_put_dnode(&dn);
-			mutex_unlock_op(sbi, ilock);
+			f2fs_unlock_op(sbi);
 			goto out;
 		}
 	}
 	f2fs_put_dnode(&dn);
-	mutex_unlock_op(sbi, ilock);
+	f2fs_unlock_op(sbi);
 
 	file_update_time(vma->vm_file);
 	lock_page(page);
@@ -88,6 +88,7 @@
 	set_page_dirty(page);
 	SetPageUptodate(page);
 
+	trace_f2fs_vm_page_mkwrite(page, DATA);
 mapped:
 	/* fill the page */
 	wait_on_page_writeback(page);
@@ -188,8 +189,9 @@
 			if (ret)
 				goto out;
 		}
-		filemap_fdatawait_range(sbi->node_inode->i_mapping,
-							0, LONG_MAX);
+		ret = wait_on_node_pages_writeback(sbi, inode->i_ino);
+		if (ret)
+			goto out;
 		ret = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
 	}
 out:
@@ -270,7 +272,7 @@
 	unsigned int blocksize = inode->i_sb->s_blocksize;
 	struct dnode_of_data dn;
 	pgoff_t free_from;
-	int count = 0, ilock = -1;
+	int count = 0;
 	int err;
 
 	trace_f2fs_truncate_blocks_enter(inode, from);
@@ -278,13 +280,13 @@
 	free_from = (pgoff_t)
 			((from + blocksize - 1) >> (sbi->log_blocksize));
 
-	ilock = mutex_lock_op(sbi);
+	f2fs_lock_op(sbi);
 	set_new_dnode(&dn, inode, NULL, NULL, 0);
 	err = get_dnode_of_data(&dn, free_from, LOOKUP_NODE);
 	if (err) {
 		if (err == -ENOENT)
 			goto free_next;
-		mutex_unlock_op(sbi, ilock);
+		f2fs_unlock_op(sbi);
 		trace_f2fs_truncate_blocks_exit(inode, err);
 		return err;
 	}
@@ -295,7 +297,7 @@
 		count = ADDRS_PER_BLOCK;
 
 	count -= dn.ofs_in_node;
-	BUG_ON(count < 0);
+	f2fs_bug_on(count < 0);
 
 	if (dn.ofs_in_node || IS_INODE(dn.node_page)) {
 		truncate_data_blocks_range(&dn, count);
@@ -305,7 +307,7 @@
 	f2fs_put_dnode(&dn);
 free_next:
 	err = truncate_inode_blocks(inode, free_from);
-	mutex_unlock_op(sbi, ilock);
+	f2fs_unlock_op(sbi);
 
 	/* lastly zero out the first data page */
 	truncate_partial_data_page(inode, from);
@@ -416,16 +418,15 @@
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 	struct page *page;
-	int ilock;
 
 	if (!len)
 		return;
 
 	f2fs_balance_fs(sbi);
 
-	ilock = mutex_lock_op(sbi);
+	f2fs_lock_op(sbi);
 	page = get_new_data_page(inode, NULL, index, false);
-	mutex_unlock_op(sbi, ilock);
+	f2fs_unlock_op(sbi);
 
 	if (!IS_ERR(page)) {
 		wait_on_page_writeback(page);
@@ -484,7 +485,6 @@
 			struct address_space *mapping = inode->i_mapping;
 			loff_t blk_start, blk_end;
 			struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
-			int ilock;
 
 			f2fs_balance_fs(sbi);
 
@@ -493,9 +493,9 @@
 			truncate_inode_pages_range(mapping, blk_start,
 					blk_end - 1);
 
-			ilock = mutex_lock_op(sbi);
+			f2fs_lock_op(sbi);
 			ret = truncate_hole(inode, pg_start, pg_end);
-			mutex_unlock_op(sbi, ilock);
+			f2fs_unlock_op(sbi);
 		}
 	}
 
@@ -529,13 +529,12 @@
 
 	for (index = pg_start; index <= pg_end; index++) {
 		struct dnode_of_data dn;
-		int ilock;
 
-		ilock = mutex_lock_op(sbi);
+		f2fs_lock_op(sbi);
 		set_new_dnode(&dn, inode, NULL, NULL, 0);
 		ret = get_dnode_of_data(&dn, index, ALLOC_NODE);
 		if (ret) {
-			mutex_unlock_op(sbi, ilock);
+			f2fs_unlock_op(sbi);
 			break;
 		}
 
@@ -543,12 +542,12 @@
 			ret = reserve_new_block(&dn);
 			if (ret) {
 				f2fs_put_dnode(&dn);
-				mutex_unlock_op(sbi, ilock);
+				f2fs_unlock_op(sbi);
 				break;
 			}
 		}
 		f2fs_put_dnode(&dn);
-		mutex_unlock_op(sbi, ilock);
+		f2fs_unlock_op(sbi);
 
 		if (pg_start == pg_end)
 			new_size = offset + len;
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 2f157e8..b7ad1ec 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -77,13 +77,15 @@
 		else
 			wait_ms = increase_sleep_time(gc_th, wait_ms);
 
-#ifdef CONFIG_F2FS_STAT_FS
-		sbi->bg_gc++;
-#endif
+		stat_inc_bggc_count(sbi);
 
 		/* if return value is not zero, no victim was selected */
 		if (f2fs_gc(sbi))
 			wait_ms = gc_th->no_gc_sleep_time;
+
+		/* balancing f2fs's metadata periodically */
+		f2fs_balance_fs_bg(sbi);
+
 	} while (!kthread_should_stop());
 	return 0;
 }
@@ -236,8 +238,8 @@
 	return UINT_MAX - ((100 * (100 - u) * age) / (100 + u));
 }
 
-static unsigned int get_gc_cost(struct f2fs_sb_info *sbi, unsigned int segno,
-					struct victim_sel_policy *p)
+static inline unsigned int get_gc_cost(struct f2fs_sb_info *sbi,
+			unsigned int segno, struct victim_sel_policy *p)
 {
 	if (p->alloc_mode == SSR)
 		return get_seg_entry(sbi, segno)->ckpt_valid_blocks;
@@ -293,7 +295,11 @@
 			}
 			break;
 		}
-		p.offset = ((segno / p.ofs_unit) * p.ofs_unit) + p.ofs_unit;
+
+		p.offset = segno + p.ofs_unit;
+		if (p.ofs_unit > 1)
+			p.offset -= segno % p.ofs_unit;
+
 		secno = GET_SECNO(sbi, segno);
 
 		if (sec_usage_check(sbi, secno))
@@ -306,10 +312,9 @@
 		if (p.min_cost > cost) {
 			p.min_segno = segno;
 			p.min_cost = cost;
-		}
-
-		if (cost == max_cost)
+		} else if (unlikely(cost == max_cost)) {
 			continue;
+		}
 
 		if (nsearched++ >= p.max_search) {
 			sbi->last_victim[p.gc_mode] = segno;
@@ -358,12 +363,8 @@
 		iput(inode);
 		return;
 	}
-repeat:
-	new_ie = kmem_cache_alloc(winode_slab, GFP_NOFS);
-	if (!new_ie) {
-		cond_resched();
-		goto repeat;
-	}
+
+	new_ie = f2fs_kmem_cache_alloc(winode_slab, GFP_NOFS);
 	new_ie->inode = inode;
 	list_add_tail(&new_ie->list, ilist);
 }
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 9339cd2..d0eaa9f 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -37,6 +37,31 @@
 		inode->i_flags |= S_DIRSYNC;
 }
 
+static void __get_inode_rdev(struct inode *inode, struct f2fs_inode *ri)
+{
+	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
+			S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
+		if (ri->i_addr[0])
+			inode->i_rdev = old_decode_dev(le32_to_cpu(ri->i_addr[0]));
+		else
+			inode->i_rdev = new_decode_dev(le32_to_cpu(ri->i_addr[1]));
+	}
+}
+
+static void __set_inode_rdev(struct inode *inode, struct f2fs_inode *ri)
+{
+	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
+		if (old_valid_dev(inode->i_rdev)) {
+			ri->i_addr[0] = cpu_to_le32(old_encode_dev(inode->i_rdev));
+			ri->i_addr[1] = 0;
+		} else {
+			ri->i_addr[0] = 0;
+			ri->i_addr[1] = cpu_to_le32(new_encode_dev(inode->i_rdev));
+			ri->i_addr[2] = 0;
+		}
+	}
+}
+
 static int do_read_inode(struct inode *inode)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
@@ -73,10 +98,6 @@
 	inode->i_ctime.tv_nsec = le32_to_cpu(ri->i_ctime_nsec);
 	inode->i_mtime.tv_nsec = le32_to_cpu(ri->i_mtime_nsec);
 	inode->i_generation = le32_to_cpu(ri->i_generation);
-	if (ri->i_addr[0])
-		inode->i_rdev = old_decode_dev(le32_to_cpu(ri->i_addr[0]));
-	else
-		inode->i_rdev = new_decode_dev(le32_to_cpu(ri->i_addr[1]));
 
 	fi->i_current_depth = le32_to_cpu(ri->i_current_depth);
 	fi->i_xattr_nid = le32_to_cpu(ri->i_xattr_nid);
@@ -84,8 +105,13 @@
 	fi->flags = 0;
 	fi->i_advise = ri->i_advise;
 	fi->i_pino = le32_to_cpu(ri->i_pino);
+
 	get_extent_info(&fi->ext, ri->i_ext);
 	get_inline_info(fi, ri);
+
+	/* get rdev by using inline_info */
+	__get_inode_rdev(inode, ri);
+
 	f2fs_put_page(node_page, 1);
 	return 0;
 }
@@ -179,21 +205,10 @@
 	ri->i_pino = cpu_to_le32(F2FS_I(inode)->i_pino);
 	ri->i_generation = cpu_to_le32(inode->i_generation);
 
-	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
-		if (old_valid_dev(inode->i_rdev)) {
-			ri->i_addr[0] =
-				cpu_to_le32(old_encode_dev(inode->i_rdev));
-			ri->i_addr[1] = 0;
-		} else {
-			ri->i_addr[0] = 0;
-			ri->i_addr[1] =
-				cpu_to_le32(new_encode_dev(inode->i_rdev));
-			ri->i_addr[2] = 0;
-		}
-	}
-
+	__set_inode_rdev(inode, ri);
 	set_cold_node(inode, node_page);
 	set_page_dirty(node_page);
+
 	clear_inode_flag(F2FS_I(inode), FI_DIRTY_INODE);
 }
 
@@ -214,7 +229,7 @@
 int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
-	int ret, ilock;
+	int ret;
 
 	if (inode->i_ino == F2FS_NODE_INO(sbi) ||
 			inode->i_ino == F2FS_META_INO(sbi))
@@ -227,9 +242,9 @@
 	 * We need to lock here to prevent from producing dirty node pages
 	 * during the urgent cleaning time when runing out of free sections.
 	 */
-	ilock = mutex_lock_op(sbi);
+	f2fs_lock_op(sbi);
 	ret = update_inode_page(inode);
-	mutex_unlock_op(sbi, ilock);
+	f2fs_unlock_op(sbi);
 
 	if (wbc)
 		f2fs_balance_fs(sbi);
@@ -243,7 +258,6 @@
 void f2fs_evict_inode(struct inode *inode)
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
-	int ilock;
 
 	trace_f2fs_evict_inode(inode);
 	truncate_inode_pages(&inode->i_data, 0);
@@ -252,7 +266,7 @@
 			inode->i_ino == F2FS_META_INO(sbi))
 		goto no_delete;
 
-	BUG_ON(atomic_read(&F2FS_I(inode)->dirty_dents));
+	f2fs_bug_on(atomic_read(&F2FS_I(inode)->dirty_dents));
 	remove_dirty_dir_inode(inode);
 
 	if (inode->i_nlink || is_bad_inode(inode))
@@ -265,9 +279,9 @@
 	if (F2FS_HAS_BLOCKS(inode))
 		f2fs_truncate(inode);
 
-	ilock = mutex_lock_op(sbi);
+	f2fs_lock_op(sbi);
 	remove_inode_page(inode);
-	mutex_unlock_op(sbi, ilock);
+	f2fs_unlock_op(sbi);
 
 	sb_end_intwrite(inode->i_sb);
 no_delete:
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 2a5359c..575adac 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -27,19 +27,19 @@
 	nid_t ino;
 	struct inode *inode;
 	bool nid_free = false;
-	int err, ilock;
+	int err;
 
 	inode = new_inode(sb);
 	if (!inode)
 		return ERR_PTR(-ENOMEM);
 
-	ilock = mutex_lock_op(sbi);
+	f2fs_lock_op(sbi);
 	if (!alloc_nid(sbi, &ino)) {
-		mutex_unlock_op(sbi, ilock);
+		f2fs_unlock_op(sbi);
 		err = -ENOSPC;
 		goto fail;
 	}
-	mutex_unlock_op(sbi, ilock);
+	f2fs_unlock_op(sbi);
 
 	inode->i_uid = current_fsuid();
 
@@ -115,7 +115,7 @@
 	struct f2fs_sb_info *sbi = F2FS_SB(sb);
 	struct inode *inode;
 	nid_t ino = 0;
-	int err, ilock;
+	int err;
 
 	f2fs_balance_fs(sbi);
 
@@ -131,9 +131,9 @@
 	inode->i_mapping->a_ops = &f2fs_dblock_aops;
 	ino = inode->i_ino;
 
-	ilock = mutex_lock_op(sbi);
+	f2fs_lock_op(sbi);
 	err = f2fs_add_link(dentry, inode);
-	mutex_unlock_op(sbi, ilock);
+	f2fs_unlock_op(sbi);
 	if (err)
 		goto out;
 
@@ -157,7 +157,7 @@
 	struct inode *inode = old_dentry->d_inode;
 	struct super_block *sb = dir->i_sb;
 	struct f2fs_sb_info *sbi = F2FS_SB(sb);
-	int err, ilock;
+	int err;
 
 	f2fs_balance_fs(sbi);
 
@@ -165,9 +165,9 @@
 	ihold(inode);
 
 	set_inode_flag(F2FS_I(inode), FI_INC_LINK);
-	ilock = mutex_lock_op(sbi);
+	f2fs_lock_op(sbi);
 	err = f2fs_add_link(dentry, inode);
-	mutex_unlock_op(sbi, ilock);
+	f2fs_unlock_op(sbi);
 	if (err)
 		goto out;
 
@@ -220,7 +220,6 @@
 	struct f2fs_dir_entry *de;
 	struct page *page;
 	int err = -ENOENT;
-	int ilock;
 
 	trace_f2fs_unlink_enter(dir, dentry);
 	f2fs_balance_fs(sbi);
@@ -229,16 +228,16 @@
 	if (!de)
 		goto fail;
 
+	f2fs_lock_op(sbi);
 	err = acquire_orphan_inode(sbi);
 	if (err) {
+		f2fs_unlock_op(sbi);
 		kunmap(page);
 		f2fs_put_page(page, 0);
 		goto fail;
 	}
-
-	ilock = mutex_lock_op(sbi);
 	f2fs_delete_entry(de, page, inode);
-	mutex_unlock_op(sbi, ilock);
+	f2fs_unlock_op(sbi);
 
 	/* In order to evict this inode,  we set it dirty */
 	mark_inode_dirty(inode);
@@ -254,7 +253,7 @@
 	struct f2fs_sb_info *sbi = F2FS_SB(sb);
 	struct inode *inode;
 	size_t symlen = strlen(symname) + 1;
-	int err, ilock;
+	int err;
 
 	f2fs_balance_fs(sbi);
 
@@ -265,9 +264,9 @@
 	inode->i_op = &f2fs_symlink_inode_operations;
 	inode->i_mapping->a_ops = &f2fs_dblock_aops;
 
-	ilock = mutex_lock_op(sbi);
+	f2fs_lock_op(sbi);
 	err = f2fs_add_link(dentry, inode);
-	mutex_unlock_op(sbi, ilock);
+	f2fs_unlock_op(sbi);
 	if (err)
 		goto out;
 
@@ -290,7 +289,7 @@
 {
 	struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
 	struct inode *inode;
-	int err, ilock;
+	int err;
 
 	f2fs_balance_fs(sbi);
 
@@ -304,9 +303,9 @@
 	mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO);
 
 	set_inode_flag(F2FS_I(inode), FI_INC_LINK);
-	ilock = mutex_lock_op(sbi);
+	f2fs_lock_op(sbi);
 	err = f2fs_add_link(dentry, inode);
-	mutex_unlock_op(sbi, ilock);
+	f2fs_unlock_op(sbi);
 	if (err)
 		goto out_fail;
 
@@ -342,7 +341,6 @@
 	struct f2fs_sb_info *sbi = F2FS_SB(sb);
 	struct inode *inode;
 	int err = 0;
-	int ilock;
 
 	if (!new_valid_dev(rdev))
 		return -EINVAL;
@@ -356,9 +354,9 @@
 	init_special_inode(inode, inode->i_mode, rdev);
 	inode->i_op = &f2fs_special_inode_operations;
 
-	ilock = mutex_lock_op(sbi);
+	f2fs_lock_op(sbi);
 	err = f2fs_add_link(dentry, inode);
-	mutex_unlock_op(sbi, ilock);
+	f2fs_unlock_op(sbi);
 	if (err)
 		goto out;
 
@@ -387,7 +385,7 @@
 	struct f2fs_dir_entry *old_dir_entry = NULL;
 	struct f2fs_dir_entry *old_entry;
 	struct f2fs_dir_entry *new_entry;
-	int err = -ENOENT, ilock = -1;
+	int err = -ENOENT;
 
 	f2fs_balance_fs(sbi);
 
@@ -402,7 +400,7 @@
 			goto out_old;
 	}
 
-	ilock = mutex_lock_op(sbi);
+	f2fs_lock_op(sbi);
 
 	if (new_inode) {
 
@@ -467,7 +465,7 @@
 		update_inode_page(old_dir);
 	}
 
-	mutex_unlock_op(sbi, ilock);
+	f2fs_unlock_op(sbi);
 	return 0;
 
 put_out_dir:
@@ -477,7 +475,7 @@
 		kunmap(old_dir_page);
 		f2fs_put_page(old_dir_page, 0);
 	}
-	mutex_unlock_op(sbi, ilock);
+	f2fs_unlock_op(sbi);
 out_old:
 	kunmap(old_page);
 	f2fs_put_page(old_page, 0);
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 51ef278..4ac4150 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -204,7 +204,7 @@
 		}
 		e->ni = *ni;
 		e->checkpointed = true;
-		BUG_ON(ni->blk_addr == NEW_ADDR);
+		f2fs_bug_on(ni->blk_addr == NEW_ADDR);
 	} else if (new_blkaddr == NEW_ADDR) {
 		/*
 		 * when nid is reallocated,
@@ -212,19 +212,19 @@
 		 * So, reinitialize it with new information.
 		 */
 		e->ni = *ni;
-		BUG_ON(ni->blk_addr != NULL_ADDR);
+		f2fs_bug_on(ni->blk_addr != NULL_ADDR);
 	}
 
 	if (new_blkaddr == NEW_ADDR)
 		e->checkpointed = false;
 
 	/* sanity check */
-	BUG_ON(nat_get_blkaddr(e) != ni->blk_addr);
-	BUG_ON(nat_get_blkaddr(e) == NULL_ADDR &&
+	f2fs_bug_on(nat_get_blkaddr(e) != ni->blk_addr);
+	f2fs_bug_on(nat_get_blkaddr(e) == NULL_ADDR &&
 			new_blkaddr == NULL_ADDR);
-	BUG_ON(nat_get_blkaddr(e) == NEW_ADDR &&
+	f2fs_bug_on(nat_get_blkaddr(e) == NEW_ADDR &&
 			new_blkaddr == NEW_ADDR);
-	BUG_ON(nat_get_blkaddr(e) != NEW_ADDR &&
+	f2fs_bug_on(nat_get_blkaddr(e) != NEW_ADDR &&
 			nat_get_blkaddr(e) != NULL_ADDR &&
 			new_blkaddr == NEW_ADDR);
 
@@ -240,7 +240,7 @@
 	write_unlock(&nm_i->nat_tree_lock);
 }
 
-static int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
+int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
 {
 	struct f2fs_nm_info *nm_i = NM_I(sbi);
 
@@ -495,10 +495,10 @@
 
 	get_node_info(sbi, dn->nid, &ni);
 	if (dn->inode->i_blocks == 0) {
-		BUG_ON(ni.blk_addr != NULL_ADDR);
+		f2fs_bug_on(ni.blk_addr != NULL_ADDR);
 		goto invalidate;
 	}
-	BUG_ON(ni.blk_addr == NULL_ADDR);
+	f2fs_bug_on(ni.blk_addr == NULL_ADDR);
 
 	/* Deallocate node address */
 	invalidate_blocks(sbi, ni.blk_addr);
@@ -822,7 +822,7 @@
 	}
 
 	/* 0 is possible, after f2fs_new_inode() is failed */
-	BUG_ON(inode->i_blocks != 0 && inode->i_blocks != 1);
+	f2fs_bug_on(inode->i_blocks != 0 && inode->i_blocks != 1);
 	set_new_dnode(&dn, inode, page, page, ino);
 	truncate_node(&dn);
 	return 0;
@@ -863,7 +863,7 @@
 	get_node_info(sbi, dn->nid, &old_ni);
 
 	/* Reinitialize old_ni with new node page */
-	BUG_ON(old_ni.blk_addr != NULL_ADDR);
+	f2fs_bug_on(old_ni.blk_addr != NULL_ADDR);
 	new_ni = old_ni;
 	new_ni.ino = dn->inode->i_ino;
 	set_node_addr(sbi, &new_ni, NEW_ADDR);
@@ -969,7 +969,7 @@
 		goto repeat;
 	}
 got_it:
-	BUG_ON(nid != nid_of_node(page));
+	f2fs_bug_on(nid != nid_of_node(page));
 	mark_page_accessed(page);
 	return page;
 }
@@ -1148,6 +1148,47 @@
 	return nwritten;
 }
 
+int wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino)
+{
+	struct address_space *mapping = sbi->node_inode->i_mapping;
+	pgoff_t index = 0, end = LONG_MAX;
+	struct pagevec pvec;
+	int nr_pages;
+	int ret2 = 0, ret = 0;
+
+	pagevec_init(&pvec, 0);
+	while ((index <= end) &&
+			(nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
+			PAGECACHE_TAG_WRITEBACK,
+			min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1)) != 0) {
+		unsigned i;
+
+		for (i = 0; i < nr_pages; i++) {
+			struct page *page = pvec.pages[i];
+
+			/* until radix tree lookup accepts end_index */
+			if (page->index > end)
+				continue;
+
+			if (ino && ino_of_node(page) == ino) {
+				wait_on_page_writeback(page);
+				if (TestClearPageError(page))
+					ret = -EIO;
+			}
+		}
+		pagevec_release(&pvec);
+		cond_resched();
+	}
+
+	if (test_and_clear_bit(AS_ENOSPC, &mapping->flags))
+		ret2 = -ENOSPC;
+	if (test_and_clear_bit(AS_EIO, &mapping->flags))
+		ret2 = -EIO;
+	if (!ret)
+		ret = ret2;
+	return ret;
+}
+
 static int f2fs_write_node_page(struct page *page,
 				struct writeback_control *wbc)
 {
@@ -1156,11 +1197,14 @@
 	block_t new_addr;
 	struct node_info ni;
 
+	if (sbi->por_doing)
+		goto redirty_out;
+
 	wait_on_page_writeback(page);
 
 	/* get old block addr of this node page */
 	nid = nid_of_node(page);
-	BUG_ON(page->index != nid);
+	f2fs_bug_on(page->index != nid);
 
 	get_node_info(sbi, nid, &ni);
 
@@ -1171,12 +1215,8 @@
 		return 0;
 	}
 
-	if (wbc->for_reclaim) {
-		dec_page_count(sbi, F2FS_DIRTY_NODES);
-		wbc->pages_skipped++;
-		set_page_dirty(page);
-		return AOP_WRITEPAGE_ACTIVATE;
-	}
+	if (wbc->for_reclaim)
+		goto redirty_out;
 
 	mutex_lock(&sbi->node_write);
 	set_page_writeback(page);
@@ -1186,6 +1226,12 @@
 	mutex_unlock(&sbi->node_write);
 	unlock_page(page);
 	return 0;
+
+redirty_out:
+	dec_page_count(sbi, F2FS_DIRTY_NODES);
+	wbc->pages_skipped++;
+	set_page_dirty(page);
+	return AOP_WRITEPAGE_ACTIVATE;
 }
 
 /*
@@ -1200,11 +1246,8 @@
 	struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
 	long nr_to_write = wbc->nr_to_write;
 
-	/* First check balancing cached NAT entries */
-	if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK)) {
-		f2fs_sync_fs(sbi->sb, true);
-		return 0;
-	}
+	/* balancing f2fs's metadata in background */
+	f2fs_balance_fs_bg(sbi);
 
 	/* collect a number of dirty node pages and write together */
 	if (get_pages(sbi, F2FS_DIRTY_NODES) < COLLECT_DIRTY_NODES)
@@ -1223,6 +1266,8 @@
 	struct address_space *mapping = page->mapping;
 	struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
 
+	trace_f2fs_set_page_dirty(page, NODE);
+
 	SetPageUptodate(page);
 	if (!PageDirty(page)) {
 		__set_page_dirty_nobuffers(page);
@@ -1291,23 +1336,18 @@
 	if (nid == 0)
 		return 0;
 
-	if (!build)
-		goto retry;
-
-	/* do not add allocated nids */
-	read_lock(&nm_i->nat_tree_lock);
-	ne = __lookup_nat_cache(nm_i, nid);
-	if (ne && nat_get_blkaddr(ne) != NULL_ADDR)
-		allocated = true;
-	read_unlock(&nm_i->nat_tree_lock);
-	if (allocated)
-		return 0;
-retry:
-	i = kmem_cache_alloc(free_nid_slab, GFP_NOFS);
-	if (!i) {
-		cond_resched();
-		goto retry;
+	if (build) {
+		/* do not add allocated nids */
+		read_lock(&nm_i->nat_tree_lock);
+		ne = __lookup_nat_cache(nm_i, nid);
+		if (ne && nat_get_blkaddr(ne) != NULL_ADDR)
+			allocated = true;
+		read_unlock(&nm_i->nat_tree_lock);
+		if (allocated)
+			return 0;
 	}
+
+	i = f2fs_kmem_cache_alloc(free_nid_slab, GFP_NOFS);
 	i->nid = nid;
 	i->state = NID_NEW;
 
@@ -1350,7 +1390,7 @@
 			break;
 
 		blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr);
-		BUG_ON(blk_addr == NEW_ADDR);
+		f2fs_bug_on(blk_addr == NEW_ADDR);
 		if (blk_addr == NULL_ADDR) {
 			if (add_free_nid(nm_i, start_nid, true) < 0)
 				break;
@@ -1421,14 +1461,14 @@
 
 	/* We should not use stale free nids created by build_free_nids */
 	if (nm_i->fcnt && !sbi->on_build_free_nids) {
-		BUG_ON(list_empty(&nm_i->free_nid_list));
+		f2fs_bug_on(list_empty(&nm_i->free_nid_list));
 		list_for_each(this, &nm_i->free_nid_list) {
 			i = list_entry(this, struct free_nid, list);
 			if (i->state == NID_NEW)
 				break;
 		}
 
-		BUG_ON(i->state != NID_NEW);
+		f2fs_bug_on(i->state != NID_NEW);
 		*nid = i->nid;
 		i->state = NID_ALLOC;
 		nm_i->fcnt--;
@@ -1439,9 +1479,9 @@
 
 	/* Let's scan nat pages and its caches to get free nids */
 	mutex_lock(&nm_i->build_lock);
-	sbi->on_build_free_nids = 1;
+	sbi->on_build_free_nids = true;
 	build_free_nids(sbi);
-	sbi->on_build_free_nids = 0;
+	sbi->on_build_free_nids = false;
 	mutex_unlock(&nm_i->build_lock);
 	goto retry;
 }
@@ -1456,7 +1496,7 @@
 
 	spin_lock(&nm_i->free_nid_list_lock);
 	i = __lookup_free_nid_list(nid, &nm_i->free_nid_list);
-	BUG_ON(!i || i->state != NID_ALLOC);
+	f2fs_bug_on(!i || i->state != NID_ALLOC);
 	__del_from_free_nid_list(i);
 	spin_unlock(&nm_i->free_nid_list_lock);
 }
@@ -1474,7 +1514,7 @@
 
 	spin_lock(&nm_i->free_nid_list_lock);
 	i = __lookup_free_nid_list(nid, &nm_i->free_nid_list);
-	BUG_ON(!i || i->state != NID_ALLOC);
+	f2fs_bug_on(!i || i->state != NID_ALLOC);
 	if (nm_i->fcnt > 2 * MAX_FREE_NIDS) {
 		__del_from_free_nid_list(i);
 	} else {
@@ -1677,7 +1717,7 @@
 			nat_blk = page_address(page);
 		}
 
-		BUG_ON(!nat_blk);
+		f2fs_bug_on(!nat_blk);
 		raw_ne = nat_blk->entries[nid - start_nid];
 flush_now:
 		new_blkaddr = nat_get_blkaddr(ne);
@@ -1781,11 +1821,11 @@
 	/* destroy free nid list */
 	spin_lock(&nm_i->free_nid_list_lock);
 	list_for_each_entry_safe(i, next_i, &nm_i->free_nid_list, list) {
-		BUG_ON(i->state == NID_ALLOC);
+		f2fs_bug_on(i->state == NID_ALLOC);
 		__del_from_free_nid_list(i);
 		nm_i->fcnt--;
 	}
-	BUG_ON(nm_i->fcnt);
+	f2fs_bug_on(nm_i->fcnt);
 	spin_unlock(&nm_i->free_nid_list_lock);
 
 	/* destroy nat cache */
@@ -1799,7 +1839,7 @@
 			__del_from_nat_cache(nm_i, e);
 		}
 	}
-	BUG_ON(nm_i->nat_cnt);
+	f2fs_bug_on(nm_i->nat_cnt);
 	write_unlock(&nm_i->nat_tree_lock);
 
 	kfree(nm_i->nat_bitmap);
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index 51ef5ee..fdc8116 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -64,24 +64,31 @@
 	name.name = raw_inode->i_name;
 retry:
 	de = f2fs_find_entry(dir, &name, &page);
-	if (de && inode->i_ino == le32_to_cpu(de->ino)) {
-		kunmap(page);
-		f2fs_put_page(page, 0);
-		goto out;
-	}
+	if (de && inode->i_ino == le32_to_cpu(de->ino))
+		goto out_unmap_put;
 	if (de) {
 		einode = f2fs_iget(inode->i_sb, le32_to_cpu(de->ino));
 		if (IS_ERR(einode)) {
 			WARN_ON(1);
 			if (PTR_ERR(einode) == -ENOENT)
 				err = -EEXIST;
-			goto out;
+			goto out_unmap_put;
+		}
+		err = acquire_orphan_inode(F2FS_SB(inode->i_sb));
+		if (err) {
+			iput(einode);
+			goto out_unmap_put;
 		}
 		f2fs_delete_entry(de, page, einode);
 		iput(einode);
 		goto retry;
 	}
 	err = __f2fs_add_link(dir, &name, inode);
+	goto out;
+
+out_unmap_put:
+	kunmap(page);
+	f2fs_put_page(page, 0);
 out:
 	f2fs_msg(inode->i_sb, KERN_NOTICE, "recover_inode and its dentry: "
 			"ino = %x, name = %s, dir = %lx, err = %d",
@@ -285,7 +292,6 @@
 	struct f2fs_summary sum;
 	struct node_info ni;
 	int err = 0, recovered = 0;
-	int ilock;
 
 	start = start_bidx_of_node(ofs_of_node(page), fi);
 	if (IS_INODE(page))
@@ -293,20 +299,20 @@
 	else
 		end = start + ADDRS_PER_BLOCK;
 
-	ilock = mutex_lock_op(sbi);
+	f2fs_lock_op(sbi);
 	set_new_dnode(&dn, inode, NULL, NULL, 0);
 
 	err = get_dnode_of_data(&dn, start, ALLOC_NODE);
 	if (err) {
-		mutex_unlock_op(sbi, ilock);
+		f2fs_unlock_op(sbi);
 		return err;
 	}
 
 	wait_on_page_writeback(dn.node_page);
 
 	get_node_info(sbi, dn.nid, &ni);
-	BUG_ON(ni.ino != ino_of_node(page));
-	BUG_ON(ofs_of_node(dn.node_page) != ofs_of_node(page));
+	f2fs_bug_on(ni.ino != ino_of_node(page));
+	f2fs_bug_on(ofs_of_node(dn.node_page) != ofs_of_node(page));
 
 	for (; start < end; start++) {
 		block_t src, dest;
@@ -316,9 +322,9 @@
 
 		if (src != dest && dest != NEW_ADDR && dest != NULL_ADDR) {
 			if (src == NULL_ADDR) {
-				int err = reserve_new_block(&dn);
+				err = reserve_new_block(&dn);
 				/* We should not get -ENOSPC */
-				BUG_ON(err);
+				f2fs_bug_on(err);
 			}
 
 			/* Check the previous node page having this index */
@@ -349,7 +355,7 @@
 	recover_node_page(sbi, dn.node_page, &sum, &ni, blkaddr);
 err:
 	f2fs_put_dnode(&dn);
-	mutex_unlock_op(sbi, ilock);
+	f2fs_unlock_op(sbi);
 
 	f2fs_msg(sbi->sb, KERN_NOTICE, "recover_data: ino = %lx, "
 			"recovered_data = %d blocks, err = %d",
@@ -419,6 +425,7 @@
 {
 	struct list_head inode_list;
 	int err;
+	bool need_writecp = false;
 
 	fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry",
 			sizeof(struct fsync_inode_entry), NULL);
@@ -428,7 +435,7 @@
 	INIT_LIST_HEAD(&inode_list);
 
 	/* step #1: find fsynced inode numbers */
-	sbi->por_doing = 1;
+	sbi->por_doing = true;
 	err = find_fsync_dnodes(sbi, &inode_list);
 	if (err)
 		goto out;
@@ -436,14 +443,16 @@
 	if (list_empty(&inode_list))
 		goto out;
 
+	need_writecp = true;
+
 	/* step #2: recover data */
 	err = recover_data(sbi, &inode_list, CURSEG_WARM_NODE);
-	BUG_ON(!list_empty(&inode_list));
+	f2fs_bug_on(!list_empty(&inode_list));
 out:
 	destroy_fsync_dnodes(&inode_list);
 	kmem_cache_destroy(fsync_entry_slab);
-	sbi->por_doing = 0;
-	if (!err)
+	sbi->por_doing = false;
+	if (!err && need_writecp)
 		write_checkpoint(sbi, false);
 	return err;
 }
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 09af9c7..fa284d3 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -36,6 +36,14 @@
 	}
 }
 
+void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi)
+{
+	/* check the # of cached NAT entries and prefree segments */
+	if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK) ||
+				excess_prefree_segs(sbi))
+		f2fs_sync_fs(sbi->sb, true);
+}
+
 static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno,
 		enum dirty_type dirty_type)
 {
@@ -50,20 +58,10 @@
 
 	if (dirty_type == DIRTY) {
 		struct seg_entry *sentry = get_seg_entry(sbi, segno);
-		enum dirty_type t = DIRTY_HOT_DATA;
+		enum dirty_type t = sentry->type;
 
-		dirty_type = sentry->type;
-
-		if (!test_and_set_bit(segno, dirty_i->dirty_segmap[dirty_type]))
-			dirty_i->nr_dirty[dirty_type]++;
-
-		/* Only one bitmap should be set */
-		for (; t <= DIRTY_COLD_NODE; t++) {
-			if (t == dirty_type)
-				continue;
-			if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t]))
-				dirty_i->nr_dirty[t]--;
-		}
+		if (!test_and_set_bit(segno, dirty_i->dirty_segmap[t]))
+			dirty_i->nr_dirty[t]++;
 	}
 }
 
@@ -76,12 +74,11 @@
 		dirty_i->nr_dirty[dirty_type]--;
 
 	if (dirty_type == DIRTY) {
-		enum dirty_type t = DIRTY_HOT_DATA;
+		struct seg_entry *sentry = get_seg_entry(sbi, segno);
+		enum dirty_type t = sentry->type;
 
-		/* clear all the bitmaps */
-		for (; t <= DIRTY_COLD_NODE; t++)
-			if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t]))
-				dirty_i->nr_dirty[t]--;
+		if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t]))
+			dirty_i->nr_dirty[t]--;
 
 		if (get_valid_blocks(sbi, segno, sbi->segs_per_sec) == 0)
 			clear_bit(GET_SECNO(sbi, segno),
@@ -142,27 +139,33 @@
 void clear_prefree_segments(struct f2fs_sb_info *sbi)
 {
 	struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
-	unsigned int segno = -1;
+	unsigned long *prefree_map = dirty_i->dirty_segmap[PRE];
 	unsigned int total_segs = TOTAL_SEGS(sbi);
+	unsigned int start = 0, end = -1;
 
 	mutex_lock(&dirty_i->seglist_lock);
+
 	while (1) {
-		segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs,
-				segno + 1);
-		if (segno >= total_segs)
+		int i;
+		start = find_next_bit(prefree_map, total_segs, end + 1);
+		if (start >= total_segs)
 			break;
+		end = find_next_zero_bit(prefree_map, total_segs, start + 1);
 
-		if (test_and_clear_bit(segno, dirty_i->dirty_segmap[PRE]))
-			dirty_i->nr_dirty[PRE]--;
+		for (i = start; i < end; i++)
+			clear_bit(i, prefree_map);
 
-		/* Let's use trim */
-		if (test_opt(sbi, DISCARD))
-			blkdev_issue_discard(sbi->sb->s_bdev,
-					START_BLOCK(sbi, segno) <<
-					sbi->log_sectors_per_block,
-					1 << (sbi->log_sectors_per_block +
-						sbi->log_blocks_per_seg),
-					GFP_NOFS, 0);
+		dirty_i->nr_dirty[PRE] -= end - start;
+
+		if (!test_opt(sbi, DISCARD))
+			continue;
+
+		blkdev_issue_discard(sbi->sb->s_bdev,
+				START_BLOCK(sbi, start) <<
+				sbi->log_sectors_per_block,
+				(1 << (sbi->log_sectors_per_block +
+				sbi->log_blocks_per_seg)) * (end - start),
+				GFP_NOFS, 0);
 	}
 	mutex_unlock(&dirty_i->seglist_lock);
 }
@@ -195,7 +198,7 @@
 	new_vblocks = se->valid_blocks + del;
 	offset = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) & (sbi->blocks_per_seg - 1);
 
-	BUG_ON((new_vblocks >> (sizeof(unsigned short) << 3) ||
+	f2fs_bug_on((new_vblocks >> (sizeof(unsigned short) << 3) ||
 				(new_vblocks > sbi->blocks_per_seg)));
 
 	se->valid_blocks = new_vblocks;
@@ -235,7 +238,7 @@
 	unsigned int segno = GET_SEGNO(sbi, addr);
 	struct sit_info *sit_i = SIT_I(sbi);
 
-	BUG_ON(addr == NULL_ADDR);
+	f2fs_bug_on(addr == NULL_ADDR);
 	if (addr == NEW_ADDR)
 		return;
 
@@ -267,9 +270,8 @@
  */
 int npages_for_summary_flush(struct f2fs_sb_info *sbi)
 {
-	int total_size_bytes = 0;
 	int valid_sum_count = 0;
-	int i, sum_space;
+	int i, sum_in_page;
 
 	for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
 		if (sbi->ckpt->alloc_type[i] == SSR)
@@ -278,13 +280,12 @@
 			valid_sum_count += curseg_blkoff(sbi, i);
 	}
 
-	total_size_bytes = valid_sum_count * (SUMMARY_SIZE + 1)
-			+ sizeof(struct nat_journal) + 2
-			+ sizeof(struct sit_journal) + 2;
-	sum_space = PAGE_CACHE_SIZE - SUM_FOOTER_SIZE;
-	if (total_size_bytes < sum_space)
+	sum_in_page = (PAGE_CACHE_SIZE - 2 * SUM_JOURNAL_SIZE -
+			SUM_FOOTER_SIZE) / SUMMARY_SIZE;
+	if (valid_sum_count <= sum_in_page)
 		return 1;
-	else if (total_size_bytes < 2 * sum_space)
+	else if ((valid_sum_count - sum_in_page) <=
+		(PAGE_CACHE_SIZE - SUM_FOOTER_SIZE) / SUMMARY_SIZE)
 		return 2;
 	return 3;
 }
@@ -350,7 +351,7 @@
 		if (dir == ALLOC_RIGHT) {
 			secno = find_next_zero_bit(free_i->free_secmap,
 							TOTAL_SECS(sbi), 0);
-			BUG_ON(secno >= TOTAL_SECS(sbi));
+			f2fs_bug_on(secno >= TOTAL_SECS(sbi));
 		} else {
 			go_left = 1;
 			left_start = hint - 1;
@@ -366,7 +367,7 @@
 		}
 		left_start = find_next_zero_bit(free_i->free_secmap,
 							TOTAL_SECS(sbi), 0);
-		BUG_ON(left_start >= TOTAL_SECS(sbi));
+		f2fs_bug_on(left_start >= TOTAL_SECS(sbi));
 		break;
 	}
 	secno = left_start;
@@ -405,7 +406,7 @@
 	}
 got_it:
 	/* set it as dirty segment in free segmap */
-	BUG_ON(test_bit(segno, free_i->free_segmap));
+	f2fs_bug_on(test_bit(segno, free_i->free_segmap));
 	__set_inuse(sbi, segno);
 	*newseg = segno;
 	write_unlock(&free_i->segmap_lock);
@@ -550,9 +551,8 @@
 		change_curseg(sbi, type, true);
 	else
 		new_curseg(sbi, type, false);
-#ifdef CONFIG_F2FS_STAT_FS
-	sbi->segment_count[curseg->alloc_type]++;
-#endif
+
+	stat_inc_seg_type(sbi, curseg);
 }
 
 void allocate_new_segments(struct f2fs_sb_info *sbi)
@@ -597,6 +597,11 @@
 
 	if (p->is_sync)
 		complete(p->wait);
+
+	if (!get_pages(p->sbi, F2FS_WRITEBACK) &&
+			!list_empty(&p->sbi->cp_wait.task_list))
+		wake_up(&p->sbi->cp_wait);
+
 	kfree(p);
 	bio_put(bio);
 }
@@ -657,6 +662,7 @@
 				block_t blk_addr, enum page_type type)
 {
 	struct block_device *bdev = sbi->sb->s_bdev;
+	int bio_blocks;
 
 	verify_block_addr(sbi, blk_addr);
 
@@ -676,7 +682,8 @@
 			goto retry;
 		}
 
-		sbi->bio[type] = f2fs_bio_alloc(bdev, max_hw_blocks(sbi));
+		bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi));
+		sbi->bio[type] = f2fs_bio_alloc(bdev, bio_blocks);
 		sbi->bio[type]->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr);
 		sbi->bio[type]->bi_private = priv;
 		/*
@@ -771,7 +778,7 @@
 		return __get_segment_type_4(page, p_type);
 	}
 	/* NR_CURSEG_TYPE(6) logs by default */
-	BUG_ON(sbi->active_logs != NR_CURSEG_TYPE);
+	f2fs_bug_on(sbi->active_logs != NR_CURSEG_TYPE);
 	return __get_segment_type_6(page, p_type);
 }
 
@@ -801,9 +808,8 @@
 
 	mutex_lock(&sit_i->sentry_lock);
 	__refresh_next_blkoff(sbi, curseg);
-#ifdef CONFIG_F2FS_STAT_FS
-	sbi->block_count[curseg->alloc_type]++;
-#endif
+
+	stat_inc_block_count(sbi, curseg);
 
 	/*
 	 * SIT information should be updated before segment allocation,
@@ -849,7 +855,7 @@
 	struct f2fs_summary sum;
 	struct node_info ni;
 
-	BUG_ON(old_blkaddr == NULL_ADDR);
+	f2fs_bug_on(old_blkaddr == NULL_ADDR);
 	get_node_info(sbi, dn->nid, &ni);
 	set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
 
@@ -1122,8 +1128,6 @@
 						SUM_JOURNAL_SIZE);
 	written_size += SUM_JOURNAL_SIZE;
 
-	set_page_dirty(page);
-
 	/* Step 3: write summary entries */
 	for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
 		unsigned short blkoff;
@@ -1142,18 +1146,20 @@
 			summary = (struct f2fs_summary *)(kaddr + written_size);
 			*summary = seg_i->sum_blk->entries[j];
 			written_size += SUMMARY_SIZE;
-			set_page_dirty(page);
 
 			if (written_size + SUMMARY_SIZE <= PAGE_CACHE_SIZE -
 							SUM_FOOTER_SIZE)
 				continue;
 
+			set_page_dirty(page);
 			f2fs_put_page(page, 1);
 			page = NULL;
 		}
 	}
-	if (page)
+	if (page) {
+		set_page_dirty(page);
 		f2fs_put_page(page, 1);
+	}
 }
 
 static void write_normal_summaries(struct f2fs_sb_info *sbi,
@@ -1239,7 +1245,7 @@
 	/* get current sit block page without lock */
 	src_page = get_meta_page(sbi, src_off);
 	dst_page = grab_meta_page(sbi, dst_off);
-	BUG_ON(PageDirty(src_page));
+	f2fs_bug_on(PageDirty(src_page));
 
 	src_addr = page_address(src_page);
 	dst_addr = page_address(dst_page);
@@ -1271,9 +1277,9 @@
 			__mark_sit_entry_dirty(sbi, segno);
 		}
 		update_sits_in_cursum(sum, -sits_in_cursum(sum));
-		return 1;
+		return true;
 	}
-	return 0;
+	return false;
 }
 
 /*
@@ -1637,6 +1643,7 @@
 	sm_info->ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
 	sm_info->main_segments = le32_to_cpu(raw_super->segment_count_main);
 	sm_info->ssa_blkaddr = le32_to_cpu(raw_super->ssa_blkaddr);
+	sm_info->rec_prefree_segments = DEF_RECLAIM_PREFREE_SEGMENTS;
 
 	err = build_sit_info(sbi);
 	if (err)
@@ -1744,6 +1751,8 @@
 void destroy_segment_manager(struct f2fs_sb_info *sbi)
 {
 	struct f2fs_sm_info *sm_info = SM_I(sbi);
+	if (!sm_info)
+		return;
 	destroy_dirty_segmap(sbi);
 	destroy_curseg(sbi);
 	destroy_free_segmap(sbi);
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index bdd10ea..269f690 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -14,6 +14,8 @@
 #define NULL_SEGNO			((unsigned int)(~0))
 #define NULL_SECNO			((unsigned int)(~0))
 
+#define DEF_RECLAIM_PREFREE_SEGMENTS	100	/* 200MB of prefree segments */
+
 /* L: Logical segment # in volume, R: Relative segment # in main area */
 #define GET_L2R_SEGNO(free_i, segno)	(segno - free_i->start_segno)
 #define GET_R2L_SEGNO(free_i, segno)	(segno + free_i->start_segno)
@@ -90,6 +92,8 @@
 	(blk_addr << ((sbi)->log_blocksize - F2FS_LOG_SECTOR_SIZE))
 #define SECTOR_TO_BLOCK(sbi, sectors)					\
 	(sectors >> ((sbi)->log_blocksize - F2FS_LOG_SECTOR_SIZE))
+#define MAX_BIO_BLOCKS(max_hw_blocks)					\
+	(min((int)max_hw_blocks, BIO_MAX_PAGES))
 
 /* during checkpoint, bio_private is used to synchronize the last bio */
 struct bio_private {
@@ -470,6 +474,11 @@
 						reserved_sections(sbi)));
 }
 
+static inline bool excess_prefree_segs(struct f2fs_sb_info *sbi)
+{
+	return (prefree_segments(sbi) > SM_I(sbi)->rec_prefree_segments);
+}
+
 static inline int utilization(struct f2fs_sb_info *sbi)
 {
 	return div_u64((u64)valid_user_blocks(sbi) * 100, sbi->user_block_count);
@@ -513,16 +522,13 @@
 	return curseg->next_blkoff;
 }
 
+#ifdef CONFIG_F2FS_CHECK_FS
 static inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno)
 {
 	unsigned int end_segno = SM_I(sbi)->segment_count - 1;
 	BUG_ON(segno > end_segno);
 }
 
-/*
- * This function is used for only debugging.
- * NOTE: In future, we have to remove this function.
- */
 static inline void verify_block_addr(struct f2fs_sb_info *sbi, block_t blk_addr)
 {
 	struct f2fs_sm_info *sm_info = SM_I(sbi);
@@ -541,8 +547,9 @@
 {
 	struct f2fs_sm_info *sm_info = SM_I(sbi);
 	unsigned int end_segno = sm_info->segment_count - 1;
+	bool is_valid  = test_bit_le(0, raw_sit->valid_map) ? true : false;
 	int valid_blocks = 0;
-	int i;
+	int cur_pos = 0, next_pos;
 
 	/* check segment usage */
 	BUG_ON(GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg);
@@ -551,11 +558,26 @@
 	BUG_ON(segno > end_segno);
 
 	/* check bitmap with valid block count */
-	for (i = 0; i < sbi->blocks_per_seg; i++)
-		if (f2fs_test_bit(i, raw_sit->valid_map))
-			valid_blocks++;
+	do {
+		if (is_valid) {
+			next_pos = find_next_zero_bit_le(&raw_sit->valid_map,
+					sbi->blocks_per_seg,
+					cur_pos);
+			valid_blocks += next_pos - cur_pos;
+		} else
+			next_pos = find_next_bit_le(&raw_sit->valid_map,
+					sbi->blocks_per_seg,
+					cur_pos);
+		cur_pos = next_pos;
+		is_valid = !is_valid;
+	} while (cur_pos < sbi->blocks_per_seg);
 	BUG_ON(GET_SIT_VBLOCKS(raw_sit) != valid_blocks);
 }
+#else
+#define check_seg_range(sbi, segno)
+#define verify_block_addr(sbi, blk_addr)
+#define check_block_count(sbi, segno, raw_sit)
+#endif
 
 static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi,
 						unsigned int start)
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 13d0a0f..bafff72 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -43,7 +43,9 @@
 	Opt_disable_roll_forward,
 	Opt_discard,
 	Opt_noheap,
+	Opt_user_xattr,
 	Opt_nouser_xattr,
+	Opt_acl,
 	Opt_noacl,
 	Opt_active_logs,
 	Opt_disable_ext_identify,
@@ -56,7 +58,9 @@
 	{Opt_disable_roll_forward, "disable_roll_forward"},
 	{Opt_discard, "discard"},
 	{Opt_noheap, "no_heap"},
+	{Opt_user_xattr, "user_xattr"},
 	{Opt_nouser_xattr, "nouser_xattr"},
+	{Opt_acl, "acl"},
 	{Opt_noacl, "noacl"},
 	{Opt_active_logs, "active_logs=%u"},
 	{Opt_disable_ext_identify, "disable_ext_identify"},
@@ -65,24 +69,40 @@
 };
 
 /* Sysfs support for f2fs */
+enum {
+	GC_THREAD,	/* struct f2fs_gc_thread */
+	SM_INFO,	/* struct f2fs_sm_info */
+};
+
 struct f2fs_attr {
 	struct attribute attr;
 	ssize_t (*show)(struct f2fs_attr *, struct f2fs_sb_info *, char *);
 	ssize_t (*store)(struct f2fs_attr *, struct f2fs_sb_info *,
 			 const char *, size_t);
+	int struct_type;
 	int offset;
 };
 
+static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type)
+{
+	if (struct_type == GC_THREAD)
+		return (unsigned char *)sbi->gc_thread;
+	else if (struct_type == SM_INFO)
+		return (unsigned char *)SM_I(sbi);
+	return NULL;
+}
+
 static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
 			struct f2fs_sb_info *sbi, char *buf)
 {
-	struct f2fs_gc_kthread *gc_kth = sbi->gc_thread;
+	unsigned char *ptr = NULL;
 	unsigned int *ui;
 
-	if (!gc_kth)
+	ptr = __struct_ptr(sbi, a->struct_type);
+	if (!ptr)
 		return -EINVAL;
 
-	ui = (unsigned int *)(((char *)gc_kth) + a->offset);
+	ui = (unsigned int *)(ptr + a->offset);
 
 	return snprintf(buf, PAGE_SIZE, "%u\n", *ui);
 }
@@ -91,15 +111,16 @@
 			struct f2fs_sb_info *sbi,
 			const char *buf, size_t count)
 {
-	struct f2fs_gc_kthread *gc_kth = sbi->gc_thread;
+	unsigned char *ptr;
 	unsigned long t;
 	unsigned int *ui;
 	ssize_t ret;
 
-	if (!gc_kth)
+	ptr = __struct_ptr(sbi, a->struct_type);
+	if (!ptr)
 		return -EINVAL;
 
-	ui = (unsigned int *)(((char *)gc_kth) + a->offset);
+	ui = (unsigned int *)(ptr + a->offset);
 
 	ret = kstrtoul(skip_spaces(buf), 0, &t);
 	if (ret < 0)
@@ -135,21 +156,25 @@
 	complete(&sbi->s_kobj_unregister);
 }
 
-#define F2FS_ATTR_OFFSET(_name, _mode, _show, _store, _elname) \
+#define F2FS_ATTR_OFFSET(_struct_type, _name, _mode, _show, _store, _offset) \
 static struct f2fs_attr f2fs_attr_##_name = {			\
 	.attr = {.name = __stringify(_name), .mode = _mode },	\
 	.show	= _show,					\
 	.store	= _store,					\
-	.offset = offsetof(struct f2fs_gc_kthread, _elname),	\
+	.struct_type = _struct_type,				\
+	.offset = _offset					\
 }
 
-#define F2FS_RW_ATTR(name, elname)	\
-	F2FS_ATTR_OFFSET(name, 0644, f2fs_sbi_show, f2fs_sbi_store, elname)
+#define F2FS_RW_ATTR(struct_type, struct_name, name, elname)	\
+	F2FS_ATTR_OFFSET(struct_type, name, 0644,		\
+		f2fs_sbi_show, f2fs_sbi_store,			\
+		offsetof(struct struct_name, elname))
 
-F2FS_RW_ATTR(gc_min_sleep_time, min_sleep_time);
-F2FS_RW_ATTR(gc_max_sleep_time, max_sleep_time);
-F2FS_RW_ATTR(gc_no_gc_sleep_time, no_gc_sleep_time);
-F2FS_RW_ATTR(gc_idle, gc_idle);
+F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_min_sleep_time, min_sleep_time);
+F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time);
+F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time);
+F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_idle, gc_idle);
+F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments);
 
 #define ATTR_LIST(name) (&f2fs_attr_##name.attr)
 static struct attribute *f2fs_attrs[] = {
@@ -157,6 +182,7 @@
 	ATTR_LIST(gc_max_sleep_time),
 	ATTR_LIST(gc_no_gc_sleep_time),
 	ATTR_LIST(gc_idle),
+	ATTR_LIST(reclaim_segments),
 	NULL,
 };
 
@@ -237,6 +263,9 @@
 			set_opt(sbi, NOHEAP);
 			break;
 #ifdef CONFIG_F2FS_FS_XATTR
+		case Opt_user_xattr:
+			set_opt(sbi, XATTR_USER);
+			break;
 		case Opt_nouser_xattr:
 			clear_opt(sbi, XATTR_USER);
 			break;
@@ -244,6 +273,10 @@
 			set_opt(sbi, INLINE_XATTR);
 			break;
 #else
+		case Opt_user_xattr:
+			f2fs_msg(sb, KERN_INFO,
+				"user_xattr options not supported");
+			break;
 		case Opt_nouser_xattr:
 			f2fs_msg(sb, KERN_INFO,
 				"nouser_xattr options not supported");
@@ -254,10 +287,16 @@
 			break;
 #endif
 #ifdef CONFIG_F2FS_FS_POSIX_ACL
+		case Opt_acl:
+			set_opt(sbi, POSIX_ACL);
+			break;
 		case Opt_noacl:
 			clear_opt(sbi, POSIX_ACL);
 			break;
 #else
+		case Opt_acl:
+			f2fs_msg(sb, KERN_INFO, "acl options not supported");
+			break;
 		case Opt_noacl:
 			f2fs_msg(sb, KERN_INFO, "noacl options not supported");
 			break;
@@ -355,7 +394,9 @@
 	f2fs_destroy_stats(sbi);
 	stop_gc_thread(sbi);
 
-	write_checkpoint(sbi, true);
+	/* We don't need to do checkpoint when it's clean */
+	if (sbi->s_dirty && get_pages(sbi, F2FS_DIRTY_NODES))
+		write_checkpoint(sbi, true);
 
 	iput(sbi->node_inode);
 	iput(sbi->meta_inode);
@@ -727,30 +768,47 @@
 		atomic_set(&sbi->nr_pages[i], 0);
 }
 
-static int validate_superblock(struct super_block *sb,
-		struct f2fs_super_block **raw_super,
-		struct buffer_head **raw_super_buf, sector_t block)
+/*
+ * Read f2fs raw super block.
+ * Because we have two copies of super block, so read the first one at first,
+ * if the first one is invalid, move to read the second one.
+ */
+static int read_raw_super_block(struct super_block *sb,
+			struct f2fs_super_block **raw_super,
+			struct buffer_head **raw_super_buf)
 {
-	const char *super = (block == 0 ? "first" : "second");
+	int block = 0;
 
-	/* read f2fs raw super block */
+retry:
 	*raw_super_buf = sb_bread(sb, block);
 	if (!*raw_super_buf) {
-		f2fs_msg(sb, KERN_ERR, "unable to read %s superblock",
-				super);
-		return -EIO;
+		f2fs_msg(sb, KERN_ERR, "Unable to read %dth superblock",
+				block + 1);
+		if (block == 0) {
+			block++;
+			goto retry;
+		} else {
+			return -EIO;
+		}
 	}
 
 	*raw_super = (struct f2fs_super_block *)
 		((char *)(*raw_super_buf)->b_data + F2FS_SUPER_OFFSET);
 
 	/* sanity checking of raw super */
-	if (!sanity_check_raw_super(sb, *raw_super))
-		return 0;
+	if (sanity_check_raw_super(sb, *raw_super)) {
+		brelse(*raw_super_buf);
+		f2fs_msg(sb, KERN_ERR, "Can't find a valid F2FS filesystem "
+				"in %dth superblock", block + 1);
+		if(block == 0) {
+			block++;
+			goto retry;
+		} else {
+			return -EINVAL;
+		}
+	}
 
-	f2fs_msg(sb, KERN_ERR, "Can't find a valid F2FS filesystem "
-				"in %s superblock", super);
-	return -EINVAL;
+	return 0;
 }
 
 static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
@@ -760,7 +818,6 @@
 	struct buffer_head *raw_super_buf;
 	struct inode *root;
 	long err = -EINVAL;
-	int i;
 
 	/* allocate memory for f2fs-specific super block info */
 	sbi = kzalloc(sizeof(struct f2fs_sb_info), GFP_KERNEL);
@@ -773,14 +830,10 @@
 		goto free_sbi;
 	}
 
-	err = validate_superblock(sb, &raw_super, &raw_super_buf, 0);
-	if (err) {
-		brelse(raw_super_buf);
-		/* check secondary superblock when primary failed */
-		err = validate_superblock(sb, &raw_super, &raw_super_buf, 1);
-		if (err)
-			goto free_sb_buf;
-	}
+	err = read_raw_super_block(sb, &raw_super, &raw_super_buf);
+	if (err)
+		goto free_sbi;
+
 	sb->s_fs_info = sbi;
 	/* init some FS parameters */
 	sbi->active_logs = NR_CURSEG_TYPE;
@@ -818,12 +871,12 @@
 	mutex_init(&sbi->gc_mutex);
 	mutex_init(&sbi->writepages);
 	mutex_init(&sbi->cp_mutex);
-	for (i = 0; i < NR_GLOBAL_LOCKS; i++)
-		mutex_init(&sbi->fs_lock[i]);
 	mutex_init(&sbi->node_write);
-	sbi->por_doing = 0;
+	sbi->por_doing = false;
 	spin_lock_init(&sbi->stat_lock);
 	init_rwsem(&sbi->bio_sem);
+	init_rwsem(&sbi->cp_rwsem);
+	init_waitqueue_head(&sbi->cp_wait);
 	init_sb_info(sbi);
 
 	/* get an inode for meta space */
@@ -922,12 +975,12 @@
 		/* After POR, we can run background GC thread.*/
 		err = start_gc_thread(sbi);
 		if (err)
-			goto fail;
+			goto free_gc;
 	}
 
 	err = f2fs_build_stats(sbi);
 	if (err)
-		goto fail;
+		goto free_gc;
 
 	if (f2fs_proc_root)
 		sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
@@ -953,6 +1006,12 @@
 
 	return 0;
 fail:
+	if (sbi->s_proc) {
+		remove_proc_entry("segment_info", sbi->s_proc);
+		remove_proc_entry(sb->s_id, f2fs_proc_root);
+	}
+	f2fs_destroy_stats(sbi);
+free_gc:
 	stop_gc_thread(sbi);
 free_root_inode:
 	dput(sb->s_root);
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index 1ac8a5f..aa7a3f1 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -154,6 +154,9 @@
 }
 
 #ifdef CONFIG_F2FS_FS_SECURITY
+static int __f2fs_setxattr(struct inode *inode, int name_index,
+			const char *name, const void *value, size_t value_len,
+			struct page *ipage);
 static int f2fs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
 		void *page)
 {
@@ -161,7 +164,7 @@
 	int err = 0;
 
 	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
-		err = f2fs_setxattr(inode, F2FS_XATTR_INDEX_SECURITY,
+		err = __f2fs_setxattr(inode, F2FS_XATTR_INDEX_SECURITY,
 				xattr->name, xattr->value,
 				xattr->value_len, (struct page *)page);
 		if (err < 0)
@@ -369,7 +372,7 @@
 			alloc_nid_failed(sbi, new_nid);
 			return PTR_ERR(xpage);
 		}
-		BUG_ON(new_nid);
+		f2fs_bug_on(new_nid);
 	} else {
 		struct dnode_of_data dn;
 		set_new_dnode(&dn, inode, NULL, NULL, new_nid);
@@ -469,16 +472,15 @@
 	return error;
 }
 
-int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
-			const void *value, size_t value_len, struct page *ipage)
+static int __f2fs_setxattr(struct inode *inode, int name_index,
+			const char *name, const void *value, size_t value_len,
+			struct page *ipage)
 {
-	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 	struct f2fs_inode_info *fi = F2FS_I(inode);
 	struct f2fs_xattr_entry *here, *last;
 	void *base_addr;
 	int found, newsize;
 	size_t name_len;
-	int ilock;
 	__u32 new_hsize;
 	int error = -ENOMEM;
 
@@ -493,10 +495,6 @@
 	if (name_len > F2FS_NAME_LEN || value_len > MAX_VALUE_LEN(inode))
 		return -ERANGE;
 
-	f2fs_balance_fs(sbi);
-
-	ilock = mutex_lock_op(sbi);
-
 	base_addr = read_all_xattrs(inode, ipage);
 	if (!base_addr)
 		goto exit;
@@ -522,7 +520,7 @@
 		 */
 		free = MIN_OFFSET(inode) - ((char *)last - (char *)base_addr);
 		if (found)
-			free = free - ENTRY_SIZE(here);
+			free = free + ENTRY_SIZE(here);
 
 		if (free < newsize) {
 			error = -ENOSPC;
@@ -578,7 +576,21 @@
 	else
 		update_inode_page(inode);
 exit:
-	mutex_unlock_op(sbi, ilock);
 	kzfree(base_addr);
 	return error;
 }
+
+int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
+			const void *value, size_t value_len, struct page *ipage)
+{
+	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+	int err;
+
+	f2fs_balance_fs(sbi);
+
+	f2fs_lock_op(sbi);
+	err = __f2fs_setxattr(inode, name_index, name, value, value_len, ipage);
+	f2fs_unlock_op(sbi);
+
+	return err;
+}
diff --git a/fs/file_table.c b/fs/file_table.c
index 23b6dca..5fff903 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -294,7 +294,7 @@
 	delayed_fput(NULL);
 }
 
-static DECLARE_WORK(delayed_fput_work, delayed_fput);
+static DECLARE_DELAYED_WORK(delayed_fput_work, delayed_fput);
 
 void fput(struct file *file)
 {
@@ -313,7 +313,7 @@
 		}
 
 		if (llist_add(&file->f_u.fu_llist, &delayed_fput_list))
-			schedule_work(&delayed_fput_work);
+			schedule_delayed_work(&delayed_fput_work, 1);
 	}
 }
 
diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c
index b2a86e3..29d7feb 100644
--- a/fs/fscache/cookie.c
+++ b/fs/fscache/cookie.c
@@ -58,15 +58,16 @@
 struct fscache_cookie *__fscache_acquire_cookie(
 	struct fscache_cookie *parent,
 	const struct fscache_cookie_def *def,
-	void *netfs_data)
+	void *netfs_data,
+	bool enable)
 {
 	struct fscache_cookie *cookie;
 
 	BUG_ON(!def);
 
-	_enter("{%s},{%s},%p",
+	_enter("{%s},{%s},%p,%u",
 	       parent ? (char *) parent->def->name : "<no-parent>",
-	       def->name, netfs_data);
+	       def->name, netfs_data, enable);
 
 	fscache_stat(&fscache_n_acquires);
 
@@ -106,7 +107,7 @@
 	cookie->def		= def;
 	cookie->parent		= parent;
 	cookie->netfs_data	= netfs_data;
-	cookie->flags		= 0;
+	cookie->flags		= (1 << FSCACHE_COOKIE_NO_DATA_YET);
 
 	/* radix tree insertion won't use the preallocation pool unless it's
 	 * told it may not wait */
@@ -124,16 +125,22 @@
 		break;
 	}
 
-	/* if the object is an index then we need do nothing more here - we
-	 * create indices on disk when we need them as an index may exist in
-	 * multiple caches */
-	if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) {
-		if (fscache_acquire_non_index_cookie(cookie) < 0) {
-			atomic_dec(&parent->n_children);
-			__fscache_cookie_put(cookie);
-			fscache_stat(&fscache_n_acquires_nobufs);
-			_leave(" = NULL");
-			return NULL;
+	if (enable) {
+		/* if the object is an index then we need do nothing more here
+		 * - we create indices on disk when we need them as an index
+		 * may exist in multiple caches */
+		if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) {
+			if (fscache_acquire_non_index_cookie(cookie) == 0) {
+				set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags);
+			} else {
+				atomic_dec(&parent->n_children);
+				__fscache_cookie_put(cookie);
+				fscache_stat(&fscache_n_acquires_nobufs);
+				_leave(" = NULL");
+				return NULL;
+			}
+		} else {
+			set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags);
 		}
 	}
 
@@ -144,6 +151,39 @@
 EXPORT_SYMBOL(__fscache_acquire_cookie);
 
 /*
+ * Enable a cookie to permit it to accept new operations.
+ */
+void __fscache_enable_cookie(struct fscache_cookie *cookie,
+			     bool (*can_enable)(void *data),
+			     void *data)
+{
+	_enter("%p", cookie);
+
+	wait_on_bit_lock(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK,
+			 fscache_wait_bit, TASK_UNINTERRUPTIBLE);
+
+	if (test_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags))
+		goto out_unlock;
+
+	if (can_enable && !can_enable(data)) {
+		/* The netfs decided it didn't want to enable after all */
+	} else if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) {
+		/* Wait for outstanding disablement to complete */
+		__fscache_wait_on_invalidate(cookie);
+
+		if (fscache_acquire_non_index_cookie(cookie) == 0)
+			set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags);
+	} else {
+		set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags);
+	}
+
+out_unlock:
+	clear_bit_unlock(FSCACHE_COOKIE_ENABLEMENT_LOCK, &cookie->flags);
+	wake_up_bit(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK);
+}
+EXPORT_SYMBOL(__fscache_enable_cookie);
+
+/*
  * acquire a non-index cookie
  * - this must make sure the index chain is instantiated and instantiate the
  *   object representation too
@@ -157,7 +197,7 @@
 
 	_enter("");
 
-	cookie->flags = 1 << FSCACHE_COOKIE_UNAVAILABLE;
+	set_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);
 
 	/* now we need to see whether the backing objects for this cookie yet
 	 * exist, if not there'll be nothing to search */
@@ -180,9 +220,7 @@
 
 	_debug("cache %s", cache->tag->name);
 
-	cookie->flags =
-		(1 << FSCACHE_COOKIE_LOOKING_UP) |
-		(1 << FSCACHE_COOKIE_NO_DATA_YET);
+	set_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags);
 
 	/* ask the cache to allocate objects for this cookie and its parent
 	 * chain */
@@ -398,7 +436,8 @@
 	if (!hlist_empty(&cookie->backing_objects)) {
 		spin_lock(&cookie->lock);
 
-		if (!hlist_empty(&cookie->backing_objects) &&
+		if (fscache_cookie_enabled(cookie) &&
+		    !hlist_empty(&cookie->backing_objects) &&
 		    !test_and_set_bit(FSCACHE_COOKIE_INVALIDATING,
 				      &cookie->flags)) {
 			object = hlist_entry(cookie->backing_objects.first,
@@ -452,10 +491,14 @@
 
 	spin_lock(&cookie->lock);
 
-	/* update the index entry on disk in each cache backing this cookie */
-	hlist_for_each_entry(object,
-			     &cookie->backing_objects, cookie_link) {
-		fscache_raise_event(object, FSCACHE_OBJECT_EV_UPDATE);
+	if (fscache_cookie_enabled(cookie)) {
+		/* update the index entry on disk in each cache backing this
+		 * cookie.
+		 */
+		hlist_for_each_entry(object,
+				     &cookie->backing_objects, cookie_link) {
+			fscache_raise_event(object, FSCACHE_OBJECT_EV_UPDATE);
+		}
 	}
 
 	spin_unlock(&cookie->lock);
@@ -464,15 +507,80 @@
 EXPORT_SYMBOL(__fscache_update_cookie);
 
 /*
+ * Disable a cookie to stop it from accepting new requests from the netfs.
+ */
+void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
+{
+	struct fscache_object *object;
+	bool awaken = false;
+
+	_enter("%p,%u", cookie, invalidate);
+
+	ASSERTCMP(atomic_read(&cookie->n_active), >, 0);
+
+	if (atomic_read(&cookie->n_children) != 0) {
+		printk(KERN_ERR "FS-Cache: Cookie '%s' still has children\n",
+		       cookie->def->name);
+		BUG();
+	}
+
+	wait_on_bit_lock(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK,
+			 fscache_wait_bit, TASK_UNINTERRUPTIBLE);
+	if (!test_and_clear_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags))
+		goto out_unlock_enable;
+
+	/* If the cookie is being invalidated, wait for that to complete first
+	 * so that we can reuse the flag.
+	 */
+	__fscache_wait_on_invalidate(cookie);
+
+	/* Dispose of the backing objects */
+	set_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags);
+
+	spin_lock(&cookie->lock);
+	if (!hlist_empty(&cookie->backing_objects)) {
+		hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) {
+			if (invalidate)
+				set_bit(FSCACHE_OBJECT_RETIRED, &object->flags);
+			fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
+		}
+	} else {
+		if (test_and_clear_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags))
+			awaken = true;
+	}
+	spin_unlock(&cookie->lock);
+	if (awaken)
+		wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING);
+
+	/* Wait for cessation of activity requiring access to the netfs (when
+	 * n_active reaches 0).  This makes sure outstanding reads and writes
+	 * have completed.
+	 */
+	if (!atomic_dec_and_test(&cookie->n_active))
+		wait_on_atomic_t(&cookie->n_active, fscache_wait_atomic_t,
+				 TASK_UNINTERRUPTIBLE);
+
+	/* Reset the cookie state if it wasn't relinquished */
+	if (!test_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) {
+		atomic_inc(&cookie->n_active);
+		set_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
+	}
+
+out_unlock_enable:
+	clear_bit_unlock(FSCACHE_COOKIE_ENABLEMENT_LOCK, &cookie->flags);
+	wake_up_bit(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK);
+	_leave("");
+}
+EXPORT_SYMBOL(__fscache_disable_cookie);
+
+/*
  * release a cookie back to the cache
  * - the object will be marked as recyclable on disk if retire is true
  * - all dependents of this cookie must have already been unregistered
  *   (indices/files/pages)
  */
-void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
+void __fscache_relinquish_cookie(struct fscache_cookie *cookie, bool retire)
 {
-	struct fscache_object *object;
-
 	fscache_stat(&fscache_n_relinquishes);
 	if (retire)
 		fscache_stat(&fscache_n_relinquishes_retire);
@@ -487,31 +595,10 @@
 	       cookie, cookie->def->name, cookie->netfs_data,
 	       atomic_read(&cookie->n_active), retire);
 
-	ASSERTCMP(atomic_read(&cookie->n_active), >, 0);
-
-	if (atomic_read(&cookie->n_children) != 0) {
-		printk(KERN_ERR "FS-Cache: Cookie '%s' still has children\n",
-		       cookie->def->name);
-		BUG();
-	}
-
 	/* No further netfs-accessing operations on this cookie permitted */
 	set_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags);
-	if (retire)
-		set_bit(FSCACHE_COOKIE_RETIRED, &cookie->flags);
 
-	spin_lock(&cookie->lock);
-	hlist_for_each_entry(object, &cookie->backing_objects, cookie_link) {
-		fscache_raise_event(object, FSCACHE_OBJECT_EV_KILL);
-	}
-	spin_unlock(&cookie->lock);
-
-	/* Wait for cessation of activity requiring access to the netfs (when
-	 * n_active reaches 0).
-	 */
-	if (!atomic_dec_and_test(&cookie->n_active))
-		wait_on_atomic_t(&cookie->n_active, fscache_wait_atomic_t,
-				 TASK_UNINTERRUPTIBLE);
+	__fscache_disable_cookie(cookie, retire);
 
 	/* Clear pointers back to the netfs */
 	cookie->netfs_data	= NULL;
@@ -568,6 +655,7 @@
 {
 	struct fscache_operation *op;
 	struct fscache_object *object;
+	bool wake_cookie = false;
 	int ret;
 
 	_enter("%p,", cookie);
@@ -591,7 +679,8 @@
 
 	spin_lock(&cookie->lock);
 
-	if (hlist_empty(&cookie->backing_objects))
+	if (!fscache_cookie_enabled(cookie) ||
+	    hlist_empty(&cookie->backing_objects))
 		goto inconsistent;
 	object = hlist_entry(cookie->backing_objects.first,
 			     struct fscache_object, cookie_link);
@@ -600,7 +689,7 @@
 
 	op->debug_id = atomic_inc_return(&fscache_op_debug_id);
 
-	atomic_inc(&cookie->n_active);
+	__fscache_use_cookie(cookie);
 	if (fscache_submit_op(object, op) < 0)
 		goto submit_failed;
 
@@ -622,9 +711,11 @@
 	return ret;
 
 submit_failed:
-	atomic_dec(&cookie->n_active);
+	wake_cookie = __fscache_unuse_cookie(cookie);
 inconsistent:
 	spin_unlock(&cookie->lock);
+	if (wake_cookie)
+		__fscache_wake_unused_cookie(cookie);
 	kfree(op);
 	_leave(" = -ESTALE");
 	return -ESTALE;
diff --git a/fs/fscache/fsdef.c b/fs/fscache/fsdef.c
index 10a2ade..5a117df 100644
--- a/fs/fscache/fsdef.c
+++ b/fs/fscache/fsdef.c
@@ -59,6 +59,7 @@
 	.lock		= __SPIN_LOCK_UNLOCKED(fscache_fsdef_index.lock),
 	.backing_objects = HLIST_HEAD_INIT,
 	.def		= &fscache_fsdef_index_def,
+	.flags		= 1 << FSCACHE_COOKIE_ENABLED,
 };
 EXPORT_SYMBOL(fscache_fsdef_index);
 
diff --git a/fs/fscache/netfs.c b/fs/fscache/netfs.c
index b1bb611..989f394 100644
--- a/fs/fscache/netfs.c
+++ b/fs/fscache/netfs.c
@@ -45,6 +45,7 @@
 	netfs->primary_index->def		= &fscache_fsdef_netfs_def;
 	netfs->primary_index->parent		= &fscache_fsdef_index;
 	netfs->primary_index->netfs_data	= netfs;
+	netfs->primary_index->flags		= 1 << FSCACHE_COOKIE_ENABLED;
 
 	atomic_inc(&netfs->primary_index->parent->usage);
 	atomic_inc(&netfs->primary_index->parent->n_children);
diff --git a/fs/fscache/object.c b/fs/fscache/object.c
index 86d75a6..dcb8216 100644
--- a/fs/fscache/object.c
+++ b/fs/fscache/object.c
@@ -495,6 +495,7 @@
 		 * returning ENODATA.
 		 */
 		set_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
+		clear_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);
 
 		_debug("wake up lookup %p", &cookie->flags);
 		clear_bit_unlock(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags);
@@ -527,6 +528,7 @@
 
 		/* We do (presumably) have data */
 		clear_bit_unlock(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
+		clear_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);
 
 		/* Allow write requests to begin stacking up and read requests
 		 * to begin shovelling data.
@@ -679,7 +681,8 @@
 	 */
 	spin_lock(&cookie->lock);
 	hlist_del_init(&object->cookie_link);
-	if (test_and_clear_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags))
+	if (hlist_empty(&cookie->backing_objects) &&
+	    test_and_clear_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags))
 		awaken = true;
 	spin_unlock(&cookie->lock);
 
@@ -927,7 +930,7 @@
 	 */
 	if (!fscache_use_cookie(object)) {
 		ASSERT(object->cookie->stores.rnode == NULL);
-		set_bit(FSCACHE_COOKIE_RETIRED, &cookie->flags);
+		set_bit(FSCACHE_OBJECT_RETIRED, &object->flags);
 		_leave(" [no cookie]");
 		return transit_to(KILL_OBJECT);
 	}
diff --git a/fs/fscache/page.c b/fs/fscache/page.c
index 73899c1..7f5c658 100644
--- a/fs/fscache/page.c
+++ b/fs/fscache/page.c
@@ -163,12 +163,10 @@
 
 	fscache_stat(&fscache_n_attr_changed_calls);
 
-	if (fscache_object_is_active(object) &&
-	    fscache_use_cookie(object)) {
+	if (fscache_object_is_active(object)) {
 		fscache_stat(&fscache_n_cop_attr_changed);
 		ret = object->cache->ops->attr_changed(object);
 		fscache_stat_d(&fscache_n_cop_attr_changed);
-		fscache_unuse_cookie(object);
 		if (ret < 0)
 			fscache_abort_object(object);
 	}
@@ -184,6 +182,7 @@
 {
 	struct fscache_operation *op;
 	struct fscache_object *object;
+	bool wake_cookie;
 
 	_enter("%p", cookie);
 
@@ -199,15 +198,19 @@
 	}
 
 	fscache_operation_init(op, fscache_attr_changed_op, NULL);
-	op->flags = FSCACHE_OP_ASYNC | (1 << FSCACHE_OP_EXCLUSIVE);
+	op->flags = FSCACHE_OP_ASYNC |
+		(1 << FSCACHE_OP_EXCLUSIVE) |
+		(1 << FSCACHE_OP_UNUSE_COOKIE);
 
 	spin_lock(&cookie->lock);
 
-	if (hlist_empty(&cookie->backing_objects))
+	if (!fscache_cookie_enabled(cookie) ||
+	    hlist_empty(&cookie->backing_objects))
 		goto nobufs;
 	object = hlist_entry(cookie->backing_objects.first,
 			     struct fscache_object, cookie_link);
 
+	__fscache_use_cookie(cookie);
 	if (fscache_submit_exclusive_op(object, op) < 0)
 		goto nobufs;
 	spin_unlock(&cookie->lock);
@@ -217,8 +220,11 @@
 	return 0;
 
 nobufs:
+	wake_cookie = __fscache_unuse_cookie(cookie);
 	spin_unlock(&cookie->lock);
 	kfree(op);
+	if (wake_cookie)
+		__fscache_wake_unused_cookie(cookie);
 	fscache_stat(&fscache_n_attr_changed_nobufs);
 	_leave(" = %d", -ENOBUFS);
 	return -ENOBUFS;
@@ -263,7 +269,6 @@
 	}
 
 	fscache_operation_init(&op->op, NULL, fscache_release_retrieval_op);
-	atomic_inc(&cookie->n_active);
 	op->op.flags	= FSCACHE_OP_MYTHREAD |
 		(1UL << FSCACHE_OP_WAITING) |
 		(1UL << FSCACHE_OP_UNUSE_COOKIE);
@@ -384,6 +389,7 @@
 {
 	struct fscache_retrieval *op;
 	struct fscache_object *object;
+	bool wake_cookie = false;
 	int ret;
 
 	_enter("%p,%p,,,", cookie, page);
@@ -405,7 +411,7 @@
 		return -ERESTARTSYS;
 
 	op = fscache_alloc_retrieval(cookie, page->mapping,
-				     end_io_func,context);
+				     end_io_func, context);
 	if (!op) {
 		_leave(" = -ENOMEM");
 		return -ENOMEM;
@@ -414,13 +420,15 @@
 
 	spin_lock(&cookie->lock);
 
-	if (hlist_empty(&cookie->backing_objects))
+	if (!fscache_cookie_enabled(cookie) ||
+	    hlist_empty(&cookie->backing_objects))
 		goto nobufs_unlock;
 	object = hlist_entry(cookie->backing_objects.first,
 			     struct fscache_object, cookie_link);
 
 	ASSERT(test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags));
 
+	__fscache_use_cookie(cookie);
 	atomic_inc(&object->n_reads);
 	__set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags);
 
@@ -475,9 +483,11 @@
 
 nobufs_unlock_dec:
 	atomic_dec(&object->n_reads);
+	wake_cookie = __fscache_unuse_cookie(cookie);
 nobufs_unlock:
 	spin_unlock(&cookie->lock);
-	atomic_dec(&cookie->n_active);
+	if (wake_cookie)
+		__fscache_wake_unused_cookie(cookie);
 	kfree(op);
 nobufs:
 	fscache_stat(&fscache_n_retrievals_nobufs);
@@ -514,6 +524,7 @@
 {
 	struct fscache_retrieval *op;
 	struct fscache_object *object;
+	bool wake_cookie = false;
 	int ret;
 
 	_enter("%p,,%d,,,", cookie, *nr_pages);
@@ -542,11 +553,13 @@
 
 	spin_lock(&cookie->lock);
 
-	if (hlist_empty(&cookie->backing_objects))
+	if (!fscache_cookie_enabled(cookie) ||
+	    hlist_empty(&cookie->backing_objects))
 		goto nobufs_unlock;
 	object = hlist_entry(cookie->backing_objects.first,
 			     struct fscache_object, cookie_link);
 
+	__fscache_use_cookie(cookie);
 	atomic_inc(&object->n_reads);
 	__set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags);
 
@@ -601,10 +614,12 @@
 
 nobufs_unlock_dec:
 	atomic_dec(&object->n_reads);
+	wake_cookie = __fscache_unuse_cookie(cookie);
 nobufs_unlock:
 	spin_unlock(&cookie->lock);
-	atomic_dec(&cookie->n_active);
 	kfree(op);
+	if (wake_cookie)
+		__fscache_wake_unused_cookie(cookie);
 nobufs:
 	fscache_stat(&fscache_n_retrievals_nobufs);
 	_leave(" = -ENOBUFS");
@@ -626,6 +641,7 @@
 {
 	struct fscache_retrieval *op;
 	struct fscache_object *object;
+	bool wake_cookie = false;
 	int ret;
 
 	_enter("%p,%p,,,", cookie, page);
@@ -653,13 +669,15 @@
 
 	spin_lock(&cookie->lock);
 
-	if (hlist_empty(&cookie->backing_objects))
+	if (!fscache_cookie_enabled(cookie) ||
+	    hlist_empty(&cookie->backing_objects))
 		goto nobufs_unlock;
 	object = hlist_entry(cookie->backing_objects.first,
 			     struct fscache_object, cookie_link);
 
+	__fscache_use_cookie(cookie);
 	if (fscache_submit_op(object, &op->op) < 0)
-		goto nobufs_unlock;
+		goto nobufs_unlock_dec;
 	spin_unlock(&cookie->lock);
 
 	fscache_stat(&fscache_n_alloc_ops);
@@ -689,10 +707,13 @@
 	_leave(" = %d", ret);
 	return ret;
 
+nobufs_unlock_dec:
+	wake_cookie = __fscache_unuse_cookie(cookie);
 nobufs_unlock:
 	spin_unlock(&cookie->lock);
-	atomic_dec(&cookie->n_active);
 	kfree(op);
+	if (wake_cookie)
+		__fscache_wake_unused_cookie(cookie);
 nobufs:
 	fscache_stat(&fscache_n_allocs_nobufs);
 	_leave(" = -ENOBUFS");
@@ -889,6 +910,7 @@
 {
 	struct fscache_storage *op;
 	struct fscache_object *object;
+	bool wake_cookie = false;
 	int ret;
 
 	_enter("%p,%x,", cookie, (u32) page->flags);
@@ -920,7 +942,8 @@
 	ret = -ENOBUFS;
 	spin_lock(&cookie->lock);
 
-	if (hlist_empty(&cookie->backing_objects))
+	if (!fscache_cookie_enabled(cookie) ||
+	    hlist_empty(&cookie->backing_objects))
 		goto nobufs;
 	object = hlist_entry(cookie->backing_objects.first,
 			     struct fscache_object, cookie_link);
@@ -957,7 +980,7 @@
 	op->op.debug_id	= atomic_inc_return(&fscache_op_debug_id);
 	op->store_limit = object->store_limit;
 
-	atomic_inc(&cookie->n_active);
+	__fscache_use_cookie(cookie);
 	if (fscache_submit_op(object, &op->op) < 0)
 		goto submit_failed;
 
@@ -984,10 +1007,10 @@
 	return 0;
 
 submit_failed:
-	atomic_dec(&cookie->n_active);
 	spin_lock(&cookie->stores_lock);
 	radix_tree_delete(&cookie->stores, page->index);
 	spin_unlock(&cookie->stores_lock);
+	wake_cookie = __fscache_unuse_cookie(cookie);
 	page_cache_release(page);
 	ret = -ENOBUFS;
 	goto nobufs;
@@ -999,6 +1022,8 @@
 	spin_unlock(&cookie->lock);
 	radix_tree_preload_end();
 	kfree(op);
+	if (wake_cookie)
+		__fscache_wake_unused_cookie(cookie);
 	fscache_stat(&fscache_n_stores_nobufs);
 	_leave(" = -ENOBUFS");
 	return -ENOBUFS;
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index 8ca88d7..b96a49b 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -589,11 +589,14 @@
 ATTRIBUTE_GROUPS(cuse_class_dev);
 
 static struct miscdevice cuse_miscdev = {
-	.minor		= MISC_DYNAMIC_MINOR,
+	.minor		= CUSE_MINOR,
 	.name		= "cuse",
 	.fops		= &cuse_channel_fops,
 };
 
+MODULE_ALIAS_MISCDEV(CUSE_MINOR);
+MODULE_ALIAS("devname:cuse");
+
 static int __init cuse_init(void)
 {
 	int i, rc;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 4598345..7e70506 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -334,7 +334,8 @@
 
 		BUG_ON(req->inode != inode);
 		curr_index = req->misc.write.in.offset >> PAGE_CACHE_SHIFT;
-		if (curr_index == index) {
+		if (curr_index <= index &&
+		    index < curr_index + req->num_pages) {
 			found = true;
 			break;
 		}
@@ -1409,8 +1410,13 @@
 
 static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req)
 {
-	__free_page(req->pages[0]);
-	fuse_file_put(req->ff, false);
+	int i;
+
+	for (i = 0; i < req->num_pages; i++)
+		__free_page(req->pages[i]);
+
+	if (req->ff)
+		fuse_file_put(req->ff, false);
 }
 
 static void fuse_writepage_finish(struct fuse_conn *fc, struct fuse_req *req)
@@ -1418,30 +1424,34 @@
 	struct inode *inode = req->inode;
 	struct fuse_inode *fi = get_fuse_inode(inode);
 	struct backing_dev_info *bdi = inode->i_mapping->backing_dev_info;
+	int i;
 
 	list_del(&req->writepages_entry);
-	dec_bdi_stat(bdi, BDI_WRITEBACK);
-	dec_zone_page_state(req->pages[0], NR_WRITEBACK_TEMP);
-	bdi_writeout_inc(bdi);
+	for (i = 0; i < req->num_pages; i++) {
+		dec_bdi_stat(bdi, BDI_WRITEBACK);
+		dec_zone_page_state(req->pages[i], NR_WRITEBACK_TEMP);
+		bdi_writeout_inc(bdi);
+	}
 	wake_up(&fi->page_waitq);
 }
 
 /* Called under fc->lock, may release and reacquire it */
-static void fuse_send_writepage(struct fuse_conn *fc, struct fuse_req *req)
+static void fuse_send_writepage(struct fuse_conn *fc, struct fuse_req *req,
+				loff_t size)
 __releases(fc->lock)
 __acquires(fc->lock)
 {
 	struct fuse_inode *fi = get_fuse_inode(req->inode);
-	loff_t size = i_size_read(req->inode);
 	struct fuse_write_in *inarg = &req->misc.write.in;
+	__u64 data_size = req->num_pages * PAGE_CACHE_SIZE;
 
 	if (!fc->connected)
 		goto out_free;
 
-	if (inarg->offset + PAGE_CACHE_SIZE <= size) {
-		inarg->size = PAGE_CACHE_SIZE;
+	if (inarg->offset + data_size <= size) {
+		inarg->size = data_size;
 	} else if (inarg->offset < size) {
-		inarg->size = size & (PAGE_CACHE_SIZE - 1);
+		inarg->size = size - inarg->offset;
 	} else {
 		/* Got truncated off completely */
 		goto out_free;
@@ -1472,12 +1482,13 @@
 {
 	struct fuse_conn *fc = get_fuse_conn(inode);
 	struct fuse_inode *fi = get_fuse_inode(inode);
+	size_t crop = i_size_read(inode);
 	struct fuse_req *req;
 
 	while (fi->writectr >= 0 && !list_empty(&fi->queued_writes)) {
 		req = list_entry(fi->queued_writes.next, struct fuse_req, list);
 		list_del_init(&req->list);
-		fuse_send_writepage(fc, req);
+		fuse_send_writepage(fc, req, crop);
 	}
 }
 
@@ -1488,12 +1499,62 @@
 
 	mapping_set_error(inode->i_mapping, req->out.h.error);
 	spin_lock(&fc->lock);
+	while (req->misc.write.next) {
+		struct fuse_conn *fc = get_fuse_conn(inode);
+		struct fuse_write_in *inarg = &req->misc.write.in;
+		struct fuse_req *next = req->misc.write.next;
+		req->misc.write.next = next->misc.write.next;
+		next->misc.write.next = NULL;
+		next->ff = fuse_file_get(req->ff);
+		list_add(&next->writepages_entry, &fi->writepages);
+
+		/*
+		 * Skip fuse_flush_writepages() to make it easy to crop requests
+		 * based on primary request size.
+		 *
+		 * 1st case (trivial): there are no concurrent activities using
+		 * fuse_set/release_nowrite.  Then we're on safe side because
+		 * fuse_flush_writepages() would call fuse_send_writepage()
+		 * anyway.
+		 *
+		 * 2nd case: someone called fuse_set_nowrite and it is waiting
+		 * now for completion of all in-flight requests.  This happens
+		 * rarely and no more than once per page, so this should be
+		 * okay.
+		 *
+		 * 3rd case: someone (e.g. fuse_do_setattr()) is in the middle
+		 * of fuse_set_nowrite..fuse_release_nowrite section.  The fact
+		 * that fuse_set_nowrite returned implies that all in-flight
+		 * requests were completed along with all of their secondary
+		 * requests.  Further primary requests are blocked by negative
+		 * writectr.  Hence there cannot be any in-flight requests and
+		 * no invocations of fuse_writepage_end() while we're in
+		 * fuse_set_nowrite..fuse_release_nowrite section.
+		 */
+		fuse_send_writepage(fc, next, inarg->offset + inarg->size);
+	}
 	fi->writectr--;
 	fuse_writepage_finish(fc, req);
 	spin_unlock(&fc->lock);
 	fuse_writepage_free(fc, req);
 }
 
+static struct fuse_file *fuse_write_file_get(struct fuse_conn *fc,
+					     struct fuse_inode *fi)
+{
+	struct fuse_file *ff = NULL;
+
+	spin_lock(&fc->lock);
+	if (!WARN_ON(list_empty(&fi->write_files))) {
+		ff = list_entry(fi->write_files.next, struct fuse_file,
+				write_entry);
+		fuse_file_get(ff);
+	}
+	spin_unlock(&fc->lock);
+
+	return ff;
+}
+
 static int fuse_writepage_locked(struct page *page)
 {
 	struct address_space *mapping = page->mapping;
@@ -1501,8 +1562,8 @@
 	struct fuse_conn *fc = get_fuse_conn(inode);
 	struct fuse_inode *fi = get_fuse_inode(inode);
 	struct fuse_req *req;
-	struct fuse_file *ff;
 	struct page *tmp_page;
+	int error = -ENOMEM;
 
 	set_page_writeback(page);
 
@@ -1515,16 +1576,16 @@
 	if (!tmp_page)
 		goto err_free;
 
-	spin_lock(&fc->lock);
-	BUG_ON(list_empty(&fi->write_files));
-	ff = list_entry(fi->write_files.next, struct fuse_file, write_entry);
-	req->ff = fuse_file_get(ff);
-	spin_unlock(&fc->lock);
+	error = -EIO;
+	req->ff = fuse_write_file_get(fc, fi);
+	if (!req->ff)
+		goto err_free;
 
-	fuse_write_fill(req, ff, page_offset(page), 0);
+	fuse_write_fill(req, req->ff, page_offset(page), 0);
 
 	copy_highpage(tmp_page, page);
 	req->misc.write.in.write_flags |= FUSE_WRITE_CACHE;
+	req->misc.write.next = NULL;
 	req->in.argpages = 1;
 	req->num_pages = 1;
 	req->pages[0] = tmp_page;
@@ -1550,19 +1611,263 @@
 	fuse_request_free(req);
 err:
 	end_page_writeback(page);
-	return -ENOMEM;
+	return error;
 }
 
 static int fuse_writepage(struct page *page, struct writeback_control *wbc)
 {
 	int err;
 
+	if (fuse_page_is_writeback(page->mapping->host, page->index)) {
+		/*
+		 * ->writepages() should be called for sync() and friends.  We
+		 * should only get here on direct reclaim and then we are
+		 * allowed to skip a page which is already in flight
+		 */
+		WARN_ON(wbc->sync_mode == WB_SYNC_ALL);
+
+		redirty_page_for_writepage(wbc, page);
+		return 0;
+	}
+
 	err = fuse_writepage_locked(page);
 	unlock_page(page);
 
 	return err;
 }
 
+struct fuse_fill_wb_data {
+	struct fuse_req *req;
+	struct fuse_file *ff;
+	struct inode *inode;
+	struct page **orig_pages;
+};
+
+static void fuse_writepages_send(struct fuse_fill_wb_data *data)
+{
+	struct fuse_req *req = data->req;
+	struct inode *inode = data->inode;
+	struct fuse_conn *fc = get_fuse_conn(inode);
+	struct fuse_inode *fi = get_fuse_inode(inode);
+	int num_pages = req->num_pages;
+	int i;
+
+	req->ff = fuse_file_get(data->ff);
+	spin_lock(&fc->lock);
+	list_add_tail(&req->list, &fi->queued_writes);
+	fuse_flush_writepages(inode);
+	spin_unlock(&fc->lock);
+
+	for (i = 0; i < num_pages; i++)
+		end_page_writeback(data->orig_pages[i]);
+}
+
+static bool fuse_writepage_in_flight(struct fuse_req *new_req,
+				     struct page *page)
+{
+	struct fuse_conn *fc = get_fuse_conn(new_req->inode);
+	struct fuse_inode *fi = get_fuse_inode(new_req->inode);
+	struct fuse_req *tmp;
+	struct fuse_req *old_req;
+	bool found = false;
+	pgoff_t curr_index;
+
+	BUG_ON(new_req->num_pages != 0);
+
+	spin_lock(&fc->lock);
+	list_del(&new_req->writepages_entry);
+	list_for_each_entry(old_req, &fi->writepages, writepages_entry) {
+		BUG_ON(old_req->inode != new_req->inode);
+		curr_index = old_req->misc.write.in.offset >> PAGE_CACHE_SHIFT;
+		if (curr_index <= page->index &&
+		    page->index < curr_index + old_req->num_pages) {
+			found = true;
+			break;
+		}
+	}
+	if (!found) {
+		list_add(&new_req->writepages_entry, &fi->writepages);
+		goto out_unlock;
+	}
+
+	new_req->num_pages = 1;
+	for (tmp = old_req; tmp != NULL; tmp = tmp->misc.write.next) {
+		BUG_ON(tmp->inode != new_req->inode);
+		curr_index = tmp->misc.write.in.offset >> PAGE_CACHE_SHIFT;
+		if (tmp->num_pages == 1 &&
+		    curr_index == page->index) {
+			old_req = tmp;
+		}
+	}
+
+	if (old_req->num_pages == 1 && (old_req->state == FUSE_REQ_INIT ||
+					old_req->state == FUSE_REQ_PENDING)) {
+		struct backing_dev_info *bdi = page->mapping->backing_dev_info;
+
+		copy_highpage(old_req->pages[0], page);
+		spin_unlock(&fc->lock);
+
+		dec_bdi_stat(bdi, BDI_WRITEBACK);
+		dec_zone_page_state(page, NR_WRITEBACK_TEMP);
+		bdi_writeout_inc(bdi);
+		fuse_writepage_free(fc, new_req);
+		fuse_request_free(new_req);
+		goto out;
+	} else {
+		new_req->misc.write.next = old_req->misc.write.next;
+		old_req->misc.write.next = new_req;
+	}
+out_unlock:
+	spin_unlock(&fc->lock);
+out:
+	return found;
+}
+
+static int fuse_writepages_fill(struct page *page,
+		struct writeback_control *wbc, void *_data)
+{
+	struct fuse_fill_wb_data *data = _data;
+	struct fuse_req *req = data->req;
+	struct inode *inode = data->inode;
+	struct fuse_conn *fc = get_fuse_conn(inode);
+	struct page *tmp_page;
+	bool is_writeback;
+	int err;
+
+	if (!data->ff) {
+		err = -EIO;
+		data->ff = fuse_write_file_get(fc, get_fuse_inode(inode));
+		if (!data->ff)
+			goto out_unlock;
+	}
+
+	/*
+	 * Being under writeback is unlikely but possible.  For example direct
+	 * read to an mmaped fuse file will set the page dirty twice; once when
+	 * the pages are faulted with get_user_pages(), and then after the read
+	 * completed.
+	 */
+	is_writeback = fuse_page_is_writeback(inode, page->index);
+
+	if (req && req->num_pages &&
+	    (is_writeback || req->num_pages == FUSE_MAX_PAGES_PER_REQ ||
+	     (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_write ||
+	     data->orig_pages[req->num_pages - 1]->index + 1 != page->index)) {
+		fuse_writepages_send(data);
+		data->req = NULL;
+	}
+	err = -ENOMEM;
+	tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
+	if (!tmp_page)
+		goto out_unlock;
+
+	/*
+	 * The page must not be redirtied until the writeout is completed
+	 * (i.e. userspace has sent a reply to the write request).  Otherwise
+	 * there could be more than one temporary page instance for each real
+	 * page.
+	 *
+	 * This is ensured by holding the page lock in page_mkwrite() while
+	 * checking fuse_page_is_writeback().  We already hold the page lock
+	 * since clear_page_dirty_for_io() and keep it held until we add the
+	 * request to the fi->writepages list and increment req->num_pages.
+	 * After this fuse_page_is_writeback() will indicate that the page is
+	 * under writeback, so we can release the page lock.
+	 */
+	if (data->req == NULL) {
+		struct fuse_inode *fi = get_fuse_inode(inode);
+
+		err = -ENOMEM;
+		req = fuse_request_alloc_nofs(FUSE_MAX_PAGES_PER_REQ);
+		if (!req) {
+			__free_page(tmp_page);
+			goto out_unlock;
+		}
+
+		fuse_write_fill(req, data->ff, page_offset(page), 0);
+		req->misc.write.in.write_flags |= FUSE_WRITE_CACHE;
+		req->misc.write.next = NULL;
+		req->in.argpages = 1;
+		req->background = 1;
+		req->num_pages = 0;
+		req->end = fuse_writepage_end;
+		req->inode = inode;
+
+		spin_lock(&fc->lock);
+		list_add(&req->writepages_entry, &fi->writepages);
+		spin_unlock(&fc->lock);
+
+		data->req = req;
+	}
+	set_page_writeback(page);
+
+	copy_highpage(tmp_page, page);
+	req->pages[req->num_pages] = tmp_page;
+	req->page_descs[req->num_pages].offset = 0;
+	req->page_descs[req->num_pages].length = PAGE_SIZE;
+
+	inc_bdi_stat(page->mapping->backing_dev_info, BDI_WRITEBACK);
+	inc_zone_page_state(tmp_page, NR_WRITEBACK_TEMP);
+
+	err = 0;
+	if (is_writeback && fuse_writepage_in_flight(req, page)) {
+		end_page_writeback(page);
+		data->req = NULL;
+		goto out_unlock;
+	}
+	data->orig_pages[req->num_pages] = page;
+
+	/*
+	 * Protected by fc->lock against concurrent access by
+	 * fuse_page_is_writeback().
+	 */
+	spin_lock(&fc->lock);
+	req->num_pages++;
+	spin_unlock(&fc->lock);
+
+out_unlock:
+	unlock_page(page);
+
+	return err;
+}
+
+static int fuse_writepages(struct address_space *mapping,
+			   struct writeback_control *wbc)
+{
+	struct inode *inode = mapping->host;
+	struct fuse_fill_wb_data data;
+	int err;
+
+	err = -EIO;
+	if (is_bad_inode(inode))
+		goto out;
+
+	data.inode = inode;
+	data.req = NULL;
+	data.ff = NULL;
+
+	err = -ENOMEM;
+	data.orig_pages = kzalloc(sizeof(struct page *) *
+				  FUSE_MAX_PAGES_PER_REQ,
+				  GFP_NOFS);
+	if (!data.orig_pages)
+		goto out;
+
+	err = write_cache_pages(mapping, wbc, fuse_writepages_fill, &data);
+	if (data.req) {
+		/* Ignore errors if we can write at least one page */
+		BUG_ON(!data.req->num_pages);
+		fuse_writepages_send(&data);
+		err = 0;
+	}
+	if (data.ff)
+		fuse_file_put(data.ff, false);
+
+	kfree(data.orig_pages);
+out:
+	return err;
+}
+
 static int fuse_launder_page(struct page *page)
 {
 	int err = 0;
@@ -1602,14 +1907,17 @@
 static int fuse_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	struct page *page = vmf->page;
-	/*
-	 * Don't use page->mapping as it may become NULL from a
-	 * concurrent truncate.
-	 */
-	struct inode *inode = vma->vm_file->f_mapping->host;
+	struct inode *inode = file_inode(vma->vm_file);
+
+	file_update_time(vma->vm_file);
+	lock_page(page);
+	if (page->mapping != inode->i_mapping) {
+		unlock_page(page);
+		return VM_FAULT_NOPAGE;
+	}
 
 	fuse_wait_on_page_writeback(inode, page->index);
-	return 0;
+	return VM_FAULT_LOCKED;
 }
 
 static const struct vm_operations_struct fuse_file_vm_ops = {
@@ -2581,6 +2889,7 @@
 static const struct address_space_operations fuse_file_aops  = {
 	.readpage	= fuse_readpage,
 	.writepage	= fuse_writepage,
+	.writepages	= fuse_writepages,
 	.launder_page	= fuse_launder_page,
 	.readpages	= fuse_readpages,
 	.set_page_dirty	= __set_page_dirty_nobuffers,
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 4715674..7d27309 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -321,6 +321,7 @@
 		struct {
 			struct fuse_write_in in;
 			struct fuse_write_out out;
+			struct fuse_req *next;
 		} write;
 		struct fuse_notify_retrieve_in retrieve_in;
 		struct fuse_lk_in lk_in;
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 1f7d805..b7fc035 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -611,12 +611,14 @@
 		gfs2_write_calc_reserv(ip, len, &data_blocks, &ind_blocks);
 
 	if (alloc_required) {
+		struct gfs2_alloc_parms ap = { .aflags = 0, };
 		error = gfs2_quota_lock_check(ip);
 		if (error)
 			goto out_unlock;
 
 		requested = data_blocks + ind_blocks;
-		error = gfs2_inplace_reserve(ip, requested, 0);
+		ap.target = requested;
+		error = gfs2_inplace_reserve(ip, &ap);
 		if (error)
 			goto out_qunlock;
 	}
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 62a65fc..fe0500c 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -1216,6 +1216,7 @@
 {
 	struct gfs2_inode *ip = GFS2_I(inode);
 	struct gfs2_sbd *sdp = GFS2_SB(inode);
+	struct gfs2_alloc_parms ap = { .target = 1, };
 	struct buffer_head *dibh;
 	int error;
 	int unstuff = 0;
@@ -1226,7 +1227,7 @@
 		if (error)
 			return error;
 
-		error = gfs2_inplace_reserve(ip, 1, 0);
+		error = gfs2_inplace_reserve(ip, &ap);
 		if (error)
 			goto do_grow_qunlock;
 		unstuff = 1;
@@ -1279,6 +1280,7 @@
 
 int gfs2_setattr_size(struct inode *inode, u64 newsize)
 {
+	struct gfs2_inode *ip = GFS2_I(inode);
 	int ret;
 	u64 oldsize;
 
@@ -1294,7 +1296,7 @@
 
 	inode_dio_wait(inode);
 
-	ret = gfs2_rs_alloc(GFS2_I(inode));
+	ret = gfs2_rs_alloc(ip);
 	if (ret)
 		goto out;
 
@@ -1304,6 +1306,7 @@
 		goto out;
 	}
 
+	gfs2_rs_deltree(ip->i_res);
 	ret = do_shrink(inode, oldsize, newsize);
 out:
 	put_write_access(inode);
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 0621b46..efc078f 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -383,6 +383,7 @@
 	struct inode *inode = file_inode(vma->vm_file);
 	struct gfs2_inode *ip = GFS2_I(inode);
 	struct gfs2_sbd *sdp = GFS2_SB(inode);
+	struct gfs2_alloc_parms ap = { .aflags = 0, };
 	unsigned long last_index;
 	u64 pos = page->index << PAGE_CACHE_SHIFT;
 	unsigned int data_blocks, ind_blocks, rblocks;
@@ -430,7 +431,8 @@
 	if (ret)
 		goto out_unlock;
 	gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, &data_blocks, &ind_blocks);
-	ret = gfs2_inplace_reserve(ip, data_blocks + ind_blocks, 0);
+	ap.target = data_blocks + ind_blocks;
+	ret = gfs2_inplace_reserve(ip, &ap);
 	if (ret)
 		goto out_quota_unlock;
 
@@ -620,7 +622,7 @@
 	if (!(file->f_mode & FMODE_WRITE))
 		return 0;
 
-	gfs2_rs_delete(ip);
+	gfs2_rs_delete(ip, &inode->i_writecount);
 	return 0;
 }
 
@@ -800,6 +802,7 @@
 	struct inode *inode = file_inode(file);
 	struct gfs2_sbd *sdp = GFS2_SB(inode);
 	struct gfs2_inode *ip = GFS2_I(inode);
+	struct gfs2_alloc_parms ap = { .aflags = 0, };
 	unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
 	loff_t bytes, max_bytes;
 	int error;
@@ -850,7 +853,8 @@
 retry:
 		gfs2_write_calc_reserv(ip, bytes, &data_blocks, &ind_blocks);
 
-		error = gfs2_inplace_reserve(ip, data_blocks + ind_blocks, 0);
+		ap.target = data_blocks + ind_blocks;
+		error = gfs2_inplace_reserve(ip, &ap);
 		if (error) {
 			if (error == -ENOSPC && bytes > sdp->sd_sb.sb_bsize) {
 				bytes >>= 1;
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index c2f41b4..e66a800 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -31,6 +31,7 @@
 #include <linux/bit_spinlock.h>
 #include <linux/percpu.h>
 #include <linux/list_sort.h>
+#include <linux/lockref.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -129,10 +130,10 @@
  *
  */
 
-void gfs2_glock_hold(struct gfs2_glock *gl)
+static void gfs2_glock_hold(struct gfs2_glock *gl)
 {
-	GLOCK_BUG_ON(gl, atomic_read(&gl->gl_ref) == 0);
-	atomic_inc(&gl->gl_ref);
+	GLOCK_BUG_ON(gl, __lockref_is_dead(&gl->gl_lockref));
+	lockref_get(&gl->gl_lockref);
 }
 
 /**
@@ -187,20 +188,6 @@
 }
 
 /**
- * gfs2_glock_put_nolock() - Decrement reference count on glock
- * @gl: The glock to put
- *
- * This function should only be used if the caller has its own reference
- * to the glock, in addition to the one it is dropping.
- */
-
-void gfs2_glock_put_nolock(struct gfs2_glock *gl)
-{
-	if (atomic_dec_and_test(&gl->gl_ref))
-		GLOCK_BUG_ON(gl, 1);
-}
-
-/**
  * gfs2_glock_put() - Decrement reference count on glock
  * @gl: The glock to put
  *
@@ -211,17 +198,22 @@
 	struct gfs2_sbd *sdp = gl->gl_sbd;
 	struct address_space *mapping = gfs2_glock2aspace(gl);
 
-	if (atomic_dec_and_lock(&gl->gl_ref, &lru_lock)) {
-		__gfs2_glock_remove_from_lru(gl);
-		spin_unlock(&lru_lock);
-		spin_lock_bucket(gl->gl_hash);
-		hlist_bl_del_rcu(&gl->gl_list);
-		spin_unlock_bucket(gl->gl_hash);
-		GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders));
-		GLOCK_BUG_ON(gl, mapping && mapping->nrpages);
-		trace_gfs2_glock_put(gl);
-		sdp->sd_lockstruct.ls_ops->lm_put_lock(gl);
-	}
+	if (lockref_put_or_lock(&gl->gl_lockref))
+		return;
+
+	lockref_mark_dead(&gl->gl_lockref);
+
+	spin_lock(&lru_lock);
+	__gfs2_glock_remove_from_lru(gl);
+	spin_unlock(&lru_lock);
+	spin_unlock(&gl->gl_lockref.lock);
+	spin_lock_bucket(gl->gl_hash);
+	hlist_bl_del_rcu(&gl->gl_list);
+	spin_unlock_bucket(gl->gl_hash);
+	GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders));
+	GLOCK_BUG_ON(gl, mapping && mapping->nrpages);
+	trace_gfs2_glock_put(gl);
+	sdp->sd_lockstruct.ls_ops->lm_put_lock(gl);
 }
 
 /**
@@ -244,7 +236,7 @@
 			continue;
 		if (gl->gl_sbd != sdp)
 			continue;
-		if (atomic_inc_not_zero(&gl->gl_ref))
+		if (lockref_get_not_dead(&gl->gl_lockref))
 			return gl;
 	}
 
@@ -396,10 +388,11 @@
 	held2 = (new_state != LM_ST_UNLOCKED);
 
 	if (held1 != held2) {
+		GLOCK_BUG_ON(gl, __lockref_is_dead(&gl->gl_lockref));
 		if (held2)
-			gfs2_glock_hold(gl);
+			gl->gl_lockref.count++;
 		else
-			gfs2_glock_put_nolock(gl);
+			gl->gl_lockref.count--;
 	}
 	if (held1 && held2 && list_empty(&gl->gl_holders))
 		clear_bit(GLF_QUEUED, &gl->gl_flags);
@@ -626,9 +619,9 @@
 out_sched:
 	clear_bit(GLF_LOCK, &gl->gl_flags);
 	smp_mb__after_clear_bit();
-	gfs2_glock_hold(gl);
+	gl->gl_lockref.count++;
 	if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
-		gfs2_glock_put_nolock(gl);
+		gl->gl_lockref.count--;
 	return;
 
 out_unlock:
@@ -754,7 +747,7 @@
 	gl->gl_sbd = sdp;
 	gl->gl_flags = 0;
 	gl->gl_name = name;
-	atomic_set(&gl->gl_ref, 1);
+	gl->gl_lockref.count = 1;
 	gl->gl_state = LM_ST_UNLOCKED;
 	gl->gl_target = LM_ST_UNLOCKED;
 	gl->gl_demote_state = LM_ST_EXCLUSIVE;
@@ -1356,10 +1349,10 @@
 		}
 	}
 
-	spin_unlock(&gl->gl_spin);
+	gl->gl_lockref.count++;
 	set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
-	smp_wmb();
-	gfs2_glock_hold(gl);
+	spin_unlock(&gl->gl_spin);
+
 	if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
 		gfs2_glock_put(gl);
 }
@@ -1404,15 +1397,19 @@
 	while(!list_empty(list)) {
 		gl = list_entry(list->next, struct gfs2_glock, gl_lru);
 		list_del_init(&gl->gl_lru);
+		if (!spin_trylock(&gl->gl_spin)) {
+			list_add(&gl->gl_lru, &lru_list);
+			atomic_inc(&lru_count);
+			continue;
+		}
 		clear_bit(GLF_LRU, &gl->gl_flags);
-		gfs2_glock_hold(gl);
 		spin_unlock(&lru_lock);
-		spin_lock(&gl->gl_spin);
+		gl->gl_lockref.count++;
 		if (demote_ok(gl))
 			handle_callback(gl, LM_ST_UNLOCKED, 0, false);
 		WARN_ON(!test_and_clear_bit(GLF_LOCK, &gl->gl_flags));
 		if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
-			gfs2_glock_put_nolock(gl);
+			gl->gl_lockref.count--;
 		spin_unlock(&gl->gl_spin);
 		spin_lock(&lru_lock);
 	}
@@ -1493,7 +1490,7 @@
 
 	rcu_read_lock();
 	hlist_bl_for_each_entry_rcu(gl, pos, head, gl_list) {
-		if ((gl->gl_sbd == sdp) && atomic_inc_not_zero(&gl->gl_ref))
+		if ((gl->gl_sbd == sdp) && lockref_get_not_dead(&gl->gl_lockref))
 			examiner(gl);
 	}
 	rcu_read_unlock();
@@ -1746,7 +1743,7 @@
 		  state2str(gl->gl_demote_state), dtime,
 		  atomic_read(&gl->gl_ail_count),
 		  atomic_read(&gl->gl_revokes),
-		  atomic_read(&gl->gl_ref), gl->gl_hold_time);
+		  (int)gl->gl_lockref.count, gl->gl_hold_time);
 
 	list_for_each_entry(gh, &gl->gl_holders, gh_list) {
 		error = dump_holder(seq, gh);
@@ -1902,7 +1899,7 @@
 			gi->nhash = 0;
 		}
 	/* Skip entries for other sb and dead entries */
-	} while (gi->sdp != gi->gl->gl_sbd || atomic_read(&gi->gl->gl_ref) == 0);
+	} while (gi->sdp != gi->gl->gl_sbd || __lockref_is_dead(&gl->gl_lockref));
 
 	return 0;
 }
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index 69f66e3..6647d77 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -181,8 +181,6 @@
 extern int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 			  const struct gfs2_glock_operations *glops,
 			  int create, struct gfs2_glock **glp);
-extern void gfs2_glock_hold(struct gfs2_glock *gl);
-extern void gfs2_glock_put_nolock(struct gfs2_glock *gl);
 extern void gfs2_glock_put(struct gfs2_glock *gl);
 extern void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state,
 			     unsigned flags, struct gfs2_holder *gh);
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index e2e0a90..db908f6 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -525,9 +525,9 @@
 
 	if (gl->gl_demote_state == LM_ST_UNLOCKED &&
 	    gl->gl_state == LM_ST_SHARED && ip) {
-		gfs2_glock_hold(gl);
+		gl->gl_lockref.count++;
 		if (queue_work(gfs2_delete_workqueue, &gl->gl_delete) == 0)
-			gfs2_glock_put_nolock(gl);
+			gl->gl_lockref.count--;
 	}
 }
 
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 26aabd7..ba1ea67 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -21,6 +21,7 @@
 #include <linux/rbtree.h>
 #include <linux/ktime.h>
 #include <linux/percpu.h>
+#include <linux/lockref.h>
 
 #define DIO_WAIT	0x00000010
 #define DIO_METADATA	0x00000020
@@ -71,6 +72,7 @@
 	u32 bi_offset;
 	u32 bi_start;
 	u32 bi_len;
+	u32 bi_blocks;
 };
 
 struct gfs2_rgrpd {
@@ -101,19 +103,25 @@
 
 struct gfs2_rbm {
 	struct gfs2_rgrpd *rgd;
-	struct gfs2_bitmap *bi;	/* Bitmap must belong to the rgd */
 	u32 offset;		/* The offset is bitmap relative */
+	int bii;		/* Bitmap index */
 };
 
+static inline struct gfs2_bitmap *rbm_bi(const struct gfs2_rbm *rbm)
+{
+	return rbm->rgd->rd_bits + rbm->bii;
+}
+
 static inline u64 gfs2_rbm_to_block(const struct gfs2_rbm *rbm)
 {
-	return rbm->rgd->rd_data0 + (rbm->bi->bi_start * GFS2_NBBY) + rbm->offset;
+	return rbm->rgd->rd_data0 + (rbm_bi(rbm)->bi_start * GFS2_NBBY) +
+		rbm->offset;
 }
 
 static inline bool gfs2_rbm_eq(const struct gfs2_rbm *rbm1,
 			       const struct gfs2_rbm *rbm2)
 {
-	return (rbm1->rgd == rbm2->rgd) && (rbm1->bi == rbm2->bi) && 
+	return (rbm1->rgd == rbm2->rgd) && (rbm1->bii == rbm2->bii) &&
 	       (rbm1->offset == rbm2->offset);
 }
 
@@ -278,6 +286,20 @@
 	unsigned int rs_qa_qd_num;
 };
 
+/*
+ * Allocation parameters
+ * @target: The number of blocks we'd ideally like to allocate
+ * @aflags: The flags (e.g. Orlov flag)
+ *
+ * The intent is to gradually expand this structure over time in
+ * order to give more information, e.g. alignment, min extent size
+ * to the allocation code.
+ */
+struct gfs2_alloc_parms {
+	u32 target;
+	u32 aflags;
+};
+
 enum {
 	GLF_LOCK			= 1,
 	GLF_DEMOTE			= 3,
@@ -300,9 +322,9 @@
 	struct gfs2_sbd *gl_sbd;
 	unsigned long gl_flags;		/* GLF_... */
 	struct lm_lockname gl_name;
-	atomic_t gl_ref;
 
-	spinlock_t gl_spin;
+	struct lockref gl_lockref;
+#define gl_spin gl_lockref.lock
 
 	/* State fields protected by gl_spin */
 	unsigned int gl_state:2,	/* Current state */
@@ -398,11 +420,10 @@
 
 struct gfs2_quota_data {
 	struct list_head qd_list;
-	struct list_head qd_reclaim;
-
-	atomic_t qd_count;
-
 	struct kqid qd_id;
+	struct lockref qd_lockref;
+	struct list_head qd_lru;
+
 	unsigned long qd_flags;		/* QDF_... */
 
 	s64 qd_change;
@@ -516,7 +537,6 @@
 
 	unsigned int gt_logd_secs;
 
-	unsigned int gt_quota_simul_sync; /* Max quotavals to sync at once */
 	unsigned int gt_quota_warn_period; /* Secs between quota warn msgs */
 	unsigned int gt_quota_scale_num; /* Numerator */
 	unsigned int gt_quota_scale_den; /* Denominator */
@@ -694,6 +714,7 @@
 	struct list_head sd_quota_list;
 	atomic_t sd_quota_count;
 	struct mutex sd_quota_mutex;
+	struct mutex sd_quota_sync_mutex;
 	wait_queue_head_t sd_quota_wait;
 	struct list_head sd_trunc_list;
 	spinlock_t sd_trunc_lock;
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index d2384f7..1615df1 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -379,6 +379,7 @@
 static int alloc_dinode(struct gfs2_inode *ip, u32 flags)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+	struct gfs2_alloc_parms ap = { .target = RES_DINODE, .aflags = flags, };
 	int error;
 	int dblocks = 1;
 
@@ -386,7 +387,7 @@
 	if (error)
 		goto out;
 
-	error = gfs2_inplace_reserve(ip, RES_DINODE, flags);
+	error = gfs2_inplace_reserve(ip, &ap);
 	if (error)
 		goto out_quota;
 
@@ -472,6 +473,7 @@
 		       struct gfs2_inode *ip, int arq)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
+	struct gfs2_alloc_parms ap = { .target = sdp->sd_max_dirres, };
 	int error;
 
 	if (arq) {
@@ -479,7 +481,7 @@
 		if (error)
 			goto fail_quota_locks;
 
-		error = gfs2_inplace_reserve(dip, sdp->sd_max_dirres, 0);
+		error = gfs2_inplace_reserve(dip, &ap);
 		if (error)
 			goto fail_quota_locks;
 
@@ -584,17 +586,17 @@
 	if (!IS_ERR(inode)) {
 		d = d_splice_alias(inode, dentry);
 		error = 0;
-		if (file && !IS_ERR(d)) {
-			if (d == NULL)
-				d = dentry;
-			if (S_ISREG(inode->i_mode))
-				error = finish_open(file, d, gfs2_open_common, opened);
-			else
+		if (file) {
+			if (S_ISREG(inode->i_mode)) {
+				WARN_ON(d != NULL);
+				error = finish_open(file, dentry, gfs2_open_common, opened);
+			} else {
 				error = finish_no_open(file, d);
+			}
+		} else {
+			dput(d);
 		}
 		gfs2_glock_dq_uninit(ghs);
-		if (IS_ERR(d))
-			return PTR_ERR(d);
 		return error;
 	} else if (error != -ENOENT) {
 		goto fail_gunlock;
@@ -713,7 +715,7 @@
 fail_free_inode:
 	if (ip->i_gl)
 		gfs2_glock_put(ip->i_gl);
-	gfs2_rs_delete(ip);
+	gfs2_rs_delete(ip, NULL);
 	free_inode_nonrcu(inode);
 	inode = NULL;
 fail_gunlock:
@@ -781,8 +783,10 @@
 		error = finish_open(file, dentry, gfs2_open_common, opened);
 
 	gfs2_glock_dq_uninit(&gh);
-	if (error)
+	if (error) {
+		dput(d);
 		return ERR_PTR(error);
+	}
 	return d;
 }
 
@@ -874,11 +878,12 @@
 	error = 0;
 
 	if (alloc_required) {
+		struct gfs2_alloc_parms ap = { .target = sdp->sd_max_dirres, };
 		error = gfs2_quota_lock_check(dip);
 		if (error)
 			goto out_gunlock;
 
-		error = gfs2_inplace_reserve(dip, sdp->sd_max_dirres, 0);
+		error = gfs2_inplace_reserve(dip, &ap);
 		if (error)
 			goto out_gunlock_q;
 
@@ -1163,14 +1168,16 @@
 	d = __gfs2_lookup(dir, dentry, file, opened);
 	if (IS_ERR(d))
 		return PTR_ERR(d);
-	if (d == NULL)
-		d = dentry;
-	if (d->d_inode) {
+	if (d != NULL)
+		dentry = d;
+	if (dentry->d_inode) {
 		if (!(*opened & FILE_OPENED))
-			return finish_no_open(file, d);
+			return finish_no_open(file, dentry);
+		dput(d);
 		return 0;
 	}
 
+	BUG_ON(d != NULL);
 	if (!(flags & O_CREAT))
 		return -ENOENT;
 
@@ -1385,11 +1392,12 @@
 		goto out_gunlock;
 
 	if (alloc_required) {
+		struct gfs2_alloc_parms ap = { .target = sdp->sd_max_dirres, };
 		error = gfs2_quota_lock_check(ndip);
 		if (error)
 			goto out_gunlock;
 
-		error = gfs2_inplace_reserve(ndip, sdp->sd_max_dirres, 0);
+		error = gfs2_inplace_reserve(ndip, &ap);
 		if (error)
 			goto out_gunlock_q;
 
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
index 351586e..0650db2 100644
--- a/fs/gfs2/main.c
+++ b/fs/gfs2/main.c
@@ -31,12 +31,6 @@
 
 struct workqueue_struct *gfs2_control_wq;
 
-static struct shrinker qd_shrinker = {
-	.count_objects = gfs2_qd_shrink_count,
-	.scan_objects = gfs2_qd_shrink_scan,
-	.seeks = DEFAULT_SEEKS,
-};
-
 static void gfs2_init_inode_once(void *foo)
 {
 	struct gfs2_inode *ip = foo;
@@ -87,6 +81,10 @@
 	if (error)
 		return error;
 
+	error = list_lru_init(&gfs2_qd_lru);
+	if (error)
+		goto fail_lru;
+
 	error = gfs2_glock_init();
 	if (error)
 		goto fail;
@@ -139,7 +137,7 @@
 	if (!gfs2_rsrv_cachep)
 		goto fail;
 
-	register_shrinker(&qd_shrinker);
+	register_shrinker(&gfs2_qd_shrinker);
 
 	error = register_filesystem(&gfs2_fs_type);
 	if (error)
@@ -179,7 +177,9 @@
 fail_unregister:
 	unregister_filesystem(&gfs2_fs_type);
 fail:
-	unregister_shrinker(&qd_shrinker);
+	list_lru_destroy(&gfs2_qd_lru);
+fail_lru:
+	unregister_shrinker(&gfs2_qd_shrinker);
 	gfs2_glock_exit();
 
 	if (gfs2_rsrv_cachep)
@@ -214,13 +214,14 @@
 
 static void __exit exit_gfs2_fs(void)
 {
-	unregister_shrinker(&qd_shrinker);
+	unregister_shrinker(&gfs2_qd_shrinker);
 	gfs2_glock_exit();
 	gfs2_unregister_debugfs();
 	unregister_filesystem(&gfs2_fs_type);
 	unregister_filesystem(&gfs2meta_fs_type);
 	destroy_workqueue(gfs_recovery_wq);
 	destroy_workqueue(gfs2_control_wq);
+	list_lru_destroy(&gfs2_qd_lru);
 
 	rcu_barrier();
 
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 19ff5e8..82303b4 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -51,7 +51,6 @@
 {
 	spin_lock_init(&gt->gt_spin);
 
-	gt->gt_quota_simul_sync = 64;
 	gt->gt_quota_warn_period = 10;
 	gt->gt_quota_scale_num = 1;
 	gt->gt_quota_scale_den = 1;
@@ -94,6 +93,7 @@
 
 	INIT_LIST_HEAD(&sdp->sd_quota_list);
 	mutex_init(&sdp->sd_quota_mutex);
+	mutex_init(&sdp->sd_quota_sync_mutex);
 	init_waitqueue_head(&sdp->sd_quota_wait);
 	INIT_LIST_HEAD(&sdp->sd_trunc_list);
 	spin_lock_init(&sdp->sd_trunc_lock);
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index db44135..453b50e 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -50,6 +50,8 @@
 #include <linux/freezer.h>
 #include <linux/quota.h>
 #include <linux/dqblk_xfs.h>
+#include <linux/lockref.h>
+#include <linux/list_lru.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -71,29 +73,25 @@
 	struct kqid qc_id;
 };
 
-static LIST_HEAD(qd_lru_list);
-static atomic_t qd_lru_count = ATOMIC_INIT(0);
-static DEFINE_SPINLOCK(qd_lru_lock);
+/* Lock order: qd_lock -> qd->lockref.lock -> lru lock */
+static DEFINE_SPINLOCK(qd_lock);
+struct list_lru gfs2_qd_lru;
 
-unsigned long gfs2_qd_shrink_scan(struct shrinker *shrink,
-				  struct shrink_control *sc)
+static void gfs2_qd_dispose(struct list_head *list)
 {
 	struct gfs2_quota_data *qd;
 	struct gfs2_sbd *sdp;
-	int nr_to_scan = sc->nr_to_scan;
-	long freed = 0;
 
-	if (!(sc->gfp_mask & __GFP_FS))
-		return SHRINK_STOP;
-
-	spin_lock(&qd_lru_lock);
-	while (nr_to_scan && !list_empty(&qd_lru_list)) {
-		qd = list_entry(qd_lru_list.next,
-				struct gfs2_quota_data, qd_reclaim);
+	while (!list_empty(list)) {
+		qd = list_entry(list->next, struct gfs2_quota_data, qd_lru);
 		sdp = qd->qd_gl->gl_sbd;
 
+		list_del(&qd->qd_lru);
+
 		/* Free from the filesystem-specific list */
+		spin_lock(&qd_lock);
 		list_del(&qd->qd_list);
+		spin_unlock(&qd_lock);
 
 		gfs2_assert_warn(sdp, !qd->qd_change);
 		gfs2_assert_warn(sdp, !qd->qd_slot_count);
@@ -103,24 +101,59 @@
 		atomic_dec(&sdp->sd_quota_count);
 
 		/* Delete it from the common reclaim list */
-		list_del_init(&qd->qd_reclaim);
-		atomic_dec(&qd_lru_count);
-		spin_unlock(&qd_lru_lock);
 		kmem_cache_free(gfs2_quotad_cachep, qd);
-		spin_lock(&qd_lru_lock);
-		nr_to_scan--;
-		freed++;
 	}
-	spin_unlock(&qd_lru_lock);
+}
+
+
+static enum lru_status gfs2_qd_isolate(struct list_head *item, spinlock_t *lock, void *arg)
+{
+	struct list_head *dispose = arg;
+	struct gfs2_quota_data *qd = list_entry(item, struct gfs2_quota_data, qd_lru);
+
+	if (!spin_trylock(&qd->qd_lockref.lock))
+		return LRU_SKIP;
+
+	if (qd->qd_lockref.count == 0) {
+		lockref_mark_dead(&qd->qd_lockref);
+		list_move(&qd->qd_lru, dispose);
+	}
+
+	spin_unlock(&qd->qd_lockref.lock);
+	return LRU_REMOVED;
+}
+
+static unsigned long gfs2_qd_shrink_scan(struct shrinker *shrink,
+					 struct shrink_control *sc)
+{
+	LIST_HEAD(dispose);
+	unsigned long freed;
+
+	if (!(sc->gfp_mask & __GFP_FS))
+		return SHRINK_STOP;
+
+	freed = list_lru_walk_node(&gfs2_qd_lru, sc->nid, gfs2_qd_isolate,
+				   &dispose, &sc->nr_to_scan);
+
+	gfs2_qd_dispose(&dispose);
+
 	return freed;
 }
 
-unsigned long gfs2_qd_shrink_count(struct shrinker *shrink,
-				   struct shrink_control *sc)
+static unsigned long gfs2_qd_shrink_count(struct shrinker *shrink,
+					  struct shrink_control *sc)
 {
-	return vfs_pressure_ratio(atomic_read(&qd_lru_count));
+	return vfs_pressure_ratio(list_lru_count_node(&gfs2_qd_lru, sc->nid));
 }
 
+struct shrinker gfs2_qd_shrinker = {
+	.count_objects = gfs2_qd_shrink_count,
+	.scan_objects = gfs2_qd_shrink_scan,
+	.seeks = DEFAULT_SEEKS,
+	.flags = SHRINKER_NUMA_AWARE,
+};
+
+
 static u64 qd2index(struct gfs2_quota_data *qd)
 {
 	struct kqid qid = qd->qd_id;
@@ -148,10 +181,11 @@
 	if (!qd)
 		return -ENOMEM;
 
-	atomic_set(&qd->qd_count, 1);
+	qd->qd_lockref.count = 1;
+	spin_lock_init(&qd->qd_lockref.lock);
 	qd->qd_id = qid;
 	qd->qd_slot = -1;
-	INIT_LIST_HEAD(&qd->qd_reclaim);
+	INIT_LIST_HEAD(&qd->qd_lru);
 
 	error = gfs2_glock_get(sdp, qd2index(qd),
 			      &gfs2_quota_glops, CREATE, &qd->qd_gl);
@@ -177,16 +211,11 @@
 
 	for (;;) {
 		found = 0;
-		spin_lock(&qd_lru_lock);
+		spin_lock(&qd_lock);
 		list_for_each_entry(qd, &sdp->sd_quota_list, qd_list) {
-			if (qid_eq(qd->qd_id, qid)) {
-				if (!atomic_read(&qd->qd_count) &&
-				    !list_empty(&qd->qd_reclaim)) {
-					/* Remove it from reclaim list */
-					list_del_init(&qd->qd_reclaim);
-					atomic_dec(&qd_lru_count);
-				}
-				atomic_inc(&qd->qd_count);
+			if (qid_eq(qd->qd_id, qid) &&
+			    lockref_get_not_dead(&qd->qd_lockref)) {
+				list_lru_del(&gfs2_qd_lru, &qd->qd_lru);
 				found = 1;
 				break;
 			}
@@ -202,7 +231,7 @@
 			new_qd = NULL;
 		}
 
-		spin_unlock(&qd_lru_lock);
+		spin_unlock(&qd_lock);
 
 		if (qd) {
 			if (new_qd) {
@@ -222,18 +251,19 @@
 static void qd_hold(struct gfs2_quota_data *qd)
 {
 	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
-	gfs2_assert(sdp, atomic_read(&qd->qd_count));
-	atomic_inc(&qd->qd_count);
+	gfs2_assert(sdp, !__lockref_is_dead(&qd->qd_lockref));
+	lockref_get(&qd->qd_lockref);
 }
 
 static void qd_put(struct gfs2_quota_data *qd)
 {
-	if (atomic_dec_and_lock(&qd->qd_count, &qd_lru_lock)) {
-		/* Add to the reclaim list */
-		list_add_tail(&qd->qd_reclaim, &qd_lru_list);
-		atomic_inc(&qd_lru_count);
-		spin_unlock(&qd_lru_lock);
-	}
+	if (lockref_put_or_lock(&qd->qd_lockref))
+		return;
+
+	qd->qd_lockref.count = 0;
+	list_lru_add(&gfs2_qd_lru, &qd->qd_lru);
+	spin_unlock(&qd->qd_lockref.lock);
+
 }
 
 static int slot_get(struct gfs2_quota_data *qd)
@@ -242,10 +272,10 @@
 	unsigned int c, o = 0, b;
 	unsigned char byte = 0;
 
-	spin_lock(&qd_lru_lock);
+	spin_lock(&qd_lock);
 
 	if (qd->qd_slot_count++) {
-		spin_unlock(&qd_lru_lock);
+		spin_unlock(&qd_lock);
 		return 0;
 	}
 
@@ -269,13 +299,13 @@
 
 	sdp->sd_quota_bitmap[c][o] |= 1 << b;
 
-	spin_unlock(&qd_lru_lock);
+	spin_unlock(&qd_lock);
 
 	return 0;
 
 fail:
 	qd->qd_slot_count--;
-	spin_unlock(&qd_lru_lock);
+	spin_unlock(&qd_lock);
 	return -ENOSPC;
 }
 
@@ -283,23 +313,43 @@
 {
 	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
 
-	spin_lock(&qd_lru_lock);
+	spin_lock(&qd_lock);
 	gfs2_assert(sdp, qd->qd_slot_count);
 	qd->qd_slot_count++;
-	spin_unlock(&qd_lru_lock);
+	spin_unlock(&qd_lock);
+}
+
+static void gfs2_icbit_munge(struct gfs2_sbd *sdp, unsigned char **bitmap,
+			     unsigned int bit, int new_value)
+{
+	unsigned int c, o, b = bit;
+	int old_value;
+
+	c = b / (8 * PAGE_SIZE);
+	b %= 8 * PAGE_SIZE;
+	o = b / 8;
+	b %= 8;
+
+	old_value = (bitmap[c][o] & (1 << b));
+	gfs2_assert_withdraw(sdp, !old_value != !new_value);
+
+	if (new_value)
+		bitmap[c][o] |= 1 << b;
+	else
+		bitmap[c][o] &= ~(1 << b);
 }
 
 static void slot_put(struct gfs2_quota_data *qd)
 {
 	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
 
-	spin_lock(&qd_lru_lock);
+	spin_lock(&qd_lock);
 	gfs2_assert(sdp, qd->qd_slot_count);
 	if (!--qd->qd_slot_count) {
 		gfs2_icbit_munge(sdp, sdp->sd_quota_bitmap, qd->qd_slot, 0);
 		qd->qd_slot = -1;
 	}
-	spin_unlock(&qd_lru_lock);
+	spin_unlock(&qd_lock);
 }
 
 static int bh_get(struct gfs2_quota_data *qd)
@@ -363,6 +413,25 @@
 	mutex_unlock(&sdp->sd_quota_mutex);
 }
 
+static int qd_check_sync(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd,
+			 u64 *sync_gen)
+{
+	if (test_bit(QDF_LOCKED, &qd->qd_flags) ||
+	    !test_bit(QDF_CHANGE, &qd->qd_flags) ||
+	    (sync_gen && (qd->qd_sync_gen >= *sync_gen)))
+		return 0;
+
+	if (!lockref_get_not_dead(&qd->qd_lockref))
+		return 0;
+
+	list_move_tail(&qd->qd_list, &sdp->sd_quota_list);
+	set_bit(QDF_LOCKED, &qd->qd_flags);
+	qd->qd_change_sync = qd->qd_change;
+	gfs2_assert_warn(sdp, qd->qd_slot_count);
+	qd->qd_slot_count++;
+	return 1;
+}
+
 static int qd_fish(struct gfs2_sbd *sdp, struct gfs2_quota_data **qdp)
 {
 	struct gfs2_quota_data *qd = NULL;
@@ -374,31 +443,18 @@
 	if (sdp->sd_vfs->s_flags & MS_RDONLY)
 		return 0;
 
-	spin_lock(&qd_lru_lock);
+	spin_lock(&qd_lock);
 
 	list_for_each_entry(qd, &sdp->sd_quota_list, qd_list) {
-		if (test_bit(QDF_LOCKED, &qd->qd_flags) ||
-		    !test_bit(QDF_CHANGE, &qd->qd_flags) ||
-		    qd->qd_sync_gen >= sdp->sd_quota_sync_gen)
-			continue;
-
-		list_move_tail(&qd->qd_list, &sdp->sd_quota_list);
-
-		set_bit(QDF_LOCKED, &qd->qd_flags);
-		gfs2_assert_warn(sdp, atomic_read(&qd->qd_count));
-		atomic_inc(&qd->qd_count);
-		qd->qd_change_sync = qd->qd_change;
-		gfs2_assert_warn(sdp, qd->qd_slot_count);
-		qd->qd_slot_count++;
-		found = 1;
-
-		break;
+		found = qd_check_sync(sdp, qd, &sdp->sd_quota_sync_gen);
+		if (found)
+			break;
 	}
 
 	if (!found)
 		qd = NULL;
 
-	spin_unlock(&qd_lru_lock);
+	spin_unlock(&qd_lock);
 
 	if (qd) {
 		gfs2_assert_warn(sdp, qd->qd_change_sync);
@@ -416,43 +472,6 @@
 	return 0;
 }
 
-static int qd_trylock(struct gfs2_quota_data *qd)
-{
-	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;
-
-	if (sdp->sd_vfs->s_flags & MS_RDONLY)
-		return 0;
-
-	spin_lock(&qd_lru_lock);
-
-	if (test_bit(QDF_LOCKED, &qd->qd_flags) ||
-	    !test_bit(QDF_CHANGE, &qd->qd_flags)) {
-		spin_unlock(&qd_lru_lock);
-		return 0;
-	}
-
-	list_move_tail(&qd->qd_list, &sdp->sd_quota_list);
-
-	set_bit(QDF_LOCKED, &qd->qd_flags);
-	gfs2_assert_warn(sdp, atomic_read(&qd->qd_count));
-	atomic_inc(&qd->qd_count);
-	qd->qd_change_sync = qd->qd_change;
-	gfs2_assert_warn(sdp, qd->qd_slot_count);
-	qd->qd_slot_count++;
-
-	spin_unlock(&qd_lru_lock);
-
-	gfs2_assert_warn(sdp, qd->qd_change_sync);
-	if (bh_get(qd)) {
-		clear_bit(QDF_LOCKED, &qd->qd_flags);
-		slot_put(qd);
-		qd_put(qd);
-		return 0;
-	}
-
-	return 1;
-}
-
 static void qd_unlock(struct gfs2_quota_data *qd)
 {
 	gfs2_assert_warn(qd->qd_gl->gl_sbd,
@@ -602,9 +621,9 @@
 	x = be64_to_cpu(qc->qc_change) + change;
 	qc->qc_change = cpu_to_be64(x);
 
-	spin_lock(&qd_lru_lock);
+	spin_lock(&qd_lock);
 	qd->qd_change = x;
-	spin_unlock(&qd_lru_lock);
+	spin_unlock(&qd_lock);
 
 	if (!x) {
 		gfs2_assert_warn(sdp, test_bit(QDF_CHANGE, &qd->qd_flags));
@@ -763,6 +782,7 @@
 {
 	struct gfs2_sbd *sdp = (*qda)->qd_gl->gl_sbd;
 	struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
+	struct gfs2_alloc_parms ap = { .aflags = 0, };
 	unsigned int data_blocks, ind_blocks;
 	struct gfs2_holder *ghs, i_gh;
 	unsigned int qx, x;
@@ -815,7 +835,8 @@
 	blocks = num_qd * data_blocks + RES_DINODE + num_qd + 3;
 
 	reserved = 1 + (nalloc * (data_blocks + ind_blocks));
-	error = gfs2_inplace_reserve(ip, reserved, 0);
+	ap.target = reserved;
+	error = gfs2_inplace_reserve(ip, &ap);
 	if (error)
 		goto out_alloc;
 
@@ -974,9 +995,9 @@
 	if (!qd->qd_qb.qb_limit)
 		return 0;
 
-	spin_lock(&qd_lru_lock);
+	spin_lock(&qd_lock);
 	value = qd->qd_change;
-	spin_unlock(&qd_lru_lock);
+	spin_unlock(&qd_lock);
 
 	spin_lock(&gt->gt_spin);
 	num = gt->gt_quota_scale_num;
@@ -1001,9 +1022,11 @@
 
 void gfs2_quota_unlock(struct gfs2_inode *ip)
 {
+	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct gfs2_quota_data *qda[4];
 	unsigned int count = 0;
 	unsigned int x;
+	int found;
 
 	if (!test_and_clear_bit(GIF_QD_LOCKED, &ip->i_flags))
 		goto out;
@@ -1016,9 +1039,25 @@
 		sync = need_sync(qd);
 
 		gfs2_glock_dq_uninit(&ip->i_res->rs_qa_qd_ghs[x]);
+		if (!sync)
+			continue;
 
-		if (sync && qd_trylock(qd))
-			qda[count++] = qd;
+		spin_lock(&qd_lock);
+		found = qd_check_sync(sdp, qd, NULL);
+		spin_unlock(&qd_lock);
+
+		if (!found)
+			continue;
+
+		gfs2_assert_warn(sdp, qd->qd_change_sync);
+		if (bh_get(qd)) {
+			clear_bit(QDF_LOCKED, &qd->qd_flags);
+			slot_put(qd);
+			qd_put(qd);
+			continue;
+		}
+
+		qda[count++] = qd;
 	}
 
 	if (count) {
@@ -1067,9 +1106,9 @@
 			continue;
 
 		value = (s64)be64_to_cpu(qd->qd_qb.qb_value);
-		spin_lock(&qd_lru_lock);
+		spin_lock(&qd_lock);
 		value += qd->qd_change;
-		spin_unlock(&qd_lru_lock);
+		spin_unlock(&qd_lock);
 
 		if (be64_to_cpu(qd->qd_qb.qb_limit) && (s64)be64_to_cpu(qd->qd_qb.qb_limit) < value) {
 			print_message(qd, "exceeded");
@@ -1118,17 +1157,18 @@
 {
 	struct gfs2_sbd *sdp = sb->s_fs_info;
 	struct gfs2_quota_data **qda;
-	unsigned int max_qd = gfs2_tune_get(sdp, gt_quota_simul_sync);
+	unsigned int max_qd = PAGE_SIZE/sizeof(struct gfs2_holder);
 	unsigned int num_qd;
 	unsigned int x;
 	int error = 0;
 
-	sdp->sd_quota_sync_gen++;
-
 	qda = kcalloc(max_qd, sizeof(struct gfs2_quota_data *), GFP_KERNEL);
 	if (!qda)
 		return -ENOMEM;
 
+	mutex_lock(&sdp->sd_quota_sync_mutex);
+	sdp->sd_quota_sync_gen++;
+
 	do {
 		num_qd = 0;
 
@@ -1153,6 +1193,7 @@
 		}
 	} while (!error && num_qd == max_qd);
 
+	mutex_unlock(&sdp->sd_quota_sync_mutex);
 	kfree(qda);
 
 	return error;
@@ -1258,11 +1299,11 @@
 			qd->qd_slot = slot;
 			qd->qd_slot_count = 1;
 
-			spin_lock(&qd_lru_lock);
+			spin_lock(&qd_lock);
 			gfs2_icbit_munge(sdp, sdp->sd_quota_bitmap, slot, 1);
 			list_add(&qd->qd_list, &sdp->sd_quota_list);
 			atomic_inc(&sdp->sd_quota_count);
-			spin_unlock(&qd_lru_lock);
+			spin_unlock(&qd_lock);
 
 			found++;
 		}
@@ -1288,30 +1329,34 @@
 	struct gfs2_quota_data *qd;
 	unsigned int x;
 
-	spin_lock(&qd_lru_lock);
+	spin_lock(&qd_lock);
 	while (!list_empty(head)) {
 		qd = list_entry(head->prev, struct gfs2_quota_data, qd_list);
 
-		if (atomic_read(&qd->qd_count) > 1 ||
-		    (atomic_read(&qd->qd_count) &&
-		     !test_bit(QDF_CHANGE, &qd->qd_flags))) {
+		/*
+		 * To be removed in due course... we should be able to
+		 * ensure that all refs to the qd have done by this point
+		 * so that this rather odd test is not required
+		 */
+		spin_lock(&qd->qd_lockref.lock);
+		if (qd->qd_lockref.count > 1 ||
+		    (qd->qd_lockref.count && !test_bit(QDF_CHANGE, &qd->qd_flags))) {
+			spin_unlock(&qd->qd_lockref.lock);
 			list_move(&qd->qd_list, head);
-			spin_unlock(&qd_lru_lock);
+			spin_unlock(&qd_lock);
 			schedule();
-			spin_lock(&qd_lru_lock);
+			spin_lock(&qd_lock);
 			continue;
 		}
+		spin_unlock(&qd->qd_lockref.lock);
 
 		list_del(&qd->qd_list);
 		/* Also remove if this qd exists in the reclaim list */
-		if (!list_empty(&qd->qd_reclaim)) {
-			list_del_init(&qd->qd_reclaim);
-			atomic_dec(&qd_lru_count);
-		}
+		list_lru_del(&gfs2_qd_lru, &qd->qd_lru);
 		atomic_dec(&sdp->sd_quota_count);
-		spin_unlock(&qd_lru_lock);
+		spin_unlock(&qd_lock);
 
-		if (!atomic_read(&qd->qd_count)) {
+		if (!qd->qd_lockref.count) {
 			gfs2_assert_warn(sdp, !qd->qd_change);
 			gfs2_assert_warn(sdp, !qd->qd_slot_count);
 		} else
@@ -1321,9 +1366,9 @@
 		gfs2_glock_put(qd->qd_gl);
 		kmem_cache_free(gfs2_quotad_cachep, qd);
 
-		spin_lock(&qd_lru_lock);
+		spin_lock(&qd_lock);
 	}
-	spin_unlock(&qd_lru_lock);
+	spin_unlock(&qd_lock);
 
 	gfs2_assert_warn(sdp, !atomic_read(&sdp->sd_quota_count));
 
@@ -1462,7 +1507,7 @@
 	}
 	fqs->qs_uquota.qfs_nextents = 1; /* unsupported */
 	fqs->qs_gquota = fqs->qs_uquota; /* its the same inode in both cases */
-	fqs->qs_incoredqs = atomic_read(&qd_lru_count);
+	fqs->qs_incoredqs = list_lru_count(&gfs2_qd_lru);
 	return 0;
 }
 
@@ -1573,10 +1618,12 @@
 	if (gfs2_is_stuffed(ip))
 		alloc_required = 1;
 	if (alloc_required) {
+		struct gfs2_alloc_parms ap = { .aflags = 0, };
 		gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota),
 				       &data_blocks, &ind_blocks);
 		blocks = 1 + data_blocks + ind_blocks;
-		error = gfs2_inplace_reserve(ip, blocks, 0);
+		ap.target = blocks;
+		error = gfs2_inplace_reserve(ip, &ap);
 		if (error)
 			goto out_i;
 		blocks += gfs2_rg_blocks(ip, blocks);
diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h
index 0f64d9d..96e4f34 100644
--- a/fs/gfs2/quota.h
+++ b/fs/gfs2/quota.h
@@ -10,9 +10,10 @@
 #ifndef __QUOTA_DOT_H__
 #define __QUOTA_DOT_H__
 
+#include <linux/list_lru.h>
+
 struct gfs2_inode;
 struct gfs2_sbd;
-struct shrink_control;
 
 #define NO_UID_QUOTA_CHANGE INVALID_UID
 #define NO_GID_QUOTA_CHANGE INVALID_GID
@@ -53,10 +54,8 @@
 	return ret;
 }
 
-extern unsigned long gfs2_qd_shrink_count(struct shrinker *shrink,
-					  struct shrink_control *sc);
-extern unsigned long gfs2_qd_shrink_scan(struct shrinker *shrink,
-					 struct shrink_control *sc);
 extern const struct quotactl_ops gfs2_quotactl_ops;
+extern struct shrinker gfs2_qd_shrinker;
+extern struct list_lru gfs2_qd_lru;
 
 #endif /* __QUOTA_DOT_H__ */
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 6931743..4d83abd 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -81,11 +81,12 @@
 			       unsigned char new_state)
 {
 	unsigned char *byte1, *byte2, *end, cur_state;
-	unsigned int buflen = rbm->bi->bi_len;
+	struct gfs2_bitmap *bi = rbm_bi(rbm);
+	unsigned int buflen = bi->bi_len;
 	const unsigned int bit = (rbm->offset % GFS2_NBBY) * GFS2_BIT_SIZE;
 
-	byte1 = rbm->bi->bi_bh->b_data + rbm->bi->bi_offset + (rbm->offset / GFS2_NBBY);
-	end = rbm->bi->bi_bh->b_data + rbm->bi->bi_offset + buflen;
+	byte1 = bi->bi_bh->b_data + bi->bi_offset + (rbm->offset / GFS2_NBBY);
+	end = bi->bi_bh->b_data + bi->bi_offset + buflen;
 
 	BUG_ON(byte1 >= end);
 
@@ -95,18 +96,17 @@
 		printk(KERN_WARNING "GFS2: buf_blk = 0x%x old_state=%d, "
 		       "new_state=%d\n", rbm->offset, cur_state, new_state);
 		printk(KERN_WARNING "GFS2: rgrp=0x%llx bi_start=0x%x\n",
-		       (unsigned long long)rbm->rgd->rd_addr,
-		       rbm->bi->bi_start);
+		       (unsigned long long)rbm->rgd->rd_addr, bi->bi_start);
 		printk(KERN_WARNING "GFS2: bi_offset=0x%x bi_len=0x%x\n",
-		       rbm->bi->bi_offset, rbm->bi->bi_len);
+		       bi->bi_offset, bi->bi_len);
 		dump_stack();
 		gfs2_consist_rgrpd(rbm->rgd);
 		return;
 	}
 	*byte1 ^= (cur_state ^ new_state) << bit;
 
-	if (do_clone && rbm->bi->bi_clone) {
-		byte2 = rbm->bi->bi_clone + rbm->bi->bi_offset + (rbm->offset / GFS2_NBBY);
+	if (do_clone && bi->bi_clone) {
+		byte2 = bi->bi_clone + bi->bi_offset + (rbm->offset / GFS2_NBBY);
 		cur_state = (*byte2 >> bit) & GFS2_BIT_MASK;
 		*byte2 ^= (cur_state ^ new_state) << bit;
 	}
@@ -121,7 +121,8 @@
 
 static inline u8 gfs2_testbit(const struct gfs2_rbm *rbm)
 {
-	const u8 *buffer = rbm->bi->bi_bh->b_data + rbm->bi->bi_offset;
+	struct gfs2_bitmap *bi = rbm_bi(rbm);
+	const u8 *buffer = bi->bi_bh->b_data + bi->bi_offset;
 	const u8 *byte;
 	unsigned int bit;
 
@@ -252,29 +253,53 @@
 static int gfs2_rbm_from_block(struct gfs2_rbm *rbm, u64 block)
 {
 	u64 rblock = block - rbm->rgd->rd_data0;
-	u32 x;
 
 	if (WARN_ON_ONCE(rblock > UINT_MAX))
 		return -EINVAL;
 	if (block >= rbm->rgd->rd_data0 + rbm->rgd->rd_data)
 		return -E2BIG;
 
-	rbm->bi = rbm->rgd->rd_bits;
+	rbm->bii = 0;
 	rbm->offset = (u32)(rblock);
 	/* Check if the block is within the first block */
-	if (rbm->offset < (rbm->bi->bi_start + rbm->bi->bi_len) * GFS2_NBBY)
+	if (rbm->offset < rbm_bi(rbm)->bi_blocks)
 		return 0;
 
 	/* Adjust for the size diff between gfs2_meta_header and gfs2_rgrp */
 	rbm->offset += (sizeof(struct gfs2_rgrp) -
 			sizeof(struct gfs2_meta_header)) * GFS2_NBBY;
-	x = rbm->offset / rbm->rgd->rd_sbd->sd_blocks_per_bitmap;
-	rbm->offset -= x * rbm->rgd->rd_sbd->sd_blocks_per_bitmap;
-	rbm->bi += x;
+	rbm->bii = rbm->offset / rbm->rgd->rd_sbd->sd_blocks_per_bitmap;
+	rbm->offset -= rbm->bii * rbm->rgd->rd_sbd->sd_blocks_per_bitmap;
 	return 0;
 }
 
 /**
+ * gfs2_rbm_incr - increment an rbm structure
+ * @rbm: The rbm with rgd already set correctly
+ *
+ * This function takes an existing rbm structure and increments it to the next
+ * viable block offset.
+ *
+ * Returns: If incrementing the offset would cause the rbm to go past the
+ *          end of the rgrp, true is returned, otherwise false.
+ *
+ */
+
+static bool gfs2_rbm_incr(struct gfs2_rbm *rbm)
+{
+	if (rbm->offset + 1 < rbm_bi(rbm)->bi_blocks) { /* in the same bitmap */
+		rbm->offset++;
+		return false;
+	}
+	if (rbm->bii == rbm->rgd->rd_length - 1) /* at the last bitmap */
+		return true;
+
+	rbm->offset = 0;
+	rbm->bii++;
+	return false;
+}
+
+/**
  * gfs2_unaligned_extlen - Look for free blocks which are not byte aligned
  * @rbm: Position to search (value/result)
  * @n_unaligned: Number of unaligned blocks to check
@@ -285,7 +310,6 @@
 
 static bool gfs2_unaligned_extlen(struct gfs2_rbm *rbm, u32 n_unaligned, u32 *len)
 {
-	u64 block;
 	u32 n;
 	u8 res;
 
@@ -296,8 +320,7 @@
 		(*len)--;
 		if (*len == 0)
 			return true;
-		block = gfs2_rbm_to_block(rbm);
-		if (gfs2_rbm_from_block(rbm, block + 1))
+		if (gfs2_rbm_incr(rbm))
 			return true;
 	}
 
@@ -328,6 +351,7 @@
 	u32 chunk_size;
 	u8 *ptr, *start, *end;
 	u64 block;
+	struct gfs2_bitmap *bi;
 
 	if (n_unaligned &&
 	    gfs2_unaligned_extlen(&rbm, 4 - n_unaligned, &len))
@@ -336,11 +360,12 @@
 	n_unaligned = len & 3;
 	/* Start is now byte aligned */
 	while (len > 3) {
-		start = rbm.bi->bi_bh->b_data;
-		if (rbm.bi->bi_clone)
-			start = rbm.bi->bi_clone;
-		end = start + rbm.bi->bi_bh->b_size;
-		start += rbm.bi->bi_offset;
+		bi = rbm_bi(&rbm);
+		start = bi->bi_bh->b_data;
+		if (bi->bi_clone)
+			start = bi->bi_clone;
+		end = start + bi->bi_bh->b_size;
+		start += bi->bi_offset;
 		BUG_ON(rbm.offset & 3);
 		start += (rbm.offset / GFS2_NBBY);
 		bytes = min_t(u32, len / GFS2_NBBY, (end - start));
@@ -605,11 +630,13 @@
 	RB_CLEAR_NODE(&rs->rs_node);
 
 	if (rs->rs_free) {
+		struct gfs2_bitmap *bi = rbm_bi(&rs->rs_rbm);
+
 		/* return reserved blocks to the rgrp */
 		BUG_ON(rs->rs_rbm.rgd->rd_reserved < rs->rs_free);
 		rs->rs_rbm.rgd->rd_reserved -= rs->rs_free;
 		rs->rs_free = 0;
-		clear_bit(GBF_FULL, &rs->rs_rbm.bi->bi_flags);
+		clear_bit(GBF_FULL, &bi->bi_flags);
 		smp_mb__after_clear_bit();
 	}
 }
@@ -634,14 +661,13 @@
 /**
  * gfs2_rs_delete - delete a multi-block reservation
  * @ip: The inode for this reservation
+ * @wcount: The inode's write count, or NULL
  *
  */
-void gfs2_rs_delete(struct gfs2_inode *ip)
+void gfs2_rs_delete(struct gfs2_inode *ip, atomic_t *wcount)
 {
-	struct inode *inode = &ip->i_inode;
-
 	down_write(&ip->i_rw_mutex);
-	if (ip->i_res && atomic_read(&inode->i_writecount) <= 1) {
+	if (ip->i_res && ((wcount == NULL) || (atomic_read(wcount) <= 1))) {
 		gfs2_rs_deltree(ip->i_res);
 		BUG_ON(ip->i_res->rs_free);
 		kmem_cache_free(gfs2_rsrv_cachep, ip->i_res);
@@ -743,18 +769,21 @@
 			bi->bi_offset = sizeof(struct gfs2_rgrp);
 			bi->bi_start = 0;
 			bi->bi_len = bytes;
+			bi->bi_blocks = bytes * GFS2_NBBY;
 		/* header block */
 		} else if (x == 0) {
 			bytes = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_rgrp);
 			bi->bi_offset = sizeof(struct gfs2_rgrp);
 			bi->bi_start = 0;
 			bi->bi_len = bytes;
+			bi->bi_blocks = bytes * GFS2_NBBY;
 		/* last block */
 		} else if (x + 1 == length) {
 			bytes = bytes_left;
 			bi->bi_offset = sizeof(struct gfs2_meta_header);
 			bi->bi_start = rgd->rd_bitbytes - bytes_left;
 			bi->bi_len = bytes;
+			bi->bi_blocks = bytes * GFS2_NBBY;
 		/* other blocks */
 		} else {
 			bytes = sdp->sd_sb.sb_bsize -
@@ -762,6 +791,7 @@
 			bi->bi_offset = sizeof(struct gfs2_meta_header);
 			bi->bi_start = rgd->rd_bitbytes - bytes_left;
 			bi->bi_len = bytes;
+			bi->bi_blocks = bytes * GFS2_NBBY;
 		}
 
 		bytes_left -= bytes;
@@ -1392,12 +1422,12 @@
  * rg_mblk_search - find a group of multiple free blocks to form a reservation
  * @rgd: the resource group descriptor
  * @ip: pointer to the inode for which we're reserving blocks
- * @requested: number of blocks required for this allocation
+ * @ap: the allocation parameters
  *
  */
 
 static void rg_mblk_search(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip,
-			   unsigned requested)
+			   const struct gfs2_alloc_parms *ap)
 {
 	struct gfs2_rbm rbm = { .rgd = rgd, };
 	u64 goal;
@@ -1410,7 +1440,7 @@
 	if (S_ISDIR(inode->i_mode))
 		extlen = 1;
 	else {
-		extlen = max_t(u32, atomic_read(&rs->rs_sizehint), requested);
+		extlen = max_t(u32, atomic_read(&rs->rs_sizehint), ap->target);
 		extlen = clamp(extlen, RGRP_RSRV_MINBLKS, free_blocks);
 	}
 	if ((rgd->rd_free_clone < rgd->rd_reserved) || (free_blocks < extlen))
@@ -1554,14 +1584,14 @@
 			 const struct gfs2_inode *ip, bool nowrap)
 {
 	struct buffer_head *bh;
-	struct gfs2_bitmap *initial_bi;
+	int initial_bii;
 	u32 initial_offset;
 	u32 offset;
 	u8 *buffer;
-	int index;
 	int n = 0;
 	int iters = rbm->rgd->rd_length;
 	int ret;
+	struct gfs2_bitmap *bi;
 
 	/* If we are not starting at the beginning of a bitmap, then we
 	 * need to add one to the bitmap count to ensure that we search
@@ -1571,52 +1601,53 @@
 		iters++;
 
 	while(1) {
-		if (test_bit(GBF_FULL, &rbm->bi->bi_flags) &&
+		bi = rbm_bi(rbm);
+		if (test_bit(GBF_FULL, &bi->bi_flags) &&
 		    (state == GFS2_BLKST_FREE))
 			goto next_bitmap;
 
-		bh = rbm->bi->bi_bh;
-		buffer = bh->b_data + rbm->bi->bi_offset;
+		bh = bi->bi_bh;
+		buffer = bh->b_data + bi->bi_offset;
 		WARN_ON(!buffer_uptodate(bh));
-		if (state != GFS2_BLKST_UNLINKED && rbm->bi->bi_clone)
-			buffer = rbm->bi->bi_clone + rbm->bi->bi_offset;
+		if (state != GFS2_BLKST_UNLINKED && bi->bi_clone)
+			buffer = bi->bi_clone + bi->bi_offset;
 		initial_offset = rbm->offset;
-		offset = gfs2_bitfit(buffer, rbm->bi->bi_len, rbm->offset, state);
+		offset = gfs2_bitfit(buffer, bi->bi_len, rbm->offset, state);
 		if (offset == BFITNOENT)
 			goto bitmap_full;
 		rbm->offset = offset;
 		if (ip == NULL)
 			return 0;
 
-		initial_bi = rbm->bi;
+		initial_bii = rbm->bii;
 		ret = gfs2_reservation_check_and_update(rbm, ip, minext);
 		if (ret == 0)
 			return 0;
 		if (ret > 0) {
-			n += (rbm->bi - initial_bi);
+			n += (rbm->bii - initial_bii);
 			goto next_iter;
 		}
 		if (ret == -E2BIG) {
-			index = 0;
+			rbm->bii = 0;
 			rbm->offset = 0;
-			n += (rbm->bi - initial_bi);
+			n += (rbm->bii - initial_bii);
 			goto res_covered_end_of_rgrp;
 		}
 		return ret;
 
 bitmap_full:	/* Mark bitmap as full and fall through */
-		if ((state == GFS2_BLKST_FREE) && initial_offset == 0)
-			set_bit(GBF_FULL, &rbm->bi->bi_flags);
+		if ((state == GFS2_BLKST_FREE) && initial_offset == 0) {
+			struct gfs2_bitmap *bi = rbm_bi(rbm);
+			set_bit(GBF_FULL, &bi->bi_flags);
+		}
 
 next_bitmap:	/* Find next bitmap in the rgrp */
 		rbm->offset = 0;
-		index = rbm->bi - rbm->rgd->rd_bits;
-		index++;
-		if (index == rbm->rgd->rd_length)
-			index = 0;
+		rbm->bii++;
+		if (rbm->bii == rbm->rgd->rd_length)
+			rbm->bii = 0;
 res_covered_end_of_rgrp:
-		rbm->bi = &rbm->rgd->rd_bits[index];
-		if ((index == 0) && nowrap)
+		if ((rbm->bii == 0) && nowrap)
 			break;
 		n++;
 next_iter:
@@ -1645,7 +1676,7 @@
 	struct gfs2_inode *ip;
 	int error;
 	int found = 0;
-	struct gfs2_rbm rbm = { .rgd = rgd, .bi = rgd->rd_bits, .offset = 0 };
+	struct gfs2_rbm rbm = { .rgd = rgd, .bii = 0, .offset = 0 };
 
 	while (1) {
 		down_write(&sdp->sd_log_flush_lock);
@@ -1800,12 +1831,12 @@
 /**
  * gfs2_inplace_reserve - Reserve space in the filesystem
  * @ip: the inode to reserve space for
- * @requested: the number of blocks to be reserved
+ * @ap: the allocation parameters
  *
  * Returns: errno
  */
 
-int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested, u32 aflags)
+int gfs2_inplace_reserve(struct gfs2_inode *ip, const struct gfs2_alloc_parms *ap)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct gfs2_rgrpd *begin = NULL;
@@ -1817,17 +1848,16 @@
 
 	if (sdp->sd_args.ar_rgrplvb)
 		flags |= GL_SKIP;
-	if (gfs2_assert_warn(sdp, requested))
+	if (gfs2_assert_warn(sdp, ap->target))
 		return -EINVAL;
 	if (gfs2_rs_active(rs)) {
 		begin = rs->rs_rbm.rgd;
-		flags = 0; /* Yoda: Do or do not. There is no try */
 	} else if (ip->i_rgd && rgrp_contains_block(ip->i_rgd, ip->i_goal)) {
 		rs->rs_rbm.rgd = begin = ip->i_rgd;
 	} else {
 		rs->rs_rbm.rgd = begin = gfs2_blk2rgrpd(sdp, ip->i_goal, 1);
 	}
-	if (S_ISDIR(ip->i_inode.i_mode) && (aflags & GFS2_AF_ORLOV))
+	if (S_ISDIR(ip->i_inode.i_mode) && (ap->aflags & GFS2_AF_ORLOV))
 		skip = gfs2_orlov_skip(ip);
 	if (rs->rs_rbm.rgd == NULL)
 		return -EBADSLT;
@@ -1869,14 +1899,14 @@
 
 		/* Get a reservation if we don't already have one */
 		if (!gfs2_rs_active(rs))
-			rg_mblk_search(rs->rs_rbm.rgd, ip, requested);
+			rg_mblk_search(rs->rs_rbm.rgd, ip, ap);
 
 		/* Skip rgrps when we can't get a reservation on first pass */
 		if (!gfs2_rs_active(rs) && (loops < 1))
 			goto check_rgrp;
 
 		/* If rgrp has enough free space, use it */
-		if (rs->rs_rbm.rgd->rd_free_clone >= requested) {
+		if (rs->rs_rbm.rgd->rd_free_clone >= ap->target) {
 			ip->i_rgd = rs->rs_rbm.rgd;
 			return 0;
 		}
@@ -1973,14 +2003,14 @@
 
 	*n = 1;
 	block = gfs2_rbm_to_block(rbm);
-	gfs2_trans_add_meta(rbm->rgd->rd_gl, rbm->bi->bi_bh);
+	gfs2_trans_add_meta(rbm->rgd->rd_gl, rbm_bi(rbm)->bi_bh);
 	gfs2_setbit(rbm, true, dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED);
 	block++;
 	while (*n < elen) {
 		ret = gfs2_rbm_from_block(&pos, block);
 		if (ret || gfs2_testbit(&pos) != GFS2_BLKST_FREE)
 			break;
-		gfs2_trans_add_meta(pos.rgd->rd_gl, pos.bi->bi_bh);
+		gfs2_trans_add_meta(pos.rgd->rd_gl, rbm_bi(&pos)->bi_bh);
 		gfs2_setbit(&pos, true, GFS2_BLKST_USED);
 		(*n)++;
 		block++;
@@ -2001,6 +2031,7 @@
 				     u32 blen, unsigned char new_state)
 {
 	struct gfs2_rbm rbm;
+	struct gfs2_bitmap *bi;
 
 	rbm.rgd = gfs2_blk2rgrpd(sdp, bstart, 1);
 	if (!rbm.rgd) {
@@ -2011,15 +2042,15 @@
 
 	while (blen--) {
 		gfs2_rbm_from_block(&rbm, bstart);
+		bi = rbm_bi(&rbm);
 		bstart++;
-		if (!rbm.bi->bi_clone) {
-			rbm.bi->bi_clone = kmalloc(rbm.bi->bi_bh->b_size,
-						   GFP_NOFS | __GFP_NOFAIL);
-			memcpy(rbm.bi->bi_clone + rbm.bi->bi_offset,
-			       rbm.bi->bi_bh->b_data + rbm.bi->bi_offset,
-			       rbm.bi->bi_len);
+		if (!bi->bi_clone) {
+			bi->bi_clone = kmalloc(bi->bi_bh->b_size,
+					       GFP_NOFS | __GFP_NOFAIL);
+			memcpy(bi->bi_clone + bi->bi_offset,
+			       bi->bi_bh->b_data + bi->bi_offset, bi->bi_len);
 		}
-		gfs2_trans_add_meta(rbm.rgd->rd_gl, rbm.bi->bi_bh);
+		gfs2_trans_add_meta(rbm.rgd->rd_gl, bi->bi_bh);
 		gfs2_setbit(&rbm, false, new_state);
 	}
 
@@ -2103,6 +2134,35 @@
 }
 
 /**
+ * gfs2_set_alloc_start - Set starting point for block allocation
+ * @rbm: The rbm which will be set to the required location
+ * @ip: The gfs2 inode
+ * @dinode: Flag to say if allocation includes a new inode
+ *
+ * This sets the starting point from the reservation if one is active
+ * otherwise it falls back to guessing a start point based on the
+ * inode's goal block or the last allocation point in the rgrp.
+ */
+
+static void gfs2_set_alloc_start(struct gfs2_rbm *rbm,
+				 const struct gfs2_inode *ip, bool dinode)
+{
+	u64 goal;
+
+	if (gfs2_rs_active(ip->i_res)) {
+		*rbm = ip->i_res->rs_rbm;
+		return;
+	}
+
+	if (!dinode && rgrp_contains_block(rbm->rgd, ip->i_goal))
+		goal = ip->i_goal;
+	else
+		goal = rbm->rgd->rd_last_alloc + rbm->rgd->rd_data0;
+
+	gfs2_rbm_from_block(rbm, goal);
+}
+
+/**
  * gfs2_alloc_blocks - Allocate one or more blocks of data and/or a dinode
  * @ip: the inode to allocate the block for
  * @bn: Used to return the starting block number
@@ -2120,22 +2180,14 @@
 	struct buffer_head *dibh;
 	struct gfs2_rbm rbm = { .rgd = ip->i_rgd, };
 	unsigned int ndata;
-	u64 goal;
 	u64 block; /* block, within the file system scope */
 	int error;
 
-	if (gfs2_rs_active(ip->i_res))
-		goal = gfs2_rbm_to_block(&ip->i_res->rs_rbm);
-	else if (!dinode && rgrp_contains_block(rbm.rgd, ip->i_goal))
-		goal = ip->i_goal;
-	else
-		goal = rbm.rgd->rd_last_alloc + rbm.rgd->rd_data0;
-
-	gfs2_rbm_from_block(&rbm, goal);
+	gfs2_set_alloc_start(&rbm, ip, dinode);
 	error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, 0, ip, false);
 
 	if (error == -ENOSPC) {
-		gfs2_rbm_from_block(&rbm, goal);
+		gfs2_set_alloc_start(&rbm, ip, dinode);
 		error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, 0, NULL, false);
 	}
 
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
index 5b3f4a8..3a10d2f 100644
--- a/fs/gfs2/rgrp.h
+++ b/fs/gfs2/rgrp.h
@@ -40,7 +40,7 @@
 extern struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip);
 
 #define GFS2_AF_ORLOV 1
-extern int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested, u32 flags);
+extern int gfs2_inplace_reserve(struct gfs2_inode *ip, const struct gfs2_alloc_parms *ap);
 extern void gfs2_inplace_release(struct gfs2_inode *ip);
 
 extern int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *n,
@@ -48,7 +48,7 @@
 
 extern int gfs2_rs_alloc(struct gfs2_inode *ip);
 extern void gfs2_rs_deltree(struct gfs2_blkreserv *rs);
-extern void gfs2_rs_delete(struct gfs2_inode *ip);
+extern void gfs2_rs_delete(struct gfs2_inode *ip, atomic_t *wcount);
 extern void __gfs2_free_blocks(struct gfs2_inode *ip, u64 bstart, u32 blen, int meta);
 extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen);
 extern void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip);
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index e5639de..35da5b1 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -1526,7 +1526,7 @@
 out:
 	/* Case 3 starts here */
 	truncate_inode_pages(&inode->i_data, 0);
-	gfs2_rs_delete(ip);
+	gfs2_rs_delete(ip, NULL);
 	gfs2_ordered_del_inode(ip);
 	clear_inode(inode);
 	gfs2_dir_hash_inval(ip);
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c
index aa5c480..d09f6ed 100644
--- a/fs/gfs2/sys.c
+++ b/fs/gfs2/sys.c
@@ -587,7 +587,6 @@
 TUNE_ATTR(complain_secs, 0);
 TUNE_ATTR(statfs_slow, 0);
 TUNE_ATTR(new_files_jdata, 0);
-TUNE_ATTR(quota_simul_sync, 1);
 TUNE_ATTR(statfs_quantum, 1);
 TUNE_ATTR_3(quota_scale, quota_scale_show, quota_scale_store);
 
@@ -597,7 +596,6 @@
 	&tune_attr_max_readahead.attr,
 	&tune_attr_complain_secs.attr,
 	&tune_attr_statfs_slow.attr,
-	&tune_attr_quota_simul_sync.attr,
 	&tune_attr_statfs_quantum.attr,
 	&tune_attr_quota_scale.attr,
 	&tune_attr_new_files_jdata.attr,
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c
index 6402fb6..f7109f6 100644
--- a/fs/gfs2/util.c
+++ b/fs/gfs2/util.c
@@ -268,23 +268,3 @@
 	return rv;
 }
 
-void gfs2_icbit_munge(struct gfs2_sbd *sdp, unsigned char **bitmap,
-		      unsigned int bit, int new_value)
-{
-	unsigned int c, o, b = bit;
-	int old_value;
-
-	c = b / (8 * PAGE_SIZE);
-	b %= 8 * PAGE_SIZE;
-	o = b / 8;
-	b %= 8;
-
-	old_value = (bitmap[c][o] & (1 << b));
-	gfs2_assert_withdraw(sdp, !old_value != !new_value);
-
-	if (new_value)
-		bitmap[c][o] |= 1 << b;
-	else
-		bitmap[c][o] &= ~(1 << b);
-}
-
diff --git a/fs/gfs2/util.h b/fs/gfs2/util.h
index 8053573..b7ffb09 100644
--- a/fs/gfs2/util.h
+++ b/fs/gfs2/util.h
@@ -164,8 +164,6 @@
 #define gfs2_tune_get(sdp, field) \
 gfs2_tune_get_i(&(sdp)->sd_tune, &(sdp)->sd_tune.field)
 
-void gfs2_icbit_munge(struct gfs2_sbd *sdp, unsigned char **bitmap,
-		      unsigned int bit, int new_value);
 int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...);
 
 #endif /* __UTIL_DOT_H__ */
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
index ecd37f3..8c6a6f6 100644
--- a/fs/gfs2/xattr.c
+++ b/fs/gfs2/xattr.c
@@ -723,6 +723,7 @@
 			     unsigned int blks,
 			     ea_skeleton_call_t skeleton_call, void *private)
 {
+	struct gfs2_alloc_parms ap = { .target = blks };
 	struct buffer_head *dibh;
 	int error;
 
@@ -734,7 +735,7 @@
 	if (error)
 		return error;
 
-	error = gfs2_inplace_reserve(ip, blks, 0);
+	error = gfs2_inplace_reserve(ip, &ap);
 	if (error)
 		goto out_gunlock_q;
 
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index be0c39b..aa603e0 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -26,7 +26,6 @@
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/hrtimer.h>
-#include <linux/backing-dev.h>
 
 static void __journal_temp_unlink_buffer(struct journal_head *jh);
 
@@ -100,10 +99,11 @@
 
 alloc_transaction:
 	if (!journal->j_running_transaction) {
-		new_transaction = kzalloc(sizeof(*new_transaction), GFP_NOFS);
+		new_transaction = kzalloc(sizeof(*new_transaction),
+						GFP_NOFS|__GFP_NOFAIL);
 		if (!new_transaction) {
-			congestion_wait(BLK_RW_ASYNC, HZ/50);
-			goto alloc_transaction;
+			ret = -ENOMEM;
+			goto out;
 		}
 	}
 
diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
index c1a3e60..7f464c5 100644
--- a/fs/jfs/jfs_inode.c
+++ b/fs/jfs/jfs_inode.c
@@ -95,7 +95,7 @@
 
 	if (insert_inode_locked(inode) < 0) {
 		rc = -EINVAL;
-		goto fail_unlock;
+		goto fail_put;
 	}
 
 	inode_init_owner(inode, parent, mode);
@@ -156,7 +156,6 @@
 fail_drop:
 	dquot_drop(inode);
 	inode->i_flags |= S_NOQUOTA;
-fail_unlock:
 	clear_nlink(inode);
 	unlock_new_inode(inode);
 fail_put:
diff --git a/fs/minix/Kconfig b/fs/minix/Kconfig
index 6624684..f2a0cfc 100644
--- a/fs/minix/Kconfig
+++ b/fs/minix/Kconfig
@@ -18,7 +18,7 @@
 
 config MINIX_FS_NATIVE_ENDIAN
 	def_bool MINIX_FS
-	depends on H8300 || M32R || MICROBLAZE || MIPS || S390 || SUPERH || SPARC || XTENSA || (M68K && !MMU)
+	depends on M32R || MICROBLAZE || MIPS || S390 || SUPERH || SPARC || XTENSA || (M68K && !MMU)
 
 config MINIX_FS_BIG_ENDIAN_16BIT_INDEXED
 	def_bool MINIX_FS
diff --git a/fs/namei.c b/fs/namei.c
index 251178a..e029a4c 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2258,10 +2258,11 @@
  * path_mountpoint - look up a path to be umounted
  * @dfd:	directory file descriptor to start walk from
  * @name:	full pathname to walk
+ * @path:	pointer to container for result
  * @flags:	lookup flags
  *
  * Look up the given name, but don't attempt to revalidate the last component.
- * Returns 0 and "path" will be valid on success; Retuns error otherwise.
+ * Returns 0 and "path" will be valid on success; Returns error otherwise.
  */
 static int
 path_mountpoint(int dfd, const char *name, struct path *path, unsigned int flags)
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index b5e80b0..38c1768 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -140,6 +140,17 @@
 	  If the NFS client is unchanged from the upstream kernel, this
 	  option should be set to the default "kernel.org".
 
+config NFS_V4_1_MIGRATION
+	bool "NFSv4.1 client support for migration"
+	depends on NFS_V4_1
+	default n
+	help
+	  This option makes the NFS client advertise to NFSv4.1 servers that
+          it can support NFSv4 migration.
+
+          The NFSv4.1 pieces of the Linux NFSv4 migration implementation are
+          still experimental.  If you are not an NFSv4 developer, say N here.
+
 config NFS_V4_SECURITY_LABEL
 	bool
 	depends on NFS_V4_2 && SECURITY
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 67cd732..073b4cf 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -164,8 +164,7 @@
 		svc_xprt_put(serv->sv_bc_xprt);
 		serv->sv_bc_xprt = NULL;
 	}
-	dprintk("--> %s return %ld\n", __func__,
-		IS_ERR(rqstp) ? PTR_ERR(rqstp) : 0);
+	dprintk("--> %s return %d\n", __func__, PTR_ERR_OR_ZERO(rqstp));
 	return rqstp;
 }
 
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 2dceee4..1d09289 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -590,6 +590,8 @@
 
 	if (test_bit(NFS_CS_DISCRTRY, &clp->cl_flags))
 		args.flags |= RPC_CLNT_CREATE_DISCRTRY;
+	if (test_bit(NFS_CS_NO_RETRANS_TIMEOUT, &clp->cl_flags))
+		args.flags |= RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT;
 	if (test_bit(NFS_CS_NORESVPORT, &clp->cl_flags))
 		args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
 	if (test_bit(NFS_CS_INFINITE_SLOTS, &clp->cl_flags))
@@ -784,8 +786,10 @@
 		goto error;
 
 	server->port = data->nfs_server.port;
+	server->auth_info = data->auth_info;
 
-	error = nfs_init_server_rpcclient(server, &timeparms, data->auth_flavors[0]);
+	error = nfs_init_server_rpcclient(server, &timeparms,
+					  data->selected_flavor);
 	if (error < 0)
 		goto error;
 
@@ -926,6 +930,7 @@
 	target->acdirmax = source->acdirmax;
 	target->caps = source->caps;
 	target->options = source->options;
+	target->auth_info = source->auth_info;
 }
 EXPORT_SYMBOL_GPL(nfs_server_copy_userdata);
 
@@ -943,7 +948,7 @@
 }
 EXPORT_SYMBOL_GPL(nfs_server_insert_lists);
 
-static void nfs_server_remove_lists(struct nfs_server *server)
+void nfs_server_remove_lists(struct nfs_server *server)
 {
 	struct nfs_client *clp = server->nfs_client;
 	struct nfs_net *nn;
@@ -960,6 +965,7 @@
 
 	synchronize_rcu();
 }
+EXPORT_SYMBOL_GPL(nfs_server_remove_lists);
 
 /*
  * Allocate and initialise a server record
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 8b3dd71..812154a 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1125,7 +1125,13 @@
 	if (inode && S_ISDIR(inode->i_mode)) {
 		/* Purge readdir caches. */
 		nfs_zap_caches(inode);
-		if (dentry->d_flags & DCACHE_DISCONNECTED)
+		/*
+		 * We can't d_drop the root of a disconnected tree:
+		 * its d_hash is on the s_anon list and d_drop() would hide
+		 * it from shrink_dcache_for_unmount(), leading to busy
+		 * inodes on unmount and further oopses.
+		 */
+		if (IS_ROOT(dentry))
 			goto out_valid;
 	}
 	/* If we have submounts, don't unhash ! */
@@ -1361,7 +1367,7 @@
 
 static int do_open(struct inode *inode, struct file *filp)
 {
-	nfs_fscache_set_inode_cookie(inode, filp);
+	nfs_fscache_open_file(inode, filp);
 	return 0;
 }
 
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
index 24d1d1c..3ef01f0 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
@@ -39,7 +39,7 @@
 	/* create a cache index for looking up filehandles */
 	clp->fscache = fscache_acquire_cookie(nfs_fscache_netfs.primary_index,
 					      &nfs_fscache_server_index_def,
-					      clp);
+					      clp, true);
 	dfprintk(FSCACHE, "NFS: get client cookie (0x%p/0x%p)\n",
 		 clp, clp->fscache);
 }
@@ -139,7 +139,7 @@
 	/* create a cache index for looking up filehandles */
 	nfss->fscache = fscache_acquire_cookie(nfss->nfs_client->fscache,
 					       &nfs_fscache_super_index_def,
-					       nfss);
+					       nfss, true);
 	dfprintk(FSCACHE, "NFS: get superblock cookie (0x%p/0x%p)\n",
 		 nfss, nfss->fscache);
 	return;
@@ -178,163 +178,79 @@
 /*
  * Initialise the per-inode cache cookie pointer for an NFS inode.
  */
-void nfs_fscache_init_inode_cookie(struct inode *inode)
+void nfs_fscache_init_inode(struct inode *inode)
 {
-	NFS_I(inode)->fscache = NULL;
-	if (S_ISREG(inode->i_mode))
-		set_bit(NFS_INO_FSCACHE, &NFS_I(inode)->flags);
-}
-
-/*
- * Get the per-inode cache cookie for an NFS inode.
- */
-static void nfs_fscache_enable_inode_cookie(struct inode *inode)
-{
-	struct super_block *sb = inode->i_sb;
 	struct nfs_inode *nfsi = NFS_I(inode);
 
-	if (nfsi->fscache || !NFS_FSCACHE(inode))
+	nfsi->fscache = NULL;
+	if (!S_ISREG(inode->i_mode))
 		return;
-
-	if ((NFS_SB(sb)->options & NFS_OPTION_FSCACHE)) {
-		nfsi->fscache = fscache_acquire_cookie(
-			NFS_SB(sb)->fscache,
-			&nfs_fscache_inode_object_def,
-			nfsi);
-
-		dfprintk(FSCACHE, "NFS: get FH cookie (0x%p/0x%p/0x%p)\n",
-			 sb, nfsi, nfsi->fscache);
-	}
+	nfsi->fscache = fscache_acquire_cookie(NFS_SB(inode->i_sb)->fscache,
+					       &nfs_fscache_inode_object_def,
+					       nfsi, false);
 }
 
 /*
  * Release a per-inode cookie.
  */
-void nfs_fscache_release_inode_cookie(struct inode *inode)
+void nfs_fscache_clear_inode(struct inode *inode)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
+	struct fscache_cookie *cookie = nfs_i_fscache(inode);
 
-	dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n",
-		 nfsi, nfsi->fscache);
+	dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", nfsi, cookie);
 
-	fscache_relinquish_cookie(nfsi->fscache, 0);
+	fscache_relinquish_cookie(cookie, false);
 	nfsi->fscache = NULL;
 }
 
-/*
- * Retire a per-inode cookie, destroying the data attached to it.
- */
-void nfs_fscache_zap_inode_cookie(struct inode *inode)
+static bool nfs_fscache_can_enable(void *data)
 {
-	struct nfs_inode *nfsi = NFS_I(inode);
+	struct inode *inode = data;
 
-	dfprintk(FSCACHE, "NFS: zapping cookie (0x%p/0x%p)\n",
-		 nfsi, nfsi->fscache);
-
-	fscache_relinquish_cookie(nfsi->fscache, 1);
-	nfsi->fscache = NULL;
+	return !inode_is_open_for_write(inode);
 }
 
 /*
- * Turn off the cache with regard to a per-inode cookie if opened for writing,
- * invalidating all the pages in the page cache relating to the associated
- * inode to clear the per-page caching.
+ * Enable or disable caching for a file that is being opened as appropriate.
+ * The cookie is allocated when the inode is initialised, but is not enabled at
+ * that time.  Enablement is deferred to file-open time to avoid stat() and
+ * access() thrashing the cache.
+ *
+ * For now, with NFS, only regular files that are open read-only will be able
+ * to use the cache.
+ *
+ * We enable the cache for an inode if we open it read-only and it isn't
+ * currently open for writing.  We disable the cache if the inode is open
+ * write-only.
+ *
+ * The caller uses the file struct to pin i_writecount on the inode before
+ * calling us when a file is opened for writing, so we can make use of that.
+ *
+ * Note that this may be invoked multiple times in parallel by parallel
+ * nfs_open() functions.
  */
-static void nfs_fscache_disable_inode_cookie(struct inode *inode)
+void nfs_fscache_open_file(struct inode *inode, struct file *filp)
 {
-	clear_bit(NFS_INO_FSCACHE, &NFS_I(inode)->flags);
+	struct nfs_inode *nfsi = NFS_I(inode);
+	struct fscache_cookie *cookie = nfs_i_fscache(inode);
 
-	if (NFS_I(inode)->fscache) {
-		dfprintk(FSCACHE,
-			 "NFS: nfsi 0x%p turning cache off\n", NFS_I(inode));
+	if (!fscache_cookie_valid(cookie))
+		return;
 
-		/* Need to uncache any pages attached to this inode that
-		 * fscache knows about before turning off the cache.
-		 */
-		fscache_uncache_all_inode_pages(NFS_I(inode)->fscache, inode);
-		nfs_fscache_zap_inode_cookie(inode);
+	if (inode_is_open_for_write(inode)) {
+		dfprintk(FSCACHE, "NFS: nfsi 0x%p disabling cache\n", nfsi);
+		clear_bit(NFS_INO_FSCACHE, &nfsi->flags);
+		fscache_disable_cookie(cookie, true);
+		fscache_uncache_all_inode_pages(cookie, inode);
+	} else {
+		dfprintk(FSCACHE, "NFS: nfsi 0x%p enabling cache\n", nfsi);
+		fscache_enable_cookie(cookie, nfs_fscache_can_enable, inode);
+		if (fscache_cookie_enabled(cookie))
+			set_bit(NFS_INO_FSCACHE, &NFS_I(inode)->flags);
 	}
 }
-
-/*
- * wait_on_bit() sleep function for uninterruptible waiting
- */
-static int nfs_fscache_wait_bit(void *flags)
-{
-	schedule();
-	return 0;
-}
-
-/*
- * Lock against someone else trying to also acquire or relinquish a cookie
- */
-static inline void nfs_fscache_inode_lock(struct inode *inode)
-{
-	struct nfs_inode *nfsi = NFS_I(inode);
-
-	while (test_and_set_bit(NFS_INO_FSCACHE_LOCK, &nfsi->flags))
-		wait_on_bit(&nfsi->flags, NFS_INO_FSCACHE_LOCK,
-			    nfs_fscache_wait_bit, TASK_UNINTERRUPTIBLE);
-}
-
-/*
- * Unlock cookie management lock
- */
-static inline void nfs_fscache_inode_unlock(struct inode *inode)
-{
-	struct nfs_inode *nfsi = NFS_I(inode);
-
-	smp_mb__before_clear_bit();
-	clear_bit(NFS_INO_FSCACHE_LOCK, &nfsi->flags);
-	smp_mb__after_clear_bit();
-	wake_up_bit(&nfsi->flags, NFS_INO_FSCACHE_LOCK);
-}
-
-/*
- * Decide if we should enable or disable local caching for this inode.
- * - For now, with NFS, only regular files that are open read-only will be able
- *   to use the cache.
- * - May be invoked multiple times in parallel by parallel nfs_open() functions.
- */
-void nfs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
-{
-	if (NFS_FSCACHE(inode)) {
-		nfs_fscache_inode_lock(inode);
-		if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
-			nfs_fscache_disable_inode_cookie(inode);
-		else
-			nfs_fscache_enable_inode_cookie(inode);
-		nfs_fscache_inode_unlock(inode);
-	}
-}
-EXPORT_SYMBOL_GPL(nfs_fscache_set_inode_cookie);
-
-/*
- * Replace a per-inode cookie due to revalidation detecting a file having
- * changed on the server.
- */
-void nfs_fscache_reset_inode_cookie(struct inode *inode)
-{
-	struct nfs_inode *nfsi = NFS_I(inode);
-	struct nfs_server *nfss = NFS_SERVER(inode);
-	NFS_IFDEBUG(struct fscache_cookie *old = nfsi->fscache);
-
-	nfs_fscache_inode_lock(inode);
-	if (nfsi->fscache) {
-		/* retire the current fscache cache and get a new one */
-		fscache_relinquish_cookie(nfsi->fscache, 1);
-
-		nfsi->fscache = fscache_acquire_cookie(
-			nfss->nfs_client->fscache,
-			&nfs_fscache_inode_object_def,
-			nfsi);
-
-		dfprintk(FSCACHE,
-			 "NFS: revalidation new cookie (0x%p/0x%p/0x%p/0x%p)\n",
-			 nfss, nfsi, old, nfsi->fscache);
-	}
-	nfs_fscache_inode_unlock(inode);
-}
+EXPORT_SYMBOL_GPL(nfs_fscache_open_file);
 
 /*
  * Release the caching state associated with a page, if the page isn't busy
@@ -344,12 +260,11 @@
 int nfs_fscache_release_page(struct page *page, gfp_t gfp)
 {
 	if (PageFsCache(page)) {
-		struct nfs_inode *nfsi = NFS_I(page->mapping->host);
-		struct fscache_cookie *cookie = nfsi->fscache;
+		struct fscache_cookie *cookie = nfs_i_fscache(page->mapping->host);
 
 		BUG_ON(!cookie);
 		dfprintk(FSCACHE, "NFS: fscache releasepage (0x%p/0x%p/0x%p)\n",
-			 cookie, page, nfsi);
+			 cookie, page, NFS_I(page->mapping->host));
 
 		if (!fscache_maybe_release_page(cookie, page, gfp))
 			return 0;
@@ -367,13 +282,12 @@
  */
 void __nfs_fscache_invalidate_page(struct page *page, struct inode *inode)
 {
-	struct nfs_inode *nfsi = NFS_I(inode);
-	struct fscache_cookie *cookie = nfsi->fscache;
+	struct fscache_cookie *cookie = nfs_i_fscache(inode);
 
 	BUG_ON(!cookie);
 
 	dfprintk(FSCACHE, "NFS: fscache invalidatepage (0x%p/0x%p/0x%p)\n",
-		 cookie, page, nfsi);
+		 cookie, page, NFS_I(inode));
 
 	fscache_wait_on_page_write(cookie, page);
 
@@ -417,9 +331,9 @@
 
 	dfprintk(FSCACHE,
 		 "NFS: readpage_from_fscache(fsc:%p/p:%p(i:%lx f:%lx)/0x%p)\n",
-		 NFS_I(inode)->fscache, page, page->index, page->flags, inode);
+		 nfs_i_fscache(inode), page, page->index, page->flags, inode);
 
-	ret = fscache_read_or_alloc_page(NFS_I(inode)->fscache,
+	ret = fscache_read_or_alloc_page(nfs_i_fscache(inode),
 					 page,
 					 nfs_readpage_from_fscache_complete,
 					 ctx,
@@ -459,9 +373,9 @@
 	int ret;
 
 	dfprintk(FSCACHE, "NFS: nfs_getpages_from_fscache (0x%p/%u/0x%p)\n",
-		 NFS_I(inode)->fscache, npages, inode);
+		 nfs_i_fscache(inode), npages, inode);
 
-	ret = fscache_read_or_alloc_pages(NFS_I(inode)->fscache,
+	ret = fscache_read_or_alloc_pages(nfs_i_fscache(inode),
 					  mapping, pages, nr_pages,
 					  nfs_readpage_from_fscache_complete,
 					  ctx,
@@ -506,15 +420,15 @@
 
 	dfprintk(FSCACHE,
 		 "NFS: readpage_to_fscache(fsc:%p/p:%p(i:%lx f:%lx)/%d)\n",
-		 NFS_I(inode)->fscache, page, page->index, page->flags, sync);
+		 nfs_i_fscache(inode), page, page->index, page->flags, sync);
 
-	ret = fscache_write_page(NFS_I(inode)->fscache, page, GFP_KERNEL);
+	ret = fscache_write_page(nfs_i_fscache(inode), page, GFP_KERNEL);
 	dfprintk(FSCACHE,
 		 "NFS:     readpage_to_fscache: p:%p(i:%lu f:%lx) ret %d\n",
 		 page, page->index, page->flags, ret);
 
 	if (ret != 0) {
-		fscache_uncache_page(NFS_I(inode)->fscache, page);
+		fscache_uncache_page(nfs_i_fscache(inode), page);
 		nfs_add_fscache_stats(inode,
 				      NFSIOS_FSCACHE_PAGES_WRITTEN_FAIL, 1);
 		nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_UNCACHED, 1);
diff --git a/fs/nfs/fscache.h b/fs/nfs/fscache.h
index 4ecb766..d7fe3e7 100644
--- a/fs/nfs/fscache.h
+++ b/fs/nfs/fscache.h
@@ -76,11 +76,9 @@
 extern void nfs_fscache_get_super_cookie(struct super_block *, const char *, int);
 extern void nfs_fscache_release_super_cookie(struct super_block *);
 
-extern void nfs_fscache_init_inode_cookie(struct inode *);
-extern void nfs_fscache_release_inode_cookie(struct inode *);
-extern void nfs_fscache_zap_inode_cookie(struct inode *);
-extern void nfs_fscache_set_inode_cookie(struct inode *, struct file *);
-extern void nfs_fscache_reset_inode_cookie(struct inode *);
+extern void nfs_fscache_init_inode(struct inode *);
+extern void nfs_fscache_clear_inode(struct inode *);
+extern void nfs_fscache_open_file(struct inode *, struct file *);
 
 extern void __nfs_fscache_invalidate_page(struct page *, struct inode *);
 extern int nfs_fscache_release_page(struct page *, gfp_t);
@@ -187,12 +185,10 @@
 
 static inline void nfs_fscache_release_super_cookie(struct super_block *sb) {}
 
-static inline void nfs_fscache_init_inode_cookie(struct inode *inode) {}
-static inline void nfs_fscache_release_inode_cookie(struct inode *inode) {}
-static inline void nfs_fscache_zap_inode_cookie(struct inode *inode) {}
-static inline void nfs_fscache_set_inode_cookie(struct inode *inode,
-						struct file *filp) {}
-static inline void nfs_fscache_reset_inode_cookie(struct inode *inode) {}
+static inline void nfs_fscache_init_inode(struct inode *inode) {}
+static inline void nfs_fscache_clear_inode(struct inode *inode) {}
+static inline void nfs_fscache_open_file(struct inode *inode,
+					 struct file *filp) {}
 
 static inline int nfs_fscache_release_page(struct page *page, gfp_t gfp)
 {
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index eda8879..18ab2da 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -122,7 +122,7 @@
 	WARN_ON_ONCE(!list_empty(&NFS_I(inode)->open_files));
 	nfs_zap_acl_cache(inode);
 	nfs_access_zap_cache(inode);
-	nfs_fscache_release_inode_cookie(inode);
+	nfs_fscache_clear_inode(inode);
 }
 EXPORT_SYMBOL_GPL(nfs_clear_inode);
 
@@ -274,12 +274,6 @@
 	if (label == NULL)
 		return;
 
-	if (nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL) == 0)
-		return;
-
-	if (NFS_SERVER(inode)->nfs_client->cl_minorversion < 2)
-		return;
-
 	if ((fattr->valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL) && inode->i_security) {
 		error = security_inode_notifysecctx(inode, label->label,
 				label->len);
@@ -459,7 +453,7 @@
 		nfsi->attrtimeo_timestamp = now;
 		nfsi->access_cache = RB_ROOT;
 
-		nfs_fscache_init_inode_cookie(inode);
+		nfs_fscache_init_inode(inode);
 
 		unlock_new_inode(inode);
 	} else
@@ -854,7 +848,7 @@
 		return PTR_ERR(ctx);
 	nfs_file_set_open_context(filp, ctx);
 	put_nfs_open_context(ctx);
-	nfs_fscache_set_inode_cookie(inode, filp);
+	nfs_fscache_open_file(inode, filp);
 	return 0;
 }
 
@@ -923,6 +917,8 @@
 	if (nfsi->cache_validity & NFS_INO_INVALID_ACL)
 		nfs_zap_acl_cache(inode);
 
+	nfs_setsecurity(inode, fattr, label);
+
 	dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n",
 		inode->i_sb->s_id,
 		(long long)NFS_FILEID(inode));
@@ -1209,6 +1205,7 @@
 	 * not on the result */
 	return nfs_fhandle_hash(fh);
 }
+EXPORT_SYMBOL_GPL(_nfs_display_fhandle_hash);
 
 /*
  * _nfs_display_fhandle - display an NFS file handle on the console
@@ -1253,6 +1250,7 @@
 		}
 	}
 }
+EXPORT_SYMBOL_GPL(_nfs_display_fhandle);
 #endif
 
 /**
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 38da8c2..bca6a3e 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -88,8 +88,8 @@
 	unsigned int		namlen;
 	unsigned int		options;
 	unsigned int		bsize;
-	unsigned int		auth_flavor_len;
-	rpc_authflavor_t	auth_flavors[1];
+	struct nfs_auth_info	auth_info;
+	rpc_authflavor_t	selected_flavor;
 	char			*client_address;
 	unsigned int		version;
 	unsigned int		minorversion;
@@ -154,6 +154,7 @@
 				  rpc_authflavor_t);
 int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *, struct nfs_fattr *);
 void nfs_server_insert_lists(struct nfs_server *);
+void nfs_server_remove_lists(struct nfs_server *);
 void nfs_init_timeout_values(struct rpc_timeout *, int, unsigned int, unsigned int);
 int nfs_init_server_rpcclient(struct nfs_server *, const struct rpc_timeout *t,
 		rpc_authflavor_t);
@@ -174,6 +175,8 @@
 					struct nfs_subversion *);
 extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *,
 						      struct nfs_fh *);
+extern int nfs4_update_server(struct nfs_server *server, const char *hostname,
+					struct sockaddr *sap, size_t salen);
 extern void nfs_free_server(struct nfs_server *server);
 extern struct nfs_server *nfs_clone_server(struct nfs_server *,
 					   struct nfs_fh *,
@@ -323,6 +326,7 @@
 extern struct file_system_type nfs4_xdev_fs_type;
 extern struct file_system_type nfs4_referral_fs_type;
 #endif
+bool nfs_auth_info_match(const struct nfs_auth_info *, rpc_authflavor_t);
 struct dentry *nfs_try_mount(int, const char *, struct nfs_mount_info *,
 			struct nfs_subversion *);
 void nfs_initialise_sb(struct super_block *);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 28842ab..3ce79b0 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -29,6 +29,8 @@
 	NFS4CLNT_SERVER_SCOPE_MISMATCH,
 	NFS4CLNT_PURGE_STATE,
 	NFS4CLNT_BIND_CONN_TO_SESSION,
+	NFS4CLNT_MOVED,
+	NFS4CLNT_LEASE_MOVED,
 };
 
 #define NFS4_RENEW_TIMEOUT		0x01
@@ -50,6 +52,7 @@
 	const struct nfs4_state_recovery_ops *reboot_recovery_ops;
 	const struct nfs4_state_recovery_ops *nograce_recovery_ops;
 	const struct nfs4_state_maintenance_ops *state_renewal_ops;
+	const struct nfs4_mig_recovery_ops *mig_recovery_ops;
 };
 
 #define NFS_SEQID_CONFIRMED 1
@@ -203,6 +206,12 @@
 	int (*renew_lease)(struct nfs_client *, struct rpc_cred *);
 };
 
+struct nfs4_mig_recovery_ops {
+	int (*get_locations)(struct inode *, struct nfs4_fs_locations *,
+		struct page *, struct rpc_cred *);
+	int (*fsid_present)(struct inode *, struct rpc_cred *);
+};
+
 extern const struct dentry_operations nfs4_dentry_operations;
 
 /* dir.c */
@@ -213,10 +222,11 @@
 extern struct file_system_type nfs4_fs_type;
 
 /* nfs4namespace.c */
-rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *);
 struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *);
 struct vfsmount *nfs4_submount(struct nfs_server *, struct dentry *,
 			       struct nfs_fh *, struct nfs_fattr *);
+int nfs4_replace_transport(struct nfs_server *server,
+				const struct nfs4_fs_locations *locations);
 
 /* nfs4proc.c */
 extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *);
@@ -231,6 +241,9 @@
 extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
 extern int nfs4_proc_fs_locations(struct rpc_clnt *, struct inode *, const struct qstr *,
 				  struct nfs4_fs_locations *, struct page *);
+extern int nfs4_proc_get_locations(struct inode *, struct nfs4_fs_locations *,
+		struct page *page, struct rpc_cred *);
+extern int nfs4_proc_fsid_present(struct inode *, struct rpc_cred *);
 extern struct rpc_clnt *nfs4_proc_lookup_mountpoint(struct inode *, struct qstr *,
 			    struct nfs_fh *, struct nfs_fattr *);
 extern int nfs4_proc_secinfo(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *);
@@ -411,6 +424,8 @@
 extern void nfs4_schedule_state_manager(struct nfs_client *);
 extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp);
 extern int nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *);
+extern int nfs4_schedule_migration_recovery(const struct nfs_server *);
+extern void nfs4_schedule_lease_moved_recovery(struct nfs_client *);
 extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags);
 extern void nfs41_handle_server_scope(struct nfs_client *,
 				      struct nfs41_server_scope **);
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index a860ab5..b4a160a 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -197,6 +197,7 @@
 	clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
 	clp->cl_minorversion = cl_init->minorversion;
 	clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion];
+	clp->cl_mig_gen = 1;
 	return clp;
 
 error:
@@ -368,6 +369,7 @@
 	if (clp->cl_minorversion != 0)
 		__set_bit(NFS_CS_INFINITE_SLOTS, &clp->cl_flags);
 	__set_bit(NFS_CS_DISCRTRY, &clp->cl_flags);
+	__set_bit(NFS_CS_NO_RETRANS_TIMEOUT, &clp->cl_flags);
 	error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_GSS_KRB5I);
 	if (error == -EINVAL)
 		error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX);
@@ -924,7 +926,7 @@
 	dprintk("Server FSID: %llx:%llx\n",
 			(unsigned long long) server->fsid.major,
 			(unsigned long long) server->fsid.minor);
-	dprintk("Mount FH: %d\n", mntfh->size);
+	nfs_display_fhandle(mntfh, "Pseudo-fs root FH");
 
 	nfs4_session_set_rwsize(server);
 
@@ -947,9 +949,8 @@
  * Create a version 4 volume record
  */
 static int nfs4_init_server(struct nfs_server *server,
-		const struct nfs_parsed_mount_data *data)
+		struct nfs_parsed_mount_data *data)
 {
-	rpc_authflavor_t pseudoflavor = RPC_AUTH_UNIX;
 	struct rpc_timeout timeparms;
 	int error;
 
@@ -961,9 +962,15 @@
 	/* Initialise the client representation from the mount data */
 	server->flags = data->flags;
 	server->options = data->options;
+	server->auth_info = data->auth_info;
 
-	if (data->auth_flavor_len >= 1)
-		pseudoflavor = data->auth_flavors[0];
+	/* Use the first specified auth flavor. If this flavor isn't
+	 * allowed by the server, use the SECINFO path to try the
+	 * other specified flavors */
+	if (data->auth_info.flavor_len >= 1)
+		data->selected_flavor = data->auth_info.flavors[0];
+	else
+		data->selected_flavor = RPC_AUTH_UNIX;
 
 	/* Get a client record */
 	error = nfs4_set_client(server,
@@ -971,7 +978,7 @@
 			(const struct sockaddr *)&data->nfs_server.address,
 			data->nfs_server.addrlen,
 			data->client_address,
-			pseudoflavor,
+			data->selected_flavor,
 			data->nfs_server.protocol,
 			&timeparms,
 			data->minorversion,
@@ -991,7 +998,8 @@
 
 	server->port = data->nfs_server.port;
 
-	error = nfs_init_server_rpcclient(server, &timeparms, pseudoflavor);
+	error = nfs_init_server_rpcclient(server, &timeparms,
+					  data->selected_flavor);
 
 error:
 	/* Done */
@@ -1018,7 +1026,7 @@
 	if (!server)
 		return ERR_PTR(-ENOMEM);
 
-	auth_probe = mount_info->parsed->auth_flavor_len < 1;
+	auth_probe = mount_info->parsed->auth_info.flavor_len < 1;
 
 	/* set up the general RPC client */
 	error = nfs4_init_server(server, mount_info->parsed);
@@ -1046,6 +1054,7 @@
 {
 	struct nfs_client *parent_client;
 	struct nfs_server *server, *parent_server;
+	bool auth_probe;
 	int error;
 
 	dprintk("--> nfs4_create_referral_server()\n");
@@ -1078,8 +1087,9 @@
 	if (error < 0)
 		goto error;
 
-	error = nfs4_server_common_setup(server, mntfh,
-			!(parent_server->flags & NFS_MOUNT_SECFLAVOUR));
+	auth_probe = parent_server->auth_info.flavor_len < 1;
+
+	error = nfs4_server_common_setup(server, mntfh, auth_probe);
 	if (error < 0)
 		goto error;
 
@@ -1091,3 +1101,111 @@
 	dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
 	return ERR_PTR(error);
 }
+
+/*
+ * Grab the destination's particulars, including lease expiry time.
+ *
+ * Returns zero if probe succeeded and retrieved FSID matches the FSID
+ * we have cached.
+ */
+static int nfs_probe_destination(struct nfs_server *server)
+{
+	struct inode *inode = server->super->s_root->d_inode;
+	struct nfs_fattr *fattr;
+	int error;
+
+	fattr = nfs_alloc_fattr();
+	if (fattr == NULL)
+		return -ENOMEM;
+
+	/* Sanity: the probe won't work if the destination server
+	 * does not recognize the migrated FH. */
+	error = nfs_probe_fsinfo(server, NFS_FH(inode), fattr);
+
+	nfs_free_fattr(fattr);
+	return error;
+}
+
+/**
+ * nfs4_update_server - Move an nfs_server to a different nfs_client
+ *
+ * @server: represents FSID to be moved
+ * @hostname: new end-point's hostname
+ * @sap: new end-point's socket address
+ * @salen: size of "sap"
+ *
+ * The nfs_server must be quiescent before this function is invoked.
+ * Either its session is drained (NFSv4.1+), or its transport is
+ * plugged and drained (NFSv4.0).
+ *
+ * Returns zero on success, or a negative errno value.
+ */
+int nfs4_update_server(struct nfs_server *server, const char *hostname,
+		       struct sockaddr *sap, size_t salen)
+{
+	struct nfs_client *clp = server->nfs_client;
+	struct rpc_clnt *clnt = server->client;
+	struct xprt_create xargs = {
+		.ident		= clp->cl_proto,
+		.net		= &init_net,
+		.dstaddr	= sap,
+		.addrlen	= salen,
+		.servername	= hostname,
+	};
+	char buf[INET6_ADDRSTRLEN + 1];
+	struct sockaddr_storage address;
+	struct sockaddr *localaddr = (struct sockaddr *)&address;
+	int error;
+
+	dprintk("--> %s: move FSID %llx:%llx to \"%s\")\n", __func__,
+			(unsigned long long)server->fsid.major,
+			(unsigned long long)server->fsid.minor,
+			hostname);
+
+	error = rpc_switch_client_transport(clnt, &xargs, clnt->cl_timeout);
+	if (error != 0) {
+		dprintk("<-- %s(): rpc_switch_client_transport returned %d\n",
+			__func__, error);
+		goto out;
+	}
+
+	error = rpc_localaddr(clnt, localaddr, sizeof(address));
+	if (error != 0) {
+		dprintk("<-- %s(): rpc_localaddr returned %d\n",
+			__func__, error);
+		goto out;
+	}
+
+	error = -EAFNOSUPPORT;
+	if (rpc_ntop(localaddr, buf, sizeof(buf)) == 0) {
+		dprintk("<-- %s(): rpc_ntop returned %d\n",
+			__func__, error);
+		goto out;
+	}
+
+	nfs_server_remove_lists(server);
+	error = nfs4_set_client(server, hostname, sap, salen, buf,
+				clp->cl_rpcclient->cl_auth->au_flavor,
+				clp->cl_proto, clnt->cl_timeout,
+				clp->cl_minorversion, clp->cl_net);
+	nfs_put_client(clp);
+	if (error != 0) {
+		nfs_server_insert_lists(server);
+		dprintk("<-- %s(): nfs4_set_client returned %d\n",
+			__func__, error);
+		goto out;
+	}
+
+	if (server->nfs_client->cl_hostname == NULL)
+		server->nfs_client->cl_hostname = kstrdup(hostname, GFP_KERNEL);
+	nfs_server_insert_lists(server);
+
+	error = nfs_probe_destination(server);
+	if (error < 0)
+		goto out;
+
+	dprintk("<-- %s() succeeded\n", __func__);
+
+out:
+	return error;
+}
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
index 9c8f09a..8de3407 100644
--- a/fs/nfs/nfs4file.c
+++ b/fs/nfs/nfs4file.c
@@ -73,7 +73,7 @@
 
 	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 	nfs_file_set_open_context(filp, ctx);
-	nfs_fscache_set_inode_cookie(inode, filp);
+	nfs_fscache_open_file(inode, filp);
 	err = 0;
 
 out_put_ctx:
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index 049b9fb..4e7f05d 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -137,6 +137,7 @@
 
 /**
  * nfs_find_best_sec - Find a security mechanism supported locally
+ * @server: NFS server struct
  * @flavors: List of security tuples returned by SECINFO procedure
  *
  * Return the pseudoflavor of the first security mechanism in
@@ -145,7 +146,8 @@
  * is searched in the order returned from the server, per RFC 3530
  * recommendation.
  */
-rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
+static rpc_authflavor_t nfs_find_best_sec(struct nfs_server *server,
+					  struct nfs4_secinfo_flavors *flavors)
 {
 	rpc_authflavor_t pseudoflavor;
 	struct nfs4_secinfo4 *secinfo;
@@ -160,12 +162,19 @@
 		case RPC_AUTH_GSS:
 			pseudoflavor = rpcauth_get_pseudoflavor(secinfo->flavor,
 							&secinfo->flavor_info);
-			if (pseudoflavor != RPC_AUTH_MAXFLAVOR)
+			/* make sure pseudoflavor matches sec= mount opt */
+			if (pseudoflavor != RPC_AUTH_MAXFLAVOR &&
+			    nfs_auth_info_match(&server->auth_info,
+						pseudoflavor))
 				return pseudoflavor;
 			break;
 		}
 	}
 
+	/* if there were any sec= options then nothing matched */
+	if (server->auth_info.flavor_len > 0)
+		return -EPERM;
+
 	return RPC_AUTH_UNIX;
 }
 
@@ -187,7 +196,7 @@
 		goto out;
 	}
 
-	flavor = nfs_find_best_sec(flavors);
+	flavor = nfs_find_best_sec(NFS_SERVER(inode), flavors);
 
 out:
 	put_page(page);
@@ -389,7 +398,7 @@
 
 	if (client->cl_auth->au_flavor != flavor)
 		flavor = client->cl_auth->au_flavor;
-	else if (!(server->flags & NFS_MOUNT_SECFLAVOUR)) {
+	else {
 		rpc_authflavor_t new = nfs4_negotiate_security(dir, name);
 		if ((int)new >= 0)
 			flavor = new;
@@ -399,3 +408,104 @@
 	rpc_shutdown_client(client);
 	return mnt;
 }
+
+/*
+ * Try one location from the fs_locations array.
+ *
+ * Returns zero on success, or a negative errno value.
+ */
+static int nfs4_try_replacing_one_location(struct nfs_server *server,
+		char *page, char *page2,
+		const struct nfs4_fs_location *location)
+{
+	const size_t addr_bufsize = sizeof(struct sockaddr_storage);
+	struct sockaddr *sap;
+	unsigned int s;
+	size_t salen;
+	int error;
+
+	sap = kmalloc(addr_bufsize, GFP_KERNEL);
+	if (sap == NULL)
+		return -ENOMEM;
+
+	error = -ENOENT;
+	for (s = 0; s < location->nservers; s++) {
+		const struct nfs4_string *buf = &location->servers[s];
+		char *hostname;
+
+		if (buf->len <= 0 || buf->len > PAGE_SIZE)
+			continue;
+
+		if (memchr(buf->data, IPV6_SCOPE_DELIMITER, buf->len) != NULL)
+			continue;
+
+		salen = nfs_parse_server_name(buf->data, buf->len,
+						sap, addr_bufsize, server);
+		if (salen == 0)
+			continue;
+		rpc_set_port(sap, NFS_PORT);
+
+		error = -ENOMEM;
+		hostname = kstrndup(buf->data, buf->len, GFP_KERNEL);
+		if (hostname == NULL)
+			break;
+
+		error = nfs4_update_server(server, hostname, sap, salen);
+		kfree(hostname);
+		if (error == 0)
+			break;
+	}
+
+	kfree(sap);
+	return error;
+}
+
+/**
+ * nfs4_replace_transport - set up transport to destination server
+ *
+ * @server: export being migrated
+ * @locations: fs_locations array
+ *
+ * Returns zero on success, or a negative errno value.
+ *
+ * The client tries all the entries in the "locations" array, in the
+ * order returned by the server, until one works or the end of the
+ * array is reached.
+ */
+int nfs4_replace_transport(struct nfs_server *server,
+			   const struct nfs4_fs_locations *locations)
+{
+	char *page = NULL, *page2 = NULL;
+	int loc, error;
+
+	error = -ENOENT;
+	if (locations == NULL || locations->nlocations <= 0)
+		goto out;
+
+	error = -ENOMEM;
+	page = (char *) __get_free_page(GFP_USER);
+	if (!page)
+		goto out;
+	page2 = (char *) __get_free_page(GFP_USER);
+	if (!page2)
+		goto out;
+
+	for (loc = 0; loc < locations->nlocations; loc++) {
+		const struct nfs4_fs_location *location =
+						&locations->locations[loc];
+
+		if (location == NULL || location->nservers <= 0 ||
+		    location->rootpath.ncomponents == 0)
+			continue;
+
+		error = nfs4_try_replacing_one_location(server, page,
+							page2, location);
+		if (error == 0)
+			break;
+	}
+
+out:
+	free_page((unsigned long)page);
+	free_page((unsigned long)page2);
+	return error;
+}
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 75e46bb..659990c 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -105,9 +105,6 @@
 	if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL) == 0)
 		return NULL;
 
-	if (NFS_SERVER(dir)->nfs_client->cl_minorversion < 2)
-		return NULL;
-
 	err = security_dentry_init_security(dentry, sattr->ia_mode,
 				&dentry->d_name, (void **)&label->label, &label->len);
 	if (err == 0)
@@ -384,6 +381,14 @@
 		case -NFS4ERR_STALE_CLIENTID:
 			nfs4_schedule_lease_recovery(clp);
 			goto wait_on_recovery;
+		case -NFS4ERR_MOVED:
+			ret = nfs4_schedule_migration_recovery(server);
+			if (ret < 0)
+				break;
+			goto wait_on_recovery;
+		case -NFS4ERR_LEASE_MOVED:
+			nfs4_schedule_lease_moved_recovery(clp);
+			goto wait_on_recovery;
 #if defined(CONFIG_NFS_V4_1)
 		case -NFS4ERR_BADSESSION:
 		case -NFS4ERR_BADSLOT:
@@ -431,6 +436,8 @@
 	return nfs4_map_errors(ret);
 wait_on_recovery:
 	ret = nfs4_wait_clnt_recover(clp);
+	if (test_bit(NFS_MIG_FAILED, &server->mig_status))
+		return -EIO;
 	if (ret == 0)
 		exception->retry = 1;
 	return ret;
@@ -1318,31 +1325,24 @@
 	int ret;
 
 	if (!data->rpc_done) {
-		ret = data->rpc_status;
-		goto err;
+		if (data->rpc_status) {
+			ret = data->rpc_status;
+			goto err;
+		}
+		/* cached opens have already been processed */
+		goto update;
 	}
 
-	ret = -ESTALE;
-	if (!(data->f_attr.valid & NFS_ATTR_FATTR_TYPE) ||
-	    !(data->f_attr.valid & NFS_ATTR_FATTR_FILEID) ||
-	    !(data->f_attr.valid & NFS_ATTR_FATTR_CHANGE))
-		goto err;
-
-	ret = -ENOMEM;
-	state = nfs4_get_open_state(inode, data->owner);
-	if (state == NULL)
-		goto err;
-
 	ret = nfs_refresh_inode(inode, &data->f_attr);
 	if (ret)
 		goto err;
 
-	nfs_setsecurity(inode, &data->f_attr, data->f_label);
-
 	if (data->o_res.delegation_type != 0)
 		nfs4_opendata_check_deleg(data, state);
+update:
 	update_open_stateid(state, &data->o_res.stateid, NULL,
 			    data->o_arg.fmode);
+	atomic_inc(&state->count);
 
 	return state;
 err:
@@ -1575,6 +1575,12 @@
 			/* Don't recall a delegation if it was lost */
 			nfs4_schedule_lease_recovery(server->nfs_client);
 			return -EAGAIN;
+		case -NFS4ERR_MOVED:
+			nfs4_schedule_migration_recovery(server);
+			return -EAGAIN;
+		case -NFS4ERR_LEASE_MOVED:
+			nfs4_schedule_lease_moved_recovery(server->nfs_client);
+			return -EAGAIN;
 		case -NFS4ERR_DELEG_REVOKED:
 		case -NFS4ERR_ADMIN_REVOKED:
 		case -NFS4ERR_BAD_STATEID:
@@ -2697,6 +2703,10 @@
 		nfs4_close_state(ctx->state, ctx->mode);
 }
 
+#define FATTR4_WORD1_NFS40_MASK (2*FATTR4_WORD1_MOUNTED_ON_FILEID - 1UL)
+#define FATTR4_WORD2_NFS41_MASK (2*FATTR4_WORD2_SUPPATTR_EXCLCREAT - 1UL)
+#define FATTR4_WORD2_NFS42_MASK (2*FATTR4_WORD2_CHANGE_SECURITY_LABEL - 1UL)
+
 static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
 {
 	struct nfs4_server_caps_arg args = {
@@ -2712,12 +2722,25 @@
 
 	status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
 	if (status == 0) {
+		/* Sanity check the server answers */
+		switch (server->nfs_client->cl_minorversion) {
+		case 0:
+			res.attr_bitmask[1] &= FATTR4_WORD1_NFS40_MASK;
+			res.attr_bitmask[2] = 0;
+			break;
+		case 1:
+			res.attr_bitmask[2] &= FATTR4_WORD2_NFS41_MASK;
+			break;
+		case 2:
+			res.attr_bitmask[2] &= FATTR4_WORD2_NFS42_MASK;
+		}
 		memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask));
 		server->caps &= ~(NFS_CAP_ACLS|NFS_CAP_HARDLINKS|
 				NFS_CAP_SYMLINKS|NFS_CAP_FILEID|
 				NFS_CAP_MODE|NFS_CAP_NLINK|NFS_CAP_OWNER|
 				NFS_CAP_OWNER_GROUP|NFS_CAP_ATIME|
-				NFS_CAP_CTIME|NFS_CAP_MTIME);
+				NFS_CAP_CTIME|NFS_CAP_MTIME|
+				NFS_CAP_SECURITY_LABEL);
 		if (res.attr_bitmask[0] & FATTR4_WORD0_ACL)
 			server->caps |= NFS_CAP_ACLS;
 		if (res.has_links != 0)
@@ -2746,14 +2769,12 @@
 #endif
 		memcpy(server->attr_bitmask_nl, res.attr_bitmask,
 				sizeof(server->attr_bitmask));
+		server->attr_bitmask_nl[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
 
-		if (server->caps & NFS_CAP_SECURITY_LABEL) {
-			server->attr_bitmask_nl[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
-			res.attr_bitmask[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
-		}
 		memcpy(server->cache_consistency_bitmask, res.attr_bitmask, sizeof(server->cache_consistency_bitmask));
 		server->cache_consistency_bitmask[0] &= FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE;
 		server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
+		server->cache_consistency_bitmask[2] = 0;
 		server->acl_bitmask = res.acl_bitmask;
 		server->fh_expire_type = res.fh_expire_type;
 	}
@@ -2864,11 +2885,24 @@
 	int status = -EPERM;
 	size_t i;
 
-	for (i = 0; i < ARRAY_SIZE(flav_array); i++) {
-		status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]);
-		if (status == -NFS4ERR_WRONGSEC || status == -EACCES)
-			continue;
-		break;
+	if (server->auth_info.flavor_len > 0) {
+		/* try each flavor specified by user */
+		for (i = 0; i < server->auth_info.flavor_len; i++) {
+			status = nfs4_lookup_root_sec(server, fhandle, info,
+						server->auth_info.flavors[i]);
+			if (status == -NFS4ERR_WRONGSEC || status == -EACCES)
+				continue;
+			break;
+		}
+	} else {
+		/* no flavors specified by user, try default list */
+		for (i = 0; i < ARRAY_SIZE(flav_array); i++) {
+			status = nfs4_lookup_root_sec(server, fhandle, info,
+						      flav_array[i]);
+			if (status == -NFS4ERR_WRONGSEC || status == -EACCES)
+				continue;
+			break;
+		}
 	}
 
 	/*
@@ -2910,9 +2944,6 @@
 		status = nfs4_lookup_root(server, fhandle, info);
 		if (status != -NFS4ERR_WRONGSEC)
 			break;
-		/* Did user force a 'sec=' mount option? */
-		if (server->flags & NFS_MOUNT_SECFLAVOUR)
-			break;
 	default:
 		status = nfs4_do_find_root_sec(server, fhandle, info);
 	}
@@ -2981,11 +3012,16 @@
 	status = nfs4_proc_fs_locations(client, dir, name, locations, page);
 	if (status != 0)
 		goto out;
-	/* Make sure server returned a different fsid for the referral */
+
+	/*
+	 * If the fsid didn't change, this is a migration event, not a
+	 * referral.  Cause us to drop into the exception handler, which
+	 * will kick off migration recovery.
+	 */
 	if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &locations->fattr.fsid)) {
 		dprintk("%s: server did not return a different fsid for"
 			" a referral at %s\n", __func__, name->name);
-		status = -EIO;
+		status = -NFS4ERR_MOVED;
 		goto out;
 	}
 	/* Fixup attributes for the nfs_lookup() call to nfs_fhget() */
@@ -3165,9 +3201,6 @@
 			err = -EPERM;
 			if (client != *clnt)
 				goto out;
-			/* No security negotiation if the user specified 'sec=' */
-			if (NFS_SERVER(dir)->flags & NFS_MOUNT_SECFLAVOUR)
-				goto out;
 			client = nfs4_create_sec_client(client, dir, name);
 			if (IS_ERR(client))
 				return PTR_ERR(client);
@@ -4220,7 +4253,13 @@
 	unsigned long timestamp = data->timestamp;
 
 	trace_nfs4_renew_async(clp, task->tk_status);
-	if (task->tk_status < 0) {
+	switch (task->tk_status) {
+	case 0:
+		break;
+	case -NFS4ERR_LEASE_MOVED:
+		nfs4_schedule_lease_moved_recovery(clp);
+		break;
+	default:
 		/* Unless we're shutting down, schedule state recovery! */
 		if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) == 0)
 			return;
@@ -4574,7 +4613,7 @@
 	struct nfs4_label label = {0, 0, buflen, buf};
 
 	u32 bitmask[3] = { 0, 0, FATTR4_WORD2_SECURITY_LABEL };
-	struct nfs4_getattr_arg args = {
+	struct nfs4_getattr_arg arg = {
 		.fh		= NFS_FH(inode),
 		.bitmask	= bitmask,
 	};
@@ -4585,14 +4624,14 @@
 	};
 	struct rpc_message msg = {
 		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_GETATTR],
-		.rpc_argp	= &args,
+		.rpc_argp	= &arg,
 		.rpc_resp	= &res,
 	};
 	int ret;
 
 	nfs_fattr_init(&fattr);
 
-	ret = rpc_call_sync(server->client, &msg, 0);
+	ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 0);
 	if (ret)
 		return ret;
 	if (!(fattr.valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL))
@@ -4629,7 +4668,7 @@
 	struct iattr sattr = {0};
 	struct nfs_server *server = NFS_SERVER(inode);
 	const u32 bitmask[3] = { 0, 0, FATTR4_WORD2_SECURITY_LABEL };
-	struct nfs_setattrargs args = {
+	struct nfs_setattrargs arg = {
 		.fh             = NFS_FH(inode),
 		.iap            = &sattr,
 		.server		= server,
@@ -4643,14 +4682,14 @@
 	};
 	struct rpc_message msg = {
 		.rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_SETATTR],
-		.rpc_argp       = &args,
+		.rpc_argp       = &arg,
 		.rpc_resp       = &res,
 	};
 	int status;
 
-	nfs4_stateid_copy(&args.stateid, &zero_stateid);
+	nfs4_stateid_copy(&arg.stateid, &zero_stateid);
 
-	status = rpc_call_sync(server->client, &msg, 0);
+	status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
 	if (status)
 		dprintk("%s failed: %d\n", __func__, status);
 
@@ -4734,17 +4773,24 @@
 			if (state == NULL)
 				break;
 			if (nfs4_schedule_stateid_recovery(server, state) < 0)
-				goto stateid_invalid;
+				goto recovery_failed;
 			goto wait_on_recovery;
 		case -NFS4ERR_EXPIRED:
 			if (state != NULL) {
 				if (nfs4_schedule_stateid_recovery(server, state) < 0)
-					goto stateid_invalid;
+					goto recovery_failed;
 			}
 		case -NFS4ERR_STALE_STATEID:
 		case -NFS4ERR_STALE_CLIENTID:
 			nfs4_schedule_lease_recovery(clp);
 			goto wait_on_recovery;
+		case -NFS4ERR_MOVED:
+			if (nfs4_schedule_migration_recovery(server) < 0)
+				goto recovery_failed;
+			goto wait_on_recovery;
+		case -NFS4ERR_LEASE_MOVED:
+			nfs4_schedule_lease_moved_recovery(clp);
+			goto wait_on_recovery;
 #if defined(CONFIG_NFS_V4_1)
 		case -NFS4ERR_BADSESSION:
 		case -NFS4ERR_BADSLOT:
@@ -4756,29 +4802,28 @@
 			dprintk("%s ERROR %d, Reset session\n", __func__,
 				task->tk_status);
 			nfs4_schedule_session_recovery(clp->cl_session, task->tk_status);
-			task->tk_status = 0;
-			return -EAGAIN;
+			goto restart_call;
 #endif /* CONFIG_NFS_V4_1 */
 		case -NFS4ERR_DELAY:
 			nfs_inc_server_stats(server, NFSIOS_DELAY);
 		case -NFS4ERR_GRACE:
 			rpc_delay(task, NFS4_POLL_RETRY_MAX);
-			task->tk_status = 0;
-			return -EAGAIN;
 		case -NFS4ERR_RETRY_UNCACHED_REP:
 		case -NFS4ERR_OLD_STATEID:
-			task->tk_status = 0;
-			return -EAGAIN;
+			goto restart_call;
 	}
 	task->tk_status = nfs4_map_errors(task->tk_status);
 	return 0;
-stateid_invalid:
+recovery_failed:
 	task->tk_status = -EIO;
 	return 0;
 wait_on_recovery:
 	rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
 	if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
 		rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
+	if (test_bit(NFS_MIG_FAILED, &server->mig_status))
+		goto recovery_failed;
+restart_call:
 	task->tk_status = 0;
 	return -EAGAIN;
 }
@@ -5105,6 +5150,7 @@
 			status = 0;
 	}
 	request->fl_ops->fl_release_private(request);
+	request->fl_ops = NULL;
 out:
 	return status;
 }
@@ -5778,6 +5824,7 @@
 	struct nfs_release_lockowner_args args;
 	struct nfs4_sequence_args seq_args;
 	struct nfs4_sequence_res seq_res;
+	unsigned long timestamp;
 };
 
 static void nfs4_release_lockowner_prepare(struct rpc_task *task, void *calldata)
@@ -5785,12 +5832,27 @@
 	struct nfs_release_lockowner_data *data = calldata;
 	nfs40_setup_sequence(data->server,
 				&data->seq_args, &data->seq_res, task);
+	data->timestamp = jiffies;
 }
 
 static void nfs4_release_lockowner_done(struct rpc_task *task, void *calldata)
 {
 	struct nfs_release_lockowner_data *data = calldata;
+	struct nfs_server *server = data->server;
+
 	nfs40_sequence_done(task, &data->seq_res);
+
+	switch (task->tk_status) {
+	case 0:
+		renew_lease(server, data->timestamp);
+		break;
+	case -NFS4ERR_STALE_CLIENTID:
+	case -NFS4ERR_EXPIRED:
+	case -NFS4ERR_LEASE_MOVED:
+	case -NFS4ERR_DELAY:
+		if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN)
+			rpc_restart_call_prepare(task);
+	}
 }
 
 static void nfs4_release_lockowner_release(void *calldata)
@@ -5989,6 +6051,283 @@
 	return err;
 }
 
+/*
+ * This operation also signals the server that this client is
+ * performing migration recovery.  The server can stop returning
+ * NFS4ERR_LEASE_MOVED to this client.  A RENEW operation is
+ * appended to this compound to identify the client ID which is
+ * performing recovery.
+ */
+static int _nfs40_proc_get_locations(struct inode *inode,
+				     struct nfs4_fs_locations *locations,
+				     struct page *page, struct rpc_cred *cred)
+{
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct rpc_clnt *clnt = server->client;
+	u32 bitmask[2] = {
+		[0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS,
+	};
+	struct nfs4_fs_locations_arg args = {
+		.clientid	= server->nfs_client->cl_clientid,
+		.fh		= NFS_FH(inode),
+		.page		= page,
+		.bitmask	= bitmask,
+		.migration	= 1,		/* skip LOOKUP */
+		.renew		= 1,		/* append RENEW */
+	};
+	struct nfs4_fs_locations_res res = {
+		.fs_locations	= locations,
+		.migration	= 1,
+		.renew		= 1,
+	};
+	struct rpc_message msg = {
+		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS],
+		.rpc_argp	= &args,
+		.rpc_resp	= &res,
+		.rpc_cred	= cred,
+	};
+	unsigned long now = jiffies;
+	int status;
+
+	nfs_fattr_init(&locations->fattr);
+	locations->server = server;
+	locations->nlocations = 0;
+
+	nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
+	nfs4_set_sequence_privileged(&args.seq_args);
+	status = nfs4_call_sync_sequence(clnt, server, &msg,
+					&args.seq_args, &res.seq_res);
+	if (status)
+		return status;
+
+	renew_lease(server, now);
+	return 0;
+}
+
+#ifdef CONFIG_NFS_V4_1
+
+/*
+ * This operation also signals the server that this client is
+ * performing migration recovery.  The server can stop asserting
+ * SEQ4_STATUS_LEASE_MOVED for this client.  The client ID
+ * performing this operation is identified in the SEQUENCE
+ * operation in this compound.
+ *
+ * When the client supports GETATTR(fs_locations_info), it can
+ * be plumbed in here.
+ */
+static int _nfs41_proc_get_locations(struct inode *inode,
+				     struct nfs4_fs_locations *locations,
+				     struct page *page, struct rpc_cred *cred)
+{
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct rpc_clnt *clnt = server->client;
+	u32 bitmask[2] = {
+		[0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS,
+	};
+	struct nfs4_fs_locations_arg args = {
+		.fh		= NFS_FH(inode),
+		.page		= page,
+		.bitmask	= bitmask,
+		.migration	= 1,		/* skip LOOKUP */
+	};
+	struct nfs4_fs_locations_res res = {
+		.fs_locations	= locations,
+		.migration	= 1,
+	};
+	struct rpc_message msg = {
+		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS],
+		.rpc_argp	= &args,
+		.rpc_resp	= &res,
+		.rpc_cred	= cred,
+	};
+	int status;
+
+	nfs_fattr_init(&locations->fattr);
+	locations->server = server;
+	locations->nlocations = 0;
+
+	nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
+	nfs4_set_sequence_privileged(&args.seq_args);
+	status = nfs4_call_sync_sequence(clnt, server, &msg,
+					&args.seq_args, &res.seq_res);
+	if (status == NFS4_OK &&
+	    res.seq_res.sr_status_flags & SEQ4_STATUS_LEASE_MOVED)
+		status = -NFS4ERR_LEASE_MOVED;
+	return status;
+}
+
+#endif	/* CONFIG_NFS_V4_1 */
+
+/**
+ * nfs4_proc_get_locations - discover locations for a migrated FSID
+ * @inode: inode on FSID that is migrating
+ * @locations: result of query
+ * @page: buffer
+ * @cred: credential to use for this operation
+ *
+ * Returns NFS4_OK on success, a negative NFS4ERR status code if the
+ * operation failed, or a negative errno if a local error occurred.
+ *
+ * On success, "locations" is filled in, but if the server has
+ * no locations information, NFS_ATTR_FATTR_V4_LOCATIONS is not
+ * asserted.
+ *
+ * -NFS4ERR_LEASE_MOVED is returned if the server still has leases
+ * from this client that require migration recovery.
+ */
+int nfs4_proc_get_locations(struct inode *inode,
+			    struct nfs4_fs_locations *locations,
+			    struct page *page, struct rpc_cred *cred)
+{
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs_client *clp = server->nfs_client;
+	const struct nfs4_mig_recovery_ops *ops =
+					clp->cl_mvops->mig_recovery_ops;
+	struct nfs4_exception exception = { };
+	int status;
+
+	dprintk("%s: FSID %llx:%llx on \"%s\"\n", __func__,
+		(unsigned long long)server->fsid.major,
+		(unsigned long long)server->fsid.minor,
+		clp->cl_hostname);
+	nfs_display_fhandle(NFS_FH(inode), __func__);
+
+	do {
+		status = ops->get_locations(inode, locations, page, cred);
+		if (status != -NFS4ERR_DELAY)
+			break;
+		nfs4_handle_exception(server, status, &exception);
+	} while (exception.retry);
+	return status;
+}
+
+/*
+ * This operation also signals the server that this client is
+ * performing "lease moved" recovery.  The server can stop
+ * returning NFS4ERR_LEASE_MOVED to this client.  A RENEW operation
+ * is appended to this compound to identify the client ID which is
+ * performing recovery.
+ */
+static int _nfs40_proc_fsid_present(struct inode *inode, struct rpc_cred *cred)
+{
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
+	struct rpc_clnt *clnt = server->client;
+	struct nfs4_fsid_present_arg args = {
+		.fh		= NFS_FH(inode),
+		.clientid	= clp->cl_clientid,
+		.renew		= 1,		/* append RENEW */
+	};
+	struct nfs4_fsid_present_res res = {
+		.renew		= 1,
+	};
+	struct rpc_message msg = {
+		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_FSID_PRESENT],
+		.rpc_argp	= &args,
+		.rpc_resp	= &res,
+		.rpc_cred	= cred,
+	};
+	unsigned long now = jiffies;
+	int status;
+
+	res.fh = nfs_alloc_fhandle();
+	if (res.fh == NULL)
+		return -ENOMEM;
+
+	nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
+	nfs4_set_sequence_privileged(&args.seq_args);
+	status = nfs4_call_sync_sequence(clnt, server, &msg,
+						&args.seq_args, &res.seq_res);
+	nfs_free_fhandle(res.fh);
+	if (status)
+		return status;
+
+	do_renew_lease(clp, now);
+	return 0;
+}
+
+#ifdef CONFIG_NFS_V4_1
+
+/*
+ * This operation also signals the server that this client is
+ * performing "lease moved" recovery.  The server can stop asserting
+ * SEQ4_STATUS_LEASE_MOVED for this client.  The client ID performing
+ * this operation is identified in the SEQUENCE operation in this
+ * compound.
+ */
+static int _nfs41_proc_fsid_present(struct inode *inode, struct rpc_cred *cred)
+{
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct rpc_clnt *clnt = server->client;
+	struct nfs4_fsid_present_arg args = {
+		.fh		= NFS_FH(inode),
+	};
+	struct nfs4_fsid_present_res res = {
+	};
+	struct rpc_message msg = {
+		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_FSID_PRESENT],
+		.rpc_argp	= &args,
+		.rpc_resp	= &res,
+		.rpc_cred	= cred,
+	};
+	int status;
+
+	res.fh = nfs_alloc_fhandle();
+	if (res.fh == NULL)
+		return -ENOMEM;
+
+	nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
+	nfs4_set_sequence_privileged(&args.seq_args);
+	status = nfs4_call_sync_sequence(clnt, server, &msg,
+						&args.seq_args, &res.seq_res);
+	nfs_free_fhandle(res.fh);
+	if (status == NFS4_OK &&
+	    res.seq_res.sr_status_flags & SEQ4_STATUS_LEASE_MOVED)
+		status = -NFS4ERR_LEASE_MOVED;
+	return status;
+}
+
+#endif	/* CONFIG_NFS_V4_1 */
+
+/**
+ * nfs4_proc_fsid_present - Is this FSID present or absent on server?
+ * @inode: inode on FSID to check
+ * @cred: credential to use for this operation
+ *
+ * Server indicates whether the FSID is present, moved, or not
+ * recognized.  This operation is necessary to clear a LEASE_MOVED
+ * condition for this client ID.
+ *
+ * Returns NFS4_OK if the FSID is present on this server,
+ * -NFS4ERR_MOVED if the FSID is no longer present, a negative
+ *  NFS4ERR code if some error occurred on the server, or a
+ *  negative errno if a local failure occurred.
+ */
+int nfs4_proc_fsid_present(struct inode *inode, struct rpc_cred *cred)
+{
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs_client *clp = server->nfs_client;
+	const struct nfs4_mig_recovery_ops *ops =
+					clp->cl_mvops->mig_recovery_ops;
+	struct nfs4_exception exception = { };
+	int status;
+
+	dprintk("%s: FSID %llx:%llx on \"%s\"\n", __func__,
+		(unsigned long long)server->fsid.major,
+		(unsigned long long)server->fsid.minor,
+		clp->cl_hostname);
+	nfs_display_fhandle(NFS_FH(inode), __func__);
+
+	do {
+		status = ops->fsid_present(inode, cred);
+		if (status != -NFS4ERR_DELAY)
+			break;
+		nfs4_handle_exception(server, status, &exception);
+	} while (exception.retry);
+	return status;
+}
+
 /**
  * If 'use_integrity' is true and the state managment nfs_client
  * cl_rpcclient is using krb5i/p, use the integrity protected cl_rpcclient
@@ -6275,8 +6614,14 @@
 	struct nfs41_exchange_id_args args = {
 		.verifier = &verifier,
 		.client = clp,
+#ifdef CONFIG_NFS_V4_1_MIGRATION
 		.flags = EXCHGID4_FLAG_SUPP_MOVED_REFER |
-			EXCHGID4_FLAG_BIND_PRINC_STATEID,
+			 EXCHGID4_FLAG_BIND_PRINC_STATEID |
+			 EXCHGID4_FLAG_SUPP_MOVED_MIGR,
+#else
+		.flags = EXCHGID4_FLAG_SUPP_MOVED_REFER |
+			 EXCHGID4_FLAG_BIND_PRINC_STATEID,
+#endif
 	};
 	struct nfs41_exchange_id_res res = {
 		0
@@ -7615,6 +7960,9 @@
 			break;
 		}
 
+		if (!nfs_auth_info_match(&server->auth_info, flavor))
+			flavor = RPC_AUTH_MAXFLAVOR;
+
 		if (flavor != RPC_AUTH_MAXFLAVOR) {
 			err = nfs4_lookup_root_sec(server, fhandle,
 						   info, flavor);
@@ -7886,6 +8234,18 @@
 };
 #endif
 
+static const struct nfs4_mig_recovery_ops nfs40_mig_recovery_ops = {
+	.get_locations = _nfs40_proc_get_locations,
+	.fsid_present = _nfs40_proc_fsid_present,
+};
+
+#if defined(CONFIG_NFS_V4_1)
+static const struct nfs4_mig_recovery_ops nfs41_mig_recovery_ops = {
+	.get_locations = _nfs41_proc_get_locations,
+	.fsid_present = _nfs41_proc_fsid_present,
+};
+#endif	/* CONFIG_NFS_V4_1 */
+
 static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = {
 	.minor_version = 0,
 	.init_caps = NFS_CAP_READDIRPLUS
@@ -7901,6 +8261,7 @@
 	.reboot_recovery_ops = &nfs40_reboot_recovery_ops,
 	.nograce_recovery_ops = &nfs40_nograce_recovery_ops,
 	.state_renewal_ops = &nfs40_state_renewal_ops,
+	.mig_recovery_ops = &nfs40_mig_recovery_ops,
 };
 
 #if defined(CONFIG_NFS_V4_1)
@@ -7921,6 +8282,7 @@
 	.reboot_recovery_ops = &nfs41_reboot_recovery_ops,
 	.nograce_recovery_ops = &nfs41_nograce_recovery_ops,
 	.state_renewal_ops = &nfs41_state_renewal_ops,
+	.mig_recovery_ops = &nfs41_mig_recovery_ops,
 };
 #endif
 
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index cc14cbb..c8e729d 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -239,8 +239,6 @@
 	}
 }
 
-#if defined(CONFIG_NFS_V4_1)
-
 static int nfs4_drain_slot_tbl(struct nfs4_slot_table *tbl)
 {
 	set_bit(NFS4_SLOT_TBL_DRAINING, &tbl->slot_tbl_state);
@@ -270,6 +268,8 @@
 	return nfs4_drain_slot_tbl(&ses->fc_slot_table);
 }
 
+#if defined(CONFIG_NFS_V4_1)
+
 static int nfs41_setup_state_renewal(struct nfs_client *clp)
 {
 	int status;
@@ -1197,20 +1197,74 @@
 }
 EXPORT_SYMBOL_GPL(nfs4_schedule_lease_recovery);
 
+/**
+ * nfs4_schedule_migration_recovery - trigger migration recovery
+ *
+ * @server: FSID that is migrating
+ *
+ * Returns zero if recovery has started, otherwise a negative NFS4ERR
+ * value is returned.
+ */
+int nfs4_schedule_migration_recovery(const struct nfs_server *server)
+{
+	struct nfs_client *clp = server->nfs_client;
+
+	if (server->fh_expire_type != NFS4_FH_PERSISTENT) {
+		pr_err("NFS: volatile file handles not supported (server %s)\n",
+				clp->cl_hostname);
+		return -NFS4ERR_IO;
+	}
+
+	if (test_bit(NFS_MIG_FAILED, &server->mig_status))
+		return -NFS4ERR_IO;
+
+	dprintk("%s: scheduling migration recovery for (%llx:%llx) on %s\n",
+			__func__,
+			(unsigned long long)server->fsid.major,
+			(unsigned long long)server->fsid.minor,
+			clp->cl_hostname);
+
+	set_bit(NFS_MIG_IN_TRANSITION,
+			&((struct nfs_server *)server)->mig_status);
+	set_bit(NFS4CLNT_MOVED, &clp->cl_state);
+
+	nfs4_schedule_state_manager(clp);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(nfs4_schedule_migration_recovery);
+
+/**
+ * nfs4_schedule_lease_moved_recovery - start lease-moved recovery
+ *
+ * @clp: server to check for moved leases
+ *
+ */
+void nfs4_schedule_lease_moved_recovery(struct nfs_client *clp)
+{
+	dprintk("%s: scheduling lease-moved recovery for client ID %llx on %s\n",
+		__func__, clp->cl_clientid, clp->cl_hostname);
+
+	set_bit(NFS4CLNT_LEASE_MOVED, &clp->cl_state);
+	nfs4_schedule_state_manager(clp);
+}
+EXPORT_SYMBOL_GPL(nfs4_schedule_lease_moved_recovery);
+
 int nfs4_wait_clnt_recover(struct nfs_client *clp)
 {
 	int res;
 
 	might_sleep();
 
+	atomic_inc(&clp->cl_count);
 	res = wait_on_bit(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING,
 			nfs_wait_bit_killable, TASK_KILLABLE);
 	if (res)
-		return res;
-
+		goto out;
 	if (clp->cl_cons_state < 0)
-		return clp->cl_cons_state;
-	return 0;
+		res = clp->cl_cons_state;
+out:
+	nfs_put_client(clp);
+	return res;
 }
 
 int nfs4_client_recover_expired_lease(struct nfs_client *clp)
@@ -1375,8 +1429,8 @@
 			case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
 				goto out;
 			default:
-				printk(KERN_ERR "NFS: %s: unhandled error %d. "
-					"Zeroing state\n", __func__, status);
+				printk(KERN_ERR "NFS: %s: unhandled error %d\n",
+					 __func__, status);
 			case -ENOMEM:
 			case -NFS4ERR_DENIED:
 			case -NFS4ERR_RECLAIM_BAD:
@@ -1422,7 +1476,7 @@
 		if (status >= 0) {
 			status = nfs4_reclaim_locks(state, ops);
 			if (status >= 0) {
-				if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) {
+				if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) {
 					spin_lock(&state->state_lock);
 					list_for_each_entry(lock, &state->lock_states, ls_locks) {
 						if (!test_bit(NFS_LOCK_INITIALIZED, &lock->ls_flags))
@@ -1439,15 +1493,12 @@
 		}
 		switch (status) {
 			default:
-				printk(KERN_ERR "NFS: %s: unhandled error %d. "
-					"Zeroing state\n", __func__, status);
+				printk(KERN_ERR "NFS: %s: unhandled error %d\n",
+					__func__, status);
 			case -ENOENT:
 			case -ENOMEM:
 			case -ESTALE:
-				/*
-				 * Open state on this file cannot be recovered
-				 * All we can do is revert to using the zero stateid.
-				 */
+				/* Open state on this file cannot be recovered */
 				nfs4_state_mark_recovery_failed(state, status);
 				break;
 			case -EAGAIN:
@@ -1628,7 +1679,6 @@
 			nfs4_state_end_reclaim_reboot(clp);
 			break;
 		case -NFS4ERR_STALE_CLIENTID:
-		case -NFS4ERR_LEASE_MOVED:
 			set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
 			nfs4_state_clear_reclaim_reboot(clp);
 			nfs4_state_start_reclaim_reboot(clp);
@@ -1829,6 +1879,168 @@
 	return 0;
 }
 
+/*
+ * Try remote migration of one FSID from a source server to a
+ * destination server.  The source server provides a list of
+ * potential destinations.
+ *
+ * Returns zero or a negative NFS4ERR status code.
+ */
+static int nfs4_try_migration(struct nfs_server *server, struct rpc_cred *cred)
+{
+	struct nfs_client *clp = server->nfs_client;
+	struct nfs4_fs_locations *locations = NULL;
+	struct inode *inode;
+	struct page *page;
+	int status, result;
+
+	dprintk("--> %s: FSID %llx:%llx on \"%s\"\n", __func__,
+			(unsigned long long)server->fsid.major,
+			(unsigned long long)server->fsid.minor,
+			clp->cl_hostname);
+
+	result = 0;
+	page = alloc_page(GFP_KERNEL);
+	locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL);
+	if (page == NULL || locations == NULL) {
+		dprintk("<-- %s: no memory\n", __func__);
+		goto out;
+	}
+
+	inode = server->super->s_root->d_inode;
+	result = nfs4_proc_get_locations(inode, locations, page, cred);
+	if (result) {
+		dprintk("<-- %s: failed to retrieve fs_locations: %d\n",
+			__func__, result);
+		goto out;
+	}
+
+	result = -NFS4ERR_NXIO;
+	if (!(locations->fattr.valid & NFS_ATTR_FATTR_V4_LOCATIONS)) {
+		dprintk("<-- %s: No fs_locations data, migration skipped\n",
+			__func__);
+		goto out;
+	}
+
+	nfs4_begin_drain_session(clp);
+
+	status = nfs4_replace_transport(server, locations);
+	if (status != 0) {
+		dprintk("<-- %s: failed to replace transport: %d\n",
+			__func__, status);
+		goto out;
+	}
+
+	result = 0;
+	dprintk("<-- %s: migration succeeded\n", __func__);
+
+out:
+	if (page != NULL)
+		__free_page(page);
+	kfree(locations);
+	if (result) {
+		pr_err("NFS: migration recovery failed (server %s)\n",
+				clp->cl_hostname);
+		set_bit(NFS_MIG_FAILED, &server->mig_status);
+	}
+	return result;
+}
+
+/*
+ * Returns zero or a negative NFS4ERR status code.
+ */
+static int nfs4_handle_migration(struct nfs_client *clp)
+{
+	const struct nfs4_state_maintenance_ops *ops =
+				clp->cl_mvops->state_renewal_ops;
+	struct nfs_server *server;
+	struct rpc_cred *cred;
+
+	dprintk("%s: migration reported on \"%s\"\n", __func__,
+			clp->cl_hostname);
+
+	spin_lock(&clp->cl_lock);
+	cred = ops->get_state_renewal_cred_locked(clp);
+	spin_unlock(&clp->cl_lock);
+	if (cred == NULL)
+		return -NFS4ERR_NOENT;
+
+	clp->cl_mig_gen++;
+restart:
+	rcu_read_lock();
+	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
+		int status;
+
+		if (server->mig_gen == clp->cl_mig_gen)
+			continue;
+		server->mig_gen = clp->cl_mig_gen;
+
+		if (!test_and_clear_bit(NFS_MIG_IN_TRANSITION,
+						&server->mig_status))
+			continue;
+
+		rcu_read_unlock();
+		status = nfs4_try_migration(server, cred);
+		if (status < 0) {
+			put_rpccred(cred);
+			return status;
+		}
+		goto restart;
+	}
+	rcu_read_unlock();
+	put_rpccred(cred);
+	return 0;
+}
+
+/*
+ * Test each nfs_server on the clp's cl_superblocks list to see
+ * if it's moved to another server.  Stop when the server no longer
+ * returns NFS4ERR_LEASE_MOVED.
+ */
+static int nfs4_handle_lease_moved(struct nfs_client *clp)
+{
+	const struct nfs4_state_maintenance_ops *ops =
+				clp->cl_mvops->state_renewal_ops;
+	struct nfs_server *server;
+	struct rpc_cred *cred;
+
+	dprintk("%s: lease moved reported on \"%s\"\n", __func__,
+			clp->cl_hostname);
+
+	spin_lock(&clp->cl_lock);
+	cred = ops->get_state_renewal_cred_locked(clp);
+	spin_unlock(&clp->cl_lock);
+	if (cred == NULL)
+		return -NFS4ERR_NOENT;
+
+	clp->cl_mig_gen++;
+restart:
+	rcu_read_lock();
+	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
+		struct inode *inode;
+		int status;
+
+		if (server->mig_gen == clp->cl_mig_gen)
+			continue;
+		server->mig_gen = clp->cl_mig_gen;
+
+		rcu_read_unlock();
+
+		inode = server->super->s_root->d_inode;
+		status = nfs4_proc_fsid_present(inode, cred);
+		if (status != -NFS4ERR_MOVED)
+			goto restart;	/* wasn't this one */
+		if (nfs4_try_migration(server, cred) == -NFS4ERR_LEASE_MOVED)
+			goto restart;	/* there are more */
+		goto out;
+	}
+	rcu_read_unlock();
+
+out:
+	put_rpccred(cred);
+	return 0;
+}
+
 /**
  * nfs4_discover_server_trunking - Detect server IP address trunking
  *
@@ -2017,9 +2229,10 @@
 		nfs41_handle_server_reboot(clp);
 	if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED |
 			    SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED |
-			    SEQ4_STATUS_ADMIN_STATE_REVOKED |
-			    SEQ4_STATUS_LEASE_MOVED))
+			    SEQ4_STATUS_ADMIN_STATE_REVOKED))
 		nfs41_handle_state_revoked(clp);
+	if (flags & SEQ4_STATUS_LEASE_MOVED)
+		nfs4_schedule_lease_moved_recovery(clp);
 	if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED)
 		nfs41_handle_recallable_state_revoked(clp);
 	if (flags & SEQ4_STATUS_BACKCHANNEL_FAULT)
@@ -2157,7 +2370,20 @@
 			status = nfs4_check_lease(clp);
 			if (status < 0)
 				goto out_error;
-			continue;
+		}
+
+		if (test_and_clear_bit(NFS4CLNT_MOVED, &clp->cl_state)) {
+			section = "migration";
+			status = nfs4_handle_migration(clp);
+			if (status < 0)
+				goto out_error;
+		}
+
+		if (test_and_clear_bit(NFS4CLNT_LEASE_MOVED, &clp->cl_state)) {
+			section = "lease moved";
+			status = nfs4_handle_lease_moved(clp);
+			if (status < 0)
+				goto out_error;
 		}
 
 		/* First recover reboot state... */
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c
index e26acdd..65ab0a0 100644
--- a/fs/nfs/nfs4super.c
+++ b/fs/nfs/nfs4super.c
@@ -261,9 +261,9 @@
 
 	res = nfs_follow_remote_path(root_mnt, export_path);
 
-	dfprintk(MOUNT, "<-- nfs4_try_mount() = %ld%s\n",
-			IS_ERR(res) ? PTR_ERR(res) : 0,
-			IS_ERR(res) ? " [error]" : "");
+	dfprintk(MOUNT, "<-- nfs4_try_mount() = %d%s\n",
+		 PTR_ERR_OR_ZERO(res),
+		 IS_ERR(res) ? " [error]" : "");
 	return res;
 }
 
@@ -319,9 +319,9 @@
 	data->mnt_path = export_path;
 
 	res = nfs_follow_remote_path(root_mnt, export_path);
-	dprintk("<-- nfs4_referral_mount() = %ld%s\n",
-			IS_ERR(res) ? PTR_ERR(res) : 0,
-			IS_ERR(res) ? " [error]" : "");
+	dprintk("<-- nfs4_referral_mount() = %d%s\n",
+		PTR_ERR_OR_ZERO(res),
+		IS_ERR(res) ? " [error]" : "");
 	return res;
 }
 
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 79210d2..5be2868 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -105,12 +105,8 @@
 #ifdef CONFIG_NFS_V4_SECURITY_LABEL
 /* PI(4 bytes) + LFS(4 bytes) + 1(for null terminator?) + MAXLABELLEN */
 #define	nfs4_label_maxsz	(4 + 4 + 1 + XDR_QUADLEN(NFS4_MAXLABELLEN))
-#define encode_readdir_space 24
-#define encode_readdir_bitmask_sz 3
 #else
 #define	nfs4_label_maxsz	0
-#define encode_readdir_space 20
-#define encode_readdir_bitmask_sz 2
 #endif
 /* We support only one layout type per file system */
 #define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8)
@@ -595,11 +591,13 @@
 #define NFS4_enc_getattr_sz	(compound_encode_hdr_maxsz + \
 				encode_sequence_maxsz + \
 				encode_putfh_maxsz + \
-				encode_getattr_maxsz)
+				encode_getattr_maxsz + \
+				encode_renew_maxsz)
 #define NFS4_dec_getattr_sz	(compound_decode_hdr_maxsz + \
 				decode_sequence_maxsz + \
 				decode_putfh_maxsz + \
-				decode_getattr_maxsz)
+				decode_getattr_maxsz + \
+				decode_renew_maxsz)
 #define NFS4_enc_lookup_sz	(compound_encode_hdr_maxsz + \
 				encode_sequence_maxsz + \
 				encode_putfh_maxsz + \
@@ -736,13 +734,15 @@
 				 encode_sequence_maxsz + \
 				 encode_putfh_maxsz + \
 				 encode_lookup_maxsz + \
-				 encode_fs_locations_maxsz)
+				 encode_fs_locations_maxsz + \
+				 encode_renew_maxsz)
 #define NFS4_dec_fs_locations_sz \
 				(compound_decode_hdr_maxsz + \
 				 decode_sequence_maxsz + \
 				 decode_putfh_maxsz + \
 				 decode_lookup_maxsz + \
-				 decode_fs_locations_maxsz)
+				 decode_fs_locations_maxsz + \
+				 decode_renew_maxsz)
 #define NFS4_enc_secinfo_sz 	(compound_encode_hdr_maxsz + \
 				encode_sequence_maxsz + \
 				encode_putfh_maxsz + \
@@ -751,6 +751,18 @@
 				decode_sequence_maxsz + \
 				decode_putfh_maxsz + \
 				decode_secinfo_maxsz)
+#define NFS4_enc_fsid_present_sz \
+				(compound_encode_hdr_maxsz + \
+				 encode_sequence_maxsz + \
+				 encode_putfh_maxsz + \
+				 encode_getfh_maxsz + \
+				 encode_renew_maxsz)
+#define NFS4_dec_fsid_present_sz \
+				(compound_decode_hdr_maxsz + \
+				 decode_sequence_maxsz + \
+				 decode_putfh_maxsz + \
+				 decode_getfh_maxsz + \
+				 decode_renew_maxsz)
 #if defined(CONFIG_NFS_V4_1)
 #define NFS4_enc_bind_conn_to_session_sz \
 				(compound_encode_hdr_maxsz + \
@@ -1565,6 +1577,8 @@
 	};
 	uint32_t dircount = readdir->count >> 1;
 	__be32 *p, verf[2];
+	uint32_t attrlen = 0;
+	unsigned int i;
 
 	if (readdir->plus) {
 		attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE|
@@ -1573,26 +1587,27 @@
 			FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV|
 			FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS|
 			FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
+		attrs[2] |= FATTR4_WORD2_SECURITY_LABEL;
 		dircount >>= 1;
 	}
 	/* Use mounted_on_fileid only if the server supports it */
 	if (!(readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID))
 		attrs[0] |= FATTR4_WORD0_FILEID;
+	for (i = 0; i < ARRAY_SIZE(attrs); i++) {
+		attrs[i] &= readdir->bitmask[i];
+		if (attrs[i] != 0)
+			attrlen = i+1;
+	}
 
 	encode_op_hdr(xdr, OP_READDIR, decode_readdir_maxsz, hdr);
 	encode_uint64(xdr, readdir->cookie);
 	encode_nfs4_verifier(xdr, &readdir->verifier);
-	p = reserve_space(xdr, encode_readdir_space);
+	p = reserve_space(xdr, 12 + (attrlen << 2));
 	*p++ = cpu_to_be32(dircount);
 	*p++ = cpu_to_be32(readdir->count);
-	*p++ = cpu_to_be32(encode_readdir_bitmask_sz);
-	*p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]);
-	*p   = cpu_to_be32(attrs[1] & readdir->bitmask[1]);
-	if (encode_readdir_bitmask_sz > 2) {
-		if (hdr->minorversion > 1)
-			attrs[2] |= FATTR4_WORD2_SECURITY_LABEL;
-		p++, *p++ = cpu_to_be32(attrs[2] & readdir->bitmask[2]);
-	}
+	*p++ = cpu_to_be32(attrlen);
+	for (i = 0; i < attrlen; i++)
+		*p++ = cpu_to_be32(attrs[i]);
 	memcpy(verf, readdir->verifier.data, sizeof(verf));
 
 	dprintk("%s: cookie = %llu, verifier = %08x:%08x, bitmap = %08x:%08x:%08x\n",
@@ -2687,11 +2702,20 @@
 
 	encode_compound_hdr(xdr, req, &hdr);
 	encode_sequence(xdr, &args->seq_args, &hdr);
-	encode_putfh(xdr, args->dir_fh, &hdr);
-	encode_lookup(xdr, args->name, &hdr);
-	replen = hdr.replen;	/* get the attribute into args->page */
-	encode_fs_locations(xdr, args->bitmask, &hdr);
+	if (args->migration) {
+		encode_putfh(xdr, args->fh, &hdr);
+		replen = hdr.replen;
+		encode_fs_locations(xdr, args->bitmask, &hdr);
+		if (args->renew)
+			encode_renew(xdr, args->clientid, &hdr);
+	} else {
+		encode_putfh(xdr, args->dir_fh, &hdr);
+		encode_lookup(xdr, args->name, &hdr);
+		replen = hdr.replen;
+		encode_fs_locations(xdr, args->bitmask, &hdr);
+	}
 
+	/* Set up reply kvec to capture returned fs_locations array. */
 	xdr_inline_pages(&req->rq_rcv_buf, replen << 2, &args->page,
 			0, PAGE_SIZE);
 	encode_nops(&hdr);
@@ -2715,6 +2739,26 @@
 	encode_nops(&hdr);
 }
 
+/*
+ * Encode FSID_PRESENT request
+ */
+static void nfs4_xdr_enc_fsid_present(struct rpc_rqst *req,
+				      struct xdr_stream *xdr,
+				      struct nfs4_fsid_present_arg *args)
+{
+	struct compound_hdr hdr = {
+		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
+	};
+
+	encode_compound_hdr(xdr, req, &hdr);
+	encode_sequence(xdr, &args->seq_args, &hdr);
+	encode_putfh(xdr, args->fh, &hdr);
+	encode_getfh(xdr, &hdr);
+	if (args->renew)
+		encode_renew(xdr, args->clientid, &hdr);
+	encode_nops(&hdr);
+}
+
 #if defined(CONFIG_NFS_V4_1)
 /*
  * BIND_CONN_TO_SESSION request
@@ -6824,13 +6868,26 @@
 	status = decode_putfh(xdr);
 	if (status)
 		goto out;
-	status = decode_lookup(xdr);
-	if (status)
-		goto out;
-	xdr_enter_page(xdr, PAGE_SIZE);
-	status = decode_getfattr_generic(xdr, &res->fs_locations->fattr,
+	if (res->migration) {
+		xdr_enter_page(xdr, PAGE_SIZE);
+		status = decode_getfattr_generic(xdr,
+					&res->fs_locations->fattr,
 					 NULL, res->fs_locations,
 					 NULL, res->fs_locations->server);
+		if (status)
+			goto out;
+		if (res->renew)
+			status = decode_renew(xdr);
+	} else {
+		status = decode_lookup(xdr);
+		if (status)
+			goto out;
+		xdr_enter_page(xdr, PAGE_SIZE);
+		status = decode_getfattr_generic(xdr,
+					&res->fs_locations->fattr,
+					 NULL, res->fs_locations,
+					 NULL, res->fs_locations->server);
+	}
 out:
 	return status;
 }
@@ -6859,6 +6916,34 @@
 	return status;
 }
 
+/*
+ * Decode FSID_PRESENT response
+ */
+static int nfs4_xdr_dec_fsid_present(struct rpc_rqst *rqstp,
+				     struct xdr_stream *xdr,
+				     struct nfs4_fsid_present_res *res)
+{
+	struct compound_hdr hdr;
+	int status;
+
+	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_getfh(xdr, res->fh);
+	if (status)
+		goto out;
+	if (res->renew)
+		status = decode_renew(xdr);
+out:
+	return status;
+}
+
 #if defined(CONFIG_NFS_V4_1)
 /*
  * Decode BIND_CONN_TO_SESSION response
@@ -7373,6 +7458,7 @@
 	PROC(FS_LOCATIONS,	enc_fs_locations,	dec_fs_locations),
 	PROC(RELEASE_LOCKOWNER,	enc_release_lockowner,	dec_release_lockowner),
 	PROC(SECINFO,		enc_secinfo,		dec_secinfo),
+	PROC(FSID_PRESENT,	enc_fsid_present,	dec_fsid_present),
 #if defined(CONFIG_NFS_V4_1)
 	PROC(EXCHANGE_ID,	enc_exchange_id,	dec_exchange_id),
 	PROC(CREATE_SESSION,	enc_create_session,	dec_create_session),
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index a03b9c6..317d6fc 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -497,7 +497,8 @@
 	static const struct {
 		rpc_authflavor_t flavour;
 		const char *str;
-	} sec_flavours[] = {
+	} sec_flavours[NFS_AUTH_INFO_MAX_FLAVORS] = {
+		/* update NFS_AUTH_INFO_MAX_FLAVORS when this list changes! */
 		{ RPC_AUTH_NULL, "null" },
 		{ RPC_AUTH_UNIX, "sys" },
 		{ RPC_AUTH_GSS_KRB5, "krb5" },
@@ -923,8 +924,7 @@
 		data->mount_server.port	= NFS_UNSPEC_PORT;
 		data->nfs_server.port	= NFS_UNSPEC_PORT;
 		data->nfs_server.protocol = XPRT_TRANSPORT_TCP;
-		data->auth_flavors[0]	= RPC_AUTH_MAXFLAVOR;
-		data->auth_flavor_len	= 0;
+		data->selected_flavor	= RPC_AUTH_MAXFLAVOR;
 		data->minorversion	= 0;
 		data->need_mount	= true;
 		data->net		= current->nsproxy->net_ns;
@@ -1019,14 +1019,53 @@
 	}
 }
 
-static void nfs_set_auth_parsed_mount_data(struct nfs_parsed_mount_data *data,
-		rpc_authflavor_t pseudoflavor)
+/*
+ * Add 'flavor' to 'auth_info' if not already present.
+ * Returns true if 'flavor' ends up in the list, false otherwise
+ */
+static bool nfs_auth_info_add(struct nfs_auth_info *auth_info,
+			      rpc_authflavor_t flavor)
 {
-	data->auth_flavors[0] = pseudoflavor;
-	data->auth_flavor_len = 1;
+	unsigned int i;
+	unsigned int max_flavor_len = (sizeof(auth_info->flavors) /
+				       sizeof(auth_info->flavors[0]));
+
+	/* make sure this flavor isn't already in the list */
+	for (i = 0; i < auth_info->flavor_len; i++) {
+		if (flavor == auth_info->flavors[i])
+			return true;
+	}
+
+	if (auth_info->flavor_len + 1 >= max_flavor_len) {
+		dfprintk(MOUNT, "NFS: too many sec= flavors\n");
+		return false;
+	}
+
+	auth_info->flavors[auth_info->flavor_len++] = flavor;
+	return true;
 }
 
 /*
+ * Return true if 'match' is in auth_info or auth_info is empty.
+ * Return false otherwise.
+ */
+bool nfs_auth_info_match(const struct nfs_auth_info *auth_info,
+			 rpc_authflavor_t match)
+{
+	int i;
+
+	if (!auth_info->flavor_len)
+		return true;
+
+	for (i = 0; i < auth_info->flavor_len; i++) {
+		if (auth_info->flavors[i] == match)
+			return true;
+	}
+	return false;
+}
+EXPORT_SYMBOL_GPL(nfs_auth_info_match);
+
+/*
  * Parse the value of the 'sec=' option.
  */
 static int nfs_parse_security_flavors(char *value,
@@ -1034,49 +1073,55 @@
 {
 	substring_t args[MAX_OPT_ARGS];
 	rpc_authflavor_t pseudoflavor;
+	char *p;
 
 	dfprintk(MOUNT, "NFS: parsing sec=%s option\n", value);
 
-	switch (match_token(value, nfs_secflavor_tokens, args)) {
-	case Opt_sec_none:
-		pseudoflavor = RPC_AUTH_NULL;
-		break;
-	case Opt_sec_sys:
-		pseudoflavor = RPC_AUTH_UNIX;
-		break;
-	case Opt_sec_krb5:
-		pseudoflavor = RPC_AUTH_GSS_KRB5;
-		break;
-	case Opt_sec_krb5i:
-		pseudoflavor = RPC_AUTH_GSS_KRB5I;
-		break;
-	case Opt_sec_krb5p:
-		pseudoflavor = RPC_AUTH_GSS_KRB5P;
-		break;
-	case Opt_sec_lkey:
-		pseudoflavor = RPC_AUTH_GSS_LKEY;
-		break;
-	case Opt_sec_lkeyi:
-		pseudoflavor = RPC_AUTH_GSS_LKEYI;
-		break;
-	case Opt_sec_lkeyp:
-		pseudoflavor = RPC_AUTH_GSS_LKEYP;
-		break;
-	case Opt_sec_spkm:
-		pseudoflavor = RPC_AUTH_GSS_SPKM;
-		break;
-	case Opt_sec_spkmi:
-		pseudoflavor = RPC_AUTH_GSS_SPKMI;
-		break;
-	case Opt_sec_spkmp:
-		pseudoflavor = RPC_AUTH_GSS_SPKMP;
-		break;
-	default:
-		return 0;
+	while ((p = strsep(&value, ":")) != NULL) {
+		switch (match_token(p, nfs_secflavor_tokens, args)) {
+		case Opt_sec_none:
+			pseudoflavor = RPC_AUTH_NULL;
+			break;
+		case Opt_sec_sys:
+			pseudoflavor = RPC_AUTH_UNIX;
+			break;
+		case Opt_sec_krb5:
+			pseudoflavor = RPC_AUTH_GSS_KRB5;
+			break;
+		case Opt_sec_krb5i:
+			pseudoflavor = RPC_AUTH_GSS_KRB5I;
+			break;
+		case Opt_sec_krb5p:
+			pseudoflavor = RPC_AUTH_GSS_KRB5P;
+			break;
+		case Opt_sec_lkey:
+			pseudoflavor = RPC_AUTH_GSS_LKEY;
+			break;
+		case Opt_sec_lkeyi:
+			pseudoflavor = RPC_AUTH_GSS_LKEYI;
+			break;
+		case Opt_sec_lkeyp:
+			pseudoflavor = RPC_AUTH_GSS_LKEYP;
+			break;
+		case Opt_sec_spkm:
+			pseudoflavor = RPC_AUTH_GSS_SPKM;
+			break;
+		case Opt_sec_spkmi:
+			pseudoflavor = RPC_AUTH_GSS_SPKMI;
+			break;
+		case Opt_sec_spkmp:
+			pseudoflavor = RPC_AUTH_GSS_SPKMP;
+			break;
+		default:
+			dfprintk(MOUNT,
+				 "NFS: sec= option '%s' not recognized\n", p);
+			return 0;
+		}
+
+		if (!nfs_auth_info_add(&mnt->auth_info, pseudoflavor))
+			return 0;
 	}
 
-	mnt->flags |= NFS_MOUNT_SECFLAVOUR;
-	nfs_set_auth_parsed_mount_data(mnt, pseudoflavor);
 	return 1;
 }
 
@@ -1623,12 +1668,14 @@
 }
 
 /*
- * Ensure that the specified authtype in args->auth_flavors[0] is supported by
- * the server. Returns 0 if it's ok, and -EACCES if not.
+ * Ensure that a specified authtype in args->auth_info is supported by
+ * the server. Returns 0 and sets args->selected_flavor if it's ok, and
+ * -EACCES if not.
  */
-static int nfs_verify_authflavor(struct nfs_parsed_mount_data *args,
+static int nfs_verify_authflavors(struct nfs_parsed_mount_data *args,
 			rpc_authflavor_t *server_authlist, unsigned int count)
 {
+	rpc_authflavor_t flavor = RPC_AUTH_MAXFLAVOR;
 	unsigned int i;
 
 	/*
@@ -1640,17 +1687,20 @@
 	 * can be used.
 	 */
 	for (i = 0; i < count; i++) {
-		if (args->auth_flavors[0] == server_authlist[i] ||
-		    server_authlist[i] == RPC_AUTH_NULL)
+		flavor = server_authlist[i];
+
+		if (nfs_auth_info_match(&args->auth_info, flavor) ||
+		    flavor == RPC_AUTH_NULL)
 			goto out;
 	}
 
-	dfprintk(MOUNT, "NFS: auth flavor %u not supported by server\n",
-		args->auth_flavors[0]);
+	dfprintk(MOUNT,
+		 "NFS: specified auth flavors not supported by server\n");
 	return -EACCES;
 
 out:
-	dfprintk(MOUNT, "NFS: using auth flavor %u\n", args->auth_flavors[0]);
+	args->selected_flavor = flavor;
+	dfprintk(MOUNT, "NFS: using auth flavor %u\n", args->selected_flavor);
 	return 0;
 }
 
@@ -1738,9 +1788,10 @@
 	 * Was a sec= authflavor specified in the options? First, verify
 	 * whether the server supports it, and then just try to use it if so.
 	 */
-	if (args->auth_flavor_len > 0) {
-		status = nfs_verify_authflavor(args, authlist, authlist_len);
-		dfprintk(MOUNT, "NFS: using auth flavor %u\n", args->auth_flavors[0]);
+	if (args->auth_info.flavor_len > 0) {
+		status = nfs_verify_authflavors(args, authlist, authlist_len);
+		dfprintk(MOUNT, "NFS: using auth flavor %u\n",
+			 args->selected_flavor);
 		if (status)
 			return ERR_PTR(status);
 		return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod);
@@ -1769,7 +1820,7 @@
 			/* Fallthrough */
 		}
 		dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", flavor);
-		nfs_set_auth_parsed_mount_data(args, flavor);
+		args->selected_flavor = flavor;
 		server = nfs_mod->rpc_ops->create_server(mount_info, nfs_mod);
 		if (!IS_ERR(server))
 			return server;
@@ -1785,7 +1836,7 @@
 
 	/* Last chance! Try AUTH_UNIX */
 	dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", RPC_AUTH_UNIX);
-	nfs_set_auth_parsed_mount_data(args, RPC_AUTH_UNIX);
+	args->selected_flavor = RPC_AUTH_UNIX;
 	return nfs_mod->rpc_ops->create_server(mount_info, nfs_mod);
 }
 
@@ -1972,9 +2023,9 @@
 		args->bsize		= data->bsize;
 
 		if (data->flags & NFS_MOUNT_SECFLAVOUR)
-			nfs_set_auth_parsed_mount_data(args, data->pseudoflavor);
+			args->selected_flavor = data->pseudoflavor;
 		else
-			nfs_set_auth_parsed_mount_data(args, RPC_AUTH_UNIX);
+			args->selected_flavor = RPC_AUTH_UNIX;
 		if (!args->nfs_server.hostname)
 			goto out_nomem;
 
@@ -2108,9 +2159,6 @@
 
 	nfs_set_port(sap, &args->nfs_server.port, port);
 
-	if (args->auth_flavor_len > 1)
-		goto out_bad_auth;
-
 	return nfs_parse_devname(dev_name,
 				   &args->nfs_server.hostname,
 				   max_namelen,
@@ -2130,10 +2178,6 @@
 out_no_address:
 	dfprintk(MOUNT, "NFS: mount program didn't pass remote address\n");
 	return -EINVAL;
-
-out_bad_auth:
-	dfprintk(MOUNT, "NFS: Too many RPC auth flavours specified\n");
-	return -EINVAL;
 }
 
 static int
@@ -2143,8 +2187,10 @@
 	if (data->flags != nfss->flags ||
 	    data->rsize != nfss->rsize ||
 	    data->wsize != nfss->wsize ||
+	    data->version != nfss->nfs_client->rpc_ops->version ||
+	    data->minorversion != nfss->nfs_client->cl_minorversion ||
 	    data->retrans != nfss->client->cl_timeout->to_retries ||
-	    data->auth_flavors[0] != nfss->client->cl_auth->au_flavor ||
+	    data->selected_flavor != nfss->client->cl_auth->au_flavor ||
 	    data->acregmin != nfss->acregmin / HZ ||
 	    data->acregmax != nfss->acregmax / HZ ||
 	    data->acdirmin != nfss->acdirmin / HZ ||
@@ -2189,7 +2235,8 @@
 	data->rsize = nfss->rsize;
 	data->wsize = nfss->wsize;
 	data->retrans = nfss->client->cl_timeout->to_retries;
-	nfs_set_auth_parsed_mount_data(data, nfss->client->cl_auth->au_flavor);
+	data->selected_flavor = nfss->client->cl_auth->au_flavor;
+	data->auth_info = nfss->auth_info;
 	data->acregmin = nfss->acregmin / HZ;
 	data->acregmax = nfss->acregmax / HZ;
 	data->acdirmin = nfss->acdirmin / HZ;
@@ -2197,12 +2244,14 @@
 	data->timeo = 10U * nfss->client->cl_timeout->to_initval / HZ;
 	data->nfs_server.port = nfss->port;
 	data->nfs_server.addrlen = nfss->nfs_client->cl_addrlen;
+	data->version = nfsvers;
+	data->minorversion = nfss->nfs_client->cl_minorversion;
 	memcpy(&data->nfs_server.address, &nfss->nfs_client->cl_addr,
 		data->nfs_server.addrlen);
 
 	/* overwrite those values with any that were specified */
-	error = nfs_parse_mount_options((char *)options, data);
-	if (error < 0)
+	error = -EINVAL;
+	if (!nfs_parse_mount_options((char *)options, data))
 		goto out;
 
 	/*
@@ -2332,7 +2381,7 @@
 		goto Ebusy;
 	if (a->acdirmax != b->acdirmax)
 		goto Ebusy;
-	if (b->flags & NFS_MOUNT_SECFLAVOUR &&
+	if (b->auth_info.flavor_len > 0 &&
 	   clnt_a->cl_auth->au_flavor != clnt_b->cl_auth->au_flavor)
 		goto Ebusy;
 	return 1;
@@ -2530,6 +2579,7 @@
 			mntroot = ERR_PTR(error);
 			goto error_splat_bdi;
 		}
+		server->super = s;
 	}
 
 	if (!s->s_root) {
@@ -2713,9 +2763,9 @@
 					   data->auth_flavours,
 					   sizeof(pseudoflavor)))
 				return -EFAULT;
-			nfs_set_auth_parsed_mount_data(args, pseudoflavor);
+			args->selected_flavor = pseudoflavor;
 		} else
-			nfs_set_auth_parsed_mount_data(args, RPC_AUTH_UNIX);
+			args->selected_flavor = RPC_AUTH_UNIX;
 
 		c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN);
 		if (IS_ERR(c))
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 8285de9..11d7894 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -493,7 +493,7 @@
 	unsigned long long fileid;
 	struct dentry *sdentry;
 	struct rpc_task *task;
-	int            error = -EIO;
+	int            error = -EBUSY;
 
 	dfprintk(VFS, "NFS: silly-rename(%pd2, ct=%d)\n",
 		dentry, d_count(dentry));
@@ -502,7 +502,6 @@
 	/*
 	 * We don't allow a dentry to be silly-renamed twice.
 	 */
-	error = -EBUSY;
 	if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
 		goto out;
 
diff --git a/fs/proc/array.c b/fs/proc/array.c
index cbd0f1b..1bd2077 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -183,6 +183,7 @@
 	seq_printf(m,
 		"State:\t%s\n"
 		"Tgid:\t%d\n"
+		"Ngid:\t%d\n"
 		"Pid:\t%d\n"
 		"PPid:\t%d\n"
 		"TracerPid:\t%d\n"
@@ -190,6 +191,7 @@
 		"Gid:\t%d\t%d\t%d\t%d\n",
 		get_task_state(p),
 		task_tgid_nr_ns(p, ns),
+		task_numa_group_id(p),
 		pid_nr_ns(pid, ns),
 		ppid, tpid,
 		from_kuid_munged(user_ns, cred->uid),
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 9f8ef9b..8eaa1ba 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -288,10 +288,14 @@
 static unsigned long proc_reg_get_unmapped_area(struct file *file, unsigned long orig_addr, unsigned long len, unsigned long pgoff, unsigned long flags)
 {
 	struct proc_dir_entry *pde = PDE(file_inode(file));
-	int rv = -EIO;
-	unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
+	unsigned long rv = -EIO;
+	unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long) = NULL;
 	if (use_pde(pde)) {
-		get_unmapped_area = pde->proc_fops->get_unmapped_area;
+#ifdef CONFIG_MMU
+		get_unmapped_area = current->mm->get_unmapped_area;
+#endif
+		if (pde->proc_fops->get_unmapped_area)
+			get_unmapped_area = pde->proc_fops->get_unmapped_area;
 		if (get_unmapped_area)
 			rv = get_unmapped_area(file, orig_addr, len, pgoff, flags);
 		unuse_pde(pde);
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index 106a835..70779b2 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -14,16 +14,13 @@
 #include <linux/of.h>
 #include <linux/export.h>
 #include <linux/slab.h>
-#include <asm/prom.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
 static inline void set_node_proc_entry(struct device_node *np,
 				       struct proc_dir_entry *de)
 {
-#ifdef HAVE_ARCH_DEVTREE_FIXUPS
 	np->pde = de;
-#endif
 }
 
 static struct proc_dir_entry *proc_device_tree;
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 7366e9d..390bdab 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -941,6 +941,8 @@
 		frame = pte_pfn(pte);
 		flags = PM_PRESENT;
 		page = vm_normal_page(vma, addr, pte);
+		if (pte_soft_dirty(pte))
+			flags2 |= __PM_SOFT_DIRTY;
 	} else if (is_swap_pte(pte)) {
 		swp_entry_t entry;
 		if (pte_swp_soft_dirty(pte))
@@ -960,7 +962,7 @@
 
 	if (page && !PageAnon(page))
 		flags |= PM_FILE;
-	if ((vma->vm_flags & VM_SOFTDIRTY) || pte_soft_dirty(pte))
+	if ((vma->vm_flags & VM_SOFTDIRTY))
 		flags2 |= __PM_SOFT_DIRTY;
 
 	*pme = make_pme(PM_PFRAME(frame) | PM_STATUS2(pm->v2, flags2) | flags);
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index dea86e8..2b363e2 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -117,6 +117,7 @@
 
 static void copy_to_if_dqblk(struct if_dqblk *dst, struct fs_disk_quota *src)
 {
+	memset(dst, 0, sizeof(*dst));
 	dst->dqb_bhardlimit = src->d_blk_hardlimit;
 	dst->dqb_bsoftlimit = src->d_blk_softlimit;
 	dst->dqb_curspace = src->d_bcount;
diff --git a/fs/select.c b/fs/select.c
index 55278a3..467bb1c 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -238,8 +238,7 @@
 
 	set_current_state(state);
 	if (!pwq->triggered)
-		rc = freezable_schedule_hrtimeout_range(expires, slack,
-							HRTIMER_MODE_ABS);
+		rc = schedule_hrtimeout_range(expires, slack, HRTIMER_MODE_ABS);
 	__set_current_state(TASK_RUNNING);
 
 	/*
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 3135c25..a290157 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -328,6 +328,8 @@
 				m->read_pos = offset;
 				retval = file->f_pos = offset;
 			}
+		} else {
+			file->f_pos = offset;
 		}
 	}
 	file->f_version = m->version;
diff --git a/fs/statfs.c b/fs/statfs.c
index c219e733..083dc0a 100644
--- a/fs/statfs.c
+++ b/fs/statfs.c
@@ -94,7 +94,7 @@
 
 int fd_statfs(int fd, struct kstatfs *st)
 {
-	struct fd f = fdget(fd);
+	struct fd f = fdget_raw(fd);
 	int error = -EBADF;
 	if (f.file) {
 		error = vfs_statfs(&f.file->f_path, st);
diff --git a/fs/sysfs/Makefile b/fs/sysfs/Makefile
index 7a1ceb9..8876ac1 100644
--- a/fs/sysfs/Makefile
+++ b/fs/sysfs/Makefile
@@ -2,5 +2,4 @@
 # Makefile for the sysfs virtual filesystem
 #
 
-obj-y		:= inode.o file.o dir.o symlink.o mount.o bin.o \
-		   group.o
+obj-y		:= inode.o file.o dir.o symlink.o mount.o group.o
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
deleted file mode 100644
index c590cab..0000000
--- a/fs/sysfs/bin.c
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
- * fs/sysfs/bin.c - sysfs binary file implementation
- *
- * Copyright (c) 2003 Patrick Mochel
- * Copyright (c) 2003 Matthew Wilcox
- * Copyright (c) 2004 Silicon Graphics, Inc.
- * Copyright (c) 2007 SUSE Linux Products GmbH
- * Copyright (c) 2007 Tejun Heo <teheo@suse.de>
- *
- * This file is released under the GPLv2.
- *
- * Please see Documentation/filesystems/sysfs.txt for more information.
- */
-
-#undef DEBUG
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/kobject.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/mm.h>
-#include <linux/uaccess.h>
-
-#include "sysfs.h"
-
-/*
- * There's one bin_buffer for each open file.
- *
- * filp->private_data points to bin_buffer and
- * sysfs_dirent->s_bin_attr.buffers points to a the bin_buffer s
- * sysfs_dirent->s_bin_attr.buffers is protected by sysfs_bin_lock
- */
-static DEFINE_MUTEX(sysfs_bin_lock);
-
-struct bin_buffer {
-	struct mutex			mutex;
-	void				*buffer;
-	int				mmapped;
-	const struct vm_operations_struct *vm_ops;
-	struct file			*file;
-	struct hlist_node		list;
-};
-
-static int
-fill_read(struct file *file, char *buffer, loff_t off, size_t count)
-{
-	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
-	struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
-	struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
-	int rc;
-
-	/* need attr_sd for attr, its parent for kobj */
-	if (!sysfs_get_active(attr_sd))
-		return -ENODEV;
-
-	rc = -EIO;
-	if (attr->read)
-		rc = attr->read(file, kobj, attr, buffer, off, count);
-
-	sysfs_put_active(attr_sd);
-
-	return rc;
-}
-
-static ssize_t
-read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
-{
-	struct bin_buffer *bb = file->private_data;
-	int size = file_inode(file)->i_size;
-	loff_t offs = *off;
-	int count = min_t(size_t, bytes, PAGE_SIZE);
-	char *temp;
-
-	if (!bytes)
-		return 0;
-
-	if (size) {
-		if (offs > size)
-			return 0;
-		if (offs + count > size)
-			count = size - offs;
-	}
-
-	temp = kmalloc(count, GFP_KERNEL);
-	if (!temp)
-		return -ENOMEM;
-
-	mutex_lock(&bb->mutex);
-
-	count = fill_read(file, bb->buffer, offs, count);
-	if (count < 0) {
-		mutex_unlock(&bb->mutex);
-		goto out_free;
-	}
-
-	memcpy(temp, bb->buffer, count);
-
-	mutex_unlock(&bb->mutex);
-
-	if (copy_to_user(userbuf, temp, count)) {
-		count = -EFAULT;
-		goto out_free;
-	}
-
-	pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count);
-
-	*off = offs + count;
-
- out_free:
-	kfree(temp);
-	return count;
-}
-
-static int
-flush_write(struct file *file, char *buffer, loff_t offset, size_t count)
-{
-	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
-	struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
-	struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
-	int rc;
-
-	/* need attr_sd for attr, its parent for kobj */
-	if (!sysfs_get_active(attr_sd))
-		return -ENODEV;
-
-	rc = -EIO;
-	if (attr->write)
-		rc = attr->write(file, kobj, attr, buffer, offset, count);
-
-	sysfs_put_active(attr_sd);
-
-	return rc;
-}
-
-static ssize_t write(struct file *file, const char __user *userbuf,
-		     size_t bytes, loff_t *off)
-{
-	struct bin_buffer *bb = file->private_data;
-	int size = file_inode(file)->i_size;
-	loff_t offs = *off;
-	int count = min_t(size_t, bytes, PAGE_SIZE);
-	char *temp;
-
-	if (!bytes)
-		return 0;
-
-	if (size) {
-		if (offs > size)
-			return 0;
-		if (offs + count > size)
-			count = size - offs;
-	}
-
-	temp = memdup_user(userbuf, count);
-	if (IS_ERR(temp))
-		return PTR_ERR(temp);
-
-	mutex_lock(&bb->mutex);
-
-	memcpy(bb->buffer, temp, count);
-
-	count = flush_write(file, bb->buffer, offs, count);
-	mutex_unlock(&bb->mutex);
-
-	if (count > 0)
-		*off = offs + count;
-
-	kfree(temp);
-	return count;
-}
-
-static void bin_vma_open(struct vm_area_struct *vma)
-{
-	struct file *file = vma->vm_file;
-	struct bin_buffer *bb = file->private_data;
-	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
-
-	if (!bb->vm_ops)
-		return;
-
-	if (!sysfs_get_active(attr_sd))
-		return;
-
-	if (bb->vm_ops->open)
-		bb->vm_ops->open(vma);
-
-	sysfs_put_active(attr_sd);
-}
-
-static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-	struct file *file = vma->vm_file;
-	struct bin_buffer *bb = file->private_data;
-	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
-	int ret;
-
-	if (!bb->vm_ops)
-		return VM_FAULT_SIGBUS;
-
-	if (!sysfs_get_active(attr_sd))
-		return VM_FAULT_SIGBUS;
-
-	ret = VM_FAULT_SIGBUS;
-	if (bb->vm_ops->fault)
-		ret = bb->vm_ops->fault(vma, vmf);
-
-	sysfs_put_active(attr_sd);
-	return ret;
-}
-
-static int bin_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-	struct file *file = vma->vm_file;
-	struct bin_buffer *bb = file->private_data;
-	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
-	int ret;
-
-	if (!bb->vm_ops)
-		return VM_FAULT_SIGBUS;
-
-	if (!sysfs_get_active(attr_sd))
-		return VM_FAULT_SIGBUS;
-
-	ret = 0;
-	if (bb->vm_ops->page_mkwrite)
-		ret = bb->vm_ops->page_mkwrite(vma, vmf);
-	else
-		file_update_time(file);
-
-	sysfs_put_active(attr_sd);
-	return ret;
-}
-
-static int bin_access(struct vm_area_struct *vma, unsigned long addr,
-		  void *buf, int len, int write)
-{
-	struct file *file = vma->vm_file;
-	struct bin_buffer *bb = file->private_data;
-	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
-	int ret;
-
-	if (!bb->vm_ops)
-		return -EINVAL;
-
-	if (!sysfs_get_active(attr_sd))
-		return -EINVAL;
-
-	ret = -EINVAL;
-	if (bb->vm_ops->access)
-		ret = bb->vm_ops->access(vma, addr, buf, len, write);
-
-	sysfs_put_active(attr_sd);
-	return ret;
-}
-
-#ifdef CONFIG_NUMA
-static int bin_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
-{
-	struct file *file = vma->vm_file;
-	struct bin_buffer *bb = file->private_data;
-	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
-	int ret;
-
-	if (!bb->vm_ops)
-		return 0;
-
-	if (!sysfs_get_active(attr_sd))
-		return -EINVAL;
-
-	ret = 0;
-	if (bb->vm_ops->set_policy)
-		ret = bb->vm_ops->set_policy(vma, new);
-
-	sysfs_put_active(attr_sd);
-	return ret;
-}
-
-static struct mempolicy *bin_get_policy(struct vm_area_struct *vma,
-					unsigned long addr)
-{
-	struct file *file = vma->vm_file;
-	struct bin_buffer *bb = file->private_data;
-	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
-	struct mempolicy *pol;
-
-	if (!bb->vm_ops)
-		return vma->vm_policy;
-
-	if (!sysfs_get_active(attr_sd))
-		return vma->vm_policy;
-
-	pol = vma->vm_policy;
-	if (bb->vm_ops->get_policy)
-		pol = bb->vm_ops->get_policy(vma, addr);
-
-	sysfs_put_active(attr_sd);
-	return pol;
-}
-
-static int bin_migrate(struct vm_area_struct *vma, const nodemask_t *from,
-			const nodemask_t *to, unsigned long flags)
-{
-	struct file *file = vma->vm_file;
-	struct bin_buffer *bb = file->private_data;
-	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
-	int ret;
-
-	if (!bb->vm_ops)
-		return 0;
-
-	if (!sysfs_get_active(attr_sd))
-		return 0;
-
-	ret = 0;
-	if (bb->vm_ops->migrate)
-		ret = bb->vm_ops->migrate(vma, from, to, flags);
-
-	sysfs_put_active(attr_sd);
-	return ret;
-}
-#endif
-
-static const struct vm_operations_struct bin_vm_ops = {
-	.open		= bin_vma_open,
-	.fault		= bin_fault,
-	.page_mkwrite	= bin_page_mkwrite,
-	.access		= bin_access,
-#ifdef CONFIG_NUMA
-	.set_policy	= bin_set_policy,
-	.get_policy	= bin_get_policy,
-	.migrate	= bin_migrate,
-#endif
-};
-
-static int mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct bin_buffer *bb = file->private_data;
-	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
-	struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
-	struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
-	int rc;
-
-	mutex_lock(&bb->mutex);
-
-	/* need attr_sd for attr, its parent for kobj */
-	rc = -ENODEV;
-	if (!sysfs_get_active(attr_sd))
-		goto out_unlock;
-
-	rc = -EINVAL;
-	if (!attr->mmap)
-		goto out_put;
-
-	rc = attr->mmap(file, kobj, attr, vma);
-	if (rc)
-		goto out_put;
-
-	/*
-	 * PowerPC's pci_mmap of legacy_mem uses shmem_zero_setup()
-	 * to satisfy versions of X which crash if the mmap fails: that
-	 * substitutes a new vm_file, and we don't then want bin_vm_ops.
-	 */
-	if (vma->vm_file != file)
-		goto out_put;
-
-	rc = -EINVAL;
-	if (bb->mmapped && bb->vm_ops != vma->vm_ops)
-		goto out_put;
-
-	/*
-	 * It is not possible to successfully wrap close.
-	 * So error if someone is trying to use close.
-	 */
-	rc = -EINVAL;
-	if (vma->vm_ops && vma->vm_ops->close)
-		goto out_put;
-
-	rc = 0;
-	bb->mmapped = 1;
-	bb->vm_ops = vma->vm_ops;
-	vma->vm_ops = &bin_vm_ops;
-out_put:
-	sysfs_put_active(attr_sd);
-out_unlock:
-	mutex_unlock(&bb->mutex);
-
-	return rc;
-}
-
-static int open(struct inode *inode, struct file *file)
-{
-	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
-	struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
-	struct bin_buffer *bb = NULL;
-	int error;
-
-	/* binary file operations requires both @sd and its parent */
-	if (!sysfs_get_active(attr_sd))
-		return -ENODEV;
-
-	error = -EACCES;
-	if ((file->f_mode & FMODE_WRITE) && !(attr->write || attr->mmap))
-		goto err_out;
-	if ((file->f_mode & FMODE_READ) && !(attr->read || attr->mmap))
-		goto err_out;
-
-	error = -ENOMEM;
-	bb = kzalloc(sizeof(*bb), GFP_KERNEL);
-	if (!bb)
-		goto err_out;
-
-	bb->buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
-	if (!bb->buffer)
-		goto err_out;
-
-	mutex_init(&bb->mutex);
-	bb->file = file;
-	file->private_data = bb;
-
-	mutex_lock(&sysfs_bin_lock);
-	hlist_add_head(&bb->list, &attr_sd->s_bin_attr.buffers);
-	mutex_unlock(&sysfs_bin_lock);
-
-	/* open succeeded, put active references */
-	sysfs_put_active(attr_sd);
-	return 0;
-
- err_out:
-	sysfs_put_active(attr_sd);
-	kfree(bb);
-	return error;
-}
-
-static int release(struct inode *inode, struct file *file)
-{
-	struct bin_buffer *bb = file->private_data;
-
-	mutex_lock(&sysfs_bin_lock);
-	hlist_del(&bb->list);
-	mutex_unlock(&sysfs_bin_lock);
-
-	kfree(bb->buffer);
-	kfree(bb);
-	return 0;
-}
-
-const struct file_operations bin_fops = {
-	.read		= read,
-	.write		= write,
-	.mmap		= mmap,
-	.llseek		= generic_file_llseek,
-	.open		= open,
-	.release	= release,
-};
-
-
-void unmap_bin_file(struct sysfs_dirent *attr_sd)
-{
-	struct bin_buffer *bb;
-
-	if (sysfs_type(attr_sd) != SYSFS_KOBJ_BIN_ATTR)
-		return;
-
-	mutex_lock(&sysfs_bin_lock);
-
-	hlist_for_each_entry(bb, &attr_sd->s_bin_attr.buffers, list) {
-		struct inode *inode = file_inode(bb->file);
-
-		unmap_mapping_range(inode->i_mapping, 0, 0, 1);
-	}
-
-	mutex_unlock(&sysfs_bin_lock);
-}
-
-/**
- *	sysfs_create_bin_file - create binary file for object.
- *	@kobj:	object.
- *	@attr:	attribute descriptor.
- */
-int sysfs_create_bin_file(struct kobject *kobj,
-			  const struct bin_attribute *attr)
-{
-	BUG_ON(!kobj || !kobj->sd || !attr);
-
-	return sysfs_add_file(kobj->sd, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
-}
-EXPORT_SYMBOL_GPL(sysfs_create_bin_file);
-
-/**
- *	sysfs_remove_bin_file - remove binary file for object.
- *	@kobj:	object.
- *	@attr:	attribute descriptor.
- */
-void sysfs_remove_bin_file(struct kobject *kobj,
-			   const struct bin_attribute *attr)
-{
-	sysfs_hash_and_remove(kobj->sd, NULL, attr->attr.name);
-}
-EXPORT_SYMBOL_GPL(sysfs_remove_bin_file);
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 4d83ced..5e73d66 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -26,21 +26,21 @@
 #include "sysfs.h"
 
 DEFINE_MUTEX(sysfs_mutex);
-DEFINE_SPINLOCK(sysfs_assoc_lock);
+DEFINE_SPINLOCK(sysfs_symlink_target_lock);
 
-#define to_sysfs_dirent(X) rb_entry((X), struct sysfs_dirent, s_rb);
+#define to_sysfs_dirent(X) rb_entry((X), struct sysfs_dirent, s_rb)
 
 static DEFINE_SPINLOCK(sysfs_ino_lock);
 static DEFINE_IDA(sysfs_ino_ida);
 
 /**
  *	sysfs_name_hash
- *	@ns:   Namespace tag to hash
  *	@name: Null terminated string to hash
+ *	@ns:   Namespace tag to hash
  *
  *	Returns 31 bit hash of ns + name (so it fits in an off_t )
  */
-static unsigned int sysfs_name_hash(const void *ns, const char *name)
+static unsigned int sysfs_name_hash(const char *name, const void *ns)
 {
 	unsigned long hash = init_name_hash();
 	unsigned int len = strlen(name);
@@ -56,8 +56,8 @@
 	return hash;
 }
 
-static int sysfs_name_compare(unsigned int hash, const void *ns,
-	const char *name, const struct sysfs_dirent *sd)
+static int sysfs_name_compare(unsigned int hash, const char *name,
+			      const void *ns, const struct sysfs_dirent *sd)
 {
 	if (hash != sd->s_hash)
 		return hash - sd->s_hash;
@@ -69,7 +69,7 @@
 static int sysfs_sd_compare(const struct sysfs_dirent *left,
 			    const struct sysfs_dirent *right)
 {
-	return sysfs_name_compare(left->s_hash, left->s_ns, left->s_name,
+	return sysfs_name_compare(left->s_hash, left->s_name, left->s_ns,
 				  right);
 }
 
@@ -132,24 +132,6 @@
 	rb_erase(&sd->s_rb, &sd->s_parent->s_dir.children);
 }
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-
-/* Test for attributes that want to ignore lockdep for read-locking */
-static bool ignore_lockdep(struct sysfs_dirent *sd)
-{
-	return sysfs_type(sd) == SYSFS_KOBJ_ATTR &&
-			sd->s_attr.attr->ignore_lockdep;
-}
-
-#else
-
-static inline bool ignore_lockdep(struct sysfs_dirent *sd)
-{
-	return true;
-}
-
-#endif
-
 /**
  *	sysfs_get_active - get an active reference to sysfs_dirent
  *	@sd: sysfs_dirent to get an active reference to
@@ -168,7 +150,7 @@
 	if (!atomic_inc_unless_negative(&sd->s_active))
 		return NULL;
 
-	if (likely(!ignore_lockdep(sd)))
+	if (likely(!sysfs_ignore_lockdep(sd)))
 		rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_);
 	return sd;
 }
@@ -187,7 +169,7 @@
 	if (unlikely(!sd))
 		return;
 
-	if (likely(!ignore_lockdep(sd)))
+	if (likely(!sysfs_ignore_lockdep(sd)))
 		rwsem_release(&sd->dep_map, 1, _RET_IP_);
 	v = atomic_dec_return(&sd->s_active);
 	if (likely(v != SD_DEACTIVATED_BIAS))
@@ -400,22 +382,19 @@
 /**
  *	sysfs_addrm_start - prepare for sysfs_dirent add/remove
  *	@acxt: pointer to sysfs_addrm_cxt to be used
- *	@parent_sd: parent sysfs_dirent
  *
- *	This function is called when the caller is about to add or
- *	remove sysfs_dirent under @parent_sd.  This function acquires
- *	sysfs_mutex.  @acxt is used to keep and pass context to
- *	other addrm functions.
+ *	This function is called when the caller is about to add or remove
+ *	sysfs_dirent.  This function acquires sysfs_mutex.  @acxt is used
+ *	to keep and pass context to other addrm functions.
  *
  *	LOCKING:
  *	Kernel thread context (may sleep).  sysfs_mutex is locked on
  *	return.
  */
-void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
-		       struct sysfs_dirent *parent_sd)
+void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt)
+	__acquires(sysfs_mutex)
 {
 	memset(acxt, 0, sizeof(*acxt));
-	acxt->parent_sd = parent_sd;
 
 	mutex_lock(&sysfs_mutex);
 }
@@ -424,10 +403,11 @@
  *	__sysfs_add_one - add sysfs_dirent to parent without warning
  *	@acxt: addrm context to use
  *	@sd: sysfs_dirent to be added
+ *	@parent_sd: the parent sysfs_dirent to add @sd to
  *
- *	Get @acxt->parent_sd and set sd->s_parent to it and increment
- *	nlink of parent inode if @sd is a directory and link into the
- *	children list of the parent.
+ *	Get @parent_sd and set @sd->s_parent to it and increment nlink of
+ *	the parent inode if @sd is a directory and link into the children
+ *	list of the parent.
  *
  *	This function should be called between calls to
  *	sysfs_addrm_start() and sysfs_addrm_finish() and should be
@@ -440,27 +420,28 @@
  *	0 on success, -EEXIST if entry with the given name already
  *	exists.
  */
-int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
+int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd,
+		    struct sysfs_dirent *parent_sd)
 {
 	struct sysfs_inode_attrs *ps_iattr;
 	int ret;
 
-	if (!!sysfs_ns_type(acxt->parent_sd) != !!sd->s_ns) {
+	if (!!sysfs_ns_type(parent_sd) != !!sd->s_ns) {
 		WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n",
-			sysfs_ns_type(acxt->parent_sd) ? "required" : "invalid",
-			acxt->parent_sd->s_name, sd->s_name);
+			sysfs_ns_type(parent_sd) ? "required" : "invalid",
+			parent_sd->s_name, sd->s_name);
 		return -EINVAL;
 	}
 
-	sd->s_hash = sysfs_name_hash(sd->s_ns, sd->s_name);
-	sd->s_parent = sysfs_get(acxt->parent_sd);
+	sd->s_hash = sysfs_name_hash(sd->s_name, sd->s_ns);
+	sd->s_parent = sysfs_get(parent_sd);
 
 	ret = sysfs_link_sibling(sd);
 	if (ret)
 		return ret;
 
 	/* Update timestamps on the parent */
-	ps_iattr = acxt->parent_sd->s_iattr;
+	ps_iattr = parent_sd->s_iattr;
 	if (ps_iattr) {
 		struct iattr *ps_iattrs = &ps_iattr->ia_iattr;
 		ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME;
@@ -490,14 +471,32 @@
 	return path;
 }
 
+void sysfs_warn_dup(struct sysfs_dirent *parent, const char *name)
+{
+	char *path;
+
+	path = kzalloc(PATH_MAX, GFP_KERNEL);
+	if (path) {
+		sysfs_pathname(parent, path);
+		strlcat(path, "/", PATH_MAX);
+		strlcat(path, name, PATH_MAX);
+	}
+
+	WARN(1, KERN_WARNING "sysfs: cannot create duplicate filename '%s'\n",
+	     path ? path : name);
+
+	kfree(path);
+}
+
 /**
  *	sysfs_add_one - add sysfs_dirent to parent
  *	@acxt: addrm context to use
  *	@sd: sysfs_dirent to be added
+ *	@parent_sd: the parent sysfs_dirent to add @sd to
  *
- *	Get @acxt->parent_sd and set sd->s_parent to it and increment
- *	nlink of parent inode if @sd is a directory and link into the
- *	children list of the parent.
+ *	Get @parent_sd and set @sd->s_parent to it and increment nlink of
+ *	the parent inode if @sd is a directory and link into the children
+ *	list of the parent.
  *
  *	This function should be called between calls to
  *	sysfs_addrm_start() and sysfs_addrm_finish() and should be
@@ -510,23 +509,15 @@
  *	0 on success, -EEXIST if entry with the given name already
  *	exists.
  */
-int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
+int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd,
+		  struct sysfs_dirent *parent_sd)
 {
 	int ret;
 
-	ret = __sysfs_add_one(acxt, sd);
-	if (ret == -EEXIST) {
-		char *path = kzalloc(PATH_MAX, GFP_KERNEL);
-		WARN(1, KERN_WARNING
-		     "sysfs: cannot create duplicate filename '%s'\n",
-		     (path == NULL) ? sd->s_name
-				    : (sysfs_pathname(acxt->parent_sd, path),
-				       strlcat(path, "/", PATH_MAX),
-				       strlcat(path, sd->s_name, PATH_MAX),
-				       path));
-		kfree(path);
-	}
+	ret = __sysfs_add_one(acxt, sd, parent_sd);
 
+	if (ret == -EEXIST)
+		sysfs_warn_dup(parent_sd, sd->s_name);
 	return ret;
 }
 
@@ -545,16 +536,22 @@
  *	LOCKING:
  *	Determined by sysfs_addrm_start().
  */
-void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
+static void sysfs_remove_one(struct sysfs_addrm_cxt *acxt,
+			     struct sysfs_dirent *sd)
 {
 	struct sysfs_inode_attrs *ps_iattr;
 
-	BUG_ON(sd->s_flags & SYSFS_FLAG_REMOVED);
+	/*
+	 * Removal can be called multiple times on the same node.  Only the
+	 * first invocation is effective and puts the base ref.
+	 */
+	if (sd->s_flags & SYSFS_FLAG_REMOVED)
+		return;
 
 	sysfs_unlink_sibling(sd);
 
 	/* Update timestamps on the parent */
-	ps_iattr = acxt->parent_sd->s_iattr;
+	ps_iattr = sd->s_parent->s_iattr;
 	if (ps_iattr) {
 		struct iattr *ps_iattrs = &ps_iattr->ia_iattr;
 		ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME;
@@ -577,6 +574,7 @@
  *	sysfs_mutex is released.
  */
 void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
+	__releases(sysfs_mutex)
 {
 	/* release resources acquired by sysfs_addrm_start() */
 	mutex_unlock(&sysfs_mutex);
@@ -588,7 +586,7 @@
 		acxt->removed = sd->u.removed_list;
 
 		sysfs_deactivate(sd);
-		unmap_bin_file(sd);
+		sysfs_unmap_bin_file(sd);
 		sysfs_put(sd);
 	}
 }
@@ -597,6 +595,7 @@
  *	sysfs_find_dirent - find sysfs_dirent with the given name
  *	@parent_sd: sysfs_dirent to search under
  *	@name: name to look for
+ *	@ns: the namespace tag to use
  *
  *	Look for sysfs_dirent with name @name under @parent_sd.
  *
@@ -607,8 +606,8 @@
  *	Pointer to sysfs_dirent if found, NULL if not.
  */
 struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
-				       const void *ns,
-				       const unsigned char *name)
+				       const unsigned char *name,
+				       const void *ns)
 {
 	struct rb_node *node = parent_sd->s_dir.children.rb_node;
 	unsigned int hash;
@@ -620,13 +619,13 @@
 		return NULL;
 	}
 
-	hash = sysfs_name_hash(ns, name);
+	hash = sysfs_name_hash(name, ns);
 	while (node) {
 		struct sysfs_dirent *sd;
 		int result;
 
 		sd = to_sysfs_dirent(node);
-		result = sysfs_name_compare(hash, ns, name, sd);
+		result = sysfs_name_compare(hash, name, ns, sd);
 		if (result < 0)
 			node = node->rb_left;
 		else if (result > 0)
@@ -638,9 +637,10 @@
 }
 
 /**
- *	sysfs_get_dirent - find and get sysfs_dirent with the given name
+ *	sysfs_get_dirent_ns - find and get sysfs_dirent with the given name
  *	@parent_sd: sysfs_dirent to search under
  *	@name: name to look for
+ *	@ns: the namespace tag to use
  *
  *	Look for sysfs_dirent with name @name under @parent_sd and get
  *	it if found.
@@ -651,24 +651,25 @@
  *	RETURNS:
  *	Pointer to sysfs_dirent if found, NULL if not.
  */
-struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
-				      const void *ns,
-				      const unsigned char *name)
+struct sysfs_dirent *sysfs_get_dirent_ns(struct sysfs_dirent *parent_sd,
+					 const unsigned char *name,
+					 const void *ns)
 {
 	struct sysfs_dirent *sd;
 
 	mutex_lock(&sysfs_mutex);
-	sd = sysfs_find_dirent(parent_sd, ns, name);
+	sd = sysfs_find_dirent(parent_sd, name, ns);
 	sysfs_get(sd);
 	mutex_unlock(&sysfs_mutex);
 
 	return sd;
 }
-EXPORT_SYMBOL_GPL(sysfs_get_dirent);
+EXPORT_SYMBOL_GPL(sysfs_get_dirent_ns);
 
 static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
-	enum kobj_ns_type type, const void *ns, const char *name,
-	struct sysfs_dirent **p_sd)
+		      enum kobj_ns_type type,
+		      const char *name, const void *ns,
+		      struct sysfs_dirent **p_sd)
 {
 	umode_t mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
 	struct sysfs_addrm_cxt acxt;
@@ -685,8 +686,8 @@
 	sd->s_dir.kobj = kobj;
 
 	/* link in */
-	sysfs_addrm_start(&acxt, parent_sd);
-	rc = sysfs_add_one(&acxt, sd);
+	sysfs_addrm_start(&acxt);
+	rc = sysfs_add_one(&acxt, sd, parent_sd);
 	sysfs_addrm_finish(&acxt);
 
 	if (rc == 0)
@@ -701,7 +702,7 @@
 			struct sysfs_dirent **p_sd)
 {
 	return create_dir(kobj, kobj->sd,
-			  KOBJ_NS_TYPE_NONE, NULL, name, p_sd);
+			  KOBJ_NS_TYPE_NONE, name, NULL, p_sd);
 }
 
 /**
@@ -730,14 +731,14 @@
 }
 
 /**
- *	sysfs_create_dir - create a directory for an object.
- *	@kobj:		object we're creating directory for.
+ * sysfs_create_dir_ns - create a directory for an object with a namespace tag
+ * @kobj: object we're creating directory for
+ * @ns: the namespace tag to use
  */
-int sysfs_create_dir(struct kobject *kobj)
+int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
 {
 	enum kobj_ns_type type;
 	struct sysfs_dirent *parent_sd, *sd;
-	const void *ns = NULL;
 	int error = 0;
 
 	BUG_ON(!kobj);
@@ -750,11 +751,9 @@
 	if (!parent_sd)
 		return -ENOENT;
 
-	if (sysfs_ns_type(parent_sd))
-		ns = kobj->ktype->namespace(kobj);
 	type = sysfs_read_ns_type(kobj);
 
-	error = create_dir(kobj, parent_sd, type, ns, kobject_name(kobj), &sd);
+	error = create_dir(kobj, parent_sd, type, kobject_name(kobj), ns, &sd);
 	if (!error)
 		kobj->sd = sd;
 	return error;
@@ -776,7 +775,7 @@
 	type = sysfs_ns_type(parent_sd);
 	ns = sysfs_info(dir->i_sb)->ns[type];
 
-	sd = sysfs_find_dirent(parent_sd, ns, dentry->d_name.name);
+	sd = sysfs_find_dirent(parent_sd, dentry->d_name.name, ns);
 
 	/* no such entry */
 	if (!sd) {
@@ -807,41 +806,128 @@
 	.setxattr	= sysfs_setxattr,
 };
 
-static void remove_dir(struct sysfs_dirent *sd)
+static struct sysfs_dirent *sysfs_leftmost_descendant(struct sysfs_dirent *pos)
 {
-	struct sysfs_addrm_cxt acxt;
+	struct sysfs_dirent *last;
 
-	sysfs_addrm_start(&acxt, sd->s_parent);
-	sysfs_remove_one(&acxt, sd);
-	sysfs_addrm_finish(&acxt);
+	while (true) {
+		struct rb_node *rbn;
+
+		last = pos;
+
+		if (sysfs_type(pos) != SYSFS_DIR)
+			break;
+
+		rbn = rb_first(&pos->s_dir.children);
+		if (!rbn)
+			break;
+
+		pos = to_sysfs_dirent(rbn);
+	}
+
+	return last;
 }
 
-void sysfs_remove_subdir(struct sysfs_dirent *sd)
+/**
+ * sysfs_next_descendant_post - find the next descendant for post-order walk
+ * @pos: the current position (%NULL to initiate traversal)
+ * @root: sysfs_dirent whose descendants to walk
+ *
+ * Find the next descendant to visit for post-order traversal of @root's
+ * descendants.  @root is included in the iteration and the last node to be
+ * visited.
+ */
+static struct sysfs_dirent *sysfs_next_descendant_post(struct sysfs_dirent *pos,
+						       struct sysfs_dirent *root)
 {
-	remove_dir(sd);
+	struct rb_node *rbn;
+
+	lockdep_assert_held(&sysfs_mutex);
+
+	/* if first iteration, visit leftmost descendant which may be root */
+	if (!pos)
+		return sysfs_leftmost_descendant(root);
+
+	/* if we visited @root, we're done */
+	if (pos == root)
+		return NULL;
+
+	/* if there's an unvisited sibling, visit its leftmost descendant */
+	rbn = rb_next(&pos->s_rb);
+	if (rbn)
+		return sysfs_leftmost_descendant(to_sysfs_dirent(rbn));
+
+	/* no sibling left, visit parent */
+	return pos->s_parent;
 }
 
-
-static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd)
+static void __sysfs_remove(struct sysfs_addrm_cxt *acxt,
+			   struct sysfs_dirent *sd)
 {
-	struct sysfs_addrm_cxt acxt;
-	struct rb_node *pos;
+	struct sysfs_dirent *pos, *next;
 
-	if (!dir_sd)
+	if (!sd)
 		return;
 
-	pr_debug("sysfs %s: removing dir\n", dir_sd->s_name);
-	sysfs_addrm_start(&acxt, dir_sd);
-	pos = rb_first(&dir_sd->s_dir.children);
-	while (pos) {
-		struct sysfs_dirent *sd = to_sysfs_dirent(pos);
-		pos = rb_next(pos);
-		if (sysfs_type(sd) != SYSFS_DIR)
-			sysfs_remove_one(&acxt, sd);
+	pr_debug("sysfs %s: removing\n", sd->s_name);
+
+	next = NULL;
+	do {
+		pos = next;
+		next = sysfs_next_descendant_post(pos, sd);
+		if (pos)
+			sysfs_remove_one(acxt, pos);
+	} while (next);
+}
+
+/**
+ * sysfs_remove - remove a sysfs_dirent recursively
+ * @sd: the sysfs_dirent to remove
+ *
+ * Remove @sd along with all its subdirectories and files.
+ */
+void sysfs_remove(struct sysfs_dirent *sd)
+{
+	struct sysfs_addrm_cxt acxt;
+
+	sysfs_addrm_start(&acxt);
+	__sysfs_remove(&acxt, sd);
+	sysfs_addrm_finish(&acxt);
+}
+
+/**
+ * sysfs_hash_and_remove - find a sysfs_dirent by name and remove it
+ * @dir_sd: parent of the target
+ * @name: name of the sysfs_dirent to remove
+ * @ns: namespace tag of the sysfs_dirent to remove
+ *
+ * Look for the sysfs_dirent with @name and @ns under @dir_sd and remove
+ * it.  Returns 0 on success, -ENOENT if such entry doesn't exist.
+ */
+int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name,
+			  const void *ns)
+{
+	struct sysfs_addrm_cxt acxt;
+	struct sysfs_dirent *sd;
+
+	if (!dir_sd) {
+		WARN(1, KERN_WARNING "sysfs: can not remove '%s', no directory\n",
+			name);
+		return -ENOENT;
 	}
+
+	sysfs_addrm_start(&acxt);
+
+	sd = sysfs_find_dirent(dir_sd, name, ns);
+	if (sd)
+		__sysfs_remove(&acxt, sd);
+
 	sysfs_addrm_finish(&acxt);
 
-	remove_dir(dir_sd);
+	if (sd)
+		return 0;
+	else
+		return -ENOENT;
 }
 
 /**
@@ -852,21 +938,34 @@
  *	the directory before we remove the directory, and we've inlined
  *	what used to be sysfs_rmdir() below, instead of calling separately.
  */
-
 void sysfs_remove_dir(struct kobject *kobj)
 {
 	struct sysfs_dirent *sd = kobj->sd;
 
-	spin_lock(&sysfs_assoc_lock);
+	/*
+	 * In general, kboject owner is responsible for ensuring removal
+	 * doesn't race with other operations and sysfs doesn't provide any
+	 * protection; however, when @kobj is used as a symlink target, the
+	 * symlinking entity usually doesn't own @kobj and thus has no
+	 * control over removal.  @kobj->sd may be removed anytime and
+	 * symlink code may end up dereferencing an already freed sd.
+	 *
+	 * sysfs_symlink_target_lock synchronizes @kobj->sd disassociation
+	 * against symlink operations so that symlink code can safely
+	 * dereference @kobj->sd.
+	 */
+	spin_lock(&sysfs_symlink_target_lock);
 	kobj->sd = NULL;
-	spin_unlock(&sysfs_assoc_lock);
+	spin_unlock(&sysfs_symlink_target_lock);
 
-	__sysfs_remove_dir(sd);
+	if (sd) {
+		WARN_ON_ONCE(sysfs_type(sd) != SYSFS_DIR);
+		sysfs_remove(sd);
+	}
 }
 
-int sysfs_rename(struct sysfs_dirent *sd,
-	struct sysfs_dirent *new_parent_sd, const void *new_ns,
-	const char *new_name)
+int sysfs_rename(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent_sd,
+		 const char *new_name, const void *new_ns)
 {
 	int error;
 
@@ -878,7 +977,7 @@
 		goto out;	/* nothing to rename */
 
 	error = -EEXIST;
-	if (sysfs_find_dirent(new_parent_sd, new_ns, new_name))
+	if (sysfs_find_dirent(new_parent_sd, new_name, new_ns))
 		goto out;
 
 	/* rename sysfs_dirent */
@@ -899,7 +998,7 @@
 	sysfs_get(new_parent_sd);
 	sysfs_put(sd->s_parent);
 	sd->s_ns = new_ns;
-	sd->s_hash = sysfs_name_hash(sd->s_ns, sd->s_name);
+	sd->s_hash = sysfs_name_hash(sd->s_name, sd->s_ns);
 	sd->s_parent = new_parent_sd;
 	sysfs_link_sibling(sd);
 
@@ -909,30 +1008,25 @@
 	return error;
 }
 
-int sysfs_rename_dir(struct kobject *kobj, const char *new_name)
+int sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name,
+			const void *new_ns)
 {
 	struct sysfs_dirent *parent_sd = kobj->sd->s_parent;
-	const void *new_ns = NULL;
 
-	if (sysfs_ns_type(parent_sd))
-		new_ns = kobj->ktype->namespace(kobj);
-
-	return sysfs_rename(kobj->sd, parent_sd, new_ns, new_name);
+	return sysfs_rename(kobj->sd, parent_sd, new_name, new_ns);
 }
 
-int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj)
+int sysfs_move_dir_ns(struct kobject *kobj, struct kobject *new_parent_kobj,
+		      const void *new_ns)
 {
 	struct sysfs_dirent *sd = kobj->sd;
 	struct sysfs_dirent *new_parent_sd;
-	const void *new_ns = NULL;
 
 	BUG_ON(!sd->s_parent);
-	if (sysfs_ns_type(sd->s_parent))
-		new_ns = kobj->ktype->namespace(kobj);
 	new_parent_sd = new_parent_kobj && new_parent_kobj->sd ?
 		new_parent_kobj->sd : &sysfs_root;
 
-	return sysfs_rename(sd, new_parent_sd, new_ns, sd->s_name);
+	return sysfs_rename(sd, new_parent_sd, sd->s_name, new_ns);
 }
 
 /* Relationship between s_mode and the DT_xxx types */
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 15ef5eb..79b5da2 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -21,70 +21,114 @@
 #include <linux/mutex.h>
 #include <linux/limits.h>
 #include <linux/uaccess.h>
+#include <linux/seq_file.h>
+#include <linux/mm.h>
 
 #include "sysfs.h"
 
 /*
- * There's one sysfs_buffer for each open file and one
- * sysfs_open_dirent for each sysfs_dirent with one or more open
- * files.
+ * There's one sysfs_open_file for each open file and one sysfs_open_dirent
+ * for each sysfs_dirent with one or more open files.
  *
- * filp->private_data points to sysfs_buffer and
- * sysfs_dirent->s_attr.open points to sysfs_open_dirent.  s_attr.open
- * is protected by sysfs_open_dirent_lock.
+ * sysfs_dirent->s_attr.open points to sysfs_open_dirent.  s_attr.open is
+ * protected by sysfs_open_dirent_lock.
+ *
+ * filp->private_data points to seq_file whose ->private points to
+ * sysfs_open_file.  sysfs_open_files are chained at
+ * sysfs_open_dirent->files, which is protected by sysfs_open_file_mutex.
  */
 static DEFINE_SPINLOCK(sysfs_open_dirent_lock);
+static DEFINE_MUTEX(sysfs_open_file_mutex);
 
 struct sysfs_open_dirent {
 	atomic_t		refcnt;
 	atomic_t		event;
 	wait_queue_head_t	poll;
-	struct list_head	buffers; /* goes through sysfs_buffer.list */
+	struct list_head	files; /* goes through sysfs_open_file.list */
 };
 
-struct sysfs_buffer {
-	size_t			count;
-	loff_t			pos;
-	char			*page;
-	const struct sysfs_ops	*ops;
+struct sysfs_open_file {
+	struct sysfs_dirent	*sd;
+	struct file		*file;
 	struct mutex		mutex;
-	int			needs_read_fill;
 	int			event;
 	struct list_head	list;
+
+	bool			mmapped;
+	const struct vm_operations_struct *vm_ops;
 };
 
-/**
- *	fill_read_buffer - allocate and fill buffer from object.
- *	@dentry:	dentry pointer.
- *	@buffer:	data buffer for file.
- *
- *	Allocate @buffer->page, if it hasn't been already, then call the
- *	kobject's show() method to fill the buffer with this attribute's
- *	data.
- *	This is called only once, on the file's first read unless an error
- *	is returned.
- */
-static int fill_read_buffer(struct dentry *dentry, struct sysfs_buffer *buffer)
+static bool sysfs_is_bin(struct sysfs_dirent *sd)
 {
-	struct sysfs_dirent *attr_sd = dentry->d_fsdata;
-	struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
-	const struct sysfs_ops *ops = buffer->ops;
-	int ret = 0;
+	return sysfs_type(sd) == SYSFS_KOBJ_BIN_ATTR;
+}
+
+static struct sysfs_open_file *sysfs_of(struct file *file)
+{
+	return ((struct seq_file *)file->private_data)->private;
+}
+
+/*
+ * Determine ktype->sysfs_ops for the given sysfs_dirent.  This function
+ * must be called while holding an active reference.
+ */
+static const struct sysfs_ops *sysfs_file_ops(struct sysfs_dirent *sd)
+{
+	struct kobject *kobj = sd->s_parent->s_dir.kobj;
+
+	if (!sysfs_ignore_lockdep(sd))
+		lockdep_assert_held(sd);
+	return kobj->ktype ? kobj->ktype->sysfs_ops : NULL;
+}
+
+/*
+ * Reads on sysfs are handled through seq_file, which takes care of hairy
+ * details like buffering and seeking.  The following function pipes
+ * sysfs_ops->show() result through seq_file.
+ */
+static int sysfs_seq_show(struct seq_file *sf, void *v)
+{
+	struct sysfs_open_file *of = sf->private;
+	struct kobject *kobj = of->sd->s_parent->s_dir.kobj;
+	const struct sysfs_ops *ops;
+	char *buf;
 	ssize_t count;
 
-	if (!buffer->page)
-		buffer->page = (char *) get_zeroed_page(GFP_KERNEL);
-	if (!buffer->page)
-		return -ENOMEM;
+	/* acquire buffer and ensure that it's >= PAGE_SIZE */
+	count = seq_get_buf(sf, &buf);
+	if (count < PAGE_SIZE) {
+		seq_commit(sf, -1);
+		return 0;
+	}
 
-	/* need attr_sd for attr and ops, its parent for kobj */
-	if (!sysfs_get_active(attr_sd))
+	/*
+	 * Need @of->sd for attr and ops, its parent for kobj.  @of->mutex
+	 * nests outside active ref and is just to ensure that the ops
+	 * aren't called concurrently for the same open file.
+	 */
+	mutex_lock(&of->mutex);
+	if (!sysfs_get_active(of->sd)) {
+		mutex_unlock(&of->mutex);
 		return -ENODEV;
+	}
 
-	buffer->event = atomic_read(&attr_sd->s_attr.open->event);
-	count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page);
+	of->event = atomic_read(&of->sd->s_attr.open->event);
 
-	sysfs_put_active(attr_sd);
+	/*
+	 * Lookup @ops and invoke show().  Control may reach here via seq
+	 * file lseek even if @ops->show() isn't implemented.
+	 */
+	ops = sysfs_file_ops(of->sd);
+	if (ops->show)
+		count = ops->show(kobj, of->sd->s_attr.attr, buf);
+	else
+		count = 0;
+
+	sysfs_put_active(of->sd);
+	mutex_unlock(&of->mutex);
+
+	if (count < 0)
+		return count;
 
 	/*
 	 * The code works fine with PAGE_SIZE return but it's likely to
@@ -96,155 +140,389 @@
 		/* Try to struggle along */
 		count = PAGE_SIZE - 1;
 	}
-	if (count >= 0) {
-		buffer->needs_read_fill = 0;
-		buffer->count = count;
-	} else {
-		ret = count;
-	}
-	return ret;
+	seq_commit(sf, count);
+	return 0;
 }
 
-/**
- *	sysfs_read_file - read an attribute.
- *	@file:	file pointer.
- *	@buf:	buffer to fill.
- *	@count:	number of bytes to read.
- *	@ppos:	starting offset in file.
- *
- *	Userspace wants to read an attribute file. The attribute descriptor
- *	is in the file's ->d_fsdata. The target object is in the directory's
- *	->d_fsdata.
- *
- *	We call fill_read_buffer() to allocate and fill the buffer from the
- *	object's show() method exactly once (if the read is happening from
- *	the beginning of the file). That should fill the entire buffer with
- *	all the data the object has to offer for that attribute.
- *	We then call flush_read_buffer() to copy the buffer to userspace
- *	in the increments specified.
+/*
+ * Read method for bin files.  As reading a bin file can have side-effects,
+ * the exact offset and bytes specified in read(2) call should be passed to
+ * the read callback making it difficult to use seq_file.  Implement
+ * simplistic custom buffering for bin files.
  */
-
-static ssize_t
-sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+static ssize_t sysfs_bin_read(struct file *file, char __user *userbuf,
+			      size_t bytes, loff_t *off)
 {
-	struct sysfs_buffer *buffer = file->private_data;
-	ssize_t retval = 0;
+	struct sysfs_open_file *of = sysfs_of(file);
+	struct bin_attribute *battr = of->sd->s_attr.bin_attr;
+	struct kobject *kobj = of->sd->s_parent->s_dir.kobj;
+	loff_t size = file_inode(file)->i_size;
+	int count = min_t(size_t, bytes, PAGE_SIZE);
+	loff_t offs = *off;
+	char *buf;
 
-	mutex_lock(&buffer->mutex);
-	if (buffer->needs_read_fill || *ppos == 0) {
-		retval = fill_read_buffer(file->f_path.dentry, buffer);
-		if (retval)
-			goto out;
+	if (!bytes)
+		return 0;
+
+	if (size) {
+		if (offs > size)
+			return 0;
+		if (offs + count > size)
+			count = size - offs;
 	}
-	pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
-		 __func__, count, *ppos, buffer->page);
-	retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
-					 buffer->count);
-out:
-	mutex_unlock(&buffer->mutex);
-	return retval;
-}
 
-/**
- *	fill_write_buffer - copy buffer from userspace.
- *	@buffer:	data buffer for file.
- *	@buf:		data from user.
- *	@count:		number of bytes in @userbuf.
- *
- *	Allocate @buffer->page if it hasn't been already, then
- *	copy the user-supplied buffer into it.
- */
-static int fill_write_buffer(struct sysfs_buffer *buffer,
-			     const char __user *buf, size_t count)
-{
-	int error;
-
-	if (!buffer->page)
-		buffer->page = (char *)get_zeroed_page(GFP_KERNEL);
-	if (!buffer->page)
+	buf = kmalloc(count, GFP_KERNEL);
+	if (!buf)
 		return -ENOMEM;
 
-	if (count >= PAGE_SIZE)
-		count = PAGE_SIZE - 1;
-	error = copy_from_user(buffer->page, buf, count);
-	buffer->needs_read_fill = 1;
-	/* if buf is assumed to contain a string, terminate it by \0,
-	   so e.g. sscanf() can scan the string easily */
-	buffer->page[count] = 0;
-	return error ? -EFAULT : count;
+	/* need of->sd for battr, its parent for kobj */
+	mutex_lock(&of->mutex);
+	if (!sysfs_get_active(of->sd)) {
+		count = -ENODEV;
+		mutex_unlock(&of->mutex);
+		goto out_free;
+	}
+
+	if (battr->read)
+		count = battr->read(file, kobj, battr, buf, offs, count);
+	else
+		count = -EIO;
+
+	sysfs_put_active(of->sd);
+	mutex_unlock(&of->mutex);
+
+	if (count < 0)
+		goto out_free;
+
+	if (copy_to_user(userbuf, buf, count)) {
+		count = -EFAULT;
+		goto out_free;
+	}
+
+	pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count);
+
+	*off = offs + count;
+
+ out_free:
+	kfree(buf);
+	return count;
 }
 
-
 /**
- *	flush_write_buffer - push buffer to kobject.
- *	@dentry:	dentry to the attribute
- *	@buffer:	data buffer for file.
- *	@count:		number of bytes
+ * flush_write_buffer - push buffer to kobject
+ * @of: open file
+ * @buf: data buffer for file
+ * @off: file offset to write to
+ * @count: number of bytes
  *
- *	Get the correct pointers for the kobject and the attribute we're
- *	dealing with, then call the store() method for the attribute,
- *	passing the buffer that we acquired in fill_write_buffer().
+ * Get the correct pointers for the kobject and the attribute we're dealing
+ * with, then call the store() method for it with @buf.
  */
-static int flush_write_buffer(struct dentry *dentry,
-			      struct sysfs_buffer *buffer, size_t count)
+static int flush_write_buffer(struct sysfs_open_file *of, char *buf, loff_t off,
+			      size_t count)
 {
-	struct sysfs_dirent *attr_sd = dentry->d_fsdata;
-	struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
-	const struct sysfs_ops *ops = buffer->ops;
-	int rc;
+	struct kobject *kobj = of->sd->s_parent->s_dir.kobj;
+	int rc = 0;
 
-	/* need attr_sd for attr and ops, its parent for kobj */
-	if (!sysfs_get_active(attr_sd))
+	/*
+	 * Need @of->sd for attr and ops, its parent for kobj.  @of->mutex
+	 * nests outside active ref and is just to ensure that the ops
+	 * aren't called concurrently for the same open file.
+	 */
+	mutex_lock(&of->mutex);
+	if (!sysfs_get_active(of->sd)) {
+		mutex_unlock(&of->mutex);
 		return -ENODEV;
+	}
 
-	rc = ops->store(kobj, attr_sd->s_attr.attr, buffer->page, count);
+	if (sysfs_is_bin(of->sd)) {
+		struct bin_attribute *battr = of->sd->s_attr.bin_attr;
 
-	sysfs_put_active(attr_sd);
+		rc = -EIO;
+		if (battr->write)
+			rc = battr->write(of->file, kobj, battr, buf, off,
+					  count);
+	} else {
+		const struct sysfs_ops *ops = sysfs_file_ops(of->sd);
+
+		rc = ops->store(kobj, of->sd->s_attr.attr, buf, count);
+	}
+
+	sysfs_put_active(of->sd);
+	mutex_unlock(&of->mutex);
 
 	return rc;
 }
 
-
 /**
- *	sysfs_write_file - write an attribute.
- *	@file:	file pointer
- *	@buf:	data to write
- *	@count:	number of bytes
- *	@ppos:	starting offset
+ * sysfs_write_file - write an attribute
+ * @file: file pointer
+ * @user_buf: data to write
+ * @count: number of bytes
+ * @ppos: starting offset
  *
- *	Similar to sysfs_read_file(), though working in the opposite direction.
- *	We allocate and fill the data from the user in fill_write_buffer(),
- *	then push it to the kobject in flush_write_buffer().
- *	There is no easy way for us to know if userspace is only doing a partial
- *	write, so we don't support them. We expect the entire buffer to come
- *	on the first write.
- *	Hint: if you're writing a value, first read the file, modify only the
- *	the value you're changing, then write entire buffer back.
+ * Copy data in from userland and pass it to the matching
+ * sysfs_ops->store() by invoking flush_write_buffer().
+ *
+ * There is no easy way for us to know if userspace is only doing a partial
+ * write, so we don't support them. We expect the entire buffer to come on
+ * the first write.  Hint: if you're writing a value, first read the file,
+ * modify only the the value you're changing, then write entire buffer
+ * back.
  */
-static ssize_t sysfs_write_file(struct file *file, const char __user *buf,
+static ssize_t sysfs_write_file(struct file *file, const char __user *user_buf,
 				size_t count, loff_t *ppos)
 {
-	struct sysfs_buffer *buffer = file->private_data;
-	ssize_t len;
+	struct sysfs_open_file *of = sysfs_of(file);
+	ssize_t len = min_t(size_t, count, PAGE_SIZE);
+	loff_t size = file_inode(file)->i_size;
+	char *buf;
 
-	mutex_lock(&buffer->mutex);
-	len = fill_write_buffer(buffer, buf, count);
-	if (len > 0)
-		len = flush_write_buffer(file->f_path.dentry, buffer, len);
+	if (sysfs_is_bin(of->sd) && size) {
+		if (size <= *ppos)
+			return 0;
+		len = min_t(ssize_t, len, size - *ppos);
+	}
+
+	if (!len)
+		return 0;
+
+	buf = kmalloc(len + 1, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	if (copy_from_user(buf, user_buf, len)) {
+		len = -EFAULT;
+		goto out_free;
+	}
+	buf[len] = '\0';	/* guarantee string termination */
+
+	len = flush_write_buffer(of, buf, *ppos, len);
 	if (len > 0)
 		*ppos += len;
-	mutex_unlock(&buffer->mutex);
+out_free:
+	kfree(buf);
 	return len;
 }
 
+static void sysfs_bin_vma_open(struct vm_area_struct *vma)
+{
+	struct file *file = vma->vm_file;
+	struct sysfs_open_file *of = sysfs_of(file);
+
+	if (!of->vm_ops)
+		return;
+
+	if (!sysfs_get_active(of->sd))
+		return;
+
+	if (of->vm_ops->open)
+		of->vm_ops->open(vma);
+
+	sysfs_put_active(of->sd);
+}
+
+static int sysfs_bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct file *file = vma->vm_file;
+	struct sysfs_open_file *of = sysfs_of(file);
+	int ret;
+
+	if (!of->vm_ops)
+		return VM_FAULT_SIGBUS;
+
+	if (!sysfs_get_active(of->sd))
+		return VM_FAULT_SIGBUS;
+
+	ret = VM_FAULT_SIGBUS;
+	if (of->vm_ops->fault)
+		ret = of->vm_ops->fault(vma, vmf);
+
+	sysfs_put_active(of->sd);
+	return ret;
+}
+
+static int sysfs_bin_page_mkwrite(struct vm_area_struct *vma,
+				  struct vm_fault *vmf)
+{
+	struct file *file = vma->vm_file;
+	struct sysfs_open_file *of = sysfs_of(file);
+	int ret;
+
+	if (!of->vm_ops)
+		return VM_FAULT_SIGBUS;
+
+	if (!sysfs_get_active(of->sd))
+		return VM_FAULT_SIGBUS;
+
+	ret = 0;
+	if (of->vm_ops->page_mkwrite)
+		ret = of->vm_ops->page_mkwrite(vma, vmf);
+	else
+		file_update_time(file);
+
+	sysfs_put_active(of->sd);
+	return ret;
+}
+
+static int sysfs_bin_access(struct vm_area_struct *vma, unsigned long addr,
+			    void *buf, int len, int write)
+{
+	struct file *file = vma->vm_file;
+	struct sysfs_open_file *of = sysfs_of(file);
+	int ret;
+
+	if (!of->vm_ops)
+		return -EINVAL;
+
+	if (!sysfs_get_active(of->sd))
+		return -EINVAL;
+
+	ret = -EINVAL;
+	if (of->vm_ops->access)
+		ret = of->vm_ops->access(vma, addr, buf, len, write);
+
+	sysfs_put_active(of->sd);
+	return ret;
+}
+
+#ifdef CONFIG_NUMA
+static int sysfs_bin_set_policy(struct vm_area_struct *vma,
+				struct mempolicy *new)
+{
+	struct file *file = vma->vm_file;
+	struct sysfs_open_file *of = sysfs_of(file);
+	int ret;
+
+	if (!of->vm_ops)
+		return 0;
+
+	if (!sysfs_get_active(of->sd))
+		return -EINVAL;
+
+	ret = 0;
+	if (of->vm_ops->set_policy)
+		ret = of->vm_ops->set_policy(vma, new);
+
+	sysfs_put_active(of->sd);
+	return ret;
+}
+
+static struct mempolicy *sysfs_bin_get_policy(struct vm_area_struct *vma,
+					      unsigned long addr)
+{
+	struct file *file = vma->vm_file;
+	struct sysfs_open_file *of = sysfs_of(file);
+	struct mempolicy *pol;
+
+	if (!of->vm_ops)
+		return vma->vm_policy;
+
+	if (!sysfs_get_active(of->sd))
+		return vma->vm_policy;
+
+	pol = vma->vm_policy;
+	if (of->vm_ops->get_policy)
+		pol = of->vm_ops->get_policy(vma, addr);
+
+	sysfs_put_active(of->sd);
+	return pol;
+}
+
+static int sysfs_bin_migrate(struct vm_area_struct *vma, const nodemask_t *from,
+			     const nodemask_t *to, unsigned long flags)
+{
+	struct file *file = vma->vm_file;
+	struct sysfs_open_file *of = sysfs_of(file);
+	int ret;
+
+	if (!of->vm_ops)
+		return 0;
+
+	if (!sysfs_get_active(of->sd))
+		return 0;
+
+	ret = 0;
+	if (of->vm_ops->migrate)
+		ret = of->vm_ops->migrate(vma, from, to, flags);
+
+	sysfs_put_active(of->sd);
+	return ret;
+}
+#endif
+
+static const struct vm_operations_struct sysfs_bin_vm_ops = {
+	.open		= sysfs_bin_vma_open,
+	.fault		= sysfs_bin_fault,
+	.page_mkwrite	= sysfs_bin_page_mkwrite,
+	.access		= sysfs_bin_access,
+#ifdef CONFIG_NUMA
+	.set_policy	= sysfs_bin_set_policy,
+	.get_policy	= sysfs_bin_get_policy,
+	.migrate	= sysfs_bin_migrate,
+#endif
+};
+
+static int sysfs_bin_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct sysfs_open_file *of = sysfs_of(file);
+	struct bin_attribute *battr = of->sd->s_attr.bin_attr;
+	struct kobject *kobj = of->sd->s_parent->s_dir.kobj;
+	int rc;
+
+	mutex_lock(&of->mutex);
+
+	/* need of->sd for battr, its parent for kobj */
+	rc = -ENODEV;
+	if (!sysfs_get_active(of->sd))
+		goto out_unlock;
+
+	if (!battr->mmap)
+		goto out_put;
+
+	rc = battr->mmap(file, kobj, battr, vma);
+	if (rc)
+		goto out_put;
+
+	/*
+	 * PowerPC's pci_mmap of legacy_mem uses shmem_zero_setup()
+	 * to satisfy versions of X which crash if the mmap fails: that
+	 * substitutes a new vm_file, and we don't then want bin_vm_ops.
+	 */
+	if (vma->vm_file != file)
+		goto out_put;
+
+	rc = -EINVAL;
+	if (of->mmapped && of->vm_ops != vma->vm_ops)
+		goto out_put;
+
+	/*
+	 * It is not possible to successfully wrap close.
+	 * So error if someone is trying to use close.
+	 */
+	rc = -EINVAL;
+	if (vma->vm_ops && vma->vm_ops->close)
+		goto out_put;
+
+	rc = 0;
+	of->mmapped = 1;
+	of->vm_ops = vma->vm_ops;
+	vma->vm_ops = &sysfs_bin_vm_ops;
+out_put:
+	sysfs_put_active(of->sd);
+out_unlock:
+	mutex_unlock(&of->mutex);
+
+	return rc;
+}
+
 /**
  *	sysfs_get_open_dirent - get or create sysfs_open_dirent
  *	@sd: target sysfs_dirent
- *	@buffer: sysfs_buffer for this instance of open
+ *	@of: sysfs_open_file for this instance of open
  *
  *	If @sd->s_attr.open exists, increment its reference count;
- *	otherwise, create one.  @buffer is chained to the buffers
- *	list.
+ *	otherwise, create one.  @of is chained to the files list.
  *
  *	LOCKING:
  *	Kernel thread context (may sleep).
@@ -253,11 +531,12 @@
  *	0 on success, -errno on failure.
  */
 static int sysfs_get_open_dirent(struct sysfs_dirent *sd,
-				 struct sysfs_buffer *buffer)
+				 struct sysfs_open_file *of)
 {
 	struct sysfs_open_dirent *od, *new_od = NULL;
 
  retry:
+	mutex_lock(&sysfs_open_file_mutex);
 	spin_lock_irq(&sysfs_open_dirent_lock);
 
 	if (!sd->s_attr.open && new_od) {
@@ -268,10 +547,11 @@
 	od = sd->s_attr.open;
 	if (od) {
 		atomic_inc(&od->refcnt);
-		list_add_tail(&buffer->list, &od->buffers);
+		list_add_tail(&of->list, &od->files);
 	}
 
 	spin_unlock_irq(&sysfs_open_dirent_lock);
+	mutex_unlock(&sysfs_open_file_mutex);
 
 	if (od) {
 		kfree(new_od);
@@ -286,36 +566,40 @@
 	atomic_set(&new_od->refcnt, 0);
 	atomic_set(&new_od->event, 1);
 	init_waitqueue_head(&new_od->poll);
-	INIT_LIST_HEAD(&new_od->buffers);
+	INIT_LIST_HEAD(&new_od->files);
 	goto retry;
 }
 
 /**
  *	sysfs_put_open_dirent - put sysfs_open_dirent
  *	@sd: target sysfs_dirent
- *	@buffer: associated sysfs_buffer
+ *	@of: associated sysfs_open_file
  *
- *	Put @sd->s_attr.open and unlink @buffer from the buffers list.
- *	If reference count reaches zero, disassociate and free it.
+ *	Put @sd->s_attr.open and unlink @of from the files list.  If
+ *	reference count reaches zero, disassociate and free it.
  *
  *	LOCKING:
  *	None.
  */
 static void sysfs_put_open_dirent(struct sysfs_dirent *sd,
-				  struct sysfs_buffer *buffer)
+				  struct sysfs_open_file *of)
 {
 	struct sysfs_open_dirent *od = sd->s_attr.open;
 	unsigned long flags;
 
+	mutex_lock(&sysfs_open_file_mutex);
 	spin_lock_irqsave(&sysfs_open_dirent_lock, flags);
 
-	list_del(&buffer->list);
+	if (of)
+		list_del(&of->list);
+
 	if (atomic_dec_and_test(&od->refcnt))
 		sd->s_attr.open = NULL;
 	else
 		od = NULL;
 
 	spin_unlock_irqrestore(&sysfs_open_dirent_lock, flags);
+	mutex_unlock(&sysfs_open_file_mutex);
 
 	kfree(od);
 }
@@ -324,67 +608,81 @@
 {
 	struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
 	struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
-	struct sysfs_buffer *buffer;
-	const struct sysfs_ops *ops;
+	struct sysfs_open_file *of;
+	bool has_read, has_write;
 	int error = -EACCES;
 
 	/* need attr_sd for attr and ops, its parent for kobj */
 	if (!sysfs_get_active(attr_sd))
 		return -ENODEV;
 
-	/* every kobject with an attribute needs a ktype assigned */
-	if (kobj->ktype && kobj->ktype->sysfs_ops)
-		ops = kobj->ktype->sysfs_ops;
-	else {
-		WARN(1, KERN_ERR
-		     "missing sysfs attribute operations for kobject: %s\n",
-		     kobject_name(kobj));
+	if (sysfs_is_bin(attr_sd)) {
+		struct bin_attribute *battr = attr_sd->s_attr.bin_attr;
+
+		has_read = battr->read || battr->mmap;
+		has_write = battr->write || battr->mmap;
+	} else {
+		const struct sysfs_ops *ops = sysfs_file_ops(attr_sd);
+
+		/* every kobject with an attribute needs a ktype assigned */
+		if (WARN(!ops, KERN_ERR
+			 "missing sysfs attribute operations for kobject: %s\n",
+			 kobject_name(kobj)))
+			goto err_out;
+
+		has_read = ops->show;
+		has_write = ops->store;
+	}
+
+	/* check perms and supported operations */
+	if ((file->f_mode & FMODE_WRITE) &&
+	    (!(inode->i_mode & S_IWUGO) || !has_write))
 		goto err_out;
-	}
 
-	/* File needs write support.
-	 * The inode's perms must say it's ok,
-	 * and we must have a store method.
-	 */
-	if (file->f_mode & FMODE_WRITE) {
-		if (!(inode->i_mode & S_IWUGO) || !ops->store)
-			goto err_out;
-	}
+	if ((file->f_mode & FMODE_READ) &&
+	    (!(inode->i_mode & S_IRUGO) || !has_read))
+		goto err_out;
 
-	/* File needs read support.
-	 * The inode's perms must say it's ok, and we there
-	 * must be a show method for it.
-	 */
-	if (file->f_mode & FMODE_READ) {
-		if (!(inode->i_mode & S_IRUGO) || !ops->show)
-			goto err_out;
-	}
-
-	/* No error? Great, allocate a buffer for the file, and store it
-	 * it in file->private_data for easy access.
-	 */
+	/* allocate a sysfs_open_file for the file */
 	error = -ENOMEM;
-	buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL);
-	if (!buffer)
+	of = kzalloc(sizeof(struct sysfs_open_file), GFP_KERNEL);
+	if (!of)
 		goto err_out;
 
-	mutex_init(&buffer->mutex);
-	buffer->needs_read_fill = 1;
-	buffer->ops = ops;
-	file->private_data = buffer;
+	mutex_init(&of->mutex);
+	of->sd = attr_sd;
+	of->file = file;
 
-	/* make sure we have open dirent struct */
-	error = sysfs_get_open_dirent(attr_sd, buffer);
+	/*
+	 * Always instantiate seq_file even if read access doesn't use
+	 * seq_file or is not requested.  This unifies private data access
+	 * and readable regular files are the vast majority anyway.
+	 */
+	if (sysfs_is_bin(attr_sd))
+		error = single_open(file, NULL, of);
+	else
+		error = single_open(file, sysfs_seq_show, of);
 	if (error)
 		goto err_free;
 
+	/* seq_file clears PWRITE unconditionally, restore it if WRITE */
+	if (file->f_mode & FMODE_WRITE)
+		file->f_mode |= FMODE_PWRITE;
+
+	/* make sure we have open dirent struct */
+	error = sysfs_get_open_dirent(attr_sd, of);
+	if (error)
+		goto err_close;
+
 	/* open succeeded, put active references */
 	sysfs_put_active(attr_sd);
 	return 0;
 
- err_free:
-	kfree(buffer);
- err_out:
+err_close:
+	single_release(inode, file);
+err_free:
+	kfree(of);
+err_out:
 	sysfs_put_active(attr_sd);
 	return error;
 }
@@ -392,17 +690,41 @@
 static int sysfs_release(struct inode *inode, struct file *filp)
 {
 	struct sysfs_dirent *sd = filp->f_path.dentry->d_fsdata;
-	struct sysfs_buffer *buffer = filp->private_data;
+	struct sysfs_open_file *of = sysfs_of(filp);
 
-	sysfs_put_open_dirent(sd, buffer);
-
-	if (buffer->page)
-		free_page((unsigned long)buffer->page);
-	kfree(buffer);
+	sysfs_put_open_dirent(sd, of);
+	single_release(inode, filp);
+	kfree(of);
 
 	return 0;
 }
 
+void sysfs_unmap_bin_file(struct sysfs_dirent *sd)
+{
+	struct sysfs_open_dirent *od;
+	struct sysfs_open_file *of;
+
+	if (!sysfs_is_bin(sd))
+		return;
+
+	spin_lock_irq(&sysfs_open_dirent_lock);
+	od = sd->s_attr.open;
+	if (od)
+		atomic_inc(&od->refcnt);
+	spin_unlock_irq(&sysfs_open_dirent_lock);
+	if (!od)
+		return;
+
+	mutex_lock(&sysfs_open_file_mutex);
+	list_for_each_entry(of, &od->files, list) {
+		struct inode *inode = file_inode(of->file);
+		unmap_mapping_range(inode->i_mapping, 0, 0, 1);
+	}
+	mutex_unlock(&sysfs_open_file_mutex);
+
+	sysfs_put_open_dirent(sd, NULL);
+}
+
 /* Sysfs attribute files are pollable.  The idea is that you read
  * the content and then you use 'poll' or 'select' to wait for
  * the content to change.  When the content changes (assuming the
@@ -418,7 +740,7 @@
  */
 static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
 {
-	struct sysfs_buffer *buffer = filp->private_data;
+	struct sysfs_open_file *of = sysfs_of(filp);
 	struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
 	struct sysfs_open_dirent *od = attr_sd->s_attr.open;
 
@@ -430,13 +752,12 @@
 
 	sysfs_put_active(attr_sd);
 
-	if (buffer->event != atomic_read(&od->event))
+	if (of->event != atomic_read(&od->event))
 		goto trigger;
 
 	return DEFAULT_POLLMASK;
 
  trigger:
-	buffer->needs_read_fill = 1;
 	return DEFAULT_POLLMASK|POLLERR|POLLPRI;
 }
 
@@ -466,9 +787,9 @@
 	mutex_lock(&sysfs_mutex);
 
 	if (sd && dir)
-		sd = sysfs_find_dirent(sd, NULL, dir);
+		sd = sysfs_find_dirent(sd, dir, NULL);
 	if (sd && attr)
-		sd = sysfs_find_dirent(sd, NULL, attr);
+		sd = sysfs_find_dirent(sd, attr, NULL);
 	if (sd)
 		sysfs_notify_dirent(sd);
 
@@ -477,7 +798,7 @@
 EXPORT_SYMBOL_GPL(sysfs_notify);
 
 const struct file_operations sysfs_file_operations = {
-	.read		= sysfs_read_file,
+	.read		= seq_read,
 	.write		= sysfs_write_file,
 	.llseek		= generic_file_llseek,
 	.open		= sysfs_open_file,
@@ -485,58 +806,25 @@
 	.poll		= sysfs_poll,
 };
 
-static int sysfs_attr_ns(struct kobject *kobj, const struct attribute *attr,
-			 const void **pns)
-{
-	struct sysfs_dirent *dir_sd = kobj->sd;
-	const struct sysfs_ops *ops;
-	const void *ns = NULL;
-	int err;
+const struct file_operations sysfs_bin_operations = {
+	.read		= sysfs_bin_read,
+	.write		= sysfs_write_file,
+	.llseek		= generic_file_llseek,
+	.mmap		= sysfs_bin_mmap,
+	.open		= sysfs_open_file,
+	.release	= sysfs_release,
+	.poll		= sysfs_poll,
+};
 
-	if (!dir_sd) {
-		WARN(1, KERN_ERR "sysfs: kobject %s without dirent\n",
-			kobject_name(kobj));
-		return -ENOENT;
-	}
-
-	err = 0;
-	if (!sysfs_ns_type(dir_sd))
-		goto out;
-
-	err = -EINVAL;
-	if (!kobj->ktype)
-		goto out;
-	ops = kobj->ktype->sysfs_ops;
-	if (!ops)
-		goto out;
-	if (!ops->namespace)
-		goto out;
-
-	err = 0;
-	ns = ops->namespace(kobj, attr);
-out:
-	if (err) {
-		WARN(1, KERN_ERR
-		     "missing sysfs namespace attribute operation for kobject: %s\n",
-		     kobject_name(kobj));
-	}
-	*pns = ns;
-	return err;
-}
-
-int sysfs_add_file_mode(struct sysfs_dirent *dir_sd,
-			const struct attribute *attr, int type, umode_t amode)
+int sysfs_add_file_mode_ns(struct sysfs_dirent *dir_sd,
+			   const struct attribute *attr, int type,
+			   umode_t amode, const void *ns)
 {
 	umode_t mode = (amode & S_IALLUGO) | S_IFREG;
 	struct sysfs_addrm_cxt acxt;
 	struct sysfs_dirent *sd;
-	const void *ns;
 	int rc;
 
-	rc = sysfs_attr_ns(dir_sd->s_dir.kobj, attr, &ns);
-	if (rc)
-		return rc;
-
 	sd = sysfs_new_dirent(attr->name, mode, type);
 	if (!sd)
 		return -ENOMEM;
@@ -545,8 +833,8 @@
 	sd->s_attr.attr = (void *)attr;
 	sysfs_dirent_init_lockdep(sd);
 
-	sysfs_addrm_start(&acxt, dir_sd);
-	rc = sysfs_add_one(&acxt, sd);
+	sysfs_addrm_start(&acxt);
+	rc = sysfs_add_one(&acxt, sd, dir_sd);
 	sysfs_addrm_finish(&acxt);
 
 	if (rc)
@@ -559,23 +847,25 @@
 int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
 		   int type)
 {
-	return sysfs_add_file_mode(dir_sd, attr, type, attr->mode);
+	return sysfs_add_file_mode_ns(dir_sd, attr, type, attr->mode, NULL);
 }
 
-
 /**
- *	sysfs_create_file - create an attribute file for an object.
- *	@kobj:	object we're creating for.
- *	@attr:	attribute descriptor.
+ * sysfs_create_file_ns - create an attribute file for an object with custom ns
+ * @kobj: object we're creating for
+ * @attr: attribute descriptor
+ * @ns: namespace the new file should belong to
  */
-int sysfs_create_file(struct kobject *kobj, const struct attribute *attr)
+int sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr,
+			 const void *ns)
 {
 	BUG_ON(!kobj || !kobj->sd || !attr);
 
-	return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR);
+	return sysfs_add_file_mode_ns(kobj->sd, attr, SYSFS_KOBJ_ATTR,
+				      attr->mode, ns);
 
 }
-EXPORT_SYMBOL_GPL(sysfs_create_file);
+EXPORT_SYMBOL_GPL(sysfs_create_file_ns);
 
 int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr)
 {
@@ -604,7 +894,7 @@
 	int error;
 
 	if (group)
-		dir_sd = sysfs_get_dirent(kobj->sd, NULL, group);
+		dir_sd = sysfs_get_dirent(kobj->sd, group);
 	else
 		dir_sd = sysfs_get(kobj->sd);
 
@@ -630,17 +920,12 @@
 {
 	struct sysfs_dirent *sd;
 	struct iattr newattrs;
-	const void *ns;
 	int rc;
 
-	rc = sysfs_attr_ns(kobj, attr, &ns);
-	if (rc)
-		return rc;
-
 	mutex_lock(&sysfs_mutex);
 
 	rc = -ENOENT;
-	sd = sysfs_find_dirent(kobj->sd, ns, attr->name);
+	sd = sysfs_find_dirent(kobj->sd, attr->name, NULL);
 	if (!sd)
 		goto out;
 
@@ -655,22 +940,21 @@
 EXPORT_SYMBOL_GPL(sysfs_chmod_file);
 
 /**
- *	sysfs_remove_file - remove an object attribute.
- *	@kobj:	object we're acting for.
- *	@attr:	attribute descriptor.
+ * sysfs_remove_file_ns - remove an object attribute with a custom ns tag
+ * @kobj: object we're acting for
+ * @attr: attribute descriptor
+ * @ns: namespace tag of the file to remove
  *
- *	Hash the attribute name and kill the victim.
+ * Hash the attribute name and namespace tag and kill the victim.
  */
-void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr)
+void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr,
+			  const void *ns)
 {
-	const void *ns;
+	struct sysfs_dirent *dir_sd = kobj->sd;
 
-	if (sysfs_attr_ns(kobj, attr, &ns))
-		return;
-
-	sysfs_hash_and_remove(kobj->sd, ns, attr->name);
+	sysfs_hash_and_remove(dir_sd, attr->name, ns);
 }
-EXPORT_SYMBOL_GPL(sysfs_remove_file);
+EXPORT_SYMBOL_GPL(sysfs_remove_file_ns);
 
 void sysfs_remove_files(struct kobject *kobj, const struct attribute **ptr)
 {
@@ -692,16 +976,42 @@
 	struct sysfs_dirent *dir_sd;
 
 	if (group)
-		dir_sd = sysfs_get_dirent(kobj->sd, NULL, group);
+		dir_sd = sysfs_get_dirent(kobj->sd, group);
 	else
 		dir_sd = sysfs_get(kobj->sd);
 	if (dir_sd) {
-		sysfs_hash_and_remove(dir_sd, NULL, attr->name);
+		sysfs_hash_and_remove(dir_sd, attr->name, NULL);
 		sysfs_put(dir_sd);
 	}
 }
 EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
 
+/**
+ *	sysfs_create_bin_file - create binary file for object.
+ *	@kobj:	object.
+ *	@attr:	attribute descriptor.
+ */
+int sysfs_create_bin_file(struct kobject *kobj,
+			  const struct bin_attribute *attr)
+{
+	BUG_ON(!kobj || !kobj->sd || !attr);
+
+	return sysfs_add_file(kobj->sd, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
+}
+EXPORT_SYMBOL_GPL(sysfs_create_bin_file);
+
+/**
+ *	sysfs_remove_bin_file - remove binary file for object.
+ *	@kobj:	object.
+ *	@attr:	attribute descriptor.
+ */
+void sysfs_remove_bin_file(struct kobject *kobj,
+			   const struct bin_attribute *attr)
+{
+	sysfs_hash_and_remove(kobj->sd, attr->attr.name, NULL);
+}
+EXPORT_SYMBOL_GPL(sysfs_remove_bin_file);
+
 struct sysfs_schedule_callback_struct {
 	struct list_head	workq_list;
 	struct kobject		*kobj;
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 5f92cd2..1898a10 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -26,7 +26,7 @@
 
 	if (grp->attrs)
 		for (attr = grp->attrs; *attr; attr++)
-			sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name);
+			sysfs_hash_and_remove(dir_sd, (*attr)->name, NULL);
 	if (grp->bin_attrs)
 		for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++)
 			sysfs_remove_bin_file(kobj, *bin_attr);
@@ -49,16 +49,17 @@
 			 * re-adding (if required) the file.
 			 */
 			if (update)
-				sysfs_hash_and_remove(dir_sd, NULL,
-						      (*attr)->name);
+				sysfs_hash_and_remove(dir_sd, (*attr)->name,
+						      NULL);
 			if (grp->is_visible) {
 				mode = grp->is_visible(kobj, *attr, i);
 				if (!mode)
 					continue;
 			}
-			error = sysfs_add_file_mode(dir_sd, *attr,
-						    SYSFS_KOBJ_ATTR,
-						    (*attr)->mode | mode);
+			error = sysfs_add_file_mode_ns(dir_sd, *attr,
+						       SYSFS_KOBJ_ATTR,
+						       (*attr)->mode | mode,
+						       NULL);
 			if (unlikely(error))
 				break;
 		}
@@ -110,7 +111,7 @@
 	error = create_files(sd, kobj, grp, update);
 	if (error) {
 		if (grp->name)
-			sysfs_remove_subdir(sd);
+			sysfs_remove(sd);
 	}
 	sysfs_put(sd);
 	return error;
@@ -206,7 +207,7 @@
 	struct sysfs_dirent *sd;
 
 	if (grp->name) {
-		sd = sysfs_get_dirent(dir_sd, NULL, grp->name);
+		sd = sysfs_get_dirent(dir_sd, grp->name);
 		if (!sd) {
 			WARN(!sd, KERN_WARNING
 			     "sysfs group %p not found for kobject '%s'\n",
@@ -218,7 +219,7 @@
 
 	remove_files(sd, kobj, grp);
 	if (grp->name)
-		sysfs_remove_subdir(sd);
+		sysfs_remove(sd);
 
 	sysfs_put(sd);
 }
@@ -261,7 +262,7 @@
 	struct attribute *const *attr;
 	int i;
 
-	dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name);
+	dir_sd = sysfs_get_dirent(kobj->sd, grp->name);
 	if (!dir_sd)
 		return -ENOENT;
 
@@ -269,7 +270,7 @@
 		error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR);
 	if (error) {
 		while (--i >= 0)
-			sysfs_hash_and_remove(dir_sd, NULL, (*--attr)->name);
+			sysfs_hash_and_remove(dir_sd, (*--attr)->name, NULL);
 	}
 	sysfs_put(dir_sd);
 
@@ -288,10 +289,10 @@
 	struct sysfs_dirent *dir_sd;
 	struct attribute *const *attr;
 
-	dir_sd = sysfs_get_dirent(kobj->sd, NULL, grp->name);
+	dir_sd = sysfs_get_dirent(kobj->sd, grp->name);
 	if (dir_sd) {
 		for (attr = grp->attrs; *attr; ++attr)
-			sysfs_hash_and_remove(dir_sd, NULL, (*attr)->name);
+			sysfs_hash_and_remove(dir_sd, (*attr)->name, NULL);
 		sysfs_put(dir_sd);
 	}
 }
@@ -310,7 +311,7 @@
 	struct sysfs_dirent *dir_sd;
 	int error = 0;
 
-	dir_sd = sysfs_get_dirent(kobj->sd, NULL, group_name);
+	dir_sd = sysfs_get_dirent(kobj->sd, group_name);
 	if (!dir_sd)
 		return -ENOENT;
 
@@ -332,9 +333,9 @@
 {
 	struct sysfs_dirent *dir_sd;
 
-	dir_sd = sysfs_get_dirent(kobj->sd, NULL, group_name);
+	dir_sd = sysfs_get_dirent(kobj->sd, group_name);
 	if (dir_sd) {
-		sysfs_hash_and_remove(dir_sd, NULL, link_name);
+		sysfs_hash_and_remove(dir_sd, link_name, NULL);
 		sysfs_put(dir_sd);
 	}
 }
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 963f910..1750f79 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -258,9 +258,9 @@
 		inode->i_fop = &sysfs_file_operations;
 		break;
 	case SYSFS_KOBJ_BIN_ATTR:
-		bin_attr = sd->s_bin_attr.bin_attr;
+		bin_attr = sd->s_attr.bin_attr;
 		inode->i_size = bin_attr->size;
-		inode->i_fop = &bin_fops;
+		inode->i_fop = &sysfs_bin_operations;
 		break;
 	case SYSFS_KOBJ_LINK:
 		inode->i_op = &sysfs_symlink_inode_operations;
@@ -314,32 +314,6 @@
 	sysfs_put(sd);
 }
 
-int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns,
-			  const char *name)
-{
-	struct sysfs_addrm_cxt acxt;
-	struct sysfs_dirent *sd;
-
-	if (!dir_sd) {
-		WARN(1, KERN_WARNING "sysfs: can not remove '%s', no directory\n",
-			name);
-		return -ENOENT;
-	}
-
-	sysfs_addrm_start(&acxt, dir_sd);
-
-	sd = sysfs_find_dirent(dir_sd, ns, name);
-	if (sd)
-		sysfs_remove_one(&acxt, sd);
-
-	sysfs_addrm_finish(&acxt);
-
-	if (sd)
-		return 0;
-	else
-		return -ENOENT;
-}
-
 int sysfs_permission(struct inode *inode, int mask)
 {
 	struct sysfs_dirent *sd;
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 2dd4507..3ae3f1b 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -33,13 +33,15 @@
 
 	BUG_ON(!name || !parent_sd);
 
-	/* target->sd can go away beneath us but is protected with
-	 * sysfs_assoc_lock.  Fetch target_sd from it.
+	/*
+	 * We don't own @target and it may be removed at any time.
+	 * Synchronize using sysfs_symlink_target_lock.  See
+	 * sysfs_remove_dir() for details.
 	 */
-	spin_lock(&sysfs_assoc_lock);
+	spin_lock(&sysfs_symlink_target_lock);
 	if (target->sd)
 		target_sd = sysfs_get(target->sd);
-	spin_unlock(&sysfs_assoc_lock);
+	spin_unlock(&sysfs_symlink_target_lock);
 
 	error = -ENOENT;
 	if (!target_sd)
@@ -52,18 +54,18 @@
 
 	ns_type = sysfs_ns_type(parent_sd);
 	if (ns_type)
-		sd->s_ns = target->ktype->namespace(target);
+		sd->s_ns = target_sd->s_ns;
 	sd->s_symlink.target_sd = target_sd;
 	target_sd = NULL;	/* reference is now owned by the symlink */
 
-	sysfs_addrm_start(&acxt, parent_sd);
+	sysfs_addrm_start(&acxt);
 	/* Symlinks must be between directories with the same ns_type */
 	if (!ns_type ||
 	    (ns_type == sysfs_ns_type(sd->s_symlink.target_sd->s_parent))) {
 		if (warn)
-			error = sysfs_add_one(&acxt, sd);
+			error = sysfs_add_one(&acxt, sd, parent_sd);
 		else
-			error = __sysfs_add_one(&acxt, sd);
+			error = __sysfs_add_one(&acxt, sd, parent_sd);
 	} else {
 		error = -EINVAL;
 		WARN(1, KERN_WARNING
@@ -155,11 +157,17 @@
 			const char *name)
 {
 	const void *ns = NULL;
-	spin_lock(&sysfs_assoc_lock);
+
+	/*
+	 * We don't own @target and it may be removed at any time.
+	 * Synchronize using sysfs_symlink_target_lock.  See
+	 * sysfs_remove_dir() for details.
+	 */
+	spin_lock(&sysfs_symlink_target_lock);
 	if (targ->sd && sysfs_ns_type(kobj->sd))
 		ns = targ->sd->s_ns;
-	spin_unlock(&sysfs_assoc_lock);
-	sysfs_hash_and_remove(kobj->sd, ns, name);
+	spin_unlock(&sysfs_symlink_target_lock);
+	sysfs_hash_and_remove(kobj->sd, name, ns);
 }
 
 /**
@@ -176,24 +184,25 @@
 	else
 		parent_sd = kobj->sd;
 
-	sysfs_hash_and_remove(parent_sd, NULL, name);
+	sysfs_hash_and_remove(parent_sd, name, NULL);
 }
 EXPORT_SYMBOL_GPL(sysfs_remove_link);
 
 /**
- *	sysfs_rename_link - rename symlink in object's directory.
+ *	sysfs_rename_link_ns - rename symlink in object's directory.
  *	@kobj:	object we're acting for.
  *	@targ:	object we're pointing to.
  *	@old:	previous name of the symlink.
  *	@new:	new name of the symlink.
+ *	@new_ns: new namespace of the symlink.
  *
  *	A helper function for the common rename symlink idiom.
  */
-int sysfs_rename_link(struct kobject *kobj, struct kobject *targ,
-			const char *old, const char *new)
+int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *targ,
+			 const char *old, const char *new, const void *new_ns)
 {
 	struct sysfs_dirent *parent_sd, *sd = NULL;
-	const void *old_ns = NULL, *new_ns = NULL;
+	const void *old_ns = NULL;
 	int result;
 
 	if (!kobj)
@@ -205,7 +214,7 @@
 		old_ns = targ->sd->s_ns;
 
 	result = -ENOENT;
-	sd = sysfs_get_dirent(parent_sd, old_ns, old);
+	sd = sysfs_get_dirent_ns(parent_sd, old, old_ns);
 	if (!sd)
 		goto out;
 
@@ -215,16 +224,13 @@
 	if (sd->s_symlink.target_sd->s_dir.kobj != targ)
 		goto out;
 
-	if (sysfs_ns_type(parent_sd))
-		new_ns = targ->ktype->namespace(targ);
-
-	result = sysfs_rename(sd, parent_sd, new_ns, new);
+	result = sysfs_rename(sd, parent_sd, new, new_ns);
 
 out:
 	sysfs_put(sd);
 	return result;
 }
-EXPORT_SYMBOL_GPL(sysfs_rename_link);
+EXPORT_SYMBOL_GPL(sysfs_rename_link_ns);
 
 static int sysfs_get_target_path(struct sysfs_dirent *parent_sd,
 				 struct sysfs_dirent *target_sd, char *path)
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index b6deca3..0af09fb 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -29,15 +29,13 @@
 };
 
 struct sysfs_elem_attr {
-	struct attribute	*attr;
+	union {
+		struct attribute	*attr;
+		struct bin_attribute	*bin_attr;
+	};
 	struct sysfs_open_dirent *open;
 };
 
-struct sysfs_elem_bin_attr {
-	struct bin_attribute	*bin_attr;
-	struct hlist_head	buffers;
-};
-
 struct sysfs_inode_attrs {
 	struct iattr	ia_iattr;
 	void		*ia_secdata;
@@ -74,7 +72,6 @@
 		struct sysfs_elem_dir		s_dir;
 		struct sysfs_elem_symlink	s_symlink;
 		struct sysfs_elem_attr		s_attr;
-		struct sysfs_elem_bin_attr	s_bin_attr;
 	};
 
 	unsigned short		s_flags;
@@ -115,6 +112,7 @@
 }
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
+
 #define sysfs_dirent_init_lockdep(sd)				\
 do {								\
 	struct attribute *attr = sd->s_attr.attr;		\
@@ -124,15 +122,31 @@
 								\
 	lockdep_init_map(&sd->dep_map, "s_active", key, 0);	\
 } while (0)
+
+/* Test for attributes that want to ignore lockdep for read-locking */
+static inline bool sysfs_ignore_lockdep(struct sysfs_dirent *sd)
+{
+	int type = sysfs_type(sd);
+
+	return (type == SYSFS_KOBJ_ATTR || type == SYSFS_KOBJ_BIN_ATTR) &&
+		sd->s_attr.attr->ignore_lockdep;
+}
+
 #else
+
 #define sysfs_dirent_init_lockdep(sd) do {} while (0)
+
+static inline bool sysfs_ignore_lockdep(struct sysfs_dirent *sd)
+{
+	return true;
+}
+
 #endif
 
 /*
  * Context structure to be used while adding/removing nodes.
  */
 struct sysfs_addrm_cxt {
-	struct sysfs_dirent	*parent_sd;
 	struct sysfs_dirent	*removed;
 };
 
@@ -156,38 +170,37 @@
  * dir.c
  */
 extern struct mutex sysfs_mutex;
-extern spinlock_t sysfs_assoc_lock;
+extern spinlock_t sysfs_symlink_target_lock;
 extern const struct dentry_operations sysfs_dentry_ops;
 
 extern const struct file_operations sysfs_dir_operations;
 extern const struct inode_operations sysfs_dir_inode_operations;
 
-struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd);
 struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd);
 void sysfs_put_active(struct sysfs_dirent *sd);
-void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
-		       struct sysfs_dirent *parent_sd);
-int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd);
-int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd);
-void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd);
+void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt);
+void sysfs_warn_dup(struct sysfs_dirent *parent, const char *name);
+int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd,
+		    struct sysfs_dirent *parent_sd);
+int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd,
+		  struct sysfs_dirent *parent_sd);
+void sysfs_remove(struct sysfs_dirent *sd);
+int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name,
+			  const void *ns);
 void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
 
 struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
-				       const void *ns,
-				       const unsigned char *name);
-struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
-				      const void *ns,
-				      const unsigned char *name);
+				       const unsigned char *name,
+				       const void *ns);
 struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type);
 
 void release_sysfs_dirent(struct sysfs_dirent *sd);
 
 int sysfs_create_subdir(struct kobject *kobj, const char *name,
 			struct sysfs_dirent **p_sd);
-void sysfs_remove_subdir(struct sysfs_dirent *sd);
 
 int sysfs_rename(struct sysfs_dirent *sd, struct sysfs_dirent *new_parent_sd,
-		 const void *ns, const char *new_name);
+		 const char *new_name, const void *new_ns);
 
 static inline struct sysfs_dirent *__sysfs_get(struct sysfs_dirent *sd)
 {
@@ -218,25 +231,21 @@
 		  struct kstat *stat);
 int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 		   size_t size, int flags);
-int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const void *ns,
-			  const char *name);
 int sysfs_inode_init(void);
 
 /*
  * file.c
  */
 extern const struct file_operations sysfs_file_operations;
+extern const struct file_operations sysfs_bin_operations;
 
 int sysfs_add_file(struct sysfs_dirent *dir_sd,
 		   const struct attribute *attr, int type);
 
-int sysfs_add_file_mode(struct sysfs_dirent *dir_sd,
-			const struct attribute *attr, int type, umode_t amode);
-/*
- * bin.c
- */
-extern const struct file_operations bin_fops;
-void unmap_bin_file(struct sysfs_dirent *attr_sd);
+int sysfs_add_file_mode_ns(struct sysfs_dirent *dir_sd,
+			   const struct attribute *attr, int type,
+			   umode_t amode, const void *ns);
+void sysfs_unmap_bin_file(struct sysfs_dirent *sd);
 
 /*
  * symlink.c
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 6e025e0..cc1febd 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -2563,9 +2563,9 @@
 	unsigned int from, to, ffs = chance(1, 2);
 	unsigned char *p = (void *)buf;
 
-	from = prandom_u32() % (len + 1);
-	/* Corruption may only span one max. write unit */
-	to = min(len, ALIGN(from, c->max_write_size));
+	from = prandom_u32() % len;
+	/* Corruption span max to end of write unit */
+	to = min(len, ALIGN(from + 1, c->max_write_size));
 
 	ubifs_warn("filled bytes %u-%u with %s", from, to - 1,
 		   ffs ? "0xFFs" : "random data");
diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
index 76ca53c..9718da8 100644
--- a/fs/ubifs/gc.c
+++ b/fs/ubifs/gc.c
@@ -668,8 +668,7 @@
 	ubifs_assert(!wbuf->used);
 
 	for (i = 0; ; i++) {
-		int space_before = c->leb_size - wbuf->offs - wbuf->used;
-		int space_after;
+		int space_before, space_after;
 
 		cond_resched();
 
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 3e4aa72..f69daa5 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1630,8 +1630,10 @@
 	}
 
 	c->write_reserve_buf = kmalloc(COMPRESSED_DATA_NODE_BUF_SZ, GFP_KERNEL);
-	if (!c->write_reserve_buf)
+	if (!c->write_reserve_buf) {
+		err = -ENOMEM;
 		goto out;
+	}
 
 	err = ubifs_lpt_init(c, 0, 1);
 	if (err)
@@ -2064,8 +2066,10 @@
 	}
 
 	sb->s_root = d_make_root(root);
-	if (!sb->s_root)
+	if (!sb->s_root) {
+		err = -ENOMEM;
 		goto out_umount;
+	}
 
 	mutex_unlock(&c->umount_mutex);
 	return 0;
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 9121938..3306b9f 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -76,6 +76,9 @@
 
 #define UDF_DEFAULT_BLOCKSIZE 2048
 
+#define VSD_FIRST_SECTOR_OFFSET		32768
+#define VSD_MAX_SECTOR_OFFSET		0x800000
+
 enum { UDF_MAX_LINKS = 0xffff };
 
 /* These are the "meat" - everything else is stuffing */
@@ -685,7 +688,7 @@
 static loff_t udf_check_vsd(struct super_block *sb)
 {
 	struct volStructDesc *vsd = NULL;
-	loff_t sector = 32768;
+	loff_t sector = VSD_FIRST_SECTOR_OFFSET;
 	int sectorsize;
 	struct buffer_head *bh = NULL;
 	int nsr02 = 0;
@@ -703,8 +706,18 @@
 	udf_debug("Starting at sector %u (%ld byte sectors)\n",
 		  (unsigned int)(sector >> sb->s_blocksize_bits),
 		  sb->s_blocksize);
-	/* Process the sequence (if applicable) */
-	for (; !nsr02 && !nsr03; sector += sectorsize) {
+	/* Process the sequence (if applicable). The hard limit on the sector
+	 * offset is arbitrary, hopefully large enough so that all valid UDF
+	 * filesystems will be recognised. There is no mention of an upper
+	 * bound to the size of the volume recognition area in the standard.
+	 *  The limit will prevent the code to read all the sectors of a
+	 * specially crafted image (like a bluray disc full of CD001 sectors),
+	 * potentially causing minutes or even hours of uninterruptible I/O
+	 * activity. This actually happened with uninitialised SSD partitions
+	 * (all 0xFF) before the check for the limit and all valid IDs were
+	 * added */
+	for (; !nsr02 && !nsr03 && sector < VSD_MAX_SECTOR_OFFSET;
+	     sector += sectorsize) {
 		/* Read a block */
 		bh = udf_tread(sb, sector >> sb->s_blocksize_bits);
 		if (!bh)
@@ -714,10 +727,7 @@
 		vsd = (struct volStructDesc *)(bh->b_data +
 					      (sector & (sb->s_blocksize - 1)));
 
-		if (vsd->stdIdent[0] == 0) {
-			brelse(bh);
-			break;
-		} else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001,
+		if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001,
 				    VSD_STD_ID_LEN)) {
 			switch (vsd->structType) {
 			case 0:
@@ -753,6 +763,17 @@
 		else if (!strncmp(vsd->stdIdent, VSD_STD_ID_NSR03,
 				    VSD_STD_ID_LEN))
 			nsr03 = sector;
+		else if (!strncmp(vsd->stdIdent, VSD_STD_ID_BOOT2,
+				    VSD_STD_ID_LEN))
+			; /* nothing */
+		else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CDW02,
+				    VSD_STD_ID_LEN))
+			; /* nothing */
+		else {
+			/* invalid id : end of volume recognition area */
+			brelse(bh);
+			break;
+		}
 		brelse(bh);
 	}
 
@@ -760,7 +781,8 @@
 		return nsr03;
 	else if (nsr02)
 		return nsr02;
-	else if (sector - (sbi->s_session << sb->s_blocksize_bits) == 32768)
+	else if (!bh && sector - (sbi->s_session << sb->s_blocksize_bits) ==
+			VSD_FIRST_SECTOR_OFFSET)
 		return -1;
 	else
 		return 0;
@@ -1270,6 +1292,9 @@
 	 * PHYSICAL partitions are already set up
 	 */
 	type1_idx = i;
+#ifdef UDFFS_DEBUG
+	map = NULL; /* supress 'maybe used uninitialized' warning */
+#endif
 	for (i = 0; i < sbi->s_partitions; i++) {
 		map = &sbi->s_partmaps[i];
 
@@ -1891,7 +1916,9 @@
 			return 0;
 		}
 		if (nsr_off == -1)
-			udf_debug("Failed to read byte 32768. Assuming open disc. Skipping validity check\n");
+			udf_debug("Failed to read sector at offset %d. "
+				  "Assuming open disc. Skipping validity "
+				  "check\n", VSD_FIRST_SECTOR_OFFSET);
 		if (!sbi->s_last_block)
 			sbi->s_last_block = udf_get_last_block(sb);
 	} else {
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 02e113b..d901982 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -311,7 +311,6 @@
 	unsigned int physical_node_count;
 	struct list_head physical_node_list;
 	struct mutex physical_node_lock;
-	struct list_head power_dependent;
 	void (*remove)(struct acpi_device *);
 };
 
@@ -456,8 +455,6 @@
 acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
 				    acpi_notify_handler handler);
 int acpi_pm_device_sleep_state(struct device *, int *, int);
-void acpi_dev_pm_add_dependent(acpi_handle handle, struct device *depdev);
-void acpi_dev_pm_remove_dependent(acpi_handle handle, struct device *depdev);
 #else
 static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
 					       acpi_notify_handler handler,
@@ -478,10 +475,6 @@
 	return (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3_COLD) ?
 		m : ACPI_STATE_D0;
 }
-static inline void acpi_dev_pm_add_dependent(acpi_handle handle,
-					     struct device *depdev) {}
-static inline void acpi_dev_pm_remove_dependent(acpi_handle handle,
-						struct device *depdev) {}
 #endif
 
 #ifdef CONFIG_PM_RUNTIME
diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h
index 0bd750e..556c83ee 100644
--- a/include/acpi/actbl1.h
+++ b/include/acpi/actbl1.h
@@ -596,7 +596,7 @@
 
 /* Generic Error Status block */
 
-struct acpi_hest_generic_status {
+struct acpi_generic_status {
 	u32 block_status;
 	u32 raw_data_offset;
 	u32 raw_data_length;
@@ -606,15 +606,15 @@
 
 /* Values for block_status flags above */
 
-#define ACPI_HEST_UNCORRECTABLE             (1)
-#define ACPI_HEST_CORRECTABLE               (1<<1)
-#define ACPI_HEST_MULTIPLE_UNCORRECTABLE    (1<<2)
-#define ACPI_HEST_MULTIPLE_CORRECTABLE      (1<<3)
-#define ACPI_HEST_ERROR_ENTRY_COUNT         (0xFF<<4)	/* 8 bits, error count */
+#define ACPI_GEN_ERR_UC			BIT(0)
+#define ACPI_GEN_ERR_CE			BIT(1)
+#define ACPI_GEN_ERR_MULTI_UC		BIT(2)
+#define ACPI_GEN_ERR_MULTI_CE		BIT(3)
+#define ACPI_GEN_ERR_COUNT_SHIFT	(0xFF<<4) /* 8 bits, error count */
 
 /* Generic Error Data entry */
 
-struct acpi_hest_generic_data {
+struct acpi_generic_data {
 	u8 section_type[16];
 	u32 error_severity;
 	u16 revision;
diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h
index 720446c..dfd60d0 100644
--- a/include/acpi/ghes.h
+++ b/include/acpi/ghes.h
@@ -14,7 +14,7 @@
 
 struct ghes {
 	struct acpi_hest_generic *generic;
-	struct acpi_hest_generic_status *estatus;
+	struct acpi_generic_status *estatus;
 	u64 buffer_paddr;
 	unsigned long flags;
 	union {
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index bde6469..a5f56a0 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -10,6 +10,8 @@
 #ifdef CONFIG_GPIOLIB
 
 #include <linux/compiler.h>
+#include <linux/gpio/driver.h>
+#include <linux/gpio/consumer.h>
 
 /* Platforms may implement their GPIO interface with library code,
  * at a small performance cost for non-inlined operations and some
@@ -49,122 +51,11 @@
 struct device_node;
 struct gpio_desc;
 
-/**
- * struct gpio_chip - abstract a GPIO controller
- * @label: for diagnostics
- * @dev: optional device providing the GPIOs
- * @owner: helps prevent removal of modules exporting active GPIOs
- * @list: links gpio_chips together for traversal
- * @request: optional hook for chip-specific activation, such as
- *	enabling module power and clock; may sleep
- * @free: optional hook for chip-specific deactivation, such as
- *	disabling module power and clock; may sleep
- * @get_direction: returns direction for signal "offset", 0=out, 1=in,
- *	(same as GPIOF_DIR_XXX), or negative error
- * @direction_input: configures signal "offset" as input, or returns error
- * @get: returns value for signal "offset"; for output signals this
- *	returns either the value actually sensed, or zero
- * @direction_output: configures signal "offset" as output, or returns error
- * @set_debounce: optional hook for setting debounce time for specified gpio in
- *      interrupt triggered gpio chips
- * @set: assigns output value for signal "offset"
- * @to_irq: optional hook supporting non-static gpio_to_irq() mappings;
- *	implementation may not sleep
- * @dbg_show: optional routine to show contents in debugfs; default code
- *	will be used when this is omitted, but custom code can show extra
- *	state (such as pullup/pulldown configuration).
- * @base: identifies the first GPIO number handled by this chip; or, if
- *	negative during registration, requests dynamic ID allocation.
- * @ngpio: the number of GPIOs handled by this controller; the last GPIO
- *	handled is (base + ngpio - 1).
- * @desc: array of ngpio descriptors. Private.
- * @can_sleep: flag must be set iff get()/set() methods sleep, as they
- *	must while accessing GPIO expander chips over I2C or SPI
- * @names: if set, must be an array of strings to use as alternative
- *      names for the GPIOs in this chip. Any entry in the array
- *      may be NULL if there is no alias for the GPIO, however the
- *      array must be @ngpio entries long.  A name can include a single printk
- *      format specifier for an unsigned int.  It is substituted by the actual
- *      number of the gpio.
- *
- * A gpio_chip can help platforms abstract various sources of GPIOs so
- * they can all be accessed through a common programing interface.
- * Example sources would be SOC controllers, FPGAs, multifunction
- * chips, dedicated GPIO expanders, and so on.
- *
- * Each chip controls a number of signals, identified in method calls
- * by "offset" values in the range 0..(@ngpio - 1).  When those signals
- * are referenced through calls like gpio_get_value(gpio), the offset
- * is calculated by subtracting @base from the gpio number.
- */
-struct gpio_chip {
-	const char		*label;
-	struct device		*dev;
-	struct module		*owner;
-	struct list_head        list;
-
-	int			(*request)(struct gpio_chip *chip,
-						unsigned offset);
-	void			(*free)(struct gpio_chip *chip,
-						unsigned offset);
-	int			(*get_direction)(struct gpio_chip *chip,
-						unsigned offset);
-	int			(*direction_input)(struct gpio_chip *chip,
-						unsigned offset);
-	int			(*get)(struct gpio_chip *chip,
-						unsigned offset);
-	int			(*direction_output)(struct gpio_chip *chip,
-						unsigned offset, int value);
-	int			(*set_debounce)(struct gpio_chip *chip,
-						unsigned offset, unsigned debounce);
-
-	void			(*set)(struct gpio_chip *chip,
-						unsigned offset, int value);
-
-	int			(*to_irq)(struct gpio_chip *chip,
-						unsigned offset);
-
-	void			(*dbg_show)(struct seq_file *s,
-						struct gpio_chip *chip);
-	int			base;
-	u16			ngpio;
-	struct gpio_desc	*desc;
-	const char		*const *names;
-	unsigned		can_sleep:1;
-	unsigned		exported:1;
-
-#if defined(CONFIG_OF_GPIO)
-	/*
-	 * If CONFIG_OF is enabled, then all GPIO controllers described in the
-	 * device tree automatically may have an OF translation
-	 */
-	struct device_node *of_node;
-	int of_gpio_n_cells;
-	int (*of_xlate)(struct gpio_chip *gc,
-		        const struct of_phandle_args *gpiospec, u32 *flags);
-#endif
-#ifdef CONFIG_PINCTRL
-	/*
-	 * If CONFIG_PINCTRL is enabled, then gpio controllers can optionally
-	 * describe the actual pin range which they serve in an SoC. This
-	 * information would be used by pinctrl subsystem to configure
-	 * corresponding pins for gpio usage.
-	 */
-	struct list_head pin_ranges;
-#endif
-};
-
-extern const char *gpiochip_is_requested(struct gpio_chip *chip,
-			unsigned offset);
-extern struct gpio_chip *gpio_to_chip(unsigned gpio);
-
-/* add/remove chips */
-extern int gpiochip_add(struct gpio_chip *chip);
-extern int __must_check gpiochip_remove(struct gpio_chip *chip);
-extern struct gpio_chip *gpiochip_find(void *data,
-					int (*match)(struct gpio_chip *chip,
-						     void *data));
-
+/* caller holds gpio_lock *OR* gpio is marked as requested */
+static inline struct gpio_chip *gpio_to_chip(unsigned gpio)
+{
+	return gpiod_to_chip(gpio_to_desc(gpio));
+}
 
 /* Always use the library code for GPIO management calls,
  * or when sleeping may be involved.
@@ -172,43 +63,84 @@
 extern int gpio_request(unsigned gpio, const char *label);
 extern void gpio_free(unsigned gpio);
 
-extern int gpio_direction_input(unsigned gpio);
-extern int gpio_direction_output(unsigned gpio, int value);
+static inline int gpio_direction_input(unsigned gpio)
+{
+	return gpiod_direction_input(gpio_to_desc(gpio));
+}
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+	return gpiod_direction_output(gpio_to_desc(gpio), value);
+}
 
-extern int gpio_set_debounce(unsigned gpio, unsigned debounce);
+static inline int gpio_set_debounce(unsigned gpio, unsigned debounce)
+{
+	return gpiod_set_debounce(gpio_to_desc(gpio), debounce);
+}
 
-extern int gpio_get_value_cansleep(unsigned gpio);
-extern void gpio_set_value_cansleep(unsigned gpio, int value);
+static inline int gpio_get_value_cansleep(unsigned gpio)
+{
+	return gpiod_get_raw_value_cansleep(gpio_to_desc(gpio));
+}
+static inline void gpio_set_value_cansleep(unsigned gpio, int value)
+{
+	return gpiod_set_raw_value_cansleep(gpio_to_desc(gpio), value);
+}
 
 
 /* A platform's <asm/gpio.h> code may want to inline the I/O calls when
  * the GPIO is constant and refers to some always-present controller,
  * giving direct access to chip registers and tight bitbanging loops.
  */
-extern int __gpio_get_value(unsigned gpio);
-extern void __gpio_set_value(unsigned gpio, int value);
+static inline int __gpio_get_value(unsigned gpio)
+{
+	return gpiod_get_raw_value(gpio_to_desc(gpio));
+}
+static inline void __gpio_set_value(unsigned gpio, int value)
+{
+	return gpiod_set_raw_value(gpio_to_desc(gpio), value);
+}
 
-extern int __gpio_cansleep(unsigned gpio);
+static inline int __gpio_cansleep(unsigned gpio)
+{
+	return gpiod_cansleep(gpio_to_desc(gpio));
+}
 
-extern int __gpio_to_irq(unsigned gpio);
+static inline int __gpio_to_irq(unsigned gpio)
+{
+	return gpiod_to_irq(gpio_to_desc(gpio));
+}
+
+extern int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset);
+extern void gpio_unlock_as_irq(struct gpio_chip *chip, unsigned int offset);
 
 extern int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
 extern int gpio_request_array(const struct gpio *array, size_t num);
 extern void gpio_free_array(const struct gpio *array, size_t num);
 
-#ifdef CONFIG_GPIO_SYSFS
-
 /*
  * A sysfs interface can be exported by individual drivers if they want,
  * but more typically is configured entirely from userspace.
  */
-extern int gpio_export(unsigned gpio, bool direction_may_change);
-extern int gpio_export_link(struct device *dev, const char *name,
-			unsigned gpio);
-extern int gpio_sysfs_set_active_low(unsigned gpio, int value);
-extern void gpio_unexport(unsigned gpio);
+static inline int gpio_export(unsigned gpio, bool direction_may_change)
+{
+	return gpiod_export(gpio_to_desc(gpio), direction_may_change);
+}
 
-#endif	/* CONFIG_GPIO_SYSFS */
+static inline int gpio_export_link(struct device *dev, const char *name,
+				   unsigned gpio)
+{
+	return gpiod_export_link(dev, name, gpio_to_desc(gpio));
+}
+
+static inline int gpio_sysfs_set_active_low(unsigned gpio, int value)
+{
+	return gpiod_sysfs_set_active_low(gpio_to_desc(gpio), value);
+}
+
+static inline void gpio_unexport(unsigned gpio)
+{
+	gpiod_unexport(gpio_to_desc(gpio));
+}
 
 #ifdef CONFIG_PINCTRL
 
@@ -228,6 +160,9 @@
 int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
 			   unsigned int gpio_offset, unsigned int pin_offset,
 			   unsigned int npins);
+int gpiochip_add_pingroup_range(struct gpio_chip *chip,
+			struct pinctrl_dev *pctldev,
+			unsigned int gpio_offset, const char *pin_group);
 void gpiochip_remove_pin_ranges(struct gpio_chip *chip);
 
 #else
@@ -239,6 +174,13 @@
 {
 	return 0;
 }
+static inline int
+gpiochip_add_pingroup_range(struct gpio_chip *chip,
+			struct pinctrl_dev *pctldev,
+			unsigned int gpio_offset, const char *pin_group)
+{
+	return 0;
+}
 
 static inline void
 gpiochip_remove_pin_ranges(struct gpio_chip *chip)
@@ -278,31 +220,4 @@
 
 #endif /* !CONFIG_GPIOLIB */
 
-#ifndef CONFIG_GPIO_SYSFS
-
-struct device;
-
-/* sysfs support is only available with gpiolib, where it's optional */
-
-static inline int gpio_export(unsigned gpio, bool direction_may_change)
-{
-	return -ENOSYS;
-}
-
-static inline int gpio_export_link(struct device *dev, const char *name,
-				unsigned gpio)
-{
-	return -ENOSYS;
-}
-
-static inline int gpio_sysfs_set_active_low(unsigned gpio, int value)
-{
-	return -ENOSYS;
-}
-
-static inline void gpio_unexport(unsigned gpio)
-{
-}
-#endif	/* CONFIG_GPIO_SYSFS */
-
 #endif /* _ASM_GENERIC_GPIO_H */
diff --git a/include/asm-generic/preempt.h b/include/asm-generic/preempt.h
new file mode 100644
index 0000000..ddf2b42
--- /dev/null
+++ b/include/asm-generic/preempt.h
@@ -0,0 +1,105 @@
+#ifndef __ASM_PREEMPT_H
+#define __ASM_PREEMPT_H
+
+#include <linux/thread_info.h>
+
+/*
+ * We mask the PREEMPT_NEED_RESCHED bit so as not to confuse all current users
+ * that think a non-zero value indicates we cannot preempt.
+ */
+static __always_inline int preempt_count(void)
+{
+	return current_thread_info()->preempt_count & ~PREEMPT_NEED_RESCHED;
+}
+
+static __always_inline int *preempt_count_ptr(void)
+{
+	return &current_thread_info()->preempt_count;
+}
+
+/*
+ * We now loose PREEMPT_NEED_RESCHED and cause an extra reschedule; however the
+ * alternative is loosing a reschedule. Better schedule too often -- also this
+ * should be a very rare operation.
+ */
+static __always_inline void preempt_count_set(int pc)
+{
+	*preempt_count_ptr() = pc;
+}
+
+/*
+ * must be macros to avoid header recursion hell
+ */
+#define task_preempt_count(p) \
+	(task_thread_info(p)->preempt_count & ~PREEMPT_NEED_RESCHED)
+
+#define init_task_preempt_count(p) do { \
+	task_thread_info(p)->preempt_count = PREEMPT_DISABLED; \
+} while (0)
+
+#define init_idle_preempt_count(p, cpu) do { \
+	task_thread_info(p)->preempt_count = PREEMPT_ENABLED; \
+} while (0)
+
+/*
+ * We fold the NEED_RESCHED bit into the preempt count such that
+ * preempt_enable() can decrement and test for needing to reschedule with a
+ * single instruction.
+ *
+ * We invert the actual bit, so that when the decrement hits 0 we know we both
+ * need to resched (the bit is cleared) and can resched (no preempt count).
+ */
+
+static __always_inline void set_preempt_need_resched(void)
+{
+	*preempt_count_ptr() &= ~PREEMPT_NEED_RESCHED;
+}
+
+static __always_inline void clear_preempt_need_resched(void)
+{
+	*preempt_count_ptr() |= PREEMPT_NEED_RESCHED;
+}
+
+static __always_inline bool test_preempt_need_resched(void)
+{
+	return !(*preempt_count_ptr() & PREEMPT_NEED_RESCHED);
+}
+
+/*
+ * The various preempt_count add/sub methods
+ */
+
+static __always_inline void __preempt_count_add(int val)
+{
+	*preempt_count_ptr() += val;
+}
+
+static __always_inline void __preempt_count_sub(int val)
+{
+	*preempt_count_ptr() -= val;
+}
+
+static __always_inline bool __preempt_count_dec_and_test(void)
+{
+	return !--*preempt_count_ptr();
+}
+
+/*
+ * Returns true when we need to resched and can (barring IRQ state).
+ */
+static __always_inline bool should_resched(void)
+{
+	return unlikely(!*preempt_count_ptr());
+}
+
+#ifdef CONFIG_PREEMPT
+extern asmlinkage void preempt_schedule(void);
+#define __preempt_schedule() preempt_schedule()
+
+#ifdef CONFIG_CONTEXT_TRACKING
+extern asmlinkage void preempt_schedule_context(void);
+#define __preempt_schedule_context() preempt_schedule_context()
+#endif
+#endif /* CONFIG_PREEMPT */
+
+#endif /* __ASM_PREEMPT_H */
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index 93b7f96..6d26b40 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -33,6 +33,16 @@
 #define ARCH_TIMER_MEM_PHYS_ACCESS	2
 #define ARCH_TIMER_MEM_VIRT_ACCESS	3
 
+#define ARCH_TIMER_USR_PCT_ACCESS_EN	(1 << 0) /* physical counter */
+#define ARCH_TIMER_USR_VCT_ACCESS_EN	(1 << 1) /* virtual counter */
+#define ARCH_TIMER_VIRT_EVT_EN		(1 << 2)
+#define ARCH_TIMER_EVT_TRIGGER_SHIFT	(4)
+#define ARCH_TIMER_EVT_TRIGGER_MASK	(0xF << ARCH_TIMER_EVT_TRIGGER_SHIFT)
+#define ARCH_TIMER_USR_VT_ACCESS_EN	(1 << 8) /* virtual timer registers */
+#define ARCH_TIMER_USR_PT_ACCESS_EN	(1 << 9) /* physical timer registers */
+
+#define ARCH_TIMER_EVT_STREAM_FREQ	10000	/* 100us */
+
 #ifdef CONFIG_ARM_ARCH_TIMER
 
 extern u32 arch_timer_get_rate(void);
diff --git a/include/dt-bindings/clock/efm32-cmu.h b/include/dt-bindings/clock/efm32-cmu.h
new file mode 100644
index 0000000..b21b91e
--- /dev/null
+++ b/include/dt-bindings/clock/efm32-cmu.h
@@ -0,0 +1,42 @@
+#ifndef __DT_BINDINGS_CLOCK_EFM32_CMU_H
+#define __DT_BINDINGS_CLOCK_EFM32_CMU_H
+
+#define clk_HFXO		0
+#define clk_HFRCO		1
+#define clk_LFXO		2
+#define clk_LFRCO		3
+#define clk_ULFRCO		4
+#define clk_AUXHFRCO		5
+#define clk_HFCLKNODIV		6
+#define clk_HFCLK		7
+#define clk_HFPERCLK		8
+#define clk_HFCORECLK		9
+#define clk_LFACLK		10
+#define clk_LFBCLK		11
+#define clk_WDOGCLK		12
+#define clk_HFCORECLKDMA	13
+#define clk_HFCORECLKAES	14
+#define clk_HFCORECLKUSBC	15
+#define clk_HFCORECLKUSB	16
+#define clk_HFCORECLKLE		17
+#define clk_HFCORECLKEBI	18
+#define clk_HFPERCLKUSART0	19
+#define clk_HFPERCLKUSART1	20
+#define clk_HFPERCLKUSART2	21
+#define clk_HFPERCLKUART0	22
+#define clk_HFPERCLKUART1	23
+#define clk_HFPERCLKTIMER0	24
+#define clk_HFPERCLKTIMER1	25
+#define clk_HFPERCLKTIMER2	26
+#define clk_HFPERCLKTIMER3	27
+#define clk_HFPERCLKACMP0	28
+#define clk_HFPERCLKACMP1	29
+#define clk_HFPERCLKI2C0	30
+#define clk_HFPERCLKI2C1	31
+#define clk_HFPERCLKGPIO	32
+#define clk_HFPERCLKVCMP	33
+#define clk_HFPERCLKPRS		34
+#define clk_HFPERCLKADC0	35
+#define clk_HFPERCLKDAC0	36
+
+#endif /* __DT_BINDINGS_CLOCK_EFM32_CMU_H */
diff --git a/include/dt-bindings/mfd/dbx500-prcmu.h b/include/dt-bindings/mfd/dbx500-prcmu.h
new file mode 100644
index 0000000..552a2d1
--- /dev/null
+++ b/include/dt-bindings/mfd/dbx500-prcmu.h
@@ -0,0 +1,83 @@
+/*
+ * This header provides constants for the PRCMU bindings.
+ *
+ */
+
+#ifndef _DT_BINDINGS_MFD_PRCMU_H
+#define _DT_BINDINGS_MFD_PRCMU_H
+
+/*
+ * Clock identifiers.
+ */
+#define ARMCLK			0
+#define PRCMU_ACLK		1
+#define PRCMU_SVAMMCSPCLK 	2
+#define PRCMU_SDMMCHCLK 	2  /* DBx540 only. */
+#define PRCMU_SIACLK 		3
+#define PRCMU_SIAMMDSPCLK 	3  /* DBx540 only. */
+#define PRCMU_SGACLK 		4
+#define PRCMU_UARTCLK 		5
+#define PRCMU_MSP02CLK 		6
+#define PRCMU_MSP1CLK 		7
+#define PRCMU_I2CCLK 		8
+#define PRCMU_SDMMCCLK 		9
+#define PRCMU_SLIMCLK 		10
+#define PRCMU_CAMCLK 		10 /* DBx540 only. */
+#define PRCMU_PER1CLK 		11
+#define PRCMU_PER2CLK 		12
+#define PRCMU_PER3CLK 		13
+#define PRCMU_PER5CLK 		14
+#define PRCMU_PER6CLK 		15
+#define PRCMU_PER7CLK 		16
+#define PRCMU_LCDCLK 		17
+#define PRCMU_BMLCLK 		18
+#define PRCMU_HSITXCLK 		19
+#define PRCMU_HSIRXCLK 		20
+#define PRCMU_HDMICLK		21
+#define PRCMU_APEATCLK 		22
+#define PRCMU_APETRACECLK 	23
+#define PRCMU_MCDECLK  	 	24
+#define PRCMU_IPI2CCLK  	25
+#define PRCMU_DSIALTCLK  	26
+#define PRCMU_DMACLK  	 	27
+#define PRCMU_B2R2CLK  	 	28
+#define PRCMU_TVCLK  	 	29
+#define SPARE_UNIPROCLK  	30
+#define PRCMU_SSPCLK  	 	31
+#define PRCMU_RNGCLK  	 	32
+#define PRCMU_UICCCLK  	 	33
+#define PRCMU_G1CLK             34 /* DBx540 only. */
+#define PRCMU_HVACLK            35 /* DBx540 only. */
+#define PRCMU_SPARE1CLK	 	36
+#define PRCMU_SPARE2CLK	 	37
+
+#define PRCMU_NUM_REG_CLOCKS  	38
+
+#define PRCMU_RTCCLK  	 	PRCMU_NUM_REG_CLOCKS
+#define PRCMU_SYSCLK  	 	39
+#define PRCMU_CDCLK  	 	40
+#define PRCMU_TIMCLK  	 	41
+#define PRCMU_PLLSOC0  	 	42
+#define PRCMU_PLLSOC1  	 	43
+#define PRCMU_ARMSS  	 	44
+#define PRCMU_PLLDDR  	 	45
+
+/* DSI Clocks */
+#define PRCMU_PLLDSI  	 	46
+#define PRCMU_DSI0CLK 	  	47
+#define PRCMU_DSI1CLK  	 	48
+#define PRCMU_DSI0ESCCLK  	49
+#define PRCMU_DSI1ESCCLK  	50
+#define PRCMU_DSI2ESCCLK  	51
+
+/* LCD DSI PLL - Ux540 only */
+#define PRCMU_PLLDSI_LCD        52
+#define PRCMU_DSI0CLK_LCD       53
+#define PRCMU_DSI1CLK_LCD       54
+#define PRCMU_DSI0ESCCLK_LCD    55
+#define PRCMU_DSI1ESCCLK_LCD    56
+#define PRCMU_DSI2ESCCLK_LCD    57
+
+#define PRCMU_NUM_CLKS  	58
+
+#endif
diff --git a/include/dt-bindings/pinctrl/am43xx.h b/include/dt-bindings/pinctrl/am43xx.h
new file mode 100644
index 0000000..eb6c366a
--- /dev/null
+++ b/include/dt-bindings/pinctrl/am43xx.h
@@ -0,0 +1,31 @@
+/*
+ * This header provides constants specific to AM43XX pinctrl bindings.
+ */
+
+#ifndef _DT_BINDINGS_PINCTRL_AM43XX_H
+#define _DT_BINDINGS_PINCTRL_AM43XX_H
+
+#define MUX_MODE0	0
+#define MUX_MODE1	1
+#define MUX_MODE2	2
+#define MUX_MODE3	3
+#define MUX_MODE4	4
+#define MUX_MODE5	5
+#define MUX_MODE6	6
+#define MUX_MODE7	7
+
+#define PULL_DISABLE		(1 << 16)
+#define PULL_UP			(1 << 17)
+#define INPUT_EN		(1 << 18)
+#define SLEWCTRL_FAST		(1 << 19)
+#define DS0_PULL_UP_DOWN_EN	(1 << 27)
+
+#define PIN_OUTPUT		(PULL_DISABLE)
+#define PIN_OUTPUT_PULLUP	(PULL_UP)
+#define PIN_OUTPUT_PULLDOWN	0
+#define PIN_INPUT		(INPUT_EN | PULL_DISABLE)
+#define PIN_INPUT_PULLUP	(INPUT_EN | PULL_UP)
+#define PIN_INPUT_PULLDOWN	(INPUT_EN)
+
+#endif
+
diff --git a/include/dt-bindings/pinctrl/at91.h b/include/dt-bindings/pinctrl/at91.h
index d7988b4..0fee6ff 100644
--- a/include/dt-bindings/pinctrl/at91.h
+++ b/include/dt-bindings/pinctrl/at91.h
@@ -16,7 +16,7 @@
 #define AT91_PINCTRL_PULL_DOWN		(1 << 3)
 #define AT91_PINCTRL_DIS_SCHMIT		(1 << 4)
 #define AT91_PINCTRL_DEBOUNCE		(1 << 16)
-#define AT91_PINCTRL_DEBOUNCE_VA(x)	(x << 17)
+#define AT91_PINCTRL_DEBOUNCE_VAL(x)	(x << 17)
 
 #define AT91_PINCTRL_PULL_UP_DEGLITCH	(AT91_PINCTRL_PULL_UP | AT91_PINCTRL_DEGLITCH)
 
diff --git a/include/dt-bindings/pinctrl/dra.h b/include/dt-bindings/pinctrl/dra.h
new file mode 100644
index 0000000..002a285
--- /dev/null
+++ b/include/dt-bindings/pinctrl/dra.h
@@ -0,0 +1,50 @@
+/*
+ * This header provides constants for DRA pinctrl bindings.
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Rajendra Nayak <rnayak@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _DT_BINDINGS_PINCTRL_DRA_H
+#define _DT_BINDINGS_PINCTRL_DRA_H
+
+/* DRA7 mux mode options for each pin. See TRM for options */
+#define MUX_MODE0	0x0
+#define MUX_MODE1	0x1
+#define MUX_MODE2	0x2
+#define MUX_MODE3	0x3
+#define MUX_MODE4	0x4
+#define MUX_MODE5	0x5
+#define MUX_MODE6	0x6
+#define MUX_MODE7	0x7
+#define MUX_MODE8	0x8
+#define MUX_MODE9	0x9
+#define MUX_MODE10	0xa
+#define MUX_MODE11	0xb
+#define MUX_MODE12	0xc
+#define MUX_MODE13	0xd
+#define MUX_MODE14	0xe
+#define MUX_MODE15	0xf
+
+#define PULL_ENA		(1 << 16)
+#define PULL_UP			(1 << 17)
+#define INPUT_EN		(1 << 18)
+#define SLEWCONTROL		(1 << 19)
+#define WAKEUP_EN		(1 << 24)
+#define WAKEUP_EVENT		(1 << 25)
+
+/* Active pin states */
+#define PIN_OUTPUT		0
+#define PIN_OUTPUT_PULLUP	(PIN_OUTPUT | PULL_ENA | PULL_UP)
+#define PIN_OUTPUT_PULLDOWN	(PIN_OUTPUT | PULL_ENA)
+#define PIN_INPUT		INPUT_EN
+#define PIN_INPUT_SLEW		(INPUT_EN | SLEWCONTROL)
+#define PIN_INPUT_PULLUP	(PULL_ENA | INPUT_EN | PULL_UP)
+#define PIN_INPUT_PULLDOWN	(PULL_ENA | INPUT_EN)
+
+#endif
+
diff --git a/include/dt-bindings/pinctrl/omap.h b/include/dt-bindings/pinctrl/omap.h
index edbd250..bed35e3 100644
--- a/include/dt-bindings/pinctrl/omap.h
+++ b/include/dt-bindings/pinctrl/omap.h
@@ -23,7 +23,7 @@
 #define PULL_UP			(1 << 4)
 #define ALTELECTRICALSEL	(1 << 5)
 
-/* 34xx specific mux bit defines */
+/* omap3/4/5 specific mux bit defines */
 #define INPUT_EN		(1 << 8)
 #define OFF_EN			(1 << 9)
 #define OFFOUT_EN		(1 << 10)
@@ -31,8 +31,6 @@
 #define OFF_PULL_EN		(1 << 12)
 #define OFF_PULL_UP		(1 << 13)
 #define WAKEUP_EN		(1 << 14)
-
-/* 44xx specific mux bit defines */
 #define WAKEUP_EVENT		(1 << 15)
 
 /* Active pin states */
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index a5db4ae..c30bac8 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -311,6 +311,7 @@
 #define OSC_INVALID_REVISION_ERROR	8
 #define OSC_CAPABILITIES_MASK_ERROR	16
 
+acpi_status acpi_str_to_uuid(char *str, u8 *uuid);
 acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context);
 
 /* platform-wide _OSC bits */
diff --git a/include/linux/acpi_gpio.h b/include/linux/acpi_gpio.h
index 4c120a1..d875bc3 100644
--- a/include/linux/acpi_gpio.h
+++ b/include/linux/acpi_gpio.h
@@ -2,36 +2,35 @@
 #define _LINUX_ACPI_GPIO_H_
 
 #include <linux/device.h>
+#include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 
 /**
  * struct acpi_gpio_info - ACPI GPIO specific information
  * @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo
+ * @active_low: in case of @gpioint, the pin is active low
  */
 struct acpi_gpio_info {
 	bool gpioint;
+	bool active_low;
 };
 
 #ifdef CONFIG_GPIO_ACPI
 
-int acpi_get_gpio(char *path, int pin);
-int acpi_get_gpio_by_index(struct device *dev, int index,
-			   struct acpi_gpio_info *info);
+struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
+					  struct acpi_gpio_info *info);
 void acpi_gpiochip_request_interrupts(struct gpio_chip *chip);
 void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
 
 #else /* CONFIG_GPIO_ACPI */
 
-static inline int acpi_get_gpio(char *path, int pin)
+static inline struct gpio_desc *
+acpi_get_gpiod_by_index(struct device *dev, int index,
+			struct acpi_gpio_info *info)
 {
-	return -ENODEV;
-}
-
-static inline int acpi_get_gpio_by_index(struct device *dev, int index,
-					 struct acpi_gpio_info *info)
-{
-	return -ENODEV;
+	return ERR_PTR(-ENOSYS);
 }
 
 static inline void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { }
@@ -39,4 +38,14 @@
 
 #endif /* CONFIG_GPIO_ACPI */
 
+static inline int acpi_get_gpio_by_index(struct device *dev, int index,
+					 struct acpi_gpio_info *info)
+{
+	struct gpio_desc *desc = acpi_get_gpiod_by_index(dev, index, info);
+
+	if (IS_ERR(desc))
+		return PTR_ERR(desc);
+	return desc_to_gpio(desc);
+}
+
 #endif /* _LINUX_ACPI_GPIO_H_ */
diff --git a/include/linux/ata.h b/include/linux/ata.h
index bf4c69c..f2f4d8d 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -219,6 +219,7 @@
 	ATA_CMD_IDLE		= 0xE3, /* place in idle power mode */
 	ATA_CMD_EDD		= 0x90,	/* execute device diagnostic */
 	ATA_CMD_DOWNLOAD_MICRO  = 0x92,
+	ATA_CMD_DOWNLOAD_MICRO_DMA = 0x93,
 	ATA_CMD_NOP		= 0x00,
 	ATA_CMD_FLUSH		= 0xE7,
 	ATA_CMD_FLUSH_EXT	= 0xEA,
@@ -268,12 +269,15 @@
 	ATA_CMD_WRITE_LOG_EXT	= 0x3F,
 	ATA_CMD_READ_LOG_DMA_EXT = 0x47,
 	ATA_CMD_WRITE_LOG_DMA_EXT = 0x57,
+	ATA_CMD_TRUSTED_NONDATA	= 0x5B,
 	ATA_CMD_TRUSTED_RCV	= 0x5C,
 	ATA_CMD_TRUSTED_RCV_DMA = 0x5D,
 	ATA_CMD_TRUSTED_SND	= 0x5E,
 	ATA_CMD_TRUSTED_SND_DMA = 0x5F,
 	ATA_CMD_PMP_READ	= 0xE4,
+	ATA_CMD_PMP_READ_DMA	= 0xE9,
 	ATA_CMD_PMP_WRITE	= 0xE8,
+	ATA_CMD_PMP_WRITE_DMA	= 0xEB,
 	ATA_CMD_CONF_OVERLAY	= 0xB1,
 	ATA_CMD_SEC_SET_PASS	= 0xF1,
 	ATA_CMD_SEC_UNLOCK	= 0xF2,
@@ -292,6 +296,9 @@
 	ATA_CMD_CFA_TRANS_SECT	= 0x87,
 	ATA_CMD_CFA_ERASE	= 0xC0,
 	ATA_CMD_CFA_WRITE_MULT_NE = 0xCD,
+	ATA_CMD_REQ_SENSE_DATA  = 0x0B,
+	ATA_CMD_SANITIZE_DEVICE = 0xB4,
+
 	/* marked obsolete in the ATA/ATAPI-7 spec */
 	ATA_CMD_RESTORE		= 0x10,
 
diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
index be201ca..00beddf 100644
--- a/include/linux/atmel_serial.h
+++ b/include/linux/atmel_serial.h
@@ -125,5 +125,6 @@
 #define ATMEL_US_IF		0x4c			/* IrDA Filter Register */
 
 #define ATMEL_US_NAME		0xf0			/* Ip Name */
+#define ATMEL_US_VERSION	0xfc			/* Ip Version */
 
 #endif
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index a3b6b82..bd0c459 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -10,6 +10,14 @@
 #define BITS_TO_LONGS(nr)	DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
 #endif
 
+/*
+ * Create a contiguous bitmask starting at bit position @l and ending at
+ * position @h. For example
+ * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.
+ */
+#define GENMASK(h, l)		(((U32_C(1) << ((h) - (l) + 1)) - 1) << (l))
+#define GENMASK_ULL(h, l)	(((U64_C(1) << ((h) - (l) + 1)) - 1) << (l))
+
 extern unsigned int __sw_hweight8(unsigned int w);
 extern unsigned int __sw_hweight16(unsigned int w);
 extern unsigned int __sw_hweight32(unsigned int w);
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 3561d30..39c1d94 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -612,11 +612,6 @@
 	int subsys_id;
 	int disabled;
 	int early_init;
-	/*
-	 * True if this subsys uses ID. ID is not available before cgroup_init()
-	 * (not available in early_init time.)
-	 */
-	bool use_id;
 
 	/*
 	 * If %false, this subsystem is properly hierarchical -
@@ -642,9 +637,6 @@
 	 */
 	struct cgroupfs_root *root;
 	struct list_head sibling;
-	/* used when use_id == true */
-	struct idr idr;
-	spinlock_t id_lock;
 
 	/* list of cftype_sets */
 	struct list_head cftsets;
@@ -875,35 +867,6 @@
 int cgroup_attach_task_all(struct task_struct *from, struct task_struct *);
 int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from);
 
-/*
- * CSS ID is ID for cgroup_subsys_state structs under subsys. This only works
- * if cgroup_subsys.use_id == true. It can be used for looking up and scanning.
- * CSS ID is assigned at cgroup allocation (create) automatically
- * and removed when subsys calls free_css_id() function. This is because
- * the lifetime of cgroup_subsys_state is subsys's matter.
- *
- * Looking up and scanning function should be called under rcu_read_lock().
- * Taking cgroup_mutex is not necessary for following calls.
- * But the css returned by this routine can be "not populated yet" or "being
- * destroyed". The caller should check css and cgroup's status.
- */
-
-/*
- * Typically Called at ->destroy(), or somewhere the subsys frees
- * cgroup_subsys_state.
- */
-void free_css_id(struct cgroup_subsys *ss, struct cgroup_subsys_state *css);
-
-/* Find a cgroup_subsys_state which has given ID */
-
-struct cgroup_subsys_state *css_lookup(struct cgroup_subsys *ss, int id);
-
-/* Returns true if root is ancestor of cg */
-bool css_is_ancestor(struct cgroup_subsys_state *cg,
-		     const struct cgroup_subsys_state *root);
-
-/* Get id and depth of css */
-unsigned short css_id(struct cgroup_subsys_state *css);
 struct cgroup_subsys_state *css_from_dir(struct dentry *dentry,
 					 struct cgroup_subsys *ss);
 
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 73bdb69..7e59253 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -472,6 +472,7 @@
 struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
 				  void *data);
 struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data);
+int of_clk_get_parent_count(struct device_node *np);
 const char *of_clk_get_parent_name(struct device_node *np, int index);
 
 void of_clk_init(const struct of_device_id *matches);
diff --git a/include/linux/clk/mxs.h b/include/linux/clk/mxs.h
index 90c30dc..5138a90 100644
--- a/include/linux/clk/mxs.h
+++ b/include/linux/clk/mxs.h
@@ -9,8 +9,6 @@
 #ifndef __LINUX_CLK_MXS_H
 #define __LINUX_CLK_MXS_H
 
-int mx23_clocks_init(void);
-int mx28_clocks_init(void);
 int mxs_saif_clkmux_select(unsigned int clkmux);
 
 #endif
diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h
deleted file mode 100644
index e074fdd..0000000
--- a/include/linux/clk/sunxi.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2012 Maxime Ripard
- *
- * Maxime Ripard <maxime.ripard@free-electrons.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __LINUX_CLK_SUNXI_H_
-#define __LINUX_CLK_SUNXI_H_
-
-void __init sunxi_init_clocks(void);
-
-#endif
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
index 0857922..493aa02 100644
--- a/include/linux/clockchips.h
+++ b/include/linux/clockchips.h
@@ -60,6 +60,7 @@
  * Core shall set the interrupt affinity dynamically in broadcast mode
  */
 #define CLOCK_EVT_FEAT_DYNIRQ		0x000020
+#define CLOCK_EVT_FEAT_PERCPU		0x000040
 
 /**
  * struct clock_event_device - clock event device descriptor
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index dbbf8aa..67301a4 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -292,6 +292,8 @@
 extern struct clocksource * __init __weak clocksource_default_clock(void);
 extern void clocksource_mark_unstable(struct clocksource *cs);
 
+extern u64
+clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask);
 extern void
 clocks_calc_mult_shift(u32 *mult, u32 *shift, u32 from, u32 to, u32 minsec);
 
diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h
index 842de22..ded4299 100644
--- a/include/linux/compiler-gcc4.h
+++ b/include/linux/compiler-gcc4.h
@@ -65,6 +65,21 @@
 #define __visible __attribute__((externally_visible))
 #endif
 
+/*
+ * GCC 'asm goto' miscompiles certain code sequences:
+ *
+ *   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670
+ *
+ * Work it around via a compiler barrier quirk suggested by Jakub Jelinek.
+ * Fixed in GCC 4.8.2 and later versions.
+ *
+ * (asm goto is automatically volatile - the naming reflects this.)
+ */
+#if GCC_VERSION <= 40801
+# define asm_volatile_goto(x...)	do { asm goto(x); asm (""); } while (0)
+#else
+# define asm_volatile_goto(x...)	do { asm goto(x); } while (0)
+#endif
 
 #ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP
 #if GCC_VERSION >= 40400
diff --git a/include/linux/completion.h b/include/linux/completion.h
index 3cd574d..22c33e3 100644
--- a/include/linux/completion.h
+++ b/include/linux/completion.h
@@ -5,7 +5,7 @@
  * (C) Copyright 2001 Linus Torvalds
  *
  * Atomic wait-for-completion handler data structures.
- * See kernel/sched/core.c for details.
+ * See kernel/sched/completion.c for details.
  */
 
 #include <linux/wait.h>
diff --git a/include/linux/cper.h b/include/linux/cper.h
index c230494..2fc0ec3 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -218,8 +218,8 @@
 #define CPER_PROC_VALID_IP			0x1000
 
 #define CPER_MEM_VALID_ERROR_STATUS		0x0001
-#define CPER_MEM_VALID_PHYSICAL_ADDRESS		0x0002
-#define CPER_MEM_VALID_PHYSICAL_ADDRESS_MASK	0x0004
+#define CPER_MEM_VALID_PA			0x0002
+#define CPER_MEM_VALID_PA_MASK			0x0004
 #define CPER_MEM_VALID_NODE			0x0008
 #define CPER_MEM_VALID_CARD			0x0010
 #define CPER_MEM_VALID_MODULE			0x0020
@@ -232,6 +232,9 @@
 #define CPER_MEM_VALID_RESPONDER_ID		0x1000
 #define CPER_MEM_VALID_TARGET_ID		0x2000
 #define CPER_MEM_VALID_ERROR_TYPE		0x4000
+#define CPER_MEM_VALID_RANK_NUMBER		0x8000
+#define CPER_MEM_VALID_CARD_HANDLE		0x10000
+#define CPER_MEM_VALID_MODULE_HANDLE		0x20000
 
 #define CPER_PCIE_VALID_PORT_TYPE		0x0001
 #define CPER_PCIE_VALID_VERSION			0x0002
@@ -347,6 +350,10 @@
 	__u64	responder_id;
 	__u64	target_id;
 	__u8	error_type;
+	__u8	reserved;
+	__u16	rank;
+	__u16	mem_array_handle;	/* card handle in UEFI 2.4 */
+	__u16	mem_dev_handle;		/* module handle in UEFI 2.4 */
 };
 
 struct cper_sec_pcie {
@@ -389,6 +396,6 @@
 
 u64 cper_next_record_id(void);
 void cper_print_bits(const char *prefix, unsigned int bits,
-		     const char *strs[], unsigned int strs_size);
+		     const char * const strs[], unsigned int strs_size);
 
 #endif
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 801ff9e..fbd25c3 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -18,6 +18,7 @@
 #include <linux/cpumask.h>
 
 struct device;
+struct device_node;
 
 struct cpu {
 	int node_id;		/* The node which contains the CPU */
@@ -29,6 +30,8 @@
 extern struct device *get_cpu_device(unsigned cpu);
 extern bool cpu_is_hotpluggable(unsigned cpu);
 extern bool arch_match_cpu_phys_id(int cpu, u64 phys_id);
+extern bool arch_find_n_match_cpu_physical_id(struct device_node *cpun,
+					      int cpu, unsigned int *thread);
 
 extern int cpu_add_dev_attr(struct device_attribute *attr);
 extern void cpu_remove_dev_attr(struct device_attribute *attr);
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 263489d..4d0b4d1 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -206,6 +206,12 @@
 	return ERR_PTR(-ENODEV);
 }
 
+static inline struct dentry *debugfs_create_atomic_t(const char *name, umode_t mode,
+				     struct dentry *parent, atomic_t *value)
+{
+	return ERR_PTR(-ENODEV);
+}
+
 static inline struct dentry *debugfs_create_bool(const char *name, umode_t mode,
 						 struct dentry *parent,
 						 u32 *value)
@@ -227,6 +233,12 @@
 	return ERR_PTR(-ENODEV);
 }
 
+static inline int debugfs_print_regs32(struct seq_file *s, const struct debugfs_reg32 *regs,
+			 int nregs, void __iomem *base, char *prefix)
+{
+	return 0;
+}
+
 static inline bool debugfs_initialized(void)
 {
 	return false;
diff --git a/include/linux/device.h b/include/linux/device.h
index 2a9d6ed..b025925 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -26,6 +26,7 @@
 #include <linux/atomic.h>
 #include <linux/ratelimit.h>
 #include <linux/uidgid.h>
+#include <linux/gfp.h>
 #include <asm/device.h>
 
 struct device;
@@ -63,9 +64,7 @@
  * @name:	The name of the bus.
  * @dev_name:	Used for subsystems to enumerate devices like ("foo%u", dev->id).
  * @dev_root:	Default device to use as the parent.
- * @bus_attrs:	Default attributes of the bus.
  * @dev_attrs:	Default attributes of the devices on the bus.
- * @drv_attrs:	Default attributes of the device drivers on the bus.
  * @bus_groups:	Default attributes of the bus.
  * @dev_groups:	Default attributes of the devices on the bus.
  * @drv_groups: Default attributes of the device drivers on the bus.
@@ -106,9 +105,7 @@
 	const char		*name;
 	const char		*dev_name;
 	struct device		*dev_root;
-	struct bus_attribute	*bus_attrs;	/* use bus_groups instead */
 	struct device_attribute	*dev_attrs;	/* use dev_groups instead */
-	struct driver_attribute	*drv_attrs;	/* use drv_groups instead */
 	const struct attribute_group **bus_groups;
 	const struct attribute_group **dev_groups;
 	const struct attribute_group **drv_groups;
@@ -329,8 +326,6 @@
  * @owner:	The module owner.
  * @class_attrs: Default attributes of this class.
  * @dev_groups:	Default attributes of the devices that belong to the class.
- * @dev_attrs:	Default attributes of the devices belong to the class.
- * @dev_bin_attrs: Default binary attributes of the devices belong to the class.
  * @dev_kobj:	The kobject that represents this class and links it into the hierarchy.
  * @dev_uevent:	Called when a device is added, removed from this class, or a
  *		few other things that generate uevents to add the environment
@@ -358,9 +353,7 @@
 	struct module		*owner;
 
 	struct class_attribute		*class_attrs;
-	struct device_attribute		*dev_attrs;	/* use dev_groups instead */
 	const struct attribute_group	**dev_groups;
-	struct bin_attribute		*dev_bin_attrs;
 	struct kobject			*dev_kobj;
 
 	int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
@@ -427,8 +420,6 @@
 			char *buf);
 	ssize_t (*store)(struct class *class, struct class_attribute *attr,
 			const char *buf, size_t count);
-	const void *(*namespace)(struct class *class,
-				 const struct class_attribute *attr);
 };
 
 #define CLASS_ATTR(_name, _mode, _show, _store) \
@@ -438,10 +429,24 @@
 #define CLASS_ATTR_RO(_name) \
 	struct class_attribute class_attr_##_name = __ATTR_RO(_name)
 
-extern int __must_check class_create_file(struct class *class,
-					  const struct class_attribute *attr);
-extern void class_remove_file(struct class *class,
-			      const struct class_attribute *attr);
+extern int __must_check class_create_file_ns(struct class *class,
+					     const struct class_attribute *attr,
+					     const void *ns);
+extern void class_remove_file_ns(struct class *class,
+				 const struct class_attribute *attr,
+				 const void *ns);
+
+static inline int __must_check class_create_file(struct class *class,
+					const struct class_attribute *attr)
+{
+	return class_create_file_ns(class, attr, NULL);
+}
+
+static inline void class_remove_file(struct class *class,
+				     const struct class_attribute *attr)
+{
+	return class_remove_file_ns(class, attr, NULL);
+}
 
 /* Simple class attribute that is just a static string */
 struct class_attribute_string {
@@ -602,8 +607,24 @@
 extern void devres_remove_group(struct device *dev, void *id);
 extern int devres_release_group(struct device *dev, void *id);
 
-/* managed kzalloc/kfree for device drivers, no kmalloc, always use kzalloc */
-extern void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp);
+/* managed devm_k.alloc/kfree for device drivers */
+extern void *devm_kmalloc(struct device *dev, size_t size, gfp_t gfp);
+static inline void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp)
+{
+	return devm_kmalloc(dev, size, gfp | __GFP_ZERO);
+}
+static inline void *devm_kmalloc_array(struct device *dev,
+				       size_t n, size_t size, gfp_t flags)
+{
+	if (size != 0 && n > SIZE_MAX / size)
+		return NULL;
+	return devm_kmalloc(dev, n * size, flags);
+}
+static inline void *devm_kcalloc(struct device *dev,
+				 size_t n, size_t size, gfp_t flags)
+{
+	return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
+}
 extern void devm_kfree(struct device *dev, void *p);
 
 void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res);
@@ -1149,16 +1170,15 @@
 #endif
 
 /*
- * dev_WARN*() acts like dev_printk(), but with the key difference
- * of using a WARN/WARN_ON to get the message out, including the
- * file/line information and a backtrace.
+ * dev_WARN*() acts like dev_printk(), but with the key difference of
+ * using WARN/WARN_ONCE to include file/line information and a backtrace.
  */
 #define dev_WARN(dev, format, arg...) \
-	WARN(1, "Device: %s\n" format, dev_driver_string(dev), ## arg);
+	WARN(1, "%s %s: " format, dev_driver_string(dev), dev_name(dev), ## arg);
 
 #define dev_WARN_ONCE(dev, condition, format, arg...) \
-	WARN_ONCE(condition, "Device %s\n" format, \
-			dev_driver_string(dev), ## arg)
+	WARN_ONCE(condition, "%s %s: " format, \
+			dev_driver_string(dev), dev_name(dev), ## arg)
 
 /* Create alias, so I can be autoloaded. */
 #define MODULE_ALIAS_CHARDEV(major,minor) \
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index b6eb7a0..f820f0a 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -99,6 +99,7 @@
 extern const struct dmi_device * dmi_find_device(int type, const char *name,
 	const struct dmi_device *from);
 extern void dmi_scan_machine(void);
+extern void dmi_memdev_walk(void);
 extern void dmi_set_dump_stack_arch_desc(void);
 extern bool dmi_get_date(int field, int *yearp, int *monthp, int *dayp);
 extern int dmi_name_in_vendors(const char *str);
@@ -107,6 +108,7 @@
 extern int dmi_walk(void (*decode)(const struct dmi_header *, void *),
 	void *private_data);
 extern bool dmi_match(enum dmi_field f, const char *str);
+extern void dmi_memdev_name(u16 handle, const char **bank, const char **device);
 
 #else
 
@@ -115,6 +117,7 @@
 static inline const struct dmi_device * dmi_find_device(int type, const char *name,
 	const struct dmi_device *from) { return NULL; }
 static inline void dmi_scan_machine(void) { return; }
+static inline void dmi_memdev_walk(void) { }
 static inline void dmi_set_dump_stack_arch_desc(void) { }
 static inline bool dmi_get_date(int field, int *yearp, int *monthp, int *dayp)
 {
@@ -133,6 +136,8 @@
 	void *private_data) { return -1; }
 static inline bool dmi_match(enum dmi_field f, const char *str)
 	{ return false; }
+static inline void dmi_memdev_name(u16 handle, const char **bank,
+		const char **device) { }
 static inline const struct dmi_system_id *
 	dmi_first_match(const struct dmi_system_id *list) { return NULL; }
 
diff --git a/include/linux/edac.h b/include/linux/edac.h
index 5c6d7fb..dbdffe8 100644
--- a/include/linux/edac.h
+++ b/include/linux/edac.h
@@ -51,7 +51,7 @@
 #define EDAC_MC_LABEL_LEN	31
 
 /* Maximum size of the location string */
-#define LOCATION_SIZE 80
+#define LOCATION_SIZE 256
 
 /* Defines the maximum number of labels that can be reported */
 #define EDAC_MAX_LABELS		8
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 5f8f176..bc5687d 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -39,6 +39,8 @@
 typedef unsigned long efi_status_t;
 typedef u8 efi_bool_t;
 typedef u16 efi_char16_t;		/* UNICODE character */
+typedef u64 efi_physical_addr_t;
+typedef void *efi_handle_t;
 
 
 typedef struct {
@@ -96,6 +98,7 @@
 #define EFI_MEMORY_DESCRIPTOR_VERSION	1
 
 #define EFI_PAGE_SHIFT		12
+#define EFI_PAGE_SIZE		(1UL << EFI_PAGE_SHIFT)
 
 typedef struct {
 	u32 type;
@@ -157,11 +160,13 @@
 	efi_table_hdr_t hdr;
 	void *raise_tpl;
 	void *restore_tpl;
-	void *allocate_pages;
-	void *free_pages;
-	void *get_memory_map;
-	void *allocate_pool;
-	void *free_pool;
+	efi_status_t (*allocate_pages)(int, int, unsigned long,
+				       efi_physical_addr_t *);
+	efi_status_t (*free_pages)(efi_physical_addr_t, unsigned long);
+	efi_status_t (*get_memory_map)(unsigned long *, void *, unsigned long *,
+				       unsigned long *, u32 *);
+	efi_status_t (*allocate_pool)(int, unsigned long, void **);
+	efi_status_t (*free_pool)(void *);
 	void *create_event;
 	void *set_timer;
 	void *wait_for_event;
@@ -171,7 +176,7 @@
 	void *install_protocol_interface;
 	void *reinstall_protocol_interface;
 	void *uninstall_protocol_interface;
-	void *handle_protocol;
+	efi_status_t (*handle_protocol)(efi_handle_t, efi_guid_t *, void **);
 	void *__reserved;
 	void *register_protocol_notify;
 	void *locate_handle;
@@ -181,7 +186,7 @@
 	void *start_image;
 	void *exit;
 	void *unload_image;
-	void *exit_boot_services;
+	efi_status_t (*exit_boot_services)(efi_handle_t, unsigned long);
 	void *get_next_monotonic_count;
 	void *stall;
 	void *set_watchdog_timer;
@@ -404,6 +409,12 @@
 	unsigned long table;
 } efi_config_table_t;
 
+typedef struct {
+	efi_guid_t guid;
+	const char *name;
+	unsigned long *ptr;
+} efi_config_table_type_t;
+
 #define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL)
 
 #define EFI_2_30_SYSTEM_TABLE_REVISION  ((2 << 16) | (30))
@@ -488,10 +499,6 @@
 	unsigned long unload;
 } efi_loaded_image_t;
 
-typedef struct {
-	u64 revision;
-	void *open_volume;
-} efi_file_io_interface_t;
 
 typedef struct {
 	u64 size;
@@ -504,20 +511,30 @@
 	efi_char16_t filename[1];
 } efi_file_info_t;
 
-typedef struct {
+typedef struct _efi_file_handle {
 	u64 revision;
-	void *open;
-	void *close;
+	efi_status_t (*open)(struct _efi_file_handle *,
+			     struct _efi_file_handle **,
+			     efi_char16_t *, u64, u64);
+	efi_status_t (*close)(struct _efi_file_handle *);
 	void *delete;
-	void *read;
+	efi_status_t (*read)(struct _efi_file_handle *, unsigned long *,
+			     void *);
 	void *write;
 	void *get_position;
 	void *set_position;
-	void *get_info;
+	efi_status_t (*get_info)(struct _efi_file_handle *, efi_guid_t *,
+			unsigned long *, void *);
 	void *set_info;
 	void *flush;
 } efi_file_handle_t;
 
+typedef struct _efi_file_io_interface {
+	u64 revision;
+	int (*open_volume)(struct _efi_file_io_interface *,
+			   efi_file_handle_t **);
+} efi_file_io_interface_t;
+
 #define EFI_FILE_MODE_READ	0x0000000000000001
 #define EFI_FILE_MODE_WRITE	0x0000000000000002
 #define EFI_FILE_MODE_CREATE	0x8000000000000000
@@ -552,6 +569,7 @@
 	efi_get_next_high_mono_count_t *get_next_high_mono_count;
 	efi_reset_system_t *reset_system;
 	efi_set_virtual_address_map_t *set_virtual_address_map;
+	struct efi_memory_map *memmap;
 } efi;
 
 static inline int
@@ -587,6 +605,7 @@
 }
 #endif
 extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr);
+extern int efi_config_init(efi_config_table_type_t *arch_tables);
 extern u64 efi_get_iobase (void);
 extern u32 efi_mem_type (unsigned long phys_addr);
 extern u64 efi_mem_attributes (unsigned long phys_addr);
@@ -784,6 +803,13 @@
 	struct kobject kobj;
 };
 
+
+struct efi_simple_text_output_protocol {
+	void *reset;
+	efi_status_t (*output_string)(void *, void *);
+	void *test_string;
+};
+
 extern struct list_head efivar_sysfs_list;
 
 static inline void
diff --git a/include/linux/extcon.h b/include/linux/extcon.h
index fcb51c8..21c59af 100644
--- a/include/linux/extcon.h
+++ b/include/linux/extcon.h
@@ -51,10 +51,10 @@
 enum extcon_cable_name {
 	EXTCON_USB = 0,
 	EXTCON_USB_HOST,
-	EXTCON_TA, /* Travel Adaptor */
+	EXTCON_TA,			/* Travel Adaptor */
 	EXTCON_FAST_CHARGER,
 	EXTCON_SLOW_CHARGER,
-	EXTCON_CHARGE_DOWNSTREAM, /* Charging an external device */
+	EXTCON_CHARGE_DOWNSTREAM,	/* Charging an external device */
 	EXTCON_HDMI,
 	EXTCON_MHL,
 	EXTCON_DVI,
@@ -76,8 +76,8 @@
 
 /**
  * struct extcon_dev - An extcon device represents one external connector.
- * @name:	The name of this extcon device. Parent device name is used
- *		if NULL.
+ * @name:		The name of this extcon device. Parent device name is
+ *			used if NULL.
  * @supported_cable:	Array of supported cable names ending with NULL.
  *			If supported_cable is NULL, cable name related APIs
  *			are disabled.
@@ -89,21 +89,21 @@
  *			be attached simulataneously. {0x7, 0} is equivalent to
  *			{0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there
  *			can be no simultaneous connections.
- * @print_name:	An optional callback to override the method to print the
- *		name of the extcon device.
+ * @print_name:		An optional callback to override the method to print the
+ *			name of the extcon device.
  * @print_state:	An optional callback to override the method to print the
- *		status of the extcon device.
- * @dev:	Device of this extcon. Do not provide at register-time.
- * @state:	Attach/detach state of this extcon. Do not provide at
- *		register-time
- * @nh:	Notifier for the state change events from this extcon
- * @entry:	To support list of extcon devices so that users can search
- *		for extcon devices based on the extcon name.
+ *			status of the extcon device.
+ * @dev:		Device of this extcon.
+ * @state:		Attach/detach state of this extcon. Do not provide at
+ *			register-time.
+ * @nh:			Notifier for the state change events from this extcon
+ * @entry:		To support list of extcon devices so that users can search
+ *			for extcon devices based on the extcon name.
  * @lock:
  * @max_supported:	Internal value to store the number of cables.
  * @extcon_dev_type:	Device_type struct to provide attribute_groups
  *			customized for each extcon device.
- * @cables:	Sysfs subdirectories. Each represents one cable.
+ * @cables:		Sysfs subdirectories. Each represents one cable.
  *
  * In most cases, users only need to provide "User initializing data" of
  * this struct when registering an extcon. In some exceptional cases,
@@ -111,26 +111,27 @@
  * are overwritten by register function.
  */
 struct extcon_dev {
-	/* --- Optional user initializing data --- */
-	const char	*name;
+	/* Optional user initializing data */
+	const char *name;
 	const char **supported_cable;
-	const u32	*mutually_exclusive;
+	const u32 *mutually_exclusive;
 
-	/* --- Optional callbacks to override class functions --- */
+	/* Optional callbacks to override class functions */
 	ssize_t	(*print_name)(struct extcon_dev *edev, char *buf);
 	ssize_t	(*print_state)(struct extcon_dev *edev, char *buf);
 
-	/* --- Internal data. Please do not set. --- */
-	struct device	*dev;
-	u32		state;
+	/* Internal data. Please do not set. */
+	struct device dev;
 	struct raw_notifier_head nh;
 	struct list_head entry;
-	spinlock_t lock; /* could be called by irq handler */
 	int max_supported;
+	spinlock_t lock;	/* could be called by irq handler */
+	u32 state;
 
 	/* /sys/class/extcon/.../cable.n/... */
 	struct device_type extcon_dev_type;
 	struct extcon_cable *cables;
+
 	/* /sys/class/extcon/.../mutually_exclusive/... */
 	struct attribute_group attr_g_muex;
 	struct attribute **attrs_muex;
@@ -138,13 +139,13 @@
 };
 
 /**
- * struct extcon_cable	- An internal data for each cable of extcon device.
- * @edev:	The extcon device
+ * struct extcon_cable - An internal data for each cable of extcon device.
+ * @edev:		The extcon device
  * @cable_index:	Index of this cable in the edev
- * @attr_g:	Attribute group for the cable
- * @attr_name:	"name" sysfs entry
- * @attr_state:	"state" sysfs entry
- * @attrs:	Array pointing to attr_name and attr_state for attr_g
+ * @attr_g:		Attribute group for the cable
+ * @attr_name:		"name" sysfs entry
+ * @attr_state:		"state" sysfs entry
+ * @attrs:		Array pointing to attr_name and attr_state for attr_g
  */
 struct extcon_cable {
 	struct extcon_dev *edev;
@@ -159,11 +160,13 @@
 
 /**
  * struct extcon_specific_cable_nb - An internal data for
- *				extcon_register_interest().
- * @internal_nb:	a notifier block bridging extcon notifier and cable notifier.
- * @user_nb:	user provided notifier block for events from a specific cable.
+ *				     extcon_register_interest().
+ * @internal_nb:	A notifier block bridging extcon notifier
+ *			and cable notifier.
+ * @user_nb:		user provided notifier block for events from
+ *			a specific cable.
  * @cable_index:	the target cable.
- * @edev:	the target extcon device.
+ * @edev:		the target extcon device.
  * @previous_value:	the saved previous event value.
  */
 struct extcon_specific_cable_nb {
@@ -180,7 +183,7 @@
  * Following APIs are for notifiers or configurations.
  * Notifiers are the external port and connection devices.
  */
-extern int extcon_dev_register(struct extcon_dev *edev, struct device *dev);
+extern int extcon_dev_register(struct extcon_dev *edev);
 extern void extcon_dev_unregister(struct extcon_dev *edev);
 extern struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name);
 
@@ -238,8 +241,7 @@
 extern int extcon_unregister_notifier(struct extcon_dev *edev,
 				      struct notifier_block *nb);
 #else /* CONFIG_EXTCON */
-static inline int extcon_dev_register(struct extcon_dev *edev,
-				      struct device *dev)
+static inline int extcon_dev_register(struct extcon_dev *edev)
 {
 	return 0;
 }
diff --git a/include/linux/extcon/extcon-adc-jack.h b/include/linux/extcon/extcon-adc-jack.h
index 20e9eef..9ca958c 100644
--- a/include/linux/extcon/extcon-adc-jack.h
+++ b/include/linux/extcon/extcon-adc-jack.h
@@ -20,10 +20,10 @@
 
 /**
  * struct adc_jack_cond - condition to use an extcon state
- * @state      - the corresponding extcon state (if 0, this struct denotes
- *             the last adc_jack_cond element among the array)
- * @min_adc    - min adc value for this condition
- * @max_adc    - max adc value for this condition
+ * @state:		the corresponding extcon state (if 0, this struct
+ *			denotes the last adc_jack_cond element among the array)
+ * @min_adc:		min adc value for this condition
+ * @max_adc:		max adc value for this condition
  *
  * For example, if { .state = 0x3, .min_adc = 100, .max_adc = 200}, it means
  * that if ADC value is between (inclusive) 100 and 200, than the cable 0 and
@@ -33,34 +33,34 @@
  * because when no adc_jack_cond is met, state = 0 is automatically chosen.
  */
 struct adc_jack_cond {
-	u32 state; /* extcon state value. 0 if invalid */
+	u32 state;	/* extcon state value. 0 if invalid */
 	u32 min_adc;
 	u32 max_adc;
 };
 
 /**
  * struct adc_jack_pdata - platform data for adc jack device.
- * @name       - name of the extcon device. If null, "adc-jack" is used.
- * @consumer_channel - Unique name to identify the channel on the consumer
- *                   side. This typically describes the channels used within
- *                   the consumer. E.g. 'battery_voltage'
- * @cable_names        - array of cable names ending with null.
- * @adc_contitions     - array of struct adc_jack_cond conditions ending
- *                     with .state = 0 entry. This describes how to decode
- *                     adc values into extcon state.
- * @irq_flags  - irq flags used for the @irq
- * @handling_delay_ms  - in some devices, we need to read ADC value some
- *                     milli-seconds after the interrupt occurs. You may
- *                     describe such delays with @handling_delay_ms, which
- *                     is rounded-off by jiffies.
+ * @name:		name of the extcon device. If null, "adc-jack" is used.
+ * @consumer_channel:	Unique name to identify the channel on the consumer
+ *			side. This typically describes the channels used within
+ *			the consumer. E.g. 'battery_voltage'
+ * @cable_names:	array of cable names ending with null.
+ * @adc_contitions:	array of struct adc_jack_cond conditions ending
+ *			with .state = 0 entry. This describes how to decode
+ *			adc values into extcon state.
+ * @irq_flags:		irq flags used for the @irq
+ * @handling_delay_ms:	in some devices, we need to read ADC value some
+ *			milli-seconds after the interrupt occurs. You may
+ *			describe such delays with @handling_delay_ms, which
+ *			is rounded-off by jiffies.
  */
 struct adc_jack_pdata {
 	const char *name;
 	const char *consumer_channel;
-	/*
-	 * The last entry should be NULL
-	 */
+
+	/* The last entry should be NULL */
 	const char **cable_names;
+
 	/* The last entry's state should be 0 */
 	struct adc_jack_cond *adc_conditions;
 
diff --git a/include/linux/extcon/extcon-gpio.h b/include/linux/extcon/extcon-gpio.h
index 2d8307f..4195810 100644
--- a/include/linux/extcon/extcon-gpio.h
+++ b/include/linux/extcon/extcon-gpio.h
@@ -25,14 +25,17 @@
 
 /**
  * struct gpio_extcon_platform_data - A simple GPIO-controlled extcon device.
- * @name	The name of this GPIO extcon device.
- * @gpio	Corresponding GPIO.
- * @debounce	Debounce time for GPIO IRQ in ms.
- * @irq_flags	IRQ Flags (e.g., IRQF_TRIGGER_LOW).
- * @state_on	print_state is overriden with state_on if attached. If Null,
- *		default method of extcon class is used.
- * @state_off	print_state is overriden with state_on if detached. If Null,
- *		default method of extcon class is used.
+ * @name:		The name of this GPIO extcon device.
+ * @gpio:		Corresponding GPIO.
+ * @gpio_active_low:	Boolean describing whether gpio active state is 1 or 0
+ *			If true, low state of gpio means active.
+ *			If false, high state of gpio means active.
+ * @debounce:		Debounce time for GPIO IRQ in ms.
+ * @irq_flags:		IRQ Flags (e.g., IRQF_TRIGGER_LOW).
+ * @state_on:		print_state is overriden with state_on if attached.
+ *			If NULL, default method of extcon class is used.
+ * @state_off:		print_state is overriden with state_on if detached.
+ *			If NUll, default method of extcon class is used.
  *
  * Note that in order for state_on or state_off to be valid, both state_on
  * and state_off should be not NULL. If at least one of them is NULL,
@@ -41,6 +44,7 @@
 struct gpio_extcon_platform_data {
 	const char *name;
 	unsigned gpio;
+	bool gpio_active_low;
 	unsigned long debounce;
 	unsigned long irq_flags;
 
diff --git a/include/linux/filter.h b/include/linux/filter.h
index a6ac848..ff4e40c 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -6,6 +6,7 @@
 
 #include <linux/atomic.h>
 #include <linux/compat.h>
+#include <linux/workqueue.h>
 #include <uapi/linux/filter.h>
 
 #ifdef CONFIG_COMPAT
@@ -25,15 +26,19 @@
 {
 	atomic_t		refcnt;
 	unsigned int         	len;	/* Number of filter blocks */
+	struct rcu_head		rcu;
 	unsigned int		(*bpf_func)(const struct sk_buff *skb,
 					    const struct sock_filter *filter);
-	struct rcu_head		rcu;
-	struct sock_filter     	insns[0];
+	union {
+		struct sock_filter     	insns[0];
+		struct work_struct	work;
+	};
 };
 
-static inline unsigned int sk_filter_len(const struct sk_filter *fp)
+static inline unsigned int sk_filter_size(unsigned int proglen)
 {
-	return fp->len * sizeof(struct sock_filter) + sizeof(*fp);
+	return max(sizeof(struct sk_filter),
+		   offsetof(struct sk_filter, insns[proglen]));
 }
 
 extern int sk_filter(struct sock *sk, struct sk_buff *skb);
@@ -67,11 +72,13 @@
 }
 #define SK_RUN_FILTER(FILTER, SKB) (*FILTER->bpf_func)(SKB, FILTER->insns)
 #else
+#include <linux/slab.h>
 static inline void bpf_jit_compile(struct sk_filter *fp)
 {
 }
 static inline void bpf_jit_free(struct sk_filter *fp)
 {
+	kfree(fp);
 }
 #define SK_RUN_FILTER(FILTER, SKB) sk_run_filter(SKB, FILTER->insns)
 #endif
diff --git a/include/linux/fs.h b/include/linux/fs.h
index ab2a0ca..bf5d574 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2347,6 +2347,11 @@
 	if (file)
 		atomic_inc(&file_inode(file)->i_writecount);
 }
+static inline bool inode_is_open_for_write(const struct inode *inode)
+{
+	return atomic_read(&inode->i_writecount) > 0;
+}
+
 #ifdef CONFIG_IMA
 static inline void i_readcount_dec(struct inode *inode)
 {
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index 7823e9e..7714849 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -308,36 +308,6 @@
 	void (*dissociate_pages)(struct fscache_cache *cache);
 };
 
-/*
- * data file or index object cookie
- * - a file will only appear in one cache
- * - a request to cache a file may or may not be honoured, subject to
- *   constraints such as disk space
- * - indices are created on disk just-in-time
- */
-struct fscache_cookie {
-	atomic_t			usage;		/* number of users of this cookie */
-	atomic_t			n_children;	/* number of children of this cookie */
-	atomic_t			n_active;	/* number of active users of netfs ptrs */
-	spinlock_t			lock;
-	spinlock_t			stores_lock;	/* lock on page store tree */
-	struct hlist_head		backing_objects; /* object(s) backing this file/index */
-	const struct fscache_cookie_def	*def;		/* definition */
-	struct fscache_cookie		*parent;	/* parent of this entry */
-	void				*netfs_data;	/* back pointer to netfs */
-	struct radix_tree_root		stores;		/* pages to be stored on this cookie */
-#define FSCACHE_COOKIE_PENDING_TAG	0		/* pages tag: pending write to cache */
-#define FSCACHE_COOKIE_STORING_TAG	1		/* pages tag: writing to cache */
-
-	unsigned long			flags;
-#define FSCACHE_COOKIE_LOOKING_UP	0	/* T if non-index cookie being looked up still */
-#define FSCACHE_COOKIE_NO_DATA_YET	1	/* T if new object with no cached data yet */
-#define FSCACHE_COOKIE_UNAVAILABLE	2	/* T if cookie is unavailable (error, etc) */
-#define FSCACHE_COOKIE_INVALIDATING	3	/* T if cookie is being invalidated */
-#define FSCACHE_COOKIE_RELINQUISHED	4	/* T if cookie has been relinquished */
-#define FSCACHE_COOKIE_RETIRED		5	/* T if cookie was retired */
-};
-
 extern struct fscache_cookie fscache_fsdef_index;
 
 /*
@@ -400,6 +370,7 @@
 #define FSCACHE_OBJECT_IS_LIVE		3	/* T if object is not withdrawn or relinquished */
 #define FSCACHE_OBJECT_IS_LOOKED_UP	4	/* T if object has been looked up */
 #define FSCACHE_OBJECT_IS_AVAILABLE	5	/* T if object has become active */
+#define FSCACHE_OBJECT_RETIRED		6	/* T if object was retired on relinquishment */
 
 	struct list_head	cache_link;	/* link in cache->object_list */
 	struct hlist_node	cookie_link;	/* link in cookie->backing_objects */
@@ -511,6 +482,11 @@
 	op->end_io_func(page, op->context, error);
 }
 
+static inline void __fscache_use_cookie(struct fscache_cookie *cookie)
+{
+	atomic_inc(&cookie->n_active);
+}
+
 /**
  * fscache_use_cookie - Request usage of cookie attached to an object
  * @object: Object description
@@ -524,6 +500,16 @@
 	return atomic_inc_not_zero(&cookie->n_active) != 0;
 }
 
+static inline bool __fscache_unuse_cookie(struct fscache_cookie *cookie)
+{
+	return atomic_dec_and_test(&cookie->n_active);
+}
+
+static inline void __fscache_wake_unused_cookie(struct fscache_cookie *cookie)
+{
+	wake_up_atomic_t(&cookie->n_active);
+}
+
 /**
  * fscache_unuse_cookie - Cease usage of cookie attached to an object
  * @object: Object description
@@ -534,8 +520,8 @@
 static inline void fscache_unuse_cookie(struct fscache_object *object)
 {
 	struct fscache_cookie *cookie = object->cookie;
-	if (atomic_dec_and_test(&cookie->n_active))
-		wake_up_atomic_t(&cookie->n_active);
+	if (__fscache_unuse_cookie(cookie))
+		__fscache_wake_unused_cookie(cookie);
 }
 
 /*
diff --git a/include/linux/fscache.h b/include/linux/fscache.h
index 19b4645..115bb81 100644
--- a/include/linux/fscache.h
+++ b/include/linux/fscache.h
@@ -167,6 +167,42 @@
 };
 
 /*
+ * data file or index object cookie
+ * - a file will only appear in one cache
+ * - a request to cache a file may or may not be honoured, subject to
+ *   constraints such as disk space
+ * - indices are created on disk just-in-time
+ */
+struct fscache_cookie {
+	atomic_t			usage;		/* number of users of this cookie */
+	atomic_t			n_children;	/* number of children of this cookie */
+	atomic_t			n_active;	/* number of active users of netfs ptrs */
+	spinlock_t			lock;
+	spinlock_t			stores_lock;	/* lock on page store tree */
+	struct hlist_head		backing_objects; /* object(s) backing this file/index */
+	const struct fscache_cookie_def	*def;		/* definition */
+	struct fscache_cookie		*parent;	/* parent of this entry */
+	void				*netfs_data;	/* back pointer to netfs */
+	struct radix_tree_root		stores;		/* pages to be stored on this cookie */
+#define FSCACHE_COOKIE_PENDING_TAG	0		/* pages tag: pending write to cache */
+#define FSCACHE_COOKIE_STORING_TAG	1		/* pages tag: writing to cache */
+
+	unsigned long			flags;
+#define FSCACHE_COOKIE_LOOKING_UP	0	/* T if non-index cookie being looked up still */
+#define FSCACHE_COOKIE_NO_DATA_YET	1	/* T if new object with no cached data yet */
+#define FSCACHE_COOKIE_UNAVAILABLE	2	/* T if cookie is unavailable (error, etc) */
+#define FSCACHE_COOKIE_INVALIDATING	3	/* T if cookie is being invalidated */
+#define FSCACHE_COOKIE_RELINQUISHED	4	/* T if cookie has been relinquished */
+#define FSCACHE_COOKIE_ENABLED		5	/* T if cookie is enabled */
+#define FSCACHE_COOKIE_ENABLEMENT_LOCK	6	/* T if cookie is being en/disabled */
+};
+
+static inline bool fscache_cookie_enabled(struct fscache_cookie *cookie)
+{
+	return test_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags);
+}
+
+/*
  * slow-path functions for when there is actually caching available, and the
  * netfs does actually have a valid token
  * - these are not to be called directly
@@ -181,8 +217,8 @@
 extern struct fscache_cookie *__fscache_acquire_cookie(
 	struct fscache_cookie *,
 	const struct fscache_cookie_def *,
-	void *);
-extern void __fscache_relinquish_cookie(struct fscache_cookie *, int);
+	void *, bool);
+extern void __fscache_relinquish_cookie(struct fscache_cookie *, bool);
 extern int __fscache_check_consistency(struct fscache_cookie *);
 extern void __fscache_update_cookie(struct fscache_cookie *);
 extern int __fscache_attr_changed(struct fscache_cookie *);
@@ -211,6 +247,9 @@
 					      struct inode *);
 extern void __fscache_readpages_cancel(struct fscache_cookie *cookie,
 				       struct list_head *pages);
+extern void __fscache_disable_cookie(struct fscache_cookie *, bool);
+extern void __fscache_enable_cookie(struct fscache_cookie *,
+				    bool (*)(void *), void *);
 
 /**
  * fscache_register_netfs - Register a filesystem as desiring caching services
@@ -289,6 +328,7 @@
  * @def: A description of the cache object, including callback operations
  * @netfs_data: An arbitrary piece of data to be kept in the cookie to
  * represent the cache object to the netfs
+ * @enable: Whether or not to enable a data cookie immediately
  *
  * This function is used to inform FS-Cache about part of an index hierarchy
  * that can be used to locate files.  This is done by requesting a cookie for
@@ -301,10 +341,12 @@
 struct fscache_cookie *fscache_acquire_cookie(
 	struct fscache_cookie *parent,
 	const struct fscache_cookie_def *def,
-	void *netfs_data)
+	void *netfs_data,
+	bool enable)
 {
-	if (fscache_cookie_valid(parent))
-		return __fscache_acquire_cookie(parent, def, netfs_data);
+	if (fscache_cookie_valid(parent) && fscache_cookie_enabled(parent))
+		return __fscache_acquire_cookie(parent, def, netfs_data,
+						enable);
 	else
 		return NULL;
 }
@@ -322,7 +364,7 @@
  * description.
  */
 static inline
-void fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
+void fscache_relinquish_cookie(struct fscache_cookie *cookie, bool retire)
 {
 	if (fscache_cookie_valid(cookie))
 		__fscache_relinquish_cookie(cookie, retire);
@@ -341,7 +383,7 @@
 static inline
 int fscache_check_consistency(struct fscache_cookie *cookie)
 {
-	if (fscache_cookie_valid(cookie))
+	if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
 		return __fscache_check_consistency(cookie);
 	else
 		return 0;
@@ -360,7 +402,7 @@
 static inline
 void fscache_update_cookie(struct fscache_cookie *cookie)
 {
-	if (fscache_cookie_valid(cookie))
+	if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
 		__fscache_update_cookie(cookie);
 }
 
@@ -407,7 +449,7 @@
 static inline
 int fscache_attr_changed(struct fscache_cookie *cookie)
 {
-	if (fscache_cookie_valid(cookie))
+	if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
 		return __fscache_attr_changed(cookie);
 	else
 		return -ENOBUFS;
@@ -429,7 +471,7 @@
 static inline
 void fscache_invalidate(struct fscache_cookie *cookie)
 {
-	if (fscache_cookie_valid(cookie))
+	if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
 		__fscache_invalidate(cookie);
 }
 
@@ -503,7 +545,7 @@
 			       void *context,
 			       gfp_t gfp)
 {
-	if (fscache_cookie_valid(cookie))
+	if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
 		return __fscache_read_or_alloc_page(cookie, page, end_io_func,
 						    context, gfp);
 	else
@@ -554,7 +596,7 @@
 				void *context,
 				gfp_t gfp)
 {
-	if (fscache_cookie_valid(cookie))
+	if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
 		return __fscache_read_or_alloc_pages(cookie, mapping, pages,
 						     nr_pages, end_io_func,
 						     context, gfp);
@@ -585,7 +627,7 @@
 		       struct page *page,
 		       gfp_t gfp)
 {
-	if (fscache_cookie_valid(cookie))
+	if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
 		return __fscache_alloc_page(cookie, page, gfp);
 	else
 		return -ENOBUFS;
@@ -634,7 +676,7 @@
 		       struct page *page,
 		       gfp_t gfp)
 {
-	if (fscache_cookie_valid(cookie))
+	if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
 		return __fscache_write_page(cookie, page, gfp);
 	else
 		return -ENOBUFS;
@@ -744,4 +786,47 @@
 		__fscache_uncache_all_inode_pages(cookie, inode);
 }
 
+/**
+ * fscache_disable_cookie - Disable a cookie
+ * @cookie: The cookie representing the cache object
+ * @invalidate: Invalidate the backing object
+ *
+ * Disable a cookie from accepting further alloc, read, write, invalidate,
+ * update or acquire operations.  Outstanding operations can still be waited
+ * upon and pages can still be uncached and the cookie relinquished.
+ *
+ * This will not return until all outstanding operations have completed.
+ *
+ * If @invalidate is set, then the backing object will be invalidated and
+ * detached, otherwise it will just be detached.
+ */
+static inline
+void fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
+{
+	if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
+		__fscache_disable_cookie(cookie, invalidate);
+}
+
+/**
+ * fscache_enable_cookie - Reenable a cookie
+ * @cookie: The cookie representing the cache object
+ * @can_enable: A function to permit enablement once lock is held
+ * @data: Data for can_enable()
+ *
+ * Reenable a previously disabled cookie, allowing it to accept further alloc,
+ * read, write, invalidate, update or acquire operations.  An attempt will be
+ * made to immediately reattach the cookie to a backing object.
+ *
+ * The can_enable() function is called (if not NULL) once the enablement lock
+ * is held to rule on whether enablement is still permitted to go ahead.
+ */
+static inline
+void fscache_enable_cookie(struct fscache_cookie *cookie,
+			   bool (*can_enable)(void *data),
+			   void *data)
+{
+	if (fscache_cookie_valid(cookie) && !fscache_cookie_enabled(cookie))
+		__fscache_enable_cookie(cookie, can_enable, data);
+}
+
 #endif /* _LINUX_FSCACHE_H */
diff --git a/include/linux/gpio.h b/include/linux/gpio.h
index 552e3f4..13dfd24 100644
--- a/include/linux/gpio.h
+++ b/include/linux/gpio.h
@@ -16,14 +16,17 @@
 #define GPIOF_OUT_INIT_LOW	(GPIOF_DIR_OUT | GPIOF_INIT_LOW)
 #define GPIOF_OUT_INIT_HIGH	(GPIOF_DIR_OUT | GPIOF_INIT_HIGH)
 
+/* Gpio pin is active-low */
+#define GPIOF_ACTIVE_LOW        (1 << 2)
+
 /* Gpio pin is open drain */
-#define GPIOF_OPEN_DRAIN	(1 << 2)
+#define GPIOF_OPEN_DRAIN	(1 << 3)
 
 /* Gpio pin is open source */
-#define GPIOF_OPEN_SOURCE	(1 << 3)
+#define GPIOF_OPEN_SOURCE	(1 << 4)
 
-#define GPIOF_EXPORT		(1 << 4)
-#define GPIOF_EXPORT_CHANGEABLE	(1 << 5)
+#define GPIOF_EXPORT		(1 << 5)
+#define GPIOF_EXPORT_CHANGEABLE	(1 << 6)
 #define GPIOF_EXPORT_DIR_FIXED	(GPIOF_EXPORT)
 #define GPIOF_EXPORT_DIR_CHANGEABLE (GPIOF_EXPORT | GPIOF_EXPORT_CHANGEABLE)
 
@@ -74,12 +77,22 @@
 
 #endif /* ! CONFIG_ARCH_HAVE_CUSTOM_GPIO_H */
 
+/* CONFIG_GPIOLIB: bindings for managed devices that want to request gpios */
+
+struct device;
+
+int devm_gpio_request(struct device *dev, unsigned gpio, const char *label);
+int devm_gpio_request_one(struct device *dev, unsigned gpio,
+			  unsigned long flags, const char *label);
+void devm_gpio_free(struct device *dev, unsigned int gpio);
+
 #else /* ! CONFIG_GPIOLIB */
 
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/bug.h>
+#include <linux/pinctrl/pinctrl.h>
 
 struct device;
 struct gpio_chip;
@@ -204,6 +217,18 @@
 	return -EINVAL;
 }
 
+static inline int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
+{
+	WARN_ON(1);
+	return -EINVAL;
+}
+
+static inline void gpio_unlock_as_irq(struct gpio_chip *chip,
+				      unsigned int offset)
+{
+	WARN_ON(1);
+}
+
 static inline int irq_to_gpio(unsigned irq)
 {
 	/* irq can never have been returned from gpio_to_irq() */
@@ -220,20 +245,40 @@
 	return -EINVAL;
 }
 
+static inline int
+gpiochip_add_pingroup_range(struct gpio_chip *chip,
+			struct pinctrl_dev *pctldev,
+			unsigned int gpio_offset, const char *pin_group)
+{
+	WARN_ON(1);
+	return -EINVAL;
+}
+
 static inline void
 gpiochip_remove_pin_ranges(struct gpio_chip *chip)
 {
 	WARN_ON(1);
 }
 
+static inline int devm_gpio_request(struct device *dev, unsigned gpio,
+				    const char *label)
+{
+	WARN_ON(1);
+	return -EINVAL;
+}
+
+static inline int devm_gpio_request_one(struct device *dev, unsigned gpio,
+					unsigned long flags, const char *label)
+{
+	WARN_ON(1);
+	return -EINVAL;
+}
+
+static inline void devm_gpio_free(struct device *dev, unsigned int gpio)
+{
+	WARN_ON(1);
+}
+
 #endif /* ! CONFIG_GPIOLIB */
 
-struct device;
-
-/* bindings for managed devices that want to request gpios */
-int devm_gpio_request(struct device *dev, unsigned gpio, const char *label);
-int devm_gpio_request_one(struct device *dev, unsigned gpio,
-			  unsigned long flags, const char *label);
-void devm_gpio_free(struct device *dev, unsigned int gpio);
-
 #endif /* __LINUX_GPIO_H */
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
new file mode 100644
index 0000000..4d34dbb
--- /dev/null
+++ b/include/linux/gpio/consumer.h
@@ -0,0 +1,253 @@
+#ifndef __LINUX_GPIO_CONSUMER_H
+#define __LINUX_GPIO_CONSUMER_H
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+
+#ifdef CONFIG_GPIOLIB
+
+struct device;
+struct gpio_chip;
+
+/**
+ * Opaque descriptor for a GPIO. These are obtained using gpiod_get() and are
+ * preferable to the old integer-based handles.
+ *
+ * Contrary to integers, a pointer to a gpio_desc is guaranteed to be valid
+ * until the GPIO is released.
+ */
+struct gpio_desc;
+
+/* Acquire and dispose GPIOs */
+struct gpio_desc *__must_check gpiod_get(struct device *dev,
+					 const char *con_id);
+struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
+					       const char *con_id,
+					       unsigned int idx);
+void gpiod_put(struct gpio_desc *desc);
+
+struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
+					      const char *con_id);
+struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
+						    const char *con_id,
+						    unsigned int idx);
+void devm_gpiod_put(struct device *dev, struct gpio_desc *desc);
+
+int gpiod_get_direction(const struct gpio_desc *desc);
+int gpiod_direction_input(struct gpio_desc *desc);
+int gpiod_direction_output(struct gpio_desc *desc, int value);
+
+/* Value get/set from non-sleeping context */
+int gpiod_get_value(const struct gpio_desc *desc);
+void gpiod_set_value(struct gpio_desc *desc, int value);
+int gpiod_get_raw_value(const struct gpio_desc *desc);
+void gpiod_set_raw_value(struct gpio_desc *desc, int value);
+
+/* Value get/set from sleeping context */
+int gpiod_get_value_cansleep(const struct gpio_desc *desc);
+void gpiod_set_value_cansleep(struct gpio_desc *desc, int value);
+int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc);
+void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value);
+
+int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce);
+
+int gpiod_is_active_low(const struct gpio_desc *desc);
+int gpiod_cansleep(const struct gpio_desc *desc);
+
+int gpiod_to_irq(const struct gpio_desc *desc);
+
+/* Convert between the old gpio_ and new gpiod_ interfaces */
+struct gpio_desc *gpio_to_desc(unsigned gpio);
+int desc_to_gpio(const struct gpio_desc *desc);
+struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc);
+
+#else /* CONFIG_GPIOLIB */
+
+static inline struct gpio_desc *__must_check gpiod_get(struct device *dev,
+						       const char *con_id)
+{
+	return ERR_PTR(-ENOSYS);
+}
+static inline struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
+							     const char *con_id,
+							     unsigned int idx)
+{
+	return ERR_PTR(-ENOSYS);
+}
+static inline void gpiod_put(struct gpio_desc *desc)
+{
+	might_sleep();
+
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+}
+
+static inline struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
+							    const char *con_id)
+{
+	return ERR_PTR(-ENOSYS);
+}
+static inline
+struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
+						    const char *con_id,
+						    unsigned int idx)
+{
+	return ERR_PTR(-ENOSYS);
+}
+static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
+{
+	might_sleep();
+
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+}
+
+
+static inline int gpiod_get_direction(const struct gpio_desc *desc)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+	return -ENOSYS;
+}
+static inline int gpiod_direction_input(struct gpio_desc *desc)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+	return -ENOSYS;
+}
+static inline int gpiod_direction_output(struct gpio_desc *desc, int value)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+	return -ENOSYS;
+}
+
+
+static inline int gpiod_get_value(const struct gpio_desc *desc)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+	return 0;
+}
+static inline void gpiod_set_value(struct gpio_desc *desc, int value)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+}
+static inline int gpiod_get_raw_value(const struct gpio_desc *desc)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+	return 0;
+}
+static inline void gpiod_set_raw_value(struct gpio_desc *desc, int value)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+}
+
+static inline int gpiod_get_value_cansleep(const struct gpio_desc *desc)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+	return 0;
+}
+static inline void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+}
+static inline int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+	return 0;
+}
+static inline void gpiod_set_raw_value_cansleep(struct gpio_desc *desc,
+						int value)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+}
+
+static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+	return -ENOSYS;
+}
+
+static inline int gpiod_is_active_low(const struct gpio_desc *desc)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+	return 0;
+}
+static inline int gpiod_cansleep(const struct gpio_desc *desc)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+	return 0;
+}
+
+static inline int gpiod_to_irq(const struct gpio_desc *desc)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+	return -EINVAL;
+}
+
+static inline struct gpio_desc *gpio_to_desc(unsigned gpio)
+{
+	return ERR_PTR(-EINVAL);
+}
+static inline int desc_to_gpio(const struct gpio_desc *desc)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+	return -EINVAL;
+}
+static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+	return ERR_PTR(-ENODEV);
+}
+
+
+#endif /* CONFIG_GPIOLIB */
+
+#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS)
+
+int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
+int gpiod_export_link(struct device *dev, const char *name,
+		      struct gpio_desc *desc);
+int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value);
+void gpiod_unexport(struct gpio_desc *desc);
+
+#else  /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */
+
+static inline int gpiod_export(struct gpio_desc *desc,
+			       bool direction_may_change)
+{
+	return -ENOSYS;
+}
+
+static inline int gpiod_export_link(struct device *dev, const char *name,
+				    struct gpio_desc *desc)
+{
+	return -ENOSYS;
+}
+
+static inline int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
+{
+	return -ENOSYS;
+}
+
+static inline void gpiod_unexport(struct gpio_desc *desc)
+{
+}
+
+#endif /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */
+
+#endif
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
new file mode 100644
index 0000000..656a27e
--- /dev/null
+++ b/include/linux/gpio/driver.h
@@ -0,0 +1,184 @@
+#ifndef __LINUX_GPIO_DRIVER_H
+#define __LINUX_GPIO_DRIVER_H
+
+#include <linux/types.h>
+
+struct device;
+struct gpio_desc;
+struct seq_file;
+
+/**
+ * struct gpio_chip - abstract a GPIO controller
+ * @label: for diagnostics
+ * @dev: optional device providing the GPIOs
+ * @owner: helps prevent removal of modules exporting active GPIOs
+ * @list: links gpio_chips together for traversal
+ * @request: optional hook for chip-specific activation, such as
+ *	enabling module power and clock; may sleep
+ * @free: optional hook for chip-specific deactivation, such as
+ *	disabling module power and clock; may sleep
+ * @get_direction: returns direction for signal "offset", 0=out, 1=in,
+ *	(same as GPIOF_DIR_XXX), or negative error
+ * @direction_input: configures signal "offset" as input, or returns error
+ * @direction_output: configures signal "offset" as output, or returns error
+ * @get: returns value for signal "offset"; for output signals this
+ *	returns either the value actually sensed, or zero
+ * @set: assigns output value for signal "offset"
+ * @set_debounce: optional hook for setting debounce time for specified gpio in
+ *      interrupt triggered gpio chips
+ * @to_irq: optional hook supporting non-static gpio_to_irq() mappings;
+ *	implementation may not sleep
+ * @dbg_show: optional routine to show contents in debugfs; default code
+ *	will be used when this is omitted, but custom code can show extra
+ *	state (such as pullup/pulldown configuration).
+ * @base: identifies the first GPIO number handled by this chip; or, if
+ *	negative during registration, requests dynamic ID allocation.
+ * @ngpio: the number of GPIOs handled by this controller; the last GPIO
+ *	handled is (base + ngpio - 1).
+ * @desc: array of ngpio descriptors. Private.
+ * @can_sleep: flag must be set iff get()/set() methods sleep, as they
+ *	must while accessing GPIO expander chips over I2C or SPI
+ * @names: if set, must be an array of strings to use as alternative
+ *      names for the GPIOs in this chip. Any entry in the array
+ *      may be NULL if there is no alias for the GPIO, however the
+ *      array must be @ngpio entries long.  A name can include a single printk
+ *      format specifier for an unsigned int.  It is substituted by the actual
+ *      number of the gpio.
+ *
+ * A gpio_chip can help platforms abstract various sources of GPIOs so
+ * they can all be accessed through a common programing interface.
+ * Example sources would be SOC controllers, FPGAs, multifunction
+ * chips, dedicated GPIO expanders, and so on.
+ *
+ * Each chip controls a number of signals, identified in method calls
+ * by "offset" values in the range 0..(@ngpio - 1).  When those signals
+ * are referenced through calls like gpio_get_value(gpio), the offset
+ * is calculated by subtracting @base from the gpio number.
+ */
+struct gpio_chip {
+	const char		*label;
+	struct device		*dev;
+	struct module		*owner;
+	struct list_head        list;
+
+	int			(*request)(struct gpio_chip *chip,
+						unsigned offset);
+	void			(*free)(struct gpio_chip *chip,
+						unsigned offset);
+	int			(*get_direction)(struct gpio_chip *chip,
+						unsigned offset);
+	int			(*direction_input)(struct gpio_chip *chip,
+						unsigned offset);
+	int			(*direction_output)(struct gpio_chip *chip,
+						unsigned offset, int value);
+	int			(*get)(struct gpio_chip *chip,
+						unsigned offset);
+	void			(*set)(struct gpio_chip *chip,
+						unsigned offset, int value);
+	int			(*set_debounce)(struct gpio_chip *chip,
+						unsigned offset,
+						unsigned debounce);
+
+	int			(*to_irq)(struct gpio_chip *chip,
+						unsigned offset);
+
+	void			(*dbg_show)(struct seq_file *s,
+						struct gpio_chip *chip);
+	int			base;
+	u16			ngpio;
+	struct gpio_desc	*desc;
+	const char		*const *names;
+	unsigned		can_sleep:1;
+	unsigned		exported:1;
+
+#if defined(CONFIG_OF_GPIO)
+	/*
+	 * If CONFIG_OF is enabled, then all GPIO controllers described in the
+	 * device tree automatically may have an OF translation
+	 */
+	struct device_node *of_node;
+	int of_gpio_n_cells;
+	int (*of_xlate)(struct gpio_chip *gc,
+			const struct of_phandle_args *gpiospec, u32 *flags);
+#endif
+#ifdef CONFIG_PINCTRL
+	/*
+	 * If CONFIG_PINCTRL is enabled, then gpio controllers can optionally
+	 * describe the actual pin range which they serve in an SoC. This
+	 * information would be used by pinctrl subsystem to configure
+	 * corresponding pins for gpio usage.
+	 */
+	struct list_head pin_ranges;
+#endif
+};
+
+extern const char *gpiochip_is_requested(struct gpio_chip *chip,
+			unsigned offset);
+
+/* add/remove chips */
+extern int gpiochip_add(struct gpio_chip *chip);
+extern int __must_check gpiochip_remove(struct gpio_chip *chip);
+extern struct gpio_chip *gpiochip_find(void *data,
+			      int (*match)(struct gpio_chip *chip, void *data));
+
+/* lock/unlock as IRQ */
+int gpiod_lock_as_irq(struct gpio_desc *desc);
+void gpiod_unlock_as_irq(struct gpio_desc *desc);
+
+/**
+ * Lookup table for associating GPIOs to specific devices and functions using
+ * platform data.
+ */
+struct gpiod_lookup {
+	struct list_head list;
+	/*
+	 * name of the chip the GPIO belongs to
+	 */
+	const char *chip_label;
+	/*
+	 * hardware number (i.e. relative to the chip) of the GPIO
+	 */
+	u16 chip_hwnum;
+	/*
+	 * name of device that can claim this GPIO
+	 */
+	const char *dev_id;
+	/*
+	 * name of the GPIO from the device's point of view
+	 */
+	const char *con_id;
+	/*
+	 * index of the GPIO in case several GPIOs share the same name
+	 */
+	unsigned int idx;
+	/*
+	 * mask of GPIOF_* values
+	 */
+	unsigned long flags;
+};
+
+/*
+ * Simple definition of a single GPIO under a con_id
+ */
+#define GPIO_LOOKUP(_chip_label, _chip_hwnum, _dev_id, _con_id, _flags) \
+	GPIO_LOOKUP_IDX(_chip_label, _chip_hwnum, _dev_id, _con_id, 0, _flags)
+
+/*
+ * Use this macro if you need to have several GPIOs under the same con_id.
+ * Each GPIO needs to use a different index and can be accessed using
+ * gpiod_get_index()
+ */
+#define GPIO_LOOKUP_IDX(_chip_label, _chip_hwnum, _dev_id, _con_id, _idx, \
+			_flags)                                           \
+{                                                                         \
+	.chip_label = _chip_label,                                        \
+	.chip_hwnum = _chip_hwnum,                                        \
+	.dev_id = _dev_id,                                                \
+	.con_id = _con_id,                                                \
+	.idx = _idx,                                                      \
+	.flags = _flags,                                                  \
+}
+
+void gpiod_add_table(struct gpiod_lookup *table, size_t size);
+
+#endif
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index 1e04106..d9cf963 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -33,7 +33,7 @@
 #define __irq_enter()					\
 	do {						\
 		account_irq_enter_time(current);	\
-		add_preempt_count(HARDIRQ_OFFSET);	\
+		preempt_count_add(HARDIRQ_OFFSET);	\
 		trace_hardirq_enter();			\
 	} while (0)
 
@@ -49,7 +49,7 @@
 	do {						\
 		trace_hardirq_exit();			\
 		account_irq_exit_time(current);		\
-		sub_preempt_count(HARDIRQ_OFFSET);	\
+		preempt_count_sub(HARDIRQ_OFFSET);	\
 	} while (0)
 
 /*
@@ -62,7 +62,7 @@
 		lockdep_off();					\
 		ftrace_nmi_enter();				\
 		BUG_ON(in_nmi());				\
-		add_preempt_count(NMI_OFFSET + HARDIRQ_OFFSET);	\
+		preempt_count_add(NMI_OFFSET + HARDIRQ_OFFSET);	\
 		rcu_nmi_enter();				\
 		trace_hardirq_enter();				\
 	} while (0)
@@ -72,7 +72,7 @@
 		trace_hardirq_exit();				\
 		rcu_nmi_exit();					\
 		BUG_ON(!in_nmi());				\
-		sub_preempt_count(NMI_OFFSET + HARDIRQ_OFFSET);	\
+		preempt_count_sub(NMI_OFFSET + HARDIRQ_OFFSET);	\
 		ftrace_nmi_exit();				\
 		lockdep_on();					\
 	} while (0)
diff --git a/include/linux/hashtable.h b/include/linux/hashtable.h
index a9df51f..519b6e2 100644
--- a/include/linux/hashtable.h
+++ b/include/linux/hashtable.h
@@ -174,6 +174,21 @@
 		member)
 
 /**
+ * hash_for_each_possible_rcu_notrace - iterate over all possible objects hashing
+ * to the same bucket in an rcu enabled hashtable in a rcu enabled hashtable
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ *
+ * This is the same as hash_for_each_possible_rcu() except that it does
+ * not do any RCU debugging or tracing.
+ */
+#define hash_for_each_possible_rcu_notrace(name, obj, member, key) \
+	hlist_for_each_entry_rcu_notrace(obj, \
+		&name[hash_min(key, HASH_BITS(name))], member)
+
+/**
  * hash_for_each_possible_safe - iterate over all possible objects hashing to the
  * same bucket safe against removals
  * @name: hashtable to iterate
diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-sensor-hub.h
index 32ba451..a265af2 100644
--- a/include/linux/hid-sensor-hub.h
+++ b/include/linux/hid-sensor-hub.h
@@ -47,11 +47,13 @@
  * @hdev:		Stores the hid instance.
  * @vendor_id:		Vendor id of hub device.
  * @product_id:		Product id of hub device.
+ * @ref_cnt:		Number of MFD clients have opened this device
  */
 struct hid_sensor_hub_device {
 	struct hid_device *hdev;
 	u32 vendor_id;
 	u32 product_id;
+	int ref_cnt;
 };
 
 /**
@@ -74,6 +76,22 @@
 			 void *priv);
 };
 
+/**
+* sensor_hub_device_open() - Open hub device
+* @hsdev:	Hub device instance.
+*
+* Used to open hid device for sensor hub.
+*/
+int sensor_hub_device_open(struct hid_sensor_hub_device *hsdev);
+
+/**
+* sensor_hub_device_clode() - Close hub device
+* @hsdev:	Hub device instance.
+*
+* Used to clode hid device for sensor hub.
+*/
+void sensor_hub_device_close(struct hid_sensor_hub_device *hsdev);
+
 /* Registration functions */
 
 /**
diff --git a/include/linux/hwmon-vid.h b/include/linux/hwmon-vid.h
index f346e4d..da0a680 100644
--- a/include/linux/hwmon-vid.h
+++ b/include/linux/hwmon-vid.h
@@ -38,7 +38,7 @@
 		return ((val >= 1100) && (val <= 1850) ?
 			((18499 - val * 10) / 25 + 5) / 10 : -1);
 	default:
-		return -1;
+		return -EINVAL;
 	}
 }
 
diff --git a/include/linux/hwmon.h b/include/linux/hwmon.h
index b2514f7..09354f6 100644
--- a/include/linux/hwmon.h
+++ b/include/linux/hwmon.h
@@ -15,9 +15,19 @@
 #define _HWMON_H_
 
 struct device;
+struct attribute_group;
 
 struct device *hwmon_device_register(struct device *dev);
+struct device *
+hwmon_device_register_with_groups(struct device *dev, const char *name,
+				  void *drvdata,
+				  const struct attribute_group **groups);
+struct device *
+devm_hwmon_device_register_with_groups(struct device *dev, const char *name,
+				       void *drvdata,
+				       const struct attribute_group **groups);
 
 void hwmon_device_unregister(struct device *dev);
+void devm_hwmon_device_unregister(struct device *dev);
 
 #endif
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index d98503b..15da677 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -432,15 +432,6 @@
 	u32 ring_data_startoffset;
 };
 
-struct hv_ring_buffer_debug_info {
-	u32 current_interrupt_mask;
-	u32 current_read_index;
-	u32 current_write_index;
-	u32 bytes_avail_toread;
-	u32 bytes_avail_towrite;
-};
-
-
 /*
  *
  * hv_get_ringbuffer_availbytes()
@@ -902,23 +893,6 @@
 	CHANNEL_OPENED_STATE,
 };
 
-struct vmbus_channel_debug_info {
-	u32 relid;
-	enum vmbus_channel_state state;
-	uuid_le interfacetype;
-	uuid_le interface_instance;
-	u32 monitorid;
-	u32 servermonitor_pending;
-	u32 servermonitor_latency;
-	u32 servermonitor_connectionid;
-	u32 clientmonitor_pending;
-	u32 clientmonitor_latency;
-	u32 clientmonitor_connectionid;
-
-	struct hv_ring_buffer_debug_info inbound;
-	struct hv_ring_buffer_debug_info outbound;
-};
-
 /*
  * Represents each channel msg on the vmbus connection This is a
  * variable-size data structure depending on the msg type itself
@@ -1184,19 +1158,8 @@
 				     u64 *requestid);
 
 
-extern void vmbus_get_debug_info(struct vmbus_channel *channel,
-				     struct vmbus_channel_debug_info *debug);
-
 extern void vmbus_ontimer(unsigned long data);
 
-struct hv_dev_port_info {
-	u32 int_mask;
-	u32 read_idx;
-	u32 write_idx;
-	u32 bytes_avail_toread;
-	u32 bytes_avail_towrite;
-};
-
 /* Base driver object */
 struct hv_driver {
 	const char *name;
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index 81cbbdb..673a3ce 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -26,6 +26,7 @@
 #define __TWL_H_
 
 #include <linux/types.h>
+#include <linux/phy/phy.h>
 #include <linux/input/matrix_keypad.h>
 
 /*
@@ -615,6 +616,7 @@
 struct twl4030_usb_data {
 	enum twl4030_usb_mode	usb_mode;
 	unsigned long		features;
+	struct phy_init_data	*init_data;
 
 	int		(*phy_init)(struct device *dev);
 	int		(*phy_exit)(struct device *dev);
diff --git a/include/linux/ide.h b/include/linux/ide.h
index b179749..46a1422 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1514,7 +1514,7 @@
 
 char *ide_media_string(ide_drive_t *);
 
-extern struct device_attribute ide_dev_attrs[];
+extern const struct attribute_group *ide_dev_groups[];
 extern struct bus_type ide_bus_type;
 extern struct class *ide_port_class;
 
diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h
index 2bac0eb..15607b4 100644
--- a/include/linux/iio/buffer.h
+++ b/include/linux/iio/buffer.h
@@ -11,6 +11,7 @@
 #define _IIO_BUFFER_GENERIC_H_
 #include <linux/sysfs.h>
 #include <linux/iio/iio.h>
+#include <linux/kref.h>
 
 #ifdef CONFIG_IIO_BUFFER
 
@@ -26,6 +27,8 @@
  * @set_bytes_per_datum:set number of bytes per datum
  * @get_length:		get number of datums in buffer
  * @set_length:		set number of datums in buffer
+ * @release:		called when the last reference to the buffer is dropped,
+ *			should free all resources allocated by the buffer.
  *
  * The purpose of this structure is to make the buffer element
  * modular as event for a given driver, different usecases may require
@@ -36,7 +39,7 @@
  * any of them not existing.
  **/
 struct iio_buffer_access_funcs {
-	int (*store_to)(struct iio_buffer *buffer, u8 *data);
+	int (*store_to)(struct iio_buffer *buffer, const void *data);
 	int (*read_first_n)(struct iio_buffer *buffer,
 			    size_t n,
 			    char __user *buf);
@@ -47,6 +50,8 @@
 	int (*set_bytes_per_datum)(struct iio_buffer *buffer, size_t bpd);
 	int (*get_length)(struct iio_buffer *buffer);
 	int (*set_length)(struct iio_buffer *buffer, int length);
+
+	void (*release)(struct iio_buffer *buffer);
 };
 
 /**
@@ -67,6 +72,7 @@
  * @demux_list:		[INTERN] list of operations required to demux the scan.
  * @demux_bounce:	[INTERN] buffer for doing gather from incoming scan.
  * @buffer_list:	[INTERN] entry in the devices list of current buffers.
+ * @ref:		[INTERN] reference count of the buffer.
  */
 struct iio_buffer {
 	int					length;
@@ -81,8 +87,9 @@
 	bool					stufftoread;
 	const struct attribute_group *attrs;
 	struct list_head			demux_list;
-	unsigned char				*demux_bounce;
+	void					*demux_bounce;
 	struct list_head			buffer_list;
+	struct kref				ref;
 };
 
 /**
@@ -120,7 +127,32 @@
  * @indio_dev:		iio_dev structure for device.
  * @data:		Full scan.
  */
-int iio_push_to_buffers(struct iio_dev *indio_dev, unsigned char *data);
+int iio_push_to_buffers(struct iio_dev *indio_dev, const void *data);
+
+/*
+ * iio_push_to_buffers_with_timestamp() - push data and timestamp to buffers
+ * @indio_dev:		iio_dev structure for device.
+ * @data:		sample data
+ * @timestamp:		timestamp for the sample data
+ *
+ * Pushes data to the IIO device's buffers. If timestamps are enabled for the
+ * device the function will store the supplied timestamp as the last element in
+ * the sample data buffer before pushing it to the device buffers. The sample
+ * data buffer needs to be large enough to hold the additional timestamp
+ * (usually the buffer should be indio->scan_bytes bytes large).
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+static inline int iio_push_to_buffers_with_timestamp(struct iio_dev *indio_dev,
+	void *data, int64_t timestamp)
+{
+	if (indio_dev->scan_timestamp) {
+		size_t ts_offset = indio_dev->scan_bytes / sizeof(int64_t) - 1;
+		((int64_t *)data)[ts_offset] = timestamp;
+	}
+
+	return iio_push_to_buffers(indio_dev, data);
+}
 
 int iio_update_demux(struct iio_dev *indio_dev);
 
@@ -174,11 +206,27 @@
 					   iio_buffer_show_enable,	\
 					   iio_buffer_store_enable)
 
-int iio_sw_buffer_preenable(struct iio_dev *indio_dev);
-
 bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev,
 	const unsigned long *mask);
 
+struct iio_buffer *iio_buffer_get(struct iio_buffer *buffer);
+void iio_buffer_put(struct iio_buffer *buffer);
+
+/**
+ * iio_device_attach_buffer - Attach a buffer to a IIO device
+ * @indio_dev: The device the buffer should be attached to
+ * @buffer: The buffer to attach to the device
+ *
+ * This function attaches a buffer to a IIO device. The buffer stays attached to
+ * the device until the device is freed. The function should only be called at
+ * most once per device.
+ */
+static inline void iio_device_attach_buffer(struct iio_dev *indio_dev,
+	struct iio_buffer *buffer)
+{
+	indio_dev->buffer = iio_buffer_get(buffer);
+}
+
 #else /* CONFIG_IIO_BUFFER */
 
 static inline int iio_buffer_register(struct iio_dev *indio_dev,
@@ -191,6 +239,9 @@
 static inline void iio_buffer_unregister(struct iio_dev *indio_dev)
 {}
 
+static inline void iio_buffer_get(struct iio_buffer *buffer) {}
+static inline void iio_buffer_put(struct iio_buffer *buffer) {}
+
 #endif /* CONFIG_IIO_BUFFER */
 
 #endif /* _IIO_BUFFER_GENERIC_H_ */
diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h
index e51f654..3c005eb 100644
--- a/include/linux/iio/common/st_sensors.h
+++ b/include/linux/iio/common/st_sensors.h
@@ -16,6 +16,7 @@
 #include <linux/irqreturn.h>
 #include <linux/iio/trigger.h>
 #include <linux/bitops.h>
+#include <linux/regulator/consumer.h>
 
 #include <linux/platform_data/st_sensors_pdata.h>
 
@@ -184,6 +185,7 @@
 	u8 wai;
 	char sensors_supported[ST_SENSORS_MAX_4WAI][ST_SENSORS_MAX_NAME];
 	struct iio_chan_spec *ch;
+	int num_ch;
 	struct st_sensor_odr odr;
 	struct st_sensor_power pw;
 	struct st_sensor_axis enable_axis;
@@ -200,6 +202,8 @@
  * @trig: The trigger in use by the core driver.
  * @sensor: Pointer to the current sensor struct in use.
  * @current_fullscale: Maximum range of measure by the sensor.
+ * @vdd: Pointer to sensor's Vdd power supply
+ * @vdd_io: Pointer to sensor's Vdd-IO power supply
  * @enabled: Status of the sensor (false->off, true->on).
  * @multiread_bit: Use or not particular bit for [I2C/SPI] multiread.
  * @buffer_data: Data used by buffer part.
@@ -215,6 +219,8 @@
 	struct iio_trigger *trig;
 	struct st_sensors *sensor;
 	struct st_sensor_fullscale_avl *current_fullscale;
+	struct regulator *vdd;
+	struct regulator *vdd_io;
 
 	bool enabled;
 	bool multiread_bit;
diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h
index 833926c..2752b1f 100644
--- a/include/linux/iio/consumer.h
+++ b/include/linux/iio/consumer.h
@@ -77,7 +77,7 @@
  * fail.
  */
 struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev,
-					     int (*cb)(u8 *data,
+					     int (*cb)(const void *data,
 						       void *private),
 					     void *private);
 /**
diff --git a/include/linux/iio/events.h b/include/linux/iio/events.h
index 13ce220..5dab2c4 100644
--- a/include/linux/iio/events.h
+++ b/include/linux/iio/events.h
@@ -26,20 +26,6 @@
 
 #define IIO_GET_EVENT_FD_IOCTL _IOR('i', 0x90, int)
 
-enum iio_event_type {
-	IIO_EV_TYPE_THRESH,
-	IIO_EV_TYPE_MAG,
-	IIO_EV_TYPE_ROC,
-	IIO_EV_TYPE_THRESH_ADAPTIVE,
-	IIO_EV_TYPE_MAG_ADAPTIVE,
-};
-
-enum iio_event_direction {
-	IIO_EV_DIR_EITHER,
-	IIO_EV_DIR_RISING,
-	IIO_EV_DIR_FALLING,
-};
-
 /**
  * IIO_EVENT_CODE() - create event identifier
  * @chan_type:	Type of the channel. Should be one of enum iio_chan_type.
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index 2103cc3..256a90a 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -36,6 +36,14 @@
 	IIO_CHAN_INFO_PHASE,
 	IIO_CHAN_INFO_HARDWAREGAIN,
 	IIO_CHAN_INFO_HYSTERESIS,
+	IIO_CHAN_INFO_INT_TIME,
+};
+
+enum iio_shared_by {
+	IIO_SEPARATE,
+	IIO_SHARED_BY_TYPE,
+	IIO_SHARED_BY_DIR,
+	IIO_SHARED_BY_ALL
 };
 
 enum iio_endian {
@@ -57,7 +65,7 @@
  */
 struct iio_chan_spec_ext_info {
 	const char *name;
-	bool shared;
+	enum iio_shared_by shared;
 	ssize_t (*read)(struct iio_dev *, uintptr_t private,
 			struct iio_chan_spec const *, char *buf);
 	ssize_t (*write)(struct iio_dev *, uintptr_t private,
@@ -125,12 +133,35 @@
 #define IIO_ENUM_AVAILABLE(_name, _e) \
 { \
 	.name = (_name "_available"), \
-	.shared = true, \
+	.shared = IIO_SHARED_BY_TYPE, \
 	.read = iio_enum_available_read, \
 	.private = (uintptr_t)(_e), \
 }
 
 /**
+ * struct iio_event_spec - specification for a channel event
+ * @type:		    Type of the event
+ * @dir:		    Direction of the event
+ * @mask_separate:	    Bit mask of enum iio_event_info values. Attributes
+ *			    set in this mask will be registered per channel.
+ * @mask_shared_by_type:    Bit mask of enum iio_event_info values. Attributes
+ *			    set in this mask will be shared by channel type.
+ * @mask_shared_by_dir:	    Bit mask of enum iio_event_info values. Attributes
+ *			    set in this mask will be shared by channel type and
+ *			    direction.
+ * @mask_shared_by_all:	    Bit mask of enum iio_event_info values. Attributes
+ *			    set in this mask will be shared by all channels.
+ */
+struct iio_event_spec {
+	enum iio_event_type type;
+	enum iio_event_direction dir;
+	unsigned long mask_separate;
+	unsigned long mask_shared_by_type;
+	unsigned long mask_shared_by_dir;
+	unsigned long mask_shared_by_all;
+};
+
+/**
  * struct iio_chan_spec - specification of a single channel
  * @type:		What type of measurement is the channel making.
  * @channel:		What number do we wish to assign the channel.
@@ -146,13 +177,18 @@
  *			shift:		Shift right by this before masking out
  *					realbits.
  *			endianness:	little or big endian
- * @info_mask:		What information is to be exported about this channel.
- *			This includes calibbias, scale etc.
  * @info_mask_separate: What information is to be exported that is specific to
  *			this channel.
  * @info_mask_shared_by_type: What information is to be exported that is shared
-*			by all channels of the same type.
+ *			by all channels of the same type.
+ * @info_mask_shared_by_dir: What information is to be exported that is shared
+ *			by all channels of the same direction.
+ * @info_mask_shared_by_all: What information is to be exported that is shared
+ *			by all channels.
  * @event_mask:		What events can this channel produce.
+ * @event_spec:		Array of events which should be registered for this
+ *			channel.
+ * @num_event_specs:	Size of the event_spec array.
  * @ext_info:		Array of extended info attributes for this channel.
  *			The array is NULL terminated, the last element should
  *			have its name field set to NULL.
@@ -186,10 +222,13 @@
 		u8	shift;
 		enum iio_endian endianness;
 	} scan_type;
-	long			info_mask;
 	long			info_mask_separate;
 	long			info_mask_shared_by_type;
+	long			info_mask_shared_by_dir;
+	long			info_mask_shared_by_all;
 	long			event_mask;
+	const struct iio_event_spec *event_spec;
+	unsigned int		num_event_specs;
 	const struct iio_chan_spec_ext_info *ext_info;
 	const char		*extend_name;
 	const char		*datasheet_name;
@@ -212,7 +251,9 @@
 	enum iio_chan_info_enum type)
 {
 	return (chan->info_mask_separate & BIT(type)) |
-	       (chan->info_mask_shared_by_type & BIT(type));
+		(chan->info_mask_shared_by_type & BIT(type)) |
+		(chan->info_mask_shared_by_dir & BIT(type)) |
+		(chan->info_mask_shared_by_all & BIT(type));
 }
 
 #define IIO_ST(si, rb, sb, sh)						\
@@ -270,6 +311,12 @@
  *			is event dependant. event_code specifies which event.
  * @write_event_value:	write the value associated with the event.
  *			Meaning is event dependent.
+ * @read_event_config_new: find out if the event is enabled. New style interface.
+ * @write_event_config_new: set if the event is enabled. New style interface.
+ * @read_event_value_new: read a configuration value associated with the event.
+ *                         New style interface.
+ * @write_event_value_new: write a configuration value for the event. New style
+ *			   interface.
  * @validate_trigger:	function to validate the trigger when the
  *			current trigger gets changed.
  * @update_scan_mode:	function to configure device and scan buffer when
@@ -310,6 +357,30 @@
 	int (*write_event_value)(struct iio_dev *indio_dev,
 				 u64 event_code,
 				 int val);
+
+	int (*read_event_config_new)(struct iio_dev *indio_dev,
+				 const struct iio_chan_spec *chan,
+				 enum iio_event_type type,
+				 enum iio_event_direction dir);
+
+	int (*write_event_config_new)(struct iio_dev *indio_dev,
+				  const struct iio_chan_spec *chan,
+				  enum iio_event_type type,
+				  enum iio_event_direction dir,
+				  int state);
+
+	int (*read_event_value_new)(struct iio_dev *indio_dev,
+				const struct iio_chan_spec *chan,
+				enum iio_event_type type,
+				enum iio_event_direction dir,
+				enum iio_event_info info, int *val, int *val2);
+
+	int (*write_event_value_new)(struct iio_dev *indio_dev,
+				 const struct iio_chan_spec *chan,
+				 enum iio_event_type type,
+				 enum iio_event_direction dir,
+				 enum iio_event_info info, int val, int val2);
+
 	int (*validate_trigger)(struct iio_dev *indio_dev,
 				struct iio_trigger *trig);
 	int (*update_scan_mode)(struct iio_dev *indio_dev,
@@ -457,7 +528,7 @@
 {
 	if (indio_dev)
 		put_device(&indio_dev->dev);
-};
+}
 
 /**
  * dev_to_iio_dev() - Get IIO device struct from a device struct
@@ -593,7 +664,7 @@
 {
 	return indio_dev->currentmode
 		& (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE);
-};
+}
 
 /**
  * iio_get_debugfs_dentry() - helper function to get the debugfs_dentry
@@ -603,12 +674,12 @@
 static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev)
 {
 	return indio_dev->debugfs_dentry;
-};
+}
 #else
 static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev)
 {
 	return NULL;
-};
+}
 #endif
 
 int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer,
diff --git a/include/linux/iio/sysfs.h b/include/linux/iio/sysfs.h
index 2958c96..8a1d186 100644
--- a/include/linux/iio/sysfs.h
+++ b/include/linux/iio/sysfs.h
@@ -100,6 +100,21 @@
 #define IIO_CONST_ATTR_SAMP_FREQ_AVAIL(_string)			\
 	IIO_CONST_ATTR(sampling_frequency_available, _string)
 
+/**
+ * IIO_DEV_ATTR_INT_TIME_AVAIL - list available integration times
+ * @_show: output method for the attribute
+ **/
+#define IIO_DEV_ATTR_INT_TIME_AVAIL(_show)		\
+	IIO_DEVICE_ATTR(integration_time_available, S_IRUGO, _show, NULL, 0)
+/**
+ * IIO_CONST_ATTR_INT_TIME_AVAIL - list available integration times
+ * @_string: frequency string for the attribute
+ *
+ * Constant version
+ **/
+#define IIO_CONST_ATTR_INT_TIME_AVAIL(_string)		\
+	IIO_CONST_ATTR(integration_time_available, _string)
+
 #define IIO_DEV_ATTR_TEMP_RAW(_show)			\
 	IIO_DEVICE_ATTR(in_temp_raw, S_IRUGO, _show, NULL, 0)
 
diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h
index 88bf0f0..4ac928e 100644
--- a/include/linux/iio/types.h
+++ b/include/linux/iio/types.h
@@ -54,6 +54,26 @@
 	IIO_MOD_LIGHT_BLUE,
 };
 
+enum iio_event_type {
+	IIO_EV_TYPE_THRESH,
+	IIO_EV_TYPE_MAG,
+	IIO_EV_TYPE_ROC,
+	IIO_EV_TYPE_THRESH_ADAPTIVE,
+	IIO_EV_TYPE_MAG_ADAPTIVE,
+};
+
+enum iio_event_info {
+	IIO_EV_INFO_ENABLE,
+	IIO_EV_INFO_VALUE,
+	IIO_EV_INFO_HYSTERESIS,
+};
+
+enum iio_event_direction {
+	IIO_EV_DIR_EITHER,
+	IIO_EV_DIR_RISING,
+	IIO_EV_DIR_FALLING,
+};
+
 #define IIO_VAL_INT 1
 #define IIO_VAL_INT_PLUS_MICRO 2
 #define IIO_VAL_INT_PLUS_NANO 3
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 5e865b5..c9e831d 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -19,6 +19,7 @@
 
 #include <linux/atomic.h>
 #include <asm/ptrace.h>
+#include <asm/irq.h>
 
 /*
  * These correspond to the IORESOURCE_IRQ_* defines in
@@ -374,6 +375,16 @@
 
 asmlinkage void do_softirq(void);
 asmlinkage void __do_softirq(void);
+
+#ifdef __ARCH_HAS_DO_SOFTIRQ
+void do_softirq_own_stack(void);
+#else
+static inline void do_softirq_own_stack(void)
+{
+	__do_softirq();
+}
+#endif
+
 extern void open_softirq(int nr, void (*action)(struct softirq_action *));
 extern void softirq_init(void);
 extern void __raise_softirq_irqoff(unsigned int nr);
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index 19c19a5..f6c82de 100644
--- a/include/linux/ipc_namespace.h
+++ b/include/linux/ipc_namespace.h
@@ -34,9 +34,9 @@
 	int		sem_ctls[4];
 	int		used_sems;
 
-	int		msg_ctlmax;
-	int		msg_ctlmnb;
-	int		msg_ctlmni;
+	unsigned int	msg_ctlmax;
+	unsigned int	msg_ctlmnb;
+	unsigned int	msg_ctlmni;
 	atomic_t	msg_bytes;
 	atomic_t	msg_hdrs;
 	int		auto_msgmni;
diff --git a/include/linux/irqchip/bcm2835.h b/include/linux/irqchip/bcm2835.h
deleted file mode 100644
index 48a859b..0000000
--- a/include/linux/irqchip/bcm2835.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2010 Broadcom
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef __LINUX_IRQCHIP_BCM2835_H_
-#define __LINUX_IRQCHIP_BCM2835_H_
-
-#include <asm/exception.h>
-
-extern void bcm2835_init_irq(void);
-
-extern asmlinkage void __exception_irq_entry bcm2835_handle_irq(
-	struct pt_regs *regs);
-
-#endif
diff --git a/include/linux/kdb.h b/include/linux/kdb.h
index 7f6fe6e..290db12 100644
--- a/include/linux/kdb.h
+++ b/include/linux/kdb.h
@@ -109,6 +109,7 @@
 	KDB_REASON_RECURSE,	/* Recursive entry to kdb;
 				 * regs probably valid */
 	KDB_REASON_SSTEP,	/* Single Step trap. - regs valid */
+	KDB_REASON_SYSTEM_NMI,	/* In NMI due to SYSTEM cmd; regs valid */
 } kdb_reason_t;
 
 extern int kdb_trap_printk;
diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h
index c6e091b..dfb4f2f 100644
--- a/include/linux/kgdb.h
+++ b/include/linux/kgdb.h
@@ -310,6 +310,7 @@
 kgdb_handle_exception(int ex_vector, int signo, int err_code,
 		      struct pt_regs *regs);
 extern int kgdb_nmicallback(int cpu, void *regs);
+extern int kgdb_nmicallin(int cpu, int trapnr, void *regs, atomic_t *snd_rdy);
 extern void gdbstub_exit(int status);
 
 extern int			kgdb_single_step;
diff --git a/include/linux/kobj_completion.h b/include/linux/kobj_completion.h
new file mode 100644
index 0000000..a428f64
--- /dev/null
+++ b/include/linux/kobj_completion.h
@@ -0,0 +1,18 @@
+#ifndef _KOBJ_COMPLETION_H_
+#define _KOBJ_COMPLETION_H_
+
+#include <linux/kobject.h>
+#include <linux/completion.h>
+
+struct kobj_completion {
+	struct kobject kc_kobj;
+	struct completion kc_unregister;
+};
+
+#define kobj_to_kobj_completion(kobj) \
+	container_of(kobj, struct kobj_completion, kc_kobj)
+
+void kobj_completion_init(struct kobj_completion *kc, struct kobj_type *ktype);
+void kobj_completion_release(struct kobject *kobj);
+void kobj_completion_del_and_wait(struct kobj_completion *kc);
+#endif /* _KOBJ_COMPLETION_H_ */
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index de6dcbcc..e7ba650 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -107,6 +107,7 @@
 extern struct kobject *kobject_get(struct kobject *kobj);
 extern void kobject_put(struct kobject *kobj);
 
+extern const void *kobject_namespace(struct kobject *kobj);
 extern char *kobject_get_path(struct kobject *kobj, gfp_t flag);
 
 struct kobj_type {
diff --git a/include/linux/lockref.h b/include/linux/lockref.h
index f279ed9..13dfd36 100644
--- a/include/linux/lockref.h
+++ b/include/linux/lockref.h
@@ -36,4 +36,10 @@
 extern void lockref_mark_dead(struct lockref *);
 extern int lockref_get_not_dead(struct lockref *);
 
+/* Must be called under spinlock for reliable results */
+static inline int __lockref_is_dead(const struct lockref *l)
+{
+	return ((int)l->count < 0);
+}
+
 #endif /* __LINUX_LOCKREF_H */
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index ecc82b3..b3e7a66 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -137,47 +137,24 @@
 extern void mem_cgroup_replace_page_cache(struct page *oldpage,
 					struct page *newpage);
 
-/**
- * mem_cgroup_toggle_oom - toggle the memcg OOM killer for the current task
- * @new: true to enable, false to disable
- *
- * Toggle whether a failed memcg charge should invoke the OOM killer
- * or just return -ENOMEM.  Returns the previous toggle state.
- *
- * NOTE: Any path that enables the OOM killer before charging must
- *       call mem_cgroup_oom_synchronize() afterward to finalize the
- *       OOM handling and clean up.
- */
-static inline bool mem_cgroup_toggle_oom(bool new)
+static inline void mem_cgroup_oom_enable(void)
 {
-	bool old;
-
-	old = current->memcg_oom.may_oom;
-	current->memcg_oom.may_oom = new;
-
-	return old;
+	WARN_ON(current->memcg_oom.may_oom);
+	current->memcg_oom.may_oom = 1;
 }
 
-static inline void mem_cgroup_enable_oom(void)
+static inline void mem_cgroup_oom_disable(void)
 {
-	bool old = mem_cgroup_toggle_oom(true);
-
-	WARN_ON(old == true);
-}
-
-static inline void mem_cgroup_disable_oom(void)
-{
-	bool old = mem_cgroup_toggle_oom(false);
-
-	WARN_ON(old == false);
+	WARN_ON(!current->memcg_oom.may_oom);
+	current->memcg_oom.may_oom = 0;
 }
 
 static inline bool task_in_memcg_oom(struct task_struct *p)
 {
-	return p->memcg_oom.in_memcg_oom;
+	return p->memcg_oom.memcg;
 }
 
-bool mem_cgroup_oom_synchronize(void);
+bool mem_cgroup_oom_synchronize(bool wait);
 
 #ifdef CONFIG_MEMCG_SWAP
 extern int do_swap_account;
@@ -402,16 +379,11 @@
 {
 }
 
-static inline bool mem_cgroup_toggle_oom(bool new)
-{
-	return false;
-}
-
-static inline void mem_cgroup_enable_oom(void)
+static inline void mem_cgroup_oom_enable(void)
 {
 }
 
-static inline void mem_cgroup_disable_oom(void)
+static inline void mem_cgroup_oom_disable(void)
 {
 }
 
@@ -420,7 +392,7 @@
 	return false;
 }
 
-static inline bool mem_cgroup_oom_synchronize(void)
+static inline bool mem_cgroup_oom_synchronize(bool wait)
 {
 	return false;
 }
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index da6716b..ea4d249 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -136,6 +136,7 @@
 
 struct mempolicy *get_vma_policy(struct task_struct *tsk,
 		struct vm_area_struct *vma, unsigned long addr);
+bool vma_policy_mof(struct task_struct *task, struct vm_area_struct *vma);
 
 extern void numa_default_policy(void);
 extern void numa_policy_init(void);
diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
index cebe97e..7314fc4 100644
--- a/include/linux/mfd/core.h
+++ b/include/linux/mfd/core.h
@@ -59,6 +59,12 @@
 	 * pm_runtime_no_callbacks().
 	 */
 	bool			pm_runtime_no_callbacks;
+
+	/* A list of regulator supplies that should be mapped to the MFD
+	 * device rather than the child device when requested
+	 */
+	const char		**parent_supplies;
+	int			num_parent_supplies;
 };
 
 /*
diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h
index ca0790f..060e112 100644
--- a/include/linux/mfd/dbx500-prcmu.h
+++ b/include/linux/mfd/dbx500-prcmu.h
@@ -12,6 +12,8 @@
 #include <linux/notifier.h>
 #include <linux/err.h>
 
+#include <dt-bindings/mfd/dbx500-prcmu.h> /* For clock identifiers */
+
 /* Offset for the firmware version within the TCPM */
 #define DB8500_PRCMU_FW_VERSION_OFFSET 0xA4
 #define DBX540_PRCMU_FW_VERSION_OFFSET 0xA8
@@ -94,74 +96,6 @@
 #define PRCMU_CLKSRC_ARMCLKFIX		0x46
 #define PRCMU_CLKSRC_HDMICLK		0x47
 
-/*
- * Clock identifiers.
- */
-enum prcmu_clock {
-	PRCMU_SGACLK,
-	PRCMU_UARTCLK,
-	PRCMU_MSP02CLK,
-	PRCMU_MSP1CLK,
-	PRCMU_I2CCLK,
-	PRCMU_SDMMCCLK,
-	PRCMU_SPARE1CLK,
-	PRCMU_SLIMCLK,
-	PRCMU_PER1CLK,
-	PRCMU_PER2CLK,
-	PRCMU_PER3CLK,
-	PRCMU_PER5CLK,
-	PRCMU_PER6CLK,
-	PRCMU_PER7CLK,
-	PRCMU_LCDCLK,
-	PRCMU_BMLCLK,
-	PRCMU_HSITXCLK,
-	PRCMU_HSIRXCLK,
-	PRCMU_HDMICLK,
-	PRCMU_APEATCLK,
-	PRCMU_APETRACECLK,
-	PRCMU_MCDECLK,
-	PRCMU_IPI2CCLK,
-	PRCMU_DSIALTCLK,
-	PRCMU_DMACLK,
-	PRCMU_B2R2CLK,
-	PRCMU_TVCLK,
-	PRCMU_SSPCLK,
-	PRCMU_RNGCLK,
-	PRCMU_UICCCLK,
-	PRCMU_PWMCLK,
-	PRCMU_IRDACLK,
-	PRCMU_IRRCCLK,
-	PRCMU_SIACLK,
-	PRCMU_SVACLK,
-	PRCMU_ACLK,
-	PRCMU_HVACLK, /* Ux540 only */
-	PRCMU_G1CLK, /* Ux540 only */
-	PRCMU_SDMMCHCLK,
-	PRCMU_CAMCLK,
-	PRCMU_BML8580CLK,
-	PRCMU_NUM_REG_CLOCKS,
-	PRCMU_SYSCLK = PRCMU_NUM_REG_CLOCKS,
-	PRCMU_CDCLK,
-	PRCMU_TIMCLK,
-	PRCMU_PLLSOC0,
-	PRCMU_PLLSOC1,
-	PRCMU_ARMSS,
-	PRCMU_PLLDDR,
-	PRCMU_PLLDSI,
-	PRCMU_DSI0CLK,
-	PRCMU_DSI1CLK,
-	PRCMU_DSI0ESCCLK,
-	PRCMU_DSI1ESCCLK,
-	PRCMU_DSI2ESCCLK,
-	/* LCD DSI PLL - Ux540 only */
-	PRCMU_PLLDSI_LCD,
-	PRCMU_DSI0CLK_LCD,
-	PRCMU_DSI1CLK_LCD,
-	PRCMU_DSI0ESCCLK_LCD,
-	PRCMU_DSI1ESCCLK_LCD,
-	PRCMU_DSI2ESCCLK_LCD,
-};
-
 /**
  * enum prcmu_wdog_id - PRCMU watchdog IDs
  * @PRCMU_WDOG_ALL: use all timers
diff --git a/include/linux/mfd/mc13xxx.h b/include/linux/mfd/mc13xxx.h
index 41ed592..67c17b5 100644
--- a/include/linux/mfd/mc13xxx.h
+++ b/include/linux/mfd/mc13xxx.h
@@ -41,6 +41,13 @@
 		unsigned int mode, unsigned int channel,
 		u8 ato, bool atox, unsigned int *sample);
 
+#define MC13783_AUDIO_RX0	36
+#define MC13783_AUDIO_RX1	37
+#define MC13783_AUDIO_TX	38
+#define MC13783_SSI_NETWORK	39
+#define MC13783_AUDIO_CODEC	40
+#define MC13783_AUDIO_DAC	41
+
 #define MC13XXX_IRQ_ADCDONE	0
 #define MC13XXX_IRQ_ADCBISDONE	1
 #define MC13XXX_IRQ_TS		2
diff --git a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
index b6bdcd6..7086b22 100644
--- a/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
+++ b/include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
@@ -363,4 +363,9 @@
 #define IMX6Q_GPR13_SATA_TX_LVL_1_240_V		(0x1f << 2)
 #define IMX6Q_GPR13_SATA_MPLL_CLK_EN		BIT(1)
 #define IMX6Q_GPR13_SATA_TX_EDGE_RATE		BIT(0)
+
+/* For imx6sl iomux gpr register field define */
+#define IMX6SL_GPR1_FEC_CLOCK_MUX1_SEL_MASK    (0x3 << 17)
+#define IMX6SL_GPR1_FEC_CLOCK_MUX2_SEL_MASK    (0x1 << 14)
+
 #endif /* __LINUX_IMX6Q_IOMUXC_GPR_H */
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index 25f2c61..08cce7f 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -46,16 +46,24 @@
 /* Step Enable */
 #define STEPENB_MASK		(0x1FFFF << 0)
 #define STEPENB(val)		((val) << 0)
+#define ENB(val)			(1 << (val))
+#define STPENB_STEPENB		STEPENB(0x1FFFF)
+#define STPENB_STEPENB_TC	STEPENB(0x1FFF)
 
 /* IRQ enable */
 #define IRQENB_HW_PEN		BIT(0)
 #define IRQENB_FIFO0THRES	BIT(2)
+#define IRQENB_FIFO0OVRRUN	BIT(3)
+#define IRQENB_FIFO0UNDRFLW	BIT(4)
 #define IRQENB_FIFO1THRES	BIT(5)
+#define IRQENB_FIFO1OVRRUN	BIT(6)
+#define IRQENB_FIFO1UNDRFLW	BIT(7)
 #define IRQENB_PENUP		BIT(9)
 
 /* Step Configuration */
 #define STEPCONFIG_MODE_MASK	(3 << 0)
 #define STEPCONFIG_MODE(val)	((val) << 0)
+#define STEPCONFIG_MODE_SWCNT	STEPCONFIG_MODE(1)
 #define STEPCONFIG_MODE_HWSYNC	STEPCONFIG_MODE(2)
 #define STEPCONFIG_AVG_MASK	(7 << 2)
 #define STEPCONFIG_AVG(val)	((val) << 2)
@@ -123,6 +131,7 @@
 #define ADC_CLK			3000000
 #define TOTAL_STEPS		16
 #define TOTAL_CHANNELS		8
+#define FIFO1_THRESHOLD		19
 
 /*
 * ADC runs at 3MHz, and it takes
diff --git a/include/linux/migrate.h b/include/linux/migrate.h
index 8d3c57f..f5096b5 100644
--- a/include/linux/migrate.h
+++ b/include/linux/migrate.h
@@ -90,11 +90,12 @@
 #endif /* CONFIG_MIGRATION */
 
 #ifdef CONFIG_NUMA_BALANCING
-extern int migrate_misplaced_page(struct page *page, int node);
-extern int migrate_misplaced_page(struct page *page, int node);
+extern int migrate_misplaced_page(struct page *page,
+				  struct vm_area_struct *vma, int node);
 extern bool migrate_ratelimited(int node);
 #else
-static inline int migrate_misplaced_page(struct page *page, int node)
+static inline int migrate_misplaced_page(struct page *page,
+					 struct vm_area_struct *vma, int node)
 {
 	return -EAGAIN; /* can't migrate now */
 }
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
index 09c2300..f7eaf2d 100644
--- a/include/linux/miscdevice.h
+++ b/include/linux/miscdevice.h
@@ -31,6 +31,7 @@
 #define I2O_MINOR		166
 #define MICROCODE_MINOR		184
 #define TUN_MINOR		200
+#define CUSE_MINOR		203
 #define MWAVE_MINOR		219	/* ACP/Mwave Modem */
 #define MPT_MINOR		220
 #define MPT2SAS_MINOR		221
@@ -45,6 +46,7 @@
 #define MAPPER_CTRL_MINOR	236
 #define LOOP_CTRL_MINOR		237
 #define VHOST_NET_MINOR		238
+#define UHID_MINOR		239
 #define MISC_DYNAMIC_MINOR	255
 
 struct device;
diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h
index 68029b3..5eb4e31 100644
--- a/include/linux/mlx5/device.h
+++ b/include/linux/mlx5/device.h
@@ -181,7 +181,7 @@
 	MLX5_DEV_CAP_FLAG_TLP_HINTS	= 1LL << 39,
 	MLX5_DEV_CAP_FLAG_SIG_HAND_OVER	= 1LL << 40,
 	MLX5_DEV_CAP_FLAG_DCT		= 1LL << 41,
-	MLX5_DEV_CAP_FLAG_CMDIF_CSUM	= 1LL << 46,
+	MLX5_DEV_CAP_FLAG_CMDIF_CSUM	= 3LL << 46,
 };
 
 enum {
@@ -417,7 +417,7 @@
 	struct health_buffer	health;
 	__be32			rsvd2[884];
 	__be32			health_counter;
-	__be32			rsvd3[1023];
+	__be32			rsvd3[1019];
 	__be64			ieee1588_clk;
 	__be32			ieee1588_clk_type;
 	__be32			clr_intx;
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index 8888381..6b8c496 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -82,7 +82,7 @@
 };
 
 enum {
-	MLX5_MAX_EQ_NAME	= 20
+	MLX5_MAX_EQ_NAME	= 32
 };
 
 enum {
@@ -747,8 +747,7 @@
 
 enum {
 	MLX5_PROF_MASK_QP_SIZE		= (u64)1 << 0,
-	MLX5_PROF_MASK_CMDIF_CSUM	= (u64)1 << 1,
-	MLX5_PROF_MASK_MR_CACHE		= (u64)1 << 2,
+	MLX5_PROF_MASK_MR_CACHE		= (u64)1 << 1,
 };
 
 enum {
@@ -758,7 +757,6 @@
 struct mlx5_profile {
 	u64	mask;
 	u32	log_max_qp;
-	int	cmdif_csum;
 	struct {
 		int	size;
 		int	limit;
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 8b6e55e..8aa4006 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -297,12 +297,26 @@
 /*
  * Try to grab a ref unless the page has a refcount of zero, return false if
  * that is the case.
+ * This can be called when MMU is off so it must not access
+ * any of the virtual mappings.
  */
 static inline int get_page_unless_zero(struct page *page)
 {
 	return atomic_inc_not_zero(&page->_count);
 }
 
+/*
+ * Try to drop a ref unless the page has a refcount of one, return false if
+ * that is the case.
+ * This is to make sure that the refcount won't become zero after this drop.
+ * This can be called when MMU is off so it must not access
+ * any of the virtual mappings.
+ */
+static inline int put_page_unless_one(struct page *page)
+{
+	return atomic_add_unless(&page->_count, -1, 1);
+}
+
 extern int page_is_ram(unsigned long pfn);
 
 /* Support for virtually mapped pages */
@@ -581,11 +595,11 @@
  * sets it, so none of the operations on it need to be atomic.
  */
 
-/* Page flags: | [SECTION] | [NODE] | ZONE | [LAST_NID] | ... | FLAGS | */
+/* Page flags: | [SECTION] | [NODE] | ZONE | [LAST_CPUPID] | ... | FLAGS | */
 #define SECTIONS_PGOFF		((sizeof(unsigned long)*8) - SECTIONS_WIDTH)
 #define NODES_PGOFF		(SECTIONS_PGOFF - NODES_WIDTH)
 #define ZONES_PGOFF		(NODES_PGOFF - ZONES_WIDTH)
-#define LAST_NID_PGOFF		(ZONES_PGOFF - LAST_NID_WIDTH)
+#define LAST_CPUPID_PGOFF	(ZONES_PGOFF - LAST_CPUPID_WIDTH)
 
 /*
  * Define the bit shifts to access each section.  For non-existent
@@ -595,7 +609,7 @@
 #define SECTIONS_PGSHIFT	(SECTIONS_PGOFF * (SECTIONS_WIDTH != 0))
 #define NODES_PGSHIFT		(NODES_PGOFF * (NODES_WIDTH != 0))
 #define ZONES_PGSHIFT		(ZONES_PGOFF * (ZONES_WIDTH != 0))
-#define LAST_NID_PGSHIFT	(LAST_NID_PGOFF * (LAST_NID_WIDTH != 0))
+#define LAST_CPUPID_PGSHIFT	(LAST_CPUPID_PGOFF * (LAST_CPUPID_WIDTH != 0))
 
 /* NODE:ZONE or SECTION:ZONE is used to ID a zone for the buddy allocator */
 #ifdef NODE_NOT_IN_PAGE_FLAGS
@@ -617,7 +631,7 @@
 #define ZONES_MASK		((1UL << ZONES_WIDTH) - 1)
 #define NODES_MASK		((1UL << NODES_WIDTH) - 1)
 #define SECTIONS_MASK		((1UL << SECTIONS_WIDTH) - 1)
-#define LAST_NID_MASK		((1UL << LAST_NID_WIDTH) - 1)
+#define LAST_CPUPID_MASK	((1UL << LAST_CPUPID_WIDTH) - 1)
 #define ZONEID_MASK		((1UL << ZONEID_SHIFT) - 1)
 
 static inline enum zone_type page_zonenum(const struct page *page)
@@ -661,51 +675,117 @@
 #endif
 
 #ifdef CONFIG_NUMA_BALANCING
-#ifdef LAST_NID_NOT_IN_PAGE_FLAGS
-static inline int page_nid_xchg_last(struct page *page, int nid)
+static inline int cpu_pid_to_cpupid(int cpu, int pid)
 {
-	return xchg(&page->_last_nid, nid);
+	return ((cpu & LAST__CPU_MASK) << LAST__PID_SHIFT) | (pid & LAST__PID_MASK);
 }
 
-static inline int page_nid_last(struct page *page)
+static inline int cpupid_to_pid(int cpupid)
 {
-	return page->_last_nid;
+	return cpupid & LAST__PID_MASK;
 }
-static inline void page_nid_reset_last(struct page *page)
+
+static inline int cpupid_to_cpu(int cpupid)
 {
-	page->_last_nid = -1;
+	return (cpupid >> LAST__PID_SHIFT) & LAST__CPU_MASK;
+}
+
+static inline int cpupid_to_nid(int cpupid)
+{
+	return cpu_to_node(cpupid_to_cpu(cpupid));
+}
+
+static inline bool cpupid_pid_unset(int cpupid)
+{
+	return cpupid_to_pid(cpupid) == (-1 & LAST__PID_MASK);
+}
+
+static inline bool cpupid_cpu_unset(int cpupid)
+{
+	return cpupid_to_cpu(cpupid) == (-1 & LAST__CPU_MASK);
+}
+
+static inline bool __cpupid_match_pid(pid_t task_pid, int cpupid)
+{
+	return (task_pid & LAST__PID_MASK) == cpupid_to_pid(cpupid);
+}
+
+#define cpupid_match_pid(task, cpupid) __cpupid_match_pid(task->pid, cpupid)
+#ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS
+static inline int page_cpupid_xchg_last(struct page *page, int cpupid)
+{
+	return xchg(&page->_last_cpupid, cpupid);
+}
+
+static inline int page_cpupid_last(struct page *page)
+{
+	return page->_last_cpupid;
+}
+static inline void page_cpupid_reset_last(struct page *page)
+{
+	page->_last_cpupid = -1;
 }
 #else
-static inline int page_nid_last(struct page *page)
+static inline int page_cpupid_last(struct page *page)
 {
-	return (page->flags >> LAST_NID_PGSHIFT) & LAST_NID_MASK;
+	return (page->flags >> LAST_CPUPID_PGSHIFT) & LAST_CPUPID_MASK;
 }
 
-extern int page_nid_xchg_last(struct page *page, int nid);
+extern int page_cpupid_xchg_last(struct page *page, int cpupid);
 
-static inline void page_nid_reset_last(struct page *page)
+static inline void page_cpupid_reset_last(struct page *page)
 {
-	int nid = (1 << LAST_NID_SHIFT) - 1;
+	int cpupid = (1 << LAST_CPUPID_SHIFT) - 1;
 
-	page->flags &= ~(LAST_NID_MASK << LAST_NID_PGSHIFT);
-	page->flags |= (nid & LAST_NID_MASK) << LAST_NID_PGSHIFT;
+	page->flags &= ~(LAST_CPUPID_MASK << LAST_CPUPID_PGSHIFT);
+	page->flags |= (cpupid & LAST_CPUPID_MASK) << LAST_CPUPID_PGSHIFT;
 }
-#endif /* LAST_NID_NOT_IN_PAGE_FLAGS */
-#else
-static inline int page_nid_xchg_last(struct page *page, int nid)
+#endif /* LAST_CPUPID_NOT_IN_PAGE_FLAGS */
+#else /* !CONFIG_NUMA_BALANCING */
+static inline int page_cpupid_xchg_last(struct page *page, int cpupid)
 {
-	return page_to_nid(page);
+	return page_to_nid(page); /* XXX */
 }
 
-static inline int page_nid_last(struct page *page)
+static inline int page_cpupid_last(struct page *page)
 {
-	return page_to_nid(page);
+	return page_to_nid(page); /* XXX */
 }
 
-static inline void page_nid_reset_last(struct page *page)
+static inline int cpupid_to_nid(int cpupid)
+{
+	return -1;
+}
+
+static inline int cpupid_to_pid(int cpupid)
+{
+	return -1;
+}
+
+static inline int cpupid_to_cpu(int cpupid)
+{
+	return -1;
+}
+
+static inline int cpu_pid_to_cpupid(int nid, int pid)
+{
+	return -1;
+}
+
+static inline bool cpupid_pid_unset(int cpupid)
+{
+	return 1;
+}
+
+static inline void page_cpupid_reset_last(struct page *page)
 {
 }
-#endif
+
+static inline bool cpupid_match_pid(struct task_struct *task, int cpupid)
+{
+	return false;
+}
+#endif /* CONFIG_NUMA_BALANCING */
 
 static inline struct zone *page_zone(const struct page *page)
 {
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index d9851ee..a3198e5 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -174,8 +174,8 @@
 	void *shadow;
 #endif
 
-#ifdef LAST_NID_NOT_IN_PAGE_FLAGS
-	int _last_nid;
+#ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS
+	int _last_cpupid;
 #endif
 }
 /*
@@ -420,28 +420,15 @@
 	 */
 	unsigned long numa_next_scan;
 
-	/* numa_next_reset is when the PTE scanner period will be reset */
-	unsigned long numa_next_reset;
-
 	/* Restart point for scanning and setting pte_numa */
 	unsigned long numa_scan_offset;
 
 	/* numa_scan_seq prevents two threads setting pte_numa */
 	int numa_scan_seq;
-
-	/*
-	 * The first node a task was scheduled on. If a task runs on
-	 * a different node than Make PTE Scan Go Now.
-	 */
-	int first_nid;
 #endif
 	struct uprobes_state uprobes_state;
 };
 
-/* first nid will either be a valid NID or one of these values */
-#define NUMA_PTE_SCAN_INIT	-1
-#define NUMA_PTE_SCAN_ACTIVE	-2
-
 static inline void mm_init_cpumask(struct mm_struct *mm)
 {
 #ifdef CONFIG_CPUMASK_OFFSTACK
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3de49ac..adf4070 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2264,11 +2264,12 @@
 }
 
 #ifdef CONFIG_XPS
-extern int netif_set_xps_queue(struct net_device *dev, struct cpumask *mask,
+extern int netif_set_xps_queue(struct net_device *dev,
+			       const struct cpumask *mask,
 			       u16 index);
 #else
 static inline int netif_set_xps_queue(struct net_device *dev,
-				      struct cpumask *mask,
+				      const struct cpumask *mask,
 				      u16 index)
 {
 	return 0;
@@ -2873,8 +2874,20 @@
 #define dev_proc_init() 0
 #endif
 
-extern int netdev_class_create_file(struct class_attribute *class_attr);
-extern void netdev_class_remove_file(struct class_attribute *class_attr);
+extern int netdev_class_create_file_ns(struct class_attribute *class_attr,
+				       const void *ns);
+extern void netdev_class_remove_file_ns(struct class_attribute *class_attr,
+					const void *ns);
+
+static inline int netdev_class_create_file(struct class_attribute *class_attr)
+{
+	return netdev_class_create_file_ns(class_attr, NULL);
+}
+
+static inline void netdev_class_remove_file(struct class_attribute *class_attr)
+{
+	netdev_class_remove_file_ns(class_attr, NULL);
+}
 
 extern struct kobj_ns_type_operations net_ns_type_operations;
 
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index f3c7c24..fbfdb9d 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -24,7 +24,8 @@
 	struct net_device *dev;
 	char dev_name[IFNAMSIZ];
 	const char *name;
-	void (*rx_hook)(struct netpoll *, int, char *, int);
+	void (*rx_skb_hook)(struct netpoll *np, int source, struct sk_buff *skb,
+			    int offset, int len);
 
 	union inet_addr local_ip, remote_ip;
 	bool ipv6;
@@ -41,7 +42,7 @@
 	unsigned long rx_flags;
 	spinlock_t rx_lock;
 	struct semaphore dev_lock;
-	struct list_head rx_np; /* netpolls that registered an rx_hook */
+	struct list_head rx_np; /* netpolls that registered an rx_skb_hook */
 
 	struct sk_buff_head neigh_tx; /* list of neigh requests to reply to */
 	struct sk_buff_head txq;
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index e36dee5..c6f41b6 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -395,7 +395,9 @@
 #define FATTR4_WORD1_FS_LAYOUT_TYPES    (1UL << 30)
 #define FATTR4_WORD2_LAYOUT_BLKSIZE     (1UL << 1)
 #define FATTR4_WORD2_MDSTHRESHOLD       (1UL << 4)
-#define FATTR4_WORD2_SECURITY_LABEL     (1UL << 17)
+#define FATTR4_WORD2_SECURITY_LABEL     (1UL << 16)
+#define FATTR4_WORD2_CHANGE_SECURITY_LABEL \
+					(1UL << 17)
 
 /* MDS threshold bitmap bits */
 #define THRESHOLD_RD                    (1UL << 0)
@@ -460,6 +462,7 @@
 	NFSPROC4_CLNT_FS_LOCATIONS,
 	NFSPROC4_CLNT_RELEASE_LOCKOWNER,
 	NFSPROC4_CLNT_SECINFO,
+	NFSPROC4_CLNT_FSID_PRESENT,
 
 	/* nfs41 */
 	NFSPROC4_CLNT_EXCHANGE_ID,
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 3ea4cde..14a4820 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -269,9 +269,13 @@
 	return test_bit(NFS_INO_STALE, &NFS_I(inode)->flags);
 }
 
-static inline int NFS_FSCACHE(const struct inode *inode)
+static inline struct fscache_cookie *nfs_i_fscache(struct inode *inode)
 {
-	return test_bit(NFS_INO_FSCACHE, &NFS_I(inode)->flags);
+#ifdef CONFIG_NFS_FSCACHE
+	return NFS_I(inode)->fscache;
+#else
+	return NULL;
+#endif
 }
 
 static inline __u64 NFS_FILEID(const struct inode *inode)
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index b8cedce..1150ea4 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -41,6 +41,7 @@
 #define NFS_CS_DISCRTRY		1		/* - disconnect on RPC retry */
 #define NFS_CS_MIGRATION	2		/* - transparent state migr */
 #define NFS_CS_INFINITE_SLOTS	3		/* - don't limit TCP slots */
+#define NFS_CS_NO_RETRANS_TIMEOUT	4	/* - Disable retransmit timeouts */
 	struct sockaddr_storage	cl_addr;	/* server identifier */
 	size_t			cl_addrlen;
 	char *			cl_hostname;	/* hostname of server */
@@ -78,6 +79,7 @@
 	char			cl_ipaddr[48];
 	u32			cl_cb_ident;	/* v4.0 callback identifier */
 	const struct nfs4_minor_version_ops *cl_mvops;
+	unsigned long		cl_mig_gen;
 
 	/* NFSv4.0 transport blocking */
 	struct nfs4_slot_table	*cl_slot_tbl;
@@ -147,7 +149,9 @@
 	__u64			maxfilesize;	/* maximum file size */
 	struct timespec		time_delta;	/* smallest time granularity */
 	unsigned long		mount_time;	/* when this fs was mounted */
+	struct super_block	*super;		/* VFS super block */
 	dev_t			s_dev;		/* superblock dev numbers */
+	struct nfs_auth_info	auth_info;	/* parsed auth flavors */
 
 #ifdef CONFIG_NFS_FSCACHE
 	struct nfs_fscache_key	*fscache_key;	/* unique key for superblock */
@@ -187,6 +191,12 @@
 	struct list_head	state_owners_lru;
 	struct list_head	layouts;
 	struct list_head	delegations;
+
+	unsigned long		mig_gen;
+	unsigned long		mig_status;
+#define NFS_MIG_IN_TRANSITION		(1)
+#define NFS_MIG_FAILED			(2)
+
 	void (*destroy)(struct nfs_server *);
 
 	atomic_t active; /* Keep trace of any activity to this server */
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 49f52c8..3ccfcec 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -591,6 +591,13 @@
 	struct nfs_fattr		*new_fattr;
 };
 
+/* parsed sec= options */
+#define NFS_AUTH_INFO_MAX_FLAVORS 12 /* see fs/nfs/super.c */
+struct nfs_auth_info {
+	unsigned int            flavor_len;
+	rpc_authflavor_t        flavors[NFS_AUTH_INFO_MAX_FLAVORS];
+};
+
 /*
  * Argument struct for decode_entry function
  */
@@ -1053,14 +1060,18 @@
 struct nfs4_fs_locations_arg {
 	struct nfs4_sequence_args	seq_args;
 	const struct nfs_fh *dir_fh;
+	const struct nfs_fh *fh;
 	const struct qstr *name;
 	struct page *page;
 	const u32 *bitmask;
+	clientid4 clientid;
+	unsigned char migration:1, renew:1;
 };
 
 struct nfs4_fs_locations_res {
 	struct nfs4_sequence_res	seq_res;
 	struct nfs4_fs_locations       *fs_locations;
+	unsigned char			migration:1, renew:1;
 };
 
 struct nfs4_secinfo4 {
@@ -1084,6 +1095,19 @@
 	struct nfs4_secinfo_flavors	*flavors;
 };
 
+struct nfs4_fsid_present_arg {
+	struct nfs4_sequence_args	seq_args;
+	const struct nfs_fh		*fh;
+	clientid4			clientid;
+	unsigned char			renew:1;
+};
+
+struct nfs4_fsid_present_res {
+	struct nfs4_sequence_res	seq_res;
+	struct nfs_fh			*fh;
+	unsigned char			renew:1;
+};
+
 #endif /* CONFIG_NFS_V4 */
 
 struct nfstime4 {
diff --git a/include/linux/of.h b/include/linux/of.h
index f95aee3..276c546 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -136,7 +136,9 @@
 	return of_read_number(cell, size);
 }
 
+#if defined(CONFIG_SPARC)
 #include <asm/prom.h>
+#endif
 
 /* Default #address and #size cells.  Allow arch asm/prom.h to override */
 #if !defined(OF_ROOT_NODE_ADDR_CELLS_DEFAULT)
@@ -226,6 +228,19 @@
 	return num;
 }
 
+static inline int of_get_available_child_count(const struct device_node *np)
+{
+	struct device_node *child;
+	int num = 0;
+
+	for_each_available_child_of_node(np, child)
+		num++;
+
+	return num;
+}
+
+/* cache lookup */
+extern struct device_node *of_find_next_cache_node(const struct device_node *);
 extern struct device_node *of_find_node_with_property(
 	struct device_node *from, const char *prop_name);
 #define for_each_node_with_property(dn, prop_name) \
@@ -275,6 +290,7 @@
 extern const struct of_device_id *of_match_node(
 	const struct of_device_id *matches, const struct device_node *node);
 extern int of_modalias_node(struct device_node *node, char *modalias, int len);
+extern void of_print_phandle_args(const char *msg, const struct of_phandle_args *args);
 extern struct device_node *of_parse_phandle(const struct device_node *np,
 					    const char *phandle_name,
 					    int index);
@@ -364,6 +380,9 @@
 #define for_each_child_of_node(parent, child) \
 	while (0)
 
+#define for_each_available_child_of_node(parent, child) \
+	while (0)
+
 static inline struct device_node *of_get_child_by_name(
 					const struct device_node *node,
 					const char *name)
@@ -376,6 +395,11 @@
 	return 0;
 }
 
+static inline int of_get_available_child_count(const struct device_node *np)
+{
+	return 0;
+}
+
 static inline int of_device_is_compatible(const struct device_node *device,
 					  const char *name)
 {
@@ -534,13 +558,10 @@
 #define of_match_node(_matches, _node)	NULL
 #endif /* CONFIG_OF */
 
-#ifndef of_node_to_nid
-static inline int of_node_to_nid(struct device_node *np)
-{
-	return numa_node_id();
-}
-
-#define of_node_to_nid of_node_to_nid
+#if defined(CONFIG_OF) && defined(CONFIG_NUMA)
+extern int of_node_to_nid(struct device_node *np);
+#else
+static inline int of_node_to_nid(struct device_node *device) { return 0; }
 #endif
 
 /**
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 4c2e6f2..5f6ed6b 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -34,6 +34,10 @@
 	res->name = np->full_name;
 }
 
+/* Translate a DMA address from device space to CPU space */
+extern u64 of_translate_dma_address(struct device_node *dev,
+				    const __be32 *in_addr);
+
 #ifdef CONFIG_OF_ADDRESS
 extern u64 of_translate_address(struct device_node *np, const __be32 *addr);
 extern bool of_can_translate_address(struct device_node *dev);
@@ -52,10 +56,7 @@
 extern const __be32 *of_get_address(struct device_node *dev, int index,
 			   u64 *size, unsigned int *flags);
 
-#ifndef pci_address_to_pio
-static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; }
-#define pci_address_to_pio pci_address_to_pio
-#endif
+extern unsigned long pci_address_to_pio(phys_addr_t addr);
 
 extern int of_pci_range_parser_init(struct of_pci_range_parser *parser,
 			struct device_node *node);
@@ -63,13 +64,6 @@
 					struct of_pci_range_parser *parser,
 					struct of_pci_range *range);
 #else /* CONFIG_OF_ADDRESS */
-#ifndef of_address_to_resource
-static inline int of_address_to_resource(struct device_node *dev, int index,
-					 struct resource *r)
-{
-	return -EINVAL;
-}
-#endif
 static inline struct device_node *of_find_matching_node_by_address(
 					struct device_node *from,
 					const struct of_device_id *matches,
@@ -77,12 +71,7 @@
 {
 	return NULL;
 }
-#ifndef of_iomap
-static inline void __iomem *of_iomap(struct device_node *device, int index)
-{
-	return NULL;
-}
-#endif
+
 static inline const __be32 *of_get_address(struct device_node *dev, int index,
 					u64 *size, unsigned int *flags)
 {
@@ -103,6 +92,22 @@
 }
 #endif /* CONFIG_OF_ADDRESS */
 
+#ifdef CONFIG_OF
+extern int of_address_to_resource(struct device_node *dev, int index,
+				  struct resource *r);
+void __iomem *of_iomap(struct device_node *node, int index);
+#else
+static inline int of_address_to_resource(struct device_node *dev, int index,
+					 struct resource *r)
+{
+	return -EINVAL;
+}
+
+static inline void __iomem *of_iomap(struct device_node *device, int index)
+{
+	return NULL;
+}
+#endif
 
 #if defined(CONFIG_OF_ADDRESS) && defined(CONFIG_PCI)
 extern const __be32 *of_get_pci_address(struct device_node *dev, int bar_no,
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index a478c62..0beaee9 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -96,31 +96,30 @@
 
 extern int early_init_dt_scan_chosen(unsigned long node, const char *uname,
 				     int depth, void *data);
-extern void early_init_dt_check_for_initrd(unsigned long node);
 extern int early_init_dt_scan_memory(unsigned long node, const char *uname,
 				     int depth, void *data);
 extern void early_init_dt_add_memory_arch(u64 base, u64 size);
 extern void * early_init_dt_alloc_memory_arch(u64 size, u64 align);
 extern u64 dt_mem_next_cell(int s, __be32 **cellp);
 
-/*
- * If BLK_DEV_INITRD, the fdt early init code will call this function,
- * to be provided by the arch code. start and end are specified as
- * physical addresses.
- */
-#ifdef CONFIG_BLK_DEV_INITRD
-extern void early_init_dt_setup_initrd_arch(u64 start, u64 end);
-#endif
-
 /* Early flat tree scan hooks */
 extern int early_init_dt_scan_root(unsigned long node, const char *uname,
 				   int depth, void *data);
 
+extern bool early_init_dt_scan(void *params);
+
+extern const char *of_flat_dt_get_machine_name(void);
+extern const void *of_flat_dt_match_machine(const void *default_match,
+		const void * (*get_next_compat)(const char * const**));
+
 /* Other Prototypes */
 extern void unflatten_device_tree(void);
+extern void unflatten_and_copy_device_tree(void);
 extern void early_init_devtree(void *);
 #else /* CONFIG_OF_FLATTREE */
+static inline const char *of_flat_dt_get_machine_name(void) { return NULL; }
 static inline void unflatten_device_tree(void) {}
+static inline void unflatten_and_copy_device_tree(void) {}
 #endif /* CONFIG_OF_FLATTREE */
 
 #endif /* __ASSEMBLY__ */
diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h
index a83dc6f..f14123a 100644
--- a/include/linux/of_gpio.h
+++ b/include/linux/of_gpio.h
@@ -19,6 +19,7 @@
 #include <linux/errno.h>
 #include <linux/gpio.h>
 #include <linux/of.h>
+#include <linux/gpio/consumer.h>
 
 struct device_node;
 
@@ -47,7 +48,7 @@
 	return container_of(gc, struct of_mm_gpio_chip, gc);
 }
 
-extern int of_get_named_gpio_flags(struct device_node *np,
+extern struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
 		const char *list_name, int index, enum of_gpio_flags *flags);
 
 extern int of_mm_gpiochip_add(struct device_node *np,
@@ -62,10 +63,10 @@
 #else /* CONFIG_OF_GPIO */
 
 /* Drivers may not strictly depend on the GPIO support, so let them link. */
-static inline int of_get_named_gpio_flags(struct device_node *np,
+static inline struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
 		const char *list_name, int index, enum of_gpio_flags *flags)
 {
-	return -ENOSYS;
+	return ERR_PTR(-ENOSYS);
 }
 
 static inline int of_gpio_simple_xlate(struct gpio_chip *gc,
@@ -80,6 +81,18 @@
 
 #endif /* CONFIG_OF_GPIO */
 
+static inline int of_get_named_gpio_flags(struct device_node *np,
+		const char *list_name, int index, enum of_gpio_flags *flags)
+{
+	struct gpio_desc *desc;
+	desc = of_get_named_gpiod_flags(np, list_name, index, flags);
+
+	if (IS_ERR(desc))
+		return PTR_ERR(desc);
+	else
+		return desc_to_gpio(desc);
+}
+
 /**
  * of_gpio_named_count() - Count GPIOs for a device
  * @np:		device node to count GPIOs for
@@ -117,15 +130,21 @@
 }
 
 /**
- * of_get_gpio_flags() - Get a GPIO number and flags to use with GPIO API
+ * of_get_gpiod_flags() - Get a GPIO descriptor and flags to use with GPIO API
  * @np:		device node to get GPIO from
  * @index:	index of the GPIO
  * @flags:	a flags pointer to fill in
  *
- * Returns GPIO number to use with Linux generic GPIO API, or one of the errno
+ * Returns GPIO descriptor to use with Linux generic GPIO API, or a errno
  * value on the error condition. If @flags is not NULL the function also fills
  * in flags for the GPIO.
  */
+static inline struct gpio_desc *of_get_gpiod_flags(struct device_node *np,
+					int index, enum of_gpio_flags *flags)
+{
+	return of_get_named_gpiod_flags(np, "gpios", index, flags);
+}
+
 static inline int of_get_gpio_flags(struct device_node *np, int index,
 		      enum of_gpio_flags *flags)
 {
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
index fcd63ba..3f23b44 100644
--- a/include/linux/of_irq.h
+++ b/include/linux/of_irq.h
@@ -8,22 +8,6 @@
 #include <linux/ioport.h>
 #include <linux/of.h>
 
-/**
- * of_irq - container for device_node/irq_specifier pair for an irq controller
- * @controller: pointer to interrupt controller device tree node
- * @size: size of interrupt specifier
- * @specifier: array of cells @size long specifing the specific interrupt
- *
- * This structure is returned when an interrupt is mapped. The controller
- * field needs to be put() after use
- */
-#define OF_MAX_IRQ_SPEC		4 /* We handle specifiers of at most 4 cells */
-struct of_irq {
-	struct device_node *controller; /* Interrupt controller node */
-	u32 size; /* Specifier size */
-	u32 specifier[OF_MAX_IRQ_SPEC]; /* Specifier copy */
-};
-
 typedef int (*of_irq_init_cb_t)(struct device_node *, struct device_node *);
 
 /*
@@ -35,35 +19,38 @@
 #if defined(CONFIG_PPC32) && defined(CONFIG_PPC_PMAC)
 extern unsigned int of_irq_workarounds;
 extern struct device_node *of_irq_dflt_pic;
-extern int of_irq_map_oldworld(struct device_node *device, int index,
-			       struct of_irq *out_irq);
+extern int of_irq_parse_oldworld(struct device_node *device, int index,
+			       struct of_phandle_args *out_irq);
 #else /* CONFIG_PPC32 && CONFIG_PPC_PMAC */
 #define of_irq_workarounds (0)
 #define of_irq_dflt_pic (NULL)
-static inline int of_irq_map_oldworld(struct device_node *device, int index,
-				      struct of_irq *out_irq)
+static inline int of_irq_parse_oldworld(struct device_node *device, int index,
+				      struct of_phandle_args *out_irq)
 {
 	return -EINVAL;
 }
 #endif /* CONFIG_PPC32 && CONFIG_PPC_PMAC */
 
-
-extern int of_irq_map_raw(struct device_node *parent, const __be32 *intspec,
-			  u32 ointsize, const __be32 *addr,
-			  struct of_irq *out_irq);
-extern int of_irq_map_one(struct device_node *device, int index,
-			  struct of_irq *out_irq);
-extern unsigned int irq_create_of_mapping(struct device_node *controller,
-					  const u32 *intspec,
-					  unsigned int intsize);
+extern int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq);
+extern int of_irq_parse_one(struct device_node *device, int index,
+			  struct of_phandle_args *out_irq);
+extern unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data);
 extern int of_irq_to_resource(struct device_node *dev, int index,
 			      struct resource *r);
-extern int of_irq_count(struct device_node *dev);
 extern int of_irq_to_resource_table(struct device_node *dev,
 		struct resource *res, int nr_irqs);
 
 extern void of_irq_init(const struct of_device_id *matches);
 
+#ifdef CONFIG_OF_IRQ
+extern int of_irq_count(struct device_node *dev);
+#else
+static inline int of_irq_count(struct device_node *dev)
+{
+	return 0;
+}
+#endif
+
 #if defined(CONFIG_OF)
 /*
  * irq_of_parse_and_map() is used by all OF enabled platforms; but SPARC
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
index fd9c408..1a1f5ff 100644
--- a/include/linux/of_pci.h
+++ b/include/linux/of_pci.h
@@ -5,8 +5,9 @@
 #include <linux/msi.h>
 
 struct pci_dev;
-struct of_irq;
-int of_irq_map_pci(const struct pci_dev *pdev, struct of_irq *out_irq);
+struct of_phandle_args;
+int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq);
+int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin);
 
 struct device_node;
 struct device_node *of_pci_find_child_device(struct device_node *parent,
diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h
deleted file mode 100644
index c841282..0000000
--- a/include/linux/of_reserved_mem.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __OF_RESERVED_MEM_H
-#define __OF_RESERVED_MEM_H
-
-#ifdef CONFIG_OF_RESERVED_MEM
-void of_reserved_mem_device_init(struct device *dev);
-void of_reserved_mem_device_release(struct device *dev);
-void early_init_dt_scan_reserved_mem(void);
-#else
-static inline void of_reserved_mem_device_init(struct device *dev) { }
-static inline void of_reserved_mem_device_release(struct device *dev) { }
-static inline void early_init_dt_scan_reserved_mem(void) { }
-#endif
-
-#endif /* __OF_RESERVED_MEM_H */
diff --git a/include/linux/page-flags-layout.h b/include/linux/page-flags-layout.h
index 93506a1..da52366 100644
--- a/include/linux/page-flags-layout.h
+++ b/include/linux/page-flags-layout.h
@@ -38,10 +38,10 @@
  * The last is when there is insufficient space in page->flags and a separate
  * lookup is necessary.
  *
- * No sparsemem or sparsemem vmemmap: |       NODE     | ZONE |          ... | FLAGS |
- *         " plus space for last_nid: |       NODE     | ZONE | LAST_NID ... | FLAGS |
- * classic sparse with space for node:| SECTION | NODE | ZONE |          ... | FLAGS |
- *         " plus space for last_nid: | SECTION | NODE | ZONE | LAST_NID ... | FLAGS |
+ * No sparsemem or sparsemem vmemmap: |       NODE     | ZONE |             ... | FLAGS |
+ *      " plus space for last_cpupid: |       NODE     | ZONE | LAST_CPUPID ... | FLAGS |
+ * classic sparse with space for node:| SECTION | NODE | ZONE |             ... | FLAGS |
+ *      " plus space for last_cpupid: | SECTION | NODE | ZONE | LAST_CPUPID ... | FLAGS |
  * classic sparse no space for node:  | SECTION |     ZONE    | ... | FLAGS |
  */
 #if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
@@ -62,15 +62,21 @@
 #endif
 
 #ifdef CONFIG_NUMA_BALANCING
-#define LAST_NID_SHIFT NODES_SHIFT
+#define LAST__PID_SHIFT 8
+#define LAST__PID_MASK  ((1 << LAST__PID_SHIFT)-1)
+
+#define LAST__CPU_SHIFT NR_CPUS_BITS
+#define LAST__CPU_MASK  ((1 << LAST__CPU_SHIFT)-1)
+
+#define LAST_CPUPID_SHIFT (LAST__PID_SHIFT+LAST__CPU_SHIFT)
 #else
-#define LAST_NID_SHIFT 0
+#define LAST_CPUPID_SHIFT 0
 #endif
 
-#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT+LAST_NID_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS
-#define LAST_NID_WIDTH LAST_NID_SHIFT
+#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT+LAST_CPUPID_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS
+#define LAST_CPUPID_WIDTH LAST_CPUPID_SHIFT
 #else
-#define LAST_NID_WIDTH 0
+#define LAST_CPUPID_WIDTH 0
 #endif
 
 /*
@@ -81,8 +87,8 @@
 #define NODE_NOT_IN_PAGE_FLAGS
 #endif
 
-#if defined(CONFIG_NUMA_BALANCING) && LAST_NID_WIDTH == 0
-#define LAST_NID_NOT_IN_PAGE_FLAGS
+#if defined(CONFIG_NUMA_BALANCING) && LAST_CPUPID_WIDTH == 0
+#define LAST_CPUPID_NOT_IN_PAGE_FLAGS
 #endif
 
 #endif /* _LINUX_PAGE_FLAGS_LAYOUT */
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 6d53675..98ada58 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -329,7 +329,9 @@
  * System with lots of page flags available. This allows separate
  * flags for PageHead() and PageTail() checks of compound pages so that bit
  * tests can be used in performance sensitive paths. PageCompound is
- * generally not used in hot code paths.
+ * generally not used in hot code paths except arch/powerpc/mm/init_64.c
+ * and arch/powerpc/kvm/book3s_64_vio_hv.c which use it to detect huge pages
+ * and avoid handling those in real mode.
  */
 __PAGEFLAG(Head, head) CLEARPAGEFLAG(Head, head)
 __PAGEFLAG(Tail, tail)
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index cc88172..9e4761c 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -332,7 +332,7 @@
 #endif
 
 #ifndef this_cpu_sub
-# define this_cpu_sub(pcp, val)		this_cpu_add((pcp), -(val))
+# define this_cpu_sub(pcp, val)		this_cpu_add((pcp), -(typeof(pcp))(val))
 #endif
 
 #ifndef this_cpu_inc
@@ -375,22 +375,6 @@
 # define this_cpu_or(pcp, val)		__pcpu_size_call(this_cpu_or_, (pcp), (val))
 #endif
 
-#ifndef this_cpu_xor
-# ifndef this_cpu_xor_1
-#  define this_cpu_xor_1(pcp, val)	_this_cpu_generic_to_op((pcp), (val), ^=)
-# endif
-# ifndef this_cpu_xor_2
-#  define this_cpu_xor_2(pcp, val)	_this_cpu_generic_to_op((pcp), (val), ^=)
-# endif
-# ifndef this_cpu_xor_4
-#  define this_cpu_xor_4(pcp, val)	_this_cpu_generic_to_op((pcp), (val), ^=)
-# endif
-# ifndef this_cpu_xor_8
-#  define this_cpu_xor_8(pcp, val)	_this_cpu_generic_to_op((pcp), (val), ^=)
-# endif
-# define this_cpu_xor(pcp, val)		__pcpu_size_call(this_cpu_or_, (pcp), (val))
-#endif
-
 #define _this_cpu_generic_add_return(pcp, val)				\
 ({									\
 	typeof(pcp) ret__;						\
@@ -418,7 +402,7 @@
 # define this_cpu_add_return(pcp, val)	__pcpu_size_call_return2(this_cpu_add_return_, pcp, val)
 #endif
 
-#define this_cpu_sub_return(pcp, val)	this_cpu_add_return(pcp, -(val))
+#define this_cpu_sub_return(pcp, val)	this_cpu_add_return(pcp, -(typeof(pcp))(val))
 #define this_cpu_inc_return(pcp)	this_cpu_add_return(pcp, 1)
 #define this_cpu_dec_return(pcp)	this_cpu_add_return(pcp, -1)
 
@@ -586,7 +570,7 @@
 #endif
 
 #ifndef __this_cpu_sub
-# define __this_cpu_sub(pcp, val)	__this_cpu_add((pcp), -(val))
+# define __this_cpu_sub(pcp, val)	__this_cpu_add((pcp), -(typeof(pcp))(val))
 #endif
 
 #ifndef __this_cpu_inc
@@ -629,22 +613,6 @@
 # define __this_cpu_or(pcp, val)	__pcpu_size_call(__this_cpu_or_, (pcp), (val))
 #endif
 
-#ifndef __this_cpu_xor
-# ifndef __this_cpu_xor_1
-#  define __this_cpu_xor_1(pcp, val)	__this_cpu_generic_to_op((pcp), (val), ^=)
-# endif
-# ifndef __this_cpu_xor_2
-#  define __this_cpu_xor_2(pcp, val)	__this_cpu_generic_to_op((pcp), (val), ^=)
-# endif
-# ifndef __this_cpu_xor_4
-#  define __this_cpu_xor_4(pcp, val)	__this_cpu_generic_to_op((pcp), (val), ^=)
-# endif
-# ifndef __this_cpu_xor_8
-#  define __this_cpu_xor_8(pcp, val)	__this_cpu_generic_to_op((pcp), (val), ^=)
-# endif
-# define __this_cpu_xor(pcp, val)	__pcpu_size_call(__this_cpu_xor_, (pcp), (val))
-#endif
-
 #define __this_cpu_generic_add_return(pcp, val)				\
 ({									\
 	__this_cpu_add(pcp, val);					\
@@ -668,7 +636,7 @@
 	__pcpu_size_call_return2(__this_cpu_add_return_, pcp, val)
 #endif
 
-#define __this_cpu_sub_return(pcp, val)	__this_cpu_add_return(pcp, -(val))
+#define __this_cpu_sub_return(pcp, val)	__this_cpu_add_return(pcp, -(typeof(pcp))(val))
 #define __this_cpu_inc_return(pcp)	__this_cpu_add_return(pcp, 1)
 #define __this_cpu_dec_return(pcp)	__this_cpu_add_return(pcp, -1)
 
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 866e85c..2e069d1 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -294,9 +294,31 @@
  */
 struct perf_event {
 #ifdef CONFIG_PERF_EVENTS
-	struct list_head		group_entry;
+	/*
+	 * entry onto perf_event_context::event_list;
+	 *   modifications require ctx->lock
+	 *   RCU safe iterations.
+	 */
 	struct list_head		event_entry;
+
+	/*
+	 * XXX: group_entry and sibling_list should be mutually exclusive;
+	 * either you're a sibling on a group, or you're the group leader.
+	 * Rework the code to always use the same list element.
+	 *
+	 * Locked for modification by both ctx->mutex and ctx->lock; holding
+	 * either sufficies for read.
+	 */
+	struct list_head		group_entry;
 	struct list_head		sibling_list;
+
+	/*
+	 * We need storage to track the entries in perf_pmu_migrate_context; we
+	 * cannot use the event_entry because of RCU and we want to keep the
+	 * group in tact which avoids us using the other two entries.
+	 */
+	struct list_head		migrate_entry;
+
 	struct hlist_node		hlist_entry;
 	int				nr_siblings;
 	int				group_flags;
@@ -562,6 +584,10 @@
 	struct perf_regs_user		regs_user;
 	u64				stack_user_size;
 	u64				weight;
+	/*
+	 * Transaction flags for abort events:
+	 */
+	u64				txn;
 };
 
 static inline void perf_sample_data_init(struct perf_sample_data *data,
@@ -577,6 +603,7 @@
 	data->stack_user_size = 0;
 	data->weight = 0;
 	data->data_src.val = 0;
+	data->txn = 0;
 }
 
 extern void perf_output_sample(struct perf_output_handle *handle,
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
new file mode 100644
index 0000000..6d72269
--- /dev/null
+++ b/include/linux/phy/phy.h
@@ -0,0 +1,270 @@
+/*
+ * phy.h -- generic phy header file
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Author: Kishon Vijay Abraham I <kishon@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 __DRIVERS_PHY_H
+#define __DRIVERS_PHY_H
+
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/device.h>
+#include <linux/pm_runtime.h>
+
+struct phy;
+
+/**
+ * struct phy_ops - set of function pointers for performing phy operations
+ * @init: operation to be performed for initializing phy
+ * @exit: operation to be performed while exiting
+ * @power_on: powering on the phy
+ * @power_off: powering off the phy
+ * @owner: the module owner containing the ops
+ */
+struct phy_ops {
+	int	(*init)(struct phy *phy);
+	int	(*exit)(struct phy *phy);
+	int	(*power_on)(struct phy *phy);
+	int	(*power_off)(struct phy *phy);
+	struct module *owner;
+};
+
+/**
+ * struct phy - represents the phy device
+ * @dev: phy device
+ * @id: id of the phy device
+ * @ops: function pointers for performing phy operations
+ * @init_data: list of PHY consumers (non-dt only)
+ * @mutex: mutex to protect phy_ops
+ * @init_count: used to protect when the PHY is used by multiple consumers
+ * @power_count: used to protect when the PHY is used by multiple consumers
+ */
+struct phy {
+	struct device		dev;
+	int			id;
+	const struct phy_ops	*ops;
+	struct phy_init_data	*init_data;
+	struct mutex		mutex;
+	int			init_count;
+	int			power_count;
+};
+
+/**
+ * struct phy_provider - represents the phy provider
+ * @dev: phy provider device
+ * @owner: the module owner having of_xlate
+ * @of_xlate: function pointer to obtain phy instance from phy pointer
+ * @list: to maintain a linked list of PHY providers
+ */
+struct phy_provider {
+	struct device		*dev;
+	struct module		*owner;
+	struct list_head	list;
+	struct phy * (*of_xlate)(struct device *dev,
+		struct of_phandle_args *args);
+};
+
+/**
+ * struct phy_consumer - represents the phy consumer
+ * @dev_name: the device name of the controller that will use this PHY device
+ * @port: name given to the consumer port
+ */
+struct phy_consumer {
+	const char *dev_name;
+	const char *port;
+};
+
+/**
+ * struct phy_init_data - contains the list of PHY consumers
+ * @num_consumers: number of consumers for this PHY device
+ * @consumers: list of PHY consumers
+ */
+struct phy_init_data {
+	unsigned int num_consumers;
+	struct phy_consumer *consumers;
+};
+
+#define PHY_CONSUMER(_dev_name, _port)				\
+{								\
+	.dev_name	= _dev_name,				\
+	.port		= _port,				\
+}
+
+#define	to_phy(dev)	(container_of((dev), struct phy, dev))
+
+#define	of_phy_provider_register(dev, xlate)	\
+	__of_phy_provider_register((dev), THIS_MODULE, (xlate))
+
+#define	devm_of_phy_provider_register(dev, xlate)	\
+	__devm_of_phy_provider_register((dev), THIS_MODULE, (xlate))
+
+static inline void phy_set_drvdata(struct phy *phy, void *data)
+{
+	dev_set_drvdata(&phy->dev, data);
+}
+
+static inline void *phy_get_drvdata(struct phy *phy)
+{
+	return dev_get_drvdata(&phy->dev);
+}
+
+#if IS_ENABLED(CONFIG_GENERIC_PHY)
+int phy_pm_runtime_get(struct phy *phy);
+int phy_pm_runtime_get_sync(struct phy *phy);
+int phy_pm_runtime_put(struct phy *phy);
+int phy_pm_runtime_put_sync(struct phy *phy);
+void phy_pm_runtime_allow(struct phy *phy);
+void phy_pm_runtime_forbid(struct phy *phy);
+int phy_init(struct phy *phy);
+int phy_exit(struct phy *phy);
+int phy_power_on(struct phy *phy);
+int phy_power_off(struct phy *phy);
+struct phy *phy_get(struct device *dev, const char *string);
+struct phy *devm_phy_get(struct device *dev, const char *string);
+void phy_put(struct phy *phy);
+void devm_phy_put(struct device *dev, struct phy *phy);
+struct phy *of_phy_simple_xlate(struct device *dev,
+	struct of_phandle_args *args);
+struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
+	struct phy_init_data *init_data);
+struct phy *devm_phy_create(struct device *dev,
+	const struct phy_ops *ops, struct phy_init_data *init_data);
+void phy_destroy(struct phy *phy);
+void devm_phy_destroy(struct device *dev, struct phy *phy);
+struct phy_provider *__of_phy_provider_register(struct device *dev,
+	struct module *owner, struct phy * (*of_xlate)(struct device *dev,
+	struct of_phandle_args *args));
+struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
+	struct module *owner, struct phy * (*of_xlate)(struct device *dev,
+	struct of_phandle_args *args));
+void of_phy_provider_unregister(struct phy_provider *phy_provider);
+void devm_of_phy_provider_unregister(struct device *dev,
+	struct phy_provider *phy_provider);
+#else
+static inline int phy_pm_runtime_get(struct phy *phy)
+{
+	return -ENOSYS;
+}
+
+static inline int phy_pm_runtime_get_sync(struct phy *phy)
+{
+	return -ENOSYS;
+}
+
+static inline int phy_pm_runtime_put(struct phy *phy)
+{
+	return -ENOSYS;
+}
+
+static inline int phy_pm_runtime_put_sync(struct phy *phy)
+{
+	return -ENOSYS;
+}
+
+static inline void phy_pm_runtime_allow(struct phy *phy)
+{
+	return;
+}
+
+static inline void phy_pm_runtime_forbid(struct phy *phy)
+{
+	return;
+}
+
+static inline int phy_init(struct phy *phy)
+{
+	return -ENOSYS;
+}
+
+static inline int phy_exit(struct phy *phy)
+{
+	return -ENOSYS;
+}
+
+static inline int phy_power_on(struct phy *phy)
+{
+	return -ENOSYS;
+}
+
+static inline int phy_power_off(struct phy *phy)
+{
+	return -ENOSYS;
+}
+
+static inline struct phy *phy_get(struct device *dev, const char *string)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline struct phy *devm_phy_get(struct device *dev, const char *string)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline void phy_put(struct phy *phy)
+{
+}
+
+static inline void devm_phy_put(struct device *dev, struct phy *phy)
+{
+}
+
+static inline struct phy *of_phy_simple_xlate(struct device *dev,
+	struct of_phandle_args *args)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline struct phy *phy_create(struct device *dev,
+	const struct phy_ops *ops, struct phy_init_data *init_data)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline struct phy *devm_phy_create(struct device *dev,
+	const struct phy_ops *ops, struct phy_init_data *init_data)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline void phy_destroy(struct phy *phy)
+{
+}
+
+static inline void devm_phy_destroy(struct device *dev, struct phy *phy)
+{
+}
+
+static inline struct phy_provider *__of_phy_provider_register(
+	struct device *dev, struct module *owner, struct phy * (*of_xlate)(
+	struct device *dev, struct of_phandle_args *args))
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline struct phy_provider *__devm_of_phy_provider_register(struct device
+	*dev, struct module *owner, struct phy * (*of_xlate)(struct device *dev,
+	struct of_phandle_args *args))
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline void of_phy_provider_unregister(struct phy_provider *phy_provider)
+{
+}
+
+static inline void devm_of_phy_provider_unregister(struct device *dev,
+	struct phy_provider *phy_provider)
+{
+}
+#endif
+
+#endif /* __DRIVERS_PHY_H */
diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
index 5979147..fefb886 100644
--- a/include/linux/pinctrl/pinctrl.h
+++ b/include/linux/pinctrl/pinctrl.h
@@ -144,6 +144,9 @@
 extern struct pinctrl_gpio_range *
 pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev,
 				 unsigned int pin);
+extern int pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+				const char *pin_group, const unsigned **pins,
+				unsigned *num_pins);
 
 #ifdef CONFIG_OF
 extern struct pinctrl_dev *of_pinctrl_get(struct device_node *np);
diff --git a/include/linux/platform_data/clk-nomadik.h b/include/linux/platform_data/clk-nomadik.h
deleted file mode 100644
index 5713c87..0000000
--- a/include/linux/platform_data/clk-nomadik.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* Minimal platform data header */
-void nomadik_clk_init(void);
diff --git a/include/linux/platform_data/clk-ux500.h b/include/linux/platform_data/clk-ux500.h
index 9d98f3a..97baf83 100644
--- a/include/linux/platform_data/clk-ux500.h
+++ b/include/linux/platform_data/clk-ux500.h
@@ -10,6 +10,9 @@
 #ifndef __CLK_UX500_H
 #define __CLK_UX500_H
 
+void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
+		       u32 clkrst5_base, u32 clkrst6_base);
+
 void u8500_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
 		    u32 clkrst5_base, u32 clkrst6_base);
 void u9540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h
index 8db5ae0..689a856 100644
--- a/include/linux/platform_data/davinci_asp.h
+++ b/include/linux/platform_data/davinci_asp.h
@@ -84,6 +84,8 @@
 	u8 version;
 	u8 txnumevt;
 	u8 rxnumevt;
+	int tx_dma_channel;
+	int rx_dma_channel;
 };
 
 enum {
diff --git a/include/linux/platform_data/dma-s3c24xx.h b/include/linux/platform_data/dma-s3c24xx.h
new file mode 100644
index 0000000..89ba1b0
--- /dev/null
+++ b/include/linux/platform_data/dma-s3c24xx.h
@@ -0,0 +1,46 @@
+/*
+ * S3C24XX DMA handling
+ *
+ * Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+/* Helper to encode the source selection constraints for early s3c socs. */
+#define S3C24XX_DMA_CHANREQ(src, chan)	((BIT(3) | src) << chan * 4)
+
+enum s3c24xx_dma_bus {
+	S3C24XX_DMA_APB,
+	S3C24XX_DMA_AHB,
+};
+
+/**
+ * @bus: on which bus does the peripheral reside - AHB or APB.
+ * @handshake: is a handshake with the peripheral necessary
+ * @chansel: channel selection information, depending on variant; reqsel for
+ *	     s3c2443 and later and channel-selection map for earlier SoCs
+ *	     see CHANSEL doc in s3c2443-dma.c
+ */
+struct s3c24xx_dma_channel {
+	enum s3c24xx_dma_bus bus;
+	bool handshake;
+	u16 chansel;
+};
+
+/**
+ * struct s3c24xx_dma_platdata - platform specific settings
+ * @num_phy_channels: number of physical channels
+ * @channels: array of virtual channel descriptions
+ * @num_channels: number of virtual channels
+ */
+struct s3c24xx_dma_platdata {
+	int num_phy_channels;
+	struct s3c24xx_dma_channel *channels;
+	int num_channels;
+};
+
+struct dma_chan;
+bool s3c24xx_dma_filter(struct dma_chan *chan, void *param);
diff --git a/include/linux/platform_data/gpio-davinci.h b/include/linux/platform_data/gpio-davinci.h
new file mode 100644
index 0000000..6efd202
--- /dev/null
+++ b/include/linux/platform_data/gpio-davinci.h
@@ -0,0 +1,60 @@
+/*
+ * DaVinci GPIO Platform Related Defines
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DAVINCI_GPIO_PLATFORM_H
+#define __DAVINCI_GPIO_PLATFORM_H
+
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+#include <asm-generic/gpio.h>
+
+enum davinci_gpio_type {
+	GPIO_TYPE_TNETV107X = 0,
+};
+
+struct davinci_gpio_platform_data {
+	u32	ngpio;
+	u32	gpio_unbanked;
+	u32	intc_irq_num;
+};
+
+
+struct davinci_gpio_controller {
+	struct gpio_chip	chip;
+	int			irq_base;
+	/* Serialize access to GPIO registers */
+	spinlock_t		lock;
+	void __iomem		*regs;
+	void __iomem		*set_data;
+	void __iomem		*clr_data;
+	void __iomem		*in_data;
+	int			gpio_unbanked;
+	unsigned		gpio_irq;
+};
+
+/*
+ * basic gpio routines
+ */
+#define	GPIO(X)		(X)	/* 0 <= X <= (DAVINCI_N_GPIO - 1) */
+
+/* Convert GPIO signal to GPIO pin number */
+#define GPIO_TO_PIN(bank, gpio)	(16 * (bank) + (gpio))
+
+static inline u32 __gpio_mask(unsigned gpio)
+{
+	return 1 << (gpio % 32);
+}
+#endif
diff --git a/include/linux/platform_data/leds-lp55xx.h b/include/linux/platform_data/leds-lp55xx.h
index 51a2ff5..624ff9e 100644
--- a/include/linux/platform_data/leds-lp55xx.h
+++ b/include/linux/platform_data/leds-lp55xx.h
@@ -22,6 +22,7 @@
 
 struct lp55xx_led_config {
 	const char *name;
+	const char *default_trigger;
 	u8 chan_nr;
 	u8 led_current; /* mA x10, 0 if led is not connected */
 	u8 max_current;
@@ -66,10 +67,8 @@
 	/* Clock configuration */
 	u8 clock_mode;
 
-	/* Platform specific functions */
-	int (*setup_resources)(void);
-	void (*release_resources)(void);
-	void (*enable)(bool state);
+	/* optional enable GPIO */
+	int enable_gpio;
 
 	/* Predefined pattern data */
 	struct lp55xx_predef_pattern *patterns;
diff --git a/include/linux/platform_data/leds-pca9685.h b/include/linux/platform_data/leds-pca9685.h
new file mode 100644
index 0000000..778e9e4
--- /dev/null
+++ b/include/linux/platform_data/leds-pca9685.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2013 Maximilian Güntner <maximilian.guentner@gmail.com>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * Based on leds-pca963x.h by Peter Meerwald <p.meerwald@bct-electronic.com>
+ *
+ * LED driver for the NXP PCA9685 PWM chip
+ *
+ */
+
+#ifndef __LINUX_PCA9685_H
+#define __LINUX_PCA9685_H
+
+#include <linux/leds.h>
+
+enum pca9685_outdrv {
+	PCA9685_OPEN_DRAIN,
+	PCA9685_TOTEM_POLE,
+};
+
+enum pca9685_inverted {
+	PCA9685_NOT_INVERTED,
+	PCA9685_INVERTED,
+};
+
+struct pca9685_platform_data {
+	struct led_platform_data leds;
+	enum pca9685_outdrv outdrv;
+	enum pca9685_inverted inverted;
+};
+
+#endif /* __LINUX_PCA9685_H */
diff --git a/include/linux/platform_data/mipi-csis.h b/include/linux/platform_data/mipi-csis.h
index bf34e17..c2fd902 100644
--- a/include/linux/platform_data/mipi-csis.h
+++ b/include/linux/platform_data/mipi-csis.h
@@ -25,13 +25,4 @@
 	u8 hs_settle;
 };
 
-/**
- * s5p_csis_phy_enable - global MIPI-CSI receiver D-PHY control
- * @id:     MIPI-CSIS harware instance index (0...1)
- * @on:     true to enable D-PHY and deassert its reset
- *          false to disable D-PHY
- * @return: 0 on success, or negative error code on failure
- */
-int s5p_csis_phy_enable(int id, bool on);
-
 #endif /* __PLAT_SAMSUNG_MIPI_CSIS_H_ */
diff --git a/include/linux/platform_data/pinctrl-adi2.h b/include/linux/platform_data/pinctrl-adi2.h
new file mode 100644
index 0000000..8f91300
--- /dev/null
+++ b/include/linux/platform_data/pinctrl-adi2.h
@@ -0,0 +1,40 @@
+/*
+ * Pinctrl Driver for ADI GPIO2 controller
+ *
+ * Copyright 2007-2013 Analog Devices Inc.
+ *
+ * Licensed under the GPLv2 or later
+ */
+
+
+#ifndef PINCTRL_ADI2_H
+#define PINCTRL_ADI2_H
+
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+/**
+ * struct adi_pinctrl_gpio_platform_data - Pinctrl gpio platform data
+ * for ADI GPIO2 device.
+ *
+ * @port_gpio_base: Optional global GPIO index of the GPIO bank.
+ *                 0 means driver decides.
+ * @port_pin_base: Pin index of the pin controller device.
+ * @port_width: PIN number of the GPIO bank device
+ * @pint_id: GPIO PINT device id that this GPIO bank should map to.
+ * @pint_assign: The 32-bit GPIO PINT registers can be divided into 2 parts. A
+ *               GPIO bank can be mapped into either low 16 bits[0] or high 16
+ *               bits[1] of each PINT register.
+ * @pint_map: GIOP bank mapping code in PINT device
+ */
+struct adi_pinctrl_gpio_platform_data {
+	unsigned int port_gpio_base;
+	unsigned int port_pin_base;
+	unsigned int port_width;
+	u8 pinctrl_id;
+	u8 pint_id;
+	bool pint_assign;
+	u8 pint_map;
+};
+
+#endif
diff --git a/include/linux/platform_data/pinctrl-single.h b/include/linux/platform_data/pinctrl-single.h
new file mode 100644
index 0000000..72eacda
--- /dev/null
+++ b/include/linux/platform_data/pinctrl-single.h
@@ -0,0 +1,12 @@
+/**
+ * irq:		optional wake-up interrupt
+ * rearm:	optional soc specific rearm function
+ *
+ * Note that the irq and rearm setup should come from device
+ * tree except for omap where there are still some dependencies
+ * to the legacy PRM code.
+ */
+struct pcs_pdata {
+	int irq;
+	void (*rearm)(void);
+};
diff --git a/include/linux/platform_data/usb-ehci-s5p.h b/include/linux/platform_data/usb-ehci-s5p.h
deleted file mode 100644
index 5f28cae..0000000
--- a/include/linux/platform_data/usb-ehci-s5p.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#ifndef __PLAT_SAMSUNG_EHCI_H
-#define __PLAT_SAMSUNG_EHCI_H __FILE__
-
-struct s5p_ehci_platdata {
-	int (*phy_init)(struct platform_device *pdev, int type);
-	int (*phy_exit)(struct platform_device *pdev, int type);
-};
-
-extern void s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd);
-
-#endif /* __PLAT_SAMSUNG_EHCI_H */
diff --git a/include/linux/platform_data/usb-ohci-exynos.h b/include/linux/platform_data/usb-ohci-exynos.h
deleted file mode 100644
index c256c59..0000000
--- a/include/linux/platform_data/usb-ohci-exynos.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- *		http://www.samsung.com/
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#ifndef __MACH_EXYNOS_OHCI_H
-#define __MACH_EXYNOS_OHCI_H
-
-struct exynos4_ohci_platdata {
-	int (*phy_init)(struct platform_device *pdev, int type);
-	int (*phy_exit)(struct platform_device *pdev, int type);
-};
-
-extern void exynos4_ohci_set_platdata(struct exynos4_ohci_platdata *pd);
-
-#endif /* __MACH_EXYNOS_OHCI_H */
diff --git a/include/linux/platform_data/usb-rcar-gen2-phy.h b/include/linux/platform_data/usb-rcar-gen2-phy.h
new file mode 100644
index 0000000..dd3ba46
--- /dev/null
+++ b/include/linux/platform_data/usb-rcar-gen2-phy.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Cogent Embedded, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __USB_RCAR_GEN2_PHY_H
+#define __USB_RCAR_GEN2_PHY_H
+
+#include <linux/types.h>
+
+struct rcar_gen2_phy_platform_data {
+	/* USB channel 0 configuration */
+	bool chan0_pci:1;	/* true: PCI USB host 0, false: USBHS */
+	/* USB channel 2 configuration */
+	bool chan2_pci:1;	/* true: PCI USB host 2, false: USBSS */
+};
+
+#endif
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index ce8e4ff..16f6654 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -178,6 +178,7 @@
 	int (*resume)(struct platform_device *);
 	struct device_driver driver;
 	const struct platform_device_id *id_table;
+	bool prevent_deferred_probe;
 };
 
 #define to_platform_driver(drv)	(container_of((drv), struct platform_driver, \
diff --git a/include/linux/preempt.h b/include/linux/preempt.h
index f5d4723..a3d9dc8 100644
--- a/include/linux/preempt.h
+++ b/include/linux/preempt.h
@@ -6,106 +6,95 @@
  * preempt_count (used for kernel preemption, interrupt count, etc.)
  */
 
-#include <linux/thread_info.h>
 #include <linux/linkage.h>
 #include <linux/list.h>
 
+/*
+ * We use the MSB mostly because its available; see <linux/preempt_mask.h> for
+ * the other bits -- can't include that header due to inclusion hell.
+ */
+#define PREEMPT_NEED_RESCHED	0x80000000
+
+#include <asm/preempt.h>
+
 #if defined(CONFIG_DEBUG_PREEMPT) || defined(CONFIG_PREEMPT_TRACER)
-  extern void add_preempt_count(int val);
-  extern void sub_preempt_count(int val);
+extern void preempt_count_add(int val);
+extern void preempt_count_sub(int val);
+#define preempt_count_dec_and_test() ({ preempt_count_sub(1); should_resched(); })
 #else
-# define add_preempt_count(val)	do { preempt_count() += (val); } while (0)
-# define sub_preempt_count(val)	do { preempt_count() -= (val); } while (0)
+#define preempt_count_add(val)	__preempt_count_add(val)
+#define preempt_count_sub(val)	__preempt_count_sub(val)
+#define preempt_count_dec_and_test() __preempt_count_dec_and_test()
 #endif
 
-#define inc_preempt_count() add_preempt_count(1)
-#define dec_preempt_count() sub_preempt_count(1)
+#define __preempt_count_inc() __preempt_count_add(1)
+#define __preempt_count_dec() __preempt_count_sub(1)
 
-#define preempt_count()	(current_thread_info()->preempt_count)
-
-#ifdef CONFIG_PREEMPT
-
-asmlinkage void preempt_schedule(void);
-
-#define preempt_check_resched() \
-do { \
-	if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \
-		preempt_schedule(); \
-} while (0)
-
-#ifdef CONFIG_CONTEXT_TRACKING
-
-void preempt_schedule_context(void);
-
-#define preempt_check_resched_context() \
-do { \
-	if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \
-		preempt_schedule_context(); \
-} while (0)
-#else
-
-#define preempt_check_resched_context() preempt_check_resched()
-
-#endif /* CONFIG_CONTEXT_TRACKING */
-
-#else /* !CONFIG_PREEMPT */
-
-#define preempt_check_resched()		do { } while (0)
-#define preempt_check_resched_context()	do { } while (0)
-
-#endif /* CONFIG_PREEMPT */
-
+#define preempt_count_inc() preempt_count_add(1)
+#define preempt_count_dec() preempt_count_sub(1)
 
 #ifdef CONFIG_PREEMPT_COUNT
 
 #define preempt_disable() \
 do { \
-	inc_preempt_count(); \
+	preempt_count_inc(); \
 	barrier(); \
 } while (0)
 
 #define sched_preempt_enable_no_resched() \
 do { \
 	barrier(); \
-	dec_preempt_count(); \
+	preempt_count_dec(); \
 } while (0)
 
-#define preempt_enable_no_resched()	sched_preempt_enable_no_resched()
+#define preempt_enable_no_resched() sched_preempt_enable_no_resched()
 
+#ifdef CONFIG_PREEMPT
 #define preempt_enable() \
 do { \
-	preempt_enable_no_resched(); \
 	barrier(); \
-	preempt_check_resched(); \
+	if (unlikely(preempt_count_dec_and_test())) \
+		__preempt_schedule(); \
 } while (0)
 
-/* For debugging and tracer internals only! */
-#define add_preempt_count_notrace(val)			\
-	do { preempt_count() += (val); } while (0)
-#define sub_preempt_count_notrace(val)			\
-	do { preempt_count() -= (val); } while (0)
-#define inc_preempt_count_notrace() add_preempt_count_notrace(1)
-#define dec_preempt_count_notrace() sub_preempt_count_notrace(1)
+#define preempt_check_resched() \
+do { \
+	if (should_resched()) \
+		__preempt_schedule(); \
+} while (0)
+
+#else
+#define preempt_enable() preempt_enable_no_resched()
+#define preempt_check_resched() do { } while (0)
+#endif
 
 #define preempt_disable_notrace() \
 do { \
-	inc_preempt_count_notrace(); \
+	__preempt_count_inc(); \
 	barrier(); \
 } while (0)
 
 #define preempt_enable_no_resched_notrace() \
 do { \
 	barrier(); \
-	dec_preempt_count_notrace(); \
+	__preempt_count_dec(); \
 } while (0)
 
-/* preempt_check_resched is OK to trace */
+#ifdef CONFIG_PREEMPT
+
+#ifndef CONFIG_CONTEXT_TRACKING
+#define __preempt_schedule_context() __preempt_schedule()
+#endif
+
 #define preempt_enable_notrace() \
 do { \
-	preempt_enable_no_resched_notrace(); \
 	barrier(); \
-	preempt_check_resched_context(); \
+	if (unlikely(__preempt_count_dec_and_test())) \
+		__preempt_schedule_context(); \
 } while (0)
+#else
+#define preempt_enable_notrace() preempt_enable_no_resched_notrace()
+#endif
 
 #else /* !CONFIG_PREEMPT_COUNT */
 
@@ -115,10 +104,11 @@
  * that can cause faults and scheduling migrate into our preempt-protected
  * region.
  */
-#define preempt_disable()		barrier()
+#define preempt_disable()			barrier()
 #define sched_preempt_enable_no_resched()	barrier()
-#define preempt_enable_no_resched()	barrier()
-#define preempt_enable()		barrier()
+#define preempt_enable_no_resched()		barrier()
+#define preempt_enable()			barrier()
+#define preempt_check_resched()			do { } while (0)
 
 #define preempt_disable_notrace()		barrier()
 #define preempt_enable_no_resched_notrace()	barrier()
diff --git a/include/linux/printk.h b/include/linux/printk.h
index e6131a78..6949258 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -233,6 +233,8 @@
 	no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
 #endif
 
+#include <linux/dynamic_debug.h>
+
 /* If you are writing a driver, please use dev_dbg instead */
 #if defined(CONFIG_DYNAMIC_DEBUG)
 /* dynamic_pr_debug() uses pr_fmt() internally so we don't need it here */
@@ -343,7 +345,19 @@
 #endif
 
 /* If you are writing a driver, please use dev_dbg instead */
-#if defined(DEBUG)
+#if defined(CONFIG_DYNAMIC_DEBUG)
+/* descriptor check is first to prevent flooding with "callbacks suppressed" */
+#define pr_debug_ratelimited(fmt, ...)					\
+do {									\
+	static DEFINE_RATELIMIT_STATE(_rs,				\
+				      DEFAULT_RATELIMIT_INTERVAL,	\
+				      DEFAULT_RATELIMIT_BURST);		\
+	DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt);			\
+	if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT) &&	\
+	    __ratelimit(&_rs))						\
+		__dynamic_pr_debug(&descriptor, fmt, ##__VA_ARGS__);	\
+} while (0)
+#elif defined(DEBUG)
 #define pr_debug_ratelimited(fmt, ...)					\
 	printk_ratelimited(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
 #else
diff --git a/include/linux/random.h b/include/linux/random.h
index 3b9377d..6312dd9 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -17,6 +17,7 @@
 extern void get_random_bytes(void *buf, int nbytes);
 extern void get_random_bytes_arch(void *buf, int nbytes);
 void generate_random_uuid(unsigned char uuid_out[16]);
+extern int random_int_secret_init(void);
 
 #ifndef MODULE
 extern const struct file_operations random_fops, urandom_fops;
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index 4106721..45a0a9e 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -19,6 +19,21 @@
  */
 
 /*
+ * INIT_LIST_HEAD_RCU - Initialize a list_head visible to RCU readers
+ * @list: list to be initialized
+ *
+ * You should instead use INIT_LIST_HEAD() for normal initialization and
+ * cleanup tasks, when readers have no access to the list being initialized.
+ * However, if the list being initialized is visible to readers, you
+ * need to keep the compiler from being too mischievous.
+ */
+static inline void INIT_LIST_HEAD_RCU(struct list_head *list)
+{
+	ACCESS_ONCE(list->next) = list;
+	ACCESS_ONCE(list->prev) = list;
+}
+
+/*
  * return the ->next pointer of a list_head in an rcu safe
  * way, we must not access it directly
  */
@@ -191,9 +206,13 @@
 	if (list_empty(list))
 		return;
 
-	/* "first" and "last" tracking list, so initialize it. */
+	/*
+	 * "first" and "last" tracking list, so initialize it.  RCU readers
+	 * have access to this list, so we must use INIT_LIST_HEAD_RCU()
+	 * instead of INIT_LIST_HEAD().
+	 */
 
-	INIT_LIST_HEAD(list);
+	INIT_LIST_HEAD_RCU(list);
 
 	/*
 	 * At this point, the list body still points to the source list.
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index f1f1bc3..39cbb88 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -261,6 +261,10 @@
 		rcu_irq_exit(); \
 	} while (0)
 
+#if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP)
+extern bool __rcu_is_watching(void);
+#endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) */
+
 /*
  * Infrastructure to implement the synchronize_() primitives in
  * TREE_RCU and rcu_barrier_() primitives in TINY_RCU.
@@ -297,10 +301,6 @@
 }
 #endif	/* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
 
-#if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_SMP)
-extern int rcu_is_cpu_idle(void);
-#endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_SMP) */
-
 #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU)
 bool rcu_lockdep_current_cpu_online(void);
 #else /* #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU) */
@@ -351,7 +351,7 @@
 {
 	if (!debug_lockdep_rcu_enabled())
 		return 1;
-	if (rcu_is_cpu_idle())
+	if (!rcu_is_watching())
 		return 0;
 	if (!rcu_lockdep_current_cpu_online())
 		return 0;
@@ -402,7 +402,7 @@
 
 	if (!debug_lockdep_rcu_enabled())
 		return 1;
-	if (rcu_is_cpu_idle())
+	if (!rcu_is_watching())
 		return 0;
 	if (!rcu_lockdep_current_cpu_online())
 		return 0;
@@ -771,7 +771,7 @@
 	__rcu_read_lock();
 	__acquire(RCU);
 	rcu_lock_acquire(&rcu_lock_map);
-	rcu_lockdep_assert(!rcu_is_cpu_idle(),
+	rcu_lockdep_assert(rcu_is_watching(),
 			   "rcu_read_lock() used illegally while idle");
 }
 
@@ -792,7 +792,7 @@
  */
 static inline void rcu_read_unlock(void)
 {
-	rcu_lockdep_assert(!rcu_is_cpu_idle(),
+	rcu_lockdep_assert(rcu_is_watching(),
 			   "rcu_read_unlock() used illegally while idle");
 	rcu_lock_release(&rcu_lock_map);
 	__release(RCU);
@@ -821,7 +821,7 @@
 	local_bh_disable();
 	__acquire(RCU_BH);
 	rcu_lock_acquire(&rcu_bh_lock_map);
-	rcu_lockdep_assert(!rcu_is_cpu_idle(),
+	rcu_lockdep_assert(rcu_is_watching(),
 			   "rcu_read_lock_bh() used illegally while idle");
 }
 
@@ -832,7 +832,7 @@
  */
 static inline void rcu_read_unlock_bh(void)
 {
-	rcu_lockdep_assert(!rcu_is_cpu_idle(),
+	rcu_lockdep_assert(rcu_is_watching(),
 			   "rcu_read_unlock_bh() used illegally while idle");
 	rcu_lock_release(&rcu_bh_lock_map);
 	__release(RCU_BH);
@@ -857,7 +857,7 @@
 	preempt_disable();
 	__acquire(RCU_SCHED);
 	rcu_lock_acquire(&rcu_sched_lock_map);
-	rcu_lockdep_assert(!rcu_is_cpu_idle(),
+	rcu_lockdep_assert(rcu_is_watching(),
 			   "rcu_read_lock_sched() used illegally while idle");
 }
 
@@ -875,7 +875,7 @@
  */
 static inline void rcu_read_unlock_sched(void)
 {
-	rcu_lockdep_assert(!rcu_is_cpu_idle(),
+	rcu_lockdep_assert(rcu_is_watching(),
 			   "rcu_read_unlock_sched() used illegally while idle");
 	rcu_lock_release(&rcu_sched_lock_map);
 	__release(RCU_SCHED);
diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h
index e31005e..09ebcbe 100644
--- a/include/linux/rcutiny.h
+++ b/include/linux/rcutiny.h
@@ -132,4 +132,21 @@
 }
 #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
+#if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE)
+
+static inline bool rcu_is_watching(void)
+{
+	return __rcu_is_watching();
+}
+
+#else /* defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) */
+
+static inline bool rcu_is_watching(void)
+{
+	return true;
+}
+
+
+#endif /* #else defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) */
+
 #endif /* __LINUX_RCUTINY_H */
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
index 226169d..4b9c815 100644
--- a/include/linux/rcutree.h
+++ b/include/linux/rcutree.h
@@ -90,4 +90,6 @@
 extern void rcu_scheduler_starting(void);
 extern int rcu_scheduler_active __read_mostly;
 
+extern bool rcu_is_watching(void);
+
 #endif /* __LINUX_RCUTREE_H */
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index a10380b..e559078 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -23,6 +23,7 @@
 struct i2c_client;
 struct irq_domain;
 struct spi_device;
+struct spmi_device;
 struct regmap;
 struct regmap_range_cfg;
 struct regmap_field;
@@ -70,6 +71,8 @@
 	unsigned int range_max;
 };
 
+#define regmap_reg_range(low, high) { .range_min = low, .range_max = high, }
+
 /*
  * A table of ranges including some yes ranges and some no ranges.
  * If a register belongs to a no_range, the corresponding check function
@@ -318,6 +321,8 @@
 			       const struct regmap_config *config);
 struct regmap *regmap_init_spi(struct spi_device *dev,
 			       const struct regmap_config *config);
+struct regmap *regmap_init_spmi(struct spmi_device *dev,
+			       const struct regmap_config *config);
 struct regmap *regmap_init_mmio_clk(struct device *dev, const char *clk_id,
 				    void __iomem *regs,
 				    const struct regmap_config *config);
@@ -330,6 +335,8 @@
 				    const struct regmap_config *config);
 struct regmap *devm_regmap_init_spi(struct spi_device *dev,
 				    const struct regmap_config *config);
+struct regmap *devm_regmap_init_spmi(struct spmi_device *dev,
+				     const struct regmap_config *config);
 struct regmap *devm_regmap_init_mmio_clk(struct device *dev, const char *clk_id,
 					 void __iomem *regs,
 					 const struct regmap_config *config);
@@ -374,10 +381,13 @@
 			const struct regmap_config *config);
 struct regmap *dev_get_regmap(struct device *dev, const char *name);
 int regmap_write(struct regmap *map, unsigned int reg, unsigned int val);
+int regmap_write_async(struct regmap *map, unsigned int reg, unsigned int val);
 int regmap_raw_write(struct regmap *map, unsigned int reg,
 		     const void *val, size_t val_len);
 int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
 			size_t val_count);
+int regmap_multi_reg_write(struct regmap *map, struct reg_default *regs,
+			int num_regs);
 int regmap_raw_write_async(struct regmap *map, unsigned int reg,
 			   const void *val, size_t val_len);
 int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val);
@@ -387,9 +397,14 @@
 		     size_t val_count);
 int regmap_update_bits(struct regmap *map, unsigned int reg,
 		       unsigned int mask, unsigned int val);
+int regmap_update_bits_async(struct regmap *map, unsigned int reg,
+			     unsigned int mask, unsigned int val);
 int regmap_update_bits_check(struct regmap *map, unsigned int reg,
 			     unsigned int mask, unsigned int val,
 			     bool *change);
+int regmap_update_bits_check_async(struct regmap *map, unsigned int reg,
+				   unsigned int mask, unsigned int val,
+				   bool *change);
 int regmap_get_val_bytes(struct regmap *map);
 int regmap_async_complete(struct regmap *map);
 bool regmap_can_raw_write(struct regmap *map);
@@ -425,11 +440,15 @@
  * @reg: Offset of the register within the regmap bank
  * @lsb: lsb of the register field.
  * @reg: msb of the register field.
+ * @id_size: port size if it has some ports
+ * @id_offset: address offset for each ports
  */
 struct reg_field {
 	unsigned int reg;
 	unsigned int lsb;
 	unsigned int msb;
+	unsigned int id_size;
+	unsigned int id_offset;
 };
 
 #define REG_FIELD(_reg, _lsb, _msb) {		\
@@ -448,6 +467,15 @@
 
 int regmap_field_read(struct regmap_field *field, unsigned int *val);
 int regmap_field_write(struct regmap_field *field, unsigned int val);
+int regmap_field_update_bits(struct regmap_field *field,
+			     unsigned int mask, unsigned int val);
+
+int regmap_fields_write(struct regmap_field *field, unsigned int id,
+			unsigned int val);
+int regmap_fields_read(struct regmap_field *field, unsigned int id,
+		       unsigned int *val);
+int regmap_fields_update_bits(struct regmap_field *field,  unsigned int id,
+			      unsigned int mask, unsigned int val);
 
 /**
  * Description of an IRQ for the generic regmap irq_chip.
@@ -527,6 +555,13 @@
 	return -EINVAL;
 }
 
+static inline int regmap_write_async(struct regmap *map, unsigned int reg,
+				     unsigned int val)
+{
+	WARN_ONCE(1, "regmap API is disabled");
+	return -EINVAL;
+}
+
 static inline int regmap_raw_write(struct regmap *map, unsigned int reg,
 				   const void *val, size_t val_len)
 {
@@ -576,6 +611,14 @@
 	return -EINVAL;
 }
 
+static inline int regmap_update_bits_async(struct regmap *map,
+					   unsigned int reg,
+					   unsigned int mask, unsigned int val)
+{
+	WARN_ONCE(1, "regmap API is disabled");
+	return -EINVAL;
+}
+
 static inline int regmap_update_bits_check(struct regmap *map,
 					   unsigned int reg,
 					   unsigned int mask, unsigned int val,
@@ -585,6 +628,16 @@
 	return -EINVAL;
 }
 
+static inline int regmap_update_bits_check_async(struct regmap *map,
+						 unsigned int reg,
+						 unsigned int mask,
+						 unsigned int val,
+						 bool *change)
+{
+	WARN_ONCE(1, "regmap API is disabled");
+	return -EINVAL;
+}
+
 static inline int regmap_get_val_bytes(struct regmap *map)
 {
 	WARN_ONCE(1, "regmap API is disabled");
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index 27be915..e530681 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -146,6 +146,32 @@
 void regulator_put(struct regulator *regulator);
 void devm_regulator_put(struct regulator *regulator);
 
+int regulator_register_supply_alias(struct device *dev, const char *id,
+				    struct device *alias_dev,
+				    const char *alias_id);
+void regulator_unregister_supply_alias(struct device *dev, const char *id);
+
+int regulator_bulk_register_supply_alias(struct device *dev, const char **id,
+					 struct device *alias_dev,
+					 const char **alias_id, int num_id);
+void regulator_bulk_unregister_supply_alias(struct device *dev,
+					    const char **id, int num_id);
+
+int devm_regulator_register_supply_alias(struct device *dev, const char *id,
+					 struct device *alias_dev,
+					 const char *alias_id);
+void devm_regulator_unregister_supply_alias(struct device *dev,
+					    const char *id);
+
+int devm_regulator_bulk_register_supply_alias(struct device *dev,
+					      const char **id,
+					      struct device *alias_dev,
+					      const char **alias_id,
+					      int num_id);
+void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
+						 const char **id,
+						 int num_id);
+
 /* regulator output control and status */
 int __must_check regulator_enable(struct regulator *regulator);
 int regulator_disable(struct regulator *regulator);
@@ -250,6 +276,59 @@
 {
 }
 
+static inline int regulator_register_supply_alias(struct device *dev,
+						  const char *id,
+						  struct device *alias_dev,
+						  const char *alias_id)
+{
+	return 0;
+}
+
+static inline void regulator_unregister_supply_alias(struct device *dev,
+						    const char *id)
+{
+}
+
+static inline int regulator_bulk_register_supply_alias(struct device *dev,
+						       const char **id,
+						       struct device *alias_dev,
+						       const char **alias_id,
+						       int num_id)
+{
+	return 0;
+}
+
+static inline void regulator_bulk_unregister_supply_alias(struct device *dev,
+							  const char **id,
+							  int num_id)
+{
+}
+
+static inline int devm_regulator_register_supply_alias(struct device *dev,
+						       const char *id,
+						       struct device *alias_dev,
+						       const char *alias_id)
+{
+	return 0;
+}
+
+static inline void devm_regulator_unregister_supply_alias(struct device *dev,
+							  const char *id)
+{
+}
+
+static inline int devm_regulator_bulk_register_supply_alias(
+		struct device *dev, const char **id, struct device *alias_dev,
+		const char **alias_id, int num_id)
+{
+	return 0;
+}
+
+static inline void devm_regulator_bulk_unregister_supply_alias(
+		struct device *dev, const char **id, int num_id)
+{
+}
+
 static inline int regulator_enable(struct regulator *regulator)
 {
 	return 0;
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
index 9bdad43..9370e65 100644
--- a/include/linux/regulator/driver.h
+++ b/include/linux/regulator/driver.h
@@ -46,19 +46,26 @@
  * regulator_list_linear_range().
  *
  * @min_uV:  Lowest voltage in range
- * @max_uV:  Highest voltage in range
  * @min_sel: Lowest selector for range
  * @max_sel: Highest selector for range
  * @uV_step: Step size
  */
 struct regulator_linear_range {
 	unsigned int min_uV;
-	unsigned int max_uV;
 	unsigned int min_sel;
 	unsigned int max_sel;
 	unsigned int uV_step;
 };
 
+/* Initialize struct regulator_linear_range */
+#define REGULATOR_LINEAR_RANGE(_min_uV, _min_sel, _max_sel, _step_uV)	\
+{									\
+	.min_uV		= _min_uV,					\
+	.min_sel	= _min_sel,					\
+	.max_sel	= _max_sel,					\
+	.uV_step	= _step_uV,					\
+}
+
 /**
  * struct regulator_ops - regulator operations.
  *
@@ -209,6 +216,7 @@
  * @min_uV: Voltage given by the lowest selector (if linear mapping)
  * @uV_step: Voltage increase with each selector (if linear mapping)
  * @linear_min_sel: Minimal selector for starting linear mapping
+ * @fixed_uV: Fixed voltage of rails.
  * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
  * @volt_table: Voltage mapping table (if table based mapping)
  *
@@ -241,6 +249,7 @@
 	unsigned int min_uV;
 	unsigned int uV_step;
 	unsigned int linear_min_sel;
+	int fixed_uV;
 	unsigned int ramp_delay;
 
 	const struct regulator_linear_range *linear_ranges;
@@ -336,7 +345,12 @@
 struct regulator_dev *
 regulator_register(const struct regulator_desc *regulator_desc,
 		   const struct regulator_config *config);
+struct regulator_dev *
+devm_regulator_register(struct device *dev,
+			const struct regulator_desc *regulator_desc,
+			const struct regulator_config *config);
 void regulator_unregister(struct regulator_dev *rdev);
+void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev);
 
 int regulator_notifier_call_chain(struct regulator_dev *rdev,
 				  unsigned long event, void *data);
diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h
index 999b20c..730e638 100644
--- a/include/linux/regulator/machine.h
+++ b/include/linux/regulator/machine.h
@@ -95,6 +95,7 @@
  * @initial_state: Suspend state to set by default.
  * @initial_mode: Mode to set at startup.
  * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
+ * @enable_time: Turn-on time of the rails (unit: microseconds)
  */
 struct regulation_constraints {
 
@@ -129,6 +130,7 @@
 	unsigned int initial_mode;
 
 	unsigned int ramp_delay;
+	unsigned int enable_time;
 
 	/* constraint flags */
 	unsigned always_on:1;	/* regulator never off when system is on */
@@ -193,15 +195,10 @@
 
 #ifdef CONFIG_REGULATOR
 void regulator_has_full_constraints(void);
-void regulator_use_dummy_regulator(void);
 #else
 static inline void regulator_has_full_constraints(void)
 {
 }
-
-static inline void regulator_use_dummy_regulator(void)
-{
-}
 #endif
 
 #endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 6682da3..045b0d2 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -22,6 +22,7 @@
 #include <linux/errno.h>
 #include <linux/nodemask.h>
 #include <linux/mm_types.h>
+#include <linux/preempt.h>
 
 #include <asm/page.h>
 #include <asm/ptrace.h>
@@ -427,6 +428,14 @@
 		.sum_exec_runtime = 0,				\
 	}
 
+#define PREEMPT_ENABLED		(PREEMPT_NEED_RESCHED)
+
+#ifdef CONFIG_PREEMPT_COUNT
+#define PREEMPT_DISABLED	(1 + PREEMPT_ENABLED)
+#else
+#define PREEMPT_DISABLED	PREEMPT_ENABLED
+#endif
+
 /*
  * Disable preemption until the scheduler is running.
  * Reset by start_kernel()->sched_init()->init_idle().
@@ -434,7 +443,7 @@
  * We include PREEMPT_ACTIVE to avoid cond_resched() from working
  * before the scheduler is active -- see should_resched().
  */
-#define INIT_PREEMPT_COUNT	(1 + PREEMPT_ACTIVE)
+#define INIT_PREEMPT_COUNT	(PREEMPT_DISABLED + PREEMPT_ACTIVE)
 
 /**
  * struct thread_group_cputimer - thread group interval timer counts
@@ -768,6 +777,7 @@
 #define SD_ASYM_PACKING		0x0800  /* Place busy groups earlier in the domain */
 #define SD_PREFER_SIBLING	0x1000	/* Prefer to place tasks in a sibling domain */
 #define SD_OVERLAP		0x2000	/* sched_domains of this level overlap */
+#define SD_NUMA			0x4000	/* cross-node balancing */
 
 extern int __weak arch_sd_sibiling_asym_packing(void);
 
@@ -811,6 +821,10 @@
 
 	u64 last_update;
 
+	/* idle_balance() stats */
+	u64 max_newidle_lb_cost;
+	unsigned long next_decay_max_lb_cost;
+
 #ifdef CONFIG_SCHEDSTATS
 	/* load_balance() stats */
 	unsigned int lb_count[CPU_MAX_IDLE_TYPES];
@@ -1029,6 +1043,8 @@
 	struct task_struct *last_wakee;
 	unsigned long wakee_flips;
 	unsigned long wakee_flip_decay_ts;
+
+	int wake_cpu;
 #endif
 	int on_rq;
 
@@ -1324,10 +1340,41 @@
 #endif
 #ifdef CONFIG_NUMA_BALANCING
 	int numa_scan_seq;
-	int numa_migrate_seq;
 	unsigned int numa_scan_period;
+	unsigned int numa_scan_period_max;
+	int numa_preferred_nid;
+	int numa_migrate_deferred;
+	unsigned long numa_migrate_retry;
 	u64 node_stamp;			/* migration stamp  */
 	struct callback_head numa_work;
+
+	struct list_head numa_entry;
+	struct numa_group *numa_group;
+
+	/*
+	 * Exponential decaying average of faults on a per-node basis.
+	 * Scheduling placement decisions are made based on the these counts.
+	 * The values remain static for the duration of a PTE scan
+	 */
+	unsigned long *numa_faults;
+	unsigned long total_numa_faults;
+
+	/*
+	 * numa_faults_buffer records faults per node during the current
+	 * scan window. When the scan completes, the counts in numa_faults
+	 * decay and these values are copied.
+	 */
+	unsigned long *numa_faults_buffer;
+
+	/*
+	 * numa_faults_locality tracks if faults recorded during the last
+	 * scan window were remote/local. The task scan period is adapted
+	 * based on the locality of the faults with different weights
+	 * depending on whether they were shared or private faults
+	 */
+	unsigned long numa_faults_locality[2];
+
+	unsigned long numa_pages_migrated;
 #endif /* CONFIG_NUMA_BALANCING */
 
 	struct rcu_head rcu;
@@ -1394,11 +1441,10 @@
 	} memcg_batch;
 	unsigned int memcg_kmem_skip_account;
 	struct memcg_oom_info {
+		struct mem_cgroup *memcg;
+		gfp_t gfp_mask;
+		int order;
 		unsigned int may_oom:1;
-		unsigned int in_memcg_oom:1;
-		unsigned int oom_locked:1;
-		int wakeups;
-		struct mem_cgroup *wait_on_memcg;
 	} memcg_oom;
 #endif
 #ifdef CONFIG_UPROBES
@@ -1413,16 +1459,33 @@
 /* Future-safe accessor for struct task_struct's cpus_allowed. */
 #define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed)
 
+#define TNF_MIGRATED	0x01
+#define TNF_NO_GROUP	0x02
+#define TNF_SHARED	0x04
+#define TNF_FAULT_LOCAL	0x08
+
 #ifdef CONFIG_NUMA_BALANCING
-extern void task_numa_fault(int node, int pages, bool migrated);
+extern void task_numa_fault(int last_node, int node, int pages, int flags);
+extern pid_t task_numa_group_id(struct task_struct *p);
 extern void set_numabalancing_state(bool enabled);
+extern void task_numa_free(struct task_struct *p);
+
+extern unsigned int sysctl_numa_balancing_migrate_deferred;
 #else
-static inline void task_numa_fault(int node, int pages, bool migrated)
+static inline void task_numa_fault(int last_node, int node, int pages,
+				   int flags)
 {
 }
+static inline pid_t task_numa_group_id(struct task_struct *p)
+{
+	return 0;
+}
 static inline void set_numabalancing_state(bool enabled)
 {
 }
+static inline void task_numa_free(struct task_struct *p)
+{
+}
 #endif
 
 static inline struct pid *task_pid(struct task_struct *task)
@@ -1975,7 +2038,7 @@
 #else
  static inline void kick_process(struct task_struct *tsk) { }
 #endif
-extern void sched_fork(struct task_struct *p);
+extern void sched_fork(unsigned long clone_flags, struct task_struct *p);
 extern void sched_dead(struct task_struct *p);
 
 extern void proc_caches_init(void);
@@ -2402,11 +2465,6 @@
 	return (state & TASK_INTERRUPTIBLE) || __fatal_signal_pending(p);
 }
 
-static inline int need_resched(void)
-{
-	return unlikely(test_thread_flag(TIF_NEED_RESCHED));
-}
-
 /*
  * cond_resched() and cond_resched_lock(): latency reduction via
  * explicit rescheduling in places that are safe. The return
@@ -2475,36 +2533,105 @@
 {
 	return task_thread_info(p)->status & TS_POLLING;
 }
-static inline void current_set_polling(void)
+static inline void __current_set_polling(void)
 {
 	current_thread_info()->status |= TS_POLLING;
 }
 
-static inline void current_clr_polling(void)
+static inline bool __must_check current_set_polling_and_test(void)
+{
+	__current_set_polling();
+
+	/*
+	 * Polling state must be visible before we test NEED_RESCHED,
+	 * paired by resched_task()
+	 */
+	smp_mb();
+
+	return unlikely(tif_need_resched());
+}
+
+static inline void __current_clr_polling(void)
 {
 	current_thread_info()->status &= ~TS_POLLING;
-	smp_mb__after_clear_bit();
+}
+
+static inline bool __must_check current_clr_polling_and_test(void)
+{
+	__current_clr_polling();
+
+	/*
+	 * Polling state must be visible before we test NEED_RESCHED,
+	 * paired by resched_task()
+	 */
+	smp_mb();
+
+	return unlikely(tif_need_resched());
 }
 #elif defined(TIF_POLLING_NRFLAG)
 static inline int tsk_is_polling(struct task_struct *p)
 {
 	return test_tsk_thread_flag(p, TIF_POLLING_NRFLAG);
 }
-static inline void current_set_polling(void)
+
+static inline void __current_set_polling(void)
 {
 	set_thread_flag(TIF_POLLING_NRFLAG);
 }
 
-static inline void current_clr_polling(void)
+static inline bool __must_check current_set_polling_and_test(void)
+{
+	__current_set_polling();
+
+	/*
+	 * Polling state must be visible before we test NEED_RESCHED,
+	 * paired by resched_task()
+	 *
+	 * XXX: assumes set/clear bit are identical barrier wise.
+	 */
+	smp_mb__after_clear_bit();
+
+	return unlikely(tif_need_resched());
+}
+
+static inline void __current_clr_polling(void)
 {
 	clear_thread_flag(TIF_POLLING_NRFLAG);
 }
+
+static inline bool __must_check current_clr_polling_and_test(void)
+{
+	__current_clr_polling();
+
+	/*
+	 * Polling state must be visible before we test NEED_RESCHED,
+	 * paired by resched_task()
+	 */
+	smp_mb__after_clear_bit();
+
+	return unlikely(tif_need_resched());
+}
+
 #else
 static inline int tsk_is_polling(struct task_struct *p) { return 0; }
-static inline void current_set_polling(void) { }
-static inline void current_clr_polling(void) { }
+static inline void __current_set_polling(void) { }
+static inline void __current_clr_polling(void) { }
+
+static inline bool __must_check current_set_polling_and_test(void)
+{
+	return unlikely(tif_need_resched());
+}
+static inline bool __must_check current_clr_polling_and_test(void)
+{
+	return unlikely(tif_need_resched());
+}
 #endif
 
+static __always_inline bool need_resched(void)
+{
+	return unlikely(tif_need_resched());
+}
+
 /*
  * Thread group CPU time accounting.
  */
@@ -2546,6 +2673,11 @@
 	return task_thread_info(p)->cpu;
 }
 
+static inline int task_node(const struct task_struct *p)
+{
+	return cpu_to_node(task_cpu(p));
+}
+
 extern void set_task_cpu(struct task_struct *p, unsigned int cpu);
 
 #else
diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h
index bf8086b..10d16c4f 100644
--- a/include/linux/sched/sysctl.h
+++ b/include/linux/sched/sysctl.h
@@ -47,7 +47,6 @@
 extern unsigned int sysctl_numa_balancing_scan_delay;
 extern unsigned int sysctl_numa_balancing_scan_period_min;
 extern unsigned int sysctl_numa_balancing_scan_period_max;
-extern unsigned int sysctl_numa_balancing_scan_period_reset;
 extern unsigned int sysctl_numa_balancing_scan_size;
 extern unsigned int sysctl_numa_balancing_settle_count;
 
diff --git a/include/linux/sched_clock.h b/include/linux/sched_clock.h
index fa7922c..cddf0c2 100644
--- a/include/linux/sched_clock.h
+++ b/include/linux/sched_clock.h
@@ -15,7 +15,7 @@
 #endif
 
 extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate);
-
-extern unsigned long long (*sched_clock_func)(void);
+extern void sched_clock_register(u64 (*read)(void), int bits,
+				 unsigned long rate);
 
 #endif
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index b98291a..f729be9 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -66,7 +66,6 @@
 	void		(*set_ldisc)(struct uart_port *, int new);
 	void		(*pm)(struct uart_port *, unsigned int state,
 			      unsigned int oldstate);
-	int		(*set_wake)(struct uart_port *, unsigned int state);
 
 	/*
 	 * Return a string describing the type of the port
diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h
index d340497..50fe651 100644
--- a/include/linux/serial_sci.h
+++ b/include/linux/serial_sci.h
@@ -5,7 +5,7 @@
 #include <linux/sh_dma.h>
 
 /*
- * Generic header for SuperH (H)SCI(F) (used by sh/sh64/h8300 and related parts)
+ * Generic header for SuperH (H)SCI(F) (used by sh/sh64 and related parts)
  */
 
 #define SCIx_NOT_SUPPORTED	(-1)
diff --git a/include/linux/sfi.h b/include/linux/sfi.h
index fe81791..d9b436f 100644
--- a/include/linux/sfi.h
+++ b/include/linux/sfi.h
@@ -59,6 +59,9 @@
 #ifndef _LINUX_SFI_H
 #define _LINUX_SFI_H
 
+#include <linux/init.h>
+#include <linux/types.h>
+
 /* Table signatures reserved by the SFI specification */
 #define SFI_SIG_SYST		"SYST"
 #define SFI_SIG_FREQ		"FREQ"
diff --git a/include/linux/spi/rspi.h b/include/linux/spi/rspi.h
index 900f0e3..a25bd6f 100644
--- a/include/linux/spi/rspi.h
+++ b/include/linux/spi/rspi.h
@@ -26,6 +26,8 @@
 	unsigned int dma_rx_id;
 
 	unsigned dma_width_16bit:1;	/* DMAC read/write width = 16-bit */
+
+	u16 num_chipselect;
 };
 
 #endif
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 887116d..8c62ba7 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -23,6 +23,7 @@
 #include <linux/mod_devicetable.h>
 #include <linux/slab.h>
 #include <linux/kthread.h>
+#include <linux/completion.h>
 
 /*
  * INTERFACES between SPI master-side drivers and SPI infrastructure.
@@ -150,8 +151,7 @@
 }
 
 struct spi_message;
-
-
+struct spi_transfer;
 
 /**
  * struct spi_driver - Host side "protocol" driver
@@ -257,6 +257,9 @@
  * @queue_lock: spinlock to syncronise access to message queue
  * @queue: message queue
  * @cur_msg: the currently in-flight message
+ * @cur_msg_prepared: spi_prepare_message was called for the currently
+ *                    in-flight message
+ * @xfer_completion: used by core tranfer_one_message()
  * @busy: message pump is busy
  * @running: message pump is running
  * @rt: whether this queue is set to run as a realtime task
@@ -274,6 +277,16 @@
  * @unprepare_transfer_hardware: there are currently no more messages on the
  *	queue so the subsystem notifies the driver that it may relax the
  *	hardware by issuing this call
+ * @set_cs: assert or deassert chip select, true to assert.  May be called
+ *          from interrupt context.
+ * @prepare_message: set up the controller to transfer a single message,
+ *                   for example doing DMA mapping.  Called from threaded
+ *                   context.
+ * @transfer_one: transfer a single spi_transfer. When the
+ *	          driver is finished with this transfer it must call
+ *	          spi_finalize_current_transfer() so the subsystem can issue
+ *                the next transfer
+ * @unprepare_message: undo any work done by prepare_message().
  * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
  *	number. Any individual value may be -ENOENT for CS lines that
  *	are not GPIOs (driven by the SPI controller itself).
@@ -388,11 +401,25 @@
 	bool				running;
 	bool				rt;
 	bool				auto_runtime_pm;
+	bool                            cur_msg_prepared;
+	struct completion               xfer_completion;
 
 	int (*prepare_transfer_hardware)(struct spi_master *master);
 	int (*transfer_one_message)(struct spi_master *master,
 				    struct spi_message *mesg);
 	int (*unprepare_transfer_hardware)(struct spi_master *master);
+	int (*prepare_message)(struct spi_master *master,
+			       struct spi_message *message);
+	int (*unprepare_message)(struct spi_master *master,
+				 struct spi_message *message);
+
+	/*
+	 * These hooks are for drivers that use a generic implementation
+	 * of transfer_one_message() provied by the core.
+	 */
+	void (*set_cs)(struct spi_device *spi, bool enable);
+	int (*transfer_one)(struct spi_master *master, struct spi_device *spi,
+			    struct spi_transfer *transfer);
 
 	/* gpio chip select */
 	int			*cs_gpios;
@@ -428,12 +455,15 @@
 /* Calls the driver make to interact with the message queue */
 extern struct spi_message *spi_get_next_queued_message(struct spi_master *master);
 extern void spi_finalize_current_message(struct spi_master *master);
+extern void spi_finalize_current_transfer(struct spi_master *master);
 
 /* the spi driver core manages memory for the spi_master classdev */
 extern struct spi_master *
 spi_alloc_master(struct device *host, unsigned size);
 
 extern int spi_register_master(struct spi_master *master);
+extern int devm_spi_register_master(struct device *dev,
+				    struct spi_master *master);
 extern void spi_unregister_master(struct spi_master *master);
 
 extern struct spi_master *spi_busnum_to_master(u16 busnum);
@@ -823,6 +853,33 @@
 	return (status < 0) ? status : result;
 }
 
+/**
+ * spi_w8r16be - SPI synchronous 8 bit write followed by 16 bit big-endian read
+ * @spi: device with which data will be exchanged
+ * @cmd: command to be written before data is read back
+ * Context: can sleep
+ *
+ * This returns the (unsigned) sixteen bit number returned by the device in cpu
+ * endianness, or else a negative error code. Callable only from contexts that
+ * can sleep.
+ *
+ * This function is similar to spi_w8r16, with the exception that it will
+ * convert the read 16 bit data word from big-endian to native endianness.
+ *
+ */
+static inline ssize_t spi_w8r16be(struct spi_device *spi, u8 cmd)
+
+{
+	ssize_t status;
+	__be16 result;
+
+	status = spi_write_then_read(spi, &cmd, 1, &result, 2);
+	if (status < 0)
+		return status;
+
+	return be16_to_cpu(result);
+}
+
 /*---------------------------------------------------------------------------*/
 
 /*
diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
index 3b5e910..d2abbdb 100644
--- a/include/linux/stop_machine.h
+++ b/include/linux/stop_machine.h
@@ -28,6 +28,7 @@
 };
 
 int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg);
+int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *arg);
 void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg,
 			 struct cpu_stop_work *work_buf);
 int stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg);
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 6740801..8af2804 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -49,6 +49,7 @@
 
 	unsigned int		cl_softrtry : 1,/* soft timeouts */
 				cl_discrtry : 1,/* disconnect before retry */
+				cl_noretranstimeo: 1,/* No retransmit timeouts */
 				cl_autobind : 1,/* use getport() */
 				cl_chatty   : 1;/* be verbose */
 
@@ -126,6 +127,7 @@
 #define RPC_CLNT_CREATE_QUIET		(1UL << 6)
 #define RPC_CLNT_CREATE_INFINITE_SLOTS	(1UL << 7)
 #define RPC_CLNT_CREATE_NO_IDLE_TIMEOUT	(1UL << 8)
+#define RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT	(1UL << 9)
 
 struct rpc_clnt *rpc_create(struct rpc_create_args *args);
 struct rpc_clnt	*rpc_bind_new_program(struct rpc_clnt *,
@@ -134,6 +136,10 @@
 struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
 struct rpc_clnt *rpc_clone_client_set_auth(struct rpc_clnt *,
 				rpc_authflavor_t);
+int		rpc_switch_client_transport(struct rpc_clnt *,
+				struct xprt_create *,
+				const struct rpc_timeout *);
+
 void		rpc_shutdown_client(struct rpc_clnt *);
 void		rpc_release_client(struct rpc_clnt *);
 void		rpc_task_release_client(struct rpc_task *);
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 096ee58..3a847de 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -122,6 +122,7 @@
 #define RPC_TASK_SENT		0x0800		/* message was sent */
 #define RPC_TASK_TIMEOUT	0x1000		/* fail with ETIMEDOUT on timeout */
 #define RPC_TASK_NOCONNECT	0x2000		/* return ENOTCONN if not connected */
+#define RPC_TASK_NO_RETRANS_TIMEOUT	0x4000		/* wait forever for a reply */
 
 #define RPC_IS_ASYNC(t)		((t)->tk_flags & RPC_TASK_ASYNC)
 #define RPC_IS_SWAPPER(t)	((t)->tk_flags & RPC_TASK_SWAPPER)
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index cec7b9b..8097b9d 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -288,7 +288,7 @@
 int			xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
 void			xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task);
 void			xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task);
-int			xprt_prepare_transmit(struct rpc_task *task);
+bool			xprt_prepare_transmit(struct rpc_task *task);
 void			xprt_transmit(struct rpc_task *task);
 void			xprt_end_transmit(struct rpc_task *task);
 int			xprt_adjust_timeout(struct rpc_rqst *req);
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 11baec7..6695040 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -173,7 +173,6 @@
 struct sysfs_ops {
 	ssize_t	(*show)(struct kobject *, struct attribute *, char *);
 	ssize_t	(*store)(struct kobject *, struct attribute *, const char *, size_t);
-	const void *(*namespace)(struct kobject *, const struct attribute *);
 };
 
 struct sysfs_dirent;
@@ -183,19 +182,23 @@
 int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
 			    void *data, struct module *owner);
 
-int __must_check sysfs_create_dir(struct kobject *kobj);
+int __must_check sysfs_create_dir_ns(struct kobject *kobj, const void *ns);
 void sysfs_remove_dir(struct kobject *kobj);
-int __must_check sysfs_rename_dir(struct kobject *kobj, const char *new_name);
-int __must_check sysfs_move_dir(struct kobject *kobj,
-				struct kobject *new_parent_kobj);
+int __must_check sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name,
+				     const void *new_ns);
+int __must_check sysfs_move_dir_ns(struct kobject *kobj,
+				   struct kobject *new_parent_kobj,
+				   const void *new_ns);
 
-int __must_check sysfs_create_file(struct kobject *kobj,
-				   const struct attribute *attr);
+int __must_check sysfs_create_file_ns(struct kobject *kobj,
+				      const struct attribute *attr,
+				      const void *ns);
 int __must_check sysfs_create_files(struct kobject *kobj,
 				   const struct attribute **attr);
 int __must_check sysfs_chmod_file(struct kobject *kobj,
 				  const struct attribute *attr, umode_t mode);
-void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr);
+void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr,
+			  const void *ns);
 void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr);
 
 int __must_check sysfs_create_bin_file(struct kobject *kobj,
@@ -210,8 +213,9 @@
 					  const char *name);
 void sysfs_remove_link(struct kobject *kobj, const char *name);
 
-int sysfs_rename_link(struct kobject *kobj, struct kobject *target,
-			const char *old_name, const char *new_name);
+int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *target,
+			 const char *old_name, const char *new_name,
+			 const void *new_ns);
 
 void sysfs_delete_link(struct kobject *dir, struct kobject *targ,
 			const char *name);
@@ -241,9 +245,9 @@
 
 void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr);
 void sysfs_notify_dirent(struct sysfs_dirent *sd);
-struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
-				      const void *ns,
-				      const unsigned char *name);
+struct sysfs_dirent *sysfs_get_dirent_ns(struct sysfs_dirent *parent_sd,
+					 const unsigned char *name,
+					 const void *ns);
 struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd);
 void sysfs_put(struct sysfs_dirent *sd);
 
@@ -257,7 +261,7 @@
 	return -ENOSYS;
 }
 
-static inline int sysfs_create_dir(struct kobject *kobj)
+static inline int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
 {
 	return 0;
 }
@@ -266,19 +270,22 @@
 {
 }
 
-static inline int sysfs_rename_dir(struct kobject *kobj, const char *new_name)
+static inline int sysfs_rename_dir_ns(struct kobject *kobj,
+				      const char *new_name, const void *new_ns)
 {
 	return 0;
 }
 
-static inline int sysfs_move_dir(struct kobject *kobj,
-				 struct kobject *new_parent_kobj)
+static inline int sysfs_move_dir_ns(struct kobject *kobj,
+				    struct kobject *new_parent_kobj,
+				    const void *new_ns)
 {
 	return 0;
 }
 
-static inline int sysfs_create_file(struct kobject *kobj,
-				    const struct attribute *attr)
+static inline int sysfs_create_file_ns(struct kobject *kobj,
+				       const struct attribute *attr,
+				       const void *ns)
 {
 	return 0;
 }
@@ -295,8 +302,9 @@
 	return 0;
 }
 
-static inline void sysfs_remove_file(struct kobject *kobj,
-				     const struct attribute *attr)
+static inline void sysfs_remove_file_ns(struct kobject *kobj,
+					const struct attribute *attr,
+					const void *ns)
 {
 }
 
@@ -333,8 +341,9 @@
 {
 }
 
-static inline int sysfs_rename_link(struct kobject *k, struct kobject *t,
-				    const char *old_name, const char *new_name)
+static inline int sysfs_rename_link_ns(struct kobject *k, struct kobject *t,
+				       const char *old_name,
+				       const char *new_name, const void *ns)
 {
 	return 0;
 }
@@ -413,10 +422,9 @@
 static inline void sysfs_notify_dirent(struct sysfs_dirent *sd)
 {
 }
-static inline
-struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
-				      const void *ns,
-				      const unsigned char *name)
+static inline struct sysfs_dirent *
+sysfs_get_dirent_ns(struct sysfs_dirent *parent_sd, const unsigned char *name,
+		    const void *ns)
 {
 	return NULL;
 }
@@ -435,4 +443,28 @@
 
 #endif /* CONFIG_SYSFS */
 
+static inline int __must_check sysfs_create_file(struct kobject *kobj,
+						 const struct attribute *attr)
+{
+	return sysfs_create_file_ns(kobj, attr, NULL);
+}
+
+static inline void sysfs_remove_file(struct kobject *kobj,
+				     const struct attribute *attr)
+{
+	return sysfs_remove_file_ns(kobj, attr, NULL);
+}
+
+static inline int sysfs_rename_link(struct kobject *kobj, struct kobject *target,
+				    const char *old_name, const char *new_name)
+{
+	return sysfs_rename_link_ns(kobj, target, old_name, new_name, NULL);
+}
+
+static inline struct sysfs_dirent *
+sysfs_get_dirent(struct sysfs_dirent *parent_sd, const unsigned char *name)
+{
+	return sysfs_get_dirent_ns(parent_sd, name, NULL);
+}
+
 #endif /* _SYSFS_H_ */
diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h
index 7faf933..387fa7d 100644
--- a/include/linux/sysrq.h
+++ b/include/linux/sysrq.h
@@ -17,9 +17,6 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 
-/* Enable/disable SYSRQ support by default (0==no, 1==yes). */
-#define SYSRQ_DEFAULT_ENABLE	1
-
 /* Possible values of bitmask for enabling sysrq functions */
 /* 0x0001 is reserved for enable everything */
 #define SYSRQ_ENABLE_LOG	0x0002
diff --git a/include/linux/tegra-powergate.h b/include/linux/tegra-powergate.h
index 55c29a8..c98cfa4 100644
--- a/include/linux/tegra-powergate.h
+++ b/include/linux/tegra-powergate.h
@@ -34,8 +34,15 @@
 #define TEGRA_POWERGATE_CPU3	11
 #define TEGRA_POWERGATE_CELP	12
 #define TEGRA_POWERGATE_3D1	13
+#define TEGRA_POWERGATE_CPU0	14
+#define TEGRA_POWERGATE_C0NC	15
+#define TEGRA_POWERGATE_C1NC	16
+#define TEGRA_POWERGATE_DIS	18
+#define TEGRA_POWERGATE_DISB	19
+#define TEGRA_POWERGATE_XUSBA	20
+#define TEGRA_POWERGATE_XUSBB	21
+#define TEGRA_POWERGATE_XUSBC	22
 
-#define TEGRA_POWERGATE_CPU0	TEGRA_POWERGATE_CPU
 #define TEGRA_POWERGATE_3D0	TEGRA_POWERGATE_3D
 
 int tegra_powergate_is_powered(int id);
diff --git a/include/linux/thinkpad_acpi.h b/include/linux/thinkpad_acpi.h
new file mode 100644
index 0000000..361de59
--- /dev/null
+++ b/include/linux/thinkpad_acpi.h
@@ -0,0 +1,15 @@
+#ifndef __THINKPAD_ACPI_H__
+#define __THINKPAD_ACPI_H__
+
+/* These two functions return 0 if success, or negative error code
+   (e g -ENODEV if no led present) */
+
+enum {
+	TPACPI_LED_MUTE,
+	TPACPI_LED_MICMUTE,
+	TPACPI_LED_MAX,
+};
+
+int tpacpi_led_set(int whichled, bool on);
+
+#endif
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index e7e0473..fddbe20 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -104,8 +104,21 @@
 #define test_thread_flag(flag) \
 	test_ti_thread_flag(current_thread_info(), flag)
 
-#define set_need_resched()	set_thread_flag(TIF_NEED_RESCHED)
-#define clear_need_resched()	clear_thread_flag(TIF_NEED_RESCHED)
+static inline __deprecated void set_need_resched(void)
+{
+	/*
+	 * Use of this function in deprecated.
+	 *
+	 * As of this writing there are only a few users in the DRM tree left
+	 * all of which are wrong and can be removed without causing too much
+	 * grief.
+	 *
+	 * The DRM people are aware and are working on removing the last few
+	 * instances.
+	 */
+}
+
+#define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED)
 
 #if defined TIF_RESTORE_SIGMASK && !defined HAVE_SET_RESTORE_SIGMASK
 /*
diff --git a/include/linux/timex.h b/include/linux/timex.h
index dd3edd7..9d3f1a5 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -64,6 +64,20 @@
 
 #include <asm/timex.h>
 
+#ifndef random_get_entropy
+/*
+ * The random_get_entropy() function is used by the /dev/random driver
+ * in order to extract entropy via the relative unpredictability of
+ * when an interrupt takes places versus a high speed, fine-grained
+ * timing source or cycle counter.  Since it will be occurred on every
+ * single interrupt, it must have a very low cost/overhead.
+ *
+ * By default we use get_cycles() for this purpose, but individual
+ * architectures may override this in their asm/timex.h header file.
+ */
+#define random_get_entropy()	get_cycles()
+#endif
+
 /*
  * SHIFT_PLL is used as a dampening factor to define how much we
  * adjust the frequency correction for a given offset in PLL mode.
diff --git a/include/linux/topology.h b/include/linux/topology.h
index d3cf0d6..12ae6ce 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -106,6 +106,8 @@
 	.last_balance		= jiffies,				\
 	.balance_interval	= 1,					\
 	.smt_gain		= 1178,	/* 15% */			\
+	.max_newidle_lb_cost	= 0,					\
+	.next_decay_max_lb_cost	= jiffies,				\
 }
 #endif
 #endif /* CONFIG_SCHED_SMT */
@@ -135,6 +137,8 @@
 				,					\
 	.last_balance		= jiffies,				\
 	.balance_interval	= 1,					\
+	.max_newidle_lb_cost	= 0,					\
+	.next_decay_max_lb_cost	= jiffies,				\
 }
 #endif
 #endif /* CONFIG_SCHED_MC */
@@ -166,6 +170,8 @@
 				,					\
 	.last_balance		= jiffies,				\
 	.balance_interval	= 1,					\
+	.max_newidle_lb_cost	= 0,					\
+	.next_decay_max_lb_cost	= jiffies,				\
 }
 #endif
 
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 64f8646..97d660e 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -180,7 +180,6 @@
 	   IFF the port was initialized. Do not use to free resources. Called
 	   under the port mutex to serialize against activate/shutdowns */
 	void (*shutdown)(struct tty_port *port);
-	void (*drop)(struct tty_port *port);
 	/* Called under the port mutex from tty_port_open, serialized using
 	   the port mutex */
         /* FIXME: long term getting the tty argument *out* of this would be
@@ -672,31 +671,17 @@
 #define wait_event_interruptible_tty(tty, wq, condition)		\
 ({									\
 	int __ret = 0;							\
-	if (!(condition)) {						\
-		__wait_event_interruptible_tty(tty, wq, condition, __ret);	\
-	}								\
+	if (!(condition))						\
+		__ret = __wait_event_interruptible_tty(tty, wq,		\
+						       condition);	\
 	__ret;								\
 })
 
-#define __wait_event_interruptible_tty(tty, wq, condition, ret)		\
-do {									\
-	DEFINE_WAIT(__wait);						\
-									\
-	for (;;) {							\
-		prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);	\
-		if (condition)						\
-			break;						\
-		if (!signal_pending(current)) {				\
-			tty_unlock(tty);					\
+#define __wait_event_interruptible_tty(tty, wq, condition)		\
+	___wait_event(wq, condition, TASK_INTERRUPTIBLE, 0, 0,		\
+			tty_unlock(tty);				\
 			schedule();					\
-			tty_lock(tty);					\
-			continue;					\
-		}							\
-		ret = -ERESTARTSYS;					\
-		break;							\
-	}								\
-	finish_wait(&wq, &__wait);					\
-} while (0)
+			tty_lock(tty))
 
 #ifdef CONFIG_PROC_FS
 extern void proc_tty_register_driver(struct tty_driver *);
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index 5ca0951..9d8cf05 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -15,7 +15,7 @@
  */
 static inline void pagefault_disable(void)
 {
-	inc_preempt_count();
+	preempt_count_inc();
 	/*
 	 * make sure to have issued the store before a pagefault
 	 * can hit.
@@ -30,11 +30,7 @@
 	 * the pagefault handler again.
 	 */
 	barrier();
-	dec_preempt_count();
-	/*
-	 * make sure we do..
-	 */
-	barrier();
+	preempt_count_dec();
 	preempt_check_resched();
 }
 
diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
index 06f28be..319eae7 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -30,6 +30,7 @@
 struct vm_area_struct;
 struct mm_struct;
 struct inode;
+struct notifier_block;
 
 #ifdef CONFIG_ARCH_SUPPORTS_UPROBES
 # include <asm/uprobes.h>
@@ -108,6 +109,7 @@
 extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
 extern bool __weak is_swbp_insn(uprobe_opcode_t *insn);
 extern bool __weak is_trap_insn(uprobe_opcode_t *insn);
+extern int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t);
 extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc);
 extern int uprobe_apply(struct inode *inode, loff_t offset, struct uprobe_consumer *uc, bool);
 extern void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc);
@@ -117,14 +119,21 @@
 extern void uprobe_end_dup_mmap(void);
 extern void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm);
 extern void uprobe_free_utask(struct task_struct *t);
-extern void uprobe_copy_process(struct task_struct *t);
+extern void uprobe_copy_process(struct task_struct *t, unsigned long flags);
 extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs);
 extern int uprobe_post_sstep_notifier(struct pt_regs *regs);
 extern int uprobe_pre_sstep_notifier(struct pt_regs *regs);
 extern void uprobe_notify_resume(struct pt_regs *regs);
 extern bool uprobe_deny_signal(void);
-extern bool __weak arch_uprobe_skip_sstep(struct arch_uprobe *aup, struct pt_regs *regs);
+extern bool arch_uprobe_skip_sstep(struct arch_uprobe *aup, struct pt_regs *regs);
 extern void uprobe_clear_state(struct mm_struct *mm);
+extern int  arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
+extern int  arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern int  arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
+extern int  arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
+extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs);
 #else /* !CONFIG_UPROBES */
 struct uprobes_state {
 };
@@ -174,7 +183,7 @@
 static inline void uprobe_free_utask(struct task_struct *t)
 {
 }
-static inline void uprobe_copy_process(struct task_struct *t)
+static inline void uprobe_copy_process(struct task_struct *t, unsigned long flags)
 {
 }
 static inline void uprobe_clear_state(struct mm_struct *mm)
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 001629c..7454865 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -475,7 +475,8 @@
  * @lpm_capable: device supports LPM
  * @usb2_hw_lpm_capable: device can perform USB2 hardware LPM
  * @usb2_hw_lpm_besl_capable: device can perform USB2 hardware BESL LPM
- * @usb2_hw_lpm_enabled: USB2 hardware LPM enabled
+ * @usb2_hw_lpm_enabled: USB2 hardware LPM is enabled
+ * @usb2_hw_lpm_allowed: Userspace allows USB 2.0 LPM to be enabled
  * @usb3_lpm_enabled: USB3 hardware LPM enabled
  * @string_langid: language ID for strings
  * @product: iProduct string, if present (static)
@@ -548,6 +549,7 @@
 	unsigned usb2_hw_lpm_capable:1;
 	unsigned usb2_hw_lpm_besl_capable:1;
 	unsigned usb2_hw_lpm_enabled:1;
+	unsigned usb2_hw_lpm_allowed:1;
 	unsigned usb3_lpm_enabled:1;
 	int string_langid;
 
@@ -702,7 +704,7 @@
 		unsigned int num_streams, gfp_t mem_flags);
 
 /* Reverts a group of bulk endpoints back to not using stream IDs. */
-extern void usb_free_streams(struct usb_interface *interface,
+extern int usb_free_streams(struct usb_interface *interface,
 		struct usb_host_endpoint **eps, unsigned int num_eps,
 		gfp_t mem_flags);
 
@@ -1209,11 +1211,13 @@
 	struct list_head urb_list;
 	wait_queue_head_t wait;
 	spinlock_t lock;
+	atomic_t suspend_wakeups;
 	unsigned int poisoned:1;
 };
 
 static inline void init_usb_anchor(struct usb_anchor *anchor)
 {
+	memset(anchor, 0, sizeof(*anchor));
 	INIT_LIST_HEAD(&anchor->urb_list);
 	init_waitqueue_head(&anchor->wait);
 	spin_lock_init(&anchor->lock);
@@ -1574,6 +1578,8 @@
 extern void usb_poison_anchored_urbs(struct usb_anchor *anchor);
 extern void usb_unpoison_anchored_urbs(struct usb_anchor *anchor);
 extern void usb_unlink_anchored_urbs(struct usb_anchor *anchor);
+extern void usb_anchor_suspend_wakeups(struct usb_anchor *anchor);
+extern void usb_anchor_resume_wakeups(struct usb_anchor *anchor);
 extern void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor);
 extern void usb_unanchor_urb(struct urb *urb);
 extern int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 75efc45..b8aba19 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -73,6 +73,7 @@
 	spinlock_t lock;
 	struct list_head  head;
 	struct tasklet_struct bh;
+	struct usb_host_endpoint *completing_ep;
 };
 
 struct usb_hcd {
@@ -140,6 +141,7 @@
 	unsigned		wireless:1;	/* Wireless USB HCD */
 	unsigned		authorized_default:1;
 	unsigned		has_tt:1;	/* Integrated TT in root hub */
+	unsigned		amd_resume_bug:1; /* AMD remote wakeup quirk */
 
 	unsigned int		irq;		/* irq allocated */
 	void __iomem		*regs;		/* device memory/io */
@@ -378,6 +380,12 @@
 	return hcd->driver->flags & HCD_BH;
 }
 
+static inline bool hcd_periodic_completion_in_progress(struct usb_hcd *hcd,
+		struct usb_host_endpoint *ep)
+{
+	return hcd->high_prio_bh.completing_ep == ep;
+}
+
 extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
 extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
 		int status);
@@ -428,6 +436,8 @@
 extern void usb_hcd_pci_remove(struct pci_dev *dev);
 extern void usb_hcd_pci_shutdown(struct pci_dev *dev);
 
+extern int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev);
+
 #ifdef CONFIG_PM
 extern const struct dev_pm_ops usb_hcd_pci_pm_ops;
 #endif
@@ -496,6 +506,7 @@
 	struct usb_device	*hub;	/* upstream highspeed hub */
 	int			multi;	/* true means one TT per port */
 	unsigned		think_time;	/* think time in ns */
+	void			*hcpriv;	/* HCD private data */
 
 	/* for control/bulk error recovery (CLEAR_TT_BUFFER) */
 	spinlock_t		lock;
@@ -554,9 +565,8 @@
 		 * of (7/6 * 8 * bytecount) = 9.33 * bytecount */
 		/* bytecount = data payload byte count */
 
-#define NS_TO_US(ns)	((ns + 500L) / 1000L)
-			/* convert & round nanoseconds to microseconds */
-
+#define NS_TO_US(ns)	DIV_ROUND_UP(ns, 1000L)
+			/* convert nanoseconds to microseconds, rounding up */
 
 /*
  * Full/low speed bandwidth allocation constants/support.
diff --git a/include/linux/usb/intel_mid_otg.h b/include/linux/usb/intel_mid_otg.h
deleted file mode 100644
index 756cf55..0000000
--- a/include/linux/usb/intel_mid_otg.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Intel MID (Langwell/Penwell) USB OTG Transceiver driver
- * Copyright (C) 2008 - 2010, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef __INTEL_MID_OTG_H
-#define __INTEL_MID_OTG_H
-
-#include <linux/pm.h>
-#include <linux/usb/otg.h>
-#include <linux/notifier.h>
-
-struct intel_mid_otg_xceiv;
-
-/* This is a common data structure for Intel MID platform to
- * save values of the OTG state machine */
-struct otg_hsm {
-	/* Input */
-	int a_bus_resume;
-	int a_bus_suspend;
-	int a_conn;
-	int a_sess_vld;
-	int a_srp_det;
-	int a_vbus_vld;
-	int b_bus_resume;
-	int b_bus_suspend;
-	int b_conn;
-	int b_se0_srp;
-	int b_ssend_srp;
-	int b_sess_end;
-	int b_sess_vld;
-	int id;
-/* id values */
-#define ID_B		0x05
-#define ID_A		0x04
-#define ID_ACA_C	0x03
-#define ID_ACA_B	0x02
-#define ID_ACA_A	0x01
-	int power_up;
-	int adp_change;
-	int test_device;
-
-	/* Internal variables */
-	int a_set_b_hnp_en;
-	int b_srp_done;
-	int b_hnp_enable;
-	int hnp_poll_enable;
-
-	/* Timeout indicator for timers */
-	int a_wait_vrise_tmout;
-	int a_wait_bcon_tmout;
-	int a_aidl_bdis_tmout;
-	int a_bidl_adis_tmout;
-	int a_bidl_adis_tmr;
-	int a_wait_vfall_tmout;
-	int b_ase0_brst_tmout;
-	int b_bus_suspend_tmout;
-	int b_srp_init_tmout;
-	int b_srp_fail_tmout;
-	int b_srp_fail_tmr;
-	int b_adp_sense_tmout;
-
-	/* Informative variables */
-	int a_bus_drop;
-	int a_bus_req;
-	int a_clr_err;
-	int b_bus_req;
-	int a_suspend_req;
-	int b_bus_suspend_vld;
-
-	/* Output */
-	int drv_vbus;
-	int loc_conn;
-	int loc_sof;
-
-	/* Others */
-	int vbus_srp_up;
-};
-
-/* must provide ULPI access function to read/write registers implemented in
- * ULPI address space */
-struct iotg_ulpi_access_ops {
-	int	(*read)(struct intel_mid_otg_xceiv *iotg, u8 reg, u8 *val);
-	int	(*write)(struct intel_mid_otg_xceiv *iotg, u8 reg, u8 val);
-};
-
-#define OTG_A_DEVICE	0x0
-#define OTG_B_DEVICE	0x1
-
-/*
- * the Intel MID (Langwell/Penwell) otg transceiver driver needs to interact
- * with device and host drivers to implement the USB OTG related feature. More
- * function members are added based on usb_phy data structure for this
- * purpose.
- */
-struct intel_mid_otg_xceiv {
-	struct usb_phy		otg;
-	struct otg_hsm		hsm;
-
-	/* base address */
-	void __iomem		*base;
-
-	/* ops to access ulpi */
-	struct iotg_ulpi_access_ops	ulpi_ops;
-
-	/* atomic notifier for interrupt context */
-	struct atomic_notifier_head	iotg_notifier;
-
-	/* start/stop USB Host function */
-	int	(*start_host)(struct intel_mid_otg_xceiv *iotg);
-	int	(*stop_host)(struct intel_mid_otg_xceiv *iotg);
-
-	/* start/stop USB Peripheral function */
-	int	(*start_peripheral)(struct intel_mid_otg_xceiv *iotg);
-	int	(*stop_peripheral)(struct intel_mid_otg_xceiv *iotg);
-
-	/* start/stop ADP sense/probe function */
-	int	(*set_adp_probe)(struct intel_mid_otg_xceiv *iotg,
-					bool enabled, int dev);
-	int	(*set_adp_sense)(struct intel_mid_otg_xceiv *iotg,
-					bool enabled);
-
-#ifdef CONFIG_PM
-	/* suspend/resume USB host function */
-	int	(*suspend_host)(struct intel_mid_otg_xceiv *iotg,
-					pm_message_t message);
-	int	(*resume_host)(struct intel_mid_otg_xceiv *iotg);
-
-	int	(*suspend_peripheral)(struct intel_mid_otg_xceiv *iotg,
-					pm_message_t message);
-	int	(*resume_peripheral)(struct intel_mid_otg_xceiv *iotg);
-#endif
-
-};
-static inline
-struct intel_mid_otg_xceiv *otg_to_mid_xceiv(struct usb_phy *otg)
-{
-	return container_of(otg, struct intel_mid_otg_xceiv, otg);
-}
-
-#define MID_OTG_NOTIFY_CONNECT		0x0001
-#define MID_OTG_NOTIFY_DISCONN		0x0002
-#define MID_OTG_NOTIFY_HSUSPEND		0x0003
-#define MID_OTG_NOTIFY_HRESUME		0x0004
-#define MID_OTG_NOTIFY_CSUSPEND		0x0005
-#define MID_OTG_NOTIFY_CRESUME		0x0006
-#define MID_OTG_NOTIFY_HOSTADD		0x0007
-#define MID_OTG_NOTIFY_HOSTREMOVE	0x0008
-#define MID_OTG_NOTIFY_CLIENTADD	0x0009
-#define MID_OTG_NOTIFY_CLIENTREMOVE	0x000a
-
-static inline int
-intel_mid_otg_register_notifier(struct intel_mid_otg_xceiv *iotg,
-				struct notifier_block *nb)
-{
-	return atomic_notifier_chain_register(&iotg->iotg_notifier, nb);
-}
-
-static inline void
-intel_mid_otg_unregister_notifier(struct intel_mid_otg_xceiv *iotg,
-				struct notifier_block *nb)
-{
-	atomic_notifier_chain_unregister(&iotg->iotg_notifier, nb);
-}
-
-#endif /* __INTEL_MID_OTG_H */
diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h
index 053c268..eb50525 100644
--- a/include/linux/usb/musb.h
+++ b/include/linux/usb/musb.h
@@ -99,8 +99,6 @@
 	/* MUSB_HOST, MUSB_PERIPHERAL, or MUSB_OTG */
 	u8		mode;
 
-	u8		has_mailbox:1;
-
 	/* for clk_get() */
 	const char	*clock;
 
diff --git a/include/linux/usb/omap_control_usb.h b/include/linux/usb/omap_control_usb.h
index 27b5b8c..596b019 100644
--- a/include/linux/usb/omap_control_usb.h
+++ b/include/linux/usb/omap_control_usb.h
@@ -19,20 +19,23 @@
 #ifndef __OMAP_CONTROL_USB_H__
 #define __OMAP_CONTROL_USB_H__
 
+enum omap_control_usb_type {
+	OMAP_CTRL_TYPE_OTGHS = 1,	/* Mailbox OTGHS_CONTROL */
+	OMAP_CTRL_TYPE_USB2,	/* USB2_PHY, power down in CONTROL_DEV_CONF */
+	OMAP_CTRL_TYPE_PIPE3,	/* PIPE3 PHY, DPLL & seperate Rx/Tx power */
+	OMAP_CTRL_TYPE_DRA7USB2, /* USB2 PHY, power and power_aux e.g. DRA7 */
+};
+
 struct omap_control_usb {
 	struct device *dev;
 
-	u32 __iomem *dev_conf;
 	u32 __iomem *otghs_control;
-	u32 __iomem *phy_power;
+	u32 __iomem *power;
+	u32 __iomem *power_aux;
 
 	struct clk *sys_clk;
 
-	u32 type;
-};
-
-struct omap_control_usb_platform_data {
-	u8 type;
+	enum omap_control_usb_type type;
 };
 
 enum omap_control_usb_mode {
@@ -42,10 +45,6 @@
 	USB_MODE_DISCONNECT,
 };
 
-/* To differentiate ctrl module IP having either mailbox or USB3 PHY power */
-#define	OMAP_CTRL_DEV_TYPE1		0x1
-#define	OMAP_CTRL_DEV_TYPE2		0x2
-
 #define	OMAP_CTRL_DEV_PHY_PD		BIT(0)
 
 #define	OMAP_CTRL_DEV_AVALID		BIT(0)
@@ -63,26 +62,18 @@
 #define	OMAP_CTRL_USB3_PHY_TX_RX_POWERON	0x3
 #define	OMAP_CTRL_USB3_PHY_TX_RX_POWEROFF	0x0
 
+#define OMAP_CTRL_USB2_PHY_PD		BIT(28)
+
 #if IS_ENABLED(CONFIG_OMAP_CONTROL_USB)
-extern struct device *omap_get_control_dev(void);
 extern void omap_control_usb_phy_power(struct device *dev, int on);
-extern void omap_control_usb3_phy_power(struct device *dev, bool on);
 extern void omap_control_usb_set_mode(struct device *dev,
 	enum omap_control_usb_mode mode);
 #else
-static inline struct device *omap_get_control_dev(void)
-{
-	return ERR_PTR(-ENODEV);
-}
 
 static inline void omap_control_usb_phy_power(struct device *dev, int on)
 {
 }
 
-static inline void omap_control_usb3_phy_power(struct device *dev, int on)
-{
-}
-
 static inline void omap_control_usb_set_mode(struct device *dev,
 	enum omap_control_usb_mode mode)
 {
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index d528b80..704a1ab 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -320,6 +320,8 @@
 extern void usb_serial_put(struct usb_serial *serial);
 extern int usb_serial_generic_open(struct tty_struct *tty,
 	struct usb_serial_port *port);
+extern int usb_serial_generic_write_start(struct usb_serial_port *port,
+							gfp_t mem_flags);
 extern int usb_serial_generic_write(struct tty_struct *tty,
 	struct usb_serial_port *port, const unsigned char *buf, int count);
 extern void usb_serial_generic_close(struct usb_serial_port *port);
diff --git a/include/linux/usb/usb_phy_gen_xceiv.h b/include/linux/usb/usb_phy_gen_xceiv.h
index f9a7e7b..cc8d818 100644
--- a/include/linux/usb/usb_phy_gen_xceiv.h
+++ b/include/linux/usb/usb_phy_gen_xceiv.h
@@ -9,10 +9,11 @@
 
 	/* if set fails with -EPROBE_DEFER if can't get regulator */
 	unsigned int needs_vcc:1;
-	unsigned int needs_reset:1;
+	unsigned int needs_reset:1;	/* deprecated */
+	int gpio_reset;
 };
 
-#if IS_ENABLED(CONFIG_NOP_USB_XCEIV)
+#if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE))
 /* sometimes transceivers are accessed only through e.g. ULPI */
 extern void usb_nop_xceiv_register(void);
 extern void usb_nop_xceiv_unregister(void);
diff --git a/include/linux/usb/wusb-wa.h b/include/linux/usb/wusb-wa.h
index 4ff744e..c125713 100644
--- a/include/linux/usb/wusb-wa.h
+++ b/include/linux/usb/wusb-wa.h
@@ -142,7 +142,7 @@
 struct wa_notif_hdr {
 	u8 bLength;
 	u8 bNotifyType;			/* enum wa_notif_type */
-} __attribute__((packed));
+} __packed;
 
 /**
  * HWA DN Received notification [(WUSB] section 8.5.4.2)
@@ -158,7 +158,7 @@
 	u8 bSourceDeviceAddr;		/* from errata 2005/07 */
 	u8 bmAttributes;
 	struct wusb_dn_hdr dndata[];
-} __attribute__((packed));
+} __packed;
 
 /* [WUSB] section 8.3.3 */
 enum wa_xfer_type {
@@ -167,6 +167,8 @@
 	WA_XFER_TYPE_ISO = 0x82,
 	WA_XFER_RESULT = 0x83,
 	WA_XFER_ABORT = 0x84,
+	WA_XFER_ISO_PACKET_INFO = 0xA0,
+	WA_XFER_ISO_PACKET_STATUS = 0xA1,
 };
 
 /* [WUSB] section 8.3.3 */
@@ -177,28 +179,47 @@
 	__le32 dwTransferID;		/* Host-assigned ID */
 	__le32 dwTransferLength;	/* Length of data to xfer */
 	u8 bTransferSegment;
-} __attribute__((packed));
+} __packed;
 
 struct wa_xfer_ctl {
 	struct wa_xfer_hdr hdr;
 	u8 bmAttribute;
 	__le16 wReserved;
 	struct usb_ctrlrequest baSetupData;
-} __attribute__((packed));
+} __packed;
 
 struct wa_xfer_bi {
 	struct wa_xfer_hdr hdr;
 	u8 bReserved;
 	__le16 wReserved;
-} __attribute__((packed));
+} __packed;
 
+/* [WUSB] section 8.5.5 */
 struct wa_xfer_hwaiso {
 	struct wa_xfer_hdr hdr;
 	u8 bReserved;
 	__le16 wPresentationTime;
 	__le32 dwNumOfPackets;
-	/* FIXME: u8 pktdata[]? */
-} __attribute__((packed));
+} __packed;
+
+struct wa_xfer_packet_info_hwaiso {
+	__le16 wLength;
+	u8 bPacketType;
+	u8 bReserved;
+	__le16 PacketLength[0];
+} __packed;
+
+struct wa_xfer_packet_status_len_hwaiso {
+	__le16 PacketLength;
+	__le16 PacketStatus;
+} __packed;
+
+struct wa_xfer_packet_status_hwaiso {
+	__le16 wLength;
+	u8 bPacketType;
+	u8 bReserved;
+	struct wa_xfer_packet_status_len_hwaiso PacketStatus[0];
+} __packed;
 
 /* [WUSB] section 8.3.3.5 */
 struct wa_xfer_abort {
@@ -206,7 +227,7 @@
 	u8 bRequestType;
 	__le16 wRPipe;			/* RPipe index */
 	__le32 dwTransferID;		/* Host-assigned ID */
-} __attribute__((packed));
+} __packed;
 
 /**
  * WA Transfer Complete notification ([WUSB] section 8.3.3.3)
@@ -216,7 +237,7 @@
 	struct wa_notif_hdr hdr;
 	u8 bEndpoint;
 	u8 Reserved;
-} __attribute__((packed));
+} __packed;
 
 /** Transfer result basic codes [WUSB] table 8-15 */
 enum {
@@ -243,7 +264,7 @@
 	u8     bTransferSegment;
 	u8     bTransferStatus;
 	__le32 dwNumOfPackets;
-} __attribute__((packed));
+} __packed;
 
 /**
  * Wire Adapter Class Descriptor ([WUSB] section 8.5.2.7).
@@ -258,16 +279,16 @@
 struct usb_wa_descriptor {
 	u8	bLength;
 	u8	bDescriptorType;
-	u16	bcdWAVersion;
+	__le16	bcdWAVersion;
 	u8	bNumPorts;		/* don't use!! */
 	u8	bmAttributes;		/* Reserved == 0 */
-	u16	wNumRPipes;
-	u16	wRPipeMaxBlock;
+	__le16	wNumRPipes;
+	__le16	wRPipeMaxBlock;
 	u8	bRPipeBlockSize;
 	u8	bPwrOn2PwrGood;
 	u8	bNumMMCIEs;
 	u8	DeviceRemovable;	/* FIXME: in DWA this is up to 16 bytes */
-} __attribute__((packed));
+} __packed;
 
 /**
  * HWA Device Information Buffer (WUSB1.0[T8.54])
@@ -277,6 +298,6 @@
 	u8	bDeviceAddress;
 	__le16	wPHYRates;
 	u8	bmDeviceAttribute;
-} __attribute__((packed));
+} __packed;
 
 #endif /* #ifndef __LINUX_USB_WUSB_WA_H */
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
index bf99cd0..6303568 100644
--- a/include/linux/usb_usual.h
+++ b/include/linux/usb_usual.h
@@ -66,7 +66,9 @@
 	US_FLAG(INITIAL_READ10,	0x00100000)			\
 		/* Initial READ(10) (and others) must be retried */	\
 	US_FLAG(WRITE_CACHE,	0x00200000)			\
-		/* Write Cache status is not available */
+		/* Write Cache status is not available */	\
+	US_FLAG(NEEDS_CAP16,	0x00400000)
+		/* cannot handle READ_CAPACITY_10 */
 
 #define US_FLAG(name, value)	US_FL_##name = value ,
 enum { US_DO_ALL_FLAGS };
diff --git a/include/linux/vgaarb.h b/include/linux/vgaarb.h
index 80cf817..2c02f3a 100644
--- a/include/linux/vgaarb.h
+++ b/include/linux/vgaarb.h
@@ -65,15 +65,8 @@
  *     out of the arbitration process (and can be safe to take
  *     interrupts at any time.
  */
-#if defined(CONFIG_VGA_ARB)
 extern void vga_set_legacy_decoding(struct pci_dev *pdev,
 				    unsigned int decodes);
-#else
-static inline void vga_set_legacy_decoding(struct pci_dev *pdev,
-					   unsigned int decodes)
-{
-}
-#endif
 
 /**
  *     vga_get         - acquire & locks VGA resources
diff --git a/include/linux/wait.h b/include/linux/wait.h
index a67fc16..61939ba 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -1,7 +1,8 @@
 #ifndef _LINUX_WAIT_H
 #define _LINUX_WAIT_H
-
-
+/*
+ * Linux wait queue related types and methods
+ */
 #include <linux/list.h>
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
@@ -13,27 +14,27 @@
 int default_wake_function(wait_queue_t *wait, unsigned mode, int flags, void *key);
 
 struct __wait_queue {
-	unsigned int flags;
+	unsigned int		flags;
 #define WQ_FLAG_EXCLUSIVE	0x01
-	void *private;
-	wait_queue_func_t func;
-	struct list_head task_list;
+	void			*private;
+	wait_queue_func_t	func;
+	struct list_head	task_list;
 };
 
 struct wait_bit_key {
-	void *flags;
-	int bit_nr;
-#define WAIT_ATOMIC_T_BIT_NR -1
+	void			*flags;
+	int			bit_nr;
+#define WAIT_ATOMIC_T_BIT_NR	-1
 };
 
 struct wait_bit_queue {
-	struct wait_bit_key key;
-	wait_queue_t wait;
+	struct wait_bit_key	key;
+	wait_queue_t		wait;
 };
 
 struct __wait_queue_head {
-	spinlock_t lock;
-	struct list_head task_list;
+	spinlock_t		lock;
+	struct list_head	task_list;
 };
 typedef struct __wait_queue_head wait_queue_head_t;
 
@@ -84,17 +85,17 @@
 
 static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p)
 {
-	q->flags = 0;
-	q->private = p;
-	q->func = default_wake_function;
+	q->flags	= 0;
+	q->private	= p;
+	q->func		= default_wake_function;
 }
 
-static inline void init_waitqueue_func_entry(wait_queue_t *q,
-					wait_queue_func_t func)
+static inline void
+init_waitqueue_func_entry(wait_queue_t *q, wait_queue_func_t func)
 {
-	q->flags = 0;
-	q->private = NULL;
-	q->func = func;
+	q->flags	= 0;
+	q->private	= NULL;
+	q->func		= func;
 }
 
 static inline int waitqueue_active(wait_queue_head_t *q)
@@ -114,8 +115,8 @@
 /*
  * Used for wake-one threads:
  */
-static inline void __add_wait_queue_exclusive(wait_queue_head_t *q,
-					      wait_queue_t *wait)
+static inline void
+__add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait)
 {
 	wait->flags |= WQ_FLAG_EXCLUSIVE;
 	__add_wait_queue(q, wait);
@@ -127,23 +128,22 @@
 	list_add_tail(&new->task_list, &head->task_list);
 }
 
-static inline void __add_wait_queue_tail_exclusive(wait_queue_head_t *q,
-					      wait_queue_t *wait)
+static inline void
+__add_wait_queue_tail_exclusive(wait_queue_head_t *q, wait_queue_t *wait)
 {
 	wait->flags |= WQ_FLAG_EXCLUSIVE;
 	__add_wait_queue_tail(q, wait);
 }
 
-static inline void __remove_wait_queue(wait_queue_head_t *head,
-							wait_queue_t *old)
+static inline void
+__remove_wait_queue(wait_queue_head_t *head, wait_queue_t *old)
 {
 	list_del(&old->task_list);
 }
 
 void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr, void *key);
 void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key);
-void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode, int nr,
-			void *key);
+void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode, int nr, void *key);
 void __wake_up_locked(wait_queue_head_t *q, unsigned int mode, int nr);
 void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr);
 void __wake_up_bit(wait_queue_head_t *, void *, int);
@@ -170,27 +170,64 @@
 /*
  * Wakeup macros to be used to report events to the targets.
  */
-#define wake_up_poll(x, m)				\
+#define wake_up_poll(x, m)						\
 	__wake_up(x, TASK_NORMAL, 1, (void *) (m))
-#define wake_up_locked_poll(x, m)				\
+#define wake_up_locked_poll(x, m)					\
 	__wake_up_locked_key((x), TASK_NORMAL, (void *) (m))
-#define wake_up_interruptible_poll(x, m)			\
+#define wake_up_interruptible_poll(x, m)				\
 	__wake_up(x, TASK_INTERRUPTIBLE, 1, (void *) (m))
 #define wake_up_interruptible_sync_poll(x, m)				\
 	__wake_up_sync_key((x), TASK_INTERRUPTIBLE, 1, (void *) (m))
 
-#define __wait_event(wq, condition) 					\
-do {									\
-	DEFINE_WAIT(__wait);						\
+#define ___wait_cond_timeout(condition)					\
+({									\
+	bool __cond = (condition);					\
+	if (__cond && !__ret)						\
+		__ret = 1;						\
+	__cond || !__ret;						\
+})
+
+#define ___wait_is_interruptible(state)					\
+	(!__builtin_constant_p(state) ||				\
+		state == TASK_INTERRUPTIBLE || state == TASK_KILLABLE)	\
+
+#define ___wait_event(wq, condition, state, exclusive, ret, cmd)	\
+({									\
+	__label__ __out;						\
+	wait_queue_t __wait;						\
+	long __ret = ret;						\
+									\
+	INIT_LIST_HEAD(&__wait.task_list);				\
+	if (exclusive)							\
+		__wait.flags = WQ_FLAG_EXCLUSIVE;			\
+	else								\
+		__wait.flags = 0;					\
 									\
 	for (;;) {							\
-		prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);	\
+		long __int = prepare_to_wait_event(&wq, &__wait, state);\
+									\
 		if (condition)						\
 			break;						\
-		schedule();						\
+									\
+		if (___wait_is_interruptible(state) && __int) {		\
+			__ret = __int;					\
+			if (exclusive) {				\
+				abort_exclusive_wait(&wq, &__wait,	\
+						     state, NULL);	\
+				goto __out;				\
+			}						\
+			break;						\
+		}							\
+									\
+		cmd;							\
 	}								\
 	finish_wait(&wq, &__wait);					\
-} while (0)
+__out:	__ret;								\
+})
+
+#define __wait_event(wq, condition)					\
+	(void)___wait_event(wq, condition, TASK_UNINTERRUPTIBLE, 0, 0,	\
+			    schedule())
 
 /**
  * wait_event - sleep until a condition gets true
@@ -204,29 +241,17 @@
  * wake_up() has to be called after changing any variable that could
  * change the result of the wait condition.
  */
-#define wait_event(wq, condition) 					\
+#define wait_event(wq, condition)					\
 do {									\
-	if (condition)	 						\
+	if (condition)							\
 		break;							\
 	__wait_event(wq, condition);					\
 } while (0)
 
-#define __wait_event_timeout(wq, condition, ret)			\
-do {									\
-	DEFINE_WAIT(__wait);						\
-									\
-	for (;;) {							\
-		prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);	\
-		if (condition)						\
-			break;						\
-		ret = schedule_timeout(ret);				\
-		if (!ret)						\
-			break;						\
-	}								\
-	if (!ret && (condition))					\
-		ret = 1;						\
-	finish_wait(&wq, &__wait);					\
-} while (0)
+#define __wait_event_timeout(wq, condition, timeout)			\
+	___wait_event(wq, ___wait_cond_timeout(condition),		\
+		      TASK_UNINTERRUPTIBLE, 0, timeout,			\
+		      __ret = schedule_timeout(__ret))
 
 /**
  * wait_event_timeout - sleep until a condition gets true or a timeout elapses
@@ -248,28 +273,14 @@
 #define wait_event_timeout(wq, condition, timeout)			\
 ({									\
 	long __ret = timeout;						\
-	if (!(condition)) 						\
-		__wait_event_timeout(wq, condition, __ret);		\
+	if (!___wait_cond_timeout(condition))				\
+		__ret = __wait_event_timeout(wq, condition, timeout);	\
 	__ret;								\
 })
 
-#define __wait_event_interruptible(wq, condition, ret)			\
-do {									\
-	DEFINE_WAIT(__wait);						\
-									\
-	for (;;) {							\
-		prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);	\
-		if (condition)						\
-			break;						\
-		if (!signal_pending(current)) {				\
-			schedule();					\
-			continue;					\
-		}							\
-		ret = -ERESTARTSYS;					\
-		break;							\
-	}								\
-	finish_wait(&wq, &__wait);					\
-} while (0)
+#define __wait_event_interruptible(wq, condition)			\
+	___wait_event(wq, condition, TASK_INTERRUPTIBLE, 0, 0,		\
+		      schedule())
 
 /**
  * wait_event_interruptible - sleep until a condition gets true
@@ -290,31 +301,14 @@
 ({									\
 	int __ret = 0;							\
 	if (!(condition))						\
-		__wait_event_interruptible(wq, condition, __ret);	\
+		__ret = __wait_event_interruptible(wq, condition);	\
 	__ret;								\
 })
 
-#define __wait_event_interruptible_timeout(wq, condition, ret)		\
-do {									\
-	DEFINE_WAIT(__wait);						\
-									\
-	for (;;) {							\
-		prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);	\
-		if (condition)						\
-			break;						\
-		if (!signal_pending(current)) {				\
-			ret = schedule_timeout(ret);			\
-			if (!ret)					\
-				break;					\
-			continue;					\
-		}							\
-		ret = -ERESTARTSYS;					\
-		break;							\
-	}								\
-	if (!ret && (condition))					\
-		ret = 1;						\
-	finish_wait(&wq, &__wait);					\
-} while (0)
+#define __wait_event_interruptible_timeout(wq, condition, timeout)	\
+	___wait_event(wq, ___wait_cond_timeout(condition),		\
+		      TASK_INTERRUPTIBLE, 0, timeout,			\
+		      __ret = schedule_timeout(__ret))
 
 /**
  * wait_event_interruptible_timeout - sleep until a condition gets true or a timeout elapses
@@ -337,15 +331,15 @@
 #define wait_event_interruptible_timeout(wq, condition, timeout)	\
 ({									\
 	long __ret = timeout;						\
-	if (!(condition))						\
-		__wait_event_interruptible_timeout(wq, condition, __ret); \
+	if (!___wait_cond_timeout(condition))				\
+		__ret = __wait_event_interruptible_timeout(wq,		\
+						condition, timeout);	\
 	__ret;								\
 })
 
 #define __wait_event_hrtimeout(wq, condition, timeout, state)		\
 ({									\
 	int __ret = 0;							\
-	DEFINE_WAIT(__wait);						\
 	struct hrtimer_sleeper __t;					\
 									\
 	hrtimer_init_on_stack(&__t.timer, CLOCK_MONOTONIC,		\
@@ -356,25 +350,15 @@
 				       current->timer_slack_ns,		\
 				       HRTIMER_MODE_REL);		\
 									\
-	for (;;) {							\
-		prepare_to_wait(&wq, &__wait, state);			\
-		if (condition)						\
-			break;						\
-		if (state == TASK_INTERRUPTIBLE &&			\
-		    signal_pending(current)) {				\
-			__ret = -ERESTARTSYS;				\
-			break;						\
-		}							\
+	__ret = ___wait_event(wq, condition, state, 0, 0,		\
 		if (!__t.task) {					\
 			__ret = -ETIME;					\
 			break;						\
 		}							\
-		schedule();						\
-	}								\
+		schedule());						\
 									\
 	hrtimer_cancel(&__t.timer);					\
 	destroy_hrtimer_on_stack(&__t.timer);				\
-	finish_wait(&wq, &__wait);					\
 	__ret;								\
 })
 
@@ -428,33 +412,15 @@
 	__ret;								\
 })
 
-#define __wait_event_interruptible_exclusive(wq, condition, ret)	\
-do {									\
-	DEFINE_WAIT(__wait);						\
-									\
-	for (;;) {							\
-		prepare_to_wait_exclusive(&wq, &__wait,			\
-					TASK_INTERRUPTIBLE);		\
-		if (condition) {					\
-			finish_wait(&wq, &__wait);			\
-			break;						\
-		}							\
-		if (!signal_pending(current)) {				\
-			schedule();					\
-			continue;					\
-		}							\
-		ret = -ERESTARTSYS;					\
-		abort_exclusive_wait(&wq, &__wait, 			\
-				TASK_INTERRUPTIBLE, NULL);		\
-		break;							\
-	}								\
-} while (0)
+#define __wait_event_interruptible_exclusive(wq, condition)		\
+	___wait_event(wq, condition, TASK_INTERRUPTIBLE, 1, 0,		\
+		      schedule())
 
 #define wait_event_interruptible_exclusive(wq, condition)		\
 ({									\
 	int __ret = 0;							\
 	if (!(condition))						\
-		__wait_event_interruptible_exclusive(wq, condition, __ret);\
+		__ret = __wait_event_interruptible_exclusive(wq, condition);\
 	__ret;								\
 })
 
@@ -606,24 +572,8 @@
 	 ? 0 : __wait_event_interruptible_locked(wq, condition, 1, 1))
 
 
-
-#define __wait_event_killable(wq, condition, ret)			\
-do {									\
-	DEFINE_WAIT(__wait);						\
-									\
-	for (;;) {							\
-		prepare_to_wait(&wq, &__wait, TASK_KILLABLE);		\
-		if (condition)						\
-			break;						\
-		if (!fatal_signal_pending(current)) {			\
-			schedule();					\
-			continue;					\
-		}							\
-		ret = -ERESTARTSYS;					\
-		break;							\
-	}								\
-	finish_wait(&wq, &__wait);					\
-} while (0)
+#define __wait_event_killable(wq, condition)				\
+	___wait_event(wq, condition, TASK_KILLABLE, 0, 0, schedule())
 
 /**
  * wait_event_killable - sleep until a condition gets true
@@ -644,26 +594,17 @@
 ({									\
 	int __ret = 0;							\
 	if (!(condition))						\
-		__wait_event_killable(wq, condition, __ret);		\
+		__ret = __wait_event_killable(wq, condition);		\
 	__ret;								\
 })
 
 
 #define __wait_event_lock_irq(wq, condition, lock, cmd)			\
-do {									\
-	DEFINE_WAIT(__wait);						\
-									\
-	for (;;) {							\
-		prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);	\
-		if (condition)						\
-			break;						\
-		spin_unlock_irq(&lock);					\
-		cmd;							\
-		schedule();						\
-		spin_lock_irq(&lock);					\
-	}								\
-	finish_wait(&wq, &__wait);					\
-} while (0)
+	(void)___wait_event(wq, condition, TASK_UNINTERRUPTIBLE, 0, 0,	\
+			    spin_unlock_irq(&lock);			\
+			    cmd;					\
+			    schedule();					\
+			    spin_lock_irq(&lock))
 
 /**
  * wait_event_lock_irq_cmd - sleep until a condition gets true. The
@@ -723,26 +664,12 @@
 } while (0)
 
 
-#define __wait_event_interruptible_lock_irq(wq, condition,		\
-					    lock, ret, cmd)		\
-do {									\
-	DEFINE_WAIT(__wait);						\
-									\
-	for (;;) {							\
-		prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);	\
-		if (condition)						\
-			break;						\
-		if (signal_pending(current)) {				\
-			ret = -ERESTARTSYS;				\
-			break;						\
-		}							\
-		spin_unlock_irq(&lock);					\
-		cmd;							\
-		schedule();						\
-		spin_lock_irq(&lock);					\
-	}								\
-	finish_wait(&wq, &__wait);					\
-} while (0)
+#define __wait_event_interruptible_lock_irq(wq, condition, lock, cmd)	\
+	___wait_event(wq, condition, TASK_INTERRUPTIBLE, 0, 0,		\
+		      spin_unlock_irq(&lock);				\
+		      cmd;						\
+		      schedule();					\
+		      spin_lock_irq(&lock))
 
 /**
  * wait_event_interruptible_lock_irq_cmd - sleep until a condition gets true.
@@ -772,10 +699,9 @@
 #define wait_event_interruptible_lock_irq_cmd(wq, condition, lock, cmd)	\
 ({									\
 	int __ret = 0;							\
-									\
 	if (!(condition))						\
-		__wait_event_interruptible_lock_irq(wq, condition,	\
-						    lock, __ret, cmd);	\
+		__ret = __wait_event_interruptible_lock_irq(wq,		\
+						condition, lock, cmd);	\
 	__ret;								\
 })
 
@@ -804,39 +730,24 @@
 #define wait_event_interruptible_lock_irq(wq, condition, lock)		\
 ({									\
 	int __ret = 0;							\
-									\
 	if (!(condition))						\
-		__wait_event_interruptible_lock_irq(wq, condition,	\
-						    lock, __ret, );	\
+		__ret = __wait_event_interruptible_lock_irq(wq,		\
+						condition, lock,);	\
 	__ret;								\
 })
 
 #define __wait_event_interruptible_lock_irq_timeout(wq, condition,	\
-						    lock, ret)		\
-do {									\
-	DEFINE_WAIT(__wait);						\
-									\
-	for (;;) {							\
-		prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);	\
-		if (condition)						\
-			break;						\
-		if (signal_pending(current)) {				\
-			ret = -ERESTARTSYS;				\
-			break;						\
-		}							\
-		spin_unlock_irq(&lock);					\
-		ret = schedule_timeout(ret);				\
-		spin_lock_irq(&lock);					\
-		if (!ret)						\
-			break;						\
-	}								\
-	finish_wait(&wq, &__wait);					\
-} while (0)
+						    lock, timeout)	\
+	___wait_event(wq, ___wait_cond_timeout(condition),		\
+		      TASK_INTERRUPTIBLE, 0, timeout,			\
+		      spin_unlock_irq(&lock);				\
+		      __ret = schedule_timeout(__ret);			\
+		      spin_lock_irq(&lock));
 
 /**
- * wait_event_interruptible_lock_irq_timeout - sleep until a condition gets true or a timeout elapses.
- *		The condition is checked under the lock. This is expected
- *		to be called with the lock taken.
+ * wait_event_interruptible_lock_irq_timeout - sleep until a condition gets
+ *		true or a timeout elapses. The condition is checked under
+ *		the lock. This is expected to be called with the lock taken.
  * @wq: the waitqueue to wait on
  * @condition: a C expression for the event to wait for
  * @lock: a locked spinlock_t, which will be released before schedule()
@@ -860,11 +771,10 @@
 #define wait_event_interruptible_lock_irq_timeout(wq, condition, lock,	\
 						  timeout)		\
 ({									\
-	int __ret = timeout;						\
-									\
-	if (!(condition))						\
-		__wait_event_interruptible_lock_irq_timeout(		\
-					wq, condition, lock, __ret);	\
+	long __ret = timeout;						\
+	if (!___wait_cond_timeout(condition))				\
+		__ret = __wait_event_interruptible_lock_irq_timeout(	\
+					wq, condition, lock, timeout);	\
 	__ret;								\
 })
 
@@ -875,20 +785,18 @@
  * We plan to remove these interfaces.
  */
 extern void sleep_on(wait_queue_head_t *q);
-extern long sleep_on_timeout(wait_queue_head_t *q,
-				      signed long timeout);
+extern long sleep_on_timeout(wait_queue_head_t *q, signed long timeout);
 extern void interruptible_sleep_on(wait_queue_head_t *q);
-extern long interruptible_sleep_on_timeout(wait_queue_head_t *q,
-					   signed long timeout);
+extern long interruptible_sleep_on_timeout(wait_queue_head_t *q, signed long timeout);
 
 /*
  * Waitqueues which are removed from the waitqueue_head at wakeup time
  */
 void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state);
 void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state);
+long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state);
 void finish_wait(wait_queue_head_t *q, wait_queue_t *wait);
-void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait,
-			unsigned int mode, void *key);
+void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait, unsigned int mode, void *key);
 int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
 int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
 
@@ -934,8 +842,8 @@
  * One uses wait_on_bit() where one is waiting for the bit to clear,
  * but has no intention of setting it.
  */
-static inline int wait_on_bit(void *word, int bit,
-				int (*action)(void *), unsigned mode)
+static inline int
+wait_on_bit(void *word, int bit, int (*action)(void *), unsigned mode)
 {
 	if (!test_bit(bit, word))
 		return 0;
@@ -958,8 +866,8 @@
  * One uses wait_on_bit_lock() where one is waiting for the bit to
  * clear with the intention of setting it, and when done, clearing it.
  */
-static inline int wait_on_bit_lock(void *word, int bit,
-				int (*action)(void *), unsigned mode)
+static inline int
+wait_on_bit_lock(void *word, int bit, int (*action)(void *), unsigned mode)
 {
 	if (!test_and_set_bit(bit, word))
 		return 0;
@@ -983,5 +891,5 @@
 		return 0;
 	return out_of_line_wait_on_atomic_t(val, action, mode);
 }
-	
-#endif
+
+#endif /* _LINUX_WAIT_H */
diff --git a/include/linux/yam.h b/include/linux/yam.h
index 7fe2822..512cdc2 100644
--- a/include/linux/yam.h
+++ b/include/linux/yam.h
@@ -77,6 +77,6 @@
 
 struct yamdrv_ioctl_mcs {
 	int cmd;
-	int bitrate;
+	unsigned int bitrate;
 	unsigned char bits[YAM_FPGA_SIZE];
 };
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
index a7a683e..a8c2ef6 100644
--- a/include/net/cipso_ipv4.h
+++ b/include/net/cipso_ipv4.h
@@ -290,6 +290,7 @@
 	unsigned char err_offset = 0;
 	u8 opt_len = opt[1];
 	u8 opt_iter;
+	u8 tag_len;
 
 	if (opt_len < 8) {
 		err_offset = 1;
@@ -302,11 +303,12 @@
 	}
 
 	for (opt_iter = 6; opt_iter < opt_len;) {
-		if (opt[opt_iter + 1] > (opt_len - opt_iter)) {
+		tag_len = opt[opt_iter + 1];
+		if ((tag_len == 0) || (opt[opt_iter + 1] > (opt_len - opt_iter))) {
 			err_offset = opt_iter + 1;
 			goto out;
 		}
-		opt_iter += opt[opt_iter + 1];
+		opt_iter += tag_len;
 	}
 
 out:
diff --git a/include/net/dst.h b/include/net/dst.h
index 3bc4865..3c4c944 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -479,10 +479,22 @@
 {
 	return dst_orig;
 } 
+
+static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst)
+{
+	return NULL;
+}
+
 #else
 extern struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
 				     const struct flowi *fl, struct sock *sk,
 				     int flags);
+
+/* skb attached with this dst needs transformation if dst->xfrm is valid */
+static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst)
+{
+	return dst->xfrm;
+}
 #endif
 
 #endif /* _NET_DST_H */
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 48ec25a..5e661a9 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -165,6 +165,7 @@
 static inline void rt6_clean_expires(struct rt6_info *rt)
 {
 	rt->rt6i_flags &= ~RTF_EXPIRES;
+	rt->dst.expires = 0;
 }
 
 static inline void rt6_set_expires(struct rt6_info *rt, unsigned long expires)
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index f525e70..2b786b7 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -194,11 +194,9 @@
 	       skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb));
 }
 
-static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt, struct in6_addr *dest)
+static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt)
 {
-	if (rt->rt6i_flags & RTF_GATEWAY)
-		return &rt->rt6i_gateway;
-	return dest;
+	return &rt->rt6i_gateway;
 }
 
 #endif
diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index d0d11df..807d6b7 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -133,7 +133,7 @@
 
 /* Basic interface to register ieee802154 device */
 struct ieee802154_dev *
-ieee802154_alloc_device(size_t priv_data_lex, struct ieee802154_ops *ops);
+ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops);
 void ieee802154_free_device(struct ieee802154_dev *dev);
 int ieee802154_register_device(struct ieee802154_dev *dev);
 void ieee802154_unregister_device(struct ieee802154_dev *dev);
diff --git a/include/net/sock.h b/include/net/sock.h
index 1d37a80..808cbc2 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1630,16 +1630,14 @@
 
 static inline void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp)
 {
-	unsigned int size = sk_filter_len(fp);
-
-	atomic_sub(size, &sk->sk_omem_alloc);
+	atomic_sub(sk_filter_size(fp->len), &sk->sk_omem_alloc);
 	sk_filter_release(fp);
 }
 
 static inline void sk_filter_charge(struct sock *sk, struct sk_filter *fp)
 {
 	atomic_inc(&fp->refcnt);
-	atomic_add(sk_filter_len(fp), &sk->sk_omem_alloc);
+	atomic_add(sk_filter_size(fp->len), &sk->sk_omem_alloc);
 }
 
 /*
diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h
index 3ce69fd..52f02a6 100644
--- a/include/sound/ak4114.h
+++ b/include/sound/ak4114.h
@@ -170,7 +170,7 @@
 	void * private_data;
 	unsigned int init: 1;
 	spinlock_t lock;
-	unsigned char regmap[7];
+	unsigned char regmap[6];
 	unsigned char txcsb[5];
 	struct snd_kcontrol *kctls[AK4114_CONTROLS];
 	struct snd_pcm_substream *playback_substream;
@@ -189,7 +189,7 @@
 
 int snd_ak4114_create(struct snd_card *card,
 		      ak4114_read_t *read, ak4114_write_t *write,
-		      const unsigned char pgm[7], const unsigned char txcsb[5],
+		      const unsigned char pgm[6], const unsigned char txcsb[5],
 		      void *private_data, struct ak4114 **r_ak4114);
 void snd_ak4114_reg_write(struct ak4114 *ak4114, unsigned char reg, unsigned char mask, unsigned char val);
 void snd_ak4114_reinit(struct ak4114 *ak4114);
diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h
index 9031a26..ae6c3b8 100644
--- a/include/sound/compress_driver.h
+++ b/include/sound/compress_driver.h
@@ -171,4 +171,13 @@
 	wake_up(&stream->runtime->sleep);
 }
 
+static inline void snd_compr_drain_notify(struct snd_compr_stream *stream)
+{
+	if (snd_BUG_ON(!stream))
+		return;
+
+	stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+	wake_up(&stream->runtime->sleep);
+}
+
 #endif
diff --git a/include/sound/cs42l52.h b/include/sound/cs42l52.h
index 4c68955..7c2be4a 100644
--- a/include/sound/cs42l52.h
+++ b/include/sound/cs42l52.h
@@ -31,6 +31,8 @@
 	/* Charge Pump Freq. Check datasheet Pg73 */
 	unsigned int chgfreq;
 
+	/* Reset GPIO */
+	unsigned int reset_gpio;
 };
 
 #endif /* __CS42L52_H */
diff --git a/include/sound/cs42l73.h b/include/sound/cs42l73.h
new file mode 100644
index 0000000..f354be4
--- /dev/null
+++ b/include/sound/cs42l73.h
@@ -0,0 +1,22 @@
+/*
+ * linux/sound/cs42l73.h -- Platform data for CS42L73
+ *
+ * Copyright (c) 2012 Cirrus Logic Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __CS42L73_H
+#define __CS42L73_H
+
+struct cs42l73_platform_data {
+	/* RST GPIO */
+	unsigned int reset_gpio;
+	unsigned int chgfreq;
+	int jack_detection;
+	unsigned int mclk_freq;
+};
+
+#endif /* __CS42L73_H */
diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
index f11c35c..1501731 100644
--- a/include/sound/dmaengine_pcm.h
+++ b/include/sound/dmaengine_pcm.h
@@ -61,6 +61,8 @@
  * @slave_id: Slave requester id for the DMA channel.
  * @filter_data: Custom DMA channel filter data, this will usually be used when
  * requesting the DMA channel.
+ * @chan_name: Custom channel name to use when requesting DMA channel.
+ * @fifo_size: FIFO size of the DAI controller in bytes
  */
 struct snd_dmaengine_dai_dma_data {
 	dma_addr_t addr;
@@ -68,6 +70,8 @@
 	u32 maxburst;
 	unsigned int slave_id;
 	void *filter_data;
+	const char *chan_name;
+	unsigned int fifo_size;
 };
 
 void snd_dmaengine_pcm_set_config_from_dai_data(
@@ -96,6 +100,10 @@
  * playback.
  */
 #define SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX BIT(3)
+/*
+ * The PCM streams have custom channel names specified.
+ */
+#define SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME BIT(4)
 
 /**
  * struct snd_dmaengine_pcm_config - Configuration data for dmaengine based PCM
diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h
index cf15b82..af99839 100644
--- a/include/sound/memalloc.h
+++ b/include/sound/memalloc.h
@@ -52,6 +52,11 @@
 #else
 #define SNDRV_DMA_TYPE_DEV_SG	SNDRV_DMA_TYPE_DEV /* no SG-buf support */
 #endif
+#ifdef CONFIG_GENERIC_ALLOCATOR
+#define SNDRV_DMA_TYPE_DEV_IRAM		4	/* generic device iram-buffer */
+#else
+#define SNDRV_DMA_TYPE_DEV_IRAM	SNDRV_DMA_TYPE_DEV
+#endif
 
 /*
  * info for buffer allocation
diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h
index fe66533..12afab1 100644
--- a/include/sound/rcar_snd.h
+++ b/include/sound/rcar_snd.h
@@ -36,7 +36,6 @@
 #define RSND_SSI_CLK_PIN_SHARE		(1 << 31)
 #define RSND_SSI_CLK_FROM_ADG		(1 << 30) /* clock parent is master */
 #define RSND_SSI_SYNC			(1 << 29) /* SSI34_sync etc */
-#define RSND_SSI_DEPENDENT		(1 << 28) /* SSI needs SRU/SCU */
 
 #define RSND_SSI_PLAY			(1 << 24)
 
@@ -68,6 +67,7 @@
  *
  * A : generation
  */
+#define RSND_GEN_MASK	(0xF << 0)
 #define RSND_GEN1	(1 << 0) /* fixme */
 #define RSND_GEN2	(2 << 0) /* fixme */
 
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index ae9a227..800c101 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -105,6 +105,8 @@
 int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
 	int pll_id, int source, unsigned int freq_in, unsigned int freq_out);
 
+int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio);
+
 /* Digital Audio interface formatting */
 int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
 
@@ -131,6 +133,7 @@
 	int (*set_pll)(struct snd_soc_dai *dai, int pll_id, int source,
 		unsigned int freq_in, unsigned int freq_out);
 	int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div);
+	int (*set_bclk_ratio)(struct snd_soc_dai *dai, unsigned int ratio);
 
 	/*
 	 * DAI format configuration
@@ -166,6 +169,13 @@
 		struct snd_soc_dai *);
 	int (*prepare)(struct snd_pcm_substream *,
 		struct snd_soc_dai *);
+	/*
+	 * NOTE: Commands passed to the trigger function are not necessarily
+	 * compatible with the current state of the dai. For example this
+	 * sequence of commands is possible: START STOP STOP.
+	 * So do not unconditionally use refcounting functions in the trigger
+	 * function, e.g. clk_enable/disable.
+	 */
 	int (*trigger)(struct snd_pcm_substream *, int,
 		struct snd_soc_dai *);
 	int (*bespoke_trigger)(struct snd_pcm_substream *, int,
@@ -276,6 +286,13 @@
 		dai->capture_dma_data = data;
 }
 
+static inline void snd_soc_dai_init_dma_data(struct snd_soc_dai *dai,
+					     void *playback, void *capture)
+{
+	dai->playback_dma_data = playback;
+	dai->capture_dma_data = capture;
+}
+
 static inline void snd_soc_dai_set_drvdata(struct snd_soc_dai *dai,
 		void *data)
 {
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 27a72d5..2037c45 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -286,6 +286,8 @@
 	.info = snd_soc_info_volsw, \
 	.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
 	.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) }
+#define SOC_DAPM_SINGLE_VIRT(xname, max) \
+	SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0)
 #define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
 	.info = snd_soc_info_volsw, \
@@ -300,6 +302,8 @@
 	.tlv.p = (tlv_array), \
 	.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
 	.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
+#define SOC_DAPM_SINGLE_TLV_VIRT(xname, max, tlv_array) \
+	SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0, tlv_array)
 #define SOC_DAPM_ENUM(xname, xenum) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
 	.info = snd_soc_info_enum_double, \
diff --git a/include/sound/soc.h b/include/sound/soc.h
index d22cb0a..1f741cb 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -13,6 +13,7 @@
 #ifndef __LINUX_SND_SOC_H
 #define __LINUX_SND_SOC_H
 
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/types.h>
 #include <linux/notifier.h>
@@ -330,7 +331,6 @@
 struct snd_soc_jack;
 struct snd_soc_jack_zone;
 struct snd_soc_jack_pin;
-struct snd_soc_cache_ops;
 #include <sound/soc-dapm.h>
 #include <sound/soc-dpcm.h>
 
@@ -348,10 +348,6 @@
 	SND_SOC_REGMAP,
 };
 
-enum snd_soc_compress_type {
-	SND_SOC_FLAT_COMPRESSION = 1,
-};
-
 enum snd_soc_pcm_subclass {
 	SND_SOC_PCM_CLASS_PCM	= 0,
 	SND_SOC_PCM_CLASS_BE	= 1,
@@ -369,6 +365,7 @@
 
 int snd_soc_register_card(struct snd_soc_card *card);
 int snd_soc_unregister_card(struct snd_soc_card *card);
+int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card);
 int snd_soc_suspend(struct device *dev);
 int snd_soc_resume(struct device *dev);
 int snd_soc_poweroff(struct device *dev);
@@ -386,6 +383,9 @@
 int snd_soc_register_component(struct device *dev,
 			 const struct snd_soc_component_driver *cmpnt_drv,
 			 struct snd_soc_dai_driver *dai_drv, int num_dai);
+int devm_snd_soc_register_component(struct device *dev,
+			 const struct snd_soc_component_driver *cmpnt_drv,
+			 struct snd_soc_dai_driver *dai_drv, int num_dai);
 void snd_soc_unregister_component(struct device *dev);
 int snd_soc_codec_volatile_register(struct snd_soc_codec *codec,
 				    unsigned int reg);
@@ -403,12 +403,6 @@
 			unsigned int reg, unsigned int value);
 int snd_soc_cache_read(struct snd_soc_codec *codec,
 		       unsigned int reg, unsigned int *value);
-int snd_soc_default_volatile_register(struct snd_soc_codec *codec,
-				      unsigned int reg);
-int snd_soc_default_readable_register(struct snd_soc_codec *codec,
-				      unsigned int reg);
-int snd_soc_default_writable_register(struct snd_soc_codec *codec,
-				      unsigned int reg);
 int snd_soc_platform_read(struct snd_soc_platform *platform,
 					unsigned int reg);
 int snd_soc_platform_write(struct snd_soc_platform *platform,
@@ -542,22 +536,6 @@
 	struct snd_ctl_elem_value *ucontrol);
 
 /**
- * struct snd_soc_reg_access - Describes whether a given register is
- * readable, writable or volatile.
- *
- * @reg: the register number
- * @read: whether this register is readable
- * @write: whether this register is writable
- * @vol: whether this register is volatile
- */
-struct snd_soc_reg_access {
-	u16 reg;
-	u16 read;
-	u16 write;
-	u16 vol;
-};
-
-/**
  * struct snd_soc_jack_pin - Describes a pin to update based on jack detection
  *
  * @pin:    name of the pin to update
@@ -657,17 +635,26 @@
 	int (*trigger)(struct snd_compr_stream *);
 };
 
-/* SoC cache ops */
-struct snd_soc_cache_ops {
+/* component interface */
+struct snd_soc_component_driver {
 	const char *name;
-	enum snd_soc_compress_type id;
-	int (*init)(struct snd_soc_codec *codec);
-	int (*exit)(struct snd_soc_codec *codec);
-	int (*read)(struct snd_soc_codec *codec, unsigned int reg,
-		unsigned int *value);
-	int (*write)(struct snd_soc_codec *codec, unsigned int reg,
-		unsigned int value);
-	int (*sync)(struct snd_soc_codec *codec);
+
+	/* DT */
+	int (*of_xlate_dai_name)(struct snd_soc_component *component,
+				 struct of_phandle_args *args,
+				 const char **dai_name);
+};
+
+struct snd_soc_component {
+	const char *name;
+	int id;
+	struct device *dev;
+	struct list_head list;
+
+	struct snd_soc_dai_driver *dai_drv;
+	int num_dai;
+
+	const struct snd_soc_component_driver *driver;
 };
 
 /* SoC Audio Codec device */
@@ -683,8 +670,6 @@
 	struct list_head list;
 	struct list_head card_list;
 	int num_dai;
-	enum snd_soc_compress_type compress_type;
-	size_t reg_size;	/* reg_cache_size * reg_word_size */
 	int (*volatile_register)(struct snd_soc_codec *, unsigned int);
 	int (*readable_register)(struct snd_soc_codec *, unsigned int);
 	int (*writable_register)(struct snd_soc_codec *, unsigned int);
@@ -708,13 +693,13 @@
 	unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int);
 	unsigned int (*read)(struct snd_soc_codec *, unsigned int);
 	int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
-	int (*bulk_write_raw)(struct snd_soc_codec *, unsigned int, const void *, size_t);
 	void *reg_cache;
-	const void *reg_def_copy;
-	const struct snd_soc_cache_ops *cache_ops;
 	struct mutex cache_rw_mutex;
 	int val_bytes;
 
+	/* component */
+	struct snd_soc_component component;
+
 	/* dapm */
 	struct snd_soc_dapm_context dapm;
 	unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */
@@ -733,6 +718,7 @@
 	int (*remove)(struct snd_soc_codec *);
 	int (*suspend)(struct snd_soc_codec *);
 	int (*resume)(struct snd_soc_codec *);
+	struct snd_soc_component_driver component_driver;
 
 	/* Default control and setup, added after probe() is run */
 	const struct snd_kcontrol_new *controls;
@@ -760,9 +746,6 @@
 	short reg_cache_step;
 	short reg_word_size;
 	const void *reg_cache_default;
-	short reg_access_size;
-	const struct snd_soc_reg_access *reg_access_default;
-	enum snd_soc_compress_type compress_type;
 
 	/* codec bias level */
 	int (*set_bias_level)(struct snd_soc_codec *,
@@ -849,20 +832,6 @@
 #endif
 };
 
-struct snd_soc_component_driver {
-	const char *name;
-};
-
-struct snd_soc_component {
-	const char *name;
-	int id;
-	int num_dai;
-	struct device *dev;
-	struct list_head list;
-
-	const struct snd_soc_component_driver *driver;
-};
-
 struct snd_soc_dai_link {
 	/* config - must be set by machine driver */
 	const char *name;			/* Codec name */
@@ -944,12 +913,6 @@
 	 * associated per device
 	 */
 	const char *name_prefix;
-
-	/*
-	 * set this to the desired compression type if you want to
-	 * override the one supplied in codec->driver->compress_type
-	 */
-	enum snd_soc_compress_type compress_type;
 };
 
 struct snd_soc_aux_dev {
@@ -1088,7 +1051,8 @@
 /* mixer control */
 struct soc_mixer_control {
 	int min, max, platform_max;
-	unsigned int reg, rreg, shift, rshift;
+	int reg, rreg;
+	unsigned int shift, rshift;
 	unsigned int invert:1;
 	unsigned int autodisable:1;
 };
@@ -1121,8 +1085,6 @@
 unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg);
 unsigned int snd_soc_write(struct snd_soc_codec *codec,
 			   unsigned int reg, unsigned int val);
-unsigned int snd_soc_bulk_write_raw(struct snd_soc_codec *codec,
-				    unsigned int reg, const void *data, size_t len);
 
 /* device driver data */
 
@@ -1201,6 +1163,8 @@
 				   const char *propname);
 unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
 				     const char *prefix);
+int snd_soc_of_get_dai_name(struct device_node *of_node,
+			    const char **dai_name);
 
 #include <sound/soc-dai.h>
 
diff --git a/include/trace/events/asoc.h b/include/trace/events/asoc.h
index 5fc2dcd..03996b2 100644
--- a/include/trace/events/asoc.h
+++ b/include/trace/events/asoc.h
@@ -14,6 +14,7 @@
 struct snd_soc_platform;
 struct snd_soc_card;
 struct snd_soc_dapm_widget;
+struct snd_soc_dapm_path;
 
 /*
  * Log register events
diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
index 52ae548..e0dc355 100644
--- a/include/trace/events/f2fs.h
+++ b/include/trace/events/f2fs.h
@@ -36,6 +36,11 @@
 		{ CURSEG_COLD_NODE, 	"Cold NODE" },			\
 		{ NO_CHECK_TYPE, 	"No TYPE" })
 
+#define show_file_type(type)						\
+	__print_symbolic(type,						\
+		{ 0,		"FILE" },				\
+		{ 1,		"DIR" })
+
 #define show_gc_type(type)						\
 	__print_symbolic(type,						\
 		{ FG_GC,	"Foreground GC" },			\
@@ -623,6 +628,52 @@
 		__entry->size)
 );
 
+DECLARE_EVENT_CLASS(f2fs__page,
+
+	TP_PROTO(struct page *page, int type),
+
+	TP_ARGS(page, type),
+
+	TP_STRUCT__entry(
+		__field(dev_t,	dev)
+		__field(ino_t,	ino)
+		__field(int, type)
+		__field(int, dir)
+		__field(pgoff_t, index)
+		__field(int, dirty)
+	),
+
+	TP_fast_assign(
+		__entry->dev	= page->mapping->host->i_sb->s_dev;
+		__entry->ino	= page->mapping->host->i_ino;
+		__entry->type	= type;
+		__entry->dir	= S_ISDIR(page->mapping->host->i_mode);
+		__entry->index	= page->index;
+		__entry->dirty	= PageDirty(page);
+	),
+
+	TP_printk("dev = (%d,%d), ino = %lu, %s, %s, index = %lu, dirty = %d",
+		show_dev_ino(__entry),
+		show_block_type(__entry->type),
+		show_file_type(__entry->dir),
+		(unsigned long)__entry->index,
+		__entry->dirty)
+);
+
+DEFINE_EVENT(f2fs__page, f2fs_set_page_dirty,
+
+	TP_PROTO(struct page *page, int type),
+
+	TP_ARGS(page, type)
+);
+
+DEFINE_EVENT(f2fs__page, f2fs_vm_page_mkwrite,
+
+	TP_PROTO(struct page *page, int type),
+
+	TP_ARGS(page, type)
+);
+
 TRACE_EVENT(f2fs_submit_write_page,
 
 	TP_PROTO(struct page *page, block_t blk_addr, int type),
diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h
index ee2376c..aca3822 100644
--- a/include/trace/events/rcu.h
+++ b/include/trace/events/rcu.h
@@ -39,15 +39,26 @@
 #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU)
 
 /*
- * Tracepoint for grace-period events: starting and ending a grace
- * period ("start" and "end", respectively), a CPU noting the start
- * of a new grace period or the end of an old grace period ("cpustart"
- * and "cpuend", respectively), a CPU passing through a quiescent
- * state ("cpuqs"), a CPU coming online or going offline ("cpuonl"
- * and "cpuofl", respectively), a CPU being kicked for being too
- * long in dyntick-idle mode ("kick"), a CPU accelerating its new
- * callbacks to RCU_NEXT_READY_TAIL ("AccReadyCB"), and a CPU
- * accelerating its new callbacks to RCU_WAIT_TAIL ("AccWaitCB").
+ * Tracepoint for grace-period events.  Takes a string identifying the
+ * RCU flavor, the grace-period number, and a string identifying the
+ * grace-period-related event as follows:
+ *
+ *	"AccReadyCB": CPU acclerates new callbacks to RCU_NEXT_READY_TAIL.
+ *	"AccWaitCB": CPU accelerates new callbacks to RCU_WAIT_TAIL.
+ *	"newreq": Request a new grace period.
+ *	"start": Start a grace period.
+ *	"cpustart": CPU first notices a grace-period start.
+ *	"cpuqs": CPU passes through a quiescent state.
+ *	"cpuonl": CPU comes online.
+ *	"cpuofl": CPU goes offline.
+ *	"reqwait": GP kthread sleeps waiting for grace-period request.
+ *	"reqwaitsig": GP kthread awakened by signal from reqwait state.
+ *	"fqswait": GP kthread waiting until time to force quiescent states.
+ *	"fqsstart": GP kthread starts forcing quiescent states.
+ *	"fqsend": GP kthread done forcing quiescent states.
+ *	"fqswaitsig": GP kthread awakened by signal from fqswait state.
+ *	"end": End a grace period.
+ *	"cpuend": CPU first notices a grace-period end.
  */
 TRACE_EVENT(rcu_grace_period,
 
@@ -161,6 +172,46 @@
 );
 
 /*
+ * Tracepoint for RCU no-CBs CPU callback handoffs.  This event is intended
+ * to assist debugging of these handoffs.
+ *
+ * The first argument is the name of the RCU flavor, and the second is
+ * the number of the offloaded CPU are extracted.  The third and final
+ * argument is a string as follows:
+ *
+ *	"WakeEmpty": Wake rcuo kthread, first CB to empty list.
+ *	"WakeOvf": Wake rcuo kthread, CB list is huge.
+ *	"WakeNot": Don't wake rcuo kthread.
+ *	"WakeNotPoll": Don't wake rcuo kthread because it is polling.
+ *	"Poll": Start of new polling cycle for rcu_nocb_poll.
+ *	"Sleep": Sleep waiting for CBs for !rcu_nocb_poll.
+ *	"WokeEmpty": rcuo kthread woke to find empty list.
+ *	"WokeNonEmpty": rcuo kthread woke to find non-empty list.
+ *	"WaitQueue": Enqueue partially done, timed wait for it to complete.
+ *	"WokeQueue": Partial enqueue now complete.
+ */
+TRACE_EVENT(rcu_nocb_wake,
+
+	TP_PROTO(const char *rcuname, int cpu, const char *reason),
+
+	TP_ARGS(rcuname, cpu, reason),
+
+	TP_STRUCT__entry(
+		__field(const char *, rcuname)
+		__field(int, cpu)
+		__field(const char *, reason)
+	),
+
+	TP_fast_assign(
+		__entry->rcuname = rcuname;
+		__entry->cpu = cpu;
+		__entry->reason = reason;
+	),
+
+	TP_printk("%s %d %s", __entry->rcuname, __entry->cpu, __entry->reason)
+);
+
+/*
  * Tracepoint for tasks blocking within preemptible-RCU read-side
  * critical sections.  Track the type of RCU (which one day might
  * include SRCU), the grace-period number that the task is blocking
@@ -540,17 +591,17 @@
 TRACE_EVENT(rcu_batch_end,
 
 	TP_PROTO(const char *rcuname, int callbacks_invoked,
-		 bool cb, bool nr, bool iit, bool risk),
+		 char cb, char nr, char iit, char risk),
 
 	TP_ARGS(rcuname, callbacks_invoked, cb, nr, iit, risk),
 
 	TP_STRUCT__entry(
 		__field(const char *, rcuname)
 		__field(int, callbacks_invoked)
-		__field(bool, cb)
-		__field(bool, nr)
-		__field(bool, iit)
-		__field(bool, risk)
+		__field(char, cb)
+		__field(char, nr)
+		__field(char, iit)
+		__field(char, risk)
 	),
 
 	TP_fast_assign(
@@ -656,6 +707,7 @@
 #define trace_rcu_future_grace_period(rcuname, gpnum, completed, c, \
 				      level, grplo, grphi, event) \
 				      do { } while (0)
+#define trace_rcu_nocb_wake(rcuname, cpu, reason) do { } while (0)
 #define trace_rcu_preempt_task(rcuname, pid, gpnum) do { } while (0)
 #define trace_rcu_unlock_preempted_task(rcuname, gpnum, pid) do { } while (0)
 #define trace_rcu_quiescent_state_report(rcuname, gpnum, mask, qsmask, level, \
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index 2e7d994..613381b 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -100,7 +100,7 @@
 	/*
 	 * For all intents and purposes a preempted task is a running task.
 	 */
-	if (task_thread_info(p)->preempt_count & PREEMPT_ACTIVE)
+	if (task_preempt_count(p) & PREEMPT_ACTIVE)
 		state = TASK_RUNNING | TASK_STATE_MAX;
 #endif
 
diff --git a/include/trace/events/spi.h b/include/trace/events/spi.h
new file mode 100644
index 0000000..7e02c98
--- /dev/null
+++ b/include/trace/events/spi.h
@@ -0,0 +1,156 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM spi
+
+#if !defined(_TRACE_SPI_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_SPI_H
+
+#include <linux/ktime.h>
+#include <linux/tracepoint.h>
+
+DECLARE_EVENT_CLASS(spi_master,
+
+	TP_PROTO(struct spi_master *master),
+
+	TP_ARGS(master),
+
+	TP_STRUCT__entry(
+		__field(        int,           bus_num             )
+	),
+
+	TP_fast_assign(
+		__entry->bus_num = master->bus_num;
+	),
+
+	TP_printk("spi%d", (int)__entry->bus_num)
+
+);
+
+DEFINE_EVENT(spi_master, spi_master_idle,
+
+	TP_PROTO(struct spi_master *master),
+
+	TP_ARGS(master)
+
+);
+
+DEFINE_EVENT(spi_master, spi_master_busy,
+
+	TP_PROTO(struct spi_master *master),
+
+	TP_ARGS(master)
+
+);
+
+DECLARE_EVENT_CLASS(spi_message,
+
+	TP_PROTO(struct spi_message *msg),
+
+	TP_ARGS(msg),
+
+	TP_STRUCT__entry(
+		__field(        int,            bus_num         )
+		__field(        int,            chip_select     )
+		__field(        struct spi_message *,   msg     )
+	),
+
+	TP_fast_assign(
+		__entry->bus_num = msg->spi->master->bus_num;
+		__entry->chip_select = msg->spi->chip_select;
+		__entry->msg = msg;
+	),
+
+        TP_printk("spi%d.%d %p", (int)__entry->bus_num,
+		  (int)__entry->chip_select,
+		  (struct spi_message *)__entry->msg)
+);
+
+DEFINE_EVENT(spi_message, spi_message_submit,
+
+	TP_PROTO(struct spi_message *msg),
+
+	TP_ARGS(msg)
+
+);
+
+DEFINE_EVENT(spi_message, spi_message_start,
+
+	TP_PROTO(struct spi_message *msg),
+
+	TP_ARGS(msg)
+
+);
+
+TRACE_EVENT(spi_message_done,
+
+	TP_PROTO(struct spi_message *msg),
+
+	TP_ARGS(msg),
+
+	TP_STRUCT__entry(
+		__field(        int,            bus_num         )
+		__field(        int,            chip_select     )
+		__field(        struct spi_message *,   msg     )
+		__field(        unsigned,       frame           )
+		__field(        unsigned,       actual          )
+	),
+
+	TP_fast_assign(
+		__entry->bus_num = msg->spi->master->bus_num;
+		__entry->chip_select = msg->spi->chip_select;
+		__entry->msg = msg;
+		__entry->frame = msg->frame_length;
+		__entry->actual = msg->actual_length;
+	),
+
+        TP_printk("spi%d.%d %p len=%u/%u", (int)__entry->bus_num,
+		  (int)__entry->chip_select,
+		  (struct spi_message *)__entry->msg,
+                  (unsigned)__entry->actual, (unsigned)__entry->frame)
+);
+
+DECLARE_EVENT_CLASS(spi_transfer,
+
+	TP_PROTO(struct spi_message *msg, struct spi_transfer *xfer),
+
+	TP_ARGS(msg, xfer),
+
+	TP_STRUCT__entry(
+		__field(        int,            bus_num         )
+		__field(        int,            chip_select     )
+		__field(        struct spi_transfer *,   xfer   )
+		__field(        int,            len             )
+	),
+
+	TP_fast_assign(
+		__entry->bus_num = msg->spi->master->bus_num;
+		__entry->chip_select = msg->spi->chip_select;
+		__entry->xfer = xfer;
+		__entry->len = xfer->len;
+	),
+
+        TP_printk("spi%d.%d %p len=%d", (int)__entry->bus_num,
+		  (int)__entry->chip_select,
+		  (struct spi_message *)__entry->xfer,
+		  (int)__entry->len)
+);
+
+DEFINE_EVENT(spi_transfer, spi_transfer_start,
+
+	TP_PROTO(struct spi_message *msg, struct spi_transfer *xfer),
+
+	TP_ARGS(msg, xfer)
+
+);
+
+DEFINE_EVENT(spi_transfer, spi_transfer_stop,
+
+	TP_PROTO(struct spi_message *msg, struct spi_transfer *xfer),
+
+	TP_ARGS(msg, xfer)
+
+);
+
+#endif /* _TRACE_POWER_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/target.h b/include/trace/events/target.h
index aef8fc3..da9cc0f 100644
--- a/include/trace/events/target.h
+++ b/include/trace/events/target.h
@@ -144,7 +144,7 @@
 	),
 
 	TP_fast_assign(
-		__entry->unpacked_lun	= cmd->se_lun->unpacked_lun;
+		__entry->unpacked_lun	= cmd->orig_fe_lun;
 		__entry->opcode		= cmd->t_task_cdb[0];
 		__entry->data_length	= cmd->data_length;
 		__entry->task_attribute	= cmd->sam_task_attr;
@@ -182,7 +182,7 @@
 	),
 
 	TP_fast_assign(
-		__entry->unpacked_lun	= cmd->se_lun->unpacked_lun;
+		__entry->unpacked_lun	= cmd->orig_fe_lun;
 		__entry->opcode		= cmd->t_task_cdb[0];
 		__entry->data_length	= cmd->data_length;
 		__entry->task_attribute	= cmd->sam_task_attr;
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 5508117..28acbaf 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -223,6 +223,8 @@
 	__u32 connection;
 	__u32 mm_width, mm_height; /**< HxW in millimeters */
 	__u32 subpixel;
+
+	__u32 pad;
 };
 
 #define DRM_MODE_PROP_PENDING	(1<<0)
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index 115add2..33d2b8f 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -241,6 +241,8 @@
 header-y += mei.h
 header-y += mempolicy.h
 header-y += meye.h
+header-y += mic_common.h
+header-y += mic_ioctl.h
 header-y += mii.h
 header-y += minix_fs.h
 header-y += mman.h
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 75cef3f..db0b825 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -329,7 +329,6 @@
 #define AUDIT_ARCH_ARMEB	(EM_ARM)
 #define AUDIT_ARCH_CRIS		(EM_CRIS|__AUDIT_ARCH_LE)
 #define AUDIT_ARCH_FRV		(EM_FRV)
-#define AUDIT_ARCH_H8300	(EM_H8_300)
 #define AUDIT_ARCH_I386		(EM_386|__AUDIT_ARCH_LE)
 #define AUDIT_ARCH_IA64		(EM_IA_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
 #define AUDIT_ARCH_M32R		(EM_M32R)
diff --git a/include/uapi/linux/elf-em.h b/include/uapi/linux/elf-em.h
index 59c17a2..01529bd 100644
--- a/include/uapi/linux/elf-em.h
+++ b/include/uapi/linux/elf-em.h
@@ -31,7 +31,6 @@
 #define EM_CRIS		76	/* Axis Communications 32-bit embedded processor */
 #define EM_V850		87	/* NEC v850 */
 #define EM_M32R		88	/* Renesas M32R */
-#define EM_H8_300	46	/* Renesas H8/300,300H,H8S */
 #define EM_MN10300	89	/* Panasonic/MEI MN10300, AM33 */
 #define EM_BLACKFIN     106     /* ADI Blackfin Processor */
 #define EM_TI_C6000	140	/* TI C6X DSPs */
diff --git a/include/uapi/linux/mic_common.h b/include/uapi/linux/mic_common.h
new file mode 100644
index 0000000..17e7d95
--- /dev/null
+++ b/include/uapi/linux/mic_common.h
@@ -0,0 +1,240 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC driver.
+ *
+ */
+#ifndef __MIC_COMMON_H_
+#define __MIC_COMMON_H_
+
+#include <linux/virtio_ring.h>
+
+#ifndef __KERNEL__
+#define ALIGN(a, x)	(((a) + (x) - 1) & ~((x) - 1))
+#define __aligned(x)	__attribute__ ((aligned(x)))
+#endif
+
+#define mic_aligned_size(x) ALIGN(sizeof(x), 8)
+
+/**
+ * struct mic_device_desc: Virtio device information shared between the
+ * virtio driver and userspace backend
+ *
+ * @type: Device type: console/network/disk etc.  Type 0/-1 terminates.
+ * @num_vq: Number of virtqueues.
+ * @feature_len: Number of bytes of feature bits.  Multiply by 2: one for
+   host features and one for guest acknowledgements.
+ * @config_len: Number of bytes of the config array after virtqueues.
+ * @status: A status byte, written by the Guest.
+ * @config: Start of the following variable length config.
+ */
+struct mic_device_desc {
+	__s8 type;
+	__u8 num_vq;
+	__u8 feature_len;
+	__u8 config_len;
+	__u8 status;
+	__u64 config[0];
+} __aligned(8);
+
+/**
+ * struct mic_device_ctrl: Per virtio device information in the device page
+ * used internally by the host and card side drivers.
+ *
+ * @vdev: Used for storing MIC vdev information by the guest.
+ * @config_change: Set to 1 by host when a config change is requested.
+ * @vdev_reset: Set to 1 by guest to indicate virtio device has been reset.
+ * @guest_ack: Set to 1 by guest to ack a command.
+ * @host_ack: Set to 1 by host to ack a command.
+ * @used_address_updated: Set to 1 by guest when the used address should be
+ * updated.
+ * @c2h_vdev_db: The doorbell number to be used by guest. Set by host.
+ * @h2c_vdev_db: The doorbell number to be used by host. Set by guest.
+ */
+struct mic_device_ctrl {
+	__u64 vdev;
+	__u8 config_change;
+	__u8 vdev_reset;
+	__u8 guest_ack;
+	__u8 host_ack;
+	__u8 used_address_updated;
+	__s8 c2h_vdev_db;
+	__s8 h2c_vdev_db;
+} __aligned(8);
+
+/**
+ * struct mic_bootparam: Virtio device independent information in device page
+ *
+ * @magic: A magic value used by the card to ensure it can see the host
+ * @c2h_shutdown_db: Card to Host shutdown doorbell set by host
+ * @h2c_shutdown_db: Host to Card shutdown doorbell set by card
+ * @h2c_config_db: Host to Card Virtio config doorbell set by card
+ * @shutdown_status: Card shutdown status set by card
+ * @shutdown_card: Set to 1 by the host when a card shutdown is initiated
+ */
+struct mic_bootparam {
+	__u32 magic;
+	__s8 c2h_shutdown_db;
+	__s8 h2c_shutdown_db;
+	__s8 h2c_config_db;
+	__u8 shutdown_status;
+	__u8 shutdown_card;
+} __aligned(8);
+
+/**
+ * struct mic_device_page: High level representation of the device page
+ *
+ * @bootparam: The bootparam structure is used for sharing information and
+ * status updates between MIC host and card drivers.
+ * @desc: Array of MIC virtio device descriptors.
+ */
+struct mic_device_page {
+	struct mic_bootparam bootparam;
+	struct mic_device_desc desc[0];
+};
+/**
+ * struct mic_vqconfig: This is how we expect the device configuration field
+ * for a virtqueue to be laid out in config space.
+ *
+ * @address: Guest/MIC physical address of the virtio ring
+ * (avail and desc rings)
+ * @used_address: Guest/MIC physical address of the used ring
+ * @num: The number of entries in the virtio_ring
+ */
+struct mic_vqconfig {
+	__u64 address;
+	__u64 used_address;
+	__u16 num;
+} __aligned(8);
+
+/*
+ * The alignment to use between consumer and producer parts of vring.
+ * This is pagesize for historical reasons.
+ */
+#define MIC_VIRTIO_RING_ALIGN		4096
+
+#define MIC_MAX_VRINGS			4
+#define MIC_VRING_ENTRIES		128
+
+/*
+ * Max vring entries (power of 2) to ensure desc and avail rings
+ * fit in a single page
+ */
+#define MIC_MAX_VRING_ENTRIES		128
+
+/**
+ * Max size of the desc block in bytes: includes:
+ *	- struct mic_device_desc
+ *	- struct mic_vqconfig (num_vq of these)
+ *	- host and guest features
+ *	- virtio device config space
+ */
+#define MIC_MAX_DESC_BLK_SIZE		256
+
+/**
+ * struct _mic_vring_info - Host vring info exposed to userspace backend
+ * for the avail index and magic for the card.
+ *
+ * @avail_idx: host avail idx
+ * @magic: A magic debug cookie.
+ */
+struct _mic_vring_info {
+	__u16 avail_idx;
+	int magic;
+};
+
+/**
+ * struct mic_vring - Vring information.
+ *
+ * @vr: The virtio ring.
+ * @info: Host vring information exposed to the userspace backend for the
+ * avail index and magic for the card.
+ * @va: The va for the buffer allocated for vr and info.
+ * @len: The length of the buffer required for allocating vr and info.
+ */
+struct mic_vring {
+	struct vring vr;
+	struct _mic_vring_info *info;
+	void *va;
+	int len;
+};
+
+#define mic_aligned_desc_size(d) ALIGN(mic_desc_size(d), 8)
+
+#ifndef INTEL_MIC_CARD
+static inline unsigned mic_desc_size(const struct mic_device_desc *desc)
+{
+	return mic_aligned_size(*desc)
+		+ desc->num_vq * mic_aligned_size(struct mic_vqconfig)
+		+ desc->feature_len * 2
+		+ desc->config_len;
+}
+
+static inline struct mic_vqconfig *
+mic_vq_config(const struct mic_device_desc *desc)
+{
+	return (struct mic_vqconfig *)(desc + 1);
+}
+
+static inline __u8 *mic_vq_features(const struct mic_device_desc *desc)
+{
+	return (__u8 *)(mic_vq_config(desc) + desc->num_vq);
+}
+
+static inline __u8 *mic_vq_configspace(const struct mic_device_desc *desc)
+{
+	return mic_vq_features(desc) + desc->feature_len * 2;
+}
+static inline unsigned mic_total_desc_size(struct mic_device_desc *desc)
+{
+	return mic_aligned_desc_size(desc) +
+		mic_aligned_size(struct mic_device_ctrl);
+}
+#endif
+
+/* Device page size */
+#define MIC_DP_SIZE 4096
+
+#define MIC_MAGIC 0xc0ffee00
+
+/**
+ * enum mic_states - MIC states.
+ */
+enum mic_states {
+	MIC_OFFLINE = 0,
+	MIC_ONLINE,
+	MIC_SHUTTING_DOWN,
+	MIC_RESET_FAILED,
+	MIC_SUSPENDING,
+	MIC_SUSPENDED,
+	MIC_LAST
+};
+
+/**
+ * enum mic_status - MIC status reported by card after
+ * a host or card initiated shutdown or a card crash.
+ */
+enum mic_status {
+	MIC_NOP = 0,
+	MIC_CRASHED,
+	MIC_HALTED,
+	MIC_POWER_OFF,
+	MIC_RESTART,
+	MIC_STATUS_LAST
+};
+
+#endif
diff --git a/include/uapi/linux/mic_ioctl.h b/include/uapi/linux/mic_ioctl.h
new file mode 100644
index 0000000..7fabba5
--- /dev/null
+++ b/include/uapi/linux/mic_ioctl.h
@@ -0,0 +1,76 @@
+/*
+ * Intel MIC Platform Software Stack (MPSS)
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Intel MIC Host driver.
+ *
+ */
+#ifndef _MIC_IOCTL_H_
+#define _MIC_IOCTL_H_
+
+#include <linux/types.h>
+
+/*
+ * mic_copy - MIC virtio descriptor copy.
+ *
+ * @iov: An array of IOVEC structures containing user space buffers.
+ * @iovcnt: Number of IOVEC structures in iov.
+ * @vr_idx: The vring index.
+ * @update_used: A non zero value results in used index being updated.
+ * @out_len: The aggregate of the total length written to or read from
+ *	the virtio device.
+ */
+struct mic_copy_desc {
+#ifdef __KERNEL__
+	struct iovec __user *iov;
+#else
+	struct iovec *iov;
+#endif
+	int iovcnt;
+	__u8 vr_idx;
+	__u8 update_used;
+	__u32 out_len;
+};
+
+/*
+ * Add a new virtio device
+ * The (struct mic_device_desc *) pointer points to a device page entry
+ *	for the virtio device consisting of:
+ *	- struct mic_device_desc
+ *	- struct mic_vqconfig (num_vq of these)
+ *	- host and guest features
+ *	- virtio device config space
+ * The total size referenced by the pointer should equal the size returned
+ * by desc_size() in mic_common.h
+ */
+#define MIC_VIRTIO_ADD_DEVICE _IOWR('s', 1, struct mic_device_desc *)
+
+/*
+ * Copy the number of entries in the iovec and update the used index
+ * if requested by the user.
+ */
+#define MIC_VIRTIO_COPY_DESC	_IOWR('s', 2, struct mic_copy_desc *)
+
+/*
+ * Notify virtio device of a config change
+ * The (__u8 *) pointer points to config space values for the device
+ * as they should be written into the device page. The total size
+ * referenced by the pointer should equal the config_len field of struct
+ * mic_device_desc.
+ */
+#define MIC_VIRTIO_CONFIG_CHANGE _IOWR('s', 5, __u8 *)
+
+#endif
diff --git a/include/uapi/linux/nfs_mount.h b/include/uapi/linux/nfs_mount.h
index 576bddd..64b0f22 100644
--- a/include/uapi/linux/nfs_mount.h
+++ b/include/uapi/linux/nfs_mount.h
@@ -60,7 +60,7 @@
 #define NFS_MOUNT_BROKEN_SUID	0x0400	/* 4 */
 #define NFS_MOUNT_NOACL		0x0800	/* 4 */
 #define NFS_MOUNT_STRICTLOCK	0x1000	/* reserved for NFSv4 */
-#define NFS_MOUNT_SECFLAVOUR	0x2000	/* 5 */
+#define NFS_MOUNT_SECFLAVOUR	0x2000	/* 5 non-text parsed mount data only */
 #define NFS_MOUNT_NORDIRPLUS	0x4000	/* 5 */
 #define NFS_MOUNT_UNSHARED	0x8000	/* 5 */
 #define NFS_MOUNT_FLAGMASK	0xFFFF
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 009a655..e1802d6 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -136,8 +136,9 @@
 	PERF_SAMPLE_WEIGHT			= 1U << 14,
 	PERF_SAMPLE_DATA_SRC			= 1U << 15,
 	PERF_SAMPLE_IDENTIFIER			= 1U << 16,
+	PERF_SAMPLE_TRANSACTION			= 1U << 17,
 
-	PERF_SAMPLE_MAX = 1U << 17,		/* non-ABI */
+	PERF_SAMPLE_MAX = 1U << 18,		/* non-ABI */
 };
 
 /*
@@ -181,6 +182,28 @@
 };
 
 /*
+ * Values for the memory transaction event qualifier, mostly for
+ * abort events. Multiple bits can be set.
+ */
+enum {
+	PERF_TXN_ELISION        = (1 << 0), /* From elision */
+	PERF_TXN_TRANSACTION    = (1 << 1), /* From transaction */
+	PERF_TXN_SYNC           = (1 << 2), /* Instruction is related */
+	PERF_TXN_ASYNC          = (1 << 3), /* Instruction not related */
+	PERF_TXN_RETRY          = (1 << 4), /* Retry possible */
+	PERF_TXN_CONFLICT       = (1 << 5), /* Conflict abort */
+	PERF_TXN_CAPACITY_WRITE = (1 << 6), /* Capacity write abort */
+	PERF_TXN_CAPACITY_READ  = (1 << 7), /* Capacity read abort */
+
+	PERF_TXN_MAX	        = (1 << 8), /* non-ABI */
+
+	/* bits 32..63 are reserved for the abort code */
+
+	PERF_TXN_ABORT_MASK  = (0xffffffffULL << 32),
+	PERF_TXN_ABORT_SHIFT = 32,
+};
+
+/*
  * The format of the data returned by read() on a perf event fd,
  * as specified by attr.read_format:
  *
@@ -456,13 +479,15 @@
 	/*
 	 * Control data for the mmap() data buffer.
 	 *
-	 * User-space reading the @data_head value should issue an rmb(), on
-	 * SMP capable platforms, after reading this value -- see
-	 * perf_event_wakeup().
+	 * User-space reading the @data_head value should issue an smp_rmb(),
+	 * after reading this value.
 	 *
 	 * When the mapping is PROT_WRITE the @data_tail value should be
-	 * written by userspace to reflect the last read data. In this case
-	 * the kernel will not over-write unread data.
+	 * written by userspace to reflect the last read data, after issueing
+	 * an smp_mb() to separate the data read from the ->data_tail store.
+	 * In this case the kernel will not over-write unread data.
+	 *
+	 * See perf_output_put_handle() for the data ordering.
 	 */
 	__u64   data_head;		/* head in the data section */
 	__u64	data_tail;		/* user-space written tail */
diff --git a/include/uapi/linux/tc_act/Kbuild b/include/uapi/linux/tc_act/Kbuild
index 0623ec4..56f1216 100644
--- a/include/uapi/linux/tc_act/Kbuild
+++ b/include/uapi/linux/tc_act/Kbuild
@@ -1,5 +1,6 @@
 # UAPI Header export list
 header-y += tc_csum.h
+header-y += tc_defact.h
 header-y += tc_gact.h
 header-y += tc_ipt.h
 header-y += tc_mirred.h
diff --git a/include/linux/tc_act/tc_defact.h b/include/uapi/linux/tc_act/tc_defact.h
similarity index 75%
rename from include/linux/tc_act/tc_defact.h
rename to include/uapi/linux/tc_act/tc_defact.h
index 6f65d07..17dddb4 100644
--- a/include/linux/tc_act/tc_defact.h
+++ b/include/uapi/linux/tc_act/tc_defact.h
@@ -6,7 +6,7 @@
 struct tc_defact {
 	tc_gen;
 };
-                                                                                
+
 enum {
 	TCA_DEF_UNSPEC,
 	TCA_DEF_TM,
diff --git a/include/uapi/rdma/ib_user_verbs.h b/include/uapi/rdma/ib_user_verbs.h
index 0b233c5..e3ddd86 100644
--- a/include/uapi/rdma/ib_user_verbs.h
+++ b/include/uapi/rdma/ib_user_verbs.h
@@ -87,8 +87,10 @@
 	IB_USER_VERBS_CMD_CLOSE_XRCD,
 	IB_USER_VERBS_CMD_CREATE_XSRQ,
 	IB_USER_VERBS_CMD_OPEN_QP,
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
 	IB_USER_VERBS_CMD_CREATE_FLOW = IB_USER_VERBS_CMD_THRESHOLD,
 	IB_USER_VERBS_CMD_DESTROY_FLOW
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
 };
 
 /*
@@ -126,6 +128,7 @@
 	__u16 out_words;
 };
 
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
 struct ib_uverbs_cmd_hdr_ex {
 	__u32 command;
 	__u16 in_words;
@@ -134,6 +137,7 @@
 	__u16 provider_out_words;
 	__u32 cmd_hdr_reserved;
 };
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
 
 struct ib_uverbs_get_context {
 	__u64 response;
@@ -696,6 +700,7 @@
 	__u64 driver_data[0];
 };
 
+#ifdef CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING
 struct ib_kern_eth_filter {
 	__u8  dst_mac[6];
 	__u8  src_mac[6];
@@ -780,6 +785,7 @@
 	__u32 comp_mask;
 	__u32 flow_handle;
 };
+#endif /* CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING */
 
 struct ib_uverbs_create_srq {
 	__u64 response;
diff --git a/include/uapi/sound/Kbuild b/include/uapi/sound/Kbuild
index 0f7d279..a7f2770 100644
--- a/include/uapi/sound/Kbuild
+++ b/include/uapi/sound/Kbuild
@@ -5,6 +5,7 @@
 header-y += compress_offload.h
 header-y += compress_params.h
 header-y += emu10k1.h
+header-y += firewire.h
 header-y += hdsp.h
 header-y += hdspm.h
 header-y += sb16_csp.h
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
index 041203f..9fc6219 100644
--- a/include/uapi/sound/asound.h
+++ b/include/uapi/sound/asound.h
@@ -93,9 +93,10 @@
 	SNDRV_HWDEP_IFACE_SB_RC,	/* SB Extigy/Audigy2NX remote control */
 	SNDRV_HWDEP_IFACE_HDA,		/* HD-audio */
 	SNDRV_HWDEP_IFACE_USB_STREAM,	/* direct access to usb stream */
+	SNDRV_HWDEP_IFACE_FW_DICE,	/* TC DICE FireWire device */
 
 	/* Don't forget to change the following: */
-	SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM
+	SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_FW_DICE
 };
 
 struct snd_hwdep_info {
diff --git a/include/uapi/sound/firewire.h b/include/uapi/sound/firewire.h
new file mode 100644
index 0000000..59f5961
--- /dev/null
+++ b/include/uapi/sound/firewire.h
@@ -0,0 +1,51 @@
+#ifndef _UAPI_SOUND_FIREWIRE_H_INCLUDED
+#define _UAPI_SOUND_FIREWIRE_H_INCLUDED
+
+#include <linux/ioctl.h>
+
+/* events can be read() from the hwdep device */
+
+#define SNDRV_FIREWIRE_EVENT_LOCK_STATUS	0x000010cc
+#define SNDRV_FIREWIRE_EVENT_DICE_NOTIFICATION	0xd1ce004e
+
+struct snd_firewire_event_common {
+	unsigned int type; /* SNDRV_FIREWIRE_EVENT_xxx */
+};
+
+struct snd_firewire_event_lock_status {
+	unsigned int type;
+	unsigned int status; /* 0/1 = unlocked/locked */
+};
+
+struct snd_firewire_event_dice_notification {
+	unsigned int type;
+	unsigned int notification; /* DICE-specific bits */
+};
+
+union snd_firewire_event {
+	struct snd_firewire_event_common            common;
+	struct snd_firewire_event_lock_status       lock_status;
+	struct snd_firewire_event_dice_notification dice_notification;
+};
+
+
+#define SNDRV_FIREWIRE_IOCTL_GET_INFO _IOR('H', 0xf8, struct snd_firewire_get_info)
+#define SNDRV_FIREWIRE_IOCTL_LOCK      _IO('H', 0xf9)
+#define SNDRV_FIREWIRE_IOCTL_UNLOCK    _IO('H', 0xfa)
+
+#define SNDRV_FIREWIRE_TYPE_DICE	1
+/* Fireworks, AV/C, RME, MOTU, ... */
+
+struct snd_firewire_get_info {
+	unsigned int type; /* SNDRV_FIREWIRE_TYPE_xxx */
+	unsigned int card; /* same as fw_cdev_get_info.card */
+	unsigned char guid[8];
+	char device_name[16]; /* device node in /dev */
+};
+
+/*
+ * SNDRV_FIREWIRE_IOCTL_LOCK prevents the driver from streaming.
+ * Returns -EBUSY if the driver is already streaming.
+ */
+
+#endif /* _UAPI_SOUND_FIREWIRE_H_INCLUDED */
diff --git a/include/video/exynos_dp.h b/include/video/exynos_dp.h
deleted file mode 100644
index bd8cabd..0000000
--- a/include/video/exynos_dp.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Samsung SoC DP device support
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _EXYNOS_DP_H
-#define _EXYNOS_DP_H
-
-#define DP_TIMEOUT_LOOP_COUNT 100
-#define MAX_CR_LOOP 5
-#define MAX_EQ_LOOP 5
-
-enum link_rate_type {
-	LINK_RATE_1_62GBPS = 0x06,
-	LINK_RATE_2_70GBPS = 0x0a
-};
-
-enum link_lane_count_type {
-	LANE_COUNT1 = 1,
-	LANE_COUNT2 = 2,
-	LANE_COUNT4 = 4
-};
-
-enum link_training_state {
-	START,
-	CLOCK_RECOVERY,
-	EQUALIZER_TRAINING,
-	FINISHED,
-	FAILED
-};
-
-enum voltage_swing_level {
-	VOLTAGE_LEVEL_0,
-	VOLTAGE_LEVEL_1,
-	VOLTAGE_LEVEL_2,
-	VOLTAGE_LEVEL_3,
-};
-
-enum pre_emphasis_level {
-	PRE_EMPHASIS_LEVEL_0,
-	PRE_EMPHASIS_LEVEL_1,
-	PRE_EMPHASIS_LEVEL_2,
-	PRE_EMPHASIS_LEVEL_3,
-};
-
-enum pattern_set {
-	PRBS7,
-	D10_2,
-	TRAINING_PTN1,
-	TRAINING_PTN2,
-	DP_NONE
-};
-
-enum color_space {
-	COLOR_RGB,
-	COLOR_YCBCR422,
-	COLOR_YCBCR444
-};
-
-enum color_depth {
-	COLOR_6,
-	COLOR_8,
-	COLOR_10,
-	COLOR_12
-};
-
-enum color_coefficient {
-	COLOR_YCBCR601,
-	COLOR_YCBCR709
-};
-
-enum dynamic_range {
-	VESA,
-	CEA
-};
-
-enum pll_status {
-	PLL_UNLOCKED,
-	PLL_LOCKED
-};
-
-enum clock_recovery_m_value_type {
-	CALCULATED_M,
-	REGISTER_M
-};
-
-enum video_timing_recognition_type {
-	VIDEO_TIMING_FROM_CAPTURE,
-	VIDEO_TIMING_FROM_REGISTER
-};
-
-enum analog_power_block {
-	AUX_BLOCK,
-	CH0_BLOCK,
-	CH1_BLOCK,
-	CH2_BLOCK,
-	CH3_BLOCK,
-	ANALOG_TOTAL,
-	POWER_ALL
-};
-
-struct video_info {
-	char *name;
-
-	bool h_sync_polarity;
-	bool v_sync_polarity;
-	bool interlaced;
-
-	enum color_space color_space;
-	enum dynamic_range dynamic_range;
-	enum color_coefficient ycbcr_coeff;
-	enum color_depth color_depth;
-
-	enum link_rate_type link_rate;
-	enum link_lane_count_type lane_count;
-};
-
-struct exynos_dp_platdata {
-	struct video_info *video_info;
-
-	void (*phy_init)(void);
-	void (*phy_exit)(void);
-};
-
-#endif /* _EXYNOS_DP_H */
diff --git a/include/video/exynos_mipi_dsim.h b/include/video/exynos_mipi_dsim.h
index 89dc88a..6a578f8 100644
--- a/include/video/exynos_mipi_dsim.h
+++ b/include/video/exynos_mipi_dsim.h
@@ -216,6 +216,7 @@
  *	automatically.
  * @e_clk_src: select byte clock source.
  * @pd: pointer to MIPI-DSI driver platform data.
+ * @phy: pointer to the MIPI-DSI PHY
  */
 struct mipi_dsim_device {
 	struct device			*dev;
@@ -236,6 +237,7 @@
 	bool				suspended;
 
 	struct mipi_dsim_platform_data	*pd;
+	struct phy			*phy;
 };
 
 /*
@@ -248,7 +250,6 @@
  * @enabled: indicate whether mipi controller got enabled or not.
  * @lcd_panel_info: pointer for lcd panel specific structure.
  *	this structure specifies width, height, timing and polarity and so on.
- * @phy_enable: pointer to a callback controlling D-PHY enable/reset
  */
 struct mipi_dsim_platform_data {
 	char				lcd_panel_name[PANEL_NAME_SIZE];
@@ -256,8 +257,6 @@
 	struct mipi_dsim_config		*dsim_config;
 	unsigned int			enabled;
 	void				*lcd_panel_info;
-
-	int (*phy_enable)(struct platform_device *pdev, bool on);
 };
 
 /*
diff --git a/init/Kconfig b/init/Kconfig
index 3ecd8a1..bc8911f 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -284,7 +284,7 @@
 
 config AUDITSYSCALL
 	bool "Enable system-call auditing support"
-	depends on AUDIT && (X86 || PPC || S390 || IA64 || UML || SPARC64 || SUPERH || (ARM && AEABI && !OABI_COMPAT))
+	depends on AUDIT && (X86 || PARISC || PPC || S390 || IA64 || UML || SPARC64 || SUPERH || (ARM && AEABI && !OABI_COMPAT))
 	default y if SECURITY_SELINUX
 	help
 	  Enable low-overhead system-call auditing infrastructure that
@@ -354,7 +354,8 @@
 
 config VIRT_CPU_ACCOUNTING_GEN
 	bool "Full dynticks CPU time accounting"
-	depends on HAVE_CONTEXT_TRACKING && 64BIT
+	depends on HAVE_CONTEXT_TRACKING
+	depends on HAVE_VIRT_CPU_ACCOUNTING_GEN
 	select VIRT_CPU_ACCOUNTING
 	select CONTEXT_TRACKING
 	help
diff --git a/init/main.c b/init/main.c
index af310af..379090f 100644
--- a/init/main.c
+++ b/init/main.c
@@ -76,6 +76,7 @@
 #include <linux/elevator.h>
 #include <linux/sched_clock.h>
 #include <linux/context_tracking.h>
+#include <linux/random.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -692,7 +693,7 @@
 
 	if (preempt_count() != count) {
 		sprintf(msgbuf, "preemption imbalance ");
-		preempt_count() = count;
+		preempt_count_set(count);
 	}
 	if (irqs_disabled()) {
 		strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf));
@@ -780,6 +781,7 @@
 	do_ctors();
 	usermodehelper_enable();
 	do_initcalls();
+	random_int_secret_init();
 }
 
 static void __init do_pre_smp_initcalls(void)
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
index 130dfec..b0e99de 100644
--- a/ipc/ipc_sysctl.c
+++ b/ipc/ipc_sysctl.c
@@ -62,7 +62,7 @@
 	return err;
 }
 
-static int proc_ipc_callback_dointvec(ctl_table *table, int write,
+static int proc_ipc_callback_dointvec_minmax(ctl_table *table, int write,
 	void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	struct ctl_table ipc_table;
@@ -72,7 +72,7 @@
 	memcpy(&ipc_table, table, sizeof(ipc_table));
 	ipc_table.data = get_ipc(table);
 
-	rc = proc_dointvec(&ipc_table, write, buffer, lenp, ppos);
+	rc = proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
 
 	if (write && !rc && lenp_bef == *lenp)
 		/*
@@ -152,15 +152,13 @@
 #define proc_ipc_dointvec	   NULL
 #define proc_ipc_dointvec_minmax   NULL
 #define proc_ipc_dointvec_minmax_orphans   NULL
-#define proc_ipc_callback_dointvec NULL
+#define proc_ipc_callback_dointvec_minmax  NULL
 #define proc_ipcauto_dointvec_minmax NULL
 #endif
 
 static int zero;
 static int one = 1;
-#ifdef CONFIG_CHECKPOINT_RESTORE
 static int int_max = INT_MAX;
-#endif
 
 static struct ctl_table ipc_kern_table[] = {
 	{
@@ -198,21 +196,27 @@
 		.data		= &init_ipc_ns.msg_ctlmax,
 		.maxlen		= sizeof (init_ipc_ns.msg_ctlmax),
 		.mode		= 0644,
-		.proc_handler	= proc_ipc_dointvec,
+		.proc_handler	= proc_ipc_dointvec_minmax,
+		.extra1		= &zero,
+		.extra2		= &int_max,
 	},
 	{
 		.procname	= "msgmni",
 		.data		= &init_ipc_ns.msg_ctlmni,
 		.maxlen		= sizeof (init_ipc_ns.msg_ctlmni),
 		.mode		= 0644,
-		.proc_handler	= proc_ipc_callback_dointvec,
+		.proc_handler	= proc_ipc_callback_dointvec_minmax,
+		.extra1		= &zero,
+		.extra2		= &int_max,
 	},
 	{
 		.procname	=  "msgmnb",
 		.data		= &init_ipc_ns.msg_ctlmnb,
 		.maxlen		= sizeof (init_ipc_ns.msg_ctlmnb),
 		.mode		= 0644,
-		.proc_handler	= proc_ipc_dointvec,
+		.proc_handler	= proc_ipc_dointvec_minmax,
+		.extra1		= &zero,
+		.extra2		= &int_max,
 	},
 	{
 		.procname	= "sem",
diff --git a/ipc/sem.c b/ipc/sem.c
index 8c4f59b..db9d241 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -1282,6 +1282,12 @@
 
 	sem_lock(sma, NULL, -1);
 
+	if (sma->sem_perm.deleted) {
+		sem_unlock(sma, -1);
+		rcu_read_unlock();
+		return -EIDRM;
+	}
+
 	curr = &sma->sem_base[semnum];
 
 	ipc_assert_locked_object(&sma->sem_perm);
@@ -1336,12 +1342,14 @@
 		int i;
 
 		sem_lock(sma, NULL, -1);
+		if (sma->sem_perm.deleted) {
+			err = -EIDRM;
+			goto out_unlock;
+		}
 		if(nsems > SEMMSL_FAST) {
 			if (!ipc_rcu_getref(sma)) {
-				sem_unlock(sma, -1);
-				rcu_read_unlock();
 				err = -EIDRM;
-				goto out_free;
+				goto out_unlock;
 			}
 			sem_unlock(sma, -1);
 			rcu_read_unlock();
@@ -1354,10 +1362,8 @@
 			rcu_read_lock();
 			sem_lock_and_putref(sma);
 			if (sma->sem_perm.deleted) {
-				sem_unlock(sma, -1);
-				rcu_read_unlock();
 				err = -EIDRM;
-				goto out_free;
+				goto out_unlock;
 			}
 		}
 		for (i = 0; i < sma->sem_nsems; i++)
@@ -1375,8 +1381,8 @@
 		struct sem_undo *un;
 
 		if (!ipc_rcu_getref(sma)) {
-			rcu_read_unlock();
-			return -EIDRM;
+			err = -EIDRM;
+			goto out_rcu_wakeup;
 		}
 		rcu_read_unlock();
 
@@ -1404,10 +1410,8 @@
 		rcu_read_lock();
 		sem_lock_and_putref(sma);
 		if (sma->sem_perm.deleted) {
-			sem_unlock(sma, -1);
-			rcu_read_unlock();
 			err = -EIDRM;
-			goto out_free;
+			goto out_unlock;
 		}
 
 		for (i = 0; i < nsems; i++)
@@ -1431,6 +1435,10 @@
 		goto out_rcu_wakeup;
 
 	sem_lock(sma, NULL, -1);
+	if (sma->sem_perm.deleted) {
+		err = -EIDRM;
+		goto out_unlock;
+	}
 	curr = &sma->sem_base[semnum];
 
 	switch (cmd) {
@@ -1836,6 +1844,10 @@
 	if (error)
 		goto out_rcu_wakeup;
 
+	error = -EIDRM;
+	locknum = sem_lock(sma, sops, nsops);
+	if (sma->sem_perm.deleted)
+		goto out_unlock_free;
 	/*
 	 * semid identifiers are not unique - find_alloc_undo may have
 	 * allocated an undo structure, it was invalidated by an RMID
@@ -1843,8 +1855,6 @@
 	 * This case can be detected checking un->semid. The existence of
 	 * "un" itself is guaranteed by rcu.
 	 */
-	error = -EIDRM;
-	locknum = sem_lock(sma, sops, nsops);
 	if (un && un->semid == -1)
 		goto out_unlock_free;
 
@@ -2057,6 +2067,12 @@
 		}
 
 		sem_lock(sma, NULL, -1);
+		/* exit_sem raced with IPC_RMID, nothing to do */
+		if (sma->sem_perm.deleted) {
+			sem_unlock(sma, -1);
+			rcu_read_unlock();
+			continue;
+		}
 		un = __lookup_undo(ulp, semid);
 		if (un == NULL) {
 			/* exit_sem raced with IPC_RMID+semget() that created
diff --git a/ipc/util.c b/ipc/util.c
index fdb8ae7..7684f41 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -17,12 +17,27 @@
  *            Pavel Emelianov <xemul@openvz.org>
  *
  * General sysv ipc locking scheme:
- *  when doing ipc id lookups, take the ids->rwsem
- *      rcu_read_lock()
- *          obtain the ipc object (kern_ipc_perm)
- *          perform security, capabilities, auditing and permission checks, etc.
- *          acquire the ipc lock (kern_ipc_perm.lock) throught ipc_lock_object()
- *             perform data updates (ie: SET, RMID, LOCK/UNLOCK commands)
+ *	rcu_read_lock()
+ *          obtain the ipc object (kern_ipc_perm) by looking up the id in an idr
+ *	    tree.
+ *	    - perform initial checks (capabilities, auditing and permission,
+ *	      etc).
+ *	    - perform read-only operations, such as STAT, INFO commands.
+ *	      acquire the ipc lock (kern_ipc_perm.lock) through
+ *	      ipc_lock_object()
+ *		- perform data updates, such as SET, RMID commands and
+ *		  mechanism-specific operations (semop/semtimedop,
+ *		  msgsnd/msgrcv, shmat/shmdt).
+ *	    drop the ipc lock, through ipc_unlock_object().
+ *	rcu_read_unlock()
+ *
+ *  The ids->rwsem must be taken when:
+ *	- creating, removing and iterating the existing entries in ipc
+ *	  identifier sets.
+ *	- iterating through files under /proc/sysvipc/
+ *
+ *  Note that sems have a special fast path that avoids kern_ipc_perm.lock -
+ *  see sem_lock().
  */
 
 #include <linux/mm.h>
diff --git a/kernel/Makefile b/kernel/Makefile
index 1ce4755..a4d1aa8 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -6,9 +6,9 @@
 	    cpu.o exit.o itimer.o time.o softirq.o resource.o \
 	    sysctl.o sysctl_binary.o capability.o ptrace.o timer.o user.o \
 	    signal.o sys.o kmod.o workqueue.o pid.o task_work.o \
-	    rcupdate.o extable.o params.o posix-timers.o \
-	    kthread.o wait.o sys_ni.o posix-cpu-timers.o mutex.o \
-	    hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \
+	    extable.o params.o posix-timers.o \
+	    kthread.o sys_ni.o posix-cpu-timers.o mutex.o \
+	    hrtimer.o rwsem.o nsproxy.o semaphore.o \
 	    notifier.o ksysfs.o cred.o reboot.o \
 	    async.o range.o groups.o lglock.o smpboot.o
 
@@ -27,6 +27,7 @@
 obj-y += printk/
 obj-y += cpu/
 obj-y += irq/
+obj-y += rcu/
 
 obj-$(CONFIG_CHECKPOINT_RESTORE) += kcmp.o
 obj-$(CONFIG_FREEZER) += freezer.o
@@ -81,12 +82,6 @@
 obj-$(CONFIG_DETECT_HUNG_TASK) += hung_task.o
 obj-$(CONFIG_LOCKUP_DETECTOR) += watchdog.o
 obj-$(CONFIG_SECCOMP) += seccomp.o
-obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
-obj-$(CONFIG_TREE_RCU) += rcutree.o
-obj-$(CONFIG_TREE_PREEMPT_RCU) += rcutree.o
-obj-$(CONFIG_TREE_RCU_TRACE) += rcutree_trace.o
-obj-$(CONFIG_TINY_RCU) += rcutiny.o
-obj-$(CONFIG_TINY_PREEMPT_RCU) += rcutiny.o
 obj-$(CONFIG_RELAY) += relay.o
 obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
 obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
diff --git a/kernel/bounds.c b/kernel/bounds.c
index 0c9b862..e8ca97b 100644
--- a/kernel/bounds.c
+++ b/kernel/bounds.c
@@ -10,6 +10,7 @@
 #include <linux/mmzone.h>
 #include <linux/kbuild.h>
 #include <linux/page_cgroup.h>
+#include <linux/log2.h>
 
 void foo(void)
 {
@@ -17,5 +18,8 @@
 	DEFINE(NR_PAGEFLAGS, __NR_PAGEFLAGS);
 	DEFINE(MAX_NR_ZONES, __MAX_NR_ZONES);
 	DEFINE(NR_PCG_FLAGS, __NR_PCG_FLAGS);
+#ifdef CONFIG_SMP
+	DEFINE(NR_CPUS_BITS, ilog2(CONFIG_NR_CPUS));
+#endif
 	/* End of constants */
 }
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 2418b6e..e0839bc 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -125,38 +125,6 @@
 };
 
 /*
- * CSS ID -- ID per subsys's Cgroup Subsys State(CSS). used only when
- * cgroup_subsys->use_id != 0.
- */
-#define CSS_ID_MAX	(65535)
-struct css_id {
-	/*
-	 * The css to which this ID points. This pointer is set to valid value
-	 * after cgroup is populated. If cgroup is removed, this will be NULL.
-	 * This pointer is expected to be RCU-safe because destroy()
-	 * is called after synchronize_rcu(). But for safe use, css_tryget()
-	 * should be used for avoiding race.
-	 */
-	struct cgroup_subsys_state __rcu *css;
-	/*
-	 * ID of this css.
-	 */
-	unsigned short id;
-	/*
-	 * Depth in hierarchy which this ID belongs to.
-	 */
-	unsigned short depth;
-	/*
-	 * ID is freed by RCU. (and lookup routine is RCU safe.)
-	 */
-	struct rcu_head rcu_head;
-	/*
-	 * Hierarchy of CSS ID belongs to.
-	 */
-	unsigned short stack[0]; /* Array of Length (depth+1) */
-};
-
-/*
  * cgroup_event represents events which userspace want to receive.
  */
 struct cgroup_event {
@@ -387,9 +355,6 @@
 static struct css_set init_css_set;
 static struct cgrp_cset_link init_cgrp_cset_link;
 
-static int cgroup_init_idr(struct cgroup_subsys *ss,
-			   struct cgroup_subsys_state *css);
-
 /*
  * css_set_lock protects the list of css_set objects, and the chain of
  * tasks off each css_set.  Nests outside task->alloc_lock due to
@@ -841,8 +806,6 @@
 	.capabilities	= BDI_CAP_NO_ACCT_AND_WRITEBACK,
 };
 
-static int alloc_css_id(struct cgroup_subsys_state *child_css);
-
 static struct inode *cgroup_new_inode(umode_t mode, struct super_block *sb)
 {
 	struct inode *inode = new_inode(sb);
@@ -2039,7 +2002,7 @@
 
 		/* @tsk either already exited or can't exit until the end */
 		if (tsk->flags & PF_EXITING)
-			continue;
+			goto next;
 
 		/* as per above, nr_threads may decrease, but not increase. */
 		BUG_ON(i >= group_size);
@@ -2047,7 +2010,7 @@
 		ent.cgrp = task_cgroup_from_root(tsk, root);
 		/* nothing to do if this task is already in the cgroup */
 		if (ent.cgrp == cgrp)
-			continue;
+			goto next;
 		/*
 		 * saying GFP_ATOMIC has no effect here because we did prealloc
 		 * earlier, but it's good form to communicate our expectations.
@@ -2055,7 +2018,7 @@
 		retval = flex_array_put(group, i, &ent, GFP_ATOMIC);
 		BUG_ON(retval != 0);
 		i++;
-
+	next:
 		if (!threadgroup)
 			break;
 	} while_each_thread(leader, tsk);
@@ -3188,11 +3151,9 @@
 
 	WARN_ON_ONCE(!rcu_read_lock_held());
 
-	/* if first iteration, visit the leftmost descendant */
-	if (!pos) {
-		next = css_leftmost_descendant(root);
-		return next != root ? next : NULL;
-	}
+	/* if first iteration, visit leftmost descendant which may be @root */
+	if (!pos)
+		return css_leftmost_descendant(root);
 
 	/* if we visited @root, we're done */
 	if (pos == root)
@@ -4242,21 +4203,6 @@
 				goto err;
 		}
 	}
-
-	/* This cgroup is ready now */
-	for_each_root_subsys(cgrp->root, ss) {
-		struct cgroup_subsys_state *css = cgroup_css(cgrp, ss);
-		struct css_id *id = rcu_dereference_protected(css->id, true);
-
-		/*
-		 * Update id->css pointer and make this css visible from
-		 * CSS ID functions. This pointer will be dereferened
-		 * from RCU-read-side without locks.
-		 */
-		if (id)
-			rcu_assign_pointer(id->css, css);
-	}
-
 	return 0;
 err:
 	cgroup_clear_dir(cgrp, subsys_mask);
@@ -4325,7 +4271,6 @@
 	css->cgroup = cgrp;
 	css->ss = ss;
 	css->flags = 0;
-	css->id = NULL;
 
 	if (cgrp->parent)
 		css->parent = cgroup_css(cgrp->parent, ss);
@@ -4457,12 +4402,6 @@
 			goto err_free_all;
 
 		init_css(css, ss, cgrp);
-
-		if (ss->use_id) {
-			err = alloc_css_id(css);
-			if (err)
-				goto err_free_all;
-		}
 	}
 
 	/*
@@ -4927,12 +4866,6 @@
 
 	/* our new subsystem will be attached to the dummy hierarchy. */
 	init_css(css, ss, cgroup_dummy_top);
-	/* init_idr must be after init_css() because it sets css->id. */
-	if (ss->use_id) {
-		ret = cgroup_init_idr(ss, css);
-		if (ret)
-			goto err_unload;
-	}
 
 	/*
 	 * Now we need to entangle the css into the existing css_sets. unlike
@@ -4998,9 +4931,6 @@
 
 	offline_css(cgroup_css(cgroup_dummy_top, ss));
 
-	if (ss->use_id)
-		idr_destroy(&ss->idr);
-
 	/* deassign the subsys_id */
 	cgroup_subsys[ss->subsys_id] = NULL;
 
@@ -5027,8 +4957,7 @@
 	/*
 	 * remove subsystem's css from the cgroup_dummy_top and free it -
 	 * need to free before marking as null because ss->css_free needs
-	 * the cgrp->subsys pointer to find their state. note that this
-	 * also takes care of freeing the css_id.
+	 * the cgrp->subsys pointer to find their state.
 	 */
 	ss->css_free(cgroup_css(cgroup_dummy_top, ss));
 	RCU_INIT_POINTER(cgroup_dummy_top->subsys[ss->subsys_id], NULL);
@@ -5099,8 +5028,6 @@
 	for_each_builtin_subsys(ss, i) {
 		if (!ss->early_init)
 			cgroup_init_subsys(ss);
-		if (ss->use_id)
-			cgroup_init_idr(ss, init_css_set.subsys[ss->subsys_id]);
 	}
 
 	/* allocate id for the dummy hierarchy */
@@ -5520,181 +5447,6 @@
 }
 __setup("cgroup_disable=", cgroup_disable);
 
-/*
- * Functons for CSS ID.
- */
-
-/* to get ID other than 0, this should be called when !cgroup_is_dead() */
-unsigned short css_id(struct cgroup_subsys_state *css)
-{
-	struct css_id *cssid;
-
-	/*
-	 * This css_id() can return correct value when somone has refcnt
-	 * on this or this is under rcu_read_lock(). Once css->id is allocated,
-	 * it's unchanged until freed.
-	 */
-	cssid = rcu_dereference_raw(css->id);
-
-	if (cssid)
-		return cssid->id;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(css_id);
-
-/**
- *  css_is_ancestor - test "root" css is an ancestor of "child"
- * @child: the css to be tested.
- * @root: the css supporsed to be an ancestor of the child.
- *
- * Returns true if "root" is an ancestor of "child" in its hierarchy. Because
- * this function reads css->id, the caller must hold rcu_read_lock().
- * But, considering usual usage, the csses should be valid objects after test.
- * Assuming that the caller will do some action to the child if this returns
- * returns true, the caller must take "child";s reference count.
- * If "child" is valid object and this returns true, "root" is valid, too.
- */
-
-bool css_is_ancestor(struct cgroup_subsys_state *child,
-		    const struct cgroup_subsys_state *root)
-{
-	struct css_id *child_id;
-	struct css_id *root_id;
-
-	child_id  = rcu_dereference(child->id);
-	if (!child_id)
-		return false;
-	root_id = rcu_dereference(root->id);
-	if (!root_id)
-		return false;
-	if (child_id->depth < root_id->depth)
-		return false;
-	if (child_id->stack[root_id->depth] != root_id->id)
-		return false;
-	return true;
-}
-
-void free_css_id(struct cgroup_subsys *ss, struct cgroup_subsys_state *css)
-{
-	struct css_id *id = rcu_dereference_protected(css->id, true);
-
-	/* When this is called before css_id initialization, id can be NULL */
-	if (!id)
-		return;
-
-	BUG_ON(!ss->use_id);
-
-	rcu_assign_pointer(id->css, NULL);
-	rcu_assign_pointer(css->id, NULL);
-	spin_lock(&ss->id_lock);
-	idr_remove(&ss->idr, id->id);
-	spin_unlock(&ss->id_lock);
-	kfree_rcu(id, rcu_head);
-}
-EXPORT_SYMBOL_GPL(free_css_id);
-
-/*
- * This is called by init or create(). Then, calls to this function are
- * always serialized (By cgroup_mutex() at create()).
- */
-
-static struct css_id *get_new_cssid(struct cgroup_subsys *ss, int depth)
-{
-	struct css_id *newid;
-	int ret, size;
-
-	BUG_ON(!ss->use_id);
-
-	size = sizeof(*newid) + sizeof(unsigned short) * (depth + 1);
-	newid = kzalloc(size, GFP_KERNEL);
-	if (!newid)
-		return ERR_PTR(-ENOMEM);
-
-	idr_preload(GFP_KERNEL);
-	spin_lock(&ss->id_lock);
-	/* Don't use 0. allocates an ID of 1-65535 */
-	ret = idr_alloc(&ss->idr, newid, 1, CSS_ID_MAX + 1, GFP_NOWAIT);
-	spin_unlock(&ss->id_lock);
-	idr_preload_end();
-
-	/* Returns error when there are no free spaces for new ID.*/
-	if (ret < 0)
-		goto err_out;
-
-	newid->id = ret;
-	newid->depth = depth;
-	return newid;
-err_out:
-	kfree(newid);
-	return ERR_PTR(ret);
-
-}
-
-static int __init_or_module cgroup_init_idr(struct cgroup_subsys *ss,
-					    struct cgroup_subsys_state *rootcss)
-{
-	struct css_id *newid;
-
-	spin_lock_init(&ss->id_lock);
-	idr_init(&ss->idr);
-
-	newid = get_new_cssid(ss, 0);
-	if (IS_ERR(newid))
-		return PTR_ERR(newid);
-
-	newid->stack[0] = newid->id;
-	RCU_INIT_POINTER(newid->css, rootcss);
-	RCU_INIT_POINTER(rootcss->id, newid);
-	return 0;
-}
-
-static int alloc_css_id(struct cgroup_subsys_state *child_css)
-{
-	struct cgroup_subsys_state *parent_css = css_parent(child_css);
-	struct css_id *child_id, *parent_id;
-	int i, depth;
-
-	parent_id = rcu_dereference_protected(parent_css->id, true);
-	depth = parent_id->depth + 1;
-
-	child_id = get_new_cssid(child_css->ss, depth);
-	if (IS_ERR(child_id))
-		return PTR_ERR(child_id);
-
-	for (i = 0; i < depth; i++)
-		child_id->stack[i] = parent_id->stack[i];
-	child_id->stack[depth] = child_id->id;
-	/*
-	 * child_id->css pointer will be set after this cgroup is available
-	 * see cgroup_populate_dir()
-	 */
-	rcu_assign_pointer(child_css->id, child_id);
-
-	return 0;
-}
-
-/**
- * css_lookup - lookup css by id
- * @ss: cgroup subsys to be looked into.
- * @id: the id
- *
- * Returns pointer to cgroup_subsys_state if there is valid one with id.
- * NULL if not. Should be called under rcu_read_lock()
- */
-struct cgroup_subsys_state *css_lookup(struct cgroup_subsys *ss, int id)
-{
-	struct css_id *cssid = NULL;
-
-	BUG_ON(!ss->use_id);
-	cssid = idr_find(&ss->idr, id);
-
-	if (unlikely(!cssid))
-		return NULL;
-
-	return rcu_dereference(cssid->css);
-}
-EXPORT_SYMBOL_GPL(css_lookup);
-
 /**
  * css_from_dir - get corresponding css from the dentry of a cgroup dir
  * @dentry: directory dentry of interest
diff --git a/kernel/context_tracking.c b/kernel/context_tracking.c
index 859c8df..e5f3917 100644
--- a/kernel/context_tracking.c
+++ b/kernel/context_tracking.c
@@ -120,7 +120,7 @@
  * instead of preempt_schedule() to exit user context if needed before
  * calling the scheduler.
  */
-void __sched notrace preempt_schedule_context(void)
+asmlinkage void __sched notrace preempt_schedule_context(void)
 {
 	enum ctx_state prev_ctx;
 
diff --git a/kernel/cpu.c b/kernel/cpu.c
index d7f07a2..63aa50d 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -308,6 +308,23 @@
 	}
 	smpboot_park_threads(cpu);
 
+	/*
+	 * By now we've cleared cpu_active_mask, wait for all preempt-disabled
+	 * and RCU users of this state to go away such that all new such users
+	 * will observe it.
+	 *
+	 * For CONFIG_PREEMPT we have preemptible RCU and its sync_rcu() might
+	 * not imply sync_sched(), so explicitly call both.
+	 */
+#ifdef CONFIG_PREEMPT
+	synchronize_sched();
+#endif
+	synchronize_rcu();
+
+	/*
+	 * So now all preempt/rcu users must observe !cpu_active().
+	 */
+
 	err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu));
 	if (err) {
 		/* CPU didn't die: tell everyone.  Can't complain. */
diff --git a/kernel/cpu/idle.c b/kernel/cpu/idle.c
index e695c0a..988573a 100644
--- a/kernel/cpu/idle.c
+++ b/kernel/cpu/idle.c
@@ -44,7 +44,7 @@
 	rcu_idle_enter();
 	trace_cpu_idle_rcuidle(0, smp_processor_id());
 	local_irq_enable();
-	while (!need_resched())
+	while (!tif_need_resched())
 		cpu_relax();
 	trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id());
 	rcu_idle_exit();
@@ -92,8 +92,7 @@
 			if (cpu_idle_force_poll || tick_check_broadcast_expired()) {
 				cpu_idle_poll();
 			} else {
-				current_clr_polling();
-				if (!need_resched()) {
+				if (!current_clr_polling_and_test()) {
 					stop_critical_timings();
 					rcu_idle_enter();
 					arch_cpu_idle();
@@ -103,9 +102,16 @@
 				} else {
 					local_irq_enable();
 				}
-				current_set_polling();
+				__current_set_polling();
 			}
 			arch_cpu_idle_exit();
+			/*
+			 * We need to test and propagate the TIF_NEED_RESCHED
+			 * bit here because we might not have send the
+			 * reschedule IPI to idle tasks.
+			 */
+			if (tif_need_resched())
+				set_preempt_need_resched();
 		}
 		tick_nohz_idle_exit();
 		schedule_preempt_disabled();
@@ -129,7 +135,7 @@
 	 */
 	boot_init_stack_canary();
 #endif
-	current_set_polling();
+	__current_set_polling();
 	arch_cpu_idle_prepare();
 	cpu_idle_loop();
 }
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
index 0506d44..7d2f35e 100644
--- a/kernel/debug/debug_core.c
+++ b/kernel/debug/debug_core.c
@@ -575,8 +575,12 @@
 		raw_spin_lock(&dbg_slave_lock);
 
 #ifdef CONFIG_SMP
+	/* If send_ready set, slaves are already waiting */
+	if (ks->send_ready)
+		atomic_set(ks->send_ready, 1);
+
 	/* Signal the other CPUs to enter kgdb_wait() */
-	if ((!kgdb_single_step) && kgdb_do_roundup)
+	else if ((!kgdb_single_step) && kgdb_do_roundup)
 		kgdb_roundup_cpus(flags);
 #endif
 
@@ -678,11 +682,11 @@
 	if (arch_kgdb_ops.enable_nmi)
 		arch_kgdb_ops.enable_nmi(0);
 
+	memset(ks, 0, sizeof(struct kgdb_state));
 	ks->cpu			= raw_smp_processor_id();
 	ks->ex_vector		= evector;
 	ks->signo		= signo;
 	ks->err_code		= ecode;
-	ks->kgdb_usethreadid	= 0;
 	ks->linux_regs		= regs;
 
 	if (kgdb_reenter_check(ks))
@@ -732,6 +736,30 @@
 	return 1;
 }
 
+int kgdb_nmicallin(int cpu, int trapnr, void *regs, atomic_t *send_ready)
+{
+#ifdef CONFIG_SMP
+	if (!kgdb_io_ready(0) || !send_ready)
+		return 1;
+
+	if (kgdb_info[cpu].enter_kgdb == 0) {
+		struct kgdb_state kgdb_var;
+		struct kgdb_state *ks = &kgdb_var;
+
+		memset(ks, 0, sizeof(struct kgdb_state));
+		ks->cpu			= cpu;
+		ks->ex_vector		= trapnr;
+		ks->signo		= SIGTRAP;
+		ks->err_code		= KGDB_KDB_REASON_SYSTEM_NMI;
+		ks->linux_regs		= regs;
+		ks->send_ready		= send_ready;
+		kgdb_cpu_enter(ks, regs, DCPU_WANT_MASTER);
+		return 0;
+	}
+#endif
+	return 1;
+}
+
 static void kgdb_console_write(struct console *co, const char *s,
    unsigned count)
 {
diff --git a/kernel/debug/debug_core.h b/kernel/debug/debug_core.h
index 2235967..572aa4f 100644
--- a/kernel/debug/debug_core.h
+++ b/kernel/debug/debug_core.h
@@ -26,6 +26,7 @@
 	unsigned long		threadid;
 	long			kgdb_usethreadid;
 	struct pt_regs		*linux_regs;
+	atomic_t		*send_ready;
 };
 
 /* Exception state values */
@@ -74,11 +75,13 @@
 extern int kdb_parse(const char *cmdstr);
 extern int kdb_common_init_state(struct kgdb_state *ks);
 extern int kdb_common_deinit_state(void);
+#define KGDB_KDB_REASON_SYSTEM_NMI KDB_REASON_SYSTEM_NMI
 #else /* ! CONFIG_KGDB_KDB */
 static inline int kdb_stub(struct kgdb_state *ks)
 {
 	return DBG_PASS_EVENT;
 }
+#define KGDB_KDB_REASON_SYSTEM_NMI 0
 #endif /* CONFIG_KGDB_KDB */
 
 #endif /* _DEBUG_CORE_H_ */
diff --git a/kernel/debug/kdb/kdb_debugger.c b/kernel/debug/kdb/kdb_debugger.c
index 328d18e..8859ca3 100644
--- a/kernel/debug/kdb/kdb_debugger.c
+++ b/kernel/debug/kdb/kdb_debugger.c
@@ -69,7 +69,10 @@
 	if (atomic_read(&kgdb_setting_breakpoint))
 		reason = KDB_REASON_KEYBOARD;
 
-	if (in_nmi())
+	if (ks->err_code == KDB_REASON_SYSTEM_NMI && ks->signo == SIGTRAP)
+		reason = KDB_REASON_SYSTEM_NMI;
+
+	else if (in_nmi())
 		reason = KDB_REASON_NMI;
 
 	for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) {
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c
index 00eb8f7..0b097c8 100644
--- a/kernel/debug/kdb/kdb_main.c
+++ b/kernel/debug/kdb/kdb_main.c
@@ -1200,6 +1200,9 @@
 			   instruction_pointer(regs));
 		kdb_dumpregs(regs);
 		break;
+	case KDB_REASON_SYSTEM_NMI:
+		kdb_printf("due to System NonMaskable Interrupt\n");
+		break;
 	case KDB_REASON_NMI:
 		kdb_printf("due to NonMaskable Interrupt @ "
 			   kdb_machreg_fmt "\n",
diff --git a/kernel/events/core.c b/kernel/events/core.c
index cb4238e..8c875ef 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -175,8 +175,8 @@
 static int max_samples_per_tick __read_mostly	= DIV_ROUND_UP(DEFAULT_MAX_SAMPLE_RATE, HZ);
 static int perf_sample_period_ns __read_mostly	= DEFAULT_SAMPLE_PERIOD_NS;
 
-static atomic_t perf_sample_allowed_ns __read_mostly =
-	ATOMIC_INIT( DEFAULT_SAMPLE_PERIOD_NS * DEFAULT_CPU_TIME_MAX_PERCENT / 100);
+static int perf_sample_allowed_ns __read_mostly =
+	DEFAULT_SAMPLE_PERIOD_NS * DEFAULT_CPU_TIME_MAX_PERCENT / 100;
 
 void update_perf_cpu_limits(void)
 {
@@ -184,7 +184,7 @@
 
 	tmp *= sysctl_perf_cpu_time_max_percent;
 	do_div(tmp, 100);
-	atomic_set(&perf_sample_allowed_ns, tmp);
+	ACCESS_ONCE(perf_sample_allowed_ns) = tmp;
 }
 
 static int perf_rotate_context(struct perf_cpu_context *cpuctx);
@@ -193,7 +193,7 @@
 		void __user *buffer, size_t *lenp,
 		loff_t *ppos)
 {
-	int ret = proc_dointvec(table, write, buffer, lenp, ppos);
+	int ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
 
 	if (ret || !write)
 		return ret;
@@ -228,14 +228,15 @@
  * we detect that events are taking too long.
  */
 #define NR_ACCUMULATED_SAMPLES 128
-DEFINE_PER_CPU(u64, running_sample_length);
+static DEFINE_PER_CPU(u64, running_sample_length);
 
 void perf_sample_event_took(u64 sample_len_ns)
 {
 	u64 avg_local_sample_len;
 	u64 local_samples_len;
+	u64 allowed_ns = ACCESS_ONCE(perf_sample_allowed_ns);
 
-	if (atomic_read(&perf_sample_allowed_ns) == 0)
+	if (allowed_ns == 0)
 		return;
 
 	/* decay the counter by 1 average sample */
@@ -251,7 +252,7 @@
 	 */
 	avg_local_sample_len = local_samples_len/NR_ACCUMULATED_SAMPLES;
 
-	if (avg_local_sample_len <= atomic_read(&perf_sample_allowed_ns))
+	if (avg_local_sample_len <= allowed_ns)
 		return;
 
 	if (max_samples_per_tick <= 1)
@@ -262,10 +263,9 @@
 	perf_sample_period_ns = NSEC_PER_SEC / sysctl_perf_event_sample_rate;
 
 	printk_ratelimited(KERN_WARNING
-			"perf samples too long (%lld > %d), lowering "
+			"perf samples too long (%lld > %lld), lowering "
 			"kernel.perf_event_max_sample_rate to %d\n",
-			avg_local_sample_len,
-			atomic_read(&perf_sample_allowed_ns),
+			avg_local_sample_len, allowed_ns,
 			sysctl_perf_event_sample_rate);
 
 	update_perf_cpu_limits();
@@ -899,6 +899,7 @@
 		put_ctx(ctx->parent_ctx);
 		ctx->parent_ctx = NULL;
 	}
+	ctx->generation++;
 }
 
 static u32 perf_event_pid(struct perf_event *event, struct task_struct *p)
@@ -1136,6 +1137,8 @@
 	ctx->nr_events++;
 	if (event->attr.inherit_stat)
 		ctx->nr_stat++;
+
+	ctx->generation++;
 }
 
 /*
@@ -1201,6 +1204,9 @@
 	if (sample_type & PERF_SAMPLE_DATA_SRC)
 		size += sizeof(data->data_src.val);
 
+	if (sample_type & PERF_SAMPLE_TRANSACTION)
+		size += sizeof(data->txn);
+
 	event->header_size = size;
 }
 
@@ -1310,6 +1316,8 @@
 	 */
 	if (event->state > PERF_EVENT_STATE_OFF)
 		event->state = PERF_EVENT_STATE_OFF;
+
+	ctx->generation++;
 }
 
 static void perf_group_detach(struct perf_event *event)
@@ -2146,22 +2154,38 @@
 }
 
 /*
- * Test whether two contexts are equivalent, i.e. whether they
- * have both been cloned from the same version of the same context
- * and they both have the same number of enabled events.
- * If the number of enabled events is the same, then the set
- * of enabled events should be the same, because these are both
- * inherited contexts, therefore we can't access individual events
- * in them directly with an fd; we can only enable/disable all
- * events via prctl, or enable/disable all events in a family
- * via ioctl, which will have the same effect on both contexts.
+ * Test whether two contexts are equivalent, i.e. whether they have both been
+ * cloned from the same version of the same context.
+ *
+ * Equivalence is measured using a generation number in the context that is
+ * incremented on each modification to it; see unclone_ctx(), list_add_event()
+ * and list_del_event().
  */
 static int context_equiv(struct perf_event_context *ctx1,
 			 struct perf_event_context *ctx2)
 {
-	return ctx1->parent_ctx && ctx1->parent_ctx == ctx2->parent_ctx
-		&& ctx1->parent_gen == ctx2->parent_gen
-		&& !ctx1->pin_count && !ctx2->pin_count;
+	/* Pinning disables the swap optimization */
+	if (ctx1->pin_count || ctx2->pin_count)
+		return 0;
+
+	/* If ctx1 is the parent of ctx2 */
+	if (ctx1 == ctx2->parent_ctx && ctx1->generation == ctx2->parent_gen)
+		return 1;
+
+	/* If ctx2 is the parent of ctx1 */
+	if (ctx1->parent_ctx == ctx2 && ctx1->parent_gen == ctx2->generation)
+		return 1;
+
+	/*
+	 * If ctx1 and ctx2 have the same parent; we flatten the parent
+	 * hierarchy, see perf_event_init_context().
+	 */
+	if (ctx1->parent_ctx && ctx1->parent_ctx == ctx2->parent_ctx &&
+			ctx1->parent_gen == ctx2->parent_gen)
+		return 1;
+
+	/* Unmatched */
+	return 0;
 }
 
 static void __perf_event_sync_stat(struct perf_event *event,
@@ -2244,7 +2268,7 @@
 {
 	struct perf_event_context *ctx = task->perf_event_ctxp[ctxn];
 	struct perf_event_context *next_ctx;
-	struct perf_event_context *parent;
+	struct perf_event_context *parent, *next_parent;
 	struct perf_cpu_context *cpuctx;
 	int do_switch = 1;
 
@@ -2256,10 +2280,18 @@
 		return;
 
 	rcu_read_lock();
-	parent = rcu_dereference(ctx->parent_ctx);
 	next_ctx = next->perf_event_ctxp[ctxn];
-	if (parent && next_ctx &&
-	    rcu_dereference(next_ctx->parent_ctx) == parent) {
+	if (!next_ctx)
+		goto unlock;
+
+	parent = rcu_dereference(ctx->parent_ctx);
+	next_parent = rcu_dereference(next_ctx->parent_ctx);
+
+	/* If neither context have a parent context; they cannot be clones. */
+	if (!parent && !next_parent)
+		goto unlock;
+
+	if (next_parent == ctx || next_ctx == parent || next_parent == parent) {
 		/*
 		 * Looks like the two contexts are clones, so we might be
 		 * able to optimize the context switch.  We lock both
@@ -2287,6 +2319,7 @@
 		raw_spin_unlock(&next_ctx->lock);
 		raw_spin_unlock(&ctx->lock);
 	}
+unlock:
 	rcu_read_unlock();
 
 	if (do_switch) {
@@ -4572,6 +4605,9 @@
 	if (sample_type & PERF_SAMPLE_DATA_SRC)
 		perf_output_put(handle, data->data_src.val);
 
+	if (sample_type & PERF_SAMPLE_TRANSACTION)
+		perf_output_put(handle, data->txn);
+
 	if (!event->attr.watermark) {
 		int wakeup_events = event->attr.wakeup_events;
 
@@ -5100,27 +5136,26 @@
 	unsigned int size;
 	char tmp[16];
 	char *buf = NULL;
-	const char *name;
-
-	memset(tmp, 0, sizeof(tmp));
+	char *name;
 
 	if (file) {
 		struct inode *inode;
 		dev_t dev;
+
+		buf = kmalloc(PATH_MAX, GFP_KERNEL);
+		if (!buf) {
+			name = "//enomem";
+			goto cpy_name;
+		}
 		/*
-		 * d_path works from the end of the rb backwards, so we
+		 * d_path() works from the end of the rb backwards, so we
 		 * need to add enough zero bytes after the string to handle
 		 * the 64bit alignment we do later.
 		 */
-		buf = kzalloc(PATH_MAX + sizeof(u64), GFP_KERNEL);
-		if (!buf) {
-			name = strncpy(tmp, "//enomem", sizeof(tmp));
-			goto got_name;
-		}
-		name = d_path(&file->f_path, buf, PATH_MAX);
+		name = d_path(&file->f_path, buf, PATH_MAX - sizeof(u64));
 		if (IS_ERR(name)) {
-			name = strncpy(tmp, "//toolong", sizeof(tmp));
-			goto got_name;
+			name = "//toolong";
+			goto cpy_name;
 		}
 		inode = file_inode(vma->vm_file);
 		dev = inode->i_sb->s_dev;
@@ -5128,34 +5163,39 @@
 		gen = inode->i_generation;
 		maj = MAJOR(dev);
 		min = MINOR(dev);
-
-	} else {
-		if (arch_vma_name(mmap_event->vma)) {
-			name = strncpy(tmp, arch_vma_name(mmap_event->vma),
-				       sizeof(tmp) - 1);
-			tmp[sizeof(tmp) - 1] = '\0';
-			goto got_name;
-		}
-
-		if (!vma->vm_mm) {
-			name = strncpy(tmp, "[vdso]", sizeof(tmp));
-			goto got_name;
-		} else if (vma->vm_start <= vma->vm_mm->start_brk &&
-				vma->vm_end >= vma->vm_mm->brk) {
-			name = strncpy(tmp, "[heap]", sizeof(tmp));
-			goto got_name;
-		} else if (vma->vm_start <= vma->vm_mm->start_stack &&
-				vma->vm_end >= vma->vm_mm->start_stack) {
-			name = strncpy(tmp, "[stack]", sizeof(tmp));
-			goto got_name;
-		}
-
-		name = strncpy(tmp, "//anon", sizeof(tmp));
 		goto got_name;
+	} else {
+		name = (char *)arch_vma_name(vma);
+		if (name)
+			goto cpy_name;
+
+		if (vma->vm_start <= vma->vm_mm->start_brk &&
+				vma->vm_end >= vma->vm_mm->brk) {
+			name = "[heap]";
+			goto cpy_name;
+		}
+		if (vma->vm_start <= vma->vm_mm->start_stack &&
+				vma->vm_end >= vma->vm_mm->start_stack) {
+			name = "[stack]";
+			goto cpy_name;
+		}
+
+		name = "//anon";
+		goto cpy_name;
 	}
 
+cpy_name:
+	strlcpy(tmp, name, sizeof(tmp));
+	name = tmp;
 got_name:
-	size = ALIGN(strlen(name)+1, sizeof(u64));
+	/*
+	 * Since our buffer works in 8 byte units we need to align our string
+	 * size to a multiple of 8. However, we must guarantee the tail end is
+	 * zero'd out to avoid leaking random bits to userspace.
+	 */
+	size = strlen(name)+1;
+	while (!IS_ALIGNED(size, sizeof(u64)))
+		name[size++] = '\0';
 
 	mmap_event->file_name = name;
 	mmap_event->file_size = size;
@@ -6292,6 +6332,7 @@
 
 	return snprintf(page, PAGE_SIZE-1, "%d\n", pmu->type);
 }
+static DEVICE_ATTR_RO(type);
 
 static ssize_t
 perf_event_mux_interval_ms_show(struct device *dev,
@@ -6336,17 +6377,19 @@
 
 	return count;
 }
+static DEVICE_ATTR_RW(perf_event_mux_interval_ms);
 
-static struct device_attribute pmu_dev_attrs[] = {
-	__ATTR_RO(type),
-	__ATTR_RW(perf_event_mux_interval_ms),
-	__ATTR_NULL,
+static struct attribute *pmu_dev_attrs[] = {
+	&dev_attr_type.attr,
+	&dev_attr_perf_event_mux_interval_ms.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(pmu_dev);
 
 static int pmu_bus_running;
 static struct bus_type pmu_bus = {
 	.name		= "event_source",
-	.dev_attrs	= pmu_dev_attrs,
+	.dev_groups	= pmu_dev_groups,
 };
 
 static void pmu_dev_release(struct device *dev)
@@ -6767,6 +6810,10 @@
 	if (ret)
 		return -EFAULT;
 
+	/* disabled for now */
+	if (attr->mmap2)
+		return -EINVAL;
+
 	if (attr->__reserved_1)
 		return -EINVAL;
 
@@ -7122,7 +7169,6 @@
 	}
 
 	perf_install_in_context(ctx, event, event->cpu);
-	++ctx->generation;
 	perf_unpin_context(ctx);
 	mutex_unlock(&ctx->mutex);
 
@@ -7205,7 +7251,6 @@
 	WARN_ON_ONCE(ctx->parent_ctx);
 	mutex_lock(&ctx->mutex);
 	perf_install_in_context(ctx, event, cpu);
-	++ctx->generation;
 	perf_unpin_context(ctx);
 	mutex_unlock(&ctx->mutex);
 
@@ -7234,15 +7279,15 @@
 		perf_remove_from_context(event);
 		unaccount_event_cpu(event, src_cpu);
 		put_ctx(src_ctx);
-		list_add(&event->event_entry, &events);
+		list_add(&event->migrate_entry, &events);
 	}
 	mutex_unlock(&src_ctx->mutex);
 
 	synchronize_rcu();
 
 	mutex_lock(&dst_ctx->mutex);
-	list_for_each_entry_safe(event, tmp, &events, event_entry) {
-		list_del(&event->event_entry);
+	list_for_each_entry_safe(event, tmp, &events, migrate_entry) {
+		list_del(&event->migrate_entry);
 		if (event->state >= PERF_EVENT_STATE_OFF)
 			event->state = PERF_EVENT_STATE_INACTIVE;
 		account_event_cpu(event, dst_cpu);
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index ca65997..569b2187 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -82,16 +82,16 @@
 }
 
 #define DEFINE_OUTPUT_COPY(func_name, memcpy_func)			\
-static inline unsigned int						\
+static inline unsigned long						\
 func_name(struct perf_output_handle *handle,				\
-	  const void *buf, unsigned int len)				\
+	  const void *buf, unsigned long len)				\
 {									\
 	unsigned long size, written;					\
 									\
 	do {								\
-		size = min_t(unsigned long, handle->size, len);		\
-									\
+		size    = min(handle->size, len);			\
 		written = memcpy_func(handle->addr, buf, size);		\
+		written = size - written;				\
 									\
 		len -= written;						\
 		handle->addr += written;				\
@@ -110,20 +110,37 @@
 	return len;							\
 }
 
-static inline int memcpy_common(void *dst, const void *src, size_t n)
+static inline unsigned long
+memcpy_common(void *dst, const void *src, unsigned long n)
 {
 	memcpy(dst, src, n);
-	return n;
+	return 0;
 }
 
 DEFINE_OUTPUT_COPY(__output_copy, memcpy_common)
 
-#define MEMCPY_SKIP(dst, src, n) (n)
+static inline unsigned long
+memcpy_skip(void *dst, const void *src, unsigned long n)
+{
+	return 0;
+}
 
-DEFINE_OUTPUT_COPY(__output_skip, MEMCPY_SKIP)
+DEFINE_OUTPUT_COPY(__output_skip, memcpy_skip)
 
 #ifndef arch_perf_out_copy_user
-#define arch_perf_out_copy_user __copy_from_user_inatomic
+#define arch_perf_out_copy_user arch_perf_out_copy_user
+
+static inline unsigned long
+arch_perf_out_copy_user(void *dst, const void *src, unsigned long n)
+{
+	unsigned long ret;
+
+	pagefault_disable();
+	ret = __copy_from_user_inatomic(dst, src, n);
+	pagefault_enable();
+
+	return ret;
+}
 #endif
 
 DEFINE_OUTPUT_COPY(__output_copy_user, arch_perf_out_copy_user)
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index cd55144..e8b168a 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -12,40 +12,10 @@
 #include <linux/perf_event.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
+#include <linux/circ_buf.h>
 
 #include "internal.h"
 
-static bool perf_output_space(struct ring_buffer *rb, unsigned long tail,
-			      unsigned long offset, unsigned long head)
-{
-	unsigned long sz = perf_data_size(rb);
-	unsigned long mask = sz - 1;
-
-	/*
-	 * check if user-writable
-	 * overwrite : over-write its own tail
-	 * !overwrite: buffer possibly drops events.
-	 */
-	if (rb->overwrite)
-		return true;
-
-	/*
-	 * verify that payload is not bigger than buffer
-	 * otherwise masking logic may fail to detect
-	 * the "not enough space" condition
-	 */
-	if ((head - offset) > sz)
-		return false;
-
-	offset = (offset - tail) & mask;
-	head   = (head   - tail) & mask;
-
-	if ((int)(head - offset) < 0)
-		return false;
-
-	return true;
-}
-
 static void perf_output_wakeup(struct perf_output_handle *handle)
 {
 	atomic_set(&handle->rb->poll, POLL_IN);
@@ -87,15 +57,36 @@
 		goto out;
 
 	/*
-	 * Publish the known good head. Rely on the full barrier implied
-	 * by atomic_dec_and_test() order the rb->head read and this
-	 * write.
+	 * Since the mmap() consumer (userspace) can run on a different CPU:
+	 *
+	 *   kernel				user
+	 *
+	 *   READ ->data_tail			READ ->data_head
+	 *   smp_mb()	(A)			smp_rmb()	(C)
+	 *   WRITE $data			READ $data
+	 *   smp_wmb()	(B)			smp_mb()	(D)
+	 *   STORE ->data_head			WRITE ->data_tail
+	 *
+	 * Where A pairs with D, and B pairs with C.
+	 *
+	 * I don't think A needs to be a full barrier because we won't in fact
+	 * write data until we see the store from userspace. So we simply don't
+	 * issue the data WRITE until we observe it. Be conservative for now.
+	 *
+	 * OTOH, D needs to be a full barrier since it separates the data READ
+	 * from the tail WRITE.
+	 *
+	 * For B a WMB is sufficient since it separates two WRITEs, and for C
+	 * an RMB is sufficient since it separates two READs.
+	 *
+	 * See perf_output_begin().
 	 */
+	smp_wmb();
 	rb->user_page->data_head = head;
 
 	/*
-	 * Now check if we missed an update, rely on the (compiler)
-	 * barrier in atomic_dec_and_test() to re-read rb->head.
+	 * Now check if we missed an update -- rely on previous implied
+	 * compiler barriers to force a re-read.
 	 */
 	if (unlikely(head != local_read(&rb->head))) {
 		local_inc(&rb->nest);
@@ -114,8 +105,7 @@
 {
 	struct ring_buffer *rb;
 	unsigned long tail, offset, head;
-	int have_lost;
-	struct perf_sample_data sample_data;
+	int have_lost, page_shift;
 	struct {
 		struct perf_event_header header;
 		u64			 id;
@@ -130,55 +120,63 @@
 		event = event->parent;
 
 	rb = rcu_dereference(event->rb);
-	if (!rb)
+	if (unlikely(!rb))
 		goto out;
 
-	handle->rb	= rb;
-	handle->event	= event;
-
-	if (!rb->nr_pages)
+	if (unlikely(!rb->nr_pages))
 		goto out;
 
+	handle->rb    = rb;
+	handle->event = event;
+
 	have_lost = local_read(&rb->lost);
-	if (have_lost) {
-		lost_event.header.size = sizeof(lost_event);
-		perf_event_header__init_id(&lost_event.header, &sample_data,
-					   event);
-		size += lost_event.header.size;
+	if (unlikely(have_lost)) {
+		size += sizeof(lost_event);
+		if (event->attr.sample_id_all)
+			size += event->id_header_size;
 	}
 
 	perf_output_get_handle(handle);
 
 	do {
-		/*
-		 * Userspace could choose to issue a mb() before updating the
-		 * tail pointer. So that all reads will be completed before the
-		 * write is issued.
-		 */
 		tail = ACCESS_ONCE(rb->user_page->data_tail);
-		smp_rmb();
 		offset = head = local_read(&rb->head);
-		head += size;
-		if (unlikely(!perf_output_space(rb, tail, offset, head)))
+		if (!rb->overwrite &&
+		    unlikely(CIRC_SPACE(head, tail, perf_data_size(rb)) < size))
 			goto fail;
+		head += size;
 	} while (local_cmpxchg(&rb->head, offset, head) != offset);
 
-	if (head - local_read(&rb->wakeup) > rb->watermark)
+	/*
+	 * Separate the userpage->tail read from the data stores below.
+	 * Matches the MB userspace SHOULD issue after reading the data
+	 * and before storing the new tail position.
+	 *
+	 * See perf_output_put_handle().
+	 */
+	smp_mb();
+
+	if (unlikely(head - local_read(&rb->wakeup) > rb->watermark))
 		local_add(rb->watermark, &rb->wakeup);
 
-	handle->page = offset >> (PAGE_SHIFT + page_order(rb));
-	handle->page &= rb->nr_pages - 1;
-	handle->size = offset & ((PAGE_SIZE << page_order(rb)) - 1);
-	handle->addr = rb->data_pages[handle->page];
-	handle->addr += handle->size;
-	handle->size = (PAGE_SIZE << page_order(rb)) - handle->size;
+	page_shift = PAGE_SHIFT + page_order(rb);
 
-	if (have_lost) {
+	handle->page = (offset >> page_shift) & (rb->nr_pages - 1);
+	offset &= (1UL << page_shift) - 1;
+	handle->addr = rb->data_pages[handle->page] + offset;
+	handle->size = (1UL << page_shift) - offset;
+
+	if (unlikely(have_lost)) {
+		struct perf_sample_data sample_data;
+
+		lost_event.header.size = sizeof(lost_event);
 		lost_event.header.type = PERF_RECORD_LOST;
 		lost_event.header.misc = 0;
 		lost_event.id          = event->id;
 		lost_event.lost        = local_xchg(&rb->lost, 0);
 
+		perf_event_header__init_id(&lost_event.header,
+					   &sample_data, event);
 		perf_output_put(handle, lost_event);
 		perf_event__output_id_sample(event, handle, &sample_data);
 	}
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index ad8e1bd..24b7d6c 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -35,6 +35,7 @@
 #include <linux/kdebug.h>	/* notifier mechanism */
 #include "../../mm/internal.h"	/* munlock_vma_page */
 #include <linux/percpu-rwsem.h>
+#include <linux/task_work.h>
 
 #include <linux/uprobes.h>
 
@@ -244,12 +245,12 @@
  * the architecture. If an arch has variable length instruction and the
  * breakpoint instruction is not of the smallest length instruction
  * supported by that architecture then we need to modify is_trap_at_addr and
- * write_opcode accordingly. This would never be a problem for archs that
- * have fixed length instructions.
+ * uprobe_write_opcode accordingly. This would never be a problem for archs
+ * that have fixed length instructions.
  */
 
 /*
- * write_opcode - write the opcode at a given virtual address.
+ * uprobe_write_opcode - write the opcode at a given virtual address.
  * @mm: the probed process address space.
  * @vaddr: the virtual address to store the opcode.
  * @opcode: opcode to be written at @vaddr.
@@ -260,7 +261,7 @@
  * For mm @mm, write the opcode at @vaddr.
  * Return 0 (success) or a negative errno.
  */
-static int write_opcode(struct mm_struct *mm, unsigned long vaddr,
+int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr,
 			uprobe_opcode_t opcode)
 {
 	struct page *old_page, *new_page;
@@ -314,7 +315,7 @@
  */
 int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
 {
-	return write_opcode(mm, vaddr, UPROBE_SWBP_INSN);
+	return uprobe_write_opcode(mm, vaddr, UPROBE_SWBP_INSN);
 }
 
 /**
@@ -329,7 +330,7 @@
 int __weak
 set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
 {
-	return write_opcode(mm, vaddr, *(uprobe_opcode_t *)auprobe->insn);
+	return uprobe_write_opcode(mm, vaddr, *(uprobe_opcode_t *)auprobe->insn);
 }
 
 static int match_uprobe(struct uprobe *l, struct uprobe *r)
@@ -503,9 +504,8 @@
 	return ret;
 }
 
-static int
-__copy_insn(struct address_space *mapping, struct file *filp, char *insn,
-			unsigned long nbytes, loff_t offset)
+static int __copy_insn(struct address_space *mapping, struct file *filp,
+			void *insn, int nbytes, loff_t offset)
 {
 	struct page *page;
 
@@ -527,28 +527,28 @@
 
 static int copy_insn(struct uprobe *uprobe, struct file *filp)
 {
-	struct address_space *mapping;
-	unsigned long nbytes;
-	int bytes;
+	struct address_space *mapping = uprobe->inode->i_mapping;
+	loff_t offs = uprobe->offset;
+	void *insn = uprobe->arch.insn;
+	int size = MAX_UINSN_BYTES;
+	int len, err = -EIO;
 
-	nbytes = PAGE_SIZE - (uprobe->offset & ~PAGE_MASK);
-	mapping = uprobe->inode->i_mapping;
+	/* Copy only available bytes, -EIO if nothing was read */
+	do {
+		if (offs >= i_size_read(uprobe->inode))
+			break;
 
-	/* Instruction at end of binary; copy only available bytes */
-	if (uprobe->offset + MAX_UINSN_BYTES > uprobe->inode->i_size)
-		bytes = uprobe->inode->i_size - uprobe->offset;
-	else
-		bytes = MAX_UINSN_BYTES;
-
-	/* Instruction at the page-boundary; copy bytes in second page */
-	if (nbytes < bytes) {
-		int err = __copy_insn(mapping, filp, uprobe->arch.insn + nbytes,
-				bytes - nbytes, uprobe->offset + nbytes);
+		len = min_t(int, size, PAGE_SIZE - (offs & ~PAGE_MASK));
+		err = __copy_insn(mapping, filp, insn, len, offs);
 		if (err)
-			return err;
-		bytes = nbytes;
-	}
-	return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset);
+			break;
+
+		insn += len;
+		offs += len;
+		size -= len;
+	} while (size);
+
+	return err;
 }
 
 static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
@@ -576,7 +576,7 @@
 	if (ret)
 		goto out;
 
-	/* write_opcode() assumes we don't cross page boundary */
+	/* uprobe_write_opcode() assumes we don't cross page boundary */
 	BUG_ON((uprobe->offset & ~PAGE_MASK) +
 			UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
 
@@ -1096,21 +1096,22 @@
 }
 
 /* Slot allocation for XOL */
-static int xol_add_vma(struct xol_area *area)
+static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
 {
-	struct mm_struct *mm = current->mm;
 	int ret = -EALREADY;
 
 	down_write(&mm->mmap_sem);
 	if (mm->uprobes_state.xol_area)
 		goto fail;
 
-	ret = -ENOMEM;
-	/* Try to map as high as possible, this is only a hint. */
-	area->vaddr = get_unmapped_area(NULL, TASK_SIZE - PAGE_SIZE, PAGE_SIZE, 0, 0);
-	if (area->vaddr & ~PAGE_MASK) {
-		ret = area->vaddr;
-		goto fail;
+	if (!area->vaddr) {
+		/* Try to map as high as possible, this is only a hint. */
+		area->vaddr = get_unmapped_area(NULL, TASK_SIZE - PAGE_SIZE,
+						PAGE_SIZE, 0, 0);
+		if (area->vaddr & ~PAGE_MASK) {
+			ret = area->vaddr;
+			goto fail;
+		}
 	}
 
 	ret = install_special_mapping(mm, area->vaddr, PAGE_SIZE,
@@ -1120,13 +1121,49 @@
 
 	smp_wmb();	/* pairs with get_xol_area() */
 	mm->uprobes_state.xol_area = area;
-	ret = 0;
  fail:
 	up_write(&mm->mmap_sem);
 
 	return ret;
 }
 
+static struct xol_area *__create_xol_area(unsigned long vaddr)
+{
+	struct mm_struct *mm = current->mm;
+	uprobe_opcode_t insn = UPROBE_SWBP_INSN;
+	struct xol_area *area;
+
+	area = kmalloc(sizeof(*area), GFP_KERNEL);
+	if (unlikely(!area))
+		goto out;
+
+	area->bitmap = kzalloc(BITS_TO_LONGS(UINSNS_PER_PAGE) * sizeof(long), GFP_KERNEL);
+	if (!area->bitmap)
+		goto free_area;
+
+	area->page = alloc_page(GFP_HIGHUSER);
+	if (!area->page)
+		goto free_bitmap;
+
+	area->vaddr = vaddr;
+	init_waitqueue_head(&area->wq);
+	/* Reserve the 1st slot for get_trampoline_vaddr() */
+	set_bit(0, area->bitmap);
+	atomic_set(&area->slot_count, 1);
+	copy_to_page(area->page, 0, &insn, UPROBE_SWBP_INSN_SIZE);
+
+	if (!xol_add_vma(mm, area))
+		return area;
+
+	__free_page(area->page);
+ free_bitmap:
+	kfree(area->bitmap);
+ free_area:
+	kfree(area);
+ out:
+	return NULL;
+}
+
 /*
  * get_xol_area - Allocate process's xol_area if necessary.
  * This area will be used for storing instructions for execution out of line.
@@ -1137,42 +1174,12 @@
 {
 	struct mm_struct *mm = current->mm;
 	struct xol_area *area;
-	uprobe_opcode_t insn = UPROBE_SWBP_INSN;
+
+	if (!mm->uprobes_state.xol_area)
+		__create_xol_area(0);
 
 	area = mm->uprobes_state.xol_area;
-	if (area)
-		goto ret;
-
-	area = kzalloc(sizeof(*area), GFP_KERNEL);
-	if (unlikely(!area))
-		goto out;
-
-	area->bitmap = kzalloc(BITS_TO_LONGS(UINSNS_PER_PAGE) * sizeof(long), GFP_KERNEL);
-	if (!area->bitmap)
-		goto free_area;
-
-	area->page = alloc_page(GFP_HIGHUSER);
-	if (!area->page)
-		goto free_bitmap;
-
-	/* allocate first slot of task's xol_area for the return probes */
-	set_bit(0, area->bitmap);
-	copy_to_page(area->page, 0, &insn, UPROBE_SWBP_INSN_SIZE);
-	atomic_set(&area->slot_count, 1);
-	init_waitqueue_head(&area->wq);
-
-	if (!xol_add_vma(area))
-		return area;
-
-	__free_page(area->page);
- free_bitmap:
-	kfree(area->bitmap);
- free_area:
-	kfree(area);
- out:
-	area = mm->uprobes_state.xol_area;
- ret:
-	smp_read_barrier_depends();     /* pairs with wmb in xol_add_vma() */
+	smp_read_barrier_depends();	/* pairs with wmb in xol_add_vma() */
 	return area;
 }
 
@@ -1256,7 +1263,8 @@
 		return 0;
 
 	/* Initialize the slot */
-	copy_to_page(area->page, xol_vaddr, uprobe->arch.insn, MAX_UINSN_BYTES);
+	copy_to_page(area->page, xol_vaddr,
+			uprobe->arch.ixol, sizeof(uprobe->arch.ixol));
 	/*
 	 * We probably need flush_icache_user_range() but it needs vma.
 	 * This should work on supported architectures too.
@@ -1345,14 +1353,6 @@
 }
 
 /*
- * Called in context of a new clone/fork from copy_process.
- */
-void uprobe_copy_process(struct task_struct *t)
-{
-	t->utask = NULL;
-}
-
-/*
  * Allocate a uprobe_task object for the task if if necessary.
  * Called when the thread hits a breakpoint.
  *
@@ -1367,6 +1367,90 @@
 	return current->utask;
 }
 
+static int dup_utask(struct task_struct *t, struct uprobe_task *o_utask)
+{
+	struct uprobe_task *n_utask;
+	struct return_instance **p, *o, *n;
+
+	n_utask = kzalloc(sizeof(struct uprobe_task), GFP_KERNEL);
+	if (!n_utask)
+		return -ENOMEM;
+	t->utask = n_utask;
+
+	p = &n_utask->return_instances;
+	for (o = o_utask->return_instances; o; o = o->next) {
+		n = kmalloc(sizeof(struct return_instance), GFP_KERNEL);
+		if (!n)
+			return -ENOMEM;
+
+		*n = *o;
+		atomic_inc(&n->uprobe->ref);
+		n->next = NULL;
+
+		*p = n;
+		p = &n->next;
+		n_utask->depth++;
+	}
+
+	return 0;
+}
+
+static void uprobe_warn(struct task_struct *t, const char *msg)
+{
+	pr_warn("uprobe: %s:%d failed to %s\n",
+			current->comm, current->pid, msg);
+}
+
+static void dup_xol_work(struct callback_head *work)
+{
+	kfree(work);
+
+	if (current->flags & PF_EXITING)
+		return;
+
+	if (!__create_xol_area(current->utask->vaddr))
+		uprobe_warn(current, "dup xol area");
+}
+
+/*
+ * Called in context of a new clone/fork from copy_process.
+ */
+void uprobe_copy_process(struct task_struct *t, unsigned long flags)
+{
+	struct uprobe_task *utask = current->utask;
+	struct mm_struct *mm = current->mm;
+	struct callback_head *work;
+	struct xol_area *area;
+
+	t->utask = NULL;
+
+	if (!utask || !utask->return_instances)
+		return;
+
+	if (mm == t->mm && !(flags & CLONE_VFORK))
+		return;
+
+	if (dup_utask(t, utask))
+		return uprobe_warn(t, "dup ret instances");
+
+	/* The task can fork() after dup_xol_work() fails */
+	area = mm->uprobes_state.xol_area;
+	if (!area)
+		return uprobe_warn(t, "dup xol area");
+
+	if (mm == t->mm)
+		return;
+
+	/* TODO: move it into the union in uprobe_task */
+	work = kmalloc(sizeof(*work), GFP_KERNEL);
+	if (!work)
+		return uprobe_warn(t, "dup xol area");
+
+	t->utask->vaddr = area->vaddr;
+	init_task_work(work, dup_xol_work);
+	task_work_add(t, work, true);
+}
+
 /*
  * Current area->vaddr notion assume the trampoline address is always
  * equal area->vaddr.
@@ -1857,9 +1941,4 @@
 
 	return register_die_notifier(&uprobe_exception_nb);
 }
-module_init(init_uprobes);
-
-static void __exit exit_uprobes(void)
-{
-}
-module_exit(exit_uprobes);
+__initcall(init_uprobes);
diff --git a/kernel/fork.c b/kernel/fork.c
index 086fe73..f6d11fc 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -817,9 +817,6 @@
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 	mm->pmd_huge_pte = NULL;
 #endif
-#ifdef CONFIG_NUMA_BALANCING
-	mm->first_nid = NUMA_PTE_SCAN_INIT;
-#endif
 	if (!mm_init(mm, tsk))
 		goto fail_nomem;
 
@@ -1313,7 +1310,7 @@
 #endif
 
 	/* Perform scheduler related setup. Assign this task to a CPU. */
-	sched_fork(p);
+	sched_fork(clone_flags, p);
 
 	retval = perf_event_init_task(p);
 	if (retval)
@@ -1373,7 +1370,6 @@
 	INIT_LIST_HEAD(&p->pi_state_list);
 	p->pi_state_cache = NULL;
 #endif
-	uprobe_copy_process(p);
 	/*
 	 * sigaltstack should be cleared when sharing the same VM
 	 */
@@ -1490,6 +1486,7 @@
 	perf_event_fork(p);
 
 	trace_task_newtask(p, clone_flags);
+	uprobe_copy_process(p, clone_flags);
 
 	return p;
 
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 706724e..cf68bb3 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -465,27 +465,26 @@
 }
 EXPORT_SYMBOL_GPL(irq_create_strict_mappings);
 
-unsigned int irq_create_of_mapping(struct device_node *controller,
-				   const u32 *intspec, unsigned int intsize)
+unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
 {
 	struct irq_domain *domain;
 	irq_hw_number_t hwirq;
 	unsigned int type = IRQ_TYPE_NONE;
 	unsigned int virq;
 
-	domain = controller ? irq_find_host(controller) : irq_default_domain;
+	domain = irq_data->np ? irq_find_host(irq_data->np) : irq_default_domain;
 	if (!domain) {
 		pr_warn("no irq domain found for %s !\n",
-			of_node_full_name(controller));
+			of_node_full_name(irq_data->np));
 		return 0;
 	}
 
 	/* If domain has no translation, then we assume interrupt line */
 	if (domain->ops->xlate == NULL)
-		hwirq = intspec[0];
+		hwirq = irq_data->args[0];
 	else {
-		if (domain->ops->xlate(domain, controller, intspec, intsize,
-				     &hwirq, &type))
+		if (domain->ops->xlate(domain, irq_data->np, irq_data->args,
+					irq_data->args_count, &hwirq, &type))
 			return 0;
 	}
 
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 514bcfd..3e59f95 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -956,7 +956,7 @@
 			goto out_mput;
 		}
 
-		sched_setscheduler(t, SCHED_FIFO, &param);
+		sched_setscheduler_nocheck(t, SCHED_FIFO, &param);
 
 		/*
 		 * We keep the reference to the task struct even if
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index e16c45b..4e8e14c 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -4224,7 +4224,7 @@
 	printk("\n%srcu_scheduler_active = %d, debug_locks = %d\n",
 	       !rcu_lockdep_current_cpu_online()
 			? "RCU used illegally from offline CPU!\n"
-			: rcu_is_cpu_idle()
+			: !rcu_is_watching()
 				? "RCU used illegally from idle CPU!\n"
 				: "",
 	       rcu_scheduler_active, debug_locks);
@@ -4247,7 +4247,7 @@
 	 * So complain bitterly if someone does call rcu_read_lock(),
 	 * rcu_read_lock_bh() and so on from extended quiescent states.
 	 */
-	if (rcu_is_cpu_idle())
+	if (!rcu_is_watching())
 		printk("RCU used illegally from extended quiescent state!\n");
 
 	lockdep_print_held_locks(curr);
diff --git a/kernel/mutex.c b/kernel/mutex.c
index 6d647ae..d24105b 100644
--- a/kernel/mutex.c
+++ b/kernel/mutex.c
@@ -410,7 +410,7 @@
 static __always_inline int __sched
 __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
 		    struct lockdep_map *nest_lock, unsigned long ip,
-		    struct ww_acquire_ctx *ww_ctx)
+		    struct ww_acquire_ctx *ww_ctx, const bool use_ww_ctx)
 {
 	struct task_struct *task = current;
 	struct mutex_waiter waiter;
@@ -450,7 +450,7 @@
 		struct task_struct *owner;
 		struct mspin_node  node;
 
-		if (!__builtin_constant_p(ww_ctx == NULL) && ww_ctx->acquired > 0) {
+		if (use_ww_ctx && ww_ctx->acquired > 0) {
 			struct ww_mutex *ww;
 
 			ww = container_of(lock, struct ww_mutex, base);
@@ -480,7 +480,7 @@
 		if ((atomic_read(&lock->count) == 1) &&
 		    (atomic_cmpxchg(&lock->count, 1, 0) == 1)) {
 			lock_acquired(&lock->dep_map, ip);
-			if (!__builtin_constant_p(ww_ctx == NULL)) {
+			if (use_ww_ctx) {
 				struct ww_mutex *ww;
 				ww = container_of(lock, struct ww_mutex, base);
 
@@ -551,7 +551,7 @@
 			goto err;
 		}
 
-		if (!__builtin_constant_p(ww_ctx == NULL) && ww_ctx->acquired > 0) {
+		if (use_ww_ctx && ww_ctx->acquired > 0) {
 			ret = __mutex_lock_check_stamp(lock, ww_ctx);
 			if (ret)
 				goto err;
@@ -575,7 +575,7 @@
 	lock_acquired(&lock->dep_map, ip);
 	mutex_set_owner(lock);
 
-	if (!__builtin_constant_p(ww_ctx == NULL)) {
+	if (use_ww_ctx) {
 		struct ww_mutex *ww = container_of(lock, struct ww_mutex, base);
 		struct mutex_waiter *cur;
 
@@ -615,7 +615,7 @@
 {
 	might_sleep();
 	__mutex_lock_common(lock, TASK_UNINTERRUPTIBLE,
-			    subclass, NULL, _RET_IP_, NULL);
+			    subclass, NULL, _RET_IP_, NULL, 0);
 }
 
 EXPORT_SYMBOL_GPL(mutex_lock_nested);
@@ -625,7 +625,7 @@
 {
 	might_sleep();
 	__mutex_lock_common(lock, TASK_UNINTERRUPTIBLE,
-			    0, nest, _RET_IP_, NULL);
+			    0, nest, _RET_IP_, NULL, 0);
 }
 
 EXPORT_SYMBOL_GPL(_mutex_lock_nest_lock);
@@ -635,7 +635,7 @@
 {
 	might_sleep();
 	return __mutex_lock_common(lock, TASK_KILLABLE,
-				   subclass, NULL, _RET_IP_, NULL);
+				   subclass, NULL, _RET_IP_, NULL, 0);
 }
 EXPORT_SYMBOL_GPL(mutex_lock_killable_nested);
 
@@ -644,7 +644,7 @@
 {
 	might_sleep();
 	return __mutex_lock_common(lock, TASK_INTERRUPTIBLE,
-				   subclass, NULL, _RET_IP_, NULL);
+				   subclass, NULL, _RET_IP_, NULL, 0);
 }
 
 EXPORT_SYMBOL_GPL(mutex_lock_interruptible_nested);
@@ -682,7 +682,7 @@
 
 	might_sleep();
 	ret =  __mutex_lock_common(&lock->base, TASK_UNINTERRUPTIBLE,
-				   0, &ctx->dep_map, _RET_IP_, ctx);
+				   0, &ctx->dep_map, _RET_IP_, ctx, 1);
 	if (!ret && ctx->acquired > 1)
 		return ww_mutex_deadlock_injection(lock, ctx);
 
@@ -697,7 +697,7 @@
 
 	might_sleep();
 	ret = __mutex_lock_common(&lock->base, TASK_INTERRUPTIBLE,
-				  0, &ctx->dep_map, _RET_IP_, ctx);
+				  0, &ctx->dep_map, _RET_IP_, ctx, 1);
 
 	if (!ret && ctx->acquired > 1)
 		return ww_mutex_deadlock_injection(lock, ctx);
@@ -809,28 +809,28 @@
 	struct mutex *lock = container_of(lock_count, struct mutex, count);
 
 	__mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, 0,
-			    NULL, _RET_IP_, NULL);
+			    NULL, _RET_IP_, NULL, 0);
 }
 
 static noinline int __sched
 __mutex_lock_killable_slowpath(struct mutex *lock)
 {
 	return __mutex_lock_common(lock, TASK_KILLABLE, 0,
-				   NULL, _RET_IP_, NULL);
+				   NULL, _RET_IP_, NULL, 0);
 }
 
 static noinline int __sched
 __mutex_lock_interruptible_slowpath(struct mutex *lock)
 {
 	return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, 0,
-				   NULL, _RET_IP_, NULL);
+				   NULL, _RET_IP_, NULL, 0);
 }
 
 static noinline int __sched
 __ww_mutex_lock_slowpath(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
 {
 	return __mutex_lock_common(&lock->base, TASK_UNINTERRUPTIBLE, 0,
-				   NULL, _RET_IP_, ctx);
+				   NULL, _RET_IP_, ctx, 1);
 }
 
 static noinline int __sched
@@ -838,7 +838,7 @@
 					    struct ww_acquire_ctx *ctx)
 {
 	return __mutex_lock_common(&lock->base, TASK_INTERRUPTIBLE, 0,
-				   NULL, _RET_IP_, ctx);
+				   NULL, _RET_IP_, ctx, 1);
 }
 
 #endif
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index c9c759d..0121dab 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -846,7 +846,7 @@
 	goto Finish;
 }
 
-late_initcall(software_resume);
+late_initcall_sync(software_resume);
 
 
 static const char * const hibernation_modes[] = {
diff --git a/kernel/rcu/Makefile b/kernel/rcu/Makefile
new file mode 100644
index 0000000..01e9ec3
--- /dev/null
+++ b/kernel/rcu/Makefile
@@ -0,0 +1,6 @@
+obj-y += update.o srcu.o
+obj-$(CONFIG_RCU_TORTURE_TEST) += torture.o
+obj-$(CONFIG_TREE_RCU) += tree.o
+obj-$(CONFIG_TREE_PREEMPT_RCU) += tree.o
+obj-$(CONFIG_TREE_RCU_TRACE) += tree_trace.o
+obj-$(CONFIG_TINY_RCU) += tiny.o
diff --git a/kernel/rcu.h b/kernel/rcu/rcu.h
similarity index 94%
rename from kernel/rcu.h
rename to kernel/rcu/rcu.h
index 7713196..7859a0a 100644
--- a/kernel/rcu.h
+++ b/kernel/rcu/rcu.h
@@ -122,4 +122,11 @@
 
 #endif /* #ifdef CONFIG_RCU_STALL_COMMON */
 
+/*
+ * Strings used in tracepoints need to be exported via the
+ * tracing system such that tools like perf and trace-cmd can
+ * translate the string address pointers to actual text.
+ */
+#define TPS(x)  tracepoint_string(x)
+
 #endif /* __LINUX_RCU_H */
diff --git a/kernel/srcu.c b/kernel/rcu/srcu.c
similarity index 100%
rename from kernel/srcu.c
rename to kernel/rcu/srcu.c
diff --git a/kernel/rcutiny.c b/kernel/rcu/tiny.c
similarity index 90%
rename from kernel/rcutiny.c
rename to kernel/rcu/tiny.c
index 9ed6075..0c9a934 100644
--- a/kernel/rcutiny.c
+++ b/kernel/rcu/tiny.c
@@ -35,6 +35,7 @@
 #include <linux/time.h>
 #include <linux/cpu.h>
 #include <linux/prefetch.h>
+#include <linux/ftrace_event.h>
 
 #ifdef CONFIG_RCU_TRACE
 #include <trace/events/rcu.h>
@@ -42,7 +43,7 @@
 
 #include "rcu.h"
 
-/* Forward declarations for rcutiny_plugin.h. */
+/* Forward declarations for tiny_plugin.h. */
 struct rcu_ctrlblk;
 static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp);
 static void rcu_process_callbacks(struct softirq_action *unused);
@@ -52,22 +53,23 @@
 
 static long long rcu_dynticks_nesting = DYNTICK_TASK_EXIT_IDLE;
 
-#include "rcutiny_plugin.h"
+#include "tiny_plugin.h"
 
 /* Common code for rcu_idle_enter() and rcu_irq_exit(), see kernel/rcutree.c. */
 static void rcu_idle_enter_common(long long newval)
 {
 	if (newval) {
-		RCU_TRACE(trace_rcu_dyntick("--=",
+		RCU_TRACE(trace_rcu_dyntick(TPS("--="),
 					    rcu_dynticks_nesting, newval));
 		rcu_dynticks_nesting = newval;
 		return;
 	}
-	RCU_TRACE(trace_rcu_dyntick("Start", rcu_dynticks_nesting, newval));
+	RCU_TRACE(trace_rcu_dyntick(TPS("Start"),
+				    rcu_dynticks_nesting, newval));
 	if (!is_idle_task(current)) {
-		struct task_struct *idle = idle_task(smp_processor_id());
+		struct task_struct *idle __maybe_unused = idle_task(smp_processor_id());
 
-		RCU_TRACE(trace_rcu_dyntick("Error on entry: not idle task",
+		RCU_TRACE(trace_rcu_dyntick(TPS("Entry error: not idle task"),
 					    rcu_dynticks_nesting, newval));
 		ftrace_dump(DUMP_ALL);
 		WARN_ONCE(1, "Current pid: %d comm: %s / Idle pid: %d comm: %s",
@@ -120,15 +122,15 @@
 static void rcu_idle_exit_common(long long oldval)
 {
 	if (oldval) {
-		RCU_TRACE(trace_rcu_dyntick("++=",
+		RCU_TRACE(trace_rcu_dyntick(TPS("++="),
 					    oldval, rcu_dynticks_nesting));
 		return;
 	}
-	RCU_TRACE(trace_rcu_dyntick("End", oldval, rcu_dynticks_nesting));
+	RCU_TRACE(trace_rcu_dyntick(TPS("End"), oldval, rcu_dynticks_nesting));
 	if (!is_idle_task(current)) {
-		struct task_struct *idle = idle_task(smp_processor_id());
+		struct task_struct *idle __maybe_unused = idle_task(smp_processor_id());
 
-		RCU_TRACE(trace_rcu_dyntick("Error on exit: not idle task",
+		RCU_TRACE(trace_rcu_dyntick(TPS("Exit error: not idle task"),
 			  oldval, rcu_dynticks_nesting));
 		ftrace_dump(DUMP_ALL);
 		WARN_ONCE(1, "Current pid: %d comm: %s / Idle pid: %d comm: %s",
@@ -174,18 +176,18 @@
 }
 EXPORT_SYMBOL_GPL(rcu_irq_enter);
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
+#if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE)
 
 /*
  * Test whether RCU thinks that the current CPU is idle.
  */
-int rcu_is_cpu_idle(void)
+bool __rcu_is_watching(void)
 {
-	return !rcu_dynticks_nesting;
+	return rcu_dynticks_nesting;
 }
-EXPORT_SYMBOL(rcu_is_cpu_idle);
+EXPORT_SYMBOL(__rcu_is_watching);
 
-#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+#endif /* defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) */
 
 /*
  * Test whether the current CPU was interrupted from idle.  Nested
@@ -273,7 +275,7 @@
 	if (&rcp->rcucblist == rcp->donetail) {
 		RCU_TRACE(trace_rcu_batch_start(rcp->name, 0, 0, -1));
 		RCU_TRACE(trace_rcu_batch_end(rcp->name, 0,
-					      ACCESS_ONCE(rcp->rcucblist),
+					      !!ACCESS_ONCE(rcp->rcucblist),
 					      need_resched(),
 					      is_idle_task(current),
 					      false));
@@ -304,7 +306,8 @@
 		RCU_TRACE(cb_count++);
 	}
 	RCU_TRACE(rcu_trace_sub_qlen(rcp, cb_count));
-	RCU_TRACE(trace_rcu_batch_end(rcp->name, cb_count, 0, need_resched(),
+	RCU_TRACE(trace_rcu_batch_end(rcp->name,
+				      cb_count, 0, need_resched(),
 				      is_idle_task(current),
 				      false));
 }
diff --git a/kernel/rcutiny_plugin.h b/kernel/rcu/tiny_plugin.h
similarity index 100%
rename from kernel/rcutiny_plugin.h
rename to kernel/rcu/tiny_plugin.h
diff --git a/kernel/rcutorture.c b/kernel/rcu/torture.c
similarity index 99%
rename from kernel/rcutorture.c
rename to kernel/rcu/torture.c
index be63101..3929cd4 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcu/torture.c
@@ -52,6 +52,12 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com> and Josh Triplett <josh@freedesktop.org>");
 
+MODULE_ALIAS("rcutorture");
+#ifdef MODULE_PARAM_PREFIX
+#undef MODULE_PARAM_PREFIX
+#endif
+#define MODULE_PARAM_PREFIX "rcutorture."
+
 static int fqs_duration;
 module_param(fqs_duration, int, 0444);
 MODULE_PARM_DESC(fqs_duration, "Duration of fqs bursts (us), 0 to disable");
diff --git a/kernel/rcutree.c b/kernel/rcu/tree.c
similarity index 94%
rename from kernel/rcutree.c
rename to kernel/rcu/tree.c
index 32618b3..4c06ddf 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcu/tree.c
@@ -41,6 +41,7 @@
 #include <linux/export.h>
 #include <linux/completion.h>
 #include <linux/moduleparam.h>
+#include <linux/module.h>
 #include <linux/percpu.h>
 #include <linux/notifier.h>
 #include <linux/cpu.h>
@@ -56,17 +57,16 @@
 #include <linux/ftrace_event.h>
 #include <linux/suspend.h>
 
-#include "rcutree.h"
+#include "tree.h"
 #include <trace/events/rcu.h>
 
 #include "rcu.h"
 
-/*
- * Strings used in tracepoints need to be exported via the
- * tracing system such that tools like perf and trace-cmd can
- * translate the string address pointers to actual text.
- */
-#define TPS(x)	tracepoint_string(x)
+MODULE_ALIAS("rcutree");
+#ifdef MODULE_PARAM_PREFIX
+#undef MODULE_PARAM_PREFIX
+#endif
+#define MODULE_PARAM_PREFIX "rcutree."
 
 /* Data structures. */
 
@@ -222,7 +222,7 @@
 }
 EXPORT_SYMBOL_GPL(rcu_note_context_switch);
 
-DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = {
+static DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = {
 	.dynticks_nesting = DYNTICK_TASK_EXIT_IDLE,
 	.dynticks = ATOMIC_INIT(1),
 #ifdef CONFIG_NO_HZ_FULL_SYSIDLE
@@ -371,7 +371,8 @@
 {
 	trace_rcu_dyntick(TPS("Start"), oldval, rdtp->dynticks_nesting);
 	if (!user && !is_idle_task(current)) {
-		struct task_struct *idle = idle_task(smp_processor_id());
+		struct task_struct *idle __maybe_unused =
+			idle_task(smp_processor_id());
 
 		trace_rcu_dyntick(TPS("Error on entry: not idle task"), oldval, 0);
 		ftrace_dump(DUMP_ORIG);
@@ -407,7 +408,7 @@
 	long long oldval;
 	struct rcu_dynticks *rdtp;
 
-	rdtp = &__get_cpu_var(rcu_dynticks);
+	rdtp = this_cpu_ptr(&rcu_dynticks);
 	oldval = rdtp->dynticks_nesting;
 	WARN_ON_ONCE((oldval & DYNTICK_TASK_NEST_MASK) == 0);
 	if ((oldval & DYNTICK_TASK_NEST_MASK) == DYNTICK_TASK_NEST_VALUE)
@@ -435,7 +436,7 @@
 
 	local_irq_save(flags);
 	rcu_eqs_enter(false);
-	rcu_sysidle_enter(&__get_cpu_var(rcu_dynticks), 0);
+	rcu_sysidle_enter(this_cpu_ptr(&rcu_dynticks), 0);
 	local_irq_restore(flags);
 }
 EXPORT_SYMBOL_GPL(rcu_idle_enter);
@@ -478,7 +479,7 @@
 	struct rcu_dynticks *rdtp;
 
 	local_irq_save(flags);
-	rdtp = &__get_cpu_var(rcu_dynticks);
+	rdtp = this_cpu_ptr(&rcu_dynticks);
 	oldval = rdtp->dynticks_nesting;
 	rdtp->dynticks_nesting--;
 	WARN_ON_ONCE(rdtp->dynticks_nesting < 0);
@@ -508,7 +509,8 @@
 	rcu_cleanup_after_idle(smp_processor_id());
 	trace_rcu_dyntick(TPS("End"), oldval, rdtp->dynticks_nesting);
 	if (!user && !is_idle_task(current)) {
-		struct task_struct *idle = idle_task(smp_processor_id());
+		struct task_struct *idle __maybe_unused =
+			idle_task(smp_processor_id());
 
 		trace_rcu_dyntick(TPS("Error on exit: not idle task"),
 				  oldval, rdtp->dynticks_nesting);
@@ -528,7 +530,7 @@
 	struct rcu_dynticks *rdtp;
 	long long oldval;
 
-	rdtp = &__get_cpu_var(rcu_dynticks);
+	rdtp = this_cpu_ptr(&rcu_dynticks);
 	oldval = rdtp->dynticks_nesting;
 	WARN_ON_ONCE(oldval < 0);
 	if (oldval & DYNTICK_TASK_NEST_MASK)
@@ -555,7 +557,7 @@
 
 	local_irq_save(flags);
 	rcu_eqs_exit(false);
-	rcu_sysidle_exit(&__get_cpu_var(rcu_dynticks), 0);
+	rcu_sysidle_exit(this_cpu_ptr(&rcu_dynticks), 0);
 	local_irq_restore(flags);
 }
 EXPORT_SYMBOL_GPL(rcu_idle_exit);
@@ -599,7 +601,7 @@
 	long long oldval;
 
 	local_irq_save(flags);
-	rdtp = &__get_cpu_var(rcu_dynticks);
+	rdtp = this_cpu_ptr(&rcu_dynticks);
 	oldval = rdtp->dynticks_nesting;
 	rdtp->dynticks_nesting++;
 	WARN_ON_ONCE(rdtp->dynticks_nesting == 0);
@@ -620,7 +622,7 @@
  */
 void rcu_nmi_enter(void)
 {
-	struct rcu_dynticks *rdtp = &__get_cpu_var(rcu_dynticks);
+	struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
 
 	if (rdtp->dynticks_nmi_nesting == 0 &&
 	    (atomic_read(&rdtp->dynticks) & 0x1))
@@ -642,7 +644,7 @@
  */
 void rcu_nmi_exit(void)
 {
-	struct rcu_dynticks *rdtp = &__get_cpu_var(rcu_dynticks);
+	struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
 
 	if (rdtp->dynticks_nmi_nesting == 0 ||
 	    --rdtp->dynticks_nmi_nesting != 0)
@@ -655,21 +657,34 @@
 }
 
 /**
- * rcu_is_cpu_idle - see if RCU thinks that the current CPU is idle
+ * __rcu_is_watching - are RCU read-side critical sections safe?
+ *
+ * Return true if RCU is watching the running CPU, which means that
+ * this CPU can safely enter RCU read-side critical sections.  Unlike
+ * rcu_is_watching(), the caller of __rcu_is_watching() must have at
+ * least disabled preemption.
+ */
+bool __rcu_is_watching(void)
+{
+	return atomic_read(this_cpu_ptr(&rcu_dynticks.dynticks)) & 0x1;
+}
+
+/**
+ * rcu_is_watching - see if RCU thinks that the current CPU is idle
  *
  * If the current CPU is in its idle loop and is neither in an interrupt
  * or NMI handler, return true.
  */
-int rcu_is_cpu_idle(void)
+bool rcu_is_watching(void)
 {
 	int ret;
 
 	preempt_disable();
-	ret = (atomic_read(&__get_cpu_var(rcu_dynticks).dynticks) & 0x1) == 0;
+	ret = __rcu_is_watching();
 	preempt_enable();
 	return ret;
 }
-EXPORT_SYMBOL(rcu_is_cpu_idle);
+EXPORT_SYMBOL_GPL(rcu_is_watching);
 
 #if defined(CONFIG_PROVE_RCU) && defined(CONFIG_HOTPLUG_CPU)
 
@@ -703,7 +718,7 @@
 	if (in_nmi())
 		return 1;
 	preempt_disable();
-	rdp = &__get_cpu_var(rcu_sched_data);
+	rdp = this_cpu_ptr(&rcu_sched_data);
 	rnp = rdp->mynode;
 	ret = (rdp->grpmask & rnp->qsmaskinit) ||
 	      !rcu_scheduler_fully_active;
@@ -723,7 +738,7 @@
  */
 static int rcu_is_cpu_rrupt_from_idle(void)
 {
-	return __get_cpu_var(rcu_dynticks).dynticks_nesting <= 1;
+	return __this_cpu_read(rcu_dynticks.dynticks_nesting) <= 1;
 }
 
 /*
@@ -802,8 +817,11 @@
 
 static void record_gp_stall_check_time(struct rcu_state *rsp)
 {
-	rsp->gp_start = jiffies;
-	rsp->jiffies_stall = jiffies + rcu_jiffies_till_stall_check();
+	unsigned long j = ACCESS_ONCE(jiffies);
+
+	rsp->gp_start = j;
+	smp_wmb(); /* Record start time before stall time. */
+	rsp->jiffies_stall = j + rcu_jiffies_till_stall_check();
 }
 
 /*
@@ -898,6 +916,12 @@
 	force_quiescent_state(rsp);  /* Kick them all. */
 }
 
+/*
+ * This function really isn't for public consumption, but RCU is special in
+ * that context switches can allow the state machine to make progress.
+ */
+extern void resched_cpu(int cpu);
+
 static void print_cpu_stall(struct rcu_state *rsp)
 {
 	int cpu;
@@ -927,22 +951,60 @@
 				     3 * rcu_jiffies_till_stall_check() + 3;
 	raw_spin_unlock_irqrestore(&rnp->lock, flags);
 
-	set_need_resched();  /* kick ourselves to get things going. */
+	/*
+	 * Attempt to revive the RCU machinery by forcing a context switch.
+	 *
+	 * A context switch would normally allow the RCU state machine to make
+	 * progress and it could be we're stuck in kernel space without context
+	 * switches for an entirely unreasonable amount of time.
+	 */
+	resched_cpu(smp_processor_id());
 }
 
 static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
 {
+	unsigned long completed;
+	unsigned long gpnum;
+	unsigned long gps;
 	unsigned long j;
 	unsigned long js;
 	struct rcu_node *rnp;
 
-	if (rcu_cpu_stall_suppress)
+	if (rcu_cpu_stall_suppress || !rcu_gp_in_progress(rsp))
 		return;
 	j = ACCESS_ONCE(jiffies);
+
+	/*
+	 * Lots of memory barriers to reject false positives.
+	 *
+	 * The idea is to pick up rsp->gpnum, then rsp->jiffies_stall,
+	 * then rsp->gp_start, and finally rsp->completed.  These values
+	 * are updated in the opposite order with memory barriers (or
+	 * equivalent) during grace-period initialization and cleanup.
+	 * Now, a false positive can occur if we get an new value of
+	 * rsp->gp_start and a old value of rsp->jiffies_stall.  But given
+	 * the memory barriers, the only way that this can happen is if one
+	 * grace period ends and another starts between these two fetches.
+	 * Detect this by comparing rsp->completed with the previous fetch
+	 * from rsp->gpnum.
+	 *
+	 * Given this check, comparisons of jiffies, rsp->jiffies_stall,
+	 * and rsp->gp_start suffice to forestall false positives.
+	 */
+	gpnum = ACCESS_ONCE(rsp->gpnum);
+	smp_rmb(); /* Pick up ->gpnum first... */
 	js = ACCESS_ONCE(rsp->jiffies_stall);
+	smp_rmb(); /* ...then ->jiffies_stall before the rest... */
+	gps = ACCESS_ONCE(rsp->gp_start);
+	smp_rmb(); /* ...and finally ->gp_start before ->completed. */
+	completed = ACCESS_ONCE(rsp->completed);
+	if (ULONG_CMP_GE(completed, gpnum) ||
+	    ULONG_CMP_LT(j, js) ||
+	    ULONG_CMP_GE(gps, js))
+		return; /* No stall or GP completed since entering function. */
 	rnp = rdp->mynode;
 	if (rcu_gp_in_progress(rsp) &&
-	    (ACCESS_ONCE(rnp->qsmask) & rdp->grpmask) && ULONG_CMP_GE(j, js)) {
+	    (ACCESS_ONCE(rnp->qsmask) & rdp->grpmask)) {
 
 		/* We haven't checked in, so go dump stack. */
 		print_cpu_stall(rsp);
@@ -1297,7 +1359,7 @@
 }
 
 /*
- * Initialize a new grace period.
+ * Initialize a new grace period.  Return 0 if no grace period required.
  */
 static int rcu_gp_init(struct rcu_state *rsp)
 {
@@ -1306,18 +1368,27 @@
 
 	rcu_bind_gp_kthread();
 	raw_spin_lock_irq(&rnp->lock);
+	if (rsp->gp_flags == 0) {
+		/* Spurious wakeup, tell caller to go back to sleep.  */
+		raw_spin_unlock_irq(&rnp->lock);
+		return 0;
+	}
 	rsp->gp_flags = 0; /* Clear all flags: New grace period. */
 
-	if (rcu_gp_in_progress(rsp)) {
-		/* Grace period already in progress, don't start another.  */
+	if (WARN_ON_ONCE(rcu_gp_in_progress(rsp))) {
+		/*
+		 * Grace period already in progress, don't start another.
+		 * Not supposed to be able to happen.
+		 */
 		raw_spin_unlock_irq(&rnp->lock);
 		return 0;
 	}
 
 	/* Advance to a new grace period and initialize state. */
+	record_gp_stall_check_time(rsp);
+	smp_wmb(); /* Record GP times before starting GP. */
 	rsp->gpnum++;
 	trace_rcu_grace_period(rsp->name, rsp->gpnum, TPS("start"));
-	record_gp_stall_check_time(rsp);
 	raw_spin_unlock_irq(&rnp->lock);
 
 	/* Exclude any concurrent CPU-hotplug operations. */
@@ -1366,7 +1437,7 @@
 /*
  * Do one round of quiescent-state forcing.
  */
-int rcu_gp_fqs(struct rcu_state *rsp, int fqs_state_in)
+static int rcu_gp_fqs(struct rcu_state *rsp, int fqs_state_in)
 {
 	int fqs_state = fqs_state_in;
 	bool isidle = false;
@@ -1451,8 +1522,12 @@
 	rsp->fqs_state = RCU_GP_IDLE;
 	rdp = this_cpu_ptr(rsp->rda);
 	rcu_advance_cbs(rsp, rnp, rdp);  /* Reduce false positives below. */
-	if (cpu_needs_another_gp(rsp, rdp))
-		rsp->gp_flags = 1;
+	if (cpu_needs_another_gp(rsp, rdp)) {
+		rsp->gp_flags = RCU_GP_FLAG_INIT;
+		trace_rcu_grace_period(rsp->name,
+				       ACCESS_ONCE(rsp->gpnum),
+				       TPS("newreq"));
+	}
 	raw_spin_unlock_irq(&rnp->lock);
 }
 
@@ -1462,6 +1537,7 @@
 static int __noreturn rcu_gp_kthread(void *arg)
 {
 	int fqs_state;
+	int gf;
 	unsigned long j;
 	int ret;
 	struct rcu_state *rsp = arg;
@@ -1471,14 +1547,19 @@
 
 		/* Handle grace-period start. */
 		for (;;) {
+			trace_rcu_grace_period(rsp->name,
+					       ACCESS_ONCE(rsp->gpnum),
+					       TPS("reqwait"));
 			wait_event_interruptible(rsp->gp_wq,
-						 rsp->gp_flags &
+						 ACCESS_ONCE(rsp->gp_flags) &
 						 RCU_GP_FLAG_INIT);
-			if ((rsp->gp_flags & RCU_GP_FLAG_INIT) &&
-			    rcu_gp_init(rsp))
+			if (rcu_gp_init(rsp))
 				break;
 			cond_resched();
 			flush_signals(current);
+			trace_rcu_grace_period(rsp->name,
+					       ACCESS_ONCE(rsp->gpnum),
+					       TPS("reqwaitsig"));
 		}
 
 		/* Handle quiescent-state forcing. */
@@ -1488,10 +1569,16 @@
 			j = HZ;
 			jiffies_till_first_fqs = HZ;
 		}
+		ret = 0;
 		for (;;) {
-			rsp->jiffies_force_qs = jiffies + j;
+			if (!ret)
+				rsp->jiffies_force_qs = jiffies + j;
+			trace_rcu_grace_period(rsp->name,
+					       ACCESS_ONCE(rsp->gpnum),
+					       TPS("fqswait"));
 			ret = wait_event_interruptible_timeout(rsp->gp_wq,
-					(rsp->gp_flags & RCU_GP_FLAG_FQS) ||
+					((gf = ACCESS_ONCE(rsp->gp_flags)) &
+					 RCU_GP_FLAG_FQS) ||
 					(!ACCESS_ONCE(rnp->qsmask) &&
 					 !rcu_preempt_blocked_readers_cgp(rnp)),
 					j);
@@ -1500,13 +1587,23 @@
 			    !rcu_preempt_blocked_readers_cgp(rnp))
 				break;
 			/* If time for quiescent-state forcing, do it. */
-			if (ret == 0 || (rsp->gp_flags & RCU_GP_FLAG_FQS)) {
+			if (ULONG_CMP_GE(jiffies, rsp->jiffies_force_qs) ||
+			    (gf & RCU_GP_FLAG_FQS)) {
+				trace_rcu_grace_period(rsp->name,
+						       ACCESS_ONCE(rsp->gpnum),
+						       TPS("fqsstart"));
 				fqs_state = rcu_gp_fqs(rsp, fqs_state);
+				trace_rcu_grace_period(rsp->name,
+						       ACCESS_ONCE(rsp->gpnum),
+						       TPS("fqsend"));
 				cond_resched();
 			} else {
 				/* Deal with stray signal. */
 				cond_resched();
 				flush_signals(current);
+				trace_rcu_grace_period(rsp->name,
+						       ACCESS_ONCE(rsp->gpnum),
+						       TPS("fqswaitsig"));
 			}
 			j = jiffies_till_next_fqs;
 			if (j > HZ) {
@@ -1554,6 +1651,8 @@
 		return;
 	}
 	rsp->gp_flags = RCU_GP_FLAG_INIT;
+	trace_rcu_grace_period(rsp->name, ACCESS_ONCE(rsp->gpnum),
+			       TPS("newreq"));
 
 	/*
 	 * We can't do wakeups while holding the rnp->lock, as that
@@ -2255,7 +2354,7 @@
 	 * If called from an extended quiescent state, invoke the RCU
 	 * core in order to force a re-evaluation of RCU's idleness.
 	 */
-	if (rcu_is_cpu_idle() && cpu_online(smp_processor_id()))
+	if (!rcu_is_watching() && cpu_online(smp_processor_id()))
 		invoke_rcu_core();
 
 	/* If interrupts were disabled or CPU offline, don't invoke RCU core. */
@@ -2725,10 +2824,13 @@
 
 	for_each_rcu_flavor(rsp) {
 		rdp = per_cpu_ptr(rsp->rda, cpu);
-		if (rdp->qlen != rdp->qlen_lazy)
+		if (!rdp->nxtlist)
+			continue;
+		hc = true;
+		if (rdp->qlen != rdp->qlen_lazy || !all_lazy) {
 			al = false;
-		if (rdp->nxtlist)
-			hc = true;
+			break;
+		}
 	}
 	if (all_lazy)
 		*all_lazy = al;
@@ -3216,7 +3318,7 @@
 
 /*
  * Compute the rcu_node tree geometry from kernel parameters.  This cannot
- * replace the definitions in rcutree.h because those are needed to size
+ * replace the definitions in tree.h because those are needed to size
  * the ->node array in the rcu_state structure.
  */
 static void __init rcu_init_geometry(void)
@@ -3295,8 +3397,8 @@
 
 	rcu_bootup_announce();
 	rcu_init_geometry();
-	rcu_init_one(&rcu_sched_state, &rcu_sched_data);
 	rcu_init_one(&rcu_bh_state, &rcu_bh_data);
+	rcu_init_one(&rcu_sched_state, &rcu_sched_data);
 	__rcu_init_preempt();
 	open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
 
@@ -3311,4 +3413,4 @@
 		rcu_cpu_notify(NULL, CPU_UP_PREPARE, (void *)(long)cpu);
 }
 
-#include "rcutree_plugin.h"
+#include "tree_plugin.h"
diff --git a/kernel/rcutree.h b/kernel/rcu/tree.h
similarity index 99%
rename from kernel/rcutree.h
rename to kernel/rcu/tree.h
index 5f97eab..52be957 100644
--- a/kernel/rcutree.h
+++ b/kernel/rcu/tree.h
@@ -104,6 +104,8 @@
 				    /* idle-period nonlazy_posted snapshot. */
 	unsigned long last_accelerate;
 				    /* Last jiffy CBs were accelerated. */
+	unsigned long last_advance_all;
+				    /* Last jiffy CBs were all advanced. */
 	int tick_nohz_enabled_snap; /* Previously seen value from sysfs. */
 #endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */
 };
diff --git a/kernel/rcutree_plugin.h b/kernel/rcu/tree_plugin.h
similarity index 96%
rename from kernel/rcutree_plugin.h
rename to kernel/rcu/tree_plugin.h
index 130c97b..3822ac0 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -28,7 +28,7 @@
 #include <linux/gfp.h>
 #include <linux/oom.h>
 #include <linux/smpboot.h>
-#include "time/tick-internal.h"
+#include "../time/tick-internal.h"
 
 #define RCU_KTHREAD_PRIO 1
 
@@ -96,10 +96,15 @@
 #endif /* #ifdef CONFIG_RCU_NOCB_CPU_ZERO */
 #ifdef CONFIG_RCU_NOCB_CPU_ALL
 	pr_info("\tOffload RCU callbacks from all CPUs\n");
-	cpumask_setall(rcu_nocb_mask);
+	cpumask_copy(rcu_nocb_mask, cpu_possible_mask);
 #endif /* #ifdef CONFIG_RCU_NOCB_CPU_ALL */
 #endif /* #ifndef CONFIG_RCU_NOCB_CPU_NONE */
 	if (have_rcu_nocb_mask) {
+		if (!cpumask_subset(rcu_nocb_mask, cpu_possible_mask)) {
+			pr_info("\tNote: kernel parameter 'rcu_nocbs=' contains nonexistent CPUs.\n");
+			cpumask_and(rcu_nocb_mask, cpu_possible_mask,
+				    rcu_nocb_mask);
+		}
 		cpulist_scnprintf(nocb_buf, sizeof(nocb_buf), rcu_nocb_mask);
 		pr_info("\tOffload RCU callbacks from CPUs: %s.\n", nocb_buf);
 		if (rcu_nocb_poll)
@@ -660,7 +665,7 @@
 
 static void rcu_preempt_do_callbacks(void)
 {
-	rcu_do_batch(&rcu_preempt_state, &__get_cpu_var(rcu_preempt_data));
+	rcu_do_batch(&rcu_preempt_state, this_cpu_ptr(&rcu_preempt_data));
 }
 
 #endif /* #ifdef CONFIG_RCU_BOOST */
@@ -1128,7 +1133,7 @@
 
 #ifdef CONFIG_RCU_BOOST
 
-#include "rtmutex_common.h"
+#include "../rtmutex_common.h"
 
 #ifdef CONFIG_RCU_TRACE
 
@@ -1332,7 +1337,7 @@
  */
 static bool rcu_is_callbacks_kthread(void)
 {
-	return __get_cpu_var(rcu_cpu_kthread_task) == current;
+	return __this_cpu_read(rcu_cpu_kthread_task) == current;
 }
 
 #define RCU_BOOST_DELAY_JIFFIES DIV_ROUND_UP(CONFIG_RCU_BOOST_DELAY * HZ, 1000)
@@ -1382,8 +1387,8 @@
 
 static void rcu_kthread_do_work(void)
 {
-	rcu_do_batch(&rcu_sched_state, &__get_cpu_var(rcu_sched_data));
-	rcu_do_batch(&rcu_bh_state, &__get_cpu_var(rcu_bh_data));
+	rcu_do_batch(&rcu_sched_state, this_cpu_ptr(&rcu_sched_data));
+	rcu_do_batch(&rcu_bh_state, this_cpu_ptr(&rcu_bh_data));
 	rcu_preempt_do_callbacks();
 }
 
@@ -1402,7 +1407,7 @@
 
 static int rcu_cpu_kthread_should_run(unsigned int cpu)
 {
-	return __get_cpu_var(rcu_cpu_has_work);
+	return __this_cpu_read(rcu_cpu_has_work);
 }
 
 /*
@@ -1412,8 +1417,8 @@
  */
 static void rcu_cpu_kthread(unsigned int cpu)
 {
-	unsigned int *statusp = &__get_cpu_var(rcu_cpu_kthread_status);
-	char work, *workp = &__get_cpu_var(rcu_cpu_has_work);
+	unsigned int *statusp = this_cpu_ptr(&rcu_cpu_kthread_status);
+	char work, *workp = this_cpu_ptr(&rcu_cpu_has_work);
 	int spincnt;
 
 	for (spincnt = 0; spincnt < 10; spincnt++) {
@@ -1630,17 +1635,23 @@
 extern int tick_nohz_enabled;
 
 /*
- * Try to advance callbacks for all flavors of RCU on the current CPU.
- * Afterwards, if there are any callbacks ready for immediate invocation,
- * return true.
+ * Try to advance callbacks for all flavors of RCU on the current CPU, but
+ * only if it has been awhile since the last time we did so.  Afterwards,
+ * if there are any callbacks ready for immediate invocation, return true.
  */
 static bool rcu_try_advance_all_cbs(void)
 {
 	bool cbs_ready = false;
 	struct rcu_data *rdp;
+	struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
 	struct rcu_node *rnp;
 	struct rcu_state *rsp;
 
+	/* Exit early if we advanced recently. */
+	if (jiffies == rdtp->last_advance_all)
+		return 0;
+	rdtp->last_advance_all = jiffies;
+
 	for_each_rcu_flavor(rsp) {
 		rdp = this_cpu_ptr(rsp->rda);
 		rnp = rdp->mynode;
@@ -1739,6 +1750,8 @@
 	 */
 	if (rdtp->all_lazy &&
 	    rdtp->nonlazy_posted != rdtp->nonlazy_posted_snap) {
+		rdtp->all_lazy = false;
+		rdtp->nonlazy_posted_snap = rdtp->nonlazy_posted;
 		invoke_rcu_core();
 		return;
 	}
@@ -1768,17 +1781,11 @@
  */
 static void rcu_cleanup_after_idle(int cpu)
 {
-	struct rcu_data *rdp;
-	struct rcu_state *rsp;
 
 	if (rcu_is_nocb_cpu(cpu))
 		return;
-	rcu_try_advance_all_cbs();
-	for_each_rcu_flavor(rsp) {
-		rdp = per_cpu_ptr(rsp->rda, cpu);
-		if (cpu_has_callbacks_ready_to_invoke(rdp))
-			invoke_rcu_core();
-	}
+	if (rcu_try_advance_all_cbs())
+		invoke_rcu_core();
 }
 
 /*
@@ -2108,15 +2115,22 @@
 
 	/* If we are not being polled and there is a kthread, awaken it ... */
 	t = ACCESS_ONCE(rdp->nocb_kthread);
-	if (rcu_nocb_poll | !t)
+	if (rcu_nocb_poll || !t) {
+		trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
+				    TPS("WakeNotPoll"));
 		return;
+	}
 	len = atomic_long_read(&rdp->nocb_q_count);
 	if (old_rhpp == &rdp->nocb_head) {
 		wake_up(&rdp->nocb_wq); /* ... only if queue was empty ... */
 		rdp->qlen_last_fqs_check = 0;
+		trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("WakeEmpty"));
 	} else if (len > rdp->qlen_last_fqs_check + qhimark) {
 		wake_up_process(t); /* ... or if many callbacks queued. */
 		rdp->qlen_last_fqs_check = LONG_MAX / 2;
+		trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("WakeOvf"));
+	} else {
+		trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu, TPS("WakeNot"));
 	}
 	return;
 }
@@ -2140,10 +2154,12 @@
 	if (__is_kfree_rcu_offset((unsigned long)rhp->func))
 		trace_rcu_kfree_callback(rdp->rsp->name, rhp,
 					 (unsigned long)rhp->func,
-					 rdp->qlen_lazy, rdp->qlen);
+					 -atomic_long_read(&rdp->nocb_q_count_lazy),
+					 -atomic_long_read(&rdp->nocb_q_count));
 	else
 		trace_rcu_callback(rdp->rsp->name, rhp,
-				   rdp->qlen_lazy, rdp->qlen);
+				   -atomic_long_read(&rdp->nocb_q_count_lazy),
+				   -atomic_long_read(&rdp->nocb_q_count));
 	return 1;
 }
 
@@ -2221,6 +2237,7 @@
 static int rcu_nocb_kthread(void *arg)
 {
 	int c, cl;
+	bool firsttime = 1;
 	struct rcu_head *list;
 	struct rcu_head *next;
 	struct rcu_head **tail;
@@ -2229,14 +2246,27 @@
 	/* Each pass through this loop invokes one batch of callbacks */
 	for (;;) {
 		/* If not polling, wait for next batch of callbacks. */
-		if (!rcu_nocb_poll)
+		if (!rcu_nocb_poll) {
+			trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
+					    TPS("Sleep"));
 			wait_event_interruptible(rdp->nocb_wq, rdp->nocb_head);
+		} else if (firsttime) {
+			firsttime = 0;
+			trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
+					    TPS("Poll"));
+		}
 		list = ACCESS_ONCE(rdp->nocb_head);
 		if (!list) {
+			if (!rcu_nocb_poll)
+				trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
+						    TPS("WokeEmpty"));
 			schedule_timeout_interruptible(1);
 			flush_signals(current);
 			continue;
 		}
+		firsttime = 1;
+		trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
+				    TPS("WokeNonEmpty"));
 
 		/*
 		 * Extract queued callbacks, update counts, and wait
@@ -2257,7 +2287,11 @@
 			next = list->next;
 			/* Wait for enqueuing to complete, if needed. */
 			while (next == NULL && &list->next != tail) {
+				trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
+						    TPS("WaitQueue"));
 				schedule_timeout_interruptible(1);
+				trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
+						    TPS("WokeQueue"));
 				next = list->next;
 			}
 			debug_rcu_head_unqueue(list);
diff --git a/kernel/rcutree_trace.c b/kernel/rcu/tree_trace.c
similarity index 99%
rename from kernel/rcutree_trace.c
rename to kernel/rcu/tree_trace.c
index cf6c174..3596797 100644
--- a/kernel/rcutree_trace.c
+++ b/kernel/rcu/tree_trace.c
@@ -44,7 +44,7 @@
 #include <linux/seq_file.h>
 
 #define RCU_TREE_NONCORE
-#include "rcutree.h"
+#include "tree.h"
 
 static int r_open(struct inode *inode, struct file *file,
 					const struct seq_operations *op)
diff --git a/kernel/rcupdate.c b/kernel/rcu/update.c
similarity index 97%
rename from kernel/rcupdate.c
rename to kernel/rcu/update.c
index b02a339..6cb3dff 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcu/update.c
@@ -53,6 +53,12 @@
 
 #include "rcu.h"
 
+MODULE_ALIAS("rcupdate");
+#ifdef MODULE_PARAM_PREFIX
+#undef MODULE_PARAM_PREFIX
+#endif
+#define MODULE_PARAM_PREFIX "rcupdate."
+
 module_param(rcu_expedited, int, 0);
 
 #ifdef CONFIG_PREEMPT_RCU
@@ -148,7 +154,7 @@
 {
 	if (!debug_lockdep_rcu_enabled())
 		return 1;
-	if (rcu_is_cpu_idle())
+	if (!rcu_is_watching())
 		return 0;
 	if (!rcu_lockdep_current_cpu_online())
 		return 0;
@@ -298,7 +304,7 @@
 #endif
 
 int rcu_cpu_stall_suppress __read_mostly; /* 1 = suppress stall warnings. */
-int rcu_cpu_stall_timeout __read_mostly = CONFIG_RCU_CPU_STALL_TIMEOUT;
+static int rcu_cpu_stall_timeout __read_mostly = CONFIG_RCU_CPU_STALL_TIMEOUT;
 
 module_param(rcu_cpu_stall_suppress, int, 0644);
 module_param(rcu_cpu_stall_timeout, int, 0644);
diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile
index 54adcf3..7b62140 100644
--- a/kernel/sched/Makefile
+++ b/kernel/sched/Makefile
@@ -12,6 +12,7 @@
 endif
 
 obj-y += core.o proc.o clock.o cputime.o idle_task.o fair.o rt.o stop_task.o
+obj-y += wait.o completion.o
 obj-$(CONFIG_SMP) += cpupri.o
 obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o
 obj-$(CONFIG_SCHEDSTATS) += stats.o
diff --git a/kernel/sched/completion.c b/kernel/sched/completion.c
new file mode 100644
index 0000000..a63f4dc
--- /dev/null
+++ b/kernel/sched/completion.c
@@ -0,0 +1,299 @@
+/*
+ * Generic wait-for-completion handler;
+ *
+ * It differs from semaphores in that their default case is the opposite,
+ * wait_for_completion default blocks whereas semaphore default non-block. The
+ * interface also makes it easy to 'complete' multiple waiting threads,
+ * something which isn't entirely natural for semaphores.
+ *
+ * But more importantly, the primitive documents the usage. Semaphores would
+ * typically be used for exclusion which gives rise to priority inversion.
+ * Waiting for completion is a typically sync point, but not an exclusion point.
+ */
+
+#include <linux/sched.h>
+#include <linux/completion.h>
+
+/**
+ * complete: - signals a single thread waiting on this completion
+ * @x:  holds the state of this particular completion
+ *
+ * This will wake up a single thread waiting on this completion. Threads will be
+ * awakened in the same order in which they were queued.
+ *
+ * See also complete_all(), wait_for_completion() and related routines.
+ *
+ * It may be assumed that this function implies a write memory barrier before
+ * changing the task state if and only if any tasks are woken up.
+ */
+void complete(struct completion *x)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&x->wait.lock, flags);
+	x->done++;
+	__wake_up_locked(&x->wait, TASK_NORMAL, 1);
+	spin_unlock_irqrestore(&x->wait.lock, flags);
+}
+EXPORT_SYMBOL(complete);
+
+/**
+ * complete_all: - signals all threads waiting on this completion
+ * @x:  holds the state of this particular completion
+ *
+ * This will wake up all threads waiting on this particular completion event.
+ *
+ * It may be assumed that this function implies a write memory barrier before
+ * changing the task state if and only if any tasks are woken up.
+ */
+void complete_all(struct completion *x)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&x->wait.lock, flags);
+	x->done += UINT_MAX/2;
+	__wake_up_locked(&x->wait, TASK_NORMAL, 0);
+	spin_unlock_irqrestore(&x->wait.lock, flags);
+}
+EXPORT_SYMBOL(complete_all);
+
+static inline long __sched
+do_wait_for_common(struct completion *x,
+		   long (*action)(long), long timeout, int state)
+{
+	if (!x->done) {
+		DECLARE_WAITQUEUE(wait, current);
+
+		__add_wait_queue_tail_exclusive(&x->wait, &wait);
+		do {
+			if (signal_pending_state(state, current)) {
+				timeout = -ERESTARTSYS;
+				break;
+			}
+			__set_current_state(state);
+			spin_unlock_irq(&x->wait.lock);
+			timeout = action(timeout);
+			spin_lock_irq(&x->wait.lock);
+		} while (!x->done && timeout);
+		__remove_wait_queue(&x->wait, &wait);
+		if (!x->done)
+			return timeout;
+	}
+	x->done--;
+	return timeout ?: 1;
+}
+
+static inline long __sched
+__wait_for_common(struct completion *x,
+		  long (*action)(long), long timeout, int state)
+{
+	might_sleep();
+
+	spin_lock_irq(&x->wait.lock);
+	timeout = do_wait_for_common(x, action, timeout, state);
+	spin_unlock_irq(&x->wait.lock);
+	return timeout;
+}
+
+static long __sched
+wait_for_common(struct completion *x, long timeout, int state)
+{
+	return __wait_for_common(x, schedule_timeout, timeout, state);
+}
+
+static long __sched
+wait_for_common_io(struct completion *x, long timeout, int state)
+{
+	return __wait_for_common(x, io_schedule_timeout, timeout, state);
+}
+
+/**
+ * wait_for_completion: - waits for completion of a task
+ * @x:  holds the state of this particular completion
+ *
+ * This waits to be signaled for completion of a specific task. It is NOT
+ * interruptible and there is no timeout.
+ *
+ * See also similar routines (i.e. wait_for_completion_timeout()) with timeout
+ * and interrupt capability. Also see complete().
+ */
+void __sched wait_for_completion(struct completion *x)
+{
+	wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE);
+}
+EXPORT_SYMBOL(wait_for_completion);
+
+/**
+ * wait_for_completion_timeout: - waits for completion of a task (w/timeout)
+ * @x:  holds the state of this particular completion
+ * @timeout:  timeout value in jiffies
+ *
+ * This waits for either a completion of a specific task to be signaled or for a
+ * specified timeout to expire. The timeout is in jiffies. It is not
+ * interruptible.
+ *
+ * Return: 0 if timed out, and positive (at least 1, or number of jiffies left
+ * till timeout) if completed.
+ */
+unsigned long __sched
+wait_for_completion_timeout(struct completion *x, unsigned long timeout)
+{
+	return wait_for_common(x, timeout, TASK_UNINTERRUPTIBLE);
+}
+EXPORT_SYMBOL(wait_for_completion_timeout);
+
+/**
+ * wait_for_completion_io: - waits for completion of a task
+ * @x:  holds the state of this particular completion
+ *
+ * This waits to be signaled for completion of a specific task. It is NOT
+ * interruptible and there is no timeout. The caller is accounted as waiting
+ * for IO.
+ */
+void __sched wait_for_completion_io(struct completion *x)
+{
+	wait_for_common_io(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE);
+}
+EXPORT_SYMBOL(wait_for_completion_io);
+
+/**
+ * wait_for_completion_io_timeout: - waits for completion of a task (w/timeout)
+ * @x:  holds the state of this particular completion
+ * @timeout:  timeout value in jiffies
+ *
+ * This waits for either a completion of a specific task to be signaled or for a
+ * specified timeout to expire. The timeout is in jiffies. It is not
+ * interruptible. The caller is accounted as waiting for IO.
+ *
+ * Return: 0 if timed out, and positive (at least 1, or number of jiffies left
+ * till timeout) if completed.
+ */
+unsigned long __sched
+wait_for_completion_io_timeout(struct completion *x, unsigned long timeout)
+{
+	return wait_for_common_io(x, timeout, TASK_UNINTERRUPTIBLE);
+}
+EXPORT_SYMBOL(wait_for_completion_io_timeout);
+
+/**
+ * wait_for_completion_interruptible: - waits for completion of a task (w/intr)
+ * @x:  holds the state of this particular completion
+ *
+ * This waits for completion of a specific task to be signaled. It is
+ * interruptible.
+ *
+ * Return: -ERESTARTSYS if interrupted, 0 if completed.
+ */
+int __sched wait_for_completion_interruptible(struct completion *x)
+{
+	long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_INTERRUPTIBLE);
+	if (t == -ERESTARTSYS)
+		return t;
+	return 0;
+}
+EXPORT_SYMBOL(wait_for_completion_interruptible);
+
+/**
+ * wait_for_completion_interruptible_timeout: - waits for completion (w/(to,intr))
+ * @x:  holds the state of this particular completion
+ * @timeout:  timeout value in jiffies
+ *
+ * This waits for either a completion of a specific task to be signaled or for a
+ * specified timeout to expire. It is interruptible. The timeout is in jiffies.
+ *
+ * Return: -ERESTARTSYS if interrupted, 0 if timed out, positive (at least 1,
+ * or number of jiffies left till timeout) if completed.
+ */
+long __sched
+wait_for_completion_interruptible_timeout(struct completion *x,
+					  unsigned long timeout)
+{
+	return wait_for_common(x, timeout, TASK_INTERRUPTIBLE);
+}
+EXPORT_SYMBOL(wait_for_completion_interruptible_timeout);
+
+/**
+ * wait_for_completion_killable: - waits for completion of a task (killable)
+ * @x:  holds the state of this particular completion
+ *
+ * This waits to be signaled for completion of a specific task. It can be
+ * interrupted by a kill signal.
+ *
+ * Return: -ERESTARTSYS if interrupted, 0 if completed.
+ */
+int __sched wait_for_completion_killable(struct completion *x)
+{
+	long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_KILLABLE);
+	if (t == -ERESTARTSYS)
+		return t;
+	return 0;
+}
+EXPORT_SYMBOL(wait_for_completion_killable);
+
+/**
+ * wait_for_completion_killable_timeout: - waits for completion of a task (w/(to,killable))
+ * @x:  holds the state of this particular completion
+ * @timeout:  timeout value in jiffies
+ *
+ * This waits for either a completion of a specific task to be
+ * signaled or for a specified timeout to expire. It can be
+ * interrupted by a kill signal. The timeout is in jiffies.
+ *
+ * Return: -ERESTARTSYS if interrupted, 0 if timed out, positive (at least 1,
+ * or number of jiffies left till timeout) if completed.
+ */
+long __sched
+wait_for_completion_killable_timeout(struct completion *x,
+				     unsigned long timeout)
+{
+	return wait_for_common(x, timeout, TASK_KILLABLE);
+}
+EXPORT_SYMBOL(wait_for_completion_killable_timeout);
+
+/**
+ *	try_wait_for_completion - try to decrement a completion without blocking
+ *	@x:	completion structure
+ *
+ *	Return: 0 if a decrement cannot be done without blocking
+ *		 1 if a decrement succeeded.
+ *
+ *	If a completion is being used as a counting completion,
+ *	attempt to decrement the counter without blocking. This
+ *	enables us to avoid waiting if the resource the completion
+ *	is protecting is not available.
+ */
+bool try_wait_for_completion(struct completion *x)
+{
+	unsigned long flags;
+	int ret = 1;
+
+	spin_lock_irqsave(&x->wait.lock, flags);
+	if (!x->done)
+		ret = 0;
+	else
+		x->done--;
+	spin_unlock_irqrestore(&x->wait.lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(try_wait_for_completion);
+
+/**
+ *	completion_done - Test to see if a completion has any waiters
+ *	@x:	completion structure
+ *
+ *	Return: 0 if there are waiters (wait_for_completion() in progress)
+ *		 1 if there are no waiters.
+ *
+ */
+bool completion_done(struct completion *x)
+{
+	unsigned long flags;
+	int ret = 1;
+
+	spin_lock_irqsave(&x->wait.lock, flags);
+	if (!x->done)
+		ret = 0;
+	spin_unlock_irqrestore(&x->wait.lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(completion_done);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 5ac63c9..1deccd7 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -513,12 +513,11 @@
  * might also involve a cross-CPU call to trigger the scheduler on
  * the target CPU.
  */
-#ifdef CONFIG_SMP
 void resched_task(struct task_struct *p)
 {
 	int cpu;
 
-	assert_raw_spin_locked(&task_rq(p)->lock);
+	lockdep_assert_held(&task_rq(p)->lock);
 
 	if (test_tsk_need_resched(p))
 		return;
@@ -526,8 +525,10 @@
 	set_tsk_need_resched(p);
 
 	cpu = task_cpu(p);
-	if (cpu == smp_processor_id())
+	if (cpu == smp_processor_id()) {
+		set_preempt_need_resched();
 		return;
+	}
 
 	/* NEED_RESCHED must be visible before we test polling */
 	smp_mb();
@@ -546,6 +547,7 @@
 	raw_spin_unlock_irqrestore(&rq->lock, flags);
 }
 
+#ifdef CONFIG_SMP
 #ifdef CONFIG_NO_HZ_COMMON
 /*
  * In the semi idle case, use the nearest busy cpu for migrating timers
@@ -693,12 +695,6 @@
 	}
 }
 
-#else /* !CONFIG_SMP */
-void resched_task(struct task_struct *p)
-{
-	assert_raw_spin_locked(&task_rq(p)->lock);
-	set_tsk_need_resched(p);
-}
 #endif /* CONFIG_SMP */
 
 #if defined(CONFIG_RT_GROUP_SCHED) || (defined(CONFIG_FAIR_GROUP_SCHED) && \
@@ -767,14 +763,14 @@
 static void enqueue_task(struct rq *rq, struct task_struct *p, int flags)
 {
 	update_rq_clock(rq);
-	sched_info_queued(p);
+	sched_info_queued(rq, p);
 	p->sched_class->enqueue_task(rq, p, flags);
 }
 
 static void dequeue_task(struct rq *rq, struct task_struct *p, int flags)
 {
 	update_rq_clock(rq);
-	sched_info_dequeued(p);
+	sched_info_dequeued(rq, p);
 	p->sched_class->dequeue_task(rq, p, flags);
 }
 
@@ -987,7 +983,7 @@
 	 * ttwu() will sort out the placement.
 	 */
 	WARN_ON_ONCE(p->state != TASK_RUNNING && p->state != TASK_WAKING &&
-			!(task_thread_info(p)->preempt_count & PREEMPT_ACTIVE));
+			!(task_preempt_count(p) & PREEMPT_ACTIVE));
 
 #ifdef CONFIG_LOCKDEP
 	/*
@@ -1017,6 +1013,107 @@
 	__set_task_cpu(p, new_cpu);
 }
 
+static void __migrate_swap_task(struct task_struct *p, int cpu)
+{
+	if (p->on_rq) {
+		struct rq *src_rq, *dst_rq;
+
+		src_rq = task_rq(p);
+		dst_rq = cpu_rq(cpu);
+
+		deactivate_task(src_rq, p, 0);
+		set_task_cpu(p, cpu);
+		activate_task(dst_rq, p, 0);
+		check_preempt_curr(dst_rq, p, 0);
+	} else {
+		/*
+		 * Task isn't running anymore; make it appear like we migrated
+		 * it before it went to sleep. This means on wakeup we make the
+		 * previous cpu our targer instead of where it really is.
+		 */
+		p->wake_cpu = cpu;
+	}
+}
+
+struct migration_swap_arg {
+	struct task_struct *src_task, *dst_task;
+	int src_cpu, dst_cpu;
+};
+
+static int migrate_swap_stop(void *data)
+{
+	struct migration_swap_arg *arg = data;
+	struct rq *src_rq, *dst_rq;
+	int ret = -EAGAIN;
+
+	src_rq = cpu_rq(arg->src_cpu);
+	dst_rq = cpu_rq(arg->dst_cpu);
+
+	double_raw_lock(&arg->src_task->pi_lock,
+			&arg->dst_task->pi_lock);
+	double_rq_lock(src_rq, dst_rq);
+	if (task_cpu(arg->dst_task) != arg->dst_cpu)
+		goto unlock;
+
+	if (task_cpu(arg->src_task) != arg->src_cpu)
+		goto unlock;
+
+	if (!cpumask_test_cpu(arg->dst_cpu, tsk_cpus_allowed(arg->src_task)))
+		goto unlock;
+
+	if (!cpumask_test_cpu(arg->src_cpu, tsk_cpus_allowed(arg->dst_task)))
+		goto unlock;
+
+	__migrate_swap_task(arg->src_task, arg->dst_cpu);
+	__migrate_swap_task(arg->dst_task, arg->src_cpu);
+
+	ret = 0;
+
+unlock:
+	double_rq_unlock(src_rq, dst_rq);
+	raw_spin_unlock(&arg->dst_task->pi_lock);
+	raw_spin_unlock(&arg->src_task->pi_lock);
+
+	return ret;
+}
+
+/*
+ * Cross migrate two tasks
+ */
+int migrate_swap(struct task_struct *cur, struct task_struct *p)
+{
+	struct migration_swap_arg arg;
+	int ret = -EINVAL;
+
+	arg = (struct migration_swap_arg){
+		.src_task = cur,
+		.src_cpu = task_cpu(cur),
+		.dst_task = p,
+		.dst_cpu = task_cpu(p),
+	};
+
+	if (arg.src_cpu == arg.dst_cpu)
+		goto out;
+
+	/*
+	 * These three tests are all lockless; this is OK since all of them
+	 * will be re-checked with proper locks held further down the line.
+	 */
+	if (!cpu_active(arg.src_cpu) || !cpu_active(arg.dst_cpu))
+		goto out;
+
+	if (!cpumask_test_cpu(arg.dst_cpu, tsk_cpus_allowed(arg.src_task)))
+		goto out;
+
+	if (!cpumask_test_cpu(arg.src_cpu, tsk_cpus_allowed(arg.dst_task)))
+		goto out;
+
+	ret = stop_two_cpus(arg.dst_cpu, arg.src_cpu, migrate_swap_stop, &arg);
+
+out:
+	return ret;
+}
+
 struct migration_arg {
 	struct task_struct *task;
 	int dest_cpu;
@@ -1236,9 +1333,9 @@
  * The caller (fork, wakeup) owns p->pi_lock, ->cpus_allowed is stable.
  */
 static inline
-int select_task_rq(struct task_struct *p, int sd_flags, int wake_flags)
+int select_task_rq(struct task_struct *p, int cpu, int sd_flags, int wake_flags)
 {
-	int cpu = p->sched_class->select_task_rq(p, sd_flags, wake_flags);
+	cpu = p->sched_class->select_task_rq(p, cpu, sd_flags, wake_flags);
 
 	/*
 	 * In order not to call set_task_cpu() on a blocking task we need
@@ -1330,12 +1427,13 @@
 
 	if (rq->idle_stamp) {
 		u64 delta = rq_clock(rq) - rq->idle_stamp;
-		u64 max = 2*sysctl_sched_migration_cost;
+		u64 max = 2*rq->max_idle_balance_cost;
 
-		if (delta > max)
+		update_avg(&rq->avg_idle, delta);
+
+		if (rq->avg_idle > max)
 			rq->avg_idle = max;
-		else
-			update_avg(&rq->avg_idle, delta);
+
 		rq->idle_stamp = 0;
 	}
 #endif
@@ -1396,6 +1494,14 @@
 
 void scheduler_ipi(void)
 {
+	/*
+	 * Fold TIF_NEED_RESCHED into the preempt_count; anybody setting
+	 * TIF_NEED_RESCHED remotely (for the first time) will also send
+	 * this IPI.
+	 */
+	if (tif_need_resched())
+		set_preempt_need_resched();
+
 	if (llist_empty(&this_rq()->wake_list)
 			&& !tick_nohz_full_cpu(smp_processor_id())
 			&& !got_nohz_idle_kick())
@@ -1513,7 +1619,7 @@
 	if (p->sched_class->task_waking)
 		p->sched_class->task_waking(p);
 
-	cpu = select_task_rq(p, SD_BALANCE_WAKE, wake_flags);
+	cpu = select_task_rq(p, p->wake_cpu, SD_BALANCE_WAKE, wake_flags);
 	if (task_cpu(p) != cpu) {
 		wake_flags |= WF_MIGRATED;
 		set_task_cpu(p, cpu);
@@ -1595,7 +1701,7 @@
  *
  * __sched_fork() is basic setup used by init_idle() too:
  */
-static void __sched_fork(struct task_struct *p)
+static void __sched_fork(unsigned long clone_flags, struct task_struct *p)
 {
 	p->on_rq			= 0;
 
@@ -1619,16 +1725,24 @@
 
 #ifdef CONFIG_NUMA_BALANCING
 	if (p->mm && atomic_read(&p->mm->mm_users) == 1) {
-		p->mm->numa_next_scan = jiffies;
-		p->mm->numa_next_reset = jiffies;
+		p->mm->numa_next_scan = jiffies + msecs_to_jiffies(sysctl_numa_balancing_scan_delay);
 		p->mm->numa_scan_seq = 0;
 	}
 
+	if (clone_flags & CLONE_VM)
+		p->numa_preferred_nid = current->numa_preferred_nid;
+	else
+		p->numa_preferred_nid = -1;
+
 	p->node_stamp = 0ULL;
 	p->numa_scan_seq = p->mm ? p->mm->numa_scan_seq : 0;
-	p->numa_migrate_seq = p->mm ? p->mm->numa_scan_seq - 1 : 0;
 	p->numa_scan_period = sysctl_numa_balancing_scan_delay;
 	p->numa_work.next = &p->numa_work;
+	p->numa_faults = NULL;
+	p->numa_faults_buffer = NULL;
+
+	INIT_LIST_HEAD(&p->numa_entry);
+	p->numa_group = NULL;
 #endif /* CONFIG_NUMA_BALANCING */
 }
 
@@ -1654,12 +1768,12 @@
 /*
  * fork()/clone()-time setup:
  */
-void sched_fork(struct task_struct *p)
+void sched_fork(unsigned long clone_flags, struct task_struct *p)
 {
 	unsigned long flags;
 	int cpu = get_cpu();
 
-	__sched_fork(p);
+	__sched_fork(clone_flags, p);
 	/*
 	 * We mark the process as running here. This guarantees that
 	 * nobody will actually run it, and a signal or other external
@@ -1717,10 +1831,7 @@
 #if defined(CONFIG_SMP)
 	p->on_cpu = 0;
 #endif
-#ifdef CONFIG_PREEMPT_COUNT
-	/* Want to start with kernel preemption disabled. */
-	task_thread_info(p)->preempt_count = 1;
-#endif
+	init_task_preempt_count(p);
 #ifdef CONFIG_SMP
 	plist_node_init(&p->pushable_tasks, MAX_PRIO);
 #endif
@@ -1747,7 +1858,7 @@
 	 *  - cpus_allowed can change in the fork path
 	 *  - any previously selected cpu might disappear through hotplug
 	 */
-	set_task_cpu(p, select_task_rq(p, SD_BALANCE_FORK, 0));
+	set_task_cpu(p, select_task_rq(p, task_cpu(p), SD_BALANCE_FORK, 0));
 #endif
 
 	/* Initialize new task's runnable average */
@@ -1838,7 +1949,7 @@
 		    struct task_struct *next)
 {
 	trace_sched_switch(prev, next);
-	sched_info_switch(prev, next);
+	sched_info_switch(rq, prev, next);
 	perf_event_task_sched_out(prev, next);
 	fire_sched_out_preempt_notifiers(prev, next);
 	prepare_lock_switch(rq, next);
@@ -1890,6 +2001,8 @@
 	if (mm)
 		mmdrop(mm);
 	if (unlikely(prev_state == TASK_DEAD)) {
+		task_numa_free(prev);
+
 		/*
 		 * Remove function-return probe instances associated with this
 		 * task and put them back on the free list.
@@ -2073,7 +2186,7 @@
 	int dest_cpu;
 
 	raw_spin_lock_irqsave(&p->pi_lock, flags);
-	dest_cpu = p->sched_class->select_task_rq(p, SD_BALANCE_EXEC, 0);
+	dest_cpu = p->sched_class->select_task_rq(p, task_cpu(p), SD_BALANCE_EXEC, 0);
 	if (dest_cpu == smp_processor_id())
 		goto unlock;
 
@@ -2215,7 +2328,7 @@
 #if defined(CONFIG_PREEMPT) && (defined(CONFIG_DEBUG_PREEMPT) || \
 				defined(CONFIG_PREEMPT_TRACER))
 
-void __kprobes add_preempt_count(int val)
+void __kprobes preempt_count_add(int val)
 {
 #ifdef CONFIG_DEBUG_PREEMPT
 	/*
@@ -2224,7 +2337,7 @@
 	if (DEBUG_LOCKS_WARN_ON((preempt_count() < 0)))
 		return;
 #endif
-	preempt_count() += val;
+	__preempt_count_add(val);
 #ifdef CONFIG_DEBUG_PREEMPT
 	/*
 	 * Spinlock count overflowing soon?
@@ -2235,9 +2348,9 @@
 	if (preempt_count() == val)
 		trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
 }
-EXPORT_SYMBOL(add_preempt_count);
+EXPORT_SYMBOL(preempt_count_add);
 
-void __kprobes sub_preempt_count(int val)
+void __kprobes preempt_count_sub(int val)
 {
 #ifdef CONFIG_DEBUG_PREEMPT
 	/*
@@ -2255,9 +2368,9 @@
 
 	if (preempt_count() == val)
 		trace_preempt_on(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
-	preempt_count() -= val;
+	__preempt_count_sub(val);
 }
-EXPORT_SYMBOL(sub_preempt_count);
+EXPORT_SYMBOL(preempt_count_sub);
 
 #endif
 
@@ -2430,6 +2543,7 @@
 	put_prev_task(rq, prev);
 	next = pick_next_task(rq);
 	clear_tsk_need_resched(prev);
+	clear_preempt_need_resched();
 	rq->skip_clock_update = 0;
 
 	if (likely(prev != next)) {
@@ -2520,9 +2634,9 @@
 		return;
 
 	do {
-		add_preempt_count_notrace(PREEMPT_ACTIVE);
+		__preempt_count_add(PREEMPT_ACTIVE);
 		__schedule();
-		sub_preempt_count_notrace(PREEMPT_ACTIVE);
+		__preempt_count_sub(PREEMPT_ACTIVE);
 
 		/*
 		 * Check again in case we missed a preemption opportunity
@@ -2541,20 +2655,19 @@
  */
 asmlinkage void __sched preempt_schedule_irq(void)
 {
-	struct thread_info *ti = current_thread_info();
 	enum ctx_state prev_state;
 
 	/* Catch callers which need to be fixed */
-	BUG_ON(ti->preempt_count || !irqs_disabled());
+	BUG_ON(preempt_count() || !irqs_disabled());
 
 	prev_state = exception_enter();
 
 	do {
-		add_preempt_count(PREEMPT_ACTIVE);
+		__preempt_count_add(PREEMPT_ACTIVE);
 		local_irq_enable();
 		__schedule();
 		local_irq_disable();
-		sub_preempt_count(PREEMPT_ACTIVE);
+		__preempt_count_sub(PREEMPT_ACTIVE);
 
 		/*
 		 * Check again in case we missed a preemption opportunity
@@ -2575,393 +2688,6 @@
 }
 EXPORT_SYMBOL(default_wake_function);
 
-/*
- * The core wakeup function. Non-exclusive wakeups (nr_exclusive == 0) just
- * wake everything up. If it's an exclusive wakeup (nr_exclusive == small +ve
- * number) then we wake all the non-exclusive tasks and one exclusive task.
- *
- * There are circumstances in which we can try to wake a task which has already
- * started to run but is not in state TASK_RUNNING. try_to_wake_up() returns
- * zero in this (rare) case, and we handle it by continuing to scan the queue.
- */
-static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
-			int nr_exclusive, int wake_flags, void *key)
-{
-	wait_queue_t *curr, *next;
-
-	list_for_each_entry_safe(curr, next, &q->task_list, task_list) {
-		unsigned flags = curr->flags;
-
-		if (curr->func(curr, mode, wake_flags, key) &&
-				(flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
-			break;
-	}
-}
-
-/**
- * __wake_up - wake up threads blocked on a waitqueue.
- * @q: the waitqueue
- * @mode: which threads
- * @nr_exclusive: how many wake-one or wake-many threads to wake up
- * @key: is directly passed to the wakeup function
- *
- * It may be assumed that this function implies a write memory barrier before
- * changing the task state if and only if any tasks are woken up.
- */
-void __wake_up(wait_queue_head_t *q, unsigned int mode,
-			int nr_exclusive, void *key)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&q->lock, flags);
-	__wake_up_common(q, mode, nr_exclusive, 0, key);
-	spin_unlock_irqrestore(&q->lock, flags);
-}
-EXPORT_SYMBOL(__wake_up);
-
-/*
- * Same as __wake_up but called with the spinlock in wait_queue_head_t held.
- */
-void __wake_up_locked(wait_queue_head_t *q, unsigned int mode, int nr)
-{
-	__wake_up_common(q, mode, nr, 0, NULL);
-}
-EXPORT_SYMBOL_GPL(__wake_up_locked);
-
-void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key)
-{
-	__wake_up_common(q, mode, 1, 0, key);
-}
-EXPORT_SYMBOL_GPL(__wake_up_locked_key);
-
-/**
- * __wake_up_sync_key - wake up threads blocked on a waitqueue.
- * @q: the waitqueue
- * @mode: which threads
- * @nr_exclusive: how many wake-one or wake-many threads to wake up
- * @key: opaque value to be passed to wakeup targets
- *
- * The sync wakeup differs that the waker knows that it will schedule
- * away soon, so while the target thread will be woken up, it will not
- * be migrated to another CPU - ie. the two threads are 'synchronized'
- * with each other. This can prevent needless bouncing between CPUs.
- *
- * On UP it can prevent extra preemption.
- *
- * It may be assumed that this function implies a write memory barrier before
- * changing the task state if and only if any tasks are woken up.
- */
-void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode,
-			int nr_exclusive, void *key)
-{
-	unsigned long flags;
-	int wake_flags = WF_SYNC;
-
-	if (unlikely(!q))
-		return;
-
-	if (unlikely(nr_exclusive != 1))
-		wake_flags = 0;
-
-	spin_lock_irqsave(&q->lock, flags);
-	__wake_up_common(q, mode, nr_exclusive, wake_flags, key);
-	spin_unlock_irqrestore(&q->lock, flags);
-}
-EXPORT_SYMBOL_GPL(__wake_up_sync_key);
-
-/*
- * __wake_up_sync - see __wake_up_sync_key()
- */
-void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
-{
-	__wake_up_sync_key(q, mode, nr_exclusive, NULL);
-}
-EXPORT_SYMBOL_GPL(__wake_up_sync);	/* For internal use only */
-
-/**
- * complete: - signals a single thread waiting on this completion
- * @x:  holds the state of this particular completion
- *
- * This will wake up a single thread waiting on this completion. Threads will be
- * awakened in the same order in which they were queued.
- *
- * See also complete_all(), wait_for_completion() and related routines.
- *
- * It may be assumed that this function implies a write memory barrier before
- * changing the task state if and only if any tasks are woken up.
- */
-void complete(struct completion *x)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&x->wait.lock, flags);
-	x->done++;
-	__wake_up_common(&x->wait, TASK_NORMAL, 1, 0, NULL);
-	spin_unlock_irqrestore(&x->wait.lock, flags);
-}
-EXPORT_SYMBOL(complete);
-
-/**
- * complete_all: - signals all threads waiting on this completion
- * @x:  holds the state of this particular completion
- *
- * This will wake up all threads waiting on this particular completion event.
- *
- * It may be assumed that this function implies a write memory barrier before
- * changing the task state if and only if any tasks are woken up.
- */
-void complete_all(struct completion *x)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&x->wait.lock, flags);
-	x->done += UINT_MAX/2;
-	__wake_up_common(&x->wait, TASK_NORMAL, 0, 0, NULL);
-	spin_unlock_irqrestore(&x->wait.lock, flags);
-}
-EXPORT_SYMBOL(complete_all);
-
-static inline long __sched
-do_wait_for_common(struct completion *x,
-		   long (*action)(long), long timeout, int state)
-{
-	if (!x->done) {
-		DECLARE_WAITQUEUE(wait, current);
-
-		__add_wait_queue_tail_exclusive(&x->wait, &wait);
-		do {
-			if (signal_pending_state(state, current)) {
-				timeout = -ERESTARTSYS;
-				break;
-			}
-			__set_current_state(state);
-			spin_unlock_irq(&x->wait.lock);
-			timeout = action(timeout);
-			spin_lock_irq(&x->wait.lock);
-		} while (!x->done && timeout);
-		__remove_wait_queue(&x->wait, &wait);
-		if (!x->done)
-			return timeout;
-	}
-	x->done--;
-	return timeout ?: 1;
-}
-
-static inline long __sched
-__wait_for_common(struct completion *x,
-		  long (*action)(long), long timeout, int state)
-{
-	might_sleep();
-
-	spin_lock_irq(&x->wait.lock);
-	timeout = do_wait_for_common(x, action, timeout, state);
-	spin_unlock_irq(&x->wait.lock);
-	return timeout;
-}
-
-static long __sched
-wait_for_common(struct completion *x, long timeout, int state)
-{
-	return __wait_for_common(x, schedule_timeout, timeout, state);
-}
-
-static long __sched
-wait_for_common_io(struct completion *x, long timeout, int state)
-{
-	return __wait_for_common(x, io_schedule_timeout, timeout, state);
-}
-
-/**
- * wait_for_completion: - waits for completion of a task
- * @x:  holds the state of this particular completion
- *
- * This waits to be signaled for completion of a specific task. It is NOT
- * interruptible and there is no timeout.
- *
- * See also similar routines (i.e. wait_for_completion_timeout()) with timeout
- * and interrupt capability. Also see complete().
- */
-void __sched wait_for_completion(struct completion *x)
-{
-	wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE);
-}
-EXPORT_SYMBOL(wait_for_completion);
-
-/**
- * wait_for_completion_timeout: - waits for completion of a task (w/timeout)
- * @x:  holds the state of this particular completion
- * @timeout:  timeout value in jiffies
- *
- * This waits for either a completion of a specific task to be signaled or for a
- * specified timeout to expire. The timeout is in jiffies. It is not
- * interruptible.
- *
- * Return: 0 if timed out, and positive (at least 1, or number of jiffies left
- * till timeout) if completed.
- */
-unsigned long __sched
-wait_for_completion_timeout(struct completion *x, unsigned long timeout)
-{
-	return wait_for_common(x, timeout, TASK_UNINTERRUPTIBLE);
-}
-EXPORT_SYMBOL(wait_for_completion_timeout);
-
-/**
- * wait_for_completion_io: - waits for completion of a task
- * @x:  holds the state of this particular completion
- *
- * This waits to be signaled for completion of a specific task. It is NOT
- * interruptible and there is no timeout. The caller is accounted as waiting
- * for IO.
- */
-void __sched wait_for_completion_io(struct completion *x)
-{
-	wait_for_common_io(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE);
-}
-EXPORT_SYMBOL(wait_for_completion_io);
-
-/**
- * wait_for_completion_io_timeout: - waits for completion of a task (w/timeout)
- * @x:  holds the state of this particular completion
- * @timeout:  timeout value in jiffies
- *
- * This waits for either a completion of a specific task to be signaled or for a
- * specified timeout to expire. The timeout is in jiffies. It is not
- * interruptible. The caller is accounted as waiting for IO.
- *
- * Return: 0 if timed out, and positive (at least 1, or number of jiffies left
- * till timeout) if completed.
- */
-unsigned long __sched
-wait_for_completion_io_timeout(struct completion *x, unsigned long timeout)
-{
-	return wait_for_common_io(x, timeout, TASK_UNINTERRUPTIBLE);
-}
-EXPORT_SYMBOL(wait_for_completion_io_timeout);
-
-/**
- * wait_for_completion_interruptible: - waits for completion of a task (w/intr)
- * @x:  holds the state of this particular completion
- *
- * This waits for completion of a specific task to be signaled. It is
- * interruptible.
- *
- * Return: -ERESTARTSYS if interrupted, 0 if completed.
- */
-int __sched wait_for_completion_interruptible(struct completion *x)
-{
-	long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_INTERRUPTIBLE);
-	if (t == -ERESTARTSYS)
-		return t;
-	return 0;
-}
-EXPORT_SYMBOL(wait_for_completion_interruptible);
-
-/**
- * wait_for_completion_interruptible_timeout: - waits for completion (w/(to,intr))
- * @x:  holds the state of this particular completion
- * @timeout:  timeout value in jiffies
- *
- * This waits for either a completion of a specific task to be signaled or for a
- * specified timeout to expire. It is interruptible. The timeout is in jiffies.
- *
- * Return: -ERESTARTSYS if interrupted, 0 if timed out, positive (at least 1,
- * or number of jiffies left till timeout) if completed.
- */
-long __sched
-wait_for_completion_interruptible_timeout(struct completion *x,
-					  unsigned long timeout)
-{
-	return wait_for_common(x, timeout, TASK_INTERRUPTIBLE);
-}
-EXPORT_SYMBOL(wait_for_completion_interruptible_timeout);
-
-/**
- * wait_for_completion_killable: - waits for completion of a task (killable)
- * @x:  holds the state of this particular completion
- *
- * This waits to be signaled for completion of a specific task. It can be
- * interrupted by a kill signal.
- *
- * Return: -ERESTARTSYS if interrupted, 0 if completed.
- */
-int __sched wait_for_completion_killable(struct completion *x)
-{
-	long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_KILLABLE);
-	if (t == -ERESTARTSYS)
-		return t;
-	return 0;
-}
-EXPORT_SYMBOL(wait_for_completion_killable);
-
-/**
- * wait_for_completion_killable_timeout: - waits for completion of a task (w/(to,killable))
- * @x:  holds the state of this particular completion
- * @timeout:  timeout value in jiffies
- *
- * This waits for either a completion of a specific task to be
- * signaled or for a specified timeout to expire. It can be
- * interrupted by a kill signal. The timeout is in jiffies.
- *
- * Return: -ERESTARTSYS if interrupted, 0 if timed out, positive (at least 1,
- * or number of jiffies left till timeout) if completed.
- */
-long __sched
-wait_for_completion_killable_timeout(struct completion *x,
-				     unsigned long timeout)
-{
-	return wait_for_common(x, timeout, TASK_KILLABLE);
-}
-EXPORT_SYMBOL(wait_for_completion_killable_timeout);
-
-/**
- *	try_wait_for_completion - try to decrement a completion without blocking
- *	@x:	completion structure
- *
- *	Return: 0 if a decrement cannot be done without blocking
- *		 1 if a decrement succeeded.
- *
- *	If a completion is being used as a counting completion,
- *	attempt to decrement the counter without blocking. This
- *	enables us to avoid waiting if the resource the completion
- *	is protecting is not available.
- */
-bool try_wait_for_completion(struct completion *x)
-{
-	unsigned long flags;
-	int ret = 1;
-
-	spin_lock_irqsave(&x->wait.lock, flags);
-	if (!x->done)
-		ret = 0;
-	else
-		x->done--;
-	spin_unlock_irqrestore(&x->wait.lock, flags);
-	return ret;
-}
-EXPORT_SYMBOL(try_wait_for_completion);
-
-/**
- *	completion_done - Test to see if a completion has any waiters
- *	@x:	completion structure
- *
- *	Return: 0 if there are waiters (wait_for_completion() in progress)
- *		 1 if there are no waiters.
- *
- */
-bool completion_done(struct completion *x)
-{
-	unsigned long flags;
-	int ret = 1;
-
-	spin_lock_irqsave(&x->wait.lock, flags);
-	if (!x->done)
-		ret = 0;
-	spin_unlock_irqrestore(&x->wait.lock, flags);
-	return ret;
-}
-EXPORT_SYMBOL(completion_done);
-
 static long __sched
 sleep_on_common(wait_queue_head_t *q, int state, long timeout)
 {
@@ -3598,13 +3324,11 @@
 	struct task_struct *p;
 	int retval;
 
-	get_online_cpus();
 	rcu_read_lock();
 
 	p = find_process_by_pid(pid);
 	if (!p) {
 		rcu_read_unlock();
-		put_online_cpus();
 		return -ESRCH;
 	}
 
@@ -3661,7 +3385,6 @@
 	free_cpumask_var(cpus_allowed);
 out_put_task:
 	put_task_struct(p);
-	put_online_cpus();
 	return retval;
 }
 
@@ -3706,7 +3429,6 @@
 	unsigned long flags;
 	int retval;
 
-	get_online_cpus();
 	rcu_read_lock();
 
 	retval = -ESRCH;
@@ -3719,12 +3441,11 @@
 		goto out_unlock;
 
 	raw_spin_lock_irqsave(&p->pi_lock, flags);
-	cpumask_and(mask, &p->cpus_allowed, cpu_online_mask);
+	cpumask_and(mask, &p->cpus_allowed, cpu_active_mask);
 	raw_spin_unlock_irqrestore(&p->pi_lock, flags);
 
 out_unlock:
 	rcu_read_unlock();
-	put_online_cpus();
 
 	return retval;
 }
@@ -3794,16 +3515,11 @@
 	return 0;
 }
 
-static inline int should_resched(void)
-{
-	return need_resched() && !(preempt_count() & PREEMPT_ACTIVE);
-}
-
 static void __cond_resched(void)
 {
-	add_preempt_count(PREEMPT_ACTIVE);
+	__preempt_count_add(PREEMPT_ACTIVE);
 	__schedule();
-	sub_preempt_count(PREEMPT_ACTIVE);
+	__preempt_count_sub(PREEMPT_ACTIVE);
 }
 
 int __sched _cond_resched(void)
@@ -4186,7 +3902,7 @@
 
 	raw_spin_lock_irqsave(&rq->lock, flags);
 
-	__sched_fork(idle);
+	__sched_fork(0, idle);
 	idle->state = TASK_RUNNING;
 	idle->se.exec_start = sched_clock();
 
@@ -4212,7 +3928,7 @@
 	raw_spin_unlock_irqrestore(&rq->lock, flags);
 
 	/* Set the preempt count _outside_ the spinlocks! */
-	task_thread_info(idle)->preempt_count = 0;
+	init_idle_preempt_count(idle, cpu);
 
 	/*
 	 * The idle tasks have their own, simple scheduling class:
@@ -4346,6 +4062,53 @@
 	return ret;
 }
 
+#ifdef CONFIG_NUMA_BALANCING
+/* Migrate current task p to target_cpu */
+int migrate_task_to(struct task_struct *p, int target_cpu)
+{
+	struct migration_arg arg = { p, target_cpu };
+	int curr_cpu = task_cpu(p);
+
+	if (curr_cpu == target_cpu)
+		return 0;
+
+	if (!cpumask_test_cpu(target_cpu, tsk_cpus_allowed(p)))
+		return -EINVAL;
+
+	/* TODO: This is not properly updating schedstats */
+
+	return stop_one_cpu(curr_cpu, migration_cpu_stop, &arg);
+}
+
+/*
+ * Requeue a task on a given node and accurately track the number of NUMA
+ * tasks on the runqueues
+ */
+void sched_setnuma(struct task_struct *p, int nid)
+{
+	struct rq *rq;
+	unsigned long flags;
+	bool on_rq, running;
+
+	rq = task_rq_lock(p, &flags);
+	on_rq = p->on_rq;
+	running = task_current(rq, p);
+
+	if (on_rq)
+		dequeue_task(rq, p, 0);
+	if (running)
+		p->sched_class->put_prev_task(rq, p);
+
+	p->numa_preferred_nid = nid;
+
+	if (running)
+		p->sched_class->set_curr_task(rq);
+	if (on_rq)
+		enqueue_task(rq, p, 0);
+	task_rq_unlock(rq, p, &flags);
+}
+#endif
+
 /*
  * migration_cpu_stop - this will be executed by a highprio stopper thread
  * and performs thread migration by bumping thread off CPU then
@@ -5119,6 +4882,9 @@
 DEFINE_PER_CPU(struct sched_domain *, sd_llc);
 DEFINE_PER_CPU(int, sd_llc_size);
 DEFINE_PER_CPU(int, sd_llc_id);
+DEFINE_PER_CPU(struct sched_domain *, sd_numa);
+DEFINE_PER_CPU(struct sched_domain *, sd_busy);
+DEFINE_PER_CPU(struct sched_domain *, sd_asym);
 
 static void update_top_cache_domain(int cpu)
 {
@@ -5130,11 +4896,18 @@
 	if (sd) {
 		id = cpumask_first(sched_domain_span(sd));
 		size = cpumask_weight(sched_domain_span(sd));
+		rcu_assign_pointer(per_cpu(sd_busy, cpu), sd->parent);
 	}
 
 	rcu_assign_pointer(per_cpu(sd_llc, cpu), sd);
 	per_cpu(sd_llc_size, cpu) = size;
 	per_cpu(sd_llc_id, cpu) = id;
+
+	sd = lowest_flag_domain(cpu, SD_NUMA);
+	rcu_assign_pointer(per_cpu(sd_numa, cpu), sd);
+
+	sd = highest_flag_domain(cpu, SD_ASYM_PACKING);
+	rcu_assign_pointer(per_cpu(sd_asym, cpu), sd);
 }
 
 /*
@@ -5654,6 +5427,7 @@
 					| 0*SD_SHARE_PKG_RESOURCES
 					| 1*SD_SERIALIZE
 					| 0*SD_PREFER_SIBLING
+					| 1*SD_NUMA
 					| sd_local_flags(level)
 					,
 		.last_balance		= jiffies,
@@ -6335,14 +6109,17 @@
 
 	sched_init_numa();
 
-	get_online_cpus();
+	/*
+	 * There's no userspace yet to cause hotplug operations; hence all the
+	 * cpu masks are stable and all blatant races in the below code cannot
+	 * happen.
+	 */
 	mutex_lock(&sched_domains_mutex);
 	init_sched_domains(cpu_active_mask);
 	cpumask_andnot(non_isolated_cpus, cpu_possible_mask, cpu_isolated_map);
 	if (cpumask_empty(non_isolated_cpus))
 		cpumask_set_cpu(smp_processor_id(), non_isolated_cpus);
 	mutex_unlock(&sched_domains_mutex);
-	put_online_cpus();
 
 	hotcpu_notifier(sched_domains_numa_masks_update, CPU_PRI_SCHED_ACTIVE);
 	hotcpu_notifier(cpuset_cpu_active, CPU_PRI_CPUSET_ACTIVE);
@@ -6505,6 +6282,7 @@
 		rq->online = 0;
 		rq->idle_stamp = 0;
 		rq->avg_idle = 2*sysctl_sched_migration_cost;
+		rq->max_idle_balance_cost = sysctl_sched_migration_cost;
 
 		INIT_LIST_HEAD(&rq->cfs_tasks);
 
@@ -7277,7 +7055,12 @@
 
 	runtime_enabled = quota != RUNTIME_INF;
 	runtime_was_enabled = cfs_b->quota != RUNTIME_INF;
-	account_cfs_bandwidth_used(runtime_enabled, runtime_was_enabled);
+	/*
+	 * If we need to toggle cfs_bandwidth_used, off->on must occur
+	 * before making related changes, and on->off must occur afterwards
+	 */
+	if (runtime_enabled && !runtime_was_enabled)
+		cfs_bandwidth_usage_inc();
 	raw_spin_lock_irq(&cfs_b->lock);
 	cfs_b->period = ns_to_ktime(period);
 	cfs_b->quota = quota;
@@ -7303,6 +7086,8 @@
 			unthrottle_cfs_rq(cfs_rq);
 		raw_spin_unlock_irq(&rq->lock);
 	}
+	if (runtime_was_enabled && !runtime_enabled)
+		cfs_bandwidth_usage_dec();
 out_unlock:
 	mutex_unlock(&cfs_constraints_mutex);
 
diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c
index 1965599..5c34d18 100644
--- a/kernel/sched/debug.c
+++ b/kernel/sched/debug.c
@@ -15,6 +15,7 @@
 #include <linux/seq_file.h>
 #include <linux/kallsyms.h>
 #include <linux/utsname.h>
+#include <linux/mempolicy.h>
 
 #include "sched.h"
 
@@ -137,6 +138,9 @@
 	SEQ_printf(m, "%15Ld %15Ld %15Ld.%06ld %15Ld.%06ld %15Ld.%06ld",
 		0LL, 0LL, 0LL, 0L, 0LL, 0L, 0LL, 0L);
 #endif
+#ifdef CONFIG_NUMA_BALANCING
+	SEQ_printf(m, " %d", cpu_to_node(task_cpu(p)));
+#endif
 #ifdef CONFIG_CGROUP_SCHED
 	SEQ_printf(m, " %s", task_group_path(task_group(p)));
 #endif
@@ -159,7 +163,7 @@
 	read_lock_irqsave(&tasklist_lock, flags);
 
 	do_each_thread(g, p) {
-		if (!p->on_rq || task_cpu(p) != rq_cpu)
+		if (task_cpu(p) != rq_cpu)
 			continue;
 
 		print_task(m, rq, p);
@@ -225,6 +229,14 @@
 			atomic_read(&cfs_rq->tg->runnable_avg));
 #endif
 #endif
+#ifdef CONFIG_CFS_BANDWIDTH
+	SEQ_printf(m, "  .%-30s: %d\n", "tg->cfs_bandwidth.timer_active",
+			cfs_rq->tg->cfs_bandwidth.timer_active);
+	SEQ_printf(m, "  .%-30s: %d\n", "throttled",
+			cfs_rq->throttled);
+	SEQ_printf(m, "  .%-30s: %d\n", "throttle_count",
+			cfs_rq->throttle_count);
+#endif
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
 	print_cfs_group_stats(m, cpu, cfs_rq->tg);
@@ -345,7 +357,7 @@
 	cpu_clk = local_clock();
 	local_irq_restore(flags);
 
-	SEQ_printf(m, "Sched Debug Version: v0.10, %s %.*s\n",
+	SEQ_printf(m, "Sched Debug Version: v0.11, %s %.*s\n",
 		init_utsname()->release,
 		(int)strcspn(init_utsname()->version, " "),
 		init_utsname()->version);
@@ -488,6 +500,56 @@
 
 __initcall(init_sched_debug_procfs);
 
+#define __P(F) \
+	SEQ_printf(m, "%-45s:%21Ld\n", #F, (long long)F)
+#define P(F) \
+	SEQ_printf(m, "%-45s:%21Ld\n", #F, (long long)p->F)
+#define __PN(F) \
+	SEQ_printf(m, "%-45s:%14Ld.%06ld\n", #F, SPLIT_NS((long long)F))
+#define PN(F) \
+	SEQ_printf(m, "%-45s:%14Ld.%06ld\n", #F, SPLIT_NS((long long)p->F))
+
+
+static void sched_show_numa(struct task_struct *p, struct seq_file *m)
+{
+#ifdef CONFIG_NUMA_BALANCING
+	struct mempolicy *pol;
+	int node, i;
+
+	if (p->mm)
+		P(mm->numa_scan_seq);
+
+	task_lock(p);
+	pol = p->mempolicy;
+	if (pol && !(pol->flags & MPOL_F_MORON))
+		pol = NULL;
+	mpol_get(pol);
+	task_unlock(p);
+
+	SEQ_printf(m, "numa_migrations, %ld\n", xchg(&p->numa_pages_migrated, 0));
+
+	for_each_online_node(node) {
+		for (i = 0; i < 2; i++) {
+			unsigned long nr_faults = -1;
+			int cpu_current, home_node;
+
+			if (p->numa_faults)
+				nr_faults = p->numa_faults[2*node + i];
+
+			cpu_current = !i ? (task_node(p) == node) :
+				(pol && node_isset(node, pol->v.nodes));
+
+			home_node = (p->numa_preferred_nid == node);
+
+			SEQ_printf(m, "numa_faults, %d, %d, %d, %d, %ld\n",
+				i, node, cpu_current, home_node, nr_faults);
+		}
+	}
+
+	mpol_put(pol);
+#endif
+}
+
 void proc_sched_show_task(struct task_struct *p, struct seq_file *m)
 {
 	unsigned long nr_switches;
@@ -591,6 +653,8 @@
 		SEQ_printf(m, "%-45s:%21Ld\n",
 			   "clock-delta", (long long)(t1-t0));
 	}
+
+	sched_show_numa(p, m);
 }
 
 void proc_sched_set_task(struct task_struct *p)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 7c70201..df77c60 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -681,6 +681,8 @@
 }
 
 #ifdef CONFIG_SMP
+static unsigned long task_h_load(struct task_struct *p);
+
 static inline void __update_task_entity_contrib(struct sched_entity *se);
 
 /* Give new task start runnable values to heavy its load in infant time */
@@ -818,11 +820,12 @@
 
 #ifdef CONFIG_NUMA_BALANCING
 /*
- * numa task sample period in ms
+ * Approximate time to scan a full NUMA task in ms. The task scan period is
+ * calculated based on the tasks virtual memory size and
+ * numa_balancing_scan_size.
  */
-unsigned int sysctl_numa_balancing_scan_period_min = 100;
-unsigned int sysctl_numa_balancing_scan_period_max = 100*50;
-unsigned int sysctl_numa_balancing_scan_period_reset = 100*600;
+unsigned int sysctl_numa_balancing_scan_period_min = 1000;
+unsigned int sysctl_numa_balancing_scan_period_max = 60000;
 
 /* Portion of address space to scan in MB */
 unsigned int sysctl_numa_balancing_scan_size = 256;
@@ -830,41 +833,810 @@
 /* Scan @scan_size MB every @scan_period after an initial @scan_delay in ms */
 unsigned int sysctl_numa_balancing_scan_delay = 1000;
 
+/*
+ * After skipping a page migration on a shared page, skip N more numa page
+ * migrations unconditionally. This reduces the number of NUMA migrations
+ * in shared memory workloads, and has the effect of pulling tasks towards
+ * where their memory lives, over pulling the memory towards the task.
+ */
+unsigned int sysctl_numa_balancing_migrate_deferred = 16;
+
+static unsigned int task_nr_scan_windows(struct task_struct *p)
+{
+	unsigned long rss = 0;
+	unsigned long nr_scan_pages;
+
+	/*
+	 * Calculations based on RSS as non-present and empty pages are skipped
+	 * by the PTE scanner and NUMA hinting faults should be trapped based
+	 * on resident pages
+	 */
+	nr_scan_pages = sysctl_numa_balancing_scan_size << (20 - PAGE_SHIFT);
+	rss = get_mm_rss(p->mm);
+	if (!rss)
+		rss = nr_scan_pages;
+
+	rss = round_up(rss, nr_scan_pages);
+	return rss / nr_scan_pages;
+}
+
+/* For sanitys sake, never scan more PTEs than MAX_SCAN_WINDOW MB/sec. */
+#define MAX_SCAN_WINDOW 2560
+
+static unsigned int task_scan_min(struct task_struct *p)
+{
+	unsigned int scan, floor;
+	unsigned int windows = 1;
+
+	if (sysctl_numa_balancing_scan_size < MAX_SCAN_WINDOW)
+		windows = MAX_SCAN_WINDOW / sysctl_numa_balancing_scan_size;
+	floor = 1000 / windows;
+
+	scan = sysctl_numa_balancing_scan_period_min / task_nr_scan_windows(p);
+	return max_t(unsigned int, floor, scan);
+}
+
+static unsigned int task_scan_max(struct task_struct *p)
+{
+	unsigned int smin = task_scan_min(p);
+	unsigned int smax;
+
+	/* Watch for min being lower than max due to floor calculations */
+	smax = sysctl_numa_balancing_scan_period_max / task_nr_scan_windows(p);
+	return max(smin, smax);
+}
+
+/*
+ * Once a preferred node is selected the scheduler balancer will prefer moving
+ * a task to that node for sysctl_numa_balancing_settle_count number of PTE
+ * scans. This will give the process the chance to accumulate more faults on
+ * the preferred node but still allow the scheduler to move the task again if
+ * the nodes CPUs are overloaded.
+ */
+unsigned int sysctl_numa_balancing_settle_count __read_mostly = 4;
+
+static void account_numa_enqueue(struct rq *rq, struct task_struct *p)
+{
+	rq->nr_numa_running += (p->numa_preferred_nid != -1);
+	rq->nr_preferred_running += (p->numa_preferred_nid == task_node(p));
+}
+
+static void account_numa_dequeue(struct rq *rq, struct task_struct *p)
+{
+	rq->nr_numa_running -= (p->numa_preferred_nid != -1);
+	rq->nr_preferred_running -= (p->numa_preferred_nid == task_node(p));
+}
+
+struct numa_group {
+	atomic_t refcount;
+
+	spinlock_t lock; /* nr_tasks, tasks */
+	int nr_tasks;
+	pid_t gid;
+	struct list_head task_list;
+
+	struct rcu_head rcu;
+	unsigned long total_faults;
+	unsigned long faults[0];
+};
+
+pid_t task_numa_group_id(struct task_struct *p)
+{
+	return p->numa_group ? p->numa_group->gid : 0;
+}
+
+static inline int task_faults_idx(int nid, int priv)
+{
+	return 2 * nid + priv;
+}
+
+static inline unsigned long task_faults(struct task_struct *p, int nid)
+{
+	if (!p->numa_faults)
+		return 0;
+
+	return p->numa_faults[task_faults_idx(nid, 0)] +
+		p->numa_faults[task_faults_idx(nid, 1)];
+}
+
+static inline unsigned long group_faults(struct task_struct *p, int nid)
+{
+	if (!p->numa_group)
+		return 0;
+
+	return p->numa_group->faults[2*nid] + p->numa_group->faults[2*nid+1];
+}
+
+/*
+ * These return the fraction of accesses done by a particular task, or
+ * task group, on a particular numa node.  The group weight is given a
+ * larger multiplier, in order to group tasks together that are almost
+ * evenly spread out between numa nodes.
+ */
+static inline unsigned long task_weight(struct task_struct *p, int nid)
+{
+	unsigned long total_faults;
+
+	if (!p->numa_faults)
+		return 0;
+
+	total_faults = p->total_numa_faults;
+
+	if (!total_faults)
+		return 0;
+
+	return 1000 * task_faults(p, nid) / total_faults;
+}
+
+static inline unsigned long group_weight(struct task_struct *p, int nid)
+{
+	if (!p->numa_group || !p->numa_group->total_faults)
+		return 0;
+
+	return 1000 * group_faults(p, nid) / p->numa_group->total_faults;
+}
+
+static unsigned long weighted_cpuload(const int cpu);
+static unsigned long source_load(int cpu, int type);
+static unsigned long target_load(int cpu, int type);
+static unsigned long power_of(int cpu);
+static long effective_load(struct task_group *tg, int cpu, long wl, long wg);
+
+/* Cached statistics for all CPUs within a node */
+struct numa_stats {
+	unsigned long nr_running;
+	unsigned long load;
+
+	/* Total compute capacity of CPUs on a node */
+	unsigned long power;
+
+	/* Approximate capacity in terms of runnable tasks on a node */
+	unsigned long capacity;
+	int has_capacity;
+};
+
+/*
+ * XXX borrowed from update_sg_lb_stats
+ */
+static void update_numa_stats(struct numa_stats *ns, int nid)
+{
+	int cpu;
+
+	memset(ns, 0, sizeof(*ns));
+	for_each_cpu(cpu, cpumask_of_node(nid)) {
+		struct rq *rq = cpu_rq(cpu);
+
+		ns->nr_running += rq->nr_running;
+		ns->load += weighted_cpuload(cpu);
+		ns->power += power_of(cpu);
+	}
+
+	ns->load = (ns->load * SCHED_POWER_SCALE) / ns->power;
+	ns->capacity = DIV_ROUND_CLOSEST(ns->power, SCHED_POWER_SCALE);
+	ns->has_capacity = (ns->nr_running < ns->capacity);
+}
+
+struct task_numa_env {
+	struct task_struct *p;
+
+	int src_cpu, src_nid;
+	int dst_cpu, dst_nid;
+
+	struct numa_stats src_stats, dst_stats;
+
+	int imbalance_pct, idx;
+
+	struct task_struct *best_task;
+	long best_imp;
+	int best_cpu;
+};
+
+static void task_numa_assign(struct task_numa_env *env,
+			     struct task_struct *p, long imp)
+{
+	if (env->best_task)
+		put_task_struct(env->best_task);
+	if (p)
+		get_task_struct(p);
+
+	env->best_task = p;
+	env->best_imp = imp;
+	env->best_cpu = env->dst_cpu;
+}
+
+/*
+ * This checks if the overall compute and NUMA accesses of the system would
+ * be improved if the source tasks was migrated to the target dst_cpu taking
+ * into account that it might be best if task running on the dst_cpu should
+ * be exchanged with the source task
+ */
+static void task_numa_compare(struct task_numa_env *env,
+			      long taskimp, long groupimp)
+{
+	struct rq *src_rq = cpu_rq(env->src_cpu);
+	struct rq *dst_rq = cpu_rq(env->dst_cpu);
+	struct task_struct *cur;
+	long dst_load, src_load;
+	long load;
+	long imp = (groupimp > 0) ? groupimp : taskimp;
+
+	rcu_read_lock();
+	cur = ACCESS_ONCE(dst_rq->curr);
+	if (cur->pid == 0) /* idle */
+		cur = NULL;
+
+	/*
+	 * "imp" is the fault differential for the source task between the
+	 * source and destination node. Calculate the total differential for
+	 * the source task and potential destination task. The more negative
+	 * the value is, the more rmeote accesses that would be expected to
+	 * be incurred if the tasks were swapped.
+	 */
+	if (cur) {
+		/* Skip this swap candidate if cannot move to the source cpu */
+		if (!cpumask_test_cpu(env->src_cpu, tsk_cpus_allowed(cur)))
+			goto unlock;
+
+		/*
+		 * If dst and source tasks are in the same NUMA group, or not
+		 * in any group then look only at task weights.
+		 */
+		if (cur->numa_group == env->p->numa_group) {
+			imp = taskimp + task_weight(cur, env->src_nid) -
+			      task_weight(cur, env->dst_nid);
+			/*
+			 * Add some hysteresis to prevent swapping the
+			 * tasks within a group over tiny differences.
+			 */
+			if (cur->numa_group)
+				imp -= imp/16;
+		} else {
+			/*
+			 * Compare the group weights. If a task is all by
+			 * itself (not part of a group), use the task weight
+			 * instead.
+			 */
+			if (env->p->numa_group)
+				imp = groupimp;
+			else
+				imp = taskimp;
+
+			if (cur->numa_group)
+				imp += group_weight(cur, env->src_nid) -
+				       group_weight(cur, env->dst_nid);
+			else
+				imp += task_weight(cur, env->src_nid) -
+				       task_weight(cur, env->dst_nid);
+		}
+	}
+
+	if (imp < env->best_imp)
+		goto unlock;
+
+	if (!cur) {
+		/* Is there capacity at our destination? */
+		if (env->src_stats.has_capacity &&
+		    !env->dst_stats.has_capacity)
+			goto unlock;
+
+		goto balance;
+	}
+
+	/* Balance doesn't matter much if we're running a task per cpu */
+	if (src_rq->nr_running == 1 && dst_rq->nr_running == 1)
+		goto assign;
+
+	/*
+	 * In the overloaded case, try and keep the load balanced.
+	 */
+balance:
+	dst_load = env->dst_stats.load;
+	src_load = env->src_stats.load;
+
+	/* XXX missing power terms */
+	load = task_h_load(env->p);
+	dst_load += load;
+	src_load -= load;
+
+	if (cur) {
+		load = task_h_load(cur);
+		dst_load -= load;
+		src_load += load;
+	}
+
+	/* make src_load the smaller */
+	if (dst_load < src_load)
+		swap(dst_load, src_load);
+
+	if (src_load * env->imbalance_pct < dst_load * 100)
+		goto unlock;
+
+assign:
+	task_numa_assign(env, cur, imp);
+unlock:
+	rcu_read_unlock();
+}
+
+static void task_numa_find_cpu(struct task_numa_env *env,
+				long taskimp, long groupimp)
+{
+	int cpu;
+
+	for_each_cpu(cpu, cpumask_of_node(env->dst_nid)) {
+		/* Skip this CPU if the source task cannot migrate */
+		if (!cpumask_test_cpu(cpu, tsk_cpus_allowed(env->p)))
+			continue;
+
+		env->dst_cpu = cpu;
+		task_numa_compare(env, taskimp, groupimp);
+	}
+}
+
+static int task_numa_migrate(struct task_struct *p)
+{
+	struct task_numa_env env = {
+		.p = p,
+
+		.src_cpu = task_cpu(p),
+		.src_nid = task_node(p),
+
+		.imbalance_pct = 112,
+
+		.best_task = NULL,
+		.best_imp = 0,
+		.best_cpu = -1
+	};
+	struct sched_domain *sd;
+	unsigned long taskweight, groupweight;
+	int nid, ret;
+	long taskimp, groupimp;
+
+	/*
+	 * Pick the lowest SD_NUMA domain, as that would have the smallest
+	 * imbalance and would be the first to start moving tasks about.
+	 *
+	 * And we want to avoid any moving of tasks about, as that would create
+	 * random movement of tasks -- counter the numa conditions we're trying
+	 * to satisfy here.
+	 */
+	rcu_read_lock();
+	sd = rcu_dereference(per_cpu(sd_numa, env.src_cpu));
+	env.imbalance_pct = 100 + (sd->imbalance_pct - 100) / 2;
+	rcu_read_unlock();
+
+	taskweight = task_weight(p, env.src_nid);
+	groupweight = group_weight(p, env.src_nid);
+	update_numa_stats(&env.src_stats, env.src_nid);
+	env.dst_nid = p->numa_preferred_nid;
+	taskimp = task_weight(p, env.dst_nid) - taskweight;
+	groupimp = group_weight(p, env.dst_nid) - groupweight;
+	update_numa_stats(&env.dst_stats, env.dst_nid);
+
+	/* If the preferred nid has capacity, try to use it. */
+	if (env.dst_stats.has_capacity)
+		task_numa_find_cpu(&env, taskimp, groupimp);
+
+	/* No space available on the preferred nid. Look elsewhere. */
+	if (env.best_cpu == -1) {
+		for_each_online_node(nid) {
+			if (nid == env.src_nid || nid == p->numa_preferred_nid)
+				continue;
+
+			/* Only consider nodes where both task and groups benefit */
+			taskimp = task_weight(p, nid) - taskweight;
+			groupimp = group_weight(p, nid) - groupweight;
+			if (taskimp < 0 && groupimp < 0)
+				continue;
+
+			env.dst_nid = nid;
+			update_numa_stats(&env.dst_stats, env.dst_nid);
+			task_numa_find_cpu(&env, taskimp, groupimp);
+		}
+	}
+
+	/* No better CPU than the current one was found. */
+	if (env.best_cpu == -1)
+		return -EAGAIN;
+
+	sched_setnuma(p, env.dst_nid);
+
+	/*
+	 * Reset the scan period if the task is being rescheduled on an
+	 * alternative node to recheck if the tasks is now properly placed.
+	 */
+	p->numa_scan_period = task_scan_min(p);
+
+	if (env.best_task == NULL) {
+		int ret = migrate_task_to(p, env.best_cpu);
+		return ret;
+	}
+
+	ret = migrate_swap(p, env.best_task);
+	put_task_struct(env.best_task);
+	return ret;
+}
+
+/* Attempt to migrate a task to a CPU on the preferred node. */
+static void numa_migrate_preferred(struct task_struct *p)
+{
+	/* This task has no NUMA fault statistics yet */
+	if (unlikely(p->numa_preferred_nid == -1 || !p->numa_faults))
+		return;
+
+	/* Periodically retry migrating the task to the preferred node */
+	p->numa_migrate_retry = jiffies + HZ;
+
+	/* Success if task is already running on preferred CPU */
+	if (cpu_to_node(task_cpu(p)) == p->numa_preferred_nid)
+		return;
+
+	/* Otherwise, try migrate to a CPU on the preferred node */
+	task_numa_migrate(p);
+}
+
+/*
+ * When adapting the scan rate, the period is divided into NUMA_PERIOD_SLOTS
+ * increments. The more local the fault statistics are, the higher the scan
+ * period will be for the next scan window. If local/remote ratio is below
+ * NUMA_PERIOD_THRESHOLD (where range of ratio is 1..NUMA_PERIOD_SLOTS) the
+ * scan period will decrease
+ */
+#define NUMA_PERIOD_SLOTS 10
+#define NUMA_PERIOD_THRESHOLD 3
+
+/*
+ * Increase the scan period (slow down scanning) if the majority of
+ * our memory is already on our local node, or if the majority of
+ * the page accesses are shared with other processes.
+ * Otherwise, decrease the scan period.
+ */
+static void update_task_scan_period(struct task_struct *p,
+			unsigned long shared, unsigned long private)
+{
+	unsigned int period_slot;
+	int ratio;
+	int diff;
+
+	unsigned long remote = p->numa_faults_locality[0];
+	unsigned long local = p->numa_faults_locality[1];
+
+	/*
+	 * If there were no record hinting faults then either the task is
+	 * completely idle or all activity is areas that are not of interest
+	 * to automatic numa balancing. Scan slower
+	 */
+	if (local + shared == 0) {
+		p->numa_scan_period = min(p->numa_scan_period_max,
+			p->numa_scan_period << 1);
+
+		p->mm->numa_next_scan = jiffies +
+			msecs_to_jiffies(p->numa_scan_period);
+
+		return;
+	}
+
+	/*
+	 * Prepare to scale scan period relative to the current period.
+	 *	 == NUMA_PERIOD_THRESHOLD scan period stays the same
+	 *       <  NUMA_PERIOD_THRESHOLD scan period decreases (scan faster)
+	 *	 >= NUMA_PERIOD_THRESHOLD scan period increases (scan slower)
+	 */
+	period_slot = DIV_ROUND_UP(p->numa_scan_period, NUMA_PERIOD_SLOTS);
+	ratio = (local * NUMA_PERIOD_SLOTS) / (local + remote);
+	if (ratio >= NUMA_PERIOD_THRESHOLD) {
+		int slot = ratio - NUMA_PERIOD_THRESHOLD;
+		if (!slot)
+			slot = 1;
+		diff = slot * period_slot;
+	} else {
+		diff = -(NUMA_PERIOD_THRESHOLD - ratio) * period_slot;
+
+		/*
+		 * Scale scan rate increases based on sharing. There is an
+		 * inverse relationship between the degree of sharing and
+		 * the adjustment made to the scanning period. Broadly
+		 * speaking the intent is that there is little point
+		 * scanning faster if shared accesses dominate as it may
+		 * simply bounce migrations uselessly
+		 */
+		period_slot = DIV_ROUND_UP(diff, NUMA_PERIOD_SLOTS);
+		ratio = DIV_ROUND_UP(private * NUMA_PERIOD_SLOTS, (private + shared));
+		diff = (diff * ratio) / NUMA_PERIOD_SLOTS;
+	}
+
+	p->numa_scan_period = clamp(p->numa_scan_period + diff,
+			task_scan_min(p), task_scan_max(p));
+	memset(p->numa_faults_locality, 0, sizeof(p->numa_faults_locality));
+}
+
 static void task_numa_placement(struct task_struct *p)
 {
-	int seq;
+	int seq, nid, max_nid = -1, max_group_nid = -1;
+	unsigned long max_faults = 0, max_group_faults = 0;
+	unsigned long fault_types[2] = { 0, 0 };
+	spinlock_t *group_lock = NULL;
 
-	if (!p->mm)	/* for example, ksmd faulting in a user's mm */
-		return;
 	seq = ACCESS_ONCE(p->mm->numa_scan_seq);
 	if (p->numa_scan_seq == seq)
 		return;
 	p->numa_scan_seq = seq;
+	p->numa_scan_period_max = task_scan_max(p);
 
-	/* FIXME: Scheduling placement policy hints go here */
+	/* If the task is part of a group prevent parallel updates to group stats */
+	if (p->numa_group) {
+		group_lock = &p->numa_group->lock;
+		spin_lock(group_lock);
+	}
+
+	/* Find the node with the highest number of faults */
+	for_each_online_node(nid) {
+		unsigned long faults = 0, group_faults = 0;
+		int priv, i;
+
+		for (priv = 0; priv < 2; priv++) {
+			long diff;
+
+			i = task_faults_idx(nid, priv);
+			diff = -p->numa_faults[i];
+
+			/* Decay existing window, copy faults since last scan */
+			p->numa_faults[i] >>= 1;
+			p->numa_faults[i] += p->numa_faults_buffer[i];
+			fault_types[priv] += p->numa_faults_buffer[i];
+			p->numa_faults_buffer[i] = 0;
+
+			faults += p->numa_faults[i];
+			diff += p->numa_faults[i];
+			p->total_numa_faults += diff;
+			if (p->numa_group) {
+				/* safe because we can only change our own group */
+				p->numa_group->faults[i] += diff;
+				p->numa_group->total_faults += diff;
+				group_faults += p->numa_group->faults[i];
+			}
+		}
+
+		if (faults > max_faults) {
+			max_faults = faults;
+			max_nid = nid;
+		}
+
+		if (group_faults > max_group_faults) {
+			max_group_faults = group_faults;
+			max_group_nid = nid;
+		}
+	}
+
+	update_task_scan_period(p, fault_types[0], fault_types[1]);
+
+	if (p->numa_group) {
+		/*
+		 * If the preferred task and group nids are different,
+		 * iterate over the nodes again to find the best place.
+		 */
+		if (max_nid != max_group_nid) {
+			unsigned long weight, max_weight = 0;
+
+			for_each_online_node(nid) {
+				weight = task_weight(p, nid) + group_weight(p, nid);
+				if (weight > max_weight) {
+					max_weight = weight;
+					max_nid = nid;
+				}
+			}
+		}
+
+		spin_unlock(group_lock);
+	}
+
+	/* Preferred node as the node with the most faults */
+	if (max_faults && max_nid != p->numa_preferred_nid) {
+		/* Update the preferred nid and migrate task if possible */
+		sched_setnuma(p, max_nid);
+		numa_migrate_preferred(p);
+	}
+}
+
+static inline int get_numa_group(struct numa_group *grp)
+{
+	return atomic_inc_not_zero(&grp->refcount);
+}
+
+static inline void put_numa_group(struct numa_group *grp)
+{
+	if (atomic_dec_and_test(&grp->refcount))
+		kfree_rcu(grp, rcu);
+}
+
+static void task_numa_group(struct task_struct *p, int cpupid, int flags,
+			int *priv)
+{
+	struct numa_group *grp, *my_grp;
+	struct task_struct *tsk;
+	bool join = false;
+	int cpu = cpupid_to_cpu(cpupid);
+	int i;
+
+	if (unlikely(!p->numa_group)) {
+		unsigned int size = sizeof(struct numa_group) +
+				    2*nr_node_ids*sizeof(unsigned long);
+
+		grp = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
+		if (!grp)
+			return;
+
+		atomic_set(&grp->refcount, 1);
+		spin_lock_init(&grp->lock);
+		INIT_LIST_HEAD(&grp->task_list);
+		grp->gid = p->pid;
+
+		for (i = 0; i < 2*nr_node_ids; i++)
+			grp->faults[i] = p->numa_faults[i];
+
+		grp->total_faults = p->total_numa_faults;
+
+		list_add(&p->numa_entry, &grp->task_list);
+		grp->nr_tasks++;
+		rcu_assign_pointer(p->numa_group, grp);
+	}
+
+	rcu_read_lock();
+	tsk = ACCESS_ONCE(cpu_rq(cpu)->curr);
+
+	if (!cpupid_match_pid(tsk, cpupid))
+		goto no_join;
+
+	grp = rcu_dereference(tsk->numa_group);
+	if (!grp)
+		goto no_join;
+
+	my_grp = p->numa_group;
+	if (grp == my_grp)
+		goto no_join;
+
+	/*
+	 * Only join the other group if its bigger; if we're the bigger group,
+	 * the other task will join us.
+	 */
+	if (my_grp->nr_tasks > grp->nr_tasks)
+		goto no_join;
+
+	/*
+	 * Tie-break on the grp address.
+	 */
+	if (my_grp->nr_tasks == grp->nr_tasks && my_grp > grp)
+		goto no_join;
+
+	/* Always join threads in the same process. */
+	if (tsk->mm == current->mm)
+		join = true;
+
+	/* Simple filter to avoid false positives due to PID collisions */
+	if (flags & TNF_SHARED)
+		join = true;
+
+	/* Update priv based on whether false sharing was detected */
+	*priv = !join;
+
+	if (join && !get_numa_group(grp))
+		goto no_join;
+
+	rcu_read_unlock();
+
+	if (!join)
+		return;
+
+	double_lock(&my_grp->lock, &grp->lock);
+
+	for (i = 0; i < 2*nr_node_ids; i++) {
+		my_grp->faults[i] -= p->numa_faults[i];
+		grp->faults[i] += p->numa_faults[i];
+	}
+	my_grp->total_faults -= p->total_numa_faults;
+	grp->total_faults += p->total_numa_faults;
+
+	list_move(&p->numa_entry, &grp->task_list);
+	my_grp->nr_tasks--;
+	grp->nr_tasks++;
+
+	spin_unlock(&my_grp->lock);
+	spin_unlock(&grp->lock);
+
+	rcu_assign_pointer(p->numa_group, grp);
+
+	put_numa_group(my_grp);
+	return;
+
+no_join:
+	rcu_read_unlock();
+	return;
+}
+
+void task_numa_free(struct task_struct *p)
+{
+	struct numa_group *grp = p->numa_group;
+	int i;
+	void *numa_faults = p->numa_faults;
+
+	if (grp) {
+		spin_lock(&grp->lock);
+		for (i = 0; i < 2*nr_node_ids; i++)
+			grp->faults[i] -= p->numa_faults[i];
+		grp->total_faults -= p->total_numa_faults;
+
+		list_del(&p->numa_entry);
+		grp->nr_tasks--;
+		spin_unlock(&grp->lock);
+		rcu_assign_pointer(p->numa_group, NULL);
+		put_numa_group(grp);
+	}
+
+	p->numa_faults = NULL;
+	p->numa_faults_buffer = NULL;
+	kfree(numa_faults);
 }
 
 /*
  * Got a PROT_NONE fault for a page on @node.
  */
-void task_numa_fault(int node, int pages, bool migrated)
+void task_numa_fault(int last_cpupid, int node, int pages, int flags)
 {
 	struct task_struct *p = current;
+	bool migrated = flags & TNF_MIGRATED;
+	int priv;
 
 	if (!numabalancing_enabled)
 		return;
 
-	/* FIXME: Allocate task-specific structure for placement policy here */
+	/* for example, ksmd faulting in a user's mm */
+	if (!p->mm)
+		return;
+
+	/* Do not worry about placement if exiting */
+	if (p->state == TASK_DEAD)
+		return;
+
+	/* Allocate buffer to track faults on a per-node basis */
+	if (unlikely(!p->numa_faults)) {
+		int size = sizeof(*p->numa_faults) * 2 * nr_node_ids;
+
+		/* numa_faults and numa_faults_buffer share the allocation */
+		p->numa_faults = kzalloc(size * 2, GFP_KERNEL|__GFP_NOWARN);
+		if (!p->numa_faults)
+			return;
+
+		BUG_ON(p->numa_faults_buffer);
+		p->numa_faults_buffer = p->numa_faults + (2 * nr_node_ids);
+		p->total_numa_faults = 0;
+		memset(p->numa_faults_locality, 0, sizeof(p->numa_faults_locality));
+	}
 
 	/*
-	 * If pages are properly placed (did not migrate) then scan slower.
-	 * This is reset periodically in case of phase changes
+	 * First accesses are treated as private, otherwise consider accesses
+	 * to be private if the accessing pid has not changed
 	 */
-        if (!migrated)
-		p->numa_scan_period = min(sysctl_numa_balancing_scan_period_max,
-			p->numa_scan_period + jiffies_to_msecs(10));
+	if (unlikely(last_cpupid == (-1 & LAST_CPUPID_MASK))) {
+		priv = 1;
+	} else {
+		priv = cpupid_match_pid(p, last_cpupid);
+		if (!priv && !(flags & TNF_NO_GROUP))
+			task_numa_group(p, last_cpupid, flags, &priv);
+	}
 
 	task_numa_placement(p);
+
+	/*
+	 * Retry task to preferred node migration periodically, in case it
+	 * case it previously failed, or the scheduler moved us.
+	 */
+	if (time_after(jiffies, p->numa_migrate_retry))
+		numa_migrate_preferred(p);
+
+	if (migrated)
+		p->numa_pages_migrated += pages;
+
+	p->numa_faults_buffer[task_faults_idx(node, priv)] += pages;
+	p->numa_faults_locality[!!(flags & TNF_FAULT_LOCAL)] += pages;
 }
 
 static void reset_ptenuma_scan(struct task_struct *p)
@@ -884,6 +1656,7 @@
 	struct mm_struct *mm = p->mm;
 	struct vm_area_struct *vma;
 	unsigned long start, end;
+	unsigned long nr_pte_updates = 0;
 	long pages;
 
 	WARN_ON_ONCE(p != container_of(work, struct task_struct, numa_work));
@@ -900,35 +1673,9 @@
 	if (p->flags & PF_EXITING)
 		return;
 
-	/*
-	 * We do not care about task placement until a task runs on a node
-	 * other than the first one used by the address space. This is
-	 * largely because migrations are driven by what CPU the task
-	 * is running on. If it's never scheduled on another node, it'll
-	 * not migrate so why bother trapping the fault.
-	 */
-	if (mm->first_nid == NUMA_PTE_SCAN_INIT)
-		mm->first_nid = numa_node_id();
-	if (mm->first_nid != NUMA_PTE_SCAN_ACTIVE) {
-		/* Are we running on a new node yet? */
-		if (numa_node_id() == mm->first_nid &&
-		    !sched_feat_numa(NUMA_FORCE))
-			return;
-
-		mm->first_nid = NUMA_PTE_SCAN_ACTIVE;
-	}
-
-	/*
-	 * Reset the scan period if enough time has gone by. Objective is that
-	 * scanning will be reduced if pages are properly placed. As tasks
-	 * can enter different phases this needs to be re-examined. Lacking
-	 * proper tracking of reference behaviour, this blunt hammer is used.
-	 */
-	migrate = mm->numa_next_reset;
-	if (time_after(now, migrate)) {
-		p->numa_scan_period = sysctl_numa_balancing_scan_period_min;
-		next_scan = now + msecs_to_jiffies(sysctl_numa_balancing_scan_period_reset);
-		xchg(&mm->numa_next_reset, next_scan);
+	if (!mm->numa_next_scan) {
+		mm->numa_next_scan = now +
+			msecs_to_jiffies(sysctl_numa_balancing_scan_delay);
 	}
 
 	/*
@@ -938,20 +1685,20 @@
 	if (time_before(now, migrate))
 		return;
 
-	if (p->numa_scan_period == 0)
-		p->numa_scan_period = sysctl_numa_balancing_scan_period_min;
+	if (p->numa_scan_period == 0) {
+		p->numa_scan_period_max = task_scan_max(p);
+		p->numa_scan_period = task_scan_min(p);
+	}
 
 	next_scan = now + msecs_to_jiffies(p->numa_scan_period);
 	if (cmpxchg(&mm->numa_next_scan, migrate, next_scan) != migrate)
 		return;
 
 	/*
-	 * Do not set pte_numa if the current running node is rate-limited.
-	 * This loses statistics on the fault but if we are unwilling to
-	 * migrate to this node, it is less likely we can do useful work
+	 * Delay this task enough that another task of this mm will likely win
+	 * the next time around.
 	 */
-	if (migrate_ratelimited(numa_node_id()))
-		return;
+	p->node_stamp += 2 * TICK_NSEC;
 
 	start = mm->numa_scan_offset;
 	pages = sysctl_numa_balancing_scan_size;
@@ -967,18 +1714,32 @@
 		vma = mm->mmap;
 	}
 	for (; vma; vma = vma->vm_next) {
-		if (!vma_migratable(vma))
+		if (!vma_migratable(vma) || !vma_policy_mof(p, vma))
 			continue;
 
-		/* Skip small VMAs. They are not likely to be of relevance */
-		if (vma->vm_end - vma->vm_start < HPAGE_SIZE)
+		/*
+		 * Shared library pages mapped by multiple processes are not
+		 * migrated as it is expected they are cache replicated. Avoid
+		 * hinting faults in read-only file-backed mappings or the vdso
+		 * as migrating the pages will be of marginal benefit.
+		 */
+		if (!vma->vm_mm ||
+		    (vma->vm_file && (vma->vm_flags & (VM_READ|VM_WRITE)) == (VM_READ)))
 			continue;
 
 		do {
 			start = max(start, vma->vm_start);
 			end = ALIGN(start + (pages << PAGE_SHIFT), HPAGE_SIZE);
 			end = min(end, vma->vm_end);
-			pages -= change_prot_numa(vma, start, end);
+			nr_pte_updates += change_prot_numa(vma, start, end);
+
+			/*
+			 * Scan sysctl_numa_balancing_scan_size but ensure that
+			 * at least one PTE is updated so that unused virtual
+			 * address space is quickly skipped.
+			 */
+			if (nr_pte_updates)
+				pages -= (end - start) >> PAGE_SHIFT;
 
 			start = end;
 			if (pages <= 0)
@@ -988,10 +1749,10 @@
 
 out:
 	/*
-	 * It is possible to reach the end of the VMA list but the last few VMAs are
-	 * not guaranteed to the vma_migratable. If they are not, we would find the
-	 * !migratable VMA on the next scan but not reset the scanner to the start
-	 * so check it now.
+	 * It is possible to reach the end of the VMA list but the last few
+	 * VMAs are not guaranteed to the vma_migratable. If they are not, we
+	 * would find the !migratable VMA on the next scan but not reset the
+	 * scanner to the start so check it now.
 	 */
 	if (vma)
 		mm->numa_scan_offset = start;
@@ -1025,8 +1786,8 @@
 
 	if (now - curr->node_stamp > period) {
 		if (!curr->node_stamp)
-			curr->numa_scan_period = sysctl_numa_balancing_scan_period_min;
-		curr->node_stamp = now;
+			curr->numa_scan_period = task_scan_min(curr);
+		curr->node_stamp += period;
 
 		if (!time_before(jiffies, curr->mm->numa_next_scan)) {
 			init_task_work(work, task_numa_work); /* TODO: move this into sched_fork() */
@@ -1038,6 +1799,14 @@
 static void task_tick_numa(struct rq *rq, struct task_struct *curr)
 {
 }
+
+static inline void account_numa_enqueue(struct rq *rq, struct task_struct *p)
+{
+}
+
+static inline void account_numa_dequeue(struct rq *rq, struct task_struct *p)
+{
+}
 #endif /* CONFIG_NUMA_BALANCING */
 
 static void
@@ -1047,8 +1816,12 @@
 	if (!parent_entity(se))
 		update_load_add(&rq_of(cfs_rq)->load, se->load.weight);
 #ifdef CONFIG_SMP
-	if (entity_is_task(se))
-		list_add(&se->group_node, &rq_of(cfs_rq)->cfs_tasks);
+	if (entity_is_task(se)) {
+		struct rq *rq = rq_of(cfs_rq);
+
+		account_numa_enqueue(rq, task_of(se));
+		list_add(&se->group_node, &rq->cfs_tasks);
+	}
 #endif
 	cfs_rq->nr_running++;
 }
@@ -1059,8 +1832,10 @@
 	update_load_sub(&cfs_rq->load, se->load.weight);
 	if (!parent_entity(se))
 		update_load_sub(&rq_of(cfs_rq)->load, se->load.weight);
-	if (entity_is_task(se))
+	if (entity_is_task(se)) {
+		account_numa_dequeue(rq_of(cfs_rq), task_of(se));
 		list_del_init(&se->group_node);
+	}
 	cfs_rq->nr_running--;
 }
 
@@ -2070,13 +2845,14 @@
 	return static_key_false(&__cfs_bandwidth_used);
 }
 
-void account_cfs_bandwidth_used(int enabled, int was_enabled)
+void cfs_bandwidth_usage_inc(void)
 {
-	/* only need to count groups transitioning between enabled/!enabled */
-	if (enabled && !was_enabled)
-		static_key_slow_inc(&__cfs_bandwidth_used);
-	else if (!enabled && was_enabled)
-		static_key_slow_dec(&__cfs_bandwidth_used);
+	static_key_slow_inc(&__cfs_bandwidth_used);
+}
+
+void cfs_bandwidth_usage_dec(void)
+{
+	static_key_slow_dec(&__cfs_bandwidth_used);
 }
 #else /* HAVE_JUMP_LABEL */
 static bool cfs_bandwidth_used(void)
@@ -2084,7 +2860,8 @@
 	return true;
 }
 
-void account_cfs_bandwidth_used(int enabled, int was_enabled) {}
+void cfs_bandwidth_usage_inc(void) {}
+void cfs_bandwidth_usage_dec(void) {}
 #endif /* HAVE_JUMP_LABEL */
 
 /*
@@ -2335,6 +3112,8 @@
 	cfs_rq->throttled_clock = rq_clock(rq);
 	raw_spin_lock(&cfs_b->lock);
 	list_add_tail_rcu(&cfs_rq->throttled_list, &cfs_b->throttled_cfs_rq);
+	if (!cfs_b->timer_active)
+		__start_cfs_bandwidth(cfs_b);
 	raw_spin_unlock(&cfs_b->lock);
 }
 
@@ -2448,6 +3227,13 @@
 	if (idle)
 		goto out_unlock;
 
+	/*
+	 * if we have relooped after returning idle once, we need to update our
+	 * status as actually running, so that other cpus doing
+	 * __start_cfs_bandwidth will stop trying to cancel us.
+	 */
+	cfs_b->timer_active = 1;
+
 	__refill_cfs_bandwidth_runtime(cfs_b);
 
 	if (!throttled) {
@@ -2508,7 +3294,13 @@
 /* how long we wait to gather additional slack before distributing */
 static const u64 cfs_bandwidth_slack_period = 5 * NSEC_PER_MSEC;
 
-/* are we near the end of the current quota period? */
+/*
+ * Are we near the end of the current quota period?
+ *
+ * Requires cfs_b->lock for hrtimer_expires_remaining to be safe against the
+ * hrtimer base being cleared by __hrtimer_start_range_ns. In the case of
+ * migrate_hrtimers, base is never cleared, so we are fine.
+ */
 static int runtime_refresh_within(struct cfs_bandwidth *cfs_b, u64 min_expire)
 {
 	struct hrtimer *refresh_timer = &cfs_b->period_timer;
@@ -2584,10 +3376,12 @@
 	u64 expires;
 
 	/* confirm we're still not at a refresh boundary */
-	if (runtime_refresh_within(cfs_b, min_bandwidth_expiration))
-		return;
-
 	raw_spin_lock(&cfs_b->lock);
+	if (runtime_refresh_within(cfs_b, min_bandwidth_expiration)) {
+		raw_spin_unlock(&cfs_b->lock);
+		return;
+	}
+
 	if (cfs_b->quota != RUNTIME_INF && cfs_b->runtime > slice) {
 		runtime = cfs_b->runtime;
 		cfs_b->runtime = 0;
@@ -2708,11 +3502,11 @@
 	 * (timer_active==0 becomes visible before the hrtimer call-back
 	 * terminates).  In either case we ensure that it's re-programmed
 	 */
-	while (unlikely(hrtimer_active(&cfs_b->period_timer))) {
+	while (unlikely(hrtimer_active(&cfs_b->period_timer)) &&
+	       hrtimer_try_to_cancel(&cfs_b->period_timer) < 0) {
+		/* bounce the lock to allow do_sched_cfs_period_timer to run */
 		raw_spin_unlock(&cfs_b->lock);
-		/* ensure cfs_b->lock is available while we wait */
-		hrtimer_cancel(&cfs_b->period_timer);
-
+		cpu_relax();
 		raw_spin_lock(&cfs_b->lock);
 		/* if someone else restarted the timer then we're done */
 		if (cfs_b->timer_active)
@@ -3113,7 +3907,7 @@
 {
 	struct sched_entity *se = tg->se[cpu];
 
-	if (!tg->parent)	/* the trivial, non-cgroup case */
+	if (!tg->parent || !wl)	/* the trivial, non-cgroup case */
 		return wl;
 
 	for_each_sched_entity(se) {
@@ -3166,8 +3960,7 @@
 }
 #else
 
-static inline unsigned long effective_load(struct task_group *tg, int cpu,
-		unsigned long wl, unsigned long wg)
+static long effective_load(struct task_group *tg, int cpu, long wl, long wg)
 {
 	return wl;
 }
@@ -3420,11 +4213,10 @@
  * preempt must be disabled.
  */
 static int
-select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flags)
+select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_flags)
 {
 	struct sched_domain *tmp, *affine_sd = NULL, *sd = NULL;
 	int cpu = smp_processor_id();
-	int prev_cpu = task_cpu(p);
 	int new_cpu = cpu;
 	int want_affine = 0;
 	int sync = wake_flags & WF_SYNC;
@@ -3904,9 +4696,12 @@
 
 static unsigned long __read_mostly max_load_balance_interval = HZ/10;
 
+enum fbq_type { regular, remote, all };
+
 #define LBF_ALL_PINNED	0x01
 #define LBF_NEED_BREAK	0x02
-#define LBF_SOME_PINNED 0x04
+#define LBF_DST_PINNED  0x04
+#define LBF_SOME_PINNED	0x08
 
 struct lb_env {
 	struct sched_domain	*sd;
@@ -3929,6 +4724,8 @@
 	unsigned int		loop;
 	unsigned int		loop_break;
 	unsigned int		loop_max;
+
+	enum fbq_type		fbq_type;
 };
 
 /*
@@ -3975,6 +4772,78 @@
 	return delta < (s64)sysctl_sched_migration_cost;
 }
 
+#ifdef CONFIG_NUMA_BALANCING
+/* Returns true if the destination node has incurred more faults */
+static bool migrate_improves_locality(struct task_struct *p, struct lb_env *env)
+{
+	int src_nid, dst_nid;
+
+	if (!sched_feat(NUMA_FAVOUR_HIGHER) || !p->numa_faults ||
+	    !(env->sd->flags & SD_NUMA)) {
+		return false;
+	}
+
+	src_nid = cpu_to_node(env->src_cpu);
+	dst_nid = cpu_to_node(env->dst_cpu);
+
+	if (src_nid == dst_nid)
+		return false;
+
+	/* Always encourage migration to the preferred node. */
+	if (dst_nid == p->numa_preferred_nid)
+		return true;
+
+	/* If both task and group weight improve, this move is a winner. */
+	if (task_weight(p, dst_nid) > task_weight(p, src_nid) &&
+	    group_weight(p, dst_nid) > group_weight(p, src_nid))
+		return true;
+
+	return false;
+}
+
+
+static bool migrate_degrades_locality(struct task_struct *p, struct lb_env *env)
+{
+	int src_nid, dst_nid;
+
+	if (!sched_feat(NUMA) || !sched_feat(NUMA_RESIST_LOWER))
+		return false;
+
+	if (!p->numa_faults || !(env->sd->flags & SD_NUMA))
+		return false;
+
+	src_nid = cpu_to_node(env->src_cpu);
+	dst_nid = cpu_to_node(env->dst_cpu);
+
+	if (src_nid == dst_nid)
+		return false;
+
+	/* Migrating away from the preferred node is always bad. */
+	if (src_nid == p->numa_preferred_nid)
+		return true;
+
+	/* If either task or group weight get worse, don't do it. */
+	if (task_weight(p, dst_nid) < task_weight(p, src_nid) ||
+	    group_weight(p, dst_nid) < group_weight(p, src_nid))
+		return true;
+
+	return false;
+}
+
+#else
+static inline bool migrate_improves_locality(struct task_struct *p,
+					     struct lb_env *env)
+{
+	return false;
+}
+
+static inline bool migrate_degrades_locality(struct task_struct *p,
+					     struct lb_env *env)
+{
+	return false;
+}
+#endif
+
 /*
  * can_migrate_task - may task p from runqueue rq be migrated to this_cpu?
  */
@@ -3997,6 +4866,8 @@
 
 		schedstat_inc(p, se.statistics.nr_failed_migrations_affine);
 
+		env->flags |= LBF_SOME_PINNED;
+
 		/*
 		 * Remember if this task can be migrated to any other cpu in
 		 * our sched_group. We may want to revisit it if we couldn't
@@ -4005,13 +4876,13 @@
 		 * Also avoid computing new_dst_cpu if we have already computed
 		 * one in current iteration.
 		 */
-		if (!env->dst_grpmask || (env->flags & LBF_SOME_PINNED))
+		if (!env->dst_grpmask || (env->flags & LBF_DST_PINNED))
 			return 0;
 
 		/* Prevent to re-select dst_cpu via env's cpus */
 		for_each_cpu_and(cpu, env->dst_grpmask, env->cpus) {
 			if (cpumask_test_cpu(cpu, tsk_cpus_allowed(p))) {
-				env->flags |= LBF_SOME_PINNED;
+				env->flags |= LBF_DST_PINNED;
 				env->new_dst_cpu = cpu;
 				break;
 			}
@@ -4030,11 +4901,24 @@
 
 	/*
 	 * Aggressive migration if:
-	 * 1) task is cache cold, or
-	 * 2) too many balance attempts have failed.
+	 * 1) destination numa is preferred
+	 * 2) task is cache cold, or
+	 * 3) too many balance attempts have failed.
 	 */
-
 	tsk_cache_hot = task_hot(p, rq_clock_task(env->src_rq), env->sd);
+	if (!tsk_cache_hot)
+		tsk_cache_hot = migrate_degrades_locality(p, env);
+
+	if (migrate_improves_locality(p, env)) {
+#ifdef CONFIG_SCHEDSTATS
+		if (tsk_cache_hot) {
+			schedstat_inc(env->sd, lb_hot_gained[env->idle]);
+			schedstat_inc(p, se.statistics.nr_forced_migrations);
+		}
+#endif
+		return 1;
+	}
+
 	if (!tsk_cache_hot ||
 		env->sd->nr_balance_failed > env->sd->cache_nice_tries) {
 
@@ -4077,8 +4961,6 @@
 	return 0;
 }
 
-static unsigned long task_h_load(struct task_struct *p);
-
 static const unsigned int sched_nr_migrate_break = 32;
 
 /*
@@ -4291,6 +5173,10 @@
 	unsigned int group_weight;
 	int group_imb; /* Is there an imbalance in the group ? */
 	int group_has_capacity; /* Is there extra capacity in the group? */
+#ifdef CONFIG_NUMA_BALANCING
+	unsigned int nr_numa_running;
+	unsigned int nr_preferred_running;
+#endif
 };
 
 /*
@@ -4330,7 +5216,7 @@
 /**
  * get_sd_load_idx - Obtain the load index for a given sched domain.
  * @sd: The sched_domain whose load_idx is to be obtained.
- * @idle: The Idle status of the CPU for whose sd load_icx is obtained.
+ * @idle: The idle status of the CPU for whose sd load_idx is obtained.
  *
  * Return: The load index.
  */
@@ -4447,7 +5333,7 @@
 {
 	struct sched_domain *child = sd->child;
 	struct sched_group *group, *sdg = sd->groups;
-	unsigned long power;
+	unsigned long power, power_orig;
 	unsigned long interval;
 
 	interval = msecs_to_jiffies(sd->balance_interval);
@@ -4459,7 +5345,7 @@
 		return;
 	}
 
-	power = 0;
+	power_orig = power = 0;
 
 	if (child->flags & SD_OVERLAP) {
 		/*
@@ -4467,8 +5353,12 @@
 		 * span the current group.
 		 */
 
-		for_each_cpu(cpu, sched_group_cpus(sdg))
-			power += power_of(cpu);
+		for_each_cpu(cpu, sched_group_cpus(sdg)) {
+			struct sched_group *sg = cpu_rq(cpu)->sd->groups;
+
+			power_orig += sg->sgp->power_orig;
+			power += sg->sgp->power;
+		}
 	} else  {
 		/*
 		 * !SD_OVERLAP domains can assume that child groups
@@ -4477,12 +5367,14 @@
 
 		group = child->groups;
 		do {
+			power_orig += group->sgp->power_orig;
 			power += group->sgp->power;
 			group = group->next;
 		} while (group != child->groups);
 	}
 
-	sdg->sgp->power_orig = sdg->sgp->power = power;
+	sdg->sgp->power_orig = power_orig;
+	sdg->sgp->power = power;
 }
 
 /*
@@ -4526,13 +5418,12 @@
  * cpu 3 and leave one of the cpus in the second group unused.
  *
  * The current solution to this issue is detecting the skew in the first group
- * by noticing it has a cpu that is overloaded while the remaining cpus are
- * idle -- or rather, there's a distinct imbalance in the cpus; see
- * sg_imbalanced().
+ * by noticing the lower domain failed to reach balance and had difficulty
+ * moving tasks due to affinity constraints.
  *
  * When this is so detected; this group becomes a candidate for busiest; see
- * update_sd_pick_busiest(). And calculcate_imbalance() and
- * find_busiest_group() avoid some of the usual balance conditional to allow it
+ * update_sd_pick_busiest(). And calculate_imbalance() and
+ * find_busiest_group() avoid some of the usual balance conditions to allow it
  * to create an effective group imbalance.
  *
  * This is a somewhat tricky proposition since the next run might not find the
@@ -4540,49 +5431,36 @@
  * subtle and fragile situation.
  */
 
-struct sg_imb_stats {
-	unsigned long max_nr_running, min_nr_running;
-	unsigned long max_cpu_load, min_cpu_load;
-};
-
-static inline void init_sg_imb_stats(struct sg_imb_stats *sgi)
+static inline int sg_imbalanced(struct sched_group *group)
 {
-	sgi->max_cpu_load = sgi->max_nr_running = 0UL;
-	sgi->min_cpu_load = sgi->min_nr_running = ~0UL;
+	return group->sgp->imbalance;
 }
 
-static inline void
-update_sg_imb_stats(struct sg_imb_stats *sgi,
-		    unsigned long load, unsigned long nr_running)
+/*
+ * Compute the group capacity.
+ *
+ * Avoid the issue where N*frac(smt_power) >= 1 creates 'phantom' cores by
+ * first dividing out the smt factor and computing the actual number of cores
+ * and limit power unit capacity with that.
+ */
+static inline int sg_capacity(struct lb_env *env, struct sched_group *group)
 {
-	if (load > sgi->max_cpu_load)
-		sgi->max_cpu_load = load;
-	if (sgi->min_cpu_load > load)
-		sgi->min_cpu_load = load;
+	unsigned int capacity, smt, cpus;
+	unsigned int power, power_orig;
 
-	if (nr_running > sgi->max_nr_running)
-		sgi->max_nr_running = nr_running;
-	if (sgi->min_nr_running > nr_running)
-		sgi->min_nr_running = nr_running;
-}
+	power = group->sgp->power;
+	power_orig = group->sgp->power_orig;
+	cpus = group->group_weight;
 
-static inline int
-sg_imbalanced(struct sg_lb_stats *sgs, struct sg_imb_stats *sgi)
-{
-	/*
-	 * Consider the group unbalanced when the imbalance is larger
-	 * than the average weight of a task.
-	 *
-	 * APZ: with cgroup the avg task weight can vary wildly and
-	 *      might not be a suitable number - should we keep a
-	 *      normalized nr_running number somewhere that negates
-	 *      the hierarchy?
-	 */
-	if ((sgi->max_cpu_load - sgi->min_cpu_load) >= sgs->load_per_task &&
-	    (sgi->max_nr_running - sgi->min_nr_running) > 1)
-		return 1;
+	/* smt := ceil(cpus / power), assumes: 1 < smt_power < 2 */
+	smt = DIV_ROUND_UP(SCHED_POWER_SCALE * cpus, power_orig);
+	capacity = cpus / smt; /* cores */
 
-	return 0;
+	capacity = min_t(unsigned, capacity, DIV_ROUND_CLOSEST(power, SCHED_POWER_SCALE));
+	if (!capacity)
+		capacity = fix_small_capacity(env->sd, group);
+
+	return capacity;
 }
 
 /**
@@ -4597,12 +5475,11 @@
 			struct sched_group *group, int load_idx,
 			int local_group, struct sg_lb_stats *sgs)
 {
-	struct sg_imb_stats sgi;
 	unsigned long nr_running;
 	unsigned long load;
 	int i;
 
-	init_sg_imb_stats(&sgi);
+	memset(sgs, 0, sizeof(*sgs));
 
 	for_each_cpu_and(i, sched_group_cpus(group), env->cpus) {
 		struct rq *rq = cpu_rq(i);
@@ -4610,24 +5487,22 @@
 		nr_running = rq->nr_running;
 
 		/* Bias balancing toward cpus of our domain */
-		if (local_group) {
+		if (local_group)
 			load = target_load(i, load_idx);
-		} else {
+		else
 			load = source_load(i, load_idx);
-			update_sg_imb_stats(&sgi, load, nr_running);
-		}
 
 		sgs->group_load += load;
 		sgs->sum_nr_running += nr_running;
+#ifdef CONFIG_NUMA_BALANCING
+		sgs->nr_numa_running += rq->nr_numa_running;
+		sgs->nr_preferred_running += rq->nr_preferred_running;
+#endif
 		sgs->sum_weighted_load += weighted_cpuload(i);
 		if (idle_cpu(i))
 			sgs->idle_cpus++;
 	}
 
-	if (local_group && (env->idle != CPU_NEWLY_IDLE ||
-			time_after_eq(jiffies, group->sgp->next_update)))
-		update_group_power(env->sd, env->dst_cpu);
-
 	/* Adjust by relative CPU power of the group */
 	sgs->group_power = group->sgp->power;
 	sgs->avg_load = (sgs->group_load*SCHED_POWER_SCALE) / sgs->group_power;
@@ -4635,16 +5510,11 @@
 	if (sgs->sum_nr_running)
 		sgs->load_per_task = sgs->sum_weighted_load / sgs->sum_nr_running;
 
-	sgs->group_imb = sg_imbalanced(sgs, &sgi);
-
-	sgs->group_capacity =
-		DIV_ROUND_CLOSEST(sgs->group_power, SCHED_POWER_SCALE);
-
-	if (!sgs->group_capacity)
-		sgs->group_capacity = fix_small_capacity(env->sd, group);
-
 	sgs->group_weight = group->group_weight;
 
+	sgs->group_imb = sg_imbalanced(group);
+	sgs->group_capacity = sg_capacity(env, group);
+
 	if (sgs->group_capacity > sgs->sum_nr_running)
 		sgs->group_has_capacity = 1;
 }
@@ -4693,14 +5563,42 @@
 	return false;
 }
 
+#ifdef CONFIG_NUMA_BALANCING
+static inline enum fbq_type fbq_classify_group(struct sg_lb_stats *sgs)
+{
+	if (sgs->sum_nr_running > sgs->nr_numa_running)
+		return regular;
+	if (sgs->sum_nr_running > sgs->nr_preferred_running)
+		return remote;
+	return all;
+}
+
+static inline enum fbq_type fbq_classify_rq(struct rq *rq)
+{
+	if (rq->nr_running > rq->nr_numa_running)
+		return regular;
+	if (rq->nr_running > rq->nr_preferred_running)
+		return remote;
+	return all;
+}
+#else
+static inline enum fbq_type fbq_classify_group(struct sg_lb_stats *sgs)
+{
+	return all;
+}
+
+static inline enum fbq_type fbq_classify_rq(struct rq *rq)
+{
+	return regular;
+}
+#endif /* CONFIG_NUMA_BALANCING */
+
 /**
  * update_sd_lb_stats - Update sched_domain's statistics for load balancing.
  * @env: The load balancing environment.
- * @balance: Should we balance.
  * @sds: variable to hold the statistics for this sched_domain.
  */
-static inline void update_sd_lb_stats(struct lb_env *env,
-					struct sd_lb_stats *sds)
+static inline void update_sd_lb_stats(struct lb_env *env, struct sd_lb_stats *sds)
 {
 	struct sched_domain *child = env->sd->child;
 	struct sched_group *sg = env->sd->groups;
@@ -4720,11 +5618,17 @@
 		if (local_group) {
 			sds->local = sg;
 			sgs = &sds->local_stat;
+
+			if (env->idle != CPU_NEWLY_IDLE ||
+			    time_after_eq(jiffies, sg->sgp->next_update))
+				update_group_power(env->sd, env->dst_cpu);
 		}
 
-		memset(sgs, 0, sizeof(*sgs));
 		update_sg_lb_stats(env, sg, load_idx, local_group, sgs);
 
+		if (local_group)
+			goto next_group;
+
 		/*
 		 * In case the child domain prefers tasks go to siblings
 		 * first, lower the sg capacity to one so that we'll try
@@ -4735,21 +5639,25 @@
 		 * heaviest group when it is already under-utilized (possible
 		 * with a large weight task outweighs the tasks on the system).
 		 */
-		if (prefer_sibling && !local_group &&
-				sds->local && sds->local_stat.group_has_capacity)
+		if (prefer_sibling && sds->local &&
+		    sds->local_stat.group_has_capacity)
 			sgs->group_capacity = min(sgs->group_capacity, 1U);
 
-		/* Now, start updating sd_lb_stats */
-		sds->total_load += sgs->group_load;
-		sds->total_pwr += sgs->group_power;
-
-		if (!local_group && update_sd_pick_busiest(env, sds, sg, sgs)) {
+		if (update_sd_pick_busiest(env, sds, sg, sgs)) {
 			sds->busiest = sg;
 			sds->busiest_stat = *sgs;
 		}
 
+next_group:
+		/* Now, start updating sd_lb_stats */
+		sds->total_load += sgs->group_load;
+		sds->total_pwr += sgs->group_power;
+
 		sg = sg->next;
 	} while (sg != env->sd->groups);
+
+	if (env->sd->flags & SD_NUMA)
+		env->fbq_type = fbq_classify_group(&sds->busiest_stat);
 }
 
 /**
@@ -5053,15 +5961,39 @@
 	int i;
 
 	for_each_cpu_and(i, sched_group_cpus(group), env->cpus) {
-		unsigned long power = power_of(i);
-		unsigned long capacity = DIV_ROUND_CLOSEST(power,
-							   SCHED_POWER_SCALE);
-		unsigned long wl;
+		unsigned long power, capacity, wl;
+		enum fbq_type rt;
 
+		rq = cpu_rq(i);
+		rt = fbq_classify_rq(rq);
+
+		/*
+		 * We classify groups/runqueues into three groups:
+		 *  - regular: there are !numa tasks
+		 *  - remote:  there are numa tasks that run on the 'wrong' node
+		 *  - all:     there is no distinction
+		 *
+		 * In order to avoid migrating ideally placed numa tasks,
+		 * ignore those when there's better options.
+		 *
+		 * If we ignore the actual busiest queue to migrate another
+		 * task, the next balance pass can still reduce the busiest
+		 * queue by moving tasks around inside the node.
+		 *
+		 * If we cannot move enough load due to this classification
+		 * the next pass will adjust the group classification and
+		 * allow migration of more tasks.
+		 *
+		 * Both cases only affect the total convergence complexity.
+		 */
+		if (rt > env->fbq_type)
+			continue;
+
+		power = power_of(i);
+		capacity = DIV_ROUND_CLOSEST(power, SCHED_POWER_SCALE);
 		if (!capacity)
 			capacity = fix_small_capacity(env->sd, group);
 
-		rq = cpu_rq(i);
 		wl = weighted_cpuload(i);
 
 		/*
@@ -5164,6 +6096,7 @@
 			int *continue_balancing)
 {
 	int ld_moved, cur_ld_moved, active_balance = 0;
+	struct sched_domain *sd_parent = sd->parent;
 	struct sched_group *group;
 	struct rq *busiest;
 	unsigned long flags;
@@ -5177,6 +6110,7 @@
 		.idle		= idle,
 		.loop_break	= sched_nr_migrate_break,
 		.cpus		= cpus,
+		.fbq_type	= all,
 	};
 
 	/*
@@ -5268,17 +6202,17 @@
 		 * moreover subsequent load balance cycles should correct the
 		 * excess load moved.
 		 */
-		if ((env.flags & LBF_SOME_PINNED) && env.imbalance > 0) {
-
-			env.dst_rq	 = cpu_rq(env.new_dst_cpu);
-			env.dst_cpu	 = env.new_dst_cpu;
-			env.flags	&= ~LBF_SOME_PINNED;
-			env.loop	 = 0;
-			env.loop_break	 = sched_nr_migrate_break;
+		if ((env.flags & LBF_DST_PINNED) && env.imbalance > 0) {
 
 			/* Prevent to re-select dst_cpu via env's cpus */
 			cpumask_clear_cpu(env.dst_cpu, env.cpus);
 
+			env.dst_rq	 = cpu_rq(env.new_dst_cpu);
+			env.dst_cpu	 = env.new_dst_cpu;
+			env.flags	&= ~LBF_DST_PINNED;
+			env.loop	 = 0;
+			env.loop_break	 = sched_nr_migrate_break;
+
 			/*
 			 * Go back to "more_balance" rather than "redo" since we
 			 * need to continue with same src_cpu.
@@ -5286,6 +6220,18 @@
 			goto more_balance;
 		}
 
+		/*
+		 * We failed to reach balance because of affinity.
+		 */
+		if (sd_parent) {
+			int *group_imbalance = &sd_parent->groups->sgp->imbalance;
+
+			if ((env.flags & LBF_SOME_PINNED) && env.imbalance > 0) {
+				*group_imbalance = 1;
+			} else if (*group_imbalance)
+				*group_imbalance = 0;
+		}
+
 		/* All tasks on this runqueue were pinned by CPU affinity */
 		if (unlikely(env.flags & LBF_ALL_PINNED)) {
 			cpumask_clear_cpu(cpu_of(busiest), cpus);
@@ -5393,6 +6339,7 @@
 	struct sched_domain *sd;
 	int pulled_task = 0;
 	unsigned long next_balance = jiffies + HZ;
+	u64 curr_cost = 0;
 
 	this_rq->idle_stamp = rq_clock(this_rq);
 
@@ -5409,15 +6356,27 @@
 	for_each_domain(this_cpu, sd) {
 		unsigned long interval;
 		int continue_balancing = 1;
+		u64 t0, domain_cost;
 
 		if (!(sd->flags & SD_LOAD_BALANCE))
 			continue;
 
+		if (this_rq->avg_idle < curr_cost + sd->max_newidle_lb_cost)
+			break;
+
 		if (sd->flags & SD_BALANCE_NEWIDLE) {
+			t0 = sched_clock_cpu(this_cpu);
+
 			/* If we've pulled tasks over stop searching: */
 			pulled_task = load_balance(this_cpu, this_rq,
 						   sd, CPU_NEWLY_IDLE,
 						   &continue_balancing);
+
+			domain_cost = sched_clock_cpu(this_cpu) - t0;
+			if (domain_cost > sd->max_newidle_lb_cost)
+				sd->max_newidle_lb_cost = domain_cost;
+
+			curr_cost += domain_cost;
 		}
 
 		interval = msecs_to_jiffies(sd->balance_interval);
@@ -5439,6 +6398,9 @@
 		 */
 		this_rq->next_balance = next_balance;
 	}
+
+	if (curr_cost > this_rq->max_idle_balance_cost)
+		this_rq->max_idle_balance_cost = curr_cost;
 }
 
 /*
@@ -5572,16 +6534,16 @@
 static inline void set_cpu_sd_state_busy(void)
 {
 	struct sched_domain *sd;
+	int cpu = smp_processor_id();
 
 	rcu_read_lock();
-	sd = rcu_dereference_check_sched_domain(this_rq()->sd);
+	sd = rcu_dereference(per_cpu(sd_busy, cpu));
 
 	if (!sd || !sd->nohz_idle)
 		goto unlock;
 	sd->nohz_idle = 0;
 
-	for (; sd; sd = sd->parent)
-		atomic_inc(&sd->groups->sgp->nr_busy_cpus);
+	atomic_inc(&sd->groups->sgp->nr_busy_cpus);
 unlock:
 	rcu_read_unlock();
 }
@@ -5589,16 +6551,16 @@
 void set_cpu_sd_state_idle(void)
 {
 	struct sched_domain *sd;
+	int cpu = smp_processor_id();
 
 	rcu_read_lock();
-	sd = rcu_dereference_check_sched_domain(this_rq()->sd);
+	sd = rcu_dereference(per_cpu(sd_busy, cpu));
 
 	if (!sd || sd->nohz_idle)
 		goto unlock;
 	sd->nohz_idle = 1;
 
-	for (; sd; sd = sd->parent)
-		atomic_dec(&sd->groups->sgp->nr_busy_cpus);
+	atomic_dec(&sd->groups->sgp->nr_busy_cpus);
 unlock:
 	rcu_read_unlock();
 }
@@ -5662,15 +6624,39 @@
 	/* Earliest time when we have to do rebalance again */
 	unsigned long next_balance = jiffies + 60*HZ;
 	int update_next_balance = 0;
-	int need_serialize;
+	int need_serialize, need_decay = 0;
+	u64 max_cost = 0;
 
 	update_blocked_averages(cpu);
 
 	rcu_read_lock();
 	for_each_domain(cpu, sd) {
+		/*
+		 * Decay the newidle max times here because this is a regular
+		 * visit to all the domains. Decay ~1% per second.
+		 */
+		if (time_after(jiffies, sd->next_decay_max_lb_cost)) {
+			sd->max_newidle_lb_cost =
+				(sd->max_newidle_lb_cost * 253) / 256;
+			sd->next_decay_max_lb_cost = jiffies + HZ;
+			need_decay = 1;
+		}
+		max_cost += sd->max_newidle_lb_cost;
+
 		if (!(sd->flags & SD_LOAD_BALANCE))
 			continue;
 
+		/*
+		 * Stop the load balance at this level. There is another
+		 * CPU in our sched group which is doing load balancing more
+		 * actively.
+		 */
+		if (!continue_balancing) {
+			if (need_decay)
+				continue;
+			break;
+		}
+
 		interval = sd->balance_interval;
 		if (idle != CPU_IDLE)
 			interval *= sd->busy_factor;
@@ -5689,7 +6675,7 @@
 		if (time_after_eq(jiffies, sd->last_balance + interval)) {
 			if (load_balance(cpu, rq, sd, idle, &continue_balancing)) {
 				/*
-				 * The LBF_SOME_PINNED logic could have changed
+				 * The LBF_DST_PINNED logic could have changed
 				 * env->dst_cpu, so we can't know our idle
 				 * state even if we migrated tasks. Update it.
 				 */
@@ -5704,14 +6690,14 @@
 			next_balance = sd->last_balance + interval;
 			update_next_balance = 1;
 		}
-
+	}
+	if (need_decay) {
 		/*
-		 * Stop the load balance at this level. There is another
-		 * CPU in our sched group which is doing load balancing more
-		 * actively.
+		 * Ensure the rq-wide value also decays but keep it at a
+		 * reasonable floor to avoid funnies with rq->avg_idle.
 		 */
-		if (!continue_balancing)
-			break;
+		rq->max_idle_balance_cost =
+			max((u64)sysctl_sched_migration_cost, max_cost);
 	}
 	rcu_read_unlock();
 
@@ -5781,6 +6767,8 @@
 {
 	unsigned long now = jiffies;
 	struct sched_domain *sd;
+	struct sched_group_power *sgp;
+	int nr_busy;
 
 	if (unlikely(idle_cpu(cpu)))
 		return 0;
@@ -5806,22 +6794,22 @@
 		goto need_kick;
 
 	rcu_read_lock();
-	for_each_domain(cpu, sd) {
-		struct sched_group *sg = sd->groups;
-		struct sched_group_power *sgp = sg->sgp;
-		int nr_busy = atomic_read(&sgp->nr_busy_cpus);
+	sd = rcu_dereference(per_cpu(sd_busy, cpu));
 
-		if (sd->flags & SD_SHARE_PKG_RESOURCES && nr_busy > 1)
+	if (sd) {
+		sgp = sd->groups->sgp;
+		nr_busy = atomic_read(&sgp->nr_busy_cpus);
+
+		if (nr_busy > 1)
 			goto need_kick_unlock;
-
-		if (sd->flags & SD_ASYM_PACKING && nr_busy != sg->group_weight
-		    && (cpumask_first_and(nohz.idle_cpus_mask,
-					  sched_domain_span(sd)) < cpu))
-			goto need_kick_unlock;
-
-		if (!(sd->flags & (SD_SHARE_PKG_RESOURCES | SD_ASYM_PACKING)))
-			break;
 	}
+
+	sd = rcu_dereference(per_cpu(sd_asym, cpu));
+
+	if (sd && (cpumask_first_and(nohz.idle_cpus_mask,
+				  sched_domain_span(sd)) < cpu))
+		goto need_kick_unlock;
+
 	rcu_read_unlock();
 	return 0;
 
@@ -6214,7 +7202,8 @@
 		se->cfs_rq = parent->my_q;
 
 	se->my_q = cfs_rq;
-	update_load_set(&se->load, 0);
+	/* guarantee group entities always have weight */
+	update_load_set(&se->load, NICE_0_LOAD);
 	se->parent = parent;
 }
 
diff --git a/kernel/sched/features.h b/kernel/sched/features.h
index 99399f8..5716929 100644
--- a/kernel/sched/features.h
+++ b/kernel/sched/features.h
@@ -63,10 +63,23 @@
 /*
  * Apply the automatic NUMA scheduling policy. Enabled automatically
  * at runtime if running on a NUMA machine. Can be controlled via
- * numa_balancing=. Allow PTE scanning to be forced on UMA machines
- * for debugging the core machinery.
+ * numa_balancing=
  */
 #ifdef CONFIG_NUMA_BALANCING
 SCHED_FEAT(NUMA,	false)
-SCHED_FEAT(NUMA_FORCE,	false)
+
+/*
+ * NUMA_FAVOUR_HIGHER will favor moving tasks towards nodes where a
+ * higher number of hinting faults are recorded during active load
+ * balancing.
+ */
+SCHED_FEAT(NUMA_FAVOUR_HIGHER, true)
+
+/*
+ * NUMA_RESIST_LOWER will resist moving tasks towards nodes where a
+ * lower number of hinting faults have been recorded. As this has
+ * the potential to prevent a task ever migrating to a new node
+ * due to CPU overload it is disabled by default.
+ */
+SCHED_FEAT(NUMA_RESIST_LOWER, false)
 #endif
diff --git a/kernel/sched/idle_task.c b/kernel/sched/idle_task.c
index d8da010..516c3d9 100644
--- a/kernel/sched/idle_task.c
+++ b/kernel/sched/idle_task.c
@@ -9,7 +9,7 @@
 
 #ifdef CONFIG_SMP
 static int
-select_task_rq_idle(struct task_struct *p, int sd_flag, int flags)
+select_task_rq_idle(struct task_struct *p, int cpu, int sd_flag, int flags)
 {
 	return task_cpu(p); /* IDLE tasks as never migrated */
 }
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 01970c8..7d57275 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -246,8 +246,10 @@
 	 * if we should look at the mask. It would be a shame
 	 * if we looked at the mask, but the mask was not
 	 * updated yet.
+	 *
+	 * Matched by the barrier in pull_rt_task().
 	 */
-	wmb();
+	smp_wmb();
 	atomic_inc(&rq->rd->rto_count);
 }
 
@@ -1169,13 +1171,10 @@
 static int find_lowest_rq(struct task_struct *task);
 
 static int
-select_task_rq_rt(struct task_struct *p, int sd_flag, int flags)
+select_task_rq_rt(struct task_struct *p, int cpu, int sd_flag, int flags)
 {
 	struct task_struct *curr;
 	struct rq *rq;
-	int cpu;
-
-	cpu = task_cpu(p);
 
 	if (p->nr_cpus_allowed == 1)
 		goto out;
@@ -1213,8 +1212,7 @@
 	 */
 	if (curr && unlikely(rt_task(curr)) &&
 	    (curr->nr_cpus_allowed < 2 ||
-	     curr->prio <= p->prio) &&
-	    (p->nr_cpus_allowed > 1)) {
+	     curr->prio <= p->prio)) {
 		int target = find_lowest_rq(p);
 
 		if (target != -1)
@@ -1630,6 +1628,12 @@
 	if (likely(!rt_overloaded(this_rq)))
 		return 0;
 
+	/*
+	 * Match the barrier from rt_set_overloaded; this guarantees that if we
+	 * see overloaded we must also see the rto_mask bit.
+	 */
+	smp_rmb();
+
 	for_each_cpu(cpu, this_rq->rd->rto_mask) {
 		if (this_cpu == cpu)
 			continue;
@@ -1931,8 +1935,8 @@
 	p->rt.time_slice = sched_rr_timeslice;
 
 	/*
-	 * Requeue to the end of queue if we (and all of our ancestors) are the
-	 * only element on the queue
+	 * Requeue to the end of queue if we (and all of our ancestors) are not
+	 * the only element on the queue
 	 */
 	for_each_sched_rt_entity(rt_se) {
 		if (rt_se->run_list.prev != rt_se->run_list.next) {
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index b3c5653..88c85b2 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -6,6 +6,7 @@
 #include <linux/spinlock.h>
 #include <linux/stop_machine.h>
 #include <linux/tick.h>
+#include <linux/slab.h>
 
 #include "cpupri.h"
 #include "cpuacct.h"
@@ -408,6 +409,10 @@
 	 * remote CPUs use both these fields when doing load calculation.
 	 */
 	unsigned int nr_running;
+#ifdef CONFIG_NUMA_BALANCING
+	unsigned int nr_numa_running;
+	unsigned int nr_preferred_running;
+#endif
 	#define CPU_LOAD_IDX_MAX 5
 	unsigned long cpu_load[CPU_LOAD_IDX_MAX];
 	unsigned long last_load_update_tick;
@@ -476,6 +481,9 @@
 	u64 age_stamp;
 	u64 idle_stamp;
 	u64 avg_idle;
+
+	/* This is used to determine avg_idle's max value */
+	u64 max_idle_balance_cost;
 #endif
 
 #ifdef CONFIG_IRQ_TIME_ACCOUNTING
@@ -552,6 +560,12 @@
 	return rq->clock_task;
 }
 
+#ifdef CONFIG_NUMA_BALANCING
+extern void sched_setnuma(struct task_struct *p, int node);
+extern int migrate_task_to(struct task_struct *p, int cpu);
+extern int migrate_swap(struct task_struct *, struct task_struct *);
+#endif /* CONFIG_NUMA_BALANCING */
+
 #ifdef CONFIG_SMP
 
 #define rcu_dereference_check_sched_domain(p) \
@@ -593,9 +607,24 @@
 	return hsd;
 }
 
+static inline struct sched_domain *lowest_flag_domain(int cpu, int flag)
+{
+	struct sched_domain *sd;
+
+	for_each_domain(cpu, sd) {
+		if (sd->flags & flag)
+			break;
+	}
+
+	return sd;
+}
+
 DECLARE_PER_CPU(struct sched_domain *, sd_llc);
 DECLARE_PER_CPU(int, sd_llc_size);
 DECLARE_PER_CPU(int, sd_llc_id);
+DECLARE_PER_CPU(struct sched_domain *, sd_numa);
+DECLARE_PER_CPU(struct sched_domain *, sd_busy);
+DECLARE_PER_CPU(struct sched_domain *, sd_asym);
 
 struct sched_group_power {
 	atomic_t ref;
@@ -605,6 +634,7 @@
 	 */
 	unsigned int power, power_orig;
 	unsigned long next_update;
+	int imbalance; /* XXX unrelated to power but shared group state */
 	/*
 	 * Number of busy cpus in this group.
 	 */
@@ -719,6 +749,7 @@
 	 */
 	smp_wmb();
 	task_thread_info(p)->cpu = cpu;
+	p->wake_cpu = cpu;
 #endif
 }
 
@@ -974,7 +1005,7 @@
 	void (*put_prev_task) (struct rq *rq, struct task_struct *p);
 
 #ifdef CONFIG_SMP
-	int  (*select_task_rq)(struct task_struct *p, int sd_flag, int flags);
+	int  (*select_task_rq)(struct task_struct *p, int task_cpu, int sd_flag, int flags);
 	void (*migrate_task_rq)(struct task_struct *p, int next_cpu);
 
 	void (*pre_schedule) (struct rq *this_rq, struct task_struct *task);
@@ -1220,6 +1251,24 @@
 	lock_set_subclass(&this_rq->lock.dep_map, 0, _RET_IP_);
 }
 
+static inline void double_lock(spinlock_t *l1, spinlock_t *l2)
+{
+	if (l1 > l2)
+		swap(l1, l2);
+
+	spin_lock(l1);
+	spin_lock_nested(l2, SINGLE_DEPTH_NESTING);
+}
+
+static inline void double_raw_lock(raw_spinlock_t *l1, raw_spinlock_t *l2)
+{
+	if (l1 > l2)
+		swap(l1, l2);
+
+	raw_spin_lock(l1);
+	raw_spin_lock_nested(l2, SINGLE_DEPTH_NESTING);
+}
+
 /*
  * double_rq_lock - safely lock two runqueues
  *
@@ -1305,7 +1354,8 @@
 extern void init_cfs_rq(struct cfs_rq *cfs_rq);
 extern void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq);
 
-extern void account_cfs_bandwidth_used(int enabled, int was_enabled);
+extern void cfs_bandwidth_usage_inc(void);
+extern void cfs_bandwidth_usage_dec(void);
 
 #ifdef CONFIG_NO_HZ_COMMON
 enum rq_nohz_flag_bits {
diff --git a/kernel/sched/stats.h b/kernel/sched/stats.h
index c7edee7..4ab7043 100644
--- a/kernel/sched/stats.h
+++ b/kernel/sched/stats.h
@@ -59,9 +59,9 @@
  * from dequeue_task() to account for possible rq->clock skew across cpus. The
  * delta taken on each cpu would annul the skew.
  */
-static inline void sched_info_dequeued(struct task_struct *t)
+static inline void sched_info_dequeued(struct rq *rq, struct task_struct *t)
 {
-	unsigned long long now = rq_clock(task_rq(t)), delta = 0;
+	unsigned long long now = rq_clock(rq), delta = 0;
 
 	if (unlikely(sched_info_on()))
 		if (t->sched_info.last_queued)
@@ -69,7 +69,7 @@
 	sched_info_reset_dequeued(t);
 	t->sched_info.run_delay += delta;
 
-	rq_sched_info_dequeued(task_rq(t), delta);
+	rq_sched_info_dequeued(rq, delta);
 }
 
 /*
@@ -77,9 +77,9 @@
  * long it was waiting to run.  We also note when it began so that we
  * can keep stats on how long its timeslice is.
  */
-static void sched_info_arrive(struct task_struct *t)
+static void sched_info_arrive(struct rq *rq, struct task_struct *t)
 {
-	unsigned long long now = rq_clock(task_rq(t)), delta = 0;
+	unsigned long long now = rq_clock(rq), delta = 0;
 
 	if (t->sched_info.last_queued)
 		delta = now - t->sched_info.last_queued;
@@ -88,7 +88,7 @@
 	t->sched_info.last_arrival = now;
 	t->sched_info.pcount++;
 
-	rq_sched_info_arrive(task_rq(t), delta);
+	rq_sched_info_arrive(rq, delta);
 }
 
 /*
@@ -96,11 +96,11 @@
  * the timestamp if it is already not set.  It's assumed that
  * sched_info_dequeued() will clear that stamp when appropriate.
  */
-static inline void sched_info_queued(struct task_struct *t)
+static inline void sched_info_queued(struct rq *rq, struct task_struct *t)
 {
 	if (unlikely(sched_info_on()))
 		if (!t->sched_info.last_queued)
-			t->sched_info.last_queued = rq_clock(task_rq(t));
+			t->sched_info.last_queued = rq_clock(rq);
 }
 
 /*
@@ -111,15 +111,15 @@
  * sched_info_queued() to mark that it has now again started waiting on
  * the runqueue.
  */
-static inline void sched_info_depart(struct task_struct *t)
+static inline void sched_info_depart(struct rq *rq, struct task_struct *t)
 {
-	unsigned long long delta = rq_clock(task_rq(t)) -
+	unsigned long long delta = rq_clock(rq) -
 					t->sched_info.last_arrival;
 
-	rq_sched_info_depart(task_rq(t), delta);
+	rq_sched_info_depart(rq, delta);
 
 	if (t->state == TASK_RUNNING)
-		sched_info_queued(t);
+		sched_info_queued(rq, t);
 }
 
 /*
@@ -128,32 +128,34 @@
  * the idle task.)  We are only called when prev != next.
  */
 static inline void
-__sched_info_switch(struct task_struct *prev, struct task_struct *next)
+__sched_info_switch(struct rq *rq,
+		    struct task_struct *prev, struct task_struct *next)
 {
-	struct rq *rq = task_rq(prev);
-
 	/*
 	 * prev now departs the cpu.  It's not interesting to record
 	 * stats about how efficient we were at scheduling the idle
 	 * process, however.
 	 */
 	if (prev != rq->idle)
-		sched_info_depart(prev);
+		sched_info_depart(rq, prev);
 
 	if (next != rq->idle)
-		sched_info_arrive(next);
+		sched_info_arrive(rq, next);
 }
 static inline void
-sched_info_switch(struct task_struct *prev, struct task_struct *next)
+sched_info_switch(struct rq *rq,
+		  struct task_struct *prev, struct task_struct *next)
 {
 	if (unlikely(sched_info_on()))
-		__sched_info_switch(prev, next);
+		__sched_info_switch(rq, prev, next);
 }
 #else
-#define sched_info_queued(t)			do { } while (0)
+#define sched_info_queued(rq, t)		do { } while (0)
 #define sched_info_reset_dequeued(t)	do { } while (0)
-#define sched_info_dequeued(t)			do { } while (0)
-#define sched_info_switch(t, next)		do { } while (0)
+#define sched_info_dequeued(rq, t)		do { } while (0)
+#define sched_info_depart(rq, t)		do { } while (0)
+#define sched_info_arrive(rq, next)		do { } while (0)
+#define sched_info_switch(rq, t, next)		do { } while (0)
 #endif /* CONFIG_SCHEDSTATS || CONFIG_TASK_DELAY_ACCT */
 
 /*
diff --git a/kernel/sched/stop_task.c b/kernel/sched/stop_task.c
index e08fbee..47197de 100644
--- a/kernel/sched/stop_task.c
+++ b/kernel/sched/stop_task.c
@@ -11,7 +11,7 @@
 
 #ifdef CONFIG_SMP
 static int
-select_task_rq_stop(struct task_struct *p, int sd_flag, int flags)
+select_task_rq_stop(struct task_struct *p, int cpu, int sd_flag, int flags)
 {
 	return task_cpu(p); /* stop tasks as never migrate */
 }
diff --git a/kernel/wait.c b/kernel/sched/wait.c
similarity index 73%
rename from kernel/wait.c
rename to kernel/sched/wait.c
index d550920..7d50f79 100644
--- a/kernel/wait.c
+++ b/kernel/sched/wait.c
@@ -53,6 +53,109 @@
 
 
 /*
+ * The core wakeup function. Non-exclusive wakeups (nr_exclusive == 0) just
+ * wake everything up. If it's an exclusive wakeup (nr_exclusive == small +ve
+ * number) then we wake all the non-exclusive tasks and one exclusive task.
+ *
+ * There are circumstances in which we can try to wake a task which has already
+ * started to run but is not in state TASK_RUNNING. try_to_wake_up() returns
+ * zero in this (rare) case, and we handle it by continuing to scan the queue.
+ */
+static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
+			int nr_exclusive, int wake_flags, void *key)
+{
+	wait_queue_t *curr, *next;
+
+	list_for_each_entry_safe(curr, next, &q->task_list, task_list) {
+		unsigned flags = curr->flags;
+
+		if (curr->func(curr, mode, wake_flags, key) &&
+				(flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
+			break;
+	}
+}
+
+/**
+ * __wake_up - wake up threads blocked on a waitqueue.
+ * @q: the waitqueue
+ * @mode: which threads
+ * @nr_exclusive: how many wake-one or wake-many threads to wake up
+ * @key: is directly passed to the wakeup function
+ *
+ * It may be assumed that this function implies a write memory barrier before
+ * changing the task state if and only if any tasks are woken up.
+ */
+void __wake_up(wait_queue_head_t *q, unsigned int mode,
+			int nr_exclusive, void *key)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&q->lock, flags);
+	__wake_up_common(q, mode, nr_exclusive, 0, key);
+	spin_unlock_irqrestore(&q->lock, flags);
+}
+EXPORT_SYMBOL(__wake_up);
+
+/*
+ * Same as __wake_up but called with the spinlock in wait_queue_head_t held.
+ */
+void __wake_up_locked(wait_queue_head_t *q, unsigned int mode, int nr)
+{
+	__wake_up_common(q, mode, nr, 0, NULL);
+}
+EXPORT_SYMBOL_GPL(__wake_up_locked);
+
+void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key)
+{
+	__wake_up_common(q, mode, 1, 0, key);
+}
+EXPORT_SYMBOL_GPL(__wake_up_locked_key);
+
+/**
+ * __wake_up_sync_key - wake up threads blocked on a waitqueue.
+ * @q: the waitqueue
+ * @mode: which threads
+ * @nr_exclusive: how many wake-one or wake-many threads to wake up
+ * @key: opaque value to be passed to wakeup targets
+ *
+ * The sync wakeup differs that the waker knows that it will schedule
+ * away soon, so while the target thread will be woken up, it will not
+ * be migrated to another CPU - ie. the two threads are 'synchronized'
+ * with each other. This can prevent needless bouncing between CPUs.
+ *
+ * On UP it can prevent extra preemption.
+ *
+ * It may be assumed that this function implies a write memory barrier before
+ * changing the task state if and only if any tasks are woken up.
+ */
+void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode,
+			int nr_exclusive, void *key)
+{
+	unsigned long flags;
+	int wake_flags = 1; /* XXX WF_SYNC */
+
+	if (unlikely(!q))
+		return;
+
+	if (unlikely(nr_exclusive != 1))
+		wake_flags = 0;
+
+	spin_lock_irqsave(&q->lock, flags);
+	__wake_up_common(q, mode, nr_exclusive, wake_flags, key);
+	spin_unlock_irqrestore(&q->lock, flags);
+}
+EXPORT_SYMBOL_GPL(__wake_up_sync_key);
+
+/*
+ * __wake_up_sync - see __wake_up_sync_key()
+ */
+void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
+{
+	__wake_up_sync_key(q, mode, nr_exclusive, NULL);
+}
+EXPORT_SYMBOL_GPL(__wake_up_sync);	/* For internal use only */
+
+/*
  * Note: we use "set_current_state()" _after_ the wait-queue add,
  * because we need a memory barrier there on SMP, so that any
  * wake-function that tests for the wait-queue being active
@@ -92,6 +195,30 @@
 }
 EXPORT_SYMBOL(prepare_to_wait_exclusive);
 
+long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state)
+{
+	unsigned long flags;
+
+	if (signal_pending_state(state, current))
+		return -ERESTARTSYS;
+
+	wait->private = current;
+	wait->func = autoremove_wake_function;
+
+	spin_lock_irqsave(&q->lock, flags);
+	if (list_empty(&wait->task_list)) {
+		if (wait->flags & WQ_FLAG_EXCLUSIVE)
+			__add_wait_queue_tail(q, wait);
+		else
+			__add_wait_queue(q, wait);
+	}
+	set_current_state(state);
+	spin_unlock_irqrestore(&q->lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(prepare_to_wait_event);
+
 /**
  * finish_wait - clean up after waiting in a queue
  * @q: waitqueue waited on
diff --git a/kernel/smp.c b/kernel/smp.c
index 0564571..f5768b0 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -524,6 +524,11 @@
 	nr_cpu_ids = find_last_bit(cpumask_bits(cpu_possible_mask),NR_CPUS) + 1;
 }
 
+void __weak smp_announce(void)
+{
+	printk(KERN_INFO "Brought up %d CPUs\n", num_online_cpus());
+}
+
 /* Called by boot processor to activate the rest. */
 void __init smp_init(void)
 {
@@ -540,7 +545,7 @@
 	}
 
 	/* Any cleanup work */
-	printk(KERN_INFO "Brought up %ld CPUs\n", (long)num_online_cpus());
+	smp_announce();
 	smp_cpus_done(setup_max_cpus);
 }
 
diff --git a/kernel/softirq.c b/kernel/softirq.c
index d7d498d..b249883 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -29,7 +29,6 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/irq.h>
 
-#include <asm/irq.h>
 /*
    - No shared variables, all the data are CPU local.
    - If a softirq needs serialization, let it serialize itself
@@ -100,13 +99,13 @@
 
 	raw_local_irq_save(flags);
 	/*
-	 * The preempt tracer hooks into add_preempt_count and will break
+	 * The preempt tracer hooks into preempt_count_add and will break
 	 * lockdep because it calls back into lockdep after SOFTIRQ_OFFSET
 	 * is set and before current->softirq_enabled is cleared.
 	 * We must manually increment preempt_count here and manually
 	 * call the trace_preempt_off later.
 	 */
-	preempt_count() += cnt;
+	__preempt_count_add(cnt);
 	/*
 	 * Were softirqs turned off above:
 	 */
@@ -120,7 +119,7 @@
 #else /* !CONFIG_TRACE_IRQFLAGS */
 static inline void __local_bh_disable(unsigned long ip, unsigned int cnt)
 {
-	add_preempt_count(cnt);
+	preempt_count_add(cnt);
 	barrier();
 }
 #endif /* CONFIG_TRACE_IRQFLAGS */
@@ -134,12 +133,11 @@
 
 static void __local_bh_enable(unsigned int cnt)
 {
-	WARN_ON_ONCE(in_irq());
 	WARN_ON_ONCE(!irqs_disabled());
 
 	if (softirq_count() == cnt)
 		trace_softirqs_on(_RET_IP_);
-	sub_preempt_count(cnt);
+	preempt_count_sub(cnt);
 }
 
 /*
@@ -149,6 +147,7 @@
  */
 void _local_bh_enable(void)
 {
+	WARN_ON_ONCE(in_irq());
 	__local_bh_enable(SOFTIRQ_DISABLE_OFFSET);
 }
 
@@ -169,12 +168,17 @@
 	 * Keep preemption disabled until we are done with
 	 * softirq processing:
  	 */
-	sub_preempt_count(SOFTIRQ_DISABLE_OFFSET - 1);
+	preempt_count_sub(SOFTIRQ_DISABLE_OFFSET - 1);
 
-	if (unlikely(!in_interrupt() && local_softirq_pending()))
+	if (unlikely(!in_interrupt() && local_softirq_pending())) {
+		/*
+		 * Run softirq if any pending. And do it in its own stack
+		 * as we may be calling this deep in a task call stack already.
+		 */
 		do_softirq();
+	}
 
-	dec_preempt_count();
+	preempt_count_dec();
 #ifdef CONFIG_TRACE_IRQFLAGS
 	local_irq_enable();
 #endif
@@ -256,7 +260,7 @@
 				       " exited with %08x?\n", vec_nr,
 				       softirq_to_name[vec_nr], h->action,
 				       prev_count, preempt_count());
-				preempt_count() = prev_count;
+				preempt_count_set(prev_count);
 			}
 
 			rcu_bh_qs(cpu);
@@ -280,10 +284,11 @@
 
 	account_irq_exit_time(current);
 	__local_bh_enable(SOFTIRQ_OFFSET);
+	WARN_ON_ONCE(in_interrupt());
 	tsk_restore_flags(current, old_flags, PF_MEMALLOC);
 }
 
-#ifndef __ARCH_HAS_DO_SOFTIRQ
+
 
 asmlinkage void do_softirq(void)
 {
@@ -298,13 +303,11 @@
 	pending = local_softirq_pending();
 
 	if (pending)
-		__do_softirq();
+		do_softirq_own_stack();
 
 	local_irq_restore(flags);
 }
 
-#endif
-
 /*
  * Enter an interrupt context.
  */
@@ -329,15 +332,21 @@
 static inline void invoke_softirq(void)
 {
 	if (!force_irqthreads) {
+#ifdef CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK
 		/*
 		 * We can safely execute softirq on the current stack if
 		 * it is the irq stack, because it should be near empty
-		 * at this stage. But we have no way to know if the arch
-		 * calls irq_exit() on the irq stack. So call softirq
-		 * in its own stack to prevent from any overrun on top
-		 * of a potentially deep task stack.
+		 * at this stage.
 		 */
-		do_softirq();
+		__do_softirq();
+#else
+		/*
+		 * Otherwise, irq_exit() is called on the task stack that can
+		 * be potentially deep already. So call softirq in its own stack
+		 * to prevent from any overrun.
+		 */
+		do_softirq_own_stack();
+#endif
 	} else {
 		wakeup_softirqd();
 	}
@@ -369,7 +378,7 @@
 
 	account_irq_exit_time(current);
 	trace_hardirq_exit();
-	sub_preempt_count(HARDIRQ_OFFSET);
+	preempt_count_sub(HARDIRQ_OFFSET);
 	if (!in_interrupt() && local_softirq_pending())
 		invoke_softirq();
 
@@ -771,6 +780,10 @@
 {
 	local_irq_disable();
 	if (local_softirq_pending()) {
+		/*
+		 * We can safely run softirq on inline stack, as we are not deep
+		 * in the task stack here.
+		 */
 		__do_softirq();
 		rcu_note_context_switch(cpu);
 		local_irq_enable();
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index c09f295..84571e0 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -20,6 +20,7 @@
 #include <linux/kallsyms.h>
 #include <linux/smpboot.h>
 #include <linux/atomic.h>
+#include <linux/lglock.h>
 
 /*
  * Structure to determine completion condition and record errors.  May
@@ -43,6 +44,14 @@
 static DEFINE_PER_CPU(struct task_struct *, cpu_stopper_task);
 static bool stop_machine_initialized = false;
 
+/*
+ * Avoids a race between stop_two_cpus and global stop_cpus, where
+ * the stoppers could get queued up in reverse order, leading to
+ * system deadlock. Using an lglock means stop_two_cpus remains
+ * relatively cheap.
+ */
+DEFINE_STATIC_LGLOCK(stop_cpus_lock);
+
 static void cpu_stop_init_done(struct cpu_stop_done *done, unsigned int nr_todo)
 {
 	memset(done, 0, sizeof(*done));
@@ -115,6 +124,184 @@
 	return done.executed ? done.ret : -ENOENT;
 }
 
+/* This controls the threads on each CPU. */
+enum multi_stop_state {
+	/* Dummy starting state for thread. */
+	MULTI_STOP_NONE,
+	/* Awaiting everyone to be scheduled. */
+	MULTI_STOP_PREPARE,
+	/* Disable interrupts. */
+	MULTI_STOP_DISABLE_IRQ,
+	/* Run the function */
+	MULTI_STOP_RUN,
+	/* Exit */
+	MULTI_STOP_EXIT,
+};
+
+struct multi_stop_data {
+	int			(*fn)(void *);
+	void			*data;
+	/* Like num_online_cpus(), but hotplug cpu uses us, so we need this. */
+	unsigned int		num_threads;
+	const struct cpumask	*active_cpus;
+
+	enum multi_stop_state	state;
+	atomic_t		thread_ack;
+};
+
+static void set_state(struct multi_stop_data *msdata,
+		      enum multi_stop_state newstate)
+{
+	/* Reset ack counter. */
+	atomic_set(&msdata->thread_ack, msdata->num_threads);
+	smp_wmb();
+	msdata->state = newstate;
+}
+
+/* Last one to ack a state moves to the next state. */
+static void ack_state(struct multi_stop_data *msdata)
+{
+	if (atomic_dec_and_test(&msdata->thread_ack))
+		set_state(msdata, msdata->state + 1);
+}
+
+/* This is the cpu_stop function which stops the CPU. */
+static int multi_cpu_stop(void *data)
+{
+	struct multi_stop_data *msdata = data;
+	enum multi_stop_state curstate = MULTI_STOP_NONE;
+	int cpu = smp_processor_id(), err = 0;
+	unsigned long flags;
+	bool is_active;
+
+	/*
+	 * When called from stop_machine_from_inactive_cpu(), irq might
+	 * already be disabled.  Save the state and restore it on exit.
+	 */
+	local_save_flags(flags);
+
+	if (!msdata->active_cpus)
+		is_active = cpu == cpumask_first(cpu_online_mask);
+	else
+		is_active = cpumask_test_cpu(cpu, msdata->active_cpus);
+
+	/* Simple state machine */
+	do {
+		/* Chill out and ensure we re-read multi_stop_state. */
+		cpu_relax();
+		if (msdata->state != curstate) {
+			curstate = msdata->state;
+			switch (curstate) {
+			case MULTI_STOP_DISABLE_IRQ:
+				local_irq_disable();
+				hard_irq_disable();
+				break;
+			case MULTI_STOP_RUN:
+				if (is_active)
+					err = msdata->fn(msdata->data);
+				break;
+			default:
+				break;
+			}
+			ack_state(msdata);
+		}
+	} while (curstate != MULTI_STOP_EXIT);
+
+	local_irq_restore(flags);
+	return err;
+}
+
+struct irq_cpu_stop_queue_work_info {
+	int cpu1;
+	int cpu2;
+	struct cpu_stop_work *work1;
+	struct cpu_stop_work *work2;
+};
+
+/*
+ * This function is always run with irqs and preemption disabled.
+ * This guarantees that both work1 and work2 get queued, before
+ * our local migrate thread gets the chance to preempt us.
+ */
+static void irq_cpu_stop_queue_work(void *arg)
+{
+	struct irq_cpu_stop_queue_work_info *info = arg;
+	cpu_stop_queue_work(info->cpu1, info->work1);
+	cpu_stop_queue_work(info->cpu2, info->work2);
+}
+
+/**
+ * stop_two_cpus - stops two cpus
+ * @cpu1: the cpu to stop
+ * @cpu2: the other cpu to stop
+ * @fn: function to execute
+ * @arg: argument to @fn
+ *
+ * Stops both the current and specified CPU and runs @fn on one of them.
+ *
+ * returns when both are completed.
+ */
+int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *arg)
+{
+	struct cpu_stop_done done;
+	struct cpu_stop_work work1, work2;
+	struct irq_cpu_stop_queue_work_info call_args;
+	struct multi_stop_data msdata;
+
+	preempt_disable();
+	msdata = (struct multi_stop_data){
+		.fn = fn,
+		.data = arg,
+		.num_threads = 2,
+		.active_cpus = cpumask_of(cpu1),
+	};
+
+	work1 = work2 = (struct cpu_stop_work){
+		.fn = multi_cpu_stop,
+		.arg = &msdata,
+		.done = &done
+	};
+
+	call_args = (struct irq_cpu_stop_queue_work_info){
+		.cpu1 = cpu1,
+		.cpu2 = cpu2,
+		.work1 = &work1,
+		.work2 = &work2,
+	};
+
+	cpu_stop_init_done(&done, 2);
+	set_state(&msdata, MULTI_STOP_PREPARE);
+
+	/*
+	 * If we observe both CPUs active we know _cpu_down() cannot yet have
+	 * queued its stop_machine works and therefore ours will get executed
+	 * first. Or its not either one of our CPUs that's getting unplugged,
+	 * in which case we don't care.
+	 *
+	 * This relies on the stopper workqueues to be FIFO.
+	 */
+	if (!cpu_active(cpu1) || !cpu_active(cpu2)) {
+		preempt_enable();
+		return -ENOENT;
+	}
+
+	lg_local_lock(&stop_cpus_lock);
+	/*
+	 * Queuing needs to be done by the lowest numbered CPU, to ensure
+	 * that works are always queued in the same order on every CPU.
+	 * This prevents deadlocks.
+	 */
+	smp_call_function_single(min(cpu1, cpu2),
+				 &irq_cpu_stop_queue_work,
+				 &call_args, 0);
+	lg_local_unlock(&stop_cpus_lock);
+	preempt_enable();
+
+	wait_for_completion(&done.completion);
+
+	return done.executed ? done.ret : -ENOENT;
+}
+
 /**
  * stop_one_cpu_nowait - stop a cpu but don't wait for completion
  * @cpu: cpu to stop
@@ -159,10 +346,10 @@
 	 * preempted by a stopper which might wait for other stoppers
 	 * to enter @fn which can lead to deadlock.
 	 */
-	preempt_disable();
+	lg_global_lock(&stop_cpus_lock);
 	for_each_cpu(cpu, cpumask)
 		cpu_stop_queue_work(cpu, &per_cpu(stop_cpus_work, cpu));
-	preempt_enable();
+	lg_global_unlock(&stop_cpus_lock);
 }
 
 static int __stop_cpus(const struct cpumask *cpumask,
@@ -359,98 +546,14 @@
 
 #ifdef CONFIG_STOP_MACHINE
 
-/* This controls the threads on each CPU. */
-enum stopmachine_state {
-	/* Dummy starting state for thread. */
-	STOPMACHINE_NONE,
-	/* Awaiting everyone to be scheduled. */
-	STOPMACHINE_PREPARE,
-	/* Disable interrupts. */
-	STOPMACHINE_DISABLE_IRQ,
-	/* Run the function */
-	STOPMACHINE_RUN,
-	/* Exit */
-	STOPMACHINE_EXIT,
-};
-
-struct stop_machine_data {
-	int			(*fn)(void *);
-	void			*data;
-	/* Like num_online_cpus(), but hotplug cpu uses us, so we need this. */
-	unsigned int		num_threads;
-	const struct cpumask	*active_cpus;
-
-	enum stopmachine_state	state;
-	atomic_t		thread_ack;
-};
-
-static void set_state(struct stop_machine_data *smdata,
-		      enum stopmachine_state newstate)
-{
-	/* Reset ack counter. */
-	atomic_set(&smdata->thread_ack, smdata->num_threads);
-	smp_wmb();
-	smdata->state = newstate;
-}
-
-/* Last one to ack a state moves to the next state. */
-static void ack_state(struct stop_machine_data *smdata)
-{
-	if (atomic_dec_and_test(&smdata->thread_ack))
-		set_state(smdata, smdata->state + 1);
-}
-
-/* This is the cpu_stop function which stops the CPU. */
-static int stop_machine_cpu_stop(void *data)
-{
-	struct stop_machine_data *smdata = data;
-	enum stopmachine_state curstate = STOPMACHINE_NONE;
-	int cpu = smp_processor_id(), err = 0;
-	unsigned long flags;
-	bool is_active;
-
-	/*
-	 * When called from stop_machine_from_inactive_cpu(), irq might
-	 * already be disabled.  Save the state and restore it on exit.
-	 */
-	local_save_flags(flags);
-
-	if (!smdata->active_cpus)
-		is_active = cpu == cpumask_first(cpu_online_mask);
-	else
-		is_active = cpumask_test_cpu(cpu, smdata->active_cpus);
-
-	/* Simple state machine */
-	do {
-		/* Chill out and ensure we re-read stopmachine_state. */
-		cpu_relax();
-		if (smdata->state != curstate) {
-			curstate = smdata->state;
-			switch (curstate) {
-			case STOPMACHINE_DISABLE_IRQ:
-				local_irq_disable();
-				hard_irq_disable();
-				break;
-			case STOPMACHINE_RUN:
-				if (is_active)
-					err = smdata->fn(smdata->data);
-				break;
-			default:
-				break;
-			}
-			ack_state(smdata);
-		}
-	} while (curstate != STOPMACHINE_EXIT);
-
-	local_irq_restore(flags);
-	return err;
-}
-
 int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus)
 {
-	struct stop_machine_data smdata = { .fn = fn, .data = data,
-					    .num_threads = num_online_cpus(),
-					    .active_cpus = cpus };
+	struct multi_stop_data msdata = {
+		.fn = fn,
+		.data = data,
+		.num_threads = num_online_cpus(),
+		.active_cpus = cpus,
+	};
 
 	if (!stop_machine_initialized) {
 		/*
@@ -461,7 +564,7 @@
 		unsigned long flags;
 		int ret;
 
-		WARN_ON_ONCE(smdata.num_threads != 1);
+		WARN_ON_ONCE(msdata.num_threads != 1);
 
 		local_irq_save(flags);
 		hard_irq_disable();
@@ -472,8 +575,8 @@
 	}
 
 	/* Set the initial state and stop all online cpus. */
-	set_state(&smdata, STOPMACHINE_PREPARE);
-	return stop_cpus(cpu_online_mask, stop_machine_cpu_stop, &smdata);
+	set_state(&msdata, MULTI_STOP_PREPARE);
+	return stop_cpus(cpu_online_mask, multi_cpu_stop, &msdata);
 }
 
 int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus)
@@ -513,25 +616,25 @@
 int stop_machine_from_inactive_cpu(int (*fn)(void *), void *data,
 				  const struct cpumask *cpus)
 {
-	struct stop_machine_data smdata = { .fn = fn, .data = data,
+	struct multi_stop_data msdata = { .fn = fn, .data = data,
 					    .active_cpus = cpus };
 	struct cpu_stop_done done;
 	int ret;
 
 	/* Local CPU must be inactive and CPU hotplug in progress. */
 	BUG_ON(cpu_active(raw_smp_processor_id()));
-	smdata.num_threads = num_active_cpus() + 1;	/* +1 for local */
+	msdata.num_threads = num_active_cpus() + 1;	/* +1 for local */
 
 	/* No proper task established and can't sleep - busy wait for lock. */
 	while (!mutex_trylock(&stop_cpus_mutex))
 		cpu_relax();
 
 	/* Schedule work on other CPUs and execute directly for local CPU */
-	set_state(&smdata, STOPMACHINE_PREPARE);
+	set_state(&msdata, MULTI_STOP_PREPARE);
 	cpu_stop_init_done(&done, num_active_cpus());
-	queue_stop_cpus_work(cpu_active_mask, stop_machine_cpu_stop, &smdata,
+	queue_stop_cpus_work(cpu_active_mask, multi_cpu_stop, &msdata,
 			     &done);
-	ret = stop_machine_cpu_stop(&smdata);
+	ret = multi_cpu_stop(&msdata);
 
 	/* Busy wait for completion. */
 	while (!completion_done(&done.completion))
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index b2f06f3..36547dd 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -190,7 +190,7 @@
 
 #ifdef CONFIG_MAGIC_SYSRQ
 /* Note: sysrq code uses it's own private copy */
-static int __sysrq_enabled = SYSRQ_DEFAULT_ENABLE;
+static int __sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE;
 
 static int sysrq_sysctl_handler(ctl_table *table, int write,
 				void __user *buffer, size_t *lenp,
@@ -371,13 +371,6 @@
 		.proc_handler	= proc_dointvec,
 	},
 	{
-		.procname	= "numa_balancing_scan_period_reset",
-		.data		= &sysctl_numa_balancing_scan_period_reset,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec,
-	},
-	{
 		.procname	= "numa_balancing_scan_period_max_ms",
 		.data		= &sysctl_numa_balancing_scan_period_max,
 		.maxlen		= sizeof(unsigned int),
@@ -391,6 +384,20 @@
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec,
 	},
+	{
+		.procname       = "numa_balancing_settle_count",
+		.data           = &sysctl_numa_balancing_settle_count,
+		.maxlen         = sizeof(unsigned int),
+		.mode           = 0644,
+		.proc_handler   = proc_dointvec,
+	},
+	{
+		.procname       = "numa_balancing_migrate_deferred",
+		.data           = &sysctl_numa_balancing_migrate_deferred,
+		.maxlen         = sizeof(unsigned int),
+		.mode           = 0644,
+		.proc_handler   = proc_dointvec,
+	},
 #endif /* CONFIG_NUMA_BALANCING */
 #endif /* CONFIG_SCHED_DEBUG */
 	{
@@ -1049,6 +1056,7 @@
 		.maxlen		= sizeof(sysctl_perf_event_sample_rate),
 		.mode		= 0644,
 		.proc_handler	= perf_proc_update_handler,
+		.extra1		= &one,
 	},
 	{
 		.procname	= "perf_cpu_time_max_percent",
diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig
index 2b62fe8..3ce6e8c 100644
--- a/kernel/time/Kconfig
+++ b/kernel/time/Kconfig
@@ -100,7 +100,7 @@
 	# RCU_USER_QS dependency
 	depends on HAVE_CONTEXT_TRACKING
 	# VIRT_CPU_ACCOUNTING_GEN dependency
-	depends on 64BIT
+	depends on HAVE_VIRT_CPU_ACCOUNTING_GEN
 	select NO_HZ_COMMON
 	select RCU_USER_QS
 	select RCU_NOCB_CPU
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index eec50fc..88c9c65 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -490,7 +490,7 @@
 	clockid_t baseid = alarm_bases[clock2alarm(which_clock)].base_clockid;
 
 	if (!alarmtimer_get_rtcdev())
-		return -ENOTSUPP;
+		return -EINVAL;
 
 	return hrtimer_get_res(baseid, tp);
 }
@@ -507,7 +507,7 @@
 	struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)];
 
 	if (!alarmtimer_get_rtcdev())
-		return -ENOTSUPP;
+		return -EINVAL;
 
 	*tp = ktime_to_timespec(base->gettime());
 	return 0;
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index 38959c8..086ad60 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -33,6 +33,54 @@
 	int res;
 };
 
+static u64 cev_delta2ns(unsigned long latch, struct clock_event_device *evt,
+			bool ismax)
+{
+	u64 clc = (u64) latch << evt->shift;
+	u64 rnd;
+
+	if (unlikely(!evt->mult)) {
+		evt->mult = 1;
+		WARN_ON(1);
+	}
+	rnd = (u64) evt->mult - 1;
+
+	/*
+	 * Upper bound sanity check. If the backwards conversion is
+	 * not equal latch, we know that the above shift overflowed.
+	 */
+	if ((clc >> evt->shift) != (u64)latch)
+		clc = ~0ULL;
+
+	/*
+	 * Scaled math oddities:
+	 *
+	 * For mult <= (1 << shift) we can safely add mult - 1 to
+	 * prevent integer rounding loss. So the backwards conversion
+	 * from nsec to device ticks will be correct.
+	 *
+	 * For mult > (1 << shift), i.e. device frequency is > 1GHz we
+	 * need to be careful. Adding mult - 1 will result in a value
+	 * which when converted back to device ticks can be larger
+	 * than latch by up to (mult - 1) >> shift. For the min_delta
+	 * calculation we still want to apply this in order to stay
+	 * above the minimum device ticks limit. For the upper limit
+	 * we would end up with a latch value larger than the upper
+	 * limit of the device, so we omit the add to stay below the
+	 * device upper boundary.
+	 *
+	 * Also omit the add if it would overflow the u64 boundary.
+	 */
+	if ((~0ULL - clc > rnd) &&
+	    (!ismax || evt->mult <= (1U << evt->shift)))
+		clc += rnd;
+
+	do_div(clc, evt->mult);
+
+	/* Deltas less than 1usec are pointless noise */
+	return clc > 1000 ? clc : 1000;
+}
+
 /**
  * clockevents_delta2ns - Convert a latch value (device ticks) to nanoseconds
  * @latch:	value to convert
@@ -42,20 +90,7 @@
  */
 u64 clockevent_delta2ns(unsigned long latch, struct clock_event_device *evt)
 {
-	u64 clc = (u64) latch << evt->shift;
-
-	if (unlikely(!evt->mult)) {
-		evt->mult = 1;
-		WARN_ON(1);
-	}
-
-	do_div(clc, evt->mult);
-	if (clc < 1000)
-		clc = 1000;
-	if (clc > KTIME_MAX)
-		clc = KTIME_MAX;
-
-	return clc;
+	return cev_delta2ns(latch, evt, false);
 }
 EXPORT_SYMBOL_GPL(clockevent_delta2ns);
 
@@ -380,8 +415,8 @@
 		sec = 600;
 
 	clockevents_calc_mult_shift(dev, freq, sec);
-	dev->min_delta_ns = clockevent_delta2ns(dev->min_delta_ticks, dev);
-	dev->max_delta_ns = clockevent_delta2ns(dev->max_delta_ticks, dev);
+	dev->min_delta_ns = cev_delta2ns(dev->min_delta_ticks, dev, false);
+	dev->max_delta_ns = cev_delta2ns(dev->max_delta_ticks, dev, true);
 }
 
 /**
@@ -584,7 +619,7 @@
 				     const char *buf, size_t count)
 {
 	char name[CS_NAME_LEN];
-	size_t ret = sysfs_get_uname(buf, name, count);
+	ssize_t ret = sysfs_get_uname(buf, name, count);
 	struct clock_event_device *ce;
 
 	if (ret < 0)
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 50a8736..ba3e502 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -479,6 +479,7 @@
 static inline void clocksource_resume_watchdog(void) { }
 static inline int __clocksource_watchdog_kthread(void) { return 0; }
 static bool clocksource_is_watchdog(struct clocksource *cs) { return false; }
+void clocksource_mark_unstable(struct clocksource *cs) { }
 
 #endif /* CONFIG_CLOCKSOURCE_WATCHDOG */
 
@@ -537,40 +538,55 @@
 }
 
 /**
- * clocksource_max_deferment - Returns max time the clocksource can be deferred
- * @cs:         Pointer to clocksource
- *
+ * clocks_calc_max_nsecs - Returns maximum nanoseconds that can be converted
+ * @mult:	cycle to nanosecond multiplier
+ * @shift:	cycle to nanosecond divisor (power of two)
+ * @maxadj:	maximum adjustment value to mult (~11%)
+ * @mask:	bitmask for two's complement subtraction of non 64 bit counters
  */
-static u64 clocksource_max_deferment(struct clocksource *cs)
+u64 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask)
 {
 	u64 max_nsecs, max_cycles;
 
 	/*
 	 * Calculate the maximum number of cycles that we can pass to the
 	 * cyc2ns function without overflowing a 64-bit signed result. The
-	 * maximum number of cycles is equal to ULLONG_MAX/(cs->mult+cs->maxadj)
+	 * maximum number of cycles is equal to ULLONG_MAX/(mult+maxadj)
 	 * which is equivalent to the below.
-	 * max_cycles < (2^63)/(cs->mult + cs->maxadj)
-	 * max_cycles < 2^(log2((2^63)/(cs->mult + cs->maxadj)))
-	 * max_cycles < 2^(log2(2^63) - log2(cs->mult + cs->maxadj))
-	 * max_cycles < 2^(63 - log2(cs->mult + cs->maxadj))
-	 * max_cycles < 1 << (63 - log2(cs->mult + cs->maxadj))
+	 * max_cycles < (2^63)/(mult + maxadj)
+	 * max_cycles < 2^(log2((2^63)/(mult + maxadj)))
+	 * max_cycles < 2^(log2(2^63) - log2(mult + maxadj))
+	 * max_cycles < 2^(63 - log2(mult + maxadj))
+	 * max_cycles < 1 << (63 - log2(mult + maxadj))
 	 * Please note that we add 1 to the result of the log2 to account for
 	 * any rounding errors, ensure the above inequality is satisfied and
 	 * no overflow will occur.
 	 */
-	max_cycles = 1ULL << (63 - (ilog2(cs->mult + cs->maxadj) + 1));
+	max_cycles = 1ULL << (63 - (ilog2(mult + maxadj) + 1));
 
 	/*
 	 * The actual maximum number of cycles we can defer the clocksource is
-	 * determined by the minimum of max_cycles and cs->mask.
+	 * determined by the minimum of max_cycles and mask.
 	 * Note: Here we subtract the maxadj to make sure we don't sleep for
 	 * too long if there's a large negative adjustment.
 	 */
-	max_cycles = min_t(u64, max_cycles, (u64) cs->mask);
-	max_nsecs = clocksource_cyc2ns(max_cycles, cs->mult - cs->maxadj,
-					cs->shift);
+	max_cycles = min(max_cycles, mask);
+	max_nsecs = clocksource_cyc2ns(max_cycles, mult - maxadj, shift);
 
+	return max_nsecs;
+}
+
+/**
+ * clocksource_max_deferment - Returns max time the clocksource can be deferred
+ * @cs:         Pointer to clocksource
+ *
+ */
+static u64 clocksource_max_deferment(struct clocksource *cs)
+{
+	u64 max_nsecs;
+
+	max_nsecs = clocks_calc_max_nsecs(cs->mult, cs->shift, cs->maxadj,
+					  cs->mask);
 	/*
 	 * To ensure that the clocksource does not wrap whilst we are idle,
 	 * limit the time the clocksource can be deferred by 12.5%. Please
@@ -893,7 +909,7 @@
 	return count;
 }
 
-size_t sysfs_get_uname(const char *buf, char *dst, size_t cnt)
+ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt)
 {
 	size_t ret = cnt;
 
@@ -924,7 +940,7 @@
 					  struct device_attribute *attr,
 					  const char *buf, size_t count)
 {
-	size_t ret;
+	ssize_t ret;
 
 	mutex_lock(&clocksource_mutex);
 
@@ -952,7 +968,7 @@
 {
 	struct clocksource *cs;
 	char name[CS_NAME_LEN];
-	size_t ret;
+	ssize_t ret;
 
 	ret = sysfs_get_uname(buf, name, count);
 	if (ret < 0)
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index bb22151..af8d1d4 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -475,6 +475,7 @@
 	 * called as close as possible to 500 ms before the new second starts.
 	 * This code is run on a timer.  If the clock is set, that timer
 	 * may not expire at the correct time.  Thus, we adjust...
+	 * We want the clock to be within a couple of ticks from the target.
 	 */
 	if (!ntp_synced()) {
 		/*
@@ -485,7 +486,7 @@
 	}
 
 	getnstimeofday(&now);
-	if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2) {
+	if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec * 5) {
 		struct timespec adjust = now;
 
 		fail = -ENODEV;
diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c
index 0b479a6..68b7993 100644
--- a/kernel/time/sched_clock.c
+++ b/kernel/time/sched_clock.c
@@ -8,25 +8,28 @@
 #include <linux/clocksource.h>
 #include <linux/init.h>
 #include <linux/jiffies.h>
+#include <linux/ktime.h>
 #include <linux/kernel.h>
 #include <linux/moduleparam.h>
 #include <linux/sched.h>
 #include <linux/syscore_ops.h>
-#include <linux/timer.h>
+#include <linux/hrtimer.h>
 #include <linux/sched_clock.h>
+#include <linux/seqlock.h>
+#include <linux/bitops.h>
 
 struct clock_data {
+	ktime_t wrap_kt;
 	u64 epoch_ns;
-	u32 epoch_cyc;
-	u32 epoch_cyc_copy;
+	u64 epoch_cyc;
+	seqcount_t seq;
 	unsigned long rate;
 	u32 mult;
 	u32 shift;
 	bool suspended;
 };
 
-static void sched_clock_poll(unsigned long wrap_ticks);
-static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0);
+static struct hrtimer sched_clock_timer;
 static int irqtime = -1;
 
 core_param(irqtime, irqtime, int, 0400);
@@ -35,42 +38,46 @@
 	.mult	= NSEC_PER_SEC / HZ,
 };
 
-static u32 __read_mostly sched_clock_mask = 0xffffffff;
+static u64 __read_mostly sched_clock_mask;
 
-static u32 notrace jiffy_sched_clock_read(void)
+static u64 notrace jiffy_sched_clock_read(void)
 {
-	return (u32)(jiffies - INITIAL_JIFFIES);
+	/*
+	 * We don't need to use get_jiffies_64 on 32-bit arches here
+	 * because we register with BITS_PER_LONG
+	 */
+	return (u64)(jiffies - INITIAL_JIFFIES);
 }
 
-static u32 __read_mostly (*read_sched_clock)(void) = jiffy_sched_clock_read;
+static u32 __read_mostly (*read_sched_clock_32)(void);
+
+static u64 notrace read_sched_clock_32_wrapper(void)
+{
+	return read_sched_clock_32();
+}
+
+static u64 __read_mostly (*read_sched_clock)(void) = jiffy_sched_clock_read;
 
 static inline u64 notrace cyc_to_ns(u64 cyc, u32 mult, u32 shift)
 {
 	return (cyc * mult) >> shift;
 }
 
-static unsigned long long notrace sched_clock_32(void)
+unsigned long long notrace sched_clock(void)
 {
 	u64 epoch_ns;
-	u32 epoch_cyc;
-	u32 cyc;
+	u64 epoch_cyc;
+	u64 cyc;
+	unsigned long seq;
 
 	if (cd.suspended)
 		return cd.epoch_ns;
 
-	/*
-	 * Load the epoch_cyc and epoch_ns atomically.  We do this by
-	 * ensuring that we always write epoch_cyc, epoch_ns and
-	 * epoch_cyc_copy in strict order, and read them in strict order.
-	 * If epoch_cyc and epoch_cyc_copy are not equal, then we're in
-	 * the middle of an update, and we should repeat the load.
-	 */
 	do {
+		seq = read_seqcount_begin(&cd.seq);
 		epoch_cyc = cd.epoch_cyc;
-		smp_rmb();
 		epoch_ns = cd.epoch_ns;
-		smp_rmb();
-	} while (epoch_cyc != cd.epoch_cyc_copy);
+	} while (read_seqcount_retry(&cd.seq, seq));
 
 	cyc = read_sched_clock();
 	cyc = (cyc - epoch_cyc) & sched_clock_mask;
@@ -83,49 +90,46 @@
 static void notrace update_sched_clock(void)
 {
 	unsigned long flags;
-	u32 cyc;
+	u64 cyc;
 	u64 ns;
 
 	cyc = read_sched_clock();
 	ns = cd.epoch_ns +
 		cyc_to_ns((cyc - cd.epoch_cyc) & sched_clock_mask,
 			  cd.mult, cd.shift);
-	/*
-	 * Write epoch_cyc and epoch_ns in a way that the update is
-	 * detectable in cyc_to_fixed_sched_clock().
-	 */
+
 	raw_local_irq_save(flags);
-	cd.epoch_cyc_copy = cyc;
-	smp_wmb();
+	write_seqcount_begin(&cd.seq);
 	cd.epoch_ns = ns;
-	smp_wmb();
 	cd.epoch_cyc = cyc;
+	write_seqcount_end(&cd.seq);
 	raw_local_irq_restore(flags);
 }
 
-static void sched_clock_poll(unsigned long wrap_ticks)
+static enum hrtimer_restart sched_clock_poll(struct hrtimer *hrt)
 {
-	mod_timer(&sched_clock_timer, round_jiffies(jiffies + wrap_ticks));
 	update_sched_clock();
+	hrtimer_forward_now(hrt, cd.wrap_kt);
+	return HRTIMER_RESTART;
 }
 
-void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
+void __init sched_clock_register(u64 (*read)(void), int bits,
+				 unsigned long rate)
 {
-	unsigned long r, w;
+	unsigned long r;
 	u64 res, wrap;
 	char r_unit;
 
 	if (cd.rate > rate)
 		return;
 
-	BUG_ON(bits > 32);
 	WARN_ON(!irqs_disabled());
 	read_sched_clock = read;
-	sched_clock_mask = (1ULL << bits) - 1;
+	sched_clock_mask = CLOCKSOURCE_MASK(bits);
 	cd.rate = rate;
 
 	/* calculate the mult/shift to convert counter ticks to ns. */
-	clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 0);
+	clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 3600);
 
 	r = rate;
 	if (r >= 4000000) {
@@ -138,20 +142,14 @@
 		r_unit = ' ';
 
 	/* calculate how many ns until we wrap */
-	wrap = cyc_to_ns((1ULL << bits) - 1, cd.mult, cd.shift);
-	do_div(wrap, NSEC_PER_MSEC);
-	w = wrap;
+	wrap = clocks_calc_max_nsecs(cd.mult, cd.shift, 0, sched_clock_mask);
+	cd.wrap_kt = ns_to_ktime(wrap - (wrap >> 3));
 
 	/* calculate the ns resolution of this counter */
 	res = cyc_to_ns(1ULL, cd.mult, cd.shift);
-	pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lums\n",
-		bits, r, r_unit, res, w);
+	pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lluns\n",
+		bits, r, r_unit, res, wrap);
 
-	/*
-	 * Start the timer to keep sched_clock() properly updated and
-	 * sets the initial epoch.
-	 */
-	sched_clock_timer.data = msecs_to_jiffies(w - (w / 10));
 	update_sched_clock();
 
 	/*
@@ -166,11 +164,10 @@
 	pr_debug("Registered %pF as sched_clock source\n", read);
 }
 
-unsigned long long __read_mostly (*sched_clock_func)(void) = sched_clock_32;
-
-unsigned long long notrace sched_clock(void)
+void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
 {
-	return sched_clock_func();
+	read_sched_clock_32 = read;
+	sched_clock_register(read_sched_clock_32_wrapper, bits, rate);
 }
 
 void __init sched_clock_postinit(void)
@@ -180,14 +177,22 @@
 	 * make it the final one one.
 	 */
 	if (read_sched_clock == jiffy_sched_clock_read)
-		setup_sched_clock(jiffy_sched_clock_read, 32, HZ);
+		sched_clock_register(jiffy_sched_clock_read, BITS_PER_LONG, HZ);
 
-	sched_clock_poll(sched_clock_timer.data);
+	update_sched_clock();
+
+	/*
+	 * Start the timer to keep sched_clock() properly updated and
+	 * sets the initial epoch.
+	 */
+	hrtimer_init(&sched_clock_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	sched_clock_timer.function = sched_clock_poll;
+	hrtimer_start(&sched_clock_timer, cd.wrap_kt, HRTIMER_MODE_REL);
 }
 
 static int sched_clock_suspend(void)
 {
-	sched_clock_poll(sched_clock_timer.data);
+	sched_clock_poll(&sched_clock_timer);
 	cd.suspended = true;
 	return 0;
 }
@@ -195,7 +200,6 @@
 static void sched_clock_resume(void)
 {
 	cd.epoch_cyc = read_sched_clock();
-	cd.epoch_cyc_copy = cd.epoch_cyc;
 	cd.suspended = false;
 }
 
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index 218bcb5..9532690 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -70,6 +70,7 @@
 					struct clock_event_device *newdev)
 {
 	if ((newdev->features & CLOCK_EVT_FEAT_DUMMY) ||
+	    (newdev->features & CLOCK_EVT_FEAT_PERCPU) ||
 	    (newdev->features & CLOCK_EVT_FEAT_C3STOP))
 		return false;
 
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index bc906ca..18e71f7 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -31,7 +31,7 @@
 
 extern void clockevents_shutdown(struct clock_event_device *dev);
 
-extern size_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
+extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
 
 /*
  * NO_HZ / high resolution timer shared code
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 947ba25..3abf534 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1613,9 +1613,10 @@
  * ktime_get_update_offsets - hrtimer helper
  * @offs_real:	pointer to storage for monotonic -> realtime offset
  * @offs_boot:	pointer to storage for monotonic -> boottime offset
+ * @offs_tai:	pointer to storage for monotonic -> clock tai offset
  *
  * Returns current monotonic time and updates the offsets
- * Called from hrtimer_interupt() or retrigger_next_event()
+ * Called from hrtimer_interrupt() or retrigger_next_event()
  */
 ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot,
 							ktime_t *offs_tai)
diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c
index 0b537f2..1fb08f2 100644
--- a/kernel/time/timer_stats.c
+++ b/kernel/time/timer_stats.c
@@ -298,15 +298,15 @@
 	period = ktime_to_timespec(time);
 	ms = period.tv_nsec / 1000000;
 
-	seq_puts(m, "Timer Stats Version: v0.2\n");
+	seq_puts(m, "Timer Stats Version: v0.3\n");
 	seq_printf(m, "Sample period: %ld.%03ld s\n", period.tv_sec, ms);
 	if (atomic_read(&overflow_count))
-		seq_printf(m, "Overflow: %d entries\n",
-			atomic_read(&overflow_count));
+		seq_printf(m, "Overflow: %d entries\n", atomic_read(&overflow_count));
+	seq_printf(m, "Collection: %s\n", timer_stats_active ? "active" : "inactive");
 
 	for (i = 0; i < nr_entries; i++) {
 		entry = entries + i;
- 		if (entry->timer_flag & TIMER_STATS_FLAG_DEFERRABLE) {
+		if (entry->timer_flag & TIMER_STATS_FLAG_DEFERRABLE) {
 			seq_printf(m, "%4luD, %5d %-16s ",
 				entry->count, entry->pid, entry->comm);
 		} else {
diff --git a/kernel/timer.c b/kernel/timer.c
index 4296d13..6582b82 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1092,7 +1092,7 @@
 static void call_timer_fn(struct timer_list *timer, void (*fn)(unsigned long),
 			  unsigned long data)
 {
-	int preempt_count = preempt_count();
+	int count = preempt_count();
 
 #ifdef CONFIG_LOCKDEP
 	/*
@@ -1119,16 +1119,16 @@
 
 	lock_map_release(&lockdep_map);
 
-	if (preempt_count != preempt_count()) {
+	if (count != preempt_count()) {
 		WARN_ONCE(1, "timer: %pF preempt leak: %08x -> %08x\n",
-			  fn, preempt_count, preempt_count());
+			  fn, count, preempt_count());
 		/*
 		 * Restore the preempt count. That gives us a decent
 		 * chance to survive and extract information. If the
 		 * callback kept a lock held, bad luck, but not worse
 		 * than the BUG() we had.
 		 */
-		preempt_count() = preempt_count;
+		preempt_count_set(count);
 	}
 }
 
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 7974ba2..d9fea7d 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1509,7 +1509,8 @@
 #endif
 		((pc & HARDIRQ_MASK) ? TRACE_FLAG_HARDIRQ : 0) |
 		((pc & SOFTIRQ_MASK) ? TRACE_FLAG_SOFTIRQ : 0) |
-		(need_resched() ? TRACE_FLAG_NEED_RESCHED : 0);
+		(tif_need_resched() ? TRACE_FLAG_NEED_RESCHED : 0) |
+		(test_preempt_need_resched() ? TRACE_FLAG_PREEMPT_RESCHED : 0);
 }
 EXPORT_SYMBOL_GPL(tracing_generic_entry_update);
 
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 10c86fb..73d08aa 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -124,6 +124,7 @@
 	TRACE_FLAG_NEED_RESCHED		= 0x04,
 	TRACE_FLAG_HARDIRQ		= 0x08,
 	TRACE_FLAG_SOFTIRQ		= 0x10,
+	TRACE_FLAG_PREEMPT_RESCHED	= 0x20,
 };
 
 #define TRACE_BUF_SIZE		1024
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
index 80c36bc..78e27e3 100644
--- a/kernel/trace/trace_event_perf.c
+++ b/kernel/trace/trace_event_perf.c
@@ -26,7 +26,7 @@
 {
 	/* The ftrace function trace is allowed only for root. */
 	if (ftrace_event_is_function(tp_event) &&
-	    perf_paranoid_kernel() && !capable(CAP_SYS_ADMIN))
+	    perf_paranoid_tracepoint_raw() && !capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
 	/* No tracing, just counting, so no obvious leak */
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
index 34e7cba..ed32284 100644
--- a/kernel/trace/trace_output.c
+++ b/kernel/trace/trace_output.c
@@ -618,8 +618,23 @@
 		(entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
 		(entry->flags & TRACE_FLAG_IRQS_NOSUPPORT) ? 'X' :
 		'.';
-	need_resched =
-		(entry->flags & TRACE_FLAG_NEED_RESCHED) ? 'N' : '.';
+
+	switch (entry->flags & (TRACE_FLAG_NEED_RESCHED |
+				TRACE_FLAG_PREEMPT_RESCHED)) {
+	case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_PREEMPT_RESCHED:
+		need_resched = 'N';
+		break;
+	case TRACE_FLAG_NEED_RESCHED:
+		need_resched = 'n';
+		break;
+	case TRACE_FLAG_PREEMPT_RESCHED:
+		need_resched = 'p';
+		break;
+	default:
+		need_resched = '.';
+		break;
+	}
+
 	hardsoft_irq =
 		(hardirq && softirq) ? 'H' :
 		hardirq ? 'h' :
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 06344d98..ebef88f 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -312,6 +312,15 @@
 	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
 	  unless you really know what this hack does.
 
+config MAGIC_SYSRQ_DEFAULT_ENABLE
+	hex "Enable magic SysRq key functions by default"
+	depends on MAGIC_SYSRQ
+	default 0x1
+	help
+	  Specifies which SysRq key functions are enabled by default.
+	  This may be set to 1 or 0 to enable or disable them all, or
+	  to a bitmask as described in Documentation/sysrq.txt.
+
 config DEBUG_KERNEL
 	bool "Kernel debugging"
 	help
@@ -983,7 +992,7 @@
 
 config DEBUG_KOBJECT_RELEASE
 	bool "kobject release debugging"
-	depends on DEBUG_KERNEL
+	depends on DEBUG_OBJECTS_TIMERS
 	help
 	  kobjects are reference counted objects.  This means that their
 	  last reference count put is not predictable, and the kobject can
diff --git a/lib/kobject.c b/lib/kobject.c
index 669bf19..5b4b888 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -13,11 +13,30 @@
  */
 
 #include <linux/kobject.h>
+#include <linux/kobj_completion.h>
 #include <linux/string.h>
 #include <linux/export.h>
 #include <linux/stat.h>
 #include <linux/slab.h>
 
+/**
+ * kobject_namespace - return @kobj's namespace tag
+ * @kobj: kobject in question
+ *
+ * Returns namespace tag of @kobj if its parent has namespace ops enabled
+ * and thus @kobj should have a namespace tag associated with it.  Returns
+ * %NULL otherwise.
+ */
+const void *kobject_namespace(struct kobject *kobj)
+{
+	const struct kobj_ns_type_operations *ns_ops = kobj_ns_ops(kobj);
+
+	if (!ns_ops || ns_ops->type == KOBJ_NS_TYPE_NONE)
+		return NULL;
+
+	return kobj->ktype->namespace(kobj);
+}
+
 /*
  * populate_dir - populate directory with attributes.
  * @kobj: object we're working on.
@@ -46,13 +65,21 @@
 
 static int create_dir(struct kobject *kobj)
 {
-	int error = 0;
-	error = sysfs_create_dir(kobj);
+	int error;
+
+	error = sysfs_create_dir_ns(kobj, kobject_namespace(kobj));
 	if (!error) {
 		error = populate_dir(kobj);
 		if (error)
 			sysfs_remove_dir(kobj);
 	}
+
+	/*
+	 * @kobj->sd may be deleted by an ancestor going away.  Hold an
+	 * extra reference so that it stays until @kobj is gone.
+	 */
+	sysfs_get(kobj->sd);
+
 	return error;
 }
 
@@ -428,7 +455,7 @@
 		goto out;
 	}
 
-	error = sysfs_rename_dir(kobj, new_name);
+	error = sysfs_rename_dir_ns(kobj, new_name, kobject_namespace(kobj));
 	if (error)
 		goto out;
 
@@ -472,6 +499,7 @@
 		if (kobj->kset)
 			new_parent = kobject_get(&kobj->kset->kobj);
 	}
+
 	/* old object path */
 	devpath = kobject_get_path(kobj, GFP_KERNEL);
 	if (!devpath) {
@@ -486,7 +514,7 @@
 	sprintf(devpath_string, "DEVPATH_OLD=%s", devpath);
 	envp[0] = devpath_string;
 	envp[1] = NULL;
-	error = sysfs_move_dir(kobj, new_parent);
+	error = sysfs_move_dir_ns(kobj, new_parent, kobject_namespace(kobj));
 	if (error)
 		goto out;
 	old_parent = kobj->parent;
@@ -508,10 +536,15 @@
  */
 void kobject_del(struct kobject *kobj)
 {
+	struct sysfs_dirent *sd;
+
 	if (!kobj)
 		return;
 
+	sd = kobj->sd;
 	sysfs_remove_dir(kobj);
+	sysfs_put(sd);
+
 	kobj->state_in_sysfs = 0;
 	kobj_kset_leave(kobj);
 	kobject_put(kobj->parent);
@@ -592,7 +625,7 @@
 {
 	struct kobject *kobj = container_of(kref, struct kobject, kref);
 #ifdef CONFIG_DEBUG_KOBJECT_RELEASE
-	pr_debug("kobject: '%s' (%p): %s, parent %p (delayed)\n",
+	pr_info("kobject: '%s' (%p): %s, parent %p (delayed)\n",
 		 kobject_name(kobj), kobj, __func__, kobj->parent);
 	INIT_DELAYED_WORK(&kobj->release, kobject_delayed_cleanup);
 	schedule_delayed_work(&kobj->release, HZ);
@@ -727,6 +760,55 @@
 };
 
 /**
+ * kobj_completion_init - initialize a kobj_completion object.
+ * @kc: kobj_completion
+ * @ktype: type of kobject to initialize
+ *
+ * kobj_completion structures can be embedded within structures with different
+ * lifetime rules.  During the release of the enclosing object, we can
+ * wait on the release of the kobject so that we don't free it while it's
+ * still busy.
+ */
+void kobj_completion_init(struct kobj_completion *kc, struct kobj_type *ktype)
+{
+	init_completion(&kc->kc_unregister);
+	kobject_init(&kc->kc_kobj, ktype);
+}
+EXPORT_SYMBOL_GPL(kobj_completion_init);
+
+/**
+ * kobj_completion_release - release a kobj_completion object
+ * @kobj: kobject embedded in kobj_completion
+ *
+ * Used with kobject_release to notify waiters that the kobject has been
+ * released.
+ */
+void kobj_completion_release(struct kobject *kobj)
+{
+	struct kobj_completion *kc = kobj_to_kobj_completion(kobj);
+	complete(&kc->kc_unregister);
+}
+EXPORT_SYMBOL_GPL(kobj_completion_release);
+
+/**
+ * kobj_completion_del_and_wait - release the kobject and wait for it
+ * @kc: kobj_completion object to release
+ *
+ * Delete the kobject from sysfs and drop the reference count.  Then wait
+ * until any other outstanding references are also dropped.  This routine
+ * is only necessary once other references may have been taken on the
+ * kobject.  Typically this happens when the kobject has been published
+ * to sysfs via kobject_add.
+ */
+void kobj_completion_del_and_wait(struct kobj_completion *kc)
+{
+	kobject_del(&kc->kc_kobj);
+	kobject_put(&kc->kc_kobj);
+	wait_for_completion(&kc->kc_unregister);
+}
+EXPORT_SYMBOL_GPL(kobj_completion_del_and_wait);
+
+/**
  * kset_register - initialize and add a kset.
  * @k: kset.
  */
diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c
index 6dc09d8..872a15a 100644
--- a/lib/locking-selftest.c
+++ b/lib/locking-selftest.c
@@ -1002,7 +1002,7 @@
 	 * Some tests (e.g. double-unlock) might corrupt the preemption
 	 * count, so restore it:
 	 */
-	preempt_count() = saved_preempt_count;
+	preempt_count_set(saved_preempt_count);
 #ifdef CONFIG_TRACE_IRQFLAGS
 	if (softirq_count())
 		current->softirqs_enabled = 0;
diff --git a/lib/lockref.c b/lib/lockref.c
index 6f9d434..af6e95d 100644
--- a/lib/lockref.c
+++ b/lib/lockref.c
@@ -153,6 +153,7 @@
 	assert_spin_locked(&lockref->lock);
 	lockref->count = -128;
 }
+EXPORT_SYMBOL(lockref_mark_dead);
 
 /**
  * lockref_get_not_dead - Increments count unless the ref is dead
diff --git a/lib/percpu-refcount.c b/lib/percpu-refcount.c
index 7deeb62..1a53d49 100644
--- a/lib/percpu-refcount.c
+++ b/lib/percpu-refcount.c
@@ -53,6 +53,7 @@
 	ref->release = release;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(percpu_ref_init);
 
 /**
  * percpu_ref_cancel_init - cancel percpu_ref_init()
@@ -84,6 +85,7 @@
 		free_percpu(ref->pcpu_count);
 	}
 }
+EXPORT_SYMBOL_GPL(percpu_ref_cancel_init);
 
 static void percpu_ref_kill_rcu(struct rcu_head *rcu)
 {
@@ -156,3 +158,4 @@
 
 	call_rcu_sched(&ref->rcu, percpu_ref_kill_rcu);
 }
+EXPORT_SYMBOL_GPL(percpu_ref_kill_and_confirm);
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index a685c8a..d16fa29 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -577,7 +577,8 @@
 		miter->__offset += miter->consumed;
 		miter->__remaining -= miter->consumed;
 
-		if (miter->__flags & SG_MITER_TO_SG)
+		if ((miter->__flags & SG_MITER_TO_SG) &&
+		    !PageSlab(miter->page))
 			flush_kernel_dcache_page(miter->page);
 
 		if (miter->__flags & SG_MITER_ATOMIC) {
diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c
index 4c0d0e5..04abe53 100644
--- a/lib/smp_processor_id.c
+++ b/lib/smp_processor_id.c
@@ -9,10 +9,9 @@
 
 notrace unsigned int debug_smp_processor_id(void)
 {
-	unsigned long preempt_count = preempt_count();
 	int this_cpu = raw_smp_processor_id();
 
-	if (likely(preempt_count))
+	if (likely(preempt_count()))
 		goto out;
 
 	if (irqs_disabled())
diff --git a/mm/filemap.c b/mm/filemap.c
index 1e6aec4..ae4846f 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1616,7 +1616,6 @@
 	struct inode *inode = mapping->host;
 	pgoff_t offset = vmf->pgoff;
 	struct page *page;
-	bool memcg_oom;
 	pgoff_t size;
 	int ret = 0;
 
@@ -1625,11 +1624,7 @@
 		return VM_FAULT_SIGBUS;
 
 	/*
-	 * Do we have something in the page cache already?  Either
-	 * way, try readahead, but disable the memcg OOM killer for it
-	 * as readahead is optional and no errors are propagated up
-	 * the fault stack.  The OOM killer is enabled while trying to
-	 * instantiate the faulting page individually below.
+	 * Do we have something in the page cache already?
 	 */
 	page = find_get_page(mapping, offset);
 	if (likely(page) && !(vmf->flags & FAULT_FLAG_TRIED)) {
@@ -1637,14 +1632,10 @@
 		 * We found the page, so try async readahead before
 		 * waiting for the lock.
 		 */
-		memcg_oom = mem_cgroup_toggle_oom(false);
 		do_async_mmap_readahead(vma, ra, file, page, offset);
-		mem_cgroup_toggle_oom(memcg_oom);
 	} else if (!page) {
 		/* No page in the page cache at all */
-		memcg_oom = mem_cgroup_toggle_oom(false);
 		do_sync_mmap_readahead(vma, ra, file, offset);
-		mem_cgroup_toggle_oom(memcg_oom);
 		count_vm_event(PGMAJFAULT);
 		mem_cgroup_count_vm_event(vma->vm_mm, PGMAJFAULT);
 		ret = VM_FAULT_MAJOR;
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 7489884..2612f60 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1278,64 +1278,105 @@
 int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
 				unsigned long addr, pmd_t pmd, pmd_t *pmdp)
 {
+	struct anon_vma *anon_vma = NULL;
 	struct page *page;
 	unsigned long haddr = addr & HPAGE_PMD_MASK;
-	int target_nid;
-	int current_nid = -1;
-	bool migrated;
+	int page_nid = -1, this_nid = numa_node_id();
+	int target_nid, last_cpupid = -1;
+	bool page_locked;
+	bool migrated = false;
+	int flags = 0;
 
 	spin_lock(&mm->page_table_lock);
 	if (unlikely(!pmd_same(pmd, *pmdp)))
 		goto out_unlock;
 
 	page = pmd_page(pmd);
-	get_page(page);
-	current_nid = page_to_nid(page);
+	BUG_ON(is_huge_zero_page(page));
+	page_nid = page_to_nid(page);
+	last_cpupid = page_cpupid_last(page);
 	count_vm_numa_event(NUMA_HINT_FAULTS);
-	if (current_nid == numa_node_id())
+	if (page_nid == this_nid) {
 		count_vm_numa_event(NUMA_HINT_FAULTS_LOCAL);
-
-	target_nid = mpol_misplaced(page, vma, haddr);
-	if (target_nid == -1) {
-		put_page(page);
-		goto clear_pmdnuma;
+		flags |= TNF_FAULT_LOCAL;
 	}
 
-	/* Acquire the page lock to serialise THP migrations */
-	spin_unlock(&mm->page_table_lock);
-	lock_page(page);
+	/*
+	 * Avoid grouping on DSO/COW pages in specific and RO pages
+	 * in general, RO pages shouldn't hurt as much anyway since
+	 * they can be in shared cache state.
+	 */
+	if (!pmd_write(pmd))
+		flags |= TNF_NO_GROUP;
 
-	/* Confirm the PTE did not while locked */
+	/*
+	 * Acquire the page lock to serialise THP migrations but avoid dropping
+	 * page_table_lock if at all possible
+	 */
+	page_locked = trylock_page(page);
+	target_nid = mpol_misplaced(page, vma, haddr);
+	if (target_nid == -1) {
+		/* If the page was locked, there are no parallel migrations */
+		if (page_locked)
+			goto clear_pmdnuma;
+
+		/*
+		 * Otherwise wait for potential migrations and retry. We do
+		 * relock and check_same as the page may no longer be mapped.
+		 * As the fault is being retried, do not account for it.
+		 */
+		spin_unlock(&mm->page_table_lock);
+		wait_on_page_locked(page);
+		page_nid = -1;
+		goto out;
+	}
+
+	/* Page is misplaced, serialise migrations and parallel THP splits */
+	get_page(page);
+	spin_unlock(&mm->page_table_lock);
+	if (!page_locked)
+		lock_page(page);
+	anon_vma = page_lock_anon_vma_read(page);
+
+	/* Confirm the PMD did not change while page_table_lock was released */
 	spin_lock(&mm->page_table_lock);
 	if (unlikely(!pmd_same(pmd, *pmdp))) {
 		unlock_page(page);
 		put_page(page);
+		page_nid = -1;
 		goto out_unlock;
 	}
-	spin_unlock(&mm->page_table_lock);
 
-	/* Migrate the THP to the requested node */
+	/*
+	 * Migrate the THP to the requested node, returns with page unlocked
+	 * and pmd_numa cleared.
+	 */
+	spin_unlock(&mm->page_table_lock);
 	migrated = migrate_misplaced_transhuge_page(mm, vma,
 				pmdp, pmd, addr, page, target_nid);
-	if (!migrated)
-		goto check_same;
+	if (migrated) {
+		flags |= TNF_MIGRATED;
+		page_nid = target_nid;
+	}
 
-	task_numa_fault(target_nid, HPAGE_PMD_NR, true);
-	return 0;
-
-check_same:
-	spin_lock(&mm->page_table_lock);
-	if (unlikely(!pmd_same(pmd, *pmdp)))
-		goto out_unlock;
+	goto out;
 clear_pmdnuma:
+	BUG_ON(!PageLocked(page));
 	pmd = pmd_mknonnuma(pmd);
 	set_pmd_at(mm, haddr, pmdp, pmd);
 	VM_BUG_ON(pmd_numa(*pmdp));
 	update_mmu_cache_pmd(vma, addr, pmdp);
+	unlock_page(page);
 out_unlock:
 	spin_unlock(&mm->page_table_lock);
-	if (current_nid != -1)
-		task_numa_fault(current_nid, HPAGE_PMD_NR, false);
+
+out:
+	if (anon_vma)
+		page_unlock_anon_vma_read(anon_vma);
+
+	if (page_nid != -1)
+		task_numa_fault(last_cpupid, page_nid, HPAGE_PMD_NR, flags);
+
 	return 0;
 }
 
@@ -1432,6 +1473,12 @@
 	return ret;
 }
 
+/*
+ * Returns
+ *  - 0 if PMD could not be locked
+ *  - 1 if PMD was locked but protections unchange and TLB flush unnecessary
+ *  - HPAGE_PMD_NR is protections changed and TLB flush necessary
+ */
 int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
 		unsigned long addr, pgprot_t newprot, int prot_numa)
 {
@@ -1440,22 +1487,34 @@
 
 	if (__pmd_trans_huge_lock(pmd, vma) == 1) {
 		pmd_t entry;
-		entry = pmdp_get_and_clear(mm, addr, pmd);
+		ret = 1;
 		if (!prot_numa) {
+			entry = pmdp_get_and_clear(mm, addr, pmd);
 			entry = pmd_modify(entry, newprot);
+			ret = HPAGE_PMD_NR;
 			BUG_ON(pmd_write(entry));
 		} else {
 			struct page *page = pmd_page(*pmd);
 
-			/* only check non-shared pages */
-			if (page_mapcount(page) == 1 &&
+			/*
+			 * Do not trap faults against the zero page. The
+			 * read-only data is likely to be read-cached on the
+			 * local CPU cache and it is less useful to know about
+			 * local vs remote hits on the zero page.
+			 */
+			if (!is_huge_zero_page(page) &&
 			    !pmd_numa(*pmd)) {
+				entry = pmdp_get_and_clear(mm, addr, pmd);
 				entry = pmd_mknuma(entry);
+				ret = HPAGE_PMD_NR;
 			}
 		}
-		set_pmd_at(mm, addr, pmd, entry);
+
+		/* Set PMD if cleared earlier */
+		if (ret == HPAGE_PMD_NR)
+			set_pmd_at(mm, addr, pmd, entry);
+
 		spin_unlock(&vma->vm_mm->page_table_lock);
-		ret = 1;
 	}
 
 	return ret;
@@ -1636,7 +1695,7 @@
 		page_tail->mapping = page->mapping;
 
 		page_tail->index = page->index + i;
-		page_nid_xchg_last(page_tail, page_nid_last(page));
+		page_cpupid_xchg_last(page_tail, page_cpupid_last(page));
 
 		BUG_ON(!PageAnon(page_tail));
 		BUG_ON(!PageUptodate(page_tail));
@@ -2697,6 +2756,7 @@
 
 	mmun_start = haddr;
 	mmun_end   = haddr + HPAGE_PMD_SIZE;
+again:
 	mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
 	spin_lock(&mm->page_table_lock);
 	if (unlikely(!pmd_trans_huge(*pmd))) {
@@ -2719,7 +2779,14 @@
 	split_huge_page(page);
 
 	put_page(page);
-	BUG_ON(pmd_trans_huge(*pmd));
+
+	/*
+	 * We don't always have down_write of mmap_sem here: a racing
+	 * do_huge_pmd_wp_page() might have copied-on-write to another
+	 * huge page before our split_huge_page() got the anon_vma lock.
+	 */
+	if (unlikely(pmd_trans_huge(*pmd)))
+		goto again;
 }
 
 void split_huge_page_pmd_mm(struct mm_struct *mm, unsigned long address,
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index b49579c..0b7656e 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -653,6 +653,7 @@
 	BUG_ON(page_count(page));
 	BUG_ON(page_mapcount(page));
 	restore_reserve = PagePrivate(page);
+	ClearPagePrivate(page);
 
 	spin_lock(&hugetlb_lock);
 	hugetlb_cgroup_uncharge_page(hstate_index(h),
@@ -695,8 +696,22 @@
 	/* we rely on prep_new_huge_page to set the destructor */
 	set_compound_order(page, order);
 	__SetPageHead(page);
+	__ClearPageReserved(page);
 	for (i = 1; i < nr_pages; i++, p = mem_map_next(p, page, i)) {
 		__SetPageTail(p);
+		/*
+		 * For gigantic hugepages allocated through bootmem at
+		 * boot, it's safer to be consistent with the not-gigantic
+		 * hugepages and clear the PG_reserved bit from all tail pages
+		 * too.  Otherwse drivers using get_user_pages() to access tail
+		 * pages may get the reference counting wrong if they see
+		 * PG_reserved set on a tail page (despite the head page not
+		 * having PG_reserved set).  Enforcing this consistency between
+		 * head and tail pages allows drivers to optimize away a check
+		 * on the head page when they need know if put_page() is needed
+		 * after get_user_pages().
+		 */
+		__ClearPageReserved(p);
 		set_page_count(p, 0);
 		p->first_page = page;
 	}
@@ -1329,9 +1344,9 @@
 #else
 		page = virt_to_page(m);
 #endif
-		__ClearPageReserved(page);
 		WARN_ON(page_count(page) != 1);
 		prep_compound_huge_page(page, h->order);
+		WARN_ON(PageReserved(page));
 		prep_new_huge_page(h, page, page_to_nid(page));
 		/*
 		 * If we had gigantic hugepages allocated at boot time, we need
diff --git a/mm/list_lru.c b/mm/list_lru.c
index 7246791..72f9dec 100644
--- a/mm/list_lru.c
+++ b/mm/list_lru.c
@@ -81,8 +81,9 @@
 		 * decrement nr_to_walk first so that we don't livelock if we
 		 * get stuck on large numbesr of LRU_RETRY items
 		 */
-		if (--(*nr_to_walk) == 0)
+		if (!*nr_to_walk)
 			break;
+		--*nr_to_walk;
 
 		ret = isolate(item, &nlru->lock, cb_arg);
 		switch (ret) {
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 1c52ddb..7968209 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -54,6 +54,7 @@
 #include <linux/page_cgroup.h>
 #include <linux/cpu.h>
 #include <linux/oom.h>
+#include <linux/lockdep.h>
 #include "internal.h"
 #include <net/sock.h>
 #include <net/ip.h>
@@ -498,6 +499,29 @@
 	return (memcg == root_mem_cgroup);
 }
 
+/*
+ * We restrict the id in the range of [1, 65535], so it can fit into
+ * an unsigned short.
+ */
+#define MEM_CGROUP_ID_MAX	USHRT_MAX
+
+static inline unsigned short mem_cgroup_id(struct mem_cgroup *memcg)
+{
+	/*
+	 * The ID of the root cgroup is 0, but memcg treat 0 as an
+	 * invalid ID, so we return (cgroup_id + 1).
+	 */
+	return memcg->css.cgroup->id + 1;
+}
+
+static inline struct mem_cgroup *mem_cgroup_from_id(unsigned short id)
+{
+	struct cgroup_subsys_state *css;
+
+	css = css_from_id(id - 1, &mem_cgroup_subsys);
+	return mem_cgroup_from_css(css);
+}
+
 /* Writing them here to avoid exposing memcg's inner layout */
 #if defined(CONFIG_INET) && defined(CONFIG_MEMCG_KMEM)
 
@@ -569,16 +593,11 @@
 #ifdef CONFIG_MEMCG_KMEM
 /*
  * This will be the memcg's index in each cache's ->memcg_params->memcg_caches.
- * There are two main reasons for not using the css_id for this:
- *  1) this works better in sparse environments, where we have a lot of memcgs,
- *     but only a few kmem-limited. Or also, if we have, for instance, 200
- *     memcgs, and none but the 200th is kmem-limited, we'd have to have a
- *     200 entry array for that.
- *
- *  2) In order not to violate the cgroup API, we would like to do all memory
- *     allocation in ->create(). At that point, we haven't yet allocated the
- *     css_id. Having a separate index prevents us from messing with the cgroup
- *     core for this
+ * The main reason for not using cgroup id for this:
+ *  this works better in sparse environments, where we have a lot of memcgs,
+ *  but only a few kmem-limited. Or also, if we have, for instance, 200
+ *  memcgs, and none but the 200th is kmem-limited, we'd have to have a
+ *  200 entry array for that.
  *
  * The current size of the caches array is stored in
  * memcg_limited_groups_array_size.  It will double each time we have to
@@ -593,14 +612,14 @@
  * cgroups is a reasonable guess. In the future, it could be a parameter or
  * tunable, but that is strictly not necessary.
  *
- * MAX_SIZE should be as large as the number of css_ids. Ideally, we could get
+ * MAX_SIZE should be as large as the number of cgrp_ids. Ideally, we could get
  * this constant directly from cgroup, but it is understandable that this is
  * better kept as an internal representation in cgroup.c. In any case, the
- * css_id space is not getting any smaller, and we don't have to necessarily
+ * cgrp_id space is not getting any smaller, and we don't have to necessarily
  * increase ours as well if it increases.
  */
 #define MEMCG_CACHES_MIN_SIZE 4
-#define MEMCG_CACHES_MAX_SIZE 65535
+#define MEMCG_CACHES_MAX_SIZE MEM_CGROUP_ID_MAX
 
 /*
  * A lot of the calls to the cache allocation functions are expected to be
@@ -866,6 +885,7 @@
 	unsigned long val = 0;
 	int cpu;
 
+	get_online_cpus();
 	for_each_online_cpu(cpu)
 		val += per_cpu(memcg->stat->events[idx], cpu);
 #ifdef CONFIG_HOTPLUG_CPU
@@ -873,6 +893,7 @@
 	val += memcg->nocpu_base.events[idx];
 	spin_unlock(&memcg->pcp_counter_lock);
 #endif
+	put_online_cpus();
 	return val;
 }
 
@@ -1405,7 +1426,7 @@
 		return true;
 	if (!root_memcg->use_hierarchy || !memcg)
 		return false;
-	return css_is_ancestor(&memcg->css, &root_memcg->css);
+	return cgroup_is_descendant(memcg->css.cgroup, root_memcg->css.cgroup);
 }
 
 static bool mem_cgroup_same_or_subtree(const struct mem_cgroup *root_memcg,
@@ -2044,6 +2065,12 @@
 	return total;
 }
 
+#ifdef CONFIG_LOCKDEP
+static struct lockdep_map memcg_oom_lock_dep_map = {
+	.name = "memcg_oom_lock",
+};
+#endif
+
 static DEFINE_SPINLOCK(memcg_oom_lock);
 
 /*
@@ -2081,7 +2108,8 @@
 			}
 			iter->oom_lock = false;
 		}
-	}
+	} else
+		mutex_acquire(&memcg_oom_lock_dep_map, 0, 1, _RET_IP_);
 
 	spin_unlock(&memcg_oom_lock);
 
@@ -2093,6 +2121,7 @@
 	struct mem_cgroup *iter;
 
 	spin_lock(&memcg_oom_lock);
+	mutex_release(&memcg_oom_lock_dep_map, 1, _RET_IP_);
 	for_each_mem_cgroup_tree(iter, memcg)
 		iter->oom_lock = false;
 	spin_unlock(&memcg_oom_lock);
@@ -2159,27 +2188,67 @@
 		memcg_wakeup_oom(memcg);
 }
 
-/*
- * try to call OOM killer
- */
 static void mem_cgroup_oom(struct mem_cgroup *memcg, gfp_t mask, int order)
 {
-	bool locked;
-	int wakeups;
-
 	if (!current->memcg_oom.may_oom)
 		return;
-
-	current->memcg_oom.in_memcg_oom = 1;
-
 	/*
-	 * As with any blocking lock, a contender needs to start
-	 * listening for wakeups before attempting the trylock,
-	 * otherwise it can miss the wakeup from the unlock and sleep
-	 * indefinitely.  This is just open-coded because our locking
-	 * is so particular to memcg hierarchies.
+	 * We are in the middle of the charge context here, so we
+	 * don't want to block when potentially sitting on a callstack
+	 * that holds all kinds of filesystem and mm locks.
+	 *
+	 * Also, the caller may handle a failed allocation gracefully
+	 * (like optional page cache readahead) and so an OOM killer
+	 * invocation might not even be necessary.
+	 *
+	 * That's why we don't do anything here except remember the
+	 * OOM context and then deal with it at the end of the page
+	 * fault when the stack is unwound, the locks are released,
+	 * and when we know whether the fault was overall successful.
 	 */
-	wakeups = atomic_read(&memcg->oom_wakeups);
+	css_get(&memcg->css);
+	current->memcg_oom.memcg = memcg;
+	current->memcg_oom.gfp_mask = mask;
+	current->memcg_oom.order = order;
+}
+
+/**
+ * mem_cgroup_oom_synchronize - complete memcg OOM handling
+ * @handle: actually kill/wait or just clean up the OOM state
+ *
+ * This has to be called at the end of a page fault if the memcg OOM
+ * handler was enabled.
+ *
+ * Memcg supports userspace OOM handling where failed allocations must
+ * sleep on a waitqueue until the userspace task resolves the
+ * situation.  Sleeping directly in the charge context with all kinds
+ * of locks held is not a good idea, instead we remember an OOM state
+ * in the task and mem_cgroup_oom_synchronize() has to be called at
+ * the end of the page fault to complete the OOM handling.
+ *
+ * Returns %true if an ongoing memcg OOM situation was detected and
+ * completed, %false otherwise.
+ */
+bool mem_cgroup_oom_synchronize(bool handle)
+{
+	struct mem_cgroup *memcg = current->memcg_oom.memcg;
+	struct oom_wait_info owait;
+	bool locked;
+
+	/* OOM is global, do not handle */
+	if (!memcg)
+		return false;
+
+	if (!handle)
+		goto cleanup;
+
+	owait.memcg = memcg;
+	owait.wait.flags = 0;
+	owait.wait.func = memcg_oom_wake_function;
+	owait.wait.private = current;
+	INIT_LIST_HEAD(&owait.wait.task_list);
+
+	prepare_to_wait(&memcg_oom_waitq, &owait.wait, TASK_KILLABLE);
 	mem_cgroup_mark_under_oom(memcg);
 
 	locked = mem_cgroup_oom_trylock(memcg);
@@ -2189,95 +2258,16 @@
 
 	if (locked && !memcg->oom_kill_disable) {
 		mem_cgroup_unmark_under_oom(memcg);
-		mem_cgroup_out_of_memory(memcg, mask, order);
-		mem_cgroup_oom_unlock(memcg);
-		/*
-		 * There is no guarantee that an OOM-lock contender
-		 * sees the wakeups triggered by the OOM kill
-		 * uncharges.  Wake any sleepers explicitely.
-		 */
-		memcg_oom_recover(memcg);
+		finish_wait(&memcg_oom_waitq, &owait.wait);
+		mem_cgroup_out_of_memory(memcg, current->memcg_oom.gfp_mask,
+					 current->memcg_oom.order);
 	} else {
-		/*
-		 * A system call can just return -ENOMEM, but if this
-		 * is a page fault and somebody else is handling the
-		 * OOM already, we need to sleep on the OOM waitqueue
-		 * for this memcg until the situation is resolved.
-		 * Which can take some time because it might be
-		 * handled by a userspace task.
-		 *
-		 * However, this is the charge context, which means
-		 * that we may sit on a large call stack and hold
-		 * various filesystem locks, the mmap_sem etc. and we
-		 * don't want the OOM handler to deadlock on them
-		 * while we sit here and wait.  Store the current OOM
-		 * context in the task_struct, then return -ENOMEM.
-		 * At the end of the page fault handler, with the
-		 * stack unwound, pagefault_out_of_memory() will check
-		 * back with us by calling
-		 * mem_cgroup_oom_synchronize(), possibly putting the
-		 * task to sleep.
-		 */
-		current->memcg_oom.oom_locked = locked;
-		current->memcg_oom.wakeups = wakeups;
-		css_get(&memcg->css);
-		current->memcg_oom.wait_on_memcg = memcg;
-	}
-}
-
-/**
- * mem_cgroup_oom_synchronize - complete memcg OOM handling
- *
- * This has to be called at the end of a page fault if the the memcg
- * OOM handler was enabled and the fault is returning %VM_FAULT_OOM.
- *
- * Memcg supports userspace OOM handling, so failed allocations must
- * sleep on a waitqueue until the userspace task resolves the
- * situation.  Sleeping directly in the charge context with all kinds
- * of locks held is not a good idea, instead we remember an OOM state
- * in the task and mem_cgroup_oom_synchronize() has to be called at
- * the end of the page fault to put the task to sleep and clean up the
- * OOM state.
- *
- * Returns %true if an ongoing memcg OOM situation was detected and
- * finalized, %false otherwise.
- */
-bool mem_cgroup_oom_synchronize(void)
-{
-	struct oom_wait_info owait;
-	struct mem_cgroup *memcg;
-
-	/* OOM is global, do not handle */
-	if (!current->memcg_oom.in_memcg_oom)
-		return false;
-
-	/*
-	 * We invoked the OOM killer but there is a chance that a kill
-	 * did not free up any charges.  Everybody else might already
-	 * be sleeping, so restart the fault and keep the rampage
-	 * going until some charges are released.
-	 */
-	memcg = current->memcg_oom.wait_on_memcg;
-	if (!memcg)
-		goto out;
-
-	if (test_thread_flag(TIF_MEMDIE) || fatal_signal_pending(current))
-		goto out_memcg;
-
-	owait.memcg = memcg;
-	owait.wait.flags = 0;
-	owait.wait.func = memcg_oom_wake_function;
-	owait.wait.private = current;
-	INIT_LIST_HEAD(&owait.wait.task_list);
-
-	prepare_to_wait(&memcg_oom_waitq, &owait.wait, TASK_KILLABLE);
-	/* Only sleep if we didn't miss any wakeups since OOM */
-	if (atomic_read(&memcg->oom_wakeups) == current->memcg_oom.wakeups)
 		schedule();
-	finish_wait(&memcg_oom_waitq, &owait.wait);
-out_memcg:
-	mem_cgroup_unmark_under_oom(memcg);
-	if (current->memcg_oom.oom_locked) {
+		mem_cgroup_unmark_under_oom(memcg);
+		finish_wait(&memcg_oom_waitq, &owait.wait);
+	}
+
+	if (locked) {
 		mem_cgroup_oom_unlock(memcg);
 		/*
 		 * There is no guarantee that an OOM-lock contender
@@ -2286,10 +2276,9 @@
 		 */
 		memcg_oom_recover(memcg);
 	}
+cleanup:
+	current->memcg_oom.memcg = NULL;
 	css_put(&memcg->css);
-	current->memcg_oom.wait_on_memcg = NULL;
-out:
-	current->memcg_oom.in_memcg_oom = 0;
 	return true;
 }
 
@@ -2703,6 +2692,9 @@
 		     || fatal_signal_pending(current)))
 		goto bypass;
 
+	if (unlikely(task_in_memcg_oom(current)))
+		goto bypass;
+
 	/*
 	 * We always charge the cgroup the mm_struct belongs to.
 	 * The mm_struct's mem_cgroup changes on task migration if the
@@ -2800,8 +2792,10 @@
 	*ptr = memcg;
 	return 0;
 nomem:
-	*ptr = NULL;
-	return -ENOMEM;
+	if (!(gfp_mask & __GFP_NOFAIL)) {
+		*ptr = NULL;
+		return -ENOMEM;
+	}
 bypass:
 	*ptr = root_mem_cgroup;
 	return -EINTR;
@@ -2850,15 +2844,10 @@
  */
 static struct mem_cgroup *mem_cgroup_lookup(unsigned short id)
 {
-	struct cgroup_subsys_state *css;
-
 	/* ID 0 is unused ID */
 	if (!id)
 		return NULL;
-	css = css_lookup(&mem_cgroup_subsys, id);
-	if (!css)
-		return NULL;
-	return mem_cgroup_from_css(css);
+	return mem_cgroup_from_id(id);
 }
 
 struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
@@ -3806,8 +3795,7 @@
 {
 	/* Update stat data for mem_cgroup */
 	preempt_disable();
-	WARN_ON_ONCE(from->stat->count[idx] < nr_pages);
-	__this_cpu_add(from->stat->count[idx], -nr_pages);
+	__this_cpu_sub(from->stat->count[idx], nr_pages);
 	__this_cpu_add(to->stat->count[idx], nr_pages);
 	preempt_enable();
 }
@@ -4375,7 +4363,7 @@
 	 * css_get() was called in uncharge().
 	 */
 	if (do_swap_account && swapout && memcg)
-		swap_cgroup_record(ent, css_id(&memcg->css));
+		swap_cgroup_record(ent, mem_cgroup_id(memcg));
 }
 #endif
 
@@ -4427,8 +4415,8 @@
 {
 	unsigned short old_id, new_id;
 
-	old_id = css_id(&from->css);
-	new_id = css_id(&to->css);
+	old_id = mem_cgroup_id(from);
+	new_id = mem_cgroup_id(to);
 
 	if (swap_cgroup_cmpxchg(entry, old_id, new_id) == old_id) {
 		mem_cgroup_swap_statistics(from, false);
@@ -4983,31 +4971,18 @@
 	} while (usage > 0);
 }
 
-/*
- * This mainly exists for tests during the setting of set of use_hierarchy.
- * Since this is the very setting we are changing, the current hierarchy value
- * is meaningless
- */
-static inline bool __memcg_has_children(struct mem_cgroup *memcg)
-{
-	struct cgroup_subsys_state *pos;
-
-	/* bounce at first found */
-	css_for_each_child(pos, &memcg->css)
-		return true;
-	return false;
-}
-
-/*
- * Must be called with memcg_create_mutex held, unless the cgroup is guaranteed
- * to be already dead (as in mem_cgroup_force_empty, for instance).  This is
- * from mem_cgroup_count_children(), in the sense that we don't really care how
- * many children we have; we only need to know if we have any.  It also counts
- * any memcg without hierarchy as infertile.
- */
 static inline bool memcg_has_children(struct mem_cgroup *memcg)
 {
-	return memcg->use_hierarchy && __memcg_has_children(memcg);
+	lockdep_assert_held(&memcg_create_mutex);
+	/*
+	 * The lock does not prevent addition or deletion to the list
+	 * of children, but it prevents a new child from being
+	 * initialized based on this parent in css_online(), so it's
+	 * enough to decide whether hierarchically inherited
+	 * attributes can still be changed or not.
+	 */
+	return memcg->use_hierarchy &&
+		!list_empty(&memcg->css.cgroup->children);
 }
 
 /*
@@ -5087,7 +5062,7 @@
 	 */
 	if ((!parent_memcg || !parent_memcg->use_hierarchy) &&
 				(val == 1 || val == 0)) {
-		if (!__memcg_has_children(memcg))
+		if (list_empty(&memcg->css.cgroup->children))
 			memcg->use_hierarchy = val;
 		else
 			retval = -EBUSY;
@@ -6204,7 +6179,6 @@
 	size_t size = memcg_size();
 
 	mem_cgroup_remove_from_trees(memcg);
-	free_css_id(&mem_cgroup_subsys, &memcg->css);
 
 	for_each_node(node)
 		free_mem_cgroup_per_zone_info(memcg, node);
@@ -6307,6 +6281,9 @@
 	struct mem_cgroup *parent = mem_cgroup_from_css(css_parent(css));
 	int error = 0;
 
+	if (css->cgroup->id > MEM_CGROUP_ID_MAX)
+		return -ENOSPC;
+
 	if (!parent)
 		return 0;
 
@@ -6578,7 +6555,7 @@
 	}
 	/* There is a swap entry and a page doesn't exist or isn't charged */
 	if (ent.val && !ret &&
-			css_id(&mc.from->css) == lookup_swap_cgroup_id(ent)) {
+	    mem_cgroup_id(mc.from) == lookup_swap_cgroup_id(ent)) {
 		ret = MC_TARGET_SWAP;
 		if (target)
 			target->ent = ent;
@@ -6998,7 +6975,6 @@
 	.bind = mem_cgroup_bind,
 	.base_cftypes = mem_cgroup_files,
 	.early_init = 0,
-	.use_id = 1,
 };
 
 #ifdef CONFIG_MEMCG_SWAP
diff --git a/mm/memory.c b/mm/memory.c
index e2bbba4..33a3dbe 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -69,8 +69,8 @@
 
 #include "internal.h"
 
-#ifdef LAST_NID_NOT_IN_PAGE_FLAGS
-#warning Unfortunate NUMA and NUMA Balancing config, growing page-frame for last_nid.
+#ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS
+#warning Unfortunate NUMA and NUMA Balancing config, growing page-frame for last_cpupid.
 #endif
 
 #ifndef CONFIG_NEED_MULTIPLE_NODES
@@ -837,6 +837,8 @@
 					 */
 					make_migration_entry_read(&entry);
 					pte = swp_entry_to_pte(entry);
+					if (pte_swp_soft_dirty(*src_pte))
+						pte = pte_swp_mksoft_dirty(pte);
 					set_pte_at(src_mm, addr, src_pte, pte);
 				}
 			}
@@ -2719,6 +2721,14 @@
 		get_page(dirty_page);
 
 reuse:
+		/*
+		 * Clear the pages cpupid information as the existing
+		 * information potentially belongs to a now completely
+		 * unrelated process.
+		 */
+		if (old_page)
+			page_cpupid_xchg_last(old_page, (1 << LAST_CPUPID_SHIFT) - 1);
+
 		flush_cache_page(vma, address, pte_pfn(orig_pte));
 		entry = pte_mkyoung(orig_pte);
 		entry = maybe_mkwrite(pte_mkdirty(entry), vma);
@@ -3519,13 +3529,16 @@
 }
 
 int numa_migrate_prep(struct page *page, struct vm_area_struct *vma,
-				unsigned long addr, int current_nid)
+				unsigned long addr, int page_nid,
+				int *flags)
 {
 	get_page(page);
 
 	count_vm_numa_event(NUMA_HINT_FAULTS);
-	if (current_nid == numa_node_id())
+	if (page_nid == numa_node_id()) {
 		count_vm_numa_event(NUMA_HINT_FAULTS_LOCAL);
+		*flags |= TNF_FAULT_LOCAL;
+	}
 
 	return mpol_misplaced(page, vma, addr);
 }
@@ -3535,9 +3548,11 @@
 {
 	struct page *page = NULL;
 	spinlock_t *ptl;
-	int current_nid = -1;
+	int page_nid = -1;
+	int last_cpupid;
 	int target_nid;
 	bool migrated = false;
+	int flags = 0;
 
 	/*
 	* The "pte" at this point cannot be used safely without
@@ -3564,124 +3579,45 @@
 		pte_unmap_unlock(ptep, ptl);
 		return 0;
 	}
+	BUG_ON(is_zero_pfn(page_to_pfn(page)));
 
-	current_nid = page_to_nid(page);
-	target_nid = numa_migrate_prep(page, vma, addr, current_nid);
+	/*
+	 * Avoid grouping on DSO/COW pages in specific and RO pages
+	 * in general, RO pages shouldn't hurt as much anyway since
+	 * they can be in shared cache state.
+	 */
+	if (!pte_write(pte))
+		flags |= TNF_NO_GROUP;
+
+	/*
+	 * Flag if the page is shared between multiple address spaces. This
+	 * is later used when determining whether to group tasks together
+	 */
+	if (page_mapcount(page) > 1 && (vma->vm_flags & VM_SHARED))
+		flags |= TNF_SHARED;
+
+	last_cpupid = page_cpupid_last(page);
+	page_nid = page_to_nid(page);
+	target_nid = numa_migrate_prep(page, vma, addr, page_nid, &flags);
 	pte_unmap_unlock(ptep, ptl);
 	if (target_nid == -1) {
-		/*
-		 * Account for the fault against the current node if it not
-		 * being replaced regardless of where the page is located.
-		 */
-		current_nid = numa_node_id();
 		put_page(page);
 		goto out;
 	}
 
 	/* Migrate to the requested node */
-	migrated = migrate_misplaced_page(page, target_nid);
-	if (migrated)
-		current_nid = target_nid;
+	migrated = migrate_misplaced_page(page, vma, target_nid);
+	if (migrated) {
+		page_nid = target_nid;
+		flags |= TNF_MIGRATED;
+	}
 
 out:
-	if (current_nid != -1)
-		task_numa_fault(current_nid, 1, migrated);
+	if (page_nid != -1)
+		task_numa_fault(last_cpupid, page_nid, 1, flags);
 	return 0;
 }
 
-/* NUMA hinting page fault entry point for regular pmds */
-#ifdef CONFIG_NUMA_BALANCING
-static int do_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
-		     unsigned long addr, pmd_t *pmdp)
-{
-	pmd_t pmd;
-	pte_t *pte, *orig_pte;
-	unsigned long _addr = addr & PMD_MASK;
-	unsigned long offset;
-	spinlock_t *ptl;
-	bool numa = false;
-	int local_nid = numa_node_id();
-
-	spin_lock(&mm->page_table_lock);
-	pmd = *pmdp;
-	if (pmd_numa(pmd)) {
-		set_pmd_at(mm, _addr, pmdp, pmd_mknonnuma(pmd));
-		numa = true;
-	}
-	spin_unlock(&mm->page_table_lock);
-
-	if (!numa)
-		return 0;
-
-	/* we're in a page fault so some vma must be in the range */
-	BUG_ON(!vma);
-	BUG_ON(vma->vm_start >= _addr + PMD_SIZE);
-	offset = max(_addr, vma->vm_start) & ~PMD_MASK;
-	VM_BUG_ON(offset >= PMD_SIZE);
-	orig_pte = pte = pte_offset_map_lock(mm, pmdp, _addr, &ptl);
-	pte += offset >> PAGE_SHIFT;
-	for (addr = _addr + offset; addr < _addr + PMD_SIZE; pte++, addr += PAGE_SIZE) {
-		pte_t pteval = *pte;
-		struct page *page;
-		int curr_nid = local_nid;
-		int target_nid;
-		bool migrated;
-		if (!pte_present(pteval))
-			continue;
-		if (!pte_numa(pteval))
-			continue;
-		if (addr >= vma->vm_end) {
-			vma = find_vma(mm, addr);
-			/* there's a pte present so there must be a vma */
-			BUG_ON(!vma);
-			BUG_ON(addr < vma->vm_start);
-		}
-		if (pte_numa(pteval)) {
-			pteval = pte_mknonnuma(pteval);
-			set_pte_at(mm, addr, pte, pteval);
-		}
-		page = vm_normal_page(vma, addr, pteval);
-		if (unlikely(!page))
-			continue;
-		/* only check non-shared pages */
-		if (unlikely(page_mapcount(page) != 1))
-			continue;
-
-		/*
-		 * Note that the NUMA fault is later accounted to either
-		 * the node that is currently running or where the page is
-		 * migrated to.
-		 */
-		curr_nid = local_nid;
-		target_nid = numa_migrate_prep(page, vma, addr,
-					       page_to_nid(page));
-		if (target_nid == -1) {
-			put_page(page);
-			continue;
-		}
-
-		/* Migrate to the requested node */
-		pte_unmap_unlock(pte, ptl);
-		migrated = migrate_misplaced_page(page, target_nid);
-		if (migrated)
-			curr_nid = target_nid;
-		task_numa_fault(curr_nid, 1, migrated);
-
-		pte = pte_offset_map_lock(mm, pmdp, addr, &ptl);
-	}
-	pte_unmap_unlock(orig_pte, ptl);
-
-	return 0;
-}
-#else
-static int do_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
-		     unsigned long addr, pmd_t *pmdp)
-{
-	BUG();
-	return 0;
-}
-#endif /* CONFIG_NUMA_BALANCING */
-
 /*
  * These routines also need to handle stuff like marking pages dirty
  * and/or accessed for architectures that don't do it in hardware (most
@@ -3820,8 +3756,8 @@
 		}
 	}
 
-	if (pmd_numa(*pmd))
-		return do_pmd_numa_page(mm, vma, address, pmd);
+	/* THP should already have been handled */
+	BUG_ON(pmd_numa(*pmd));
 
 	/*
 	 * Use __pte_alloc instead of pte_alloc_map, because we can't
@@ -3863,15 +3799,21 @@
 	 * space.  Kernel faults are handled more gracefully.
 	 */
 	if (flags & FAULT_FLAG_USER)
-		mem_cgroup_enable_oom();
+		mem_cgroup_oom_enable();
 
 	ret = __handle_mm_fault(mm, vma, address, flags);
 
-	if (flags & FAULT_FLAG_USER)
-		mem_cgroup_disable_oom();
-
-	if (WARN_ON(task_in_memcg_oom(current) && !(ret & VM_FAULT_OOM)))
-		mem_cgroup_oom_synchronize();
+	if (flags & FAULT_FLAG_USER) {
+		mem_cgroup_oom_disable();
+                /*
+                 * The task may have entered a memcg OOM situation but
+                 * if the allocation error was handled gracefully (no
+                 * VM_FAULT_OOM), there is no need to kill anything.
+                 * Just clean up the OOM state peacefully.
+                 */
+                if (task_in_memcg_oom(current) && !(ret & VM_FAULT_OOM))
+                        mem_cgroup_oom_synchronize(false);
+	}
 
 	return ret;
 }
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 0472964..71cb253 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -1679,6 +1679,30 @@
 	return pol;
 }
 
+bool vma_policy_mof(struct task_struct *task, struct vm_area_struct *vma)
+{
+	struct mempolicy *pol = get_task_policy(task);
+	if (vma) {
+		if (vma->vm_ops && vma->vm_ops->get_policy) {
+			bool ret = false;
+
+			pol = vma->vm_ops->get_policy(vma, vma->vm_start);
+			if (pol && (pol->flags & MPOL_F_MOF))
+				ret = true;
+			mpol_cond_put(pol);
+
+			return ret;
+		} else if (vma->vm_policy) {
+			pol = vma->vm_policy;
+		}
+	}
+
+	if (!pol)
+		return default_policy.flags & MPOL_F_MOF;
+
+	return pol->flags & MPOL_F_MOF;
+}
+
 static int apply_policy_zone(struct mempolicy *policy, enum zone_type zone)
 {
 	enum zone_type dynamic_policy_zone = policy_zone;
@@ -2277,6 +2301,35 @@
 	kmem_cache_free(sn_cache, n);
 }
 
+#ifdef CONFIG_NUMA_BALANCING
+static bool numa_migrate_deferred(struct task_struct *p, int last_cpupid)
+{
+	/* Never defer a private fault */
+	if (cpupid_match_pid(p, last_cpupid))
+		return false;
+
+	if (p->numa_migrate_deferred) {
+		p->numa_migrate_deferred--;
+		return true;
+	}
+	return false;
+}
+
+static inline void defer_numa_migrate(struct task_struct *p)
+{
+	p->numa_migrate_deferred = sysctl_numa_balancing_migrate_deferred;
+}
+#else
+static inline bool numa_migrate_deferred(struct task_struct *p, int last_cpupid)
+{
+	return false;
+}
+
+static inline void defer_numa_migrate(struct task_struct *p)
+{
+}
+#endif /* CONFIG_NUMA_BALANCING */
+
 /**
  * mpol_misplaced - check whether current page node is valid in policy
  *
@@ -2300,6 +2353,8 @@
 	struct zone *zone;
 	int curnid = page_to_nid(page);
 	unsigned long pgoff;
+	int thiscpu = raw_smp_processor_id();
+	int thisnid = cpu_to_node(thiscpu);
 	int polnid = -1;
 	int ret = -1;
 
@@ -2348,9 +2403,11 @@
 
 	/* Migrate the page towards the node whose CPU is referencing it */
 	if (pol->flags & MPOL_F_MORON) {
-		int last_nid;
+		int last_cpupid;
+		int this_cpupid;
 
-		polnid = numa_node_id();
+		polnid = thisnid;
+		this_cpupid = cpu_pid_to_cpupid(thiscpu, current->pid);
 
 		/*
 		 * Multi-stage node selection is used in conjunction
@@ -2373,8 +2430,25 @@
 		 * it less likely we act on an unlikely task<->page
 		 * relation.
 		 */
-		last_nid = page_nid_xchg_last(page, polnid);
-		if (last_nid != polnid)
+		last_cpupid = page_cpupid_xchg_last(page, this_cpupid);
+		if (!cpupid_pid_unset(last_cpupid) && cpupid_to_nid(last_cpupid) != thisnid) {
+
+			/* See sysctl_numa_balancing_migrate_deferred comment */
+			if (!cpupid_match_pid(current, last_cpupid))
+				defer_numa_migrate(current);
+
+			goto out;
+		}
+
+		/*
+		 * The quadratic filter above reduces extraneous migration
+		 * of shared pages somewhat. This code reduces it even more,
+		 * reducing the overhead of page migrations of shared pages.
+		 * This makes workloads with shared pages rely more on
+		 * "move task near its memory", and less on "move memory
+		 * towards its task", which is exactly what we want.
+		 */
+		if (numa_migrate_deferred(current, last_cpupid))
 			goto out;
 	}
 
diff --git a/mm/migrate.c b/mm/migrate.c
index a26bccd..dfc8300 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -161,6 +161,8 @@
 
 	get_page(new);
 	pte = pte_mkold(mk_pte(new, vma->vm_page_prot));
+	if (pte_swp_soft_dirty(*ptep))
+		pte = pte_mksoft_dirty(pte);
 	if (is_write_migration_entry(entry))
 		pte = pte_mkwrite(pte);
 #ifdef CONFIG_HUGETLB_PAGE
@@ -443,6 +445,8 @@
  */
 void migrate_page_copy(struct page *newpage, struct page *page)
 {
+	int cpupid;
+
 	if (PageHuge(page) || PageTransHuge(page))
 		copy_huge_page(newpage, page);
 	else
@@ -479,6 +483,13 @@
 			__set_page_dirty_nobuffers(newpage);
  	}
 
+	/*
+	 * Copy NUMA information to the new page, to prevent over-eager
+	 * future migrations of this same page.
+	 */
+	cpupid = page_cpupid_xchg_last(page, -1);
+	page_cpupid_xchg_last(newpage, cpupid);
+
 	mlock_migrate_page(newpage, page);
 	ksm_migrate_page(newpage, page);
 	/*
@@ -1498,7 +1509,7 @@
 					  __GFP_NOWARN) &
 					 ~GFP_IOFS, 0);
 	if (newpage)
-		page_nid_xchg_last(newpage, page_nid_last(page));
+		page_cpupid_xchg_last(newpage, page_cpupid_last(page));
 
 	return newpage;
 }
@@ -1599,7 +1610,8 @@
  * node. Caller is expected to have an elevated reference count on
  * the page that will be dropped by this function before returning.
  */
-int migrate_misplaced_page(struct page *page, int node)
+int migrate_misplaced_page(struct page *page, struct vm_area_struct *vma,
+			   int node)
 {
 	pg_data_t *pgdat = NODE_DATA(node);
 	int isolated;
@@ -1607,10 +1619,11 @@
 	LIST_HEAD(migratepages);
 
 	/*
-	 * Don't migrate pages that are mapped in multiple processes.
-	 * TODO: Handle false sharing detection instead of this hammer
+	 * Don't migrate file pages that are mapped in multiple processes
+	 * with execute permissions as they are probably shared libraries.
 	 */
-	if (page_mapcount(page) != 1)
+	if (page_mapcount(page) != 1 && page_is_file_cache(page) &&
+	    (vma->vm_flags & VM_EXEC))
 		goto out;
 
 	/*
@@ -1661,13 +1674,6 @@
 	int page_lru = page_is_file_cache(page);
 
 	/*
-	 * Don't migrate pages that are mapped in multiple processes.
-	 * TODO: Handle false sharing detection instead of this hammer
-	 */
-	if (page_mapcount(page) != 1)
-		goto out_dropref;
-
-	/*
 	 * Rate-limit the amount of data that is being migrated to a node.
 	 * Optimal placement is no good if the memory bus is saturated and
 	 * all the time is being spent migrating!
@@ -1680,7 +1686,7 @@
 	if (!new_page)
 		goto out_fail;
 
-	page_nid_xchg_last(new_page, page_nid_last(page));
+	page_cpupid_xchg_last(new_page, page_cpupid_last(page));
 
 	isolated = numamigrate_isolate_page(pgdat, page);
 	if (!isolated) {
@@ -1713,12 +1719,12 @@
 		unlock_page(new_page);
 		put_page(new_page);		/* Free it */
 
-		unlock_page(page);
+		/* Retake the callers reference and putback on LRU */
+		get_page(page);
 		putback_lru_page(page);
-
-		count_vm_events(PGMIGRATE_FAIL, HPAGE_PMD_NR);
-		isolated = 0;
-		goto out;
+		mod_zone_page_state(page_zone(page),
+			 NR_ISOLATED_ANON + page_lru, -HPAGE_PMD_NR);
+		goto out_fail;
 	}
 
 	/*
@@ -1735,9 +1741,9 @@
 	entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
 	entry = pmd_mkhuge(entry);
 
-	page_add_new_anon_rmap(new_page, vma, haddr);
-
+	pmdp_clear_flush(vma, haddr, pmd);
 	set_pmd_at(mm, haddr, pmd, entry);
+	page_add_new_anon_rmap(new_page, vma, haddr);
 	update_mmu_cache_pmd(vma, address, &entry);
 	page_remove_rmap(page);
 	/*
@@ -1756,7 +1762,6 @@
 	count_vm_events(PGMIGRATE_SUCCESS, HPAGE_PMD_NR);
 	count_vm_numa_events(NUMA_PAGE_MIGRATE, HPAGE_PMD_NR);
 
-out:
 	mod_zone_page_state(page_zone(page),
 			NR_ISOLATED_ANON + page_lru,
 			-HPAGE_PMD_NR);
@@ -1765,6 +1770,10 @@
 out_fail:
 	count_vm_events(PGMIGRATE_FAIL, HPAGE_PMD_NR);
 out_dropref:
+	entry = pmd_mknonnuma(entry);
+	set_pmd_at(mm, haddr, pmd, entry);
+	update_mmu_cache_pmd(vma, address, &entry);
+
 	unlock_page(page);
 	put_page(page);
 	return 0;
diff --git a/mm/mm_init.c b/mm/mm_init.c
index 633c088..68562e9 100644
--- a/mm/mm_init.c
+++ b/mm/mm_init.c
@@ -71,26 +71,26 @@
 	unsigned long or_mask, add_mask;
 
 	shift = 8 * sizeof(unsigned long);
-	width = shift - SECTIONS_WIDTH - NODES_WIDTH - ZONES_WIDTH - LAST_NID_SHIFT;
+	width = shift - SECTIONS_WIDTH - NODES_WIDTH - ZONES_WIDTH - LAST_CPUPID_SHIFT;
 	mminit_dprintk(MMINIT_TRACE, "pageflags_layout_widths",
-		"Section %d Node %d Zone %d Lastnid %d Flags %d\n",
+		"Section %d Node %d Zone %d Lastcpupid %d Flags %d\n",
 		SECTIONS_WIDTH,
 		NODES_WIDTH,
 		ZONES_WIDTH,
-		LAST_NID_WIDTH,
+		LAST_CPUPID_WIDTH,
 		NR_PAGEFLAGS);
 	mminit_dprintk(MMINIT_TRACE, "pageflags_layout_shifts",
-		"Section %d Node %d Zone %d Lastnid %d\n",
+		"Section %d Node %d Zone %d Lastcpupid %d\n",
 		SECTIONS_SHIFT,
 		NODES_SHIFT,
 		ZONES_SHIFT,
-		LAST_NID_SHIFT);
+		LAST_CPUPID_SHIFT);
 	mminit_dprintk(MMINIT_TRACE, "pageflags_layout_pgshifts",
-		"Section %lu Node %lu Zone %lu Lastnid %lu\n",
+		"Section %lu Node %lu Zone %lu Lastcpupid %lu\n",
 		(unsigned long)SECTIONS_PGSHIFT,
 		(unsigned long)NODES_PGSHIFT,
 		(unsigned long)ZONES_PGSHIFT,
-		(unsigned long)LAST_NID_PGSHIFT);
+		(unsigned long)LAST_CPUPID_PGSHIFT);
 	mminit_dprintk(MMINIT_TRACE, "pageflags_layout_nodezoneid",
 		"Node/Zone ID: %lu -> %lu\n",
 		(unsigned long)(ZONEID_PGOFF + ZONEID_SHIFT),
@@ -102,9 +102,9 @@
 	mminit_dprintk(MMINIT_TRACE, "pageflags_layout_nodeflags",
 		"Node not in page flags");
 #endif
-#ifdef LAST_NID_NOT_IN_PAGE_FLAGS
+#ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS
 	mminit_dprintk(MMINIT_TRACE, "pageflags_layout_nodeflags",
-		"Last nid not in page flags");
+		"Last cpupid not in page flags");
 #endif
 
 	if (SECTIONS_WIDTH) {
diff --git a/mm/mmzone.c b/mm/mmzone.c
index 2ac0afb..bf34fb8 100644
--- a/mm/mmzone.c
+++ b/mm/mmzone.c
@@ -97,20 +97,20 @@
 		INIT_LIST_HEAD(&lruvec->lists[lru]);
 }
 
-#if defined(CONFIG_NUMA_BALANCING) && !defined(LAST_NID_NOT_IN_PAGE_FLAGS)
-int page_nid_xchg_last(struct page *page, int nid)
+#if defined(CONFIG_NUMA_BALANCING) && !defined(LAST_CPUPID_NOT_IN_PAGE_FLAGS)
+int page_cpupid_xchg_last(struct page *page, int cpupid)
 {
 	unsigned long old_flags, flags;
-	int last_nid;
+	int last_cpupid;
 
 	do {
 		old_flags = flags = page->flags;
-		last_nid = page_nid_last(page);
+		last_cpupid = page_cpupid_last(page);
 
-		flags &= ~(LAST_NID_MASK << LAST_NID_PGSHIFT);
-		flags |= (nid & LAST_NID_MASK) << LAST_NID_PGSHIFT;
+		flags &= ~(LAST_CPUPID_MASK << LAST_CPUPID_PGSHIFT);
+		flags |= (cpupid & LAST_CPUPID_MASK) << LAST_CPUPID_PGSHIFT;
 	} while (unlikely(cmpxchg(&page->flags, old_flags, flags) != old_flags));
 
-	return last_nid;
+	return last_cpupid;
 }
 #endif
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 94722a4..a597f2f 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -37,14 +37,12 @@
 
 static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
 		unsigned long addr, unsigned long end, pgprot_t newprot,
-		int dirty_accountable, int prot_numa, bool *ret_all_same_node)
+		int dirty_accountable, int prot_numa)
 {
 	struct mm_struct *mm = vma->vm_mm;
 	pte_t *pte, oldpte;
 	spinlock_t *ptl;
 	unsigned long pages = 0;
-	bool all_same_node = true;
-	int last_nid = -1;
 
 	pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
 	arch_enter_lazy_mmu_mode();
@@ -63,15 +61,7 @@
 
 				page = vm_normal_page(vma, addr, oldpte);
 				if (page) {
-					int this_nid = page_to_nid(page);
-					if (last_nid == -1)
-						last_nid = this_nid;
-					if (last_nid != this_nid)
-						all_same_node = false;
-
-					/* only check non-shared pages */
-					if (!pte_numa(oldpte) &&
-					    page_mapcount(page) == 1) {
+					if (!pte_numa(oldpte)) {
 						ptent = pte_mknuma(ptent);
 						updated = true;
 					}
@@ -94,40 +84,27 @@
 			swp_entry_t entry = pte_to_swp_entry(oldpte);
 
 			if (is_write_migration_entry(entry)) {
+				pte_t newpte;
 				/*
 				 * A protection check is difficult so
 				 * just be safe and disable write
 				 */
 				make_migration_entry_read(&entry);
-				set_pte_at(mm, addr, pte,
-					swp_entry_to_pte(entry));
+				newpte = swp_entry_to_pte(entry);
+				if (pte_swp_soft_dirty(oldpte))
+					newpte = pte_swp_mksoft_dirty(newpte);
+				set_pte_at(mm, addr, pte, newpte);
+
+				pages++;
 			}
-			pages++;
 		}
 	} while (pte++, addr += PAGE_SIZE, addr != end);
 	arch_leave_lazy_mmu_mode();
 	pte_unmap_unlock(pte - 1, ptl);
 
-	*ret_all_same_node = all_same_node;
 	return pages;
 }
 
-#ifdef CONFIG_NUMA_BALANCING
-static inline void change_pmd_protnuma(struct mm_struct *mm, unsigned long addr,
-				       pmd_t *pmd)
-{
-	spin_lock(&mm->page_table_lock);
-	set_pmd_at(mm, addr & PMD_MASK, pmd, pmd_mknuma(*pmd));
-	spin_unlock(&mm->page_table_lock);
-}
-#else
-static inline void change_pmd_protnuma(struct mm_struct *mm, unsigned long addr,
-				       pmd_t *pmd)
-{
-	BUG();
-}
-#endif /* CONFIG_NUMA_BALANCING */
-
 static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
 		pud_t *pud, unsigned long addr, unsigned long end,
 		pgprot_t newprot, int dirty_accountable, int prot_numa)
@@ -135,34 +112,33 @@
 	pmd_t *pmd;
 	unsigned long next;
 	unsigned long pages = 0;
-	bool all_same_node;
 
 	pmd = pmd_offset(pud, addr);
 	do {
+		unsigned long this_pages;
+
 		next = pmd_addr_end(addr, end);
 		if (pmd_trans_huge(*pmd)) {
 			if (next - addr != HPAGE_PMD_SIZE)
 				split_huge_page_pmd(vma, addr, pmd);
-			else if (change_huge_pmd(vma, pmd, addr, newprot,
-						 prot_numa)) {
-				pages += HPAGE_PMD_NR;
-				continue;
+			else {
+				int nr_ptes = change_huge_pmd(vma, pmd, addr,
+						newprot, prot_numa);
+
+				if (nr_ptes) {
+					if (nr_ptes == HPAGE_PMD_NR)
+						pages++;
+
+					continue;
+				}
 			}
 			/* fall through */
 		}
 		if (pmd_none_or_clear_bad(pmd))
 			continue;
-		pages += change_pte_range(vma, pmd, addr, next, newprot,
-				 dirty_accountable, prot_numa, &all_same_node);
-
-		/*
-		 * If we are changing protections for NUMA hinting faults then
-		 * set pmd_numa if the examined pages were all on the same
-		 * node. This allows a regular PMD to be handled as one fault
-		 * and effectively batches the taking of the PTL
-		 */
-		if (prot_numa && all_same_node)
-			change_pmd_protnuma(vma->vm_mm, addr, pmd);
+		this_pages = change_pte_range(vma, pmd, addr, next, newprot,
+				 dirty_accountable, prot_numa);
+		pages += this_pages;
 	} while (pmd++, addr = next, addr != end);
 
 	return pages;
diff --git a/mm/mremap.c b/mm/mremap.c
index 91b13d6..0843feb 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -25,7 +25,6 @@
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
-#include <asm/pgalloc.h>
 
 #include "internal.h"
 
@@ -63,10 +62,8 @@
 		return NULL;
 
 	pmd = pmd_alloc(mm, pud, addr);
-	if (!pmd) {
-		pud_free(mm, pud);
+	if (!pmd)
 		return NULL;
-	}
 
 	VM_BUG_ON(pmd_trans_huge(*pmd));
 
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 314e9d2..6738c47 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -680,7 +680,7 @@
 {
 	struct zonelist *zonelist;
 
-	if (mem_cgroup_oom_synchronize())
+	if (mem_cgroup_oom_synchronize(true))
 		return;
 
 	zonelist = node_zonelist(first_online_node, GFP_KERNEL);
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index f5236f8..6380758 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -1210,11 +1210,11 @@
 	return 1;
 }
 
-static long bdi_max_pause(struct backing_dev_info *bdi,
-			  unsigned long bdi_dirty)
+static unsigned long bdi_max_pause(struct backing_dev_info *bdi,
+				   unsigned long bdi_dirty)
 {
-	long bw = bdi->avg_write_bandwidth;
-	long t;
+	unsigned long bw = bdi->avg_write_bandwidth;
+	unsigned long t;
 
 	/*
 	 * Limit pause time for small memory systems. If sleeping for too long
@@ -1226,7 +1226,7 @@
 	t = bdi_dirty / (1 + bw / roundup_pow_of_two(1 + HZ / 8));
 	t++;
 
-	return min_t(long, t, MAX_PAUSE);
+	return min_t(unsigned long, t, MAX_PAUSE);
 }
 
 static long bdi_min_pause(struct backing_dev_info *bdi,
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index dd886fa..73d812f 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -626,7 +626,7 @@
 		bad_page(page);
 		return 1;
 	}
-	page_nid_reset_last(page);
+	page_cpupid_reset_last(page);
 	if (page->flags & PAGE_FLAGS_CHECK_AT_PREP)
 		page->flags &= ~PAGE_FLAGS_CHECK_AT_PREP;
 	return 0;
@@ -4015,7 +4015,7 @@
 		mminit_verify_page_links(page, zone, nid, pfn);
 		init_page_count(page);
 		page_mapcount_reset(page);
-		page_nid_reset_last(page);
+		page_cpupid_reset_last(page);
 		SetPageReserved(page);
 		/*
 		 * Mark the block movable so that blocks are reserved for
diff --git a/mm/pagewalk.c b/mm/pagewalk.c
index 5da2cbc..2beeabf 100644
--- a/mm/pagewalk.c
+++ b/mm/pagewalk.c
@@ -242,7 +242,7 @@
 		if (err)
 			break;
 		pgd++;
-	} while (addr = next, addr != end);
+	} while (addr = next, addr < end);
 
 	return err;
 }
diff --git a/mm/percpu.c b/mm/percpu.c
index 8c8e08f..0d10def 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -1706,8 +1706,9 @@
 
 out_free_areas:
 	for (group = 0; group < ai->nr_groups; group++)
-		free_fn(areas[group],
-			ai->groups[group].nr_units * ai->unit_size);
+		if (areas[group])
+			free_fn(areas[group],
+				ai->groups[group].nr_units * ai->unit_size);
 out_free:
 	pcpu_free_alloc_info(ai);
 	if (areas)
diff --git a/mm/slab_common.c b/mm/slab_common.c
index a344327..e2e98af 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -56,6 +56,7 @@
 			continue;
 		}
 
+#if !defined(CONFIG_SLUB) || !defined(CONFIG_SLUB_DEBUG_ON)
 		/*
 		 * For simplicity, we won't check this in the list of memcg
 		 * caches. We have control over memcg naming, and if there
@@ -69,6 +70,7 @@
 			s = NULL;
 			return -EINVAL;
 		}
+#endif
 	}
 
 	WARN_ON(strchr(name, ' '));	/* It confuses parsers */
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 3963fc2..de7c904 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1824,6 +1824,7 @@
 	struct filename *pathname;
 	int i, type, prev;
 	int err;
+	unsigned int old_block_size;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
@@ -1914,6 +1915,7 @@
 	}
 
 	swap_file = p->swap_file;
+	old_block_size = p->old_block_size;
 	p->swap_file = NULL;
 	p->max = 0;
 	swap_map = p->swap_map;
@@ -1938,7 +1940,7 @@
 	inode = mapping->host;
 	if (S_ISBLK(inode->i_mode)) {
 		struct block_device *bdev = I_BDEV(inode);
-		set_blocksize(bdev, p->old_block_size);
+		set_blocksize(bdev, old_block_size);
 		blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
 	} else {
 		mutex_lock(&inode->i_mutex);
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 53f2f82..eea668d 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -211,6 +211,7 @@
 	down_write(&shrinker_rwsem);
 	list_del(&shrinker->list);
 	up_write(&shrinker_rwsem);
+	kfree(shrinker->nr_deferred);
 }
 EXPORT_SYMBOL(unregister_shrinker);
 
diff --git a/mm/zswap.c b/mm/zswap.c
index 841e35f..d93510c 100644
--- a/mm/zswap.c
+++ b/mm/zswap.c
@@ -804,6 +804,10 @@
 	}
 	tree->rbroot = RB_ROOT;
 	spin_unlock(&tree->lock);
+
+	zbud_destroy_pool(tree->pool);
+	kfree(tree);
+	zswap_trees[type] = NULL;
 }
 
 static struct zbud_ops zswap_zbud_ops = {
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c
index 3091297..c7e634a 100644
--- a/net/8021q/vlan_netlink.c
+++ b/net/8021q/vlan_netlink.c
@@ -171,7 +171,7 @@
 
 	return nla_total_size(2) +	/* IFLA_VLAN_PROTOCOL */
 	       nla_total_size(2) +	/* IFLA_VLAN_ID */
-	       sizeof(struct ifla_vlan_flags) + /* IFLA_VLAN_FLAGS */
+	       nla_total_size(sizeof(struct ifla_vlan_flags)) + /* IFLA_VLAN_FLAGS */
 	       vlan_qos_map_size(vlan->nr_ingress_mappings) +
 	       vlan_qos_map_size(vlan->nr_egress_mappings);
 }
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index c72d1bc..1356af6 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -65,6 +65,7 @@
 	batadv_recv_handler_init();
 
 	batadv_iv_init();
+	batadv_nc_init();
 
 	batadv_event_workqueue = create_singlethread_workqueue("bat_events");
 
@@ -142,7 +143,7 @@
 	if (ret < 0)
 		goto err;
 
-	ret = batadv_nc_init(bat_priv);
+	ret = batadv_nc_mesh_init(bat_priv);
 	if (ret < 0)
 		goto err;
 
@@ -167,7 +168,7 @@
 	batadv_vis_quit(bat_priv);
 
 	batadv_gw_node_purge(bat_priv);
-	batadv_nc_free(bat_priv);
+	batadv_nc_mesh_free(bat_priv);
 	batadv_dat_free(bat_priv);
 	batadv_bla_free(bat_priv);
 
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c
index a487d46..4ecc0b6 100644
--- a/net/batman-adv/network-coding.c
+++ b/net/batman-adv/network-coding.c
@@ -35,6 +35,20 @@
 				       struct batadv_hard_iface *recv_if);
 
 /**
+ * batadv_nc_init - one-time initialization for network coding
+ */
+int __init batadv_nc_init(void)
+{
+	int ret;
+
+	/* Register our packet type */
+	ret = batadv_recv_handler_register(BATADV_CODED,
+					   batadv_nc_recv_coded_packet);
+
+	return ret;
+}
+
+/**
  * batadv_nc_start_timer - initialise the nc periodic worker
  * @bat_priv: the bat priv with all the soft interface information
  */
@@ -45,10 +59,10 @@
 }
 
 /**
- * batadv_nc_init - initialise coding hash table and start house keeping
+ * batadv_nc_mesh_init - initialise coding hash table and start house keeping
  * @bat_priv: the bat priv with all the soft interface information
  */
-int batadv_nc_init(struct batadv_priv *bat_priv)
+int batadv_nc_mesh_init(struct batadv_priv *bat_priv)
 {
 	bat_priv->nc.timestamp_fwd_flush = jiffies;
 	bat_priv->nc.timestamp_sniffed_purge = jiffies;
@@ -70,11 +84,6 @@
 	batadv_hash_set_lock_class(bat_priv->nc.coding_hash,
 				   &batadv_nc_decoding_hash_lock_class_key);
 
-	/* Register our packet type */
-	if (batadv_recv_handler_register(BATADV_CODED,
-					 batadv_nc_recv_coded_packet) < 0)
-		goto err;
-
 	INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker);
 	batadv_nc_start_timer(bat_priv);
 
@@ -1721,12 +1730,11 @@
 }
 
 /**
- * batadv_nc_free - clean up network coding memory
+ * batadv_nc_mesh_free - clean up network coding memory
  * @bat_priv: the bat priv with all the soft interface information
  */
-void batadv_nc_free(struct batadv_priv *bat_priv)
+void batadv_nc_mesh_free(struct batadv_priv *bat_priv)
 {
-	batadv_recv_handler_unregister(BATADV_CODED);
 	cancel_delayed_work_sync(&bat_priv->nc.work);
 
 	batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, NULL);
diff --git a/net/batman-adv/network-coding.h b/net/batman-adv/network-coding.h
index 85a4ec8..ddfa618 100644
--- a/net/batman-adv/network-coding.h
+++ b/net/batman-adv/network-coding.h
@@ -22,8 +22,9 @@
 
 #ifdef CONFIG_BATMAN_ADV_NC
 
-int batadv_nc_init(struct batadv_priv *bat_priv);
-void batadv_nc_free(struct batadv_priv *bat_priv);
+int batadv_nc_init(void);
+int batadv_nc_mesh_init(struct batadv_priv *bat_priv);
+void batadv_nc_mesh_free(struct batadv_priv *bat_priv);
 void batadv_nc_update_nc_node(struct batadv_priv *bat_priv,
 			      struct batadv_orig_node *orig_node,
 			      struct batadv_orig_node *orig_neigh_node,
@@ -46,12 +47,17 @@
 
 #else /* ifdef CONFIG_BATMAN_ADV_NC */
 
-static inline int batadv_nc_init(struct batadv_priv *bat_priv)
+static inline int batadv_nc_init(void)
 {
 	return 0;
 }
 
-static inline void batadv_nc_free(struct batadv_priv *bat_priv)
+static inline int batadv_nc_mesh_init(struct batadv_priv *bat_priv)
+{
+	return 0;
+}
+
+static inline void batadv_nc_mesh_free(struct batadv_priv *bat_priv)
 {
 	return;
 }
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index ca04163..e6b7fec 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -64,7 +64,7 @@
 			br_flood_deliver(br, skb, false);
 			goto out;
 		}
-		if (br_multicast_rcv(br, NULL, skb)) {
+		if (br_multicast_rcv(br, NULL, skb, vid)) {
 			kfree_skb(skb);
 			goto out;
 		}
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index ffd5874..33e8f23 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -700,7 +700,7 @@
 
 		vid = nla_get_u16(tb[NDA_VLAN]);
 
-		if (vid >= VLAN_N_VID) {
+		if (!vid || vid >= VLAN_VID_MASK) {
 			pr_info("bridge: RTM_NEWNEIGH with invalid vlan id %d\n",
 				vid);
 			return -EINVAL;
@@ -794,7 +794,7 @@
 
 		vid = nla_get_u16(tb[NDA_VLAN]);
 
-		if (vid >= VLAN_N_VID) {
+		if (!vid || vid >= VLAN_VID_MASK) {
 			pr_info("bridge: RTM_NEWNEIGH with invalid vlan id %d\n",
 				vid);
 			return -EINVAL;
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index a2fd37e..7e73c32 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -80,7 +80,7 @@
 		br_fdb_update(br, p, eth_hdr(skb)->h_source, vid);
 
 	if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) &&
-	    br_multicast_rcv(br, p, skb))
+	    br_multicast_rcv(br, p, skb, vid))
 		goto drop;
 
 	if (p->state == BR_STATE_LEARNING)
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index 85a09bb..b7b1914 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -453,7 +453,7 @@
 		call_rcu_bh(&p->rcu, br_multicast_free_pg);
 		err = 0;
 
-		if (!mp->ports && !mp->mglist && mp->timer_armed &&
+		if (!mp->ports && !mp->mglist &&
 		    netif_running(br->dev))
 			mod_timer(&mp->timer, jiffies);
 		break;
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index d1c5786..686284f 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -272,7 +272,7 @@
 		del_timer(&p->timer);
 		call_rcu_bh(&p->rcu, br_multicast_free_pg);
 
-		if (!mp->ports && !mp->mglist && mp->timer_armed &&
+		if (!mp->ports && !mp->mglist &&
 		    netif_running(br->dev))
 			mod_timer(&mp->timer, jiffies);
 
@@ -620,7 +620,6 @@
 
 	mp->br = br;
 	mp->addr = *group;
-
 	setup_timer(&mp->timer, br_multicast_group_expired,
 		    (unsigned long)mp);
 
@@ -660,6 +659,7 @@
 	struct net_bridge_mdb_entry *mp;
 	struct net_bridge_port_group *p;
 	struct net_bridge_port_group __rcu **pp;
+	unsigned long now = jiffies;
 	int err;
 
 	spin_lock(&br->multicast_lock);
@@ -674,6 +674,7 @@
 
 	if (!port) {
 		mp->mglist = true;
+		mod_timer(&mp->timer, now + br->multicast_membership_interval);
 		goto out;
 	}
 
@@ -681,7 +682,7 @@
 	     (p = mlock_dereference(*pp, br)) != NULL;
 	     pp = &p->next) {
 		if (p->port == port)
-			goto out;
+			goto found;
 		if ((unsigned long)p->port < (unsigned long)port)
 			break;
 	}
@@ -692,6 +693,8 @@
 	rcu_assign_pointer(*pp, p);
 	br_mdb_notify(br->dev, port, group, RTM_NEWMDB);
 
+found:
+	mod_timer(&p->timer, now + br->multicast_membership_interval);
 out:
 	err = 0;
 
@@ -944,7 +947,8 @@
 
 static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
 					 struct net_bridge_port *port,
-					 struct sk_buff *skb)
+					 struct sk_buff *skb,
+					 u16 vid)
 {
 	struct igmpv3_report *ih;
 	struct igmpv3_grec *grec;
@@ -954,12 +958,10 @@
 	int type;
 	int err = 0;
 	__be32 group;
-	u16 vid = 0;
 
 	if (!pskb_may_pull(skb, sizeof(*ih)))
 		return -EINVAL;
 
-	br_vlan_get_tag(skb, &vid);
 	ih = igmpv3_report_hdr(skb);
 	num = ntohs(ih->ngrec);
 	len = sizeof(*ih);
@@ -1002,7 +1004,8 @@
 #if IS_ENABLED(CONFIG_IPV6)
 static int br_ip6_multicast_mld2_report(struct net_bridge *br,
 					struct net_bridge_port *port,
-					struct sk_buff *skb)
+					struct sk_buff *skb,
+					u16 vid)
 {
 	struct icmp6hdr *icmp6h;
 	struct mld2_grec *grec;
@@ -1010,12 +1013,10 @@
 	int len;
 	int num;
 	int err = 0;
-	u16 vid = 0;
 
 	if (!pskb_may_pull(skb, sizeof(*icmp6h)))
 		return -EINVAL;
 
-	br_vlan_get_tag(skb, &vid);
 	icmp6h = icmp6_hdr(skb);
 	num = ntohs(icmp6h->icmp6_dataun.un_data16[1]);
 	len = sizeof(*icmp6h);
@@ -1138,7 +1139,8 @@
 
 static int br_ip4_multicast_query(struct net_bridge *br,
 				  struct net_bridge_port *port,
-				  struct sk_buff *skb)
+				  struct sk_buff *skb,
+				  u16 vid)
 {
 	const struct iphdr *iph = ip_hdr(skb);
 	struct igmphdr *ih = igmp_hdr(skb);
@@ -1150,7 +1152,6 @@
 	unsigned long now = jiffies;
 	__be32 group;
 	int err = 0;
-	u16 vid = 0;
 
 	spin_lock(&br->multicast_lock);
 	if (!netif_running(br->dev) ||
@@ -1186,14 +1187,10 @@
 	if (!group)
 		goto out;
 
-	br_vlan_get_tag(skb, &vid);
 	mp = br_mdb_ip4_get(mlock_dereference(br->mdb, br), group, vid);
 	if (!mp)
 		goto out;
 
-	mod_timer(&mp->timer, now + br->multicast_membership_interval);
-	mp->timer_armed = true;
-
 	max_delay *= br->multicast_last_member_count;
 
 	if (mp->mglist &&
@@ -1219,7 +1216,8 @@
 #if IS_ENABLED(CONFIG_IPV6)
 static int br_ip6_multicast_query(struct net_bridge *br,
 				  struct net_bridge_port *port,
-				  struct sk_buff *skb)
+				  struct sk_buff *skb,
+				  u16 vid)
 {
 	const struct ipv6hdr *ip6h = ipv6_hdr(skb);
 	struct mld_msg *mld;
@@ -1231,7 +1229,6 @@
 	unsigned long now = jiffies;
 	const struct in6_addr *group = NULL;
 	int err = 0;
-	u16 vid = 0;
 
 	spin_lock(&br->multicast_lock);
 	if (!netif_running(br->dev) ||
@@ -1265,14 +1262,10 @@
 	if (!group)
 		goto out;
 
-	br_vlan_get_tag(skb, &vid);
 	mp = br_mdb_ip6_get(mlock_dereference(br->mdb, br), group, vid);
 	if (!mp)
 		goto out;
 
-	mod_timer(&mp->timer, now + br->multicast_membership_interval);
-	mp->timer_armed = true;
-
 	max_delay *= br->multicast_last_member_count;
 	if (mp->mglist &&
 	    (timer_pending(&mp->timer) ?
@@ -1358,7 +1351,7 @@
 			call_rcu_bh(&p->rcu, br_multicast_free_pg);
 			br_mdb_notify(br->dev, port, group, RTM_DELMDB);
 
-			if (!mp->ports && !mp->mglist && mp->timer_armed &&
+			if (!mp->ports && !mp->mglist &&
 			    netif_running(br->dev))
 				mod_timer(&mp->timer, jiffies);
 		}
@@ -1370,12 +1363,30 @@
 		     br->multicast_last_member_interval;
 
 	if (!port) {
-		if (mp->mglist && mp->timer_armed &&
+		if (mp->mglist &&
 		    (timer_pending(&mp->timer) ?
 		     time_after(mp->timer.expires, time) :
 		     try_to_del_timer_sync(&mp->timer) >= 0)) {
 			mod_timer(&mp->timer, time);
 		}
+
+		goto out;
+	}
+
+	for (p = mlock_dereference(mp->ports, br);
+	     p != NULL;
+	     p = mlock_dereference(p->next, br)) {
+		if (p->port != port)
+			continue;
+
+		if (!hlist_unhashed(&p->mglist) &&
+		    (timer_pending(&p->timer) ?
+		     time_after(p->timer.expires, time) :
+		     try_to_del_timer_sync(&p->timer) >= 0)) {
+			mod_timer(&p->timer, time);
+		}
+
+		break;
 	}
 out:
 	spin_unlock(&br->multicast_lock);
@@ -1424,7 +1435,8 @@
 
 static int br_multicast_ipv4_rcv(struct net_bridge *br,
 				 struct net_bridge_port *port,
-				 struct sk_buff *skb)
+				 struct sk_buff *skb,
+				 u16 vid)
 {
 	struct sk_buff *skb2 = skb;
 	const struct iphdr *iph;
@@ -1432,7 +1444,6 @@
 	unsigned int len;
 	unsigned int offset;
 	int err;
-	u16 vid = 0;
 
 	/* We treat OOM as packet loss for now. */
 	if (!pskb_may_pull(skb, sizeof(*iph)))
@@ -1493,7 +1504,6 @@
 
 	err = 0;
 
-	br_vlan_get_tag(skb2, &vid);
 	BR_INPUT_SKB_CB(skb)->igmp = 1;
 	ih = igmp_hdr(skb2);
 
@@ -1504,10 +1514,10 @@
 		err = br_ip4_multicast_add_group(br, port, ih->group, vid);
 		break;
 	case IGMPV3_HOST_MEMBERSHIP_REPORT:
-		err = br_ip4_multicast_igmp3_report(br, port, skb2);
+		err = br_ip4_multicast_igmp3_report(br, port, skb2, vid);
 		break;
 	case IGMP_HOST_MEMBERSHIP_QUERY:
-		err = br_ip4_multicast_query(br, port, skb2);
+		err = br_ip4_multicast_query(br, port, skb2, vid);
 		break;
 	case IGMP_HOST_LEAVE_MESSAGE:
 		br_ip4_multicast_leave_group(br, port, ih->group, vid);
@@ -1525,7 +1535,8 @@
 #if IS_ENABLED(CONFIG_IPV6)
 static int br_multicast_ipv6_rcv(struct net_bridge *br,
 				 struct net_bridge_port *port,
-				 struct sk_buff *skb)
+				 struct sk_buff *skb,
+				 u16 vid)
 {
 	struct sk_buff *skb2;
 	const struct ipv6hdr *ip6h;
@@ -1535,7 +1546,6 @@
 	unsigned int len;
 	int offset;
 	int err;
-	u16 vid = 0;
 
 	if (!pskb_may_pull(skb, sizeof(*ip6h)))
 		return -EINVAL;
@@ -1625,7 +1635,6 @@
 
 	err = 0;
 
-	br_vlan_get_tag(skb, &vid);
 	BR_INPUT_SKB_CB(skb)->igmp = 1;
 
 	switch (icmp6_type) {
@@ -1642,10 +1651,10 @@
 		break;
 	    }
 	case ICMPV6_MLD2_REPORT:
-		err = br_ip6_multicast_mld2_report(br, port, skb2);
+		err = br_ip6_multicast_mld2_report(br, port, skb2, vid);
 		break;
 	case ICMPV6_MGM_QUERY:
-		err = br_ip6_multicast_query(br, port, skb2);
+		err = br_ip6_multicast_query(br, port, skb2, vid);
 		break;
 	case ICMPV6_MGM_REDUCTION:
 	    {
@@ -1666,7 +1675,7 @@
 #endif
 
 int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port,
-		     struct sk_buff *skb)
+		     struct sk_buff *skb, u16 vid)
 {
 	BR_INPUT_SKB_CB(skb)->igmp = 0;
 	BR_INPUT_SKB_CB(skb)->mrouters_only = 0;
@@ -1676,10 +1685,10 @@
 
 	switch (skb->protocol) {
 	case htons(ETH_P_IP):
-		return br_multicast_ipv4_rcv(br, port, skb);
+		return br_multicast_ipv4_rcv(br, port, skb, vid);
 #if IS_ENABLED(CONFIG_IPV6)
 	case htons(ETH_P_IPV6):
-		return br_multicast_ipv6_rcv(br, port, skb);
+		return br_multicast_ipv6_rcv(br, port, skb, vid);
 #endif
 	}
 
@@ -1798,7 +1807,6 @@
 		hlist_for_each_entry_safe(mp, n, &mdb->mhash[i],
 					  hlist[ver]) {
 			del_timer(&mp->timer);
-			mp->timer_armed = false;
 			call_rcu_bh(&mp->rcu, br_multicast_free_group);
 		}
 	}
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index e74ddc1..f75d92e 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -243,7 +243,7 @@
 
 		vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]);
 
-		if (vinfo->vid >= VLAN_N_VID)
+		if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
 			return -EINVAL;
 
 		switch (cmd) {
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index efb57d9..2e8244e 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -126,7 +126,6 @@
 	struct timer_list		timer;
 	struct br_ip			addr;
 	bool				mglist;
-	bool				timer_armed;
 };
 
 struct net_bridge_mdb_htable
@@ -452,7 +451,8 @@
 extern unsigned int br_mdb_rehash_seq;
 extern int br_multicast_rcv(struct net_bridge *br,
 			    struct net_bridge_port *port,
-			    struct sk_buff *skb);
+			    struct sk_buff *skb,
+			    u16 vid);
 extern struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
 					       struct sk_buff *skb, u16 vid);
 extern void br_multicast_add_port(struct net_bridge_port *port);
@@ -523,7 +523,8 @@
 #else
 static inline int br_multicast_rcv(struct net_bridge *br,
 				   struct net_bridge_port *port,
-				   struct sk_buff *skb)
+				   struct sk_buff *skb,
+				   u16 vid)
 {
 	return 0;
 }
@@ -643,9 +644,7 @@
 	 * vid wasn't set
 	 */
 	smp_rmb();
-	return (v->pvid & VLAN_TAG_PRESENT) ?
-			(v->pvid & ~VLAN_TAG_PRESENT) :
-			VLAN_N_VID;
+	return v->pvid ?: VLAN_N_VID;
 }
 
 #else
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index 108084a..656a6f3 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -134,7 +134,7 @@
 
 	if (br->bridge_forward_delay < BR_MIN_FORWARD_DELAY)
 		__br_set_forward_delay(br, BR_MIN_FORWARD_DELAY);
-	else if (br->bridge_forward_delay < BR_MAX_FORWARD_DELAY)
+	else if (br->bridge_forward_delay > BR_MAX_FORWARD_DELAY)
 		__br_set_forward_delay(br, BR_MAX_FORWARD_DELAY);
 
 	if (r == 0) {
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 9a9ffe7..53f0990 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -45,37 +45,34 @@
 		return 0;
 	}
 
-	if (vid) {
-		if (v->port_idx) {
-			p = v->parent.port;
-			br = p->br;
-			dev = p->dev;
-		} else {
-			br = v->parent.br;
-			dev = br->dev;
-		}
-		ops = dev->netdev_ops;
+	if (v->port_idx) {
+		p = v->parent.port;
+		br = p->br;
+		dev = p->dev;
+	} else {
+		br = v->parent.br;
+		dev = br->dev;
+	}
+	ops = dev->netdev_ops;
 
-		if (p && (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) {
-			/* Add VLAN to the device filter if it is supported.
-			 * Stricly speaking, this is not necessary now, since
-			 * devices are made promiscuous by the bridge, but if
-			 * that ever changes this code will allow tagged
-			 * traffic to enter the bridge.
-			 */
-			err = ops->ndo_vlan_rx_add_vid(dev, htons(ETH_P_8021Q),
-						       vid);
-			if (err)
-				return err;
-		}
+	if (p && (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) {
+		/* Add VLAN to the device filter if it is supported.
+		 * Stricly speaking, this is not necessary now, since
+		 * devices are made promiscuous by the bridge, but if
+		 * that ever changes this code will allow tagged
+		 * traffic to enter the bridge.
+		 */
+		err = ops->ndo_vlan_rx_add_vid(dev, htons(ETH_P_8021Q),
+					       vid);
+		if (err)
+			return err;
+	}
 
-		err = br_fdb_insert(br, p, dev->dev_addr, vid);
-		if (err) {
-			br_err(br, "failed insert local address into bridge "
-			       "forwarding table\n");
-			goto out_filt;
-		}
-
+	err = br_fdb_insert(br, p, dev->dev_addr, vid);
+	if (err) {
+		br_err(br, "failed insert local address into bridge "
+		       "forwarding table\n");
+		goto out_filt;
 	}
 
 	set_bit(vid, v->vlan_bitmap);
@@ -98,7 +95,7 @@
 	__vlan_delete_pvid(v, vid);
 	clear_bit(vid, v->untagged_bitmap);
 
-	if (v->port_idx && vid) {
+	if (v->port_idx) {
 		struct net_device *dev = v->parent.port->dev;
 		const struct net_device_ops *ops = dev->netdev_ops;
 
@@ -192,6 +189,8 @@
 bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
 			struct sk_buff *skb, u16 *vid)
 {
+	int err;
+
 	/* If VLAN filtering is disabled on the bridge, all packets are
 	 * permitted.
 	 */
@@ -204,20 +203,32 @@
 	if (!v)
 		return false;
 
-	if (br_vlan_get_tag(skb, vid)) {
+	err = br_vlan_get_tag(skb, vid);
+	if (!*vid) {
 		u16 pvid = br_get_pvid(v);
 
-		/* Frame did not have a tag.  See if pvid is set
-		 * on this port.  That tells us which vlan untagged
-		 * traffic belongs to.
+		/* Frame had a tag with VID 0 or did not have a tag.
+		 * See if pvid is set on this port.  That tells us which
+		 * vlan untagged or priority-tagged traffic belongs to.
 		 */
 		if (pvid == VLAN_N_VID)
 			return false;
 
-		/* PVID is set on this port.  Any untagged ingress
-		 * frame is considered to belong to this vlan.
+		/* PVID is set on this port.  Any untagged or priority-tagged
+		 * ingress frame is considered to belong to this vlan.
 		 */
-		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), pvid);
+		*vid = pvid;
+		if (likely(err))
+			/* Untagged Frame. */
+			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), pvid);
+		else
+			/* Priority-tagged Frame.
+			 * At this point, We know that skb->vlan_tci had
+			 * VLAN_TAG_PRESENT bit and its VID field was 0x000.
+			 * We update only VID field and preserve PCP field.
+			 */
+			skb->vlan_tci |= pvid;
+
 		return true;
 	}
 
@@ -248,7 +259,9 @@
 	return false;
 }
 
-/* Must be protected by RTNL */
+/* Must be protected by RTNL.
+ * Must be called with vid in range from 1 to 4094 inclusive.
+ */
 int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags)
 {
 	struct net_port_vlans *pv = NULL;
@@ -278,7 +291,9 @@
 	return err;
 }
 
-/* Must be protected by RTNL */
+/* Must be protected by RTNL.
+ * Must be called with vid in range from 1 to 4094 inclusive.
+ */
 int br_vlan_delete(struct net_bridge *br, u16 vid)
 {
 	struct net_port_vlans *pv;
@@ -289,14 +304,9 @@
 	if (!pv)
 		return -EINVAL;
 
-	if (vid) {
-		/* If the VID !=0 remove fdb for this vid. VID 0 is special
-		 * in that it's the default and is always there in the fdb.
-		 */
-		spin_lock_bh(&br->hash_lock);
-		fdb_delete_by_addr(br, br->dev->dev_addr, vid);
-		spin_unlock_bh(&br->hash_lock);
-	}
+	spin_lock_bh(&br->hash_lock);
+	fdb_delete_by_addr(br, br->dev->dev_addr, vid);
+	spin_unlock_bh(&br->hash_lock);
 
 	__vlan_del(pv, vid);
 	return 0;
@@ -329,7 +339,9 @@
 	return 0;
 }
 
-/* Must be protected by RTNL */
+/* Must be protected by RTNL.
+ * Must be called with vid in range from 1 to 4094 inclusive.
+ */
 int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags)
 {
 	struct net_port_vlans *pv = NULL;
@@ -363,7 +375,9 @@
 	return err;
 }
 
-/* Must be protected by RTNL */
+/* Must be protected by RTNL.
+ * Must be called with vid in range from 1 to 4094 inclusive.
+ */
 int nbp_vlan_delete(struct net_bridge_port *port, u16 vid)
 {
 	struct net_port_vlans *pv;
@@ -374,14 +388,9 @@
 	if (!pv)
 		return -EINVAL;
 
-	if (vid) {
-		/* If the VID !=0 remove fdb for this vid. VID 0 is special
-		 * in that it's the default and is always there in the fdb.
-		 */
-		spin_lock_bh(&port->br->hash_lock);
-		fdb_delete_by_addr(port->br, port->dev->dev_addr, vid);
-		spin_unlock_bh(&port->br->hash_lock);
-	}
+	spin_lock_bh(&port->br->hash_lock);
+	fdb_delete_by_addr(port->br, port->dev->dev_addr, vid);
+	spin_unlock_bh(&port->br->hash_lock);
 
 	return __vlan_del(pv, vid);
 }
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index 5180938..7c470c3 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -181,6 +181,7 @@
 	ub->qlen++;
 
 	pm = nlmsg_data(nlh);
+	memset(pm, 0, sizeof(*pm));
 
 	/* Fill in the ulog data */
 	pm->version = EBT_ULOG_VERSION;
@@ -193,8 +194,6 @@
 	pm->hook = hooknr;
 	if (uloginfo->prefix != NULL)
 		strcpy(pm->prefix, uloginfo->prefix);
-	else
-		*(pm->prefix) = '\0';
 
 	if (in) {
 		strcpy(pm->physindev, in->name);
@@ -204,16 +203,14 @@
 			strcpy(pm->indev, br_port_get_rcu(in)->br->dev->name);
 		else
 			strcpy(pm->indev, in->name);
-	} else
-		pm->indev[0] = pm->physindev[0] = '\0';
+	}
 
 	if (out) {
 		/* If out exists, then out is a bridge port */
 		strcpy(pm->physoutdev, out->name);
 		/* rcu_read_lock()ed by nf_hook_slow */
 		strcpy(pm->outdev, br_port_get_rcu(out)->br->dev->name);
-	} else
-		pm->outdev[0] = pm->physoutdev[0] = '\0';
+	}
 
 	if (skb_copy_bits(skb, -ETH_HLEN, pm->data, copy_len) < 0)
 		BUG();
diff --git a/net/compat.c b/net/compat.c
index f0a1ba6..8903258 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -71,6 +71,8 @@
 	    __get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
 	    __get_user(kmsg->msg_flags, &umsg->msg_flags))
 		return -EFAULT;
+	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
+		return -EINVAL;
 	kmsg->msg_name = compat_ptr(tmp1);
 	kmsg->msg_iov = compat_ptr(tmp2);
 	kmsg->msg_control = compat_ptr(tmp3);
diff --git a/net/core/dev.c b/net/core/dev.c
index 65f829c..3430b1e 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1917,7 +1917,8 @@
 	return new_map;
 }
 
-int netif_set_xps_queue(struct net_device *dev, struct cpumask *mask, u16 index)
+int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,
+			u16 index)
 {
 	struct xps_dev_maps *dev_maps, *new_dev_maps = NULL;
 	struct xps_map *map, *new_map;
diff --git a/net/core/filter.c b/net/core/filter.c
index 6438f29..01b7808 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -644,7 +644,6 @@
 	struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu);
 
 	bpf_jit_free(fp);
-	kfree(fp);
 }
 EXPORT_SYMBOL(sk_filter_release_rcu);
 
@@ -683,7 +682,7 @@
 	if (fprog->filter == NULL)
 		return -EINVAL;
 
-	fp = kmalloc(fsize + sizeof(*fp), GFP_KERNEL);
+	fp = kmalloc(sk_filter_size(fprog->len), GFP_KERNEL);
 	if (!fp)
 		return -ENOMEM;
 	memcpy(fp->insns, fprog->filter, fsize);
@@ -723,6 +722,7 @@
 {
 	struct sk_filter *fp, *old_fp;
 	unsigned int fsize = sizeof(struct sock_filter) * fprog->len;
+	unsigned int sk_fsize = sk_filter_size(fprog->len);
 	int err;
 
 	if (sock_flag(sk, SOCK_FILTER_LOCKED))
@@ -732,11 +732,11 @@
 	if (fprog->filter == NULL)
 		return -EINVAL;
 
-	fp = sock_kmalloc(sk, fsize+sizeof(*fp), GFP_KERNEL);
+	fp = sock_kmalloc(sk, sk_fsize, GFP_KERNEL);
 	if (!fp)
 		return -ENOMEM;
 	if (copy_from_user(fp->insns, fprog->filter, fsize)) {
-		sock_kfree_s(sk, fp, fsize+sizeof(*fp));
+		sock_kfree_s(sk, fp, sk_fsize);
 		return -EFAULT;
 	}
 
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 8d7d0dd..143b6fd 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -40,7 +40,7 @@
 		struct iphdr _iph;
 ip:
 		iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
-		if (!iph)
+		if (!iph || iph->ihl < 5)
 			return false;
 
 		if (ip_is_fragment(iph))
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index d954b56..325dee8 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -1344,17 +1344,19 @@
 	return error;
 }
 
-int netdev_class_create_file(struct class_attribute *class_attr)
+int netdev_class_create_file_ns(struct class_attribute *class_attr,
+				const void *ns)
 {
-	return class_create_file(&net_class, class_attr);
+	return class_create_file_ns(&net_class, class_attr, ns);
 }
-EXPORT_SYMBOL(netdev_class_create_file);
+EXPORT_SYMBOL(netdev_class_create_file_ns);
 
-void netdev_class_remove_file(struct class_attribute *class_attr)
+void netdev_class_remove_file_ns(struct class_attribute *class_attr,
+				 const void *ns)
 {
-	class_remove_file(&net_class, class_attr);
+	class_remove_file_ns(&net_class, class_attr, ns);
 }
-EXPORT_SYMBOL(netdev_class_remove_file);
+EXPORT_SYMBOL(netdev_class_remove_file_ns);
 
 int netdev_kobject_init(void)
 {
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index fc75c9e..8f97199 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -636,8 +636,9 @@
 
 			netpoll_send_skb(np, send_skb);
 
-			/* If there are several rx_hooks for the same address,
-			   we're fine by sending a single reply */
+			/* If there are several rx_skb_hooks for the same
+			 * address we're fine by sending a single reply
+			 */
 			break;
 		}
 		spin_unlock_irqrestore(&npinfo->rx_lock, flags);
@@ -719,8 +720,9 @@
 
 			netpoll_send_skb(np, send_skb);
 
-			/* If there are several rx_hooks for the same address,
-			   we're fine by sending a single reply */
+			/* If there are several rx_skb_hooks for the same
+			 * address, we're fine by sending a single reply
+			 */
 			break;
 		}
 		spin_unlock_irqrestore(&npinfo->rx_lock, flags);
@@ -756,11 +758,12 @@
 
 int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)
 {
-	int proto, len, ulen;
-	int hits = 0;
+	int proto, len, ulen, data_len;
+	int hits = 0, offset;
 	const struct iphdr *iph;
 	struct udphdr *uh;
 	struct netpoll *np, *tmp;
+	uint16_t source;
 
 	if (list_empty(&npinfo->rx_np))
 		goto out;
@@ -820,7 +823,10 @@
 
 		len -= iph->ihl*4;
 		uh = (struct udphdr *)(((char *)iph) + iph->ihl*4);
+		offset = (unsigned char *)(uh + 1) - skb->data;
 		ulen = ntohs(uh->len);
+		data_len = skb->len - offset;
+		source = ntohs(uh->source);
 
 		if (ulen != len)
 			goto out;
@@ -834,9 +840,7 @@
 			if (np->local_port && np->local_port != ntohs(uh->dest))
 				continue;
 
-			np->rx_hook(np, ntohs(uh->source),
-				       (char *)(uh+1),
-				       ulen - sizeof(struct udphdr));
+			np->rx_skb_hook(np, source, skb, offset, data_len);
 			hits++;
 		}
 	} else {
@@ -859,7 +863,10 @@
 		if (!pskb_may_pull(skb, sizeof(struct udphdr)))
 			goto out;
 		uh = udp_hdr(skb);
+		offset = (unsigned char *)(uh + 1) - skb->data;
 		ulen = ntohs(uh->len);
+		data_len = skb->len - offset;
+		source = ntohs(uh->source);
 		if (ulen != skb->len)
 			goto out;
 		if (udp6_csum_init(skb, uh, IPPROTO_UDP))
@@ -872,9 +879,7 @@
 			if (np->local_port && np->local_port != ntohs(uh->dest))
 				continue;
 
-			np->rx_hook(np, ntohs(uh->source),
-				       (char *)(uh+1),
-				       ulen - sizeof(struct udphdr));
+			np->rx_skb_hook(np, source, skb, offset, data_len);
 			hits++;
 		}
 #endif
@@ -1062,7 +1067,7 @@
 
 	npinfo->netpoll = np;
 
-	if (np->rx_hook) {
+	if (np->rx_skb_hook) {
 		spin_lock_irqsave(&npinfo->rx_lock, flags);
 		npinfo->rx_flags |= NETPOLL_RX_ENABLED;
 		list_add_tail(&np->rx, &npinfo->rx_np);
diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c
index 3f1ec15..8d9d05e 100644
--- a/net/core/secure_seq.c
+++ b/net/core/secure_seq.c
@@ -10,6 +10,7 @@
 
 #include <net/secure_seq.h>
 
+#if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_INET)
 #define NET_SECRET_SIZE (MD5_MESSAGE_BYTES / 4)
 
 static u32 net_secret[NET_SECRET_SIZE] ____cacheline_aligned;
@@ -29,6 +30,7 @@
 		cmpxchg(&net_secret[--i], 0, tmp);
 	}
 }
+#endif
 
 #ifdef CONFIG_INET
 static u32 seq_scale(u32 seq)
diff --git a/net/core/sock.c b/net/core/sock.c
index 5b6beba..0b39e7a 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2319,6 +2319,7 @@
 	sk->sk_ll_usec		=	sysctl_net_busy_read;
 #endif
 
+	sk->sk_pacing_rate = ~0U;
 	/*
 	 * Before updating sk_refcnt, we must commit prior changes to memory
 	 * (Documentation/RCU/rculist_nulls.txt for details)
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index c85e71e..ff41b4d 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -1372,6 +1372,8 @@
 	real_dev = dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
 	if (!real_dev)
 		return -ENODEV;
+	if (real_dev->type != ARPHRD_IEEE802154)
+		return -EINVAL;
 
 	lowpan_dev_info(dev)->real_dev = real_dev;
 	lowpan_dev_info(dev)->fragment_tag = 0;
@@ -1386,6 +1388,9 @@
 
 	entry->ldev = dev;
 
+	/* Set the lowpan harware address to the wpan hardware address. */
+	memcpy(dev->dev_addr, real_dev->dev_addr, IEEE802154_ADDR_LEN);
+
 	mutex_lock(&lowpan_dev_info(dev)->dev_list_mtx);
 	INIT_LIST_HEAD(&entry->list);
 	list_add_tail(&entry->list, &lowpan_devices);
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 7bd8983..96da9c7 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -287,7 +287,7 @@
 			if (unlikely(!INET_TW_MATCH(sk, net, acookie,
 						    saddr, daddr, ports,
 						    dif))) {
-				sock_put(sk);
+				inet_twsk_put(inet_twsk(sk));
 				goto begintw;
 			}
 			goto out;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index a04d872..3982eab 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -772,15 +772,20 @@
 		/* initialize protocol header pointer */
 		skb->transport_header = skb->network_header + fragheaderlen;
 
-		skb->ip_summed = CHECKSUM_PARTIAL;
 		skb->csum = 0;
 
-		/* specify the length of each IP datagram fragment */
-		skb_shinfo(skb)->gso_size = maxfraglen - fragheaderlen;
-		skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
+
 		__skb_queue_tail(queue, skb);
+	} else if (skb_is_gso(skb)) {
+		goto append;
 	}
 
+	skb->ip_summed = CHECKSUM_PARTIAL;
+	/* specify the length of each IP datagram fragment */
+	skb_shinfo(skb)->gso_size = maxfraglen - fragheaderlen;
+	skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
+
+append:
 	return skb_append_datato_frags(sk, skb, getfrag, from,
 				       (length - transhdrlen));
 }
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index e805e7b..6e87f85 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -125,8 +125,17 @@
 				  iph->saddr, iph->daddr, 0);
 	if (tunnel != NULL) {
 		struct pcpu_tstats *tstats;
+		u32 oldmark = skb->mark;
+		int ret;
 
-		if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
+
+		/* temporarily mark the skb with the tunnel o_key, to
+		 * only match policies with this mark.
+		 */
+		skb->mark = be32_to_cpu(tunnel->parms.o_key);
+		ret = xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb);
+		skb->mark = oldmark;
+		if (!ret)
 			return -1;
 
 		tstats = this_cpu_ptr(tunnel->dev->tstats);
@@ -135,7 +144,6 @@
 		tstats->rx_bytes += skb->len;
 		u64_stats_update_end(&tstats->syncp);
 
-		skb->mark = 0;
 		secpath_reset(skb);
 		skb->dev = tunnel->dev;
 		return 1;
@@ -167,7 +175,7 @@
 
 	memset(&fl4, 0, sizeof(fl4));
 	flowi4_init_output(&fl4, tunnel->parms.link,
-			   be32_to_cpu(tunnel->parms.i_key), RT_TOS(tos),
+			   be32_to_cpu(tunnel->parms.o_key), RT_TOS(tos),
 			   RT_SCOPE_UNIVERSE,
 			   IPPROTO_IPIP, 0,
 			   dst, tiph->saddr, 0, 0);
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 85a4f21..59da7cd 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -271,6 +271,11 @@
 	local_bh_disable();
 	addend = xt_write_recseq_begin();
 	private = table->private;
+	/*
+	 * Ensure we load private-> members after we've fetched the base
+	 * pointer.
+	 */
+	smp_read_barrier_depends();
 	table_base = private->entries[smp_processor_id()];
 
 	e = get_entry(table_base, private->hook_entry[hook]);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index d23118d..718dfbd 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -327,6 +327,11 @@
 	addend = xt_write_recseq_begin();
 	private = table->private;
 	cpu        = smp_processor_id();
+	/*
+	 * Ensure we load private-> members after we've fetched the base
+	 * pointer.
+	 */
+	smp_read_barrier_depends();
 	table_base = private->entries[cpu];
 	jumpstack  = (struct ipt_entry **)private->jumpstack[cpu];
 	stackptr   = per_cpu_ptr(private->stackptr, cpu);
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index cbc2215..9cb993c 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -220,6 +220,7 @@
 	ub->qlen++;
 
 	pm = nlmsg_data(nlh);
+	memset(pm, 0, sizeof(*pm));
 
 	/* We might not have a timestamp, get one */
 	if (skb->tstamp.tv64 == 0)
@@ -238,8 +239,6 @@
 	}
 	else if (loginfo->prefix[0] != '\0')
 		strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix));
-	else
-		*(pm->prefix) = '\0';
 
 	if (in && in->hard_header_len > 0 &&
 	    skb->mac_header != skb->network_header &&
@@ -251,13 +250,9 @@
 
 	if (in)
 		strncpy(pm->indev_name, in->name, sizeof(pm->indev_name));
-	else
-		pm->indev_name[0] = '\0';
 
 	if (out)
 		strncpy(pm->outdev_name, out->name, sizeof(pm->outdev_name));
-	else
-		pm->outdev_name[0] = '\0';
 
 	/* copy_len <= skb->len, so can't fail. */
 	if (skb_copy_bits(skb, 0, pm->payload, copy_len) < 0)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 727f436..6011615 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2072,7 +2072,7 @@
 							      RT_SCOPE_LINK);
 			goto make_route;
 		}
-		if (fl4->saddr) {
+		if (!fl4->saddr) {
 			if (ipv4_is_multicast(fl4->daddr))
 				fl4->saddr = inet_select_addr(dev_out, 0,
 							      fl4->flowi4_scope);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 25a89ea..068c8fb 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1284,7 +1284,10 @@
 		tp->lost_cnt_hint -= tcp_skb_pcount(prev);
 	}
 
-	TCP_SKB_CB(skb)->tcp_flags |= TCP_SKB_CB(prev)->tcp_flags;
+	TCP_SKB_CB(prev)->tcp_flags |= TCP_SKB_CB(skb)->tcp_flags;
+	if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
+		TCP_SKB_CB(prev)->end_seq++;
+
 	if (skb == tcp_highest_sack(sk))
 		tcp_advance_highest_sack(sk, skb);
 
@@ -2853,7 +2856,8 @@
 	 * left edge of the send window.
 	 * See draft-ietf-tcplw-high-performance-00, section 3.3.
 	 */
-	if (seq_rtt < 0 && tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr)
+	if (seq_rtt < 0 && tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr &&
+	    flag & FLAG_ACKED)
 		seq_rtt = tcp_time_stamp - tp->rx_opt.rcv_tsecr;
 
 	if (seq_rtt < 0)
@@ -2868,14 +2872,19 @@
 }
 
 /* Compute time elapsed between (last) SYNACK and the ACK completing 3WHS. */
-static void tcp_synack_rtt_meas(struct sock *sk, struct request_sock *req)
+static void tcp_synack_rtt_meas(struct sock *sk, const u32 synack_stamp)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 	s32 seq_rtt = -1;
 
-	if (tp->lsndtime && !tp->total_retrans)
-		seq_rtt = tcp_time_stamp - tp->lsndtime;
-	tcp_ack_update_rtt(sk, FLAG_SYN_ACKED, seq_rtt, -1);
+	if (synack_stamp && !tp->total_retrans)
+		seq_rtt = tcp_time_stamp - synack_stamp;
+
+	/* If the ACK acks both the SYNACK and the (Fast Open'd) data packets
+	 * sent in SYN_RECV, SYNACK RTT is the smooth RTT computed in tcp_ack()
+	 */
+	if (!tp->srtt)
+		tcp_ack_update_rtt(sk, FLAG_SYN_ACKED, seq_rtt, -1);
 }
 
 static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
@@ -2978,6 +2987,7 @@
 	s32 seq_rtt = -1;
 	s32 ca_seq_rtt = -1;
 	ktime_t last_ackt = net_invalid_timestamp();
+	bool rtt_update;
 
 	while ((skb = tcp_write_queue_head(sk)) && skb != tcp_send_head(sk)) {
 		struct tcp_skb_cb *scb = TCP_SKB_CB(skb);
@@ -3054,14 +3064,13 @@
 	if (skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED))
 		flag |= FLAG_SACK_RENEGING;
 
-	if (tcp_ack_update_rtt(sk, flag, seq_rtt, sack_rtt) ||
-	    (flag & FLAG_ACKED))
-		tcp_rearm_rto(sk);
+	rtt_update = tcp_ack_update_rtt(sk, flag, seq_rtt, sack_rtt);
 
 	if (flag & FLAG_ACKED) {
 		const struct tcp_congestion_ops *ca_ops
 			= inet_csk(sk)->icsk_ca_ops;
 
+		tcp_rearm_rto(sk);
 		if (unlikely(icsk->icsk_mtup.probe_size &&
 			     !after(tp->mtu_probe.probe_seq_end, tp->snd_una))) {
 			tcp_mtup_probe_success(sk);
@@ -3100,6 +3109,13 @@
 
 			ca_ops->pkts_acked(sk, pkts_acked, rtt_us);
 		}
+	} else if (skb && rtt_update && sack_rtt >= 0 &&
+		   sack_rtt > (s32)(now - TCP_SKB_CB(skb)->when)) {
+		/* Do not re-arm RTO if the sack RTT is measured from data sent
+		 * after when the head was last (re)transmitted. Otherwise the
+		 * timeout may continue to extend in loss recovery.
+		 */
+		tcp_rearm_rto(sk);
 	}
 
 #if FASTRETRANS_DEBUG > 0
@@ -3288,7 +3304,7 @@
 			tcp_init_cwnd_reduction(sk, true);
 			tcp_set_ca_state(sk, TCP_CA_CWR);
 			tcp_end_cwnd_reduction(sk);
-			tcp_set_ca_state(sk, TCP_CA_Open);
+			tcp_try_keep_open(sk);
 			NET_INC_STATS_BH(sock_net(sk),
 					 LINUX_MIB_TCPLOSSPROBERECOVERY);
 		}
@@ -5584,6 +5600,7 @@
 	struct request_sock *req;
 	int queued = 0;
 	bool acceptable;
+	u32 synack_stamp;
 
 	tp->rx_opt.saw_tstamp = 0;
 
@@ -5666,9 +5683,11 @@
 		 * so release it.
 		 */
 		if (req) {
+			synack_stamp = tcp_rsk(req)->snt_synack;
 			tp->total_retrans = req->num_retrans;
 			reqsk_fastopen_remove(sk, req, false);
 		} else {
+			synack_stamp = tp->lsndtime;
 			/* Make sure socket is routed, for correct metrics. */
 			icsk->icsk_af_ops->rebuild_header(sk);
 			tcp_init_congestion_control(sk);
@@ -5691,7 +5710,7 @@
 		tp->snd_una = TCP_SKB_CB(skb)->ack_seq;
 		tp->snd_wnd = ntohs(th->window) << tp->rx_opt.snd_wscale;
 		tcp_init_wl(tp, TCP_SKB_CB(skb)->seq);
-		tcp_synack_rtt_meas(sk, req);
+		tcp_synack_rtt_meas(sk, synack_stamp);
 
 		if (tp->rx_opt.tstamp_ok)
 			tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;
@@ -5709,6 +5728,8 @@
 		} else
 			tcp_init_metrics(sk);
 
+		tcp_update_pacing_rate(sk);
+
 		/* Prevent spurious tcp_cwnd_restart() on first data packet */
 		tp->lsndtime = tcp_time_stamp;
 
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
index 3a7525e..533c58a 100644
--- a/net/ipv4/tcp_offload.c
+++ b/net/ipv4/tcp_offload.c
@@ -18,6 +18,7 @@
 				netdev_features_t features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
+	unsigned int sum_truesize = 0;
 	struct tcphdr *th;
 	unsigned int thlen;
 	unsigned int seq;
@@ -102,13 +103,7 @@
 		if (copy_destructor) {
 			skb->destructor = gso_skb->destructor;
 			skb->sk = gso_skb->sk;
-			/* {tcp|sock}_wfree() use exact truesize accounting :
-			 * sum(skb->truesize) MUST be exactly be gso_skb->truesize
-			 * So we account mss bytes of 'true size' for each segment.
-			 * The last segment will contain the remaining.
-			 */
-			skb->truesize = mss;
-			gso_skb->truesize -= mss;
+			sum_truesize += skb->truesize;
 		}
 		skb = skb->next;
 		th = tcp_hdr(skb);
@@ -125,7 +120,9 @@
 	if (copy_destructor) {
 		swap(gso_skb->sk, skb->sk);
 		swap(gso_skb->destructor, skb->destructor);
-		swap(gso_skb->truesize, skb->truesize);
+		sum_truesize += skb->truesize;
+		atomic_add(sum_truesize - gso_skb->truesize,
+			   &skb->sk->sk_wmem_alloc);
 	}
 
 	delta = htonl(oldlen + (skb_tail_pointer(skb) -
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index e6bb825..d46f214 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -637,6 +637,8 @@
 	unsigned int size = 0;
 	unsigned int eff_sacks;
 
+	opts->options = 0;
+
 #ifdef CONFIG_TCP_MD5SIG
 	*md5 = tp->af_specific->md5_lookup(sk, sk);
 	if (unlikely(*md5)) {
@@ -984,8 +986,10 @@
 static void tcp_set_skb_tso_segs(const struct sock *sk, struct sk_buff *skb,
 				 unsigned int mss_now)
 {
-	if (skb->len <= mss_now || !sk_can_gso(sk) ||
-	    skb->ip_summed == CHECKSUM_NONE) {
+	/* Make sure we own this skb before messing gso_size/gso_segs */
+	WARN_ON_ONCE(skb_cloned(skb));
+
+	if (skb->len <= mss_now || skb->ip_summed == CHECKSUM_NONE) {
 		/* Avoid the costly divide in the normal
 		 * non-TSO case.
 		 */
@@ -1065,9 +1069,7 @@
 	if (nsize < 0)
 		nsize = 0;
 
-	if (skb_cloned(skb) &&
-	    skb_is_nonlinear(skb) &&
-	    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+	if (skb_unclone(skb, GFP_ATOMIC))
 		return -ENOMEM;
 
 	/* Get a new skb... force flag on. */
@@ -2342,6 +2344,8 @@
 		int oldpcount = tcp_skb_pcount(skb);
 
 		if (unlikely(oldpcount > 1)) {
+			if (skb_unclone(skb, GFP_ATOMIC))
+				return -ENOMEM;
 			tcp_init_tso_segs(sk, skb, cur_mss);
 			tcp_adjust_pcount(sk, skb, oldpcount - tcp_skb_pcount(skb));
 		}
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 9a459be..e1a6393 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -104,9 +104,14 @@
 	const struct iphdr *iph = ip_hdr(skb);
 	u8 *xprth = skb_network_header(skb) + iph->ihl * 4;
 	struct flowi4 *fl4 = &fl->u.ip4;
+	int oif = 0;
+
+	if (skb_dst(skb))
+		oif = skb_dst(skb)->dev->ifindex;
 
 	memset(fl4, 0, sizeof(struct flowi4));
 	fl4->flowi4_mark = skb->mark;
+	fl4->flowi4_oif = reverse ? skb->skb_iif : oif;
 
 	if (!ip_is_fragment(iph)) {
 		switch (iph->protocol) {
@@ -235,7 +240,7 @@
 	.destroy =		xfrm4_dst_destroy,
 	.ifdown =		xfrm4_dst_ifdown,
 	.local_out =		__ip_local_out,
-	.gc_thresh =		1024,
+	.gc_thresh =		32768,
 };
 
 static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 73784c3..82e1da3 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -618,8 +618,7 @@
 	struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+offset);
 	struct xfrm_state *x;
 
-	if (type != ICMPV6_DEST_UNREACH &&
-	    type != ICMPV6_PKT_TOOBIG &&
+	if (type != ICMPV6_PKT_TOOBIG &&
 	    type != NDISC_REDIRECT)
 		return;
 
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index d3618a7..e67e63f 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -436,8 +436,7 @@
 	struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data + offset);
 	struct xfrm_state *x;
 
-	if (type != ICMPV6_DEST_UNREACH &&
-	    type != ICMPV6_PKT_TOOBIG &&
+	if (type != ICMPV6_PKT_TOOBIG &&
 	    type != NDISC_REDIRECT)
 		return;
 
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 32b4a16..066640e 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -116,7 +116,7 @@
 			}
 			if (unlikely(!INET6_TW_MATCH(sk, net, saddr, daddr,
 						     ports, dif))) {
-				sock_put(sk);
+				inet_twsk_put(inet_twsk(sk));
 				goto begintw;
 			}
 			goto out;
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 7bb5446..bf4a9a0 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -976,6 +976,7 @@
 		if (t->parms.o_flags&GRE_SEQ)
 			addend += 4;
 	}
+	t->hlen = addend;
 
 	if (p->flags & IP6_TNL_F_CAP_XMIT) {
 		int strict = (ipv6_addr_type(&p->raddr) &
@@ -1002,8 +1003,6 @@
 		}
 		ip6_rt_put(rt);
 	}
-
-	t->hlen = addend;
 }
 
 static int ip6gre_tnl_change(struct ip6_tnl *t,
@@ -1173,9 +1172,8 @@
 
 static int ip6gre_tunnel_change_mtu(struct net_device *dev, int new_mtu)
 {
-	struct ip6_tnl *tunnel = netdev_priv(dev);
 	if (new_mtu < 68 ||
-	    new_mtu > 0xFFF8 - dev->hard_header_len - tunnel->hlen)
+	    new_mtu > 0xFFF8 - dev->hard_header_len)
 		return -EINVAL;
 	dev->mtu = new_mtu;
 	return 0;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index a54c45c..91fb4e8 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -105,7 +105,7 @@
 	}
 
 	rcu_read_lock_bh();
-	nexthop = rt6_nexthop((struct rt6_info *)dst, &ipv6_hdr(skb)->daddr);
+	nexthop = rt6_nexthop((struct rt6_info *)dst);
 	neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop);
 	if (unlikely(!neigh))
 		neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false);
@@ -874,7 +874,7 @@
 	 */
 	rt = (struct rt6_info *) *dst;
 	rcu_read_lock_bh();
-	n = __ipv6_neigh_lookup_noref(rt->dst.dev, rt6_nexthop(rt, &fl6->daddr));
+	n = __ipv6_neigh_lookup_noref(rt->dst.dev, rt6_nexthop(rt));
 	err = n && !(n->nud_state & NUD_VALID) ? -EINVAL : 0;
 	rcu_read_unlock_bh();
 
@@ -1008,6 +1008,7 @@
 
 {
 	struct sk_buff *skb;
+	struct frag_hdr fhdr;
 	int err;
 
 	/* There is support for UDP large send offload by network
@@ -1015,8 +1016,6 @@
 	 * udp datagram
 	 */
 	if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) {
-		struct frag_hdr fhdr;
-
 		skb = sock_alloc_send_skb(sk,
 			hh_len + fragheaderlen + transhdrlen + 20,
 			(flags & MSG_DONTWAIT), &err);
@@ -1036,20 +1035,24 @@
 		skb->transport_header = skb->network_header + fragheaderlen;
 
 		skb->protocol = htons(ETH_P_IPV6);
-		skb->ip_summed = CHECKSUM_PARTIAL;
 		skb->csum = 0;
 
-		/* Specify the length of each IPv6 datagram fragment.
-		 * It has to be a multiple of 8.
-		 */
-		skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
-					     sizeof(struct frag_hdr)) & ~7;
-		skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
-		ipv6_select_ident(&fhdr, rt);
-		skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
 		__skb_queue_tail(&sk->sk_write_queue, skb);
+	} else if (skb_is_gso(skb)) {
+		goto append;
 	}
 
+	skb->ip_summed = CHECKSUM_PARTIAL;
+	/* Specify the length of each IPv6 datagram fragment.
+	 * It has to be a multiple of 8.
+	 */
+	skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
+				     sizeof(struct frag_hdr)) & ~7;
+	skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
+	ipv6_select_ident(&fhdr, rt);
+	skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
+
+append:
 	return skb_append_datato_frags(sk, skb, getfrag, from,
 				       (length - transhdrlen));
 }
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index a791552..583b77e 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1430,9 +1430,17 @@
 static int
 ip6_tnl_change_mtu(struct net_device *dev, int new_mtu)
 {
-	if (new_mtu < IPV6_MIN_MTU) {
-		return -EINVAL;
+	struct ip6_tnl *tnl = netdev_priv(dev);
+
+	if (tnl->parms.proto == IPPROTO_IPIP) {
+		if (new_mtu < 68)
+			return -EINVAL;
+	} else {
+		if (new_mtu < IPV6_MIN_MTU)
+			return -EINVAL;
 	}
+	if (new_mtu > 0xFFF8 - dev->hard_header_len)
+		return -EINVAL;
 	dev->mtu = new_mtu;
 	return 0;
 }
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 5636a91..ce507d9 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -64,8 +64,7 @@
 		(struct ip_comp_hdr *)(skb->data + offset);
 	struct xfrm_state *x;
 
-	if (type != ICMPV6_DEST_UNREACH &&
-	    type != ICMPV6_PKT_TOOBIG &&
+	if (type != ICMPV6_PKT_TOOBIG &&
 	    type != NDISC_REDIRECT)
 		return;
 
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 44400c2..710238f 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -349,6 +349,11 @@
 	local_bh_disable();
 	addend = xt_write_recseq_begin();
 	private = table->private;
+	/*
+	 * Ensure we load private-> members after we've fetched the base
+	 * pointer.
+	 */
+	smp_read_barrier_depends();
 	cpu        = smp_processor_id();
 	table_base = private->entries[cpu];
 	jumpstack  = (struct ip6t_entry **)private->jumpstack[cpu];
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index c979dd9..04e17b3 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -476,6 +476,24 @@
 }
 
 #ifdef CONFIG_IPV6_ROUTER_PREF
+struct __rt6_probe_work {
+	struct work_struct work;
+	struct in6_addr target;
+	struct net_device *dev;
+};
+
+static void rt6_probe_deferred(struct work_struct *w)
+{
+	struct in6_addr mcaddr;
+	struct __rt6_probe_work *work =
+		container_of(w, struct __rt6_probe_work, work);
+
+	addrconf_addr_solict_mult(&work->target, &mcaddr);
+	ndisc_send_ns(work->dev, NULL, &work->target, &mcaddr, NULL);
+	dev_put(work->dev);
+	kfree(w);
+}
+
 static void rt6_probe(struct rt6_info *rt)
 {
 	struct neighbour *neigh;
@@ -499,17 +517,23 @@
 
 	if (!neigh ||
 	    time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) {
-		struct in6_addr mcaddr;
-		struct in6_addr *target;
+		struct __rt6_probe_work *work;
 
-		if (neigh) {
+		work = kmalloc(sizeof(*work), GFP_ATOMIC);
+
+		if (neigh && work)
 			neigh->updated = jiffies;
-			write_unlock(&neigh->lock);
-		}
 
-		target = (struct in6_addr *)&rt->rt6i_gateway;
-		addrconf_addr_solict_mult(target, &mcaddr);
-		ndisc_send_ns(rt->dst.dev, NULL, target, &mcaddr, NULL);
+		if (neigh)
+			write_unlock(&neigh->lock);
+
+		if (work) {
+			INIT_WORK(&work->work, rt6_probe_deferred);
+			work->target = rt->rt6i_gateway;
+			dev_hold(rt->dst.dev);
+			work->dev = rt->dst.dev;
+			schedule_work(&work->work);
+		}
 	} else {
 out:
 		write_unlock(&neigh->lock);
@@ -851,7 +875,6 @@
 			if (ort->rt6i_dst.plen != 128 &&
 			    ipv6_addr_equal(&ort->rt6i_dst.addr, daddr))
 				rt->rt6i_flags |= RTF_ANYCAST;
-			rt->rt6i_gateway = *daddr;
 		}
 
 		rt->rt6i_flags |= RTF_CACHE;
@@ -1064,10 +1087,13 @@
 	if (rt->rt6i_genid != rt_genid_ipv6(dev_net(rt->dst.dev)))
 		return NULL;
 
-	if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie))
-		return dst;
+	if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie))
+		return NULL;
 
-	return NULL;
+	if (rt6_check_expired(rt))
+		return NULL;
+
+	return dst;
 }
 
 static struct dst_entry *ip6_negative_advice(struct dst_entry *dst)
@@ -1338,6 +1364,7 @@
 	rt->dst.flags |= DST_HOST;
 	rt->dst.output  = ip6_output;
 	atomic_set(&rt->dst.__refcnt, 1);
+	rt->rt6i_gateway  = fl6->daddr;
 	rt->rt6i_dst.addr = fl6->daddr;
 	rt->rt6i_dst.plen = 128;
 	rt->rt6i_idev     = idev;
@@ -1873,7 +1900,10 @@
 			in6_dev_hold(rt->rt6i_idev);
 		rt->dst.lastuse = jiffies;
 
-		rt->rt6i_gateway = ort->rt6i_gateway;
+		if (ort->rt6i_flags & RTF_GATEWAY)
+			rt->rt6i_gateway = ort->rt6i_gateway;
+		else
+			rt->rt6i_gateway = *dest;
 		rt->rt6i_flags = ort->rt6i_flags;
 		if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ==
 		    (RTF_DEFAULT | RTF_ADDRCONF))
@@ -2160,6 +2190,7 @@
 	else
 		rt->rt6i_flags |= RTF_LOCAL;
 
+	rt->rt6i_gateway  = *addr;
 	rt->rt6i_dst.addr = *addr;
 	rt->rt6i_dst.plen = 128;
 	rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL);
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 72b7eaa..1878609 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1225,9 +1225,6 @@
 	if (tclass < 0)
 		tclass = np->tclass;
 
-	if (dontfrag < 0)
-		dontfrag = np->dontfrag;
-
 	if (msg->msg_flags&MSG_CONFIRM)
 		goto do_confirm;
 back_from_confirm:
@@ -1246,6 +1243,8 @@
 	up->pending = AF_INET6;
 
 do_append_data:
+	if (dontfrag < 0)
+		dontfrag = np->dontfrag;
 	up->len += ulen;
 	getfrag  =  is_udplite ?  udplite_getfrag : ip_generic_getfrag;
 	err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen,
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 23ed03d..5f8e128 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -135,9 +135,14 @@
 	struct ipv6_opt_hdr *exthdr;
 	const unsigned char *nh = skb_network_header(skb);
 	u8 nexthdr = nh[IP6CB(skb)->nhoff];
+	int oif = 0;
+
+	if (skb_dst(skb))
+		oif = skb_dst(skb)->dev->ifindex;
 
 	memset(fl6, 0, sizeof(struct flowi6));
 	fl6->flowi6_mark = skb->mark;
+	fl6->flowi6_oif = reverse ? skb->skb_iif : oif;
 
 	fl6->daddr = reverse ? hdr->saddr : hdr->daddr;
 	fl6->saddr = reverse ? hdr->daddr : hdr->saddr;
@@ -284,7 +289,7 @@
 	.destroy =		xfrm6_dst_destroy,
 	.ifdown =		xfrm6_dst_ifdown,
 	.local_out =		__ip6_local_out,
-	.gc_thresh =		1024,
+	.gc_thresh =		32768,
 };
 
 static struct xfrm_policy_afinfo xfrm6_policy_afinfo = {
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 0578d4f..0f67690 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -2563,9 +2563,8 @@
 				  jiffies + msecs_to_jiffies(val));
 
 			/* Wait for IR-LMP to call us back */
-			__wait_event_interruptible(self->query_wait,
-			      (self->cachedaddr != 0 || self->errno == -ETIME),
-						   err);
+			err = __wait_event_interruptible(self->query_wait,
+			      (self->cachedaddr != 0 || self->errno == -ETIME));
 
 			/* If watchdog is still activated, kill it! */
 			del_timer(&(self->watchdog));
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 9d58537..911ef03 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1098,7 +1098,8 @@
 
 	x->id.proto = proto;
 	x->id.spi = sa->sadb_sa_spi;
-	x->props.replay_window = sa->sadb_sa_replay;
+	x->props.replay_window = min_t(unsigned int, sa->sadb_sa_replay,
+					(sizeof(x->replay.bitmap) * 8));
 	if (sa->sadb_sa_flags & SADB_SAFLAGS_NOECN)
 		x->props.flags |= XFRM_STATE_NOECN;
 	if (sa->sadb_sa_flags & SADB_SAFLAGS_DECAP_DSCP)
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index feae495..b076e83 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -115,6 +115,11 @@
 static void l2tp_session_set_header_len(struct l2tp_session *session, int version);
 static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel);
 
+static inline struct l2tp_tunnel *l2tp_tunnel(struct sock *sk)
+{
+	return sk->sk_user_data;
+}
+
 static inline struct l2tp_net *l2tp_pernet(struct net *net)
 {
 	BUG_ON(!net);
@@ -504,7 +509,7 @@
 		return 0;
 
 #if IS_ENABLED(CONFIG_IPV6)
-	if (sk->sk_family == PF_INET6) {
+	if (sk->sk_family == PF_INET6 && !l2tp_tunnel(sk)->v4mapped) {
 		if (!uh->check) {
 			LIMIT_NETDEBUG(KERN_INFO "L2TP: IPv6: checksum is 0\n");
 			return 1;
@@ -1128,7 +1133,7 @@
 	/* Queue the packet to IP for output */
 	skb->local_df = 1;
 #if IS_ENABLED(CONFIG_IPV6)
-	if (skb->sk->sk_family == PF_INET6)
+	if (skb->sk->sk_family == PF_INET6 && !tunnel->v4mapped)
 		error = inet6_csk_xmit(skb, NULL);
 	else
 #endif
@@ -1255,7 +1260,7 @@
 
 		/* Calculate UDP checksum if configured to do so */
 #if IS_ENABLED(CONFIG_IPV6)
-		if (sk->sk_family == PF_INET6)
+		if (sk->sk_family == PF_INET6 && !tunnel->v4mapped)
 			l2tp_xmit_ipv6_csum(sk, skb, udp_len);
 		else
 #endif
@@ -1304,10 +1309,9 @@
  */
 static void l2tp_tunnel_destruct(struct sock *sk)
 {
-	struct l2tp_tunnel *tunnel;
+	struct l2tp_tunnel *tunnel = l2tp_tunnel(sk);
 	struct l2tp_net *pn;
 
-	tunnel = sk->sk_user_data;
 	if (tunnel == NULL)
 		goto end;
 
@@ -1675,7 +1679,7 @@
 	}
 
 	/* Check if this socket has already been prepped */
-	tunnel = (struct l2tp_tunnel *)sk->sk_user_data;
+	tunnel = l2tp_tunnel(sk);
 	if (tunnel != NULL) {
 		/* This socket has already been prepped */
 		err = -EBUSY;
@@ -1704,6 +1708,24 @@
 	if (cfg != NULL)
 		tunnel->debug = cfg->debug;
 
+#if IS_ENABLED(CONFIG_IPV6)
+	if (sk->sk_family == PF_INET6) {
+		struct ipv6_pinfo *np = inet6_sk(sk);
+
+		if (ipv6_addr_v4mapped(&np->saddr) &&
+		    ipv6_addr_v4mapped(&np->daddr)) {
+			struct inet_sock *inet = inet_sk(sk);
+
+			tunnel->v4mapped = true;
+			inet->inet_saddr = np->saddr.s6_addr32[3];
+			inet->inet_rcv_saddr = np->rcv_saddr.s6_addr32[3];
+			inet->inet_daddr = np->daddr.s6_addr32[3];
+		} else {
+			tunnel->v4mapped = false;
+		}
+	}
+#endif
+
 	/* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
 	tunnel->encap = encap;
 	if (encap == L2TP_ENCAPTYPE_UDP) {
@@ -1712,7 +1734,7 @@
 		udp_sk(sk)->encap_rcv = l2tp_udp_encap_recv;
 		udp_sk(sk)->encap_destroy = l2tp_udp_encap_destroy;
 #if IS_ENABLED(CONFIG_IPV6)
-		if (sk->sk_family == PF_INET6)
+		if (sk->sk_family == PF_INET6 && !tunnel->v4mapped)
 			udpv6_encap_enable();
 		else
 #endif
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index 66a559b..6f251cb 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -194,6 +194,9 @@
 	struct sock		*sock;		/* Parent socket */
 	int			fd;		/* Parent fd, if tunnel socket
 						 * was created by userspace */
+#if IS_ENABLED(CONFIG_IPV6)
+	bool			v4mapped;
+#endif
 
 	struct work_struct	del_work;
 
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index 5ebee2d..8c46b27 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -353,7 +353,9 @@
 		goto error_put_sess_tun;
 	}
 
+	local_bh_disable();
 	l2tp_xmit_skb(session, skb, session->hdr_len);
+	local_bh_enable();
 
 	sock_put(ps->tunnel_sock);
 	sock_put(sk);
@@ -422,7 +424,9 @@
 	skb->data[0] = ppph[0];
 	skb->data[1] = ppph[1];
 
+	local_bh_disable();
 	l2tp_xmit_skb(session, skb, session->hdr_len);
+	local_bh_enable();
 
 	sock_put(sk_tun);
 	sock_put(sk);
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 2e7855a..629dee7 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3518,7 +3518,7 @@
 		return -EINVAL;
 	}
 	band = chanctx_conf->def.chan->band;
-	sta = sta_info_get(sdata, peer);
+	sta = sta_info_get_bss(sdata, peer);
 	if (sta) {
 		qos = test_sta_flag(sta, WLAN_STA_WME);
 	} else {
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index b618651..611abfc 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -893,6 +893,8 @@
  *	that the scan completed.
  * @SCAN_ABORTED: Set for our scan work function when the driver reported
  *	a scan complete for an aborted scan.
+ * @SCAN_HW_CANCELLED: Set for our scan work function when the scan is being
+ *	cancelled.
  */
 enum {
 	SCAN_SW_SCANNING,
@@ -900,6 +902,7 @@
 	SCAN_ONCHANNEL_SCANNING,
 	SCAN_COMPLETED,
 	SCAN_ABORTED,
+	SCAN_HW_CANCELLED,
 };
 
 /**
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index acd1f71..0c2a294 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -394,6 +394,8 @@
 
 		if (started)
 			ieee80211_start_next_roc(local);
+		else if (list_empty(&local->roc_list))
+			ieee80211_run_deferred_scan(local);
 	}
 
  out_unlock:
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 54395d7..674eac1 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3056,6 +3056,9 @@
 	case NL80211_IFTYPE_ADHOC:
 		if (!bssid)
 			return 0;
+		if (ether_addr_equal(sdata->vif.addr, hdr->addr2) ||
+		    ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2))
+			return 0;
 		if (ieee80211_is_beacon(hdr->frame_control)) {
 			return 1;
 		} else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) {
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 08afe74..d2d17a4 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -238,6 +238,9 @@
 	enum ieee80211_band band;
 	int i, ielen, n_chans;
 
+	if (test_bit(SCAN_HW_CANCELLED, &local->scanning))
+		return false;
+
 	do {
 		if (local->hw_scan_band == IEEE80211_NUM_BANDS)
 			return false;
@@ -940,7 +943,23 @@
 	if (!local->scan_req)
 		goto out;
 
+	/*
+	 * We have a scan running and the driver already reported completion,
+	 * but the worker hasn't run yet or is stuck on the mutex - mark it as
+	 * cancelled.
+	 */
+	if (test_bit(SCAN_HW_SCANNING, &local->scanning) &&
+	    test_bit(SCAN_COMPLETED, &local->scanning)) {
+		set_bit(SCAN_HW_CANCELLED, &local->scanning);
+		goto out;
+	}
+
 	if (test_bit(SCAN_HW_SCANNING, &local->scanning)) {
+		/*
+		 * Make sure that __ieee80211_scan_completed doesn't trigger a
+		 * scan on another band.
+		 */
+		set_bit(SCAN_HW_CANCELLED, &local->scanning);
 		if (local->ops->cancel_hw_scan)
 			drv_cancel_hw_scan(local,
 				rcu_dereference_protected(local->scan_sdata,
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 368837f..78dc2e9 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -180,6 +180,9 @@
 	struct ieee80211_local *local = sta->local;
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
 
+	if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
+		sta->last_rx = jiffies;
+
 	if (ieee80211_is_data_qos(mgmt->frame_control)) {
 		struct ieee80211_hdr *hdr = (void *) skb->data;
 		u8 *qc = ieee80211_get_qos_ctl(hdr);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 3456c04..70b5a05 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1120,7 +1120,8 @@
 		tx->sta = rcu_dereference(sdata->u.vlan.sta);
 		if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr)
 			return TX_DROP;
-	} else if (info->flags & IEEE80211_TX_CTL_INJECTED ||
+	} else if (info->flags & (IEEE80211_TX_CTL_INJECTED |
+				  IEEE80211_TX_INTFL_NL80211_FRAME_TX) ||
 		   tx->sdata->control_port_protocol == tx->skb->protocol) {
 		tx->sta = sta_info_get_bss(sdata, hdr->addr1);
 	}
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index e1b34a1..69e4ef5 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2103,7 +2103,7 @@
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_supported_band *sband;
-	int rate, skip, shift;
+	int rate, shift;
 	u8 i, exrates, *pos;
 	u32 basic_rates = sdata->vif.bss_conf.basic_rates;
 	u32 rate_flags;
@@ -2131,14 +2131,11 @@
 		pos = skb_put(skb, exrates + 2);
 		*pos++ = WLAN_EID_EXT_SUPP_RATES;
 		*pos++ = exrates;
-		skip = 0;
 		for (i = 8; i < sband->n_bitrates; i++) {
 			u8 basic = 0;
 			if ((rate_flags & sband->bitrates[i].flags)
 			    != rate_flags)
 				continue;
-			if (skip++ < 8)
-				continue;
 			if (need_basic && basic_rates & BIT(i))
 				basic = 0x80;
 			rate = DIV_ROUND_UP(sband->bitrates[i].bitrate,
@@ -2241,6 +2238,10 @@
 	}
 
 	rate = cfg80211_calculate_bitrate(&ri);
+	if (WARN_ONCE(!rate,
+		      "Invalid bitrate: flags=0x%x, idx=%d, vht_nss=%d\n",
+		      status->flag, status->rate_idx, status->vht_nss))
+		return 0;
 
 	/* rewind from end of MPDU */
 	if (status->flag & RX_FLAG_MACTIME_END)
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index f448471..f63c238 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1637,12 +1637,9 @@
 			continue;
 		}
 		while (ip_vs_send_sync_msg(tinfo->sock, sb->mesg) < 0) {
-			int ret = 0;
-
-			__wait_event_interruptible(*sk_sleep(sk),
+			int ret = __wait_event_interruptible(*sk_sleep(sk),
 						   sock_writeable(sk) ||
-						   kthread_should_stop(),
-						   ret);
+						   kthread_should_stop());
 			if (unlikely(kthread_should_stop()))
 				goto done;
 		}
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index bdebd03..70866d1 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -778,8 +778,8 @@
 				   flowi6_to_flowi(&fl1), false)) {
 			if (!afinfo->route(&init_net, (struct dst_entry **)&rt2,
 					   flowi6_to_flowi(&fl2), false)) {
-				if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway,
-					    sizeof(rt1->rt6i_gateway)) &&
+				if (ipv6_addr_equal(rt6_nexthop(rt1),
+						    rt6_nexthop(rt2)) &&
 				    rt1->dst.dev == rt2->dst.dev)
 					ret = 1;
 				dst_release(&rt2->dst);
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 8b03028..227aa11 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -845,8 +845,13 @@
 		return NULL;
 	}
 
-	table->private = newinfo;
 	newinfo->initial_entries = private->initial_entries;
+	/*
+	 * Ensure contents of newinfo are visible before assigning to
+	 * private.
+	 */
+	smp_wmb();
+	table->private = newinfo;
 
 	/*
 	 * Even though table entries have now been swapped, other CPU's
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index 1e2fae3..ed00fef 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -147,6 +147,7 @@
 {
 	const struct xt_NFQ_info_v3 *info = par->targinfo;
 	u32 queue = info->queuenum;
+	int ret;
 
 	if (info->queues_total > 1) {
 		if (info->flags & NFQ_FLAG_CPU_FANOUT) {
@@ -157,7 +158,11 @@
 			queue = nfqueue_hash(skb, par);
 	}
 
-	return NF_QUEUE_NR(queue);
+	ret = NF_QUEUE_NR(queue);
+	if (info->flags & NFQ_FLAG_BYPASS)
+		ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
+
+	return ret;
 }
 
 static struct xt_target nfqueue_tg_reg[] __read_mostly = {
diff --git a/net/openvswitch/dp_notify.c b/net/openvswitch/dp_notify.c
index c323567..5c2dab2 100644
--- a/net/openvswitch/dp_notify.c
+++ b/net/openvswitch/dp_notify.c
@@ -65,8 +65,7 @@
 					continue;
 
 				netdev_vport = netdev_vport_priv(vport);
-				if (netdev_vport->dev->reg_state == NETREG_UNREGISTERED ||
-				    netdev_vport->dev->reg_state == NETREG_UNREGISTERING)
+				if (!(netdev_vport->dev->priv_flags & IFF_OVS_DATAPATH))
 					dp_detach_port_notify(vport);
 			}
 		}
@@ -88,6 +87,10 @@
 		return NOTIFY_DONE;
 
 	if (event == NETDEV_UNREGISTER) {
+		/* upper_dev_unlink and decrement promisc immediately */
+		ovs_netdev_detach_dev(vport);
+
+		/* schedule vport destroy, dev_put and genl notification */
 		ovs_net = net_generic(dev_net(dev), ovs_net_id);
 		queue_work(system_wq, &ovs_net->dp_notify_work);
 	}
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c
index 09d93c1..d21f77d 100644
--- a/net/openvswitch/vport-netdev.c
+++ b/net/openvswitch/vport-netdev.c
@@ -150,15 +150,25 @@
 	ovs_vport_free(vport_from_priv(netdev_vport));
 }
 
+void ovs_netdev_detach_dev(struct vport *vport)
+{
+	struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
+
+	ASSERT_RTNL();
+	netdev_vport->dev->priv_flags &= ~IFF_OVS_DATAPATH;
+	netdev_rx_handler_unregister(netdev_vport->dev);
+	netdev_upper_dev_unlink(netdev_vport->dev,
+				netdev_master_upper_dev_get(netdev_vport->dev));
+	dev_set_promiscuity(netdev_vport->dev, -1);
+}
+
 static void netdev_destroy(struct vport *vport)
 {
 	struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
 
 	rtnl_lock();
-	netdev_vport->dev->priv_flags &= ~IFF_OVS_DATAPATH;
-	netdev_rx_handler_unregister(netdev_vport->dev);
-	netdev_upper_dev_unlink(netdev_vport->dev, get_dpdev(vport->dp));
-	dev_set_promiscuity(netdev_vport->dev, -1);
+	if (netdev_vport->dev->priv_flags & IFF_OVS_DATAPATH)
+		ovs_netdev_detach_dev(vport);
 	rtnl_unlock();
 
 	call_rcu(&netdev_vport->rcu, free_port_rcu);
diff --git a/net/openvswitch/vport-netdev.h b/net/openvswitch/vport-netdev.h
index dd298b5..8df01c11 100644
--- a/net/openvswitch/vport-netdev.h
+++ b/net/openvswitch/vport-netdev.h
@@ -39,5 +39,6 @@
 }
 
 const char *ovs_netdev_get_name(const struct vport *);
+void ovs_netdev_detach_dev(struct vport *);
 
 #endif /* vport_netdev.h */
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
index a2fef8b..fdc041c 100644
--- a/net/sched/sch_fq.c
+++ b/net/sched/sch_fq.c
@@ -255,6 +255,7 @@
 				     f->socket_hash != sk->sk_hash)) {
 				f->credit = q->initial_quantum;
 				f->socket_hash = sk->sk_hash;
+				f->time_next_packet = 0ULL;
 			}
 			return f;
 		}
@@ -472,20 +473,16 @@
 	if (f->credit > 0 || !q->rate_enable)
 		goto out;
 
-	if (skb->sk && skb->sk->sk_state != TCP_TIME_WAIT) {
-		rate = skb->sk->sk_pacing_rate ?: q->flow_default_rate;
+	rate = q->flow_max_rate;
+	if (skb->sk && skb->sk->sk_state != TCP_TIME_WAIT)
+		rate = min(skb->sk->sk_pacing_rate, rate);
 
-		rate = min(rate, q->flow_max_rate);
-	} else {
-		rate = q->flow_max_rate;
-		if (rate == ~0U)
-			goto out;
-	}
-	if (rate) {
+	if (rate != ~0U) {
 		u32 plen = max(qdisc_pkt_len(skb), q->quantum);
 		u64 len = (u64)plen * NSEC_PER_SEC;
 
-		do_div(len, rate);
+		if (likely(rate))
+			do_div(len, rate);
 		/* Since socket rate can change later,
 		 * clamp the delay to 125 ms.
 		 * TODO: maybe segment the too big skb, as in commit
@@ -656,7 +653,7 @@
 		q->quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]);
 
 	if (tb[TCA_FQ_INITIAL_QUANTUM])
-		q->quantum = nla_get_u32(tb[TCA_FQ_INITIAL_QUANTUM]);
+		q->initial_quantum = nla_get_u32(tb[TCA_FQ_INITIAL_QUANTUM]);
 
 	if (tb[TCA_FQ_FLOW_DEFAULT_RATE])
 		q->flow_default_rate = nla_get_u32(tb[TCA_FQ_FLOW_DEFAULT_RATE]);
@@ -735,12 +732,14 @@
 	if (opts == NULL)
 		goto nla_put_failure;
 
+	/* TCA_FQ_FLOW_DEFAULT_RATE is not used anymore,
+	 * do not bother giving its value
+	 */
 	if (nla_put_u32(skb, TCA_FQ_PLIMIT, sch->limit) ||
 	    nla_put_u32(skb, TCA_FQ_FLOW_PLIMIT, q->flow_plimit) ||
 	    nla_put_u32(skb, TCA_FQ_QUANTUM, q->quantum) ||
 	    nla_put_u32(skb, TCA_FQ_INITIAL_QUANTUM, q->initial_quantum) ||
 	    nla_put_u32(skb, TCA_FQ_RATE_ENABLE, q->rate_enable) ||
-	    nla_put_u32(skb, TCA_FQ_FLOW_DEFAULT_RATE, q->flow_default_rate) ||
 	    nla_put_u32(skb, TCA_FQ_FLOW_MAX_RATE, q->flow_max_rate) ||
 	    nla_put_u32(skb, TCA_FQ_BUCKETS_LOG, q->fq_trees_log))
 		goto nla_put_failure;
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index a6d788d..b87e83d 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -358,6 +358,21 @@
 	return PSCHED_NS2TICKS(ticks);
 }
 
+static void tfifo_reset(struct Qdisc *sch)
+{
+	struct netem_sched_data *q = qdisc_priv(sch);
+	struct rb_node *p;
+
+	while ((p = rb_first(&q->t_root))) {
+		struct sk_buff *skb = netem_rb_to_skb(p);
+
+		rb_erase(p, &q->t_root);
+		skb->next = NULL;
+		skb->prev = NULL;
+		kfree_skb(skb);
+	}
+}
+
 static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
@@ -520,6 +535,7 @@
 			skb->next = NULL;
 			skb->prev = NULL;
 			len = qdisc_pkt_len(skb);
+			sch->qstats.backlog -= len;
 			kfree_skb(skb);
 		}
 	}
@@ -609,6 +625,7 @@
 	struct netem_sched_data *q = qdisc_priv(sch);
 
 	qdisc_reset_queue(sch);
+	tfifo_reset(sch);
 	if (q->qdisc)
 		qdisc_reset(q->qdisc);
 	qdisc_watchdog_cancel(&q->watchdog);
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index e7b2d4f..96a5591 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -279,7 +279,9 @@
 		sctp_v6_to_addr(&dst_saddr, &fl6->saddr, htons(bp->port));
 		rcu_read_lock();
 		list_for_each_entry_rcu(laddr, &bp->address_list, list) {
-			if (!laddr->valid || (laddr->state != SCTP_ADDR_SRC))
+			if (!laddr->valid || laddr->state == SCTP_ADDR_DEL ||
+			    (laddr->state != SCTP_ADDR_SRC &&
+			     !asoc->src_out_of_asoc_ok))
 				continue;
 
 			/* Do not compare against v4 addrs */
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 0ac3a65..3191373 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -536,7 +536,8 @@
 	 * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
 	 */
 	if (!sctp_checksum_disable) {
-		if (!(dst->dev->features & NETIF_F_SCTP_CSUM)) {
+		if (!(dst->dev->features & NETIF_F_SCTP_CSUM) ||
+		    (dst_xfrm(dst) != NULL) || packet->ipfragok) {
 			__u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len);
 
 			/* 3) Put the resultant value into the checksum field in the
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 666c668..1a6eef3 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -860,7 +860,6 @@
 	    (!asoc->temp) && (sk->sk_shutdown != SHUTDOWN_MASK))
 		return;
 
-	BUG_ON(asoc->peer.primary_path == NULL);
 	sctp_unhash_established(asoc);
 	sctp_association_free(asoc);
 }
diff --git a/net/socket.c b/net/socket.c
index ebed4b6..c226ace 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1964,6 +1964,16 @@
 	unsigned int name_len;
 };
 
+static int copy_msghdr_from_user(struct msghdr *kmsg,
+				 struct msghdr __user *umsg)
+{
+	if (copy_from_user(kmsg, umsg, sizeof(struct msghdr)))
+		return -EFAULT;
+	if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
+		return -EINVAL;
+	return 0;
+}
+
 static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
 			 struct msghdr *msg_sys, unsigned int flags,
 			 struct used_address *used_address)
@@ -1982,8 +1992,11 @@
 	if (MSG_CMSG_COMPAT & flags) {
 		if (get_compat_msghdr(msg_sys, msg_compat))
 			return -EFAULT;
-	} else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
-		return -EFAULT;
+	} else {
+		err = copy_msghdr_from_user(msg_sys, msg);
+		if (err)
+			return err;
+	}
 
 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
 		err = -EMSGSIZE;
@@ -2191,8 +2204,11 @@
 	if (MSG_CMSG_COMPAT & flags) {
 		if (get_compat_msghdr(msg_sys, msg_compat))
 			return -EFAULT;
-	} else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
-		return -EFAULT;
+	} else {
+		err = copy_msghdr_from_user(msg_sys, msg);
+		if (err)
+			return err;
+	}
 
 	if (msg_sys->msg_iovlen > UIO_FASTIOV) {
 		err = -EMSGSIZE;
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 0846566..97912b4 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -420,41 +420,53 @@
 	memcpy(gss_msg->databuf, &uid, sizeof(uid));
 	gss_msg->msg.data = gss_msg->databuf;
 	gss_msg->msg.len = sizeof(uid);
-	BUG_ON(sizeof(uid) > UPCALL_BUF_LEN);
+
+	BUILD_BUG_ON(sizeof(uid) > sizeof(gss_msg->databuf));
 }
 
-static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,
+static int gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,
 				const char *service_name,
 				const char *target_name)
 {
 	struct gss_api_mech *mech = gss_msg->auth->mech;
 	char *p = gss_msg->databuf;
-	int len = 0;
+	size_t buflen = sizeof(gss_msg->databuf);
+	int len;
 
-	gss_msg->msg.len = sprintf(gss_msg->databuf, "mech=%s uid=%d ",
-				   mech->gm_name,
-				   from_kuid(&init_user_ns, gss_msg->uid));
-	p += gss_msg->msg.len;
+	len = scnprintf(p, buflen, "mech=%s uid=%d ", mech->gm_name,
+			from_kuid(&init_user_ns, gss_msg->uid));
+	buflen -= len;
+	p += len;
+	gss_msg->msg.len = len;
 	if (target_name) {
-		len = sprintf(p, "target=%s ", target_name);
+		len = scnprintf(p, buflen, "target=%s ", target_name);
+		buflen -= len;
 		p += len;
 		gss_msg->msg.len += len;
 	}
 	if (service_name != NULL) {
-		len = sprintf(p, "service=%s ", service_name);
+		len = scnprintf(p, buflen, "service=%s ", service_name);
+		buflen -= len;
 		p += len;
 		gss_msg->msg.len += len;
 	}
 	if (mech->gm_upcall_enctypes) {
-		len = sprintf(p, "enctypes=%s ", mech->gm_upcall_enctypes);
+		len = scnprintf(p, buflen, "enctypes=%s ",
+				mech->gm_upcall_enctypes);
+		buflen -= len;
 		p += len;
 		gss_msg->msg.len += len;
 	}
-	len = sprintf(p, "\n");
+	len = scnprintf(p, buflen, "\n");
+	if (len == 0)
+		goto out_overflow;
 	gss_msg->msg.len += len;
 
 	gss_msg->msg.data = gss_msg->databuf;
-	BUG_ON(gss_msg->msg.len > UPCALL_BUF_LEN);
+	return 0;
+out_overflow:
+	WARN_ON_ONCE(1);
+	return -ENOMEM;
 }
 
 static struct gss_upcall_msg *
@@ -463,15 +475,15 @@
 {
 	struct gss_upcall_msg *gss_msg;
 	int vers;
+	int err = -ENOMEM;
 
 	gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS);
 	if (gss_msg == NULL)
-		return ERR_PTR(-ENOMEM);
+		goto err;
 	vers = get_pipe_version(gss_auth->net);
-	if (vers < 0) {
-		kfree(gss_msg);
-		return ERR_PTR(vers);
-	}
+	err = vers;
+	if (err < 0)
+		goto err_free_msg;
 	gss_msg->pipe = gss_auth->gss_pipe[vers]->pipe;
 	INIT_LIST_HEAD(&gss_msg->list);
 	rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
@@ -482,10 +494,17 @@
 	switch (vers) {
 	case 0:
 		gss_encode_v0_msg(gss_msg);
+		break;
 	default:
-		gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name);
+		err = gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name);
+		if (err)
+			goto err_free_msg;
 	};
 	return gss_msg;
+err_free_msg:
+	kfree(gss_msg);
+err:
+	return ERR_PTR(err);
 }
 
 static struct gss_upcall_msg *
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 7747960..dab09da 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -25,12 +25,12 @@
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/slab.h>
+#include <linux/rcupdate.h>
 #include <linux/utsname.h>
 #include <linux/workqueue.h>
 #include <linux/in.h>
 #include <linux/in6.h>
 #include <linux/un.h>
-#include <linux/rcupdate.h>
 
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/addr.h>
@@ -264,6 +264,26 @@
 	return rpc_pipefs_notifier_unregister(&rpc_clients_block);
 }
 
+static struct rpc_xprt *rpc_clnt_set_transport(struct rpc_clnt *clnt,
+		struct rpc_xprt *xprt,
+		const struct rpc_timeout *timeout)
+{
+	struct rpc_xprt *old;
+
+	spin_lock(&clnt->cl_lock);
+	old = rcu_dereference_protected(clnt->cl_xprt,
+			lockdep_is_held(&clnt->cl_lock));
+
+	if (!xprt_bound(xprt))
+		clnt->cl_autobind = 1;
+
+	clnt->cl_timeout = timeout;
+	rcu_assign_pointer(clnt->cl_xprt, xprt);
+	spin_unlock(&clnt->cl_lock);
+
+	return old;
+}
+
 static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename)
 {
 	clnt->cl_nodelen = strlen(nodename);
@@ -272,12 +292,13 @@
 	memcpy(clnt->cl_nodename, nodename, clnt->cl_nodelen);
 }
 
-static int rpc_client_register(const struct rpc_create_args *args,
-			       struct rpc_clnt *clnt)
+static int rpc_client_register(struct rpc_clnt *clnt,
+			       rpc_authflavor_t pseudoflavor,
+			       const char *client_name)
 {
 	struct rpc_auth_create_args auth_args = {
-		.pseudoflavor = args->authflavor,
-		.target_name = args->client_name,
+		.pseudoflavor = pseudoflavor,
+		.target_name = client_name,
 	};
 	struct rpc_auth *auth;
 	struct net *net = rpc_net_ns(clnt);
@@ -298,7 +319,7 @@
 	auth = rpcauth_create(&auth_args, clnt);
 	if (IS_ERR(auth)) {
 		dprintk("RPC:       Couldn't create auth handle (flavor %u)\n",
-				args->authflavor);
+				pseudoflavor);
 		err = PTR_ERR(auth);
 		goto err_auth;
 	}
@@ -337,7 +358,8 @@
 {
 	const struct rpc_program *program = args->program;
 	const struct rpc_version *version;
-	struct rpc_clnt		*clnt = NULL;
+	struct rpc_clnt *clnt = NULL;
+	const struct rpc_timeout *timeout;
 	int err;
 
 	/* sanity check the name before trying to print it */
@@ -365,7 +387,6 @@
 	if (err)
 		goto out_no_clid;
 
-	rcu_assign_pointer(clnt->cl_xprt, xprt);
 	clnt->cl_procinfo = version->procs;
 	clnt->cl_maxproc  = version->nrprocs;
 	clnt->cl_prog     = args->prognumber ? : program->number;
@@ -380,16 +401,15 @@
 	INIT_LIST_HEAD(&clnt->cl_tasks);
 	spin_lock_init(&clnt->cl_lock);
 
-	if (!xprt_bound(xprt))
-		clnt->cl_autobind = 1;
-
-	clnt->cl_timeout = xprt->timeout;
+	timeout = xprt->timeout;
 	if (args->timeout != NULL) {
 		memcpy(&clnt->cl_timeout_default, args->timeout,
 				sizeof(clnt->cl_timeout_default));
-		clnt->cl_timeout = &clnt->cl_timeout_default;
+		timeout = &clnt->cl_timeout_default;
 	}
 
+	rpc_clnt_set_transport(clnt, xprt, timeout);
+
 	clnt->cl_rtt = &clnt->cl_rtt_default;
 	rpc_init_rtt(&clnt->cl_rtt_default, clnt->cl_timeout->to_initval);
 
@@ -398,7 +418,7 @@
 	/* save the nodename */
 	rpc_clnt_set_nodename(clnt, utsname()->nodename);
 
-	err = rpc_client_register(args, clnt);
+	err = rpc_client_register(clnt, args->authflavor, args->client_name);
 	if (err)
 		goto out_no_path;
 	if (parent)
@@ -600,6 +620,80 @@
 }
 EXPORT_SYMBOL_GPL(rpc_clone_client_set_auth);
 
+/**
+ * rpc_switch_client_transport: switch the RPC transport on the fly
+ * @clnt: pointer to a struct rpc_clnt
+ * @args: pointer to the new transport arguments
+ * @timeout: pointer to the new timeout parameters
+ *
+ * This function allows the caller to switch the RPC transport for the
+ * rpc_clnt structure 'clnt' to allow it to connect to a mirrored NFS
+ * server, for instance.  It assumes that the caller has ensured that
+ * there are no active RPC tasks by using some form of locking.
+ *
+ * Returns zero if "clnt" is now using the new xprt.  Otherwise a
+ * negative errno is returned, and "clnt" continues to use the old
+ * xprt.
+ */
+int rpc_switch_client_transport(struct rpc_clnt *clnt,
+		struct xprt_create *args,
+		const struct rpc_timeout *timeout)
+{
+	const struct rpc_timeout *old_timeo;
+	rpc_authflavor_t pseudoflavor;
+	struct rpc_xprt *xprt, *old;
+	struct rpc_clnt *parent;
+	int err;
+
+	xprt = xprt_create_transport(args);
+	if (IS_ERR(xprt)) {
+		dprintk("RPC:       failed to create new xprt for clnt %p\n",
+			clnt);
+		return PTR_ERR(xprt);
+	}
+
+	pseudoflavor = clnt->cl_auth->au_flavor;
+
+	old_timeo = clnt->cl_timeout;
+	old = rpc_clnt_set_transport(clnt, xprt, timeout);
+
+	rpc_unregister_client(clnt);
+	__rpc_clnt_remove_pipedir(clnt);
+
+	/*
+	 * A new transport was created.  "clnt" therefore
+	 * becomes the root of a new cl_parent tree.  clnt's
+	 * children, if it has any, still point to the old xprt.
+	 */
+	parent = clnt->cl_parent;
+	clnt->cl_parent = clnt;
+
+	/*
+	 * The old rpc_auth cache cannot be re-used.  GSS
+	 * contexts in particular are between a single
+	 * client and server.
+	 */
+	err = rpc_client_register(clnt, pseudoflavor, NULL);
+	if (err)
+		goto out_revert;
+
+	synchronize_rcu();
+	if (parent != clnt)
+		rpc_release_client(parent);
+	xprt_put(old);
+	dprintk("RPC:       replaced xprt for clnt %p\n", clnt);
+	return 0;
+
+out_revert:
+	rpc_clnt_set_transport(clnt, old, old_timeo);
+	clnt->cl_parent = parent;
+	rpc_client_register(clnt, pseudoflavor, NULL);
+	xprt_put(xprt);
+	dprintk("RPC:       failed to switch xprt for clnt %p\n", clnt);
+	return err;
+}
+EXPORT_SYMBOL_GPL(rpc_switch_client_transport);
+
 /*
  * Kill all tasks for the given client.
  * XXX: kill their descendants as well?
@@ -772,6 +866,8 @@
 		atomic_inc(&clnt->cl_count);
 		if (clnt->cl_softrtry)
 			task->tk_flags |= RPC_TASK_SOFT;
+		if (clnt->cl_noretranstimeo)
+			task->tk_flags |= RPC_TASK_NO_RETRANS_TIMEOUT;
 		if (sk_memalloc_socks()) {
 			struct rpc_xprt *xprt;
 
@@ -1690,6 +1786,7 @@
 	dprint_status(task);
 
 	trace_rpc_connect_status(task, status);
+	task->tk_status = 0;
 	switch (status) {
 		/* if soft mounted, test if we've timed out */
 	case -ETIMEDOUT:
@@ -1698,12 +1795,14 @@
 	case -ECONNREFUSED:
 	case -ECONNRESET:
 	case -ENETUNREACH:
+		/* retry with existing socket, after a delay */
+		rpc_delay(task, 3*HZ);
 		if (RPC_IS_SOFTCONN(task))
 			break;
-		/* retry with existing socket, after a delay */
-	case 0:
 	case -EAGAIN:
-		task->tk_status = 0;
+		task->tk_action = call_bind;
+		return;
+	case 0:
 		clnt->cl_stats->netreconn++;
 		task->tk_action = call_transmit;
 		return;
@@ -1717,13 +1816,14 @@
 static void
 call_transmit(struct rpc_task *task)
 {
+	int is_retrans = RPC_WAS_SENT(task);
+
 	dprint_status(task);
 
 	task->tk_action = call_status;
 	if (task->tk_status < 0)
 		return;
-	task->tk_status = xprt_prepare_transmit(task);
-	if (task->tk_status != 0)
+	if (!xprt_prepare_transmit(task))
 		return;
 	task->tk_action = call_transmit_status;
 	/* Encode here so that rpcsec_gss can use correct sequence number. */
@@ -1742,6 +1842,8 @@
 	xprt_transmit(task);
 	if (task->tk_status < 0)
 		return;
+	if (is_retrans)
+		task->tk_client->cl_stats->rpcretrans++;
 	/*
 	 * On success, ensure that we call xprt_end_transmit() before sleeping
 	 * in order to allow access to the socket to other RPC requests.
@@ -1811,8 +1913,7 @@
 {
 	struct rpc_rqst *req = task->tk_rqstp;
 
-	task->tk_status = xprt_prepare_transmit(task);
-	if (task->tk_status == -EAGAIN) {
+	if (!xprt_prepare_transmit(task)) {
 		/*
 		 * Could not reserve the transport. Try again after the
 		 * transport is released.
@@ -1900,7 +2001,8 @@
 		rpc_delay(task, 3*HZ);
 	case -ETIMEDOUT:
 		task->tk_action = call_timeout;
-		if (task->tk_client->cl_discrtry)
+		if (!(task->tk_flags & RPC_TASK_NO_RETRANS_TIMEOUT)
+		    && task->tk_client->cl_discrtry)
 			xprt_conditional_disconnect(req->rq_xprt,
 					req->rq_connect_cookie);
 		break;
@@ -1982,7 +2084,6 @@
 	rpcauth_invalcred(task);
 
 retry:
-	clnt->cl_stats->rpcretrans++;
 	task->tk_action = call_bind;
 	task->tk_status = 0;
 }
@@ -2025,7 +2126,6 @@
 	if (req->rq_rcv_buf.len < 12) {
 		if (!RPC_IS_SOFT(task)) {
 			task->tk_action = call_bind;
-			clnt->cl_stats->rpcretrans++;
 			goto out_retry;
 		}
 		dprintk("RPC:       %s: too small RPC reply size (%d bytes)\n",
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 095363e..04199bc 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -205,10 +205,8 @@
 		goto out_sleep;
 	}
 	xprt->snd_task = task;
-	if (req != NULL) {
-		req->rq_bytes_sent = 0;
+	if (req != NULL)
 		req->rq_ntrans++;
-	}
 
 	return 1;
 
@@ -263,7 +261,6 @@
 	}
 	if (__xprt_get_cong(xprt, task)) {
 		xprt->snd_task = task;
-		req->rq_bytes_sent = 0;
 		req->rq_ntrans++;
 		return 1;
 	}
@@ -300,10 +297,8 @@
 
 	req = task->tk_rqstp;
 	xprt->snd_task = task;
-	if (req) {
-		req->rq_bytes_sent = 0;
+	if (req)
 		req->rq_ntrans++;
-	}
 	return true;
 }
 
@@ -329,7 +324,6 @@
 	}
 	if (__xprt_get_cong(xprt, task)) {
 		xprt->snd_task = task;
-		req->rq_bytes_sent = 0;
 		req->rq_ntrans++;
 		return true;
 	}
@@ -358,6 +352,11 @@
 void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
 {
 	if (xprt->snd_task == task) {
+		if (task != NULL) {
+			struct rpc_rqst *req = task->tk_rqstp;
+			if (req != NULL)
+				req->rq_bytes_sent = 0;
+		}
 		xprt_clear_locked(xprt);
 		__xprt_lock_write_next(xprt);
 	}
@@ -375,6 +374,11 @@
 void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task)
 {
 	if (xprt->snd_task == task) {
+		if (task != NULL) {
+			struct rpc_rqst *req = task->tk_rqstp;
+			if (req != NULL)
+				req->rq_bytes_sent = 0;
+		}
 		xprt_clear_locked(xprt);
 		__xprt_lock_write_next_cong(xprt);
 	}
@@ -854,24 +858,36 @@
  * @task: RPC task about to send a request
  *
  */
-int xprt_prepare_transmit(struct rpc_task *task)
+bool xprt_prepare_transmit(struct rpc_task *task)
 {
 	struct rpc_rqst	*req = task->tk_rqstp;
 	struct rpc_xprt	*xprt = req->rq_xprt;
-	int err = 0;
+	bool ret = false;
 
 	dprintk("RPC: %5u xprt_prepare_transmit\n", task->tk_pid);
 
 	spin_lock_bh(&xprt->transport_lock);
-	if (req->rq_reply_bytes_recvd && !req->rq_bytes_sent) {
-		err = req->rq_reply_bytes_recvd;
+	if (!req->rq_bytes_sent) {
+		if (req->rq_reply_bytes_recvd) {
+			task->tk_status = req->rq_reply_bytes_recvd;
+			goto out_unlock;
+		}
+		if ((task->tk_flags & RPC_TASK_NO_RETRANS_TIMEOUT)
+		    && xprt_connected(xprt)
+		    && req->rq_connect_cookie == xprt->connect_cookie) {
+			xprt->ops->set_retrans_timeout(task);
+			rpc_sleep_on(&xprt->pending, task, xprt_timer);
+			goto out_unlock;
+		}
+	}
+	if (!xprt->ops->reserve_xprt(xprt, task)) {
+		task->tk_status = -EAGAIN;
 		goto out_unlock;
 	}
-	if (!xprt->ops->reserve_xprt(xprt, task))
-		err = -EAGAIN;
+	ret = true;
 out_unlock:
 	spin_unlock_bh(&xprt->transport_lock);
-	return err;
+	return ret;
 }
 
 void xprt_end_transmit(struct rpc_task *task)
@@ -912,7 +928,6 @@
 	} else if (!req->rq_bytes_sent)
 		return;
 
-	req->rq_connect_cookie = xprt->connect_cookie;
 	req->rq_xtime = ktime_get();
 	status = xprt->ops->send_request(task);
 	if (status != 0) {
@@ -938,12 +953,14 @@
 	/* Don't race with disconnect */
 	if (!xprt_connected(xprt))
 		task->tk_status = -ENOTCONN;
-	else if (!req->rq_reply_bytes_recvd && rpc_reply_expected(task)) {
+	else {
 		/*
 		 * Sleep on the pending queue since
 		 * we're expecting a reply.
 		 */
-		rpc_sleep_on(&xprt->pending, task, xprt_timer);
+		if (!req->rq_reply_bytes_recvd && rpc_reply_expected(task))
+			rpc_sleep_on(&xprt->pending, task, xprt_timer);
+		req->rq_connect_cookie = xprt->connect_cookie;
 	}
 	spin_unlock_bh(&xprt->transport_lock);
 }
@@ -1087,11 +1104,9 @@
 	for (i = 0; i < num_prealloc; i++) {
 		req = kzalloc(sizeof(struct rpc_rqst), GFP_KERNEL);
 		if (!req)
-			break;
+			goto out_free;
 		list_add(&req->rq_list, &xprt->free);
 	}
-	if (i < num_prealloc)
-		goto out_free;
 	if (max_alloc > num_prealloc)
 		xprt->max_reqs = max_alloc;
 	else
@@ -1186,6 +1201,12 @@
 	req->rq_xprt    = xprt;
 	req->rq_buffer  = NULL;
 	req->rq_xid     = xprt_alloc_xid(xprt);
+	req->rq_connect_cookie = xprt->connect_cookie - 1;
+	req->rq_bytes_sent = 0;
+	req->rq_snd_buf.len = 0;
+	req->rq_snd_buf.buflen = 0;
+	req->rq_rcv_buf.len = 0;
+	req->rq_rcv_buf.buflen = 0;
 	req->rq_release_snd_buf = NULL;
 	xprt_reset_majortimeo(req);
 	dprintk("RPC: %5u reserved req %p xid %08x\n", task->tk_pid,
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index ee03d35..17c8892 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -835,6 +835,8 @@
 
 	dprintk("RPC:       xs_close xprt %p\n", xprt);
 
+	cancel_delayed_work_sync(&transport->connect_worker);
+
 	xs_reset_transport(transport);
 	xprt->reestablish_timeout = 0;
 
@@ -854,14 +856,6 @@
 		xs_tcp_shutdown(xprt);
 }
 
-static void xs_local_destroy(struct rpc_xprt *xprt)
-{
-	xs_close(xprt);
-	xs_free_peer_addresses(xprt);
-	xprt_free(xprt);
-	module_put(THIS_MODULE);
-}
-
 /**
  * xs_destroy - prepare to shutdown a transport
  * @xprt: doomed transport
@@ -869,13 +863,12 @@
  */
 static void xs_destroy(struct rpc_xprt *xprt)
 {
-	struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
-
 	dprintk("RPC:       xs_destroy xprt %p\n", xprt);
 
-	cancel_delayed_work_sync(&transport->connect_worker);
-
-	xs_local_destroy(xprt);
+	xs_close(xprt);
+	xs_free_peer_addresses(xprt);
+	xprt_free(xprt);
+	module_put(THIS_MODULE);
 }
 
 static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
@@ -1511,6 +1504,7 @@
 			transport->tcp_copied = 0;
 			transport->tcp_flags =
 				TCP_RCV_COPY_FRAGHDR | TCP_RCV_COPY_XID;
+			xprt->connect_cookie++;
 
 			xprt_wake_pending_tasks(xprt, -EAGAIN);
 		}
@@ -1816,6 +1810,10 @@
 }
 #endif
 
+static void xs_dummy_setup_socket(struct work_struct *work)
+{
+}
+
 static struct socket *xs_create_sock(struct rpc_xprt *xprt,
 		struct sock_xprt *transport, int family, int type, int protocol)
 {
@@ -2112,6 +2110,19 @@
 
 	if (!transport->inet) {
 		struct sock *sk = sock->sk;
+		unsigned int keepidle = xprt->timeout->to_initval / HZ;
+		unsigned int keepcnt = xprt->timeout->to_retries + 1;
+		unsigned int opt_on = 1;
+
+		/* TCP Keepalive options */
+		kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
+				(char *)&opt_on, sizeof(opt_on));
+		kernel_setsockopt(sock, SOL_TCP, TCP_KEEPIDLE,
+				(char *)&keepidle, sizeof(keepidle));
+		kernel_setsockopt(sock, SOL_TCP, TCP_KEEPINTVL,
+				(char *)&keepidle, sizeof(keepidle));
+		kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT,
+				(char *)&keepcnt, sizeof(keepcnt));
 
 		write_lock_bh(&sk->sk_callback_lock);
 
@@ -2151,7 +2162,6 @@
 	case 0:
 	case -EINPROGRESS:
 		/* SYN_SENT! */
-		xprt->connect_cookie++;
 		if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
 			xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
 	}
@@ -2498,7 +2508,7 @@
 	.send_request		= xs_local_send_request,
 	.set_retrans_timeout	= xprt_set_retrans_timeout_def,
 	.close			= xs_close,
-	.destroy		= xs_local_destroy,
+	.destroy		= xs_destroy,
 	.print_stats		= xs_local_print_stats,
 };
 
@@ -2655,6 +2665,9 @@
 	xprt->ops = &xs_local_ops;
 	xprt->timeout = &xs_local_default_timeout;
 
+	INIT_DELAYED_WORK(&transport->connect_worker,
+			xs_dummy_setup_socket);
+
 	switch (sun->sun_family) {
 	case AF_LOCAL:
 		if (sun->sun_path[0] != '/') {
@@ -2859,8 +2872,8 @@
 	if (args->bc_xprt->xpt_bc_xprt) {
 		/*
 		 * This server connection already has a backchannel
-		 * export; we can't create a new one, as we wouldn't be
-		 * able to match replies based on xid any more.  So,
+		 * transport; we can't create a new one, as we wouldn't
+		 * be able to match replies based on xid any more.  So,
 		 * reuse the already-existing one:
 		 */
 		 return args->bc_xprt->xpt_bc_xprt;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 86de99a..c1f403b 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1246,6 +1246,15 @@
 	return 0;
 }
 
+static void unix_sock_inherit_flags(const struct socket *old,
+				    struct socket *new)
+{
+	if (test_bit(SOCK_PASSCRED, &old->flags))
+		set_bit(SOCK_PASSCRED, &new->flags);
+	if (test_bit(SOCK_PASSSEC, &old->flags))
+		set_bit(SOCK_PASSSEC, &new->flags);
+}
+
 static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
 {
 	struct sock *sk = sock->sk;
@@ -1280,6 +1289,7 @@
 	/* attach accepted sock to socket */
 	unix_state_lock(tsk);
 	newsock->state = SS_CONNECTED;
+	unix_sock_inherit_flags(sock, newsock);
 	sock_graft(tsk, newsock);
 	unix_state_unlock(tsk);
 	return 0;
diff --git a/net/unix/diag.c b/net/unix/diag.c
index d591091..86fa0f3 100644
--- a/net/unix/diag.c
+++ b/net/unix/diag.c
@@ -124,6 +124,7 @@
 	rep->udiag_family = AF_UNIX;
 	rep->udiag_type = sk->sk_type;
 	rep->udiag_state = sk->sk_state;
+	rep->pad = 0;
 	rep->udiag_ino = sk_ino;
 	sock_diag_save_cookie(sk, rep->udiag_cookie);
 
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 6715396..aff959e 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -566,18 +566,13 @@
 	/* check and set up bitrates */
 	ieee80211_set_bitrate_flags(wiphy);
 
-
+	rtnl_lock();
 	res = device_add(&rdev->wiphy.dev);
-	if (res)
-		return res;
-
-	res = rfkill_register(rdev->rfkill);
 	if (res) {
-		device_del(&rdev->wiphy.dev);
+		rtnl_unlock();
 		return res;
 	}
 
-	rtnl_lock();
 	/* set up regulatory info */
 	wiphy_regulatory_register(wiphy);
 
@@ -606,6 +601,15 @@
 
 	rdev->wiphy.registered = true;
 	rtnl_unlock();
+
+	res = rfkill_register(rdev->rfkill);
+	if (res) {
+		rfkill_destroy(rdev->rfkill);
+		rdev->rfkill = NULL;
+		wiphy_unregister(&rdev->wiphy);
+		return res;
+	}
+
 	return 0;
 }
 EXPORT_SYMBOL(wiphy_register);
@@ -640,7 +644,8 @@
 		rtnl_unlock();
 		__count == 0; }));
 
-	rfkill_unregister(rdev->rfkill);
+	if (rdev->rfkill)
+		rfkill_unregister(rdev->rfkill);
 
 	rtnl_lock();
 	rdev->wiphy.registered = false;
@@ -953,8 +958,6 @@
 	case NETDEV_PRE_UP:
 		if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
 			return notifier_from_errno(-EOPNOTSUPP);
-		if (rfkill_blocked(rdev->rfkill))
-			return notifier_from_errno(-ERFKILL);
 		ret = cfg80211_can_add_interface(rdev, wdev->iftype);
 		if (ret)
 			return notifier_from_errno(ret);
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 9ad43c6..3159e9c 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -411,6 +411,9 @@
 cfg80211_can_add_interface(struct cfg80211_registered_device *rdev,
 			   enum nl80211_iftype iftype)
 {
+	if (rfkill_blocked(rdev->rfkill))
+		return -ERFKILL;
+
 	return cfg80211_can_change_interface(rdev, NULL, iftype);
 }
 
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 39bff7d..403fe29 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -263,6 +263,8 @@
 				if (chan->flags & IEEE80211_CHAN_DISABLED)
 					continue;
 				wdev->wext.ibss.chandef.chan = chan;
+				wdev->wext.ibss.chandef.center_freq1 =
+					chan->center_freq;
 				break;
 			}
 
@@ -347,6 +349,7 @@
 	if (chan) {
 		wdev->wext.ibss.chandef.chan = chan;
 		wdev->wext.ibss.chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
+		wdev->wext.ibss.chandef.center_freq1 = freq;
 		wdev->wext.ibss.channel_fixed = true;
 	} else {
 		/* cfg80211_ibss_wext_join will pick one if needed */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index af8d84a..626dc3b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2421,7 +2421,7 @@
 		change = true;
 	}
 
-	if (flags && (*flags & NL80211_MNTR_FLAG_ACTIVE) &&
+	if (flags && (*flags & MONITOR_FLAG_ACTIVE) &&
 	    !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
 		return -EOPNOTSUPP;
 
@@ -2483,7 +2483,7 @@
 				  info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
 				  &flags);
 
-	if (!err && (flags & NL80211_MNTR_FLAG_ACTIVE) &&
+	if (!err && (flags & MONITOR_FLAG_ACTIVE) &&
 	    !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
 		return -EOPNOTSUPP;
 
diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c
index 7d604c0..a271c27 100644
--- a/net/wireless/radiotap.c
+++ b/net/wireless/radiotap.c
@@ -97,6 +97,10 @@
 	struct ieee80211_radiotap_header *radiotap_header,
 	int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns)
 {
+	/* check the radiotap header can actually be present */
+	if (max_length < sizeof(struct ieee80211_radiotap_header))
+		return -EINVAL;
+
 	/* Linux only supports version 0 radiotap format */
 	if (radiotap_header->it_version)
 		return -EINVAL;
@@ -131,7 +135,8 @@
 			 */
 
 			if ((unsigned long)iterator->_arg -
-			    (unsigned long)iterator->_rtheader >
+			    (unsigned long)iterator->_rtheader +
+			    sizeof(uint32_t) >
 			    (unsigned long)iterator->_max_length)
 				return -EINVAL;
 		}
diff --git a/net/x25/Kconfig b/net/x25/Kconfig
index c959312c..e2fa133 100644
--- a/net/x25/Kconfig
+++ b/net/x25/Kconfig
@@ -16,8 +16,8 @@
 	  if you want that) and the lower level data link layer protocol LAPB
 	  (say Y to "LAPB Data Link Driver" below if you want that).
 
-	  You can read more about X.25 at <http://www.sangoma.com/x25.htm> and
-	  <http://www.cisco.com/univercd/cc/td/doc/product/software/ios11/cbook/cx25.htm>.
+	  You can read more about X.25 at <http://www.sangoma.com/tutorials/x25/> and
+	  <http://docwiki.cisco.com/wiki/X.25>.
 	  Information about X.25 for Linux is contained in the files
 	  <file:Documentation/networking/x25.txt> and
 	  <file:Documentation/networking/x25-iface.txt>.
diff --git a/net/xfrm/xfrm_ipcomp.c b/net/xfrm/xfrm_ipcomp.c
index 2906d52..3be02b6 100644
--- a/net/xfrm/xfrm_ipcomp.c
+++ b/net/xfrm/xfrm_ipcomp.c
@@ -141,14 +141,14 @@
 	const int plen = skb->len;
 	int dlen = IPCOMP_SCRATCH_SIZE;
 	u8 *start = skb->data;
-	const int cpu = get_cpu();
-	u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
-	struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu);
+	struct crypto_comp *tfm;
+	u8 *scratch;
 	int err;
 
 	local_bh_disable();
+	scratch = *this_cpu_ptr(ipcomp_scratches);
+	tfm = *this_cpu_ptr(ipcd->tfms);
 	err = crypto_comp_compress(tfm, start, plen, scratch, &dlen);
-	local_bh_enable();
 	if (err)
 		goto out;
 
@@ -158,13 +158,13 @@
 	}
 
 	memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen);
-	put_cpu();
+	local_bh_enable();
 
 	pskb_trim(skb, dlen + sizeof(struct ip_comp_hdr));
 	return 0;
 
 out:
-	put_cpu();
+	local_bh_enable();
 	return err;
 }
 
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index ed38d5d..76e1873 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -334,7 +334,8 @@
 
 	atomic_inc(&policy->genid);
 
-	del_timer(&policy->polq.hold_timer);
+	if (del_timer(&policy->polq.hold_timer))
+		xfrm_pol_put(policy);
 	xfrm_queue_purge(&policy->polq.hold_queue);
 
 	if (del_timer(&policy->timer))
@@ -589,7 +590,8 @@
 
 	spin_lock_bh(&pq->hold_queue.lock);
 	skb_queue_splice_init(&pq->hold_queue, &list);
-	del_timer(&pq->hold_timer);
+	if (del_timer(&pq->hold_timer))
+		xfrm_pol_put(old);
 	spin_unlock_bh(&pq->hold_queue.lock);
 
 	if (skb_queue_empty(&list))
@@ -600,7 +602,8 @@
 	spin_lock_bh(&pq->hold_queue.lock);
 	skb_queue_splice(&list, &pq->hold_queue);
 	pq->timeout = XFRM_QUEUE_TMO_MIN;
-	mod_timer(&pq->hold_timer, jiffies);
+	if (!mod_timer(&pq->hold_timer, jiffies))
+		xfrm_pol_hold(new);
 	spin_unlock_bh(&pq->hold_queue.lock);
 }
 
@@ -1769,6 +1772,10 @@
 
 	spin_lock(&pq->hold_queue.lock);
 	skb = skb_peek(&pq->hold_queue);
+	if (!skb) {
+		spin_unlock(&pq->hold_queue.lock);
+		goto out;
+	}
 	dst = skb_dst(skb);
 	sk = skb->sk;
 	xfrm_decode_session(skb, &fl, dst->ops->family);
@@ -1787,8 +1794,9 @@
 			goto purge_queue;
 
 		pq->timeout = pq->timeout << 1;
-		mod_timer(&pq->hold_timer, jiffies + pq->timeout);
-		return;
+		if (!mod_timer(&pq->hold_timer, jiffies + pq->timeout))
+			xfrm_pol_hold(pol);
+	goto out;
 	}
 
 	dst_release(dst);
@@ -1819,11 +1827,14 @@
 		err = dst_output(skb);
 	}
 
+out:
+	xfrm_pol_put(pol);
 	return;
 
 purge_queue:
 	pq->timeout = 0;
 	xfrm_queue_purge(&pq->hold_queue);
+	xfrm_pol_put(pol);
 }
 
 static int xdst_queue_output(struct sk_buff *skb)
@@ -1831,7 +1842,8 @@
 	unsigned long sched_next;
 	struct dst_entry *dst = skb_dst(skb);
 	struct xfrm_dst *xdst = (struct xfrm_dst *) dst;
-	struct xfrm_policy_queue *pq = &xdst->pols[0]->polq;
+	struct xfrm_policy *pol = xdst->pols[0];
+	struct xfrm_policy_queue *pq = &pol->polq;
 
 	if (pq->hold_queue.qlen > XFRM_MAX_QUEUE_LEN) {
 		kfree_skb(skb);
@@ -1850,10 +1862,12 @@
 	if (del_timer(&pq->hold_timer)) {
 		if (time_before(pq->hold_timer.expires, sched_next))
 			sched_next = pq->hold_timer.expires;
+		xfrm_pol_put(pol);
 	}
 
 	__skb_queue_tail(&pq->hold_queue, skb);
-	mod_timer(&pq->hold_timer, sched_next);
+	if (!mod_timer(&pq->hold_timer, sched_next))
+		xfrm_pol_hold(pol);
 
 	spin_unlock_bh(&pq->hold_queue.lock);
 
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c
index 8dafe6d3..dab57da 100644
--- a/net/xfrm/xfrm_replay.c
+++ b/net/xfrm/xfrm_replay.c
@@ -61,9 +61,9 @@
 
 	switch (event) {
 	case XFRM_REPLAY_UPDATE:
-		if (x->replay_maxdiff &&
-		    (x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
-		    (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) {
+		if (!x->replay_maxdiff ||
+		    ((x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
+		    (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff))) {
 			if (x->xflags & XFRM_TIME_DEFER)
 				event = XFRM_REPLAY_TIMEOUT;
 			else
@@ -129,8 +129,7 @@
 		return 0;
 
 	diff = x->replay.seq - seq;
-	if (diff >= min_t(unsigned int, x->props.replay_window,
-			  sizeof(x->replay.bitmap) * 8)) {
+	if (diff >= x->props.replay_window) {
 		x->stats.replay_window++;
 		goto err;
 	}
@@ -302,9 +301,10 @@
 
 	switch (event) {
 	case XFRM_REPLAY_UPDATE:
-		if (x->replay_maxdiff &&
-		    (replay_esn->seq - preplay_esn->seq < x->replay_maxdiff) &&
-		    (replay_esn->oseq - preplay_esn->oseq < x->replay_maxdiff)) {
+		if (!x->replay_maxdiff ||
+		    ((replay_esn->seq - preplay_esn->seq < x->replay_maxdiff) &&
+		    (replay_esn->oseq - preplay_esn->oseq
+		     < x->replay_maxdiff))) {
 			if (x->xflags & XFRM_TIME_DEFER)
 				event = XFRM_REPLAY_TIMEOUT;
 			else
@@ -353,28 +353,30 @@
 
 	switch (event) {
 	case XFRM_REPLAY_UPDATE:
-		if (!x->replay_maxdiff)
-			break;
-
-		if (replay_esn->seq_hi == preplay_esn->seq_hi)
-			seq_diff = replay_esn->seq - preplay_esn->seq;
-		else
-			seq_diff = ~preplay_esn->seq + replay_esn->seq + 1;
-
-		if (replay_esn->oseq_hi == preplay_esn->oseq_hi)
-			oseq_diff = replay_esn->oseq - preplay_esn->oseq;
-		else
-			oseq_diff = ~preplay_esn->oseq + replay_esn->oseq + 1;
-
-		if (seq_diff < x->replay_maxdiff &&
-		    oseq_diff < x->replay_maxdiff) {
-
-			if (x->xflags & XFRM_TIME_DEFER)
-				event = XFRM_REPLAY_TIMEOUT;
+		if (x->replay_maxdiff) {
+			if (replay_esn->seq_hi == preplay_esn->seq_hi)
+				seq_diff = replay_esn->seq - preplay_esn->seq;
 			else
-				return;
+				seq_diff = ~preplay_esn->seq + replay_esn->seq
+					   + 1;
+
+			if (replay_esn->oseq_hi == preplay_esn->oseq_hi)
+				oseq_diff = replay_esn->oseq
+					    - preplay_esn->oseq;
+			else
+				oseq_diff = ~preplay_esn->oseq
+					    + replay_esn->oseq + 1;
+
+			if (seq_diff >= x->replay_maxdiff ||
+			    oseq_diff >= x->replay_maxdiff)
+				break;
 		}
 
+		if (x->xflags & XFRM_TIME_DEFER)
+			event = XFRM_REPLAY_TIMEOUT;
+		else
+			return;
+
 		break;
 
 	case XFRM_REPLAY_TIMEOUT:
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 3f565e4..f964d4c 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -446,7 +446,8 @@
 	memcpy(&x->sel, &p->sel, sizeof(x->sel));
 	memcpy(&x->lft, &p->lft, sizeof(x->lft));
 	x->props.mode = p->mode;
-	x->props.replay_window = p->replay_window;
+	x->props.replay_window = min_t(unsigned int, p->replay_window,
+					sizeof(x->replay.bitmap) * 8);
 	x->props.reqid = p->reqid;
 	x->props.family = p->family;
 	memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr));
@@ -1856,7 +1857,7 @@
 	if (x->km.state != XFRM_STATE_VALID)
 		goto out;
 
-	err = xfrm_replay_verify_len(x->replay_esn, rp);
+	err = xfrm_replay_verify_len(x->replay_esn, re);
 	if (err)
 		goto out;
 
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 487ac6f..9a11f9f 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -55,6 +55,7 @@
 static unsigned int table_size, table_cnt;
 static int all_symbols = 0;
 static char symbol_prefix_char = '\0';
+static unsigned long long kernel_start_addr = 0;
 
 int token_profit[0x10000];
 
@@ -65,7 +66,10 @@
 
 static void usage(void)
 {
-	fprintf(stderr, "Usage: kallsyms [--all-symbols] [--symbol-prefix=<prefix char>] < in.map > out.S\n");
+	fprintf(stderr, "Usage: kallsyms [--all-symbols] "
+			"[--symbol-prefix=<prefix char>] "
+			"[--page-offset=<CONFIG_PAGE_OFFSET>] "
+			"< in.map > out.S\n");
 	exit(1);
 }
 
@@ -194,6 +198,9 @@
 	int i;
 	int offset = 1;
 
+	if (s->addr < kernel_start_addr)
+		return 0;
+
 	/* skip prefix char */
 	if (symbol_prefix_char && *(s->sym + 1) == symbol_prefix_char)
 		offset++;
@@ -646,6 +653,9 @@
 				if ((*p == '"' && *(p+2) == '"') || (*p == '\'' && *(p+2) == '\''))
 					p++;
 				symbol_prefix_char = *p;
+			} else if (strncmp(argv[i], "--page-offset=", 14) == 0) {
+				const char *p = &argv[i][14];
+				kernel_start_addr = strtoull(p, NULL, 16);
 			} else
 				usage();
 		}
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 0149949..32b10f5 100644
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -82,6 +82,8 @@
 		kallsymopt="${kallsymopt} --all-symbols"
 	fi
 
+	kallsymopt="${kallsymopt} --page-offset=$CONFIG_PAGE_OFFSET"
+
 	local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL}               \
 		      ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
 
diff --git a/scripts/package/Makefile b/scripts/package/Makefile
index a4f31c9..c5d4733 100644
--- a/scripts/package/Makefile
+++ b/scripts/package/Makefile
@@ -115,7 +115,9 @@
 	-o $(perf-tar).tar;                                         \
 mkdir -p $(perf-tar);                                               \
 git --git-dir=$(srctree)/.git rev-parse HEAD > $(perf-tar)/HEAD;    \
-tar rf $(perf-tar).tar $(perf-tar)/HEAD;                            \
+(cd $(srctree)/tools/perf;                                          \
+util/PERF-VERSION-GEN ../../$(perf-tar)/ 2>/dev/null);              \
+tar rf $(perf-tar).tar $(perf-tar)/HEAD $(perf-tar)/PERF-VERSION-FILE; \
 rm -r $(perf-tar);                                                  \
 $(if $(findstring tar-src,$@),,                                     \
 $(if $(findstring bz2,$@),bzip2,                                    \
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 95c2b26..7db9954 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -580,15 +580,13 @@
 
 	/* check if the next ns is a sibling, parent, gp, .. */
 	parent = ns->parent;
-	while (parent) {
+	while (ns != root) {
 		mutex_unlock(&ns->lock);
 		next = list_entry_next(ns, base.list);
 		if (!list_entry_is_head(next, &parent->sub_ns, base.list)) {
 			mutex_lock(&next->lock);
 			return next;
 		}
-		if (parent == root)
-			return NULL;
 		ns = parent;
 		parent = parent->parent;
 	}
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 345bec0..705c287 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -610,6 +610,7 @@
 	aa_put_dfa(profile->policy.dfa);
 	aa_put_replacedby(profile->replacedby);
 
+	kzfree(profile->hash);
 	kzfree(profile);
 }
 
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index c123628..7c2a0a7 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -63,16 +63,6 @@
 
 struct cgroup_subsys devices_subsys;
 
-static int devcgroup_can_attach(struct cgroup_subsys_state *new_css,
-				struct cgroup_taskset *set)
-{
-	struct task_struct *task = cgroup_taskset_first(set);
-
-	if (current != task && !capable(CAP_SYS_ADMIN))
-		return -EPERM;
-	return 0;
-}
-
 /*
  * called under devcgroup_mutex
  */
@@ -697,7 +687,6 @@
 
 struct cgroup_subsys devices_subsys = {
 	.name = "devices",
-	.can_attach = devcgroup_can_attach,
 	.css_alloc = devcgroup_css_alloc,
 	.css_free = devcgroup_css_free,
 	.css_online = devcgroup_online,
diff --git a/sound/aoa/core/gpio-feature.c b/sound/aoa/core/gpio-feature.c
index faa3174..f341539 100644
--- a/sound/aoa/core/gpio-feature.c
+++ b/sound/aoa/core/gpio-feature.c
@@ -10,8 +10,9 @@
  * registers.
  */
 
-#include <asm/pmac_feature.h>
+#include <linux/of_irq.h>
 #include <linux/interrupt.h>
+#include <asm/pmac_feature.h>
 #include "../aoa.h"
 
 /* TODO: these are lots of global variables
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c
index 15e7613..4678360 100644
--- a/sound/aoa/soundbus/i2sbus/core.c
+++ b/sound/aoa/soundbus/i2sbus/core.c
@@ -11,6 +11,8 @@
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <sound/core.h>
 
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c
index e6f4633..66de90e 100644
--- a/sound/arm/pxa2xx-ac97-lib.c
+++ b/sound/arm/pxa2xx-ac97-lib.c
@@ -117,8 +117,7 @@
 {
 	gsr_bits = 0;
 
-	GCR |= GCR_WARM_RST | GCR_PRIRDY_IEN | GCR_SECRDY_IEN;
-	wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
+	GCR |= GCR_WARM_RST;
 }
 
 static inline void pxa_ac97_cold_pxa25x(void)
@@ -129,8 +128,6 @@
 	gsr_bits = 0;
 
 	GCR = GCR_COLD_RST;
-	GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
-	wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
 }
 #endif
 
@@ -149,8 +146,6 @@
 
 static inline void pxa_ac97_cold_pxa27x(void)
 {
-	unsigned int timeout;
-
 	GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
 	GCR &= ~GCR_COLD_RST;  /* then assert nCRST */
 
@@ -161,29 +156,20 @@
 	udelay(5);
 	clk_disable(ac97conf_clk);
 	GCR = GCR_COLD_RST | GCR_WARM_RST;
-	timeout = 100;     /* wait for the codec-ready bit to be set */
-	while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
-		mdelay(1);
 }
 #endif
 
 #ifdef CONFIG_PXA3xx
 static inline void pxa_ac97_warm_pxa3xx(void)
 {
-	int timeout = 100;
-
 	gsr_bits = 0;
 
 	/* Can't use interrupts */
 	GCR |= GCR_WARM_RST;
-	while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
-		mdelay(1);
 }
 
 static inline void pxa_ac97_cold_pxa3xx(void)
 {
-	int timeout = 1000;
-
 	/* Hold CLKBPB for 100us */
 	GCR = 0;
 	GCR = GCR_CLKBPB;
@@ -199,14 +185,13 @@
 	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
 
 	GCR = GCR_WARM_RST | GCR_COLD_RST;
-	while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--)
-		mdelay(10);
 }
 #endif
 
 bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97)
 {
 	unsigned long gsr;
+	unsigned int timeout = 100;
 
 #ifdef CONFIG_PXA25x
 	if (cpu_is_pxa25x())
@@ -223,7 +208,11 @@
 		pxa_ac97_warm_pxa3xx();
 	else
 #endif
-		BUG();
+		snd_BUG();
+
+	while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
+		mdelay(1);
+
 	gsr = GSR | gsr_bits;
 	if (!(gsr & (GSR_PCR | GSR_SCR))) {
 		printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
@@ -239,6 +228,7 @@
 bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97)
 {
 	unsigned long gsr;
+	unsigned int timeout = 1000;
 
 #ifdef CONFIG_PXA25x
 	if (cpu_is_pxa25x())
@@ -255,7 +245,10 @@
 		pxa_ac97_cold_pxa3xx();
 	else
 #endif
-		BUG();
+		snd_BUG();
+
+	while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
+		mdelay(1);
 
 	gsr = GSR | gsr_bits;
 	if (!(gsr & (GSR_PCR | GSR_SCR))) {
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index 5066a37..9a2ac1e 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -185,7 +185,7 @@
 		goto err;
 
 	card->dev = &dev->dev;
-	strncpy(card->driver, dev->dev.driver->name, sizeof(card->driver));
+	strlcpy(card->driver, dev->dev.driver->name, sizeof(card->driver));
 
 	ret = pxa2xx_pcm_new(card, &pxa2xx_ac97_pcm_client, &pxa2xx_ac97_pcm);
 	if (ret)
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
index ae63d22..c5f0ddd 100644
--- a/sound/atmel/ac97c.c
+++ b/sound/atmel/ac97c.c
@@ -34,7 +34,6 @@
 #include <linux/dw_dmac.h>
 
 #include <mach/cpu.h>
-#include <mach/gpio.h>
 
 #ifdef CONFIG_ARCH_AT91
 #include <mach/hardware.h>
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index bea523a..d9af638 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -680,14 +680,48 @@
 		return -EPERM;
 	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
 	if (!retval) {
-		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
-		wake_up(&stream->runtime->sleep);
+		snd_compr_drain_notify(stream);
 		stream->runtime->total_bytes_available = 0;
 		stream->runtime->total_bytes_transferred = 0;
 	}
 	return retval;
 }
 
+static int snd_compress_wait_for_drain(struct snd_compr_stream *stream)
+{
+	int ret;
+
+	/*
+	 * We are called with lock held. So drop the lock while we wait for
+	 * drain complete notfication from the driver
+	 *
+	 * It is expected that driver will notify the drain completion and then
+	 * stream will be moved to SETUP state, even if draining resulted in an
+	 * error. We can trigger next track after this.
+	 */
+	stream->runtime->state = SNDRV_PCM_STATE_DRAINING;
+	mutex_unlock(&stream->device->lock);
+
+	/* we wait for drain to complete here, drain can return when
+	 * interruption occurred, wait returned error or success.
+	 * For the first two cases we don't do anything different here and
+	 * return after waking up
+	 */
+
+	ret = wait_event_interruptible(stream->runtime->sleep,
+			(stream->runtime->state != SNDRV_PCM_STATE_DRAINING));
+	if (ret == -ERESTARTSYS)
+		pr_debug("wait aborted by a signal");
+	else if (ret)
+		pr_debug("wait for drain failed with %d\n", ret);
+
+
+	wake_up(&stream->runtime->sleep);
+	mutex_lock(&stream->device->lock);
+
+	return ret;
+}
+
 static int snd_compr_drain(struct snd_compr_stream *stream)
 {
 	int retval;
@@ -695,12 +729,15 @@
 	if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
 			stream->runtime->state == SNDRV_PCM_STATE_SETUP)
 		return -EPERM;
+
 	retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
-	if (!retval) {
-		stream->runtime->state = SNDRV_PCM_STATE_DRAINING;
+	if (retval) {
+		pr_debug("SND_COMPR_TRIGGER_DRAIN failed %d\n", retval);
 		wake_up(&stream->runtime->sleep);
+		return retval;
 	}
-	return retval;
+
+	return snd_compress_wait_for_drain(stream);
 }
 
 static int snd_compr_next_track(struct snd_compr_stream *stream)
@@ -736,9 +773,14 @@
 		return -EPERM;
 
 	retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_PARTIAL_DRAIN);
+	if (retval) {
+		pr_debug("Partial drain returned failure\n");
+		wake_up(&stream->runtime->sleep);
+		return retval;
+	}
 
 	stream->next_track = false;
-	return retval;
+	return snd_compress_wait_for_drain(stream);
 }
 
 static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
diff --git a/sound/core/init.c b/sound/core/init.c
index 6b90871..1351f22 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -66,7 +66,7 @@
 #ifdef MODULE
 	const char *s1, *s2;
 
-	if (!module || !module->name || !slots[idx])
+	if (!module || !*module->name || !slots[idx])
 		return 0;
 
 	s1 = module->name;
@@ -597,7 +597,7 @@
 	/* last resort... */
 	snd_printk(KERN_ERR "unable to set card id (%s)\n", id);
 	if (card->proc_root->name)
-		strcpy(card->id, card->proc_root->name);
+		strlcpy(card->id, card->proc_root->name, sizeof(card->id));
 }
 
 /**
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index bdf826f..9d93f02 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -30,6 +30,7 @@
 #include <linux/seq_file.h>
 #include <asm/uaccess.h>
 #include <linux/dma-mapping.h>
+#include <linux/genalloc.h>
 #include <linux/moduleparam.h>
 #include <linux/mutex.h>
 #include <sound/memalloc.h>
@@ -157,6 +158,51 @@
 	dec_snd_pages(pg);
 	dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma);
 }
+
+#ifdef CONFIG_GENERIC_ALLOCATOR
+/**
+ * snd_malloc_dev_iram - allocate memory from on-chip internal ram
+ * @dmab: buffer allocation record to store the allocated data
+ * @size: number of bytes to allocate from the iram
+ *
+ * This function requires iram phandle provided via of_node
+ */
+static void snd_malloc_dev_iram(struct snd_dma_buffer *dmab, size_t size)
+{
+	struct device *dev = dmab->dev.dev;
+	struct gen_pool *pool = NULL;
+
+	dmab->area = NULL;
+	dmab->addr = 0;
+
+	if (dev->of_node)
+		pool = of_get_named_gen_pool(dev->of_node, "iram", 0);
+
+	if (!pool)
+		return;
+
+	/* Assign the pool into private_data field */
+	dmab->private_data = pool;
+
+	dmab->area = (void *)gen_pool_alloc(pool, size);
+	if (!dmab->area)
+		return;
+
+	dmab->addr = gen_pool_virt_to_phys(pool, (unsigned long)dmab->area);
+}
+
+/**
+ * snd_free_dev_iram - free allocated specific memory from on-chip internal ram
+ * @dmab: buffer allocation record to store the allocated data
+ */
+static void snd_free_dev_iram(struct snd_dma_buffer *dmab)
+{
+	struct gen_pool *pool = dmab->private_data;
+
+	if (pool && dmab->area)
+		gen_pool_free(pool, (unsigned long)dmab->area, dmab->bytes);
+}
+#endif /* CONFIG_GENERIC_ALLOCATOR */
 #endif /* CONFIG_HAS_DMA */
 
 /*
@@ -197,6 +243,16 @@
 		dmab->addr = 0;
 		break;
 #ifdef CONFIG_HAS_DMA
+#ifdef CONFIG_GENERIC_ALLOCATOR
+	case SNDRV_DMA_TYPE_DEV_IRAM:
+		snd_malloc_dev_iram(dmab, size);
+		if (dmab->area)
+			break;
+		/* Internal memory might have limited size and no enough space,
+		 * so if we fail to malloc, try to fetch memory traditionally.
+		 */
+		dmab->dev.type = SNDRV_DMA_TYPE_DEV;
+#endif /* CONFIG_GENERIC_ALLOCATOR */
 	case SNDRV_DMA_TYPE_DEV:
 		dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr);
 		break;
@@ -269,6 +325,11 @@
 		snd_free_pages(dmab->area, dmab->bytes);
 		break;
 #ifdef CONFIG_HAS_DMA
+#ifdef CONFIG_GENERIC_ALLOCATOR
+	case SNDRV_DMA_TYPE_DEV_IRAM:
+		snd_free_dev_iram(dmab);
+		break;
+#endif /* CONFIG_GENERIC_ALLOCATOR */
 	case SNDRV_DMA_TYPE_DEV:
 		snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
 		break;
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 17f45e8..e1e9e0c 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -49,6 +49,8 @@
 	struct snd_pcm *pcm;
 
 	list_for_each_entry(pcm, &snd_pcm_devices, list) {
+		if (pcm->internal)
+			continue;
 		if (pcm->card == card && pcm->device == device)
 			return pcm;
 	}
@@ -60,6 +62,8 @@
 	struct snd_pcm *pcm;
 
 	list_for_each_entry(pcm, &snd_pcm_devices, list) {
+		if (pcm->internal)
+			continue;
 		if (pcm->card == card && pcm->device > device)
 			return pcm->device;
 		else if (pcm->card->number > card->number)
diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c
index aa924d9..94d0873 100644
--- a/sound/core/pcm_dmaengine.c
+++ b/sound/core/pcm_dmaengine.c
@@ -63,23 +63,19 @@
 	struct dma_slave_config *slave_config)
 {
 	enum dma_slave_buswidth buswidth;
+	int bits;
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S8:
-		buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
-		break;
-	case SNDRV_PCM_FORMAT_S16_LE:
-		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
-		break;
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_S32_LE:
-		buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
-		break;
-	default:
+	bits = snd_pcm_format_physical_width(params_format(params));
+	if (bits < 8 || bits > 64)
 		return -EINVAL;
-	}
+	else if (bits == 8)
+		buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	else if (bits == 16)
+		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+	else if (bits <= 32)
+		buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	else
+		buswidth = DMA_SLAVE_BUSWIDTH_8_BYTES;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		slave_config->direction = DMA_MEM_TO_DEV;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index a68d4c6..01a5e05 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -2428,6 +2428,7 @@
 	case SNDRV_PCM_STATE_DRAINING:
 		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
 			goto __badfd;
+		/* Fall through */
 	case SNDRV_PCM_STATE_RUNNING:
 		if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
 			break;
@@ -2460,6 +2461,7 @@
 	case SNDRV_PCM_STATE_DRAINING:
 		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
 			goto __badfd;
+		/* Fall through */
 	case SNDRV_PCM_STATE_RUNNING:
 		if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
 			break;
@@ -3199,6 +3201,14 @@
 			     struct vm_area_struct *area)
 {
 	area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
+#ifdef CONFIG_GENERIC_ALLOCATOR
+	if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_IRAM) {
+		area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
+		return remap_pfn_range(area, area->vm_start,
+				substream->dma_buffer.addr >> PAGE_SHIFT,
+				area->vm_end - area->vm_start, area->vm_page_prot);
+	}
+#endif /* CONFIG_GENERIC_ALLOCATOR */
 #ifdef ARCH_HAS_DMA_MMAP_COHERENT
 	if (!substream->ops->page &&
 	    substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV)
diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c
index 0c796bc..6c6d09a 100644
--- a/sound/drivers/opl3/opl3_midi.c
+++ b/sound/drivers/opl3/opl3_midi.c
@@ -390,6 +390,11 @@
 		voice = snd_opl3_oss_map[chan->number];		
 	}
 
+	if (voice < 0) {
+		spin_unlock_irqrestore(&opl3->voice_lock, flags);
+		return;
+	}
+
 	if (voice < MAX_OPL2_VOICES) {
 		/* Left register block for voices 0 .. 8 */
 		reg_side = OPL3_LEFT;
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
index 1c19cd7..f664bae 100644
--- a/sound/drivers/pcsp/pcsp.c
+++ b/sound/drivers/pcsp/pcsp.c
@@ -46,8 +46,9 @@
 	int err;
 	int div, min_div, order;
 
+	hrtimer_get_res(CLOCK_MONOTONIC, &tp);
+
 	if (!nopcm) {
-		hrtimer_get_res(CLOCK_MONOTONIC, &tp);
 		if (tp.tv_sec || tp.tv_nsec > PCSP_MAX_PERIOD_NS) {
 			printk(KERN_ERR "PCSP: Timer resolution is not sufficient "
 				"(%linS)\n", tp.tv_nsec);
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig
index ea063e1..b3e274f 100644
--- a/sound/firewire/Kconfig
+++ b/sound/firewire/Kconfig
@@ -11,6 +11,21 @@
 	tristate
 	depends on SND_PCM
 
+config SND_DICE
+	tristate "DICE-based DACs (EXPERIMENTAL)"
+	select SND_HWDEP
+	select SND_PCM
+	select SND_FIREWIRE_LIB
+	help
+	  Say Y here to include support for many DACs based on the DICE
+	  chip family (DICE-II/Jr/Mini) from TC Applied Technologies.
+
+	  At the moment, this driver supports playback only.  If you
+	  want to use devices that support capturing, use FFADO instead.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-dice.
+
 config SND_FIREWIRE_SPEAKERS
 	tristate "FireWire speakers"
 	select SND_PCM
diff --git a/sound/firewire/Makefile b/sound/firewire/Makefile
index 460179d..5099550 100644
--- a/sound/firewire/Makefile
+++ b/sound/firewire/Makefile
@@ -1,10 +1,12 @@
 snd-firewire-lib-objs := lib.o iso-resources.o packets-buffer.o \
 			 fcp.o cmp.o amdtp.o
+snd-dice-objs := dice.o
 snd-firewire-speakers-objs := speakers.o
 snd-isight-objs := isight.o
 snd-scs1x-objs := scs1x.o
 
 obj-$(CONFIG_SND_FIREWIRE_LIB) += snd-firewire-lib.o
+obj-$(CONFIG_SND_DICE) += snd-dice.o
 obj-$(CONFIG_SND_FIREWIRE_SPEAKERS) += snd-firewire-speakers.o
 obj-$(CONFIG_SND_ISIGHT) += snd-isight.o
 obj-$(CONFIG_SND_SCS1X) += snd-scs1x.o
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c
index ea995af..d322689 100644
--- a/sound/firewire/amdtp.c
+++ b/sound/firewire/amdtp.c
@@ -42,9 +42,6 @@
 int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit,
 			  enum cip_out_flags flags)
 {
-	if (flags != CIP_NONBLOCKING)
-		return -EINVAL;
-
 	s->unit = fw_unit_get(unit);
 	s->flags = flags;
 	s->context = ERR_PTR(-1);
@@ -62,73 +59,91 @@
  */
 void amdtp_out_stream_destroy(struct amdtp_out_stream *s)
 {
-	WARN_ON(!IS_ERR(s->context));
+	WARN_ON(amdtp_out_stream_running(s));
 	mutex_destroy(&s->mutex);
 	fw_unit_put(s->unit);
 }
 EXPORT_SYMBOL(amdtp_out_stream_destroy);
 
+const unsigned int amdtp_syt_intervals[CIP_SFC_COUNT] = {
+	[CIP_SFC_32000]  =  8,
+	[CIP_SFC_44100]  =  8,
+	[CIP_SFC_48000]  =  8,
+	[CIP_SFC_88200]  = 16,
+	[CIP_SFC_96000]  = 16,
+	[CIP_SFC_176400] = 32,
+	[CIP_SFC_192000] = 32,
+};
+EXPORT_SYMBOL(amdtp_syt_intervals);
+
 /**
- * amdtp_out_stream_set_rate - set the sample rate
+ * amdtp_out_stream_set_parameters - set stream parameters
  * @s: the AMDTP output stream to configure
  * @rate: the sample rate
+ * @pcm_channels: the number of PCM samples in each data block, to be encoded
+ *                as AM824 multi-bit linear audio
+ * @midi_ports: the number of MIDI ports (i.e., MPX-MIDI Data Channels)
  *
- * The sample rate must be set before the stream is started, and must not be
+ * The parameters must be set before the stream is started, and must not be
  * changed while the stream is running.
  */
-void amdtp_out_stream_set_rate(struct amdtp_out_stream *s, unsigned int rate)
+void amdtp_out_stream_set_parameters(struct amdtp_out_stream *s,
+				     unsigned int rate,
+				     unsigned int pcm_channels,
+				     unsigned int midi_ports)
 {
-	static const struct {
-		unsigned int rate;
-		unsigned int syt_interval;
-	} rate_info[] = {
-		[CIP_SFC_32000]  = {  32000,  8, },
-		[CIP_SFC_44100]  = {  44100,  8, },
-		[CIP_SFC_48000]  = {  48000,  8, },
-		[CIP_SFC_88200]  = {  88200, 16, },
-		[CIP_SFC_96000]  = {  96000, 16, },
-		[CIP_SFC_176400] = { 176400, 32, },
-		[CIP_SFC_192000] = { 192000, 32, },
+	static const unsigned int rates[] = {
+		[CIP_SFC_32000]  =  32000,
+		[CIP_SFC_44100]  =  44100,
+		[CIP_SFC_48000]  =  48000,
+		[CIP_SFC_88200]  =  88200,
+		[CIP_SFC_96000]  =  96000,
+		[CIP_SFC_176400] = 176400,
+		[CIP_SFC_192000] = 192000,
 	};
 	unsigned int sfc;
 
-	if (WARN_ON(!IS_ERR(s->context)))
+	if (WARN_ON(amdtp_out_stream_running(s)))
 		return;
 
-	for (sfc = 0; sfc < ARRAY_SIZE(rate_info); ++sfc)
-		if (rate_info[sfc].rate == rate) {
-			s->sfc = sfc;
-			s->syt_interval = rate_info[sfc].syt_interval;
-			return;
-		}
+	for (sfc = 0; sfc < CIP_SFC_COUNT; ++sfc)
+		if (rates[sfc] == rate)
+			goto sfc_found;
 	WARN_ON(1);
+	return;
+
+sfc_found:
+	s->dual_wire = (s->flags & CIP_HI_DUALWIRE) && sfc > CIP_SFC_96000;
+	if (s->dual_wire) {
+		sfc -= 2;
+		rate /= 2;
+		pcm_channels *= 2;
+	}
+	s->sfc = sfc;
+	s->data_block_quadlets = pcm_channels + DIV_ROUND_UP(midi_ports, 8);
+	s->pcm_channels = pcm_channels;
+	s->midi_ports = midi_ports;
+
+	s->syt_interval = amdtp_syt_intervals[sfc];
+
+	/* default buffering in the device */
+	s->transfer_delay = TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE;
+	if (s->flags & CIP_BLOCKING)
+		/* additional buffering needed to adjust for no-data packets */
+		s->transfer_delay += TICKS_PER_SECOND * s->syt_interval / rate;
 }
-EXPORT_SYMBOL(amdtp_out_stream_set_rate);
+EXPORT_SYMBOL(amdtp_out_stream_set_parameters);
 
 /**
  * amdtp_out_stream_get_max_payload - get the stream's packet size
  * @s: the AMDTP output stream
  *
  * This function must not be called before the stream has been configured
- * with amdtp_out_stream_set_hw_params(), amdtp_out_stream_set_pcm(), and
- * amdtp_out_stream_set_midi().
+ * with amdtp_out_stream_set_parameters().
  */
 unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s)
 {
-	static const unsigned int max_data_blocks[] = {
-		[CIP_SFC_32000]  =  4,
-		[CIP_SFC_44100]  =  6,
-		[CIP_SFC_48000]  =  6,
-		[CIP_SFC_88200]  = 12,
-		[CIP_SFC_96000]  = 12,
-		[CIP_SFC_176400] = 23,
-		[CIP_SFC_192000] = 24,
-	};
-
-	s->data_block_quadlets = s->pcm_channels;
-	s->data_block_quadlets += DIV_ROUND_UP(s->midi_ports, 8);
-
-	return 8 + max_data_blocks[s->sfc] * 4 * s->data_block_quadlets;
+	return 8 + s->syt_interval * s->data_block_quadlets * 4;
 }
 EXPORT_SYMBOL(amdtp_out_stream_get_max_payload);
 
@@ -138,19 +153,26 @@
 static void amdtp_write_s32(struct amdtp_out_stream *s,
 			    struct snd_pcm_substream *pcm,
 			    __be32 *buffer, unsigned int frames);
+static void amdtp_write_s16_dualwire(struct amdtp_out_stream *s,
+				     struct snd_pcm_substream *pcm,
+				     __be32 *buffer, unsigned int frames);
+static void amdtp_write_s32_dualwire(struct amdtp_out_stream *s,
+				     struct snd_pcm_substream *pcm,
+				     __be32 *buffer, unsigned int frames);
 
 /**
  * amdtp_out_stream_set_pcm_format - set the PCM format
  * @s: the AMDTP output stream to configure
  * @format: the format of the ALSA PCM device
  *
- * The sample format must be set before the stream is started, and must not be
- * changed while the stream is running.
+ * The sample format must be set after the other paramters (rate/PCM channels/
+ * MIDI) and before the stream is started, and must not be changed while the
+ * stream is running.
  */
 void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s,
 				     snd_pcm_format_t format)
 {
-	if (WARN_ON(!IS_ERR(s->context)))
+	if (WARN_ON(amdtp_out_stream_running(s)))
 		return;
 
 	switch (format) {
@@ -158,10 +180,16 @@
 		WARN_ON(1);
 		/* fall through */
 	case SNDRV_PCM_FORMAT_S16:
-		s->transfer_samples = amdtp_write_s16;
+		if (s->dual_wire)
+			s->transfer_samples = amdtp_write_s16_dualwire;
+		else
+			s->transfer_samples = amdtp_write_s16;
 		break;
 	case SNDRV_PCM_FORMAT_S32:
-		s->transfer_samples = amdtp_write_s32;
+		if (s->dual_wire)
+			s->transfer_samples = amdtp_write_s32_dualwire;
+		else
+			s->transfer_samples = amdtp_write_s32;
 		break;
 	}
 }
@@ -248,7 +276,7 @@
 	s->last_syt_offset = syt_offset;
 
 	if (syt_offset < TICKS_PER_CYCLE) {
-		syt_offset += TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE;
+		syt_offset += s->transfer_delay;
 		syt = (cycle + syt_offset / TICKS_PER_CYCLE) << 12;
 		syt += syt_offset % TICKS_PER_CYCLE;
 
@@ -268,7 +296,7 @@
 
 	channels = s->pcm_channels;
 	src = (void *)runtime->dma_area +
-			s->pcm_buffer_pointer * (runtime->frame_bits / 8);
+			frames_to_bytes(runtime, s->pcm_buffer_pointer);
 	remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer;
 	frame_step = s->data_block_quadlets - channels;
 
@@ -294,7 +322,7 @@
 
 	channels = s->pcm_channels;
 	src = (void *)runtime->dma_area +
-			s->pcm_buffer_pointer * (runtime->frame_bits / 8);
+			frames_to_bytes(runtime, s->pcm_buffer_pointer);
 	remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer;
 	frame_step = s->data_block_quadlets - channels;
 
@@ -310,6 +338,68 @@
 	}
 }
 
+static void amdtp_write_s32_dualwire(struct amdtp_out_stream *s,
+				     struct snd_pcm_substream *pcm,
+				     __be32 *buffer, unsigned int frames)
+{
+	struct snd_pcm_runtime *runtime = pcm->runtime;
+	unsigned int channels, frame_adjust_1, frame_adjust_2, i, c;
+	const u32 *src;
+
+	channels = s->pcm_channels;
+	src = (void *)runtime->dma_area +
+			s->pcm_buffer_pointer * (runtime->frame_bits / 8);
+	frame_adjust_1 = channels - 1;
+	frame_adjust_2 = 1 - (s->data_block_quadlets - channels);
+
+	channels /= 2;
+	for (i = 0; i < frames; ++i) {
+		for (c = 0; c < channels; ++c) {
+			*buffer = cpu_to_be32((*src >> 8) | 0x40000000);
+			src++;
+			buffer += 2;
+		}
+		buffer -= frame_adjust_1;
+		for (c = 0; c < channels; ++c) {
+			*buffer = cpu_to_be32((*src >> 8) | 0x40000000);
+			src++;
+			buffer += 2;
+		}
+		buffer -= frame_adjust_2;
+	}
+}
+
+static void amdtp_write_s16_dualwire(struct amdtp_out_stream *s,
+				     struct snd_pcm_substream *pcm,
+				     __be32 *buffer, unsigned int frames)
+{
+	struct snd_pcm_runtime *runtime = pcm->runtime;
+	unsigned int channels, frame_adjust_1, frame_adjust_2, i, c;
+	const u16 *src;
+
+	channels = s->pcm_channels;
+	src = (void *)runtime->dma_area +
+			s->pcm_buffer_pointer * (runtime->frame_bits / 8);
+	frame_adjust_1 = channels - 1;
+	frame_adjust_2 = 1 - (s->data_block_quadlets - channels);
+
+	channels /= 2;
+	for (i = 0; i < frames; ++i) {
+		for (c = 0; c < channels; ++c) {
+			*buffer = cpu_to_be32((*src << 8) | 0x40000000);
+			src++;
+			buffer += 2;
+		}
+		buffer -= frame_adjust_1;
+		for (c = 0; c < channels; ++c) {
+			*buffer = cpu_to_be32((*src << 8) | 0x40000000);
+			src++;
+			buffer += 2;
+		}
+		buffer -= frame_adjust_2;
+	}
+}
+
 static void amdtp_fill_pcm_silence(struct amdtp_out_stream *s,
 				   __be32 *buffer, unsigned int frames)
 {
@@ -344,8 +434,17 @@
 		return;
 	index = s->packet_index;
 
-	data_blocks = calculate_data_blocks(s);
 	syt = calculate_syt(s, cycle);
+	if (!(s->flags & CIP_BLOCKING)) {
+		data_blocks = calculate_data_blocks(s);
+	} else {
+		if (syt != 0xffff) {
+			data_blocks = s->syt_interval;
+		} else {
+			data_blocks = 0;
+			syt = 0xffffff;
+		}
+	}
 
 	buffer = s->buffer.packets[index].buffer;
 	buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) |
@@ -386,6 +485,9 @@
 	s->packet_index = index;
 
 	if (pcm) {
+		if (s->dual_wire)
+			data_blocks *= 2;
+
 		ptr = s->pcm_buffer_pointer + data_blocks;
 		if (ptr >= pcm->runtime->buffer_size)
 			ptr -= pcm->runtime->buffer_size;
@@ -455,9 +557,8 @@
  * @speed: firewire speed code
  *
  * The stream cannot be started until it has been configured with
- * amdtp_out_stream_set_hw_params(), amdtp_out_stream_set_pcm(), and
- * amdtp_out_stream_set_midi(); and it must be started before any
- * PCM or MIDI device can be started.
+ * amdtp_out_stream_set_parameters() and amdtp_out_stream_set_pcm_format(),
+ * and it must be started before any PCM or MIDI device can be started.
  */
 int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed)
 {
@@ -477,7 +578,7 @@
 
 	mutex_lock(&s->mutex);
 
-	if (WARN_ON(!IS_ERR(s->context) ||
+	if (WARN_ON(amdtp_out_stream_running(s) ||
 		    (!s->pcm_channels && !s->midi_ports))) {
 		err = -EBADFD;
 		goto err_unlock;
@@ -573,7 +674,7 @@
 {
 	mutex_lock(&s->mutex);
 
-	if (IS_ERR(s->context)) {
+	if (!amdtp_out_stream_running(s)) {
 		mutex_unlock(&s->mutex);
 		return;
 	}
diff --git a/sound/firewire/amdtp.h b/sound/firewire/amdtp.h
index f6103d6..839ebf8 100644
--- a/sound/firewire/amdtp.h
+++ b/sound/firewire/amdtp.h
@@ -1,6 +1,7 @@
 #ifndef SOUND_FIREWIRE_AMDTP_H_INCLUDED
 #define SOUND_FIREWIRE_AMDTP_H_INCLUDED
 
+#include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/mutex.h>
 #include "packets-buffer.h"
@@ -11,9 +12,18 @@
  *	sample_rate/8000 samples, with rounding up or down to adjust
  *	for clock skew and left-over fractional samples.  This should
  *	be used if supported by the device.
+ * @CIP_BLOCKING: In blocking mode, each packet contains either zero or
+ *	SYT_INTERVAL samples, with these two types alternating so that
+ *	the overall sample rate comes out right.
+ * @CIP_HI_DUALWIRE: At rates above 96 kHz, pretend that the stream runs
+ *	at half the actual sample rate with twice the number of channels;
+ *	two samples of a channel are stored consecutively in the packet.
+ *	Requires blocking mode and SYT_INTERVAL-aligned PCM buffer size.
  */
 enum cip_out_flags {
-	CIP_NONBLOCKING = 0,
+	CIP_NONBLOCKING	= 0x00,
+	CIP_BLOCKING	= 0x01,
+	CIP_HI_DUALWIRE	= 0x02,
 };
 
 /**
@@ -27,6 +37,7 @@
 	CIP_SFC_96000  = 4,
 	CIP_SFC_176400 = 5,
 	CIP_SFC_192000 = 6,
+	CIP_SFC_COUNT
 };
 
 #define AMDTP_OUT_PCM_FORMAT_BITS	(SNDRV_PCM_FMTBIT_S16 | \
@@ -43,6 +54,7 @@
 	struct mutex mutex;
 
 	enum cip_sfc sfc;
+	bool dual_wire;
 	unsigned int data_block_quadlets;
 	unsigned int pcm_channels;
 	unsigned int midi_ports;
@@ -51,6 +63,7 @@
 				 __be32 *buffer, unsigned int frames);
 
 	unsigned int syt_interval;
+	unsigned int transfer_delay;
 	unsigned int source_node_id_field;
 	struct iso_packets_buffer buffer;
 
@@ -74,7 +87,10 @@
 			  enum cip_out_flags flags);
 void amdtp_out_stream_destroy(struct amdtp_out_stream *s);
 
-void amdtp_out_stream_set_rate(struct amdtp_out_stream *s, unsigned int rate);
+void amdtp_out_stream_set_parameters(struct amdtp_out_stream *s,
+				     unsigned int rate,
+				     unsigned int pcm_channels,
+				     unsigned int midi_ports);
 unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s);
 
 int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed);
@@ -87,31 +103,11 @@
 unsigned long amdtp_out_stream_pcm_pointer(struct amdtp_out_stream *s);
 void amdtp_out_stream_pcm_abort(struct amdtp_out_stream *s);
 
-/**
- * amdtp_out_stream_set_pcm - configure format of PCM samples
- * @s: the AMDTP output stream to be configured
- * @pcm_channels: the number of PCM samples in each data block, to be encoded
- *                as AM824 multi-bit linear audio
- *
- * This function must not be called while the stream is running.
- */
-static inline void amdtp_out_stream_set_pcm(struct amdtp_out_stream *s,
-					    unsigned int pcm_channels)
-{
-	s->pcm_channels = pcm_channels;
-}
+extern const unsigned int amdtp_syt_intervals[CIP_SFC_COUNT];
 
-/**
- * amdtp_out_stream_set_midi - configure format of MIDI data
- * @s: the AMDTP output stream to be configured
- * @midi_ports: the number of MIDI ports (i.e., MPX-MIDI Data Channels)
- *
- * This function must not be called while the stream is running.
- */
-static inline void amdtp_out_stream_set_midi(struct amdtp_out_stream *s,
-					     unsigned int midi_ports)
+static inline bool amdtp_out_stream_running(struct amdtp_out_stream *s)
 {
-	s->midi_ports = midi_ports;
+	return !IS_ERR(s->context);
 }
 
 /**
diff --git a/sound/firewire/cmp.c b/sound/firewire/cmp.c
index 645cb0b..efdbf58 100644
--- a/sound/firewire/cmp.c
+++ b/sound/firewire/cmp.c
@@ -48,9 +48,6 @@
 		      int (*check)(struct cmp_connection *c, __be32 pcr),
 		      enum bus_reset_handling bus_reset_handling)
 {
-	struct fw_device *device = fw_parent_device(c->resources.unit);
-	int generation = c->resources.generation;
-	int rcode, errors = 0;
 	__be32 old_arg, buffer[2];
 	int err;
 
@@ -59,36 +56,31 @@
 		old_arg = buffer[0];
 		buffer[1] = modify(c, buffer[0]);
 
-		rcode = fw_run_transaction(
-				device->card, TCODE_LOCK_COMPARE_SWAP,
-				device->node_id, generation, device->max_speed,
+		err = snd_fw_transaction(
+				c->resources.unit, TCODE_LOCK_COMPARE_SWAP,
 				CSR_REGISTER_BASE + CSR_IPCR(c->pcr_index),
-				buffer, 8);
+				buffer, 8,
+				FW_FIXED_GENERATION | c->resources.generation);
 
-		if (rcode == RCODE_COMPLETE) {
-			if (buffer[0] == old_arg) /* success? */
-				break;
+		if (err < 0) {
+			if (err == -EAGAIN &&
+			    bus_reset_handling == SUCCEED_ON_BUS_RESET)
+				err = 0;
+			return err;
+		}
 
-			if (check) {
-				err = check(c, buffer[0]);
-				if (err < 0)
-					return err;
-			}
-		} else if (rcode == RCODE_GENERATION)
-			goto bus_reset;
-		else if (rcode_is_permanent_error(rcode) || ++errors >= 3)
-			goto io_error;
+		if (buffer[0] == old_arg) /* success? */
+			break;
+
+		if (check) {
+			err = check(c, buffer[0]);
+			if (err < 0)
+				return err;
+		}
 	}
 	c->last_pcr_value = buffer[1];
 
 	return 0;
-
-io_error:
-	cmp_error(c, "transaction failed: %s\n", fw_rcode_string(rcode));
-	return -EIO;
-
-bus_reset:
-	return bus_reset_handling == ABORT_ON_BUS_RESET ? -EAGAIN : 0;
 }
 
 
@@ -108,7 +100,7 @@
 
 	err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST,
 				 CSR_REGISTER_BASE + CSR_IMPR,
-				 &impr_be, 4);
+				 &impr_be, 4, 0);
 	if (err < 0)
 		return err;
 	impr = be32_to_cpu(impr_be);
diff --git a/sound/firewire/dice-interface.h b/sound/firewire/dice-interface.h
new file mode 100644
index 0000000..27b044f
--- /dev/null
+++ b/sound/firewire/dice-interface.h
@@ -0,0 +1,371 @@
+#ifndef SOUND_FIREWIRE_DICE_INTERFACE_H_INCLUDED
+#define SOUND_FIREWIRE_DICE_INTERFACE_H_INCLUDED
+
+/*
+ * DICE device interface definitions
+ */
+
+/*
+ * Generally, all registers can be read like memory, i.e., with quadlet read or
+ * block read transactions with at least quadlet-aligned offset and length.
+ * Writes are not allowed except where noted; quadlet-sized registers must be
+ * written with a quadlet write transaction.
+ *
+ * All values are in big endian.  The DICE firmware runs on a little-endian CPU
+ * and just byte-swaps _all_ quadlets on the bus, so values without endianness
+ * (e.g. strings) get scrambled and must be byte-swapped again by the driver.
+ */
+
+/*
+ * Streaming is handled by the "DICE driver" interface.  Its registers are
+ * located in this private address space.
+ */
+#define DICE_PRIVATE_SPACE		0xffffe0000000uLL
+
+/*
+ * The registers are organized in several sections, which are organized
+ * separately to allow them to be extended individually.  Whether a register is
+ * supported can be detected by checking its offset against its section's size.
+ *
+ * The section offset values are relative to DICE_PRIVATE_SPACE; the offset/
+ * size values are measured in quadlets.  Read-only.
+ */
+#define DICE_GLOBAL_OFFSET		0x00
+#define DICE_GLOBAL_SIZE		0x04
+#define DICE_TX_OFFSET			0x08
+#define DICE_TX_SIZE			0x0c
+#define DICE_RX_OFFSET			0x10
+#define DICE_RX_SIZE			0x14
+#define DICE_EXT_SYNC_OFFSET		0x18
+#define DICE_EXT_SYNC_SIZE		0x1c
+#define DICE_UNUSED2_OFFSET		0x20
+#define DICE_UNUSED2_SIZE		0x24
+
+/*
+ * Global settings.
+ */
+
+/*
+ * Stores the full 64-bit address (node ID and offset in the node's address
+ * space) where the device will send notifications.  Must be changed with
+ * a compare/swap transaction by the owner.  This register is automatically
+ * cleared on a bus reset.
+ */
+#define GLOBAL_OWNER			0x000
+#define  OWNER_NO_OWNER			0xffff000000000000uLL
+#define  OWNER_NODE_SHIFT		48
+
+/*
+ * A bitmask with asynchronous events; read-only.  When any event(s) happen,
+ * the bits of previous events are cleared, and the value of this register is
+ * also written to the address stored in the owner register.
+ */
+#define GLOBAL_NOTIFICATION		0x008
+/* Some registers in the Rx/Tx sections may have changed. */
+#define  NOTIFY_RX_CFG_CHG		0x00000001
+#define  NOTIFY_TX_CFG_CHG		0x00000002
+/* Lock status of the current clock source may have changed. */
+#define  NOTIFY_LOCK_CHG		0x00000010
+/* Write to the clock select register has been finished. */
+#define  NOTIFY_CLOCK_ACCEPTED		0x00000020
+/* Lock status of some clock source has changed. */
+#define  NOTIFY_EXT_STATUS		0x00000040
+/* Other bits may be used for device-specific events. */
+
+/*
+ * A name that can be customized for each device; read/write.  Padded with zero
+ * bytes.  Quadlets are byte-swapped.  The encoding is whatever the host driver
+ * happens to be using.
+ */
+#define GLOBAL_NICK_NAME		0x00c
+#define  NICK_NAME_SIZE			64
+
+/*
+ * The current sample rate and clock source; read/write.  Whether a clock
+ * source or sample rate is supported is device-specific; the internal clock
+ * source is always available.  Low/mid/high = up to 48/96/192 kHz.  This
+ * register can be changed even while streams are running.
+ */
+#define GLOBAL_CLOCK_SELECT		0x04c
+#define  CLOCK_SOURCE_MASK		0x000000ff
+#define  CLOCK_SOURCE_AES1		0x00000000
+#define  CLOCK_SOURCE_AES2		0x00000001
+#define  CLOCK_SOURCE_AES3		0x00000002
+#define  CLOCK_SOURCE_AES4		0x00000003
+#define  CLOCK_SOURCE_AES_ANY		0x00000004
+#define  CLOCK_SOURCE_ADAT		0x00000005
+#define  CLOCK_SOURCE_TDIF		0x00000006
+#define  CLOCK_SOURCE_WC		0x00000007
+#define  CLOCK_SOURCE_ARX1		0x00000008
+#define  CLOCK_SOURCE_ARX2		0x00000009
+#define  CLOCK_SOURCE_ARX3		0x0000000a
+#define  CLOCK_SOURCE_ARX4		0x0000000b
+#define  CLOCK_SOURCE_INTERNAL		0x0000000c
+#define  CLOCK_RATE_MASK		0x0000ff00
+#define  CLOCK_RATE_32000		0x00000000
+#define  CLOCK_RATE_44100		0x00000100
+#define  CLOCK_RATE_48000		0x00000200
+#define  CLOCK_RATE_88200		0x00000300
+#define  CLOCK_RATE_96000		0x00000400
+#define  CLOCK_RATE_176400		0x00000500
+#define  CLOCK_RATE_192000		0x00000600
+#define  CLOCK_RATE_ANY_LOW		0x00000700
+#define  CLOCK_RATE_ANY_MID		0x00000800
+#define  CLOCK_RATE_ANY_HIGH		0x00000900
+#define  CLOCK_RATE_NONE		0x00000a00
+#define  CLOCK_RATE_SHIFT		8
+
+/*
+ * Enable streaming; read/write.  Writing a non-zero value (re)starts all
+ * streams that have a valid iso channel set; zero stops all streams.  The
+ * streams' parameters must be configured before starting.  This register is
+ * automatically cleared on a bus reset.
+ */
+#define GLOBAL_ENABLE			0x050
+
+/*
+ * Status of the sample clock; read-only.
+ */
+#define GLOBAL_STATUS			0x054
+/* The current clock source is locked. */
+#define  STATUS_SOURCE_LOCKED		0x00000001
+/* The actual sample rate; CLOCK_RATE_32000-_192000 or _NONE. */
+#define  STATUS_NOMINAL_RATE_MASK	0x0000ff00
+
+/*
+ * Status of all clock sources; read-only.
+ */
+#define GLOBAL_EXTENDED_STATUS		0x058
+/*
+ * The _LOCKED bits always show the current status; any change generates
+ * a notification.
+ */
+#define  EXT_STATUS_AES1_LOCKED		0x00000001
+#define  EXT_STATUS_AES2_LOCKED		0x00000002
+#define  EXT_STATUS_AES3_LOCKED		0x00000004
+#define  EXT_STATUS_AES4_LOCKED		0x00000008
+#define  EXT_STATUS_ADAT_LOCKED		0x00000010
+#define  EXT_STATUS_TDIF_LOCKED		0x00000020
+#define  EXT_STATUS_ARX1_LOCKED		0x00000040
+#define  EXT_STATUS_ARX2_LOCKED		0x00000080
+#define  EXT_STATUS_ARX3_LOCKED		0x00000100
+#define  EXT_STATUS_ARX4_LOCKED		0x00000200
+#define  EXT_STATUS_WC_LOCKED		0x00000400
+/*
+ * The _SLIP bits do not generate notifications; a set bit indicates that an
+ * error occurred since the last time when this register was read with
+ * a quadlet read transaction.
+ */
+#define  EXT_STATUS_AES1_SLIP		0x00010000
+#define  EXT_STATUS_AES2_SLIP		0x00020000
+#define  EXT_STATUS_AES3_SLIP		0x00040000
+#define  EXT_STATUS_AES4_SLIP		0x00080000
+#define  EXT_STATUS_ADAT_SLIP		0x00100000
+#define  EXT_STATUS_TDIF_SLIP		0x00200000
+#define  EXT_STATUS_ARX1_SLIP		0x00400000
+#define  EXT_STATUS_ARX2_SLIP		0x00800000
+#define  EXT_STATUS_ARX3_SLIP		0x01000000
+#define  EXT_STATUS_ARX4_SLIP		0x02000000
+#define  EXT_STATUS_WC_SLIP		0x04000000
+
+/*
+ * The measured rate of the current clock source, in Hz; read-only.
+ */
+#define GLOBAL_SAMPLE_RATE		0x05c
+
+/*
+ * The version of the DICE driver specification that this device conforms to;
+ * read-only.
+ */
+#define GLOBAL_VERSION			0x060
+
+/* Some old firmware versions do not have the following global registers: */
+
+/*
+ * Supported sample rates and clock sources; read-only.
+ */
+#define GLOBAL_CLOCK_CAPABILITIES	0x064
+#define  CLOCK_CAP_RATE_32000		0x00000001
+#define  CLOCK_CAP_RATE_44100		0x00000002
+#define  CLOCK_CAP_RATE_48000		0x00000004
+#define  CLOCK_CAP_RATE_88200		0x00000008
+#define  CLOCK_CAP_RATE_96000		0x00000010
+#define  CLOCK_CAP_RATE_176400		0x00000020
+#define  CLOCK_CAP_RATE_192000		0x00000040
+#define  CLOCK_CAP_SOURCE_AES1		0x00010000
+#define  CLOCK_CAP_SOURCE_AES2		0x00020000
+#define  CLOCK_CAP_SOURCE_AES3		0x00040000
+#define  CLOCK_CAP_SOURCE_AES4		0x00080000
+#define  CLOCK_CAP_SOURCE_AES_ANY	0x00100000
+#define  CLOCK_CAP_SOURCE_ADAT		0x00200000
+#define  CLOCK_CAP_SOURCE_TDIF		0x00400000
+#define  CLOCK_CAP_SOURCE_WC		0x00800000
+#define  CLOCK_CAP_SOURCE_ARX1		0x01000000
+#define  CLOCK_CAP_SOURCE_ARX2		0x02000000
+#define  CLOCK_CAP_SOURCE_ARX3		0x04000000
+#define  CLOCK_CAP_SOURCE_ARX4		0x08000000
+#define  CLOCK_CAP_SOURCE_INTERNAL	0x10000000
+
+/*
+ * Names of all clock sources; read-only.  Quadlets are byte-swapped.  Names
+ * are separated with one backslash, the list is terminated with two
+ * backslashes.  Unused clock sources are included.
+ */
+#define GLOBAL_CLOCK_SOURCE_NAMES	0x068
+#define  CLOCK_SOURCE_NAMES_SIZE	256
+
+/*
+ * Capture stream settings.  This section includes the number/size registers
+ * and the registers of all streams.
+ */
+
+/*
+ * The number of supported capture streams; read-only.
+ */
+#define TX_NUMBER			0x000
+
+/*
+ * The size of one stream's register block, in quadlets; read-only.  The
+ * registers of the first stream follow immediately afterwards; the registers
+ * of the following streams are offset by this register's value.
+ */
+#define TX_SIZE				0x004
+
+/*
+ * The isochronous channel number on which packets are sent, or -1 if the
+ * stream is not to be used; read/write.
+ */
+#define TX_ISOCHRONOUS			0x008
+
+/*
+ * The number of audio channels; read-only.  There will be one quadlet per
+ * channel; the first channel is the first quadlet in a data block.
+ */
+#define TX_NUMBER_AUDIO			0x00c
+
+/*
+ * The number of MIDI ports, 0-8; read-only.  If > 0, there will be one
+ * additional quadlet in each data block, following the audio quadlets.
+ */
+#define TX_NUMBER_MIDI			0x010
+
+/*
+ * The speed at which the packets are sent, SCODE_100-_400; read/write.
+ */
+#define TX_SPEED			0x014
+
+/*
+ * Names of all audio channels; read-only.  Quadlets are byte-swapped.  Names
+ * are separated with one backslash, the list is terminated with two
+ * backslashes.
+ */
+#define TX_NAMES			0x018
+#define  TX_NAMES_SIZE			256
+
+/*
+ * Audio IEC60958 capabilities; read-only.  Bitmask with one bit per audio
+ * channel.
+ */
+#define TX_AC3_CAPABILITIES		0x118
+
+/*
+ * Send audio data with IEC60958 label; read/write.  Bitmask with one bit per
+ * audio channel.  This register can be changed even while the stream is
+ * running.
+ */
+#define TX_AC3_ENABLE			0x11c
+
+/*
+ * Playback stream settings.  This section includes the number/size registers
+ * and the registers of all streams.
+ */
+
+/*
+ * The number of supported playback streams; read-only.
+ */
+#define RX_NUMBER			0x000
+
+/*
+ * The size of one stream's register block, in quadlets; read-only.  The
+ * registers of the first stream follow immediately afterwards; the registers
+ * of the following streams are offset by this register's value.
+ */
+#define RX_SIZE				0x004
+
+/*
+ * The isochronous channel number on which packets are received, or -1 if the
+ * stream is not to be used; read/write.
+ */
+#define RX_ISOCHRONOUS			0x008
+
+/*
+ * Index of first quadlet to be interpreted; read/write.  If > 0, that many
+ * quadlets at the beginning of each data block will be ignored, and all the
+ * audio and MIDI quadlets will follow.
+ */
+#define RX_SEQ_START			0x00c
+
+/*
+ * The number of audio channels; read-only.  There will be one quadlet per
+ * channel.
+ */
+#define RX_NUMBER_AUDIO			0x010
+
+/*
+ * The number of MIDI ports, 0-8; read-only.  If > 0, there will be one
+ * additional quadlet in each data block, following the audio quadlets.
+ */
+#define RX_NUMBER_MIDI			0x014
+
+/*
+ * Names of all audio channels; read-only.  Quadlets are byte-swapped.  Names
+ * are separated with one backslash, the list is terminated with two
+ * backslashes.
+ */
+#define RX_NAMES			0x018
+#define  RX_NAMES_SIZE			256
+
+/*
+ * Audio IEC60958 capabilities; read-only.  Bitmask with one bit per audio
+ * channel.
+ */
+#define RX_AC3_CAPABILITIES		0x118
+
+/*
+ * Receive audio data with IEC60958 label; read/write.  Bitmask with one bit
+ * per audio channel.  This register can be changed even while the stream is
+ * running.
+ */
+#define RX_AC3_ENABLE			0x11c
+
+/*
+ * Extended synchronization information.
+ * This section can be read completely with a block read request.
+ */
+
+/*
+ * Current clock source; read-only.
+ */
+#define EXT_SYNC_CLOCK_SOURCE		0x000
+
+/*
+ * Clock source is locked (boolean); read-only.
+ */
+#define EXT_SYNC_LOCKED			0x004
+
+/*
+ * Current sample rate (CLOCK_RATE_* >> CLOCK_RATE_SHIFT), _32000-_192000 or
+ * _NONE; read-only.
+ */
+#define EXT_SYNC_RATE			0x008
+
+/*
+ * ADAT user data bits; read-only.
+ */
+#define EXT_SYNC_ADAT_USER_DATA		0x00c
+/* The data bits, if available. */
+#define  ADAT_USER_DATA_MASK		0x0f
+/* The data bits are not available. */
+#define  ADAT_USER_DATA_NO_DATA		0x10
+
+#endif
diff --git a/sound/firewire/dice.c b/sound/firewire/dice.c
new file mode 100644
index 0000000..6feee66
--- /dev/null
+++ b/sound/firewire/dice.c
@@ -0,0 +1,1494 @@
+/*
+ * TC Applied Technologies Digital Interface Communications Engine driver
+ *
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+
+#include <linux/compat.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <sound/control.h>
+#include <sound/core.h>
+#include <sound/firewire.h>
+#include <sound/hwdep.h>
+#include <sound/info.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include "amdtp.h"
+#include "iso-resources.h"
+#include "lib.h"
+#include "dice-interface.h"
+
+
+struct dice {
+	struct snd_card *card;
+	struct fw_unit *unit;
+	spinlock_t lock;
+	struct mutex mutex;
+	unsigned int global_offset;
+	unsigned int rx_offset;
+	unsigned int clock_caps;
+	unsigned int rx_channels[3];
+	unsigned int rx_midi_ports[3];
+	struct fw_address_handler notification_handler;
+	int owner_generation;
+	int dev_lock_count; /* > 0 driver, < 0 userspace */
+	bool dev_lock_changed;
+	bool global_enabled;
+	struct completion clock_accepted;
+	wait_queue_head_t hwdep_wait;
+	u32 notification_bits;
+	struct fw_iso_resources resources;
+	struct amdtp_out_stream stream;
+};
+
+MODULE_DESCRIPTION("DICE driver");
+MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
+MODULE_LICENSE("GPL v2");
+
+static const unsigned int dice_rates[] = {
+	/* mode 0 */
+	[0] =  32000,
+	[1] =  44100,
+	[2] =  48000,
+	/* mode 1 */
+	[3] =  88200,
+	[4] =  96000,
+	/* mode 2 */
+	[5] = 176400,
+	[6] = 192000,
+};
+
+static unsigned int rate_to_index(unsigned int rate)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(dice_rates); ++i)
+		if (dice_rates[i] == rate)
+			return i;
+
+	return 0;
+}
+
+static unsigned int rate_index_to_mode(unsigned int rate_index)
+{
+	return ((int)rate_index - 1) / 2;
+}
+
+static void dice_lock_changed(struct dice *dice)
+{
+	dice->dev_lock_changed = true;
+	wake_up(&dice->hwdep_wait);
+}
+
+static int dice_try_lock(struct dice *dice)
+{
+	int err;
+
+	spin_lock_irq(&dice->lock);
+
+	if (dice->dev_lock_count < 0) {
+		err = -EBUSY;
+		goto out;
+	}
+
+	if (dice->dev_lock_count++ == 0)
+		dice_lock_changed(dice);
+	err = 0;
+
+out:
+	spin_unlock_irq(&dice->lock);
+
+	return err;
+}
+
+static void dice_unlock(struct dice *dice)
+{
+	spin_lock_irq(&dice->lock);
+
+	if (WARN_ON(dice->dev_lock_count <= 0))
+		goto out;
+
+	if (--dice->dev_lock_count == 0)
+		dice_lock_changed(dice);
+
+out:
+	spin_unlock_irq(&dice->lock);
+}
+
+static inline u64 global_address(struct dice *dice, unsigned int offset)
+{
+	return DICE_PRIVATE_SPACE + dice->global_offset + offset;
+}
+
+// TODO: rx index
+static inline u64 rx_address(struct dice *dice, unsigned int offset)
+{
+	return DICE_PRIVATE_SPACE + dice->rx_offset + offset;
+}
+
+static int dice_owner_set(struct dice *dice)
+{
+	struct fw_device *device = fw_parent_device(dice->unit);
+	__be64 *buffer;
+	int err, errors = 0;
+
+	buffer = kmalloc(2 * 8, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	for (;;) {
+		buffer[0] = cpu_to_be64(OWNER_NO_OWNER);
+		buffer[1] = cpu_to_be64(
+			((u64)device->card->node_id << OWNER_NODE_SHIFT) |
+			dice->notification_handler.offset);
+
+		dice->owner_generation = device->generation;
+		smp_rmb(); /* node_id vs. generation */
+		err = snd_fw_transaction(dice->unit,
+					 TCODE_LOCK_COMPARE_SWAP,
+					 global_address(dice, GLOBAL_OWNER),
+					 buffer, 2 * 8,
+					 FW_FIXED_GENERATION |
+							dice->owner_generation);
+
+		if (err == 0) {
+			if (buffer[0] != cpu_to_be64(OWNER_NO_OWNER)) {
+				dev_err(&dice->unit->device,
+					"device is already in use\n");
+				err = -EBUSY;
+			}
+			break;
+		}
+		if (err != -EAGAIN || ++errors >= 3)
+			break;
+
+		msleep(20);
+	}
+
+	kfree(buffer);
+
+	return err;
+}
+
+static int dice_owner_update(struct dice *dice)
+{
+	struct fw_device *device = fw_parent_device(dice->unit);
+	__be64 *buffer;
+	int err;
+
+	if (dice->owner_generation == -1)
+		return 0;
+
+	buffer = kmalloc(2 * 8, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	buffer[0] = cpu_to_be64(OWNER_NO_OWNER);
+	buffer[1] = cpu_to_be64(
+		((u64)device->card->node_id << OWNER_NODE_SHIFT) |
+		dice->notification_handler.offset);
+
+	dice->owner_generation = device->generation;
+	smp_rmb(); /* node_id vs. generation */
+	err = snd_fw_transaction(dice->unit, TCODE_LOCK_COMPARE_SWAP,
+				 global_address(dice, GLOBAL_OWNER),
+				 buffer, 2 * 8,
+				 FW_FIXED_GENERATION | dice->owner_generation);
+
+	if (err == 0) {
+		if (buffer[0] != cpu_to_be64(OWNER_NO_OWNER)) {
+			dev_err(&dice->unit->device,
+				"device is already in use\n");
+			err = -EBUSY;
+		}
+	} else if (err == -EAGAIN) {
+		err = 0; /* try again later */
+	}
+
+	kfree(buffer);
+
+	if (err < 0)
+		dice->owner_generation = -1;
+
+	return err;
+}
+
+static void dice_owner_clear(struct dice *dice)
+{
+	struct fw_device *device = fw_parent_device(dice->unit);
+	__be64 *buffer;
+
+	buffer = kmalloc(2 * 8, GFP_KERNEL);
+	if (!buffer)
+		return;
+
+	buffer[0] = cpu_to_be64(
+		((u64)device->card->node_id << OWNER_NODE_SHIFT) |
+		dice->notification_handler.offset);
+	buffer[1] = cpu_to_be64(OWNER_NO_OWNER);
+	snd_fw_transaction(dice->unit, TCODE_LOCK_COMPARE_SWAP,
+			   global_address(dice, GLOBAL_OWNER),
+			   buffer, 2 * 8, FW_QUIET |
+			   FW_FIXED_GENERATION | dice->owner_generation);
+
+	kfree(buffer);
+
+	dice->owner_generation = -1;
+}
+
+static int dice_enable_set(struct dice *dice)
+{
+	__be32 value;
+	int err;
+
+	value = cpu_to_be32(1);
+	err = snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST,
+				 global_address(dice, GLOBAL_ENABLE),
+				 &value, 4,
+				 FW_FIXED_GENERATION | dice->owner_generation);
+	if (err < 0)
+		return err;
+
+	dice->global_enabled = true;
+
+	return 0;
+}
+
+static void dice_enable_clear(struct dice *dice)
+{
+	__be32 value;
+
+	if (!dice->global_enabled)
+		return;
+
+	value = 0;
+	snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST,
+			   global_address(dice, GLOBAL_ENABLE),
+			   &value, 4, FW_QUIET |
+			   FW_FIXED_GENERATION | dice->owner_generation);
+
+	dice->global_enabled = false;
+}
+
+static void dice_notification(struct fw_card *card, struct fw_request *request,
+			      int tcode, int destination, int source,
+			      int generation, unsigned long long offset,
+			      void *data, size_t length, void *callback_data)
+{
+	struct dice *dice = callback_data;
+	u32 bits;
+	unsigned long flags;
+
+	if (tcode != TCODE_WRITE_QUADLET_REQUEST) {
+		fw_send_response(card, request, RCODE_TYPE_ERROR);
+		return;
+	}
+	if ((offset & 3) != 0) {
+		fw_send_response(card, request, RCODE_ADDRESS_ERROR);
+		return;
+	}
+
+	bits = be32_to_cpup(data);
+
+	spin_lock_irqsave(&dice->lock, flags);
+	dice->notification_bits |= bits;
+	spin_unlock_irqrestore(&dice->lock, flags);
+
+	fw_send_response(card, request, RCODE_COMPLETE);
+
+	if (bits & NOTIFY_CLOCK_ACCEPTED)
+		complete(&dice->clock_accepted);
+	wake_up(&dice->hwdep_wait);
+}
+
+static int dice_rate_constraint(struct snd_pcm_hw_params *params,
+				struct snd_pcm_hw_rule *rule)
+{
+	struct dice *dice = rule->private;
+	const struct snd_interval *channels =
+		hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+	struct snd_interval *rate =
+		hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+	struct snd_interval allowed_rates = {
+		.min = UINT_MAX, .max = 0, .integer = 1
+	};
+	unsigned int i, mode;
+
+	for (i = 0; i < ARRAY_SIZE(dice_rates); ++i) {
+		mode = rate_index_to_mode(i);
+		if ((dice->clock_caps & (1 << i)) &&
+		    snd_interval_test(channels, dice->rx_channels[mode])) {
+			allowed_rates.min = min(allowed_rates.min,
+						dice_rates[i]);
+			allowed_rates.max = max(allowed_rates.max,
+						dice_rates[i]);
+		}
+	}
+
+	return snd_interval_refine(rate, &allowed_rates);
+}
+
+static int dice_channels_constraint(struct snd_pcm_hw_params *params,
+				    struct snd_pcm_hw_rule *rule)
+{
+	struct dice *dice = rule->private;
+	const struct snd_interval *rate =
+		hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
+	struct snd_interval *channels =
+		hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+	struct snd_interval allowed_channels = {
+		.min = UINT_MAX, .max = 0, .integer = 1
+	};
+	unsigned int i, mode;
+
+	for (i = 0; i < ARRAY_SIZE(dice_rates); ++i)
+		if ((dice->clock_caps & (1 << i)) &&
+		    snd_interval_test(rate, dice_rates[i])) {
+			mode = rate_index_to_mode(i);
+			allowed_channels.min = min(allowed_channels.min,
+						   dice->rx_channels[mode]);
+			allowed_channels.max = max(allowed_channels.max,
+						   dice->rx_channels[mode]);
+		}
+
+	return snd_interval_refine(channels, &allowed_channels);
+}
+
+static int dice_open(struct snd_pcm_substream *substream)
+{
+	static const struct snd_pcm_hardware hardware = {
+		.info = SNDRV_PCM_INFO_MMAP |
+			SNDRV_PCM_INFO_MMAP_VALID |
+			SNDRV_PCM_INFO_BATCH |
+			SNDRV_PCM_INFO_INTERLEAVED |
+			SNDRV_PCM_INFO_BLOCK_TRANSFER,
+		.formats = AMDTP_OUT_PCM_FORMAT_BITS,
+		.channels_min = UINT_MAX,
+		.channels_max = 0,
+		.buffer_bytes_max = 16 * 1024 * 1024,
+		.period_bytes_min = 1,
+		.period_bytes_max = UINT_MAX,
+		.periods_min = 1,
+		.periods_max = UINT_MAX,
+	};
+	struct dice *dice = substream->private_data;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	unsigned int i;
+	int err;
+
+	err = dice_try_lock(dice);
+	if (err < 0)
+		goto error;
+
+	runtime->hw = hardware;
+
+	for (i = 0; i < ARRAY_SIZE(dice_rates); ++i)
+		if (dice->clock_caps & (1 << i))
+			runtime->hw.rates |=
+				snd_pcm_rate_to_rate_bit(dice_rates[i]);
+	snd_pcm_limit_hw_rates(runtime);
+
+	for (i = 0; i < 3; ++i)
+		if (dice->rx_channels[i]) {
+			runtime->hw.channels_min = min(runtime->hw.channels_min,
+						       dice->rx_channels[i]);
+			runtime->hw.channels_max = max(runtime->hw.channels_max,
+						       dice->rx_channels[i]);
+		}
+
+	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+				  dice_rate_constraint, dice,
+				  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+	if (err < 0)
+		goto err_lock;
+	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+				  dice_channels_constraint, dice,
+				  SNDRV_PCM_HW_PARAM_RATE, -1);
+	if (err < 0)
+		goto err_lock;
+
+	err = snd_pcm_hw_constraint_step(runtime, 0,
+					 SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 32);
+	if (err < 0)
+		goto err_lock;
+	err = snd_pcm_hw_constraint_step(runtime, 0,
+					 SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 32);
+	if (err < 0)
+		goto err_lock;
+
+	err = snd_pcm_hw_constraint_minmax(runtime,
+					   SNDRV_PCM_HW_PARAM_PERIOD_TIME,
+					   5000, UINT_MAX);
+	if (err < 0)
+		goto err_lock;
+
+	err = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+	if (err < 0)
+		goto err_lock;
+
+	return 0;
+
+err_lock:
+	dice_unlock(dice);
+error:
+	return err;
+}
+
+static int dice_close(struct snd_pcm_substream *substream)
+{
+	struct dice *dice = substream->private_data;
+
+	dice_unlock(dice);
+
+	return 0;
+}
+
+static int dice_stream_start_packets(struct dice *dice)
+{
+	int err;
+
+	if (amdtp_out_stream_running(&dice->stream))
+		return 0;
+
+	err = amdtp_out_stream_start(&dice->stream, dice->resources.channel,
+				     fw_parent_device(dice->unit)->max_speed);
+	if (err < 0)
+		return err;
+
+	err = dice_enable_set(dice);
+	if (err < 0) {
+		amdtp_out_stream_stop(&dice->stream);
+		return err;
+	}
+
+	return 0;
+}
+
+static int dice_stream_start(struct dice *dice)
+{
+	__be32 channel;
+	int err;
+
+	if (!dice->resources.allocated) {
+		err = fw_iso_resources_allocate(&dice->resources,
+				amdtp_out_stream_get_max_payload(&dice->stream),
+				fw_parent_device(dice->unit)->max_speed);
+		if (err < 0)
+			goto error;
+
+		channel = cpu_to_be32(dice->resources.channel);
+		err = snd_fw_transaction(dice->unit,
+					 TCODE_WRITE_QUADLET_REQUEST,
+					 rx_address(dice, RX_ISOCHRONOUS),
+					 &channel, 4, 0);
+		if (err < 0)
+			goto err_resources;
+	}
+
+	err = dice_stream_start_packets(dice);
+	if (err < 0)
+		goto err_rx_channel;
+
+	return 0;
+
+err_rx_channel:
+	channel = cpu_to_be32((u32)-1);
+	snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST,
+			   rx_address(dice, RX_ISOCHRONOUS), &channel, 4, 0);
+err_resources:
+	fw_iso_resources_free(&dice->resources);
+error:
+	return err;
+}
+
+static void dice_stream_stop_packets(struct dice *dice)
+{
+	if (amdtp_out_stream_running(&dice->stream)) {
+		dice_enable_clear(dice);
+		amdtp_out_stream_stop(&dice->stream);
+	}
+}
+
+static void dice_stream_stop(struct dice *dice)
+{
+	__be32 channel;
+
+	dice_stream_stop_packets(dice);
+
+	if (!dice->resources.allocated)
+		return;
+
+	channel = cpu_to_be32((u32)-1);
+	snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST,
+			   rx_address(dice, RX_ISOCHRONOUS), &channel, 4, 0);
+
+	fw_iso_resources_free(&dice->resources);
+}
+
+static int dice_change_rate(struct dice *dice, unsigned int clock_rate)
+{
+	__be32 value;
+	int err;
+
+	INIT_COMPLETION(dice->clock_accepted);
+
+	value = cpu_to_be32(clock_rate | CLOCK_SOURCE_ARX1);
+	err = snd_fw_transaction(dice->unit, TCODE_WRITE_QUADLET_REQUEST,
+				 global_address(dice, GLOBAL_CLOCK_SELECT),
+				 &value, 4, 0);
+	if (err < 0)
+		return err;
+
+	if (!wait_for_completion_timeout(&dice->clock_accepted,
+					 msecs_to_jiffies(100)))
+		dev_warn(&dice->unit->device, "clock change timed out\n");
+
+	return 0;
+}
+
+static int dice_hw_params(struct snd_pcm_substream *substream,
+			  struct snd_pcm_hw_params *hw_params)
+{
+	struct dice *dice = substream->private_data;
+	unsigned int rate_index, mode;
+	int err;
+
+	mutex_lock(&dice->mutex);
+	dice_stream_stop(dice);
+	mutex_unlock(&dice->mutex);
+
+	err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
+					       params_buffer_bytes(hw_params));
+	if (err < 0)
+		return err;
+
+	rate_index = rate_to_index(params_rate(hw_params));
+	err = dice_change_rate(dice, rate_index << CLOCK_RATE_SHIFT);
+	if (err < 0)
+		return err;
+
+	mode = rate_index_to_mode(rate_index);
+	amdtp_out_stream_set_parameters(&dice->stream,
+					params_rate(hw_params),
+					params_channels(hw_params),
+					dice->rx_midi_ports[mode]);
+	amdtp_out_stream_set_pcm_format(&dice->stream,
+					params_format(hw_params));
+
+	return 0;
+}
+
+static int dice_hw_free(struct snd_pcm_substream *substream)
+{
+	struct dice *dice = substream->private_data;
+
+	mutex_lock(&dice->mutex);
+	dice_stream_stop(dice);
+	mutex_unlock(&dice->mutex);
+
+	return snd_pcm_lib_free_vmalloc_buffer(substream);
+}
+
+static int dice_prepare(struct snd_pcm_substream *substream)
+{
+	struct dice *dice = substream->private_data;
+	int err;
+
+	mutex_lock(&dice->mutex);
+
+	if (amdtp_out_streaming_error(&dice->stream))
+		dice_stream_stop_packets(dice);
+
+	err = dice_stream_start(dice);
+	if (err < 0) {
+		mutex_unlock(&dice->mutex);
+		return err;
+	}
+
+	mutex_unlock(&dice->mutex);
+
+	amdtp_out_stream_pcm_prepare(&dice->stream);
+
+	return 0;
+}
+
+static int dice_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct dice *dice = substream->private_data;
+	struct snd_pcm_substream *pcm;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		pcm = substream;
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		pcm = NULL;
+		break;
+	default:
+		return -EINVAL;
+	}
+	amdtp_out_stream_pcm_trigger(&dice->stream, pcm);
+
+	return 0;
+}
+
+static snd_pcm_uframes_t dice_pointer(struct snd_pcm_substream *substream)
+{
+	struct dice *dice = substream->private_data;
+
+	return amdtp_out_stream_pcm_pointer(&dice->stream);
+}
+
+static int dice_create_pcm(struct dice *dice)
+{
+	static struct snd_pcm_ops ops = {
+		.open      = dice_open,
+		.close     = dice_close,
+		.ioctl     = snd_pcm_lib_ioctl,
+		.hw_params = dice_hw_params,
+		.hw_free   = dice_hw_free,
+		.prepare   = dice_prepare,
+		.trigger   = dice_trigger,
+		.pointer   = dice_pointer,
+		.page      = snd_pcm_lib_get_vmalloc_page,
+		.mmap      = snd_pcm_lib_mmap_vmalloc,
+	};
+	struct snd_pcm *pcm;
+	int err;
+
+	err = snd_pcm_new(dice->card, "DICE", 0, 1, 0, &pcm);
+	if (err < 0)
+		return err;
+	pcm->private_data = dice;
+	strcpy(pcm->name, dice->card->shortname);
+	pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->ops = &ops;
+
+	return 0;
+}
+
+static long dice_hwdep_read(struct snd_hwdep *hwdep, char __user *buf,
+			    long count, loff_t *offset)
+{
+	struct dice *dice = hwdep->private_data;
+	DEFINE_WAIT(wait);
+	union snd_firewire_event event;
+
+	spin_lock_irq(&dice->lock);
+
+	while (!dice->dev_lock_changed && dice->notification_bits == 0) {
+		prepare_to_wait(&dice->hwdep_wait, &wait, TASK_INTERRUPTIBLE);
+		spin_unlock_irq(&dice->lock);
+		schedule();
+		finish_wait(&dice->hwdep_wait, &wait);
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+		spin_lock_irq(&dice->lock);
+	}
+
+	memset(&event, 0, sizeof(event));
+	if (dice->dev_lock_changed) {
+		event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
+		event.lock_status.status = dice->dev_lock_count > 0;
+		dice->dev_lock_changed = false;
+
+		count = min(count, (long)sizeof(event.lock_status));
+	} else {
+		event.dice_notification.type = SNDRV_FIREWIRE_EVENT_DICE_NOTIFICATION;
+		event.dice_notification.notification = dice->notification_bits;
+		dice->notification_bits = 0;
+
+		count = min(count, (long)sizeof(event.dice_notification));
+	}
+
+	spin_unlock_irq(&dice->lock);
+
+	if (copy_to_user(buf, &event, count))
+		return -EFAULT;
+
+	return count;
+}
+
+static unsigned int dice_hwdep_poll(struct snd_hwdep *hwdep, struct file *file,
+				    poll_table *wait)
+{
+	struct dice *dice = hwdep->private_data;
+	unsigned int events;
+
+	poll_wait(file, &dice->hwdep_wait, wait);
+
+	spin_lock_irq(&dice->lock);
+	if (dice->dev_lock_changed || dice->notification_bits != 0)
+		events = POLLIN | POLLRDNORM;
+	else
+		events = 0;
+	spin_unlock_irq(&dice->lock);
+
+	return events;
+}
+
+static int dice_hwdep_get_info(struct dice *dice, void __user *arg)
+{
+	struct fw_device *dev = fw_parent_device(dice->unit);
+	struct snd_firewire_get_info info;
+
+	memset(&info, 0, sizeof(info));
+	info.type = SNDRV_FIREWIRE_TYPE_DICE;
+	info.card = dev->card->index;
+	*(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
+	*(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
+	strlcpy(info.device_name, dev_name(&dev->device),
+		sizeof(info.device_name));
+
+	if (copy_to_user(arg, &info, sizeof(info)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int dice_hwdep_lock(struct dice *dice)
+{
+	int err;
+
+	spin_lock_irq(&dice->lock);
+
+	if (dice->dev_lock_count == 0) {
+		dice->dev_lock_count = -1;
+		err = 0;
+	} else {
+		err = -EBUSY;
+	}
+
+	spin_unlock_irq(&dice->lock);
+
+	return err;
+}
+
+static int dice_hwdep_unlock(struct dice *dice)
+{
+	int err;
+
+	spin_lock_irq(&dice->lock);
+
+	if (dice->dev_lock_count == -1) {
+		dice->dev_lock_count = 0;
+		err = 0;
+	} else {
+		err = -EBADFD;
+	}
+
+	spin_unlock_irq(&dice->lock);
+
+	return err;
+}
+
+static int dice_hwdep_release(struct snd_hwdep *hwdep, struct file *file)
+{
+	struct dice *dice = hwdep->private_data;
+
+	spin_lock_irq(&dice->lock);
+	if (dice->dev_lock_count == -1)
+		dice->dev_lock_count = 0;
+	spin_unlock_irq(&dice->lock);
+
+	return 0;
+}
+
+static int dice_hwdep_ioctl(struct snd_hwdep *hwdep, struct file *file,
+			    unsigned int cmd, unsigned long arg)
+{
+	struct dice *dice = hwdep->private_data;
+
+	switch (cmd) {
+	case SNDRV_FIREWIRE_IOCTL_GET_INFO:
+		return dice_hwdep_get_info(dice, (void __user *)arg);
+	case SNDRV_FIREWIRE_IOCTL_LOCK:
+		return dice_hwdep_lock(dice);
+	case SNDRV_FIREWIRE_IOCTL_UNLOCK:
+		return dice_hwdep_unlock(dice);
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
+#ifdef CONFIG_COMPAT
+static int dice_hwdep_compat_ioctl(struct snd_hwdep *hwdep, struct file *file,
+				   unsigned int cmd, unsigned long arg)
+{
+	return dice_hwdep_ioctl(hwdep, file, cmd,
+				(unsigned long)compat_ptr(arg));
+}
+#else
+#define dice_hwdep_compat_ioctl NULL
+#endif
+
+static int dice_create_hwdep(struct dice *dice)
+{
+	static const struct snd_hwdep_ops ops = {
+		.read         = dice_hwdep_read,
+		.release      = dice_hwdep_release,
+		.poll         = dice_hwdep_poll,
+		.ioctl        = dice_hwdep_ioctl,
+		.ioctl_compat = dice_hwdep_compat_ioctl,
+	};
+	struct snd_hwdep *hwdep;
+	int err;
+
+	err = snd_hwdep_new(dice->card, "DICE", 0, &hwdep);
+	if (err < 0)
+		return err;
+	strcpy(hwdep->name, "DICE");
+	hwdep->iface = SNDRV_HWDEP_IFACE_FW_DICE;
+	hwdep->ops = ops;
+	hwdep->private_data = dice;
+	hwdep->exclusive = true;
+
+	return 0;
+}
+
+static int dice_proc_read_mem(struct dice *dice, void *buffer,
+			      unsigned int offset_q, unsigned int quadlets)
+{
+	unsigned int i;
+	int err;
+
+	err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
+				 DICE_PRIVATE_SPACE + 4 * offset_q,
+				 buffer, 4 * quadlets, 0);
+	if (err < 0)
+		return err;
+
+	for (i = 0; i < quadlets; ++i)
+		be32_to_cpus(&((u32 *)buffer)[i]);
+
+	return 0;
+}
+
+static const char *str_from_array(const char *const strs[], unsigned int count,
+				  unsigned int i)
+{
+	if (i < count)
+		return strs[i];
+	else
+		return "(unknown)";
+}
+
+static void dice_proc_fixup_string(char *s, unsigned int size)
+{
+	unsigned int i;
+
+	for (i = 0; i < size; i += 4)
+		cpu_to_le32s((u32 *)(s + i));
+
+	for (i = 0; i < size - 2; ++i) {
+		if (s[i] == '\0')
+			return;
+		if (s[i] == '\\' && s[i + 1] == '\\') {
+			s[i + 2] = '\0';
+			return;
+		}
+	}
+	s[size - 1] = '\0';
+}
+
+static void dice_proc_read(struct snd_info_entry *entry,
+			   struct snd_info_buffer *buffer)
+{
+	static const char *const section_names[5] = {
+		"global", "tx", "rx", "ext_sync", "unused2"
+	};
+	static const char *const clock_sources[] = {
+		"aes1", "aes2", "aes3", "aes4", "aes", "adat", "tdif",
+		"wc", "arx1", "arx2", "arx3", "arx4", "internal"
+	};
+	static const char *const rates[] = {
+		"32000", "44100", "48000", "88200", "96000", "176400", "192000",
+		"any low", "any mid", "any high", "none"
+	};
+	struct dice *dice = entry->private_data;
+	u32 sections[ARRAY_SIZE(section_names) * 2];
+	struct {
+		u32 number;
+		u32 size;
+	} tx_rx_header;
+	union {
+		struct {
+			u32 owner_hi, owner_lo;
+			u32 notification;
+			char nick_name[NICK_NAME_SIZE];
+			u32 clock_select;
+			u32 enable;
+			u32 status;
+			u32 extended_status;
+			u32 sample_rate;
+			u32 version;
+			u32 clock_caps;
+			char clock_source_names[CLOCK_SOURCE_NAMES_SIZE];
+		} global;
+		struct {
+			u32 iso;
+			u32 number_audio;
+			u32 number_midi;
+			u32 speed;
+			char names[TX_NAMES_SIZE];
+			u32 ac3_caps;
+			u32 ac3_enable;
+		} tx;
+		struct {
+			u32 iso;
+			u32 seq_start;
+			u32 number_audio;
+			u32 number_midi;
+			char names[RX_NAMES_SIZE];
+			u32 ac3_caps;
+			u32 ac3_enable;
+		} rx;
+		struct {
+			u32 clock_source;
+			u32 locked;
+			u32 rate;
+			u32 adat_user_data;
+		} ext_sync;
+	} buf;
+	unsigned int quadlets, stream, i;
+
+	if (dice_proc_read_mem(dice, sections, 0, ARRAY_SIZE(sections)) < 0)
+		return;
+	snd_iprintf(buffer, "sections:\n");
+	for (i = 0; i < ARRAY_SIZE(section_names); ++i)
+		snd_iprintf(buffer, "  %s: offset %u, size %u\n",
+			    section_names[i],
+			    sections[i * 2], sections[i * 2 + 1]);
+
+	quadlets = min_t(u32, sections[1], sizeof(buf.global) / 4);
+	if (dice_proc_read_mem(dice, &buf.global, sections[0], quadlets) < 0)
+		return;
+	snd_iprintf(buffer, "global:\n");
+	snd_iprintf(buffer, "  owner: %04x:%04x%08x\n",
+		    buf.global.owner_hi >> 16,
+		    buf.global.owner_hi & 0xffff, buf.global.owner_lo);
+	snd_iprintf(buffer, "  notification: %08x\n", buf.global.notification);
+	dice_proc_fixup_string(buf.global.nick_name, NICK_NAME_SIZE);
+	snd_iprintf(buffer, "  nick name: %s\n", buf.global.nick_name);
+	snd_iprintf(buffer, "  clock select: %s %s\n",
+		    str_from_array(clock_sources, ARRAY_SIZE(clock_sources),
+				   buf.global.clock_select & CLOCK_SOURCE_MASK),
+		    str_from_array(rates, ARRAY_SIZE(rates),
+				   (buf.global.clock_select & CLOCK_RATE_MASK)
+				   >> CLOCK_RATE_SHIFT));
+	snd_iprintf(buffer, "  enable: %u\n", buf.global.enable);
+	snd_iprintf(buffer, "  status: %slocked %s\n",
+		    buf.global.status & STATUS_SOURCE_LOCKED ? "" : "un",
+		    str_from_array(rates, ARRAY_SIZE(rates),
+				   (buf.global.status &
+				    STATUS_NOMINAL_RATE_MASK)
+				   >> CLOCK_RATE_SHIFT));
+	snd_iprintf(buffer, "  ext status: %08x\n", buf.global.extended_status);
+	snd_iprintf(buffer, "  sample rate: %u\n", buf.global.sample_rate);
+	snd_iprintf(buffer, "  version: %u.%u.%u.%u\n",
+		    (buf.global.version >> 24) & 0xff,
+		    (buf.global.version >> 16) & 0xff,
+		    (buf.global.version >>  8) & 0xff,
+		    (buf.global.version >>  0) & 0xff);
+	if (quadlets >= 90) {
+		snd_iprintf(buffer, "  clock caps:");
+		for (i = 0; i <= 6; ++i)
+			if (buf.global.clock_caps & (1 << i))
+				snd_iprintf(buffer, " %s", rates[i]);
+		for (i = 0; i <= 12; ++i)
+			if (buf.global.clock_caps & (1 << (16 + i)))
+				snd_iprintf(buffer, " %s", clock_sources[i]);
+		snd_iprintf(buffer, "\n");
+		dice_proc_fixup_string(buf.global.clock_source_names,
+				       CLOCK_SOURCE_NAMES_SIZE);
+		snd_iprintf(buffer, "  clock source names: %s\n",
+			    buf.global.clock_source_names);
+	}
+
+	if (dice_proc_read_mem(dice, &tx_rx_header, sections[2], 2) < 0)
+		return;
+	quadlets = min_t(u32, tx_rx_header.size, sizeof(buf.tx));
+	for (stream = 0; stream < tx_rx_header.number; ++stream) {
+		if (dice_proc_read_mem(dice, &buf.tx, sections[2] + 2 +
+				       stream * tx_rx_header.size,
+				       quadlets) < 0)
+			break;
+		snd_iprintf(buffer, "tx %u:\n", stream);
+		snd_iprintf(buffer, "  iso channel: %d\n", (int)buf.tx.iso);
+		snd_iprintf(buffer, "  audio channels: %u\n",
+			    buf.tx.number_audio);
+		snd_iprintf(buffer, "  midi ports: %u\n", buf.tx.number_midi);
+		snd_iprintf(buffer, "  speed: S%u\n", 100u << buf.tx.speed);
+		if (quadlets >= 68) {
+			dice_proc_fixup_string(buf.tx.names, TX_NAMES_SIZE);
+			snd_iprintf(buffer, "  names: %s\n", buf.tx.names);
+		}
+		if (quadlets >= 70) {
+			snd_iprintf(buffer, "  ac3 caps: %08x\n",
+				    buf.tx.ac3_caps);
+			snd_iprintf(buffer, "  ac3 enable: %08x\n",
+				    buf.tx.ac3_enable);
+		}
+	}
+
+	if (dice_proc_read_mem(dice, &tx_rx_header, sections[4], 2) < 0)
+		return;
+	quadlets = min_t(u32, tx_rx_header.size, sizeof(buf.rx));
+	for (stream = 0; stream < tx_rx_header.number; ++stream) {
+		if (dice_proc_read_mem(dice, &buf.rx, sections[4] + 2 +
+				       stream * tx_rx_header.size,
+				       quadlets) < 0)
+			break;
+		snd_iprintf(buffer, "rx %u:\n", stream);
+		snd_iprintf(buffer, "  iso channel: %d\n", (int)buf.rx.iso);
+		snd_iprintf(buffer, "  sequence start: %u\n", buf.rx.seq_start);
+		snd_iprintf(buffer, "  audio channels: %u\n",
+			    buf.rx.number_audio);
+		snd_iprintf(buffer, "  midi ports: %u\n", buf.rx.number_midi);
+		if (quadlets >= 68) {
+			dice_proc_fixup_string(buf.rx.names, RX_NAMES_SIZE);
+			snd_iprintf(buffer, "  names: %s\n", buf.rx.names);
+		}
+		if (quadlets >= 70) {
+			snd_iprintf(buffer, "  ac3 caps: %08x\n",
+				    buf.rx.ac3_caps);
+			snd_iprintf(buffer, "  ac3 enable: %08x\n",
+				    buf.rx.ac3_enable);
+		}
+	}
+
+	quadlets = min_t(u32, sections[7], sizeof(buf.ext_sync) / 4);
+	if (quadlets >= 4) {
+		if (dice_proc_read_mem(dice, &buf.ext_sync,
+				       sections[6], 4) < 0)
+			return;
+		snd_iprintf(buffer, "ext status:\n");
+		snd_iprintf(buffer, "  clock source: %s\n",
+			    str_from_array(clock_sources,
+					   ARRAY_SIZE(clock_sources),
+					   buf.ext_sync.clock_source));
+		snd_iprintf(buffer, "  locked: %u\n", buf.ext_sync.locked);
+		snd_iprintf(buffer, "  rate: %s\n",
+			    str_from_array(rates, ARRAY_SIZE(rates),
+					   buf.ext_sync.rate));
+		snd_iprintf(buffer, "  adat user data: ");
+		if (buf.ext_sync.adat_user_data & ADAT_USER_DATA_NO_DATA)
+			snd_iprintf(buffer, "-\n");
+		else
+			snd_iprintf(buffer, "%x\n",
+				    buf.ext_sync.adat_user_data);
+	}
+}
+
+static void dice_create_proc(struct dice *dice)
+{
+	struct snd_info_entry *entry;
+
+	if (!snd_card_proc_new(dice->card, "dice", &entry))
+		snd_info_set_text_ops(entry, dice, dice_proc_read);
+}
+
+static void dice_card_free(struct snd_card *card)
+{
+	struct dice *dice = card->private_data;
+
+	amdtp_out_stream_destroy(&dice->stream);
+	fw_core_remove_address_handler(&dice->notification_handler);
+	mutex_destroy(&dice->mutex);
+}
+
+#define OUI_WEISS		0x001c6a
+
+#define DICE_CATEGORY_ID	0x04
+#define WEISS_CATEGORY_ID	0x00
+
+static int dice_interface_check(struct fw_unit *unit)
+{
+	static const int min_values[10] = {
+		10, 0x64 / 4,
+		10, 0x18 / 4,
+		10, 0x18 / 4,
+		0, 0,
+		0, 0,
+	};
+	struct fw_device *device = fw_parent_device(unit);
+	struct fw_csr_iterator it;
+	int key, value, vendor = -1, model = -1, err;
+	unsigned int category, i;
+	__be32 pointers[ARRAY_SIZE(min_values)];
+	__be32 tx_data[4];
+	__be32 version;
+
+	/*
+	 * Check that GUID and unit directory are constructed according to DICE
+	 * rules, i.e., that the specifier ID is the GUID's OUI, and that the
+	 * GUID chip ID consists of the 8-bit category ID, the 10-bit product
+	 * ID, and a 22-bit serial number.
+	 */
+	fw_csr_iterator_init(&it, unit->directory);
+	while (fw_csr_iterator_next(&it, &key, &value)) {
+		switch (key) {
+		case CSR_SPECIFIER_ID:
+			vendor = value;
+			break;
+		case CSR_MODEL:
+			model = value;
+			break;
+		}
+	}
+	if (vendor == OUI_WEISS)
+		category = WEISS_CATEGORY_ID;
+	else
+		category = DICE_CATEGORY_ID;
+	if (device->config_rom[3] != ((vendor << 8) | category) ||
+	    device->config_rom[4] >> 22 != model)
+		return -ENODEV;
+
+	/*
+	 * Check that the sub address spaces exist and are located inside the
+	 * private address space.  The minimum values are chosen so that all
+	 * minimally required registers are included.
+	 */
+	err = snd_fw_transaction(unit, TCODE_READ_BLOCK_REQUEST,
+				 DICE_PRIVATE_SPACE,
+				 pointers, sizeof(pointers), 0);
+	if (err < 0)
+		return -ENODEV;
+	for (i = 0; i < ARRAY_SIZE(pointers); ++i) {
+		value = be32_to_cpu(pointers[i]);
+		if (value < min_values[i] || value >= 0x40000)
+			return -ENODEV;
+	}
+
+	/* We support playback only. Let capture devices be handled by FFADO. */
+	err = snd_fw_transaction(unit, TCODE_READ_BLOCK_REQUEST,
+				 DICE_PRIVATE_SPACE +
+				 be32_to_cpu(pointers[2]) * 4,
+				 tx_data, sizeof(tx_data), 0);
+	if (err < 0 || (tx_data[0] && tx_data[3]))
+		return -ENODEV;
+
+	/*
+	 * Check that the implemented DICE driver specification major version
+	 * number matches.
+	 */
+	err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST,
+				 DICE_PRIVATE_SPACE +
+				 be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION,
+				 &version, 4, 0);
+	if (err < 0)
+		return -ENODEV;
+	if ((version & cpu_to_be32(0xff000000)) != cpu_to_be32(0x01000000)) {
+		dev_err(&unit->device,
+			"unknown DICE version: 0x%08x\n", be32_to_cpu(version));
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int highest_supported_mode_rate(struct dice *dice, unsigned int mode)
+{
+	int i;
+
+	for (i = ARRAY_SIZE(dice_rates) - 1; i >= 0; --i)
+		if ((dice->clock_caps & (1 << i)) &&
+		    rate_index_to_mode(i) == mode)
+			return i;
+
+	return -1;
+}
+
+static int dice_read_mode_params(struct dice *dice, unsigned int mode)
+{
+	__be32 values[2];
+	int rate_index, err;
+
+	rate_index = highest_supported_mode_rate(dice, mode);
+	if (rate_index < 0) {
+		dice->rx_channels[mode] = 0;
+		dice->rx_midi_ports[mode] = 0;
+		return 0;
+	}
+
+	err = dice_change_rate(dice, rate_index << CLOCK_RATE_SHIFT);
+	if (err < 0)
+		return err;
+
+	err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
+				 rx_address(dice, RX_NUMBER_AUDIO),
+				 values, 2 * 4, 0);
+	if (err < 0)
+		return err;
+
+	dice->rx_channels[mode]   = be32_to_cpu(values[0]);
+	dice->rx_midi_ports[mode] = be32_to_cpu(values[1]);
+
+	return 0;
+}
+
+static int dice_read_params(struct dice *dice)
+{
+	__be32 pointers[6];
+	__be32 value;
+	int mode, err;
+
+	err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
+				 DICE_PRIVATE_SPACE,
+				 pointers, sizeof(pointers), 0);
+	if (err < 0)
+		return err;
+
+	dice->global_offset = be32_to_cpu(pointers[0]) * 4;
+	dice->rx_offset = be32_to_cpu(pointers[4]) * 4;
+
+	/* some very old firmwares don't tell about their clock support */
+	if (be32_to_cpu(pointers[1]) * 4 >= GLOBAL_CLOCK_CAPABILITIES + 4) {
+		err = snd_fw_transaction(
+				dice->unit, TCODE_READ_QUADLET_REQUEST,
+				global_address(dice, GLOBAL_CLOCK_CAPABILITIES),
+				&value, 4, 0);
+		if (err < 0)
+			return err;
+		dice->clock_caps = be32_to_cpu(value);
+	} else {
+		/* this should be supported by any device */
+		dice->clock_caps = CLOCK_CAP_RATE_44100 |
+				   CLOCK_CAP_RATE_48000 |
+				   CLOCK_CAP_SOURCE_ARX1 |
+				   CLOCK_CAP_SOURCE_INTERNAL;
+	}
+
+	for (mode = 2; mode >= 0; --mode) {
+		err = dice_read_mode_params(dice, mode);
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+static void dice_card_strings(struct dice *dice)
+{
+	struct snd_card *card = dice->card;
+	struct fw_device *dev = fw_parent_device(dice->unit);
+	char vendor[32], model[32];
+	unsigned int i;
+	int err;
+
+	strcpy(card->driver, "DICE");
+
+	strcpy(card->shortname, "DICE");
+	BUILD_BUG_ON(NICK_NAME_SIZE < sizeof(card->shortname));
+	err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
+				 global_address(dice, GLOBAL_NICK_NAME),
+				 card->shortname, sizeof(card->shortname), 0);
+	if (err >= 0) {
+		/* DICE strings are returned in "always-wrong" endianness */
+		BUILD_BUG_ON(sizeof(card->shortname) % 4 != 0);
+		for (i = 0; i < sizeof(card->shortname); i += 4)
+			swab32s((u32 *)&card->shortname[i]);
+		card->shortname[sizeof(card->shortname) - 1] = '\0';
+	}
+
+	strcpy(vendor, "?");
+	fw_csr_string(dev->config_rom + 5, CSR_VENDOR, vendor, sizeof(vendor));
+	strcpy(model, "?");
+	fw_csr_string(dice->unit->directory, CSR_MODEL, model, sizeof(model));
+	snprintf(card->longname, sizeof(card->longname),
+		 "%s %s (serial %u) at %s, S%d",
+		 vendor, model, dev->config_rom[4] & 0x3fffff,
+		 dev_name(&dice->unit->device), 100 << dev->max_speed);
+
+	strcpy(card->mixername, "DICE");
+}
+
+static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
+{
+	struct snd_card *card;
+	struct dice *dice;
+	__be32 clock_sel;
+	int err;
+
+	err = dice_interface_check(unit);
+	if (err < 0)
+		return err;
+
+	err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*dice), &card);
+	if (err < 0)
+		return err;
+	snd_card_set_dev(card, &unit->device);
+
+	dice = card->private_data;
+	dice->card = card;
+	spin_lock_init(&dice->lock);
+	mutex_init(&dice->mutex);
+	dice->unit = unit;
+	init_completion(&dice->clock_accepted);
+	init_waitqueue_head(&dice->hwdep_wait);
+
+	dice->notification_handler.length = 4;
+	dice->notification_handler.address_callback = dice_notification;
+	dice->notification_handler.callback_data = dice;
+	err = fw_core_add_address_handler(&dice->notification_handler,
+					  &fw_high_memory_region);
+	if (err < 0)
+		goto err_mutex;
+
+	err = dice_owner_set(dice);
+	if (err < 0)
+		goto err_notification_handler;
+
+	err = dice_read_params(dice);
+	if (err < 0)
+		goto err_owner;
+
+	err = fw_iso_resources_init(&dice->resources, unit);
+	if (err < 0)
+		goto err_owner;
+	dice->resources.channels_mask = 0x00000000ffffffffuLL;
+
+	err = amdtp_out_stream_init(&dice->stream, unit,
+				    CIP_BLOCKING | CIP_HI_DUALWIRE);
+	if (err < 0)
+		goto err_resources;
+
+	card->private_free = dice_card_free;
+
+	dice_card_strings(dice);
+
+	err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST,
+				 global_address(dice, GLOBAL_CLOCK_SELECT),
+				 &clock_sel, 4, 0);
+	if (err < 0)
+		goto error;
+	clock_sel &= cpu_to_be32(~CLOCK_SOURCE_MASK);
+	clock_sel |= cpu_to_be32(CLOCK_SOURCE_ARX1);
+	err = snd_fw_transaction(unit, TCODE_WRITE_QUADLET_REQUEST,
+				 global_address(dice, GLOBAL_CLOCK_SELECT),
+				 &clock_sel, 4, 0);
+	if (err < 0)
+		goto error;
+
+	err = dice_create_pcm(dice);
+	if (err < 0)
+		goto error;
+
+	err = dice_create_hwdep(dice);
+	if (err < 0)
+		goto error;
+
+	dice_create_proc(dice);
+
+	err = snd_card_register(card);
+	if (err < 0)
+		goto error;
+
+	dev_set_drvdata(&unit->device, dice);
+
+	return 0;
+
+err_resources:
+	fw_iso_resources_destroy(&dice->resources);
+err_owner:
+	dice_owner_clear(dice);
+err_notification_handler:
+	fw_core_remove_address_handler(&dice->notification_handler);
+err_mutex:
+	mutex_destroy(&dice->mutex);
+error:
+	snd_card_free(card);
+	return err;
+}
+
+static void dice_remove(struct fw_unit *unit)
+{
+	struct dice *dice = dev_get_drvdata(&unit->device);
+
+	amdtp_out_stream_pcm_abort(&dice->stream);
+
+	snd_card_disconnect(dice->card);
+
+	mutex_lock(&dice->mutex);
+
+	dice_stream_stop(dice);
+	dice_owner_clear(dice);
+
+	mutex_unlock(&dice->mutex);
+
+	snd_card_free_when_closed(dice->card);
+}
+
+static void dice_bus_reset(struct fw_unit *unit)
+{
+	struct dice *dice = dev_get_drvdata(&unit->device);
+
+	/*
+	 * On a bus reset, the DICE firmware disables streaming and then goes
+	 * off contemplating its own navel for hundreds of milliseconds before
+	 * it can react to any of our attempts to reenable streaming.  This
+	 * means that we lose synchronization anyway, so we force our streams
+	 * to stop so that the application can restart them in an orderly
+	 * manner.
+	 */
+	amdtp_out_stream_pcm_abort(&dice->stream);
+
+	mutex_lock(&dice->mutex);
+
+	dice->global_enabled = false;
+	dice_stream_stop_packets(dice);
+
+	dice_owner_update(dice);
+
+	fw_iso_resources_update(&dice->resources);
+
+	mutex_unlock(&dice->mutex);
+}
+
+#define DICE_INTERFACE	0x000001
+
+static const struct ieee1394_device_id dice_id_table[] = {
+	{
+		.match_flags = IEEE1394_MATCH_VERSION,
+		.version     = DICE_INTERFACE,
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(ieee1394, dice_id_table);
+
+static struct fw_driver dice_driver = {
+	.driver   = {
+		.owner	= THIS_MODULE,
+		.name	= KBUILD_MODNAME,
+		.bus	= &fw_bus_type,
+	},
+	.probe    = dice_probe,
+	.update   = dice_bus_reset,
+	.remove   = dice_remove,
+	.id_table = dice_id_table,
+};
+
+static int __init alsa_dice_init(void)
+{
+	return driver_register(&dice_driver.driver);
+}
+
+static void __exit alsa_dice_exit(void)
+{
+	driver_unregister(&dice_driver.driver);
+}
+
+module_init(alsa_dice_init);
+module_exit(alsa_dice_exit);
diff --git a/sound/firewire/fcp.c b/sound/firewire/fcp.c
index ec578b5..860c080 100644
--- a/sound/firewire/fcp.c
+++ b/sound/firewire/fcp.c
@@ -90,7 +90,7 @@
 					  : TCODE_WRITE_BLOCK_REQUEST;
 		ret = snd_fw_transaction(t.unit, tcode,
 					 CSR_REGISTER_BASE + CSR_FCP_COMMAND,
-					 (void *)command, command_size);
+					 (void *)command, command_size, 0);
 		if (ret < 0)
 			break;
 
diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c
index 58a5afe..fd42e6b 100644
--- a/sound/firewire/isight.c
+++ b/sound/firewire/isight.c
@@ -217,7 +217,7 @@
 
 static int isight_connect(struct isight *isight)
 {
-	int ch, err, rcode, errors = 0;
+	int ch, err;
 	__be32 value;
 
 retry_after_bus_reset:
@@ -230,27 +230,19 @@
 	}
 
 	value = cpu_to_be32(ch | (isight->device->max_speed << SPEED_SHIFT));
-	for (;;) {
-		rcode = fw_run_transaction(
-				isight->device->card,
-				TCODE_WRITE_QUADLET_REQUEST,
-				isight->device->node_id,
-				isight->resources.generation,
-				isight->device->max_speed,
-				isight->audio_base + REG_ISO_TX_CONFIG,
-				&value, 4);
-		if (rcode == RCODE_COMPLETE) {
-			return 0;
-		} else if (rcode == RCODE_GENERATION) {
-			fw_iso_resources_free(&isight->resources);
-			goto retry_after_bus_reset;
-		} else if (rcode_is_permanent_error(rcode) || ++errors >= 3) {
-			err = -EIO;
-			goto err_resources;
-		}
-		msleep(5);
+	err = snd_fw_transaction(isight->unit, TCODE_WRITE_QUADLET_REQUEST,
+				 isight->audio_base + REG_ISO_TX_CONFIG,
+				 &value, 4, FW_FIXED_GENERATION |
+				 isight->resources.generation);
+	if (err == -EAGAIN) {
+		fw_iso_resources_free(&isight->resources);
+		goto retry_after_bus_reset;
+	} else if (err < 0) {
+		goto err_resources;
 	}
 
+	return 0;
+
 err_resources:
 	fw_iso_resources_free(&isight->resources);
 error:
@@ -315,17 +307,19 @@
 static int reg_read(struct isight *isight, int offset, __be32 *value)
 {
 	return snd_fw_transaction(isight->unit, TCODE_READ_QUADLET_REQUEST,
-				  isight->audio_base + offset, value, 4);
+				  isight->audio_base + offset, value, 4, 0);
 }
 
 static int reg_write(struct isight *isight, int offset, __be32 value)
 {
 	return snd_fw_transaction(isight->unit, TCODE_WRITE_QUADLET_REQUEST,
-				  isight->audio_base + offset, &value, 4);
+				  isight->audio_base + offset, &value, 4, 0);
 }
 
 static void isight_stop_streaming(struct isight *isight)
 {
+	__be32 value;
+
 	if (!isight->context)
 		return;
 
@@ -333,7 +327,10 @@
 	fw_iso_context_destroy(isight->context);
 	isight->context = NULL;
 	fw_iso_resources_free(&isight->resources);
-	reg_write(isight, REG_AUDIO_ENABLE, 0);
+	value = 0;
+	snd_fw_transaction(isight->unit, TCODE_WRITE_QUADLET_REQUEST,
+			   isight->audio_base + REG_AUDIO_ENABLE,
+			   &value, 4, FW_QUIET);
 }
 
 static int isight_hw_free(struct snd_pcm_substream *substream)
diff --git a/sound/firewire/lib.c b/sound/firewire/lib.c
index 14eb414..7409edb 100644
--- a/sound/firewire/lib.c
+++ b/sound/firewire/lib.c
@@ -11,7 +11,7 @@
 #include <linux/module.h>
 #include "lib.h"
 
-#define ERROR_RETRY_DELAY_MS	5
+#define ERROR_RETRY_DELAY_MS	20
 
 /**
  * snd_fw_transaction - send a request and wait for its completion
@@ -20,6 +20,9 @@
  * @offset: the address in the target's address space
  * @buffer: input/output data
  * @length: length of @buffer
+ * @flags: use %FW_FIXED_GENERATION and add the generation value to attempt the
+ *         request only in that generation; use %FW_QUIET to suppress error
+ *         messages
  *
  * Submits an asynchronous request to the target device, and waits for the
  * response.  The node ID and the current generation are derived from @unit.
@@ -27,14 +30,18 @@
  * Returns zero on success, or a negative error code.
  */
 int snd_fw_transaction(struct fw_unit *unit, int tcode,
-		       u64 offset, void *buffer, size_t length)
+		       u64 offset, void *buffer, size_t length,
+		       unsigned int flags)
 {
 	struct fw_device *device = fw_parent_device(unit);
 	int generation, rcode, tries = 0;
 
+	generation = flags & FW_GENERATION_MASK;
 	for (;;) {
-		generation = device->generation;
-		smp_rmb(); /* node_id vs. generation */
+		if (!(flags & FW_FIXED_GENERATION)) {
+			generation = device->generation;
+			smp_rmb(); /* node_id vs. generation */
+		}
 		rcode = fw_run_transaction(device->card, tcode,
 					   device->node_id, generation,
 					   device->max_speed, offset,
@@ -43,9 +50,14 @@
 		if (rcode == RCODE_COMPLETE)
 			return 0;
 
+		if (rcode == RCODE_GENERATION && (flags & FW_FIXED_GENERATION))
+			return -EAGAIN;
+
 		if (rcode_is_permanent_error(rcode) || ++tries >= 3) {
-			dev_err(&unit->device, "transaction failed: %s\n",
-				fw_rcode_string(rcode));
+			if (!(flags & FW_QUIET))
+				dev_err(&unit->device,
+					"transaction failed: %s\n",
+					fw_rcode_string(rcode));
 			return -EIO;
 		}
 
diff --git a/sound/firewire/lib.h b/sound/firewire/lib.h
index aef3014..02cfabc 100644
--- a/sound/firewire/lib.h
+++ b/sound/firewire/lib.h
@@ -6,8 +6,13 @@
 
 struct fw_unit;
 
+#define FW_GENERATION_MASK	0x00ff
+#define FW_FIXED_GENERATION	0x0100
+#define FW_QUIET		0x0200
+
 int snd_fw_transaction(struct fw_unit *unit, int tcode,
-		       u64 offset, void *buffer, size_t length);
+		       u64 offset, void *buffer, size_t length,
+		       unsigned int flags);
 
 /* returns true if retrying the transaction would not make sense */
 static inline bool rcode_is_permanent_error(int rcode)
diff --git a/sound/firewire/scs1x.c b/sound/firewire/scs1x.c
index 505fc81..858023c 100644
--- a/sound/firewire/scs1x.c
+++ b/sound/firewire/scs1x.c
@@ -369,7 +369,7 @@
 	data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) |
 			   scs->hss_handler.offset);
 	err = snd_fw_transaction(scs->unit, TCODE_WRITE_BLOCK_REQUEST,
-				 HSS1394_ADDRESS, &data, 8);
+				 HSS1394_ADDRESS, &data, 8, 0);
 	if (err < 0)
 		dev_err(&scs->unit->device, "HSS1394 communication failed\n");
 
@@ -455,12 +455,16 @@
 static void scs_update(struct fw_unit *unit)
 {
 	struct scs *scs = dev_get_drvdata(&unit->device);
+	int generation;
 	__be64 data;
 
 	data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) |
 			   scs->hss_handler.offset);
+	generation = fw_parent_device(unit)->generation;
+	smp_rmb(); /* node_id vs. generation */
 	snd_fw_transaction(scs->unit, TCODE_WRITE_BLOCK_REQUEST,
-			   HSS1394_ADDRESS, &data, 8);
+			   HSS1394_ADDRESS, &data, 8,
+			   FW_FIXED_GENERATION | generation);
 }
 
 static void scs_remove(struct fw_unit *unit)
diff --git a/sound/firewire/speakers.c b/sound/firewire/speakers.c
index fe9e6e2..cc8bc3a 100644
--- a/sound/firewire/speakers.c
+++ b/sound/firewire/speakers.c
@@ -52,7 +52,6 @@
 	struct mutex mutex;
 	struct cmp_connection connection;
 	struct amdtp_out_stream stream;
-	bool stream_running;
 	bool mute;
 	s16 volume[6];
 	s16 volume_min;
@@ -188,10 +187,9 @@
 
 static void fwspk_stop_stream(struct fwspk *fwspk)
 {
-	if (fwspk->stream_running) {
+	if (amdtp_out_stream_running(&fwspk->stream)) {
 		amdtp_out_stream_stop(&fwspk->stream);
 		cmp_connection_break(&fwspk->connection);
-		fwspk->stream_running = false;
 	}
 }
 
@@ -246,8 +244,10 @@
 	if (err < 0)
 		goto error;
 
-	amdtp_out_stream_set_rate(&fwspk->stream, params_rate(hw_params));
-	amdtp_out_stream_set_pcm(&fwspk->stream, params_channels(hw_params));
+	amdtp_out_stream_set_parameters(&fwspk->stream,
+					params_rate(hw_params),
+					params_channels(hw_params),
+					0);
 
 	amdtp_out_stream_set_pcm_format(&fwspk->stream,
 					params_format(hw_params));
@@ -285,7 +285,7 @@
 	if (amdtp_out_streaming_error(&fwspk->stream))
 		fwspk_stop_stream(fwspk);
 
-	if (!fwspk->stream_running) {
+	if (!amdtp_out_stream_running(&fwspk->stream)) {
 		err = cmp_connection_establish(&fwspk->connection,
 			amdtp_out_stream_get_max_payload(&fwspk->stream));
 		if (err < 0)
@@ -296,8 +296,6 @@
 					fwspk->connection.speed);
 		if (err < 0)
 			goto err_connection;
-
-		fwspk->stream_running = true;
 	}
 
 	mutex_unlock(&fwspk->mutex);
@@ -647,7 +645,7 @@
 	int err;
 
 	err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST,
-				 OXFORD_FIRMWARE_ID_ADDRESS, &data, 4);
+				 OXFORD_FIRMWARE_ID_ADDRESS, &data, 4, 0);
 	return err >= 0 ? be32_to_cpu(data) : 0;
 }
 
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
index 5bf4fca..15ae025 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -60,7 +60,7 @@
 
 	printk(KERN_DEBUG "AK4114 REG DUMP:\n");
 	for (i = 0; i < 0x20; i++)
-		printk(KERN_DEBUG "reg[%02x] = %02x (%02x)\n", i, reg_read(ak4114, i), i < sizeof(ak4114->regmap) ? ak4114->regmap[i] : 0);
+		printk(KERN_DEBUG "reg[%02x] = %02x (%02x)\n", i, reg_read(ak4114, i), i < ARRAY_SIZE(ak4114->regmap) ? ak4114->regmap[i] : 0);
 }
 #endif
 
@@ -81,7 +81,7 @@
 
 int snd_ak4114_create(struct snd_card *card,
 		      ak4114_read_t *read, ak4114_write_t *write,
-		      const unsigned char pgm[7], const unsigned char txcsb[5],
+		      const unsigned char pgm[6], const unsigned char txcsb[5],
 		      void *private_data, struct ak4114 **r_ak4114)
 {
 	struct ak4114 *chip;
@@ -101,7 +101,7 @@
 	chip->private_data = private_data;
 	INIT_DELAYED_WORK(&chip->work, ak4114_stats);
 
-	for (reg = 0; reg < 7; reg++)
+	for (reg = 0; reg < 6; reg++)
 		chip->regmap[reg] = pgm[reg];
 	for (reg = 0; reg < 5; reg++)
 		chip->txcsb[reg] = txcsb[reg];
@@ -142,7 +142,7 @@
 	/* release reset, but leave powerdown */
 	reg_write(chip, AK4114_REG_PWRDN, (old | AK4114_RST) & ~AK4114_PWN);
 	udelay(200);
-	for (reg = 1; reg < 7; reg++)
+	for (reg = 1; reg < 6; reg++)
 		reg_write(chip, reg, chip->regmap[reg]);
 	for (reg = 0; reg < 5; reg++)
 		reg_write(chip, reg + AK4114_REG_TXCSB0, chip->txcsb[reg]);
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index ed726d1..f3735e6 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -583,7 +583,7 @@
 	if (idx >= num_names)
 		return -EINVAL;
 	input_names = ak->adc_info[mixer_ch].input_names;
-	strncpy(uinfo->value.enumerated.name, input_names[idx],
+	strlcpy(uinfo->value.enumerated.name, input_names[idx],
 		sizeof(uinfo->value.enumerated.name));
 	return 0;
 }
diff --git a/sound/isa/cmi8328.c b/sound/isa/cmi8328.c
index f84f073..ab6b2dc 100644
--- a/sound/isa/cmi8328.c
+++ b/sound/isa/cmi8328.c
@@ -126,6 +126,7 @@
 	outb(val, port + 3);	/* yes, value goes to the same port as index */
 }
 
+#ifdef CONFIG_PM
 static void snd_cmi8328_cfg_save(u16 port, u8 cfg[])
 {
 	cfg[0] = snd_cmi8328_cfg_read(port, CFG1);
@@ -139,6 +140,7 @@
 	snd_cmi8328_cfg_write(port, CFG2, cfg[1]);
 	snd_cmi8328_cfg_write(port, CFG3, cfg[2]);
 }
+#endif /* CONFIG_PM */
 
 static int snd_cmi8328_mixer(struct snd_wss *chip)
 {
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index c1aa21e..48da227 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -208,6 +208,7 @@
 	switch (cmd) {
 		/* get information */
 	case SNDRV_SB_CSP_IOCTL_INFO:
+		memset(&info, 0, sizeof(info));
 		*info.codec_name = *p->codec_name;
 		info.func_nr = p->func_nr;
 		info.acc_format = p->acc_format;
diff --git a/sound/mips/ad1843.c b/sound/mips/ad1843.c
index c624510..5869075 100644
--- a/sound/mips/ad1843.c
+++ b/sound/mips/ad1843.c
@@ -276,7 +276,7 @@
 		if (reg == -1)
 			reg = fp->reg;
 		else
-			BUG_ON(reg != fp->reg);
+			WARN_ON(reg != fp->reg);
 		m = ((1 << fp->nbits) - 1) << fp->lo_bit;
 		mask |= m;
 		bits |= (value << fp->lo_bit) & m;
diff --git a/sound/oss/sb_ess.c b/sound/oss/sb_ess.c
index c0be085..0e7254b 100644
--- a/sound/oss/sb_ess.c
+++ b/sound/oss/sb_ess.c
@@ -1544,7 +1544,7 @@
 		return 1;
 	default:
 		return 0;
-	};
+	}
 };
 
 #ifdef FKS_LOGGING
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index d2b9d61..b680d03 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -739,7 +739,7 @@
 	reg = ad1889_readw(chip, AD_DS_WADA);
 	snd_iprintf(buffer, "Right: %s, -%d dB\n",
 			(reg & AD_DS_WADA_RWAM) ? "mute" : "unmute",
-			((reg & AD_DS_WADA_RWAA) >> 8) * 3);
+			(reg & AD_DS_WADA_RWAA) * 3);
 	
 	reg = ad1889_readw(chip, AD_DS_WAS);
 	snd_iprintf(buffer, "Wave samplerate: %u Hz\n", reg);
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 3dfa12b..c6835a3 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -855,7 +855,6 @@
 static void snd_ali_update_ptr(struct snd_ali *codec, int channel)
 {
 	struct snd_ali_voice *pvoice;
-	struct snd_pcm_runtime *runtime;
 	struct snd_ali_channel_control *pchregs;
 	unsigned int old, mask;
 #ifdef ALI_DEBUG
@@ -872,7 +871,6 @@
 		return;
 
 	pvoice = &codec->synth.voices[channel];
-	runtime = pvoice->substream->runtime;
 
 	udelay(100);
 	spin_lock(&codec->reg_lock);
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
index dc632cd..5f2acd3 100644
--- a/sound/pci/asihpi/asihpi.c
+++ b/sound/pci/asihpi/asihpi.c
@@ -1913,6 +1913,7 @@
 	struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol);
 	*/
 	u32 h_control = kcontrol->private_value;
+	unsigned int idx;
 	u16 band;
 	u16 tuner_bands[HPI_TUNER_BAND_LAST];
 	u32 num_bands = 0;
@@ -1920,7 +1921,10 @@
 	num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands,
 			HPI_TUNER_BAND_LAST);
 
-	band = tuner_bands[ucontrol->value.enumerated.item[0]];
+	idx = ucontrol->value.enumerated.item[0];
+	if (idx >= ARRAY_SIZE(tuner_bands))
+		idx = ARRAY_SIZE(tuner_bands) - 1;
+	band = tuner_bands[idx];
 	hpi_handle_error(hpi_tuner_set_band(h_control, band));
 
 	return 1;
@@ -2383,7 +2387,8 @@
 	struct snd_card_asihpi *asihpi =
 			(struct snd_card_asihpi *)(kcontrol->private_data);
 	struct clk_cache *clkcache = &asihpi->cc;
-	int change, item;
+	unsigned int item;
+	int change;
 	u32 h_control = kcontrol->private_value;
 
 	change = 1;
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
index b46dc9b..9fb03b4 100644
--- a/sound/pci/au88x0/au88x0_pcm.c
+++ b/sound/pci/au88x0/au88x0_pcm.c
@@ -671,7 +671,7 @@
 			return err;
 		break;
 #endif
-	};
+	}
 
 	if (VORTEX_PCM_TYPE(pcm) == VORTEX_PCM_SPDIF) {
 		for (i = 0; i < ARRAY_SIZE(snd_vortex_mixer_spdif); i++) {
diff --git a/sound/pci/au88x0/au88x0_synth.c b/sound/pci/au88x0/au88x0_synth.c
index 8bef473..922a84b 100644
--- a/sound/pci/au88x0/au88x0_synth.c
+++ b/sound/pci/au88x0/au88x0_synth.c
@@ -219,7 +219,6 @@
 		*/
 		hwwrite(vortex->mmio, WT_RUN(wt), val);
 		return 0xc;
-		break;
 	case 1:		/* param 0 */
 		/*
 		printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
@@ -227,7 +226,6 @@
 		*/
 		hwwrite(vortex->mmio, WT_PARM(wt, 0), val);
 		return 0xc;
-		break;
 	case 2:		/* param 1 */
 		/*
 		printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
@@ -235,7 +233,6 @@
 		*/
 		hwwrite(vortex->mmio, WT_PARM(wt, 1), val);
 		return 0xc;
-		break;
 	case 3:		/* param 2 */
 		/*
 		printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
@@ -243,7 +240,6 @@
 		*/
 		hwwrite(vortex->mmio, WT_PARM(wt, 2), val);
 		return 0xc;
-		break;
 	case 4:		/* param 3 */
 		/*
 		printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
@@ -251,7 +247,6 @@
 		*/
 		hwwrite(vortex->mmio, WT_PARM(wt, 3), val);
 		return 0xc;
-		break;
 	case 6:		/* mute */
 		/*
 		printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
@@ -259,20 +254,17 @@
 		*/
 		hwwrite(vortex->mmio, WT_MUTE(wt), val);
 		return 0xc;
-		break;
 	case 0xb:
-		{		/* delay */
-			/*
-			printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
-			       WT_DELAY(wt,0), (int)val);
-			*/
-			hwwrite(vortex->mmio, WT_DELAY(wt, 3), val);
-			hwwrite(vortex->mmio, WT_DELAY(wt, 2), val);
-			hwwrite(vortex->mmio, WT_DELAY(wt, 1), val);
-			hwwrite(vortex->mmio, WT_DELAY(wt, 0), val);
-			return 0xc;
-		}
-		break;
+			/* delay */
+		/*
+		printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n",
+		       WT_DELAY(wt,0), (int)val);
+		*/
+		hwwrite(vortex->mmio, WT_DELAY(wt, 3), val);
+		hwwrite(vortex->mmio, WT_DELAY(wt, 2), val);
+		hwwrite(vortex->mmio, WT_DELAY(wt, 1), val);
+		hwwrite(vortex->mmio, WT_DELAY(wt, 0), val);
+		return 0xc;
 		/* Global WT block parameters */
 	case 5:		/* sramp */
 		ecx = WT_SRAMP(wt);
@@ -291,7 +283,6 @@
 		break;
 	default:
 		return 0;
-		break;
 	}
 	/*
 	printk(KERN_DEBUG "vortex: WT SetReg(0x%x) = 0x%08x\n", ecx, (int)val);
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index c8e1216..1aef712 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -715,14 +715,14 @@
 	const struct snd_azf3328 *chip = ac97->private_data;
 	unsigned short reg_azf = snd_azf3328_mixer_ac97_map_reg_idx(reg_ac97);
 	unsigned short reg_val = 0;
-	bool unsupported = 0;
+	bool unsupported = false;
 
 	snd_azf3328_dbgmixer(
 		"snd_azf3328_mixer_ac97_read reg_ac97 %u\n",
 			reg_ac97
 	);
 	if (reg_azf & AZF_AC97_REG_UNSUPPORTED)
-		unsupported = 1;
+		unsupported = true;
 	else {
 		if (reg_azf & AZF_AC97_REG_REAL_IO_READ)
 			reg_val = snd_azf3328_mixer_inw(chip,
@@ -759,7 +759,7 @@
 				reg_val = azf_emulated_ac97_vendor_id & 0xffff;
 				break;
 			default:
-				unsupported = 1;
+				unsupported = true;
 				break;
 			}
 		}
@@ -776,14 +776,14 @@
 {
 	const struct snd_azf3328 *chip = ac97->private_data;
 	unsigned short reg_azf = snd_azf3328_mixer_ac97_map_reg_idx(reg_ac97);
-	bool unsupported = 0;
+	bool unsupported = false;
 
 	snd_azf3328_dbgmixer(
 		"snd_azf3328_mixer_ac97_write reg_ac97 %u val %u\n",
 			reg_ac97, val
 	);
 	if (reg_azf & AZF_AC97_REG_UNSUPPORTED)
-		unsupported = 1;
+		unsupported = true;
 	else {
 		if (reg_azf & AZF_AC97_REG_REAL_IO_WRITE)
 			snd_azf3328_mixer_outw(
@@ -808,7 +808,7 @@
 				 */
 				break;
 			default:
-				unsupported = 1;
+				unsupported = true;
 				break;
 			}
 		}
@@ -1559,7 +1559,7 @@
 	struct snd_azf3328_codec_data *codec = runtime->private_data;
 	int result = 0;
 	u16 flags1;
-	bool previously_muted = 0;
+	bool previously_muted = false;
 	bool is_main_mixer_playback_codec = (AZF_CODEC_PLAYBACK == codec->type);
 
 	snd_azf3328_dbgcalls("snd_azf3328_pcm_trigger cmd %d\n", cmd);
diff --git a/sound/pci/cs5535audio/cs5535audio_olpc.c b/sound/pci/cs5535audio/cs5535audio_olpc.c
index da1cb9c..e6a4450 100644
--- a/sound/pci/cs5535audio/cs5535audio_olpc.c
+++ b/sound/pci/cs5535audio/cs5535audio_olpc.c
@@ -161,13 +161,13 @@
 	/* drop the original AD1888 HPF control */
 	memset(&elem, 0, sizeof(elem));
 	elem.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-	strncpy(elem.name, "High Pass Filter Enable", sizeof(elem.name));
+	strlcpy(elem.name, "High Pass Filter Enable", sizeof(elem.name));
 	snd_ctl_remove_id(card, &elem);
 
 	/* drop the original V_REFOUT control */
 	memset(&elem, 0, sizeof(elem));
 	elem.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-	strncpy(elem.name, "V_REFOUT Enable", sizeof(elem.name));
+	strlcpy(elem.name, "V_REFOUT Enable", sizeof(elem.name));
 	snd_ctl_remove_id(card, &elem);
 
 	/* add the OLPC-specific controls */
diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c
index 0c00eb4..84f86bf 100644
--- a/sound/pci/ctxfi/ctdaio.c
+++ b/sound/pci/ctxfi/ctdaio.c
@@ -33,7 +33,7 @@
 	unsigned short right;
 };
 
-struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = {
+static struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = {
 	[LINEO1] = {.left = 0x00, .right = 0x01},
 	[LINEO2] = {.left = 0x18, .right = 0x19},
 	[LINEO3] = {.left = 0x08, .right = 0x09},
@@ -44,7 +44,7 @@
 	[SPDIFI1] = {.left = 0x95, .right = 0x9d},
 };
 
-struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = {
+static struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = {
 	[LINEO1] = {.left = 0x40, .right = 0x41},
 	[LINEO2] = {.left = 0x60, .right = 0x61},
 	[LINEO3] = {.left = 0x50, .right = 0x51},
diff --git a/sound/pci/ctxfi/cthardware.c b/sound/pci/ctxfi/cthardware.c
index 110b8ac..a689f25 100644
--- a/sound/pci/ctxfi/cthardware.c
+++ b/sound/pci/ctxfi/cthardware.c
@@ -69,7 +69,8 @@
 {
 	int i;
 
-	BUG_ON(!field);
+	if (WARN_ON(!field))
+		return 0;
 	/* @field should always be greater than 0 */
 	for (i = 0; !(field & (1 << i)); )
 		i++;
@@ -81,7 +82,8 @@
 {
 	int i;
 
-	BUG_ON(!field);
+	if (WARN_ON(!field))
+		return;
 	/* @field should always be greater than 0 */
 	for (i = 0; !(field & (1 << i)); )
 		i++;
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index 0275209..1f9c7c4 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -1182,15 +1182,20 @@
 	u32 *gpr_map;
 	mm_segment_t seg;
 
-	if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL ||
-	    (icode->gpr_map = (u_int32_t __user *)
-	     kcalloc(512 + 256 + 256 + 2 * 1024, sizeof(u_int32_t),
-		     GFP_KERNEL)) == NULL ||
-	    (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS,
-				sizeof(*controls), GFP_KERNEL)) == NULL) {
-		err = -ENOMEM;
-		goto __err;
-	}
+	err = -ENOMEM;
+	icode = kzalloc(sizeof(*icode), GFP_KERNEL);
+	if (!icode)
+		return err;
+
+	icode->gpr_map = (u_int32_t __user *) kcalloc(512 + 256 + 256 + 2 * 1024,
+						      sizeof(u_int32_t), GFP_KERNEL);
+	if (!icode->gpr_map)
+		goto __err_gpr;
+	controls = kcalloc(SND_EMU10K1_GPR_CONTROLS,
+			   sizeof(*controls), GFP_KERNEL);
+	if (!controls)
+		goto __err_ctrls;
+
 	gpr_map = (u32 __force *)icode->gpr_map;
 
 	icode->tram_data_map = icode->gpr_map + 512;
@@ -1741,12 +1746,12 @@
 	emu->support_tlv = 0; /* clear again */
 	snd_leave_user(seg);
 
- __err:
+__err:
 	kfree(controls);
-	if (icode != NULL) {
-		kfree((void __force *)icode->gpr_map);
-		kfree(icode);
-	}
+__err_ctrls:
+	kfree((void __force *)icode->gpr_map);
+__err_gpr:
+	kfree(icode);
 	return err;
 }
 
@@ -1813,18 +1818,26 @@
 	u32 *gpr_map;
 	mm_segment_t seg;
 
-	if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL)
-		return -ENOMEM;
-	if ((icode->gpr_map = (u_int32_t __user *)
-	     kcalloc(256 + 160 + 160 + 2 * 512, sizeof(u_int32_t),
-		     GFP_KERNEL)) == NULL ||
-            (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS,
-				sizeof(struct snd_emu10k1_fx8010_control_gpr),
-				GFP_KERNEL)) == NULL ||
-	    (ipcm = kzalloc(sizeof(*ipcm), GFP_KERNEL)) == NULL) {
-		err = -ENOMEM;
-		goto __err;
-	}
+	err = -ENOMEM;
+	icode = kzalloc(sizeof(*icode), GFP_KERNEL);
+	if (!icode)
+		return err;
+
+	icode->gpr_map = (u_int32_t __user *) kcalloc(256 + 160 + 160 + 2 * 512,
+						      sizeof(u_int32_t), GFP_KERNEL);
+	if (!icode->gpr_map)
+		goto __err_gpr;
+
+	controls = kcalloc(SND_EMU10K1_GPR_CONTROLS,
+			   sizeof(struct snd_emu10k1_fx8010_control_gpr),
+			   GFP_KERNEL);
+	if (!controls)
+		goto __err_ctrls;
+
+	ipcm = kzalloc(sizeof(*ipcm), GFP_KERNEL);
+	if (!ipcm)
+		goto __err_ipcm;
+
 	gpr_map = (u32 __force *)icode->gpr_map;
 
 	icode->tram_data_map = icode->gpr_map + 256;
@@ -2363,13 +2376,14 @@
 	snd_leave_user(seg);
 	if (err >= 0)
 		err = snd_emu10k1_ipcm_poke(emu, ipcm);
-      __err:
+__err:
 	kfree(ipcm);
+__err_ipcm:
 	kfree(controls);
-	if (icode != NULL) {
-		kfree((void __force *)icode->gpr_map);
-		kfree(icode);
-	}
+__err_ctrls:
+	kfree((void __force *)icode->gpr_map);
+__err_gpr:
+	kfree(icode);
 	return err;
 }
 
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
index 48a9d00..853c6a6 100644
--- a/sound/pci/hda/hda_auto_parser.c
+++ b/sound/pci/hda/hda_auto_parser.c
@@ -638,7 +638,7 @@
 			/* don't add channel suffix for Headphone controls */
 			int idx = get_hp_label_index(codec, nid, cfg->hp_pins,
 						     cfg->hp_outs);
-			if (idx >= 0)
+			if (idx >= 0 && indexp)
 				*indexp = idx;
 			sfx = "";
 		}
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c
index 63c9909..98bce98 100644
--- a/sound/pci/hda/hda_beep.c
+++ b/sound/pci/hda/hda_beep.c
@@ -110,6 +110,7 @@
 	case SND_BELL:
 		if (hz)
 			hz = 1000;
+		/* fallthru */
 	case SND_TONE:
 		if (beep->linear_tone)
 			beep->tone = beep_linear_tone(beep, hz);
@@ -151,10 +152,8 @@
 	int err;
 
 	input_dev = input_allocate_device();
-	if (!input_dev) {
-		printk(KERN_INFO "hda_beep: unable to allocate input device\n");
+	if (!input_dev)
 		return -ENOMEM;
-	}
 
 	/* setup digital beep device */
 	input_dev->name = "HDA Digital PCBeep";
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 5b6c4e3..dd5403d 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -565,7 +565,7 @@
 		range_val = !!(parm & (1 << (shift-1))); /* ranges */
 		val = parm & mask;
 		if (val == 0 && null_count++) {  /* no second chance */
-			snd_printk(KERN_WARNING "hda_codec: "
+			snd_printdd("hda_codec: "
 				   "invalid CONNECT_LIST verb %x[%i]:%x\n",
 				    nid, i, parm);
 			return 0;
@@ -2634,8 +2634,7 @@
 	items = codec->mixers.list;
 	for (i = 0; i < codec->mixers.used; i++) {
 		struct snd_kcontrol *sctl = items[i].kctl;
-		if (!sctl || !sctl->id.name ||
-		    sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER)
+		if (!sctl || sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER)
 			continue;
 		for (s = slaves; *s; s++) {
 			char tmpname[sizeof(sctl->id.name)];
@@ -2662,7 +2661,7 @@
 }
 
 /* guess the value corresponding to 0dB */
-static int get_kctl_0dB_offset(struct snd_kcontrol *kctl)
+static int get_kctl_0dB_offset(struct snd_kcontrol *kctl, int *step_to_check)
 {
 	int _tlv[4];
 	const int *tlv = NULL;
@@ -2677,8 +2676,19 @@
 		set_fs(fs);
 	} else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ)
 		tlv = kctl->tlv.p;
-	if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE)
-		val = -tlv[2] / tlv[3];
+	if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) {
+		int step = tlv[3];
+		step &= ~TLV_DB_SCALE_MUTE;
+		if (!step)
+			return -1;
+		if (*step_to_check && *step_to_check != step) {
+			snd_printk(KERN_ERR "hda_codec: Mismatching dB step for vmaster slave (%d!=%d)\n",
+				   *step_to_check, step);
+			return -1;
+		}
+		*step_to_check = step;
+		val = -tlv[2] / step;
+	}
 	return val;
 }
 
@@ -2699,7 +2709,7 @@
 /* initialize the slave volume with 0dB */
 static int init_slave_0dB(void *data, struct snd_kcontrol *slave)
 {
-	int offset = get_kctl_0dB_offset(slave);
+	int offset = get_kctl_0dB_offset(slave, data);
 	if (offset > 0)
 		put_kctl_with_value(slave, offset);
 	return 0;
@@ -2760,9 +2770,11 @@
 
 	/* init with master mute & zero volume */
 	put_kctl_with_value(kctl, 0);
-	if (init_slave_vol)
+	if (init_slave_vol) {
+		int step = 0;
 		map_slaves(codec, slaves, suffix,
-			   tlv ? init_slave_0dB : init_slave_unmute, kctl);
+			   tlv ? init_slave_0dB : init_slave_unmute, &step);
+	}
 
 	if (ctl_ret)
 		*ctl_ret = kctl;
@@ -4864,8 +4876,8 @@
 	spin_unlock(&codec->power_lock);
 
 	state = hda_call_codec_suspend(codec, true);
-	codec->pm_down_notified = 0;
-	if (!bus->power_keep_link_on && (state & AC_PWRST_CLK_STOP_OK)) {
+	if (!codec->pm_down_notified &&
+	    !bus->power_keep_link_on && (state & AC_PWRST_CLK_STOP_OK)) {
 		codec->pm_down_notified = 1;
 		hda_call_pm_notify(bus, false);
 	}
@@ -5395,11 +5407,6 @@
 			snd_hda_codec_setup_stream(codec,
 						   mout->hp_out_nid[i],
 						   stream_tag, 0, format);
-	for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
-		if (!mout->no_share_stream && mout->extra_out_nid[i])
-			snd_hda_codec_setup_stream(codec,
-						   mout->extra_out_nid[i],
-						   stream_tag, 0, format);
 
 	/* surrounds */
 	for (i = 1; i < mout->num_dacs; i++) {
@@ -5410,6 +5417,20 @@
 			snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
 						   0, format);
 	}
+
+	/* extra surrounds */
+	for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) {
+		int ch = 0;
+		if (!mout->extra_out_nid[i])
+			break;
+		if (chs >= (i + 1) * 2)
+			ch = i * 2;
+		else if (!mout->no_share_stream)
+			break;
+		snd_hda_codec_setup_stream(codec, mout->extra_out_nid[i],
+					   stream_tag, ch, format);
+	}
+
 	return 0;
 }
 EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 7aa9870..77db694 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -698,6 +698,7 @@
 	unsigned int in_reset:1;	/* during reset operation */
 	unsigned int power_keep_link_on:1; /* don't power off HDA link */
 	unsigned int no_response_fallback:1; /* don't fallback at RIRB error */
+	unsigned int avoid_link_reset:1; /* don't reset link at runtime PM */
 
 	int primary_dig_out_type;	/* primary digital out PCM type */
 };
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index d0d7ac1..32d3e38 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -2,6 +2,7 @@
  * Generic routines and proc interface for ELD(EDID Like Data) information
  *
  * Copyright(c) 2008 Intel Corporation.
+ * Copyright (c) 2013 Anssi Hannula <anssi.hannula@iki.fi>
  *
  * Authors:
  * 		Wu Fengguang <wfg@linux.intel.com>
@@ -478,10 +479,9 @@
 		snd_iprintf(buffer, "sad%d_profile\t\t%d\n", i, a->profile);
 }
 
-static void hdmi_print_eld_info(struct snd_info_entry *entry,
-				struct snd_info_buffer *buffer)
+void snd_hdmi_print_eld_info(struct hdmi_eld *eld,
+			     struct snd_info_buffer *buffer)
 {
-	struct hdmi_eld *eld = entry->private_data;
 	struct parsed_hdmi_eld *e = &eld->info;
 	char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
 	int i;
@@ -500,13 +500,10 @@
 		[4 ... 7] = "reserved"
 	};
 
-	mutex_lock(&eld->lock);
 	snd_iprintf(buffer, "monitor_present\t\t%d\n", eld->monitor_present);
 	snd_iprintf(buffer, "eld_valid\t\t%d\n", eld->eld_valid);
-	if (!eld->eld_valid) {
-		mutex_unlock(&eld->lock);
+	if (!eld->eld_valid)
 		return;
-	}
 	snd_iprintf(buffer, "monitor_name\t\t%s\n", e->monitor_name);
 	snd_iprintf(buffer, "connection_type\t\t%s\n",
 				eld_connection_type_names[e->conn_type]);
@@ -528,13 +525,11 @@
 
 	for (i = 0; i < e->sad_count; i++)
 		hdmi_print_sad_info(i, e->sad + i, buffer);
-	mutex_unlock(&eld->lock);
 }
 
-static void hdmi_write_eld_info(struct snd_info_entry *entry,
-				struct snd_info_buffer *buffer)
+void snd_hdmi_write_eld_info(struct hdmi_eld *eld,
+			     struct snd_info_buffer *buffer)
 {
-	struct hdmi_eld *eld = entry->private_data;
 	struct parsed_hdmi_eld *e = &eld->info;
 	char line[64];
 	char name[64];
@@ -542,7 +537,6 @@
 	long long val;
 	unsigned int n;
 
-	mutex_lock(&eld->lock);
 	while (!snd_info_get_line(buffer, line, sizeof(line))) {
 		if (sscanf(line, "%s %llx", name, &val) != 2)
 			continue;
@@ -594,38 +588,7 @@
 				e->sad_count = n + 1;
 		}
 	}
-	mutex_unlock(&eld->lock);
 }
-
-
-int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld,
-			 int index)
-{
-	char name[32];
-	struct snd_info_entry *entry;
-	int err;
-
-	snprintf(name, sizeof(name), "eld#%d.%d", codec->addr, index);
-	err = snd_card_proc_new(codec->bus->card, name, &entry);
-	if (err < 0)
-		return err;
-
-	snd_info_set_text_ops(entry, eld, hdmi_print_eld_info);
-	entry->c.text.write = hdmi_write_eld_info;
-	entry->mode |= S_IWUSR;
-	eld->proc_entry = entry;
-
-	return 0;
-}
-
-void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld)
-{
-	if (!codec->bus->shutdown && eld->proc_entry) {
-		snd_device_free(codec->bus->card, eld->proc_entry);
-		eld->proc_entry = NULL;
-	}
-}
-
 #endif /* CONFIG_PROC_FS */
 
 /* update PCM info based on ELD */
@@ -671,3 +634,153 @@
 	hinfo->maxbps = min(hinfo->maxbps, maxbps);
 	hinfo->channels_max = min(hinfo->channels_max, channels_max);
 }
+
+
+/* ATI/AMD specific stuff (ELD emulation) */
+
+#define ATI_VERB_SET_AUDIO_DESCRIPTOR	0x776
+#define ATI_VERB_SET_SINK_INFO_INDEX	0x780
+#define ATI_VERB_GET_SPEAKER_ALLOCATION	0xf70
+#define ATI_VERB_GET_AUDIO_DESCRIPTOR	0xf76
+#define ATI_VERB_GET_AUDIO_VIDEO_DELAY	0xf7b
+#define ATI_VERB_GET_SINK_INFO_INDEX	0xf80
+#define ATI_VERB_GET_SINK_INFO_DATA	0xf81
+
+#define ATI_SPKALLOC_SPKALLOC		0x007f
+#define ATI_SPKALLOC_TYPE_HDMI		0x0100
+#define ATI_SPKALLOC_TYPE_DISPLAYPORT	0x0200
+
+/* first three bytes are just standard SAD */
+#define ATI_AUDIODESC_CHANNELS		0x00000007
+#define ATI_AUDIODESC_RATES		0x0000ff00
+#define ATI_AUDIODESC_LPCM_STEREO_RATES	0xff000000
+
+/* in standard HDMI VSDB format */
+#define ATI_DELAY_VIDEO_LATENCY		0x000000ff
+#define ATI_DELAY_AUDIO_LATENCY		0x0000ff00
+
+enum ati_sink_info_idx {
+	ATI_INFO_IDX_MANUFACTURER_ID	= 0,
+	ATI_INFO_IDX_PRODUCT_ID		= 1,
+	ATI_INFO_IDX_SINK_DESC_LEN	= 2,
+	ATI_INFO_IDX_PORT_ID_LOW	= 3,
+	ATI_INFO_IDX_PORT_ID_HIGH	= 4,
+	ATI_INFO_IDX_SINK_DESC_FIRST	= 5,
+	ATI_INFO_IDX_SINK_DESC_LAST	= 22, /* max len 18 bytes */
+};
+
+int snd_hdmi_get_eld_ati(struct hda_codec *codec, hda_nid_t nid,
+			 unsigned char *buf, int *eld_size, bool rev3_or_later)
+{
+	int spkalloc, ati_sad, aud_synch;
+	int sink_desc_len = 0;
+	int pos, i;
+
+	/* ATI/AMD does not have ELD, emulate it */
+
+	spkalloc = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SPEAKER_ALLOCATION, 0);
+
+	if (!spkalloc) {
+		snd_printd(KERN_INFO "HDMI ATI/AMD: no speaker allocation for ELD\n");
+		return -EINVAL;
+	}
+
+	memset(buf, 0, ELD_FIXED_BYTES + ELD_MAX_MNL + ELD_MAX_SAD * 3);
+
+	/* version */
+	buf[0] = ELD_VER_CEA_861D << 3;
+
+	/* speaker allocation from EDID */
+	buf[7] = spkalloc & ATI_SPKALLOC_SPKALLOC;
+
+	/* is DisplayPort? */
+	if (spkalloc & ATI_SPKALLOC_TYPE_DISPLAYPORT)
+		buf[5] |= 0x04;
+
+	pos = ELD_FIXED_BYTES;
+
+	if (rev3_or_later) {
+		int sink_info;
+
+		snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_PORT_ID_LOW);
+		sink_info = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0);
+		put_unaligned_le32(sink_info, buf + 8);
+
+		snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_PORT_ID_HIGH);
+		sink_info = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0);
+		put_unaligned_le32(sink_info, buf + 12);
+
+		snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_MANUFACTURER_ID);
+		sink_info = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0);
+		put_unaligned_le16(sink_info, buf + 16);
+
+		snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_PRODUCT_ID);
+		sink_info = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0);
+		put_unaligned_le16(sink_info, buf + 18);
+
+		snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_SINK_DESC_LEN);
+		sink_desc_len = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0);
+
+		if (sink_desc_len > ELD_MAX_MNL) {
+			snd_printd(KERN_INFO "HDMI ATI/AMD: Truncating HDMI sink description with length %d\n",
+				   sink_desc_len);
+			sink_desc_len = ELD_MAX_MNL;
+		}
+
+		buf[4] |= sink_desc_len;
+
+		for (i = 0; i < sink_desc_len; i++) {
+			snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_SINK_INFO_INDEX, ATI_INFO_IDX_SINK_DESC_FIRST + i);
+			buf[pos++] = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_SINK_INFO_DATA, 0);
+		}
+	}
+
+	for (i = AUDIO_CODING_TYPE_LPCM; i <= AUDIO_CODING_TYPE_WMAPRO; i++) {
+		if (i == AUDIO_CODING_TYPE_SACD || i == AUDIO_CODING_TYPE_DST)
+			continue; /* not handled by ATI/AMD */
+
+		snd_hda_codec_write(codec, nid, 0, ATI_VERB_SET_AUDIO_DESCRIPTOR, i << 3);
+		ati_sad = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_AUDIO_DESCRIPTOR, 0);
+
+		if (ati_sad & ATI_AUDIODESC_RATES) {
+			/* format is supported, copy SAD as-is */
+			buf[pos++] = (ati_sad & 0x0000ff) >> 0;
+			buf[pos++] = (ati_sad & 0x00ff00) >> 8;
+			buf[pos++] = (ati_sad & 0xff0000) >> 16;
+		}
+
+		if (i == AUDIO_CODING_TYPE_LPCM
+		    && (ati_sad & ATI_AUDIODESC_LPCM_STEREO_RATES)
+		    && (ati_sad & ATI_AUDIODESC_LPCM_STEREO_RATES) >> 16 != (ati_sad & ATI_AUDIODESC_RATES)) {
+			/* for PCM there is a separate stereo rate mask */
+			buf[pos++] = ((ati_sad & 0x000000ff) & ~ATI_AUDIODESC_CHANNELS) | 0x1;
+			/* rates from the extra byte */
+			buf[pos++] = (ati_sad & 0xff000000) >> 24;
+			buf[pos++] = (ati_sad & 0x00ff0000) >> 16;
+		}
+	}
+
+	if (pos == ELD_FIXED_BYTES + sink_desc_len) {
+		snd_printd(KERN_INFO "HDMI ATI/AMD: no audio descriptors for ELD\n");
+		return -EINVAL;
+	}
+
+	aud_synch = snd_hda_codec_read(codec, nid, 0, ATI_VERB_GET_AUDIO_VIDEO_DELAY, 0);
+	if ((aud_synch & ATI_DELAY_VIDEO_LATENCY) && (aud_synch & ATI_DELAY_AUDIO_LATENCY)) {
+		int video_latency = (aud_synch & ATI_DELAY_VIDEO_LATENCY) - 1;
+		int audio_latency = ((aud_synch & ATI_DELAY_AUDIO_LATENCY) >> 8) - 1;
+
+		if (video_latency > audio_latency)
+			buf[6] = min(video_latency - audio_latency, 0xfa);
+	}
+
+	/* Baseline length */
+	buf[2] = pos - 4;
+
+	/* SAD count */
+	buf[5] |= ((pos - ELD_FIXED_BYTES - sink_desc_len) / 3) << 4;
+
+	*eld_size = pos;
+
+	return 0;
+}
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index ac41e9c..276f6e7 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -549,11 +549,15 @@
 static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec,
 				      struct nid_path *path)
 {
+	struct hda_gen_spec *spec = codec->spec;
 	int i;
 
 	for (i = path->depth - 1; i >= 0; i--) {
-		if (nid_has_volume(codec, path->path[i], HDA_OUTPUT))
-			return path->path[i];
+		hda_nid_t nid = path->path[i];
+		if ((spec->out_vol_mask >> nid) & 1)
+			continue;
+		if (nid_has_volume(codec, nid, HDA_OUTPUT))
+			return nid;
 	}
 	return 0;
 }
@@ -3531,7 +3535,7 @@
 		if (!multi)
 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
 							inv_dmic);
-		else if (!multi_cap_vol)
+		else if (!multi_cap_vol && !inv_dmic)
 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
 		else
 			err = create_multi_cap_vol_ctl(codec);
@@ -4475,9 +4479,11 @@
 					    true, &spec->vmaster_mute.sw_kctl);
 		if (err < 0)
 			return err;
-		if (spec->vmaster_mute.hook)
+		if (spec->vmaster_mute.hook) {
 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
 						 spec->vmaster_mute_enum);
+			snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
+		}
 	}
 
 	free_kctls(spec); /* no longer needed */
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index 48d4402..7e45cb4 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -242,6 +242,9 @@
 	/* additional mute flags (only effective with auto_mute_via_amp=1) */
 	u64 mute_bits;
 
+	/* bitmask for skipping volume controls */
+	u64 out_vol_mask;
+
 	/* badness tables for output path evaluations */
 	const struct badness_table *main_out_badness;
 	const struct badness_table *extra_out_badness;
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 6e61a01..7a09404 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -169,6 +169,7 @@
 			 "{Intel, PPT},"
 			 "{Intel, LPT},"
 			 "{Intel, LPT_LP},"
+			 "{Intel, WPT_LP},"
 			 "{Intel, HPT},"
 			 "{Intel, PBG},"
 			 "{Intel, SCH},"
@@ -568,6 +569,7 @@
 	AZX_DRIVER_ICH,
 	AZX_DRIVER_PCH,
 	AZX_DRIVER_SCH,
+	AZX_DRIVER_HDMI,
 	AZX_DRIVER_ATI,
 	AZX_DRIVER_ATIHDMI,
 	AZX_DRIVER_ATIHDMI_NS,
@@ -612,6 +614,11 @@
 #define AZX_DCAPS_INTEL_PCH \
 	(AZX_DCAPS_INTEL_PCH_NOPM | AZX_DCAPS_PM_RUNTIME)
 
+#define AZX_DCAPS_INTEL_HASWELL \
+	(AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_ALIGN_BUFSIZE | \
+	 AZX_DCAPS_COUNT_LPIB_DELAY | AZX_DCAPS_PM_RUNTIME | \
+	 AZX_DCAPS_I915_POWERWELL)
+
 /* quirks for ATI SB / AMD Hudson */
 #define AZX_DCAPS_PRESET_ATI_SB \
 	(AZX_DCAPS_ATI_SNOOP | AZX_DCAPS_NO_TCSEL | \
@@ -642,6 +649,7 @@
 	[AZX_DRIVER_ICH] = "HDA Intel",
 	[AZX_DRIVER_PCH] = "HDA Intel PCH",
 	[AZX_DRIVER_SCH] = "HDA Intel MID",
+	[AZX_DRIVER_HDMI] = "HDA Intel HDMI",
 	[AZX_DRIVER_ATI] = "HDA ATI SB",
 	[AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI",
 	[AZX_DRIVER_ATIHDMI_NS] = "HDA ATI HDMI",
@@ -906,12 +914,12 @@
 			chip->rirb.res[addr] = res;
 			smp_wmb();
 			chip->rirb.cmds[addr]--;
-		} else
-			snd_printk(KERN_ERR SFX "%s: spurious response %#x:%#x, "
-				   "last cmd=%#08x\n",
+		} else if (printk_ratelimit()) {
+			snd_printk(KERN_ERR SFX "%s: spurious response %#x:%#x, last cmd=%#08x\n",
 				   pci_name(chip->pci),
 				   res, res_ex,
 				   chip->last_cmd[addr]);
+		}
 	}
 }
 
@@ -2986,7 +2994,8 @@
 		  STATESTS_INT_MASK);
 
 	azx_stop_chip(chip);
-	azx_enter_link_reset(chip);
+	if (!chip->bus->avoid_link_reset)
+		azx_enter_link_reset(chip);
 	azx_clear_irq_pending(chip);
 	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
 		hda_display_power(false);
@@ -3985,16 +3994,16 @@
 	/* Lynx Point-LP */
 	{ PCI_DEVICE(0x8086, 0x9c21),
 	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
+	/* Wildcat Point-LP */
+	{ PCI_DEVICE(0x8086, 0x9ca0),
+	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
 	/* Haswell */
 	{ PCI_DEVICE(0x8086, 0x0a0c),
-	  .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH |
-	  AZX_DCAPS_I915_POWERWELL },
+	  .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL },
 	{ PCI_DEVICE(0x8086, 0x0c0c),
-	  .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH |
-	  AZX_DCAPS_I915_POWERWELL },
+	  .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL },
 	{ PCI_DEVICE(0x8086, 0x0d0c),
-	  .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH |
-	  AZX_DCAPS_I915_POWERWELL },
+	  .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL },
 	/* 5 Series/3400 */
 	{ PCI_DEVICE(0x8086, 0x3b56),
 	  .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM },
@@ -4074,6 +4083,22 @@
 	  .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
 	{ PCI_DEVICE(0x1002, 0xaa48),
 	  .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+	{ PCI_DEVICE(0x1002, 0xaa50),
+	  .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+	{ PCI_DEVICE(0x1002, 0xaa58),
+	  .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+	{ PCI_DEVICE(0x1002, 0xaa60),
+	  .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+	{ PCI_DEVICE(0x1002, 0xaa68),
+	  .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+	{ PCI_DEVICE(0x1002, 0xaa80),
+	  .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+	{ PCI_DEVICE(0x1002, 0xaa88),
+	  .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+	{ PCI_DEVICE(0x1002, 0xaa90),
+	  .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+	{ PCI_DEVICE(0x1002, 0xaa98),
+	  .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
 	{ PCI_DEVICE(0x1002, 0x9902),
 	  .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI },
 	{ PCI_DEVICE(0x1002, 0xaaa0),
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index 05b3e3e..afe5944 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -286,7 +286,7 @@
 	jack = codec->jacktbl.list;
 	for (i = 0; i < codec->jacktbl.used; i++, jack++)
 		if (jack->nid) {
-			if (!jack->kctl)
+			if (!jack->kctl || jack->block_report)
 				continue;
 			state = get_jack_plug_state(jack->pin_sense);
 			snd_kctl_jack_report(codec->bus->card, jack->kctl, state);
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h
index 379420c..46e1ea8 100644
--- a/sound/pci/hda/hda_jack.h
+++ b/sound/pci/hda/hda_jack.h
@@ -28,6 +28,7 @@
 	unsigned int jack_detect:1;	/* capable of jack-detection? */
 	unsigned int jack_dirty:1;	/* needs to update? */
 	unsigned int phantom_jack:1;    /* a fixed, always present port? */
+	unsigned int block_report:1;    /* in a transitional state - do not report to userspace */
 	hda_nid_t gating_jack;		/* valid when gating jack plugged */
 	hda_nid_t gated_jack;		/* gated is dependent on this jack */
 	struct snd_kcontrol *kctl;	/* assigned kctl for jack-detection */
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 2e7493e..d398b64 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -428,6 +428,7 @@
 	HDA_FIXUP_ACT_PROBE,
 	HDA_FIXUP_ACT_INIT,
 	HDA_FIXUP_ACT_BUILD,
+	HDA_FIXUP_ACT_FREE,
 };
 
 int snd_hda_add_verbs(struct hda_codec *codec, const struct hda_verb *list);
@@ -751,10 +752,6 @@
 	int	eld_size;
 	char    eld_buffer[ELD_MAX_SIZE];
 	struct parsed_hdmi_eld info;
-	struct mutex lock;
-#ifdef CONFIG_PROC_FS
-	struct snd_info_entry *proc_entry;
-#endif
 };
 
 int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid);
@@ -766,21 +763,15 @@
 void snd_hdmi_eld_update_pcm_info(struct parsed_hdmi_eld *e,
 			      struct hda_pcm_stream *hinfo);
 
+int snd_hdmi_get_eld_ati(struct hda_codec *codec, hda_nid_t nid,
+			 unsigned char *buf, int *eld_size,
+			 bool rev3_or_later);
+
 #ifdef CONFIG_PROC_FS
-int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld,
-			 int index);
-void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld);
-#else
-static inline int snd_hda_eld_proc_new(struct hda_codec *codec,
-				       struct hdmi_eld *eld,
-				       int index)
-{
-	return 0;
-}
-static inline void snd_hda_eld_proc_free(struct hda_codec *codec,
-					 struct hdmi_eld *eld)
-{
-}
+void snd_hdmi_print_eld_info(struct hdmi_eld *eld,
+			     struct snd_info_buffer *buffer);
+void snd_hdmi_write_eld_info(struct hdmi_eld *eld,
+			     struct snd_info_buffer *buffer);
 #endif
 
 #define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 0cbdd87..87d2e03 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -968,6 +968,18 @@
 	}
 }
 
+static void ad1884_fixup_thinkpad(struct hda_codec *codec,
+				  const struct hda_fixup *fix, int action)
+{
+	struct ad198x_spec *spec = codec->spec;
+
+	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+		spec->gen.keep_eapd_on = 1;
+		spec->gen.vmaster_mute.hook = ad_vmaster_eapd_hook;
+		spec->eapd_nid = 0x12;
+	}
+}
+
 /* set magic COEFs for dmic */
 static const struct hda_verb ad1884_dmic_init_verbs[] = {
 	{0x01, AC_VERB_SET_COEF_INDEX, 0x13f7},
@@ -979,6 +991,7 @@
 	AD1884_FIXUP_AMP_OVERRIDE,
 	AD1884_FIXUP_HP_EAPD,
 	AD1884_FIXUP_DMIC_COEF,
+	AD1884_FIXUP_THINKPAD,
 	AD1884_FIXUP_HP_TOUCHSMART,
 };
 
@@ -997,6 +1010,12 @@
 		.type = HDA_FIXUP_VERBS,
 		.v.verbs = ad1884_dmic_init_verbs,
 	},
+	[AD1884_FIXUP_THINKPAD] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = ad1884_fixup_thinkpad,
+		.chained = true,
+		.chain_id = AD1884_FIXUP_DMIC_COEF,
+	},
 	[AD1884_FIXUP_HP_TOUCHSMART] = {
 		.type = HDA_FIXUP_VERBS,
 		.v.verbs = ad1884_dmic_init_verbs,
@@ -1008,7 +1027,7 @@
 static const struct snd_pci_quirk ad1884_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x103c, 0x2a82, "HP Touchsmart", AD1884_FIXUP_HP_TOUCHSMART),
 	SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1884_FIXUP_HP_EAPD),
-	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1884_FIXUP_DMIC_COEF),
+	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1884_FIXUP_THINKPAD),
 	{}
 };
 
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 6e9876f..54d1479 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -759,7 +759,7 @@
 /*
  * CA0132 codec access
  */
-unsigned int codec_send_command(struct hda_codec *codec, hda_nid_t nid,
+static unsigned int codec_send_command(struct hda_codec *codec, hda_nid_t nid,
 		unsigned int verb, unsigned int parm, unsigned int *res)
 {
 	unsigned int response;
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 18d9725..072755c 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -597,6 +597,7 @@
  * Its layout is no longer compatible with CS4206/CS4207
  */
 enum {
+	CS4208_MAC_AUTO,
 	CS4208_MBA6,
 	CS4208_GPIO0,
 };
@@ -608,7 +609,12 @@
 };
 
 static const struct snd_pci_quirk cs4208_fixup_tbl[] = {
-	/* codec SSID */
+	SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS4208_MAC_AUTO),
+	{} /* terminator */
+};
+
+/* codec SSID matching */
+static const struct snd_pci_quirk cs4208_mac_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x106b, 0x7100, "MacBookAir 6,1", CS4208_MBA6),
 	SND_PCI_QUIRK(0x106b, 0x7200, "MacBookAir 6,2", CS4208_MBA6),
 	{} /* terminator */
@@ -626,6 +632,20 @@
 	}
 }
 
+static const struct hda_fixup cs4208_fixups[];
+
+/* remap the fixup from codec SSID and apply it */
+static void cs4208_fixup_mac(struct hda_codec *codec,
+			     const struct hda_fixup *fix, int action)
+{
+	if (action != HDA_FIXUP_ACT_PRE_PROBE)
+		return;
+	snd_hda_pick_fixup(codec, NULL, cs4208_mac_fixup_tbl, cs4208_fixups);
+	if (codec->fixup_id < 0 || codec->fixup_id == CS4208_MAC_AUTO)
+		codec->fixup_id = CS4208_GPIO0; /* default fixup */
+	snd_hda_apply_fixup(codec, action);
+}
+
 static const struct hda_fixup cs4208_fixups[] = {
 	[CS4208_MBA6] = {
 		.type = HDA_FIXUP_PINS,
@@ -637,6 +657,10 @@
 		.type = HDA_FIXUP_FUNC,
 		.v.func = cs4208_fixup_gpio0,
 	},
+	[CS4208_MAC_AUTO] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = cs4208_fixup_mac,
+	},
 };
 
 /* correct the 0dB offset of input pins */
@@ -660,6 +684,8 @@
 		return -ENOMEM;
 
 	spec->gen.automute_hook = cs_automute;
+	/* exclude NID 0x10 (HP) from output volumes due to different steps */
+	spec->gen.out_vol_mask = 1ULL << 0x10;
 
 	snd_hda_pick_fixup(codec, cs4208_models, cs4208_fixup_tbl,
 			   cs4208_fixups);
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index ec68eaea..c205bb1 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -3208,11 +3208,17 @@
 	return 0;
 }
 
+static void cx_auto_free(struct hda_codec *codec)
+{
+	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE);
+	snd_hda_gen_free(codec);
+}
+
 static const struct hda_codec_ops cx_auto_patch_ops = {
 	.build_controls = cx_auto_build_controls,
 	.build_pcms = snd_hda_gen_build_pcms,
 	.init = cx_auto_init,
-	.free = snd_hda_gen_free,
+	.free = cx_auto_free,
 	.unsol_event = snd_hda_jack_unsol_event,
 #ifdef CONFIG_PM
 	.check_power_status = snd_hda_gen_check_power_status,
@@ -3232,8 +3238,84 @@
 	CXT_FIXUP_HEADPHONE_MIC_PIN,
 	CXT_FIXUP_HEADPHONE_MIC,
 	CXT_FIXUP_GPIO1,
+	CXT_FIXUP_THINKPAD_ACPI,
 };
 
+#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
+
+#include <linux/thinkpad_acpi.h>
+
+static int (*led_set_func)(int, bool);
+
+static void update_tpacpi_mute_led(void *private_data, int enabled)
+{
+	struct hda_codec *codec = private_data;
+	struct conexant_spec *spec = codec->spec;
+
+	if (spec->dynamic_eapd)
+		cx_auto_vmaster_hook(private_data, enabled);
+
+	if (led_set_func)
+		led_set_func(TPACPI_LED_MUTE, !enabled);
+}
+
+static void update_tpacpi_micmute_led(struct hda_codec *codec,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	if (!ucontrol || !led_set_func)
+		return;
+	if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
+		/* TODO: How do I verify if it's a mono or stereo here? */
+		bool val = ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1];
+		led_set_func(TPACPI_LED_MICMUTE, !val);
+	}
+}
+
+static void cxt_fixup_thinkpad_acpi(struct hda_codec *codec,
+				  const struct hda_fixup *fix, int action)
+{
+	struct conexant_spec *spec = codec->spec;
+
+	bool removefunc = false;
+
+	if (action == HDA_FIXUP_ACT_PROBE) {
+		if (!led_set_func)
+			led_set_func = symbol_request(tpacpi_led_set);
+		if (!led_set_func) {
+			snd_printk(KERN_WARNING "Failed to find thinkpad-acpi symbol tpacpi_led_set\n");
+			return;
+		}
+
+		removefunc = true;
+		if (led_set_func(TPACPI_LED_MUTE, false) >= 0) {
+			spec->gen.vmaster_mute.hook = update_tpacpi_mute_led;
+			removefunc = false;
+		}
+		if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) {
+			if (spec->gen.num_adc_nids > 1)
+				snd_printdd("Skipping micmute LED control due to several ADCs");
+			else {
+				spec->gen.cap_sync_hook = update_tpacpi_micmute_led;
+				removefunc = false;
+			}
+		}
+	}
+
+	if (led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
+		symbol_put(tpacpi_led_set);
+		led_set_func = NULL;
+	}
+}
+
+#else
+
+static void cxt_fixup_thinkpad_acpi(struct hda_codec *codec,
+				  const struct hda_fixup *fix, int action)
+{
+}
+
+#endif
+
 static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
 				  const struct hda_fixup *fix, int action)
 {
@@ -3344,6 +3426,8 @@
 	[CXT_PINCFG_LENOVO_TP410] = {
 		.type = HDA_FIXUP_PINS,
 		.v.pins = cxt_pincfg_lenovo_tp410,
+		.chained = true,
+		.chain_id = CXT_FIXUP_THINKPAD_ACPI,
 	},
 	[CXT_PINCFG_LEMOTE_A1004] = {
 		.type = HDA_FIXUP_PINS,
@@ -3385,6 +3469,10 @@
 			{ }
 		},
 	},
+	[CXT_FIXUP_THINKPAD_ACPI] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = cxt_fixup_thinkpad_acpi,
+	},
 };
 
 static const struct snd_pci_quirk cxt5051_fixups[] = {
@@ -3507,7 +3595,7 @@
 	return 0;
 
  error:
-	snd_hda_gen_free(codec);
+	cx_auto_free(codec);
 	return err;
 }
 
@@ -3568,6 +3656,8 @@
 	  .patch = patch_conexant_auto },
 	{ .id = 0x14f15115, .name = "CX20757",
 	  .patch = patch_conexant_auto },
+	{ .id = 0x14f151d7, .name = "CX20952",
+	  .patch = patch_conexant_auto },
 	{} /* terminator */
 };
 
@@ -3594,6 +3684,7 @@
 MODULE_ALIAS("snd-hda-codec-id:14f15113");
 MODULE_ALIAS("snd-hda-codec-id:14f15114");
 MODULE_ALIAS("snd-hda-codec-id:14f15115");
+MODULE_ALIAS("snd-hda-codec-id:14f151d7");
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Conexant HD-audio codec");
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 7ea0245..e687923 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -6,6 +6,7 @@
  *  Copyright (c) 2006 ATI Technologies Inc.
  *  Copyright (c) 2008 NVIDIA Corp.  All rights reserved.
  *  Copyright (c) 2008 Wei Ni <wni@nvidia.com>
+ *  Copyright (c) 2013 Anssi Hannula <anssi.hannula@iki.fi>
  *
  *  Authors:
  *			Wu Fengguang <wfg@linux.intel.com>
@@ -45,6 +46,7 @@
 MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info");
 
 #define is_haswell(codec)  ((codec)->vendor_id == 0x80862807)
+#define is_valleyview(codec) ((codec)->vendor_id == 0x80862882)
 
 struct hdmi_spec_per_cvt {
 	hda_nid_t cvt_nid;
@@ -63,9 +65,11 @@
 	hda_nid_t pin_nid;
 	int num_mux_nids;
 	hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
+	hda_nid_t cvt_nid;
 
 	struct hda_codec *codec;
 	struct hdmi_eld sink_eld;
+	struct mutex lock;
 	struct delayed_work work;
 	struct snd_kcontrol *eld_ctl;
 	int repoll_count;
@@ -75,6 +79,42 @@
 	bool chmap_set;		/* channel-map override by ALSA API? */
 	unsigned char chmap[8]; /* ALSA API channel-map */
 	char pcm_name[8];	/* filled in build_pcm callbacks */
+#ifdef CONFIG_PROC_FS
+	struct snd_info_entry *proc_entry;
+#endif
+};
+
+struct cea_channel_speaker_allocation;
+
+/* operations used by generic code that can be overridden by patches */
+struct hdmi_ops {
+	int (*pin_get_eld)(struct hda_codec *codec, hda_nid_t pin_nid,
+			   unsigned char *buf, int *eld_size);
+
+	/* get and set channel assigned to each HDMI ASP (audio sample packet) slot */
+	int (*pin_get_slot_channel)(struct hda_codec *codec, hda_nid_t pin_nid,
+				    int asp_slot);
+	int (*pin_set_slot_channel)(struct hda_codec *codec, hda_nid_t pin_nid,
+				    int asp_slot, int channel);
+
+	void (*pin_setup_infoframe)(struct hda_codec *codec, hda_nid_t pin_nid,
+				    int ca, int active_channels, int conn_type);
+
+	/* enable/disable HBR (HD passthrough) */
+	int (*pin_hbr_setup)(struct hda_codec *codec, hda_nid_t pin_nid, bool hbr);
+
+	int (*setup_stream)(struct hda_codec *codec, hda_nid_t cvt_nid,
+			    hda_nid_t pin_nid, u32 stream_tag, int format);
+
+	/* Helpers for producing the channel map TLVs. These can be overridden
+	 * for devices that have non-standard mapping requirements. */
+	int (*chmap_cea_alloc_validate_get_type)(struct cea_channel_speaker_allocation *cap,
+						 int channels);
+	void (*cea_alloc_to_tlv_chmap)(struct cea_channel_speaker_allocation *cap,
+				       unsigned int *chmap, int channels);
+
+	/* check that the user-given chmap is supported */
+	int (*chmap_validate)(int ca, int channels, unsigned char *chmap);
 };
 
 struct hdmi_spec {
@@ -88,8 +128,9 @@
 	unsigned int channels_max; /* max over all cvts */
 
 	struct hdmi_eld temp_eld;
+	struct hdmi_ops ops;
 	/*
-	 * Non-generic ATI/NVIDIA specific
+	 * Non-generic VIA/NVIDIA specific
 	 */
 	struct hda_multi_out multiout;
 	struct hda_pcm_stream pcm_playback;
@@ -348,17 +389,19 @@
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct hdmi_spec *spec = codec->spec;
+	struct hdmi_spec_per_pin *per_pin;
 	struct hdmi_eld *eld;
 	int pin_idx;
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
 
 	pin_idx = kcontrol->private_value;
-	eld = &get_pin(spec, pin_idx)->sink_eld;
+	per_pin = get_pin(spec, pin_idx);
+	eld = &per_pin->sink_eld;
 
-	mutex_lock(&eld->lock);
+	mutex_lock(&per_pin->lock);
 	uinfo->count = eld->eld_valid ? eld->eld_size : 0;
-	mutex_unlock(&eld->lock);
+	mutex_unlock(&per_pin->lock);
 
 	return 0;
 }
@@ -368,15 +411,17 @@
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct hdmi_spec *spec = codec->spec;
+	struct hdmi_spec_per_pin *per_pin;
 	struct hdmi_eld *eld;
 	int pin_idx;
 
 	pin_idx = kcontrol->private_value;
-	eld = &get_pin(spec, pin_idx)->sink_eld;
+	per_pin = get_pin(spec, pin_idx);
+	eld = &per_pin->sink_eld;
 
-	mutex_lock(&eld->lock);
+	mutex_lock(&per_pin->lock);
 	if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data)) {
-		mutex_unlock(&eld->lock);
+		mutex_unlock(&per_pin->lock);
 		snd_BUG();
 		return -EINVAL;
 	}
@@ -386,7 +431,7 @@
 	if (eld->eld_valid)
 		memcpy(ucontrol->value.bytes.data, eld->eld_buffer,
 		       eld->eld_size);
-	mutex_unlock(&eld->lock);
+	mutex_unlock(&per_pin->lock);
 
 	return 0;
 }
@@ -477,6 +522,68 @@
 				    AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
 }
 
+/*
+ * ELD proc files
+ */
+
+#ifdef CONFIG_PROC_FS
+static void print_eld_info(struct snd_info_entry *entry,
+			   struct snd_info_buffer *buffer)
+{
+	struct hdmi_spec_per_pin *per_pin = entry->private_data;
+
+	mutex_lock(&per_pin->lock);
+	snd_hdmi_print_eld_info(&per_pin->sink_eld, buffer);
+	mutex_unlock(&per_pin->lock);
+}
+
+static void write_eld_info(struct snd_info_entry *entry,
+			   struct snd_info_buffer *buffer)
+{
+	struct hdmi_spec_per_pin *per_pin = entry->private_data;
+
+	mutex_lock(&per_pin->lock);
+	snd_hdmi_write_eld_info(&per_pin->sink_eld, buffer);
+	mutex_unlock(&per_pin->lock);
+}
+
+static int eld_proc_new(struct hdmi_spec_per_pin *per_pin, int index)
+{
+	char name[32];
+	struct hda_codec *codec = per_pin->codec;
+	struct snd_info_entry *entry;
+	int err;
+
+	snprintf(name, sizeof(name), "eld#%d.%d", codec->addr, index);
+	err = snd_card_proc_new(codec->bus->card, name, &entry);
+	if (err < 0)
+		return err;
+
+	snd_info_set_text_ops(entry, per_pin, print_eld_info);
+	entry->c.text.write = write_eld_info;
+	entry->mode |= S_IWUSR;
+	per_pin->proc_entry = entry;
+
+	return 0;
+}
+
+static void eld_proc_free(struct hdmi_spec_per_pin *per_pin)
+{
+	if (!per_pin->codec->bus->shutdown && per_pin->proc_entry) {
+		snd_device_free(per_pin->codec->bus->card, per_pin->proc_entry);
+		per_pin->proc_entry = NULL;
+	}
+}
+#else
+static inline int eld_proc_new(struct hdmi_spec_per_pin *per_pin,
+			       int index)
+{
+	return 0;
+}
+static inline void eld_proc_free(struct hdmi_spec_per_pin *per_pin)
+{
+}
+#endif
 
 /*
  * Channel mapping routines
@@ -577,74 +684,91 @@
 				       hda_nid_t pin_nid)
 {
 #ifdef CONFIG_SND_DEBUG_VERBOSE
+	struct hdmi_spec *spec = codec->spec;
 	int i;
-	int slot;
+	int channel;
 
 	for (i = 0; i < 8; i++) {
-		slot = snd_hda_codec_read(codec, pin_nid, 0,
-						AC_VERB_GET_HDMI_CHAN_SLOT, i);
+		channel = spec->ops.pin_get_slot_channel(codec, pin_nid, i);
 		printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
-						slot >> 4, slot & 0xf);
+						channel, i);
 	}
 #endif
 }
 
-
 static void hdmi_std_setup_channel_mapping(struct hda_codec *codec,
 				       hda_nid_t pin_nid,
 				       bool non_pcm,
 				       int ca)
 {
+	struct hdmi_spec *spec = codec->spec;
+	struct cea_channel_speaker_allocation *ch_alloc;
 	int i;
 	int err;
 	int order;
 	int non_pcm_mapping[8];
 
 	order = get_channel_allocation_order(ca);
+	ch_alloc = &channel_allocations[order];
 
 	if (hdmi_channel_mapping[ca][1] == 0) {
-		for (i = 0; i < channel_allocations[order].channels; i++)
-			hdmi_channel_mapping[ca][i] = i | (i << 4);
-		for (; i < 8; i++)
-			hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
+		int hdmi_slot = 0;
+		/* fill actual channel mappings in ALSA channel (i) order */
+		for (i = 0; i < ch_alloc->channels; i++) {
+			while (!ch_alloc->speakers[7 - hdmi_slot] && !WARN_ON(hdmi_slot >= 8))
+				hdmi_slot++; /* skip zero slots */
+
+			hdmi_channel_mapping[ca][i] = (i << 4) | hdmi_slot++;
+		}
+		/* fill the rest of the slots with ALSA channel 0xf */
+		for (hdmi_slot = 0; hdmi_slot < 8; hdmi_slot++)
+			if (!ch_alloc->speakers[7 - hdmi_slot])
+				hdmi_channel_mapping[ca][i++] = (0xf << 4) | hdmi_slot;
 	}
 
 	if (non_pcm) {
-		for (i = 0; i < channel_allocations[order].channels; i++)
-			non_pcm_mapping[i] = i | (i << 4);
+		for (i = 0; i < ch_alloc->channels; i++)
+			non_pcm_mapping[i] = (i << 4) | i;
 		for (; i < 8; i++)
-			non_pcm_mapping[i] = 0xf | (i << 4);
+			non_pcm_mapping[i] = (0xf << 4) | i;
 	}
 
 	for (i = 0; i < 8; i++) {
-		err = snd_hda_codec_write(codec, pin_nid, 0,
-					  AC_VERB_SET_HDMI_CHAN_SLOT,
-					  non_pcm ? non_pcm_mapping[i] : hdmi_channel_mapping[ca][i]);
+		int slotsetup = non_pcm ? non_pcm_mapping[i] : hdmi_channel_mapping[ca][i];
+		int hdmi_slot = slotsetup & 0x0f;
+		int channel = (slotsetup & 0xf0) >> 4;
+		err = spec->ops.pin_set_slot_channel(codec, pin_nid, hdmi_slot, channel);
 		if (err) {
 			snd_printdd(KERN_NOTICE
 				    "HDMI: channel mapping failed\n");
 			break;
 		}
 	}
-
-	hdmi_debug_channel_mapping(codec, pin_nid);
 }
 
 struct channel_map_table {
 	unsigned char map;		/* ALSA API channel map position */
-	unsigned char cea_slot;		/* CEA slot value */
 	int spk_mask;			/* speaker position bit mask */
 };
 
 static struct channel_map_table map_tables[] = {
-	{ SNDRV_CHMAP_FL,	0x00,	FL },
-	{ SNDRV_CHMAP_FR,	0x01,	FR },
-	{ SNDRV_CHMAP_RL,	0x04,	RL },
-	{ SNDRV_CHMAP_RR,	0x05,	RR },
-	{ SNDRV_CHMAP_LFE,	0x02,	LFE },
-	{ SNDRV_CHMAP_FC,	0x03,	FC },
-	{ SNDRV_CHMAP_RLC,	0x06,	RLC },
-	{ SNDRV_CHMAP_RRC,	0x07,	RRC },
+	{ SNDRV_CHMAP_FL,	FL },
+	{ SNDRV_CHMAP_FR,	FR },
+	{ SNDRV_CHMAP_RL,	RL },
+	{ SNDRV_CHMAP_RR,	RR },
+	{ SNDRV_CHMAP_LFE,	LFE },
+	{ SNDRV_CHMAP_FC,	FC },
+	{ SNDRV_CHMAP_RLC,	RLC },
+	{ SNDRV_CHMAP_RRC,	RRC },
+	{ SNDRV_CHMAP_RC,	RC },
+	{ SNDRV_CHMAP_FLC,	FLC },
+	{ SNDRV_CHMAP_FRC,	FRC },
+	{ SNDRV_CHMAP_FLH,	FLH },
+	{ SNDRV_CHMAP_FRH,	FRH },
+	{ SNDRV_CHMAP_FLW,	FLW },
+	{ SNDRV_CHMAP_FRW,	FRW },
+	{ SNDRV_CHMAP_TC,	TC },
+	{ SNDRV_CHMAP_FCH,	FCH },
 	{} /* terminator */
 };
 
@@ -660,25 +784,19 @@
 }
 
 /* from ALSA API channel position to CEA slot */
-static int to_cea_slot(unsigned char c)
+static int to_cea_slot(int ordered_ca, unsigned char pos)
 {
-	struct channel_map_table *t = map_tables;
-	for (; t->map; t++) {
-		if (t->map == c)
-			return t->cea_slot;
-	}
-	return 0x0f;
-}
+	int mask = to_spk_mask(pos);
+	int i;
 
-/* from CEA slot to ALSA API channel position */
-static int from_cea_slot(unsigned char c)
-{
-	struct channel_map_table *t = map_tables;
-	for (; t->map; t++) {
-		if (t->cea_slot == c)
-			return t->map;
+	if (mask) {
+		for (i = 0; i < 8; i++) {
+			if (channel_allocations[ordered_ca].speakers[7 - i] == mask)
+				return i;
+		}
 	}
-	return 0;
+
+	return -1;
 }
 
 /* from speaker bit mask to ALSA API channel position */
@@ -692,6 +810,14 @@
 	return 0;
 }
 
+/* from CEA slot to ALSA API channel position */
+static int from_cea_slot(int ordered_ca, unsigned char slot)
+{
+	int mask = channel_allocations[ordered_ca].speakers[7 - slot];
+
+	return spk_to_chmap(mask);
+}
+
 /* get the CA index corresponding to the given ALSA API channel map */
 static int hdmi_manual_channel_allocation(int chs, unsigned char *map)
 {
@@ -718,18 +844,29 @@
 /* set up the channel slots for the given ALSA API channel map */
 static int hdmi_manual_setup_channel_mapping(struct hda_codec *codec,
 					     hda_nid_t pin_nid,
-					     int chs, unsigned char *map)
+					     int chs, unsigned char *map,
+					     int ca)
 {
-	int i;
-	for (i = 0; i < 8; i++) {
-		int val, err;
-		if (i < chs)
-			val = to_cea_slot(map[i]);
-		else
-			val = 0xf;
-		val |= (i << 4);
-		err = snd_hda_codec_write(codec, pin_nid, 0,
-					  AC_VERB_SET_HDMI_CHAN_SLOT, val);
+	struct hdmi_spec *spec = codec->spec;
+	int ordered_ca = get_channel_allocation_order(ca);
+	int alsa_pos, hdmi_slot;
+	int assignments[8] = {[0 ... 7] = 0xf};
+
+	for (alsa_pos = 0; alsa_pos < chs; alsa_pos++) {
+
+		hdmi_slot = to_cea_slot(ordered_ca, map[alsa_pos]);
+
+		if (hdmi_slot < 0)
+			continue; /* unassigned channel */
+
+		assignments[hdmi_slot] = alsa_pos;
+	}
+
+	for (hdmi_slot = 0; hdmi_slot < 8; hdmi_slot++) {
+		int err;
+
+		err = spec->ops.pin_set_slot_channel(codec, pin_nid, hdmi_slot,
+						     assignments[hdmi_slot]);
 		if (err)
 			return -EINVAL;
 	}
@@ -740,9 +877,10 @@
 static void hdmi_setup_fake_chmap(unsigned char *map, int ca)
 {
 	int i;
+	int ordered_ca = get_channel_allocation_order(ca);
 	for (i = 0; i < 8; i++) {
-		if (i < channel_allocations[ca].channels)
-			map[i] = from_cea_slot((hdmi_channel_mapping[ca][i] >> 4) & 0x0f);
+		if (i < channel_allocations[ordered_ca].channels)
+			map[i] = from_cea_slot(ordered_ca, hdmi_channel_mapping[ca][i] & 0x0f);
 		else
 			map[i] = 0;
 	}
@@ -755,11 +893,29 @@
 {
 	if (!non_pcm && chmap_set) {
 		hdmi_manual_setup_channel_mapping(codec, pin_nid,
-						  channels, map);
+						  channels, map, ca);
 	} else {
 		hdmi_std_setup_channel_mapping(codec, pin_nid, non_pcm, ca);
 		hdmi_setup_fake_chmap(map, ca);
 	}
+
+	hdmi_debug_channel_mapping(codec, pin_nid);
+}
+
+static int hdmi_pin_set_slot_channel(struct hda_codec *codec, hda_nid_t pin_nid,
+				     int asp_slot, int channel)
+{
+	return snd_hda_codec_write(codec, pin_nid, 0,
+				   AC_VERB_SET_HDMI_CHAN_SLOT,
+				   (channel << 4) | asp_slot);
+}
+
+static int hdmi_pin_get_slot_channel(struct hda_codec *codec, hda_nid_t pin_nid,
+				     int asp_slot)
+{
+	return (snd_hda_codec_read(codec, pin_nid, 0,
+				   AC_VERB_GET_HDMI_CHAN_SLOT,
+				   asp_slot) & 0xf0) >> 4;
 }
 
 /*
@@ -883,15 +1039,64 @@
 	return true;
 }
 
+static void hdmi_pin_setup_infoframe(struct hda_codec *codec,
+				     hda_nid_t pin_nid,
+				     int ca, int active_channels,
+				     int conn_type)
+{
+	union audio_infoframe ai;
+
+	if (conn_type == 0) { /* HDMI */
+		struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi;
+
+		hdmi_ai->type		= 0x84;
+		hdmi_ai->ver		= 0x01;
+		hdmi_ai->len		= 0x0a;
+		hdmi_ai->CC02_CT47	= active_channels - 1;
+		hdmi_ai->CA		= ca;
+		hdmi_checksum_audio_infoframe(hdmi_ai);
+	} else if (conn_type == 1) { /* DisplayPort */
+		struct dp_audio_infoframe *dp_ai = &ai.dp;
+
+		dp_ai->type		= 0x84;
+		dp_ai->len		= 0x1b;
+		dp_ai->ver		= 0x11 << 2;
+		dp_ai->CC02_CT47	= active_channels - 1;
+		dp_ai->CA		= ca;
+	} else {
+		snd_printd("HDMI: unknown connection type at pin %d\n",
+			    pin_nid);
+		return;
+	}
+
+	/*
+	 * sizeof(ai) is used instead of sizeof(*hdmi_ai) or
+	 * sizeof(*dp_ai) to avoid partial match/update problems when
+	 * the user switches between HDMI/DP monitors.
+	 */
+	if (!hdmi_infoframe_uptodate(codec, pin_nid, ai.bytes,
+					sizeof(ai))) {
+		snd_printdd("hdmi_pin_setup_infoframe: "
+			    "pin=%d channels=%d ca=0x%02x\n",
+			    pin_nid,
+			    active_channels, ca);
+		hdmi_stop_infoframe_trans(codec, pin_nid);
+		hdmi_fill_audio_infoframe(codec, pin_nid,
+					    ai.bytes, sizeof(ai));
+		hdmi_start_infoframe_trans(codec, pin_nid);
+	}
+}
+
 static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
 				       struct hdmi_spec_per_pin *per_pin,
 				       bool non_pcm)
 {
+	struct hdmi_spec *spec = codec->spec;
 	hda_nid_t pin_nid = per_pin->pin_nid;
 	int channels = per_pin->channels;
+	int active_channels;
 	struct hdmi_eld *eld;
-	int ca;
-	union audio_infoframe ai;
+	int ca, ordered_ca;
 
 	if (!channels)
 		return;
@@ -912,66 +1117,30 @@
 	if (ca < 0)
 		ca = 0;
 
-	memset(&ai, 0, sizeof(ai));
-	if (eld->info.conn_type == 0) { /* HDMI */
-		struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi;
+	ordered_ca = get_channel_allocation_order(ca);
+	active_channels = channel_allocations[ordered_ca].channels;
 
-		hdmi_ai->type		= 0x84;
-		hdmi_ai->ver		= 0x01;
-		hdmi_ai->len		= 0x0a;
-		hdmi_ai->CC02_CT47	= channels - 1;
-		hdmi_ai->CA		= ca;
-		hdmi_checksum_audio_infoframe(hdmi_ai);
-	} else if (eld->info.conn_type == 1) { /* DisplayPort */
-		struct dp_audio_infoframe *dp_ai = &ai.dp;
-
-		dp_ai->type		= 0x84;
-		dp_ai->len		= 0x1b;
-		dp_ai->ver		= 0x11 << 2;
-		dp_ai->CC02_CT47	= channels - 1;
-		dp_ai->CA		= ca;
-	} else {
-		snd_printd("HDMI: unknown connection type at pin %d\n",
-			    pin_nid);
-		return;
-	}
+	hdmi_set_channel_count(codec, per_pin->cvt_nid, active_channels);
 
 	/*
-	 * sizeof(ai) is used instead of sizeof(*hdmi_ai) or
-	 * sizeof(*dp_ai) to avoid partial match/update problems when
-	 * the user switches between HDMI/DP monitors.
+	 * always configure channel mapping, it may have been changed by the
+	 * user in the meantime
 	 */
-	if (!hdmi_infoframe_uptodate(codec, pin_nid, ai.bytes,
-					sizeof(ai))) {
-		snd_printdd("hdmi_setup_audio_infoframe: "
-			    "pin=%d channels=%d\n",
-			    pin_nid,
-			    channels);
-		hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca,
-					   channels, per_pin->chmap,
-					   per_pin->chmap_set);
-		hdmi_stop_infoframe_trans(codec, pin_nid);
-		hdmi_fill_audio_infoframe(codec, pin_nid,
-					    ai.bytes, sizeof(ai));
-		hdmi_start_infoframe_trans(codec, pin_nid);
-	} else {
-		/* For non-pcm audio switch, setup new channel mapping
-		 * accordingly */
-		if (per_pin->non_pcm != non_pcm)
-			hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca,
-						   channels, per_pin->chmap,
-						   per_pin->chmap_set);
-	}
+	hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca,
+				   channels, per_pin->chmap,
+				   per_pin->chmap_set);
+
+	spec->ops.pin_setup_infoframe(codec, pin_nid, ca, active_channels,
+				      eld->info.conn_type);
 
 	per_pin->non_pcm = non_pcm;
 }
 
-
 /*
  * Unsolicited events
  */
 
-static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll);
+static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll);
 
 static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
 {
@@ -997,8 +1166,8 @@
 	if (pin_idx < 0)
 		return;
 
-	hdmi_present_sense(get_pin(spec, pin_idx), 1);
-	snd_hda_jack_report_sync(codec);
+	if (hdmi_present_sense(get_pin(spec, pin_idx), 1))
+		snd_hda_jack_report_sync(codec);
 }
 
 static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
@@ -1069,26 +1238,22 @@
 #define is_hbr_format(format) \
 	((format & AC_FMT_TYPE_NON_PCM) && (format & AC_FMT_CHAN_MASK) == 7)
 
-static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
-			      hda_nid_t pin_nid, u32 stream_tag, int format)
+static int hdmi_pin_hbr_setup(struct hda_codec *codec, hda_nid_t pin_nid,
+			      bool hbr)
 {
-	int pinctl;
-	int new_pinctl = 0;
-
-	if (is_haswell(codec))
-		haswell_verify_D0(codec, cvt_nid, pin_nid);
+	int pinctl, new_pinctl;
 
 	if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) {
 		pinctl = snd_hda_codec_read(codec, pin_nid, 0,
 					    AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
 
 		new_pinctl = pinctl & ~AC_PINCTL_EPT;
-		if (is_hbr_format(format))
+		if (hbr)
 			new_pinctl |= AC_PINCTL_EPT_HBR;
 		else
 			new_pinctl |= AC_PINCTL_EPT_NATIVE;
 
-		snd_printdd("hdmi_setup_stream: "
+		snd_printdd("hdmi_pin_hbr_setup: "
 			    "NID=0x%x, %spinctl=0x%x\n",
 			    pin_nid,
 			    pinctl == new_pinctl ? "" : "new-",
@@ -1098,11 +1263,26 @@
 			snd_hda_codec_write(codec, pin_nid, 0,
 					    AC_VERB_SET_PIN_WIDGET_CONTROL,
 					    new_pinctl);
-
-	}
-	if (is_hbr_format(format) && !new_pinctl) {
-		snd_printdd("hdmi_setup_stream: HBR is not supported\n");
+	} else if (hbr)
 		return -EINVAL;
+
+	return 0;
+}
+
+static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
+			      hda_nid_t pin_nid, u32 stream_tag, int format)
+{
+	struct hdmi_spec *spec = codec->spec;
+	int err;
+
+	if (is_haswell(codec))
+		haswell_verify_D0(codec, cvt_nid, pin_nid);
+
+	err = spec->ops.pin_hbr_setup(codec, pin_nid, is_hbr_format(format));
+
+	if (err) {
+		snd_printdd("hdmi_setup_stream: HBR is not supported\n");
+		return err;
 	}
 
 	snd_hda_codec_setup_stream(codec, cvt_nid, stream_tag, 0, format);
@@ -1148,7 +1328,16 @@
 	return 0;
 }
 
-static void haswell_config_cvts(struct hda_codec *codec,
+/* Intel HDMI workaround to fix audio routing issue:
+ * For some Intel display codecs, pins share the same connection list.
+ * So a conveter can be selected by multiple pins and playback on any of these
+ * pins will generate sound on the external display, because audio flows from
+ * the same converter to the display pipeline. Also muting one pin may make
+ * other pins have no sound output.
+ * So this function assures that an assigned converter for a pin is not selected
+ * by any other pins.
+ */
+static void intel_not_share_assigned_cvt(struct hda_codec *codec,
 			hda_nid_t pin_nid, int mux_idx)
 {
 	struct hdmi_spec *spec = codec->spec;
@@ -1219,6 +1408,7 @@
 	per_cvt = get_cvt(spec, cvt_idx);
 	/* Claim converter */
 	per_cvt->assigned = 1;
+	per_pin->cvt_nid = per_cvt->cvt_nid;
 	hinfo->nid = per_cvt->cvt_nid;
 
 	snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
@@ -1226,8 +1416,8 @@
 			    mux_idx);
 
 	/* configure unused pins to choose other converters */
-	if (is_haswell(codec))
-		haswell_config_cvts(codec, per_pin->pin_nid, mux_idx);
+	if (is_haswell(codec) || is_valleyview(codec))
+		intel_not_share_assigned_cvt(codec, per_pin->pin_nid, mux_idx);
 
 	snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid);
 
@@ -1285,8 +1475,9 @@
 	return 0;
 }
 
-static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
+static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
 {
+	struct hda_jack_tbl *jack;
 	struct hda_codec *codec = per_pin->codec;
 	struct hdmi_spec *spec = codec->spec;
 	struct hdmi_eld *eld = &spec->temp_eld;
@@ -1303,7 +1494,9 @@
 	int present = snd_hda_pin_sense(codec, pin_nid);
 	bool update_eld = false;
 	bool eld_changed = false;
+	bool ret;
 
+	mutex_lock(&per_pin->lock);
 	pin_eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE);
 	if (pin_eld->monitor_present)
 		eld->eld_valid  = !!(present & AC_PINSENSE_ELDV);
@@ -1315,7 +1508,7 @@
 		codec->addr, pin_nid, pin_eld->monitor_present, eld->eld_valid);
 
 	if (eld->eld_valid) {
-		if (snd_hdmi_get_eld(codec, pin_nid, eld->eld_buffer,
+		if (spec->ops.pin_get_eld(codec, pin_nid, eld->eld_buffer,
 						     &eld->eld_size) < 0)
 			eld->eld_valid = false;
 		else {
@@ -1333,11 +1526,10 @@
 			queue_delayed_work(codec->bus->workq,
 					   &per_pin->work,
 					   msecs_to_jiffies(300));
-			return;
+			goto unlock;
 		}
 	}
 
-	mutex_lock(&pin_eld->lock);
 	if (pin_eld->eld_valid && !eld->eld_valid) {
 		update_eld = true;
 		eld_changed = true;
@@ -1354,20 +1546,29 @@
 		pin_eld->eld_size = eld->eld_size;
 		pin_eld->info = eld->info;
 
-		/* Haswell-specific workaround: re-setup when the transcoder is
-		 * changed during the stream playback
+		/*
+		 * Re-setup pin and infoframe. This is needed e.g. when
+		 * - sink is first plugged-in (infoframe is not set up if !monitor_present)
+		 * - transcoder can change during stream playback on Haswell
 		 */
-		if (is_haswell(codec) &&
-		    eld->eld_valid && !old_eld_valid && per_pin->setup)
+		if (eld->eld_valid && !old_eld_valid && per_pin->setup)
 			hdmi_setup_audio_infoframe(codec, per_pin,
 						   per_pin->non_pcm);
 	}
-	mutex_unlock(&pin_eld->lock);
 
 	if (eld_changed)
 		snd_ctl_notify(codec->bus->card,
 			       SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
 			       &per_pin->eld_ctl->id);
+ unlock:
+	ret = !repoll || !pin_eld->monitor_present || pin_eld->eld_valid;
+
+	jack = snd_hda_jack_tbl_get(codec, pin_nid);
+	if (jack)
+		jack->block_report = !ret;
+
+	mutex_unlock(&per_pin->lock);
+	return ret;
 }
 
 static void hdmi_repoll_eld(struct work_struct *work)
@@ -1378,7 +1579,8 @@
 	if (per_pin->repoll_count++ > 6)
 		per_pin->repoll_count = 0;
 
-	hdmi_present_sense(per_pin, per_pin->repoll_count);
+	if (hdmi_present_sense(per_pin, per_pin->repoll_count))
+		snd_hda_jack_report_sync(per_pin->codec);
 }
 
 static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
@@ -1538,14 +1740,14 @@
 	bool non_pcm;
 
 	non_pcm = check_non_pcm_per_cvt(codec, cvt_nid);
+	mutex_lock(&per_pin->lock);
 	per_pin->channels = substream->runtime->channels;
 	per_pin->setup = true;
 
-	hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels);
-
 	hdmi_setup_audio_infoframe(codec, per_pin, non_pcm);
+	mutex_unlock(&per_pin->lock);
 
-	return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format);
+	return spec->ops.setup_stream(codec, cvt_nid, pin_nid, stream_tag, format);
 }
 
 static int generic_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
@@ -1581,11 +1783,14 @@
 		per_pin = get_pin(spec, pin_idx);
 
 		snd_hda_spdif_ctls_unassign(codec, pin_idx);
+
+		mutex_lock(&per_pin->lock);
 		per_pin->chmap_set = false;
 		memset(per_pin->chmap, 0, sizeof(per_pin->chmap));
 
 		per_pin->setup = false;
 		per_pin->channels = 0;
+		mutex_unlock(&per_pin->lock);
 	}
 
 	return 0;
@@ -1614,14 +1819,40 @@
 	return 0;
 }
 
+static int hdmi_chmap_cea_alloc_validate_get_type(struct cea_channel_speaker_allocation *cap,
+						  int channels)
+{
+	/* If the speaker allocation matches the channel count, it is OK.*/
+	if (cap->channels != channels)
+		return -1;
+
+	/* all channels are remappable freely */
+	return SNDRV_CTL_TLVT_CHMAP_VAR;
+}
+
+static void hdmi_cea_alloc_to_tlv_chmap(struct cea_channel_speaker_allocation *cap,
+					unsigned int *chmap, int channels)
+{
+	int count = 0;
+	int c;
+
+	for (c = 7; c >= 0; c--) {
+		int spk = cap->speakers[c];
+		if (!spk)
+			continue;
+
+		chmap[count++] = spk_to_chmap(spk);
+	}
+
+	WARN_ON(count != channels);
+}
+
 static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 			      unsigned int size, unsigned int __user *tlv)
 {
 	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
 	struct hda_codec *codec = info->private_data;
 	struct hdmi_spec *spec = codec->spec;
-	const unsigned int valid_mask =
-		FL | FR | RL | RR | LFE | FC | RLC | RRC;
 	unsigned int __user *dst;
 	int chs, count = 0;
 
@@ -1632,18 +1863,19 @@
 	size -= 8;
 	dst = tlv + 2;
 	for (chs = 2; chs <= spec->channels_max; chs++) {
-		int i, c;
+		int i;
 		struct cea_channel_speaker_allocation *cap;
 		cap = channel_allocations;
 		for (i = 0; i < ARRAY_SIZE(channel_allocations); i++, cap++) {
 			int chs_bytes = chs * 4;
-			if (cap->channels != chs)
-				continue;
-			if (cap->spk_mask & ~valid_mask)
+			int type = spec->ops.chmap_cea_alloc_validate_get_type(cap, chs);
+			unsigned int tlv_chmap[8];
+
+			if (type < 0)
 				continue;
 			if (size < 8)
 				return -ENOMEM;
-			if (put_user(SNDRV_CTL_TLVT_CHMAP_VAR, dst) ||
+			if (put_user(type, dst) ||
 			    put_user(chs_bytes, dst + 1))
 				return -EFAULT;
 			dst += 2;
@@ -1653,14 +1885,10 @@
 				return -ENOMEM;
 			size -= chs_bytes;
 			count += chs_bytes;
-			for (c = 7; c >= 0; c--) {
-				int spk = cap->speakers[c];
-				if (!spk)
-					continue;
-				if (put_user(spk_to_chmap(spk), dst))
-					return -EFAULT;
-				dst++;
-			}
+			spec->ops.cea_alloc_to_tlv_chmap(cap, tlv_chmap, chs);
+			if (copy_to_user(dst, tlv_chmap, chs_bytes))
+				return -EFAULT;
+			dst += chs;
 		}
 	}
 	if (put_user(count, tlv + 1))
@@ -1694,7 +1922,7 @@
 	unsigned int ctl_idx;
 	struct snd_pcm_substream *substream;
 	unsigned char chmap[8];
-	int i, ca, prepared = 0;
+	int i, err, ca, prepared = 0;
 
 	ctl_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 	substream = snd_pcm_chmap_substream(info, ctl_idx);
@@ -1718,10 +1946,17 @@
 	ca = hdmi_manual_channel_allocation(ARRAY_SIZE(chmap), chmap);
 	if (ca < 0)
 		return -EINVAL;
+	if (spec->ops.chmap_validate) {
+		err = spec->ops.chmap_validate(ca, ARRAY_SIZE(chmap), chmap);
+		if (err)
+			return err;
+	}
+	mutex_lock(&per_pin->lock);
 	per_pin->chmap_set = true;
 	memcpy(per_pin->chmap, chmap, sizeof(chmap));
 	if (prepared)
 		hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm);
+	mutex_unlock(&per_pin->lock);
 
 	return 0;
 }
@@ -1838,12 +2073,11 @@
 
 	for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
 		struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
-		struct hdmi_eld *eld = &per_pin->sink_eld;
 
 		per_pin->codec = codec;
-		mutex_init(&eld->lock);
+		mutex_init(&per_pin->lock);
 		INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld);
-		snd_hda_eld_proc_new(codec, eld, pin_idx);
+		eld_proc_new(per_pin, pin_idx);
 	}
 	return 0;
 }
@@ -1884,10 +2118,9 @@
 
 	for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
 		struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
-		struct hdmi_eld *eld = &per_pin->sink_eld;
 
 		cancel_delayed_work(&per_pin->work);
-		snd_hda_eld_proc_free(codec, eld);
+		eld_proc_free(per_pin);
 	}
 
 	flush_workqueue(codec->bus->workq);
@@ -1924,6 +2157,17 @@
 #endif
 };
 
+static const struct hdmi_ops generic_standard_hdmi_ops = {
+	.pin_get_eld				= snd_hdmi_get_eld,
+	.pin_get_slot_channel			= hdmi_pin_get_slot_channel,
+	.pin_set_slot_channel			= hdmi_pin_set_slot_channel,
+	.pin_setup_infoframe			= hdmi_pin_setup_infoframe,
+	.pin_hbr_setup				= hdmi_pin_hbr_setup,
+	.setup_stream				= hdmi_setup_stream,
+	.chmap_cea_alloc_validate_get_type	= hdmi_chmap_cea_alloc_validate_get_type,
+	.cea_alloc_to_tlv_chmap			= hdmi_cea_alloc_to_tlv_chmap,
+};
+
 
 static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
 					     hda_nid_t nid)
@@ -2006,6 +2250,7 @@
 	if (spec == NULL)
 		return -ENOMEM;
 
+	spec->ops = generic_standard_hdmi_ops;
 	codec->spec = spec;
 	hdmi_array_init(spec, 4);
 
@@ -2561,49 +2806,398 @@
 }
 
 /*
- * ATI-specific implementations
- *
- * FIXME: we may omit the whole this and use the generic code once after
- * it's confirmed to work.
+ * NVIDIA codecs ignore ASP mapping for 2ch - confirmed on:
+ * - 0x10de0015
+ * - 0x10de0040
+ */
+static int nvhdmi_chmap_cea_alloc_validate_get_type(struct cea_channel_speaker_allocation *cap,
+						    int channels)
+{
+	if (cap->ca_index == 0x00 && channels == 2)
+		return SNDRV_CTL_TLVT_CHMAP_FIXED;
+
+	return hdmi_chmap_cea_alloc_validate_get_type(cap, channels);
+}
+
+static int nvhdmi_chmap_validate(int ca, int chs, unsigned char *map)
+{
+	if (ca == 0x00 && (map[0] != SNDRV_CHMAP_FL || map[1] != SNDRV_CHMAP_FR))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int patch_nvhdmi(struct hda_codec *codec)
+{
+	struct hdmi_spec *spec;
+	int err;
+
+	err = patch_generic_hdmi(codec);
+	if (err)
+		return err;
+
+	spec = codec->spec;
+
+	spec->ops.chmap_cea_alloc_validate_get_type =
+		nvhdmi_chmap_cea_alloc_validate_get_type;
+	spec->ops.chmap_validate = nvhdmi_chmap_validate;
+
+	return 0;
+}
+
+/*
+ * ATI/AMD-specific implementations
  */
 
-#define ATIHDMI_CVT_NID		0x02	/* audio converter */
-#define ATIHDMI_PIN_NID		0x03	/* HDMI output pin */
+#define is_amdhdmi_rev3_or_later(codec) \
+	((codec)->vendor_id == 0x1002aa01 && ((codec)->revision_id & 0xff00) >= 0x0300)
+#define has_amd_full_remap_support(codec) is_amdhdmi_rev3_or_later(codec)
 
-static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
-					struct hda_codec *codec,
-					unsigned int stream_tag,
-					unsigned int format,
-					struct snd_pcm_substream *substream)
+/* ATI/AMD specific HDA pin verbs, see the AMD HDA Verbs specification */
+#define ATI_VERB_SET_CHANNEL_ALLOCATION	0x771
+#define ATI_VERB_SET_DOWNMIX_INFO	0x772
+#define ATI_VERB_SET_MULTICHANNEL_01	0x777
+#define ATI_VERB_SET_MULTICHANNEL_23	0x778
+#define ATI_VERB_SET_MULTICHANNEL_45	0x779
+#define ATI_VERB_SET_MULTICHANNEL_67	0x77a
+#define ATI_VERB_SET_HBR_CONTROL	0x77c
+#define ATI_VERB_SET_MULTICHANNEL_1	0x785
+#define ATI_VERB_SET_MULTICHANNEL_3	0x786
+#define ATI_VERB_SET_MULTICHANNEL_5	0x787
+#define ATI_VERB_SET_MULTICHANNEL_7	0x788
+#define ATI_VERB_SET_MULTICHANNEL_MODE	0x789
+#define ATI_VERB_GET_CHANNEL_ALLOCATION	0xf71
+#define ATI_VERB_GET_DOWNMIX_INFO	0xf72
+#define ATI_VERB_GET_MULTICHANNEL_01	0xf77
+#define ATI_VERB_GET_MULTICHANNEL_23	0xf78
+#define ATI_VERB_GET_MULTICHANNEL_45	0xf79
+#define ATI_VERB_GET_MULTICHANNEL_67	0xf7a
+#define ATI_VERB_GET_HBR_CONTROL	0xf7c
+#define ATI_VERB_GET_MULTICHANNEL_1	0xf85
+#define ATI_VERB_GET_MULTICHANNEL_3	0xf86
+#define ATI_VERB_GET_MULTICHANNEL_5	0xf87
+#define ATI_VERB_GET_MULTICHANNEL_7	0xf88
+#define ATI_VERB_GET_MULTICHANNEL_MODE	0xf89
+
+/* AMD specific HDA cvt verbs */
+#define ATI_VERB_SET_RAMP_RATE		0x770
+#define ATI_VERB_GET_RAMP_RATE		0xf70
+
+#define ATI_OUT_ENABLE 0x1
+
+#define ATI_MULTICHANNEL_MODE_PAIRED	0
+#define ATI_MULTICHANNEL_MODE_SINGLE	1
+
+#define ATI_HBR_CAPABLE 0x01
+#define ATI_HBR_ENABLE 0x10
+
+static int atihdmi_pin_get_eld(struct hda_codec *codec, hda_nid_t nid,
+			   unsigned char *buf, int *eld_size)
+{
+	/* call hda_eld.c ATI/AMD-specific function */
+	return snd_hdmi_get_eld_ati(codec, nid, buf, eld_size,
+				    is_amdhdmi_rev3_or_later(codec));
+}
+
+static void atihdmi_pin_setup_infoframe(struct hda_codec *codec, hda_nid_t pin_nid, int ca,
+					int active_channels, int conn_type)
+{
+	snd_hda_codec_write(codec, pin_nid, 0, ATI_VERB_SET_CHANNEL_ALLOCATION, ca);
+}
+
+static int atihdmi_paired_swap_fc_lfe(int pos)
+{
+	/*
+	 * ATI/AMD have automatic FC/LFE swap built-in
+	 * when in pairwise mapping mode.
+	 */
+
+	switch (pos) {
+		/* see channel_allocations[].speakers[] */
+		case 2: return 3;
+		case 3: return 2;
+		default: break;
+	}
+
+	return pos;
+}
+
+static int atihdmi_paired_chmap_validate(int ca, int chs, unsigned char *map)
+{
+	struct cea_channel_speaker_allocation *cap;
+	int i, j;
+
+	/* check that only channel pairs need to be remapped on old pre-rev3 ATI/AMD */
+
+	cap = &channel_allocations[get_channel_allocation_order(ca)];
+	for (i = 0; i < chs; ++i) {
+		int mask = to_spk_mask(map[i]);
+		bool ok = false;
+		bool companion_ok = false;
+
+		if (!mask)
+			continue;
+
+		for (j = 0 + i % 2; j < 8; j += 2) {
+			int chan_idx = 7 - atihdmi_paired_swap_fc_lfe(j);
+			if (cap->speakers[chan_idx] == mask) {
+				/* channel is in a supported position */
+				ok = true;
+
+				if (i % 2 == 0 && i + 1 < chs) {
+					/* even channel, check the odd companion */
+					int comp_chan_idx = 7 - atihdmi_paired_swap_fc_lfe(j + 1);
+					int comp_mask_req = to_spk_mask(map[i+1]);
+					int comp_mask_act = cap->speakers[comp_chan_idx];
+
+					if (comp_mask_req == comp_mask_act)
+						companion_ok = true;
+					else
+						return -EINVAL;
+				}
+				break;
+			}
+		}
+
+		if (!ok)
+			return -EINVAL;
+
+		if (companion_ok)
+			i++; /* companion channel already checked */
+	}
+
+	return 0;
+}
+
+static int atihdmi_pin_set_slot_channel(struct hda_codec *codec, hda_nid_t pin_nid,
+					int hdmi_slot, int stream_channel)
+{
+	int verb;
+	int ati_channel_setup = 0;
+
+	if (hdmi_slot > 7)
+		return -EINVAL;
+
+	if (!has_amd_full_remap_support(codec)) {
+		hdmi_slot = atihdmi_paired_swap_fc_lfe(hdmi_slot);
+
+		/* In case this is an odd slot but without stream channel, do not
+		 * disable the slot since the corresponding even slot could have a
+		 * channel. In case neither have a channel, the slot pair will be
+		 * disabled when this function is called for the even slot. */
+		if (hdmi_slot % 2 != 0 && stream_channel == 0xf)
+			return 0;
+
+		hdmi_slot -= hdmi_slot % 2;
+
+		if (stream_channel != 0xf)
+			stream_channel -= stream_channel % 2;
+	}
+
+	verb = ATI_VERB_SET_MULTICHANNEL_01 + hdmi_slot/2 + (hdmi_slot % 2) * 0x00e;
+
+	/* ati_channel_setup format: [7..4] = stream_channel_id, [1] = mute, [0] = enable */
+
+	if (stream_channel != 0xf)
+		ati_channel_setup = (stream_channel << 4) | ATI_OUT_ENABLE;
+
+	return snd_hda_codec_write(codec, pin_nid, 0, verb, ati_channel_setup);
+}
+
+static int atihdmi_pin_get_slot_channel(struct hda_codec *codec, hda_nid_t pin_nid,
+					int asp_slot)
+{
+	bool was_odd = false;
+	int ati_asp_slot = asp_slot;
+	int verb;
+	int ati_channel_setup;
+
+	if (asp_slot > 7)
+		return -EINVAL;
+
+	if (!has_amd_full_remap_support(codec)) {
+		ati_asp_slot = atihdmi_paired_swap_fc_lfe(asp_slot);
+		if (ati_asp_slot % 2 != 0) {
+			ati_asp_slot -= 1;
+			was_odd = true;
+		}
+	}
+
+	verb = ATI_VERB_GET_MULTICHANNEL_01 + ati_asp_slot/2 + (ati_asp_slot % 2) * 0x00e;
+
+	ati_channel_setup = snd_hda_codec_read(codec, pin_nid, 0, verb, 0);
+
+	if (!(ati_channel_setup & ATI_OUT_ENABLE))
+		return 0xf;
+
+	return ((ati_channel_setup & 0xf0) >> 4) + !!was_odd;
+}
+
+static int atihdmi_paired_chmap_cea_alloc_validate_get_type(struct cea_channel_speaker_allocation *cap,
+							    int channels)
+{
+	int c;
+
+	/*
+	 * Pre-rev3 ATI/AMD codecs operate in a paired channel mode, so
+	 * we need to take that into account (a single channel may take 2
+	 * channel slots if we need to carry a silent channel next to it).
+	 * On Rev3+ AMD codecs this function is not used.
+	 */
+	int chanpairs = 0;
+
+	/* We only produce even-numbered channel count TLVs */
+	if ((channels % 2) != 0)
+		return -1;
+
+	for (c = 0; c < 7; c += 2) {
+		if (cap->speakers[c] || cap->speakers[c+1])
+			chanpairs++;
+	}
+
+	if (chanpairs * 2 != channels)
+		return -1;
+
+	return SNDRV_CTL_TLVT_CHMAP_PAIRED;
+}
+
+static void atihdmi_paired_cea_alloc_to_tlv_chmap(struct cea_channel_speaker_allocation *cap,
+						  unsigned int *chmap, int channels)
+{
+	/* produce paired maps for pre-rev3 ATI/AMD codecs */
+	int count = 0;
+	int c;
+
+	for (c = 7; c >= 0; c--) {
+		int chan = 7 - atihdmi_paired_swap_fc_lfe(7 - c);
+		int spk = cap->speakers[chan];
+		if (!spk) {
+			/* add N/A channel if the companion channel is occupied */
+			if (cap->speakers[chan + (chan % 2 ? -1 : 1)])
+				chmap[count++] = SNDRV_CHMAP_NA;
+
+			continue;
+		}
+
+		chmap[count++] = spk_to_chmap(spk);
+	}
+
+	WARN_ON(count != channels);
+}
+
+static int atihdmi_pin_hbr_setup(struct hda_codec *codec, hda_nid_t pin_nid,
+				 bool hbr)
+{
+	int hbr_ctl, hbr_ctl_new;
+
+	hbr_ctl = snd_hda_codec_read(codec, pin_nid, 0, ATI_VERB_GET_HBR_CONTROL, 0);
+	if (hbr_ctl & ATI_HBR_CAPABLE) {
+		if (hbr)
+			hbr_ctl_new = hbr_ctl | ATI_HBR_ENABLE;
+		else
+			hbr_ctl_new = hbr_ctl & ~ATI_HBR_ENABLE;
+
+		snd_printdd("atihdmi_pin_hbr_setup: "
+				"NID=0x%x, %shbr-ctl=0x%x\n",
+				pin_nid,
+				hbr_ctl == hbr_ctl_new ? "" : "new-",
+				hbr_ctl_new);
+
+		if (hbr_ctl != hbr_ctl_new)
+			snd_hda_codec_write(codec, pin_nid, 0,
+						ATI_VERB_SET_HBR_CONTROL,
+						hbr_ctl_new);
+
+	} else if (hbr)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int atihdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
+				hda_nid_t pin_nid, u32 stream_tag, int format)
+{
+
+	if (is_amdhdmi_rev3_or_later(codec)) {
+		int ramp_rate = 180; /* default as per AMD spec */
+		/* disable ramp-up/down for non-pcm as per AMD spec */
+		if (format & AC_FMT_TYPE_NON_PCM)
+			ramp_rate = 0;
+
+		snd_hda_codec_write(codec, cvt_nid, 0, ATI_VERB_SET_RAMP_RATE, ramp_rate);
+	}
+
+	return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format);
+}
+
+
+static int atihdmi_init(struct hda_codec *codec)
 {
 	struct hdmi_spec *spec = codec->spec;
-	struct hdmi_spec_per_cvt *per_cvt = get_cvt(spec, 0);
-	int chans = substream->runtime->channels;
-	int i, err;
+	int pin_idx, err;
 
-	err = simple_playback_pcm_prepare(hinfo, codec, stream_tag, format,
-					  substream);
-	if (err < 0)
+	err = generic_hdmi_init(codec);
+
+	if (err)
 		return err;
-	snd_hda_codec_write(codec, per_cvt->cvt_nid, 0,
-			    AC_VERB_SET_CVT_CHAN_COUNT, chans - 1);
-	/* FIXME: XXX */
-	for (i = 0; i < chans; i++) {
-		snd_hda_codec_write(codec, per_cvt->cvt_nid, 0,
-				    AC_VERB_SET_HDMI_CHAN_SLOT,
-				    (i << 4) | i);
+
+	for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
+		struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
+
+		/* make sure downmix information in infoframe is zero */
+		snd_hda_codec_write(codec, per_pin->pin_nid, 0, ATI_VERB_SET_DOWNMIX_INFO, 0);
+
+		/* enable channel-wise remap mode if supported */
+		if (has_amd_full_remap_support(codec))
+			snd_hda_codec_write(codec, per_pin->pin_nid, 0,
+					    ATI_VERB_SET_MULTICHANNEL_MODE,
+					    ATI_MULTICHANNEL_MODE_SINGLE);
 	}
+
 	return 0;
 }
 
 static int patch_atihdmi(struct hda_codec *codec)
 {
 	struct hdmi_spec *spec;
-	int err = patch_simple_hdmi(codec, ATIHDMI_CVT_NID, ATIHDMI_PIN_NID);
-	if (err < 0)
+	struct hdmi_spec_per_cvt *per_cvt;
+	int err, cvt_idx;
+
+	err = patch_generic_hdmi(codec);
+
+	if (err)
 		return err;
+
+	codec->patch_ops.init = atihdmi_init;
+
 	spec = codec->spec;
-	spec->pcm_playback.ops.prepare = atihdmi_playback_pcm_prepare;
+
+	spec->ops.pin_get_eld = atihdmi_pin_get_eld;
+	spec->ops.pin_get_slot_channel = atihdmi_pin_get_slot_channel;
+	spec->ops.pin_set_slot_channel = atihdmi_pin_set_slot_channel;
+	spec->ops.pin_setup_infoframe = atihdmi_pin_setup_infoframe;
+	spec->ops.pin_hbr_setup = atihdmi_pin_hbr_setup;
+	spec->ops.setup_stream = atihdmi_setup_stream;
+
+	if (!has_amd_full_remap_support(codec)) {
+		/* override to ATI/AMD-specific versions with pairwise mapping */
+		spec->ops.chmap_cea_alloc_validate_get_type =
+			atihdmi_paired_chmap_cea_alloc_validate_get_type;
+		spec->ops.cea_alloc_to_tlv_chmap = atihdmi_paired_cea_alloc_to_tlv_chmap;
+		spec->ops.chmap_validate = atihdmi_paired_chmap_validate;
+	}
+
+	/* ATI/AMD converters do not advertise all of their capabilities */
+	for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) {
+		per_cvt = get_cvt(spec, cvt_idx);
+		per_cvt->channels_max = max(per_cvt->channels_max, 8u);
+		per_cvt->rates |= SUPPORTED_RATES;
+		per_cvt->formats |= SUPPORTED_FORMATS;
+		per_cvt->maxbps = max(per_cvt->maxbps, 24u);
+	}
+
+	spec->channels_max = max(spec->channels_max, 8u);
+
 	return 0;
 }
 
@@ -2623,7 +3217,7 @@
 { .id = 0x1002793c, .name = "RS600 HDMI",	.patch = patch_atihdmi },
 { .id = 0x10027919, .name = "RS600 HDMI",	.patch = patch_atihdmi },
 { .id = 0x1002791a, .name = "RS690/780 HDMI",	.patch = patch_atihdmi },
-{ .id = 0x1002aa01, .name = "R6xx HDMI",	.patch = patch_generic_hdmi },
+{ .id = 0x1002aa01, .name = "R6xx HDMI",	.patch = patch_atihdmi },
 { .id = 0x10951390, .name = "SiI1390 HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x10951392, .name = "SiI1392 HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x17e80047, .name = "Chrontel HDMI",	.patch = patch_generic_hdmi },
@@ -2632,30 +3226,30 @@
 { .id = 0x10de0005, .name = "MCP77/78 HDMI",	.patch = patch_nvhdmi_8ch_7x },
 { .id = 0x10de0006, .name = "MCP77/78 HDMI",	.patch = patch_nvhdmi_8ch_7x },
 { .id = 0x10de0007, .name = "MCP79/7A HDMI",	.patch = patch_nvhdmi_8ch_7x },
-{ .id = 0x10de000a, .name = "GPU 0a HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de000b, .name = "GPU 0b HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de000c, .name = "MCP89 HDMI",	.patch = patch_generic_hdmi },
-{ .id = 0x10de000d, .name = "GPU 0d HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de0010, .name = "GPU 10 HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de0011, .name = "GPU 11 HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de0012, .name = "GPU 12 HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de0013, .name = "GPU 13 HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de0014, .name = "GPU 14 HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de0015, .name = "GPU 15 HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de0016, .name = "GPU 16 HDMI/DP",	.patch = patch_generic_hdmi },
+{ .id = 0x10de000a, .name = "GPU 0a HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de000b, .name = "GPU 0b HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de000c, .name = "MCP89 HDMI",	.patch = patch_nvhdmi },
+{ .id = 0x10de000d, .name = "GPU 0d HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de0010, .name = "GPU 10 HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de0011, .name = "GPU 11 HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de0012, .name = "GPU 12 HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de0013, .name = "GPU 13 HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de0014, .name = "GPU 14 HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de0015, .name = "GPU 15 HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de0016, .name = "GPU 16 HDMI/DP",	.patch = patch_nvhdmi },
 /* 17 is known to be absent */
-{ .id = 0x10de0018, .name = "GPU 18 HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de0019, .name = "GPU 19 HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de001a, .name = "GPU 1a HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de001b, .name = "GPU 1b HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de001c, .name = "GPU 1c HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de0040, .name = "GPU 40 HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de0041, .name = "GPU 41 HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de0042, .name = "GPU 42 HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de0043, .name = "GPU 43 HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de0044, .name = "GPU 44 HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de0051, .name = "GPU 51 HDMI/DP",	.patch = patch_generic_hdmi },
-{ .id = 0x10de0060, .name = "GPU 60 HDMI/DP",	.patch = patch_generic_hdmi },
+{ .id = 0x10de0018, .name = "GPU 18 HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de0019, .name = "GPU 19 HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de001a, .name = "GPU 1a HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de001b, .name = "GPU 1b HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de001c, .name = "GPU 1c HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de0040, .name = "GPU 40 HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de0041, .name = "GPU 41 HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de0042, .name = "GPU 42 HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de0043, .name = "GPU 43 HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de0044, .name = "GPU 44 HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de0051, .name = "GPU 51 HDMI/DP",	.patch = patch_nvhdmi },
+{ .id = 0x10de0060, .name = "GPU 60 HDMI/DP",	.patch = patch_nvhdmi },
 { .id = 0x10de0067, .name = "MCP67 HDMI",	.patch = patch_nvhdmi_2ch },
 { .id = 0x10de8001, .name = "MCP73 HDMI",	.patch = patch_nvhdmi_2ch },
 { .id = 0x11069f80, .name = "VX900 HDMI/DP",	.patch = patch_via_hdmi },
@@ -2671,6 +3265,7 @@
 { .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi },
 { .id = 0x80862807, .name = "Haswell HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x80862880, .name = "CedarTrail HDMI",	.patch = patch_generic_hdmi },
+{ .id = 0x80862882, .name = "Valleyview2 HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x808629fb, .name = "Crestline HDMI",	.patch = patch_generic_hdmi },
 {} /* terminator */
 };
@@ -2725,6 +3320,7 @@
 MODULE_ALIAS("snd-hda-codec-id:80862806");
 MODULE_ALIAS("snd-hda-codec-id:80862807");
 MODULE_ALIAS("snd-hda-codec-id:80862880");
+MODULE_ALIAS("snd-hda-codec-id:80862882");
 MODULE_ALIAS("snd-hda-codec-id:808629fb");
 
 MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 0e303b9..24d924d 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -554,8 +554,6 @@
 			nid = portd;
 		else if (tmp == 3)
 			nid = porti;
-		else
-			return 1;
 		if (found_in_nid_list(nid, spec->gen.autocfg.line_out_pins,
 				      spec->gen.autocfg.line_outs))
 			return 1;
@@ -579,26 +577,35 @@
 /*
  * COEF access helper functions
  */
-static int alc_read_coef_idx(struct hda_codec *codec,
-			unsigned int coef_idx)
+
+static int alc_read_coefex_idx(struct hda_codec *codec,
+					hda_nid_t nid,
+					unsigned int coef_idx)
 {
 	unsigned int val;
-	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX,
 		    		coef_idx);
-	val = snd_hda_codec_read(codec, 0x20, 0,
+	val = snd_hda_codec_read(codec, nid, 0,
 			 	AC_VERB_GET_PROC_COEF, 0);
 	return val;
 }
 
-static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx,
+#define alc_read_coef_idx(codec, coef_idx) \
+	alc_read_coefex_idx(codec, 0x20, coef_idx)
+
+static void alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
+							unsigned int coef_idx,
 							unsigned int coef_val)
 {
-	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX,
 			    coef_idx);
-	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF,
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PROC_COEF,
 			    coef_val);
 }
 
+#define alc_write_coef_idx(codec, coef_idx, coef_val) \
+	alc_write_coefex_idx(codec, 0x20, coef_idx, coef_val)
+
 /* a special bypass for COEF 0; read the cached value at the second time */
 static unsigned int alc_get_coef0(struct hda_codec *codec)
 {
@@ -831,7 +838,11 @@
 		snd_hda_shutup_pins(codec);
 }
 
-#define alc_free	snd_hda_gen_free
+static void alc_free(struct hda_codec *codec)
+{
+	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE);
+	snd_hda_gen_free(codec);
+}
 
 #ifdef CONFIG_PM
 static void alc_power_eapd(struct hda_codec *codec)
@@ -1043,6 +1054,7 @@
 	ALC880_FIXUP_UNIWILL,
 	ALC880_FIXUP_UNIWILL_DIG,
 	ALC880_FIXUP_Z71V,
+	ALC880_FIXUP_ASUS_W5A,
 	ALC880_FIXUP_3ST_BASE,
 	ALC880_FIXUP_3ST,
 	ALC880_FIXUP_3ST_DIG,
@@ -1213,6 +1225,26 @@
 			{ }
 		}
 	},
+	[ALC880_FIXUP_ASUS_W5A] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			/* set up the whole pins as BIOS is utterly broken */
+			{ 0x14, 0x0121411f }, /* HP */
+			{ 0x15, 0x411111f0 }, /* N/A */
+			{ 0x16, 0x411111f0 }, /* N/A */
+			{ 0x17, 0x411111f0 }, /* N/A */
+			{ 0x18, 0x90a60160 }, /* mic */
+			{ 0x19, 0x411111f0 }, /* N/A */
+			{ 0x1a, 0x411111f0 }, /* N/A */
+			{ 0x1b, 0x411111f0 }, /* N/A */
+			{ 0x1c, 0x411111f0 }, /* N/A */
+			{ 0x1d, 0x411111f0 }, /* N/A */
+			{ 0x1e, 0xb743111e }, /* SPDIF out */
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC880_FIXUP_GPIO1,
+	},
 	[ALC880_FIXUP_3ST_BASE] = {
 		.type = HDA_FIXUP_PINS,
 		.v.pins = (const struct hda_pintbl[]) {
@@ -1334,6 +1366,7 @@
 
 static const struct snd_pci_quirk alc880_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810),
+	SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS W5A", ALC880_FIXUP_ASUS_W5A),
 	SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V),
 	SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_FIXUP_GPIO1),
 	SND_PCI_QUIRK(0x1558, 0x5401, "Clevo GPIO2", ALC880_FIXUP_GPIO2),
@@ -2388,6 +2421,7 @@
 enum {
 	ALC268_FIXUP_INV_DMIC,
 	ALC268_FIXUP_HP_EAPD,
+	ALC268_FIXUP_SPDIF,
 };
 
 static const struct hda_fixup alc268_fixups[] = {
@@ -2402,6 +2436,13 @@
 			{}
 		}
 	},
+	[ALC268_FIXUP_SPDIF] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			{ 0x1e, 0x014b1180 }, /* enable SPDIF out */
+			{}
+		}
+	},
 };
 
 static const struct hda_model_fixup alc268_fixup_models[] = {
@@ -2411,6 +2452,7 @@
 };
 
 static const struct snd_pci_quirk alc268_fixup_tbl[] = {
+	SND_PCI_QUIRK(0x1025, 0x0139, "Acer TravelMate 6293", ALC268_FIXUP_SPDIF),
 	SND_PCI_QUIRK(0x1025, 0x015b, "Acer AOA 150 (ZG5)", ALC268_FIXUP_INV_DMIC),
 	/* below is codec SSID since multiple Toshiba laptops have the
 	 * same PCI SSID 1179:ff00
@@ -2539,7 +2581,9 @@
 	ALC269_TYPE_ALC282,
 	ALC269_TYPE_ALC283,
 	ALC269_TYPE_ALC284,
+	ALC269_TYPE_ALC285,
 	ALC269_TYPE_ALC286,
+	ALC269_TYPE_ALC255,
 };
 
 /*
@@ -2558,6 +2602,7 @@
 	case ALC269_TYPE_ALC269VC:
 	case ALC269_TYPE_ALC280:
 	case ALC269_TYPE_ALC284:
+	case ALC269_TYPE_ALC285:
 		ssids = alc269va_ssids;
 		break;
 	case ALC269_TYPE_ALC269VB:
@@ -2565,6 +2610,7 @@
 	case ALC269_TYPE_ALC282:
 	case ALC269_TYPE_ALC283:
 	case ALC269_TYPE_ALC286:
+	case ALC269_TYPE_ALC255:
 		ssids = alc269_ssids;
 		break;
 	default:
@@ -2652,7 +2698,7 @@
 			    AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
 
 	if (hp_pin_sense)
-		msleep(85);
+		msleep(100);
 
 	snd_hda_codec_write(codec, hp_pin, 0,
 			    AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
@@ -2661,7 +2707,7 @@
 	alc_write_coef_idx(codec, 0x46, val | (3 << 12));
 
 	if (hp_pin_sense)
-		msleep(85);
+		msleep(100);
 	snd_hda_shutup_pins(codec);
 	alc_write_coef_idx(codec, 0x43, 0x9614);
 }
@@ -2819,6 +2865,15 @@
 	alc_write_coef_idx(codec, 0x1e, coef | 0x80);
 }
 
+static void alc269_fixup_headset_mic(struct hda_codec *codec,
+				       const struct hda_fixup *fix, int action)
+{
+	struct alc_spec *spec = codec->spec;
+
+	if (action == HDA_FIXUP_ACT_PRE_PROBE)
+		spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
+}
+
 static void alc271_fixup_dmic(struct hda_codec *codec,
 			      const struct hda_fixup *fix, int action)
 {
@@ -2935,6 +2990,23 @@
 		snd_hda_set_pin_ctl_cache(codec, spec->mute_led_nid, pinval);
 }
 
+/* Make sure the led works even in runtime suspend */
+static unsigned int led_power_filter(struct hda_codec *codec,
+						  hda_nid_t nid,
+						  unsigned int power_state)
+{
+	struct alc_spec *spec = codec->spec;
+
+	if (power_state != AC_PWRST_D3 || nid != spec->mute_led_nid)
+		return power_state;
+
+	/* Set pin ctl again, it might have just been set to 0 */
+	snd_hda_set_pin_ctl(codec, nid,
+			    snd_hda_codec_get_pin_target(codec, nid));
+
+	return AC_PWRST_D0;
+}
+
 static void alc269_fixup_hp_mute_led(struct hda_codec *codec,
 				     const struct hda_fixup *fix, int action)
 {
@@ -2954,6 +3026,7 @@
 		spec->mute_led_nid = pin - 0x0a + 0x18;
 		spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
 		spec->gen.vmaster_mute_enum = 1;
+		codec->power_filter = led_power_filter;
 		snd_printd("Detected mute LED for %x:%d\n", spec->mute_led_nid,
 			   spec->mute_led_polarity);
 		break;
@@ -2969,6 +3042,7 @@
 		spec->mute_led_nid = 0x18;
 		spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
 		spec->gen.vmaster_mute_enum = 1;
+		codec->power_filter = led_power_filter;
 	}
 }
 
@@ -2981,6 +3055,7 @@
 		spec->mute_led_nid = 0x19;
 		spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
 		spec->gen.vmaster_mute_enum = 1;
+		codec->power_filter = led_power_filter;
 	}
 }
 
@@ -3043,6 +3118,19 @@
 	int val;
 
 	switch (codec->vendor_id) {
+	case 0x10ec0255:
+		/* LDO and MISC control */
+		alc_write_coef_idx(codec, 0x1b, 0x0c0b);
+		/* UAJ function set to menual mode */
+		alc_write_coef_idx(codec, 0x45, 0xd089);
+		/* Direct Drive HP Amp control(Set to verb control)*/
+		val = alc_read_coefex_idx(codec, 0x57, 0x05);
+		alc_write_coefex_idx(codec, 0x57, 0x05, val & ~(1<<14));
+		/* Set MIC2 Vref gate with HP */
+		alc_write_coef_idx(codec, 0x06, 0x6104);
+		/* Direct Drive HP Amp control */
+		alc_write_coefex_idx(codec, 0x57, 0x03, 0x8aa6);
+		break;
 	case 0x10ec0283:
 		alc_write_coef_idx(codec, 0x1b, 0x0c0b);
 		alc_write_coef_idx(codec, 0x45, 0xc429);
@@ -3074,6 +3162,14 @@
 	int val;
 
 	switch (codec->vendor_id) {
+	case 0x10ec0255:
+		alc_write_coef_idx(codec, 0x45, 0xc489);
+		snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
+		alc_write_coefex_idx(codec, 0x57, 0x03, 0x8aa6);
+		/* Set MIC2 Vref gate to normal */
+		alc_write_coef_idx(codec, 0x06, 0x6100);
+		snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
+		break;
 	case 0x10ec0283:
 		alc_write_coef_idx(codec, 0x45, 0xc429);
 		snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
@@ -3105,6 +3201,12 @@
 static void alc_headset_mode_default(struct hda_codec *codec)
 {
 	switch (codec->vendor_id) {
+	case 0x10ec0255:
+		alc_write_coef_idx(codec, 0x45, 0xc089);
+		alc_write_coef_idx(codec, 0x45, 0xc489);
+		alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6);
+		alc_write_coef_idx(codec, 0x49, 0x0049);
+		break;
 	case 0x10ec0283:
 		alc_write_coef_idx(codec, 0x06, 0x2100);
 		alc_write_coef_idx(codec, 0x32, 0x4ea3);
@@ -3128,6 +3230,12 @@
 static void alc_headset_mode_ctia(struct hda_codec *codec)
 {
 	switch (codec->vendor_id) {
+	case 0x10ec0255:
+		/* Set to CTIA type */
+		alc_write_coef_idx(codec, 0x45, 0xd489);
+		alc_write_coef_idx(codec, 0x1b, 0x0c2b);
+		alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6);
+		break;
 	case 0x10ec0283:
 		alc_write_coef_idx(codec, 0x45, 0xd429);
 		alc_write_coef_idx(codec, 0x1b, 0x0c2b);
@@ -3150,6 +3258,12 @@
 static void alc_headset_mode_omtp(struct hda_codec *codec)
 {
 	switch (codec->vendor_id) {
+	case 0x10ec0255:
+		/* Set to OMTP Type */
+		alc_write_coef_idx(codec, 0x45, 0xe489);
+		alc_write_coef_idx(codec, 0x1b, 0x0c2b);
+		alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6);
+		break;
 	case 0x10ec0283:
 		alc_write_coef_idx(codec, 0x45, 0xe429);
 		alc_write_coef_idx(codec, 0x1b, 0x0c2b);
@@ -3175,6 +3289,15 @@
 	struct alc_spec *spec = codec->spec;
 
 	switch (codec->vendor_id) {
+	case 0x10ec0255:
+		/* combo jack auto switch control(Check type)*/
+		alc_write_coef_idx(codec, 0x45, 0xd089);
+		/* combo jack auto switch control(Vref conteol) */
+		alc_write_coef_idx(codec, 0x49, 0x0149);
+		msleep(300);
+		val = alc_read_coef_idx(codec, 0x46);
+		is_ctia = (val & 0x0070) == 0x0070;
+		break;
 	case 0x10ec0283:
 		alc_write_coef_idx(codec, 0x45, 0xd029);
 		msleep(300);
@@ -3321,6 +3444,21 @@
 		alc_fixup_headset_mode(codec, fix, action);
 }
 
+static void alc_fixup_headset_mode_alc255(struct hda_codec *codec,
+				const struct hda_fixup *fix, int action)
+{
+	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+		/* Set to iphone type */
+		alc_write_coef_idx(codec, 0x1b, 0x880b);
+		alc_write_coef_idx(codec, 0x45, 0xd089);
+		alc_write_coef_idx(codec, 0x1b, 0x080b);
+		alc_write_coef_idx(codec, 0x46, 0x0004);
+		alc_write_coef_idx(codec, 0x1b, 0x0c0b);
+		msleep(30);
+	}
+	alc_fixup_headset_mode(codec, fix, action);
+}
+
 static void alc_fixup_headset_mode_alc668(struct hda_codec *codec,
 				const struct hda_fixup *fix, int action)
 {
@@ -3434,7 +3572,11 @@
 	switch (action) {
 	case HDA_FIXUP_ACT_PRE_PROBE:
 		alc283_chromebook_caps(codec);
+		/* Disable AA-loopback as it causes white noise */
+		spec->gen.mixer_nid = 0;
 		spec->gen.hp_automute_hook = alc283_hp_automute_hook;
+		break;
+	case HDA_FIXUP_ACT_INIT:
 		/* MIC2-VREF control */
 		/* Set to manual mode */
 		val = alc_read_coef_idx(codec, 0x06);
@@ -3496,6 +3638,83 @@
 	}
 }
 
+static void alc290_fixup_mono_speakers(struct hda_codec *codec,
+				       const struct hda_fixup *fix, int action)
+{
+	if (action == HDA_FIXUP_ACT_PRE_PROBE)
+		/* Remove DAC node 0x03, as it seems to be
+		   giving mono output */
+		snd_hda_override_wcaps(codec, 0x03, 0);
+}
+
+#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
+
+#include <linux/thinkpad_acpi.h>
+
+static int (*led_set_func)(int, bool);
+
+static void update_tpacpi_mute_led(void *private_data, int enabled)
+{
+	if (led_set_func)
+		led_set_func(TPACPI_LED_MUTE, !enabled);
+}
+
+static void update_tpacpi_micmute_led(struct hda_codec *codec,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	if (!ucontrol || !led_set_func)
+		return;
+	if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
+		/* TODO: How do I verify if it's a mono or stereo here? */
+		bool val = ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1];
+		led_set_func(TPACPI_LED_MICMUTE, !val);
+	}
+}
+
+static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
+				  const struct hda_fixup *fix, int action)
+{
+	struct alc_spec *spec = codec->spec;
+	bool removefunc = false;
+
+	if (action == HDA_FIXUP_ACT_PROBE) {
+		if (!led_set_func)
+			led_set_func = symbol_request(tpacpi_led_set);
+		if (!led_set_func) {
+			snd_printk(KERN_WARNING "Failed to find thinkpad-acpi symbol tpacpi_led_set\n");
+			return;
+		}
+
+		removefunc = true;
+		if (led_set_func(TPACPI_LED_MUTE, false) >= 0) {
+			spec->gen.vmaster_mute.hook = update_tpacpi_mute_led;
+			removefunc = false;
+		}
+		if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) {
+			if (spec->gen.num_adc_nids > 1)
+				snd_printdd("Skipping micmute LED control due to several ADCs");
+			else {
+				spec->gen.cap_sync_hook = update_tpacpi_micmute_led;
+				removefunc = false;
+			}
+		}
+	}
+
+	if (led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
+		symbol_put(tpacpi_led_set);
+		led_set_func = NULL;
+	}
+}
+
+#else
+
+static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
+				  const struct hda_fixup *fix, int action)
+{
+}
+
+#endif
+
 enum {
 	ALC269_FIXUP_SONY_VAIO,
 	ALC275_FIXUP_SONY_VAIO_GPIO2,
@@ -3507,6 +3726,7 @@
 	ALC271_FIXUP_DMIC,
 	ALC269_FIXUP_PCM_44K,
 	ALC269_FIXUP_STEREO_DMIC,
+	ALC269_FIXUP_HEADSET_MIC,
 	ALC269_FIXUP_QUANTA_MUTE,
 	ALC269_FIXUP_LIFEBOOK,
 	ALC269_FIXUP_AMIC,
@@ -3519,9 +3739,11 @@
 	ALC269_FIXUP_HP_GPIO_LED,
 	ALC269_FIXUP_INV_DMIC,
 	ALC269_FIXUP_LENOVO_DOCK,
+	ALC286_FIXUP_SONY_MIC_NO_PRESENCE,
 	ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT,
 	ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
 	ALC269_FIXUP_DELL2_MIC_NO_PRESENCE,
+	ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
 	ALC269_FIXUP_HEADSET_MODE,
 	ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC,
 	ALC269_FIXUP_ASUS_X101_FUNC,
@@ -3531,10 +3753,15 @@
 	ALC271_FIXUP_HP_GATE_MIC_JACK,
 	ALC269_FIXUP_ACER_AC700,
 	ALC269_FIXUP_LIMIT_INT_MIC_BOOST,
+	ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED,
 	ALC269VB_FIXUP_ORDISSIMO_EVE2,
 	ALC283_FIXUP_CHROME_BOOK,
 	ALC282_FIXUP_ASUS_TX300,
 	ALC283_FIXUP_INT_MIC,
+	ALC290_FIXUP_MONO_SPEAKERS,
+	ALC269_FIXUP_THINKPAD_ACPI,
+	ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+	ALC255_FIXUP_HEADSET_MODE,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -3603,6 +3830,10 @@
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc269_fixup_stereo_dmic,
 	},
+	[ALC269_FIXUP_HEADSET_MIC] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc269_fixup_headset_mic,
+	},
 	[ALC269_FIXUP_QUANTA_MUTE] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc269_fixup_quanta_mute,
@@ -3712,6 +3943,15 @@
 		.chained = true,
 		.chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
 	},
+	[ALC269_FIXUP_DELL3_MIC_NO_PRESENCE] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			{ 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
+	},
 	[ALC269_FIXUP_HEADSET_MODE] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc_fixup_headset_mode,
@@ -3720,6 +3960,15 @@
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc_fixup_headset_mode_no_hp_mic,
 	},
+	[ALC286_FIXUP_SONY_MIC_NO_PRESENCE] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			{ 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC269_FIXUP_HEADSET_MIC
+	},
 	[ALC269_FIXUP_ASUS_X101_FUNC] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc269_fixup_x101_headset_mic,
@@ -3777,6 +4026,12 @@
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc269_fixup_limit_int_mic_boost,
 	},
+	[ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc269_fixup_limit_int_mic_boost,
+		.chained = true,
+		.chain_id = ALC269_FIXUP_HP_MUTE_LED_MIC1,
+	},
 	[ALC269VB_FIXUP_ORDISSIMO_EVE2] = {
 		.type = HDA_FIXUP_PINS,
 		.v.pins = (const struct hda_pintbl[]) {
@@ -3804,6 +4059,32 @@
 		.chained = true,
 		.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
 	},
+	[ALC290_FIXUP_MONO_SPEAKERS] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc290_fixup_mono_speakers,
+		.chained = true,
+		.chain_id = ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
+	},
+	[ALC269_FIXUP_THINKPAD_ACPI] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc_fixup_thinkpad_acpi,
+		.chained = true,
+		.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
+	},
+	[ALC255_FIXUP_DELL1_MIC_NO_PRESENCE] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			{ 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
+			{ 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
+			{ }
+		},
+		.chained = true,
+		.chain_id = ALC255_FIXUP_HEADSET_MODE
+	},
+	[ALC255_FIXUP_HEADSET_MODE] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc_fixup_headset_mode_alc255,
+	},
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -3845,12 +4126,16 @@
 	SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+	SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_MONO_SPEAKERS),
+	SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
+	SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
 	SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED),
 	SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED),
 	SND_PCI_QUIRK(0x103c, 0x21ed, "HP Falco Chromebook", ALC283_FIXUP_CHROME_BOOK),
 	SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
 	SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
@@ -3867,6 +4152,7 @@
 	SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
 	SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
 	SND_PCI_QUIRK(0x1043, 0x8516, "ASUS X101CH", ALC269_FIXUP_ASUS_X101),
+	SND_PCI_QUIRK(0x104d, 0x90b6, "Sony VAIO Pro 13", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
 	SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
 	SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
@@ -3885,7 +4171,7 @@
 	SND_PCI_QUIRK(0x17aa, 0x2208, "Thinkpad T431s", ALC269_FIXUP_LENOVO_DOCK),
 	SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
 	SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
-	SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
+	SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_THINKPAD_ACPI),
 	SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
 	SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
 	SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC),
@@ -3952,6 +4238,7 @@
 	{.id = ALC269_FIXUP_STEREO_DMIC, .name = "alc269-dmic"},
 	{.id = ALC271_FIXUP_DMIC, .name = "alc271-dmic"},
 	{.id = ALC269_FIXUP_INV_DMIC, .name = "inv-dmic"},
+	{.id = ALC269_FIXUP_HEADSET_MIC, .name = "headset-mic"},
 	{.id = ALC269_FIXUP_LENOVO_DOCK, .name = "lenovo-dock"},
 	{.id = ALC269_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"},
 	{.id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
@@ -4072,9 +4359,16 @@
 	case 0x10ec0292:
 		spec->codec_variant = ALC269_TYPE_ALC284;
 		break;
+	case 0x10ec0285:
+	case 0x10ec0293:
+		spec->codec_variant = ALC269_TYPE_ALC285;
+		break;
 	case 0x10ec0286:
 		spec->codec_variant = ALC269_TYPE_ALC286;
 		break;
+	case 0x10ec0255:
+		spec->codec_variant = ALC269_TYPE_ALC255;
+		break;
 	}
 
 	if (snd_hda_codec_read(codec, 0x51, 0, AC_VERB_PARAMETERS, 0) == 0x10ec5505) {
@@ -4362,6 +4656,25 @@
 		       "hda_codec: failed to override amp caps for NID 0x2\n");
 }
 
+static const struct snd_pcm_chmap_elem asus_pcm_2_1_chmaps[] = {
+	{ .channels = 2,
+	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
+	{ .channels = 4,
+	  .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
+		   SNDRV_CHMAP_NA, SNDRV_CHMAP_LFE } }, /* LFE only on right */
+	{ }
+};
+
+/* override the 2.1 chmap */
+static void alc662_fixup_bass_chmap(struct hda_codec *codec,
+				    const struct hda_fixup *fix, int action)
+{
+	if (action == HDA_FIXUP_ACT_BUILD) {
+		struct alc_spec *spec = codec->spec;
+		spec->gen.pcm_rec[0].stream[0].chmap = asus_pcm_2_1_chmaps;
+	}
+}
+
 enum {
 	ALC662_FIXUP_ASPIRE,
 	ALC662_FIXUP_IDEAPAD,
@@ -4382,6 +4695,7 @@
 	ALC662_FIXUP_INV_DMIC,
 	ALC668_FIXUP_DELL_MIC_NO_PRESENCE,
 	ALC668_FIXUP_HEADSET_MODE,
+	ALC662_FIXUP_BASS_CHMAP,
 };
 
 static const struct hda_fixup alc662_fixups[] = {
@@ -4556,6 +4870,12 @@
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc_fixup_headset_mode_alc668,
 	},
+	[ALC662_FIXUP_BASS_CHMAP] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc662_fixup_bass_chmap,
+		.chained = true,
+		.chain_id = ALC662_FIXUP_ASUS_MODE4
+	},
 };
 
 static const struct snd_pci_quirk alc662_fixup_tbl[] = {
@@ -4568,7 +4888,10 @@
 	SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
 	SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
+	SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
+	SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_CHMAP),
+	SND_PCI_QUIRK(0x1043, 0x1bf3, "ASUS N76VZ", ALC662_FIXUP_BASS_CHMAP),
 	SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT),
 	SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),
 	SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
@@ -4787,6 +5110,7 @@
 static const struct hda_codec_preset snd_hda_preset_realtek[] = {
 	{ .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
 	{ .id = 0x10ec0233, .name = "ALC233", .patch = patch_alc269 },
+	{ .id = 0x10ec0255, .name = "ALC255", .patch = patch_alc269 },
 	{ .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
 	{ .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
 	{ .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
@@ -4800,9 +5124,11 @@
 	{ .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 },
 	{ .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 },
 	{ .id = 0x10ec0284, .name = "ALC284", .patch = patch_alc269 },
+	{ .id = 0x10ec0285, .name = "ALC285", .patch = patch_alc269 },
 	{ .id = 0x10ec0286, .name = "ALC286", .patch = patch_alc269 },
 	{ .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 },
 	{ .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 },
+	{ .id = 0x10ec0293, .name = "ALC293", .patch = patch_alc269 },
 	{ .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
 	  .patch = patch_alc861 },
 	{ .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index fba0cef..69a549a 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -2091,8 +2091,10 @@
 {
 	struct sigmatel_spec *spec = codec->spec;
 
-	if (action == HDA_FIXUP_ACT_PRE_PROBE)
+	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 		spec->mic_mute_led_gpio = 0x08; /* GPIO3 */
+		codec->bus->avoid_link_reset = 1;
+	}
 }
 
 static void stac92hd83xxx_fixup_headset_jack(struct hda_codec *codec,
diff --git a/sound/pci/ice1712/psc724.c b/sound/pci/ice1712/psc724.c
index 302ac6d..4019cf2 100644
--- a/sound/pci/ice1712/psc724.c
+++ b/sound/pci/ice1712/psc724.c
@@ -203,12 +203,12 @@
 	/* notify about master speaker mute change */
 	memset(&elem_id, 0, sizeof(elem_id));
 	elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-	strncpy(elem_id.name, "Master Speakers Playback Switch",
+	strlcpy(elem_id.name, "Master Speakers Playback Switch",
 						sizeof(elem_id.name));
 	kctl = snd_ctl_find_id(ice->card, &elem_id);
 	snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
 	/* and headphone mute change */
-	strncpy(elem_id.name, spec->wm8776.ctl[WM8776_CTL_HP_SW].name,
+	strlcpy(elem_id.name, spec->wm8776.ctl[WM8776_CTL_HP_SW].name,
 						sizeof(elem_id.name));
 	kctl = snd_ctl_find_id(ice->card, &elem_id);
 	snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
diff --git a/sound/pci/ice1712/quartet.c b/sound/pci/ice1712/quartet.c
index 975e035..71c6003 100644
--- a/sound/pci/ice1712/quartet.c
+++ b/sound/pci/ice1712/quartet.c
@@ -203,6 +203,7 @@
 #define AK4620_DEEMVOL_REG	0x03
 #define AK4620_SMUTE		(1<<7)
 
+#ifdef CONFIG_PROC_FS
 /*
  * Conversion from int value to its binary form. Used for debugging.
  * The output buffer must be allocated prior to calling the function.
@@ -227,6 +228,7 @@
 	buffer[pos] = '\0';
 	return buffer;
 }
+#endif /* CONFIG_PROC_FS */
 
 /*
  * Initial setup of the conversion array GPIO <-> rate
diff --git a/sound/pci/ice1712/wm8766.c b/sound/pci/ice1712/wm8766.c
index e473f8a..21b373b 100644
--- a/sound/pci/ice1712/wm8766.c
+++ b/sound/pci/ice1712/wm8766.c
@@ -253,7 +253,8 @@
 	}
 	if (wm->ctl[n].flags & WM8766_FLAG_INVERT) {
 		val1 = wm->ctl[n].max - (val1 - wm->ctl[n].min);
-		val2 = wm->ctl[n].max - (val2 - wm->ctl[n].min);
+		if (wm->ctl[n].flags & WM8766_FLAG_STEREO)
+			val2 = wm->ctl[n].max - (val2 - wm->ctl[n].min);
 	}
 	ucontrol->value.integer.value[0] = val1;
 	if (wm->ctl[n].flags & WM8766_FLAG_STEREO)
diff --git a/sound/pci/ice1712/wm8776.c b/sound/pci/ice1712/wm8776.c
index a3c05fe..e66c0da 100644
--- a/sound/pci/ice1712/wm8776.c
+++ b/sound/pci/ice1712/wm8776.c
@@ -52,7 +52,7 @@
 	unsigned int index_offset;
 
 	memset(&elem_id, 0, sizeof(elem_id));
-	strncpy(elem_id.name, ctl_name, sizeof(elem_id.name));
+	strlcpy(elem_id.name, ctl_name, sizeof(elem_id.name));
 	elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 	kctl = snd_ctl_find_id(card, &elem_id);
 	if (!kctl)
@@ -526,7 +526,8 @@
 	}
 	if (wm->ctl[n].flags & WM8776_FLAG_INVERT) {
 		val1 = wm->ctl[n].max - (val1 - wm->ctl[n].min);
-		val2 = wm->ctl[n].max - (val2 - wm->ctl[n].min);
+		if (wm->ctl[n].flags & WM8776_FLAG_STEREO)
+			val2 = wm->ctl[n].max - (val2 - wm->ctl[n].min);
 	}
 	ucontrol->value.integer.value[0] = val1;
 	if (wm->ctl[n].flags & WM8776_FLAG_STEREO)
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 59c8aae..08d8733 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -1541,17 +1541,16 @@
 					      snd_dma_pci_data(chip->pci),
 					      rec->prealloc_size, rec->prealloc_max_size);
 
-	if (rec->ac97_idx == ICHD_PCMOUT && rec->playback_ops) {
+	if (rec->playback_ops &&
+	    rec->playback_ops->open == snd_intel8x0_playback_open) {
 		struct snd_pcm_chmap *chmap;
 		int chs = 2;
-		if (rec->ac97_idx == ICHD_PCMOUT) {
-			if (chip->multi8)
-				chs = 8;
-			else if (chip->multi6)
-				chs = 6;
-			else if (chip->multi4)
-				chs = 4;
-		}
+		if (chip->multi8)
+			chs = 8;
+		else if (chip->multi6)
+			chs = 6;
+		else if (chip->multi4)
+			chs = 4;
 		err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 					     snd_pcm_alt_chmaps, chs, 0,
 					     &chmap);
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c
index 7307d97..0568540 100644
--- a/sound/pci/lola/lola.c
+++ b/sound/pci/lola/lola.c
@@ -463,7 +463,7 @@
 
 	err = lola_read_param(chip, 1, LOLA_PAR_FUNCTION_TYPE, &val);
 	if (err < 0) {
-		printk(KERN_ERR SFX "Can't read FUNCTION_TYPE for 0x%x\n", nid);
+		printk(KERN_ERR SFX "Can't read FUNCTION_TYPE\n");
 		return err;
 	}
 	if (val != 1) {
diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c
index 3230e57..5fcaaa6 100644
--- a/sound/pci/lx6464es/lx6464es.c
+++ b/sound/pci/lx6464es/lx6464es.c
@@ -453,8 +453,8 @@
 				     lower_32_bits(buf), upper_32_bits(buf),
 				     &buffer_index);
 
-		snd_printdd(LXP "starting: buffer index %x on %p (%d bytes)\n",
-			    buffer_index, (void *)buf, period_bytes);
+		snd_printdd(LXP "starting: buffer index %x on 0x%lx (%d bytes)\n",
+			    buffer_index, (unsigned long)buf, period_bytes);
 		buf += period_bytes;
 	}
 
diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c
index 633c860..626ecad 100644
--- a/sound/pci/lx6464es/lx_core.c
+++ b/sound/pci/lx6464es/lx_core.c
@@ -1191,8 +1191,8 @@
 	unpack_pointer(buf, &buf_lo, &buf_hi);
 	err = lx_buffer_give(chip, 0, is_capture, period_bytes, buf_lo, buf_hi,
 			     &buffer_index);
-	snd_printdd(LXP "interrupt: gave buffer index %x on %p (%d bytes)\n",
-		    buffer_index, (void *)buf, period_bytes);
+	snd_printdd(LXP "interrupt: gave buffer index %x on 0x%lx (%d bytes)\n",
+		    buffer_index, (unsigned long)buf, period_bytes);
 
 	lx_stream->frame_pos = next_pos;
 	spin_unlock_irqrestore(&chip->lock, flags);
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index bb9ebc5..0236363 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -350,9 +350,8 @@
 	struct rme96 *rme96 = snd_pcm_substream_chip(substream);
 	count <<= rme96->playback_frlog;
 	pos <<= rme96->playback_frlog;
-	copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src,
-			    count);
-	return 0;
+	return copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src,
+				   count);
 }
 
 static int
@@ -365,9 +364,8 @@
 	struct rme96 *rme96 = snd_pcm_substream_chip(substream);
 	count <<= rme96->capture_frlog;
 	pos <<= rme96->capture_frlog;
-	copy_to_user_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos,
-			    count);
-        return 0;
+	return copy_to_user_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos,
+				   count);
 }
 
 /*
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 4f255df..f59a321 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -4845,6 +4845,7 @@
 			if ((err = hdsp_get_iobox_version(hdsp)) < 0)
 				return err;
 		}
+		memset(&hdsp_version, 0, sizeof(hdsp_version));
 		hdsp_version.io_type = hdsp->io_type;
 		hdsp_version.firmware_rev = hdsp->firmware_rev;
 		if ((err = copy_to_user(argp, &hdsp_version, sizeof(hdsp_version))))
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 3cde55b..e98dc00 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -3996,7 +3996,6 @@
 					return 1;
 			}
 			return 0;
-			break;
 		case AES32:
 			status = hdspm_read(hdspm, HDSPM_statusRegister);
 			if (status & HDSPM_tcoLockAes) {
@@ -4006,9 +4005,6 @@
 					return 1;
 			}
 			return 0;
-
-			break;
-
 		case RayDAT:
 		case AIO:
 			status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
@@ -4018,7 +4014,6 @@
 			if (status & 0x4000000)
 				return 1; /* Lock */
 			return 0; /* No signal */
-			break;
 
 		default:
 			break;
@@ -6405,7 +6400,7 @@
 		memset(&hdspm_version, 0, sizeof(hdspm_version));
 
 		hdspm_version.card_type = hdspm->io_type;
-		strncpy(hdspm_version.cardname, hdspm->card_name,
+		strlcpy(hdspm_version.cardname, hdspm->card_name,
 				sizeof(hdspm_version.cardname));
 		hdspm_version.serial = hdspm->serial;
 		hdspm_version.firmware_rev = hdspm->firmware_rev;
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index c93fbbb..7a43c0c 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -28,6 +28,8 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <sound/core.h>
 #include "pmac.h"
 #include <sound/pcm_params.h>
diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c
index 8c7dcbe..ebb76f2 100644
--- a/sound/ppc/snd_ps3.c
+++ b/sound/ppc/snd_ps3.c
@@ -933,8 +933,10 @@
 	int i, ret;
 	u64 lpar_addr, lpar_size;
 
-	BUG_ON(!firmware_has_feature(FW_FEATURE_PS3_LV1));
-	BUG_ON(dev->match_id != PS3_MATCH_ID_SOUND);
+	if (WARN_ON(!firmware_has_feature(FW_FEATURE_PS3_LV1)))
+		return -ENODEV;
+	if (WARN_ON(dev->match_id != PS3_MATCH_ID_SOUND))
+		return -ENODEV;
 
 	the_card.ps3_dev = dev;
 
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index b23354a..b9ffc17 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -31,6 +31,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/string.h>
+#include <linux/of_irq.h>
 #include <sound/core.h>
 #include <asm/io.h>
 #include <asm/irq.h>
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 61a64d2..8b9e701 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,5 +1,5 @@
 snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o
-snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o
+snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o soc-devres.o
 
 ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
 snd-soc-core-objs += soc-generic-dmaengine-pcm.o
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c
index 3109db7..612e580 100644
--- a/sound/soc/atmel/atmel-pcm.c
+++ b/sound/soc/atmel/atmel-pcm.c
@@ -50,7 +50,7 @@
 	buf->area = dma_alloc_coherent(pcm->card->dev, size,
 			&buf->addr, GFP_KERNEL);
 	pr_debug("atmel-pcm: alloc dma buffer: area=%p, addr=%p, size=%zu\n",
-			(void *)buf->area, (void *)buf->addr, size);
+			(void *)buf->area, (void *)(long)buf->addr, size);
 
 	if (!buf->area)
 		return -ENOMEM;
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index bb53dea..8697ced 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -777,7 +777,7 @@
 	if (ret) {
 		dev_err(dev, "Could not register PCM: %d\n", ret);
 		goto err_unregister_dai;
-	};
+	}
 
 	return 0;
 
diff --git a/sound/soc/atmel/atmel_wm8904.c b/sound/soc/atmel/atmel_wm8904.c
index 7222380..b4e3690 100644
--- a/sound/soc/atmel/atmel_wm8904.c
+++ b/sound/soc/atmel/atmel_wm8904.c
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/pinctrl/consumer.h>
 
 #include <sound/soc.h>
 
@@ -155,15 +154,8 @@
 	struct snd_soc_card *card = &atmel_asoc_wm8904_card;
 	struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink;
 	struct clk *clk_src;
-	struct pinctrl *pinctrl;
 	int id, ret;
 
-	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-	if (IS_ERR(pinctrl)) {
-		dev_err(&pdev->dev, "failed to request pinctrl\n");
-		return PTR_ERR(pinctrl);
-	}
-
 	card->dev = &pdev->dev;
 	ret = atmel_asoc_wm8904_dt_init(pdev);
 	if (ret) {
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index 802717e..f15bff1 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -37,6 +37,7 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/of.h>
 
 #include <linux/atmel-ssc.h>
 
diff --git a/sound/soc/blackfin/bf5xx-sport.c b/sound/soc/blackfin/bf5xx-sport.c
index 6953512..9dfa124 100644
--- a/sound/soc/blackfin/bf5xx-sport.c
+++ b/sound/soc/blackfin/bf5xx-sport.c
@@ -179,8 +179,9 @@
 	struct dmasg *desc, temp_desc;
 	unsigned long flags;
 
-	BUG_ON(sport->dummy_rx_desc == NULL);
-	BUG_ON(sport->curr_rx_desc == sport->dummy_rx_desc);
+	if (WARN_ON(!sport->dummy_rx_desc) ||
+	    WARN_ON(sport->curr_rx_desc == sport->dummy_rx_desc))
+		return -EINVAL;
 
 	/* Maybe the dummy buffer descriptor ring is damaged */
 	sport->dummy_rx_desc->next_desc_addr = sport->dummy_rx_desc + 1;
@@ -250,8 +251,9 @@
 		return -EBUSY;
 	if (sport->tx_run) {
 		/* tx is running, rx is not running */
-		BUG_ON(sport->dma_rx_desc == NULL);
-		BUG_ON(sport->curr_rx_desc != sport->dummy_rx_desc);
+		if (WARN_ON(!sport->dma_rx_desc) ||
+		    WARN_ON(sport->curr_rx_desc != sport->dummy_rx_desc))
+			return -EINVAL;
 		local_irq_save(flags);
 		while ((get_dma_curr_desc_ptr(sport->dma_rx_chan) -
 			sizeof(struct dmasg)) != sport->dummy_rx_desc)
@@ -298,8 +300,9 @@
 	struct dmasg *desc, temp_desc;
 	unsigned long flags;
 
-	BUG_ON(sport->dummy_tx_desc == NULL);
-	BUG_ON(sport->curr_tx_desc == sport->dummy_tx_desc);
+	if (WARN_ON(!sport->dummy_tx_desc) ||
+	    WARN_ON(sport->curr_tx_desc == sport->dummy_tx_desc))
+		return -EINVAL;
 
 	sport->dummy_tx_desc->next_desc_addr = sport->dummy_tx_desc + 1;
 
@@ -331,8 +334,9 @@
 	if (sport->tx_run)
 		return -EBUSY;
 	if (sport->rx_run) {
-		BUG_ON(sport->dma_tx_desc == NULL);
-		BUG_ON(sport->curr_tx_desc != sport->dummy_tx_desc);
+		if (WARN_ON(!sport->dma_tx_desc) ||
+		    WARN_ON(sport->curr_tx_desc != sport->dummy_tx_desc))
+			return -EINVAL;
 		/* Hook the normal buffer descriptor */
 		local_irq_save(flags);
 		while ((get_dma_curr_desc_ptr(sport->dma_tx_chan) -
@@ -767,7 +771,8 @@
 int sport_set_rx_callback(struct sport_device *sport,
 		       void (*rx_callback)(void *), void *rx_data)
 {
-	BUG_ON(rx_callback == NULL);
+	if (WARN_ON(!rx_callback))
+		return -EINVAL;
 	sport->rx_callback = rx_callback;
 	sport->rx_data = rx_data;
 
@@ -778,7 +783,8 @@
 int sport_set_tx_callback(struct sport_device *sport,
 		void (*tx_callback)(void *), void *tx_data)
 {
-	BUG_ON(tx_callback == NULL);
+	if (WARN_ON(!tx_callback))
+		return -EINVAL;
 	sport->tx_callback = tx_callback;
 	sport->tx_data = tx_data;
 
@@ -789,7 +795,8 @@
 int sport_set_err_callback(struct sport_device *sport,
 		void (*err_callback)(void *), void *err_data)
 {
-	BUG_ON(err_callback == NULL);
+	if (WARN_ON(!err_callback))
+		return -EINVAL;
 	sport->err_callback = err_callback;
 	sport->err_data = err_data;
 
@@ -856,7 +863,8 @@
 
 	param.wdsize = wdsize;
 	param.dummy_count = dummy_count;
-	BUG_ON(param.wdsize == 0 || param.dummy_count == 0);
+	if (WARN_ON(param.wdsize == 0 || param.dummy_count == 0))
+		return NULL;
 
 	ret = sport_config_pdev(pdev, &param);
 	if (ret)
diff --git a/sound/soc/cirrus/Kconfig b/sound/soc/cirrus/Kconfig
index 2c20f01..06f938d 100644
--- a/sound/soc/cirrus/Kconfig
+++ b/sound/soc/cirrus/Kconfig
@@ -1,6 +1,6 @@
 config SND_EP93XX_SOC
 	tristate "SoC Audio support for the Cirrus Logic EP93xx series"
-	depends on ARCH_EP93XX && SND_SOC
+	depends on (ARCH_EP93XX || COMPILE_TEST) && SND_SOC
 	select SND_SOC_GENERIC_DMAENGINE_PCM
 	help
 	  Say Y or M if you want to add support for codecs attached to
diff --git a/sound/soc/cirrus/ep93xx-pcm.c b/sound/soc/cirrus/ep93xx-pcm.c
index 0e9f56e..cfe517e 100644
--- a/sound/soc/cirrus/ep93xx-pcm.c
+++ b/sound/soc/cirrus/ep93xx-pcm.c
@@ -57,9 +57,22 @@
 	return false;
 }
 
+static struct dma_chan *ep93xx_compat_request_channel(
+	struct snd_soc_pcm_runtime *rtd,
+	struct snd_pcm_substream *substream)
+{
+	struct snd_dmaengine_dai_dma_data *dma_data;
+
+	dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+
+	return snd_dmaengine_pcm_request_channel(ep93xx_pcm_dma_filter,
+						 dma_data);
+}
+
 static const struct snd_dmaengine_pcm_config ep93xx_dmaengine_pcm_config = {
 	.pcm_hardware = &ep93xx_pcm_hardware,
 	.compat_filter_fn = ep93xx_pcm_dma_filter,
+	.compat_request_channel = ep93xx_compat_request_channel,
 	.prealloc_buffer_size = 131072,
 };
 
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c
index 259d1ac..75d0ad5 100644
--- a/sound/soc/codecs/88pm860x-codec.c
+++ b/sound/soc/codecs/88pm860x-codec.c
@@ -16,6 +16,7 @@
 #include <linux/mfd/88pm860x.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/regmap.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -140,6 +141,7 @@
 	unsigned int		filter;
 	struct snd_soc_codec	*codec;
 	struct i2c_client	*i2c;
+	struct regmap		*regmap;
 	struct pm860x_chip	*chip;
 	struct pm860x_det	det;
 
@@ -269,48 +271,6 @@
 	{   -86, 29,  0}, {   -56, 30,  0}, {   -28, 31,  0}, {     0,  0,  0},
 };
 
-static int pm860x_volatile(unsigned int reg)
-{
-	BUG_ON(reg >= REG_CACHE_SIZE);
-
-	switch (reg) {
-	case PM860X_AUDIO_SUPPLIES_2:
-		return 1;
-	}
-
-	return 0;
-}
-
-static unsigned int pm860x_read_reg_cache(struct snd_soc_codec *codec,
-					  unsigned int reg)
-{
-	unsigned char *cache = codec->reg_cache;
-
-	BUG_ON(reg >= REG_CACHE_SIZE);
-
-	if (pm860x_volatile(reg))
-		return cache[reg];
-
-	reg += REG_CACHE_BASE;
-
-	return pm860x_reg_read(codec->control_data, reg);
-}
-
-static int pm860x_write_reg_cache(struct snd_soc_codec *codec,
-				  unsigned int reg, unsigned int value)
-{
-	unsigned char *cache = codec->reg_cache;
-
-	BUG_ON(reg >= REG_CACHE_SIZE);
-
-	if (!pm860x_volatile(reg))
-		cache[reg] = (unsigned char)value;
-
-	reg += REG_CACHE_BASE;
-
-	return pm860x_reg_write(codec->control_data, reg, value);
-}
-
 static int snd_soc_get_volsw_2r_st(struct snd_kcontrol *kcontrol,
 				   struct snd_ctl_elem_value *ucontrol)
 {
@@ -1169,6 +1129,7 @@
 static int pm860x_set_bias_level(struct snd_soc_codec *codec,
 				 enum snd_soc_bias_level level)
 {
+	struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
 	int data;
 
 	switch (level) {
@@ -1182,17 +1143,17 @@
 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
 			/* Enable Audio PLL & Audio section */
 			data = AUDIO_PLL | AUDIO_SECTION_ON;
-			pm860x_reg_write(codec->control_data, REG_MISC2, data);
+			pm860x_reg_write(pm860x->i2c, REG_MISC2, data);
 			udelay(300);
 			data = AUDIO_PLL | AUDIO_SECTION_RESET
 				| AUDIO_SECTION_ON;
-			pm860x_reg_write(codec->control_data, REG_MISC2, data);
+			pm860x_reg_write(pm860x->i2c, REG_MISC2, data);
 		}
 		break;
 
 	case SND_SOC_BIAS_OFF:
 		data = AUDIO_PLL | AUDIO_SECTION_RESET | AUDIO_SECTION_ON;
-		pm860x_set_bits(codec->control_data, REG_MISC2, data, 0);
+		pm860x_set_bits(pm860x->i2c, REG_MISC2, data, 0);
 		break;
 	}
 	codec->dapm.bias_level = level;
@@ -1322,17 +1283,17 @@
 	pm860x->det.lo_shrt = lo_shrt;
 
 	if (det & SND_JACK_HEADPHONE)
-		pm860x_set_bits(codec->control_data, REG_HS_DET,
+		pm860x_set_bits(pm860x->i2c, REG_HS_DET,
 				EN_HS_DET, EN_HS_DET);
 	/* headset short detect */
 	if (hs_shrt) {
 		data = CLR_SHORT_HS2 | CLR_SHORT_HS1;
-		pm860x_set_bits(codec->control_data, REG_SHORTS, data, data);
+		pm860x_set_bits(pm860x->i2c, REG_SHORTS, data, data);
 	}
 	/* Lineout short detect */
 	if (lo_shrt) {
 		data = CLR_SHORT_LO2 | CLR_SHORT_LO1;
-		pm860x_set_bits(codec->control_data, REG_SHORTS, data, data);
+		pm860x_set_bits(pm860x->i2c, REG_SHORTS, data, data);
 	}
 
 	/* sync status */
@@ -1350,7 +1311,7 @@
 	pm860x->det.mic_det = det;
 
 	if (det & SND_JACK_MICROPHONE)
-		pm860x_set_bits(codec->control_data, REG_MIC_DET,
+		pm860x_set_bits(pm860x->i2c, REG_MIC_DET,
 				MICDET_MASK, MICDET_MASK);
 
 	/* sync status */
@@ -1366,7 +1327,7 @@
 
 	pm860x->codec = codec;
 
-	codec->control_data = pm860x->i2c;
+	codec->control_data = pm860x->regmap;
 
 	for (i = 0; i < 4; i++) {
 		ret = request_threaded_irq(pm860x->irq[i], NULL,
@@ -1380,14 +1341,6 @@
 
 	pm860x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-	ret = pm860x_bulk_read(codec->control_data, REG_CACHE_BASE,
-			       REG_CACHE_SIZE, codec->reg_cache);
-	if (ret < 0) {
-		dev_err(codec->dev, "Failed to fill register cache: %d\n",
-			ret);
-		goto out;
-	}
-
 	return 0;
 
 out:
@@ -1410,10 +1363,6 @@
 static struct snd_soc_codec_driver soc_codec_dev_pm860x = {
 	.probe		= pm860x_probe,
 	.remove		= pm860x_remove,
-	.read		= pm860x_read_reg_cache,
-	.write		= pm860x_write_reg_cache,
-	.reg_cache_size	= REG_CACHE_SIZE,
-	.reg_word_size	= sizeof(u8),
 	.set_bias_level	= pm860x_set_bias_level,
 
 	.controls = pm860x_snd_controls,
@@ -1439,6 +1388,8 @@
 	pm860x->chip = chip;
 	pm860x->i2c = (chip->id == CHIP_PM8607) ? chip->client
 			: chip->companion;
+	pm860x->regmap = (chip->id == CHIP_PM8607) ? chip->regmap
+			: chip->regmap_companion;
 	platform_set_drvdata(pdev, pm860x);
 
 	for (i = 0; i < 4; i++) {
diff --git a/sound/soc/codecs/88pm860x-codec.h b/sound/soc/codecs/88pm860x-codec.h
index 3364ba4..f7282f4 100644
--- a/sound/soc/codecs/88pm860x-codec.h
+++ b/sound/soc/codecs/88pm860x-codec.h
@@ -12,67 +12,66 @@
 #ifndef __88PM860X_H
 #define __88PM860X_H
 
-/* The offset of these registers are 0xb0 */
-#define PM860X_PCM_IFACE_1		0x00
-#define PM860X_PCM_IFACE_2		0x01
-#define PM860X_PCM_IFACE_3		0x02
-#define PM860X_PCM_RATE			0x03
-#define PM860X_EC_PATH			0x04
-#define PM860X_SIDETONE_L_GAIN		0x05
-#define PM860X_SIDETONE_R_GAIN		0x06
-#define PM860X_SIDETONE_SHIFT		0x07
-#define PM860X_ADC_OFFSET_1		0x08
-#define PM860X_ADC_OFFSET_2		0x09
-#define PM860X_DMIC_DELAY		0x0a
+#define PM860X_PCM_IFACE_1		0xb0
+#define PM860X_PCM_IFACE_2		0xb1
+#define PM860X_PCM_IFACE_3		0xb2
+#define PM860X_PCM_RATE			0xb3
+#define PM860X_EC_PATH			0xb4
+#define PM860X_SIDETONE_L_GAIN		0xb5
+#define PM860X_SIDETONE_R_GAIN		0xb6
+#define PM860X_SIDETONE_SHIFT		0xb7
+#define PM860X_ADC_OFFSET_1		0xb8
+#define PM860X_ADC_OFFSET_2		0xb9
+#define PM860X_DMIC_DELAY		0xba
 
-#define PM860X_I2S_IFACE_1		0x0b
-#define PM860X_I2S_IFACE_2		0x0c
-#define PM860X_I2S_IFACE_3		0x0d
-#define PM860X_I2S_IFACE_4		0x0e
-#define PM860X_EQUALIZER_N0_1		0x0f
-#define PM860X_EQUALIZER_N0_2		0x10
-#define PM860X_EQUALIZER_N1_1		0x11
-#define PM860X_EQUALIZER_N1_2		0x12
-#define PM860X_EQUALIZER_D1_1		0x13
-#define PM860X_EQUALIZER_D1_2		0x14
-#define PM860X_LOFI_GAIN_LEFT		0x15
-#define PM860X_LOFI_GAIN_RIGHT		0x16
-#define PM860X_HIFIL_GAIN_LEFT		0x17
-#define PM860X_HIFIL_GAIN_RIGHT		0x18
-#define PM860X_HIFIR_GAIN_LEFT		0x19
-#define PM860X_HIFIR_GAIN_RIGHT		0x1a
-#define PM860X_DAC_OFFSET		0x1b
-#define PM860X_OFFSET_LEFT_1		0x1c
-#define PM860X_OFFSET_LEFT_2		0x1d
-#define PM860X_OFFSET_RIGHT_1		0x1e
-#define PM860X_OFFSET_RIGHT_2		0x1f
-#define PM860X_ADC_ANA_1		0x20
-#define PM860X_ADC_ANA_2		0x21
-#define PM860X_ADC_ANA_3		0x22
-#define PM860X_ADC_ANA_4		0x23
-#define PM860X_ANA_TO_ANA		0x24
-#define PM860X_HS1_CTRL			0x25
-#define PM860X_HS2_CTRL			0x26
-#define PM860X_LO1_CTRL			0x27
-#define PM860X_LO2_CTRL			0x28
-#define PM860X_EAR_CTRL_1		0x29
-#define PM860X_EAR_CTRL_2		0x2a
-#define PM860X_AUDIO_SUPPLIES_1		0x2b
-#define PM860X_AUDIO_SUPPLIES_2		0x2c
-#define PM860X_ADC_EN_1			0x2d
-#define PM860X_ADC_EN_2			0x2e
-#define PM860X_DAC_EN_1			0x2f
-#define PM860X_DAC_EN_2			0x31
-#define PM860X_AUDIO_CAL_1		0x32
-#define PM860X_AUDIO_CAL_2		0x33
-#define PM860X_AUDIO_CAL_3		0x34
-#define PM860X_AUDIO_CAL_4		0x35
-#define PM860X_AUDIO_CAL_5		0x36
-#define PM860X_ANA_INPUT_SEL_1		0x37
-#define PM860X_ANA_INPUT_SEL_2		0x38
+#define PM860X_I2S_IFACE_1		0xbb
+#define PM860X_I2S_IFACE_2		0xbc
+#define PM860X_I2S_IFACE_3		0xbd
+#define PM860X_I2S_IFACE_4		0xbe
+#define PM860X_EQUALIZER_N0_1		0xbf
+#define PM860X_EQUALIZER_N0_2		0xc0
+#define PM860X_EQUALIZER_N1_1		0xc1
+#define PM860X_EQUALIZER_N1_2		0xc2
+#define PM860X_EQUALIZER_D1_1		0xc3
+#define PM860X_EQUALIZER_D1_2		0xc4
+#define PM860X_LOFI_GAIN_LEFT		0xc5
+#define PM860X_LOFI_GAIN_RIGHT		0xc6
+#define PM860X_HIFIL_GAIN_LEFT		0xc7
+#define PM860X_HIFIL_GAIN_RIGHT		0xc8
+#define PM860X_HIFIR_GAIN_LEFT		0xc9
+#define PM860X_HIFIR_GAIN_RIGHT		0xca
+#define PM860X_DAC_OFFSET		0xcb
+#define PM860X_OFFSET_LEFT_1		0xcc
+#define PM860X_OFFSET_LEFT_2		0xcd
+#define PM860X_OFFSET_RIGHT_1		0xce
+#define PM860X_OFFSET_RIGHT_2		0xcf
+#define PM860X_ADC_ANA_1		0xd0
+#define PM860X_ADC_ANA_2		0xd1
+#define PM860X_ADC_ANA_3		0xd2
+#define PM860X_ADC_ANA_4		0xd3
+#define PM860X_ANA_TO_ANA		0xd4
+#define PM860X_HS1_CTRL			0xd5
+#define PM860X_HS2_CTRL			0xd6
+#define PM860X_LO1_CTRL			0xd7
+#define PM860X_LO2_CTRL			0xd8
+#define PM860X_EAR_CTRL_1		0xd9
+#define PM860X_EAR_CTRL_2		0xda
+#define PM860X_AUDIO_SUPPLIES_1		0xdb
+#define PM860X_AUDIO_SUPPLIES_2		0xdc
+#define PM860X_ADC_EN_1			0xdd
+#define PM860X_ADC_EN_2			0xde
+#define PM860X_DAC_EN_1			0xdf
+#define PM860X_DAC_EN_2			0xe1
+#define PM860X_AUDIO_CAL_1		0xe2
+#define PM860X_AUDIO_CAL_2		0xe3
+#define PM860X_AUDIO_CAL_3		0xe4
+#define PM860X_AUDIO_CAL_4		0xe5
+#define PM860X_AUDIO_CAL_5		0xe6
+#define PM860X_ANA_INPUT_SEL_1		0xe7
+#define PM860X_ANA_INPUT_SEL_2		0xe8
 
-#define PM860X_PCM_IFACE_4		0x39
-#define PM860X_I2S_IFACE_5		0x3a
+#define PM860X_PCM_IFACE_4		0xe9
+#define PM860X_I2S_IFACE_5		0xea
 
 #define PM860X_SHORTS			0x3b
 #define PM860X_PLL_ADJ_1		0x3c
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c
index 80555d7..21ae8d4 100644
--- a/sound/soc/codecs/ab8500-codec.c
+++ b/sound/soc/codecs/ab8500-codec.c
@@ -126,6 +126,8 @@
 
 /* Private data for AB8500 device-driver */
 struct ab8500_codec_drvdata {
+	struct regmap *regmap;
+
 	/* Sidetone */
 	long *sid_fir_values;
 	enum sid_state sid_status;
@@ -166,49 +168,35 @@
  */
 
 /* Read a register from the audio-bank of AB8500 */
-static unsigned int ab8500_codec_read_reg(struct snd_soc_codec *codec,
-					unsigned int reg)
+static int ab8500_codec_read_reg(void *context, unsigned int reg,
+				 unsigned int *value)
 {
+	struct device *dev = context;
 	int status;
-	unsigned int value = 0;
 
 	u8 value8;
-	status = abx500_get_register_interruptible(codec->dev, AB8500_AUDIO,
-						reg, &value8);
-	if (status < 0) {
-		dev_err(codec->dev,
-			"%s: ERROR: Register (0x%02x:0x%02x) read failed (%d).\n",
-			__func__, (u8)AB8500_AUDIO, (u8)reg, status);
-	} else {
-		dev_dbg(codec->dev,
-			"%s: Read 0x%02x from register 0x%02x:0x%02x\n",
-			__func__, value8, (u8)AB8500_AUDIO, (u8)reg);
-		value = (unsigned int)value8;
-	}
-
-	return value;
-}
-
-/* Write to a register in the audio-bank of AB8500 */
-static int ab8500_codec_write_reg(struct snd_soc_codec *codec,
-				unsigned int reg, unsigned int value)
-{
-	int status;
-
-	status = abx500_set_register_interruptible(codec->dev, AB8500_AUDIO,
-						reg, value);
-	if (status < 0)
-		dev_err(codec->dev,
-			"%s: ERROR: Register (%02x:%02x) write failed (%d).\n",
-			__func__, (u8)AB8500_AUDIO, (u8)reg, status);
-	else
-		dev_dbg(codec->dev,
-			"%s: Wrote 0x%02x into register %02x:%02x\n",
-			__func__, (u8)value, (u8)AB8500_AUDIO, (u8)reg);
+	status = abx500_get_register_interruptible(dev, AB8500_AUDIO,
+						   reg, &value8);
+	*value = (unsigned int)value8;
 
 	return status;
 }
 
+/* Write to a register in the audio-bank of AB8500 */
+static int ab8500_codec_write_reg(void *context, unsigned int reg,
+				  unsigned int value)
+{
+	struct device *dev = context;
+
+	return abx500_set_register_interruptible(dev, AB8500_AUDIO,
+						 reg, value);
+}
+
+static const struct regmap_config ab8500_codec_regmap = {
+	.reg_read = ab8500_codec_read_reg,
+	.reg_write = ab8500_codec_write_reg,
+};
+
 /*
  * Controls - DAPM
  */
@@ -2312,17 +2300,17 @@
 	case 0:
 		break;
 	case 1:
-		slot = find_first_bit((unsigned long *)&tx_mask, 32);
+		slot = ffs(tx_mask);
 		snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, slot);
 		snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, slot);
 		snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, slot);
 		snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, slot);
 		break;
 	case 2:
-		slot = find_first_bit((unsigned long *)&tx_mask, 32);
+		slot = ffs(tx_mask);
 		snd_soc_update_bits(codec, AB8500_DASLOTCONF1, mask, slot);
 		snd_soc_update_bits(codec, AB8500_DASLOTCONF3, mask, slot);
-		slot = find_next_bit((unsigned long *)&tx_mask, 32, slot + 1);
+		slot = fls(tx_mask);
 		snd_soc_update_bits(codec, AB8500_DASLOTCONF2, mask, slot);
 		snd_soc_update_bits(codec, AB8500_DASLOTCONF4, mask, slot);
 		break;
@@ -2353,18 +2341,18 @@
 	case 0:
 		break;
 	case 1:
-		slot = find_first_bit((unsigned long *)&rx_mask, 32);
+		slot = ffs(rx_mask);
 		snd_soc_update_bits(codec, AB8500_ADSLOTSEL(slot),
 				AB8500_MASK_SLOT(slot),
 				AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT3, slot));
 		break;
 	case 2:
-		slot = find_first_bit((unsigned long *)&rx_mask, 32);
+		slot = ffs(rx_mask);
 		snd_soc_update_bits(codec,
 				AB8500_ADSLOTSEL(slot),
 				AB8500_MASK_SLOT(slot),
 				AB8500_ADSLOTSELX_AD_OUT_TO_SLOT(AB8500_AD_OUT3, slot));
-		slot = find_next_bit((unsigned long *)&rx_mask, 32, slot + 1);
+		slot = fls(rx_mask);
 		snd_soc_update_bits(codec,
 				AB8500_ADSLOTSEL(slot),
 				AB8500_MASK_SLOT(slot),
@@ -2485,9 +2473,13 @@
 
 	dev_dbg(dev, "%s: Enter.\n", __func__);
 
+	snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
+
 	/* Setup AB8500 according to board-settings */
 	pdata = dev_get_platdata(dev->parent);
 
+	codec->control_data = drvdata->regmap;
+
 	if (np) {
 		if (!pdata)
 			pdata = devm_kzalloc(dev,
@@ -2532,12 +2524,10 @@
 	}
 
 	/* Override HW-defaults */
-	ab8500_codec_write_reg(codec,
-				AB8500_ANACONF5,
-				BIT(AB8500_ANACONF5_HSAUTOEN));
-	ab8500_codec_write_reg(codec,
-				AB8500_SHORTCIRCONF,
-				BIT(AB8500_SHORTCIRCONF_HSZCDDIS));
+	snd_soc_write(codec, AB8500_ANACONF5,
+		      BIT(AB8500_ANACONF5_HSAUTOEN));
+	snd_soc_write(codec, AB8500_SHORTCIRCONF,
+		      BIT(AB8500_SHORTCIRCONF_HSZCDDIS));
 
 	/* Add filter controls */
 	status = snd_soc_add_codec_controls(codec, ab8500_filter_controls,
@@ -2567,9 +2557,6 @@
 
 static struct snd_soc_codec_driver ab8500_codec_driver = {
 	.probe =		ab8500_codec_probe,
-	.read =			ab8500_codec_read_reg,
-	.write =		ab8500_codec_write_reg,
-	.reg_word_size =	sizeof(u8),
 	.controls =		ab8500_ctrls,
 	.num_controls =		ARRAY_SIZE(ab8500_ctrls),
 	.dapm_widgets =		ab8500_dapm_widgets,
@@ -2588,10 +2575,21 @@
 	/* Create driver private-data struct */
 	drvdata = devm_kzalloc(&pdev->dev, sizeof(struct ab8500_codec_drvdata),
 			GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
 	drvdata->sid_status = SID_UNCONFIGURED;
 	drvdata->anc_status = ANC_UNCONFIGURED;
 	dev_set_drvdata(&pdev->dev, drvdata);
 
+	drvdata->regmap = devm_regmap_init(&pdev->dev, NULL, &pdev->dev,
+					   &ab8500_codec_regmap);
+	if (IS_ERR(drvdata->regmap)) {
+		status = PTR_ERR(drvdata->regmap);
+		dev_err(&pdev->dev, "%s: Failed to allocate regmap: %d\n",
+			__func__, status);
+		return status;
+	}
+
 	dev_dbg(&pdev->dev, "%s: Register codec.\n", __func__);
 	status = snd_soc_register_codec(&pdev->dev, &ab8500_codec_driver,
 				ab8500_codec_dai,
@@ -2606,7 +2604,7 @@
 
 static int ab8500_codec_driver_remove(struct platform_device *pdev)
 {
-	dev_info(&pdev->dev, "%s Enter.\n", __func__);
+	dev_dbg(&pdev->dev, "%s Enter.\n", __func__);
 
 	snd_soc_unregister_codec(&pdev->dev);
 
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index 1aa10dd..59654b1 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -32,6 +32,7 @@
 };
 
 struct adau1373 {
+	struct regmap *regmap;
 	struct adau1373_dai dais[3];
 };
 
@@ -73,7 +74,6 @@
 #define ADAU1373_PLL_CTRL4(x)	(0x2c + (x) * 7)
 #define ADAU1373_PLL_CTRL5(x)	(0x2d + (x) * 7)
 #define ADAU1373_PLL_CTRL6(x)	(0x2e + (x) * 7)
-#define ADAU1373_PLL_CTRL7(x)	(0x2f + (x) * 7)
 #define ADAU1373_HEADDECT	0x36
 #define ADAU1373_ADC_DAC_STATUS	0x37
 #define ADAU1373_ADC_CTRL	0x3c
@@ -152,37 +152,172 @@
 #define ADAU1373_EP_CTRL_MICBIAS1_OFFSET 4
 #define ADAU1373_EP_CTRL_MICBIAS2_OFFSET 2
 
-static const uint8_t adau1373_default_regs[] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* 0x30 */
-	0x00, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x00, /* 0x40 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x80 */
-	0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00,
-	0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x90 */
-	0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00,
-	0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0xa0 */
-	0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */
-	0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0 */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, /* 0xe0 */
-	0x00, 0x1f, 0x0f, 0x00, 0x00,
+static const struct reg_default adau1373_reg_defaults[] = {
+	{ ADAU1373_INPUT_MODE,		0x00 },
+	{ ADAU1373_AINL_CTRL(0),	0x00 },
+	{ ADAU1373_AINR_CTRL(0),	0x00 },
+	{ ADAU1373_AINL_CTRL(1),	0x00 },
+	{ ADAU1373_AINR_CTRL(1),	0x00 },
+	{ ADAU1373_AINL_CTRL(2),	0x00 },
+	{ ADAU1373_AINR_CTRL(2),	0x00 },
+	{ ADAU1373_AINL_CTRL(3),	0x00 },
+	{ ADAU1373_AINR_CTRL(3),	0x00 },
+	{ ADAU1373_LLINE_OUT(0),	0x00 },
+	{ ADAU1373_RLINE_OUT(0),	0x00 },
+	{ ADAU1373_LLINE_OUT(1),	0x00 },
+	{ ADAU1373_RLINE_OUT(1),	0x00 },
+	{ ADAU1373_LSPK_OUT,		0x00 },
+	{ ADAU1373_RSPK_OUT,		0x00 },
+	{ ADAU1373_LHP_OUT,		0x00 },
+	{ ADAU1373_RHP_OUT,		0x00 },
+	{ ADAU1373_ADC_GAIN,		0x00 },
+	{ ADAU1373_LADC_MIXER,		0x00 },
+	{ ADAU1373_RADC_MIXER,		0x00 },
+	{ ADAU1373_LLINE1_MIX,		0x00 },
+	{ ADAU1373_RLINE1_MIX,		0x00 },
+	{ ADAU1373_LLINE2_MIX,		0x00 },
+	{ ADAU1373_RLINE2_MIX,		0x00 },
+	{ ADAU1373_LSPK_MIX,		0x00 },
+	{ ADAU1373_RSPK_MIX,		0x00 },
+	{ ADAU1373_LHP_MIX,		0x00 },
+	{ ADAU1373_RHP_MIX,		0x00 },
+	{ ADAU1373_EP_MIX,		0x00 },
+	{ ADAU1373_HP_CTRL,		0x00 },
+	{ ADAU1373_HP_CTRL2,		0x00 },
+	{ ADAU1373_LS_CTRL,		0x00 },
+	{ ADAU1373_EP_CTRL,		0x00 },
+	{ ADAU1373_MICBIAS_CTRL1,	0x00 },
+	{ ADAU1373_MICBIAS_CTRL2,	0x00 },
+	{ ADAU1373_OUTPUT_CTRL,		0x00 },
+	{ ADAU1373_PWDN_CTRL1,		0x00 },
+	{ ADAU1373_PWDN_CTRL2,		0x00 },
+	{ ADAU1373_PWDN_CTRL3,		0x00 },
+	{ ADAU1373_DPLL_CTRL(0),	0x00 },
+	{ ADAU1373_PLL_CTRL1(0),	0x00 },
+	{ ADAU1373_PLL_CTRL2(0),	0x00 },
+	{ ADAU1373_PLL_CTRL3(0),	0x00 },
+	{ ADAU1373_PLL_CTRL4(0),	0x00 },
+	{ ADAU1373_PLL_CTRL5(0),	0x00 },
+	{ ADAU1373_PLL_CTRL6(0),	0x02 },
+	{ ADAU1373_DPLL_CTRL(1),	0x00 },
+	{ ADAU1373_PLL_CTRL1(1),	0x00 },
+	{ ADAU1373_PLL_CTRL2(1),	0x00 },
+	{ ADAU1373_PLL_CTRL3(1),	0x00 },
+	{ ADAU1373_PLL_CTRL4(1),	0x00 },
+	{ ADAU1373_PLL_CTRL5(1),	0x00 },
+	{ ADAU1373_PLL_CTRL6(1),	0x02 },
+	{ ADAU1373_HEADDECT,		0x00 },
+	{ ADAU1373_ADC_CTRL,		0x00 },
+	{ ADAU1373_CLK_SRC_DIV(0),	0x00 },
+	{ ADAU1373_CLK_SRC_DIV(1),	0x00 },
+	{ ADAU1373_DAI(0),		0x0a },
+	{ ADAU1373_DAI(1),		0x0a },
+	{ ADAU1373_DAI(2),		0x0a },
+	{ ADAU1373_BCLKDIV(0),		0x00 },
+	{ ADAU1373_BCLKDIV(1),		0x00 },
+	{ ADAU1373_BCLKDIV(2),		0x00 },
+	{ ADAU1373_SRC_RATIOA(0),	0x00 },
+	{ ADAU1373_SRC_RATIOB(0),	0x00 },
+	{ ADAU1373_SRC_RATIOA(1),	0x00 },
+	{ ADAU1373_SRC_RATIOB(1),	0x00 },
+	{ ADAU1373_SRC_RATIOA(2),	0x00 },
+	{ ADAU1373_SRC_RATIOB(2),	0x00 },
+	{ ADAU1373_DEEMP_CTRL,		0x00 },
+	{ ADAU1373_SRC_DAI_CTRL(0),	0x08 },
+	{ ADAU1373_SRC_DAI_CTRL(1),	0x08 },
+	{ ADAU1373_SRC_DAI_CTRL(2),	0x08 },
+	{ ADAU1373_DIN_MIX_CTRL(0),	0x00 },
+	{ ADAU1373_DIN_MIX_CTRL(1),	0x00 },
+	{ ADAU1373_DIN_MIX_CTRL(2),	0x00 },
+	{ ADAU1373_DIN_MIX_CTRL(3),	0x00 },
+	{ ADAU1373_DIN_MIX_CTRL(4),	0x00 },
+	{ ADAU1373_DOUT_MIX_CTRL(0),	0x00 },
+	{ ADAU1373_DOUT_MIX_CTRL(1),	0x00 },
+	{ ADAU1373_DOUT_MIX_CTRL(2),	0x00 },
+	{ ADAU1373_DOUT_MIX_CTRL(3),	0x00 },
+	{ ADAU1373_DOUT_MIX_CTRL(4),	0x00 },
+	{ ADAU1373_DAI_PBL_VOL(0),	0x00 },
+	{ ADAU1373_DAI_PBR_VOL(0),	0x00 },
+	{ ADAU1373_DAI_PBL_VOL(1),	0x00 },
+	{ ADAU1373_DAI_PBR_VOL(1),	0x00 },
+	{ ADAU1373_DAI_PBL_VOL(2),	0x00 },
+	{ ADAU1373_DAI_PBR_VOL(2),	0x00 },
+	{ ADAU1373_DAI_RECL_VOL(0),	0x00 },
+	{ ADAU1373_DAI_RECR_VOL(0),	0x00 },
+	{ ADAU1373_DAI_RECL_VOL(1),	0x00 },
+	{ ADAU1373_DAI_RECR_VOL(1),	0x00 },
+	{ ADAU1373_DAI_RECL_VOL(2),	0x00 },
+	{ ADAU1373_DAI_RECR_VOL(2),	0x00 },
+	{ ADAU1373_DAC1_PBL_VOL,	0x00 },
+	{ ADAU1373_DAC1_PBR_VOL,	0x00 },
+	{ ADAU1373_DAC2_PBL_VOL,	0x00 },
+	{ ADAU1373_DAC2_PBR_VOL,	0x00 },
+	{ ADAU1373_ADC_RECL_VOL,	0x00 },
+	{ ADAU1373_ADC_RECR_VOL,	0x00 },
+	{ ADAU1373_DMIC_RECL_VOL,	0x00 },
+	{ ADAU1373_DMIC_RECR_VOL,	0x00 },
+	{ ADAU1373_VOL_GAIN1,		0x00 },
+	{ ADAU1373_VOL_GAIN2,		0x00 },
+	{ ADAU1373_VOL_GAIN3,		0x00 },
+	{ ADAU1373_HPF_CTRL,		0x00 },
+	{ ADAU1373_BASS1,		0x00 },
+	{ ADAU1373_BASS2,		0x00 },
+	{ ADAU1373_DRC(0) + 0x0,	0x78 },
+	{ ADAU1373_DRC(0) + 0x1,	0x18 },
+	{ ADAU1373_DRC(0) + 0x2,	0x00 },
+	{ ADAU1373_DRC(0) + 0x3,	0x00 },
+	{ ADAU1373_DRC(0) + 0x4,	0x00 },
+	{ ADAU1373_DRC(0) + 0x5,	0xc0 },
+	{ ADAU1373_DRC(0) + 0x6,	0x00 },
+	{ ADAU1373_DRC(0) + 0x7,	0x00 },
+	{ ADAU1373_DRC(0) + 0x8,	0x00 },
+	{ ADAU1373_DRC(0) + 0x9,	0xc0 },
+	{ ADAU1373_DRC(0) + 0xa,	0x88 },
+	{ ADAU1373_DRC(0) + 0xb,	0x7a },
+	{ ADAU1373_DRC(0) + 0xc,	0xdf },
+	{ ADAU1373_DRC(0) + 0xd,	0x20 },
+	{ ADAU1373_DRC(0) + 0xe,	0x00 },
+	{ ADAU1373_DRC(0) + 0xf,	0x00 },
+	{ ADAU1373_DRC(1) + 0x0,	0x78 },
+	{ ADAU1373_DRC(1) + 0x1,	0x18 },
+	{ ADAU1373_DRC(1) + 0x2,	0x00 },
+	{ ADAU1373_DRC(1) + 0x3,	0x00 },
+	{ ADAU1373_DRC(1) + 0x4,	0x00 },
+	{ ADAU1373_DRC(1) + 0x5,	0xc0 },
+	{ ADAU1373_DRC(1) + 0x6,	0x00 },
+	{ ADAU1373_DRC(1) + 0x7,	0x00 },
+	{ ADAU1373_DRC(1) + 0x8,	0x00 },
+	{ ADAU1373_DRC(1) + 0x9,	0xc0 },
+	{ ADAU1373_DRC(1) + 0xa,	0x88 },
+	{ ADAU1373_DRC(1) + 0xb,	0x7a },
+	{ ADAU1373_DRC(1) + 0xc,	0xdf },
+	{ ADAU1373_DRC(1) + 0xd,	0x20 },
+	{ ADAU1373_DRC(1) + 0xe,	0x00 },
+	{ ADAU1373_DRC(1) + 0xf,	0x00 },
+	{ ADAU1373_DRC(2) + 0x0,	0x78 },
+	{ ADAU1373_DRC(2) + 0x1,	0x18 },
+	{ ADAU1373_DRC(2) + 0x2,	0x00 },
+	{ ADAU1373_DRC(2) + 0x3,	0x00 },
+	{ ADAU1373_DRC(2) + 0x4,	0x00 },
+	{ ADAU1373_DRC(2) + 0x5,	0xc0 },
+	{ ADAU1373_DRC(2) + 0x6,	0x00 },
+	{ ADAU1373_DRC(2) + 0x7,	0x00 },
+	{ ADAU1373_DRC(2) + 0x8,	0x00 },
+	{ ADAU1373_DRC(2) + 0x9,	0xc0 },
+	{ ADAU1373_DRC(2) + 0xa,	0x88 },
+	{ ADAU1373_DRC(2) + 0xb,	0x7a },
+	{ ADAU1373_DRC(2) + 0xc,	0xdf },
+	{ ADAU1373_DRC(2) + 0xd,	0x20 },
+	{ ADAU1373_DRC(2) + 0xe,	0x00 },
+	{ ADAU1373_DRC(2) + 0xf,	0x00 },
+	{ ADAU1373_3D_CTRL1,		0x00 },
+	{ ADAU1373_3D_CTRL2,		0x00 },
+	{ ADAU1373_FDSP_SEL1,		0x00 },
+	{ ADAU1373_FDSP_SEL2,		0x00 },
+	{ ADAU1373_FDSP_SEL2,		0x00 },
+	{ ADAU1373_FDSP_SEL4,		0x00 },
+	{ ADAU1373_DIGMICCTRL,		0x00 },
+	{ ADAU1373_DIGEN,		0x00 },
 };
 
 static const unsigned int adau1373_out_tlv[] = {
@@ -418,6 +553,7 @@
 	struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
+	struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
 	unsigned int pll_id = w->name[3] - '1';
 	unsigned int val;
 
@@ -426,7 +562,7 @@
 	else
 		val = 0;
 
-	snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id),
+	regmap_update_bits(adau1373->regmap, ADAU1373_PLL_CTRL6(pll_id),
 		ADAU1373_PLL_CTRL6_PLL_EN, val);
 
 	if (SND_SOC_DAPM_EVENT_ON(event))
@@ -938,7 +1074,7 @@
 
 	adau1373_dai->enable_src = (div != 0);
 
-	snd_soc_update_bits(codec, ADAU1373_BCLKDIV(dai->id),
+	regmap_update_bits(adau1373->regmap, ADAU1373_BCLKDIV(dai->id),
 		ADAU1373_BCLKDIV_SR_MASK | ADAU1373_BCLKDIV_BCLK_MASK,
 		(div << 2) | ADAU1373_BCLKDIV_64);
 
@@ -959,7 +1095,7 @@
 		return -EINVAL;
 	}
 
-	return snd_soc_update_bits(codec, ADAU1373_DAI(dai->id),
+	return regmap_update_bits(adau1373->regmap, ADAU1373_DAI(dai->id),
 			ADAU1373_DAI_WLEN_MASK, ctrl);
 }
 
@@ -1016,7 +1152,7 @@
 		return -EINVAL;
 	}
 
-	snd_soc_update_bits(codec, ADAU1373_DAI(dai->id),
+	regmap_update_bits(adau1373->regmap, ADAU1373_DAI(dai->id),
 		~ADAU1373_DAI_WLEN_MASK, ctrl);
 
 	return 0;
@@ -1039,7 +1175,7 @@
 	adau1373_dai->sysclk = freq;
 	adau1373_dai->clk_src = clk_id;
 
-	snd_soc_update_bits(dai->codec, ADAU1373_BCLKDIV(dai->id),
+	regmap_update_bits(adau1373->regmap, ADAU1373_BCLKDIV(dai->id),
 		ADAU1373_BCLKDIV_SOURCE, clk_id << 5);
 
 	return 0;
@@ -1120,6 +1256,7 @@
 static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id,
 	int source, unsigned int freq_in, unsigned int freq_out)
 {
+	struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
 	unsigned int dpll_div = 0;
 	unsigned int x, r, n, m, i, j, mode;
 
@@ -1187,36 +1324,36 @@
 
 	if (dpll_div) {
 		dpll_div = 11 - dpll_div;
-		snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id),
+		regmap_update_bits(adau1373->regmap, ADAU1373_PLL_CTRL6(pll_id),
 			ADAU1373_PLL_CTRL6_DPLL_BYPASS, 0);
 	} else {
-		snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id),
+		regmap_update_bits(adau1373->regmap, ADAU1373_PLL_CTRL6(pll_id),
 			ADAU1373_PLL_CTRL6_DPLL_BYPASS,
 			ADAU1373_PLL_CTRL6_DPLL_BYPASS);
 	}
 
-	snd_soc_write(codec, ADAU1373_DPLL_CTRL(pll_id),
+	regmap_write(adau1373->regmap, ADAU1373_DPLL_CTRL(pll_id),
 		(source << 4) | dpll_div);
-	snd_soc_write(codec, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff);
-	snd_soc_write(codec, ADAU1373_PLL_CTRL2(pll_id), m & 0xff);
-	snd_soc_write(codec, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff);
-	snd_soc_write(codec, ADAU1373_PLL_CTRL4(pll_id), n & 0xff);
-	snd_soc_write(codec, ADAU1373_PLL_CTRL5(pll_id),
+	regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff);
+	regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL2(pll_id), m & 0xff);
+	regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff);
+	regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL4(pll_id), n & 0xff);
+	regmap_write(adau1373->regmap, ADAU1373_PLL_CTRL5(pll_id),
 		(r << 3) | (x << 1) | mode);
 
 	/* Set sysclk to pll_rate / 4 */
-	snd_soc_update_bits(codec, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09);
+	regmap_update_bits(adau1373->regmap, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09);
 
 	return 0;
 }
 
-static void adau1373_load_drc_settings(struct snd_soc_codec *codec,
+static void adau1373_load_drc_settings(struct adau1373 *adau1373,
 	unsigned int nr, uint8_t *drc)
 {
 	unsigned int i;
 
 	for (i = 0; i < ADAU1373_DRC_SIZE; ++i)
-		snd_soc_write(codec, ADAU1373_DRC(nr) + i, drc[i]);
+		regmap_write(adau1373->regmap, ADAU1373_DRC(nr) + i, drc[i]);
 }
 
 static bool adau1373_valid_micbias(enum adau1373_micbias_voltage micbias)
@@ -1235,13 +1372,14 @@
 
 static int adau1373_probe(struct snd_soc_codec *codec)
 {
+	struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
 	struct adau1373_platform_data *pdata = codec->dev->platform_data;
 	bool lineout_differential = false;
 	unsigned int val;
 	int ret;
 	int i;
 
-	ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
+	ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
 	if (ret) {
 		dev_err(codec->dev, "failed to set cache I/O: %d\n", ret);
 		return ret;
@@ -1256,7 +1394,7 @@
 			return -EINVAL;
 
 		for (i = 0; i < pdata->num_drc; ++i) {
-			adau1373_load_drc_settings(codec, i,
+			adau1373_load_drc_settings(adau1373, i,
 				pdata->drc_setting[i]);
 		}
 
@@ -1268,18 +1406,18 @@
 			if (pdata->input_differential[i])
 				val |= BIT(i);
 		}
-		snd_soc_write(codec, ADAU1373_INPUT_MODE, val);
+		regmap_write(adau1373->regmap, ADAU1373_INPUT_MODE, val);
 
 		val = 0;
 		if (pdata->lineout_differential)
 			val |= ADAU1373_OUTPUT_CTRL_LDIFF;
 		if (pdata->lineout_ground_sense)
 			val |= ADAU1373_OUTPUT_CTRL_LNFBEN;
-		snd_soc_write(codec, ADAU1373_OUTPUT_CTRL, val);
+		regmap_write(adau1373->regmap, ADAU1373_OUTPUT_CTRL, val);
 
 		lineout_differential = pdata->lineout_differential;
 
-		snd_soc_write(codec, ADAU1373_EP_CTRL,
+		regmap_write(adau1373->regmap, ADAU1373_EP_CTRL,
 			(pdata->micbias1 << ADAU1373_EP_CTRL_MICBIAS1_OFFSET) |
 			(pdata->micbias2 << ADAU1373_EP_CTRL_MICBIAS2_OFFSET));
 	}
@@ -1289,7 +1427,7 @@
 			ARRAY_SIZE(adau1373_lineout2_controls));
 	}
 
-	snd_soc_write(codec, ADAU1373_ADC_CTRL,
+	regmap_write(adau1373->regmap, ADAU1373_ADC_CTRL,
 	    ADAU1373_ADC_CTRL_RESET_FORCE | ADAU1373_ADC_CTRL_PEAK_DETECT);
 
 	return 0;
@@ -1298,17 +1436,19 @@
 static int adau1373_set_bias_level(struct snd_soc_codec *codec,
 	enum snd_soc_bias_level level)
 {
+	struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
+
 	switch (level) {
 	case SND_SOC_BIAS_ON:
 		break;
 	case SND_SOC_BIAS_PREPARE:
 		break;
 	case SND_SOC_BIAS_STANDBY:
-		snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3,
+		regmap_update_bits(adau1373->regmap, ADAU1373_PWDN_CTRL3,
 			ADAU1373_PWDN_CTRL3_PWR_EN, ADAU1373_PWDN_CTRL3_PWR_EN);
 		break;
 	case SND_SOC_BIAS_OFF:
-		snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3,
+		regmap_update_bits(adau1373->regmap, ADAU1373_PWDN_CTRL3,
 			ADAU1373_PWDN_CTRL3_PWR_EN, 0);
 		break;
 	}
@@ -1324,17 +1464,49 @@
 
 static int adau1373_suspend(struct snd_soc_codec *codec)
 {
-	return adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	ret = adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	regcache_cache_only(adau1373->regmap, true);
+
+	return ret;
 }
 
 static int adau1373_resume(struct snd_soc_codec *codec)
 {
+	struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
+
+	regcache_cache_only(adau1373->regmap, false);
 	adau1373_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-	snd_soc_cache_sync(codec);
+	regcache_sync(adau1373->regmap);
 
 	return 0;
 }
 
+static bool adau1373_register_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case ADAU1373_SOFT_RESET:
+	case ADAU1373_ADC_DAC_STATUS:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct regmap_config adau1373_regmap_config = {
+	.val_bits = 8,
+	.reg_bits = 8,
+
+	.volatile_reg = adau1373_register_volatile,
+	.max_register = ADAU1373_SOFT_RESET,
+
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = adau1373_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(adau1373_reg_defaults),
+};
+
 static struct snd_soc_codec_driver adau1373_codec_driver = {
 	.probe =	adau1373_probe,
 	.remove =	adau1373_remove,
@@ -1342,9 +1514,6 @@
 	.resume =	adau1373_resume,
 	.set_bias_level = adau1373_set_bias_level,
 	.idle_bias_off = true,
-	.reg_cache_size = ARRAY_SIZE(adau1373_default_regs),
-	.reg_cache_default = adau1373_default_regs,
-	.reg_word_size = sizeof(uint8_t),
 
 	.set_pll = adau1373_set_pll,
 
@@ -1366,6 +1535,13 @@
 	if (!adau1373)
 		return -ENOMEM;
 
+	adau1373->regmap = devm_regmap_init_i2c(client,
+		&adau1373_regmap_config);
+	if (IS_ERR(adau1373->regmap))
+		return PTR_ERR(adau1373->regmap);
+
+	regmap_write(adau1373->regmap, ADAU1373_SOFT_RESET, 0x00);
+
 	dev_set_drvdata(&client->dev, adau1373);
 
 	ret = snd_soc_register_codec(&client->dev, &adau1373_codec_driver,
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c
index 15b012d0..14a7c16 100644
--- a/sound/soc/codecs/adav80x.c
+++ b/sound/soc/codecs/adav80x.c
@@ -115,22 +115,34 @@
 
 #define ADAV80X_PLL_OUTE_SYSCLKPD(x)		BIT(2 - (x))
 
-static u8 adav80x_default_regs[] = {
-	0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x01, 0x80, 0x26, 0x00, 0x00,
-	0x02, 0x40, 0x20, 0x00, 0x09, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x92, 0xb1, 0x37,
-	0x48, 0xd2, 0xfb, 0xca, 0xd2, 0x15, 0xe8, 0x29, 0xb9, 0x6a, 0xda, 0x2b,
-	0xb7, 0xc0, 0x11, 0x65, 0x5c, 0xf6, 0xff, 0x8d, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00,
-	0x00, 0xe8, 0x46, 0xe1, 0x5b, 0xd3, 0x43, 0x77, 0x93, 0xa7, 0x44, 0xee,
-	0x32, 0x12, 0xc0, 0x11, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x3f,
-	0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x52, 0x00,
+static struct reg_default adav80x_reg_defaults[] = {
+	{ ADAV80X_PLAYBACK_CTRL,	0x01 },
+	{ ADAV80X_AUX_IN_CTRL,		0x01 },
+	{ ADAV80X_REC_CTRL,		0x02 },
+	{ ADAV80X_AUX_OUT_CTRL,		0x01 },
+	{ ADAV80X_DPATH_CTRL1,		0xc0 },
+	{ ADAV80X_DPATH_CTRL2,		0x11 },
+	{ ADAV80X_DAC_CTRL1,		0x00 },
+	{ ADAV80X_DAC_CTRL2,		0x00 },
+	{ ADAV80X_DAC_CTRL3,		0x00 },
+	{ ADAV80X_DAC_L_VOL,		0xff },
+	{ ADAV80X_DAC_R_VOL,		0xff },
+	{ ADAV80X_PGA_L_VOL,		0x00 },
+	{ ADAV80X_PGA_R_VOL,		0x00 },
+	{ ADAV80X_ADC_CTRL1,		0x00 },
+	{ ADAV80X_ADC_CTRL2,		0x00 },
+	{ ADAV80X_ADC_L_VOL,		0xff },
+	{ ADAV80X_ADC_R_VOL,		0xff },
+	{ ADAV80X_PLL_CTRL1,		0x00 },
+	{ ADAV80X_PLL_CTRL2,		0x00 },
+	{ ADAV80X_ICLK_CTRL1,		0x00 },
+	{ ADAV80X_ICLK_CTRL2,		0x00 },
+	{ ADAV80X_PLL_CLK_SRC,		0x00 },
+	{ ADAV80X_PLL_OUTE,		0x00 },
 };
 
 struct adav80x {
-	enum snd_soc_control_type control_type;
+	struct regmap *regmap;
 
 	enum adav80x_clk_src clk_src;
 	unsigned int sysclk;
@@ -298,7 +310,7 @@
 		val = ADAV80X_DAC_CTRL2_DEEMPH_NONE;
 	}
 
-	return snd_soc_update_bits(codec, ADAV80X_DAC_CTRL2,
+	return regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL2,
 		ADAV80X_DAC_CTRL2_DEEMPH_MASK, val);
 }
 
@@ -394,10 +406,11 @@
 		return -EINVAL;
 	}
 
-	snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][0],
+	regmap_update_bits(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][0],
 		ADAV80X_CAPTURE_MODE_MASK | ADAV80X_CAPTURE_MODE_MASTER,
 		capture);
-	snd_soc_write(codec, adav80x_port_ctrl_regs[dai->id][1], playback);
+	regmap_write(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][1],
+		playback);
 
 	adav80x->dai_fmt[dai->id] = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
 
@@ -407,6 +420,7 @@
 static int adav80x_set_adc_clock(struct snd_soc_codec *codec,
 		unsigned int sample_rate)
 {
+	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
 	unsigned int val;
 
 	if (sample_rate <= 48000)
@@ -414,7 +428,7 @@
 	else
 		val = ADAV80X_ADC_CTRL1_MODULATOR_64FS;
 
-	snd_soc_update_bits(codec, ADAV80X_ADC_CTRL1,
+	regmap_update_bits(adav80x->regmap, ADAV80X_ADC_CTRL1,
 		ADAV80X_ADC_CTRL1_MODULATOR_MASK, val);
 
 	return 0;
@@ -423,6 +437,7 @@
 static int adav80x_set_dac_clock(struct snd_soc_codec *codec,
 		unsigned int sample_rate)
 {
+	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
 	unsigned int val;
 
 	if (sample_rate <= 48000)
@@ -430,7 +445,7 @@
 	else
 		val = ADAV80X_DAC_CTRL2_DIV2 | ADAV80X_DAC_CTRL2_INTERPOL_128FS;
 
-	snd_soc_update_bits(codec, ADAV80X_DAC_CTRL2,
+	regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL2,
 		ADAV80X_DAC_CTRL2_DIV_MASK | ADAV80X_DAC_CTRL2_INTERPOL_MASK,
 		val);
 
@@ -440,6 +455,7 @@
 static int adav80x_set_capture_pcm_format(struct snd_soc_codec *codec,
 		struct snd_soc_dai *dai, snd_pcm_format_t format)
 {
+	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
 	unsigned int val;
 
 	switch (format) {
@@ -459,7 +475,7 @@
 		return -EINVAL;
 	}
 
-	snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][0],
+	regmap_update_bits(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][0],
 		ADAV80X_CAPTURE_WORD_LEN_MASK, val);
 
 	return 0;
@@ -491,7 +507,7 @@
 		return -EINVAL;
 	}
 
-	snd_soc_update_bits(codec, adav80x_port_ctrl_regs[dai->id][1],
+	regmap_update_bits(adav80x->regmap, adav80x_port_ctrl_regs[dai->id][1],
 		ADAV80X_PLAYBACK_MODE_MASK, val);
 
 	return 0;
@@ -554,8 +570,10 @@
 					ADAV80X_ICLK_CTRL1_ICLK2_SRC(clk_id);
 			iclk_ctrl2 = ADAV80X_ICLK_CTRL2_ICLK1_SRC(clk_id);
 
-			snd_soc_write(codec, ADAV80X_ICLK_CTRL1, iclk_ctrl1);
-			snd_soc_write(codec, ADAV80X_ICLK_CTRL2, iclk_ctrl2);
+			regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL1,
+				iclk_ctrl1);
+			regmap_write(adav80x->regmap, ADAV80X_ICLK_CTRL2,
+				iclk_ctrl2);
 
 			snd_soc_dapm_sync(&codec->dapm);
 		}
@@ -575,10 +593,12 @@
 		mask = ADAV80X_PLL_OUTE_SYSCLKPD(clk_id);
 
 		if (freq == 0) {
-			snd_soc_update_bits(codec, ADAV80X_PLL_OUTE, mask, mask);
+			regmap_update_bits(adav80x->regmap, ADAV80X_PLL_OUTE,
+				mask, mask);
 			adav80x->sysclk_pd[clk_id] = true;
 		} else {
-			snd_soc_update_bits(codec, ADAV80X_PLL_OUTE, mask, 0);
+			regmap_update_bits(adav80x->regmap, ADAV80X_PLL_OUTE,
+				mask, 0);
 			adav80x->sysclk_pd[clk_id] = false;
 		}
 
@@ -650,9 +670,9 @@
 		return -EINVAL;
 	}
 
-	snd_soc_update_bits(codec, ADAV80X_PLL_CTRL1, ADAV80X_PLL_CTRL1_PLLDIV,
-		pll_ctrl1);
-	snd_soc_update_bits(codec, ADAV80X_PLL_CTRL2,
+	regmap_update_bits(adav80x->regmap, ADAV80X_PLL_CTRL1,
+			ADAV80X_PLL_CTRL1_PLLDIV, pll_ctrl1);
+	regmap_update_bits(adav80x->regmap, ADAV80X_PLL_CTRL2,
 			ADAV80X_PLL_CTRL2_PLL_MASK(pll_id), pll_ctrl2);
 
 	if (source != adav80x->pll_src) {
@@ -661,7 +681,7 @@
 		else
 			pll_src = ADAV80X_PLL_CLK_SRC_PLL_XIN(pll_id);
 
-		snd_soc_update_bits(codec, ADAV80X_PLL_CLK_SRC,
+		regmap_update_bits(adav80x->regmap, ADAV80X_PLL_CLK_SRC,
 				ADAV80X_PLL_CLK_SRC_PLL_MASK(pll_id), pll_src);
 
 		adav80x->pll_src = source;
@@ -675,6 +695,7 @@
 static int adav80x_set_bias_level(struct snd_soc_codec *codec,
 		enum snd_soc_bias_level level)
 {
+	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
 	unsigned int mask = ADAV80X_DAC_CTRL1_PD;
 
 	switch (level) {
@@ -683,10 +704,12 @@
 	case SND_SOC_BIAS_PREPARE:
 		break;
 	case SND_SOC_BIAS_STANDBY:
-		snd_soc_update_bits(codec, ADAV80X_DAC_CTRL1, mask, 0x00);
+		regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL1, mask,
+			0x00);
 		break;
 	case SND_SOC_BIAS_OFF:
-		snd_soc_update_bits(codec, ADAV80X_DAC_CTRL1, mask, mask);
+		regmap_update_bits(adav80x->regmap, ADAV80X_DAC_CTRL1, mask,
+			mask);
 		break;
 	}
 
@@ -780,7 +803,7 @@
 	int ret;
 	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
 
-	ret = snd_soc_codec_set_cache_io(codec, 7, 9, adav80x->control_type);
+	ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
 	if (ret) {
 		dev_err(codec->dev, "failed to set cache I/O: %d\n", ret);
 		return ret;
@@ -791,23 +814,31 @@
 	snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL2");
 
 	/* Power down S/PDIF receiver, since it is currently not supported */
-	snd_soc_write(codec, ADAV80X_PLL_OUTE, 0x20);
+	regmap_write(adav80x->regmap, ADAV80X_PLL_OUTE, 0x20);
 	/* Disable DAC zero flag */
-	snd_soc_write(codec, ADAV80X_DAC_CTRL3, 0x6);
+	regmap_write(adav80x->regmap, ADAV80X_DAC_CTRL3, 0x6);
 
 	return adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 }
 
 static int adav80x_suspend(struct snd_soc_codec *codec)
 {
-	return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	ret = adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	regcache_cache_only(adav80x->regmap, true);
+
+	return ret;
 }
 
 static int adav80x_resume(struct snd_soc_codec *codec)
 {
+	struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
+
+	regcache_cache_only(adav80x->regmap, false);
 	adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-	codec->cache_sync = 1;
-	snd_soc_cache_sync(codec);
+	regcache_sync(adav80x->regmap);
 
 	return 0;
 }
@@ -827,10 +858,6 @@
 	.set_pll = adav80x_set_pll,
 	.set_sysclk = adav80x_set_sysclk,
 
-	.reg_word_size = sizeof(u8),
-	.reg_cache_size = ARRAY_SIZE(adav80x_default_regs),
-	.reg_cache_default = adav80x_default_regs,
-
 	.controls = adav80x_controls,
 	.num_controls = ARRAY_SIZE(adav80x_controls),
 	.dapm_widgets = adav80x_dapm_widgets,
@@ -839,18 +866,21 @@
 	.num_dapm_routes = ARRAY_SIZE(adav80x_dapm_routes),
 };
 
-static int adav80x_bus_probe(struct device *dev,
-			     enum snd_soc_control_type control_type)
+static int adav80x_bus_probe(struct device *dev, struct regmap *regmap)
 {
 	struct adav80x *adav80x;
 	int ret;
 
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
 	adav80x = kzalloc(sizeof(*adav80x), GFP_KERNEL);
 	if (!adav80x)
 		return -ENOMEM;
 
+
 	dev_set_drvdata(dev, adav80x);
-	adav80x->control_type = control_type;
+	adav80x->regmap = regmap;
 
 	ret = snd_soc_register_codec(dev, &adav80x_codec_driver,
 		adav80x_dais, ARRAY_SIZE(adav80x_dais));
@@ -868,6 +898,19 @@
 }
 
 #if defined(CONFIG_SPI_MASTER)
+static const struct regmap_config adav80x_spi_regmap_config = {
+	.val_bits = 8,
+	.pad_bits = 1,
+	.reg_bits = 7,
+	.read_flag_mask = 0x01,
+
+	.max_register = ADAV80X_PLL_OUTE,
+
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = adav80x_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults),
+};
+
 static const struct spi_device_id adav80x_spi_id[] = {
 	{ "adav801", 0 },
 	{ }
@@ -876,7 +919,8 @@
 
 static int adav80x_spi_probe(struct spi_device *spi)
 {
-	return adav80x_bus_probe(&spi->dev, SND_SOC_SPI);
+	return adav80x_bus_probe(&spi->dev,
+		devm_regmap_init_spi(spi, &adav80x_spi_regmap_config));
 }
 
 static int adav80x_spi_remove(struct spi_device *spi)
@@ -896,6 +940,18 @@
 #endif
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static const struct regmap_config adav80x_i2c_regmap_config = {
+	.val_bits = 8,
+	.pad_bits = 1,
+	.reg_bits = 7,
+
+	.max_register = ADAV80X_PLL_OUTE,
+
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults = adav80x_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(adav80x_reg_defaults),
+};
+
 static const struct i2c_device_id adav80x_i2c_id[] = {
 	{ "adav803", 0 },
 	{ }
@@ -905,7 +961,8 @@
 static int adav80x_i2c_probe(struct i2c_client *client,
 			     const struct i2c_device_id *id)
 {
-	return adav80x_bus_probe(&client->dev, SND_SOC_I2C);
+	return adav80x_bus_probe(&client->dev,
+		devm_regmap_init_i2c(client, &adav80x_i2c_regmap_config));
 }
 
 static int adav80x_i2c_remove(struct i2c_client *client)
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index 71059c0..b4819dc 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -45,8 +45,6 @@
 #define AK4104_TX_TXE			(1 << 0)
 #define AK4104_TX_V			(1 << 1)
 
-#define DRV_NAME "ak4104-codec"
-
 struct ak4104_private {
 	struct regmap *regmap;
 };
@@ -291,12 +289,19 @@
 };
 MODULE_DEVICE_TABLE(of, ak4104_of_match);
 
+static const struct spi_device_id ak4104_id_table[] = {
+	{ "ak4104", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, ak4104_id_table);
+
 static struct spi_driver ak4104_spi_driver = {
 	.driver  = {
-		.name   = DRV_NAME,
+		.name   = "ak4104",
 		.owner  = THIS_MODULE,
 		.of_match_table = ak4104_of_match,
 	},
+	.id_table = ak4104_id_table,
 	.probe  = ak4104_spi_probe,
 	.remove = ak4104_spi_remove,
 };
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c
index 5f9af1f..49cc5f6 100644
--- a/sound/soc/codecs/ak4641.c
+++ b/sound/soc/codecs/ak4641.c
@@ -328,7 +328,7 @@
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		ak4641->playback_fs = rate;
 		ak4641_set_deemph(codec);
-	};
+	}
 
 	return 0;
 }
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 2d03787..090d499 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -257,7 +257,7 @@
 		 * This operation came from example code of
 		 * "ASAHI KASEI AK4642" (japanese) manual p94.
 		 */
-		snd_soc_write(codec, SG_SL1, PMMP | MGAIN0);
+		snd_soc_update_bits(codec, SG_SL1, PMMP | MGAIN0, PMMP | MGAIN0);
 		snd_soc_write(codec, TIMER, ZTM(0x3) | WTM(0x3));
 		snd_soc_write(codec, ALC_CTL1, ALC | LMTH0);
 		snd_soc_update_bits(codec, PW_MGMT1, PMADL, PMADL);
@@ -352,7 +352,6 @@
 	 */
 	default:
 		return -EINVAL;
-		break;
 	}
 	snd_soc_update_bits(codec, MD_CTL1, DIF_MASK, data);
 
@@ -405,7 +404,6 @@
 		break;
 	default:
 		return -EINVAL;
-		break;
 	}
 	snd_soc_update_bits(codec, MD_CTL2, FS_MASK, rate);
 
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index 657808b..6f05b17 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -1477,21 +1477,25 @@
 {
 	struct arizona *arizona = fll->arizona;
 	int ret;
+	bool use_sync = false;
 
 	/*
 	 * If we have both REFCLK and SYNCCLK then enable both,
 	 * otherwise apply the SYNCCLK settings to REFCLK.
 	 */
-	if (fll->ref_src >= 0 && fll->ref_src != fll->sync_src) {
+	if (fll->ref_src >= 0 && fll->ref_freq &&
+	    fll->ref_src != fll->sync_src) {
 		regmap_update_bits(arizona->regmap, fll->base + 5,
 				   ARIZONA_FLL1_OUTDIV_MASK,
 				   ref->outdiv << ARIZONA_FLL1_OUTDIV_SHIFT);
 
 		arizona_apply_fll(arizona, fll->base, ref, fll->ref_src,
 				  false);
-		if (fll->sync_src >= 0)
+		if (fll->sync_src >= 0) {
 			arizona_apply_fll(arizona, fll->base + 0x10, sync,
 					  fll->sync_src, true);
+			use_sync = true;
+		}
 	} else if (fll->sync_src >= 0) {
 		regmap_update_bits(arizona->regmap, fll->base + 5,
 				   ARIZONA_FLL1_OUTDIV_MASK,
@@ -1511,7 +1515,7 @@
 	 * Increase the bandwidth if we're not using a low frequency
 	 * sync source.
 	 */
-	if (fll->sync_src >= 0 && fll->sync_freq > 100000)
+	if (use_sync && fll->sync_freq > 100000)
 		regmap_update_bits(arizona->regmap, fll->base + 0x17,
 				   ARIZONA_FLL1_SYNC_BW, 0);
 	else
@@ -1526,8 +1530,7 @@
 
 	regmap_update_bits(arizona->regmap, fll->base + 1,
 			   ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
-	if (fll->ref_src >= 0 && fll->sync_src >= 0 &&
-	    fll->ref_src != fll->sync_src)
+	if (use_sync)
 		regmap_update_bits(arizona->regmap, fll->base + 0x11,
 				   ARIZONA_FLL1_SYNC_ENA,
 				   ARIZONA_FLL1_SYNC_ENA);
@@ -1561,10 +1564,12 @@
 	if (fll->ref_src == source && fll->ref_freq == Fref)
 		return 0;
 
-	if (fll->fout && Fref > 0) {
-		ret = arizona_calc_fll(fll, &ref, Fref, fll->fout);
-		if (ret != 0)
-			return ret;
+	if (fll->fout) {
+		if (Fref > 0) {
+			ret = arizona_calc_fll(fll, &ref, Fref, fll->fout);
+			if (ret != 0)
+				return ret;
+		}
 
 		if (fll->sync_src >= 0) {
 			ret = arizona_calc_fll(fll, &sync, fll->sync_freq,
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c
index 23316c8..43737a27 100644
--- a/sound/soc/codecs/cq93vc.c
+++ b/sound/soc/codecs/cq93vc.c
@@ -38,24 +38,6 @@
 #include <sound/soc.h>
 #include <sound/initval.h>
 
-static inline unsigned int cq93vc_read(struct snd_soc_codec *codec,
-						unsigned int reg)
-{
-	struct davinci_vc *davinci_vc = codec->control_data;
-
-	return readl(davinci_vc->base + reg);
-}
-
-static inline int cq93vc_write(struct snd_soc_codec *codec, unsigned int reg,
-		       unsigned int value)
-{
-	struct davinci_vc *davinci_vc = codec->control_data;
-
-	writel(value, davinci_vc->base + reg);
-
-	return 0;
-}
-
 static const struct snd_kcontrol_new cq93vc_snd_controls[] = {
 	SOC_SINGLE("PGA Capture Volume", DAVINCI_VC_REG05, 0, 0x03, 0),
 	SOC_SINGLE("Mono DAC Playback Volume", DAVINCI_VC_REG09, 0, 0x3f, 0),
@@ -64,13 +46,15 @@
 static int cq93vc_mute(struct snd_soc_dai *dai, int mute)
 {
 	struct snd_soc_codec *codec = dai->codec;
-	u8 reg = cq93vc_read(codec, DAVINCI_VC_REG09) & ~DAVINCI_VC_REG09_MUTE;
+	u8 reg;
 
 	if (mute)
-		cq93vc_write(codec, DAVINCI_VC_REG09,
-			     reg | DAVINCI_VC_REG09_MUTE);
+		reg = DAVINCI_VC_REG09_MUTE;
 	else
-		cq93vc_write(codec, DAVINCI_VC_REG09, reg);
+		reg = 0;
+
+	snd_soc_update_bits(codec, DAVINCI_VC_REG09, DAVINCI_VC_REG09_MUTE,
+			    reg);
 
 	return 0;
 }
@@ -79,7 +63,7 @@
 				 int clk_id, unsigned int freq, int dir)
 {
 	struct snd_soc_codec *codec = codec_dai->codec;
-	struct davinci_vc *davinci_vc = codec->control_data;
+	struct davinci_vc *davinci_vc = codec->dev->platform_data;
 
 	switch (freq) {
 	case 22579200:
@@ -97,18 +81,18 @@
 {
 	switch (level) {
 	case SND_SOC_BIAS_ON:
-		cq93vc_write(codec, DAVINCI_VC_REG12,
+		snd_soc_write(codec, DAVINCI_VC_REG12,
 			     DAVINCI_VC_REG12_POWER_ALL_ON);
 		break;
 	case SND_SOC_BIAS_PREPARE:
 		break;
 	case SND_SOC_BIAS_STANDBY:
-		cq93vc_write(codec, DAVINCI_VC_REG12,
+		snd_soc_write(codec, DAVINCI_VC_REG12,
 			     DAVINCI_VC_REG12_POWER_ALL_OFF);
 		break;
 	case SND_SOC_BIAS_OFF:
 		/* force all power off */
-		cq93vc_write(codec, DAVINCI_VC_REG12,
+		snd_soc_write(codec, DAVINCI_VC_REG12,
 			     DAVINCI_VC_REG12_POWER_ALL_OFF);
 		break;
 	}
@@ -154,11 +138,9 @@
 	struct davinci_vc *davinci_vc = codec->dev->platform_data;
 
 	davinci_vc->cq93vc.codec = codec;
-	codec->control_data = davinci_vc;
+	codec->control_data = davinci_vc->regmap;
 
-	/* Set controls */
-	snd_soc_add_codec_controls(codec, cq93vc_snd_controls,
-			     ARRAY_SIZE(cq93vc_snd_controls));
+	snd_soc_codec_set_cache_io(codec, 32, 32, SND_SOC_REGMAP);
 
 	/* Off, with power on */
 	cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -174,12 +156,12 @@
 }
 
 static struct snd_soc_codec_driver soc_codec_dev_cq93vc = {
-	.read = cq93vc_read,
-	.write = cq93vc_write,
 	.set_bias_level = cq93vc_set_bias_level,
 	.probe = cq93vc_probe,
 	.remove = cq93vc_remove,
 	.resume = cq93vc_resume,
+	.controls = cq93vc_snd_controls,
+	.num_controls = ARRAY_SIZE(cq93vc_snd_controls),
 };
 
 static int cq93vc_platform_probe(struct platform_device *pdev)
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index a20f1bb..f6e9534 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -25,6 +25,7 @@
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
+#include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
 #include <sound/pcm.h>
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c
index be2ba1b..8b427c9 100644
--- a/sound/soc/codecs/cs42l52.c
+++ b/sound/soc/codecs/cs42l52.c
@@ -17,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
@@ -1116,40 +1117,6 @@
 	cs42l52->sysclk = CS42L52_DEFAULT_CLK;
 	cs42l52->config.format = CS42L52_DEFAULT_FORMAT;
 
-	/* Set Platform MICx CFG */
-	snd_soc_update_bits(codec, CS42L52_MICA_CTL,
-			    CS42L52_MIC_CTL_TYPE_MASK,
-				cs42l52->pdata.mica_cfg <<
-				CS42L52_MIC_CTL_TYPE_SHIFT);
-
-	snd_soc_update_bits(codec, CS42L52_MICB_CTL,
-			    CS42L52_MIC_CTL_TYPE_MASK,
-				cs42l52->pdata.micb_cfg <<
-				CS42L52_MIC_CTL_TYPE_SHIFT);
-
-	/* if Single Ended, Get Mic_Select */
-	if (cs42l52->pdata.mica_cfg)
-		snd_soc_update_bits(codec, CS42L52_MICA_CTL,
-				    CS42L52_MIC_CTL_MIC_SEL_MASK,
-				cs42l52->pdata.mica_sel <<
-				CS42L52_MIC_CTL_MIC_SEL_SHIFT);
-	if (cs42l52->pdata.micb_cfg)
-		snd_soc_update_bits(codec, CS42L52_MICB_CTL,
-				    CS42L52_MIC_CTL_MIC_SEL_MASK,
-				cs42l52->pdata.micb_sel <<
-				CS42L52_MIC_CTL_MIC_SEL_SHIFT);
-
-	/* Set Platform Charge Pump Freq */
-	snd_soc_update_bits(codec, CS42L52_CHARGE_PUMP,
-			    CS42L52_CHARGE_PUMP_MASK,
-				cs42l52->pdata.chgfreq <<
-				CS42L52_CHARGE_PUMP_SHIFT);
-
-	/* Set Platform Bias Level */
-	snd_soc_update_bits(codec, CS42L52_IFACE_CTL2,
-			    CS42L52_IFACE_CTL2_BIAS_LVL,
-				cs42l52->pdata.micbias_lvl);
-
 	return ret;
 }
 
@@ -1205,6 +1172,7 @@
 			     const struct i2c_device_id *id)
 {
 	struct cs42l52_private *cs42l52;
+	struct cs42l52_platform_data *pdata = dev_get_platdata(&i2c_client->dev);
 	int ret;
 	unsigned int devid = 0;
 	unsigned int reg;
@@ -1222,11 +1190,22 @@
 		return ret;
 	}
 
-	i2c_set_clientdata(i2c_client, cs42l52);
+	if (pdata)
+		cs42l52->pdata = *pdata;
 
-	if (dev_get_platdata(&i2c_client->dev))
-		memcpy(&cs42l52->pdata, dev_get_platdata(&i2c_client->dev),
-		       sizeof(cs42l52->pdata));
+	if (cs42l52->pdata.reset_gpio) {
+		ret = gpio_request_one(cs42l52->pdata.reset_gpio,
+				       GPIOF_OUT_INIT_HIGH, "CS42L52 /RST");
+		if (ret < 0) {
+			dev_err(&i2c_client->dev, "Failed to request /RST %d: %d\n",
+				cs42l52->pdata.reset_gpio, ret);
+			return ret;
+		}
+		gpio_set_value_cansleep(cs42l52->pdata.reset_gpio, 0);
+		gpio_set_value_cansleep(cs42l52->pdata.reset_gpio, 1);
+	}
+
+	i2c_set_clientdata(i2c_client, cs42l52);
 
 	ret = regmap_register_patch(cs42l52->regmap, cs42l52_threshold_patch,
 				    ARRAY_SIZE(cs42l52_threshold_patch));
@@ -1244,7 +1223,43 @@
 		return ret;
 	}
 
-	regcache_cache_only(cs42l52->regmap, true);
+	dev_info(&i2c_client->dev, "Cirrus Logic CS42L52, Revision: %02X\n",
+			reg & 0xFF);
+
+	/* Set Platform Data */
+	if (cs42l52->pdata.mica_cfg)
+		regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL,
+				   CS42L52_MIC_CTL_TYPE_MASK,
+				cs42l52->pdata.mica_cfg <<
+				CS42L52_MIC_CTL_TYPE_SHIFT);
+
+	if (cs42l52->pdata.micb_cfg)
+		regmap_update_bits(cs42l52->regmap, CS42L52_MICB_CTL,
+				   CS42L52_MIC_CTL_TYPE_MASK,
+				cs42l52->pdata.micb_cfg <<
+				CS42L52_MIC_CTL_TYPE_SHIFT);
+
+	if (cs42l52->pdata.mica_sel)
+		regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL,
+				   CS42L52_MIC_CTL_MIC_SEL_MASK,
+				cs42l52->pdata.mica_sel <<
+				CS42L52_MIC_CTL_MIC_SEL_SHIFT);
+	if (cs42l52->pdata.micb_sel)
+		regmap_update_bits(cs42l52->regmap, CS42L52_MICB_CTL,
+				   CS42L52_MIC_CTL_MIC_SEL_MASK,
+				cs42l52->pdata.micb_sel <<
+				CS42L52_MIC_CTL_MIC_SEL_SHIFT);
+
+	if (cs42l52->pdata.chgfreq)
+		regmap_update_bits(cs42l52->regmap, CS42L52_CHARGE_PUMP,
+				   CS42L52_CHARGE_PUMP_MASK,
+				cs42l52->pdata.chgfreq <<
+				CS42L52_CHARGE_PUMP_SHIFT);
+
+	if (cs42l52->pdata.micbias_lvl)
+		regmap_update_bits(cs42l52->regmap, CS42L52_IFACE_CTL2,
+				   CS42L52_IFACE_CTL2_BIAS_LVL,
+				cs42l52->pdata.micbias_lvl);
 
 	ret =  snd_soc_register_codec(&i2c_client->dev,
 			&soc_codec_dev_cs42l52, &cs42l52_dai, 1);
diff --git a/sound/soc/codecs/cs42l52.h b/sound/soc/codecs/cs42l52.h
index 4277012..1a9412d 100644
--- a/sound/soc/codecs/cs42l52.h
+++ b/sound/soc/codecs/cs42l52.h
@@ -269,6 +269,6 @@
 #define CS42L52_FIX_BITS1			0x3E
 #define CS42L52_FIX_BITS2			0x47
 
-#define CS42L52_MAX_REGISTER			0x34
+#define CS42L52_MAX_REGISTER			0x47
 
 #endif
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
index 3b20c86..549d5d6 100644
--- a/sound/soc/codecs/cs42l73.c
+++ b/sound/soc/codecs/cs42l73.c
@@ -17,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/of_gpio.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/regmap.h>
@@ -28,6 +29,7 @@
 #include <sound/soc-dapm.h>
 #include <sound/initval.h>
 #include <sound/tlv.h>
+#include <sound/cs42l73.h>
 #include "cs42l73.h"
 
 struct sp_config {
@@ -35,6 +37,7 @@
 	u32 srate;
 };
 struct  cs42l73_private {
+	struct cs42l73_platform_data pdata;
 	struct sp_config config[3];
 	struct regmap *regmap;
 	u32 sysclk;
@@ -310,15 +313,6 @@
 	SOC_ENUM_SINGLE(CS42L73_NGCAB, 0,
 		ARRAY_SIZE(cs42l73_ng_delay_text), cs42l73_ng_delay_text);
 
-static const char * const charge_pump_freq_text[] = {
-	"0", "1", "2", "3", "4",
-	"5", "6", "7", "8", "9",
-	"10", "11", "12", "13", "14", "15" };
-
-static const struct soc_enum charge_pump_enum =
-	SOC_ENUM_SINGLE(CS42L73_CPFCHC, 4,
-		ARRAY_SIZE(charge_pump_freq_text), charge_pump_freq_text);
-
 static const char * const cs42l73_mono_mix_texts[] = {
 	"Left", "Right", "Mono Mix"};
 
@@ -511,8 +505,6 @@
 	SOC_SINGLE("NG Threshold", CS42L73_NGCAB, 2, 7, 0),
 	SOC_ENUM("NG Delay", ng_delay_enum),
 
-	SOC_ENUM("Charge Pump Frequency", charge_pump_enum),
-
 	SOC_DOUBLE_R_TLV("XSP-IP Volume",
 			CS42L73_XSPAIPAA, CS42L73_XSPBIPBA, 0, 0x3F, 1,
 			attn_tlv),
@@ -1055,11 +1047,11 @@
 
 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 	case SND_SOC_DAIFMT_CBM_CFM:
-		mmcc |= MS_MASTER;
+		mmcc |= CS42L73_MS_MASTER;
 		break;
 
 	case SND_SOC_DAIFMT_CBS_CFS:
-		mmcc &= ~MS_MASTER;
+		mmcc &= ~CS42L73_MS_MASTER;
 		break;
 
 	default:
@@ -1071,11 +1063,11 @@
 
 	switch (format) {
 	case SND_SOC_DAIFMT_I2S:
-		spc &= ~SPDIF_PCM;
+		spc &= ~CS42L73_SPDIF_PCM;
 		break;
 	case SND_SOC_DAIFMT_DSP_A:
 	case SND_SOC_DAIFMT_DSP_B:
-		if (mmcc & MS_MASTER) {
+		if (mmcc & CS42L73_MS_MASTER) {
 			dev_err(codec->dev,
 				"PCM format in slave mode only\n");
 			return -EINVAL;
@@ -1085,25 +1077,25 @@
 				"PCM format is not supported on ASP port\n");
 			return -EINVAL;
 		}
-		spc |= SPDIF_PCM;
+		spc |= CS42L73_SPDIF_PCM;
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	if (spc & SPDIF_PCM) {
+	if (spc & CS42L73_SPDIF_PCM) {
 		/* Clear PCM mode, clear PCM_BIT_ORDER bit for MSB->LSB */
-		spc &= ~(PCM_MODE_MASK | PCM_BIT_ORDER);
+		spc &= ~(CS42L73_PCM_MODE_MASK | CS42L73_PCM_BIT_ORDER);
 		switch (format) {
 		case SND_SOC_DAIFMT_DSP_B:
 			if (inv == SND_SOC_DAIFMT_IB_IF)
-				spc |= PCM_MODE0;
+				spc |= CS42L73_PCM_MODE0;
 			if (inv == SND_SOC_DAIFMT_IB_NF)
-				spc |= PCM_MODE1;
+				spc |= CS42L73_PCM_MODE1;
 		break;
 		case SND_SOC_DAIFMT_DSP_A:
 			if (inv == SND_SOC_DAIFMT_IB_IF)
-				spc |= PCM_MODE1;
+				spc |= CS42L73_PCM_MODE1;
 			break;
 		default:
 			return -EINVAL;
@@ -1163,7 +1155,7 @@
 	int mclk_coeff;
 	int srate = params_rate(params);
 
-	if (priv->config[id].mmcc & MS_MASTER) {
+	if (priv->config[id].mmcc & CS42L73_MS_MASTER) {
 		/* CS42L73 Master */
 		/* MCLK -> srate */
 		mclk_coeff =
@@ -1182,13 +1174,13 @@
 		priv->config[id].spc &= 0xFC;
 		/* Use SCLK=64*Fs if internal MCLK >= 6.4MHz */
 		if (priv->mclk >= 6400000)
-			priv->config[id].spc |= MCK_SCLK_64FS;
+			priv->config[id].spc |= CS42L73_MCK_SCLK_64FS;
 		else
-			priv->config[id].spc |= MCK_SCLK_MCLK;
+			priv->config[id].spc |= CS42L73_MCK_SCLK_MCLK;
 	} else {
 		/* CS42L73 Slave */
 		priv->config[id].spc &= 0xFC;
-		priv->config[id].spc |= MCK_SCLK_64FS;
+		priv->config[id].spc |= CS42L73_MCK_SCLK_64FS;
 	}
 	/* Update ASRCs */
 	priv->config[id].srate = srate;
@@ -1208,8 +1200,8 @@
 
 	switch (level) {
 	case SND_SOC_BIAS_ON:
-		snd_soc_update_bits(codec, CS42L73_DMMCC, MCLKDIS, 0);
-		snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 0);
+		snd_soc_update_bits(codec, CS42L73_DMMCC, CS42L73_MCLKDIS, 0);
+		snd_soc_update_bits(codec, CS42L73_PWRCTL1, CS42L73_PDN, 0);
 		break;
 
 	case SND_SOC_BIAS_PREPARE:
@@ -1220,11 +1212,11 @@
 			regcache_cache_only(cs42l73->regmap, false);
 			regcache_sync(cs42l73->regmap);
 		}
-		snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 1);
+		snd_soc_update_bits(codec, CS42L73_PWRCTL1, CS42L73_PDN, 1);
 		break;
 
 	case SND_SOC_BIAS_OFF:
-		snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 1);
+		snd_soc_update_bits(codec, CS42L73_PWRCTL1, CS42L73_PDN, 1);
 		if (cs42l73->shutdwn_delay > 0) {
 			mdelay(cs42l73->shutdwn_delay);
 			cs42l73->shutdwn_delay = 0;
@@ -1233,7 +1225,7 @@
 				     * down.
 				     */
 		}
-		snd_soc_update_bits(codec, CS42L73_DMMCC, MCLKDIS, 1);
+		snd_soc_update_bits(codec, CS42L73_DMMCC, CS42L73_MCLKDIS, 1);
 		break;
 	}
 	codec->dapm.bias_level = level;
@@ -1367,11 +1359,16 @@
 		return ret;
 	}
 
-	regcache_cache_only(cs42l73->regmap, true);
-
 	cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-	cs42l73->mclksel = CS42L73_CLKID_MCLK1;	/* MCLK1 as master clk */
+	/* Set Charge Pump Frequency */
+	if (cs42l73->pdata.chgfreq)
+		snd_soc_update_bits(codec, CS42L73_CPFCHC,
+				    CS42L73_CHARGEPUMP_MASK,
+					cs42l73->pdata.chgfreq << 4);
+
+	/* MCLK1 as master clk */
+	cs42l73->mclksel = CS42L73_CLKID_MCLK1;
 	cs42l73->mclk = 0;
 
 	return ret;
@@ -1415,9 +1412,11 @@
 			     const struct i2c_device_id *id)
 {
 	struct cs42l73_private *cs42l73;
+	struct cs42l73_platform_data *pdata = dev_get_platdata(&i2c_client->dev);
 	int ret;
 	unsigned int devid = 0;
 	unsigned int reg;
+	u32 val32;
 
 	cs42l73 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l73_private),
 			       GFP_KERNEL);
@@ -1426,14 +1425,49 @@
 		return -ENOMEM;
 	}
 
-	i2c_set_clientdata(i2c_client, cs42l73);
-
 	cs42l73->regmap = devm_regmap_init_i2c(i2c_client, &cs42l73_regmap);
 	if (IS_ERR(cs42l73->regmap)) {
 		ret = PTR_ERR(cs42l73->regmap);
 		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
 		return ret;
 	}
+
+	if (pdata) {
+		cs42l73->pdata = *pdata;
+	} else {
+		pdata = devm_kzalloc(&i2c_client->dev,
+				     sizeof(struct cs42l73_platform_data),
+				GFP_KERNEL);
+		if (!pdata) {
+			dev_err(&i2c_client->dev, "could not allocate pdata\n");
+			return -ENOMEM;
+		}
+		if (i2c_client->dev.of_node) {
+			if (of_property_read_u32(i2c_client->dev.of_node,
+				"chgfreq", &val32) >= 0)
+				pdata->chgfreq = val32;
+		}
+		pdata->reset_gpio = of_get_named_gpio(i2c_client->dev.of_node,
+						"reset-gpio", 0);
+		cs42l73->pdata = *pdata;
+	}
+
+	i2c_set_clientdata(i2c_client, cs42l73);
+
+	if (cs42l73->pdata.reset_gpio) {
+		ret = gpio_request_one(cs42l73->pdata.reset_gpio,
+				       GPIOF_OUT_INIT_HIGH, "CS42L73 /RST");
+		if (ret < 0) {
+			dev_err(&i2c_client->dev, "Failed to request /RST %d: %d\n",
+				cs42l73->pdata.reset_gpio, ret);
+			return ret;
+		}
+		gpio_set_value_cansleep(cs42l73->pdata.reset_gpio, 0);
+		gpio_set_value_cansleep(cs42l73->pdata.reset_gpio, 1);
+	}
+
+	regcache_cache_bypass(cs42l73->regmap, true);
+
 	/* initialize codec */
 	ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, &reg);
 	devid = (reg & 0xFF) << 12;
@@ -1444,7 +1478,6 @@
 	ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_E, &reg);
 	devid |= (reg & 0xF0) >> 4;
 
-
 	if (devid != CS42L73_DEVID) {
 		ret = -ENODEV;
 		dev_err(&i2c_client->dev,
@@ -1462,7 +1495,7 @@
 	dev_info(&i2c_client->dev,
 		 "Cirrus Logic CS42L73, Revision: %02X\n", reg & 0xFF);
 
-	regcache_cache_only(cs42l73->regmap, true);
+	regcache_cache_bypass(cs42l73->regmap, false);
 
 	ret =  snd_soc_register_codec(&i2c_client->dev,
 			&soc_codec_dev_cs42l73, cs42l73_dai,
@@ -1478,6 +1511,12 @@
 	return 0;
 }
 
+static const struct of_device_id cs42l73_of_match[] = {
+	{ .compatible = "cirrus,cs42l73", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, cs42l73_of_match);
+
 static const struct i2c_device_id cs42l73_id[] = {
 	{"cs42l73", 0},
 	{}
@@ -1489,6 +1528,7 @@
 	.driver = {
 		   .name = "cs42l73",
 		   .owner = THIS_MODULE,
+		   .of_match_table = cs42l73_of_match,
 		   },
 	.id_table = cs42l73_id,
 	.probe = cs42l73_i2c_probe,
diff --git a/sound/soc/codecs/cs42l73.h b/sound/soc/codecs/cs42l73.h
index f30a4c4..4574618 100644
--- a/sound/soc/codecs/cs42l73.h
+++ b/sound/soc/codecs/cs42l73.h
@@ -128,59 +128,60 @@
 /* Bitfield Definitions */
 
 /* CS42L73_PWRCTL1 */
-#define PDN_ADCB		(1 << 7)
-#define PDN_DMICB		(1 << 6)
-#define PDN_ADCA		(1 << 5)
-#define PDN_DMICA		(1 << 4)
-#define PDN_LDO			(1 << 2)
-#define DISCHG_FILT		(1 << 1)
-#define PDN			(1 << 0)
+#define CS42L73_PDN_ADCB		(1 << 7)
+#define CS42L73_PDN_DMICB		(1 << 6)
+#define CS42L73_PDN_ADCA		(1 << 5)
+#define CS42L73_PDN_DMICA		(1 << 4)
+#define CS42L73_PDN_LDO			(1 << 2)
+#define CS42L73_DISCHG_FILT		(1 << 1)
+#define CS42L73_PDN			(1 << 0)
 
 /* CS42L73_PWRCTL2 */
-#define PDN_MIC2_BIAS		(1 << 7)
-#define PDN_MIC1_BIAS		(1 << 6)
-#define PDN_VSP			(1 << 4)
-#define PDN_ASP_SDOUT		(1 << 3)
-#define PDN_ASP_SDIN		(1 << 2)
-#define PDN_XSP_SDOUT		(1 << 1)
-#define PDN_XSP_SDIN		(1 << 0)
+#define CS42L73_PDN_MIC2_BIAS		(1 << 7)
+#define CS42L73_PDN_MIC1_BIAS		(1 << 6)
+#define CS42L73_PDN_VSP			(1 << 4)
+#define CS42L73_PDN_ASP_SDOUT		(1 << 3)
+#define CS42L73_PDN_ASP_SDIN		(1 << 2)
+#define CS42L73_PDN_XSP_SDOUT		(1 << 1)
+#define CS42L73_PDN_XSP_SDIN		(1 << 0)
 
 /* CS42L73_PWRCTL3 */
-#define PDN_THMS		(1 << 5)
-#define PDN_SPKLO		(1 << 4)
-#define PDN_EAR			(1 << 3)
-#define PDN_SPK			(1 << 2)
-#define PDN_LO			(1 << 1)
-#define PDN_HP			(1 << 0)
+#define CS42L73_PDN_THMS		(1 << 5)
+#define CS42L73_PDN_SPKLO		(1 << 4)
+#define CS42L73_PDN_EAR			(1 << 3)
+#define CS42L73_PDN_SPK			(1 << 2)
+#define CS42L73_PDN_LO			(1 << 1)
+#define CS42L73_PDN_HP			(1 << 0)
 
 /* Thermal Overload Detect. Requires interrupt ... */
-#define THMOVLD_150C		0
-#define THMOVLD_132C		1
-#define THMOVLD_115C		2
-#define THMOVLD_098C		3
+#define CS42L73_THMOVLD_150C		0
+#define CS42L73_THMOVLD_132C		1
+#define CS42L73_THMOVLD_115C		2
+#define CS42L73_THMOVLD_098C		3
 
+#define CS42L73_CHARGEPUMP_MASK	(0xF0)
 
 /* CS42L73_ASPC, CS42L73_XSPC, CS42L73_VSPC */
-#define	SP_3ST			(1 << 7)
-#define SPDIF_I2S		(0 << 6)
-#define SPDIF_PCM		(1 << 6)
-#define PCM_MODE0		(0 << 4)
-#define PCM_MODE1		(1 << 4)
-#define PCM_MODE2		(2 << 4)
-#define PCM_MODE_MASK		(3 << 4)
-#define PCM_BIT_ORDER		(1 << 3)
-#define MCK_SCLK_64FS		(0 << 0)
-#define MCK_SCLK_MCLK		(2 << 0)
-#define MCK_SCLK_PREMCLK	(3 << 0)
+#define	CS42L73_SP_3ST			(1 << 7)
+#define CS42L73_SPDIF_I2S		(0 << 6)
+#define CS42L73_SPDIF_PCM		(1 << 6)
+#define CS42L73_PCM_MODE0		(0 << 4)
+#define CS42L73_PCM_MODE1		(1 << 4)
+#define CS42L73_PCM_MODE2		(2 << 4)
+#define CS42L73_PCM_MODE_MASK		(3 << 4)
+#define CS42L73_PCM_BIT_ORDER		(1 << 3)
+#define CS42L73_MCK_SCLK_64FS		(0 << 0)
+#define CS42L73_MCK_SCLK_MCLK		(2 << 0)
+#define CS42L73_MCK_SCLK_PREMCLK	(3 << 0)
 
 /* CS42L73_xSPMMCC */
-#define MS_MASTER		(1 << 7)
+#define CS42L73_MS_MASTER		(1 << 7)
 
 
 /* CS42L73_DMMCC */
-#define MCLKDIS			(1 << 0)
-#define MCLKSEL_MCLK2		(1 << 4)
-#define MCLKSEL_MCLK1		(0 << 4)
+#define CS42L73_MCLKDIS			(1 << 0)
+#define CS42L73_MCLKSEL_MCLK2		(1 << 4)
+#define CS42L73_MCLKSEL_MCLK1		(0 << 4)
 
 /* CS42L73 MCLK derived from MCLK1 or MCLK2 */
 #define CS42L73_CLKID_MCLK1     0
@@ -194,28 +195,26 @@
 #define CS42L73_VSP		2
 
 /* IS1, IM1 */
-#define MIC2_SDET		(1 << 6)
-#define THMOVLD			(1 << 4)
-#define DIGMIXOVFL		(1 << 3)
-#define IPBOVFL			(1 << 1)
-#define IPAOVFL			(1 << 0)
+#define CS42L73_MIC2_SDET		(1 << 6)
+#define CS42L73_THMOVLD			(1 << 4)
+#define CS42L73_DIGMIXOVFL		(1 << 3)
+#define CS42L73_IPBOVFL			(1 << 1)
+#define CS42L73_IPAOVFL			(1 << 0)
 
 /* Analog Softramp */
-#define ANLGOSFT		(1 << 0)
+#define CS42L73_ANLGOSFT		(1 << 0)
 
 /* HP A/B Analog Mute */
-#define HPA_MUTE		(1 << 7)
+#define CS42L73_HPA_MUTE		(1 << 7)
 /* LO A/B Analog Mute	*/
-#define LOA_MUTE		(1 << 7)
+#define CS42L73_LOA_MUTE		(1 << 7)
 /* Digital Mute */
-#define HLAD_MUTE		(1 << 0)
-#define HLBD_MUTE		(1 << 1)
-#define SPKD_MUTE		(1 << 2)
-#define ESLD_MUTE		(1 << 3)
+#define CS42L73_HLAD_MUTE		(1 << 0)
+#define CS42L73_HLBD_MUTE		(1 << 1)
+#define CS42L73_SPKD_MUTE		(1 << 2)
+#define CS42L73_ESLD_MUTE		(1 << 3)
 
 /* Misc defines for codec */
-#define CS42L73_RESET_GPIO 143
-
 #define CS42L73_DEVID		0x00042A73
 #define CS42L73_MCLKX_MIN	5644800
 #define CS42L73_MCLKX_MAX	38400000
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index 566a367..53d7dab 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -38,294 +39,223 @@
 };
 
 struct max98088_priv {
-       enum max98088_type devtype;
-       struct max98088_pdata *pdata;
-       unsigned int sysclk;
-       struct max98088_cdata dai[2];
-       int eq_textcnt;
-       const char **eq_texts;
-       struct soc_enum eq_enum;
-       u8 ina_state;
-       u8 inb_state;
-       unsigned int ex_mode;
-       unsigned int digmic;
-       unsigned int mic1pre;
-       unsigned int mic2pre;
-       unsigned int extmic_mode;
+	struct regmap *regmap;
+	enum max98088_type devtype;
+	struct max98088_pdata *pdata;
+	unsigned int sysclk;
+	struct max98088_cdata dai[2];
+	int eq_textcnt;
+	const char **eq_texts;
+	struct soc_enum eq_enum;
+	u8 ina_state;
+	u8 inb_state;
+	unsigned int ex_mode;
+	unsigned int digmic;
+	unsigned int mic1pre;
+	unsigned int mic2pre;
+	unsigned int extmic_mode;
 };
 
-static const u8 max98088_reg[M98088_REG_CNT] = {
-       0x00, /* 00 IRQ status */
-       0x00, /* 01 MIC status */
-       0x00, /* 02 jack status */
-       0x00, /* 03 battery voltage */
-       0x00, /* 04 */
-       0x00, /* 05 */
-       0x00, /* 06 */
-       0x00, /* 07 */
-       0x00, /* 08 */
-       0x00, /* 09 */
-       0x00, /* 0A */
-       0x00, /* 0B */
-       0x00, /* 0C */
-       0x00, /* 0D */
-       0x00, /* 0E */
-       0x00, /* 0F interrupt enable */
+static const struct reg_default max98088_reg[] = {
+	{  0xf, 0x00 }, /* 0F interrupt enable */
 
-       0x00, /* 10 master clock */
-       0x00, /* 11 DAI1 clock mode */
-       0x00, /* 12 DAI1 clock control */
-       0x00, /* 13 DAI1 clock control */
-       0x00, /* 14 DAI1 format */
-       0x00, /* 15 DAI1 clock */
-       0x00, /* 16 DAI1 config */
-       0x00, /* 17 DAI1 TDM */
-       0x00, /* 18 DAI1 filters */
-       0x00, /* 19 DAI2 clock mode */
-       0x00, /* 1A DAI2 clock control */
-       0x00, /* 1B DAI2 clock control */
-       0x00, /* 1C DAI2 format */
-       0x00, /* 1D DAI2 clock */
-       0x00, /* 1E DAI2 config */
-       0x00, /* 1F DAI2 TDM */
+	{ 0x10, 0x00 }, /* 10 master clock */
+	{ 0x11, 0x00 }, /* 11 DAI1 clock mode */
+	{ 0x12, 0x00 }, /* 12 DAI1 clock control */
+	{ 0x13, 0x00 }, /* 13 DAI1 clock control */
+	{ 0x14, 0x00 }, /* 14 DAI1 format */
+	{ 0x15, 0x00 }, /* 15 DAI1 clock */
+	{ 0x16, 0x00 }, /* 16 DAI1 config */
+	{ 0x17, 0x00 }, /* 17 DAI1 TDM */
+	{ 0x18, 0x00 }, /* 18 DAI1 filters */
+	{ 0x19, 0x00 }, /* 19 DAI2 clock mode */
+	{ 0x1a, 0x00 }, /* 1A DAI2 clock control */
+	{ 0x1b, 0x00 }, /* 1B DAI2 clock control */
+	{ 0x1c, 0x00 }, /* 1C DAI2 format */
+	{ 0x1d, 0x00 }, /* 1D DAI2 clock */
+	{ 0x1e, 0x00 }, /* 1E DAI2 config */
+	{ 0x1f, 0x00 }, /* 1F DAI2 TDM */
 
-       0x00, /* 20 DAI2 filters */
-       0x00, /* 21 data config */
-       0x00, /* 22 DAC mixer */
-       0x00, /* 23 left ADC mixer */
-       0x00, /* 24 right ADC mixer */
-       0x00, /* 25 left HP mixer */
-       0x00, /* 26 right HP mixer */
-       0x00, /* 27 HP control */
-       0x00, /* 28 left REC mixer */
-       0x00, /* 29 right REC mixer */
-       0x00, /* 2A REC control */
-       0x00, /* 2B left SPK mixer */
-       0x00, /* 2C right SPK mixer */
-       0x00, /* 2D SPK control */
-       0x00, /* 2E sidetone */
-       0x00, /* 2F DAI1 playback level */
+	{ 0x20, 0x00 }, /* 20 DAI2 filters */
+	{ 0x21, 0x00 }, /* 21 data config */
+	{ 0x22, 0x00 }, /* 22 DAC mixer */
+	{ 0x23, 0x00 }, /* 23 left ADC mixer */
+	{ 0x24, 0x00 }, /* 24 right ADC mixer */
+	{ 0x25, 0x00 }, /* 25 left HP mixer */
+	{ 0x26, 0x00 }, /* 26 right HP mixer */
+	{ 0x27, 0x00 }, /* 27 HP control */
+	{ 0x28, 0x00 }, /* 28 left REC mixer */
+	{ 0x29, 0x00 }, /* 29 right REC mixer */
+	{ 0x2a, 0x00 }, /* 2A REC control */
+	{ 0x2b, 0x00 }, /* 2B left SPK mixer */
+	{ 0x2c, 0x00 }, /* 2C right SPK mixer */
+	{ 0x2d, 0x00 }, /* 2D SPK control */
+	{ 0x2e, 0x00 }, /* 2E sidetone */
+	{ 0x2f, 0x00 }, /* 2F DAI1 playback level */
 
-       0x00, /* 30 DAI1 playback level */
-       0x00, /* 31 DAI2 playback level */
-       0x00, /* 32 DAI2 playbakc level */
-       0x00, /* 33 left ADC level */
-       0x00, /* 34 right ADC level */
-       0x00, /* 35 MIC1 level */
-       0x00, /* 36 MIC2 level */
-       0x00, /* 37 INA level */
-       0x00, /* 38 INB level */
-       0x00, /* 39 left HP volume */
-       0x00, /* 3A right HP volume */
-       0x00, /* 3B left REC volume */
-       0x00, /* 3C right REC volume */
-       0x00, /* 3D left SPK volume */
-       0x00, /* 3E right SPK volume */
-       0x00, /* 3F MIC config */
+	{ 0x30, 0x00 }, /* 30 DAI1 playback level */
+	{ 0x31, 0x00 }, /* 31 DAI2 playback level */
+	{ 0x32, 0x00 }, /* 32 DAI2 playbakc level */
+	{ 0x33, 0x00 }, /* 33 left ADC level */
+	{ 0x34, 0x00 }, /* 34 right ADC level */
+	{ 0x35, 0x00 }, /* 35 MIC1 level */
+	{ 0x36, 0x00 }, /* 36 MIC2 level */
+	{ 0x37, 0x00 }, /* 37 INA level */
+	{ 0x38, 0x00 }, /* 38 INB level */
+	{ 0x39, 0x00 }, /* 39 left HP volume */
+	{ 0x3a, 0x00 }, /* 3A right HP volume */
+	{ 0x3b, 0x00 }, /* 3B left REC volume */
+	{ 0x3c, 0x00 }, /* 3C right REC volume */
+	{ 0x3d, 0x00 }, /* 3D left SPK volume */
+	{ 0x3e, 0x00 }, /* 3E right SPK volume */
+	{ 0x3f, 0x00 }, /* 3F MIC config */
 
-       0x00, /* 40 MIC threshold */
-       0x00, /* 41 excursion limiter filter */
-       0x00, /* 42 excursion limiter threshold */
-       0x00, /* 43 ALC */
-       0x00, /* 44 power limiter threshold */
-       0x00, /* 45 power limiter config */
-       0x00, /* 46 distortion limiter config */
-       0x00, /* 47 audio input */
-       0x00, /* 48 microphone */
-       0x00, /* 49 level control */
-       0x00, /* 4A bypass switches */
-       0x00, /* 4B jack detect */
-       0x00, /* 4C input enable */
-       0x00, /* 4D output enable */
-       0xF0, /* 4E bias control */
-       0x00, /* 4F DAC power */
+	{ 0x40, 0x00 }, /* 40 MIC threshold */
+	{ 0x41, 0x00 }, /* 41 excursion limiter filter */
+	{ 0x42, 0x00 }, /* 42 excursion limiter threshold */
+	{ 0x43, 0x00 }, /* 43 ALC */
+	{ 0x44, 0x00 }, /* 44 power limiter threshold */
+	{ 0x45, 0x00 }, /* 45 power limiter config */
+	{ 0x46, 0x00 }, /* 46 distortion limiter config */
+	{ 0x47, 0x00 }, /* 47 audio input */
+        { 0x48, 0x00 }, /* 48 microphone */
+	{ 0x49, 0x00 }, /* 49 level control */
+	{ 0x4a, 0x00 }, /* 4A bypass switches */
+	{ 0x4b, 0x00 }, /* 4B jack detect */
+	{ 0x4c, 0x00 }, /* 4C input enable */
+	{ 0x4d, 0x00 }, /* 4D output enable */
+	{ 0x4e, 0xF0 }, /* 4E bias control */
+	{ 0x4f, 0x00 }, /* 4F DAC power */
 
-       0x0F, /* 50 DAC power */
-       0x00, /* 51 system */
-       0x00, /* 52 DAI1 EQ1 */
-       0x00, /* 53 DAI1 EQ1 */
-       0x00, /* 54 DAI1 EQ1 */
-       0x00, /* 55 DAI1 EQ1 */
-       0x00, /* 56 DAI1 EQ1 */
-       0x00, /* 57 DAI1 EQ1 */
-       0x00, /* 58 DAI1 EQ1 */
-       0x00, /* 59 DAI1 EQ1 */
-       0x00, /* 5A DAI1 EQ1 */
-       0x00, /* 5B DAI1 EQ1 */
-       0x00, /* 5C DAI1 EQ2 */
-       0x00, /* 5D DAI1 EQ2 */
-       0x00, /* 5E DAI1 EQ2 */
-       0x00, /* 5F DAI1 EQ2 */
+	{ 0x50, 0x0F }, /* 50 DAC power */
+	{ 0x51, 0x00 }, /* 51 system */
+	{ 0x52, 0x00 }, /* 52 DAI1 EQ1 */
+	{ 0x53, 0x00 }, /* 53 DAI1 EQ1 */
+	{ 0x54, 0x00 }, /* 54 DAI1 EQ1 */
+	{ 0x55, 0x00 }, /* 55 DAI1 EQ1 */
+	{ 0x56, 0x00 }, /* 56 DAI1 EQ1 */
+	{ 0x57, 0x00 }, /* 57 DAI1 EQ1 */
+	{ 0x58, 0x00 }, /* 58 DAI1 EQ1 */
+	{ 0x59, 0x00 }, /* 59 DAI1 EQ1 */
+	{ 0x5a, 0x00 }, /* 5A DAI1 EQ1 */
+	{ 0x5b, 0x00 }, /* 5B DAI1 EQ1 */
+	{ 0x5c, 0x00 }, /* 5C DAI1 EQ2 */
+	{ 0x5d, 0x00 }, /* 5D DAI1 EQ2 */
+	{ 0x5e, 0x00 }, /* 5E DAI1 EQ2 */
+	{ 0x5f, 0x00 }, /* 5F DAI1 EQ2 */
 
-       0x00, /* 60 DAI1 EQ2 */
-       0x00, /* 61 DAI1 EQ2 */
-       0x00, /* 62 DAI1 EQ2 */
-       0x00, /* 63 DAI1 EQ2 */
-       0x00, /* 64 DAI1 EQ2 */
-       0x00, /* 65 DAI1 EQ2 */
-       0x00, /* 66 DAI1 EQ3 */
-       0x00, /* 67 DAI1 EQ3 */
-       0x00, /* 68 DAI1 EQ3 */
-       0x00, /* 69 DAI1 EQ3 */
-       0x00, /* 6A DAI1 EQ3 */
-       0x00, /* 6B DAI1 EQ3 */
-       0x00, /* 6C DAI1 EQ3 */
-       0x00, /* 6D DAI1 EQ3 */
-       0x00, /* 6E DAI1 EQ3 */
-       0x00, /* 6F DAI1 EQ3 */
+	{ 0x60, 0x00 }, /* 60 DAI1 EQ2 */
+	{ 0x61, 0x00 }, /* 61 DAI1 EQ2 */
+	{ 0x62, 0x00 }, /* 62 DAI1 EQ2 */
+	{ 0x63, 0x00 }, /* 63 DAI1 EQ2 */
+	{ 0x64, 0x00 }, /* 64 DAI1 EQ2 */
+	{ 0x65, 0x00 }, /* 65 DAI1 EQ2 */
+	{ 0x66, 0x00 }, /* 66 DAI1 EQ3 */
+	{ 0x67, 0x00 }, /* 67 DAI1 EQ3 */
+	{ 0x68, 0x00 }, /* 68 DAI1 EQ3 */
+	{ 0x69, 0x00 }, /* 69 DAI1 EQ3 */
+	{ 0x6a, 0x00 }, /* 6A DAI1 EQ3 */
+	{ 0x6b, 0x00 }, /* 6B DAI1 EQ3 */
+	{ 0x6c, 0x00 }, /* 6C DAI1 EQ3 */
+	{ 0x6d, 0x00 }, /* 6D DAI1 EQ3 */
+	{ 0x6e, 0x00 }, /* 6E DAI1 EQ3 */
+	{ 0x6f, 0x00 }, /* 6F DAI1 EQ3 */
 
-       0x00, /* 70 DAI1 EQ4 */
-       0x00, /* 71 DAI1 EQ4 */
-       0x00, /* 72 DAI1 EQ4 */
-       0x00, /* 73 DAI1 EQ4 */
-       0x00, /* 74 DAI1 EQ4 */
-       0x00, /* 75 DAI1 EQ4 */
-       0x00, /* 76 DAI1 EQ4 */
-       0x00, /* 77 DAI1 EQ4 */
-       0x00, /* 78 DAI1 EQ4 */
-       0x00, /* 79 DAI1 EQ4 */
-       0x00, /* 7A DAI1 EQ5 */
-       0x00, /* 7B DAI1 EQ5 */
-       0x00, /* 7C DAI1 EQ5 */
-       0x00, /* 7D DAI1 EQ5 */
-       0x00, /* 7E DAI1 EQ5 */
-       0x00, /* 7F DAI1 EQ5 */
+	{ 0x70, 0x00 }, /* 70 DAI1 EQ4 */
+	{ 0x71, 0x00 }, /* 71 DAI1 EQ4 */
+	{ 0x72, 0x00 }, /* 72 DAI1 EQ4 */
+	{ 0x73, 0x00 }, /* 73 DAI1 EQ4 */
+	{ 0x74, 0x00 }, /* 74 DAI1 EQ4 */
+	{ 0x75, 0x00 }, /* 75 DAI1 EQ4 */
+	{ 0x76, 0x00 }, /* 76 DAI1 EQ4 */
+	{ 0x77, 0x00 }, /* 77 DAI1 EQ4 */
+	{ 0x78, 0x00 }, /* 78 DAI1 EQ4 */
+	{ 0x79, 0x00 }, /* 79 DAI1 EQ4 */
+	{ 0x7a, 0x00 }, /* 7A DAI1 EQ5 */
+	{ 0x7b, 0x00 }, /* 7B DAI1 EQ5 */
+	{ 0x7c, 0x00 }, /* 7C DAI1 EQ5 */
+	{ 0x7d, 0x00 }, /* 7D DAI1 EQ5 */
+	{ 0x7e, 0x00 }, /* 7E DAI1 EQ5 */
+	{ 0x7f, 0x00 }, /* 7F DAI1 EQ5 */
 
-       0x00, /* 80 DAI1 EQ5 */
-       0x00, /* 81 DAI1 EQ5 */
-       0x00, /* 82 DAI1 EQ5 */
-       0x00, /* 83 DAI1 EQ5 */
-       0x00, /* 84 DAI2 EQ1 */
-       0x00, /* 85 DAI2 EQ1 */
-       0x00, /* 86 DAI2 EQ1 */
-       0x00, /* 87 DAI2 EQ1 */
-       0x00, /* 88 DAI2 EQ1 */
-       0x00, /* 89 DAI2 EQ1 */
-       0x00, /* 8A DAI2 EQ1 */
-       0x00, /* 8B DAI2 EQ1 */
-       0x00, /* 8C DAI2 EQ1 */
-       0x00, /* 8D DAI2 EQ1 */
-       0x00, /* 8E DAI2 EQ2 */
-       0x00, /* 8F DAI2 EQ2 */
+	{ 0x80, 0x00 }, /* 80 DAI1 EQ5 */
+	{ 0x81, 0x00 }, /* 81 DAI1 EQ5 */
+	{ 0x82, 0x00 }, /* 82 DAI1 EQ5 */
+	{ 0x83, 0x00 }, /* 83 DAI1 EQ5 */
+	{ 0x84, 0x00 }, /* 84 DAI2 EQ1 */
+	{ 0x85, 0x00 }, /* 85 DAI2 EQ1 */
+	{ 0x86, 0x00 }, /* 86 DAI2 EQ1 */
+	{ 0x87, 0x00 }, /* 87 DAI2 EQ1 */
+	{ 0x88, 0x00 }, /* 88 DAI2 EQ1 */
+	{ 0x89, 0x00 }, /* 89 DAI2 EQ1 */
+	{ 0x8a, 0x00 }, /* 8A DAI2 EQ1 */
+	{ 0x8b, 0x00 }, /* 8B DAI2 EQ1 */
+	{ 0x8c, 0x00 }, /* 8C DAI2 EQ1 */
+	{ 0x8d, 0x00 }, /* 8D DAI2 EQ1 */
+	{ 0x8e, 0x00 }, /* 8E DAI2 EQ2 */
+	{ 0x8f, 0x00 }, /* 8F DAI2 EQ2 */
 
-       0x00, /* 90 DAI2 EQ2 */
-       0x00, /* 91 DAI2 EQ2 */
-       0x00, /* 92 DAI2 EQ2 */
-       0x00, /* 93 DAI2 EQ2 */
-       0x00, /* 94 DAI2 EQ2 */
-       0x00, /* 95 DAI2 EQ2 */
-       0x00, /* 96 DAI2 EQ2 */
-       0x00, /* 97 DAI2 EQ2 */
-       0x00, /* 98 DAI2 EQ3 */
-       0x00, /* 99 DAI2 EQ3 */
-       0x00, /* 9A DAI2 EQ3 */
-       0x00, /* 9B DAI2 EQ3 */
-       0x00, /* 9C DAI2 EQ3 */
-       0x00, /* 9D DAI2 EQ3 */
-       0x00, /* 9E DAI2 EQ3 */
-       0x00, /* 9F DAI2 EQ3 */
+	{ 0x90, 0x00 }, /* 90 DAI2 EQ2 */
+	{ 0x91, 0x00 }, /* 91 DAI2 EQ2 */
+	{ 0x92, 0x00 }, /* 92 DAI2 EQ2 */
+	{ 0x93, 0x00 }, /* 93 DAI2 EQ2 */
+	{ 0x94, 0x00 }, /* 94 DAI2 EQ2 */
+	{ 0x95, 0x00 }, /* 95 DAI2 EQ2 */
+	{ 0x96, 0x00 }, /* 96 DAI2 EQ2 */
+	{ 0x97, 0x00 }, /* 97 DAI2 EQ2 */
+	{ 0x98, 0x00 }, /* 98 DAI2 EQ3 */
+	{ 0x99, 0x00 }, /* 99 DAI2 EQ3 */
+	{ 0x9a, 0x00 }, /* 9A DAI2 EQ3 */
+        { 0x9b, 0x00 }, /* 9B DAI2 EQ3 */
+	{ 0x9c, 0x00 }, /* 9C DAI2 EQ3 */
+	{ 0x9d, 0x00 }, /* 9D DAI2 EQ3 */
+	{ 0x9e, 0x00 }, /* 9E DAI2 EQ3 */
+	{ 0x9f, 0x00 }, /* 9F DAI2 EQ3 */
 
-       0x00, /* A0 DAI2 EQ3 */
-       0x00, /* A1 DAI2 EQ3 */
-       0x00, /* A2 DAI2 EQ4 */
-       0x00, /* A3 DAI2 EQ4 */
-       0x00, /* A4 DAI2 EQ4 */
-       0x00, /* A5 DAI2 EQ4 */
-       0x00, /* A6 DAI2 EQ4 */
-       0x00, /* A7 DAI2 EQ4 */
-       0x00, /* A8 DAI2 EQ4 */
-       0x00, /* A9 DAI2 EQ4 */
-       0x00, /* AA DAI2 EQ4 */
-       0x00, /* AB DAI2 EQ4 */
-       0x00, /* AC DAI2 EQ5 */
-       0x00, /* AD DAI2 EQ5 */
-       0x00, /* AE DAI2 EQ5 */
-       0x00, /* AF DAI2 EQ5 */
+	{ 0xa0, 0x00 }, /* A0 DAI2 EQ3 */
+	{ 0xa1, 0x00 }, /* A1 DAI2 EQ3 */
+	{ 0xa2, 0x00 }, /* A2 DAI2 EQ4 */
+	{ 0xa3, 0x00 }, /* A3 DAI2 EQ4 */
+	{ 0xa4, 0x00 }, /* A4 DAI2 EQ4 */
+	{ 0xa5, 0x00 }, /* A5 DAI2 EQ4 */
+	{ 0xa6, 0x00 }, /* A6 DAI2 EQ4 */
+	{ 0xa7, 0x00 }, /* A7 DAI2 EQ4 */
+	{ 0xa8, 0x00 }, /* A8 DAI2 EQ4 */
+	{ 0xa9, 0x00 }, /* A9 DAI2 EQ4 */
+	{ 0xaa, 0x00 }, /* AA DAI2 EQ4 */
+	{ 0xab, 0x00 }, /* AB DAI2 EQ4 */
+	{ 0xac, 0x00 }, /* AC DAI2 EQ5 */
+	{ 0xad, 0x00 }, /* AD DAI2 EQ5 */
+	{ 0xae, 0x00 }, /* AE DAI2 EQ5 */
+	{ 0xaf, 0x00 }, /* AF DAI2 EQ5 */
 
-       0x00, /* B0 DAI2 EQ5 */
-       0x00, /* B1 DAI2 EQ5 */
-       0x00, /* B2 DAI2 EQ5 */
-       0x00, /* B3 DAI2 EQ5 */
-       0x00, /* B4 DAI2 EQ5 */
-       0x00, /* B5 DAI2 EQ5 */
-       0x00, /* B6 DAI1 biquad */
-       0x00, /* B7 DAI1 biquad */
-       0x00, /* B8 DAI1 biquad */
-       0x00, /* B9 DAI1 biquad */
-       0x00, /* BA DAI1 biquad */
-       0x00, /* BB DAI1 biquad */
-       0x00, /* BC DAI1 biquad */
-       0x00, /* BD DAI1 biquad */
-       0x00, /* BE DAI1 biquad */
-       0x00, /* BF DAI1 biquad */
+	{ 0xb0, 0x00 }, /* B0 DAI2 EQ5 */
+	{ 0xb1, 0x00 }, /* B1 DAI2 EQ5 */
+	{ 0xb2, 0x00 }, /* B2 DAI2 EQ5 */
+	{ 0xb3, 0x00 }, /* B3 DAI2 EQ5 */
+	{ 0xb4, 0x00 }, /* B4 DAI2 EQ5 */
+	{ 0xb5, 0x00 }, /* B5 DAI2 EQ5 */
+	{ 0xb6, 0x00 }, /* B6 DAI1 biquad */
+	{ 0xb7, 0x00 }, /* B7 DAI1 biquad */
+	{ 0xb8 ,0x00 }, /* B8 DAI1 biquad */
+	{ 0xb9, 0x00 }, /* B9 DAI1 biquad */
+	{ 0xba, 0x00 }, /* BA DAI1 biquad */
+	{ 0xbb, 0x00 }, /* BB DAI1 biquad */
+	{ 0xbc, 0x00 }, /* BC DAI1 biquad */
+	{ 0xbd, 0x00 }, /* BD DAI1 biquad */
+	{ 0xbe, 0x00 }, /* BE DAI1 biquad */
+        { 0xbf, 0x00 }, /* BF DAI1 biquad */
 
-       0x00, /* C0 DAI2 biquad */
-       0x00, /* C1 DAI2 biquad */
-       0x00, /* C2 DAI2 biquad */
-       0x00, /* C3 DAI2 biquad */
-       0x00, /* C4 DAI2 biquad */
-       0x00, /* C5 DAI2 biquad */
-       0x00, /* C6 DAI2 biquad */
-       0x00, /* C7 DAI2 biquad */
-       0x00, /* C8 DAI2 biquad */
-       0x00, /* C9 DAI2 biquad */
-       0x00, /* CA */
-       0x00, /* CB */
-       0x00, /* CC */
-       0x00, /* CD */
-       0x00, /* CE */
-       0x00, /* CF */
-
-       0x00, /* D0 */
-       0x00, /* D1 */
-       0x00, /* D2 */
-       0x00, /* D3 */
-       0x00, /* D4 */
-       0x00, /* D5 */
-       0x00, /* D6 */
-       0x00, /* D7 */
-       0x00, /* D8 */
-       0x00, /* D9 */
-       0x00, /* DA */
-       0x70, /* DB */
-       0x00, /* DC */
-       0x00, /* DD */
-       0x00, /* DE */
-       0x00, /* DF */
-
-       0x00, /* E0 */
-       0x00, /* E1 */
-       0x00, /* E2 */
-       0x00, /* E3 */
-       0x00, /* E4 */
-       0x00, /* E5 */
-       0x00, /* E6 */
-       0x00, /* E7 */
-       0x00, /* E8 */
-       0x00, /* E9 */
-       0x00, /* EA */
-       0x00, /* EB */
-       0x00, /* EC */
-       0x00, /* ED */
-       0x00, /* EE */
-       0x00, /* EF */
-
-       0x00, /* F0 */
-       0x00, /* F1 */
-       0x00, /* F2 */
-       0x00, /* F3 */
-       0x00, /* F4 */
-       0x00, /* F5 */
-       0x00, /* F6 */
-       0x00, /* F7 */
-       0x00, /* F8 */
-       0x00, /* F9 */
-       0x00, /* FA */
-       0x00, /* FB */
-       0x00, /* FC */
-       0x00, /* FD */
-       0x00, /* FE */
-       0x00, /* FF */
+	{ 0xc0, 0x00 }, /* C0 DAI2 biquad */
+	{ 0xc1, 0x00 }, /* C1 DAI2 biquad */
+	{ 0xc2, 0x00 }, /* C2 DAI2 biquad */
+	{ 0xc3, 0x00 }, /* C3 DAI2 biquad */
+	{ 0xc4, 0x00 }, /* C4 DAI2 biquad */
+	{ 0xc5, 0x00 }, /* C5 DAI2 biquad */
+	{ 0xc6, 0x00 }, /* C6 DAI2 biquad */
+	{ 0xc7, 0x00 }, /* C7 DAI2 biquad */
+	{ 0xc8, 0x00 }, /* C8 DAI2 biquad */
+	{ 0xc9, 0x00 }, /* C9 DAI2 biquad */
 };
 
 static struct {
@@ -606,11 +536,28 @@
        { 0xFF, 0x00, 1 }, /* FF */
 };
 
-static int max98088_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+static bool max98088_readable_register(struct device *dev, unsigned int reg)
+{
+       return max98088_access[reg].readable;
+}
+
+static bool max98088_volatile_register(struct device *dev, unsigned int reg)
 {
        return max98088_access[reg].vol;
 }
 
+static const struct regmap_config max98088_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.readable_reg = max98088_readable_register,
+	.volatile_reg = max98088_volatile_register,
+	.max_register = 0xff,
+
+	.reg_defaults = max98088_reg,
+	.num_reg_defaults = ARRAY_SIZE(max98088_reg),
+	.cache_type = REGCACHE_RBTREE,
+};
 
 /*
  * Load equalizer DSP coefficient configurations registers
@@ -621,8 +568,9 @@
        unsigned int eq_reg;
        unsigned int i;
 
-       BUG_ON(band > 4);
-       BUG_ON(dai > 1);
+	if (WARN_ON(band > 4) ||
+	    WARN_ON(dai > 1))
+		return;
 
        /* Load the base register address */
        eq_reg = dai ? M98088_REG_84_DAI2_EQ_BASE : M98088_REG_52_DAI1_EQ_BASE;
@@ -962,7 +910,8 @@
        struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
        u8 *state;
 
-       BUG_ON(!((channel == 1) || (channel == 2)));
+	if (WARN_ON(!(channel == 1 || channel == 2)))
+		return -EINVAL;
 
        switch (line) {
        case LINE_INA:
@@ -1610,58 +1559,34 @@
        return 0;
 }
 
-static void max98088_sync_cache(struct snd_soc_codec *codec)
-{
-       u8 *reg_cache = codec->reg_cache;
-       int i;
-
-       if (!codec->cache_sync)
-               return;
-
-       codec->cache_only = 0;
-
-       /* write back cached values if they're writeable and
-        * different from the hardware default.
-        */
-       for (i = 1; i < codec->driver->reg_cache_size; i++) {
-               if (!max98088_access[i].writable)
-                       continue;
-
-               if (reg_cache[i] == max98088_reg[i])
-                       continue;
-
-               snd_soc_write(codec, i, reg_cache[i]);
-       }
-
-       codec->cache_sync = 0;
-}
-
 static int max98088_set_bias_level(struct snd_soc_codec *codec,
                                   enum snd_soc_bias_level level)
 {
-       switch (level) {
-       case SND_SOC_BIAS_ON:
-               break;
+	struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
 
-       case SND_SOC_BIAS_PREPARE:
-               break;
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		break;
 
-       case SND_SOC_BIAS_STANDBY:
-               if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
-                       max98088_sync_cache(codec);
+	case SND_SOC_BIAS_PREPARE:
+		break;
 
-               snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
-                               M98088_MBEN, M98088_MBEN);
-               break;
+	case SND_SOC_BIAS_STANDBY:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
+			regcache_sync(max98088->regmap);
 
-       case SND_SOC_BIAS_OFF:
-               snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
-                               M98088_MBEN, 0);
-               codec->cache_sync = 1;
-               break;
-       }
-       codec->dapm.bias_level = level;
-       return 0;
+		snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
+				   M98088_MBEN, M98088_MBEN);
+		break;
+
+	case SND_SOC_BIAS_OFF:
+		snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
+				    M98088_MBEN, 0);
+		regcache_mark_dirty(max98088->regmap);
+		break;
+	}
+	codec->dapm.bias_level = level;
+	return 0;
 }
 
 #define MAX98088_RATES SNDRV_PCM_RATE_8000_96000
@@ -1988,9 +1913,9 @@
        struct max98088_cdata *cdata;
        int ret = 0;
 
-       codec->cache_sync = 1;
+       regcache_mark_dirty(max98088->regmap);
 
-       ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
@@ -2048,9 +1973,6 @@
 
        max98088_handle_pdata(codec);
 
-       snd_soc_add_codec_controls(codec, max98088_snd_controls,
-                            ARRAY_SIZE(max98088_snd_controls));
-
 err_access:
        return ret;
 }
@@ -2066,15 +1988,13 @@
 }
 
 static struct snd_soc_codec_driver soc_codec_dev_max98088 = {
-       .probe   = max98088_probe,
-       .remove  = max98088_remove,
-       .suspend = max98088_suspend,
-       .resume  = max98088_resume,
-       .set_bias_level = max98088_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(max98088_reg),
-       .reg_word_size = sizeof(u8),
-       .reg_cache_default = max98088_reg,
-       .volatile_register = max98088_volatile_register,
+	.probe   = max98088_probe,
+	.remove  = max98088_remove,
+	.suspend = max98088_suspend,
+	.resume  = max98088_resume,
+	.set_bias_level = max98088_set_bias_level,
+	.controls = max98088_snd_controls,
+	.num_controls = ARRAY_SIZE(max98088_snd_controls),
 	.dapm_widgets = max98088_dapm_widgets,
 	.num_dapm_widgets = ARRAY_SIZE(max98088_dapm_widgets),
 	.dapm_routes = max98088_audio_map,
@@ -2082,7 +2002,7 @@
 };
 
 static int max98088_i2c_probe(struct i2c_client *i2c,
-                            const struct i2c_device_id *id)
+			      const struct i2c_device_id *id)
 {
        struct max98088_priv *max98088;
        int ret;
@@ -2092,6 +2012,10 @@
        if (max98088 == NULL)
                return -ENOMEM;
 
+       max98088->regmap = devm_regmap_init_i2c(i2c, &max98088_regmap);
+       if (IS_ERR(max98088->regmap))
+	       return PTR_ERR(max98088->regmap);
+
        max98088->devtype = id->driver_data;
 
        i2c_set_clientdata(i2c, max98088);
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index 8dbcacd..6724431 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -39,6 +39,7 @@
 };
 
 struct max98095_priv {
+	struct regmap *regmap;
 	enum max98095_type devtype;
 	struct max98095_pdata *pdata;
 	unsigned int sysclk;
@@ -56,263 +57,145 @@
 	struct snd_soc_jack *mic_jack;
 };
 
-static const u8 max98095_reg_def[M98095_REG_CNT] = {
-	0x00, /* 00 */
-	0x00, /* 01 */
-	0x00, /* 02 */
-	0x00, /* 03 */
-	0x00, /* 04 */
-	0x00, /* 05 */
-	0x00, /* 06 */
-	0x00, /* 07 */
-	0x00, /* 08 */
-	0x00, /* 09 */
-	0x00, /* 0A */
-	0x00, /* 0B */
-	0x00, /* 0C */
-	0x00, /* 0D */
-	0x00, /* 0E */
-	0x00, /* 0F */
-	0x00, /* 10 */
-	0x00, /* 11 */
-	0x00, /* 12 */
-	0x00, /* 13 */
-	0x00, /* 14 */
-	0x00, /* 15 */
-	0x00, /* 16 */
-	0x00, /* 17 */
-	0x00, /* 18 */
-	0x00, /* 19 */
-	0x00, /* 1A */
-	0x00, /* 1B */
-	0x00, /* 1C */
-	0x00, /* 1D */
-	0x00, /* 1E */
-	0x00, /* 1F */
-	0x00, /* 20 */
-	0x00, /* 21 */
-	0x00, /* 22 */
-	0x00, /* 23 */
-	0x00, /* 24 */
-	0x00, /* 25 */
-	0x00, /* 26 */
-	0x00, /* 27 */
-	0x00, /* 28 */
-	0x00, /* 29 */
-	0x00, /* 2A */
-	0x00, /* 2B */
-	0x00, /* 2C */
-	0x00, /* 2D */
-	0x00, /* 2E */
-	0x00, /* 2F */
-	0x00, /* 30 */
-	0x00, /* 31 */
-	0x00, /* 32 */
-	0x00, /* 33 */
-	0x00, /* 34 */
-	0x00, /* 35 */
-	0x00, /* 36 */
-	0x00, /* 37 */
-	0x00, /* 38 */
-	0x00, /* 39 */
-	0x00, /* 3A */
-	0x00, /* 3B */
-	0x00, /* 3C */
-	0x00, /* 3D */
-	0x00, /* 3E */
-	0x00, /* 3F */
-	0x00, /* 40 */
-	0x00, /* 41 */
-	0x00, /* 42 */
-	0x00, /* 43 */
-	0x00, /* 44 */
-	0x00, /* 45 */
-	0x00, /* 46 */
-	0x00, /* 47 */
-	0x00, /* 48 */
-	0x00, /* 49 */
-	0x00, /* 4A */
-	0x00, /* 4B */
-	0x00, /* 4C */
-	0x00, /* 4D */
-	0x00, /* 4E */
-	0x00, /* 4F */
-	0x00, /* 50 */
-	0x00, /* 51 */
-	0x00, /* 52 */
-	0x00, /* 53 */
-	0x00, /* 54 */
-	0x00, /* 55 */
-	0x00, /* 56 */
-	0x00, /* 57 */
-	0x00, /* 58 */
-	0x00, /* 59 */
-	0x00, /* 5A */
-	0x00, /* 5B */
-	0x00, /* 5C */
-	0x00, /* 5D */
-	0x00, /* 5E */
-	0x00, /* 5F */
-	0x00, /* 60 */
-	0x00, /* 61 */
-	0x00, /* 62 */
-	0x00, /* 63 */
-	0x00, /* 64 */
-	0x00, /* 65 */
-	0x00, /* 66 */
-	0x00, /* 67 */
-	0x00, /* 68 */
-	0x00, /* 69 */
-	0x00, /* 6A */
-	0x00, /* 6B */
-	0x00, /* 6C */
-	0x00, /* 6D */
-	0x00, /* 6E */
-	0x00, /* 6F */
-	0x00, /* 70 */
-	0x00, /* 71 */
-	0x00, /* 72 */
-	0x00, /* 73 */
-	0x00, /* 74 */
-	0x00, /* 75 */
-	0x00, /* 76 */
-	0x00, /* 77 */
-	0x00, /* 78 */
-	0x00, /* 79 */
-	0x00, /* 7A */
-	0x00, /* 7B */
-	0x00, /* 7C */
-	0x00, /* 7D */
-	0x00, /* 7E */
-	0x00, /* 7F */
-	0x00, /* 80 */
-	0x00, /* 81 */
-	0x00, /* 82 */
-	0x00, /* 83 */
-	0x00, /* 84 */
-	0x00, /* 85 */
-	0x00, /* 86 */
-	0x00, /* 87 */
-	0x00, /* 88 */
-	0x00, /* 89 */
-	0x00, /* 8A */
-	0x00, /* 8B */
-	0x00, /* 8C */
-	0x00, /* 8D */
-	0x00, /* 8E */
-	0x00, /* 8F */
-	0x00, /* 90 */
-	0x00, /* 91 */
-	0x30, /* 92 */
-	0xF0, /* 93 */
-	0x00, /* 94 */
-	0x00, /* 95 */
-	0x3F, /* 96 */
-	0x00, /* 97 */
-	0x00, /* 98 */
-	0x00, /* 99 */
-	0x00, /* 9A */
-	0x00, /* 9B */
-	0x00, /* 9C */
-	0x00, /* 9D */
-	0x00, /* 9E */
-	0x00, /* 9F */
-	0x00, /* A0 */
-	0x00, /* A1 */
-	0x00, /* A2 */
-	0x00, /* A3 */
-	0x00, /* A4 */
-	0x00, /* A5 */
-	0x00, /* A6 */
-	0x00, /* A7 */
-	0x00, /* A8 */
-	0x00, /* A9 */
-	0x00, /* AA */
-	0x00, /* AB */
-	0x00, /* AC */
-	0x00, /* AD */
-	0x00, /* AE */
-	0x00, /* AF */
-	0x00, /* B0 */
-	0x00, /* B1 */
-	0x00, /* B2 */
-	0x00, /* B3 */
-	0x00, /* B4 */
-	0x00, /* B5 */
-	0x00, /* B6 */
-	0x00, /* B7 */
-	0x00, /* B8 */
-	0x00, /* B9 */
-	0x00, /* BA */
-	0x00, /* BB */
-	0x00, /* BC */
-	0x00, /* BD */
-	0x00, /* BE */
-	0x00, /* BF */
-	0x00, /* C0 */
-	0x00, /* C1 */
-	0x00, /* C2 */
-	0x00, /* C3 */
-	0x00, /* C4 */
-	0x00, /* C5 */
-	0x00, /* C6 */
-	0x00, /* C7 */
-	0x00, /* C8 */
-	0x00, /* C9 */
-	0x00, /* CA */
-	0x00, /* CB */
-	0x00, /* CC */
-	0x00, /* CD */
-	0x00, /* CE */
-	0x00, /* CF */
-	0x00, /* D0 */
-	0x00, /* D1 */
-	0x00, /* D2 */
-	0x00, /* D3 */
-	0x00, /* D4 */
-	0x00, /* D5 */
-	0x00, /* D6 */
-	0x00, /* D7 */
-	0x00, /* D8 */
-	0x00, /* D9 */
-	0x00, /* DA */
-	0x00, /* DB */
-	0x00, /* DC */
-	0x00, /* DD */
-	0x00, /* DE */
-	0x00, /* DF */
-	0x00, /* E0 */
-	0x00, /* E1 */
-	0x00, /* E2 */
-	0x00, /* E3 */
-	0x00, /* E4 */
-	0x00, /* E5 */
-	0x00, /* E6 */
-	0x00, /* E7 */
-	0x00, /* E8 */
-	0x00, /* E9 */
-	0x00, /* EA */
-	0x00, /* EB */
-	0x00, /* EC */
-	0x00, /* ED */
-	0x00, /* EE */
-	0x00, /* EF */
-	0x00, /* F0 */
-	0x00, /* F1 */
-	0x00, /* F2 */
-	0x00, /* F3 */
-	0x00, /* F4 */
-	0x00, /* F5 */
-	0x00, /* F6 */
-	0x00, /* F7 */
-	0x00, /* F8 */
-	0x00, /* F9 */
-	0x00, /* FA */
-	0x00, /* FB */
-	0x00, /* FC */
-	0x00, /* FD */
-	0x00, /* FE */
-	0x00, /* FF */
+static const struct reg_default max98095_reg_def[] = {
+	{  0xf, 0x00 }, /* 0F */
+	{ 0x10, 0x00 }, /* 10 */
+	{ 0x11, 0x00 }, /* 11 */
+	{ 0x12, 0x00 }, /* 12 */
+	{ 0x13, 0x00 }, /* 13 */
+	{ 0x14, 0x00 }, /* 14 */
+	{ 0x15, 0x00 }, /* 15 */
+	{ 0x16, 0x00 }, /* 16 */
+	{ 0x17, 0x00 }, /* 17 */
+	{ 0x18, 0x00 }, /* 18 */
+	{ 0x19, 0x00 }, /* 19 */
+	{ 0x1a, 0x00 }, /* 1A */
+	{ 0x1b, 0x00 }, /* 1B */
+	{ 0x1c, 0x00 }, /* 1C */
+	{ 0x1d, 0x00 }, /* 1D */
+	{ 0x1e, 0x00 }, /* 1E */
+	{ 0x1f, 0x00 }, /* 1F */
+	{ 0x20, 0x00 }, /* 20 */
+	{ 0x21, 0x00 }, /* 21 */
+	{ 0x22, 0x00 }, /* 22 */
+	{ 0x23, 0x00 }, /* 23 */
+	{ 0x24, 0x00 }, /* 24 */
+	{ 0x25, 0x00 }, /* 25 */
+	{ 0x26, 0x00 }, /* 26 */
+	{ 0x27, 0x00 }, /* 27 */
+	{ 0x28, 0x00 }, /* 28 */
+	{ 0x29, 0x00 }, /* 29 */
+	{ 0x2a, 0x00 }, /* 2A */
+	{ 0x2b, 0x00 }, /* 2B */
+	{ 0x2c, 0x00 }, /* 2C */
+	{ 0x2d, 0x00 }, /* 2D */
+	{ 0x2e, 0x00 }, /* 2E */
+	{ 0x2f, 0x00 }, /* 2F */
+	{ 0x30, 0x00 }, /* 30 */
+	{ 0x31, 0x00 }, /* 31 */
+	{ 0x32, 0x00 }, /* 32 */
+	{ 0x33, 0x00 }, /* 33 */
+	{ 0x34, 0x00 }, /* 34 */
+	{ 0x35, 0x00 }, /* 35 */
+	{ 0x36, 0x00 }, /* 36 */
+	{ 0x37, 0x00 }, /* 37 */
+	{ 0x38, 0x00 }, /* 38 */
+	{ 0x39, 0x00 }, /* 39 */
+	{ 0x3a, 0x00 }, /* 3A */
+	{ 0x3b, 0x00 }, /* 3B */
+	{ 0x3c, 0x00 }, /* 3C */
+	{ 0x3d, 0x00 }, /* 3D */
+	{ 0x3e, 0x00 }, /* 3E */
+	{ 0x3f, 0x00 }, /* 3F */
+	{ 0x40, 0x00 }, /* 40 */
+	{ 0x41, 0x00 }, /* 41 */
+	{ 0x42, 0x00 }, /* 42 */
+	{ 0x43, 0x00 }, /* 43 */
+	{ 0x44, 0x00 }, /* 44 */
+	{ 0x45, 0x00 }, /* 45 */
+	{ 0x46, 0x00 }, /* 46 */
+	{ 0x47, 0x00 }, /* 47 */
+	{ 0x48, 0x00 }, /* 48 */
+	{ 0x49, 0x00 }, /* 49 */
+	{ 0x4a, 0x00 }, /* 4A */
+	{ 0x4b, 0x00 }, /* 4B */
+	{ 0x4c, 0x00 }, /* 4C */
+	{ 0x4d, 0x00 }, /* 4D */
+	{ 0x4e, 0x00 }, /* 4E */
+	{ 0x4f, 0x00 }, /* 4F */
+	{ 0x50, 0x00 }, /* 50 */
+	{ 0x51, 0x00 }, /* 51 */
+	{ 0x52, 0x00 }, /* 52 */
+	{ 0x53, 0x00 }, /* 53 */
+	{ 0x54, 0x00 }, /* 54 */
+	{ 0x55, 0x00 }, /* 55 */
+	{ 0x56, 0x00 }, /* 56 */
+	{ 0x57, 0x00 }, /* 57 */
+	{ 0x58, 0x00 }, /* 58 */
+	{ 0x59, 0x00 }, /* 59 */
+	{ 0x5a, 0x00 }, /* 5A */
+	{ 0x5b, 0x00 }, /* 5B */
+	{ 0x5c, 0x00 }, /* 5C */
+	{ 0x5d, 0x00 }, /* 5D */
+	{ 0x5e, 0x00 }, /* 5E */
+	{ 0x5f, 0x00 }, /* 5F */
+	{ 0x60, 0x00 }, /* 60 */
+	{ 0x61, 0x00 }, /* 61 */
+	{ 0x62, 0x00 }, /* 62 */
+	{ 0x63, 0x00 }, /* 63 */
+	{ 0x64, 0x00 }, /* 64 */
+	{ 0x65, 0x00 }, /* 65 */
+	{ 0x66, 0x00 }, /* 66 */
+	{ 0x67, 0x00 }, /* 67 */
+	{ 0x68, 0x00 }, /* 68 */
+	{ 0x69, 0x00 }, /* 69 */
+	{ 0x6a, 0x00 }, /* 6A */
+	{ 0x6b, 0x00 }, /* 6B */
+	{ 0x6c, 0x00 }, /* 6C */
+	{ 0x6d, 0x00 }, /* 6D */
+	{ 0x6e, 0x00 }, /* 6E */
+	{ 0x6f, 0x00 }, /* 6F */
+	{ 0x70, 0x00 }, /* 70 */
+	{ 0x71, 0x00 }, /* 71 */
+	{ 0x72, 0x00 }, /* 72 */
+	{ 0x73, 0x00 }, /* 73 */
+	{ 0x74, 0x00 }, /* 74 */
+	{ 0x75, 0x00 }, /* 75 */
+	{ 0x76, 0x00 }, /* 76 */
+	{ 0x77, 0x00 }, /* 77 */
+	{ 0x78, 0x00 }, /* 78 */
+	{ 0x79, 0x00 }, /* 79 */
+	{ 0x7a, 0x00 }, /* 7A */
+	{ 0x7b, 0x00 }, /* 7B */
+	{ 0x7c, 0x00 }, /* 7C */
+	{ 0x7d, 0x00 }, /* 7D */
+	{ 0x7e, 0x00 }, /* 7E */
+	{ 0x7f, 0x00 }, /* 7F */
+	{ 0x80, 0x00 }, /* 80 */
+	{ 0x81, 0x00 }, /* 81 */
+	{ 0x82, 0x00 }, /* 82 */
+	{ 0x83, 0x00 }, /* 83 */
+	{ 0x84, 0x00 }, /* 84 */
+	{ 0x85, 0x00 }, /* 85 */
+	{ 0x86, 0x00 }, /* 86 */
+	{ 0x87, 0x00 }, /* 87 */
+	{ 0x88, 0x00 }, /* 88 */
+	{ 0x89, 0x00 }, /* 89 */
+	{ 0x8a, 0x00 }, /* 8A */
+	{ 0x8b, 0x00 }, /* 8B */
+	{ 0x8c, 0x00 }, /* 8C */
+	{ 0x8d, 0x00 }, /* 8D */
+	{ 0x8e, 0x00 }, /* 8E */
+	{ 0x8f, 0x00 }, /* 8F */
+	{ 0x90, 0x00 }, /* 90 */
+	{ 0x91, 0x00 }, /* 91 */
+	{ 0x92, 0x30 }, /* 92 */
+	{ 0x93, 0xF0 }, /* 93 */
+	{ 0x94, 0x00 }, /* 94 */
+	{ 0x95, 0x00 }, /* 95 */
+	{ 0x96, 0x3F }, /* 96 */
+	{ 0x97, 0x00 }, /* 97 */
+	{ 0xff, 0x00 }, /* FF */
 };
 
 static struct {
@@ -577,14 +460,14 @@
 	{ 0xFF, 0x00 }, /* FF */
 };
 
-static int max98095_readable(struct snd_soc_codec *codec, unsigned int reg)
+static bool max98095_readable(struct device *dev, unsigned int reg)
 {
 	if (reg >= M98095_REG_CNT)
 		return 0;
 	return max98095_access[reg].readable != 0;
 }
 
-static int max98095_volatile(struct snd_soc_codec *codec, unsigned int reg)
+static bool max98095_volatile(struct device *dev, unsigned int reg)
 {
 	if (reg > M98095_REG_MAX_CACHED)
 		return 1;
@@ -611,22 +494,18 @@
 	return 0;
 }
 
-/*
- * Filter coefficients are in a separate register segment
- * and they share the address space of the normal registers.
- * The coefficient registers do not need or share the cache.
- */
-static int max98095_hw_write(struct snd_soc_codec *codec, unsigned int reg,
-			     unsigned int value)
-{
-	int ret;
+static const struct regmap_config max98095_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
 
-	codec->cache_bypass = 1;
-	ret = snd_soc_write(codec, reg, value);
-	codec->cache_bypass = 0;
+	.reg_defaults = max98095_reg_def,
+	.num_reg_defaults = ARRAY_SIZE(max98095_reg_def),
+	.max_register = M98095_0FF_REV_ID,
+	.cache_type = REGCACHE_RBTREE,
 
-	return ret ? -EIO : 0;
-}
+	.readable_reg = max98095_readable,
+	.volatile_reg = max98095_volatile,
+};
 
 /*
  * Load equalizer DSP coefficient configurations registers
@@ -637,8 +516,9 @@
 	unsigned int eq_reg;
 	unsigned int i;
 
-	BUG_ON(band > 4);
-	BUG_ON(dai > 1);
+	if (WARN_ON(band > 4) ||
+	    WARN_ON(dai > 1))
+		return;
 
 	/* Load the base register address */
 	eq_reg = dai ? M98095_142_DAI2_EQ_BASE : M98095_110_DAI1_EQ_BASE;
@@ -648,8 +528,8 @@
 
 	/* Step through the registers and coefs */
 	for (i = 0; i < M98095_COEFS_PER_BAND; i++) {
-		max98095_hw_write(codec, eq_reg++, M98095_BYTE1(coefs[i]));
-		max98095_hw_write(codec, eq_reg++, M98095_BYTE0(coefs[i]));
+		snd_soc_write(codec, eq_reg++, M98095_BYTE1(coefs[i]));
+		snd_soc_write(codec, eq_reg++, M98095_BYTE0(coefs[i]));
 	}
 }
 
@@ -662,8 +542,9 @@
 	unsigned int bq_reg;
 	unsigned int i;
 
-	BUG_ON(band > 1);
-	BUG_ON(dai > 1);
+	if (WARN_ON(band > 1) ||
+	    WARN_ON(dai > 1))
+		return;
 
 	/* Load the base register address */
 	bq_reg = dai ? M98095_17E_DAI2_BQ_BASE : M98095_174_DAI1_BQ_BASE;
@@ -673,8 +554,8 @@
 
 	/* Step through the registers and coefs */
 	for (i = 0; i < M98095_COEFS_PER_BAND; i++) {
-		max98095_hw_write(codec, bq_reg++, M98095_BYTE1(coefs[i]));
-		max98095_hw_write(codec, bq_reg++, M98095_BYTE0(coefs[i]));
+		snd_soc_write(codec, bq_reg++, M98095_BYTE1(coefs[i]));
+		snd_soc_write(codec, bq_reg++, M98095_BYTE0(coefs[i]));
 	}
 }
 
@@ -1011,7 +892,8 @@
 	struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
 	u8 *state;
 
-	BUG_ON(!((channel == 1) || (channel == 2)));
+	if (WARN_ON(!(channel == 1 || channel == 2)))
+		return -EINVAL;
 
 	state = &max98095->lin_state;
 
@@ -1285,14 +1167,6 @@
 	{"MIC2 Input", NULL, "MIC2"},
 };
 
-static int max98095_add_widgets(struct snd_soc_codec *codec)
-{
-	snd_soc_add_codec_controls(codec, max98095_snd_controls,
-			     ARRAY_SIZE(max98095_snd_controls));
-
-	return 0;
-}
-
 /* codec mclk clock divider coefficients */
 static const struct {
 	u32 rate;
@@ -1748,6 +1622,7 @@
 static int max98095_set_bias_level(struct snd_soc_codec *codec,
 				   enum snd_soc_bias_level level)
 {
+	struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
 	int ret;
 
 	switch (level) {
@@ -1759,7 +1634,7 @@
 
 	case SND_SOC_BIAS_STANDBY:
 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-			ret = snd_soc_cache_sync(codec);
+			ret = regcache_sync(max98095->regmap);
 
 			if (ret != 0) {
 				dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
@@ -1774,7 +1649,7 @@
 	case SND_SOC_BIAS_OFF:
 		snd_soc_update_bits(codec, M98095_090_PWR_EN_IN,
 				M98095_MBEN, 0);
-		codec->cache_sync = 1;
+		regcache_mark_dirty(max98095->regmap);
 		break;
 	}
 	codec->dapm.bias_level = level;
@@ -1868,7 +1743,8 @@
 	int fs, best, best_val, i;
 	int regmask, regsave;
 
-	BUG_ON(channel > 1);
+	if (WARN_ON(channel > 1))
+		return -EINVAL;
 
 	if (!pdata || !max98095->eq_textcnt)
 		return 0;
@@ -2341,7 +2217,7 @@
 	/* Reset to hardware default for registers, as there is not
 	 * a soft reset hardware control register */
 	for (i = M98095_010_HOST_INT_CFG; i < M98095_REG_MAX_CACHED; i++) {
-		ret = snd_soc_write(codec, i, max98095_reg_def[i]);
+		ret = snd_soc_write(codec, i, snd_soc_read(codec, i));
 		if (ret < 0) {
 			dev_err(codec->dev, "Failed to reset: %d\n", ret);
 			return ret;
@@ -2358,7 +2234,7 @@
 	struct i2c_client *client;
 	int ret = 0;
 
-	ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
+	ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
 	if (ret != 0) {
 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
 		return ret;
@@ -2447,8 +2323,6 @@
 	snd_soc_update_bits(codec, M98095_097_PWR_SYS, M98095_SHDNRUN,
 		M98095_SHDNRUN);
 
-	max98095_add_widgets(codec);
-
 	return 0;
 
 err_irq:
@@ -2480,11 +2354,8 @@
 	.suspend = max98095_suspend,
 	.resume  = max98095_resume,
 	.set_bias_level = max98095_set_bias_level,
-	.reg_cache_size = ARRAY_SIZE(max98095_reg_def),
-	.reg_word_size = sizeof(u8),
-	.reg_cache_default = max98095_reg_def,
-	.readable_register = max98095_readable,
-	.volatile_register = max98095_volatile,
+	.controls = max98095_snd_controls,
+	.num_controls = ARRAY_SIZE(max98095_snd_controls),
 	.dapm_widgets	  = max98095_dapm_widgets,
 	.num_dapm_widgets = ARRAY_SIZE(max98095_dapm_widgets),
 	.dapm_routes     = max98095_audio_map,
@@ -2502,6 +2373,13 @@
 	if (max98095 == NULL)
 		return -ENOMEM;
 
+	max98095->regmap = devm_regmap_init_i2c(i2c, &max98095_regmap);
+	if (IS_ERR(max98095->regmap)) {
+		ret = PTR_ERR(max98095->regmap);
+		dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
+		return ret;
+	}
+
 	max98095->devtype = id->driver_data;
 	i2c_set_clientdata(i2c, max98095);
 	max98095->pdata = i2c->dev.platform_data;
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c
index 58c38a5..c5dd617 100644
--- a/sound/soc/codecs/max9850.c
+++ b/sound/soc/codecs/max9850.c
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -27,18 +28,26 @@
 #include "max9850.h"
 
 struct max9850_priv {
+	struct regmap *regmap;
 	unsigned int sysclk;
 };
 
 /* max9850 register cache */
-static const u8 max9850_reg[MAX9850_CACHEREGNUM] = {
-	0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+static const struct reg_default max9850_reg[] = {
+	{  2, 0x0c },
+	{  3, 0x00 },
+	{  4, 0x00 },
+	{  5, 0x00 },
+	{  6, 0x00 },
+	{  7, 0x00 },
+	{  8, 0x00 },
+	{  9, 0x00 },
+	{ 10, 0x00 },
 };
 
 /* these registers are not used at the moment but provided for the sake of
  * completeness */
-static int max9850_volatile_register(struct snd_soc_codec *codec,
-		unsigned int reg)
+static bool max9850_volatile_register(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
 	case MAX9850_STATUSA:
@@ -49,6 +58,15 @@
 	}
 }
 
+static const struct regmap_config max9850_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = MAX9850_DIGITAL_AUDIO,
+	.volatile_reg = max9850_volatile_register,
+	.cache_type = REGCACHE_RBTREE,
+};
+
 static const unsigned int max9850_tlv[] = {
 	TLV_DB_RANGE_HEAD(4),
 	0x18, 0x1f, TLV_DB_SCALE_ITEM(-7450, 400, 0),
@@ -225,6 +243,7 @@
 static int max9850_set_bias_level(struct snd_soc_codec *codec,
 				  enum snd_soc_bias_level level)
 {
+	struct max9850_priv *max9850 = snd_soc_codec_get_drvdata(codec);
 	int ret;
 
 	switch (level) {
@@ -234,7 +253,7 @@
 		break;
 	case SND_SOC_BIAS_STANDBY:
 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-			ret = snd_soc_cache_sync(codec);
+			ret = regcache_sync(max9850->regmap);
 			if (ret) {
 				dev_err(codec->dev,
 					"Failed to sync cache: %d\n", ret);
@@ -295,7 +314,7 @@
 {
 	int ret;
 
-	ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
+	ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
 	if (ret < 0) {
 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
 		return ret;
@@ -316,10 +335,6 @@
 	.suspend =	max9850_suspend,
 	.resume =	max9850_resume,
 	.set_bias_level = max9850_set_bias_level,
-	.reg_cache_size = ARRAY_SIZE(max9850_reg),
-	.reg_word_size = sizeof(u8),
-	.reg_cache_default = max9850_reg,
-	.volatile_register = max9850_volatile_register,
 
 	.controls = max9850_controls,
 	.num_controls = ARRAY_SIZE(max9850_controls),
@@ -340,6 +355,10 @@
 	if (max9850 == NULL)
 		return -ENOMEM;
 
+	max9850->regmap = devm_regmap_init_i2c(i2c, &max9850_regmap);
+	if (IS_ERR(max9850->regmap))
+		return PTR_ERR(max9850->regmap);
+
 	i2c_set_clientdata(i2c, max9850);
 
 	ret = snd_soc_register_codec(&i2c->dev,
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c
index ea141e1..bae6016 100644
--- a/sound/soc/codecs/mc13783.c
+++ b/sound/soc/codecs/mc13783.c
@@ -30,16 +30,10 @@
 #include <sound/soc.h>
 #include <sound/initval.h>
 #include <sound/soc-dapm.h>
+#include <linux/regmap.h>
 
 #include "mc13783.h"
 
-#define MC13783_AUDIO_RX0	36
-#define MC13783_AUDIO_RX1	37
-#define MC13783_AUDIO_TX	38
-#define MC13783_SSI_NETWORK	39
-#define MC13783_AUDIO_CODEC	40
-#define MC13783_AUDIO_DAC	41
-
 #define AUDIO_RX0_ALSPEN		(1 << 5)
 #define AUDIO_RX0_ALSPSEL		(1 << 7)
 #define AUDIO_RX0_ADDCDC		(1 << 21)
@@ -95,45 +89,12 @@
 
 struct mc13783_priv {
 	struct mc13xxx *mc13xxx;
+	struct regmap *regmap;
 
 	enum mc13783_ssi_port adc_ssi_port;
 	enum mc13783_ssi_port dac_ssi_port;
 };
 
-static unsigned int mc13783_read(struct snd_soc_codec *codec,
-	unsigned int reg)
-{
-	struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
-	unsigned int value = 0;
-
-	mc13xxx_lock(priv->mc13xxx);
-
-	mc13xxx_reg_read(priv->mc13xxx, reg, &value);
-
-	mc13xxx_unlock(priv->mc13xxx);
-
-	return value;
-}
-
-static int mc13783_write(struct snd_soc_codec *codec,
-	unsigned int reg, unsigned int value)
-{
-	struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
-	int ret;
-
-	mc13xxx_lock(priv->mc13xxx);
-
-	ret = mc13xxx_reg_write(priv->mc13xxx, reg, value);
-
-	/* include errata fix for spi audio problems */
-	if (reg == MC13783_AUDIO_CODEC || reg == MC13783_AUDIO_DAC)
-		ret = mc13xxx_reg_write(priv->mc13xxx, reg, value);
-
-	mc13xxx_unlock(priv->mc13xxx);
-
-	return ret;
-}
-
 /* Mapping between sample rates and register value */
 static unsigned int mc13783_rates[] = {
 	8000, 11025, 12000, 16000,
@@ -382,7 +343,7 @@
 		break;
 	default:
 		return -EINVAL;
-	};
+	}
 
 	snd_soc_update_bits(codec, MC13783_SSI_NETWORK, mask, val);
 
@@ -466,6 +427,29 @@
 static const struct snd_kcontrol_new samp_ctl =
 	SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 3, 1, 0);
 
+static const char * const speaker_amp_source_text[] = {
+	"CODEC", "Right"
+};
+static const SOC_ENUM_SINGLE_DECL(speaker_amp_source, MC13783_AUDIO_RX0, 4,
+				  speaker_amp_source_text);
+static const struct snd_kcontrol_new speaker_amp_source_mux =
+	SOC_DAPM_ENUM("Speaker Amp Source MUX", speaker_amp_source);
+
+static const char * const headset_amp_source_text[] = {
+	"CODEC", "Mixer"
+};
+
+static const SOC_ENUM_SINGLE_DECL(headset_amp_source, MC13783_AUDIO_RX0, 11,
+				  headset_amp_source_text);
+static const struct snd_kcontrol_new headset_amp_source_mux =
+	SOC_DAPM_ENUM("Headset Amp Source MUX", headset_amp_source);
+
+static const struct snd_kcontrol_new cdcout_ctl =
+	SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 18, 1, 0);
+
+static const struct snd_kcontrol_new adc_bypass_ctl =
+	SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_CODEC, 16, 1, 0);
+
 static const struct snd_kcontrol_new lamp_ctl =
 	SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 5, 1, 0);
 
@@ -503,12 +487,22 @@
 	SND_SOC_DAPM_VIRT_MUX("PGA Right Input Mux", SND_SOC_NOPM, 0, 0,
 			      &right_input_mux),
 
+	SND_SOC_DAPM_MUX("Speaker Amp Source MUX", SND_SOC_NOPM, 0, 0,
+			 &speaker_amp_source_mux),
+
+	SND_SOC_DAPM_MUX("Headset Amp Source MUX", SND_SOC_NOPM, 0, 0,
+			 &headset_amp_source_mux),
+
 	SND_SOC_DAPM_PGA("PGA Left Input", SND_SOC_NOPM, 0, 0, NULL, 0),
 	SND_SOC_DAPM_PGA("PGA Right Input", SND_SOC_NOPM, 0, 0, NULL, 0),
 
 	SND_SOC_DAPM_ADC("ADC", "Capture", MC13783_AUDIO_CODEC, 11, 0),
 	SND_SOC_DAPM_SUPPLY("ADC_Reset", MC13783_AUDIO_CODEC, 15, 0, NULL, 0),
 
+	SND_SOC_DAPM_PGA("Voice CODEC PGA", MC13783_AUDIO_RX1, 0, 0, NULL, 0),
+	SND_SOC_DAPM_SWITCH("Voice CODEC Bypass", MC13783_AUDIO_CODEC, 16, 0,
+			&adc_bypass_ctl),
+
 /* Output */
 	SND_SOC_DAPM_SUPPLY("DAC_E", MC13783_AUDIO_DAC, 11, 0, NULL, 0),
 	SND_SOC_DAPM_SUPPLY("DAC_Reset", MC13783_AUDIO_DAC, 15, 0, NULL, 0),
@@ -516,10 +510,15 @@
 	SND_SOC_DAPM_OUTPUT("RXOUTR"),
 	SND_SOC_DAPM_OUTPUT("HSL"),
 	SND_SOC_DAPM_OUTPUT("HSR"),
+	SND_SOC_DAPM_OUTPUT("LSPL"),
 	SND_SOC_DAPM_OUTPUT("LSP"),
 	SND_SOC_DAPM_OUTPUT("SP"),
+	SND_SOC_DAPM_OUTPUT("CDCOUT"),
 
-	SND_SOC_DAPM_SWITCH("Speaker Amp", MC13783_AUDIO_RX0, 3, 0, &samp_ctl),
+	SND_SOC_DAPM_SWITCH("CDCOUT Switch", MC13783_AUDIO_RX0, 18, 0,
+			&cdcout_ctl),
+	SND_SOC_DAPM_SWITCH("Speaker Amp Switch", MC13783_AUDIO_RX0, 3, 0,
+			&samp_ctl),
 	SND_SOC_DAPM_SWITCH("Loudspeaker Amp", SND_SOC_NOPM, 0, 0, &lamp_ctl),
 	SND_SOC_DAPM_SWITCH("Headset Amp Left", MC13783_AUDIO_RX0, 10, 0,
 			&hlamp_ctl),
@@ -554,20 +553,28 @@
 	{ "ADC", NULL, "PGA Right Input"},
 	{ "ADC", NULL, "ADC_Reset"},
 
+	{ "Voice CODEC PGA", "Voice CODEC Bypass", "ADC" },
+
+	{ "Speaker Amp Source MUX", "CODEC", "Voice CODEC PGA"},
+	{ "Speaker Amp Source MUX", "Right", "DAC PGA"},
+
+	{ "Headset Amp Source MUX", "CODEC", "Voice CODEC PGA"},
+	{ "Headset Amp Source MUX", "Mixer", "DAC PGA"},
+
 /* Output */
 	{ "HSL", NULL, "Headset Amp Left" },
 	{ "HSR", NULL, "Headset Amp Right"},
 	{ "RXOUTL", NULL, "Line out Amp Left"},
 	{ "RXOUTR", NULL, "Line out Amp Right"},
-	{ "SP", NULL, "Speaker Amp"},
-	{ "Speaker Amp", NULL, "DAC PGA"},
-	{ "LSP", NULL, "DAC PGA"},
-	{ "Headset Amp Left", NULL, "DAC PGA"},
-	{ "Headset Amp Right", NULL, "DAC PGA"},
+	{ "SP", "Speaker Amp Switch", "Speaker Amp Source MUX"},
+	{ "LSP", "Loudspeaker Amp", "Speaker Amp Source MUX"},
+	{ "HSL", "Headset Amp Left", "Headset Amp Source MUX"},
+	{ "HSR", "Headset Amp Right", "Headset Amp Source MUX"},
 	{ "Line out Amp Left", NULL, "DAC PGA"},
 	{ "Line out Amp Right", NULL, "DAC PGA"},
 	{ "DAC PGA", NULL, "DAC"},
 	{ "DAC", NULL, "DAC_E"},
+	{ "CDCOUT", "CDCOUT Switch", "Voice CODEC PGA"},
 };
 
 static const char * const mc13783_3d_mixer[] = {"Stereo", "Phase Mix",
@@ -580,15 +587,39 @@
 static struct snd_kcontrol_new mc13783_control_list[] = {
 	SOC_SINGLE("Loudspeaker enable", MC13783_AUDIO_RX0, 5, 1, 0),
 	SOC_SINGLE("PCM Playback Volume", MC13783_AUDIO_RX1, 6, 15, 0),
+	SOC_SINGLE("PCM Playback Switch", MC13783_AUDIO_RX1, 5, 1, 0),
 	SOC_DOUBLE("PCM Capture Volume", MC13783_AUDIO_TX, 19, 14, 31, 0),
 	SOC_ENUM("3D Control", mc13783_enum_3d_mixer),
+
+	SOC_SINGLE("CDCOUT Switch", MC13783_AUDIO_RX0, 18, 1, 0),
+	SOC_SINGLE("Earpiece Amp Switch", MC13783_AUDIO_RX0, 3, 1, 0),
+	SOC_DOUBLE("Headset Amp Switch", MC13783_AUDIO_RX0, 10, 9, 1, 0),
+	SOC_DOUBLE("Line out Amp Switch", MC13783_AUDIO_RX0, 16, 15, 1, 0),
+
+	SOC_SINGLE("PCM Capture Mixin Switch", MC13783_AUDIO_RX0, 22, 1, 0),
+	SOC_SINGLE("Line in Capture Mixin Switch", MC13783_AUDIO_RX0, 23, 1, 0),
+
+	SOC_SINGLE("CODEC Capture Volume", MC13783_AUDIO_RX1, 1, 15, 0),
+	SOC_SINGLE("CODEC Capture Mixin Switch", MC13783_AUDIO_RX0, 21, 1, 0),
+
+	SOC_SINGLE("Line in Capture Volume", MC13783_AUDIO_RX1, 12, 15, 0),
+	SOC_SINGLE("Line in Capture Switch", MC13783_AUDIO_RX1, 10, 1, 0),
+
+	SOC_SINGLE("MC1 Capture Bias Switch", MC13783_AUDIO_TX, 0, 1, 0),
+	SOC_SINGLE("MC2 Capture Bias Switch", MC13783_AUDIO_TX, 1, 1, 0),
 };
 
 static int mc13783_probe(struct snd_soc_codec *codec)
 {
 	struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
+	int ret;
 
-	mc13xxx_lock(priv->mc13xxx);
+	codec->control_data = dev_get_regmap(codec->dev->parent, NULL);
+	ret = snd_soc_codec_set_cache_io(codec, 8, 24, SND_SOC_REGMAP);
+	if (ret != 0) {
+		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+		return ret;
+	}
 
 	/* these are the reset values */
 	mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_RX0, 0x25893);
@@ -612,8 +643,6 @@
 		mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_DAC,
 				0, AUDIO_SSI_SEL);
 
-	mc13xxx_unlock(priv->mc13xxx);
-
 	return 0;
 }
 
@@ -621,13 +650,9 @@
 {
 	struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
 
-	mc13xxx_lock(priv->mc13xxx);
-
 	/* Make sure VAUDIOON is off */
 	mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_RX0, 0x3, 0);
 
-	mc13xxx_unlock(priv->mc13xxx);
-
 	return 0;
 }
 
@@ -717,8 +742,6 @@
 static struct snd_soc_codec_driver soc_codec_dev_mc13783 = {
 	.probe		= mc13783_probe,
 	.remove		= mc13783_remove,
-	.read		= mc13783_read,
-	.write		= mc13783_write,
 	.controls	= mc13783_control_list,
 	.num_controls	= ARRAY_SIZE(mc13783_control_list),
 	.dapm_widgets	= mc13783_dapm_widgets,
diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c
index 2611882..185fa3bc 100644
--- a/sound/soc/codecs/ml26124.c
+++ b/sound/soc/codecs/ml26124.c
@@ -342,6 +342,8 @@
 	struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec);
 	int i = get_coeff(priv->mclk, params_rate(hw_params));
 
+	if (i < 0)
+		return i;
 	priv->substream = substream;
 	priv->rate = params_rate(hw_params);
 
diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c
index 651ce09..73f9c36 100644
--- a/sound/soc/codecs/pcm1681.c
+++ b/sound/soc/codecs/pcm1681.c
@@ -21,6 +21,7 @@
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/regmap.h>
+#include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
 #include <sound/pcm.h>
@@ -270,7 +271,7 @@
 static const struct regmap_config pcm1681_regmap = {
 	.reg_bits		= 8,
 	.val_bits		= 8,
-	.max_register		= ARRAY_SIZE(pcm1681_reg_defaults) + 1,
+	.max_register		= 0x13,
 	.reg_defaults		= pcm1681_reg_defaults,
 	.num_reg_defaults	= ARRAY_SIZE(pcm1681_reg_defaults),
 	.writeable_reg		= pcm1681_writeable_reg,
diff --git a/sound/soc/codecs/pcm1792a.c b/sound/soc/codecs/pcm1792a.c
index 2a8eccf..7146653a 100644
--- a/sound/soc/codecs/pcm1792a.c
+++ b/sound/soc/codecs/pcm1792a.c
@@ -28,6 +28,7 @@
 #include <sound/initval.h>
 #include <sound/soc.h>
 #include <sound/tlv.h>
+#include <linux/of.h>
 #include <linux/of_device.h>
 
 #include "pcm1792a.h"
@@ -188,7 +189,7 @@
 static const struct regmap_config pcm1792a_regmap = {
 	.reg_bits		= 8,
 	.val_bits		= 8,
-	.max_register		= 24,
+	.max_register		= 23,
 	.reg_defaults		= pcm1792a_reg_defaults,
 	.num_reg_defaults	= ARRAY_SIZE(pcm1792a_reg_defaults),
 	.writeable_reg		= pcm1792a_writeable_reg,
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index c26a8f8..a3fb411 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -21,6 +21,7 @@
 #include <linux/of_gpio.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
+#include <linux/acpi.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -926,7 +927,7 @@
 	return 0;
 }
 
-void hp_amp_power_on(struct snd_soc_codec *codec)
+static void hp_amp_power_on(struct snd_soc_codec *codec)
 {
 	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
 
@@ -1603,13 +1604,14 @@
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_codec *codec = rtd->codec;
 	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
-	unsigned int val_len = 0, val_clk, mask_clk, dai_sel;
-	int pre_div, bclk_ms, frame_size;
+	unsigned int val_len = 0, val_clk, mask_clk;
+	int dai_sel, pre_div, bclk_ms, frame_size;
 
 	rt5640->lrck[dai->id] = params_rate(params);
 	pre_div = get_clk_info(rt5640->sysclk, rt5640->lrck[dai->id]);
 	if (pre_div < 0) {
-		dev_err(codec->dev, "Unsupported clock setting\n");
+		dev_err(codec->dev, "Unsupported clock setting %d for DAI %d\n",
+			rt5640->lrck[dai->id], dai->id);
 		return -EINVAL;
 	}
 	frame_size = snd_soc_params_to_frame_size(params);
@@ -1673,7 +1675,8 @@
 {
 	struct snd_soc_codec *codec = dai->codec;
 	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
-	unsigned int reg_val = 0, dai_sel;
+	unsigned int reg_val = 0;
+	int dai_sel;
 
 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 	case SND_SOC_DAIFMT_CBM_CFM:
@@ -1977,13 +1980,20 @@
 	rt5640_reset(codec);
 	regcache_cache_only(rt5640->regmap, true);
 	regcache_mark_dirty(rt5640->regmap);
+	if (gpio_is_valid(rt5640->pdata.ldo1_en))
+		gpio_set_value_cansleep(rt5640->pdata.ldo1_en, 0);
 
 	return 0;
 }
 
 static int rt5640_resume(struct snd_soc_codec *codec)
 {
-	rt5640_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
+
+	if (gpio_is_valid(rt5640->pdata.ldo1_en)) {
+		gpio_set_value_cansleep(rt5640->pdata.ldo1_en, 1);
+		msleep(400);
+	}
 
 	return 0;
 }
@@ -2080,6 +2090,14 @@
 };
 MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id);
 
+#ifdef CONFIG_ACPI
+static struct acpi_device_id rt5640_acpi_match[] = {
+	{ "INT33CA", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, rt5640_acpi_match);
+#endif
+
 static int rt5640_parse_dt(struct rt5640_priv *rt5640, struct device_node *np)
 {
 	rt5640->pdata.in1_diff = of_property_read_bool(np,
@@ -2199,6 +2217,7 @@
 	.driver = {
 		.name = "rt5640",
 		.owner = THIS_MODULE,
+		.acpi_match_table = ACPI_PTR(rt5640_acpi_match),
 	},
 	.probe = rt5640_i2c_probe,
 	.remove   = rt5640_i2c_remove,
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c
index 38f3b10..52e7cb0 100644
--- a/sound/soc/codecs/si476x.c
+++ b/sound/soc/codecs/si476x.c
@@ -60,48 +60,6 @@
 	SI476X_PCM_FORMAT_S24_LE	= 6,
 };
 
-static unsigned int si476x_codec_read(struct snd_soc_codec *codec,
-				      unsigned int reg)
-{
-	int err;
-	unsigned int val;
-	struct si476x_core *core = codec->control_data;
-
-	si476x_core_lock(core);
-	if (!si476x_core_is_powered_up(core))
-		regcache_cache_only(core->regmap, true);
-
-	err = regmap_read(core->regmap, reg, &val);
-
-	if (!si476x_core_is_powered_up(core))
-		regcache_cache_only(core->regmap, false);
-	si476x_core_unlock(core);
-
-	if (err < 0)
-		return err;
-
-	return val;
-}
-
-static int si476x_codec_write(struct snd_soc_codec *codec,
-			      unsigned int reg, unsigned int val)
-{
-	int err;
-	struct si476x_core *core = codec->control_data;
-
-	si476x_core_lock(core);
-	if (!si476x_core_is_powered_up(core))
-		regcache_cache_only(core->regmap, true);
-
-	err = regmap_write(core->regmap, reg, val);
-
-	if (!si476x_core_is_powered_up(core))
-		regcache_cache_only(core->regmap, false);
-	si476x_core_unlock(core);
-
-	return err;
-}
-
 static const struct snd_soc_dapm_widget si476x_dapm_widgets[] = {
 SND_SOC_DAPM_OUTPUT("LOUT"),
 SND_SOC_DAPM_OUTPUT("ROUT"),
@@ -115,6 +73,7 @@
 static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
 				    unsigned int fmt)
 {
+	struct si476x_core *core = i2c_mfd_cell_to_core(codec_dai->dev);
 	int err;
 	u16 format = 0;
 
@@ -178,9 +137,14 @@
 		return -EINVAL;
 	}
 
+	si476x_core_lock(core);
+
 	err = snd_soc_update_bits(codec_dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT,
 				  SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK,
 				  format);
+
+	si476x_core_unlock(core);
+
 	if (err < 0) {
 		dev_err(codec_dai->codec->dev, "Failed to set output format\n");
 		return err;
@@ -193,6 +157,7 @@
 				  struct snd_pcm_hw_params *params,
 				  struct snd_soc_dai *dai)
 {
+	struct si476x_core *core = i2c_mfd_cell_to_core(dai->dev);
 	int rate, width, err;
 
 	rate = params_rate(params);
@@ -218,11 +183,13 @@
 		return -EINVAL;
 	}
 
+	si476x_core_lock(core);
+
 	err = snd_soc_write(dai->codec, SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE,
 			    rate);
 	if (err < 0) {
 		dev_err(dai->codec->dev, "Failed to set sample rate\n");
-		return err;
+		goto out;
 	}
 
 	err = snd_soc_update_bits(dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT,
@@ -231,15 +198,18 @@
 				  (width << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT));
 	if (err < 0) {
 		dev_err(dai->codec->dev, "Failed to set output width\n");
-		return err;
+		goto out;
 	}
 
-	return 0;
+out:
+	si476x_core_unlock(core);
+
+	return err;
 }
 
 static int si476x_codec_probe(struct snd_soc_codec *codec)
 {
-	codec->control_data = i2c_mfd_cell_to_core(codec->dev);
+	codec->control_data = dev_get_regmap(codec->dev->parent, NULL);
 	return 0;
 }
 
@@ -268,8 +238,6 @@
 
 static struct snd_soc_codec_driver soc_codec_dev_si476x = {
 	.probe  = si476x_codec_probe,
-	.read   = si476x_codec_read,
-	.write  = si476x_codec_write,
 	.dapm_widgets = si476x_dapm_widgets,
 	.num_dapm_widgets = ARRAY_SIZE(si476x_dapm_widgets),
 	.dapm_routes = si476x_dapm_routes,
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
index dba26e63..13045f2 100644
--- a/sound/soc/codecs/sn95031.c
+++ b/sound/soc/codecs/sn95031.c
@@ -164,30 +164,28 @@
 }
 /*end - adc helper functions */
 
-static inline unsigned int sn95031_read(struct snd_soc_codec *codec,
-			unsigned int reg)
+static int sn95031_read(void *ctx, unsigned int reg, unsigned int *val)
 {
 	u8 value = 0;
 	int ret;
 
 	ret = intel_scu_ipc_ioread8(reg, &value);
-	if (ret)
-		pr_err("read of %x failed, err %d\n", reg, ret);
-	return value;
+	if (ret == 0)
+		*val = value;
 
-}
-
-static inline int sn95031_write(struct snd_soc_codec *codec,
-			unsigned int reg, unsigned int value)
-{
-	int ret;
-
-	ret = intel_scu_ipc_iowrite8(reg, value);
-	if (ret)
-		pr_err("write of %x failed, err %d\n", reg, ret);
 	return ret;
 }
 
+static int sn95031_write(void *ctx, unsigned int reg, unsigned int value)
+{
+	return intel_scu_ipc_iowrite8(reg, value);
+}
+
+static const struct regmap_config sn95031_regmap = {
+	.reg_read = sn95031_read,
+	.reg_write = sn95031_write,
+};
+
 static int sn95031_set_vaud_bias(struct snd_soc_codec *codec,
 		enum snd_soc_bias_level level)
 {
@@ -827,6 +825,8 @@
 {
 	pr_debug("codec_probe called\n");
 
+	snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
+
 	/* PCM interface config
 	 * This sets the pcm rx slot conguration to max 6 slots
 	 * for max 4 dais (2 stereo and 2 mono)
@@ -886,8 +886,6 @@
 static struct snd_soc_codec_driver sn95031_codec = {
 	.probe		= sn95031_codec_probe,
 	.remove		= sn95031_codec_remove,
-	.read		= sn95031_read,
-	.write		= sn95031_write,
 	.set_bias_level	= sn95031_set_vaud_bias,
 	.idle_bias_off	= true,
 	.dapm_widgets	= sn95031_dapm_widgets,
@@ -898,7 +896,14 @@
 
 static int sn95031_device_probe(struct platform_device *pdev)
 {
+	struct regmap *regmap;
+
 	pr_debug("codec device probe called for %s\n", dev_name(&pdev->dev));
+
+	regmap = devm_regmap_init(&pdev->dev, NULL, NULL, &sn95031_regmap);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
 	return snd_soc_register_codec(&pdev->dev, &sn95031_codec,
 			sn95031_dais, ARRAY_SIZE(sn95031_dais));
 }
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c
index 6d31d88..a895a5e 100644
--- a/sound/soc/codecs/tas5086.c
+++ b/sound/soc/codecs/tas5086.c
@@ -37,6 +37,7 @@
 #include <linux/i2c.h>
 #include <linux/regmap.h>
 #include <linux/spi/spi.h>
+#include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
 #include <sound/pcm.h>
@@ -244,6 +245,8 @@
 	unsigned int	mclk, sclk;
 	unsigned int	format;
 	bool		deemph;
+	unsigned int	charge_period;
+	unsigned int	pwm_start_mid_z;
 	/* Current sample rate for de-emphasis control */
 	int		rate;
 	/* GPIO driving Reset pin, if any */
@@ -429,7 +432,7 @@
 	default:
 		dev_err(codec->dev, "Invalid bit width\n");
 		return -EINVAL;
-	};
+	}
 
 	ret = regmap_write(priv->regmap, TAS5086_SERIAL_DATA_IF, val);
 	if (ret < 0)
@@ -456,6 +459,75 @@
 	return regmap_write(priv->regmap, TAS5086_SOFT_MUTE, val);
 }
 
+static void tas5086_reset(struct tas5086_private *priv)
+{
+	if (gpio_is_valid(priv->gpio_nreset)) {
+		/* Reset codec - minimum assertion time is 400ns */
+		gpio_direction_output(priv->gpio_nreset, 0);
+		udelay(1);
+		gpio_set_value(priv->gpio_nreset, 1);
+
+		/* Codec needs ~15ms to wake up */
+		msleep(15);
+	}
+}
+
+/* charge period values in microseconds */
+static const int tas5086_charge_period[] = {
+	  13000,  16900,   23400,   31200,   41600,   54600,   72800,   96200,
+	 130000, 156000,  234000,  312000,  416000,  546000,  728000,  962000,
+	1300000, 169000, 2340000, 3120000, 4160000, 5460000, 7280000, 9620000,
+};
+
+static int tas5086_init(struct device *dev, struct tas5086_private *priv)
+{
+	int ret, i;
+
+	/*
+	 * If any of the channels is configured to start in Mid-Z mode,
+	 * configure 'part 1' of the PWM starts to use Mid-Z, and tell
+	 * all configured mid-z channels to start start under 'part 1'.
+	 */
+	if (priv->pwm_start_mid_z)
+		regmap_write(priv->regmap, TAS5086_PWM_START,
+			     TAS5086_PWM_START_MIDZ_FOR_START_1 |
+				priv->pwm_start_mid_z);
+
+	/* lookup and set split-capacitor charge period */
+	if (priv->charge_period == 0) {
+		regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0);
+	} else {
+		i = index_in_array(tas5086_charge_period,
+				   ARRAY_SIZE(tas5086_charge_period),
+				   priv->charge_period);
+		if (i >= 0)
+			regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE,
+				     i + 0x08);
+		else
+			dev_warn(dev,
+				 "Invalid split-cap charge period of %d ns.\n",
+				 priv->charge_period);
+	}
+
+	/* enable factory trim */
+	ret = regmap_write(priv->regmap, TAS5086_OSC_TRIM, 0x00);
+	if (ret < 0)
+		return ret;
+
+	/* start all channels */
+	ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x20);
+	if (ret < 0)
+		return ret;
+
+	/* mute all channels for now */
+	ret = regmap_write(priv->regmap, TAS5086_SOFT_MUTE,
+			   TAS5086_SOFT_MUTE_ALL);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
 /* TAS5086 controls */
 static const DECLARE_TLV_DB_SCALE(tas5086_dac_tlv, -10350, 50, 1);
 
@@ -691,14 +763,39 @@
 };
 
 #ifdef CONFIG_PM
+static int tas5086_soc_suspend(struct snd_soc_codec *codec)
+{
+	struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	/* Shut down all channels */
+	ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x60);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
 static int tas5086_soc_resume(struct snd_soc_codec *codec)
 {
 	struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+	int ret;
 
-	/* Restore codec state */
-	return regcache_sync(priv->regmap);
+	tas5086_reset(priv);
+	regcache_mark_dirty(priv->regmap);
+
+	ret = tas5086_init(codec->dev, priv);
+	if (ret < 0)
+		return ret;
+
+	ret = regcache_sync(priv->regmap);
+	if (ret < 0)
+		return ret;
+
+	return 0;
 }
 #else
+#define tas5086_soc_suspend	NULL
 #define tas5086_soc_resume	NULL
 #endif /* CONFIG_PM */
 
@@ -710,23 +807,19 @@
 MODULE_DEVICE_TABLE(of, tas5086_dt_ids);
 #endif
 
-/* charge period values in microseconds */
-static const int tas5086_charge_period[] = {
-	  13000,  16900,   23400,   31200,   41600,   54600,   72800,   96200,
-	 130000, 156000,  234000,  312000,  416000,  546000,  728000,  962000,
-	1300000, 169000, 2340000, 3120000, 4160000, 5460000, 7280000, 9620000,
-};
-
 static int tas5086_probe(struct snd_soc_codec *codec)
 {
 	struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
-	int charge_period = 1300000; /* hardware default is 1300 ms */
-	u8 pwm_start_mid_z = 0;
 	int i, ret;
 
+	priv->pwm_start_mid_z = 0;
+	priv->charge_period = 1300000; /* hardware default is 1300 ms */
+
 	if (of_match_device(of_match_ptr(tas5086_dt_ids), codec->dev)) {
 		struct device_node *of_node = codec->dev->of_node;
-		of_property_read_u32(of_node, "ti,charge-period", &charge_period);
+
+		of_property_read_u32(of_node, "ti,charge-period",
+				     &priv->charge_period);
 
 		for (i = 0; i < 6; i++) {
 			char name[25];
@@ -735,43 +828,11 @@
 				 "ti,mid-z-channel-%d", i + 1);
 
 			if (of_get_property(of_node, name, NULL) != NULL)
-				pwm_start_mid_z |= 1 << i;
+				priv->pwm_start_mid_z |= 1 << i;
 		}
 	}
 
-	/*
-	 * If any of the channels is configured to start in Mid-Z mode,
-	 * configure 'part 1' of the PWM starts to use Mid-Z, and tell
-	 * all configured mid-z channels to start start under 'part 1'.
-	 */
-	if (pwm_start_mid_z)
-		regmap_write(priv->regmap, TAS5086_PWM_START,
-			     TAS5086_PWM_START_MIDZ_FOR_START_1 |
-				pwm_start_mid_z);
-
-	/* lookup and set split-capacitor charge period */
-	if (charge_period == 0) {
-		regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0);
-	} else {
-		i = index_in_array(tas5086_charge_period,
-				   ARRAY_SIZE(tas5086_charge_period),
-				   charge_period);
-		if (i >= 0)
-			regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE,
-				     i + 0x08);
-		else
-			dev_warn(codec->dev,
-				 "Invalid split-cap charge period of %d ns.\n",
-				 charge_period);
-	}
-
-	/* enable factory trim */
-	ret = regmap_write(priv->regmap, TAS5086_OSC_TRIM, 0x00);
-	if (ret < 0)
-		return ret;
-
-	/* start all channels */
-	ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x20);
+	ret = tas5086_init(codec->dev, priv);
 	if (ret < 0)
 		return ret;
 
@@ -780,12 +841,6 @@
 	if (ret < 0)
 		return ret;
 
-	/* mute all channels for now */
-	ret = regmap_write(priv->regmap, TAS5086_SOFT_MUTE,
-			   TAS5086_SOFT_MUTE_ALL);
-	if (ret < 0)
-		return ret;
-
 	return 0;
 }
 
@@ -803,6 +858,7 @@
 static struct snd_soc_codec_driver soc_codec_dev_tas5086 = {
 	.probe			= tas5086_probe,
 	.remove			= tas5086_remove,
+	.suspend		= tas5086_soc_suspend,
 	.resume			= tas5086_soc_resume,
 	.controls		= tas5086_controls,
 	.num_controls		= ARRAY_SIZE(tas5086_controls),
@@ -862,17 +918,8 @@
 		if (devm_gpio_request(dev, gpio_nreset, "TAS5086 Reset"))
 			gpio_nreset = -EINVAL;
 
-	if (gpio_is_valid(gpio_nreset)) {
-		/* Reset codec - minimum assertion time is 400ns */
-		gpio_direction_output(gpio_nreset, 0);
-		udelay(1);
-		gpio_set_value(gpio_nreset, 1);
-
-		/* Codec needs ~15ms to wake up */
-		msleep(15);
-	}
-
 	priv->gpio_nreset = gpio_nreset;
+	tas5086_reset(priv);
 
 	/* The TAS5086 always returns 0x03 in its TAS5086_DEV_ID register */
 	ret = regmap_read(priv->regmap, TAS5086_DEV_ID, &i);
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 31762eb..5d430cc 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -24,6 +24,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -37,11 +38,27 @@
 /*
  * AIC23 register cache
  */
-static const u16 tlv320aic23_reg[] = {
-	0x0097, 0x0097, 0x00F9, 0x00F9,	/* 0 */
-	0x001A, 0x0004, 0x0007, 0x0001,	/* 4 */
-	0x0020, 0x0000, 0x0000, 0x0000,	/* 8 */
-	0x0000, 0x0000, 0x0000, 0x0000,	/* 12 */
+static const struct reg_default tlv320aic23_reg[] = {
+	{  0, 0x0097 },
+	{  1, 0x0097 },
+	{  2, 0x00F9 },
+	{  3, 0x00F9 },
+	{  4, 0x001A },
+	{  5, 0x0004 },
+	{  6, 0x0007 },
+	{  7, 0x0001 },
+	{  8, 0x0020 },
+	{  9, 0x0000 },
+};
+
+static const struct regmap_config tlv320aic23_regmap = {
+	.reg_bits = 7,
+	.val_bits = 9,
+
+	.max_register = TLV320AIC23_RESET,
+	.reg_defaults = tlv320aic23_reg,
+	.num_reg_defaults = ARRAY_SIZE(tlv320aic23_reg),
+	.cache_type = REGCACHE_RBTREE,
 };
 
 static const char *rec_src_text[] = { "Line", "Mic" };
@@ -171,7 +188,7 @@
 
 /* AIC23 driver data */
 struct aic23 {
-	enum snd_soc_control_type control_type;
+	struct regmap *regmap;
 	int mclk;
 	int requested_adc;
 	int requested_dac;
@@ -532,7 +549,9 @@
 
 static int tlv320aic23_resume(struct snd_soc_codec *codec)
 {
-	snd_soc_cache_sync(codec);
+	struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
+	regcache_mark_dirty(aic23->regmap);
+	regcache_sync(aic23->regmap);
 	tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
 	return 0;
@@ -540,10 +559,9 @@
 
 static int tlv320aic23_probe(struct snd_soc_codec *codec)
 {
-	struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
 	int ret;
 
-	ret = snd_soc_codec_set_cache_io(codec, 7, 9, aic23->control_type);
+	ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
 	if (ret < 0) {
 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
 		return ret;
@@ -552,16 +570,6 @@
 	/* Reset codec */
 	snd_soc_write(codec, TLV320AIC23_RESET, 0);
 
-	/* Write the register default value to cache for reserved registers,
-	 * so the write to the these registers are suppressed by the cache
-	 * restore code when it skips writes of default registers.
-	 */
-	snd_soc_cache_write(codec, 0x0A, 0);
-	snd_soc_cache_write(codec, 0x0B, 0);
-	snd_soc_cache_write(codec, 0x0C, 0);
-	snd_soc_cache_write(codec, 0x0D, 0);
-	snd_soc_cache_write(codec, 0x0E, 0);
-
 	/* power on device */
 	tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
@@ -586,9 +594,6 @@
 
 	snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x1);
 
-	snd_soc_add_codec_controls(codec, tlv320aic23_snd_controls,
-				ARRAY_SIZE(tlv320aic23_snd_controls));
-
 	return 0;
 }
 
@@ -599,21 +604,19 @@
 }
 
 static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
-	.reg_cache_size = ARRAY_SIZE(tlv320aic23_reg),
-	.reg_word_size = sizeof(u16),
-	.reg_cache_default = tlv320aic23_reg,
 	.probe = tlv320aic23_probe,
 	.remove = tlv320aic23_remove,
 	.suspend = tlv320aic23_suspend,
 	.resume = tlv320aic23_resume,
 	.set_bias_level = tlv320aic23_set_bias_level,
+	.controls = tlv320aic23_snd_controls,
+	.num_controls = ARRAY_SIZE(tlv320aic23_snd_controls),
 	.dapm_widgets = tlv320aic23_dapm_widgets,
 	.num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
 	.dapm_routes = tlv320aic23_intercon,
 	.num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon),
 };
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 /*
  * If the i2c layer weren't so broken, we could pass this kind of data
  * around
@@ -631,8 +634,11 @@
 	if (aic23 == NULL)
 		return -ENOMEM;
 
+	aic23->regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap);
+	if (IS_ERR(aic23->regmap))
+		return PTR_ERR(aic23->regmap);
+
 	i2c_set_clientdata(i2c, aic23);
-	aic23->control_type = SND_SOC_I2C;
 
 	ret =  snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1);
@@ -660,29 +666,7 @@
 	.id_table = tlv320aic23_id,
 };
 
-#endif
-
-static int __init tlv320aic23_modinit(void)
-{
-	int ret;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-	ret = i2c_add_driver(&tlv320aic23_i2c_driver);
-	if (ret != 0) {
-		printk(KERN_ERR "Failed to register TLV320AIC23 I2C driver: %d\n",
-		       ret);
-	}
-#endif
-	return ret;
-}
-module_init(tlv320aic23_modinit);
-
-static void __exit tlv320aic23_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-	i2c_del_driver(&tlv320aic23_i2c_driver);
-#endif
-}
-module_exit(tlv320aic23_exit);
+module_i2c_driver(tlv320aic23_i2c_driver);
 
 MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver");
 MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index 7b8f3d9..94a658f 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -29,6 +29,7 @@
 /* AIC26 driver private data */
 struct aic26 {
 	struct spi_device *spi;
+	struct regmap *regmap;
 	struct snd_soc_codec *codec;
 	int master;
 	int datfm;
@@ -40,85 +41,6 @@
 	int keyclick_len;
 };
 
-/* ---------------------------------------------------------------------
- * Register access routines
- */
-static unsigned int aic26_reg_read(struct snd_soc_codec *codec,
-				   unsigned int reg)
-{
-	struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
-	u16 *cache = codec->reg_cache;
-	u16 cmd, value;
-	u8 buffer[2];
-	int rc;
-
-	if (reg >= AIC26_NUM_REGS) {
-		WARN_ON_ONCE(1);
-		return 0;
-	}
-
-	/* Do SPI transfer; first 16bits are command; remaining is
-	 * register contents */
-	cmd = AIC26_READ_COMMAND_WORD(reg);
-	buffer[0] = (cmd >> 8) & 0xff;
-	buffer[1] = cmd & 0xff;
-	rc = spi_write_then_read(aic26->spi, buffer, 2, buffer, 2);
-	if (rc) {
-		dev_err(&aic26->spi->dev, "AIC26 reg read error\n");
-		return -EIO;
-	}
-	value = (buffer[0] << 8) | buffer[1];
-
-	/* Update the cache before returning with the value */
-	cache[reg] = value;
-	return value;
-}
-
-static unsigned int aic26_reg_read_cache(struct snd_soc_codec *codec,
-					 unsigned int reg)
-{
-	u16 *cache = codec->reg_cache;
-
-	if (reg >= AIC26_NUM_REGS) {
-		WARN_ON_ONCE(1);
-		return 0;
-	}
-
-	return cache[reg];
-}
-
-static int aic26_reg_write(struct snd_soc_codec *codec, unsigned int reg,
-			   unsigned int value)
-{
-	struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
-	u16 *cache = codec->reg_cache;
-	u16 cmd;
-	u8 buffer[4];
-	int rc;
-
-	if (reg >= AIC26_NUM_REGS) {
-		WARN_ON_ONCE(1);
-		return -EINVAL;
-	}
-
-	/* Do SPI transfer; first 16bits are command; remaining is data
-	 * to write into register */
-	cmd = AIC26_WRITE_COMMAND_WORD(reg);
-	buffer[0] = (cmd >> 8) & 0xff;
-	buffer[1] = cmd & 0xff;
-	buffer[2] = value >> 8;
-	buffer[3] = value;
-	rc = spi_write(aic26->spi, buffer, 4);
-	if (rc) {
-		dev_err(&aic26->spi->dev, "AIC26 reg read error\n");
-		return -EIO;
-	}
-
-	/* update cache before returning */
-	cache[reg] = value;
-	return 0;
-}
-
 static const struct snd_soc_dapm_widget tlv320aic26_dapm_widgets[] = {
 SND_SOC_DAPM_INPUT("MICIN"),
 SND_SOC_DAPM_INPUT("AUX"),
@@ -195,19 +117,15 @@
 	snd_soc_write(codec, AIC26_REG_PLL_PROG2, reg);
 
 	/* Audio Control 3 (master mode, fsref rate) */
-	reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL3);
-	reg &= ~0xf800;
 	if (aic26->master)
-		reg |= 0x0800;
+		reg = 0x0800;
 	if (fsref == 48000)
-		reg |= 0x2000;
-	snd_soc_write(codec, AIC26_REG_AUDIO_CTRL3, reg);
+		reg = 0x2000;
+	snd_soc_update_bits(codec, AIC26_REG_AUDIO_CTRL3, 0xf800, reg);
 
 	/* Audio Control 1 (FSref divisor) */
-	reg = aic26_reg_read_cache(codec, AIC26_REG_AUDIO_CTRL1);
-	reg &= ~0x0fff;
-	reg |= wlen | aic26->datfm | (divisor << 3) | divisor;
-	snd_soc_write(codec, AIC26_REG_AUDIO_CTRL1, reg);
+	reg = wlen | aic26->datfm | (divisor << 3) | divisor;
+	snd_soc_update_bits(codec, AIC26_REG_AUDIO_CTRL1, 0xfff, reg);
 
 	return 0;
 }
@@ -219,16 +137,16 @@
 {
 	struct snd_soc_codec *codec = dai->codec;
 	struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
-	u16 reg = aic26_reg_read_cache(codec, AIC26_REG_DAC_GAIN);
+	u16 reg;
 
 	dev_dbg(&aic26->spi->dev, "aic26_mute(dai=%p, mute=%i)\n",
 		dai, mute);
 
 	if (mute)
-		reg |= 0x8080;
+		reg = 0x8080;
 	else
-		reg &= ~0x8080;
-	snd_soc_write(codec, AIC26_REG_DAC_GAIN, reg);
+		reg = 0;
+	snd_soc_update_bits(codec, AIC26_REG_DAC_GAIN, 0x8000, reg);
 
 	return 0;
 }
@@ -346,7 +264,7 @@
 	struct aic26 *aic26 = dev_get_drvdata(dev);
 	int val, amp, freq, len;
 
-	val = aic26_reg_read_cache(aic26->codec, AIC26_REG_AUDIO_CTRL2);
+	val = snd_soc_read(aic26->codec, AIC26_REG_AUDIO_CTRL2);
 	amp = (val >> 12) & 0x7;
 	freq = (125 << ((val >> 8) & 0x7)) >> 1;
 	len = 2 * (1 + ((val >> 4) & 0xf));
@@ -360,11 +278,9 @@
 				  const char *buf, size_t count)
 {
 	struct aic26 *aic26 = dev_get_drvdata(dev);
-	int val;
 
-	val = aic26_reg_read_cache(aic26->codec, AIC26_REG_AUDIO_CTRL2);
-	val |= 0x8000;
-	snd_soc_write(aic26->codec, AIC26_REG_AUDIO_CTRL2, val);
+	snd_soc_update_bits(aic26->codec, AIC26_REG_AUDIO_CTRL2,
+			    0x8000, 0x800);
 
 	return count;
 }
@@ -377,7 +293,9 @@
 static int aic26_probe(struct snd_soc_codec *codec)
 {
 	struct aic26 *aic26 = dev_get_drvdata(codec->dev);
-	int ret, err, i, reg;
+	int ret, reg;
+
+	snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
 
 	aic26->codec = codec;
 
@@ -393,37 +311,30 @@
 	reg |= 0x0800; /* set master mode */
 	snd_soc_write(codec, AIC26_REG_AUDIO_CTRL3, reg);
 
-	/* Fill register cache */
-	for (i = 0; i < codec->driver->reg_cache_size; i++)
-		snd_soc_read(codec, i);
-
 	/* Register the sysfs files for debugging */
 	/* Create SysFS files */
 	ret = device_create_file(codec->dev, &dev_attr_keyclick);
 	if (ret)
 		dev_info(codec->dev, "error creating sysfs files\n");
 
-	/* register controls */
-	dev_dbg(codec->dev, "Registering controls\n");
-	err = snd_soc_add_codec_controls(codec, aic26_snd_controls,
-			ARRAY_SIZE(aic26_snd_controls));
-	WARN_ON(err < 0);
-
 	return 0;
 }
 
 static struct snd_soc_codec_driver aic26_soc_codec_dev = {
 	.probe = aic26_probe,
-	.read = aic26_reg_read,
-	.write = aic26_reg_write,
-	.reg_cache_size = AIC26_NUM_REGS,
-	.reg_word_size = sizeof(u16),
+	.controls = aic26_snd_controls,
+	.num_controls = ARRAY_SIZE(aic26_snd_controls),
 	.dapm_widgets = tlv320aic26_dapm_widgets,
 	.num_dapm_widgets = ARRAY_SIZE(tlv320aic26_dapm_widgets),
 	.dapm_routes = tlv320aic26_dapm_routes,
 	.num_dapm_routes = ARRAY_SIZE(tlv320aic26_dapm_routes),
 };
 
+static const struct regmap_config aic26_regmap = {
+	.reg_bits = 16,
+	.val_bits = 16,
+};
+
 /* ---------------------------------------------------------------------
  * SPI device portion of driver: probe and release routines and SPI
  * 				 driver registration.
@@ -440,6 +351,10 @@
 	if (!aic26)
 		return -ENOMEM;
 
+	aic26->regmap = devm_regmap_init_spi(spi, &aic26_regmap);
+	if (IS_ERR(aic26->regmap))
+		return PTR_ERR(aic26->regmap);
+
 	/* Initialize the driver data */
 	aic26->spi = spi;
 	dev_set_drvdata(&spi->dev, aic26);
diff --git a/sound/soc/codecs/tlv320aic26.h b/sound/soc/codecs/tlv320aic26.h
index 67f19c3..629b85e 100644
--- a/sound/soc/codecs/tlv320aic26.h
+++ b/sound/soc/codecs/tlv320aic26.h
@@ -9,10 +9,7 @@
 #define _TLV320AIC16_H_
 
 /* AIC26 Registers */
-#define AIC26_READ_COMMAND_WORD(addr)	((1 << 15) | (addr << 5))
-#define AIC26_WRITE_COMMAND_WORD(addr)	((0 << 15) | (addr << 5))
-#define AIC26_PAGE_ADDR(page, offset)	((page << 6) | offset)
-#define AIC26_NUM_REGS			AIC26_PAGE_ADDR(3, 0)
+#define AIC26_PAGE_ADDR(page, offset)	((page << 11) | offset << 5)
 
 /* Page 0: Auxiliary data registers */
 #define AIC26_REG_BAT1			AIC26_PAGE_ADDR(0, 0x05)
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index 2ed57d4..18cdcca 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -60,9 +60,8 @@
 };
 
 struct aic32x4_priv {
+	struct regmap *regmap;
 	u32 sysclk;
-	u8 page_no;
-	void *control_data;
 	u32 power_cfg;
 	u32 micpga_routing;
 	bool swapdacs;
@@ -262,67 +261,25 @@
 	{"Right ADC", NULL, "Right Input Mixer"},
 };
 
-static inline int aic32x4_change_page(struct snd_soc_codec *codec,
-					unsigned int new_page)
-{
-	struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
-	u8 data[2];
-	int ret;
+static const struct regmap_range_cfg aic32x4_regmap_pages[] = {
+	{
+		.selector_reg = 0,
+		.selector_mask  = 0xff,
+		.window_start = 0,
+		.window_len = 128,
+		.range_min = AIC32X4_PAGE1,
+		.range_max = AIC32X4_PAGE1 + 127,
+	},
+};
 
-	data[0] = 0x00;
-	data[1] = new_page & 0xff;
+static const struct regmap_config aic32x4_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
 
-	ret = codec->hw_write(codec->control_data, data, 2);
-	if (ret == 2) {
-		aic32x4->page_no = new_page;
-		return 0;
-	} else {
-		return ret;
-	}
-}
-
-static int aic32x4_write(struct snd_soc_codec *codec, unsigned int reg,
-				unsigned int val)
-{
-	struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
-	unsigned int page = reg / 128;
-	unsigned int fixed_reg = reg % 128;
-	u8 data[2];
-	int ret;
-
-	/* A write to AIC32X4_PSEL is really a non-explicit page change */
-	if (reg == AIC32X4_PSEL)
-		return aic32x4_change_page(codec, val);
-
-	if (aic32x4->page_no != page) {
-		ret = aic32x4_change_page(codec, page);
-		if (ret != 0)
-			return ret;
-	}
-
-	data[0] = fixed_reg & 0xff;
-	data[1] = val & 0xff;
-
-	if (codec->hw_write(codec->control_data, data, 2) == 2)
-		return 0;
-	else
-		return -EIO;
-}
-
-static unsigned int aic32x4_read(struct snd_soc_codec *codec, unsigned int reg)
-{
-	struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
-	unsigned int page = reg / 128;
-	unsigned int fixed_reg = reg % 128;
-	int ret;
-
-	if (aic32x4->page_no != page) {
-		ret = aic32x4_change_page(codec, page);
-		if (ret != 0)
-			return ret;
-	}
-	return i2c_smbus_read_byte_data(codec->control_data, fixed_reg & 0xff);
-}
+	.max_register = AIC32X4_RMICPGAVOL,
+	.ranges = aic32x4_regmap_pages,
+	.num_ranges = ARRAY_SIZE(aic32x4_regmap_pages),
+};
 
 static inline int aic32x4_get_divs(int mclk, int rate)
 {
@@ -617,16 +574,10 @@
 {
 	struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
 	u32 tmp_reg;
-	int ret;
 
-	codec->hw_write = (hw_write_t) i2c_master_send;
-	codec->control_data = aic32x4->control_data;
+	snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
 
 	if (aic32x4->rstn_gpio >= 0) {
-		ret = devm_gpio_request_one(codec->dev, aic32x4->rstn_gpio,
-				GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn");
-		if (ret != 0)
-			return ret;
 		ndelay(10);
 		gpio_set_value(aic32x4->rstn_gpio, 1);
 	}
@@ -692,8 +643,6 @@
 }
 
 static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = {
-	.read = aic32x4_read,
-	.write = aic32x4_write,
 	.probe = aic32x4_probe,
 	.remove = aic32x4_remove,
 	.suspend = aic32x4_suspend,
@@ -720,7 +669,10 @@
 	if (aic32x4 == NULL)
 		return -ENOMEM;
 
-	aic32x4->control_data = i2c;
+	aic32x4->regmap = devm_regmap_init_i2c(i2c, &aic32x4_regmap);
+	if (IS_ERR(aic32x4->regmap))
+		return PTR_ERR(aic32x4->regmap);
+
 	i2c_set_clientdata(i2c, aic32x4);
 
 	if (pdata) {
@@ -735,6 +687,13 @@
 		aic32x4->rstn_gpio = -1;
 	}
 
+	if (aic32x4->rstn_gpio >= 0) {
+		ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio,
+				GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn");
+		if (ret != 0)
+			return ret;
+	}
+
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_aic32x4, &aic32x4_dai, 1);
 	return ret;
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 6e3f269..546d16b 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -40,6 +40,7 @@
 #include <linux/i2c.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
+#include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -72,9 +73,9 @@
 /* codec private data */
 struct aic3x_priv {
 	struct snd_soc_codec *codec;
+	struct regmap *regmap;
 	struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES];
 	struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES];
-	enum snd_soc_control_type control_type;
 	struct aic3x_setup_data *setup;
 	unsigned int sysclk;
 	struct list_head list;
@@ -90,41 +91,45 @@
 	enum aic3x_micbias_voltage micbias_vg;
 };
 
-/*
- * AIC3X register cache
- * We can't read the AIC3X register space when we are
- * using 2 wire for device control, so we cache them instead.
- * There is no point in caching the reset register
- */
-static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = {
-	0x00, 0x00, 0x00, 0x10,	/* 0 */
-	0x04, 0x00, 0x00, 0x00,	/* 4 */
-	0x00, 0x00, 0x00, 0x01,	/* 8 */
-	0x00, 0x00, 0x00, 0x80,	/* 12 */
-	0x80, 0xff, 0xff, 0x78,	/* 16 */
-	0x78, 0x78, 0x78, 0x78,	/* 20 */
-	0x78, 0x00, 0x00, 0xfe,	/* 24 */
-	0x00, 0x00, 0xfe, 0x00,	/* 28 */
-	0x18, 0x18, 0x00, 0x00,	/* 32 */
-	0x00, 0x00, 0x00, 0x00,	/* 36 */
-	0x00, 0x00, 0x00, 0x80,	/* 40 */
-	0x80, 0x00, 0x00, 0x00,	/* 44 */
-	0x00, 0x00, 0x00, 0x04,	/* 48 */
-	0x00, 0x00, 0x00, 0x00,	/* 52 */
-	0x00, 0x00, 0x04, 0x00,	/* 56 */
-	0x00, 0x00, 0x00, 0x00,	/* 60 */
-	0x00, 0x04, 0x00, 0x00,	/* 64 */
-	0x00, 0x00, 0x00, 0x00,	/* 68 */
-	0x04, 0x00, 0x00, 0x00,	/* 72 */
-	0x00, 0x00, 0x00, 0x00,	/* 76 */
-	0x00, 0x00, 0x00, 0x00,	/* 80 */
-	0x00, 0x00, 0x00, 0x00,	/* 84 */
-	0x00, 0x00, 0x00, 0x00,	/* 88 */
-	0x00, 0x00, 0x00, 0x00,	/* 92 */
-	0x00, 0x00, 0x00, 0x00,	/* 96 */
-	0x00, 0x00, 0x02, 0x00,	/* 100 */
-	0x00, 0x00, 0x00, 0x00,	/* 104 */
-	0x00, 0x00,            	/* 108 */
+static const struct reg_default aic3x_reg[] = {
+	{   0, 0x00 }, {   1, 0x00 }, {   2, 0x00 }, {   3, 0x10 },
+	{   4, 0x04 }, {   5, 0x00 }, {   6, 0x00 }, {   7, 0x00 },
+	{   8, 0x00 }, {   9, 0x00 }, {  10, 0x00 }, {  11, 0x01 },
+	{  12, 0x00 }, {  13, 0x00 }, {  14, 0x00 }, {  15, 0x80 },
+	{  16, 0x80 }, {  17, 0xff }, {  18, 0xff }, {  19, 0x78 },
+	{  20, 0x78 }, {  21, 0x78 }, {  22, 0x78 }, {  23, 0x78 },
+	{  24, 0x78 }, {  25, 0x00 }, {  26, 0x00 }, {  27, 0xfe },
+	{  28, 0x00 }, {  29, 0x00 }, {  30, 0xfe }, {  31, 0x00 },
+	{  32, 0x18 }, {  33, 0x18 }, {  34, 0x00 }, {  35, 0x00 },
+	{  36, 0x00 }, {  37, 0x00 }, {  38, 0x00 }, {  39, 0x00 },
+	{  40, 0x00 }, {  41, 0x00 }, {  42, 0x00 }, {  43, 0x80 },
+	{  44, 0x80 }, {  45, 0x00 }, {  46, 0x00 }, {  47, 0x00 },
+	{  48, 0x00 }, {  49, 0x00 }, {  50, 0x00 }, {  51, 0x04 },
+	{  52, 0x00 }, {  53, 0x00 }, {  54, 0x00 }, {  55, 0x00 },
+	{  56, 0x00 }, {  57, 0x00 }, {  58, 0x04 }, {  59, 0x00 },
+	{  60, 0x00 }, {  61, 0x00 }, {  62, 0x00 }, {  63, 0x00 },
+	{  64, 0x00 }, {  65, 0x04 }, {  66, 0x00 }, {  67, 0x00 },
+	{  68, 0x00 }, {  69, 0x00 }, {  70, 0x00 }, {  71, 0x00 },
+	{  72, 0x04 }, {  73, 0x00 }, {  74, 0x00 }, {  75, 0x00 },
+	{  76, 0x00 }, {  77, 0x00 }, {  78, 0x00 }, {  79, 0x00 },
+	{  80, 0x00 }, {  81, 0x00 }, {  82, 0x00 }, {  83, 0x00 },
+	{  84, 0x00 }, {  85, 0x00 }, {  86, 0x00 }, {  87, 0x00 },
+	{  88, 0x00 }, {  89, 0x00 }, {  90, 0x00 }, {  91, 0x00 },
+	{  92, 0x00 }, {  93, 0x00 }, {  94, 0x00 }, {  95, 0x00 },
+	{  96, 0x00 }, {  97, 0x00 }, {  98, 0x00 }, {  99, 0x00 },
+	{ 100, 0x00 }, { 101, 0x00 }, { 102, 0x02 }, { 103, 0x00 },
+	{ 104, 0x00 }, { 105, 0x00 }, { 106, 0x00 }, { 107, 0x00 },
+	{ 108, 0x00 }, { 109, 0x00 },
+};
+
+static const struct regmap_config aic3x_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = DAC_ICC_ADJ,
+	.reg_defaults = aic3x_reg,
+	.num_reg_defaults = ARRAY_SIZE(aic3x_reg),
+	.cache_type = REGCACHE_RBTREE,
 };
 
 #define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \
@@ -674,6 +679,8 @@
 	/* Left Input */
 	{"Left Line1L Mux", "single-ended", "LINE1L"},
 	{"Left Line1L Mux", "differential", "LINE1L"},
+	{"Left Line1R Mux", "single-ended", "LINE1R"},
+	{"Left Line1R Mux", "differential", "LINE1R"},
 
 	{"Left Line2L Mux", "single-ended", "LINE2L"},
 	{"Left Line2L Mux", "differential", "LINE2L"},
@@ -690,6 +697,8 @@
 	/* Right Input */
 	{"Right Line1R Mux", "single-ended", "LINE1R"},
 	{"Right Line1R Mux", "differential", "LINE1R"},
+	{"Right Line1L Mux", "single-ended", "LINE1L"},
+	{"Right Line1L Mux", "differential", "LINE1L"},
 
 	{"Right Line2R Mux", "single-ended", "LINE2R"},
 	{"Right Line2R Mux", "differential", "LINE2R"},
@@ -824,12 +833,6 @@
 	struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
 
-	snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets,
-				  ARRAY_SIZE(aic3x_dapm_widgets));
-
-	/* set up audio path interconnects */
-	snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
-
 	if (aic3x->model == AIC3X_MODEL_3007) {
 		snd_soc_dapm_new_controls(dapm, aic3007_dapm_widgets,
 			ARRAY_SIZE(aic3007_dapm_widgets));
@@ -1078,29 +1081,6 @@
 	return 0;
 }
 
-static int aic3x_init_3007(struct snd_soc_codec *codec)
-{
-	u8 tmp1, tmp2, *cache = codec->reg_cache;
-
-	/*
-	 * There is no need to cache writes to undocumented page 0xD but
-	 * respective page 0 register cache entries must be preserved
-	 */
-	tmp1 = cache[0xD];
-	tmp2 = cache[0x8];
-	/* Class-D speaker driver init; datasheet p. 46 */
-	snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x0D);
-	snd_soc_write(codec, 0xD, 0x0D);
-	snd_soc_write(codec, 0x8, 0x5C);
-	snd_soc_write(codec, 0x8, 0x5D);
-	snd_soc_write(codec, 0x8, 0x5C);
-	snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x00);
-	cache[0xD] = tmp1;
-	cache[0x8] = tmp2;
-
-	return 0;
-}
-
 static int aic3x_regulator_event(struct notifier_block *nb,
 				 unsigned long event, void *data)
 {
@@ -1115,7 +1095,7 @@
 		 */
 		if (gpio_is_valid(aic3x->gpio_reset))
 			gpio_set_value(aic3x->gpio_reset, 0);
-		aic3x->codec->cache_sync = 1;
+		regcache_mark_dirty(aic3x->regmap);
 	}
 
 	return 0;
@@ -1124,8 +1104,7 @@
 static int aic3x_set_power(struct snd_soc_codec *codec, int power)
 {
 	struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
-	int i, ret;
-	u8 *cache = codec->reg_cache;
+	int ret;
 
 	if (power) {
 		ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),
@@ -1133,12 +1112,6 @@
 		if (ret)
 			goto out;
 		aic3x->power = 1;
-		/*
-		 * Reset release and cache sync is necessary only if some
-		 * supply was off or if there were cached writes
-		 */
-		if (!codec->cache_sync)
-			goto out;
 
 		if (gpio_is_valid(aic3x->gpio_reset)) {
 			udelay(1);
@@ -1146,12 +1119,8 @@
 		}
 
 		/* Sync reg_cache with the hardware */
-		codec->cache_only = 0;
-		for (i = AIC3X_SAMPLE_RATE_SEL_REG; i < ARRAY_SIZE(aic3x_reg); i++)
-			snd_soc_write(codec, i, cache[i]);
-		if (aic3x->model == AIC3X_MODEL_3007)
-			aic3x_init_3007(codec);
-		codec->cache_sync = 0;
+		regcache_cache_only(aic3x->regmap, false);
+		regcache_sync(aic3x->regmap);
 	} else {
 		/*
 		 * Do soft reset to this codec instance in order to clear
@@ -1159,10 +1128,10 @@
 		 * remain on
 		 */
 		snd_soc_write(codec, AIC3X_RESET, SOFT_RESET);
-		codec->cache_sync = 1;
+		regcache_mark_dirty(aic3x->regmap);
 		aic3x->power = 0;
 		/* HW writes are needless when bias is off */
-		codec->cache_only = 1;
+		regcache_cache_only(aic3x->regmap, true);
 		ret = regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies),
 					     aic3x->supplies);
 	}
@@ -1317,7 +1286,6 @@
 	snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL);
 
 	if (aic3x->model == AIC3X_MODEL_3007) {
-		aic3x_init_3007(codec);
 		snd_soc_write(codec, CLASSD_CTRL, 0);
 	}
 
@@ -1345,29 +1313,12 @@
 	INIT_LIST_HEAD(&aic3x->list);
 	aic3x->codec = codec;
 
-	ret = snd_soc_codec_set_cache_io(codec, 8, 8, aic3x->control_type);
+	ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
 	if (ret != 0) {
 		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
 		return ret;
 	}
 
-	if (gpio_is_valid(aic3x->gpio_reset) &&
-	    !aic3x_is_shared_reset(aic3x)) {
-		ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset");
-		if (ret != 0)
-			goto err_gpio;
-		gpio_direction_output(aic3x->gpio_reset, 0);
-	}
-
-	for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
-		aic3x->supplies[i].supply = aic3x_supply_names[i];
-
-	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies),
-				 aic3x->supplies);
-	if (ret != 0) {
-		dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
-		goto err_get;
-	}
 	for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) {
 		aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event;
 		aic3x->disable_nb[i].aic3x = aic3x;
@@ -1381,7 +1332,7 @@
 		}
 	}
 
-	codec->cache_only = 1;
+	regcache_mark_dirty(aic3x->regmap);
 	aic3x_init(codec);
 
 	if (aic3x->setup) {
@@ -1392,8 +1343,6 @@
 			      (aic3x->setup->gpio_func[1] & 0xf) << 4);
 	}
 
-	snd_soc_add_codec_controls(codec, aic3x_snd_controls,
-			     ARRAY_SIZE(aic3x_snd_controls));
 	if (aic3x->model == AIC3X_MODEL_3007)
 		snd_soc_add_codec_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
 
@@ -1424,12 +1373,6 @@
 	while (i--)
 		regulator_unregister_notifier(aic3x->supplies[i].consumer,
 					      &aic3x->disable_nb[i].nb);
-	regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
-err_get:
-	if (gpio_is_valid(aic3x->gpio_reset) &&
-	    !aic3x_is_shared_reset(aic3x))
-		gpio_free(aic3x->gpio_reset);
-err_gpio:
 	return ret;
 }
 
@@ -1440,15 +1383,9 @@
 
 	aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	list_del(&aic3x->list);
-	if (gpio_is_valid(aic3x->gpio_reset) &&
-	    !aic3x_is_shared_reset(aic3x)) {
-		gpio_set_value(aic3x->gpio_reset, 0);
-		gpio_free(aic3x->gpio_reset);
-	}
 	for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
 		regulator_unregister_notifier(aic3x->supplies[i].consumer,
 					      &aic3x->disable_nb[i].nb);
-	regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
 
 	return 0;
 }
@@ -1456,13 +1393,16 @@
 static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
 	.set_bias_level = aic3x_set_bias_level,
 	.idle_bias_off = true,
-	.reg_cache_size = ARRAY_SIZE(aic3x_reg),
-	.reg_word_size = sizeof(u8),
-	.reg_cache_default = aic3x_reg,
 	.probe = aic3x_probe,
 	.remove = aic3x_remove,
 	.suspend = aic3x_suspend,
 	.resume = aic3x_resume,
+	.controls = aic3x_snd_controls,
+	.num_controls = ARRAY_SIZE(aic3x_snd_controls),
+	.dapm_widgets = aic3x_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(aic3x_dapm_widgets),
+	.dapm_routes = intercon,
+	.num_dapm_routes = ARRAY_SIZE(intercon),
 };
 
 /*
@@ -1479,6 +1419,16 @@
 };
 MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
 
+static const struct reg_default aic3007_class_d[] = {
+	/* Class-D speaker driver init; datasheet p. 46 */
+	{ AIC3X_PAGE_SELECT, 0x0D },
+	{ 0xD, 0x0D },
+	{ 0x8, 0x5C },
+	{ 0x8, 0x5D },
+	{ 0x8, 0x5C },
+	{ AIC3X_PAGE_SELECT, 0x00 },
+};
+
 /*
  * If the i2c layer weren't so broken, we could pass this kind of data
  * around
@@ -1490,7 +1440,7 @@
 	struct aic3x_priv *aic3x;
 	struct aic3x_setup_data *ai3x_setup;
 	struct device_node *np = i2c->dev.of_node;
-	int ret;
+	int ret, i;
 	u32 value;
 
 	aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL);
@@ -1499,7 +1449,13 @@
 		return -ENOMEM;
 	}
 
-	aic3x->control_type = SND_SOC_I2C;
+	aic3x->regmap = devm_regmap_init_i2c(i2c, &aic3x_regmap);
+	if (IS_ERR(aic3x->regmap)) {
+		ret = PTR_ERR(aic3x->regmap);
+		return ret;
+	}
+
+	regcache_cache_only(aic3x->regmap, true);
 
 	i2c_set_clientdata(i2c, aic3x);
 	if (pdata) {
@@ -1551,14 +1507,54 @@
 
 	aic3x->model = id->driver_data;
 
+	if (gpio_is_valid(aic3x->gpio_reset) &&
+	    !aic3x_is_shared_reset(aic3x)) {
+		ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset");
+		if (ret != 0)
+			goto err;
+		gpio_direction_output(aic3x->gpio_reset, 0);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
+		aic3x->supplies[i].supply = aic3x_supply_names[i];
+
+	ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(aic3x->supplies),
+				      aic3x->supplies);
+	if (ret != 0) {
+		dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
+		goto err_gpio;
+	}
+
+	if (aic3x->model == AIC3X_MODEL_3007) {
+		ret = regmap_register_patch(aic3x->regmap, aic3007_class_d,
+					    ARRAY_SIZE(aic3007_class_d));
+		if (ret != 0)
+			dev_err(&i2c->dev, "Failed to init class D: %d\n",
+				ret);
+	}
+
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_aic3x, &aic3x_dai, 1);
 	return ret;
+
+err_gpio:
+	if (gpio_is_valid(aic3x->gpio_reset) &&
+	    !aic3x_is_shared_reset(aic3x))
+		gpio_free(aic3x->gpio_reset);
+err:
+	return ret;
 }
 
 static int aic3x_i2c_remove(struct i2c_client *client)
 {
+	struct aic3x_priv *aic3x = i2c_get_clientdata(client);
+
 	snd_soc_unregister_codec(&client->dev);
+	if (gpio_is_valid(aic3x->gpio_reset) &&
+	    !aic3x_is_shared_reset(aic3x)) {
+		gpio_set_value(aic3x->gpio_reset, 0);
+		gpio_free(aic3x->gpio_reset);
+	}
 	return 0;
 }
 
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index c58bee8..b27c396 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -30,6 +30,7 @@
 #include <sound/tpa6130a2-plat.h>
 #include <sound/soc.h>
 #include <sound/tlv.h>
+#include <linux/of_gpio.h>
 
 #include "tpa6130a2.h"
 
@@ -55,7 +56,8 @@
 	struct tpa6130a2_data *data;
 	int val;
 
-	BUG_ON(tpa6130a2_client == NULL);
+	if (WARN_ON(!tpa6130a2_client))
+		return -EINVAL;
 	data = i2c_get_clientdata(tpa6130a2_client);
 
 	/* If powered off, return the cached value */
@@ -77,7 +79,8 @@
 	struct tpa6130a2_data *data;
 	int val = 0;
 
-	BUG_ON(tpa6130a2_client == NULL);
+	if (WARN_ON(!tpa6130a2_client))
+		return -EINVAL;
 	data = i2c_get_clientdata(tpa6130a2_client);
 
 	if (data->power_state) {
@@ -98,7 +101,8 @@
 {
 	struct tpa6130a2_data *data;
 
-	BUG_ON(tpa6130a2_client == NULL);
+	if (WARN_ON(!tpa6130a2_client))
+		return 0;
 	data = i2c_get_clientdata(tpa6130a2_client);
 
 	return data->regs[reg];
@@ -109,7 +113,8 @@
 	struct tpa6130a2_data *data;
 	int i, ret = 0;
 
-	BUG_ON(tpa6130a2_client == NULL);
+	if (WARN_ON(!tpa6130a2_client))
+		return -EINVAL;
 	data = i2c_get_clientdata(tpa6130a2_client);
 
 	for (i = 1; i < TPA6130A2_REG_VERSION; i++) {
@@ -127,7 +132,8 @@
 	u8	val;
 	int	ret = 0;
 
-	BUG_ON(tpa6130a2_client == NULL);
+	if (WARN_ON(!tpa6130a2_client))
+		return -EINVAL;
 	data = i2c_get_clientdata(tpa6130a2_client);
 
 	mutex_lock(&data->mutex);
@@ -193,7 +199,8 @@
 	unsigned int mask = (1 << fls(max)) - 1;
 	unsigned int invert = mc->invert;
 
-	BUG_ON(tpa6130a2_client == NULL);
+	if (WARN_ON(!tpa6130a2_client))
+		return -EINVAL;
 	data = i2c_get_clientdata(tpa6130a2_client);
 
 	mutex_lock(&data->mutex);
@@ -223,7 +230,8 @@
 	unsigned int val = (ucontrol->value.integer.value[0] & mask);
 	unsigned int val_reg;
 
-	BUG_ON(tpa6130a2_client == NULL);
+	if (WARN_ON(!tpa6130a2_client))
+		return -EINVAL;
 	data = i2c_get_clientdata(tpa6130a2_client);
 
 	if (invert)
@@ -364,30 +372,33 @@
 {
 	struct device *dev;
 	struct tpa6130a2_data *data;
-	struct tpa6130a2_platform_data *pdata;
+	struct tpa6130a2_platform_data *pdata = client->dev.platform_data;
+	struct device_node *np = client->dev.of_node;
 	const char *regulator;
 	int ret;
 
 	dev = &client->dev;
 
-	if (client->dev.platform_data == NULL) {
-		dev_err(dev, "Platform data not set\n");
-		dump_stack();
-		return -ENODEV;
-	}
-
 	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
 	if (data == NULL) {
 		dev_err(dev, "Can not allocate memory\n");
 		return -ENOMEM;
 	}
 
+	if (pdata) {
+		data->power_gpio = pdata->power_gpio;
+	} else if (np) {
+		data->power_gpio = of_get_named_gpio(np, "power-gpio", 0);
+	} else {
+		dev_err(dev, "Platform data not set\n");
+		dump_stack();
+		return -ENODEV;
+	}
+
 	tpa6130a2_client = client;
 
 	i2c_set_clientdata(tpa6130a2_client, data);
 
-	pdata = client->dev.platform_data;
-	data->power_gpio = pdata->power_gpio;
 	data->id = id->driver_data;
 
 	mutex_init(&data->mutex);
@@ -466,10 +477,20 @@
 };
 MODULE_DEVICE_TABLE(i2c, tpa6130a2_id);
 
+#if IS_ENABLED(CONFIG_OF)
+static const struct of_device_id tpa6130a2_of_match[] = {
+	{ .compatible = "ti,tpa6130a2", },
+	{ .compatible = "ti,tpa6140a2" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, tpa6130a2_of_match);
+#endif
+
 static struct i2c_driver tpa6130a2_i2c_driver = {
 	.driver = {
 		.name = "tpa6130a2",
 		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(tpa6130a2_of_match),
 	},
 	.probe = tpa6130a2_probe,
 	.remove = tpa6130a2_remove,
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 1e3884d..dfc51bb 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -46,13 +46,7 @@
 /* TWL4030 PMBR1 Register GPIO6 mux bits */
 #define TWL4030_GPIO6_PWM0_MUTE(value)	((value & 0x03) << 2)
 
-/* Shadow register used by the audio driver */
-#define TWL4030_REG_SW_SHADOW		0x4A
-#define TWL4030_CACHEREGNUM	(TWL4030_REG_SW_SHADOW + 1)
-
-/* TWL4030_REG_SW_SHADOW (0x4A) Fields */
-#define TWL4030_HFL_EN			0x01
-#define TWL4030_HFR_EN			0x02
+#define TWL4030_CACHEREGNUM	(TWL4030_REG_MISC_SET_2 + 1)
 
 /*
  * twl4030 register cache & default register settings
@@ -132,7 +126,6 @@
 	0x00, /* REG_VIBRA_PWM_SET	(0x47)	*/
 	0x00, /* REG_ANAMIC_GAIN	(0x48)	*/
 	0x00, /* REG_MISC_SET_2		(0x49)	*/
-	0x00, /* REG_SW_SHADOW		(0x4A)	- Shadow, non HW register */
 };
 
 /* codec private data */
@@ -198,42 +191,41 @@
 	int write_to_reg = 0;
 
 	twl4030_write_reg_cache(codec, reg, value);
-	if (likely(reg < TWL4030_REG_SW_SHADOW)) {
-		/* Decide if the given register can be written */
-		switch (reg) {
-		case TWL4030_REG_EAR_CTL:
-			if (twl4030->earpiece_enabled)
-				write_to_reg = 1;
-			break;
-		case TWL4030_REG_PREDL_CTL:
-			if (twl4030->predrivel_enabled)
-				write_to_reg = 1;
-			break;
-		case TWL4030_REG_PREDR_CTL:
-			if (twl4030->predriver_enabled)
-				write_to_reg = 1;
-			break;
-		case TWL4030_REG_PRECKL_CTL:
-			if (twl4030->carkitl_enabled)
-				write_to_reg = 1;
-			break;
-		case TWL4030_REG_PRECKR_CTL:
-			if (twl4030->carkitr_enabled)
-				write_to_reg = 1;
-			break;
-		case TWL4030_REG_HS_GAIN_SET:
-			if (twl4030->hsl_enabled || twl4030->hsr_enabled)
-				write_to_reg = 1;
-			break;
-		default:
-			/* All other register can be written */
+	/* Decide if the given register can be written */
+	switch (reg) {
+	case TWL4030_REG_EAR_CTL:
+		if (twl4030->earpiece_enabled)
 			write_to_reg = 1;
-			break;
-		}
-		if (write_to_reg)
-			return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
-						    value, reg);
+		break;
+	case TWL4030_REG_PREDL_CTL:
+		if (twl4030->predrivel_enabled)
+			write_to_reg = 1;
+		break;
+	case TWL4030_REG_PREDR_CTL:
+		if (twl4030->predriver_enabled)
+			write_to_reg = 1;
+		break;
+	case TWL4030_REG_PRECKL_CTL:
+		if (twl4030->carkitl_enabled)
+			write_to_reg = 1;
+		break;
+	case TWL4030_REG_PRECKR_CTL:
+		if (twl4030->carkitr_enabled)
+			write_to_reg = 1;
+		break;
+	case TWL4030_REG_HS_GAIN_SET:
+		if (twl4030->hsl_enabled || twl4030->hsr_enabled)
+			write_to_reg = 1;
+		break;
+	default:
+		/* All other register can be written */
+		write_to_reg = 1;
+		break;
 	}
+	if (write_to_reg)
+		return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
+					    value, reg);
+
 	return 0;
 }
 
@@ -532,7 +524,7 @@
 
 /* Handsfree Left virtual mute */
 static const struct snd_kcontrol_new twl4030_dapm_handsfreelmute_control =
-	SOC_DAPM_SINGLE("Switch", TWL4030_REG_SW_SHADOW, 0, 1, 0);
+	SOC_DAPM_SINGLE_VIRT("Switch", 1);
 
 /* Handsfree Right */
 static const char *twl4030_handsfreer_texts[] =
@@ -548,7 +540,7 @@
 
 /* Handsfree Right virtual mute */
 static const struct snd_kcontrol_new twl4030_dapm_handsfreermute_control =
-	SOC_DAPM_SINGLE("Switch", TWL4030_REG_SW_SHADOW, 1, 1, 0);
+	SOC_DAPM_SINGLE_VIRT("Switch", 1);
 
 /* Vibra */
 /* Vibra audio path selection */
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 3c79dbb..f2f4bcb 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -54,12 +54,7 @@
 #define TWL6040_OUTHF_0dB 0x03
 #define TWL6040_OUTHF_M52dB 0x1D
 
-/* Shadow register used by the driver */
-#define TWL6040_REG_SW_SHADOW	0x2F
-#define TWL6040_CACHEREGNUM	(TWL6040_REG_SW_SHADOW + 1)
-
-/* TWL6040_REG_SW_SHADOW (0x2F) fields */
-#define TWL6040_EAR_PATH_ENABLE	0x01
+#define TWL6040_CACHEREGNUM	(TWL6040_REG_STATUS + 1)
 
 struct twl6040_jack_data {
 	struct snd_soc_jack *jack;
@@ -135,8 +130,6 @@
 	0x00, /* REG_HFOTRIM	0x2C	*/
 	0x09, /* REG_ACCCTL	0x2D	*/
 	0x00, /* REG_STATUS	0x2E (ro) */
-
-	0x00, /* REG_SW_SHADOW	0x2F - Shadow, non HW register */
 };
 
 /* List of registers to be restored after power up */
@@ -220,12 +213,8 @@
 	if (reg >= TWL6040_CACHEREGNUM)
 		return -EIO;
 
-	if (likely(reg < TWL6040_REG_SW_SHADOW)) {
-		value = twl6040_reg_read(twl6040, reg);
-		twl6040_write_reg_cache(codec, reg, value);
-	} else {
-		value = twl6040_read_reg_cache(codec, reg);
-	}
+	value = twl6040_reg_read(twl6040, reg);
+	twl6040_write_reg_cache(codec, reg, value);
 
 	return value;
 }
@@ -246,7 +235,7 @@
 		return priv->dl2_unmuted;
 	default:
 		return 1;
-	};
+	}
 }
 
 /*
@@ -261,8 +250,7 @@
 		return -EIO;
 
 	twl6040_write_reg_cache(codec, reg, value);
-	if (likely(reg < TWL6040_REG_SW_SHADOW) &&
-	    twl6040_is_path_unmuted(codec, reg))
+	if (twl6040_is_path_unmuted(codec, reg))
 		return twl6040_reg_write(twl6040, reg, value);
 	else
 		return 0;
@@ -555,7 +543,7 @@
 	SOC_DAPM_ENUM("Route", twl6040_hf_enum[1]);
 
 static const struct snd_kcontrol_new ep_path_enable_control =
-	SOC_DAPM_SINGLE("Switch", TWL6040_REG_SW_SHADOW, 0, 1, 0);
+	SOC_DAPM_SINGLE_VIRT("Switch", 1);
 
 static const struct snd_kcontrol_new auxl_switch_control =
 	SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 6, 1, 0);
@@ -1100,7 +1088,7 @@
 		break;
 	default:
 		break;
-	};
+	}
 }
 
 static int twl6040_digital_mute(struct snd_soc_dai *dai, int mute)
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c
index d5ebcb0..71ce315 100644
--- a/sound/soc/codecs/wm0010.c
+++ b/sound/soc/codecs/wm0010.c
@@ -372,7 +372,8 @@
 	offset = 0;
 	dsp = inforec->dsp_target;
 	wm0010->boot_failed = false;
-	BUG_ON(!list_empty(&xfer_list));
+	if (WARN_ON(!list_empty(&xfer_list)))
+		return -EINVAL;
 	init_completion(&done);
 
 	/* First record should be INFO */
@@ -793,11 +794,11 @@
 		wm0010->max_spi_freq = 0;
 	} else {
 		for (i = 0; i < ARRAY_SIZE(pll_clock_map); i++)
-			if (freq >= pll_clock_map[i].max_sysclk)
+			if (freq >= pll_clock_map[i].max_sysclk) {
+				wm0010->max_spi_freq = pll_clock_map[i].max_pll_spi_speed;
+				wm0010->pll_clkctrl1 = pll_clock_map[i].pll_clkctrl1;
 				break;
-
-		wm0010->max_spi_freq = pll_clock_map[i].max_pll_spi_speed;
-		wm0010->pll_clkctrl1 = pll_clock_map[i].pll_clkctrl1;
+			}
 	}
 
 	return 0;
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index 7fefd76..8ae5027 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -137,7 +137,8 @@
 	unsigned long rate;
 	int ret;
 
-	BUG_ON(wm2000->anc_mode != ANC_OFF);
+	if (WARN_ON(wm2000->anc_mode != ANC_OFF))
+		return -EINVAL;
 
 	dev_dbg(&i2c->dev, "Beginning power up\n");
 
@@ -277,7 +278,8 @@
 {
 	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
 
-	BUG_ON(wm2000->anc_mode != ANC_ACTIVE);
+	if (WARN_ON(wm2000->anc_mode != ANC_ACTIVE))
+		return -EINVAL;
 
 	if (analogue) {
 		wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
@@ -315,7 +317,8 @@
 {
 	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
 
-	BUG_ON(wm2000->anc_mode != ANC_BYPASS);
+	if (WARN_ON(wm2000->anc_mode != ANC_BYPASS))
+		return -EINVAL;
 	
 	wm2000_write(i2c, WM2000_REG_SYS_CTL1, 0);
 
@@ -349,7 +352,8 @@
 {
 	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
 
-	BUG_ON(wm2000->anc_mode != ANC_ACTIVE);
+	if (WARN_ON(wm2000->anc_mode != ANC_ACTIVE))
+		return -EINVAL;
 
 	if (analogue) {
 		wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, 248 / 4);
@@ -392,7 +396,8 @@
 {
 	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
 
-	BUG_ON(wm2000->anc_mode != ANC_STANDBY);
+	if (WARN_ON(wm2000->anc_mode != ANC_STANDBY))
+		return -EINVAL;
 
 	wm2000_write(i2c, WM2000_REG_SYS_CTL1, 0);
 
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
index ac1745d..4cf91de 100644
--- a/sound/soc/codecs/wm5100.c
+++ b/sound/soc/codecs/wm5100.c
@@ -1972,7 +1972,8 @@
 {
 	struct wm5100_jack_mode *mode = &wm5100->pdata.jack_modes[the_mode];
 
-	BUG_ON(the_mode >= ARRAY_SIZE(wm5100->pdata.jack_modes));
+	if (WARN_ON(the_mode >= ARRAY_SIZE(wm5100->pdata.jack_modes)))
+		return;
 
 	gpio_set_value_cansleep(wm5100->pdata.hp_pol, mode->hp_pol);
 	regmap_update_bits(wm5100->regmap, WM5100_ACCESSORY_DETECT_MODE_1,
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index bbd6438..8c91be5 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -983,24 +983,36 @@
 	ARIZONA_MUX_ROUTES("ASRC2L", "ASRC2L"),
 	ARIZONA_MUX_ROUTES("ASRC2R", "ASRC2R"),
 
+	{ "AEC Loopback", "HPOUT1L", "OUT1L" },
+	{ "AEC Loopback", "HPOUT1R", "OUT1R" },
 	{ "HPOUT1L", NULL, "OUT1L" },
 	{ "HPOUT1R", NULL, "OUT1R" },
 
+	{ "AEC Loopback", "HPOUT2L", "OUT2L" },
+	{ "AEC Loopback", "HPOUT2R", "OUT2R" },
 	{ "HPOUT2L", NULL, "OUT2L" },
 	{ "HPOUT2R", NULL, "OUT2R" },
 
+	{ "AEC Loopback", "HPOUT3L", "OUT3L" },
+	{ "AEC Loopback", "HPOUT3R", "OUT3R" },
 	{ "HPOUT3L", NULL, "OUT3L" },
 	{ "HPOUT3R", NULL, "OUT3L" },
 
+	{ "AEC Loopback", "SPKOUTL", "OUT4L" },
 	{ "SPKOUTLN", NULL, "OUT4L" },
 	{ "SPKOUTLP", NULL, "OUT4L" },
 
+	{ "AEC Loopback", "SPKOUTR", "OUT4R" },
 	{ "SPKOUTRN", NULL, "OUT4R" },
 	{ "SPKOUTRP", NULL, "OUT4R" },
 
+	{ "AEC Loopback", "SPKDAT1L", "OUT5L" },
+	{ "AEC Loopback", "SPKDAT1R", "OUT5R" },
 	{ "SPKDAT1L", NULL, "OUT5L" },
 	{ "SPKDAT1R", NULL, "OUT5R" },
 
+	{ "AEC Loopback", "SPKDAT2L", "OUT6L" },
+	{ "AEC Loopback", "SPKDAT2R", "OUT6R" },
 	{ "SPKDAT2L", NULL, "OUT6L" },
 	{ "SPKDAT2R", NULL, "OUT6R" },
 
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index af1318d..a183dcf 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -274,7 +274,7 @@
 		break;
 
 	default:
-		BUG();
+		WARN(1, "Invalid shift %d\n", w->shift);
 		return -1;
 	}
 
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index d2a0928..48dc7d2 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -32,13 +32,6 @@
 
 #include "wm8400.h"
 
-/* Fake register for internal state */
-#define WM8400_INTDRIVBITS      (WM8400_REGISTER_COUNT + 1)
-#define WM8400_INMIXL_PWR			0
-#define WM8400_AINLMUX_PWR			1
-#define WM8400_INMIXR_PWR			2
-#define WM8400_AINRMUX_PWR			3
-
 static struct regulator_bulk_data power[] = {
 	{
 		.supply = "I2S1VDD",
@@ -74,32 +67,6 @@
 	int fll_in, fll_out;
 };
 
-static inline unsigned int wm8400_read(struct snd_soc_codec *codec,
-				       unsigned int reg)
-{
-	struct wm8400_priv *wm8400 = snd_soc_codec_get_drvdata(codec);
-
-	if (reg == WM8400_INTDRIVBITS)
-		return wm8400->fake_register;
-	else
-		return wm8400_reg_read(wm8400->wm8400, reg);
-}
-
-/*
- * write to the wm8400 register space
- */
-static int wm8400_write(struct snd_soc_codec *codec, unsigned int reg,
-	unsigned int value)
-{
-	struct wm8400_priv *wm8400 = snd_soc_codec_get_drvdata(codec);
-
-	if (reg == WM8400_INTDRIVBITS) {
-		wm8400->fake_register = value;
-		return 0;
-	} else
-		return wm8400_set_bits(wm8400->wm8400, reg, 0xffff, value);
-}
-
 static void wm8400_codec_reset(struct snd_soc_codec *codec)
 {
 	struct wm8400_priv *wm8400 = snd_soc_codec_get_drvdata(codec);
@@ -352,32 +319,6 @@
  * _DAPM_ Controls
  */
 
-static int inmixer_event (struct snd_soc_dapm_widget *w,
-	struct snd_kcontrol *kcontrol, int event)
-{
-	u16 reg, fakepower;
-
-	reg = snd_soc_read(w->codec, WM8400_POWER_MANAGEMENT_2);
-	fakepower = snd_soc_read(w->codec, WM8400_INTDRIVBITS);
-
-	if (fakepower & ((1 << WM8400_INMIXL_PWR) |
-		(1 << WM8400_AINLMUX_PWR))) {
-		reg |= WM8400_AINL_ENA;
-	} else {
-		reg &= ~WM8400_AINL_ENA;
-	}
-
-	if (fakepower & ((1 << WM8400_INMIXR_PWR) |
-		(1 << WM8400_AINRMUX_PWR))) {
-		reg |= WM8400_AINR_ENA;
-	} else {
-		reg &= ~WM8400_AINR_ENA;
-	}
-	snd_soc_write(w->codec, WM8400_POWER_MANAGEMENT_2, reg);
-
-	return 0;
-}
-
 static int outmixer_event (struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol * kcontrol, int event)
 {
@@ -658,27 +599,26 @@
 		   0, &wm8400_dapm_rin34_pga_controls[0],
 		   ARRAY_SIZE(wm8400_dapm_rin34_pga_controls)),
 
+SND_SOC_DAPM_SUPPLY("INL", WM8400_POWER_MANAGEMENT_2, WM8400_AINL_ENA_SHIFT,
+		    0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("INR", WM8400_POWER_MANAGEMENT_2, WM8400_AINR_ENA_SHIFT,
+		    0, NULL, 0),
+
 /* INMIXL */
-SND_SOC_DAPM_MIXER_E("INMIXL", WM8400_INTDRIVBITS, WM8400_INMIXL_PWR, 0,
+SND_SOC_DAPM_MIXER("INMIXL", SND_SOC_NOPM, 0, 0,
 	&wm8400_dapm_inmixl_controls[0],
-	ARRAY_SIZE(wm8400_dapm_inmixl_controls),
-	inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	ARRAY_SIZE(wm8400_dapm_inmixl_controls)),
 
 /* AINLMUX */
-SND_SOC_DAPM_MUX_E("AILNMUX", WM8400_INTDRIVBITS, WM8400_AINLMUX_PWR, 0,
-	&wm8400_dapm_ainlmux_controls, inmixer_event,
-	SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_MUX("AILNMUX", SND_SOC_NOPM, 0, 0, &wm8400_dapm_ainlmux_controls),
 
 /* INMIXR */
-SND_SOC_DAPM_MIXER_E("INMIXR", WM8400_INTDRIVBITS, WM8400_INMIXR_PWR, 0,
+SND_SOC_DAPM_MIXER("INMIXR", SND_SOC_NOPM, 0, 0,
 	&wm8400_dapm_inmixr_controls[0],
-	ARRAY_SIZE(wm8400_dapm_inmixr_controls),
-	inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	ARRAY_SIZE(wm8400_dapm_inmixr_controls)),
 
 /* AINRMUX */
-SND_SOC_DAPM_MUX_E("AIRNMUX", WM8400_INTDRIVBITS, WM8400_AINRMUX_PWR, 0,
-	&wm8400_dapm_ainrmux_controls, inmixer_event,
-	SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_MUX("AIRNMUX", SND_SOC_NOPM, 0, 0, &wm8400_dapm_ainrmux_controls),
 
 /* Output Side */
 /* DACs */
@@ -789,11 +729,13 @@
 	{"LIN34 PGA", "LIN3 Switch", "LIN3"},
 	{"LIN34 PGA", "LIN4 Switch", "LIN4/RXN"},
 	/* INMIXL */
+	{"INMIXL", NULL, "INL"},
 	{"INMIXL", "Record Left Volume", "LOMIX"},
 	{"INMIXL", "LIN2 Volume", "LIN2"},
 	{"INMIXL", "LINPGA12 Switch", "LIN12 PGA"},
 	{"INMIXL", "LINPGA34 Switch", "LIN34 PGA"},
 	/* AILNMUX */
+	{"AILNMUX", NULL, "INL"},
 	{"AILNMUX", "INMIXL Mix", "INMIXL"},
 	{"AILNMUX", "DIFFINL Mix", "LIN12 PGA"},
 	{"AILNMUX", "DIFFINL Mix", "LIN34 PGA"},
@@ -808,12 +750,14 @@
 	/* RIN34 PGA */
 	{"RIN34 PGA", "RIN3 Switch", "RIN3"},
 	{"RIN34 PGA", "RIN4 Switch", "RIN4/RXP"},
-	/* INMIXL */
+	/* INMIXR */
+	{"INMIXR", NULL, "INR"},
 	{"INMIXR", "Record Right Volume", "ROMIX"},
 	{"INMIXR", "RIN2 Volume", "RIN2"},
 	{"INMIXR", "RINPGA12 Switch", "RIN12 PGA"},
 	{"INMIXR", "RINPGA34 Switch", "RIN34 PGA"},
 	/* AIRNMUX */
+	{"AIRNMUX", NULL, "INR"},
 	{"AIRNMUX", "INMIXR Mix", "INMIXR"},
 	{"AIRNMUX", "DIFFINR Mix", "RIN12 PGA"},
 	{"AIRNMUX", "DIFFINR Mix", "RIN34 PGA"},
@@ -1365,9 +1309,12 @@
 		return -ENOMEM;
 
 	snd_soc_codec_set_drvdata(codec, priv);
-	codec->control_data = priv->wm8400 = wm8400;
+	priv->wm8400 = wm8400;
+	codec->control_data = wm8400->regmap;
 	priv->codec = codec;
 
+	snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
+
 	ret = devm_regulator_bulk_get(wm8400->dev,
 				 ARRAY_SIZE(power), &power[0]);
 	if (ret != 0) {
@@ -1414,8 +1361,6 @@
 	.remove =	wm8400_codec_remove,
 	.suspend =	wm8400_suspend,
 	.resume =	wm8400_resume,
-	.read = snd_soc_read,
-	.write = wm8400_write,
 	.set_bias_level = wm8400_set_bias_level,
 
 	.controls = wm8400_snd_controls,
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 5e9c40f..08a414b 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -736,7 +736,7 @@
 		break;
 
 	default:
-		BUG_ON("Unknown DAI driver ID\n");
+		WARN(1, "Unknown DAI driver ID\n");
 		return -EINVAL;
 	}
 
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index f31017e..942d58e 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -325,7 +325,8 @@
 	struct snd_soc_codec *codec = dai->codec;
 	struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec);
 
-	BUG_ON(dai->driver->id >= ARRAY_SIZE(wm8776->sysclk));
+	if (WARN_ON(dai->driver->id >= ARRAY_SIZE(wm8776->sysclk)))
+		return -EINVAL;
 
 	wm8776->sysclk[dai->driver->id] = freq;
 
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 7c8257c..734209e 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -279,7 +279,8 @@
 		break;
 
 	default:
-		BUG();
+		WARN(1, "Invalid event %d\n", event);
+		break;
 	}
 
 	return 0;
@@ -691,7 +692,8 @@
 	unsigned int K, Ndiv, Nmod, target;
 	unsigned int div;
 
-	BUG_ON(!Fout);
+	if (WARN_ON(!Fout))
+		return -EINVAL;
 
 	/* The FLL must run at 90-100MHz which is then scaled down to
 	 * the output value by FLLCLK_DIV. */
@@ -742,8 +744,9 @@
 	/* Move down to proper range now rounding is done */
 	fll_div->k = K / 10;
 
-	BUG_ON(target != Fout * (fll_div->fllclk_div << 2));
-	BUG_ON(!K && target != Fref * fll_div->fll_ratio * fll_div->n);
+	if (WARN_ON(target != Fout * (fll_div->fllclk_div << 2)) ||
+	    WARN_ON(!K && target != Fref * fll_div->fll_ratio * fll_div->n))
+		return -EINVAL;
 
 	return 0;
 }
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 4dfa8dc..3938fb1 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -658,7 +658,8 @@
 static int cp_event(struct snd_soc_dapm_widget *w,
 		    struct snd_kcontrol *kcontrol, int event)
 {
-	BUG_ON(event != SND_SOC_DAPM_POST_PMU);
+	if (WARN_ON(event != SND_SOC_DAPM_POST_PMU))
+		return -EINVAL;
 
 	/* Maximum startup time */
 	udelay(500);
@@ -740,7 +741,7 @@
 		dcs_r = 3;
 		break;
 	default:
-		BUG();
+		WARN(1, "Invalid reg %d\n", reg);
 		return -EINVAL;
 	}
 
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c
index b0710d8..b7488f1 100644
--- a/sound/soc/codecs/wm8958-dsp2.c
+++ b/sound/soc/codecs/wm8958-dsp2.c
@@ -348,7 +348,7 @@
 		aif = 1;
 		break;
 	default:
-		BUG();
+		WARN(1, "Invalid path %d\n", path);
 		return;
 	}
 
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 11d80f3..ac1ff99 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -1758,6 +1758,9 @@
 		 WM8962_EQL_B4_GAIN_SHIFT, 31, 0, eq_tlv),
 SOC_DOUBLE_R_TLV("EQ5 Volume", WM8962_EQ3, WM8962_EQ23,
 		 WM8962_EQL_B5_GAIN_SHIFT, 31, 0, eq_tlv),
+SND_SOC_BYTES("EQL Coefficients", WM8962_EQ4, 18),
+SND_SOC_BYTES("EQR Coefficients", WM8962_EQ24, 18),
+
 
 SOC_SINGLE("3D Switch", WM8962_THREED1, 0, 1, 0),
 SND_SOC_BYTES_MASK("3D Coefficients", WM8962_THREED1, 4, WM8962_THREED_ENA),
@@ -1775,6 +1778,11 @@
 SND_SOC_BYTES("HPF Coefficients", WM8962_LHPF2, 1),
 WM8962_DSP2_ENABLE("HD Bass Switch", WM8962_HDBASS_ENA_SHIFT),
 SND_SOC_BYTES("HD Bass Coefficients", WM8962_HDBASS_AI_1, 30),
+
+SOC_DOUBLE("ALC Switch", WM8962_ALC1, WM8962_ALCL_ENA_SHIFT,
+		WM8962_ALCR_ENA_SHIFT, 1, 0),
+SND_SOC_BYTES_MASK("ALC Coefficients", WM8962_ALC1, 4,
+		WM8962_ALCL_ENA_MASK | WM8962_ALCR_ENA_MASK),
 };
 
 static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = {
@@ -1845,7 +1853,7 @@
 		break;
 
 	default:
-		BUG();
+		WARN(1, "Invalid event %d\n", event);
 		return -EINVAL;
 	}
 
@@ -1937,7 +1945,7 @@
 		break;
 
 	default:
-		BUG();
+		WARN(1, "Invalid event %d\n", event);
 		return -EINVAL;
 	
 	}
@@ -1966,7 +1974,7 @@
 		reg = WM8962_SPKOUTL_VOLUME;
 		break;
 	default:
-		BUG();
+		WARN(1, "Invalid shift %d\n", w->shift);
 		return -EINVAL;
 	}
 
@@ -1974,7 +1982,7 @@
 	case SND_SOC_DAPM_POST_PMU:
 		return snd_soc_write(codec, reg, snd_soc_read(codec, reg));
 	default:
-		BUG();
+		WARN(1, "Invalid event %d\n", event);
 		return -EINVAL;
 	}
 }
@@ -1997,7 +2005,7 @@
 		break;
 
 	default:
-		BUG();
+		WARN(1, "Invalid event %d\n", event);
 		return -EINVAL;
 	}
 
@@ -3242,7 +3250,7 @@
 }
 #endif
 
-static void wm8962_set_gpio_mode(struct snd_soc_codec *codec, int gpio)
+static void wm8962_set_gpio_mode(struct wm8962_priv *wm8962, int gpio)
 {
 	int mask = 0;
 	int val = 0;
@@ -3263,8 +3271,8 @@
 	}
 
 	if (mask)
-		snd_soc_update_bits(codec, WM8962_ANALOGUE_CLOCKING1,
-				    mask, val);
+		regmap_update_bits(wm8962->regmap, WM8962_ANALOGUE_CLOCKING1,
+				   mask, val);
 }
 
 #ifdef CONFIG_GPIOLIB
@@ -3276,7 +3284,6 @@
 static int wm8962_gpio_request(struct gpio_chip *chip, unsigned offset)
 {
 	struct wm8962_priv *wm8962 = gpio_to_wm8962(chip);
-	struct snd_soc_codec *codec = wm8962->codec;
 
 	/* The WM8962 GPIOs aren't linearly numbered.  For simplicity
 	 * we export linear numbers and error out if the unsupported
@@ -3292,7 +3299,7 @@
 		return -EINVAL;
 	}
 
-	wm8962_set_gpio_mode(codec, offset + 1);
+	wm8962_set_gpio_mode(wm8962, offset + 1);
 
 	return 0;
 }
@@ -3376,8 +3383,7 @@
 {
 	int ret;
 	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
-	struct wm8962_pdata *pdata = &wm8962->pdata;
-	int i, trigger, irq_pol;
+	int i;
 	bool dmicclk, dmicdat;
 
 	wm8962->codec = codec;
@@ -3409,75 +3415,6 @@
 		}
 	}
 
-	/* SYSCLK defaults to on; make sure it is off so we can safely
-	 * write to registers if the device is declocked.
-	 */
-	snd_soc_update_bits(codec, WM8962_CLOCKING2, WM8962_SYSCLK_ENA, 0);
-
-	/* Ensure we have soft control over all registers */
-	snd_soc_update_bits(codec, WM8962_CLOCKING2,
-			    WM8962_CLKREG_OVD, WM8962_CLKREG_OVD);
-
-	/* Ensure that the oscillator and PLLs are disabled */
-	snd_soc_update_bits(codec, WM8962_PLL2,
-			    WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA,
-			    0);
-
-	/* Apply static configuration for GPIOs */
-	for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++)
-		if (pdata->gpio_init[i]) {
-			wm8962_set_gpio_mode(codec, i + 1);
-			snd_soc_write(codec, 0x200 + i,
-					pdata->gpio_init[i] & 0xffff);
-		}
-
-
-	/* Put the speakers into mono mode? */
-	if (pdata->spk_mono)
-		snd_soc_update_bits(codec, WM8962_CLASS_D_CONTROL_2,
-				WM8962_SPK_MONO_MASK, WM8962_SPK_MONO);
-
-	/* Micbias setup, detection enable and detection
-	 * threasholds. */
-	if (pdata->mic_cfg)
-		snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_4,
-				    WM8962_MICDET_ENA |
-				    WM8962_MICDET_THR_MASK |
-				    WM8962_MICSHORT_THR_MASK |
-				    WM8962_MICBIAS_LVL,
-				    pdata->mic_cfg);
-
-	/* Latch volume update bits */
-	snd_soc_update_bits(codec, WM8962_LEFT_INPUT_VOLUME,
-			    WM8962_IN_VU, WM8962_IN_VU);
-	snd_soc_update_bits(codec, WM8962_RIGHT_INPUT_VOLUME,
-			    WM8962_IN_VU, WM8962_IN_VU);
-	snd_soc_update_bits(codec, WM8962_LEFT_ADC_VOLUME,
-			    WM8962_ADC_VU, WM8962_ADC_VU);
-	snd_soc_update_bits(codec, WM8962_RIGHT_ADC_VOLUME,
-			    WM8962_ADC_VU, WM8962_ADC_VU);
-	snd_soc_update_bits(codec, WM8962_LEFT_DAC_VOLUME,
-			    WM8962_DAC_VU, WM8962_DAC_VU);
-	snd_soc_update_bits(codec, WM8962_RIGHT_DAC_VOLUME,
-			    WM8962_DAC_VU, WM8962_DAC_VU);
-	snd_soc_update_bits(codec, WM8962_SPKOUTL_VOLUME,
-			    WM8962_SPKOUT_VU, WM8962_SPKOUT_VU);
-	snd_soc_update_bits(codec, WM8962_SPKOUTR_VOLUME,
-			    WM8962_SPKOUT_VU, WM8962_SPKOUT_VU);
-	snd_soc_update_bits(codec, WM8962_HPOUTL_VOLUME,
-			    WM8962_HPOUT_VU, WM8962_HPOUT_VU);
-	snd_soc_update_bits(codec, WM8962_HPOUTR_VOLUME,
-			    WM8962_HPOUT_VU, WM8962_HPOUT_VU);
-
-	/* Stereo control for EQ */
-	snd_soc_update_bits(codec, WM8962_EQ1, WM8962_EQ_SHARED_COEFF, 0);
-
-	/* Don't debouce interrupts so we don't need SYSCLK */
-	snd_soc_update_bits(codec, WM8962_IRQ_DEBOUNCE,
-			    WM8962_FLL_LOCK_DB | WM8962_PLL3_LOCK_DB |
-			    WM8962_PLL2_LOCK_DB | WM8962_TEMP_SHUT_DB,
-			    0);
-
 	wm8962_add_widgets(codec);
 
 	/* Save boards having to disable DMIC when not in use */
@@ -3506,36 +3443,6 @@
 	wm8962_init_beep(codec);
 	wm8962_init_gpio(codec);
 
-	if (wm8962->irq) {
-		if (pdata->irq_active_low) {
-			trigger = IRQF_TRIGGER_LOW;
-			irq_pol = WM8962_IRQ_POL;
-		} else {
-			trigger = IRQF_TRIGGER_HIGH;
-			irq_pol = 0;
-		}
-
-		snd_soc_update_bits(codec, WM8962_INTERRUPT_CONTROL,
-				    WM8962_IRQ_POL, irq_pol);
-
-		ret = request_threaded_irq(wm8962->irq, NULL, wm8962_irq,
-					   trigger | IRQF_ONESHOT,
-					   "wm8962", codec->dev);
-		if (ret != 0) {
-			dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
-				wm8962->irq, ret);
-			wm8962->irq = 0;
-			/* Non-fatal */
-		} else {
-			/* Enable some IRQs by default */
-			snd_soc_update_bits(codec,
-					    WM8962_INTERRUPT_STATUS_2_MASK,
-					    WM8962_FLL_LOCK_EINT |
-					    WM8962_TEMP_SHUT_EINT |
-					    WM8962_FIFOS_ERR_EINT, 0);
-		}
-	}
-
 	return 0;
 }
 
@@ -3544,9 +3451,6 @@
 	struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
 	int i;
 
-	if (wm8962->irq)
-		free_irq(wm8962->irq, codec);
-
 	cancel_delayed_work_sync(&wm8962->mic_work);
 
 	wm8962_free_gpio(codec);
@@ -3619,7 +3523,7 @@
 	struct wm8962_pdata *pdata = dev_get_platdata(&i2c->dev);
 	struct wm8962_priv *wm8962;
 	unsigned int reg;
-	int ret, i;
+	int ret, i, irq_pol, trigger;
 
 	wm8962 = devm_kzalloc(&i2c->dev, sizeof(struct wm8962_priv),
 			      GFP_KERNEL);
@@ -3704,6 +3608,77 @@
 		goto err_enable;
 	}
 
+	/* SYSCLK defaults to on; make sure it is off so we can safely
+	 * write to registers if the device is declocked.
+	 */
+	regmap_update_bits(wm8962->regmap, WM8962_CLOCKING2,
+			   WM8962_SYSCLK_ENA, 0);
+
+	/* Ensure we have soft control over all registers */
+	regmap_update_bits(wm8962->regmap, WM8962_CLOCKING2,
+			   WM8962_CLKREG_OVD, WM8962_CLKREG_OVD);
+
+	/* Ensure that the oscillator and PLLs are disabled */
+	regmap_update_bits(wm8962->regmap, WM8962_PLL2,
+			   WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA,
+			   0);
+
+	/* Apply static configuration for GPIOs */
+	for (i = 0; i < ARRAY_SIZE(wm8962->pdata.gpio_init); i++)
+		if (wm8962->pdata.gpio_init[i]) {
+			wm8962_set_gpio_mode(wm8962, i + 1);
+			regmap_write(wm8962->regmap, 0x200 + i,
+				     wm8962->pdata.gpio_init[i] & 0xffff);
+		}
+
+
+	/* Put the speakers into mono mode? */
+	if (wm8962->pdata.spk_mono)
+		regmap_update_bits(wm8962->regmap, WM8962_CLASS_D_CONTROL_2,
+				   WM8962_SPK_MONO_MASK, WM8962_SPK_MONO);
+
+	/* Micbias setup, detection enable and detection
+	 * threasholds. */
+	if (wm8962->pdata.mic_cfg)
+		regmap_update_bits(wm8962->regmap, WM8962_ADDITIONAL_CONTROL_4,
+				   WM8962_MICDET_ENA |
+				   WM8962_MICDET_THR_MASK |
+				   WM8962_MICSHORT_THR_MASK |
+				   WM8962_MICBIAS_LVL,
+				   wm8962->pdata.mic_cfg);
+
+	/* Latch volume update bits */
+	regmap_update_bits(wm8962->regmap, WM8962_LEFT_INPUT_VOLUME,
+			   WM8962_IN_VU, WM8962_IN_VU);
+	regmap_update_bits(wm8962->regmap, WM8962_RIGHT_INPUT_VOLUME,
+			   WM8962_IN_VU, WM8962_IN_VU);
+	regmap_update_bits(wm8962->regmap, WM8962_LEFT_ADC_VOLUME,
+			   WM8962_ADC_VU, WM8962_ADC_VU);
+	regmap_update_bits(wm8962->regmap, WM8962_RIGHT_ADC_VOLUME,
+			   WM8962_ADC_VU, WM8962_ADC_VU);
+	regmap_update_bits(wm8962->regmap, WM8962_LEFT_DAC_VOLUME,
+			   WM8962_DAC_VU, WM8962_DAC_VU);
+	regmap_update_bits(wm8962->regmap, WM8962_RIGHT_DAC_VOLUME,
+			   WM8962_DAC_VU, WM8962_DAC_VU);
+	regmap_update_bits(wm8962->regmap, WM8962_SPKOUTL_VOLUME,
+			   WM8962_SPKOUT_VU, WM8962_SPKOUT_VU);
+	regmap_update_bits(wm8962->regmap, WM8962_SPKOUTR_VOLUME,
+			   WM8962_SPKOUT_VU, WM8962_SPKOUT_VU);
+	regmap_update_bits(wm8962->regmap, WM8962_HPOUTL_VOLUME,
+			   WM8962_HPOUT_VU, WM8962_HPOUT_VU);
+	regmap_update_bits(wm8962->regmap, WM8962_HPOUTR_VOLUME,
+			   WM8962_HPOUT_VU, WM8962_HPOUT_VU);
+
+	/* Stereo control for EQ */
+	regmap_update_bits(wm8962->regmap, WM8962_EQ1,
+			   WM8962_EQ_SHARED_COEFF, 0);
+
+	/* Don't debouce interrupts so we don't need SYSCLK */
+	regmap_update_bits(wm8962->regmap, WM8962_IRQ_DEBOUNCE,
+			   WM8962_FLL_LOCK_DB | WM8962_PLL3_LOCK_DB |
+			   WM8962_PLL2_LOCK_DB | WM8962_TEMP_SHUT_DB,
+			   0);
+
 	if (wm8962->pdata.in4_dc_measure) {
 		ret = regmap_register_patch(wm8962->regmap,
 					    wm8962_dc_measure,
@@ -3714,6 +3689,37 @@
 				ret);
 	}
 
+	if (wm8962->irq) {
+		if (wm8962->pdata.irq_active_low) {
+			trigger = IRQF_TRIGGER_LOW;
+			irq_pol = WM8962_IRQ_POL;
+		} else {
+			trigger = IRQF_TRIGGER_HIGH;
+			irq_pol = 0;
+		}
+
+		regmap_update_bits(wm8962->regmap, WM8962_INTERRUPT_CONTROL,
+				   WM8962_IRQ_POL, irq_pol);
+
+		ret = devm_request_threaded_irq(&i2c->dev, wm8962->irq, NULL,
+						wm8962_irq,
+						trigger | IRQF_ONESHOT,
+						"wm8962", &i2c->dev);
+		if (ret != 0) {
+			dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
+				wm8962->irq, ret);
+			wm8962->irq = 0;
+			/* Non-fatal */
+		} else {
+			/* Enable some IRQs by default */
+			regmap_update_bits(wm8962->regmap,
+					   WM8962_INTERRUPT_STATUS_2_MASK,
+					   WM8962_FLL_LOCK_EINT |
+					   WM8962_TEMP_SHUT_EINT |
+					   WM8962_FIFOS_ERR_EINT, 0);
+		}
+	}
+
 	pm_runtime_enable(&i2c->dev);
 	pm_request_idle(&i2c->dev);
 
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index 46fe83d..1a7655b 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -438,6 +438,8 @@
 	struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
 	int block = wm8996_get_retune_mobile_block(kcontrol->id.name);
 
+	if (block < 0)
+		return block;
 	ucontrol->value.enumerated.item[0] = wm8996->retune_mobile_cfg[block];
 
 	return 0;
@@ -608,7 +610,7 @@
 		wm8996_bg_disable(codec);
 		break;
 	default:
-		BUG();
+		WARN(1, "Invalid event %d\n", event);
 		ret = -EINVAL;
 	}
 
@@ -625,7 +627,7 @@
 		msleep(5);
 		break;
 	default:
-		BUG();
+		WARN(1, "Invalid event %d\n", event);
 		ret = -EINVAL;
 	}
 
@@ -646,7 +648,7 @@
 		wm8996->hpout_pending |= w->shift;
 		break;
 	default:
-		BUG();
+		WARN(1, "Invalid event %d\n", event);
 		return -EINVAL;
 	}
 
@@ -767,7 +769,7 @@
 		wm8996->dcs_pending |= 1 << w->shift;
 		break;
 	default:
-		BUG();
+		WARN(1, "Invalid event %d\n", event);
 		return -EINVAL;
 	}
 
@@ -1656,7 +1658,7 @@
 		lrclk_rx_reg = WM8996_AIF2_RX_LRCLK_2;
 		break;
 	default:
-		BUG();
+		WARN(1, "Invalid dai id %d\n", dai->id);
 		return -EINVAL;
 	}
 
@@ -1768,7 +1770,7 @@
 		dsp_shift = WM8996_DSP2_DIV_SHIFT;
 		break;
 	default:
-		BUG();
+		WARN(1, "Invalid dai id %d\n", dai->id);
 		return -EINVAL;
 	}
 
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index a53e175..acea892 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -221,7 +221,8 @@
 	struct snd_soc_codec *codec = w->codec;
 	u16 status, rate;
 
-	BUG_ON(event != SND_SOC_DAPM_PRE_PMD);
+	if (WARN_ON(event != SND_SOC_DAPM_PRE_PMD))
+		return -EINVAL;
 
 	/* Gracefully shut down the voice interface. */
 	status = ac97_read(codec, AC97_EXTENDED_MID) | 0x1000;
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index b38f350..46ec0e9 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -341,6 +341,8 @@
 static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *region,
 					  unsigned int offset)
 {
+	if (WARN_ON(!region))
+		return offset;
 	switch (region->type) {
 	case WMFW_ADSP1_PM:
 		return region->base + (offset * 3);
@@ -353,7 +355,7 @@
 	case WMFW_ADSP1_ZM:
 		return region->base + (offset * 2);
 	default:
-		WARN_ON(NULL != "Unknown memory region type");
+		WARN(1, "Unknown memory region type");
 		return offset;
 	}
 }
@@ -396,11 +398,12 @@
 	ret = regmap_raw_write(adsp->regmap, reg, scratch,
 			       ctl->len);
 	if (ret) {
-		adsp_err(adsp, "Failed to write %zu bytes to %x\n",
-			 ctl->len, reg);
+		adsp_err(adsp, "Failed to write %zu bytes to %x: %d\n",
+			 ctl->len, reg, ret);
 		kfree(scratch);
 		return ret;
 	}
+	adsp_dbg(adsp, "Wrote %zu bytes to %x\n", ctl->len, reg);
 
 	kfree(scratch);
 
@@ -450,11 +453,12 @@
 
 	ret = regmap_raw_read(adsp->regmap, reg, scratch, ctl->len);
 	if (ret) {
-		adsp_err(adsp, "Failed to read %zu bytes from %x\n",
-			 ctl->len, reg);
+		adsp_err(adsp, "Failed to read %zu bytes from %x: %d\n",
+			 ctl->len, reg, ret);
 		kfree(scratch);
 		return ret;
 	}
+	adsp_dbg(adsp, "Read %zu bytes from %x\n", ctl->len, reg);
 
 	memcpy(buf, scratch, ctl->len);
 	kfree(scratch);
@@ -568,6 +572,7 @@
 			 file, header->ver);
 		goto out_fw;
 	}
+	adsp_info(dsp, "Firmware version: %d\n", header->ver);
 
 	if (header->core != dsp->type) {
 		adsp_err(dsp, "%s: invalid core %d != %d\n",
@@ -602,7 +607,7 @@
 		break;
 
 	default:
-		BUG_ON(NULL == "Unknown DSP type");
+		WARN(1, "Unknown DSP type");
 		goto out_fw;
 	}
 
@@ -642,27 +647,22 @@
 			reg = offset;
 			break;
 		case WMFW_ADSP1_PM:
-			BUG_ON(!mem);
 			region_name = "PM";
 			reg = wm_adsp_region_to_reg(mem, offset);
 			break;
 		case WMFW_ADSP1_DM:
-			BUG_ON(!mem);
 			region_name = "DM";
 			reg = wm_adsp_region_to_reg(mem, offset);
 			break;
 		case WMFW_ADSP2_XM:
-			BUG_ON(!mem);
 			region_name = "XM";
 			reg = wm_adsp_region_to_reg(mem, offset);
 			break;
 		case WMFW_ADSP2_YM:
-			BUG_ON(!mem);
 			region_name = "YM";
 			reg = wm_adsp_region_to_reg(mem, offset);
 			break;
 		case WMFW_ADSP1_ZM:
-			BUG_ON(!mem);
 			region_name = "ZM";
 			reg = wm_adsp_region_to_reg(mem, offset);
 			break;
@@ -689,7 +689,8 @@
 						&buf_list);
 			if (!buf) {
 				adsp_err(dsp, "Out of memory\n");
-				return -ENOMEM;
+				ret = -ENOMEM;
+				goto out_fw;
 			}
 
 			ret = regmap_raw_write_async(regmap, reg, buf->buf,
@@ -901,10 +902,8 @@
 		break;
 	}
 
-	if (mem == NULL) {
-		BUG_ON(mem != NULL);
+	if (WARN_ON(!mem))
 		return -EINVAL;
-	}
 
 	switch (dsp->type) {
 	case WMFW_ADSP1:
@@ -998,7 +997,7 @@
 		break;
 
 	default:
-		BUG_ON(NULL == "Unknown DSP type");
+		WARN(1, "Unknown DSP type");
 		return -EINVAL;
 	}
 
@@ -1062,6 +1061,7 @@
 			if (i + 1 < algs) {
 				region->len = be32_to_cpu(adsp1_alg[i + 1].dm);
 				region->len -= be32_to_cpu(adsp1_alg[i].dm);
+				region->len *= 4;
 				wm_adsp_create_control(dsp, region);
 			} else {
 				adsp_warn(dsp, "Missing length info for region DM with ID %x\n",
@@ -1079,6 +1079,7 @@
 			if (i + 1 < algs) {
 				region->len = be32_to_cpu(adsp1_alg[i + 1].zm);
 				region->len -= be32_to_cpu(adsp1_alg[i].zm);
+				region->len *= 4;
 				wm_adsp_create_control(dsp, region);
 			} else {
 				adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
@@ -1108,6 +1109,7 @@
 			if (i + 1 < algs) {
 				region->len = be32_to_cpu(adsp2_alg[i + 1].xm);
 				region->len -= be32_to_cpu(adsp2_alg[i].xm);
+				region->len *= 4;
 				wm_adsp_create_control(dsp, region);
 			} else {
 				adsp_warn(dsp, "Missing length info for region XM with ID %x\n",
@@ -1125,6 +1127,7 @@
 			if (i + 1 < algs) {
 				region->len = be32_to_cpu(adsp2_alg[i + 1].ym);
 				region->len -= be32_to_cpu(adsp2_alg[i].ym);
+				region->len *= 4;
 				wm_adsp_create_control(dsp, region);
 			} else {
 				adsp_warn(dsp, "Missing length info for region YM with ID %x\n",
@@ -1142,6 +1145,7 @@
 			if (i + 1 < algs) {
 				region->len = be32_to_cpu(adsp2_alg[i + 1].zm);
 				region->len -= be32_to_cpu(adsp2_alg[i].zm);
+				region->len *= 4;
 				wm_adsp_create_control(dsp, region);
 			} else {
 				adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
@@ -1313,8 +1317,8 @@
 						     le32_to_cpu(blk->len));
 			if (ret != 0) {
 				adsp_err(dsp,
-					"%s.%d: Failed to write to %x in %s\n",
-					file, blocks, reg, region_name);
+					"%s.%d: Failed to write to %x in %s: %d\n",
+					file, blocks, reg, region_name, ret);
 			}
 		}
 
@@ -1358,6 +1362,7 @@
 	struct snd_soc_codec *codec = w->codec;
 	struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
 	struct wm_adsp *dsp = &dsps[w->shift];
+	struct wm_adsp_alg_region *alg_region;
 	struct wm_coeff_ctl *ctl;
 	int ret;
 	int val;
@@ -1435,6 +1440,14 @@
 
 		list_for_each_entry(ctl, &dsp->ctl_list, list)
 			ctl->enabled = 0;
+
+		while (!list_empty(&dsp->alg_regions)) {
+			alg_region = list_first_entry(&dsp->alg_regions,
+						      struct wm_adsp_alg_region,
+						      list);
+			list_del(&alg_region->list);
+			kfree(alg_region);
+		}
 		break;
 
 	default:
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 8b50e59..b371066 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -530,6 +530,7 @@
 				hubs->hp_startup_mode);
 			break;
 		}
+		break;
 
 	case SND_SOC_DAPM_PRE_PMD:
 		snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1,
@@ -610,7 +611,7 @@
 		break;
 
 	default:
-		BUG();
+		WARN(1, "Invalid event %d\n", event);
 		break;
 	}
 
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index c82f89c..95970f5 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -1,9 +1,10 @@
 config SND_DAVINCI_SOC
-	tristate "SoC Audio for the TI DAVINCI chip"
-	depends on ARCH_DAVINCI
+	tristate "SoC Audio for the TI DAVINCI or AM33XX chip"
+	depends on ARCH_DAVINCI || SOC_AM33XX
 	help
+	  Platform driver for daVinci or AM33xx
 	  Say Y or M if you want to add support for codecs attached to
-	  the DAVINCI AC97 or I2S interface. You will also need
+	  the DAVINCI AC97, I2S, or McASP interface. You will also need
 	  to select the audio interfaces to support below.
 
 config SND_DAVINCI_SOC_I2S
@@ -15,6 +16,17 @@
 config SND_DAVINCI_SOC_VCIF
 	tristate
 
+config SND_AM33XX_SOC_EVM
+	tristate "SoC Audio for the AM33XX chip based boards"
+	depends on SND_DAVINCI_SOC && SOC_AM33XX
+	select SND_SOC_TLV320AIC3X
+	select SND_DAVINCI_SOC_MCASP
+	help
+	  Say Y or M if you want to add support for SoC audio on AM33XX
+	  boards using McASP and TLV320AIC3X codec. For example AM335X-EVM,
+	  AM335X-EVMSK, and BeagelBone with AudioCape boards have this
+	  setup.
+
 config SND_DAVINCI_SOC_EVM
 	tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM"
 	depends on SND_DAVINCI_SOC
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile
index a396ab6..bc81e79 100644
--- a/sound/soc/davinci/Makefile
+++ b/sound/soc/davinci/Makefile
@@ -13,6 +13,7 @@
 snd-soc-evm-objs := davinci-evm.o
 
 obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o
+obj-$(CONFIG_SND_AM33XX_SOC_EVM) += snd-soc-evm.o
 obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o
 obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o
 obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index fd7c45b..623eb5e 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -16,6 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/platform_data/edma.h>
 #include <linux/i2c.h>
+#include <linux/of_platform.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
@@ -23,10 +24,16 @@
 #include <asm/dma.h>
 #include <asm/mach-types.h>
 
+#include <linux/edma.h>
+
 #include "davinci-pcm.h"
 #include "davinci-i2s.h"
 #include "davinci-mcasp.h"
 
+struct snd_soc_card_drvdata_davinci {
+	unsigned sysclk;
+};
+
 #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
 		SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
 static int evm_hw_params(struct snd_pcm_substream *substream,
@@ -35,27 +42,11 @@
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_card *soc_card = codec->card;
 	int ret = 0;
-	unsigned sysclk;
-
-	/* ASP1 on DM355 EVM is clocked by an external oscillator */
-	if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm() ||
-	    machine_is_davinci_dm365_evm())
-		sysclk = 27000000;
-
-	/* ASP0 in DM6446 EVM is clocked by U55, as configured by
-	 * board-dm644x-evm.c using GPIOs from U18.  There are six
-	 * options; here we "know" we use a 48 KHz sample rate.
-	 */
-	else if (machine_is_davinci_evm())
-		sysclk = 12288000;
-
-	else if (machine_is_davinci_da830_evm() ||
-				machine_is_davinci_da850_evm())
-		sysclk = 24576000;
-
-	else
-		return -EINVAL;
+	unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *)
+			   snd_soc_card_get_drvdata(soc_card))->sysclk;
 
 	/* set codec DAI configuration */
 	ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT);
@@ -133,13 +124,22 @@
 {
 	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct device_node *np = codec->card->dev->of_node;
+	int ret;
 
 	/* Add davinci-evm specific widgets */
 	snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets,
 				  ARRAY_SIZE(aic3x_dapm_widgets));
 
-	/* Set up davinci-evm specific audio path audio_map */
-	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
+	if (np) {
+		ret = snd_soc_of_parse_audio_routing(codec->card,
+							"ti,audio-routing");
+		if (ret)
+			return ret;
+	} else {
+		/* Set up davinci-evm specific audio path audio_map */
+		snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
+	}
 
 	/* not connected */
 	snd_soc_dapm_disable_pin(dapm, "MONO_LOUT");
@@ -243,35 +243,65 @@
 };
 
 /* davinci dm6446 evm audio machine driver */
+/*
+ * ASP0 in DM6446 EVM is clocked by U55, as configured by
+ * board-dm644x-evm.c using GPIOs from U18.  There are six
+ * options; here we "know" we use a 48 KHz sample rate.
+ */
+static struct snd_soc_card_drvdata_davinci dm6446_snd_soc_card_drvdata = {
+	.sysclk = 12288000,
+};
+
 static struct snd_soc_card dm6446_snd_soc_card_evm = {
 	.name = "DaVinci DM6446 EVM",
 	.owner = THIS_MODULE,
 	.dai_link = &dm6446_evm_dai,
 	.num_links = 1,
+	.drvdata = &dm6446_snd_soc_card_drvdata,
 };
 
 /* davinci dm355 evm audio machine driver */
+/* ASP1 on DM355 EVM is clocked by an external oscillator */
+static struct snd_soc_card_drvdata_davinci dm355_snd_soc_card_drvdata = {
+	.sysclk = 27000000,
+};
+
 static struct snd_soc_card dm355_snd_soc_card_evm = {
 	.name = "DaVinci DM355 EVM",
 	.owner = THIS_MODULE,
 	.dai_link = &dm355_evm_dai,
 	.num_links = 1,
+	.drvdata = &dm355_snd_soc_card_drvdata,
 };
 
 /* davinci dm365 evm audio machine driver */
+static struct snd_soc_card_drvdata_davinci dm365_snd_soc_card_drvdata = {
+	.sysclk = 27000000,
+};
+
 static struct snd_soc_card dm365_snd_soc_card_evm = {
 	.name = "DaVinci DM365 EVM",
 	.owner = THIS_MODULE,
 	.dai_link = &dm365_evm_dai,
 	.num_links = 1,
+	.drvdata = &dm365_snd_soc_card_drvdata,
 };
 
 /* davinci dm6467 evm audio machine driver */
+static struct snd_soc_card_drvdata_davinci dm6467_snd_soc_card_drvdata = {
+	.sysclk = 27000000,
+};
+
 static struct snd_soc_card dm6467_snd_soc_card_evm = {
 	.name = "DaVinci DM6467 EVM",
 	.owner = THIS_MODULE,
 	.dai_link = dm6467_evm_dai,
 	.num_links = ARRAY_SIZE(dm6467_evm_dai),
+	.drvdata = &dm6467_snd_soc_card_drvdata,
+};
+
+static struct snd_soc_card_drvdata_davinci da830_snd_soc_card_drvdata = {
+	.sysclk = 24576000,
 };
 
 static struct snd_soc_card da830_snd_soc_card = {
@@ -279,6 +309,11 @@
 	.owner = THIS_MODULE,
 	.dai_link = &da830_evm_dai,
 	.num_links = 1,
+	.drvdata = &da830_snd_soc_card_drvdata,
+};
+
+static struct snd_soc_card_drvdata_davinci da850_snd_soc_card_drvdata = {
+	.sysclk = 24576000,
 };
 
 static struct snd_soc_card da850_snd_soc_card = {
@@ -286,8 +321,101 @@
 	.owner = THIS_MODULE,
 	.dai_link = &da850_evm_dai,
 	.num_links = 1,
+	.drvdata = &da850_snd_soc_card_drvdata,
 };
 
+#if defined(CONFIG_OF)
+
+/*
+ * The struct is used as place holder. It will be completely
+ * filled with data from dt node.
+ */
+static struct snd_soc_dai_link evm_dai_tlv320aic3x = {
+	.name		= "TLV320AIC3X",
+	.stream_name	= "AIC3X",
+	.codec_dai_name	= "tlv320aic3x-hifi",
+	.ops            = &evm_ops,
+	.init           = evm_aic3x_init,
+};
+
+static const struct of_device_id davinci_evm_dt_ids[] = {
+	{
+		.compatible = "ti,da830-evm-audio",
+		.data = (void *) &evm_dai_tlv320aic3x,
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, davinci_evm_dt_ids);
+
+/* davinci evm audio machine driver */
+static struct snd_soc_card evm_soc_card = {
+	.owner = THIS_MODULE,
+	.num_links = 1,
+};
+
+static int davinci_evm_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	const struct of_device_id *match =
+		of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev);
+	struct snd_soc_dai_link *dai = (struct snd_soc_dai_link *) match->data;
+	struct snd_soc_card_drvdata_davinci *drvdata = NULL;
+	int ret = 0;
+
+	evm_soc_card.dai_link = dai;
+
+	dai->codec_of_node = of_parse_phandle(np, "ti,audio-codec", 0);
+	if (!dai->codec_of_node)
+		return -EINVAL;
+
+	dai->cpu_of_node = of_parse_phandle(np, "ti,mcasp-controller", 0);
+	if (!dai->cpu_of_node)
+		return -EINVAL;
+
+	dai->platform_of_node = dai->cpu_of_node;
+
+	evm_soc_card.dev = &pdev->dev;
+	ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model");
+	if (ret)
+		return ret;
+
+	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+
+	ret = of_property_read_u32(np, "ti,codec-clock-rate", &drvdata->sysclk);
+	if (ret < 0)
+		return -EINVAL;
+
+	snd_soc_card_set_drvdata(&evm_soc_card, drvdata);
+	ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card);
+
+	if (ret)
+		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+
+	return ret;
+}
+
+static int davinci_evm_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_card(card);
+
+	return 0;
+}
+
+static struct platform_driver davinci_evm_driver = {
+	.probe		= davinci_evm_probe,
+	.remove		= davinci_evm_remove,
+	.driver		= {
+		.name	= "davinci_evm",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(davinci_evm_dt_ids),
+	},
+};
+#endif
+
 static struct platform_device *evm_snd_device;
 
 static int __init evm_init(void)
@@ -296,6 +424,15 @@
 	int index;
 	int ret;
 
+	/*
+	 * If dtb is there, the devices will be created dynamically.
+	 * Only register platfrom driver structure.
+	 */
+#if defined(CONFIG_OF)
+	if (of_have_populated_dt())
+		return platform_driver_register(&davinci_evm_driver);
+#endif
+
 	if (machine_is_davinci_evm()) {
 		evm_snd_dev_data = &dm6446_snd_soc_card_evm;
 		index = 0;
@@ -331,6 +468,13 @@
 
 static void __exit evm_exit(void)
 {
+#if defined(CONFIG_OF)
+	if (of_have_populated_dt()) {
+		platform_driver_unregister(&davinci_evm_driver);
+		return;
+	}
+#endif
+
 	platform_device_unregister(evm_snd_device);
 }
 
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 32ddb7f..71e14bb3 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -1001,18 +1001,40 @@
 	.name		= "davinci-mcasp",
 };
 
+/* Some HW specific values and defaults. The rest is filled in from DT. */
+static struct snd_platform_data dm646x_mcasp_pdata = {
+	.tx_dma_offset = 0x400,
+	.rx_dma_offset = 0x400,
+	.asp_chan_q = EVENTQ_0,
+	.version = MCASP_VERSION_1,
+};
+
+static struct snd_platform_data da830_mcasp_pdata = {
+	.tx_dma_offset = 0x2000,
+	.rx_dma_offset = 0x2000,
+	.asp_chan_q = EVENTQ_0,
+	.version = MCASP_VERSION_2,
+};
+
+static struct snd_platform_data omap2_mcasp_pdata = {
+	.tx_dma_offset = 0,
+	.rx_dma_offset = 0,
+	.asp_chan_q = EVENTQ_0,
+	.version = MCASP_VERSION_3,
+};
+
 static const struct of_device_id mcasp_dt_ids[] = {
 	{
 		.compatible = "ti,dm646x-mcasp-audio",
-		.data = (void *)MCASP_VERSION_1,
+		.data = &dm646x_mcasp_pdata,
 	},
 	{
 		.compatible = "ti,da830-mcasp-audio",
-		.data = (void *)MCASP_VERSION_2,
+		.data = &da830_mcasp_pdata,
 	},
 	{
-		.compatible = "ti,omap2-mcasp-audio",
-		.data = (void *)MCASP_VERSION_3,
+		.compatible = "ti,am33xx-mcasp-audio",
+		.data = &omap2_mcasp_pdata,
 	},
 	{ /* sentinel */ }
 };
@@ -1025,9 +1047,9 @@
 	struct snd_platform_data *pdata = NULL;
 	const struct of_device_id *match =
 			of_match_device(mcasp_dt_ids, &pdev->dev);
+	struct of_phandle_args dma_spec;
 
 	const u32 *of_serial_dir32;
-	u8 *of_serial_dir;
 	u32 val;
 	int i, ret = 0;
 
@@ -1035,20 +1057,13 @@
 		pdata = pdev->dev.platform_data;
 		return pdata;
 	} else if (match) {
-		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-		if (!pdata) {
-			ret = -ENOMEM;
-			goto nodata;
-		}
+		pdata = (struct snd_platform_data *) match->data;
 	} else {
 		/* control shouldn't reach here. something is wrong */
 		ret = -EINVAL;
 		goto nodata;
 	}
 
-	if (match->data)
-		pdata->version = (u8)((int)match->data);
-
 	ret = of_property_read_u32(np, "op-mode", &val);
 	if (ret >= 0)
 		pdata->op_mode = val;
@@ -1065,35 +1080,46 @@
 		pdata->tdm_slots = val;
 	}
 
-	ret = of_property_read_u32(np, "num-serializer", &val);
-	if (ret >= 0)
-		pdata->num_serializer = val;
-
 	of_serial_dir32 = of_get_property(np, "serial-dir", &val);
 	val /= sizeof(u32);
-	if (val != pdata->num_serializer) {
-		dev_err(&pdev->dev,
-				"num-serializer(%d) != serial-dir size(%d)\n",
-				pdata->num_serializer, val);
-		ret = -EINVAL;
-		goto nodata;
-	}
-
 	if (of_serial_dir32) {
-		of_serial_dir = devm_kzalloc(&pdev->dev,
-						(sizeof(*of_serial_dir) * val),
-						GFP_KERNEL);
+		u8 *of_serial_dir = devm_kzalloc(&pdev->dev,
+						 (sizeof(*of_serial_dir) * val),
+						 GFP_KERNEL);
 		if (!of_serial_dir) {
 			ret = -ENOMEM;
 			goto nodata;
 		}
 
-		for (i = 0; i < pdata->num_serializer; i++)
+		for (i = 0; i < val; i++)
 			of_serial_dir[i] = be32_to_cpup(&of_serial_dir32[i]);
 
+		pdata->num_serializer = val;
 		pdata->serial_dir = of_serial_dir;
 	}
 
+	ret = of_property_match_string(np, "dma-names", "tx");
+	if (ret < 0)
+		goto nodata;
+
+	ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret,
+					 &dma_spec);
+	if (ret < 0)
+		goto nodata;
+
+	pdata->tx_dma_channel = dma_spec.args[0];
+
+	ret = of_property_match_string(np, "dma-names", "rx");
+	if (ret < 0)
+		goto nodata;
+
+	ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret,
+					 &dma_spec);
+	if (ret < 0)
+		goto nodata;
+
+	pdata->rx_dma_channel = dma_spec.args[0];
+
 	ret = of_property_read_u32(np, "tx-num-evt", &val);
 	if (ret >= 0)
 		pdata->txnumevt = val;
@@ -1124,7 +1150,7 @@
 static int davinci_mcasp_probe(struct platform_device *pdev)
 {
 	struct davinci_pcm_dma_params *dma_data;
-	struct resource *mem, *ioarea, *res;
+	struct resource *mem, *ioarea, *res, *dat;
 	struct snd_platform_data *pdata;
 	struct davinci_audio_dev *dev;
 	int ret;
@@ -1145,10 +1171,15 @@
 		return -EINVAL;
 	}
 
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
 	if (!mem) {
-		dev_err(&pdev->dev, "no mem resource?\n");
-		return -ENODEV;
+		dev_warn(dev->dev,
+			 "\"mpu\" mem resource not found, using index 0\n");
+		mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		if (!mem) {
+			dev_err(&pdev->dev, "no mem resource?\n");
+			return -ENODEV;
+		}
 	}
 
 	ioarea = devm_request_mem_region(&pdev->dev, mem->start,
@@ -1182,40 +1213,36 @@
 	dev->rxnumevt = pdata->rxnumevt;
 	dev->dev = &pdev->dev;
 
+	dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
+	if (!dat)
+		dat = mem;
+
 	dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
 	dma_data->asp_chan_q = pdata->asp_chan_q;
 	dma_data->ram_chan_q = pdata->ram_chan_q;
 	dma_data->sram_pool = pdata->sram_pool;
 	dma_data->sram_size = pdata->sram_size_playback;
-	dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
-							mem->start);
+	dma_data->dma_addr = dat->start + pdata->tx_dma_offset;
 
-	/* first TX, then RX */
 	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "no DMA resource\n");
-		ret = -ENODEV;
-		goto err_release_clk;
-	}
-
-	dma_data->channel = res->start;
+	if (res)
+		dma_data->channel = res->start;
+	else
+		dma_data->channel = pdata->tx_dma_channel;
 
 	dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE];
 	dma_data->asp_chan_q = pdata->asp_chan_q;
 	dma_data->ram_chan_q = pdata->ram_chan_q;
 	dma_data->sram_pool = pdata->sram_pool;
 	dma_data->sram_size = pdata->sram_size_capture;
-	dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
-							mem->start);
+	dma_data->dma_addr = dat->start + pdata->rx_dma_offset;
 
 	res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!res) {
-		dev_err(&pdev->dev, "no DMA resource\n");
-		ret = -ENODEV;
-		goto err_release_clk;
-	}
+	if (res)
+		dma_data->channel = res->start;
+	else
+		dma_data->channel = pdata->rx_dma_channel;
 
-	dma_data->channel = res->start;
 	dev_set_drvdata(&pdev->dev, dev);
 	ret = snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
 					 &davinci_mcasp_dai[pdata->op_mode], 1);
@@ -1251,12 +1278,51 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int davinci_mcasp_suspend(struct device *dev)
+{
+	struct davinci_audio_dev *a = dev_get_drvdata(dev);
+	void __iomem *base = a->base;
+
+	a->context.txfmtctl = mcasp_get_reg(base + DAVINCI_MCASP_TXFMCTL_REG);
+	a->context.rxfmtctl = mcasp_get_reg(base + DAVINCI_MCASP_RXFMCTL_REG);
+	a->context.txfmt = mcasp_get_reg(base + DAVINCI_MCASP_TXFMT_REG);
+	a->context.rxfmt = mcasp_get_reg(base + DAVINCI_MCASP_RXFMT_REG);
+	a->context.aclkxctl = mcasp_get_reg(base + DAVINCI_MCASP_ACLKXCTL_REG);
+	a->context.aclkrctl = mcasp_get_reg(base + DAVINCI_MCASP_ACLKRCTL_REG);
+	a->context.pdir = mcasp_get_reg(base + DAVINCI_MCASP_PDIR_REG);
+
+	return 0;
+}
+
+static int davinci_mcasp_resume(struct device *dev)
+{
+	struct davinci_audio_dev *a = dev_get_drvdata(dev);
+	void __iomem *base = a->base;
+
+	mcasp_set_reg(base + DAVINCI_MCASP_TXFMCTL_REG, a->context.txfmtctl);
+	mcasp_set_reg(base + DAVINCI_MCASP_RXFMCTL_REG, a->context.rxfmtctl);
+	mcasp_set_reg(base + DAVINCI_MCASP_TXFMT_REG, a->context.txfmt);
+	mcasp_set_reg(base + DAVINCI_MCASP_RXFMT_REG, a->context.rxfmt);
+	mcasp_set_reg(base + DAVINCI_MCASP_ACLKXCTL_REG, a->context.aclkxctl);
+	mcasp_set_reg(base + DAVINCI_MCASP_ACLKRCTL_REG, a->context.aclkrctl);
+	mcasp_set_reg(base + DAVINCI_MCASP_PDIR_REG, a->context.pdir);
+
+	return 0;
+}
+#endif
+
+SIMPLE_DEV_PM_OPS(davinci_mcasp_pm_ops,
+		  davinci_mcasp_suspend,
+		  davinci_mcasp_resume);
+
 static struct platform_driver davinci_mcasp_driver = {
 	.probe		= davinci_mcasp_probe,
 	.remove		= davinci_mcasp_remove,
 	.driver		= {
 		.name	= "davinci-mcasp",
 		.owner	= THIS_MODULE,
+		.pm	= &davinci_mcasp_pm_ops,
 		.of_match_table = mcasp_dt_ids,
 	},
 };
@@ -1266,4 +1332,3 @@
 MODULE_AUTHOR("Steve Chen");
 MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface");
 MODULE_LICENSE("GPL");
-
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h
index a9ac0c1..a2e27e1 100644
--- a/sound/soc/davinci/davinci-mcasp.h
+++ b/sound/soc/davinci/davinci-mcasp.h
@@ -43,6 +43,18 @@
 	/* McASP FIFO related */
 	u8	txnumevt;
 	u8	rxnumevt;
+
+#ifdef CONFIG_PM_SLEEP
+	struct {
+		u32	txfmtctl;
+		u32	rxfmtctl;
+		u32	txfmt;
+		u32	rxfmt;
+		u32	aclkxctl;
+		u32	aclkrctl;
+		u32	pdir;
+	} context;
+#endif
 };
 
 #endif	/* DAVINCI_MCASP_H */
diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c
index 9a4a0ca..5983740 100644
--- a/sound/soc/fsl/eukrea-tlv320.c
+++ b/sound/soc/fsl/eukrea-tlv320.c
@@ -42,7 +42,8 @@
 				  SND_SOC_DAIFMT_NB_NF |
 				  SND_SOC_DAIFMT_CBM_CFM);
 	if (ret) {
-		pr_err("%s: failed set cpu dai format\n", __func__);
+		dev_err(cpu_dai->dev,
+			"Failed to set the cpu dai format.\n");
 		return ret;
 	}
 
@@ -50,14 +51,16 @@
 				  SND_SOC_DAIFMT_NB_NF |
 				  SND_SOC_DAIFMT_CBM_CFM);
 	if (ret) {
-		pr_err("%s: failed set codec dai format\n", __func__);
+		dev_err(cpu_dai->dev,
+			"Failed to set the codec format.\n");
 		return ret;
 	}
 
 	ret = snd_soc_dai_set_sysclk(codec_dai, 0,
 				     CODEC_CLOCK, SND_SOC_CLOCK_OUT);
 	if (ret) {
-		pr_err("%s: failed setting codec sysclk\n", __func__);
+		dev_err(cpu_dai->dev,
+			"Failed to set the codec sysclk.\n");
 		return ret;
 	}
 	snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0);
@@ -65,7 +68,8 @@
 	ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0,
 				SND_SOC_CLOCK_IN);
 	if (ret) {
-		pr_err("can't set CPU system clock IMX_SSP_SYS_CLK\n");
+		dev_err(cpu_dai->dev,
+			"Can't set the IMX_SSP_SYS_CLK CPU system clock.\n");
 		return ret;
 	}
 
@@ -155,7 +159,8 @@
 		.owner = THIS_MODULE,
 	},
 	.probe = eukrea_tlv320_probe,
-	.remove = eukrea_tlv320_remove,};
+	.remove = eukrea_tlv320_remove,
+};
 
 module_platform_driver(eukrea_tlv320_driver);
 
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index 9cc5c1f..d1b111e 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -21,6 +21,8 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/gfp.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/list.h>
 #include <linux/slab.h>
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index 3920c3e8..55193a5 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -963,7 +963,7 @@
 		return true;
 	default:
 		return false;
-	};
+	}
 }
 
 static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg)
@@ -982,7 +982,7 @@
 		return true;
 	default:
 		return false;
-	};
+	}
 }
 
 static const struct regmap_config fsl_spdif_regmap_config = {
@@ -1107,11 +1107,6 @@
 
 	/* Get the addresses and IRQ */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (IS_ERR(res)) {
-		dev_err(&pdev->dev, "could not determine device resources\n");
-		return PTR_ERR(res);
-	}
-
 	regs = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(regs))
 		return PTR_ERR(regs);
@@ -1172,23 +1167,16 @@
 	/* Register with ASoC */
 	dev_set_drvdata(&pdev->dev, spdif_priv);
 
-	ret = snd_soc_register_component(&pdev->dev, &fsl_spdif_component,
-					 &spdif_priv->cpu_dai_drv, 1);
+	ret = devm_snd_soc_register_component(&pdev->dev, &fsl_spdif_component,
+					      &spdif_priv->cpu_dai_drv, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
 		return ret;
 	}
 
 	ret = imx_pcm_dma_init(pdev);
-	if (ret) {
+	if (ret)
 		dev_err(&pdev->dev, "imx_pcm_dma_init failed: %d\n", ret);
-		goto error_component;
-	}
-
-	return ret;
-
-error_component:
-	snd_soc_unregister_component(&pdev->dev);
 
 	return ret;
 }
@@ -1196,7 +1184,6 @@
 static int fsl_spdif_remove(struct platform_device *pdev)
 {
 	imx_pcm_dma_exit(pdev);
-	snd_soc_unregister_component(&pdev->dev);
 
 	return 0;
 }
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index c6b7439..35e2773 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -469,19 +469,12 @@
 			 * parameters, then the second stream may be
 			 * constrained to the wrong sample rate or size.
 			 */
-			if (!first_runtime->sample_bits) {
-				dev_err(substream->pcm->card->dev,
-					"set sample size in %s stream first\n",
-					substream->stream ==
-					SNDRV_PCM_STREAM_PLAYBACK
-					? "capture" : "playback");
-				return -EAGAIN;
-			}
-
-			snd_pcm_hw_constraint_minmax(substream->runtime,
-				SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
+			if (first_runtime->sample_bits) {
+				snd_pcm_hw_constraint_minmax(substream->runtime,
+						SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
 				first_runtime->sample_bits,
 				first_runtime->sample_bits);
+			}
 		}
 
 		ssi_private->second_stream = substream;
@@ -748,7 +741,7 @@
 	fsl_ssi_setup(fsl_ac97_data);
 }
 
-void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+static void fsl_ssi_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
 		unsigned short val)
 {
 	struct ccsr_ssi *ssi = fsl_ac97_data->ssi;
@@ -770,7 +763,7 @@
 	udelay(100);
 }
 
-unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97,
+static unsigned short fsl_ssi_ac97_read(struct snd_ac97 *ac97,
 		unsigned short reg)
 {
 	struct ccsr_ssi *ssi = fsl_ac97_data->ssi;
@@ -936,7 +929,7 @@
 	ssi_private->ssi_phys = res.start;
 
 	ssi_private->irq = irq_of_parse_and_map(np, 0);
-	if (ssi_private->irq == NO_IRQ) {
+	if (!ssi_private->irq) {
 		dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
 		return -ENXIO;
 	}
@@ -1135,7 +1128,6 @@
 	if (ssi_private->ssi_on_imx)
 		imx_pcm_dma_exit(pdev);
 	snd_soc_unregister_component(&pdev->dev);
-	dev_set_drvdata(&pdev->dev, NULL);
 	device_remove_file(&pdev->dev, &ssi_private->dev_attr);
 	if (ssi_private->ssi_on_imx)
 		clk_disable_unprepare(ssi_private->clk);
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c
index d3bf71a..ac86993 100644
--- a/sound/soc/fsl/imx-audmux.c
+++ b/sound/soc/fsl/imx-audmux.c
@@ -66,13 +66,10 @@
 				size_t count, loff_t *ppos)
 {
 	ssize_t ret;
-	char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	char *buf;
 	int port = (int)file->private_data;
 	u32 pdcr, ptcr;
 
-	if (!buf)
-		return -ENOMEM;
-
 	if (audmux_clk) {
 		ret = clk_prepare_enable(audmux_clk);
 		if (ret)
@@ -85,6 +82,10 @@
 	if (audmux_clk)
 		clk_disable_unprepare(audmux_clk);
 
+	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
 	ret = snprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n",
 		       pdcr, ptcr);
 
diff --git a/sound/soc/fsl/imx-mc13783.c b/sound/soc/fsl/imx-mc13783.c
index a3d60d4..79cee78 100644
--- a/sound/soc/fsl/imx-mc13783.c
+++ b/sound/soc/fsl/imx-mc13783.c
@@ -112,7 +112,7 @@
 		return ret;
 	}
 
-	if (machine_is_mx31_3ds()) {
+	if (machine_is_mx31_3ds() || machine_is_mx31moboard()) {
 		imx_audmux_v2_configure_port(MX31_AUDMUX_PORT4_SSI_PINS_4,
 			IMX_AUDMUX_V2_PTCR_SYN,
 			IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0) |
@@ -160,6 +160,7 @@
 	.driver = {
 		.name = "imx_mc13783",
 		.owner = THIS_MODULE,
+		.pm = &snd_soc_pm_ops,
 	},
 	.probe = imx_mc13783_probe,
 	.remove = imx_mc13783_remove
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c
index 4dc1296..aee2307 100644
--- a/sound/soc/fsl/imx-pcm-dma.c
+++ b/sound/soc/fsl/imx-pcm-dma.c
@@ -25,12 +25,10 @@
 
 static bool filter(struct dma_chan *chan, void *param)
 {
-	struct snd_dmaengine_dai_dma_data *dma_data = param;
-
 	if (!imx_dma_is_general_purpose(chan))
 		return false;
 
-	chan->private = dma_data->filter_data;
+	chan->private = param;
 
 	return true;
 }
diff --git a/sound/soc/fsl/imx-pcm-fiq.c b/sound/soc/fsl/imx-pcm-fiq.c
index 34043c5..10e3305 100644
--- a/sound/soc/fsl/imx-pcm-fiq.c
+++ b/sound/soc/fsl/imx-pcm-fiq.c
@@ -39,8 +39,6 @@
 	unsigned int period;
 	int periods;
 	unsigned long offset;
-	unsigned long last_offset;
-	unsigned long size;
 	struct hrtimer hrt;
 	int poll_time_ns;
 	struct snd_pcm_substream *substream;
@@ -52,9 +50,7 @@
 	struct imx_pcm_runtime_data *iprtd =
 		container_of(hrt, struct imx_pcm_runtime_data, hrt);
 	struct snd_pcm_substream *substream = iprtd->substream;
-	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct pt_regs regs;
-	unsigned long delta;
 
 	if (!atomic_read(&iprtd->running))
 		return HRTIMER_NORESTART;
@@ -66,19 +62,7 @@
 	else
 		iprtd->offset = regs.ARM_r9 & 0xffff;
 
-	/* How much data have we transferred since the last period report? */
-	if (iprtd->offset >= iprtd->last_offset)
-		delta = iprtd->offset - iprtd->last_offset;
-	else
-		delta = runtime->buffer_size + iprtd->offset
-			- iprtd->last_offset;
-
-	/* If we've transferred at least a period then report it and
-	 * reset our poll time */
-	if (delta >= iprtd->period) {
-		snd_pcm_period_elapsed(substream);
-		iprtd->last_offset = iprtd->offset;
-	}
+	snd_pcm_period_elapsed(substream);
 
 	hrtimer_forward_now(hrt, ns_to_ktime(iprtd->poll_time_ns));
 
@@ -95,11 +79,9 @@
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct imx_pcm_runtime_data *iprtd = runtime->private_data;
 
-	iprtd->size = params_buffer_bytes(params);
 	iprtd->periods = params_periods(params);
-	iprtd->period = params_period_bytes(params) ;
+	iprtd->period = params_period_bytes(params);
 	iprtd->offset = 0;
-	iprtd->last_offset = 0;
 	iprtd->poll_time_ns = 1000000000 / params_rate(params) *
 				params_period_size(params);
 	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c
index ca1be1d..f2beae7 100644
--- a/sound/soc/fsl/imx-sgtl5000.c
+++ b/sound/soc/fsl/imx-sgtl5000.c
@@ -159,7 +159,7 @@
 	data->card.dapm_widgets = imx_sgtl5000_dapm_widgets;
 	data->card.num_dapm_widgets = ARRAY_SIZE(imx_sgtl5000_dapm_widgets);
 
-	ret = snd_soc_register_card(&data->card);
+	ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
 	if (ret) {
 		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
 		goto fail;
@@ -186,7 +186,6 @@
 {
 	struct imx_sgtl5000_data *data = platform_get_drvdata(pdev);
 
-	snd_soc_unregister_card(&data->card);
 	clk_put(data->codec_clk);
 
 	return 0;
@@ -202,6 +201,7 @@
 	.driver = {
 		.name = "imx-sgtl5000",
 		.owner = THIS_MODULE,
+		.pm = &snd_soc_pm_ops,
 		.of_match_table = imx_sgtl5000_dt_ids,
 	},
 	.probe = imx_sgtl5000_probe,
diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c
index 816013b..8499d52 100644
--- a/sound/soc/fsl/imx-spdif.c
+++ b/sound/soc/fsl/imx-spdif.c
@@ -87,7 +87,7 @@
 	if (ret)
 		goto error_dir;
 
-	ret = snd_soc_register_card(&data->card);
+	ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
 	if (ret) {
 		dev_err(&pdev->dev, "snd_soc_register_card failed: %d\n", ret);
 		goto error_dir;
@@ -119,8 +119,6 @@
 	if (data->txdev)
 		platform_device_unregister(data->txdev);
 
-	snd_soc_unregister_card(&data->card);
-
 	return 0;
 }
 
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c
index f58bcd8..f5f248c 100644
--- a/sound/soc/fsl/imx-ssi.c
+++ b/sound/soc/fsl/imx-ssi.c
@@ -600,22 +600,19 @@
 	ssi->fiq_params.dma_params_rx = &ssi->dma_params_rx;
 	ssi->fiq_params.dma_params_tx = &ssi->dma_params_tx;
 
-	ret = imx_pcm_fiq_init(pdev, &ssi->fiq_params);
-	if (ret)
-		goto failed_pcm_fiq;
+	ssi->fiq_init = imx_pcm_fiq_init(pdev, &ssi->fiq_params);
+	ssi->dma_init = imx_pcm_dma_init(pdev);
 
-	ret = imx_pcm_dma_init(pdev);
-	if (ret)
-		goto failed_pcm_dma;
+	if (ssi->fiq_init && ssi->dma_init) {
+		ret = ssi->fiq_init;
+		goto failed_pcm;
+	}
 
 	return 0;
 
-failed_pcm_dma:
-	imx_pcm_fiq_exit(pdev);
-failed_pcm_fiq:
+failed_pcm:
 	snd_soc_unregister_component(&pdev->dev);
 failed_register:
-	release_mem_region(res->start, resource_size(res));
 	clk_disable_unprepare(ssi->clk);
 failed_clk:
 	snd_soc_set_ac97_ops(NULL);
@@ -625,18 +622,19 @@
 
 static int imx_ssi_remove(struct platform_device *pdev)
 {
-	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	struct imx_ssi *ssi = platform_get_drvdata(pdev);
 
-	imx_pcm_dma_exit(pdev);
-	imx_pcm_fiq_exit(pdev);
+	if (!ssi->dma_init)
+		imx_pcm_dma_exit(pdev);
+
+	if (!ssi->fiq_init)
+		imx_pcm_fiq_exit(pdev);
 
 	snd_soc_unregister_component(&pdev->dev);
 
 	if (ssi->flags & IMX_SSI_USE_AC97)
 		ac97_ssi = NULL;
 
-	release_mem_region(res->start, resource_size(res));
 	clk_disable_unprepare(ssi->clk);
 	snd_soc_set_ac97_ops(NULL);
 
diff --git a/sound/soc/fsl/imx-ssi.h b/sound/soc/fsl/imx-ssi.h
index fb1616b..560c40f 100644
--- a/sound/soc/fsl/imx-ssi.h
+++ b/sound/soc/fsl/imx-ssi.h
@@ -211,6 +211,8 @@
 	struct imx_dma_data filter_data_rx;
 	struct imx_pcm_fiq_params fiq_params;
 
+	int fiq_init;
+	int dma_init;
 	int enabled;
 };
 
diff --git a/sound/soc/fsl/imx-wm8962.c b/sound/soc/fsl/imx-wm8962.c
index 722afe6..361f94f 100644
--- a/sound/soc/fsl/imx-wm8962.c
+++ b/sound/soc/fsl/imx-wm8962.c
@@ -266,7 +266,7 @@
 	data->card.late_probe = imx_wm8962_late_probe;
 	data->card.set_bias_level = imx_wm8962_set_bias_level;
 
-	ret = snd_soc_register_card(&data->card);
+	ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
 	if (ret) {
 		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
 		goto clk_fail;
@@ -279,8 +279,7 @@
 	return 0;
 
 clk_fail:
-	if (!IS_ERR(data->codec_clk))
-		clk_disable_unprepare(data->codec_clk);
+	clk_disable_unprepare(data->codec_clk);
 fail:
 	if (ssi_np)
 		of_node_put(ssi_np);
@@ -296,7 +295,6 @@
 
 	if (!IS_ERR(data->codec_clk))
 		clk_disable_unprepare(data->codec_clk);
-	snd_soc_unregister_card(&data->card);
 
 	return 0;
 }
@@ -311,6 +309,7 @@
 	.driver = {
 		.name = "imx-wm8962",
 		.owner = THIS_MODULE,
+		.pm = &snd_soc_pm_ops,
 		.of_match_table = imx_wm8962_dt_ids,
 	},
 	.probe = imx_wm8962_probe,
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index 2a847ca..161e5055 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -10,6 +10,8 @@
 #include <linux/of_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
 #include <sound/soc.h>
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
index 3ef7a0c..24eafa2 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.c
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -291,7 +291,7 @@
 
 	rc = snd_soc_set_ac97_ops(&psc_ac97_ops);
 	if (rc != 0) {
-		dev_err(&op->dev, "Failed to set AC'97 ops: %d\n", ret);
+		dev_err(&op->dev, "Failed to set AC'97 ops: %d\n", rc);
 		return rc;
 	}
 
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index 228c52e..fa756d0 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -12,6 +12,7 @@
 
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <sound/soc.h>
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
index ba59c23..f75c3cf 100644
--- a/sound/soc/fsl/p1022_ds.c
+++ b/sound/soc/fsl/p1022_ds.c
@@ -12,6 +12,7 @@
 
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <sound/soc.h>
diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c
index f215519..9d89bb0 100644
--- a/sound/soc/fsl/p1022_rdk.c
+++ b/sound/soc/fsl/p1022_rdk.c
@@ -19,6 +19,7 @@
 
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <sound/soc.h>
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index 8c49147..b2fbb70 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -27,6 +27,11 @@
 	if (!ret && daifmt)
 		ret = snd_soc_dai_set_fmt(dai, daifmt);
 
+	if (ret == -ENOTSUPP) {
+		dev_dbg(dai->dev, "ASoC: set_fmt is not supported\n");
+		ret = 0;
+	}
+
 	if (!ret && set->sysclk)
 		ret = snd_soc_dai_set_sysclk(dai, 0, set->sysclk, 0);
 
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
index b238434..55d0d9d3 100644
--- a/sound/soc/kirkwood/kirkwood-dma.c
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -29,9 +29,7 @@
 #define KIRKWOOD_FORMATS \
 	(SNDRV_PCM_FMTBIT_S16_LE | \
 	 SNDRV_PCM_FMTBIT_S24_LE | \
-	 SNDRV_PCM_FMTBIT_S32_LE | \
-	 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | \
-	 SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE)
+	 SNDRV_PCM_FMTBIT_S32_LE)
 
 static struct kirkwood_dma_data *kirkwood_priv(struct snd_pcm_substream *subs)
 {
@@ -161,7 +159,7 @@
 		 * Enable Error interrupts. We're only ack'ing them but
 		 * it's useful for diagnostics
 		 */
-		writel((unsigned long)-1, priv->io + KIRKWOOD_ERR_MASK);
+		writel((unsigned int)-1, priv->io + KIRKWOOD_ERR_MASK);
 	}
 
 	dram = mv_mbus_dram_info();
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
index 0f3d73d..d34d917 100644
--- a/sound/soc/kirkwood/kirkwood-i2s.c
+++ b/sound/soc/kirkwood/kirkwood-i2s.c
@@ -103,7 +103,7 @@
 {
 	uint32_t clks_ctrl;
 
-	if (rate == 44100 || rate == 48000 || rate == 96000) {
+	if (IS_ERR(priv->extclk)) {
 		/* use internal dco for the supported rates
 		 * defined in kirkwood_i2s_dai */
 		dev_dbg(dai->dev, "%s: dco set rate = %lu\n",
@@ -160,9 +160,11 @@
 	case SNDRV_PCM_FORMAT_S16_LE:
 		i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16;
 		ctl_play = KIRKWOOD_PLAYCTL_SIZE_16_C |
-			   KIRKWOOD_PLAYCTL_I2S_EN;
+			   KIRKWOOD_PLAYCTL_I2S_EN |
+			   KIRKWOOD_PLAYCTL_SPDIF_EN;
 		ctl_rec = KIRKWOOD_RECCTL_SIZE_16_C |
-			  KIRKWOOD_RECCTL_I2S_EN;
+			  KIRKWOOD_RECCTL_I2S_EN |
+			  KIRKWOOD_RECCTL_SPDIF_EN;
 		break;
 	/*
 	 * doesn't work... S20_3LE != kirkwood 20bit format ?
@@ -178,9 +180,11 @@
 	case SNDRV_PCM_FORMAT_S24_LE:
 		i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24;
 		ctl_play = KIRKWOOD_PLAYCTL_SIZE_24 |
-			   KIRKWOOD_PLAYCTL_I2S_EN;
+			   KIRKWOOD_PLAYCTL_I2S_EN |
+			   KIRKWOOD_PLAYCTL_SPDIF_EN;
 		ctl_rec = KIRKWOOD_RECCTL_SIZE_24 |
-			  KIRKWOOD_RECCTL_I2S_EN;
+			  KIRKWOOD_RECCTL_I2S_EN |
+			  KIRKWOOD_RECCTL_SPDIF_EN;
 		break;
 	case SNDRV_PCM_FORMAT_S32_LE:
 		i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32;
@@ -240,6 +244,11 @@
 				   ctl);
 	}
 
+	if (dai->id == 0)
+		ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN;	/* i2s */
+	else
+		ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN;	/* spdif */
+
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 		/* configure */
@@ -258,7 +267,8 @@
 
 	case SNDRV_PCM_TRIGGER_STOP:
 		/* stop audio, disable interrupts */
-		ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
+		ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
+				KIRKWOOD_PLAYCTL_SPDIF_MUTE;
 		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
 
 		value = readl(priv->io + KIRKWOOD_INT_MASK);
@@ -272,13 +282,15 @@
 
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
-		ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
+		ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
+				KIRKWOOD_PLAYCTL_SPDIF_MUTE;
 		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
 		break;
 
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE);
+		ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
+				KIRKWOOD_PLAYCTL_SPDIF_MUTE);
 		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
 		break;
 
@@ -301,7 +313,13 @@
 	case SNDRV_PCM_TRIGGER_START:
 		/* configure */
 		ctl = priv->ctl_rec;
-		value = ctl & ~KIRKWOOD_RECCTL_I2S_EN;
+		if (dai->id == 0)
+			ctl &= ~KIRKWOOD_RECCTL_SPDIF_EN;	/* i2s */
+		else
+			ctl &= ~KIRKWOOD_RECCTL_I2S_EN;		/* spdif */
+
+		value = ctl & ~(KIRKWOOD_RECCTL_I2S_EN |
+				KIRKWOOD_RECCTL_SPDIF_EN);
 		writel(value, priv->io + KIRKWOOD_RECCTL);
 
 		/* enable interrupts */
@@ -361,9 +379,8 @@
 	return 0;
 }
 
-static int kirkwood_i2s_probe(struct snd_soc_dai *dai)
+static int kirkwood_i2s_init(struct kirkwood_dma_data *priv)
 {
-	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
 	unsigned long value;
 	unsigned int reg_data;
 
@@ -404,9 +421,10 @@
 	.set_fmt        = kirkwood_i2s_set_fmt,
 };
 
-
-static struct snd_soc_dai_driver kirkwood_i2s_dai = {
-	.probe = kirkwood_i2s_probe,
+static struct snd_soc_dai_driver kirkwood_i2s_dai[2] = {
+    {
+	.name = "i2s",
+	.id = 0,
 	.playback = {
 		.channels_min = 1,
 		.channels_max = 2,
@@ -422,10 +440,32 @@
 		.formats = KIRKWOOD_I2S_FORMATS,
 	},
 	.ops = &kirkwood_i2s_dai_ops,
+    },
+    {
+	.name = "spdif",
+	.id = 1,
+	.playback = {
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
+				SNDRV_PCM_RATE_96000,
+		.formats = KIRKWOOD_I2S_FORMATS,
+	},
+	.capture = {
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
+				SNDRV_PCM_RATE_96000,
+		.formats = KIRKWOOD_I2S_FORMATS,
+	},
+	.ops = &kirkwood_i2s_dai_ops,
+    },
 };
 
-static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk = {
-	.probe = kirkwood_i2s_probe,
+static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
+    {
+	.name = "i2s",
+	.id = 0,
 	.playback = {
 		.channels_min = 1,
 		.channels_max = 2,
@@ -443,6 +483,28 @@
 		.formats = KIRKWOOD_I2S_FORMATS,
 	},
 	.ops = &kirkwood_i2s_dai_ops,
+    },
+    {
+	.name = "spdif",
+	.id = 1,
+	.playback = {
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_192000 |
+			 SNDRV_PCM_RATE_CONTINUOUS |
+			 SNDRV_PCM_RATE_KNOT,
+		.formats = KIRKWOOD_I2S_FORMATS,
+	},
+	.capture = {
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_192000 |
+			 SNDRV_PCM_RATE_CONTINUOUS |
+			 SNDRV_PCM_RATE_KNOT,
+		.formats = KIRKWOOD_I2S_FORMATS,
+	},
+	.ops = &kirkwood_i2s_dai_ops,
+    },
 };
 
 static const struct snd_soc_component_driver kirkwood_i2s_component = {
@@ -452,7 +514,7 @@
 static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
 {
 	struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data;
-	struct snd_soc_dai_driver *soc_dai = &kirkwood_i2s_dai;
+	struct snd_soc_dai_driver *soc_dai = kirkwood_i2s_dai;
 	struct kirkwood_dma_data *priv;
 	struct resource *mem;
 	struct device_node *np = pdev->dev.of_node;
@@ -496,14 +558,17 @@
 		return err;
 
 	priv->extclk = devm_clk_get(&pdev->dev, "extclk");
-	if (!IS_ERR(priv->extclk)) {
+	if (IS_ERR(priv->extclk)) {
+		if (PTR_ERR(priv->extclk) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+	} else {
 		if (priv->extclk == priv->clk) {
 			devm_clk_put(&pdev->dev, priv->extclk);
 			priv->extclk = ERR_PTR(-EINVAL);
 		} else {
 			dev_info(&pdev->dev, "found external clock\n");
 			clk_prepare_enable(priv->extclk);
-			soc_dai = &kirkwood_i2s_dai_extclk;
+			soc_dai = kirkwood_i2s_dai_extclk;
 		}
 	}
 
@@ -521,7 +586,7 @@
 	}
 
 	err = snd_soc_register_component(&pdev->dev, &kirkwood_i2s_component,
-					 soc_dai, 1);
+					 soc_dai, 2);
 	if (err) {
 		dev_err(&pdev->dev, "snd_soc_register_component failed\n");
 		goto err_component;
@@ -532,6 +597,9 @@
 		dev_err(&pdev->dev, "snd_soc_register_platform failed\n");
 		goto err_platform;
 	}
+
+	kirkwood_i2s_init(priv);
+
 	return 0;
  err_platform:
 	snd_soc_unregister_component(&pdev->dev);
diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c
index 025be0e..65f2a5b 100644
--- a/sound/soc/kirkwood/kirkwood-openrd.c
+++ b/sound/soc/kirkwood/kirkwood-openrd.c
@@ -52,7 +52,7 @@
 {
 	.name = "CS42L51",
 	.stream_name = "CS42L51 HiFi",
-	.cpu_dai_name = "mvebu-audio",
+	.cpu_dai_name = "i2s",
 	.platform_name = "mvebu-audio",
 	.codec_dai_name = "cs42l51-hifi",
 	.codec_name = "cs42l51-codec.0-004a",
diff --git a/sound/soc/kirkwood/kirkwood-t5325.c b/sound/soc/kirkwood/kirkwood-t5325.c
index 27545b0..d213832 100644
--- a/sound/soc/kirkwood/kirkwood-t5325.c
+++ b/sound/soc/kirkwood/kirkwood-t5325.c
@@ -68,7 +68,7 @@
 {
 	.name = "ALC5621",
 	.stream_name = "ALC5621 HiFi",
-	.cpu_dai_name = "mvebu-audio",
+	.cpu_dai_name = "i2s",
 	.platform_name = "mvebu-audio",
 	.codec_dai_name = "alc5621-hifi",
 	.codec_name = "alc562x-codec.0-001a",
diff --git a/sound/soc/kirkwood/kirkwood.h b/sound/soc/kirkwood/kirkwood.h
index f8e1ccc..bf23afb 100644
--- a/sound/soc/kirkwood/kirkwood.h
+++ b/sound/soc/kirkwood/kirkwood.h
@@ -123,8 +123,8 @@
 /* need to find where they come from               */
 #define KIRKWOOD_SND_MIN_PERIODS		8
 #define KIRKWOOD_SND_MAX_PERIODS		16
-#define KIRKWOOD_SND_MIN_PERIOD_BYTES		0x4000
-#define KIRKWOOD_SND_MAX_PERIOD_BYTES		0x4000
+#define KIRKWOOD_SND_MIN_PERIOD_BYTES		0x800
+#define KIRKWOOD_SND_MAX_PERIOD_BYTES		0x8000
 #define KIRKWOOD_SND_MAX_BUFFER_BYTES		(KIRKWOOD_SND_MAX_PERIOD_BYTES \
 						 * KIRKWOOD_SND_MAX_PERIODS)
 
diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c
index ee36384..d3d4c32 100644
--- a/sound/soc/mid-x86/mfld_machine.c
+++ b/sound/soc/mid-x86/mfld_machine.c
@@ -400,7 +400,7 @@
 	}
 	/* register the soc card */
 	snd_soc_card_mfld.dev = &pdev->dev;
-	ret_val = snd_soc_register_card(&snd_soc_card_mfld);
+	ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_mfld);
 	if (ret_val) {
 		pr_debug("snd_soc_register_card failed %d\n", ret_val);
 		return ret_val;
@@ -410,20 +410,12 @@
 	return 0;
 }
 
-static int snd_mfld_mc_remove(struct platform_device *pdev)
-{
-	pr_debug("snd_mfld_mc_remove called\n");
-	snd_soc_unregister_card(&snd_soc_card_mfld);
-	return 0;
-}
-
 static struct platform_driver snd_mfld_mc_driver = {
 	.driver = {
 		.owner = THIS_MODULE,
 		.name = "msic_audio",
 	},
 	.probe = snd_mfld_mc_probe,
-	.remove = snd_mfld_mc_remove,
 };
 
 module_platform_driver(snd_mfld_mc_driver);
diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c
index 392fc0b..b6b5eb6 100644
--- a/sound/soc/mid-x86/sst_platform.c
+++ b/sound/soc/mid-x86/sst_platform.c
@@ -40,7 +40,8 @@
 
 int sst_register_dsp(struct sst_device *dev)
 {
-	BUG_ON(!dev);
+	if (WARN_ON(!dev))
+		return -EINVAL;
 	if (!try_module_get(dev->dev->driver->owner))
 		return -ENODEV;
 	mutex_lock(&sst_lock);
@@ -59,7 +60,8 @@
 
 int sst_unregister_dsp(struct sst_device *dev)
 {
-	BUG_ON(!dev);
+	if (WARN_ON(!dev))
+		return -EINVAL;
 	if (dev != sst)
 		return -EINVAL;
 
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
index b56b8a0..54e622a 100644
--- a/sound/soc/mxs/mxs-saif.c
+++ b/sound/soc/mxs/mxs-saif.c
@@ -494,6 +494,7 @@
 	struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
 	struct mxs_saif *master_saif;
 	u32 delay;
+	int ret;
 
 	master_saif = mxs_saif_get_master(saif);
 	if (!master_saif)
@@ -503,23 +504,37 @@
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		if (saif->state == MXS_SAIF_STATE_RUNNING)
+			return 0;
+
 		dev_dbg(cpu_dai->dev, "start\n");
 
-		clk_enable(master_saif->clk);
-		if (!master_saif->mclk_in_use)
-			__raw_writel(BM_SAIF_CTRL_RUN,
-				master_saif->base + SAIF_CTRL + MXS_SET_ADDR);
+		ret = clk_enable(master_saif->clk);
+		if (ret) {
+			dev_err(saif->dev, "Failed to enable master clock\n");
+			return ret;
+		}
 
 		/*
 		 * If the saif's master is not himself, we also need to enable
 		 * itself clk for its internal basic logic to work.
 		 */
 		if (saif != master_saif) {
-			clk_enable(saif->clk);
+			ret = clk_enable(saif->clk);
+			if (ret) {
+				dev_err(saif->dev, "Failed to enable master clock\n");
+				clk_disable(master_saif->clk);
+				return ret;
+			}
+
 			__raw_writel(BM_SAIF_CTRL_RUN,
 				saif->base + SAIF_CTRL + MXS_SET_ADDR);
 		}
 
+		if (!master_saif->mclk_in_use)
+			__raw_writel(BM_SAIF_CTRL_RUN,
+				master_saif->base + SAIF_CTRL + MXS_SET_ADDR);
+
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 			/*
 			 * write data to saif data register to trigger
@@ -543,6 +558,7 @@
 		}
 
 		master_saif->ongoing = 1;
+		saif->state = MXS_SAIF_STATE_RUNNING;
 
 		dev_dbg(saif->dev, "CTRL 0x%x STAT 0x%x\n",
 			__raw_readl(saif->base + SAIF_CTRL),
@@ -555,6 +571,9 @@
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		if (saif->state == MXS_SAIF_STATE_STOPPED)
+			return 0;
+
 		dev_dbg(cpu_dai->dev, "stop\n");
 
 		/* wait a while for the current sample to complete */
@@ -575,6 +594,7 @@
 		}
 
 		master_saif->ongoing = 0;
+		saif->state = MXS_SAIF_STATE_STOPPED;
 
 		break;
 	default:
@@ -768,8 +788,8 @@
 			dev_warn(&pdev->dev, "failed to init clocks\n");
 	}
 
-	ret = snd_soc_register_component(&pdev->dev, &mxs_saif_component,
-					 &mxs_saif_dai, 1);
+	ret = devm_snd_soc_register_component(&pdev->dev, &mxs_saif_component,
+					      &mxs_saif_dai, 1);
 	if (ret) {
 		dev_err(&pdev->dev, "register DAI failed\n");
 		return ret;
@@ -778,21 +798,15 @@
 	ret = mxs_pcm_platform_register(&pdev->dev);
 	if (ret) {
 		dev_err(&pdev->dev, "register PCM failed: %d\n", ret);
-		goto failed_pdev_alloc;
+		return ret;
 	}
 
 	return 0;
-
-failed_pdev_alloc:
-	snd_soc_unregister_component(&pdev->dev);
-
-	return ret;
 }
 
 static int mxs_saif_remove(struct platform_device *pdev)
 {
 	mxs_pcm_platform_unregister(&pdev->dev);
-	snd_soc_unregister_component(&pdev->dev);
 
 	return 0;
 }
diff --git a/sound/soc/mxs/mxs-saif.h b/sound/soc/mxs/mxs-saif.h
index 53eaa4b..fbaf7ba 100644
--- a/sound/soc/mxs/mxs-saif.h
+++ b/sound/soc/mxs/mxs-saif.h
@@ -124,6 +124,11 @@
 
 	u32 fifo_underrun;
 	u32 fifo_overrun;
+
+	enum {
+		MXS_SAIF_STATE_STOPPED,
+		MXS_SAIF_STATE_RUNNING,
+	} state;
 };
 
 extern int mxs_saif_put_mclk(unsigned int saif_id);
diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c
index 4bb2737..61822cc 100644
--- a/sound/soc/mxs/mxs-sgtl5000.c
+++ b/sound/soc/mxs/mxs-sgtl5000.c
@@ -122,14 +122,12 @@
 	.num_links	= ARRAY_SIZE(mxs_sgtl5000_dai),
 };
 
-static int mxs_sgtl5000_probe_dt(struct platform_device *pdev)
+static int mxs_sgtl5000_probe(struct platform_device *pdev)
 {
+	struct snd_soc_card *card = &mxs_sgtl5000;
+	int ret, i;
 	struct device_node *np = pdev->dev.of_node;
 	struct device_node *saif_np[2], *codec_np;
-	int i;
-
-	if (!np)
-		return 1; /* no device tree */
 
 	saif_np[0] = of_parse_phandle(np, "saif-controllers", 0);
 	saif_np[1] = of_parse_phandle(np, "saif-controllers", 1);
@@ -152,18 +150,6 @@
 	of_node_put(saif_np[0]);
 	of_node_put(saif_np[1]);
 
-	return 0;
-}
-
-static int mxs_sgtl5000_probe(struct platform_device *pdev)
-{
-	struct snd_soc_card *card = &mxs_sgtl5000;
-	int ret;
-
-	ret = mxs_sgtl5000_probe_dt(pdev);
-	if (ret < 0)
-		return ret;
-
 	/*
 	 * Set an init clock(11.28Mhz) for sgtl5000 initialization(i2c r/w).
 	 * The Sgtl5000 sysclk is derived from saif0 mclk and it's range
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index daa78a0..4a07f71 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -1,6 +1,6 @@
 config SND_OMAP_SOC
 	tristate "SoC Audio for the Texas Instruments OMAP chips"
-	depends on (ARCH_OMAP && DMA_OMAP) || (ARCH_ARM && COMPILE_TEST)
+	depends on (ARCH_OMAP && DMA_OMAP) || (ARM && COMPILE_TEST)
 	select SND_DMAENGINE_PCM
 
 config SND_OMAP_SOC_DMIC
@@ -26,7 +26,7 @@
 
 config SND_OMAP_SOC_RX51
 	tristate "SoC Audio support for Nokia RX-51"
-	depends on SND_OMAP_SOC && ARCH_ARM && (MACH_NOKIA_RX51 || COMPILE_TEST)
+	depends on SND_OMAP_SOC && ARM && (MACH_NOKIA_RX51 || COMPILE_TEST)
 	select SND_OMAP_SOC_MCBSP
 	select SND_SOC_TLV320AIC3X
 	select SND_SOC_TPA6130A2
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index 5e8d640..6d216cb 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -344,8 +344,11 @@
 	clk_set_parent(sys_clkout2_src, func96m_clk);
 	clk_set_rate(sys_clkout2, 12000000);
 
-	BUG_ON((gpio_request(N810_HEADSET_AMP_GPIO, "hs_amp") < 0) ||
-	       (gpio_request(N810_SPEAKER_AMP_GPIO, "spk_amp") < 0));
+	if (WARN_ON((gpio_request(N810_HEADSET_AMP_GPIO, "hs_amp") < 0) ||
+		    (gpio_request(N810_SPEAKER_AMP_GPIO, "spk_amp") < 0))) {
+		err = -EINVAL;
+		goto err4;
+	}
 
 	gpio_direction_output(N810_HEADSET_AMP_GPIO, 0);
 	gpio_direction_output(N810_SPEAKER_AMP_GPIO, 0);
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index 90d2a7c..cd9ee16 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -490,14 +490,9 @@
 
 	mcpdm->dev = &pdev->dev;
 
-	return snd_soc_register_component(&pdev->dev, &omap_mcpdm_component,
-					  &omap_mcpdm_dai, 1);
-}
-
-static int asoc_mcpdm_remove(struct platform_device *pdev)
-{
-	snd_soc_unregister_component(&pdev->dev);
-	return 0;
+	return devm_snd_soc_register_component(&pdev->dev,
+					       &omap_mcpdm_component,
+					       &omap_mcpdm_dai, 1);
 }
 
 static const struct of_device_id omap_mcpdm_of_match[] = {
@@ -514,7 +509,6 @@
 	},
 
 	.probe	= asoc_mcpdm_probe,
-	.remove	= asoc_mcpdm_remove,
 };
 
 module_platform_driver(asoc_mcpdm_driver);
diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c
index 2a9324f..6a8d6b5 100644
--- a/sound/soc/omap/omap-twl4030.c
+++ b/sound/soc/omap/omap-twl4030.c
@@ -338,9 +338,9 @@
 	}
 
 	snd_soc_card_set_drvdata(card, priv);
-	ret = snd_soc_register_card(card);
+	ret = devm_snd_soc_register_card(&pdev->dev, card);
 	if (ret) {
-		dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+		dev_err(&pdev->dev, "devm_snd_soc_register_card() failed: %d\n",
 			ret);
 		return ret;
 	}
@@ -357,7 +357,6 @@
 		snd_soc_jack_free_gpios(&priv->hs_jack,
 					ARRAY_SIZE(hs_jack_gpios),
 					hs_jack_gpios);
-	snd_soc_unregister_card(card);
 
 	return 0;
 }
diff --git a/sound/soc/pxa/brownstone.c b/sound/soc/pxa/brownstone.c
index 5b7d969..08acdc2 100644
--- a/sound/soc/pxa/brownstone.c
+++ b/sound/soc/pxa/brownstone.c
@@ -163,6 +163,7 @@
 	.driver		= {
 		.name	= "brownstone-audio",
 		.owner	= THIS_MODULE,
+		.pm     = &snd_soc_pm_ops,
 	},
 	.probe		= brownstone_probe,
 	.remove		= brownstone_remove,
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index f4cce1e..1853d41 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -329,6 +329,7 @@
 	.driver		= {
 		.name	= "corgi-audio",
 		.owner	= THIS_MODULE,
+		.pm     = &snd_soc_pm_ops,
 	},
 	.probe		= corgi_probe,
 	.remove		= corgi_remove,
diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c
index 70d799b..44b5c09 100644
--- a/sound/soc/pxa/e740_wm9705.c
+++ b/sound/soc/pxa/e740_wm9705.c
@@ -178,6 +178,7 @@
 	.driver		= {
 		.name	= "e740-audio",
 		.owner	= THIS_MODULE,
+		.pm     = &snd_soc_pm_ops,
 	},
 	.probe		= e740_probe,
 	.remove		= e740_remove,
diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c
index f94d2ab..c34e447 100644
--- a/sound/soc/pxa/e750_wm9705.c
+++ b/sound/soc/pxa/e750_wm9705.c
@@ -160,6 +160,7 @@
 	.driver		= {
 		.name	= "e750-audio",
 		.owner	= THIS_MODULE,
+		.pm     = &snd_soc_pm_ops,
 	},
 	.probe		= e750_probe,
 	.remove		= e750_remove,
diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c
index 8768a64..3137f80 100644
--- a/sound/soc/pxa/e800_wm9712.c
+++ b/sound/soc/pxa/e800_wm9712.c
@@ -150,6 +150,7 @@
 	.driver		= {
 		.name	= "e800-audio",
 		.owner	= THIS_MODULE,
+		.pm     = &snd_soc_pm_ops,
 	},
 	.probe		= e800_probe,
 	.remove		= e800_remove,
diff --git a/sound/soc/pxa/imote2.c b/sound/soc/pxa/imote2.c
index eef1f7b..fd2f4ed 100644
--- a/sound/soc/pxa/imote2.c
+++ b/sound/soc/pxa/imote2.c
@@ -91,6 +91,7 @@
 	.driver		= {
 		.name	= "imote2-audio",
 		.owner	= THIS_MODULE,
+		.pm     = &snd_soc_pm_ops,
 	},
 	.probe		= imote2_probe,
 	.remove		= imote2_remove,
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c
index bbea778..160c524 100644
--- a/sound/soc/pxa/mioa701_wm9713.c
+++ b/sound/soc/pxa/mioa701_wm9713.c
@@ -215,6 +215,7 @@
 	.driver		= {
 		.name		= "mioa701-wm9713",
 		.owner		= THIS_MODULE,
+		.pm     = &snd_soc_pm_ops,
 	},
 };
 
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c
index 41752a5..5bf5f1f 100644
--- a/sound/soc/pxa/mmp-sspa.c
+++ b/sound/soc/pxa/mmp-sspa.c
@@ -455,8 +455,8 @@
 	priv->dai_fmt = (unsigned int) -1;
 	platform_set_drvdata(pdev, priv);
 
-	return snd_soc_register_component(&pdev->dev, &mmp_sspa_component,
-					  &mmp_sspa_dai, 1);
+	return devm_snd_soc_register_component(&pdev->dev, &mmp_sspa_component,
+					       &mmp_sspa_dai, 1);
 }
 
 static int asoc_mmp_sspa_remove(struct platform_device *pdev)
@@ -466,7 +466,6 @@
 	clk_disable(priv->audio_clk);
 	clk_put(priv->audio_clk);
 	clk_put(priv->sysclk);
-	snd_soc_unregister_component(&pdev->dev);
 	return 0;
 }
 
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
index e1ffcdd..3284c4b 100644
--- a/sound/soc/pxa/palm27x.c
+++ b/sound/soc/pxa/palm27x.c
@@ -181,6 +181,7 @@
 	.driver		= {
 		.name		= "palm27x-asoc",
 		.owner		= THIS_MODULE,
+		.pm     = &snd_soc_pm_ops,
 	},
 };
 
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index fafe463..c93e138 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -303,6 +303,7 @@
 	.driver		= {
 		.name	= "poodle-audio",
 		.owner	= THIS_MODULE,
+		.pm     = &snd_soc_pm_ops,
 	},
 	.probe		= poodle_probe,
 	.remove		= poodle_remove,
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index f1059d9..ae956e3 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -89,33 +89,6 @@
 	.filter_data	= &pxa2xx_ac97_pcm_aux_mic_mono_req,
 };
 
-#ifdef CONFIG_PM
-static int pxa2xx_ac97_suspend(struct snd_soc_dai *dai)
-{
-	return pxa2xx_ac97_hw_suspend();
-}
-
-static int pxa2xx_ac97_resume(struct snd_soc_dai *dai)
-{
-	return pxa2xx_ac97_hw_resume();
-}
-
-#else
-#define pxa2xx_ac97_suspend	NULL
-#define pxa2xx_ac97_resume	NULL
-#endif
-
-static int pxa2xx_ac97_probe(struct snd_soc_dai *dai)
-{
-	return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev));
-}
-
-static int pxa2xx_ac97_remove(struct snd_soc_dai *dai)
-{
-	pxa2xx_ac97_hw_remove(to_platform_device(dai->dev));
-	return 0;
-}
-
 static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
 				 struct snd_pcm_hw_params *params,
 				 struct snd_soc_dai *cpu_dai)
@@ -185,10 +158,6 @@
 {
 	.name = "pxa2xx-ac97",
 	.ac97_control = 1,
-	.probe = pxa2xx_ac97_probe,
-	.remove = pxa2xx_ac97_remove,
-	.suspend = pxa2xx_ac97_suspend,
-	.resume = pxa2xx_ac97_resume,
 	.playback = {
 		.stream_name = "AC97 Playback",
 		.channels_min = 2,
@@ -246,6 +215,12 @@
 		return -ENXIO;
 	}
 
+	ret = pxa2xx_ac97_hw_probe(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "PXA2xx AC97 hw probe error (%d)\n", ret);
+		return ret;
+	}
+
 	ret = snd_soc_set_ac97_ops(&pxa2xx_ac97_ops);
 	if (ret != 0)
 		return ret;
@@ -262,15 +237,34 @@
 {
 	snd_soc_unregister_component(&pdev->dev);
 	snd_soc_set_ac97_ops(NULL);
+	pxa2xx_ac97_hw_remove(pdev);
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int pxa2xx_ac97_dev_suspend(struct device *dev)
+{
+	return pxa2xx_ac97_hw_suspend();
+}
+
+static int pxa2xx_ac97_dev_resume(struct device *dev)
+{
+	return pxa2xx_ac97_hw_resume();
+}
+
+static SIMPLE_DEV_PM_OPS(pxa2xx_ac97_pm_ops,
+		pxa2xx_ac97_dev_suspend, pxa2xx_ac97_dev_resume);
+#endif
+
 static struct platform_driver pxa2xx_ac97_driver = {
 	.probe		= pxa2xx_ac97_dev_probe,
 	.remove		= pxa2xx_ac97_dev_remove,
 	.driver		= {
 		.name	= "pxa2xx-ac97",
 		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM_SLEEP
+		.pm	= &pxa2xx_ac97_pm_ops,
+#endif
 	},
 };
 
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index d5340a0..c0d648d 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -165,7 +165,8 @@
 {
 	struct snd_dmaengine_dai_dma_data *dma_data;
 
-	BUG_ON(IS_ERR(clk_i2s));
+	if (WARN_ON(IS_ERR(clk_i2s)))
+		return -EINVAL;
 	clk_prepare_enable(clk_i2s);
 	clk_ena = 1;
 	pxa_i2s_wait();
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index a3fe191..1d9c2ed 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -275,6 +275,7 @@
 	.driver		= {
 		.name	= "tosa-audio",
 		.owner	= THIS_MODULE,
+		.pm     = &snd_soc_pm_ops,
 	},
 	.probe		= tosa_probe,
 	.remove		= tosa_remove,
diff --git a/sound/soc/pxa/ttc-dkb.c b/sound/soc/pxa/ttc-dkb.c
index 13c9ee0..0b535b5 100644
--- a/sound/soc/pxa/ttc-dkb.c
+++ b/sound/soc/pxa/ttc-dkb.c
@@ -160,6 +160,7 @@
 	.driver		= {
 		.name	= "ttc-dkb-audio",
 		.owner	= THIS_MODULE,
+		.pm     = &snd_soc_pm_ops,
 	},
 	.probe		= ttc_dkb_probe,
 	.remove		= ttc_dkb_remove,
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c
index d0740a7..5cfaa54 100644
--- a/sound/soc/s6000/s6000-pcm.c
+++ b/sound/soc/s6000/s6000-pcm.c
@@ -90,7 +90,8 @@
 		return;
 	}
 
-	BUG_ON(period_size & 15);
+	if (WARN_ON(period_size & 15))
+		return;
 	s6dmac_put_fifo(DMA_MASK_DMAC(channel), DMA_INDEX_CHNL(channel),
 			src, dst, period_size);
 
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index 2eea184..37459df 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -2,7 +2,7 @@
 	tristate "ASoC support for Samsung"
 	depends on PLAT_SAMSUNG
 	select S3C64XX_DMA if ARCH_S3C64XX
-	select S3C2410_DMA if ARCH_S3C24XX
+	select S3C24XX_DMA if ARCH_S3C24XX
 	help
 	  Say Y or M if you want to add support for codecs attached to
 	  the Samsung SoCs' Audio interfaces. You will also need to
diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c
index 29e2468..84f5d8b 100644
--- a/sound/soc/samsung/bells.c
+++ b/sound/soc/samsung/bells.c
@@ -356,6 +356,7 @@
 
 static struct snd_soc_dapm_route bells_routes[] = {
 	{ "Sub CLK_SYS", NULL, "OPCLK" },
+	{ "CLKIN", NULL, "OPCLK" },
 
 	{ "DMIC", NULL, "MICBIAS2" },
 	{ "IN2L", NULL, "DMIC" },
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index b302f3b..a5cbdb4 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -702,13 +702,6 @@
 	}
 	writel(mod, i2s->addr + I2SMOD);
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		snd_soc_dai_set_dma_data(dai, substream,
-			(void *)&i2s->dma_playback);
-	else
-		snd_soc_dai_set_dma_data(dai, substream,
-			(void *)&i2s->dma_capture);
-
 	i2s->frmclk = params_rate(params);
 
 	return 0;
@@ -970,6 +963,8 @@
 	}
 	clk_prepare_enable(i2s->clk);
 
+	snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
+
 	if (other) {
 		other->addr = i2s->addr;
 		other->clk = i2s->clk;
@@ -1060,7 +1055,7 @@
 	i2s->i2s_dai_drv.ops = &samsung_i2s_dai_ops;
 	i2s->i2s_dai_drv.suspend = i2s_suspend;
 	i2s->i2s_dai_drv.resume = i2s_resume;
-	i2s->i2s_dai_drv.playback.channels_min = 2;
+	i2s->i2s_dai_drv.playback.channels_min = 1;
 	i2s->i2s_dai_drv.playback.channels_max = 2;
 	i2s->i2s_dai_drv.playback.rates = SAMSUNG_I2S_RATES;
 	i2s->i2s_dai_drv.playback.formats = SAMSUNG_I2S_FMTS;
@@ -1073,7 +1068,7 @@
 		dev_set_drvdata(&i2s->pdev->dev, i2s);
 	} else {	/* Create a new platform_device for Secondary */
 		i2s->pdev = platform_device_alloc("samsung-i2s-sec", -1);
-		if (IS_ERR(i2s->pdev))
+		if (!i2s->pdev)
 			return NULL;
 
 		i2s->pdev->dev.parent = &pdev->dev;
@@ -1143,9 +1138,9 @@
 			dev_err(&pdev->dev, "Unable to get drvdata\n");
 			return -EFAULT;
 		}
-		snd_soc_register_component(&sec_dai->pdev->dev,
-					   &samsung_i2s_component,
-					   &sec_dai->i2s_dai_drv, 1);
+		devm_snd_soc_register_component(&sec_dai->pdev->dev,
+						&samsung_i2s_component,
+						&sec_dai->i2s_dai_drv, 1);
 		samsung_asoc_dma_platform_register(&pdev->dev);
 		return 0;
 	}
@@ -1258,8 +1253,9 @@
 		goto err;
 	}
 
-	snd_soc_register_component(&pri_dai->pdev->dev, &samsung_i2s_component,
-				   &pri_dai->i2s_dai_drv, 1);
+	devm_snd_soc_register_component(&pri_dai->pdev->dev,
+					&samsung_i2s_component,
+					&pri_dai->i2s_dai_drv, 1);
 
 	pm_runtime_enable(&pdev->dev);
 
@@ -1294,7 +1290,6 @@
 	i2s->sec_dai = NULL;
 
 	samsung_asoc_dma_platform_unregister(&pdev->dev);
-	snd_soc_unregister_component(&pdev->dev);
 
 	return 0;
 }
diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c
index e5e81b1..fefc561 100644
--- a/sound/soc/samsung/s3c-i2s-v2.c
+++ b/sound/soc/samsung/s3c-i2s-v2.c
@@ -31,11 +31,7 @@
 #undef S3C_IIS_V2_SUPPORTED
 
 #if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) \
-	|| defined(CONFIG_CPU_S5PV210)
-#define S3C_IIS_V2_SUPPORTED
-#endif
-
-#ifdef CONFIG_PLAT_S3C64XX
+	|| defined(CONFIG_ARCH_S3C64XX) || defined(CONFIG_CPU_S5PV210)
 #define S3C_IIS_V2_SUPPORTED
 #endif
 
diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c
index 5fd7a05..b072bd1 100644
--- a/sound/soc/samsung/smdk_wm8994.c
+++ b/sound/soc/samsung/smdk_wm8994.c
@@ -9,6 +9,7 @@
 
 #include "../codecs/wm8994.h"
 #include <sound/pcm_params.h>
+#include <sound/soc.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -193,7 +194,7 @@
 
 	platform_set_drvdata(pdev, board);
 
-	ret = snd_soc_register_card(card);
+	ret = devm_snd_soc_register_card(&pdev->dev, card);
 
 	if (ret)
 		dev_err(&pdev->dev, "snd_soc_register_card() failed:%d\n", ret);
@@ -201,23 +202,14 @@
 	return ret;
 }
 
-static int smdk_audio_remove(struct platform_device *pdev)
-{
-	struct snd_soc_card *card = platform_get_drvdata(pdev);
-
-	snd_soc_unregister_card(card);
-
-	return 0;
-}
-
 static struct platform_driver smdk_audio_driver = {
 	.driver		= {
 		.name	= "smdk-audio-wm8894",
 		.owner	= THIS_MODULE,
 		.of_match_table = of_match_ptr(samsung_wm8994_of_match),
+		.pm	= &snd_soc_pm_ops,
 	},
 	.probe		= smdk_audio_probe,
-	.remove		= smdk_audio_remove,
 };
 
 module_platform_driver(smdk_audio_driver);
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index 56d8ff6..14011d9 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -37,7 +37,6 @@
 config SND_SOC_RCAR
 	tristate "R-Car series SRU/SCU/SSIU/SSI support"
 	select SND_SIMPLE_CARD
-	select RCAR_CLK_ADG
 	help
 	  This option enables R-Car SUR/SCU/SSIU/SSI sound support
 
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
index d80deb7..9430097 100644
--- a/sound/soc/sh/rcar/adg.c
+++ b/sound/soc/sh/rcar/adg.c
@@ -8,7 +8,6 @@
  * for more details.
  */
 #include <linux/sh_clk.h>
-#include <mach/clock.h>
 #include "rsnd.h"
 
 #define CLKA	0
@@ -22,6 +21,7 @@
 
 	int rate_of_441khz_div_6;
 	int rate_of_48khz_div_6;
+	u32 ckr;
 };
 
 #define for_each_rsnd_clk(pos, adg, i)		\
@@ -116,6 +116,11 @@
 
 found_clock:
 
+	/* see rsnd_adg_ssi_clk_init() */
+	rsnd_mod_bset(mod, SSICKR, 0x00FF0000, adg->ckr);
+	rsnd_mod_write(mod, BRRA,  0x00000002); /* 1/6 */
+	rsnd_mod_write(mod, BRRB,  0x00000002); /* 1/6 */
+
 	/*
 	 * This "mod" = "ssi" here.
 	 * we can get "ssi id" from mod
@@ -182,9 +187,7 @@
 		}
 	}
 
-	rsnd_priv_bset(priv, SSICKR, 0x00FF0000, ckr);
-	rsnd_priv_write(priv, BRRA,  0x00000002); /* 1/6 */
-	rsnd_priv_write(priv, BRRB,  0x00000002); /* 1/6 */
+	adg->ckr = ckr;
 }
 
 int rsnd_adg_probe(struct platform_device *pdev,
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index a357060..78c35b4 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -94,6 +94,7 @@
  *
  */
 #include <linux/pm_runtime.h>
+#include <linux/shdma-base.h>
 #include "rsnd.h"
 
 #define RSND_RATES SNDRV_PCM_RATE_8000_96000
@@ -103,54 +104,9 @@
  *	rsnd_platform functions
  */
 #define rsnd_platform_call(priv, dai, func, param...)	\
-	(!(priv->info->func) ? -ENODEV :		\
+	(!(priv->info->func) ? 0 :		\
 	 priv->info->func(param))
 
-
-/*
- *	basic function
- */
-u32 rsnd_read(struct rsnd_priv *priv,
-	      struct rsnd_mod *mod, enum rsnd_reg reg)
-{
-	void __iomem *base = rsnd_gen_reg_get(priv, mod, reg);
-
-	BUG_ON(!base);
-
-	return ioread32(base);
-}
-
-void rsnd_write(struct rsnd_priv *priv,
-		struct rsnd_mod *mod,
-		enum rsnd_reg reg, u32 data)
-{
-	void __iomem *base = rsnd_gen_reg_get(priv, mod, reg);
-	struct device *dev = rsnd_priv_to_dev(priv);
-
-	BUG_ON(!base);
-
-	dev_dbg(dev, "w %p : %08x\n", base, data);
-
-	iowrite32(data, base);
-}
-
-void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
-	       enum rsnd_reg reg, u32 mask, u32 data)
-{
-	void __iomem *base = rsnd_gen_reg_get(priv, mod, reg);
-	struct device *dev = rsnd_priv_to_dev(priv);
-	u32 val;
-
-	BUG_ON(!base);
-
-	val = ioread32(base);
-	val &= ~mask;
-	val |= data & mask;
-	iowrite32(val, base);
-
-	dev_dbg(dev, "s %p : %08x\n", base, val);
-}
-
 /*
  *	rsnd_mod functions
  */
@@ -254,13 +210,6 @@
 	return !!dma->chan;
 }
 
-static bool rsnd_dma_filter(struct dma_chan *chan, void *param)
-{
-	chan->private = param;
-
-	return true;
-}
-
 int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
 		  int is_play, int id,
 		  int (*inquiry)(struct rsnd_dma *dma,
@@ -268,7 +217,9 @@
 		  int (*complete)(struct rsnd_dma *dma))
 {
 	struct device *dev = rsnd_priv_to_dev(priv);
+	struct dma_slave_config cfg;
 	dma_cap_mask_t mask;
+	int ret;
 
 	if (dma->chan) {
 		dev_err(dev, "it already has dma channel\n");
@@ -278,15 +229,23 @@
 	dma_cap_zero(mask);
 	dma_cap_set(DMA_SLAVE, mask);
 
-	dma->slave.shdma_slave.slave_id = id;
-
-	dma->chan = dma_request_channel(mask, rsnd_dma_filter,
-					&dma->slave.shdma_slave);
+	dma->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter,
+						     (void *)id, dev,
+						     is_play ? "tx" : "rx");
 	if (!dma->chan) {
 		dev_err(dev, "can't get dma channel\n");
 		return -EIO;
 	}
 
+	cfg.slave_id	= id;
+	cfg.dst_addr	= 0; /* use default addr when playback */
+	cfg.src_addr	= 0; /* use default addr when capture */
+	cfg.direction	= is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
+
+	ret = dmaengine_slave_config(dma->chan, &cfg);
+	if (ret < 0)
+		goto rsnd_dma_init_err;
+
 	dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 	dma->priv = priv;
 	dma->inquiry = inquiry;
@@ -294,6 +253,11 @@
 	INIT_WORK(&dma->work, rsnd_dma_do_work);
 
 	return 0;
+
+rsnd_dma_init_err:
+	rsnd_dma_quit(priv, dma);
+
+	return ret;
 }
 
 void  rsnd_dma_quit(struct rsnd_priv *priv,
@@ -363,6 +327,9 @@
 
 struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id)
 {
+	if ((id < 0) || (id >= rsnd_dai_nr(priv)))
+		return NULL;
+
 	return priv->rdai + id;
 }
 
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c
index babb203..61212ee 100644
--- a/sound/soc/sh/rcar/gen.c
+++ b/sound/soc/sh/rcar/gen.c
@@ -11,6 +11,11 @@
 #include "rsnd.h"
 
 struct rsnd_gen_ops {
+	int (*probe)(struct platform_device *pdev,
+		     struct rcar_snd_info *info,
+		     struct rsnd_priv *priv);
+	void (*remove)(struct platform_device *pdev,
+		      struct rsnd_priv *priv);
 	int (*path_init)(struct rsnd_priv *priv,
 			 struct rsnd_dai *rdai,
 			 struct rsnd_dai_stream *io);
@@ -19,21 +24,97 @@
 			 struct rsnd_dai_stream *io);
 };
 
-struct rsnd_gen_reg_map {
-	int index;	/* -1 : not supported */
-	u32 offset_id;	/* offset of ssi0, ssi1, ssi2... */
-	u32 offset_adr;	/* offset of SSICR, SSISR, ... */
-};
-
 struct rsnd_gen {
 	void __iomem *base[RSND_BASE_MAX];
 
-	struct rsnd_gen_reg_map reg_map[RSND_REG_MAX];
 	struct rsnd_gen_ops *ops;
+
+	struct regmap *regmap;
+	struct regmap_field *regs[RSND_REG_MAX];
 };
 
 #define rsnd_priv_to_gen(p)	((struct rsnd_gen *)(p)->gen)
 
+#define RSND_REG_SET(gen, id, reg_id, offset, _id_offset, _id_size)	\
+	[id] = {							\
+		.reg = (unsigned int)gen->base[reg_id] + offset,	\
+		.lsb = 0,						\
+		.msb = 31,						\
+		.id_size = _id_size,					\
+		.id_offset = _id_offset,				\
+	}
+
+/*
+ *		basic function
+ */
+static int rsnd_regmap_write32(void *context, const void *_data, size_t count)
+{
+	struct rsnd_priv *priv = context;
+	struct device *dev = rsnd_priv_to_dev(priv);
+	u32 *data = (u32 *)_data;
+	u32 val = data[1];
+	void __iomem *reg = (void *)data[0];
+
+	iowrite32(val, reg);
+
+	dev_dbg(dev, "w %p : %08x\n", reg, val);
+
+	return 0;
+}
+
+static int rsnd_regmap_read32(void *context,
+			      const void *_data, size_t reg_size,
+			      void *_val, size_t val_size)
+{
+	struct rsnd_priv *priv = context;
+	struct device *dev = rsnd_priv_to_dev(priv);
+	u32 *data = (u32 *)_data;
+	u32 *val = (u32 *)_val;
+	void __iomem *reg = (void *)data[0];
+
+	*val = ioread32(reg);
+
+	dev_dbg(dev, "r %p : %08x\n", reg, *val);
+
+	return 0;
+}
+
+static struct regmap_bus rsnd_regmap_bus = {
+	.write				= rsnd_regmap_write32,
+	.read				= rsnd_regmap_read32,
+	.reg_format_endian_default	= REGMAP_ENDIAN_NATIVE,
+	.val_format_endian_default	= REGMAP_ENDIAN_NATIVE,
+};
+
+u32 rsnd_read(struct rsnd_priv *priv,
+	      struct rsnd_mod *mod, enum rsnd_reg reg)
+{
+	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
+	u32 val;
+
+	regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val);
+
+	return val;
+}
+
+void rsnd_write(struct rsnd_priv *priv,
+		struct rsnd_mod *mod,
+		enum rsnd_reg reg, u32 data)
+{
+	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
+
+	regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data);
+}
+
+void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
+	       enum rsnd_reg reg, u32 mask, u32 data)
+{
+	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
+
+	regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod),
+				  mask, data);
+}
+
 /*
  *		Gen2
  *		will be filled in the future
@@ -98,44 +179,64 @@
 	return ret;
 }
 
-static struct rsnd_gen_ops rsnd_gen1_ops = {
-	.path_init	= rsnd_gen1_path_init,
-	.path_exit	= rsnd_gen1_path_exit,
-};
+/* single address mapping */
+#define RSND_GEN1_S_REG(gen, reg, id, offset)	\
+	RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, 0, 9)
 
-#define RSND_GEN1_REG_MAP(g, s, i, oi, oa)				\
-	do {								\
-		(g)->reg_map[RSND_REG_##i].index  = RSND_GEN1_##s;	\
-		(g)->reg_map[RSND_REG_##i].offset_id = oi;		\
-		(g)->reg_map[RSND_REG_##i].offset_adr = oa;		\
-	} while (0)
+/* multi address mapping */
+#define RSND_GEN1_M_REG(gen, reg, id, offset, _id_offset)	\
+	RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, _id_offset, 9)
 
-static void rsnd_gen1_reg_map_init(struct rsnd_gen *gen)
+static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen)
 {
-	RSND_GEN1_REG_MAP(gen, SRU,	SRC_ROUTE_SEL,	0x0,	0x00);
-	RSND_GEN1_REG_MAP(gen, SRU,	SRC_TMG_SEL0,	0x0,	0x08);
-	RSND_GEN1_REG_MAP(gen, SRU,	SRC_TMG_SEL1,	0x0,	0x0c);
-	RSND_GEN1_REG_MAP(gen, SRU,	SRC_TMG_SEL2,	0x0,	0x10);
-	RSND_GEN1_REG_MAP(gen, SRU,	SRC_CTRL,	0x0,	0xc0);
-	RSND_GEN1_REG_MAP(gen, SRU,	SSI_MODE0,	0x0,	0xD0);
-	RSND_GEN1_REG_MAP(gen, SRU,	SSI_MODE1,	0x0,	0xD4);
-	RSND_GEN1_REG_MAP(gen, SRU,	BUSIF_MODE,	0x4,	0x20);
-	RSND_GEN1_REG_MAP(gen, SRU,	BUSIF_ADINR,	0x40,	0x214);
+	int i;
+	struct device *dev = rsnd_priv_to_dev(priv);
+	struct regmap_config regc;
+	struct reg_field regf[RSND_REG_MAX] = {
+		RSND_GEN1_S_REG(gen, SRU,	SRC_ROUTE_SEL,	0x00),
+		RSND_GEN1_S_REG(gen, SRU,	SRC_TMG_SEL0,	0x08),
+		RSND_GEN1_S_REG(gen, SRU,	SRC_TMG_SEL1,	0x0c),
+		RSND_GEN1_S_REG(gen, SRU,	SRC_TMG_SEL2,	0x10),
+		RSND_GEN1_S_REG(gen, SRU,	SRC_CTRL,	0xc0),
+		RSND_GEN1_S_REG(gen, SRU,	SSI_MODE0,	0xD0),
+		RSND_GEN1_S_REG(gen, SRU,	SSI_MODE1,	0xD4),
+		RSND_GEN1_M_REG(gen, SRU,	BUSIF_MODE,	0x20,	0x4),
+		RSND_GEN1_M_REG(gen, SRU,	BUSIF_ADINR,	0x214,	0x40),
 
-	RSND_GEN1_REG_MAP(gen, ADG,	BRRA,		0x0,	0x00);
-	RSND_GEN1_REG_MAP(gen, ADG,	BRRB,		0x0,	0x04);
-	RSND_GEN1_REG_MAP(gen, ADG,	SSICKR,		0x0,	0x08);
-	RSND_GEN1_REG_MAP(gen, ADG,	AUDIO_CLK_SEL0,	0x0,	0x0c);
-	RSND_GEN1_REG_MAP(gen, ADG,	AUDIO_CLK_SEL1,	0x0,	0x10);
-	RSND_GEN1_REG_MAP(gen, ADG,	AUDIO_CLK_SEL3,	0x0,	0x18);
-	RSND_GEN1_REG_MAP(gen, ADG,	AUDIO_CLK_SEL4,	0x0,	0x1c);
-	RSND_GEN1_REG_MAP(gen, ADG,	AUDIO_CLK_SEL5,	0x0,	0x20);
+		RSND_GEN1_S_REG(gen, ADG,	BRRA,		0x00),
+		RSND_GEN1_S_REG(gen, ADG,	BRRB,		0x04),
+		RSND_GEN1_S_REG(gen, ADG,	SSICKR,		0x08),
+		RSND_GEN1_S_REG(gen, ADG,	AUDIO_CLK_SEL0,	0x0c),
+		RSND_GEN1_S_REG(gen, ADG,	AUDIO_CLK_SEL1,	0x10),
+		RSND_GEN1_S_REG(gen, ADG,	AUDIO_CLK_SEL3,	0x18),
+		RSND_GEN1_S_REG(gen, ADG,	AUDIO_CLK_SEL4,	0x1c),
+		RSND_GEN1_S_REG(gen, ADG,	AUDIO_CLK_SEL5,	0x20),
 
-	RSND_GEN1_REG_MAP(gen, SSI,	SSICR,		0x40,	0x00);
-	RSND_GEN1_REG_MAP(gen, SSI,	SSISR,		0x40,	0x04);
-	RSND_GEN1_REG_MAP(gen, SSI,	SSITDR,		0x40,	0x08);
-	RSND_GEN1_REG_MAP(gen, SSI,	SSIRDR,		0x40,	0x0c);
-	RSND_GEN1_REG_MAP(gen, SSI,	SSIWSR,		0x40,	0x20);
+		RSND_GEN1_M_REG(gen, SSI,	SSICR,		0x00,	0x40),
+		RSND_GEN1_M_REG(gen, SSI,	SSISR,		0x04,	0x40),
+		RSND_GEN1_M_REG(gen, SSI,	SSITDR,		0x08,	0x40),
+		RSND_GEN1_M_REG(gen, SSI,	SSIRDR,		0x0c,	0x40),
+		RSND_GEN1_M_REG(gen, SSI,	SSIWSR,		0x20,	0x40),
+	};
+
+	memset(&regc, 0, sizeof(regc));
+	regc.reg_bits = 32;
+	regc.val_bits = 32;
+
+	gen->regmap = devm_regmap_init(dev, &rsnd_regmap_bus, priv, &regc);
+	if (IS_ERR(gen->regmap)) {
+		dev_err(dev, "regmap error %ld\n", PTR_ERR(gen->regmap));
+		return PTR_ERR(gen->regmap);
+	}
+
+	for (i = 0; i < RSND_REG_MAX; i++) {
+		gen->regs[i] = devm_regmap_field_alloc(dev, gen->regmap, regf[i]);
+		if (IS_ERR(gen->regs[i]))
+			return PTR_ERR(gen->regs[i]);
+
+	}
+
+	return 0;
 }
 
 static int rsnd_gen1_probe(struct platform_device *pdev,
@@ -147,6 +248,7 @@
 	struct resource *sru_res;
 	struct resource *adg_res;
 	struct resource *ssi_res;
+	int ret;
 
 	/*
 	 * map address
@@ -163,8 +265,9 @@
 	    IS_ERR(gen->base[RSND_GEN1_SSI]))
 		return -ENODEV;
 
-	gen->ops = &rsnd_gen1_ops;
-	rsnd_gen1_reg_map_init(gen);
+	ret = rsnd_gen1_regmap_init(priv, gen);
+	if (ret < 0)
+		return ret;
 
 	dev_dbg(dev, "Gen1 device probed\n");
 	dev_dbg(dev, "SRU : %08x => %p\n",	sru_res->start,
@@ -183,6 +286,13 @@
 {
 }
 
+static struct rsnd_gen_ops rsnd_gen1_ops = {
+	.probe		= rsnd_gen1_probe,
+	.remove		= rsnd_gen1_remove,
+	.path_init	= rsnd_gen1_path_init,
+	.path_exit	= rsnd_gen1_path_exit,
+};
+
 /*
  *		Gen
  */
@@ -204,46 +314,12 @@
 	return gen->ops->path_exit(priv, rdai, io);
 }
 
-void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
-			       struct rsnd_mod *mod,
-			       enum rsnd_reg reg)
-{
-	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
-	struct device *dev = rsnd_priv_to_dev(priv);
-	int index;
-	u32 offset_id, offset_adr;
-
-	if (reg >= RSND_REG_MAX) {
-		dev_err(dev, "rsnd_reg reg error\n");
-		return NULL;
-	}
-
-	index		= gen->reg_map[reg].index;
-	offset_id	= gen->reg_map[reg].offset_id;
-	offset_adr	= gen->reg_map[reg].offset_adr;
-
-	if (index < 0) {
-		dev_err(dev, "unsupported reg access %d\n", reg);
-		return NULL;
-	}
-
-	if (offset_id && mod)
-		offset_id *= rsnd_mod_id(mod);
-
-	/*
-	 * index/offset were set on gen1/gen2
-	 */
-
-	return gen->base[index] + offset_id + offset_adr;
-}
-
 int rsnd_gen_probe(struct platform_device *pdev,
 		   struct rcar_snd_info *info,
 		   struct rsnd_priv *priv)
 {
 	struct device *dev = rsnd_priv_to_dev(priv);
 	struct rsnd_gen *gen;
-	int i;
 
 	gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL);
 	if (!gen) {
@@ -251,30 +327,23 @@
 		return -ENOMEM;
 	}
 
+	if (rsnd_is_gen1(priv))
+		gen->ops = &rsnd_gen1_ops;
+
+	if (!gen->ops) {
+		dev_err(dev, "unknown generation R-Car sound device\n");
+		return -ENODEV;
+	}
+
 	priv->gen = gen;
 
-	/*
-	 * see
-	 *	rsnd_reg_get()
-	 *	rsnd_gen_probe()
-	 */
-	for (i = 0; i < RSND_REG_MAX; i++)
-		gen->reg_map[i].index = -1;
-
-	/*
-	 *	init each module
-	 */
-	if (rsnd_is_gen1(priv))
-		return rsnd_gen1_probe(pdev, info, priv);
-
-	dev_err(dev, "unknown generation R-Car sound device\n");
-
-	return -ENODEV;
+	return gen->ops->probe(pdev, info, priv);
 }
 
 void rsnd_gen_remove(struct platform_device *pdev,
 		     struct rsnd_priv *priv)
 {
-	if (rsnd_is_gen1(priv))
-		rsnd_gen1_remove(pdev, priv);
+	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
+
+	gen->ops->remove(pdev, priv);
 }
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index 9cc6986..9e463e5 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -78,10 +78,6 @@
 #define rsnd_mod_bset(m, r, s, d) \
 	rsnd_bset(rsnd_mod_to_priv(m), m, RSND_REG_##r, s, d)
 
-#define rsnd_priv_read(p, r)		rsnd_read(p, NULL, RSND_REG_##r)
-#define rsnd_priv_write(p, r, d)	rsnd_write(p, NULL, RSND_REG_##r, d)
-#define rsnd_priv_bset(p, r, s, d)	rsnd_bset(p, NULL, RSND_REG_##r, s, d)
-
 u32 rsnd_read(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg);
 void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod,
 		enum rsnd_reg reg, u32 data);
@@ -220,8 +216,8 @@
 void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
 			       struct rsnd_mod *mod,
 			       enum rsnd_reg reg);
-#define rsnd_is_gen1(s)		((s)->info->flags & RSND_GEN1)
-#define rsnd_is_gen2(s)		((s)->info->flags & RSND_GEN2)
+#define rsnd_is_gen1(s)		(((s)->info->flags & RSND_GEN_MASK) == RSND_GEN1)
+#define rsnd_is_gen2(s)		(((s)->info->flags & RSND_GEN_MASK) == RSND_GEN2)
 
 /*
  *	R-Car ADG
@@ -285,6 +281,7 @@
 void rsnd_scu_remove(struct platform_device *pdev,
 		     struct rsnd_priv *priv);
 struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id);
+bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod);
 #define rsnd_scu_nr(priv) ((priv)->scu_nr)
 
 /*
diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c
index 2df2e91..f4453e3 100644
--- a/sound/soc/sh/rcar/scu.c
+++ b/sound/soc/sh/rcar/scu.c
@@ -146,20 +146,26 @@
 	return 0;
 }
 
+bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod)
+{
+	struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
+	u32 flags = rsnd_scu_mode_flags(scu);
+
+	return !!(flags & RSND_SCU_USE_HPBIF);
+}
+
 static int rsnd_scu_start(struct rsnd_mod *mod,
 			  struct rsnd_dai *rdai,
 			  struct rsnd_dai_stream *io)
 {
 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
-	struct rsnd_scu *scu = rsnd_mod_to_scu(mod);
 	struct device *dev = rsnd_priv_to_dev(priv);
-	u32 flags = rsnd_scu_mode_flags(scu);
 	int ret;
 
 	/*
 	 * SCU will be used if it has RSND_SCU_USE_HPBIF flags
 	 */
-	if (!(flags & RSND_SCU_USE_HPBIF)) {
+	if (!rsnd_scu_hpbif_is_enable(mod)) {
 		/* it use PIO transter */
 		dev_dbg(dev, "%s%d is not used\n",
 			rsnd_mod_name(mod), rsnd_mod_id(mod));
@@ -192,7 +198,8 @@
 
 struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id)
 {
-	BUG_ON(id < 0 || id >= rsnd_scu_nr(priv));
+	if (WARN_ON(id < 0 || id >= rsnd_scu_nr(priv)))
+		id = 0;
 
 	return &((struct rsnd_scu *)(priv->scu) + id)->mod;
 }
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index fae26d3..5ac20cd 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -101,29 +101,30 @@
 #define rsnd_ssi_to_ssiu(ssi)\
 	(((struct rsnd_ssiu *)((ssi) - rsnd_mod_id(&(ssi)->mod))) - 1)
 
-static void rsnd_ssi_mode_init(struct rsnd_priv *priv,
-			       struct rsnd_ssiu *ssiu)
+static void rsnd_ssi_mode_set(struct rsnd_priv *priv,
+			      struct rsnd_dai *rdai,
+			      struct rsnd_ssi *ssi)
 {
 	struct device *dev = rsnd_priv_to_dev(priv);
-	struct rsnd_ssi *ssi;
+	struct rsnd_mod *scu;
+	struct rsnd_ssiu *ssiu = rsnd_ssi_to_ssiu(ssi);
+	int id = rsnd_mod_id(&ssi->mod);
 	u32 flags;
 	u32 val;
-	int i;
+
+	scu   = rsnd_scu_mod_get(priv, rsnd_mod_id(&ssi->mod));
 
 	/*
 	 * SSI_MODE0
 	 */
-	ssiu->ssi_mode0 = 0;
-	for_each_rsnd_ssi(ssi, priv, i) {
-		flags = rsnd_ssi_mode_flags(ssi);
 
-		/* see also BUSIF_MODE */
-		if (!(flags & RSND_SSI_DEPENDENT)) {
-			ssiu->ssi_mode0 |= (1 << i);
-			dev_dbg(dev, "SSI%d uses INDEPENDENT mode\n", i);
-		} else {
-			dev_dbg(dev, "SSI%d uses DEPENDENT mode\n", i);
-		}
+	/* see also BUSIF_MODE */
+	if (rsnd_scu_hpbif_is_enable(scu)) {
+		ssiu->ssi_mode0 &= ~(1 << id);
+		dev_dbg(dev, "SSI%d uses DEPENDENT mode\n", id);
+	} else {
+		ssiu->ssi_mode0 |= (1 << id);
+		dev_dbg(dev, "SSI%d uses INDEPENDENT mode\n", id);
 	}
 
 	/*
@@ -132,7 +133,7 @@
 #define ssi_parent_set(p, sync, adg, ext)		\
 	do {						\
 		ssi->parent = ssiu->ssi + p;		\
-		if (flags & RSND_SSI_CLK_FROM_ADG)	\
+		if (rsnd_rdai_is_clk_master(rdai))	\
 			val = adg;			\
 		else					\
 			val = ext;			\
@@ -140,15 +141,11 @@
 			val |= sync;			\
 	} while (0)
 
-	ssiu->ssi_mode1 = 0;
-	for_each_rsnd_ssi(ssi, priv, i) {
-		flags = rsnd_ssi_mode_flags(ssi);
-
-		if (!(flags & RSND_SSI_CLK_PIN_SHARE))
-			continue;
+	flags = rsnd_ssi_mode_flags(ssi);
+	if (flags & RSND_SSI_CLK_PIN_SHARE) {
 
 		val = 0;
-		switch (i) {
+		switch (id) {
 		case 1:
 			ssi_parent_set(0, (1 << 4), (0x2 << 0), (0x1 << 0));
 			break;
@@ -165,11 +162,6 @@
 
 		ssiu->ssi_mode1 |= val;
 	}
-}
-
-static void rsnd_ssi_mode_set(struct rsnd_ssi *ssi)
-{
-	struct rsnd_ssiu *ssiu = rsnd_ssi_to_ssiu(ssi);
 
 	rsnd_mod_write(&ssi->mod, SSI_MODE0, ssiu->ssi_mode0);
 	rsnd_mod_write(&ssi->mod, SSI_MODE1, ssiu->ssi_mode1);
@@ -379,7 +371,7 @@
 	ssi->cr_own	= cr;
 	ssi->err	= -1; /* ignore 1st error */
 
-	rsnd_ssi_mode_set(ssi);
+	rsnd_ssi_mode_set(priv, rdai, ssi);
 
 	dev_dbg(dev, "%s.%d init\n", rsnd_mod_name(mod), rsnd_mod_id(mod));
 
@@ -619,7 +611,8 @@
 
 struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id)
 {
-	BUG_ON(id < 0 || id >= rsnd_ssi_nr(priv));
+	if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv)))
+		id = 0;
 
 	return &(((struct rsnd_ssiu *)(priv->ssiu))->ssi + id)->mod;
 }
@@ -706,8 +699,6 @@
 		rsnd_mod_init(priv, &ssi->mod, ops, i);
 	}
 
-	rsnd_ssi_mode_init(priv, ssiu);
-
 	dev_dbg(dev, "ssi probed\n");
 
 	return 0;
diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c
index 9dc24ff..d55babe 100644
--- a/sound/soc/sh/siu_dai.c
+++ b/sound/soc/sh/siu_dai.c
@@ -543,7 +543,8 @@
 	/* Stop the siu if the other stream is not using it */
 	if (!port_info->play_cap) {
 		/* during stmread or stmwrite ? */
-		BUG_ON(port_info->playback.rw_flg || port_info->capture.rw_flg);
+		if (WARN_ON(port_info->playback.rw_flg || port_info->capture.rw_flg))
+			return;
 		siu_dai_spbstop(port_info);
 		siu_dai_stop(port_info);
 	}
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index e72f554..375dc6d 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -11,12 +11,9 @@
  *  option) any later version.
  */
 
-#include <linux/i2c.h>
-#include <linux/spi/spi.h>
 #include <sound/soc.h>
-#include <linux/bitmap.h>
-#include <linux/rbtree.h>
 #include <linux/export.h>
+#include <linux/slab.h>
 
 #include <trace/events/asoc.h>
 
@@ -39,7 +36,8 @@
 		break;
 	}
 	default:
-		BUG();
+		WARN(1, "Invalid word_size %d\n", word_size);
+		break;
 	}
 	return false;
 }
@@ -60,12 +58,92 @@
 		return cache[idx];
 	}
 	default:
-		BUG();
+		WARN(1, "Invalid word_size %d\n", word_size);
+		break;
 	}
 	/* unreachable */
 	return -1;
 }
 
+int snd_soc_cache_init(struct snd_soc_codec *codec)
+{
+	const struct snd_soc_codec_driver *codec_drv = codec->driver;
+	size_t reg_size;
+
+	reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
+
+	mutex_init(&codec->cache_rw_mutex);
+
+	dev_dbg(codec->dev, "ASoC: Initializing cache for %s codec\n",
+				codec->name);
+
+	if (codec_drv->reg_cache_default)
+		codec->reg_cache = kmemdup(codec_drv->reg_cache_default,
+					   reg_size, GFP_KERNEL);
+	else
+		codec->reg_cache = kzalloc(reg_size, GFP_KERNEL);
+	if (!codec->reg_cache)
+		return -ENOMEM;
+
+	return 0;
+}
+
+/*
+ * NOTE: keep in mind that this function might be called
+ * multiple times.
+ */
+int snd_soc_cache_exit(struct snd_soc_codec *codec)
+{
+	dev_dbg(codec->dev, "ASoC: Destroying cache for %s codec\n",
+			codec->name);
+	if (!codec->reg_cache)
+		return 0;
+	kfree(codec->reg_cache);
+	codec->reg_cache = NULL;
+	return 0;
+}
+
+/**
+ * snd_soc_cache_read: Fetch the value of a given register from the cache.
+ *
+ * @codec: CODEC to configure.
+ * @reg: The register index.
+ * @value: The value to be returned.
+ */
+int snd_soc_cache_read(struct snd_soc_codec *codec,
+		       unsigned int reg, unsigned int *value)
+{
+	if (!value)
+		return -EINVAL;
+
+	mutex_lock(&codec->cache_rw_mutex);
+	*value = snd_soc_get_cache_val(codec->reg_cache, reg,
+				       codec->driver->reg_word_size);
+	mutex_unlock(&codec->cache_rw_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_cache_read);
+
+/**
+ * snd_soc_cache_write: Set the value of a given register in the cache.
+ *
+ * @codec: CODEC to configure.
+ * @reg: The register index.
+ * @value: The new register value.
+ */
+int snd_soc_cache_write(struct snd_soc_codec *codec,
+			unsigned int reg, unsigned int value)
+{
+	mutex_lock(&codec->cache_rw_mutex);
+	snd_soc_set_cache_val(codec->reg_cache, reg, value,
+			      codec->driver->reg_word_size);
+	mutex_unlock(&codec->cache_rw_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_cache_write);
+
 static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
 {
 	int i;
@@ -78,8 +156,8 @@
 		ret = snd_soc_cache_read(codec, i, &val);
 		if (ret)
 			return ret;
-		if (codec->reg_def_copy)
-			if (snd_soc_get_cache_val(codec->reg_def_copy,
+		if (codec_drv->reg_cache_default)
+			if (snd_soc_get_cache_val(codec_drv->reg_cache_default,
 						  i, codec_drv->reg_word_size) == val)
 				continue;
 
@@ -94,150 +172,6 @@
 	return 0;
 }
 
-static int snd_soc_flat_cache_write(struct snd_soc_codec *codec,
-				    unsigned int reg, unsigned int value)
-{
-	snd_soc_set_cache_val(codec->reg_cache, reg, value,
-			      codec->driver->reg_word_size);
-	return 0;
-}
-
-static int snd_soc_flat_cache_read(struct snd_soc_codec *codec,
-				   unsigned int reg, unsigned int *value)
-{
-	*value = snd_soc_get_cache_val(codec->reg_cache, reg,
-				       codec->driver->reg_word_size);
-	return 0;
-}
-
-static int snd_soc_flat_cache_exit(struct snd_soc_codec *codec)
-{
-	if (!codec->reg_cache)
-		return 0;
-	kfree(codec->reg_cache);
-	codec->reg_cache = NULL;
-	return 0;
-}
-
-static int snd_soc_flat_cache_init(struct snd_soc_codec *codec)
-{
-	if (codec->reg_def_copy)
-		codec->reg_cache = kmemdup(codec->reg_def_copy,
-					   codec->reg_size, GFP_KERNEL);
-	else
-		codec->reg_cache = kzalloc(codec->reg_size, GFP_KERNEL);
-	if (!codec->reg_cache)
-		return -ENOMEM;
-
-	return 0;
-}
-
-/* an array of all supported compression types */
-static const struct snd_soc_cache_ops cache_types[] = {
-	/* Flat *must* be the first entry for fallback */
-	{
-		.id = SND_SOC_FLAT_COMPRESSION,
-		.name = "flat",
-		.init = snd_soc_flat_cache_init,
-		.exit = snd_soc_flat_cache_exit,
-		.read = snd_soc_flat_cache_read,
-		.write = snd_soc_flat_cache_write,
-		.sync = snd_soc_flat_cache_sync
-	},
-};
-
-int snd_soc_cache_init(struct snd_soc_codec *codec)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(cache_types); ++i)
-		if (cache_types[i].id == codec->compress_type)
-			break;
-
-	/* Fall back to flat compression */
-	if (i == ARRAY_SIZE(cache_types)) {
-		dev_warn(codec->dev, "ASoC: Could not match compress type: %d\n",
-			 codec->compress_type);
-		i = 0;
-	}
-
-	mutex_init(&codec->cache_rw_mutex);
-	codec->cache_ops = &cache_types[i];
-
-	if (codec->cache_ops->init) {
-		if (codec->cache_ops->name)
-			dev_dbg(codec->dev, "ASoC: Initializing %s cache for %s codec\n",
-				codec->cache_ops->name, codec->name);
-		return codec->cache_ops->init(codec);
-	}
-	return -ENOSYS;
-}
-
-/*
- * NOTE: keep in mind that this function might be called
- * multiple times.
- */
-int snd_soc_cache_exit(struct snd_soc_codec *codec)
-{
-	if (codec->cache_ops && codec->cache_ops->exit) {
-		if (codec->cache_ops->name)
-			dev_dbg(codec->dev, "ASoC: Destroying %s cache for %s codec\n",
-				codec->cache_ops->name, codec->name);
-		return codec->cache_ops->exit(codec);
-	}
-	return -ENOSYS;
-}
-
-/**
- * snd_soc_cache_read: Fetch the value of a given register from the cache.
- *
- * @codec: CODEC to configure.
- * @reg: The register index.
- * @value: The value to be returned.
- */
-int snd_soc_cache_read(struct snd_soc_codec *codec,
-		       unsigned int reg, unsigned int *value)
-{
-	int ret;
-
-	mutex_lock(&codec->cache_rw_mutex);
-
-	if (value && codec->cache_ops && codec->cache_ops->read) {
-		ret = codec->cache_ops->read(codec, reg, value);
-		mutex_unlock(&codec->cache_rw_mutex);
-		return ret;
-	}
-
-	mutex_unlock(&codec->cache_rw_mutex);
-	return -ENOSYS;
-}
-EXPORT_SYMBOL_GPL(snd_soc_cache_read);
-
-/**
- * snd_soc_cache_write: Set the value of a given register in the cache.
- *
- * @codec: CODEC to configure.
- * @reg: The register index.
- * @value: The new register value.
- */
-int snd_soc_cache_write(struct snd_soc_codec *codec,
-			unsigned int reg, unsigned int value)
-{
-	int ret;
-
-	mutex_lock(&codec->cache_rw_mutex);
-
-	if (codec->cache_ops && codec->cache_ops->write) {
-		ret = codec->cache_ops->write(codec, reg, value);
-		mutex_unlock(&codec->cache_rw_mutex);
-		return ret;
-	}
-
-	mutex_unlock(&codec->cache_rw_mutex);
-	return -ENOSYS;
-}
-EXPORT_SYMBOL_GPL(snd_soc_cache_write);
-
 /**
  * snd_soc_cache_sync: Sync the register cache with the hardware.
  *
@@ -249,92 +183,19 @@
  */
 int snd_soc_cache_sync(struct snd_soc_codec *codec)
 {
+	const char *name = "flat";
 	int ret;
-	const char *name;
 
-	if (!codec->cache_sync) {
+	if (!codec->cache_sync)
 		return 0;
-	}
 
-	if (!codec->cache_ops || !codec->cache_ops->sync)
-		return -ENOSYS;
-
-	if (codec->cache_ops->name)
-		name = codec->cache_ops->name;
-	else
-		name = "unknown";
-
-	if (codec->cache_ops->name)
-		dev_dbg(codec->dev, "ASoC: Syncing %s cache for %s codec\n",
-			codec->cache_ops->name, codec->name);
+	dev_dbg(codec->dev, "ASoC: Syncing cache for %s codec\n",
+		codec->name);
 	trace_snd_soc_cache_sync(codec, name, "start");
-	ret = codec->cache_ops->sync(codec);
+	ret = snd_soc_flat_cache_sync(codec);
 	if (!ret)
 		codec->cache_sync = 0;
 	trace_snd_soc_cache_sync(codec, name, "end");
 	return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_cache_sync);
-
-static int snd_soc_get_reg_access_index(struct snd_soc_codec *codec,
-					unsigned int reg)
-{
-	const struct snd_soc_codec_driver *codec_drv;
-	unsigned int min, max, index;
-
-	codec_drv = codec->driver;
-	min = 0;
-	max = codec_drv->reg_access_size - 1;
-	do {
-		index = (min + max) / 2;
-		if (codec_drv->reg_access_default[index].reg == reg)
-			return index;
-		if (codec_drv->reg_access_default[index].reg < reg)
-			min = index + 1;
-		else
-			max = index;
-	} while (min <= max);
-	return -1;
-}
-
-int snd_soc_default_volatile_register(struct snd_soc_codec *codec,
-				      unsigned int reg)
-{
-	int index;
-
-	if (reg >= codec->driver->reg_cache_size)
-		return 1;
-	index = snd_soc_get_reg_access_index(codec, reg);
-	if (index < 0)
-		return 0;
-	return codec->driver->reg_access_default[index].vol;
-}
-EXPORT_SYMBOL_GPL(snd_soc_default_volatile_register);
-
-int snd_soc_default_readable_register(struct snd_soc_codec *codec,
-				      unsigned int reg)
-{
-	int index;
-
-	if (reg >= codec->driver->reg_cache_size)
-		return 1;
-	index = snd_soc_get_reg_access_index(codec, reg);
-	if (index < 0)
-		return 0;
-	return codec->driver->reg_access_default[index].read;
-}
-EXPORT_SYMBOL_GPL(snd_soc_default_readable_register);
-
-int snd_soc_default_writable_register(struct snd_soc_codec *codec,
-				      unsigned int reg)
-{
-	int index;
-
-	if (reg >= codec->driver->reg_cache_size)
-		return 1;
-	index = snd_soc_get_reg_access_index(codec, reg);
-	if (index < 0)
-		return 0;
-	return codec->driver->reg_access_default[index].write;
-}
-EXPORT_SYMBOL_GPL(snd_soc_default_writable_register);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 1a38be0..4e53d87 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -662,6 +662,8 @@
 				codec->cache_sync = 1;
 				if (codec->using_regmap)
 					regcache_mark_dirty(codec->control_data);
+				/* deactivate pins to sleep state */
+				pinctrl_pm_select_sleep_state(codec->dev);
 				break;
 			default:
 				dev_dbg(codec->dev,
@@ -679,6 +681,9 @@
 
 		if (cpu_dai->driver->suspend && cpu_dai->driver->ac97_control)
 			cpu_dai->driver->suspend(cpu_dai);
+
+		/* deactivate pins to sleep state */
+		pinctrl_pm_select_sleep_state(cpu_dai->dev);
 	}
 
 	if (card->suspend_post)
@@ -807,6 +812,16 @@
 	if (list_empty(&card->codec_dev_list))
 		return 0;
 
+	/* activate pins from sleep state */
+	for (i = 0; i < card->num_rtd; i++) {
+		struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
+		struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
+		if (cpu_dai->active)
+			pinctrl_pm_select_default_state(cpu_dai->dev);
+		if (codec_dai->active)
+			pinctrl_pm_select_default_state(codec_dai->dev);
+	}
+
 	/* AC97 devices might have other drivers hanging off them so
 	 * need to resume immediately.  Other drivers don't have that
 	 * problem and may take a substantial amount of time to resume
@@ -1589,17 +1604,13 @@
 		soc_remove_codec(codec);
 }
 
-static int snd_soc_init_codec_cache(struct snd_soc_codec *codec,
-				    enum snd_soc_compress_type compress_type)
+static int snd_soc_init_codec_cache(struct snd_soc_codec *codec)
 {
 	int ret;
 
 	if (codec->cache_init)
 		return 0;
 
-	/* override the compress_type if necessary */
-	if (compress_type && codec->compress_type != compress_type)
-		codec->compress_type = compress_type;
 	ret = snd_soc_cache_init(codec);
 	if (ret < 0) {
 		dev_err(codec->dev,
@@ -1614,8 +1625,6 @@
 static int snd_soc_instantiate_card(struct snd_soc_card *card)
 {
 	struct snd_soc_codec *codec;
-	struct snd_soc_codec_conf *codec_conf;
-	enum snd_soc_compress_type compress_type;
 	struct snd_soc_dai_link *dai_link;
 	int ret, i, order, dai_fmt;
 
@@ -1639,19 +1648,7 @@
 	list_for_each_entry(codec, &codec_list, list) {
 		if (codec->cache_init)
 			continue;
-		/* by default we don't override the compress_type */
-		compress_type = 0;
-		/* check to see if we need to override the compress_type */
-		for (i = 0; i < card->num_configs; ++i) {
-			codec_conf = &card->codec_conf[i];
-			if (!strcmp(codec->name, codec_conf->dev_name)) {
-				compress_type = codec_conf->compress_type;
-				if (compress_type && compress_type
-				    != codec->compress_type)
-					break;
-			}
-		}
-		ret = snd_soc_init_codec_cache(codec, compress_type);
+		ret = snd_soc_init_codec_cache(codec);
 		if (ret < 0)
 			goto base_error;
 	}
@@ -1947,6 +1944,14 @@
 
 	snd_soc_dapm_shutdown(card);
 
+	/* deactivate pins to sleep state */
+	for (i = 0; i < card->num_rtd; i++) {
+		struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
+		struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
+		pinctrl_pm_select_sleep_state(codec_dai->dev);
+		pinctrl_pm_select_sleep_state(cpu_dai->dev);
+	}
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(snd_soc_poweroff);
@@ -2297,13 +2302,6 @@
 }
 EXPORT_SYMBOL_GPL(snd_soc_write);
 
-unsigned int snd_soc_bulk_write_raw(struct snd_soc_codec *codec,
-				    unsigned int reg, const void *data, size_t len)
-{
-	return codec->bulk_write_raw(codec, reg, data, len);
-}
-EXPORT_SYMBOL_GPL(snd_soc_bulk_write_raw);
-
 /**
  * snd_soc_update_bits - update codec register bits
  * @codec: audio codec
@@ -2576,8 +2574,9 @@
 
 	if (uinfo->value.enumerated.item > e->max - 1)
 		uinfo->value.enumerated.item = e->max - 1;
-	strcpy(uinfo->value.enumerated.name,
-		e->texts[uinfo->value.enumerated.item]);
+	strlcpy(uinfo->value.enumerated.name,
+		e->texts[uinfo->value.enumerated.item],
+		sizeof(uinfo->value.enumerated.name));
 	return 0;
 }
 EXPORT_SYMBOL_GPL(snd_soc_info_enum_double);
@@ -3576,6 +3575,22 @@
 EXPORT_SYMBOL_GPL(snd_soc_codec_set_pll);
 
 /**
+ * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio.
+ * @dai: DAI
+ * @ratio Ratio of BCLK to Sample rate.
+ *
+ * Configures the DAI for a preset BCLK to sample rate ratio.
+ */
+int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
+{
+	if (dai->driver && dai->driver->ops->set_bclk_ratio)
+		return dai->driver->ops->set_bclk_ratio(dai, ratio);
+	else
+		return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio);
+
+/**
  * snd_soc_dai_set_fmt - configure DAI hardware audio format.
  * @dai: DAI
  * @fmt: SND_SOC_DAIFMT_ format value.
@@ -3775,6 +3790,16 @@
 	if (ret != 0)
 		soc_cleanup_card_debugfs(card);
 
+	/* deactivate pins to sleep state */
+	for (i = 0; i < card->num_rtd; i++) {
+		struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
+		struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
+		if (!codec_dai->active)
+			pinctrl_pm_select_sleep_state(codec_dai->dev);
+		if (!cpu_dai->active)
+			pinctrl_pm_select_sleep_state(cpu_dai->dev);
+	}
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_register_card);
@@ -4020,6 +4045,113 @@
 }
 
 /**
+ * snd_soc_register_component - Register a component with the ASoC core
+ *
+ */
+static int
+__snd_soc_register_component(struct device *dev,
+			     struct snd_soc_component *cmpnt,
+			     const struct snd_soc_component_driver *cmpnt_drv,
+			     struct snd_soc_dai_driver *dai_drv,
+			     int num_dai, bool allow_single_dai)
+{
+	int ret;
+
+	dev_dbg(dev, "component register %s\n", dev_name(dev));
+
+	if (!cmpnt) {
+		dev_err(dev, "ASoC: Failed to connecting component\n");
+		return -ENOMEM;
+	}
+
+	cmpnt->name = fmt_single_name(dev, &cmpnt->id);
+	if (!cmpnt->name) {
+		dev_err(dev, "ASoC: Failed to simplifying name\n");
+		return -ENOMEM;
+	}
+
+	cmpnt->dev	= dev;
+	cmpnt->driver	= cmpnt_drv;
+	cmpnt->dai_drv	= dai_drv;
+	cmpnt->num_dai	= num_dai;
+
+	/*
+	 * snd_soc_register_dai()  uses fmt_single_name(), and
+	 * snd_soc_register_dais() uses fmt_multiple_name()
+	 * for dai->name which is used for name based matching
+	 *
+	 * this function is used from cpu/codec.
+	 * allow_single_dai flag can ignore "codec" driver reworking
+	 * since it had been used snd_soc_register_dais(),
+	 */
+	if ((1 == num_dai) && allow_single_dai)
+		ret = snd_soc_register_dai(dev, dai_drv);
+	else
+		ret = snd_soc_register_dais(dev, dai_drv, num_dai);
+	if (ret < 0) {
+		dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
+		goto error_component_name;
+	}
+
+	mutex_lock(&client_mutex);
+	list_add(&cmpnt->list, &component_list);
+	mutex_unlock(&client_mutex);
+
+	dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name);
+
+	return ret;
+
+error_component_name:
+	kfree(cmpnt->name);
+
+	return ret;
+}
+
+int snd_soc_register_component(struct device *dev,
+			       const struct snd_soc_component_driver *cmpnt_drv,
+			       struct snd_soc_dai_driver *dai_drv,
+			       int num_dai)
+{
+	struct snd_soc_component *cmpnt;
+
+	cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL);
+	if (!cmpnt) {
+		dev_err(dev, "ASoC: Failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	return __snd_soc_register_component(dev, cmpnt, cmpnt_drv,
+					    dai_drv, num_dai, true);
+}
+EXPORT_SYMBOL_GPL(snd_soc_register_component);
+
+/**
+ * snd_soc_unregister_component - Unregister a component from the ASoC core
+ *
+ */
+void snd_soc_unregister_component(struct device *dev)
+{
+	struct snd_soc_component *cmpnt;
+
+	list_for_each_entry(cmpnt, &component_list, list) {
+		if (dev == cmpnt->dev)
+			goto found;
+	}
+	return;
+
+found:
+	snd_soc_unregister_dais(dev, cmpnt->num_dai);
+
+	mutex_lock(&client_mutex);
+	list_del(&cmpnt->list);
+	mutex_unlock(&client_mutex);
+
+	dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name);
+	kfree(cmpnt->name);
+}
+EXPORT_SYMBOL_GPL(snd_soc_unregister_component);
+
+/**
  * snd_soc_add_platform - Add a platform to the ASoC core
  * @dev: The parent device for the platform
  * @platform: The platform to add
@@ -4165,7 +4297,6 @@
 			   struct snd_soc_dai_driver *dai_drv,
 			   int num_dai)
 {
-	size_t reg_size;
 	struct snd_soc_codec *codec;
 	int ret, i;
 
@@ -4182,11 +4313,6 @@
 		goto fail_codec;
 	}
 
-	if (codec_drv->compress_type)
-		codec->compress_type = codec_drv->compress_type;
-	else
-		codec->compress_type = SND_SOC_FLAT_COMPRESSION;
-
 	codec->write = codec_drv->write;
 	codec->read = codec_drv->read;
 	codec->volatile_register = codec_drv->volatile_register;
@@ -4203,35 +4329,6 @@
 	codec->num_dai = num_dai;
 	mutex_init(&codec->mutex);
 
-	/* allocate CODEC register cache */
-	if (codec_drv->reg_cache_size && codec_drv->reg_word_size) {
-		reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
-		codec->reg_size = reg_size;
-		/* it is necessary to make a copy of the default register cache
-		 * because in the case of using a compression type that requires
-		 * the default register cache to be marked as the
-		 * kernel might have freed the array by the time we initialize
-		 * the cache.
-		 */
-		if (codec_drv->reg_cache_default) {
-			codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default,
-						      reg_size, GFP_KERNEL);
-			if (!codec->reg_def_copy) {
-				ret = -ENOMEM;
-				goto fail_codec_name;
-			}
-		}
-	}
-
-	if (codec_drv->reg_access_size && codec_drv->reg_access_default) {
-		if (!codec->volatile_register)
-			codec->volatile_register = snd_soc_default_volatile_register;
-		if (!codec->readable_register)
-			codec->readable_register = snd_soc_default_readable_register;
-		if (!codec->writable_register)
-			codec->writable_register = snd_soc_default_writable_register;
-	}
-
 	for (i = 0; i < num_dai; i++) {
 		fixup_codec_formats(&dai_drv[i].playback);
 		fixup_codec_formats(&dai_drv[i].capture);
@@ -4241,10 +4338,12 @@
 	list_add(&codec->list, &codec_list);
 	mutex_unlock(&client_mutex);
 
-	/* register any DAIs */
-	ret = snd_soc_register_dais(dev, dai_drv, num_dai);
+	/* register component */
+	ret = __snd_soc_register_component(dev, &codec->component,
+					   &codec_drv->component_driver,
+					   dai_drv, num_dai, false);
 	if (ret < 0) {
-		dev_err(codec->dev, "ASoC: Failed to regster DAIs: %d\n", ret);
+		dev_err(codec->dev, "ASoC: Failed to regster component: %d\n", ret);
 		goto fail_codec_name;
 	}
 
@@ -4279,7 +4378,7 @@
 	return;
 
 found:
-	snd_soc_unregister_dais(dev, codec->num_dai);
+	snd_soc_unregister_component(dev);
 
 	mutex_lock(&client_mutex);
 	list_del(&codec->list);
@@ -4288,98 +4387,11 @@
 	dev_dbg(codec->dev, "ASoC: Unregistered codec '%s'\n", codec->name);
 
 	snd_soc_cache_exit(codec);
-	kfree(codec->reg_def_copy);
 	kfree(codec->name);
 	kfree(codec);
 }
 EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
 
-
-/**
- * snd_soc_register_component - Register a component with the ASoC core
- *
- */
-int snd_soc_register_component(struct device *dev,
-			 const struct snd_soc_component_driver *cmpnt_drv,
-			 struct snd_soc_dai_driver *dai_drv,
-			 int num_dai)
-{
-	struct snd_soc_component *cmpnt;
-	int ret;
-
-	dev_dbg(dev, "component register %s\n", dev_name(dev));
-
-	cmpnt = devm_kzalloc(dev, sizeof(*cmpnt), GFP_KERNEL);
-	if (!cmpnt) {
-		dev_err(dev, "ASoC: Failed to allocate memory\n");
-		return -ENOMEM;
-	}
-
-	cmpnt->name = fmt_single_name(dev, &cmpnt->id);
-	if (!cmpnt->name) {
-		dev_err(dev, "ASoC: Failed to simplifying name\n");
-		return -ENOMEM;
-	}
-
-	cmpnt->dev	= dev;
-	cmpnt->driver	= cmpnt_drv;
-	cmpnt->num_dai	= num_dai;
-
-	/*
-	 * snd_soc_register_dai()  uses fmt_single_name(), and
-	 * snd_soc_register_dais() uses fmt_multiple_name()
-	 * for dai->name which is used for name based matching
-	 */
-	if (1 == num_dai)
-		ret = snd_soc_register_dai(dev, dai_drv);
-	else
-		ret = snd_soc_register_dais(dev, dai_drv, num_dai);
-	if (ret < 0) {
-		dev_err(dev, "ASoC: Failed to regster DAIs: %d\n", ret);
-		goto error_component_name;
-	}
-
-	mutex_lock(&client_mutex);
-	list_add(&cmpnt->list, &component_list);
-	mutex_unlock(&client_mutex);
-
-	dev_dbg(cmpnt->dev, "ASoC: Registered component '%s'\n", cmpnt->name);
-
-	return ret;
-
-error_component_name:
-	kfree(cmpnt->name);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(snd_soc_register_component);
-
-/**
- * snd_soc_unregister_component - Unregister a component from the ASoC core
- *
- */
-void snd_soc_unregister_component(struct device *dev)
-{
-	struct snd_soc_component *cmpnt;
-
-	list_for_each_entry(cmpnt, &component_list, list) {
-		if (dev == cmpnt->dev)
-			goto found;
-	}
-	return;
-
-found:
-	snd_soc_unregister_dais(dev, cmpnt->num_dai);
-
-	mutex_lock(&client_mutex);
-	list_del(&cmpnt->list);
-	mutex_unlock(&client_mutex);
-
-	dev_dbg(dev, "ASoC: Unregistered component '%s'\n", cmpnt->name);
-	kfree(cmpnt->name);
-}
-EXPORT_SYMBOL_GPL(snd_soc_unregister_component);
-
 /* Retrieve a card's name from device tree */
 int snd_soc_of_parse_card_name(struct snd_soc_card *card,
 			       const char *propname)
@@ -4567,6 +4579,60 @@
 }
 EXPORT_SYMBOL_GPL(snd_soc_of_parse_daifmt);
 
+int snd_soc_of_get_dai_name(struct device_node *of_node,
+			    const char **dai_name)
+{
+	struct snd_soc_component *pos;
+	struct of_phandle_args args;
+	int ret;
+
+	ret = of_parse_phandle_with_args(of_node, "sound-dai",
+					 "#sound-dai-cells", 0, &args);
+	if (ret)
+		return ret;
+
+	ret = -EPROBE_DEFER;
+
+	mutex_lock(&client_mutex);
+	list_for_each_entry(pos, &component_list, list) {
+		if (pos->dev->of_node != args.np)
+			continue;
+
+		if (pos->driver->of_xlate_dai_name) {
+			ret = pos->driver->of_xlate_dai_name(pos, &args, dai_name);
+		} else {
+			int id = -1;
+
+			switch (args.args_count) {
+			case 0:
+				id = 0; /* same as dai_drv[0] */
+				break;
+			case 1:
+				id = args.args[0];
+				break;
+			default:
+				/* not supported */
+				break;
+			}
+
+			if (id < 0 || id >= pos->num_dai) {
+				ret = -EINVAL;
+			} else {
+				*dai_name = pos->dai_drv[id].name;
+				ret = 0;
+			}
+		}
+
+		break;
+	}
+	mutex_unlock(&client_mutex);
+
+	of_node_put(args.np);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_of_get_dai_name);
+
 static int __init snd_soc_init(void)
 {
 #ifdef CONFIG_DEBUG_FS
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index c17c14c..dcade13 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -59,31 +59,31 @@
 /* dapm power sequences - make this per codec in the future */
 static int dapm_up_seq[] = {
 	[snd_soc_dapm_pre] = 0,
-	[snd_soc_dapm_supply] = 1,
 	[snd_soc_dapm_regulator_supply] = 1,
 	[snd_soc_dapm_clock_supply] = 1,
-	[snd_soc_dapm_micbias] = 2,
+	[snd_soc_dapm_supply] = 2,
+	[snd_soc_dapm_micbias] = 3,
 	[snd_soc_dapm_dai_link] = 2,
-	[snd_soc_dapm_dai_in] = 3,
-	[snd_soc_dapm_dai_out] = 3,
-	[snd_soc_dapm_aif_in] = 3,
-	[snd_soc_dapm_aif_out] = 3,
-	[snd_soc_dapm_mic] = 4,
-	[snd_soc_dapm_mux] = 5,
-	[snd_soc_dapm_virt_mux] = 5,
-	[snd_soc_dapm_value_mux] = 5,
-	[snd_soc_dapm_dac] = 6,
-	[snd_soc_dapm_switch] = 7,
-	[snd_soc_dapm_mixer] = 7,
-	[snd_soc_dapm_mixer_named_ctl] = 7,
-	[snd_soc_dapm_pga] = 8,
-	[snd_soc_dapm_adc] = 9,
-	[snd_soc_dapm_out_drv] = 10,
-	[snd_soc_dapm_hp] = 10,
-	[snd_soc_dapm_spk] = 10,
-	[snd_soc_dapm_line] = 10,
-	[snd_soc_dapm_kcontrol] = 11,
-	[snd_soc_dapm_post] = 12,
+	[snd_soc_dapm_dai_in] = 4,
+	[snd_soc_dapm_dai_out] = 4,
+	[snd_soc_dapm_aif_in] = 4,
+	[snd_soc_dapm_aif_out] = 4,
+	[snd_soc_dapm_mic] = 5,
+	[snd_soc_dapm_mux] = 6,
+	[snd_soc_dapm_virt_mux] = 6,
+	[snd_soc_dapm_value_mux] = 6,
+	[snd_soc_dapm_dac] = 7,
+	[snd_soc_dapm_switch] = 8,
+	[snd_soc_dapm_mixer] = 8,
+	[snd_soc_dapm_mixer_named_ctl] = 8,
+	[snd_soc_dapm_pga] = 9,
+	[snd_soc_dapm_adc] = 10,
+	[snd_soc_dapm_out_drv] = 11,
+	[snd_soc_dapm_hp] = 11,
+	[snd_soc_dapm_spk] = 11,
+	[snd_soc_dapm_line] = 11,
+	[snd_soc_dapm_kcontrol] = 12,
+	[snd_soc_dapm_post] = 13,
 };
 
 static int dapm_down_seq[] = {
@@ -109,10 +109,10 @@
 	[snd_soc_dapm_dai_in] = 10,
 	[snd_soc_dapm_dai_out] = 10,
 	[snd_soc_dapm_dai_link] = 11,
-	[snd_soc_dapm_clock_supply] = 12,
-	[snd_soc_dapm_regulator_supply] = 12,
 	[snd_soc_dapm_supply] = 12,
-	[snd_soc_dapm_post] = 13,
+	[snd_soc_dapm_clock_supply] = 13,
+	[snd_soc_dapm_regulator_supply] = 13,
+	[snd_soc_dapm_post] = 14,
 };
 
 static void pop_wait(u32 pop_time)
@@ -409,6 +409,12 @@
 		mutex_unlock(&w->platform->mutex);
 }
 
+static void soc_dapm_async_complete(struct snd_soc_dapm_context *dapm)
+{
+	if (dapm->codec && dapm->codec->using_regmap)
+		regmap_async_complete(dapm->codec->control_data);
+}
+
 static int soc_widget_update_bits_locked(struct snd_soc_dapm_widget *w,
 	unsigned short reg, unsigned int mask, unsigned int value)
 {
@@ -417,8 +423,9 @@
 	int ret;
 
 	if (w->codec && w->codec->using_regmap) {
-		ret = regmap_update_bits_check(w->codec->control_data,
-					       reg, mask, value, &change);
+		ret = regmap_update_bits_check_async(w->codec->control_data,
+						     reg, mask, value,
+						     &change);
 		if (ret != 0)
 			return ret;
 	} else {
@@ -499,18 +506,22 @@
 		int val;
 		struct soc_mixer_control *mc = (struct soc_mixer_control *)
 			w->kcontrol_news[i].private_value;
-		unsigned int reg = mc->reg;
+		int reg = mc->reg;
 		unsigned int shift = mc->shift;
 		int max = mc->max;
 		unsigned int mask = (1 << fls(max)) - 1;
 		unsigned int invert = mc->invert;
 
-		val = soc_widget_read(w, reg);
-		val = (val >> shift) & mask;
-		if (invert)
-			val = max - val;
+		if (reg != SND_SOC_NOPM) {
+			val = soc_widget_read(w, reg);
+			val = (val >> shift) & mask;
+			if (invert)
+				val = max - val;
+			p->connect = !!val;
+		} else {
+			p->connect = 0;
+		}
 
-		p->connect = !!val;
 	}
 	break;
 	case snd_soc_dapm_mux: {
@@ -1197,6 +1208,8 @@
 {
 	int ret;
 
+	soc_dapm_async_complete(w->dapm);
+
 	if (SND_SOC_DAPM_EVENT_ON(event)) {
 		if (w->on_val & SND_SOC_DAPM_REGULATOR_BYPASS) {
 			ret = regulator_allow_bypass(w->regulator, false);
@@ -1230,6 +1243,8 @@
 	if (!w->clk)
 		return -EIO;
 
+	soc_dapm_async_complete(w->dapm);
+
 #ifdef CONFIG_HAVE_CLK
 	if (SND_SOC_DAPM_EVENT_ON(event)) {
 		return clk_prepare_enable(w->clk);
@@ -1412,7 +1427,7 @@
 		power = 0;
 		break;
 	default:
-		BUG();
+		WARN(1, "Unknown event %d\n", event);
 		return;
 	}
 
@@ -1422,6 +1437,7 @@
 	if (w->event && (w->event_flags & event)) {
 		pop_dbg(w->dapm->dev, card->pop_time, "pop test : %s %s\n",
 			w->name, ev_name);
+		soc_dapm_async_complete(w->dapm);
 		trace_snd_soc_dapm_widget_event_start(w, event);
 		ret = w->event(w, NULL, event);
 		trace_snd_soc_dapm_widget_event_done(w, event);
@@ -1444,7 +1460,7 @@
 			       power_list)->reg;
 
 	list_for_each_entry(w, pending, power_list) {
-		BUG_ON(reg != w->reg);
+		WARN_ON(reg != w->reg);
 		w->power = w->new_power;
 
 		mask |= w->mask << w->shift;
@@ -1494,6 +1510,7 @@
 	struct list_head *list, int event, bool power_up)
 {
 	struct snd_soc_dapm_widget *w, *n;
+	struct snd_soc_dapm_context *d;
 	LIST_HEAD(pending);
 	int cur_sort = -1;
 	int cur_subseq = -1;
@@ -1524,6 +1541,9 @@
 								       cur_subseq);
 			}
 
+			if (cur_dapm && w->dapm != cur_dapm)
+				soc_dapm_async_complete(cur_dapm);
+
 			INIT_LIST_HEAD(&pending);
 			cur_sort = -1;
 			cur_subseq = INT_MIN;
@@ -1582,6 +1602,10 @@
 				cur_dapm->seq_notifier(cur_dapm,
 						       i, cur_subseq);
 	}
+
+	list_for_each_entry(d, &card->dapm_list, list) {
+		soc_dapm_async_complete(d);
+	}
 }
 
 static void dapm_widget_update(struct snd_soc_card *card)
@@ -1840,6 +1864,7 @@
 			 */
 			switch (w->id) {
 			case snd_soc_dapm_siggen:
+			case snd_soc_dapm_vmid:
 				break;
 			case snd_soc_dapm_supply:
 			case snd_soc_dapm_regulator_supply:
@@ -1949,7 +1974,7 @@
 				w->active ? "active" : "inactive");
 
 	list_for_each_entry(p, &w->sources, list_sink) {
-		if (p->connected && !p->connected(w, p->sink))
+		if (p->connected && !p->connected(w, p->source))
 			continue;
 
 		if (p->connect)
@@ -2001,7 +2026,7 @@
 		level = "Off\n";
 		break;
 	default:
-		BUG();
+		WARN(1, "Unknown bias_level %d\n", dapm->bias_level);
 		level = "Unknown\n";
 		break;
 	}
@@ -2791,7 +2816,7 @@
 	struct snd_soc_card *card = codec->card;
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
-	unsigned int reg = mc->reg;
+	int reg = mc->reg;
 	unsigned int shift = mc->shift;
 	int max = mc->max;
 	unsigned int mask = (1 << fls(max)) - 1;
@@ -2804,7 +2829,7 @@
 			 kcontrol->id.name);
 
 	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
-	if (dapm_kcontrol_is_powered(kcontrol))
+	if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM)
 		val = (snd_soc_read(codec, reg) >> shift) & mask;
 	else
 		val = dapm_kcontrol_get_value(kcontrol);
@@ -2835,7 +2860,7 @@
 	struct snd_soc_card *card = codec->card;
 	struct soc_mixer_control *mc =
 		(struct soc_mixer_control *)kcontrol->private_value;
-	unsigned int reg = mc->reg;
+	int reg = mc->reg;
 	unsigned int shift = mc->shift;
 	int max = mc->max;
 	unsigned int mask = (1 << fls(max)) - 1;
@@ -2857,19 +2882,24 @@
 
 	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
 
-	dapm_kcontrol_set_value(kcontrol, val);
+	change = dapm_kcontrol_set_value(kcontrol, val);
 
-	mask = mask << shift;
-	val = val << shift;
+	if (reg != SND_SOC_NOPM) {
+		mask = mask << shift;
+		val = val << shift;
 
-	change = snd_soc_test_bits(codec, reg, mask, val);
+		change = snd_soc_test_bits(codec, reg, mask, val);
+	}
+
 	if (change) {
-		update.kcontrol = kcontrol;
-		update.reg = reg;
-		update.mask = mask;
-		update.val = val;
+		if (reg != SND_SOC_NOPM) {
+			update.kcontrol = kcontrol;
+			update.reg = reg;
+			update.mask = mask;
+			update.val = val;
 
-		card->update = &update;
+			card->update = &update;
+		}
 
 		soc_dapm_mixer_update_power(card, kcontrol, connect);
 
@@ -3329,8 +3359,9 @@
 	u64 fmt;
 	int ret;
 
-	BUG_ON(!config);
-	BUG_ON(list_empty(&w->sources) || list_empty(&w->sinks));
+	if (WARN_ON(!config) ||
+	    WARN_ON(list_empty(&w->sources) || list_empty(&w->sinks)))
+		return -EINVAL;
 
 	/* We only support a single source and sink, pick the first */
 	source_p = list_first_entry(&w->sources, struct snd_soc_dapm_path,
@@ -3338,9 +3369,10 @@
 	sink_p = list_first_entry(&w->sinks, struct snd_soc_dapm_path,
 				  list_source);
 
-	BUG_ON(!source_p || !sink_p);
-	BUG_ON(!sink_p->source || !source_p->sink);
-	BUG_ON(!source_p->source || !sink_p->sink);
+	if (WARN_ON(!source_p || !sink_p) ||
+	    WARN_ON(!sink_p->source || !source_p->sink) ||
+	    WARN_ON(!source_p->source || !sink_p->sink))
+		return -EINVAL;
 
 	source = source_p->source->priv;
 	sink = sink_p->sink->priv;
@@ -3416,7 +3448,7 @@
 		break;
 
 	default:
-		BUG();
+		WARN(1, "Unknown event %d\n", event);
 		return -EINVAL;
 	}
 
@@ -3495,6 +3527,7 @@
 		if (!w) {
 			dev_err(dapm->dev, "ASoC: Failed to create %s widget\n",
 				dai->driver->playback.stream_name);
+			return -ENOMEM;
 		}
 
 		w->priv = dai;
@@ -3513,6 +3546,7 @@
 		if (!w) {
 			dev_err(dapm->dev, "ASoC: Failed to create %s widget\n",
 				dai->driver->capture.stream_name);
+			return -ENOMEM;
 		}
 
 		w->priv = dai;
diff --git a/sound/soc/soc-devres.c b/sound/soc/soc-devres.c
new file mode 100644
index 0000000..b1d7322
--- /dev/null
+++ b/sound/soc/soc-devres.c
@@ -0,0 +1,86 @@
+/*
+ * soc-devres.c  --  ALSA SoC Audio Layer devres functions
+ *
+ * Copyright (C) 2013 Linaro Ltd
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <sound/soc.h>
+
+static void devm_component_release(struct device *dev, void *res)
+{
+	snd_soc_unregister_component(*(struct device **)res);
+}
+
+/**
+ * devm_snd_soc_register_component - resource managed component registration
+ * @dev: Device used to manage component
+ * @cmpnt_drv: Component driver
+ * @dai_drv: DAI driver
+ * @num_dai: Number of DAIs to register
+ *
+ * Register a component with automatic unregistration when the device is
+ * unregistered.
+ */
+int devm_snd_soc_register_component(struct device *dev,
+			 const struct snd_soc_component_driver *cmpnt_drv,
+			 struct snd_soc_dai_driver *dai_drv, int num_dai)
+{
+	struct device **ptr;
+	int ret;
+
+	ptr = devres_alloc(devm_component_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return -ENOMEM;
+
+	ret = snd_soc_register_component(dev, cmpnt_drv, dai_drv, num_dai);
+	if (ret == 0) {
+		*ptr = dev;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(devm_snd_soc_register_component);
+
+static void devm_card_release(struct device *dev, void *res)
+{
+	snd_soc_unregister_card(*(struct snd_soc_card **)res);
+}
+
+/**
+ * devm_snd_soc_register_card - resource managed card registration
+ * @dev: Device used to manage card
+ * @card: Card to register
+ *
+ * Register a card with automatic unregistration when the device is
+ * unregistered.
+ */
+int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card)
+{
+	struct device **ptr;
+	int ret;
+
+	ptr = devres_alloc(devm_card_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return -ENOMEM;
+
+	ret = snd_soc_register_card(card);
+	if (ret == 0) {
+		*ptr = dev;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(devm_snd_soc_register_card);
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c
index e29ec3c..cbc9c96 100644
--- a/sound/soc/soc-generic-dmaengine-pcm.c
+++ b/sound/soc/soc-generic-dmaengine-pcm.c
@@ -25,7 +25,7 @@
 #include <sound/dmaengine_pcm.h>
 
 struct dmaengine_pcm {
-	struct dma_chan *chan[SNDRV_PCM_STREAM_CAPTURE + 1];
+	struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1];
 	const struct snd_dmaengine_pcm_config *config;
 	struct snd_soc_platform platform;
 	unsigned int flags;
@@ -36,6 +36,15 @@
 	return container_of(p, struct dmaengine_pcm, platform);
 }
 
+static struct device *dmaengine_dma_dev(struct dmaengine_pcm *pcm,
+	struct snd_pcm_substream *substream)
+{
+	if (!pcm->chan[substream->stream])
+		return NULL;
+
+	return pcm->chan[substream->stream]->device->dev;
+}
+
 /**
  * snd_dmaengine_pcm_prepare_slave_config() - Generic prepare_slave_config callback
  * @substream: PCM substream
@@ -75,12 +84,21 @@
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
 	struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
+	int (*prepare_slave_config)(struct snd_pcm_substream *substream,
+			struct snd_pcm_hw_params *params,
+			struct dma_slave_config *slave_config);
 	struct dma_slave_config slave_config;
 	int ret;
 
-	if (pcm->config->prepare_slave_config) {
-		ret = pcm->config->prepare_slave_config(substream, params,
-				&slave_config);
+	memset(&slave_config, 0, sizeof(slave_config));
+
+	if (!pcm->config)
+		prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config;
+	else
+		prepare_slave_config = pcm->config->prepare_slave_config;
+
+	if (prepare_slave_config) {
+		ret = prepare_slave_config(substream, params, &slave_config);
 		if (ret)
 			return ret;
 
@@ -92,6 +110,42 @@
 	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
 }
 
+static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
+	struct device *dma_dev = dmaengine_dma_dev(pcm, substream);
+	struct dma_chan *chan = pcm->chan[substream->stream];
+	struct snd_dmaengine_dai_dma_data *dma_data;
+	struct dma_slave_caps dma_caps;
+	struct snd_pcm_hardware hw;
+	int ret;
+
+	if (pcm->config && pcm->config->pcm_hardware)
+		return snd_soc_set_runtime_hwparams(substream,
+				pcm->config->pcm_hardware);
+
+	dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+
+	memset(&hw, 0, sizeof(hw));
+	hw.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+			SNDRV_PCM_INFO_INTERLEAVED;
+	hw.periods_min = 2;
+	hw.periods_max = UINT_MAX;
+	hw.period_bytes_min = 256;
+	hw.period_bytes_max = dma_get_max_seg_size(dma_dev);
+	hw.buffer_bytes_max = SIZE_MAX;
+	hw.fifo_size = dma_data->fifo_size;
+
+	ret = dma_get_slave_caps(chan, &dma_caps);
+	if (ret == 0) {
+		if (dma_caps.cmd_pause)
+			hw.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME;
+	}
+
+	return snd_soc_set_runtime_hwparams(substream, &hw);
+}
+
 static int dmaengine_pcm_open(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -99,23 +153,13 @@
 	struct dma_chan *chan = pcm->chan[substream->stream];
 	int ret;
 
-	ret = snd_soc_set_runtime_hwparams(substream,
-				pcm->config->pcm_hardware);
+	ret = dmaengine_pcm_set_runtime_hwparams(substream);
 	if (ret)
 		return ret;
 
 	return snd_dmaengine_pcm_open(substream, chan);
 }
 
-static struct device *dmaengine_dma_dev(struct dmaengine_pcm *pcm,
-	struct snd_pcm_substream *substream)
-{
-	if (!pcm->chan[substream->stream])
-		return NULL;
-
-	return pcm->chan[substream->stream]->device->dev;
-}
-
 static void dmaengine_pcm_free(struct snd_pcm *pcm)
 {
 	snd_pcm_lib_preallocate_free_for_all(pcm);
@@ -126,6 +170,9 @@
 	struct snd_pcm_substream *substream)
 {
 	struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
+	struct snd_dmaengine_dai_dma_data *dma_data;
+
+	dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
 	if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) && pcm->chan[0])
 		return pcm->chan[0];
@@ -134,22 +181,42 @@
 		return pcm->config->compat_request_channel(rtd, substream);
 
 	return snd_dmaengine_pcm_request_channel(pcm->config->compat_filter_fn,
-		snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
+						 dma_data->filter_data);
 }
 
 static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
 	struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
 	const struct snd_dmaengine_pcm_config *config = pcm->config;
+	struct device *dev = rtd->platform->dev;
+	struct snd_dmaengine_dai_dma_data *dma_data;
 	struct snd_pcm_substream *substream;
+	size_t prealloc_buffer_size;
+	size_t max_buffer_size;
 	unsigned int i;
 	int ret;
 
+	if (config && config->prealloc_buffer_size) {
+		prealloc_buffer_size = config->prealloc_buffer_size;
+		max_buffer_size = config->pcm_hardware->buffer_bytes_max;
+	} else {
+		prealloc_buffer_size = 512 * 1024;
+		max_buffer_size = SIZE_MAX;
+	}
+
+
 	for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
 		substream = rtd->pcm->streams[i].substream;
 		if (!substream)
 			continue;
 
+		dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+
+		if (!pcm->chan[i] &&
+		    (pcm->flags & SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME))
+			pcm->chan[i] = dma_request_slave_channel(dev,
+				dma_data->chan_name);
+
 		if (!pcm->chan[i] && (pcm->flags & SND_DMAENGINE_PCM_FLAG_COMPAT)) {
 			pcm->chan[i] = dmaengine_pcm_compat_request_channel(rtd,
 				substream);
@@ -163,10 +230,10 @@
 		}
 
 		ret = snd_pcm_lib_preallocate_pages(substream,
-				SNDRV_DMA_TYPE_DEV,
+				SNDRV_DMA_TYPE_DEV_IRAM,
 				dmaengine_dma_dev(pcm, substream),
-				config->prealloc_buffer_size,
-				config->pcm_hardware->buffer_bytes_max);
+				prealloc_buffer_size,
+				max_buffer_size);
 		if (ret)
 			goto err_free;
 	}
@@ -222,7 +289,9 @@
 {
 	unsigned int i;
 
-	if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_DT) || !dev->of_node)
+	if ((pcm->flags & (SND_DMAENGINE_PCM_FLAG_NO_DT |
+			   SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) ||
+	    !dev->of_node)
 		return;
 
 	if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) {
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
index 122c0c1..4f11d23 100644
--- a/sound/soc/soc-io.c
+++ b/sound/soc/soc-io.c
@@ -65,31 +65,6 @@
 	return val;
 }
 
-/* Primitive bulk write support for soc-cache.  The data pointed to by
- * `data' needs to already be in the form the hardware expects.  Any
- * data written through this function will not go through the cache as
- * it only handles writing to volatile or out of bounds registers.
- *
- * This is currently only supported for devices using the regmap API
- * wrappers.
- */
-static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec,
-				     unsigned int reg,
-				     const void *data, size_t len)
-{
-	/* To ensure that we don't get out of sync with the cache, check
-	 * whether the base register is volatile or if we've directly asked
-	 * to bypass the cache.  Out of bounds registers are considered
-	 * volatile.
-	 */
-	if (!codec->cache_bypass
-	    && !snd_soc_codec_volatile_register(codec, reg)
-	    && reg < codec->driver->reg_cache_size)
-		return -EINVAL;
-
-	return regmap_raw_write(codec->control_data, reg, data, len);
-}
-
 /**
  * snd_soc_codec_set_cache_io: Set up standard I/O functions.
  *
@@ -119,7 +94,6 @@
 	memset(&config, 0, sizeof(config));
 	codec->write = hw_write;
 	codec->read = hw_read;
-	codec->bulk_write_raw = snd_soc_hw_bulk_write_raw;
 
 	config.reg_bits = addr_bits;
 	config.val_bits = data_bits;
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index 71358e3..23d43da 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -65,6 +65,7 @@
 	struct snd_soc_codec *codec;
 	struct snd_soc_dapm_context *dapm;
 	struct snd_soc_jack_pin *pin;
+	unsigned int sync = 0;
 	int enable;
 
 	trace_snd_soc_jack_report(jack, mask, status);
@@ -92,12 +93,16 @@
 			snd_soc_dapm_enable_pin(dapm, pin->pin);
 		else
 			snd_soc_dapm_disable_pin(dapm, pin->pin);
+
+		/* we need to sync for this case only */
+		sync = 1;
 	}
 
 	/* Report before the DAPM sync to help users updating micbias status */
 	blocking_notifier_call_chain(&jack->notifier, jack->status, jack);
 
-	snd_soc_dapm_sync(dapm);
+	if (sync)
+		snd_soc_dapm_sync(dapm);
 
 	snd_jack_report(jack->jack, jack->status);
 
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 330c9a6..42782c0 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
@@ -183,6 +184,8 @@
 	struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver;
 	int ret = 0;
 
+	pinctrl_pm_select_default_state(cpu_dai->dev);
+	pinctrl_pm_select_default_state(codec_dai->dev);
 	pm_runtime_get_sync(cpu_dai->dev);
 	pm_runtime_get_sync(codec_dai->dev);
 	pm_runtime_get_sync(platform->dev);
@@ -190,7 +193,7 @@
 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
 	/* startup the audio subsystem */
-	if (cpu_dai->driver->ops->startup) {
+	if (cpu_dai->driver->ops && cpu_dai->driver->ops->startup) {
 		ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
 		if (ret < 0) {
 			dev_err(cpu_dai->dev, "ASoC: can't open interface"
@@ -208,7 +211,7 @@
 		}
 	}
 
-	if (codec_dai->driver->ops->startup) {
+	if (codec_dai->driver->ops && codec_dai->driver->ops->startup) {
 		ret = codec_dai->driver->ops->startup(substream, codec_dai);
 		if (ret < 0) {
 			dev_err(codec_dai->dev, "ASoC: can't open codec"
@@ -317,6 +320,10 @@
 	pm_runtime_put(platform->dev);
 	pm_runtime_put(codec_dai->dev);
 	pm_runtime_put(cpu_dai->dev);
+	if (!codec_dai->active)
+		pinctrl_pm_select_sleep_state(codec_dai->dev);
+	if (!cpu_dai->active)
+		pinctrl_pm_select_sleep_state(cpu_dai->dev);
 
 	return ret;
 }
@@ -426,6 +433,10 @@
 	pm_runtime_put(platform->dev);
 	pm_runtime_put(codec_dai->dev);
 	pm_runtime_put(cpu_dai->dev);
+	if (!codec_dai->active)
+		pinctrl_pm_select_sleep_state(codec_dai->dev);
+	if (!cpu_dai->active)
+		pinctrl_pm_select_sleep_state(cpu_dai->dev);
 
 	return 0;
 }
@@ -463,7 +474,7 @@
 		}
 	}
 
-	if (codec_dai->driver->ops->prepare) {
+	if (codec_dai->driver->ops && codec_dai->driver->ops->prepare) {
 		ret = codec_dai->driver->ops->prepare(substream, codec_dai);
 		if (ret < 0) {
 			dev_err(codec_dai->dev, "ASoC: DAI prepare error: %d\n",
@@ -472,7 +483,7 @@
 		}
 	}
 
-	if (cpu_dai->driver->ops->prepare) {
+	if (cpu_dai->driver->ops && cpu_dai->driver->ops->prepare) {
 		ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
 		if (ret < 0) {
 			dev_err(cpu_dai->dev, "ASoC: DAI prepare error: %d\n",
@@ -523,7 +534,7 @@
 		}
 	}
 
-	if (codec_dai->driver->ops->hw_params) {
+	if (codec_dai->driver->ops && codec_dai->driver->ops->hw_params) {
 		ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
 		if (ret < 0) {
 			dev_err(codec_dai->dev, "ASoC: can't set %s hw params:"
@@ -532,7 +543,7 @@
 		}
 	}
 
-	if (cpu_dai->driver->ops->hw_params) {
+	if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_params) {
 		ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
 		if (ret < 0) {
 			dev_err(cpu_dai->dev, "ASoC: %s hw params failed: %d\n",
@@ -559,11 +570,11 @@
 	return ret;
 
 platform_err:
-	if (cpu_dai->driver->ops->hw_free)
+	if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_free)
 		cpu_dai->driver->ops->hw_free(substream, cpu_dai);
 
 interface_err:
-	if (codec_dai->driver->ops->hw_free)
+	if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free)
 		codec_dai->driver->ops->hw_free(substream, codec_dai);
 
 codec_err:
@@ -600,10 +611,10 @@
 		platform->driver->ops->hw_free(substream);
 
 	/* now free hw params for the DAIs  */
-	if (codec_dai->driver->ops->hw_free)
+	if (codec_dai->driver->ops && codec_dai->driver->ops->hw_free)
 		codec_dai->driver->ops->hw_free(substream, codec_dai);
 
-	if (cpu_dai->driver->ops->hw_free)
+	if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_free)
 		cpu_dai->driver->ops->hw_free(substream, cpu_dai);
 
 	mutex_unlock(&rtd->pcm_mutex);
@@ -618,7 +629,7 @@
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	int ret;
 
-	if (codec_dai->driver->ops->trigger) {
+	if (codec_dai->driver->ops && codec_dai->driver->ops->trigger) {
 		ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai);
 		if (ret < 0)
 			return ret;
@@ -630,7 +641,7 @@
 			return ret;
 	}
 
-	if (cpu_dai->driver->ops->trigger) {
+	if (cpu_dai->driver->ops && cpu_dai->driver->ops->trigger) {
 		ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai);
 		if (ret < 0)
 			return ret;
@@ -647,19 +658,20 @@
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	int ret;
 
-	if (codec_dai->driver->ops->bespoke_trigger) {
+	if (codec_dai->driver->ops &&
+	    codec_dai->driver->ops->bespoke_trigger) {
 		ret = codec_dai->driver->ops->bespoke_trigger(substream, cmd, codec_dai);
 		if (ret < 0)
 			return ret;
 	}
 
-	if (platform->driver->bespoke_trigger) {
+	if (platform->driver->ops && platform->driver->bespoke_trigger) {
 		ret = platform->driver->bespoke_trigger(substream, cmd);
 		if (ret < 0)
 			return ret;
 	}
 
-	if (cpu_dai->driver->ops->bespoke_trigger) {
+	if (cpu_dai->driver->ops && cpu_dai->driver->ops->bespoke_trigger) {
 		ret = cpu_dai->driver->ops->bespoke_trigger(substream, cmd, cpu_dai);
 		if (ret < 0)
 			return ret;
@@ -684,10 +696,10 @@
 	if (platform->driver->ops && platform->driver->ops->pointer)
 		offset = platform->driver->ops->pointer(substream);
 
-	if (cpu_dai->driver->ops->delay)
+	if (cpu_dai->driver->ops && cpu_dai->driver->ops->delay)
 		delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
 
-	if (codec_dai->driver->ops->delay)
+	if (codec_dai->driver->ops && codec_dai->driver->ops->delay)
 		delay += codec_dai->driver->ops->delay(substream, codec_dai);
 
 	if (platform->driver->delay)
@@ -721,7 +733,7 @@
 	list_add(&dpcm->list_be, &fe->dpcm[stream].be_clients);
 	list_add(&dpcm->list_fe, &be->dpcm[stream].fe_clients);
 
-	dev_dbg(fe->dev, "  connected new DPCM %s path %s %s %s\n",
+	dev_dbg(fe->dev, "connected new DPCM %s path %s %s %s\n",
 			stream ? "capture" : "playback",  fe->dai_link->name,
 			stream ? "<-" : "->", be->dai_link->name);
 
@@ -749,7 +761,7 @@
 		if (dpcm->fe == fe)
 			continue;
 
-		dev_dbg(fe->dev, "  reparent %s path %s %s %s\n",
+		dev_dbg(fe->dev, "reparent %s path %s %s %s\n",
 			stream ? "capture" : "playback",
 			dpcm->fe->dai_link->name,
 			stream ? "<-" : "->", dpcm->be->dai_link->name);
@@ -773,7 +785,7 @@
 		if (dpcm->state != SND_SOC_DPCM_LINK_STATE_FREE)
 			continue;
 
-		dev_dbg(fe->dev, "  freed DSP %s path %s %s %s\n",
+		dev_dbg(fe->dev, "freed DSP %s path %s %s %s\n",
 			stream ? "capture" : "playback", fe->dai_link->name,
 			stream ? "<-" : "->", dpcm->be->dai_link->name);
 
@@ -1037,6 +1049,12 @@
 		struct snd_pcm_substream *be_substream =
 			snd_soc_dpcm_get_substream(be, stream);
 
+		if (!be_substream) {
+			dev_err(be->dev, "ASoC: no backend %s stream\n",
+				stream ? "capture" : "playback");
+			continue;
+		}
+
 		/* is this op for this BE ? */
 		if (!snd_soc_dpcm_be_can_update(fe, be, stream))
 			continue;
@@ -1054,7 +1072,8 @@
 		    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE))
 			continue;
 
-		dev_dbg(be->dev, "ASoC: open BE %s\n", be->dai_link->name);
+		dev_dbg(be->dev, "ASoC: open %s BE %s\n",
+			stream ? "capture" : "playback", be->dai_link->name);
 
 		be_substream->runtime = be->dpcm[stream].runtime;
 		err = soc_pcm_open(be_substream);
@@ -1673,7 +1692,7 @@
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_platform *platform = rtd->platform;
 
-	if (platform->driver->ops->ioctl)
+	if (platform->driver->ops && platform->driver->ops->ioctl)
 		return platform->driver->ops->ioctl(substream, cmd, arg);
 	return snd_pcm_lib_ioctl(substream, cmd, arg);
 }
@@ -1934,8 +1953,8 @@
 
 		dev_dbg(be->dev, "ASoC: BE digital mute %s\n", be->dai_link->name);
 
-		if (drv->ops->digital_mute && dai->playback_active)
-				drv->ops->digital_mute(dai, mute);
+		if (drv->ops && drv->ops->digital_mute && dai->playback_active)
+			drv->ops->digital_mute(dai, mute);
 	}
 
 	return 0;
@@ -2116,7 +2135,7 @@
 
 	pcm->private_free = platform->driver->pcm_free;
 out:
-	dev_info(rtd->card->dev, " %s <-> %s mapping ok\n", codec_dai->name,
+	dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", codec_dai->name,
 		cpu_dai->name);
 	return ret;
 }
@@ -2224,7 +2243,7 @@
 int snd_soc_platform_trigger(struct snd_pcm_substream *substream,
 		int cmd, struct snd_soc_platform *platform)
 {
-	if (platform->driver->ops->trigger)
+	if (platform->driver->ops && platform->driver->ops->trigger)
 		return platform->driver->ops->trigger(substream, cmd);
 	return 0;
 }
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c
index 29b211e..5e63365 100644
--- a/sound/soc/soc-utils.c
+++ b/sound/soc/soc-utils.c
@@ -75,7 +75,11 @@
 
 static int dummy_dma_open(struct snd_pcm_substream *substream)
 {
-	snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware);
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+	/* BE's dont need dummy params */
+	if (!rtd->dai_link->no_pcm)
+		snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware);
 
 	return 0;
 }
diff --git a/sound/soc/spear/spdif_in.c b/sound/soc/spear/spdif_in.c
index 63acfeb..21a8c95 100644
--- a/sound/soc/spear/spdif_in.c
+++ b/sound/soc/spear/spdif_in.c
@@ -257,20 +257,12 @@
 		return ret;
 	}
 
-	return snd_soc_register_component(&pdev->dev, &spdif_in_component,
-					 &spdif_in_dai, 1);
-}
-
-static int spdif_in_remove(struct platform_device *pdev)
-{
-	snd_soc_unregister_component(&pdev->dev);
-
-	return 0;
+	return devm_snd_soc_register_component(&pdev->dev, &spdif_in_component,
+					       &spdif_in_dai, 1);
 }
 
 static struct platform_driver spdif_in_driver = {
 	.probe		= spdif_in_probe,
-	.remove		= spdif_in_remove,
 	.driver		= {
 		.name	= "spdif-in",
 		.owner	= THIS_MODULE,
diff --git a/sound/soc/spear/spdif_out.c b/sound/soc/spear/spdif_out.c
index 2fdf68c..b6ef6f7 100644
--- a/sound/soc/spear/spdif_out.c
+++ b/sound/soc/spear/spdif_out.c
@@ -280,7 +280,6 @@
 	struct spdif_out_dev *host;
 	struct spear_spdif_platform_data *pdata;
 	struct resource *res;
-	int ret;
 
 	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
 	if (!host) {
@@ -307,16 +306,8 @@
 
 	dev_set_drvdata(&pdev->dev, host);
 
-	ret = snd_soc_register_component(&pdev->dev, &spdif_out_component,
-					 &spdif_out_dai, 1);
-	return ret;
-}
-
-static int spdif_out_remove(struct platform_device *pdev)
-{
-	snd_soc_unregister_component(&pdev->dev);
-
-	return 0;
+	return devm_snd_soc_register_component(&pdev->dev, &spdif_out_component,
+					       &spdif_out_dai, 1);
 }
 
 #ifdef CONFIG_PM
@@ -357,7 +348,6 @@
 
 static struct platform_driver spdif_out_driver = {
 	.probe		= spdif_out_probe,
-	.remove		= spdif_out_remove,
 	.driver		= {
 		.name	= "spdif-out",
 		.owner	= THIS_MODULE,
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c
index 52af7f6..364bf6a 100644
--- a/sound/soc/tegra/tegra20_i2s.c
+++ b/sound/soc/tegra/tegra20_i2s.c
@@ -297,7 +297,7 @@
 		return true;
 	default:
 		return false;
-	};
+	}
 }
 
 static bool tegra20_i2s_volatile_reg(struct device *dev, unsigned int reg)
@@ -310,7 +310,7 @@
 		return true;
 	default:
 		return false;
-	};
+	}
 }
 
 static bool tegra20_i2s_precious_reg(struct device *dev, unsigned int reg)
@@ -321,7 +321,7 @@
 		return true;
 	default:
 		return false;
-	};
+	}
 }
 
 static const struct regmap_config tegra20_i2s_regmap_config = {
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c
index 551b3c9..08bc693 100644
--- a/sound/soc/tegra/tegra20_spdif.c
+++ b/sound/soc/tegra/tegra20_spdif.c
@@ -213,7 +213,7 @@
 		return true;
 	default:
 		return false;
-	};
+	}
 }
 
 static bool tegra20_spdif_volatile_reg(struct device *dev, unsigned int reg)
@@ -234,7 +234,7 @@
 		return true;
 	default:
 		return false;
-	};
+	}
 }
 
 static bool tegra20_spdif_precious_reg(struct device *dev, unsigned int reg)
@@ -247,7 +247,7 @@
 		return true;
 	default:
 		return false;
-	};
+	}
 }
 
 static const struct regmap_config tegra20_spdif_regmap_config = {
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
index d554d46..3115433 100644
--- a/sound/soc/tegra/tegra30_ahub.c
+++ b/sound/soc/tegra/tegra30_ahub.c
@@ -100,6 +100,7 @@
 {
 	int channel;
 	u32 reg, val;
+	struct tegra30_ahub_cif_conf cif_conf;
 
 	channel = find_first_zero_bit(ahub->rx_usage,
 				      TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
@@ -123,15 +124,21 @@
 	       TEGRA30_AHUB_CHANNEL_CTRL_RX_PACK_16;
 	tegra30_apbif_write(reg, val);
 
+	cif_conf.threshold = 0;
+	cif_conf.audio_channels = 2;
+	cif_conf.client_channels = 2;
+	cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16;
+	cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16;
+	cif_conf.expand = 0;
+	cif_conf.stereo_conv = 0;
+	cif_conf.replicate = 0;
+	cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_RX;
+	cif_conf.truncate = 0;
+	cif_conf.mono_conv = 0;
+
 	reg = TEGRA30_AHUB_CIF_RX_CTRL +
 	      (channel * TEGRA30_AHUB_CIF_RX_CTRL_STRIDE);
-	val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
-	      (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
-	      (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
-	      TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
-	      TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 |
-	      TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
-	tegra30_apbif_write(reg, val);
+	ahub->soc_data->set_audio_cif(ahub->regmap_apbif, reg, &cif_conf);
 
 	return 0;
 }
@@ -183,6 +190,7 @@
 {
 	int channel;
 	u32 reg, val;
+	struct tegra30_ahub_cif_conf cif_conf;
 
 	channel = find_first_zero_bit(ahub->tx_usage,
 				      TEGRA30_AHUB_CHANNEL_CTRL_COUNT);
@@ -206,15 +214,21 @@
 	       TEGRA30_AHUB_CHANNEL_CTRL_TX_PACK_16;
 	tegra30_apbif_write(reg, val);
 
+	cif_conf.threshold = 0;
+	cif_conf.audio_channels = 2;
+	cif_conf.client_channels = 2;
+	cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16;
+	cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16;
+	cif_conf.expand = 0;
+	cif_conf.stereo_conv = 0;
+	cif_conf.replicate = 0;
+	cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_TX;
+	cif_conf.truncate = 0;
+	cif_conf.mono_conv = 0;
+
 	reg = TEGRA30_AHUB_CIF_TX_CTRL +
 	      (channel * TEGRA30_AHUB_CIF_TX_CTRL_STRIDE);
-	val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
-	      (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
-	      (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
-	      TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
-	      TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16 |
-	      TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
-	tegra30_apbif_write(reg, val);
+	ahub->soc_data->set_audio_cif(ahub->regmap_apbif, reg, &cif_conf);
 
 	return 0;
 }
@@ -346,7 +360,7 @@
 		return true;
 	default:
 		break;
-	};
+	}
 
 	if (REG_IN_ARRAY(reg, CHANNEL_CTRL) ||
 	    REG_IN_ARRAY(reg, CHANNEL_CLEAR) ||
@@ -381,7 +395,7 @@
 		return true;
 	default:
 		break;
-	};
+	}
 
 	if (REG_IN_ARRAY(reg, CHANNEL_CLEAR) ||
 	    REG_IN_ARRAY(reg, CHANNEL_STATUS) ||
@@ -437,13 +451,21 @@
 
 static struct tegra30_ahub_soc_data soc_data_tegra30 = {
 	.clk_list_mask = CLK_LIST_MASK_TEGRA30,
+	.set_audio_cif = tegra30_ahub_set_cif,
 };
 
 static struct tegra30_ahub_soc_data soc_data_tegra114 = {
 	.clk_list_mask = CLK_LIST_MASK_TEGRA114,
+	.set_audio_cif = tegra30_ahub_set_cif,
+};
+
+static struct tegra30_ahub_soc_data soc_data_tegra124 = {
+	.clk_list_mask = CLK_LIST_MASK_TEGRA114,
+	.set_audio_cif = tegra124_ahub_set_cif,
 };
 
 static const struct of_device_id tegra30_ahub_of_match[] = {
+	{ .compatible = "nvidia,tegra124-ahub", .data = &soc_data_tegra124 },
 	{ .compatible = "nvidia,tegra114-ahub", .data = &soc_data_tegra114 },
 	{ .compatible = "nvidia,tegra30-ahub",  .data = &soc_data_tegra30 },
 	{},
@@ -497,6 +519,7 @@
 	}
 	dev_set_drvdata(&pdev->dev, ahub);
 
+	ahub->soc_data = soc_data;
 	ahub->dev = &pdev->dev;
 
 	ahub->clk_d_audio = clk_get(&pdev->dev, "d_audio");
@@ -669,6 +692,70 @@
 };
 module_platform_driver(tegra30_ahub_driver);
 
+void tegra30_ahub_set_cif(struct regmap *regmap, unsigned int reg,
+			  struct tegra30_ahub_cif_conf *conf)
+{
+	unsigned int value;
+
+	value = (conf->threshold <<
+			TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
+		((conf->audio_channels - 1) <<
+			TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
+		((conf->client_channels - 1) <<
+			TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
+		(conf->audio_bits <<
+			TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
+		(conf->client_bits <<
+			TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT) |
+		(conf->expand <<
+			TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT) |
+		(conf->stereo_conv <<
+			TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) |
+		(conf->replicate <<
+			TEGRA30_AUDIOCIF_CTRL_REPLICATE_SHIFT) |
+		(conf->direction <<
+			TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT) |
+		(conf->truncate <<
+			TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT) |
+		(conf->mono_conv <<
+			TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT);
+
+	regmap_write(regmap, reg, value);
+}
+EXPORT_SYMBOL_GPL(tegra30_ahub_set_cif);
+
+void tegra124_ahub_set_cif(struct regmap *regmap, unsigned int reg,
+			   struct tegra30_ahub_cif_conf *conf)
+{
+	unsigned int value;
+
+	value = (conf->threshold <<
+			TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
+		((conf->audio_channels - 1) <<
+			TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
+		((conf->client_channels - 1) <<
+			TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
+		(conf->audio_bits <<
+			TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
+		(conf->client_bits <<
+			TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT) |
+		(conf->expand <<
+			TEGRA30_AUDIOCIF_CTRL_EXPAND_SHIFT) |
+		(conf->stereo_conv <<
+			TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT) |
+		(conf->replicate <<
+			TEGRA30_AUDIOCIF_CTRL_REPLICATE_SHIFT) |
+		(conf->direction <<
+			TEGRA30_AUDIOCIF_CTRL_DIRECTION_SHIFT) |
+		(conf->truncate <<
+			TEGRA30_AUDIOCIF_CTRL_TRUNCATE_SHIFT) |
+		(conf->mono_conv <<
+			TEGRA30_AUDIOCIF_CTRL_MONO_CONV_SHIFT);
+
+	regmap_write(regmap, reg, value);
+}
+EXPORT_SYMBOL_GPL(tegra124_ahub_set_cif);
+
 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
 MODULE_DESCRIPTION("Tegra30 AHUB driver");
 MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/tegra/tegra30_ahub.h b/sound/soc/tegra/tegra30_ahub.h
index 09766cd..d67321d 100644
--- a/sound/soc/tegra/tegra30_ahub.h
+++ b/sound/soc/tegra/tegra30_ahub.h
@@ -25,16 +25,30 @@
 #define TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US	0xf
 #define TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK	(TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT)
 
+#define TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT	24
+#define TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US	0x3f
+#define TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK	(TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_MASK_US << TEGRA124_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT)
+
 /* Channel count minus 1 */
 #define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT	24
 #define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US	7
 #define TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK	(TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT)
 
 /* Channel count minus 1 */
+#define TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT	20
+#define TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US	0xf
+#define TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK	(TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_MASK_US << TEGRA124_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT)
+
+/* Channel count minus 1 */
 #define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT	16
 #define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US	7
 #define TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK	(TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT)
 
+/* Channel count minus 1 */
+#define TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT	16
+#define TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US	0xf
+#define TEGRA124_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK	(TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_MASK_US << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT)
+
 #define TEGRA30_AUDIOCIF_BITS_4				0
 #define TEGRA30_AUDIOCIF_BITS_8				1
 #define TEGRA30_AUDIOCIF_BITS_12			2
@@ -86,7 +100,7 @@
 #define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_CH1		(TEGRA30_AUDIOCIF_STEREO_CONV_CH1 << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT)
 #define TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_AVG		(TEGRA30_AUDIOCIF_STEREO_CONV_AVG << TEGRA30_AUDIOCIF_CTRL_STEREO_CONV_SHIFT)
 
-#define TEGRA30_AUDIOCIF_CTRL_REPLICATE			3
+#define TEGRA30_AUDIOCIF_CTRL_REPLICATE_SHIFT		3
 
 #define TEGRA30_AUDIOCIF_DIRECTION_TX			0
 #define TEGRA30_AUDIOCIF_DIRECTION_RX			1
@@ -468,8 +482,30 @@
 					  enum tegra30_ahub_txcif txcif);
 extern int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif);
 
+struct tegra30_ahub_cif_conf {
+	unsigned int threshold;
+	unsigned int audio_channels;
+	unsigned int client_channels;
+	unsigned int audio_bits;
+	unsigned int client_bits;
+	unsigned int expand;
+	unsigned int stereo_conv;
+	unsigned int replicate;
+	unsigned int direction;
+	unsigned int truncate;
+	unsigned int mono_conv;
+};
+
+void tegra30_ahub_set_cif(struct regmap *regmap, unsigned int reg,
+			  struct tegra30_ahub_cif_conf *conf);
+void tegra124_ahub_set_cif(struct regmap *regmap, unsigned int reg,
+			   struct tegra30_ahub_cif_conf *conf);
+
 struct tegra30_ahub_soc_data {
 	u32 clk_list_mask;
+	void (*set_audio_cif)(struct regmap *regmap,
+			      unsigned int reg,
+			      struct tegra30_ahub_cif_conf *conf);
 	/*
 	 * FIXME: There are many more differences in HW, such as:
 	 * - More APBIF channels.
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index 47565fd04..231a785 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -30,6 +30,7 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
@@ -179,6 +180,7 @@
 	struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
 	unsigned int mask, val, reg;
 	int ret, sample_size, srate, i2sclock, bitcnt;
+	struct tegra30_ahub_cif_conf cif_conf;
 
 	if (params_channels(params) != 2)
 		return -EINVAL;
@@ -217,21 +219,26 @@
 
 	regmap_write(i2s->regmap, TEGRA30_I2S_TIMING, val);
 
-	val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
-	      (1 << TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
-	      (1 << TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
-	      TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_16 |
-	      TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_16;
+	cif_conf.threshold = 0;
+	cif_conf.audio_channels = 2;
+	cif_conf.client_channels = 2;
+	cif_conf.audio_bits = TEGRA30_AUDIOCIF_BITS_16;
+	cif_conf.client_bits = TEGRA30_AUDIOCIF_BITS_16;
+	cif_conf.expand = 0;
+	cif_conf.stereo_conv = 0;
+	cif_conf.replicate = 0;
+	cif_conf.truncate = 0;
+	cif_conf.mono_conv = 0;
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
+		cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_RX;
 		reg = TEGRA30_I2S_CIF_RX_CTRL;
 	} else {
-		val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
+		cif_conf.direction = TEGRA30_AUDIOCIF_DIRECTION_TX;
 		reg = TEGRA30_I2S_CIF_TX_CTRL;
 	}
 
-	regmap_write(i2s->regmap, reg, val);
+	i2s->soc_data->set_audio_cif(i2s->regmap, reg, &cif_conf);
 
 	val = (1 << TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) |
 	      (1 << TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT);
@@ -369,7 +376,7 @@
 		return true;
 	default:
 		return false;
-	};
+	}
 }
 
 static bool tegra30_i2s_volatile_reg(struct device *dev, unsigned int reg)
@@ -382,7 +389,7 @@
 		return true;
 	default:
 		return false;
-	};
+	}
 }
 
 static const struct regmap_config tegra30_i2s_regmap_config = {
@@ -396,9 +403,24 @@
 	.cache_type = REGCACHE_RBTREE,
 };
 
+static const struct tegra30_i2s_soc_data tegra30_i2s_config = {
+	.set_audio_cif = tegra30_ahub_set_cif,
+};
+
+static const struct tegra30_i2s_soc_data tegra124_i2s_config = {
+	.set_audio_cif = tegra124_ahub_set_cif,
+};
+
+static const struct of_device_id tegra30_i2s_of_match[] = {
+	{ .compatible = "nvidia,tegra124-i2s", .data = &tegra124_i2s_config },
+	{ .compatible = "nvidia,tegra30-i2s", .data = &tegra30_i2s_config },
+	{},
+};
+
 static int tegra30_i2s_platform_probe(struct platform_device *pdev)
 {
 	struct tegra30_i2s *i2s;
+	const struct of_device_id *match;
 	u32 cif_ids[2];
 	struct resource *mem, *memregion;
 	void __iomem *regs;
@@ -412,6 +434,14 @@
 	}
 	dev_set_drvdata(&pdev->dev, i2s);
 
+	match = of_match_device(tegra30_i2s_of_match, &pdev->dev);
+	if (!match) {
+		dev_err(&pdev->dev, "Error: No device match found\n");
+		ret = -ENODEV;
+		goto err;
+	}
+	i2s->soc_data = (struct tegra30_i2s_soc_data *)match->data;
+
 	i2s->dai = tegra30_i2s_dai_template;
 	i2s->dai.name = dev_name(&pdev->dev);
 
@@ -539,11 +569,6 @@
 }
 #endif
 
-static const struct of_device_id tegra30_i2s_of_match[] = {
-	{ .compatible = "nvidia,tegra30-i2s", },
-	{},
-};
-
 static const struct dev_pm_ops tegra30_i2s_pm_ops = {
 	SET_RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend,
 			   tegra30_i2s_runtime_resume, NULL)
diff --git a/sound/soc/tegra/tegra30_i2s.h b/sound/soc/tegra/tegra30_i2s.h
index bea23af..4d0b0a3 100644
--- a/sound/soc/tegra/tegra30_i2s.h
+++ b/sound/soc/tegra/tegra30_i2s.h
@@ -225,7 +225,14 @@
 #define TEGRA30_I2S_LCOEF_COEF_MASK_US			0xffff
 #define TEGRA30_I2S_LCOEF_COEF_MASK			(TEGRA30_I2S_LCOEF_COEF_MASK_US << TEGRA30_I2S_LCOEF_COEF_SHIFT)
 
+struct tegra30_i2s_soc_data {
+	void (*set_audio_cif)(struct regmap *regmap,
+			      unsigned int reg,
+			      struct tegra30_ahub_cif_conf *conf);
+};
+
 struct tegra30_i2s {
+	const struct tegra30_i2s_soc_data *soc_data;
 	struct snd_soc_dai_driver dai;
 	int cif_id;
 	struct clk *clk_i2s;
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
index d173880..1be311c 100644
--- a/sound/soc/tegra/tegra_asoc_utils.c
+++ b/sound/soc/tegra/tegra_asoc_utils.c
@@ -182,6 +182,8 @@
 		data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA30;
 	else if (of_machine_is_compatible("nvidia,tegra114"))
 		data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA114;
+	else if (of_machine_is_compatible("nvidia,tegra124"))
+		data->soc = TEGRA_ASOC_UTILS_SOC_TEGRA124;
 	else {
 		dev_err(data->dev, "SoC unknown to Tegra ASoC utils\n");
 		return -EINVAL;
diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h
index 19fdcaf..9577121 100644
--- a/sound/soc/tegra/tegra_asoc_utils.h
+++ b/sound/soc/tegra/tegra_asoc_utils.h
@@ -30,6 +30,7 @@
 	TEGRA_ASOC_UTILS_SOC_TEGRA20,
 	TEGRA_ASOC_UTILS_SOC_TEGRA30,
 	TEGRA_ASOC_UTILS_SOC_TEGRA114,
+	TEGRA_ASOC_UTILS_SOC_TEGRA124,
 };
 
 struct tegra_asoc_utils_data {
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index f056f63..7b2d23b 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -56,7 +56,6 @@
 static const struct snd_dmaengine_pcm_config tegra_dmaengine_pcm_config = {
 	.pcm_hardware = &tegra_pcm_hardware,
 	.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
-	.compat_filter_fn = NULL,
 	.prealloc_buffer_size = PAGE_SIZE * 8,
 };
 
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c
index 45a6428..fbd077f 100644
--- a/sound/soc/txx9/txx9aclc.c
+++ b/sound/soc/txx9/txx9aclc.c
@@ -115,8 +115,8 @@
 	spin_lock_irqsave(&dmadata->dma_lock, flags);
 	if (dmadata->frag_count >= 0) {
 		dmadata->dmacount--;
-		BUG_ON(dmadata->dmacount < 0);
-		tasklet_schedule(&dmadata->tasklet);
+		if (!WARN_ON(dmadata->dmacount < 0))
+			tasklet_schedule(&dmadata->tasklet);
 	}
 	spin_unlock_irqrestore(&dmadata->dma_lock, flags);
 }
@@ -181,7 +181,10 @@
 		spin_unlock_irqrestore(&dmadata->dma_lock, flags);
 		return;
 	}
-	BUG_ON(dmadata->dmacount >= NR_DMA_CHAIN);
+	if (WARN_ON(dmadata->dmacount >= NR_DMA_CHAIN)) {
+		spin_unlock_irqrestore(&dmadata->dma_lock, flags);
+		return;
+	}
 	while (dmadata->dmacount < NR_DMA_CHAIN) {
 		dmadata->dmacount++;
 		spin_unlock_irqrestore(&dmadata->dma_lock, flags);
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
index 54aaad2..b47f6fe 100644
--- a/sound/sparc/cs4231.c
+++ b/sound/sparc/cs4231.c
@@ -429,7 +429,8 @@
 		unsigned int period_size = snd_pcm_lib_period_bytes(substream);
 		unsigned int offset = period_size * (*periods_sent);
 
-		BUG_ON(period_size >= (1 << 24));
+		if (WARN_ON(period_size >= (1 << 24)))
+			return;
 
 		if (dma_cont->request(dma_cont,
 				      runtime->dma_addr + offset, period_size))
@@ -912,7 +913,8 @@
 	chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE |
 					    CS4231_PLAYBACK_PIO);
 
-	BUG_ON(runtime->period_size > 0xffff + 1);
+	if (WARN_ON(runtime->period_size > 0xffff + 1))
+		return -EINVAL;
 
 	chip->p_periods_sent = 0;
 	spin_unlock_irqrestore(&chip->lock, flags);
diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c
index c39c779..66edc4a 100644
--- a/sound/usb/6fire/chip.c
+++ b/sound/usb/6fire/chip.c
@@ -101,7 +101,7 @@
 			usb_set_intfdata(intf, chips[i]);
 			mutex_unlock(&register_mutex);
 			return 0;
-		} else if (regidx < 0)
+		} else if (!devices[i] && regidx < 0)
 			regidx = i;
 	}
 	if (regidx < 0) {
diff --git a/sound/usb/caiaq/control.c b/sound/usb/caiaq/control.c
index ae6b50f..f65fc09 100644
--- a/sound/usb/caiaq/control.c
+++ b/sound/usb/caiaq/control.c
@@ -28,6 +28,7 @@
 #include "control.h"
 
 #define CNT_INTVAL 0x10000
+#define MASCHINE_BANK_SIZE 32
 
 static int control_info(struct snd_kcontrol *kcontrol,
 			struct snd_ctl_elem_info *uinfo)
@@ -105,6 +106,10 @@
 		USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1))
 		cmd = EP1_CMD_DIMM_LEDS;
 
+	if (cdev->chip.usb_id ==
+		USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER))
+		cmd = EP1_CMD_DIMM_LEDS;
+
 	if (pos & CNT_INTVAL) {
 		int i = pos & ~CNT_INTVAL;
 
@@ -121,6 +126,20 @@
 				     usb_sndbulkpipe(cdev->chip.dev, 8),
 				     cdev->ep8_out_buf, sizeof(cdev->ep8_out_buf),
 				     &actual_len, 200);
+		} else if (cdev->chip.usb_id ==
+			USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER)) {
+
+			int bank = 0;
+			int offset = 0;
+
+			if (i >= MASCHINE_BANK_SIZE) {
+				bank = 0x1e;
+				offset = MASCHINE_BANK_SIZE;
+			}
+
+			snd_usb_caiaq_send_command_bank(cdev, cmd, bank,
+					cdev->control_state + offset,
+					MASCHINE_BANK_SIZE);
 		} else {
 			snd_usb_caiaq_send_command(cdev, cmd,
 					cdev->control_state, sizeof(cdev->control_state));
@@ -490,6 +509,74 @@
 	{ "LED: FX2: Mode",			133 | CNT_INTVAL },
 };
 
+static struct caiaq_controller maschine_controller[] = {
+	{ "LED: Pad 1",				3  | CNT_INTVAL },
+	{ "LED: Pad 2",				2  | CNT_INTVAL },
+	{ "LED: Pad 3",				1  | CNT_INTVAL },
+	{ "LED: Pad 4",				0  | CNT_INTVAL },
+	{ "LED: Pad 5",				7  | CNT_INTVAL },
+	{ "LED: Pad 6",				6  | CNT_INTVAL },
+	{ "LED: Pad 7",				5  | CNT_INTVAL },
+	{ "LED: Pad 8",				4  | CNT_INTVAL },
+	{ "LED: Pad 9",				11 | CNT_INTVAL },
+	{ "LED: Pad 10",			10 | CNT_INTVAL },
+	{ "LED: Pad 11",			9  | CNT_INTVAL },
+	{ "LED: Pad 12",			8  | CNT_INTVAL },
+	{ "LED: Pad 13",			15 | CNT_INTVAL },
+	{ "LED: Pad 14",			14 | CNT_INTVAL },
+	{ "LED: Pad 15",			13 | CNT_INTVAL },
+	{ "LED: Pad 16",			12 | CNT_INTVAL },
+
+	{ "LED: Mute",				16 | CNT_INTVAL },
+	{ "LED: Solo",				17 | CNT_INTVAL },
+	{ "LED: Select",			18 | CNT_INTVAL },
+	{ "LED: Duplicate",			19 | CNT_INTVAL },
+	{ "LED: Navigate",			20 | CNT_INTVAL },
+	{ "LED: Pad Mode",			21 | CNT_INTVAL },
+	{ "LED: Pattern",			22 | CNT_INTVAL },
+	{ "LED: Scene",				23 | CNT_INTVAL },
+
+	{ "LED: Shift",				24 | CNT_INTVAL },
+	{ "LED: Erase",				25 | CNT_INTVAL },
+	{ "LED: Grid",				26 | CNT_INTVAL },
+	{ "LED: Right Bottom",			27 | CNT_INTVAL },
+	{ "LED: Rec",				28 | CNT_INTVAL },
+	{ "LED: Play",				29 | CNT_INTVAL },
+	{ "LED: Left Bottom",			32 | CNT_INTVAL },
+	{ "LED: Restart",			33 | CNT_INTVAL },
+
+	{ "LED: Group A",			41 | CNT_INTVAL },
+	{ "LED: Group B",			40 | CNT_INTVAL },
+	{ "LED: Group C",			37 | CNT_INTVAL },
+	{ "LED: Group D",			36 | CNT_INTVAL },
+	{ "LED: Group E",			39 | CNT_INTVAL },
+	{ "LED: Group F",			38 | CNT_INTVAL },
+	{ "LED: Group G",			35 | CNT_INTVAL },
+	{ "LED: Group H",			34 | CNT_INTVAL },
+
+	{ "LED: Auto Write",			42 | CNT_INTVAL },
+	{ "LED: Snap",				43 | CNT_INTVAL },
+	{ "LED: Right Top",			44 | CNT_INTVAL },
+	{ "LED: Left Top",			45 | CNT_INTVAL },
+	{ "LED: Sampling",			46 | CNT_INTVAL },
+	{ "LED: Browse",			47 | CNT_INTVAL },
+	{ "LED: Step",				48 | CNT_INTVAL },
+	{ "LED: Control",			49 | CNT_INTVAL },
+
+	{ "LED: Top Button 1",			57 | CNT_INTVAL },
+	{ "LED: Top Button 2",			56 | CNT_INTVAL },
+	{ "LED: Top Button 3",			55 | CNT_INTVAL },
+	{ "LED: Top Button 4",			54 | CNT_INTVAL },
+	{ "LED: Top Button 5",			53 | CNT_INTVAL },
+	{ "LED: Top Button 6",			52 | CNT_INTVAL },
+	{ "LED: Top Button 7",			51 | CNT_INTVAL },
+	{ "LED: Top Button 8",			50 | CNT_INTVAL },
+
+	{ "LED: Note Repeat",			58 | CNT_INTVAL },
+
+	{ "Backlight Display",			59 | CNT_INTVAL }
+};
+
 static int add_controls(struct caiaq_controller *c, int num,
 			struct snd_usb_caiaqdev *cdev)
 {
@@ -553,6 +640,11 @@
 		ret = add_controls(kontrols4_controller,
 			ARRAY_SIZE(kontrols4_controller), cdev);
 		break;
+
+	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
+		ret = add_controls(maschine_controller,
+			ARRAY_SIZE(maschine_controller), cdev);
+		break;
 	}
 
 	return ret;
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index 1a61dd1..bc55f70 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -235,6 +235,31 @@
 			   cdev->ep1_out_buf, len+1, &actual_len, 200);
 }
 
+int snd_usb_caiaq_send_command_bank(struct snd_usb_caiaqdev *cdev,
+			       unsigned char command,
+			       unsigned char bank,
+			       const unsigned char *buffer,
+			       int len)
+{
+	int actual_len;
+	struct usb_device *usb_dev = cdev->chip.dev;
+
+	if (!usb_dev)
+		return -EIO;
+
+	if (len > EP1_BUFSIZE - 2)
+		len = EP1_BUFSIZE - 2;
+
+	if (buffer && len > 0)
+		memcpy(cdev->ep1_out_buf+2, buffer, len);
+
+	cdev->ep1_out_buf[0] = command;
+	cdev->ep1_out_buf[1] = bank;
+
+	return usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, 1),
+			   cdev->ep1_out_buf, len+2, &actual_len, 200);
+}
+
 int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *cdev,
 		   		    int rate, int depth, int bpp)
 {
diff --git a/sound/usb/caiaq/device.h b/sound/usb/caiaq/device.h
index ad102fa..ab0f752 100644
--- a/sound/usb/caiaq/device.h
+++ b/sound/usb/caiaq/device.h
@@ -128,5 +128,10 @@
 			       unsigned char command,
 			       const unsigned char *buffer,
 			       int len);
+int snd_usb_caiaq_send_command_bank(struct snd_usb_caiaqdev *cdev,
+			       unsigned char command,
+			       unsigned char bank,
+			       const unsigned char *buffer,
+			       int len);
 
 #endif /* CAIAQ_DEVICE_H */
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 64952e2..d979050 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -79,7 +79,6 @@
 /* Vendor/product IDs for this card */
 static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
 static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
-static int nrpacks = 8;		/* max. number of packets per urb */
 static int device_setup[SNDRV_CARDS]; /* device parameter for this card */
 static bool ignore_ctl_error;
 static bool autoclock = true;
@@ -94,8 +93,6 @@
 MODULE_PARM_DESC(vid, "Vendor ID for the USB audio device.");
 module_param_array(pid, int, NULL, 0444);
 MODULE_PARM_DESC(pid, "Product ID for the USB audio device.");
-module_param(nrpacks, int, 0644);
-MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB.");
 module_param_array(device_setup, int, NULL, 0444);
 MODULE_PARM_DESC(device_setup, "Specific device setup (if needed).");
 module_param(ignore_ctl_error, bool, 0444);
@@ -349,6 +346,7 @@
 	case USB_SPEED_LOW:
 	case USB_SPEED_FULL:
 	case USB_SPEED_HIGH:
+	case USB_SPEED_WIRELESS:
 	case USB_SPEED_SUPER:
 		break;
 	default:
@@ -374,7 +372,6 @@
 	chip->dev = dev;
 	chip->card = card;
 	chip->setup = device_setup[idx];
-	chip->nrpacks = nrpacks;
 	chip->autoclock = autoclock;
 	chip->probing = 1;
 
@@ -754,19 +751,4 @@
 	.supports_autosuspend = 1,
 };
 
-static int __init snd_usb_audio_init(void)
-{
-	if (nrpacks < 1 || nrpacks > MAX_PACKS) {
-		printk(KERN_WARNING "invalid nrpacks value.\n");
-		return -EINVAL;
-	}
-	return usb_register(&usb_audio_driver);
-}
-
-static void __exit snd_usb_audio_cleanup(void)
-{
-	usb_deregister(&usb_audio_driver);
-}
-
-module_init(snd_usb_audio_init);
-module_exit(snd_usb_audio_cleanup);
+module_usb_driver(usb_audio_driver);
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 5ecacaa..9867ab8 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -2,11 +2,11 @@
 #define __USBAUDIO_CARD_H
 
 #define MAX_NR_RATES	1024
-#define MAX_PACKS	20
+#define MAX_PACKS	6		/* per URB */
 #define MAX_PACKS_HS	(MAX_PACKS * 8)	/* in high speed mode */
-#define MAX_URBS	8
+#define MAX_URBS	12
 #define SYNC_URBS	4	/* always four urbs for sync */
-#define MAX_QUEUE	24	/* try not to exceed this queue length, in ms */
+#define MAX_QUEUE	18	/* try not to exceed this queue length, in ms */
 
 struct audioformat {
 	struct list_head list;
@@ -87,6 +87,7 @@
 	unsigned int phase;		/* phase accumulator */
 	unsigned int maxpacksize;	/* max packet size in bytes */
 	unsigned int maxframesize;      /* max packet size in frames */
+	unsigned int max_urb_frames;	/* max URB size in frames */
 	unsigned int curpacksize;	/* current packet size in bytes (for capture) */
 	unsigned int curframesize;      /* current packet size in frames (for capture) */
 	unsigned int syncmaxsize;	/* sync endpoint packet size */
@@ -95,7 +96,7 @@
 	unsigned int syncinterval;	/* P for adaptive mode, 0 otherwise */
 	unsigned char silence_value;
 	unsigned int stride;
-	int iface, alt_idx;
+	int iface, altsetting;
 	int skip_packets;		/* quirks for devices to ignore the first n packets
 					   in a stream */
 
@@ -116,6 +117,8 @@
 	unsigned int channels_max;	/* max channels in the all audiofmts */
 	unsigned int cur_rate;		/* current rate (for hw_params callback) */
 	unsigned int period_bytes;	/* current period bytes (for hw_params callback) */
+	unsigned int period_frames;	/* current frames per period */
+	unsigned int buffer_periods;	/* current periods per buffer */
 	unsigned int altset_idx;     /* USB data format: index of alternate setting */
 	unsigned int txfr_quirk:1;	/* allow sub-frame alignment */
 	unsigned int fmt_type;		/* USB audio format type (1-3) */
@@ -125,6 +128,7 @@
 
 	unsigned int hwptr_done;	/* processed byte position in the buffer */
 	unsigned int transfer_done;		/* processed frames since last period update */
+	unsigned int frame_limit;	/* limits number of packets in URB */
 
 	/* data and sync endpoints for this stream */
 	unsigned int ep_num;		/* the endpoint number */
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 93e970f..b9ba0fc 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -33,7 +33,6 @@
 #include "pcm.h"
 #include "quirks.h"
 
-#define EP_FLAG_ACTIVATED	0
 #define EP_FLAG_RUNNING		1
 #define EP_FLAG_STOPPING	2
 
@@ -426,9 +425,9 @@
 	list_for_each_entry(ep, &chip->ep_list, list) {
 		if (ep->ep_num == ep_num &&
 		    ep->iface == alts->desc.bInterfaceNumber &&
-		    ep->alt_idx == alts->desc.bAlternateSetting) {
+		    ep->altsetting == alts->desc.bAlternateSetting) {
 			snd_printdd(KERN_DEBUG "Re-using EP %x in iface %d,%d @%p\n",
-					ep_num, ep->iface, ep->alt_idx, ep);
+					ep_num, ep->iface, ep->altsetting, ep);
 			goto __exit_unlock;
 		}
 	}
@@ -447,7 +446,7 @@
 	ep->type = type;
 	ep->ep_num = ep_num;
 	ep->iface = alts->desc.bInterfaceNumber;
-	ep->alt_idx = alts->desc.bAlternateSetting;
+	ep->altsetting = alts->desc.bAlternateSetting;
 	INIT_LIST_HEAD(&ep->ready_playback_urbs);
 	ep_num &= USB_ENDPOINT_NUMBER_MASK;
 
@@ -574,11 +573,14 @@
 			      snd_pcm_format_t pcm_format,
 			      unsigned int channels,
 			      unsigned int period_bytes,
+			      unsigned int frames_per_period,
+			      unsigned int periods_per_buffer,
 			      struct audioformat *fmt,
 			      struct snd_usb_endpoint *sync_ep)
 {
-	unsigned int maxsize, i, urb_packs, total_packs, packs_per_ms;
-	int is_playback = usb_pipeout(ep->pipe);
+	unsigned int maxsize, minsize, packs_per_ms, max_packs_per_urb;
+	unsigned int max_packs_per_period, urbs_per_period, urb_packs;
+	unsigned int max_urbs, i;
 	int frame_bits = snd_pcm_format_physical_width(pcm_format) * channels;
 
 	if (pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE && fmt->dsd_dop) {
@@ -611,58 +613,67 @@
 	else
 		ep->curpacksize = maxsize;
 
-	if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL)
+	if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL) {
 		packs_per_ms = 8 >> ep->datainterval;
-	else
-		packs_per_ms = 1;
-
-	if (is_playback && !snd_usb_endpoint_implicit_feedback_sink(ep)) {
-		urb_packs = max(ep->chip->nrpacks, 1);
-		urb_packs = min(urb_packs, (unsigned int) MAX_PACKS);
+		max_packs_per_urb = MAX_PACKS_HS;
 	} else {
-		urb_packs = 1;
+		packs_per_ms = 1;
+		max_packs_per_urb = MAX_PACKS;
 	}
-
-	urb_packs *= packs_per_ms;
-
 	if (sync_ep && !snd_usb_endpoint_implicit_feedback_sink(ep))
-		urb_packs = min(urb_packs, 1U << sync_ep->syncinterval);
+		max_packs_per_urb = min(max_packs_per_urb,
+					1U << sync_ep->syncinterval);
+	max_packs_per_urb = max(1u, max_packs_per_urb >> ep->datainterval);
 
-	/* decide how many packets to be used */
-	if (is_playback && !snd_usb_endpoint_implicit_feedback_sink(ep)) {
-		unsigned int minsize, maxpacks;
+	/*
+	 * Capture endpoints need to use small URBs because there's no way
+	 * to tell in advance where the next period will end, and we don't
+	 * want the next URB to complete much after the period ends.
+	 *
+	 * Playback endpoints with implicit sync much use the same parameters
+	 * as their corresponding capture endpoint.
+	 */
+	if (usb_pipein(ep->pipe) ||
+			snd_usb_endpoint_implicit_feedback_sink(ep)) {
+
+		/* make capture URBs <= 1 ms and smaller than a period */
+		urb_packs = min(max_packs_per_urb, packs_per_ms);
+		while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
+			urb_packs >>= 1;
+		ep->nurbs = MAX_URBS;
+
+	/*
+	 * Playback endpoints without implicit sync are adjusted so that
+	 * a period fits as evenly as possible in the smallest number of
+	 * URBs.  The total number of URBs is adjusted to the size of the
+	 * ALSA buffer, subject to the MAX_URBS and MAX_QUEUE limits.
+	 */
+	} else {
 		/* determine how small a packet can be */
-		minsize = (ep->freqn >> (16 - ep->datainterval))
-			  * (frame_bits >> 3);
+		minsize = (ep->freqn >> (16 - ep->datainterval)) *
+				(frame_bits >> 3);
 		/* with sync from device, assume it can be 12% lower */
 		if (sync_ep)
 			minsize -= minsize >> 3;
 		minsize = max(minsize, 1u);
-		total_packs = (period_bytes + minsize - 1) / minsize;
-		/* we need at least two URBs for queueing */
-		if (total_packs < 2) {
-			total_packs = 2;
-		} else {
-			/* and we don't want too long a queue either */
-			maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2);
-			total_packs = min(total_packs, maxpacks);
-		}
-	} else {
-		while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
-			urb_packs >>= 1;
-		total_packs = MAX_URBS * urb_packs;
-	}
 
-	ep->nurbs = (total_packs + urb_packs - 1) / urb_packs;
-	if (ep->nurbs > MAX_URBS) {
-		/* too much... */
-		ep->nurbs = MAX_URBS;
-		total_packs = MAX_URBS * urb_packs;
-	} else if (ep->nurbs < 2) {
-		/* too little - we need at least two packets
-		 * to ensure contiguous playback/capture
-		 */
-		ep->nurbs = 2;
+		/* how many packets will contain an entire ALSA period? */
+		max_packs_per_period = DIV_ROUND_UP(period_bytes, minsize);
+
+		/* how many URBs will contain a period? */
+		urbs_per_period = DIV_ROUND_UP(max_packs_per_period,
+				max_packs_per_urb);
+		/* how many packets are needed in each URB? */
+		urb_packs = DIV_ROUND_UP(max_packs_per_period, urbs_per_period);
+
+		/* limit the number of frames in a single URB */
+		ep->max_urb_frames = DIV_ROUND_UP(frames_per_period,
+					urbs_per_period);
+
+		/* try to use enough URBs to contain an entire ALSA buffer */
+		max_urbs = min((unsigned) MAX_URBS,
+				MAX_QUEUE * packs_per_ms / urb_packs);
+		ep->nurbs = min(max_urbs, urbs_per_period * periods_per_buffer);
 	}
 
 	/* allocate and initialize data urbs */
@@ -670,8 +681,7 @@
 		struct snd_urb_ctx *u = &ep->urb[i];
 		u->index = i;
 		u->ep = ep;
-		u->packets = (i + 1) * total_packs / ep->nurbs
-			- i * total_packs / ep->nurbs;
+		u->packets = urb_packs;
 		u->buffer_size = maxsize * u->packets;
 
 		if (fmt->fmt_type == UAC_FORMAT_TYPE_II)
@@ -703,8 +713,7 @@
 /*
  * configure a sync endpoint
  */
-static int sync_ep_set_params(struct snd_usb_endpoint *ep,
-			      struct audioformat *fmt)
+static int sync_ep_set_params(struct snd_usb_endpoint *ep)
 {
 	int i;
 
@@ -748,6 +757,8 @@
  * @pcm_format: the audio fomat.
  * @channels: the number of audio channels.
  * @period_bytes: the number of bytes in one alsa period.
+ * @period_frames: the number of frames in one alsa period.
+ * @buffer_periods: the number of periods in one alsa buffer.
  * @rate: the frame rate.
  * @fmt: the USB audio format information
  * @sync_ep: the sync endpoint to use, if any
@@ -760,6 +771,8 @@
 				snd_pcm_format_t pcm_format,
 				unsigned int channels,
 				unsigned int period_bytes,
+				unsigned int period_frames,
+				unsigned int buffer_periods,
 				unsigned int rate,
 				struct audioformat *fmt,
 				struct snd_usb_endpoint *sync_ep)
@@ -793,10 +806,11 @@
 	switch (ep->type) {
 	case  SND_USB_ENDPOINT_TYPE_DATA:
 		err = data_ep_set_params(ep, pcm_format, channels,
-					 period_bytes, fmt, sync_ep);
+					 period_bytes, period_frames,
+					 buffer_periods, fmt, sync_ep);
 		break;
 	case  SND_USB_ENDPOINT_TYPE_SYNC:
-		err = sync_ep_set_params(ep, fmt);
+		err = sync_ep_set_params(ep);
 		break;
 	default:
 		err = -EINVAL;
@@ -931,28 +945,21 @@
  *
  * @ep: the endpoint to deactivate
  *
- * If the endpoint is not currently in use, this functions will select the
- * alternate interface setting 0 for the interface of this endpoint.
+ * If the endpoint is not currently in use, this functions will
+ * deactivate its associated URBs.
  *
  * In case of any active users, this functions does nothing.
- *
- * Returns an error if usb_set_interface() failed, 0 in all other
- * cases.
  */
-int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep)
+void snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep)
 {
 	if (!ep)
-		return -EINVAL;
+		return;
+
+	if (ep->use_count != 0)
+		return;
 
 	deactivate_urbs(ep, true);
 	wait_clear_urbs(ep);
-
-	if (ep->use_count != 0)
-		return 0;
-
-	clear_bit(EP_FLAG_ACTIVATED, &ep->flags);
-
-	return 0;
 }
 
 /**
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index 2287adf..1c7e8ee 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -12,6 +12,8 @@
 				snd_pcm_format_t pcm_format,
 				unsigned int channels,
 				unsigned int period_bytes,
+				unsigned int period_frames,
+				unsigned int buffer_periods,
 				unsigned int rate,
 				struct audioformat *fmt,
 				struct snd_usb_endpoint *sync_ep);
@@ -20,7 +22,7 @@
 void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep);
 int  snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
-int  snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
+void snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_free(struct list_head *head);
 
 int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep);
diff --git a/sound/usb/helper.c b/sound/usb/helper.c
index 6209024..51ed1ac 100644
--- a/sound/usb/helper.c
+++ b/sound/usb/helper.c
@@ -118,6 +118,7 @@
 {
 	switch (snd_usb_get_speed(chip->dev)) {
 	case USB_SPEED_HIGH:
+	case USB_SPEED_WIRELESS:
 	case USB_SPEED_SUPER:
 		if (get_endpoint(alts, 0)->bInterval >= 1 &&
 		    get_endpoint(alts, 0)->bInterval <= 4)
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 95558ef..44b0ba4 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1151,14 +1151,14 @@
 	const char *names_to_check[] = {
 		"Headset", "headset", "Headphone", "headphone", NULL};
 	const char **s;
-	bool found = 0;
+	bool found = false;
 
 	if (strcmp("Speaker", kctl->id.name))
 		return;
 
 	for (s = names_to_check; *s; s++)
 		if (strstr(card->shortname, *s)) {
-			found = 1;
+			found = true;
 			break;
 		}
 
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index b375d58..ca3256d 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -241,16 +241,17 @@
 		struct snd_usb_endpoint *ep = subs->sync_endpoint;
 
 		if (subs->data_endpoint->iface != subs->sync_endpoint->iface ||
-		    subs->data_endpoint->alt_idx != subs->sync_endpoint->alt_idx) {
+		    subs->data_endpoint->altsetting != subs->sync_endpoint->altsetting) {
 			err = usb_set_interface(subs->dev,
 						subs->sync_endpoint->iface,
-						subs->sync_endpoint->alt_idx);
+						subs->sync_endpoint->altsetting);
 			if (err < 0) {
+				clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);
 				snd_printk(KERN_ERR
 					   "%d:%d:%d: cannot set interface (%d)\n",
 					   subs->dev->devnum,
 					   subs->sync_endpoint->iface,
-					   subs->sync_endpoint->alt_idx, err);
+					   subs->sync_endpoint->altsetting, err);
 				return -EIO;
 			}
 		}
@@ -282,22 +283,6 @@
 	}
 }
 
-static int deactivate_endpoints(struct snd_usb_substream *subs)
-{
-	int reta, retb;
-
-	reta = snd_usb_endpoint_deactivate(subs->sync_endpoint);
-	retb = snd_usb_endpoint_deactivate(subs->data_endpoint);
-
-	if (reta < 0)
-		return reta;
-
-	if (retb < 0)
-		return retb;
-
-	return 0;
-}
-
 static int search_roland_implicit_fb(struct usb_device *dev, int ifnum,
 				     unsigned int altsetting,
 				     struct usb_host_interface **alts,
@@ -595,6 +580,7 @@
 						   subs->pcm_format,
 						   subs->channels,
 						   subs->period_bytes,
+						   0, 0,
 						   subs->cur_rate,
 						   subs->cur_audiofmt,
 						   NULL);
@@ -631,6 +617,7 @@
 					  subs->pcm_format,
 					  sync_fp->channels,
 					  sync_period_bytes,
+					  0, 0,
 					  subs->cur_rate,
 					  sync_fp,
 					  NULL);
@@ -653,6 +640,8 @@
 					  subs->pcm_format,
 					  subs->channels,
 					  subs->period_bytes,
+					  subs->period_frames,
+					  subs->buffer_periods,
 					  subs->cur_rate,
 					  subs->cur_audiofmt,
 					  subs->sync_endpoint);
@@ -689,6 +678,8 @@
 
 	subs->pcm_format = params_format(hw_params);
 	subs->period_bytes = params_period_bytes(hw_params);
+	subs->period_frames = params_period_size(hw_params);
+	subs->buffer_periods = params_periods(hw_params);
 	subs->channels = params_channels(hw_params);
 	subs->cur_rate = params_rate(hw_params);
 
@@ -730,7 +721,8 @@
 	down_read(&subs->stream->chip->shutdown_rwsem);
 	if (!subs->stream->chip->shutdown) {
 		stop_endpoints(subs, true);
-		deactivate_endpoints(subs);
+		snd_usb_endpoint_deactivate(subs->sync_endpoint);
+		snd_usb_endpoint_deactivate(subs->data_endpoint);
 	}
 	up_read(&subs->stream->chip->shutdown_rwsem);
 	return snd_pcm_lib_free_vmalloc_buffer(substream);
@@ -1363,6 +1355,7 @@
 	frames = 0;
 	urb->number_of_packets = 0;
 	spin_lock_irqsave(&subs->lock, flags);
+	subs->frame_limit += ep->max_urb_frames;
 	for (i = 0; i < ctx->packets; i++) {
 		if (ctx->packet_size[i])
 			counts = ctx->packet_size[i];
@@ -1377,6 +1370,7 @@
 		subs->transfer_done += counts;
 		if (subs->transfer_done >= runtime->period_size) {
 			subs->transfer_done -= runtime->period_size;
+			subs->frame_limit = 0;
 			period_elapsed = 1;
 			if (subs->fmt_type == UAC_FORMAT_TYPE_II) {
 				if (subs->transfer_done > 0) {
@@ -1399,8 +1393,10 @@
 				break;
 			}
 		}
-		if (period_elapsed &&
-		    !snd_usb_endpoint_implicit_feedback_sink(subs->data_endpoint)) /* finish at the period boundary */
+		/* finish at the period boundary or after enough frames */
+		if ((period_elapsed ||
+				subs->transfer_done >= subs->frame_limit) &&
+		    !snd_usb_endpoint_implicit_feedback_sink(ep))
 			break;
 	}
 	bytes = frames * ep->stride;
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index c4339f9..d737d0e 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -281,8 +281,6 @@
 	const unsigned int *maps;
 	int c;
 
-	if (!bits)
-		return NULL;
 	if (channels > ARRAY_SIZE(chmap->map))
 		return NULL;
 
@@ -293,9 +291,19 @@
 	maps = protocol == UAC_VERSION_2 ? uac2_maps : uac1_maps;
 	chmap->channels = channels;
 	c = 0;
-	for (; bits && *maps; maps++, bits >>= 1) {
-		if (bits & 1)
-			chmap->map[c++] = *maps;
+
+	if (bits) {
+		for (; bits && *maps; maps++, bits >>= 1)
+			if (bits & 1)
+				chmap->map[c++] = *maps;
+	} else {
+		/* If we're missing wChannelConfig, then guess something
+		    to make sure the channel map is not skipped entirely */
+		if (channels == 1)
+			chmap->map[c++] = SNDRV_CHMAP_MONO;
+		else
+			for (; c < channels && *maps; maps++)
+				chmap->map[c++] = *maps;
 	}
 
 	for (; c < channels; c++)
@@ -579,6 +587,7 @@
 
 			num_channels = as->bNrChannels;
 			format = le32_to_cpu(as->bmFormats);
+			chconfig = le32_to_cpu(as->bmChannelConfig);
 
 			/* lookup the terminal associated to this interface
 			 * to extract the clock */
@@ -586,7 +595,8 @@
 									    as->bTerminalLink);
 			if (input_term) {
 				clock = input_term->bCSourceID;
-				chconfig = le32_to_cpu(input_term->bmChannelConfig);
+				if (!chconfig && (num_channels == input_term->bNrChannels))
+					chconfig = le32_to_cpu(input_term->bmChannelConfig);
 				break;
 			}
 
@@ -652,7 +662,6 @@
 					* (fp->maxpacksize & 0x7ff);
 		fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
 		fp->clock = clock;
-		fp->chmap = convert_chmap(num_channels, chconfig, protocol);
 
 		/* some quirks for attributes here */
 
@@ -688,12 +697,16 @@
 		/* ok, let's parse further... */
 		if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream) < 0) {
 			kfree(fp->rate_table);
-			kfree(fp->chmap);
 			kfree(fp);
 			fp = NULL;
 			continue;
 		}
 
+		/* Create chmap */
+		if (fp->channels != num_channels)
+			chconfig = 0;
+		fp->chmap = convert_chmap(fp->channels, chconfig, protocol);
+
 		snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint);
 		err = snd_usb_add_audio_stream(chip, stream, fp);
 		if (err < 0) {
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index caabe9b..5d2fe05 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -55,7 +55,6 @@
 	struct list_head mixer_list;	/* list of mixer interfaces */
 
 	int setup;			/* from the 'device_setup' module param */
-	int nrpacks;			/* from the 'nrpacks' module param */
 	bool autoclock;			/* from the 'autoclock' module param */
 
 	struct usb_host_interface *ctrl_intf;	/* the audio control interface */
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c
index d0323a6..999550b 100644
--- a/sound/usb/usx2y/us122l.c
+++ b/sound/usb/usx2y/us122l.c
@@ -262,7 +262,9 @@
 	}
 
 	area->vm_ops = &usb_stream_hwdep_vm_ops;
-	area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
+	area->vm_flags |= VM_DONTDUMP;
+	if (!read)
+		area->vm_flags |= VM_DONTEXPAND;
 	area->vm_private_data = us122l;
 	atomic_inc(&us122l->mmap_count);
 out:
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index 63fb521..6234a51 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -299,19 +299,6 @@
 	usX2Y_clients_stop(usX2Y);
 }
 
-static void usX2Y_error_sequence(struct usX2Ydev *usX2Y,
-				 struct snd_usX2Y_substream *subs, struct urb *urb)
-{
-	snd_printk(KERN_ERR
-"Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n"
-"Most probably some urb of usb-frame %i is still missing.\n"
-"Cause could be too long delays in usb-hcd interrupt handling.\n",
-		   usb_get_current_frame_number(usX2Y->dev),
-		   subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
-		   usX2Y->wait_iso_frame, urb->start_frame, usX2Y->wait_iso_frame);
-	usX2Y_clients_stop(usX2Y);
-}
-
 static void i_usX2Y_urb_complete(struct urb *urb)
 {
 	struct snd_usX2Y_substream *subs = urb->context;
@@ -328,12 +315,9 @@
 		usX2Y_error_urb_status(usX2Y, subs, urb);
 		return;
 	}
-	if (likely((urb->start_frame & 0xFFFF) == (usX2Y->wait_iso_frame & 0xFFFF)))
-		subs->completed_urb = urb;
-	else {
-		usX2Y_error_sequence(usX2Y, subs, urb);
-		return;
-	}
+
+	subs->completed_urb = urb;
+
 	{
 		struct snd_usX2Y_substream *capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE],
 			*playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK];
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
index f2a1acd..814d0e8 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -244,13 +244,8 @@
 		usX2Y_error_urb_status(usX2Y, subs, urb);
 		return;
 	}
-	if (likely((urb->start_frame & 0xFFFF) == (usX2Y->wait_iso_frame & 0xFFFF)))
-		subs->completed_urb = urb;
-	else {
-		usX2Y_error_sequence(usX2Y, subs, urb);
-		return;
-	}
 
+	subs->completed_urb = urb;
 	capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE];
 	capsubs2 = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2];
 	playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK];
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 8fd9ec6..b8d6d54 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -89,6 +89,7 @@
 static char *os_build;
 static char *os_version;
 static char *lic_version = "Unknown version";
+static char full_domain_name[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
 static struct utsname uts_buf;
 
 /*
@@ -1367,7 +1368,7 @@
 }
 
 
-static int
+static void
 kvp_get_domain_name(char *buffer, int length)
 {
 	struct addrinfo	hints, *info ;
@@ -1381,12 +1382,12 @@
 
 	error = getaddrinfo(buffer, NULL, &hints, &info);
 	if (error != 0) {
-		strcpy(buffer, "getaddrinfo failed\n");
-		return error;
+		snprintf(buffer, length, "getaddrinfo failed: 0x%x %s",
+			error, gai_strerror(error));
+		return;
 	}
-	strcpy(buffer, info->ai_canonname);
+	snprintf(buffer, length, "%s", info->ai_canonname);
 	freeaddrinfo(info);
-	return error;
 }
 
 static int
@@ -1433,7 +1434,6 @@
 	int	pool;
 	char	*if_name;
 	struct hv_kvp_ipaddr_value *kvp_ip_val;
-	char *kvp_send_buffer;
 	char *kvp_recv_buffer;
 	size_t kvp_recv_buffer_len;
 
@@ -1442,17 +1442,21 @@
 	openlog("KVP", 0, LOG_USER);
 	syslog(LOG_INFO, "KVP starting; pid is:%d", getpid());
 
-	kvp_recv_buffer_len = NLMSG_HDRLEN + sizeof(struct cn_msg) + sizeof(struct hv_kvp_msg);
-	kvp_send_buffer = calloc(1, kvp_recv_buffer_len);
+	kvp_recv_buffer_len = NLMSG_LENGTH(0) + sizeof(struct cn_msg) + sizeof(struct hv_kvp_msg);
 	kvp_recv_buffer = calloc(1, kvp_recv_buffer_len);
-	if (!(kvp_send_buffer && kvp_recv_buffer)) {
-		syslog(LOG_ERR, "Failed to allocate netlink buffers");
+	if (!kvp_recv_buffer) {
+		syslog(LOG_ERR, "Failed to allocate netlink buffer");
 		exit(EXIT_FAILURE);
 	}
 	/*
 	 * Retrieve OS release information.
 	 */
 	kvp_get_os_info();
+	/*
+	 * Cache Fully Qualified Domain Name because getaddrinfo takes an
+	 * unpredictable amount of time to finish.
+	 */
+	kvp_get_domain_name(full_domain_name, sizeof(full_domain_name));
 
 	if (kvp_file_init()) {
 		syslog(LOG_ERR, "Failed to initialize the pools");
@@ -1488,7 +1492,7 @@
 	/*
 	 * Register ourselves with the kernel.
 	 */
-	message = (struct cn_msg *)kvp_send_buffer;
+	message = (struct cn_msg *)kvp_recv_buffer;
 	message->id.idx = CN_KVP_IDX;
 	message->id.val = CN_KVP_VAL;
 
@@ -1671,8 +1675,7 @@
 
 		switch (hv_msg->body.kvp_enum_data.index) {
 		case FullyQualifiedDomainName:
-			kvp_get_domain_name(key_value,
-					HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
+			strcpy(key_value, full_domain_name);
 			strcpy(key_name, "FullyQualifiedDomainName");
 			break;
 		case IntegrationServicesVersion:
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c
index 8611962..8bcb040 100644
--- a/tools/hv/hv_vss_daemon.c
+++ b/tools/hv/hv_vss_daemon.c
@@ -140,7 +140,6 @@
 	struct cn_msg	*incoming_cn_msg;
 	int	op;
 	struct hv_vss_msg *vss_msg;
-	char *vss_send_buffer;
 	char *vss_recv_buffer;
 	size_t vss_recv_buffer_len;
 
@@ -150,10 +149,9 @@
 	openlog("Hyper-V VSS", 0, LOG_USER);
 	syslog(LOG_INFO, "VSS starting; pid is:%d", getpid());
 
-	vss_recv_buffer_len = NLMSG_HDRLEN + sizeof(struct cn_msg) + sizeof(struct hv_vss_msg);
-	vss_send_buffer = calloc(1, vss_recv_buffer_len);
+	vss_recv_buffer_len = NLMSG_LENGTH(0) + sizeof(struct cn_msg) + sizeof(struct hv_vss_msg);
 	vss_recv_buffer = calloc(1, vss_recv_buffer_len);
-	if (!(vss_send_buffer && vss_recv_buffer)) {
+	if (!vss_recv_buffer) {
 		syslog(LOG_ERR, "Failed to allocate netlink buffers");
 		exit(EXIT_FAILURE);
 	}
@@ -185,7 +183,7 @@
 	/*
 	 * Register ourselves with the kernel.
 	 */
-	message = (struct cn_msg *)vss_send_buffer;
+	message = (struct cn_msg *)vss_recv_buffer;
 	message->id.idx = CN_VSS_IDX;
 	message->id.val = CN_VSS_VAL;
 	message->ack = 0;
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index ca6cb77..fc15020 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -134,14 +134,14 @@
   print_install =
 else
   Q = @
-  print_compile =		echo '  CC                 '$(OBJ);
-  print_app_build =		echo '  BUILD              '$(OBJ);
-  print_fpic_compile =		echo '  CC FPIC            '$(OBJ);
-  print_shared_lib_compile =	echo '  BUILD SHARED LIB   '$(OBJ);
-  print_plugin_obj_compile =	echo '  CC PLUGIN OBJ      '$(OBJ);
-  print_plugin_build =		echo '  CC PLUGI           '$(OBJ);
-  print_static_lib_build =	echo '  BUILD STATIC LIB   '$(OBJ);
-  print_install =		echo '  INSTALL     '$1'	to	$(DESTDIR_SQ)$2';
+  print_compile =		echo '  CC       '$(OBJ);
+  print_app_build =		echo '  BUILD    '$(OBJ);
+  print_fpic_compile =		echo '  CC FPIC  '$(OBJ);
+  print_shared_lib_compile =	echo '  BUILD    SHARED LIB '$(OBJ);
+  print_plugin_obj_compile =	echo '  BUILD    PLUGIN OBJ '$(OBJ);
+  print_plugin_build =		echo '  BUILD    PLUGIN     '$(OBJ);
+  print_static_lib_build =	echo '  BUILD    STATIC LIB '$(OBJ);
+  print_install =		echo '  INSTALL  '$1'	to	$(DESTDIR_SQ)$2';
 endif
 
 do_fpic_compile =					\
@@ -268,7 +268,7 @@
 TRACEEVENT-CFLAGS: force
 	@FLAGS='$(TRACK_CFLAGS)'; \
 	    if test x"$$FLAGS" != x"`cat TRACEEVENT-CFLAGS 2>/dev/null`" ; then \
-		echo 1>&2 "    * new build flags or cross compiler"; \
+		echo 1>&2 "  FLAGS:   * new build flags or cross compiler"; \
 		echo "$$FLAGS" >TRACEEVENT-CFLAGS; \
             fi
 
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index d1c2a6a..8f450ad 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -305,6 +305,11 @@
 	return 0;
 }
 
+void pevent_register_trace_clock(struct pevent *pevent, char *trace_clock)
+{
+	pevent->trace_clock = trace_clock;
+}
+
 struct func_map {
 	unsigned long long		addr;
 	char				*func;
@@ -599,10 +604,11 @@
  * This registers a string by the address it was stored in the kernel.
  * The @fmt passed in is duplicated.
  */
-int pevent_register_print_string(struct pevent *pevent, char *fmt,
+int pevent_register_print_string(struct pevent *pevent, const char *fmt,
 				 unsigned long long addr)
 {
 	struct printk_list *item = malloc(sizeof(*item));
+	char *p;
 
 	if (!item)
 		return -1;
@@ -610,10 +616,21 @@
 	item->next = pevent->printklist;
 	item->addr = addr;
 
+	/* Strip off quotes and '\n' from the end */
+	if (fmt[0] == '"')
+		fmt++;
 	item->printk = strdup(fmt);
 	if (!item->printk)
 		goto out_free;
 
+	p = item->printk + strlen(item->printk) - 1;
+	if (*p == '"')
+		*p = 0;
+
+	p -= 2;
+	if (strcmp(p, "\\n") == 0)
+		*p = 0;
+
 	pevent->printklist = item;
 	pevent->printk_count++;
 
@@ -3488,6 +3505,7 @@
 	struct pevent *pevent = event->pevent;
 	struct print_flag_sym *flag;
 	struct format_field *field;
+	struct printk_map *printk;
 	unsigned long long val, fval;
 	unsigned long addr;
 	char *str;
@@ -3523,7 +3541,12 @@
 		if (!(field->flags & FIELD_IS_ARRAY) &&
 		    field->size == pevent->long_size) {
 			addr = *(unsigned long *)(data + field->offset);
-			trace_seq_printf(s, "%lx", addr);
+			/* Check if it matches a print format */
+			printk = find_printk(pevent, addr);
+			if (printk)
+				trace_seq_puts(s, printk->printk);
+			else
+				trace_seq_printf(s, "%lx", addr);
 			break;
 		}
 		str = malloc(len + 1);
@@ -3565,15 +3588,23 @@
 		}
 		break;
 	case PRINT_HEX:
-		field = arg->hex.field->field.field;
-		if (!field) {
-			str = arg->hex.field->field.name;
-			field = pevent_find_any_field(event, str);
-			if (!field)
-				goto out_warning_field;
-			arg->hex.field->field.field = field;
+		if (arg->hex.field->type == PRINT_DYNAMIC_ARRAY) {
+			unsigned long offset;
+			offset = pevent_read_number(pevent,
+				data + arg->hex.field->dynarray.field->offset,
+				arg->hex.field->dynarray.field->size);
+			hex = data + (offset & 0xffff);
+		} else {
+			field = arg->hex.field->field.field;
+			if (!field) {
+				str = arg->hex.field->field.name;
+				field = pevent_find_any_field(event, str);
+				if (!field)
+					goto out_warning_field;
+				arg->hex.field->field.field = field;
+			}
+			hex = data + field->offset;
 		}
-		hex = data + field->offset;
 		len = eval_num_arg(data, size, event, arg->hex.size);
 		for (i = 0; i < len; i++) {
 			if (i)
@@ -3771,8 +3802,8 @@
 	if (asprintf(&arg->atom.atom, "%lld", ip) < 0)
 		goto out_free;
 
-	/* skip the first "%pf : " */
-	for (ptr = fmt + 6, bptr = data + field->offset;
+	/* skip the first "%pf: " */
+	for (ptr = fmt + 5, bptr = data + field->offset;
 	     bptr < data + size && *ptr; ptr++) {
 		int ls = 0;
 
@@ -3882,7 +3913,6 @@
 	struct format_field *field;
 	struct printk_map *printk;
 	char *format;
-	char *p;
 
 	field = pevent->bprint_fmt_field;
 
@@ -3899,25 +3929,13 @@
 
 	printk = find_printk(pevent, addr);
 	if (!printk) {
-		if (asprintf(&format, "%%pf : (NO FORMAT FOUND at %llx)\n", addr) < 0)
+		if (asprintf(&format, "%%pf: (NO FORMAT FOUND at %llx)\n", addr) < 0)
 			return NULL;
 		return format;
 	}
 
-	p = printk->printk;
-	/* Remove any quotes. */
-	if (*p == '"')
-		p++;
-	if (asprintf(&format, "%s : %s", "%pf", p) < 0)
+	if (asprintf(&format, "%s: %s", "%pf", printk->printk) < 0)
 		return NULL;
-	/* remove ending quotes and new line since we will add one too */
-	p = format + strlen(format) - 1;
-	if (*p == '"')
-		*p = 0;
-
-	p -= 2;
-	if (strcmp(p, "\\n") == 0)
-		*p = 0;
 
 	return format;
 }
@@ -3963,7 +3981,7 @@
 	unsigned int i;
 
 	for (i = 0; i < len && p[i]; i++)
-		if (!isprint(p[i]))
+		if (!isprint(p[i]) && !isspace(p[i]))
 		    return 0;
 	return 1;
 }
@@ -4428,11 +4446,11 @@
 {
 	int print_pretty = 1;
 
-	if (event->pevent->print_raw)
+	if (event->pevent->print_raw || (event->flags & EVENT_FL_PRINTRAW))
 		print_event_fields(s, record->data, record->size, event);
 	else {
 
-		if (event->handler)
+		if (event->handler && !(event->flags & EVENT_FL_NOHANDLE))
 			print_pretty = event->handler(s, record, event,
 						      event->context);
 
@@ -4443,8 +4461,21 @@
 	trace_seq_terminate(s);
 }
 
+static bool is_timestamp_in_us(char *trace_clock, bool use_trace_clock)
+{
+	if (!use_trace_clock)
+		return true;
+
+	if (!strcmp(trace_clock, "local") || !strcmp(trace_clock, "global")
+	    || !strcmp(trace_clock, "uptime") || !strcmp(trace_clock, "perf"))
+		return true;
+
+	/* trace_clock is setting in tsc or counter mode */
+	return false;
+}
+
 void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
-			struct pevent_record *record)
+			struct pevent_record *record, bool use_trace_clock)
 {
 	static const char *spaces = "                    "; /* 20 spaces */
 	struct event_format *event;
@@ -4457,9 +4488,14 @@
 	int pid;
 	int len;
 	int p;
+	bool use_usec_format;
 
-	secs = record->ts / NSECS_PER_SEC;
-	nsecs = record->ts - secs * NSECS_PER_SEC;
+	use_usec_format = is_timestamp_in_us(pevent->trace_clock,
+							use_trace_clock);
+	if (use_usec_format) {
+		secs = record->ts / NSECS_PER_SEC;
+		nsecs = record->ts - secs * NSECS_PER_SEC;
+	}
 
 	if (record->size < 0) {
 		do_warning("ug! negative record size %d", record->size);
@@ -4484,15 +4520,20 @@
 	} else
 		trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu);
 
-	if (pevent->flags & PEVENT_NSEC_OUTPUT) {
-		usecs = nsecs;
-		p = 9;
-	} else {
-		usecs = (nsecs + 500) / NSECS_PER_USEC;
-		p = 6;
-	}
+	if (use_usec_format) {
+		if (pevent->flags & PEVENT_NSEC_OUTPUT) {
+			usecs = nsecs;
+			p = 9;
+		} else {
+			usecs = (nsecs + 500) / NSECS_PER_USEC;
+			p = 6;
+		}
 
-	trace_seq_printf(s, " %5lu.%0*lu: %s: ", secs, p, usecs, event->name);
+		trace_seq_printf(s, " %5lu.%0*lu: %s: ",
+					secs, p, usecs, event->name);
+	} else
+		trace_seq_printf(s, " %12llu: %s: ",
+					record->ts, event->name);
 
 	/* Space out the event names evenly. */
 	len = strlen(event->name);
@@ -5326,6 +5367,48 @@
 	return -1;
 }
 
+/**
+ * pevent_print_func_field - print a field and a format for function pointers
+ * @s: The seq to print to
+ * @fmt: The printf format to print the field with.
+ * @event: the event that the field is for
+ * @name: The name of the field
+ * @record: The record with the field name.
+ * @err: print default error if failed.
+ *
+ * Returns: 0 on success, -1 field not found, or 1 if buffer is full.
+ */
+int pevent_print_func_field(struct trace_seq *s, const char *fmt,
+			    struct event_format *event, const char *name,
+			    struct pevent_record *record, int err)
+{
+	struct format_field *field = pevent_find_field(event, name);
+	struct pevent *pevent = event->pevent;
+	unsigned long long val;
+	struct func_map *func;
+	char tmp[128];
+
+	if (!field)
+		goto failed;
+
+	if (pevent_read_number_field(field, record->data, &val))
+		goto failed;
+
+	func = find_func(pevent, val);
+
+	if (func)
+		snprintf(tmp, 128, "%s/0x%llx", func->func, func->addr - val);
+	else
+		sprintf(tmp, "0x%08llx", val);
+
+	return trace_seq_printf(s, fmt, tmp);
+
+ failed:
+	if (err)
+		trace_seq_printf(s, "CAN'T FIND FIELD \"%s\"", name);
+	return -1;
+}
+
 static void free_func_handle(struct pevent_function_handler *func)
 {
 	struct pevent_func_params *params;
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index c37b202..8d73d25 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -20,6 +20,7 @@
 #ifndef _PARSE_EVENTS_H
 #define _PARSE_EVENTS_H
 
+#include <stdbool.h>
 #include <stdarg.h>
 #include <regex.h>
 
@@ -307,6 +308,8 @@
 	EVENT_FL_ISBPRINT	= 0x04,
 	EVENT_FL_ISFUNCENT	= 0x10,
 	EVENT_FL_ISFUNCRET	= 0x20,
+	EVENT_FL_NOHANDLE	= 0x40,
+	EVENT_FL_PRINTRAW	= 0x80,
 
 	EVENT_FL_FAILED		= 0x80000000
 };
@@ -450,6 +453,8 @@
 
 	/* cache */
 	struct event_format *last_event;
+
+	char *trace_clock;
 };
 
 static inline void pevent_set_flag(struct pevent *pevent, int flag)
@@ -527,14 +532,15 @@
 };
 
 int pevent_register_comm(struct pevent *pevent, const char *comm, int pid);
+void pevent_register_trace_clock(struct pevent *pevent, char *trace_clock);
 int pevent_register_function(struct pevent *pevent, char *name,
 			     unsigned long long addr, char *mod);
-int pevent_register_print_string(struct pevent *pevent, char *fmt,
+int pevent_register_print_string(struct pevent *pevent, const char *fmt,
 				 unsigned long long addr);
 int pevent_pid_is_registered(struct pevent *pevent, int pid);
 
 void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
-			struct pevent_record *record);
+			struct pevent_record *record, bool use_trace_clock);
 
 int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size,
 			     int long_size);
@@ -563,6 +569,10 @@
 			   struct event_format *event, const char *name,
 			   struct pevent_record *record, int err);
 
+int pevent_print_func_field(struct trace_seq *s, const char *fmt,
+			   struct event_format *event, const char *name,
+			   struct pevent_record *record, int err);
+
 int pevent_register_event_handler(struct pevent *pevent, int id,
 				  const char *sys_name, const char *event_name,
 				  pevent_event_handler_func func, void *context);
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 8f8fbc2..782d86e 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -13,6 +13,7 @@
 common-cmds.h
 perf.data
 perf.data.old
+output.svg
 perf-archive
 tags
 TAGS
diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile
index 5a37a7c..3ba1c0b 100644
--- a/tools/perf/Documentation/Makefile
+++ b/tools/perf/Documentation/Makefile
@@ -145,16 +145,17 @@
 
 ifneq ($(findstring $(MAKEFLAGS),s),s)
 ifneq ($(V),1)
-	QUIET_ASCIIDOC	= @echo '   ' ASCIIDOC $@;
-	QUIET_XMLTO	= @echo '   ' XMLTO $@;
-	QUIET_DB2TEXI	= @echo '   ' DB2TEXI $@;
-	QUIET_MAKEINFO	= @echo '   ' MAKEINFO $@;
-	QUIET_DBLATEX	= @echo '   ' DBLATEX $@;
-	QUIET_XSLTPROC	= @echo '   ' XSLTPROC $@;
-	QUIET_GEN	= @echo '   ' GEN $@;
+	QUIET_ASCIIDOC	= @echo '  ASCIIDOC '$@;
+	QUIET_XMLTO	= @echo '  XMLTO    '$@;
+	QUIET_DB2TEXI	= @echo '  DB2TEXI  '$@;
+	QUIET_MAKEINFO	= @echo '  MAKEINFO '$@;
+	QUIET_DBLATEX	= @echo '  DBLATEX  '$@;
+	QUIET_XSLTPROC	= @echo '  XSLTPROC '$@;
+	QUIET_GEN	= @echo '  GEN      '$@;
 	QUIET_STDERR	= 2> /dev/null
 	QUIET_SUBDIR0	= +@subdir=
-	QUIET_SUBDIR1	= ;$(NO_SUBDIR) echo '   ' SUBDIR $$subdir; \
+	QUIET_SUBDIR1	= ;$(NO_SUBDIR) \
+			   echo '  SUBDIR   ' $$subdir; \
 			  $(MAKE) $(PRINT_DIR) -C $$subdir
 	export V
 endif
@@ -183,47 +184,43 @@
 endif
 
 do-install-man: man
-	$(INSTALL) -d -m 755 $(DESTDIR)$(man1dir)
-#	$(INSTALL) -d -m 755 $(DESTDIR)$(man5dir)
-#	$(INSTALL) -d -m 755 $(DESTDIR)$(man7dir)
-	$(INSTALL) -m 644 $(DOC_MAN1) $(DESTDIR)$(man1dir)
-#	$(INSTALL) -m 644 $(DOC_MAN5) $(DESTDIR)$(man5dir)
-#	$(INSTALL) -m 644 $(DOC_MAN7) $(DESTDIR)$(man7dir)
+	$(call QUIET_INSTALL, Documentation-man) \
+		$(INSTALL) -d -m 755 $(DESTDIR)$(man1dir); \
+#		$(INSTALL) -d -m 755 $(DESTDIR)$(man5dir); \
+#		$(INSTALL) -d -m 755 $(DESTDIR)$(man7dir); \
+		$(INSTALL) -m 644 $(DOC_MAN1) $(DESTDIR)$(man1dir); \
+#		$(INSTALL) -m 644 $(DOC_MAN5) $(DESTDIR)$(man5dir); \
+#		$(INSTALL) -m 644 $(DOC_MAN7) $(DESTDIR)$(man7dir)
 
 install-man: check-man-tools man
 
-try-install-man:
 ifdef missing_tools
-	$(warning Please install $(missing_tools) to have the man pages installed)
+  DO_INSTALL_MAN = $(warning Please install $(missing_tools) to have the man pages installed)
 else
-	$(MAKE) do-install-man
+  DO_INSTALL_MAN = do-install-man
 endif
 
+try-install-man: $(DO_INSTALL_MAN)
+
 install-info: info
-	$(INSTALL) -d -m 755 $(DESTDIR)$(infodir)
-	$(INSTALL) -m 644 $(OUTPUT)perf.info $(OUTPUT)perfman.info $(DESTDIR)$(infodir)
+	$(call QUIET_INSTALL, Documentation-info) \
+		$(INSTALL) -d -m 755 $(DESTDIR)$(infodir); \
+		$(INSTALL) -m 644 $(OUTPUT)perf.info $(OUTPUT)perfman.info $(DESTDIR)$(infodir); \
 	if test -r $(DESTDIR)$(infodir)/dir; then \
-	  $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perf.info ;\
-	  $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perfman.info ;\
+		$(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perf.info ;\
+		$(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perfman.info ;\
 	else \
 	  echo "No directory found in $(DESTDIR)$(infodir)" >&2 ; \
 	fi
 
 install-pdf: pdf
-	$(INSTALL) -d -m 755 $(DESTDIR)$(pdfdir)
-	$(INSTALL) -m 644 $(OUTPUT)user-manual.pdf $(DESTDIR)$(pdfdir)
+	$(call QUIET_INSTALL, Documentation-pdf) \
+		$(INSTALL) -d -m 755 $(DESTDIR)$(pdfdir); \
+		$(INSTALL) -m 644 $(OUTPUT)user-manual.pdf $(DESTDIR)$(pdfdir)
 
 #install-html: html
 #	'$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir)
 
-ifneq ($(MAKECMDGOALS),clean)
-ifneq ($(MAKECMDGOALS),tags)
-$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
-	$(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) $(OUTPUT)PERF-VERSION-FILE
-
--include $(OUTPUT)PERF-VERSION-FILE
-endif
-endif
 
 #
 # Determine "include::" file references in asciidoc files.
@@ -253,15 +250,17 @@
 	$(PERL_PATH) ./cmd-list.perl ../command-list.txt $(QUIET_STDERR) && \
 	date >$@
 
+CLEAN_FILES =									\
+	$(MAN_XML) $(addsuffix +,$(MAN_XML))					\
+	$(MAN_HTML) $(addsuffix +,$(MAN_HTML))					\
+	$(DOC_HTML) $(DOC_MAN1) $(DOC_MAN5) $(DOC_MAN7)				\
+	$(OUTPUT)*.texi $(OUTPUT)*.texi+ $(OUTPUT)*.texi++			\
+	$(OUTPUT)perf.info $(OUTPUT)perfman.info				\
+	$(OUTPUT)howto-index.txt $(OUTPUT)howto/*.html $(OUTPUT)doc.dep		\
+	$(OUTPUT)technical/api-*.html $(OUTPUT)technical/api-index.txt		\
+	$(cmds_txt) $(OUTPUT)*.made
 clean:
-	$(RM) $(MAN_XML) $(addsuffix +,$(MAN_XML))
-	$(RM) $(MAN_HTML) $(addsuffix +,$(MAN_HTML))
-	$(RM) $(DOC_HTML) $(DOC_MAN1) $(DOC_MAN5) $(DOC_MAN7)
-	$(RM) $(OUTPUT)*.texi $(OUTPUT)*.texi+ $(OUTPUT)*.texi++
-	$(RM) $(OUTPUT)perf.info $(OUTPUT)perfman.info
-	$(RM) $(OUTPUT)howto-index.txt $(OUTPUT)howto/*.html $(OUTPUT)doc.dep
-	$(RM) $(OUTPUT)technical/api-*.html $(OUTPUT)technical/api-index.txt
-	$(RM) $(cmds_txt) $(OUTPUT)*.made
+	$(call QUIET_CLEAN, Documentation) $(RM) $(CLEAN_FILES)
 
 $(MAN_HTML): $(OUTPUT)%.html : %.txt
 	$(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
@@ -342,5 +341,3 @@
 
 #quick-install-html:
 #	'$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(HTML_REF) $(DESTDIR)$(htmldir)
-
-.PHONY: .FORCE-PERF-VERSION-FILE
diff --git a/tools/perf/Documentation/perf-buildid-cache.txt b/tools/perf/Documentation/perf-buildid-cache.txt
index e9a8349..fd77d81 100644
--- a/tools/perf/Documentation/perf-buildid-cache.txt
+++ b/tools/perf/Documentation/perf-buildid-cache.txt
@@ -21,6 +21,19 @@
 -a::
 --add=::
         Add specified file to the cache.
+-k::
+--kcore::
+        Add specified kcore file to the cache. For the current host that is
+        /proc/kcore which requires root permissions to read. Be aware that
+        running 'perf buildid-cache' as root may update root's build-id cache
+        not the user's. Use the -v option to see where the file is created.
+        Note that the copied file contains only code sections not the whole core
+        image. Note also that files "kallsyms" and "modules" must also be in the
+        same directory and are also copied.  All 3 files are created with read
+        permissions for root only. kcore will not be added if there is already a
+        kcore in the cache (with the same build-id) that has the same modules at
+        the same addresses. Use the -v option to see if a copy of kcore is
+        actually made.
 -r::
 --remove=::
         Remove specified file from the cache.
diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt
index ac84db2..6a06cef 100644
--- a/tools/perf/Documentation/perf-kvm.txt
+++ b/tools/perf/Documentation/perf-kvm.txt
@@ -109,7 +109,9 @@
 
 -m::
 --mmap-pages=::
-    Number of mmap data pages. Must be a power of two.
+    Number of mmap data pages (must be a power of two) or size
+    specification with appended unit character - B/K/M/G. The
+    size is rounded up to have nearest pages power of two value.
 
 -a::
 --all-cpus::
diff --git a/tools/perf/Documentation/perf-lock.txt b/tools/perf/Documentation/perf-lock.txt
index c7f5f55..ab25be2 100644
--- a/tools/perf/Documentation/perf-lock.txt
+++ b/tools/perf/Documentation/perf-lock.txt
@@ -48,7 +48,7 @@
 -k::
 --key=<value>::
         Sorting key. Possible values: acquired (default), contended,
-        wait_total, wait_max, wait_min.
+	avg_wait, wait_total, wait_max, wait_min.
 
 INFO OPTIONS
 ------------
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index e297b74..052f7c4 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -87,11 +87,25 @@
 
 -m::
 --mmap-pages=::
-	Number of mmap data pages. Must be a power of two.
+	Number of mmap data pages (must be a power of two) or size
+	specification with appended unit character - B/K/M/G. The
+	size is rounded up to have nearest pages power of two value.
 
 -g::
+	Enables call-graph (stack chain/backtrace) recording.
+
 --call-graph::
-	Do call-graph (stack chain/backtrace) recording.
+	Setup and enable call-graph (stack chain/backtrace) recording,
+	implies -g.
+
+	Allows specifying "fp" (frame pointer) or "dwarf"
+	(DWARF's CFI - Call Frame Information) as the method to collect
+	the information used to show the call graphs.
+
+	In some systems, where binaries are build with gcc
+	--fomit-frame-pointer, using the "fp" method will produce bogus
+	call graphs, using "dwarf", if available (perf tools linked to
+	the libunwind library) should be used instead.
 
 -q::
 --quiet::
@@ -166,6 +180,9 @@
         - u:  only when the branch target is at the user level
         - k: only when the branch target is in the kernel
         - hv: only when the target is at the hypervisor level
+	- in_tx: only when the target is in a hardware transaction
+	- no_tx: only when the target is not in a hardware transaction
+	- abort_tx: only when the target is a hardware transaction abort
 
 +
 The option requires at least one branch type among any, any_call, any_ret, ind_call.
@@ -176,12 +193,14 @@
 The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k
 Note that this feature may not be available on all processors.
 
--W::
 --weight::
 Enable weightened sampling. An additional weight is recorded per sample and can be
 displayed with the weight and local_weight sort keys.  This currently works for TSX
 abort events and some memory events in precise mode on modern Intel CPUs.
 
+--transaction::
+Record transaction flags for transaction related events.
+
 SEE ALSO
 --------
 linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 2b8097e..10a2798 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -71,7 +71,11 @@
 	entries are displayed as "[other]".
 	- cpu: cpu number the task ran at the time of sample
 	- srcline: filename and line number executed at the time of sample.  The
-	DWARF debuggin info must be provided.
+	DWARF debugging info must be provided.
+	- weight: Event specific weight, e.g. memory latency or transaction
+	abort cost. This is the global weight.
+	- local_weight: Local weight version of the weight above.
+	- transaction: Transaction abort flags.
 
 	By default, comm, dso and symbol keys are used.
 	(i.e. --sort comm,dso,symbol)
@@ -85,6 +89,8 @@
 	- symbol_from: name of function branched from
 	- symbol_to: name of function branched to
 	- mispredict: "N" for predicted branch, "Y" for mispredicted branch
+	- in_tx: branch in TSX transaction
+	- abort: TSX transaction abort.
 
 	And default sort keys are changed to comm, dso_from, symbol_from, dso_to
 	and symbol_to, see '--branch-stack'.
@@ -135,6 +141,14 @@
 
 	Default: fractal,0.5,callee,function.
 
+--max-stack::
+	Set the stack depth limit when parsing the callchain, anything
+	beyond the specified depth will be ignored. This is a trade-off
+	between information loss and faster processing especially for
+	workloads that can have a very long callchain stack.
+
+	Default: 127
+
 -G::
 --inverted::
         alias for inverted caller based call graph.
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 73c9759..80c7da6 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -137,6 +137,11 @@
 After starting the program, wait msecs before measuring. This is useful to
 filter out the startup phase of the program, which is often very different.
 
+-T::
+--transaction::
+
+Print statistics of transactional execution if supported.
+
 EXAMPLES
 --------
 
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt
index 1632b0e..3ff8bd4 100644
--- a/tools/perf/Documentation/perf-timechart.txt
+++ b/tools/perf/Documentation/perf-timechart.txt
@@ -8,7 +8,8 @@
 SYNOPSIS
 --------
 [verse]
-'perf timechart' {record}
+'perf timechart' record <command>
+'perf timechart' [<options>]
 
 DESCRIPTION
 -----------
@@ -41,6 +42,18 @@
 --symfs=<directory>::
         Look for files with symbols relative to this directory.
 
+EXAMPLES
+--------
+
+$ perf timechart record git pull
+
+  [ perf record: Woken up 13 times to write data ]
+  [ perf record: Captured and wrote 4.253 MB perf.data (~185801 samples) ]
+
+$ perf timechart
+
+  Written 10.2 seconds of trace to output.svg.
+
 SEE ALSO
 --------
 linkperf:perf-record[1]
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 58d6598..7de01dd 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -68,7 +68,9 @@
 
 -m <pages>::
 --mmap-pages=<pages>::
-	Number of mmapped data pages.
+	Number of mmap data pages (must be a power of two) or size
+	specification with appended unit character - B/K/M/G. The
+	size is rounded up to have nearest pages power of two value.
 
 -p <pid>::
 --pid=<pid>::
@@ -112,7 +114,8 @@
 
 -s::
 --sort::
-	Sort by key(s): pid, comm, dso, symbol, parent, srcline, weight, local_weight.
+	Sort by key(s): pid, comm, dso, symbol, parent, srcline, weight,
+	local_weight, abort, in_tx, transaction
 
 -n::
 --show-nr-samples::
@@ -140,20 +143,20 @@
 --asm-raw::
 	Show raw instruction encoding of assembly instructions.
 
--G [type,min,order]::
+-G::
+	Enables call-graph (stack chain/backtrace) recording.
+
 --call-graph::
-        Display call chains using type, min percent threshold and order.
-	type can be either:
-	- flat: single column, linear exposure of call chains.
-	- graph: use a graph tree, displaying absolute overhead rates.
-	- fractal: like graph, but displays relative rates. Each branch of
-		 the tree is considered as a new profiled object.
+	Setup and enable call-graph (stack chain/backtrace) recording,
+	implies -G.
 
-	order can be either:
-	- callee: callee based call graph.
-	- caller: inverted caller based call graph.
+--max-stack::
+	Set the stack depth limit when parsing the callchain, anything
+	beyond the specified depth will be ignored. This is a trade-off
+	between information loss and faster processing especially for
+	workloads that can have a very long callchain stack.
 
-	Default: fractal,0.5,callee.
+	Default: 127
 
 --ignore-callees=<regex>::
         Ignore callees of the function(s) matching the given regex.
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index daccd2c..7b0497f 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -9,6 +9,7 @@
 --------
 [verse]
 'perf trace'
+'perf trace record'
 
 DESCRIPTION
 -----------
@@ -16,9 +17,14 @@
 syscalls, but other system events like pagefaults, task lifetime events,
 scheduling events, etc.
 
-Initially this is a live mode only tool, but eventually will work with
-perf.data files like the other tools, allowing a detached 'record' from
-analysis phases.
+This is a live mode tool in addition to working with perf.data files like
+the other perf tools. Files can be generated using the 'perf record' command
+but the session needs to include the raw_syscalls events (-e 'raw_syscalls:*').
+Alernatively, the 'perf trace record' can be used as a shortcut to
+automatically include the raw_syscalls events when writing events to a file.
+
+The following options apply to perf trace; options to perf trace record are
+found in the perf record man page.
 
 OPTIONS
 -------
@@ -59,7 +65,9 @@
 
 -m::
 --mmap-pages=::
-	Number of mmap data pages. Must be a power of two.
+	Number of mmap data pages (must be a power of two) or size
+	specification with appended unit character - B/K/M/G. The
+	size is rounded up to have nearest pages power of two value.
 
 -C::
 --cpu::
@@ -78,6 +86,21 @@
 --input
 	Process events from a given perf data file.
 
+-T
+--time
+	Print full timestamp rather time relative to first sample.
+
+--comm::
+        Show process COMM right beside its ID, on by default, disable with --no-comm.
+
+--summary::
+	Show a summary of syscalls by thread with min, max, and average times (in
+    msec) and relative stddev.
+
+--tool_stats::
+	Show tool stats such as number of times fd->pathname was discovered thru
+	hooking the open syscall return + vfs_getname or via reading /proc/pid/fd, etc.
+
 SEE ALSO
 --------
 linkperf:perf-record[1], linkperf:perf-script[1]
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 3a0ff7f..4835618 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -1,818 +1,79 @@
-include ../scripts/Makefile.include
-
-# The default target of this Makefile is...
-all:
-
-include config/utilities.mak
-
-# Define V to have a more verbose compile.
 #
-# Define O to save output files in a separate directory.
+# This is a simple wrapper Makefile that calls the main Makefile.perf
+# with a -j option to do parallel builds
 #
-# Define ARCH as name of target architecture if you want cross-builds.
-#
-# Define CROSS_COMPILE as prefix name of compiler if you want cross-builds.
-#
-# Define NO_LIBPERL to disable perl script extension.
-#
-# Define NO_LIBPYTHON to disable python script extension.
-#
-# Define PYTHON to point to the python binary if the default
-# `python' is not correct; for example: PYTHON=python2
-#
-# Define PYTHON_CONFIG to point to the python-config binary if
-# the default `$(PYTHON)-config' is not correct.
-#
-# Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8
-#
-# Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72.
-#
-# Define LDFLAGS=-static to build a static binary.
-#
-# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
-#
-# Define NO_DWARF if you do not want debug-info analysis feature at all.
-#
-# Define WERROR=0 to disable treating any warnings as errors.
-#
-# Define NO_NEWT if you do not want TUI support. (deprecated)
-#
-# Define NO_SLANG if you do not want TUI support.
-#
-# Define NO_GTK2 if you do not want GTK+ GUI support.
-#
-# Define NO_DEMANGLE if you do not want C++ symbol demangling.
-#
-# Define NO_LIBELF if you do not want libelf dependency (e.g. cross-builds)
-#
-# Define NO_LIBUNWIND if you do not want libunwind dependency for dwarf
-# backtrace post unwind.
-#
-# Define NO_BACKTRACE if you do not want stack backtrace debug feature
-#
-# Define NO_LIBNUMA if you do not want numa perf benchmark
-#
-# Define NO_LIBAUDIT if you do not want libaudit support
-#
-# Define NO_LIBBIONIC if you do not want bionic support
-
-ifeq ($(srctree),)
-srctree := $(patsubst %/,%,$(dir $(shell pwd)))
-srctree := $(patsubst %/,%,$(dir $(srctree)))
-#$(info Determined 'srctree' to be $(srctree))
-endif
-
-ifneq ($(objtree),)
-#$(info Determined 'objtree' to be $(objtree))
-endif
-
-ifneq ($(OUTPUT),)
-#$(info Determined 'OUTPUT' to be $(OUTPUT))
-endif
-
-$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
-	@$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
-
-CC = $(CROSS_COMPILE)gcc
-AR = $(CROSS_COMPILE)ar
-
-RM      = rm -f
-MKDIR   = mkdir
-FIND    = find
-INSTALL = install
-FLEX    = flex
-BISON   = bison
-STRIP   = strip
-
-LK_DIR          = $(srctree)/tools/lib/lk/
-TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
-
-# include config/Makefile by default and rule out
-# non-config cases
-config := 1
-
-NON_CONFIG_TARGETS := clean TAGS tags cscope help
-
-ifdef MAKECMDGOALS
-ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),)
-  config := 0
-endif
-endif
-
-ifeq ($(config),1)
-include config/Makefile
-endif
-
-export prefix bindir sharedir sysconfdir
-
-# sparse is architecture-neutral, which means that we need to tell it
-# explicitly what architecture to check for. Fix this up for yours..
-SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
-
-# Guard against environment variables
-BUILTIN_OBJS =
-LIB_H =
-LIB_OBJS =
-PYRF_OBJS =
-SCRIPT_SH =
-
-SCRIPT_SH += perf-archive.sh
-
-grep-libs = $(filter -l%,$(1))
-strip-libs = $(filter-out -l%,$(1))
-
-ifneq ($(OUTPUT),)
-  TE_PATH=$(OUTPUT)
-ifneq ($(subdir),)
-  LK_PATH=$(OUTPUT)/../lib/lk/
-else
-  LK_PATH=$(OUTPUT)
-endif
-else
-  TE_PATH=$(TRACE_EVENT_DIR)
-  LK_PATH=$(LK_DIR)
-endif
-
-LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
-export LIBTRACEEVENT
-
-LIBLK = $(LK_PATH)liblk.a
-export LIBLK
-
-# python extension build directories
-PYTHON_EXTBUILD     := $(OUTPUT)python_ext_build/
-PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
-PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
-export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
-
-python-clean := rm -rf $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
-
-PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
-PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBLK)
-
-$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
-	$(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \
-	  --quiet build_ext; \
-	mkdir -p $(OUTPUT)python && \
-	cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
-#
-# No Perl scripts right now:
+# If you want to invoke the perf build in some non-standard way then
+# you can use the 'make -f Makefile.perf' method to invoke it.
 #
 
-SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
+#
+# Clear out the built-in rules GNU make defines by default (such as .o targets),
+# so that we pass through all targets to Makefile.perf:
+#
+.SUFFIXES:
 
 #
-# Single 'perf' binary right now:
+# We don't want to pass along options like -j:
 #
-PROGRAMS += $(OUTPUT)perf
+unexport MAKEFLAGS
 
-# what 'all' will build and 'install' will install, in perfexecdir
-ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
-
-# what 'all' will build but not install in perfexecdir
-OTHER_PROGRAMS = $(OUTPUT)perf
-
-# Set paths to tools early so that they can be used for version tests.
-ifndef SHELL_PATH
-  SHELL_PATH = /bin/sh
-endif
-ifndef PERL_PATH
-  PERL_PATH = /usr/bin/perl
-endif
-
-export PERL_PATH
-
-$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
-	$(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c
-
-$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
-	$(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c -p parse_events_
-
-$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
-	$(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c
-
-$(OUTPUT)util/pmu-bison.c: util/pmu.y
-	$(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_
-
-$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
-$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
-
-LIB_FILE=$(OUTPUT)libperf.a
-
-LIB_H += ../../include/uapi/linux/perf_event.h
-LIB_H += ../../include/linux/rbtree.h
-LIB_H += ../../include/linux/list.h
-LIB_H += ../../include/uapi/linux/const.h
-LIB_H += ../../include/linux/hash.h
-LIB_H += ../../include/linux/stringify.h
-LIB_H += util/include/linux/bitmap.h
-LIB_H += util/include/linux/bitops.h
-LIB_H += util/include/linux/compiler.h
-LIB_H += util/include/linux/const.h
-LIB_H += util/include/linux/ctype.h
-LIB_H += util/include/linux/kernel.h
-LIB_H += util/include/linux/list.h
-LIB_H += util/include/linux/export.h
-LIB_H += util/include/linux/magic.h
-LIB_H += util/include/linux/poison.h
-LIB_H += util/include/linux/prefetch.h
-LIB_H += util/include/linux/rbtree.h
-LIB_H += util/include/linux/rbtree_augmented.h
-LIB_H += util/include/linux/string.h
-LIB_H += util/include/linux/types.h
-LIB_H += util/include/linux/linkage.h
-LIB_H += util/include/asm/asm-offsets.h
-LIB_H += util/include/asm/bug.h
-LIB_H += util/include/asm/byteorder.h
-LIB_H += util/include/asm/hweight.h
-LIB_H += util/include/asm/swab.h
-LIB_H += util/include/asm/system.h
-LIB_H += util/include/asm/uaccess.h
-LIB_H += util/include/dwarf-regs.h
-LIB_H += util/include/asm/dwarf2.h
-LIB_H += util/include/asm/cpufeature.h
-LIB_H += util/include/asm/unistd_32.h
-LIB_H += util/include/asm/unistd_64.h
-LIB_H += perf.h
-LIB_H += util/annotate.h
-LIB_H += util/cache.h
-LIB_H += util/callchain.h
-LIB_H += util/build-id.h
-LIB_H += util/debug.h
-LIB_H += util/sysfs.h
-LIB_H += util/pmu.h
-LIB_H += util/event.h
-LIB_H += util/evsel.h
-LIB_H += util/evlist.h
-LIB_H += util/exec_cmd.h
-LIB_H += util/types.h
-LIB_H += util/levenshtein.h
-LIB_H += util/machine.h
-LIB_H += util/map.h
-LIB_H += util/parse-options.h
-LIB_H += util/parse-events.h
-LIB_H += util/quote.h
-LIB_H += util/util.h
-LIB_H += util/xyarray.h
-LIB_H += util/header.h
-LIB_H += util/help.h
-LIB_H += util/session.h
-LIB_H += util/strbuf.h
-LIB_H += util/strlist.h
-LIB_H += util/strfilter.h
-LIB_H += util/svghelper.h
-LIB_H += util/tool.h
-LIB_H += util/run-command.h
-LIB_H += util/sigchain.h
-LIB_H += util/dso.h
-LIB_H += util/symbol.h
-LIB_H += util/color.h
-LIB_H += util/values.h
-LIB_H += util/sort.h
-LIB_H += util/hist.h
-LIB_H += util/thread.h
-LIB_H += util/thread_map.h
-LIB_H += util/trace-event.h
-LIB_H += util/probe-finder.h
-LIB_H += util/dwarf-aux.h
-LIB_H += util/probe-event.h
-LIB_H += util/pstack.h
-LIB_H += util/cpumap.h
-LIB_H += util/top.h
-LIB_H += $(ARCH_INCLUDE)
-LIB_H += util/cgroup.h
-LIB_H += $(LIB_INCLUDE)traceevent/event-parse.h
-LIB_H += util/target.h
-LIB_H += util/rblist.h
-LIB_H += util/intlist.h
-LIB_H += util/perf_regs.h
-LIB_H += util/unwind.h
-LIB_H += util/vdso.h
-LIB_H += ui/helpline.h
-LIB_H += ui/progress.h
-LIB_H += ui/util.h
-LIB_H += ui/ui.h
-
-LIB_OBJS += $(OUTPUT)util/abspath.o
-LIB_OBJS += $(OUTPUT)util/alias.o
-LIB_OBJS += $(OUTPUT)util/annotate.o
-LIB_OBJS += $(OUTPUT)util/build-id.o
-LIB_OBJS += $(OUTPUT)util/config.o
-LIB_OBJS += $(OUTPUT)util/ctype.o
-LIB_OBJS += $(OUTPUT)util/sysfs.o
-LIB_OBJS += $(OUTPUT)util/pmu.o
-LIB_OBJS += $(OUTPUT)util/environment.o
-LIB_OBJS += $(OUTPUT)util/event.o
-LIB_OBJS += $(OUTPUT)util/evlist.o
-LIB_OBJS += $(OUTPUT)util/evsel.o
-LIB_OBJS += $(OUTPUT)util/exec_cmd.o
-LIB_OBJS += $(OUTPUT)util/help.o
-LIB_OBJS += $(OUTPUT)util/levenshtein.o
-LIB_OBJS += $(OUTPUT)util/parse-options.o
-LIB_OBJS += $(OUTPUT)util/parse-events.o
-LIB_OBJS += $(OUTPUT)util/path.o
-LIB_OBJS += $(OUTPUT)util/rbtree.o
-LIB_OBJS += $(OUTPUT)util/bitmap.o
-LIB_OBJS += $(OUTPUT)util/hweight.o
-LIB_OBJS += $(OUTPUT)util/run-command.o
-LIB_OBJS += $(OUTPUT)util/quote.o
-LIB_OBJS += $(OUTPUT)util/strbuf.o
-LIB_OBJS += $(OUTPUT)util/string.o
-LIB_OBJS += $(OUTPUT)util/strlist.o
-LIB_OBJS += $(OUTPUT)util/strfilter.o
-LIB_OBJS += $(OUTPUT)util/top.o
-LIB_OBJS += $(OUTPUT)util/usage.o
-LIB_OBJS += $(OUTPUT)util/wrapper.o
-LIB_OBJS += $(OUTPUT)util/sigchain.o
-LIB_OBJS += $(OUTPUT)util/dso.o
-LIB_OBJS += $(OUTPUT)util/symbol.o
-LIB_OBJS += $(OUTPUT)util/symbol-elf.o
-LIB_OBJS += $(OUTPUT)util/color.o
-LIB_OBJS += $(OUTPUT)util/pager.o
-LIB_OBJS += $(OUTPUT)util/header.o
-LIB_OBJS += $(OUTPUT)util/callchain.o
-LIB_OBJS += $(OUTPUT)util/values.o
-LIB_OBJS += $(OUTPUT)util/debug.o
-LIB_OBJS += $(OUTPUT)util/machine.o
-LIB_OBJS += $(OUTPUT)util/map.o
-LIB_OBJS += $(OUTPUT)util/pstack.o
-LIB_OBJS += $(OUTPUT)util/session.o
-LIB_OBJS += $(OUTPUT)util/thread.o
-LIB_OBJS += $(OUTPUT)util/thread_map.o
-LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
-LIB_OBJS += $(OUTPUT)util/parse-events-flex.o
-LIB_OBJS += $(OUTPUT)util/parse-events-bison.o
-LIB_OBJS += $(OUTPUT)util/pmu-flex.o
-LIB_OBJS += $(OUTPUT)util/pmu-bison.o
-LIB_OBJS += $(OUTPUT)util/trace-event-read.o
-LIB_OBJS += $(OUTPUT)util/trace-event-info.o
-LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o
-LIB_OBJS += $(OUTPUT)util/svghelper.o
-LIB_OBJS += $(OUTPUT)util/sort.o
-LIB_OBJS += $(OUTPUT)util/hist.o
-LIB_OBJS += $(OUTPUT)util/probe-event.o
-LIB_OBJS += $(OUTPUT)util/util.o
-LIB_OBJS += $(OUTPUT)util/xyarray.o
-LIB_OBJS += $(OUTPUT)util/cpumap.o
-LIB_OBJS += $(OUTPUT)util/cgroup.o
-LIB_OBJS += $(OUTPUT)util/target.o
-LIB_OBJS += $(OUTPUT)util/rblist.o
-LIB_OBJS += $(OUTPUT)util/intlist.o
-LIB_OBJS += $(OUTPUT)util/vdso.o
-LIB_OBJS += $(OUTPUT)util/stat.o
-LIB_OBJS += $(OUTPUT)util/record.o
-
-LIB_OBJS += $(OUTPUT)ui/setup.o
-LIB_OBJS += $(OUTPUT)ui/helpline.o
-LIB_OBJS += $(OUTPUT)ui/progress.o
-LIB_OBJS += $(OUTPUT)ui/util.o
-LIB_OBJS += $(OUTPUT)ui/hist.o
-LIB_OBJS += $(OUTPUT)ui/stdio/hist.o
-
-LIB_OBJS += $(OUTPUT)arch/common.o
-
-LIB_OBJS += $(OUTPUT)tests/parse-events.o
-LIB_OBJS += $(OUTPUT)tests/dso-data.o
-LIB_OBJS += $(OUTPUT)tests/attr.o
-LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o
-LIB_OBJS += $(OUTPUT)tests/open-syscall.o
-LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o
-LIB_OBJS += $(OUTPUT)tests/open-syscall-tp-fields.o
-LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
-LIB_OBJS += $(OUTPUT)tests/perf-record.o
-LIB_OBJS += $(OUTPUT)tests/rdpmc.o
-LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
-LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
-LIB_OBJS += $(OUTPUT)tests/pmu.o
-LIB_OBJS += $(OUTPUT)tests/hists_link.o
-LIB_OBJS += $(OUTPUT)tests/python-use.o
-LIB_OBJS += $(OUTPUT)tests/bp_signal.o
-LIB_OBJS += $(OUTPUT)tests/bp_signal_overflow.o
-LIB_OBJS += $(OUTPUT)tests/task-exit.o
-LIB_OBJS += $(OUTPUT)tests/sw-clock.o
-ifeq ($(ARCH),x86)
-LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o
-endif
-LIB_OBJS += $(OUTPUT)tests/code-reading.o
-LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
-LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o
-
-BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
-BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
-# Benchmark modules
-BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
-BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
-ifeq ($(RAW_ARCH),x86_64)
-BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
-BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
-endif
-BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
-BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o
-
-BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
-BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o
-BUILTIN_OBJS += $(OUTPUT)builtin-help.o
-BUILTIN_OBJS += $(OUTPUT)builtin-sched.o
-BUILTIN_OBJS += $(OUTPUT)builtin-buildid-list.o
-BUILTIN_OBJS += $(OUTPUT)builtin-buildid-cache.o
-BUILTIN_OBJS += $(OUTPUT)builtin-list.o
-BUILTIN_OBJS += $(OUTPUT)builtin-record.o
-BUILTIN_OBJS += $(OUTPUT)builtin-report.o
-BUILTIN_OBJS += $(OUTPUT)builtin-stat.o
-BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o
-BUILTIN_OBJS += $(OUTPUT)builtin-top.o
-BUILTIN_OBJS += $(OUTPUT)builtin-script.o
-BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
-BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
-BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
-BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
-BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
-BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o
-BUILTIN_OBJS += $(OUTPUT)builtin-mem.o
-
-PERFLIBS = $(LIB_FILE) $(LIBLK) $(LIBTRACEEVENT)
-
-# We choose to avoid "if .. else if .. else .. endif endif"
-# because maintaining the nesting to match is a pain.  If
-# we had "elif" things would have been much nicer...
-
--include arch/$(ARCH)/Makefile
-
-ifneq ($(OUTPUT),)
-  CFLAGS += -I$(OUTPUT)
-endif
-
-ifdef NO_LIBELF
-EXTLIBS := $(filter-out -lelf,$(EXTLIBS))
-
-# Remove ELF/DWARF dependent codes
-LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS))
-LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS))
-LIB_OBJS := $(filter-out $(OUTPUT)util/probe-event.o,$(LIB_OBJS))
-LIB_OBJS := $(filter-out $(OUTPUT)util/probe-finder.o,$(LIB_OBJS))
-
-BUILTIN_OBJS := $(filter-out $(OUTPUT)builtin-probe.o,$(BUILTIN_OBJS))
-
-# Use minimal symbol handling
-LIB_OBJS += $(OUTPUT)util/symbol-minimal.o
-
-else # NO_LIBELF
-ifndef NO_DWARF
-  LIB_OBJS += $(OUTPUT)util/probe-finder.o
-  LIB_OBJS += $(OUTPUT)util/dwarf-aux.o
-endif # NO_DWARF
-endif # NO_LIBELF
-
-ifndef NO_LIBUNWIND
-  LIB_OBJS += $(OUTPUT)util/unwind.o
-endif
-LIB_OBJS += $(OUTPUT)tests/keep-tracking.o
-
-ifndef NO_LIBAUDIT
-  BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
-endif
-
-ifndef NO_SLANG
-  LIB_OBJS += $(OUTPUT)ui/browser.o
-  LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o
-  LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
-  LIB_OBJS += $(OUTPUT)ui/browsers/map.o
-  LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
-  LIB_OBJS += $(OUTPUT)ui/tui/setup.o
-  LIB_OBJS += $(OUTPUT)ui/tui/util.o
-  LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
-  LIB_OBJS += $(OUTPUT)ui/tui/progress.o
-  LIB_H += ui/browser.h
-  LIB_H += ui/browsers/map.h
-  LIB_H += ui/keysyms.h
-  LIB_H += ui/libslang.h
-endif
-
-ifndef NO_GTK2
-  LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
-  LIB_OBJS += $(OUTPUT)ui/gtk/hists.o
-  LIB_OBJS += $(OUTPUT)ui/gtk/setup.o
-  LIB_OBJS += $(OUTPUT)ui/gtk/util.o
-  LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o
-  LIB_OBJS += $(OUTPUT)ui/gtk/progress.o
-  LIB_OBJS += $(OUTPUT)ui/gtk/annotate.o
-endif
-
-ifndef NO_LIBPERL
-  LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-perl.o
-  LIB_OBJS += $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o
-endif
-
-ifndef NO_LIBPYTHON
-  LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o
-  LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o
-endif
-
-ifeq ($(NO_PERF_REGS),0)
-  ifeq ($(ARCH),x86)
-    LIB_H += arch/x86/include/perf_regs.h
+#
+# Do a parallel build with multiple jobs, based on the number of CPUs online
+# in this system: 'make -j8' on a 8-CPU system, etc.
+#
+# (To override it, run 'make JOBS=1' and similar.)
+#
+ifeq ($(JOBS),)
+  JOBS := $(shell grep -c ^processor /proc/cpuinfo 2>/dev/null)
+  ifeq ($(JOBS),)
+    JOBS := 1
   endif
 endif
 
-ifndef NO_LIBNUMA
-  BUILTIN_OBJS += $(OUTPUT)bench/numa.o
+#
+# Only pass canonical directory names as the output directory:
+#
+ifneq ($(O),)
+  FULL_O := $(shell readlink -f $(O) || echo $(O))
 endif
 
-ifdef ASCIIDOC8
-  export ASCIIDOC8
+#
+# Only accept the 'DEBUG' variable from the command line:
+#
+ifeq ("$(origin DEBUG)", "command line")
+  ifeq ($(DEBUG),)
+    override DEBUG = 0
+  else
+    SET_DEBUG = "DEBUG=$(DEBUG)"
+  endif
+else
+  override DEBUG = 0
 endif
 
-LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group
+define print_msg
+  @printf '  BUILD:   Doing '\''make \033[33m-j'$(JOBS)'\033[m'\'' parallel build\n'
+endef
 
-export INSTALL SHELL_PATH
+define make
+  @$(MAKE) -f Makefile.perf --no-print-directory -j$(JOBS) O=$(FULL_O) $(SET_DEBUG) $@
+endef
 
-### Build rules
+#
+# Needed if no target specified:
+#
+all:
+	$(print_msg)
+	$(make)
 
-SHELL = $(SHELL_PATH)
+#
+# The clean target is not really parallel, don't print the jobs info:
+#
+clean:
+	$(make)
 
-all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
-
-please_set_SHELL_PATH_to_a_more_modern_shell:
-	@$$(:)
-
-shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell
-
-strip: $(PROGRAMS) $(OUTPUT)perf
-	$(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf
-
-$(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -include $(OUTPUT)PERF-VERSION-FILE \
-		'-DPERF_HTML_PATH="$(htmldir_SQ)"' \
-		$(CFLAGS) -c $(filter %.c,$^) -o $@
-
-$(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS)
-	$(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(OUTPUT)perf.o \
-               $(BUILTIN_OBJS) $(LIBS) -o $@
-
-$(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
-		'-DPERF_HTML_PATH="$(htmldir_SQ)"' \
-		'-DPERF_MAN_PATH="$(mandir_SQ)"' \
-		'-DPERF_INFO_PATH="$(infodir_SQ)"' $<
-
-$(OUTPUT)builtin-timechart.o: builtin-timechart.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
-		'-DPERF_HTML_PATH="$(htmldir_SQ)"' \
-		'-DPERF_MAN_PATH="$(mandir_SQ)"' \
-		'-DPERF_INFO_PATH="$(infodir_SQ)"' $<
-
-$(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt
-
-$(OUTPUT)common-cmds.h: $(wildcard Documentation/perf-*.txt)
-	$(QUIET_GEN). util/generate-cmdlist.sh > $@+ && mv $@+ $@
-
-$(SCRIPTS) : % : %.sh
-	$(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@'
-
-# These can record PERF_VERSION
-$(OUTPUT)perf.o perf.spec \
-	$(SCRIPTS) \
-	: $(OUTPUT)PERF-VERSION-FILE
-
-.SUFFIXES:
-.SUFFIXES: .o .c .S .s
-
-# These two need to be here so that when O= is not used they take precedence
-# over the general rule for .o
-
-$(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -w $<
-
-$(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w $<
-
-$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
-$(OUTPUT)%.i: %.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
-$(OUTPUT)%.s: %.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -S $(CFLAGS) $<
-$(OUTPUT)%.o: %.S
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
-$(OUTPUT)%.s: %.S
-	$(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
-
-$(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
-		'-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \
-		'-DPREFIX="$(prefix_SQ)"' \
-		$<
-
-$(OUTPUT)tests/attr.o: tests/attr.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
-		'-DBINDIR="$(bindir_SQ)"' -DPYTHON='"$(PYTHON_WORD)"' \
-		$<
-
-$(OUTPUT)tests/python-use.o: tests/python-use.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
-		-DPYTHONPATH='"$(OUTPUT)python"' \
-		-DPYTHON='"$(PYTHON_WORD)"' \
-		$<
-
-$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
-
-$(OUTPUT)ui/browser.o: ui/browser.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
-
-$(OUTPUT)ui/browsers/annotate.o: ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
-
-$(OUTPUT)ui/browsers/hists.o: ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
-
-$(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
-
-$(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
-
-$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
-
-$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $<
-
-$(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default $<
-
-$(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default $<
-
-$(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
-
-$(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
-
-$(OUTPUT)perf-%: %.o $(PERFLIBS)
-	$(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS)
-
-$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
-$(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
-
-# we compile into subdirectories. if the target directory is not the source directory, they might not exists. So
-# we depend the various files onto their directories.
-DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
-$(DIRECTORY_DEPS): | $(sort $(dir $(DIRECTORY_DEPS)))
-# In the second step, we make a rule to actually create these directories
-$(sort $(dir $(DIRECTORY_DEPS))):
-	$(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null
-
-$(LIB_FILE): $(LIB_OBJS)
-	$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
-
-# libtraceevent.a
-$(LIBTRACEEVENT):
-	$(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) libtraceevent.a
-
-$(LIBTRACEEVENT)-clean:
-	$(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) clean
-
-# if subdir is set, we've been called from above so target has been built
-# already
-$(LIBLK):
-ifeq ($(subdir),)
-	$(QUIET_SUBDIR0)$(LK_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) liblk.a
-endif
-
-$(LIBLK)-clean:
-ifeq ($(subdir),)
-	$(QUIET_SUBDIR0)$(LK_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) clean
-endif
-
-help:
-	@echo 'Perf make targets:'
-	@echo '  doc		- make *all* documentation (see below)'
-	@echo '  man		- make manpage documentation (access with man <foo>)'
-	@echo '  html		- make html documentation'
-	@echo '  info		- make GNU info documentation (access with info <foo>)'
-	@echo '  pdf		- make pdf documentation'
-	@echo '  TAGS		- use etags to make tag information for source browsing'
-	@echo '  tags		- use ctags to make tag information for source browsing'
-	@echo '  cscope	- use cscope to make interactive browsing database'
-	@echo ''
-	@echo 'Perf install targets:'
-	@echo '  NOTE: documentation build requires asciidoc, xmlto packages to be installed'
-	@echo '  HINT: use "make prefix=<path> <install target>" to install to a particular'
-	@echo '        path like make prefix=/usr/local install install-doc'
-	@echo '  install	- install compiled binaries'
-	@echo '  install-doc	- install *all* documentation'
-	@echo '  install-man	- install manpage documentation'
-	@echo '  install-html	- install html documentation'
-	@echo '  install-info	- install GNU info documentation'
-	@echo '  install-pdf	- install pdf documentation'
-	@echo ''
-	@echo '  quick-install-doc	- alias for quick-install-man'
-	@echo '  quick-install-man	- install the documentation quickly'
-	@echo '  quick-install-html	- install the html documentation quickly'
-	@echo ''
-	@echo 'Perf maintainer targets:'
-	@echo '  clean			- clean all binary objects and build output'
-
-
-DOC_TARGETS := doc man html info pdf
-
-INSTALL_DOC_TARGETS := $(patsubst %,install-%,$(DOC_TARGETS)) try-install-man
-INSTALL_DOC_TARGETS += quick-install-doc quick-install-man quick-install-html
-
-# 'make doc' should call 'make -C Documentation all'
-$(DOC_TARGETS):
-	$(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all)
-
-TAGS:
-	$(RM) TAGS
-	$(FIND) . -name '*.[hcS]' -print | xargs etags -a
-
-tags:
-	$(RM) tags
-	$(FIND) . -name '*.[hcS]' -print | xargs ctags -a
-
-cscope:
-	$(RM) cscope*
-	$(FIND) . -name '*.[hcS]' -print | xargs cscope -b
-
-### Detect prefix changes
-TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\
-             $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ)
-
-$(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS
-	@FLAGS='$(TRACK_CFLAGS)'; \
-	    if test x"$$FLAGS" != x"`cat $(OUTPUT)PERF-CFLAGS 2>/dev/null`" ; then \
-		echo 1>&2 "    * new build flags or prefix"; \
-		echo "$$FLAGS" >$(OUTPUT)PERF-CFLAGS; \
-            fi
-
-### Testing rules
-
-# GNU make supports exporting all variables by "export" without parameters.
-# However, the environment gets quite big, and some programs have problems
-# with that.
-
-check: $(OUTPUT)common-cmds.h
-	if sparse; \
-	then \
-		for i in *.c */*.c; \
-		do \
-			sparse $(CFLAGS) $(SPARSE_FLAGS) $$i || exit; \
-		done; \
-	else \
-		exit 1; \
-	fi
-
-### Installation rules
-
-install-bin: all
-	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
-	$(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'
-	$(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
-ifndef NO_LIBPERL
-	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
-	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
-	$(INSTALL) scripts/perl/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
-	$(INSTALL) scripts/perl/*.pl -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl'
-	$(INSTALL) scripts/perl/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
-endif
-ifndef NO_LIBPYTHON
-	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'
-	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
-	$(INSTALL) scripts/python/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'
-	$(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'
-	$(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
-endif
-	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'
-	$(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
-	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'
-	$(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'
-	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
-	$(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
-
-install: install-bin try-install-man
-
-install-python_ext:
-	$(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
-
-# 'make install-doc' should call 'make -C Documentation install'
-$(INSTALL_DOC_TARGETS):
-	$(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:-doc=)
-
-### Cleaning rules
-
-clean: $(LIBTRACEEVENT)-clean $(LIBLK)-clean
-	$(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS)
-	$(RM) $(ALL_PROGRAMS) perf
-	$(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope*
-	$(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
-	$(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS
-	$(RM) $(OUTPUT)util/*-bison*
-	$(RM) $(OUTPUT)util/*-flex*
-	$(python-clean)
-
-.PHONY: all install clean strip $(LIBTRACEEVENT) $(LIBLK)
-.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
-.PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope .FORCE-PERF-CFLAGS
+#
+# All other targets get passed through:
+#
+%:
+	$(print_msg)
+	$(make)
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
new file mode 100644
index 0000000..7fc8f17
--- /dev/null
+++ b/tools/perf/Makefile.perf
@@ -0,0 +1,892 @@
+include ../scripts/Makefile.include
+
+# The default target of this Makefile is...
+all:
+
+include config/utilities.mak
+
+# Define V to have a more verbose compile.
+#
+# Define O to save output files in a separate directory.
+#
+# Define ARCH as name of target architecture if you want cross-builds.
+#
+# Define CROSS_COMPILE as prefix name of compiler if you want cross-builds.
+#
+# Define NO_LIBPERL to disable perl script extension.
+#
+# Define NO_LIBPYTHON to disable python script extension.
+#
+# Define PYTHON to point to the python binary if the default
+# `python' is not correct; for example: PYTHON=python2
+#
+# Define PYTHON_CONFIG to point to the python-config binary if
+# the default `$(PYTHON)-config' is not correct.
+#
+# Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8
+#
+# Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72.
+#
+# Define LDFLAGS=-static to build a static binary.
+#
+# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
+#
+# Define NO_DWARF if you do not want debug-info analysis feature at all.
+#
+# Define WERROR=0 to disable treating any warnings as errors.
+#
+# Define NO_NEWT if you do not want TUI support. (deprecated)
+#
+# Define NO_SLANG if you do not want TUI support.
+#
+# Define NO_GTK2 if you do not want GTK+ GUI support.
+#
+# Define NO_DEMANGLE if you do not want C++ symbol demangling.
+#
+# Define NO_LIBELF if you do not want libelf dependency (e.g. cross-builds)
+#
+# Define NO_LIBUNWIND if you do not want libunwind dependency for dwarf
+# backtrace post unwind.
+#
+# Define NO_BACKTRACE if you do not want stack backtrace debug feature
+#
+# Define NO_LIBNUMA if you do not want numa perf benchmark
+#
+# Define NO_LIBAUDIT if you do not want libaudit support
+#
+# Define NO_LIBBIONIC if you do not want bionic support
+
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
+ifneq ($(objtree),)
+#$(info Determined 'objtree' to be $(objtree))
+endif
+
+ifneq ($(OUTPUT),)
+#$(info Determined 'OUTPUT' to be $(OUTPUT))
+endif
+
+$(OUTPUT)PERF-VERSION-FILE: ../../.git/HEAD
+	@$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
+	@touch $(OUTPUT)PERF-VERSION-FILE
+
+CC = $(CROSS_COMPILE)gcc
+AR = $(CROSS_COMPILE)ar
+
+RM      = rm -f
+LN      = ln -f
+MKDIR   = mkdir
+FIND    = find
+INSTALL = install
+FLEX    = flex
+BISON   = bison
+STRIP   = strip
+
+LK_DIR          = $(srctree)/tools/lib/lk/
+TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
+
+# include config/Makefile by default and rule out
+# non-config cases
+config := 1
+
+NON_CONFIG_TARGETS := clean TAGS tags cscope help
+
+ifdef MAKECMDGOALS
+ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),)
+  config := 0
+endif
+endif
+
+ifeq ($(config),1)
+include config/Makefile
+endif
+
+export prefix bindir sharedir sysconfdir
+
+# sparse is architecture-neutral, which means that we need to tell it
+# explicitly what architecture to check for. Fix this up for yours..
+SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
+
+# Guard against environment variables
+BUILTIN_OBJS =
+LIB_H =
+LIB_OBJS =
+GTK_OBJS =
+PYRF_OBJS =
+SCRIPT_SH =
+
+SCRIPT_SH += perf-archive.sh
+
+grep-libs = $(filter -l%,$(1))
+strip-libs = $(filter-out -l%,$(1))
+
+ifneq ($(OUTPUT),)
+  TE_PATH=$(OUTPUT)
+ifneq ($(subdir),)
+  LK_PATH=$(OUTPUT)/../lib/lk/
+else
+  LK_PATH=$(OUTPUT)
+endif
+else
+  TE_PATH=$(TRACE_EVENT_DIR)
+  LK_PATH=$(LK_DIR)
+endif
+
+LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
+export LIBTRACEEVENT
+
+LIBLK = $(LK_PATH)liblk.a
+export LIBLK
+
+# python extension build directories
+PYTHON_EXTBUILD     := $(OUTPUT)python_ext_build/
+PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
+PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
+export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
+
+python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
+
+PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
+PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBLK)
+
+$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
+	$(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \
+	  --quiet build_ext; \
+	mkdir -p $(OUTPUT)python && \
+	cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
+#
+# No Perl scripts right now:
+#
+
+SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
+
+#
+# Single 'perf' binary right now:
+#
+PROGRAMS += $(OUTPUT)perf
+
+# what 'all' will build and 'install' will install, in perfexecdir
+ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
+
+# what 'all' will build but not install in perfexecdir
+OTHER_PROGRAMS = $(OUTPUT)perf
+
+# Set paths to tools early so that they can be used for version tests.
+ifndef SHELL_PATH
+  SHELL_PATH = /bin/sh
+endif
+ifndef PERL_PATH
+  PERL_PATH = /usr/bin/perl
+endif
+
+export PERL_PATH
+
+$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
+	$(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c
+
+$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
+	$(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c -p parse_events_
+
+$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
+	$(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c
+
+$(OUTPUT)util/pmu-bison.c: util/pmu.y
+	$(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_
+
+$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
+$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
+
+LIB_FILE=$(OUTPUT)libperf.a
+
+LIB_H += ../../include/uapi/linux/perf_event.h
+LIB_H += ../../include/linux/rbtree.h
+LIB_H += ../../include/linux/list.h
+LIB_H += ../../include/uapi/linux/const.h
+LIB_H += ../../include/linux/hash.h
+LIB_H += ../../include/linux/stringify.h
+LIB_H += util/include/linux/bitmap.h
+LIB_H += util/include/linux/bitops.h
+LIB_H += util/include/linux/compiler.h
+LIB_H += util/include/linux/const.h
+LIB_H += util/include/linux/ctype.h
+LIB_H += util/include/linux/kernel.h
+LIB_H += util/include/linux/list.h
+LIB_H += util/include/linux/export.h
+LIB_H += util/include/linux/magic.h
+LIB_H += util/include/linux/poison.h
+LIB_H += util/include/linux/prefetch.h
+LIB_H += util/include/linux/rbtree.h
+LIB_H += util/include/linux/rbtree_augmented.h
+LIB_H += util/include/linux/string.h
+LIB_H += util/include/linux/types.h
+LIB_H += util/include/linux/linkage.h
+LIB_H += util/include/asm/asm-offsets.h
+LIB_H += util/include/asm/bug.h
+LIB_H += util/include/asm/byteorder.h
+LIB_H += util/include/asm/hweight.h
+LIB_H += util/include/asm/swab.h
+LIB_H += util/include/asm/system.h
+LIB_H += util/include/asm/uaccess.h
+LIB_H += util/include/dwarf-regs.h
+LIB_H += util/include/asm/dwarf2.h
+LIB_H += util/include/asm/cpufeature.h
+LIB_H += util/include/asm/unistd_32.h
+LIB_H += util/include/asm/unistd_64.h
+LIB_H += perf.h
+LIB_H += util/annotate.h
+LIB_H += util/cache.h
+LIB_H += util/callchain.h
+LIB_H += util/build-id.h
+LIB_H += util/debug.h
+LIB_H += util/fs.h
+LIB_H += util/pmu.h
+LIB_H += util/event.h
+LIB_H += util/evsel.h
+LIB_H += util/evlist.h
+LIB_H += util/exec_cmd.h
+LIB_H += util/types.h
+LIB_H += util/levenshtein.h
+LIB_H += util/machine.h
+LIB_H += util/map.h
+LIB_H += util/parse-options.h
+LIB_H += util/parse-events.h
+LIB_H += util/quote.h
+LIB_H += util/util.h
+LIB_H += util/xyarray.h
+LIB_H += util/header.h
+LIB_H += util/help.h
+LIB_H += util/session.h
+LIB_H += util/strbuf.h
+LIB_H += util/strlist.h
+LIB_H += util/strfilter.h
+LIB_H += util/svghelper.h
+LIB_H += util/tool.h
+LIB_H += util/run-command.h
+LIB_H += util/sigchain.h
+LIB_H += util/dso.h
+LIB_H += util/symbol.h
+LIB_H += util/color.h
+LIB_H += util/values.h
+LIB_H += util/sort.h
+LIB_H += util/hist.h
+LIB_H += util/comm.h
+LIB_H += util/thread.h
+LIB_H += util/thread_map.h
+LIB_H += util/trace-event.h
+LIB_H += util/probe-finder.h
+LIB_H += util/dwarf-aux.h
+LIB_H += util/probe-event.h
+LIB_H += util/pstack.h
+LIB_H += util/cpumap.h
+LIB_H += util/top.h
+LIB_H += $(ARCH_INCLUDE)
+LIB_H += util/cgroup.h
+LIB_H += $(LIB_INCLUDE)traceevent/event-parse.h
+LIB_H += util/target.h
+LIB_H += util/rblist.h
+LIB_H += util/intlist.h
+LIB_H += util/perf_regs.h
+LIB_H += util/unwind.h
+LIB_H += util/vdso.h
+LIB_H += ui/helpline.h
+LIB_H += ui/progress.h
+LIB_H += ui/util.h
+LIB_H += ui/ui.h
+LIB_H += util/data.h
+
+LIB_OBJS += $(OUTPUT)util/abspath.o
+LIB_OBJS += $(OUTPUT)util/alias.o
+LIB_OBJS += $(OUTPUT)util/annotate.o
+LIB_OBJS += $(OUTPUT)util/build-id.o
+LIB_OBJS += $(OUTPUT)util/config.o
+LIB_OBJS += $(OUTPUT)util/ctype.o
+LIB_OBJS += $(OUTPUT)util/fs.o
+LIB_OBJS += $(OUTPUT)util/pmu.o
+LIB_OBJS += $(OUTPUT)util/environment.o
+LIB_OBJS += $(OUTPUT)util/event.o
+LIB_OBJS += $(OUTPUT)util/evlist.o
+LIB_OBJS += $(OUTPUT)util/evsel.o
+LIB_OBJS += $(OUTPUT)util/exec_cmd.o
+LIB_OBJS += $(OUTPUT)util/help.o
+LIB_OBJS += $(OUTPUT)util/levenshtein.o
+LIB_OBJS += $(OUTPUT)util/parse-options.o
+LIB_OBJS += $(OUTPUT)util/parse-events.o
+LIB_OBJS += $(OUTPUT)util/path.o
+LIB_OBJS += $(OUTPUT)util/rbtree.o
+LIB_OBJS += $(OUTPUT)util/bitmap.o
+LIB_OBJS += $(OUTPUT)util/hweight.o
+LIB_OBJS += $(OUTPUT)util/run-command.o
+LIB_OBJS += $(OUTPUT)util/quote.o
+LIB_OBJS += $(OUTPUT)util/strbuf.o
+LIB_OBJS += $(OUTPUT)util/string.o
+LIB_OBJS += $(OUTPUT)util/strlist.o
+LIB_OBJS += $(OUTPUT)util/strfilter.o
+LIB_OBJS += $(OUTPUT)util/top.o
+LIB_OBJS += $(OUTPUT)util/usage.o
+LIB_OBJS += $(OUTPUT)util/wrapper.o
+LIB_OBJS += $(OUTPUT)util/sigchain.o
+LIB_OBJS += $(OUTPUT)util/dso.o
+LIB_OBJS += $(OUTPUT)util/symbol.o
+LIB_OBJS += $(OUTPUT)util/symbol-elf.o
+LIB_OBJS += $(OUTPUT)util/color.o
+LIB_OBJS += $(OUTPUT)util/pager.o
+LIB_OBJS += $(OUTPUT)util/header.o
+LIB_OBJS += $(OUTPUT)util/callchain.o
+LIB_OBJS += $(OUTPUT)util/values.o
+LIB_OBJS += $(OUTPUT)util/debug.o
+LIB_OBJS += $(OUTPUT)util/machine.o
+LIB_OBJS += $(OUTPUT)util/map.o
+LIB_OBJS += $(OUTPUT)util/pstack.o
+LIB_OBJS += $(OUTPUT)util/session.o
+LIB_OBJS += $(OUTPUT)util/comm.o
+LIB_OBJS += $(OUTPUT)util/thread.o
+LIB_OBJS += $(OUTPUT)util/thread_map.o
+LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
+LIB_OBJS += $(OUTPUT)util/parse-events-flex.o
+LIB_OBJS += $(OUTPUT)util/parse-events-bison.o
+LIB_OBJS += $(OUTPUT)util/pmu-flex.o
+LIB_OBJS += $(OUTPUT)util/pmu-bison.o
+LIB_OBJS += $(OUTPUT)util/trace-event-read.o
+LIB_OBJS += $(OUTPUT)util/trace-event-info.o
+LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o
+LIB_OBJS += $(OUTPUT)util/svghelper.o
+LIB_OBJS += $(OUTPUT)util/sort.o
+LIB_OBJS += $(OUTPUT)util/hist.o
+LIB_OBJS += $(OUTPUT)util/probe-event.o
+LIB_OBJS += $(OUTPUT)util/util.o
+LIB_OBJS += $(OUTPUT)util/xyarray.o
+LIB_OBJS += $(OUTPUT)util/cpumap.o
+LIB_OBJS += $(OUTPUT)util/cgroup.o
+LIB_OBJS += $(OUTPUT)util/target.o
+LIB_OBJS += $(OUTPUT)util/rblist.o
+LIB_OBJS += $(OUTPUT)util/intlist.o
+LIB_OBJS += $(OUTPUT)util/vdso.o
+LIB_OBJS += $(OUTPUT)util/stat.o
+LIB_OBJS += $(OUTPUT)util/record.o
+LIB_OBJS += $(OUTPUT)util/srcline.o
+LIB_OBJS += $(OUTPUT)util/data.o
+
+LIB_OBJS += $(OUTPUT)ui/setup.o
+LIB_OBJS += $(OUTPUT)ui/helpline.o
+LIB_OBJS += $(OUTPUT)ui/progress.o
+LIB_OBJS += $(OUTPUT)ui/util.o
+LIB_OBJS += $(OUTPUT)ui/hist.o
+LIB_OBJS += $(OUTPUT)ui/stdio/hist.o
+
+LIB_OBJS += $(OUTPUT)arch/common.o
+
+LIB_OBJS += $(OUTPUT)tests/parse-events.o
+LIB_OBJS += $(OUTPUT)tests/dso-data.o
+LIB_OBJS += $(OUTPUT)tests/attr.o
+LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o
+LIB_OBJS += $(OUTPUT)tests/open-syscall.o
+LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o
+LIB_OBJS += $(OUTPUT)tests/open-syscall-tp-fields.o
+LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
+LIB_OBJS += $(OUTPUT)tests/perf-record.o
+LIB_OBJS += $(OUTPUT)tests/rdpmc.o
+LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
+LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
+LIB_OBJS += $(OUTPUT)tests/pmu.o
+LIB_OBJS += $(OUTPUT)tests/hists_link.o
+LIB_OBJS += $(OUTPUT)tests/python-use.o
+LIB_OBJS += $(OUTPUT)tests/bp_signal.o
+LIB_OBJS += $(OUTPUT)tests/bp_signal_overflow.o
+LIB_OBJS += $(OUTPUT)tests/task-exit.o
+LIB_OBJS += $(OUTPUT)tests/sw-clock.o
+ifeq ($(ARCH),x86)
+LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o
+endif
+LIB_OBJS += $(OUTPUT)tests/code-reading.o
+LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
+LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o
+
+BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
+BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
+# Benchmark modules
+BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
+BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
+ifeq ($(RAW_ARCH),x86_64)
+BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
+BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
+endif
+BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
+BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o
+
+BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
+BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o
+BUILTIN_OBJS += $(OUTPUT)builtin-help.o
+BUILTIN_OBJS += $(OUTPUT)builtin-sched.o
+BUILTIN_OBJS += $(OUTPUT)builtin-buildid-list.o
+BUILTIN_OBJS += $(OUTPUT)builtin-buildid-cache.o
+BUILTIN_OBJS += $(OUTPUT)builtin-list.o
+BUILTIN_OBJS += $(OUTPUT)builtin-record.o
+BUILTIN_OBJS += $(OUTPUT)builtin-report.o
+BUILTIN_OBJS += $(OUTPUT)builtin-stat.o
+BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o
+BUILTIN_OBJS += $(OUTPUT)builtin-top.o
+BUILTIN_OBJS += $(OUTPUT)builtin-script.o
+BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
+BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
+BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
+BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
+BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
+BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o
+BUILTIN_OBJS += $(OUTPUT)builtin-mem.o
+
+PERFLIBS = $(LIB_FILE) $(LIBLK) $(LIBTRACEEVENT)
+
+# We choose to avoid "if .. else if .. else .. endif endif"
+# because maintaining the nesting to match is a pain.  If
+# we had "elif" things would have been much nicer...
+
+-include arch/$(ARCH)/Makefile
+
+ifneq ($(OUTPUT),)
+  CFLAGS += -I$(OUTPUT)
+endif
+
+ifdef NO_LIBELF
+EXTLIBS := $(filter-out -lelf,$(EXTLIBS))
+
+# Remove ELF/DWARF dependent codes
+LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS))
+LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS))
+LIB_OBJS := $(filter-out $(OUTPUT)util/probe-event.o,$(LIB_OBJS))
+LIB_OBJS := $(filter-out $(OUTPUT)util/probe-finder.o,$(LIB_OBJS))
+
+BUILTIN_OBJS := $(filter-out $(OUTPUT)builtin-probe.o,$(BUILTIN_OBJS))
+
+# Use minimal symbol handling
+LIB_OBJS += $(OUTPUT)util/symbol-minimal.o
+
+else # NO_LIBELF
+ifndef NO_DWARF
+  LIB_OBJS += $(OUTPUT)util/probe-finder.o
+  LIB_OBJS += $(OUTPUT)util/dwarf-aux.o
+endif # NO_DWARF
+endif # NO_LIBELF
+
+ifndef NO_LIBUNWIND
+  LIB_OBJS += $(OUTPUT)util/unwind.o
+endif
+LIB_OBJS += $(OUTPUT)tests/keep-tracking.o
+
+ifndef NO_LIBAUDIT
+  BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
+endif
+
+ifndef NO_SLANG
+  LIB_OBJS += $(OUTPUT)ui/browser.o
+  LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o
+  LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
+  LIB_OBJS += $(OUTPUT)ui/browsers/map.o
+  LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
+  LIB_OBJS += $(OUTPUT)ui/tui/setup.o
+  LIB_OBJS += $(OUTPUT)ui/tui/util.o
+  LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
+  LIB_OBJS += $(OUTPUT)ui/tui/progress.o
+  LIB_H += ui/tui/tui.h
+  LIB_H += ui/browser.h
+  LIB_H += ui/browsers/map.h
+  LIB_H += ui/keysyms.h
+  LIB_H += ui/libslang.h
+endif
+
+ifndef NO_GTK2
+  ALL_PROGRAMS += $(OUTPUT)libperf-gtk.so
+
+  GTK_OBJS += $(OUTPUT)ui/gtk/browser.o
+  GTK_OBJS += $(OUTPUT)ui/gtk/hists.o
+  GTK_OBJS += $(OUTPUT)ui/gtk/setup.o
+  GTK_OBJS += $(OUTPUT)ui/gtk/util.o
+  GTK_OBJS += $(OUTPUT)ui/gtk/helpline.o
+  GTK_OBJS += $(OUTPUT)ui/gtk/progress.o
+  GTK_OBJS += $(OUTPUT)ui/gtk/annotate.o
+
+install-gtk: $(OUTPUT)libperf-gtk.so
+	$(call QUIET_INSTALL, 'GTK UI') \
+		$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(libdir_SQ)'; \
+		$(INSTALL) $(OUTPUT)libperf-gtk.so '$(DESTDIR_SQ)$(libdir_SQ)'
+endif
+
+ifndef NO_LIBPERL
+  LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-perl.o
+  LIB_OBJS += $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o
+endif
+
+ifndef NO_LIBPYTHON
+  LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o
+  LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o
+endif
+
+ifeq ($(NO_PERF_REGS),0)
+  ifeq ($(ARCH),x86)
+    LIB_H += arch/x86/include/perf_regs.h
+  endif
+endif
+
+ifndef NO_LIBNUMA
+  BUILTIN_OBJS += $(OUTPUT)bench/numa.o
+endif
+
+ifdef ASCIIDOC8
+  export ASCIIDOC8
+endif
+
+LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group
+
+export INSTALL SHELL_PATH
+
+### Build rules
+
+SHELL = $(SHELL_PATH)
+
+all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
+
+please_set_SHELL_PATH_to_a_more_modern_shell:
+	@$$(:)
+
+shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell
+
+strip: $(PROGRAMS) $(OUTPUT)perf
+	$(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf
+
+$(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -include $(OUTPUT)PERF-VERSION-FILE \
+		'-DPERF_HTML_PATH="$(htmldir_SQ)"' \
+		$(CFLAGS) -c $(filter %.c,$^) -o $@
+
+$(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS)
+	$(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(OUTPUT)perf.o \
+               $(BUILTIN_OBJS) $(LIBS) -o $@
+
+$(GTK_OBJS): $(OUTPUT)%.o: %.c $(LIB_H)
+	$(QUIET_CC)$(CC) -o $@ -c -fPIC $(CFLAGS) $(GTK_CFLAGS) $<
+
+$(OUTPUT)libperf-gtk.so: $(GTK_OBJS) $(PERFLIBS)
+	$(QUIET_LINK)$(CC) -o $@ -shared $(ALL_LDFLAGS) $(filter %.o,$^) $(GTK_LIBS)
+
+$(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
+		'-DPERF_HTML_PATH="$(htmldir_SQ)"' \
+		'-DPERF_MAN_PATH="$(mandir_SQ)"' \
+		'-DPERF_INFO_PATH="$(infodir_SQ)"' $<
+
+$(OUTPUT)builtin-timechart.o: builtin-timechart.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
+		'-DPERF_HTML_PATH="$(htmldir_SQ)"' \
+		'-DPERF_MAN_PATH="$(mandir_SQ)"' \
+		'-DPERF_INFO_PATH="$(infodir_SQ)"' $<
+
+$(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt
+
+$(OUTPUT)common-cmds.h: $(wildcard Documentation/perf-*.txt)
+	$(QUIET_GEN). util/generate-cmdlist.sh > $@+ && mv $@+ $@
+
+$(SCRIPTS) : % : %.sh
+	$(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@'
+
+# These can record PERF_VERSION
+$(OUTPUT)perf.o perf.spec \
+	$(SCRIPTS) \
+	: $(OUTPUT)PERF-VERSION-FILE
+
+.SUFFIXES:
+
+#
+# If a target does not match any of the later rules then prefix it by $(OUTPUT)
+# This makes targets like 'make O=/tmp/perf perf.o' work in a natural way.
+#
+ifneq ($(OUTPUT),)
+%.o: $(OUTPUT)%.o
+	@echo "    # Redirected target $@ => $(OUTPUT)$@"
+util/%.o: $(OUTPUT)util/%.o
+	@echo "    # Redirected target $@ => $(OUTPUT)$@"
+bench/%.o: $(OUTPUT)bench/%.o
+	@echo "    # Redirected target $@ => $(OUTPUT)$@"
+tests/%.o: $(OUTPUT)tests/%.o
+	@echo "    # Redirected target $@ => $(OUTPUT)$@"
+endif
+
+# These two need to be here so that when O= is not used they take precedence
+# over the general rule for .o
+
+$(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -w $<
+
+$(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w $<
+
+$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
+$(OUTPUT)%.i: %.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
+$(OUTPUT)%.s: %.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -S $(CFLAGS) $<
+$(OUTPUT)%.o: %.S
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
+$(OUTPUT)%.s: %.S
+	$(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
+
+$(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
+		'-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \
+		'-DPREFIX="$(prefix_SQ)"' \
+		$<
+
+$(OUTPUT)tests/attr.o: tests/attr.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
+		'-DBINDIR="$(bindir_SQ)"' -DPYTHON='"$(PYTHON_WORD)"' \
+		$<
+
+$(OUTPUT)tests/python-use.o: tests/python-use.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
+		-DPYTHONPATH='"$(OUTPUT)python"' \
+		-DPYTHON='"$(PYTHON_WORD)"' \
+		$<
+
+$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
+
+$(OUTPUT)ui/setup.o: ui/setup.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DLIBDIR='"$(libdir_SQ)"' $<
+
+$(OUTPUT)ui/browser.o: ui/browser.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
+
+$(OUTPUT)ui/browsers/annotate.o: ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
+
+$(OUTPUT)ui/browsers/hists.o: ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
+
+$(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
+
+$(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
+
+$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
+
+$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $<
+
+$(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default $<
+
+$(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default $<
+
+$(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
+
+$(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
+
+$(OUTPUT)perf-%: %.o $(PERFLIBS)
+	$(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS)
+
+$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
+$(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
+
+# we compile into subdirectories. if the target directory is not the source directory, they might not exists. So
+# we depend the various files onto their directories.
+DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(GTK_OBJS)
+DIRECTORY_DEPS += $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
+$(DIRECTORY_DEPS): | $(sort $(dir $(DIRECTORY_DEPS)))
+# In the second step, we make a rule to actually create these directories
+$(sort $(dir $(DIRECTORY_DEPS))):
+	$(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null
+
+$(LIB_FILE): $(LIB_OBJS)
+	$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
+
+# libtraceevent.a
+TE_SOURCES = $(wildcard $(TRACE_EVENT_DIR)*.[ch])
+
+$(LIBTRACEEVENT): $(TE_SOURCES)
+	$(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) CFLAGS="-g -Wall $(EXTRA_CFLAGS)" libtraceevent.a
+
+$(LIBTRACEEVENT)-clean:
+	$(call QUIET_CLEAN, libtraceevent)
+	@$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null
+
+LIBLK_SOURCES = $(wildcard $(LK_PATH)*.[ch])
+
+# if subdir is set, we've been called from above so target has been built
+# already
+$(LIBLK): $(LIBLK_SOURCES)
+ifeq ($(subdir),)
+	$(QUIET_SUBDIR0)$(LK_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) liblk.a
+endif
+
+$(LIBLK)-clean:
+ifeq ($(subdir),)
+	$(call QUIET_CLEAN, liblk)
+	@$(MAKE) -C $(LK_DIR) O=$(OUTPUT) clean >/dev/null
+endif
+
+help:
+	@echo 'Perf make targets:'
+	@echo '  doc		- make *all* documentation (see below)'
+	@echo '  man		- make manpage documentation (access with man <foo>)'
+	@echo '  html		- make html documentation'
+	@echo '  info		- make GNU info documentation (access with info <foo>)'
+	@echo '  pdf		- make pdf documentation'
+	@echo '  TAGS		- use etags to make tag information for source browsing'
+	@echo '  tags		- use ctags to make tag information for source browsing'
+	@echo '  cscope	- use cscope to make interactive browsing database'
+	@echo ''
+	@echo 'Perf install targets:'
+	@echo '  NOTE: documentation build requires asciidoc, xmlto packages to be installed'
+	@echo '  HINT: use "make prefix=<path> <install target>" to install to a particular'
+	@echo '        path like make prefix=/usr/local install install-doc'
+	@echo '  install	- install compiled binaries'
+	@echo '  install-doc	- install *all* documentation'
+	@echo '  install-man	- install manpage documentation'
+	@echo '  install-html	- install html documentation'
+	@echo '  install-info	- install GNU info documentation'
+	@echo '  install-pdf	- install pdf documentation'
+	@echo ''
+	@echo '  quick-install-doc	- alias for quick-install-man'
+	@echo '  quick-install-man	- install the documentation quickly'
+	@echo '  quick-install-html	- install the html documentation quickly'
+	@echo ''
+	@echo 'Perf maintainer targets:'
+	@echo '  clean			- clean all binary objects and build output'
+
+
+DOC_TARGETS := doc man html info pdf
+
+INSTALL_DOC_TARGETS := $(patsubst %,install-%,$(DOC_TARGETS)) try-install-man
+INSTALL_DOC_TARGETS += quick-install-doc quick-install-man quick-install-html
+
+# 'make doc' should call 'make -C Documentation all'
+$(DOC_TARGETS):
+	$(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all)
+
+TAGS:
+	$(RM) TAGS
+	$(FIND) . -name '*.[hcS]' -print | xargs etags -a
+
+tags:
+	$(RM) tags
+	$(FIND) . -name '*.[hcS]' -print | xargs ctags -a
+
+cscope:
+	$(RM) cscope*
+	$(FIND) . -name '*.[hcS]' -print | xargs cscope -b
+
+### Detect prefix changes
+TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\
+             $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ)
+
+$(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS
+	@FLAGS='$(TRACK_CFLAGS)'; \
+	    if test x"$$FLAGS" != x"`cat $(OUTPUT)PERF-CFLAGS 2>/dev/null`" ; then \
+		echo 1>&2 "  FLAGS:   * new build flags or prefix"; \
+		echo "$$FLAGS" >$(OUTPUT)PERF-CFLAGS; \
+            fi
+
+### Testing rules
+
+# GNU make supports exporting all variables by "export" without parameters.
+# However, the environment gets quite big, and some programs have problems
+# with that.
+
+check: $(OUTPUT)common-cmds.h
+	if sparse; \
+	then \
+		for i in *.c */*.c; \
+		do \
+			sparse $(CFLAGS) $(SPARSE_FLAGS) $$i || exit; \
+		done; \
+	else \
+		exit 1; \
+	fi
+
+### Installation rules
+
+install-gtk:
+
+install-bin: all install-gtk
+	$(call QUIET_INSTALL, binaries) \
+		$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'; \
+		$(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'; \
+		$(LN) '$(DESTDIR_SQ)$(bindir_SQ)/perf' '$(DESTDIR_SQ)$(bindir_SQ)/trace'
+	$(call QUIET_INSTALL, libexec) \
+		$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
+	$(call QUIET_INSTALL, perf-archive) \
+		$(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
+ifndef NO_LIBPERL
+	$(call QUIET_INSTALL, perl-scripts) \
+		$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \
+		$(INSTALL) scripts/perl/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \
+		$(INSTALL) scripts/perl/*.pl -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl'; \
+		$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'; \
+		$(INSTALL) scripts/perl/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
+endif
+ifndef NO_LIBPYTHON
+	$(call QUIET_INSTALL, python-scripts) \
+		$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'; \
+		$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'; \
+		$(INSTALL) scripts/python/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'; \
+		$(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'; \
+		$(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
+endif
+	$(call QUIET_INSTALL, bash_completion-script) \
+		$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \
+		$(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
+	$(call QUIET_INSTALL, tests) \
+		$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
+		$(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
+		$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
+		$(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
+
+install: install-bin try-install-man
+
+install-python_ext:
+	$(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
+
+# 'make install-doc' should call 'make -C Documentation install'
+$(INSTALL_DOC_TARGETS):
+	$(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:-doc=)
+
+### Cleaning rules
+
+#
+# This is here, not in config/Makefile, because config/Makefile does
+# not get included for the clean target:
+#
+config-clean:
+	$(call QUIET_CLEAN, config)
+	@$(MAKE) -C config/feature-checks clean >/dev/null
+
+clean: $(LIBTRACEEVENT)-clean $(LIBLK)-clean config-clean
+	$(call QUIET_CLEAN, core-objs)  $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
+	$(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf
+	$(call QUIET_CLEAN, core-gen)   $(RM)  *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
+	$(call QUIET_CLEAN, Documentation)
+	@$(MAKE) -C Documentation O=$(OUTPUT) clean >/dev/null
+	$(python-clean)
+
+#
+# Trick: if ../../.git does not exist - we are building out of tree for example,
+# then force version regeneration:
+#
+ifeq ($(wildcard ../../.git/HEAD),)
+    GIT-HEAD-PHONY = ../../.git/HEAD
+else
+    GIT-HEAD-PHONY =
+endif
+
+.PHONY: all install clean config-clean strip install-gtk
+.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
+.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope .FORCE-PERF-CFLAGS
+
diff --git a/tools/perf/arch/x86/include/perf_regs.h b/tools/perf/arch/x86/include/perf_regs.h
index 7fcdcdb..e84ca76 100644
--- a/tools/perf/arch/x86/include/perf_regs.h
+++ b/tools/perf/arch/x86/include/perf_regs.h
@@ -5,7 +5,7 @@
 #include "../../util/types.h"
 #include <asm/perf_regs.h>
 
-#ifndef ARCH_X86_64
+#ifndef HAVE_ARCH_X86_64_SUPPORT
 #define PERF_REGS_MASK ((1ULL << PERF_REG_X86_32_MAX) - 1)
 #else
 #define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \
@@ -52,7 +52,7 @@
 		return "FS";
 	case PERF_REG_X86_GS:
 		return "GS";
-#ifdef ARCH_X86_64
+#ifdef HAVE_ARCH_X86_64_SUPPORT
 	case PERF_REG_X86_R8:
 		return "R8";
 	case PERF_REG_X86_R9:
@@ -69,7 +69,7 @@
 		return "R14";
 	case PERF_REG_X86_R15:
 		return "R15";
-#endif /* ARCH_X86_64 */
+#endif /* HAVE_ARCH_X86_64_SUPPORT */
 	default:
 		return NULL;
 	}
diff --git a/tools/perf/arch/x86/util/unwind.c b/tools/perf/arch/x86/util/unwind.c
index 78d956e..456a88c 100644
--- a/tools/perf/arch/x86/util/unwind.c
+++ b/tools/perf/arch/x86/util/unwind.c
@@ -4,7 +4,7 @@
 #include "perf_regs.h"
 #include "../../util/unwind.h"
 
-#ifdef ARCH_X86_64
+#ifdef HAVE_ARCH_X86_64_SUPPORT
 int unwind__arch_reg_id(int regnum)
 {
 	int id;
@@ -108,4 +108,4 @@
 
 	return id;
 }
-#endif /* ARCH_X86_64 */
+#endif /* HAVE_ARCH_X86_64_SUPPORT */
diff --git a/tools/perf/bash_completion b/tools/perf/bash_completion
index 56e6a12..62e157db 100644
--- a/tools/perf/bash_completion
+++ b/tools/perf/bash_completion
@@ -1,17 +1,87 @@
 # perf completion
 
-function_exists()
+# Taken from git.git's completion script.
+__my_reassemble_comp_words_by_ref()
 {
-	declare -F $1 > /dev/null
-	return $?
+	local exclude i j first
+	# Which word separators to exclude?
+	exclude="${1//[^$COMP_WORDBREAKS]}"
+	cword_=$COMP_CWORD
+	if [ -z "$exclude" ]; then
+		words_=("${COMP_WORDS[@]}")
+		return
+	fi
+	# List of word completion separators has shrunk;
+	# re-assemble words to complete.
+	for ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
+		# Append each nonempty word consisting of just
+		# word separator characters to the current word.
+		first=t
+		while
+			[ $i -gt 0 ] &&
+			[ -n "${COMP_WORDS[$i]}" ] &&
+			# word consists of excluded word separators
+			[ "${COMP_WORDS[$i]//[^$exclude]}" = "${COMP_WORDS[$i]}" ]
+		do
+			# Attach to the previous token,
+			# unless the previous token is the command name.
+			if [ $j -ge 2 ] && [ -n "$first" ]; then
+				((j--))
+			fi
+			first=
+			words_[$j]=${words_[j]}${COMP_WORDS[i]}
+			if [ $i = $COMP_CWORD ]; then
+				cword_=$j
+			fi
+			if (($i < ${#COMP_WORDS[@]} - 1)); then
+				((i++))
+			else
+				# Done.
+				return
+			fi
+		done
+		words_[$j]=${words_[j]}${COMP_WORDS[i]}
+		if [ $i = $COMP_CWORD ]; then
+			cword_=$j
+		fi
+	done
 }
 
-function_exists __ltrim_colon_completions ||
+type _get_comp_words_by_ref &>/dev/null ||
+_get_comp_words_by_ref()
+{
+	local exclude cur_ words_ cword_
+	if [ "$1" = "-n" ]; then
+		exclude=$2
+		shift 2
+	fi
+	__my_reassemble_comp_words_by_ref "$exclude"
+	cur_=${words_[cword_]}
+	while [ $# -gt 0 ]; do
+		case "$1" in
+		cur)
+			cur=$cur_
+			;;
+		prev)
+			prev=${words_[$cword_-1]}
+			;;
+		words)
+			words=("${words_[@]}")
+			;;
+		cword)
+			cword=$cword_
+			;;
+		esac
+		shift
+	done
+}
+
+type __ltrim_colon_completions &>/dev/null ||
 __ltrim_colon_completions()
 {
 	if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
 		# Remove colon-word prefix from COMPREPLY items
-		local colon_word=${1%${1##*:}}
+		local colon_word=${1%"${1##*:}"}
 		local i=${#COMPREPLY[*]}
 		while [[ $((--i)) -ge 0 ]]; do
 			COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
@@ -19,23 +89,18 @@
 	fi
 }
 
-have perf &&
+type perf &>/dev/null &&
 _perf()
 {
-	local cur prev cmd
+	local cur words cword prev cmd
 
 	COMPREPLY=()
-	if function_exists _get_comp_words_by_ref; then
-		_get_comp_words_by_ref -n : cur prev
-	else
-		cur=$(_get_cword :)
-		prev=${COMP_WORDS[COMP_CWORD-1]}
-	fi
+	_get_comp_words_by_ref -n =: cur words cword prev
 
-	cmd=${COMP_WORDS[0]}
+	cmd=${words[0]}
 
 	# List perf subcommands or long options
-	if [ $COMP_CWORD -eq 1 ]; then
+	if [ $cword -eq 1 ]; then
 		if [[ $cur == --* ]]; then
 			COMPREPLY=( $( compgen -W '--help --version \
 			--exec-path --html-path --paginate --no-pager \
@@ -45,18 +110,17 @@
 			COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
 		fi
 	# List possible events for -e option
-	elif [[ $prev == "-e" && "${COMP_WORDS[1]}" == @(record|stat|top) ]]; then
+	elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then
 		evts=$($cmd list --raw-dump)
 		COMPREPLY=( $( compgen -W '$evts' -- "$cur" ) )
 		__ltrim_colon_completions $cur
 	# List long option names
 	elif [[ $cur == --* ]];  then
-		subcmd=${COMP_WORDS[1]}
+		subcmd=${words[1]}
 		opts=$($cmd $subcmd --list-opts)
 		COMPREPLY=( $( compgen -W '$opts' -- "$cur" ) )
-	# Fall down to list regular files
-	else
-		_filedir
 	fi
 } &&
-complete -F _perf perf
+
+complete -o bashdefault -o default -o nospace -F _perf perf 2>/dev/null \
+	|| complete -o default -o nospace -F _perf perf
diff --git a/tools/perf/bench/mem-memcpy-arch.h b/tools/perf/bench/mem-memcpy-arch.h
index a72e36c..57b4ed8 100644
--- a/tools/perf/bench/mem-memcpy-arch.h
+++ b/tools/perf/bench/mem-memcpy-arch.h
@@ -1,5 +1,5 @@
 
-#ifdef ARCH_X86_64
+#ifdef HAVE_ARCH_X86_64_SUPPORT
 
 #define MEMCPY_FN(fn, name, desc)		\
 	extern void *fn(void *, const void *, size_t);
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index 8cdca43..5ce71d3 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -58,7 +58,7 @@
 	{ "default",
 	  "Default memcpy() provided by glibc",
 	  memcpy },
-#ifdef ARCH_X86_64
+#ifdef HAVE_ARCH_X86_64_SUPPORT
 
 #define MEMCPY_FN(fn, name, desc) { name, desc, fn },
 #include "mem-memcpy-x86-64-asm-def.h"
diff --git a/tools/perf/bench/mem-memset-arch.h b/tools/perf/bench/mem-memset-arch.h
index a040fa7..633800c 100644
--- a/tools/perf/bench/mem-memset-arch.h
+++ b/tools/perf/bench/mem-memset-arch.h
@@ -1,5 +1,5 @@
 
-#ifdef ARCH_X86_64
+#ifdef HAVE_ARCH_X86_64_SUPPORT
 
 #define MEMSET_FN(fn, name, desc)		\
 	extern void *fn(void *, int, size_t);
diff --git a/tools/perf/bench/mem-memset.c b/tools/perf/bench/mem-memset.c
index 4a2f120..9af79d2 100644
--- a/tools/perf/bench/mem-memset.c
+++ b/tools/perf/bench/mem-memset.c
@@ -58,7 +58,7 @@
 	{ "default",
 	  "Default memset() provided by glibc",
 	  memset },
-#ifdef ARCH_X86_64
+#ifdef HAVE_ARCH_X86_64_SUPPORT
 
 #define MEMSET_FN(fn, name, desc) { name, desc, fn },
 #include "mem-memset-x86-64-asm-def.h"
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 30d1c32..d4c83c6 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -429,14 +429,14 @@
 	return 0;
 }
 
-static void parse_setup_cpu_list(void)
+static int parse_setup_cpu_list(void)
 {
 	struct thread_data *td;
 	char *str0, *str;
 	int t;
 
 	if (!g->p.cpu_list_str)
-		return;
+		return 0;
 
 	dprintf("g->p.nr_tasks: %d\n", g->p.nr_tasks);
 
@@ -500,8 +500,12 @@
 
 		dprintf("CPUs: %d_%d-%d#%dx%d\n", bind_cpu_0, bind_len, bind_cpu_1, step, mul);
 
-		BUG_ON(bind_cpu_0 < 0 || bind_cpu_0 >= g->p.nr_cpus);
-		BUG_ON(bind_cpu_1 < 0 || bind_cpu_1 >= g->p.nr_cpus);
+		if (bind_cpu_0 >= g->p.nr_cpus || bind_cpu_1 >= g->p.nr_cpus) {
+			printf("\nTest not applicable, system has only %d CPUs.\n", g->p.nr_cpus);
+			return -1;
+		}
+
+		BUG_ON(bind_cpu_0 < 0 || bind_cpu_1 < 0);
 		BUG_ON(bind_cpu_0 > bind_cpu_1);
 
 		for (bind_cpu = bind_cpu_0; bind_cpu <= bind_cpu_1; bind_cpu += step) {
@@ -541,6 +545,7 @@
 		printf("# NOTE: %d tasks bound, %d tasks unbound\n", t, g->p.nr_tasks - t);
 
 	free(str0);
+	return 0;
 }
 
 static int parse_cpus_opt(const struct option *opt __maybe_unused,
@@ -561,14 +566,14 @@
 	return 0;
 }
 
-static void parse_setup_node_list(void)
+static int parse_setup_node_list(void)
 {
 	struct thread_data *td;
 	char *str0, *str;
 	int t;
 
 	if (!g->p.node_list_str)
-		return;
+		return 0;
 
 	dprintf("g->p.nr_tasks: %d\n", g->p.nr_tasks);
 
@@ -619,8 +624,12 @@
 
 		dprintf("NODEs: %d-%d #%d\n", bind_node_0, bind_node_1, step);
 
-		BUG_ON(bind_node_0 < 0 || bind_node_0 >= g->p.nr_nodes);
-		BUG_ON(bind_node_1 < 0 || bind_node_1 >= g->p.nr_nodes);
+		if (bind_node_0 >= g->p.nr_nodes || bind_node_1 >= g->p.nr_nodes) {
+			printf("\nTest not applicable, system has only %d nodes.\n", g->p.nr_nodes);
+			return -1;
+		}
+
+		BUG_ON(bind_node_0 < 0 || bind_node_1 < 0);
 		BUG_ON(bind_node_0 > bind_node_1);
 
 		for (bind_node = bind_node_0; bind_node <= bind_node_1; bind_node += step) {
@@ -651,6 +660,7 @@
 		printf("# NOTE: %d tasks mem-bound, %d tasks unbound\n", t, g->p.nr_tasks - t);
 
 	free(str0);
+	return 0;
 }
 
 static int parse_nodes_opt(const struct option *opt __maybe_unused,
@@ -1110,7 +1120,7 @@
 		/* Check whether our max runtime timed out: */
 		if (g->p.nr_secs) {
 			timersub(&stop, &start0, &diff);
-			if (diff.tv_sec >= g->p.nr_secs) {
+			if ((u32)diff.tv_sec >= g->p.nr_secs) {
 				g->stop_work = true;
 				break;
 			}
@@ -1157,7 +1167,7 @@
 			runtime_ns_max += diff.tv_usec * 1000;
 
 			if (details >= 0) {
-				printf(" #%2d / %2d: %14.2lf nsecs/op [val: %016lx]\n",
+				printf(" #%2d / %2d: %14.2lf nsecs/op [val: %016"PRIx64"]\n",
 					process_nr, thread_nr, runtime_ns_max / bytes_done, val);
 			}
 			fflush(stdout);
@@ -1356,8 +1366,8 @@
 	init_thread_data();
 
 	tprintf("#\n");
-	parse_setup_cpu_list();
-	parse_setup_node_list();
+	if (parse_setup_cpu_list() || parse_setup_node_list())
+		return -1;
 	tprintf("#\n");
 
 	print_summary();
@@ -1600,7 +1610,6 @@
 	return 0;
 
 err:
-	usage_with_options(numa_usage, options);
 	return -1;
 }
 
@@ -1701,8 +1710,7 @@
 	BUG_ON(ret < 0);
 
 	for (i = 0; i < nr; i++) {
-		if (run_bench_numa(tests[i][0], tests[i] + 1))
-			return -1;
+		run_bench_numa(tests[i][0], tests[i] + 1);
 	}
 
 	printf("\n");
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index 69cfba8..07a8d76 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -7,9 +7,7 @@
  * Based on pipe-test-1m.c by Ingo Molnar <mingo@redhat.com>
  *  http://people.redhat.com/mingo/cfs-scheduler/tools/pipe-test-1m.c
  * Ported to perf by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
- *
  */
-
 #include "../perf.h"
 #include "../util/util.h"
 #include "../util/parse-options.h"
@@ -28,12 +26,24 @@
 #include <sys/time.h>
 #include <sys/types.h>
 
+#include <pthread.h>
+
+struct thread_data {
+	int			nr;
+	int			pipe_read;
+	int			pipe_write;
+	pthread_t		pthread;
+};
+
 #define LOOPS_DEFAULT 1000000
-static int loops = LOOPS_DEFAULT;
+static	int			loops = LOOPS_DEFAULT;
+
+/* Use processes by default: */
+static bool			threaded;
 
 static const struct option options[] = {
-	OPT_INTEGER('l', "loop", &loops,
-		    "Specify number of loops"),
+	OPT_INTEGER('l', "loop",	&loops,		"Specify number of loops"),
+	OPT_BOOLEAN('T', "threaded",	&threaded,	"Specify threads/process based task setup"),
 	OPT_END()
 };
 
@@ -42,13 +52,37 @@
 	NULL
 };
 
-int bench_sched_pipe(int argc, const char **argv,
-		     const char *prefix __maybe_unused)
+static void *worker_thread(void *__tdata)
 {
-	int pipe_1[2], pipe_2[2];
+	struct thread_data *td = __tdata;
 	int m = 0, i;
+	int ret;
+
+	for (i = 0; i < loops; i++) {
+		if (!td->nr) {
+			ret = read(td->pipe_read, &m, sizeof(int));
+			BUG_ON(ret != sizeof(int));
+			ret = write(td->pipe_write, &m, sizeof(int));
+			BUG_ON(ret != sizeof(int));
+		} else {
+			ret = write(td->pipe_write, &m, sizeof(int));
+			BUG_ON(ret != sizeof(int));
+			ret = read(td->pipe_read, &m, sizeof(int));
+			BUG_ON(ret != sizeof(int));
+		}
+	}
+
+	return NULL;
+}
+
+int bench_sched_pipe(int argc, const char **argv, const char *prefix __maybe_unused)
+{
+	struct thread_data threads[2], *td;
+	int pipe_1[2], pipe_2[2];
 	struct timeval start, stop, diff;
 	unsigned long long result_usec = 0;
+	int nr_threads = 2;
+	int t;
 
 	/*
 	 * why does "ret" exist?
@@ -58,43 +92,66 @@
 	int __maybe_unused ret, wait_stat;
 	pid_t pid, retpid __maybe_unused;
 
-	argc = parse_options(argc, argv, options,
-			     bench_sched_pipe_usage, 0);
+	argc = parse_options(argc, argv, options, bench_sched_pipe_usage, 0);
 
 	BUG_ON(pipe(pipe_1));
 	BUG_ON(pipe(pipe_2));
 
-	pid = fork();
-	assert(pid >= 0);
-
 	gettimeofday(&start, NULL);
 
-	if (!pid) {
-		for (i = 0; i < loops; i++) {
-			ret = read(pipe_1[0], &m, sizeof(int));
-			ret = write(pipe_2[1], &m, sizeof(int));
+	for (t = 0; t < nr_threads; t++) {
+		td = threads + t;
+
+		td->nr = t;
+
+		if (t == 0) {
+			td->pipe_read = pipe_1[0];
+			td->pipe_write = pipe_2[1];
+		} else {
+			td->pipe_write = pipe_1[1];
+			td->pipe_read = pipe_2[0];
 		}
+	}
+
+
+	if (threaded) {
+
+		for (t = 0; t < nr_threads; t++) {
+			td = threads + t;
+
+			ret = pthread_create(&td->pthread, NULL, worker_thread, td);
+			BUG_ON(ret);
+		}
+
+		for (t = 0; t < nr_threads; t++) {
+			td = threads + t;
+
+			ret = pthread_join(td->pthread, NULL);
+			BUG_ON(ret);
+		}
+
 	} else {
-		for (i = 0; i < loops; i++) {
-			ret = write(pipe_1[1], &m, sizeof(int));
-			ret = read(pipe_2[0], &m, sizeof(int));
+		pid = fork();
+		assert(pid >= 0);
+
+		if (!pid) {
+			worker_thread(threads + 0);
+			exit(0);
+		} else {
+			worker_thread(threads + 1);
 		}
+
+		retpid = waitpid(pid, &wait_stat, 0);
+		assert((retpid == pid) && WIFEXITED(wait_stat));
 	}
 
 	gettimeofday(&stop, NULL);
 	timersub(&stop, &start, &diff);
 
-	if (pid) {
-		retpid = waitpid(pid, &wait_stat, 0);
-		assert((retpid == pid) && WIFEXITED(wait_stat));
-	} else {
-		exit(0);
-	}
-
 	switch (bench_format) {
 	case BENCH_FORMAT_DEFAULT:
-		printf("# Executed %d pipe operations between two tasks\n\n",
-			loops);
+		printf("# Executed %d pipe operations between two %s\n\n",
+			loops, threaded ? "threads" : "processes");
 
 		result_usec = diff.tv_sec * 1000000;
 		result_usec += diff.tv_usec;
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 5ebd0c3..4087ab1 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -28,8 +28,10 @@
 #include "util/hist.h"
 #include "util/session.h"
 #include "util/tool.h"
+#include "util/data.h"
 #include "arch/common.h"
 
+#include <dlfcn.h>
 #include <linux/bitmap.h>
 
 struct perf_annotate {
@@ -63,7 +65,7 @@
 		return 0;
 	}
 
-	he = __hists__add_entry(&evsel->hists, al, NULL, 1, 1);
+	he = __hists__add_entry(&evsel->hists, al, NULL, NULL, NULL, 1, 1, 0);
 	if (he == NULL)
 		return -ENOMEM;
 
@@ -116,11 +118,11 @@
 				    ann->print_line, ann->full_paths, 0, 0);
 }
 
-static void hists__find_annotations(struct hists *self,
+static void hists__find_annotations(struct hists *hists,
 				    struct perf_evsel *evsel,
 				    struct perf_annotate *ann)
 {
-	struct rb_node *nd = rb_first(&self->entries), *next;
+	struct rb_node *nd = rb_first(&hists->entries), *next;
 	int key = K_RIGHT;
 
 	while (nd) {
@@ -142,8 +144,18 @@
 
 		if (use_browser == 2) {
 			int ret;
+			int (*annotate)(struct hist_entry *he,
+					struct perf_evsel *evsel,
+					struct hist_browser_timer *hbt);
 
-			ret = hist_entry__gtk_annotate(he, evsel, NULL);
+			annotate = dlsym(perf_gtk_handle,
+					 "hist_entry__gtk_annotate");
+			if (annotate == NULL) {
+				ui__error("GTK browser not found!\n");
+				return;
+			}
+
+			ret = annotate(he, evsel, NULL);
 			if (!ret || !ann->skip_missing)
 				return;
 
@@ -188,9 +200,13 @@
 	struct perf_session *session;
 	struct perf_evsel *pos;
 	u64 total_nr_samples;
+	struct perf_data_file file = {
+		.path  = input_name,
+		.mode  = PERF_DATA_MODE_READ,
+		.force = ann->force,
+	};
 
-	session = perf_session__new(input_name, O_RDONLY,
-				    ann->force, false, &ann->tool);
+	session = perf_session__new(&file, false, &ann->tool);
 	if (session == NULL)
 		return -ENOMEM;
 
@@ -231,7 +247,7 @@
 
 		if (nr_samples > 0) {
 			total_nr_samples += nr_samples;
-			hists__collapse_resort(hists);
+			hists__collapse_resort(hists, NULL);
 			hists__output_resort(hists);
 
 			if (symbol_conf.event_group &&
@@ -243,12 +259,21 @@
 	}
 
 	if (total_nr_samples == 0) {
-		ui__error("The %s file has no samples!\n", session->filename);
+		ui__error("The %s file has no samples!\n", file.path);
 		goto out_delete;
 	}
 
-	if (use_browser == 2)
-		perf_gtk__show_annotations();
+	if (use_browser == 2) {
+		void (*show_annotations)(void);
+
+		show_annotations = dlsym(perf_gtk_handle,
+					 "perf_gtk__show_annotations");
+		if (show_annotations == NULL) {
+			ui__error("GTK browser not found!\n");
+			goto out_delete;
+		}
+		show_annotations();
+	}
 
 out_delete:
 	/*
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index 77298bf..e47f90c 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -1,21 +1,18 @@
 /*
- *
  * builtin-bench.c
  *
- * General benchmarking subsystem provided by perf
+ * General benchmarking collections provided by perf
  *
  * Copyright (C) 2009, Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
- *
  */
 
 /*
+ * Available benchmark collection list:
  *
- * Available subsystem list:
- *  sched ... scheduler and IPC mechanism
+ *  sched ... scheduler and IPC performance
  *  mem   ... memory access performance
- *
+ *  numa  ... NUMA scheduling and MM performance
  */
-
 #include "perf.h"
 #include "util/util.h"
 #include "util/parse-options.h"
@@ -25,112 +22,92 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/prctl.h>
 
-struct bench_suite {
-	const char *name;
-	const char *summary;
-	int (*fn)(int, const char **, const char *);
+typedef int (*bench_fn_t)(int argc, const char **argv, const char *prefix);
+
+struct bench {
+	const char	*name;
+	const char	*summary;
+	bench_fn_t	fn;
 };
-						\
-/* sentinel: easy for help */
-#define suite_all { "all", "Test all benchmark suites", NULL }
 
-#ifdef LIBNUMA_SUPPORT
-static struct bench_suite numa_suites[] = {
-	{ "mem",
-	  "Benchmark for NUMA workloads",
-	  bench_numa },
-	suite_all,
-	{ NULL,
-	  NULL,
-	  NULL                  }
+#ifdef HAVE_LIBNUMA_SUPPORT
+static struct bench numa_benchmarks[] = {
+	{ "mem",	"Benchmark for NUMA workloads",			bench_numa		},
+	{ "all",	"Test all NUMA benchmarks",			NULL			},
+	{ NULL,		NULL,						NULL			}
 };
 #endif
 
-static struct bench_suite sched_suites[] = {
-	{ "messaging",
-	  "Benchmark for scheduler and IPC mechanisms",
-	  bench_sched_messaging },
-	{ "pipe",
-	  "Flood of communication over pipe() between two processes",
-	  bench_sched_pipe      },
-	suite_all,
-	{ NULL,
-	  NULL,
-	  NULL                  }
+static struct bench sched_benchmarks[] = {
+	{ "messaging",	"Benchmark for scheduling and IPC",		bench_sched_messaging	},
+	{ "pipe",	"Benchmark for pipe() between two processes",	bench_sched_pipe	},
+	{ "all",	"Test all scheduler benchmarks",		NULL			},
+	{ NULL,		NULL,						NULL			}
 };
 
-static struct bench_suite mem_suites[] = {
-	{ "memcpy",
-	  "Simple memory copy in various ways",
-	  bench_mem_memcpy },
-	{ "memset",
-	  "Simple memory set in various ways",
-	  bench_mem_memset },
-	suite_all,
-	{ NULL,
-	  NULL,
-	  NULL             }
+static struct bench mem_benchmarks[] = {
+	{ "memcpy",	"Benchmark for memcpy()",			bench_mem_memcpy	},
+	{ "memset",	"Benchmark for memset() tests",			bench_mem_memset	},
+	{ "all",	"Test all memory benchmarks",			NULL			},
+	{ NULL,		NULL,						NULL			}
 };
 
-struct bench_subsys {
-	const char *name;
-	const char *summary;
-	struct bench_suite *suites;
+struct collection {
+	const char	*name;
+	const char	*summary;
+	struct bench	*benchmarks;
 };
 
-static struct bench_subsys subsystems[] = {
-#ifdef LIBNUMA_SUPPORT
-	{ "numa",
-	  "NUMA scheduling and MM behavior",
-	  numa_suites },
+static struct collection collections[] = {
+	{ "sched",	"Scheduler and IPC benchmarks",		sched_benchmarks	},
+	{ "mem",	"Memory access benchmarks",			mem_benchmarks		},
+#ifdef HAVE_LIBNUMA_SUPPORT
+	{ "numa",	"NUMA scheduling and MM benchmarks",		numa_benchmarks		},
 #endif
-	{ "sched",
-	  "scheduler and IPC mechanism",
-	  sched_suites },
-	{ "mem",
-	  "memory access performance",
-	  mem_suites },
-	{ "all",		/* sentinel: easy for help */
-	  "all benchmark subsystem",
-	  NULL },
-	{ NULL,
-	  NULL,
-	  NULL       }
+	{ "all",	"All benchmarks",				NULL			},
+	{ NULL,		NULL,						NULL			}
 };
 
-static void dump_suites(int subsys_index)
+/* Iterate over all benchmark collections: */
+#define for_each_collection(coll) \
+	for (coll = collections; coll->name; coll++)
+
+/* Iterate over all benchmarks within a collection: */
+#define for_each_bench(coll, bench) \
+	for (bench = coll->benchmarks; bench->name; bench++)
+
+static void dump_benchmarks(struct collection *coll)
 {
-	int i;
+	struct bench *bench;
 
-	printf("# List of available suites for %s...\n\n",
-	       subsystems[subsys_index].name);
+	printf("\n        # List of available benchmarks for collection '%s':\n\n", coll->name);
 
-	for (i = 0; subsystems[subsys_index].suites[i].name; i++)
-		printf("%14s: %s\n",
-		       subsystems[subsys_index].suites[i].name,
-		       subsystems[subsys_index].suites[i].summary);
+	for_each_bench(coll, bench)
+		printf("%14s: %s\n", bench->name, bench->summary);
 
 	printf("\n");
-	return;
 }
 
 static const char *bench_format_str;
+
+/* Output/formatting style, exported to benchmark modules: */
 int bench_format = BENCH_FORMAT_DEFAULT;
 
 static const struct option bench_options[] = {
-	OPT_STRING('f', "format", &bench_format_str, "default",
-		    "Specify format style"),
+	OPT_STRING('f', "format", &bench_format_str, "default", "Specify format style"),
 	OPT_END()
 };
 
 static const char * const bench_usage[] = {
-	"perf bench [<common options>] <subsystem> <suite> [<options>]",
+	"perf bench [<common options>] <collection> <benchmark> [<options>]",
 	NULL
 };
 
 static void print_usage(void)
 {
+	struct collection *coll;
 	int i;
 
 	printf("Usage: \n");
@@ -138,11 +115,10 @@
 		printf("\t%s\n", bench_usage[i]);
 	printf("\n");
 
-	printf("# List of available subsystems...\n\n");
+	printf("        # List of all available benchmark collections:\n\n");
 
-	for (i = 0; subsystems[i].name; i++)
-		printf("%14s: %s\n",
-		       subsystems[i].name, subsystems[i].summary);
+	for_each_collection(coll)
+		printf("%14s: %s\n", coll->name, coll->summary);
 	printf("\n");
 }
 
@@ -159,44 +135,74 @@
 	return BENCH_FORMAT_UNKNOWN;
 }
 
-static void all_suite(struct bench_subsys *subsys)	  /* FROM HERE */
+/*
+ * Run a specific benchmark but first rename the running task's ->comm[]
+ * to something meaningful:
+ */
+static int run_bench(const char *coll_name, const char *bench_name, bench_fn_t fn,
+		     int argc, const char **argv, const char *prefix)
 {
-	int i;
+	int size;
+	char *name;
+	int ret;
+
+	size = strlen(coll_name) + 1 + strlen(bench_name) + 1;
+
+	name = zalloc(size);
+	BUG_ON(!name);
+
+	scnprintf(name, size, "%s-%s", coll_name, bench_name);
+
+	prctl(PR_SET_NAME, name);
+	argv[0] = name;
+
+	ret = fn(argc, argv, prefix);
+
+	free(name);
+
+	return ret;
+}
+
+static void run_collection(struct collection *coll)
+{
+	struct bench *bench;
 	const char *argv[2];
-	struct bench_suite *suites = subsys->suites;
 
 	argv[1] = NULL;
 	/*
 	 * TODO:
-	 * preparing preset parameters for
+	 *
+	 * Preparing preset parameters for
 	 * embedded, ordinary PC, HPC, etc...
-	 * will be helpful
+	 * would be helpful.
 	 */
-	for (i = 0; suites[i].fn; i++) {
-		printf("# Running %s/%s benchmark...\n",
-		       subsys->name,
-		       suites[i].name);
+	for_each_bench(coll, bench) {
+		if (!bench->fn)
+			break;
+		printf("# Running %s/%s benchmark...\n", coll->name, bench->name);
 		fflush(stdout);
 
-		argv[1] = suites[i].name;
-		suites[i].fn(1, argv, NULL);
+		argv[1] = bench->name;
+		run_bench(coll->name, bench->name, bench->fn, 1, argv, NULL);
 		printf("\n");
 	}
 }
 
-static void all_subsystem(void)
+static void run_all_collections(void)
 {
-	int i;
-	for (i = 0; subsystems[i].suites; i++)
-		all_suite(&subsystems[i]);
+	struct collection *coll;
+
+	for_each_collection(coll)
+		run_collection(coll);
 }
 
 int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused)
 {
-	int i, j, status = 0;
+	struct collection *coll;
+	int ret = 0;
 
 	if (argc < 2) {
-		/* No subsystem specified. */
+		/* No collection specified. */
 		print_usage();
 		goto end;
 	}
@@ -206,7 +212,7 @@
 
 	bench_format = bench_str2int(bench_format_str);
 	if (bench_format == BENCH_FORMAT_UNKNOWN) {
-		printf("Unknown format descriptor:%s\n", bench_format_str);
+		printf("Unknown format descriptor: '%s'\n", bench_format_str);
 		goto end;
 	}
 
@@ -216,52 +222,51 @@
 	}
 
 	if (!strcmp(argv[0], "all")) {
-		all_subsystem();
+		run_all_collections();
 		goto end;
 	}
 
-	for (i = 0; subsystems[i].name; i++) {
-		if (strcmp(subsystems[i].name, argv[0]))
+	for_each_collection(coll) {
+		struct bench *bench;
+
+		if (strcmp(coll->name, argv[0]))
 			continue;
 
 		if (argc < 2) {
-			/* No suite specified. */
-			dump_suites(i);
+			/* No bench specified. */
+			dump_benchmarks(coll);
 			goto end;
 		}
 
 		if (!strcmp(argv[1], "all")) {
-			all_suite(&subsystems[i]);
+			run_collection(coll);
 			goto end;
 		}
 
-		for (j = 0; subsystems[i].suites[j].name; j++) {
-			if (strcmp(subsystems[i].suites[j].name, argv[1]))
+		for_each_bench(coll, bench) {
+			if (strcmp(bench->name, argv[1]))
 				continue;
 
 			if (bench_format == BENCH_FORMAT_DEFAULT)
-				printf("# Running %s/%s benchmark...\n",
-				       subsystems[i].name,
-				       subsystems[i].suites[j].name);
+				printf("# Running '%s/%s' benchmark:\n", coll->name, bench->name);
 			fflush(stdout);
-			status = subsystems[i].suites[j].fn(argc - 1,
-							    argv + 1, prefix);
+			ret = run_bench(coll->name, bench->name, bench->fn, argc-1, argv+1, prefix);
 			goto end;
 		}
 
 		if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
-			dump_suites(i);
+			dump_benchmarks(coll);
 			goto end;
 		}
 
-		printf("Unknown suite:%s for %s\n", argv[1], argv[0]);
-		status = 1;
+		printf("Unknown benchmark: '%s' for collection '%s'\n", argv[1], argv[0]);
+		ret = 1;
 		goto end;
 	}
 
-	printf("Unknown subsystem:%s\n", argv[0]);
-	status = 1;
+	printf("Unknown collection: '%s'\n", argv[0]);
+	ret = 1;
 
 end:
-	return status;
+	return ret;
 }
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index c96c8fa..cfede86 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -6,6 +6,11 @@
  * Copyright (C) 2010, Red Hat Inc.
  * Copyright (C) 2010, Arnaldo Carvalho de Melo <acme@redhat.com>
  */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+#include <dirent.h>
+#include <unistd.h>
 #include "builtin.h"
 #include "perf.h"
 #include "util/cache.h"
@@ -17,6 +22,140 @@
 #include "util/session.h"
 #include "util/symbol.h"
 
+static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid)
+{
+	char root_dir[PATH_MAX];
+	char notes[PATH_MAX];
+	u8 build_id[BUILD_ID_SIZE];
+	char *p;
+
+	strlcpy(root_dir, proc_dir, sizeof(root_dir));
+
+	p = strrchr(root_dir, '/');
+	if (!p)
+		return -1;
+	*p = '\0';
+
+	scnprintf(notes, sizeof(notes), "%s/sys/kernel/notes", root_dir);
+
+	if (sysfs__read_build_id(notes, build_id, sizeof(build_id)))
+		return -1;
+
+	build_id__sprintf(build_id, sizeof(build_id), sbuildid);
+
+	return 0;
+}
+
+static int build_id_cache__kcore_dir(char *dir, size_t sz)
+{
+	struct timeval tv;
+	struct tm tm;
+	char dt[32];
+
+	if (gettimeofday(&tv, NULL) || !localtime_r(&tv.tv_sec, &tm))
+		return -1;
+
+	if (!strftime(dt, sizeof(dt), "%Y%m%d%H%M%S", &tm))
+		return -1;
+
+	scnprintf(dir, sz, "%s%02u", dt, (unsigned)tv.tv_usec / 10000);
+
+	return 0;
+}
+
+static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,
+					  size_t to_dir_sz)
+{
+	char from[PATH_MAX];
+	char to[PATH_MAX];
+	struct dirent *dent;
+	int ret = -1;
+	DIR *d;
+
+	d = opendir(to_dir);
+	if (!d)
+		return -1;
+
+	scnprintf(from, sizeof(from), "%s/modules", from_dir);
+
+	while (1) {
+		dent = readdir(d);
+		if (!dent)
+			break;
+		if (dent->d_type != DT_DIR)
+			continue;
+		scnprintf(to, sizeof(to), "%s/%s/modules", to_dir,
+			  dent->d_name);
+		if (!compare_proc_modules(from, to)) {
+			scnprintf(to, sizeof(to), "%s/%s", to_dir,
+				  dent->d_name);
+			strlcpy(to_dir, to, to_dir_sz);
+			ret = 0;
+			break;
+		}
+	}
+
+	closedir(d);
+
+	return ret;
+}
+
+static int build_id_cache__add_kcore(const char *filename, const char *debugdir)
+{
+	char dir[32], sbuildid[BUILD_ID_SIZE * 2 + 1];
+	char from_dir[PATH_MAX], to_dir[PATH_MAX];
+	char *p;
+
+	strlcpy(from_dir, filename, sizeof(from_dir));
+
+	p = strrchr(from_dir, '/');
+	if (!p || strcmp(p + 1, "kcore"))
+		return -1;
+	*p = '\0';
+
+	if (build_id_cache__kcore_buildid(from_dir, sbuildid))
+		return -1;
+
+	scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s",
+		  debugdir, sbuildid);
+
+	if (!build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) {
+		pr_debug("same kcore found in %s\n", to_dir);
+		return 0;
+	}
+
+	if (build_id_cache__kcore_dir(dir, sizeof(dir)))
+		return -1;
+
+	scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s/%s",
+		  debugdir, sbuildid, dir);
+
+	if (mkdir_p(to_dir, 0755))
+		return -1;
+
+	if (kcore_copy(from_dir, to_dir)) {
+		/* Remove YYYYmmddHHMMSShh directory */
+		if (!rmdir(to_dir)) {
+			p = strrchr(to_dir, '/');
+			if (p)
+				*p = '\0';
+			/* Try to remove buildid directory */
+			if (!rmdir(to_dir)) {
+				p = strrchr(to_dir, '/');
+				if (p)
+					*p = '\0';
+				/* Try to remove [kernel.kcore] directory */
+				rmdir(to_dir);
+			}
+		}
+		return -1;
+	}
+
+	pr_debug("kcore added to build-id cache directory %s\n", to_dir);
+
+	return 0;
+}
+
 static int build_id_cache__add_file(const char *filename, const char *debugdir)
 {
 	char sbuild_id[BUILD_ID_SIZE * 2 + 1];
@@ -82,8 +221,12 @@
 
 static int build_id_cache__fprintf_missing(const char *filename, bool force, FILE *fp)
 {
-	struct perf_session *session = perf_session__new(filename, O_RDONLY,
-							 force, false, NULL);
+	struct perf_data_file file = {
+		.path  = filename,
+		.mode  = PERF_DATA_MODE_READ,
+		.force = force,
+	};
+	struct perf_session *session = perf_session__new(&file, false, NULL);
 	if (session == NULL)
 		return -1;
 
@@ -130,11 +273,14 @@
 	char const *add_name_list_str = NULL,
 		   *remove_name_list_str = NULL,
 		   *missing_filename = NULL,
-		   *update_name_list_str = NULL;
+		   *update_name_list_str = NULL,
+		   *kcore_filename;
 
 	const struct option buildid_cache_options[] = {
 	OPT_STRING('a', "add", &add_name_list_str,
 		   "file list", "file(s) to add"),
+	OPT_STRING('k', "kcore", &kcore_filename,
+		   "file", "kcore file to add"),
 	OPT_STRING('r', "remove", &remove_name_list_str, "file list",
 		    "file(s) to remove"),
 	OPT_STRING('M', "missing", &missing_filename, "file",
@@ -217,5 +363,9 @@
 		}
 	}
 
+	if (kcore_filename &&
+	    build_id_cache__add_kcore(kcore_filename, debugdir))
+		pr_warning("Couldn't add %s\n", kcore_filename);
+
 	return ret;
 }
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index e74366a..ed3873b 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -15,6 +15,7 @@
 #include "util/parse-options.h"
 #include "util/session.h"
 #include "util/symbol.h"
+#include "util/data.h"
 
 static int sysfs__fprintf_build_id(FILE *fp)
 {
@@ -52,6 +53,11 @@
 static int perf_session__list_build_ids(bool force, bool with_hits)
 {
 	struct perf_session *session;
+	struct perf_data_file file = {
+		.path  = input_name,
+		.mode  = PERF_DATA_MODE_READ,
+		.force = force,
+	};
 
 	symbol__elf_init();
 	/*
@@ -60,15 +66,14 @@
 	if (filename__fprintf_build_id(input_name, stdout))
 		goto out;
 
-	session = perf_session__new(input_name, O_RDONLY, force, false,
-				    &build_id__mark_dso_hit_ops);
+	session = perf_session__new(&file, false, &build_id__mark_dso_hit_ops);
 	if (session == NULL)
 		return -1;
 	/*
 	 * in pipe-mode, the only way to get the buildids is to parse
 	 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
 	 */
-	if (with_hits || session->fd_pipe)
+	if (with_hits || perf_data_file__is_pipe(&file))
 		perf_session__process_events(session, &build_id__mark_dso_hit_ops);
 
 	perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits);
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index f28799e..3b67ea2 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -16,6 +16,7 @@
 #include "util/sort.h"
 #include "util/symbol.h"
 #include "util/util.h"
+#include "util/data.h"
 
 #include <stdlib.h>
 #include <math.h>
@@ -42,7 +43,7 @@
 
 struct data__file {
 	struct perf_session	*session;
-	const char		*file;
+	struct perf_data_file	file;
 	int			 idx;
 	struct hists		*hists;
 	struct diff_hpp_fmt	 fmt[PERF_HPP_DIFF__MAX_INDEX];
@@ -302,11 +303,12 @@
 	return -1;
 }
 
-static int hists__add_entry(struct hists *self,
+static int hists__add_entry(struct hists *hists,
 			    struct addr_location *al, u64 period,
-			    u64 weight)
+			    u64 weight, u64 transaction)
 {
-	if (__hists__add_entry(self, al, NULL, period, weight) != NULL)
+	if (__hists__add_entry(hists, al, NULL, NULL, NULL, period, weight,
+			       transaction) != NULL)
 		return 0;
 	return -ENOMEM;
 }
@@ -328,7 +330,8 @@
 	if (al.filtered)
 		return 0;
 
-	if (hists__add_entry(&evsel->hists, &al, sample->period, sample->weight)) {
+	if (hists__add_entry(&evsel->hists, &al, sample->period,
+			     sample->weight, sample->transaction)) {
 		pr_warning("problem incrementing symbol period, skipping event\n");
 		return -1;
 	}
@@ -367,7 +370,7 @@
 	list_for_each_entry(evsel, &evlist->entries, node) {
 		struct hists *hists = &evsel->hists;
 
-		hists__collapse_resort(hists);
+		hists__collapse_resort(hists, NULL);
 	}
 }
 
@@ -599,7 +602,7 @@
 
 	data__for_each_file(i, d)
 		fprintf(stdout, "#  [%d] %s %s\n",
-			d->idx, d->file,
+			d->idx, d->file.path,
 			!d->idx ? "(Baseline)" : "");
 
 	fprintf(stdout, "#\n");
@@ -661,17 +664,16 @@
 	int ret = -EINVAL, i;
 
 	data__for_each_file(i, d) {
-		d->session = perf_session__new(d->file, O_RDONLY, force,
-					       false, &tool);
+		d->session = perf_session__new(&d->file, false, &tool);
 		if (!d->session) {
-			pr_err("Failed to open %s\n", d->file);
+			pr_err("Failed to open %s\n", d->file.path);
 			ret = -ENOMEM;
 			goto out_delete;
 		}
 
 		ret = perf_session__process_events(d->session, &tool);
 		if (ret) {
-			pr_err("Failed to process %s\n", d->file);
+			pr_err("Failed to process %s\n", d->file.path);
 			goto out_delete;
 		}
 
@@ -1014,7 +1016,12 @@
 		return -ENOMEM;
 
 	data__for_each_file(i, d) {
-		d->file = use_default ? defaults[i] : argv[i];
+		struct perf_data_file *file = &d->file;
+
+		file->path  = use_default ? defaults[i] : argv[i];
+		file->mode  = PERF_DATA_MODE_READ,
+		file->force = force,
+
 		d->idx  = i;
 	}
 
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 05bd9df..20b0f12 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -14,13 +14,18 @@
 #include "util/parse-events.h"
 #include "util/parse-options.h"
 #include "util/session.h"
+#include "util/data.h"
 
 static int __cmd_evlist(const char *file_name, struct perf_attr_details *details)
 {
 	struct perf_session *session;
 	struct perf_evsel *pos;
+	struct perf_data_file file = {
+		.path = file_name,
+		.mode = PERF_DATA_MODE_READ,
+	};
 
-	session = perf_session__new(file_name, O_RDONLY, 0, false, NULL);
+	session = perf_session__new(&file, 0, NULL);
 	if (session == NULL)
 		return -ENOMEM;
 
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index afe377b..6a25085 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -15,6 +15,7 @@
 #include "util/tool.h"
 #include "util/debug.h"
 #include "util/build-id.h"
+#include "util/data.h"
 
 #include "util/parse-options.h"
 
@@ -71,12 +72,17 @@
 				   union perf_event *event,
 				   struct perf_evlist **pevlist)
 {
+	struct perf_inject *inject = container_of(tool, struct perf_inject,
+						  tool);
 	int ret;
 
 	ret = perf_event__process_attr(tool, event, pevlist);
 	if (ret)
 		return ret;
 
+	if (!inject->pipe_output)
+		return 0;
+
 	return perf_event__repipe_synth(tool, event);
 }
 
@@ -100,8 +106,8 @@
 				     struct perf_evsel *evsel,
 				     struct machine *machine)
 {
-	if (evsel->handler.func) {
-		inject_handler f = evsel->handler.func;
+	if (evsel->handler) {
+		inject_handler f = evsel->handler;
 		return f(tool, event, sample, evsel, machine);
 	}
 
@@ -161,38 +167,38 @@
 	return err;
 }
 
-static int dso__read_build_id(struct dso *self)
+static int dso__read_build_id(struct dso *dso)
 {
-	if (self->has_build_id)
+	if (dso->has_build_id)
 		return 0;
 
-	if (filename__read_build_id(self->long_name, self->build_id,
-				    sizeof(self->build_id)) > 0) {
-		self->has_build_id = true;
+	if (filename__read_build_id(dso->long_name, dso->build_id,
+				    sizeof(dso->build_id)) > 0) {
+		dso->has_build_id = true;
 		return 0;
 	}
 
 	return -1;
 }
 
-static int dso__inject_build_id(struct dso *self, struct perf_tool *tool,
+static int dso__inject_build_id(struct dso *dso, struct perf_tool *tool,
 				struct machine *machine)
 {
 	u16 misc = PERF_RECORD_MISC_USER;
 	int err;
 
-	if (dso__read_build_id(self) < 0) {
-		pr_debug("no build_id found for %s\n", self->long_name);
+	if (dso__read_build_id(dso) < 0) {
+		pr_debug("no build_id found for %s\n", dso->long_name);
 		return -1;
 	}
 
-	if (self->kernel)
+	if (dso->kernel)
 		misc = PERF_RECORD_MISC_KERNEL;
 
-	err = perf_event__synthesize_build_id(tool, self, misc, perf_event__repipe,
+	err = perf_event__synthesize_build_id(tool, dso, misc, perf_event__repipe,
 					      machine);
 	if (err) {
-		pr_err("Can't synthesize build_id event for %s\n", self->long_name);
+		pr_err("Can't synthesize build_id event for %s\n", dso->long_name);
 		return -1;
 	}
 
@@ -231,7 +237,7 @@
 				 * account this as unresolved.
 				 */
 			} else {
-#ifdef LIBELF_SUPPORT
+#ifdef HAVE_LIBELF_SUPPORT
 				pr_warning("no symbols found in %s, maybe "
 					   "install a debug package?\n",
 					   al.map->dso->long_name);
@@ -345,6 +351,10 @@
 {
 	struct perf_session *session;
 	int ret = -EINVAL;
+	struct perf_data_file file = {
+		.path = inject->input_name,
+		.mode = PERF_DATA_MODE_READ,
+	};
 
 	signal(SIGINT, sig_handler);
 
@@ -355,7 +365,7 @@
 		inject->tool.tracing_data = perf_event__repipe_tracing_data;
 	}
 
-	session = perf_session__new(inject->input_name, O_RDONLY, false, true, &inject->tool);
+	session = perf_session__new(&file, true, &inject->tool);
 	if (session == NULL)
 		return -ENOMEM;
 
@@ -373,11 +383,11 @@
 				if (perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID"))
 					return -EINVAL;
 
-				evsel->handler.func = perf_inject__sched_switch;
+				evsel->handler = perf_inject__sched_switch;
 			} else if (!strcmp(name, "sched:sched_process_exit"))
-				evsel->handler.func = perf_inject__sched_process_exit;
+				evsel->handler = perf_inject__sched_process_exit;
 			else if (!strncmp(name, "sched:sched_stat_", 17))
-				evsel->handler.func = perf_inject__sched_stat;
+				evsel->handler = perf_inject__sched_stat;
 		}
 	}
 
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 9b5f077..929462a 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -13,6 +13,7 @@
 
 #include "util/parse-options.h"
 #include "util/trace-event.h"
+#include "util/data.h"
 
 #include "util/debug.h"
 
@@ -314,10 +315,10 @@
 		return -1;
 	}
 
-	dump_printf(" ... thread: %s:%d\n", thread->comm, thread->tid);
+	dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
 
-	if (evsel->handler.func != NULL) {
-		tracepoint_handler f = evsel->handler.func;
+	if (evsel->handler != NULL) {
+		tracepoint_handler f = evsel->handler;
 		return f(evsel, sample);
 	}
 
@@ -486,8 +487,12 @@
 		{ "kmem:kfree",			perf_evsel__process_free_event, },
     		{ "kmem:kmem_cache_free",	perf_evsel__process_free_event, },
 	};
+	struct perf_data_file file = {
+		.path = input_name,
+		.mode = PERF_DATA_MODE_READ,
+	};
 
-	session = perf_session__new(input_name, O_RDONLY, 0, false, &perf_kmem);
+	session = perf_session__new(&file, false, &perf_kmem);
 	if (session == NULL)
 		return -ENOMEM;
 
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 935d522..cd9f920 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -17,9 +17,12 @@
 #include "util/tool.h"
 #include "util/stat.h"
 #include "util/top.h"
+#include "util/data.h"
 
 #include <sys/prctl.h>
+#ifdef HAVE_TIMERFD_SUPPORT
 #include <sys/timerfd.h>
+#endif
 
 #include <termios.h>
 #include <semaphore.h>
@@ -336,6 +339,7 @@
 		INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
 }
 
+#ifdef HAVE_TIMERFD_SUPPORT
 static void clear_events_cache_stats(struct list_head *kvm_events_cache)
 {
 	struct list_head *head;
@@ -357,6 +361,7 @@
 		}
 	}
 }
+#endif
 
 static int kvm_events_hash_fn(u64 key)
 {
@@ -782,6 +787,7 @@
 		pr_info("\nLost events: %" PRIu64 "\n\n", kvm->lost_events);
 }
 
+#ifdef HAVE_TIMERFD_SUPPORT
 static int process_lost_event(struct perf_tool *tool,
 			      union perf_event *event __maybe_unused,
 			      struct perf_sample *sample __maybe_unused,
@@ -792,6 +798,7 @@
 	kvm->lost_events++;
 	return 0;
 }
+#endif
 
 static bool skip_sample(struct perf_kvm_stat *kvm,
 			struct perf_sample *sample)
@@ -871,6 +878,7 @@
 	return true;
 }
 
+#ifdef HAVE_TIMERFD_SUPPORT
 /* keeping the max events to a modest level to keep
  * the processing of samples per mmap smooth.
  */
@@ -888,11 +896,18 @@
 	while ((event = perf_evlist__mmap_read(kvm->evlist, idx)) != NULL) {
 		err = perf_evlist__parse_sample(kvm->evlist, event, &sample);
 		if (err) {
+			perf_evlist__mmap_consume(kvm->evlist, idx);
 			pr_err("Failed to parse sample\n");
 			return -1;
 		}
 
 		err = perf_session_queue_event(kvm->session, event, &sample, 0);
+		/*
+		 * FIXME: Here we can't consume the event, as perf_session_queue_event will
+		 *        point to it, and it'll get possibly overwritten by the kernel.
+		 */
+		perf_evlist__mmap_consume(kvm->evlist, idx);
+
 		if (err) {
 			pr_err("Failed to enqueue sample: %d\n", err);
 			return -1;
@@ -1205,6 +1220,7 @@
 out:
 	return rc;
 }
+#endif
 
 static int read_events(struct perf_kvm_stat *kvm)
 {
@@ -1215,10 +1231,13 @@
 		.comm			= perf_event__process_comm,
 		.ordered_samples	= true,
 	};
+	struct perf_data_file file = {
+		.path = input_name,
+		.mode = PERF_DATA_MODE_READ,
+	};
 
 	kvm->tool = eops;
-	kvm->session = perf_session__new(kvm->file_name, O_RDONLY, 0, false,
-					 &kvm->tool);
+	kvm->session = perf_session__new(&file, false, &kvm->tool);
 	if (!kvm->session) {
 		pr_err("Initializing perf session failed\n");
 		return -EINVAL;
@@ -1368,6 +1387,7 @@
 	return kvm_events_report_vcpu(kvm);
 }
 
+#ifdef HAVE_TIMERFD_SUPPORT
 static struct perf_evlist *kvm_live_event_list(void)
 {
 	struct perf_evlist *evlist;
@@ -1426,8 +1446,9 @@
 	const struct option live_options[] = {
 		OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid",
 			"record events on existing process id"),
-		OPT_UINTEGER('m', "mmap-pages", &kvm->opts.mmap_pages,
-			"number of mmap data pages"),
+		OPT_CALLBACK('m', "mmap-pages", &kvm->opts.mmap_pages, "pages",
+			"number of mmap data pages",
+			perf_evlist__parse_mmap_pages),
 		OPT_INCR('v', "verbose", &verbose,
 			"be more verbose (show counter open errors, etc)"),
 		OPT_BOOLEAN('a', "all-cpus", &kvm->opts.target.system_wide,
@@ -1449,6 +1470,9 @@
 		"perf kvm stat live [<options>]",
 		NULL
 	};
+	struct perf_data_file file = {
+		.mode = PERF_DATA_MODE_WRITE,
+	};
 
 
 	/* event handling */
@@ -1513,7 +1537,7 @@
 	/*
 	 * perf session
 	 */
-	kvm->session = perf_session__new(NULL, O_WRONLY, false, false, &kvm->tool);
+	kvm->session = perf_session__new(&file, false, &kvm->tool);
 	if (kvm->session == NULL) {
 		err = -ENOMEM;
 		goto out;
@@ -1551,6 +1575,7 @@
 
 	return err;
 }
+#endif
 
 static void print_kvm_stat_usage(void)
 {
@@ -1589,8 +1614,10 @@
 	if (!strncmp(argv[1], "rep", 3))
 		return kvm_events_report(&kvm, argc - 1 , argv + 1);
 
+#ifdef HAVE_TIMERFD_SUPPORT
 	if (!strncmp(argv[1], "live", 4))
 		return kvm_events_live(&kvm, argc - 1 , argv + 1);
+#endif
 
 perf_stat:
 	return cmd_stat(argc, argv, NULL);
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index e79f423..011195e 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -14,51 +14,63 @@
 #include "util/parse-events.h"
 #include "util/cache.h"
 #include "util/pmu.h"
+#include "util/parse-options.h"
 
 int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 {
+	int i;
+	const struct option list_options[] = {
+		OPT_END()
+	};
+	const char * const list_usage[] = {
+		"perf list [hw|sw|cache|tracepoint|pmu|event_glob]",
+		NULL
+	};
+
+	argc = parse_options(argc, argv, list_options, list_usage,
+			     PARSE_OPT_STOP_AT_NON_OPTION);
+
 	setup_pager();
 
-	if (argc == 1)
+	if (argc == 0) {
 		print_events(NULL, false);
-	else {
-		int i;
+		return 0;
+	}
 
-		for (i = 1; i < argc; ++i) {
-			if (i > 2)
-				putchar('\n');
-			if (strncmp(argv[i], "tracepoint", 10) == 0)
-				print_tracepoint_events(NULL, NULL, false);
-			else if (strcmp(argv[i], "hw") == 0 ||
-				 strcmp(argv[i], "hardware") == 0)
-				print_events_type(PERF_TYPE_HARDWARE);
-			else if (strcmp(argv[i], "sw") == 0 ||
-				 strcmp(argv[i], "software") == 0)
-				print_events_type(PERF_TYPE_SOFTWARE);
-			else if (strcmp(argv[i], "cache") == 0 ||
-				 strcmp(argv[i], "hwcache") == 0)
-				print_hwcache_events(NULL, false);
-			else if (strcmp(argv[i], "pmu") == 0)
-				print_pmu_events(NULL, false);
-			else if (strcmp(argv[i], "--raw-dump") == 0)
-				print_events(NULL, true);
-			else {
-				char *sep = strchr(argv[i], ':'), *s;
-				int sep_idx;
+	for (i = 0; i < argc; ++i) {
+		if (i)
+			putchar('\n');
+		if (strncmp(argv[i], "tracepoint", 10) == 0)
+			print_tracepoint_events(NULL, NULL, false);
+		else if (strcmp(argv[i], "hw") == 0 ||
+			 strcmp(argv[i], "hardware") == 0)
+			print_events_type(PERF_TYPE_HARDWARE);
+		else if (strcmp(argv[i], "sw") == 0 ||
+			 strcmp(argv[i], "software") == 0)
+			print_events_type(PERF_TYPE_SOFTWARE);
+		else if (strcmp(argv[i], "cache") == 0 ||
+			 strcmp(argv[i], "hwcache") == 0)
+			print_hwcache_events(NULL, false);
+		else if (strcmp(argv[i], "pmu") == 0)
+			print_pmu_events(NULL, false);
+		else if (strcmp(argv[i], "--raw-dump") == 0)
+			print_events(NULL, true);
+		else {
+			char *sep = strchr(argv[i], ':'), *s;
+			int sep_idx;
 
-				if (sep == NULL) {
-					print_events(argv[i], false);
-					continue;
-				}
-				sep_idx = sep - argv[i];
-				s = strdup(argv[i]);
-				if (s == NULL)
-					return -1;
-
-				s[sep_idx] = '\0';
-				print_tracepoint_events(s, s + sep_idx + 1, false);
-				free(s);
+			if (sep == NULL) {
+				print_events(argv[i], false);
+				continue;
 			}
+			sep_idx = sep - argv[i];
+			s = strdup(argv[i]);
+			if (s == NULL)
+				return -1;
+
+			s[sep_idx] = '\0';
+			print_tracepoint_events(s, s + sep_idx + 1, false);
+			free(s);
 		}
 	}
 	return 0;
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index ee33ba2..c852c7a 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -15,6 +15,7 @@
 #include "util/debug.h"
 #include "util/session.h"
 #include "util/tool.h"
+#include "util/data.h"
 
 #include <sys/types.h>
 #include <sys/prctl.h>
@@ -56,7 +57,9 @@
 
 	unsigned int		nr_readlock;
 	unsigned int		nr_trylock;
+
 	/* these times are in nano sec. */
+	u64                     avg_wait_time;
 	u64			wait_time_total;
 	u64			wait_time_min;
 	u64			wait_time_max;
@@ -208,6 +211,7 @@
 
 SINGLE_KEY(nr_acquired)
 SINGLE_KEY(nr_contended)
+SINGLE_KEY(avg_wait_time)
 SINGLE_KEY(wait_time_total)
 SINGLE_KEY(wait_time_max)
 
@@ -244,6 +248,7 @@
 struct lock_key keys[] = {
 	DEF_KEY_LOCK(acquired, nr_acquired),
 	DEF_KEY_LOCK(contended, nr_contended),
+	DEF_KEY_LOCK(avg_wait, avg_wait_time),
 	DEF_KEY_LOCK(wait_total, wait_time_total),
 	DEF_KEY_LOCK(wait_min, wait_time_min),
 	DEF_KEY_LOCK(wait_max, wait_time_max),
@@ -321,10 +326,12 @@
 
 	new->addr = addr;
 	new->name = zalloc(sizeof(char) * strlen(name) + 1);
-	if (!new->name)
+	if (!new->name) {
+		free(new);
 		goto alloc_failed;
-	strcpy(new->name, name);
+	}
 
+	strcpy(new->name, name);
 	new->wait_time_min = ULLONG_MAX;
 
 	list_add(&new->hash_entry, entry);
@@ -400,17 +407,17 @@
 
 	ls = lock_stat_findnew(addr, name);
 	if (!ls)
-		return -1;
+		return -ENOMEM;
 	if (ls->discard)
 		return 0;
 
 	ts = thread_stat_findnew(sample->tid);
 	if (!ts)
-		return -1;
+		return -ENOMEM;
 
 	seq = get_seq(ts, addr);
 	if (!seq)
-		return -1;
+		return -ENOMEM;
 
 	switch (seq->state) {
 	case SEQ_STATE_UNINITIALIZED:
@@ -446,7 +453,6 @@
 		list_del(&seq->list);
 		free(seq);
 		goto end;
-		break;
 	default:
 		BUG_ON("Unknown state of lock sequence found!\n");
 		break;
@@ -473,17 +479,17 @@
 
 	ls = lock_stat_findnew(addr, name);
 	if (!ls)
-		return -1;
+		return -ENOMEM;
 	if (ls->discard)
 		return 0;
 
 	ts = thread_stat_findnew(sample->tid);
 	if (!ts)
-		return -1;
+		return -ENOMEM;
 
 	seq = get_seq(ts, addr);
 	if (!seq)
-		return -1;
+		return -ENOMEM;
 
 	switch (seq->state) {
 	case SEQ_STATE_UNINITIALIZED:
@@ -508,8 +514,6 @@
 		list_del(&seq->list);
 		free(seq);
 		goto end;
-		break;
-
 	default:
 		BUG_ON("Unknown state of lock sequence found!\n");
 		break;
@@ -517,6 +521,7 @@
 
 	seq->state = SEQ_STATE_ACQUIRED;
 	ls->nr_acquired++;
+	ls->avg_wait_time = ls->nr_contended ? ls->wait_time_total/ls->nr_contended : 0;
 	seq->prev_event_time = sample->time;
 end:
 	return 0;
@@ -536,17 +541,17 @@
 
 	ls = lock_stat_findnew(addr, name);
 	if (!ls)
-		return -1;
+		return -ENOMEM;
 	if (ls->discard)
 		return 0;
 
 	ts = thread_stat_findnew(sample->tid);
 	if (!ts)
-		return -1;
+		return -ENOMEM;
 
 	seq = get_seq(ts, addr);
 	if (!seq)
-		return -1;
+		return -ENOMEM;
 
 	switch (seq->state) {
 	case SEQ_STATE_UNINITIALIZED:
@@ -564,7 +569,6 @@
 		list_del(&seq->list);
 		free(seq);
 		goto end;
-		break;
 	default:
 		BUG_ON("Unknown state of lock sequence found!\n");
 		break;
@@ -572,6 +576,7 @@
 
 	seq->state = SEQ_STATE_CONTENDED;
 	ls->nr_contended++;
+	ls->avg_wait_time = ls->wait_time_total/ls->nr_contended;
 	seq->prev_event_time = sample->time;
 end:
 	return 0;
@@ -591,22 +596,21 @@
 
 	ls = lock_stat_findnew(addr, name);
 	if (!ls)
-		return -1;
+		return -ENOMEM;
 	if (ls->discard)
 		return 0;
 
 	ts = thread_stat_findnew(sample->tid);
 	if (!ts)
-		return -1;
+		return -ENOMEM;
 
 	seq = get_seq(ts, addr);
 	if (!seq)
-		return -1;
+		return -ENOMEM;
 
 	switch (seq->state) {
 	case SEQ_STATE_UNINITIALIZED:
 		goto end;
-		break;
 	case SEQ_STATE_ACQUIRED:
 		break;
 	case SEQ_STATE_READ_ACQUIRED:
@@ -624,7 +628,6 @@
 		ls->discard = 1;
 		bad_hist[BROKEN_RELEASE]++;
 		goto free_seq;
-		break;
 	default:
 		BUG_ON("Unknown state of lock sequence found!\n");
 		break;
@@ -690,7 +693,7 @@
 
 	pr_info("\n=== output for debug===\n\n");
 	pr_info("bad: %d, total: %d\n", bad, total);
-	pr_info("bad rate: %f %%\n", (double)bad / (double)total * 100);
+	pr_info("bad rate: %.2f %%\n", (double)bad / (double)total * 100);
 	pr_info("histogram of events caused bad sequence\n");
 	for (i = 0; i < BROKEN_MAX; i++)
 		pr_info(" %10s: %d\n", name[i], bad_hist[i]);
@@ -707,6 +710,7 @@
 	pr_info("%10s ", "acquired");
 	pr_info("%10s ", "contended");
 
+	pr_info("%15s ", "avg wait (ns)");
 	pr_info("%15s ", "total wait (ns)");
 	pr_info("%15s ", "max wait (ns)");
 	pr_info("%15s ", "min wait (ns)");
@@ -738,6 +742,7 @@
 		pr_info("%10u ", st->nr_acquired);
 		pr_info("%10u ", st->nr_contended);
 
+		pr_info("%15" PRIu64 " ", st->avg_wait_time);
 		pr_info("%15" PRIu64 " ", st->wait_time_total);
 		pr_info("%15" PRIu64 " ", st->wait_time_max);
 		pr_info("%15" PRIu64 " ", st->wait_time_min == ULLONG_MAX ?
@@ -762,7 +767,7 @@
 	while (node) {
 		st = container_of(node, struct thread_stat, rb);
 		t = perf_session__findnew(session, st->tid);
-		pr_info("%10d: %s\n", st->tid, t->comm);
+		pr_info("%10d: %s\n", st->tid, thread__comm_str(t));
 		node = rb_next(node);
 	};
 }
@@ -814,42 +819,14 @@
 		return -1;
 	}
 
-	if (evsel->handler.func != NULL) {
-		tracepoint_handler f = evsel->handler.func;
+	if (evsel->handler != NULL) {
+		tracepoint_handler f = evsel->handler;
 		return f(evsel, sample);
 	}
 
 	return 0;
 }
 
-static const struct perf_evsel_str_handler lock_tracepoints[] = {
-	{ "lock:lock_acquire",	 perf_evsel__process_lock_acquire,   }, /* CONFIG_LOCKDEP */
-	{ "lock:lock_acquired",	 perf_evsel__process_lock_acquired,  }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
-	{ "lock:lock_contended", perf_evsel__process_lock_contended, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
-	{ "lock:lock_release",	 perf_evsel__process_lock_release,   }, /* CONFIG_LOCKDEP */
-};
-
-static int read_events(void)
-{
-	struct perf_tool eops = {
-		.sample		 = process_sample_event,
-		.comm		 = perf_event__process_comm,
-		.ordered_samples = true,
-	};
-	session = perf_session__new(input_name, O_RDONLY, 0, false, &eops);
-	if (!session) {
-		pr_err("Initializing perf session failed\n");
-		return -1;
-	}
-
-	if (perf_session__set_tracepoints_handlers(session, lock_tracepoints)) {
-		pr_err("Initializing perf session tracepoint handlers failed\n");
-		return -1;
-	}
-
-	return perf_session__process_events(session, &eops);
-}
-
 static void sort_result(void)
 {
 	unsigned int i;
@@ -862,18 +839,58 @@
 	}
 }
 
-static int __cmd_report(void)
+static const struct perf_evsel_str_handler lock_tracepoints[] = {
+	{ "lock:lock_acquire",	 perf_evsel__process_lock_acquire,   }, /* CONFIG_LOCKDEP */
+	{ "lock:lock_acquired",	 perf_evsel__process_lock_acquired,  }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
+	{ "lock:lock_contended", perf_evsel__process_lock_contended, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
+	{ "lock:lock_release",	 perf_evsel__process_lock_release,   }, /* CONFIG_LOCKDEP */
+};
+
+static int __cmd_report(bool display_info)
 {
+	int err = -EINVAL;
+	struct perf_tool eops = {
+		.sample		 = process_sample_event,
+		.comm		 = perf_event__process_comm,
+		.ordered_samples = true,
+	};
+	struct perf_data_file file = {
+		.path = input_name,
+		.mode = PERF_DATA_MODE_READ,
+	};
+
+	session = perf_session__new(&file, false, &eops);
+	if (!session) {
+		pr_err("Initializing perf session failed\n");
+		return -ENOMEM;
+	}
+
+	if (!perf_session__has_traces(session, "lock record"))
+		goto out_delete;
+
+	if (perf_session__set_tracepoints_handlers(session, lock_tracepoints)) {
+		pr_err("Initializing perf session tracepoint handlers failed\n");
+		goto out_delete;
+	}
+
+	if (select_key())
+		goto out_delete;
+
+	err = perf_session__process_events(session, &eops);
+	if (err)
+		goto out_delete;
+
 	setup_pager();
+	if (display_info) /* used for info subcommand */
+		err = dump_info();
+	else {
+		sort_result();
+		print_result();
+	}
 
-	if ((select_key() != 0) ||
-	    (read_events() != 0))
-		return -1;
-
-	sort_result();
-	print_result();
-
-	return 0;
+out_delete:
+	perf_session__delete(session);
+	return err;
 }
 
 static int __cmd_record(int argc, const char **argv)
@@ -881,7 +898,7 @@
 	const char *record_args[] = {
 		"record", "-R", "-m", "1024", "-c", "1",
 	};
-	unsigned int rec_argc, i, j;
+	unsigned int rec_argc, i, j, ret;
 	const char **rec_argv;
 
 	for (i = 0; i < ARRAY_SIZE(lock_tracepoints); i++) {
@@ -898,7 +915,7 @@
 	rec_argc += 2 * ARRAY_SIZE(lock_tracepoints);
 
 	rec_argv = calloc(rec_argc + 1, sizeof(char *));
-	if (rec_argv == NULL)
+	if (!rec_argv)
 		return -ENOMEM;
 
 	for (i = 0; i < ARRAY_SIZE(record_args); i++)
@@ -914,7 +931,9 @@
 
 	BUG_ON(i != rec_argc);
 
-	return cmd_record(i, rec_argv, NULL);
+	ret = cmd_record(i, rec_argv, NULL);
+	free(rec_argv);
+	return ret;
 }
 
 int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
@@ -934,7 +953,7 @@
 	};
 	const struct option report_options[] = {
 	OPT_STRING('k', "key", &sort_key, "acquired",
-		    "key for sorting (acquired / contended / wait_total / wait_max / wait_min)"),
+		    "key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"),
 	/* TODO: type */
 	OPT_END()
 	};
@@ -972,7 +991,7 @@
 			if (argc)
 				usage_with_options(report_usage, report_options);
 		}
-		__cmd_report();
+		rc = __cmd_report(false);
 	} else if (!strcmp(argv[0], "script")) {
 		/* Aliased to 'perf script' */
 		return cmd_script(argc, argv, prefix);
@@ -985,11 +1004,7 @@
 		}
 		/* recycling report_lock_ops */
 		trace_handler = &report_lock_ops;
-		setup_pager();
-		if (read_events() != 0)
-			rc = -1;
-		else
-			rc = dump_info();
+		rc = __cmd_report(true);
 	} else {
 		usage_with_options(lock_usage, lock_options);
 	}
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 253133a..31c00f1 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -5,6 +5,7 @@
 #include "util/trace-event.h"
 #include "util/tool.h"
 #include "util/session.h"
+#include "util/data.h"
 
 #define MEM_OPERATION_LOAD	"load"
 #define MEM_OPERATION_STORE	"store"
@@ -119,10 +120,14 @@
 
 static int report_raw_events(struct perf_mem *mem)
 {
+	struct perf_data_file file = {
+		.path = input_name,
+		.mode = PERF_DATA_MODE_READ,
+	};
 	int err = -EINVAL;
 	int ret;
-	struct perf_session *session = perf_session__new(input_name, O_RDONLY,
-							 0, false, &mem->tool);
+	struct perf_session *session = perf_session__new(&file, false,
+							 &mem->tool);
 
 	if (session == NULL)
 		return -ENOMEM;
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index e8a66f9..89acc17 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -173,7 +173,7 @@
 	if  (str && !params.target) {
 		if (!strcmp(opt->long_name, "exec"))
 			params.uprobes = true;
-#ifdef DWARF_SUPPORT
+#ifdef HAVE_DWARF_SUPPORT
 		else if (!strcmp(opt->long_name, "module"))
 			params.uprobes = false;
 #endif
@@ -187,7 +187,7 @@
 	return ret;
 }
 
-#ifdef DWARF_SUPPORT
+#ifdef HAVE_DWARF_SUPPORT
 static int opt_show_lines(const struct option *opt __maybe_unused,
 			  const char *str, int unset __maybe_unused)
 {
@@ -257,7 +257,7 @@
 		"perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
 		"perf probe [<options>] --del '[GROUP:]EVENT' ...",
 		"perf probe --list",
-#ifdef DWARF_SUPPORT
+#ifdef HAVE_DWARF_SUPPORT
 		"perf probe [<options>] --line 'LINEDESC'",
 		"perf probe [<options>] --vars 'PROBEPOINT'",
 #endif
@@ -271,7 +271,7 @@
 	OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
 		opt_del_probe_event),
 	OPT_CALLBACK('a', "add", NULL,
-#ifdef DWARF_SUPPORT
+#ifdef HAVE_DWARF_SUPPORT
 		"[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
 		" [[NAME=]ARG ...]",
 #else
@@ -283,7 +283,7 @@
 		"\t\tFUNC:\tFunction name\n"
 		"\t\tOFF:\tOffset from function entry (in byte)\n"
 		"\t\t%return:\tPut the probe at function return\n"
-#ifdef DWARF_SUPPORT
+#ifdef HAVE_DWARF_SUPPORT
 		"\t\tSRC:\tSource code path\n"
 		"\t\tRL:\tRelative line number from function entry.\n"
 		"\t\tAL:\tAbsolute line number in file.\n"
@@ -296,7 +296,7 @@
 		opt_add_probe_event),
 	OPT_BOOLEAN('f', "force", &params.force_add, "forcibly add events"
 		    " with existing name"),
-#ifdef DWARF_SUPPORT
+#ifdef HAVE_DWARF_SUPPORT
 	OPT_CALLBACK('L', "line", NULL,
 		     "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]",
 		     "Show source code lines.", opt_show_lines),
@@ -408,7 +408,7 @@
 		return ret;
 	}
 
-#ifdef DWARF_SUPPORT
+#ifdef HAVE_DWARF_SUPPORT
 	if (params.show_lines && !params.uprobes) {
 		if (params.mod_events) {
 			pr_err("  Error: Don't use --line with"
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index a41ac415..15280b5 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -24,12 +24,13 @@
 #include "util/symbol.h"
 #include "util/cpumap.h"
 #include "util/thread_map.h"
+#include "util/data.h"
 
 #include <unistd.h>
 #include <sched.h>
 #include <sys/mman.h>
 
-#ifndef HAVE_ON_EXIT
+#ifndef HAVE_ON_EXIT_SUPPORT
 #ifndef ATEXIT_MAX
 #define ATEXIT_MAX 32
 #endif
@@ -65,31 +66,25 @@
 	struct perf_tool	tool;
 	struct perf_record_opts	opts;
 	u64			bytes_written;
-	const char		*output_name;
+	struct perf_data_file	file;
 	struct perf_evlist	*evlist;
 	struct perf_session	*session;
 	const char		*progname;
-	int			output;
-	unsigned int		page_size;
 	int			realtime_prio;
 	bool			no_buildid;
 	bool			no_buildid_cache;
 	long			samples;
-	off_t			post_processing_offset;
 };
 
-static void advance_output(struct perf_record *rec, size_t size)
-{
-	rec->bytes_written += size;
-}
-
 static int write_output(struct perf_record *rec, void *buf, size_t size)
 {
+	struct perf_data_file *file = &rec->file;
+
 	while (size) {
-		int ret = write(rec->output, buf, size);
+		int ret = write(file->fd, buf, size);
 
 		if (ret < 0) {
-			pr_err("failed to write\n");
+			pr_err("failed to write perf data, error: %m\n");
 			return -1;
 		}
 
@@ -119,7 +114,7 @@
 {
 	unsigned int head = perf_mmap__read_head(md);
 	unsigned int old = md->prev;
-	unsigned char *data = md->base + rec->page_size;
+	unsigned char *data = md->base + page_size;
 	unsigned long size;
 	void *buf;
 	int rc = 0;
@@ -234,10 +229,6 @@
 			       "or try again with a smaller value of -m/--mmap_pages.\n"
 			       "(current value: %d)\n", opts->mmap_pages);
 			rc = -errno;
-		} else if (!is_power_of_2(opts->mmap_pages) &&
-			   (opts->mmap_pages != UINT_MAX)) {
-			pr_err("--mmap_pages/-m value must be a power of two.");
-			rc = -EINVAL;
 		} else {
 			pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno));
 			rc = -errno;
@@ -253,31 +244,34 @@
 
 static int process_buildids(struct perf_record *rec)
 {
-	u64 size = lseek(rec->output, 0, SEEK_CUR);
+	struct perf_data_file *file  = &rec->file;
+	struct perf_session *session = rec->session;
+	u64 start = session->header.data_offset;
 
+	u64 size = lseek(file->fd, 0, SEEK_CUR);
 	if (size == 0)
 		return 0;
 
-	rec->session->fd = rec->output;
-	return __perf_session__process_events(rec->session, rec->post_processing_offset,
-					      size - rec->post_processing_offset,
+	return __perf_session__process_events(session, start,
+					      size - start,
 					      size, &build_id__mark_dso_hit_ops);
 }
 
 static void perf_record__exit(int status, void *arg)
 {
 	struct perf_record *rec = arg;
+	struct perf_data_file *file = &rec->file;
 
 	if (status != 0)
 		return;
 
-	if (!rec->opts.pipe_output) {
+	if (!file->is_pipe) {
 		rec->session->header.data_size += rec->bytes_written;
 
 		if (!rec->no_buildid)
 			process_buildids(rec);
 		perf_session__write_header(rec->session, rec->evlist,
-					   rec->output, true);
+					   file->fd, true);
 		perf_session__delete(rec->session);
 		perf_evlist__delete(rec->evlist);
 		symbol__exit();
@@ -343,70 +337,11 @@
 	return rc;
 }
 
-static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
+static void perf_record__init_features(struct perf_record *rec)
 {
-	struct stat st;
-	int flags;
-	int err, output, feat;
-	unsigned long waking = 0;
-	const bool forks = argc > 0;
-	struct machine *machine;
-	struct perf_tool *tool = &rec->tool;
-	struct perf_record_opts *opts = &rec->opts;
 	struct perf_evlist *evsel_list = rec->evlist;
-	const char *output_name = rec->output_name;
-	struct perf_session *session;
-	bool disabled = false;
-
-	rec->progname = argv[0];
-
-	rec->page_size = sysconf(_SC_PAGE_SIZE);
-
-	on_exit(perf_record__sig_exit, rec);
-	signal(SIGCHLD, sig_handler);
-	signal(SIGINT, sig_handler);
-	signal(SIGUSR1, sig_handler);
-	signal(SIGTERM, sig_handler);
-
-	if (!output_name) {
-		if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
-			opts->pipe_output = true;
-		else
-			rec->output_name = output_name = "perf.data";
-	}
-	if (output_name) {
-		if (!strcmp(output_name, "-"))
-			opts->pipe_output = true;
-		else if (!stat(output_name, &st) && st.st_size) {
-			char oldname[PATH_MAX];
-			snprintf(oldname, sizeof(oldname), "%s.old",
-				 output_name);
-			unlink(oldname);
-			rename(output_name, oldname);
-		}
-	}
-
-	flags = O_CREAT|O_RDWR|O_TRUNC;
-
-	if (opts->pipe_output)
-		output = STDOUT_FILENO;
-	else
-		output = open(output_name, flags, S_IRUSR | S_IWUSR);
-	if (output < 0) {
-		perror("failed to create output file");
-		return -1;
-	}
-
-	rec->output = output;
-
-	session = perf_session__new(output_name, O_WRONLY,
-				    true, false, NULL);
-	if (session == NULL) {
-		pr_err("Not enough memory for reading perf file header\n");
-		return -1;
-	}
-
-	rec->session = session;
+	struct perf_session *session = rec->session;
+	int feat;
 
 	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
 		perf_header__set_feat(&session->header, feat);
@@ -419,10 +354,42 @@
 
 	if (!rec->opts.branch_stack)
 		perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
+}
+
+static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
+{
+	int err;
+	unsigned long waking = 0;
+	const bool forks = argc > 0;
+	struct machine *machine;
+	struct perf_tool *tool = &rec->tool;
+	struct perf_record_opts *opts = &rec->opts;
+	struct perf_evlist *evsel_list = rec->evlist;
+	struct perf_data_file *file = &rec->file;
+	struct perf_session *session;
+	bool disabled = false;
+
+	rec->progname = argv[0];
+
+	on_exit(perf_record__sig_exit, rec);
+	signal(SIGCHLD, sig_handler);
+	signal(SIGINT, sig_handler);
+	signal(SIGUSR1, sig_handler);
+	signal(SIGTERM, sig_handler);
+
+	session = perf_session__new(file, false, NULL);
+	if (session == NULL) {
+		pr_err("Not enough memory for reading perf file header\n");
+		return -1;
+	}
+
+	rec->session = session;
+
+	perf_record__init_features(rec);
 
 	if (forks) {
 		err = perf_evlist__prepare_workload(evsel_list, &opts->target,
-						    argv, opts->pipe_output,
+						    argv, file->is_pipe,
 						    true);
 		if (err < 0) {
 			pr_err("Couldn't run the workload!\n");
@@ -443,13 +410,13 @@
 	 */
 	on_exit(perf_record__exit, rec);
 
-	if (opts->pipe_output) {
-		err = perf_header__write_pipe(output);
+	if (file->is_pipe) {
+		err = perf_header__write_pipe(file->fd);
 		if (err < 0)
 			goto out_delete_session;
 	} else {
 		err = perf_session__write_header(session, evsel_list,
-						 output, false);
+						 file->fd, false);
 		if (err < 0)
 			goto out_delete_session;
 	}
@@ -462,11 +429,9 @@
 		goto out_delete_session;
 	}
 
-	rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
-
 	machine = &session->machines.host;
 
-	if (opts->pipe_output) {
+	if (file->is_pipe) {
 		err = perf_event__synthesize_attrs(tool, session,
 						   process_synthesized_event);
 		if (err < 0) {
@@ -483,13 +448,13 @@
 			 * return this more properly and also
 			 * propagate errors that now are calling die()
 			 */
-			err = perf_event__synthesize_tracing_data(tool, output, evsel_list,
+			err = perf_event__synthesize_tracing_data(tool, file->fd, evsel_list,
 								  process_synthesized_event);
 			if (err <= 0) {
 				pr_err("Couldn't record tracing data.\n");
 				goto out_delete_session;
 			}
-			advance_output(rec, err);
+			rec->bytes_written += err;
 		}
 	}
 
@@ -590,7 +555,7 @@
 	fprintf(stderr,
 		"[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
 		(double)rec->bytes_written / 1024.0 / 1024.0,
-		output_name,
+		file->path,
 		rec->bytes_written / 24);
 
 	return 0;
@@ -618,6 +583,9 @@
 	BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
 	BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
 	BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
+	BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX),
+	BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX),
+	BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX),
 	BRANCH_END
 };
 
@@ -684,7 +652,7 @@
 	return ret;
 }
 
-#ifdef LIBUNWIND_SUPPORT
+#ifdef HAVE_LIBUNWIND_SUPPORT
 static int get_stack_size(char *str, unsigned long *_size)
 {
 	char *endptr;
@@ -710,23 +678,14 @@
 	       max_size, str);
 	return -1;
 }
-#endif /* LIBUNWIND_SUPPORT */
+#endif /* HAVE_LIBUNWIND_SUPPORT */
 
-int record_parse_callchain_opt(const struct option *opt,
-			       const char *arg, int unset)
+int record_parse_callchain(const char *arg, struct perf_record_opts *opts)
 {
-	struct perf_record_opts *opts = opt->value;
 	char *tok, *name, *saveptr = NULL;
 	char *buf;
 	int ret = -1;
 
-	/* --no-call-graph */
-	if (unset)
-		return 0;
-
-	/* We specified default option if none is provided. */
-	BUG_ON(!arg);
-
 	/* We need buffer that we know we can write to. */
 	buf = malloc(strlen(arg) + 1);
 	if (!buf)
@@ -748,7 +707,7 @@
 				       "needed for -g fp\n");
 			break;
 
-#ifdef LIBUNWIND_SUPPORT
+#ifdef HAVE_LIBUNWIND_SUPPORT
 		/* Dwarf style */
 		} else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
 			const unsigned long default_stack_dump_size = 8192;
@@ -764,13 +723,9 @@
 				ret = get_stack_size(tok, &size);
 				opts->stack_dump_size = size;
 			}
-
-			if (!ret)
-				pr_debug("callchain: stack dump size %d\n",
-					 opts->stack_dump_size);
-#endif /* LIBUNWIND_SUPPORT */
+#endif /* HAVE_LIBUNWIND_SUPPORT */
 		} else {
-			pr_err("callchain: Unknown -g option "
+			pr_err("callchain: Unknown --call-graph option "
 			       "value: %s\n", arg);
 			break;
 		}
@@ -778,13 +733,52 @@
 	} while (0);
 
 	free(buf);
+	return ret;
+}
 
+static void callchain_debug(struct perf_record_opts *opts)
+{
+	pr_debug("callchain: type %d\n", opts->call_graph);
+
+	if (opts->call_graph == CALLCHAIN_DWARF)
+		pr_debug("callchain: stack dump size %d\n",
+			 opts->stack_dump_size);
+}
+
+int record_parse_callchain_opt(const struct option *opt,
+			       const char *arg,
+			       int unset)
+{
+	struct perf_record_opts *opts = opt->value;
+	int ret;
+
+	/* --no-call-graph */
+	if (unset) {
+		opts->call_graph = CALLCHAIN_NONE;
+		pr_debug("callchain: disabled\n");
+		return 0;
+	}
+
+	ret = record_parse_callchain(arg, opts);
 	if (!ret)
-		pr_debug("callchain: type %d\n", opts->call_graph);
+		callchain_debug(opts);
 
 	return ret;
 }
 
+int record_callchain_opt(const struct option *opt,
+			 const char *arg __maybe_unused,
+			 int unset __maybe_unused)
+{
+	struct perf_record_opts *opts = opt->value;
+
+	if (opts->call_graph == CALLCHAIN_NONE)
+		opts->call_graph = CALLCHAIN_FP;
+
+	callchain_debug(opts);
+	return 0;
+}
+
 static const char * const record_usage[] = {
 	"perf record [<options>] [<command>]",
 	"perf record [<options>] -- <command> [<options>]",
@@ -813,12 +807,12 @@
 	},
 };
 
-#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
+#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: "
 
-#ifdef LIBUNWIND_SUPPORT
-const char record_callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
+#ifdef HAVE_LIBUNWIND_SUPPORT
+const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf";
 #else
-const char record_callchain_help[] = CALLCHAIN_HELP "[fp]";
+const char record_callchain_help[] = CALLCHAIN_HELP "fp";
 #endif
 
 /*
@@ -849,18 +843,22 @@
 	OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
 		    "list of cpus to monitor"),
 	OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
-	OPT_STRING('o', "output", &record.output_name, "file",
+	OPT_STRING('o', "output", &record.file.path, "file",
 		    "output file name"),
 	OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
 		    "child tasks do not inherit counters"),
 	OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
-	OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages,
-		     "number of mmap data pages"),
+	OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages",
+		     "number of mmap data pages",
+		     perf_evlist__parse_mmap_pages),
 	OPT_BOOLEAN(0, "group", &record.opts.group,
 		    "put the counters into a counter group"),
-	OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts,
-			     "mode[,dump_size]", record_callchain_help,
-			     &record_parse_callchain_opt, "fp"),
+	OPT_CALLBACK_NOOPT('g', NULL, &record.opts,
+			   NULL, "enables call-graph recording" ,
+			   &record_callchain_opt),
+	OPT_CALLBACK(0, "call-graph", &record.opts,
+		     "mode[,dump_size]", record_callchain_help,
+		     &record_parse_callchain_opt),
 	OPT_INCR('v', "verbose", &verbose,
 		    "be more verbose (show counter open errors, etc)"),
 	OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
@@ -891,6 +889,8 @@
 		     parse_branch_stack),
 	OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
 		    "sample by weight (on special events only)"),
+	OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
+		    "sample transaction flags (special events only)"),
 	OPT_END()
 };
 
@@ -960,20 +960,7 @@
 	if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
 		usage_with_options(record_usage, record_options);
 
-	if (rec->opts.user_interval != ULLONG_MAX)
-		rec->opts.default_interval = rec->opts.user_interval;
-	if (rec->opts.user_freq != UINT_MAX)
-		rec->opts.freq = rec->opts.user_freq;
-
-	/*
-	 * User specified count overrides default frequency.
-	 */
-	if (rec->opts.default_interval)
-		rec->opts.freq = 0;
-	else if (rec->opts.freq) {
-		rec->opts.default_interval = rec->opts.freq;
-	} else {
-		ui__error("frequency and count are zero, aborting\n");
+	if (perf_record_opts__config(&rec->opts)) {
 		err = -EINVAL;
 		goto out_free_fd;
 	}
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 72eae74..8cf8e66 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -33,8 +33,10 @@
 #include "util/thread.h"
 #include "util/sort.h"
 #include "util/hist.h"
+#include "util/data.h"
 #include "arch/common.h"
 
+#include <dlfcn.h>
 #include <linux/bitmap.h>
 
 struct perf_report {
@@ -47,6 +49,7 @@
 	bool			show_threads;
 	bool			inverted_callchain;
 	bool			mem_mode;
+	int			max_stack;
 	struct perf_read_values	show_threads_values;
 	const char		*pretty_printing_style;
 	const char		*cpu_list;
@@ -88,7 +91,8 @@
 	if ((sort__has_parent || symbol_conf.use_callchain) &&
 	    sample->callchain) {
 		err = machine__resolve_callchain(machine, evsel, al->thread,
-						 sample, &parent, al);
+						 sample, &parent, al,
+						 rep->max_stack);
 		if (err)
 			return err;
 	}
@@ -111,7 +115,8 @@
 	 * and this is indirectly achieved by passing period=weight here
 	 * and the he_stat__add_period() function.
 	 */
-	he = __hists__add_mem_entry(&evsel->hists, al, parent, mi, cost, cost);
+	he = __hists__add_entry(&evsel->hists, al, parent, NULL, mi,
+				cost, cost, 0);
 	if (!he)
 		return -ENOMEM;
 
@@ -179,7 +184,8 @@
 	if ((sort__has_parent || symbol_conf.use_callchain)
 	    && sample->callchain) {
 		err = machine__resolve_callchain(machine, evsel, al->thread,
-						 sample, &parent, al);
+						 sample, &parent, al,
+						 rep->max_stack);
 		if (err)
 			return err;
 	}
@@ -195,12 +201,16 @@
 
 		err = -ENOMEM;
 
+		/* overwrite the 'al' to branch-to info */
+		al->map = bi[i].to.map;
+		al->sym = bi[i].to.sym;
+		al->addr = bi[i].to.addr;
 		/*
 		 * The report shows the percentage of total branches captured
 		 * and not events sampled. Thus we use a pseudo period of 1.
 		 */
-		he = __hists__add_branch_entry(&evsel->hists, al, parent,
-				&bi[i], 1, 1);
+		he = __hists__add_entry(&evsel->hists, al, parent, &bi[i], NULL,
+					1, 1, 0);
 		if (he) {
 			struct annotation *notes;
 			bx = he->branch_info;
@@ -242,24 +252,28 @@
 	return err;
 }
 
-static int perf_evsel__add_hist_entry(struct perf_evsel *evsel,
+static int perf_evsel__add_hist_entry(struct perf_tool *tool,
+				      struct perf_evsel *evsel,
 				      struct addr_location *al,
 				      struct perf_sample *sample,
 				      struct machine *machine)
 {
+	struct perf_report *rep = container_of(tool, struct perf_report, tool);
 	struct symbol *parent = NULL;
 	int err = 0;
 	struct hist_entry *he;
 
 	if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
 		err = machine__resolve_callchain(machine, evsel, al->thread,
-						 sample, &parent, al);
+						 sample, &parent, al,
+						 rep->max_stack);
 		if (err)
 			return err;
 	}
 
-	he = __hists__add_entry(&evsel->hists, al, parent, sample->period,
-					sample->weight);
+	he = __hists__add_entry(&evsel->hists, al, parent, NULL, NULL,
+				sample->period, sample->weight,
+				sample->transaction);
 	if (he == NULL)
 		return -ENOMEM;
 
@@ -330,7 +344,8 @@
 		if (al.map != NULL)
 			al.map->dso->hit = 1;
 
-		ret = perf_evsel__add_hist_entry(evsel, &al, sample, machine);
+		ret = perf_evsel__add_hist_entry(tool, evsel, &al, sample,
+						 machine);
 		if (ret < 0)
 			pr_debug("problem incrementing symbol period, skipping event\n");
 	}
@@ -364,10 +379,11 @@
 /* For pipe mode, sample_type is not currently set */
 static int perf_report__setup_sample_type(struct perf_report *rep)
 {
-	struct perf_session *self = rep->session;
-	u64 sample_type = perf_evlist__combined_sample_type(self->evlist);
+	struct perf_session *session = rep->session;
+	u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
+	bool is_pipe = perf_data_file__is_pipe(session->file);
 
-	if (!self->fd_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
+	if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
 		if (sort__has_parent) {
 			ui__error("Selected --sort parent, but no "
 				    "callchain data. Did you call "
@@ -390,7 +406,7 @@
 	}
 
 	if (sort__mode == SORT_MODE__BRANCH) {
-		if (!self->fd_pipe &&
+		if (!is_pipe &&
 		    !(sample_type & PERF_SAMPLE_BRANCH_STACK)) {
 			ui__error("Selected -b but no branch data. "
 				  "Did you call perf record without -b?\n");
@@ -407,14 +423,14 @@
 }
 
 static size_t hists__fprintf_nr_sample_events(struct perf_report *rep,
-					      struct hists *self,
+					      struct hists *hists,
 					      const char *evname, FILE *fp)
 {
 	size_t ret;
 	char unit;
-	unsigned long nr_samples = self->stats.nr_events[PERF_RECORD_SAMPLE];
-	u64 nr_events = self->stats.total_period;
-	struct perf_evsel *evsel = hists_to_evsel(self);
+	unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
+	u64 nr_events = hists->stats.total_period;
+	struct perf_evsel *evsel = hists_to_evsel(hists);
 	char buf[512];
 	size_t size = sizeof(buf);
 
@@ -486,6 +502,8 @@
 	struct map *kernel_map;
 	struct kmap *kernel_kmap;
 	const char *help = "For a higher level overview, try: perf report --sort comm,dso";
+	struct ui_progress prog;
+	struct perf_data_file *file = session->file;
 
 	signal(SIGINT, sig_handler);
 
@@ -547,13 +565,19 @@
 	}
 
 	nr_samples = 0;
+	list_for_each_entry(pos, &session->evlist->entries, node)
+		nr_samples += pos->hists.nr_entries;
+
+	ui_progress__init(&prog, nr_samples, "Merging related events...");
+
+	nr_samples = 0;
 	list_for_each_entry(pos, &session->evlist->entries, node) {
 		struct hists *hists = &pos->hists;
 
 		if (pos->idx == 0)
 			hists->symbol_filter_str = rep->symbol_filter_str;
 
-		hists__collapse_resort(hists);
+		hists__collapse_resort(hists, &prog);
 		nr_samples += hists->stats.nr_events[PERF_RECORD_SAMPLE];
 
 		/* Non-group events are considered as leader */
@@ -565,12 +589,13 @@
 			hists__link(leader_hists, hists);
 		}
 	}
+	ui_progress__finish();
 
 	if (session_done())
 		return 0;
 
 	if (nr_samples == 0) {
-		ui__error("The %s file has no samples!\n", session->filename);
+		ui__error("The %s file has no samples!\n", file->path);
 		return 0;
 	}
 
@@ -591,8 +616,19 @@
 				ret = 0;
 
 		} else if (use_browser == 2) {
-			perf_evlist__gtk_browse_hists(session->evlist, help,
-						      NULL, rep->min_percent);
+			int (*hist_browser)(struct perf_evlist *,
+					    const char *,
+					    struct hist_browser_timer *,
+					    float min_pcnt);
+
+			hist_browser = dlsym(perf_gtk_handle,
+					     "perf_evlist__gtk_browse_hists");
+			if (hist_browser == NULL) {
+				ui__error("GTK browser not found!\n");
+				return ret;
+			}
+			hist_browser(session->evlist, help, NULL,
+				     rep->min_percent);
 		}
 	} else
 		perf_evlist__tty_browse_hists(session->evlist, rep, help);
@@ -757,6 +793,7 @@
 			.ordered_samples = true,
 			.ordering_requires_timestamps = true,
 		},
+		.max_stack		 = PERF_MAX_STACK_DEPTH,
 		.pretty_printing_style	 = "normal",
 	};
 	const struct option options[] = {
@@ -787,7 +824,7 @@
 		   "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline,"
 		   " dso_to, dso_from, symbol_to, symbol_from, mispredict,"
 		   " weight, local_weight, mem, symbol_daddr, dso_daddr, tlb, "
-		   "snoop, locked"),
+		   "snoop, locked, abort, in_tx, transaction"),
 	OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
 		    "Show sample percentage for different cpu modes"),
 	OPT_STRING('p', "parent", &parent_pattern, "regex",
@@ -797,6 +834,10 @@
 	OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order",
 		     "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address). "
 		     "Default: fractal,0.5,callee,function", &parse_callchain_opt, callchain_default_opt),
+	OPT_INTEGER(0, "max-stack", &report.max_stack,
+		    "Set the maximum stack depth when parsing the callchain, "
+		    "anything beyond the specified depth will be ignored. "
+		    "Default: " __stringify(PERF_MAX_STACK_DEPTH)),
 	OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
 		    "alias for inverted call graph"),
 	OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
@@ -845,6 +886,9 @@
 		     "Don't show entries under that percent", parse_percent_limit),
 	OPT_END()
 	};
+	struct perf_data_file file = {
+		.mode  = PERF_DATA_MODE_READ,
+	};
 
 	perf_config(perf_report_config, &report);
 
@@ -867,16 +911,11 @@
 			input_name = "perf.data";
 	}
 
-	if (strcmp(input_name, "-") != 0)
-		setup_browser(true);
-	else {
-		use_browser = 0;
-		perf_hpp__init();
-	}
+	file.path  = input_name;
+	file.force = report.force;
 
 repeat:
-	session = perf_session__new(input_name, O_RDONLY,
-				    report.force, false, &report.tool);
+	session = perf_session__new(&file, false, &report.tool);
 	if (session == NULL)
 		return -ENOMEM;
 
@@ -914,8 +953,22 @@
 			sort_order = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked";
 	}
 
-	if (setup_sorting() < 0)
-		usage_with_options(report_usage, options);
+	if (setup_sorting() < 0) {
+		parse_options_usage(report_usage, options, "s", 1);
+		goto error;
+	}
+
+	if (parent_pattern != default_parent_pattern) {
+		if (sort_dimension__add("parent") < 0)
+			goto error;
+	}
+
+	if (strcmp(input_name, "-") != 0)
+		setup_browser(true);
+	else {
+		use_browser = 0;
+		perf_hpp__init();
+	}
 
 	/*
 	 * Only in the TUI browser we are doing integrated annotation,
@@ -946,11 +999,6 @@
 	if (symbol__init() < 0)
 		goto error;
 
-	if (parent_pattern != default_parent_pattern) {
-		if (sort_dimension__add("parent") < 0)
-			goto error;
-	}
-
 	if (argc) {
 		/*
 		 * Special case: if there's an argument left then assume that
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index d8c51b2..0f3c6551 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -737,12 +737,12 @@
 
 	if (verbose) {
 		printf("fork event\n");
-		printf("... parent: %s/%d\n", parent->comm, parent->tid);
-		printf("...  child: %s/%d\n", child->comm, child->tid);
+		printf("... parent: %s/%d\n", thread__comm_str(parent), parent->tid);
+		printf("...  child: %s/%d\n", thread__comm_str(child), child->tid);
 	}
 
-	register_pid(sched, parent->tid, parent->comm);
-	register_pid(sched, child->tid, child->comm);
+	register_pid(sched, parent->tid, thread__comm_str(parent));
+	register_pid(sched, child->tid, thread__comm_str(child));
 	return 0;
 }
 
@@ -1077,7 +1077,7 @@
 	if (!atoms) {
 		if (thread_atoms_insert(sched, migrant))
 			return -1;
-		register_pid(sched, migrant->tid, migrant->comm);
+		register_pid(sched, migrant->tid, thread__comm_str(migrant));
 		atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid);
 		if (!atoms) {
 			pr_err("migration-event: Internal tree error");
@@ -1111,13 +1111,13 @@
 	/*
 	 * Ignore idle threads:
 	 */
-	if (!strcmp(work_list->thread->comm, "swapper"))
+	if (!strcmp(thread__comm_str(work_list->thread), "swapper"))
 		return;
 
 	sched->all_runtime += work_list->total_runtime;
 	sched->all_count   += work_list->nb_atoms;
 
-	ret = printf("  %s:%d ", work_list->thread->comm, work_list->thread->tid);
+	ret = printf("  %s:%d ", thread__comm_str(work_list->thread), work_list->thread->tid);
 
 	for (i = 0; i < 24 - ret; i++)
 		printf(" ");
@@ -1334,7 +1334,7 @@
 	printf("  %12.6f secs ", (double)timestamp/1e9);
 	if (new_shortname) {
 		printf("%s => %s:%d\n",
-			sched_in->shortname, sched_in->comm, sched_in->tid);
+		       sched_in->shortname, thread__comm_str(sched_in), sched_in->tid);
 	} else {
 		printf("\n");
 	}
@@ -1427,8 +1427,8 @@
 	evsel->hists.stats.total_period += sample->period;
 	hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
 
-	if (evsel->handler.func != NULL) {
-		tracepoint_handler f = evsel->handler.func;
+	if (evsel->handler != NULL) {
+		tracepoint_handler f = evsel->handler;
 		err = f(tool, evsel, sample, machine);
 	}
 
@@ -1446,8 +1446,12 @@
 		{ "sched:sched_migrate_task", process_sched_migrate_task_event, },
 	};
 	struct perf_session *session;
+	struct perf_data_file file = {
+		.path = input_name,
+		.mode = PERF_DATA_MODE_READ,
+	};
 
-	session = perf_session__new(input_name, O_RDONLY, 0, false, &sched->tool);
+	session = perf_session__new(&file, false, &sched->tool);
 	if (session == NULL) {
 		pr_debug("No Memory for session\n");
 		return -1;
@@ -1651,29 +1655,27 @@
 	return cmd_record(i, rec_argv, NULL);
 }
 
-static const char default_sort_order[] = "avg, max, switch, runtime";
-static struct perf_sched sched = {
-	.tool = {
-		.sample		 = perf_sched__process_tracepoint_sample,
-		.comm		 = perf_event__process_comm,
-		.lost		 = perf_event__process_lost,
-		.fork		 = perf_sched__process_fork_event,
-		.ordered_samples = true,
-	},
-	.cmp_pid	      = LIST_HEAD_INIT(sched.cmp_pid),
-	.sort_list	      = LIST_HEAD_INIT(sched.sort_list),
-	.start_work_mutex     = PTHREAD_MUTEX_INITIALIZER,
-	.work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER,
-	.curr_pid	      = { [0 ... MAX_CPUS - 1] = -1 },
-	.sort_order	      = default_sort_order,
-	.replay_repeat	      = 10,
-	.profile_cpu	      = -1,
-	.next_shortname1      = 'A',
-	.next_shortname2      = '0',
-};
-
 int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
 {
+	const char default_sort_order[] = "avg, max, switch, runtime";
+	struct perf_sched sched = {
+		.tool = {
+			.sample		 = perf_sched__process_tracepoint_sample,
+			.comm		 = perf_event__process_comm,
+			.lost		 = perf_event__process_lost,
+			.fork		 = perf_sched__process_fork_event,
+			.ordered_samples = true,
+		},
+		.cmp_pid	      = LIST_HEAD_INIT(sched.cmp_pid),
+		.sort_list	      = LIST_HEAD_INIT(sched.sort_list),
+		.start_work_mutex     = PTHREAD_MUTEX_INITIALIZER,
+		.work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER,
+		.sort_order	      = default_sort_order,
+		.replay_repeat	      = 10,
+		.profile_cpu	      = -1,
+		.next_shortname1      = 'A',
+		.next_shortname2      = '0',
+	};
 	const struct option latency_options[] = {
 	OPT_STRING('s', "sort", &sched.sort_order, "key[,key2...]",
 		   "sort by key(s): runtime, switch, avg, max"),
@@ -1729,6 +1731,10 @@
 		.switch_event	    = replay_switch_event,
 		.fork_event	    = replay_fork_event,
 	};
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(sched.curr_pid); i++)
+		sched.curr_pid[i] = -1;
 
 	argc = parse_options(argc, argv, sched_options, sched_usage,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 9c333ff..baf1798 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -15,6 +15,7 @@
 #include "util/evlist.h"
 #include "util/evsel.h"
 #include "util/sort.h"
+#include "util/data.h"
 #include <linux/bitmap.h>
 
 static char const		*script_name;
@@ -228,6 +229,24 @@
 	return 0;
 }
 
+static void set_print_ip_opts(struct perf_event_attr *attr)
+{
+	unsigned int type = attr->type;
+
+	output[type].print_ip_opts = 0;
+	if (PRINT_FIELD(IP))
+		output[type].print_ip_opts |= PRINT_IP_OPT_IP;
+
+	if (PRINT_FIELD(SYM))
+		output[type].print_ip_opts |= PRINT_IP_OPT_SYM;
+
+	if (PRINT_FIELD(DSO))
+		output[type].print_ip_opts |= PRINT_IP_OPT_DSO;
+
+	if (PRINT_FIELD(SYMOFFSET))
+		output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET;
+}
+
 /*
  * verify all user requested events exist and the samples
  * have the expected data
@@ -236,7 +255,6 @@
 {
 	int j;
 	struct perf_evsel *evsel;
-	struct perf_event_attr *attr;
 
 	for (j = 0; j < PERF_TYPE_MAX; ++j) {
 		evsel = perf_session__find_first_evtype(session, j);
@@ -259,20 +277,7 @@
 		if (evsel == NULL)
 			continue;
 
-		attr = &evsel->attr;
-
-		output[j].print_ip_opts = 0;
-		if (PRINT_FIELD(IP))
-			output[j].print_ip_opts |= PRINT_IP_OPT_IP;
-
-		if (PRINT_FIELD(SYM))
-			output[j].print_ip_opts |= PRINT_IP_OPT_SYM;
-
-		if (PRINT_FIELD(DSO))
-			output[j].print_ip_opts |= PRINT_IP_OPT_DSO;
-
-		if (PRINT_FIELD(SYMOFFSET))
-			output[j].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET;
+		set_print_ip_opts(&evsel->attr);
 	}
 
 	return 0;
@@ -290,11 +295,11 @@
 
 	if (PRINT_FIELD(COMM)) {
 		if (latency_format)
-			printf("%8.8s ", thread->comm);
+			printf("%8.8s ", thread__comm_str(thread));
 		else if (PRINT_FIELD(IP) && symbol_conf.use_callchain)
-			printf("%s ", thread->comm);
+			printf("%s ", thread__comm_str(thread));
 		else
-			printf("%16s ", thread->comm);
+			printf("%16s ", thread__comm_str(thread));
 	}
 
 	if (PRINT_FIELD(PID) && PRINT_FIELD(TID))
@@ -409,7 +414,9 @@
 	printf(" => ");
 
 	/* print branch_to information */
-	if (PRINT_FIELD(ADDR))
+	if (PRINT_FIELD(ADDR) ||
+	    ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
+	     !output[attr->type].user_set))
 		print_sample_addr(event, sample, machine, thread, attr);
 
 	printf("\n");
@@ -539,32 +546,51 @@
 	return 0;
 }
 
-static struct perf_tool perf_script = {
-	.sample		 = process_sample_event,
-	.mmap		 = perf_event__process_mmap,
-	.mmap2		 = perf_event__process_mmap2,
-	.comm		 = perf_event__process_comm,
-	.exit		 = perf_event__process_exit,
-	.fork		 = perf_event__process_fork,
-	.attr		 = perf_event__process_attr,
-	.tracing_data	 = perf_event__process_tracing_data,
-	.build_id	 = perf_event__process_build_id,
-	.ordered_samples = true,
-	.ordering_requires_timestamps = true,
+struct perf_script {
+	struct perf_tool	tool;
+	struct perf_session	*session;
 };
 
+static int process_attr(struct perf_tool *tool, union perf_event *event,
+			struct perf_evlist **pevlist)
+{
+	struct perf_script *scr = container_of(tool, struct perf_script, tool);
+	struct perf_evlist *evlist;
+	struct perf_evsel *evsel, *pos;
+	int err;
+
+	err = perf_event__process_attr(tool, event, pevlist);
+	if (err)
+		return err;
+
+	evlist = *pevlist;
+	evsel = perf_evlist__last(*pevlist);
+
+	if (evsel->attr.type >= PERF_TYPE_MAX)
+		return 0;
+
+	list_for_each_entry(pos, &evlist->entries, node) {
+		if (pos->attr.type == evsel->attr.type && pos != evsel)
+			return 0;
+	}
+
+	set_print_ip_opts(&evsel->attr);
+
+	return perf_evsel__check_attr(evsel, scr->session);
+}
+
 static void sig_handler(int sig __maybe_unused)
 {
 	session_done = 1;
 }
 
-static int __cmd_script(struct perf_session *session)
+static int __cmd_script(struct perf_script *script)
 {
 	int ret;
 
 	signal(SIGINT, sig_handler);
 
-	ret = perf_session__process_events(session, &perf_script);
+	ret = perf_session__process_events(script->session, &script->tool);
 
 	if (debug_mode)
 		pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
@@ -1113,10 +1139,14 @@
 	char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN];
 	DIR *scripts_dir, *lang_dir;
 	struct perf_session *session;
+	struct perf_data_file file = {
+		.path = input_name,
+		.mode = PERF_DATA_MODE_READ,
+	};
 	char *temp;
 	int i = 0;
 
-	session = perf_session__new(input_name, O_RDONLY, 0, false, NULL);
+	session = perf_session__new(&file, false, NULL);
 	if (!session)
 		return -1;
 
@@ -1266,6 +1296,21 @@
 	char *script_path = NULL;
 	const char **__argv;
 	int i, j, err;
+	struct perf_script script = {
+		.tool = {
+			.sample		 = process_sample_event,
+			.mmap		 = perf_event__process_mmap,
+			.mmap2		 = perf_event__process_mmap2,
+			.comm		 = perf_event__process_comm,
+			.exit		 = perf_event__process_exit,
+			.fork		 = perf_event__process_fork,
+			.attr		 = process_attr,
+			.tracing_data	 = perf_event__process_tracing_data,
+			.build_id	 = perf_event__process_build_id,
+			.ordered_samples = true,
+			.ordering_requires_timestamps = true,
+		},
+	};
 	const struct option options[] = {
 	OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
 		    "dump raw trace in ASCII"),
@@ -1317,12 +1362,17 @@
 		"perf script [<options>] <top-script> [script-args]",
 		NULL
 	};
+	struct perf_data_file file = {
+		.mode = PERF_DATA_MODE_READ,
+	};
 
 	setup_scripting();
 
 	argc = parse_options(argc, argv, options, script_usage,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
 
+	file.path = input_name;
+
 	if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
 		rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
 		if (!rec_script_path)
@@ -1486,11 +1536,12 @@
 	if (!script_name)
 		setup_pager();
 
-	session = perf_session__new(input_name, O_RDONLY, 0, false,
-				    &perf_script);
+	session = perf_session__new(&file, false, &script.tool);
 	if (session == NULL)
 		return -ENOMEM;
 
+	script.session = session;
+
 	if (cpu_list) {
 		if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap))
 			return -1;
@@ -1514,7 +1565,7 @@
 			return -1;
 		}
 
-		input = open(session->filename, O_RDONLY);	/* input_name */
+		input = open(file.path, O_RDONLY);	/* input_name */
 		if (input < 0) {
 			perror("failed to open file");
 			return -1;
@@ -1554,7 +1605,7 @@
 	if (err < 0)
 		goto out;
 
-	err = __cmd_script(session);
+	err = __cmd_script(&script);
 
 	perf_session__delete(session);
 	cleanup_scripting();
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f686d5f..0fc1c94 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -46,6 +46,7 @@
 #include "util/util.h"
 #include "util/parse-options.h"
 #include "util/parse-events.h"
+#include "util/pmu.h"
 #include "util/event.h"
 #include "util/evlist.h"
 #include "util/evsel.h"
@@ -70,6 +71,41 @@
 static void print_counter(struct perf_evsel *counter, char *prefix);
 static void print_aggr(char *prefix);
 
+/* Default events used for perf stat -T */
+static const char * const transaction_attrs[] = {
+	"task-clock",
+	"{"
+	"instructions,"
+	"cycles,"
+	"cpu/cycles-t/,"
+	"cpu/tx-start/,"
+	"cpu/el-start/,"
+	"cpu/cycles-ct/"
+	"}"
+};
+
+/* More limited version when the CPU does not have all events. */
+static const char * const transaction_limited_attrs[] = {
+	"task-clock",
+	"{"
+	"instructions,"
+	"cycles,"
+	"cpu/cycles-t/,"
+	"cpu/tx-start/"
+	"}"
+};
+
+/* must match transaction_attrs and the beginning limited_attrs */
+enum {
+	T_TASK_CLOCK,
+	T_INSTRUCTIONS,
+	T_CYCLES,
+	T_CYCLES_IN_TX,
+	T_TRANSACTION_START,
+	T_ELISION_START,
+	T_CYCLES_IN_TX_CP,
+};
+
 static struct perf_evlist	*evsel_list;
 
 static struct perf_target	target = {
@@ -90,6 +126,7 @@
 static volatile pid_t		child_pid			= -1;
 static bool			null_run			=  false;
 static int			detailed_run			=  0;
+static bool			transaction_run;
 static bool			big_num				=  true;
 static int			big_num_opt			=  -1;
 static const char		*csv_sep			= NULL;
@@ -214,7 +251,10 @@
 static struct stats runtime_ll_cache_stats[MAX_NR_CPUS];
 static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS];
 static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS];
+static struct stats runtime_cycles_in_tx_stats[MAX_NR_CPUS];
 static struct stats walltime_nsecs_stats;
+static struct stats runtime_transaction_stats[MAX_NR_CPUS];
+static struct stats runtime_elision_stats[MAX_NR_CPUS];
 
 static void perf_stat__reset_stats(struct perf_evlist *evlist)
 {
@@ -236,6 +276,11 @@
 	memset(runtime_ll_cache_stats, 0, sizeof(runtime_ll_cache_stats));
 	memset(runtime_itlb_cache_stats, 0, sizeof(runtime_itlb_cache_stats));
 	memset(runtime_dtlb_cache_stats, 0, sizeof(runtime_dtlb_cache_stats));
+	memset(runtime_cycles_in_tx_stats, 0,
+			sizeof(runtime_cycles_in_tx_stats));
+	memset(runtime_transaction_stats, 0,
+		sizeof(runtime_transaction_stats));
+	memset(runtime_elision_stats, 0, sizeof(runtime_elision_stats));
 	memset(&walltime_nsecs_stats, 0, sizeof(walltime_nsecs_stats));
 }
 
@@ -274,6 +319,29 @@
 	return 0;
 }
 
+static struct perf_evsel *nth_evsel(int n)
+{
+	static struct perf_evsel **array;
+	static int array_len;
+	struct perf_evsel *ev;
+	int j;
+
+	/* Assumes this only called when evsel_list does not change anymore. */
+	if (!array) {
+		list_for_each_entry(ev, &evsel_list->entries, node)
+			array_len++;
+		array = malloc(array_len * sizeof(void *));
+		if (!array)
+			exit(ENOMEM);
+		j = 0;
+		list_for_each_entry(ev, &evsel_list->entries, node)
+			array[j++] = ev;
+	}
+	if (n < array_len)
+		return array[n];
+	return NULL;
+}
+
 /*
  * Update various tracking values we maintain to print
  * more semantic information such as miss/hit ratios,
@@ -285,6 +353,15 @@
 		update_stats(&runtime_nsecs_stats[0], count[0]);
 	else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
 		update_stats(&runtime_cycles_stats[0], count[0]);
+	else if (transaction_run &&
+		 perf_evsel__cmp(counter, nth_evsel(T_CYCLES_IN_TX)))
+		update_stats(&runtime_cycles_in_tx_stats[0], count[0]);
+	else if (transaction_run &&
+		 perf_evsel__cmp(counter, nth_evsel(T_TRANSACTION_START)))
+		update_stats(&runtime_transaction_stats[0], count[0]);
+	else if (transaction_run &&
+		 perf_evsel__cmp(counter, nth_evsel(T_ELISION_START)))
+		update_stats(&runtime_elision_stats[0], count[0]);
 	else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND))
 		update_stats(&runtime_stalled_cycles_front_stats[0], count[0]);
 	else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND))
@@ -457,6 +534,7 @@
 			perror("failed to prepare workload");
 			return -1;
 		}
+		child_pid = evsel_list->workload.pid;
 	}
 
 	if (group)
@@ -628,10 +706,13 @@
 {
 	double msecs = avg / 1e6;
 	const char *fmt = csv_output ? "%.6f%s%s" : "%18.6f%s%-25s";
+	char name[25];
 
 	aggr_printout(evsel, cpu, nr);
 
-	fprintf(output, fmt, msecs, csv_sep, perf_evsel__name(evsel));
+	scnprintf(name, sizeof(name), "%s%s",
+		  perf_evsel__name(evsel), csv_output ? "" : " (msec)");
+	fprintf(output, fmt, msecs, csv_sep, name);
 
 	if (evsel->cgrp)
 		fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
@@ -827,7 +908,7 @@
 
 static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
 {
-	double total, ratio = 0.0;
+	double total, ratio = 0.0, total2;
 	const char *fmt;
 
 	if (csv_output)
@@ -852,11 +933,10 @@
 
 	if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
 		total = avg_stats(&runtime_cycles_stats[cpu]);
-		if (total)
+		if (total) {
 			ratio = avg / total;
-
-		fprintf(output, " #   %5.2f  insns per cycle        ", ratio);
-
+			fprintf(output, " #   %5.2f  insns per cycle        ", ratio);
+		}
 		total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]);
 		total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu]));
 
@@ -919,10 +999,47 @@
 	} else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) {
 		total = avg_stats(&runtime_nsecs_stats[cpu]);
 
+		if (total) {
+			ratio = avg / total;
+			fprintf(output, " # %8.3f GHz                    ", ratio);
+		}
+	} else if (transaction_run &&
+		   perf_evsel__cmp(evsel, nth_evsel(T_CYCLES_IN_TX))) {
+		total = avg_stats(&runtime_cycles_stats[cpu]);
 		if (total)
-			ratio = 1.0 * avg / total;
+			fprintf(output,
+				" #   %5.2f%% transactional cycles   ",
+				100.0 * (avg / total));
+	} else if (transaction_run &&
+		   perf_evsel__cmp(evsel, nth_evsel(T_CYCLES_IN_TX_CP))) {
+		total = avg_stats(&runtime_cycles_stats[cpu]);
+		total2 = avg_stats(&runtime_cycles_in_tx_stats[cpu]);
+		if (total2 < avg)
+			total2 = avg;
+		if (total)
+			fprintf(output,
+				" #   %5.2f%% aborted cycles         ",
+				100.0 * ((total2-avg) / total));
+	} else if (transaction_run &&
+		   perf_evsel__cmp(evsel, nth_evsel(T_TRANSACTION_START)) &&
+		   avg > 0 &&
+		   runtime_cycles_in_tx_stats[cpu].n != 0) {
+		total = avg_stats(&runtime_cycles_in_tx_stats[cpu]);
 
-		fprintf(output, " # %8.3f GHz                    ", ratio);
+		if (total)
+			ratio = total / avg;
+
+		fprintf(output, " # %8.0f cycles / transaction   ", ratio);
+	} else if (transaction_run &&
+		   perf_evsel__cmp(evsel, nth_evsel(T_ELISION_START)) &&
+		   avg > 0 &&
+		   runtime_cycles_in_tx_stats[cpu].n != 0) {
+		total = avg_stats(&runtime_cycles_in_tx_stats[cpu]);
+
+		if (total)
+			ratio = total / avg;
+
+		fprintf(output, " # %8.0f cycles / elision       ", ratio);
 	} else if (runtime_nsecs_stats[cpu].n != 0) {
 		char unit = 'M';
 
@@ -1115,7 +1232,11 @@
 	if (!csv_output) {
 		fprintf(output, "\n");
 		fprintf(output, " Performance counter stats for ");
-		if (!perf_target__has_task(&target)) {
+		if (target.system_wide)
+			fprintf(output, "\'system wide");
+		else if (target.cpu_list)
+			fprintf(output, "\'CPU(s) %s", target.cpu_list);
+		else if (!perf_target__has_task(&target)) {
 			fprintf(output, "\'%s", argv[0]);
 			for (i = 1; i < argc; i++)
 				fprintf(output, " %s", argv[i]);
@@ -1236,6 +1357,16 @@
 	return 0;
 }
 
+static int setup_events(const char * const *attrs, unsigned len)
+{
+	unsigned i;
+
+	for (i = 0; i < len; i++) {
+		if (parse_events(evsel_list, attrs[i]))
+			return -1;
+	}
+	return 0;
+}
 
 /*
  * Add default attributes, if there were no attributes specified or
@@ -1354,6 +1485,22 @@
 	if (null_run)
 		return 0;
 
+	if (transaction_run) {
+		int err;
+		if (pmu_have_event("cpu", "cycles-ct") &&
+		    pmu_have_event("cpu", "el-start"))
+			err = setup_events(transaction_attrs,
+					ARRAY_SIZE(transaction_attrs));
+		else
+			err = setup_events(transaction_limited_attrs,
+				 ARRAY_SIZE(transaction_limited_attrs));
+		if (err < 0) {
+			fprintf(stderr, "Cannot set up transaction events\n");
+			return -1;
+		}
+		return 0;
+	}
+
 	if (!evsel_list->nr_entries) {
 		if (perf_evlist__add_default_attrs(evsel_list, default_attrs) < 0)
 			return -1;
@@ -1388,6 +1535,8 @@
 	int output_fd = 0;
 	const char *output_name	= NULL;
 	const struct option options[] = {
+	OPT_BOOLEAN('T', "transaction", &transaction_run,
+		    "hardware transaction statistics"),
 	OPT_CALLBACK('e', "event", &evsel_list, "event",
 		     "event selector. use 'perf list' to list available events",
 		     parse_events_option),
@@ -1447,7 +1596,7 @@
 		"perf stat [<options>] [<command>]",
 		NULL
 	};
-	int status = -ENOMEM, run_idx;
+	int status = -EINVAL, run_idx;
 	const char *mode;
 
 	setlocale(LC_ALL, "");
@@ -1465,12 +1614,15 @@
 
 	if (output_name && output_fd) {
 		fprintf(stderr, "cannot use both --output and --log-fd\n");
-		usage_with_options(stat_usage, options);
+		parse_options_usage(stat_usage, options, "o", 1);
+		parse_options_usage(NULL, options, "log-fd", 0);
+		goto out;
 	}
 
 	if (output_fd < 0) {
 		fprintf(stderr, "argument to --log-fd must be a > 0\n");
-		usage_with_options(stat_usage, options);
+		parse_options_usage(stat_usage, options, "log-fd", 0);
+		goto out;
 	}
 
 	if (!output) {
@@ -1507,16 +1659,21 @@
 		/* User explicitly passed -B? */
 		if (big_num_opt == 1) {
 			fprintf(stderr, "-B option not supported with -x\n");
-			usage_with_options(stat_usage, options);
+			parse_options_usage(stat_usage, options, "B", 1);
+			parse_options_usage(NULL, options, "x", 1);
+			goto out;
 		} else /* Nope, so disable big number formatting */
 			big_num = false;
 	} else if (big_num_opt == 0) /* User passed --no-big-num */
 		big_num = false;
 
-	if (!argc && !perf_target__has_task(&target))
+	if (!argc && perf_target__none(&target))
 		usage_with_options(stat_usage, options);
+
 	if (run_count < 0) {
-		usage_with_options(stat_usage, options);
+		pr_err("Run count must be a positive number\n");
+		parse_options_usage(stat_usage, options, "r", 1);
+		goto out;
 	} else if (run_count == 0) {
 		forever = true;
 		run_count = 1;
@@ -1528,8 +1685,10 @@
 		fprintf(stderr, "both cgroup and no-aggregation "
 			"modes only available in system-wide mode\n");
 
-		usage_with_options(stat_usage, options);
-		return -1;
+		parse_options_usage(stat_usage, options, "G", 1);
+		parse_options_usage(NULL, options, "A", 1);
+		parse_options_usage(NULL, options, "a", 1);
+		goto out;
 	}
 
 	if (add_default_attributes())
@@ -1538,25 +1697,28 @@
 	perf_target__validate(&target);
 
 	if (perf_evlist__create_maps(evsel_list, &target) < 0) {
-		if (perf_target__has_task(&target))
+		if (perf_target__has_task(&target)) {
 			pr_err("Problems finding threads of monitor\n");
-		if (perf_target__has_cpu(&target))
+			parse_options_usage(stat_usage, options, "p", 1);
+			parse_options_usage(NULL, options, "t", 1);
+		} else if (perf_target__has_cpu(&target)) {
 			perror("failed to parse CPUs map");
-
-		usage_with_options(stat_usage, options);
-		return -1;
+			parse_options_usage(stat_usage, options, "C", 1);
+			parse_options_usage(NULL, options, "a", 1);
+		}
+		goto out;
 	}
 	if (interval && interval < 100) {
 		pr_err("print interval must be >= 100ms\n");
-		usage_with_options(stat_usage, options);
-		return -1;
+		parse_options_usage(stat_usage, options, "I", 1);
+		goto out_free_maps;
 	}
 
 	if (perf_evlist__alloc_stats(evsel_list, interval))
 		goto out_free_maps;
 
 	if (perf_stat_init_aggr_mode())
-		goto out;
+		goto out_free_maps;
 
 	/*
 	 * We dont want to block the signals - that would cause
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index c2e0231..41c9bde2 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -36,6 +36,7 @@
 #include "util/session.h"
 #include "util/svghelper.h"
 #include "util/tool.h"
+#include "util/data.h"
 
 #define SUPPORT_OLD_POWER_EVENTS 1
 #define PWR_EVENT_EXIT -1
@@ -482,8 +483,8 @@
 	if (sample->cpu > numcpus)
 		numcpus = sample->cpu;
 
-	if (evsel->handler.func != NULL) {
-		tracepoint_handler f = evsel->handler.func;
+	if (evsel->handler != NULL) {
+		tracepoint_handler f = evsel->handler;
 		return f(evsel, sample);
 	}
 
@@ -990,8 +991,13 @@
 		{ "power:power_frequency",	process_sample_power_frequency },
 #endif
 	};
-	struct perf_session *session = perf_session__new(input_name, O_RDONLY,
-							 0, false, &perf_timechart);
+	struct perf_data_file file = {
+		.path = input_name,
+		.mode = PERF_DATA_MODE_READ,
+	};
+
+	struct perf_session *session = perf_session__new(&file, false,
+							 &perf_timechart);
 	int ret = -EINVAL;
 
 	if (session == NULL)
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 2122141..9acca88 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -246,10 +246,10 @@
 	struct hist_entry *he;
 
 	pthread_mutex_lock(&evsel->hists.lock);
-	he = __hists__add_entry(&evsel->hists, al, NULL, sample->period,
-				sample->weight);
+	he = __hists__add_entry(&evsel->hists, al, NULL, NULL, NULL,
+				sample->period, sample->weight,
+				sample->transaction);
 	pthread_mutex_unlock(&evsel->hists.lock);
-
 	if (he == NULL)
 		return NULL;
 
@@ -287,7 +287,7 @@
 		return;
 	}
 
-	hists__collapse_resort(&top->sym_evsel->hists);
+	hists__collapse_resort(&top->sym_evsel->hists, NULL);
 	hists__output_resort(&top->sym_evsel->hists);
 	hists__decay_entries(&top->sym_evsel->hists,
 			     top->hide_user_symbols,
@@ -553,7 +553,7 @@
 	if (t->evlist->selected != NULL)
 		t->sym_evsel = t->evlist->selected;
 
-	hists__collapse_resort(&t->sym_evsel->hists);
+	hists__collapse_resort(&t->sym_evsel->hists, NULL);
 	hists__output_resort(&t->sym_evsel->hists);
 	hists__decay_entries(&t->sym_evsel->hists,
 			     t->hide_user_symbols,
@@ -771,7 +771,8 @@
 		    sample->callchain) {
 			err = machine__resolve_callchain(machine, evsel,
 							 al.thread, sample,
-							 &parent, &al);
+							 &parent, &al,
+							 top->max_stack);
 			if (err)
 				return;
 		}
@@ -810,7 +811,7 @@
 		ret = perf_evlist__parse_sample(top->evlist, event, &sample);
 		if (ret) {
 			pr_err("Can't parse sample, err = %d\n", ret);
-			continue;
+			goto next_event;
 		}
 
 		evsel = perf_evlist__id2evsel(session->evlist, sample.id);
@@ -825,13 +826,13 @@
 		case PERF_RECORD_MISC_USER:
 			++top->us_samples;
 			if (top->hide_user_symbols)
-				continue;
+				goto next_event;
 			machine = &session->machines.host;
 			break;
 		case PERF_RECORD_MISC_KERNEL:
 			++top->kernel_samples;
 			if (top->hide_kernel_symbols)
-				continue;
+				goto next_event;
 			machine = &session->machines.host;
 			break;
 		case PERF_RECORD_MISC_GUEST_KERNEL:
@@ -847,7 +848,7 @@
 			 */
 			/* Fall thru */
 		default:
-			continue;
+			goto next_event;
 		}
 
 
@@ -856,9 +857,11 @@
 						   &sample, machine);
 		} else if (event->header.type < PERF_RECORD_MAX) {
 			hists__inc_nr_events(&evsel->hists, event->header.type);
-			machine__process_event(machine, event);
+			machine__process_event(machine, event, &sample);
 		} else
 			++session->stats.nr_unknown_events;
+next_event:
+		perf_evlist__mmap_consume(top->evlist, idx);
 	}
 }
 
@@ -930,11 +933,8 @@
 	struct perf_record_opts *opts = &top->record_opts;
 	pthread_t thread;
 	int ret;
-	/*
-	 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
-	 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
-	 */
-	top->session = perf_session__new(NULL, O_WRONLY, false, false, NULL);
+
+	top->session = perf_session__new(NULL, false, NULL);
 	if (top->session == NULL)
 		return -ENOMEM;
 
@@ -1016,16 +1016,16 @@
 }
 
 static int
+callchain_opt(const struct option *opt, const char *arg, int unset)
+{
+	symbol_conf.use_callchain = true;
+	return record_callchain_opt(opt, arg, unset);
+}
+
+static int
 parse_callchain_opt(const struct option *opt, const char *arg, int unset)
 {
-	/*
-	 * --no-call-graph
-	 */
-	if (unset)
-		return 0;
-
 	symbol_conf.use_callchain = true;
-
 	return record_parse_callchain_opt(opt, arg, unset);
 }
 
@@ -1041,7 +1041,7 @@
 
 int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
 {
-	int status;
+	int status = -1;
 	char errbuf[BUFSIZ];
 	struct perf_top top = {
 		.count_filter	     = 5,
@@ -1051,10 +1051,11 @@
 			.user_freq	= UINT_MAX,
 			.user_interval	= ULLONG_MAX,
 			.freq		= 4000, /* 4 KHz */
-			.target		     = {
+			.target		= {
 				.uses_mmap   = true,
 			},
 		},
+		.max_stack	     = PERF_MAX_STACK_DEPTH,
 		.sym_pcnt_filter     = 5,
 	};
 	struct perf_record_opts *opts = &top.record_opts;
@@ -1074,10 +1075,13 @@
 		    "list of cpus to monitor"),
 	OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
 		   "file", "vmlinux pathname"),
+	OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux,
+		    "don't load vmlinux even if found"),
 	OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols,
 		    "hide kernel symbols"),
-	OPT_UINTEGER('m', "mmap-pages", &opts->mmap_pages,
-		     "number of mmap data pages"),
+	OPT_CALLBACK('m', "mmap-pages", &opts->mmap_pages, "pages",
+		     "number of mmap data pages",
+		     perf_evlist__parse_mmap_pages),
 	OPT_INTEGER('r', "realtime", &top.realtime_prio,
 		    "collect data with this RT SCHED_FIFO priority"),
 	OPT_INTEGER('d', "delay", &top.delay_secs,
@@ -1103,12 +1107,19 @@
 	OPT_INCR('v', "verbose", &verbose,
 		    "be more verbose (show counter open errors, etc)"),
 	OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
-		   "sort by key(s): pid, comm, dso, symbol, parent, weight, local_weight"),
+		   "sort by key(s): pid, comm, dso, symbol, parent, weight, local_weight,"
+		   " abort, in_tx, transaction"),
 	OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
 		    "Show a column with the number of samples"),
-	OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts,
-			     "mode[,dump_size]", record_callchain_help,
-			     &parse_callchain_opt, "fp"),
+	OPT_CALLBACK_NOOPT('G', NULL, &top.record_opts,
+			   NULL, "enables call-graph recording",
+			   &callchain_opt),
+	OPT_CALLBACK(0, "call-graph", &top.record_opts,
+		     "mode[,dump_size]", record_callchain_help,
+		     &parse_callchain_opt),
+	OPT_INTEGER(0, "max-stack", &top.max_stack,
+		    "Set the maximum stack depth when parsing the callchain. "
+		    "Default: " __stringify(PERF_MAX_STACK_DEPTH)),
 	OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
 		   "ignore callees of these functions in call graphs",
 		   report_parse_ignore_callees_opt),
@@ -1149,8 +1160,10 @@
 	if (sort_order == default_sort_order)
 		sort_order = "dso,symbol";
 
-	if (setup_sorting() < 0)
-		usage_with_options(top_usage, options);
+	if (setup_sorting() < 0) {
+		parse_options_usage(top_usage, options, "s", 1);
+		goto out_delete_evlist;
+	}
 
 	/* display thread wants entries to be collapsed in a different tree */
 	sort__need_collapse = 1;
@@ -1196,20 +1209,7 @@
 	if (top.delay_secs < 1)
 		top.delay_secs = 1;
 
-	if (opts->user_interval != ULLONG_MAX)
-		opts->default_interval = opts->user_interval;
-	if (opts->user_freq != UINT_MAX)
-		opts->freq = opts->user_freq;
-
-	/*
-	 * User specified count overrides default frequency.
-	 */
-	if (opts->default_interval)
-		opts->freq = 0;
-	else if (opts->freq) {
-		opts->default_interval = opts->freq;
-	} else {
-		ui__error("frequency and count are zero, aborting\n");
+	if (perf_record_opts__config(opts)) {
 		status = -EINVAL;
 		goto out_delete_maps;
 	}
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 71aa3e3..329b783 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -10,9 +10,11 @@
 #include "util/strlist.h"
 #include "util/intlist.h"
 #include "util/thread_map.h"
+#include "util/stat.h"
 
 #include <libaudit.h>
 #include <stdlib.h>
+#include <sys/eventfd.h>
 #include <sys/mman.h>
 #include <linux/futex.h>
 
@@ -33,49 +35,279 @@
 # define MADV_UNMERGEABLE	13
 #endif
 
-static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
-					 unsigned long arg,
-					 u8 arg_idx __maybe_unused,
-					 u8 *arg_mask __maybe_unused)
+struct tp_field {
+	int offset;
+	union {
+		u64 (*integer)(struct tp_field *field, struct perf_sample *sample);
+		void *(*pointer)(struct tp_field *field, struct perf_sample *sample);
+	};
+};
+
+#define TP_UINT_FIELD(bits) \
+static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
+{ \
+	return *(u##bits *)(sample->raw_data + field->offset); \
+}
+
+TP_UINT_FIELD(8);
+TP_UINT_FIELD(16);
+TP_UINT_FIELD(32);
+TP_UINT_FIELD(64);
+
+#define TP_UINT_FIELD__SWAPPED(bits) \
+static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
+{ \
+	u##bits value = *(u##bits *)(sample->raw_data + field->offset); \
+	return bswap_##bits(value);\
+}
+
+TP_UINT_FIELD__SWAPPED(16);
+TP_UINT_FIELD__SWAPPED(32);
+TP_UINT_FIELD__SWAPPED(64);
+
+static int tp_field__init_uint(struct tp_field *field,
+			       struct format_field *format_field,
+			       bool needs_swap)
 {
-	return scnprintf(bf, size, "%#lx", arg);
+	field->offset = format_field->offset;
+
+	switch (format_field->size) {
+	case 1:
+		field->integer = tp_field__u8;
+		break;
+	case 2:
+		field->integer = needs_swap ? tp_field__swapped_u16 : tp_field__u16;
+		break;
+	case 4:
+		field->integer = needs_swap ? tp_field__swapped_u32 : tp_field__u32;
+		break;
+	case 8:
+		field->integer = needs_swap ? tp_field__swapped_u64 : tp_field__u64;
+		break;
+	default:
+		return -1;
+	}
+
+	return 0;
+}
+
+static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
+{
+	return sample->raw_data + field->offset;
+}
+
+static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
+{
+	field->offset = format_field->offset;
+	field->pointer = tp_field__ptr;
+	return 0;
+}
+
+struct syscall_tp {
+	struct tp_field id;
+	union {
+		struct tp_field args, ret;
+	};
+};
+
+static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
+					  struct tp_field *field,
+					  const char *name)
+{
+	struct format_field *format_field = perf_evsel__field(evsel, name);
+
+	if (format_field == NULL)
+		return -1;
+
+	return tp_field__init_uint(field, format_field, evsel->needs_swap);
+}
+
+#define perf_evsel__init_sc_tp_uint_field(evsel, name) \
+	({ struct syscall_tp *sc = evsel->priv;\
+	   perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); })
+
+static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
+					 struct tp_field *field,
+					 const char *name)
+{
+	struct format_field *format_field = perf_evsel__field(evsel, name);
+
+	if (format_field == NULL)
+		return -1;
+
+	return tp_field__init_ptr(field, format_field);
+}
+
+#define perf_evsel__init_sc_tp_ptr_field(evsel, name) \
+	({ struct syscall_tp *sc = evsel->priv;\
+	   perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); })
+
+static void perf_evsel__delete_priv(struct perf_evsel *evsel)
+{
+	free(evsel->priv);
+	evsel->priv = NULL;
+	perf_evsel__delete(evsel);
+}
+
+static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction,
+						    void *handler, int idx)
+{
+	struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction, idx);
+
+	if (evsel) {
+		evsel->priv = malloc(sizeof(struct syscall_tp));
+
+		if (evsel->priv == NULL)
+			goto out_delete;
+
+		if (perf_evsel__init_sc_tp_uint_field(evsel, id))
+			goto out_delete;
+
+		evsel->handler = handler;
+	}
+
+	return evsel;
+
+out_delete:
+	perf_evsel__delete_priv(evsel);
+	return NULL;
+}
+
+#define perf_evsel__sc_tp_uint(evsel, name, sample) \
+	({ struct syscall_tp *fields = evsel->priv; \
+	   fields->name.integer(&fields->name, sample); })
+
+#define perf_evsel__sc_tp_ptr(evsel, name, sample) \
+	({ struct syscall_tp *fields = evsel->priv; \
+	   fields->name.pointer(&fields->name, sample); })
+
+static int perf_evlist__add_syscall_newtp(struct perf_evlist *evlist,
+					  void *sys_enter_handler,
+					  void *sys_exit_handler)
+{
+	int ret = -1;
+	int idx = evlist->nr_entries;
+	struct perf_evsel *sys_enter, *sys_exit;
+
+	sys_enter = perf_evsel__syscall_newtp("sys_enter", sys_enter_handler, idx++);
+	if (sys_enter == NULL)
+		goto out;
+
+	if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
+		goto out_delete_sys_enter;
+
+	sys_exit = perf_evsel__syscall_newtp("sys_exit", sys_exit_handler, idx++);
+	if (sys_exit == NULL)
+		goto out_delete_sys_enter;
+
+	if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
+		goto out_delete_sys_exit;
+
+	perf_evlist__add(evlist, sys_enter);
+	perf_evlist__add(evlist, sys_exit);
+
+	ret = 0;
+out:
+	return ret;
+
+out_delete_sys_exit:
+	perf_evsel__delete_priv(sys_exit);
+out_delete_sys_enter:
+	perf_evsel__delete_priv(sys_enter);
+	goto out;
+}
+
+
+struct syscall_arg {
+	unsigned long val;
+	struct thread *thread;
+	struct trace  *trace;
+	void	      *parm;
+	u8	      idx;
+	u8	      mask;
+};
+
+struct strarray {
+	int	    offset;
+	int	    nr_entries;
+	const char **entries;
+};
+
+#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
+	.nr_entries = ARRAY_SIZE(array), \
+	.entries = array, \
+}
+
+#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
+	.offset	    = off, \
+	.nr_entries = ARRAY_SIZE(array), \
+	.entries = array, \
+}
+
+static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
+						const char *intfmt,
+					        struct syscall_arg *arg)
+{
+	struct strarray *sa = arg->parm;
+	int idx = arg->val - sa->offset;
+
+	if (idx < 0 || idx >= sa->nr_entries)
+		return scnprintf(bf, size, intfmt, arg->val);
+
+	return scnprintf(bf, size, "%s", sa->entries[idx]);
+}
+
+static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
+					      struct syscall_arg *arg)
+{
+	return __syscall_arg__scnprintf_strarray(bf, size, "%d", arg);
+}
+
+#define SCA_STRARRAY syscall_arg__scnprintf_strarray
+
+static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
+						 struct syscall_arg *arg)
+{
+	return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
+}
+
+#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
+
+static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
+					struct syscall_arg *arg);
+
+#define SCA_FD syscall_arg__scnprintf_fd
+
+static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
+					   struct syscall_arg *arg)
+{
+	int fd = arg->val;
+
+	if (fd == AT_FDCWD)
+		return scnprintf(bf, size, "CWD");
+
+	return syscall_arg__scnprintf_fd(bf, size, arg);
+}
+
+#define SCA_FDAT syscall_arg__scnprintf_fd_at
+
+static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
+					      struct syscall_arg *arg);
+
+#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
+
+static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
+					 struct syscall_arg *arg)
+{
+	return scnprintf(bf, size, "%#lx", arg->val);
 }
 
 #define SCA_HEX syscall_arg__scnprintf_hex
 
-static size_t syscall_arg__scnprintf_whence(char *bf, size_t size,
-					    unsigned long arg,
-					    u8 arg_idx __maybe_unused,
-					    u8 *arg_mask __maybe_unused)
-{
-	int whence = arg;
-
-	switch (whence) {
-#define P_WHENCE(n) case SEEK_##n: return scnprintf(bf, size, #n)
-	P_WHENCE(SET);
-	P_WHENCE(CUR);
-	P_WHENCE(END);
-#ifdef SEEK_DATA
-	P_WHENCE(DATA);
-#endif
-#ifdef SEEK_HOLE
-	P_WHENCE(HOLE);
-#endif
-#undef P_WHENCE
-	default: break;
-	}
-
-	return scnprintf(bf, size, "%#x", whence);
-}
-
-#define SCA_WHENCE syscall_arg__scnprintf_whence
-
 static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
-					       unsigned long arg,
-					       u8 arg_idx __maybe_unused,
-					       u8 *arg_mask __maybe_unused)
+					       struct syscall_arg *arg)
 {
-	int printed = 0, prot = arg;
+	int printed = 0, prot = arg->val;
 
 	if (prot == PROT_NONE)
 		return scnprintf(bf, size, "NONE");
@@ -104,10 +336,9 @@
 #define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
 
 static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
-						unsigned long arg, u8 arg_idx __maybe_unused,
-						u8 *arg_mask __maybe_unused)
+						struct syscall_arg *arg)
 {
-	int printed = 0, flags = arg;
+	int printed = 0, flags = arg->val;
 
 #define	P_MMAP_FLAG(n) \
 	if (flags & MAP_##n) { \
@@ -148,10 +379,9 @@
 #define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
 
 static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
-						      unsigned long arg, u8 arg_idx __maybe_unused,
-						      u8 *arg_mask __maybe_unused)
+						      struct syscall_arg *arg)
 {
-	int behavior = arg;
+	int behavior = arg->val;
 
 	switch (behavior) {
 #define	P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
@@ -190,8 +420,38 @@
 
 #define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
 
-static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, unsigned long arg,
-					      u8 arg_idx __maybe_unused, u8 *arg_mask)
+static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
+					   struct syscall_arg *arg)
+{
+	int printed = 0, op = arg->val;
+
+	if (op == 0)
+		return scnprintf(bf, size, "NONE");
+#define	P_CMD(cmd) \
+	if ((op & LOCK_##cmd) == LOCK_##cmd) { \
+		printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
+		op &= ~LOCK_##cmd; \
+	}
+
+	P_CMD(SH);
+	P_CMD(EX);
+	P_CMD(NB);
+	P_CMD(UN);
+	P_CMD(MAND);
+	P_CMD(RW);
+	P_CMD(READ);
+	P_CMD(WRITE);
+#undef P_OP
+
+	if (op)
+		printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
+
+	return printed;
+}
+
+#define SCA_FLOCK syscall_arg__scnprintf_flock
+
+static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
 {
 	enum syscall_futex_args {
 		SCF_UADDR   = (1 << 0),
@@ -201,24 +461,24 @@
 		SCF_UADDR2  = (1 << 4),
 		SCF_VAL3    = (1 << 5),
 	};
-	int op = arg;
+	int op = arg->val;
 	int cmd = op & FUTEX_CMD_MASK;
 	size_t printed = 0;
 
 	switch (cmd) {
 #define	P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
-	P_FUTEX_OP(WAIT);	    *arg_mask |= SCF_VAL3|SCF_UADDR2;		  break;
-	P_FUTEX_OP(WAKE);	    *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
-	P_FUTEX_OP(FD);		    *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
-	P_FUTEX_OP(REQUEUE);	    *arg_mask |= SCF_VAL3|SCF_TIMEOUT;	          break;
-	P_FUTEX_OP(CMP_REQUEUE);    *arg_mask |= SCF_TIMEOUT;			  break;
-	P_FUTEX_OP(CMP_REQUEUE_PI); *arg_mask |= SCF_TIMEOUT;			  break;
+	P_FUTEX_OP(WAIT);	    arg->mask |= SCF_VAL3|SCF_UADDR2;		  break;
+	P_FUTEX_OP(WAKE);	    arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
+	P_FUTEX_OP(FD);		    arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
+	P_FUTEX_OP(REQUEUE);	    arg->mask |= SCF_VAL3|SCF_TIMEOUT;	          break;
+	P_FUTEX_OP(CMP_REQUEUE);    arg->mask |= SCF_TIMEOUT;			  break;
+	P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT;			  break;
 	P_FUTEX_OP(WAKE_OP);							  break;
-	P_FUTEX_OP(LOCK_PI);	    *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
-	P_FUTEX_OP(UNLOCK_PI);	    *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
-	P_FUTEX_OP(TRYLOCK_PI);	    *arg_mask |= SCF_VAL3|SCF_UADDR2;		  break;
-	P_FUTEX_OP(WAIT_BITSET);    *arg_mask |= SCF_UADDR2;			  break;
-	P_FUTEX_OP(WAKE_BITSET);    *arg_mask |= SCF_UADDR2;			  break;
+	P_FUTEX_OP(LOCK_PI);	    arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
+	P_FUTEX_OP(UNLOCK_PI);	    arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
+	P_FUTEX_OP(TRYLOCK_PI);	    arg->mask |= SCF_VAL3|SCF_UADDR2;		  break;
+	P_FUTEX_OP(WAIT_BITSET);    arg->mask |= SCF_UADDR2;			  break;
+	P_FUTEX_OP(WAKE_BITSET);    arg->mask |= SCF_UADDR2;			  break;
 	P_FUTEX_OP(WAIT_REQUEUE_PI);						  break;
 	default: printed = scnprintf(bf, size, "%#x", cmd);			  break;
 	}
@@ -234,14 +494,194 @@
 
 #define SCA_FUTEX_OP  syscall_arg__scnprintf_futex_op
 
-static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
-					       unsigned long arg,
-					       u8 arg_idx, u8 *arg_mask)
+static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
+static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
+
+static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
+static DEFINE_STRARRAY(itimers);
+
+static const char *whences[] = { "SET", "CUR", "END",
+#ifdef SEEK_DATA
+"DATA",
+#endif
+#ifdef SEEK_HOLE
+"HOLE",
+#endif
+};
+static DEFINE_STRARRAY(whences);
+
+static const char *fcntl_cmds[] = {
+	"DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
+	"SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
+	"F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
+	"F_GETOWNER_UIDS",
+};
+static DEFINE_STRARRAY(fcntl_cmds);
+
+static const char *rlimit_resources[] = {
+	"CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
+	"MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
+	"RTTIME",
+};
+static DEFINE_STRARRAY(rlimit_resources);
+
+static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
+static DEFINE_STRARRAY(sighow);
+
+static const char *clockid[] = {
+	"REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
+	"MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE",
+};
+static DEFINE_STRARRAY(clockid);
+
+static const char *socket_families[] = {
+	"UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
+	"BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
+	"SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
+	"RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
+	"BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
+	"ALG", "NFC", "VSOCK",
+};
+static DEFINE_STRARRAY(socket_families);
+
+#ifndef SOCK_TYPE_MASK
+#define SOCK_TYPE_MASK 0xf
+#endif
+
+static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size,
+						      struct syscall_arg *arg)
 {
-	int printed = 0, flags = arg;
+	size_t printed;
+	int type = arg->val,
+	    flags = type & ~SOCK_TYPE_MASK;
+
+	type &= SOCK_TYPE_MASK;
+	/*
+ 	 * Can't use a strarray, MIPS may override for ABI reasons.
+ 	 */
+	switch (type) {
+#define	P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
+	P_SK_TYPE(STREAM);
+	P_SK_TYPE(DGRAM);
+	P_SK_TYPE(RAW);
+	P_SK_TYPE(RDM);
+	P_SK_TYPE(SEQPACKET);
+	P_SK_TYPE(DCCP);
+	P_SK_TYPE(PACKET);
+#undef P_SK_TYPE
+	default:
+		printed = scnprintf(bf, size, "%#x", type);
+	}
+
+#define	P_SK_FLAG(n) \
+	if (flags & SOCK_##n) { \
+		printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
+		flags &= ~SOCK_##n; \
+	}
+
+	P_SK_FLAG(CLOEXEC);
+	P_SK_FLAG(NONBLOCK);
+#undef P_SK_FLAG
+
+	if (flags)
+		printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
+
+	return printed;
+}
+
+#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
+
+#ifndef MSG_PROBE
+#define MSG_PROBE	     0x10
+#endif
+#ifndef MSG_WAITFORONE
+#define MSG_WAITFORONE	0x10000
+#endif
+#ifndef MSG_SENDPAGE_NOTLAST
+#define MSG_SENDPAGE_NOTLAST 0x20000
+#endif
+#ifndef MSG_FASTOPEN
+#define MSG_FASTOPEN	     0x20000000
+#endif
+
+static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
+					       struct syscall_arg *arg)
+{
+	int printed = 0, flags = arg->val;
+
+	if (flags == 0)
+		return scnprintf(bf, size, "NONE");
+#define	P_MSG_FLAG(n) \
+	if (flags & MSG_##n) { \
+		printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
+		flags &= ~MSG_##n; \
+	}
+
+	P_MSG_FLAG(OOB);
+	P_MSG_FLAG(PEEK);
+	P_MSG_FLAG(DONTROUTE);
+	P_MSG_FLAG(TRYHARD);
+	P_MSG_FLAG(CTRUNC);
+	P_MSG_FLAG(PROBE);
+	P_MSG_FLAG(TRUNC);
+	P_MSG_FLAG(DONTWAIT);
+	P_MSG_FLAG(EOR);
+	P_MSG_FLAG(WAITALL);
+	P_MSG_FLAG(FIN);
+	P_MSG_FLAG(SYN);
+	P_MSG_FLAG(CONFIRM);
+	P_MSG_FLAG(RST);
+	P_MSG_FLAG(ERRQUEUE);
+	P_MSG_FLAG(NOSIGNAL);
+	P_MSG_FLAG(MORE);
+	P_MSG_FLAG(WAITFORONE);
+	P_MSG_FLAG(SENDPAGE_NOTLAST);
+	P_MSG_FLAG(FASTOPEN);
+	P_MSG_FLAG(CMSG_CLOEXEC);
+#undef P_MSG_FLAG
+
+	if (flags)
+		printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
+
+	return printed;
+}
+
+#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
+
+static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
+						 struct syscall_arg *arg)
+{
+	size_t printed = 0;
+	int mode = arg->val;
+
+	if (mode == F_OK) /* 0 */
+		return scnprintf(bf, size, "F");
+#define	P_MODE(n) \
+	if (mode & n##_OK) { \
+		printed += scnprintf(bf + printed, size - printed, "%s", #n); \
+		mode &= ~n##_OK; \
+	}
+
+	P_MODE(R);
+	P_MODE(W);
+	P_MODE(X);
+#undef P_MODE
+
+	if (mode)
+		printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
+
+	return printed;
+}
+
+#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
+
+static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
+					       struct syscall_arg *arg)
+{
+	int printed = 0, flags = arg->val;
 
 	if (!(flags & O_CREAT))
-		*arg_mask |= 1 << (arg_idx + 1); /* Mask the mode parm */
+		arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
 
 	if (flags == 0)
 		return scnprintf(bf, size, "RDONLY");
@@ -291,32 +731,225 @@
 
 #define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
 
+static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
+						   struct syscall_arg *arg)
+{
+	int printed = 0, flags = arg->val;
+
+	if (flags == 0)
+		return scnprintf(bf, size, "NONE");
+#define	P_FLAG(n) \
+	if (flags & EFD_##n) { \
+		printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
+		flags &= ~EFD_##n; \
+	}
+
+	P_FLAG(SEMAPHORE);
+	P_FLAG(CLOEXEC);
+	P_FLAG(NONBLOCK);
+#undef P_FLAG
+
+	if (flags)
+		printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
+
+	return printed;
+}
+
+#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
+
+static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
+						struct syscall_arg *arg)
+{
+	int printed = 0, flags = arg->val;
+
+#define	P_FLAG(n) \
+	if (flags & O_##n) { \
+		printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
+		flags &= ~O_##n; \
+	}
+
+	P_FLAG(CLOEXEC);
+	P_FLAG(NONBLOCK);
+#undef P_FLAG
+
+	if (flags)
+		printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
+
+	return printed;
+}
+
+#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
+
+static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
+{
+	int sig = arg->val;
+
+	switch (sig) {
+#define	P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
+	P_SIGNUM(HUP);
+	P_SIGNUM(INT);
+	P_SIGNUM(QUIT);
+	P_SIGNUM(ILL);
+	P_SIGNUM(TRAP);
+	P_SIGNUM(ABRT);
+	P_SIGNUM(BUS);
+	P_SIGNUM(FPE);
+	P_SIGNUM(KILL);
+	P_SIGNUM(USR1);
+	P_SIGNUM(SEGV);
+	P_SIGNUM(USR2);
+	P_SIGNUM(PIPE);
+	P_SIGNUM(ALRM);
+	P_SIGNUM(TERM);
+	P_SIGNUM(STKFLT);
+	P_SIGNUM(CHLD);
+	P_SIGNUM(CONT);
+	P_SIGNUM(STOP);
+	P_SIGNUM(TSTP);
+	P_SIGNUM(TTIN);
+	P_SIGNUM(TTOU);
+	P_SIGNUM(URG);
+	P_SIGNUM(XCPU);
+	P_SIGNUM(XFSZ);
+	P_SIGNUM(VTALRM);
+	P_SIGNUM(PROF);
+	P_SIGNUM(WINCH);
+	P_SIGNUM(IO);
+	P_SIGNUM(PWR);
+	P_SIGNUM(SYS);
+	default: break;
+	}
+
+	return scnprintf(bf, size, "%#x", sig);
+}
+
+#define SCA_SIGNUM syscall_arg__scnprintf_signum
+
+#define TCGETS		0x5401
+
+static const char *tioctls[] = {
+	"TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
+	"TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
+	"TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
+	"TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
+	"TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
+	"TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
+	"TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
+	"TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
+	"TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
+	"TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
+	"TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
+	[0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
+	"TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
+	"TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
+	"TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
+};
+
+static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
+
+#define STRARRAY(arg, name, array) \
+	  .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
+	  .arg_parm	 = { [arg] = &strarray__##array, }
+
 static struct syscall_fmt {
 	const char *name;
 	const char *alias;
-	size_t	   (*arg_scnprintf[6])(char *bf, size_t size, unsigned long arg, u8 arg_idx, u8 *arg_mask);
+	size_t	   (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
+	void	   *arg_parm[6];
 	bool	   errmsg;
 	bool	   timeout;
 	bool	   hexret;
 } syscall_fmts[] = {
-	{ .name	    = "access",	    .errmsg = true, },
+	{ .name	    = "access",	    .errmsg = true,
+	  .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
 	{ .name	    = "arch_prctl", .errmsg = true, .alias = "prctl", },
 	{ .name	    = "brk",	    .hexret = true,
 	  .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
-	{ .name	    = "mmap",	    .hexret = true, },
+	{ .name     = "clock_gettime",  .errmsg = true, STRARRAY(0, clk_id, clockid), },
+	{ .name	    = "close",	    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, 
 	{ .name	    = "connect",    .errmsg = true, },
-	{ .name	    = "fstat",	    .errmsg = true, .alias = "newfstat", },
-	{ .name	    = "fstatat",    .errmsg = true, .alias = "newfstatat", },
+	{ .name	    = "dup",	    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "dup2",	    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "dup3",	    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "epoll_ctl",  .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
+	{ .name	    = "eventfd2",   .errmsg = true,
+	  .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
+	{ .name	    = "faccessat",  .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
+	{ .name	    = "fadvise64",  .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "fallocate",  .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "fchdir",	    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "fchmod",	    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "fchmodat",   .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 
+	{ .name	    = "fchown",	    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "fchownat",   .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 
+	{ .name	    = "fcntl",	    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */
+			     [1] = SCA_STRARRAY, /* cmd */ },
+	  .arg_parm	 = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
+	{ .name	    = "fdatasync",  .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "flock",	    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */
+			     [1] = SCA_FLOCK, /* cmd */ }, },
+	{ .name	    = "fsetxattr",  .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "fstat",	    .errmsg = true, .alias = "newfstat",
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "fstatat",    .errmsg = true, .alias = "newfstatat",
+	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
+	{ .name	    = "fstatfs",    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "fsync",    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "ftruncate", .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 	{ .name	    = "futex",	    .errmsg = true,
 	  .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
+	{ .name	    = "futimesat", .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 
+	{ .name	    = "getdents",   .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "getdents64", .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "getitimer",  .errmsg = true, STRARRAY(0, which, itimers), },
+	{ .name	    = "getrlimit",  .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
 	{ .name	    = "ioctl",	    .errmsg = true,
-	  .arg_scnprintf = { [2] = SCA_HEX, /* arg */ }, },
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ 
+			     [1] = SCA_STRHEXARRAY, /* cmd */
+			     [2] = SCA_HEX, /* arg */ },
+	  .arg_parm	 = { [1] = &strarray__tioctls, /* cmd */ }, },
+	{ .name	    = "kill",	    .errmsg = true,
+	  .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
+	{ .name	    = "linkat",	    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 
 	{ .name	    = "lseek",	    .errmsg = true,
-	  .arg_scnprintf = { [2] = SCA_WHENCE, /* whence */ }, },
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */
+			     [2] = SCA_STRARRAY, /* whence */ },
+	  .arg_parm	 = { [2] = &strarray__whences, /* whence */ }, },
 	{ .name	    = "lstat",	    .errmsg = true, .alias = "newlstat", },
 	{ .name     = "madvise",    .errmsg = true,
 	  .arg_scnprintf = { [0] = SCA_HEX,	 /* start */
 			     [2] = SCA_MADV_BHV, /* behavior */ }, },
+	{ .name	    = "mkdirat",    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 
+	{ .name	    = "mknodat",    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 
+	{ .name	    = "mlock",	    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
+	{ .name	    = "mlockall",   .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
 	{ .name	    = "mmap",	    .hexret = true,
 	  .arg_scnprintf = { [0] = SCA_HEX,	  /* addr */
 			     [2] = SCA_MMAP_PROT, /* prot */
@@ -327,24 +960,91 @@
 	{ .name	    = "mremap",	    .hexret = true,
 	  .arg_scnprintf = { [0] = SCA_HEX, /* addr */
 			     [4] = SCA_HEX, /* new_addr */ }, },
+	{ .name	    = "munlock",    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
 	{ .name	    = "munmap",	    .errmsg = true,
 	  .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
+	{ .name	    = "name_to_handle_at", .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
+	{ .name	    = "newfstatat", .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
 	{ .name	    = "open",	    .errmsg = true,
 	  .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
 	{ .name	    = "open_by_handle_at", .errmsg = true,
-	  .arg_scnprintf = { [2] = SCA_OPEN_FLAGS, /* flags */ }, },
+	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
+			     [2] = SCA_OPEN_FLAGS, /* flags */ }, },
 	{ .name	    = "openat",	    .errmsg = true,
-	  .arg_scnprintf = { [2] = SCA_OPEN_FLAGS, /* flags */ }, },
+	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
+			     [2] = SCA_OPEN_FLAGS, /* flags */ }, },
+	{ .name	    = "pipe2",	    .errmsg = true,
+	  .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
 	{ .name	    = "poll",	    .errmsg = true, .timeout = true, },
 	{ .name	    = "ppoll",	    .errmsg = true, .timeout = true, },
-	{ .name	    = "pread",	    .errmsg = true, .alias = "pread64", },
-	{ .name	    = "pwrite",	    .errmsg = true, .alias = "pwrite64", },
-	{ .name	    = "read",	    .errmsg = true, },
-	{ .name	    = "recvfrom",   .errmsg = true, },
+	{ .name	    = "pread",	    .errmsg = true, .alias = "pread64",
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "preadv",	    .errmsg = true, .alias = "pread",
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "prlimit64",  .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
+	{ .name	    = "pwrite",	    .errmsg = true, .alias = "pwrite64",
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "pwritev",    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "read",	    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "readlinkat", .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
+	{ .name	    = "readv",	    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "recvfrom",   .errmsg = true,
+	  .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
+	{ .name	    = "recvmmsg",   .errmsg = true,
+	  .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
+	{ .name	    = "recvmsg",    .errmsg = true,
+	  .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
+	{ .name	    = "renameat",   .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
+	{ .name	    = "rt_sigaction", .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
+	{ .name	    = "rt_sigprocmask",  .errmsg = true, STRARRAY(0, how, sighow), },
+	{ .name	    = "rt_sigqueueinfo", .errmsg = true,
+	  .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
+	{ .name	    = "rt_tgsigqueueinfo", .errmsg = true,
+	  .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
 	{ .name	    = "select",	    .errmsg = true, .timeout = true, },
-	{ .name	    = "socket",	    .errmsg = true, },
+	{ .name	    = "sendmmsg",    .errmsg = true,
+	  .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
+	{ .name	    = "sendmsg",    .errmsg = true,
+	  .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
+	{ .name	    = "sendto",	    .errmsg = true,
+	  .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
+	{ .name	    = "setitimer",  .errmsg = true, STRARRAY(0, which, itimers), },
+	{ .name	    = "setrlimit",  .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
+	{ .name	    = "shutdown",   .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "socket",	    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
+			     [1] = SCA_SK_TYPE, /* type */ },
+	  .arg_parm	 = { [0] = &strarray__socket_families, /* family */ }, },
+	{ .name	    = "socketpair", .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
+			     [1] = SCA_SK_TYPE, /* type */ },
+	  .arg_parm	 = { [0] = &strarray__socket_families, /* family */ }, },
 	{ .name	    = "stat",	    .errmsg = true, .alias = "newstat", },
+	{ .name	    = "symlinkat",  .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 
+	{ .name	    = "tgkill",	    .errmsg = true,
+	  .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
+	{ .name	    = "tkill",	    .errmsg = true,
+	  .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
 	{ .name	    = "uname",	    .errmsg = true, .alias = "newuname", },
+	{ .name	    = "unlinkat",   .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
+	{ .name	    = "utimensat",  .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
+	{ .name	    = "write",	    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
+	{ .name	    = "writev",	    .errmsg = true,
+	  .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 
 };
 
 static int syscall_fmt__cmp(const void *name, const void *fmtp)
@@ -364,8 +1064,8 @@
 	const char	    *name;
 	bool		    filtered;
 	struct syscall_fmt  *fmt;
-	size_t		    (**arg_scnprintf)(char *bf, size_t size,
-					      unsigned long arg, u8 arg_idx, u8 *args_mask);
+	size_t		    (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
+	void		    **arg_parm;
 };
 
 static size_t fprintf_duration(unsigned long t, FILE *fp)
@@ -389,11 +1089,24 @@
 	unsigned long	  nr_events;
 	char		  *entry_str;
 	double		  runtime_ms;
+	struct {
+		int	  max;
+		char	  **table;
+	} paths;
+
+	struct intlist *syscall_stats;
 };
 
 static struct thread_trace *thread_trace__new(void)
 {
-	return zalloc(sizeof(struct thread_trace));
+	struct thread_trace *ttrace =  zalloc(sizeof(struct thread_trace));
+
+	if (ttrace)
+		ttrace->paths.max = -1;
+
+	ttrace->syscall_stats = intlist__new(NULL);
+
+	return ttrace;
 }
 
 static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
@@ -421,26 +1134,140 @@
 
 struct trace {
 	struct perf_tool	tool;
-	int			audit_machine;
+	struct {
+		int		machine;
+		int		open_id;
+	}			audit;
 	struct {
 		int		max;
 		struct syscall  *table;
 	} syscalls;
 	struct perf_record_opts opts;
-	struct machine		host;
+	struct machine		*host;
 	u64			base_time;
+	bool			full_time;
 	FILE			*output;
 	unsigned long		nr_events;
 	struct strlist		*ev_qualifier;
 	bool			not_ev_qualifier;
+	bool			live;
+	const char 		*last_vfs_getname;
 	struct intlist		*tid_list;
 	struct intlist		*pid_list;
 	bool			sched;
 	bool			multiple_threads;
+	bool			summary;
+	bool			show_comm;
+	bool			show_tool_stats;
 	double			duration_filter;
 	double			runtime_ms;
+	struct {
+		u64		vfs_getname, proc_getname;
+	} stats;
 };
 
+static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
+{
+	struct thread_trace *ttrace = thread->priv;
+
+	if (fd > ttrace->paths.max) {
+		char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
+
+		if (npath == NULL)
+			return -1;
+
+		if (ttrace->paths.max != -1) {
+			memset(npath + ttrace->paths.max + 1, 0,
+			       (fd - ttrace->paths.max) * sizeof(char *));
+		} else {
+			memset(npath, 0, (fd + 1) * sizeof(char *));
+		}
+
+		ttrace->paths.table = npath;
+		ttrace->paths.max   = fd;
+	}
+
+	ttrace->paths.table[fd] = strdup(pathname);
+
+	return ttrace->paths.table[fd] != NULL ? 0 : -1;
+}
+
+static int thread__read_fd_path(struct thread *thread, int fd)
+{
+	char linkname[PATH_MAX], pathname[PATH_MAX];
+	struct stat st;
+	int ret;
+
+	if (thread->pid_ == thread->tid) {
+		scnprintf(linkname, sizeof(linkname),
+			  "/proc/%d/fd/%d", thread->pid_, fd);
+	} else {
+		scnprintf(linkname, sizeof(linkname),
+			  "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
+	}
+
+	if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
+		return -1;
+
+	ret = readlink(linkname, pathname, sizeof(pathname));
+
+	if (ret < 0 || ret > st.st_size)
+		return -1;
+
+	pathname[ret] = '\0';
+	return trace__set_fd_pathname(thread, fd, pathname);
+}
+
+static const char *thread__fd_path(struct thread *thread, int fd,
+				   struct trace *trace)
+{
+	struct thread_trace *ttrace = thread->priv;
+
+	if (ttrace == NULL)
+		return NULL;
+
+	if (fd < 0)
+		return NULL;
+
+	if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL))
+		if (!trace->live)
+			return NULL;
+		++trace->stats.proc_getname;
+		if (thread__read_fd_path(thread, fd)) {
+			return NULL;
+	}
+
+	return ttrace->paths.table[fd];
+}
+
+static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
+					struct syscall_arg *arg)
+{
+	int fd = arg->val;
+	size_t printed = scnprintf(bf, size, "%d", fd);
+	const char *path = thread__fd_path(arg->thread, fd, arg->trace);
+
+	if (path)
+		printed += scnprintf(bf + printed, size - printed, "<%s>", path);
+
+	return printed;
+}
+
+static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
+					      struct syscall_arg *arg)
+{
+	int fd = arg->val;
+	size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
+	struct thread_trace *ttrace = arg->thread->priv;
+
+	if (ttrace && fd >= 0 && fd <= ttrace->paths.max) {
+		free(ttrace->paths.table[fd]);
+		ttrace->paths.table[fd] = NULL;
+	}
+
+	return printed;
+}
+
 static bool trace__filter_duration(struct trace *trace, double t)
 {
 	return t < (trace->duration_filter * NSEC_PER_MSEC);
@@ -454,10 +1281,12 @@
 }
 
 static bool done = false;
+static bool interrupted = false;
 
-static void sig_handler(int sig __maybe_unused)
+static void sig_handler(int sig)
 {
 	done = true;
+	interrupted = sig == SIGINT;
 }
 
 static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
@@ -466,14 +1295,17 @@
 	size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
 	printed += fprintf_duration(duration, fp);
 
-	if (trace->multiple_threads)
+	if (trace->multiple_threads) {
+		if (trace->show_comm)
+			printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
 		printed += fprintf(fp, "%d ", thread->tid);
+	}
 
 	return printed;
 }
 
 static int trace__process_event(struct trace *trace, struct machine *machine,
-				union perf_event *event)
+				union perf_event *event, struct perf_sample *sample)
 {
 	int ret = 0;
 
@@ -481,9 +1313,9 @@
 	case PERF_RECORD_LOST:
 		color_fprintf(trace->output, PERF_COLOR_RED,
 			      "LOST %" PRIu64 " events!\n", event->lost.lost);
-		ret = machine__process_lost_event(machine, event);
+		ret = machine__process_lost_event(machine, event, sample);
 	default:
-		ret = machine__process_event(machine, event);
+		ret = machine__process_event(machine, event, sample);
 		break;
 	}
 
@@ -492,11 +1324,11 @@
 
 static int trace__tool_process(struct perf_tool *tool,
 			       union perf_event *event,
-			       struct perf_sample *sample __maybe_unused,
+			       struct perf_sample *sample,
 			       struct machine *machine)
 {
 	struct trace *trace = container_of(tool, struct trace, tool);
-	return trace__process_event(trace, machine, event);
+	return trace__process_event(trace, machine, event, sample);
 }
 
 static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
@@ -506,16 +1338,17 @@
 	if (err)
 		return err;
 
-	machine__init(&trace->host, "", HOST_KERNEL_ID);
-	machine__create_kernel_maps(&trace->host);
+	trace->host = machine__new_host();
+	if (trace->host == NULL)
+		return -ENOMEM;
 
 	if (perf_target__has_task(&trace->opts.target)) {
 		err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads,
 							trace__tool_process,
-							&trace->host);
+							trace->host);
 	} else {
 		err = perf_event__synthesize_threads(&trace->tool, trace__tool_process,
-						     &trace->host);
+						     trace->host);
 	}
 
 	if (err)
@@ -533,6 +1366,9 @@
 	if (sc->arg_scnprintf == NULL)
 		return -1;
 
+	if (sc->fmt)
+		sc->arg_parm = sc->fmt->arg_parm;
+
 	for (field = sc->tp_format->format.fields->next; field; field = field->next) {
 		if (sc->fmt && sc->fmt->arg_scnprintf[idx])
 			sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
@@ -548,7 +1384,7 @@
 {
 	char tp_name[128];
 	struct syscall *sc;
-	const char *name = audit_syscall_to_name(id, trace->audit_machine);
+	const char *name = audit_syscall_to_name(id, trace->audit.machine);
 
 	if (name == NULL)
 		return -1;
@@ -603,32 +1439,52 @@
 }
 
 static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
-				      unsigned long *args)
+				      unsigned long *args, struct trace *trace,
+				      struct thread *thread)
 {
-	int i = 0;
 	size_t printed = 0;
 
 	if (sc->tp_format != NULL) {
 		struct format_field *field;
-		u8 mask = 0, bit = 1;
+		u8 bit = 1;
+		struct syscall_arg arg = {
+			.idx	= 0,
+			.mask	= 0,
+			.trace  = trace,
+			.thread = thread,
+		};
 
 		for (field = sc->tp_format->format.fields->next; field;
-		     field = field->next, ++i, bit <<= 1) {
-			if (mask & bit)
+		     field = field->next, ++arg.idx, bit <<= 1) {
+			if (arg.mask & bit)
+				continue;
+			/*
+ 			 * Suppress this argument if its value is zero and
+ 			 * and we don't have a string associated in an
+ 			 * strarray for it.
+ 			 */
+			if (args[arg.idx] == 0 &&
+			    !(sc->arg_scnprintf &&
+			      sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
+			      sc->arg_parm[arg.idx]))
 				continue;
 
 			printed += scnprintf(bf + printed, size - printed,
 					     "%s%s: ", printed ? ", " : "", field->name);
-
-			if (sc->arg_scnprintf && sc->arg_scnprintf[i]) {
-				printed += sc->arg_scnprintf[i](bf + printed, size - printed,
-								args[i], i, &mask);
+			if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
+				arg.val = args[arg.idx];
+				if (sc->arg_parm)
+					arg.parm = sc->arg_parm[arg.idx];
+				printed += sc->arg_scnprintf[arg.idx](bf + printed,
+								      size - printed, &arg);
 			} else {
 				printed += scnprintf(bf + printed, size - printed,
-						     "%ld", args[i]);
+						     "%ld", args[arg.idx]);
 			}
 		}
 	} else {
+		int i = 0;
+
 		while (i < 6) {
 			printed += scnprintf(bf + printed, size - printed,
 					     "%sarg%d: %ld",
@@ -644,10 +1500,8 @@
 				  struct perf_sample *sample);
 
 static struct syscall *trace__syscall_info(struct trace *trace,
-					   struct perf_evsel *evsel,
-					   struct perf_sample *sample)
+					   struct perf_evsel *evsel, int id)
 {
-	int id = perf_evsel__intval(evsel, sample, "id");
 
 	if (id < 0) {
 
@@ -688,6 +1542,32 @@
 	return NULL;
 }
 
+static void thread__update_stats(struct thread_trace *ttrace,
+				 int id, struct perf_sample *sample)
+{
+	struct int_node *inode;
+	struct stats *stats;
+	u64 duration = 0;
+
+	inode = intlist__findnew(ttrace->syscall_stats, id);
+	if (inode == NULL)
+		return;
+
+	stats = inode->priv;
+	if (stats == NULL) {
+		stats = malloc(sizeof(struct stats));
+		if (stats == NULL)
+			return;
+		init_stats(stats);
+		inode->priv = stats;
+	}
+
+	if (ttrace->entry_time && sample->time > ttrace->entry_time)
+		duration = sample->time - ttrace->entry_time;
+
+	update_stats(stats, duration);
+}
+
 static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
 			    struct perf_sample *sample)
 {
@@ -695,7 +1575,8 @@
 	void *args;
 	size_t printed = 0;
 	struct thread *thread;
-	struct syscall *sc = trace__syscall_info(trace, evsel, sample);
+	int id = perf_evsel__sc_tp_uint(evsel, id, sample);
+	struct syscall *sc = trace__syscall_info(trace, evsel, id);
 	struct thread_trace *ttrace;
 
 	if (sc == NULL)
@@ -704,18 +1585,12 @@
 	if (sc->filtered)
 		return 0;
 
-	thread = machine__findnew_thread(&trace->host, sample->pid,
-					 sample->tid);
+	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
 	ttrace = thread__trace(thread, trace->output);
 	if (ttrace == NULL)
 		return -1;
 
-	args = perf_evsel__rawptr(evsel, sample, "args");
-	if (args == NULL) {
-		fprintf(trace->output, "Problems reading syscall arguments\n");
-		return -1;
-	}
-
+	args = perf_evsel__sc_tp_ptr(evsel, args, sample);
 	ttrace = thread->priv;
 
 	if (ttrace->entry_str == NULL) {
@@ -728,7 +1603,8 @@
 	msg = ttrace->entry_str;
 	printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
 
-	printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed,  args);
+	printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed,
+					   args, trace, thread);
 
 	if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) {
 		if (!trace->duration_filter) {
@@ -747,7 +1623,8 @@
 	int ret;
 	u64 duration = 0;
 	struct thread *thread;
-	struct syscall *sc = trace__syscall_info(trace, evsel, sample);
+	int id = perf_evsel__sc_tp_uint(evsel, id, sample);
+	struct syscall *sc = trace__syscall_info(trace, evsel, id);
 	struct thread_trace *ttrace;
 
 	if (sc == NULL)
@@ -756,13 +1633,21 @@
 	if (sc->filtered)
 		return 0;
 
-	thread = machine__findnew_thread(&trace->host, sample->pid,
-					 sample->tid);
+	thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
 	ttrace = thread__trace(thread, trace->output);
 	if (ttrace == NULL)
 		return -1;
 
-	ret = perf_evsel__intval(evsel, sample, "ret");
+	if (trace->summary)
+		thread__update_stats(ttrace, id, sample);
+
+	ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
+
+	if (id == trace->audit.open_id && ret >= 0 && trace->last_vfs_getname) {
+		trace__set_fd_pathname(thread, ret, trace->last_vfs_getname);
+		trace->last_vfs_getname = NULL;
+		++trace->stats.vfs_getname;
+	}
 
 	ttrace = thread->priv;
 
@@ -808,12 +1693,19 @@
 	return 0;
 }
 
+static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
+			      struct perf_sample *sample)
+{
+	trace->last_vfs_getname = perf_evsel__rawptr(evsel, sample, "pathname");
+	return 0;
+}
+
 static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
 				     struct perf_sample *sample)
 {
         u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
 	double runtime_ms = (double)runtime / NSEC_PER_MSEC;
-	struct thread *thread = machine__findnew_thread(&trace->host,
+	struct thread *thread = machine__findnew_thread(trace->host,
 							sample->pid,
 							sample->tid);
 	struct thread_trace *ttrace = thread__trace(thread, trace->output);
@@ -856,12 +1748,12 @@
 	struct trace *trace = container_of(tool, struct trace, tool);
 	int err = 0;
 
-	tracepoint_handler handler = evsel->handler.func;
+	tracepoint_handler handler = evsel->handler;
 
 	if (skip_sample(trace, sample))
 		return 0;
 
-	if (trace->base_time == 0)
+	if (!trace->full_time && trace->base_time == 0)
 		trace->base_time = sample->time;
 
 	if (handler)
@@ -901,6 +1793,51 @@
 	return 0;
 }
 
+static int trace__record(int argc, const char **argv)
+{
+	unsigned int rec_argc, i, j;
+	const char **rec_argv;
+	const char * const record_args[] = {
+		"record",
+		"-R",
+		"-m", "1024",
+		"-c", "1",
+		"-e", "raw_syscalls:sys_enter,raw_syscalls:sys_exit",
+	};
+
+	rec_argc = ARRAY_SIZE(record_args) + argc;
+	rec_argv = calloc(rec_argc + 1, sizeof(char *));
+
+	if (rec_argv == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < ARRAY_SIZE(record_args); i++)
+		rec_argv[i] = record_args[i];
+
+	for (j = 0; j < (unsigned int)argc; j++, i++)
+		rec_argv[i] = argv[j];
+
+	return cmd_record(i, rec_argv, NULL);
+}
+
+static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
+
+static void perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
+{
+	struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname",
+						     evlist->nr_entries);
+	if (evsel == NULL)
+		return;
+
+	if (perf_evsel__field(evsel, "pathname") == NULL) {
+		perf_evsel__delete(evsel);
+		return;
+	}
+
+	evsel->handler = trace__vfs_getname;
+	perf_evlist__add(evlist, evsel);
+}
+
 static int trace__run(struct trace *trace, int argc, const char **argv)
 {
 	struct perf_evlist *evlist = perf_evlist__new();
@@ -909,23 +1846,22 @@
 	unsigned long before;
 	const bool forks = argc > 0;
 
+	trace->live = true;
+
 	if (evlist == NULL) {
 		fprintf(trace->output, "Not enough memory to run!\n");
 		goto out;
 	}
 
-	if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
-	    perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) {
-		fprintf(trace->output, "Couldn't read the raw_syscalls tracepoints information!\n");
-		goto out_delete_evlist;
-	}
+	if (perf_evlist__add_syscall_newtp(evlist, trace__sys_enter, trace__sys_exit))
+		goto out_error_tp;
+
+	perf_evlist__add_vfs_getname(evlist);
 
 	if (trace->sched &&
-	    perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
-				   trace__sched_stat_runtime)) {
-		fprintf(trace->output, "Couldn't read the sched_stat_runtime tracepoint information!\n");
-		goto out_delete_evlist;
-	}
+		perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
+				trace__sched_stat_runtime))
+		goto out_error_tp;
 
 	err = perf_evlist__create_maps(evlist, &trace->opts.target);
 	if (err < 0) {
@@ -954,10 +1890,8 @@
 	}
 
 	err = perf_evlist__open(evlist);
-	if (err < 0) {
-		fprintf(trace->output, "Couldn't create the events: %s\n", strerror(errno));
-		goto out_delete_maps;
-	}
+	if (err < 0)
+		goto out_error_open;
 
 	err = perf_evlist__mmap(evlist, UINT_MAX, false);
 	if (err < 0) {
@@ -987,51 +1921,65 @@
 			err = perf_evlist__parse_sample(evlist, event, &sample);
 			if (err) {
 				fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err);
-				continue;
+				goto next_event;
 			}
 
-			if (trace->base_time == 0)
+			if (!trace->full_time && trace->base_time == 0)
 				trace->base_time = sample.time;
 
 			if (type != PERF_RECORD_SAMPLE) {
-				trace__process_event(trace, &trace->host, event);
+				trace__process_event(trace, trace->host, event, &sample);
 				continue;
 			}
 
 			evsel = perf_evlist__id2evsel(evlist, sample.id);
 			if (evsel == NULL) {
 				fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
-				continue;
+				goto next_event;
 			}
 
 			if (sample.raw_data == NULL) {
 				fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
 				       perf_evsel__name(evsel), sample.tid,
 				       sample.cpu, sample.raw_size);
-				continue;
+				goto next_event;
 			}
 
-			handler = evsel->handler.func;
+			handler = evsel->handler;
 			handler(trace, evsel, &sample);
+next_event:
+			perf_evlist__mmap_consume(evlist, i);
 
-			if (done)
-				goto out_unmap_evlist;
+			if (interrupted)
+				goto out_disable;
 		}
 	}
 
 	if (trace->nr_events == before) {
-		if (done)
-			goto out_unmap_evlist;
+		int timeout = done ? 100 : -1;
 
-		poll(evlist->pollfd, evlist->nr_fds, -1);
+		if (poll(evlist->pollfd, evlist->nr_fds, timeout) > 0)
+			goto again;
+	} else {
+		goto again;
 	}
 
-	if (done)
-		perf_evlist__disable(evlist);
+out_disable:
+	perf_evlist__disable(evlist);
 
-	goto again;
+	if (!err) {
+		if (trace->summary)
+			trace__fprintf_thread_summary(trace, trace->output);
 
-out_unmap_evlist:
+		if (trace->show_tool_stats) {
+			fprintf(trace->output, "Stats:\n "
+					       " vfs_getname : %" PRIu64 "\n"
+					       " proc_getname: %" PRIu64 "\n",
+				trace->stats.vfs_getname,
+				trace->stats.proc_getname);
+		}
+	}
+
 	perf_evlist__munmap(evlist);
 out_close_evlist:
 	perf_evlist__close(evlist);
@@ -1040,7 +1988,22 @@
 out_delete_evlist:
 	perf_evlist__delete(evlist);
 out:
+	trace->live = false;
 	return err;
+{
+	char errbuf[BUFSIZ];
+
+out_error_tp:
+	perf_evlist__strerror_tp(evlist, errno, errbuf, sizeof(errbuf));
+	goto out_error;
+
+out_error_open:
+	perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
+
+out_error:
+	fprintf(trace->output, "%s\n", errbuf);
+	goto out_delete_evlist;
+}
 }
 
 static int trace__replay(struct trace *trace)
@@ -1048,8 +2011,12 @@
 	const struct perf_evsel_str_handler handlers[] = {
 		{ "raw_syscalls:sys_enter",  trace__sys_enter, },
 		{ "raw_syscalls:sys_exit",   trace__sys_exit, },
+		{ "probe:vfs_getname",	     trace__vfs_getname, },
 	};
-
+	struct perf_data_file file = {
+		.path  = input_name,
+		.mode  = PERF_DATA_MODE_READ,
+	};
 	struct perf_session *session;
 	int err = -1;
 
@@ -1072,11 +2039,12 @@
 	if (symbol__init() < 0)
 		return -1;
 
-	session = perf_session__new(input_name, O_RDONLY, 0, false,
-				    &trace->tool);
+	session = perf_session__new(&file, false, &trace->tool);
 	if (session == NULL)
 		return -ENOMEM;
 
+	trace->host = &session->machines.host;
+
 	err = perf_session__set_tracepoints_handlers(session, handlers);
 	if (err)
 		goto out;
@@ -1101,6 +2069,9 @@
 	if (err)
 		pr_err("Failed to process events, error %d", err);
 
+	else if (trace->summary)
+		trace__fprintf_thread_summary(trace, trace->output);
+
 out:
 	perf_session__delete(session);
 
@@ -1111,47 +2082,111 @@
 {
 	size_t printed;
 
-	printed  = fprintf(fp, "\n _____________________________________________________________________\n");
-	printed += fprintf(fp," __)    Summary of events    (__\n\n");
-	printed += fprintf(fp,"              [ task - pid ]     [ events ] [ ratio ]  [ runtime ]\n");
-	printed += fprintf(fp," _____________________________________________________________________\n\n");
+	printed  = fprintf(fp, "\n _____________________________________________________________________________\n");
+	printed += fprintf(fp, " __)    Summary of events    (__\n\n");
+	printed += fprintf(fp, "              [ task - pid ]     [ events ] [ ratio ]  [ runtime ]\n");
+	printed += fprintf(fp, "                                  syscall  count    min     max    avg  stddev\n");
+	printed += fprintf(fp, "                                                   msec    msec   msec     %%\n");
+	printed += fprintf(fp, " _____________________________________________________________________________\n\n");
 
 	return printed;
 }
 
-static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
+static size_t thread__dump_stats(struct thread_trace *ttrace,
+				 struct trace *trace, FILE *fp)
 {
-	size_t printed = trace__fprintf_threads_header(fp);
-	struct rb_node *nd;
+	struct stats *stats;
+	size_t printed = 0;
+	struct syscall *sc;
+	struct int_node *inode = intlist__first(ttrace->syscall_stats);
 
-	for (nd = rb_first(&trace->host.threads); nd; nd = rb_next(nd)) {
-		struct thread *thread = rb_entry(nd, struct thread, rb_node);
-		struct thread_trace *ttrace = thread->priv;
-		const char *color;
-		double ratio;
+	if (inode == NULL)
+		return 0;
 
-		if (ttrace == NULL)
-			continue;
+	printed += fprintf(fp, "\n");
 
-		ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
+	/* each int_node is a syscall */
+	while (inode) {
+		stats = inode->priv;
+		if (stats) {
+			double min = (double)(stats->min) / NSEC_PER_MSEC;
+			double max = (double)(stats->max) / NSEC_PER_MSEC;
+			double avg = avg_stats(stats);
+			double pct;
+			u64 n = (u64) stats->n;
 
-		color = PERF_COLOR_NORMAL;
-		if (ratio > 50.0)
-			color = PERF_COLOR_RED;
-		else if (ratio > 25.0)
-			color = PERF_COLOR_GREEN;
-		else if (ratio > 5.0)
-			color = PERF_COLOR_YELLOW;
+			pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
+			avg /= NSEC_PER_MSEC;
 
-		printed += color_fprintf(fp, color, "%20s", thread->comm);
-		printed += fprintf(fp, " - %-5d :%11lu   [", thread->tid, ttrace->nr_events);
-		printed += color_fprintf(fp, color, "%5.1f%%", ratio);
-		printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
+			sc = &trace->syscalls.table[inode->i];
+			printed += fprintf(fp, "%24s  %14s : ", "", sc->name);
+			printed += fprintf(fp, "%5" PRIu64 "  %8.3f  %8.3f",
+					   n, min, max);
+			printed += fprintf(fp, "  %8.3f  %6.2f\n", avg, pct);
+		}
+
+		inode = intlist__next(inode);
 	}
 
+	printed += fprintf(fp, "\n\n");
+
 	return printed;
 }
 
+/* struct used to pass data to per-thread function */
+struct summary_data {
+	FILE *fp;
+	struct trace *trace;
+	size_t printed;
+};
+
+static int trace__fprintf_one_thread(struct thread *thread, void *priv)
+{
+	struct summary_data *data = priv;
+	FILE *fp = data->fp;
+	size_t printed = data->printed;
+	struct trace *trace = data->trace;
+	struct thread_trace *ttrace = thread->priv;
+	const char *color;
+	double ratio;
+
+	if (ttrace == NULL)
+		return 0;
+
+	ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
+
+	color = PERF_COLOR_NORMAL;
+	if (ratio > 50.0)
+		color = PERF_COLOR_RED;
+	else if (ratio > 25.0)
+		color = PERF_COLOR_GREEN;
+	else if (ratio > 5.0)
+		color = PERF_COLOR_YELLOW;
+
+	printed += color_fprintf(fp, color, "%20s", thread__comm_str(thread));
+	printed += fprintf(fp, " - %-5d :%11lu   [", thread->tid, ttrace->nr_events);
+	printed += color_fprintf(fp, color, "%5.1f%%", ratio);
+	printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
+	printed += thread__dump_stats(ttrace, trace, fp);
+
+	data->printed += printed;
+
+	return 0;
+}
+
+static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
+{
+	struct summary_data data = {
+		.fp = fp,
+		.trace = trace
+	};
+	data.printed = trace__fprintf_threads_header(fp);
+
+	machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
+
+	return data.printed;
+}
+
 static int trace__set_duration(const struct option *opt, const char *str,
 			       int unset __maybe_unused)
 {
@@ -1183,10 +2218,15 @@
 	const char * const trace_usage[] = {
 		"perf trace [<options>] [<command>]",
 		"perf trace [<options>] -- <command> [<options>]",
+		"perf trace record [<options>] [<command>]",
+		"perf trace record [<options>] -- <command> [<options>]",
 		NULL
 	};
 	struct trace trace = {
-		.audit_machine = audit_detect_machine(),
+		.audit = {
+			.machine = audit_detect_machine(),
+			.open_id = audit_name_to_syscall("open", trace.audit.machine),
+		},
 		.syscalls = {
 			. max = -1,
 		},
@@ -1201,10 +2241,14 @@
 			.mmap_pages    = 1024,
 		},
 		.output = stdout,
+		.show_comm = true,
 	};
 	const char *output_name = NULL;
 	const char *ev_qualifier_str = NULL;
 	const struct option trace_options[] = {
+	OPT_BOOLEAN(0, "comm", &trace.show_comm,
+		    "show the thread COMM next to its id"),
+	OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
 	OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
 		    "list of events to trace"),
 	OPT_STRING('o', "output", &output_name, "file", "output file name"),
@@ -1219,8 +2263,9 @@
 		    "list of cpus to monitor"),
 	OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
 		    "child tasks do not inherit counters"),
-	OPT_UINTEGER('m', "mmap-pages", &trace.opts.mmap_pages,
-		     "number of mmap data pages"),
+	OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
+		     "number of mmap data pages",
+		     perf_evlist__parse_mmap_pages),
 	OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
 		   "user to profile"),
 	OPT_CALLBACK(0, "duration", &trace, "float",
@@ -1228,11 +2273,18 @@
 		     trace__set_duration),
 	OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
 	OPT_INCR('v', "verbose", &verbose, "be more verbose"),
+	OPT_BOOLEAN('T', "time", &trace.full_time,
+		    "Show full timestamp, not time relative to first start"),
+	OPT_BOOLEAN(0, "summary", &trace.summary,
+		    "Show syscall summary with statistics"),
 	OPT_END()
 	};
 	int err;
 	char bf[BUFSIZ];
 
+	if ((argc > 1) && (strcmp(argv[1], "record") == 0))
+		return trace__record(argc-2, &argv[2]);
+
 	argc = parse_options(argc, argv, trace_options, trace_usage, 0);
 
 	if (output_name != NULL) {
@@ -1280,9 +2332,6 @@
 	else
 		err = trace__run(&trace, argc, argv);
 
-	if (trace.sched && !err)
-		trace__fprintf_thread_summary(&trace, trace.output);
-
 out_close:
 	if (output_name != NULL)
 		fclose(trace.output);
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 5f6f9b3..58b2d37 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -23,15 +23,17 @@
   endif
   ifeq (${IS_X86_64}, 1)
     RAW_ARCH := x86_64
-    CFLAGS += -DARCH_X86_64
+    CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT
     ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
+    LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
+  else
+    LIBUNWIND_LIBS = -lunwind -lunwind-x86
   endif
   NO_PERF_REGS := 0
-  LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
 endif
 
 ifeq ($(NO_PERF_REGS),0)
-  CFLAGS += -DHAVE_PERF_REGS
+  CFLAGS += -DHAVE_PERF_REGS_SUPPORT
 endif
 
 ifeq ($(src-perf),)
@@ -51,7 +53,6 @@
 # include ARCH specific config
 -include $(src-perf)/arch/$(ARCH)/Makefile
 
-include $(src-perf)/config/feature-tests.mak
 include $(src-perf)/config/utilities.mak
 
 ifeq ($(call get-executable,$(FLEX)),)
@@ -67,10 +68,11 @@
   CFLAGS += -Werror
 endif
 
-ifeq ("$(origin DEBUG)", "command line")
-  PERF_DEBUG = $(DEBUG)
+ifndef DEBUG
+  DEBUG := 0
 endif
-ifndef PERF_DEBUG
+
+ifeq ($(DEBUG),0)
   CFLAGS += -O6
 endif
 
@@ -89,20 +91,125 @@
 
 EXTLIBS = -lelf -lpthread -lrt -lm -ldl
 
-ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y)
+ifneq ($(OUTPUT),)
+  OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/
+  $(shell mkdir -p $(OUTPUT_FEATURES))
+endif
+
+feature_check = $(eval $(feature_check_code))
+define feature_check_code
+  feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS="$(LDFLAGS)" LIBUNWIND_LIBS="$(LIBUNWIND_LIBS)" -C config/feature-checks test-$1 >/dev/null 2>/dev/null && echo 1 || echo 0)
+endef
+
+feature_set = $(eval $(feature_set_code))
+define feature_set_code
+  feature-$(1) := 1
+endef
+
+#
+# Build the feature check binaries in parallel, ignore errors, ignore return value and suppress output:
+#
+
+#
+# Note that this is not a complete list of all feature tests, just
+# those that are typically built on a fully configured system.
+#
+# [ Feature tests not mentioned here have to be built explicitly in
+#   the rule that uses them - an example for that is the 'bionic'
+#   feature check. ]
+#
+CORE_FEATURE_TESTS =			\
+	backtrace			\
+	dwarf				\
+	fortify-source			\
+	glibc				\
+	gtk2				\
+	gtk2-infobar			\
+	libaudit			\
+	libbfd				\
+	libelf				\
+	libelf-getphdrnum		\
+	libelf-mmap			\
+	libnuma				\
+	libperl				\
+	libpython			\
+	libpython-version		\
+	libslang			\
+	libunwind			\
+	on-exit				\
+	stackprotector			\
+	stackprotector-all
+
+#
+# So here we detect whether test-all was rebuilt, to be able
+# to skip the print-out of the long features list if the file
+# existed before and after it was built:
+#
+ifeq ($(wildcard $(OUTPUT)config/feature-checks/test-all),)
+  test-all-failed := 1
+else
+  test-all-failed := 0
+endif
+
+#
+# Special fast-path for the 'all features are available' case:
+#
+$(call feature_check,all,$(MSG))
+
+#
+# Just in case the build freshly failed, make sure we print the
+# feature matrix:
+#
+ifeq ($(feature-all), 0)
+  test-all-failed := 1
+endif
+
+ifeq ($(test-all-failed),1)
+  $(info )
+  $(info Auto-detecting system features:)
+endif
+
+ifeq ($(feature-all), 1)
+  #
+  # test-all.c passed - just set all the core feature flags to 1:
+  #
+  $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_set,$(feat)))
+else
+  $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(CORE_FEATURE_TESTS) >/dev/null 2>&1)
+  $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat)))
+endif
+
+#
+# Print the result of the feature test:
+#
+feature_print = $(eval $(feature_print_code)) $(info $(MSG))
+
+define feature_print_code
+  ifeq ($(feature-$(1)), 1)
+    MSG = $(shell printf '...%30s: [ \033[32mon\033[m  ]' $(1))
+  else
+    MSG = $(shell printf '...%30s: [ \033[31mOFF\033[m ]' $(1))
+  endif
+endef
+
+#
+# Only print out our features if we rebuilt the testcases or if a test failed:
+#
+ifeq ($(test-all-failed), 1)
+  $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_print,$(feat)))
+  $(info )
+endif
+
+ifeq ($(feature-stackprotector-all), 1)
   CFLAGS += -fstack-protector-all
 endif
 
-ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wstack-protector,-Wstack-protector),y)
+ifeq ($(feature-stackprotector), 1)
   CFLAGS += -Wstack-protector
 endif
 
-ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wvolatile-register-var,-Wvolatile-register-var),y)
-  CFLAGS += -Wvolatile-register-var
-endif
-
-ifndef PERF_DEBUG
-  ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -D_FORTIFY_SOURCE=2,-D_FORTIFY_SOURCE=2),y)
+ifeq ($(DEBUG),0)
+  ifeq ($(feature-fortify-source), 1)
     CFLAGS += -D_FORTIFY_SOURCE=2
   endif
 endif
@@ -128,84 +235,74 @@
 CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
 
 ifndef NO_BIONIC
-ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS),bionic),y)
-  BIONIC := 1
-  EXTLIBS := $(filter-out -lrt,$(EXTLIBS))
-  EXTLIBS := $(filter-out -lpthread,$(EXTLIBS))
+  $(call feature_check,bionic)
+  ifeq ($(feature-bionic), 1)
+    BIONIC := 1
+    EXTLIBS := $(filter-out -lrt,$(EXTLIBS))
+    EXTLIBS := $(filter-out -lpthread,$(EXTLIBS))
+  endif
 endif
-endif # NO_BIONIC
 
 ifdef NO_LIBELF
   NO_DWARF := 1
   NO_DEMANGLE := 1
   NO_LIBUNWIND := 1
 else
-FLAGS_LIBELF=$(CFLAGS) $(LDFLAGS) $(EXTLIBS)
-ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF),libelf),y)
-  FLAGS_GLIBC=$(CFLAGS) $(LDFLAGS)
-  ifeq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC),glibc),y)
-    LIBC_SUPPORT := 1
-  endif
-  ifeq ($(BIONIC),1)
-    LIBC_SUPPORT := 1
-  endif
-  ifeq ($(LIBC_SUPPORT),1)
-    msg := $(warning No libelf found, disables 'probe' tool, please install elfutils-libelf-devel/libelf-dev);
+  ifeq ($(feature-libelf), 0)
+    ifeq ($(feature-glibc), 1)
+      LIBC_SUPPORT := 1
+    endif
+    ifeq ($(BIONIC),1)
+      LIBC_SUPPORT := 1
+    endif
+    ifeq ($(LIBC_SUPPORT),1)
+      msg := $(warning No libelf found, disables 'probe' tool, please install elfutils-libelf-devel/libelf-dev);
 
-    NO_LIBELF := 1
-    NO_DWARF := 1
-    NO_DEMANGLE := 1
+      NO_LIBELF := 1
+      NO_DWARF := 1
+      NO_DEMANGLE := 1
+    else
+      msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
+    endif
   else
-    msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
-  endif
-else
-  # for linking with debug library, run like:
-  # make DEBUG=1 LIBDW_DIR=/opt/libdw/
-  ifdef LIBDW_DIR
-    LIBDW_CFLAGS  := -I$(LIBDW_DIR)/include
-    LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
-  endif
+    # for linking with debug library, run like:
+    # make DEBUG=1 LIBDW_DIR=/opt/libdw/
+    ifdef LIBDW_DIR
+      LIBDW_CFLAGS  := -I$(LIBDW_DIR)/include
+      LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
+    endif
 
-  FLAGS_DWARF=$(CFLAGS) $(LIBDW_CFLAGS) -ldw -lz -lelf $(LIBDW_LDFLAGS) $(LDFLAGS) $(EXTLIBS)
-  ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF),libdw),y)
-    msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
-    NO_DWARF := 1
-  endif # Dwarf support
-endif # SOURCE_LIBELF
+    ifneq ($(feature-dwarf), 1)
+      msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
+      NO_DWARF := 1
+    endif # Dwarf support
+  endif # libelf support
 endif # NO_LIBELF
 
 ifndef NO_LIBELF
-CFLAGS += -DLIBELF_SUPPORT
-FLAGS_LIBELF=$(CFLAGS) $(LDFLAGS) $(EXTLIBS)
-ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_LIBELF),-DLIBELF_MMAP),y)
-  CFLAGS += -DLIBELF_MMAP
-endif
-ifeq ($(call try-cc,$(SOURCE_ELF_GETPHDRNUM),$(FLAGS_LIBELF),-DHAVE_ELF_GETPHDRNUM),y)
-  CFLAGS += -DHAVE_ELF_GETPHDRNUM
-endif
+  CFLAGS += -DHAVE_LIBELF_SUPPORT
 
-# include ARCH specific config
--include $(src-perf)/arch/$(ARCH)/Makefile
+  ifeq ($(feature-libelf-mmap), 1)
+    CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT
+  endif
 
-ifndef NO_DWARF
-ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
-  msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
-  NO_DWARF := 1
-else
-  CFLAGS += -DDWARF_SUPPORT $(LIBDW_CFLAGS)
-  LDFLAGS += $(LIBDW_LDFLAGS)
-  EXTLIBS += -lelf -ldw
-endif # PERF_HAVE_DWARF_REGS
-endif # NO_DWARF
+  ifeq ($(feature-libelf-getphdrnum), 1)
+    CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT
+  endif
 
-endif # NO_LIBELF
+  # include ARCH specific config
+  -include $(src-perf)/arch/$(ARCH)/Makefile
 
-ifndef NO_LIBELF
-CFLAGS += -DLIBELF_SUPPORT
-FLAGS_LIBELF=$(CFLAGS) $(LDFLAGS) $(EXTLIBS)
-ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_LIBELF),-DLIBELF_MMAP),y)
-  CFLAGS += -DLIBELF_MMAP
-endif # try-cc
+  ifndef NO_DWARF
+    ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
+      msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
+      NO_DWARF := 1
+    else
+      CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS)
+      LDFLAGS += $(LIBDW_LDFLAGS)
+      EXTLIBS += -lelf -ldw
+    endif # PERF_HAVE_DWARF_REGS
+  endif # NO_DWARF
 endif # NO_LIBELF
 
 # There's only x86 (both 32 and 64) support for CFI unwind so far
@@ -214,34 +311,35 @@
 endif
 
 ifndef NO_LIBUNWIND
-# for linking with debug library, run like:
-# make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/
-ifdef LIBUNWIND_DIR
-  LIBUNWIND_CFLAGS  := -I$(LIBUNWIND_DIR)/include
-  LIBUNWIND_LDFLAGS := -L$(LIBUNWIND_DIR)/lib
+  #
+  # For linking with debug library, run like:
+  #
+  #   make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/
+  #
+  ifdef LIBUNWIND_DIR
+    LIBUNWIND_CFLAGS  := -I$(LIBUNWIND_DIR)/include
+    LIBUNWIND_LDFLAGS := -L$(LIBUNWIND_DIR)/lib
+  endif
+
+  ifneq ($(feature-libunwind), 1)
+    msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 0.99);
+    NO_LIBUNWIND := 1
+  endif
 endif
 
-FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(CFLAGS) $(LIBUNWIND_LDFLAGS) $(LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS)
-ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND),libunwind),y)
-  msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 0.99);
-  NO_LIBUNWIND := 1
-endif # Libunwind support
-endif # NO_LIBUNWIND
-
 ifndef NO_LIBUNWIND
-  CFLAGS += -DLIBUNWIND_SUPPORT
+  CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
   EXTLIBS += $(LIBUNWIND_LIBS)
   CFLAGS += $(LIBUNWIND_CFLAGS)
   LDFLAGS += $(LIBUNWIND_LDFLAGS)
-endif # NO_LIBUNWIND
+endif
 
 ifndef NO_LIBAUDIT
-  FLAGS_LIBAUDIT = $(CFLAGS) $(LDFLAGS) -laudit
-  ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT),libaudit),y)
+  ifneq ($(feature-libaudit), 1)
     msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev);
     NO_LIBAUDIT := 1
   else
-    CFLAGS += -DLIBAUDIT_SUPPORT
+    CFLAGS += -DHAVE_LIBAUDIT_SUPPORT
     EXTLIBS += -laudit
   endif
 endif
@@ -251,30 +349,30 @@
 endif
 
 ifndef NO_SLANG
-  FLAGS_SLANG=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) -I/usr/include/slang -lslang
-  ifneq ($(call try-cc,$(SOURCE_SLANG),$(FLAGS_SLANG),libslang),y)
+  ifneq ($(feature-libslang), 1)
     msg := $(warning slang not found, disables TUI support. Please install slang-devel or libslang-dev);
     NO_SLANG := 1
   else
     # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h
     CFLAGS += -I/usr/include/slang
-    CFLAGS += -DSLANG_SUPPORT
+    CFLAGS += -DHAVE_SLANG_SUPPORT
     EXTLIBS += -lslang
   endif
 endif
 
 ifndef NO_GTK2
   FLAGS_GTK2=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
-  ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2),gtk2),y)
+  ifneq ($(feature-gtk2), 1)
     msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
     NO_GTK2 := 1
   else
-    ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2),-DHAVE_GTK_INFO_BAR),y)
-      CFLAGS += -DHAVE_GTK_INFO_BAR
+    ifeq ($(feature-gtk2-infobar), 1)
+      GTK_CFLAGS := -DHAVE_GTK_INFO_BAR_SUPPORT
     endif
-    CFLAGS += -DGTK2_SUPPORT
-    CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null)
-    EXTLIBS += $(shell pkg-config --libs gtk+-2.0 2>/dev/null)
+    CFLAGS += -DHAVE_GTK2_SUPPORT
+    GTK_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null)
+    GTK_LIBS := $(shell pkg-config --libs gtk+-2.0 2>/dev/null)
+    EXTLIBS += -ldl
   endif
 endif
 
@@ -290,7 +388,7 @@
   PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
   FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
 
-  ifneq ($(call try-cc,$(SOURCE_PERL_EMBED),$(FLAGS_PERL_EMBED),perl),y)
+  ifneq ($(feature-libperl), 1)
     CFLAGS += -DNO_LIBPERL
     NO_LIBPERL := 1
   else
@@ -299,6 +397,13 @@
   endif
 endif
 
+$(call feature_check,timerfd)
+ifeq ($(feature-timerfd), 1)
+  CFLAGS += -DHAVE_TIMERFD_SUPPORT
+else
+  msg := $(warning No timerfd support. Disables 'perf kvm stat live');
+endif
+
 disable-python = $(eval $(disable-python_code))
 define disable-python_code
   CFLAGS += -DNO_LIBPYTHON
@@ -335,11 +440,11 @@
       PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
       FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
 
-      ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED),python),y)
+      ifneq ($(feature-libpython), 1)
         $(call disable-python,Python.h (for Python 2.x))
       else
 
-        ifneq ($(call try-cc,$(SOURCE_PYTHON_VERSION),$(FLAGS_PYTHON_EMBED),python version),y)
+        ifneq ($(feature-libpython-version), 1)
           $(warning Python 3 is not yet supported; please set)
           $(warning PYTHON and/or PYTHON_CONFIG appropriately.)
           $(warning If you also have Python 2 installed, then)
@@ -362,33 +467,30 @@
   endif
 endif
 
+ifeq ($(feature-libbfd), 1)
+  EXTLIBS += -lbfd
+endif
+
 ifdef NO_DEMANGLE
   CFLAGS += -DNO_DEMANGLE
 else
-  ifdef HAVE_CPLUS_DEMANGLE
+  ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
     EXTLIBS += -liberty
-    CFLAGS += -DHAVE_CPLUS_DEMANGLE
+    CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
   else
-    FLAGS_BFD=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) -DPACKAGE='perf' -lbfd
-    has_bfd := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD),libbfd)
-    ifeq ($(has_bfd),y)
-      EXTLIBS += -lbfd
-    else
-      FLAGS_BFD_IBERTY=$(FLAGS_BFD) -liberty
-      has_bfd_iberty := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY),liberty)
-      ifeq ($(has_bfd_iberty),y)
+    ifneq ($(feature-libbfd), 1)
+      $(call feature_check,liberty)
+      ifeq ($(feature-liberty), 1)
         EXTLIBS += -lbfd -liberty
       else
-        FLAGS_BFD_IBERTY_Z=$(FLAGS_BFD_IBERTY) -lz
-        has_bfd_iberty_z := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY_Z),libz)
-        ifeq ($(has_bfd_iberty_z),y)
+        $(call feature_check,liberty-z)
+        ifeq ($(feature-liberty-z), 1)
           EXTLIBS += -lbfd -liberty -lz
         else
-          FLAGS_CPLUS_DEMANGLE=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) -liberty
-          has_cplus_demangle := $(call try-cc,$(SOURCE_CPLUS_DEMANGLE),$(FLAGS_CPLUS_DEMANGLE),demangle)
-          ifeq ($(has_cplus_demangle),y)
+          $(call feature_check,cplus-demangle)
+          ifeq ($(feature-cplus-demangle), 1)
             EXTLIBS += -liberty
-            CFLAGS += -DHAVE_CPLUS_DEMANGLE
+            CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
           else
             msg := $(warning No bfd.h/libbfd found, install binutils-dev[el]/zlib-static to gain symbol demangling)
             CFLAGS += -DNO_DEMANGLE
@@ -399,31 +501,28 @@
   endif
 endif
 
-ifndef NO_STRLCPY
-  ifeq ($(call try-cc,$(SOURCE_STRLCPY),,-DHAVE_STRLCPY),y)
-    CFLAGS += -DHAVE_STRLCPY
-  endif
+ifneq ($(filter -lbfd,$(EXTLIBS)),)
+  CFLAGS += -DHAVE_LIBBFD_SUPPORT
 endif
 
 ifndef NO_ON_EXIT
-  ifeq ($(call try-cc,$(SOURCE_ON_EXIT),,-DHAVE_ON_EXIT),y)
-    CFLAGS += -DHAVE_ON_EXIT
+  ifeq ($(feature-on-exit), 1)
+    CFLAGS += -DHAVE_ON_EXIT_SUPPORT
   endif
 endif
 
 ifndef NO_BACKTRACE
-  ifeq ($(call try-cc,$(SOURCE_BACKTRACE),,-DBACKTRACE_SUPPORT),y)
-    CFLAGS += -DBACKTRACE_SUPPORT
+  ifeq ($(feature-backtrace), 1)
+    CFLAGS += -DHAVE_BACKTRACE_SUPPORT
   endif
 endif
 
 ifndef NO_LIBNUMA
-  FLAGS_LIBNUMA = $(CFLAGS) $(LDFLAGS) -lnuma
-  ifneq ($(call try-cc,$(SOURCE_LIBNUMA),$(FLAGS_LIBNUMA),libnuma),y)
+  ifeq ($(feature-libnuma), 0)
     msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numa-libs-devel or libnuma-dev);
     NO_LIBNUMA := 1
   else
-    CFLAGS += -DLIBNUMA_SUPPORT
+    CFLAGS += -DHAVE_LIBNUMA_SUPPORT
     EXTLIBS += -lnuma
   endif
 endif
@@ -459,7 +558,12 @@
 sysconfdir = $(prefix)/etc
 ETC_PERFCONFIG = etc/perfconfig
 endif
+ifeq ($(IS_X86_64),1)
+lib = lib64
+else
 lib = lib
+endif
+libdir = $(prefix)/$(lib)
 
 # Shell quote (do not use $(call) to accommodate ancient setups);
 ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG))
@@ -472,6 +576,7 @@
 htmldir_SQ = $(subst ','\'',$(htmldir))
 prefix_SQ = $(subst ','\'',$(prefix))
 sysconfdir_SQ = $(subst ','\'',$(sysconfdir))
+libdir_SQ = $(subst ','\'',$(libdir))
 
 ifneq ($(filter /%,$(firstword $(perfexecdir))),)
 perfexec_instdir = $(perfexecdir)
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
new file mode 100644
index 0000000..c803f17
--- /dev/null
+++ b/tools/perf/config/feature-checks/Makefile
@@ -0,0 +1,148 @@
+
+FILES=					\
+	test-all			\
+	test-backtrace			\
+	test-bionic			\
+	test-dwarf			\
+	test-fortify-source		\
+	test-glibc			\
+	test-gtk2			\
+	test-gtk2-infobar		\
+	test-hello			\
+	test-libaudit			\
+	test-libbfd			\
+	test-liberty			\
+	test-liberty-z			\
+	test-cplus-demangle		\
+	test-libelf			\
+	test-libelf-getphdrnum		\
+	test-libelf-mmap		\
+	test-libnuma			\
+	test-libperl			\
+	test-libpython			\
+	test-libpython-version		\
+	test-libslang			\
+	test-libunwind			\
+	test-on-exit			\
+	test-stackprotector-all		\
+	test-stackprotector		\
+	test-timerfd
+
+CC := $(CC) -MD
+
+all: $(FILES)
+
+BUILD = $(CC) $(CFLAGS) $(LDFLAGS) -o $(OUTPUT)$@ $@.c
+
+###############################
+
+test-all:
+	$(BUILD) -Werror -fstack-protector -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma $(LIBUNWIND_LIBS) -lelf -laudit -I/usr/include/slang -lslang $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl
+
+test-hello:
+	$(BUILD)
+
+test-stackprotector-all:
+	$(BUILD) -Werror -fstack-protector-all
+
+test-stackprotector:
+	$(BUILD) -Werror -fstack-protector -Wstack-protector
+
+test-fortify-source:
+	$(BUILD) -O2 -Werror -D_FORTIFY_SOURCE=2
+
+test-bionic:
+	$(BUILD)
+
+test-libelf:
+	$(BUILD) -lelf
+
+test-glibc:
+	$(BUILD)
+
+test-dwarf:
+	$(BUILD) -ldw
+
+test-libelf-mmap:
+	$(BUILD) -lelf
+
+test-libelf-getphdrnum:
+	$(BUILD) -lelf
+
+test-libnuma:
+	$(BUILD) -lnuma
+
+test-libunwind:
+	$(BUILD) $(LIBUNWIND_LIBS) -lelf
+
+test-libaudit:
+	$(BUILD) -laudit
+
+test-libslang:
+	$(BUILD) -I/usr/include/slang -lslang
+
+test-gtk2:
+	$(BUILD) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
+
+test-gtk2-infobar:
+	$(BUILD) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
+
+grep-libs  = $(filter -l%,$(1))
+strip-libs = $(filter-out -l%,$(1))
+
+PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null)
+PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS))
+PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS))
+PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
+FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
+
+test-libperl:
+	$(BUILD) $(FLAGS_PERL_EMBED)
+
+override PYTHON := python
+override PYTHON_CONFIG := python-config
+
+escape-for-shell-sq =  $(subst ','\'',$(1))
+shell-sq = '$(escape-for-shell-sq)'
+
+PYTHON_CONFIG_SQ = $(call shell-sq,$(PYTHON_CONFIG))
+
+PYTHON_EMBED_LDOPTS = $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
+PYTHON_EMBED_LDFLAGS = $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
+PYTHON_EMBED_LIBADD = $(call grep-libs,$(PYTHON_EMBED_LDOPTS))
+PYTHON_EMBED_CCOPTS = $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
+FLAGS_PYTHON_EMBED = $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
+
+test-libpython:
+	$(BUILD) $(FLAGS_PYTHON_EMBED)
+
+test-libpython-version:
+	$(BUILD) $(FLAGS_PYTHON_EMBED)
+
+test-libbfd:
+	$(BUILD) -DPACKAGE='"perf"' -lbfd -ldl
+
+test-liberty:
+	$(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty
+
+test-liberty-z:
+	$(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz
+
+test-cplus-demangle:
+	$(BUILD) -liberty
+
+test-on-exit:
+	$(BUILD)
+
+test-backtrace:
+	$(BUILD)
+
+test-timerfd:
+	$(BUILD)
+
+-include *.d
+
+###############################
+
+clean:
+	rm -f $(FILES) *.d
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c
new file mode 100644
index 0000000..59e7a70
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-all.c
@@ -0,0 +1,111 @@
+/*
+ * test-all.c: Try to build all the main testcases at once.
+ *
+ * A well-configured system will have all the prereqs installed, so we can speed
+ * up auto-detection on such systems.
+ */
+
+/*
+ * Quirk: Python and Perl headers cannot be in arbitrary places, so keep
+ * these 3 testcases at the top:
+ */
+#define main main_test_libpython
+# include "test-libpython.c"
+#undef main
+
+#define main main_test_libpython_version
+# include "test-libpython-version.c"
+#undef main
+
+#define main main_test_libperl
+# include "test-libperl.c"
+#undef main
+
+#define main main_test_hello
+# include "test-hello.c"
+#undef main
+
+#define main main_test_libelf
+# include "test-libelf.c"
+#undef main
+
+#define main main_test_libelf_mmap
+# include "test-libelf-mmap.c"
+#undef main
+
+#define main main_test_glibc
+# include "test-glibc.c"
+#undef main
+
+#define main main_test_dwarf
+# include "test-dwarf.c"
+#undef main
+
+#define main main_test_libelf_getphdrnum
+# include "test-libelf-getphdrnum.c"
+#undef main
+
+#define main main_test_libunwind
+# include "test-libunwind.c"
+#undef main
+
+#define main main_test_libaudit
+# include "test-libaudit.c"
+#undef main
+
+#define main main_test_libslang
+# include "test-libslang.c"
+#undef main
+
+#define main main_test_gtk2
+# include "test-gtk2.c"
+#undef main
+
+#define main main_test_gtk2_infobar
+# include "test-gtk2-infobar.c"
+#undef main
+
+#define main main_test_libbfd
+# include "test-libbfd.c"
+#undef main
+
+#define main main_test_on_exit
+# include "test-on-exit.c"
+#undef main
+
+#define main main_test_backtrace
+# include "test-backtrace.c"
+#undef main
+
+#define main main_test_libnuma
+# include "test-libnuma.c"
+#undef main
+
+#define main main_test_timerfd
+# include "test-timerfd.c"
+#undef main
+
+int main(int argc, char *argv[])
+{
+	main_test_libpython();
+	main_test_libpython_version();
+	main_test_libperl();
+	main_test_hello();
+	main_test_libelf();
+	main_test_libelf_mmap();
+	main_test_glibc();
+	main_test_dwarf();
+	main_test_libelf_getphdrnum();
+	main_test_libunwind();
+	main_test_libaudit();
+	main_test_libslang();
+	main_test_gtk2(argc, argv);
+	main_test_gtk2_infobar(argc, argv);
+	main_test_libbfd();
+	main_test_on_exit();
+	main_test_backtrace();
+	main_test_libnuma();
+	main_test_timerfd();
+
+	return 0;
+}
diff --git a/tools/perf/config/feature-checks/test-backtrace.c b/tools/perf/config/feature-checks/test-backtrace.c
new file mode 100644
index 0000000..7124aa1
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-backtrace.c
@@ -0,0 +1,13 @@
+#include <execinfo.h>
+#include <stdio.h>
+
+int main(void)
+{
+	void *backtrace_fns[10];
+	size_t entries;
+
+	entries = backtrace(backtrace_fns, 10);
+	backtrace_symbols_fd(backtrace_fns, entries, 1);
+
+	return 0;
+}
diff --git a/tools/perf/config/feature-checks/test-bionic.c b/tools/perf/config/feature-checks/test-bionic.c
new file mode 100644
index 0000000..eac24e9
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-bionic.c
@@ -0,0 +1,6 @@
+#include <android/api-level.h>
+
+int main(void)
+{
+	return __ANDROID_API__;
+}
diff --git a/tools/perf/config/feature-checks/test-cplus-demangle.c b/tools/perf/config/feature-checks/test-cplus-demangle.c
new file mode 100644
index 0000000..610c686
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-cplus-demangle.c
@@ -0,0 +1,14 @@
+extern int printf(const char *format, ...);
+extern char *cplus_demangle(const char *, int);
+
+int main(void)
+{
+	char symbol[4096] = "FieldName__9ClassNameFd";
+	char *tmp;
+
+	tmp = cplus_demangle(symbol, 0);
+
+	printf("demangled symbol: {%s}\n", tmp);
+
+	return 0;
+}
diff --git a/tools/perf/config/feature-checks/test-dwarf.c b/tools/perf/config/feature-checks/test-dwarf.c
new file mode 100644
index 0000000..3fc1801
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-dwarf.c
@@ -0,0 +1,10 @@
+#include <dwarf.h>
+#include <elfutils/libdw.h>
+#include <elfutils/version.h>
+
+int main(void)
+{
+	Dwarf *dbg = dwarf_begin(0, DWARF_C_READ);
+
+	return (long)dbg;
+}
diff --git a/tools/perf/config/feature-checks/test-fortify-source.c b/tools/perf/config/feature-checks/test-fortify-source.c
new file mode 100644
index 0000000..c9f398d
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-fortify-source.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main(void)
+{
+	return puts("hi");
+}
diff --git a/tools/perf/config/feature-checks/test-glibc.c b/tools/perf/config/feature-checks/test-glibc.c
new file mode 100644
index 0000000..b082034
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-glibc.c
@@ -0,0 +1,8 @@
+#include <gnu/libc-version.h>
+
+int main(void)
+{
+	const char *version = gnu_get_libc_version();
+
+	return (long)version;
+}
diff --git a/tools/perf/config/feature-checks/test-gtk2-infobar.c b/tools/perf/config/feature-checks/test-gtk2-infobar.c
new file mode 100644
index 0000000..397b464
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-gtk2-infobar.c
@@ -0,0 +1,11 @@
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
+#include <gtk/gtk.h>
+#pragma GCC diagnostic error "-Wstrict-prototypes"
+
+int main(int argc, char *argv[])
+{
+	gtk_init(&argc, &argv);
+	gtk_info_bar_new();
+
+	return 0;
+}
diff --git a/tools/perf/config/feature-checks/test-gtk2.c b/tools/perf/config/feature-checks/test-gtk2.c
new file mode 100644
index 0000000..6bd80e5
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-gtk2.c
@@ -0,0 +1,10 @@
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
+#include <gtk/gtk.h>
+#pragma GCC diagnostic error "-Wstrict-prototypes"
+
+int main(int argc, char *argv[])
+{
+	gtk_init(&argc, &argv);
+
+        return 0;
+}
diff --git a/tools/perf/config/feature-checks/test-hello.c b/tools/perf/config/feature-checks/test-hello.c
new file mode 100644
index 0000000..c9f398d
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-hello.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main(void)
+{
+	return puts("hi");
+}
diff --git a/tools/perf/config/feature-checks/test-libaudit.c b/tools/perf/config/feature-checks/test-libaudit.c
new file mode 100644
index 0000000..afc019f
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libaudit.c
@@ -0,0 +1,10 @@
+#include <libaudit.h>
+
+extern int printf(const char *format, ...);
+
+int main(void)
+{
+	printf("error message: %s\n", audit_errno_to_name(0));
+
+	return audit_open();
+}
diff --git a/tools/perf/config/feature-checks/test-libbfd.c b/tools/perf/config/feature-checks/test-libbfd.c
new file mode 100644
index 0000000..2405990
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libbfd.c
@@ -0,0 +1,15 @@
+#include <bfd.h>
+
+extern int printf(const char *format, ...);
+
+int main(void)
+{
+	char symbol[4096] = "FieldName__9ClassNameFd";
+	char *tmp;
+
+	tmp = bfd_demangle(0, symbol, 0);
+
+	printf("demangled symbol: {%s}\n", tmp);
+
+	return 0;
+}
diff --git a/tools/perf/config/feature-checks/test-libelf-getphdrnum.c b/tools/perf/config/feature-checks/test-libelf-getphdrnum.c
new file mode 100644
index 0000000..d710459
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libelf-getphdrnum.c
@@ -0,0 +1,8 @@
+#include <libelf.h>
+
+int main(void)
+{
+	size_t dst;
+
+	return elf_getphdrnum(0, &dst);
+}
diff --git a/tools/perf/config/feature-checks/test-libelf-mmap.c b/tools/perf/config/feature-checks/test-libelf-mmap.c
new file mode 100644
index 0000000..564427d
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libelf-mmap.c
@@ -0,0 +1,8 @@
+#include <libelf.h>
+
+int main(void)
+{
+	Elf *elf = elf_begin(0, ELF_C_READ_MMAP, 0);
+
+	return (long)elf;
+}
diff --git a/tools/perf/config/feature-checks/test-libelf.c b/tools/perf/config/feature-checks/test-libelf.c
new file mode 100644
index 0000000..08db322
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libelf.c
@@ -0,0 +1,8 @@
+#include <libelf.h>
+
+int main(void)
+{
+	Elf *elf = elf_begin(0, ELF_C_READ, 0);
+
+	return (long)elf;
+}
diff --git a/tools/perf/config/feature-checks/test-libnuma.c b/tools/perf/config/feature-checks/test-libnuma.c
new file mode 100644
index 0000000..4763d9c
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libnuma.c
@@ -0,0 +1,9 @@
+#include <numa.h>
+#include <numaif.h>
+
+int main(void)
+{
+	numa_available();
+
+	return 0;
+}
diff --git a/tools/perf/config/feature-checks/test-libperl.c b/tools/perf/config/feature-checks/test-libperl.c
new file mode 100644
index 0000000..8871f6a
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libperl.c
@@ -0,0 +1,9 @@
+#include <EXTERN.h>
+#include <perl.h>
+
+int main(void)
+{
+	perl_alloc();
+
+	return 0;
+}
diff --git a/tools/perf/config/feature-checks/test-libpython-version.c b/tools/perf/config/feature-checks/test-libpython-version.c
new file mode 100644
index 0000000..facea12
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libpython-version.c
@@ -0,0 +1,10 @@
+#include <Python.h>
+
+#if PY_VERSION_HEX >= 0x03000000
+	#error
+#endif
+
+int main(void)
+{
+	return 0;
+}
diff --git a/tools/perf/config/feature-checks/test-libpython.c b/tools/perf/config/feature-checks/test-libpython.c
new file mode 100644
index 0000000..b24b28a
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libpython.c
@@ -0,0 +1,8 @@
+#include <Python.h>
+
+int main(void)
+{
+	Py_Initialize();
+
+	return 0;
+}
diff --git a/tools/perf/config/feature-checks/test-libslang.c b/tools/perf/config/feature-checks/test-libslang.c
new file mode 100644
index 0000000..22ff22e
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libslang.c
@@ -0,0 +1,6 @@
+#include <slang.h>
+
+int main(void)
+{
+	return SLsmg_init_smg();
+}
diff --git a/tools/perf/config/feature-checks/test-libunwind.c b/tools/perf/config/feature-checks/test-libunwind.c
new file mode 100644
index 0000000..43b9369
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libunwind.c
@@ -0,0 +1,27 @@
+#include <libunwind.h>
+#include <stdlib.h>
+
+extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
+                                      unw_word_t ip,
+                                      unw_dyn_info_t *di,
+                                      unw_proc_info_t *pi,
+                                      int need_unwind_info, void *arg);
+
+
+#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
+
+static unw_accessors_t accessors;
+
+int main(void)
+{
+	unw_addr_space_t addr_space;
+
+	addr_space = unw_create_addr_space(&accessors, 0);
+	if (addr_space)
+		return 0;
+
+	unw_init_remote(NULL, addr_space, NULL);
+	dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
+
+	return 0;
+}
diff --git a/tools/perf/config/feature-checks/test-on-exit.c b/tools/perf/config/feature-checks/test-on-exit.c
new file mode 100644
index 0000000..8e88b16
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-on-exit.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+static void exit_fn(int status, void *__data)
+{
+	printf("exit status: %d, data: %d\n", status, *(int *)__data);
+}
+
+static int data = 123;
+
+int main(void)
+{
+	on_exit(exit_fn, &data);
+
+	return 321;
+}
diff --git a/tools/perf/config/feature-checks/test-stackprotector-all.c b/tools/perf/config/feature-checks/test-stackprotector-all.c
new file mode 100644
index 0000000..c9f398d
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-stackprotector-all.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main(void)
+{
+	return puts("hi");
+}
diff --git a/tools/perf/config/feature-checks/test-stackprotector.c b/tools/perf/config/feature-checks/test-stackprotector.c
new file mode 100644
index 0000000..c9f398d
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-stackprotector.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main(void)
+{
+	return puts("hi");
+}
diff --git a/tools/perf/config/feature-checks/test-timerfd.c b/tools/perf/config/feature-checks/test-timerfd.c
new file mode 100644
index 0000000..8c5c083
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-timerfd.c
@@ -0,0 +1,18 @@
+/*
+ * test for timerfd functions used by perf-kvm-stat-live
+ */
+#include <sys/timerfd.h>
+
+int main(void)
+{
+	struct itimerspec new_value;
+
+	int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
+	if (fd < 0)
+		return 1;
+
+	if (timerfd_settime(fd, 0, &new_value, NULL) != 0)
+		return 1;
+
+	return 0;
+}
diff --git a/tools/perf/config/feature-checks/test-volatile-register-var.c b/tools/perf/config/feature-checks/test-volatile-register-var.c
new file mode 100644
index 0000000..c9f398d
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-volatile-register-var.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main(void)
+{
+	return puts("hi");
+}
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
deleted file mode 100644
index d5a8dd4..0000000
--- a/tools/perf/config/feature-tests.mak
+++ /dev/null
@@ -1,246 +0,0 @@
-define SOURCE_HELLO
-#include <stdio.h>
-int main(void)
-{
-	return puts(\"hi\");
-}
-endef
-
-ifndef NO_DWARF
-define SOURCE_DWARF
-#include <dwarf.h>
-#include <elfutils/libdw.h>
-#include <elfutils/version.h>
-#ifndef _ELFUTILS_PREREQ
-#error
-#endif
-
-int main(void)
-{
-	Dwarf *dbg = dwarf_begin(0, DWARF_C_READ);
-	return (long)dbg;
-}
-endef
-endif
-
-define SOURCE_LIBELF
-#include <libelf.h>
-
-int main(void)
-{
-	Elf *elf = elf_begin(0, ELF_C_READ, 0);
-	return (long)elf;
-}
-endef
-
-define SOURCE_GLIBC
-#include <gnu/libc-version.h>
-
-int main(void)
-{
-	const char *version = gnu_get_libc_version();
-	return (long)version;
-}
-endef
-
-define SOURCE_BIONIC
-#include <android/api-level.h>
-
-int main(void)
-{
-	return __ANDROID_API__;
-}
-endef
-
-define SOURCE_ELF_MMAP
-#include <libelf.h>
-int main(void)
-{
-	Elf *elf = elf_begin(0, ELF_C_READ_MMAP, 0);
-	return (long)elf;
-}
-endef
-
-define SOURCE_ELF_GETPHDRNUM
-#include <libelf.h>
-int main(void)
-{
-	size_t dst;
-	return elf_getphdrnum(0, &dst);
-}
-endef
-
-ifndef NO_SLANG
-define SOURCE_SLANG
-#include <slang.h>
-
-int main(void)
-{
-	return SLsmg_init_smg();
-}
-endef
-endif
-
-ifndef NO_GTK2
-define SOURCE_GTK2
-#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
-#include <gtk/gtk.h>
-#pragma GCC diagnostic error \"-Wstrict-prototypes\"
-
-int main(int argc, char *argv[])
-{
-        gtk_init(&argc, &argv);
-
-        return 0;
-}
-endef
-
-define SOURCE_GTK2_INFOBAR
-#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
-#include <gtk/gtk.h>
-#pragma GCC diagnostic error \"-Wstrict-prototypes\"
-
-int main(void)
-{
-	gtk_info_bar_new();
-
-	return 0;
-}
-endef
-endif
-
-ifndef NO_LIBPERL
-define SOURCE_PERL_EMBED
-#include <EXTERN.h>
-#include <perl.h>
-
-int main(void)
-{
-perl_alloc();
-return 0;
-}
-endef
-endif
-
-ifndef NO_LIBPYTHON
-define SOURCE_PYTHON_VERSION
-#include <Python.h>
-#if PY_VERSION_HEX >= 0x03000000
-	#error
-#endif
-int main(void)
-{
-	return 0;
-}
-endef
-define SOURCE_PYTHON_EMBED
-#include <Python.h>
-int main(void)
-{
-	Py_Initialize();
-	return 0;
-}
-endef
-endif
-
-define SOURCE_BFD
-#include <bfd.h>
-
-int main(void)
-{
-	bfd_demangle(0, 0, 0);
-	return 0;
-}
-endef
-
-define SOURCE_CPLUS_DEMANGLE
-extern char *cplus_demangle(const char *, int);
-
-int main(void)
-{
-	cplus_demangle(0, 0);
-	return 0;
-}
-endef
-
-define SOURCE_STRLCPY
-#include <stdlib.h>
-extern size_t strlcpy(char *dest, const char *src, size_t size);
-
-int main(void)
-{
-	strlcpy(NULL, NULL, 0);
-	return 0;
-}
-endef
-
-ifndef NO_LIBUNWIND
-define SOURCE_LIBUNWIND
-#include <libunwind.h>
-#include <stdlib.h>
-
-extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
-                                      unw_word_t ip,
-                                      unw_dyn_info_t *di,
-                                      unw_proc_info_t *pi,
-                                      int need_unwind_info, void *arg);
-
-
-#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
-
-int main(void)
-{
-	unw_addr_space_t addr_space;
-	addr_space = unw_create_addr_space(NULL, 0);
-	unw_init_remote(NULL, addr_space, NULL);
-	dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
-	return 0;
-}
-endef
-endif
-
-ifndef NO_BACKTRACE
-define SOURCE_BACKTRACE
-#include <execinfo.h>
-#include <stdio.h>
-
-int main(void)
-{
-	backtrace(NULL, 0);
-	backtrace_symbols(NULL, 0);
-	return 0;
-}
-endef
-endif
-
-ifndef NO_LIBAUDIT
-define SOURCE_LIBAUDIT
-#include <libaudit.h>
-
-int main(void)
-{
-	printf(\"error message: %s\n\", audit_errno_to_name(0));
-	return audit_open();
-}
-endef
-endif
-
-define SOURCE_ON_EXIT
-#include <stdio.h>
-
-int main(void)
-{
-	return on_exit(NULL, NULL);
-}
-endef
-
-define SOURCE_LIBNUMA
-#include <numa.h>
-#include <numaif.h>
-
-int main(void)
-{
-	numa_available();
-	return 0;
-}
-endef
diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak
index 94d2d4f..f168deb 100644
--- a/tools/perf/config/utilities.mak
+++ b/tools/perf/config/utilities.mak
@@ -179,16 +179,9 @@
 _gea_warn = $(warning The path '$(1)' is not executable.)
 _gea_err  = $(if $(1),$(error Please set '$(1)' appropriately))
 
-# try-cc
-# Usage: option = $(call try-cc, source-to-build, cc-options, msg)
-ifneq ($(V),1)
-TRY_CC_OUTPUT= > /dev/null 2>&1
+ifneq ($(findstring $(MAKEFLAGS),s),s)
+  ifneq ($(V),1)
+    QUIET_CLEAN		= @printf '  CLEAN    %s\n' $1;
+    QUIET_INSTALL	= @printf '  INSTALL  %s\n' $1;
+  endif
 endif
-TRY_CC_MSG=echo "    CHK $(3)" 1>&2;
-
-try-cc = $(shell sh -c						  \
-	'TMP="$(OUTPUT)$(TMPOUT).$$$$";				  \
-	 $(TRY_CC_MSG)						  \
-	 echo "$(1)" |						  \
-	 $(CC) -x c - $(2) -o "$$TMP" $(TRY_CC_OUTPUT) && echo y; \
-	 rm -f "$$TMP"')
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 85e1aed..8b38b4e 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -49,14 +49,14 @@
 	{ "version",	cmd_version,	0 },
 	{ "script",	cmd_script,	0 },
 	{ "sched",	cmd_sched,	0 },
-#ifdef LIBELF_SUPPORT
+#ifdef HAVE_LIBELF_SUPPORT
 	{ "probe",	cmd_probe,	0 },
 #endif
 	{ "kmem",	cmd_kmem,	0 },
 	{ "lock",	cmd_lock,	0 },
 	{ "kvm",	cmd_kvm,	0 },
 	{ "test",	cmd_test,	0 },
-#ifdef LIBAUDIT_SUPPORT
+#ifdef HAVE_LIBAUDIT_SUPPORT
 	{ "trace",	cmd_trace,	0 },
 #endif
 	{ "inject",	cmd_inject,	0 },
@@ -456,6 +456,7 @@
 {
 	const char *cmd;
 
+	/* The page_size is placed in util object. */
 	page_size = sysconf(_SC_PAGE_SIZE);
 
 	cmd = perf_extract_argv0_path(argv[0]);
@@ -480,7 +481,14 @@
 		fprintf(stderr, "cannot handle %s internally", cmd);
 		goto out;
 	}
-
+#ifdef HAVE_LIBAUDIT_SUPPORT
+	if (!prefixcmp(cmd, "trace")) {
+		set_buildid_dir();
+		setup_path();
+		argv[0] = "trace";
+		return cmd_trace(argc, argv, NULL);
+	}
+#endif
 	/* Look for flags.. */
 	argv++;
 	argc--;
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index cf20187..6a587e84 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -4,6 +4,8 @@
 #include <asm/unistd.h>
 
 #if defined(__i386__)
+#define mb()		asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
+#define wmb()		asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
 #define rmb()		asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
 #define cpu_relax()	asm volatile("rep; nop" ::: "memory");
 #define CPUINFO_PROC	"model name"
@@ -13,6 +15,8 @@
 #endif
 
 #if defined(__x86_64__)
+#define mb()		asm volatile("mfence" ::: "memory")
+#define wmb()		asm volatile("sfence" ::: "memory")
 #define rmb()		asm volatile("lfence" ::: "memory")
 #define cpu_relax()	asm volatile("rep; nop" ::: "memory");
 #define CPUINFO_PROC	"model name"
@@ -23,45 +27,61 @@
 
 #ifdef __powerpc__
 #include "../../arch/powerpc/include/uapi/asm/unistd.h"
+#define mb()		asm volatile ("sync" ::: "memory")
+#define wmb()		asm volatile ("sync" ::: "memory")
 #define rmb()		asm volatile ("sync" ::: "memory")
-#define cpu_relax()	asm volatile ("" ::: "memory");
 #define CPUINFO_PROC	"cpu"
 #endif
 
 #ifdef __s390__
+#define mb()		asm volatile("bcr 15,0" ::: "memory")
+#define wmb()		asm volatile("bcr 15,0" ::: "memory")
 #define rmb()		asm volatile("bcr 15,0" ::: "memory")
-#define cpu_relax()	asm volatile("" ::: "memory");
 #endif
 
 #ifdef __sh__
 #if defined(__SH4A__) || defined(__SH5__)
+# define mb()		asm volatile("synco" ::: "memory")
+# define wmb()		asm volatile("synco" ::: "memory")
 # define rmb()		asm volatile("synco" ::: "memory")
 #else
+# define mb()		asm volatile("" ::: "memory")
+# define wmb()		asm volatile("" ::: "memory")
 # define rmb()		asm volatile("" ::: "memory")
 #endif
-#define cpu_relax()	asm volatile("" ::: "memory")
 #define CPUINFO_PROC	"cpu type"
 #endif
 
 #ifdef __hppa__
+#define mb()		asm volatile("" ::: "memory")
+#define wmb()		asm volatile("" ::: "memory")
 #define rmb()		asm volatile("" ::: "memory")
-#define cpu_relax()	asm volatile("" ::: "memory");
 #define CPUINFO_PROC	"cpu"
 #endif
 
 #ifdef __sparc__
+#ifdef __LP64__
+#define mb()		asm volatile("ba,pt %%xcc, 1f\n"	\
+				     "membar #StoreLoad\n"	\
+				     "1:\n":::"memory")
+#else
+#define mb()		asm volatile("":::"memory")
+#endif
+#define wmb()		asm volatile("":::"memory")
 #define rmb()		asm volatile("":::"memory")
-#define cpu_relax()	asm volatile("":::"memory")
 #define CPUINFO_PROC	"cpu"
 #endif
 
 #ifdef __alpha__
+#define mb()		asm volatile("mb" ::: "memory")
+#define wmb()		asm volatile("wmb" ::: "memory")
 #define rmb()		asm volatile("mb" ::: "memory")
-#define cpu_relax()	asm volatile("" ::: "memory")
 #define CPUINFO_PROC	"cpu model"
 #endif
 
 #ifdef __ia64__
+#define mb()		asm volatile ("mf" ::: "memory")
+#define wmb()		asm volatile ("mf" ::: "memory")
 #define rmb()		asm volatile ("mf" ::: "memory")
 #define cpu_relax()	asm volatile ("hint @pause" ::: "memory")
 #define CPUINFO_PROC	"model name"
@@ -72,40 +92,55 @@
  * Use the __kuser_memory_barrier helper in the CPU helper page. See
  * arch/arm/kernel/entry-armv.S in the kernel source for details.
  */
+#define mb()		((void(*)(void))0xffff0fa0)()
+#define wmb()		((void(*)(void))0xffff0fa0)()
 #define rmb()		((void(*)(void))0xffff0fa0)()
-#define cpu_relax()	asm volatile("":::"memory")
 #define CPUINFO_PROC	"Processor"
 #endif
 
 #ifdef __aarch64__
-#define rmb()		asm volatile("dmb ld" ::: "memory")
+#define mb()		asm volatile("dmb ish" ::: "memory")
+#define wmb()		asm volatile("dmb ishld" ::: "memory")
+#define rmb()		asm volatile("dmb ishst" ::: "memory")
 #define cpu_relax()	asm volatile("yield" ::: "memory")
 #endif
 
 #ifdef __mips__
-#define rmb()		asm volatile(					\
+#define mb()		asm volatile(					\
 				".set	mips2\n\t"			\
 				"sync\n\t"				\
 				".set	mips0"				\
 				: /* no output */			\
 				: /* no input */			\
 				: "memory")
-#define cpu_relax()	asm volatile("" ::: "memory")
+#define wmb()	mb()
+#define rmb()	mb()
 #define CPUINFO_PROC	"cpu model"
 #endif
 
 #ifdef __arc__
+#define mb()		asm volatile("" ::: "memory")
+#define wmb()		asm volatile("" ::: "memory")
 #define rmb()		asm volatile("" ::: "memory")
-#define cpu_relax()	rmb()
 #define CPUINFO_PROC	"Processor"
 #endif
 
 #ifdef __metag__
+#define mb()		asm volatile("" ::: "memory")
+#define wmb()		asm volatile("" ::: "memory")
 #define rmb()		asm volatile("" ::: "memory")
-#define cpu_relax()	asm volatile("" ::: "memory")
 #define CPUINFO_PROC	"CPU"
 #endif
 
+#define barrier() asm volatile ("" ::: "memory")
+
+#ifndef cpu_relax
+#define cpu_relax() barrier()
+#endif
+
+#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
+
+
 #include <time.h>
 #include <unistd.h>
 #include <sys/types.h>
@@ -182,7 +217,9 @@
 struct branch_flags {
 	u64 mispred:1;
 	u64 predicted:1;
-	u64 reserved:62;
+	u64 in_tx:1;
+	u64 abort:1;
+	u64 reserved:60;
 };
 
 struct branch_entry {
@@ -218,7 +255,6 @@
 	bool	     no_delay;
 	bool	     no_inherit;
 	bool	     no_samples;
-	bool	     pipe_output;
 	bool	     raw_samples;
 	bool	     sample_address;
 	bool	     sample_weight;
@@ -231,6 +267,7 @@
 	u64	     default_interval;
 	u64	     user_interval;
 	u16	     stack_dump_size;
+	bool	     sample_transaction;
 };
 
 #endif
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Context.c b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
index 315067b..fcd1dd6 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/Context.c
+++ b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
@@ -25,7 +25,7 @@
 
 PyMODINIT_FUNC initperf_trace_context(void);
 
-static PyObject *perf_trace_context_common_pc(PyObject *self, PyObject *args)
+static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args)
 {
 	static struct scripting_context *scripting_context;
 	PyObject *context;
@@ -40,7 +40,7 @@
 	return Py_BuildValue("i", retval);
 }
 
-static PyObject *perf_trace_context_common_flags(PyObject *self,
+static PyObject *perf_trace_context_common_flags(PyObject *obj,
 						 PyObject *args)
 {
 	static struct scripting_context *scripting_context;
@@ -56,7 +56,7 @@
 	return Py_BuildValue("i", retval);
 }
 
-static PyObject *perf_trace_context_common_lock_depth(PyObject *self,
+static PyObject *perf_trace_context_common_lock_depth(PyObject *obj,
 						      PyObject *args)
 {
 	static struct scripting_context *scripting_context;
diff --git a/tools/perf/tests/attr/README b/tools/perf/tests/attr/README
index d102957..430024f 100644
--- a/tools/perf/tests/attr/README
+++ b/tools/perf/tests/attr/README
@@ -44,9 +44,9 @@
   perf record -c 123 kill                       (test-record-count)
   perf record -d kill                           (test-record-data)
   perf record -F 100 kill                       (test-record-freq)
-  perf record -g -- kill                        (test-record-graph-default)
-  perf record -g dwarf -- kill                  (test-record-graph-dwarf)
-  perf record -g fp kill                        (test-record-graph-fp)
+  perf record -g kill                           (test-record-graph-default)
+  perf record --call-graph dwarf kill		(test-record-graph-dwarf)
+  perf record --call-graph fp kill              (test-record-graph-fp)
   perf record --group -e cycles,instructions kill (test-record-group)
   perf record -e '{cycles,instructions}' kill   (test-record-group1)
   perf record -D kill                           (test-record-no-delay)
diff --git a/tools/perf/tests/attr/test-record-graph-default b/tools/perf/tests/attr/test-record-graph-default
index 833d184..853597a 100644
--- a/tools/perf/tests/attr/test-record-graph-default
+++ b/tools/perf/tests/attr/test-record-graph-default
@@ -1,6 +1,6 @@
 [config]
 command = record
-args    = -g -- kill >/dev/null 2>&1
+args    = -g kill >/dev/null 2>&1
 
 [event:base-record]
 sample_type=295
diff --git a/tools/perf/tests/attr/test-record-graph-dwarf b/tools/perf/tests/attr/test-record-graph-dwarf
index e93e082..d6f324e 100644
--- a/tools/perf/tests/attr/test-record-graph-dwarf
+++ b/tools/perf/tests/attr/test-record-graph-dwarf
@@ -1,6 +1,6 @@
 [config]
 command = record
-args    = -g dwarf -- kill >/dev/null 2>&1
+args    = --call-graph dwarf -- kill >/dev/null 2>&1
 
 [event:base-record]
 sample_type=12583
diff --git a/tools/perf/tests/attr/test-record-graph-fp b/tools/perf/tests/attr/test-record-graph-fp
index 7cef374..055e3be 100644
--- a/tools/perf/tests/attr/test-record-graph-fp
+++ b/tools/perf/tests/attr/test-record-graph-fp
@@ -1,6 +1,6 @@
 [config]
 command = record
-args    = -g fp kill >/dev/null 2>&1
+args    = --call-graph fp kill >/dev/null 2>&1
 
 [event:base-record]
 sample_type=295
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 6fb781d..49ccc3b 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -276,7 +276,7 @@
 		return process_sample_event(machine, evlist, event, state);
 
 	if (event->header.type < PERF_RECORD_MAX)
-		return machine__process_event(machine, event);
+		return machine__process_event(machine, event, NULL);
 
 	return 0;
 }
@@ -290,6 +290,7 @@
 	for (i = 0; i < evlist->nr_mmaps; i++) {
 		while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
 			ret = process_event(machine, evlist, event, state);
+			perf_evlist__mmap_consume(evlist, i);
 			if (ret < 0)
 				return ret;
 		}
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index dffe055..9cc81a3 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -35,6 +35,7 @@
 	if (size != write(fd, buf, size))
 		templ = NULL;
 
+	free(buf);
 	close(fd);
 	return templ;
 }
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index 4228ffc..173bf42 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -93,7 +93,7 @@
 		if (thread == NULL)
 			goto out;
 
-		thread__set_comm(thread, fake_threads[i].comm);
+		thread__set_comm(thread, fake_threads[i].comm, 0);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(fake_mmap_info); i++) {
@@ -110,7 +110,7 @@
 		strcpy(fake_mmap_event.mmap.filename,
 		       fake_mmap_info[i].filename);
 
-		machine__process_mmap_event(machine, &fake_mmap_event);
+		machine__process_mmap_event(machine, &fake_mmap_event, NULL);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(fake_symbols); i++) {
@@ -222,7 +222,8 @@
 							  &sample) < 0)
 				goto out;
 
-			he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1);
+			he = __hists__add_entry(&evsel->hists, &al, NULL,
+						NULL, NULL, 1, 1, 0);
 			if (he == NULL)
 				goto out;
 
@@ -244,7 +245,8 @@
 							  &sample) < 0)
 				goto out;
 
-			he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1);
+			he = __hists__add_entry(&evsel->hists, &al, NULL,
+						NULL, NULL, 1, 1, 0);
 			if (he == NULL)
 				goto out;
 
@@ -419,7 +421,7 @@
 		he = rb_entry(node, struct hist_entry, rb_node_in);
 
 		pr_info("%2d: entry: %-8s [%-8s] %20s: period = %"PRIu64"\n",
-			i, he->thread->comm, he->ms.map->dso->short_name,
+			i, thread__comm_str(he->thread), he->ms.map->dso->short_name,
 			he->ms.sym->name, he->stat.period);
 
 		i++;
@@ -465,7 +467,7 @@
 		goto out;
 
 	list_for_each_entry(evsel, &evlist->entries, node) {
-		hists__collapse_resort(&evsel->hists);
+		hists__collapse_resort(&evsel->hists, NULL);
 
 		if (verbose > 2)
 			print_hists(&evsel->hists);
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c
index d444ea2..376c356 100644
--- a/tools/perf/tests/keep-tracking.c
+++ b/tools/perf/tests/keep-tracking.c
@@ -36,6 +36,7 @@
 			    (pid_t)event->comm.tid == getpid() &&
 			    strcmp(event->comm.comm, comm) == 0)
 				found += 1;
+			perf_evlist__mmap_consume(evlist, i);
 		}
 	}
 	return found;
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index c4185b9..a7232c2 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -122,6 +122,7 @@
 			goto out_munmap;
 		}
 		nr_events[evsel->idx]++;
+		perf_evlist__mmap_consume(evlist, 0);
 	}
 
 	err = 0;
diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c
index fc5b9fc..524b221 100644
--- a/tools/perf/tests/open-syscall-tp-fields.c
+++ b/tools/perf/tests/open-syscall-tp-fields.c
@@ -77,8 +77,10 @@
 
 				++nr_events;
 
-				if (type != PERF_RECORD_SAMPLE)
+				if (type != PERF_RECORD_SAMPLE) {
+					perf_evlist__mmap_consume(evlist, i);
 					continue;
+				}
 
 				err = perf_evsel__parse_sample(evsel, event, &sample);
 				if (err) {
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 48114d1..ef671cd 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -2,7 +2,7 @@
 #include "parse-events.h"
 #include "evsel.h"
 #include "evlist.h"
-#include "sysfs.h"
+#include "fs.h"
 #include <lk/debugfs.h>
 #include "tests.h"
 #include <linux/hw_breakpoint.h>
@@ -1456,7 +1456,7 @@
 	int ret;
 
 	snprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu/format/",
-		 sysfs_find_mountpoint());
+		 sysfs__mountpoint());
 
 	ret = stat(path, &st);
 	if (ret)
@@ -1473,7 +1473,7 @@
 	int ret;
 
 	snprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu/events/",
-		 sysfs_find_mountpoint());
+		 sysfs__mountpoint());
 
 	ret = stat(path, &st);
 	if (ret) {
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index b8a7056..93a62b0 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -45,7 +45,7 @@
 	};
 	cpu_set_t cpu_mask;
 	size_t cpu_mask_size = sizeof(cpu_mask);
-	struct perf_evlist *evlist = perf_evlist__new();
+	struct perf_evlist *evlist = perf_evlist__new_default();
 	struct perf_evsel *evsel;
 	struct perf_sample sample;
 	const char *cmd = "sleep";
@@ -66,16 +66,6 @@
 	}
 
 	/*
-	 * We need at least one evsel in the evlist, use the default
-	 * one: "cycles".
-	 */
-	err = perf_evlist__add_default(evlist);
-	if (err < 0) {
-		pr_debug("Not enough memory to create evsel\n");
-		goto out_delete_evlist;
-	}
-
-	/*
 	 * Create maps of threads and cpus to monitor. In this case
 	 * we start with all threads and cpus (-1, -1) but then in
 	 * perf_evlist__prepare_workload we'll fill in the only thread
@@ -263,6 +253,8 @@
 						 type);
 					++errs;
 				}
+
+				perf_evlist__mmap_consume(evlist, i);
 			}
 		}
 
diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/tests/perf-time-to-tsc.c
index 0ab61b1..4ca1b93 100644
--- a/tools/perf/tests/perf-time-to-tsc.c
+++ b/tools/perf/tests/perf-time-to-tsc.c
@@ -122,7 +122,7 @@
 			if (event->header.type != PERF_RECORD_COMM ||
 			    (pid_t)event->comm.pid != getpid() ||
 			    (pid_t)event->comm.tid != getpid())
-				continue;
+				goto next_event;
 
 			if (strcmp(event->comm.comm, comm1) == 0) {
 				CHECK__(perf_evsel__parse_sample(evsel, event,
@@ -134,6 +134,8 @@
 								 &sample));
 				comm2_time = sample.time;
 			}
+next_event:
+			perf_evlist__mmap_consume(evlist, i);
 		}
 	}
 
diff --git a/tools/perf/tests/rdpmc.c b/tools/perf/tests/rdpmc.c
index ff94886..46649c2 100644
--- a/tools/perf/tests/rdpmc.c
+++ b/tools/perf/tests/rdpmc.c
@@ -9,8 +9,6 @@
 
 #if defined(__x86_64__) || defined(__i386__)
 
-#define barrier() asm volatile("" ::: "memory")
-
 static u64 rdpmc(unsigned int counter)
 {
 	unsigned int low, high;
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c
index 77f598d..1b67720 100644
--- a/tools/perf/tests/sample-parsing.c
+++ b/tools/perf/tests/sample-parsing.c
@@ -121,6 +121,9 @@
 	if (type & PERF_SAMPLE_DATA_SRC)
 		COMP(data_src);
 
+	if (type & PERF_SAMPLE_TRANSACTION)
+		COMP(transaction);
+
 	return true;
 }
 
@@ -165,6 +168,7 @@
 		.cpu		= 110,
 		.raw_size	= sizeof(raw_data),
 		.data_src	= 111,
+		.transaction	= 112,
 		.raw_data	= (void *)raw_data,
 		.callchain	= &callchain.callchain,
 		.branch_stack	= &branch_stack.branch_stack,
@@ -273,10 +277,11 @@
 
 	/*
 	 * Fail the test if it has not been updated when new sample format bits
-	 * were added.
+	 * were added.  Please actually update the test rather than just change
+	 * the condition below.
 	 */
-	if (PERF_SAMPLE_MAX > PERF_SAMPLE_IDENTIFIER << 1) {
-		pr_debug("sample format has changed - test needs updating\n");
+	if (PERF_SAMPLE_MAX > PERF_SAMPLE_TRANSACTION << 1) {
+		pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n");
 		return -1;
 	}
 
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index 2e41e2d..6e2b44e 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -78,7 +78,7 @@
 		struct perf_sample sample;
 
 		if (event->header.type != PERF_RECORD_SAMPLE)
-			continue;
+			goto next_event;
 
 		err = perf_evlist__parse_sample(evlist, event, &sample);
 		if (err < 0) {
@@ -88,6 +88,8 @@
 
 		total_periods += sample.period;
 		nr_samples++;
+next_event:
+		perf_evlist__mmap_consume(evlist, 0);
 	}
 
 	if ((u64) nr_samples == total_periods) {
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index 28fe589..c33d95f 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -37,20 +37,11 @@
 	signal(SIGCHLD, sig_handler);
 	signal(SIGUSR1, sig_handler);
 
-	evlist = perf_evlist__new();
+	evlist = perf_evlist__new_default();
 	if (evlist == NULL) {
-		pr_debug("perf_evlist__new\n");
+		pr_debug("perf_evlist__new_default\n");
 		return -1;
 	}
-	/*
-	 * We need at least one evsel in the evlist, use the default
-	 * one: "cycles".
-	 */
-	err = perf_evlist__add_default(evlist);
-	if (err < 0) {
-		pr_debug("Not enough memory to create evsel\n");
-		goto out_free_evlist;
-	}
 
 	/*
 	 * Create maps of threads and cpus to monitor. In this case
@@ -96,10 +87,10 @@
 
 retry:
 	while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) {
-		if (event->header.type != PERF_RECORD_EXIT)
-			continue;
+		if (event->header.type == PERF_RECORD_EXIT)
+			nr_exit++;
 
-		nr_exit++;
+		perf_evlist__mmap_consume(evlist, 0);
 	}
 
 	if (!exited || !nr_exit) {
@@ -117,7 +108,6 @@
 	perf_evlist__close(evlist);
 out_delete_maps:
 	perf_evlist__delete_maps(evlist);
-out_free_evlist:
 	perf_evlist__delete(evlist);
 	return err;
 }
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index 404ff66a..7d45d2f 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -21,32 +21,32 @@
 	void	      *priv;
 	const char    *title;
 	char	      *helpline;
-	unsigned int  (*refresh)(struct ui_browser *self);
-	void	      (*write)(struct ui_browser *self, void *entry, int row);
-	void	      (*seek)(struct ui_browser *self, off_t offset, int whence);
-	bool	      (*filter)(struct ui_browser *self, void *entry);
+	unsigned int  (*refresh)(struct ui_browser *browser);
+	void	      (*write)(struct ui_browser *browser, void *entry, int row);
+	void	      (*seek)(struct ui_browser *browser, off_t offset, int whence);
+	bool	      (*filter)(struct ui_browser *browser, void *entry);
 	u32	      nr_entries;
 	bool	      navkeypressed;
 	bool	      use_navkeypressed;
 };
 
 int  ui_browser__set_color(struct ui_browser *browser, int color);
-void ui_browser__set_percent_color(struct ui_browser *self,
+void ui_browser__set_percent_color(struct ui_browser *browser,
 				   double percent, bool current);
-bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row);
-void ui_browser__refresh_dimensions(struct ui_browser *self);
-void ui_browser__reset_index(struct ui_browser *self);
+bool ui_browser__is_current_entry(struct ui_browser *browser, unsigned row);
+void ui_browser__refresh_dimensions(struct ui_browser *browser);
+void ui_browser__reset_index(struct ui_browser *browser);
 
-void ui_browser__gotorc(struct ui_browser *self, int y, int x);
+void ui_browser__gotorc(struct ui_browser *browser, int y, int x);
 void ui_browser__write_graph(struct ui_browser *browser, int graph);
 void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
 			      u64 start, u64 end);
 void __ui_browser__show_title(struct ui_browser *browser, const char *title);
 void ui_browser__show_title(struct ui_browser *browser, const char *title);
-int ui_browser__show(struct ui_browser *self, const char *title,
+int ui_browser__show(struct ui_browser *browser, const char *title,
 		     const char *helpline, ...);
-void ui_browser__hide(struct ui_browser *self);
-int ui_browser__refresh(struct ui_browser *self);
+void ui_browser__hide(struct ui_browser *browser);
+int ui_browser__refresh(struct ui_browser *browser);
 int ui_browser__run(struct ui_browser *browser, int delay_secs);
 void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries);
 void ui_browser__handle_resize(struct ui_browser *browser);
@@ -63,11 +63,11 @@
 void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence);
 unsigned int ui_browser__argv_refresh(struct ui_browser *browser);
 
-void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence);
-unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self);
+void ui_browser__rb_tree_seek(struct ui_browser *browser, off_t offset, int whence);
+unsigned int ui_browser__rb_tree_refresh(struct ui_browser *browser);
 
-void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whence);
-unsigned int ui_browser__list_head_refresh(struct ui_browser *self);
+void ui_browser__list_head_seek(struct ui_browser *browser, off_t offset, int whence);
+unsigned int ui_browser__list_head_refresh(struct ui_browser *browser);
 
 void ui_browser__init(void);
 void annotate_browser__init(void);
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 08545ae..f0697a3 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -442,35 +442,37 @@
 {
 	struct map_symbol *ms = browser->b.priv;
 	struct disasm_line *dl = browser->selection;
-	struct symbol *sym = ms->sym;
 	struct annotation *notes;
-	struct symbol *target;
-	u64 ip;
+	struct addr_map_symbol target = {
+		.map = ms->map,
+		.addr = map__objdump_2mem(ms->map, dl->ops.target.addr),
+	};
 	char title[SYM_TITLE_MAX_SIZE];
 
 	if (!ins__is_call(dl->ins))
 		return false;
 
-	ip = ms->map->map_ip(ms->map, dl->ops.target.addr);
-	target = map__find_symbol(ms->map, ip, NULL);
-	if (target == NULL) {
+	if (map_groups__find_ams(&target, NULL) ||
+	    map__rip_2objdump(target.map, target.map->map_ip(target.map,
+							     target.addr)) !=
+	    dl->ops.target.addr) {
 		ui_helpline__puts("The called function was not found.");
 		return true;
 	}
 
-	notes = symbol__annotation(target);
+	notes = symbol__annotation(target.sym);
 	pthread_mutex_lock(&notes->lock);
 
-	if (notes->src == NULL && symbol__alloc_hist(target) < 0) {
+	if (notes->src == NULL && symbol__alloc_hist(target.sym) < 0) {
 		pthread_mutex_unlock(&notes->lock);
 		ui__warning("Not enough memory for annotating '%s' symbol!\n",
-			    target->name);
+			    target.sym->name);
 		return true;
 	}
 
 	pthread_mutex_unlock(&notes->lock);
-	symbol__tui_annotate(target, ms->map, evsel, hbt);
-	sym_title(sym, ms->map, title, sizeof(title));
+	symbol__tui_annotate(target.sym, target.map, evsel, hbt);
+	sym_title(ms->sym, ms->map, title, sizeof(title));
 	ui_browser__show_title(&browser->b, title);
 	return true;
 }
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 7ef36c3..16848bb 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1255,7 +1255,7 @@
 	if (thread)
 		printed += scnprintf(bf + printed, size - printed,
 				    ", Thread: %s(%d)",
-				    (thread->comm_set ? thread->comm : ""),
+				     (thread->comm_set ? thread__comm_str(thread) : ""),
 				    thread->tid);
 	if (dso)
 		printed += scnprintf(bf + printed, size - printed,
@@ -1578,7 +1578,7 @@
 		if (thread != NULL &&
 		    asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
 			     (browser->hists->thread_filter ? "out of" : "into"),
-			     (thread->comm_set ? thread->comm : ""),
+			     (thread->comm_set ? thread__comm_str(thread) : ""),
 			     thread->tid) > 0)
 			zoom_thread = nr_options++;
 
@@ -1598,7 +1598,7 @@
 			struct symbol *sym;
 
 			if (asprintf(&options[nr_options], "Run scripts for samples of thread [%s]",
-				browser->he_selection->thread->comm) > 0)
+				     thread__comm_str(browser->he_selection->thread)) > 0)
 				scripts_comm = nr_options++;
 
 			sym = browser->he_selection->ms.sym;
@@ -1701,7 +1701,7 @@
 				sort_thread.elide = false;
 			} else {
 				ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
-						   thread->comm_set ? thread->comm : "",
+						   thread->comm_set ? thread__comm_str(thread) : "",
 						   thread->tid);
 				browser->hists->thread_filter = thread;
 				sort_thread.elide = true;
@@ -1717,7 +1717,7 @@
 			memset(script_opt, 0, 64);
 
 			if (choice == scripts_comm)
-				sprintf(script_opt, " -c %s ", browser->he_selection->thread->comm);
+				sprintf(script_opt, " -c %s ", thread__comm_str(browser->he_selection->thread));
 
 			if (choice == scripts_symbol)
 				sprintf(script_opt, " -S %s ", browser->he_selection->ms.sym->name);
@@ -1889,7 +1889,7 @@
 	return key;
 }
 
-static bool filter_group_entries(struct ui_browser *self __maybe_unused,
+static bool filter_group_entries(struct ui_browser *browser __maybe_unused,
 				 void *entry)
 {
 	struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
diff --git a/tools/perf/ui/browsers/map.c b/tools/perf/ui/browsers/map.c
index 95c7cfb..b11639f 100644
--- a/tools/perf/ui/browsers/map.c
+++ b/tools/perf/ui/browsers/map.c
@@ -18,30 +18,30 @@
 	u8		  addrlen;
 };
 
-static void map_browser__write(struct ui_browser *self, void *nd, int row)
+static void map_browser__write(struct ui_browser *browser, void *nd, int row)
 {
 	struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
-	struct map_browser *mb = container_of(self, struct map_browser, b);
-	bool current_entry = ui_browser__is_current_entry(self, row);
+	struct map_browser *mb = container_of(browser, struct map_browser, b);
+	bool current_entry = ui_browser__is_current_entry(browser, row);
 	int width;
 
-	ui_browser__set_percent_color(self, 0, current_entry);
+	ui_browser__set_percent_color(browser, 0, current_entry);
 	slsmg_printf("%*" PRIx64 " %*" PRIx64 " %c ",
 		     mb->addrlen, sym->start, mb->addrlen, sym->end,
 		     sym->binding == STB_GLOBAL ? 'g' :
 		     sym->binding == STB_LOCAL  ? 'l' : 'w');
-	width = self->width - ((mb->addrlen * 2) + 4);
+	width = browser->width - ((mb->addrlen * 2) + 4);
 	if (width > 0)
 		slsmg_write_nstring(sym->name, width);
 }
 
 /* FIXME uber-kludgy, see comment on cmd_report... */
-static u32 *symbol__browser_index(struct symbol *self)
+static u32 *symbol__browser_index(struct symbol *browser)
 {
-	return ((void *)self) - sizeof(struct rb_node) - sizeof(u32);
+	return ((void *)browser) - sizeof(struct rb_node) - sizeof(u32);
 }
 
-static int map_browser__search(struct map_browser *self)
+static int map_browser__search(struct map_browser *browser)
 {
 	char target[512];
 	struct symbol *sym;
@@ -53,37 +53,37 @@
 
 	if (target[0] == '0' && tolower(target[1]) == 'x') {
 		u64 addr = strtoull(target, NULL, 16);
-		sym = map__find_symbol(self->map, addr, NULL);
+		sym = map__find_symbol(browser->map, addr, NULL);
 	} else
-		sym = map__find_symbol_by_name(self->map, target, NULL);
+		sym = map__find_symbol_by_name(browser->map, target, NULL);
 
 	if (sym != NULL) {
 		u32 *idx = symbol__browser_index(sym);
 
-		self->b.top = &sym->rb_node;
-		self->b.index = self->b.top_idx = *idx;
+		browser->b.top = &sym->rb_node;
+		browser->b.index = browser->b.top_idx = *idx;
 	} else
 		ui_helpline__fpush("%s not found!", target);
 
 	return 0;
 }
 
-static int map_browser__run(struct map_browser *self)
+static int map_browser__run(struct map_browser *browser)
 {
 	int key;
 
-	if (ui_browser__show(&self->b, self->map->dso->long_name,
+	if (ui_browser__show(&browser->b, browser->map->dso->long_name,
 			     "Press <- or ESC to exit, %s / to search",
 			     verbose ? "" : "restart with -v to use") < 0)
 		return -1;
 
 	while (1) {
-		key = ui_browser__run(&self->b, 0);
+		key = ui_browser__run(&browser->b, 0);
 
 		switch (key) {
 		case '/':
 			if (verbose)
-				map_browser__search(self);
+				map_browser__search(browser);
 		default:
 			break;
                 case K_LEFT:
@@ -94,20 +94,20 @@
 		}
 	}
 out:
-	ui_browser__hide(&self->b);
+	ui_browser__hide(&browser->b);
 	return key;
 }
 
-int map__browse(struct map *self)
+int map__browse(struct map *map)
 {
 	struct map_browser mb = {
 		.b = {
-			.entries = &self->dso->symbols[self->type],
+			.entries = &map->dso->symbols[map->type],
 			.refresh = ui_browser__rb_tree_refresh,
 			.seek	 = ui_browser__rb_tree_seek,
 			.write	 = map_browser__write,
 		},
-		.map = self,
+		.map = map,
 	};
 	struct rb_node *nd;
 	char tmp[BITS_PER_LONG / 4];
diff --git a/tools/perf/ui/browsers/map.h b/tools/perf/ui/browsers/map.h
index df8581a..2d58e4b 100644
--- a/tools/perf/ui/browsers/map.h
+++ b/tools/perf/ui/browsers/map.h
@@ -2,5 +2,5 @@
 #define _PERF_UI_MAP_BROWSER_H_ 1
 struct map;
 
-int map__browse(struct map *self);
+int map__browse(struct map *map);
 #endif /* _PERF_UI_MAP_BROWSER_H_ */
diff --git a/tools/perf/ui/browsers/scripts.c b/tools/perf/ui/browsers/scripts.c
index 12f009e..d63c68e 100644
--- a/tools/perf/ui/browsers/scripts.c
+++ b/tools/perf/ui/browsers/scripts.c
@@ -84,22 +84,22 @@
 	slsmg_write_nstring(sline->line, browser->width);
 }
 
-static int script_browser__run(struct perf_script_browser *self)
+static int script_browser__run(struct perf_script_browser *browser)
 {
 	int key;
 
-	if (ui_browser__show(&self->b, self->script_name,
+	if (ui_browser__show(&browser->b, browser->script_name,
 			     "Press <- or ESC to exit") < 0)
 		return -1;
 
 	while (1) {
-		key = ui_browser__run(&self->b, 0);
+		key = ui_browser__run(&browser->b, 0);
 
 		/* We can add some special key handling here if needed */
 		break;
 	}
 
-	ui_browser__hide(&self->b);
+	ui_browser__hide(&browser->b);
 	return key;
 }
 
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
index f538794..9c7ff8d 100644
--- a/tools/perf/ui/gtk/annotate.c
+++ b/tools/perf/ui/gtk/annotate.c
@@ -154,9 +154,9 @@
 	return 0;
 }
 
-int symbol__gtk_annotate(struct symbol *sym, struct map *map,
-			 struct perf_evsel *evsel,
-			 struct hist_browser_timer *hbt)
+static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
+				struct perf_evsel *evsel,
+				struct hist_browser_timer *hbt)
 {
 	GtkWidget *window;
 	GtkWidget *notebook;
@@ -226,6 +226,13 @@
 	return 0;
 }
 
+int hist_entry__gtk_annotate(struct hist_entry *he,
+			     struct perf_evsel *evsel,
+			     struct hist_browser_timer *hbt)
+{
+	return symbol__gtk_annotate(he->ms.sym, he->ms.map, evsel, hbt);
+}
+
 void perf_gtk__show_annotations(void)
 {
 	GtkWidget *window;
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c
index c95012c..c24d912 100644
--- a/tools/perf/ui/gtk/browser.c
+++ b/tools/perf/ui/gtk/browser.c
@@ -43,7 +43,7 @@
 	return NULL;
 }
 
-#ifdef HAVE_GTK_INFO_BAR
+#ifdef HAVE_GTK_INFO_BAR_SUPPORT
 GtkWidget *perf_gtk__setup_info_bar(void)
 {
 	GtkWidget *info_bar;
diff --git a/tools/perf/ui/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h
index 3d96785..0a9173f 100644
--- a/tools/perf/ui/gtk/gtk.h
+++ b/tools/perf/ui/gtk/gtk.h
@@ -12,7 +12,7 @@
 	GtkWidget *main_window;
 	GtkWidget *notebook;
 
-#ifdef HAVE_GTK_INFO_BAR
+#ifdef HAVE_GTK_INFO_BAR_SUPPORT
 	GtkWidget *info_bar;
 	GtkWidget *message_label;
 #endif
@@ -20,6 +20,9 @@
 	guint statbar_ctx_id;
 };
 
+int perf_gtk__init(void);
+void perf_gtk__exit(bool wait_for_ok);
+
 extern struct perf_gtk_context *pgctx;
 
 static inline bool perf_gtk__is_active_context(struct perf_gtk_context *ctx)
@@ -31,7 +34,7 @@
 int perf_gtk__deactivate_context(struct perf_gtk_context **ctx);
 
 void perf_gtk__init_helpline(void);
-void perf_gtk__init_progress(void);
+void gtk_ui_progress__init(void);
 void perf_gtk__init_hpp(void);
 
 void perf_gtk__signal(int sig);
@@ -39,7 +42,7 @@
 const char *perf_gtk__get_percent_color(double percent);
 GtkWidget *perf_gtk__setup_statusbar(void);
 
-#ifdef HAVE_GTK_INFO_BAR
+#ifdef HAVE_GTK_INFO_BAR_SUPPORT
 GtkWidget *perf_gtk__setup_info_bar(void);
 #else
 static inline GtkWidget *perf_gtk__setup_info_bar(void)
@@ -48,4 +51,17 @@
 }
 #endif
 
+struct perf_evsel;
+struct perf_evlist;
+struct hist_entry;
+struct hist_browser_timer;
+
+int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
+				  struct hist_browser_timer *hbt,
+				  float min_pcnt);
+int hist_entry__gtk_annotate(struct hist_entry *he,
+			     struct perf_evsel *evsel,
+			     struct hist_browser_timer *hbt);
+void perf_gtk__show_annotations(void);
+
 #endif /* _PERF_GTK_H_ */
diff --git a/tools/perf/ui/gtk/progress.c b/tools/perf/ui/gtk/progress.c
index 482bcf3..b656655 100644
--- a/tools/perf/ui/gtk/progress.c
+++ b/tools/perf/ui/gtk/progress.c
@@ -7,14 +7,14 @@
 static GtkWidget *dialog;
 static GtkWidget *progress;
 
-static void gtk_progress_update(u64 curr, u64 total, const char *title)
+static void gtk_ui_progress__update(struct ui_progress *p)
 {
-	double fraction = total ? 1.0 * curr / total : 0.0;
+	double fraction = p->total ? 1.0 * p->curr / p->total : 0.0;
 	char buf[1024];
 
 	if (dialog == NULL) {
 		GtkWidget *vbox = gtk_vbox_new(TRUE, 5);
-		GtkWidget *label = gtk_label_new(title);
+		GtkWidget *label = gtk_label_new(p->title);
 
 		dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 		progress = gtk_progress_bar_new();
@@ -32,7 +32,7 @@
 	}
 
 	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), fraction);
-	snprintf(buf, sizeof(buf), "%"PRIu64" / %"PRIu64, curr, total);
+	snprintf(buf, sizeof(buf), "%"PRIu64" / %"PRIu64, p->curr, p->total);
 	gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), buf);
 
 	/* we didn't call gtk_main yet, so do it manually */
@@ -40,7 +40,7 @@
 		gtk_main_iteration();
 }
 
-static void gtk_progress_finish(void)
+static void gtk_ui_progress__finish(void)
 {
 	/* this will also destroy all of its children */
 	gtk_widget_destroy(dialog);
@@ -48,12 +48,12 @@
 	dialog = NULL;
 }
 
-static struct ui_progress gtk_progress_fns = {
-	.update		= gtk_progress_update,
-	.finish		= gtk_progress_finish,
+static struct ui_progress_ops gtk_ui_progress__ops = {
+	.update		= gtk_ui_progress__update,
+	.finish		= gtk_ui_progress__finish,
 };
 
-void perf_gtk__init_progress(void)
+void gtk_ui_progress__init(void)
 {
-	progress_fns = &gtk_progress_fns;
+	ui_progress__ops = &gtk_ui_progress__ops;
 }
diff --git a/tools/perf/ui/gtk/setup.c b/tools/perf/ui/gtk/setup.c
index 6c2dd2e..1d57676 100644
--- a/tools/perf/ui/gtk/setup.c
+++ b/tools/perf/ui/gtk/setup.c
@@ -8,7 +8,7 @@
 {
 	perf_error__register(&perf_gtk_eops);
 	perf_gtk__init_helpline();
-	perf_gtk__init_progress();
+	gtk_ui_progress__init();
 	perf_gtk__init_hpp();
 
 	return gtk_init_check(NULL, NULL) ? 0 : -1;
diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c
index c06942a..696c1fb 100644
--- a/tools/perf/ui/gtk/util.c
+++ b/tools/perf/ui/gtk/util.c
@@ -53,7 +53,7 @@
 	return 0;
 }
 
-#ifdef HAVE_GTK_INFO_BAR
+#ifdef HAVE_GTK_INFO_BAR_SUPPORT
 static int perf_gtk__warning_info_bar(const char *format, va_list args)
 {
 	char *msg;
@@ -105,7 +105,7 @@
 
 struct perf_error_ops perf_gtk_eops = {
 	.error		= perf_gtk__error,
-#ifdef HAVE_GTK_INFO_BAR
+#ifdef HAVE_GTK_INFO_BAR_SUPPORT
 	.warning	= perf_gtk__warning_info_bar,
 #else
 	.warning	= perf_gtk__warning_statusbar,
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 0a19328..78f4c92 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -117,7 +117,7 @@
 			      struct perf_hpp *hpp, struct hist_entry *he) 	\
 {										\
 	return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%",			\
-			  (hpp_snprint_fn)percent_color_snprintf, true);	\
+			  percent_color_snprintf, true);			\
 }
 
 #define __HPP_ENTRY_PERCENT_FN(_type, _field)					\
diff --git a/tools/perf/ui/progress.c b/tools/perf/ui/progress.c
index 3ec69560..a0f24c7 100644
--- a/tools/perf/ui/progress.c
+++ b/tools/perf/ui/progress.c
@@ -1,26 +1,38 @@
 #include "../cache.h"
 #include "progress.h"
 
-static void nop_progress_update(u64 curr __maybe_unused,
-				u64 total __maybe_unused,
-				const char *title __maybe_unused)
+static void null_progress__update(struct ui_progress *p __maybe_unused)
 {
 }
 
-static struct ui_progress default_progress_fns =
+static struct ui_progress_ops null_progress__ops =
 {
-	.update		= nop_progress_update,
+	.update = null_progress__update,
 };
 
-struct ui_progress *progress_fns = &default_progress_fns;
+struct ui_progress_ops *ui_progress__ops = &null_progress__ops;
 
-void ui_progress__update(u64 curr, u64 total, const char *title)
+void ui_progress__update(struct ui_progress *p, u64 adv)
 {
-	return progress_fns->update(curr, total, title);
+	p->curr += adv;
+
+	if (p->curr >= p->next) {
+		p->next += p->step;
+		ui_progress__ops->update(p);
+	}
+}
+
+void ui_progress__init(struct ui_progress *p, u64 total, const char *title)
+{
+	p->curr = 0;
+	p->next = p->step = total / 16;
+	p->total = total;
+	p->title = title;
+
 }
 
 void ui_progress__finish(void)
 {
-	if (progress_fns->finish)
-		progress_fns->finish();
+	if (ui_progress__ops->finish)
+		ui_progress__ops->finish();
 }
diff --git a/tools/perf/ui/progress.h b/tools/perf/ui/progress.h
index 257cc22..29ec8ef 100644
--- a/tools/perf/ui/progress.h
+++ b/tools/perf/ui/progress.h
@@ -3,16 +3,21 @@
 
 #include <../types.h>
 
+void ui_progress__finish(void);
+ 
 struct ui_progress {
-	void (*update)(u64, u64, const char *);
+	const char *title;
+	u64 curr, next, step, total;
+};
+ 
+void ui_progress__init(struct ui_progress *p, u64 total, const char *title);
+void ui_progress__update(struct ui_progress *p, u64 adv);
+
+struct ui_progress_ops {
+	void (*update)(struct ui_progress *p);
 	void (*finish)(void);
 };
 
-extern struct ui_progress *progress_fns;
-
-void ui_progress__init(void);
-
-void ui_progress__update(u64 curr, u64 total, const char *title);
-void ui_progress__finish(void);
+extern struct ui_progress_ops *ui_progress__ops;
 
 #endif
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index 47d9a57..5df5140 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -1,10 +1,64 @@
 #include <pthread.h>
+#include <dlfcn.h>
 
 #include "../util/cache.h"
 #include "../util/debug.h"
 #include "../util/hist.h"
 
 pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
+void *perf_gtk_handle;
+
+#ifdef HAVE_GTK2_SUPPORT
+static int setup_gtk_browser(void)
+{
+	int (*perf_ui_init)(void);
+
+	if (perf_gtk_handle)
+		return 0;
+
+	perf_gtk_handle = dlopen(PERF_GTK_DSO, RTLD_LAZY);
+	if (perf_gtk_handle == NULL) {
+		char buf[PATH_MAX];
+		scnprintf(buf, sizeof(buf), "%s/%s", LIBDIR, PERF_GTK_DSO);
+		perf_gtk_handle = dlopen(buf, RTLD_LAZY);
+	}
+	if (perf_gtk_handle == NULL)
+		return -1;
+
+	perf_ui_init = dlsym(perf_gtk_handle, "perf_gtk__init");
+	if (perf_ui_init == NULL)
+		goto out_close;
+
+	if (perf_ui_init() == 0)
+		return 0;
+
+out_close:
+	dlclose(perf_gtk_handle);
+	return -1;
+}
+
+static void exit_gtk_browser(bool wait_for_ok)
+{
+	void (*perf_ui_exit)(bool);
+
+	if (perf_gtk_handle == NULL)
+		return;
+
+	perf_ui_exit = dlsym(perf_gtk_handle, "perf_gtk__exit");
+	if (perf_ui_exit == NULL)
+		goto out_close;
+
+	perf_ui_exit(wait_for_ok);
+
+out_close:
+	dlclose(perf_gtk_handle);
+
+	perf_gtk_handle = NULL;
+}
+#else
+static inline int setup_gtk_browser(void) { return -1; }
+static inline void exit_gtk_browser(bool wait_for_ok __maybe_unused) {}
+#endif
 
 void setup_browser(bool fallback_to_pager)
 {
@@ -17,8 +71,11 @@
 
 	switch (use_browser) {
 	case 2:
-		if (perf_gtk__init() == 0)
+		if (setup_gtk_browser() == 0)
 			break;
+		printf("GTK browser requested but could not find %s\n",
+		       PERF_GTK_DSO);
+		sleep(1);
 		/* fall through */
 	case 1:
 		use_browser = 1;
@@ -39,7 +96,7 @@
 {
 	switch (use_browser) {
 	case 2:
-		perf_gtk__exit(wait_for_ok);
+		exit_gtk_browser(wait_for_ok);
 		break;
 
 	case 1:
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 194e2f4..c244cb5 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -213,20 +213,19 @@
 	return ret;
 }
 
-static size_t __callchain__fprintf_flat(FILE *fp,
-					struct callchain_node *self,
+static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node,
 					u64 total_samples)
 {
 	struct callchain_list *chain;
 	size_t ret = 0;
 
-	if (!self)
+	if (!node)
 		return 0;
 
-	ret += __callchain__fprintf_flat(fp, self->parent, total_samples);
+	ret += __callchain__fprintf_flat(fp, node->parent, total_samples);
 
 
-	list_for_each_entry(chain, &self->val, list) {
+	list_for_each_entry(chain, &node->val, list) {
 		if (chain->ip >= PERF_CONTEXT_MAX)
 			continue;
 		if (chain->ms.sym)
@@ -239,15 +238,14 @@
 	return ret;
 }
 
-static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *self,
+static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *tree,
 				      u64 total_samples)
 {
 	size_t ret = 0;
 	u32 entries_printed = 0;
-	struct rb_node *rb_node;
 	struct callchain_node *chain;
+	struct rb_node *rb_node = rb_first(tree);
 
-	rb_node = rb_first(self);
 	while (rb_node) {
 		double percent;
 
@@ -315,8 +313,7 @@
 }
 
 static int hist_entry__period_snprintf(struct perf_hpp *hpp,
-				       struct hist_entry *he,
-				       bool color)
+				       struct hist_entry *he)
 {
 	const char *sep = symbol_conf.field_sep;
 	struct perf_hpp_fmt *fmt;
@@ -338,7 +335,7 @@
 		} else
 			first = false;
 
-		if (color && fmt->color)
+		if (perf_hpp__use_color() && fmt->color)
 			ret = fmt->color(fmt, hpp, he);
 		else
 			ret = fmt->entry(fmt, hpp, he);
@@ -358,12 +355,11 @@
 		.buf		= bf,
 		.size		= size,
 	};
-	bool color = !symbol_conf.field_sep;
 
 	if (size == 0 || size > bfsz)
 		size = hpp.size = bfsz;
 
-	ret = hist_entry__period_snprintf(&hpp, he, color);
+	ret = hist_entry__period_snprintf(&hpp, he);
 	hist_entry__sort_snprintf(he, bf + ret, size - ret, hists);
 
 	ret = fprintf(fp, "%s\n", bf);
@@ -482,6 +478,7 @@
 
 print_entries:
 	linesz = hists__sort_list_width(hists) + 3 + 1;
+	linesz += perf_hpp__color_overhead();
 	line = malloc(linesz);
 	if (line == NULL) {
 		ret = -1;
diff --git a/tools/perf/ui/tui/progress.c b/tools/perf/ui/tui/progress.c
index 6c2184d..3e2d936 100644
--- a/tools/perf/ui/tui/progress.c
+++ b/tools/perf/ui/tui/progress.c
@@ -2,9 +2,10 @@
 #include "../progress.h"
 #include "../libslang.h"
 #include "../ui.h"
+#include "tui.h"
 #include "../browser.h"
 
-static void tui_progress__update(u64 curr, u64 total, const char *title)
+static void tui_progress__update(struct ui_progress *p)
 {
 	int bar, y;
 	/*
@@ -14,7 +15,7 @@
 	if (use_browser <= 0)
 		return;
 
-	if (total == 0)
+	if (p->total == 0)
 		return;
 
 	ui__refresh_dimensions(true);
@@ -23,20 +24,20 @@
 	SLsmg_set_color(0);
 	SLsmg_draw_box(y, 0, 3, SLtt_Screen_Cols);
 	SLsmg_gotorc(y++, 1);
-	SLsmg_write_string((char *)title);
+	SLsmg_write_string((char *)p->title);
 	SLsmg_set_color(HE_COLORSET_SELECTED);
-	bar = ((SLtt_Screen_Cols - 2) * curr) / total;
+	bar = ((SLtt_Screen_Cols - 2) * p->curr) / p->total;
 	SLsmg_fill_region(y, 1, 1, bar, ' ');
 	SLsmg_refresh();
 	pthread_mutex_unlock(&ui__lock);
 }
 
-static struct ui_progress tui_progress_fns =
+static struct ui_progress_ops tui_progress__ops =
 {
 	.update		= tui_progress__update,
 };
 
-void ui_progress__init(void)
+void tui_progress__init(void)
 {
-	progress_fns = &tui_progress_fns;
+	ui_progress__ops = &tui_progress__ops;
 }
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c
index b940148..2f61256 100644
--- a/tools/perf/ui/tui/setup.c
+++ b/tools/perf/ui/tui/setup.c
@@ -9,6 +9,7 @@
 #include "../util.h"
 #include "../libslang.h"
 #include "../keysyms.h"
+#include "tui.h"
 
 static volatile int ui__need_resize;
 
@@ -119,7 +120,7 @@
 
 	ui_helpline__init();
 	ui_browser__init();
-	ui_progress__init();
+	tui_progress__init();
 
 	signal(SIGSEGV, ui__signal);
 	signal(SIGFPE, ui__signal);
diff --git a/tools/perf/ui/tui/tui.h b/tools/perf/ui/tui/tui.h
new file mode 100644
index 0000000..18961c7
--- /dev/null
+++ b/tools/perf/ui/tui/tui.h
@@ -0,0 +1,6 @@
+#ifndef _PERF_TUI_H_
+#define _PERF_TUI_H_ 1
+
+void tui_progress__init(void);
+
+#endif /* _PERF_TUI_H_ */
diff --git a/tools/perf/ui/ui.h b/tools/perf/ui/ui.h
index 70cb0d4..ab88383 100644
--- a/tools/perf/ui/ui.h
+++ b/tools/perf/ui/ui.h
@@ -6,13 +6,14 @@
 #include <linux/compiler.h>
 
 extern pthread_mutex_t ui__lock;
+extern void *perf_gtk_handle;
 
 extern int use_browser;
 
 void setup_browser(bool fallback_to_pager);
 void exit_browser(bool wait_for_ok);
 
-#ifdef SLANG_SUPPORT
+#ifdef HAVE_SLANG_SUPPORT
 int ui__init(void);
 void ui__exit(bool wait_for_ok);
 #else
@@ -23,17 +24,6 @@
 static inline void ui__exit(bool wait_for_ok __maybe_unused) {}
 #endif
 
-#ifdef GTK2_SUPPORT
-int perf_gtk__init(void);
-void perf_gtk__exit(bool wait_for_ok);
-#else
-static inline int perf_gtk__init(void)
-{
-	return -1;
-}
-static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {}
-#endif
-
 void ui__refresh_dimensions(bool force);
 
 #endif /* _PERF_UI_H_ */
diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN
index 15a77b7..39f1750 100755
--- a/tools/perf/util/PERF-VERSION-GEN
+++ b/tools/perf/util/PERF-VERSION-GEN
@@ -19,6 +19,9 @@
 then
 	TAG=$(git describe --abbrev=0 --match "v[0-9].[0-9]*" 2>/dev/null )
 	CID=$(git log -1 --abbrev=4 --pretty=format:"%h" 2>/dev/null) && CID="-g$CID"
+elif test -f ../../PERF-VERSION-FILE
+then
+	TAG=$(cut -d' ' -f3 ../../PERF-VERSION-FILE | sed -e 's/\"//g')
 fi
 if test -z "$TAG"
 then
@@ -40,7 +43,7 @@
 	VC=unset
 fi
 test "$VN" = "$VC" || {
-	echo >&2 "PERF_VERSION = $VN"
+	echo >&2 "  PERF_VERSION = $VN"
 	echo "#define PERF_VERSION \"$VN\"" >$GVF
 }
 
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 7eae548..cf6242c 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -825,20 +825,16 @@
 		dl->ops.target.offset = dl->ops.target.addr -
 					map__rip_2objdump(map, sym->start);
 
-	/*
-	 * kcore has no symbols, so add the call target name if it is on the
-	 * same map.
-	 */
+	/* kcore has no symbols, so add the call target name */
 	if (dl->ins && ins__is_call(dl->ins) && !dl->ops.target.name) {
-		struct symbol *s;
-		u64 ip = dl->ops.target.addr;
+		struct addr_map_symbol target = {
+			.map = map,
+			.addr = dl->ops.target.addr,
+		};
 
-		if (ip >= map->start && ip <= map->end) {
-			ip = map->map_ip(map, ip);
-			s = map__find_symbol(map, ip, NULL);
-			if (s && s->start == ip)
-				dl->ops.target.name = strdup(s->name);
-		}
+		if (!map_groups__find_ams(&target, NULL) &&
+		    target.sym->start == target.al_addr)
+			dl->ops.target.name = strdup(target.sym->name);
 	}
 
 	disasm__add(&notes->src->source, dl);
@@ -879,6 +875,8 @@
 	FILE *file;
 	int err = 0;
 	char symfs_filename[PATH_MAX];
+	struct kcore_extract kce;
+	bool delete_extract = false;
 
 	if (filename) {
 		snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
@@ -940,6 +938,23 @@
 	pr_debug("annotating [%p] %30s : [%p] %30s\n",
 		 dso, dso->long_name, sym, sym->name);
 
+	if (dso__is_kcore(dso)) {
+		kce.kcore_filename = symfs_filename;
+		kce.addr = map__rip_2objdump(map, sym->start);
+		kce.offs = sym->start;
+		kce.len = sym->end + 1 - sym->start;
+		if (!kcore_extract__create(&kce)) {
+			delete_extract = true;
+			strlcpy(symfs_filename, kce.extract_filename,
+				sizeof(symfs_filename));
+			if (free_filename) {
+				free(filename);
+				free_filename = false;
+			}
+			filename = symfs_filename;
+		}
+	}
+
 	snprintf(command, sizeof(command),
 		 "%s %s%s --start-address=0x%016" PRIx64
 		 " --stop-address=0x%016" PRIx64
@@ -972,6 +987,8 @@
 
 	pclose(file);
 out_free_filename:
+	if (delete_extract)
+		kcore_extract__delete(&kce);
 	if (free_filename)
 		free(filename);
 	return err;
@@ -1070,7 +1087,7 @@
 			  (sizeof(src_line->p) * (src_line->nr_pcnt - 1));
 
 	for (i = 0; i < len; i++) {
-		free(src_line->path);
+		free_srcline(src_line->path);
 		src_line = (void *)src_line + sizeof_src_line;
 	}
 
@@ -1081,13 +1098,11 @@
 /* Get the filename:line for the colored entries */
 static int symbol__get_source_line(struct symbol *sym, struct map *map,
 				   struct perf_evsel *evsel,
-				   struct rb_root *root, int len,
-				   const char *filename)
+				   struct rb_root *root, int len)
 {
 	u64 start;
 	int i, k;
 	int evidx = evsel->idx;
-	char cmd[PATH_MAX * 2];
 	struct source_line *src_line;
 	struct annotation *notes = symbol__annotation(sym);
 	struct sym_hist *h = annotation__histogram(notes, evidx);
@@ -1115,10 +1130,7 @@
 	start = map__rip_2objdump(map, sym->start);
 
 	for (i = 0; i < len; i++) {
-		char *path = NULL;
-		size_t line_len;
 		u64 offset;
-		FILE *fp;
 		double percent_max = 0.0;
 
 		src_line->nr_pcnt = nr_pcnt;
@@ -1135,23 +1147,9 @@
 			goto next;
 
 		offset = start + i;
-		sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset);
-		fp = popen(cmd, "r");
-		if (!fp)
-			goto next;
-
-		if (getline(&path, &line_len, fp) < 0 || !line_len)
-			goto next_close;
-
-		src_line->path = malloc(sizeof(char) * line_len + 1);
-		if (!src_line->path)
-			goto next_close;
-
-		strcpy(src_line->path, path);
+		src_line->path = get_srcline(map->dso, offset);
 		insert_source_line(&tmp_root, src_line);
 
-	next_close:
-		pclose(fp);
 	next:
 		src_line = (void *)src_line + sizeof_src_line;
 	}
@@ -1192,7 +1190,7 @@
 
 		path = src_line->path;
 		color = get_percent_color(percent_max);
-		color_fprintf(stdout, color, " %s", path);
+		color_fprintf(stdout, color, " %s\n", path);
 
 		node = rb_next(node);
 	}
@@ -1356,7 +1354,6 @@
 			 bool full_paths, int min_pcnt, int max_lines)
 {
 	struct dso *dso = map->dso;
-	const char *filename = dso->long_name;
 	struct rb_root source_line = RB_ROOT;
 	u64 len;
 
@@ -1366,9 +1363,8 @@
 	len = symbol__size(sym);
 
 	if (print_lines) {
-		symbol__get_source_line(sym, map, evsel, &source_line,
-					len, filename);
-		print_summary(&source_line, filename);
+		symbol__get_source_line(sym, map, evsel, &source_line, len);
+		print_summary(&source_line, dso->long_name);
 	}
 
 	symbol__annotate_printf(sym, map, evsel, full_paths,
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index af75515..834b7b5 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -150,7 +150,7 @@
 			 struct perf_evsel *evsel, bool print_lines,
 			 bool full_paths, int min_pcnt, int max_lines);
 
-#ifdef SLANG_SUPPORT
+#ifdef HAVE_SLANG_SUPPORT
 int symbol__tui_annotate(struct symbol *sym, struct map *map,
 			 struct perf_evsel *evsel,
 			 struct hist_browser_timer *hbt);
@@ -165,30 +165,6 @@
 }
 #endif
 
-#ifdef GTK2_SUPPORT
-int symbol__gtk_annotate(struct symbol *sym, struct map *map,
-			 struct perf_evsel *evsel,
-			 struct hist_browser_timer *hbt);
-
-static inline int hist_entry__gtk_annotate(struct hist_entry *he,
-					   struct perf_evsel *evsel,
-					   struct hist_browser_timer *hbt)
-{
-	return symbol__gtk_annotate(he->ms.sym, he->ms.map, evsel, hbt);
-}
-
-void perf_gtk__show_annotations(void);
-#else
-static inline int hist_entry__gtk_annotate(struct hist_entry *he __maybe_unused,
-				struct perf_evsel *evsel __maybe_unused,
-				struct hist_browser_timer *hbt __maybe_unused)
-{
-	return 0;
-}
-
-static inline void perf_gtk__show_annotations(void) {}
-#endif
-
 extern const char	*disassembler_style;
 
 #endif	/* __PERF_ANNOTATE_H */
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 7ded71d..a92770c 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -89,14 +89,14 @@
 	return raw - build_id;
 }
 
-char *dso__build_id_filename(struct dso *self, char *bf, size_t size)
+char *dso__build_id_filename(struct dso *dso, char *bf, size_t size)
 {
 	char build_id_hex[BUILD_ID_SIZE * 2 + 1];
 
-	if (!self->has_build_id)
+	if (!dso->has_build_id)
 		return NULL;
 
-	build_id__sprintf(self->build_id, sizeof(self->build_id), build_id_hex);
+	build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex);
 	if (bf == NULL) {
 		if (asprintf(&bf, "%s/.build-id/%.2s/%s", buildid_dir,
 			     build_id_hex, build_id_hex + 2) < 0)
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index a811f5c..929f28a 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -10,10 +10,9 @@
 struct dso;
 
 int build_id__sprintf(const u8 *build_id, int len, char *bf);
-char *dso__build_id_filename(struct dso *self, char *bf, size_t size);
+char *dso__build_id_filename(struct dso *dso, char *bf, size_t size);
 
 int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
 			   struct perf_sample *sample, struct perf_evsel *evsel,
 			   struct machine *machine);
-
 #endif
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 26e3672..7b176dd 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -70,8 +70,7 @@
 extern char *perf_pathdup(const char *fmt, ...)
 	__attribute__((format (printf, 1, 2)));
 
-#ifndef HAVE_STRLCPY
+/* Matches the libc/libbsd function attribute so we declare this unconditionally: */
 extern size_t strlcpy(char *dest, const char *src, size_t size);
-#endif
 
 #endif /* __PERF_CACHE_H */
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 482f680..e3970e3 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -21,12 +21,6 @@
 
 __thread struct callchain_cursor callchain_cursor;
 
-#define chain_for_each_child(child, parent)	\
-	list_for_each_entry(child, &parent->children, siblings)
-
-#define chain_for_each_child_safe(child, next, parent)	\
-	list_for_each_entry_safe(child, next, &parent->children, siblings)
-
 static void
 rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
 		    enum chain_mode mode)
@@ -71,10 +65,16 @@
 __sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
 		  u64 min_hit)
 {
+	struct rb_node *n;
 	struct callchain_node *child;
 
-	chain_for_each_child(child, node)
+	n = rb_first(&node->rb_root_in);
+	while (n) {
+		child = rb_entry(n, struct callchain_node, rb_node_in);
+		n = rb_next(n);
+
 		__sort_chain_flat(rb_root, child, min_hit);
+	}
 
 	if (node->hit && node->hit >= min_hit)
 		rb_insert_callchain(rb_root, node, CHAIN_FLAT);
@@ -94,11 +94,16 @@
 static void __sort_chain_graph_abs(struct callchain_node *node,
 				   u64 min_hit)
 {
+	struct rb_node *n;
 	struct callchain_node *child;
 
 	node->rb_root = RB_ROOT;
+	n = rb_first(&node->rb_root_in);
 
-	chain_for_each_child(child, node) {
+	while (n) {
+		child = rb_entry(n, struct callchain_node, rb_node_in);
+		n = rb_next(n);
+
 		__sort_chain_graph_abs(child, min_hit);
 		if (callchain_cumul_hits(child) >= min_hit)
 			rb_insert_callchain(&node->rb_root, child,
@@ -117,13 +122,18 @@
 static void __sort_chain_graph_rel(struct callchain_node *node,
 				   double min_percent)
 {
+	struct rb_node *n;
 	struct callchain_node *child;
 	u64 min_hit;
 
 	node->rb_root = RB_ROOT;
 	min_hit = ceil(node->children_hit * min_percent);
 
-	chain_for_each_child(child, node) {
+	n = rb_first(&node->rb_root_in);
+	while (n) {
+		child = rb_entry(n, struct callchain_node, rb_node_in);
+		n = rb_next(n);
+
 		__sort_chain_graph_rel(child, min_percent);
 		if (callchain_cumul_hits(child) >= min_hit)
 			rb_insert_callchain(&node->rb_root, child,
@@ -173,19 +183,26 @@
 		return NULL;
 	}
 	new->parent = parent;
-	INIT_LIST_HEAD(&new->children);
 	INIT_LIST_HEAD(&new->val);
 
 	if (inherit_children) {
-		struct callchain_node *next;
+		struct rb_node *n;
+		struct callchain_node *child;
 
-		list_splice(&parent->children, &new->children);
-		INIT_LIST_HEAD(&parent->children);
+		new->rb_root_in = parent->rb_root_in;
+		parent->rb_root_in = RB_ROOT;
 
-		chain_for_each_child(next, new)
-			next->parent = new;
+		n = rb_first(&new->rb_root_in);
+		while (n) {
+			child = rb_entry(n, struct callchain_node, rb_node_in);
+			child->parent = new;
+			n = rb_next(n);
+		}
+
+		/* make it the first child */
+		rb_link_node(&new->rb_node_in, NULL, &parent->rb_root_in.rb_node);
+		rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
 	}
-	list_add_tail(&new->siblings, &parent->children);
 
 	return new;
 }
@@ -223,7 +240,7 @@
 	}
 }
 
-static void
+static struct callchain_node *
 add_child(struct callchain_node *parent,
 	  struct callchain_cursor *cursor,
 	  u64 period)
@@ -235,6 +252,19 @@
 
 	new->children_hit = 0;
 	new->hit = period;
+	return new;
+}
+
+static s64 match_chain(struct callchain_cursor_node *node,
+		      struct callchain_list *cnode)
+{
+	struct symbol *sym = node->sym;
+
+	if (cnode->ms.sym && sym &&
+	    callchain_param.key == CCKEY_FUNCTION)
+		return cnode->ms.sym->start - sym->start;
+	else
+		return cnode->ip - node->ip;
 }
 
 /*
@@ -272,9 +302,33 @@
 
 	/* create a new child for the new branch if any */
 	if (idx_total < cursor->nr) {
+		struct callchain_node *first;
+		struct callchain_list *cnode;
+		struct callchain_cursor_node *node;
+		struct rb_node *p, **pp;
+
 		parent->hit = 0;
-		add_child(parent, cursor, period);
 		parent->children_hit += period;
+
+		node = callchain_cursor_current(cursor);
+		new = add_child(parent, cursor, period);
+
+		/*
+		 * This is second child since we moved parent's children
+		 * to new (first) child above.
+		 */
+		p = parent->rb_root_in.rb_node;
+		first = rb_entry(p, struct callchain_node, rb_node_in);
+		cnode = list_first_entry(&first->val, struct callchain_list,
+					 list);
+
+		if (match_chain(node, cnode) < 0)
+			pp = &p->rb_left;
+		else
+			pp = &p->rb_right;
+
+		rb_link_node(&new->rb_node_in, p, pp);
+		rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
 	} else {
 		parent->hit = period;
 	}
@@ -291,16 +345,40 @@
 		      u64 period)
 {
 	struct callchain_node *rnode;
+	struct callchain_cursor_node *node;
+	struct rb_node **p = &root->rb_root_in.rb_node;
+	struct rb_node *parent = NULL;
+
+	node = callchain_cursor_current(cursor);
+	if (!node)
+		return;
 
 	/* lookup in childrens */
-	chain_for_each_child(rnode, root) {
-		unsigned int ret = append_chain(rnode, cursor, period);
+	while (*p) {
+		s64 ret;
+		struct callchain_list *cnode;
 
-		if (!ret)
+		parent = *p;
+		rnode = rb_entry(parent, struct callchain_node, rb_node_in);
+		cnode = list_first_entry(&rnode->val, struct callchain_list,
+					 list);
+
+		/* just check first entry */
+		ret = match_chain(node, cnode);
+		if (ret == 0) {
+			append_chain(rnode, cursor, period);
 			goto inc_children_hit;
+		}
+
+		if (ret < 0)
+			p = &parent->rb_left;
+		else
+			p = &parent->rb_right;
 	}
 	/* nothing in children, add to the current node */
-	add_child(root, cursor, period);
+	rnode = add_child(root, cursor, period);
+	rb_link_node(&rnode->rb_node_in, parent, p);
+	rb_insert_color(&rnode->rb_node_in, &root->rb_root_in);
 
 inc_children_hit:
 	root->children_hit += period;
@@ -325,28 +403,20 @@
 	 */
 	list_for_each_entry(cnode, &root->val, list) {
 		struct callchain_cursor_node *node;
-		struct symbol *sym;
 
 		node = callchain_cursor_current(cursor);
 		if (!node)
 			break;
 
-		sym = node->sym;
-
-		if (cnode->ms.sym && sym &&
-		    callchain_param.key == CCKEY_FUNCTION) {
-			if (cnode->ms.sym->start != sym->start)
-				break;
-		} else if (cnode->ip != node->ip)
+		if (match_chain(node, cnode) != 0)
 			break;
 
-		if (!found)
-			found = true;
+		found = true;
 
 		callchain_cursor_advance(cursor);
 	}
 
-	/* matches not, relay on the parent */
+	/* matches not, relay no the parent */
 	if (!found) {
 		cursor->curr = curr_snap;
 		cursor->pos = start;
@@ -395,8 +465,9 @@
 		   struct callchain_node *dst, struct callchain_node *src)
 {
 	struct callchain_cursor_node **old_last = cursor->last;
-	struct callchain_node *child, *next_child;
+	struct callchain_node *child;
 	struct callchain_list *list, *next_list;
+	struct rb_node *n;
 	int old_pos = cursor->nr;
 	int err = 0;
 
@@ -412,12 +483,16 @@
 		append_chain_children(dst, cursor, src->hit);
 	}
 
-	chain_for_each_child_safe(child, next_child, src) {
+	n = rb_first(&src->rb_root_in);
+	while (n) {
+		child = container_of(n, struct callchain_node, rb_node_in);
+		n = rb_next(n);
+		rb_erase(&child->rb_node_in, &src->rb_root_in);
+
 		err = merge_chain_branch(cursor, dst, child);
 		if (err)
 			break;
 
-		list_del(&child->siblings);
 		free(child);
 	}
 
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 2b585bc..4f7f989 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -21,11 +21,11 @@
 
 struct callchain_node {
 	struct callchain_node	*parent;
-	struct list_head	siblings;
-	struct list_head	children;
 	struct list_head	val;
-	struct rb_node		rb_node; /* to sort nodes in an rbtree */
-	struct rb_root		rb_root; /* sorted tree of children */
+	struct rb_node		rb_node_in; /* to insert nodes in an rbtree */
+	struct rb_node		rb_node;    /* to sort nodes in an output tree */
+	struct rb_root		rb_root_in; /* input tree of children */
+	struct rb_root		rb_root;    /* sorted output tree of children */
 	unsigned int		val_nr;
 	u64			hit;
 	u64			children_hit;
@@ -86,13 +86,12 @@
 
 static inline void callchain_init(struct callchain_root *root)
 {
-	INIT_LIST_HEAD(&root->node.siblings);
-	INIT_LIST_HEAD(&root->node.children);
 	INIT_LIST_HEAD(&root->node.val);
 
 	root->node.parent = NULL;
 	root->node.hit = 0;
 	root->node.children_hit = 0;
+	root->node.rb_root_in = RB_ROOT;
 	root->max_depth = 0;
 }
 
@@ -147,6 +146,9 @@
 
 struct option;
 
+int record_parse_callchain(const char *arg, struct perf_record_opts *opts);
 int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
+int record_callchain_opt(const struct option *opt, const char *arg, int unset);
+
 extern const char record_callchain_help[];
 #endif	/* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index 11e46da..66e44a5 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -318,8 +318,15 @@
 	return r;
 }
 
-int percent_color_snprintf(char *bf, size_t size, const char *fmt, double percent)
+int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...)
 {
-	const char *color = get_percent_color(percent);
+	va_list args;
+	double percent;
+	const char *color;
+
+	va_start(args, fmt);
+	percent = va_arg(args, double);
+	va_end(args);
+	color = get_percent_color(percent);
 	return color_snprintf(bf, size, color, fmt, percent);
 }
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index dea082b..fced384 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -39,7 +39,7 @@
 int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...);
 int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
 int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
-int percent_color_snprintf(char *bf, size_t size, const char *fmt, double percent);
+int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...);
 int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
 const char *get_percent_color(double percent);
 
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c
new file mode 100644
index 0000000..ee0df0e
--- /dev/null
+++ b/tools/perf/util/comm.c
@@ -0,0 +1,121 @@
+#include "comm.h"
+#include "util.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+struct comm_str {
+	char *str;
+	struct rb_node rb_node;
+	int ref;
+};
+
+/* Should perhaps be moved to struct machine */
+static struct rb_root comm_str_root;
+
+static void comm_str__get(struct comm_str *cs)
+{
+	cs->ref++;
+}
+
+static void comm_str__put(struct comm_str *cs)
+{
+	if (!--cs->ref) {
+		rb_erase(&cs->rb_node, &comm_str_root);
+		free(cs->str);
+		free(cs);
+	}
+}
+
+static struct comm_str *comm_str__alloc(const char *str)
+{
+	struct comm_str *cs;
+
+	cs = zalloc(sizeof(*cs));
+	if (!cs)
+		return NULL;
+
+	cs->str = strdup(str);
+	if (!cs->str) {
+		free(cs);
+		return NULL;
+	}
+
+	return cs;
+}
+
+static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
+{
+	struct rb_node **p = &root->rb_node;
+	struct rb_node *parent = NULL;
+	struct comm_str *iter, *new;
+	int cmp;
+
+	while (*p != NULL) {
+		parent = *p;
+		iter = rb_entry(parent, struct comm_str, rb_node);
+
+		cmp = strcmp(str, iter->str);
+		if (!cmp)
+			return iter;
+
+		if (cmp < 0)
+			p = &(*p)->rb_left;
+		else
+			p = &(*p)->rb_right;
+	}
+
+	new = comm_str__alloc(str);
+	if (!new)
+		return NULL;
+
+	rb_link_node(&new->rb_node, parent, p);
+	rb_insert_color(&new->rb_node, root);
+
+	return new;
+}
+
+struct comm *comm__new(const char *str, u64 timestamp)
+{
+	struct comm *comm = zalloc(sizeof(*comm));
+
+	if (!comm)
+		return NULL;
+
+	comm->start = timestamp;
+
+	comm->comm_str = comm_str__findnew(str, &comm_str_root);
+	if (!comm->comm_str) {
+		free(comm);
+		return NULL;
+	}
+
+	comm_str__get(comm->comm_str);
+
+	return comm;
+}
+
+void comm__override(struct comm *comm, const char *str, u64 timestamp)
+{
+	struct comm_str *old = comm->comm_str;
+
+	comm->comm_str = comm_str__findnew(str, &comm_str_root);
+	if (!comm->comm_str) {
+		comm->comm_str = old;
+		return;
+	}
+
+	comm->start = timestamp;
+	comm_str__get(comm->comm_str);
+	comm_str__put(old);
+}
+
+void comm__free(struct comm *comm)
+{
+	comm_str__put(comm->comm_str);
+	free(comm);
+}
+
+const char *comm__str(const struct comm *comm)
+{
+	return comm->comm_str->str;
+}
diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h
new file mode 100644
index 0000000..7a86e56
--- /dev/null
+++ b/tools/perf/util/comm.h
@@ -0,0 +1,21 @@
+#ifndef __PERF_COMM_H
+#define __PERF_COMM_H
+
+#include "../perf.h"
+#include <linux/rbtree.h>
+#include <linux/list.h>
+
+struct comm_str;
+
+struct comm {
+	struct comm_str *comm_str;
+	u64 start;
+	struct list_head list;
+};
+
+void comm__free(struct comm *comm);
+struct comm *comm__new(const char *str, u64 timestamp);
+const char *comm__str(const struct comm *comm);
+void comm__override(struct comm *comm, const char *str, u64 timestamp);
+
+#endif  /* __PERF_COMM_H */
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index beb8cf9..a9b48c4 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -1,5 +1,5 @@
 #include "util.h"
-#include "sysfs.h"
+#include "fs.h"
 #include "../perf.h"
 #include "cpumap.h"
 #include <assert.h>
@@ -216,7 +216,7 @@
 
 	cpu = map->map[idx];
 
-	mnt = sysfs_find_mountpoint();
+	mnt = sysfs__mountpoint();
 	if (!mnt)
 		return -1;
 
@@ -279,7 +279,7 @@
 
 	cpu = map->map[idx];
 
-	mnt = sysfs_find_mountpoint();
+	mnt = sysfs__mountpoint();
 	if (!mnt)
 		return -1;
 
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
new file mode 100644
index 0000000..7d09faf
--- /dev/null
+++ b/tools/perf/util/data.c
@@ -0,0 +1,120 @@
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "data.h"
+#include "util.h"
+
+static bool check_pipe(struct perf_data_file *file)
+{
+	struct stat st;
+	bool is_pipe = false;
+	int fd = perf_data_file__is_read(file) ?
+		 STDIN_FILENO : STDOUT_FILENO;
+
+	if (!file->path) {
+		if (!fstat(fd, &st) && S_ISFIFO(st.st_mode))
+			is_pipe = true;
+	} else {
+		if (!strcmp(file->path, "-"))
+			is_pipe = true;
+	}
+
+	if (is_pipe)
+		file->fd = fd;
+
+	return file->is_pipe = is_pipe;
+}
+
+static int check_backup(struct perf_data_file *file)
+{
+	struct stat st;
+
+	if (!stat(file->path, &st) && st.st_size) {
+		/* TODO check errors properly */
+		char oldname[PATH_MAX];
+		snprintf(oldname, sizeof(oldname), "%s.old",
+			 file->path);
+		unlink(oldname);
+		rename(file->path, oldname);
+	}
+
+	return 0;
+}
+
+static int open_file_read(struct perf_data_file *file)
+{
+	struct stat st;
+	int fd;
+
+	fd = open(file->path, O_RDONLY);
+	if (fd < 0) {
+		int err = errno;
+
+		pr_err("failed to open %s: %s", file->path, strerror(err));
+		if (err == ENOENT && !strcmp(file->path, "perf.data"))
+			pr_err("  (try 'perf record' first)");
+		pr_err("\n");
+		return -err;
+	}
+
+	if (fstat(fd, &st) < 0)
+		goto out_close;
+
+	if (!file->force && st.st_uid && (st.st_uid != geteuid())) {
+		pr_err("file %s not owned by current user or root\n",
+		       file->path);
+		goto out_close;
+	}
+
+	if (!st.st_size) {
+		pr_info("zero-sized file (%s), nothing to do!\n",
+			file->path);
+		goto out_close;
+	}
+
+	file->size = st.st_size;
+	return fd;
+
+ out_close:
+	close(fd);
+	return -1;
+}
+
+static int open_file_write(struct perf_data_file *file)
+{
+	if (check_backup(file))
+		return -1;
+
+	return open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
+}
+
+static int open_file(struct perf_data_file *file)
+{
+	int fd;
+
+	fd = perf_data_file__is_read(file) ?
+	     open_file_read(file) : open_file_write(file);
+
+	file->fd = fd;
+	return fd < 0 ? -1 : 0;
+}
+
+int perf_data_file__open(struct perf_data_file *file)
+{
+	if (check_pipe(file))
+		return 0;
+
+	if (!file->path)
+		file->path = "perf.data";
+
+	return open_file(file);
+}
+
+void perf_data_file__close(struct perf_data_file *file)
+{
+	close(file->fd);
+}
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
new file mode 100644
index 0000000..8c2df80
--- /dev/null
+++ b/tools/perf/util/data.h
@@ -0,0 +1,48 @@
+#ifndef __PERF_DATA_H
+#define __PERF_DATA_H
+
+#include <stdbool.h>
+
+enum perf_data_mode {
+	PERF_DATA_MODE_WRITE,
+	PERF_DATA_MODE_READ,
+};
+
+struct perf_data_file {
+	const char *path;
+	int fd;
+	bool is_pipe;
+	bool force;
+	unsigned long size;
+	enum perf_data_mode mode;
+};
+
+static inline bool perf_data_file__is_read(struct perf_data_file *file)
+{
+	return file->mode == PERF_DATA_MODE_READ;
+}
+
+static inline bool perf_data_file__is_write(struct perf_data_file *file)
+{
+	return file->mode == PERF_DATA_MODE_WRITE;
+}
+
+static inline int perf_data_file__is_pipe(struct perf_data_file *file)
+{
+	return file->is_pipe;
+}
+
+static inline int perf_data_file__fd(struct perf_data_file *file)
+{
+	return file->fd;
+}
+
+static inline unsigned long perf_data_file__size(struct perf_data_file *file)
+{
+	return file->size;
+}
+
+int perf_data_file__open(struct perf_data_file *file);
+void perf_data_file__close(struct perf_data_file *file);
+
+#endif /* __PERF_DATA_H */
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index e3c1ff8..af4c687c 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -7,19 +7,20 @@
 char dso__symtab_origin(const struct dso *dso)
 {
 	static const char origin[] = {
-		[DSO_BINARY_TYPE__KALLSYMS]		= 'k',
-		[DSO_BINARY_TYPE__VMLINUX]		= 'v',
-		[DSO_BINARY_TYPE__JAVA_JIT]		= 'j',
-		[DSO_BINARY_TYPE__DEBUGLINK]		= 'l',
-		[DSO_BINARY_TYPE__BUILD_ID_CACHE]	= 'B',
-		[DSO_BINARY_TYPE__FEDORA_DEBUGINFO]	= 'f',
-		[DSO_BINARY_TYPE__UBUNTU_DEBUGINFO]	= 'u',
-		[DSO_BINARY_TYPE__BUILDID_DEBUGINFO]	= 'b',
-		[DSO_BINARY_TYPE__SYSTEM_PATH_DSO]	= 'd',
-		[DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE]	= 'K',
-		[DSO_BINARY_TYPE__GUEST_KALLSYMS]	= 'g',
-		[DSO_BINARY_TYPE__GUEST_KMODULE]	= 'G',
-		[DSO_BINARY_TYPE__GUEST_VMLINUX]	= 'V',
+		[DSO_BINARY_TYPE__KALLSYMS]			= 'k',
+		[DSO_BINARY_TYPE__VMLINUX]			= 'v',
+		[DSO_BINARY_TYPE__JAVA_JIT]			= 'j',
+		[DSO_BINARY_TYPE__DEBUGLINK]			= 'l',
+		[DSO_BINARY_TYPE__BUILD_ID_CACHE]		= 'B',
+		[DSO_BINARY_TYPE__FEDORA_DEBUGINFO]		= 'f',
+		[DSO_BINARY_TYPE__UBUNTU_DEBUGINFO]		= 'u',
+		[DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO]	= 'o',
+		[DSO_BINARY_TYPE__BUILDID_DEBUGINFO]		= 'b',
+		[DSO_BINARY_TYPE__SYSTEM_PATH_DSO]		= 'd',
+		[DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE]		= 'K',
+		[DSO_BINARY_TYPE__GUEST_KALLSYMS]		= 'g',
+		[DSO_BINARY_TYPE__GUEST_KMODULE]		= 'G',
+		[DSO_BINARY_TYPE__GUEST_VMLINUX]		= 'V',
 	};
 
 	if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND)
@@ -64,6 +65,28 @@
 			 symbol_conf.symfs, dso->long_name);
 		break;
 
+	case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
+	{
+		char *last_slash;
+		size_t len;
+		size_t dir_size;
+
+		last_slash = dso->long_name + dso->long_name_len;
+		while (last_slash != dso->long_name && *last_slash != '/')
+			last_slash--;
+
+		len = scnprintf(file, size, "%s", symbol_conf.symfs);
+		dir_size = last_slash - dso->long_name + 2;
+		if (dir_size > (size - len)) {
+			ret = -1;
+			break;
+		}
+		len += scnprintf(file + len, dir_size, "%s",  dso->long_name);
+		len += scnprintf(file + len , size - len, ".debug%s",
+								last_slash);
+		break;
+	}
+
 	case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
 		if (!dso->has_build_id) {
 			ret = -1;
@@ -427,6 +450,7 @@
 		dso->rel = 0;
 		dso->sorted_by_name = 0;
 		dso->has_build_id = 0;
+		dso->has_srcline = 1;
 		dso->kernel = DSO_TYPE_USER;
 		dso->needs_swap = DSO_SWAP__UNSET;
 		INIT_LIST_HEAD(&dso->node);
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index b793053..9ac666a 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -6,6 +6,7 @@
 #include <stdbool.h>
 #include "types.h"
 #include "map.h"
+#include "build-id.h"
 
 enum dso_binary_type {
 	DSO_BINARY_TYPE__KALLSYMS = 0,
@@ -23,6 +24,7 @@
 	DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
 	DSO_BINARY_TYPE__KCORE,
 	DSO_BINARY_TYPE__GUEST_KCORE,
+	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
 	DSO_BINARY_TYPE__NOT_FOUND,
 };
 
@@ -81,6 +83,7 @@
 	enum dso_binary_type	data_type;
 	u8		 adjust_symbols:1;
 	u8		 has_build_id:1;
+	u8		 has_srcline:1;
 	u8		 hit:1;
 	u8		 annotate_warned:1;
 	u8		 sname_alloc:1;
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index e23bde1..7defd77 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -426,7 +426,7 @@
  * @die_mem: a buffer for result DIE
  *
  * Search a non-inlined function DIE which includes @addr. Stores the
- * DIE to @die_mem and returns it if found. Returns NULl if failed.
+ * DIE to @die_mem and returns it if found. Returns NULL if failed.
  */
 Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
 				    Dwarf_Die *die_mem)
@@ -454,15 +454,32 @@
 }
 
 /**
- * die_find_inlinefunc - Search an inlined function at given address
- * @cu_die: a CU DIE which including @addr
+ * die_find_top_inlinefunc - Search the top inlined function at given address
+ * @sp_die: a subprogram DIE which including @addr
  * @addr: target address
  * @die_mem: a buffer for result DIE
  *
  * Search an inlined function DIE which includes @addr. Stores the
- * DIE to @die_mem and returns it if found. Returns NULl if failed.
+ * DIE to @die_mem and returns it if found. Returns NULL if failed.
+ * Even if several inlined functions are expanded recursively, this
+ * doesn't trace it down, and returns the topmost one.
+ */
+Dwarf_Die *die_find_top_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
+				   Dwarf_Die *die_mem)
+{
+	return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
+}
+
+/**
+ * die_find_inlinefunc - Search an inlined function at given address
+ * @sp_die: a subprogram DIE which including @addr
+ * @addr: target address
+ * @die_mem: a buffer for result DIE
+ *
+ * Search an inlined function DIE which includes @addr. Stores the
+ * DIE to @die_mem and returns it if found. Returns NULL if failed.
  * If several inlined functions are expanded recursively, this trace
- * it and returns deepest one.
+ * it down and returns deepest one.
  */
 Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
 			       Dwarf_Die *die_mem)
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index 8658d41..b4fe90c 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -79,7 +79,11 @@
 extern Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
 				    Dwarf_Die *die_mem);
 
-/* Search an inlined function including given address */
+/* Search the top inlined function including given address */
+extern Dwarf_Die *die_find_top_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
+					  Dwarf_Die *die_mem);
+
+/* Search the deepest inlined function including given address */
 extern Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
 				      Dwarf_Die *die_mem);
 
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 9b393e7..ec9ae11 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -187,7 +187,7 @@
 		return -1;
 	}
 
-	event->header.type = PERF_RECORD_MMAP2;
+	event->header.type = PERF_RECORD_MMAP;
 	/*
 	 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
 	 */
@@ -198,7 +198,6 @@
 		char prot[5];
 		char execname[PATH_MAX];
 		char anonstr[] = "//anon";
-		unsigned int ino;
 		size_t size;
 		ssize_t n;
 
@@ -209,15 +208,12 @@
 		strcpy(execname, "");
 
 		/* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
-		n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %s\n",
-		       &event->mmap2.start, &event->mmap2.len, prot,
-		       &event->mmap2.pgoff, &event->mmap2.maj,
-		       &event->mmap2.min,
-		       &ino, execname);
+		n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %*x:%*x %*u %s\n",
+		       &event->mmap.start, &event->mmap.len, prot,
+		       &event->mmap.pgoff,
+		       execname);
 
-		event->mmap2.ino = (u64)ino;
-
-		if (n != 8)
+		if (n != 5)
 			continue;
 
 		if (prot[2] != 'x')
@@ -227,15 +223,15 @@
 			strcpy(execname, anonstr);
 
 		size = strlen(execname) + 1;
-		memcpy(event->mmap2.filename, execname, size);
+		memcpy(event->mmap.filename, execname, size);
 		size = PERF_ALIGN(size, sizeof(u64));
-		event->mmap2.len -= event->mmap.start;
-		event->mmap2.header.size = (sizeof(event->mmap2) -
-					(sizeof(event->mmap2.filename) - size));
-		memset(event->mmap2.filename + size, 0, machine->id_hdr_size);
-		event->mmap2.header.size += machine->id_hdr_size;
-		event->mmap2.pid = tgid;
-		event->mmap2.tid = pid;
+		event->mmap.len -= event->mmap.start;
+		event->mmap.header.size = (sizeof(event->mmap) -
+					(sizeof(event->mmap.filename) - size));
+		memset(event->mmap.filename + size, 0, machine->id_hdr_size);
+		event->mmap.header.size += machine->id_hdr_size;
+		event->mmap.pid = tgid;
+		event->mmap.tid = pid;
 
 		if (process(tool, event, &synth_sample, machine) != 0) {
 			rc = -1;
@@ -516,18 +512,18 @@
 
 int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
 			     union perf_event *event,
-			     struct perf_sample *sample __maybe_unused,
+			     struct perf_sample *sample,
 			     struct machine *machine)
 {
-	return machine__process_comm_event(machine, event);
+	return machine__process_comm_event(machine, event, sample);
 }
 
 int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
 			     union perf_event *event,
-			     struct perf_sample *sample __maybe_unused,
+			     struct perf_sample *sample,
 			     struct machine *machine)
 {
-	return machine__process_lost_event(machine, event);
+	return machine__process_lost_event(machine, event, sample);
 }
 
 size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
@@ -550,18 +546,18 @@
 
 int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
 			     union perf_event *event,
-			     struct perf_sample *sample __maybe_unused,
+			     struct perf_sample *sample,
 			     struct machine *machine)
 {
-	return machine__process_mmap_event(machine, event);
+	return machine__process_mmap_event(machine, event, sample);
 }
 
 int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused,
 			     union perf_event *event,
-			     struct perf_sample *sample __maybe_unused,
+			     struct perf_sample *sample,
 			     struct machine *machine)
 {
-	return machine__process_mmap2_event(machine, event);
+	return machine__process_mmap2_event(machine, event, sample);
 }
 
 size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
@@ -573,18 +569,18 @@
 
 int perf_event__process_fork(struct perf_tool *tool __maybe_unused,
 			     union perf_event *event,
-			     struct perf_sample *sample __maybe_unused,
+			     struct perf_sample *sample,
 			     struct machine *machine)
 {
-	return machine__process_fork_event(machine, event);
+	return machine__process_fork_event(machine, event, sample);
 }
 
 int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
 			     union perf_event *event,
-			     struct perf_sample *sample __maybe_unused,
+			     struct perf_sample *sample,
 			     struct machine *machine)
 {
-	return machine__process_exit_event(machine, event);
+	return machine__process_exit_event(machine, event, sample);
 }
 
 size_t perf_event__fprintf(union perf_event *event, FILE *fp)
@@ -615,21 +611,21 @@
 
 int perf_event__process(struct perf_tool *tool __maybe_unused,
 			union perf_event *event,
-			struct perf_sample *sample __maybe_unused,
+			struct perf_sample *sample,
 			struct machine *machine)
 {
-	return machine__process_event(machine, event);
+	return machine__process_event(machine, event, sample);
 }
 
-void thread__find_addr_map(struct thread *self,
+void thread__find_addr_map(struct thread *thread,
 			   struct machine *machine, u8 cpumode,
 			   enum map_type type, u64 addr,
 			   struct addr_location *al)
 {
-	struct map_groups *mg = &self->mg;
+	struct map_groups *mg = &thread->mg;
 	bool load_map = false;
 
-	al->thread = self;
+	al->thread = thread;
 	al->addr = addr;
 	al->cpumode = cpumode;
 	al->filtered = false;
@@ -725,10 +721,10 @@
 		return -1;
 
 	if (symbol_conf.comm_list &&
-	    !strlist__has_entry(symbol_conf.comm_list, thread->comm))
+	    !strlist__has_entry(symbol_conf.comm_list, thread__comm_str(thread)))
 		goto out_filtered;
 
-	dump_printf(" ... thread: %s:%d\n", thread->comm, thread->tid);
+	dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
 	/*
 	 * Have we already created the kernel maps for this machine?
 	 *
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index c67ecc4..f8d70f3 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -61,6 +61,12 @@
 	u64 id;
 };
 
+struct throttle_event {
+	struct perf_event_header header;
+	u64 time;
+	u64 id;
+	u64 stream_id;
+};
 
 #define PERF_SAMPLE_MASK				\
 	(PERF_SAMPLE_IP | PERF_SAMPLE_TID |		\
@@ -69,6 +75,9 @@
 	 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD |		\
 	 PERF_SAMPLE_IDENTIFIER)
 
+/* perf sample has 16 bits size limit */
+#define PERF_SAMPLE_MAX_SIZE (1 << 16)
+
 struct sample_event {
 	struct perf_event_header        header;
 	u64 array[];
@@ -111,6 +120,7 @@
 	u64 stream_id;
 	u64 period;
 	u64 weight;
+	u64 transaction;
 	u32 cpu;
 	u32 raw_size;
 	u64 data_src;
@@ -177,6 +187,7 @@
 	struct fork_event		fork;
 	struct lost_event		lost;
 	struct read_event		read;
+	struct throttle_event		throttle;
 	struct sample_event		sample;
 	struct attr_event		attr;
 	struct event_type_event		event_type;
@@ -240,7 +251,8 @@
 			struct machine *machine);
 
 struct addr_location;
-int perf_event__preprocess_sample(const union perf_event *self,
+
+int perf_event__preprocess_sample(const union perf_event *event,
 				  struct machine *machine,
 				  struct addr_location *al,
 				  struct perf_sample *sample);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index f9f77be..b939221 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -18,6 +18,7 @@
 #include <unistd.h>
 
 #include "parse-events.h"
+#include "parse-options.h"
 
 #include <sys/mman.h>
 
@@ -49,6 +50,18 @@
 	return evlist;
 }
 
+struct perf_evlist *perf_evlist__new_default(void)
+{
+	struct perf_evlist *evlist = perf_evlist__new();
+
+	if (evlist && perf_evlist__add_default(evlist)) {
+		perf_evlist__delete(evlist);
+		evlist = NULL;
+	}
+
+	return evlist;
+}
+
 /**
  * perf_evlist__set_id_pos - set the positions of event ids.
  * @evlist: selected event list
@@ -242,7 +255,7 @@
 	if (evsel == NULL)
 		return -1;
 
-	evsel->handler.func = handler;
+	evsel->handler = handler;
 	perf_evlist__add(evlist, evsel);
 	return 0;
 }
@@ -527,7 +540,7 @@
 		if ((old & md->mask) + size != ((old + size) & md->mask)) {
 			unsigned int offset = old;
 			unsigned int len = min(sizeof(*event), size), cpy;
-			void *dst = &md->event_copy;
+			void *dst = md->event_copy;
 
 			do {
 				cpy = min(md->mask + 1 - (offset & md->mask), len);
@@ -537,7 +550,7 @@
 				len -= cpy;
 			} while (len);
 
-			event = &md->event_copy;
+			event = (union perf_event *) md->event_copy;
 		}
 
 		old += size;
@@ -545,12 +558,19 @@
 
 	md->prev = old;
 
-	if (!evlist->overwrite)
-		perf_mmap__write_tail(md, old);
-
 	return event;
 }
 
+void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
+{
+	if (!evlist->overwrite) {
+		struct perf_mmap *md = &evlist->mmap[idx];
+		unsigned int old = md->prev;
+
+		perf_mmap__write_tail(md, old);
+	}
+}
+
 static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
 {
 	if (evlist->mmap[idx].base != NULL) {
@@ -587,6 +607,8 @@
 	evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot,
 				      MAP_SHARED, fd, 0);
 	if (evlist->mmap[idx].base == MAP_FAILED) {
+		pr_debug2("failed to mmap perf event ring buffer, error %d\n",
+			  errno);
 		evlist->mmap[idx].base = NULL;
 		return -1;
 	}
@@ -595,9 +617,36 @@
 	return 0;
 }
 
-static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int mask)
+static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
+				       int prot, int mask, int cpu, int thread,
+				       int *output)
 {
 	struct perf_evsel *evsel;
+
+	list_for_each_entry(evsel, &evlist->entries, node) {
+		int fd = FD(evsel, cpu, thread);
+
+		if (*output == -1) {
+			*output = fd;
+			if (__perf_evlist__mmap(evlist, idx, prot, mask,
+						*output) < 0)
+				return -1;
+		} else {
+			if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
+				return -1;
+		}
+
+		if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
+		    perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot,
+				     int mask)
+{
 	int cpu, thread;
 	int nr_cpus = cpu_map__nr(evlist->cpus);
 	int nr_threads = thread_map__nr(evlist->threads);
@@ -607,23 +656,9 @@
 		int output = -1;
 
 		for (thread = 0; thread < nr_threads; thread++) {
-			list_for_each_entry(evsel, &evlist->entries, node) {
-				int fd = FD(evsel, cpu, thread);
-
-				if (output == -1) {
-					output = fd;
-					if (__perf_evlist__mmap(evlist, cpu,
-								prot, mask, output) < 0)
-						goto out_unmap;
-				} else {
-					if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0)
-						goto out_unmap;
-				}
-
-				if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
-				    perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0)
-					goto out_unmap;
-			}
+			if (perf_evlist__mmap_per_evsel(evlist, cpu, prot, mask,
+							cpu, thread, &output))
+				goto out_unmap;
 		}
 	}
 
@@ -635,9 +670,9 @@
 	return -1;
 }
 
-static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, int mask)
+static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot,
+					int mask)
 {
-	struct perf_evsel *evsel;
 	int thread;
 	int nr_threads = thread_map__nr(evlist->threads);
 
@@ -645,23 +680,9 @@
 	for (thread = 0; thread < nr_threads; thread++) {
 		int output = -1;
 
-		list_for_each_entry(evsel, &evlist->entries, node) {
-			int fd = FD(evsel, 0, thread);
-
-			if (output == -1) {
-				output = fd;
-				if (__perf_evlist__mmap(evlist, thread,
-							prot, mask, output) < 0)
-					goto out_unmap;
-			} else {
-				if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0)
-					goto out_unmap;
-			}
-
-			if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
-			    perf_evlist__id_add_fd(evlist, evsel, 0, thread, fd) < 0)
-				goto out_unmap;
-		}
+		if (perf_evlist__mmap_per_evsel(evlist, thread, prot, mask, 0,
+						thread, &output))
+			goto out_unmap;
 	}
 
 	return 0;
@@ -672,20 +693,76 @@
 	return -1;
 }
 
-/** perf_evlist__mmap - Create per cpu maps to receive events
+static size_t perf_evlist__mmap_size(unsigned long pages)
+{
+	/* 512 kiB: default amount of unprivileged mlocked memory */
+	if (pages == UINT_MAX)
+		pages = (512 * 1024) / page_size;
+	else if (!is_power_of_2(pages))
+		return 0;
+
+	return (pages + 1) * page_size;
+}
+
+int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
+				  int unset __maybe_unused)
+{
+	unsigned int *mmap_pages = opt->value;
+	unsigned long pages, val;
+	size_t size;
+	static struct parse_tag tags[] = {
+		{ .tag  = 'B', .mult = 1       },
+		{ .tag  = 'K', .mult = 1 << 10 },
+		{ .tag  = 'M', .mult = 1 << 20 },
+		{ .tag  = 'G', .mult = 1 << 30 },
+		{ .tag  = 0 },
+	};
+
+	val = parse_tag_value(str, tags);
+	if (val != (unsigned long) -1) {
+		/* we got file size value */
+		pages = PERF_ALIGN(val, page_size) / page_size;
+		if (pages < (1UL << 31) && !is_power_of_2(pages)) {
+			pages = next_pow2(pages);
+			pr_info("rounding mmap pages size to %lu (%lu pages)\n",
+				pages * page_size, pages);
+		}
+	} else {
+		/* we got pages count value */
+		char *eptr;
+		pages = strtoul(str, &eptr, 10);
+		if (*eptr != '\0') {
+			pr_err("failed to parse --mmap_pages/-m value\n");
+			return -1;
+		}
+	}
+
+	if (pages > UINT_MAX || pages > SIZE_MAX / page_size) {
+		pr_err("--mmap_pages/-m value too big\n");
+		return -1;
+	}
+
+	size = perf_evlist__mmap_size(pages);
+	if (!size) {
+		pr_err("--mmap_pages/-m value must be a power of two.");
+		return -1;
+	}
+
+	*mmap_pages = pages;
+	return 0;
+}
+
+/**
+ * perf_evlist__mmap - Create mmaps to receive events.
+ * @evlist: list of events
+ * @pages: map length in pages
+ * @overwrite: overwrite older events?
  *
- * @evlist - list of events
- * @pages - map length in pages
- * @overwrite - overwrite older events?
+ * If @overwrite is %false the user needs to signal event consumption using
+ * perf_mmap__write_tail().  Using perf_evlist__mmap_read() does this
+ * automatically.
  *
- * If overwrite is false the user needs to signal event consuption using:
- *
- *	struct perf_mmap *m = &evlist->mmap[cpu];
- *	unsigned int head = perf_mmap__read_head(m);
- *
- *	perf_mmap__write_tail(m, head)
- *
- * Using perf_evlist__read_on_cpu does this automatically.
+ * Return: %0 on success, negative error code otherwise.
  */
 int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
 		      bool overwrite)
@@ -695,14 +772,6 @@
 	const struct thread_map *threads = evlist->threads;
 	int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask;
 
-        /* 512 kiB: default amount of unprivileged mlocked memory */
-        if (pages == UINT_MAX)
-                pages = (512 * 1024) / page_size;
-	else if (!is_power_of_2(pages))
-		return -EINVAL;
-
-	mask = pages * page_size - 1;
-
 	if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
 		return -ENOMEM;
 
@@ -710,7 +779,9 @@
 		return -ENOMEM;
 
 	evlist->overwrite = overwrite;
-	evlist->mmap_len = (pages + 1) * page_size;
+	evlist->mmap_len = perf_evlist__mmap_size(pages);
+	pr_debug("mmap size %zuB\n", evlist->mmap_len);
+	mask = evlist->mmap_len - page_size - 1;
 
 	list_for_each_entry(evsel, &evlist->entries, node) {
 		if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
@@ -1066,3 +1137,66 @@
 
 	return printed + fprintf(fp, "\n");;
 }
+
+int perf_evlist__strerror_tp(struct perf_evlist *evlist __maybe_unused,
+			     int err, char *buf, size_t size)
+{
+	char sbuf[128];
+
+	switch (err) {
+	case ENOENT:
+		scnprintf(buf, size, "%s",
+			  "Error:\tUnable to find debugfs\n"
+			  "Hint:\tWas your kernel was compiled with debugfs support?\n"
+			  "Hint:\tIs the debugfs filesystem mounted?\n"
+			  "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'");
+		break;
+	case EACCES:
+		scnprintf(buf, size,
+			  "Error:\tNo permissions to read %s/tracing/events/raw_syscalls\n"
+			  "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n",
+			  debugfs_mountpoint, debugfs_mountpoint);
+		break;
+	default:
+		scnprintf(buf, size, "%s", strerror_r(err, sbuf, sizeof(sbuf)));
+		break;
+	}
+
+	return 0;
+}
+
+int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
+			       int err, char *buf, size_t size)
+{
+	int printed, value;
+	char sbuf[128], *emsg = strerror_r(err, sbuf, sizeof(sbuf));
+
+	switch (err) {
+	case EACCES:
+	case EPERM:
+		printed = scnprintf(buf, size,
+				    "Error:\t%s.\n"
+				    "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg);
+
+		if (filename__read_int("/proc/sys/kernel/perf_event_paranoid", &value))
+			break;
+
+		printed += scnprintf(buf + printed, size - printed, "\nHint:\t");
+
+		if (value >= 2) {
+			printed += scnprintf(buf + printed, size - printed,
+					     "For your workloads it needs to be <= 1\nHint:\t");
+		}
+		printed += scnprintf(buf + printed, size - printed,
+				     "For system wide tracing it needs to be set to -1");
+
+		printed += scnprintf(buf + printed, size - printed,
+				    ".\nHint:\tThe current value is %d.", value);
+		break;
+	default:
+		scnprintf(buf, size, "%s", emsg);
+		break;
+	}
+
+	return 0;
+}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 880d713..ecaa582 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -21,7 +21,7 @@
 	void		 *base;
 	int		 mask;
 	unsigned int	 prev;
-	union perf_event event_copy;
+	char		 event_copy[PERF_SAMPLE_MAX_SIZE];
 };
 
 struct perf_evlist {
@@ -31,7 +31,7 @@
 	int		 nr_groups;
 	int		 nr_fds;
 	int		 nr_mmaps;
-	int		 mmap_len;
+	size_t		 mmap_len;
 	int		 id_pos;
 	int		 is_pos;
 	u64		 combined_sample_type;
@@ -53,6 +53,7 @@
 };
 
 struct perf_evlist *perf_evlist__new(void);
+struct perf_evlist *perf_evlist__new_default(void);
 void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
 		       struct thread_map *threads);
 void perf_evlist__exit(struct perf_evlist *evlist);
@@ -87,7 +88,9 @@
 
 struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
 
-union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
+union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);
+
+void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
 
 int perf_evlist__open(struct perf_evlist *evlist);
 void perf_evlist__close(struct perf_evlist *evlist);
@@ -96,6 +99,7 @@
 bool perf_can_sample_identifier(void);
 void perf_evlist__config(struct perf_evlist *evlist,
 			 struct perf_record_opts *opts);
+int perf_record_opts__config(struct perf_record_opts *opts);
 
 int perf_evlist__prepare_workload(struct perf_evlist *evlist,
 				  struct perf_target *target,
@@ -103,6 +107,10 @@
 				  bool want_signal);
 int perf_evlist__start_workload(struct perf_evlist *evlist);
 
+int perf_evlist__parse_mmap_pages(const struct option *opt,
+				  const char *str,
+				  int unset);
+
 int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
 		      bool overwrite);
 void perf_evlist__munmap(struct perf_evlist *evlist);
@@ -163,10 +171,13 @@
 
 size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp);
 
+int perf_evlist__strerror_tp(struct perf_evlist *evlist, int err, char *buf, size_t size);
+int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size);
+
 static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm)
 {
 	struct perf_event_mmap_page *pc = mm->base;
-	int head = pc->data_head;
+	int head = ACCESS_ONCE(pc->data_head);
 	rmb();
 	return head;
 }
@@ -179,7 +190,7 @@
 	/*
 	 * ensure all reads are done before we write the tail out.
 	 */
-	/* mb(); */
+	mb();
 	pc->data_tail = tail;
 }
 
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 0ce9feb..5280820 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -663,7 +663,7 @@
 	}
 
 	if (opts->sample_address)
-		attr->sample_type	|= PERF_SAMPLE_DATA_SRC;
+		perf_evsel__set_sample_bit(evsel, DATA_SRC);
 
 	if (opts->no_delay) {
 		attr->watermark = 0;
@@ -675,12 +675,14 @@
 	}
 
 	if (opts->sample_weight)
-		attr->sample_type	|= PERF_SAMPLE_WEIGHT;
+		perf_evsel__set_sample_bit(evsel, WEIGHT);
 
 	attr->mmap  = track;
-	attr->mmap2 = track && !perf_missing_features.mmap2;
 	attr->comm  = track;
 
+	if (opts->sample_transaction)
+		perf_evsel__set_sample_bit(evsel, TRANSACTION);
+
 	/*
 	 * XXX see the function comment above
 	 *
@@ -983,6 +985,7 @@
 	ret += PRINT_ATTR2(exclude_host, exclude_guest);
 	ret += PRINT_ATTR2N("excl.callchain_kern", exclude_callchain_kernel,
 			    "excl.callchain_user", exclude_callchain_user);
+	ret += PRINT_ATTR_U32(mmap2);
 
 	ret += PRINT_ATTR_U32(wakeup_events);
 	ret += PRINT_ATTR_U32(wakeup_watermark);
@@ -1048,6 +1051,8 @@
 								     group_fd, flags);
 			if (FD(evsel, cpu, thread) < 0) {
 				err = -errno;
+				pr_debug2("perf_event_open failed, error %d\n",
+					  err);
 				goto try_fallback;
 			}
 			set_rlimit = NO_CHANGE;
@@ -1214,6 +1219,7 @@
 
 		sample->pid = u.val32[0];
 		sample->tid = u.val32[1];
+		array--;
 	}
 
 	return 0;
@@ -1453,6 +1459,9 @@
 			array = (void *)array + sz;
 			OVERFLOW_CHECK_u64(array);
 			data->user_stack.size = *array++;
+			if (WARN_ONCE(data->user_stack.size > sz,
+				      "user stack dump failure\n"))
+				return -EFAULT;
 		}
 	}
 
@@ -1470,6 +1479,13 @@
 		array++;
 	}
 
+	data->transaction = 0;
+	if (type & PERF_SAMPLE_TRANSACTION) {
+		OVERFLOW_CHECK_u64(array);
+		data->transaction = *array;
+		array++;
+	}
+
 	return 0;
 }
 
@@ -1562,6 +1578,9 @@
 	if (type & PERF_SAMPLE_DATA_SRC)
 		result += sizeof(u64);
 
+	if (type & PERF_SAMPLE_TRANSACTION)
+		result += sizeof(u64);
+
 	return result;
 }
 
@@ -1735,6 +1754,11 @@
 		array++;
 	}
 
+	if (type & PERF_SAMPLE_TRANSACTION) {
+		*array = sample->transaction;
+		array++;
+	}
+
 	return 0;
 }
 
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 4a7bdc7..64ec8e1 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -74,10 +74,7 @@
 		off_t		id_offset;
 	};
 	struct cgroup_sel	*cgrp;
-	struct {
-		void		*func;
-		void		*data;
-	} handler;
+	void			*handler;
 	struct cpu_map		*cpus;
 	unsigned int		sample_size;
 	int			id_pos;
@@ -197,6 +194,12 @@
 	       (e1->attr.config == e2->attr.config);
 }
 
+#define perf_evsel__cmp(a, b)			\
+	((a) &&					\
+	 (b) &&					\
+	 (a)->attr.type == (b)->attr.type &&	\
+	 (a)->attr.config == (b)->attr.config)
+
 int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
 			      int cpu, int thread, bool scale);
 
diff --git a/tools/perf/util/fs.c b/tools/perf/util/fs.c
new file mode 100644
index 0000000..f5be1f2
--- /dev/null
+++ b/tools/perf/util/fs.c
@@ -0,0 +1,119 @@
+
+/* TODO merge/factor into tools/lib/lk/debugfs.c */
+
+#include "util.h"
+#include "util/fs.h"
+
+static const char * const sysfs__fs_known_mountpoints[] = {
+	"/sys",
+	0,
+};
+
+static const char * const procfs__known_mountpoints[] = {
+	"/proc",
+	0,
+};
+
+struct fs {
+	const char		*name;
+	const char * const	*mounts;
+	char			 path[PATH_MAX + 1];
+	bool			 found;
+	long			 magic;
+};
+
+enum {
+	FS__SYSFS  = 0,
+	FS__PROCFS = 1,
+};
+
+static struct fs fs__entries[] = {
+	[FS__SYSFS] = {
+		.name	= "sysfs",
+		.mounts	= sysfs__fs_known_mountpoints,
+		.magic	= SYSFS_MAGIC,
+	},
+	[FS__PROCFS] = {
+		.name	= "proc",
+		.mounts	= procfs__known_mountpoints,
+		.magic	= PROC_SUPER_MAGIC,
+	},
+};
+
+static bool fs__read_mounts(struct fs *fs)
+{
+	bool found = false;
+	char type[100];
+	FILE *fp;
+
+	fp = fopen("/proc/mounts", "r");
+	if (fp == NULL)
+		return NULL;
+
+	while (!found &&
+	       fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
+		      fs->path, type) == 2) {
+
+		if (strcmp(type, fs->name) == 0)
+			found = true;
+	}
+
+	fclose(fp);
+	return fs->found = found;
+}
+
+static int fs__valid_mount(const char *fs, long magic)
+{
+	struct statfs st_fs;
+
+	if (statfs(fs, &st_fs) < 0)
+		return -ENOENT;
+	else if (st_fs.f_type != magic)
+		return -ENOENT;
+
+	return 0;
+}
+
+static bool fs__check_mounts(struct fs *fs)
+{
+	const char * const *ptr;
+
+	ptr = fs->mounts;
+	while (*ptr) {
+		if (fs__valid_mount(*ptr, fs->magic) == 0) {
+			fs->found = true;
+			strcpy(fs->path, *ptr);
+			return true;
+		}
+		ptr++;
+	}
+
+	return false;
+}
+
+static const char *fs__get_mountpoint(struct fs *fs)
+{
+	if (fs__check_mounts(fs))
+		return fs->path;
+
+	return fs__read_mounts(fs) ? fs->path : NULL;
+}
+
+static const char *fs__mountpoint(int idx)
+{
+	struct fs *fs = &fs__entries[idx];
+
+	if (fs->found)
+		return (const char *)fs->path;
+
+	return fs__get_mountpoint(fs);
+}
+
+#define FS__MOUNTPOINT(name, idx)	\
+const char *name##__mountpoint(void)	\
+{					\
+	return fs__mountpoint(idx);	\
+}
+
+FS__MOUNTPOINT(sysfs,  FS__SYSFS);
+FS__MOUNTPOINT(procfs, FS__PROCFS);
diff --git a/tools/perf/util/fs.h b/tools/perf/util/fs.h
new file mode 100644
index 0000000..5e09ce1
--- /dev/null
+++ b/tools/perf/util/fs.h
@@ -0,0 +1,7 @@
+#ifndef __PERF_FS
+#define __PERF_FS
+
+const char *sysfs__mountpoint(void);
+const char *procfs__mountpoint(void);
+
+#endif /* __PERF_FS */
diff --git a/tools/perf/util/generate-cmdlist.sh b/tools/perf/util/generate-cmdlist.sh
index 3ac3803..36a885d 100755
--- a/tools/perf/util/generate-cmdlist.sh
+++ b/tools/perf/util/generate-cmdlist.sh
@@ -22,7 +22,7 @@
      }' "Documentation/perf-$cmd.txt"
 done
 
-echo "#ifdef LIBELF_SUPPORT"
+echo "#ifdef HAVE_LIBELF_SUPPORT"
 sed -n -e 's/^perf-\([^ 	]*\)[ 	].* full.*/\1/p' command-list.txt |
 sort |
 while read cmd
@@ -35,5 +35,5 @@
 	    p
      }' "Documentation/perf-$cmd.txt"
 done
-echo "#endif /* LIBELF_SUPPORT */"
+echo "#endif /* HAVE_LIBELF_SUPPORT */"
 echo "};"
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index ce69901..26d9520 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -22,6 +22,7 @@
 #include "vdso.h"
 #include "strbuf.h"
 #include "build-id.h"
+#include "data.h"
 
 static bool no_buildid_cache = false;
 
@@ -2189,7 +2190,7 @@
 {
 	struct header_print_data hd;
 	struct perf_header *header = &session->header;
-	int fd = session->fd;
+	int fd = perf_data_file__fd(session->file);
 	hd.fp = fp;
 	hd.full = full;
 
@@ -2650,7 +2651,8 @@
 	struct perf_header *header = &session->header;
 	struct perf_pipe_file_header f_header;
 
-	if (perf_file_header__read_pipe(&f_header, header, session->fd,
+	if (perf_file_header__read_pipe(&f_header, header,
+					perf_data_file__fd(session->file),
 					session->repipe) < 0) {
 		pr_debug("incompatible file format\n");
 		return -EINVAL;
@@ -2751,23 +2753,36 @@
 
 int perf_session__read_header(struct perf_session *session)
 {
+	struct perf_data_file *file = session->file;
 	struct perf_header *header = &session->header;
 	struct perf_file_header	f_header;
 	struct perf_file_attr	f_attr;
 	u64			f_id;
 	int nr_attrs, nr_ids, i, j;
-	int fd = session->fd;
+	int fd = perf_data_file__fd(file);
 
 	session->evlist = perf_evlist__new();
 	if (session->evlist == NULL)
 		return -ENOMEM;
 
-	if (session->fd_pipe)
+	if (perf_data_file__is_pipe(file))
 		return perf_header__read_pipe(session);
 
 	if (perf_file_header__read(&f_header, header, fd) < 0)
 		return -EINVAL;
 
+	/*
+	 * Sanity check that perf.data was written cleanly; data size is
+	 * initialized to 0 and updated only if the on_exit function is run.
+	 * If data size is still 0 then the file contains only partial
+	 * information.  Just warn user and process it as much as it can.
+	 */
+	if (f_header.data.size == 0) {
+		pr_warning("WARNING: The %s file's data size field is 0 which is unexpected.\n"
+			   "Was the 'perf record' command properly terminated?\n",
+			   file->path);
+	}
+
 	nr_attrs = f_header.attrs.size / f_header.attr_size;
 	lseek(fd, f_header.attrs.offset, SEEK_SET);
 
@@ -2978,18 +2993,19 @@
 				     struct perf_session *session)
 {
 	ssize_t size_read, padding, size = event->tracing_data.size;
-	off_t offset = lseek(session->fd, 0, SEEK_CUR);
+	int fd = perf_data_file__fd(session->file);
+	off_t offset = lseek(fd, 0, SEEK_CUR);
 	char buf[BUFSIZ];
 
 	/* setup for reading amidst mmap */
-	lseek(session->fd, offset + sizeof(struct tracing_data_event),
+	lseek(fd, offset + sizeof(struct tracing_data_event),
 	      SEEK_SET);
 
-	size_read = trace_report(session->fd, &session->pevent,
+	size_read = trace_report(fd, &session->pevent,
 				 session->repipe);
 	padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read;
 
-	if (readn(session->fd, buf, padding) < 0) {
+	if (readn(fd, buf, padding) < 0) {
 		pr_err("%s: reading input file", __func__);
 		return -1;
 	}
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 9ff6cf3..822903e 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -160,6 +160,10 @@
 	hists__new_col_len(hists, HISTC_MEM_LVL, 21 + 3);
 	hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12);
 	hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12);
+
+	if (h->transaction)
+		hists__new_col_len(hists, HISTC_TRANSACTION,
+				   hist_entry__transaction_len());
 }
 
 void hists__output_recalc_col_len(struct hists *hists, int max_rows)
@@ -346,7 +350,7 @@
 	struct rb_node **p;
 	struct rb_node *parent = NULL;
 	struct hist_entry *he;
-	int cmp;
+	int64_t cmp;
 
 	p = &hists->entries_in->rb_node;
 
@@ -395,6 +399,7 @@
 	if (!he)
 		return NULL;
 
+	hists->nr_entries++;
 	rb_link_node(&he->rb_node_in, parent, p);
 	rb_insert_color(&he->rb_node_in, hists->entries_in);
 out:
@@ -402,74 +407,16 @@
 	return he;
 }
 
-struct hist_entry *__hists__add_mem_entry(struct hists *self,
-					  struct addr_location *al,
-					  struct symbol *sym_parent,
-					  struct mem_info *mi,
-					  u64 period,
-					  u64 weight)
-{
-	struct hist_entry entry = {
-		.thread	= al->thread,
-		.ms = {
-			.map	= al->map,
-			.sym	= al->sym,
-		},
-		.stat = {
-			.period	= period,
-			.weight = weight,
-			.nr_events = 1,
-		},
-		.cpu	= al->cpu,
-		.ip	= al->addr,
-		.level	= al->level,
-		.parent = sym_parent,
-		.filtered = symbol__parent_filter(sym_parent),
-		.hists = self,
-		.mem_info = mi,
-		.branch_info = NULL,
-	};
-	return add_hist_entry(self, &entry, al, period, weight);
-}
-
-struct hist_entry *__hists__add_branch_entry(struct hists *self,
-					     struct addr_location *al,
-					     struct symbol *sym_parent,
-					     struct branch_info *bi,
-					     u64 period,
-					     u64 weight)
-{
-	struct hist_entry entry = {
-		.thread	= al->thread,
-		.ms = {
-			.map	= bi->to.map,
-			.sym	= bi->to.sym,
-		},
-		.cpu	= al->cpu,
-		.ip	= bi->to.addr,
-		.level	= al->level,
-		.stat = {
-			.period	= period,
-			.nr_events = 1,
-			.weight = weight,
-		},
-		.parent = sym_parent,
-		.filtered = symbol__parent_filter(sym_parent),
-		.branch_info = bi,
-		.hists	= self,
-		.mem_info = NULL,
-	};
-
-	return add_hist_entry(self, &entry, al, period, weight);
-}
-
-struct hist_entry *__hists__add_entry(struct hists *self,
+struct hist_entry *__hists__add_entry(struct hists *hists,
 				      struct addr_location *al,
-				      struct symbol *sym_parent, u64 period,
-				      u64 weight)
+				      struct symbol *sym_parent,
+				      struct branch_info *bi,
+				      struct mem_info *mi,
+				      u64 period, u64 weight, u64 transaction)
 {
 	struct hist_entry entry = {
 		.thread	= al->thread,
+		.comm = thread__comm(al->thread),
 		.ms = {
 			.map	= al->map,
 			.sym	= al->sym,
@@ -478,18 +425,19 @@
 		.ip	= al->addr,
 		.level	= al->level,
 		.stat = {
-			.period	= period,
 			.nr_events = 1,
+			.period	= period,
 			.weight = weight,
 		},
 		.parent = sym_parent,
 		.filtered = symbol__parent_filter(sym_parent),
-		.hists	= self,
-		.branch_info = NULL,
-		.mem_info = NULL,
+		.hists	= hists,
+		.branch_info = bi,
+		.mem_info = mi,
+		.transaction = transaction,
 	};
 
-	return add_hist_entry(self, &entry, al, period, weight);
+	return add_hist_entry(hists, &entry, al, period, weight);
 }
 
 int64_t
@@ -530,6 +478,7 @@
 {
 	free(he->branch_info);
 	free(he->mem_info);
+	free_srcline(he->srcline);
 	free(he);
 }
 
@@ -598,7 +547,7 @@
 	hists__filter_entry_by_symbol(hists, he);
 }
 
-void hists__collapse_resort(struct hists *hists)
+void hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
 {
 	struct rb_root *root;
 	struct rb_node *next;
@@ -625,6 +574,8 @@
 			 */
 			hists__apply_filters(hists, n);
 		}
+		if (prog)
+			ui_progress__update(prog, 1);
 	}
 }
 
@@ -884,7 +835,7 @@
 	struct rb_node **p;
 	struct rb_node *parent = NULL;
 	struct hist_entry *he;
-	int cmp;
+	int64_t cmp;
 
 	if (sort__need_collapse)
 		root = &hists->entries_collapsed;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 1329b6b..b621347a 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -5,6 +5,8 @@
 #include <pthread.h>
 #include "callchain.h"
 #include "header.h"
+#include "color.h"
+#include "ui/progress.h"
 
 extern struct callchain_param callchain_param;
 
@@ -45,6 +47,8 @@
 	HISTC_CPU,
 	HISTC_SRCLINE,
 	HISTC_MISPREDICT,
+	HISTC_IN_TX,
+	HISTC_ABORT,
 	HISTC_SYMBOL_FROM,
 	HISTC_SYMBOL_TO,
 	HISTC_DSO_FROM,
@@ -57,6 +61,7 @@
 	HISTC_MEM_TLB,
 	HISTC_MEM_LVL,
 	HISTC_MEM_SNOOP,
+	HISTC_TRANSACTION,
 	HISTC_NR_COLS, /* Last entry */
 };
 
@@ -79,54 +84,43 @@
 	u16			col_len[HISTC_NR_COLS];
 };
 
-struct hist_entry *__hists__add_entry(struct hists *self,
+struct hist_entry *__hists__add_entry(struct hists *hists,
 				      struct addr_location *al,
-				      struct symbol *parent, u64 period,
-				      u64 weight);
+				      struct symbol *parent,
+				      struct branch_info *bi,
+				      struct mem_info *mi, u64 period,
+				      u64 weight, u64 transaction);
 int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right);
 int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right);
-int hist_entry__sort_snprintf(struct hist_entry *self, char *bf, size_t size,
+int hist_entry__transaction_len(void);
+int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size,
 			      struct hists *hists);
 void hist_entry__free(struct hist_entry *);
 
-struct hist_entry *__hists__add_branch_entry(struct hists *self,
-					     struct addr_location *al,
-					     struct symbol *sym_parent,
-					     struct branch_info *bi,
-					     u64 period,
-					     u64 weight);
-
-struct hist_entry *__hists__add_mem_entry(struct hists *self,
-					  struct addr_location *al,
-					  struct symbol *sym_parent,
-					  struct mem_info *mi,
-					  u64 period,
-					  u64 weight);
-
-void hists__output_resort(struct hists *self);
-void hists__collapse_resort(struct hists *self);
+void hists__output_resort(struct hists *hists);
+void hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
 
 void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
 void hists__output_recalc_col_len(struct hists *hists, int max_rows);
 
 void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h);
-void hists__inc_nr_events(struct hists *self, u32 type);
+void hists__inc_nr_events(struct hists *hists, u32 type);
 void events_stats__inc(struct events_stats *stats, u32 type);
 size_t events_stats__fprintf(struct events_stats *stats, FILE *fp);
 
-size_t hists__fprintf(struct hists *self, bool show_header, int max_rows,
+size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
 		      int max_cols, float min_pcnt, FILE *fp);
 
-int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr);
-int hist_entry__annotate(struct hist_entry *self, size_t privsize);
+int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
+int hist_entry__annotate(struct hist_entry *he, size_t privsize);
 
 void hists__filter_by_dso(struct hists *hists);
 void hists__filter_by_thread(struct hists *hists);
 void hists__filter_by_symbol(struct hists *hists);
 
-u16 hists__col_len(struct hists *self, enum hist_column col);
-void hists__set_col_len(struct hists *self, enum hist_column col, u16 len);
-bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len);
+u16 hists__col_len(struct hists *hists, enum hist_column col);
+void hists__set_col_len(struct hists *hists, enum hist_column col, u16 len);
+bool hists__new_col_len(struct hists *hists, enum hist_column col, u16 len);
 void hists__reset_col_len(struct hists *hists);
 void hists__calc_col_len(struct hists *hists, struct hist_entry *he);
 
@@ -175,6 +169,18 @@
 void perf_hpp__column_register(struct perf_hpp_fmt *format);
 void perf_hpp__column_enable(unsigned col);
 
+static inline size_t perf_hpp__use_color(void)
+{
+	return !symbol_conf.field_sep;
+}
+
+static inline size_t perf_hpp__color_overhead(void)
+{
+	return perf_hpp__use_color() ?
+	       (COLOR_MAXLEN + sizeof(PERF_COLOR_RESET)) * PERF_HPP__MAX_INDEX
+	       : 0;
+}
+
 struct perf_evlist;
 
 struct hist_browser_timer {
@@ -183,7 +189,7 @@
 	int refresh;
 };
 
-#ifdef SLANG_SUPPORT
+#ifdef HAVE_SLANG_SUPPORT
 #include "../ui/keysyms.h"
 int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
 			     struct hist_browser_timer *hbt);
@@ -204,12 +210,9 @@
 	return 0;
 }
 
-static inline int hist_entry__tui_annotate(struct hist_entry *self
-					   __maybe_unused,
-					   struct perf_evsel *evsel
-					   __maybe_unused,
-					   struct hist_browser_timer *hbt
-					   __maybe_unused)
+static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused,
+					   struct perf_evsel *evsel __maybe_unused,
+					   struct hist_browser_timer *hbt __maybe_unused)
 {
 	return 0;
 }
@@ -224,20 +227,5 @@
 #define K_SWITCH_INPUT_DATA -3000
 #endif
 
-#ifdef GTK2_SUPPORT
-int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
-				  struct hist_browser_timer *hbt __maybe_unused,
-				  float min_pcnt);
-#else
-static inline
-int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
-				  const char *help __maybe_unused,
-				  struct hist_browser_timer *hbt __maybe_unused,
-				  float min_pcnt __maybe_unused)
-{
-	return 0;
-}
-#endif
-
-unsigned int hists__sort_list_width(struct hists *self);
+unsigned int hists__sort_list_width(struct hists *hists);
 #endif	/* __PERF_HIST_H */
diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h
index cf6727e..8f14965 100644
--- a/tools/perf/util/include/dwarf-regs.h
+++ b/tools/perf/util/include/dwarf-regs.h
@@ -1,7 +1,7 @@
 #ifndef _PERF_DWARF_REGS_H_
 #define _PERF_DWARF_REGS_H_
 
-#ifdef DWARF_SUPPORT
+#ifdef HAVE_DWARF_SUPPORT
 const char *get_arch_regstr(unsigned int n);
 #endif
 
diff --git a/tools/perf/util/include/linux/compiler.h b/tools/perf/util/include/linux/compiler.h
index 96b919d..b003ad7 100644
--- a/tools/perf/util/include/linux/compiler.h
+++ b/tools/perf/util/include/linux/compiler.h
@@ -2,20 +2,29 @@
 #define _PERF_LINUX_COMPILER_H_
 
 #ifndef __always_inline
-#define __always_inline	inline
+# define __always_inline	inline __attribute__((always_inline))
 #endif
+
 #define __user
+
 #ifndef __attribute_const__
-#define __attribute_const__
+# define __attribute_const__
 #endif
 
 #ifndef __maybe_unused
-#define __maybe_unused		__attribute__((unused))
+# define __maybe_unused		__attribute__((unused))
 #endif
-#define __packed	__attribute__((__packed__))
+
+#ifndef __packed
+# define __packed		__attribute__((__packed__))
+#endif
 
 #ifndef __force
-#define __force
+# define __force
+#endif
+
+#ifndef __weak
+# define __weak			__attribute__((weak))
 #endif
 
 #endif
diff --git a/tools/perf/util/include/linux/magic.h b/tools/perf/util/include/linux/magic.h
index 58b64ed..07d63cf 100644
--- a/tools/perf/util/include/linux/magic.h
+++ b/tools/perf/util/include/linux/magic.h
@@ -9,4 +9,8 @@
 #define SYSFS_MAGIC            0x62656572
 #endif
 
+#ifndef PROC_SUPER_MAGIC
+#define PROC_SUPER_MAGIC       0x9fa0
+#endif
+
 #endif
diff --git a/tools/perf/util/intlist.c b/tools/perf/util/intlist.c
index 11a8d86..89715b6 100644
--- a/tools/perf/util/intlist.c
+++ b/tools/perf/util/intlist.c
@@ -20,6 +20,7 @@
 
 	if (node != NULL) {
 		node->i = i;
+		node->priv = NULL;
 		rc = &node->rb_node;
 	}
 
@@ -57,22 +58,36 @@
 	rblist__remove_node(&ilist->rblist, &node->rb_node);
 }
 
-struct int_node *intlist__find(struct intlist *ilist, int i)
+static struct int_node *__intlist__findnew(struct intlist *ilist,
+					   int i, bool create)
 {
-	struct int_node *node;
+	struct int_node *node = NULL;
 	struct rb_node *rb_node;
 
 	if (ilist == NULL)
 		return NULL;
 
-	node = NULL;
-	rb_node = rblist__find(&ilist->rblist, (void *)((long)i));
+	if (create)
+		rb_node = rblist__findnew(&ilist->rblist, (void *)((long)i));
+	else
+		rb_node = rblist__find(&ilist->rblist, (void *)((long)i));
+
 	if (rb_node)
 		node = container_of(rb_node, struct int_node, rb_node);
 
 	return node;
 }
 
+struct int_node *intlist__find(struct intlist *ilist, int i)
+{
+	return __intlist__findnew(ilist, i, false);
+}
+
+struct int_node *intlist__findnew(struct intlist *ilist, int i)
+{
+	return __intlist__findnew(ilist, i, true);
+}
+
 static int intlist__parse_list(struct intlist *ilist, const char *s)
 {
 	char *sep;
diff --git a/tools/perf/util/intlist.h b/tools/perf/util/intlist.h
index 62351da..aa6877d 100644
--- a/tools/perf/util/intlist.h
+++ b/tools/perf/util/intlist.h
@@ -9,6 +9,7 @@
 struct int_node {
 	struct rb_node rb_node;
 	int i;
+	void *priv;
 };
 
 struct intlist {
@@ -23,6 +24,7 @@
 
 struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx);
 struct int_node *intlist__find(struct intlist *ilist, int i);
+struct int_node *intlist__findnew(struct intlist *ilist, int i);
 
 static inline bool intlist__has_entry(struct intlist *ilist, int i)
 {
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 6188d28..ce034c1 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -40,12 +40,29 @@
 			return -ENOMEM;
 
 		snprintf(comm, sizeof(comm), "[guest/%d]", pid);
-		thread__set_comm(thread, comm);
+		thread__set_comm(thread, comm, 0);
 	}
 
 	return 0;
 }
 
+struct machine *machine__new_host(void)
+{
+	struct machine *machine = malloc(sizeof(*machine));
+
+	if (machine != NULL) {
+		machine__init(machine, "", HOST_KERNEL_ID);
+
+		if (machine__create_kernel_maps(machine) < 0)
+			goto out_delete;
+	}
+
+	return machine;
+out_delete:
+	free(machine);
+	return NULL;
+}
+
 static void dsos__delete(struct list_head *dsos)
 {
 	struct dso *pos, *n;
@@ -314,7 +331,8 @@
 	return __machine__findnew_thread(machine, 0, tid, false);
 }
 
-int machine__process_comm_event(struct machine *machine, union perf_event *event)
+int machine__process_comm_event(struct machine *machine, union perf_event *event,
+				struct perf_sample *sample)
 {
 	struct thread *thread = machine__findnew_thread(machine,
 							event->comm.pid,
@@ -323,7 +341,7 @@
 	if (dump_trace)
 		perf_event__fprintf_comm(event, stdout);
 
-	if (thread == NULL || thread__set_comm(thread, event->comm.comm)) {
+	if (thread == NULL || thread__set_comm(thread, event->comm.comm, sample->time)) {
 		dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
 		return -1;
 	}
@@ -332,7 +350,7 @@
 }
 
 int machine__process_lost_event(struct machine *machine __maybe_unused,
-				union perf_event *event)
+				union perf_event *event, struct perf_sample *sample __maybe_unused)
 {
 	dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
 		    event->lost.id, event->lost.lost);
@@ -776,75 +794,44 @@
 	return map_groups__set_modules_path_dir(&machine->kmaps, modules_path);
 }
 
+static int machine__create_module(void *arg, const char *name, u64 start)
+{
+	struct machine *machine = arg;
+	struct map *map;
+
+	map = machine__new_module(machine, start, name);
+	if (map == NULL)
+		return -1;
+
+	dso__kernel_module_get_build_id(map->dso, machine->root_dir);
+
+	return 0;
+}
+
 static int machine__create_modules(struct machine *machine)
 {
-	char *line = NULL;
-	size_t n;
-	FILE *file;
-	struct map *map;
 	const char *modules;
 	char path[PATH_MAX];
 
-	if (machine__is_default_guest(machine))
+	if (machine__is_default_guest(machine)) {
 		modules = symbol_conf.default_guest_modules;
-	else {
-		sprintf(path, "%s/proc/modules", machine->root_dir);
+	} else {
+		snprintf(path, PATH_MAX, "%s/proc/modules", machine->root_dir);
 		modules = path;
 	}
 
 	if (symbol__restricted_filename(modules, "/proc/modules"))
 		return -1;
 
-	file = fopen(modules, "r");
-	if (file == NULL)
+	if (modules__parse(modules, machine, machine__create_module))
 		return -1;
 
-	while (!feof(file)) {
-		char name[PATH_MAX];
-		u64 start;
-		char *sep;
-		int line_len;
+	if (!machine__set_modules_path(machine))
+		return 0;
 
-		line_len = getline(&line, &n, file);
-		if (line_len < 0)
-			break;
+	pr_debug("Problems setting modules path maps, continuing anyway...\n");
 
-		if (!line)
-			goto out_failure;
-
-		line[--line_len] = '\0'; /* \n */
-
-		sep = strrchr(line, 'x');
-		if (sep == NULL)
-			continue;
-
-		hex2u64(sep + 1, &start);
-
-		sep = strchr(line, ' ');
-		if (sep == NULL)
-			continue;
-
-		*sep = '\0';
-
-		snprintf(name, sizeof(name), "[%s]", line);
-		map = machine__new_module(machine, start, name);
-		if (map == NULL)
-			goto out_delete_line;
-		dso__kernel_module_get_build_id(map->dso, machine->root_dir);
-	}
-
-	free(line);
-	fclose(file);
-
-	if (machine__set_modules_path(machine) < 0) {
-		pr_debug("Problems setting modules path maps, continuing anyway...\n");
-	}
 	return 0;
-
-out_delete_line:
-	free(line);
-out_failure:
-	return -1;
 }
 
 int machine__create_kernel_maps(struct machine *machine)
@@ -998,7 +985,8 @@
 }
 
 int machine__process_mmap2_event(struct machine *machine,
-				 union perf_event *event)
+				 union perf_event *event,
+				 struct perf_sample *sample __maybe_unused)
 {
 	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
 	struct thread *thread;
@@ -1045,7 +1033,8 @@
 	return 0;
 }
 
-int machine__process_mmap_event(struct machine *machine, union perf_event *event)
+int machine__process_mmap_event(struct machine *machine, union perf_event *event,
+				struct perf_sample *sample __maybe_unused)
 {
 	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
 	struct thread *thread;
@@ -1102,7 +1091,8 @@
 	list_add_tail(&th->node, &machine->dead_threads);
 }
 
-int machine__process_fork_event(struct machine *machine, union perf_event *event)
+int machine__process_fork_event(struct machine *machine, union perf_event *event,
+				struct perf_sample *sample)
 {
 	struct thread *thread = machine__find_thread(machine, event->fork.tid);
 	struct thread *parent = machine__findnew_thread(machine,
@@ -1119,7 +1109,7 @@
 		perf_event__fprintf_task(event, stdout);
 
 	if (thread == NULL || parent == NULL ||
-	    thread__fork(thread, parent) < 0) {
+	    thread__fork(thread, parent, sample->time) < 0) {
 		dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
 		return -1;
 	}
@@ -1127,8 +1117,8 @@
 	return 0;
 }
 
-int machine__process_exit_event(struct machine *machine __maybe_unused,
-				union perf_event *event)
+int machine__process_exit_event(struct machine *machine, union perf_event *event,
+				struct perf_sample *sample __maybe_unused)
 {
 	struct thread *thread = machine__find_thread(machine, event->fork.tid);
 
@@ -1141,23 +1131,24 @@
 	return 0;
 }
 
-int machine__process_event(struct machine *machine, union perf_event *event)
+int machine__process_event(struct machine *machine, union perf_event *event,
+			   struct perf_sample *sample)
 {
 	int ret;
 
 	switch (event->header.type) {
 	case PERF_RECORD_COMM:
-		ret = machine__process_comm_event(machine, event); break;
+		ret = machine__process_comm_event(machine, event, sample); break;
 	case PERF_RECORD_MMAP:
-		ret = machine__process_mmap_event(machine, event); break;
+		ret = machine__process_mmap_event(machine, event, sample); break;
 	case PERF_RECORD_MMAP2:
-		ret = machine__process_mmap2_event(machine, event); break;
+		ret = machine__process_mmap2_event(machine, event, sample); break;
 	case PERF_RECORD_FORK:
-		ret = machine__process_fork_event(machine, event); break;
+		ret = machine__process_fork_event(machine, event, sample); break;
 	case PERF_RECORD_EXIT:
-		ret = machine__process_exit_event(machine, event); break;
+		ret = machine__process_exit_event(machine, event, sample); break;
 	case PERF_RECORD_LOST:
-		ret = machine__process_lost_event(machine, event); break;
+		ret = machine__process_lost_event(machine, event, sample); break;
 	default:
 		ret = -1;
 		break;
@@ -1267,10 +1258,12 @@
 					     struct thread *thread,
 					     struct ip_callchain *chain,
 					     struct symbol **parent,
-					     struct addr_location *root_al)
+					     struct addr_location *root_al,
+					     int max_stack)
 {
 	u8 cpumode = PERF_RECORD_MISC_USER;
-	unsigned int i;
+	int chain_nr = min(max_stack, (int)chain->nr);
+	int i;
 	int err;
 
 	callchain_cursor_reset(&callchain_cursor);
@@ -1280,7 +1273,7 @@
 		return 0;
 	}
 
-	for (i = 0; i < chain->nr; i++) {
+	for (i = 0; i < chain_nr; i++) {
 		u64 ip;
 		struct addr_location al;
 
@@ -1352,12 +1345,14 @@
 			       struct thread *thread,
 			       struct perf_sample *sample,
 			       struct symbol **parent,
-			       struct addr_location *root_al)
+			       struct addr_location *root_al,
+			       int max_stack)
 {
 	int ret;
 
 	ret = machine__resolve_callchain_sample(machine, thread,
-						sample->callchain, parent, root_al);
+						sample->callchain, parent,
+						root_al, max_stack);
 	if (ret)
 		return ret;
 
@@ -1376,3 +1371,26 @@
 				   sample);
 
 }
+
+int machine__for_each_thread(struct machine *machine,
+			     int (*fn)(struct thread *thread, void *p),
+			     void *priv)
+{
+	struct rb_node *nd;
+	struct thread *thread;
+	int rc = 0;
+
+	for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
+		thread = rb_entry(nd, struct thread, rb_node);
+		rc = fn(thread, priv);
+		if (rc != 0)
+			return rc;
+	}
+
+	list_for_each_entry(thread, &machine->dead_threads, node) {
+		rc = fn(thread, priv);
+		if (rc != 0)
+			return rc;
+	}
+	return rc;
+}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 58a6be1..2389ba8 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -40,13 +40,20 @@
 
 struct thread *machine__find_thread(struct machine *machine, pid_t tid);
 
-int machine__process_comm_event(struct machine *machine, union perf_event *event);
-int machine__process_exit_event(struct machine *machine, union perf_event *event);
-int machine__process_fork_event(struct machine *machine, union perf_event *event);
-int machine__process_lost_event(struct machine *machine, union perf_event *event);
-int machine__process_mmap_event(struct machine *machine, union perf_event *event);
-int machine__process_mmap2_event(struct machine *machine, union perf_event *event);
-int machine__process_event(struct machine *machine, union perf_event *event);
+int machine__process_comm_event(struct machine *machine, union perf_event *event,
+				struct perf_sample *sample);
+int machine__process_exit_event(struct machine *machine, union perf_event *event,
+				struct perf_sample *sample);
+int machine__process_fork_event(struct machine *machine, union perf_event *event,
+				struct perf_sample *sample);
+int machine__process_lost_event(struct machine *machine, union perf_event *event,
+				struct perf_sample *sample);
+int machine__process_mmap_event(struct machine *machine, union perf_event *event,
+				struct perf_sample *sample);
+int machine__process_mmap2_event(struct machine *machine, union perf_event *event,
+				 struct perf_sample *sample);
+int machine__process_event(struct machine *machine, union perf_event *event,
+				struct perf_sample *sample);
 
 typedef void (*machine__process_t)(struct machine *machine, void *data);
 
@@ -74,6 +81,7 @@
 void machines__set_symbol_filter(struct machines *machines,
 				 symbol_filter_t symbol_filter);
 
+struct machine *machine__new_host(void);
 int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
 void machine__exit(struct machine *machine);
 void machine__delete_dead_threads(struct machine *machine);
@@ -91,7 +99,8 @@
 			       struct thread *thread,
 			       struct perf_sample *sample,
 			       struct symbol **parent,
-			       struct addr_location *root_al);
+			       struct addr_location *root_al,
+			       int max_stack);
 
 /*
  * Default guest kernel is defined by parameter --guestkallsyms
@@ -165,4 +174,8 @@
 
 size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
 
+int machine__for_each_thread(struct machine *machine,
+			     int (*fn)(struct thread *thread, void *p),
+			     void *priv);
+
 #endif /* __PERF_MACHINE_H */
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 4f6680d..ef5bc91 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -172,7 +172,7 @@
 		pr_warning(", continuing without symbols\n");
 		return -1;
 	} else if (nr == 0) {
-#ifdef LIBELF_SUPPORT
+#ifdef HAVE_LIBELF_SUPPORT
 		const size_t len = strlen(name);
 		const size_t real_len = len - sizeof(DSO__DELETED);
 
@@ -252,10 +252,16 @@
 	return fprintf(fp, "%s", dsoname);
 }
 
-/*
+/**
+ * map__rip_2objdump - convert symbol start address to objdump address.
+ * @map: memory map
+ * @rip: symbol start address
+ *
  * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN.
  * map->dso->adjust_symbols==1 for ET_EXEC-like cases except ET_REL which is
  * relative to section start.
+ *
+ * Return: Address suitable for passing to "objdump --start-address="
  */
 u64 map__rip_2objdump(struct map *map, u64 rip)
 {
@@ -268,6 +274,29 @@
 	return map->unmap_ip(map, rip);
 }
 
+/**
+ * map__objdump_2mem - convert objdump address to a memory address.
+ * @map: memory map
+ * @ip: objdump address
+ *
+ * Closely related to map__rip_2objdump(), this function takes an address from
+ * objdump and converts it to a memory address.  Note this assumes that @map
+ * contains the address.  To be sure the result is valid, check it forwards
+ * e.g. map__rip_2objdump(map->map_ip(map, map__objdump_2mem(map, ip))) == ip
+ *
+ * Return: Memory address.
+ */
+u64 map__objdump_2mem(struct map *map, u64 ip)
+{
+	if (!map->dso->adjust_symbols)
+		return map->unmap_ip(map, ip);
+
+	if (map->dso->rel)
+		return map->unmap_ip(map, ip + map->pgoff);
+
+	return ip;
+}
+
 void map_groups__init(struct map_groups *mg)
 {
 	int i;
@@ -371,6 +400,23 @@
 	return NULL;
 }
 
+int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter)
+{
+	if (ams->addr < ams->map->start || ams->addr > ams->map->end) {
+		if (ams->map->groups == NULL)
+			return -1;
+		ams->map = map_groups__find(ams->map->groups, ams->map->type,
+					    ams->addr);
+		if (ams->map == NULL)
+			return -1;
+	}
+
+	ams->al_addr = ams->map->map_ip(ams->map, ams->addr);
+	ams->sym = map__find_symbol(ams->map, ams->al_addr, filter);
+
+	return ams->sym ? 0 : -1;
+}
+
 size_t __map_groups__fprintf_maps(struct map_groups *mg,
 				  enum map_type type, int verbose, FILE *fp)
 {
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 4886ca2..e4e259c 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -84,6 +84,9 @@
 /* rip/ip <-> addr suitable for passing to `objdump --start-address=` */
 u64 map__rip_2objdump(struct map *map, u64 rip);
 
+/* objdump address -> memory address */
+u64 map__objdump_2mem(struct map *map, u64 ip);
+
 struct symbol;
 
 typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
@@ -167,6 +170,10 @@
 					       struct map **mapp,
 					       symbol_filter_t filter);
 
+struct addr_map_symbol;
+
+int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter);
+
 static inline
 struct symbol *map_groups__find_function_by_name(struct map_groups *mg,
 						 const char *name, struct map **mapp,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 9812531..c90e55c 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -998,8 +998,10 @@
 	char evt_path[MAXPATHLEN];
 	char dir_path[MAXPATHLEN];
 
-	if (debugfs_valid_mountpoint(tracing_events_path))
+	if (debugfs_valid_mountpoint(tracing_events_path)) {
+		printf("  [ Tracepoints not available: %s ]\n", strerror(errno));
 		return;
+	}
 
 	sys_dir = opendir(tracing_events_path);
 	if (!sys_dir)
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 91346b7..3432995 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -126,6 +126,37 @@
 
 }
 
+<config>{
+config			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
+config1			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
+config2			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
+name			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
+period			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
+branch_type		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
+,			{ return ','; }
+"/"			{ BEGIN(INITIAL); return '/'; }
+{name_minus}		{ return str(yyscanner, PE_NAME); }
+}
+
+<mem>{
+{modifier_bp}		{ return str(yyscanner, PE_MODIFIER_BP); }
+:			{ return ':'; }
+{num_dec}		{ return value(yyscanner, 10); }
+{num_hex}		{ return value(yyscanner, 16); }
+	/*
+	 * We need to separate 'mem:' scanner part, in order to get specific
+	 * modifier bits parsed out. Otherwise we would need to handle PE_NAME
+	 * and we'd need to parse it manually. During the escape from <mem>
+	 * state we need to put the escaping char back, so we dont miss it.
+	 */
+.			{ unput(*yytext); BEGIN(INITIAL); }
+	/*
+	 * We destroy the scanner after reaching EOF,
+	 * but anyway just to be sure get back to INIT state.
+	 */
+<<EOF>>			{ BEGIN(INITIAL); }
+}
+
 cpu-cycles|cycles				{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
 stalled-cycles-frontend|idle-cycles-frontend	{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
 stalled-cycles-backend|idle-cycles-backend	{ return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
@@ -162,18 +193,6 @@
 refs|Reference|ops|access		|
 misses|miss				{ return str(yyscanner, PE_NAME_CACHE_OP_RESULT); }
 
-<config>{
-config			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
-config1			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
-config2			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
-name			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
-period			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
-branch_type		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
-,			{ return ','; }
-"/"			{ BEGIN(INITIAL); return '/'; }
-{name_minus}		{ return str(yyscanner, PE_NAME); }
-}
-
 mem:			{ BEGIN(mem); return PE_PREFIX_MEM; }
 r{num_raw_hex}		{ return raw(yyscanner); }
 {num_dec}		{ return value(yyscanner, 10); }
@@ -189,25 +208,7 @@
 "}"			{ return '}'; }
 =			{ return '='; }
 \n			{ }
-
-<mem>{
-{modifier_bp}		{ return str(yyscanner, PE_MODIFIER_BP); }
-:			{ return ':'; }
-{num_dec}		{ return value(yyscanner, 10); }
-{num_hex}		{ return value(yyscanner, 16); }
-	/*
-	 * We need to separate 'mem:' scanner part, in order to get specific
-	 * modifier bits parsed out. Otherwise we would need to handle PE_NAME
-	 * and we'd need to parse it manually. During the escape from <mem>
-	 * state we need to put the escaping char back, so we dont miss it.
-	 */
-.			{ unput(*yytext); BEGIN(INITIAL); }
-	/*
-	 * We destroy the scanner after reaching EOF,
-	 * but anyway just to be sure get back to INIT state.
-	 */
-<<EOF>>			{ BEGIN(INITIAL); }
-}
+.			{ }
 
 %%
 
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 2bc9e70..31f404a 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -339,10 +339,10 @@
 		if (arg[1] != '-') {
 			ctx->opt = arg + 1;
 			if (internal_help && *ctx->opt == 'h')
-				return parse_options_usage(usagestr, options);
+				return usage_with_options_internal(usagestr, options, 0);
 			switch (parse_short_opt(ctx, options)) {
 			case -1:
-				return parse_options_usage(usagestr, options);
+				return parse_options_usage(usagestr, options, arg + 1, 1);
 			case -2:
 				goto unknown;
 			default:
@@ -352,10 +352,11 @@
 				check_typos(arg + 1, options);
 			while (ctx->opt) {
 				if (internal_help && *ctx->opt == 'h')
-					return parse_options_usage(usagestr, options);
+					return usage_with_options_internal(usagestr, options, 0);
+				arg = ctx->opt;
 				switch (parse_short_opt(ctx, options)) {
 				case -1:
-					return parse_options_usage(usagestr, options);
+					return parse_options_usage(usagestr, options, arg, 1);
 				case -2:
 					/* fake a short option thing to hide the fact that we may have
 					 * started to parse aggregated stuff
@@ -383,12 +384,12 @@
 		if (internal_help && !strcmp(arg + 2, "help-all"))
 			return usage_with_options_internal(usagestr, options, 1);
 		if (internal_help && !strcmp(arg + 2, "help"))
-			return parse_options_usage(usagestr, options);
+			return usage_with_options_internal(usagestr, options, 0);
 		if (!strcmp(arg + 2, "list-opts"))
 			return PARSE_OPT_LIST;
 		switch (parse_long_opt(ctx, arg + 2, options)) {
 		case -1:
-			return parse_options_usage(usagestr, options);
+			return parse_options_usage(usagestr, options, arg + 2, 0);
 		case -2:
 			goto unknown;
 		default:
@@ -445,6 +446,89 @@
 #define USAGE_OPTS_WIDTH 24
 #define USAGE_GAP         2
 
+static void print_option_help(const struct option *opts, int full)
+{
+	size_t pos;
+	int pad;
+
+	if (opts->type == OPTION_GROUP) {
+		fputc('\n', stderr);
+		if (*opts->help)
+			fprintf(stderr, "%s\n", opts->help);
+		return;
+	}
+	if (!full && (opts->flags & PARSE_OPT_HIDDEN))
+		return;
+
+	pos = fprintf(stderr, "    ");
+	if (opts->short_name)
+		pos += fprintf(stderr, "-%c", opts->short_name);
+	else
+		pos += fprintf(stderr, "    ");
+
+	if (opts->long_name && opts->short_name)
+		pos += fprintf(stderr, ", ");
+	if (opts->long_name)
+		pos += fprintf(stderr, "--%s", opts->long_name);
+
+	switch (opts->type) {
+	case OPTION_ARGUMENT:
+		break;
+	case OPTION_LONG:
+	case OPTION_U64:
+	case OPTION_INTEGER:
+	case OPTION_UINTEGER:
+		if (opts->flags & PARSE_OPT_OPTARG)
+			if (opts->long_name)
+				pos += fprintf(stderr, "[=<n>]");
+			else
+				pos += fprintf(stderr, "[<n>]");
+		else
+			pos += fprintf(stderr, " <n>");
+		break;
+	case OPTION_CALLBACK:
+		if (opts->flags & PARSE_OPT_NOARG)
+			break;
+		/* FALLTHROUGH */
+	case OPTION_STRING:
+		if (opts->argh) {
+			if (opts->flags & PARSE_OPT_OPTARG)
+				if (opts->long_name)
+					pos += fprintf(stderr, "[=<%s>]", opts->argh);
+				else
+					pos += fprintf(stderr, "[<%s>]", opts->argh);
+			else
+				pos += fprintf(stderr, " <%s>", opts->argh);
+		} else {
+			if (opts->flags & PARSE_OPT_OPTARG)
+				if (opts->long_name)
+					pos += fprintf(stderr, "[=...]");
+				else
+					pos += fprintf(stderr, "[...]");
+			else
+				pos += fprintf(stderr, " ...");
+		}
+		break;
+	default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */
+	case OPTION_END:
+	case OPTION_GROUP:
+	case OPTION_BIT:
+	case OPTION_BOOLEAN:
+	case OPTION_INCR:
+	case OPTION_SET_UINT:
+	case OPTION_SET_PTR:
+		break;
+	}
+
+	if (pos <= USAGE_OPTS_WIDTH)
+		pad = USAGE_OPTS_WIDTH - pos;
+	else {
+		fputc('\n', stderr);
+		pad = USAGE_OPTS_WIDTH;
+	}
+	fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
+}
+
 int usage_with_options_internal(const char * const *usagestr,
 				const struct option *opts, int full)
 {
@@ -464,87 +548,9 @@
 	if (opts->type != OPTION_GROUP)
 		fputc('\n', stderr);
 
-	for (; opts->type != OPTION_END; opts++) {
-		size_t pos;
-		int pad;
+	for (  ; opts->type != OPTION_END; opts++)
+		print_option_help(opts, full);
 
-		if (opts->type == OPTION_GROUP) {
-			fputc('\n', stderr);
-			if (*opts->help)
-				fprintf(stderr, "%s\n", opts->help);
-			continue;
-		}
-		if (!full && (opts->flags & PARSE_OPT_HIDDEN))
-			continue;
-
-		pos = fprintf(stderr, "    ");
-		if (opts->short_name)
-			pos += fprintf(stderr, "-%c", opts->short_name);
-		else
-			pos += fprintf(stderr, "    ");
-
-		if (opts->long_name && opts->short_name)
-			pos += fprintf(stderr, ", ");
-		if (opts->long_name)
-			pos += fprintf(stderr, "--%s", opts->long_name);
-
-		switch (opts->type) {
-		case OPTION_ARGUMENT:
-			break;
-		case OPTION_LONG:
-		case OPTION_U64:
-		case OPTION_INTEGER:
-		case OPTION_UINTEGER:
-			if (opts->flags & PARSE_OPT_OPTARG)
-				if (opts->long_name)
-					pos += fprintf(stderr, "[=<n>]");
-				else
-					pos += fprintf(stderr, "[<n>]");
-			else
-				pos += fprintf(stderr, " <n>");
-			break;
-		case OPTION_CALLBACK:
-			if (opts->flags & PARSE_OPT_NOARG)
-				break;
-			/* FALLTHROUGH */
-		case OPTION_STRING:
-			if (opts->argh) {
-				if (opts->flags & PARSE_OPT_OPTARG)
-					if (opts->long_name)
-						pos += fprintf(stderr, "[=<%s>]", opts->argh);
-					else
-						pos += fprintf(stderr, "[<%s>]", opts->argh);
-				else
-					pos += fprintf(stderr, " <%s>", opts->argh);
-			} else {
-				if (opts->flags & PARSE_OPT_OPTARG)
-					if (opts->long_name)
-						pos += fprintf(stderr, "[=...]");
-					else
-						pos += fprintf(stderr, "[...]");
-				else
-					pos += fprintf(stderr, " ...");
-			}
-			break;
-		default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */
-		case OPTION_END:
-		case OPTION_GROUP:
-		case OPTION_BIT:
-		case OPTION_BOOLEAN:
-		case OPTION_INCR:
-		case OPTION_SET_UINT:
-		case OPTION_SET_PTR:
-			break;
-		}
-
-		if (pos <= USAGE_OPTS_WIDTH)
-			pad = USAGE_OPTS_WIDTH - pos;
-		else {
-			fputc('\n', stderr);
-			pad = USAGE_OPTS_WIDTH;
-		}
-		fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
-	}
 	fputc('\n', stderr);
 
 	return PARSE_OPT_HELP;
@@ -559,9 +565,45 @@
 }
 
 int parse_options_usage(const char * const *usagestr,
-			const struct option *opts)
+			const struct option *opts,
+			const char *optstr, bool short_opt)
 {
-	return usage_with_options_internal(usagestr, opts, 0);
+	if (!usagestr)
+		goto opt;
+
+	fprintf(stderr, "\n usage: %s\n", *usagestr++);
+	while (*usagestr && **usagestr)
+		fprintf(stderr, "    or: %s\n", *usagestr++);
+	while (*usagestr) {
+		fprintf(stderr, "%s%s\n",
+				**usagestr ? "    " : "",
+				*usagestr);
+		usagestr++;
+	}
+	fputc('\n', stderr);
+
+opt:
+	for (  ; opts->type != OPTION_END; opts++) {
+		if (short_opt) {
+			if (opts->short_name == *optstr)
+				break;
+			continue;
+		}
+
+		if (opts->long_name == NULL)
+			continue;
+
+		if (!prefixcmp(optstr, opts->long_name))
+			break;
+		if (!prefixcmp(optstr, "no-") &&
+		    !prefixcmp(optstr + 3, opts->long_name))
+			break;
+	}
+
+	if (opts->type != OPTION_END)
+		print_option_help(opts, 0);
+
+	return PARSE_OPT_HELP;
 }
 
 
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index 7bb5999..b0241e2 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -158,7 +158,9 @@
 };
 
 extern int parse_options_usage(const char * const *usagestr,
-			       const struct option *opts);
+			       const struct option *opts,
+			       const char *optstr,
+			       bool short_opt);
 
 extern void parse_options_start(struct parse_opt_ctx_t *ctx,
 				int argc, const char **argv, int flags);
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index a8c4954..5d13cb4 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -22,19 +22,23 @@
 	return ".";
 }
 
-#ifndef HAVE_STRLCPY
-size_t strlcpy(char *dest, const char *src, size_t size)
+/*
+ * If libc has strlcpy() then that version will override this
+ * implementation:
+ */
+size_t __weak strlcpy(char *dest, const char *src, size_t size)
 {
 	size_t ret = strlen(src);
 
 	if (size) {
 		size_t len = (ret >= size) ? size - 1 : ret;
+
 		memcpy(dest, src, len);
 		dest[len] = '\0';
 	}
+
 	return ret;
 }
-#endif
 
 static char *get_pathname(void)
 {
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 5a4f2b6f..a3d42cd 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -1,7 +1,7 @@
 #ifndef __PERF_REGS_H
 #define __PERF_REGS_H
 
-#ifdef HAVE_PERF_REGS
+#ifdef HAVE_PERF_REGS_SUPPORT
 #include <perf_regs.h>
 #else
 #define PERF_REGS_MASK	0
@@ -10,5 +10,5 @@
 {
 	return NULL;
 }
-#endif /* HAVE_PERF_REGS */
+#endif /* HAVE_PERF_REGS_SUPPORT */
 #endif /* __PERF_REGS_H */
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index bc9d806..c232d8d 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -4,7 +4,7 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <dirent.h>
-#include "sysfs.h"
+#include "fs.h"
 #include "util.h"
 #include "pmu.h"
 #include "parse-events.h"
@@ -77,9 +77,8 @@
 {
 	struct stat st;
 	char path[PATH_MAX];
-	const char *sysfs;
+	const char *sysfs = sysfs__mountpoint();
 
-	sysfs = sysfs_find_mountpoint();
 	if (!sysfs)
 		return -1;
 
@@ -166,9 +165,8 @@
 {
 	struct stat st;
 	char path[PATH_MAX];
-	const char *sysfs;
+	const char *sysfs = sysfs__mountpoint();
 
-	sysfs = sysfs_find_mountpoint();
 	if (!sysfs)
 		return -1;
 
@@ -212,11 +210,10 @@
 {
 	struct stat st;
 	char path[PATH_MAX];
-	const char *sysfs;
 	FILE *file;
 	int ret = 0;
+	const char *sysfs = sysfs__mountpoint();
 
-	sysfs = sysfs_find_mountpoint();
 	if (!sysfs)
 		return -1;
 
@@ -241,11 +238,10 @@
 static void pmu_read_sysfs(void)
 {
 	char path[PATH_MAX];
-	const char *sysfs;
 	DIR *dir;
 	struct dirent *dent;
+	const char *sysfs = sysfs__mountpoint();
 
-	sysfs = sysfs_find_mountpoint();
 	if (!sysfs)
 		return;
 
@@ -270,11 +266,10 @@
 {
 	struct stat st;
 	char path[PATH_MAX];
-	const char *sysfs;
 	FILE *file;
 	struct cpu_map *cpus;
+	const char *sysfs = sysfs__mountpoint();
 
-	sysfs = sysfs_find_mountpoint();
 	if (!sysfs)
 		return NULL;
 
@@ -637,3 +632,19 @@
 		printf("\n");
 	free(aliases);
 }
+
+bool pmu_have_event(const char *pname, const char *name)
+{
+	struct perf_pmu *pmu;
+	struct perf_pmu_alias *alias;
+
+	pmu = NULL;
+	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
+		if (strcmp(pname, pmu->name))
+			continue;
+		list_for_each_entry(alias, &pmu->aliases, list)
+			if (!strcmp(alias->name, name))
+				return true;
+	}
+	return false;
+}
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 6b2cbe2..1179b26 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -42,6 +42,7 @@
 struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
 
 void print_pmu_events(const char *event_glob, bool name_only);
+bool pmu_have_event(const char *pname, const char *name);
 
 int perf_pmu__test(void);
 #endif /* __PMU_H */
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index aa04bf9..9c6989c 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -47,7 +47,6 @@
 #include "session.h"
 
 #define MAX_CMDLEN 256
-#define MAX_PROBE_ARGS 128
 #define PERFPROBE_GROUP "probe"
 
 bool probe_event_dry_run;	/* Dry run flag */
@@ -201,7 +200,7 @@
 	return 0;
 }
 
-#ifdef DWARF_SUPPORT
+#ifdef HAVE_DWARF_SUPPORT
 /* Open new debuginfo of given module */
 static struct debuginfo *open_debuginfo(const char *module)
 {
@@ -630,7 +629,7 @@
 	return ret;
 }
 
-#else	/* !DWARF_SUPPORT */
+#else	/* !HAVE_DWARF_SUPPORT */
 
 static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
 					struct perf_probe_point *pp)
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 371476c..ffb657f 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -115,7 +115,7 @@
 };
 
 /* Get a Dwarf from offline image */
-static int debuginfo__init_offline_dwarf(struct debuginfo *self,
+static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
 					 const char *path)
 {
 	int fd;
@@ -124,25 +124,25 @@
 	if (fd < 0)
 		return fd;
 
-	self->dwfl = dwfl_begin(&offline_callbacks);
-	if (!self->dwfl)
+	dbg->dwfl = dwfl_begin(&offline_callbacks);
+	if (!dbg->dwfl)
 		goto error;
 
-	self->mod = dwfl_report_offline(self->dwfl, "", "", fd);
-	if (!self->mod)
+	dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd);
+	if (!dbg->mod)
 		goto error;
 
-	self->dbg = dwfl_module_getdwarf(self->mod, &self->bias);
-	if (!self->dbg)
+	dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias);
+	if (!dbg->dbg)
 		goto error;
 
 	return 0;
 error:
-	if (self->dwfl)
-		dwfl_end(self->dwfl);
+	if (dbg->dwfl)
+		dwfl_end(dbg->dwfl);
 	else
 		close(fd);
-	memset(self, 0, sizeof(*self));
+	memset(dbg, 0, sizeof(*dbg));
 
 	return -ENOENT;
 }
@@ -180,24 +180,24 @@
 };
 
 /* Get a Dwarf from live kernel image */
-static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
+static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
 					       Dwarf_Addr addr)
 {
-	self->dwfl = dwfl_begin(&kernel_callbacks);
-	if (!self->dwfl)
+	dbg->dwfl = dwfl_begin(&kernel_callbacks);
+	if (!dbg->dwfl)
 		return -EINVAL;
 
 	/* Load the kernel dwarves: Don't care the result here */
-	dwfl_linux_kernel_report_kernel(self->dwfl);
-	dwfl_linux_kernel_report_modules(self->dwfl);
+	dwfl_linux_kernel_report_kernel(dbg->dwfl);
+	dwfl_linux_kernel_report_modules(dbg->dwfl);
 
-	self->dbg = dwfl_addrdwarf(self->dwfl, addr, &self->bias);
+	dbg->dbg = dwfl_addrdwarf(dbg->dwfl, addr, &dbg->bias);
 	/* Here, check whether we could get a real dwarf */
-	if (!self->dbg) {
+	if (!dbg->dbg) {
 		pr_debug("Failed to find kernel dwarf at %lx\n",
 			 (unsigned long)addr);
-		dwfl_end(self->dwfl);
-		memset(self, 0, sizeof(*self));
+		dwfl_end(dbg->dwfl);
+		memset(dbg, 0, sizeof(*dbg));
 		return -ENOENT;
 	}
 
@@ -205,7 +205,7 @@
 }
 #else
 /* With older elfutils, this just support kernel module... */
-static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
+static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
 					       Dwarf_Addr addr __maybe_unused)
 {
 	const char *path = kernel_get_module_path("kernel");
@@ -216,44 +216,45 @@
 	}
 
 	pr_debug2("Use file %s for debuginfo\n", path);
-	return debuginfo__init_offline_dwarf(self, path);
+	return debuginfo__init_offline_dwarf(dbg, path);
 }
 #endif
 
 struct debuginfo *debuginfo__new(const char *path)
 {
-	struct debuginfo *self = zalloc(sizeof(struct debuginfo));
-	if (!self)
+	struct debuginfo *dbg = zalloc(sizeof(*dbg));
+	if (!dbg)
 		return NULL;
 
-	if (debuginfo__init_offline_dwarf(self, path) < 0) {
-		free(self);
-		self = NULL;
+	if (debuginfo__init_offline_dwarf(dbg, path) < 0) {
+		free(dbg);
+		dbg = NULL;
 	}
 
-	return self;
+	return dbg;
 }
 
 struct debuginfo *debuginfo__new_online_kernel(unsigned long addr)
 {
-	struct debuginfo *self = zalloc(sizeof(struct debuginfo));
-	if (!self)
+	struct debuginfo *dbg = zalloc(sizeof(*dbg));
+
+	if (!dbg)
 		return NULL;
 
-	if (debuginfo__init_online_kernel_dwarf(self, (Dwarf_Addr)addr) < 0) {
-		free(self);
-		self = NULL;
+	if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0) {
+		free(dbg);
+		dbg = NULL;
 	}
 
-	return self;
+	return dbg;
 }
 
-void debuginfo__delete(struct debuginfo *self)
+void debuginfo__delete(struct debuginfo *dbg)
 {
-	if (self) {
-		if (self->dwfl)
-			dwfl_end(self->dwfl);
-		free(self);
+	if (dbg) {
+		if (dbg->dwfl)
+			dwfl_end(dbg->dwfl);
+		free(dbg);
 	}
 }
 
@@ -273,12 +274,15 @@
 /*
  * Convert a location into trace_arg.
  * If tvar == NULL, this just checks variable can be converted.
+ * If fentry == true and vr_die is a parameter, do huristic search
+ * for the location fuzzed by function entry mcount.
  */
 static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
-				     Dwarf_Op *fb_ops,
+				     Dwarf_Op *fb_ops, Dwarf_Die *sp_die,
 				     struct probe_trace_arg *tvar)
 {
 	Dwarf_Attribute attr;
+	Dwarf_Addr tmp = 0;
 	Dwarf_Op *op;
 	size_t nops;
 	unsigned int regn;
@@ -291,12 +295,29 @@
 		goto static_var;
 
 	/* TODO: handle more than 1 exprs */
-	if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL ||
-	    dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0 ||
-	    nops == 0) {
-		/* TODO: Support const_value */
+	if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
+		return -EINVAL;	/* Broken DIE ? */
+	if (dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0) {
+		ret = dwarf_entrypc(sp_die, &tmp);
+		if (ret || addr != tmp ||
+		    dwarf_tag(vr_die) != DW_TAG_formal_parameter ||
+		    dwarf_highpc(sp_die, &tmp))
+			return -ENOENT;
+		/*
+		 * This is fuzzed by fentry mcount. We try to find the
+		 * parameter location at the earliest address.
+		 */
+		for (addr += 1; addr <= tmp; addr++) {
+			if (dwarf_getlocation_addr(&attr, addr, &op,
+						   &nops, 1) > 0)
+				goto found;
+		}
 		return -ENOENT;
 	}
+found:
+	if (nops == 0)
+		/* TODO: Support const_value */
+		return -ENOENT;
 
 	if (op->atom == DW_OP_addr) {
 static_var:
@@ -563,7 +584,7 @@
 	}
 
 	if (die_find_member(&type, field->name, die_mem) == NULL) {
-		pr_warning("%s(tyep:%s) has no member %s.\n", varname,
+		pr_warning("%s(type:%s) has no member %s.\n", varname,
 			   dwarf_diename(&type), field->name);
 		return -EINVAL;
 	}
@@ -600,7 +621,7 @@
 		 dwarf_diename(vr_die));
 
 	ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
-					pf->tvar);
+					&pf->sp_die, pf->tvar);
 	if (ret == -ENOENT)
 		pr_err("Failed to find the location of %s at this address.\n"
 		       " Perhaps, it has been optimized out.\n", pf->pvar->var);
@@ -1063,7 +1084,7 @@
 }
 
 /* Find probe points from debuginfo */
-static int debuginfo__find_probes(struct debuginfo *self,
+static int debuginfo__find_probes(struct debuginfo *dbg,
 				  struct probe_finder *pf)
 {
 	struct perf_probe_point *pp = &pf->pev->point;
@@ -1074,7 +1095,7 @@
 
 #if _ELFUTILS_PREREQ(0, 142)
 	/* Get the call frame information from this dwarf */
-	pf->cfi = dwarf_getcfi(self->dbg);
+	pf->cfi = dwarf_getcfi(dbg->dbg);
 #endif
 
 	off = 0;
@@ -1093,7 +1114,7 @@
 			.data = pf,
 		};
 
-		dwarf_getpubnames(self->dbg, pubname_search_cb,
+		dwarf_getpubnames(dbg->dbg, pubname_search_cb,
 				  &pubname_param, 0);
 		if (pubname_param.found) {
 			ret = probe_point_search_cb(&pf->sp_die, &probe_param);
@@ -1103,9 +1124,9 @@
 	}
 
 	/* Loop on CUs (Compilation Unit) */
-	while (!dwarf_nextcu(self->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
+	while (!dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
 		/* Get the DIE(Debugging Information Entry) of this CU */
-		diep = dwarf_offdie(self->dbg, off + cuhl, &pf->cu_die);
+		diep = dwarf_offdie(dbg->dbg, off + cuhl, &pf->cu_die);
 		if (!diep)
 			continue;
 
@@ -1136,12 +1157,80 @@
 	return ret;
 }
 
+struct local_vars_finder {
+	struct probe_finder *pf;
+	struct perf_probe_arg *args;
+	int max_args;
+	int nargs;
+	int ret;
+};
+
+/* Collect available variables in this scope */
+static int copy_variables_cb(Dwarf_Die *die_mem, void *data)
+{
+	struct local_vars_finder *vf = data;
+	struct probe_finder *pf = vf->pf;
+	int tag;
+
+	tag = dwarf_tag(die_mem);
+	if (tag == DW_TAG_formal_parameter ||
+	    tag == DW_TAG_variable) {
+		if (convert_variable_location(die_mem, vf->pf->addr,
+					      vf->pf->fb_ops, &pf->sp_die,
+					      NULL) == 0) {
+			vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem);
+			if (vf->args[vf->nargs].var == NULL) {
+				vf->ret = -ENOMEM;
+				return DIE_FIND_CB_END;
+			}
+			pr_debug(" %s", vf->args[vf->nargs].var);
+			vf->nargs++;
+		}
+	}
+
+	if (dwarf_haspc(die_mem, vf->pf->addr))
+		return DIE_FIND_CB_CONTINUE;
+	else
+		return DIE_FIND_CB_SIBLING;
+}
+
+static int expand_probe_args(Dwarf_Die *sc_die, struct probe_finder *pf,
+			     struct perf_probe_arg *args)
+{
+	Dwarf_Die die_mem;
+	int i;
+	int n = 0;
+	struct local_vars_finder vf = {.pf = pf, .args = args,
+				.max_args = MAX_PROBE_ARGS, .ret = 0};
+
+	for (i = 0; i < pf->pev->nargs; i++) {
+		/* var never be NULL */
+		if (strcmp(pf->pev->args[i].var, "$vars") == 0) {
+			pr_debug("Expanding $vars into:");
+			vf.nargs = n;
+			/* Special local variables */
+			die_find_child(sc_die, copy_variables_cb, (void *)&vf,
+				       &die_mem);
+			pr_debug(" (%d)\n", vf.nargs - n);
+			if (vf.ret < 0)
+				return vf.ret;
+			n = vf.nargs;
+		} else {
+			/* Copy normal argument */
+			args[n] = pf->pev->args[i];
+			n++;
+		}
+	}
+	return n;
+}
+
 /* Add a found probe point into trace event list */
 static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
 {
 	struct trace_event_finder *tf =
 			container_of(pf, struct trace_event_finder, pf);
 	struct probe_trace_event *tev;
+	struct perf_probe_arg *args;
 	int ret, i;
 
 	/* Check number of tevs */
@@ -1161,31 +1250,45 @@
 	pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
 		 tev->point.offset);
 
-	/* Find each argument */
-	tev->nargs = pf->pev->nargs;
-	tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
-	if (tev->args == NULL)
+	/* Expand special probe argument if exist */
+	args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS);
+	if (args == NULL)
 		return -ENOMEM;
-	for (i = 0; i < pf->pev->nargs; i++) {
-		pf->pvar = &pf->pev->args[i];
+
+	ret = expand_probe_args(sc_die, pf, args);
+	if (ret < 0)
+		goto end;
+
+	tev->nargs = ret;
+	tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
+	if (tev->args == NULL) {
+		ret = -ENOMEM;
+		goto end;
+	}
+
+	/* Find each argument */
+	for (i = 0; i < tev->nargs; i++) {
+		pf->pvar = &args[i];
 		pf->tvar = &tev->args[i];
 		/* Variable should be found from scope DIE */
 		ret = find_variable(sc_die, pf);
 		if (ret != 0)
-			return ret;
+			break;
 	}
 
-	return 0;
+end:
+	free(args);
+	return ret;
 }
 
 /* Find probe_trace_events specified by perf_probe_event from debuginfo */
-int debuginfo__find_trace_events(struct debuginfo *self,
+int debuginfo__find_trace_events(struct debuginfo *dbg,
 				 struct perf_probe_event *pev,
 				 struct probe_trace_event **tevs, int max_tevs)
 {
 	struct trace_event_finder tf = {
 			.pf = {.pev = pev, .callback = add_probe_trace_event},
-			.mod = self->mod, .max_tevs = max_tevs};
+			.mod = dbg->mod, .max_tevs = max_tevs};
 	int ret;
 
 	/* Allocate result tevs array */
@@ -1196,7 +1299,7 @@
 	tf.tevs = *tevs;
 	tf.ntevs = 0;
 
-	ret = debuginfo__find_probes(self, &tf.pf);
+	ret = debuginfo__find_probes(dbg, &tf.pf);
 	if (ret < 0) {
 		free(*tevs);
 		*tevs = NULL;
@@ -1222,7 +1325,8 @@
 	if (tag == DW_TAG_formal_parameter ||
 	    tag == DW_TAG_variable) {
 		ret = convert_variable_location(die_mem, af->pf.addr,
-						af->pf.fb_ops, NULL);
+						af->pf.fb_ops, &af->pf.sp_die,
+						NULL);
 		if (ret == 0) {
 			ret = die_get_varname(die_mem, buf, MAX_VAR_LEN);
 			pr_debug2("Add new var: %s\n", buf);
@@ -1286,14 +1390,14 @@
 }
 
 /* Find available variables at given probe point */
-int debuginfo__find_available_vars_at(struct debuginfo *self,
+int debuginfo__find_available_vars_at(struct debuginfo *dbg,
 				      struct perf_probe_event *pev,
 				      struct variable_list **vls,
 				      int max_vls, bool externs)
 {
 	struct available_var_finder af = {
 			.pf = {.pev = pev, .callback = add_available_vars},
-			.mod = self->mod,
+			.mod = dbg->mod,
 			.max_vls = max_vls, .externs = externs};
 	int ret;
 
@@ -1305,7 +1409,7 @@
 	af.vls = *vls;
 	af.nvls = 0;
 
-	ret = debuginfo__find_probes(self, &af.pf);
+	ret = debuginfo__find_probes(dbg, &af.pf);
 	if (ret < 0) {
 		/* Free vlist for error */
 		while (af.nvls--) {
@@ -1323,19 +1427,19 @@
 }
 
 /* Reverse search */
-int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr,
+int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
 				struct perf_probe_point *ppt)
 {
 	Dwarf_Die cudie, spdie, indie;
-	Dwarf_Addr _addr, baseaddr;
-	const char *fname = NULL, *func = NULL, *tmp;
+	Dwarf_Addr _addr = 0, baseaddr = 0;
+	const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
 	int baseline = 0, lineno = 0, ret = 0;
 
 	/* Adjust address with bias */
-	addr += self->bias;
+	addr += dbg->bias;
 
 	/* Find cu die */
-	if (!dwarf_addrdie(self->dbg, (Dwarf_Addr)addr - self->bias, &cudie)) {
+	if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr - dbg->bias, &cudie)) {
 		pr_warning("Failed to find debug information for address %lx\n",
 			   addr);
 		ret = -EINVAL;
@@ -1349,27 +1453,36 @@
 	/* Find a corresponding function (name, baseline and baseaddr) */
 	if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) {
 		/* Get function entry information */
-		tmp = dwarf_diename(&spdie);
-		if (!tmp ||
+		func = basefunc = dwarf_diename(&spdie);
+		if (!func ||
 		    dwarf_entrypc(&spdie, &baseaddr) != 0 ||
-		    dwarf_decl_line(&spdie, &baseline) != 0)
+		    dwarf_decl_line(&spdie, &baseline) != 0) {
+			lineno = 0;
 			goto post;
-		func = tmp;
+		}
 
-		if (addr == (unsigned long)baseaddr)
+		fname = dwarf_decl_file(&spdie);
+		if (addr == (unsigned long)baseaddr) {
 			/* Function entry - Relative line number is 0 */
 			lineno = baseline;
-		else if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr,
-					     &indie)) {
+			goto post;
+		}
+
+		/* Track down the inline functions step by step */
+		while (die_find_top_inlinefunc(&spdie, (Dwarf_Addr)addr,
+						&indie)) {
+			/* There is an inline function */
 			if (dwarf_entrypc(&indie, &_addr) == 0 &&
-			    _addr == addr)
+			    _addr == addr) {
 				/*
 				 * addr is at an inline function entry.
 				 * In this case, lineno should be the call-site
-				 * line number.
+				 * line number. (overwrite lineinfo)
 				 */
 				lineno = die_get_call_lineno(&indie);
-			else {
+				fname = die_get_call_file(&indie);
+				break;
+			} else {
 				/*
 				 * addr is in an inline function body.
 				 * Since lineno points one of the lines
@@ -1377,19 +1490,27 @@
 				 * be the entry line of the inline function.
 				 */
 				tmp = dwarf_diename(&indie);
-				if (tmp &&
-				    dwarf_decl_line(&spdie, &baseline) == 0)
-					func = tmp;
+				if (!tmp ||
+				    dwarf_decl_line(&indie, &baseline) != 0)
+					break;
+				func = tmp;
+				spdie = indie;
 			}
 		}
+		/* Verify the lineno and baseline are in a same file */
+		tmp = dwarf_decl_file(&spdie);
+		if (!tmp || strcmp(tmp, fname) != 0)
+			lineno = 0;
 	}
 
 post:
 	/* Make a relative line number or an offset */
 	if (lineno)
 		ppt->line = lineno - baseline;
-	else if (func)
+	else if (basefunc) {
 		ppt->offset = addr - (unsigned long)baseaddr;
+		func = basefunc;
+	}
 
 	/* Duplicate strings */
 	if (func) {
@@ -1519,7 +1640,7 @@
 	return param.retval;
 }
 
-int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr)
+int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr)
 {
 	struct line_finder lf = {.lr = lr, .found = 0};
 	int ret = 0;
@@ -1536,7 +1657,7 @@
 		struct dwarf_callback_param line_range_param = {
 			.data = (void *)&lf, .retval = 0};
 
-		dwarf_getpubnames(self->dbg, pubname_search_cb,
+		dwarf_getpubnames(dbg->dbg, pubname_search_cb,
 				  &pubname_param, 0);
 		if (pubname_param.found) {
 			line_range_search_cb(&lf.sp_die, &line_range_param);
@@ -1547,12 +1668,12 @@
 
 	/* Loop on CUs (Compilation Unit) */
 	while (!lf.found && ret >= 0) {
-		if (dwarf_nextcu(self->dbg, off, &noff, &cuhl,
+		if (dwarf_nextcu(dbg->dbg, off, &noff, &cuhl,
 				 NULL, NULL, NULL) != 0)
 			break;
 
 		/* Get the DIE(Debugging Information Entry) of this CU */
-		diep = dwarf_offdie(self->dbg, off + cuhl, &lf.cu_die);
+		diep = dwarf_offdie(dbg->dbg, off + cuhl, &lf.cu_die);
 		if (!diep)
 			continue;
 
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 3b7d630..ffc33cd 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -7,6 +7,7 @@
 
 #define MAX_PROBE_BUFFER	1024
 #define MAX_PROBES		 128
+#define MAX_PROBE_ARGS		 128
 
 static inline int is_c_varname(const char *name)
 {
@@ -14,7 +15,7 @@
 	return isalpha(name[0]) || name[0] == '_';
 }
 
-#ifdef DWARF_SUPPORT
+#ifdef HAVE_DWARF_SUPPORT
 
 #include "dwarf-aux.h"
 
@@ -30,25 +31,25 @@
 
 extern struct debuginfo *debuginfo__new(const char *path);
 extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr);
-extern void debuginfo__delete(struct debuginfo *self);
+extern void debuginfo__delete(struct debuginfo *dbg);
 
 /* Find probe_trace_events specified by perf_probe_event from debuginfo */
-extern int debuginfo__find_trace_events(struct debuginfo *self,
+extern int debuginfo__find_trace_events(struct debuginfo *dbg,
 					struct perf_probe_event *pev,
 					struct probe_trace_event **tevs,
 					int max_tevs);
 
 /* Find a perf_probe_point from debuginfo */
-extern int debuginfo__find_probe_point(struct debuginfo *self,
+extern int debuginfo__find_probe_point(struct debuginfo *dbg,
 				       unsigned long addr,
 				       struct perf_probe_point *ppt);
 
 /* Find a line range */
-extern int debuginfo__find_line_range(struct debuginfo *self,
+extern int debuginfo__find_line_range(struct debuginfo *dbg,
 				      struct line_range *lr);
 
 /* Find available variables */
-extern int debuginfo__find_available_vars_at(struct debuginfo *self,
+extern int debuginfo__find_available_vars_at(struct debuginfo *dbg,
 					     struct perf_probe_event *pev,
 					     struct variable_list **vls,
 					     int max_points, bool externs);
@@ -105,6 +106,6 @@
 	int			found;
 };
 
-#endif /* DWARF_SUPPORT */
+#endif /* HAVE_DWARF_SUPPORT */
 
 #endif /*_PROBE_FINDER_H */
diff --git a/tools/perf/util/pstack.h b/tools/perf/util/pstack.h
index 4cedea5..c3cb658 100644
--- a/tools/perf/util/pstack.h
+++ b/tools/perf/util/pstack.h
@@ -5,10 +5,10 @@
 
 struct pstack;
 struct pstack *pstack__new(unsigned short max_nr_entries);
-void pstack__delete(struct pstack *self);
-bool pstack__empty(const struct pstack *self);
-void pstack__remove(struct pstack *self, void *key);
-void pstack__push(struct pstack *self, void *key);
-void *pstack__pop(struct pstack *self);
+void pstack__delete(struct pstack *pstack);
+bool pstack__empty(const struct pstack *pstack);
+void pstack__remove(struct pstack *pstack, void *key);
+void pstack__push(struct pstack *pstack, void *key);
+void *pstack__pop(struct pstack *pstack);
 
 #endif /* _PERF_PSTACK_ */
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index f75ae1b..239036f 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -17,5 +17,5 @@
 util/cgroup.c
 util/rblist.c
 util/strlist.c
-util/sysfs.c
+util/fs.c
 ../../lib/rbtree.c
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 71b5412..4bf8ace 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -33,13 +33,6 @@
 # define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
 #endif
 
-struct throttle_event {
-	struct perf_event_header header;
-	u64			 time;
-	u64			 id;
-	u64			 stream_id;
-};
-
 PyMODINIT_FUNC initperf(void);
 
 #define member_def(type, member, ptype, help) \
@@ -822,6 +815,8 @@
 		PyObject *pyevent = pyrf_event__new(event);
 		struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
 
+		perf_evlist__mmap_consume(evlist, cpu);
+
 		if (pyevent == NULL)
 			return PyErr_NoMemory();
 
@@ -1036,6 +1031,7 @@
 	    pyrf_cpu_map__setup_types() < 0)
 		return;
 
+	/* The page_size is placed in util object. */
 	page_size = sysconf(_SC_PAGE_SIZE);
 
 	Py_INCREF(&pyrf_evlist__type);
diff --git a/tools/perf/util/rblist.c b/tools/perf/util/rblist.c
index a16cdd2..0dfe27d 100644
--- a/tools/perf/util/rblist.c
+++ b/tools/perf/util/rblist.c
@@ -48,10 +48,12 @@
 	rblist->node_delete(rblist, rb_node);
 }
 
-struct rb_node *rblist__find(struct rblist *rblist, const void *entry)
+static struct rb_node *__rblist__findnew(struct rblist *rblist,
+					 const void *entry,
+					 bool create)
 {
 	struct rb_node **p = &rblist->entries.rb_node;
-	struct rb_node *parent = NULL;
+	struct rb_node *parent = NULL, *new_node = NULL;
 
 	while (*p != NULL) {
 		int rc;
@@ -67,7 +69,26 @@
 			return parent;
 	}
 
-	return NULL;
+	if (create) {
+		new_node = rblist->node_new(rblist, entry);
+		if (new_node) {
+			rb_link_node(new_node, parent, p);
+			rb_insert_color(new_node, &rblist->entries);
+			++rblist->nr_entries;
+		}
+	}
+
+	return new_node;
+}
+
+struct rb_node *rblist__find(struct rblist *rblist, const void *entry)
+{
+	return __rblist__findnew(rblist, entry, false);
+}
+
+struct rb_node *rblist__findnew(struct rblist *rblist, const void *entry)
+{
+	return __rblist__findnew(rblist, entry, true);
 }
 
 void rblist__init(struct rblist *rblist)
diff --git a/tools/perf/util/rblist.h b/tools/perf/util/rblist.h
index 6d0cae5..ff9913b 100644
--- a/tools/perf/util/rblist.h
+++ b/tools/perf/util/rblist.h
@@ -32,6 +32,7 @@
 int rblist__add_node(struct rblist *rblist, const void *new_entry);
 void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node);
 struct rb_node *rblist__find(struct rblist *rblist, const void *entry);
+struct rb_node *rblist__findnew(struct rblist *rblist, const void *entry);
 struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx);
 
 static inline bool rblist__empty(const struct rblist *rblist)
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index 18d73aa..c8845b1 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -2,6 +2,8 @@
 #include "evsel.h"
 #include "cpumap.h"
 #include "parse-events.h"
+#include "fs.h"
+#include "util.h"
 
 typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel);
 
@@ -106,3 +108,72 @@
 
 	perf_evlist__set_id_pos(evlist);
 }
+
+static int get_max_rate(unsigned int *rate)
+{
+	char path[PATH_MAX];
+	const char *procfs = procfs__mountpoint();
+
+	if (!procfs)
+		return -1;
+
+	snprintf(path, PATH_MAX,
+		 "%s/sys/kernel/perf_event_max_sample_rate", procfs);
+
+	return filename__read_int(path, (int *) rate);
+}
+
+static int perf_record_opts__config_freq(struct perf_record_opts *opts)
+{
+	bool user_freq = opts->user_freq != UINT_MAX;
+	unsigned int max_rate;
+
+	if (opts->user_interval != ULLONG_MAX)
+		opts->default_interval = opts->user_interval;
+	if (user_freq)
+		opts->freq = opts->user_freq;
+
+	/*
+	 * User specified count overrides default frequency.
+	 */
+	if (opts->default_interval)
+		opts->freq = 0;
+	else if (opts->freq) {
+		opts->default_interval = opts->freq;
+	} else {
+		pr_err("frequency and count are zero, aborting\n");
+		return -1;
+	}
+
+	if (get_max_rate(&max_rate))
+		return 0;
+
+	/*
+	 * User specified frequency is over current maximum.
+	 */
+	if (user_freq && (max_rate < opts->freq)) {
+		pr_err("Maximum frequency rate (%u) reached.\n"
+		   "Please use -F freq option with lower value or consider\n"
+		   "tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n",
+		   max_rate);
+		return -1;
+	}
+
+	/*
+	 * Default frequency is over current maximum.
+	 */
+	if (max_rate < opts->freq) {
+		pr_warning("Lowering default frequency rate to %u.\n"
+			   "Please consider tweaking "
+			   "/proc/sys/kernel/perf_event_max_sample_rate.\n",
+			   max_rate);
+		opts->freq = max_rate;
+	}
+
+	return 0;
+}
+
+int perf_record_opts__config(struct perf_record_opts *opts)
+{
+	return perf_record_opts__config_freq(opts);
+}
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index a85e4ae..d5e5969 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -273,7 +273,7 @@
 	int cpu = sample->cpu;
 	void *data = sample->raw_data;
 	unsigned long long nsecs = sample->time;
-	char *comm = thread->comm;
+	const char *comm = thread__comm_str(thread);
 
 	dSP;
 
@@ -282,7 +282,7 @@
 
 	event = find_cache_event(evsel);
 	if (!event)
-		die("ug! no event found for type %" PRIu64, evsel->attr.config);
+		die("ug! no event found for type %" PRIu64, (u64)evsel->attr.config);
 
 	pid = raw_field_value(event, "common_pid", data);
 
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index cc75a3c..53c20e7 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -56,6 +56,17 @@
 	Py_FatalError("problem in Python trace event handler");
 }
 
+/*
+ * Insert val into into the dictionary and decrement the reference counter.
+ * This is necessary for dictionaries since PyDict_SetItemString() does not 
+ * steal a reference, as opposed to PyTuple_SetItem().
+ */
+static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObject *val)
+{
+	PyDict_SetItemString(dict, key, val);
+	Py_DECREF(val);
+}
+
 static void define_value(enum print_arg_type field_type,
 			 const char *ev_name,
 			 const char *field_name,
@@ -239,7 +250,7 @@
 	int cpu = sample->cpu;
 	void *data = sample->raw_data;
 	unsigned long long nsecs = sample->time;
-	char *comm = thread->comm;
+	const char *comm = thread__comm_str(thread);
 
 	t = PyTuple_New(MAX_FIELDS);
 	if (!t)
@@ -279,11 +290,11 @@
 		PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
 		PyTuple_SetItem(t, n++, PyString_FromString(comm));
 	} else {
-		PyDict_SetItemString(dict, "common_cpu", PyInt_FromLong(cpu));
-		PyDict_SetItemString(dict, "common_s", PyInt_FromLong(s));
-		PyDict_SetItemString(dict, "common_ns", PyInt_FromLong(ns));
-		PyDict_SetItemString(dict, "common_pid", PyInt_FromLong(pid));
-		PyDict_SetItemString(dict, "common_comm", PyString_FromString(comm));
+		pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu));
+		pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s));
+		pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns));
+		pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid));
+		pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm));
 	}
 	for (field = event->format.fields; field; field = field->next) {
 		if (field->flags & FIELD_IS_STRING) {
@@ -313,7 +324,7 @@
 		if (handler)
 			PyTuple_SetItem(t, n++, obj);
 		else
-			PyDict_SetItemString(dict, field->name, obj);
+			pydict_set_item_string_decref(dict, field->name, obj);
 
 	}
 	if (!handler)
@@ -370,21 +381,21 @@
 	if (!handler || !PyCallable_Check(handler))
 		goto exit;
 
-	PyDict_SetItemString(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
-	PyDict_SetItemString(dict, "attr", PyString_FromStringAndSize(
+	pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
+	pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
 			(const char *)&evsel->attr, sizeof(evsel->attr)));
-	PyDict_SetItemString(dict, "sample", PyString_FromStringAndSize(
+	pydict_set_item_string_decref(dict, "sample", PyString_FromStringAndSize(
 			(const char *)sample, sizeof(*sample)));
-	PyDict_SetItemString(dict, "raw_buf", PyString_FromStringAndSize(
+	pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
 			(const char *)sample->raw_data, sample->raw_size));
-	PyDict_SetItemString(dict, "comm",
-			PyString_FromString(thread->comm));
+	pydict_set_item_string_decref(dict, "comm",
+			PyString_FromString(thread__comm_str(thread)));
 	if (al->map) {
-		PyDict_SetItemString(dict, "dso",
+		pydict_set_item_string_decref(dict, "dso",
 			PyString_FromString(al->map->dso->name));
 	}
 	if (al->sym) {
-		PyDict_SetItemString(dict, "symbol",
+		pydict_set_item_string_decref(dict, "symbol",
 			PyString_FromString(al->sym->name));
 	}
 
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 70ffa41..f36d24a 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -16,73 +16,34 @@
 #include "perf_regs.h"
 #include "vdso.h"
 
-static int perf_session__open(struct perf_session *self, bool force)
+static int perf_session__open(struct perf_session *session)
 {
-	struct stat input_stat;
+	struct perf_data_file *file = session->file;
 
-	if (!strcmp(self->filename, "-")) {
-		self->fd_pipe = true;
-		self->fd = STDIN_FILENO;
-
-		if (perf_session__read_header(self) < 0)
-			pr_err("incompatible file format (rerun with -v to learn more)");
-
-		return 0;
-	}
-
-	self->fd = open(self->filename, O_RDONLY);
-	if (self->fd < 0) {
-		int err = errno;
-
-		pr_err("failed to open %s: %s", self->filename, strerror(err));
-		if (err == ENOENT && !strcmp(self->filename, "perf.data"))
-			pr_err("  (try 'perf record' first)");
-		pr_err("\n");
-		return -errno;
-	}
-
-	if (fstat(self->fd, &input_stat) < 0)
-		goto out_close;
-
-	if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
-		pr_err("file %s not owned by current user or root\n",
-		       self->filename);
-		goto out_close;
-	}
-
-	if (!input_stat.st_size) {
-		pr_info("zero-sized file (%s), nothing to do!\n",
-			self->filename);
-		goto out_close;
-	}
-
-	if (perf_session__read_header(self) < 0) {
+	if (perf_session__read_header(session) < 0) {
 		pr_err("incompatible file format (rerun with -v to learn more)");
-		goto out_close;
+		return -1;
 	}
 
-	if (!perf_evlist__valid_sample_type(self->evlist)) {
+	if (perf_data_file__is_pipe(file))
+		return 0;
+
+	if (!perf_evlist__valid_sample_type(session->evlist)) {
 		pr_err("non matching sample_type");
-		goto out_close;
+		return -1;
 	}
 
-	if (!perf_evlist__valid_sample_id_all(self->evlist)) {
+	if (!perf_evlist__valid_sample_id_all(session->evlist)) {
 		pr_err("non matching sample_id_all");
-		goto out_close;
+		return -1;
 	}
 
-	if (!perf_evlist__valid_read_format(self->evlist)) {
+	if (!perf_evlist__valid_read_format(session->evlist)) {
 		pr_err("non matching read_format");
-		goto out_close;
+		return -1;
 	}
 
-	self->size = input_stat.st_size;
 	return 0;
-
-out_close:
-	close(self->fd);
-	self->fd = -1;
-	return -1;
 }
 
 void perf_session__set_id_hdr_size(struct perf_session *session)
@@ -92,71 +53,70 @@
 	machines__set_id_hdr_size(&session->machines, id_hdr_size);
 }
 
-int perf_session__create_kernel_maps(struct perf_session *self)
+int perf_session__create_kernel_maps(struct perf_session *session)
 {
-	int ret = machine__create_kernel_maps(&self->machines.host);
+	int ret = machine__create_kernel_maps(&session->machines.host);
 
 	if (ret >= 0)
-		ret = machines__create_guest_kernel_maps(&self->machines);
+		ret = machines__create_guest_kernel_maps(&session->machines);
 	return ret;
 }
 
-static void perf_session__destroy_kernel_maps(struct perf_session *self)
+static void perf_session__destroy_kernel_maps(struct perf_session *session)
 {
-	machines__destroy_kernel_maps(&self->machines);
+	machines__destroy_kernel_maps(&session->machines);
 }
 
-struct perf_session *perf_session__new(const char *filename, int mode,
-				       bool force, bool repipe,
-				       struct perf_tool *tool)
+struct perf_session *perf_session__new(struct perf_data_file *file,
+				       bool repipe, struct perf_tool *tool)
 {
-	struct perf_session *self;
-	struct stat st;
-	size_t len;
+	struct perf_session *session = zalloc(sizeof(*session));
 
-	if (!filename || !strlen(filename)) {
-		if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
-			filename = "-";
-		else
-			filename = "perf.data";
-	}
-
-	len = strlen(filename);
-	self = zalloc(sizeof(*self) + len);
-
-	if (self == NULL)
+	if (!session)
 		goto out;
 
-	memcpy(self->filename, filename, len);
-	self->repipe = repipe;
-	INIT_LIST_HEAD(&self->ordered_samples.samples);
-	INIT_LIST_HEAD(&self->ordered_samples.sample_cache);
-	INIT_LIST_HEAD(&self->ordered_samples.to_free);
-	machines__init(&self->machines);
+	session->repipe = repipe;
+	INIT_LIST_HEAD(&session->ordered_samples.samples);
+	INIT_LIST_HEAD(&session->ordered_samples.sample_cache);
+	INIT_LIST_HEAD(&session->ordered_samples.to_free);
+	machines__init(&session->machines);
 
-	if (mode == O_RDONLY) {
-		if (perf_session__open(self, force) < 0)
+	if (file) {
+		if (perf_data_file__open(file))
 			goto out_delete;
-		perf_session__set_id_hdr_size(self);
-	} else if (mode == O_WRONLY) {
+
+		session->file = file;
+
+		if (perf_data_file__is_read(file)) {
+			if (perf_session__open(session) < 0)
+				goto out_close;
+
+			perf_session__set_id_hdr_size(session);
+		}
+	}
+
+	if (!file || perf_data_file__is_write(file)) {
 		/*
 		 * In O_RDONLY mode this will be performed when reading the
 		 * kernel MMAP event, in perf_event__process_mmap().
 		 */
-		if (perf_session__create_kernel_maps(self) < 0)
+		if (perf_session__create_kernel_maps(session) < 0)
 			goto out_delete;
 	}
 
 	if (tool && tool->ordering_requires_timestamps &&
-	    tool->ordered_samples && !perf_evlist__sample_id_all(self->evlist)) {
+	    tool->ordered_samples && !perf_evlist__sample_id_all(session->evlist)) {
 		dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
 		tool->ordered_samples = false;
 	}
 
-out:
-	return self;
-out_delete:
-	perf_session__delete(self);
+	return session;
+
+ out_close:
+	perf_data_file__close(file);
+ out_delete:
+	perf_session__delete(session);
+ out:
 	return NULL;
 }
 
@@ -186,15 +146,16 @@
 	free(env->pmu_mappings);
 }
 
-void perf_session__delete(struct perf_session *self)
+void perf_session__delete(struct perf_session *session)
 {
-	perf_session__destroy_kernel_maps(self);
-	perf_session__delete_dead_threads(self);
-	perf_session__delete_threads(self);
-	perf_session_env__delete(&self->header.env);
-	machines__exit(&self->machines);
-	close(self->fd);
-	free(self);
+	perf_session__destroy_kernel_maps(session);
+	perf_session__delete_dead_threads(session);
+	perf_session__delete_threads(session);
+	perf_session_env__delete(&session->header.env);
+	machines__exit(&session->machines);
+	if (session->file)
+		perf_data_file__close(session->file);
+	free(session);
 	vdso__exit();
 }
 
@@ -256,6 +217,8 @@
 		tool->sample = process_event_sample_stub;
 	if (tool->mmap == NULL)
 		tool->mmap = process_event_stub;
+	if (tool->mmap2 == NULL)
+		tool->mmap2 = process_event_stub;
 	if (tool->comm == NULL)
 		tool->comm = process_event_stub;
 	if (tool->fork == NULL)
@@ -395,6 +358,17 @@
 		swap_sample_id_all(event, &event->read + 1);
 }
 
+static void perf_event__throttle_swap(union perf_event *event,
+				      bool sample_id_all)
+{
+	event->throttle.time	  = bswap_64(event->throttle.time);
+	event->throttle.id	  = bswap_64(event->throttle.id);
+	event->throttle.stream_id = bswap_64(event->throttle.stream_id);
+
+	if (sample_id_all)
+		swap_sample_id_all(event, &event->throttle + 1);
+}
+
 static u8 revbyte(u8 b)
 {
 	int rev = (b >> 4) | ((b & 0xf) << 4);
@@ -440,6 +414,9 @@
 	attr->bp_type		= bswap_32(attr->bp_type);
 	attr->bp_addr		= bswap_64(attr->bp_addr);
 	attr->bp_len		= bswap_64(attr->bp_len);
+	attr->branch_sample_type = bswap_64(attr->branch_sample_type);
+	attr->sample_regs_user	 = bswap_64(attr->sample_regs_user);
+	attr->sample_stack_user  = bswap_32(attr->sample_stack_user);
 
 	swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64));
 }
@@ -480,6 +457,8 @@
 	[PERF_RECORD_EXIT]		  = perf_event__task_swap,
 	[PERF_RECORD_LOST]		  = perf_event__all64_swap,
 	[PERF_RECORD_READ]		  = perf_event__read_swap,
+	[PERF_RECORD_THROTTLE]		  = perf_event__throttle_swap,
+	[PERF_RECORD_UNTHROTTLE]	  = perf_event__throttle_swap,
 	[PERF_RECORD_SAMPLE]		  = perf_event__all64_swap,
 	[PERF_RECORD_HEADER_ATTR]	  = perf_event__hdr_attr_swap,
 	[PERF_RECORD_HEADER_EVENT_TYPE]	  = perf_event__event_type_swap,
@@ -523,13 +502,16 @@
 	struct perf_sample sample;
 	u64 limit = os->next_flush;
 	u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
-	unsigned idx = 0, progress_next = os->nr_samples / 16;
 	bool show_progress = limit == ULLONG_MAX;
+	struct ui_progress prog;
 	int ret;
 
 	if (!tool->ordered_samples || !limit)
 		return 0;
 
+	if (show_progress)
+		ui_progress__init(&prog, os->nr_samples, "Processing time ordered events...");
+
 	list_for_each_entry_safe(iter, tmp, head, list) {
 		if (session_done())
 			return 0;
@@ -550,11 +532,9 @@
 		os->last_flush = iter->timestamp;
 		list_del(&iter->list);
 		list_add(&iter->list, &os->sample_cache);
-		if (show_progress && (++idx >= progress_next)) {
-			progress_next += os->nr_samples / 16;
-			ui_progress__update(idx, os->nr_samples,
-					    "Processing time ordered events...");
-		}
+
+		if (show_progress)
+			ui_progress__update(&prog, 1);
 	}
 
 	if (list_empty(head)) {
@@ -858,6 +838,9 @@
 	if (sample_type & PERF_SAMPLE_DATA_SRC)
 		printf(" . data_src: 0x%"PRIx64"\n", sample->data_src);
 
+	if (sample_type & PERF_SAMPLE_TRANSACTION)
+		printf("... transaction: %" PRIx64 "\n", sample->transaction);
+
 	if (sample_type & PERF_SAMPLE_READ)
 		sample_read__printf(sample, evsel->attr.read_format);
 }
@@ -1029,6 +1012,7 @@
 static int perf_session__process_user_event(struct perf_session *session, union perf_event *event,
 					    struct perf_tool *tool, u64 file_offset)
 {
+	int fd = perf_data_file__fd(session->file);
 	int err;
 
 	dump_event(session, event, file_offset, NULL);
@@ -1042,7 +1026,7 @@
 		return err;
 	case PERF_RECORD_HEADER_TRACING_DATA:
 		/* setup for reading amidst mmap */
-		lseek(session->fd, file_offset, SEEK_SET);
+		lseek(fd, file_offset, SEEK_SET);
 		return tool->tracing_data(tool, event, session);
 	case PERF_RECORD_HEADER_BUILD_ID:
 		return tool->build_id(tool, event, session);
@@ -1099,11 +1083,11 @@
 					  file_offset);
 }
 
-void perf_event_header__bswap(struct perf_event_header *self)
+void perf_event_header__bswap(struct perf_event_header *hdr)
 {
-	self->type = bswap_32(self->type);
-	self->misc = bswap_16(self->misc);
-	self->size = bswap_16(self->size);
+	hdr->type = bswap_32(hdr->type);
+	hdr->misc = bswap_16(hdr->misc);
+	hdr->size = bswap_16(hdr->size);
 }
 
 struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
@@ -1111,11 +1095,11 @@
 	return machine__findnew_thread(&session->machines.host, 0, pid);
 }
 
-static struct thread *perf_session__register_idle_thread(struct perf_session *self)
+static struct thread *perf_session__register_idle_thread(struct perf_session *session)
 {
-	struct thread *thread = perf_session__findnew(self, 0);
+	struct thread *thread = perf_session__findnew(session, 0);
 
-	if (thread == NULL || thread__set_comm(thread, "swapper")) {
+	if (thread == NULL || thread__set_comm(thread, "swapper", 0)) {
 		pr_err("problem inserting idle task.\n");
 		thread = NULL;
 	}
@@ -1165,9 +1149,10 @@
 
 volatile int session_done;
 
-static int __perf_session__process_pipe_events(struct perf_session *self,
+static int __perf_session__process_pipe_events(struct perf_session *session,
 					       struct perf_tool *tool)
 {
+	int fd = perf_data_file__fd(session->file);
 	union perf_event *event;
 	uint32_t size, cur_size = 0;
 	void *buf = NULL;
@@ -1186,7 +1171,7 @@
 		return -errno;
 more:
 	event = buf;
-	err = readn(self->fd, event, sizeof(struct perf_event_header));
+	err = readn(fd, event, sizeof(struct perf_event_header));
 	if (err <= 0) {
 		if (err == 0)
 			goto done;
@@ -1195,7 +1180,7 @@
 		goto out_err;
 	}
 
-	if (self->header.needs_swap)
+	if (session->header.needs_swap)
 		perf_event_header__bswap(&event->header);
 
 	size = event->header.size;
@@ -1218,7 +1203,7 @@
 	p += sizeof(struct perf_event_header);
 
 	if (size - sizeof(struct perf_event_header)) {
-		err = readn(self->fd, p, size - sizeof(struct perf_event_header));
+		err = readn(fd, p, size - sizeof(struct perf_event_header));
 		if (err <= 0) {
 			if (err == 0) {
 				pr_err("unexpected end of event stream\n");
@@ -1230,7 +1215,7 @@
 		}
 	}
 
-	if ((skip = perf_session__process_event(self, event, tool, head)) < 0) {
+	if ((skip = perf_session__process_event(session, event, tool, head)) < 0) {
 		pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
 		       head, event->header.size, event->header.type);
 		err = -EINVAL;
@@ -1245,11 +1230,13 @@
 	if (!session_done())
 		goto more;
 done:
-	err = 0;
+	/* do the final flush for ordered samples */
+	session->ordered_samples.next_flush = ULLONG_MAX;
+	err = flush_sample_queue(session, tool);
 out_err:
 	free(buf);
-	perf_session__warn_about_errors(self, tool);
-	perf_session_free_sample_buffers(self);
+	perf_session__warn_about_errors(session, tool);
+	perf_session_free_sample_buffers(session);
 	return err;
 }
 
@@ -1297,12 +1284,14 @@
 				   u64 data_offset, u64 data_size,
 				   u64 file_size, struct perf_tool *tool)
 {
-	u64 head, page_offset, file_offset, file_pos, progress_next;
+	int fd = perf_data_file__fd(session->file);
+	u64 head, page_offset, file_offset, file_pos;
 	int err, mmap_prot, mmap_flags, map_idx = 0;
 	size_t	mmap_size;
 	char *buf, *mmaps[NUM_MMAPS];
 	union perf_event *event;
 	uint32_t size;
+	struct ui_progress prog;
 
 	perf_tool__fill_defaults(tool);
 
@@ -1310,10 +1299,10 @@
 	file_offset = page_offset;
 	head = data_offset - page_offset;
 
-	if (data_offset + data_size < file_size)
+	if (data_size && (data_offset + data_size < file_size))
 		file_size = data_offset + data_size;
 
-	progress_next = file_size / 16;
+	ui_progress__init(&prog, file_size, "Processing events...");
 
 	mmap_size = MMAP_SIZE;
 	if (mmap_size > file_size)
@@ -1329,7 +1318,7 @@
 		mmap_flags = MAP_PRIVATE;
 	}
 remap:
-	buf = mmap(NULL, mmap_size, mmap_prot, mmap_flags, session->fd,
+	buf = mmap(NULL, mmap_size, mmap_prot, mmap_flags, fd,
 		   file_offset);
 	if (buf == MAP_FAILED) {
 		pr_err("failed to mmap file\n");
@@ -1368,19 +1357,15 @@
 	head += size;
 	file_pos += size;
 
-	if (file_pos >= progress_next) {
-		progress_next += file_size / 16;
-		ui_progress__update(file_pos, file_size,
-				    "Processing events...");
-	}
+	ui_progress__update(&prog, size);
 
-	err = 0;
 	if (session_done())
-		goto out_err;
+		goto out;
 
 	if (file_pos < file_size)
 		goto more;
 
+out:
 	/* do the final flush for ordered samples */
 	session->ordered_samples.next_flush = ULLONG_MAX;
 	err = flush_sample_queue(session, tool);
@@ -1391,21 +1376,22 @@
 	return err;
 }
 
-int perf_session__process_events(struct perf_session *self,
+int perf_session__process_events(struct perf_session *session,
 				 struct perf_tool *tool)
 {
+	u64 size = perf_data_file__size(session->file);
 	int err;
 
-	if (perf_session__register_idle_thread(self) == NULL)
+	if (perf_session__register_idle_thread(session) == NULL)
 		return -ENOMEM;
 
-	if (!self->fd_pipe)
-		err = __perf_session__process_events(self,
-						     self->header.data_offset,
-						     self->header.data_size,
-						     self->size, tool);
+	if (!perf_data_file__is_pipe(session->file))
+		err = __perf_session__process_events(session,
+						     session->header.data_offset,
+						     session->header.data_size,
+						     size, tool);
 	else
-		err = __perf_session__process_pipe_events(self, tool);
+		err = __perf_session__process_pipe_events(session, tool);
 
 	return err;
 }
@@ -1454,15 +1440,15 @@
 	return 0;
 }
 
-size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp)
+size_t perf_session__fprintf_dsos(struct perf_session *session, FILE *fp)
 {
-	return machines__fprintf_dsos(&self->machines, fp);
+	return machines__fprintf_dsos(&session->machines, fp);
 }
 
-size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp,
+size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp,
 					  bool (skip)(struct dso *dso, int parm), int parm)
 {
-	return machines__fprintf_dsos_buildid(&self->machines, fp, skip, parm);
+	return machines__fprintf_dsos_buildid(&session->machines, fp, skip, parm);
 }
 
 size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
@@ -1523,7 +1509,8 @@
 	if (symbol_conf.use_callchain && sample->callchain) {
 
 		if (machine__resolve_callchain(machine, evsel, al.thread,
-					       sample, NULL, NULL) != 0) {
+					       sample, NULL, NULL,
+					       PERF_MAX_STACK_DEPTH) != 0) {
 			if (verbose)
 				error("Failed to resolve callchain. Skipping\n");
 			return;
@@ -1627,13 +1614,14 @@
 void perf_session__fprintf_info(struct perf_session *session, FILE *fp,
 				bool full)
 {
+	int fd = perf_data_file__fd(session->file);
 	struct stat st;
 	int ret;
 
 	if (session == NULL || fp == NULL)
 		return;
 
-	ret = fstat(session->fd, &st);
+	ret = fstat(fd, &st);
 	if (ret == -1)
 		return;
 
@@ -1662,9 +1650,9 @@
 			continue;
 
 		err = -EEXIST;
-		if (evsel->handler.func != NULL)
+		if (evsel->handler != NULL)
 			goto out;
-		evsel->handler.func = assocs[i].handler;
+		evsel->handler = assocs[i].handler;
 	}
 
 	err = 0;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 04bf737..50f6409 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -7,6 +7,7 @@
 #include "machine.h"
 #include "symbol.h"
 #include "thread.h"
+#include "data.h"
 #include <linux/rbtree.h>
 #include <linux/perf_event.h>
 
@@ -29,16 +30,13 @@
 
 struct perf_session {
 	struct perf_header	header;
-	unsigned long		size;
 	struct machines		machines;
 	struct perf_evlist	*evlist;
 	struct pevent		*pevent;
 	struct events_stats	stats;
-	int			fd;
-	bool			fd_pipe;
 	bool			repipe;
 	struct ordered_samples	ordered_samples;
-	char			filename[1];
+	struct perf_data_file	*file;
 };
 
 #define PRINT_IP_OPT_IP		(1<<0)
@@ -49,17 +47,16 @@
 
 struct perf_tool;
 
-struct perf_session *perf_session__new(const char *filename, int mode,
-				       bool force, bool repipe,
-				       struct perf_tool *tool);
+struct perf_session *perf_session__new(struct perf_data_file *file,
+				       bool repipe, struct perf_tool *tool);
 void perf_session__delete(struct perf_session *session);
 
-void perf_event_header__bswap(struct perf_event_header *self);
+void perf_event_header__bswap(struct perf_event_header *hdr);
 
-int __perf_session__process_events(struct perf_session *self,
+int __perf_session__process_events(struct perf_session *session,
 				   u64 data_offset, u64 data_size, u64 size,
 				   struct perf_tool *tool);
-int perf_session__process_events(struct perf_session *self,
+int perf_session__process_events(struct perf_session *session,
 				 struct perf_tool *tool);
 
 int perf_session_queue_event(struct perf_session *s, union perf_event *event,
@@ -67,37 +64,38 @@
 
 void perf_tool__fill_defaults(struct perf_tool *tool);
 
-int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel *evsel,
+int perf_session__resolve_callchain(struct perf_session *session,
+				    struct perf_evsel *evsel,
 				    struct thread *thread,
 				    struct ip_callchain *chain,
 				    struct symbol **parent);
 
-bool perf_session__has_traces(struct perf_session *self, const char *msg);
+bool perf_session__has_traces(struct perf_session *session, const char *msg);
 
 void mem_bswap_64(void *src, int byte_size);
 void mem_bswap_32(void *src, int byte_size);
 void perf_event__attr_swap(struct perf_event_attr *attr);
 
-int perf_session__create_kernel_maps(struct perf_session *self);
+int perf_session__create_kernel_maps(struct perf_session *session);
 
 void perf_session__set_id_hdr_size(struct perf_session *session);
 
 static inline
-struct machine *perf_session__find_machine(struct perf_session *self, pid_t pid)
+struct machine *perf_session__find_machine(struct perf_session *session, pid_t pid)
 {
-	return machines__find(&self->machines, pid);
+	return machines__find(&session->machines, pid);
 }
 
 static inline
-struct machine *perf_session__findnew_machine(struct perf_session *self, pid_t pid)
+struct machine *perf_session__findnew_machine(struct perf_session *session, pid_t pid)
 {
-	return machines__findnew(&self->machines, pid);
+	return machines__findnew(&session->machines, pid);
 }
 
-struct thread *perf_session__findnew(struct perf_session *self, pid_t pid);
-size_t perf_session__fprintf(struct perf_session *self, FILE *fp);
+struct thread *perf_session__findnew(struct perf_session *session, pid_t pid);
+size_t perf_session__fprintf(struct perf_session *session, FILE *fp);
 
-size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp);
+size_t perf_session__fprintf_dsos(struct perf_session *session, FILE *fp);
 
 size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp,
 					  bool (fn)(struct dso *dso, int parm), int parm);
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 5f118a0..3c1b75c 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1,5 +1,6 @@
 #include "sort.h"
 #include "hist.h"
+#include "comm.h"
 #include "symbol.h"
 
 regex_t		parent_regex;
@@ -42,7 +43,7 @@
 	return n;
 }
 
-static int64_t cmp_null(void *l, void *r)
+static int64_t cmp_null(const void *l, const void *r)
 {
 	if (!l && !r)
 		return 0;
@@ -60,11 +61,12 @@
 	return right->thread->tid - left->thread->tid;
 }
 
-static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf,
+static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,
 				       size_t size, unsigned int width)
 {
+	const char *comm = thread__comm_str(he->thread);
 	return repsep_snprintf(bf, size, "%*s:%5d", width - 6,
-			      self->thread->comm ?: "", self->thread->tid);
+			       comm ?: "", he->thread->tid);
 }
 
 struct sort_entry sort_thread = {
@@ -79,25 +81,21 @@
 static int64_t
 sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
 {
-	return right->thread->tid - left->thread->tid;
+	/* Compare the addr that should be unique among comm */
+	return comm__str(right->comm) - comm__str(left->comm);
 }
 
 static int64_t
 sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
 {
-	char *comm_l = left->thread->comm;
-	char *comm_r = right->thread->comm;
-
-	if (!comm_l || !comm_r)
-		return cmp_null(comm_l, comm_r);
-
-	return strcmp(comm_l, comm_r);
+	/* Compare the addr that should be unique among comm */
+	return comm__str(right->comm) - comm__str(left->comm);
 }
 
-static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf,
+static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf,
 				     size_t size, unsigned int width)
 {
-	return repsep_snprintf(bf, size, "%*s", width, self->thread->comm);
+	return repsep_snprintf(bf, size, "%*s", width, comm__str(he->comm));
 }
 
 struct sort_entry sort_comm = {
@@ -148,10 +146,10 @@
 	return repsep_snprintf(bf, size, "%-*s", width, "[unknown]");
 }
 
-static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf,
+static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf,
 				    size_t size, unsigned int width)
 {
-	return _hist_entry__dso_snprintf(self->ms.map, bf, size, width);
+	return _hist_entry__dso_snprintf(he->ms.map, bf, size, width);
 }
 
 struct sort_entry sort_dso = {
@@ -182,9 +180,19 @@
 static int64_t
 sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
 {
+	int64_t ret;
+
 	if (!left->ms.sym && !right->ms.sym)
 		return right->level - left->level;
 
+	/*
+	 * comparing symbol address alone is not enough since it's a
+	 * relative address within a dso.
+	 */
+	ret = sort__dso_cmp(left, right);
+	if (ret != 0)
+		return ret;
+
 	return _sort__sym_cmp(left->ms.sym, right->ms.sym);
 }
 
@@ -224,11 +232,11 @@
 	return ret;
 }
 
-static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
+static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
 				    size_t size, unsigned int width)
 {
-	return _hist_entry__sym_snprintf(self->ms.map, self->ms.sym, self->ip,
-					 self->level, bf, size, width);
+	return _hist_entry__sym_snprintf(he->ms.map, he->ms.sym, he->ip,
+					 he->level, bf, size, width);
 }
 
 struct sort_entry sort_sym = {
@@ -243,50 +251,32 @@
 static int64_t
 sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
 {
-	return (int64_t)(right->ip - left->ip);
+	if (!left->srcline) {
+		if (!left->ms.map)
+			left->srcline = SRCLINE_UNKNOWN;
+		else {
+			struct map *map = left->ms.map;
+			left->srcline = get_srcline(map->dso,
+					    map__rip_2objdump(map, left->ip));
+		}
+	}
+	if (!right->srcline) {
+		if (!right->ms.map)
+			right->srcline = SRCLINE_UNKNOWN;
+		else {
+			struct map *map = right->ms.map;
+			right->srcline = get_srcline(map->dso,
+					    map__rip_2objdump(map, right->ip));
+		}
+	}
+	return strcmp(left->srcline, right->srcline);
 }
 
-static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf,
+static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
 					size_t size,
 					unsigned int width __maybe_unused)
 {
-	FILE *fp = NULL;
-	char cmd[PATH_MAX + 2], *path = self->srcline, *nl;
-	size_t line_len;
-
-	if (path != NULL)
-		goto out_path;
-
-	if (!self->ms.map)
-		goto out_ip;
-
-	if (!strncmp(self->ms.map->dso->long_name, "/tmp/perf-", 10))
-		goto out_ip;
-
-	snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64,
-		 self->ms.map->dso->long_name, self->ip);
-	fp = popen(cmd, "r");
-	if (!fp)
-		goto out_ip;
-
-	if (getline(&path, &line_len, fp) < 0 || !line_len)
-		goto out_ip;
-	self->srcline = strdup(path);
-	if (self->srcline == NULL)
-		goto out_ip;
-
-	nl = strchr(self->srcline, '\n');
-	if (nl != NULL)
-		*nl = '\0';
-	path = self->srcline;
-out_path:
-	if (fp)
-		pclose(fp);
-	return repsep_snprintf(bf, size, "%s", path);
-out_ip:
-	if (fp)
-		pclose(fp);
-	return repsep_snprintf(bf, size, "%-#*llx", BITS_PER_LONG / 4, self->ip);
+	return repsep_snprintf(bf, size, "%s", he->srcline);
 }
 
 struct sort_entry sort_srcline = {
@@ -310,11 +300,11 @@
 	return strcmp(sym_l->name, sym_r->name);
 }
 
-static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf,
+static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf,
 				       size_t size, unsigned int width)
 {
 	return repsep_snprintf(bf, size, "%-*s", width,
-			      self->parent ? self->parent->name : "[other]");
+			      he->parent ? he->parent->name : "[other]");
 }
 
 struct sort_entry sort_parent = {
@@ -332,10 +322,10 @@
 	return right->cpu - left->cpu;
 }
 
-static int hist_entry__cpu_snprintf(struct hist_entry *self, char *bf,
-				       size_t size, unsigned int width)
+static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf,
+				    size_t size, unsigned int width)
 {
-	return repsep_snprintf(bf, size, "%*d", width, self->cpu);
+	return repsep_snprintf(bf, size, "%*d", width, he->cpu);
 }
 
 struct sort_entry sort_cpu = {
@@ -354,10 +344,10 @@
 			      right->branch_info->from.map);
 }
 
-static int hist_entry__dso_from_snprintf(struct hist_entry *self, char *bf,
+static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf,
 				    size_t size, unsigned int width)
 {
-	return _hist_entry__dso_snprintf(self->branch_info->from.map,
+	return _hist_entry__dso_snprintf(he->branch_info->from.map,
 					 bf, size, width);
 }
 
@@ -368,10 +358,10 @@
 			      right->branch_info->to.map);
 }
 
-static int hist_entry__dso_to_snprintf(struct hist_entry *self, char *bf,
+static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf,
 				       size_t size, unsigned int width)
 {
-	return _hist_entry__dso_snprintf(self->branch_info->to.map,
+	return _hist_entry__dso_snprintf(he->branch_info->to.map,
 					 bf, size, width);
 }
 
@@ -399,21 +389,21 @@
 	return _sort__sym_cmp(to_l->sym, to_r->sym);
 }
 
-static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf,
+static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,
 					 size_t size, unsigned int width)
 {
-	struct addr_map_symbol *from = &self->branch_info->from;
+	struct addr_map_symbol *from = &he->branch_info->from;
 	return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
-					 self->level, bf, size, width);
+					 he->level, bf, size, width);
 
 }
 
-static int hist_entry__sym_to_snprintf(struct hist_entry *self, char *bf,
+static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf,
 				       size_t size, unsigned int width)
 {
-	struct addr_map_symbol *to = &self->branch_info->to;
+	struct addr_map_symbol *to = &he->branch_info->to;
 	return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
-					 self->level, bf, size, width);
+					 he->level, bf, size, width);
 
 }
 
@@ -456,13 +446,13 @@
 	return mp || p;
 }
 
-static int hist_entry__mispredict_snprintf(struct hist_entry *self, char *bf,
+static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,
 				    size_t size, unsigned int width){
 	static const char *out = "N/A";
 
-	if (self->branch_info->flags.predicted)
+	if (he->branch_info->flags.predicted)
 		out = "N";
-	else if (self->branch_info->flags.mispred)
+	else if (he->branch_info->flags.mispred)
 		out = "Y";
 
 	return repsep_snprintf(bf, size, "%-*s", width, out);
@@ -482,19 +472,19 @@
 	return (int64_t)(r - l);
 }
 
-static int hist_entry__daddr_snprintf(struct hist_entry *self, char *bf,
+static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf,
 				    size_t size, unsigned int width)
 {
 	uint64_t addr = 0;
 	struct map *map = NULL;
 	struct symbol *sym = NULL;
 
-	if (self->mem_info) {
-		addr = self->mem_info->daddr.addr;
-		map = self->mem_info->daddr.map;
-		sym = self->mem_info->daddr.sym;
+	if (he->mem_info) {
+		addr = he->mem_info->daddr.addr;
+		map = he->mem_info->daddr.map;
+		sym = he->mem_info->daddr.sym;
 	}
-	return _hist_entry__sym_snprintf(map, sym, addr, self->level, bf, size,
+	return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
 					 width);
 }
 
@@ -512,13 +502,13 @@
 	return _sort__dso_cmp(map_l, map_r);
 }
 
-static int hist_entry__dso_daddr_snprintf(struct hist_entry *self, char *bf,
+static int hist_entry__dso_daddr_snprintf(struct hist_entry *he, char *bf,
 				    size_t size, unsigned int width)
 {
 	struct map *map = NULL;
 
-	if (self->mem_info)
-		map = self->mem_info->daddr.map;
+	if (he->mem_info)
+		map = he->mem_info->daddr.map;
 
 	return _hist_entry__dso_snprintf(map, bf, size, width);
 }
@@ -542,14 +532,14 @@
 	return (int64_t)(data_src_r.mem_lock - data_src_l.mem_lock);
 }
 
-static int hist_entry__locked_snprintf(struct hist_entry *self, char *bf,
+static int hist_entry__locked_snprintf(struct hist_entry *he, char *bf,
 				    size_t size, unsigned int width)
 {
 	const char *out;
 	u64 mask = PERF_MEM_LOCK_NA;
 
-	if (self->mem_info)
-		mask = self->mem_info->data_src.mem_lock;
+	if (he->mem_info)
+		mask = he->mem_info->data_src.mem_lock;
 
 	if (mask & PERF_MEM_LOCK_NA)
 		out = "N/A";
@@ -591,7 +581,7 @@
 };
 #define NUM_TLB_ACCESS (sizeof(tlb_access)/sizeof(const char *))
 
-static int hist_entry__tlb_snprintf(struct hist_entry *self, char *bf,
+static int hist_entry__tlb_snprintf(struct hist_entry *he, char *bf,
 				    size_t size, unsigned int width)
 {
 	char out[64];
@@ -602,8 +592,8 @@
 
 	out[0] = '\0';
 
-	if (self->mem_info)
-		m = self->mem_info->data_src.mem_dtlb;
+	if (he->mem_info)
+		m = he->mem_info->data_src.mem_dtlb;
 
 	hit = m & PERF_MEM_TLB_HIT;
 	miss = m & PERF_MEM_TLB_MISS;
@@ -668,7 +658,7 @@
 };
 #define NUM_MEM_LVL (sizeof(mem_lvl)/sizeof(const char *))
 
-static int hist_entry__lvl_snprintf(struct hist_entry *self, char *bf,
+static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf,
 				    size_t size, unsigned int width)
 {
 	char out[64];
@@ -677,8 +667,8 @@
 	u64 m =  PERF_MEM_LVL_NA;
 	u64 hit, miss;
 
-	if (self->mem_info)
-		m  = self->mem_info->data_src.mem_lvl;
+	if (he->mem_info)
+		m  = he->mem_info->data_src.mem_lvl;
 
 	out[0] = '\0';
 
@@ -736,7 +726,7 @@
 };
 #define NUM_SNOOP_ACCESS (sizeof(snoop_access)/sizeof(const char *))
 
-static int hist_entry__snoop_snprintf(struct hist_entry *self, char *bf,
+static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf,
 				    size_t size, unsigned int width)
 {
 	char out[64];
@@ -746,8 +736,8 @@
 
 	out[0] = '\0';
 
-	if (self->mem_info)
-		m = self->mem_info->data_src.mem_snoop;
+	if (he->mem_info)
+		m = he->mem_info->data_src.mem_snoop;
 
 	for (i = 0; m && i < NUM_SNOOP_ACCESS; i++, m >>= 1) {
 		if (!(m & 0x1))
@@ -784,10 +774,10 @@
 	return he_weight(left) - he_weight(right);
 }
 
-static int hist_entry__local_weight_snprintf(struct hist_entry *self, char *bf,
+static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf,
 				    size_t size, unsigned int width)
 {
-	return repsep_snprintf(bf, size, "%-*llu", width, he_weight(self));
+	return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he));
 }
 
 struct sort_entry sort_local_weight = {
@@ -803,10 +793,10 @@
 	return left->stat.weight - right->stat.weight;
 }
 
-static int hist_entry__global_weight_snprintf(struct hist_entry *self, char *bf,
+static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf,
 					      size_t size, unsigned int width)
 {
-	return repsep_snprintf(bf, size, "%-*llu", width, self->stat.weight);
+	return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight);
 }
 
 struct sort_entry sort_global_weight = {
@@ -858,6 +848,127 @@
 	.se_width_idx	= HISTC_MEM_SNOOP,
 };
 
+static int64_t
+sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+	return left->branch_info->flags.abort !=
+		right->branch_info->flags.abort;
+}
+
+static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf,
+				    size_t size, unsigned int width)
+{
+	static const char *out = ".";
+
+	if (he->branch_info->flags.abort)
+		out = "A";
+	return repsep_snprintf(bf, size, "%-*s", width, out);
+}
+
+struct sort_entry sort_abort = {
+	.se_header	= "Transaction abort",
+	.se_cmp		= sort__abort_cmp,
+	.se_snprintf	= hist_entry__abort_snprintf,
+	.se_width_idx	= HISTC_ABORT,
+};
+
+static int64_t
+sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+	return left->branch_info->flags.in_tx !=
+		right->branch_info->flags.in_tx;
+}
+
+static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf,
+				    size_t size, unsigned int width)
+{
+	static const char *out = ".";
+
+	if (he->branch_info->flags.in_tx)
+		out = "T";
+
+	return repsep_snprintf(bf, size, "%-*s", width, out);
+}
+
+struct sort_entry sort_in_tx = {
+	.se_header	= "Branch in transaction",
+	.se_cmp		= sort__in_tx_cmp,
+	.se_snprintf	= hist_entry__in_tx_snprintf,
+	.se_width_idx	= HISTC_IN_TX,
+};
+
+static int64_t
+sort__transaction_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+	return left->transaction - right->transaction;
+}
+
+static inline char *add_str(char *p, const char *str)
+{
+	strcpy(p, str);
+	return p + strlen(str);
+}
+
+static struct txbit {
+	unsigned flag;
+	const char *name;
+	int skip_for_len;
+} txbits[] = {
+	{ PERF_TXN_ELISION,        "EL ",        0 },
+	{ PERF_TXN_TRANSACTION,    "TX ",        1 },
+	{ PERF_TXN_SYNC,           "SYNC ",      1 },
+	{ PERF_TXN_ASYNC,          "ASYNC ",     0 },
+	{ PERF_TXN_RETRY,          "RETRY ",     0 },
+	{ PERF_TXN_CONFLICT,       "CON ",       0 },
+	{ PERF_TXN_CAPACITY_WRITE, "CAP-WRITE ", 1 },
+	{ PERF_TXN_CAPACITY_READ,  "CAP-READ ",  0 },
+	{ 0, NULL, 0 }
+};
+
+int hist_entry__transaction_len(void)
+{
+	int i;
+	int len = 0;
+
+	for (i = 0; txbits[i].name; i++) {
+		if (!txbits[i].skip_for_len)
+			len += strlen(txbits[i].name);
+	}
+	len += 4; /* :XX<space> */
+	return len;
+}
+
+static int hist_entry__transaction_snprintf(struct hist_entry *he, char *bf,
+					    size_t size, unsigned int width)
+{
+	u64 t = he->transaction;
+	char buf[128];
+	char *p = buf;
+	int i;
+
+	buf[0] = 0;
+	for (i = 0; txbits[i].name; i++)
+		if (txbits[i].flag & t)
+			p = add_str(p, txbits[i].name);
+	if (t && !(t & (PERF_TXN_SYNC|PERF_TXN_ASYNC)))
+		p = add_str(p, "NEITHER ");
+	if (t & PERF_TXN_ABORT_MASK) {
+		sprintf(p, ":%" PRIx64,
+			(t & PERF_TXN_ABORT_MASK) >>
+			PERF_TXN_ABORT_SHIFT);
+		p += strlen(p);
+	}
+
+	return repsep_snprintf(bf, size, "%-*s", width, buf);
+}
+
+struct sort_entry sort_transaction = {
+	.se_header	= "Transaction                ",
+	.se_cmp		= sort__transaction_cmp,
+	.se_snprintf	= hist_entry__transaction_snprintf,
+	.se_width_idx	= HISTC_TRANSACTION,
+};
+
 struct sort_dimension {
 	const char		*name;
 	struct sort_entry	*entry;
@@ -876,6 +987,7 @@
 	DIM(SORT_SRCLINE, "srcline", sort_srcline),
 	DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
 	DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
+	DIM(SORT_TRANSACTION, "transaction", sort_transaction),
 };
 
 #undef DIM
@@ -888,6 +1000,8 @@
 	DIM(SORT_SYM_FROM, "symbol_from", sort_sym_from),
 	DIM(SORT_SYM_TO, "symbol_to", sort_sym_to),
 	DIM(SORT_MISPREDICT, "mispredict", sort_mispredict),
+	DIM(SORT_IN_TX, "in_tx", sort_in_tx),
+	DIM(SORT_ABORT, "abort", sort_abort),
 };
 
 #undef DIM
@@ -1009,7 +1123,7 @@
 	return ret;
 }
 
-static void sort_entry__setup_elide(struct sort_entry *self,
+static void sort_entry__setup_elide(struct sort_entry *se,
 				    struct strlist *list,
 				    const char *list_name, FILE *fp)
 {
@@ -1017,7 +1131,7 @@
 		if (fp != NULL)
 			fprintf(fp, "# %s: %s\n", list_name,
 				strlist__entry(list, 0)->s);
-		self->elide = true;
+		se->elide = true;
 	}
 }
 
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 4e80dbd..43e5ff4 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -22,7 +22,6 @@
 #include "parse-events.h"
 
 #include "thread.h"
-#include "sort.h"
 
 extern regex_t parent_regex;
 extern const char *sort_order;
@@ -84,7 +83,9 @@
 	struct he_stat		stat;
 	struct map_symbol	ms;
 	struct thread		*thread;
+	struct comm		*comm;
 	u64			ip;
+	u64			transaction;
 	s32			cpu;
 
 	struct hist_entry_diff	diff;
@@ -145,6 +146,7 @@
 	SORT_SRCLINE,
 	SORT_LOCAL_WEIGHT,
 	SORT_GLOBAL_WEIGHT,
+	SORT_TRANSACTION,
 
 	/* branch stack specific sort keys */
 	__SORT_BRANCH_STACK,
@@ -153,6 +155,8 @@
 	SORT_SYM_FROM,
 	SORT_SYM_TO,
 	SORT_MISPREDICT,
+	SORT_ABORT,
+	SORT_IN_TX,
 
 	/* memory mode specific sort keys */
 	__SORT_MEMORY_MODE,
@@ -175,7 +179,7 @@
 
 	int64_t (*se_cmp)(struct hist_entry *, struct hist_entry *);
 	int64_t (*se_collapse)(struct hist_entry *, struct hist_entry *);
-	int	(*se_snprintf)(struct hist_entry *self, char *bf, size_t size,
+	int	(*se_snprintf)(struct hist_entry *he, char *bf, size_t size,
 			       unsigned int width);
 	u8	se_width_idx;
 	bool	elide;
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
new file mode 100644
index 0000000..d11aefb
--- /dev/null
+++ b/tools/perf/util/srcline.c
@@ -0,0 +1,265 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <linux/kernel.h>
+
+#include "util/dso.h"
+#include "util/util.h"
+#include "util/debug.h"
+
+#ifdef HAVE_LIBBFD_SUPPORT
+
+/*
+ * Implement addr2line using libbfd.
+ */
+#define PACKAGE "perf"
+#include <bfd.h>
+
+struct a2l_data {
+	const char 	*input;
+	unsigned long 	addr;
+
+	bool 		found;
+	const char 	*filename;
+	const char 	*funcname;
+	unsigned 	line;
+
+	bfd 		*abfd;
+	asymbol 	**syms;
+};
+
+static int bfd_error(const char *string)
+{
+	const char *errmsg;
+
+	errmsg = bfd_errmsg(bfd_get_error());
+	fflush(stdout);
+
+	if (string)
+		pr_debug("%s: %s\n", string, errmsg);
+	else
+		pr_debug("%s\n", errmsg);
+
+	return -1;
+}
+
+static int slurp_symtab(bfd *abfd, struct a2l_data *a2l)
+{
+	long storage;
+	long symcount;
+	asymbol **syms;
+	bfd_boolean dynamic = FALSE;
+
+	if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0)
+		return bfd_error(bfd_get_filename(abfd));
+
+	storage = bfd_get_symtab_upper_bound(abfd);
+	if (storage == 0L) {
+		storage = bfd_get_dynamic_symtab_upper_bound(abfd);
+		dynamic = TRUE;
+	}
+	if (storage < 0L)
+		return bfd_error(bfd_get_filename(abfd));
+
+	syms = malloc(storage);
+	if (dynamic)
+		symcount = bfd_canonicalize_dynamic_symtab(abfd, syms);
+	else
+		symcount = bfd_canonicalize_symtab(abfd, syms);
+
+	if (symcount < 0) {
+		free(syms);
+		return bfd_error(bfd_get_filename(abfd));
+	}
+
+	a2l->syms = syms;
+	return 0;
+}
+
+static void find_address_in_section(bfd *abfd, asection *section, void *data)
+{
+	bfd_vma pc, vma;
+	bfd_size_type size;
+	struct a2l_data *a2l = data;
+
+	if (a2l->found)
+		return;
+
+	if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0)
+		return;
+
+	pc = a2l->addr;
+	vma = bfd_get_section_vma(abfd, section);
+	size = bfd_get_section_size(section);
+
+	if (pc < vma || pc >= vma + size)
+		return;
+
+	a2l->found = bfd_find_nearest_line(abfd, section, a2l->syms, pc - vma,
+					   &a2l->filename, &a2l->funcname,
+					   &a2l->line);
+}
+
+static struct a2l_data *addr2line_init(const char *path)
+{
+	bfd *abfd;
+	struct a2l_data *a2l = NULL;
+
+	abfd = bfd_openr(path, NULL);
+	if (abfd == NULL)
+		return NULL;
+
+	if (!bfd_check_format(abfd, bfd_object))
+		goto out;
+
+	a2l = zalloc(sizeof(*a2l));
+	if (a2l == NULL)
+		goto out;
+
+	a2l->abfd = abfd;
+	a2l->input = strdup(path);
+	if (a2l->input == NULL)
+		goto out;
+
+	if (slurp_symtab(abfd, a2l))
+		goto out;
+
+	return a2l;
+
+out:
+	if (a2l) {
+		free((void *)a2l->input);
+		free(a2l);
+	}
+	bfd_close(abfd);
+	return NULL;
+}
+
+static void addr2line_cleanup(struct a2l_data *a2l)
+{
+	if (a2l->abfd)
+		bfd_close(a2l->abfd);
+	free((void *)a2l->input);
+	free(a2l->syms);
+	free(a2l);
+}
+
+static int addr2line(const char *dso_name, unsigned long addr,
+		     char **file, unsigned int *line)
+{
+	int ret = 0;
+	struct a2l_data *a2l;
+
+	a2l = addr2line_init(dso_name);
+	if (a2l == NULL) {
+		pr_warning("addr2line_init failed for %s\n", dso_name);
+		return 0;
+	}
+
+	a2l->addr = addr;
+	bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l);
+
+	if (a2l->found && a2l->filename) {
+		*file = strdup(a2l->filename);
+		*line = a2l->line;
+
+		if (*file)
+			ret = 1;
+	}
+
+	addr2line_cleanup(a2l);
+	return ret;
+}
+
+#else /* HAVE_LIBBFD_SUPPORT */
+
+static int addr2line(const char *dso_name, unsigned long addr,
+		     char **file, unsigned int *line_nr)
+{
+	FILE *fp;
+	char cmd[PATH_MAX];
+	char *filename = NULL;
+	size_t len;
+	char *sep;
+	int ret = 0;
+
+	scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64,
+		  dso_name, addr);
+
+	fp = popen(cmd, "r");
+	if (fp == NULL) {
+		pr_warning("popen failed for %s\n", dso_name);
+		return 0;
+	}
+
+	if (getline(&filename, &len, fp) < 0 || !len) {
+		pr_warning("addr2line has no output for %s\n", dso_name);
+		goto out;
+	}
+
+	sep = strchr(filename, '\n');
+	if (sep)
+		*sep = '\0';
+
+	if (!strcmp(filename, "??:0")) {
+		pr_debug("no debugging info in %s\n", dso_name);
+		free(filename);
+		goto out;
+	}
+
+	sep = strchr(filename, ':');
+	if (sep) {
+		*sep++ = '\0';
+		*file = filename;
+		*line_nr = strtoul(sep, NULL, 0);
+		ret = 1;
+	}
+out:
+	pclose(fp);
+	return ret;
+}
+#endif /* HAVE_LIBBFD_SUPPORT */
+
+char *get_srcline(struct dso *dso, unsigned long addr)
+{
+	char *file = NULL;
+	unsigned line = 0;
+	char *srcline;
+	char *dso_name = dso->long_name;
+	size_t size;
+
+	if (!dso->has_srcline)
+		return SRCLINE_UNKNOWN;
+
+	if (dso_name[0] == '[')
+		goto out;
+
+	if (!strncmp(dso_name, "/tmp/perf-", 10))
+		goto out;
+
+	if (!addr2line(dso_name, addr, &file, &line))
+		goto out;
+
+	/* just calculate actual length */
+	size = snprintf(NULL, 0, "%s:%u", file, line) + 1;
+
+	srcline = malloc(size);
+	if (srcline)
+		snprintf(srcline, size, "%s:%u", file, line);
+	else
+		srcline = SRCLINE_UNKNOWN;
+
+	free(file);
+	return srcline;
+
+out:
+	dso->has_srcline = 0;
+	return SRCLINE_UNKNOWN;
+}
+
+void free_srcline(char *srcline)
+{
+	if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0)
+		free(srcline);
+}
diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c
index 834c8eb..3edd053 100644
--- a/tools/perf/util/strfilter.c
+++ b/tools/perf/util/strfilter.c
@@ -10,22 +10,22 @@
 #define is_operator(c)	((c) == '|' || (c) == '&' || (c) == '!')
 #define is_separator(c)	(is_operator(c) || (c) == '(' || (c) == ')')
 
-static void strfilter_node__delete(struct strfilter_node *self)
+static void strfilter_node__delete(struct strfilter_node *node)
 {
-	if (self) {
-		if (self->p && !is_operator(*self->p))
-			free((char *)self->p);
-		strfilter_node__delete(self->l);
-		strfilter_node__delete(self->r);
-		free(self);
+	if (node) {
+		if (node->p && !is_operator(*node->p))
+			free((char *)node->p);
+		strfilter_node__delete(node->l);
+		strfilter_node__delete(node->r);
+		free(node);
 	}
 }
 
-void strfilter__delete(struct strfilter *self)
+void strfilter__delete(struct strfilter *filter)
 {
-	if (self) {
-		strfilter_node__delete(self->root);
-		free(self);
+	if (filter) {
+		strfilter_node__delete(filter->root);
+		free(filter);
 	}
 }
 
@@ -62,15 +62,15 @@
 						    struct strfilter_node *l,
 						    struct strfilter_node *r)
 {
-	struct strfilter_node *ret = zalloc(sizeof(struct strfilter_node));
+	struct strfilter_node *node = zalloc(sizeof(*node));
 
-	if (ret) {
-		ret->p = op;
-		ret->l = l;
-		ret->r = r;
+	if (node) {
+		node->p = op;
+		node->l = l;
+		node->r = r;
 	}
 
-	return ret;
+	return node;
 }
 
 static struct strfilter_node *strfilter_node__new(const char *s,
@@ -154,46 +154,46 @@
  */
 struct strfilter *strfilter__new(const char *rules, const char **err)
 {
-	struct strfilter *ret = zalloc(sizeof(struct strfilter));
+	struct strfilter *filter = zalloc(sizeof(*filter));
 	const char *ep = NULL;
 
-	if (ret)
-		ret->root = strfilter_node__new(rules, &ep);
+	if (filter)
+		filter->root = strfilter_node__new(rules, &ep);
 
-	if (!ret || !ret->root || *ep != '\0') {
+	if (!filter || !filter->root || *ep != '\0') {
 		if (err)
 			*err = ep;
-		strfilter__delete(ret);
-		ret = NULL;
+		strfilter__delete(filter);
+		filter = NULL;
 	}
 
-	return ret;
+	return filter;
 }
 
-static bool strfilter_node__compare(struct strfilter_node *self,
+static bool strfilter_node__compare(struct strfilter_node *node,
 				    const char *str)
 {
-	if (!self || !self->p)
+	if (!node || !node->p)
 		return false;
 
-	switch (*self->p) {
+	switch (*node->p) {
 	case '|':	/* OR */
-		return strfilter_node__compare(self->l, str) ||
-			strfilter_node__compare(self->r, str);
+		return strfilter_node__compare(node->l, str) ||
+			strfilter_node__compare(node->r, str);
 	case '&':	/* AND */
-		return strfilter_node__compare(self->l, str) &&
-			strfilter_node__compare(self->r, str);
+		return strfilter_node__compare(node->l, str) &&
+			strfilter_node__compare(node->r, str);
 	case '!':	/* NOT */
-		return !strfilter_node__compare(self->r, str);
+		return !strfilter_node__compare(node->r, str);
 	default:
-		return strglobmatch(str, self->p);
+		return strglobmatch(str, node->p);
 	}
 }
 
 /* Return true if STR matches the filter rules */
-bool strfilter__compare(struct strfilter *self, const char *str)
+bool strfilter__compare(struct strfilter *filter, const char *str)
 {
-	if (!self)
+	if (!filter)
 		return false;
-	return strfilter_node__compare(self->root, str);
+	return strfilter_node__compare(filter->root, str);
 }
diff --git a/tools/perf/util/strfilter.h b/tools/perf/util/strfilter.h
index 00f58a7..fe611f3 100644
--- a/tools/perf/util/strfilter.h
+++ b/tools/perf/util/strfilter.h
@@ -30,19 +30,19 @@
 
 /**
  * strfilter__compare - compare given string and a string filter
- * @self: String filter
+ * @filter: String filter
  * @str: target string
  *
- * Compare @str and @self. Return true if the str match the rule
+ * Compare @str and @filter. Return true if the str match the rule
  */
-bool strfilter__compare(struct strfilter *self, const char *str);
+bool strfilter__compare(struct strfilter *filter, const char *str);
 
 /**
  * strfilter__delete - delete a string filter
- * @self: String filter to delete
+ * @filter: String filter to delete
  *
- * Delete @self.
+ * Delete @filter.
  */
-void strfilter__delete(struct strfilter *self);
+void strfilter__delete(struct strfilter *filter);
 
 #endif
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index a9c829b..eed0b96 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -8,7 +8,7 @@
 #include "symbol.h"
 #include "debug.h"
 
-#ifndef HAVE_ELF_GETPHDRNUM
+#ifndef HAVE_ELF_GETPHDRNUM_SUPPORT
 static int elf_getphdrnum(Elf *elf, size_t *dst)
 {
 	GElf_Ehdr gehdr;
@@ -487,27 +487,27 @@
 
 	ek = elf_kind(elf);
 	if (ek != ELF_K_ELF)
-		goto out_close;
+		goto out_elf_end;
 
 	if (gelf_getehdr(elf, &ehdr) == NULL) {
 		pr_err("%s: cannot get elf header.\n", __func__);
-		goto out_close;
+		goto out_elf_end;
 	}
 
 	sec = elf_section_by_name(elf, &ehdr, &shdr,
 				  ".gnu_debuglink", NULL);
 	if (sec == NULL)
-		goto out_close;
+		goto out_elf_end;
 
 	data = elf_getdata(sec, NULL);
 	if (data == NULL)
-		goto out_close;
+		goto out_elf_end;
 
 	/* the start of this section is a zero-terminated string */
 	strncpy(debuglink, data->d_buf, size);
 
+out_elf_end:
 	elf_end(elf);
-
 out_close:
 	close(fd);
 out:
@@ -1018,6 +1018,601 @@
 	return err;
 }
 
+static int copy_bytes(int from, off_t from_offs, int to, off_t to_offs, u64 len)
+{
+	ssize_t r;
+	size_t n;
+	int err = -1;
+	char *buf = malloc(page_size);
+
+	if (buf == NULL)
+		return -1;
+
+	if (lseek(to, to_offs, SEEK_SET) != to_offs)
+		goto out;
+
+	if (lseek(from, from_offs, SEEK_SET) != from_offs)
+		goto out;
+
+	while (len) {
+		n = page_size;
+		if (len < n)
+			n = len;
+		/* Use read because mmap won't work on proc files */
+		r = read(from, buf, n);
+		if (r < 0)
+			goto out;
+		if (!r)
+			break;
+		n = r;
+		r = write(to, buf, n);
+		if (r < 0)
+			goto out;
+		if ((size_t)r != n)
+			goto out;
+		len -= n;
+	}
+
+	err = 0;
+out:
+	free(buf);
+	return err;
+}
+
+struct kcore {
+	int fd;
+	int elfclass;
+	Elf *elf;
+	GElf_Ehdr ehdr;
+};
+
+static int kcore__open(struct kcore *kcore, const char *filename)
+{
+	GElf_Ehdr *ehdr;
+
+	kcore->fd = open(filename, O_RDONLY);
+	if (kcore->fd == -1)
+		return -1;
+
+	kcore->elf = elf_begin(kcore->fd, ELF_C_READ, NULL);
+	if (!kcore->elf)
+		goto out_close;
+
+	kcore->elfclass = gelf_getclass(kcore->elf);
+	if (kcore->elfclass == ELFCLASSNONE)
+		goto out_end;
+
+	ehdr = gelf_getehdr(kcore->elf, &kcore->ehdr);
+	if (!ehdr)
+		goto out_end;
+
+	return 0;
+
+out_end:
+	elf_end(kcore->elf);
+out_close:
+	close(kcore->fd);
+	return -1;
+}
+
+static int kcore__init(struct kcore *kcore, char *filename, int elfclass,
+		       bool temp)
+{
+	GElf_Ehdr *ehdr;
+
+	kcore->elfclass = elfclass;
+
+	if (temp)
+		kcore->fd = mkstemp(filename);
+	else
+		kcore->fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0400);
+	if (kcore->fd == -1)
+		return -1;
+
+	kcore->elf = elf_begin(kcore->fd, ELF_C_WRITE, NULL);
+	if (!kcore->elf)
+		goto out_close;
+
+	if (!gelf_newehdr(kcore->elf, elfclass))
+		goto out_end;
+
+	ehdr = gelf_getehdr(kcore->elf, &kcore->ehdr);
+	if (!ehdr)
+		goto out_end;
+
+	return 0;
+
+out_end:
+	elf_end(kcore->elf);
+out_close:
+	close(kcore->fd);
+	unlink(filename);
+	return -1;
+}
+
+static void kcore__close(struct kcore *kcore)
+{
+	elf_end(kcore->elf);
+	close(kcore->fd);
+}
+
+static int kcore__copy_hdr(struct kcore *from, struct kcore *to, size_t count)
+{
+	GElf_Ehdr *ehdr = &to->ehdr;
+	GElf_Ehdr *kehdr = &from->ehdr;
+
+	memcpy(ehdr->e_ident, kehdr->e_ident, EI_NIDENT);
+	ehdr->e_type      = kehdr->e_type;
+	ehdr->e_machine   = kehdr->e_machine;
+	ehdr->e_version   = kehdr->e_version;
+	ehdr->e_entry     = 0;
+	ehdr->e_shoff     = 0;
+	ehdr->e_flags     = kehdr->e_flags;
+	ehdr->e_phnum     = count;
+	ehdr->e_shentsize = 0;
+	ehdr->e_shnum     = 0;
+	ehdr->e_shstrndx  = 0;
+
+	if (from->elfclass == ELFCLASS32) {
+		ehdr->e_phoff     = sizeof(Elf32_Ehdr);
+		ehdr->e_ehsize    = sizeof(Elf32_Ehdr);
+		ehdr->e_phentsize = sizeof(Elf32_Phdr);
+	} else {
+		ehdr->e_phoff     = sizeof(Elf64_Ehdr);
+		ehdr->e_ehsize    = sizeof(Elf64_Ehdr);
+		ehdr->e_phentsize = sizeof(Elf64_Phdr);
+	}
+
+	if (!gelf_update_ehdr(to->elf, ehdr))
+		return -1;
+
+	if (!gelf_newphdr(to->elf, count))
+		return -1;
+
+	return 0;
+}
+
+static int kcore__add_phdr(struct kcore *kcore, int idx, off_t offset,
+			   u64 addr, u64 len)
+{
+	GElf_Phdr gphdr;
+	GElf_Phdr *phdr;
+
+	phdr = gelf_getphdr(kcore->elf, idx, &gphdr);
+	if (!phdr)
+		return -1;
+
+	phdr->p_type	= PT_LOAD;
+	phdr->p_flags	= PF_R | PF_W | PF_X;
+	phdr->p_offset	= offset;
+	phdr->p_vaddr	= addr;
+	phdr->p_paddr	= 0;
+	phdr->p_filesz	= len;
+	phdr->p_memsz	= len;
+	phdr->p_align	= page_size;
+
+	if (!gelf_update_phdr(kcore->elf, idx, phdr))
+		return -1;
+
+	return 0;
+}
+
+static off_t kcore__write(struct kcore *kcore)
+{
+	return elf_update(kcore->elf, ELF_C_WRITE);
+}
+
+struct phdr_data {
+	off_t offset;
+	u64 addr;
+	u64 len;
+};
+
+struct kcore_copy_info {
+	u64 stext;
+	u64 etext;
+	u64 first_symbol;
+	u64 last_symbol;
+	u64 first_module;
+	u64 last_module_symbol;
+	struct phdr_data kernel_map;
+	struct phdr_data modules_map;
+};
+
+static int kcore_copy__process_kallsyms(void *arg, const char *name, char type,
+					u64 start)
+{
+	struct kcore_copy_info *kci = arg;
+
+	if (!symbol_type__is_a(type, MAP__FUNCTION))
+		return 0;
+
+	if (strchr(name, '[')) {
+		if (start > kci->last_module_symbol)
+			kci->last_module_symbol = start;
+		return 0;
+	}
+
+	if (!kci->first_symbol || start < kci->first_symbol)
+		kci->first_symbol = start;
+
+	if (!kci->last_symbol || start > kci->last_symbol)
+		kci->last_symbol = start;
+
+	if (!strcmp(name, "_stext")) {
+		kci->stext = start;
+		return 0;
+	}
+
+	if (!strcmp(name, "_etext")) {
+		kci->etext = start;
+		return 0;
+	}
+
+	return 0;
+}
+
+static int kcore_copy__parse_kallsyms(struct kcore_copy_info *kci,
+				      const char *dir)
+{
+	char kallsyms_filename[PATH_MAX];
+
+	scnprintf(kallsyms_filename, PATH_MAX, "%s/kallsyms", dir);
+
+	if (symbol__restricted_filename(kallsyms_filename, "/proc/kallsyms"))
+		return -1;
+
+	if (kallsyms__parse(kallsyms_filename, kci,
+			    kcore_copy__process_kallsyms) < 0)
+		return -1;
+
+	return 0;
+}
+
+static int kcore_copy__process_modules(void *arg,
+				       const char *name __maybe_unused,
+				       u64 start)
+{
+	struct kcore_copy_info *kci = arg;
+
+	if (!kci->first_module || start < kci->first_module)
+		kci->first_module = start;
+
+	return 0;
+}
+
+static int kcore_copy__parse_modules(struct kcore_copy_info *kci,
+				     const char *dir)
+{
+	char modules_filename[PATH_MAX];
+
+	scnprintf(modules_filename, PATH_MAX, "%s/modules", dir);
+
+	if (symbol__restricted_filename(modules_filename, "/proc/modules"))
+		return -1;
+
+	if (modules__parse(modules_filename, kci,
+			   kcore_copy__process_modules) < 0)
+		return -1;
+
+	return 0;
+}
+
+static void kcore_copy__map(struct phdr_data *p, u64 start, u64 end, u64 pgoff,
+			    u64 s, u64 e)
+{
+	if (p->addr || s < start || s >= end)
+		return;
+
+	p->addr = s;
+	p->offset = (s - start) + pgoff;
+	p->len = e < end ? e - s : end - s;
+}
+
+static int kcore_copy__read_map(u64 start, u64 len, u64 pgoff, void *data)
+{
+	struct kcore_copy_info *kci = data;
+	u64 end = start + len;
+
+	kcore_copy__map(&kci->kernel_map, start, end, pgoff, kci->stext,
+			kci->etext);
+
+	kcore_copy__map(&kci->modules_map, start, end, pgoff, kci->first_module,
+			kci->last_module_symbol);
+
+	return 0;
+}
+
+static int kcore_copy__read_maps(struct kcore_copy_info *kci, Elf *elf)
+{
+	if (elf_read_maps(elf, true, kcore_copy__read_map, kci) < 0)
+		return -1;
+
+	return 0;
+}
+
+static int kcore_copy__calc_maps(struct kcore_copy_info *kci, const char *dir,
+				 Elf *elf)
+{
+	if (kcore_copy__parse_kallsyms(kci, dir))
+		return -1;
+
+	if (kcore_copy__parse_modules(kci, dir))
+		return -1;
+
+	if (kci->stext)
+		kci->stext = round_down(kci->stext, page_size);
+	else
+		kci->stext = round_down(kci->first_symbol, page_size);
+
+	if (kci->etext) {
+		kci->etext = round_up(kci->etext, page_size);
+	} else if (kci->last_symbol) {
+		kci->etext = round_up(kci->last_symbol, page_size);
+		kci->etext += page_size;
+	}
+
+	kci->first_module = round_down(kci->first_module, page_size);
+
+	if (kci->last_module_symbol) {
+		kci->last_module_symbol = round_up(kci->last_module_symbol,
+						   page_size);
+		kci->last_module_symbol += page_size;
+	}
+
+	if (!kci->stext || !kci->etext)
+		return -1;
+
+	if (kci->first_module && !kci->last_module_symbol)
+		return -1;
+
+	return kcore_copy__read_maps(kci, elf);
+}
+
+static int kcore_copy__copy_file(const char *from_dir, const char *to_dir,
+				 const char *name)
+{
+	char from_filename[PATH_MAX];
+	char to_filename[PATH_MAX];
+
+	scnprintf(from_filename, PATH_MAX, "%s/%s", from_dir, name);
+	scnprintf(to_filename, PATH_MAX, "%s/%s", to_dir, name);
+
+	return copyfile_mode(from_filename, to_filename, 0400);
+}
+
+static int kcore_copy__unlink(const char *dir, const char *name)
+{
+	char filename[PATH_MAX];
+
+	scnprintf(filename, PATH_MAX, "%s/%s", dir, name);
+
+	return unlink(filename);
+}
+
+static int kcore_copy__compare_fds(int from, int to)
+{
+	char *buf_from;
+	char *buf_to;
+	ssize_t ret;
+	size_t len;
+	int err = -1;
+
+	buf_from = malloc(page_size);
+	buf_to = malloc(page_size);
+	if (!buf_from || !buf_to)
+		goto out;
+
+	while (1) {
+		/* Use read because mmap won't work on proc files */
+		ret = read(from, buf_from, page_size);
+		if (ret < 0)
+			goto out;
+
+		if (!ret)
+			break;
+
+		len = ret;
+
+		if (readn(to, buf_to, len) != (int)len)
+			goto out;
+
+		if (memcmp(buf_from, buf_to, len))
+			goto out;
+	}
+
+	err = 0;
+out:
+	free(buf_to);
+	free(buf_from);
+	return err;
+}
+
+static int kcore_copy__compare_files(const char *from_filename,
+				     const char *to_filename)
+{
+	int from, to, err = -1;
+
+	from = open(from_filename, O_RDONLY);
+	if (from < 0)
+		return -1;
+
+	to = open(to_filename, O_RDONLY);
+	if (to < 0)
+		goto out_close_from;
+
+	err = kcore_copy__compare_fds(from, to);
+
+	close(to);
+out_close_from:
+	close(from);
+	return err;
+}
+
+static int kcore_copy__compare_file(const char *from_dir, const char *to_dir,
+				    const char *name)
+{
+	char from_filename[PATH_MAX];
+	char to_filename[PATH_MAX];
+
+	scnprintf(from_filename, PATH_MAX, "%s/%s", from_dir, name);
+	scnprintf(to_filename, PATH_MAX, "%s/%s", to_dir, name);
+
+	return kcore_copy__compare_files(from_filename, to_filename);
+}
+
+/**
+ * kcore_copy - copy kallsyms, modules and kcore from one directory to another.
+ * @from_dir: from directory
+ * @to_dir: to directory
+ *
+ * This function copies kallsyms, modules and kcore files from one directory to
+ * another.  kallsyms and modules are copied entirely.  Only code segments are
+ * copied from kcore.  It is assumed that two segments suffice: one for the
+ * kernel proper and one for all the modules.  The code segments are determined
+ * from kallsyms and modules files.  The kernel map starts at _stext or the
+ * lowest function symbol, and ends at _etext or the highest function symbol.
+ * The module map starts at the lowest module address and ends at the highest
+ * module symbol.  Start addresses are rounded down to the nearest page.  End
+ * addresses are rounded up to the nearest page.  An extra page is added to the
+ * highest kernel symbol and highest module symbol to, hopefully, encompass that
+ * symbol too.  Because it contains only code sections, the resulting kcore is
+ * unusual.  One significant peculiarity is that the mapping (start -> pgoff)
+ * is not the same for the kernel map and the modules map.  That happens because
+ * the data is copied adjacently whereas the original kcore has gaps.  Finally,
+ * kallsyms and modules files are compared with their copies to check that
+ * modules have not been loaded or unloaded while the copies were taking place.
+ *
+ * Return: %0 on success, %-1 on failure.
+ */
+int kcore_copy(const char *from_dir, const char *to_dir)
+{
+	struct kcore kcore;
+	struct kcore extract;
+	size_t count = 2;
+	int idx = 0, err = -1;
+	off_t offset = page_size, sz, modules_offset = 0;
+	struct kcore_copy_info kci = { .stext = 0, };
+	char kcore_filename[PATH_MAX];
+	char extract_filename[PATH_MAX];
+
+	if (kcore_copy__copy_file(from_dir, to_dir, "kallsyms"))
+		return -1;
+
+	if (kcore_copy__copy_file(from_dir, to_dir, "modules"))
+		goto out_unlink_kallsyms;
+
+	scnprintf(kcore_filename, PATH_MAX, "%s/kcore", from_dir);
+	scnprintf(extract_filename, PATH_MAX, "%s/kcore", to_dir);
+
+	if (kcore__open(&kcore, kcore_filename))
+		goto out_unlink_modules;
+
+	if (kcore_copy__calc_maps(&kci, from_dir, kcore.elf))
+		goto out_kcore_close;
+
+	if (kcore__init(&extract, extract_filename, kcore.elfclass, false))
+		goto out_kcore_close;
+
+	if (!kci.modules_map.addr)
+		count -= 1;
+
+	if (kcore__copy_hdr(&kcore, &extract, count))
+		goto out_extract_close;
+
+	if (kcore__add_phdr(&extract, idx++, offset, kci.kernel_map.addr,
+			    kci.kernel_map.len))
+		goto out_extract_close;
+
+	if (kci.modules_map.addr) {
+		modules_offset = offset + kci.kernel_map.len;
+		if (kcore__add_phdr(&extract, idx, modules_offset,
+				    kci.modules_map.addr, kci.modules_map.len))
+			goto out_extract_close;
+	}
+
+	sz = kcore__write(&extract);
+	if (sz < 0 || sz > offset)
+		goto out_extract_close;
+
+	if (copy_bytes(kcore.fd, kci.kernel_map.offset, extract.fd, offset,
+		       kci.kernel_map.len))
+		goto out_extract_close;
+
+	if (modules_offset && copy_bytes(kcore.fd, kci.modules_map.offset,
+					 extract.fd, modules_offset,
+					 kci.modules_map.len))
+		goto out_extract_close;
+
+	if (kcore_copy__compare_file(from_dir, to_dir, "modules"))
+		goto out_extract_close;
+
+	if (kcore_copy__compare_file(from_dir, to_dir, "kallsyms"))
+		goto out_extract_close;
+
+	err = 0;
+
+out_extract_close:
+	kcore__close(&extract);
+	if (err)
+		unlink(extract_filename);
+out_kcore_close:
+	kcore__close(&kcore);
+out_unlink_modules:
+	if (err)
+		kcore_copy__unlink(to_dir, "modules");
+out_unlink_kallsyms:
+	if (err)
+		kcore_copy__unlink(to_dir, "kallsyms");
+
+	return err;
+}
+
+int kcore_extract__create(struct kcore_extract *kce)
+{
+	struct kcore kcore;
+	struct kcore extract;
+	size_t count = 1;
+	int idx = 0, err = -1;
+	off_t offset = page_size, sz;
+
+	if (kcore__open(&kcore, kce->kcore_filename))
+		return -1;
+
+	strcpy(kce->extract_filename, PERF_KCORE_EXTRACT);
+	if (kcore__init(&extract, kce->extract_filename, kcore.elfclass, true))
+		goto out_kcore_close;
+
+	if (kcore__copy_hdr(&kcore, &extract, count))
+		goto out_extract_close;
+
+	if (kcore__add_phdr(&extract, idx, offset, kce->addr, kce->len))
+		goto out_extract_close;
+
+	sz = kcore__write(&extract);
+	if (sz < 0 || sz > offset)
+		goto out_extract_close;
+
+	if (copy_bytes(kcore.fd, kce->offs, extract.fd, offset, kce->len))
+		goto out_extract_close;
+
+	err = 0;
+
+out_extract_close:
+	kcore__close(&extract);
+	if (err)
+		unlink(kce->extract_filename);
+out_kcore_close:
+	kcore__close(&kcore);
+
+	return err;
+}
+
+void kcore_extract__delete(struct kcore_extract *kce)
+{
+	unlink(kce->extract_filename);
+}
+
 void symbol__elf_init(void)
 {
 	elf_version(EV_CURRENT);
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index 3a802c3..2d2dd05 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -308,6 +308,21 @@
 	return -1;
 }
 
+int kcore_extract__create(struct kcore_extract *kce __maybe_unused)
+{
+	return -1;
+}
+
+void kcore_extract__delete(struct kcore_extract *kce __maybe_unused)
+{
+}
+
+int kcore_copy(const char *from_dir __maybe_unused,
+	       const char *to_dir __maybe_unused)
+{
+	return -1;
+}
+
 void symbol__elf_init(void)
 {
 }
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 7eb0362..c0c3696 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -51,6 +51,7 @@
 	DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
 	DSO_BINARY_TYPE__GUEST_KMODULE,
 	DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
+	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
 	DSO_BINARY_TYPE__NOT_FOUND,
 };
 
@@ -159,10 +160,12 @@
 
 		if (choose_best_symbol(curr, next) == SYMBOL_A) {
 			rb_erase(&next->rb_node, symbols);
+			symbol__delete(next);
 			goto again;
 		} else {
 			nd = rb_next(&curr->rb_node);
 			rb_erase(&curr->rb_node, symbols);
+			symbol__delete(curr);
 		}
 	}
 }
@@ -499,6 +502,64 @@
 	return -1;
 }
 
+int modules__parse(const char *filename, void *arg,
+		   int (*process_module)(void *arg, const char *name,
+					 u64 start))
+{
+	char *line = NULL;
+	size_t n;
+	FILE *file;
+	int err = 0;
+
+	file = fopen(filename, "r");
+	if (file == NULL)
+		return -1;
+
+	while (1) {
+		char name[PATH_MAX];
+		u64 start;
+		char *sep;
+		ssize_t line_len;
+
+		line_len = getline(&line, &n, file);
+		if (line_len < 0) {
+			if (feof(file))
+				break;
+			err = -1;
+			goto out;
+		}
+
+		if (!line) {
+			err = -1;
+			goto out;
+		}
+
+		line[--line_len] = '\0'; /* \n */
+
+		sep = strrchr(line, 'x');
+		if (sep == NULL)
+			continue;
+
+		hex2u64(sep + 1, &start);
+
+		sep = strchr(line, ' ');
+		if (sep == NULL)
+			continue;
+
+		*sep = '\0';
+
+		scnprintf(name, sizeof(name), "[%s]", line);
+
+		err = process_module(arg, name, start);
+		if (err)
+			break;
+	}
+out:
+	free(line);
+	fclose(file);
+	return err;
+}
+
 struct process_kallsyms_args {
 	struct map *map;
 	struct dso *dso;
@@ -739,6 +800,219 @@
 	return restricted;
 }
 
+struct module_info {
+	struct rb_node rb_node;
+	char *name;
+	u64 start;
+};
+
+static void add_module(struct module_info *mi, struct rb_root *modules)
+{
+	struct rb_node **p = &modules->rb_node;
+	struct rb_node *parent = NULL;
+	struct module_info *m;
+
+	while (*p != NULL) {
+		parent = *p;
+		m = rb_entry(parent, struct module_info, rb_node);
+		if (strcmp(mi->name, m->name) < 0)
+			p = &(*p)->rb_left;
+		else
+			p = &(*p)->rb_right;
+	}
+	rb_link_node(&mi->rb_node, parent, p);
+	rb_insert_color(&mi->rb_node, modules);
+}
+
+static void delete_modules(struct rb_root *modules)
+{
+	struct module_info *mi;
+	struct rb_node *next = rb_first(modules);
+
+	while (next) {
+		mi = rb_entry(next, struct module_info, rb_node);
+		next = rb_next(&mi->rb_node);
+		rb_erase(&mi->rb_node, modules);
+		free(mi->name);
+		free(mi);
+	}
+}
+
+static struct module_info *find_module(const char *name,
+				       struct rb_root *modules)
+{
+	struct rb_node *n = modules->rb_node;
+
+	while (n) {
+		struct module_info *m;
+		int cmp;
+
+		m = rb_entry(n, struct module_info, rb_node);
+		cmp = strcmp(name, m->name);
+		if (cmp < 0)
+			n = n->rb_left;
+		else if (cmp > 0)
+			n = n->rb_right;
+		else
+			return m;
+	}
+
+	return NULL;
+}
+
+static int __read_proc_modules(void *arg, const char *name, u64 start)
+{
+	struct rb_root *modules = arg;
+	struct module_info *mi;
+
+	mi = zalloc(sizeof(struct module_info));
+	if (!mi)
+		return -ENOMEM;
+
+	mi->name = strdup(name);
+	mi->start = start;
+
+	if (!mi->name) {
+		free(mi);
+		return -ENOMEM;
+	}
+
+	add_module(mi, modules);
+
+	return 0;
+}
+
+static int read_proc_modules(const char *filename, struct rb_root *modules)
+{
+	if (symbol__restricted_filename(filename, "/proc/modules"))
+		return -1;
+
+	if (modules__parse(filename, modules, __read_proc_modules)) {
+		delete_modules(modules);
+		return -1;
+	}
+
+	return 0;
+}
+
+int compare_proc_modules(const char *from, const char *to)
+{
+	struct rb_root from_modules = RB_ROOT;
+	struct rb_root to_modules = RB_ROOT;
+	struct rb_node *from_node, *to_node;
+	struct module_info *from_m, *to_m;
+	int ret = -1;
+
+	if (read_proc_modules(from, &from_modules))
+		return -1;
+
+	if (read_proc_modules(to, &to_modules))
+		goto out_delete_from;
+
+	from_node = rb_first(&from_modules);
+	to_node = rb_first(&to_modules);
+	while (from_node) {
+		if (!to_node)
+			break;
+
+		from_m = rb_entry(from_node, struct module_info, rb_node);
+		to_m = rb_entry(to_node, struct module_info, rb_node);
+
+		if (from_m->start != to_m->start ||
+		    strcmp(from_m->name, to_m->name))
+			break;
+
+		from_node = rb_next(from_node);
+		to_node = rb_next(to_node);
+	}
+
+	if (!from_node && !to_node)
+		ret = 0;
+
+	delete_modules(&to_modules);
+out_delete_from:
+	delete_modules(&from_modules);
+
+	return ret;
+}
+
+static int do_validate_kcore_modules(const char *filename, struct map *map,
+				  struct map_groups *kmaps)
+{
+	struct rb_root modules = RB_ROOT;
+	struct map *old_map;
+	int err;
+
+	err = read_proc_modules(filename, &modules);
+	if (err)
+		return err;
+
+	old_map = map_groups__first(kmaps, map->type);
+	while (old_map) {
+		struct map *next = map_groups__next(old_map);
+		struct module_info *mi;
+
+		if (old_map == map || old_map->start == map->start) {
+			/* The kernel map */
+			old_map = next;
+			continue;
+		}
+
+		/* Module must be in memory at the same address */
+		mi = find_module(old_map->dso->short_name, &modules);
+		if (!mi || mi->start != old_map->start) {
+			err = -EINVAL;
+			goto out;
+		}
+
+		old_map = next;
+	}
+out:
+	delete_modules(&modules);
+	return err;
+}
+
+/*
+ * If kallsyms is referenced by name then we look for filename in the same
+ * directory.
+ */
+static bool filename_from_kallsyms_filename(char *filename,
+					    const char *base_name,
+					    const char *kallsyms_filename)
+{
+	char *name;
+
+	strcpy(filename, kallsyms_filename);
+	name = strrchr(filename, '/');
+	if (!name)
+		return false;
+
+	name += 1;
+
+	if (!strcmp(name, "kallsyms")) {
+		strcpy(name, base_name);
+		return true;
+	}
+
+	return false;
+}
+
+static int validate_kcore_modules(const char *kallsyms_filename,
+				  struct map *map)
+{
+	struct map_groups *kmaps = map__kmap(map)->kmaps;
+	char modules_filename[PATH_MAX];
+
+	if (!filename_from_kallsyms_filename(modules_filename, "modules",
+					     kallsyms_filename))
+		return -EINVAL;
+
+	if (do_validate_kcore_modules(modules_filename, map, kmaps))
+		return -EINVAL;
+
+	return 0;
+}
+
 struct kcore_mapfn_data {
 	struct dso *dso;
 	enum map_type type;
@@ -762,28 +1036,6 @@
 	return 0;
 }
 
-/*
- * If kallsyms is referenced by name then we look for kcore in the same
- * directory.
- */
-static bool kcore_filename_from_kallsyms_filename(char *kcore_filename,
-						  const char *kallsyms_filename)
-{
-	char *name;
-
-	strcpy(kcore_filename, kallsyms_filename);
-	name = strrchr(kcore_filename, '/');
-	if (!name)
-		return false;
-
-	if (!strcmp(name, "/kallsyms")) {
-		strcpy(name, "/kcore");
-		return true;
-	}
-
-	return false;
-}
-
 static int dso__load_kcore(struct dso *dso, struct map *map,
 			   const char *kallsyms_filename)
 {
@@ -800,8 +1052,12 @@
 	if (map != machine->vmlinux_maps[map->type])
 		return -EINVAL;
 
-	if (!kcore_filename_from_kallsyms_filename(kcore_filename,
-						   kallsyms_filename))
+	if (!filename_from_kallsyms_filename(kcore_filename, "kcore",
+					     kallsyms_filename))
+		return -EINVAL;
+
+	/* All modules must be present at their original addresses */
+	if (validate_kcore_modules(kallsyms_filename, map))
 		return -EINVAL;
 
 	md.dso = dso;
@@ -1188,6 +1444,105 @@
 	return err;
 }
 
+static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
+{
+	char kallsyms_filename[PATH_MAX];
+	struct dirent *dent;
+	int ret = -1;
+	DIR *d;
+
+	d = opendir(dir);
+	if (!d)
+		return -1;
+
+	while (1) {
+		dent = readdir(d);
+		if (!dent)
+			break;
+		if (dent->d_type != DT_DIR)
+			continue;
+		scnprintf(kallsyms_filename, sizeof(kallsyms_filename),
+			  "%s/%s/kallsyms", dir, dent->d_name);
+		if (!validate_kcore_modules(kallsyms_filename, map)) {
+			strlcpy(dir, kallsyms_filename, dir_sz);
+			ret = 0;
+			break;
+		}
+	}
+
+	closedir(d);
+
+	return ret;
+}
+
+static char *dso__find_kallsyms(struct dso *dso, struct map *map)
+{
+	u8 host_build_id[BUILD_ID_SIZE];
+	char sbuild_id[BUILD_ID_SIZE * 2 + 1];
+	bool is_host = false;
+	char path[PATH_MAX];
+
+	if (!dso->has_build_id) {
+		/*
+		 * Last resort, if we don't have a build-id and couldn't find
+		 * any vmlinux file, try the running kernel kallsyms table.
+		 */
+		goto proc_kallsyms;
+	}
+
+	if (sysfs__read_build_id("/sys/kernel/notes", host_build_id,
+				 sizeof(host_build_id)) == 0)
+		is_host = dso__build_id_equal(dso, host_build_id);
+
+	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
+
+	/* Use /proc/kallsyms if possible */
+	if (is_host) {
+		DIR *d;
+		int fd;
+
+		/* If no cached kcore go with /proc/kallsyms */
+		scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s",
+			  buildid_dir, sbuild_id);
+		d = opendir(path);
+		if (!d)
+			goto proc_kallsyms;
+		closedir(d);
+
+		/*
+		 * Do not check the build-id cache, until we know we cannot use
+		 * /proc/kcore.
+		 */
+		fd = open("/proc/kcore", O_RDONLY);
+		if (fd != -1) {
+			close(fd);
+			/* If module maps match go with /proc/kallsyms */
+			if (!validate_kcore_modules("/proc/kallsyms", map))
+				goto proc_kallsyms;
+		}
+
+		/* Find kallsyms in build-id cache with kcore */
+		if (!find_matching_kcore(map, path, sizeof(path)))
+			return strdup(path);
+
+		goto proc_kallsyms;
+	}
+
+	scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s",
+		  buildid_dir, sbuild_id);
+
+	if (access(path, F_OK)) {
+		pr_err("No kallsyms or vmlinux with build-id %s was found\n",
+		       sbuild_id);
+		return NULL;
+	}
+
+	return strdup(path);
+
+proc_kallsyms:
+	return strdup("/proc/kallsyms");
+}
+
 static int dso__load_kernel_sym(struct dso *dso, struct map *map,
 				symbol_filter_t filter)
 {
@@ -1214,7 +1569,7 @@
 		goto do_kallsyms;
 	}
 
-	if (symbol_conf.vmlinux_name != NULL) {
+	if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) {
 		err = dso__load_vmlinux(dso, map,
 					symbol_conf.vmlinux_name, filter);
 		if (err > 0) {
@@ -1226,7 +1581,7 @@
 		return err;
 	}
 
-	if (vmlinux_path != NULL) {
+	if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) {
 		err = dso__load_vmlinux_path(dso, map, filter);
 		if (err > 0)
 			return err;
@@ -1236,51 +1591,11 @@
 	if (symbol_conf.symfs[0] != 0)
 		return -1;
 
-	/*
-	 * Say the kernel DSO was created when processing the build-id header table,
-	 * we have a build-id, so check if it is the same as the running kernel,
-	 * using it if it is.
-	 */
-	if (dso->has_build_id) {
-		u8 kallsyms_build_id[BUILD_ID_SIZE];
-		char sbuild_id[BUILD_ID_SIZE * 2 + 1];
+	kallsyms_allocated_filename = dso__find_kallsyms(dso, map);
+	if (!kallsyms_allocated_filename)
+		return -1;
 
-		if (sysfs__read_build_id("/sys/kernel/notes", kallsyms_build_id,
-					 sizeof(kallsyms_build_id)) == 0) {
-			if (dso__build_id_equal(dso, kallsyms_build_id)) {
-				kallsyms_filename = "/proc/kallsyms";
-				goto do_kallsyms;
-			}
-		}
-		/*
-		 * Now look if we have it on the build-id cache in
-		 * $HOME/.debug/[kernel.kallsyms].
-		 */
-		build_id__sprintf(dso->build_id, sizeof(dso->build_id),
-				  sbuild_id);
-
-		if (asprintf(&kallsyms_allocated_filename,
-			     "%s/.debug/[kernel.kallsyms]/%s",
-			     getenv("HOME"), sbuild_id) == -1) {
-			pr_err("Not enough memory for kallsyms file lookup\n");
-			return -1;
-		}
-
-		kallsyms_filename = kallsyms_allocated_filename;
-
-		if (access(kallsyms_filename, F_OK)) {
-			pr_err("No kallsyms or vmlinux with build-id %s "
-			       "was found\n", sbuild_id);
-			free(kallsyms_allocated_filename);
-			return -1;
-		}
-	} else {
-		/*
-		 * Last resort, if we don't have a build-id and couldn't find
-		 * any vmlinux file, try the running kernel kallsyms table.
-		 */
-		kallsyms_filename = "/proc/kallsyms";
-	}
+	kallsyms_filename = kallsyms_allocated_filename;
 
 do_kallsyms:
 	err = dso__load_kallsyms(dso, kallsyms_filename, map, filter);
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index fd5b70e..07de8fe 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -13,7 +13,7 @@
 #include <libgen.h>
 #include "build-id.h"
 
-#ifdef LIBELF_SUPPORT
+#ifdef HAVE_LIBELF_SUPPORT
 #include <libelf.h>
 #include <gelf.h>
 #endif
@@ -21,7 +21,7 @@
 
 #include "dso.h"
 
-#ifdef HAVE_CPLUS_DEMANGLE
+#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
 extern char *cplus_demangle(const char *, int);
 
 static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i)
@@ -46,7 +46,7 @@
  * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP;
  * for newer versions we can use mmap to reduce memory usage:
  */
-#ifdef LIBELF_MMAP
+#ifdef HAVE_LIBELF_MMAP_SUPPORT
 # define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP
 #else
 # define PERF_ELF_C_READ_MMAP ELF_C_READ
@@ -85,6 +85,7 @@
 	unsigned short	priv_size;
 	unsigned short	nr_events;
 	bool		try_vmlinux_path,
+			ignore_vmlinux,
 			show_kernel_path,
 			use_modules,
 			sort_by_name,
@@ -178,7 +179,7 @@
 	int fd;
 	enum dso_binary_type type;
 
-#ifdef LIBELF_SUPPORT
+#ifdef HAVE_LIBELF_SUPPORT
 	Elf *elf;
 	GElf_Ehdr ehdr;
 
@@ -222,6 +223,9 @@
 int kallsyms__parse(const char *filename, void *arg,
 		    int (*process_symbol)(void *arg, const char *name,
 					  char type, u64 start));
+int modules__parse(const char *filename, void *arg,
+		   int (*process_module)(void *arg, const char *name,
+					 u64 start));
 int filename__read_debuglink(const char *filename, char *debuglink,
 			     size_t size);
 
@@ -252,4 +256,21 @@
 int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data,
 		    bool *is_64_bit);
 
+#define PERF_KCORE_EXTRACT "/tmp/perf-kcore-XXXXXX"
+
+struct kcore_extract {
+	char *kcore_filename;
+	u64 addr;
+	u64 offs;
+	u64 len;
+	char extract_filename[sizeof(PERF_KCORE_EXTRACT)];
+	int fd;
+};
+
+int kcore_extract__create(struct kcore_extract *kce);
+void kcore_extract__delete(struct kcore_extract *kce);
+
+int kcore_copy(const char *from_dir, const char *to_dir);
+int compare_proc_modules(const char *from, const char *to);
+
 #endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/sysfs.c b/tools/perf/util/sysfs.c
deleted file mode 100644
index f71e9ea..0000000
--- a/tools/perf/util/sysfs.c
+++ /dev/null
@@ -1,60 +0,0 @@
-
-#include "util.h"
-#include "sysfs.h"
-
-static const char * const sysfs_known_mountpoints[] = {
-	"/sys",
-	0,
-};
-
-static int sysfs_found;
-char sysfs_mountpoint[PATH_MAX + 1];
-
-static int sysfs_valid_mountpoint(const char *sysfs)
-{
-	struct statfs st_fs;
-
-	if (statfs(sysfs, &st_fs) < 0)
-		return -ENOENT;
-	else if (st_fs.f_type != (long) SYSFS_MAGIC)
-		return -ENOENT;
-
-	return 0;
-}
-
-const char *sysfs_find_mountpoint(void)
-{
-	const char * const *ptr;
-	char type[100];
-	FILE *fp;
-
-	if (sysfs_found)
-		return (const char *) sysfs_mountpoint;
-
-	ptr = sysfs_known_mountpoints;
-	while (*ptr) {
-		if (sysfs_valid_mountpoint(*ptr) == 0) {
-			sysfs_found = 1;
-			strcpy(sysfs_mountpoint, *ptr);
-			return sysfs_mountpoint;
-		}
-		ptr++;
-	}
-
-	/* give up and parse /proc/mounts */
-	fp = fopen("/proc/mounts", "r");
-	if (fp == NULL)
-		return NULL;
-
-	while (!sysfs_found &&
-	       fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
-		      sysfs_mountpoint, type) == 2) {
-
-		if (strcmp(type, "sysfs") == 0)
-			sysfs_found = 1;
-	}
-
-	fclose(fp);
-
-	return sysfs_found ? sysfs_mountpoint : NULL;
-}
diff --git a/tools/perf/util/sysfs.h b/tools/perf/util/sysfs.h
deleted file mode 100644
index a813b72..0000000
--- a/tools/perf/util/sysfs.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __SYSFS_H__
-#define __SYSFS_H__
-
-const char *sysfs_find_mountpoint(void);
-
-#endif /* __DEBUGFS_H__ */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index e3d4a55..cd8e2f5 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -6,86 +6,137 @@
 #include "thread.h"
 #include "util.h"
 #include "debug.h"
+#include "comm.h"
 
 struct thread *thread__new(pid_t pid, pid_t tid)
 {
-	struct thread *self = zalloc(sizeof(*self));
+	char *comm_str;
+	struct comm *comm;
+	struct thread *thread = zalloc(sizeof(*thread));
 
-	if (self != NULL) {
-		map_groups__init(&self->mg);
-		self->pid_ = pid;
-		self->tid = tid;
-		self->ppid = -1;
-		self->comm = malloc(32);
-		if (self->comm)
-			snprintf(self->comm, 32, ":%d", self->tid);
+	if (thread != NULL) {
+		map_groups__init(&thread->mg);
+		thread->pid_ = pid;
+		thread->tid = tid;
+		thread->ppid = -1;
+		INIT_LIST_HEAD(&thread->comm_list);
+
+		comm_str = malloc(32);
+		if (!comm_str)
+			goto err_thread;
+
+		snprintf(comm_str, 32, ":%d", tid);
+		comm = comm__new(comm_str, 0);
+		free(comm_str);
+		if (!comm)
+			goto err_thread;
+
+		list_add(&comm->list, &thread->comm_list);
 	}
 
-	return self;
+	return thread;
+
+err_thread:
+	free(thread);
+	return NULL;
 }
 
-void thread__delete(struct thread *self)
+void thread__delete(struct thread *thread)
 {
-	map_groups__exit(&self->mg);
-	free(self->comm);
-	free(self);
-}
+	struct comm *comm, *tmp;
 
-int thread__set_comm(struct thread *self, const char *comm)
-{
-	int err;
-
-	if (self->comm)
-		free(self->comm);
-	self->comm = strdup(comm);
-	err = self->comm == NULL ? -ENOMEM : 0;
-	if (!err) {
-		self->comm_set = true;
+	map_groups__exit(&thread->mg);
+	list_for_each_entry_safe(comm, tmp, &thread->comm_list, list) {
+		list_del(&comm->list);
+		comm__free(comm);
 	}
-	return err;
+
+	free(thread);
 }
 
-int thread__comm_len(struct thread *self)
+struct comm *thread__comm(const struct thread *thread)
 {
-	if (!self->comm_len) {
-		if (!self->comm)
+	if (list_empty(&thread->comm_list))
+		return NULL;
+
+	return list_first_entry(&thread->comm_list, struct comm, list);
+}
+
+/* CHECKME: time should always be 0 if event aren't ordered */
+int thread__set_comm(struct thread *thread, const char *str, u64 timestamp)
+{
+	struct comm *new, *curr = thread__comm(thread);
+
+	/* Override latest entry if it had no specific time coverage */
+	if (!curr->start) {
+		comm__override(curr, str, timestamp);
+		return 0;
+	}
+
+	new = comm__new(str, timestamp);
+	if (!new)
+		return -ENOMEM;
+
+	list_add(&new->list, &thread->comm_list);
+	thread->comm_set = true;
+
+	return 0;
+}
+
+const char *thread__comm_str(const struct thread *thread)
+{
+	const struct comm *comm = thread__comm(thread);
+
+	if (!comm)
+		return NULL;
+
+	return comm__str(comm);
+}
+
+/* CHECKME: it should probably better return the max comm len from its comm list */
+int thread__comm_len(struct thread *thread)
+{
+	if (!thread->comm_len) {
+		const char *comm = thread__comm_str(thread);
+		if (!comm)
 			return 0;
-		self->comm_len = strlen(self->comm);
+		thread->comm_len = strlen(comm);
 	}
 
-	return self->comm_len;
+	return thread->comm_len;
 }
 
 size_t thread__fprintf(struct thread *thread, FILE *fp)
 {
-	return fprintf(fp, "Thread %d %s\n", thread->tid, thread->comm) +
+	return fprintf(fp, "Thread %d %s\n", thread->tid, thread__comm_str(thread)) +
 	       map_groups__fprintf(&thread->mg, verbose, fp);
 }
 
-void thread__insert_map(struct thread *self, struct map *map)
+void thread__insert_map(struct thread *thread, struct map *map)
 {
-	map_groups__fixup_overlappings(&self->mg, map, verbose, stderr);
-	map_groups__insert(&self->mg, map);
+	map_groups__fixup_overlappings(&thread->mg, map, verbose, stderr);
+	map_groups__insert(&thread->mg, map);
 }
 
-int thread__fork(struct thread *self, struct thread *parent)
+int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
 {
-	int i;
+	int i, err;
 
 	if (parent->comm_set) {
-		if (self->comm)
-			free(self->comm);
-		self->comm = strdup(parent->comm);
-		if (!self->comm)
+		const char *comm = thread__comm_str(parent);
+		if (!comm)
 			return -ENOMEM;
-		self->comm_set = true;
+		err = thread__set_comm(thread, comm, timestamp);
+		if (!err)
+			return err;
+		thread->comm_set = true;
 	}
 
 	for (i = 0; i < MAP__NR_TYPES; ++i)
-		if (map_groups__clone(&self->mg, &parent->mg, i) < 0)
+		if (map_groups__clone(&thread->mg, &parent->mg, i) < 0)
 			return -ENOMEM;
 
-	self->ppid = parent->tid;
+	thread->ppid = parent->tid;
 
 	return 0;
 }
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 4ebbb40..897c1b2 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -2,6 +2,7 @@
 #define __PERF_THREAD_H
 
 #include <linux/rbtree.h>
+#include <linux/list.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include "symbol.h"
@@ -18,31 +19,34 @@
 	char			shortname[3];
 	bool			comm_set;
 	bool			dead; /* if set thread has exited */
-	char			*comm;
+	struct list_head	comm_list;
 	int			comm_len;
 
 	void			*priv;
 };
 
 struct machine;
+struct comm;
 
 struct thread *thread__new(pid_t pid, pid_t tid);
-void thread__delete(struct thread *self);
+void thread__delete(struct thread *thread);
 static inline void thread__exited(struct thread *thread)
 {
 	thread->dead = true;
 }
 
-int thread__set_comm(struct thread *self, const char *comm);
-int thread__comm_len(struct thread *self);
-void thread__insert_map(struct thread *self, struct map *map);
-int thread__fork(struct thread *self, struct thread *parent);
+int thread__set_comm(struct thread *thread, const char *comm, u64 timestamp);
+int thread__comm_len(struct thread *thread);
+struct comm *thread__comm(const struct thread *thread);
+const char *thread__comm_str(const struct thread *thread);
+void thread__insert_map(struct thread *thread, struct map *map);
+int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
 size_t thread__fprintf(struct thread *thread, FILE *fp);
 
-static inline struct map *thread__find_map(struct thread *self,
+static inline struct map *thread__find_map(struct thread *thread,
 					   enum map_type type, u64 addr)
 {
-	return self ? map_groups__find(&self->mg, type, addr) : NULL;
+	return thread ? map_groups__find(&thread->mg, type, addr) : NULL;
 }
 
 void thread__find_addr_map(struct thread *thread, struct machine *machine,
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index b554ffc..88cfeaf 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -24,6 +24,7 @@
 	u64		   exact_samples;
 	u64		   guest_us_samples, guest_kernel_samples;
 	int		   print_entries, count_filter, delay_secs;
+	int		   max_stack;
 	bool		   hide_kernel_symbols, hide_user_symbols, zero;
 	bool		   use_tui, use_stdio;
 	bool		   kptr_restrict_warned;
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index e9e1c03..6681f71 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -120,42 +120,6 @@
 	return val;
 }
 
-void *raw_field_ptr(struct event_format *event, const char *name, void *data)
-{
-	struct format_field *field;
-
-	field = pevent_find_any_field(event, name);
-	if (!field)
-		return NULL;
-
-	if (field->flags & FIELD_IS_DYNAMIC) {
-		int offset;
-
-		offset = *(int *)(data + field->offset);
-		offset &= 0xffff;
-
-		return data + offset;
-	}
-
-	return data + field->offset;
-}
-
-int trace_parse_common_type(struct pevent *pevent, void *data)
-{
-	struct pevent_record record;
-
-	record.data = data;
-	return pevent_data_type(pevent, &record);
-}
-
-int trace_parse_common_pid(struct pevent *pevent, void *data)
-{
-	struct pevent_record record;
-
-	record.data = data;
-	return pevent_data_pid(pevent, &record);
-}
-
 unsigned long long read_size(struct event_format *event, void *ptr, int size)
 {
 	return pevent_read_number(event->pevent, ptr, size);
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index fafe1a4..04df631 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -11,8 +11,6 @@
 struct perf_tool;
 struct thread;
 
-extern struct pevent *perf_pevent;
-
 int bigendian(void);
 
 struct pevent *read_trace_init(int file_bigendian, int host_bigendian);
@@ -23,26 +21,19 @@
 int parse_event_file(struct pevent *pevent,
 		     char *buf, unsigned long size, char *sys);
 
-struct pevent_record *trace_peek_data(struct pevent *pevent, int cpu);
-
 unsigned long long
 raw_field_value(struct event_format *event, const char *name, void *data);
-void *raw_field_ptr(struct event_format *event, const char *name, void *data);
 
 void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size);
 void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size);
 
 ssize_t trace_report(int fd, struct pevent **pevent, bool repipe);
 
-int trace_parse_common_type(struct pevent *pevent, void *data);
-int trace_parse_common_pid(struct pevent *pevent, void *data);
-
 struct event_format *trace_find_next_event(struct pevent *pevent,
 					   struct event_format *event);
 unsigned long long read_size(struct event_format *event, void *ptr, int size);
 unsigned long long eval_flag(const char *flag);
 
-struct pevent_record *trace_read_data(struct pevent *pevent, int cpu);
 int read_tracing_data(int fd, struct list_head *pattrs);
 
 struct tracing_data {
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index cb6bc50..ec0c71a 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -13,7 +13,7 @@
 
 typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
 
-#ifdef LIBUNWIND_SUPPORT
+#ifdef HAVE_LIBUNWIND_SUPPORT
 int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
 			struct machine *machine,
 			struct thread *thread,
@@ -31,5 +31,5 @@
 {
 	return 0;
 }
-#endif /* LIBUNWIND_SUPPORT */
+#endif /* HAVE_LIBUNWIND_SUPPORT */
 #endif /* __UNWIND_H */
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 6d17b18..28a0a89 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -1,7 +1,7 @@
 #include "../perf.h"
 #include "util.h"
 #include <sys/mman.h>
-#ifdef BACKTRACE_SUPPORT
+#ifdef HAVE_BACKTRACE_SUPPORT
 #include <execinfo.h>
 #endif
 #include <stdio.h>
@@ -55,17 +55,20 @@
 	return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
 }
 
-static int slow_copyfile(const char *from, const char *to)
+static int slow_copyfile(const char *from, const char *to, mode_t mode)
 {
-	int err = 0;
+	int err = -1;
 	char *line = NULL;
 	size_t n;
 	FILE *from_fp = fopen(from, "r"), *to_fp;
+	mode_t old_umask;
 
 	if (from_fp == NULL)
 		goto out;
 
+	old_umask = umask(mode ^ 0777);
 	to_fp = fopen(to, "w");
+	umask(old_umask);
 	if (to_fp == NULL)
 		goto out_fclose_from;
 
@@ -82,7 +85,7 @@
 	return err;
 }
 
-int copyfile(const char *from, const char *to)
+int copyfile_mode(const char *from, const char *to, mode_t mode)
 {
 	int fromfd, tofd;
 	struct stat st;
@@ -93,13 +96,13 @@
 		goto out;
 
 	if (st.st_size == 0) /* /proc? do it slowly... */
-		return slow_copyfile(from, to);
+		return slow_copyfile(from, to, mode);
 
 	fromfd = open(from, O_RDONLY);
 	if (fromfd < 0)
 		goto out;
 
-	tofd = creat(to, 0755);
+	tofd = creat(to, mode);
 	if (tofd < 0)
 		goto out_close_from;
 
@@ -121,6 +124,11 @@
 	return err;
 }
 
+int copyfile(const char *from, const char *to)
+{
+	return copyfile_mode(from, to, 0755);
+}
+
 unsigned long convert_unit(unsigned long value, char *unit)
 {
 	*unit = ' ';
@@ -204,7 +212,7 @@
 }
 
 /* Obtain a backtrace and print it to stdout. */
-#ifdef BACKTRACE_SUPPORT
+#ifdef HAVE_BACKTRACE_SUPPORT
 void dump_stack(void)
 {
 	void *array[16];
@@ -361,3 +369,47 @@
 	*ptime = time_sec * NSEC_PER_SEC + time_nsec;
 	return 0;
 }
+
+unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
+{
+	struct parse_tag *i = tags;
+
+	while (i->tag) {
+		char *s;
+
+		s = strchr(str, i->tag);
+		if (s) {
+			unsigned long int value;
+			char *endptr;
+
+			value = strtoul(str, &endptr, 10);
+			if (s != endptr)
+				break;
+
+			if (value > ULONG_MAX / i->mult)
+				break;
+			value *= i->mult;
+			return value;
+		}
+		i++;
+	}
+
+	return (unsigned long) -1;
+}
+
+int filename__read_int(const char *filename, int *value)
+{
+	char line[64];
+	int fd = open(filename, O_RDONLY), err = -1;
+
+	if (fd < 0)
+		return -1;
+
+	if (read(fd, line, sizeof(line)) > 0) {
+		*value = atoi(line);
+		err = 0;
+	}
+
+	close(fd);
+	return err;
+}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index a535359..c8f362d 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -128,6 +128,8 @@
 #endif
 #endif
 
+#define PERF_GTK_DSO  "libperf-gtk.so"
+
 /* General helper functions */
 extern void usage(const char *err) NORETURN;
 extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
@@ -241,6 +243,7 @@
 
 int mkdir_p(char *path, mode_t mode);
 int copyfile(const char *from, const char *to);
+int copyfile_mode(const char *from, const char *to, mode_t mode);
 
 s64 perf_atoll(const char *str);
 char **argv_split(const char *str, int *argcp);
@@ -270,6 +273,13 @@
 	return (n != 0 && ((n & (n - 1)) == 0));
 }
 
+static inline unsigned next_pow2(unsigned x)
+{
+	if (!x)
+		return 1;
+	return 1ULL << (32 - __builtin_clz(x - 1));
+}
+
 size_t hex_width(u64 v);
 int hex2u64(const char *ptr, u64 *val);
 
@@ -281,4 +291,20 @@
 extern unsigned int page_size;
 
 void get_term_dimensions(struct winsize *ws);
+
+struct parse_tag {
+	char tag;
+	int mult;
+};
+
+unsigned long parse_tag_value(const char *str, struct parse_tag *tags);
+
+#define SRCLINE_UNKNOWN  ((char *) "??:0")
+
+struct dso;
+
+char *get_srcline(struct dso *dso, unsigned long addr);
+void free_srcline(char *srcline);
+
+int filename__read_int(const char *filename, int *value);
 #endif /* GIT_COMPAT_UTIL_H */
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index 0d0506d..ee76544 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -59,21 +59,22 @@
 QUIET_SUBDIR1  =
 
 ifneq ($(findstring $(MAKEFLAGS),s),s)
-ifneq ($(V),1)
-	QUIET_CC       = @echo '   ' CC $@;
-	QUIET_AR       = @echo '   ' AR $@;
-	QUIET_LINK     = @echo '   ' LINK $@;
-	QUIET_MKDIR    = @echo '   ' MKDIR $@;
-	QUIET_GEN      = @echo '   ' GEN $@;
+  ifneq ($(V),1)
+	QUIET_CC       = @echo '  CC       '$@;
+	QUIET_AR       = @echo '  AR       '$@;
+	QUIET_LINK     = @echo '  LINK     '$@;
+	QUIET_MKDIR    = @echo '  MKDIR    '$@;
+	QUIET_GEN      = @echo '  GEN      '$@;
 	QUIET_SUBDIR0  = +@subdir=
-	QUIET_SUBDIR1  = ;$(NO_SUBDIR) echo '   ' SUBDIR $$subdir; \
+	QUIET_SUBDIR1  = ;$(NO_SUBDIR) \
+			  echo '  SUBDIR   '$$subdir; \
 			 $(MAKE) $(PRINT_DIR) -C $$subdir
-	QUIET_FLEX     = @echo '   ' FLEX $@;
-	QUIET_BISON    = @echo '   ' BISON $@;
+	QUIET_FLEX     = @echo '  FLEX     '$@;
+	QUIET_BISON    = @echo '  BISON    '$@;
 
 	descend = \
-		+@echo '   ' DESCEND $(1); \
+		+@echo	       '  DESCEND  '$(1); \
 		mkdir -p $(OUTPUT)$(1) && \
 		$(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2)
-endif
+  endif
 endif
diff --git a/tools/testing/ktest/examples/crosstests.conf b/tools/testing/ktest/examples/crosstests.conf
index 4673660..a1203148 100644
--- a/tools/testing/ktest/examples/crosstests.conf
+++ b/tools/testing/ktest/examples/crosstests.conf
@@ -133,12 +133,6 @@
 ARCH = frv
 GCC_VER = 4.5.1
 
-# h8300 - failed make defconfig??
-TEST_START IF ${RUN} == h8300 || ${DO_FAILED}
-CROSS = h8300-elf
-ARCH = h8300
-GCC_VER = 4.5.1
-
 # m68k fails with error?
 TEST_START IF ${RUN} == m68k || ${DO_DEFAULT}
 CROSS = m68k-linux
diff --git a/tools/testing/selftests/timers/posix_timers.c b/tools/testing/selftests/timers/posix_timers.c
index 4fa655d..41bd855 100644
--- a/tools/testing/selftests/timers/posix_timers.c
+++ b/tools/testing/selftests/timers/posix_timers.c
@@ -151,7 +151,7 @@
 	fflush(stdout);
 
 	done = 0;
-	timer_create(which, NULL, &id);
+	err = timer_create(which, NULL, &id);
 	if (err < 0) {
 		perror("Can't create timer\n");
 		return -1;
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index a9dd682..1cf9ccb 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -3091,7 +3091,7 @@
 
 static int kvm_init_debug(void)
 {
-	int r = -EFAULT;
+	int r = -EEXIST;
 	struct kvm_stats_debugfs_item *p;
 
 	kvm_debugfs_dir = debugfs_create_dir("kvm", NULL);